Page MenuHomec4science

dumper_restart.cc
No OneTemporary

File Metadata

Created
Sat, Jul 20, 03:23

dumper_restart.cc

/**
* @file dumper_restart.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date Wed Aug 20 16:58:08 2014
*
* @brief This dumper saves the state of the simulation
*
* @section LICENSE
*
* Copyright INRIA and CEA
*
* The LibMultiScale is a C++ parallel framework for the multiscale
* coupling methods dedicated to material simulations. This framework
* provides an API which makes it possible to program coupled simulations
* and integration of already existing codes.
*
* This Project was initiated in a collaboration between INRIA Futurs Bordeaux
* within ScAlApplix team and CEA/DPTA Ile de France.
* The project is now continued at the Ecole Polytechnique Fédérale de Lausanne
* within the LSMS/ENAC laboratory.
*
* This software is governed by the CeCILL-C license under French law and
* abiding by the rules of distribution of free software. You can use,
* modify and/ or redistribute the software under the terms of the CeCILL-C
* license as circulated by CEA, CNRS and INRIA at the following URL
* "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy,
* modify and redistribute granted by the license, users are provided only
* with a limited warranty and the software's author, the holder of the
* economic rights, and the successive licensors have only limited
* liability.
*
* In this respect, the user's attention is drawn to the risks associated
* with loading, using, modifying and/or developing or reproducing the
* software by the user in light of its specific status of free software,
* that may mean that it is complicated to manipulate, and that also
* therefore means that it is reserved for developers and experienced
* professionals having in-depth computer knowledge. Users are therefore
* encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or
* data to be ensured and, more generally, to use and operate it in the
* same conditions as regards security.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL-C license and that you accept its terms.
*
*/
/* ------------------------------------------------------------------------ */
#include "dumper_restart.hh"
#include "communicator.hh"
#include "lib_continuum.hh"
#include "lib_dd.hh"
#include "lib_md.hh"
#include "lm_common.hh"
#include "ref_point_data.hh"
#include <iomanip>
#include <mpi.h>
/* ------------------------------------------------------------------------ */
__BEGIN_LIBMULTISCALE__
/* ------------------------------------------------------------------------ */
//! local number of Dofs per proc. Only valid for root (rank = 0) processor
static std::vector<UInt> nb_local_per_proc;
//! buffer data used to gather information on the one that will write to disk.
//! Only valid for root
static std::vector<Real *> data_per_proc;
/* ------------------------------------------------------------------------ */
DumperRestart::DumperRestart(const std::string &name) : LMObject(name) {
nb_local_dofs = 0;
allocated_size = 0;
data = NULL;
text_flag = false;
}
/* ------------------------------------------------------------------------ */
DumperRestart::~DumperRestart() {
// if (lm_my_proc_id == 0){
// //liberation de la memoire que je veux pas maintenir en parallel
// DUMP("freeing data_per_proc",DBG_INFO);
// for (UInt i = 1 ; i < lm_world_size ; ++i){
// DUMP("freeing ptr[" << i << "] " << data_per_proc[i],DBG_INFO);
// if (data_per_proc[i] != NULL){
// delete (data_per_proc[i]);
// data_per_proc[i] = NULL;
// }
// }
// nb_local_per_proc.clear();
// data_per_proc.clear();
// requests.clear();
// }
// if (data) delete(data);
}
/* ------------------------------------------------------------------------ */
void DumperRestart::initVectors(CommGroup &group) {
UInt my_rank = group.getMyRank();
UInt group_size = group.size();
if (my_rank == 0) {
nb_local_per_proc.resize(group_size);
data_per_proc.resize(group_size);
nb_local_per_proc.assign(group_size, 0);
data_per_proc.assign(group_size, 0);
for (UInt i = 0; i < group_size; ++i)
data_per_proc[i] = NULL;
}
}
/* ------------------------------------------------------------------------ */
template <typename Cont> void DumperRestart::dump(Cont &cont) {
CommGroup &group = cont.getCommGroup();
this->initVectors(group);
UInt my_rank = group.getMyRank();
UInt group_size = group.size();
// MPI_Comm mpi_group = comm.getMpiGroup(group);
// UInt real_rank = group.absoluteRank(0);
// UInt mpi_root_rank = comm.real2groupRank(real_rank, group);
constexpr UInt Dim = Cont::Dim;
LMFile file;
UInt nbTotalDofs = 0;
if (my_rank == 0) {
std::stringstream temp;
temp << this->getBaseName() << "_restart-" << std::setfill('0')
<< std::setw(4) << this->action_step << ".xml";
file.open(temp.str(), "wb", true);
b64.setOutputFile(file);
}
bool need_reallocate = false;
if (allocated_size < cont.size() && cont.size() != 0)
need_reallocate = true;
nb_local_dofs = cont.size();
group.gather(&nb_local_dofs, 1, &nb_local_per_proc[0], 0,
"gather nb local dofs");
DUMP("Gather done", DBG_INFO);
if (my_rank == 0) {
for (UInt i = 0; i < group_size; ++i) {
DUMP("nb_local[" << i << "]=" << nb_local_per_proc[i] << " "
<< nb_local_dofs,
DBG_INFO);
nbTotalDofs += nb_local_per_proc[i];
}
printHeaders(nbTotalDofs, Dim, file);
}
// allocation des array de stockage
if (need_reallocate) {
allocated_size = nb_local_dofs;
DUMP("(re)allocating for size = " << nb_local_dofs, DBG_INFO);
if (data != NULL)
data = (Real *)realloc(data, nb_local_dofs * sizeof(Real) * Dim);
else {
data = (Real *)malloc(nb_local_dofs * sizeof(Real) * Dim);
memset(data, 0, sizeof(Real) * nb_local_dofs * Dim);
}
}
if (my_rank == 0) {
// je switch le pointeur pour les donnees locales
data_per_proc[0] = data;
for (UInt i = 1; i < group_size; ++i) {
if (nb_local_per_proc[i] == 0)
continue;
if (data_per_proc[i] != NULL)
data_per_proc[i] = (Real *)realloc(
data_per_proc[i], sizeof(Real) * nb_local_per_proc[i] * Dim);
else {
data_per_proc[i] =
(Real *)malloc(sizeof(Real) * nb_local_per_proc[i] * Dim);
memset(data_per_proc[i], 0, sizeof(Real) * nb_local_per_proc[i] * Dim);
}
}
}
// chaqun construit en parallele les data qu'il veut envoyer
UInt cpt = 0;
for (auto &&at : cont) {
auto X = at.position0();
for (UInt i = 0; i < Dim; ++i)
data[cpt * Dim + i] = X[i];
++cpt;
}
DUMP("a la fin cpt = " << cpt, DBG_INFO);
DUMP("local P0 construction done", DBG_INFO);
DumpField<Dim>("P0", file, group);
cpt = 0;
for (auto &&at : cont) {
auto U = at.displacement();
for (UInt i = 0; i < Dim; ++i)
data[cpt * Dim + i] = U[i];
++cpt;
}
DUMP("local U construction done", DBG_INFO);
DumpField<Dim>("U", file, group);
cpt = 0;
for (auto &&at : cont) {
auto V = at.velocity();
for (UInt i = 0; i < Dim; ++i)
data[cpt * Dim + i] = V[i];
++cpt;
}
DUMP("local V construction done", DBG_INFO);
DumpField<Dim>("V", file, group);
// on fait le champ de position P0
// je rassemble le tout en local
if (my_rank == 0) {
printTail(file);
file.close();
}
group.synchronize();
}
/* ------------------------------------------------------------------------ */
template <UInt Dim>
inline void DumperRestart::DumpField(const std::string &fieldName, LMFile &file,
CommGroup &group) {
UInt group_size = group.size();
UInt my_rank = group.getMyRank();
// MPI_Comm mpi_group = comm.getMpiGroup(group);
// MPI_Status status;
if (my_rank == 0) {
// I switch the pointer for local data
for (UInt i = 1; i < group_size; ++i) {
if (nb_local_per_proc[i] == 0)
continue;
DUMP("pending recv from " << i << " of size " << nb_local_per_proc[i]
<< " ...",
DBG_INFO);
group.receive(data_per_proc[i], nb_local_per_proc[i] * Dim, i,
"restart data per proc");
DUMP("pending recv from " << i << " of size " << nb_local_per_proc[i]
<< " ... done",
DBG_INFO);
}
} else if (nb_local_dofs != 0) {
DUMP("sending to root " << nb_local_dofs << " ...", DBG_INFO);
group.send(data, nb_local_dofs * Dim, 0, "restart data per proc");
DUMP("sending to root " << nb_local_dofs << " ... done", DBG_INFO);
}
if (my_rank == 0) {
if (!text_flag)
b64.clearBuffer();
file.printf("<%s>\n", fieldName.c_str());
for (int i = group_size - 1; i > -1; --i) {
DUMP("waiting com from " << i, DBG_INFO);
// attend les coms avant d'ecrire sur disque
if (i > 0 && nb_local_per_proc[i] > 0) {
LM_TOIMPLEMENT;
// MPI_Wait(&requests[i], &status);
}
DUMP("reception from " << i << " complete", DBG_INFO);
for (UInt j = 0; j < nb_local_per_proc[i]; ++j) {
if (text_flag) {
for (UInt k = 0; k < Dim; ++k) {
file.printf("%.15e", data_per_proc[i][j * Dim + k]);
if (k != Dim - 1)
file.printf("\t");
}
file.printf("\n");
} else {
for (UInt k = 0; k < Dim; ++k) {
b64.pushRealInBase64(data_per_proc[i][j * Dim + k]);
}
}
}
}
if (!text_flag) {
b64.finish();
b64.dumpToFile();
}
file.printf("</%s>\n", fieldName.c_str());
}
}
/* ------------------------------------------------------------------------ */
void DumperRestart::printHeaders(UInt nbDofs, const UInt Dim, LMFile &file) {
file.printf("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
file.printf("<SimulationData nbDofs=\"%d\" dim=\"%d\" timestep=\"%d\"",
nbDofs, Dim, current_step);
if (text_flag == true)
file.printf(" dataType=\"TEXT\">\n");
else
file.printf(" dataType=\"BINARY\">\n");
}
/* ------------------------------------------------------------------------ */
void DumperRestart::printTail(LMFile &file) {
file.printf("</SimulationData>\n");
}
/* ------------------------------------------------------------------------ */
/* LMDESC RESTART
This dumper saves the state of the simulation in order to allow
restarting
simulations from
*/
/* LMEXAMPLE DUMPER res RESTART INPUT md PREFIX /home/titeuf */
/* LMHERITANCE dumper */
void DumperRestart::declareParams() {
DumperInterface::declareParams();
/* LMKEYWORD TEXT
Flag to request human-readable text output instead of binary.
*/
this->parseTag("TEXT", text_flag, false);
}
/* ------------------------------------------------------------------------ */
DECLARE_DUMPER_MAKE_CALL(DumperRestart);
__END_LIBMULTISCALE__

Event Timeline