libMesh
mesh_function.C
Go to the documentation of this file.
1 #include <libmesh/equation_systems.h>
2 #include <libmesh/replicated_mesh.h>
3 #include <libmesh/mesh_generation.h>
4 #include <libmesh/dof_map.h>
5 #include <libmesh/system.h>
6 #include <libmesh/mesh_function.h>
7 #include <libmesh/numeric_vector.h>
8 #include <libmesh/elem.h>
9 
10 #include "test_comm.h"
11 #include "libmesh_cppunit.h"
12 #include "libmesh/enum_xdr_mode.h"
13 
14 
15 using namespace libMesh;
16 
18  const Parameters &,
19  const std::string &,
20  const std::string &)
21 {
22  return
23  cos(.5*libMesh::pi*p(0)) *
24  sin(.5*libMesh::pi*p(1)) *
25  cos(.5*libMesh::pi*p(2));
26 }
27 
29  const Parameters &,
30  const std::string &,
31  const std::string &)
32 {
33  return 8*p(0) + 80*p(1) + 800*p(2);
34 }
35 
36 
37 class MeshFunctionTest : public CppUnit::TestCase
38 {
42 public:
43  LIBMESH_CPPUNIT_TEST_SUITE( MeshFunctionTest );
44 
45 #if LIBMESH_DIM > 1
46  CPPUNIT_TEST( test_subdomain_id_sets );
47 #ifdef LIBMESH_HAVE_PETSC
48  CPPUNIT_TEST( vectorMeshFunctionLagrange );
49  CPPUNIT_TEST( vectorMeshFunctionNedelec );
50  CPPUNIT_TEST( vectorMeshFunctionRaviartThomas );
51  CPPUNIT_TEST( mixedScalarAndVectorVariables );
52 #endif // LIBMESH_HAVE_PETSC
53 #endif
54 #if LIBMESH_DIM > 2
55 #ifdef LIBMESH_ENABLE_AMR
56  CPPUNIT_TEST( test_p_level );
57 #endif
58 #endif
59 
60  CPPUNIT_TEST_SUITE_END();
61 
62 protected:
63 
64 public:
65  void setUp() {}
66 
67  void tearDown() {}
68 
69  // test that mesh function works correctly with subdomain id sets.
71  {
72  LOG_UNIT_TEST;
73 
75 
77  4, 4,
78  0., 1.,
79  0., 1.,
80  QUAD4);
81 
82  // Set a subdomain id for all elements, based on location.
83  for (auto & elem : mesh.active_element_ptr_range())
84  {
85  Point c = elem->vertex_average();
86  elem->subdomain_id() =
87  subdomain_id_type(c(0)*4) + subdomain_id_type(c(1)*4)*10;
88  }
89 
90  // Add a discontinuous variable so we can easily see what side of
91  // an interface we're querying
93  System & sys = es.add_system<System> ("SimpleSystem");
94  unsigned int u_var = sys.add_variable("u", CONSTANT, MONOMIAL);
95 
96  es.init();
98 
99  MeshFunction mesh_function (sys.get_equation_systems(),
101  sys.get_dof_map(),
102  u_var);
103 
104  // Checkerboard pattern
105  const std::set<subdomain_id_type> sbdids1 {0,2,11,13,20,22,31,33};
106  const std::set<subdomain_id_type> sbdids2 {1,3,10,12,21,23,30,32};
107  mesh_function.init();
108  mesh_function.enable_out_of_mesh_mode(DenseVector<Number>());
109  mesh_function.set_subdomain_ids(&sbdids1);
110 
111  DenseVector<Number> vec_values;
112  const std::string dummy;
113 
114  // Make sure the MeshFunction's values interpolate the projected solution
115  // at the nodes
116  for (auto & elem : mesh.active_local_element_ptr_range())
117  {
118  const Point c = elem->vertex_average();
119  const Real expected_value =
120  libmesh_real(trilinear_function(c, es.parameters, dummy, dummy));
121  const std::vector<Point> offsets
122  {{0,-1/8.}, {1/8.,0}, {0,1/8.}, {-1/8.,0}};
123  for (Point offset : offsets)
124  {
125  const Point p = c + offset;
126  mesh_function(p, 0, vec_values, &sbdids1);
127  const Number retval1 = vec_values.empty() ? -12345 : vec_values(0);
128  mesh_function(p, 0, vec_values, &sbdids2);
129  const Number retval2 = vec_values.empty() ? -12345 : vec_values(0);
130  mesh_function(c, 0, vec_values, nullptr);
131  const Number retval3 = vec_values.empty() ? -12345 : vec_values(0);
132 
133  LIBMESH_ASSERT_NUMBERS_EQUAL
134  (retval3, expected_value, TOLERANCE * TOLERANCE);
135 
136  if (sbdids1.count(elem->subdomain_id()))
137  {
138  CPPUNIT_ASSERT(!sbdids2.count(elem->subdomain_id()));
139  LIBMESH_ASSERT_NUMBERS_EQUAL
140  (retval1, expected_value, TOLERANCE * TOLERANCE);
141 
142  mesh_function(c, 0, vec_values, &sbdids2);
143  CPPUNIT_ASSERT(vec_values.empty());
144  }
145  else
146  {
147  LIBMESH_ASSERT_NUMBERS_EQUAL
148  (retval2, expected_value, TOLERANCE * TOLERANCE);
149 
150  mesh_function(c, 0, vec_values, &sbdids1);
151  CPPUNIT_ASSERT(vec_values.empty());
152  }
153  }
154  }
155  }
156 
157  // test that mesh function works correctly with non-zero
158  // Elem::p_level() values.
159 #ifdef LIBMESH_ENABLE_AMR
161  {
162  LOG_UNIT_TEST;
163 
165 
167  5, 5, 5,
168  0., 1.,
169  0., 1.,
170  0., 1.,
171  HEX20);
172 
173  // Bump the p-level for all elements. We will create a system with
174  // a FIRST, LAGRANGE variable and then use the additional p-level
175  // to solve with quadratic elements. Note: set_p_level(1) actually
176  // _increases_ the existing variable order by 1, it does not set
177  // it to 1.
178  for (auto & elem : mesh.active_element_ptr_range())
179  elem->set_p_level(1);
180 
181  EquationSystems es(mesh);
182  System & sys = es.add_system<System> ("SimpleSystem");
183  unsigned int u_var = sys.add_variable("u", FIRST, LAGRANGE);
184 
185  es.init();
187 
188 
189  std::unique_ptr<NumericVector<Number>> mesh_function_vector
191  mesh_function_vector->init(sys.n_dofs(), sys.n_local_dofs(),
192  sys.get_dof_map().get_send_list(), false,
193  GHOSTED);
194 
195  sys.solution->localize(*mesh_function_vector,
196  sys.get_dof_map().get_send_list());
197 
198 
199  // So the MeshFunction knows which variables to compute values for.
200  // std::make_unique doesn't like if we try to use {u_var} in-place?
201  std::vector<unsigned int> variables {u_var};
202 
203  auto mesh_function =
204  std::make_unique<MeshFunction>(sys.get_equation_systems(),
205  *mesh_function_vector,
206  sys.get_dof_map(),
207  variables);
208 
209  mesh_function->init();
210  mesh_function->set_point_locator_tolerance(0.0001);
211  DenseVector<Number> vec_values;
212  std::string dummy;
213 
214  // Make sure the MeshFunction's values interpolate the projected solution
215  // at the nodes
216  for (const auto & node : mesh.local_node_ptr_range())
217  {
218  (*mesh_function)(*node, /*time=*/ 0., vec_values);
219  Number mesh_function_value =
220  projection_function(*node,
221  es.parameters,
222  dummy,
223  dummy);
224 
225  LIBMESH_ASSERT_NUMBERS_EQUAL
226  (vec_values(0), mesh_function_value, TOLERANCE*TOLERANCE);
227  }
228  }
229 #endif // LIBMESH_ENABLE_AMR
230 
231 #ifdef LIBMESH_HAVE_PETSC
232 
233  // A helper function that populates the solution data from output files
235  const std::string & solutions_name)
236  {
237  DenseVector<Number> output;
238 
239  // Reading mesh and solution information from XDA files
241  mesh.read(mesh_name);
242  EquationSystems es(mesh);
243  es.read(solutions_name, READ,
247  es.update();
248 
249  // Pulling the correct system and variable information from
250  // the XDA files (the default system name is "nl0")
251  System & sys = es.get_system<System>("nl0");
252  std::unique_ptr<NumericVector<Number>> mesh_function_vector =
254  mesh_function_vector->init(sys.n_dofs(), false, SERIAL);
255  sys.solution->localize(*mesh_function_vector);
256 
257  // Pulling the total number of variables stored in XDA file
258  std::vector<unsigned int> variables;
259  sys.get_all_variable_numbers(variables);
260  std::sort(variables.begin(),variables.end());
261 
262  // Setting up libMesh::MeshFunction
263  MeshFunction mesh_function(es, *mesh_function_vector,
264  sys.get_dof_map(), variables);
265  mesh_function.init();
266 
267  // Defining input parameters for MeshFunction::operator()
268  const std::set<subdomain_id_type> * subdomain_ids = nullptr;
269  const Point & p = Point(0.5, 0.5);
270 
271  // Supplying the variable values at center of mesh to output
272  (mesh_function)(p, 0.0, output, subdomain_ids);
273 
274  return output;
275  }
276 
277  // Tests the projection of Lagrange Vectors using MeshFunction
279  {
280  LOG_UNIT_TEST;
281 
282  // Populating the solution data using a helper function
283  DenseVector<Number> output = read_variable_info_from_output_data("solutions/lagrange_vec_solution_mesh.xda","solutions/lagrange_vec_solution.xda");
284  Gradient output_vec = VectorValue(output(0),output(1));
285 
286  // Expected value at center mesh
287  Gradient output_expected = VectorValue(0.100977281077292,0.201954562154583);
288 
289  LIBMESH_ASSERT_FP_EQUAL(libMesh::libmesh_real(output_vec(0)), libMesh::libmesh_real(output_expected(0)),
290  TOLERANCE * TOLERANCE);
291  LIBMESH_ASSERT_FP_EQUAL(libMesh::libmesh_real(output_vec(1)), libMesh::libmesh_real(output_expected(1)),
292  TOLERANCE * TOLERANCE);
293  }
294 
295  // Tests the projection of Nedelec Vectors using MeshFunction
297  {
298  LOG_UNIT_TEST;
299 
300  // Populating the solution data using a helper function
301  DenseVector<Number> output = read_variable_info_from_output_data("solutions/nedelec_one_solution_mesh.xda","solutions/nedelec_one_solution.xda");
302  Gradient output_vec = VectorValue(output(0),output(1));
303 
304  // Expected value at center mesh
305  Gradient output_expected = VectorValue(0.0949202883998996,-0.0949202883918033);
306 
307  LIBMESH_ASSERT_FP_EQUAL(libMesh::libmesh_real(output_vec(0)), libMesh::libmesh_real(output_expected(0)),
308  TOLERANCE * TOLERANCE);
309  LIBMESH_ASSERT_FP_EQUAL(libMesh::libmesh_real(output_vec(1)), libMesh::libmesh_real(output_expected(1)),
310  TOLERANCE * TOLERANCE);
311  }
312 
313  // Tests the projection of Raviart Thomas Vectors using MeshFunction
315  {
316  LOG_UNIT_TEST;
317 
318  // Populating the solution data using a helper function
319  DenseVector<Number> output = read_variable_info_from_output_data("solutions/raviart_thomas_solution_mesh.xda","solutions/raviart_thomas_solution.xda");
320  Gradient output_vec = VectorValue(output(0),output(1));
321 
322  // Expected value at center mesh
323  Gradient output_expected = VectorValue(0.0772539939808116,-0.0772537479511396);
324 
325  LIBMESH_ASSERT_FP_EQUAL(libMesh::libmesh_real(output_vec(0)), libMesh::libmesh_real(output_expected(0)),
326  TOLERANCE * TOLERANCE);
327  LIBMESH_ASSERT_FP_EQUAL(libMesh::libmesh_real(output_vec(1)), libMesh::libmesh_real(output_expected(1)),
328  TOLERANCE * TOLERANCE);
329  }
330 
331  // Tests MeshFunction for mixed scalar and vector variable outputs
332  // In this case, the variables types are:
333  // - variable index: 0, variable family: Raviart Thomas, Order: First
334  // - variable index: 1, variable family: Monomial, Order: Constant
335  // - variable index: 2, variable family: Scalar, Order: First
337  {
338  LOG_UNIT_TEST;
339 
340  // Populating the solution data using a helper function
341  DenseVector<Number> output = read_variable_info_from_output_data("solutions/raviart_thomas_solution_mesh.xda","solutions/raviart_thomas_solution.xda");
342  Gradient output_raviart_thomas = VectorValue(output(0),output(1));
343 
344  // Expected value at center mesh
345  Gradient raviart_thomas_expected = VectorValue(0.0772539939808116,-0.0772537479511396);
346  Number monomial_expected = -0.44265566716952;
347  Number scalar_expected = -2.86546e-18;
348 
349  // Checking Raviart Thomas variable family values
350  LIBMESH_ASSERT_FP_EQUAL(libMesh::libmesh_real(output_raviart_thomas(0)), libMesh::libmesh_real(raviart_thomas_expected(0)),
351  TOLERANCE * TOLERANCE);
352  LIBMESH_ASSERT_FP_EQUAL(libMesh::libmesh_real(output_raviart_thomas(1)), libMesh::libmesh_real(raviart_thomas_expected(1)),
353  TOLERANCE * TOLERANCE);
354  // Checking Monomial variable family value
355  LIBMESH_ASSERT_FP_EQUAL(libMesh::libmesh_real(output(2)), libMesh::libmesh_real(monomial_expected),
356  TOLERANCE * TOLERANCE);
357  // Checking scalar variable family value
358  LIBMESH_ASSERT_FP_EQUAL(libMesh::libmesh_real(output(3)), libMesh::libmesh_real(scalar_expected),
359  TOLERANCE * TOLERANCE);
360  }
361 #endif // LIBMESH_HAVE_PETSC
362 };
363 
T libmesh_real(T a)
void vectorMeshFunctionNedelec()
This is the EquationSystems class.
virtual void read(const std::string &name, void *mesh_data=nullptr, bool skip_renumber_nodes_and_elements=false, bool skip_find_neighbors=false)=0
Interfaces for reading/writing a mesh to/from a file.
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
DenseVector< Number > read_variable_info_from_output_data(const std::string &mesh_name, const std::string &solutions_name)
This class provides the ability to map between arbitrary, user-defined strings and several data types...
Definition: parameters.h:71
Number trilinear_function(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: mesh_function.C:28
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
static constexpr Real TOLERANCE
TestClass subdomain_id_type
Based on the 4-byte comment warning above, this probably doesn&#39;t work with exodusII at all...
Definition: id_types.h:43
Number projection_function(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: mesh_function.C:17
const EquationSystems & get_equation_systems() const
Definition: system.h:721
MeshBase & mesh
const Parallel::Communicator & comm() const
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
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.
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
The libMesh namespace provides an interface to certain functionality in the library.
dof_id_type n_local_dofs() const
Definition: system.C:158
const T_sys & get_system(std::string_view name) const
dof_id_type n_dofs() const
Definition: system.C:121
void project_solution(FunctionBase< Number > *f, FunctionBase< Gradient > *g=nullptr) const
Projects arbitrary functions onto the current solution.
void vectorMeshFunctionRaviartThomas()
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition: system.h:96
virtual bool empty() const override final
Definition: dense_vector.h:109
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition: system.h:1593
virtual void init() override
Override the FunctionBase::init() member function.
void read(std::string_view name, const XdrMODE, const unsigned int read_flags=(READ_HEADER|READ_DATA), bool partition_agnostic=true)
Read & initialize the systems from disk using the XDR data format.
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 vectorMeshFunctionLagrange()
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void test_subdomain_id_sets()
Definition: mesh_function.C:70
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.
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
Definition: system.h:1605
virtual void init()
Initialize all the systems.
This class provides function-like objects for data distributed over a mesh.
Definition: mesh_function.h:54
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.
CPPUNIT_TEST_SUITE_REGISTRATION(MeshFunctionTest)
const DofMap & get_dof_map() const
Definition: system.h:2374
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
const std::vector< dof_id_type > & get_send_list() const
Definition: dof_map.h:533
void update()
Updates local values for all the systems.
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.
const Real pi
.
Definition: libmesh.h:299
void mixedScalarAndVectorVariables()