<commit_before>// Copyright (c) 2010-2022, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.

#include "linearform.hpp"
#include "../general/forall.hpp"

namespace mfem
{

LinearFormExtension::LinearFormExtension(LinearForm *lf): lf(lf) { Update(); }

void LinearFormExtension::Assemble()
{
   const FiniteElementSpace &fes = *lf->FESpace();
   MFEM_VERIFY(lf->SupportsDevice(), "Not supported.");
   MFEM_VERIFY(lf->Size() == fes.GetVSize(), "LinearForm size does not "
               "match the number of vector dofs!");

   const Array<Array<int>*> &domain_integs_marker = *lf->GetDLFI_Marker();
   const int mesh_attributes_max = fes.GetMesh()->attributes.Max();
   const Array<LinearFormIntegrator*> &domain_integs = *lf->GetDLFI();

   for (int k = 0; k < domain_integs.Size(); ++k)
   {
      // Get the markers for this integrator
      const Array<int> *domain_integs_marker_k = domain_integs_marker[k];

      // check if there are markers for this integrator
      const bool has_markers_k = domain_integs_marker_k != nullptr;

      if (has_markers_k)
      {
         // Element attribute marker should be of length mesh->attributes
         MFEM_VERIFY(mesh_attributes_max == domain_integs_marker_k->Size(),
                     "invalid element marker for domain linear form "
                     "integrator #" << k << ", counting from zero");
      }

      // if there are no markers, just use the whole linear form (1)
      if (!has_markers_k) { markers.HostReadWrite(); markers = 1; }
      else
      {
         // scan the attributes to set the markers to 0 or 1
         const int NE = fes.GetNE();
         const auto attr = attributes.Read();
         const auto dimk = domain_integs_marker_k->Read();
         auto markers_w = markers.Write();
         MFEM_FORALL(e, NE, markers_w[e] = dimk[attr[e]-1] == 1;);
      }

      // Assemble the linear form
      b = 0.0;
      domain_integs[k]->AssembleDevice(fes, markers, b);
      if (k == 0) { elem_restrict_lex->MultTranspose(b, *lf); }
      else { elem_restrict_lex->AddMultTranspose(b, *lf); }
   }

   const Array<Array<int>*> &boundary_integs_marker = lf->boundary_integs_marker;
   const int bdr_attributes_max = fes.GetMesh()->bdr_attributes.Max();
   const Array<LinearFormIntegrator*> &boundary_integs = lf->boundary_integs;

   for (int k = 0; k < boundary_integs.Size(); ++k)
   {
      // Get the markers for this integrator
      const Array<int> *boundary_integs_marker_k = boundary_integs_marker[k];

      // check if there are markers for this integrator
      const bool has_markers_k = boundary_integs_marker_k != nullptr;

      if (has_markers_k)
      {
         // Element attribute marker should be of length mesh->attributes
         MFEM_VERIFY(bdr_attributes_max == boundary_integs_marker_k->Size(),
                     "invalid boundary marker for boundary linear form "
                     "integrator #" << k << ", counting from zero");
      }

      // if there are no markers, just use the whole linear form (1)
      if (!has_markers_k) { bdr_markers.HostReadWrite(); bdr_markers = 1; }
      else
      {
         // scan the attributes to set the markers to 0 or 1
         const int NBE = bdr_attributes.Size();
         const auto attr = bdr_attributes.Read();
         const auto attr_markers = boundary_integs_marker_k->Read();
         auto markers_w = bdr_markers.Write();
         MFEM_FORALL(e, NBE, markers_w[e] = attr_markers[attr[e]-1] == 1;);
      }

      // Assemble the linear form
      bdr_b = 0.0;
      boundary_integs[k]->AssembleDevice(fes, bdr_markers, bdr_b);
      bdr_restrict_lex->AddMultTranspose(bdr_b, *lf);
   }
}

void LinearFormExtension::Update()
{
   const FiniteElementSpace &fes = *lf->FESpace();
   const Mesh &mesh = *fes.GetMesh();
   constexpr ElementDofOrdering ordering = ElementDofOrdering::LEXICOGRAPHIC;

   MFEM_VERIFY(lf->Size() == fes.GetVSize(), "");

   if (lf->domain_integs.Size() > 0)
   {
      const int NE = fes.GetNE();
      markers.SetSize(NE);
      //markers.UseDevice(true);

      // Gather the attributes on the host from all the elements
      attributes.SetSize(NE);
      for (int i = 0; i < NE; ++i) { attributes[i] = mesh.GetAttribute(i); }

      elem_restrict_lex = fes.GetElementRestriction(ordering);
      MFEM_VERIFY(elem_restrict_lex, "Element restriction not available");
      b.SetSize(elem_restrict_lex->Height(), Device::GetMemoryType());
      b.UseDevice(true);
   }

   if (lf->boundary_integs.Size() > 0)
   {
      const int nf_bdr = fes.GetNFbyType(FaceType::Boundary);
      bdr_markers.SetSize(nf_bdr);
      // bdr_markers.UseDevice(true);

      // The face restriction will give us "face E-vectors" on the boundary that
      // are numbered in the order of the faces of mesh. This numbering will be
      // different than the numbering of the boundary elements. We compute
      // mappings so that the array `bdr_attributes[i]` gives the boundary
      // attribute of the `i`th boundary face in the mesh face order.
      std::unordered_map<int,int> f_to_be;
      for (int i = 0; i < mesh.GetNBE(); ++i)
      {
         const int f = mesh.GetBdrElementEdgeIndex(i);
         f_to_be[f] = i;
      }
      MFEM_VERIFY(size_t(nf_bdr) == f_to_be.size(), "Incompatible sizes");
      bdr_attributes.SetSize(nf_bdr);
      int f_ind = 0;
      for (int f = 0; f < mesh.GetNumFaces(); ++f)
      {
         if (f_to_be.find(f) != f_to_be.end())
         {
            const int be = f_to_be[f];
            bdr_attributes[f_ind] = mesh.GetBdrAttribute(be);
            ++f_ind;
         }
      }

      bdr_restrict_lex =
         dynamic_cast<const FaceRestriction*>(
            fes.GetFaceRestriction(ordering, FaceType::Boundary,
                                   L2FaceValues::SingleValued));
      MFEM_VERIFY(bdr_restrict_lex, "Face restriction not available");
      bdr_b.SetSize(bdr_restrict_lex->Height(), Device::GetMemoryType());
      bdr_b.UseDevice(true);
   }
}

} // namespace mfem
<commit_msg>Address comment for empty attributes/bdr_attributes<commit_after>// Copyright (c) 2010-2022, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.

#include "linearform.hpp"
#include "../general/forall.hpp"

namespace mfem
{

LinearFormExtension::LinearFormExtension(LinearForm *lf): lf(lf) { Update(); }

void LinearFormExtension::Assemble()
{
   const FiniteElementSpace &fes = *lf->FESpace();
   MFEM_VERIFY(lf->SupportsDevice(), "Not supported.");
   MFEM_VERIFY(lf->Size() == fes.GetVSize(), "LinearForm size does not "
               "match the number of vector dofs!");

   const Array<Array<int>*> &domain_integs_marker = *lf->GetDLFI_Marker();
   const int mesh_attributes_max = fes.GetMesh()->attributes.Size() ?
                                   fes.GetMesh()->attributes.Max() : 0;
   const Array<LinearFormIntegrator*> &domain_integs = *lf->GetDLFI();

   for (int k = 0; k < domain_integs.Size(); ++k)
   {
      // Get the markers for this integrator
      const Array<int> *domain_integs_marker_k = domain_integs_marker[k];

      // check if there are markers for this integrator
      const bool has_markers_k = domain_integs_marker_k != nullptr;

      if (has_markers_k)
      {
         // Element attribute marker should be of length mesh->attributes
         MFEM_VERIFY(mesh_attributes_max == domain_integs_marker_k->Size(),
                     "invalid element marker for domain linear form "
                     "integrator #" << k << ", counting from zero");
      }

      // if there are no markers, just use the whole linear form (1)
      if (!has_markers_k) { markers.HostReadWrite(); markers = 1; }
      else
      {
         // scan the attributes to set the markers to 0 or 1
         const int NE = fes.GetNE();
         const auto attr = attributes.Read();
         const auto dimk = domain_integs_marker_k->Read();
         auto markers_w = markers.Write();
         MFEM_FORALL(e, NE, markers_w[e] = dimk[attr[e]-1] == 1;);
      }

      // Assemble the linear form
      b = 0.0;
      domain_integs[k]->AssembleDevice(fes, markers, b);
      if (k == 0) { elem_restrict_lex->MultTranspose(b, *lf); }
      else { elem_restrict_lex->AddMultTranspose(b, *lf); }
   }

   const Array<Array<int>*> &boundary_integs_marker = lf->boundary_integs_marker;
   const int bdr_attributes_max = fes.GetMesh()->bdr_attributes.Size() ?
                                  fes.GetMesh()->bdr_attributes.Max() : 0;
   const Array<LinearFormIntegrator*> &boundary_integs = lf->boundary_integs;

   for (int k = 0; k < boundary_integs.Size(); ++k)
   {
      // Get the markers for this integrator
      const Array<int> *boundary_integs_marker_k = boundary_integs_marker[k];

      // check if there are markers for this integrator
      const bool has_markers_k = boundary_integs_marker_k != nullptr;

      if (has_markers_k)
      {
         // Element attribute marker should be of length mesh->attributes
         MFEM_VERIFY(bdr_attributes_max == boundary_integs_marker_k->Size(),
                     "invalid boundary marker for boundary linear form "
                     "integrator #" << k << ", counting from zero");
      }

      // if there are no markers, just use the whole linear form (1)
      if (!has_markers_k) { bdr_markers.HostReadWrite(); bdr_markers = 1; }
      else
      {
         // scan the attributes to set the markers to 0 or 1
         const int NBE = bdr_attributes.Size();
         const auto attr = bdr_attributes.Read();
         const auto attr_markers = boundary_integs_marker_k->Read();
         auto markers_w = bdr_markers.Write();
         MFEM_FORALL(e, NBE, markers_w[e] = attr_markers[attr[e]-1] == 1;);
      }

      // Assemble the linear form
      bdr_b = 0.0;
      boundary_integs[k]->AssembleDevice(fes, bdr_markers, bdr_b);
      bdr_restrict_lex->AddMultTranspose(bdr_b, *lf);
   }
}

void LinearFormExtension::Update()
{
   const FiniteElementSpace &fes = *lf->FESpace();
   const Mesh &mesh = *fes.GetMesh();
   constexpr ElementDofOrdering ordering = ElementDofOrdering::LEXICOGRAPHIC;

   MFEM_VERIFY(lf->Size() == fes.GetVSize(), "");

   if (lf->domain_integs.Size() > 0)
   {
      const int NE = fes.GetNE();
      markers.SetSize(NE);
      //markers.UseDevice(true);

      // Gather the attributes on the host from all the elements
      attributes.SetSize(NE);
      for (int i = 0; i < NE; ++i) { attributes[i] = mesh.GetAttribute(i); }

      elem_restrict_lex = fes.GetElementRestriction(ordering);
      MFEM_VERIFY(elem_restrict_lex, "Element restriction not available");
      b.SetSize(elem_restrict_lex->Height(), Device::GetMemoryType());
      b.UseDevice(true);
   }

   if (lf->boundary_integs.Size() > 0)
   {
      const int nf_bdr = fes.GetNFbyType(FaceType::Boundary);
      bdr_markers.SetSize(nf_bdr);
      // bdr_markers.UseDevice(true);

      // The face restriction will give us "face E-vectors" on the boundary that
      // are numbered in the order of the faces of mesh. This numbering will be
      // different than the numbering of the boundary elements. We compute
      // mappings so that the array `bdr_attributes[i]` gives the boundary
      // attribute of the `i`th boundary face in the mesh face order.
      std::unordered_map<int,int> f_to_be;
      for (int i = 0; i < mesh.GetNBE(); ++i)
      {
         const int f = mesh.GetBdrElementEdgeIndex(i);
         f_to_be[f] = i;
      }
      MFEM_VERIFY(size_t(nf_bdr) == f_to_be.size(), "Incompatible sizes");
      bdr_attributes.SetSize(nf_bdr);
      int f_ind = 0;
      for (int f = 0; f < mesh.GetNumFaces(); ++f)
      {
         if (f_to_be.find(f) != f_to_be.end())
         {
            const int be = f_to_be[f];
            bdr_attributes[f_ind] = mesh.GetBdrAttribute(be);
            ++f_ind;
         }
      }

      bdr_restrict_lex =
         dynamic_cast<const FaceRestriction*>(
            fes.GetFaceRestriction(ordering, FaceType::Boundary,
                                   L2FaceValues::SingleValued));
      MFEM_VERIFY(bdr_restrict_lex, "Face restriction not available");
      bdr_b.SetSize(bdr_restrict_lex->Height(), Device::GetMemoryType());
      bdr_b.UseDevice(true);
   }
}

} // namespace mfem
<|endoftext|>


<commit_before>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.

#include "../config/config.hpp"

#ifdef MFEM_USE_MPI

#include "fem.hpp"

namespace mfem
{

ParNonlinearForm::ParNonlinearForm(ParFiniteElementSpace *pf)
   : NonlinearForm(pf), pGrad(Operator::Hypre_ParCSR)
{
   X.MakeRef(pf, NULL);
   Y.MakeRef(pf, NULL);
   MFEM_VERIFY(!Serial(), "internal MFEM error");
}

double ParNonlinearForm::GetParGridFunctionEnergy(const Vector &x) const
{
   double loc_energy, glob_energy;

   loc_energy = GetGridFunctionEnergy(x);

   if (fnfi.Size())
   {
      MFEM_ABORT("TODO: add energy contribution from shared faces");
   }

   MPI_Allreduce(&loc_energy, &glob_energy, 1, MPI_DOUBLE, MPI_SUM,
                 ParFESpace()->GetComm());

   return glob_energy;
}

void ParNonlinearForm::Mult(const Vector &x, Vector &y) const
{
   NonlinearForm::Mult(x, y); // x --(P)--> aux1 --(A_local)--> aux2
   aux2.HostReadWrite();

   if (fnfi.Size())
   {
      // Terms over shared interior faces in parallel.
      ParFiniteElementSpace *pfes = ParFESpace();
      ParMesh *pmesh = pfes->GetParMesh();
      FaceElementTransformations *tr;
      const FiniteElement *fe1, *fe2;
      Array<int> vdofs1, vdofs2;
      Vector el_x, el_y;

      aux1.HostReadWrite();
      X.MakeRef(aux1, 0); // aux1 contains P.x
      const int n_shared_faces = pmesh->GetNSharedFaces();
      for (int i = 0; i < n_shared_faces; i++)
      {
         tr = pmesh->GetSharedFaceTransformations(i, true);

         fe1 = pfes->GetFE(tr->Elem1No);
         fe2 = pfes->GetFaceNbrFE(tr->Elem2No);

         pfes->GetElementVDofs(tr->Elem1No, vdofs1);
         pfes->GetFaceNbrElementVDofs(tr->Elem2No, vdofs2);

         el_x.SetSize(vdofs1.Size() + vdofs2.Size());
         X.GetSubVector(vdofs1, el_x.GetData());
         X.FaceNbrData().GetSubVector(vdofs2, el_x.GetData() + vdofs1.Size());

         for (int k = 0; k < fnfi.Size(); k++)
         {
            fnfi[k]->AssembleFaceVector(*fe1, *fe2, *tr, el_x, el_y);
            aux2.AddElementVector(vdofs1, el_y.HostReadWrite());
         }
      }
   }

   P->MultTranspose(aux2, y);
   y.HostReadWrite();

   for (int i = 0; i < ess_tdof_list.Size(); i++)
   {
      y(ess_tdof_list[i]) = 0.0;
   }
}

const SparseMatrix &ParNonlinearForm::GetLocalGradient(const Vector &x) const
{
   NonlinearForm::GetGradient(x); // (re)assemble Grad, no b.c.

   return *Grad;
}

Operator &ParNonlinearForm::GetGradient(const Vector &x) const
{
   ParFiniteElementSpace *pfes = ParFESpace();

   pGrad.Clear();

   NonlinearForm::GetGradient(x); // (re)assemble Grad, no b.c.

   OperatorHandle dA(pGrad.Type()), Ph(pGrad.Type());

   if (fnfi.Size() == 0)
   {
      dA.MakeSquareBlockDiag(pfes->GetComm(), pfes->GlobalVSize(),
                             pfes->GetDofOffsets(), Grad);
   }
   else
   {
      MFEM_ABORT("TODO: assemble contributions from shared face terms");
   }

   // TODO - construct Dof_TrueDof_Matrix directly in the pGrad format
   Ph.ConvertFrom(pfes->Dof_TrueDof_Matrix());
   pGrad.MakePtAP(dA, Ph);

   // Impose b.c. on pGrad
   OperatorHandle pGrad_e;
   pGrad_e.EliminateRowsCols(pGrad, ess_tdof_list);

   return *pGrad.Ptr();
}

void ParNonlinearForm::Update()
{
   Y.MakeRef(ParFESpace(), NULL);
   X.MakeRef(ParFESpace(), NULL);
   pGrad.Clear();
   NonlinearForm::Update();
}

ParBlockNonlinearForm::ParBlockNonlinearForm(Array<ParFiniteElementSpace *> &pf)
   : BlockNonlinearForm()
{
   pBlockGrad = NULL;
   SetParSpaces(pf);
}

void ParBlockNonlinearForm::SetParSpaces(Array<ParFiniteElementSpace *> &pf)
{
   delete pBlockGrad;
   pBlockGrad = NULL;

   for (int s1=0; s1<fes.Size(); ++s1)
   {
      for (int s2=0; s2<fes.Size(); ++s2)
      {
         delete phBlockGrad(s1,s2);
      }
   }

   Array<FiniteElementSpace *> serialSpaces(pf.Size());

   for (int s=0; s<pf.Size(); s++)
   {
      serialSpaces[s] = (FiniteElementSpace *) pf[s];
   }

   SetSpaces(serialSpaces);

   phBlockGrad.SetSize(fes.Size(), fes.Size());

   for (int s1=0; s1<fes.Size(); ++s1)
   {
      for (int s2=0; s2<fes.Size(); ++s2)
      {
         phBlockGrad(s1,s2) = new OperatorHandle(Operator::Hypre_ParCSR);
      }
   }
}

ParFiniteElementSpace * ParBlockNonlinearForm::ParFESpace(int k)
{
   return (ParFiniteElementSpace *)fes[k];
}

const ParFiniteElementSpace *ParBlockNonlinearForm::ParFESpace(int k) const
{
   return (const ParFiniteElementSpace *)fes[k];
}

// Here, rhs is a true dof vector
void ParBlockNonlinearForm::SetEssentialBC(const
                                           Array<Array<int> *>&bdr_attr_is_ess,
                                           Array<Vector *> &rhs)
{
   Array<Vector *> nullarray(fes.Size());
   nullarray = NULL;

   BlockNonlinearForm::SetEssentialBC(bdr_attr_is_ess, nullarray);

   for (int s=0; s<fes.Size(); ++s)
   {
      if (rhs[s])
      {
         ParFiniteElementSpace *pfes = ParFESpace(s);
         for (int i=0; i < ess_vdofs[s]->Size(); ++i)
         {
            int tdof = pfes->GetLocalTDofNumber((*(ess_vdofs[s]))[i]);
            if (tdof >= 0)
            {
               (*rhs[s])(tdof) = 0.0;
            }
         }
      }
   }
}

void ParBlockNonlinearForm::Mult(const Vector &x, Vector &y) const
{
   xs_true.Update(x.GetData(), block_trueOffsets);
   ys_true.Update(y.GetData(), block_trueOffsets);
   xs.Update(block_offsets);
   ys.Update(block_offsets);

   for (int s=0; s<fes.Size(); ++s)
   {
      fes[s]->GetProlongationMatrix()->Mult(
         xs_true.GetBlock(s), xs.GetBlock(s));
   }

   BlockNonlinearForm::MultBlocked(xs, ys);

   if (fnfi.Size() > 0)
   {
      MFEM_ABORT("TODO: assemble contributions from shared face terms");
   }

   for (int s=0; s<fes.Size(); ++s)
   {
      fes[s]->GetProlongationMatrix()->MultTranspose(
         ys.GetBlock(s), ys_true.GetBlock(s));
   }
}

/// Return the local gradient matrix for the given true-dof vector x
const BlockOperator & ParBlockNonlinearForm::GetLocalGradient(
   const Vector &x) const
{
   xs_true.Update(x.GetData(), block_trueOffsets);
   xs.Update(block_offsets);

   for (int s=0; s<fes.Size(); ++s)
   {
      fes[s]->GetProlongationMatrix()->Mult(
         xs_true.GetBlock(s), xs.GetBlock(s));
   }

   BlockNonlinearForm::GetGradientBlocked(xs); // (re)assemble Grad with b.c.

   return *BlockGrad;
}

// Set the operator type id for the parallel gradient matrix/operator.
void ParBlockNonlinearForm::SetGradientType(Operator::Type tid)
{
   for (int s1=0; s1<fes.Size(); ++s1)
   {
      for (int s2=0; s2<fes.Size(); ++s2)
      {
         phBlockGrad(s1,s2)->SetType(tid);
      }
   }
}

BlockOperator & ParBlockNonlinearForm::GetGradient(const Vector &x) const
{
   if (pBlockGrad == NULL)
   {
      pBlockGrad = new BlockOperator(block_trueOffsets);
   }

   Array<const ParFiniteElementSpace *> pfes(fes.Size());

   for (int s1=0; s1<fes.Size(); ++s1)
   {
      pfes[s1] = ParFESpace(s1);

      for (int s2=0; s2<fes.Size(); ++s2)
      {
         phBlockGrad(s1,s2)->Clear();
      }
   }

   GetLocalGradient(x); // gradients are stored in 'Grads'

   if (fnfi.Size() > 0)
   {
      MFEM_ABORT("TODO: assemble contributions from shared face terms");
   }

   for (int s1=0; s1<fes.Size(); ++s1)
   {
      for (int s2=0; s2<fes.Size(); ++s2)
      {
         OperatorHandle dA(phBlockGrad(s1,s2)->Type()),
                        Ph(phBlockGrad(s1,s2)->Type()),
                        Rh(phBlockGrad(s1,s2)->Type());

         if (s1 == s2)
         {
            dA.MakeSquareBlockDiag(pfes[s1]->GetComm(), pfes[s1]->GlobalVSize(),
                                   pfes[s1]->GetDofOffsets(), Grads(s1,s1));
            Ph.ConvertFrom(pfes[s1]->Dof_TrueDof_Matrix());
            phBlockGrad(s1,s1)->MakePtAP(dA, Ph);
         }
         else
         {
            dA.MakeRectangularBlockDiag(pfes[s1]->GetComm(),
                                        pfes[s1]->GlobalVSize(),
                                        pfes[s2]->GlobalVSize(),
                                        pfes[s1]->GetDofOffsets(),
                                        pfes[s2]->GetDofOffsets(),
                                        Grads(s1,s2));
            Rh.ConvertFrom(pfes[s1]->Dof_TrueDof_Matrix());
            Ph.ConvertFrom(pfes[s2]->Dof_TrueDof_Matrix());

            phBlockGrad(s1,s2)->MakeRAP(Rh, dA, Ph);
         }

         pBlockGrad->SetBlock(s1, s2, phBlockGrad(s1,s2)->Ptr());
      }
   }

   return *pBlockGrad;
}

ParBlockNonlinearForm::~ParBlockNonlinearForm()
{
   delete pBlockGrad;
   for (int s1=0; s1<fes.Size(); ++s1)
   {
      for (int s2=0; s2<fes.Size(); ++s2)
      {
         delete phBlockGrad(s1,s2);
      }
   }
}

}

#endif
<commit_msg>add  X.ExchangeFaceNbrData - deleted by mistake<commit_after>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.

#include "../config/config.hpp"

#ifdef MFEM_USE_MPI

#include "fem.hpp"

namespace mfem
{

ParNonlinearForm::ParNonlinearForm(ParFiniteElementSpace *pf)
   : NonlinearForm(pf), pGrad(Operator::Hypre_ParCSR)
{
   X.MakeRef(pf, NULL);
   Y.MakeRef(pf, NULL);
   MFEM_VERIFY(!Serial(), "internal MFEM error");
}

double ParNonlinearForm::GetParGridFunctionEnergy(const Vector &x) const
{
   double loc_energy, glob_energy;

   loc_energy = GetGridFunctionEnergy(x);

   if (fnfi.Size())
   {
      MFEM_ABORT("TODO: add energy contribution from shared faces");
   }

   MPI_Allreduce(&loc_energy, &glob_energy, 1, MPI_DOUBLE, MPI_SUM,
                 ParFESpace()->GetComm());

   return glob_energy;
}

void ParNonlinearForm::Mult(const Vector &x, Vector &y) const
{
   NonlinearForm::Mult(x, y); // x --(P)--> aux1 --(A_local)--> aux2
   aux2.HostReadWrite();

   if (fnfi.Size())
   {
      // Terms over shared interior faces in parallel.
      ParFiniteElementSpace *pfes = ParFESpace();
      ParMesh *pmesh = pfes->GetParMesh();
      FaceElementTransformations *tr;
      const FiniteElement *fe1, *fe2;
      Array<int> vdofs1, vdofs2;
      Vector el_x, el_y;

      aux1.HostReadWrite();
      X.MakeRef(aux1, 0); // aux1 contains P.x
      X.ExchangeFaceNbrData();
      const int n_shared_faces = pmesh->GetNSharedFaces();
      for (int i = 0; i < n_shared_faces; i++)
      {
         tr = pmesh->GetSharedFaceTransformations(i, true);

         fe1 = pfes->GetFE(tr->Elem1No);
         fe2 = pfes->GetFaceNbrFE(tr->Elem2No);

         pfes->GetElementVDofs(tr->Elem1No, vdofs1);
         pfes->GetFaceNbrElementVDofs(tr->Elem2No, vdofs2);

         el_x.SetSize(vdofs1.Size() + vdofs2.Size());
         X.GetSubVector(vdofs1, el_x.GetData());
         X.FaceNbrData().GetSubVector(vdofs2, el_x.GetData() + vdofs1.Size());

         for (int k = 0; k < fnfi.Size(); k++)
         {
            fnfi[k]->AssembleFaceVector(*fe1, *fe2, *tr, el_x, el_y);
            aux2.AddElementVector(vdofs1, el_y.HostReadWrite());
         }
      }
   }

   P->MultTranspose(aux2, y);
   y.HostReadWrite();

   for (int i = 0; i < ess_tdof_list.Size(); i++)
   {
      y(ess_tdof_list[i]) = 0.0;
   }
}

const SparseMatrix &ParNonlinearForm::GetLocalGradient(const Vector &x) const
{
   NonlinearForm::GetGradient(x); // (re)assemble Grad, no b.c.

   return *Grad;
}

Operator &ParNonlinearForm::GetGradient(const Vector &x) const
{
   ParFiniteElementSpace *pfes = ParFESpace();

   pGrad.Clear();

   NonlinearForm::GetGradient(x); // (re)assemble Grad, no b.c.

   OperatorHandle dA(pGrad.Type()), Ph(pGrad.Type());

   if (fnfi.Size() == 0)
   {
      dA.MakeSquareBlockDiag(pfes->GetComm(), pfes->GlobalVSize(),
                             pfes->GetDofOffsets(), Grad);
   }
   else
   {
      MFEM_ABORT("TODO: assemble contributions from shared face terms");
   }

   // TODO - construct Dof_TrueDof_Matrix directly in the pGrad format
   Ph.ConvertFrom(pfes->Dof_TrueDof_Matrix());
   pGrad.MakePtAP(dA, Ph);

   // Impose b.c. on pGrad
   OperatorHandle pGrad_e;
   pGrad_e.EliminateRowsCols(pGrad, ess_tdof_list);

   return *pGrad.Ptr();
}

void ParNonlinearForm::Update()
{
   Y.MakeRef(ParFESpace(), NULL);
   X.MakeRef(ParFESpace(), NULL);
   pGrad.Clear();
   NonlinearForm::Update();
}

ParBlockNonlinearForm::ParBlockNonlinearForm(Array<ParFiniteElementSpace *> &pf)
   : BlockNonlinearForm()
{
   pBlockGrad = NULL;
   SetParSpaces(pf);
}

void ParBlockNonlinearForm::SetParSpaces(Array<ParFiniteElementSpace *> &pf)
{
   delete pBlockGrad;
   pBlockGrad = NULL;

   for (int s1=0; s1<fes.Size(); ++s1)
   {
      for (int s2=0; s2<fes.Size(); ++s2)
      {
         delete phBlockGrad(s1,s2);
      }
   }

   Array<FiniteElementSpace *> serialSpaces(pf.Size());

   for (int s=0; s<pf.Size(); s++)
   {
      serialSpaces[s] = (FiniteElementSpace *) pf[s];
   }

   SetSpaces(serialSpaces);

   phBlockGrad.SetSize(fes.Size(), fes.Size());

   for (int s1=0; s1<fes.Size(); ++s1)
   {
      for (int s2=0; s2<fes.Size(); ++s2)
      {
         phBlockGrad(s1,s2) = new OperatorHandle(Operator::Hypre_ParCSR);
      }
   }
}

ParFiniteElementSpace * ParBlockNonlinearForm::ParFESpace(int k)
{
   return (ParFiniteElementSpace *)fes[k];
}

const ParFiniteElementSpace *ParBlockNonlinearForm::ParFESpace(int k) const
{
   return (const ParFiniteElementSpace *)fes[k];
}

// Here, rhs is a true dof vector
void ParBlockNonlinearForm::SetEssentialBC(const
                                           Array<Array<int> *>&bdr_attr_is_ess,
                                           Array<Vector *> &rhs)
{
   Array<Vector *> nullarray(fes.Size());
   nullarray = NULL;

   BlockNonlinearForm::SetEssentialBC(bdr_attr_is_ess, nullarray);

   for (int s=0; s<fes.Size(); ++s)
   {
      if (rhs[s])
      {
         ParFiniteElementSpace *pfes = ParFESpace(s);
         for (int i=0; i < ess_vdofs[s]->Size(); ++i)
         {
            int tdof = pfes->GetLocalTDofNumber((*(ess_vdofs[s]))[i]);
            if (tdof >= 0)
            {
               (*rhs[s])(tdof) = 0.0;
            }
         }
      }
   }
}

void ParBlockNonlinearForm::Mult(const Vector &x, Vector &y) const
{
   xs_true.Update(x.GetData(), block_trueOffsets);
   ys_true.Update(y.GetData(), block_trueOffsets);
   xs.Update(block_offsets);
   ys.Update(block_offsets);

   for (int s=0; s<fes.Size(); ++s)
   {
      fes[s]->GetProlongationMatrix()->Mult(
         xs_true.GetBlock(s), xs.GetBlock(s));
   }

   BlockNonlinearForm::MultBlocked(xs, ys);

   if (fnfi.Size() > 0)
   {
      MFEM_ABORT("TODO: assemble contributions from shared face terms");
   }

   for (int s=0; s<fes.Size(); ++s)
   {
      fes[s]->GetProlongationMatrix()->MultTranspose(
         ys.GetBlock(s), ys_true.GetBlock(s));
   }
}

/// Return the local gradient matrix for the given true-dof vector x
const BlockOperator & ParBlockNonlinearForm::GetLocalGradient(
   const Vector &x) const
{
   xs_true.Update(x.GetData(), block_trueOffsets);
   xs.Update(block_offsets);

   for (int s=0; s<fes.Size(); ++s)
   {
      fes[s]->GetProlongationMatrix()->Mult(
         xs_true.GetBlock(s), xs.GetBlock(s));
   }

   BlockNonlinearForm::GetGradientBlocked(xs); // (re)assemble Grad with b.c.

   return *BlockGrad;
}

// Set the operator type id for the parallel gradient matrix/operator.
void ParBlockNonlinearForm::SetGradientType(Operator::Type tid)
{
   for (int s1=0; s1<fes.Size(); ++s1)
   {
      for (int s2=0; s2<fes.Size(); ++s2)
      {
         phBlockGrad(s1,s2)->SetType(tid);
      }
   }
}

BlockOperator & ParBlockNonlinearForm::GetGradient(const Vector &x) const
{
   if (pBlockGrad == NULL)
   {
      pBlockGrad = new BlockOperator(block_trueOffsets);
   }

   Array<const ParFiniteElementSpace *> pfes(fes.Size());

   for (int s1=0; s1<fes.Size(); ++s1)
   {
      pfes[s1] = ParFESpace(s1);

      for (int s2=0; s2<fes.Size(); ++s2)
      {
         phBlockGrad(s1,s2)->Clear();
      }
   }

   GetLocalGradient(x); // gradients are stored in 'Grads'

   if (fnfi.Size() > 0)
   {
      MFEM_ABORT("TODO: assemble contributions from shared face terms");
   }

   for (int s1=0; s1<fes.Size(); ++s1)
   {
      for (int s2=0; s2<fes.Size(); ++s2)
      {
         OperatorHandle dA(phBlockGrad(s1,s2)->Type()),
                        Ph(phBlockGrad(s1,s2)->Type()),
                        Rh(phBlockGrad(s1,s2)->Type());

         if (s1 == s2)
         {
            dA.MakeSquareBlockDiag(pfes[s1]->GetComm(), pfes[s1]->GlobalVSize(),
                                   pfes[s1]->GetDofOffsets(), Grads(s1,s1));
            Ph.ConvertFrom(pfes[s1]->Dof_TrueDof_Matrix());
            phBlockGrad(s1,s1)->MakePtAP(dA, Ph);
         }
         else
         {
            dA.MakeRectangularBlockDiag(pfes[s1]->GetComm(),
                                        pfes[s1]->GlobalVSize(),
                                        pfes[s2]->GlobalVSize(),
                                        pfes[s1]->GetDofOffsets(),
                                        pfes[s2]->GetDofOffsets(),
                                        Grads(s1,s2));
            Rh.ConvertFrom(pfes[s1]->Dof_TrueDof_Matrix());
            Ph.ConvertFrom(pfes[s2]->Dof_TrueDof_Matrix());

            phBlockGrad(s1,s2)->MakeRAP(Rh, dA, Ph);
         }

         pBlockGrad->SetBlock(s1, s2, phBlockGrad(s1,s2)->Ptr());
      }
   }

   return *pBlockGrad;
}

ParBlockNonlinearForm::~ParBlockNonlinearForm()
{
   delete pBlockGrad;
   for (int s1=0; s1<fes.Size(); ++s1)
   {
      for (int s2=0; s2<fes.Size(); ++s2)
      {
         delete phBlockGrad(s1,s2);
      }
   }
}

}

#endif
<|endoftext|>


<commit_before><commit_msg>Test now uses the LatinHypercubeGenerator to generate sample positions<commit_after><|endoftext|>


<commit_before>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/login/chrome_restart_request.h"

#include <vector>

#include "ash/ash_switches.h"
#include "base/command_line.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/prefs/json_pref_store.h"
#include "base/prefs/pref_service.h"
#include "base/process/launch.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/sys_info.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "cc/base/switches.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/boot_times_recorder.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/session_manager_client.h"
#include "chromeos/login/user_names.h"
#include "components/policy/core/common/policy_switches.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "media/base/media_switches.h"
#include "third_party/cros_system_api/switches/chrome_switches.h"
#include "ui/app_list/app_list_switches.h"
#include "ui/base/ui_base_switches.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/events/event_switches.h"
#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
#include "ui/ozone/public/ozone_switches.h"
#include "ui/wm/core/wm_core_switches.h"
#include "url/gurl.h"

using content::BrowserThread;

namespace chromeos {

namespace {

// Increase logging level for Guest mode to avoid INFO messages in logs.
const char kGuestModeLoggingLevel[] = "1";

// Format of command line switch.
const char kSwitchFormatString[] = " --%s=\"%s\"";

// Derives the new command line from |base_command_line| by doing the following:
// - Forward a given switches list to new command;
// - Set start url if given;
// - Append/override switches using |new_switches|;
std::string DeriveCommandLine(const GURL& start_url,
                              const base::CommandLine& base_command_line,
                              const base::DictionaryValue& new_switches,
                              base::CommandLine* command_line) {
  DCHECK_NE(&base_command_line, command_line);

  static const char* const kForwardSwitches[] = {
    ::switches::kBlinkSettings,
    ::switches::kDisableAccelerated2dCanvas,
    ::switches::kDisableAcceleratedJpegDecoding,
    ::switches::kDisableAcceleratedVideoDecode,
    ::switches::kDisableBlinkFeatures,
    ::switches::kDisableCastStreamingHWEncoding,
    ::switches::kDisableDelegatedRenderer,
    ::switches::kDisableDistanceFieldText,
    ::switches::kDisableGpu,
    ::switches::kDisableGpuShaderDiskCache,
    ::switches::kDisableGpuWatchdog,
    ::switches::kDisableGpuCompositing,
    ::switches::kDisableGpuRasterization,
    ::switches::kDisableLowResTiling,
    ::switches::kDisableMediaSource,
    ::switches::kDisableOneCopy,
    ::switches::kDisablePreferCompositingToLCDText,
    ::switches::kDisablePrefixedEncryptedMedia,
    ::switches::kDisablePanelFitting,
    ::switches::kDisableSeccompFilterSandbox,
    ::switches::kDisableSetuidSandbox,
    ::switches::kDisableSlimmingPaint,
    ::switches::kDisableSurfaces,
    ::switches::kDisableTextBlobs,
    ::switches::kDisableThreadedScrolling,
    ::switches::kDisableTouchDragDrop,
    ::switches::kDisableTouchEditing,
    ::switches::kEnableAcceleratedMjpegDecode,
    ::switches::kEnableBlinkFeatures,
    ::switches::kEnableCompositorAnimationTimelines,
    ::switches::kEnableDelegatedRenderer,
    ::switches::kDisableDisplayList2dCanvas,
    ::switches::kEnableDisplayList2dCanvas,
    ::switches::kForceDisplayList2dCanvas,
    ::switches::kDisableEncryptedMedia,
    ::switches::kDisableGpuSandbox,
    ::switches::kEnableDistanceFieldText,
    ::switches::kEnableGpuRasterization,
    ::switches::kEnableImageColorProfiles,
    ::switches::kEnableLogging,
    ::switches::kEnableLowResTiling,
    ::switches::kEnablePinch,
    ::switches::kEnablePreferCompositingToLCDText,
    ::switches::kEnablePluginPlaceholderShadowDom,
    ::switches::kEnableSlimmingPaint,
    ::switches::kEnableTouchDragDrop,
    ::switches::kEnableTouchEditing,
    ::switches::kEnableViewport,
    ::switches::kEnableViewportMeta,
    ::switches::kEnableZeroCopy,
#if defined(USE_OZONE)
    ::switches::kExtraTouchNoiseFiltering,
#endif
    ::switches::kMainFrameResizesAreOrientationChanges,
    ::switches::kForceDeviceScaleFactor,
    ::switches::kForceGpuRasterization,
    ::switches::kGpuRasterizationMSAASampleCount,
    ::switches::kGpuStartupDialog,
    ::switches::kGpuSandboxAllowSysVShm,
    ::switches::kGpuSandboxFailuresFatal,
    ::switches::kGpuSandboxStartEarly,
    ::switches::kNoSandbox,
    ::switches::kNumRasterThreads,
    ::switches::kPpapiFlashArgs,
    ::switches::kPpapiFlashPath,
    ::switches::kPpapiFlashVersion,
    ::switches::kPpapiInProcess,
    ::switches::kRendererStartupDialog,
    ::switches::kRootLayerScrolls,
    ::switches::kEnableShareGroupAsyncTextureUpload,
    ::switches::kTabCaptureUpscaleQuality,
    ::switches::kTabCaptureDownscaleQuality,
#if defined(USE_X11) || defined(USE_OZONE)
    ::switches::kTouchCalibration,
#endif
    ::switches::kTouchDevices,
    ::switches::kTouchEvents,
    ::switches::kUIDisableThreadedCompositing,
    ::switches::kUIEnableCompositorAnimationTimelines,
    ::switches::kUIPrioritizeInGpuProcess,
#if defined(USE_CRAS)
    ::switches::kUseCras,
#endif
    ::switches::kUseGL,
    ::switches::kUseNormalPriorityForTileTaskWorkerThreads,
    ::switches::kUserDataDir,
    ::switches::kV,
    ::switches::kVModule,
    ::switches::kEnableWebGLDraftExtensions,
    ::switches::kEnableWebGLImageChromium,
    ::switches::kEnableWebVR,
#if defined(ENABLE_WEBRTC)
    ::switches::kDisableWebRtcHWDecoding,
    ::switches::kDisableWebRtcHWEncoding,
    ::switches::kEnableWebRtcHWH264Encoding,
#endif
    ::switches::kDisableVaapiAcceleratedVideoEncode,
#if defined(USE_OZONE)
    ::switches::kOzoneInitialDisplayBounds,
    ::switches::kOzoneInitialDisplayPhysicalSizeMm,
    ::switches::kOzonePlatform,
    ::switches::kOzoneUseSurfaceless,
#endif
    app_list::switches::kDisableSyncAppList,
    app_list::switches::kEnableCenteredAppList,
    app_list::switches::kEnableSyncAppList,
    ash::switches::kAshEnablePowerButtonQuickLock,
    ash::switches::kAshEnableUnifiedDesktop,
    ash::switches::kAshHostWindowBounds,
    ash::switches::kAshTouchHud,
    ash::switches::kAuraLegacyPowerButton,
    chromeos::switches::kDefaultWallpaperLarge,
    chromeos::switches::kDefaultWallpaperSmall,
    chromeos::switches::kGuestWallpaperLarge,
    chromeos::switches::kGuestWallpaperSmall,
    // Please keep these in alphabetical order. Non-UI Compositor switches
    // here should also be added to
    // content/browser/renderer_host/render_process_host_impl.cc.
    cc::switches::kCompositeToMailbox,
    cc::switches::kDisableCompositedAntialiasing,
    cc::switches::kDisableMainFrameBeforeActivation,
    cc::switches::kDisableThreadedAnimation,
    cc::switches::kEnableBeginFrameScheduling,
    cc::switches::kEnableGpuBenchmarking,
    cc::switches::kEnablePropertyTreeVerification,
    cc::switches::kEnableMainFrameBeforeActivation,
    cc::switches::kMaxTilesForInterestArea,
    cc::switches::kMaxUnusedResourceMemoryUsagePercentage,
    cc::switches::kShowCompositedLayerBorders,
    cc::switches::kShowFPSCounter,
    cc::switches::kShowLayerAnimationBounds,
    cc::switches::kShowPropertyChangedRects,
    cc::switches::kShowReplicaScreenSpaceRects,
    cc::switches::kShowScreenSpaceRects,
    cc::switches::kShowSurfaceDamageRects,
    cc::switches::kSlowDownRasterScaleFactor,
    cc::switches::kUIDisablePartialSwap,
    chromeos::switches::kConsumerDeviceManagementUrl,
    chromeos::switches::kDbusStub,
    chromeos::switches::kDbusUnstubClients,
    chromeos::switches::kDisableLoginAnimations,
    chromeos::switches::kEnableConsumerManagement,
    chromeos::switches::kEnterpriseEnableForcedReEnrollment,
    chromeos::switches::kHasChromeOSDiamondKey,
    chromeos::switches::kHasChromeOSKeyboard,
    chromeos::switches::kLoginProfile,
    chromeos::switches::kNaturalScrollDefault,
    chromeos::switches::kSystemInDevMode,
    policy::switches::kDeviceManagementUrl,
    wm::switches::kWindowAnimationsDisabled,
  };
  command_line->CopySwitchesFrom(base_command_line,
                                 kForwardSwitches,
                                 arraysize(kForwardSwitches));

  if (start_url.is_valid())
    command_line->AppendArg(start_url.spec());

  for (base::DictionaryValue::Iterator it(new_switches);
       !it.IsAtEnd();
       it.Advance()) {
    std::string value;
    CHECK(it.value().GetAsString(&value));
    command_line->AppendSwitchASCII(it.key(), value);
  }

  std::string cmd_line_str = command_line->GetCommandLineString();
  // Special workaround for the arguments that should be quoted.
  // Copying switches won't be needed when Guest mode won't need restart
  // http://crosbug.com/6924
  if (base_command_line.HasSwitch(::switches::kRegisterPepperPlugins)) {
    cmd_line_str += base::StringPrintf(
        kSwitchFormatString,
        ::switches::kRegisterPepperPlugins,
        base_command_line.GetSwitchValueNative(
            ::switches::kRegisterPepperPlugins).c_str());
  }

  return cmd_line_str;
}

// Simulates a session manager restart by launching give command line
// and exit current process.
void ReLaunch(const std::string& command_line) {
  std::vector<std::string> argv;

  // This is not a proper way to get |argv| but it's good enough for debugging.
  base::SplitString(command_line, ' ', &argv);

  base::LaunchProcess(argv, base::LaunchOptions());
  chrome::AttemptUserExit();
}

// Empty function that run by the local state task runner to ensure last
// commit goes through.
void EnsureLocalStateIsWritten() {}

// Wraps the work of sending chrome restart request to session manager.
// If local state is present, try to commit it first. The request is fired when
// the commit goes through or some time (3 seconds) has elapsed.
class ChromeRestartRequest
    : public base::SupportsWeakPtr<ChromeRestartRequest> {
 public:
  explicit ChromeRestartRequest(const std::string& command_line);
  ~ChromeRestartRequest();

  // Starts the request.
  void Start();

 private:
  // Fires job restart request to session manager.
  void RestartJob();

  const int pid_;
  const std::string command_line_;
  base::OneShotTimer<ChromeRestartRequest> timer_;

  DISALLOW_COPY_AND_ASSIGN(ChromeRestartRequest);
};

ChromeRestartRequest::ChromeRestartRequest(const std::string& command_line)
    : pid_(getpid()),
      command_line_(command_line) {}

ChromeRestartRequest::~ChromeRestartRequest() {}

void ChromeRestartRequest::Start() {
  VLOG(1) << "Requesting a restart with PID " << pid_
          << " and command line: " << command_line_;

  // Session Manager may kill the chrome anytime after this point.
  // Write exit_cleanly and other stuff to the disk here.
  g_browser_process->EndSession();

  PrefService* local_state = g_browser_process->local_state();
  if (!local_state) {
    RestartJob();
    return;
  }

  // XXX: normally this call must not be needed, however RestartJob
  // just kills us so settings may be lost. See http://crosbug.com/13102
  local_state->CommitPendingWrite();
  timer_.Start(
      FROM_HERE, base::TimeDelta::FromSeconds(3), this,
      &ChromeRestartRequest::RestartJob);

  // Post a task to local state task runner thus it occurs last on the task
  // queue, so it would be executed after committing pending write on that
  // thread.
  scoped_refptr<base::SequencedTaskRunner> local_state_task_runner =
      JsonPrefStore::GetTaskRunnerForFile(
          base::FilePath(chrome::kLocalStorePoolName),
          BrowserThread::GetBlockingPool());
  local_state_task_runner->PostTaskAndReply(
      FROM_HERE,
      base::Bind(&EnsureLocalStateIsWritten),
      base::Bind(&ChromeRestartRequest::RestartJob, AsWeakPtr()));
}

void ChromeRestartRequest::RestartJob() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  DBusThreadManager::Get()->GetSessionManagerClient()->RestartJob(
      pid_, command_line_);

  delete this;
}

}  // namespace

std::string GetOffTheRecordCommandLine(
    const GURL& start_url,
    bool is_oobe_completed,
    const base::CommandLine& base_command_line,
    base::CommandLine* command_line) {
  base::DictionaryValue otr_switches;
  otr_switches.SetString(switches::kGuestSession, std::string());
  otr_switches.SetString(::switches::kIncognito, std::string());
  otr_switches.SetString(::switches::kLoggingLevel, kGuestModeLoggingLevel);
  otr_switches.SetString(switches::kLoginUser, chromeos::login::kGuestUserName);

  // Override the home page.
  otr_switches.SetString(::switches::kHomePage,
                         GURL(chrome::kChromeUINewTabURL).spec());

  // If OOBE is not finished yet, lock down the guest session to not allow
  // surfing the web. Guest mode is still useful to inspect logs and run network
  // diagnostics.
  if (!is_oobe_completed)
    otr_switches.SetString(switches::kOobeGuestSession, std::string());

  return DeriveCommandLine(start_url,
                           base_command_line,
                           otr_switches,
                           command_line);
}

void RestartChrome(const std::string& command_line) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  BootTimesRecorder::Get()->set_restart_requested();

  static bool restart_requested = false;
  if (restart_requested) {
    NOTREACHED() << "Request chrome restart for more than once.";
  }
  restart_requested = true;

  if (!base::SysInfo::IsRunningOnChromeOS()) {
    // Relaunch chrome without session manager on dev box.
    ReLaunch(command_line);
    return;
  }

  // ChromeRestartRequest deletes itself after request sent to session manager.
  (new ChromeRestartRequest(command_line))->Start();
}

}  // namespace chromeos
<commit_msg>Added switches::kTopChromeMD flag to DeriveCommandLine(...) in chrome_restart_request.cc.<commit_after>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/login/chrome_restart_request.h"

#include <vector>

#include "ash/ash_switches.h"
#include "base/command_line.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/prefs/json_pref_store.h"
#include "base/prefs/pref_service.h"
#include "base/process/launch.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/sys_info.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "cc/base/switches.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/boot_times_recorder.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/session_manager_client.h"
#include "chromeos/login/user_names.h"
#include "components/policy/core/common/policy_switches.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "media/base/media_switches.h"
#include "third_party/cros_system_api/switches/chrome_switches.h"
#include "ui/app_list/app_list_switches.h"
#include "ui/base/ui_base_switches.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/events/event_switches.h"
#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
#include "ui/ozone/public/ozone_switches.h"
#include "ui/wm/core/wm_core_switches.h"
#include "url/gurl.h"

using content::BrowserThread;

namespace chromeos {

namespace {

// Increase logging level for Guest mode to avoid INFO messages in logs.
const char kGuestModeLoggingLevel[] = "1";

// Format of command line switch.
const char kSwitchFormatString[] = " --%s=\"%s\"";

// Derives the new command line from |base_command_line| by doing the following:
// - Forward a given switches list to new command;
// - Set start url if given;
// - Append/override switches using |new_switches|;
std::string DeriveCommandLine(const GURL& start_url,
                              const base::CommandLine& base_command_line,
                              const base::DictionaryValue& new_switches,
                              base::CommandLine* command_line) {
  DCHECK_NE(&base_command_line, command_line);

  static const char* const kForwardSwitches[] = {
    ::switches::kBlinkSettings,
    ::switches::kDisableAccelerated2dCanvas,
    ::switches::kDisableAcceleratedJpegDecoding,
    ::switches::kDisableAcceleratedVideoDecode,
    ::switches::kDisableBlinkFeatures,
    ::switches::kDisableCastStreamingHWEncoding,
    ::switches::kDisableDelegatedRenderer,
    ::switches::kDisableDistanceFieldText,
    ::switches::kDisableGpu,
    ::switches::kDisableGpuShaderDiskCache,
    ::switches::kDisableGpuWatchdog,
    ::switches::kDisableGpuCompositing,
    ::switches::kDisableGpuRasterization,
    ::switches::kDisableLowResTiling,
    ::switches::kDisableMediaSource,
    ::switches::kDisableOneCopy,
    ::switches::kDisablePreferCompositingToLCDText,
    ::switches::kDisablePrefixedEncryptedMedia,
    ::switches::kDisablePanelFitting,
    ::switches::kDisableSeccompFilterSandbox,
    ::switches::kDisableSetuidSandbox,
    ::switches::kDisableSlimmingPaint,
    ::switches::kDisableSurfaces,
    ::switches::kDisableTextBlobs,
    ::switches::kDisableThreadedScrolling,
    ::switches::kDisableTouchDragDrop,
    ::switches::kDisableTouchEditing,
    ::switches::kEnableAcceleratedMjpegDecode,
    ::switches::kEnableBlinkFeatures,
    ::switches::kEnableCompositorAnimationTimelines,
    ::switches::kEnableDelegatedRenderer,
    ::switches::kDisableDisplayList2dCanvas,
    ::switches::kEnableDisplayList2dCanvas,
    ::switches::kForceDisplayList2dCanvas,
    ::switches::kDisableEncryptedMedia,
    ::switches::kDisableGpuSandbox,
    ::switches::kEnableDistanceFieldText,
    ::switches::kEnableGpuRasterization,
    ::switches::kEnableImageColorProfiles,
    ::switches::kEnableLogging,
    ::switches::kEnableLowResTiling,
    ::switches::kEnablePinch,
    ::switches::kEnablePreferCompositingToLCDText,
    ::switches::kEnablePluginPlaceholderShadowDom,
    ::switches::kEnableSlimmingPaint,
    ::switches::kEnableTouchDragDrop,
    ::switches::kEnableTouchEditing,
    ::switches::kEnableViewport,
    ::switches::kEnableViewportMeta,
    ::switches::kEnableZeroCopy,
#if defined(USE_OZONE)
    ::switches::kExtraTouchNoiseFiltering,
#endif
    ::switches::kMainFrameResizesAreOrientationChanges,
    ::switches::kForceDeviceScaleFactor,
    ::switches::kForceGpuRasterization,
    ::switches::kGpuRasterizationMSAASampleCount,
    ::switches::kGpuStartupDialog,
    ::switches::kGpuSandboxAllowSysVShm,
    ::switches::kGpuSandboxFailuresFatal,
    ::switches::kGpuSandboxStartEarly,
    ::switches::kNoSandbox,
    ::switches::kNumRasterThreads,
    ::switches::kPpapiFlashArgs,
    ::switches::kPpapiFlashPath,
    ::switches::kPpapiFlashVersion,
    ::switches::kPpapiInProcess,
    ::switches::kRendererStartupDialog,
    ::switches::kRootLayerScrolls,
    ::switches::kEnableShareGroupAsyncTextureUpload,
    ::switches::kTabCaptureUpscaleQuality,
    ::switches::kTabCaptureDownscaleQuality,
#if defined(USE_X11) || defined(USE_OZONE)
    ::switches::kTouchCalibration,
#endif
    ::switches::kTouchDevices,
    ::switches::kTouchEvents,
#if defined(ENABLE_TOPCHROME_MD)
    ::switches::kTopChromeMD,
#endif
    ::switches::kUIDisableThreadedCompositing,
    ::switches::kUIEnableCompositorAnimationTimelines,
    ::switches::kUIPrioritizeInGpuProcess,
#if defined(USE_CRAS)
    ::switches::kUseCras,
#endif
    ::switches::kUseGL,
    ::switches::kUseNormalPriorityForTileTaskWorkerThreads,
    ::switches::kUserDataDir,
    ::switches::kV,
    ::switches::kVModule,
    ::switches::kEnableWebGLDraftExtensions,
    ::switches::kEnableWebGLImageChromium,
    ::switches::kEnableWebVR,
#if defined(ENABLE_WEBRTC)
    ::switches::kDisableWebRtcHWDecoding,
    ::switches::kDisableWebRtcHWEncoding,
    ::switches::kEnableWebRtcHWH264Encoding,
#endif
    ::switches::kDisableVaapiAcceleratedVideoEncode,
#if defined(USE_OZONE)
    ::switches::kOzoneInitialDisplayBounds,
    ::switches::kOzoneInitialDisplayPhysicalSizeMm,
    ::switches::kOzonePlatform,
    ::switches::kOzoneUseSurfaceless,
#endif
    app_list::switches::kDisableSyncAppList,
    app_list::switches::kEnableCenteredAppList,
    app_list::switches::kEnableSyncAppList,
    ash::switches::kAshEnablePowerButtonQuickLock,
    ash::switches::kAshEnableUnifiedDesktop,
    ash::switches::kAshHostWindowBounds,
    ash::switches::kAshTouchHud,
    ash::switches::kAuraLegacyPowerButton,
    chromeos::switches::kDefaultWallpaperLarge,
    chromeos::switches::kDefaultWallpaperSmall,
    chromeos::switches::kGuestWallpaperLarge,
    chromeos::switches::kGuestWallpaperSmall,
    // Please keep these in alphabetical order. Non-UI Compositor switches
    // here should also be added to
    // content/browser/renderer_host/render_process_host_impl.cc.
    cc::switches::kCompositeToMailbox,
    cc::switches::kDisableCompositedAntialiasing,
    cc::switches::kDisableMainFrameBeforeActivation,
    cc::switches::kDisableThreadedAnimation,
    cc::switches::kEnableBeginFrameScheduling,
    cc::switches::kEnableGpuBenchmarking,
    cc::switches::kEnablePropertyTreeVerification,
    cc::switches::kEnableMainFrameBeforeActivation,
    cc::switches::kMaxTilesForInterestArea,
    cc::switches::kMaxUnusedResourceMemoryUsagePercentage,
    cc::switches::kShowCompositedLayerBorders,
    cc::switches::kShowFPSCounter,
    cc::switches::kShowLayerAnimationBounds,
    cc::switches::kShowPropertyChangedRects,
    cc::switches::kShowReplicaScreenSpaceRects,
    cc::switches::kShowScreenSpaceRects,
    cc::switches::kShowSurfaceDamageRects,
    cc::switches::kSlowDownRasterScaleFactor,
    cc::switches::kUIDisablePartialSwap,
    chromeos::switches::kConsumerDeviceManagementUrl,
    chromeos::switches::kDbusStub,
    chromeos::switches::kDbusUnstubClients,
    chromeos::switches::kDisableLoginAnimations,
    chromeos::switches::kEnableConsumerManagement,
    chromeos::switches::kEnterpriseEnableForcedReEnrollment,
    chromeos::switches::kHasChromeOSDiamondKey,
    chromeos::switches::kHasChromeOSKeyboard,
    chromeos::switches::kLoginProfile,
    chromeos::switches::kNaturalScrollDefault,
    chromeos::switches::kSystemInDevMode,
    policy::switches::kDeviceManagementUrl,
    wm::switches::kWindowAnimationsDisabled,
  };
  command_line->CopySwitchesFrom(base_command_line,
                                 kForwardSwitches,
                                 arraysize(kForwardSwitches));

  if (start_url.is_valid())
    command_line->AppendArg(start_url.spec());

  for (base::DictionaryValue::Iterator it(new_switches);
       !it.IsAtEnd();
       it.Advance()) {
    std::string value;
    CHECK(it.value().GetAsString(&value));
    command_line->AppendSwitchASCII(it.key(), value);
  }

  std::string cmd_line_str = command_line->GetCommandLineString();
  // Special workaround for the arguments that should be quoted.
  // Copying switches won't be needed when Guest mode won't need restart
  // http://crosbug.com/6924
  if (base_command_line.HasSwitch(::switches::kRegisterPepperPlugins)) {
    cmd_line_str += base::StringPrintf(
        kSwitchFormatString,
        ::switches::kRegisterPepperPlugins,
        base_command_line.GetSwitchValueNative(
            ::switches::kRegisterPepperPlugins).c_str());
  }

  return cmd_line_str;
}

// Simulates a session manager restart by launching give command line
// and exit current process.
void ReLaunch(const std::string& command_line) {
  std::vector<std::string> argv;

  // This is not a proper way to get |argv| but it's good enough for debugging.
  base::SplitString(command_line, ' ', &argv);

  base::LaunchProcess(argv, base::LaunchOptions());
  chrome::AttemptUserExit();
}

// Empty function that run by the local state task runner to ensure last
// commit goes through.
void EnsureLocalStateIsWritten() {}

// Wraps the work of sending chrome restart request to session manager.
// If local state is present, try to commit it first. The request is fired when
// the commit goes through or some time (3 seconds) has elapsed.
class ChromeRestartRequest
    : public base::SupportsWeakPtr<ChromeRestartRequest> {
 public:
  explicit ChromeRestartRequest(const std::string& command_line);
  ~ChromeRestartRequest();

  // Starts the request.
  void Start();

 private:
  // Fires job restart request to session manager.
  void RestartJob();

  const int pid_;
  const std::string command_line_;
  base::OneShotTimer<ChromeRestartRequest> timer_;

  DISALLOW_COPY_AND_ASSIGN(ChromeRestartRequest);
};

ChromeRestartRequest::ChromeRestartRequest(const std::string& command_line)
    : pid_(getpid()),
      command_line_(command_line) {}

ChromeRestartRequest::~ChromeRestartRequest() {}

void ChromeRestartRequest::Start() {
  VLOG(1) << "Requesting a restart with PID " << pid_
          << " and command line: " << command_line_;

  // Session Manager may kill the chrome anytime after this point.
  // Write exit_cleanly and other stuff to the disk here.
  g_browser_process->EndSession();

  PrefService* local_state = g_browser_process->local_state();
  if (!local_state) {
    RestartJob();
    return;
  }

  // XXX: normally this call must not be needed, however RestartJob
  // just kills us so settings may be lost. See http://crosbug.com/13102
  local_state->CommitPendingWrite();
  timer_.Start(
      FROM_HERE, base::TimeDelta::FromSeconds(3), this,
      &ChromeRestartRequest::RestartJob);

  // Post a task to local state task runner thus it occurs last on the task
  // queue, so it would be executed after committing pending write on that
  // thread.
  scoped_refptr<base::SequencedTaskRunner> local_state_task_runner =
      JsonPrefStore::GetTaskRunnerForFile(
          base::FilePath(chrome::kLocalStorePoolName),
          BrowserThread::GetBlockingPool());
  local_state_task_runner->PostTaskAndReply(
      FROM_HERE,
      base::Bind(&EnsureLocalStateIsWritten),
      base::Bind(&ChromeRestartRequest::RestartJob, AsWeakPtr()));
}

void ChromeRestartRequest::RestartJob() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  DBusThreadManager::Get()->GetSessionManagerClient()->RestartJob(
      pid_, command_line_);

  delete this;
}

}  // namespace

std::string GetOffTheRecordCommandLine(
    const GURL& start_url,
    bool is_oobe_completed,
    const base::CommandLine& base_command_line,
    base::CommandLine* command_line) {
  base::DictionaryValue otr_switches;
  otr_switches.SetString(switches::kGuestSession, std::string());
  otr_switches.SetString(::switches::kIncognito, std::string());
  otr_switches.SetString(::switches::kLoggingLevel, kGuestModeLoggingLevel);
  otr_switches.SetString(switches::kLoginUser, chromeos::login::kGuestUserName);

  // Override the home page.
  otr_switches.SetString(::switches::kHomePage,
                         GURL(chrome::kChromeUINewTabURL).spec());

  // If OOBE is not finished yet, lock down the guest session to not allow
  // surfing the web. Guest mode is still useful to inspect logs and run network
  // diagnostics.
  if (!is_oobe_completed)
    otr_switches.SetString(switches::kOobeGuestSession, std::string());

  return DeriveCommandLine(start_url,
                           base_command_line,
                           otr_switches,
                           command_line);
}

void RestartChrome(const std::string& command_line) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  BootTimesRecorder::Get()->set_restart_requested();

  static bool restart_requested = false;
  if (restart_requested) {
    NOTREACHED() << "Request chrome restart for more than once.";
  }
  restart_requested = true;

  if (!base::SysInfo::IsRunningOnChromeOS()) {
    // Relaunch chrome without session manager on dev box.
    ReLaunch(command_line);
    return;
  }

  // ChromeRestartRequest deletes itself after request sent to session manager.
  (new ChromeRestartRequest(command_line))->Start();
}

}  // namespace chromeos
<|endoftext|>


<commit_before><commit_msg>Addressed some warnings raised by Xcode 10.2<commit_after><|endoftext|>


<commit_before>/*************************************************************************/
/*  noise_texture.cpp                                                    */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "noise_texture.h"

#include "core/core_string_names.h"

NoiseTexture::NoiseTexture() {
	update_queued = false;
	regen_queued = false;
	first_time = true;

	size = Vector2i(512, 512);
	seamless = false;
	as_normalmap = false;
	bump_strength = 8.0;
	flags = FLAGS_DEFAULT;

	noise = Ref<OpenSimplexNoise>();

	texture = VS::get_singleton()->texture_create();

	_queue_update();
}

NoiseTexture::~NoiseTexture() {
	VS::get_singleton()->free(texture);
	noise_thread.wait_to_finish();
}

void NoiseTexture::_bind_methods() {

	ClassDB::bind_method(D_METHOD("set_width", "width"), &NoiseTexture::set_width);
	ClassDB::bind_method(D_METHOD("set_height", "height"), &NoiseTexture::set_height);

	ClassDB::bind_method(D_METHOD("set_noise", "noise"), &NoiseTexture::set_noise);
	ClassDB::bind_method(D_METHOD("get_noise"), &NoiseTexture::get_noise);

	ClassDB::bind_method(D_METHOD("set_seamless", "seamless"), &NoiseTexture::set_seamless);
	ClassDB::bind_method(D_METHOD("get_seamless"), &NoiseTexture::get_seamless);

	ClassDB::bind_method(D_METHOD("set_as_normalmap", "as_normalmap"), &NoiseTexture::set_as_normalmap);
	ClassDB::bind_method(D_METHOD("is_normalmap"), &NoiseTexture::is_normalmap);

	ClassDB::bind_method(D_METHOD("set_bump_strength", "bump_strength"), &NoiseTexture::set_bump_strength);
	ClassDB::bind_method(D_METHOD("get_bump_strength"), &NoiseTexture::get_bump_strength);

	ClassDB::bind_method(D_METHOD("_update_texture"), &NoiseTexture::_update_texture);
	ClassDB::bind_method(D_METHOD("_queue_update"), &NoiseTexture::_queue_update);
	ClassDB::bind_method(D_METHOD("_generate_texture"), &NoiseTexture::_generate_texture);
	ClassDB::bind_method(D_METHOD("_thread_done", "image"), &NoiseTexture::_thread_done);

	ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,2048,1,or_greater"), "set_width", "get_width");
	ADD_PROPERTY(PropertyInfo(Variant::INT, "height", PROPERTY_HINT_RANGE, "1,2048,1,or_greater"), "set_height", "get_height");
	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "seamless"), "set_seamless", "get_seamless");
	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "as_normalmap"), "set_as_normalmap", "is_normalmap");
	ADD_PROPERTY(PropertyInfo(Variant::REAL, "bump_strength", PROPERTY_HINT_RANGE, "0,32,0.1,or_greater"), "set_bump_strength", "get_bump_strength");
	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "OpenSimplexNoise"), "set_noise", "get_noise");
}

void NoiseTexture::_validate_property(PropertyInfo &property) const {

	if (property.name == "bump_strength") {
		if (!as_normalmap) {
			property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
		}
	}
}

void NoiseTexture::_set_texture_data(const Ref<Image> &p_image) {
	data = p_image;
	if (data.is_valid()) {
		VS::get_singleton()->texture_allocate(texture, size.x, size.y, 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, flags);
		VS::get_singleton()->texture_set_data(texture, p_image);
	}
	emit_changed();
}

void NoiseTexture::_thread_done(const Ref<Image> &p_image) {

	_set_texture_data(p_image);
	noise_thread.wait_to_finish();
	if (regen_queued) {
		noise_thread.start(_thread_function, this);
		regen_queued = false;
	}
}

void NoiseTexture::_thread_function(void *p_ud) {
	NoiseTexture *tex = (NoiseTexture *)p_ud;
	tex->call_deferred("_thread_done", tex->_generate_texture());
}

void NoiseTexture::_queue_update() {

	if (update_queued)
		return;

	update_queued = true;
	call_deferred("_update_texture");
}

Ref<Image> NoiseTexture::_generate_texture() {

	// Prevent memdelete due to unref() on other thread.
	Ref<OpenSimplexNoise> ref_noise = noise;

	if (ref_noise.is_null()) {
		return Ref<Image>();
	}

	Ref<Image> image;

	if (seamless) {
		image = ref_noise->get_seamless_image(size.x);
	} else {
		image = ref_noise->get_image(size.x, size.y);
	}

	if (as_normalmap) {
		image->bumpmap_to_normalmap(bump_strength);
	}

	return image;
}

void NoiseTexture::_update_texture() {
	bool use_thread = true;
	if (first_time) {
		use_thread = false;
		first_time = false;
	}
#ifdef NO_THREADS
	use_thread = false;
#endif
	if (use_thread) {

		if (noise_thread.is_started()) {
			noise_thread.start(_thread_function, this);
			regen_queued = false;
		} else {
			regen_queued = true;
		}

	} else {
		Ref<Image> image = _generate_texture();
		_set_texture_data(image);
	}
	update_queued = false;
}

void NoiseTexture::set_noise(Ref<OpenSimplexNoise> p_noise) {
	if (p_noise == noise)
		return;
	if (noise.is_valid()) {
		noise->disconnect(CoreStringNames::get_singleton()->changed, this, "_queue_update");
	}
	noise = p_noise;
	if (noise.is_valid()) {
		noise->connect(CoreStringNames::get_singleton()->changed, this, "_queue_update");
	}
	_queue_update();
}

Ref<OpenSimplexNoise> NoiseTexture::get_noise() {
	return noise;
}

void NoiseTexture::set_width(int p_width) {
	if (p_width == size.x) return;
	size.x = p_width;
	_queue_update();
}

void NoiseTexture::set_height(int p_height) {
	if (p_height == size.y) return;
	size.y = p_height;
	_queue_update();
}

void NoiseTexture::set_seamless(bool p_seamless) {
	if (p_seamless == seamless) return;
	seamless = p_seamless;
	_queue_update();
}

bool NoiseTexture::get_seamless() {
	return seamless;
}

void NoiseTexture::set_as_normalmap(bool p_as_normalmap) {
	if (p_as_normalmap == as_normalmap) return;
	as_normalmap = p_as_normalmap;
	_queue_update();
	_change_notify();
}

bool NoiseTexture::is_normalmap() {
	return as_normalmap;
}

void NoiseTexture::set_bump_strength(float p_bump_strength) {

	if (p_bump_strength == bump_strength) return;
	bump_strength = p_bump_strength;
	if (as_normalmap)
		_queue_update();
}

float NoiseTexture::get_bump_strength() {

	return bump_strength;
}

int NoiseTexture::get_width() const {

	return size.x;
}

int NoiseTexture::get_height() const {

	return size.y;
}

void NoiseTexture::set_flags(uint32_t p_flags) {
	flags = p_flags;
	VS::get_singleton()->texture_set_flags(texture, flags);
}

uint32_t NoiseTexture::get_flags() const {
	return flags;
}

Ref<Image> NoiseTexture::get_data() const {

	return data;
}
<commit_msg>NoiseTexture: Fix regression in starting thread<commit_after>/*************************************************************************/
/*  noise_texture.cpp                                                    */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "noise_texture.h"

#include "core/core_string_names.h"

NoiseTexture::NoiseTexture() {
	update_queued = false;
	regen_queued = false;
	first_time = true;

	size = Vector2i(512, 512);
	seamless = false;
	as_normalmap = false;
	bump_strength = 8.0;
	flags = FLAGS_DEFAULT;

	noise = Ref<OpenSimplexNoise>();

	texture = VS::get_singleton()->texture_create();

	_queue_update();
}

NoiseTexture::~NoiseTexture() {
	VS::get_singleton()->free(texture);
	noise_thread.wait_to_finish();
}

void NoiseTexture::_bind_methods() {

	ClassDB::bind_method(D_METHOD("set_width", "width"), &NoiseTexture::set_width);
	ClassDB::bind_method(D_METHOD("set_height", "height"), &NoiseTexture::set_height);

	ClassDB::bind_method(D_METHOD("set_noise", "noise"), &NoiseTexture::set_noise);
	ClassDB::bind_method(D_METHOD("get_noise"), &NoiseTexture::get_noise);

	ClassDB::bind_method(D_METHOD("set_seamless", "seamless"), &NoiseTexture::set_seamless);
	ClassDB::bind_method(D_METHOD("get_seamless"), &NoiseTexture::get_seamless);

	ClassDB::bind_method(D_METHOD("set_as_normalmap", "as_normalmap"), &NoiseTexture::set_as_normalmap);
	ClassDB::bind_method(D_METHOD("is_normalmap"), &NoiseTexture::is_normalmap);

	ClassDB::bind_method(D_METHOD("set_bump_strength", "bump_strength"), &NoiseTexture::set_bump_strength);
	ClassDB::bind_method(D_METHOD("get_bump_strength"), &NoiseTexture::get_bump_strength);

	ClassDB::bind_method(D_METHOD("_update_texture"), &NoiseTexture::_update_texture);
	ClassDB::bind_method(D_METHOD("_queue_update"), &NoiseTexture::_queue_update);
	ClassDB::bind_method(D_METHOD("_generate_texture"), &NoiseTexture::_generate_texture);
	ClassDB::bind_method(D_METHOD("_thread_done", "image"), &NoiseTexture::_thread_done);

	ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,2048,1,or_greater"), "set_width", "get_width");
	ADD_PROPERTY(PropertyInfo(Variant::INT, "height", PROPERTY_HINT_RANGE, "1,2048,1,or_greater"), "set_height", "get_height");
	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "seamless"), "set_seamless", "get_seamless");
	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "as_normalmap"), "set_as_normalmap", "is_normalmap");
	ADD_PROPERTY(PropertyInfo(Variant::REAL, "bump_strength", PROPERTY_HINT_RANGE, "0,32,0.1,or_greater"), "set_bump_strength", "get_bump_strength");
	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "OpenSimplexNoise"), "set_noise", "get_noise");
}

void NoiseTexture::_validate_property(PropertyInfo &property) const {

	if (property.name == "bump_strength") {
		if (!as_normalmap) {
			property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
		}
	}
}

void NoiseTexture::_set_texture_data(const Ref<Image> &p_image) {
	data = p_image;
	if (data.is_valid()) {
		VS::get_singleton()->texture_allocate(texture, size.x, size.y, 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, flags);
		VS::get_singleton()->texture_set_data(texture, p_image);
	}
	emit_changed();
}

void NoiseTexture::_thread_done(const Ref<Image> &p_image) {

	_set_texture_data(p_image);
	noise_thread.wait_to_finish();
	if (regen_queued) {
		noise_thread.start(_thread_function, this);
		regen_queued = false;
	}
}

void NoiseTexture::_thread_function(void *p_ud) {
	NoiseTexture *tex = (NoiseTexture *)p_ud;
	tex->call_deferred("_thread_done", tex->_generate_texture());
}

void NoiseTexture::_queue_update() {

	if (update_queued)
		return;

	update_queued = true;
	call_deferred("_update_texture");
}

Ref<Image> NoiseTexture::_generate_texture() {

	// Prevent memdelete due to unref() on other thread.
	Ref<OpenSimplexNoise> ref_noise = noise;

	if (ref_noise.is_null()) {
		return Ref<Image>();
	}

	Ref<Image> image;

	if (seamless) {
		image = ref_noise->get_seamless_image(size.x);
	} else {
		image = ref_noise->get_image(size.x, size.y);
	}

	if (as_normalmap) {
		image->bumpmap_to_normalmap(bump_strength);
	}

	return image;
}

void NoiseTexture::_update_texture() {
	bool use_thread = true;
	if (first_time) {
		use_thread = false;
		first_time = false;
	}
#ifdef NO_THREADS
	use_thread = false;
#endif
	if (use_thread) {

		if (!noise_thread.is_started()) {
			noise_thread.start(_thread_function, this);
			regen_queued = false;
		} else {
			regen_queued = true;
		}

	} else {
		Ref<Image> image = _generate_texture();
		_set_texture_data(image);
	}
	update_queued = false;
}

void NoiseTexture::set_noise(Ref<OpenSimplexNoise> p_noise) {
	if (p_noise == noise)
		return;
	if (noise.is_valid()) {
		noise->disconnect(CoreStringNames::get_singleton()->changed, this, "_queue_update");
	}
	noise = p_noise;
	if (noise.is_valid()) {
		noise->connect(CoreStringNames::get_singleton()->changed, this, "_queue_update");
	}
	_queue_update();
}

Ref<OpenSimplexNoise> NoiseTexture::get_noise() {
	return noise;
}

void NoiseTexture::set_width(int p_width) {
	if (p_width == size.x) return;
	size.x = p_width;
	_queue_update();
}

void NoiseTexture::set_height(int p_height) {
	if (p_height == size.y) return;
	size.y = p_height;
	_queue_update();
}

void NoiseTexture::set_seamless(bool p_seamless) {
	if (p_seamless == seamless) return;
	seamless = p_seamless;
	_queue_update();
}

bool NoiseTexture::get_seamless() {
	return seamless;
}

void NoiseTexture::set_as_normalmap(bool p_as_normalmap) {
	if (p_as_normalmap == as_normalmap) return;
	as_normalmap = p_as_normalmap;
	_queue_update();
	_change_notify();
}

bool NoiseTexture::is_normalmap() {
	return as_normalmap;
}

void NoiseTexture::set_bump_strength(float p_bump_strength) {

	if (p_bump_strength == bump_strength) return;
	bump_strength = p_bump_strength;
	if (as_normalmap)
		_queue_update();
}

float NoiseTexture::get_bump_strength() {

	return bump_strength;
}

int NoiseTexture::get_width() const {

	return size.x;
}

int NoiseTexture::get_height() const {

	return size.y;
}

void NoiseTexture::set_flags(uint32_t p_flags) {
	flags = p_flags;
	VS::get_singleton()->texture_set_flags(texture, flags);
}

uint32_t NoiseTexture::get_flags() const {
	return flags;
}

Ref<Image> NoiseTexture::get_data() const {

	return data;
}
<|endoftext|>


<commit_before>//==================================================================================================================|
// Created 2015.02.02 by Daniel L. Watkins
//
// Copyright (C) 2015 Valpineware
// This file is licensed under the MIT License.
//==================================================================================================================|

#include "ControlStructure.h"

namespace vc { namespace graph
{
	QStringList registeredNames()
	{
		QStringList list;
		#define A(what) list.append(what)

		A("for");
		A("while");
		A("if");
		A("elseif");
		A("else");

		#undef A
		return list;
	} QStringList gRegisteredNames = registeredNames();

	QRegExp registeredNamesRegExp()
	{
		QString buffer;
		buffer.reserve(gRegisteredNames.count() * 4);

		for (QString s : gRegisteredNames)
		{
			buffer.append(s + "|");
		}

		if (buffer.at(buffer.count()-1) == "|")
			buffer.chop(1);

		return QRegExp(buffer);
	} QRegExp gRegisteredNamesRegExp = registeredNamesRegExp();	//TODO it would be cool if we could initialize this variable with a block thing to avoid name pollution. Lamda?

	void preProcessControlStructureSignature(QString &signature, QStringList &list)
	{
		signature.replace("(", " ( ");
		signature.replace(")", " ) ");

		//3) Split into a list deliminated by " "
		list = signature.split(QRegExp("\\s"));

		//remove all remaining whitespace strings
		QMutableStringListIterator mi(list);
		while (mi.hasNext())
		{
			if (QRegExp("\\s*").exactMatch(mi.next()))
				mi.remove();
		}
	}

	ControlStructure* ControlStructure::createFromVerbatimSignature(const QString signature)
	{
		QStringList list;
		QString filtered = signature;
		preProcessControlStructureSignature(filtered, list);
		QStringListIterator i(list);

		ControlStructure *cs = new ControlStructure(signature);

		//get the name
		if (i.hasNext())
		{
			const QString &cmp = i.next();

			if (gRegisteredNamesRegExp.exactMatch(cmp))
				cs->setName(cmp);
			else
				return nullptr;
		}
		else
			return nullptr;

		//this is sort of a hack, but what else should be done?
		if (cs->name() == "else")
			return cs;

		//there should be an opening parenthesis next and a closing one at the very end
		if (!i.hasNext() || i.next() != "(" || list.last() != ")")
			return nullptr;

		//now just copy everything between the two () and set that as the expression
		int openIndex = signature.indexOf("(")+1;
		int closeIndex = signature.lastIndexOf(")");
		cs->setExpression(signature.mid(openIndex, closeIndex-openIndex));

		return cs;
	}
}}<commit_msg>Cleanup<commit_after>//==================================================================================================================|
// Created 2015.02.02 by Daniel L. Watkins
//
// Copyright (C) 2015 Valpineware
// This file is licensed under the MIT License.
//==================================================================================================================|

#include "ControlStructure.h"

namespace vc { namespace graph
{
	struct Type
	{
		//blank indicates no keyword associated and should not be parsed
		QString startKeyword = "";
		bool needsStartExp = false;
	};

	QList<Type> registeredNames()
	{
		QList<Type> list;

		#define A(start, need) {Type t; t.startKeyword = start; t.needsStartExp = need; list.append( t );}

		A("for", true)
		A("while", true)
		A("if", true)
		A("elseif", true)
		A("else", false)

		#undef A
		return list;
	} QList<Type> gRegisteredNames = registeredNames();

	QRegExp registeredNamesRegExp()
	{
		QString buffer;
		buffer.reserve(gRegisteredNames.count() * 4);

		for (Type t : gRegisteredNames)
		{
			buffer.append(t.startKeyword + "|");
		}

		if (buffer.at(buffer.count()-1) == "|")
			buffer.chop(1);

		return QRegExp(buffer);
	} QRegExp gRegisteredNamesRegExp = registeredNamesRegExp();	//TODO it would be cool if we could initialize this variable with a block thing to avoid name pollution. Lamda?

	void preProcessControlStructureSignature(QString &signature, QStringList &list)
	{
		signature.replace("(", " ( ");
		signature.replace(")", " ) ");

		//3) Split into a list deliminated by " "
		list = signature.split(QRegExp("\\s"));

		//remove all remaining whitespace strings
		QMutableStringListIterator mi(list);
		while (mi.hasNext())
		{
			if (QRegExp("\\s*").exactMatch(mi.next()))
				mi.remove();
		}
	}

	ControlStructure* ControlStructure::createFromVerbatimSignature(const QString signature)
	{
		QStringList list;
		QString filtered = signature;
		preProcessControlStructureSignature(filtered, list);
		QStringListIterator i(list);

		ControlStructure *cs = new ControlStructure(signature);

		//get the name
		if (i.hasNext())
		{
			const QString &cmp = i.next();

			if (gRegisteredNamesRegExp.exactMatch(cmp))
				cs->setName(cmp);
			else
				return nullptr;
		}
		else
			return nullptr;

		//what registered type of control structure is this?
		Type type;
		for (Type &t : gRegisteredNames)
		{
			if (t.startKeyword == cs->name())
			{
				type = t;
				break;
			}
		}

		if (!type.needsStartExp)
			return cs;

		//there should be an opening parenthesis next and a closing one at the very end
		if (!i.hasNext() || i.next() != "(" || list.last() != ")")
			return nullptr;

		//now just copy everything between the two () and set that as the expression
		int openIndex = signature.indexOf("(")+1;
		int closeIndex = signature.lastIndexOf(")");
		cs->setExpression(signature.mid(openIndex, closeIndex-openIndex));

		return cs;
	}
}}<|endoftext|>