Page MenuHomec4science

domain_multiscale.cc
No OneTemporary

File Metadata

Created
Sat, May 18, 04:49

domain_multiscale.cc

/**
* @file domain_multiscale.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date Wed Jul 02 16:25:38 2014
*
* @brief This is a meta domain whose purpose is to handle other domains
*
* @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 <boost/preprocessor.hpp>
/* -------------------------------------------------------------------------- */
#include "action_interface.hh"
#include "coupler_manager.hh"
#include "domain_multiscale.hh"
#include "factory_multiscale.hh"
#include "filter_interface.hh"
#include "geometry_manager.hh"
#include "lib_continuum.hh"
#include "lib_dd.hh"
#include "lib_md.hh"
#include "lm_common.hh"
#include "lm_communicator.hh"
#include "lm_parser.hh"
/* -------------------------------------------------------------------------- */
__BEGIN_LIBMULTISCALE__
DomainMultiScale::~DomainMultiScale() {}
/* -------------------------------------------------------------------------- */
DomainMultiScale::DomainMultiScale() : LMObject("DomainMultiscale") {}
/* -------------------------------------------------------------------------- */
void DomainMultiScale::coupling(CouplingStage stage) {
#ifdef LIBMULTISCALE_USE_EPSN
if (epsn_itfc->isNodeInitialized())
epsn_itfc->beginTask("updatecoupling");
#endif
CouplerManager::getManager().coupling(stage);
#ifdef LIBMULTISCALE_USE_EPSN
if (epsn_itfc->isNodeInitialized())
epsn_itfc->endTask("updatecoupling");
#endif
}
/* -------------------------------------------------------------------------- */
UInt DomainMultiScale::build(const std::string &config) {
Parser::parseConfigFile(config, "MultiScale", "", (*this));
// if (action_manager) action_manager->init();
// if (filter) filter->init();
Communicator::getGroup("all").synchronize();
#ifdef LIBMULTISCALE_USE_EPSN
UInt epsn_status = 0;
// EPSN Ready
DUMP("EPSN is going to be READY...");
epsn_status = epsn_itfc->ready();
if (!epsn_status) {
FATAL("error on EPSN Node ready operation\n");
}
DUMP("EPSN READY");
// the main loop
DUMP("EPSN Begin HTG");
epsn_itfc->beginHTM();
epsn_itfc->beginLoop("main");
DUMP("simulation ready to start for EPSN");
#endif
return Dim;
}
/* -------------------------------------------------------------------------- */
#define BOOST_PARSE_MODEL(keyword, class, dim) \
DUMPFILE(Parser::fout, "trying to create class " \
<< stringify_macro(class) \
<< " while dimension is " << Dim << " dim is " \
<< dim << " key is " << key << " keyword is " \
<< keyword); \
if (key == keyword && dim == Dim) { \
if (Communicator::getCommunicator().getNbGroups() == 0) \
LM_FATAL("PROCESSOR KEYWORD SHOULD BE USED ON ID " << ID); \
auto &dom_group = Communicator::getCommunicator().getGroup(ID); \
model = std::make_shared<class>(ID, dom_group); \
Parser::parseConfigFile(config_file, keyword, ID, *model); \
DUMP("Loading of config file ... done", DBG_INFO_STARTUP); \
if (model == NULL) \
LM_FATAL("Could not instanciate the model: " \
<< " conf line was " << line.str()); \
model->checkAllKeywordsAreParsed(); \
model->init(); \
addObject(model); \
DUMPFILE(Parser::fout, \
"creation of " << stringify_macro(class) << " successful"); \
\
return true; \
}
#define BOOST_PARSE_MODEL_KEY(n, data, class) \
BOOST_PARSE_MODEL(stringify_macro(BOOST_PP_TUPLE_ELEM(3, 2, class)), \
BOOST_PP_TUPLE_ELEM(3, 0, class), \
BOOST_PP_TUPLE_ELEM(3, 1, class))
/* -------------------------------------------------------------------------- */
UInt DomainMultiScale::parseLineModel(std::stringstream &line) {
// first of all check if the communicator is already set correctly
try {
Communicator &myComm __attribute__((unused)) =
Communicator::getCommunicator();
} catch (LibMultiScaleException &e) {
if (lm_world_size == 1)
Communicator::createCommunicator();
else
LM_THROW(
"Communicator was not set: "
<< " before MODEL keyword the COM keyword should have been used");
}
std::string key, config_file;
std::shared_ptr<DomainInterface> model;
LMID ID = invalidDomain;
// parse the keyword of the model
Parser::parse(key, line);
// parse the ID of the model
Parser::parse(ID, line);
// parse the config file of the model
try {
Parser::parse(config_file, line);
} catch (LibMultiScaleException &e) {
config_file = Parser::getCurrentConfigFile();
}
BOOST_PP_SEQ_FOR_EACH(BOOST_PARSE_MODEL_KEY, f, LIST_ATOM_MODEL)
BOOST_PP_SEQ_FOR_EACH(BOOST_PARSE_MODEL_KEY, f, LIST_CONTINUUM_MODEL)
BOOST_PP_SEQ_FOR_EACH(BOOST_PARSE_MODEL_KEY, f, LIST_DD_MODEL)
LM_FATAL("Unknown Model type " << key
<< " maybe you should compile support "
"for this plugin ? or check the "
"dimension required ?");
return false;
}
/* -------------------------------------------------------------------------- */
/* LMDESC MultiScale Section (toplevel domain)
This section describe the most general keyword that
can be used. It allows to specify general values
of the simulation to be run.
*/
/* LMSYNTAX TODO */
/* LMEXAMPLE TODO */
ParseResult DomainMultiScale::setParam(const std::string &key,
std::stringstream &line) {
if (key == "MD_CODE" or key == "ELAST_CODE" or key == "DD_CODE")
return parseLineModel(line);
/* LMKEYWORD MODEL String Integer config_file(current_file)
Declare a new domain to be created based on the
plugins compiled. Up to now the possible models are:
- LAMMPS
- MD1D
- MECA1D
- AKANTU
- PARADIS
*/
else if (key == "MODEL")
return parseLineModel(line);
/* LMKEYWORD COUPLING_CODE ARG
TODO
*/
else if (key == "COUPLING_CODE") {
return CouplerManager::getManager().parseCouplingLine(line, Dim);
}
/* LMKEYWORD GEOMETRY ARG
TODO
*/
else if (key == "GEOMETRY") {
if (!GeometryManager::allocated())
LM_FATAL("Please use DIMENSION keyword before"
<< Parser::getParserState());
return GeometryManager::getManager().parseLine(line, Dim);
}
/* LMKEYWORD DIMENSION Integer
TODO
*/
else if (key == "DIMENSION") {
Parser::parse((UInt &)Dim, line);
spatial_dimension = Dim;
DUMP("parsing DIMENSION commande = " << Dim, DBG_INFO_STARTUP);
ActionManager::getManager();
FilterManager::getManager();
CouplerManager::getManager();
GeometryManager::getManager();
return true;
}
/* LMKEYWORD DUMPER String
TODO
\ref{dumpersSection}
*/
else if (key == "DUMPER") {
if (!ActionManager::allocated())
LM_FATAL("Please use DIMENSION keyword before"
<< Parser::getParserState());
return ActionManager::getManager().parseActionLine(line, at_dumper);
}
/* LMKEYWORD FILTER String
TODO
\ref{filterSection}
*/
else if (key == "FILTER") {
if (!FilterManager::allocated())
LM_FATAL("Please use DIMENSION keyword before"
<< Parser::getParserState());
return FilterManager::getManager().parseActionLine(line, at_filter);
}
else if (key == "COMPUTE") {
if (!FilterManager::allocated())
LM_FATAL("Please use DIMENSION keyword before"
<< Parser::getParserState());
return FilterManager::getManager().parseActionLine(line, at_compute);
}
/* LMKEYWORD STIMULATION String
TODO
\ref{stimulatorsSection}
*/
else if (key == "STIMULATION") {
if (!ActionManager::allocated())
LM_FATAL("Please use DIMENSION keyword before"
<< Parser::getParserState());
return ActionManager::getManager().parseActionLine(line, at_stimulator);
}
/* LMKEYWORD UNITCODE String
TODO
*/
else if (key == "UNITCODE") {
DUMP("parsing UNITCODE commande = " << line.str(), DBG_INFO_STARTUP);
Parser::parse(code_unit_system, line);
Parser::units_converter.setOutUnits(code_unit_system);
Parser::units_converter.computeConversions();
if (lm_my_proc_id == 0)
code_unit_system.print();
return true;
}
/* LMKEYWORD PROCESSORS Integer Integer
TODO
*/
else if (key == "PROCESSORS") {
LMID id;
Parser::parse(id, line);
UInt nb_procs = 0;
Parser::parse(nb_procs, line);
if (nb_procs == 0)
LM_FATAL("a group cannot be constituted of zero processors");
DUMPFILE(Parser::fout, "parsing " << key
<< "( Integer , Integer ) with value "
<< id << " " << nb_procs);
try {
Communicator::getCommunicator().addGroup(id, nb_procs);
} catch (LibMultiScaleException &e) {
LM_FATAL_RE(e, "COM keyword should be used before the PROCESSOR keyword");
}
return true;
}
/* LMKEYWORD COM String
TODO
*/
else if (key == "COM") {
std::string mot;
Parser::parse(mot, line);
Communicator::createCommunicator();
return true;
}
// /* LMKEYWORD GLOBAL_TIMESTEP Time
// TODO
// */
// else if (key == "GLOBAL_TIMESTEP") {
// Real dt;
// Parser::parse(dt, line);
// this->setTimeStep(dt);
// DUMPBYPROC("changing global timestep to " << dt, DBG_MESSAGE, 0);
// return true;
// }
// /* LMKEYWORD SET_CURRENT_STEP Integer
// TODO
// */
// else if (key == "SET_CURRENT_STEP") {
// UInt ts;
// Parser::parse(ts, line);
// this->setCurrentStep(ts);
// DUMPBYPROC("changing current timestep to " << ts, DBG_MESSAGE, 0);
// return true;
// }
/* LMKEYWORD RESTART_FILE String
TODO
*/
else if (key == "RESTART_FILE") {
LMID domainID;
Parser::parse(domainID, line);
std::string mot;
Parser::parse(mot, line);
DUMP("reloading file " << mot << " for domain " << domainID, DBG_MESSAGE);
if (getSharedObject(domainID)) {
if (Communicator::getGroup(domainID).amIinGroup())
getSharedObject(domainID)->readXMLFile(mot);
} else
LM_FATAL("there is no domain with ID " << domainID);
return true;
}
Communicator::getGroup("all").synchronize();
return false;
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<DomainInterface> DomainMultiScale::getModelByNumber(UInt i) {
auto iest_domain = std::next(insert_order.begin(), i);
return shared_pointer_objects[*iest_domain];
}
/* -------------------------------------------------------------------------- */
UInt DomainMultiScale::getNbModels() { return objects.size(); }
/* -------------------------------------------------------------------------- */
#define DOMAINLOOP(inloop) \
\
for (auto &obj : objects) { \
if (Communicator::getGroup(obj.first).amIinGroup()) \
inloop; \
}
#define DEFINE_RETURN_REAL_FUNCTION_BYSUM(name) \
Real DomainMultiScale::name() { \
Real res = 0; \
DOMAINLOOP(res += obj.second->name()) \
return res; \
}
/* -------------------------------------------------------------------------- */
Component &getRegisteredComponent(const std::string &component_name) {
auto managers = std::forward_as_tuple(
DomainMultiScale::getManager(), FilterManager::getManager(),
CouplerManager::getManager(), ActionManager::getManager());
Component *ptr = nullptr;
int found = 0;
auto find_comp = [&](auto &manager) {
try {
auto &component = manager.getObject(component_name);
ptr = &component;
++found;
} catch (UnknownID &e) {
}
};
std::apply([&](auto &&... manager) { (find_comp(manager), ...); }, managers);
if (found > 1) {
LM_FATAL("several components are registered with the name: "
<< component_name << " " << ptr);
}
if (not ptr) {
LM_THROW("component " << component_name << " cannot be found" << std::endl);
}
return *ptr;
}
/* -------------------------------------------------------------------------- */
OutputContainer getRegisteredOutput(const std::string &name) {
std::string component_name = name;
std::string output_name = "";
auto pos = component_name.find(".");
if (pos != std::string::npos) {
output_name = component_name.substr(pos + 1);
component_name = component_name.substr(0, pos);
}
auto &comp = getRegisteredComponent(component_name);
if (output_name != "")
return comp.evalOutput(output_name);
OutputContainer out;
out = comp;
return out;
}
/* -------------------------------------------------------------------------- */
template <>
std::unique_ptr<IDManager<DomainInterface>>
IDManager<DomainInterface>::static_pointer = NULL;
/* -------------------------------------------------------------------------- */
__END_LIBMULTISCALE__

Event Timeline