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"
40static 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)
201#if defined(LIBMESH_ENABLE_AMR) && defined(LIBMESH_ENABLE_EXCEPTIONS)
211#ifdef LIBMESH_ENABLE_EXCEPTIONS
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);
305 std::unique_ptr<MeshBase> mesh_clone =
mesh.
clone();
306 CPPUNIT_ASSERT(*mesh_clone ==
mesh);
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
403 catch (
const std::exception &e)
405 CPPUNIT_ASSERT(std::string(e.what()).find(
"Mesh refinement is not yet implemented") != std::string::npos);
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!");
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
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);
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;
CPPUNIT_TEST(testCloneEquality)
void build_two_disjoint_elems(Mesh &mesh, bool add_pair=true, const Point &translate_vec=Point(0.0, 0.0, 0.0))
void build_split_mesh_with_interface(Mesh &mesh, unsigned nx, unsigned ny, bool test_local_refinement=false)
void testTempJumpRefine()
void build_four_disjoint_elems(Mesh &mesh)
LIBMESH_CPPUNIT_TEST_SUITE(DisjointNeighborTest)
void testStitchingDiscontinuousBoundaries()
CPPUNIT_TEST(testTempJumpLocalRefineFail)
CPPUNIT_TEST(testPreserveDisjointNeighborPairsAfterStitch)
CPPUNIT_TEST(testStitchCrossMesh)
void testDisjointNeighborConflictError()
CPPUNIT_TEST(testTempJump)
CPPUNIT_TEST(testDisjointNeighborConflictError)
CPPUNIT_TEST(testTempJumpRefine)
void testStitchCrossMesh()
CPPUNIT_TEST(testStitchingDiscontinuousBoundaries)
void testPreserveDisjointNeighborPairsAfterStitch()
void testTempJumpLocalRefineFail()
The BoundaryInfo class contains information relevant to boundary conditions including storing faces,...
std::string & sideset_name(boundary_id_type id)
unsigned int side_with_boundary_id(const Elem *const elem, const boundary_id_type boundary_id) const
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.
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().
virtual void zero() override final
Sets all elements of the matrix to 0 and resets any decomposition flag which may have been previously...
Defines a dense vector for use in Finite Element-type computations.
void resize(const unsigned int n)
Resize the vector.
virtual void zero() override final
Set every element in the vector to 0.
This class allows one to associate Dirichlet boundary values with a given set of mesh boundary ids an...
virtual Elem * add_elem(Elem *e) override final
Add elem e to the end of the element array.
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.
virtual dof_id_type parallel_n_nodes() const override
virtual const Node * node_ptr(const dof_id_type i) const override final
This class handles the numbering of degrees of freedom on a mesh.
void set_implicit_neighbor_dofs(bool implicit_neighbor_dofs)
Allow the implicit_neighbor_dofs flag to be set programmatically.
void add_dirichlet_boundary(const DirichletBoundary &dirichlet_boundary)
Adds a copy of the specified Dirichlet boundary to the system.
This is the base class from which all geometric element types are derived.
virtual Node *& set_node(const unsigned int i)
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 ...
unsigned int which_neighbor_am_i(const Elem *e) const
This function tells you which neighbor e is.
const Elem * neighbor_ptr(unsigned int i) const
This is the EquationSystems class.
const MeshBase & get_mesh() const
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
NumericVector< Number > * rhs
The system matrix.
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Order default_quadrature_order() const
SparseMatrix< Number > * matrix
The system matrix.
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
virtual void solve() override
Assembles & solves the linear system A*x=b.
This is the MeshBase class.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
virtual const Node * node_ptr(const dof_id_type i) const =0
unsigned int mesh_dimension() const
PeriodicBoundaries * get_disjoint_neighbor_boundary_pairs()
void allow_renumbering(bool allow)
If false is passed in then this mesh will no longer be renumbered when being prepared for use.
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.
virtual std::unique_ptr< MeshBase > clone() const =0
Virtual "copy constructor".
void set_mesh_dimension(unsigned char d)
Resets the logical dimension of the mesh.
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 void clear()
Deletes all the element and node data that is currently stored.
virtual const Elem * query_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.
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.
virtual dof_id_type parallel_n_nodes() const =0
Implements (adaptive) mesh refinement algorithms for a MeshBase.
bool refine_elements()
Only refines the user-requested elements.
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
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].
This class provides the ability to map between arbitrary, user-defined strings and several data types...
T & set(const std::string &)
const T & get(std::string_view) const
A Point defines a location in LIBMESH_DIM dimensional Real space.
unsigned int n_points() const
This class implements specific orders of Gauss quadrature.
virtual void close()=0
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
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.
Number point_value(unsigned int var, const Point &p, const bool insist_on_success=true, const NumericVector< Number > *sol=nullptr) const
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.
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.
const DofMap & get_dof_map() const
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.
std::size_t stitch_surfaces(boundary_id_type boundary_id_1, boundary_id_type boundary_id_2, 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 prepare_after_stitching=true)
Similar to stitch_meshes, except that we stitch two adjacent surfaces within this mesh.
Wrap a libMesh-style function pointer into a FunctionBase object.
static const boundary_id_type left_id
static const boundary_id_type interface_left_id
static const boundary_id_type interface1_left_id
CPPUNIT_TEST_SUITE_REGISTRATION(DisjointNeighborTest)
static const boundary_id_type interface2_left_id
void assemble_temperature_jump(EquationSystems &es, const std::string &)
Number right_solution_fn(const Point &, const Parameters ¶ms, const std::string &, const std::string &)
static const boundary_id_type interface_right_id
static const boundary_id_type interface3_left_id
static const boundary_id_type right_id
Number heat_exact(const Point &p, const Parameters &, const std::string &, const std::string &)
static const boundary_id_type interface3_right_id
Number left_solution_fn(const Point &, const Parameters &, const std::string &, const std::string &)
static const boundary_id_type interface1_right_id
static const boundary_id_type interface2_right_id
Communicator * TestCommWorld
The libMesh namespace provides an interface to certain functionality in the library.
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
VectorValue< Real > RealVectorValue
Useful typedefs to allow transparent switching between Real and Complex data types.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real