Skip to content

Commit ca8cf87

Browse files
authored
Merge pull request #3652 from lindsayad/more-add-p-level
More add_p_level API additions
2 parents d560e9b + 709aed7 commit ca8cf87

29 files changed

+221
-122
lines changed

include/base/dof_map.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,6 +1621,11 @@ class DofMap : public ReferenceCountedObject<DofMap>,
16211621
*/
16221622
bool should_p_refine(unsigned int g) const;
16231623

1624+
/**
1625+
* Whether the given variable should be p-refined
1626+
*/
1627+
bool should_p_refine_var(unsigned int var) const;
1628+
16241629
// Prevent bad user implicit conversions
16251630
void should_p_refine(FEFamily, bool) = delete;
16261631
void should_p_refine(Order, bool) = delete;
@@ -2344,6 +2349,18 @@ unsigned int DofMap::var_group_from_var_number(const unsigned int var_num) const
23442349
libmesh_assert(var_num < n_variables());
23452350
return libmesh_map_find(_var_to_vg, var_num);
23462351
}
2352+
2353+
inline
2354+
bool DofMap::should_p_refine_var(const unsigned int var) const
2355+
{
2356+
#ifdef LIBMESH_ENABLE_AMR
2357+
const auto vg = this->var_group_from_var_number(var);
2358+
return !_dont_p_refine.count(vg);
2359+
#else
2360+
libmesh_ignore(var);
2361+
return false;
2362+
#endif
2363+
}
23472364
} // namespace libMesh
23482365

23492366
#endif // LIBMESH_DOF_MAP_H

include/fe/fe.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,8 @@ class FE : public FEGenericBase<typename FEOutputType<T>::type>
364364
*/
365365
static void nodal_soln(const Elem * elem, const Order o,
366366
const std::vector<Number> & elem_soln,
367-
std::vector<Number> & nodal_soln);
367+
std::vector<Number> & nodal_soln,
368+
bool add_p_level = true);
368369

369370
/**
370371
* Build the nodal soln on one side from the (full) element soln.
@@ -375,7 +376,8 @@ class FE : public FEGenericBase<typename FEOutputType<T>::type>
375376
static void side_nodal_soln(const Elem * elem, const Order o,
376377
const unsigned int side,
377378
const std::vector<Number> & elem_soln,
378-
std::vector<Number> & nodal_soln_on_side);
379+
std::vector<Number> & nodal_soln_on_side,
380+
bool add_p_level = true);
379381

380382
/**
381383
* \returns The number of shape functions associated with
@@ -716,7 +718,8 @@ class FE : public FEGenericBase<typename FEOutputType<T>::type>
716718
static void default_side_nodal_soln(const Elem * elem, const Order o,
717719
const unsigned int side,
718720
const std::vector<Number> & elem_soln,
719-
std::vector<Number> & nodal_soln_on_side);
721+
std::vector<Number> & nodal_soln_on_side,
722+
bool add_p_level = true);
720723

721724
/**
722725
* An array of the node locations on the last
@@ -1401,7 +1404,8 @@ OutputShape fe_fdm_second_deriv(const ElemType type,
14011404
void lagrange_nodal_soln(const Elem * elem,
14021405
const Order order,
14031406
const std::vector<Number> & elem_soln,
1404-
std::vector<Number> & nodal_soln);
1407+
std::vector<Number> & nodal_soln,
1408+
bool add_p_level = true);
14051409

14061410
/**
14071411
* Helper functions for Discontinuous-Pn type basis functions.

include/fe/fe_abstract.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,11 @@ class FEAbstract : public ReferenceCountedObject<FEAbstract>
609609
*/
610610
void add_p_level_in_reinit(bool value) { _add_p_level_in_reinit = value; }
611611

612+
/**
613+
* Whether to add p-refinement levels in init/reinit methods
614+
*/
615+
bool add_p_level_in_reinit() const { return _add_p_level_in_reinit; }
616+
612617
protected:
613618

614619
/**

include/fe/fe_interface.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ class FEInterface
9595
* Non-deprecated version of function above.
9696
*/
9797
static unsigned int n_shape_functions(const FEType & fe_t,
98-
const Elem * elem);
98+
const Elem * elem,
99+
const bool add_p_level = true);
99100

100101
/**
101102
* Same as above, but ignores the elem->p_level() and uses the
@@ -226,7 +227,8 @@ class FEInterface
226227
* The non-deprecated version of the function above.
227228
*/
228229
static unsigned int n_dofs_per_elem(const FEType & fe_t,
229-
const Elem * elem);
230+
const Elem * elem,
231+
bool add_p_level = true);
230232

231233
/**
232234
* Same thing but internally elem->p_level() is ignored and extra_order is used instead.
@@ -289,7 +291,8 @@ class FEInterface
289291
const FEType & fe_t,
290292
const Elem * elem,
291293
const std::vector<Number> & elem_soln,
292-
std::vector<Number> & nodal_soln);
294+
std::vector<Number> & nodal_soln,
295+
bool add_p_level = true);
293296

294297

295298
/**
@@ -304,7 +307,8 @@ class FEInterface
304307
const Elem * elem,
305308
const unsigned int side,
306309
const std::vector<Number> & elem_soln,
307-
std::vector<Number> & nodal_soln);
310+
std::vector<Number> & nodal_soln,
311+
bool add_p_level = true);
308312

309313
/**
310314
* This is now deprecated; use FEMap::map instead.
@@ -386,12 +390,13 @@ class FEInterface
386390

387391
/**
388392
* Non-deprecated version of the shape() function. The
389-
* Elem::p_level() is accounted for internally.
393+
* Elem::p_level() is accounted for internally if \p add_p_level
390394
*/
391395
static Real shape(const FEType & fe_t,
392396
const Elem * elem,
393397
const unsigned int i,
394-
const Point & p);
398+
const Point & p,
399+
const bool add_p_level = true);
395400

396401
/**
397402
* Non-deprecated version of the shape() function. The

include/fe/fe_macro.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
template LIBMESH_EXPORT void FE<2,SUBDIVISION>::init_shape_functions(const std::vector<Point> &, const Elem *); \
5252
template LIBMESH_EXPORT void FE<2,SUBDIVISION>::init_dual_shape_functions(unsigned int, unsigned int); \
5353
template LIBMESH_EXPORT void FE<2,SUBDIVISION>::default_all_shape_derivs (const Elem * elem, const Order o, const std::vector<Point> & p, std::vector<std::vector<Real>> * comps[3], const bool add_p_level); \
54-
template LIBMESH_EXPORT void FE<2,SUBDIVISION>::default_side_nodal_soln(const Elem * elem, const Order o, const unsigned int side, const std::vector<Number> & elem_soln, std::vector<Number> & nodal_soln_on_side)
54+
template LIBMESH_EXPORT void FE<2,SUBDIVISION>::default_side_nodal_soln(const Elem * elem, const Order o, const unsigned int side, const std::vector<Number> & elem_soln, std::vector<Number> & nodal_soln_on_side, bool add_p_level)
5555

5656
#else // LIBMESH_ENABLE_INFINITE_ELEMENTS
5757

@@ -64,7 +64,7 @@
6464
template LIBMESH_EXPORT void FE<2,SUBDIVISION>::init_shape_functions(const std::vector<Point> &, const Elem *); \
6565
template LIBMESH_EXPORT void FE<2,SUBDIVISION>::init_dual_shape_functions(unsigned int, unsigned int); \
6666
template LIBMESH_EXPORT void FE<2,SUBDIVISION>::default_all_shape_derivs (const Elem * elem, const Order o, const std::vector<Point> & p, std::vector<std::vector<Real>> * comps[3], const bool add_p_level); \
67-
template LIBMESH_EXPORT void FE<2,SUBDIVISION>::default_side_nodal_soln(const Elem * elem, const Order o, const unsigned int side, const std::vector<Number> & elem_soln, std::vector<Number> & nodal_soln_on_side)
67+
template LIBMESH_EXPORT void FE<2,SUBDIVISION>::default_side_nodal_soln(const Elem * elem, const Order o, const unsigned int side, const std::vector<Number> & elem_soln, std::vector<Number> & nodal_soln_on_side, bool add_p_level)
6868

6969
#endif // LIBMESH_ENABLE_INFINITE_ELEMENTS
7070

@@ -116,8 +116,9 @@ template <> \
116116
void FE<_dim,_fetype>::nodal_soln(const Elem * elem, \
117117
const Order order, \
118118
const std::vector<Number> & elem_soln,\
119-
std::vector<Number> & nodal_soln) \
120-
{ _funcname(elem, order, elem_soln, nodal_soln); }
119+
std::vector<Number> & nodal_soln, \
120+
const bool add_p_level) \
121+
{ _funcname(elem, order, elem_soln, nodal_soln, add_p_level); }
121122

122123
#define LIBMESH_FE_NODAL_SOLN(fetype, _funcname) \
123124
LIBMESH_FE_NODAL_SOLN_DIM(fetype, _funcname, 0) \
@@ -132,8 +133,9 @@ void FE<_dim,_fetype>::side_nodal_soln(const Elem * elem, \
132133
const Order order, \
133134
const unsigned int side, \
134135
const std::vector<Number> & elem_soln,\
135-
std::vector<Number> & nodal_soln)\
136-
{ default_side_nodal_soln(elem, order, side, elem_soln, nodal_soln); }
136+
std::vector<Number> & nodal_soln, \
137+
const bool add_p_level) \
138+
{ default_side_nodal_soln(elem, order, side, elem_soln, nodal_soln, add_p_level); }
137139

138140
#define LIBMESH_FE_SIDE_NODAL_SOLN(fetype) \
139141
LIBMESH_FE_SIDE_NODAL_SOLN_DIM(fetype, 0) \

include/systems/generic_projector.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,7 +1656,7 @@ void GenericProjector<FFunctor, GFunctor, FValue, ProjectionAction>::SortAndCopy
16561656
}
16571657
}
16581658

1659-
if (FEInterface::n_dofs_per_elem(fe_type, elem) ||
1659+
if (FEInterface::n_dofs_per_elem(fe_type, elem, add_p_level) ||
16601660
(has_interior_nodes &&
16611661
FEInterface::n_dofs_at_node(fe_type, elem, n_nodes-1, add_p_level)))
16621662
{
@@ -2549,10 +2549,12 @@ void GenericProjector<FFunctor, GFunctor, FValue, ProjectionAction>::ProjectSide
25492549
continue;
25502550

25512551
FEType fe_type = base_fe_type;
2552+
const auto & dof_map = system.get_dof_map();
2553+
const bool add_p_level = dof_map.should_p_refine_var(var);
25522554

25532555
// This may be a p refined element
25542556
fe_type.order =
2555-
libMesh::Order (fe_type.order + elem.p_level());
2557+
libMesh::Order (fe_type.order + add_p_level*elem.p_level());
25562558

25572559
// If this is a Lagrange element with DoFs on sides then by
25582560
// convention we interpolate at the node rather than project
@@ -2664,7 +2666,7 @@ void GenericProjector<FFunctor, GFunctor, FValue, ProjectionAction>::ProjectSide
26642666

26652667
std::vector<unsigned int> side_dofs;
26662668
FEInterface::dofs_on_side(&elem, dim, base_fe_type,
2667-
context.side, side_dofs);
2669+
context.side, side_dofs, add_p_level);
26682670

26692671
this->construct_projection
26702672
(dof_indices, side_dofs, var_component,
@@ -2708,10 +2710,13 @@ void GenericProjector<FFunctor, GFunctor, FValue, ProjectionAction>::ProjectInte
27082710
context.get_element_fe( var, fe, dim );
27092711

27102712
FEType fe_type = base_fe_type;
2713+
const auto & dof_map = system.get_dof_map();
2714+
const auto vg = dof_map.var_group_from_var_number(var);
2715+
const bool add_p_level = dof_map.should_p_refine(vg);
27112716

27122717
// This may be a p refined element
27132718
fe_type.order =
2714-
libMesh::Order (fe_type.order + elem->p_level());
2719+
libMesh::Order (fe_type.order + add_p_level * elem->p_level());
27152720

27162721
const unsigned int var_component =
27172722
system.variable_scalar_number(var, 0);

src/base/dof_map.C

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -813,7 +813,7 @@ void DofMap::reinit(MeshBase & mesh)
813813
}
814814
// Allocate the element DOFs
815815
const unsigned int dofs_per_elem =
816-
FEInterface::n_dofs_per_elem(base_fe_type, elem);
816+
FEInterface::n_dofs_per_elem(base_fe_type, elem, add_p_level);
817817

818818
elem->set_n_comp_group(sys_num, vg, dofs_per_elem);
819819

@@ -2509,7 +2509,7 @@ void DofMap::_dof_indices (const Elem & elem,
25092509
}
25102510

25112511
// If there are any element-based DOF numbers, get them
2512-
const unsigned int nc = FEInterface::n_dofs_per_elem(fe_type, p_level, &elem);
2512+
const unsigned int nc = FEInterface::n_dofs_per_elem(fe_type, add_p_level*p_level, &elem);
25132513

25142514
// We should never have fewer dofs than necessary on an
25152515
// element unless we're getting indices on a parent element

src/fe/fe.C

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -706,10 +706,11 @@ void
706706
FE<Dim,T>::default_side_nodal_soln(const Elem * elem, const Order o,
707707
const unsigned int side,
708708
const std::vector<Number> & elem_soln,
709-
std::vector<Number> & nodal_soln_on_side)
709+
std::vector<Number> & nodal_soln_on_side,
710+
const bool add_p_level)
710711
{
711712
std::vector<Number> full_nodal_soln;
712-
nodal_soln(elem, o, elem_soln, full_nodal_soln);
713+
nodal_soln(elem, o, elem_soln, full_nodal_soln, add_p_level);
713714
const std::vector<unsigned int> side_nodes =
714715
elem->nodes_on_side(side);
715716

src/fe/fe_base.C

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1549,10 +1549,12 @@ FEGenericBase<OutputType>::compute_proj_constraints (DofConstraints & constraint
15491549

15501550
const Variable & var = dof_map.variable(variable_number);
15511551
const FEType & base_fe_type = var.type();
1552+
const bool add_p_level = dof_map.should_p_refine_var(variable_number);
15521553

15531554
// Construct FE objects for this element and its neighbors.
15541555
std::unique_ptr<FEGenericBase<OutputShape>> my_fe
15551556
(FEGenericBase<OutputShape>::build(Dim, base_fe_type));
1557+
my_fe->add_p_level_in_reinit(add_p_level);
15561558
const FEContinuity cont = my_fe->get_continuity();
15571559

15581560
// We don't need to constrain discontinuous elements
@@ -1570,6 +1572,7 @@ FEGenericBase<OutputType>::compute_proj_constraints (DofConstraints & constraint
15701572

15711573
std::unique_ptr<FEGenericBase<OutputShape>> neigh_fe
15721574
(FEGenericBase<OutputShape>::build(Dim, base_fe_type));
1575+
neigh_fe->add_p_level_in_reinit(add_p_level);
15731576

15741577
QGauss my_qface(Dim-1, base_fe_type.default_quadrature_order());
15751578
my_fe->attach_quadrature_rule (&my_qface);
@@ -1630,15 +1633,14 @@ FEGenericBase<OutputType>::compute_proj_constraints (DofConstraints & constraint
16301633
// matrix with this and then constrain away all higher p
16311634
// DoFs.
16321635
libmesh_assert(neigh->active());
1633-
const unsigned int min_p_level =
1636+
const unsigned int min_p_level = add_p_level *
16341637
std::min(elem->p_level(), neigh->p_level());
1635-
16361638
// we may need to make the FE objects reinit with the
16371639
// minimum shared p_level
1638-
const unsigned int old_elem_level = elem->p_level();
1639-
if (elem->p_level() != min_p_level)
1640+
const unsigned int old_elem_level = add_p_level * elem->p_level();
1641+
if (old_elem_level != min_p_level)
16401642
my_fe->set_fe_order(my_fe->get_fe_type().order.get_order() + min_p_level - old_elem_level);
1641-
const unsigned int old_neigh_level = neigh->p_level();
1643+
const unsigned int old_neigh_level = add_p_level * neigh->p_level();
16421644
if (old_neigh_level != min_p_level)
16431645
neigh_fe->set_fe_order(neigh_fe->get_fe_type().order.get_order() + min_p_level - old_neigh_level);
16441646

@@ -1808,20 +1810,23 @@ FEGenericBase<OutputType>::compute_proj_constraints (DofConstraints & constraint
18081810
neigh_fe->set_fe_order(neigh_fe->get_fe_type().order.get_order() + old_neigh_level - min_p_level);
18091811
}
18101812

1811-
// p refinement constraints:
1812-
// constrain dofs shared between
1813-
// active elements and neighbors with
1814-
// lower polynomial degrees
1815-
const unsigned int min_p_level =
1816-
neigh->min_p_level_by_neighbor(elem, elem->p_level());
1817-
if (min_p_level < elem->p_level())
1813+
if (add_p_level)
1814+
{
1815+
// p refinement constraints:
1816+
// constrain dofs shared between
1817+
// active elements and neighbors with
1818+
// lower polynomial degrees
1819+
const unsigned int min_p_level =
1820+
neigh->min_p_level_by_neighbor(elem, elem->p_level());
1821+
if (min_p_level < elem->p_level())
18181822
{
18191823
// Adaptive p refinement of non-hierarchic bases will
18201824
// require more coding
18211825
libmesh_assert(my_fe->is_hierarchic());
18221826
dof_map.constrain_p_dofs(variable_number, elem,
18231827
s, min_p_level);
18241828
}
1829+
}
18251830
}
18261831
}
18271832

src/fe/fe_bernstein.C

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,16 @@ namespace {
4040
void bernstein_nodal_soln(const Elem * elem,
4141
const Order order,
4242
const std::vector<Number> & elem_soln,
43-
std::vector<Number> & nodal_soln)
43+
std::vector<Number> & nodal_soln,
44+
const bool add_p_level)
4445
{
4546
const unsigned int n_nodes = elem->n_nodes();
4647

4748
const ElemType elem_type = elem->type();
4849

4950
nodal_soln.resize(n_nodes);
5051

51-
const Order totalorder = static_cast<Order>(order + elem->p_level());
52+
const Order totalorder = static_cast<Order>(order + add_p_level*elem->p_level());
5253

5354
// FEType object to be passed to various FEInterface functions below.
5455
FEType fe_type(order, BERNSTEIN);

src/fe/fe_clough.C

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,16 @@ namespace {
3636
void clough_nodal_soln(const Elem * elem,
3737
const Order order,
3838
const std::vector<Number> & elem_soln,
39-
std::vector<Number> & nodal_soln)
39+
std::vector<Number> & nodal_soln,
40+
const bool add_p_level)
4041
{
4142
const unsigned int n_nodes = elem->n_nodes();
4243

4344
const ElemType elem_type = elem->type();
4445

4546
nodal_soln.resize(n_nodes);
4647

47-
const Order totalorder = static_cast<Order>(order + elem->p_level());
48+
const Order totalorder = static_cast<Order>(order + add_p_level*elem->p_level());
4849

4950
// FEType object to be passed to various FEInterface functions below.
5051
FEType fe_type(order, CLOUGH);

src/fe/fe_hermite.C

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ namespace {
3636
void hermite_nodal_soln(const Elem * elem,
3737
const Order order,
3838
const std::vector<Number> & elem_soln,
39-
std::vector<Number> & nodal_soln)
39+
std::vector<Number> & nodal_soln,
40+
const bool add_p_level)
4041
{
4142
const unsigned int n_nodes = elem->n_nodes();
4243

@@ -48,7 +49,7 @@ void hermite_nodal_soln(const Elem * elem,
4849
FEType fe_type(order, HERMITE);
4950

5051
const unsigned int n_sf =
51-
FEInterface::n_shape_functions(fe_type, elem);
52+
FEInterface::n_shape_functions(fe_type, elem, add_p_level);
5253

5354
std::vector<Point> refspace_nodes;
5455
FEBase::get_refspace_nodes(elem_type,refspace_nodes);
@@ -64,7 +65,7 @@ void hermite_nodal_soln(const Elem * elem,
6465
// u_i = Sum (alpha_i phi_i)
6566
for (unsigned int i=0; i<n_sf; i++)
6667
nodal_soln[n] += elem_soln[i] *
67-
FEInterface::shape(fe_type, elem, i, refspace_nodes[n]);
68+
FEInterface::shape(fe_type, elem, i, refspace_nodes[n], add_p_level);
6869
}
6970
} // hermite_nodal_soln()
7071

0 commit comments

Comments
 (0)