1 #include <libmesh/equation_systems.h> 2 #include <libmesh/replicated_mesh.h> 3 #include <libmesh/numeric_vector.h> 4 #include <libmesh/dof_map.h> 5 #include <libmesh/elem.h> 6 #include <libmesh/face_quad4.h> 7 #include <libmesh/ghosting_functor.h> 8 #include <libmesh/coupling_matrix.h> 9 #include <libmesh/quadrature_gauss.h> 10 #include <libmesh/linear_implicit_system.h> 11 #include <libmesh/mesh_refinement.h> 12 #include <libmesh/mesh_modification.h> 13 #include <libmesh/partitioner.h> 14 #include <libmesh/sparse_matrix.h> 44 _mesh(system.get_mesh()),
45 _point_locator(system.get_mesh().sub_point_locator()),
46 _coupling_matrix(nullptr)
50 CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(_mesh.n_subdomains()));
53 std::set<subdomain_id_type> ids;
54 _mesh.subdomain_ids(ids);
55 CPPUNIT_ASSERT( ids.find(1) != ids.end() );
56 CPPUNIT_ASSERT( ids.find(2) != ids.end() );
58 _point_locator->enable_out_of_mesh_mode();
63 virtual std::unique_ptr<GhostingFunctor>
clone ()
const override 66 std::make_unique<OverlappingCouplingFunctor>(_system);
68 auto coupling_matrix =
69 std::make_unique<CouplingMatrix>(*_coupling_matrix);
70 clone_functor->set_coupling_matrix(coupling_matrix);
75 { _coupling_matrix = std::move(coupling_matrix); }
77 virtual void operator()
81 map_type & coupled_elements)
override 83 std::unique_ptr<PointLocatorBase> sub_point_locator = _mesh.sub_point_locator();
85 for(
const auto & elem :
as_range(range_begin,range_end) )
87 std::set<subdomain_id_type> allowed_subdomains;
89 if( elem->subdomain_id() == 1 )
91 var = _system.variable_number(
"V");
92 allowed_subdomains.insert(2);
94 else if( elem->subdomain_id() == 2 )
96 var = _system.variable_number(
"U");
97 allowed_subdomains.insert(1);
100 CPPUNIT_FAIL(
"Something bad happpend");
102 unsigned int dim = 2;
103 FEType fe_type = _system.variable_type(var);
106 fe->attach_quadrature_rule (&qrule);
108 const std::vector<libMesh::Point> & qpoints = fe->get_xyz();
112 for (
const auto & qp : qpoints )
114 const Elem * overlapping_elem = (*sub_point_locator)( qp, &allowed_subdomains );
116 if( overlapping_elem && overlapping_elem->
processor_id() != p )
117 coupled_elements.emplace(overlapping_elem, _coupling_matrix.get());
153 virtual std::unique_ptr<Partitioner>
clone ()
const override 155 return std::make_unique<OverlappingTestPartitioner>(*this);
164 const unsigned int n)
override 168 this->single_partition_range (
mesh.active_elements_begin(),
mesh.active_elements_end());
171 libmesh_assert_greater (n, 0);
178 for (
auto & elem :
mesh.active_element_ptr_range() )
180 elem->processor_id() = e;
189 unsigned int n_sub_two_elems =
std::distance(
mesh.active_subdomain_elements_begin(2),
190 mesh.active_subdomain_elements_end(2) );
192 unsigned int n_parts_sub_two = 0;
193 if( n_sub_two_elems < n/2 )
194 n_parts_sub_two = n_sub_two_elems;
196 n_parts_sub_two = n/2;
198 const unsigned int n_parts_sub_one = n - n_parts_sub_two;
200 const dof_id_type sub_two_blk_size = cast_int<dof_id_type>
202 mesh.active_subdomain_elements_end(2) )/n_parts_sub_two );
204 this->assign_proc_id_subdomain(
mesh, 2, sub_two_blk_size, n_parts_sub_two, 0 );
207 const dof_id_type sub_one_blk_size = cast_int<dof_id_type>
209 mesh.active_subdomain_elements_end(1) )/n_parts_sub_one );
211 this->assign_proc_id_subdomain(
mesh, 1, sub_one_blk_size, n_parts_sub_one, n_parts_sub_two );
219 const unsigned int n_parts,
225 if ((e/blksize) < n_parts)
226 elem->processor_id() = offset + cast_int<processor_id_type>(e/blksize);
228 elem->processor_id() = offset;
247 std::unique_ptr<EquationSystems>
_es;
254 _mesh = std::make_unique<ReplicatedMesh>(*TestCommWorld);
256 _mesh->set_mesh_dimension(2);
258 _mesh->add_point(
Point(0.0,0.0),0 );
259 _mesh->add_point(
Point(1.0,0.0),1 );
260 _mesh->add_point(
Point(1.0,1.0),2 );
261 _mesh->add_point(
Point(0.0,1.0),3 );
267 for (
unsigned int n=0; n<4; n++)
268 elem->
set_node(n, _mesh->node_ptr(n));
271 _mesh->add_point(
Point(1.0,2.0),4 );
272 _mesh->add_point(
Point(0.0,2.0),5 );
278 elem->
set_node(0, _mesh->node_ptr(3));
279 elem->
set_node(1, _mesh->node_ptr(2));
280 elem->
set_node(2, _mesh->node_ptr(4));
281 elem->
set_node(3, _mesh->node_ptr(5));
284 _mesh->add_point(
Point(0.0,0.0),6 );
285 _mesh->add_point(
Point(1.0,0.0),7 );
286 _mesh->add_point(
Point(1.0,2.0),8 );
287 _mesh->add_point(
Point(0.0,2.0),9 );
293 elem->
set_node(0, _mesh->node_ptr(6));
294 elem->
set_node(1, _mesh->node_ptr(7));
295 elem->
set_node(2, _mesh->node_ptr(8));
296 elem->
set_node(3, _mesh->node_ptr(9));
299 _mesh->partitioner() = std::make_unique<OverlappingTestPartitioner>();
301 _mesh->prepare_for_use();
303 #ifdef LIBMESH_ENABLE_AMR 304 if (n_refinements > 0)
310 CPPUNIT_ASSERT_EQUAL(n_refinements, 0u);
311 #endif // LIBMESH_ENABLE_AMR 316 _es = std::make_unique<EquationSystems>(*_mesh);
319 std::set<subdomain_id_type> sub_one;
322 std::set<subdomain_id_type> sub_two;
342 System & system = _es->get_system(
"SimpleSystem");
344 coupling = std::make_unique<CouplingMatrix>(system.
n_vars());
353 (*coupling)(u_var,v_var) =
true;
354 (*coupling)(l_var,v_var) =
true;
355 (*coupling)(l_var,p_var) =
true;
356 (*coupling)(v_var,u_var) =
true;
357 (*coupling)(v_var,l_var) =
true;
372 #ifdef LIBMESH_HAVE_SOLVER 373 CPPUNIT_TEST( checkCouplingFunctorQuad );
374 CPPUNIT_TEST( checkCouplingFunctorTri );
375 CPPUNIT_TEST( checkOverlappingPartitioner );
376 # ifdef LIBMESH_ENABLE_AMR 377 CPPUNIT_TEST( checkCouplingFunctorQuadUnifRef );
378 CPPUNIT_TEST( checkCouplingFunctorTriUnifRef );
379 CPPUNIT_TEST( checkOverlappingPartitionerUnifRef );
383 CPPUNIT_TEST_SUITE_END();
390 this->build_quad_mesh();
398 { this->run_coupling_functor_test(0); }
401 { this->run_coupling_functor_test(1); }
407 this->run_coupling_functor_test(0);
414 this->run_coupling_functor_test(1);
419 this->run_partitioner_test(0);
424 this->run_partitioner_test(1);
435 #if defined(LIBMESH_ENABLE_AMR) && defined(LIBMESH_HAVE_SOLVER) 436 if( n_refinements > 0 )
443 CPPUNIT_ASSERT_EQUAL(n_refinements, 0u);
446 System & system = _es->get_system(
"SimpleSystem");
453 coupling_functor( _mesh->active_subdomain_elements_begin(1),
454 _mesh->active_subdomain_elements_end(1),
456 subdomain_one_couplings );
458 coupling_functor( _mesh->active_subdomain_elements_begin(2),
459 _mesh->active_subdomain_elements_end(2),
461 subdomain_two_couplings );
464 _mesh->active_subdomain_elements_end(2) );
466 CPPUNIT_ASSERT_EQUAL(n_elems_subdomain_two, static_cast<dof_id_type>(subdomain_one_couplings.size()));
467 CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(2*n_elems_subdomain_two), static_cast<dof_id_type>(subdomain_two_couplings.size()));
472 #ifdef LIBMESH_ENABLE_AMR 473 if( n_refinements > 0 )
480 CPPUNIT_ASSERT_EQUAL(n_refinements, 0u);
481 #endif // LIBMESH_ENABLE_AMR 483 System & system = _es->get_system(
"SimpleSystem");
485 std::set<processor_id_type> sub_one_proc_ids, sub_two_proc_ids;
486 for (
auto & elem : _mesh->active_subdomain_elements_ptr_range(1))
487 sub_one_proc_ids.insert(elem->processor_id());
489 for (
auto & elem : _mesh->active_subdomain_elements_ptr_range(2))
490 sub_two_proc_ids.insert(elem->processor_id());
496 CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(sub_one_proc_ids.size()));
497 CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(sub_two_proc_ids.size()));
498 CPPUNIT_ASSERT( sub_one_proc_ids == sub_two_proc_ids );
504 for (
auto &
id : sub_one_proc_ids )
505 CPPUNIT_ASSERT( sub_two_proc_ids.find(
id) == sub_two_proc_ids.end() );
508 for (
auto &
id : sub_two_proc_ids )
509 CPPUNIT_ASSERT( sub_one_proc_ids.find(
id) == sub_one_proc_ids.end() );
516 #ifdef LIBMESH_HAVE_PETSC 527 CPPUNIT_TEST( testGhostingCouplingMatrix );
528 CPPUNIT_TEST( testGhostingNullCouplingMatrix );
529 #ifdef LIBMESH_ENABLE_AMR 530 CPPUNIT_TEST( testGhostingNullCouplingMatrixUnifRef );
533 CPPUNIT_TEST_SUITE_END();
546 this->run_ghosting_test(0,
true);
552 this->run_ghosting_test(0,
false);
558 std::unique_ptr<CouplingMatrix> coupling_matrix;
560 this->run_ghosting_test(2,
false);
567 this->build_quad_mesh(n_refinements);
570 std::unique_ptr<CouplingMatrix> coupling_matrix;
571 if (build_coupling_matrix)
572 this->setup_coupling_matrix(coupling_matrix);
580 functor.set_coupling_matrix(coupling_matrix);
595 std::unique_ptr<PointLocatorBase> point_locator = _mesh->sub_point_locator();
607 for (
const auto & elem : _mesh->active_local_subdomain_elements_ptr_range(2))
610 CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(elem->subdomain_id()));
613 const std::vector<libMesh::Point> & qpoints = subdomain_two_context.
get_element_fe(u_var)->get_xyz();
619 std::set<subdomain_id_type> allowed_subdomains;
620 allowed_subdomains.insert(1);
626 for (
const auto & qp : qpoints )
628 const Elem * overlapping_elem = (*point_locator)( qp, &allowed_subdomains );
629 CPPUNIT_ASSERT(overlapping_elem);
632 subdomain_one_context.
pre_fe_reinit(system,overlapping_elem);
649 CPPUNIT_TEST( testSparsityCouplingMatrix );
650 CPPUNIT_TEST( testSparsityNullCouplingMatrix );
651 #ifdef LIBMESH_ENABLE_AMR 652 CPPUNIT_TEST( testSparsityNullCouplingMatrixUnifRef );
655 CPPUNIT_TEST_SUITE_END();
668 this->run_sparsity_pattern_test(0,
true);
674 this->run_sparsity_pattern_test(0,
false);
680 this->run_sparsity_pattern_test(1,
false);
687 this->build_quad_mesh(n_refinements);
690 std::unique_ptr<CouplingMatrix> coupling_matrix;
691 if (build_coupling_matrix)
692 this->setup_coupling_matrix(coupling_matrix);
700 coupling_functor.set_coupling_matrix(coupling_matrix);
726 std::unique_ptr<PointLocatorBase> point_locator = _mesh->sub_point_locator();
742 for (
const auto & elem : _mesh->active_local_subdomain_elements_ptr_range(1))
747 std::vector<dof_id_type> & rows = subdomain_one_context.
get_dof_indices();
758 for (
const auto & elem : _mesh->active_local_subdomain_elements_ptr_range(2))
761 CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(elem->subdomain_id()));
763 const std::vector<libMesh::Point> & qpoints = subdomain_two_context.
get_element_fe(u_var)->get_xyz();
771 std::vector<dof_id_type> & rows = subdomain_two_context.
get_dof_indices();
780 std::set<subdomain_id_type> allowed_subdomains;
781 allowed_subdomains.insert(1);
787 for (
const auto & qp : qpoints )
789 const Elem * overlapping_elem = (*point_locator)( qp, &allowed_subdomains );
790 CPPUNIT_ASSERT(overlapping_elem);
793 subdomain_one_context.
pre_fe_reinit(system,overlapping_elem);
797 std::vector<dof_id_type> & v_indices = subdomain_one_context.
get_dof_indices(v_var);
798 std::vector<dof_id_type> columns(rows);
799 columns.insert( columns.end(), v_indices.begin(), v_indices.end() );
802 K21.
resize( rows.size(), columns.size() );
812 K12.
resize(v_indices.size(), rows.size());
825 #endif // LIBMESH_HAVE_PETSC 830 #ifdef LIBMESH_HAVE_PETSC class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
void run_coupling_functor_test(unsigned int n_refinements)
OverlappingCouplingFunctor(System &system)
void checkOverlappingPartitionerUnifRef()
const DenseMatrix< Number > & get_elem_jacobian() const
Const accessor for element Jacobian.
static constexpr processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
virtual Node *& set_node(const unsigned int i)
virtual dof_id_type n_active_elem() const =0
This abstract base class defines the interface by which library code and user code can report associa...
virtual void pre_fe_reinit(const System &, const Elem *e)
Reinitializes local data vectors/matrices on the current geometric element.
void checkCouplingFunctorTriUnifRef()
void setup_coupling_matrix(std::unique_ptr< CouplingMatrix > &coupling)
The definition of the const_element_iterator struct.
void testSparsityNullCouplingMatrixUnifRef()
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
virtual std::unique_ptr< Partitioner > clone() const override
bool is_attached(SparseMatrix< Number > &matrix)
Matrices should not be attached more than once.
void testSparsityNullCouplingMatrix()
This is the base class from which all geometric element types are derived.
void checkCouplingFunctorQuad()
const Parallel::Communicator & comm() const
Order default_quadrature_order() const
std::unique_ptr< CouplingMatrix > _coupling_matrix
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?
void checkCouplingFunctorQuadUnifRef()
The libMesh namespace provides an interface to certain functionality in the library.
dof_id_type n_local_dofs() const
void run_partitioner_test(unsigned int n_refinements)
const MeshBase & get_mesh() const
Real distance(const Point &p)
void add_coupling_functor(GhostingFunctor &coupling_functor, bool to_mesh=true)
Adds a functor which can specify coupling requirements for creation of sparse matrices.
void testGhostingCouplingMatrix()
dof_id_type n_dofs() const
This is the MeshBase class.
virtual void elem_fe_reinit(const std::vector< Point > *const pts=nullptr)
Reinitializes interior FE objects on the current geometric element.
The Partitioner class provides a uniform interface for partitioning algorithms.
unsigned int variable_number(std::string_view var) const
std::unique_ptr< MeshBase > _mesh
std::unique_ptr< EquationSystems > _es
virtual void _do_partition(MeshBase &mesh, const unsigned int n) override
Partition the MeshBase into n subdomains.
virtual ~OverlappingCouplingFunctor()
std::unique_ptr< PointLocatorBase > _point_locator
void testGhostingNullCouplingMatrix()
virtual std::unique_ptr< GhostingFunctor > clone() const override
A clone() is needed because GhostingFunctor can not be shared between different meshes.
This class handles the numbering of degrees of freedom on a mesh.
void build_quad_mesh(unsigned int n_refinements=0)
void checkCouplingFunctorTri()
uint8_t processor_id_type
void reinit_send_list(MeshBase &mesh)
Clears the _send_list vector and then rebuilds it.
processor_id_type n_processors() const
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.
Implements (adaptive) mesh refinement algorithms for a MeshBase.
CPPUNIT_TEST_SUITE_REGISTRATION(OverlappingFunctorTest)
void assign_proc_id_subdomain(MeshBase &mesh, const subdomain_id_type sid, const dof_id_type blksize, const unsigned int n_parts, const processor_id_type offset)
Manages consistently variables, degrees of freedom, and coefficient vectors.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
This class provides all data required for a physics package (e.g.
const std::vector< dof_id_type > & get_dof_indices() const
Accessor for element dof indices.
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.
void run_ghosting_test(const unsigned int n_refinements, bool build_coupling_matrix)
std::vector< T > & get_values()
void testGhostingNullCouplingMatrixUnifRef()
virtual void close()=0
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
void set_coupling_matrix(std::unique_ptr< CouplingMatrix > &coupling_matrix)
subdomain_id_type subdomain_id() const
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 resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
void checkOverlappingPartitioner()
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...
void clear_sparsity()
Clears the sparsity pattern.
This class implements specific orders of Gauss quadrature.
unsigned int level ElemType type std::set< subdomain_id_type > ss processor_id_type pid unsigned int level std::set< subdomain_id_type > virtual ss SimpleRange< element_iterator > active_subdomain_elements_ptr_range(subdomain_id_type sid)=0
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
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...
void run_sparsity_pattern_test(const unsigned int n_refinements, bool build_coupling_matrix)
unsigned int n_vars() const
void testSparsityCouplingMatrix()
void compute_sparsity(const MeshBase &)
Computes the sparsity pattern for the matrices corresponding to proc_id and sends that data to Linear...
void add_algebraic_ghosting_functor(GhostingFunctor &evaluable_functor, bool to_mesh=true)
Adds a functor which can specify algebraic ghosting requirements for use with distributed vectors...
const DofMap & get_dof_map() const
processor_id_type processor_id() const
A Point defines a location in LIBMESH_DIM dimensional Real space.
const SparseMatrix< Number > & get_system_matrix() const
const std::vector< dof_id_type > & get_send_list() const
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.
void uniformly_refine(unsigned int n=1)
Uniformly refines the mesh n times.