1 #include <libmesh/dirichlet_boundaries.h> 2 #include <libmesh/dof_map.h> 3 #include <libmesh/elem.h> 4 #include <libmesh/equation_systems.h> 5 #include <libmesh/exodusII_io.h> 6 #include <libmesh/function_base.h> 7 #include <libmesh/linear_implicit_system.h> 8 #include <libmesh/mesh.h> 9 #include <libmesh/mesh_generation.h> 10 #include <libmesh/numeric_vector.h> 11 #include <libmesh/quadrature_gauss.h> 12 #include <libmesh/sparse_matrix.h> 13 #include <libmesh/wrapped_function.h> 18 #include "libmesh/mesh_refinement.h" 19 #include "libmesh/periodic_boundaries.h" 20 #include "libmesh/periodic_boundary_base.h" 40 static const int Nx = 2,
Ny = 2;
48 return (p(0) < 0.5) ? p(0) : p(0) +
b;
75 FEType fe_type = dof_map.variable_type(0);
85 fe->attach_quadrature_rule(&qrule);
86 fe_face_L->attach_quadrature_rule(&qface);
87 fe_face_R->attach_quadrature_rule(&qface);
89 const auto &JxW_vol = fe->get_JxW();
90 const auto &dphi_vol = fe->get_dphi();
91 const auto &phi_L = fe_face_L->get_phi();
92 const auto &phi_R = fe_face_R->get_phi();
93 const auto &JxW_face = fe_face_L->get_JxW();
97 std::vector<dof_id_type> dof_indices;
100 const double conductance =
Cgap *
b;
102 for (
const Elem *elem :
mesh.active_local_element_ptr_range())
104 dof_map.dof_indices(elem, dof_indices);
105 const unsigned int n_dofs = dof_indices.size();
107 Ke.
resize(n_dofs, n_dofs);
114 for (
unsigned int qp = 0; qp < qrule.n_points(); qp++)
115 for (
unsigned int i = 0; i < n_dofs; i++)
116 for (
unsigned int j = 0; j < n_dofs; j++)
117 Ke(i, j) += conductance * JxW_vol[qp] * (dphi_vol[i][qp] * dphi_vol[j][qp]);
123 fe_face_L->reinit(elem, side);
127 fe_face_R->reinit(neighbor, n_side);
129 std::vector<dof_id_type> dofs_L, dofs_R;
130 dof_map.dof_indices(elem, dofs_L);
131 dof_map.dof_indices(neighbor, dofs_R);
136 for (
unsigned int qp = 0; qp < qface.n_points(); qp++)
138 for (
unsigned int i = 0; i < n_dofs; i++)
139 for (
unsigned int j = 0; j < n_dofs; j++)
140 Ke_ll(i, j) +=
Cgap * phi_L[i][qp] * phi_L[j][qp] * JxW_face[qp];
142 for (
unsigned int i = 0; i < n_dofs; i++)
143 for (
unsigned int j = 0; j < dofs_R.size(); j++)
144 Ke_lr(i, j) += -
Cgap * phi_L[i][qp] * phi_R[j][qp] * JxW_face[qp];
155 fe_face_R->reinit(elem, side);
159 fe_face_L->reinit(neighbor, n_side);
161 std::vector<dof_id_type> dofs_R, dofs_L;
162 dof_map.dof_indices(elem, dofs_R);
163 dof_map.dof_indices(neighbor, dofs_L);
168 for (
unsigned int qp = 0; qp < qface.n_points(); qp++)
170 for (
unsigned int i = 0; i < n_dofs; i++)
171 for (
unsigned int j = 0; j < n_dofs; j++)
172 Ke_rr(i, j) +=
Cgap * phi_R[i][qp] * phi_R[j][qp] * JxW_face[qp];
174 for (
unsigned int i = 0; i < n_dofs; i++)
175 for (
unsigned int j = 0; j < dofs_L.size(); j++)
176 Ke_rl(i, j) += -
Cgap * phi_R[i][qp] * phi_L[j][qp] * JxW_face[qp];
184 dof_map.heterogenously_constrain_element_matrix_and_vector(Ke, Fe, dof_indices);
196 #ifdef LIBMESH_ENABLE_PERIODIC 197 #if defined(LIBMESH_HAVE_SOLVER) 198 CPPUNIT_TEST( testTempJump );
199 CPPUNIT_TEST( testTempJumpRefine );
201 #if defined(LIBMESH_ENABLE_AMR) && defined(LIBMESH_ENABLE_EXCEPTIONS) 205 CPPUNIT_TEST(testTempJumpLocalRefineFail);
207 CPPUNIT_TEST( testCloneEquality );
208 CPPUNIT_TEST( testStitchingDiscontinuousBoundaries );
209 CPPUNIT_TEST( testPreserveDisjointNeighborPairsAfterStitch );
210 CPPUNIT_TEST( testStitchCrossMesh );
211 #ifdef LIBMESH_ENABLE_EXCEPTIONS 212 CPPUNIT_TEST( testDisjointNeighborConflictError );
213 #endif // LIBMESH_ENABLE_EXCEPTIONS 216 CPPUNIT_TEST_SUITE_END();
225 build_two_disjoint_elems(
mesh);
237 LIBMESH_ASSERT_NUMBERS_EQUAL(elem_right_neighbor->
id(), 1, 1e-15);
250 LIBMESH_ASSERT_NUMBERS_EQUAL(elem_left_neighbor->
id(), 0, 1e-15);
259 std::set<boundary_id_type> left_bdy {
left_id };
260 std::set<boundary_id_type> right_bdy {
right_id };
261 std::vector<unsigned int> vars (1, u_var);
284 for (
Real x=0.; x<=1.; x+=0.05)
286 if (std::abs(x - 0.5) < 1e-12)
continue;
287 for (
Real y=0.; y<=1.; y+=0.05)
292 LIBMESH_ASSERT_NUMBERS_EQUAL(exact, approx, 1e-2);
303 build_two_disjoint_elems(
mesh);
305 std::unique_ptr<MeshBase> mesh_clone =
mesh.
clone();
306 CPPUNIT_ASSERT(*mesh_clone ==
mesh);
314 build_two_disjoint_elems(
mesh);
327 build_two_disjoint_elems(mesh2);
329 CPPUNIT_ASSERT(mesh2.parallel_n_nodes() == 8);
336 CPPUNIT_ASSERT(mesh2.parallel_n_nodes() == 6);
346 build_split_mesh_with_interface(
mesh,
Nx,
Ny);
354 std::set<boundary_id_type> left_bdy {
left_id };
355 std::set<boundary_id_type> right_bdy {
right_id };
356 std::vector<unsigned int> vars (1, u_var);
379 for (
Real x=0.; x<=1.; x+=0.05)
381 if (std::abs(x - 0.5) < 1e-12)
continue;
382 for (
Real y=0.; y<=1.; y+=0.05)
387 LIBMESH_ASSERT_NUMBERS_EQUAL(exact, approx, 1e-2);
393 #ifdef LIBMESH_ENABLE_EXCEPTIONS 401 build_split_mesh_with_interface(
mesh,
Nx,
Ny,
true);
403 catch (
const std::exception &e)
405 CPPUNIT_ASSERT(std::string(e.what()).find(
"Mesh refinement is not yet implemented") != std::string::npos);
408 #endif // LIBMESH_ENABLE_EXCEPTIONS 414 build_four_disjoint_elems(
mesh);
433 CPPUNIT_ASSERT(disjoint_pairs->size() == 4);
434 for (
const auto & [bid, pb_ptr] : *disjoint_pairs)
436 const auto & pb = *pb_ptr;
445 CPPUNIT_FAIL(
"Disjoint neighbor boundary pair missing after stitching!");
456 build_two_disjoint_elems(mesh_Y);
465 const auto translate_vec =
Point(1.0, 0.0, 0.0);
488 boundary.
add_side(elem, 3, left_id_x);
489 boundary.
add_side(elem, 1, interface_left_id_x);
491 boundary.
sideset_name(interface_left_id_x) =
"interface_left_x";
501 boundary.
add_side(elem, 1, right_id_x);
502 boundary.
add_side(elem, 3, interface_right_id_x);
504 boundary.
sideset_name(interface_right_id_x) =
"interface_right_x";
532 CPPUNIT_ASSERT(disjoint_pairs->size() == 4);
533 for (
const auto & [bid, pb_ptr] : *disjoint_pairs)
535 const auto & pb = *pb_ptr;
538 if ((a == interface_left_id_x &&
b == interface_right_id_x) ||
539 (a == interface_right_id_x &&
b == interface_left_id_x) ||
544 CPPUNIT_FAIL(
"Disjoint neighbor boundary pair missing after stitching!");
551 #ifdef LIBMESH_ENABLE_EXCEPTIONS 559 build_two_disjoint_elems(mesh_Y,
false);
568 const auto translate_vec =
Point(1.0, 0.0, 0.0);
592 boundary.
add_side(elem, 1, interface_left_id_x);
594 boundary.
sideset_name(interface_left_id_x) =
"interface_left_x";
604 boundary.
add_side(elem, 1, right_id_x);
605 boundary.
add_side(elem, 3, interface_right_id_x);
607 boundary.
sideset_name(interface_right_id_x) =
"interface_right_x";
630 catch (
const std::exception &e)
632 CPPUNIT_ASSERT(std::string(e.what()).find(
"Disjoint neighbor boundary pairing mismatch") != std::string::npos);
635 #endif // LIBMESH_ENABLE_EXCEPTIONS 719 libmesh_error_msg_if(nx % 2 != 0,
"nx must be even!");
724 const unsigned nxL = nx / 2;
725 const unsigned nxR = nx / 2;
726 const double dx = 1.0 /
static_cast<double>(nx);
727 const double dy = 1.0 /
static_cast<double>(ny);
732 auto nidL = [&](
unsigned i,
unsigned j) {
733 return static_cast<dof_id_type>(j * (nxL + 1) + i);
736 for (
unsigned j = 0; j <= ny; ++j)
738 const double y = j * dy;
739 for (
unsigned i = 0; i <= nxL; ++i)
741 const double x = i * dx;
750 auto nidR = [&](
unsigned i,
unsigned j) {
751 return static_cast<dof_id_type>(baseR + j * (nxR + 1) + i);
754 for (
unsigned j = 0; j <= ny; ++j)
756 const double y = j * dy;
757 for (
unsigned i = 0; i <= nxR; ++i)
759 const double x = 0.5 + i * dx;
770 for (
unsigned j = 0; j < ny; ++j)
772 for (
unsigned i = 0; i < nxL; ++i)
791 for (
unsigned j = 0; j < ny; ++j)
793 for (
unsigned i = 0; i < nxR; ++i)
824 #if LIBMESH_ENABLE_AMR 825 if (test_local_refinement)
828 for (
auto & elem :
mesh.element_ptr_range())
830 const Real xmid = elem->vertex_average()(0);
831 if ((xmid < 0.5 && xmid > 0.5 - dx) ||
832 (xmid > 0.5 && xmid < 0.5 + dx))
862 const Real dx = 0.25;
867 for (
unsigned i = 0; i < 4; ++i)
870 Real xR = (i + 1) * dx;
887 unsigned elem_id = 0;
888 for (
unsigned i = 0; i < 4; ++i)
892 unsigned base = i * 4;
static const boundary_id_type interface1_left_id
static const boundary_id_type right_id
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
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) override final
functions for adding /deleting nodes elements.
void build_two_disjoint_elems(Mesh &mesh, bool add_pair=true, const Point &translate_vec=Point(0.0, 0.0, 0.0))
Wrap a libMesh-style function pointer into a FunctionBase object.
CPPUNIT_TEST_SUITE_REGISTRATION(DisjointNeighborTest)
virtual dof_id_type parallel_n_nodes() const override
This is the EquationSystems class.
virtual Elem * add_elem(Elem *e) override final
Add elem e to the end of the element array.
virtual Node *& set_node(const unsigned int i)
Number right_solution_fn(const Point &, const Parameters ¶ms, const std::string &, const std::string &)
virtual void zero() override final
Set every element in the vector to 0.
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
void testStitchCrossMesh()
This class provides the ability to map between arbitrary, user-defined strings and several data types...
void allow_renumbering(bool allow)
If false is passed in then this mesh will no longer be renumbered when being prepared for use...
static const boundary_id_type interface1_right_id
VectorValue< Real > RealVectorValue
Useful typedefs to allow transparent switching between Real and Complex data types.
virtual void zero() override final
Sets all elements of the matrix to 0 and resets any decomposition flag which may have been previously...
libMesh::Parallel::Communicator * TestCommWorld
static const boundary_id_type interface3_right_id
void set_implicit_neighbor_dofs(bool implicit_neighbor_dofs)
Allow the implicit_neighbor_dofs flag to be set programmatically.
Number left_solution_fn(const Point &, const Parameters &, const std::string &, const std::string &)
bool refine_elements()
Only refines the user-requested elements.
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
static const boundary_id_type interface_right_id
void resize(const unsigned int n)
Resize the vector.
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]...
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.
void testTempJumpRefine()
unsigned int side_with_boundary_id(const Elem *const elem, const boundary_id_type boundary_id) const
This is the base class from which all geometric element types are derived.
void testDisjointNeighborConflictError()
void testPreserveDisjointNeighborPairsAfterStitch()
Number point_value(unsigned int var, const Point &p, const bool insist_on_success=true, const NumericVector< Number > *sol=nullptr) const
NumericVector< Number > * rhs
The system matrix.
This class allows one to associate Dirichlet boundary values with a given set of mesh boundary ids an...
Order default_quadrature_order() const
The libMesh namespace provides an interface to certain functionality in the library.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
virtual void solve() override
Assembles & solves the linear system A*x=b.
const T_sys & get_system(std::string_view name) const
void testStitchingDiscontinuousBoundaries()
virtual std::unique_ptr< MeshBase > clone() const =0
Virtual "copy constructor".
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.
This is the MeshBase class.
Number heat_exact(const Point &p, const Parameters &, const std::string &, const std::string &)
This class handles the numbering of degrees of freedom on a mesh.
void build_split_mesh_with_interface(Mesh &mesh, unsigned nx, unsigned ny, bool test_local_refinement=false)
static const boundary_id_type interface3_left_id
virtual void add_matrix(const DenseMatrix< T > &dm, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols)=0
Add the full matrix dm to the SparseMatrix.
void add_disjoint_neighbor_boundary_pairs(const boundary_id_type b1, const boundary_id_type b2, const RealVectorValue &translation)
Register a pair of boundaries as disjoint neighbor boundary pairs.
const T & get(std::string_view) const
Implements (adaptive) mesh refinement algorithms for a MeshBase.
void build_four_disjoint_elems(Mesh &mesh)
unsigned int which_neighbor_am_i(const Elem *e) const
This function tells you which neighbor e is.
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
PeriodicBoundaries * get_disjoint_neighbor_boundary_pairs()
static const boundary_id_type interface2_left_id
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
static const boundary_id_type interface2_right_id
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.
static const boundary_id_type interface_left_id
void set_mesh_dimension(unsigned char d)
Resets the logical dimension of the mesh.
virtual dof_id_type parallel_n_nodes() const =0
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.
virtual void clear()
Deletes all the element and node data that is currently stored.
virtual void close()=0
Calls the NumericVector's internal assembly routines, ensuring that the values are consistent across ...
std::string & sideset_name(boundary_id_type id)
void assemble_temperature_jump(EquationSystems &es, const std::string &)
virtual const Elem * elem_ptr(const dof_id_type i) const =0
const Elem * neighbor_ptr(unsigned int i) const
virtual void close()=0
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
T & set(const std::string &)
SparseMatrix< Number > * matrix
The system matrix.
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 ...
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
Add side side of element number elem with boundary id id to the boundary information data structure...
const MeshBase & get_mesh() const
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
This class implements specific orders of Gauss quadrature.
unsigned int mesh_dimension() const
void add_dirichlet_boundary(const DirichletBoundary &dirichlet_boundary)
Adds a copy of the specified Dirichlet boundary to the system.
virtual void init()
Initialize all the systems.
void testTempJumpLocalRefineFail()
virtual System & add_system(std::string_view system_type, std::string_view name)
Add the system of type system_type named name to the systems array.
virtual const Node * node_ptr(const dof_id_type i) const =0
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
const DofMap & get_dof_map() const
static const boundary_id_type left_id
A Point defines a location in LIBMESH_DIM dimensional Real space.
std::size_t stitch_meshes(const MeshBase &other_mesh, boundary_id_type this_mesh_boundary, boundary_id_type other_mesh_boundary, Real tol=TOLERANCE, bool clear_stitched_boundary_ids=false, bool verbose=true, bool use_binary_search=true, bool enforce_all_nodes_match_on_boundaries=false, bool merge_boundary_nodes_all_or_nothing=false, bool remap_subdomain_ids=false, bool prepare_after_stitching=true)
Stitch other_mesh to this mesh so that this mesh is the union of the two meshes.
virtual const Node * node_ptr(const dof_id_type i) const override final