v0.16.3
Loading...
Searching...
No Matches
entities_petsc_vector.cpp
Go to the documentation of this file.
1/** \file entities_petsc_vector.cpp
2 * \brief Exchange vectors with imported partition labels in serial and parallel.
3 */
4#include <MoFEM.hpp>
5using namespace MoFEM;
6
7namespace {
8
9MoFEMErrorCode checkExchange(moab::Interface &moab, ParallelComm &pcomm,
10 bool include_vertices) {
12 constexpr int nb_coeffs = 2;
14 PETSC_COMM_WORLD, moab,
15 [include_vertices](Range ents) {
16 auto selected = ents.subset_by_type(MBTRI);
17 if (include_vertices)
18 selected.merge(ents.subset_by_type(MBVERTEX));
19 return selected;
20 },
21 nb_coeffs, Sev::inform, 0, include_vertices);
22 const auto &owned = exchange.first.first;
23 const auto &ghosts = exchange.first.second;
24 const int entities_per_part = include_vertices ? 4 : 1;
25 const int expected_owned = entities_per_part * (pcomm.size() == 1 ? 2 : 1);
26 const int expected_ghosts = pcomm.size() == 1 ? 0 : entities_per_part;
27 if (owned.size() != expected_owned || ghosts.size() != expected_ghosts)
28 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
29 "Unexpected owned/ghost entity counts: %d/%d, expected %d/%d",
30 static_cast<int>(owned.size()), static_cast<int>(ghosts.size()),
31 expected_owned, expected_ghosts);
32 PetscInt local_size, global_size;
33 CHKERR VecGetLocalSize(exchange.second, &local_size);
34 CHKERR VecGetSize(exchange.second, &global_size);
35 if (local_size != nb_coeffs * expected_owned ||
36 global_size != nb_coeffs * entities_per_part * 2)
37 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
38 "Exchange vector omits mesh entities");
39
40 const auto gid_tag = moab.globalId_tag();
41 std::vector<int> gids(owned.size());
42 CHKERR moab.tag_get_data(gid_tag, owned, gids.data());
43 PetscScalar *values;
44 CHKERR VecGetArray(exchange.second, &values);
45 for (size_t e = 0; e != gids.size(); ++e)
46 for (int c = 0; c != nb_coeffs; ++c)
47 values[nb_coeffs * e + c] = nb_coeffs * gids[e] + c;
48 CHKERR VecRestoreArray(exchange.second, &values);
49 CHKERR VecGhostUpdateBegin(exchange.second, INSERT_VALUES, SCATTER_FORWARD);
50 CHKERR VecGhostUpdateEnd(exchange.second, INSERT_VALUES, SCATTER_FORWARD);
51
52 // Check entity identity as well as vector sizes: a valid scatter can still
53 // exchange values for the wrong entity if the GLOBAL_ID mapping is incorrect.
54 gids.resize(ghosts.size());
55 CHKERR moab.tag_get_data(gid_tag, ghosts, gids.data());
56 Vec local_form;
57 const PetscScalar *local_values;
58 CHKERR VecGhostGetLocalForm(exchange.second, &local_form);
59 CHKERR VecGetArrayRead(local_form, &local_values);
60 bool valid = true;
61 for (size_t e = 0; e != gids.size(); ++e)
62 for (int c = 0; c != nb_coeffs; ++c)
63 valid = valid && local_values[local_size + nb_coeffs * e + c] ==
64 nb_coeffs * gids[e] + c;
65 CHKERR VecRestoreArrayRead(local_form, &local_values);
66 CHKERR VecGhostRestoreLocalForm(exchange.second, &local_form);
67 if (!valid)
68 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
69 "Ghost values do not match the owning entities");
71}
72
73MoFEMErrorCode checkSerialFiniteElements(moab::Interface &moab) {
75 Range faces, edges;
76 CHKERR moab.get_entities_by_type(0, MBTRI, faces);
77 CHKERR moab.get_adjacencies(faces, 1, true, edges, moab::Interface::UNION);
78 int gid = 9;
79 for (auto edge : edges) {
80 CHKERR moab.tag_set_data(moab.globalId_tag(), &edge, 1, &gid);
81 ++gid;
82 }
83 MoFEM::Core core(moab);
84 MoFEM::Interface &m_field = core;
85 const auto level = BitRefLevel().set(0);
86 CHKERR m_field.getInterface<BitRefManager>()->setBitRefLevelByDim(0, 2,
87 level);
88 CHKERR m_field.add_field("TEST_FIELD", L2, AINSWORTH_LEGENDRE_BASE, 1);
89 CHKERR m_field.add_ents_to_field_by_type(0, MBTRI, "TEST_FIELD");
90 CHKERR m_field.set_field_order(0, MBTRI, "TEST_FIELD", 0);
91 CHKERR m_field.add_finite_element("TEST_FE");
92 CHKERR m_field.modify_finite_element_add_field_row("TEST_FE", "TEST_FIELD");
93 CHKERR m_field.modify_finite_element_add_field_col("TEST_FE", "TEST_FIELD");
94 CHKERR m_field.modify_finite_element_add_field_data("TEST_FE", "TEST_FIELD");
95 CHKERR m_field.add_ents_to_finite_element_by_type(0, MBTRI, "TEST_FE");
96 CHKERR m_field.add_problem("TEST_PROBLEM");
97 CHKERR m_field.modify_problem_add_finite_element("TEST_PROBLEM", "TEST_FE");
98 CHKERR m_field.modify_problem_ref_level_add_bit("TEST_PROBLEM", level);
99 CHKERR m_field.build_fields();
101 CHKERR m_field.build_adjacencies(level);
102 auto *problems = m_field.getInterface<ProblemsManager>();
103 CHKERR problems->buildProblem("TEST_PROBLEM", true);
104 CHKERR problems->partitionSimpleProblem("TEST_PROBLEM");
105 CHKERR problems->partitionFiniteElements("TEST_PROBLEM", true);
106 const Problem *problem;
107 CHKERR m_field.get_problem("TEST_PROBLEM", &problem);
108 if (problem->numeredFiniteElementsPtr->size() != 2)
109 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
110 "Serial problem lost a finite element from the imported mesh");
111 for (const auto &fe : *problem->numeredFiniteElementsPtr)
112 if (fe->getPart() != 0)
113 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
114 "Serial finite element still belongs to imported partition %d",
115 static_cast<int>(fe->getPart()));
117}
118
119MoFEMErrorCode runTest(moab::Interface &moab, ParallelComm &pcomm) {
121 if (pcomm.size() > 2)
122 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
123 "This fixture requires one or two MPI ranks");
124 const auto gid_tag = moab.globalId_tag();
125 const auto part_tag = pcomm.part_tag();
126 // Two disconnected triangles replicate a mesh imported with two partitions.
127 // Keep both labels even in serial to exercise the reported failure.
128 for (int part = 0; part != 2; ++part) {
129 const double x = 2. * part;
130 const double coords[] = {x, 0., 0., x + 1., 0., 0., x, 1., 0.};
131 Range vertices;
132 CHKERR moab.create_vertices(coords, 3, vertices);
133 const EntityHandle conn[] = {vertices[0], vertices[1], vertices[2]};
134 EntityHandle face, meshset;
135 CHKERR moab.create_element(MBTRI, conn, 3, face);
136 CHKERR moab.create_meshset(MESHSET_SET, meshset);
137 CHKERR moab.add_entities(meshset, &face, 1);
138 CHKERR moab.tag_set_data(part_tag, &meshset, 1, &part);
139 CHKERR moab.tag_set_data(pcomm.partition_tag(), &face, 1, &part);
140 const int face_gid = part + 1;
141 const int vertex_gids[] = {3 + 3 * part, 4 + 3 * part, 5 + 3 * part};
142 CHKERR moab.tag_set_data(gid_tag, &face, 1, &face_gid);
143 CHKERR moab.tag_set_data(gid_tag, vertices, vertex_gids);
144 }
145 CHKERR checkExchange(moab, pcomm, false);
146 CHKERR checkExchange(moab, pcomm, true);
147 if (pcomm.size() == 1)
148 CHKERR checkSerialFiniteElements(moab);
150}
151
152} // namespace
153
154int main(int argc, char *argv[]) {
155 MoFEM::Core::Initialize(&argc, &argv, nullptr,
156 "Entity exchange with imported partition labels\n");
157 try {
158 moab::Core moab_core;
159 ParallelComm pcomm(&moab_core, PETSC_COMM_WORLD);
160 CHKERR runTest(moab_core, pcomm);
161 }
164 return 0;
165}
SmartPetscObj< Vec > values
int main()
#define CATCH_ERRORS
Catch errors.
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ L2
field with C-1 continuity
Definition definitions.h:88
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_ATOM_TEST_INVALID
Definition definitions.h:40
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
virtual const Problem * get_problem(const std::string problem_name) const =0
Get the problem object.
virtual MoFEMErrorCode add_finite_element(const std::string &fe_name, enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
add finite element
virtual MoFEMErrorCode build_finite_elements(int verb=DEFAULT_VERBOSITY)=0
Build finite elements.
virtual MoFEMErrorCode modify_finite_element_add_field_col(const std::string &fe_name, const std::string name_row)=0
set field col which finite element use
virtual MoFEMErrorCode add_ents_to_finite_element_by_type(const EntityHandle entities, const EntityType type, const std::string name, const bool recursive=true)=0
add entities to finite element
virtual MoFEMErrorCode modify_finite_element_add_field_row(const std::string &fe_name, const std::string name_row)=0
set field row which finite element use
virtual MoFEMErrorCode modify_finite_element_add_field_data(const std::string &fe_name, const std::string name_field)=0
set finite element field data
virtual MoFEMErrorCode build_fields(int verb=DEFAULT_VERBOSITY)=0
virtual MoFEMErrorCode set_field_order(const EntityHandle meshset, const EntityType type, const std::string &name, const ApproximationOrder order, int verb=DEFAULT_VERBOSITY)=0
Set order approximation of the entities in the field.
virtual MoFEMErrorCode add_ents_to_field_by_type(const Range &ents, const EntityType type, const std::string &name, int verb=DEFAULT_VERBOSITY)=0
Add entities to field meshset.
MoFEMErrorCode buildProblem(const std::string name, const bool square_matrix, int verb=VERBOSE)
build problem data structures
virtual MoFEMErrorCode add_problem(const std::string &name, enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
Add problem.
virtual MoFEMErrorCode modify_problem_ref_level_add_bit(const std::string &name_problem, const BitRefLevel &bit)=0
add ref level to problem
virtual MoFEMErrorCode modify_problem_add_finite_element(const std::string name_problem, const std::string &fe_name)=0
add finite element to problem, this add entities assigned to finite element to a particular problem
const double c
speed of light (cm/ns)
const FTensor::Tensor2< T, Dim, Dim > Vec
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
Definition Types.hpp:40
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
Managing BitRefLevels.
static EntitiesPetscVector createEntitiesPetscVector(MPI_Comm comm, moab::Interface &moab, std::function< Range(Range)> get_entities_fun, const int nb_coeffs, Sev sev=Sev::verbose, int root_rank=0, bool get_vertices=true)
Create a ghost vector for exchanging data.
virtual MoFEMErrorCode build_adjacencies(const Range &ents, int verb=DEFAULT_VERBOSITY)=0
build adjacencies
virtual MoFEMErrorCode add_field(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
Add field.
Core (interface) class.
Definition Core.hpp:83
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition Core.cpp:68
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition Core.cpp:123
Deprecated interface functions.
keeps basic data about problem
boost::shared_ptr< NumeredEntFiniteElement_multiIndex > numeredFiniteElementsPtr
store finite elements
Problem manager is used to build and partition problems.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.