Page MenuHomec4science

domain_multiscale.cc
No OneTemporary

File Metadata

Created
Sun, May 26, 14:23

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 "lm_common.hh"
#include "lib_continuum.hh"
#include "lib_md.hh"
#include "lib_dd.hh"
#include "domain_multiscale.hh"
#include "filter_manager.hh"
#include "action_manager.hh"
#include "communicator_unity.hh"
#include "communicator_mpi_linear.hh"
#include "coupler_manager.hh"
#include "geometry_manager.hh"
#include "lm_parser.hh"
/* -------------------------------------------------------------------------- */
__BEGIN_LIBMULTISCALE__
DomainMultiScale::~DomainMultiScale(){
filter->destroy();
action_manager->destroy();
dom_group.clear();
if(coupler_manager) delete (coupler_manager);
}
/* -------------------------------------------------------------------------- */
DomainMultiScale::DomainMultiScale():
IDManager<DomainInterface,DomainMultiScale>("Domains") {
action_manager = NULL;
filter = NULL;
multi_step = 1;
}
/* -------------------------------------------------------------------------- */
UInt DomainMultiScale::getCurrentStep(){
UInt res = UINT_MAX;
std::map<DomainID,DomainInterface *>::iterator courant = objects.begin();
std::map<DomainID,DomainInterface *>::iterator dernier = objects.end();
while (courant != dernier){
if (Communicator::getCommunicator().amIinGroup(dom_group[(*courant).first]))
res = (*courant).second->getCurrentStep();
++courant;
}
return res;
}
/* -------------------------------------------------------------------------- */
Real DomainMultiScale::getTimeStep(){
Real res = -1;
std::map<DomainID,DomainInterface *>::iterator courant = objects.begin();
std::map<DomainID,DomainInterface *>::iterator dernier = objects.end();
while (courant != dernier){
if (Communicator::getCommunicator().amIinGroup(dom_group[(*courant).first]))
res = (*courant).second->getTimeStep();
++courant;
}
return res;
}
/* -------------------------------------------------------------------------- */
void DomainMultiScale::coupling(CouplingStage stage){
#ifdef LIBMULTISCALE_USE_EPSN
if (epsn_itfc->isNodeInitialized())
epsn_itfc->beginTask("updatecoupling");
#endif
coupler_manager->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::getCommunicator().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;
}
/* -------------------------------------------------------------------------- */
void DomainMultiScale::build_indexes(){
if (dom_indexes.size()==0){
/* create index for domains */
std::map<DomainID,DomainInterface *>::iterator courant = objects.begin();
std::map<DomainID,DomainInterface *>::iterator dernier = objects.end();
while (courant != dernier){
DUMP("pushing ID " << (*courant).first,DBG_INFO);
dom_indexes.push_back((*courant).first);
++courant;
}
}
}
/* -------------------------------------------------------------------------- */
Real DomainMultiScale::getFMax(){
Real res = -1e300;
std::map<DomainID,DomainInterface *>::iterator courant = objects.begin();
std::map<DomainID,DomainInterface *>::iterator dernier = objects.end();
while (courant != dernier){
if (Communicator::getCommunicator().amIinGroup(dom_group[(*courant).first]))
res = std::max(res,(*courant).second->getFMax());
++courant;
}
return res;
}
/* -------------------------------------------------------------------------- */
Real DomainMultiScale::getDirMax(){
Real res = -1e300;
std::map<DomainID,DomainInterface *>::iterator courant = objects.begin();
std::map<DomainID,DomainInterface *>::iterator dernier = objects.end();
while (courant != dernier){
if (Communicator::getCommunicator().amIinGroup(dom_group[(*courant).first]))
res = std::max(res,(*courant).second->getDirMax());
++courant;
}
return res;
}
/* -------------------------------------------------------------------------- */
#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 (lm_world_size == 1) \
dom_group[ID] = 0; \
if (dom_group.count(ID) == 0) \
LM_FATAL("PROCESSOR KEYWORD SHOULD BE USED ON ID " << ID); \
model = new class(ID,dom_group[ID]); \
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<UnityMPI>();
else LM_THROW("Communicator was not set: " <<
" before MODEL keyword the COM keyword should have been used");
}
std::string key, config_file;
DomainInterface * model = NULL;
DomainID 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") return parseLineModel(line);
else if(key == "ELAST_CODE") return parseLineModel(line);
else if(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:
\begin{itemize}
\item LAMMPS
\item MD1D
\item MECA1D
\item SIMULPACK
\item LIBMESH
\end{itemize}
More to come in future (Akantu). \\
*/
else if(key == "MODEL") return parseLineModel(line);
/* LMKEYWORD COUPLING_CODE ARG
TODO
*/
else if(key == "COUPLING_CODE"){
if (!coupler_manager)
LM_FATAL("Please use DIMENSION keyword before"
<< Parser::getParserState());
return coupler_manager->parseLine(line,Dim);
}
/* LMKEYWORD GEOMETRY ARG
TODO
*/
else if(key == "GEOMETRY"){
if (!geometry_manager)
LM_FATAL("Please use DIMENSION keyword before"
<< Parser::getParserState());
return geometry_manager->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);
action_manager = ActionManager::getManager(Dim);
filter = FilterManager::getManager(Dim);
geometry_manager = &GeometryManager::getManager();
coupler_manager = new CouplerManager();
return true;
}
/* LMKEYWORD DUMPER String
TODO
\ref{dumpersSection}
*/
else if(key == "DUMPER"){
if (!action_manager)
LM_FATAL("Please use DIMENSION keyword before"
<< Parser::getParserState());
return action_manager->parseLine(line,at_dumper);
}
/* LMKEYWORD FILTER String
TODO
\ref{filterSection}
*/
else if(key == "FILTER"){
if (!filter)
LM_FATAL("Please use DIMENSION keyword before"
<< Parser::getParserState());
return filter->parseLine(line,at_filter);
}
else if(key == "COMPUTE"){
if (!filter)
LM_FATAL("Please use DIMENSION keyword before"
<< Parser::getParserState());
return filter->parseLine(line,at_compute);
}
/* LMKEYWORD STIMULATION String
TODO
\ref{stimulatorsSection}
*/
else if(key == "STIMULATION"){
if (!action_manager)
LM_FATAL("Please use DIMENSION keyword before"
<< Parser::getParserState());
return action_manager->parseLine(line,at_stimulator);
}
/* LMKEYWORD UNITCODE String
TODO
*/
else if(key == "UNITCODE"){
DUMP("parsing UNITCODE commande = " << line,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"){
DomainID 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 {
dom_group[id] = Communicator::getCommunicator().addGroup(nb_procs);
DUMP("model ID " << id << " got communication group " << dom_group[id],DBG_INFO_STARTUP);
}
catch (LibMultiScaleException & e){
LM_FATAL("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);
if (lm_world_size==1) Communicator::createCommunicator<UnityMPI>();
else if (mot == "DISTRIBUTED"){
Communicator::createCommunicator<LinearMPI>();
}
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"){
DomainID domainID;
Parser::parse(domainID,line);
std::string mot;
Parser::parse(mot,line);
DUMP("reloading file " << mot << " for domain " << domainID,DBG_MESSAGE);
if (getObject(domainID)){
if (Communicator::getCommunicator().amIinGroup(dom_group[domainID]))
getObject(domainID)->readXMLFile(mot);
}
else LM_FATAL("there is no domain with ID " << domainID);
return true;
}
Communicator::getCommunicator().synchronize();
return false;
}
/* -------------------------------------------------------------------------- */
DomainInterface * DomainMultiScale::getModelByNumber(UInt i){
build_indexes();
return objects[dom_indexes[i]];
}
/* -------------------------------------------------------------------------- */
UInt DomainMultiScale::getNbModels(){
return objects.size();
}
/* -------------------------------------------------------------------------- */
ActionManager & DomainMultiScale::getActionManager(){
if (action_manager == NULL) LM_FATAL("action manager was not created : "
<< "critical=>this should not append "
<< "have forgotten DIMENSION keyword ?");
return *action_manager;
}
/* -------------------------------------------------------------------------- */
#define DOMAINLOOP(inloop) \
std::map<DomainID,DomainInterface *>::iterator courant = objects.begin(); \
std::map<DomainID,DomainInterface *>::iterator dernier = objects.end(); \
while (courant != dernier){ \
if (Communicator::getCommunicator().amIinGroup(dom_group[(*courant).first])) \
inloop; \
++courant; \
} \
#define DEFINE_RETURN_REAL_FUNCTION_BYSUM(name) \
Real DomainMultiScale::name(){ \
Real res = 0; \
DOMAINLOOP(res += (*courant).second->name()) \
return res; \
}
#define DEFINE_CALL_TO_SUBFUNCTION(name) \
void DomainMultiScale::name(){ \
DOMAINLOOP((*courant).second->name()) \
}
#define DEFINE_CALL_TO_SUBFUNCTION_INTARG(name) \
void DomainMultiScale::name(UInt arg1){ \
DOMAINLOOP((*courant).second->name(arg1)) \
}
#define DEFINE_CALL_TO_SUBFUNCTION_REALARG(name) \
void DomainMultiScale::name(Real arg1){ \
DOMAINLOOP((*courant).second->name(arg1)) \
}
DEFINE_RETURN_REAL_FUNCTION_BYSUM(getEpot);
DEFINE_CALL_TO_SUBFUNCTION(performStep1);
DEFINE_CALL_TO_SUBFUNCTION(performStep2);
DEFINE_CALL_TO_SUBFUNCTION(performStep3);
DEFINE_CALL_TO_SUBFUNCTION_INTARG(setCurrentStep);
DEFINE_CALL_TO_SUBFUNCTION_REALARG(setTimeStep);
DEFINE_RETURN_REAL_FUNCTION_BYSUM(getFdotDir);
DEFINE_RETURN_REAL_FUNCTION_BYSUM(getFNorm2);
DEFINE_RETURN_REAL_FUNCTION_BYSUM(getFdotOldF);
DEFINE_CALL_TO_SUBFUNCTION_REALARG(updateDirection);
DEFINE_CALL_TO_SUBFUNCTION(saveForceVector);
DEFINE_CALL_TO_SUBFUNCTION_REALARG(displaceTowardsDirection);
/* -------------------------------------------------------------------------- */
template <>
DomainMultiScale * IDManager<DomainInterface,DomainMultiScale>::static_pointer = NULL;
/* -------------------------------------------------------------------------- */
__END_LIBMULTISCALE__

Event Timeline