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