diff --git a/clients/AMEL.cc b/clients/AMEL.cc index c79534b..20d10fc 100644 --- a/clients/AMEL.cc +++ b/clients/AMEL.cc @@ -1,414 +1,384 @@ /* ./amel/AMEL.cpp ********************************** author : Guillaume ANCIAUX (guillaume.anciaux@epfl.ch, g.anciaux@laposte.net) 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 is done in a collaboration between EPFL within ENAC-LSMS (http://lsms.epfl.ch/) and INRIA Bordeaux, ScAlApplix (http://www.labri.fr/projet/scalapplix/). 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. ***********************************/ /* -------------------------------------------------------------------------- */ #define TIMER #include "action_interface.hh" #include "algebraic_parser.hh" #include "domain_multiscale.hh" #include "factory_multiscale.hh" #include "filter_interface.hh" #include "lm_common.hh" using namespace libmultiscale; /* -------------------------------------------------------------------------- */ #include <iomanip> #include <iostream> #include <sstream> /* -------------------------------------------------------------------------- */ #ifdef LIBMULTISCALE_USE_QVIEW #include <libqview.h> #endif /* -------------------------------------------------------------------------- */ #ifdef USING_EPSN #include <fstream> #include <iostream> #include <sstream> #endif /* -------------------------------------------------------------------------- */ #include <mpi.h> #include <sys/types.h> #include <unistd.h> /* -------------------------------------------------------------------------- */ #include <stdexcept> Real lastdump = -1e30; Real lastStep = 0; +/* -------------------------------------------------------------------------- */ void printState() { if (lm_my_proc_id != 0) return; struct timespec gtime; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, >ime); if (gtime.tv_sec - lastdump < 2) return; Real nstep_done = -lastStep + current_step; std::stringstream info_steps; info_steps << std::setw(3) << std::setfill(' ') << 100 * current_step / nb_step << "% - " #ifdef USE_COMPACT_STATUS << "step" #else << "passing step " #endif << std::setw(5) << std::setfill(' ') << current_step << "/" << std::setw(5) << std::setfill(' ') << nb_step; if (current_step > 0) { Real step_per_seconds = nstep_done / (gtime.tv_sec - lastdump); Real remaining_time = 1. * (nb_step - current_step) / step_per_seconds; UInt remaining_hours = int(remaining_time / 60 / 60); UInt remaining_minutes = int(remaining_time / 60 - remaining_hours * 60); UInt remaining_seconds = int(remaining_time - remaining_minutes * 60 - remaining_hours * 60 * 60); info_steps << " " << std::setw(5) << std::setfill(' ') << step_per_seconds #ifdef USE_COMPACT_STATUS << "/sec. ETA: " #else << " steps/seconds " << "remaining " #endif << std::setw(5) << std::setfill(' ') << remaining_hours #ifdef USE_COMPACT_STATUS << ":" #else << " hours " #endif #ifdef USE_COMPACT_STATUS << std::setw(2) << std::setfill('0') << remaining_minutes << ":" #else << std::setw(2) << std::setfill(' ') << remaining_minutes << " minutes " #endif #ifdef USE_COMPACT_STATUS << std::setw(2) << std::setfill('0') << remaining_seconds; #else << std::setw(2) << std::setfill(' ') << remaining_seconds << " seconds"; #endif } std::string clown = info_steps.str(); // std::cerr << "\r" << clown; std::cerr << info_steps.str() << std::endl; lastStep = current_step; lastdump = gtime.tv_sec; } + /* -------------------------------------------------------------------------- */ // void echange_args(const string &* argv,char **my_args); extern std::string lm_release_info; /* -------------------------------------------------------------------------- */ static void Usage(const std::string &name) { std::cout << "Usage : " << name << " config_file nb_time_step\n" << "\t config_file : global config file of the simulation\n" << "\t nb_time_step : number of time step wanted to be done (>=0)\n"; std::cout << "*****************************************" << std::endl; std::cout << "release info" << std::endl; std::cout << "*****************************************" << std::endl; std::cout << lm_release_info << std::endl; lm_exit(LM_EXIT_FAILURE); } /* -------------------------------------------------------------------------- */ int main(int argc, char **argv) { + loadModules(argc, argv); // loading the modules macro if (argc != 3) { if (lm_my_proc_id == 0) Usage(argv[0]); lm_exit(LM_EXIT_FAILURE); } nb_step = atoi(argv[2]); nb_step_next_event = nb_step; if (nb_step == UINT_MAX) Usage(argv[0]); MPI_Barrier(MPI_COMM_WORLD); DOWAIT_AT_STARTUP; STARTTIMER("Init0"); DomainMultiScale &dom = DomainMultiScale::getManager(); dom.build(argv[1]); auto &actions = ActionManager::getManager(); auto &filters = FilterManager::getManager(); STOPTIMER("Init0"); nb_step += current_step; #ifdef USING_EPSN std::ofstream epsn_log; struct timeval timer_epsn_start; struct timeval timer_epsn_stop; struct timeval result; std::stringstream epsn_log_filename; epsn_log_filename << "epsn_log_" << std::setfill('0') << std::setw(5) << lm_my_proc_id << ".log"; epsn_log.open(epsn_log_filename.str().c_str(), std::ios_base::out); if (epsn_itfc->isNodeInitialized()) { UInt epsn_status = 0; // EPSN Ready DUMP("EPSN is going to be READY...", DBG_INFO_STARTUP); epsn_status = epsn_itfc->ready(); if (!epsn_status) { FATAL("error on EPSN Node ready operation\n"); } DUMP("EPSN READY", DBG_INFO_STARTUP); // the main loop DUMP("EPSN Begin HTG", DBG_INFO_STARTUP); epsn_itfc->beginHTM(); epsn_itfc->beginLoop("main"); DUMP("simulation ready to start for EPSN", DBG_INFO_STARTUP); } #endif MPI_Barrier(MPI_COMM_WORLD); bool shouldPrintState = true; #ifdef LIBMULTISCALE_USE_QVIEW QView qv; qv.setMode(NET_MODE); qv.initLibQview(lm_my_proc_id); qv.beginTask("main", nb_step); shouldPrintState = false; #endif // USING_QVIEW char *varenv = getenv("PRINT_STATE"); if (varenv) shouldPrintState = true; STARTTIMER("Main_loop"); Real min_dt = dom.getTimeStep(); current_time = current_step * min_dt; #ifdef LIBMULTISCALE_TIMER UInt freq = 1; if (nb_step >= 10000) freq = 100; #endif for (; current_step < nb_step; ++current_step, current_time += min_dt) { #ifdef USING_EPSN gettimeofday(&timer_epsn_start, NULL); if (epsn_itfc->isNodeInitialized()) epsn_itfc->beginTask("body"); #endif #ifdef LIBMULTISCALE_USE_QVIEW qv.setCurrentStep(current_step); #endif // USING_QVIEW if (shouldPrintState) printState(); try { STARTTIMER("preDump"); current_stage = PRE_DUMP; actions.action(); STOPTIMER("preDump"); current_stage = PRE_STEP1; STARTTIMER("preAction1"); actions.action(); STOPTIMER("preAction1"); STARTTIMER("performStep1"); dom.performStep1(); STOPTIMER("performStep1"); STARTTIMER("CouplingStep1"); dom.coupling(COUPLING_STEP1); STOPTIMER("CouplingStep1"); current_stage = PRE_STEP2; STARTTIMER("preAction2"); actions.action(); STOPTIMER("preAction2"); STARTTIMER("performStep2"); dom.performStep2(); STOPTIMER("performStep2"); STARTTIMER("CouplingStep2"); dom.coupling(COUPLING_STEP2); STOPTIMER("CouplingStep2"); current_stage = PRE_STEP3; STARTTIMER("preAction3"); actions.action(); STOPTIMER("preAction3"); STARTTIMER("performStep3"); dom.performStep3(); STOPTIMER("performStep3"); STARTTIMER("CouplingStep3"); dom.coupling(COUPLING_STEP3); STOPTIMER("CouplingStep3"); current_stage = PRE_STEP4; STARTTIMER("preAction4"); actions.action(); STOPTIMER("preAction4"); STARTTIMER("CouplingStep4"); dom.coupling(COUPLING_STEP4); STOPTIMER("CouplingStep4"); #ifdef LIBMULTISCALE_TIMER if (current_step % freq == 0) dumpTimesInColumn(lm_my_proc_id, current_step); #endif } catch (std::runtime_error &err) { std::stringstream error_stream; error_stream << " at stage " << current_stage << ": Caught '" << err.what() << "'"; LM_FATAL(error_stream.str()); } #ifdef USING_EPSN if (epsn_itfc->isNodeInitialized()) epsn_itfc->endTask("body"); gettimeofday(&timer_epsn_stop, NULL); result.tv_sec = timer_epsn_stop.tv_sec - timer_epsn_start.tv_sec; if ((result.tv_usec = timer_epsn_stop.tv_usec - timer_epsn_start.tv_usec) < 0) { --result.tv_sec; result.tv_usec += 1000000; } Real time_epsn = result.tv_sec * 1000.0 + result.tv_usec / 1000.0; epsn_log << lm_my_proc_id << " " << current_step << " " << time_epsn << std::endl; #endif // MPI_Barrier(MPI_COMM_WORLD); } #ifdef LIBMULTISCALE_USE_QVIEW qv.endTask(); #endif // USING_QVIEW #ifdef USING_EPSN if (epsn_itfc->isNodeInitialized()) { epsn_itfc->endLoop("main"); epsn_itfc->endHTM(); } #endif current_stage = PRE_DUMP; actions.action(); current_stage = PRE_STEP1; actions.action(); STOPTIMER("Main_loop"); dom.destroy(); actions.destroy(); filters.destroy(); closeModules(); // closing the modules macro std::cerr << std::endl; lm_exit(LM_EXIT_SUCCESS); } /* -------------------------------------------------------------------------- */ - -[[noreturn]] void onTerminate() noexcept { - - std::string trace; - if (auto exc = std::current_exception()) { - // we have an exception - try { - rethrow_exception(exc); // throw to recognize the type - } catch (LibMultiScaleException &e) { - trace = e.messageWithTrace(); - } catch (std::exception &ex) { - auto e = LibMultiScaleException(ex.what()); - for (UInt i = 0; i < 4; ++i) - e.stack_trace.stack.pop_front(); - trace = e.messageWithTrace(); - } catch (...) { - auto e = LibMultiScaleException( - "LibMultiScale failed with an unknown exception"); - - for (UInt i = 0; i < 4; ++i) - e.stack_trace.stack.pop_front(); - trace = e.messageWithTrace(); - } - } - std::cerr << std::endl - << "LibMultiScale failed with the following message:" << std::endl - << std::endl - << trace; - - std::_Exit(EXIT_FAILURE); -} - -/* -------------------------------------------------------------------------- */ diff --git a/python/prologue.py b/python/prologue.py index 5f27e29..529d2a9 100644 --- a/python/prologue.py +++ b/python/prologue.py @@ -1,72 +1,72 @@ class LMParameters(object): def __init__(self, component): yop = dict( [(o.lower(), o) for o in component.getPossibleKeywords()]) - self.keywords = yop - self.component = component + self._keywords = yop + self._component = component def __getattribute__(self, name): - if name == 'keywords': + if name == '_keywords': return super(LMParameters, self).__getattribute__(name) name = name.lower() - if name in self.keywords: - return self.component.getParam(self.keywords[name]) + if name in self._keywords: + return self._component.getParam(self._keywords[name]) else: return super(LMParameters, self).__getattribute__(name) def __setattr__(self, name, val): name = name.lower() - if name == 'keywords': + if name == '_keywords': super(LMParameters, self).__setattr__(name, val) return - if name in self.keywords: + if name in self._keywords: if name == 'input' and (not isinstance(val, str)): import pylibmultiscale as lm manager = lm.FilterManager.getManager() compute_input = lm.ComputeCompatibility( - self.component.getID() + 'auto_input') + self._component.getID() + 'auto_input') # compute_input.createOutput('output') compute_input.getOutput('output').make_argument(val) manager.addObject(compute_input) val = compute_input.getID() - self.component.setParam(self.keywords[name], val) + self._component.setParam(self._keywords[name], val) return else: super(LMParameters, self).__setattr__(name, val) def __dir__(self): - return self.keywords + return self._keywords class LMInputs(object): def __init__(self, component): yop = dict( [(o.lower(), o) for o in component.getInputs()]) - self.keywords = yop + self._keywords = yop # print(yop) - self.component = component + self._component = component def __getattribute__(self, name): - if name == 'keywords': + if name == '_keywords': return super(LMInputs, self).__getattribute__(name) name = name.lower() - if name in self.keywords: - return self.component.getParam(self.keywords[name]) + if name in self._keywords: + return self._component.getParam(self._keywords[name]) else: return super(LMInputs, self).__getattribute__(name) def __setattr__(self, name, val): name = name.lower() - if name == 'keywords': + if name == '_keywords': super(LMInputs, self).__setattr__(name, val) return - if name in self.keywords: - self.component.setInput(name, val) + if name in self._keywords: + self._component.setInput(name, val) else: super(LMInputs, self).__setattr__(name, val) def __dir__(self): - return self.keywords + return self._keywords diff --git a/python/python.cc b/python/python.cc index b64b05d..d194299 100644 --- a/python/python.cc +++ b/python/python.cc @@ -1,67 +1,73 @@ #include "lm_common.hh" #include "lm_python_bindings.hh" #include <pybind11/eigen.h> #include <pybind11/pybind11.h> #include <pybind11/stl.h> namespace py = pybind11; using namespace libmultiscale; std::vector<std::string> fake_argv; std::vector<char *> c_argv; + void loadModules() { // auto sys = py::module::import("sys"); // auto argv = sys.attr("argv"); // fake_argv = py::cast<std::vector<std::string>>(argv); // std::cout << "AAAA " << fake_argv.size() << std::endl; // for (auto &&v : fake_argv) { // std::cout << "AAAA " << &v[0] << std::endl; // c_argv.push_back(&v[0]); // } // loadModules(c_argv.size(), c_argv.data()); loadModules(0, nullptr); create_seg_fault = false; } extern std::string lm_release_info; template <typename T2, typename T> void ModuleProperty(py::module &m, const char *n, T &var) { // setting a property // import the builtins and get the "property" python class auto property = py::module::import("builtins").attr("property"); m.attr(n) = property(py::cpp_function([&]() { return var; }), py::cpp_function([&](T2 &a) { var = a; })); } PYBIND11_MODULE(pylibmultiscale, m) { m.doc() = "LibMultiScale python module"; ModuleProperty<int>(m, "current_step", current_step); ModuleProperty<int>(m, "lm_my_proc_id", lm_my_proc_id); ModuleProperty<IntegrationSchemeStage>(m, "current_stage", current_stage); ModuleProperty<UInt>(m, "spatial_dimension", spatial_dimension); + ModuleProperty<bool>(m, "print_trace", print_trace); m.def("loadModules", &::loadModules, "Load all the module dependencies of libmultiscale"); m.def("closeModules", &closeModules, "close all the module dependencies of libmultiscale"); m.attr("release_info") = py::cast(lm_release_info); makeBindings(m); static py::exception<LibMultiScaleException> lm_exception( m, "LibMultiScaleException"); py::register_exception_translator([](std::exception_ptr p) { try { if (p) std::rethrow_exception(p); } catch (LibMultiScaleException &e) { - lm_exception(e.messageWithTrace().c_str()); + if (print_trace) { + std::cerr << "AAAA " << print_trace << std::endl; + lm_exception(e.messageWithTrace().c_str()); + } else + lm_exception(e.what()); } }); } diff --git a/src/common/lm_functions.cc b/src/common/lm_functions.cc index a51ea39..a78651e 100644 --- a/src/common/lm_functions.cc +++ b/src/common/lm_functions.cc @@ -1,256 +1,270 @@ /** * @file lm_functions.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * * @date Mon Sep 08 23:40:22 2014 * * @brief This file contains the global scope functions * * @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 "geometry.hh" #include "geometry_manager.hh" #include "lm_common.hh" #include "lm_parser.hh" #include <mpi.h> #include <memory> #include <cxxabi.h> #include <regex> #include <pybind11/pybind11.h> #include <pybind11/embed.h> __BEGIN_LIBMULTISCALE__ namespace py = pybind11; /* -------------------------------------------------------------------------- */ [[noreturn]] void onTerminate() noexcept { std::string trace; if (auto exc = std::current_exception()) { // we have an exception try { rethrow_exception(exc); // throw to recognize the type } catch (LibMultiScaleException &e) { - trace = e.messageWithTrace(); + if(print_trace) + trace = e.messageWithTrace(); + else + trace = e.what(); } catch (std::exception &ex) { auto e = LibMultiScaleException(ex.what()); for (UInt i = 0; i < 4; ++i) e.stack_trace.stack.pop_front(); - trace = e.messageWithTrace(); + + if(print_trace) + trace = e.messageWithTrace(); + else + trace = e.what(); } catch (...) { auto e = LibMultiScaleException( "LibMultiScale failed with an unknown exception"); for (UInt i = 0; i < 4; ++i) e.stack_trace.stack.pop_front(); - trace = e.messageWithTrace(); + if(print_trace) + trace = e.messageWithTrace(); + else + trace = e.what(); } } std::cerr << std::endl << "LibMultiScale failed with the following message:" << std::endl - << std::endl - << trace; + << std::endl << trace; std::_Exit(EXIT_FAILURE); } /* -------------------------------------------------------------------------- */ // c++ typeinfo /* -------------------------------------------------------------------------- */ std::string demangle(const char* name) { int status = -4; // some arbitrary value to eliminate the compiler warning std::unique_ptr<char, void(*)(void*)> res { abi::__cxa_demangle(name, NULL, NULL, &status), std::free }; std::regex r("libmultiscale::"); auto demangled_name = res.get(); return (status==0) ? std::regex_replace(demangled_name,r,"") : name ; } /* -------------------------------------------------------------------------- */ // MPI macros /* -------------------------------------------------------------------------- */ void loadMPI(int argc, char **argv) { int myrank, world, is_initialized; MPI_Initialized(&is_initialized); if (!is_initialized) { MPI_Init(&argc, &argv); } MPI_Comm_rank(MPI_COMM_WORLD, &myrank); lm_my_proc_id = (UInt)myrank; MPI_Comm_size(MPI_COMM_WORLD, &world); lm_world_size = (UInt)world; } void closeMPI() { MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); } /* -------------------------------------------------------------------------- */ // environment macro /* -------------------------------------------------------------------------- */ void loadENV() { char *varenv = lm_getenv("DEBUG_LEVEL"); if (varenv) global_level = lm_atoi(varenv); else global_level = DBG_WARNING; varenv = lm_getenv("DEBUG_PROC"); if (varenv) global_proc = lm_atoi(varenv); else global_proc = UINT_MAX; varenv = lm_getenv("DEBUG_PROC1"); if (varenv) global_proc1 = lm_atoi(varenv); else global_proc1 = UINT_MAX; varenv = lm_getenv("DEBUG_PROC2"); if (varenv) global_proc2 = lm_atoi(varenv); else global_proc2 = UINT_MAX; varenv = lm_getenv("DEBUG_START"); if (varenv) start_dump = lm_atoi(varenv); else start_dump = 0; varenv = lm_getenv("DEBUG_END"); if (varenv) end_dump = lm_atoi(varenv); else end_dump = UINT_MAX; varenv = lm_getenv("HOSTNAME"); if (varenv) my_hostname = varenv; else my_hostname = ""; varenv = lm_getenv("JOB_ID"); if (varenv) lm_job_id = lm_atoi(varenv); else lm_job_id = lm_world_size; varenv = lm_getenv("PRINT_CRAP_TO_FILE"); if (varenv) print_crap_to_file = true; else print_crap_to_file = false; varenv = lm_getenv("CREATE_SEG_FAULT"); if (varenv) create_seg_fault = true; else create_seg_fault = false; varenv = lm_getenv("WAIT_ON_FATAL"); if (varenv) wait_on_fatal = true; else wait_on_fatal = false; varenv = lm_getenv("WAIT_AT_STARTUP"); if (varenv) wait_at_startup = lm_atoi(varenv); else wait_at_startup = UINT_MAX; + varenv = lm_getenv("PRINT_TRACE"); + if (varenv) + print_trace = true; + else + print_trace = false; openGlobal(); } /* -------------------------------------------------------------------------- */ /// EPSN init macro /* -------------------------------------------------------------------------- */ #ifdef LIBMULTISCALE_USE_EPSN #include "Epsn..hh" #include "RedSYM..hh" EXTERN char xmlepsnfile[255]; EXTERN EPSN::Simulation::Interface *epsn_itfc; inline void loadEPSN() { epsn_itfc = NULL; epsn_itfc = new EPSN::Simulation::Interface; epsn_itfc->initORB(argc, argv); } inline closeEPSN() { epsn_itfc->finalize(); epsn_itfc->killORB(); delete epsn_itfc; } #else void loadEPSN() {} void closeEPSN() {} #endif /* -------------------------------------------------------------------------- */ /// Python init macro /* -------------------------------------------------------------------------- */ bool embedded_interpreter = false; void loadPython(){ if (not Py_IsInitialized()){ py::initialize_interpreter(); embedded_interpreter = true; } } void closePython(){ if (embedded_interpreter) py::finalize_interpreter(); } /* -------------------------------------------------------------------------- */ // init functions /* -------------------------------------------------------------------------- */ void loadModules(int argc, char **argv) { std::set_terminate(&onTerminate); loadMPI(argc, argv); loadEPSN(); loadENV(); loadPython(); } void closeModules() { GeometryManager::destroy(); Parser::freeMemory(); closeEPSN(); #ifdef LIBMULTISCALE_TIMER dumpTimes(lm_my_proc_id); #endif closeMPI(); closePython(); (*global_out).flush(); } /* -------------------------------------------------------------------------- */ // terminate exception function /* -------------------------------------------------------------------------- */ __END_LIBMULTISCALE__ diff --git a/src/common/lm_globals.cc b/src/common/lm_globals.cc index 2026015..5154320 100644 --- a/src/common/lm_globals.cc +++ b/src/common/lm_globals.cc @@ -1,117 +1,118 @@ /** * @file lm_globals.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Jaehyun Cho <jaehyun.cho@epfl.ch> * @author Till Junge <till.junge@epfl.ch> * * @date Mon Sep 08 23:40:22 2014 * * @brief This file contains all the global variables of LM * * @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 "lm_common.hh" #include <fstream> #include <limits> /* -------------------------------------------------------------------------- */ __BEGIN_LIBMULTISCALE__ /* -------------------------------------------------------------------------- */ // global variables UInt current_step; IntegrationSchemeStage current_stage; Real current_time; UInt nb_step; UInt nb_step_next_event; UInt global_level; UInt global_mod; UInt global_proc; UInt global_proc1; UInt global_proc2; UInt start_dump; UInt end_dump; std::string my_hostname; UInt print_crap_to_file; std::ostream *global_out; std::ofstream file_out; UInt wait_on_fatal; UInt wait_at_startup; UInt create_seg_fault; UInt lm_my_proc_id; UInt lm_world_size; UInt lm_job_id; UInt spatial_dimension; UInt lm_uint_max = std::numeric_limits<UInt>::max(); Real lm_real_max = std::numeric_limits<Real>::max(); /// used to avoid infinite FATAL recursion in stage PRE_FATAL bool fatal_loop = false; +bool print_trace; #if defined(LIBMULTISCALE_USE_TIMER) std::map<std::string, struct timespec> mesT; std::map<std::string, UInt> nmes; std::map<std::string, struct timespec> tstart; std::map<std::string, struct timespec> tstop; #endif /* -------------------------------------------------------------------------- */ UInt getGlobalCurrentRelease() { UInt k = 0; switch (current_stage) { case PRE_DUMP: k = 0; break; case PRE_STEP1: k = 1; break; case PRE_STEP2: k = 2; break; case PRE_STEP3: k = 3; break; case PRE_STEP4: k = 4; break; case PRE_STEP5: k = 5; break; case PRE_STEP6: k = 6; break; case PRE_STEP7: k = 7; break; case PRE_FATAL: k = 8; break; default: LM_FATAL("error: unknown stage " << current_stage); } return (8 * current_step + k); } /* -------------------------------------------------------------------------- */ __END_LIBMULTISCALE__ diff --git a/src/common/lm_globals.hh b/src/common/lm_globals.hh index c78d47f..a05a99e 100644 --- a/src/common/lm_globals.hh +++ b/src/common/lm_globals.hh @@ -1,86 +1,87 @@ /** * @file lm_globals.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Jaehyun Cho <jaehyun.cho@epfl.ch> * @author Till Junge <till.junge@epfl.ch> * * @date Mon Sep 08 23:40:22 2014 * * @brief This file contains all the global variables of LM * * @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/>. * */ #ifndef __LIBMULTISCALE_LM_GLOBALS_HH__ #define __LIBMULTISCALE_LM_GLOBALS_HH__ /* -------------------------------------------------------------------------- */ #include "lm_macros.hh" #include "lm_types.hh" #include <iostream> /* -------------------------------------------------------------------------- */ __BEGIN_LIBMULTISCALE__ static const std::string invalidFilter = "invalid filter"; static const std::string invalidGeom = "invalid geometry"; static const std::string invalidDomain = "invalid domain"; static const std::string invalidDumper = "invalid dumper"; static const std::string invalidStimulator = "invalid stimulator"; using LMID = std::string; /* -------------------------------------------------------------------------- */ // global variables EXTERN UInt current_step; EXTERN IntegrationSchemeStage current_stage; EXTERN Real current_time; EXTERN UInt nb_step; EXTERN UInt nb_step_next_event; EXTERN UInt global_level; EXTERN UInt global_mod; EXTERN UInt global_proc; EXTERN UInt global_proc1; EXTERN UInt global_proc2; EXTERN UInt start_dump; EXTERN UInt end_dump; EXTERN std::string my_hostname; EXTERN UInt print_crap_to_file; EXTERN std::ostream *global_out; EXTERN std::ofstream file_out; EXTERN UInt wait_on_fatal; EXTERN UInt wait_at_startup; EXTERN UInt create_seg_fault; EXTERN UInt lm_my_proc_id; EXTERN UInt lm_world_size; EXTERN UInt lm_job_id; EXTERN UInt spatial_dimension; EXTERN UInt lm_uint_max; EXTERN Real lm_real_max; /// used to avoid infinite FATAL recursion in stage PRE_FATAL EXTERN bool fatal_loop; +EXTERN bool print_trace; /* -------------------------------------------------------------------------- */ EXTERN UInt getGlobalCurrentRelease(); /* -------------------------------------------------------------------------- */ __END_LIBMULTISCALE__ #endif /* __LIBMULTISCALE_LM_GLOBALS_HH__ */ diff --git a/src/common/lm_python_bindings.hh b/src/common/lm_python_bindings.hh index cb6c0d4..1ce4c2b 100644 --- a/src/common/lm_python_bindings.hh +++ b/src/common/lm_python_bindings.hh @@ -1,409 +1,430 @@ #include "action_interface.hh" #include "communicator.hh" #include "compute_list.hh" #include "domain_multiscale.hh" #include "dumper_list.hh" #include "factory_multiscale.hh" #include "filter_interface.hh" #include "filter_list.hh" #include "geometry_list.hh" #include "geometry_manager.hh" #include "lib_continuum.hh" #include "lib_dd.hh" #include "lib_dumper.hh" #include "lib_filter.hh" #include "lib_geometry.hh" #include "lib_md.hh" #include "lib_stimulation.hh" #include "lm_common.hh" #include "lm_type_caster.hh" #include "stimulation_interface.hh" #include "stimulation_list.hh" #include <pybind11/eigen.h> #include <pybind11/pybind11.h> #include <pybind11/stl.h> namespace py = pybind11; __BEGIN_LIBMULTISCALE__ template <typename Class> inline void declare_domain(py::module &m, const char *class_name) { py::class_<Class, DomainInterface, std::shared_ptr<Class>>( m, class_name, py::multiple_inheritance()) .def(py::init<LMID, CommGroup &>()) .def("init", [](Class &self) { self.checkAllKeywordsAreParsed(); self.init(); }); } template <typename Class> inline void declare_geometry(py::module &m, const char *class_name) { py::class_<Class, Geometry, std::shared_ptr<Class>>( m, class_name, py::multiple_inheritance()) .def(py::init<UInt, LMID>()) .def("init", [](Class &self) { self.checkAllKeywordsAreParsed(); self.init(); }); } template <typename Class> inline void declare_stimulation(py::module &m, const char *class_name) { py::class_<Class, StimulationInterface, std::shared_ptr<Class>>( m, class_name, py::multiple_inheritance()) .def(py::init<LMID>()) .def("init", [](Class &self) { self.checkAllKeywordsAreParsed(); self.init(); }); } template <typename Class> inline void declare_compute(py::module &m, const char *class_name) { py::class_<Class, ComputeInterface, std::shared_ptr<Class>>( m, class_name, py::multiple_inheritance()) .def(py::init<LMID>()) .def("init", [](Class &self) { self.checkAllKeywordsAreParsed(); self.init(); }); } template <typename Class> inline void declare_filter(py::module &m, const char *class_name) { py::class_<Class, FilterInterface, std::shared_ptr<Class>>( m, class_name, py::multiple_inheritance()) .def(py::init<LMID>()) .def("init", [](Class &self) { self.checkAllKeywordsAreParsed(); self.init(); }); } template <typename Class> inline void declare_dumper(py::module &m, const char *class_name) { py::class_<Class, DumperInterface, std::shared_ptr<Class>>( m, class_name, py::multiple_inheritance()) .def(py::init<LMID>()) .def("init", [](Class &self) { self.checkAllKeywordsAreParsed(); self.init(); }); } inline std::string clean_class_name(const std::string &arg) { std::string res = arg; res.erase(std::remove(res.begin(), res.end(), '<'), res.end()); res.erase(std::remove(res.begin(), res.end(), '>'), res.end()); return res; } inline void makeBindings(py::module &m) { py::enum_<IntegrationSchemeStage>(m, "IntegrationSchemeStage") .value("NONE_STEP", NONE_STEP) .value("PRE_DUMP", PRE_DUMP) .value("PRE_STEP1", PRE_STEP1) .value("PRE_STEP2", PRE_STEP2) .value("PRE_STEP3", PRE_STEP3) .value("PRE_STEP4", PRE_STEP4) .value("PRE_STEP5", PRE_STEP5) .value("PRE_STEP6", PRE_STEP6) .value("PRE_STEP7", PRE_STEP7) .value("PRE_FATAL", PRE_FATAL) .value("ALL_STEP", ALL_STEP) .export_values(); py::enum_<CouplingStage>(m, "CouplingStage") .value("COUPLING_STEP1", COUPLING_STEP1) .value("COUPLING_STEP2", COUPLING_STEP2) .value("COUPLING_STEP3", COUPLING_STEP3) .value("COUPLING_STEP4", COUPLING_STEP4) .value("COUPLING_STEP5", COUPLING_STEP5) .value("COUPLING_STEP6", COUPLING_STEP6) .value("COUPLING_STEP7", COUPLING_STEP7) .export_values(); py::enum_<DOFType>(m, "DOFType") .value("dt_local_master", dt_local_master) .value("dt_local_slave", dt_local_slave) .value("dt_local", dt_local) .value("dt_ghost", dt_ghost) .value("dt_all", dt_all) .export_values(); + py::enum_<FieldType>(m, "FieldType") + .value("position0", _position0) + .value("position", _position) + .value("displacement", _displacement) + .value("velocity", _velocity) + .value("force", _force) + .value("stress", _stress) + .value("temperature", _temperature) + .value("grouprank", _grouprank) + .value("strain", _strain) + .value("epot", _epot) + .value("applied_force", _applied_force) + .value("mass", _mass) + .value("tag", _tag) + .value("id", _id) + .value("proc", _proc) + .value("charge", _charge) + .value("burgers", _burgers) + .value("normal", _normal) + .export_values(); + py::class_<DomainMultiScale>(m, "DomainMultiScale") .def_static("getManager", &DomainMultiScale::getManager, py::return_value_policy::reference) .def("build", &DomainMultiScale::build) .def("getObject", &DomainMultiScale::getObject, py::return_value_policy::reference) .def("getTimeStep", &DomainMultiScale::getTimeStep) .def("performStep1", &DomainMultiScale::performStep1) .def("performStep2", &DomainMultiScale::performStep2) .def("performStep3", &DomainMultiScale::performStep3) .def("coupling", &DomainMultiScale::coupling) .def("destroy", &DomainMultiScale::destroy) .def("addObject", py::overload_cast<std::shared_ptr<DomainInterface>>( &DomainMultiScale::addObject)); py::class_<ActionManager>(m, "ActionManager") .def_static("getManager", py::overload_cast<>(&ActionManager::getManager), py::return_value_policy::reference) .def_static("getManager", py::overload_cast<UInt>(&ActionManager::getManager), py::return_value_policy::reference) .def("action", &ActionManager::action) .def("destroy", &ActionManager::destroy) .def("addObject", py::overload_cast<std::shared_ptr<ActionInterface>>( &ActionManager::addObject)); py::class_<FilterManager>(m, "FilterManager") .def_static("getManager", py::overload_cast<>(&FilterManager::getManager), py::return_value_policy::reference) .def_static("getManager", py::overload_cast<UInt>(&FilterManager::getManager), py::return_value_policy::reference) .def("action", &FilterManager::action) .def("destroy", &FilterManager::destroy) .def("addObject", py::overload_cast<std::shared_ptr<FilterInterface>>( &FilterManager::addObject)); py::class_<CommGroup>(m, "CommGroup") .def(py::init<const LMID &, int, UInt>()); py::class_<Communicator>(m, "Communicator") .def("getCommunicator", &Communicator::getCommunicator, py::return_value_policy::reference) .def("getNumberFreeProcs", &Communicator::getNumberFreeProcs) .def("addGroup", &Communicator::addGroup) .def("getGroup", &Communicator::getGroup); m.attr("prologue") = py::module::import("prologue"); py::class_<GeometryManager>(m, "GeometryManager") .def_static("getManager", &GeometryManager::getManager, py::return_value_policy::reference) .def("addGeometry", &GeometryManager::addGeometry) .def("destroy", &GeometryManager::destroy); py::class_<Parsable, std::shared_ptr<Parsable>>(m, "Parsable") .def("getPossibleKeywords", &Parsable::getPossibleKeywords) .def("getParam", &Parsable::getParam<py::object>) .def("setParam", [](Parsable &self, const std::string &keyword, py::object &val) { self.setParam<py::object>(keyword, val); }) .def_property_readonly("params", [m](Parsable &self) { return m.attr("prologue").attr("LMParameters")(self); }); py::class_<DomainInterface, Parsable, std::shared_ptr<DomainInterface>>( m, "DomainInterface", py::multiple_inheritance()) .def("performStep1", &DomainInterface::performStep1) .def("performStep2", &DomainInterface::performStep2) .def("performStep3", &DomainInterface::performStep3) .def("performStep4", &DomainInterface::performStep4) .def("performStep5", &DomainInterface::performStep5); py::class_<Geometry, Parsable, std::shared_ptr<Geometry>>( m, "Geometry", py::multiple_inheritance()); py::class_<ActionInterface, Parsable, std::shared_ptr<ActionInterface>> action_interface(m, "ActionInterface", py::multiple_inheritance()); action_interface.def("action", &ActionInterface::action) .def("getID", [](ActionInterface &self) { return self.getID(); }) .def("getOutputs", [](ActionInterface &self) { auto &outputs = self.getOutputs(); py::dict ret; for (auto &&kv : outputs) { ret.attr("__setitem__") . operator()<py::return_value_policy::reference>(kv.first, kv.second); } return ret; }) .def("getInputs", [](ActionInterface &self) { auto &inputs = self.getInputs(); py::dict ret; for (auto &&kv : inputs) { ret.attr("__setitem__") . operator()<py::return_value_policy::reference>(kv.first, kv.second); } return ret; }) .def("createOutput", &ActionInterface::createOutput) - .def("getOutput", &ActionInterface::getOutput, + .def("getOutput", &ActionInterface::getOutput, py::arg("name") = "", py::return_value_policy::reference) .def_property_readonly("inputs", [m](ActionInterface &self) { return m.attr("prologue").attr("LMInputs")(self); }); #define PYTHON_DOMAIN(n, data, obj) \ action_interface.def("setInput", \ [m](ActionInterface &self, const std::string &name, \ BOOST_PP_TUPLE_ELEM(3, 0, obj) & input) { \ try { \ self.connect(name, input.getOutput()); \ } catch (...) { \ self.connect(name, make_argument(input)); \ } \ }); BOOST_PP_SEQ_FOR_EACH(PYTHON_DOMAIN, f, LIST_ATOM_MODEL); BOOST_PP_SEQ_FOR_EACH(PYTHON_DOMAIN, f, LIST_DD_MODEL); BOOST_PP_SEQ_FOR_EACH(PYTHON_DOMAIN, f, LIST_CONTINUUM_MODEL); #undef PYTHON_DOMAIN #define PYTHON_COMPUTE(n, data, obj) \ action_interface.def("setInput", \ [m](ActionInterface &self, const std::string &name, \ BOOST_PP_TUPLE_ELEM(3, 0, obj) & input) { \ try { \ self.connect(name, input.getOutput()); \ } catch (...) { \ self.connect(name, make_argument(input)); \ } \ }); BOOST_PP_SEQ_FOR_EACH(PYTHON_COMPUTE, f, LIST_COMPUTE); BOOST_PP_SEQ_FOR_EACH(PYTHON_COMPUTE, f, LIST_FILTER); #undef PYTHON_COMPUTE py::class_<StimulationInterface, ActionInterface, std::shared_ptr<StimulationInterface>>(m, "StimulationInterface", py::multiple_inheritance()) .def("stimulate", &StimulationInterface::stimulate); py::class_<FilterInterface, ActionInterface, std::shared_ptr<FilterInterface>>(m, "FilterInterface", py::multiple_inheritance()) .def("build", &FilterInterface::build); py::class_<DumperInterface, ActionInterface, std::shared_ptr<DumperInterface>>(m, "DumperInterface", py::multiple_inheritance()) .def("dump", &DumperInterface::dump); py::class_<ComputeInterface, FilterInterface, std::shared_ptr<ComputeInterface>>(m, "ComputeInterface", py::multiple_inheritance()) .def("compute", &ComputeInterface::compute) .def("getArray", &ComputeInterface::getArray, py::return_value_policy::reference) .def("getCastedOutput", [](ComputeInterface &self, std::string name, bool eval) { return self.getCastedOutput<ContainerArray<Real>>(name, eval); }, py::arg("name"), py::arg("eval") = true); py::class_<ContainerArray<Real>>(m, "ContainerArrayReal", py::multiple_inheritance()) //.def_readwrite("name_computed", &ContainerArray<Real>::name_computed) .def("getDim", &ContainerArray<Real>::getDim) .def("size", &ContainerArray<Real>::size, py::arg("dt") = dt_local) .def("to_array", &ContainerArray<Real>::to_array); py::class_<ArgumentContainer, std::shared_ptr<ArgumentContainer>>( m, "ArgumentContainer") .def("make_argument", [](ArgumentContainer &arg, ComputeInterface &c) { arg = make_argument(c); }) .def("make_argument", [](ArgumentContainer &arg, py::array c) { auto cont = std::make_shared<ContainerArray<Real>>("temp"); cont->setCommGroup(Communicator::getCommunicator().getGroup("all")); *cont = py::cast<ContainerArray<Real>::EigenArray>(c); arg = make_argument(std::move(cont)); }); #define PYTHON_DOMAIN(n, data, obj) \ { \ using _class = BOOST_PP_TUPLE_ELEM(3, 0, obj); \ std::string domain_name = \ clean_class_name(BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(3, 0, obj))); \ declare_domain<_class>(m, domain_name.c_str()); \ } BOOST_PP_SEQ_FOR_EACH(PYTHON_DOMAIN, f, LIST_ATOM_MODEL); BOOST_PP_SEQ_FOR_EACH(PYTHON_DOMAIN, f, LIST_DD_MODEL); BOOST_PP_SEQ_FOR_EACH(PYTHON_DOMAIN, f, LIST_CONTINUUM_MODEL); #undef PYTHON_DOMAIN #define PYTHON_GEOMETRY(n, data, obj) \ { \ using _class = BOOST_PP_TUPLE_ELEM(2, 0, obj); \ std::string geometry_name = \ clean_class_name(BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, obj))); \ \ declare_geometry<_class>(m, geometry_name.c_str()); \ } BOOST_PP_SEQ_FOR_EACH(PYTHON_GEOMETRY, f, LIST_GEOMETRY); #undef PYTHON_GEOMETRY #define PYTHON_STIMULATION(n, data, obj) \ { \ using _class = BOOST_PP_TUPLE_ELEM(2, 0, obj); \ std::string stimulation_name = \ clean_class_name(BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, obj))); \ \ declare_stimulation<_class>(m, stimulation_name.c_str()); \ } BOOST_PP_SEQ_FOR_EACH(PYTHON_STIMULATION, f, LIST_STIMULATION); #undef PYTHON_STIMULATION #define PYTHON_COMPUTE(n, data, obj) \ { \ using _class = BOOST_PP_TUPLE_ELEM(2, 0, obj); \ std::string compute_name = \ clean_class_name(BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, obj))); \ \ declare_compute<_class>(m, compute_name.c_str()); \ } BOOST_PP_SEQ_FOR_EACH(PYTHON_COMPUTE, f, LIST_COMPUTE); #undef PYTHON_COMPUTE #define PYTHON_FILTER(n, data, obj) \ { \ using _class = BOOST_PP_TUPLE_ELEM(2, 0, obj); \ std::string filter_name = \ clean_class_name(BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, obj))); \ \ declare_filter<_class>(m, filter_name.c_str()); \ } BOOST_PP_SEQ_FOR_EACH(PYTHON_FILTER, f, LIST_FILTER); #undef PYTHON_FILTER #define PYTHON_DUMPER(n, data, obj) \ { \ using _class = BOOST_PP_TUPLE_ELEM(2, 0, obj); \ std::string dumper_name = \ clean_class_name(BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, obj))); \ \ declare_dumper<_class>(m, dumper_name.c_str()); \ } BOOST_PP_SEQ_FOR_EACH(PYTHON_DUMPER, f, LIST_DUMPER); #undef PYTHON_DUMPER declare_compute<ComputeCompatibility>(m, "ComputeCompatibility"); } __END_LIBMULTISCALE__