diff --git a/src/Handlers/acRemoteForceInterface.cpp b/src/Handlers/acRemoteForceInterface.cpp index 93e3625c..c1198245 100644 --- a/src/Handlers/acRemoteForceInterface.cpp +++ b/src/Handlers/acRemoteForceInterface.cpp @@ -2,6 +2,8 @@ std::string acRemoteForceInterface::xmlname = "RemoteForceInterface"; #include "../HandlerFactory.h" +#include + int acRemoteForceInterface::Init () { Action::Init(); pugi::xml_attribute attr = node.attribute("integrator"); @@ -22,6 +24,26 @@ int acRemoteForceInterface::ConnectRemoteForceInterface(std::string integrator_) solver->lattice->RFI.setUnits(units[0],units[1],units[2]); solver->lattice->RFI.CanCopeWithUnits(false); + solver->lattice->RFI.setVar("output", solver->info.outpath); + + + std::string element_content; + int node_children = 0; + for (pugi::xml_node par = node.first_child(); par; par = par.next_sibling()) { + node_children ++; + if (node_children > 1) { + ERROR("Only a single element/CDATA allowed inside of a RemoteForceInterface xml element\n"); + return -1; + } + if ((par.type() == pugi::node_pcdata) || (par.type() == pugi::node_cdata)) { + element_content = par.value(); + } else { + std::stringstream ss; + par.print(ss); + element_content = ss.str(); + } + } + if (node_children > 0) solver->lattice->RFI.setVar("content", element_content); bool stats = false; std::string stats_prefix = solver->info.outpath; stats_prefix = stats_prefix + "_RFI"; diff --git a/src/RemoteForceInterface.h b/src/RemoteForceInterface.h index af70e81c..1dc10912 100644 --- a/src/RemoteForceInterface.h +++ b/src/RemoteForceInterface.h @@ -6,6 +6,7 @@ #include #include #include +#include namespace rfi { @@ -94,6 +95,10 @@ class RemoteForceInterface { std::vector< rfi_real_t > unit; bool non_trivial_units; bool can_cope_with_units; + typedef std::string vars_name_t; + typedef std::string vars_value_t; + typedef std::map< vars_name_t, vars_value_t > vars_t; + vars_t vars; void ISendSizes(); void WSendSizes(); void ISendParticles(); @@ -114,6 +119,7 @@ class RemoteForceInterface { public: int particle_size; std::string name; + rfi_real_t auto_timestep; RemoteForceInterface(); ~RemoteForceInterface(); void MakeTypes(bool,bool); @@ -143,6 +149,9 @@ class RemoteForceInterface { template inline std::vector Exchange(std::vector out); template inline std::basic_string Exchange(std::basic_string out); void setUnits(rfi_real_t meter, rfi_real_t second, rfi_real_t kilogram); + void setVar(const vars_name_t& name, const vars_value_t& value); + bool hasVar(const vars_name_t& name) { return vars.find(name) != vars.end(); }; + const vars_value_t& getVar(const vars_name_t& name) { return vars[name]; }; inline rfi_real_t& RawData(size_t i, int j) { if (STORAGE == ArrayOfStructures) { return tab[i*particle_size + j]; diff --git a/src/RemoteForceInterface.hpp b/src/RemoteForceInterface.hpp index e1553dcf..7eb3e05f 100644 --- a/src/RemoteForceInterface.hpp +++ b/src/RemoteForceInterface.hpp @@ -18,7 +18,7 @@ namespace rfi { -const int version = 0x000104; +const int version = 0x000105; #define safe_MPI_Type_free(datatype) { if ((*datatype) != NULL) MPI_Type_free(datatype); } @@ -117,6 +117,7 @@ RemoteForceInterface < TYPE, ROT, STORAGE, rfi_real_t, tab_allocator >::RemoteFo base_units[0] = 1.0; base_units[1] = 1.0; base_units[2] = 1.0; + auto_timestep = 1.0; non_trivial_units = false; can_cope_with_units = true; } @@ -211,6 +212,15 @@ inline void RemoteForceInterface < TYPE, ROT, STORAGE, rfi_real_t, tab_allocator non_trivial_units = true; } +template < rfi_type_t TYPE, rfi_rot_t ROT, rfi_storage_t STORAGE, typename rfi_real_t, typename tab_allocator > +inline void RemoteForceInterface < TYPE, ROT, STORAGE, rfi_real_t, tab_allocator >::setVar(const vars_name_t& name, const vars_value_t& value) { + if (Connected()) { + ERROR("Vars can be set only before connection is established\n"); + exit(-1); + } + vars[name] = value; +} + template < rfi_type_t TYPE, rfi_rot_t ROT, rfi_storage_t STORAGE, typename rfi_real_t, typename tab_allocator > inline void RemoteForceInterface < TYPE, ROT, STORAGE, rfi_real_t, tab_allocator >::CanCopeWithUnits(bool ccwu_) { if (Connected()) { @@ -362,6 +372,43 @@ int RemoteForceInterface < TYPE, ROT, STORAGE, rfi_real_t, tab_allocator >::Nego unit[RFI_DATA_FORCE+i] = kilogram*meter/(second*second); unit[RFI_DATA_MOMENT+i] = kilogram*meter*meter/(second*second); } + auto_timestep = 1.0/second; + } + + typedef std::vector vars_pack_t; + vars_pack_t my_vars, other_vars; + for (vars_t::const_iterator it = vars.begin(); it != vars.end(); it++) { + std::string v; + v = it->first; + for (std::string::const_iterator it2 = v.begin(); it2 != v.end(); it2++) my_vars.push_back(*it2); + my_vars.push_back(0); + v = it->second; + for (std::string::const_iterator it2 = v.begin(); it2 != v.end(); it2++) my_vars.push_back(*it2); + my_vars.push_back(0); + } + other_vars = Exchange(my_vars); + bool is_name = true; + std::string buf; + std::string name_buf; + std::string value_buf; + for (vars_pack_t::const_iterator it = other_vars.begin(); it != other_vars.end(); it++) { + if (*it == 0) { + if (is_name) { + name_buf = buf; + is_name = false; + } else { + value_buf = buf; + is_name = true; + debug1("RFI: %s: Received: %s = %s\n",name.c_str(), name_buf.c_str(), value_buf.c_str()); + if (vars.find(name_buf) != vars.end()) { + debug1("RFI: %s: Variable overwritten.", name.c_str()); + } + vars[name_buf] = value_buf; + } + buf.clear(); + } else { + buf.push_back(*it); + } } } diff --git a/src/simplepart.cpp b/src/simplepart.cpp index 2303796a..e5f5b582 100644 --- a/src/simplepart.cpp +++ b/src/simplepart.cpp @@ -88,10 +88,11 @@ int main(int argc, char *argv[]) { wsize.resize(RFI.Workers()); windex.resize(RFI.Workers()); Particles particles; - double dt = 0; + double dt = RFI.auto_timestep; bool logging = false; - std::string logging_filename; + std::string logging_filename = ""; + if (RFI.hasVar("output")) logging_filename = RFI.getVar("output") + "_SP_Log.csv"; int logging_iter = 1; FILE* logging_f = NULL; bool avg = false; @@ -115,14 +116,33 @@ int main(int argc, char *argv[]) { for (int i = 0; i < 3; i++) acc_vec[i] = 0.0; acc_freq = 0.0; - if (argc != 2) { + if (argc < 1 || argc > 2) { printf("Syntax: simplepart config.xml\n"); + printf(" You can omit config.xml if configuration is provided by the force calculator (eg. TCLB xml)\n"); MPI_Abort(MPI_COMM_WORLD,1); exit(1); } - char * filename = argv[1]; + + char * filename = NULL; + if (argc > 1) { + filename = argv[1]; + } pugi::xml_document config; - pugi::xml_parse_result result = config.load_file(filename, pugi::parse_default | pugi::parse_comments); + pugi::xml_parse_result result; + if (filename != NULL) { + if (RFI.hasVar("content")) { + WARNING("Ignoring content (configuration) sent by calculator"); + } + result = config.load_file(filename, pugi::parse_default | pugi::parse_comments); + } else { + if (RFI.hasVar("content")) { + result = config.load_string(RFI.getVar("content").c_str(), pugi::parse_default | pugi::parse_comments); + } else { + printf("No configuration provided (either xml file or content from force calculator\n"); + MPI_Abort(MPI_COMM_WORLD,1); + exit(1); + } + } if (!result) { ERROR("Error while parsing %s: %s\n", filename, result.description()); return -1; @@ -200,8 +220,8 @@ int main(int argc, char *argv[]) { } for (pugi::xml_attribute attr = node.first_attribute(); attr; attr = attr.next_attribute()) { std::string attr_name = attr.name(); + logging = true; if (attr_name == "name") { - logging = true; logging_filename = attr.value(); } else if (attr_name == "Iterations") { logging_iter = attr.as_int(); @@ -221,8 +241,8 @@ int main(int argc, char *argv[]) { return -1; } } - if (!logging) { - ERROR("Name not set in '%s' element", node.name()); + if (logging && logging_filename == "") { + ERROR("Loggin file name not set in '%s' element", node.name()); return -1; } } else {