libMesh
Loading...
Searching...
No Matches
dof_map_test.C
Go to the documentation of this file.
1#include <libmesh/equation_systems.h>
2#include <libmesh/mesh.h>
3#include <libmesh/mesh_generation.h>
4#include <libmesh/elem.h>
5#include <libmesh/dof_map.h>
6
8
9#include "test_comm.h"
10#include "libmesh_cppunit.h"
11
12#include <regex>
13#include <string>
14
15using namespace libMesh;
16
17#ifdef LIBMESH_ENABLE_CONSTRAINTS
18// This class is used by testConstraintLoopDetection
20{
21private:
22
24
25public:
26
27 MyConstraint( System & sys ) : Constraint(), _sys(sys) {}
28
29 virtual ~MyConstraint() {}
30
31 void constrain()
32 {
33 {
34 const dof_id_type constrained_dof_index = 0;
35 DofConstraintRow constraint_row;
36 constraint_row[1] = 1.0;
37 _sys.get_dof_map().add_constraint_row( constrained_dof_index, constraint_row, 0., true);
38 }
39 {
40 const dof_id_type constrained_dof_index = 1;
41 DofConstraintRow constraint_row;
42 constraint_row[0] = 1.0;
43 _sys.get_dof_map().add_constraint_row( constrained_dof_index, constraint_row, 0., true);
44 }
45 }
46};
47#endif
48
49
50class DofMapTest : public CppUnit::TestCase {
51public:
53
55#if LIBMESH_DIM > 1
58#endif
59#if LIBMESH_DIM > 2
61#endif
62
63#if defined(LIBMESH_ENABLE_EXCEPTIONS)
65#endif
66
67#if defined(LIBMESH_ENABLE_CONSTRAINTS) && defined(LIBMESH_ENABLE_EXCEPTIONS) && LIBMESH_DIM > 1
69#endif
70
72
74
75private:
76
77public:
78 void setUp()
79 {}
80
81 void tearDown()
82 {}
83
84 void testDofOwner(const ElemType elem_type)
85 {
87
89 System &sys = es.add_system<System> ("SimpleSystem");
90 sys.add_variable("u", THIRD, HIERARCHIC);
91
92 const unsigned int n_elem_per_side = 3;
93 const std::unique_ptr<Elem> test_elem = Elem::build(elem_type);
94 const unsigned int ymax = test_elem->dim() > 1;
95 const unsigned int zmax = test_elem->dim() > 2;
96 const unsigned int ny = ymax * n_elem_per_side;
97 const unsigned int nz = zmax * n_elem_per_side;
98
100 n_elem_per_side,
101 ny,
102 nz,
103 0., 1.,
104 0., ymax,
105 0., zmax,
106 elem_type);
107
108 es.init();
109
110 DofMap & dof_map = sys.get_dof_map();
111 for (dof_id_type id = 0; id != dof_map.n_dofs(); ++id)
112 {
113 const processor_id_type pid = dof_map.dof_owner(id);
114 CPPUNIT_ASSERT(dof_map.first_dof(pid) <= id);
115 CPPUNIT_ASSERT(id < dof_map.end_dof(pid));
116 }
117 }
118
119
120
121 void testDofOwnerOnEdge3() { LOG_UNIT_TEST; testDofOwner(EDGE3); }
122 void testDofOwnerOnQuad9() { LOG_UNIT_TEST; testDofOwner(QUAD9); }
123 void testDofOwnerOnTri6() { LOG_UNIT_TEST; testDofOwner(TRI6); }
124 void testDofOwnerOnHex27() { LOG_UNIT_TEST; testDofOwner(HEX27); }
125
126#if defined(LIBMESH_ENABLE_EXCEPTIONS)
128 {
129 LOG_UNIT_TEST;
130
132
134 System & sys = es.add_system<System> ("SimpleSystem");
135 sys.add_variable("u", SECOND);
136
137 MeshTools::Generation::build_square (mesh,4,4,-1., 1.,-1., 1., QUAD4);
138
139 // We need at least one element per processor to make sure
140 // everyone throws and we don't get out of sync before going on to
141 // future tests.
142 dof_id_type min_local_elem = mesh.n_local_elem();
143 mesh.comm().min(min_local_elem);
144
145 if (!min_local_elem)
146 return;
147
148 // We can't just CPPUNIT_ASSERT_THROW, because we want to make
149 // sure we were thrown from the right place with the right error
150 // message!
151 bool threw_desired_exception = false;
152 try {
153 es.init();
154 }
155 catch (libMesh::LogicError & e) {
156 std::regex msg_regex("only supports FEInterface::max_order");
157 CPPUNIT_ASSERT(std::regex_search(e.what(), msg_regex));
158 threw_desired_exception = true;
159 }
160 catch (...) {
161 CPPUNIT_ASSERT_MESSAGE("Unexpected exception type thrown", false);
162 }
163
164 // If we have more than 4*4 processors, or a poor partitioner, we
165 // might not get an exception on every processor
166 mesh.comm().max(threw_desired_exception);
167
168 CPPUNIT_ASSERT(threw_desired_exception);
169 }
170#endif
171
172#if defined(LIBMESH_ENABLE_CONSTRAINTS) && defined(LIBMESH_ENABLE_EXCEPTIONS)
174 {
175 LOG_UNIT_TEST;
177
179 System & sys = es.add_system<System> ("SimpleSystem");
180 sys.add_variable("u", FIRST);
181
182 MyConstraint my_constraint(sys);
183 sys.attach_constraint_object(my_constraint);
184
185 MeshTools::Generation::build_square (mesh,4,4,-1., 1.,-1., 1., QUAD4);
186
187 // Tell the dof_map to check for constraint loops
188 DofMap & dof_map = sys.get_dof_map();
189 dof_map.set_error_on_constraint_loop(true);
190
191 CPPUNIT_ASSERT_THROW_MESSAGE("Constraint loop not detected", es.init(), libMesh::LogicError);
192 }
193#endif
194
196 {
199 auto & sys = es.add_system<System>("SimpleSystem");
200 const auto last_var = sys.add_variable_array({"u0", "u1"}, fe_type);
201 MeshTools::Generation::build_square (mesh,1,1,-1., 1.,-1., 1., QUAD9);
202 es.init();
203 auto & dof_map = sys.get_dof_map();
204 const auto * const elem = mesh.query_elem_ptr(0);
205 if (elem)
206 {
207 std::vector<dof_id_type> array_dofs, work_dofs, dofs;
208 dof_map.array_dof_indices(elem, array_dofs, last_var);
209 // Make sure there are no duplicates
210 std::sort(array_dofs.begin(), array_dofs.end());
211 auto it = std::unique(array_dofs.begin(), array_dofs.end());
212 array_dofs.erase(it, array_dofs.end());
213 CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(dof_map.n_dofs()), array_dofs.size());
214 dof_map.dof_indices(elem, work_dofs, last_var);
215 dofs = work_dofs;
216 dof_map.dof_indices(elem, work_dofs, last_var - 1);
217 dofs.insert(dofs.end(), work_dofs.begin(), work_dofs.end());
218 std::sort(dofs.begin(), dofs.end());
219 CPPUNIT_ASSERT(array_dofs == dofs);
220 }
221 }
222
224 {
225 LOG_UNIT_TEST;
226 for (int i = 1; i < 3; ++i)
227 {
232 }
233 }
234
235};
236
CPPUNIT_TEST(testDofOwnerOnQuad9)
void testConstraintLoopDetection()
CPPUNIT_TEST(testBadElemFECombo)
CPPUNIT_TEST(testConstraintLoopDetection)
CPPUNIT_TEST(testDofOwnerOnEdge3)
LIBMESH_CPPUNIT_TEST_SUITE(DofMapTest)
CPPUNIT_TEST_SUITE_END()
CPPUNIT_TEST(testDofOwnerOnHex27)
void testBadElemFECombo()
void testDofOwnerOnTri6()
void testArrayDofIndicesWithType(const FEType &fe_type)
void setUp()
CPPUNIT_TEST(testDofOwnerOnTri6)
void testDofOwner(const ElemType elem_type)
CPPUNIT_TEST(testArrayDofIndices)
void testArrayDofIndices()
void tearDown()
void testDofOwnerOnEdge3()
void testDofOwnerOnHex27()
void testDofOwnerOnQuad9()
System & _sys
MyConstraint(System &sys)
virtual ~MyConstraint()
void constrain()
void max(const T &r, T &o, Request &req) const
void min(const T &r, T &o, Request &req) const
dof_id_type first_dof(const processor_id_type proc) const
dof_id_type end_dof(const processor_id_type proc) const
This class handles the numbering of degrees of freedom on a mesh.
Definition dof_map.h:181
processor_id_type dof_owner(const dof_id_type dof) const
Definition dof_map.h:815
dof_id_type n_dofs(const unsigned int vn) const
Definition dof_map.h:776
void add_constraint_row(const dof_id_type dof_number, const DofConstraintRow &constraint_row, const Number constraint_rhs, const bool forbid_constraint_overwrite)
Adds a copy of the user-defined row to the constraint matrix, using an inhomogeneous right-hand-side ...
void set_error_on_constraint_loop(bool error_on_constraint_loop)
Definition dof_map.C:234
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition elem.C:442
This is the EquationSystems class.
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.
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition fe_type.h:197
A class to represent the internal "this should never happen" errors, to be thrown by "libmesh_error()...
dof_id_type n_local_elem() const
Definition mesh_base.h:697
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition mesh.h:51
const Parallel::Communicator & comm() const
Abstract base class to be used for system constraints.
Definition system.h:182
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition system.h:100
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
unsigned int add_variable_array(const std::vector< std::string > &vars, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
Adds variables vars to the list of variables for this system.
Definition system.C:1386
void attach_constraint_object(Constraint &constrain)
Register a user object for imposing constraints.
Definition system.C:2007
const DofMap & get_dof_map() const
Definition system.h:2417
Communicator * TestCommWorld
CPPUNIT_TEST_SUITE_REGISTRATION(DofMapTest)
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_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.
ElemType
Defines an enum for geometric element types.
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
A row of the Dof constraint matrix.
Definition dof_map.h:100
uint8_t dof_id_type
Definition id_types.h:67
uint8_t processor_id_type
Definition id_types.h:104