diff --git a/Common/Context.h b/Common/Context.h index d5334e3ae8bec2874d610dfbd3bdbdb2567e49c7..8b73991768e5e973800e5611852f71b5baa68610 100644 --- a/Common/Context.h +++ b/Common/Context.h @@ -222,8 +222,8 @@ class CTX { double timeout; std::string socketName; std::string name[5], executable[5], remoteLogin[5]; - int autoSaveDatabase, autoMesh, autoMergeFile, autoHideNewViews; - int autoShowLastStep; + int autoSaveDatabase, autoArchiveSolutions, autoMesh, autoMergeFile; + int autoHideNewViews, autoShowLastStep; }solver; // print options struct{ diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h index 2e16285449c9e78d6bc3af624453ad4f869cdc1d..ce78bb75366d307c5d13e61832eeb9d56b08268c 100644 --- a/Common/DefaultOptions.h +++ b/Common/DefaultOptions.h @@ -1106,6 +1106,8 @@ StringXNumber MeshOptions_Number[] = { StringXNumber SolverOptions_Number[] = { { F|O, "AlwaysListen" , opt_solver_listen , 0. , "Always listen to incoming connection requests?" }, + { F|O, "AutoArchiveSolutions" , opt_solver_auto_archive_solutions , 0. , + "Automatically archive solutions after each computation" }, { F|O, "AutoSaveDatabase" , opt_solver_auto_save_database , 0. , "Automatically save database after each computation" }, { F|O, "AutoMesh" , opt_solver_auto_mesh , 1. , diff --git a/Common/Options.cpp b/Common/Options.cpp index ef5328c640b6421d6cd8c0d99693100c7e09f989..62f86bf6c06882cace68d0875ba6eb786b11501d 100644 --- a/Common/Options.cpp +++ b/Common/Options.cpp @@ -5732,6 +5732,13 @@ double opt_solver_auto_save_database(OPT_ARGS_NUM) return CTX::instance()->solver.autoSaveDatabase; } +double opt_solver_auto_archive_solutions(OPT_ARGS_NUM) +{ + if(action & GMSH_SET) + CTX::instance()->solver.autoArchiveSolutions = (int)val; + return CTX::instance()->solver.autoArchiveSolutions; +} + double opt_solver_auto_mesh(OPT_ARGS_NUM) { if(action & GMSH_SET) diff --git a/Common/Options.h b/Common/Options.h index 52d0def1e22c9dff5e573f67e8527120e53b8bd6..6c6e2e7ef682383dcc2d66e47054eeba464ede93 100644 --- a/Common/Options.h +++ b/Common/Options.h @@ -469,6 +469,7 @@ double opt_solver_listen(OPT_ARGS_NUM); double opt_solver_timeout(OPT_ARGS_NUM); double opt_solver_plugins(OPT_ARGS_NUM); double opt_solver_auto_save_database(OPT_ARGS_NUM); +double opt_solver_auto_archive_solutions(OPT_ARGS_NUM); double opt_solver_auto_mesh(OPT_ARGS_NUM); double opt_solver_auto_merge_file(OPT_ARGS_NUM); double opt_solver_auto_hide_new_views(OPT_ARGS_NUM); diff --git a/Fltk/onelabWindow.cpp b/Fltk/onelabWindow.cpp index c80324cc02f8baed4448a99a87dcba9186fb2ec4..7964dc6852ce5547699b5860da75fadb9c382615 100644 --- a/Fltk/onelabWindow.cpp +++ b/Fltk/onelabWindow.cpp @@ -384,49 +384,49 @@ static void updateGraphs() } } -static void saveDb(const std::string &fileName, bool withTimeStamp=false) +static std::string timeStamp() { - std::string name(fileName); - if(withTimeStamp){ - // create time stamp - time_t now; - time(&now); - tm *t = localtime(&now); - char stamp[32]; - sprintf(stamp, "_%04d-%02d-%02d_%02d-%02d-%02d", 1900 + t->tm_year, - 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); - - // add time stamp in all output files in the db, and rename them on disk - std::vector<onelab::string> strings; - onelab::server::instance()->get(strings); - for(unsigned int i = 0; i < strings.size(); i++){ - if(strings[i].getName().find("9Output files") != std::string::npos){ - std::vector<std::string> names = strings[i].getChoices(); - for(unsigned int j = 0; j < names.size(); j++){ - std::vector<std::string> split = SplitFileName(names[j]); - int n = split[1].size(); - // if name is not already stamped - if(n < 18 || split[1][n-3] != '-' || split[1][n-6] != '-' || - split[1][n-9] != '_'){ - std::string old = names[j]; - names[j] = split[0] + split[1] + stamp + split[2]; - Msg::Info("Renaming '%s' into '%s'", old.c_str(), names[j].c_str()); - rename(old.c_str(), names[j].c_str()); - } + time_t now; + time(&now); + tm *t = localtime(&now); + char stamp[32]; + sprintf(stamp, "_%04d-%02d-%02d_%02d-%02d-%02d", 1900 + t->tm_year, + 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); + return std::string(stamp); +} + +static void archiveSolutions(const std::string &timeStamp) +{ + // add time stamp in all output files in the db, and rename them on disk + std::vector<onelab::string> strings; + onelab::server::instance()->get(strings); + for(unsigned int i = 0; i < strings.size(); i++){ + if(strings[i].getName().find("9Output files") != std::string::npos){ + std::vector<std::string> names = strings[i].getChoices(); + for(unsigned int j = 0; j < names.size(); j++){ + std::vector<std::string> split = SplitFileName(names[j]); + int n = split[1].size(); + // if name is not already stamped + if(n < 18 || split[1][n-3] != '-' || split[1][n-6] != '-' || + split[1][n-9] != '_'){ + std::string old = names[j]; + names[j] = split[0] + split[1] + timeStamp + split[2]; + Msg::Info("Renaming '%s' into '%s'", old.c_str(), names[j].c_str()); + rename(old.c_str(), names[j].c_str()); } - strings[i].setChoices(names); - strings[i].setValue(names.back()); - onelab::server::instance()->set(strings[i]); } + strings[i].setChoices(names); + strings[i].setValue(names.back()); + onelab::server::instance()->set(strings[i]); } - - { - std::vector<std::string> split = SplitFileName(fileName); - name = split[0] + split[1] + stamp + split[2]; - } - FlGui::instance()->onelab->rebuildTree(); } + FlGui::instance()->onelab->rebuildTree(); +} +static void saveDb(const std::string &fileName, const std::string &timeStamp="") +{ + std::vector<std::string> split = SplitFileName(fileName); + std::string name = split[0] + split[1] + timeStamp + split[2]; Msg::StatusBar(2, true, "Saving database '%s'...", name.c_str()); if(onelab::server::instance()->toFile(name)) Msg::StatusBar(2, true, "Done saving database '%s'", name.c_str()); @@ -577,9 +577,12 @@ void onelab_cb(Fl_Widget *w, void *data) } while(action == "compute" && !FlGui::instance()->onelab->stop() && incrementLoops()); - if(CTX::instance()->solver.autoSaveDatabase && action == "compute"){ - std::string s = SplitFileName(GModel::current()->getFileName())[0] + "onelab.db"; - saveDb(s, true); + if(action == "compute" && (CTX::instance()->solver.autoSaveDatabase || + CTX::instance()->solver.autoArchiveSolutions)){ + std::string db = SplitFileName(GModel::current()->getFileName())[0] + "onelab.db"; + std::string stamp = timeStamp(); + if(CTX::instance()->solver.autoArchiveSolutions) archiveSolutions(stamp); + if(CTX::instance()->solver.autoSaveDatabase) saveDb(db, stamp); } FlGui::instance()->onelab->stop(false); @@ -595,6 +598,8 @@ void onelab_option_cb(Fl_Widget *w, void *data) double val = ((Fl_Menu_*)w)->mvalue()->value() ? 1. : 0.; if(what == "save") CTX::instance()->solver.autoSaveDatabase = val; + else if(what == "archive") + CTX::instance()->solver.autoArchiveSolutions = val; else if(what == "merge") CTX::instance()->solver.autoMergeFile = val; else if(what == "hide") @@ -717,6 +722,8 @@ onelabWindow::onelabWindow(int deltaFontSize) _gear->add("Save database automatically", 0, onelab_option_cb, (void*)"save", FL_MENU_TOGGLE); + _gear->add("Archive solutions automatically", 0, onelab_option_cb, (void*)"archive", + FL_MENU_TOGGLE); _gear->add("Remesh automatically", 0, onelab_option_cb, (void*)"mesh", FL_MENU_TOGGLE); _gear->add("Merge results automatically", 0, onelab_option_cb, (void*)"merge", @@ -1198,12 +1205,13 @@ void onelabWindow::rebuildSolverList() // update OneLab window title and gear menu _title = "OneLab"; Fl_Menu_Item* menu = (Fl_Menu_Item*)_gear->menu(); - int values[5] = {CTX::instance()->solver.autoSaveDatabase, + int values[6] = {CTX::instance()->solver.autoSaveDatabase, + CTX::instance()->solver.autoArchiveSolutions, CTX::instance()->solver.autoMesh, CTX::instance()->solver.autoMergeFile, CTX::instance()->solver.autoHideNewViews, CTX::instance()->solver.autoShowLastStep}; - for(int i = 0; i < 5; i++){ + for(int i = 0; i < 6; i++){ int idx = _gearOptionsStart - 1 + i; if(values[i]) menu[idx].set();