v0.15.0
Loading...
Searching...
No Matches
Files | Classes | Functions
ProblemsManager

Adding and managing problems. More...

Collaboration diagram for ProblemsManager:

Files

file  ProblemsManager.cpp
 Managing complexities for problem.
 
file  ProblemsManager.hpp
 Interface managing problems.
 

Classes

struct  MoFEM::ProblemsManager
 Problem manager is used to build and partition problems. More...
 

Functions

DEPRECATED MoFEMErrorCode MoFEM::ProblemsManager::partitionMesh (const Range &ents, const int dim, const int adj_dim, const int n_parts, Tag *th_vertex_weights=nullptr, Tag *th_edge_weights=nullptr, Tag *th_part_weights=nullptr, int verb=VERBOSE, const bool debug=false)
 Set partition tag to each finite element in the problem.
 
MoFEMErrorCode MoFEM::ProblemsManager::buildProblem (const std::string name, const bool square_matrix, int verb=VERBOSE)
 build problem data structures
 
MoFEMErrorCode MoFEM::ProblemsManager::buildProblem (Problem *problem_ptr, const bool square_matrix, int verb=VERBOSE)
 build problem data structures
 
MoFEMErrorCode MoFEM::ProblemsManager::buildProblemOnDistributedMesh (const std::string name, const bool square_matrix, int verb=VERBOSE)
 build problem data structures, assuming that mesh is distributed (collective)
 
MoFEMErrorCode MoFEM::ProblemsManager::buildProblemOnDistributedMesh (Problem *problem_ptr, const bool square_matrix=true, int verb=VERBOSE)
 build problem data structures, assuming that mesh is distributed (collective)
 
MoFEMErrorCode MoFEM::ProblemsManager::buildSubProblem (const std::string out_name, const std::vector< std::string > &fields_row, const std::vector< std::string > &fields_col, const std::string main_problem, const bool square_matrix=true, const map< std::string, boost::shared_ptr< Range > > *entityMapRow=nullptr, const map< std::string, boost::shared_ptr< Range > > *entityMapCol=nullptr, int verb=VERBOSE)
 build sub problem
 
MoFEMErrorCode MoFEM::ProblemsManager::buildComposedProblem (const std::string out_name, const std::vector< std::string > add_row_problems, const std::vector< std::string > add_col_problems, const bool square_matrix=true, int verb=1)
 build composite problem
 
MoFEMErrorCode MoFEM::ProblemsManager::inheritPartition (const std::string name, const std::string problem_for_rows, bool copy_rows, const std::string problem_for_cols, bool copy_cols, int verb=VERBOSE)
 build indexing and partition problem inheriting indexing and partitioning from two other problems
 
MoFEMErrorCode MoFEM::ProblemsManager::partitionSimpleProblem (const std::string name, int verb=VERBOSE)
 partition problem dofs
 
MoFEMErrorCode MoFEM::ProblemsManager::partitionProblem (const std::string name, int verb=VERBOSE)
 partition problem dofs (collective)
 
MoFEMErrorCode MoFEM::ProblemsManager::partitionFiniteElements (const std::string name, bool part_from_moab=false, int low_proc=-1, int hi_proc=-1, int verb=VERBOSE)
 partition finite elements
 
MoFEMErrorCode MoFEM::ProblemsManager::partitionGhostDofs (const std::string name, int verb=VERBOSE)
 determine ghost nodes
 
MoFEMErrorCode MoFEM::ProblemsManager::partitionGhostDofsOnDistributedMesh (const std::string name, int verb=VERBOSE)
 determine ghost nodes on distributed meshes
 
MoFEMErrorCode MoFEM::ProblemsManager::getFEMeshset (const std::string prb_name, const std::string &fe_name, EntityHandle *meshset) const
 create add entities of finite element in the problem
 
MoFEMErrorCode MoFEM::ProblemsManager::getProblemElementsLayout (const std::string name, const std::string &fe_name, PetscLayout *layout) const
 Get layout of elements in the problem.
 
MoFEMErrorCode MoFEM::ProblemsManager::removeDofsOnEntities (const std::string problem_name, const std::string field_name, const Range ents, const int lo_coeff=0, const int hi_coeff=MAX_DOFS_ON_ENTITY, const int lo_order=0, const int hi_order=100, int verb=VERBOSE, const bool debug=false)
 Remove DOFs from problem.
 
MoFEMErrorCode MoFEM::ProblemsManager::removeDofsOnEntities (const std::string problem_name, const std::string field_name, const BitRefLevel bit_ref_level, const BitRefLevel bit_ref_mask, Range *ents_ptr=nullptr, const int lo_coeff=0, const int hi_coeff=MAX_DOFS_ON_ENTITY, const int lo_order=0, const int hi_order=100, int verb=VERBOSE, const bool debug=false)
 Remove DOFs from problem by bit ref level.
 

Read load and boradcoast

@

MoFEMErrorCode MoFEM::CommInterface::partitionMesh (const Range &ents, const int dim, const int adj_dim, const int n_parts, Tag *th_vertex_weights=nullptr, Tag *th_edge_weights=nullptr, Tag *th_part_weights=nullptr, int verb=VERBOSE, const bool debug=false)
 Set partition tag to each finite element in the problem.
 

Detailed Description

Adding and managing problems.

Function Documentation

◆ buildComposedProblem()

MoFEMErrorCode MoFEM::ProblemsManager::buildComposedProblem ( const std::string  out_name,
const std::vector< std::string >  add_row_problems,
const std::vector< std::string >  add_col_problems,
const bool  square_matrix = true,
int  verb = 1 
)

build composite problem

Parameters
out_namename of build problem
add_row_problemsvector of add row problems
add_col_problemsvector of add col problems
square_matrixtrue if structurally squared matrix
verbverbosity level
Returns
error code

Definition at line 1246 of file ProblemsManager.cpp.

1249 {
1251 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "fields not build");
1253 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "FEs not build");
1255 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "adjacencies not build");
1256 MoFEM::Interface &m_field = cOre;
1257 auto problems_ptr = m_field.get_problems();
1259
1260 CHKERR m_field.clear_problem(out_name);
1261 // get reference to all problems
1262 typedef Problem_multiIndex::index<Problem_mi_tag>::type ProblemByName;
1263 ProblemByName &problems_by_name =
1264 const_cast<ProblemByName &>(problems_ptr->get<Problem_mi_tag>());
1265
1266 // Get iterators to out problem, i.e. build problem
1267 ProblemByName::iterator out_problem_it = problems_by_name.find(out_name);
1268 if (out_problem_it == problems_by_name.end()) {
1269 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1270 "problem with name < %s > not defined (top tip check spelling)",
1271 out_name.c_str());
1272 }
1273 // Make data structure for composed-problem data
1274 out_problem_it->composedProblemsData =
1275 boost::make_shared<ComposedProblemsData>();
1276 boost::shared_ptr<ComposedProblemsData> cmp_prb_data =
1277 out_problem_it->getComposedProblemsData();
1278
1279 const std::vector<std::string> *add_prb[] = {&add_row_problems,
1280 &add_col_problems};
1281 std::vector<const Problem *> *add_prb_ptr[] = {&cmp_prb_data->rowProblemsAdd,
1282 &cmp_prb_data->colProblemsAdd};
1283 std::vector<SmartPetscObj<IS>> *add_prb_is[] = {&cmp_prb_data->rowIs,
1284 &cmp_prb_data->colIs};
1285
1286 // Get local indices counter
1287 int *nb_local_dofs[] = {&out_problem_it->nbLocDofsRow,
1288 &out_problem_it->nbLocDofsCol};
1289 // Get global indices counter
1290 int *nb_dofs[] = {&out_problem_it->nbDofsRow, &out_problem_it->nbDofsCol};
1291
1292 // Set number of ghost nodes to zero
1293 {
1294 out_problem_it->nbDofsRow = 0;
1295 out_problem_it->nbDofsCol = 0;
1296 out_problem_it->nbLocDofsRow = 0;
1297 out_problem_it->nbLocDofsCol = 0;
1298 out_problem_it->nbGhostDofsRow = 0;
1299 out_problem_it->nbGhostDofsCol = 0;
1300 }
1301 int nb_dofs_reserve[] = {0, 0};
1302
1303 // Loop over rows and columns in the main problem and sub-problems
1304 for (int ss = 0; ss != ((square_matrix) ? 1 : 2); ss++) {
1305 add_prb_ptr[ss]->reserve(add_prb[ss]->size());
1306 add_prb_is[ss]->reserve(add_prb[ss]->size());
1307 for (std::vector<std::string>::const_iterator vit = add_prb[ss]->begin();
1308 vit != add_prb[ss]->end(); vit++) {
1309 ProblemByName::iterator prb_it = problems_by_name.find(*vit);
1310 if (prb_it == problems_by_name.end()) {
1311 SETERRQ(
1312 PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1313 "problem with name < %s > not defined (top tip check spelling)",
1314 vit->c_str());
1315 }
1316 add_prb_ptr[ss]->push_back(&*prb_it);
1317 // set number of dofs on rows and columns
1318 if (ss == 0) {
1319 // row
1320 *nb_dofs[ss] += add_prb_ptr[ss]->back()->getNbDofsRow();
1321 *nb_local_dofs[ss] += add_prb_ptr[ss]->back()->getNbLocalDofsRow();
1322 nb_dofs_reserve[ss] +=
1323 add_prb_ptr[ss]->back()->numeredRowDofsPtr->size();
1324 } else {
1325 // column
1326 *nb_dofs[ss] += add_prb_ptr[ss]->back()->getNbDofsCol();
1327 *nb_local_dofs[ss] += add_prb_ptr[ss]->back()->getNbLocalDofsCol();
1328 nb_dofs_reserve[ss] +=
1329 add_prb_ptr[ss]->back()->numeredColDofsPtr->size();
1330 }
1331 }
1332 }
1333 // if squre problem, rows and columns are the same
1334 if (square_matrix) {
1335 add_prb_ptr[1]->reserve(add_prb_ptr[0]->size());
1336 add_prb_is[1]->reserve(add_prb_ptr[0]->size());
1337 out_problem_it->numeredColDofsPtr = out_problem_it->numeredRowDofsPtr;
1338 *nb_dofs[1] = *nb_dofs[0];
1339 *nb_local_dofs[1] = *nb_local_dofs[0];
1340 }
1341
1342 // reserve memory for dofs
1343 boost::shared_ptr<std::vector<NumeredDofEntity>> dofs_array[2];
1344 // Reserve memory
1345 for (int ss = 0; ss != ((square_matrix) ? 1 : 2); ss++) {
1346 dofs_array[ss] = boost::make_shared<std::vector<NumeredDofEntity>>();
1347 dofs_array[ss]->reserve(nb_dofs_reserve[ss]);
1348 if (!ss)
1349 out_problem_it->getRowDofsSequence()->emplace_back(dofs_array[ss]);
1350 else
1351 out_problem_it->getColDofsSequence()->emplace_back(dofs_array[ss]);
1352 }
1353
1354 // Push back DOFs
1355 for (int ss = 0; ss != ((square_matrix) ? 1 : 2); ss++) {
1356 NumeredDofEntity_multiIndex::index<PetscGlobalIdx_mi_tag>::type::iterator
1357 dit,
1358 hi_dit;
1359 int shift_glob = 0;
1360 int shift_loc = 0;
1361 for (unsigned int pp = 0; pp != add_prb_ptr[ss]->size(); pp++) {
1362 PetscInt *dofs_out_idx_ptr;
1363 int nb_local_dofs = (*add_prb_ptr[ss])[pp]->getNbLocalDofsRow();
1364 CHKERR PetscMalloc(nb_local_dofs * sizeof(int), &dofs_out_idx_ptr);
1365 if (ss == 0) {
1366 dit = (*add_prb_ptr[ss])[pp]
1367 ->numeredRowDofsPtr->get<PetscGlobalIdx_mi_tag>()
1368 .begin();
1369 hi_dit = (*add_prb_ptr[ss])[pp]
1370 ->numeredRowDofsPtr->get<PetscGlobalIdx_mi_tag>()
1371 .end();
1372 } else {
1373 dit = (*add_prb_ptr[ss])[pp]
1374 ->numeredColDofsPtr->get<PetscGlobalIdx_mi_tag>()
1375 .begin();
1376 hi_dit = (*add_prb_ptr[ss])[pp]
1377 ->numeredColDofsPtr->get<PetscGlobalIdx_mi_tag>()
1378 .end();
1379 }
1380 int is_nb = 0;
1381 for (; dit != hi_dit; dit++) {
1382 const BitRefLevel &prb_bit = out_problem_it->getBitRefLevel();
1383 const BitRefLevel &prb_mask = out_problem_it->getBitRefLevelMask();
1384 const BitRefLevel &dof_bit = dit->get()->getBitRefLevel();
1385 if ((dof_bit & prb_bit).none() || ((dof_bit & prb_mask) != dof_bit))
1386 continue;
1387 const int rank = m_field.get_comm_rank();
1388 const int part = dit->get()->getPart();
1389 const int glob_idx = shift_glob + dit->get()->getPetscGlobalDofIdx();
1390 const int loc_idx =
1391 (part == rank) ? (shift_loc + dit->get()->getPetscLocalDofIdx())
1392 : -1;
1393 dofs_array[ss]->emplace_back(dit->get()->getDofEntityPtr(), glob_idx,
1394 glob_idx, loc_idx, part);
1395 if (part == rank) {
1396 dofs_out_idx_ptr[is_nb++] = glob_idx;
1397 }
1398 }
1399 if (is_nb > nb_local_dofs) {
1400 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
1401 "Data inconsistency");
1402 }
1403 IS is;
1404 CHKERR ISCreateGeneral(m_field.get_comm(), is_nb, dofs_out_idx_ptr,
1405 PETSC_OWN_POINTER, &is);
1406 auto smart_is = SmartPetscObj<IS>(is);
1407 (*add_prb_is[ss]).push_back(smart_is);
1408 if (ss == 0) {
1409 shift_glob += (*add_prb_ptr[ss])[pp]->getNbDofsRow();
1410 shift_loc += (*add_prb_ptr[ss])[pp]->getNbLocalDofsRow();
1411 } else {
1412 shift_glob += (*add_prb_ptr[ss])[pp]->getNbDofsCol();
1413 shift_loc += (*add_prb_ptr[ss])[pp]->getNbLocalDofsCol();
1414 }
1415 if (square_matrix) {
1416 (*add_prb_ptr[1]).push_back((*add_prb_ptr[0])[pp]);
1417 (*add_prb_is[1]).push_back(smart_is);
1418 }
1419 }
1420 }
1421
1422 if ((*add_prb_is[1]).size() != (*add_prb_is[0]).size()) {
1423 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY, "Data inconsistency");
1424 }
1425
1426 // Insert DOFs to problem multi-index
1427 for (int ss = 0; ss != ((square_matrix) ? 1 : 2); ss++) {
1428 auto hint = (ss == 0) ? out_problem_it->numeredRowDofsPtr->end()
1429 : out_problem_it->numeredColDofsPtr->end();
1430 for (auto &v : *dofs_array[ss])
1431 hint = (ss == 0) ? out_problem_it->numeredRowDofsPtr->emplace_hint(
1432 hint, dofs_array[ss], &v)
1433 : out_problem_it->numeredColDofsPtr->emplace_hint(
1434 hint, dofs_array[ss], &v);
1435 }
1436
1437 // Compress DOFs
1438 *nb_dofs[0] = 0;
1439 *nb_dofs[1] = 0;
1440 *nb_local_dofs[0] = 0;
1441 *nb_local_dofs[1] = 0;
1442 for (int ss = 0; ss != ((square_matrix) ? 1 : 2); ss++) {
1443
1444 boost::shared_ptr<NumeredDofEntity_multiIndex> dofs_ptr;
1445 if (ss == 0) {
1446 dofs_ptr = out_problem_it->numeredRowDofsPtr;
1447 } else {
1448 dofs_ptr = out_problem_it->numeredColDofsPtr;
1449 }
1450 NumeredDofEntityByUId::iterator dit, hi_dit;
1451 dit = dofs_ptr->get<Unique_mi_tag>().begin();
1452 hi_dit = dofs_ptr->get<Unique_mi_tag>().end();
1453 std::vector<int> idx;
1454 idx.reserve(std::distance(dit, hi_dit));
1455 // set dofs in order entity and dof number on entity
1456 for (; dit != hi_dit; dit++) {
1457 if (dit->get()->getPart() == (unsigned int)m_field.get_comm_rank()) {
1458 bool success = dofs_ptr->get<Unique_mi_tag>().modify(
1459 dit, NumeredDofEntity_local_idx_change((*nb_local_dofs[ss])++));
1460 if (!success) {
1461 SETERRQ(m_field.get_comm(), MOFEM_OPERATION_UNSUCCESSFUL,
1462 "modification unsuccessful");
1463 }
1464 idx.push_back(dit->get()->getPetscGlobalDofIdx());
1465 } else {
1466 if (dit->get()->getPetscLocalDofIdx() != -1) {
1467 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
1468 "local index should be negative");
1469 }
1470 }
1471 }
1472 if (square_matrix) {
1473 *nb_local_dofs[1] = *nb_local_dofs[0];
1474 }
1475
1476 // set new dofs mapping
1477 IS is;
1478 CHKERR ISCreateGeneral(m_field.get_comm(), idx.size(), &*idx.begin(),
1479 PETSC_USE_POINTER, &is);
1480 CHKERR ISGetSize(is, nb_dofs[ss]);
1481 if (square_matrix) {
1482 *nb_dofs[1] = *nb_dofs[0];
1483 }
1484
1485 AO ao;
1486 CHKERR AOCreateMappingIS(is, PETSC_NULLPTR, &ao);
1487 for (unsigned int pp = 0; pp != (*add_prb_is[ss]).size(); pp++)
1488 CHKERR AOApplicationToPetscIS(ao, (*add_prb_is[ss])[pp]);
1489
1490 // Set DOFs numeration
1491 {
1492 std::vector<int> idx_new;
1493 idx_new.reserve(dofs_ptr->size());
1494 for (NumeredDofEntityByUId::iterator dit =
1495 dofs_ptr->get<Unique_mi_tag>().begin();
1496 dit != dofs_ptr->get<Unique_mi_tag>().end(); dit++) {
1497 idx_new.push_back(dit->get()->getPetscGlobalDofIdx());
1498 }
1499 // set new global dofs numeration
1500 IS is_new;
1501 CHKERR ISCreateGeneral(m_field.get_comm(), idx_new.size(),
1502 &*idx_new.begin(), PETSC_USE_POINTER, &is_new);
1503 CHKERR AOApplicationToPetscIS(ao, is_new);
1504 // set global indices to multi-index
1505 std::vector<int>::iterator vit = idx_new.begin();
1506 for (NumeredDofEntityByUId::iterator dit =
1507 dofs_ptr->get<Unique_mi_tag>().begin();
1508 dit != dofs_ptr->get<Unique_mi_tag>().end(); dit++) {
1509 bool success =
1510 dofs_ptr->modify(dit, NumeredDofEntity_part_and_glob_idx_change(
1511 dit->get()->getPart(), *(vit++)));
1512 if (!success) {
1513 SETERRQ(m_field.get_comm(), MOFEM_OPERATION_UNSUCCESSFUL,
1514 "modification unsuccessful");
1515 }
1516 }
1517 CHKERR ISDestroy(&is_new);
1518 }
1519 CHKERR ISDestroy(&is);
1520 CHKERR AODestroy(&ao);
1521 }
1522
1523 CHKERR printPartitionedProblem(&*out_problem_it, verb);
1524 CHKERR debugPartitionedProblem(&*out_problem_it, verb);
1525
1526 // Inidcate that porble has been build
1529
1531}
#define ProblemManagerFunctionBegin
@ MOFEM_OPERATION_UNSUCCESSFUL
Definition definitions.h:34
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
virtual const Problem_multiIndex * get_problems() const =0
Get the problems object.
virtual MoFEMErrorCode clear_problem(const std::string name, int verb=DEFAULT_VERBOSITY)=0
clear problem
const double v
phase velocity of light in medium (cm/ns)
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
Definition Types.hpp:40
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
int & getBuildMoFEM() const
Get flags/semaphores for different stages.
Definition Core.hpp:225
Deprecated interface functions.
MoFEMErrorCode printPartitionedProblem(const Problem *problem_ptr, int verb=VERBOSE)
MoFEMErrorCode debugPartitionedProblem(const Problem *problem_ptr, int verb=VERBOSE)

◆ buildProblem() [1/2]

MoFEMErrorCode MoFEM::ProblemsManager::buildProblem ( const std::string  name,
const bool  square_matrix,
int  verb = VERBOSE 
)

build problem data structures

Note
If square_matrix is set to true, that indicate that problem is structurally symmetric, i.e. rows and columns have the same dofs and are indexed in the same way.
Parameters
nameproblem name
square_matrixstructurally symmetric problem
verbverbosity level
Returns
error code
Examples
build_problems.cpp, continuity_check_on_contact_prism_side_ele.cpp, continuity_check_on_skeleton_3d.cpp, forces_and_sources_testing_edge_element.cpp, forces_and_sources_testing_flat_prism_element.cpp, hcurl_divergence_operator_2d.cpp, mesh_insert_interface_atom.cpp, nonlinear_dynamics.cpp, nonlinear_elastic.cpp, prism_elements_from_surface.cpp, prism_polynomial_approximation.cpp, quad_polynomial_approximation.cpp, and remove_entities_from_problem_not_partitioned.cpp.

Definition at line 86 of file ProblemsManager.cpp.

88 {
89
90 MoFEM::Interface &m_field = cOre;
92 if (!(cOre.getBuildMoFEM() & (1 << 0)))
93 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "fields not build");
94 if (!(cOre.getBuildMoFEM() & (1 << 1)))
95 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "FEs not build");
96 if (!(cOre.getBuildMoFEM() & (1 << 2)))
97 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "adjacencies not build");
98 const Problem *problem_ptr;
99 CHKERR m_field.get_problem(name, &problem_ptr);
100 CHKERR buildProblem(const_cast<Problem *>(problem_ptr), square_matrix, verb);
101 cOre.getBuildMoFEM() |= 1 << 3; // It is assumed that user who uses this
102 // function knows what he is doing
104}
virtual const Problem * get_problem(const std::string problem_name) const =0
Get the problem object.
MoFEMErrorCode buildProblem(const std::string name, const bool square_matrix, int verb=VERBOSE)
build problem data structures

◆ buildProblem() [2/2]

MoFEMErrorCode MoFEM::ProblemsManager::buildProblem ( Problem problem_ptr,
const bool  square_matrix,
int  verb = VERBOSE 
)

build problem data structures

Note
If square_matrix is set to true, that indicate that problem is structurally symmetric, i.e. rows and columns have the same dofs and are indexed in the same way.
Parameters
problempointer
square_matrixstructurally symmetric problem
verbverbosity level
Returns
error code

Definition at line 106 of file ProblemsManager.cpp.

108 {
109 MoFEM::Interface &m_field = cOre;
110 auto dofs_field_ptr = m_field.get_dofs();
111 auto ents_field_ptr = m_field.get_field_ents();
112 auto adjacencies_ptr = m_field.get_ents_elements_adjacency();
114 PetscLogEventBegin(MOFEM_EVENT_ProblemsManager, 0, 0, 0, 0);
115
116 // Note: Only allowed changes on problem_ptr structure which not influence
117 // multi-index.
118
119 if (problem_ptr->getBitRefLevel().none()) {
120 SETERRQ(PETSC_COMM_SELF, 1, "problem <%s> refinement level not set",
121 problem_ptr->getName().c_str());
122 }
123 CHKERR m_field.clear_problem(problem_ptr->getName());
124
125 // zero finite elements
126 problem_ptr->numeredFiniteElementsPtr->clear();
127
128 DofEntity_multiIndex_active_view dofs_rows, dofs_cols;
129 auto make_rows_and_cols_view = [&](auto &dofs_rows, auto &dofs_cols) {
131 for (auto it = ents_field_ptr->begin(); it != ents_field_ptr->end(); ++it) {
132
133 const auto uid = (*it)->getLocalUniqueId();
134
135 auto r = adjacencies_ptr->get<Unique_mi_tag>().equal_range(uid);
136 for (auto lo = r.first; lo != r.second; ++lo) {
137
138 if ((lo->getBitFEId() & problem_ptr->getBitFEId()).any()) {
139 std::array<bool, 2> row_col = {false, false};
140
141 const BitRefLevel &prb_bit = problem_ptr->getBitRefLevel();
142 const BitRefLevel &prb_mask = problem_ptr->getBitRefLevelMask();
143 const BitRefLevel &fe_bit = lo->entFePtr->getBitRefLevel();
144
145 // if entity is not problem refinement level
146 if ((fe_bit & prb_mask) != fe_bit)
147 continue;
148 if ((fe_bit & prb_bit).none())
149 continue;
150
151 auto add_to_view = [&](auto &nb_dofs, auto &view, auto rc) {
152 auto dit = nb_dofs->lower_bound(uid);
153 decltype(dit) hi_dit;
154 if (dit != nb_dofs->end()) {
155 hi_dit = nb_dofs->upper_bound(
156 uid | static_cast<UId>(MAX_DOFS_ON_ENTITY - 1));
157 view.insert(dit, hi_dit);
158 row_col[rc] = true;
159 }
160 };
161
162 if ((lo->entFePtr->getBitFieldIdRow() & (*it)->getId()).any())
163 add_to_view(dofs_field_ptr, dofs_rows, ROW);
164
165 if (!square_matrix)
166 if ((lo->entFePtr->getBitFieldIdCol() & (*it)->getId()).any())
167 add_to_view(dofs_field_ptr, dofs_cols, COL);
168
169 if (square_matrix && row_col[ROW])
170 break;
171 else if (row_col[ROW] && row_col[COL])
172 break;
173 }
174 }
175 }
177 };
178
179 CHKERR make_rows_and_cols_view(dofs_rows, dofs_cols);
180
181 // Add row dofs to problem
182 {
183 // zero rows
184 problem_ptr->nbDofsRow = 0;
185 problem_ptr->nbLocDofsRow = 0;
186 problem_ptr->nbGhostDofsRow = 0;
187
188 // add dofs for rows
189 DofEntity_multiIndex_active_view::nth_index<0>::type::iterator miit,
190 hi_miit;
191 hi_miit = dofs_rows.get<0>().end();
192
193 int count_dofs = dofs_rows.get<1>().count(true);
194 boost::shared_ptr<std::vector<NumeredDofEntity>> dofs_array =
195 boost::shared_ptr<std::vector<NumeredDofEntity>>(
196 new std::vector<NumeredDofEntity>());
197 problem_ptr->getRowDofsSequence()->push_back(dofs_array);
198 dofs_array->reserve(count_dofs);
199 miit = dofs_rows.get<0>().begin();
200 for (; miit != hi_miit; miit++) {
201 if ((*miit)->getActive()) {
202 dofs_array->emplace_back(*miit);
203 dofs_array->back().dofIdx = (problem_ptr->nbDofsRow)++;
204 }
205 }
206 auto hint = problem_ptr->numeredRowDofsPtr->end();
207 for (auto &v : *dofs_array) {
208 hint = problem_ptr->numeredRowDofsPtr->emplace_hint(hint, dofs_array, &v);
209 }
210 }
211
212 // Add col dofs to problem
213 if (!square_matrix) {
214 // zero cols
215 problem_ptr->nbDofsCol = 0;
216 problem_ptr->nbLocDofsCol = 0;
217 problem_ptr->nbGhostDofsCol = 0;
218
219 // add dofs for cols
220 DofEntity_multiIndex_active_view::nth_index<0>::type::iterator miit,
221 hi_miit;
222 hi_miit = dofs_cols.get<0>().end();
223
224 int count_dofs = 0;
225 miit = dofs_cols.get<0>().begin();
226 for (; miit != hi_miit; miit++) {
227 if (!(*miit)->getActive()) {
228 continue;
229 }
230 count_dofs++;
231 }
232
233 boost::shared_ptr<std::vector<NumeredDofEntity>> dofs_array =
234 boost::shared_ptr<std::vector<NumeredDofEntity>>(
235 new std::vector<NumeredDofEntity>());
236 problem_ptr->getColDofsSequence()->push_back(dofs_array);
237 dofs_array->reserve(count_dofs);
238 miit = dofs_cols.get<0>().begin();
239 for (; miit != hi_miit; miit++) {
240 if (!(*miit)->getActive()) {
241 continue;
242 }
243 dofs_array->emplace_back(*miit);
244 dofs_array->back().dofIdx = problem_ptr->nbDofsCol++;
245 }
246 auto hint = problem_ptr->numeredColDofsPtr->end();
247 for (auto &v : *dofs_array) {
248 hint = problem_ptr->numeredColDofsPtr->emplace_hint(hint, dofs_array, &v);
249 }
250 } else {
251 problem_ptr->numeredColDofsPtr = problem_ptr->numeredRowDofsPtr;
252 problem_ptr->nbLocDofsCol = problem_ptr->nbLocDofsRow;
253 problem_ptr->nbDofsCol = problem_ptr->nbDofsRow;
254 }
255
256 // job done, some debugging and postprocessing
257 if (verb >= VERBOSE) {
258 MOFEM_LOG("SYNC", Sev::verbose)
259 << problem_ptr->getName() << " Nb. local dofs "
260 << problem_ptr->numeredRowDofsPtr->size() << " by "
261 << problem_ptr->numeredColDofsPtr->size();
262 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::verbose);
263 }
264
265 if (verb >= NOISY) {
266 MOFEM_LOG("SYNC", Sev::noisy)
267 << "FEs row dofs " << *problem_ptr << " Nb. row dof "
268 << problem_ptr->getNbDofsRow();
269 for (auto &miit : *problem_ptr->numeredRowDofsPtr)
270 MOFEM_LOG("SYNC", Sev::noisy) << *miit;
271
272 MOFEM_LOG("SYNC", Sev::noisy)
273 << "FEs col dofs " << *problem_ptr << " Nb. col dof "
274 << problem_ptr->getNbDofsCol();
275 for (auto &miit : *problem_ptr->numeredColDofsPtr)
276 MOFEM_LOG("SYNC", Sev::noisy) << *miit;
277 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::noisy);
278 }
279
280 cOre.getBuildMoFEM() |= Core::BUILD_PROBLEM; // It is assumed that user who
281 // uses this function knows
282 // what he is doing
283
284 PetscLogEventEnd(MOFEM_EVENT_ProblemsManager, 0, 0, 0, 0);
285
287}
#define MOFEM_LOG_SEVERITY_SYNC(comm, severity)
Synchronise "SYNC" on curtain severity level.
@ NOISY
@ VERBOSE
@ COL
@ ROW
#define MAX_DOFS_ON_ENTITY
Maximal number of DOFs on entity.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
multi_index_container< boost::shared_ptr< DofEntity >, indexed_by< ordered_unique< const_mem_fun< DofEntity, UId, &DofEntity::getLocalUniqueId > >, ordered_non_unique< const_mem_fun< DofEntity, char, &DofEntity::getActive > > > > DofEntity_multiIndex_active_view
multi-index view on DofEntity activity
virtual const FieldEntity_multiIndex * get_field_ents() const =0
Get the field ents object.
virtual MoFEMErrorCode get_ents_elements_adjacency(const FieldEntityEntFiniteElementAdjacencyMap_multiIndex **dofs_elements_adjacency) const =0
Get the dofs elements adjacency object.
virtual const DofEntity_multiIndex * get_dofs() const =0
Get the dofs object.
#define MOFEM_LOG(channel, severity)
Log.
uint128_t UId
Unique Id.
Definition Types.hpp:31
MoFEM::LogManager::SeverityLevel Sev
int r
Definition sdf.py:8
PetscLogEvent MOFEM_EVENT_ProblemsManager

◆ buildProblemOnDistributedMesh() [1/2]

MoFEMErrorCode MoFEM::ProblemsManager::buildProblemOnDistributedMesh ( const std::string  name,
const bool  square_matrix,
int  verb = VERBOSE 
)

build problem data structures, assuming that mesh is distributed (collective)

Mesh is distributed, that means that each processor keeps only own part of the mesh and shared entities.

Collective - need to be run on all processors in communicator, i.e. each function has to call this function.

Examples
nonlinear_dynamics.cpp, and remove_entities_from_problem.cpp.

Definition at line 289 of file ProblemsManager.cpp.

290 {
291 MoFEM::Interface &m_field = cOre;
293
295 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "fields not build");
296 if (!((cOre.getBuildMoFEM()) & Core::BUILD_FE))
297 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "FEs not build");
299 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "adjacencies not build");
300
301 const Problem *problem_ptr;
302 CHKERR m_field.get_problem(name, &problem_ptr);
303 CHKERR buildProblemOnDistributedMesh(const_cast<Problem *>(problem_ptr),
304 square_matrix, verb);
305
308
310}
MoFEMErrorCode buildProblemOnDistributedMesh(const std::string name, const bool square_matrix, int verb=VERBOSE)
build problem data structures, assuming that mesh is distributed (collective)

◆ buildProblemOnDistributedMesh() [2/2]

MoFEMErrorCode MoFEM::ProblemsManager::buildProblemOnDistributedMesh ( Problem problem_ptr,
const bool  square_matrix = true,
int  verb = VERBOSE 
)

build problem data structures, assuming that mesh is distributed (collective)

Mesh is distributed, that means that each processor keeps only own part of the mesh and shared entities.

Collective - need to be run on all processors in communicator, i.e. each function has to call this function.

Definition at line 312 of file ProblemsManager.cpp.

313 {
314 MoFEM::Interface &m_field = cOre;
315 auto fields_ptr = m_field.get_fields();
316 auto fe_ptr = m_field.get_finite_elements();
317 auto dofs_field_ptr = m_field.get_dofs();
319 PetscLogEventBegin(MOFEM_EVENT_ProblemsManager, 0, 0, 0, 0);
320
321 // clear data structures
322 CHKERR m_field.clear_problem(problem_ptr->getName());
323
325
326 if (problem_ptr->getBitRefLevel().none())
327 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_FOUND,
328 "problem <%s> refinement level not set",
329 problem_ptr->getName().c_str());
330
331 int loop_size = 2;
332 if (square_matrix) {
333 loop_size = 1;
334 problem_ptr->numeredColDofsPtr = problem_ptr->numeredRowDofsPtr;
335 } else if (problem_ptr->numeredColDofsPtr == problem_ptr->numeredRowDofsPtr) {
336 problem_ptr->numeredColDofsPtr =
337 boost::shared_ptr<NumeredDofEntity_multiIndex>(
339 }
340
341 const BitRefLevel &prb_bit = problem_ptr->getBitRefLevel();
342 const BitRefLevel &prb_mask = problem_ptr->getBitRefLevelMask();
343
344 // // get rows and cols dofs view based on data on elements
345 DofEntity_multiIndex_active_view dofs_rows, dofs_cols;
346
347 // Add DOFs to problem by visiting all elements and adding DOFs from
348 // elements to the problem
349 if (buildProblemFromFields == PETSC_FALSE) {
350
351 auto make_rows_and_cols_view = [&](auto &dofs_rows, auto &dofs_cols) {
352 auto ents_field_ptr = m_field.get_field_ents();
353 auto adjacencies_ptr = m_field.get_ents_elements_adjacency();
355 for (auto it = ents_field_ptr->begin(); it != ents_field_ptr->end();
356 ++it) {
357
358 const auto uid = (*it)->getLocalUniqueId();
359
360 auto r = adjacencies_ptr->get<Unique_mi_tag>().equal_range(uid);
361 for (auto lo = r.first; lo != r.second; ++lo) {
362
363 if ((lo->getBitFEId() & problem_ptr->getBitFEId()).any()) {
364 std::array<bool, 2> row_col = {false, false};
365
366 const BitRefLevel &fe_bit = lo->entFePtr->getBitRefLevel();
367
368 // if entity is not problem refinement level
369 if ((fe_bit & prb_bit).any() && (fe_bit & prb_mask) == fe_bit) {
370
371 auto add_to_view = [&](auto dofs, auto &view, auto rc) {
372 auto dit = dofs->lower_bound(uid);
373 decltype(dit) hi_dit;
374 if (dit != dofs->end()) {
375 hi_dit = dofs->upper_bound(
376 uid | static_cast<UId>(MAX_DOFS_ON_ENTITY - 1));
377 view.insert(dit, hi_dit);
378 row_col[rc] = true;
379 }
380 };
381
382 if ((lo->entFePtr->getBitFieldIdRow() & (*it)->getId()).any())
383 add_to_view(dofs_field_ptr, dofs_rows, ROW);
384
385 if (!square_matrix)
386 if ((lo->entFePtr->getBitFieldIdCol() & (*it)->getId()).any())
387 add_to_view(dofs_field_ptr, dofs_cols, COL);
388
389 if (square_matrix && row_col[ROW])
390 break;
391 else if (row_col[ROW] && row_col[COL])
392 break;
393 }
394 }
395 }
396 }
398 };
399
400 CHKERR make_rows_and_cols_view(dofs_rows, dofs_cols);
401 }
402
403 // Add DOFS to the problem by searching all the filedes, and adding to
404 // problem owned or shared DOFs
405 if (buildProblemFromFields == PETSC_TRUE) {
406 // Get fields IDs on elements
407 BitFieldId fields_ids_row, fields_ids_col;
408 for (auto fit = fe_ptr->begin(); fit != fe_ptr->end(); fit++) {
409 if ((fit->get()->getId() & problem_ptr->getBitFEId()).any()) {
410 fields_ids_row |= fit->get()->getBitFieldIdRow();
411 fields_ids_col |= fit->get()->getBitFieldIdCol();
412 }
413 }
414 // Get fields DOFs
415 for (auto fit = fields_ptr->begin(); fit != fields_ptr->end(); fit++) {
416 if ((fit->get()->getId() & (fields_ids_row | fields_ids_col)).any()) {
417
418 auto dit = dofs_field_ptr->get<Unique_mi_tag>().lower_bound(
419 FieldEntity::getLoBitNumberUId((*fit)->getBitNumber()));
420 auto hi_dit = dofs_field_ptr->get<Unique_mi_tag>().upper_bound(
421 FieldEntity::getHiBitNumberUId((*fit)->getBitNumber()));
422
423 for (; dit != hi_dit; dit++) {
424
425 const int owner_proc = dit->get()->getOwnerProc();
426 if (owner_proc != m_field.get_comm_rank()) {
427 const unsigned char pstatus = dit->get()->getPStatus();
428 if (pstatus == 0) {
429 continue;
430 }
431 }
432
433 const auto &dof_bit = (*dit)->getBitRefLevel();
434 // if entity is not problem refinement level
435 if ((dof_bit & prb_bit).any() && (dof_bit & prb_mask) == dof_bit) {
436
437 if ((fit->get()->getId() & fields_ids_row).any()) {
438 dofs_rows.insert(*dit);
439 }
440 if (!square_matrix) {
441 if ((fit->get()->getId() & fields_ids_col).any()) {
442 dofs_cols.insert(*dit);
443 }
444 }
445 }
446 }
447 }
448 }
449 }
450
452 // Get fields IDs on elements
453 BitFieldId fields_ids_row, fields_ids_col;
454 BitFieldId *fields_ids[2] = {&fields_ids_row, &fields_ids_col};
455 for (FiniteElement_multiIndex::iterator fit = fe_ptr->begin();
456 fit != fe_ptr->end(); fit++) {
457 if ((fit->get()->getId() & problem_ptr->getBitFEId()).any()) {
458 fields_ids_row |= fit->get()->getBitFieldIdRow();
459 fields_ids_col |= fit->get()->getBitFieldIdCol();
460 }
461 }
462
463 DofEntity_multiIndex_active_view *dofs_ptr[] = {&dofs_rows, &dofs_cols};
464 for (int ss = 0; ss != ((square_matrix) ? 1 : 2); ++ss) {
465 DofEntity_multiIndex_active_view::nth_index<1>::type::iterator miit,
466 hi_miit;
467 miit = dofs_ptr[ss]->get<1>().lower_bound(1);
468 hi_miit = dofs_ptr[ss]->get<1>().upper_bound(1);
469 Range ents_to_synchronise;
470 for (; miit != hi_miit; ++miit) {
471 if (miit->get()->getEntDofIdx() != 0)
472 continue;
473 ents_to_synchronise.insert(miit->get()->getEnt());
474 }
475 Range tmp_ents = ents_to_synchronise;
476 CHKERR m_field.getInterface<CommInterface>()->synchroniseEntities(
477 ents_to_synchronise, nullptr, verb);
478 ents_to_synchronise = subtract(ents_to_synchronise, tmp_ents);
479 for (auto fit = fields_ptr->begin(); fit != fields_ptr->end(); fit++) {
480 if ((fit->get()->getId() & *fields_ids[ss]).any()) {
481 const auto bit_number = (*fit)->getBitNumber();
482 for (Range::pair_iterator pit = ents_to_synchronise.pair_begin();
483 pit != ents_to_synchronise.pair_end(); ++pit) {
484 const auto f = pit->first;
485 const auto s = pit->second;
486 const auto lo_uid =
488 const auto hi_uid =
490
491 auto dit = dofs_field_ptr->get<Unique_mi_tag>().lower_bound(lo_uid);
492 auto hi_dit =
493 dofs_field_ptr->get<Unique_mi_tag>().upper_bound(hi_uid);
494
495 dofs_ptr[ss]->insert(dit, hi_dit);
496 }
497 }
498 }
499 }
500 }
501
502 // add dofs for rows and cols and set ownership
503 DofEntity_multiIndex_active_view *dofs_ptr[] = {&dofs_rows, &dofs_cols};
504 boost::shared_ptr<NumeredDofEntity_multiIndex> numered_dofs_ptr[] = {
505 problem_ptr->numeredRowDofsPtr, problem_ptr->numeredColDofsPtr};
506 int *nbdof_ptr[] = {&problem_ptr->nbDofsRow, &problem_ptr->nbDofsCol};
507 int *local_nbdof_ptr[] = {&problem_ptr->nbLocDofsRow,
508 &problem_ptr->nbLocDofsCol};
509 int *ghost_nbdof_ptr[] = {&problem_ptr->nbGhostDofsRow,
510 &problem_ptr->nbGhostDofsCol};
511 for (int ss = 0; ss < 2; ss++) {
512 *(nbdof_ptr[ss]) = 0;
513 *(local_nbdof_ptr[ss]) = 0;
514 *(ghost_nbdof_ptr[ss]) = 0;
515 }
516
517 // Loop over dofs on rows and columns and add to multi-indices in dofs
518 // problem structure, set partition for each dof
519 int nb_local_dofs[] = {0, 0};
520 for (int ss = 0; ss < loop_size; ss++) {
521 DofEntity_multiIndex_active_view::nth_index<1>::type::iterator miit,
522 hi_miit;
523 miit = dofs_ptr[ss]->get<1>().lower_bound(1);
524 hi_miit = dofs_ptr[ss]->get<1>().upper_bound(1);
525 for (; miit != hi_miit; miit++) {
526 int owner_proc = (*miit)->getOwnerProc();
527 if (owner_proc == m_field.get_comm_rank()) {
528 nb_local_dofs[ss]++;
529 }
530 }
531 }
532
533 // get layout
534 int start_ranges[2], end_ranges[2];
535 for (int ss = 0; ss != loop_size; ss++) {
536 PetscLayout layout;
537 CHKERR PetscLayoutCreate(m_field.get_comm(), &layout);
538 CHKERR PetscLayoutSetBlockSize(layout, 1);
539 CHKERR PetscLayoutSetLocalSize(layout, nb_local_dofs[ss]);
540 CHKERR PetscLayoutSetUp(layout);
541 CHKERR PetscLayoutGetSize(layout, &*nbdof_ptr[ss]);
542 CHKERR PetscLayoutGetRange(layout, &start_ranges[ss], &end_ranges[ss]);
543 CHKERR PetscLayoutDestroy(&layout);
544 }
545 if (square_matrix) {
546 nbdof_ptr[1] = nbdof_ptr[0];
547 nb_local_dofs[1] = nb_local_dofs[0];
548 start_ranges[1] = start_ranges[0];
549 end_ranges[1] = end_ranges[0];
550 }
551
552 // set local and global indices on own dofs
553 const size_t idx_data_type_size = sizeof(IdxDataType);
554 const size_t data_block_size = idx_data_type_size / sizeof(int);
555
556 if (sizeof(IdxDataType) % sizeof(int)) {
557 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
558 }
559 std::vector<std::vector<IdxDataType>> ids_data_packed_rows(
560 m_field.get_comm_size()),
561 ids_data_packed_cols(m_field.get_comm_size());
562
563 // Loop over dofs on this processor and prepare those dofs to send on
564 // another proc
565 for (int ss = 0; ss != loop_size; ++ss) {
566
567 DofEntity_multiIndex_active_view::nth_index<0>::type::iterator miit,
568 hi_miit;
569 hi_miit = dofs_ptr[ss]->get<0>().end();
570
571 boost::shared_ptr<std::vector<NumeredDofEntity>> dofs_array =
572 boost::shared_ptr<std::vector<NumeredDofEntity>>(
573 new std::vector<NumeredDofEntity>());
574 int nb_dofs_to_add = 0;
575 miit = dofs_ptr[ss]->get<0>().begin();
576 for (; miit != hi_miit; ++miit) {
577 // Only set global idx for dofs on this processor part
578 if (!(miit->get()->getActive()))
579 continue;
580 ++nb_dofs_to_add;
581 }
582 dofs_array->reserve(nb_dofs_to_add);
583 if (ss == 0) {
584 problem_ptr->getRowDofsSequence()->push_back(dofs_array);
585 } else {
586 problem_ptr->getColDofsSequence()->push_back(dofs_array);
587 }
588
589 int &local_idx = *local_nbdof_ptr[ss];
590 miit = dofs_ptr[ss]->get<0>().begin();
591 for (; miit != hi_miit; ++miit) {
592
593 // Only set global idx for dofs on this processor part
594 if (!(miit->get()->getActive()))
595 continue;
596
597 dofs_array->emplace_back(*miit);
598
599 int owner_proc = dofs_array->back().getOwnerProc();
600 if (owner_proc < 0) {
601 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
602 "data inconsistency");
603 }
604
605 if (owner_proc != m_field.get_comm_rank()) {
606 dofs_array->back().pArt = owner_proc;
607 dofs_array->back().dofIdx = -1;
608 dofs_array->back().petscGloablDofIdx = -1;
609 dofs_array->back().petscLocalDofIdx = -1;
610 } else {
611
612 // Set part and indexes
613 int glob_idx = start_ranges[ss] + local_idx;
614 dofs_array->back().pArt = owner_proc;
615 dofs_array->back().dofIdx = glob_idx;
616 dofs_array->back().petscGloablDofIdx = glob_idx;
617 dofs_array->back().petscLocalDofIdx = local_idx;
618 local_idx++;
619
620 unsigned char pstatus = dofs_array->back().getPStatus();
621 // check id dof is shared, if that is a case global idx added to data
622 // structure and is sended to other processors
623 if (pstatus > 0) {
624
625 for (int proc = 0;
626 proc < MAX_SHARING_PROCS &&
627 -1 != dofs_array->back().getSharingProcsPtr()[proc];
628 proc++) {
629 // make it different for rows and columns when needed
630 if (ss == 0) {
631 ids_data_packed_rows[dofs_array->back()
632 .getSharingProcsPtr()[proc]]
633 .emplace_back(dofs_array->back().getGlobalUniqueId(),
634 glob_idx);
635 } else {
636 ids_data_packed_cols[dofs_array->back()
637 .getSharingProcsPtr()[proc]]
638 .emplace_back(dofs_array->back().getGlobalUniqueId(),
639 glob_idx);
640 }
641 if (!(pstatus & PSTATUS_MULTISHARED)) {
642 break;
643 }
644 }
645 }
646 }
647 }
648
649 auto hint = numered_dofs_ptr[ss]->end();
650 for (auto &v : *dofs_array)
651 hint = numered_dofs_ptr[ss]->emplace_hint(hint, dofs_array, &v);
652 }
653 if (square_matrix) {
654 local_nbdof_ptr[1] = local_nbdof_ptr[0];
655 }
656
657 int nsends_rows = 0, nsends_cols = 0;
658 // Non zero lengths[i] represent a message to i of length lengths[i].
659 std::vector<int> lengths_rows(m_field.get_comm_size()),
660 lengths_cols(m_field.get_comm_size());
661 lengths_rows.clear();
662 lengths_cols.clear();
663 for (int proc = 0; proc < m_field.get_comm_size(); proc++) {
664 lengths_rows[proc] = ids_data_packed_rows[proc].size() * data_block_size;
665 lengths_cols[proc] = ids_data_packed_cols[proc].size() * data_block_size;
666 if (!ids_data_packed_rows[proc].empty())
667 nsends_rows++;
668 if (!ids_data_packed_cols[proc].empty())
669 nsends_cols++;
670 }
671
672 MPI_Status *status;
673 CHKERR PetscMalloc1(m_field.get_comm_size(), &status);
674
675 // Do rows
676 int nrecvs_rows; // number of messages received
677 int *onodes_rows; // list of node-ids from which messages are expected
678 int *olengths_rows; // corresponding message lengths
679 int **rbuf_row; // must bee freed by user
680
681 // make sure it is a PETSc comm
682 MPI_Comm comm;
683 CHKERR PetscCommDuplicate(m_field.get_comm(), &comm, NULL);
684
685 {
686
687 // rows
688
689 // Computes the number of messages a node expects to receive
690 CHKERR PetscGatherNumberOfMessages(comm, NULL, &lengths_rows[0],
691 &nrecvs_rows);
692 // std::cerr << nrecvs_rows << std::endl;
693
694 // Computes info about messages that a MPI-node will receive, including
695 // (from-id,length) pairs for each message.
696 CHKERR PetscGatherMessageLengths(comm, nsends_rows, nrecvs_rows,
697 &lengths_rows[0], &onodes_rows,
698 &olengths_rows);
699
700 // Gets a unique new tag from a PETSc communicator. All processors that
701 // share the communicator MUST call this routine EXACTLY the same number
702 // of times. This tag should only be used with the current objects
703 // communicator; do NOT use it with any other MPI communicator.
704 int tag_row;
705 CHKERR PetscCommGetNewTag(comm, &tag_row);
706
707 // Allocate a buffer sufficient to hold messages of size specified in
708 // olengths. And post Irecvs on these buffers using node info from onodes
709 MPI_Request *r_waits_row; // must bee freed by user
710 // rbuf has a pointers to messeges. It has size of of nrecvs (number of
711 // messages) +1. In the first index a block is allocated,
712 // such that rbuf[i] = rbuf[i-1]+olengths[i-1].
713
714 CHKERR PetscPostIrecvInt(comm, tag_row, nrecvs_rows, onodes_rows,
715 olengths_rows, &rbuf_row, &r_waits_row);
716 CHKERR PetscFree(onodes_rows);
717
718 MPI_Request *s_waits_row; // status of sens messages
719 CHKERR PetscMalloc1(nsends_rows, &s_waits_row);
720
721 // Send messeges
722 for (int proc = 0, kk = 0; proc < m_field.get_comm_size(); proc++) {
723 if (!lengths_rows[proc])
724 continue; // no message to send to this proc
725 CHKERR MPI_Isend(&(ids_data_packed_rows[proc])[0], // buffer to send
726 lengths_rows[proc], // message length
727 MPIU_INT, proc, // to proc
728 tag_row, comm, s_waits_row + kk);
729 kk++;
730 }
731
732 if (nrecvs_rows) {
733 CHKERR MPI_Waitall(nrecvs_rows, r_waits_row, status);
734 }
735 if (nsends_rows) {
736 CHKERR MPI_Waitall(nsends_rows, s_waits_row, status);
737 }
738
739 CHKERR PetscFree(r_waits_row);
740 CHKERR PetscFree(s_waits_row);
741 }
742
743 // cols
744 int nrecvs_cols = nrecvs_rows;
745 int *olengths_cols = olengths_rows;
746 PetscInt **rbuf_col = rbuf_row;
747 if (!square_matrix) {
748
749 // Computes the number of messages a node expects to receive
750 CHKERR PetscGatherNumberOfMessages(comm, NULL, &lengths_cols[0],
751 &nrecvs_cols);
752
753 // Computes info about messages that a MPI-node will receive, including
754 // (from-id,length) pairs for each message.
755 int *onodes_cols;
756 CHKERR PetscGatherMessageLengths(comm, nsends_cols, nrecvs_cols,
757 &lengths_cols[0], &onodes_cols,
758 &olengths_cols);
759
760 // Gets a unique new tag from a PETSc communicator.
761 int tag_col;
762 CHKERR PetscCommGetNewTag(comm, &tag_col);
763
764 // Allocate a buffer sufficient to hold messages of size specified in
765 // olengths. And post Irecvs on these buffers using node info from onodes
766 MPI_Request *r_waits_col; // must bee freed by user
767 CHKERR PetscPostIrecvInt(comm, tag_col, nrecvs_cols, onodes_cols,
768 olengths_cols, &rbuf_col, &r_waits_col);
769 CHKERR PetscFree(onodes_cols);
770
771 MPI_Request *s_waits_col; // status of sens messages
772 CHKERR PetscMalloc1(nsends_cols, &s_waits_col);
773
774 // Send messages
775 for (int proc = 0, kk = 0; proc < m_field.get_comm_size(); proc++) {
776 if (!lengths_cols[proc])
777 continue; // no message to send to this proc
778 CHKERR MPI_Isend(&(ids_data_packed_cols[proc])[0], // buffer to send
779 lengths_cols[proc], // message length
780 MPIU_INT, proc, // to proc
781 tag_col, comm, s_waits_col + kk);
782 kk++;
783 }
784
785 if (nrecvs_cols) {
786 CHKERR MPI_Waitall(nrecvs_cols, r_waits_col, status);
787 }
788 if (nsends_cols) {
789 CHKERR MPI_Waitall(nsends_cols, s_waits_col, status);
790 }
791
792 CHKERR PetscFree(r_waits_col);
793 CHKERR PetscFree(s_waits_col);
794 }
795
796 CHKERR PetscCommDestroy(&comm);
797 CHKERR PetscFree(status);
798
799 DofEntity_multiIndex_global_uid_view dofs_glob_uid_view;
800 auto hint = dofs_glob_uid_view.begin();
801 for (auto dof : *m_field.get_dofs())
802 dofs_glob_uid_view.emplace_hint(hint, dof);
803
804 // set values received from other processors
805 for (int ss = 0; ss != loop_size; ++ss) {
806
807 int nrecvs;
808 int *olengths;
809 int **data_procs;
810 if (ss == 0) {
811 nrecvs = nrecvs_rows;
812 olengths = olengths_rows;
813 data_procs = rbuf_row;
814 } else {
815 nrecvs = nrecvs_cols;
816 olengths = olengths_cols;
817 data_procs = rbuf_col;
818 }
819
820 UId uid;
821 for (int kk = 0; kk != nrecvs; ++kk) {
822 int len = olengths[kk];
823 int *data_from_proc = data_procs[kk];
824 for (int dd = 0; dd < len; dd += data_block_size) {
825 uid = IdxDataTypePtr(&data_from_proc[dd]).getUId();
826 auto ddit = dofs_glob_uid_view.find(uid);
827 const auto owner_proc = FieldEntity::getOwnerFromUniqueId(uid);
828
829 if (owner_proc == m_field.get_comm_rank() &&
830 PetscUnlikely(ddit == dofs_glob_uid_view.end())) {
831
832#ifndef NDEBUG
833 auto ents_field_ptr = m_field.get_field_ents();
834 MOFEM_LOG("SELF", Sev::error)
835 << "DOF is shared or multishared between processors. For example "
836 "if order of field on given entity is set in inconsistently, "
837 "has different value on two processor, error such as this is "
838 "triggered";
839
840 MOFEM_LOG("SELF", Sev::error) << "UId " << uid << " is not found";
841 MOFEM_LOG("SELF", Sev::error)
842 << "Problematic UId owner proc is " << owner_proc;
843 const auto uid_handle = FieldEntity::getHandleFromUniqueId(uid);
844 MOFEM_LOG("SELF", Sev::error)
845 << "Problematic UId entity owning processor handle is "
846 << uid_handle << " entity type "
847 << moab::CN::EntityTypeName(type_from_handle(uid_handle));
848 const auto uid_bit_number =
850 MOFEM_LOG("SELF", Sev::error)
851 << "Problematic UId field is "
852 << m_field.get_field_name(
853 field_bit_from_bit_number(uid_bit_number));
854
856 field_view.insert(ents_field_ptr->begin(), ents_field_ptr->end());
857 auto fe_it = field_view.find(FieldEntity::getGlobalUniqueIdCalculate(
858 owner_proc, uid_bit_number, uid_handle));
859 if (fe_it == field_view.end()) {
860 MOFEM_LOG("SELF", Sev::error)
861 << "Also, no field entity in database for given global UId";
862 } else {
863 MOFEM_LOG("SELF", Sev::error) << "Field entity in databse exist "
864 "(but have no DOF wih give UId";
865 MOFEM_LOG("SELF", Sev::error) << **fe_it;
866
867 // Save file with missing entity
868 auto error_file_name =
869 "error_with_missing_entity_" +
870 boost::lexical_cast<std::string>(m_field.get_comm_rank()) +
871 ".vtk";
872 MOFEM_LOG("SELF", Sev::error)
873 << "Look to file < " << error_file_name
874 << " > it contains entity with missing DOF.";
875
876 auto tmp_msh = get_temp_meshset_ptr(m_field.get_moab());
877 const auto local_fe_ent = (*fe_it)->getEnt();
878 CHKERR m_field.get_moab().add_entities(*tmp_msh, &local_fe_ent, 1);
879 CHKERR m_field.get_moab().write_file(error_file_name.c_str(), "VTK",
880 "", tmp_msh->get_ptr(), 1);
881 }
882#endif
883
884 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
885 "DOF with global UId not found (Compile code in Debug to "
886 "learn more about problem");
887 }
888
889 if (PetscUnlikely(ddit == dofs_glob_uid_view.end())) {
890 continue;
891 }
892
893 auto dit = numered_dofs_ptr[ss]->find((*ddit)->getLocalUniqueId());
894
895 if (dit != numered_dofs_ptr[ss]->end()) {
896
897 int global_idx = IdxDataTypePtr(&data_from_proc[dd]).getDofIdx();
898#ifndef NDEBUG
899 if (PetscUnlikely(global_idx < 0))
900 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
901 "received negative dof");
902#endif
903 bool success;
904 success = numered_dofs_ptr[ss]->modify(
905 dit, NumeredDofEntity_mofem_index_change(global_idx));
906
907#ifndef NDEBUG
908 if (PetscUnlikely(!success))
909 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
910 "modification unsuccessful");
911#endif
912 success = numered_dofs_ptr[ss]->modify(
913 dit, NumeredDofEntity_part_and_glob_idx_change((*dit)->getPart(),
914 global_idx));
915#ifndef NDEBUG
916 if (PetscUnlikely(!success))
917 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
918 "modification unsuccessful");
919#endif
920 };
921
922#ifndef NDEBUG
923 if (PetscUnlikely(ddit->get()->getPStatus() == 0)) {
924
925 // Dof is shared on this processor, however there is no element
926 // which have this dof. If DOF is not shared and received from other
927 // processor, but not marked as a shared on other that means that is
928 // data inconstancy and error should be thrown.
929
930 std::ostringstream zz;
931 zz << **ddit << std::endl;
932 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
933 "data inconsistency, dofs is not shared, but received "
934 "from other proc\n"
935 "%s",
936 zz.str().c_str());
937 }
938#endif
939 }
940 }
941 }
942
943 if (square_matrix) {
944 (problem_ptr->nbDofsCol) = (problem_ptr->nbDofsRow);
945 (problem_ptr->nbLocDofsCol) = (problem_ptr->nbLocDofsRow);
946 }
947
948 CHKERR PetscFree(olengths_rows);
949 CHKERR PetscFree(rbuf_row[0]);
950 CHKERR PetscFree(rbuf_row);
951 if (!square_matrix) {
952 CHKERR PetscFree(olengths_cols);
953 CHKERR PetscFree(rbuf_col[0]);
954 CHKERR PetscFree(rbuf_col);
955 }
956
957 if (square_matrix) {
958 if (numered_dofs_ptr[0]->size() != numered_dofs_ptr[1]->size()) {
959 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
960 "data inconsistency for square_matrix %ld!=%ld",
961 numered_dofs_ptr[0]->size(), numered_dofs_ptr[1]->size());
962 }
963 if (problem_ptr->numeredRowDofsPtr != problem_ptr->numeredColDofsPtr) {
964 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
965 "data inconsistency for square_matrix");
966 }
967 }
968
969 CHKERR printPartitionedProblem(problem_ptr, verb);
970 CHKERR debugPartitionedProblem(problem_ptr, verb);
971
972 PetscLogEventEnd(MOFEM_EVENT_ProblemsManager, 0, 0, 0, 0);
973
975}
@ MOFEM_NOT_FOUND
Definition definitions.h:33
multi_index_container< boost::shared_ptr< FieldEntity >, indexed_by< ordered_unique< tag< Unique_mi_tag >, const_mem_fun< FieldEntity, UId, &FieldEntity::getGlobalUniqueId > > > > FieldEntity_multiIndex_global_uid_view
multi-index view on DofEntity by uid
multi_index_container< boost::shared_ptr< NumeredDofEntity >, indexed_by< ordered_unique< tag< Unique_mi_tag >, const_mem_fun< NumeredDofEntity::interface_type_DofEntity, UId, &NumeredDofEntity::getLocalUniqueId > >, ordered_non_unique< tag< Part_mi_tag >, member< NumeredDofEntity, unsigned int, &NumeredDofEntity::pArt > >, ordered_non_unique< tag< Idx_mi_tag >, member< NumeredDofEntity, DofIdx, &NumeredDofEntity::dofIdx > >, ordered_non_unique< tag< PetscGlobalIdx_mi_tag >, member< NumeredDofEntity, DofIdx, &NumeredDofEntity::petscGloablDofIdx > >, ordered_non_unique< tag< PetscLocalIdx_mi_tag >, member< NumeredDofEntity, DofIdx, &NumeredDofEntity::petscLocalDofIdx > >, ordered_non_unique< tag< Ent_mi_tag >, const_mem_fun< NumeredDofEntity::interface_type_DofEntity, EntityHandle, &NumeredDofEntity::getEnt > > > > NumeredDofEntity_multiIndex
MultiIndex container keeps NumeredDofEntity.
multi_index_container< boost::shared_ptr< DofEntity >, indexed_by< ordered_unique< const_mem_fun< DofEntity, UId, &DofEntity::getGlobalUniqueId > > > > DofEntity_multiIndex_global_uid_view
multi-index view on DofEntity by uid
virtual const FiniteElement_multiIndex * get_finite_elements() const =0
Get the finite elements object.
virtual const Field_multiIndex * get_fields() const =0
Get the fields object.
const Tensor2_symmetric_Expr< const ddTensor0< T, Dim, i, j >, typename promote< T, double >::V, Dim, i, j > dd(const Tensor0< T * > &a, const Index< i, Dim > index1, const Index< j, Dim > index2, const Tensor1< int, Dim > &d_ijk, const Tensor1< double, Dim > &d_xyz)
Definition ddTensor0.hpp:33
std::bitset< BITFIELDID_SIZE > BitFieldId
Field Id.
Definition Types.hpp:42
auto type_from_handle(const EntityHandle h)
get type from entity handle
auto field_bit_from_bit_number(const int bit_number)
get field bit id from bit number
auto get_temp_meshset_ptr(moab::Interface &moab)
Create smart pointer to temporary meshset.
virtual int get_comm_size() const =0
virtual moab::Interface & get_moab()=0
virtual std::string get_field_name(const BitFieldId id) const =0
get field name from id
static UId getHiBitNumberUId(const FieldBitNumber bit_number)
static auto getHandleFromUniqueId(const UId uid)
Get the Handle From Unique Id.
static auto getFieldBitNumberFromUniqueId(const UId uid)
Get the Field Bit Number From Unique Id.
UId getLocalUniqueIdCalculate()
Get the Local Unique Id Calculate object.
static UId getLoBitNumberUId(const FieldBitNumber bit_number)
static auto getOwnerFromUniqueId(const UId uid)
UId getGlobalUniqueIdCalculate() const
Calculate global UId.
PetscBool synchroniseProblemEntities
DOFs in fields, not from DOFs on elements.
MoFEMErrorCode getOptions()
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.

◆ buildSubProblem()

MoFEMErrorCode MoFEM::ProblemsManager::buildSubProblem ( const std::string  out_name,
const std::vector< std::string > &  fields_row,
const std::vector< std::string > &  fields_col,
const std::string  main_problem,
const bool  square_matrix = true,
const map< std::string, boost::shared_ptr< Range > > *  entityMapRow = nullptr,
const map< std::string, boost::shared_ptr< Range > > *  entityMapCol = nullptr,
int  verb = VERBOSE 
)

build sub problem

Parameters
out_nameproblem
fields_rowvector of fields composing problem
fields_colvector of fields composing problem
main_problemmain problem
Returns
error code
Examples
free_surface.cpp, and remove_entities_from_problem.cpp.

Definition at line 977 of file ProblemsManager.cpp.

988 {
989 MoFEM::Interface &m_field = cOre;
990 auto problems_ptr = m_field.get_problems();
992
993 CHKERR m_field.clear_problem(out_name);
994
995 // get reference to all problems
996 using ProblemByName = decltype(problems_ptr->get<Problem_mi_tag>());
997 auto &problems_by_name =
998 const_cast<ProblemByName &>(problems_ptr->get<Problem_mi_tag>());
999
1000 // get iterators to out problem, i.e. build problem
1001 auto out_problem_it = problems_by_name.find(out_name);
1002 if (out_problem_it == problems_by_name.end()) {
1003 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1004 "subproblem with name < %s > not defined (top tip check spelling)",
1005 out_name.c_str());
1006 }
1007 // get iterator to main problem, i.e. out problem is subproblem of main
1008 // problem
1009 auto main_problem_it = problems_by_name.find(main_problem);
1010 if (main_problem_it == problems_by_name.end()) {
1011 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1012 "problem of subproblem with name < %s > not defined (top tip "
1013 "check spelling)",
1014 main_problem.c_str());
1015 }
1016
1017 // get dofs for row & columns for out problem,
1018 boost::shared_ptr<NumeredDofEntity_multiIndex> out_problem_dofs[] = {
1019 out_problem_it->numeredRowDofsPtr, out_problem_it->numeredColDofsPtr};
1020 // get dofs for row & columns for main problem
1021 boost::shared_ptr<NumeredDofEntity_multiIndex> main_problem_dofs[] = {
1022 main_problem_it->numeredRowDofsPtr, main_problem_it->numeredColDofsPtr};
1023 // get local indices counter
1024 int *nb_local_dofs[] = {&out_problem_it->nbLocDofsRow,
1025 &out_problem_it->nbLocDofsCol};
1026 // get global indices counter
1027 int *nb_dofs[] = {&out_problem_it->nbDofsRow, &out_problem_it->nbDofsCol};
1028
1029 // set number of ghost nodes to zero
1030 {
1031 out_problem_it->nbGhostDofsRow = 0;
1032 out_problem_it->nbGhostDofsCol = 0;
1033 }
1034
1035 // put rows & columns field names in array
1036 std::vector<std::string> fields[] = {fields_row, fields_col};
1037 const map<std::string, boost::shared_ptr<Range>> *entityMap[] = {
1038 entityMapRow, entityMapCol};
1039
1040 // make data structure fos sub-problem data
1041 out_problem_it->subProblemData =
1042 boost::make_shared<Problem::SubProblemData>();
1043
1044 // Loop over rows and columns
1045 for (int ss = 0; ss != (square_matrix ? 1 : 2); ++ss) {
1046
1047 // reset dofs and columns counters
1048 (*nb_local_dofs[ss]) = 0;
1049 (*nb_dofs[ss]) = 0;
1050 // clear arrays
1051 out_problem_dofs[ss]->clear();
1052
1053 // If DOFs are cleared clear finite elements too.
1054 out_problem_it->numeredFiniteElementsPtr->clear();
1055
1056 // get dofs by field name and insert them in out problem multi-indices
1057 for (auto field : fields[ss]) {
1058
1059 // Following reserve memory in sequences, only two allocations are here,
1060 // once for array of objects, next for array of shared pointers
1061
1062 // aliased sequence of pointer is killed with element
1063 boost::shared_ptr<std::vector<NumeredDofEntity>> dofs_array =
1064 boost::make_shared<std::vector<NumeredDofEntity>>();
1065 // reserve memory for field dofs
1066 if (!ss)
1067 out_problem_it->getRowDofsSequence()->emplace_back(dofs_array);
1068 else
1069 out_problem_it->getColDofsSequence()->emplace_back(dofs_array);
1070
1071 // create elements objects
1072 auto bit_number = m_field.get_field_bit_number(field);
1073
1074 auto add_dit_to_dofs_array = [&](auto &dit) {
1075 if (dit->get()->getPetscGlobalDofIdx() >= 0)
1076 dofs_array->emplace_back(
1077 dit->get()->getDofEntityPtr(), dit->get()->getPetscGlobalDofIdx(),
1078 dit->get()->getPetscGlobalDofIdx(),
1079 dit->get()->getPetscLocalDofIdx(), dit->get()->getPart());
1080 };
1081
1082 auto get_dafult_dof_range = [&]() {
1083 auto dit = main_problem_dofs[ss]->get<Unique_mi_tag>().lower_bound(
1084 FieldEntity::getLoBitNumberUId(bit_number));
1085 auto hi_dit = main_problem_dofs[ss]->get<Unique_mi_tag>().upper_bound(
1086 FieldEntity::getHiBitNumberUId(bit_number));
1087 return std::make_pair(dit, hi_dit);
1088 };
1089
1090 auto check = [&](auto &field) -> boost::shared_ptr<Range> {
1091 if (entityMap[ss]) {
1092 auto mit = entityMap[ss]->find(field);
1093 if (mit != entityMap[ss]->end()) {
1094 return mit->second;
1095 } else {
1096 return nullptr;
1097 }
1098 } else {
1099 return nullptr;
1100 }
1101 };
1102
1103 if (auto r_ptr = check(field)) {
1104 for (auto p = r_ptr->pair_begin(); p != r_ptr->pair_end(); ++p) {
1105 const auto lo_ent = p->first;
1106 const auto hi_ent = p->second;
1107 auto dit = main_problem_dofs[ss]->get<Unique_mi_tag>().lower_bound(
1108 DofEntity::getLoFieldEntityUId(bit_number, lo_ent));
1109 auto hi_dit = main_problem_dofs[ss]->get<Unique_mi_tag>().upper_bound(
1110 DofEntity::getHiFieldEntityUId(bit_number, hi_ent));
1111 dofs_array->reserve(std::distance(dit, hi_dit));
1112 for (; dit != hi_dit; dit++) {
1113 add_dit_to_dofs_array(dit);
1114 }
1115 }
1116 } else {
1117 auto [dit, hi_dit] = get_dafult_dof_range();
1118 dofs_array->reserve(std::distance(dit, hi_dit));
1119 for (; dit != hi_dit; dit++)
1120 add_dit_to_dofs_array(dit);
1121 }
1122
1123 // fill multi-index
1124 auto hint = out_problem_dofs[ss]->end();
1125 for (auto &v : *dofs_array)
1126 hint = out_problem_dofs[ss]->emplace_hint(hint, dofs_array, &v);
1127 }
1128 // Set local indexes
1129 {
1130 auto dit = out_problem_dofs[ss]->get<Idx_mi_tag>().begin();
1131 auto hi_dit = out_problem_dofs[ss]->get<Idx_mi_tag>().end();
1132 for (; dit != hi_dit; dit++) {
1133 int idx = -1; // if dof is not part of partition, set local index to -1
1134 if (dit->get()->getPart() == (unsigned int)m_field.get_comm_rank()) {
1135 idx = (*nb_local_dofs[ss])++;
1136 }
1137 bool success = out_problem_dofs[ss]->modify(
1138 out_problem_dofs[ss]->project<0>(dit),
1139 NumeredDofEntity_local_idx_change(idx));
1140 if (!success) {
1141 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1142 "operation unsuccessful");
1143 }
1144 };
1145 }
1146 // Set global indexes, compress global indices
1147 {
1148 auto dit =
1149 out_problem_dofs[ss]->get<PetscLocalIdx_mi_tag>().lower_bound(0);
1150 auto hi_dit =
1151 out_problem_dofs[ss]->get<PetscLocalIdx_mi_tag>().upper_bound(
1152 out_problem_dofs[ss]->size());
1153 const int nb = std::distance(dit, hi_dit);
1154 // get main problem global indices
1155 std::vector<int> main_indices(nb);
1156 for (auto it = main_indices.begin(); dit != hi_dit; dit++, it++) {
1157 *it = dit->get()->getPetscGlobalDofIdx();
1158 }
1159 // create is with global dofs
1160 IS is;
1161 CHKERR ISCreateGeneral(m_field.get_comm(), nb, &*main_indices.begin(),
1162 PETSC_USE_POINTER, &is);
1163 // create map form main problem global indices to out problem global
1164 // indices
1165 AO ao;
1166 CHKERR AOCreateMappingIS(is, PETSC_NULLPTR, &ao);
1167 if (ss == 0) {
1168 IS is_dup;
1169 CHKERR ISDuplicate(is, &is_dup);
1170 out_problem_it->getSubData()->rowIs = SmartPetscObj<IS>(is_dup, false);
1171 out_problem_it->getSubData()->rowMap = SmartPetscObj<AO>(ao, true);
1172 } else {
1173 IS is_dup;
1174 CHKERR ISDuplicate(is, &is_dup);
1175 out_problem_it->getSubData()->colIs = SmartPetscObj<IS>(is_dup, false);
1176 out_problem_it->getSubData()->colMap = SmartPetscObj<AO>(ao, true);
1177 }
1178 CHKERR AOApplicationToPetscIS(ao, is);
1179 // set global number of DOFs
1180 CHKERR ISGetSize(is, nb_dofs[ss]);
1181 CHKERR ISDestroy(&is);
1182 // set out problem global indices after applying map
1183 dit = out_problem_dofs[ss]->get<PetscLocalIdx_mi_tag>().lower_bound(0);
1184 for (std::vector<int>::iterator it = main_indices.begin(); dit != hi_dit;
1185 dit++, it++) {
1186 bool success = out_problem_dofs[ss]->modify(
1187 out_problem_dofs[ss]->project<0>(dit),
1188 NumeredDofEntity_part_and_all_indices_change(
1189 dit->get()->getPart(), *it, *it,
1190 dit->get()->getPetscLocalDofIdx()));
1191 if (!success) {
1192 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1193 "operation unsuccessful");
1194 }
1195 }
1196 // set global indices to nodes not on this part
1197 {
1198 NumeredDofEntityByLocalIdx::iterator dit =
1199 out_problem_dofs[ss]->get<PetscLocalIdx_mi_tag>().lower_bound(-1);
1200 NumeredDofEntityByLocalIdx::iterator hi_dit =
1201 out_problem_dofs[ss]->get<PetscLocalIdx_mi_tag>().upper_bound(-1);
1202 const int nb = std::distance(dit, hi_dit);
1203 std::vector<int> main_indices_non_local(nb);
1204 for (auto it = main_indices_non_local.begin(); dit != hi_dit;
1205 dit++, it++) {
1206 *it = dit->get()->getPetscGlobalDofIdx();
1207 }
1208 IS is;
1209 CHKERR ISCreateGeneral(m_field.get_comm(), nb,
1210 &*main_indices_non_local.begin(),
1211 PETSC_USE_POINTER, &is);
1212 CHKERR AOApplicationToPetscIS(ao, is);
1213 CHKERR ISDestroy(&is);
1214 dit = out_problem_dofs[ss]->get<PetscLocalIdx_mi_tag>().lower_bound(-1);
1215 for (auto it = main_indices_non_local.begin(); dit != hi_dit;
1216 dit++, it++) {
1217 bool success = out_problem_dofs[ss]->modify(
1218 out_problem_dofs[ss]->project<0>(dit),
1219 NumeredDofEntity_part_and_all_indices_change(
1220 dit->get()->getPart(), dit->get()->getDofIdx(), *it,
1221 dit->get()->getPetscLocalDofIdx()));
1222 if (!success) {
1223 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1224 "operation unsuccessful");
1225 }
1226 }
1227 }
1228 CHKERR AODestroy(&ao);
1229 }
1230 }
1231
1232 if (square_matrix) {
1233 out_problem_it->numeredColDofsPtr = out_problem_it->numeredRowDofsPtr;
1234 out_problem_it->nbLocDofsCol = out_problem_it->nbLocDofsRow;
1235 out_problem_it->nbDofsCol = out_problem_it->nbDofsRow;
1236 out_problem_it->getSubData()->colIs = out_problem_it->getSubData()->rowIs;
1237 out_problem_it->getSubData()->colMap = out_problem_it->getSubData()->rowMap;
1238 }
1239
1240 CHKERR printPartitionedProblem(&*out_problem_it, verb);
1241 CHKERR debugPartitionedProblem(&*out_problem_it, verb);
1242
1244}
@ MOFEM_ATOM_TEST_INVALID
Definition definitions.h:40
virtual FieldBitNumber get_field_bit_number(const std::string name) const =0
get field bit number
static UId getLoFieldEntityUId(const FieldBitNumber bit, const EntityHandle ent)
static UId getHiFieldEntityUId(const FieldBitNumber bit, const EntityHandle ent)

◆ getFEMeshset()

MoFEMErrorCode MoFEM::ProblemsManager::getFEMeshset ( const std::string  prb_name,
const std::string &  fe_name,
EntityHandle meshset 
) const

create add entities of finite element in the problem

\create add entities of finite element in the problem

Note
Meshset entity has to be crated
Meshset entity has to be crated
Parameters
prb_namename of the problem
fe_namename of the entity
meshsetpointer meshset handle
Returns
MoFEMErrorCode

Definition at line 2564 of file ProblemsManager.cpp.

2566 {
2567 MoFEM::Interface &m_field = cOre;
2568 const Problem *problem_ptr;
2569 const FiniteElement_multiIndex *fes_ptr;
2571
2572 CHKERR m_field.get_moab().create_meshset(MESHSET_SET, *meshset);
2573 CHKERR m_field.get_problem(prb_name, &problem_ptr);
2574 CHKERR m_field.get_finite_elements(&fes_ptr);
2575
2576 auto fe_miit = fes_ptr->get<FiniteElement_name_mi_tag>().find(fe_name);
2577 if (fe_miit != fes_ptr->get<FiniteElement_name_mi_tag>().end()) {
2578 auto fit =
2579 problem_ptr->numeredFiniteElementsPtr->get<Unique_mi_tag>().lower_bound(
2581 0, (*fe_miit)->getFEUId()));
2582 auto hi_fe_it =
2583 problem_ptr->numeredFiniteElementsPtr->get<Unique_mi_tag>().upper_bound(
2585 get_id_for_max_type<MBENTITYSET>(), (*fe_miit)->getFEUId()));
2586 std::vector<EntityHandle> fe_vec;
2587 fe_vec.reserve(std::distance(fit, hi_fe_it));
2588 for (; fit != hi_fe_it; fit++)
2589 fe_vec.push_back(fit->get()->getEnt());
2590 CHKERR m_field.get_moab().add_entities(*meshset, &*fe_vec.begin(),
2591 fe_vec.size());
2592 }
2593
2595}
multi_index_container< boost::shared_ptr< FiniteElement >, indexed_by< hashed_unique< tag< FiniteElement_Meshset_mi_tag >, member< FiniteElement, EntityHandle, &FiniteElement::meshset > >, hashed_unique< tag< BitFEId_mi_tag >, const_mem_fun< FiniteElement, BitFEId, &FiniteElement::getId >, HashBit< BitFEId >, EqBit< BitFEId > >, ordered_unique< tag< FiniteElement_name_mi_tag >, const_mem_fun< FiniteElement, boost::string_ref, &FiniteElement::getNameRef > > > > FiniteElement_multiIndex
MultiIndex for entities for FiniteElement.
UId getLocalUniqueIdCalculate() const
Generate UId for finite element entity.

◆ getProblemElementsLayout()

MoFEMErrorCode MoFEM::ProblemsManager::getProblemElementsLayout ( const std::string  name,
const std::string &  fe_name,
PetscLayout *  layout 
) const

Get layout of elements in the problem.

In layout is stored information how many elements is on each processor, for more information look int petsc documentation http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/IS/PetscLayoutCreate.html#PetscLayoutCreate

Parameters
nameproblem name
fe_namefinite elements
layoutlayout
verbverbosity level
Returns
error code

Definition at line 2598 of file ProblemsManager.cpp.

2600 {
2601 MoFEM::Interface &m_field = cOre;
2602 const Problem *problem_ptr;
2604 CHKERR m_field.get_problem(name, &problem_ptr);
2605 CHKERR problem_ptr->getNumberOfElementsByNameAndPart(PETSC_COMM_WORLD,
2606 fe_name, layout);
2608}
MoFEMErrorCode getNumberOfElementsByNameAndPart(MPI_Comm comm, const std::string name, PetscLayout *layout) const
Get number of finite elements by name on processors.

◆ inheritPartition()

MoFEMErrorCode MoFEM::ProblemsManager::inheritPartition ( const std::string  name,
const std::string  problem_for_rows,
bool  copy_rows,
const std::string  problem_for_cols,
bool  copy_cols,
int  verb = VERBOSE 
)

build indexing and partition problem inheriting indexing and partitioning from two other problems

Parameters
nameproblem name
problem_for_rowsproblem used to index rows
copy_rowsjust copy rows dofs
problem_for_colsproblem used to index cols
copy_colsjust copy cols dofs

If copy_rows/copy_cols is set to false only partition is copied between problems.

Examples
build_problems.cpp.

Definition at line 1892 of file ProblemsManager.cpp.

1894 {
1895 MoFEM::Interface &m_field = cOre;
1896 auto problems_ptr = m_field.get_problems();
1898
1900 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY, "pRoblems not build");
1901
1902 typedef Problem_multiIndex::index<Problem_mi_tag>::type ProblemByName;
1903
1904 // find p_miit
1905 ProblemByName &problems_by_name =
1906 const_cast<ProblemByName &>(problems_ptr->get<Problem_mi_tag>());
1907 ProblemByName::iterator p_miit = problems_by_name.find(name);
1908 if (p_miit == problems_by_name.end()) {
1909 SETERRQ(m_field.get_comm(), MOFEM_NOT_FOUND,
1910 "problem with name < %s > not defined (top tip check spelling)",
1911 name.c_str());
1912 }
1913 if (verb > QUIET)
1914 MOFEM_LOG("WORLD", Sev::inform)
1915 << p_miit->getName() << " from rows of " << problem_for_rows
1916 << " and columns of " << problem_for_cols;
1917
1918 // find p_miit_row
1919 ProblemByName::iterator p_miit_row = problems_by_name.find(problem_for_rows);
1920 if (p_miit_row == problems_by_name.end()) {
1921 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
1922 "problem with name < %s > not defined (top tip check spelling)",
1923 problem_for_rows.c_str());
1924 }
1925 const boost::shared_ptr<NumeredDofEntity_multiIndex> dofs_row =
1926 p_miit_row->numeredRowDofsPtr;
1927
1928 // find p_mit_col
1929 ProblemByName::iterator p_miit_col = problems_by_name.find(problem_for_cols);
1930 if (p_miit_col == problems_by_name.end()) {
1931 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
1932 "problem with name < %s > not defined (top tip check spelling)",
1933 problem_for_cols.c_str());
1934 }
1935 boost::shared_ptr<NumeredDofEntity_multiIndex> dofs_col =
1936 p_miit_col->numeredColDofsPtr;
1937
1938 bool copy[] = {copy_rows, copy_cols};
1939 boost::shared_ptr<NumeredDofEntity_multiIndex> composed_dofs[] = {
1940 p_miit->numeredRowDofsPtr, p_miit->numeredColDofsPtr};
1941
1942 int *nb_local_dofs[] = {&p_miit->nbLocDofsRow, &p_miit->nbLocDofsCol};
1943 int *nb_dofs[] = {&p_miit->nbDofsRow, &p_miit->nbDofsCol};
1944 boost::shared_ptr<NumeredDofEntity_multiIndex> copied_dofs[] = {dofs_row,
1945 dofs_col};
1946
1947 for (int ss = 0; ss < 2; ss++) {
1948
1949 // build indices
1950 *nb_local_dofs[ss] = 0;
1951 if (!copy[ss]) {
1952
1953 // only copy indices which are belong to some elements if this problem
1954 std::vector<int> is_local, is_new;
1955
1956 NumeredDofEntityByUId &dofs_by_uid =
1957 copied_dofs[ss]->get<Unique_mi_tag>();
1958 for (NumeredDofEntity_multiIndex::iterator dit =
1959 composed_dofs[ss]->begin();
1960 dit != composed_dofs[ss]->end(); dit++) {
1961 NumeredDofEntityByUId::iterator diit =
1962 dofs_by_uid.find((*dit)->getLocalUniqueId());
1963 if (diit == dofs_by_uid.end()) {
1964 SETERRQ(
1966 "data inconsistency, could not find dof in composite problem");
1967 }
1968 int part_number = (*diit)->getPart(); // get part number
1969 int petsc_global_dof = (*diit)->getPetscGlobalDofIdx();
1970 bool success;
1971 success = composed_dofs[ss]->modify(
1972 dit, NumeredDofEntity_part_and_glob_idx_change(part_number,
1973 petsc_global_dof));
1974 if (!success) {
1975 SETERRQ(m_field.get_comm(), MOFEM_OPERATION_UNSUCCESSFUL,
1976 "modification unsuccessful");
1977 }
1978 if ((*dit)->getPart() == (unsigned int)m_field.get_comm_rank()) {
1979 success = composed_dofs[ss]->modify(
1980 dit, NumeredDofEntity_local_idx_change((*nb_local_dofs[ss])++));
1981 if (!success) {
1982 SETERRQ(m_field.get_comm(), MOFEM_OPERATION_UNSUCCESSFUL,
1983 "modification unsuccessful");
1984 }
1985 is_local.push_back(petsc_global_dof);
1986 }
1987 }
1988
1989 AO ao;
1990 CHKERR AOCreateMapping(m_field.get_comm(), is_local.size(), &is_local[0],
1991 NULL, &ao);
1992
1993 // apply local to global mapping
1994 is_local.resize(0);
1995 for (NumeredDofEntity_multiIndex::iterator dit =
1996 composed_dofs[ss]->begin();
1997 dit != composed_dofs[ss]->end(); dit++) {
1998 is_local.push_back((*dit)->getPetscGlobalDofIdx());
1999 }
2000 CHKERR AOPetscToApplication(ao, is_local.size(), &is_local[0]);
2001 int idx2 = 0;
2002 for (NumeredDofEntity_multiIndex::iterator dit =
2003 composed_dofs[ss]->begin();
2004 dit != composed_dofs[ss]->end(); dit++) {
2005 int part_number = (*dit)->getPart(); // get part number
2006 int petsc_global_dof = is_local[idx2++];
2007 bool success;
2008 success = composed_dofs[ss]->modify(
2009 dit, NumeredDofEntity_part_and_glob_idx_change(part_number,
2010 petsc_global_dof));
2011 if (!success) {
2012 SETERRQ(m_field.get_comm(), MOFEM_OPERATION_UNSUCCESSFUL,
2013 "modification unsuccessful");
2014 }
2015 }
2016
2017 CHKERR AODestroy(&ao);
2018
2019 } else {
2020
2021 for (NumeredDofEntity_multiIndex::iterator dit = copied_dofs[ss]->begin();
2022 dit != copied_dofs[ss]->end(); dit++) {
2023 std::pair<NumeredDofEntity_multiIndex::iterator, bool> p;
2024 p = composed_dofs[ss]->insert(boost::shared_ptr<NumeredDofEntity>(
2025 new NumeredDofEntity((*dit)->getDofEntityPtr())));
2026 if (p.second) {
2027 (*nb_dofs[ss])++;
2028 }
2029 int dof_idx = (*dit)->getDofIdx();
2030 int part_number = (*dit)->getPart(); // get part number
2031 int petsc_global_dof = (*dit)->getPetscGlobalDofIdx();
2032 if (part_number == (unsigned int)m_field.get_comm_rank()) {
2033 const bool success = composed_dofs[ss]->modify(
2034 p.first, NumeredDofEntity_part_and_all_indices_change(
2035 part_number, dof_idx, petsc_global_dof,
2036 (*nb_local_dofs[ss])++));
2037 if (!success) {
2038 SETERRQ(m_field.get_comm(), MOFEM_OPERATION_UNSUCCESSFUL,
2039 "modification unsuccessful");
2040 }
2041 } else {
2042 const bool success = composed_dofs[ss]->modify(
2043 p.first, NumeredDofEntity_part_and_mofem_glob_idx_change(
2044 part_number, dof_idx, petsc_global_dof));
2045 if (!success) {
2046 SETERRQ(m_field.get_comm(), MOFEM_OPERATION_UNSUCCESSFUL,
2047 "modification unsuccessful");
2048 }
2049 }
2050 }
2051 }
2052 }
2053
2054 CHKERR printPartitionedProblem(&*p_miit, verb);
2055 CHKERR debugPartitionedProblem(&*p_miit, verb);
2056
2058}
@ QUIET
NumeredDofEntity_multiIndex::index< Unique_mi_tag >::type NumeredDofEntityByUId
Numbered DoF multi-index by UId.

◆ partitionFiniteElements()

MoFEMErrorCode MoFEM::ProblemsManager::partitionFiniteElements ( const std::string  name,
bool  part_from_moab = false,
int  low_proc = -1,
int  hi_proc = -1,
int  verb = VERBOSE 
)

partition finite elements

Function which partition finite elements based on dofs partitioning.
In addition it sets information about local row and cols dofs at given element on partition.

Parameters
name
part_from_moab
low_proc
hi_proc
verb
Returns
MoFEMErrorCode
Parameters
nameproblem name
Examples
build_problems.cpp, continuity_check_on_skeleton_3d.cpp, forces_and_sources_testing_edge_element.cpp, forces_and_sources_testing_flat_prism_element.cpp, hcurl_divergence_operator_2d.cpp, mesh_insert_interface_atom.cpp, nonlinear_dynamics.cpp, nonlinear_elastic.cpp, prism_elements_from_surface.cpp, prism_polynomial_approximation.cpp, quad_polynomial_approximation.cpp, and remove_entities_from_problem.cpp.

Definition at line 2163 of file ProblemsManager.cpp.

2166 {
2167 MoFEM::Interface &m_field = cOre;
2168 auto problems_ptr = m_field.get_problems();
2169 auto fe_ent_ptr = m_field.get_ents_finite_elements();
2171
2173 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY, "fields not build");
2174
2176 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY, "FEs not build");
2177
2179 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2180 "adjacencies not build");
2181
2183 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY, "problem not build");
2184
2186 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2187 "problem not partitioned");
2188
2189 if (low_proc == -1)
2190 low_proc = m_field.get_comm_rank();
2191 if (hi_proc == -1)
2192 hi_proc = m_field.get_comm_rank();
2193
2194 // Find pointer to problem of given name
2195 typedef Problem_multiIndex::index<Problem_mi_tag>::type ProblemByName;
2196 auto &problems =
2197 const_cast<ProblemByName &>(problems_ptr->get<Problem_mi_tag>());
2198 ProblemByName::iterator p_miit = problems.find(name);
2199 if (p_miit == problems.end()) {
2200 SETERRQ(m_field.get_comm(), MOFEM_NOT_FOUND,
2201 "problem < %s > not found (top tip: check spelling)",
2202 name.c_str());
2203 }
2204
2205 // Get reference on finite elements multi-index on the problem
2206 NumeredEntFiniteElement_multiIndex &problem_finite_elements =
2207 *p_miit->numeredFiniteElementsPtr;
2208
2209 // Clear all elements and data, build it again
2210 problem_finite_elements.clear();
2211
2212 // Check if dofs and columns are the same, i.e. structurally symmetric
2213 // problem
2214 bool do_cols_prob = true;
2215 if (p_miit->numeredRowDofsPtr == p_miit->numeredColDofsPtr) {
2216 do_cols_prob = false;
2217 }
2218
2219 auto get_good_elems = [&]() {
2220 auto good_elems = std::vector<decltype(fe_ent_ptr->begin())>();
2221 good_elems.reserve(fe_ent_ptr->size());
2222
2223 const auto prb_bit = p_miit->getBitRefLevel();
2224 const auto prb_mask = p_miit->getBitRefLevelMask();
2225
2226 // Loop over all elements in database and if right element is there add it
2227 // to problem finite element multi-index
2228 for (auto efit = fe_ent_ptr->begin(); efit != fe_ent_ptr->end(); ++efit) {
2229
2230 // if element is not part of problem
2231 if (((*efit)->getId() & p_miit->getBitFEId()).any()) {
2232
2233 const auto &fe_bit = (*efit)->getBitRefLevel();
2234
2235 // if entity is not problem refinement level
2236 if ((fe_bit & prb_mask) == fe_bit && (fe_bit & prb_bit).any())
2237 good_elems.emplace_back(efit);
2238 }
2239 }
2240
2241 return good_elems;
2242 };
2243
2244 auto good_elems = get_good_elems();
2245
2246 auto numbered_good_elems_ptr =
2247 boost::make_shared<std::vector<NumeredEntFiniteElement>>();
2248 numbered_good_elems_ptr->reserve(good_elems.size());
2249 for (auto &efit : good_elems)
2250 numbered_good_elems_ptr->emplace_back(NumeredEntFiniteElement(*efit));
2251
2252 if (!do_cols_prob) {
2253 for (auto &fe : *numbered_good_elems_ptr) {
2254 if (fe.sPtr->getRowFieldEntsPtr() == fe.sPtr->getColFieldEntsPtr()) {
2255 fe.getColFieldEntsPtr() = fe.getRowFieldEntsPtr();
2256 }
2257 }
2258 }
2259
2260 if (part_from_moab) {
2261 for (auto &fe : *numbered_good_elems_ptr) {
2262 if (fe.getEntType() == MBENTITYSET) {
2263 fe.part = m_field.get_comm_rank();
2264 } else {
2265 // if partition is taken from moab partition
2266 int proc = fe.getPartProc();
2267 if (proc == -1 && fe.getEntType() == MBVERTEX)
2268 proc = fe.getOwnerProc();
2269 fe.part = proc;
2270 }
2271 }
2272 }
2273
2274 for (auto &fe : *numbered_good_elems_ptr) {
2275
2277 CHKERR fe.sPtr->getRowDofView(*(p_miit->numeredRowDofsPtr), rows_view);
2278
2279 if (!part_from_moab) {
2280 if (fe.getEntType() == MBENTITYSET) {
2281 fe.part = m_field.get_comm_rank();
2282 } else {
2283 std::vector<int> parts(m_field.get_comm_size(), 0);
2284 for (auto &dof_ptr : rows_view)
2285 parts[dof_ptr->pArt]++;
2286 std::vector<int>::iterator pos =
2287 max_element(parts.begin(), parts.end());
2288 const auto max_part = std::distance(parts.begin(), pos);
2289 fe.part = max_part;
2290 }
2291 }
2292 }
2293
2294 for (auto &fe : *numbered_good_elems_ptr) {
2295
2296 auto check_fields_and_dofs = [&]() {
2297 if (!part_from_moab) {
2298 if (fe.getBitFieldIdRow().none() && m_field.get_comm_size() == 0) {
2299 MOFEM_LOG("WORLD", Sev::warning)
2300 << "At least one field has to be added to element row to "
2301 "determine partition of finite element. Check element " +
2302 boost::lexical_cast<std::string>(fe.getName());
2303 }
2304 }
2305
2306 return true;
2307 };
2308
2309 if (check_fields_and_dofs()) {
2310 // Add element to the problem
2311 auto p = problem_finite_elements.insert(
2312 boost::shared_ptr<NumeredEntFiniteElement>(numbered_good_elems_ptr,
2313 &fe));
2314 if (!p.second)
2315 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_FOUND, "element is there");
2316 }
2317 }
2318
2319 if (verb >= VERBOSE) {
2320 auto elements_on_rank =
2321 problem_finite_elements.get<Part_mi_tag>().equal_range(
2322 m_field.get_comm_rank());
2323 MOFEM_LOG("SYNC", Sev::verbose)
2324 << p_miit->getName() << " nb. elems "
2325 << std::distance(elements_on_rank.first, elements_on_rank.second);
2326 auto fe_ptr = m_field.get_finite_elements();
2327 for (auto &fe : *fe_ptr) {
2328 auto e_range =
2329 problem_finite_elements.get<Composite_Name_And_Part_mi_tag>()
2330 .equal_range(
2331 boost::make_tuple(fe->getName(), m_field.get_comm_rank()));
2332 MOFEM_LOG("SYNC", Sev::noisy)
2333 << "Element " << fe->getName() << " nb. elems "
2334 << std::distance(e_range.first, e_range.second);
2335 }
2336
2338 }
2339
2342}
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
multi_index_container< boost::shared_ptr< NumeredEntFiniteElement >, indexed_by< ordered_unique< tag< Unique_mi_tag >, const_mem_fun< NumeredEntFiniteElement::interface_type_EntFiniteElement, UId, &NumeredEntFiniteElement::getLocalUniqueId > >, ordered_non_unique< tag< Part_mi_tag >, member< NumeredEntFiniteElement, unsigned int, &NumeredEntFiniteElement::part > >, ordered_non_unique< tag< Ent_mi_tag >, const_mem_fun< NumeredEntFiniteElement::interface_type_RefEntity, EntityHandle, &NumeredEntFiniteElement::getEnt > >, ordered_non_unique< tag< Composite_Name_And_Part_mi_tag >, composite_key< NumeredEntFiniteElement, const_mem_fun< NumeredEntFiniteElement::interface_type_FiniteElement, boost::string_ref, &NumeredEntFiniteElement::getNameRef >, member< NumeredEntFiniteElement, unsigned int, &NumeredEntFiniteElement::part > > > > > NumeredEntFiniteElement_multiIndex
MultiIndex for entities for NumeredEntFiniteElement.
virtual const EntFiniteElement_multiIndex * get_ents_finite_elements() const =0
Get the ents finite elements object.
multi_index_container< boost::shared_ptr< NumeredDofEntity >, indexed_by< ordered_unique< const_mem_fun< NumeredDofEntity::interface_type_DofEntity, UId, &NumeredDofEntity::getLocalUniqueId > > > > NumeredDofEntity_multiIndex_uid_view_ordered

◆ partitionGhostDofs()

MoFEMErrorCode MoFEM::ProblemsManager::partitionGhostDofs ( const std::string  name,
int  verb = VERBOSE 
)

determine ghost nodes

Parameters
nameproblem name

DOFs are ghost dofs if are used by elements on given partition, but not owned by that partition.

Examples
build_problems.cpp, continuity_check_on_skeleton_3d.cpp, forces_and_sources_testing_edge_element.cpp, forces_and_sources_testing_flat_prism_element.cpp, hcurl_divergence_operator_2d.cpp, mesh_insert_interface_atom.cpp, nonlinear_dynamics.cpp, nonlinear_elastic.cpp, prism_elements_from_surface.cpp, prism_polynomial_approximation.cpp, quad_polynomial_approximation.cpp, and remove_entities_from_problem.cpp.

Definition at line 2344 of file ProblemsManager.cpp.

2345 {
2346 MoFEM::Interface &m_field = cOre;
2347 auto problems_ptr = m_field.get_problems();
2349
2351 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2352 "partition of problem not build");
2354 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2355 "partitions finite elements not build");
2356
2357 // get problem pointer
2358 auto p_miit = problems_ptr->get<Problem_mi_tag>().find(name);
2359 if (p_miit == problems_ptr->get<Problem_mi_tag>().end())
2360 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA, "Problem %s not fond",
2361 name.c_str());
2362
2363 // get reference to number of ghost dofs
2364 int &nb_row_ghost_dofs = p_miit->nbGhostDofsRow;
2365 int &nb_col_ghost_dofs = p_miit->nbGhostDofsCol;
2366 nb_row_ghost_dofs = 0;
2367 nb_col_ghost_dofs = 0;
2368
2369 // do work if more than one processor
2370 if (m_field.get_comm_size() > 1) {
2371
2373 ghost_idx_col_view;
2374
2375 // get elements on this partition
2376 auto fe_range =
2377 p_miit->numeredFiniteElementsPtr->get<Part_mi_tag>().equal_range(
2378 m_field.get_comm_rank());
2379
2380 // get dofs on elements which are not part of this partition
2381
2382 struct Inserter {
2383 using Vec = std::vector<boost::shared_ptr<NumeredDofEntity>>;
2384 using It = Vec::iterator;
2385 It operator()(Vec &dofs_view, It &hint,
2386 boost::shared_ptr<NumeredDofEntity> &&dof) {
2387 dofs_view.emplace_back(dof);
2388 return dofs_view.end();
2389 }
2390 };
2391
2392 // rows
2393 std::vector<boost::shared_ptr<NumeredDofEntity>> fe_vec_view;
2394 auto hint_r = ghost_idx_row_view.begin();
2395 for (auto fe_ptr = fe_range.first; fe_ptr != fe_range.second; ++fe_ptr) {
2396
2397 fe_vec_view.clear();
2398 CHKERR EntFiniteElement::getDofView((*fe_ptr)->getRowFieldEnts(),
2399 *(p_miit->getNumeredRowDofsPtr()),
2400 fe_vec_view, Inserter());
2401
2402 for (auto &dof_ptr : fe_vec_view) {
2403 if (dof_ptr->getPart() != (unsigned int)m_field.get_comm_rank()) {
2404 hint_r = ghost_idx_row_view.emplace_hint(hint_r, dof_ptr);
2405 }
2406 }
2407 }
2408
2409 // columns
2410 if (p_miit->numeredColDofsPtr == p_miit->numeredRowDofsPtr) {
2411
2412 auto hint_c = ghost_idx_col_view.begin();
2413 for (auto fe_ptr = fe_range.first; fe_ptr != fe_range.second; ++fe_ptr) {
2414
2415 fe_vec_view.clear();
2416 CHKERR EntFiniteElement::getDofView((*fe_ptr)->getColFieldEnts(),
2417 *(p_miit->getNumeredColDofsPtr()),
2418 fe_vec_view, Inserter());
2419
2420 for (auto &dof_ptr : fe_vec_view) {
2421 if (dof_ptr->getPart() != (unsigned int)m_field.get_comm_rank()) {
2422 hint_c = ghost_idx_col_view.emplace_hint(hint_c, dof_ptr);
2423 }
2424 }
2425 }
2426 }
2427
2428 int *nb_ghost_dofs[2] = {&nb_row_ghost_dofs, &nb_col_ghost_dofs};
2429 int nb_local_dofs[2] = {p_miit->nbLocDofsRow, p_miit->nbLocDofsCol};
2430
2432 &ghost_idx_row_view, &ghost_idx_col_view};
2433 NumeredDofEntityByUId *dof_by_uid_no_const[2] = {
2434 &p_miit->numeredRowDofsPtr->get<Unique_mi_tag>(),
2435 &p_miit->numeredColDofsPtr->get<Unique_mi_tag>()};
2436
2437 int loop_size = 2;
2438 if (p_miit->numeredColDofsPtr == p_miit->numeredRowDofsPtr) {
2439 loop_size = 1;
2440 }
2441
2442 // set local ghost dofs indices
2443 for (int ss = 0; ss != loop_size; ++ss) {
2444 for (auto &gid : *ghost_idx_view[ss]) {
2445 NumeredDofEntityByUId::iterator dof =
2446 dof_by_uid_no_const[ss]->find(gid->getLocalUniqueId());
2447 if (PetscUnlikely((*dof)->petscLocalDofIdx != (DofIdx)-1))
2448 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2449 "inconsistent data, ghost dof already set");
2450 bool success = dof_by_uid_no_const[ss]->modify(
2451 dof, NumeredDofEntity_local_idx_change(nb_local_dofs[ss]++));
2452 if (PetscUnlikely(!success))
2453 SETERRQ(m_field.get_comm(), MOFEM_OPERATION_UNSUCCESSFUL,
2454 "modification unsuccessful");
2455 (*nb_ghost_dofs[ss])++;
2456 }
2457 }
2458 if (loop_size == 1) {
2459 (*nb_ghost_dofs[1]) = (*nb_ghost_dofs[0]);
2460 }
2461 }
2462
2463 if (verb > QUIET) {
2464 MOFEM_LOG("SYNC", Sev::inform)
2465 << " FEs ghost dofs on problem " << p_miit->getName()
2466 << " Nb. ghost dof " << p_miit->getNbGhostDofsRow() << " by "
2467 << p_miit->getNbGhostDofsCol() << " Nb. local dof "
2468 << p_miit->getNbLocalDofsCol() << " by " << p_miit->getNbLocalDofsCol();
2469
2471 }
2472
2475}
@ MOFEM_INVALID_DATA
Definition definitions.h:36
const FTensor::Tensor2< T, Dim, Dim > Vec
int DofIdx
Index of DOF.
Definition Types.hpp:18
static MoFEMErrorCode getDofView(const FE_ENTS &fe_ents_view, const MOFEM_DOFS &mofem_dofs, MOFEM_DOFS_VIEW &dofs_view, INSERTER &&inserter)

◆ partitionGhostDofsOnDistributedMesh()

MoFEMErrorCode MoFEM::ProblemsManager::partitionGhostDofsOnDistributedMesh ( const std::string  name,
int  verb = VERBOSE 
)

determine ghost nodes on distributed meshes

Parameters
nameproblem name

It is very similar for partitionGhostDofs, however this explits that mesh is distributed.

DOFs are ghosted if are shered but not owned by partition.

Examples
remove_entities_from_problem.cpp.

Definition at line 2478 of file ProblemsManager.cpp.

2479 {
2480 MoFEM::Interface &m_field = cOre;
2481 auto problems_ptr = m_field.get_problems();
2483
2485 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2486 "partition of problem not build");
2488 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2489 "partitions finite elements not build");
2490
2491 // get problem pointer
2492 typedef Problem_multiIndex::index<Problem_mi_tag>::type ProblemsByName;
2493 // find p_miit
2494 ProblemsByName &problems_set =
2495 const_cast<ProblemsByName &>(problems_ptr->get<Problem_mi_tag>());
2496 ProblemsByName::iterator p_miit = problems_set.find(name);
2497
2498 // get reference to number of ghost dofs
2499 // get number of local dofs
2500 DofIdx *nb_ghost_dofs[2] = {&(p_miit->nbGhostDofsRow),
2501 &(p_miit->nbGhostDofsCol)};
2502 DofIdx nb_local_dofs[2] = {p_miit->nbLocDofsRow, p_miit->nbLocDofsCol};
2503 for (int ss = 0; ss != 2; ++ss) {
2504 (*nb_ghost_dofs[ss]) = 0;
2505 }
2506
2507 // do work if more than one processor
2508 if (m_field.get_comm_size() > 1) {
2509 // determine if rows on columns are different from dofs on rows
2510 int loop_size = 2;
2511 if (p_miit->numeredColDofsPtr == p_miit->numeredRowDofsPtr) {
2512 loop_size = 1;
2513 }
2514
2515 typedef decltype(p_miit->numeredRowDofsPtr) NumbDofTypeSharedPtr;
2516 NumbDofTypeSharedPtr numered_dofs[] = {p_miit->numeredRowDofsPtr,
2517 p_miit->numeredColDofsPtr};
2518
2519 // iterate over dofs on rows and dofs on columns
2520 for (int ss = 0; ss != loop_size; ++ss) {
2521
2522 // create dofs view by uid
2523 auto r = numered_dofs[ss]->get<PetscLocalIdx_mi_tag>().equal_range(-1);
2524
2525 std::vector<NumeredDofEntity_multiIndex::iterator> ghost_idx_view;
2526 ghost_idx_view.reserve(std::distance(r.first, r.second));
2527 for (; r.first != r.second; ++r.first)
2528 ghost_idx_view.emplace_back(numered_dofs[ss]->project<0>(r.first));
2529
2530 auto cmp = [](auto a, auto b) {
2531 return (*a)->getLocalUniqueId() < (*b)->getLocalUniqueId();
2532 };
2533 sort(ghost_idx_view.begin(), ghost_idx_view.end(), cmp);
2534
2535 // iterate over dofs which have negative local index
2536 for (auto gid_it : ghost_idx_view) {
2537 bool success = numered_dofs[ss]->modify(
2538 gid_it, NumeredDofEntity_local_idx_change((nb_local_dofs[ss])++));
2539 if (!success)
2540 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
2541 "modification unsuccessful");
2542 ++(*nb_ghost_dofs[ss]);
2543 }
2544 }
2545 if (loop_size == 1) {
2546 (*nb_ghost_dofs[1]) = (*nb_ghost_dofs[0]);
2547 }
2548 }
2549
2550 if (verb > QUIET) {
2551 MOFEM_LOG("SYNC", Sev::inform)
2552 << " FEs ghost dofs on problem " << p_miit->getName()
2553 << " Nb. ghost dof " << p_miit->getNbGhostDofsRow() << " by "
2554 << p_miit->getNbGhostDofsCol() << " Nb. local dof "
2555 << p_miit->getNbLocalDofsCol() << " by " << p_miit->getNbLocalDofsCol();
2556
2558 }
2559
2562}
constexpr double a

◆ partitionMesh() [1/2]

MoFEMErrorCode MoFEM::CommInterface::partitionMesh ( const Range ents,
const int  dim,
const int  adj_dim,
const int  n_parts,
Tag *  th_vertex_weights = nullptr,
Tag *  th_edge_weights = nullptr,
Tag *  th_part_weights = nullptr,
int  verb = VERBOSE,
const bool  debug = false 
)

Set partition tag to each finite element in the problem.

This will use one of the mesh partitioning programs available from PETSc See http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Mat/MatPartitioningType.html

Parameters
entsEntities to partition
dimDimension of entities to partition
adj_dimAdjacency dimension
n_partsNumber of partitions
verbVerbosity level
Returns
Error code
Examples
partition_mesh.cpp.

Definition at line 868 of file CommInterface.cpp.

871 {
872 MoFEM::Interface &m_field = cOre;
874
875 // get layout
876 int rstart, rend, nb_elems;
877 {
878 PetscLayout layout;
879 CHKERR PetscLayoutCreate(m_field.get_comm(), &layout);
880 CHKERR PetscLayoutSetBlockSize(layout, 1);
881 CHKERR PetscLayoutSetSize(layout, ents.size());
882 CHKERR PetscLayoutSetUp(layout);
883 CHKERR PetscLayoutGetSize(layout, &nb_elems);
884 CHKERR PetscLayoutGetRange(layout, &rstart, &rend);
885 CHKERR PetscLayoutDestroy(&layout);
886 if (verb >= VERBOSE) {
887 MOFEM_LOG("SYNC", Sev::inform)
888 << "Finite elements in problem: row lower " << rstart << " row upper "
889 << rend << " nb. elems " << nb_elems << " ( " << ents.size() << " )";
891 }
892 }
893
894 std::vector<EntityHandle> weight_ents;
895 weight_ents.reserve(rend - rstart + 1);
896
897 struct AdjBridge {
898 EntityHandle ent;
899 std::vector<int> adj;
900 AdjBridge(const EntityHandle ent, std::vector<int> &adj)
901 : ent(ent), adj(adj) {}
902 };
903
904 typedef multi_index_container<
905 AdjBridge,
906 indexed_by<
907
908 hashed_unique<member<AdjBridge, EntityHandle, &AdjBridge::ent>>
909
910 >>
911 AdjBridgeMap;
912
913 auto get_it = [&](auto i) {
914 auto it = ents.begin();
915 for (; i > 0; --i) {
916 if (it == ents.end())
917 break;
918 ++it;
919 }
920 return it;
921 };
922
923 Range proc_ents;
924 proc_ents.insert(get_it(rstart), get_it(rend));
925 if (proc_ents.size() != rend - rstart)
926 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
927 "Wrong number of elements in range %ld != %d", proc_ents.size(),
928 rend - rstart);
929
930 Range all_dim_ents;
931 CHKERR m_field.get_moab().get_adjacencies(
932 proc_ents, adj_dim, true, all_dim_ents, moab::Interface::UNION);
933
934 AdjBridgeMap adj_bridge_map;
935 auto hint = adj_bridge_map.begin();
936 std::vector<int> adj;
937 for (auto ent : all_dim_ents) {
938 Range adj_ents;
939 CHKERR m_field.get_moab().get_adjacencies(&ent, 1, dim, false, adj_ents);
940 adj_ents = intersect(adj_ents, ents);
941 adj.clear();
942 adj.reserve(adj_ents.size());
943 for (auto a : adj_ents)
944 adj.emplace_back(ents.index(a));
945 hint = adj_bridge_map.emplace_hint(hint, ent, adj);
946 }
947
948 int *_i;
949 int *_j;
950 {
951 const int nb_loc_elements = rend - rstart;
952 std::vector<int> i(nb_loc_elements + 1, 0), j;
953 {
954 std::vector<int> row_adj;
955 Range::iterator fe_it;
956 int ii, jj;
957 size_t max_row_size;
958 for (fe_it = proc_ents.begin(), ii = rstart, jj = 0, max_row_size = 0;
959 fe_it != proc_ents.end(); ++fe_it, ++ii) {
960
961 if (type_from_handle(*fe_it) == MBENTITYSET) {
962 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
963 "not yet implemented, don't know what to do for meshset "
964 "element");
965 } else {
966
967 Range dim_ents;
968 CHKERR m_field.get_moab().get_adjacencies(&*fe_it, 1, adj_dim, false,
969 dim_ents);
970 dim_ents = intersect(dim_ents, all_dim_ents);
971
972 row_adj.clear();
973 for (auto e : dim_ents) {
974 auto adj_it = adj_bridge_map.find(e);
975 if (adj_it != adj_bridge_map.end()) {
976
977 for (const auto idx : adj_it->adj)
978 row_adj.push_back(idx);
979
980 } else
981 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
982 "Entity not found");
983 }
984
985 std::sort(row_adj.begin(), row_adj.end());
986 auto end = std::unique(row_adj.begin(), row_adj.end());
987
988 size_t row_size = std::distance(row_adj.begin(), end);
989 max_row_size = std::max(max_row_size, row_size);
990 if (j.capacity() < (nb_loc_elements - jj) * max_row_size)
991 j.reserve(nb_loc_elements * max_row_size);
992
993 i[jj] = j.size();
994 auto diag = ents.index(*fe_it);
995 for (auto it = row_adj.begin(); it != end; ++it)
996 if (*it != diag)
997 j.push_back(*it);
998 }
999
1000 ++jj;
1001
1002 if (th_vertex_weights != NULL)
1003 weight_ents.push_back(*fe_it);
1004 }
1005
1006 i[jj] = j.size();
1007 }
1008
1009 CHKERR PetscMalloc(i.size() * sizeof(int), &_i);
1010 CHKERR PetscMalloc(j.size() * sizeof(int), &_j);
1011 copy(i.begin(), i.end(), _i);
1012 copy(j.begin(), j.end(), _j);
1013 }
1014
1015 // get weights
1016 int *vertex_weights = NULL;
1017 if (th_vertex_weights != NULL) {
1018 CHKERR PetscMalloc(weight_ents.size() * sizeof(int), &vertex_weights);
1019 CHKERR m_field.get_moab().tag_get_data(*th_vertex_weights,
1020 &*weight_ents.begin(),
1021 weight_ents.size(), vertex_weights);
1022 }
1023
1024 {
1025 Mat Adj;
1026 // Adjacency matrix used to partition problems, f.e. METIS
1027 CHKERR MatCreateMPIAdj(m_field.get_comm(), rend - rstart, nb_elems, _i, _j,
1028 PETSC_NULLPTR, &Adj);
1029 CHKERR MatSetOption(Adj, MAT_STRUCTURALLY_SYMMETRIC, PETSC_TRUE);
1030
1031 if (debug) {
1032 Mat A;
1033 CHKERR MatConvert(Adj, MATMPIAIJ, MAT_INITIAL_MATRIX, &A);
1034 CHKERR MatView(A, PETSC_VIEWER_DRAW_WORLD);
1035 std::string wait;
1036 std::cin >> wait;
1037 CHKERR MatDestroy(&A);
1038 }
1039
1040 // run pets to do partitioning
1041 MOFEM_LOG("WORLD", Sev::verbose) << "Start";
1042
1043 MatPartitioning part;
1044 IS is;
1045 CHKERR MatPartitioningCreate(m_field.get_comm(), &part);
1046
1047 CHKERR MatPartitioningSetAdjacency(part, Adj);
1048 CHKERR MatPartitioningSetFromOptions(part);
1049 CHKERR MatPartitioningSetNParts(part, n_parts);
1050 if (th_vertex_weights != NULL) {
1051 CHKERR MatPartitioningSetVertexWeights(part, vertex_weights);
1052 }
1053 CHKERR MatPartitioningApply(part, &is);
1054
1055 MOFEM_LOG("WORLD", Sev::verbose) << "End";
1056
1057 // gather
1058 IS is_gather, is_num, is_gather_num;
1059 CHKERR ISAllGather(is, &is_gather);
1060 CHKERR ISPartitioningToNumbering(is, &is_num);
1061 CHKERR ISAllGather(is_num, &is_gather_num);
1062
1063 const int *part_number, *gids;
1064 CHKERR ISGetIndices(is_gather, &part_number);
1065 CHKERR ISGetIndices(is_gather_num, &gids);
1066
1067 // set partition tag and gid tag to entities
1068 ParallelComm *pcomm = ParallelComm::get_pcomm(
1069 &m_field.get_moab(), m_field.get_basic_entity_data_ptr()->pcommID);
1070 Tag part_tag = pcomm->part_tag();
1071 CHKERR m_field.get_moab().tag_set_data(part_tag, ents, part_number);
1072 Tag gid_tag = m_field.get_moab().globalId_tag();
1073
1074 std::map<int, Range> parts_ents;
1075 {
1076 // get entities on each part
1077 Range::iterator eit = ents.begin();
1078 for (int ii = 0; eit != ents.end(); eit++, ii++) {
1079 parts_ents[part_number[ii]].insert(*eit);
1080 }
1081 Range tagged_sets;
1082 CHKERR m_field.get_moab().get_entities_by_type_and_tag(
1083 0, MBENTITYSET, &part_tag, NULL, 1, tagged_sets,
1084 moab::Interface::UNION);
1085 if (!tagged_sets.empty())
1086 CHKERR m_field.get_moab().tag_delete_data(part_tag, tagged_sets);
1087
1088 if (n_parts > (int)tagged_sets.size()) {
1089 // too few partition sets - create missing ones
1090 int num_new = n_parts - tagged_sets.size();
1091 for (int i = 0; i < num_new; i++) {
1092 EntityHandle new_set;
1093 CHKERR m_field.get_moab().create_meshset(MESHSET_SET, new_set);
1094 tagged_sets.insert(new_set);
1095 }
1096 } else if (n_parts < (int)tagged_sets.size()) {
1097 // too many partition sets - delete extras
1098 int num_del = tagged_sets.size() - n_parts;
1099 for (int i = 0; i < num_del; i++) {
1100 EntityHandle old_set = tagged_sets.pop_back();
1101 CHKERR m_field.get_moab().delete_entities(&old_set, 1);
1102 }
1103 }
1104 // write a tag to those sets denoting they're partition sets, with a
1105 // value of the proc number
1106 std::vector<int> dum_ids(n_parts);
1107 for (int i = 0; i < n_parts; i++)
1108 dum_ids[i] = i;
1109 CHKERR m_field.get_moab().tag_set_data(part_tag, tagged_sets,
1110 &*dum_ids.begin());
1111 CHKERR m_field.get_moab().clear_meshset(tagged_sets);
1112
1113 // get lower dimension entities on each part
1114 for (int pp = 0; pp != n_parts; pp++) {
1115 Range dim_ents = parts_ents[pp].subset_by_dimension(dim);
1116 for (int dd = dim - 1; dd >= 0; dd--) {
1117 Range adj_ents;
1118 CHKERR m_field.get_moab().get_adjacencies(
1119 dim_ents, dd, false, adj_ents, moab::Interface::UNION);
1120 parts_ents[pp].merge(adj_ents);
1121 }
1122 }
1123 for (int pp = 1; pp != n_parts; pp++) {
1124 for (int ppp = 0; ppp != pp; ppp++) {
1125 parts_ents[pp] = subtract(parts_ents[pp], parts_ents[ppp]);
1126 }
1127 }
1128
1129 for (int pp = 0; pp != n_parts; pp++) {
1130 CHKERR m_field.get_moab().add_entities(tagged_sets[pp], parts_ents[pp]);
1131 }
1132
1133 auto set_part = [&]() {
1135 for (EntityType t = MBEDGE; t != MBENTITYSET; ++t) {
1136 for (int pp = 0; pp != n_parts; pp++) {
1137 Range type_ents = parts_ents[pp].subset_by_type(t);
1138 CHKERR m_field.get_moab().tag_clear_data(part_tag, type_ents, &pp);
1139 }
1140 }
1142 };
1143
1144 auto set_gid = [&]() {
1146 for (int d = 0; d != 4; ++d) {
1147
1148 void *ptr;
1149 int count;
1150
1151 int gid = 1; // moab indexing from 1
1152 for (int pp = 0; pp != n_parts; pp++) {
1153 Range type_ents = parts_ents[pp].subset_by_dimension(d);
1154
1155 auto eit = type_ents.begin();
1156 for (; eit != type_ents.end();) {
1157 CHKERR m_field.get_moab().tag_iterate(
1158 gid_tag, eit, type_ents.end(), count, ptr);
1159 auto gid_tag_ptr = static_cast<int *>(ptr);
1160 for (; count > 0; --count) {
1161 *gid_tag_ptr = gid;
1162 ++eit;
1163 ++gid;
1164 ++gid_tag_ptr;
1165 }
1166 }
1167 }
1168 }
1169
1171 };
1172
1173 CHKERR set_part();
1174 CHKERR set_gid();
1175 }
1176
1177 if (debug) {
1178 if (m_field.get_comm_rank() == 0) {
1179 for (int rr = 0; rr != n_parts; rr++) {
1180 ostringstream ss;
1181 ss << "out_part_" << rr << ".vtk";
1182 MOFEM_LOG("SELF", Sev::inform) << "Save debug part mesh " << ss.str();
1183 EntityHandle meshset;
1184 CHKERR m_field.get_moab().create_meshset(MESHSET_SET, meshset);
1185 CHKERR m_field.get_moab().add_entities(meshset, parts_ents[rr]);
1186 CHKERR m_field.get_moab().write_file(ss.str().c_str(), "VTK", "",
1187 &meshset, 1);
1188 CHKERR m_field.get_moab().delete_entities(&meshset, 1);
1189 }
1190 }
1191 }
1192
1193 CHKERR ISRestoreIndices(is_gather, &part_number);
1194 CHKERR ISRestoreIndices(is_gather_num, &gids);
1195 CHKERR ISDestroy(&is_num);
1196 CHKERR ISDestroy(&is_gather_num);
1197 CHKERR ISDestroy(&is_gather);
1198 CHKERR ISDestroy(&is);
1199 CHKERR MatPartitioningDestroy(&part);
1200 CHKERR MatDestroy(&Adj);
1201 }
1202
1204}
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'j', 3 > j
constexpr AssemblyType A
constexpr double t
plate stiffness
Definition plate.cpp:58
virtual boost::shared_ptr< BasicEntityData > & get_basic_entity_data_ptr()=0
Get pointer to basic entity data.

◆ partitionMesh() [2/2]

MoFEMErrorCode MoFEM::ProblemsManager::partitionMesh ( const Range ents,
const int  dim,
const int  adj_dim,
const int  n_parts,
Tag *  th_vertex_weights = nullptr,
Tag *  th_edge_weights = nullptr,
Tag *  th_part_weights = nullptr,
int  verb = VERBOSE,
const bool  debug = false 
)

Set partition tag to each finite element in the problem.

Deprecated:
Use CommInterface

This will use one of the mesh partitioning programs available from PETSc See http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Mat/MatPartitioningType.html

Parameters
entsEntities to partition
dimDimension of entities to partition
adj_dimAdjacency dimension
n_partsNumber of partitions
verbVerbosity level
Returns
Error code

Definition at line 76 of file ProblemsManager.cpp.

79 {
80 return static_cast<MoFEM::Interface &>(cOre)
81 .getInterface<CommInterface>()
82 ->partitionMesh(ents, dim, adj_dim, n_parts, th_vertex_weights,
83 th_edge_weights, th_part_weights, verb, debug);
84}
static const bool debug

◆ partitionProblem()

MoFEMErrorCode MoFEM::ProblemsManager::partitionProblem ( const std::string  name,
int  verb = VERBOSE 
)

partition problem dofs (collective)

Parameters
nameproblem name
Examples
build_problems.cpp, continuity_check_on_skeleton_3d.cpp, mesh_insert_interface_atom.cpp, nonlinear_dynamics.cpp, nonlinear_elastic.cpp, and remove_entities_from_problem_not_partitioned.cpp.

Definition at line 1679 of file ProblemsManager.cpp.

1680 {
1681 MoFEM::Interface &m_field = cOre;
1682 auto problems_ptr = m_field.get_problems();
1684
1685 MOFEM_LOG("WORLD", Sev::noisy) << "Partition problem " << name;
1686
1687 using NumeredDofEntitysByIdx =
1688 NumeredDofEntity_multiIndex::index<Idx_mi_tag>::type;
1689 using ProblemsByName = Problem_multiIndex::index<Problem_mi_tag>::type;
1690
1691 // Find problem pointer by name
1692 auto &problems_set =
1693 const_cast<ProblemsByName &>(problems_ptr->get<Problem_mi_tag>());
1694 auto p_miit = problems_set.find(name);
1695 if (p_miit == problems_set.end()) {
1696 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA,
1697 "problem with name %s not defined (top tip check spelling)",
1698 name.c_str());
1699 }
1700 int nb_dofs_row = p_miit->getNbDofsRow();
1701
1702 if (m_field.get_comm_size() != 1) {
1703
1704 if (!(cOre.getBuildMoFEM() & (1 << 0)))
1705 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "fields not build");
1706 if (!(cOre.getBuildMoFEM() & (1 << 1)))
1707 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "FEs not build");
1708 if (!(cOre.getBuildMoFEM() & (1 << 2)))
1709 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1710 "entFEAdjacencies not build");
1711 if (!(cOre.getBuildMoFEM() & (1 << 3)))
1712 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Problems not build");
1713
1714 Mat Adj;
1715 CHKERR m_field.getInterface<MatrixManager>()
1716 ->createMPIAdjWithArrays<Idx_mi_tag>(name, &Adj, verb);
1717
1718 int m, n;
1719 CHKERR MatGetSize(Adj, &m, &n);
1720 if (verb > VERY_VERBOSE)
1721 MatView(Adj, PETSC_VIEWER_STDOUT_WORLD);
1722
1723 // partitioning
1724 MatPartitioning part;
1725 IS is;
1726 CHKERR MatPartitioningCreate(m_field.get_comm(), &part);
1727 CHKERR MatPartitioningSetAdjacency(part, Adj);
1728 CHKERR MatPartitioningSetFromOptions(part);
1729 CHKERR MatPartitioningSetNParts(part, m_field.get_comm_size());
1730 CHKERR MatPartitioningApply(part, &is);
1731 if (verb > VERY_VERBOSE)
1732 ISView(is, PETSC_VIEWER_STDOUT_WORLD);
1733
1734 // gather
1735 IS is_gather, is_num, is_gather_num;
1736 CHKERR ISAllGather(is, &is_gather);
1737 CHKERR ISPartitioningToNumbering(is, &is_num);
1738 CHKERR ISAllGather(is_num, &is_gather_num);
1739 const int *part_number, *petsc_idx;
1740 CHKERR ISGetIndices(is_gather, &part_number);
1741 CHKERR ISGetIndices(is_gather_num, &petsc_idx);
1742 int size_is_num, size_is_gather;
1743 CHKERR ISGetSize(is_gather, &size_is_gather);
1744 if (size_is_gather != (int)nb_dofs_row)
1745 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1746 "data inconsistency %d != %d", size_is_gather, nb_dofs_row);
1747
1748 CHKERR ISGetSize(is_num, &size_is_num);
1749 if (size_is_num != (int)nb_dofs_row)
1750 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1751 "data inconsistency %d != %d", size_is_num, nb_dofs_row);
1752
1753 bool square_matrix = false;
1754 if (p_miit->numeredRowDofsPtr == p_miit->numeredColDofsPtr)
1755 square_matrix = true;
1756
1757 // if (!square_matrix) {
1758 // // FIXME: This is for back compatibility, if deprecate interface
1759 // function
1760 // // build interfaces is removed, this part of the code will be obsolete
1761 // auto mit_row = p_miit->numeredRowDofsPtr->get<Idx_mi_tag>().begin();
1762 // auto hi_mit_row = p_miit->numeredRowDofsPtr->get<Idx_mi_tag>().end();
1763 // auto mit_col = p_miit->numeredColDofsPtr->get<Idx_mi_tag>().begin();
1764 // auto hi_mit_col = p_miit->numeredColDofsPtr->get<Idx_mi_tag>().end();
1765 // for (; mit_row != hi_mit_row; mit_row++, mit_col++) {
1766 // if (mit_col == hi_mit_col) {
1767 // SETERRQ(
1768 // PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1769 // "check finite element definition, nb. of rows is not equal to "
1770 // "number for columns");
1771 // }
1772 // if (mit_row->get()->getLocalUniqueId() !=
1773 // mit_col->get()->getLocalUniqueId()) {
1774 // SETERRQ(
1775 // PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1776 // "check finite element definition, nb. of rows is not equal to "
1777 // "number for columns");
1778 // }
1779 // }
1780 // }
1781
1782 auto number_dofs = [&](auto &dofs_idx, auto &counter) {
1784 for (auto miit_dofs_row = dofs_idx.begin();
1785 miit_dofs_row != dofs_idx.end(); miit_dofs_row++) {
1786 const int part = part_number[(*miit_dofs_row)->dofIdx];
1787 if (part == (unsigned int)m_field.get_comm_rank()) {
1788 const bool success = dofs_idx.modify(
1789 miit_dofs_row,
1790 NumeredDofEntity_part_and_indices_change(
1791 part, petsc_idx[(*miit_dofs_row)->dofIdx], counter++));
1792 if (!success) {
1793 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
1794 "modification unsuccessful");
1795 }
1796 } else {
1797 const bool success = dofs_idx.modify(
1798 miit_dofs_row, NumeredDofEntity_part_and_glob_idx_change(
1799 part, petsc_idx[(*miit_dofs_row)->dofIdx]));
1800 if (!success) {
1801 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
1802 "modification unsuccessful");
1803 }
1804 }
1805 }
1807 };
1808
1809 // Set petsc global indices
1810 auto &dofs_row_by_idx_no_const = const_cast<NumeredDofEntitysByIdx &>(
1811 p_miit->numeredRowDofsPtr->get<Idx_mi_tag>());
1812 int &nb_row_local_dofs = p_miit->nbLocDofsRow;
1813 int &nb_row_ghost_dofs = p_miit->nbGhostDofsRow;
1814 nb_row_local_dofs = 0;
1815 nb_row_ghost_dofs = 0;
1816
1817 CHKERR number_dofs(dofs_row_by_idx_no_const, nb_row_local_dofs);
1818
1819 int &nb_col_local_dofs = p_miit->nbLocDofsCol;
1820 int &nb_col_ghost_dofs = p_miit->nbGhostDofsCol;
1821 if (square_matrix) {
1822 nb_col_local_dofs = nb_row_local_dofs;
1823 nb_col_ghost_dofs = nb_row_ghost_dofs;
1824 } else {
1825 NumeredDofEntitysByIdx &dofs_col_by_idx_no_const =
1826 const_cast<NumeredDofEntitysByIdx &>(
1827 p_miit->numeredColDofsPtr->get<Idx_mi_tag>());
1828 nb_col_local_dofs = 0;
1829 nb_col_ghost_dofs = 0;
1830 CHKERR number_dofs(dofs_col_by_idx_no_const, nb_col_local_dofs);
1831 }
1832
1833 CHKERR ISRestoreIndices(is_gather, &part_number);
1834 CHKERR ISRestoreIndices(is_gather_num, &petsc_idx);
1835 CHKERR ISDestroy(&is_num);
1836 CHKERR ISDestroy(&is_gather_num);
1837 CHKERR ISDestroy(&is_gather);
1838 CHKERR ISDestroy(&is);
1839 CHKERR MatPartitioningDestroy(&part);
1840 CHKERR MatDestroy(&Adj);
1841 CHKERR printPartitionedProblem(&*p_miit, verb);
1842 } else {
1843
1844 auto number_dofs = [&](auto &dof_idx, auto &counter) {
1846 for (auto miit_dofs_row = dof_idx.begin(); miit_dofs_row != dof_idx.end();
1847 miit_dofs_row++) {
1848 const bool success = dof_idx.modify(
1849 miit_dofs_row,
1850 NumeredDofEntity_part_and_indices_change(0, counter, counter));
1851 ++counter;
1852 if (!success) {
1853 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
1854 "modification unsuccessful");
1855 }
1856 }
1858 };
1859
1860 auto &dofs_row_by_idx_no_const = const_cast<NumeredDofEntitysByIdx &>(
1861 p_miit->numeredRowDofsPtr->get<Idx_mi_tag>());
1862 int &nb_row_local_dofs = p_miit->nbLocDofsRow;
1863 int &nb_row_ghost_dofs = p_miit->nbGhostDofsRow;
1864 nb_row_local_dofs = 0;
1865 nb_row_ghost_dofs = 0;
1866
1867 CHKERR number_dofs(dofs_row_by_idx_no_const, nb_row_local_dofs);
1868
1869 bool square_matrix = false;
1870 if (p_miit->numeredRowDofsPtr == p_miit->numeredColDofsPtr)
1871 square_matrix = true;
1872
1873 int &nb_col_local_dofs = p_miit->nbLocDofsCol;
1874 int &nb_col_ghost_dofs = p_miit->nbGhostDofsCol;
1875 if (square_matrix) {
1876 nb_col_local_dofs = nb_row_local_dofs;
1877 nb_col_ghost_dofs = nb_row_ghost_dofs;
1878 } else {
1879 NumeredDofEntitysByIdx &dofs_col_by_idx_no_const =
1880 const_cast<NumeredDofEntitysByIdx &>(
1881 p_miit->numeredColDofsPtr->get<Idx_mi_tag>());
1882 nb_col_local_dofs = 0;
1883 nb_col_ghost_dofs = 0;
1884 CHKERR number_dofs(dofs_col_by_idx_no_const, nb_col_local_dofs);
1885 }
1886 }
1887
1888 cOre.getBuildMoFEM() |= 1 << 4;
1890}
@ VERY_VERBOSE
const double n
refractive index of diffusive medium
FTensor::Index< 'm', 3 > m

◆ partitionSimpleProblem()

MoFEMErrorCode MoFEM::ProblemsManager::partitionSimpleProblem ( const std::string  name,
int  verb = VERBOSE 
)

partition problem dofs

Parameters
nameproblem name
Examples
forces_and_sources_testing_edge_element.cpp, forces_and_sources_testing_flat_prism_element.cpp, hcurl_divergence_operator_2d.cpp, prism_elements_from_surface.cpp, prism_polynomial_approximation.cpp, and quad_polynomial_approximation.cpp.

Definition at line 1533 of file ProblemsManager.cpp.

1534 {
1535
1536 MoFEM::Interface &m_field = cOre;
1537 auto problems_ptr = m_field.get_problems();
1539
1541 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "fields not build");
1543 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "FEs not build");
1545 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "adjacencies not build");
1547 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "adjacencies not build");
1548 MOFEM_LOG("WORLD", Sev::verbose) << "Simple partition problem " << name;
1549
1550 // find p_miit
1551 typedef Problem_multiIndex::index<Problem_mi_tag>::type ProblemByName;
1552 ProblemByName &problems_set =
1553 const_cast<ProblemByName &>(problems_ptr->get<Problem_mi_tag>());
1554 ProblemByName::iterator p_miit = problems_set.find(name);
1555 if (p_miit == problems_set.end()) {
1556 SETERRQ(PETSC_COMM_SELF, 1,
1557 "problem < %s > is not found (top tip: check spelling)",
1558 name.c_str());
1559 }
1560 typedef boost::multi_index::index<NumeredDofEntity_multiIndex,
1561 Idx_mi_tag>::type NumeredDofEntitysByIdx;
1562 NumeredDofEntitysByIdx &dofs_row_by_idx =
1563 p_miit->numeredRowDofsPtr->get<Idx_mi_tag>();
1564 NumeredDofEntitysByIdx &dofs_col_by_idx =
1565 p_miit->numeredColDofsPtr->get<Idx_mi_tag>();
1566 boost::multi_index::index<NumeredDofEntity_multiIndex,
1567 Idx_mi_tag>::type::iterator miit_row,
1568 hi_miit_row;
1569 boost::multi_index::index<NumeredDofEntity_multiIndex,
1570 Idx_mi_tag>::type::iterator miit_col,
1571 hi_miit_col;
1572 DofIdx &nb_row_local_dofs = p_miit->nbLocDofsRow;
1573 DofIdx &nb_row_ghost_dofs = p_miit->nbGhostDofsRow;
1574 nb_row_local_dofs = 0;
1575 nb_row_ghost_dofs = 0;
1576 DofIdx &nb_col_local_dofs = p_miit->nbLocDofsCol;
1577 DofIdx &nb_col_ghost_dofs = p_miit->nbGhostDofsCol;
1578 nb_col_local_dofs = 0;
1579 nb_col_ghost_dofs = 0;
1580
1581 bool square_matrix = false;
1582 if (p_miit->numeredRowDofsPtr == p_miit->numeredColDofsPtr) {
1583 square_matrix = true;
1584 }
1585
1586 // get row range of local indices
1587 PetscLayout layout_row;
1588 const int *ranges_row;
1589
1590 DofIdx nb_dofs_row = dofs_row_by_idx.size();
1591 CHKERR PetscLayoutCreate(m_field.get_comm(), &layout_row);
1592 CHKERR PetscLayoutSetBlockSize(layout_row, 1);
1593 CHKERR PetscLayoutSetSize(layout_row, nb_dofs_row);
1594 CHKERR PetscLayoutSetUp(layout_row);
1595 CHKERR PetscLayoutGetRanges(layout_row, &ranges_row);
1596 // get col range of local indices
1597 PetscLayout layout_col;
1598 const int *ranges_col;
1599 if (!square_matrix) {
1600 DofIdx nb_dofs_col = dofs_col_by_idx.size();
1601 CHKERR PetscLayoutCreate(m_field.get_comm(), &layout_col);
1602 CHKERR PetscLayoutSetBlockSize(layout_col, 1);
1603 CHKERR PetscLayoutSetSize(layout_col, nb_dofs_col);
1604 CHKERR PetscLayoutSetUp(layout_col);
1605 CHKERR PetscLayoutGetRanges(layout_col, &ranges_col);
1606 }
1607 for (unsigned int part = 0; part < (unsigned int)m_field.get_comm_size();
1608 part++) {
1609 miit_row = dofs_row_by_idx.lower_bound(ranges_row[part]);
1610 hi_miit_row = dofs_row_by_idx.lower_bound(ranges_row[part + 1]);
1611 if (std::distance(miit_row, hi_miit_row) !=
1612 ranges_row[part + 1] - ranges_row[part]) {
1613 SETERRQ(
1614 PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1615 "data inconsistency, std::distance(miit_row,hi_miit_row) != rend - "
1616 "rstart (%ld != %d - %d = %d) ",
1617 std::distance(miit_row, hi_miit_row), ranges_row[part + 1],
1618 ranges_row[part], ranges_row[part + 1] - ranges_row[part]);
1619 }
1620 // loop rows
1621 for (; miit_row != hi_miit_row; miit_row++) {
1622 bool success = dofs_row_by_idx.modify(
1623 miit_row,
1624 NumeredDofEntity_part_and_glob_idx_change(part, (*miit_row)->dofIdx));
1625 if (!success)
1626 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
1627 "modification unsuccessful");
1628 if (part == (unsigned int)m_field.get_comm_rank()) {
1629 success = dofs_row_by_idx.modify(
1630 miit_row, NumeredDofEntity_local_idx_change(nb_row_local_dofs++));
1631 if (!success)
1632 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
1633 "modification unsuccessful");
1634 }
1635 }
1636 if (!square_matrix) {
1637 miit_col = dofs_col_by_idx.lower_bound(ranges_col[part]);
1638 hi_miit_col = dofs_col_by_idx.lower_bound(ranges_col[part + 1]);
1639 if (std::distance(miit_col, hi_miit_col) !=
1640 ranges_col[part + 1] - ranges_col[part]) {
1641 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1642 "data inconsistency, std::distance(miit_col,hi_miit_col) != "
1643 "rend - "
1644 "rstart (%ld != %d - %d = %d) ",
1645 std::distance(miit_col, hi_miit_col), ranges_col[part + 1],
1646 ranges_col[part], ranges_col[part + 1] - ranges_col[part]);
1647 }
1648 // loop cols
1649 for (; miit_col != hi_miit_col; miit_col++) {
1650 bool success = dofs_col_by_idx.modify(
1651 miit_col, NumeredDofEntity_part_and_glob_idx_change(
1652 part, (*miit_col)->dofIdx));
1653 if (!success)
1654 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
1655 "modification unsuccessful");
1656 if (part == (unsigned int)m_field.get_comm_rank()) {
1657 success = dofs_col_by_idx.modify(
1658 miit_col, NumeredDofEntity_local_idx_change(nb_col_local_dofs++));
1659 if (!success)
1660 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
1661 "modification unsuccessful");
1662 }
1663 }
1664 }
1665 }
1666 CHKERR PetscLayoutDestroy(&layout_row);
1667 if (!square_matrix) {
1668 CHKERR PetscLayoutDestroy(&layout_col);
1669 }
1670 if (square_matrix) {
1671 nb_col_local_dofs = nb_row_local_dofs;
1672 nb_col_ghost_dofs = nb_row_ghost_dofs;
1673 }
1674 CHKERR printPartitionedProblem(&*p_miit, verb);
1677}

◆ removeDofsOnEntities() [1/2]

MoFEMErrorCode MoFEM::ProblemsManager::removeDofsOnEntities ( const std::string  problem_name,
const std::string  field_name,
const BitRefLevel  bit_ref_level,
const BitRefLevel  bit_ref_mask,
Range ents_ptr = nullptr,
const int  lo_coeff = 0,
const int  hi_coeff = MAX_DOFS_ON_ENTITY,
const int  lo_order = 0,
const int  hi_order = 100,
int  verb = VERBOSE,
const bool  debug = false 
)

Remove DOFs from problem by bit ref level.

See for more detail other implementation for removeDofsOnEntities.

Parameters
problem_namename of the problem
field_namename of the field
bit_ref_levelbit ref level on which DOFs are removed
bit_ref_maskbit ref mask on which DOFs are removed
ents_ptrfilter entities with given bit and mask
lo_coefflow dof coefficient (rank)
hi_coeffhigh dof coefficient (rank)
verbverbosity level
debugto debug and seek for inconsistencies set to true
Returns
MoFEMErrorCode

Definition at line 3499 of file ProblemsManager.cpp.

3503 {
3504 MoFEM::Interface &m_field = cOre;
3506
3507 auto bit_manager = m_field.getInterface<BitRefManager>();
3508
3509 Range ents;
3510 if (ents_ptr) {
3511 ents = *ents_ptr;
3512 CHKERR bit_manager->filterEntitiesByRefLevel(bit_ref_level, bit_ref_mask,
3513 ents, verb);
3514 } else {
3515 CHKERR bit_manager->getEntitiesByRefLevel(bit_ref_level, bit_ref_mask, ents,
3516 verb);
3517 }
3518
3519 CHKERR removeDofsOnEntities(problem_name, field_name, ents, lo_coeff,
3520 hi_coeff, lo_order, hi_order, verb, debug);
3521
3523}
MoFEMErrorCode removeDofsOnEntities(const std::string problem_name, const std::string field_name, const Range ents, const int lo_coeff=0, const int hi_coeff=MAX_DOFS_ON_ENTITY, const int lo_order=0, const int hi_order=100, int verb=VERBOSE, const bool debug=false)
Remove DOFs from problem.
constexpr auto field_name

◆ removeDofsOnEntities() [2/2]

MoFEMErrorCode MoFEM::ProblemsManager::removeDofsOnEntities ( const std::string  problem_name,
const std::string  field_name,
const Range  ents,
const int  lo_coeff = 0,
const int  hi_coeff = MAX_DOFS_ON_ENTITY,
const int  lo_order = 0,
const int  hi_order = 100,
int  verb = VERBOSE,
const bool  debug = false 
)

Remove DOFs from problem.

Remove DOFs from problem which are on entities on the given range and given field name. On the finite element level, DOFs can be still accessed however local PETSc indices and global PETSc indices are marked with the index -1.

Note
If the index is marked -1 it is not assembled and dropped by VecSetValues and MatSetValues.
Todo:
Not yet implemented update for AO maps and IS ranges if removed entities in composite problem or sub-problem
Parameters
problem_namename of the problem
field_namename of the field
entsentities on which DOFs are removed
lo_coefflow dof coefficient (rank)
hi_coeffhigh dof coefficient (rank)
verbverbosity level
debugto debug and seek for inconsistencies set to true
Returns
MoFEMErrorCode
Examples
hanging_node_approx.cpp, helmholtz.cpp, and remove_entities_from_problem.cpp.

Definition at line 2959 of file ProblemsManager.cpp.

2962 {
2963
2964 MoFEM::Interface &m_field = cOre;
2966
2967 const Problem *prb_ptr;
2968 CHKERR m_field.get_problem(problem_name, &prb_ptr);
2969
2970 decltype(prb_ptr->numeredRowDofsPtr) numered_dofs[2] = {
2971 prb_ptr->numeredRowDofsPtr, nullptr};
2972 if (prb_ptr->numeredRowDofsPtr != prb_ptr->numeredColDofsPtr)
2973 numered_dofs[1] = prb_ptr->numeredColDofsPtr;
2974
2975 int *nbdof_ptr[] = {&prb_ptr->nbDofsRow, &prb_ptr->nbDofsCol};
2976 int *local_nbdof_ptr[] = {&prb_ptr->nbLocDofsRow, &prb_ptr->nbLocDofsCol};
2977 int *ghost_nbdof_ptr[] = {&prb_ptr->nbGhostDofsRow, &prb_ptr->nbGhostDofsCol};
2978
2979 const int nb_init_row_dofs = prb_ptr->getNbDofsRow();
2980 const int nb_init_col_dofs = prb_ptr->getNbDofsCol();
2981 const int nb_init_loc_row_dofs = prb_ptr->getNbLocalDofsRow();
2982 // const int nb_init_loc_col_dofs = prb_ptr->getNbLocalDofsCol();
2983 const int nb_init_ghost_row_dofs = prb_ptr->getNbGhostDofsRow();
2984 const int nb_init_ghost_col_dofs = prb_ptr->getNbGhostDofsCol();
2985
2986 for (int s = 0; s != 2; ++s)
2987 if (numered_dofs[s]) {
2988
2989 using NumeredDofEntity_it_view_multiIndex = multi_index_container<
2990
2991 NumeredDofEntity_multiIndex::iterator, indexed_by<sequenced<>>
2992
2993 >;
2994
2995 const auto bit_number = m_field.get_field_bit_number(field_name);
2996 NumeredDofEntity_it_view_multiIndex dofs_it_view;
2997
2998 // Set -1 to global and local dofs indices
2999 for (auto pit = ents.const_pair_begin(); pit != ents.const_pair_end();
3000 ++pit) {
3001 auto lo = numered_dofs[s]->get<Unique_mi_tag>().lower_bound(
3002 DofEntity::getLoFieldEntityUId(bit_number, pit->first));
3003 auto hi = numered_dofs[s]->get<Unique_mi_tag>().upper_bound(
3004 DofEntity::getHiFieldEntityUId(bit_number, pit->second));
3005
3006 for (; lo != hi; ++lo)
3007 if ((*lo)->getDofCoeffIdx() >= lo_coeff &&
3008 (*lo)->getDofCoeffIdx() <= hi_coeff &&
3009 (*lo)->getDofOrder() >= lo_order &&
3010 (*lo)->getDofOrder() <= hi_order)
3011 dofs_it_view.emplace_back(numered_dofs[s]->project<0>(lo));
3012 }
3013
3014 if (verb > QUIET) {
3015 for (auto &dof : dofs_it_view)
3016 MOFEM_LOG("SYNC", Sev::noisy) << **dof;
3017 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::noisy);
3018 }
3019
3020 // create weak view
3021 std::vector<boost::weak_ptr<NumeredDofEntity>> dofs_weak_view;
3022 dofs_weak_view.reserve(dofs_it_view.size());
3023 for (auto dit : dofs_it_view)
3024 dofs_weak_view.push_back(*dit);
3025
3026 if (verb >= NOISY)
3027 MOFEM_LOG_C("SYNC", Sev::noisy,
3028 "Number of DOFs in multi-index %d and to delete %d\n",
3029 numered_dofs[s]->size(), dofs_it_view.size());
3030
3031 // erase dofs from problem
3032 for (auto weak_dit : dofs_weak_view)
3033 if (auto dit = weak_dit.lock()) {
3034 numered_dofs[s]->erase(dit->getLocalUniqueId());
3035 }
3036
3037 if (verb >= NOISY)
3038 MOFEM_LOG_C("SYNC", Sev::noisy,
3039 "Number of DOFs in multi-index after delete %d\n",
3040 numered_dofs[s]->size());
3041
3042 // get current number of ghost dofs
3043 int nb_local_dofs = 0;
3044 int nb_ghost_dofs = 0;
3045 for (auto dit = numered_dofs[s]->get<PetscLocalIdx_mi_tag>().begin();
3046 dit != numered_dofs[s]->get<PetscLocalIdx_mi_tag>().end(); ++dit) {
3047 if ((*dit)->getPetscLocalDofIdx() >= 0 &&
3048 (*dit)->getPetscLocalDofIdx() < *(local_nbdof_ptr[s]))
3049 ++nb_local_dofs;
3050 else if ((*dit)->getPetscLocalDofIdx() >= *(local_nbdof_ptr[s]))
3051 ++nb_ghost_dofs;
3052 else
3053 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3054 "Impossible case. You could run problem on no distributed "
3055 "mesh. That is not implemented. Dof local index is %d",
3056 (*dit)->getPetscLocalDofIdx());
3057 }
3058
3059 // get indices
3060 auto get_indices_by_tag = [&](auto tag, auto &indices, bool only_local) {
3061 const int nb_dofs = numered_dofs[s]->size();
3062 indices.clear();
3063 indices.reserve(nb_dofs);
3064 for (auto dit = numered_dofs[s]->get<decltype(tag)>().begin();
3065 dit != numered_dofs[s]->get<decltype(tag)>().end(); ++dit) {
3066 bool add = true;
3067 if (only_local) {
3068 if ((*dit)->getPetscLocalDofIdx() < 0 ||
3069 (*dit)->getPetscLocalDofIdx() >= *(local_nbdof_ptr[s])) {
3070 add = false;
3071 }
3072 }
3073 if (add)
3074 indices.push_back(decltype(tag)::get_index(dit));
3075 }
3076 };
3077
3078 auto get_indices_by_uid = [&](auto tag, auto &indices) {
3079 const int nb_dofs = numered_dofs[s]->size();
3080 indices.clear();
3081 indices.reserve(nb_dofs);
3082 for (auto dit = numered_dofs[s]->begin(); dit != numered_dofs[s]->end();
3083 ++dit)
3084 indices.push_back(decltype(tag)::get_index(dit));
3085 };
3086
3087 auto get_sub_ao = [&](auto sub_data) {
3088 if (s == 0) {
3089 return sub_data->getSmartRowMap();
3090 } else {
3091 return sub_data->getSmartColMap();
3092 }
3093 };
3094
3095 auto set_sub_is_and_ao = [&s, &prb_ptr](auto sub_data, auto is, auto ao) {
3096 if (s == 0) {
3097 sub_data->rowIs = is;
3098 sub_data->rowMap = ao;
3099 sub_data->colIs = is; // if square problem col is equal to row
3100 sub_data->colMap = ao;
3101 } else {
3102 sub_data->colIs = is;
3103 sub_data->colMap = ao;
3104 }
3105 };
3106
3107 auto apply_symmetry = [&s, &prb_ptr](auto sub_data) {
3108 if (s == 0) {
3109 if (prb_ptr->numeredRowDofsPtr == prb_ptr->numeredColDofsPtr) {
3110 sub_data->colIs = sub_data->getSmartRowIs();
3111 sub_data->colMap = sub_data->getSmartRowMap();
3112 }
3113 }
3114 };
3115
3116 auto concatenate_dofs = [&](auto tag, auto &indices,
3117 const auto local_only) {
3119 get_indices_by_tag(tag, indices, local_only);
3120
3121 SmartPetscObj<AO> ao;
3122 // Create AO from app indices (i.e. old), to pestc indices (new after
3123 // remove)
3124 if (local_only)
3125 ao = createAOMapping(m_field.get_comm(), indices.size(),
3126 &*indices.begin(), PETSC_NULLPTR);
3127 else
3128 ao = createAOMapping(PETSC_COMM_SELF, indices.size(),
3129 &*indices.begin(), PETSC_NULLPTR);
3130
3131 // Set mapping to sub dm data
3132 if (local_only) {
3133 if (auto sub_data = prb_ptr->getSubData()) {
3134 // create is and then map it to main problem of sub-problem
3135 auto sub_is = createISGeneral(m_field.get_comm(), indices.size(),
3136 &*indices.begin(), PETSC_COPY_VALUES);
3137 // get old app, i.e. oroginal befor sub indices, and ao, from app,
3138 // to petsc sub indices.
3139 auto sub_ao = get_sub_ao(sub_data);
3140 CHKERR AOPetscToApplicationIS(sub_ao, sub_is);
3141 sub_ao = createAOMappingIS(sub_is, PETSC_NULLPTR);
3142 // set new sub ao
3143 set_sub_is_and_ao(sub_data, sub_is, sub_ao);
3144 apply_symmetry(sub_data);
3145 } else {
3146 // create sub data
3147 prb_ptr->getSubData() =
3148 boost::make_shared<Problem::SubProblemData>();
3149 auto sub_is = createISGeneral(m_field.get_comm(), indices.size(),
3150 &*indices.begin(), PETSC_COPY_VALUES);
3151 // set sub is ao
3152 set_sub_is_and_ao(prb_ptr->getSubData(), sub_is, ao);
3153 apply_symmetry(prb_ptr->getSubData());
3154 }
3155 }
3156
3157 get_indices_by_uid(tag, indices);
3158 CHKERR AOApplicationToPetsc(ao, indices.size(), &*indices.begin());
3159
3161 };
3162
3163 // set indices index
3164 auto set_concatenated_indices = [&]() {
3165 std::vector<int> global_indices;
3166 std::vector<int> local_indices;
3168 CHKERR concatenate_dofs(PetscGlobalIdx_mi_tag(), global_indices, true);
3169 CHKERR concatenate_dofs(PetscLocalIdx_mi_tag(), local_indices, false);
3170 auto gi = global_indices.begin();
3171 auto li = local_indices.begin();
3172 for (auto dit = numered_dofs[s]->begin(); dit != numered_dofs[s]->end();
3173 ++dit) {
3174 auto mod = NumeredDofEntity_part_and_all_indices_change(
3175 (*dit)->getPart(), (*dit)->getDofIdx(), *gi, *li);
3176 bool success = numered_dofs[s]->modify(dit, mod);
3177 if (!success)
3178 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
3179 "can not set negative indices");
3180 ++gi;
3181 ++li;
3182 }
3184 };
3185 CHKERR set_concatenated_indices();
3186
3187 MPI_Allreduce(&nb_local_dofs, nbdof_ptr[s], 1, MPI_INT, MPI_SUM,
3188 m_field.get_comm());
3189 *(local_nbdof_ptr[s]) = nb_local_dofs;
3190 *(ghost_nbdof_ptr[s]) = nb_ghost_dofs;
3191
3192 if (debug)
3193 for (auto dof : (*numered_dofs[s])) {
3194 if (dof->getPetscGlobalDofIdx() < 0) {
3195 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
3196 "Negative global idx");
3197 }
3198 if (dof->getPetscLocalDofIdx() < 0) {
3199 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
3200 "Negative local idx");
3201 }
3202 }
3203
3204 } else {
3205
3206 *(nbdof_ptr[1]) = *(nbdof_ptr[0]);
3207 *(local_nbdof_ptr[1]) = *(local_nbdof_ptr[0]);
3208 *(ghost_nbdof_ptr[1]) = *(ghost_nbdof_ptr[0]);
3209 }
3210
3211 if (verb > QUIET) {
3213 "WORLD", Sev::inform,
3214 "Removed DOFs from problem %s dofs [%d / %d (before %d / %d) global]",
3215 prb_ptr->getName().c_str(), prb_ptr->getNbDofsRow(),
3216 prb_ptr->getNbDofsCol(), nb_init_row_dofs, nb_init_col_dofs);
3217 MOFEM_LOG_C("SYNC", Sev::verbose,
3218 "Removed DOFs from problem %s dofs [ %d / %d "
3219 "(before %d / %d) local, %d / %d (before %d / %d)]",
3220 prb_ptr->getName().c_str(), prb_ptr->getNbLocalDofsRow(),
3221 prb_ptr->getNbLocalDofsCol(), nb_init_loc_row_dofs,
3222 nb_init_loc_row_dofs, prb_ptr->getNbGhostDofsRow(),
3223 prb_ptr->getNbGhostDofsCol(), nb_init_ghost_row_dofs,
3224 nb_init_ghost_col_dofs);
3225 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::verbose);
3226 }
3227
3229}
#define MOFEM_LOG_C(channel, severity, format,...)
auto createISGeneral(MPI_Comm comm, PetscInt n, const PetscInt idx[], PetscCopyMode mode)
Creates a data structure for an index set containing a list of integers.
auto createAOMapping(MPI_Comm comm, PetscInt napp, const PetscInt myapp[], const PetscInt mypetsc[])
Creates an application mapping using two integer arrays.
auto createAOMappingIS(IS isapp, IS ispetsc)
Creates an application mapping using two index sets.
boost::shared_ptr< NumeredDofEntity_multiIndex > numeredRowDofsPtr
store DOFs on rows for this problem