libMesh
systems_test.C
Go to the documentation of this file.
1 #include <libmesh/equation_systems.h>
2 #include <libmesh/int_range.h>
3 #include <libmesh/mesh.h>
4 #include <libmesh/node.h>
5 #include <libmesh/dof_map.h>
6 #include <libmesh/mesh_generation.h>
7 #include <libmesh/replicated_mesh.h>
8 #include <libmesh/mesh_function.h>
9 #include <libmesh/numeric_vector.h>
10 #include <libmesh/mesh_refinement.h>
11 #include <libmesh/sparse_matrix.h>
12 #include "libmesh/string_to_enum.h"
13 #include <libmesh/cell_tet4.h>
14 #include <libmesh/zero_function.h>
15 #include <libmesh/linear_implicit_system.h>
16 #include <libmesh/transient_system.h>
17 #include <libmesh/quadrature_gauss.h>
18 #include <libmesh/node_elem.h>
19 #include <libmesh/edge_edge2.h>
20 #include <libmesh/dg_fem_context.h>
21 #include <libmesh/enum_solver_type.h>
22 #include <libmesh/enum_preconditioner_type.h>
23 #include <libmesh/linear_solver.h>
24 #include <libmesh/parallel.h>
25 #include <libmesh/face_quad4.h>
26 #include <libmesh/face_quad9.h>
27 #include <libmesh/face_quad8.h>
28 #include <libmesh/face_tri3.h>
29 #include <libmesh/face_tri6.h>
30 #include <libmesh/face_tri7.h>
31 #include <libmesh/cell_hex8.h>
32 #include <libmesh/cell_hex20.h>
33 #include <libmesh/cell_hex27.h>
34 #include <libmesh/cell_tet10.h>
35 #include <libmesh/cell_tet14.h>
36 #include <libmesh/boundary_info.h>
37 
38 #include "test_comm.h"
39 #include "libmesh_cppunit.h"
40 
41 #include <string>
42 
43 using namespace libMesh;
44 
45 // Sparsity pattern augmentation class used in testDofCouplingWithVarGroups
47 {
48 private:
49 
54 
55 public:
56 
61  :
62  _mesh(mesh)
63  {}
64 
68  virtual void operator() (const MeshBase::const_element_iterator & range_begin,
69  const MeshBase::const_element_iterator & range_end,
71  map_type & coupled_elements) override
72  {
73  dof_id_type node_elem_id_1 = 2;
74  dof_id_type node_elem_id_2 = 3;
75 
76  const CouplingMatrix * const null_mat = nullptr;
77 
78  for (const auto & elem : as_range(range_begin, range_end))
79  {
80  if (elem->id() == node_elem_id_1)
81  {
82  if (elem->processor_id() != p)
83  {
84  coupled_elements.emplace(elem, null_mat);
85 
86  const Elem * neighbor = _mesh.elem_ptr(node_elem_id_2);
87  if (neighbor->processor_id() != p)
88  coupled_elements.emplace(neighbor, null_mat);
89  }
90  }
91  if (elem->id() == node_elem_id_2)
92  {
93  if (elem->processor_id() != p)
94  {
95  coupled_elements.emplace(elem, null_mat);
96 
97  const Elem * neighbor = _mesh.elem_ptr(node_elem_id_1);
98  if (neighbor->processor_id() != p)
99  coupled_elements.emplace(neighbor, null_mat);
100  }
101  }
102  }
103  }
104 
109  virtual void mesh_reinit () override
110  {
111  }
112 
117  virtual void redistribute () override
118  { this->mesh_reinit(); }
119 
120 };
121 
122 // Assembly function used in testDofCouplingWithVarGroups
124  const std::string&)
125 {
126  const MeshBase& mesh = es.get_mesh();
128  const DofMap& dof_map = system.get_dof_map();
129 
132 
133  std::vector<dof_id_type> dof_indices;
134 
135  SparseMatrix<Number> & matrix = system.get_system_matrix();
136 
137  MeshBase::const_element_iterator el = mesh.active_local_elements_begin();
138  const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end();
139 
140  for ( ; el != end_el; ++el)
141  {
142  const Elem* elem = *el;
143 
144  if(elem->type() == NODEELEM)
145  {
146  continue;
147  }
148 
149  dof_map.dof_indices (elem, dof_indices);
150  const unsigned int n_dofs = dof_indices.size();
151 
152  Ke.resize (n_dofs, n_dofs);
153  Fe.resize (n_dofs);
154 
155  for(unsigned int i=0; i<n_dofs; i++)
156  {
157  Ke(i,i) = 1.;
158  Fe(i) = 1.;
159  }
160 
161  matrix.add_matrix (Ke, dof_indices);
162  system.rhs->add_vector (Fe, dof_indices);
163  }
164 
165  // Add matrix for extra coupled dofs
166  {
167  const Node & node_1 = mesh.node_ref(1);
168  const Node & node_2 = mesh.node_ref(2);
169  dof_indices.resize(6);
170  dof_indices[0] =
171  node_1.dof_number(system.number(), system.variable_number("u"), 0);
172  dof_indices[1] =
173  node_1.dof_number(system.number(), system.variable_number("v"), 0);
174  dof_indices[2] =
175  node_1.dof_number(system.number(), system.variable_number("w"), 0);
176 
177  dof_indices[3] =
178  node_2.dof_number(system.number(), system.variable_number("u"), 0);
179  dof_indices[4] =
180  node_2.dof_number(system.number(), system.variable_number("v"), 0);
181  dof_indices[5] =
182  node_2.dof_number(system.number(), system.variable_number("w"), 0);
183 
184  const unsigned int n_dofs = dof_indices.size();
185  Ke.resize (n_dofs, n_dofs);
186  Fe.resize (n_dofs);
187 
188  for(unsigned int i=0; i<n_dofs; i++)
189  {
190  Ke(i,i) = 1.;
191  Fe(i) = 1.;
192  }
193 
194  matrix.add_matrix (Ke, dof_indices);
195  system.rhs->add_vector (Fe, dof_indices);
196  }
197 
198  system.rhs->close();
199  matrix.close();
200 }
201 
202 // Assembly function that uses a DGFEMContext
204  const std::string& /*system_name*/)
205 {
206  const MeshBase& mesh = es.get_mesh();
208 
211 
212  std::vector<dof_id_type> dof_indices;
213  SparseMatrix<Number> & matrix = system.get_system_matrix();
214 
215  DGFEMContext context(system);
216  {
217  // For efficiency, we should prerequest all
218  // the data we will need to build the
219  // linear system before doing an element loop.
220  FEBase* elem_fe = NULL;
221  context.get_element_fe(0, elem_fe);
222  elem_fe->get_JxW();
223  elem_fe->get_phi();
224  elem_fe->get_dphi();
225 
226  FEBase* side_fe = NULL;
227  context.get_side_fe( 0, side_fe );
228  side_fe->get_JxW();
229  side_fe->get_phi();
230 
231  FEBase* neighbor_side_fe = NULL;
232  context.get_neighbor_side_fe(0, neighbor_side_fe);
233  neighbor_side_fe->get_phi();
234  }
235 
236  for (const auto & elem : mesh.active_local_element_ptr_range())
237  {
238  context.pre_fe_reinit(system, elem);
239  context.elem_fe_reinit();
240 
241  // Element interior assembly
242  {
243  FEBase* elem_fe = NULL;
244  context.get_element_fe(0, elem_fe);
245 
246  const std::vector<Real> &JxW = elem_fe->get_JxW();
247  const std::vector<std::vector<Real> >& phi = elem_fe->get_phi();
248  const std::vector<std::vector<RealGradient> >& dphi = elem_fe->get_dphi();
249 
250  unsigned int n_dofs = context.get_dof_indices(0).size();
251  unsigned int n_qpoints = context.get_element_qrule().n_points();
252 
253  for (unsigned int qp=0; qp != n_qpoints; qp++)
254  for (unsigned int i=0; i != n_dofs; i++)
255  for (unsigned int j=0; j != n_dofs; j++)
256  context.get_elem_jacobian()(i,j) += JxW[qp] * dphi[i][qp]*dphi[j][qp];
257 
258  for (unsigned int qp=0; qp != n_qpoints; qp++)
259  for (unsigned int i=0; i != n_dofs; i++)
260  context.get_elem_residual()(i) += JxW[qp] * phi[i][qp];
261  }
262 
263  matrix.add_matrix (context.get_elem_jacobian(), context.get_dof_indices());
264  system.rhs->add_vector (context.get_elem_residual(), context.get_dof_indices());
265 
266  // Element side assembly
267  for (context.side = 0; context.side != elem->n_sides(); ++context.side)
268  {
269  // If there is a neighbor, then we proceed with assembly
270  // that involves elem and neighbor
271  const Elem* neighbor = elem->neighbor_ptr(context.get_side());
272  if(neighbor)
273  {
274  context.side_fe_reinit();
275  context.set_neighbor(*neighbor);
276 
277  // This call initializes neighbor data, and also sets
278  // context.dg_terms_are_active() to true
279  context.neighbor_side_fe_reinit();
280 
281  FEBase* side_fe = NULL;
282  context.get_side_fe(0, side_fe);
283 
284  const std::vector<Real> &JxW_face = side_fe->get_JxW();
285  const std::vector<std::vector<Real> >& phi_face = side_fe->get_phi();
286 
287  FEBase* neighbor_side_fe = NULL;
288  context.get_neighbor_side_fe(0, neighbor_side_fe);
289 
290  // These shape functions have been evaluated on the quadrature points
291  // for elem->side on the neighbor element
292  const std::vector<std::vector<Real> >& phi_neighbor_face =
293  neighbor_side_fe->get_phi();
294 
295  const unsigned int n_dofs = context.get_dof_indices(0).size();
296  const unsigned int n_neighbor_dofs = context.get_neighbor_dof_indices(0).size();
297  unsigned int n_sidepoints = context.get_side_qrule().n_points();
298 
299  for (unsigned int qp=0; qp<n_sidepoints; qp++)
300  {
301  for (unsigned int i=0; i<n_dofs; i++)
302  for (unsigned int j=0; j<n_dofs; j++)
303  {
304  context.get_elem_elem_jacobian()(i,j) +=
305  JxW_face[qp] * phi_face[i][qp] * phi_face[j][qp];
306  }
307 
308  for (unsigned int i=0; i<n_dofs; i++)
309  for (unsigned int j=0; j<n_neighbor_dofs; j++)
310  {
311  context.get_elem_neighbor_jacobian()(i,j) +=
312  JxW_face[qp] * phi_face[i][qp] * phi_neighbor_face[j][qp];
313  }
314 
315  for (unsigned int i=0; i<n_neighbor_dofs; i++)
316  for (unsigned int j=0; j<n_neighbor_dofs; j++)
317  {
318  context.get_neighbor_neighbor_jacobian()(i,j) +=
319  JxW_face[qp] * phi_neighbor_face[i][qp] * phi_neighbor_face[j][qp];
320  }
321 
322  for (unsigned int i=0; i<n_neighbor_dofs; i++)
323  for (unsigned int j=0; j<n_dofs; j++)
324  {
325  context.get_neighbor_elem_jacobian()(i,j) +=
326  JxW_face[qp] * phi_neighbor_face[i][qp] * phi_face[j][qp];
327  }
328  }
329 
330  matrix.add_matrix (context.get_elem_elem_jacobian(),
331  context.get_dof_indices(),
332  context.get_dof_indices());
333 
334  matrix.add_matrix (context.get_elem_neighbor_jacobian(),
335  context.get_dof_indices(),
336  context.get_neighbor_dof_indices());
337 
338  matrix.add_matrix (context.get_neighbor_elem_jacobian(),
339  context.get_neighbor_dof_indices(),
340  context.get_dof_indices());
341 
342  matrix.add_matrix (context.get_neighbor_neighbor_jacobian(),
343  context.get_neighbor_dof_indices(),
344  context.get_neighbor_dof_indices());
345  }
346  }
347  }
348 }
349 
350 
352  const Parameters&,
353  const std::string&,
354  const std::string&)
355 {
356  const Real & x = p(0);
357  const Real & y = LIBMESH_DIM > 1 ? p(1) : 0;
358  const Real & z = LIBMESH_DIM > 2 ? p(2) : 0;
359 
360  return x*(1-x)*(1-x) + x*x*(1-y) + x*(1-y)*(1-z) + y*(1-y)*z + z*(1-z)*(1-z);
361 }
362 
363 
365  const Parameters&,
366  const std::string&,
367  const std::string&)
368 {
369  const Real & x = p(0);
370  const Real & y = LIBMESH_DIM > 1 ? p(1) : 0;
371  const Real & z = LIBMESH_DIM > 2 ? p(2) : 0;
372 
373  return x + 2*y + 3*z - 1;
374 }
375 
376 
378  const Parameters&,
379  const std::string&,
380  const std::string&)
381 {
382  const Real & x = p(0);
383  const Real & y = LIBMESH_DIM > 1 ? p(1) : 0;
384  const Real & z = LIBMESH_DIM > 2 ? p(2) : 0;
385 
386  return (3*x < 1) + (3*y < 2) + (3*z > 2);
387 }
388 
389 
390 struct TripleFunction : public FunctionBase<Number>
391 {
392  TripleFunction(Number _offset = 0) : offset(_offset) {}
393 
394  virtual std::unique_ptr<FunctionBase<Number>> clone () const
395  { return std::make_unique<TripleFunction>(offset); }
396 
397  // We only really need the vector-valued output for projections
398  virtual Number operator() (const Point &,
399  const Real /*time*/ = 0.) override
400  { libmesh_error(); }
401 
402  virtual void operator() (const Point & p,
403  const Real,
404  DenseVector<Number> & output) override
405  {
406  libmesh_assert_greater(output.size(), 0);
407  Parameters params;
408  output(0) = cubic_test(p, params, "", "") + offset;
409  if (output.size() > 0)
410  output(1) = new_linear_test(p, params, "", "") + offset;
411  if (output.size() > 1)
412  output(2) = disc_thirds_test(p, params, "", "") + offset;
413  }
414 
415  Number component (unsigned int i,
416  const Point & p,
417  Real /* time */) override
418  {
419  Parameters params;
420  switch (i) {
421  case 0:
422  return cubic_test(p, params, "", "") + offset;
423  case 1:
424  return new_linear_test(p, params, "", "") + offset;
425  case 2:
426  return disc_thirds_test(p, params, "", "") + offset;
427  default:
428  libmesh_error();
429  }
430  return 0;
431  }
432 
434 };
435 
436 
437 class SystemsTest : public CppUnit::TestCase {
438 public:
439  LIBMESH_CPPUNIT_TEST_SUITE( SystemsTest );
440 
441  CPPUNIT_TEST( test100KVariables );
442 
443  CPPUNIT_TEST( testPostInitAddVector );
444  CPPUNIT_TEST( testAddVectorProjChange );
445  CPPUNIT_TEST( testAddVectorTypeChange );
446  CPPUNIT_TEST( testPostInitAddVectorTypeChange );
447 
448  CPPUNIT_TEST( testProjectHierarchicEdge3 );
449 #if LIBMESH_DIM > 1
450  CPPUNIT_TEST( testProjectHierarchicQuad9 );
451  CPPUNIT_TEST( testProjectHierarchicTri6 );
452  CPPUNIT_TEST( testProjectHierarchicTri7 );
453  CPPUNIT_TEST( test2DProjectVectorFETri3 );
454  CPPUNIT_TEST( test2DProjectVectorFEQuad4 );
455  CPPUNIT_TEST( test2DProjectVectorFETri6 );
456  CPPUNIT_TEST( test2DProjectVectorFETri7 );
457  CPPUNIT_TEST( test2DProjectVectorFEQuad8 );
458  CPPUNIT_TEST( test2DProjectVectorFEQuad9 );
459 #ifdef LIBMESH_HAVE_SOLVER
460  CPPUNIT_TEST( testBlockRestrictedVarNDofs );
461 #endif
462 #endif // LIBMESH_DIM > 1
463 #if LIBMESH_DIM > 2
464  CPPUNIT_TEST( testProjectHierarchicHex27 );
465  CPPUNIT_TEST( testProjectMeshFunctionHex27 );
466  CPPUNIT_TEST( testBoundaryProjectCube );
467  CPPUNIT_TEST( test3DProjectVectorFETet4 );
468  CPPUNIT_TEST( test3DProjectVectorFEHex8 );
469  CPPUNIT_TEST( test3DProjectVectorFETet10 );
470  CPPUNIT_TEST( test3DProjectVectorFETet14 );
471  CPPUNIT_TEST( test3DProjectVectorFEHex20 );
472  CPPUNIT_TEST( test3DProjectVectorFEHex27 );
473 #ifdef LIBMESH_HAVE_SOLVER
474  CPPUNIT_TEST( testSetSystemParameterOverEquationSystem);
475  CPPUNIT_TEST( testAssemblyWithDgFemContext );
476 #endif
477 #endif // LIBMESH_DIM > 2
478 #ifdef LIBMESH_HAVE_SOLVER
479  CPPUNIT_TEST( testDofCouplingWithVarGroups );
480 #endif
481 
482 #ifdef LIBMESH_ENABLE_AMR
483 #ifdef LIBMESH_HAVE_METAPHYSICL
484 #ifdef LIBMESH_HAVE_PETSC
485  CPPUNIT_TEST( testProjectMatrixEdge2 );
486 #if LIBMESH_DIM > 1
487  CPPUNIT_TEST( testProjectMatrixQuad4 );
488  CPPUNIT_TEST( testProjectMatrixTri3 );
489 #endif // LIBMESH_DIM > 1
490 #if LIBMESH_DIM > 2
491  CPPUNIT_TEST( testProjectMatrixHex8 );
492  CPPUNIT_TEST( testProjectMatrixTet4 );
493 #endif // LIBMESH_DIM > 2
494 #endif // LIBMESH_HAVE_PETSC
495 #endif // LIBMESH_HAVE_METAPHYSICL
496 #endif // LIBMESH_ENABLE_AMR
497 
498  CPPUNIT_TEST_SUITE_END();
499 
500 private:
501  void tripleValueTest (const Point & p,
502  const TransientExplicitSystem & sys,
503  const PointLocatorBase & locator,
504  std::set<subdomain_id_type> & u_subdomains,
505  std::set<subdomain_id_type> & v_subdomains,
506  std::set<subdomain_id_type> & w_subdomains,
507  const Parameters & param)
508  {
509  const Elem * elem = locator(p);
510  subdomain_id_type sbd_id = elem ? elem->subdomain_id() : 0;
511  TestCommWorld->max(sbd_id);
512 
513  if (u_subdomains.count(sbd_id))
514  {
515  LIBMESH_ASSERT_NUMBERS_EQUAL(cubic_test(p,param,"",""),
516  sys.point_value(0,p),
517  TOLERANCE*TOLERANCE*10);
518  LIBMESH_ASSERT_NUMBERS_EQUAL
519  (cubic_test(p,param,"","") + Number(10),
520  sys.point_value(0,p,sys.old_local_solution),
521  TOLERANCE*TOLERANCE*100);
522  LIBMESH_ASSERT_NUMBERS_EQUAL
523  (cubic_test(p,param,"","") + Number(20),
524  sys.point_value(0,p,sys.older_local_solution),
525  TOLERANCE*TOLERANCE*100);
526  }
527  if (v_subdomains.count(sbd_id))
528  {
529  LIBMESH_ASSERT_NUMBERS_EQUAL
530  (new_linear_test(p,param,"",""), sys.point_value(1,p),
531  TOLERANCE*TOLERANCE*10);
532  LIBMESH_ASSERT_NUMBERS_EQUAL
533  (new_linear_test(p,param,"","") + Number(10),
534  sys.point_value(1,p,sys.old_local_solution),
535  TOLERANCE*TOLERANCE*100);
536  LIBMESH_ASSERT_NUMBERS_EQUAL
537  (new_linear_test(p,param,"","") + Number(20),
538  sys.point_value(1,p,sys.older_local_solution),
539  TOLERANCE*TOLERANCE*100);
540  }
541  if (w_subdomains.count(sbd_id))
542  {
543  LIBMESH_ASSERT_NUMBERS_EQUAL
544  (disc_thirds_test(p,param,"",""), sys.point_value(2,p),
545  TOLERANCE*TOLERANCE*10);
546  LIBMESH_ASSERT_NUMBERS_EQUAL
547  (disc_thirds_test(p,param,"","") + Number(10),
548  sys.point_value(2,p,sys.old_local_solution),
549  TOLERANCE*TOLERANCE*100);
550  LIBMESH_ASSERT_NUMBERS_EQUAL
551  (disc_thirds_test(p,param,"","") + Number(20),
552  sys.point_value(2,p,sys.older_local_solution),
553  TOLERANCE*TOLERANCE*100);
554  }
555  }
556 
557 public:
558  void setUp()
559  {}
560 
561  void tearDown()
562  {}
563 
564 
566  EquationSystems & es)
567  {
568  ExplicitSystem &sys =
569  es.add_system<ExplicitSystem> ("Simple");
570 
571  sys.add_variable("u", FIRST);
572 
574  10,
575  0., 1.,
576  EDGE3);
577 
578  return sys;
579  }
580 
581 
583  {
585  EquationSystems es(mesh);
586  ExplicitSystem &sys =
587  es.add_system<ExplicitSystem> ("100KVars");
588 
589  dof_id_type n_dofs = 100000;
590 
591  // This takes 16 seconds in opt mode for me, 200 in dbg!?
592  /*
593  for (auto i : make_range(n_dofs))
594  sys.add_variable(std::to_string(i), FIRST);
595  */
596 
597  std::vector<std::string> var_names(n_dofs);
598  for (auto i : make_range(n_dofs))
599  var_names[i] = std::to_string(i);
600 
601  sys.add_variables(var_names, FIRST);
602 
604  4,
605  0., 1.,
606  EDGE3);
607 
608  es.init();
609 
610  CPPUNIT_ASSERT_EQUAL(sys.n_dofs(), n_dofs*5);
611  for (const Node * node : mesh.node_ptr_range())
612  CPPUNIT_ASSERT_EQUAL(dof_id_type(node->n_vars(0)), n_dofs);
613 
614  std::vector<dof_id_type> each = sys.get_dof_map().n_dofs_per_processor(888);
615  CPPUNIT_ASSERT_EQUAL(std::accumulate(each.begin(), each.end(), dof_id_type(0)), dof_id_type(5));
616  CPPUNIT_ASSERT_EQUAL(sys.get_dof_map().n_dofs(888), dof_id_type(5));
617  }
618 
619 
621  {
623  EquationSystems es(mesh);
624  ExplicitSystem & sys = simpleSetup(mesh, es);
625  es.init();
626 
627  auto & late_vec = sys.add_vector("late");
628 
629  CPPUNIT_ASSERT_EQUAL(sys.n_dofs(), dof_id_type(11));
630 
631  // late_vec should be initialized
632  CPPUNIT_ASSERT_EQUAL(late_vec.size(), dof_id_type(11));
633  CPPUNIT_ASSERT_EQUAL(late_vec.local_size(), sys.solution->local_size());
634  }
635 
636 
638  {
640  EquationSystems es(mesh);
641  ExplicitSystem & sys = simpleSetup(mesh, es);
642 
643  sys.add_vector("late", /* projections = */ false);
644  CPPUNIT_ASSERT_EQUAL(sys.vector_preservation("late"), false);
645 
646  sys.add_vector("late");
647  CPPUNIT_ASSERT_EQUAL(sys.vector_preservation("late"), true);
648  }
649 
650 
652  {
653  // Vector types are all pretty much equivalent in serial.
654  if (TestCommWorld->size() == 1)
655  return;
656 
658  EquationSystems es(mesh);
659  ExplicitSystem & sys = simpleSetup(mesh, es);
660 
661  auto & late_vec = sys.add_vector("late");
662  CPPUNIT_ASSERT_EQUAL(late_vec.type(), PARALLEL);
663  CPPUNIT_ASSERT_EQUAL(sys.vector_preservation("late"), true);
664 
665  // We should never downgrade projection settings, so "false"
666  // should be safely ignored here
667  sys.add_vector("late", false, GHOSTED);
668  CPPUNIT_ASSERT_EQUAL(late_vec.type(), GHOSTED);
669  CPPUNIT_ASSERT_EQUAL(sys.vector_preservation("late"), true);
670 
671  // We should never downgrade storage settings, so this should be a
672  // no-op.
673  sys.add_vector("late", true, PARALLEL);
674  CPPUNIT_ASSERT_EQUAL(late_vec.type(), GHOSTED);
675  CPPUNIT_ASSERT_EQUAL(sys.vector_preservation("late"), true);
676  }
677 
678 
680  {
681  // Vector types are all pretty much equivalent in serial.
682  if (TestCommWorld->size() == 1)
683  return;
684 
686  EquationSystems es(mesh);
687  ExplicitSystem & sys = simpleSetup(mesh, es);
688 
689  auto & late_vec = sys.add_vector("late");
690  CPPUNIT_ASSERT_EQUAL(late_vec.type(), PARALLEL);
691  CPPUNIT_ASSERT_EQUAL(sys.vector_preservation("late"), true);
692 
693  es.init();
694 
695  auto & dof_map = sys.get_dof_map();
696 
697  // Set some data to make sure it's preserved
698  CPPUNIT_ASSERT_EQUAL(sys.n_dofs(), dof_id_type(11));
699  for (auto i : make_range(dof_map.first_dof(),
700  dof_map.end_dof()))
701  late_vec.set(i, 2.0*i);
702  late_vec.close();
703 
704  sys.add_vector("late", false, GHOSTED);
705  CPPUNIT_ASSERT_EQUAL(late_vec.type(), GHOSTED);
706 
707  std::vector<dof_id_type> dof_indices;
708  for (auto & elem : mesh.active_local_element_ptr_range())
709  {
710  dof_map.dof_indices (elem, dof_indices);
711 
712  for (auto d : dof_indices)
713  CPPUNIT_ASSERT_EQUAL(late_vec(d), Number(2.0*d));
714  }
715  }
716 
717 
718 
719  void testProjectLine(const ElemType elem_type)
720  {
722 
723  EquationSystems es(mesh);
725  es.add_system<TransientExplicitSystem> ("SimpleSystem");
726 
727  std::set<subdomain_id_type> u_subdomains {0, 1, 4, 5},
728  v_subdomains {1, 2, 3, 4},
729  w_subdomains {0, 1, 2, 3, 4};
730 
731  sys.add_variable("u", THIRD, HIERARCHIC, &u_subdomains);
732  sys.add_variable("v", FIRST, LAGRANGE, &v_subdomains);
733  sys.add_variable("w", CONSTANT, MONOMIAL, &w_subdomains);
734 
736  6,
737  0., 1.,
738  elem_type);
739 
740  for (auto & elem : mesh.element_ptr_range())
741  elem->subdomain_id() = elem->id();
742 
743  es.init();
744  TripleFunction tfunc;
745  sys.project_solution(&tfunc);
746  tfunc.offset = 10;
747  sys.project_vector(*sys.old_local_solution, &tfunc);
748  tfunc.offset = 20;
749  sys.project_vector(*sys.older_local_solution, &tfunc);
750 
751  std::unique_ptr<PointLocatorBase> locator = mesh.sub_point_locator();
752  locator->enable_out_of_mesh_mode();
753  for (Real x = 0.1; x < 1; x += 0.2)
754  tripleValueTest(Point(x), sys, *locator,
755  u_subdomains, v_subdomains, w_subdomains,
756  es.parameters);
757 
758 #ifdef LIBMESH_ENABLE_AMR
759  for (auto & elem : mesh.element_ptr_range())
760  if ((elem->id()/2)%2)
761  elem->set_refinement_flag(Elem::REFINE);
762  es.reinit();
763 
764  locator = mesh.sub_point_locator();
765  locator->enable_out_of_mesh_mode();
766  for (Real x = 0.1; x < 1; x += 0.2)
767  tripleValueTest(Point(x), sys, *locator,
768  u_subdomains, v_subdomains, w_subdomains,
769  es.parameters);
770 #endif
771  }
772 
773  void test2DProjectVectorFE(const ElemType elem_type)
774  {
776 
777  EquationSystems es(mesh);
779  es.add_system<TransientExplicitSystem> ("SimpleSystem");
780 
781  auto u_var = sys.add_variable("u", Elem::type_to_default_order_map[elem_type], LAGRANGE_VEC);
782 
784  1, 1,
785  0., 1., 0., 1.,
786  elem_type);
787 
788  es.init();
789 
790  // Manually set-up the solution because I'm too lazy to set-up all the generic
791  // function projection code right now
792  for (const auto & node : mesh.local_node_ptr_range())
793  {
794  for (unsigned int i : make_range(Elem::type_to_dim_map[elem_type]))
795  {
796  auto dof_index = node->dof_number(sys.number(), u_var, i);
797  sys.solution->set(dof_index, (*node)(i));
798  }
799  }
800 
801  // After setting values, we need to assemble
802  sys.solution->close();
803 
804 
805 #ifdef LIBMESH_ENABLE_AMR
806  for (auto & elem : mesh.element_ptr_range())
807  elem->set_refinement_flag(Elem::REFINE);
808  es.reinit();
809 #endif
810 
811  for (const auto & node : mesh.local_node_ptr_range())
812  {
813  // 2D element here
814  for (unsigned int i : make_range(Elem::type_to_dim_map[elem_type]))
815  {
816  auto dof_index = node->dof_number(sys.number(), u_var, i);
817  auto value = (*sys.solution)(dof_index);
818  LIBMESH_ASSERT_NUMBERS_EQUAL(value, (*node)(i), TOLERANCE*TOLERANCE);
819  }
820  }
821  }
822 
823  void test3DProjectVectorFE(const ElemType elem_type)
824  {
826 
827  EquationSystems es(mesh);
829  es.add_system<TransientExplicitSystem> ("SimpleSystem");
830 
831  auto u_var = sys.add_variable
833 
835  1, 1, 1,
836  0., 1., 0., 1., 0., 1.,
837  elem_type);
838 
839  es.init();
840 
841  // Manually set-up the solution because I'm too lazy to set-up all the generic
842  // function projection code right now
843  for (const auto & node : mesh.local_node_ptr_range())
844  {
845  for (unsigned int i : make_range(Elem::type_to_dim_map[elem_type]))
846  {
847  auto dof_index = node->dof_number(sys.number(), u_var, i);
848  sys.solution->set(dof_index, (*node)(i));
849  }
850  }
851 
852  // After setting values, we need to assemble
853  sys.solution->close();
854 
855 
856 #ifdef LIBMESH_ENABLE_AMR
857  for (auto & elem : mesh.element_ptr_range())
858  elem->set_refinement_flag(Elem::REFINE);
859  es.reinit();
860 #endif
861 
862  for (const auto & node : mesh.local_node_ptr_range())
863  {
864  for (unsigned int i : make_range(Elem::type_to_dim_map[elem_type]))
865  {
866  auto dof_index = node->dof_number(sys.number(), u_var, i);
867  auto value = (*sys.solution)(dof_index);
868  LIBMESH_ASSERT_NUMBERS_EQUAL(value, (*node)(i), TOLERANCE*TOLERANCE);
869  }
870  }
871  }
872 
873  void testProjectSquare(const ElemType elem_type)
874  {
876 
877  EquationSystems es(mesh);
879  es.add_system<TransientExplicitSystem> ("SimpleSystem");
880 
881  std::set<subdomain_id_type> u_subdomains {0, 1, 4, 5},
882  v_subdomains {1, 2, 3, 4},
883  w_subdomains {0, 1, 2, 3, 4};
884 
885  sys.add_variable("u", THIRD, HIERARCHIC, &u_subdomains);
886  sys.add_variable("v", FIRST, LAGRANGE, &v_subdomains);
887  sys.add_variable("w", CONSTANT, MONOMIAL, &w_subdomains);
888 
890  3, 3,
891  0., 1., 0., 1.,
892  elem_type);
893 
894  for (auto & elem : mesh.element_ptr_range())
895  elem->subdomain_id() = elem->id()/2;
896 
897  es.init();
898  TripleFunction tfunc;
899  sys.project_solution(&tfunc);
900  tfunc.offset = 10;
901  sys.project_vector(*sys.old_local_solution, &tfunc);
902  tfunc.offset = 20;
903  sys.project_vector(*sys.older_local_solution, &tfunc);
904 
905  std::unique_ptr<PointLocatorBase> locator = mesh.sub_point_locator();
906  locator->enable_out_of_mesh_mode();
907  for (Real x = 0.1; x < 1; x += 0.2)
908  for (Real y = 0.1; y < 1; y += 0.2)
909  tripleValueTest(Point(x,y), sys, *locator,
910  u_subdomains, v_subdomains, w_subdomains,
911  es.parameters);
912 
913 #ifdef LIBMESH_ENABLE_AMR
914  for (auto & elem : mesh.element_ptr_range())
915  if ((elem->id()/2)%2)
916  elem->set_refinement_flag(Elem::REFINE);
917  es.reinit();
918 
919  locator = mesh.sub_point_locator();
920  locator->enable_out_of_mesh_mode();
921  for (Real x = 0.1; x < 1; x += 0.2)
922  for (Real y = 0.1; y < 1; y += 0.2)
923  tripleValueTest(Point(x,y), sys, *locator,
924  u_subdomains, v_subdomains, w_subdomains,
925  es.parameters);
926 #endif
927  }
928 
929  void testProjectCube(const ElemType elem_type)
930  {
932 
933  EquationSystems es(mesh);
935  es.add_system<TransientExplicitSystem> ("SimpleSystem");
936 
937  std::set<subdomain_id_type> u_subdomains {0, 1, 4, 5},
938  v_subdomains {1, 2, 3, 4},
939  w_subdomains {0, 1, 2, 3, 4};
940 
941  sys.add_variable("u", THIRD, HIERARCHIC, &u_subdomains);
942  sys.add_variable("v", FIRST, LAGRANGE, &v_subdomains);
943  sys.add_variable("w", CONSTANT, MONOMIAL, &w_subdomains);
944 
946  3, 3, 3,
947  0., 1., 0., 1., 0., 1.,
948  elem_type);
949 
950  for (auto & elem : mesh.element_ptr_range())
951  elem->subdomain_id() = elem->id()/6;
952 
953  es.init();
954  TripleFunction tfunc;
955  sys.project_solution(&tfunc);
956  tfunc.offset = 10;
957  sys.project_vector(*sys.old_local_solution, &tfunc);
958  tfunc.offset = 20;
959  sys.project_vector(*sys.older_local_solution, &tfunc);
960 
961  std::unique_ptr<PointLocatorBase> locator = mesh.sub_point_locator();
962  locator->enable_out_of_mesh_mode();
963  for (Real x = 0.1; x < 1; x += 0.2)
964  for (Real y = 0.1; y < 1; y += 0.2)
965  for (Real z = 0.1; z < 1; z += 0.2)
966  tripleValueTest(Point(x,y,z), sys, *locator,
967  u_subdomains, v_subdomains, w_subdomains,
968  es.parameters);
969 
970  #ifdef LIBMESH_ENABLE_AMR
971  for (auto & elem : mesh.element_ptr_range())
972  if ((elem->id()/2)%2)
973  elem->set_refinement_flag(Elem::REFINE);
974  es.reinit();
975 
976  locator = mesh.sub_point_locator();
977  locator->enable_out_of_mesh_mode();
978  for (Real x = 0.1; x < 1; x += 0.2)
979  for (Real y = 0.1; y < 1; y += 0.2)
980  for (Real z = 0.1; z < 1; z += 0.2)
981  tripleValueTest(Point(x,y,z), sys, *locator,
982  u_subdomains, v_subdomains, w_subdomains,
983  es.parameters);
984  #endif
985  }
986 
988  {
989  // The source mesh needs to exist everywhere it's queried, so we
990  // use a ReplicatedMesh
992 
993  EquationSystems es(mesh);
994  System &sys = es.add_system<System> ("SimpleSystem");
995  sys.add_variable("u", THIRD, MONOMIAL);
996 
998  3, 3, 3,
999  0., 1., 0., 1., 0., 1.,
1000  elem_type);
1001 
1002  es.init();
1003  sys.project_solution(cubic_test, nullptr, es.parameters);
1004 
1005  std::vector<unsigned int> variables;
1006  sys.get_all_variable_numbers(variables);
1007  std::sort(variables.begin(),variables.end());
1008 
1009  std::unique_ptr< NumericVector<Number> > mesh_function_vector =
1011  mesh_function_vector->init(sys.n_dofs(), false, SERIAL);
1012  sys.solution->localize( *mesh_function_vector );
1013 
1014  MeshFunction mesh_function(es,
1015  *mesh_function_vector,
1016  sys.get_dof_map(),
1017  variables);
1018  mesh_function.init();
1019 
1020  // Make a second system and project onto it using a MeshFunction
1021  Mesh proj_mesh(*TestCommWorld);
1022  EquationSystems proj_es(proj_mesh);
1023 
1024  System &proj_sys = proj_es.add_system<System> ("ProjectionSystem");
1025 
1026  // use 3rd order again so we can expect exact results
1027  proj_sys.add_variable("u", THIRD, HIERARCHIC);
1028 
1030  5, 5, 5,
1031  0., 1., 0., 1., 0., 1.,
1032  elem_type);
1033 
1034  proj_es.init();
1035  proj_sys.project_solution(&mesh_function);
1036 
1037  for (Real x = 0.1; x < 1; x += 0.2)
1038  for (Real y = 0.1; y < 1; y += 0.2)
1039  for (Real z = 0.1; z < 1; z += 0.2)
1040  {
1041  Point p(x,y,z);
1042  LIBMESH_ASSERT_NUMBERS_EQUAL
1043  (cubic_test(p,es.parameters,"",""),
1044  proj_sys.point_value(0,p), TOLERANCE*TOLERANCE);
1045  }
1046  }
1047 
1049  {
1050  LOG_UNIT_TEST;
1051 
1053 
1054  // const boundary_id_type BOUNDARY_ID_MIN_Z = 0;
1055  const boundary_id_type BOUNDARY_ID_MIN_Y = 1;
1056  const boundary_id_type BOUNDARY_ID_MAX_X = 2;
1057  const boundary_id_type BOUNDARY_ID_MAX_Y = 3;
1058  const boundary_id_type BOUNDARY_ID_MIN_X = 4;
1059  const boundary_id_type BOUNDARY_ID_MAX_Z = 5;
1060  const boundary_id_type NODE_BOUNDARY_ID = 10;
1061  const boundary_id_type EDGE_BOUNDARY_ID = 20;
1062  const boundary_id_type SIDE_BOUNDARY_ID = BOUNDARY_ID_MIN_X;
1063 
1064  EquationSystems es(mesh);
1065  System &sys = es.add_system<System> ("SimpleSystem");
1066  unsigned int u_var = sys.add_variable("u", FIRST, LAGRANGE);
1067 
1069  3, 3, 3,
1070  0., 1., 0., 1., 0., 1.,
1071  HEX8);
1072 
1073  // Count the number of nodes on SIDE_BOUNDARY_ID
1074  std::set<dof_id_type> projected_nodes_set;
1075 
1076  for (const auto & elem : mesh.element_ptr_range())
1077  {
1078  for (auto side : elem->side_index_range())
1079  {
1080  std::vector<boundary_id_type> vec_to_fill;
1081  mesh.get_boundary_info().boundary_ids(elem, side, vec_to_fill);
1082 
1083  auto vec_it = std::find(vec_to_fill.begin(), vec_to_fill.end(), SIDE_BOUNDARY_ID);
1084  if (vec_it != vec_to_fill.end())
1085  {
1086  for (unsigned int node_index=0; node_index<elem->n_nodes(); node_index++)
1087  {
1088  if( elem->is_node_on_side(node_index, side))
1089  {
1090  projected_nodes_set.insert(elem->node_id(node_index));
1091  }
1092  }
1093  }
1094  }
1095  }
1096 
1097  // Also add some edge and node boundary IDs
1098  for (const auto & elem : mesh.element_ptr_range())
1099  {
1100  unsigned int
1101  side_max_x = 0, side_min_y = 0,
1102  side_max_y = 0, side_max_z = 0;
1103 
1104  bool
1105  found_side_max_x = false, found_side_max_y = false,
1106  found_side_min_y = false, found_side_max_z = false;
1107 
1108  for (auto side : elem->side_index_range())
1109  {
1110  if (mesh.get_boundary_info().has_boundary_id(elem, side, BOUNDARY_ID_MAX_X))
1111  {
1112  side_max_x = side;
1113  found_side_max_x = true;
1114  }
1115 
1116  if (mesh.get_boundary_info().has_boundary_id(elem, side, BOUNDARY_ID_MIN_Y))
1117  {
1118  side_min_y = side;
1119  found_side_min_y = true;
1120  }
1121 
1122  if (mesh.get_boundary_info().has_boundary_id(elem, side, BOUNDARY_ID_MAX_Y))
1123  {
1124  side_max_y = side;
1125  found_side_max_y = true;
1126  }
1127 
1128  if (mesh.get_boundary_info().has_boundary_id(elem, side, BOUNDARY_ID_MAX_Z))
1129  {
1130  side_max_z = side;
1131  found_side_max_z = true;
1132  }
1133  }
1134 
1135  // If elem has sides on boundaries
1136  // BOUNDARY_ID_MAX_X, BOUNDARY_ID_MAX_Y, BOUNDARY_ID_MAX_Z
1137  // then let's set a node boundary condition
1138  if (found_side_max_x && found_side_max_y && found_side_max_z)
1139  for (auto n : elem->node_index_range())
1140  if (elem->is_node_on_side(n, side_max_x) &&
1141  elem->is_node_on_side(n, side_max_y) &&
1142  elem->is_node_on_side(n, side_max_z))
1143  {
1144  projected_nodes_set.insert(elem->node_id(n));
1145  mesh.get_boundary_info().add_node(elem->node_ptr(n), NODE_BOUNDARY_ID);
1146  }
1147 
1148  // If elem has sides on boundaries
1149  // BOUNDARY_ID_MAX_X and BOUNDARY_ID_MIN_Y
1150  // then let's set an edge boundary condition
1151  if (found_side_max_x && found_side_min_y)
1152  for (auto e : elem->edge_index_range())
1153  if (elem->is_edge_on_side(e, side_max_x) &&
1154  elem->is_edge_on_side(e, side_min_y))
1155  {
1156  mesh.get_boundary_info().add_edge(elem, e, EDGE_BOUNDARY_ID);
1157 
1158  for (unsigned int node_index=0; node_index<elem->n_nodes(); node_index++)
1159  {
1160  if (elem->is_node_on_edge(node_index, e))
1161  {
1162  projected_nodes_set.insert(elem->node_id(node_index));
1163  }
1164  }
1165  }
1166  }
1167 
1168  es.init();
1169 
1170  sys.solution->add(1.0);
1171 
1172  std::set<boundary_id_type> boundary_ids;
1173  boundary_ids.insert(NODE_BOUNDARY_ID);
1174  boundary_ids.insert(EDGE_BOUNDARY_ID);
1175  boundary_ids.insert(SIDE_BOUNDARY_ID);
1176  std::vector<unsigned int> variables;
1177  variables.push_back(u_var);
1178  ZeroFunction<> zf;
1179  sys.boundary_project_solution(boundary_ids, variables, &zf);
1180 
1181  // On a distributed mesh we may not have every node on every
1182  // processor
1183  TestCommWorld->set_union(projected_nodes_set);
1184 
1185  // We set the solution to be 1 everywhere and then zero on specific boundary
1186  // nodes, so the final l1 norm of the solution is the difference between the
1187  // number of nodes in the mesh and the number of nodes we zero on.
1188  Real ref_l1_norm = static_cast<Real>(mesh.n_nodes()) - static_cast<Real>(projected_nodes_set.size());
1189 
1190  LIBMESH_ASSERT_FP_EQUAL(sys.solution->l1_norm(), ref_l1_norm, TOLERANCE*TOLERANCE);
1191  }
1192 
1194  {
1195  LOG_UNIT_TEST;
1196 
1198 
1200  1,
1201  0,
1202  0,
1203  0., 1.,
1204  0., 0.,
1205  0., 0.,
1206  EDGE2);
1207 
1208  Point new_point_a(2.);
1209  Point new_point_b(3.);
1210  Node* new_node_a = mesh.add_point( new_point_a );
1211  Node* new_node_b = mesh.add_point( new_point_b );
1212  auto new_edge_elem = mesh.add_elem(Elem::build(EDGE2));
1213  new_edge_elem->set_node(0, new_node_a);
1214  new_edge_elem->set_node(1, new_node_b);
1215 
1216  mesh.elem_ref(0).subdomain_id() = 10;
1217  mesh.elem_ref(1).subdomain_id() = 10;
1218 
1219  // Add NodeElems for coupling purposes
1220  auto node_elem_1 = mesh.add_elem(Elem::build(NODEELEM));
1221  node_elem_1->set_node(0, mesh.elem_ref(0).node_ptr(1));
1222  auto node_elem_2 = mesh.add_elem(Elem::build(NODEELEM));
1223  node_elem_2->set_node(0, new_node_a);
1224 
1226 
1227  // Create an equation systems object.
1228  EquationSystems equation_systems (mesh);
1229  LinearImplicitSystem & system =
1230  equation_systems.add_system<LinearImplicitSystem> ("test");
1231 
1232  system.add_variable ("u", libMesh::FIRST);
1233  system.add_variable ("v", libMesh::FIRST);
1234  system.add_variable ("w", libMesh::FIRST);
1235 
1236  std::set<subdomain_id_type> theta_subdomains;
1237  theta_subdomains.insert(10);
1238  system.add_variable ("theta_x", libMesh::FIRST, &theta_subdomains);
1239  system.add_variable ("theta_y", libMesh::FIRST, &theta_subdomains);
1240  system.add_variable ("theta_z", libMesh::FIRST, &theta_subdomains);
1241 
1243 
1244  AugmentSparsityOnNodes augment_sparsity(mesh);
1245  system.get_dof_map().add_coupling_functor(augment_sparsity);
1246 
1247  // LASPACK GMRES + ILU defaults don't like this problem, but it's
1248  // small enough to just use a simpler iteration.
1251 
1252  equation_systems.init ();
1253 
1254  system.solve();
1255 
1256  // We set the solution to be 1 everywhere, so the final l1 norm of the
1257  // solution is the product of the number of variables and number of nodes.
1258  Real ref_l1_norm = static_cast<Real>(mesh.n_nodes() * system.n_vars());
1259 
1260  LIBMESH_ASSERT_FP_EQUAL(system.solution->l1_norm(), ref_l1_norm, TOLERANCE*TOLERANCE);
1261  }
1262 
1263 
1265  {
1266  LOG_UNIT_TEST;
1267 
1269 
1271  1,
1272  0,
1273  0,
1274  0., 1.,
1275  0., 0.,
1276  0., 0.,
1277  EDGE2);
1278 
1279  Point new_point_a(2.);
1280  Point new_point_b(3.);
1281  Node* new_node_a = mesh.add_point( new_point_a );
1282  Node* new_node_b = mesh.add_point( new_point_b );
1283  auto new_edge_elem = mesh.add_elem(Elem::build(EDGE2));
1284  new_edge_elem->set_node(0, new_node_a);
1285  new_edge_elem->set_node(1, new_node_b);
1286 
1287  mesh.elem_ref(0).subdomain_id() = 10;
1288  mesh.elem_ref(1).subdomain_id() = 10;
1289 
1291 
1292  // Create an equation systems object.
1293  EquationSystems equation_systems (mesh);
1294 
1295  // Set some parameters to the equation system that would cause a failed test
1296  equation_systems.parameters.set<unsigned int>("linear solver maximum iterations") = 0;
1297 
1298  // Setup Linear Implicit system
1299  LinearImplicitSystem & li_system =
1300  equation_systems.add_system<LinearImplicitSystem> ("test");
1301 
1302  // We must use a discontinuous variable type in this test or
1303  // else the sparsity pattern will not be correct
1304  li_system.add_variable("u", FIRST, L2_LAGRANGE);
1305 
1307  5, 5, 5,
1308  0., 1., 0., 1., 0., 1.,
1309  HEX8);
1310 
1311  li_system.attach_assemble_function (assembly_with_dg_fem_context);
1312  li_system.get_linear_solver()->set_solver_type(GMRES);
1313  // Need 5 iterations, dont overdo the preconditioning
1314  li_system.get_linear_solver()->set_preconditioner_type(IDENTITY_PRECOND);
1315 
1316  // Set some parameters to the system that work for the solve
1317  li_system.parameters.set<unsigned int>("linear solver maximum iterations") = 5;
1318  li_system.parameters.set<Real>("linear solver tolerance") = 1e-100;
1319 
1320  // Need to init before we can access the system matrix
1321  equation_systems.init ();
1322 
1323  // See the solve pass, indicating system parameters are used over equation system parameters
1324  li_system.solve();
1325 
1326  // Check that the number of iterations from the systems got obeyed
1327  CPPUNIT_ASSERT_EQUAL(li_system.n_linear_iterations(), 5u);
1328 }
1329 
1331  {
1332  LOG_UNIT_TEST;
1333 
1335 
1336  EquationSystems es(mesh);
1337  System &sys = es.add_system<LinearImplicitSystem> ("test");
1338 
1339  // We must use a discontinuous variable type in this test or
1340  // else the sparsity pattern will not be correct
1341  sys.add_variable("u", FIRST, L2_LAGRANGE);
1342 
1344  5, 5, 5,
1345  0., 1., 0., 1., 0., 1.,
1346  HEX8);
1347 
1348  es.init();
1350  sys.solve();
1351 
1352  // We don't actually assert anything in this test. We just want to check that
1353  // the assembly and solve do not encounter any errors.
1354  }
1355 
1357  {
1358  LOG_UNIT_TEST;
1359 
1361 
1363  4,
1364  4,
1365  0,
1366  0., 1.,
1367  0., 1.,
1368  0., 0.,
1369  QUAD4);
1370 
1371  for (const auto & elem : mesh.element_ptr_range())
1372  {
1373  Point c = elem->vertex_average();
1374  if (c(0) <= 0.5 && c(1) <= 0.5)
1375  elem->subdomain_id() = 0;
1376  else
1377  elem->subdomain_id() = 1;
1378  }
1379 
1381 
1382  // Create an equation systems object.
1383  EquationSystems equation_systems (mesh);
1384  ExplicitSystem& system =
1385  equation_systems.add_system<LinearImplicitSystem> ("test");
1386 
1387  std::set<subdomain_id_type> block0;
1388  std::set<subdomain_id_type> block1;
1389  block0.insert(0);
1390  block1.insert(1);
1391  auto u0 = system.add_variable ("u0", libMesh::FIRST, &block0);
1392  auto u1 = system.add_variable ("u1", libMesh::FIRST, &block1);
1393  equation_systems.init();
1394 
1395  std::vector<dof_id_type> u0_dofs;
1396  system.get_dof_map().local_variable_indices(u0_dofs, mesh, u0);
1397  std::vector<dof_id_type> u1_dofs;
1398  system.get_dof_map().local_variable_indices(u1_dofs, mesh, u1);
1399 
1400  std::set<dof_id_type> sys_u0_dofs;
1401  system.local_dof_indices(u0, sys_u0_dofs);
1402  std::set<dof_id_type> sys_u1_dofs;
1403  system.local_dof_indices(u1, sys_u1_dofs);
1404 
1405  // Get local indices from other processors too
1406  mesh.comm().allgather(u0_dofs);
1407  mesh.comm().allgather(u1_dofs);
1408  mesh.comm().set_union(sys_u0_dofs);
1409  mesh.comm().set_union(sys_u1_dofs);
1410 
1411  const std::size_t c9 = 9;
1412  const std::size_t c21 = 21;
1413  CPPUNIT_ASSERT_EQUAL(c9, u0_dofs.size());
1414  CPPUNIT_ASSERT_EQUAL(c21, u1_dofs.size());
1415  CPPUNIT_ASSERT_EQUAL(c9, sys_u0_dofs.size());
1416  CPPUNIT_ASSERT_EQUAL(c21, sys_u1_dofs.size());
1417  }
1418 
1419 #ifdef LIBMESH_ENABLE_AMR
1420 #ifdef LIBMESH_HAVE_METAPHYSICL
1421 #ifdef LIBMESH_HAVE_PETSC
1422  void testProjectMatrix1D(const ElemType elem_type)
1423  {
1424  // Use ReplicatedMesh to get consistent child element node
1425  // numbering during refinement
1427 
1428  // fix the node numbering to resolve dof_id numbering issues in parallel tests
1429  mesh.allow_renumbering(false);
1430 
1431  // init a simple 1d system
1432  EquationSystems es(mesh);
1433  System &sys = es.add_system<System> ("SimpleSystem");
1434  sys.add_variable("u", FIRST, LAGRANGE);
1435 
1437  4, 0., 1.,
1438  elem_type);
1439 
1440  es.init();
1441 
1442  // static set of coarse nodes / order of fine grid nodes from x=0 to x=1 going left to right
1443  std::set<dof_id_type> coarse_nodes({0,1,2,3,4});
1444  std::vector<dof_id_type> node_order_f({0,5,1,6,2,7,3,8,4});
1445 
1446  // stash number of dofs on coarse grid for projection sizing
1447  int n_old_dofs = sys.n_dofs();
1448 
1449  // save old coarse dof_ids in order of coarse nodes
1450  std::map <dof_id_type, dof_id_type> node2dof_c;
1451  for ( const auto & node : mesh.node_ptr_range() )
1452  {
1453  dof_id_type cdof_id = node->dof_number(0,0,0);
1454  node2dof_c.insert( std::pair<dof_id_type,dof_id_type>( node->id() , cdof_id) );
1455  }
1456 
1457  // refine the mesh so we can utilize old_dof_indices for projection_matrix
1458  MeshRefinement mr(mesh);
1459  mr.uniformly_refine(1);
1461 
1462  // fine node to dof map
1463  std::map <dof_id_type, dof_id_type> node2dof_f;
1464  for ( const auto & node : mesh.local_node_ptr_range() )
1465  {
1466  dof_id_type fdof_id = node->dof_number(0,0,0);
1467  node2dof_f.insert( std::pair<dof_id_type,dof_id_type>(node->id() , fdof_id) );
1468  }
1469 
1470  // local and global projection_matrix sizes infos
1471  int n_new_dofs = sys.n_dofs();
1472  int n_new_dofs_local = sys.get_dof_map().n_local_dofs();
1473  int ndofs_old_first = sys.get_dof_map().first_old_dof();
1474  int ndofs_old_end = sys.get_dof_map().end_old_dof();
1475  int n_old_dofs_local = ndofs_old_end - ndofs_old_first;
1476 
1477  // init and compute the projection matrix using GenericProjector
1478  std::unique_ptr<SparseMatrix<Number> > proj_mat_ptr =
1480  SparseMatrix<Number> & proj_mat = *proj_mat_ptr;
1481  proj_mat.init(n_new_dofs, n_old_dofs, n_new_dofs_local, n_old_dofs_local);
1482  sys.projection_matrix(proj_mat);
1483  proj_mat.close();
1484 
1485  // init the gold standard projection matrix
1486  std::unique_ptr<SparseMatrix<Number> > gold_mat_ptr =
1488  SparseMatrix<Number> & gold_mat = *gold_mat_ptr;
1489  gold_mat.init(n_new_dofs, n_old_dofs, n_new_dofs_local, n_old_dofs_local);
1490 
1491  // construct the gold projection matrix using static node numbering as reference info
1492  for ( const auto & node : mesh.local_node_ptr_range() )
1493  {
1494  dof_id_type node_id = node->id();
1495  dof_id_type fdof_id = (node2dof_f.find(node_id))->second;
1496 
1497  if (coarse_nodes.find(node_id) != coarse_nodes.end() )
1498  { //direct inject coarse nodes
1499  if (fdof_id >= gold_mat.row_start() && fdof_id < gold_mat.row_stop())
1500  {
1501  auto cdof_id = node2dof_c.find(node_id);
1502  gold_mat.set(fdof_id, cdof_id->second, 1.0);
1503  }
1504  }
1505  else
1506  { // new nodes with old_dof neighbor contributions
1507  if (fdof_id >= gold_mat.row_start() && fdof_id < gold_mat.row_stop())
1508  {
1509  auto node_loc = std::find(node_order_f.begin(), node_order_f.end(), node_id);
1510  auto node_n = *std::next(node_loc, 1);
1511  auto node_p = *std::prev(node_loc, 1);
1512  auto dof_p = node2dof_c.find(node_p);
1513  auto dof_n = node2dof_c.find(node_n);
1514 
1515  gold_mat.set(fdof_id, dof_p->second, 0.5);
1516  gold_mat.set(fdof_id, dof_n->second, 0.5);
1517  }
1518  }
1519  } // end gold mat build
1520  gold_mat.close();
1521 
1522  // calculate relative difference norm between the two projection matrices
1523  Real gold_norm = gold_mat.linfty_norm();
1524  gold_mat.add(-1.0, proj_mat);
1525  Real diff_norm = gold_mat.linfty_norm();
1526  CPPUNIT_ASSERT(diff_norm/gold_norm < TOLERANCE*TOLERANCE);
1527  }
1528 
1529  void testProjectMatrix2D(const ElemType elem_type)
1530  {
1531  // Use ReplicatedMesh to get consistent child element node
1532  // numbering during refinement
1534 
1535  // fix the node numbering to resolve dof_id numbering issues in parallel tests
1536  mesh.allow_renumbering(false);
1537 
1538  // init a simple 1d system
1539  EquationSystems es(mesh);
1540  System &sys = es.add_system<System> ("SimpleSystem");
1541  sys.add_variable("u", FIRST, LAGRANGE);
1542 
1543  if (elem_type == Utility::string_to_enum<ElemType>("QUAD4"))
1545  2, 2,
1546  0., 1., 0., 1.,
1547  elem_type);
1548  else if (elem_type == Utility::string_to_enum<ElemType>("TRI3"))
1550  1, 1,
1551  0., 1., 0., 1.,
1552  elem_type);
1553 
1554  es.init();
1555 
1556  // static sets of nodes and their neighbors
1557  std::set<dof_id_type> coarse_nodes;
1558  std::map<dof_id_type, std::vector<dof_id_type>> side_nbr_nodes;
1559  std::map<dof_id_type, std::vector<dof_id_type>> int_nbr_nodes;
1560 
1561  // fill neighbor maps based on static node numbering
1562  if (elem_type == Utility::string_to_enum<ElemType>("QUAD4"))
1563  {
1564  coarse_nodes.insert({0,1,2,3,4,5,6,7,8});
1565 
1566  side_nbr_nodes.insert({9, {0,1}});
1567  side_nbr_nodes.insert({14, {1,2}});
1568  side_nbr_nodes.insert({11, {0,3}});
1569  side_nbr_nodes.insert({12, {1,4}});
1570  side_nbr_nodes.insert({16, {2,5}});
1571  side_nbr_nodes.insert({13, {3,4}});
1572  side_nbr_nodes.insert({17, {4,5}});
1573  side_nbr_nodes.insert({19, {3,6}});
1574  side_nbr_nodes.insert({20, {4,7}});
1575  side_nbr_nodes.insert({23, {5,8}});
1576  side_nbr_nodes.insert({21, {6,7}});
1577  side_nbr_nodes.insert({24, {7,8}});
1578 
1579  int_nbr_nodes.insert({10, {0,1,3,4}});
1580  int_nbr_nodes.insert({15, {1,2,4,5}});
1581  int_nbr_nodes.insert({18, {3,4,6,7}});
1582  int_nbr_nodes.insert({22, {4,5,7,8}});
1583  }
1584  else if (elem_type == Utility::string_to_enum<ElemType>("TRI3"))
1585  {
1586  coarse_nodes.insert({0,1,2,3});
1587 
1588  side_nbr_nodes.insert({4, {0,1}});
1589  side_nbr_nodes.insert({5, {0,3}});
1590  side_nbr_nodes.insert({6, {1,3}});
1591  side_nbr_nodes.insert({7, {0,2}});
1592  side_nbr_nodes.insert({8, {2,3}});
1593  }
1594 
1595  // stash number of dofs on coarse grid for projection sizing
1596  int n_old_dofs = sys.n_dofs();
1597 
1598  // save old coarse dof_ids in order of coarse nodes
1599  std::map <dof_id_type, dof_id_type> node2dof_c;
1600  for ( const auto & node : mesh.node_ptr_range() )
1601  {
1602  dof_id_type cdof_id = node->dof_number(0,0,0);
1603  node2dof_c.insert( std::pair<dof_id_type,dof_id_type>( node->id() , cdof_id) );
1604  }
1605 
1606  // refine the mesh so we can utilize old_dof_indices for projection_matrix
1607  MeshRefinement mr(mesh);
1608  mr.uniformly_refine(1);
1610 
1611  // fine node to dof map
1612  std::map <dof_id_type, dof_id_type> node2dof_f;
1613  for ( const auto & node : mesh.local_node_ptr_range() )
1614  {
1615  dof_id_type fdof_id = node->dof_number(0,0,0);
1616  node2dof_f.insert( std::pair<dof_id_type,dof_id_type>(node->id() , fdof_id) );
1617  }
1618 
1619  // local and global projection_matrix sizes infos
1620  int n_new_dofs = sys.n_dofs();
1621  int n_new_dofs_local = sys.get_dof_map().n_local_dofs();
1622  int ndofs_old_first = sys.get_dof_map().first_old_dof();
1623  int ndofs_old_end = sys.get_dof_map().end_old_dof();
1624  int n_old_dofs_local = ndofs_old_end - ndofs_old_first;
1625 
1626  // init and compute the projection matrix using GenericProjector
1627  std::unique_ptr<SparseMatrix<Number> > proj_mat_ptr =
1629  SparseMatrix<Number> & proj_mat = *proj_mat_ptr;
1630  proj_mat.init(n_new_dofs, n_old_dofs, n_new_dofs_local, n_old_dofs_local);
1631  sys.projection_matrix(proj_mat);
1632  proj_mat.close();
1633 
1634  // init the gold standard projection matrix
1635  std::unique_ptr<SparseMatrix<Number> > gold_mat_ptr =
1637  SparseMatrix<Number> & gold_mat = *gold_mat_ptr;
1638  gold_mat.init(n_new_dofs, n_old_dofs, n_new_dofs_local, n_old_dofs_local);
1639 
1640  // construct the gold projection matrix using static node numbering as reference info
1641  for ( const auto & node : mesh.local_node_ptr_range() )
1642  {
1643  dof_id_type node_id = node->id();
1644  dof_id_type fdof_id = (node2dof_f.find(node_id))->second;
1645 
1646  if (coarse_nodes.find(node_id) != coarse_nodes.end() )
1647  { // direct inject coarse nodes
1648  if (fdof_id >= gold_mat.row_start() && fdof_id < gold_mat.row_stop())
1649  {
1650  auto cdof_id = node2dof_c.find(node_id);
1651  gold_mat.set(fdof_id, cdof_id->second, 1.0);
1652  }
1653  }
1654  else if ( side_nbr_nodes.find(node_id) != side_nbr_nodes.end() )
1655  { // new side nodes with old_dof neighbor contributions
1656  if (fdof_id >= gold_mat.row_start() && fdof_id < gold_mat.row_stop())
1657  {
1658  auto node_nbrs = side_nbr_nodes.find(node_id);
1659  for (auto nbr : node_nbrs->second)
1660  {
1661  auto nbr_dof = node2dof_c.find(nbr);
1662  gold_mat.set(fdof_id, nbr_dof->second, 0.5);
1663  }
1664  }
1665  }
1666  else
1667  { // new interior nodes with old_dof neighbor contributions
1668  if (fdof_id >= gold_mat.row_start() && fdof_id < gold_mat.row_stop())
1669  {
1670  auto node_nbrs = int_nbr_nodes.find(node_id);
1671  for (auto nbr : node_nbrs->second)
1672  {
1673  auto nbr_dof = node2dof_c.find(nbr);
1674  gold_mat.set(fdof_id, nbr_dof->second, 0.25);
1675  }
1676  }
1677  }
1678  } // end gold mat build
1679  gold_mat.close();
1680 
1681  // calculate relative difference norm between the two projection matrices
1682  Real gold_norm = gold_mat.linfty_norm();
1683  proj_mat.add(-1.0, gold_mat);
1684  Real diff_norm = proj_mat.linfty_norm();
1685  CPPUNIT_ASSERT(diff_norm/gold_norm < TOLERANCE*TOLERANCE);
1686  }
1687 
1688  void testProjectMatrix3D(const ElemType elem_type)
1689  {
1690  // Use ReplicatedMesh to get consistent child element node
1691  // numbering during refinement
1693 
1694  // fix the node numbering to resolve dof_id numbering issues in parallel tests
1695  mesh.allow_renumbering(false);
1696 
1697  // init a simple 1d system
1698  EquationSystems es(mesh);
1699  System &sys = es.add_system<System> ("SimpleSystem");
1700  sys.add_variable("u", FIRST, LAGRANGE);
1701 
1702  if (elem_type == Utility::string_to_enum<ElemType>("HEX8"))
1704  1, 1, 1,
1705  0., 1., 0., 1., 0., 1.,
1706  elem_type);
1707  else if (elem_type == Utility::string_to_enum<ElemType>("TET4"))
1708  {
1709  // manually build a Tet4 element
1710  mesh.add_point( Point(0,0,0), 0 );
1711  mesh.add_point( Point(1,0,0), 1 );
1712  mesh.add_point( Point(0,1,0), 2 );
1713  mesh.add_point( Point(1./3.,1./3.,1), 3 );
1714 
1715  Elem * elem = mesh.add_elem(Elem::build_with_id(TET4, 0));
1716  elem->set_node(0, mesh.node_ptr(0));
1717  elem->set_node(1, mesh.node_ptr(1));
1718  elem->set_node(2, mesh.node_ptr(2));
1719  elem->set_node(3, mesh.node_ptr(3));
1720 
1722  }
1723  es.init();
1724 
1725  // static sets of nodes and their neighbors
1726  std::set<dof_id_type> coarse_nodes;
1727  std::map<dof_id_type, std::vector<dof_id_type>> side_nbr_nodes;
1728  std::map<dof_id_type, std::vector<dof_id_type>> face_nbr_nodes;
1729  std::map<dof_id_type, std::vector<dof_id_type>> int_nbr_nodes;
1730 
1731  if (elem_type == Utility::string_to_enum<ElemType>("HEX8"))
1732  {
1733  coarse_nodes.insert({0,1,2,3,4,5,6,7});
1734 
1735  // fill neighbor maps based on static node numbering
1736  side_nbr_nodes.insert({8, {0,1}});
1737  side_nbr_nodes.insert({10, {0,2}});
1738  side_nbr_nodes.insert({15, {1,3}});
1739  side_nbr_nodes.insert({18, {2,3}});
1740  side_nbr_nodes.insert({11, {0,4}});
1741  side_nbr_nodes.insert({16, {1,5}});
1742  side_nbr_nodes.insert({21, {3,7}});
1743  side_nbr_nodes.insert({20, {2,6}});
1744  side_nbr_nodes.insert({22, {4,5}});
1745  side_nbr_nodes.insert({24, {4,6}});
1746  side_nbr_nodes.insert({25, {5,7}});
1747  side_nbr_nodes.insert({26, {6,7}});
1748 
1749  face_nbr_nodes.insert({12, {0,1,4,5}});
1750  face_nbr_nodes.insert({9 , {0,1,2,3}});
1751  face_nbr_nodes.insert({14, {0,2,4,6}});
1752  face_nbr_nodes.insert({17, {1,3,5,7}});
1753  face_nbr_nodes.insert({19, {2,3,6,7}});
1754  face_nbr_nodes.insert({23, {4,5,6,7}});
1755 
1756  int_nbr_nodes.insert({13, {0,1,2,3,4,5,6,7}});
1757  }
1758  else if (elem_type == Utility::string_to_enum<ElemType>("TET4"))
1759  {
1760  coarse_nodes.insert({0,1,2,3});
1761 
1762  // fill neighbor maps based on static node numbering
1763  side_nbr_nodes.insert({4, {0,1}});
1764  side_nbr_nodes.insert({5, {0,2}});
1765  side_nbr_nodes.insert({6, {0,3}});
1766  side_nbr_nodes.insert({7, {1,2}});
1767  side_nbr_nodes.insert({8, {1,3}});
1768  side_nbr_nodes.insert({9, {2,3}});
1769  }
1770 
1771  // stash number of dofs on coarse grid for projection sizing
1772  int n_old_dofs = sys.n_dofs();
1773 
1774  // save old coarse dof_ids in order of coarse nodes
1775  std::map <dof_id_type, dof_id_type> node2dof_c;
1776  for ( const auto & node : mesh.node_ptr_range() )
1777  {
1778  dof_id_type cdof_id = node->dof_number(0,0,0);
1779  node2dof_c.insert( std::pair<dof_id_type,dof_id_type>( node->id() , cdof_id) );
1780  }
1781 
1782  // refine the mesh so we can utilize old_dof_indices for projection_matrix
1783  MeshRefinement mr(mesh);
1784  mr.uniformly_refine(1);
1786 
1787  // fine node to dof map
1788  std::map <dof_id_type, dof_id_type> node2dof_f;
1789  for ( const auto & node : mesh.local_node_ptr_range() )
1790  {
1791  dof_id_type fdof_id = node->dof_number(0,0,0);
1792  node2dof_f.insert( std::pair<dof_id_type,dof_id_type>(node->id() , fdof_id) );
1793  }
1794 
1795  // local and global projection_matrix sizes infos
1796  int n_new_dofs = sys.n_dofs();
1797  int n_new_dofs_local = sys.get_dof_map().n_dofs_on_processor(sys.processor_id());
1798  int ndofs_old_first = sys.get_dof_map().first_old_dof(sys.processor_id());
1799  int ndofs_old_end = sys.get_dof_map().end_old_dof(sys.processor_id());
1800  int n_old_dofs_local = ndofs_old_end - ndofs_old_first;
1801 
1802  // init and compute the projection matrix using GenericProjector
1803  std::unique_ptr<SparseMatrix<Number> > proj_mat_ptr =
1805  SparseMatrix<Number> & proj_mat = *proj_mat_ptr;
1806  proj_mat.init(n_new_dofs, n_old_dofs, n_new_dofs_local, n_old_dofs_local);
1807  sys.projection_matrix(proj_mat);
1808  proj_mat.close();
1809 
1810  // init the gold standard projection matrix
1811  std::unique_ptr<SparseMatrix<Number> > gold_mat_ptr =
1813  SparseMatrix<Number> & gold_mat = *gold_mat_ptr;
1814  gold_mat.init(n_new_dofs, n_old_dofs, n_new_dofs_local, n_old_dofs_local);
1815 
1816  // construct the gold projection matrix using static node numbering as reference info
1817  for ( const auto & node : mesh.local_node_ptr_range() )
1818  {
1819  dof_id_type node_id = node->id();
1820  dof_id_type fdof_id = (node2dof_f.find(node_id))->second;
1821 
1822  if (coarse_nodes.find(node_id) != coarse_nodes.end() )
1823  { // direct inject coarse nodes
1824  if (fdof_id >= gold_mat.row_start() && fdof_id < gold_mat.row_stop())
1825  {
1826  auto cdof_id = node2dof_c.find(node_id);
1827  gold_mat.set(fdof_id, cdof_id->second, 1.0);
1828  }
1829  }
1830  else if ( side_nbr_nodes.find(node_id) != side_nbr_nodes.end() )
1831  { // new side nodes with old_dof neighbor contributions
1832  if (fdof_id >= gold_mat.row_start() && fdof_id < gold_mat.row_stop())
1833  {
1834  auto node_nbrs = side_nbr_nodes.find(node_id);
1835  for (auto nbr : node_nbrs->second)
1836  {
1837  auto nbr_dof = node2dof_c.find(nbr);
1838  gold_mat.set(fdof_id, nbr_dof->second, 0.5);
1839  }
1840  }
1841  }
1842  else if ( face_nbr_nodes.find(node_id) != face_nbr_nodes.end() )
1843  { // new face nodes with old_dof neighbor contributions
1844  if (fdof_id >= gold_mat.row_start() && fdof_id < gold_mat.row_stop())
1845  {
1846  auto node_nbrs = face_nbr_nodes.find(node_id);
1847  for (auto nbr : node_nbrs->second)
1848  {
1849  auto nbr_dof = node2dof_c.find(nbr);
1850  gold_mat.set(fdof_id, nbr_dof->second, 0.25);
1851  }
1852  }
1853  }
1854  else
1855  { // new interior nodes with old_dof neighbor contributions
1856  if (fdof_id >= gold_mat.row_start() && fdof_id < gold_mat.row_stop())
1857  {
1858  auto node_nbrs = int_nbr_nodes.find(node_id);
1859  for (auto nbr : node_nbrs->second)
1860  {
1861  auto nbr_dof = node2dof_c.find(nbr);
1862  gold_mat.set(fdof_id, nbr_dof->second, 0.125);
1863  }
1864  }
1865  }
1866  } // end gold mat build
1867  gold_mat.close();
1868 
1869  // calculate relative difference norm between the two projection matrices
1870  Real gold_norm = gold_mat.linfty_norm();
1871  proj_mat.add(-1.0, gold_mat);
1872  Real diff_norm = proj_mat.linfty_norm();
1873  CPPUNIT_ASSERT(diff_norm/gold_norm < TOLERANCE*TOLERANCE);
1874  }
1875 #endif // LIBMESH_HAVE_PETSC
1876 #endif // LIBMESH_HAVE_METAPHYSICL
1877 #endif // LIBMESH_ENABLE_AMR
1878 
1879 
1880  void testProjectHierarchicEdge3() { LOG_UNIT_TEST; testProjectLine(EDGE3); }
1881  void testProjectHierarchicQuad9() { LOG_UNIT_TEST; testProjectSquare(QUAD9); }
1882  void testProjectHierarchicTri6() { LOG_UNIT_TEST; testProjectSquare(TRI6); }
1883  void testProjectHierarchicTri7() { LOG_UNIT_TEST; testProjectSquare(TRI7); }
1884  void testProjectHierarchicHex27() { LOG_UNIT_TEST; testProjectCube(HEX27); }
1885  void testProjectMeshFunctionHex27() { LOG_UNIT_TEST; testProjectCubeWithMeshFunction(HEX27); }
1886  void test2DProjectVectorFETri3() { LOG_UNIT_TEST; test2DProjectVectorFE(TRI3); }
1887  void test2DProjectVectorFEQuad4() { LOG_UNIT_TEST; test2DProjectVectorFE(QUAD4); }
1888  void test2DProjectVectorFETri6() { LOG_UNIT_TEST; test2DProjectVectorFE(TRI6); }
1889  void test2DProjectVectorFETri7() { LOG_UNIT_TEST; test2DProjectVectorFE(TRI7); }
1890  void test2DProjectVectorFEQuad8() { LOG_UNIT_TEST; test2DProjectVectorFE(QUAD8); }
1891  void test2DProjectVectorFEQuad9() { LOG_UNIT_TEST; test2DProjectVectorFE(QUAD9); }
1892  void test3DProjectVectorFETet4() { LOG_UNIT_TEST; test3DProjectVectorFE(TET4); }
1893  void test3DProjectVectorFEHex8() { LOG_UNIT_TEST; test3DProjectVectorFE(HEX8); }
1894  void test3DProjectVectorFETet10() { LOG_UNIT_TEST; test3DProjectVectorFE(TET10); }
1895  void test3DProjectVectorFETet14() { LOG_UNIT_TEST; test3DProjectVectorFE(TET14); }
1896  void test3DProjectVectorFEHex20() { LOG_UNIT_TEST; test3DProjectVectorFE(HEX20); }
1897  void test3DProjectVectorFEHex27() { LOG_UNIT_TEST; test3DProjectVectorFE(HEX27); }
1898 
1899 #ifdef LIBMESH_ENABLE_AMR
1900 #ifdef LIBMESH_HAVE_METAPHYSICL
1901 #ifdef LIBMESH_HAVE_PETSC
1902  // projection matrix tests
1903  void testProjectMatrixEdge2() { LOG_UNIT_TEST; testProjectMatrix1D(EDGE2); }
1904  void testProjectMatrixQuad4() { LOG_UNIT_TEST; testProjectMatrix2D(QUAD4); }
1905  void testProjectMatrixTri3() { LOG_UNIT_TEST; testProjectMatrix2D(TRI3); }
1906  void testProjectMatrixHex8() { LOG_UNIT_TEST; testProjectMatrix3D(HEX8); }
1907  void testProjectMatrixTet4() { LOG_UNIT_TEST; testProjectMatrix3D(TET4); }
1908 #endif // LIBMESH_HAVE_PETSC
1909 #endif // LIBMESH_HAVE_METAPHYSICL
1910 #endif // LIBMESH_ENABLE_AMR
1911 
1912 };
1913 
unsigned int add_variables(const std::vector< std::string > &vars, 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:1471
void test3DProjectVectorFETet14()
void test2DProjectVectorFETri7()
static const Order type_to_default_order_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the default approximation order of...
Definition: elem.h:991
Number cubic_test(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: systems_test.C:351
void local_dof_indices(const unsigned int var, std::set< dof_id_type > &var_indices) const
Fills the std::set with the degrees of freedom on the local processor corresponding the the variable ...
Definition: system.C:1627
void testAddVectorTypeChange()
Definition: systems_test.C:651
ElemType
Defines an enum for geometric element types.
void testProjectMatrixQuad4()
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
This is the EquationSystems class.
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
Definition: dof_object.h:1032
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
const DenseMatrix< Number > & get_elem_jacobian() const
Const accessor for element Jacobian.
Definition: diff_context.h:274
virtual Node *& set_node(const unsigned int i)
Definition: elem.h:2558
A Node is like a Point, but with more information.
Definition: node.h:52
This abstract base class defines the interface by which library code and user code can report associa...
void tripleValueTest(const Point &p, const TransientExplicitSystem &sys, const PointLocatorBase &locator, std::set< subdomain_id_type > &u_subdomains, std::set< subdomain_id_type > &v_subdomains, std::set< subdomain_id_type > &w_subdomains, const Parameters &param)
Definition: systems_test.C:501
void get_side_fe(unsigned int var, FEGenericBase< OutputShape > *&fe) const
Accessor for edge/face (2D/3D) finite element object for variable var for the largest dimension in th...
Definition: fem_context.h:317
virtual void pre_fe_reinit(const System &, const Elem *e)
Reinitializes local data vectors/matrices on the current geometric element.
Definition: fem_context.C:1683
bool has_boundary_id(const Node *const node, const boundary_id_type id) const
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition: mesh_base.C:1638
void testProjectHierarchicTri6()
ConstFunction that simply returns 0.
Definition: zero_function.h:38
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
void neighbor_side_fe_reinit()
Initialize neighbor side data needed to assemble DG terms.
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
void test3DProjectVectorFE(const ElemType elem_type)
Definition: systems_test.C:823
The definition of the const_element_iterator struct.
Definition: mesh_base.h:2216
std::size_t distribute_dofs(MeshBase &)
Distribute dofs on the current mesh.
Definition: dof_map.C:978
static constexpr Real TOLERANCE
void local_variable_indices(T &idx, const MeshBase &mesh, unsigned int var_num) const
If T == dof_id_type, counts, if T == std::vector<dof_id_type>, fills an array of, those dof indices w...
Definition: dof_map.C:1151
dof_id_type end_old_dof(const processor_id_type proc) const
Definition: dof_map_base.h:210
void setUp()
Definition: systems_test.C:558
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
void testProjectMatrixHex8()
virtual void side_fe_reinit() override
Override side_fe_reinit to set a boolean flag so that by default DG terms are assumed to be inactive...
void resize(const unsigned int n)
Resize the vector.
Definition: dense_vector.h:396
virtual void add_vector(const T *v, const std::vector< numeric_index_type > &dof_indices)
Computes , where v is a pointer and each dof_indices[i] specifies where to add value v[i]...
const std::vector< dof_id_type > & get_neighbor_dof_indices() const
Accessor for neighbor dof indices.
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
virtual void mesh_reinit() override
Rebuild the cached _lower_to_upper map whenever our Mesh has changed.
Definition: systems_test.C:109
static const unsigned int type_to_dim_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the geometric dimension of the ele...
Definition: elem.h:635
void testAddVectorProjChange()
Definition: systems_test.C:637
void projection_matrix(SparseMatrix< Number > &proj_mat) const
This method creates a projection matrix which corresponds to the operation of project_vector between ...
TripleFunction(Number _offset=0)
Definition: systems_test.C:392
static const unsigned int prev[3]
A lookup table for the decrement modulo 3 operation, for iterating through the three nodes per elemen...
virtual std::unique_ptr< FunctionBase< Number > > clone() const
Definition: systems_test.C:394
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
MeshBase & mesh
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
NumericVector< Number > * rhs
The system matrix.
void testSetSystemParameterOverEquationSystem()
const Parallel::Communicator & comm() const
Manages storage and variables for transient systems.
NumericVector< Number > & add_vector(std::string_view vec_name, const bool projections=true, const ParallelType type=PARALLEL)
Adds the additional vector vec_name to this system.
Definition: system.C:768
void get_all_variable_numbers(std::vector< unsigned int > &all_variable_numbers) const
Fills all_variable_numbers with all the variable numbers for the variables that have been added to th...
Definition: system.C:1617
Number disc_thirds_test(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: systems_test.C:377
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.
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
Fills a user-provided std::vector with the boundary ids associated with Node node.
std::map< const Elem *, const CouplingMatrix *, CompareDofObjectsByPIDAndThenID > map_type
What elements do we care about and what variables do we care about on each element?
dof_id_type n_dofs(const unsigned int vn) const
Definition: dof_map.h:668
void test2DProjectVectorFEQuad8()
virtual LinearSolver< Number > * get_linear_solver() const override
const DenseMatrix< Number > & get_neighbor_neighbor_jacobian() const
Const accessor for element-neighbor Jacobian.
The libMesh namespace provides an interface to certain functionality in the library.
void test2DProjectVectorFEQuad9()
dof_id_type n_local_dofs(const unsigned int vn) const
Definition: dof_map.h:686
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:165
void test2DProjectVectorFEQuad4()
virtual void solve() override
Assembles & solves the linear system A*x=b.
const T_sys & get_system(std::string_view name) const
void test3DProjectVectorFETet10()
CPPUNIT_TEST_SUITE_REGISTRATION(SystemsTest)
unsigned char get_side() const
Accessor for current side of Elem object.
Definition: fem_context.h:922
void test100KVariables()
Definition: systems_test.C:582
void testProjectMatrix3D(const ElemType elem_type)
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
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
Add a new Node at Point p to the end of the vertex array, with processor_id procid.
static std::unique_ptr< SparseMatrix< T > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package(), const MatrixBuildType matrix_build_type=MatrixBuildType::AUTOMATIC)
Builds a SparseMatrix<T> using the linear solver package specified by solver_package.
void testPostInitAddVectorTypeChange()
Definition: systems_test.C:679
NumericVector< Number > * old_local_solution
All the values I need to compute my contribution to the simulation at hand.
dof_id_type n_dofs() const
Definition: system.C:121
void test2DProjectVectorFETri3()
This is the MeshBase class.
Definition: mesh_base.h:75
virtual numeric_index_type row_stop() const =0
void assemble_matrix_and_rhs(EquationSystems &es, const std::string &)
Definition: systems_test.C:123
virtual void set(const numeric_index_type i, const numeric_index_type j, const T value)=0
Set the element (i,j) to value.
virtual void elem_fe_reinit(const std::vector< Point > *const pts=nullptr)
Reinitializes interior FE objects on the current geometric element.
Definition: fem_context.C:1477
unsigned int variable_number(std::string_view var) const
Definition: system.C:1609
virtual void add(const numeric_index_type i, const numeric_index_type j, const T value)=0
Add value to the element (i,j).
This class handles the numbering of degrees of freedom on a mesh.
Definition: dof_map.h:179
NumericVector< Number > * older_local_solution
All the values I need to compute my contribution to the simulation at hand.
void project_solution(FunctionBase< Number > *f, FunctionBase< Gradient > *g=nullptr) const
Projects arbitrary functions onto the current solution.
processor_id_type size() const
void tearDown()
Definition: systems_test.C:561
const std::vector< std::vector< OutputGradient > > & get_dphi() const
Definition: fe_base.h:230
uint8_t processor_id_type
void add_node(const Node *node, const boundary_id_type id)
Add Node node with boundary id id to the boundary information data structures.
unsigned int number() const
Definition: system.h:2350
virtual void add_matrix(const DenseMatrix< T > &dm, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols)=0
Add the full matrix dm to the SparseMatrix.
void testBlockRestrictedVarNDofs()
void get_neighbor_side_fe(unsigned int var, FEGenericBase< OutputShape > *&fe) const
Accessor for neighbor edge/face (2D/3D) finite element object for variable var.
Implements (adaptive) mesh refinement algorithms for a MeshBase.
void set_neighbor(const Elem &neighbor)
Set the neighbor element which we will use to assemble DG terms.
int8_t boundary_id_type
Definition: id_types.h:51
The UnstructuredMesh class is derived from the MeshBase class.
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
void testProjectMatrixTri3()
virtual void reinit()
Handle any mesh changes and reinitialize all the systems on the updated mesh.
void test3DProjectVectorFEHex20()
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
Definition: simple_range.h:57
void test2DProjectVectorFETri6()
Number new_linear_test(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: systems_test.C:364
void testProjectHierarchicEdge3()
void set_preconditioner_type(const PreconditionerType pct)
Sets the type of preconditioner to use.
AugmentSparsityOnNodes(MeshBase &mesh)
Constructor.
Definition: systems_test.C:60
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition: system.h:1593
This class extends FEMContext in order to provide extra data required to perform local element residu...
virtual void init() override
Override the FunctionBase::init() member function.
virtual_for_inffe const std::vector< Real > & get_JxW() const
Definition: fe_abstract.h:303
const std::vector< dof_id_type > & get_dof_indices() const
Accessor for element dof indices.
Definition: diff_context.h:363
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
void testProjectSquare(const ElemType elem_type)
Definition: systems_test.C:873
unsigned int n_points() const
Definition: quadrature.h:131
void testProjectMatrixTet4()
This is the base class for point locators.
void set_solver_type(const SolverType st)
Sets the type of solver to use.
void attach_assemble_function(void fptr(EquationSystems &es, const std::string &name))
Register a user function to use in assembling the system matrix and RHS.
Definition: system.C:2161
dof_id_type n_dofs_on_processor(const processor_id_type proc) const
Definition: dof_map_base.h:197
void testProjectMatrix1D(const ElemType elem_type)
const DenseMatrix< Number > & get_elem_neighbor_jacobian() const
Const accessor for element-neighbor Jacobian.
void test2DProjectVectorFE(const ElemType elem_type)
Definition: systems_test.C:773
virtual void solve()
Solves the system.
Definition: system.h:347
virtual void close()=0
Calls the NumericVector&#39;s internal assembly routines, ensuring that the values are consistent across ...
void testProjectCube(const ElemType elem_type)
Definition: systems_test.C:929
virtual void redistribute() override
Update the cached _lower_to_upper map whenever our Mesh has been redistributed.
Definition: systems_test.C:117
void testBoundaryProjectCube()
virtual const Elem * elem_ptr(const dof_id_type i) const =0
void test3DProjectVectorFEHex8()
const DenseMatrix< Number > & get_neighbor_elem_jacobian() const
Const accessor for element-neighbor Jacobian.
const Elem * neighbor_ptr(unsigned int i) const
Definition: elem.h:2598
static const unsigned int next[3]
A lookup table for the increment modulo 3 operation, for iterating through the three nodes per elemen...
const DenseVector< Number > & get_elem_residual() const
Const accessor for element residual.
Definition: diff_context.h:242
virtual void close()=0
Calls the SparseMatrix&#39;s internal assembly routines, ensuring that the values are consistent across p...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
subdomain_id_type subdomain_id() const
Definition: elem.h:2582
MeshBase & _mesh
The Mesh we&#39;re calculating on.
Definition: systems_test.C:53
unsigned char side
Current side for side_* to examine.
Definition: fem_context.h:1013
void max(const T &r, T &o, Request &req) const
virtual numeric_index_type row_start() const =0
const Node * node_ptr(const unsigned int i) const
Definition: elem.h:2507
void testDofCouplingWithVarGroups()
T & set(const std::string &)
Definition: parameters.h:469
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
const MeshBase & get_mesh() const
static const bool value
Definition: xdr_io.C:54
virtual const Elem & elem_ref(const dof_id_type i) const
Definition: mesh_base.h:639
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
Definition: dense_matrix.h:895
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition: int_range.h:140
void test3DProjectVectorFEHex27()
ExplicitSystem & simpleSetup(UnstructuredMesh &mesh, EquationSystems &es)
Definition: systems_test.C:565
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, SolverPackage solver_package=libMesh::default_solver_package(), ParallelType parallel_type=AUTOMATIC)
Builds a NumericVector on the processors in communicator comm using the linear solver package specifi...
Parameters parameters
Data structure holding arbitrary parameters.
virtual unsigned int size() const override final
Definition: dense_vector.h:104
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.
void get_element_fe(unsigned int var, FEGenericBase< OutputShape > *&fe) const
Accessor for interior finite element object for variable var for the largest dimension in the mesh...
Definition: fem_context.h:277
virtual Real linfty_norm() const =0
void boundary_project_solution(const std::set< boundary_id_type > &b, const std::vector< unsigned int > &variables, FunctionBase< Number > *f, FunctionBase< Gradient > *g=nullptr)
Projects arbitrary boundary functions onto a vector of degree of freedom values for the current syste...
virtual const Node & node_ref(const dof_id_type i) const
Definition: mesh_base.h:596
void testProjectHierarchicTri7()
const DenseMatrix< Number > & get_elem_elem_jacobian() const
Const accessor for element-element Jacobian.
virtual void init()
Initialize all the systems.
dof_id_type first_old_dof(const processor_id_type proc) const
Definition: dof_map_base.h:204
This class provides function-like objects for data distributed over a mesh.
Definition: mesh_function.h:54
void testAssemblyWithDgFemContext()
void testProjectMatrix2D(const ElemType elem_type)
unsigned int n_vars() const
Definition: system.h:2430
void testProjectMeshFunctionHex27()
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 testProjectMatrixEdge2()
Base class for functors that can be evaluated at a point and (optionally) time.
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition: mesh.h:50
processor_id_type processor_id() const
void testProjectHierarchicHex27()
bool vector_preservation(std::string_view vec_name) const
Definition: system.C:1148
void testProjectLine(const ElemType elem_type)
Definition: systems_test.C:719
const DofMap & get_dof_map() const
Definition: system.h:2374
processor_id_type processor_id() const
Definition: dof_object.h:905
virtual ElemType type() const =0
Number component(unsigned int i, const Point &p, Real) override
Definition: systems_test.C:415
void assembly_with_dg_fem_context(EquationSystems &es, const std::string &)
Definition: systems_test.C:203
void testProjectCubeWithMeshFunction(const ElemType elem_type)
Definition: systems_test.C:987
void testPostInitAddVector()
Definition: systems_test.C:620
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
void test3DProjectVectorFETet4()
const SparseMatrix< Number > & get_system_matrix() const
void build_cube(UnstructuredMesh &mesh, const unsigned int nx=0, const unsigned int ny=0, const unsigned int nz=0, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const Real zmin=0., const Real zmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
Builds a (elements) cube.
std::vector< dof_id_type > n_dofs_per_processor(const unsigned int vn) const
Definition: dof_map.h:697
virtual dof_id_type n_nodes() const =0
This class forms the foundation from which generic finite elements may be derived.
const QBase & get_element_qrule() const
Accessor for element interior quadrature rule for the dimension of the current _elem.
Definition: fem_context.h:802
Manages consistently variables, degrees of freedom, and coefficient vectors for explicit systems...
const QBase & get_side_qrule() const
Accessor for element side quadrature rule for the dimension of the current _elem. ...
Definition: fem_context.h:809
uint8_t dof_id_type
Definition: id_types.h:67
void testProjectHierarchicQuad9()
void add_edge(const dof_id_type elem, const unsigned short int edge, const boundary_id_type id)
Add edge edge of element number elem with boundary id id to the boundary information data structure...
const std::vector< std::vector< OutputShape > > & get_phi() const
Definition: fe_base.h:207
virtual void init(const numeric_index_type m, const numeric_index_type n, const numeric_index_type m_l, const numeric_index_type n_l, const numeric_index_type nnz=30, const numeric_index_type noz=10, const numeric_index_type blocksize=1)=0
Initialize SparseMatrix with the specified sizes.
void uniformly_refine(unsigned int n=1)
Uniformly refines the mesh n times.
This class defines a coupling matrix.
void set_union(T &data, const unsigned int root_id) const