diff --git a/src/continuum/domain_continuum.cc b/src/continuum/domain_continuum.cc index cdc1907..44b6f21 100644 --- a/src/continuum/domain_continuum.cc +++ b/src/continuum/domain_continuum.cc @@ -1,256 +1,256 @@ /** * @file domain_continuum.cc * * @author Guillaume Anciaux * * @date Wed Nov 06 20:35:11 2013 * * @brief Mother of all continuum 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 "domain_continuum.hh" #include "geometry_manager.hh" #include "lib_continuum.hh" #include "lm_common.hh" #include "lm_communicator.hh" #include "xml_parser_restart.hh" /* -------------------------------------------------------------------------- */ __BEGIN_LIBMULTISCALE__ /* -------------------------------------------------------------------------- */ template DomainContinuum::DomainContinuum(CommGroup &group) : DomainContinuumInterface(group), arlequin_flag(false), mesh_container(this->getID() + ":mesh"), prestressed_periodicity_flag(false) { geometries.resize(10); createOutput("mesh"); getOutput("mesh") = mesh_container; mesh_container.setCommGroup(group); } /* -------------------------------------------------------------------------- */ template DomainContinuum::~DomainContinuum() {} /* -------------------------------------------------------------------------- */ template typename DomainContinuum::ContainerPoints & DomainContinuum::getContainer() { auto &comm_group = getCommGroup(); if (comm_group.amIinGroup()) { mesh_container.getBoundingBox() = getDomainBoundingBox(); } mesh_container.setCommGroup(getCommGroup()); return mesh_container; } /* -------------------------------------------------------------------------- */ template std::vector> & DomainContinuum::getPBCpairs() { return pbc_pairs; } /* -------------------------------------------------------------------------- */ template inline void DomainContinuum::readXMLFile( const std::string &filename) { XMLRestartParser parser; DUMP("Setting Dummy simulation from libMultiScale XML Data format " << filename, DBG_INFO); if (parser.parseFile(filename, this->restart_continue_if_notfound)) { DUMP("restart was not performed because file was not found", DBG_WARNING); return; } DUMP("read done " << filename, DBG_INFO); UnitsConverter unit; - unit.setInUnits(real_unit_system); + unit.setInUnits(si_unit_system); UInt cpt = 0; UInt cpt2 = 0; #ifndef LM_OPTIMIZED UInt total = getContainerNodes().size(); #endif // LM_OPTIMIZED DUMP("total = " << total, DBG_DETAIL); for (auto &&n : getContainerNodes()) { // for (n = it.getFirst(); !it.end() ; n = it.getNext()){ auto X = n.position0(); if (cpt2 % 100 == 0) DUMP("passing node number " << cpt2 << "/" << total << " reloaded", DBG_INFO); ++cpt2; if (!parser.isDofRegistered(X)) continue; Vector U; parser.assignDispField(X, U); n.displacement() = U; Vector V; parser.assignVelField(X, V); n.velocity() = V; if (cpt % 100 == 0) DUMP("node number " << cpt << "/" << total << " reloaded", DBG_INFO); ++cpt; } DUMP("associated " << cpt << " over " << total, DBG_INFO); // performStep2(); } /* -------------------------------------------------------------------------- */ template ContElems &DomainContinuum::getContainerElems() { auto &comm_group = getCommGroup(); auto &elems = mesh_container.getContainerElems(); if (comm_group.amIinGroup()) { elems.getBoundingBox() = getDomainBoundingBox(); } elems.setCommGroup(getCommGroup()); return elems; } /* -------------------------------------------------------------------------- */ template ContNodes &DomainContinuum::getContainerNodes() { auto &comm_group = getCommGroup(); auto &nodes = mesh_container.getContainerNodes(); if (comm_group.amIinGroup()) { nodes.getBoundingBox() = getDomainBoundingBox(); } nodes.setCommGroup(getCommGroup()); return nodes; } /* -------------------------------------------------------------------------- */ template Geometry &DomainContinuum::getGeom() { return *GeometryManager::getManager().getGeometry(geometries[0]); } /* -------------------------------------------------------------------------- */ /* LMDESC DomainContinuum This section describe the section that is associated with continuum mechanics model. It is the starting point of every Continuum Mechanics plugins. */ template inline void DomainContinuum::declareParams() { DomainInterface::declareParams(); /* LMKEYWORD DOMAIN_GEOMETRY Specify the geometry/region describing the domain */ this->parseKeyword("DOMAIN_GEOMETRY", geometries[0]); /* LMKEYWORD CONSTRAINED_GEOMETRY For minimization purpose (obsolete). This provided a region not included in the computation of the objective function and the gradient. */ this->parseKeyword("CONSTRAINED_GEOMETRY", geom_constrained, invalidGeom); /* LMKEYWORD TIMESTEP Specify the explicit integration timestep */ this->parseKeyword("TIMESTEP", timeStep); /* LMKEYWORD PRESTRESSED_PERIODICITY set whether the corrective displacement of slaves should be considered */ this->parseKeyword("PRESTRESSED_PERIODICITY", prestressed_periodicity_flag, false); } /* -------------------------------------------------------------------------- */ #ifdef LIBMULTISCALE_LIBMESH template class DomainContinuum, ContainerNodesLibMesh<1>, 1>; template class DomainContinuum, ContainerNodesLibMesh<2>, 2>; template class DomainContinuum, ContainerNodesLibMesh<3>, 3>; #endif #ifdef LIBMULTISCALE_SIMULPACK template class DomainContinuum, ContainerNodesSimulPack<2>, 2>; template class DomainContinuum, ContainerNodesSimulPack<3>, 3>; #endif #ifdef LIBMULTISCALE_MECA1D template class DomainContinuum; #endif #ifdef LIBMULTISCALE_AKANTU_PLUGIN template class DomainContinuum, ContainerNodesAkantu<1>, 1>; template class DomainContinuum, ContainerNodesAkantu<2>, 2>; template class DomainContinuum, ContainerNodesAkantu<3>, 3>; #endif __END_LIBMULTISCALE__ diff --git a/src/filter/compute_ekin.cc b/src/filter/compute_ekin.cc index a617d48..0d3580d 100644 --- a/src/filter/compute_ekin.cc +++ b/src/filter/compute_ekin.cc @@ -1,204 +1,204 @@ /** * @file compute_ekin.cc * * @author Guillaume Anciaux * * @date Wed Jul 09 21:59:47 2014 * * @brief This computes the kinetic energy of a set of DOFs * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "compute_ekin.hh" #include "lib_continuum.hh" #include "lib_dd.hh" #include "lib_md.hh" #include "lm_common.hh" #include "lm_communicator.hh" #include "ref_point_data.hh" #include "units.hh" #include "units_converter.hh" /* -------------------------------------------------------------------------- */ __BEGIN_LIBMULTISCALE__ ComputeEKin::ComputeEKin(const std::string &name) : LMObject(name), based_on_nodes_flag(false) { this->createInput("domain"); auto output_names = std::list{"nb_points", "Temperature", "EKin", "EKin_vector"}; this->createArrayOutputs(output_names); } /* -------------------------------------------------------------------------- */ ComputeEKin::~ComputeEKin() {} /* -------------------------------------------------------------------------- */ template enable_if_md ComputeEKin::build(Cont &cont) { constexpr UInt Dim = Cont::Dim; Array1D computed_ekin; computed_ekin = 0.; UInt cpt = cont.size(); for (auto &&at : cont) { Array1D vel = at.velocity(); computed_ekin += vel * vel * at.mass(); } computed_ekin *= 0.5 * code_unit_system.mvv2e; for (UInt i = 0; i < Dim; ++i) { DUMP("computed ekin[" << i << "] = " << computed_ekin[i], DBG_INFO); } CommGroup &group = cont.getCommGroup(); group.allReduce(computed_ekin.data(), Dim, "kinetic energy reduce", OP_SUM); group.allReduce(&cpt, 1, "kinetic energy counter reduce", OP_SUM); Real ekin = 0.0; for (UInt i = 0; i < Dim; ++i) { DUMP("ekin[" << i << "] = " << computed_ekin[i], DBG_INFO); ekin += computed_ekin[i]; } // compute temperature UnitsConverter unit; unit.setInUnits(code_unit_system); - unit.setOutUnits(real_unit_system); + unit.setOutUnits(si_unit_system); unit.computeConversions(); Real T = 2. / cpt / Dim / boltzmann * (ekin * unit.getConversion()); // convert the kinetic energies to the required unit systems // unit.setOutUnits(this->unit_system); // unit.computeConversions(); // ekin *= unit.getConversion(); // for (UInt i = 0; i < Dim; ++i) computed_ekin[i] *= // unit.getConversion(); DUMP("nb_points = " << cpt, DBG_INFO); this->clear(); Real nb_points = static_cast(cpt); this->getOutputAsArray("nb_points").push_back(nb_points); this->getOutputAsArray("Temperature").push_back(T); this->getOutputAsArray("EKin").push_back(ekin); this->getOutputAsArray("EKin_vector").resize(0, Dim); this->getOutputAsArray("EKin_vector").push_back(computed_ekin); } /* -------------------------------------------------------------------------- */ template enable_if_mesh ComputeEKin::build(Cont &cont) { constexpr UInt Dim = Cont::Dim; if (based_on_nodes_flag) { buildBasedOnNodes(cont); return; } Real computed_ekin = 0.0; for (auto &&el : cont.getContainerElems()) { computed_ekin += el.getEKin(); } CommGroup &group = cont.getCommGroup(); group.allReduce(&computed_ekin, 1, " kinetic energy reduce", OP_SUM); this->clear(); this->getOutputAsArray("EKin").push_back(computed_ekin); } /* -------------------------------------------------------------------------- */ template void ComputeEKin::buildBasedOnNodes(Cont &cont) { Vector computed_ekin = Array1D::Zero(); UInt cpt = cont.size(); for (auto &&at : cont.filter(~(dt_pbc_slave | dt_slave))) { auto vel = at.velocity(); computed_ekin += 0.5 * at.mass() * Vector(vel.array() * vel.array()) * code_unit_system.mvv2e; } CommGroup &group = cont.getCommGroup(); group.allReduce(&computed_ekin[0], Dim, "kinetic energy reduce", OP_SUM); group.allReduce(&cpt, 1, "kinetic energy counter reduce", OP_SUM); Real ekin = 0.0; for (UInt i = 0; i < Dim; ++i) { DUMP("ekin[" << i << "] = " << computed_ekin[i], DBG_INFO); ekin += computed_ekin[i]; } DUMP("nb_points = " << cpt, DBG_INFO); this->clear(); Real nb_points = static_cast(cpt); this->getOutputAsArray("nb_points").push_back(nb_points); this->getOutputAsArray("EKin").push_back(ekin); this->getOutputAsArray("EKin_vector").resize(0, Dim); this->getOutputAsArray("EKin_vector").push_back(computed_ekin); DUMP("Kinetic energy based on nodes could be higher than the one computed " "from elements.", DBG_WARNING); } /* -------------------------------------------------------------------------- */ /* LMDESC EKIN This computes the kinetic energy of the region provided as input */ /* LMEXAMPLE FILTER ekin EKIN INPUT md */ inline void ComputeEKin::declareParams() { ComputeInterface::declareParams(); /* LMKEYWORD BASED_ON_NODES Specify that the selection should be based on the nodes of the element. Valid for only FE. */ this->parseTag("BASED_ON_NODES", based_on_nodes_flag, false); } /* -------------------------------------------------------------------------- */ DECLARE_COMPUTE_MAKE_CALL(ComputeEKin) __END_LIBMULTISCALE__ diff --git a/src/md/domain_md.cc b/src/md/domain_md.cc index 0be5192..410a00e 100644 --- a/src/md/domain_md.cc +++ b/src/md/domain_md.cc @@ -1,208 +1,208 @@ /** * @file domain_md.cc * * @author Guillaume Anciaux * * @date Thu Nov 14 00:49:01 2013 * * @brief Mother to all molecular 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 "domain_md.hh" #include "cube.hh" #include "geometry_manager.hh" #include "lib_md.hh" #include "lm_common.hh" #include "lm_communicator.hh" #include "trace_atom.hh" #include "xml_parser_restart.hh" /* -------------------------------------------------------------------------- */ __BEGIN_LIBMULTISCALE__ /* -------------------------------------------------------------------------- */ template inline void DomainAtomic::readXMLFile(const std::string &filename) { XMLRestartParser parser; // UInt flag_memorysave_onrestart = material.mem_save_on_off; auto &group = this->getCommGroup(); int group_size = group.size(); int myrankingroup = group.getMyRank(); for (int i = 0; i < group_size; ++i) { if (myrankingroup != i) continue; DUMP("Setting DOFs simulation from libMultiScale XML Data format " << filename, DBG_INFO); if (parser.parseFile(filename, this->restart_continue_if_notfound)) { DUMP("restart was not performed because file was not found", DBG_WARNING); return; } // this->setCurrentStep(current_step); DUMP("read done " << filename, DBG_INFO); UnitsConverter unit; - unit.setInUnits(real_unit_system); + unit.setInUnits(si_unit_system); UInt cpt = 0; UInt cpt2 = 0; #ifndef LM_OPTIMIZED UInt total = atoms.size(); #endif // LM_OPTIMIZED for (auto &&at : atoms) { VectorView X = at.position0(); if (cpt2 % 100000 == 0) DUMP("passing atom number " << cpt2 << "/" << total << " reloaded", DBG_INFO_STARTUP); ++cpt2; IF_TRACED(X, "i see it"); if (!parser.isDofRegistered(X)) { DUMP("this atom " << X << ", was not reloaded: was not in restart file", DBG_DETAIL); IF_TRACED(X, "traced atom was not reloaded: was not in restart file"); continue; } Vector U; parser.assignDispField(X, U); DUMP("reloading atom at position " << X << " where disp = " << U, DBG_DETAIL); at.displacement() = U; Vector V; parser.assignVelField(X, V); at.velocity() = V; IF_TRACED(X, "reloading atom force " << at.force()); if (cpt % 100 == 0) DUMP("atom number " << cpt << "/" << total << " reloaded", DBG_INFO); ++cpt; } parser.cleanMemory(); DUMP("associated " << cpt << " over " << atoms.size(), DBG_MESSAGE); } DUMP("perform migration to have coherent stress and force values", DBG_INFO_STARTUP); // performMigration(); // perform migration in upper step // (domain_lammps.cc:initDOFs()) // performStep2(); } /* -------------------------------------------------------------------------- */ template inline Geometry &DomainAtomic::getGeom() { if (geom == invalidGeom) LM_FATAL("domain geometry has not been specified"); return *GeometryManager::getManager().getGeometry(geom); } /* -------------------------------------------------------------------------- */ template typename DomainAtomic::ContainerAtoms & DomainAtomic::getContainer() { atoms.acquireContext(*this); return atoms; } /* -------------------------------------------------------------------------- */ /* LMDESC DomainAtomic This section describe the section that is associated with molecular dynamics models. It is the starting point of every MD plugin. */ /* LMHERITANCE domain_interface */ template void DomainAtomic::declareParams() { DomainInterface::declareParams(); /* LMKEYWORD DOMAIN_GEOMETRY This describe the geometry where all degrees of freedom are located. LAMMPS and MD1D plugins enforce this constraint by refusing the creation of atoms outside of this geometry. Thus carving, selection, etc, are possible by means of this keyword. */ this->parseKeyword("DOMAIN_GEOMETRY", geom); /* LMKEYWORD TIMESTEP Sets the timestep */ this->parseKeyword("TIMESTEP", this->timeStep); } /* -------------------------------------------------------------------------- */ #ifdef LIBMULTISCALE_STAMP template class DomainAtomic; #endif #ifdef LIBMULTISCALE_LAMMPS_PLUGIN template class DomainAtomic, 2>; template class DomainAtomic, 3>; #endif #ifdef LIBMULTISCALE_MD1D template class DomainAtomic; #endif __END_LIBMULTISCALE__ diff --git a/src/parser/lm_parser.cc b/src/parser/lm_parser.cc index 0aca328..683d111 100644 --- a/src/parser/lm_parser.cc +++ b/src/parser/lm_parser.cc @@ -1,539 +1,539 @@ /** * @file lm_parser.cc * * @author Guillaume Anciaux * * @date Wed Jul 02 16:25:38 2014 * * @brief This is the central parser for 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 . * */ /* -------------------------------------------------------------------------- */ #include "lm_parser.hh" #include "coupler_manager.hh" #include "domain_multiscale.hh" #include "factory_multiscale.hh" #include "filter_interface.hh" #include "lm_common.hh" #include "lm_parsable.hh" #include /* -------------------------------------------------------------------------- */ __BEGIN_LIBMULTISCALE__ /* -------------------------------------------------------------------------- */ std::string Parser::getCurrentConfigFile() { return opened_files.back(); } /* -------------------------------------------------------------------------- */ UInt Parser::getCurrentLine() { return current_line.back(); } /* -------------------------------------------------------------------------- */ // void Parser::parseGeometry(GeomID & g,stringstream & line){ // parseString(g,line); // __attribute__((unused)) Geometry * geom = // GeometryManager::getManager().getGeometry(g); //} /* -------------------------------------------------------------------------- */ void Parser::freeMemory() { // math_parser.free_memory(); // DUMPFILE(fout,"memory cleaned"); fout.close(); } /* -------------------------------------------------------------------------- */ void Parser::getLine(std::ifstream &file, std::string &line, UInt ¤t_line) { line = ""; std::string tmp_line; getline(file, tmp_line); size_t found = tmp_line.find("\\"); ++current_line; while (found != std::string::npos) { line += tmp_line.substr(0, found - 1); getline(file, tmp_line); found = tmp_line.find("\\"); ++current_line; } line += tmp_line; } /* -------------------------------------------------------------------------- */ void Parser::rewindToLine(UInt line) { DUMPFILE(Parser::fout, "rewind to line" << line); std::ifstream &f = *opened_ifstreams.back(); f.seekg(0, std::ios_base::beg); std::string buffer; current_line.back() = 0; for (UInt i = 0; i < line - 1; ++i) { Parser::getLine(f, buffer, current_line.back()); if (current_line.back() == line - 1) break; } } /* -------------------------------------------------------------------------- */ void Parser::parseConfigFile(const std::string &file, const std::string §ion_name, const std::string §ion_id, Parsable &obj) { std::ifstream f; f.open(file.c_str()); if (!f.is_open()) { LM_FATAL("could not open config file " << file); } /// put the current file to stack opened_files.push_back(file); current_line.push_back(0); opened_ifstreams.push_back(&f); DUMP("parser state " << Parser::getParserState(), DBG_INFO); std::string buffer; bool section_flag = false; bool found_section = false; std::string mot; units_converter.setOutUnits(code_unit_system); - // section_units.push_back(real_unit_system); + // section_units.push_back(si_unit_system); while (f.good()) { Parser::getLine(f, buffer, current_line.back()); DUMP("treat line " << current_line.back(), DBG_DETAIL); unsigned long found = buffer.find_first_of("#"); std::string buffer_comment_free = buffer.substr(0, found - 1); buffer = buffer_comment_free; /* si il s'agit d'un commentaire on ne fait rien */ if (buffer[0] == '#' || buffer == "") { continue; } std::stringstream line(buffer); try { Parser::strNext(mot, line); } catch (LibMultiScaleException &e) { DUMP("Parser exception " << e.what() << std::endl << getParserState(), DBG_WARNING); continue; } if (!section_flag && mot == "Section") { Parser::strNext(mot, line); // search for ":" size_t pos = mot.find(":"); std::string id; std::string sec_name; if (pos != std::string::npos) { id = mot.substr(pos + 1); sec_name = mot.substr(0, pos); } else sec_name = mot; if (section_name == sec_name && id == section_id) { section_flag = true; found_section = true; UnitSystem units; try { Parser::parse(units, line); } catch (LibMultiScaleException &e) { LM_FATAL("unit system was not provided for section " << section_name); } section_units.push_back(units); units_converter.setInUnits(section_units.back()); units_converter.computeConversions(); continue; } } if (section_flag && mot == "endSection") { section_flag = false; section_units.pop_back(); if (section_units.size() > 0) units_converter.setInUnits(section_units.back()); units_converter.computeConversions(); } if (section_flag) { substituteVariables(buffer); UInt result = parseGenericKeywords(buffer, obj); if (!result) result = obj.parseLine(buffer); if (!result) LM_FATAL("not parsed line " << buffer); } } - // if (section_units.back() != real_unit_system) + // if (section_units.back() != si_unit_system) // LM_FATAL("problem in piling the section units"); if (!found_section) LM_FATAL("section named " << section_name << " with id " << section_id << " is missing"); /// pop the current file from stack opened_files.pop_back(); current_line.pop_back(); if (section_units.size() > 0) units_converter.setInUnits(section_units.back()); units_converter.computeConversions(); opened_ifstreams.pop_back(); DUMP("parser state " << opened_files.size() << " " << current_line.size() << " " << Parser::getParserState(), DBG_INFO); } /* -------------------------------------------------------------------------- */ void Parser::substituteVariables(std::string &str) { size_t pos = str.find("${"); while (pos != std::string::npos) { size_t pos2 = str.find("}", pos); if (pos2 == std::string::npos) LM_FATAL("syntax error: unclosed ${ } sequence \n" << Parser::getParserState()); std::string varname = str.substr(pos + 2, pos2 - pos - 2); Real res; try { math_parser.parse(varname, res); } catch (std::string mess) { LM_FATAL(getParserState() << std::endl << "\"" << str << "\"" << std::endl << mess); } std::stringstream tmp; tmp << res; str.replace(pos, pos2 - pos + 1, tmp.str()); pos = str.find("${"); } pos = str.find("$("); while (pos != std::string::npos) { size_t pos2 = str.find(")", pos); if (pos2 == std::string::npos) LM_FATAL("syntax error: unclosed $( ) sequence"); std::string varname = str.substr(pos + 2, pos2 - pos - 2); char *var = lm_getenv(varname.c_str()); if (var != NULL) str.replace(pos, pos2 - pos + 1, var); else LM_FATAL(getParserState() << std::endl << "\"" << str << "\"" << std::endl << "environment variable " << varname << " was not defined"); pos = str.find("$("); } } /* -------------------------------------------------------------------------- */ UInt Parser::parseGenericKeywords(std::string &linebuffer, Parsable &obj) { std::stringstream line(linebuffer); std::string mot; Parser::strNext(mot, line); if (mot == "LET") { std::stringstream var_buffer; try { while (1) { std::string mot; strNext(mot, line); var_buffer << mot << " "; } } catch (UnableToParseWord &e) { } catch (LibMultiScaleException &e) { LM_FATAL_RE(e, std::endl << getParserState()); } try { Real res; math_parser.parse(var_buffer.str(), res); } catch (LibMultiScaleException &e) { LM_FATAL_RE(e, std::endl << getParserState() << " cannot parse algebraic expression " << var_buffer.str()); } return true; } else if (mot == "PRINT") { Real value; if (math_parser.parse(line.str().substr(line.tellg()), value)) { std::string key; line >> key; DUMPFILE(fout, key << " = " << value); } else return false; return true; } else if (mot == "INCLUDE") { Parser::strNext(mot, line); if (mot == "this") { mot = opened_files.back(); } std::string section; try { strNext(section, line); } catch (LibMultiScaleException &e) { LM_FATAL(" Missing section name in line " << current_line.back() << ": '" << line.str() << "'" << getParserState()); } try { std::string id; strNext(id, line); parseConfigFile(mot, section, id, obj); } catch (LibMultiScaleException &e) { parseConfigFile(mot, section, "", obj); } return true; } else if (mot == "FOR") { std::string mot; // save starting point for_starting_line.push_back(current_line.back() + 1); Parser::strNext(mot, line); // read name of the for variable for_var.push_back(mot); Parser::strNext(mot, line); UInt pos = line.tellg(); if (mot != "in" || pos == line.str().length()) LM_FATAL(getParserState() << std::endl << "\"" << line.str() << "\"" << std::endl << "sytax error in for loop"); // construct the items to iterate std::string buffer = line.str().substr(pos); std::stringstream items(buffer); Parser::strNext(mot, items); std::list item_vec; if (mot == "range") { UInt start, end, increment; parse(start, items); parse(end, items); parse(increment, items); for (UInt i = start; i < end; i += increment) { std::stringstream sstr; sstr << i; item_vec.push_back(sstr.str()); } } else { while (!items.fail()) { item_vec.push_back(mot); try { Parser::strNext(mot, items); } catch (LibMultiScaleException &e) { } } } for_items.push_back(item_vec); std::string value; value = for_items.back().front(); for_items.back().pop_front(); // set the variable to the correct initial value Real res; math_parser.parse(for_var.back() + " = " + value, res); return true; } else if (mot == "endFOR") { UInt nb_items_left = for_items.back().size(); // set the variable to the next value if (nb_items_left == 0) { // it is the end of the loop then math_parser.eraseVariable(for_var.back()); for_starting_line.pop_back(); for_items.pop_back(); for_var.pop_back(); } else { std::string value; value = for_items.back().front(); for_items.back().pop_front(); DUMPFILE(Parser::fout, "inside of var loop " << for_var.back() << " now takes the value " << value); // set the variable to the correct initial value Real res; math_parser.parse(for_var.back() + " = " + value, res); // rewind the file to the correct line rewindToLine(for_starting_line.back()); } return true; } return false; } /* -------------------------------------------------------------------------- */ inline std::string Parser::getParserState() { std::stringstream res; char cwd[512]; std::fill(cwd, cwd + 512, 0); getcwd(cwd, 512); for (auto &&[file, line] : zip(opened_files, current_line)) { res << cwd << "/" << file << ":" << line << ":" << std::endl; } return res.str(); } /* -------------------------------------------------------------------------- */ std::map &Parser::getAlgebraicVariables() { return math_parser.getVariables(); } /* -------------------------------------------------------------------------- */ UInt Parser::strNext(std::string &str, std::stringstream &line) { UInt word_counter = 0; line >> str; if (line.fail()) throw UnableToParseWord(); ++word_counter; if (str[0] == '"') { str = str.substr(1); unsigned long found = str.find_first_of("\""); while (found == std::string::npos) { UInt pos = line.tellg(); if (pos < line.str().length()) { std::string tmp_str; line >> tmp_str; if (line.fail()) LM_THROW("unable to parse word"); ++word_counter; str += " " + tmp_str; found = str.find_first_of("\""); } else LM_FATAL("unterminated quoted sequence"); } if (found != str.size() - 1) LM_FATAL("quotes must be followed by a whitespace"); str = str.substr(0, found); } return word_counter; } /* -------------------------------------------------------------------------- */ void Parser::shiftLine(const ParseResult &parsed, std::stringstream &line) { std::string buf; for (UInt i = 0; i < parsed.nb_word_parsed; ++i) { line >> buf; if (line.fail()) LM_THROW("unable to shift " << parsed.nb_word_parsed << " words"); } } /* -------------------------------------------------------------------------- */ UInt _parse(Component &comp, std::stringstream &line, UInt) { std::string buffer; std::string component_name; std::string output_name = ""; std::string input_name; UInt nb = Parser::strNext(buffer, line); auto &inputs = comp.getInputs(); auto pos = buffer.find("="); if (pos != std::string::npos) { input_name = buffer.substr(0, pos); component_name = buffer.substr(pos + 1); } else if (inputs.size() == 1) { input_name = inputs.begin()->first; component_name = buffer; } else if (inputs.size() == 0) { component_name = buffer; LM_FATAL("has no input found while trying to connect " << component_name); } else { component_name = buffer; std::string str = "Input connector was not specifically provided.\n"; str += "However " + component_name + " has several connectors:\n"; for (auto i : inputs) { str += i.first + "\n"; } LM_FATAL(str); } pos = component_name.find("."); if (pos != std::string::npos) { output_name = component_name.substr(pos + 1); component_name = component_name.substr(0, pos); } DUMP(input_name << " " << component_name << " " << output_name, DBG_DETAIL); auto &input_component = getRegisteredComponent(component_name); if (&input_component == &comp) LM_FATAL("cannot connect a component to himself " << comp.getID()); comp.connect(input_name, input_component, output_name); return nb; } /* -------------------------------------------------------------------------- */ /// static instanciation /* -------------------------------------------------------------------------- */ UnitsConverter Parser::units_converter; std::vector Parser::section_units; AlgebraicExpressionParser Parser::math_parser; std::ofstream Parser::fout("log.parser", std::ios_base::out); std::vector Parser::opened_files; std::vector Parser::current_line; std::vector Parser::opened_ifstreams; std::vector Parser::for_starting_line; std::vector> Parser::for_items; std::vector Parser::for_var; __END_LIBMULTISCALE__