Page MenuHomec4science

compute_interface.cc
No OneTemporary

File Metadata

Created
Fri, Jul 26, 19:37

compute_interface.cc

/**
* @file compute.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Jaehyun Cho <jaehyun.cho@epfl.ch>
* @author Moseley Philip Arthur <philip.moseley@epfl.ch>
*
* @date Wed Jul 09 21:59:47 2014
*
* @brief This is the mother class of all computes
*
* @section LICENSE
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* LibMultiScale 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.
*
* LibMultiScale 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 LibMultiScale. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "lib_continuum.hh"
#include "lib_dd.hh"
#include "lib_dumper.hh"
#include "lib_filter.hh"
#include "lib_md.hh"
#include "lib_stimulation.hh"
#include "lm_common.hh"
/* -------------------------------------------------------------------------- */
__BEGIN_LIBMULTISCALE__
/* -------------------------------------------------------------------------- */
UInt ComputeInterface::getTotalNbData(UInt root_rank) {
CommGroup &group = this->getCommGroup();
UInt nb_data = this->getOutputAsArray().size();
group.reduce(&nb_data, 1, "reduce total number of data element", OP_SUM,
root_rank);
return nb_data;
}
/* -------------------------------------------------------------------------- */
ContainerArray<Real> &ComputeInterface::gatherAllData(UInt root_rank) {
CommGroup &group = this->getCommGroup();
UInt my_rank = group.getMyRank();
UInt nb_data = this->getOutputAsArray().size();
std::vector<UInt> nb_data_per_proc;
#ifndef LM_OPTIMIZED
UInt total_data = this->getTotalNbData(root_rank);
group.synchronize();
#endif // LM_OPTIMIZED
gather_flag = true;
gather_root_proc = root_rank;
LM_TOIMPLEMENT;
// group.allGather()
if (root_rank == my_rank) {
// prepare the array to resizes the sizes
UInt nb_procs = group.size();
DUMP("receive " << nb_procs << " procs", DBG_INFO);
DUMP("my rank is " << my_rank, DBG_INFO);
nb_data_per_proc.resize(nb_procs);
for (UInt p = 0; p < nb_procs; ++p) {
if (p == my_rank)
nb_data_per_proc[p] = nb_data;
else {
DUMP("receive from proc " << p, DBG_INFO);
group.receive(&nb_data_per_proc[p], 1, p, "gatherData: receive number");
}
}
// compute total size of the gathered data
UInt tot_size = 0;
for (UInt p = 0; p < nb_procs; ++p) {
DUMP("nb_data_per_proc[" << p << "]=" << nb_data_per_proc[p], DBG_INFO);
tot_size += nb_data_per_proc[p];
}
#ifndef LM_OPTIMIZED
LM_ASSERT(total_data == tot_size, "mismatched of global sizes");
#endif // LM_OPTIMIZED
// resize the receiving buffer
data_gather.resize(tot_size);
// receive the data from the other processors
UInt offset = 0;
for (UInt p = 0; p < nb_procs; ++p) {
// if p is my_rank/root_rank copy the data
if (p == my_rank) {
for (UInt i = 0; i < nb_data; ++i) {
data_gather[offset + i] = this->getOutputAsArray()[i];
}
}
// else receive from distant proc
else if (nb_data_per_proc[p]) {
group.receive(&data_gather[offset], nb_data_per_proc[p], p,
"gatherData: receive data");
}
// increment the offset
offset += nb_data_per_proc[p];
}
} else {
DUMP("send my nb_data = " << nb_data, DBG_INFO);
// send the amount of data I have
group.send(&nb_data, 1, root_rank, "gatherData: send number");
// if there is data to be sent : do so
if (nb_data != 0)
group.send(static_cast<ContainerArray<Real> &>(this->getOutputAsArray()),
root_rank, "gatherData: send data");
}
return data_gather;
}
/* -------------------------------------------------------------------------- */
ContainerArray<Real> &ComputeInterface::gatherData(UInt source_rank,
UInt root_rank) {
CommGroup &group = this->getCommGroup();
UInt my_rank = group.getMyRank();
UInt nb_data = this->getOutputAsArray().size();
if (root_rank == my_rank) {
if (source_rank == root_rank)
return this->getOutputAsArray();
group.receive(&nb_data, 1, source_rank, "gatherData: receive number");
if (nb_data != 0) {
data_gather.resize(this->getOutputAsArray().size());
group.receive(data_gather, source_rank, "gatherData: receive data");
}
} else if (source_rank == my_rank) {
group.send(&nb_data, 1, root_rank, "gatherData: send number");
if (nb_data != 0) {
group.send(static_cast<ContainerArray<Real> &>(this->getOutputAsArray()),
root_rank, "gatherData: send data");
}
}
return data_gather;
}
/* -------------------------------------------------------------------------- */
ContainerArray<Real> &ComputeInterface::allGatherAllData() {
CommGroup &group = this->getCommGroup();
int localSize = this->getOutputAsArray().size();
UInt np = group.size();
rcnts.resize(np);
std::vector<UInt> rcntscnts(np, 1), displs(np);
for (UInt i = 0; i < np; ++i)
displs[i] = i;
group.allGatherv(&localSize, 1, rcnts.data(), rcntscnts,
"allgatherv for compute interface");
UInt globalSize = 0;
for (UInt i = 0; i < np; ++i) {
displs[i] = globalSize;
globalSize += rcnts[i];
}
data_gather.resize(globalSize);
LM_TOIMPLEMENT;
// group.allGatherv(&static_cast<std::vector<Real> &>(*this)[0], localSize,
// &data_gather[0], &rcnts[0], &displs[0],
// "allgatherv for compute interface");
return data_gather;
}
/* -------------------------------------------------------------------------- */
ComputeInterface::ComputeInterface() : LMObject("ComputeInterface") {
this->comm_group = nullptr;
}
/* -------------------------------------------------------------------------- */
ComputeInterface::~ComputeInterface() {
gather_flag = false;
gather_root_proc = 0;
}
/* -------------------------------------------------------------------------- */
__END_LIBMULTISCALE__

Event Timeline