Skip to content

Commit db05ce9

Browse files
authored
Merge pull request #3336 from jwpeterson/dof_object_unique_ptr
DofObject::old_dof_object can be a unique_ptr
2 parents 7ba0889 + 6e849f6 commit db05ce9

6 files changed

Lines changed: 124 additions & 96 deletions

File tree

include/base/dof_object.h

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <cstddef>
3333
#include <cstring>
3434
#include <vector>
35+
#include <memory>
3536

3637
namespace libMesh
3738
{
@@ -64,21 +65,53 @@ class DofObject : public ReferenceCountedObject<DofObject>
6465
*/
6566
DofObject ();
6667

68+
public:
69+
6770
/**
68-
* Destructor. Protected so that you can't destroy one of these
69-
* except as a part of a Node or Elem.
71+
* Destructor.
7072
*/
71-
~DofObject ();
72-
73-
public:
73+
~DofObject () = default;
7474

7575
#ifdef LIBMESH_ENABLE_AMR
7676

7777
/**
7878
* This object on the last mesh. Useful for projecting
7979
* solutions from one mesh to another.
80+
*
81+
* Public access to old_dof_object is now officially deprecated and will
82+
* be removed in future libMesh versions. Use the \p get_old_dof_object()
83+
* accessor instead.
8084
*/
81-
DofObject * old_dof_object;
85+
#ifndef LIBMESH_ENABLE_DEPRECATED
86+
protected:
87+
#endif
88+
std::unique_ptr<DofObject> old_dof_object;
89+
90+
public:
91+
/**
92+
* Pointer accessor for previously public old_dof_object. If you
93+
* want to assert that the old_dof_object pointer is valid as well,
94+
* consider using the get_old_dof_object_ref() accessor instead.
95+
*/
96+
DofObject * get_old_dof_object() { return old_dof_object.get(); }
97+
const DofObject * get_old_dof_object() const { return old_dof_object.get(); }
98+
99+
/**
100+
* As above, but do not use in situations where the old_dof_object
101+
* may be nullptr, since this function asserts that the
102+
* old_dof_object is valid before returning a reference to it.
103+
*/
104+
DofObject & get_old_dof_object_ref()
105+
{
106+
libmesh_assert(old_dof_object);
107+
return *old_dof_object;
108+
}
109+
110+
const DofObject & get_old_dof_object_ref() const
111+
{
112+
libmesh_assert(old_dof_object);
113+
return *old_dof_object;
114+
}
82115

83116
/**
84117
* Sets the \p old_dof_object to nullptr
@@ -501,6 +534,17 @@ class DofObject : public ReferenceCountedObject<DofObject>
501534
*/
502535
DofObject (const DofObject &);
503536

537+
/**
538+
* Convenient factory function that calls either the (deep) copy
539+
* constructor or the default constructor depending on the input
540+
* arg. Like the copy constructor, this function is also private. We
541+
* can't use std::make_unique to construct a DofObject since the
542+
* copy constructor is private, but we can at least encapsulate the
543+
* code which calls "new" directly.
544+
*/
545+
std::unique_ptr<DofObject>
546+
construct(const DofObject * other = nullptr);
547+
504548
/**
505549
* Deep-copying assignment operator
506550
*/
@@ -676,9 +720,6 @@ class DofObject : public ReferenceCountedObject<DofObject>
676720
// Inline functions
677721
inline
678722
DofObject::DofObject () :
679-
#ifdef LIBMESH_ENABLE_AMR
680-
old_dof_object(nullptr),
681-
#endif
682723
#ifdef LIBMESH_ENABLE_UNIQUE_ID
683724
_unique_id (invalid_unique_id),
684725
#endif
@@ -690,16 +731,13 @@ DofObject::DofObject () :
690731

691732

692733

693-
694-
695734
inline
696-
DofObject::~DofObject ()
735+
std::unique_ptr<DofObject>
736+
DofObject::construct(const DofObject * other)
697737
{
698-
// Free all memory.
699-
#ifdef LIBMESH_ENABLE_AMR
700-
this->clear_old_dof_object ();
701-
#endif
702-
this->clear_dofs ();
738+
return other
739+
? std::unique_ptr<DofObject>(new DofObject(*other))
740+
: std::unique_ptr<DofObject>(new DofObject());
703741
}
704742

705743

include/systems/generic_projector.h

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,7 @@ class OldSolutionBase
609609
}
610610
else
611611
{
612-
if (!elem.old_dof_object)
612+
if (!elem.get_old_dof_object())
613613
{
614614
libmesh_error();
615615
}
@@ -659,7 +659,7 @@ class OldSolutionBase
659659
}
660660
else
661661
{
662-
if (!elem.old_dof_object)
662+
if (!elem.get_old_dof_object())
663663
return false;
664664

665665
old_context.pre_fe_reinit(sys, &elem);
@@ -795,12 +795,13 @@ class OldSolutionValue : public OldSolutionBase<Output, point_output>
795795

796796
// Be sure to handle cases where the variable wasn't defined on
797797
// this node (e.g. due to changing subdomain support)
798-
if (n.old_dof_object &&
799-
n.old_dof_object->n_vars(this->sys.number()) &&
800-
n.old_dof_object->n_comp(this->sys.number(), var))
798+
const DofObject * old_dof_object = n.get_old_dof_object();
799+
if (old_dof_object &&
800+
old_dof_object->n_vars(this->sys.number()) &&
801+
old_dof_object->n_comp(this->sys.number(), var))
801802
{
802803
const dof_id_type first_old_id =
803-
n.old_dof_object->dof_number(this->sys.number(), var, dim);
804+
old_dof_object->dof_number(this->sys.number(), var, dim);
804805
std::vector<dof_id_type> old_ids(n_mixed);
805806
std::iota(old_ids.begin(), old_ids.end(), first_old_id);
806807
old_solution.get(old_ids, derivs);
@@ -887,24 +888,23 @@ class OldSolutionValue : public OldSolutionBase<Output, point_output>
887888
// zero.
888889
if (nc != 0)
889890
{
890-
const DofObject *old_dof_object = old_elem.old_dof_object;
891-
libmesh_assert(old_dof_object);
891+
const DofObject & old_dof_object = old_elem.get_old_dof_object_ref();
892892
libmesh_assert_greater(elem.n_systems(), sys_num);
893893

894894
const std::pair<unsigned int, unsigned int>
895895
vg_and_offset = elem.var_to_vg_and_offset(sys_num,var_num);
896896
const unsigned int vg = vg_and_offset.first;
897897
const unsigned int vig = vg_and_offset.second;
898898

899-
unsigned int n_comp = old_dof_object->n_comp_group(sys_num,vg);
899+
unsigned int n_comp = old_dof_object.n_comp_group(sys_num,vg);
900900
n_comp = std::min(n_comp, nc);
901901

902902
std::vector<dof_id_type> old_dof_indices(n_comp);
903903

904904
for (unsigned int i=0; i != n_comp; ++i)
905905
{
906906
const dof_id_type d_old =
907-
old_dof_object->dof_number(sys_num, vg, vig, i, n_comp);
907+
old_dof_object.dof_number(sys_num, vg, vig, i, n_comp);
908908
const dof_id_type d_new =
909909
elem.dof_number(sys_num, vg, vig, i, n_comp);
910910
libmesh_assert_not_equal_to (d_old, DofObject::invalid_id);
@@ -1032,15 +1032,16 @@ eval_at_node(const FEMContext & c,
10321032

10331033
const Elem::RefinementState flag = c.get_elem().refinement_flag();
10341034

1035-
if (n.old_dof_object &&
1035+
const DofObject * old_dof_object = n.get_old_dof_object();
1036+
if (old_dof_object &&
10361037
(!extra_hanging_dofs ||
10371038
flag == Elem::JUST_COARSENED ||
10381039
flag == Elem::DO_NOTHING) &&
1039-
n.old_dof_object->n_vars(sys.number()) &&
1040-
n.old_dof_object->n_comp(sys.number(), var))
1040+
old_dof_object->n_vars(sys.number()) &&
1041+
old_dof_object->n_comp(sys.number(), var))
10411042
{
10421043
const dof_id_type old_id =
1043-
n.old_dof_object->dof_number(sys.number(), var, 0);
1044+
old_dof_object->dof_number(sys.number(), var, 0);
10441045
return old_solution(old_id);
10451046
}
10461047

@@ -1082,19 +1083,20 @@ eval_at_node(const FEMContext & c,
10821083

10831084
const Elem::RefinementState flag = elem.refinement_flag();
10841085

1085-
if (n.old_dof_object &&
1086+
const DofObject * old_dof_object = n.get_old_dof_object();
1087+
if (old_dof_object &&
10861088
(!extra_hanging_dofs ||
10871089
flag == Elem::JUST_COARSENED ||
10881090
flag == Elem::DO_NOTHING) &&
1089-
n.old_dof_object->n_vars(sys.number()) &&
1090-
n.old_dof_object->n_comp(sys.number(), var))
1091+
old_dof_object->n_vars(sys.number()) &&
1092+
old_dof_object->n_comp(sys.number(), var))
10911093
{
10921094
Gradient return_val;
10931095

10941096
for (unsigned int dim = 0; dim < elem.dim(); ++dim)
10951097
{
10961098
const dof_id_type old_id =
1097-
n.old_dof_object->dof_number(sys.number(), var, dim);
1099+
old_dof_object->dof_number(sys.number(), var, dim);
10981100
return_val(dim) = old_solution(old_id);
10991101
}
11001102

@@ -1139,18 +1141,19 @@ eval_at_node(const FEMContext & c,
11391141

11401142
const Elem::RefinementState flag = c.get_elem().refinement_flag();
11411143

1142-
if (n.old_dof_object &&
1144+
const DofObject * old_dof_object = n.get_old_dof_object();
1145+
if (old_dof_object &&
11431146
(!extra_hanging_dofs ||
11441147
flag == Elem::JUST_COARSENED ||
11451148
flag == Elem::DO_NOTHING) &&
1146-
n.old_dof_object->n_vars(sys.number()) &&
1147-
n.old_dof_object->n_comp(sys.number(), var))
1149+
old_dof_object->n_vars(sys.number()) &&
1150+
old_dof_object->n_comp(sys.number(), var))
11481151
{
11491152
Gradient g;
11501153
for (unsigned int d = 0; d != elem_dim; ++d)
11511154
{
11521155
const dof_id_type old_id =
1153-
n.old_dof_object->dof_number(sys.number(), var, d+1);
1156+
old_dof_object->dof_number(sys.number(), var, d+1);
11541157
g(d) = old_solution(old_id);
11551158
}
11561159
return g;
@@ -1517,7 +1520,8 @@ void GenericProjector<FFunctor, GFunctor, FValue, ProjectionAction>::SortAndCopy
15171520
// wasn't just refined or just coarsened into activity, then
15181521
// it must be newly added, so the user is responsible for
15191522
// setting the new dofs on it during a grid projection.
1520-
if (!elem->old_dof_object &&
1523+
const DofObject * old_dof_object = elem->get_old_dof_object();
1524+
if (!old_dof_object &&
15211525
elem->refinement_flag() != Elem::JUST_REFINED &&
15221526
elem->refinement_flag() != Elem::JUST_COARSENED)
15231527
continue;

src/base/dof_map.C

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -546,13 +546,13 @@ void DofMap::reinit(MeshBase & mesh)
546546
for (auto & node : mesh.node_ptr_range())
547547
{
548548
node->clear_old_dof_object();
549-
libmesh_assert (!node->old_dof_object);
549+
libmesh_assert (!node->get_old_dof_object());
550550
}
551551

552552
for (auto & elem : mesh.element_ptr_range())
553553
{
554554
elem->clear_old_dof_object();
555-
libmesh_assert (!elem->old_dof_object);
555+
libmesh_assert (!elem->get_old_dof_object());
556556
}
557557

558558

@@ -567,11 +567,11 @@ void DofMap::reinit(MeshBase & mesh)
567567
continue;
568568

569569
for (Node & node : elem->node_ref_range())
570-
if (node.old_dof_object == nullptr)
570+
if (node.get_old_dof_object() == nullptr)
571571
if (node.has_dofs(sys_num))
572572
node.set_old_dof_object();
573573

574-
libmesh_assert (!elem->old_dof_object);
574+
libmesh_assert (!elem->get_old_dof_object());
575575

576576
if (elem->has_dofs(sys_num))
577577
elem->set_old_dof_object();
@@ -2260,9 +2260,8 @@ void DofMap::old_dof_indices (const Elem & elem,
22602260
std::vector<dof_id_type> & di,
22612261
const unsigned int vn) const
22622262
{
2263-
const DofObject * old_obj = elem.node_ref(n).old_dof_object;
2264-
libmesh_assert(old_obj);
2265-
this->_node_dof_indices(elem, n, *old_obj, di, vn);
2263+
const DofObject & old_obj = elem.node_ref(n).get_old_dof_object_ref();
2264+
this->_node_dof_indices(elem, n, old_obj, di, vn);
22662265
}
22672266

22682267
#endif // LIBMESH_ENABLE_AMR
@@ -2609,7 +2608,7 @@ void DofMap::old_dof_indices (const Elem * const elem,
26092608
// then we should have old dof indices too.
26102609
libmesh_assert(!elem->has_dofs(sys_num) ||
26112610
elem->p_refinement_flag() == Elem::JUST_REFINED ||
2612-
elem->old_dof_object);
2611+
elem->get_old_dof_object());
26132612

26142613
// Clear the DOF indices vector.
26152614
di.clear();
@@ -2687,8 +2686,7 @@ void DofMap::old_dof_indices (const Elem * const elem,
26872686
for (unsigned int n=0; n<n_nodes; n++)
26882687
{
26892688
const Node * node = nodes_ptr[n];
2690-
const DofObject * old_dof_obj = node->old_dof_object;
2691-
libmesh_assert(old_dof_obj);
2689+
const DofObject & old_dof_obj = node->get_old_dof_object_ref();
26922690

26932691
// There is a potential problem with h refinement. Imagine a
26942692
// quad9 that has a linear FE on it. Then, on the hanging side,
@@ -2701,7 +2699,7 @@ void DofMap::old_dof_indices (const Elem * const elem,
27012699
#endif
27022700
ndan (type, static_cast<Order>(var.type().order + extra_order), n);
27032701

2704-
const int n_comp = old_dof_obj->n_comp_group(sys_num,vg);
2702+
const int n_comp = old_dof_obj.n_comp_group(sys_num,vg);
27052703

27062704
// If this is a non-vertex on a hanging node with extra
27072705
// degrees of freedom, we use the non-vertex dofs (which
@@ -2724,7 +2722,7 @@ void DofMap::old_dof_indices (const Elem * const elem,
27242722
for (int i=n_comp-1; i>=dof_offset; i--)
27252723
{
27262724
const dof_id_type d =
2727-
old_dof_obj->dof_number(sys_num, vg, vig, i, n_comp);
2725+
old_dof_obj.dof_number(sys_num, vg, vig, i, n_comp);
27282726

27292727
// On a newly-expanded subdomain, we
27302728
// may have some DoFs that didn't
@@ -2748,7 +2746,7 @@ void DofMap::old_dof_indices (const Elem * const elem,
27482746
for (unsigned int i=0; i != old_nc; ++i)
27492747
{
27502748
const dof_id_type d =
2751-
old_dof_obj->dof_number(sys_num, vg, vig, i, n_comp);
2749+
old_dof_obj.dof_number(sys_num, vg, vig, i, n_comp);
27522750

27532751
libmesh_assert_not_equal_to (d, DofObject::invalid_id);
27542752

@@ -2765,20 +2763,19 @@ void DofMap::old_dof_indices (const Elem * const elem,
27652763

27662764
if (nc != 0)
27672765
{
2768-
const DofObject * old_dof_obj = elem->old_dof_object;
2769-
libmesh_assert(old_dof_obj);
2766+
const DofObject & old_dof_obj = elem->get_old_dof_object_ref();
27702767

27712768
const unsigned int n_comp =
2772-
old_dof_obj->n_comp_group(sys_num,vg);
2769+
old_dof_obj.n_comp_group(sys_num,vg);
27732770

2774-
if (old_dof_obj->n_systems() > sys_num &&
2771+
if (old_dof_obj.n_systems() > sys_num &&
27752772
nc <= n_comp)
27762773
{
27772774

27782775
for (unsigned int i=0; i<nc; i++)
27792776
{
27802777
const dof_id_type d =
2781-
old_dof_obj->dof_number(sys_num, vg, vig, i, n_comp);
2778+
old_dof_obj.dof_number(sys_num, vg, vig, i, n_comp);
27822779

27832780
di.push_back(d);
27842781
}

0 commit comments

Comments
 (0)