Page MenuHomec4science

global_ids_updater.cc
No OneTemporary

File Metadata

Created
Mon, Dec 2, 19:45

global_ids_updater.cc

/**
* Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*/
/* -------------------------------------------------------------------------- */
#include "global_ids_updater.hh"
#include "element_synchronizer.hh"
#include "mesh_accessor.hh"
#include "mesh_utils.hh"
/* -------------------------------------------------------------------------- */
#include <numeric>
/* -------------------------------------------------------------------------- */
namespace akantu {
Int GlobalIdsUpdater::updateGlobalIDs(Int local_nb_new_nodes) {
if (mesh.getCommunicator().getNbProc() == 1) {
return local_nb_new_nodes;
}
auto total_nb_new_nodes = this->updateGlobalIDsLocally(local_nb_new_nodes);
if (mesh.isDistributed()) {
this->synchronizeGlobalIDs();
}
return total_nb_new_nodes;
}
Int GlobalIdsUpdater::updateGlobalIDsLocally(Int local_nb_new_nodes) {
const auto & comm = mesh.getCommunicator();
auto nb_proc = comm.getNbProc();
if (nb_proc == 1) {
return local_nb_new_nodes;
}
/// resize global ids array
MeshAccessor mesh_accessor(mesh);
auto && nodes_global_ids = mesh_accessor.getNodesGlobalIds();
auto old_nb_nodes = mesh.getNbNodes() - local_nb_new_nodes;
nodes_global_ids.resize(mesh.getNbNodes(), -1);
auto && local_or_master_pred = [this](auto && n) {
return this->mesh.isLocalOrMasterNode(n);
};
Vector<Int, 2> local_master_nodes(Vector<Int, 2>::Zero());
/// compute the number of global nodes based on the number of old nodes
auto range_old = arange(old_nb_nodes);
local_master_nodes(0) =
std::count_if(range_old.begin(), range_old.end(), local_or_master_pred);
/// compute amount of local or master doubled nodes
auto range_new = arange(old_nb_nodes, mesh.getNbNodes());
local_master_nodes(1) =
std::count_if(range_new.begin(), range_new.end(), local_or_master_pred);
auto starting_index = local_master_nodes(1);
comm.allReduce(local_master_nodes);
auto old_global_nodes = local_master_nodes(0);
auto total_nb_new_nodes = local_master_nodes(1);
if (total_nb_new_nodes == 0) {
return 0;
}
/// set global ids of local and master nodes
comm.exclusiveScan(starting_index);
starting_index += old_global_nodes;
for (auto n : range_new) {
if (mesh.isLocalOrMasterNode(n)) {
nodes_global_ids(n) = starting_index;
++starting_index;
}
}
mesh_accessor.setNbGlobalNodes(old_global_nodes + total_nb_new_nodes);
return total_nb_new_nodes;
}
void GlobalIdsUpdater::synchronizeGlobalIDs() {
this->reduce = true;
this->synchronizer->slaveReductionOnce(*this,
SynchronizationTag::_giu_global_conn);
#ifndef AKANTU_NDEBUG
for (auto node : nodes_flags) {
auto node_flag = mesh.getNodeFlag(node.first);
if (node_flag != NodeFlag::_pure_ghost) {
continue;
}
auto n = 0U;
for (auto & pair : node.second) {
if (std::get<1>(pair) == NodeFlag::_pure_ghost) {
++n;
}
}
if (n == node.second.size()) {
AKANTU_DEBUG_WARNING(
"The node " << n << "is ghost on all the neighboring processors");
}
}
#endif
this->reduce = false;
this->synchronizer->synchronizeOnce(*this,
SynchronizationTag::_giu_global_conn);
}
} // namespace akantu

Event Timeline