v0.14.0
Public Member Functions | Public Attributes | Static Public Attributes | List of all members
MoFEM::CommInterface Struct Reference

Managing BitRefLevels. More...

#include <src/interfaces/CommInterface.hpp>

Inheritance diagram for MoFEM::CommInterface:
[legend]
Collaboration diagram for MoFEM::CommInterface:
[legend]

Public Member Functions

MoFEMErrorCode query_interface (boost::typeindex::type_index type_index, UnknownInterface **iface) const
 
 CommInterface (const MoFEM::Core &core)
 
 ~CommInterface ()=default
 Destructor. More...
 
- Public Member Functions inherited from MoFEM::UnknownInterface
template<class IFACE >
MoFEMErrorCode registerInterface (bool error_if_registration_failed=true)
 Register interface. More...
 
template<class IFACE >
MoFEMErrorCode getInterface (IFACE *&iface) const
 Get interface reference to pointer of interface. More...
 
template<class IFACE >
MoFEMErrorCode getInterface (IFACE **const iface) const
 Get interface pointer to pointer of interface. More...
 
template<class IFACE , typename boost::enable_if< boost::is_pointer< IFACE >, int >::type = 0>
IFACE getInterface () const
 Get interface pointer to pointer of interface. More...
 
template<class IFACE , typename boost::enable_if< boost::is_reference< IFACE >, int >::type = 0>
IFACE getInterface () const
 Get reference to interface. More...
 
template<class IFACE >
IFACE * getInterface () const
 Function returning pointer to interface. More...
 
virtual ~UnknownInterface ()=default
 

Public Attributes

MoFEM::CorecOre
 
bool dEbug
 

Static Public Attributes

static bool debug = false
 
static Sev sev = Sev::verbose
 

Make elemets multishared

MoFEMErrorCode resolveSharedFiniteElements (const Problem *problem_ptr, const std::string &fe_name, int verb=DEFAULT_VERBOSITY)
 resolve shared entities for finite elements in the problem More...
 
MoFEMErrorCode resolveSharedFiniteElements (const std::string name, const std::string &fe_name, int verb=DEFAULT_VERBOSITY)
 resolve shared entities for finite elements in the problem More...
 

Make entities multishared

MoFEMErrorCode makeEntitiesMultishared (const EntityHandle *entities, const int num_entities, const int owner_proc=0, int verb=DEFAULT_VERBOSITY)
 make entities from proc 0 shared on all proc More...
 
MoFEMErrorCode makeEntitiesMultishared (Range &entities, const int owner_proc=0, int verb=DEFAULT_VERBOSITY)
 make entities from proc 0 shared on all proc More...
 
MoFEMErrorCode makeFieldEntitiesMultishared (const std::string field_name, const int owner_proc=0, int verb=DEFAULT_VERBOSITY)
 make field entities multi shared More...
 
MoFEMErrorCode exchangeFieldData (const std::string field_name, int verb=DEFAULT_VERBOSITY)
 Exchange field data. More...
 

Synchronize entities (Following functions in future will be

deprecated)

MoFEMErrorCode synchroniseEntities (Range &ent, std::map< int, Range > *received_ents, int verb=DEFAULT_VERBOSITY)
 synchronize entity range on processors (collective) More...
 
MoFEMErrorCode synchroniseEntities (Range &ent, int verb=DEFAULT_VERBOSITY)
 synchronize entity range on processors (collective) More...
 
MoFEMErrorCode synchroniseFieldEntities (const std::string name, int verb=DEFAULT_VERBOSITY)
 
MoFEMErrorCode resolveParentEntities (const Range &ent, int verb=DEFAULT_VERBOSITY)
 Synchronise parent entities. More...
 

Read load and boradcoast

@

MoFEMErrorCode 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. More...
 

Load file

using LoadFileFun = std::function< std::array< Range, 4 >(std::array< Range, 4 > &&, std::vector< const CubitMeshSets * > &&)>
 
static std::array< Range, 4 > defaultProcSkinFun (std::array< Range, 4 > &&proc_ents_skin, std::vector< const CubitMeshSets * > &&vec_ptr)
 
static MoFEMErrorCode loadFileRootProcAllRestDistributed (moab::Interface &moab, const char *file_name, int dim, LoadFileFun proc_skin_fun=defaultProcSkinFun, const char *options="PARALLEL=BCAST;PARTITION=")
 Root proc has whole mesh, other procs only part of it. More...
 
static Range getPartEntities (moab::Interface &moab, int part)
 

Functions when rooot proc have all entities

@

using EntitiesPetscVector = std::pair< std::pair< Range, Range >, SmartPetscObj< Vec > >
 
using UpdateGhosts = std::function< MoFEMErrorCode(Vec vec)>
 
static EntitiesPetscVector createEntitiesPetscVector (MPI_Comm comm, moab::Interface &moab, int dim, const int nb_coeffs, Sev sev=Sev::verbose, int root_rank=0)
 Create a ghost vector for exchanging data. More...
 
static MoFEMErrorCode defaultUpdateGhosts (Vec v)
 
static MoFEMErrorCode updateEntitiesPetscVector (moab::Interface &moab, EntitiesPetscVector &vec, Tag tag, UpdateGhosts update_gosts=defaultUpdateGhosts)
 Exchange data between vector and data. More...
 

Additional Inherited Members

- Static Public Member Functions inherited from MoFEM::UnknownInterface
static MoFEMErrorCode getLibVersion (Version &version)
 Get library version. More...
 
static MoFEMErrorCode getFileVersion (moab::Interface &moab, Version &version)
 Get database major version. More...
 
static MoFEMErrorCode setFileVersion (moab::Interface &moab, Version version=Version(MoFEM_VERSION_MAJOR, MoFEM_VERSION_MINOR, MoFEM_VERSION_BUILD))
 Get database major version. More...
 
static MoFEMErrorCode getInterfaceVersion (Version &version)
 Get database major version. More...
 

Detailed Description

Managing BitRefLevels.

Examples
adolc_plasticity.cpp, dm_partitioned_no_field.cpp, elasticity.cpp, EshelbianPlasticity.cpp, free_surface.cpp, level_set.cpp, mesh_smoothing.cpp, mixed_poisson.cpp, navier_stokes.cpp, partition_mesh.cpp, plastic.cpp, seepage.cpp, and thermo_elastic.cpp.

Definition at line 21 of file CommInterface.hpp.

Member Typedef Documentation

◆ EntitiesPetscVector

using MoFEM::CommInterface::EntitiesPetscVector = std::pair<std::pair<Range, Range>, SmartPetscObj<Vec> >

Definition at line 293 of file CommInterface.hpp.

◆ LoadFileFun

using MoFEM::CommInterface::LoadFileFun = std::function<std::array<Range, 4>( std::array<Range, 4> &&, std::vector<const CubitMeshSets *> &&)>

Definition at line 262 of file CommInterface.hpp.

◆ UpdateGhosts

using MoFEM::CommInterface::UpdateGhosts = std::function<MoFEMErrorCode(Vec vec)>

Definition at line 315 of file CommInterface.hpp.

Constructor & Destructor Documentation

◆ CommInterface()

MoFEM::CommInterface::CommInterface ( const MoFEM::Core core)

Definition at line 23 of file CommInterface.cpp.

24  : cOre(const_cast<MoFEM::Core &>(core)), dEbug(false) {}

◆ ~CommInterface()

MoFEM::CommInterface::~CommInterface ( )
default

Destructor.

Member Function Documentation

◆ createEntitiesPetscVector()

CommInterface::EntitiesPetscVector MoFEM::CommInterface::createEntitiesPetscVector ( MPI_Comm  comm,
moab::Interface &  moab,
int  dim,
const int  nb_coeffs,
Sev  sev = Sev::verbose,
int  root_rank = 0 
)
static

Create a ghost vector for exchanging data.

Note
Only works if loadFileRootProcAllRestDistributed function is used.
Parameters
comm
moab
dimdimension of partition entities
adj_dimdimension of adjacent entities
nb_coeffsnumber of coefficients
sev
root_rank
Returns
std::pair<Range, SmartPetscObj<Vec>>

Definition at line 1467 of file CommInterface.cpp.

1469  {
1470 
1471  SmartPetscObj<Vec> vec;
1472  Range r, ghost_ents;
1473 
1474  auto fun = [&]() {
1476  auto pcomm = ParallelComm::get_pcomm(&moab, MYPCOMM_INDEX);
1477 
1478  Tag part_tag = pcomm->part_tag();
1479  Range tagged_sets, proc_ents, off_proc_ents;
1480  CHKERR moab.get_entities_by_type_and_tag(0, MBENTITYSET, &part_tag, NULL, 1,
1481  tagged_sets,
1482  moab::Interface::UNION);
1483 
1484  if (dim > 0) {
1485  for (auto &mit : tagged_sets) {
1486  int part;
1487  CHKERR moab.tag_get_data(part_tag, &mit, 1, &part);
1488  if (part == pcomm->rank()) {
1489  CHKERR moab.get_entities_by_handle(mit, proc_ents, true);
1490  } else {
1491  CHKERR moab.get_entities_by_handle(mit, off_proc_ents, true);
1492  }
1493  }
1494  } else {
1495  std::map<int, Range> parts_ents;
1496  for (auto &mit : tagged_sets) {
1497  int part;
1498  CHKERR moab.tag_get_data(part_tag, &mit, 1, &part);
1499  CHKERR moab.get_entities_by_handle(mit, parts_ents[part], true);
1500  }
1501  Range v;
1502  CHKERR moab.get_connectivity(parts_ents[pcomm->rank()], v);
1503  int p = 0;
1504  for (; p != pcomm->rank(); ++p) {
1505  Range vv;
1506  CHKERR moab.get_connectivity(parts_ents[p], vv);
1507  v = subtract(v, vv);
1508  off_proc_ents.merge(vv);
1509  }
1510  for (; p != pcomm->size(); ++p) {
1511  Range vv;
1512  CHKERR moab.get_connectivity(parts_ents[p], vv);
1513  vv = subtract(vv, v);
1514  off_proc_ents.merge(vv);
1515  }
1516  proc_ents = v;
1517  }
1518 
1519  r = proc_ents.subset_by_dimension(dim);
1520  auto o = off_proc_ents.subset_by_dimension(dim);
1521 
1522  auto set_ghosts = [&](Range &ents) {
1523  auto gid_tag = moab.globalId_tag();
1524  std::vector<int> ghosts(ents.size());
1525  CHKERR moab.tag_get_data(gid_tag, ents, ghosts.data());
1526  std::vector<int> ghosts_nb(nb_coeffs * ents.size());
1527  for (int i = 0; i < ents.size(); ++i)
1528  for (int j = 0; j < nb_coeffs; ++j)
1529  ghosts_nb[i * nb_coeffs + j] = nb_coeffs * (ghosts[i] - 1) + j;
1530  return ghosts_nb;
1531  };
1532 
1533  std::vector<int> ghosts;
1534  if (pcomm->rank() == root_rank) {
1535  ghosts = set_ghosts(o);
1536  ghost_ents = o;
1537  } else {
1538  Range ents;
1539  CHKERR moab.get_entities_by_dimension(0, dim, ents);
1540  ents = subtract(ents, r);
1541  ghosts = set_ghosts(ents);
1542  ghost_ents = ents;
1543  }
1544 
1545  auto create_vec = [&]() {
1547  vec = createGhostVector(comm, nb_coeffs * r.size(), PETSC_DETERMINE,
1548  ghosts.size(), ghosts.data());
1550  };
1551  CHKERR create_vec();
1552 
1554  };
1555 
1556  CHKERR fun();
1557 
1558  auto out = std::make_pair(std::make_pair(r, ghost_ents), vec);
1559 
1560 #ifndef NDEBUG
1561  {
1562 
1563  auto check = [&](auto &ents, auto &id, auto &idx) {
1565  bool error = false;
1566  for (int i = 0; i < ents.size(); ++i) {
1567  for (int j = 0; j < nb_coeffs; ++j) {
1568  if (idx[i * nb_coeffs + j] != nb_coeffs * (id[i] - 1) + j) {
1569  error = true;
1570  MOFEM_LOG("SYNC", Sev::error)
1571  << "indexes not equal: " << idx[i * nb_coeffs + j]
1572  << " != " << nb_coeffs * (idx[i] - 1) + j;
1573  }
1574  }
1575  }
1576  MOFEM_LOG_SEVERITY_SYNC(PETSC_COMM_WORLD, Sev::error);
1577  if (error)
1578  CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "indexes do not match");
1580  };
1581 
1582  Tag tag;
1583  CHKERR moab.tag_get_handle("TestGather", nb_coeffs, MB_TYPE_DOUBLE, tag,
1584  MB_TAG_SPARSE | MB_TAG_CREAT);
1585  auto gid_tag = moab.globalId_tag();
1586  std::vector<int> id(r.size());
1587  CHKERR moab.tag_get_data(gid_tag, r, id.data());
1588  std::vector<double> idx(nb_coeffs * r.size());
1589  for (int i = 0; i < r.size(); ++i) {
1590  for (int j = 0; j < nb_coeffs; ++j) {
1591  idx[i * nb_coeffs + j] = nb_coeffs * (id[i] - 1) + j;
1592  }
1593  }
1594  CHKERR moab.tag_set_data(tag, r, idx.data());
1595  CHKERR updateEntitiesPetscVector(moab, out, tag);
1596  idx.resize(nb_coeffs * r.size());
1597  CHKERR moab.tag_get_data(tag, r, idx.data());
1598  CHK_THROW_MESSAGE(check(r, id, idx), "indexes do not match")
1599  id.resize(ghost_ents.size());
1600  CHKERR moab.tag_get_data(gid_tag, ghost_ents, id.data());
1601  idx.resize(nb_coeffs * ghost_ents.size());
1602  CHKERR moab.tag_get_data(tag, ghost_ents, idx.data());
1603  CHK_THROW_MESSAGE(check(ghost_ents, id, idx), "ghost indexes do not match")
1604  CHKERR moab.tag_delete(tag);
1605  }
1606 #endif // NDEBUG
1607 
1608  return out;
1609 }

◆ defaultProcSkinFun()

static std::array<Range, 4> MoFEM::CommInterface::defaultProcSkinFun ( std::array< Range, 4 > &&  proc_ents_skin,
std::vector< const CubitMeshSets * > &&  vec_ptr 
)
inlinestatic

Definition at line 265 of file CommInterface.hpp.

266  {
267  return proc_ents_skin;
268  }

◆ defaultUpdateGhosts()

static MoFEMErrorCode MoFEM::CommInterface::defaultUpdateGhosts ( Vec  v)
inlinestatic

Definition at line 317 of file CommInterface.hpp.

317  {
319  CHKERR VecAssemblyBegin(v);
320  CHKERR VecAssemblyEnd(v);
321  CHKERR VecGhostUpdateBegin(v, ADD_VALUES, SCATTER_REVERSE);
322  CHKERR VecGhostUpdateEnd(v, ADD_VALUES, SCATTER_REVERSE);
323  CHKERR VecGhostUpdateBegin(v, INSERT_VALUES, SCATTER_FORWARD);
324  CHKERR VecGhostUpdateEnd(v, INSERT_VALUES, SCATTER_FORWARD);
326  };

◆ exchangeFieldData()

MoFEMErrorCode MoFEM::CommInterface::exchangeFieldData ( const std::string  field_name,
int  verb = DEFAULT_VERBOSITY 
)

Exchange field data.

Exchange field for all shared and ghosted entities. This function should be called collectively over the communicator for this ParallelComm. If the entities vector is empty, all shared entities participate in the exchange. If a proc has no owned entities this function must still be called since it is collective.

Note
collective - need tu be run on all processors in communicator
Todo:
It is not working if field has entities diffrent than vertices.
Parameters
verb
field_name
Returns
MoFEMErrorCode

Definition at line 825 of file CommInterface.cpp.

826  {
827  MoFEM::Interface &m_field = cOre;
829  if (m_field.get_comm_size() > 1) {
830 
831  Range exchange_ents_data_verts, exchange_ents_data;
832 
833  auto *field_ents = m_field.get_field_ents();
834  auto field_bit_number = m_field.get_field_bit_number(field_name);
835  auto lo = field_ents->get<Unique_mi_tag>().lower_bound(
836  FieldEntity::getLoBitNumberUId(field_bit_number));
837  auto hi = field_ents->get<Unique_mi_tag>().lower_bound(
838  FieldEntity::getHiBitNumberUId(field_bit_number));
839 
840  for (auto it = lo; it != hi; ++it)
841  if (
842 
843  ((*it)->getPStatus()) &&
844 
845  (*it)->getNbDofsOnEnt()
846 
847  ) {
848  if ((*it)->getEntType() == MBVERTEX)
849  exchange_ents_data_verts.insert((*it)->getEnt());
850  else
851  exchange_ents_data.insert((*it)->getEnt());
852  }
853 
854  auto field_ptr = m_field.get_field_structure(field_name);
855  ParallelComm *pcomm = ParallelComm::get_pcomm(
856  &m_field.get_moab(), m_field.get_basic_entity_data_ptr()->pcommID);
857 
858  auto exchange = [&](const Range &ents, Tag th) {
860  if (!ents.empty()) {
861  std::vector<Tag> tags;
862  tags.push_back(th);
863  CHKERR pcomm->exchange_tags(tags, tags, ents);
864  }
866  };
867 
868  CHKERR exchange(exchange_ents_data_verts, field_ptr->th_FieldDataVerts);
869  CHKERR exchange(exchange_ents_data, field_ptr->th_FieldData);
870  }
872 }

◆ getPartEntities()

Range MoFEM::CommInterface::getPartEntities ( moab::Interface &  moab,
int  part 
)
static
Examples
ep.cpp.

Definition at line 1425 of file CommInterface.cpp.

1425  {
1426 
1427  ParallelComm *pcomm = ParallelComm::get_pcomm(&moab, MYPCOMM_INDEX);
1428  if (pcomm == NULL)
1429  pcomm = new ParallelComm(&moab, PETSC_COMM_WORLD);
1430  if (pcomm->size() == 1) {
1431  Range ents;
1432  CHK_MOAB_THROW(moab.get_entities_by_handle(0, ents, false),
1433  "get_entities_by_handle failed");
1434  return subtract(ents, ents.subset_by_type(MBENTITYSET));
1435  }
1436 
1437  Range proc_ents;
1438 
1439  auto get_proc_ents = [&]() {
1441 
1442  Tag part_tag = pcomm->part_tag();
1443 
1444  Range tagged_sets;
1445  CHKERR moab.get_entities_by_type_and_tag(0, MBENTITYSET, &part_tag, NULL, 1,
1446  tagged_sets,
1447  moab::Interface::UNION);
1448  for (auto &mit : tagged_sets) {
1449  int part_set;
1450  CHKERR moab.tag_get_data(part_tag, &mit, 1, &part_set);
1451  if (part_set == part) {
1452  CHKERR moab.get_entities_by_handle(mit, proc_ents, true);
1454  }
1455  }
1456  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1457  "Part not found in partitioned mesh");
1459  };
1460 
1461  CHK_THROW_MESSAGE(get_proc_ents(), "get_proc_ents failed");
1462 
1463  return proc_ents;
1464 }

◆ loadFileRootProcAllRestDistributed()

MoFEMErrorCode MoFEM::CommInterface::loadFileRootProcAllRestDistributed ( moab::Interface &  moab,
const char *  file_name,
int  dim,
LoadFileFun  proc_skin_fun = defaultProcSkinFun,
const char *  options = "PARALLEL=BCAST;PARTITION=" 
)
static

Root proc has whole mesh, other procs only part of it.

Parameters
moab
file_name
dim
proc_skin_fun
options
Returns
MoFEMErrorCode

< cubit meshsets

Examples
ep.cpp.

Definition at line 1221 of file CommInterface.cpp.

1223  {
1225 
1226  CHKERR moab.load_file(file_name, 0, options);
1227  ParallelComm *pcomm = ParallelComm::get_pcomm(&moab, MYPCOMM_INDEX);
1228  if (pcomm == NULL)
1229  pcomm = new ParallelComm(&moab, PETSC_COMM_WORLD);
1230  if (pcomm->size() == 1)
1232 
1233  Skinner skin(&moab);
1234  MOFEM_LOG_CHANNEL("WORLD");
1235  MOFEM_LOG_CHANNEL("SYNC");
1236 
1237  auto print_range_on_procs = [&](const Range &range, std::string name) {
1238  MOFEM_LOG("SYNC", sev) << name << " on proc [" << pcomm->rank()
1239  << "] : " << range.size();
1240  MOFEM_LOG_SEVERITY_SYNC(PETSC_COMM_WORLD, sev);
1241  };
1242 
1243  auto save_range_to_file = [&](const Range range, std::string name = "part") {
1244  if (!debug)
1245  return;
1246  int rr = pcomm->rank();
1247  ostringstream ss;
1248  ss << "out_" << name << "_" << rr << ".vtk";
1249  MOFEM_LOG("SYNC", sev) << "Save debug part mesh " << ss.str();
1250  EntityHandle meshset;
1251  CHKERR moab.create_meshset(MESHSET_SET, meshset);
1252  CHKERR moab.add_entities(meshset, range);
1253  if (!range.empty())
1254  CHKERR moab.write_file(ss.str().c_str(), "VTK", "", &meshset, 1);
1255  MOFEM_LOG("SYNC", sev) << "Empty range";
1256  CHKERR moab.delete_entities(&meshset, 1);
1257  MOFEM_LOG_SEVERITY_SYNC(PETSC_COMM_WORLD, sev);
1258  };
1259 
1260  auto get_skin = [&](auto e) {
1261  Range s;
1262  CHKERR skin.find_skin(0, e.subset_by_dimension(dim), false, s);
1263  return s;
1264  };
1265 
1266  auto get_adj = [&](auto ents, auto dim) {
1267  Range adj;
1268  CHKERR moab.get_adjacencies(ents, dim, false, adj, moab::Interface::UNION);
1269  return adj;
1270  };
1271 
1272  Range all_ents;
1273  CHKERR moab.get_entities_by_handle(0, all_ents, false);
1274  save_range_to_file(all_ents, "all_ents");
1275 
1276  Tag part_tag = pcomm->part_tag();
1277  Range tagged_sets, proc_ents, off_proc_ents;
1278 
1279  CHKERR moab.get_entities_by_type_and_tag(0, MBENTITYSET, &part_tag, NULL, 1,
1280  tagged_sets, moab::Interface::UNION);
1281  print_range_on_procs(tagged_sets, "tagged_sets");
1282  for (auto &mit : tagged_sets) {
1283  int part;
1284  CHKERR moab.tag_get_data(part_tag, &mit, 1, &part);
1285  if (part == pcomm->rank()) {
1286  CHKERR moab.get_entities_by_handle(mit, proc_ents, true);
1287  } else {
1288  CHKERR moab.get_entities_by_handle(mit, off_proc_ents, true);
1289  }
1290  }
1291 
1292  // set part tags to entities, they might be not set
1293  for (auto &mit : tagged_sets) {
1294  int part;
1295  CHKERR moab.tag_get_data(part_tag, &mit, 1, &part);
1296  Range ents;
1297  CHKERR moab.get_entities_by_handle(mit, ents, true);
1298  CHKERR moab.tag_clear_data(part_tag, ents, &part);
1299  }
1300 
1301  print_range_on_procs(proc_ents, "proc_ents");
1302  save_range_to_file(proc_ents, "proc_ents");
1303 
1304  auto get_proc_ents_skin = [&]() {
1305  std::array<Range, 4>
1306  proc_ents_skin; // stores only entities shared with other processors
1307  auto all_skin = get_skin(all_ents.subset_by_dimension(dim));
1308  auto proc_skin = get_skin(proc_ents.subset_by_dimension(dim));
1309  if (dim == 3) {
1310  proc_ents_skin[2] = subtract(proc_skin, all_skin); // faces
1311  proc_ents_skin[1] = get_adj(proc_ents_skin[dim - 1], 1); // edges
1312  }
1313  if (dim == 2) {
1314  proc_ents_skin[1] = subtract(proc_skin, all_skin); // edges
1315  }
1316  CHKERR moab.get_connectivity(proc_ents_skin[dim - 1], proc_ents_skin[0],
1317  false); // vertices
1318  return proc_ents_skin;
1319  };
1320 
1321  auto add_post_proc_skin = [&](auto &&proc_ents_skin) {
1322  CubitMeshSet_multiIndex cubit_meshsets_index; ///< cubit meshsets
1323 
1324  Tag nsTag, ssTag, nsTag_data, ssTag_data, bhTag, bhTag_header;
1325  CHKERR MeshsetsManager::getTags(moab, nsTag, ssTag, nsTag_data, ssTag_data,
1326  bhTag, bhTag_header, QUIET);
1327 
1328  Range meshsets;
1329  CHKERR moab.get_entities_by_type(0, MBENTITYSET, meshsets, false);
1330  for (auto m : meshsets) {
1331  // check if meshset is cubit meshset
1332  CubitMeshSets block(moab, m);
1333  if ((block.cubitBcType & CubitBCType(NODESET | SIDESET | BLOCKSET))
1334  .any()) {
1335  auto p = cubit_meshsets_index.insert(block);
1336  if (!p.second) {
1337  // blockset/nodeset/sideset set exist, could be created on other
1338  // processor.
1339  Range ents;
1340  CHKERR moab.get_entities_by_handle(m, ents, true);
1341  CHKERR moab.add_entities(p.first->getMeshset(), ents);
1342  CHKERR moab.delete_entities(&m, 1);
1343  }
1344  }
1345  }
1346 
1347  for (auto &m : cubit_meshsets_index) {
1348  MOFEM_LOG("WORLD", sev) << "LoadFile read " << m;
1349  }
1350  MOFEM_LOG_SEVERITY_SYNC(PETSC_COMM_WORLD, sev);
1351 
1352  std::vector<const CubitMeshSets *> vec_ptr;
1353  for (auto &m : cubit_meshsets_index) {
1354  vec_ptr.push_back(&m);
1355  }
1357 
1358  return proc_skin_fun(std::move(proc_ents_skin), std::move(vec_ptr));
1359  };
1360 
1361  auto remove_off_proc_ents = [&](auto &all_ents, auto &off_proc_ents,
1362  auto &proc_ents_skin) {
1363  auto to_remove = off_proc_ents;
1364  for (auto d = dim - 1; d >= 0; --d) {
1365  to_remove = subtract(to_remove, proc_ents_skin[d]);
1366  }
1367 
1368  Range meshsets;
1369  CHKERR moab.get_entities_by_type(0, MBENTITYSET, meshsets, true);
1370  for (auto m : meshsets) {
1371  CHKERR moab.remove_entities(m, to_remove);
1372  }
1373  for (int dd = dim; dd > 0; --dd) {
1374  CHKERR moab.delete_entities(to_remove.subset_by_dimension(dd));
1375  }
1376  };
1377 
1378  auto proc_ents_skin = add_post_proc_skin(get_proc_ents_skin());
1379  for (auto d = dim - 1; d >= 0; --d) {
1380  save_range_to_file(proc_ents_skin[d], "proc_ents_skin" + std::to_string(d));
1381  }
1382 
1383  if (pcomm->rank()) {
1384  remove_off_proc_ents(all_ents, off_proc_ents, proc_ents_skin);
1385  }
1386 
1387  for (auto d = dim - 1; d >= 0; --d) {
1388  print_range_on_procs(proc_ents_skin[d],
1389  "proc_ents_skin by dim" + std::to_string(d));
1390  }
1391 
1392  CHKERR pcomm->resolve_shared_ents(0, proc_ents, dim, -1,
1393  proc_ents_skin.data());
1394 
1395  if (debug) {
1396 
1397  // Create a tag
1398  auto gid_tag = moab.globalId_tag();
1399 
1400  int def_val = -1;
1401  Tag tag_handle;
1402  CHKERR moab.tag_get_handle("TestGather", 1, MB_TYPE_INTEGER, tag_handle,
1403  MB_TAG_DENSE | MB_TAG_CREAT, &def_val);
1404  Range gather_ents;
1405  if (pcomm->rank() > 0) {
1406  gather_ents = proc_ents.subset_by_dimension(3);
1407  std::vector<int> vals(gather_ents.size());
1408  std::for_each(vals.begin(), vals.end(), [](auto &v) { v = std::rand(); });
1409  CHKERR moab.tag_set_data(tag_handle, gather_ents, vals.data());
1410  CHKERR pcomm->gather_data(gather_ents, tag_handle, gid_tag, 0, 0);
1411  } else {
1412  gather_ents = proc_ents.subset_by_dimension(3);
1413  CHKERR pcomm->gather_data(gather_ents, tag_handle, gid_tag, 0, 0);
1414  }
1415  }
1416 
1417  Range all_ents_after;
1418  CHKERR moab.get_entities_by_handle(0, all_ents_after);
1419  save_range_to_file(all_ents_after.subset_by_dimension(3),
1420  "all_ents_part_after");
1421 
1423 }

◆ makeEntitiesMultishared() [1/2]

MoFEMErrorCode MoFEM::CommInterface::makeEntitiesMultishared ( const EntityHandle entities,
const int  num_entities,
const int  owner_proc = 0,
int  verb = DEFAULT_VERBOSITY 
)

make entities from proc 0 shared on all proc

Note
collective - need tu be run on all processors in communicator
Parameters
entities
num_entities
my_procdefault proc id to share from
verb
Returns
MoFEMErrorCode

Definition at line 654 of file CommInterface.cpp.

656  {
657  MoFEM::Interface &m_field = cOre;
659 
660  if (m_field.get_comm_size() > 1) {
661 
662  ParallelComm *pcomm = ParallelComm::get_pcomm(
663  &m_field.get_moab(), m_field.get_basic_entity_data_ptr()->pcommID);
664 
665  Range all_ents_range;
666  all_ents_range.insert_list(entities, entities + num_entities);
667 
668  auto get_tag = [&]() {
669  const int negone = -1;
670  Tag th;
671  m_field.get_moab().tag_get_handle("TMP_GLOBAL_ID_TAG_NAME", 1,
672  MB_TYPE_INTEGER, th,
673  MB_TAG_CREAT | MB_TAG_SPARSE, &negone);
674  return th;
675  };
676 
677  auto delete_tag = [&](auto &&th_gid) {
679  CHKERR m_field.get_moab().tag_delete(th_gid);
681  };
682 
683  auto resolve_shared_ents = [&](auto &&th_gid, auto &all_ents_range) {
684  auto set_gid = [&](auto &th_gid) {
685  std::vector<int> gids(num_entities);
686  for (size_t g = 0; g != all_ents_range.size(); ++g)
687  gids[g] = g + 1;
688  CHKERR m_field.get_moab().tag_set_data(th_gid, all_ents_range,
689  &*gids.begin());
690 
691  return &th_gid;
692  };
693 
694  auto get_skin_ents = [&](auto &all_ents_range) {
695  std::array<Range, 4> proc_ents_skin;
696  proc_ents_skin[3] = all_ents_range.subset_by_dimension(3);
697  proc_ents_skin[2] = all_ents_range.subset_by_dimension(2);
698  proc_ents_skin[1] = all_ents_range.subset_by_dimension(1);
699  proc_ents_skin[0] = all_ents_range.subset_by_dimension(0);
700  return proc_ents_skin;
701  };
702 
703  auto resolve_dim = [&](auto &all_ents_range) {
704  for (int resolve_dim = 3; resolve_dim >= 0; --resolve_dim) {
705  if (all_ents_range.num_of_dimension(resolve_dim))
706  return resolve_dim;
707  }
708  return -1;
709  };
710 
711  auto get_proc_ent = [&](auto &all_ents_range) {
712  Range proc_ent;
713  if (m_field.get_comm_rank() == owner_proc)
714  proc_ent = all_ents_range;
715  return proc_ent;
716  };
717 
718  auto resolve_shared_ents = [&](auto &&proc_ents, auto &&skin_ents) {
719  return pcomm->resolve_shared_ents(
720  0, proc_ents, resolve_dim(all_ents_range),
721  resolve_dim(all_ents_range), skin_ents.data(), set_gid(th_gid));
722  };
723 
724  CHKERR resolve_shared_ents(get_proc_ent(all_ents_range),
725  get_skin_ents(all_ents_range));
726 
727  return th_gid;
728  };
729 
730  CHKERR delete_tag(resolve_shared_ents(get_tag(), all_ents_range));
731 
732  if (verb >= NOISY) {
733 
734  auto print_owner = [&](const EntityHandle e) {
736  int moab_owner_proc;
737  EntityHandle moab_owner_handle;
738  CHKERR pcomm->get_owner_handle(e, moab_owner_proc, moab_owner_handle);
739 
740  unsigned char pstatus = 0;
741 
742  CHKERR m_field.get_moab().tag_get_data(pcomm->pstatus_tag(), &e, 1,
743  &pstatus);
744 
745  std::vector<int> shprocs(MAX_SHARING_PROCS, 0);
746  std::vector<EntityHandle> shhandles(MAX_SHARING_PROCS, 0);
747 
748  CHKERR m_field.get_moab().tag_get_data(pcomm->sharedp_tag(), &e, 1,
749  &shprocs[0]);
750  CHKERR m_field.get_moab().tag_get_data(pcomm->sharedh_tag(), &e, 1,
751  &shhandles[0]);
752  if (pstatus & PSTATUS_MULTISHARED) {
753  CHKERR m_field.get_moab().tag_get_data(pcomm->sharedps_tag(), &e, 1,
754  &shprocs[0]);
755  CHKERR m_field.get_moab().tag_get_data(pcomm->sharedhs_tag(), &e, 1,
756  &shhandles[0]);
757  }
758 
759  std::ostringstream ss;
760 
761  ss << "Rank " << m_field.get_comm_rank() << " ";
762  if (!(pstatus & PSTATUS_NOT_OWNED))
763  ss << "OWNER ";
764  if (pstatus & PSTATUS_SHARED)
765  ss << "PSTATUS_SHARED ";
766  if (pstatus & PSTATUS_MULTISHARED)
767  ss << "PSTATUS_MULTISHARED ";
768 
769  ss << "owner " << moab_owner_proc << " (" << owner_proc << ") ";
770 
771  ss << "shprocs: ";
772  for (size_t r = 0; r != m_field.get_comm_size() + 1; ++r)
773  ss << shprocs[r] << " ";
774 
775  ss << "shhandles: ";
776  for (size_t r = 0; r != m_field.get_comm_size() + 1; ++r)
777  ss << shhandles[r] << " ";
778 
779  ss << std::endl;
780  MOFEM_LOG("SYNC", Sev::noisy) << ss.str();
781  MOFEM_LOG_SYNCHRONISE(m_field.get_comm());
782 
784  };
785 
786  for (auto e : all_ents_range)
787  CHKERR print_owner(e);
788  }
789  }
790 
792 }

◆ makeEntitiesMultishared() [2/2]

MoFEMErrorCode MoFEM::CommInterface::makeEntitiesMultishared ( Range entities,
const int  owner_proc = 0,
int  verb = DEFAULT_VERBOSITY 
)

make entities from proc 0 shared on all proc

Note
collective - need tu be run on all processors in communicator
Parameters
entities
my_procdefault proc id to share from
verb
Returns
MoFEMErrorCode

Definition at line 794 of file CommInterface.cpp.

796  {
797  MoFEM::Interface &m_field = cOre;
799  if (m_field.get_comm_size() > 1) {
800  const int num_ents = entities.size();
801  std::vector<EntityHandle> vec_ents(num_ents);
802  std::copy(entities.begin(), entities.end(), vec_ents.begin());
803  CHKERR makeEntitiesMultishared(&*vec_ents.begin(), num_ents, owner_proc,
804  verb);
805  }
807 }

◆ makeFieldEntitiesMultishared()

MoFEMErrorCode MoFEM::CommInterface::makeFieldEntitiesMultishared ( const std::string  field_name,
const int  owner_proc = 0,
int  verb = DEFAULT_VERBOSITY 
)

make field entities multi shared

Note
collective - need tu be run on all processors in communicator
Parameters
field_name
owner_proc
verb
Returns
MoFEMErrorCode

Definition at line 810 of file CommInterface.cpp.

811  {
812  MoFEM::Interface &m_field = cOre;
814  if (m_field.get_comm_size() > 1) {
815  EntityHandle field_meshset = m_field.get_field_meshset(field_name);
816  std::vector<EntityHandle> field_ents;
817  CHKERR m_field.get_moab().get_entities_by_handle(field_meshset, field_ents,
818  true);
819  CHKERR makeEntitiesMultishared(&*field_ents.begin(), field_ents.size(),
820  owner_proc, verb);
821  }
823 }

◆ query_interface()

MoFEMErrorCode MoFEM::CommInterface::query_interface ( boost::typeindex::type_index  type_index,
UnknownInterface **  iface 
) const
virtual

Implements MoFEM::UnknownInterface.

Definition at line 16 of file CommInterface.cpp.

17  {
19  *iface = const_cast<CommInterface *>(this);
21 }

◆ resolveParentEntities()

MoFEMErrorCode MoFEM::CommInterface::resolveParentEntities ( const Range ent,
int  verb = DEFAULT_VERBOSITY 
)

Synchronise parent entities.

Note
collective - need tu be run on all processors in communicator

Exchange parent entity tag and bitref of entity. Note thar parent handle can be different on each processor.

Parameters
ent
verb
Returns
MoFEMErrorCode

Definition at line 256 of file CommInterface.cpp.

257  {
258  MoFEM::Interface &m_field = cOre;
259  ParallelComm *pcomm = ParallelComm::get_pcomm(
260  &m_field.get_moab(), m_field.get_basic_entity_data_ptr()->pcommID);
261 
263 
264  Range shared = ents;
265  CHKERR pcomm->filter_pstatus(shared, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1,
266  nullptr);
267  CHKERR pcomm->filter_pstatus(shared, PSTATUS_SHARED | PSTATUS_MULTISHARED,
268  PSTATUS_OR, -1, nullptr);
269 
270  auto th_RefParentHandle = cOre.get_th_RefParentHandle();
271  auto th_RefBitLevel = cOre.get_th_RefBitLevel();
272 
273  auto get_pstatus = [&](const auto ent) {
274  unsigned char pstatus;
275  CHK_MOAB_THROW(m_field.get_moab().tag_get_data(pcomm->pstatus_tag(), &ent,
276  1, &pstatus),
277  "can not get pstatus");
278  return pstatus;
279  };
280 
281  auto get_sharing_procs = [&](const auto ent, const auto pstatus) {
282  std::vector<int> sharing_procs(MAX_SHARING_PROCS, -1);
283  if (pstatus & PSTATUS_MULTISHARED) {
284  // entity is multi shared
285  CHK_MOAB_THROW(m_field.get_moab().tag_get_data(
286  pcomm->sharedps_tag(), &ent, 1, &sharing_procs[0]),
287  "can not ger sharing_procs_ptr");
288  } else if (pstatus & PSTATUS_SHARED) {
289  // shared
290  CHK_MOAB_THROW(m_field.get_moab().tag_get_data(pcomm->sharedp_tag(), &ent,
291  1, &sharing_procs[0]),
292  "can not get sharing proc");
293  }
294  return sharing_procs;
295  };
296 
297  auto get_sharing_handles = [&](const auto ent, const auto pstatus) {
298  std::vector<EntityHandle> sharing_handles(MAX_SHARING_PROCS, 0);
299  if (pstatus & PSTATUS_MULTISHARED) {
300  // entity is multi shared
301  CHK_MOAB_THROW(m_field.get_moab().tag_get_data(
302  pcomm->sharedhs_tag(), &ent, 1, &sharing_handles[0]),
303  "get shared handles");
304  } else if (pstatus & PSTATUS_SHARED) {
305  // shared
306  CHK_MOAB_THROW(m_field.get_moab().tag_get_data(pcomm->sharedh_tag(), &ent,
307  1, &sharing_handles[0]),
308  "get sharing handle");
309  }
310  return sharing_handles;
311  };
312 
313  auto get_parent_and_bit = [&](const auto ent) {
314  EntityHandle parent;
316  m_field.get_moab().tag_get_data(th_RefParentHandle, &ent, 1, &parent),
317  "get parent");
320  m_field.get_moab().tag_get_data(th_RefBitLevel, &ent, 1, &bit),
321  "get parent");
322  return std::make_pair(parent, bit);
323  };
324 
325  auto set_parent = [&](const auto ent, const auto parent) {
326  return m_field.get_moab().tag_set_data(th_RefParentHandle, &ent, 1,
327  &parent);
328  };
329 
330  auto set_bit = [&](const auto ent, const auto bit) {
331  return m_field.get_moab().tag_set_data(th_RefBitLevel, &ent, 1, &bit);
332  };
333 
334  // make a buffer
335  std::vector<std::vector<unsigned long long>> sbuffer(m_field.get_comm_size());
336 
337  for (auto ent : shared) {
338 
339  auto pstatus = get_pstatus(ent);
340  auto sharing_procs = get_sharing_procs(ent, pstatus);
341  auto sharing_handles = get_sharing_handles(ent, pstatus);
342  auto [parent, bit] = get_parent_and_bit(ent);
343 
344  if (verb >= NOISY)
345  MOFEM_LOG("SYNC", Sev::noisy) << "pstatus " << std::bitset<8>(pstatus);
346 
347  if (parent) {
348  auto pstatus_parent = get_pstatus(parent);
349  auto sharing_procs_parent = get_sharing_procs(parent, pstatus_parent);
350  auto sharing_handles_parent = get_sharing_handles(parent, pstatus_parent);
351 
352  for (int proc = 0; proc < MAX_SHARING_PROCS && -1 != sharing_procs[proc];
353  proc++) {
354  if (sharing_procs[proc] == -1)
355  SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE,
356  "sharing processor not set");
357 
358  if (sharing_procs[proc] != m_field.get_comm_rank()) {
359 
360  auto it = std::find(sharing_procs_parent.begin(),
361  sharing_procs_parent.end(), sharing_procs[proc]);
362  if (it == sharing_procs_parent.end()) {
363  SETERRQ1(
364  PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
365  "Sharing proc for parent entity can not be found proc = %u",
366  sharing_procs[proc]);
367  }
368 
369  auto handle_on_sharing_proc = sharing_handles[proc];
370  auto parent_handle_on_sharing_proc =
371  sharing_handles_parent[std::distance(sharing_procs_parent.begin(),
372  it)];
373  sbuffer[sharing_procs[proc]].push_back(handle_on_sharing_proc);
374  sbuffer[sharing_procs[proc]].push_back(parent_handle_on_sharing_proc);
375  try {
376  sbuffer[sharing_procs[proc]].push_back(bit.to_ullong());
377  } catch (std::exception &ex) {
378  MOFEM_LOG("SELF", Sev::warning) << ex.what();
379  MOFEM_LOG("SELF", Sev::warning)
380  << "On " << ent << " "
381  << moab::CN::EntityTypeName(type_from_handle(ent));
382  MOFEM_LOG("SELF", Sev::warning) << "For bit ref " << bit;
383  }
384  if (verb >= NOISY)
385  MOFEM_LOG_C("SYNC", Sev::noisy, "send %lu (%lu) to %d at %d\n", ent,
386  handle_on_sharing_proc, sharing_procs[proc],
387  m_field.get_comm_rank());
388 
389  if (!(pstatus & PSTATUS_MULTISHARED))
390  break;
391  }
392  }
393  } else {
394  for (int proc = 0; proc < MAX_SHARING_PROCS && -1 != sharing_procs[proc];
395  proc++) {
396  if (sharing_procs[proc] == -1)
397  SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE,
398  "sharing processor not set");
399 
400  if (sharing_procs[proc] != m_field.get_comm_rank()) {
401  auto handle_on_sharing_proc = sharing_handles[proc];
402  sbuffer[sharing_procs[proc]].push_back(handle_on_sharing_proc);
403  sbuffer[sharing_procs[proc]].push_back(parent);
404 
405  try {
406  sbuffer[sharing_procs[proc]].push_back(bit.to_ullong());
407  } catch (std::exception &ex) {
408  MOFEM_LOG("SELF", Sev::warning) << ex.what();
409  MOFEM_LOG("SELF", Sev::warning)
410  << "On " << ent << " "
411  << moab::CN::EntityTypeName(type_from_handle(ent));
412  MOFEM_LOG("SELF", Sev::warning) << "For bit ref " << bit;
413  }
414 
415  if (verb >= NOISY)
416  MOFEM_LOG_C("SYNC", Sev::noisy, "send %lu (%lu) to %d at %d\n", ent,
417  handle_on_sharing_proc, sharing_procs[proc],
418  m_field.get_comm_rank());
419 
420  if (!(pstatus & PSTATUS_MULTISHARED))
421  break;
422  }
423  }
424  }
425  }
426 
427  int nsends = 0; // number of messages to send
428  std::vector<int> sbuffer_lengths(
429  m_field.get_comm_size()); // length of the message to proc
430 
431  const size_t block_size = sizeof(unsigned long long) / sizeof(int);
432  for (int proc = 0; proc < m_field.get_comm_size(); proc++) {
433 
434  if (!sbuffer[proc].empty()) {
435 
436  sbuffer_lengths[proc] = sbuffer[proc].size() * block_size;
437  nsends++;
438 
439  } else {
440 
441  sbuffer_lengths[proc] = 0;
442  }
443  }
444 
445  // Make sure it is a PETSc m_field.get_comm()
446  MPI_Comm comm;
447  CHKERR PetscCommDuplicate(m_field.get_comm(), &comm, NULL);
448 
449  std::vector<MPI_Status> status(m_field.get_comm_size());
450 
451  // Computes the number of messages a node expects to receive
452  int nrecvs; // number of messages received
453  CHKERR PetscGatherNumberOfMessages(comm, NULL, &sbuffer_lengths[0], &nrecvs);
454 
455  // Computes info about messages that a MPI-node will receive, including
456  // (from-id,length) pairs for each message.
457  int *onodes; // list of node-ids from which messages are expected
458  int *olengths; // corresponding message lengths
459  CHKERR PetscGatherMessageLengths(comm, nsends, nrecvs, &sbuffer_lengths[0],
460  &onodes, &olengths);
461 
462  // Gets a unique new tag from a PETSc communicator. All processors that share
463  // the communicator MUST call this routine EXACTLY the same number of times.
464  // This tag should only be used with the current objects communicator; do NOT
465  // use it with any other MPI communicator.
466  int tag;
467  CHKERR PetscCommGetNewTag(comm, &tag);
468 
469  // Allocate a buffer sufficient to hold messages of size specified in
470  // olengths. And post Irecvs on these buffers using node info from onodes
471  int **rbuf; // must bee freed by user
472  MPI_Request *r_waits; // must bee freed by user
473  // rbuf has a pointers to messages. It has size of of nrecvs (number of
474  // messages) +1. In the first index a block is allocated,
475  // such that rbuf[i] = rbuf[i-1]+olengths[i-1].
476  CHKERR PetscPostIrecvInt(comm, tag, nrecvs, onodes, olengths, &rbuf,
477  &r_waits);
478 
479  MPI_Request *s_waits; // status of sens messages
480  CHKERR PetscMalloc1(nsends, &s_waits);
481 
482  // Send messages
483  for (int proc = 0, kk = 0; proc < m_field.get_comm_size(); proc++) {
484  if (!sbuffer_lengths[proc])
485  continue; // no message to send to this proc
486  CHKERR MPI_Isend(&(sbuffer[proc])[0], // buffer to send
487  sbuffer_lengths[proc], // message length
488  MPIU_INT, proc, // to proc
489  tag, comm, s_waits + kk);
490  kk++;
491  }
492 
493  // Wait for received
494  if (nrecvs)
495  CHKERR MPI_Waitall(nrecvs, r_waits, &status[0]);
496 
497  // Wait for send messages
498  if (nsends)
499  CHKERR MPI_Waitall(nsends, s_waits, &status[0]);
500 
501  if (verb >= VERBOSE) {
502  MOFEM_LOG_C("SYNC", Sev::verbose,
503  "Rank %d nb. shared to synchronise parents ents %u\n",
504  m_field.get_comm_rank(), shared.size());
505  }
506 
507  // synchronise range
508  for (int kk = 0; kk < nrecvs; kk++) {
509 
510  int len = olengths[kk];
511  int *data_from_proc = rbuf[kk];
512 
513  for (int ee = 0; ee < len;) {
514  EntityHandle ent;
515  EntityHandle parent;
516  unsigned long long uulong_bit;
517  bcopy(&data_from_proc[ee], &ent, sizeof(EntityHandle));
518  ee += block_size;
519  bcopy(&data_from_proc[ee], &parent, sizeof(EntityHandle));
520  ee += block_size;
521  bcopy(&data_from_proc[ee], &uulong_bit, sizeof(unsigned long long));
522  ee += block_size;
523 
524  CHKERR set_parent(ent, parent);
525  CHKERR set_bit(ent, BitRefLevel(uulong_bit));
526 
527  if (verb >= VERBOSE) {
528  MOFEM_LOG_C("SYNC", Sev::noisy, "received %lu (%lu) from %d at %d\n",
529  ent, parent, onodes[kk], m_field.get_comm_rank());
530  MOFEM_LOG("SYNC", Sev::noisy) << "Bit " << BitRefLevel(uulong_bit);
531  }
532  }
533  }
534 
535  // Cleaning
536  CHKERR PetscFree(s_waits);
537  CHKERR PetscFree(rbuf[0]);
538  CHKERR PetscFree(rbuf);
539  CHKERR PetscFree(r_waits);
540  CHKERR PetscFree(onodes);
541  CHKERR PetscFree(olengths);
542  CHKERR PetscCommDestroy(&comm);
543 
544  if (verb >= VERBOSE)
545  MOFEM_LOG_SYNCHRONISE(m_field.get_comm());
546 
548 }

◆ synchroniseEntities() [1/2]

MoFEMErrorCode MoFEM::CommInterface::synchroniseEntities ( Range ent,
int  verb = DEFAULT_VERBOSITY 
)

synchronize entity range on processors (collective)

Note
collective - need tu be run on all processors in communicator
Parameters
entents to send and received
verb
Returns
MoFEMErrorCode

Definition at line 240 of file CommInterface.cpp.

240  {
241  return synchroniseEntities(ents, nullptr, verb);
242 }

◆ synchroniseEntities() [2/2]

MoFEMErrorCode MoFEM::CommInterface::synchroniseEntities ( Range ent,
std::map< int, Range > *  received_ents,
int  verb = DEFAULT_VERBOSITY 
)

synchronize entity range on processors (collective)

synchronize entity range on processors (collective)

Note
collective - need tu be run on all processors in communicator
collective - need tu be run on all processors in communicator
Parameters
entents to send and received
received_entspointer to map with received entities
verb
Returns
MoFEMErrorCode

Definition at line 26 of file CommInterface.cpp.

27  {
28  MoFEM::Interface &m_field = cOre;
29  ParallelComm *pcomm = ParallelComm::get_pcomm(
30  &m_field.get_moab(), m_field.get_basic_entity_data_ptr()->pcommID);
32 
33  auto get_pstatus = [&](const auto ent) {
34  unsigned char pstatus;
35  CHK_MOAB_THROW(m_field.get_moab().tag_get_data(pcomm->pstatus_tag(), &ent,
36  1, &pstatus),
37  "can not get pstatus");
38  return pstatus;
39  };
40 
41  auto get_sharing_procs = [&](const auto ent, const auto pstatus) {
42  std::vector<int> sharing_procs(MAX_SHARING_PROCS, -1);
43  if (pstatus & PSTATUS_MULTISHARED) {
44  // entity is multi shared
45  CHK_MOAB_THROW(m_field.get_moab().tag_get_data(
46  pcomm->sharedps_tag(), &ent, 1, &sharing_procs[0]),
47  "can not ger sharing_procs_ptr");
48  } else if (pstatus & PSTATUS_SHARED) {
49  // shared
50  CHK_MOAB_THROW(m_field.get_moab().tag_get_data(pcomm->sharedp_tag(), &ent,
51  1, &sharing_procs[0]),
52  "can not get sharing proc");
53  }
54  return sharing_procs;
55  };
56 
57  auto get_sharing_handles = [&](const auto ent, const auto pstatus) {
58  std::vector<EntityHandle> sharing_handles(MAX_SHARING_PROCS, 0);
59  if (pstatus & PSTATUS_MULTISHARED) {
60  // entity is multi shared
61  CHK_MOAB_THROW(m_field.get_moab().tag_get_data(
62  pcomm->sharedhs_tag(), &ent, 1, &sharing_handles[0]),
63  "get shared handles");
64  } else if (pstatus & PSTATUS_SHARED) {
65  // shared
66  CHK_MOAB_THROW(m_field.get_moab().tag_get_data(pcomm->sharedh_tag(), &ent,
67  1, &sharing_handles[0]),
68  "get sharing handle");
69  }
70  return sharing_handles;
71  };
72 
73  // make a buffer entities to send
74  std::vector<std::vector<EntityHandle>> sbuffer(m_field.get_comm_size());
75 
76  for (auto ent : ents) {
77 
78  auto pstatus = get_pstatus(ent);
79  if (pstatus) {
80  auto sharing_procs = get_sharing_procs(ent, pstatus);
81  auto sharing_handles = get_sharing_handles(ent, pstatus);
82 
83  if (verb >= NOISY) {
84  MOFEM_LOG("SYNC", Sev::noisy) << "pstatus " << std::bitset<8>(pstatus);
85  }
86 
87  for (int proc = 0; proc < MAX_SHARING_PROCS && -1 != sharing_procs[proc];
88  proc++) {
89  if (sharing_procs[proc] == -1)
90  SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE,
91  "sharing processor not set");
92 
93  if (sharing_procs[proc] == m_field.get_comm_rank())
94  continue;
95 
96  const auto handle_on_sharing_proc = sharing_handles[proc];
97  // add entity to send, handle on the other side
98  sbuffer[sharing_procs[proc]].push_back(handle_on_sharing_proc);
99  if (verb >= NOISY) {
100  MOFEM_LOG_C("SYNC", Sev::noisy, "send %lu (%lu) to %d at %d\n", ent,
101  handle_on_sharing_proc, sharing_procs[proc],
102  m_field.get_comm_rank());
103  }
104 
105  if (!(pstatus & PSTATUS_MULTISHARED))
106  break;
107  }
108  }
109  }
110  if (verb >= NOISY) {
111  MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::noisy);
112  }
113 
114  int nsends = 0; // number of messages to send
115  std::vector<int> sbuffer_lengths(
116  m_field.get_comm_size()); // length of the message to proc
117  const size_t block_size =
118  sizeof(EntityHandle) /
119  sizeof(int); // FIXME check if that works on given architecture!
120  for (int proc = 0; proc < m_field.get_comm_size(); proc++) {
121 
122  if (!sbuffer[proc].empty()) {
123 
124  sbuffer_lengths[proc] = sbuffer[proc].size() * block_size;
125  nsends++;
126 
127  } else {
128 
129  sbuffer_lengths[proc] = 0;
130  }
131  }
132 
133  // Make sure it is a PETSc m_field.get_comm()
134  MPI_Comm comm;
135  CHKERR PetscCommDuplicate(m_field.get_comm(), &comm, NULL);
136 
137  std::vector<MPI_Status> status(m_field.get_comm_size());
138 
139  // Computes the number of messages a node expects to receive
140  int nrecvs; // number of messages received
141  CHKERR PetscGatherNumberOfMessages(comm, NULL, &sbuffer_lengths[0], &nrecvs);
142 
143  // Computes info about messages that a MPI-node will receive, including
144  // (from-id,length) pairs for each message.
145  int *onodes; // list of node-ids from which messages are expected
146  int *olengths; // corresponding message lengths
147  CHKERR PetscGatherMessageLengths(comm, nsends, nrecvs, &sbuffer_lengths[0],
148  &onodes, &olengths);
149 
150  // Gets a unique new tag from a PETSc communicator. All processors that share
151  // the communicator MUST call this routine EXACTLY the same number of times.
152  // This tag should only be used with the current objects communicator; do NOT
153  // use it with any other MPI communicator.
154  int tag;
155  CHKERR PetscCommGetNewTag(comm, &tag);
156 
157  // Allocate a buffer sufficient to hold messages of size specified in
158  // olengths. And post Irecvs on these buffers using node info from onodes
159  int **rbuf; // must bee freed by user
160  MPI_Request *r_waits; // must bee freed by user
161  // rbuf has a pointers to messages. It has size of of nrecvs (number of
162  // messages) +1. In the first index a block is allocated,
163  // such that rbuf[i] = rbuf[i-1]+olengths[i-1].
164  CHKERR PetscPostIrecvInt(comm, tag, nrecvs, onodes, olengths, &rbuf,
165  &r_waits);
166 
167  MPI_Request *s_waits; // status of sens messages
168  CHKERR PetscMalloc1(nsends, &s_waits);
169 
170  // Send messages
171  for (int proc = 0, kk = 0; proc < m_field.get_comm_size(); proc++) {
172  if (!sbuffer_lengths[proc])
173  continue; // no message to send to this proc
174  CHKERR MPI_Isend(&(sbuffer[proc])[0], // buffer to send
175  sbuffer_lengths[proc], // message length
176  MPIU_INT, proc, // to proc
177  tag, comm, s_waits + kk);
178  kk++;
179  }
180 
181  // Wait for received
182  if (nrecvs)
183  CHKERR MPI_Waitall(nrecvs, r_waits, &status[0]);
184 
185  // Wait for send messages
186  if (nsends)
187  CHKERR MPI_Waitall(nsends, s_waits, &status[0]);
188 
189  if (verb >= VERBOSE) {
190  MOFEM_LOG_C("SYNC", Sev::verbose, "Rank %d nb. before ents %u\n",
191  m_field.get_comm_rank(), ents.size());
192  MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::verbose);
193  }
194 
195  // synchronise range
196  for (int kk = 0; kk < nrecvs; kk++) {
197 
198  int len = olengths[kk];
199  int *data_from_proc = rbuf[kk];
200 
201  for (int ee = 0; ee < len;) {
202  EntityHandle ent;
203  bcopy(&data_from_proc[ee], &ent, sizeof(EntityHandle));
204  ents.insert(ent);
205 
206  if (received_ents) {
207  (*received_ents)[onodes[kk]].insert(ent);
208  }
209 
210  ee += block_size;
211 
212  if (verb >= VERBOSE) {
213  MOFEM_LOG_C("SYNC", Sev::noisy, "received %lu from %d at %d\n", ent,
214  onodes[kk], m_field.get_comm_rank());
215  }
216  }
217  }
218  if (verb >= VERBOSE) {
219  MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::verbose);
220  }
221 
222  if (verb >= VERBOSE) {
223  MOFEM_LOG_C("SYNC", Sev::verbose, "Rank %d nb. after ents %u",
224  m_field.get_comm_rank(), ents.size());
225  MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::verbose);
226  }
227 
228  // Cleaning
229  CHKERR PetscFree(s_waits);
230  CHKERR PetscFree(rbuf[0]);
231  CHKERR PetscFree(rbuf);
232  CHKERR PetscFree(r_waits);
233  CHKERR PetscFree(onodes);
234  CHKERR PetscFree(olengths);
235  CHKERR PetscCommDestroy(&comm);
236 
238 }

◆ updateEntitiesPetscVector()

MoFEMErrorCode MoFEM::CommInterface::updateEntitiesPetscVector ( moab::Interface &  moab,
EntitiesPetscVector vec,
Tag  tag,
UpdateGhosts  update_gosts = defaultUpdateGhosts 
)
static

Exchange data between vector and data.

Parameters
tag
Returns
MoFEMErrorCode

Definition at line 1612 of file CommInterface.cpp.

1614  {
1616 
1617  int local_size;
1618  CHKERR VecGetLocalSize(vec.second, &local_size);
1619  int nb_coeffs;
1620  CHKERR moab.tag_get_length(tag, nb_coeffs);
1621  if (vec.first.first.size() * nb_coeffs != local_size) {
1622  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1623  "Local size of vector does not match number of entities");
1624  }
1625 
1626  auto set_vec_from_tags = [&]() {
1628  double *v_array;
1629  // set vector
1630  CHKERR VecGetArray(vec.second, &v_array);
1631  CHKERR moab.tag_get_data(tag, vec.first.first, v_array);
1632  CHKERR moab.tag_get_data(tag, vec.first.second, &v_array[local_size]);
1633  CHKERR VecRestoreArray(vec.second, &v_array);
1635  };
1636 
1637  auto set_tags_from_vec = [&]() {
1639  double *v_array;
1640  CHKERR VecGetArray(vec.second, &v_array);
1641  CHKERR moab.tag_set_data(tag, vec.first.first, v_array);
1642  CHKERR moab.tag_set_data(tag, vec.first.second, &v_array[local_size]);
1643  CHKERR VecRestoreArray(vec.second, &v_array);
1645  };
1646 
1647  CHKERR set_vec_from_tags();
1648  CHKERR update_gosts(vec.second);
1649  CHKERR set_tags_from_vec();
1650 
1652 }

Member Data Documentation

◆ cOre

MoFEM::Core& MoFEM::CommInterface::cOre

Definition at line 29 of file CommInterface.hpp.

◆ debug

bool MoFEM::CommInterface::debug = false
inlinestatic

Definition at line 23 of file CommInterface.hpp.

◆ dEbug

bool MoFEM::CommInterface::dEbug

Definition at line 30 of file CommInterface.hpp.

◆ sev

Sev MoFEM::CommInterface::sev = Sev::verbose
inlinestatic

Definition at line 24 of file CommInterface.hpp.


The documentation for this struct was generated from the following files:
MoFEMFunctionReturnHot
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:460
CHK_MOAB_THROW
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
Definition: definitions.h:589
SIDESET
@ SIDESET
Definition: definitions.h:160
g
constexpr double g
Definition: shallow_wave.cpp:63
MYPCOMM_INDEX
#define MYPCOMM_INDEX
default communicator number PCOMM
Definition: definitions.h:228
MoFEM::MeshsetsManager::sortMeshsets
static void sortMeshsets(std::vector< const CubitMeshSets * > &vec_ptr)
Definition: MeshsetsManager.cpp:12
MoFEM::CoreTmp< 0 >
Core (interface) class.
Definition: Core.hpp:82
MOFEM_LOG_SEVERITY_SYNC
#define MOFEM_LOG_SEVERITY_SYNC(comm, severity)
Synchronise "SYNC" on curtain severity level.
Definition: LogManager.hpp:352
MOFEM_LOG_CHANNEL
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
Definition: LogManager.hpp:284
EntityHandle
NOISY
@ NOISY
Definition: definitions.h:224
MoFEM::CoreInterface::get_comm
virtual MPI_Comm & get_comm() const =0
MoFEM::CubitMeshSet_multiIndex
multi_index_container< CubitMeshSets, indexed_by< hashed_unique< tag< Meshset_mi_tag >, member< CubitMeshSets, EntityHandle, &CubitMeshSets::meshset > >, ordered_non_unique< tag< CubitMeshsetType_mi_tag >, const_mem_fun< CubitMeshSets, unsigned long int, &CubitMeshSets::getBcTypeULong > >, ordered_non_unique< tag< CubitMeshsetMaskedType_mi_tag >, const_mem_fun< CubitMeshSets, unsigned long int, &CubitMeshSets::getMaskedBcTypeULong > >, ordered_non_unique< tag< CubitMeshsets_name >, const_mem_fun< CubitMeshSets, std::string, &CubitMeshSets::getName > >, hashed_unique< tag< Composite_Cubit_msId_And_MeshsetType_mi_tag >, composite_key< CubitMeshSets, const_mem_fun< CubitMeshSets, int, &CubitMeshSets::getMeshsetId >, const_mem_fun< CubitMeshSets, unsigned long int, &CubitMeshSets::getMaskedBcTypeULong > > > > > CubitMeshSet_multiIndex
Stores data about meshsets (see CubitMeshSets) storing data about boundary conditions,...
Definition: BCMultiIndices.hpp:388
CHK_THROW_MESSAGE
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
Definition: definitions.h:609
MoFEM::CoreInterface::get_field_structure
virtual const Field * get_field_structure(const std::string &name, enum MoFEMTypes bh=MF_EXIST) const =0
get field structure
MoFEM::CoreInterface::get_field_bit_number
virtual FieldBitNumber get_field_bit_number(const std::string name) const =0
get field bit number
MoFEM::CoreInterface::get_comm_rank
virtual int get_comm_rank() const =0
MoFEM::th
Tag th
Definition: Projection10NodeCoordsOnField.cpp:122
MoFEM::CommInterface::updateEntitiesPetscVector
static MoFEMErrorCode updateEntitiesPetscVector(moab::Interface &moab, EntitiesPetscVector &vec, Tag tag, UpdateGhosts update_gosts=defaultUpdateGhosts)
Exchange data between vector and data.
Definition: CommInterface.cpp:1612
MoFEM::CoreInterface::get_field_meshset
virtual EntityHandle get_field_meshset(const std::string name) const =0
get field meshset
MOFEM_IMPOSSIBLE_CASE
@ MOFEM_IMPOSSIBLE_CASE
Definition: definitions.h:35
sdf.r
int r
Definition: sdf.py:8
MoFEM::DeprecatedCoreInterface
Deprecated interface functions.
Definition: DeprecatedCoreInterface.hpp:16
NODESET
@ NODESET
Definition: definitions.h:159
VERBOSE
@ VERBOSE
Definition: definitions.h:222
CHKERR
#define CHKERR
Inline error check.
Definition: definitions.h:548
MoFEM::createGhostVector
auto createGhostVector(MPI_Comm comm, PetscInt n, PetscInt N, PetscInt nghost, const PetscInt ghosts[])
Create smart ghost vector.
Definition: PetscSmartObj.hpp:179
MoFEM::CoreInterface::get_moab
virtual moab::Interface & get_moab()=0
MOFEM_LOG_C
#define MOFEM_LOG_C(channel, severity, format,...)
Definition: LogManager.hpp:311
bit
auto bit
set bit
Definition: hanging_node_approx.cpp:75
MoFEM::CoreInterface::get_basic_entity_data_ptr
virtual boost::shared_ptr< BasicEntityData > & get_basic_entity_data_ptr()=0
Get pointer to basic entity data.
MoFEM::CoreTmp< 0 >::get_th_RefParentHandle
Tag get_th_RefParentHandle() const
Definition: Core.hpp:197
MOFEM_LOG_SYNCHRONISE
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
Definition: LogManager.hpp:345
MoFEM::CoreTmp< 0 >::get_th_RefBitLevel
Tag get_th_RefBitLevel() const
Definition: Core.hpp:198
MoFEM::FieldEntity::getLoBitNumberUId
static UId getLoBitNumberUId(const FieldBitNumber bit_number)
Definition: FieldEntsMultiIndices.hpp:222
MoFEM::CoreInterface::get_comm_size
virtual int get_comm_size() const =0
MoFEM::CoreInterface::get_field_ents
virtual const FieldEntity_multiIndex * get_field_ents() const =0
Get the field ents object.
get_skin
static auto get_skin(MoFEM::Interface &m_field, Range body_ents)
Definition: EshelbianPlasticity.cpp:163
MoFEM::type_from_handle
auto type_from_handle(const EntityHandle h)
get type from entity handle
Definition: Templates.hpp:1898
i
FTensor::Index< 'i', SPACE_DIM > i
Definition: hcurl_divergence_operator_2d.cpp:27
field_name
constexpr auto field_name
Definition: poisson_2d_homogeneous.cpp:13
MoFEM::MeshsetsManager::getTags
MoFEMErrorCode getTags(int verb=-1)
get tags handlers used on meshsets
Definition: MeshsetsManager.cpp:247
MoFEM::CommInterface::synchroniseEntities
MoFEMErrorCode synchroniseEntities(Range &ent, std::map< int, Range > *received_ents, int verb=DEFAULT_VERBOSITY)
synchronize entity range on processors (collective)
Definition: CommInterface.cpp:26
v
const double v
phase velocity of light in medium (cm/ns)
Definition: initial_diffusion.cpp:40
Range
MoFEM::CommInterface::dEbug
bool dEbug
Definition: CommInterface.hpp:30
FTensor::dd
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
MoFEM::Types::CubitBCType
std::bitset< 32 > CubitBCType
Definition: Types.hpp:52
MOFEM_LOG
#define MOFEM_LOG(channel, severity)
Log.
Definition: LogManager.hpp:308
MoFEM::CommInterface::debug
static bool debug
Definition: CommInterface.hpp:23
MoFEM::CommInterface::CommInterface
CommInterface(const MoFEM::Core &core)
Definition: CommInterface.cpp:23
BLOCKSET
@ BLOCKSET
Definition: definitions.h:161
j
FTensor::Index< 'j', 3 > j
Definition: matrix_function.cpp:19
MOFEM_DATA_INCONSISTENCY
@ MOFEM_DATA_INCONSISTENCY
Definition: definitions.h:31
sdf_hertz_2d_axisymm_plane.d
float d
Definition: sdf_hertz_2d_axisymm_plane.py:4
MoFEM::FieldEntity::getHiBitNumberUId
static UId getHiBitNumberUId(const FieldBitNumber bit_number)
Definition: FieldEntsMultiIndices.hpp:228
MoFEM::CommInterface::makeEntitiesMultishared
MoFEMErrorCode makeEntitiesMultishared(const EntityHandle *entities, const int num_entities, const int owner_proc=0, int verb=DEFAULT_VERBOSITY)
make entities from proc 0 shared on all proc
Definition: CommInterface.cpp:654
MoFEM::CommInterface::cOre
MoFEM::Core & cOre
Definition: CommInterface.hpp:29
m
FTensor::Index< 'm', 3 > m
Definition: shallow_wave.cpp:80
MoFEM::Types::BitRefLevel
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
Definition: Types.hpp:40
MoFEMFunctionBeginHot
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:453
QUIET
@ QUIET
Definition: definitions.h:221
fun
auto fun
Function to approximate.
Definition: dg_projection.cpp:36
MoFEMFunctionReturn
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:429
MoFEM::CommInterface::sev
static Sev sev
Definition: CommInterface.hpp:24
MoFEMFunctionBegin
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:359