libMesh
equation_systems_test.C
Go to the documentation of this file.
1 #include <libmesh/dof_map.h>
2 #include <libmesh/elem.h>
3 #include <libmesh/equation_systems.h>
4 #include <libmesh/ghost_point_neighbors.h>
5 #include <libmesh/mesh.h>
6 #include <libmesh/mesh_generation.h>
7 #include <libmesh/mesh_refinement.h>
8 #include <libmesh/remote_elem.h>
9 #include <libmesh/replicated_mesh.h>
10 #include <libmesh/node_elem.h>
11 
12 #include "test_comm.h"
13 #include "libmesh_cppunit.h"
14 
15 
16 using namespace libMesh;
17 
18 // Anonymous namespace to avoid linker conflicts
19 namespace {
20 
21 Number bilinear_test (const Point& p,
22  const Parameters&,
23  const std::string&,
24  const std::string&)
25 {
26  const Real & x = p(0);
27  const Real & y = p(1);
28 
29  return 4*x*y - 3*x + 2*y - 1;
30 }
31 
32 }
33 
34 class EquationSystemsTest : public CppUnit::TestCase {
35 public:
36  LIBMESH_CPPUNIT_TEST_SUITE( EquationSystemsTest );
37 
38  CPPUNIT_TEST( testConstruction );
39  CPPUNIT_TEST( testAddSystem );
40  CPPUNIT_TEST( testInit );
41  CPPUNIT_TEST( testPostInitAddSystem );
42  CPPUNIT_TEST( testPostInitAddElem );
43  CPPUNIT_TEST( testReinitWithNodeElem );
44  CPPUNIT_TEST( testBadVarNames );
45 #if LIBMESH_DIM > 1
46  CPPUNIT_TEST( testRefineThenReinitPreserveFlags );
47 #ifdef LIBMESH_ENABLE_AMR // needs project_solution, even for reordering
48  CPPUNIT_TEST( testRepartitionThenReinit );
49  CPPUNIT_TEST( testSelectivePRefine );
50 #endif
51 #endif
52  CPPUNIT_TEST( testDisableDefaultGhosting );
53 
54  CPPUNIT_TEST_SUITE_END();
55 
56 private:
57 
58 public:
59  void setUp()
60  {}
61 
62  void tearDown()
63  {}
64 
65 
66 
68  {
69  LOG_UNIT_TEST;
70 
73  }
74 
76  {
77  LOG_UNIT_TEST;
78 
81  /*System &sys = */es.add_system<System> ("SimpleSystem");
82  }
83 
84  void testInit()
85  {
86  LOG_UNIT_TEST;
87 
90  /*System &sys = */es.add_system<System> ("SimpleSystem");
92  es.init();
93  }
94 
96  {
97  LOG_UNIT_TEST;
98 
101  EquationSystems es(mesh);
102  /*System &sys1 = */es.add_system<System> ("SimpleSystem");
103  es.init();
104  /*System &sys2 = */es.add_system<System> ("SecondSystem");
105  es.reinit();
106  }
107 
109  {
110  LOG_UNIT_TEST;
111 
114  EquationSystems es(mesh);
115  System &sys1 = es.add_system<System> ("SimpleSystem");
116  sys1.add_variable("u1", FIRST);
117  es.init();
118  System &sys2 = es.add_system<System> ("SecondSystem");
119  sys2.add_variable("u2", FIRST);
120  es.reinit();
121  }
122 
124  {
125  LOG_UNIT_TEST;
126 
128 
129  EquationSystems es(mesh);
130  System &sys = es.add_system<System> ("SimpleSystem");
131  sys.add_variable("u", FIRST);
132 
134  es.init();
135 
137  e->processor_id() = 0;
138  e->set_node(0, mesh.node_ptr(2));
139  e->set_node(1, mesh.node_ptr(8));
141 
142  es.reinit();
143  }
144 
146  {
147 #ifdef LIBMESH_ENABLE_EXCEPTIONS
148  LOG_UNIT_TEST;
149 
152  EquationSystems es(mesh);
153  System &sys1 = es.add_system<System> ("SimpleSystem");
154  sys1.add_variable("u", FIRST, MONOMIAL_VEC);
155  es.init();
156 
157  const FEType & fe_type = sys1.variable_type ("u");
158  std::vector<std::string> var_names;
159  std::set<std::string> system_names = {"SimpleSystem"};
160  es.build_variable_names(var_names, &fe_type);
161 
162  System &sys2 = es.add_system<System> ("SecondSystem");
163  sys2.add_variable("u_x", FIRST);
164  sys2.add_variable("u_y", FIRST);
165  sys2.add_variable("u_z", FIRST);
166  es.reinit();
167 
168  var_names.clear();
169  CPPUNIT_ASSERT_THROW_MESSAGE("Duplicate var names not detected",
170  es.build_variable_names(var_names,
171  &fe_type),
173 #endif // LIBMESH_ENABLE_EXCEPTIONS
174  }
175 
177  {
178  LOG_UNIT_TEST;
179 
181 
183  auto node_elem = mesh.add_elem(Elem::build(NODEELEM));
184  node_elem->set_node(0, mesh.node_ptr(0));
186 
187  EquationSystems es(mesh);
188  System &sys = es.add_system<System> ("SimpleSystem");
189  sys.add_variable("u", CONSTANT, MONOMIAL);
190  es.init();
191  es.reinit();
192  }
193 
195  {
196  // This test requires AMR support since it sets refinement flags.
197 #ifdef LIBMESH_ENABLE_AMR
198  LOG_UNIT_TEST;
199 
201  mesh.allow_renumbering(false);
202  EquationSystems es(mesh);
203  System & sys = es.add_system<System> ("SimpleSystem");
204  sys.add_variable("u", FIRST);
206  es.init();
207 
208  Elem * to_refine = mesh.query_elem_ptr(0);
209  if (to_refine)
210  to_refine->set_refinement_flag(Elem::REFINE);
211 
212  MeshRefinement mr(mesh);
213  mr.refine_elements();
215  es.reinit();
216 
217  if (mesh.query_elem_ptr(1))
218  CPPUNIT_ASSERT( mesh.elem_ptr(1)->active() );
219 
220  const Elem * elem = mesh.query_elem_ptr(0);
221  if (elem)
222  {
223  CPPUNIT_ASSERT_EQUAL( Elem::INACTIVE,elem->refinement_flag() );
224 
225  for (unsigned int c=0; c<elem->n_children(); c++)
226  if (elem->child_ptr(c) != remote_elem)
227  CPPUNIT_ASSERT_EQUAL(Elem::JUST_REFINED,
228  elem->child_ptr(c)->refinement_flag());
229  }
230 #endif
231  }
232 
233 
235  {
236  // This test requires AMR support since it sets refinement flags.
237 #ifdef LIBMESH_ENABLE_AMR
238  LOG_UNIT_TEST;
239 
241  EquationSystems es(mesh);
242  System & sys = es.add_system<System> ("SimpleSystem");
243  const auto un = sys.add_variable("u", FIRST);
244  const auto vn = sys.add_variable("v", CONSTANT, MONOMIAL);
246  es.init();
247  auto & dof_map = sys.get_dof_map();
248  const auto ug = dof_map.var_group_from_var_number(un);
249  const auto vg = dof_map.var_group_from_var_number(vn);
250  dof_map.should_p_refine(ug, false);
251  dof_map.should_p_refine(vg, true);
252 
253  Elem * to_refine = mesh.query_elem_ptr(0);
254  if (to_refine)
255  to_refine->set_refinement_flag(Elem::REFINE);
256 
257  MeshRefinement mr(mesh);
259  mr.refine_elements();
261  es.reinit();
262 
263  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), dof_id_type(1));
264  const Elem * elem = mesh.query_elem_ptr(0);
265  if (elem)
266  {
267  std::vector<dof_id_type> dof_indices;
268  dof_map.dof_indices(elem, dof_indices, un);
269  CPPUNIT_ASSERT_EQUAL(dof_indices.size(), std::size_t(2));
270  dof_map.dof_indices(elem, dof_indices, vn);
271  CPPUNIT_ASSERT_EQUAL(dof_indices.size(), std::size_t(2));
272  }
273 #endif
274  }
275 
276 
278  {
279  LOG_UNIT_TEST;
280 
282  mesh.allow_renumbering(false);
283  EquationSystems es(mesh);
284  System & sys = es.add_system<System> ("SimpleSystem");
285  sys.add_variable("u", FIRST);
287  es.init();
288  sys.project_solution(bilinear_test, NULL, es.parameters);
289 
290  // Force (in parallel) a different partitioning - we'll simply put
291  // everything on rank 0, which hopefully is not what our default
292  // partitioner did!
293  mesh.partition(1);
294 
295  // Make sure the solution is still intact after reinit
296  es.reinit();
297 
298  for (Real x = 0.1; x < 1; x += 0.2)
299  for (Real y = 0.1; y < 1; y += 0.2)
300  {
301  Point p(x,y);
302  LIBMESH_ASSERT_NUMBERS_EQUAL
303  (sys.point_value(0,p),
304  bilinear_test(p,es.parameters,"",""),
306  }
307  }
308 
310  {
311  LOG_UNIT_TEST;
312 
314  EquationSystems es(mesh);
315 
316  auto n_ghosts = [&mesh]() {
319  };
320 
321  auto n_evaluables = [](System &sys) {
322  return int(std::distance(sys.get_dof_map().algebraic_ghosting_functors_begin(),
323  sys.get_dof_map().algebraic_ghosting_functors_end()));
324  };
325 
326  auto n_couplings = [](System &sys) {
327  return int(std::distance(sys.get_dof_map().coupling_functors_begin(),
328  sys.get_dof_map().coupling_functors_end()));
329  };
330 
331  // One default ghosting functor on the mesh
332  CPPUNIT_ASSERT_EQUAL(n_ghosts(), 1);
333 
334  // Add another functor, making two
335  auto gpn = std::make_shared<GhostPointNeighbors>(mesh);
337  CPPUNIT_ASSERT_EQUAL(n_ghosts(), 2);
338 
339  // Remove the default, leaving just the user functor
340  es.enable_default_ghosting(false);
341  CPPUNIT_ASSERT_EQUAL(n_ghosts(), 1);
342 
343  // Which can be removed too
345  CPPUNIT_ASSERT_EQUAL(n_ghosts(), 0);
346 
347  // Adding a new system shouldn't add any default ghosting if the
348  // EquationSystems disabled it
349  System & sys1 = es.add_system<System>("System1");
350  CPPUNIT_ASSERT_EQUAL(n_ghosts(), 0);
351  CPPUNIT_ASSERT_EQUAL(n_evaluables(sys1), 0);
352  CPPUNIT_ASSERT_EQUAL(n_couplings(sys1), 0);
353 
354  // But if we reenable it then now we should have three functors,
355  // with the default algebraic and coupling functors from sys1.
356  //
357  // We currently iterate over coupling functors manually even when
358  // using them for evaluability... this test will need to change
359  // eventually, when that does.
360  es.enable_default_ghosting(true);
361  CPPUNIT_ASSERT_EQUAL(n_ghosts(), 3);
362  CPPUNIT_ASSERT_EQUAL(n_evaluables(sys1), 1);
363  CPPUNIT_ASSERT_EQUAL(n_couplings(sys1), 1);
364 
365  // Adding a second system with default ghosting reenabled should
366  // give us 2 more functors.
367  System & sys2 = es.add_system<System>("System2");
368  CPPUNIT_ASSERT_EQUAL(n_ghosts(), 5);
369  CPPUNIT_ASSERT_EQUAL(n_evaluables(sys2), 1);
370  CPPUNIT_ASSERT_EQUAL(n_couplings(sys2), 1);
371 
372  // Adding a user functor to evaluables and couplings should add it
373  // to the mesh
376  CPPUNIT_ASSERT_EQUAL(n_ghosts(), 6);
377  CPPUNIT_ASSERT_EQUAL(n_evaluables(sys1), 2);
378  CPPUNIT_ASSERT_EQUAL(n_couplings(sys1), 1);
379 
380  // Unless we say not to.
381  auto gpn3 = std::make_shared<GhostPointNeighbors>(mesh);
382  sys1.get_dof_map().add_coupling_functor(gpn3, /*to_mesh=*/false);
383  CPPUNIT_ASSERT_EQUAL(n_ghosts(), 6);
384  CPPUNIT_ASSERT_EQUAL(n_evaluables(sys1), 2);
385  CPPUNIT_ASSERT_EQUAL(n_couplings(sys1), 2);
386 
387  // Turning off default coupling again should get rid of everything
388  // except the user functors.
389  es.enable_default_ghosting(false);
390  CPPUNIT_ASSERT_EQUAL(n_ghosts(), 1);
391  CPPUNIT_ASSERT_EQUAL(n_evaluables(sys1), 1);
392  CPPUNIT_ASSERT_EQUAL(n_couplings(sys1), 1);
393  CPPUNIT_ASSERT_EQUAL(n_evaluables(sys2), 0);
394  CPPUNIT_ASSERT_EQUAL(n_couplings(sys2), 0);
395  }
396 
397 
398 
399 
400 
401 };
402 
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:196
RefinementState refinement_flag() const
Definition: elem.h:3210
This is the EquationSystems class.
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
void build_variable_names(std::vector< std::string > &var_names, const FEType *type=nullptr, const std::set< std::string > *system_names=nullptr) const
Fill the input vector var_names with the names of the variables for each system.
virtual Node *& set_node(const unsigned int i)
Definition: elem.h:2558
void build_point(UnstructuredMesh &mesh, const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 0D meshes.
This class provides the ability to map between arbitrary, user-defined strings and several data types...
Definition: parameters.h:67
void allow_renumbering(bool allow)
If false is passed in then this mesh will no longer be renumbered when being prepared for use...
Definition: mesh_base.h:1196
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
static constexpr Real TOLERANCE
bool refine_elements()
Only refines the user-requested elements.
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly ecreated (or read) mesh for use.
Definition: mesh_base.C:759
void remove_ghosting_functor(GhostingFunctor &ghosting_functor)
Removes a functor which was previously added to the set of ghosting functors.
Definition: mesh_base.C:948
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
MeshBase & mesh
void disable_refine_in_reinit()
Calls to reinit() will not try to coarsen or refine the mesh.
void set_refinement_flag(const RefinementState rflag)
Sets the value of the refinement flag for the element.
Definition: elem.h:3218
Number point_value(unsigned int var, const Point &p, const bool insist_on_success=true, const NumericVector< Number > *sol=nullptr) const
Definition: system.C:2421
virtual void enable_default_ghosting(bool enable)
Enable or disable default ghosting functors on the Mesh and on all Systems.
virtual unsigned int n_children() const =0
void build_square(UnstructuredMesh &mesh, const unsigned int nx, const unsigned int ny, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 2D meshes.
The libMesh namespace provides an interface to certain functionality in the library.
Real distance(const Point &p)
void add_coupling_functor(GhostingFunctor &coupling_functor, bool to_mesh=true)
Adds a functor which can specify coupling requirements for creation of sparse matrices.
Definition: dof_map.C:2033
unsigned int var_group_from_var_number(unsigned int var_num) const
Definition: dof_map.h:2430
virtual void partition(const unsigned int n_parts)
Call the default partitioner (currently metis_partition()).
Definition: mesh_base.C:1576
void switch_h_to_p_refinement()
Takes a mesh whose elements are flagged for h refinement and coarsening, and switches those flags to ...
void project_solution(FunctionBase< Number > *f, FunctionBase< Gradient > *g=nullptr) const
Projects arbitrary functions onto the current solution.
Implements (adaptive) mesh refinement algorithms for a MeshBase.
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition: system.h:96
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition: elem.C:444
virtual void reinit()
Handle any mesh changes and reinitialize all the systems on the updated mesh.
virtual dof_id_type max_elem_id() const =0
unsigned int add_variable(std::string_view var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
Adds the variable var to the list of variables for this system.
Definition: system.C:1357
virtual const Elem * elem_ptr(const dof_id_type i) const =0
std::set< GhostingFunctor * >::const_iterator ghosting_functors_begin() const
Beginning of range of ghosting functors.
Definition: mesh_base.h:1291
CPPUNIT_TEST_SUITE_REGISTRATION(EquationSystemsTest)
const FEType & variable_type(const unsigned int i) const
Definition: system.h:2508
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
A class to represent the internal "this should never happen" errors, to be thrown by "libmesh_error()...
static std::unique_ptr< Elem > build_with_id(const ElemType type, dof_id_type id)
Calls the build() method above with a nullptr parent, and additionally sets the newly-created Elem&#39;s ...
Definition: elem.C:558
Parameters parameters
Data structure holding arbitrary parameters.
void build_line(UnstructuredMesh &mesh, const unsigned int nx, const Real xmin=0., const Real xmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 1D meshes.
virtual void init()
Initialize all the systems.
virtual dof_id_type n_elem() const =0
virtual System & add_system(std::string_view system_type, std::string_view name)
Add the system of type system_type named name to the systems array.
virtual const Node * node_ptr(const dof_id_type i) const =0
void add_algebraic_ghosting_functor(GhostingFunctor &evaluable_functor, bool to_mesh=true)
Adds a functor which can specify algebraic ghosting requirements for use with distributed vectors...
Definition: dof_map.C:2058
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition: mesh.h:50
bool active() const
Definition: elem.h:2941
const DofMap & get_dof_map() const
Definition: system.h:2374
processor_id_type processor_id() const
Definition: dof_object.h:905
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
void ErrorVector unsigned int
Definition: adjoints_ex3.C:360
This class implements the original default geometry ghosting requirements in libMesh: point neighbors...
const Elem * child_ptr(unsigned int i) const
Definition: elem.h:3163
std::set< GhostingFunctor * >::const_iterator ghosting_functors_end() const
End of range of ghosting functors.
Definition: mesh_base.h:1297
void add_ghosting_functor(GhostingFunctor &ghosting_functor)
Adds a functor which can specify ghosting requirements for use on distributed meshes.
Definition: mesh_base.h:1267
uint8_t dof_id_type
Definition: id_types.h:67
const RemoteElem * remote_elem
Definition: remote_elem.C:57