Compare commits

...
11 changed files with 145 additions and 80 deletions
+60 -10
View File
@@ -42,8 +42,9 @@ GridFunction::GridFunction(Mesh *m, std::istream &input)
// Grid functions are stored on the device
UseDevice(true);
fes = new FiniteElementSpace;
fec_owned = fes->Load(m, input);
owned_fes = std::make_shared<FiniteElementSpace>();
fes = owned_fes.get();
fec.reset(fes->Load(m, input));
skip_comment_lines(input, '#');
istream::int_type next_char = input.peek();
@@ -85,10 +86,11 @@ GridFunction::GridFunction(Mesh *m, GridFunction *gf_array[], int num_pieces)
int vdim, ordering;
fes = gf_array[0]->FESpace();
fec_owned = FiniteElementCollection::New(fes->FEColl()->Name());
fec.reset(FiniteElementCollection::New(fes->FEColl()->Name()));
vdim = fes->GetVDim();
ordering = fes->GetOrdering();
fes = new FiniteElementSpace(m, fec_owned, vdim, ordering);
owned_fes =
std::make_shared<FiniteElementSpace>(m, fec.get(), vdim, ordering);
SetSize(fes->GetVSize());
if (m->NURBSext)
@@ -155,13 +157,61 @@ GridFunction::GridFunction(Mesh *m, GridFunction *gf_array[], int num_pieces)
fes_sequence = fes->GetSequence();
}
GridFunction &GridFunction::operator=(const GridFunction &rhs)
{
if (&rhs != this)
{
Vector::operator=(rhs);
if (fes != rhs.fes)
{
fes = rhs.fes;
owned_fes = rhs.owned_fes;
fec = rhs.fec;
}
else
{
// ensure we don't accidentally delete if rhs doesn't have shared
// ownership
if (!owned_fes)
{
owned_fes = rhs.owned_fes;
}
if (!fec)
{
fec = rhs.fec;
}
}
fes_sequence = rhs.fes_sequence;
}
return *this;
}
void GridFunction::Destroy()
{
if (fec_owned)
owned_fes.reset();
fec.reset();
}
void GridFunction::MakeOwner()
{
if (fec.get() != fes->FEColl())
{
delete fes;
delete fec_owned;
fec_owned = NULL;
fec.reset(const_cast<FiniteElementCollection *>(fes->FEColl()));
}
if (owned_fes.get() != fes)
{
owned_fes.reset(fes);
}
}
void GridFunction::MakeOwner(FiniteElementCollection* fec_)
{
if (fec_)
{
MFEM_VERIFY(fec_ == fes->FEColl(),
"fec_ not associated with fes. If you intended to release "
"ownership, see GridFunction::ShareOwner");
MakeOwner();
}
}
@@ -4486,7 +4536,7 @@ std::unique_ptr<GridFunction> GridFunction::ProlongateToMaxOrder() const
PRefinementTransferOperator P(*fes, *fesMax);
P.Mult(*this, *xMax);
xMax->MakeOwner(fecMax);
xMax->MakeOwner();
return std::unique_ptr<GridFunction>(xMax);
}
@@ -5059,7 +5109,7 @@ GridFunction *Extrude1DGridFunction(Mesh *mesh, Mesh *mesh2d,
// assuming sol is scalar
solfes2d = new FiniteElementSpace(mesh2d, solfec2d);
sol2d = new GridFunction(solfes2d);
sol2d->MakeOwner(solfec2d);
sol2d->MakeOwner();
{
GridFunctionCoefficient csol(sol);
ExtrudeCoefficient c2d(mesh, csol, ny);
+39 -29
View File
@@ -49,16 +49,15 @@ enum class ProjectType { DEFAULT, ELEMENT, GLOBAL_L2, ELEMENT_L2 };
class GridFunction : public Vector
{
protected:
/// FE space on which the grid function lives. Owned if #fec_owned is not NULL.
FiniteElementSpace *fes;
/// FE space on which the grid function lives.
FiniteElementSpace *fes = nullptr;
/** @brief Used when the grid function is read from a file. It can also be
set explicitly, see MakeOwner().
set explicitly, see MakeOwner(). */
std::shared_ptr<FiniteElementCollection> fec;
std::shared_ptr<FiniteElementSpace> owned_fes;
If not NULL, this pointer is owned by the GridFunction. */
FiniteElementCollection *fec_owned;
long fes_sequence; // see FiniteElementSpace::sequence, Mesh::sequence
long fes_sequence = 0; // see FiniteElementSpace::sequence, Mesh::sequence
/** Optional, internal true-dof vector: if the FiniteElementSpace #fes has a
non-trivial (i.e. not NULL) prolongation operator, this Vector may hold
@@ -95,20 +94,26 @@ protected:
void Destroy();
public:
GridFunction() { fes = NULL; fec_owned = NULL; fes_sequence = 0; UseDevice(true); }
GridFunction() { UseDevice(true); }
/// Copy constructor. The internal true-dof vector #t_vec is not copied.
GridFunction(const GridFunction &orig)
: Vector(orig), fes(orig.fes), fec_owned(NULL), fes_sequence(orig.fes_sequence)
: Vector(orig), fes(orig.fes), fec(orig.fec), owned_fes(orig.owned_fes),
fes_sequence(orig.fes_sequence)
{ UseDevice(true); }
GridFunction(GridFunction &&orig) = default;
/// Construct a GridFunction associated with the FiniteElementSpace @a *f.
GridFunction(FiniteElementSpace *f) : Vector(f->GetVSize())
{ fes = f; fec_owned = NULL; fes_sequence = f->GetSequence(); UseDevice(true); }
GridFunction(FiniteElementSpace *f)
: Vector(f->GetVSize()), fes(f), fes_sequence(f->GetSequence())
{ UseDevice(true); }
/// Same as above but specify the memory type
GridFunction(FiniteElementSpace *f, MemoryType mt) : Vector(f->GetVSize(), mt)
{ fes = f; fec_owned = NULL; fes_sequence = f->GetSequence(); UseDevice(true); }
GridFunction(FiniteElementSpace *f, MemoryType mt)
: Vector(f->GetVSize(), mt), fes(f), fes_sequence(f->GetSequence())
{ UseDevice(true); }
/// Construct a GridFunction using previously allocated array @a data.
/** The GridFunction does not assume ownership of @a data which is assumed to
@@ -117,14 +122,15 @@ public:
array can be replaced later using the method SetData().
*/
GridFunction(FiniteElementSpace *f, real_t *data)
: Vector(data, f->GetVSize())
{ fes = f; fec_owned = NULL; fes_sequence = f->GetSequence(); UseDevice(true); }
: Vector(data, f->GetVSize()), fes(f), fes_sequence(f->GetSequence())
{ UseDevice(true); }
/** @brief Construct a GridFunction using previously allocated Vector @a base
starting at the given offset, @a base_offset. */
GridFunction(FiniteElementSpace *f, Vector &base, int base_offset = 0)
: Vector(base, base_offset, f->GetVSize())
{ fes = f; fec_owned = NULL; fes_sequence = f->GetSequence(); UseDevice(true); }
: Vector(base, base_offset, f->GetVSize()), fes(f),
fes_sequence(f->GetSequence())
{ UseDevice(true); }
/// Construct a GridFunction on the given Mesh, using the data from @a input.
/** The content of @a input should be in the format created by the method
@@ -134,21 +140,25 @@ public:
GridFunction(Mesh *m, GridFunction *gf_array[], int num_pieces);
/// Copy assignment. Only the data of the base class Vector is copied.
/** It is assumed that this object and @a rhs use FiniteElementSpace%s that
have the same size.
/// Copy assignment. Temporary data is not copied.
GridFunction &operator=(const GridFunction &rhs);
@note Defining this method overwrites the implicitly defined copy
assignment operator. */
GridFunction &operator=(const GridFunction &rhs)
{ return operator=((const Vector &)rhs); }
GridFunction &operator=(GridFunction &&gf) = default;
/// Make the GridFunction the owner of #fec_owned and #fes.
/** If the new FiniteElementCollection, @a fec_, is NULL, ownership of #fec_owned
and #fes is taken away. */
void MakeOwner(FiniteElementCollection *fec_) { fec_owned = fec_; }
/// Make the GridFunction a shared owner of #fec and #fes.
void MakeOwner();
[[deprecated("Use MakeOwner() instead")]]
void MakeOwner(FiniteElementCollection* fec_);
/// Gets a shared ownership of #owned_fes and #fec if this GridFunction has
/// shared ownership.
void ShareOwner(std::shared_ptr<FiniteElementSpace> &fes_,
std::shared_ptr<FiniteElementCollection> &fec_)
{
fes_ = owned_fes;
fec_ = fec;
}
FiniteElementCollection *OwnFEC() { return fec_owned; }
FiniteElementCollection* OwnFEC() { return fec.get(); }
/// Shortcut for calling FiniteElementSpace::GetVectorDim() on the underlying #fes
int VectorDim() const;
+19 -9
View File
@@ -39,10 +39,13 @@ ParGridFunction::ParGridFunction(ParMesh *pmesh, const GridFunction *gf,
{
const FiniteElementSpace *glob_fes = gf->FESpace();
// duplicate the FiniteElementCollection from 'gf'
fec_owned = FiniteElementCollection::New(glob_fes->FEColl()->Name());
fec.reset(FiniteElementCollection::New(glob_fes->FEColl()->Name()));
// create a local ParFiniteElementSpace from the global one:
fes = pfes = new ParFiniteElementSpace(pmesh, glob_fes, partitioning,
fec_owned);
owned_fes = std::make_shared<ParFiniteElementSpace>(pmesh, glob_fes,
partitioning, fec.get());
fes = owned_fes.get();
pfes = static_cast<ParFiniteElementSpace *>(fes);
SetSize(pfes->GetVSize());
if (partitioning)
@@ -76,10 +79,17 @@ ParGridFunction::ParGridFunction(ParMesh *pmesh, std::istream &input)
: GridFunction(pmesh, input)
{
// Convert the FiniteElementSpace, fes, to a ParFiniteElementSpace:
pfes = new ParFiniteElementSpace(pmesh, fec_owned, fes->GetVDim(),
fes->GetOrdering());
delete fes;
fes = pfes;
owned_fes = std::make_shared<ParFiniteElementSpace>(
pmesh, fec.get(), fes->GetVDim(), fes->GetOrdering());
fes = owned_fes.get();
pfes = static_cast<ParFiniteElementSpace*>(fes);
}
ParGridFunction& ParGridFunction::operator=(const ParGridFunction &rhs)
{
operator=((const GridFunction &)rhs);
pfes = rhs.pfes;
return *this;
}
void ParGridFunction::Update()
@@ -1206,7 +1216,7 @@ GridFunction ParGridFunction::GetSerialGridFunction(int save_rank,
pfes->GetVDim(),
pfes->GetOrdering());
GridFunction serial_gf = GetSerialGridFunction(save_rank, *serial_fes);
serial_gf.MakeOwner(serial_fec); // Also assumes ownership of serial_fes
serial_gf.MakeOwner(); // Also assumes ownership of serial_fes
return serial_gf;
}
@@ -1446,7 +1456,7 @@ std::unique_ptr<ParGridFunction> ParGridFunction::ProlongateToMaxOrder() const
PRefinementTransferOperator P(*pfes, *pfesMax);
P.Mult(*this, *xMax);
xMax->MakeOwner(fecMax);
xMax->MakeOwner();
return std::unique_ptr<ParGridFunction>(xMax);
}
+4 -8
View File
@@ -70,6 +70,8 @@ public:
ParGridFunction(const ParGridFunction &orig)
: GridFunction(orig), pfes(orig.pfes) { }
ParGridFunction(ParGridFunction &&orig) = default;
ParGridFunction(ParFiniteElementSpace *pf) : GridFunction(pf), pfes(pf) { }
/// Same as above but specify the device memory type
@@ -114,14 +116,8 @@ public:
constructed. The new ParGridFunction assumes ownership of both. */
ParGridFunction(ParMesh *pmesh, std::istream &input);
/// Copy assignment. Only the data of the base class Vector is copied.
/** It is assumed that this object and @a rhs use ParFiniteElementSpace%s
that have the same size.
@note Defining this method overwrites the implicitly defined copy
assignment operator. */
ParGridFunction &operator=(const ParGridFunction &rhs)
{ return operator=((const Vector &)rhs); }
ParGridFunction &operator=(const ParGridFunction &rhs);
ParGridFunction &operator=(ParGridFunction &&orig) = default;
/// Assign constant values to the ParGridFunction data.
ParGridFunction &operator=(real_t value)
+2 -2
View File
@@ -3938,7 +3938,7 @@ void TMOP_Integrator::EnableSurfaceFitting(const ParGridFunction &s0,
dim);
// Initial gradients.
surf_fit_grad = new GridFunction(fes_grad);
surf_fit_grad->MakeOwner(fec_grad);
surf_fit_grad->MakeOwner();
for (int d = 0; d < dim; d++)
{
ParGridFunction surf_fit_grad_comp(fes, surf_fit_grad->GetData()+d*s0.Size());
@@ -3956,7 +3956,7 @@ void TMOP_Integrator::EnableSurfaceFitting(const ParGridFunction &s0,
dim*dim);
// Initial Hessians.
surf_fit_hess = new GridFunction(fes_hess);
surf_fit_hess->MakeOwner(fec_hess);
surf_fit_hess->MakeOwner();
int id = 0;
for (int d = 0; d < dim; d++)
{
+7 -6
View File
@@ -4571,8 +4571,9 @@ Mesh::Mesh(const Mesh &mesh, bool copy_nodes)
FiniteElementSpace *fes_copy =
new FiniteElementSpace(*fes, this, fec_copy);
Nodes = new GridFunction(fes_copy);
Nodes->MakeOwner(fec_copy);
*Nodes = *mesh.Nodes;
Nodes->MakeOwner();
// only copy underlying Vector data
*Nodes = static_cast<Vector &>(*mesh.Nodes);
own_nodes = 1;
}
else
@@ -4796,7 +4797,7 @@ Mesh::Mesh(const NURBSExtension& ext)
FiniteElementSpace *fes = new FiniteElementSpace(this, fec, vdim,
Ordering::byVDIM);
Nodes = new GridFunction(fes);
Nodes->MakeOwner(fec);
Nodes->MakeOwner();
NURBSext->SetCoordsFromPatches(*Nodes, vdim);
own_nodes = 1;
spaceDim = Nodes->VectorDim();
@@ -7069,7 +7070,7 @@ void Mesh::SetCurvature(int order, bool discont, int space_dim, int ordering)
const int old_space_dim = spaceDim;
SetNodalFESpace(nfes);
Nodes->MakeOwner(nfec);
Nodes->MakeOwner();
if (spaceDim != old_space_dim)
{
@@ -15499,7 +15500,7 @@ Mesh *Extrude1D(Mesh *mesh, const int ny, const real_t sy, const bool closed)
fes2d = new FiniteElementSpace(mesh2d, fec2d, 2);
mesh2d->SetNodalFESpace(fes2d);
GridFunction *nodes2d = mesh2d->GetNodes();
nodes2d->MakeOwner(fec2d);
nodes2d->MakeOwner();
NodeExtrudeCoefficient ecoeff(2, ny, sy);
Vector lnodes;
@@ -15725,7 +15726,7 @@ Mesh *Extrude2D(Mesh *mesh, const int nz, const real_t sz)
fes3d = new FiniteElementSpace(mesh3d, fec3d, 3);
mesh3d->SetNodalFESpace(fes3d);
GridFunction *nodes3d = mesh3d->GetNodes();
nodes3d->MakeOwner(fec3d);
nodes3d->MakeOwner();
NodeExtrudeCoefficient ecoeff(3, nz, sz);
Vector lnodes;
+5 -5
View File
@@ -557,7 +557,7 @@ void Mesh::CreateVTKMesh(const Vector &points, const Array<int> &cell_data,
fec = new QuadraticFECollection;
fes = new FiniteElementSpace(this, fec, spaceDim);
Nodes = new GridFunction(fes);
Nodes->MakeOwner(fec); // Nodes will destroy 'fec' and 'fes'
Nodes->MakeOwner(); // Nodes will destroy 'fec' and 'fes'
own_nodes = 1;
// Map vtk points to edge/face/element dofs
@@ -607,7 +607,7 @@ void Mesh::CreateVTKMesh(const Vector &points, const Array<int> &cell_data,
fec = new H1_FECollection(order,Dim,BasisType::ClosedUniform);
fes = new FiniteElementSpace(this, fec, spaceDim);
Nodes = new GridFunction(fes);
Nodes->MakeOwner(fec); // Nodes will destroy 'fec' and 'fes'
Nodes->MakeOwner(); // Nodes will destroy 'fec' and 'fes'
own_nodes = 1;
Array<int> dofs;
@@ -1332,7 +1332,7 @@ void Mesh::ReadNURBSMesh(std::istream &input, int &curved, int &read_gf,
FiniteElementSpace *fes = new FiniteElementSpace(this, fec, vdim,
Ordering::byVDIM);
Nodes = new GridFunction(fes);
Nodes->MakeOwner(fec);
Nodes->MakeOwner();
NURBSext->SetCoordsFromPatches(*Nodes, vdim);
own_nodes = 1;
read_gf = 0;
@@ -2525,7 +2525,7 @@ void Mesh::ReadGmshMesh(std::istream &input, int &curved, int &read_gf)
nfes = new FiniteElementSpace(this, nfec, spaceDim,
Ordering::byVDIM);
Nodes_gf.SetSpace(nfes);
Nodes_gf.MakeOwner(nfec);
Nodes_gf.MakeOwner();
int o = 0;
int el_order = 1;
@@ -4098,7 +4098,7 @@ static void FinalizeCubitSecondOrderMesh(Mesh &mesh,
FiniteElementSpace *fes = new FiniteElementSpace(&mesh, fec, Dim,
Ordering::byVDIM);
GridFunction *Nodes = new GridFunction(fes);
Nodes->MakeOwner(fec); // Nodes will destroy 'fec' and 'fes'
Nodes->MakeOwner(); // Nodes will destroy 'fec' and 'fes'
mesh.SetNodalGridFunction(Nodes, true);
for (int block_id : unique_block_ids)
+5 -7
View File
@@ -86,7 +86,7 @@ ParMesh::ParMesh(const ParMesh &pmesh, bool copy_nodes)
ParFiniteElementSpace *pfes_copy =
new ParFiniteElementSpace(*fes, *this, fec_copy);
Nodes = new ParGridFunction(pfes_copy);
Nodes->MakeOwner(fec_copy);
Nodes->MakeOwner();
*Nodes = *pmesh.Nodes;
own_nodes = 1;
}
@@ -286,7 +286,7 @@ ParMesh::ParMesh(MPI_Comm comm, Mesh &mesh, const int *partitioning_,
new ParFiniteElementSpace(this, nfec, glob_fes->GetVDim(),
glob_fes->GetOrdering());
Nodes = new ParGridFunction(pfes);
Nodes->MakeOwner(nfec); // Nodes will own nfec and pfes
Nodes->MakeOwner(); // Nodes will own nfec and pfes
}
own_nodes = 1;
@@ -2032,7 +2032,7 @@ void ParMesh::SetCurvature(int order, bool discont, int space_dim, int ordering)
auto pnodes = new ParGridFunction(nfes);
GetNodes(*pnodes);
NewNodes(*pnodes, true);
Nodes->MakeOwner(nfec);
Nodes->MakeOwner();
}
void ParMesh::SetNodalFESpace(FiniteElementSpace *nfes)
@@ -2067,9 +2067,7 @@ void ParMesh::EnsureParNodes()
*new_nodes = *Nodes;
if (Nodes->OwnFEC())
{
new_nodes->MakeOwner(Nodes->OwnFEC());
Nodes->MakeOwner(NULL); // takes away ownership of 'fec' and 'fes'
delete Nodes->FESpace();
new_nodes->MakeOwner();
}
delete Nodes;
Nodes = new_nodes;
@@ -5523,7 +5521,7 @@ Mesh ParMesh::GetSerialMesh(int save_rank) const
spaceDim,
GetNodalFESpace()->GetOrdering());
serialmesh.SetNodalFESpace(fespace_serial);
serialmesh.GetNodes()->MakeOwner(fec_serial);
serialmesh.GetNodes()->MakeOwner();
// The serial mesh owns its Nodes and they, in turn, own fec_serial and
// fespace_serial.
}
+1 -1
View File
@@ -224,7 +224,7 @@ Mesh *skin_mesh(Mesh *mesh)
FiniteElementSpace *fes_copy =
new FiniteElementSpace(*fes, bmesh, fec_copy);
GridFunction *bdr_nodes = new GridFunction(fes_copy);
bdr_nodes->MakeOwner(fec_copy);
bdr_nodes->MakeOwner();
bmesh->NewNodes(*bdr_nodes, true);
+1 -1
View File
@@ -128,7 +128,7 @@ int main (int argc, char *argv[])
ParFiniteElementSpace *fes = new ParFiniteElementSpace(&pmesh, fec,
vdim, ordering);
pfunc_proj = new ParGridFunction(fes);
pfunc_proj->MakeOwner(fec);
pfunc_proj->MakeOwner();
pfunc_proj->ProjectGridFunction(pfunc);
if (Mpi::Root())
{
+2 -2
View File
@@ -863,7 +863,7 @@ GridFunction *TestRandomPRefinement_serial(Mesh & mesh)
fespace->Update(false);
auto *sol = new GridFunction(fespace);
sol->MakeOwner(fec);
sol->MakeOwner();
*sol = 0.0; // Essential DOF value
TestSolveSerial1(mesh, *sol);
return sol;
@@ -886,7 +886,7 @@ ParGridFunction *TestRandomPRefinement_parallel(Mesh & mesh)
pfes->Update(false);
auto *sol = new ParGridFunction(pfes);
sol->MakeOwner(pfec);
sol->MakeOwner();
*sol = 0.0; // Essential DOF value
TestSolveParallel1(*pmsh, *sol);
return sol;