Commit 95423e3a by Christophe Geuzaine

basic onelab API + cleaned up onelabUtils/gmshLocalNetworkClient

parent 9d439550
......@@ -293,7 +293,7 @@ void PrintUsage(const std::string &name)
}
}
void GetOptions(int argc, char *argv[])
void GetOptions(int argc, char *argv[], bool readConfigFiles)
{
// print messages on terminal (use special 99 value so that we can detect if
// it was later set to 1 in the option file)
......@@ -301,9 +301,7 @@ void GetOptions(int argc, char *argv[])
CTX::instance()->terminal = 99;
#if defined(HAVE_PARSER)
if(argc && argv){
// parse session and option file (if argc/argv is not provided skip this
// step: this is usually what is expected when using Gmsh as a library)
if(readConfigFiles){
ParseFile(CTX::instance()->homeDir + CTX::instance()->sessionFileName, true);
ParseFile(CTX::instance()->homeDir + CTX::instance()->optionsFileName, true);
}
......
......@@ -24,6 +24,6 @@ std::vector<std::pair<std::string, std::string> > GetUsage();
std::vector<std::pair<std::string, std::string> > GetShortcutsUsage(const std::string &ctrl="");
std::vector<std::pair<std::string, std::string> > GetMouseUsage();
void PrintUsage(const std::string &name);
void GetOptions(int argc, char *argv[]);
void GetOptions(int argc, char *argv[], bool readConfigFiles);
#endif
......@@ -33,6 +33,7 @@ typedef unsigned long intptr_t;
#endif
#if defined(HAVE_ONELAB)
#include "onelabUtils.h"
#include "gmshLocalNetworkClient.h"
#endif
......@@ -53,7 +54,7 @@ typedef unsigned long intptr_t;
#include "onelabGroup.h"
#endif
int GmshInitialize(int argc, char **argv)
int GmshInitialize(int argc, char **argv, bool readConfigFiles)
{
Msg::SetNumThreads(1);
......@@ -76,7 +77,7 @@ int GmshInitialize(int argc, char **argv)
InitOptions(0);
// Read configuration files and command line options
GetOptions(argc, argv);
GetOptions(argc, argv, readConfigFiles);
// Make sure we have enough resources (stack)
CheckResources();
......@@ -246,7 +247,7 @@ int GmshFinalize()
// Delete static _interpolationSchemes of PViewData class
PViewData::removeAllInterpolationSchemes();
#endif
// Delete all Gmodels
while(GModel::list.size()>0) delete GModel::list[GModel::list.size()-1];
std::vector<GModel*>().swap(GModel::list);
......@@ -337,7 +338,7 @@ int GmshBatch()
// launch solver (if requested)
#if defined(HAVE_ONELAB)
solver_batch_cb((void*)(intptr_t)CTX::instance()->launchSolverAtStartup);
onelabUtils::runClient();
#endif
time_t now;
......@@ -352,7 +353,7 @@ int GmshBatch()
int GmshBatch(int argc, char **argv)
{
new GModel();
GmshInitialize(argc, argv);
GmshInitialize(argc, argv, true);
if(!Msg::GetGmshClient()) CTX::instance()->terminal = 1;
CTX::instance()->noPopup = 1;
GmshBatch();
......
......@@ -9,36 +9,36 @@
#include <string>
#include "GmshMessage.h"
int GmshInitialize(int argc=0, char **argv=0);
int GmshInitialize(int argc = 0, char **argv = 0, bool readConfigFiles = false);
int GmshSetMessageHandler(GmshMessage *callback);
GmshMessage *GmshGetMessageHandler();
int GmshSetBoundingBox(double xmin, double xmax,
double ymin, double ymax,
double zmin, double zmax);
int GmshSetOption(const std::string &category, const std::string &name,
std::string value, int index=0);
std::string value, int index = 0);
int GmshSetOption(const std::string &category, const std::string &name,
double value, int index=0);
double value, int index = 0);
int GmshSetOption(const std::string &category, const std::string &name,
unsigned int value, int index=0);
unsigned int value, int index = 0);
void GmshSetStringOption(const std::string &category, const std::string &name,
std::string value, int index=0);
std::string value, int index = 0);
void GmshSetNumberOption(const std::string &category, const std::string &name,
double value, int index=0);
double value, int index = 0);
void GmshSetColorOption(const std::string &category, const std::string &name,
unsigned int value, int index=0);
unsigned int value, int index = 0);
int GmshGetOption(const std::string &category, const std::string &name,
std::string &value, int index=0);
std::string &value, int index = 0);
int GmshGetOption(const std::string &category, const std::string &name,
double &value, int index=0);
double &value, int index = 0);
int GmshGetOption(const std::string &category, const std::string &name,
unsigned int &value, int index=0);
unsigned int &value, int index = 0);
std::string GmshGetStringOption(const std::string &category, const std::string &name,
int index=0);
int index = 0);
double GmshGetNumberOption(const std::string &category, const std::string &name,
int index=0);
int index = 0);
unsigned int GmshGetColorOption(const std::string &category, const std::string &name,
int index=0);
int index = 0);
int GmshRestoreDefaultOptions();
int GmshOpenProject(const std::string &fileName);
int GmshClearProject();
......@@ -48,6 +48,6 @@ int GmshWriteFile(const std::string &fileName);
int GmshFinalize();
int GmshBatch();
int GmshBatch(int argc, char **argv);
int GmshFLTK(int argc=0, char **argv=0);
int GmshFLTK(int argc = 0, char **argv = 0);
#endif
......@@ -27,6 +27,7 @@
#if defined(HAVE_ONELAB)
#include "onelab.h"
#include "onelabUtils.h"
#endif
#include "gmshLocalNetworkClient.h"
......@@ -1512,15 +1513,7 @@ void Msg::ImportPhysicalGroupsInOnelab()
void Msg::RunOnelabClient(const std::string &name, const std::string &command)
{
#if defined(HAVE_ONELAB)
onelab::remoteNetworkClient *c =
dynamic_cast<onelab::remoteNetworkClient*>(_onelabClient);
if(c){
c->runSubClient(name, command);
}
else{
gmshLocalNetworkClient client(name, command, "", true);
client.run();
}
onelabUtils::runClient(name, command);
#endif
}
......
......@@ -19,7 +19,7 @@ int main(int argc, char *argv[])
}
new GModel();
GmshInitialize(argc, argv);
GmshInitialize(argc, argv, true);
if(!Msg::GetGmshClient()) CTX::instance()->terminal = 1;
CTX::instance()->noPopup = 1;
......
......@@ -277,12 +277,12 @@ static std::string getSolverForExtension(const std::string &ext)
static int defineSolver(const std::string &name)
{
for(int i = 0; i < NUM_SOLVERS; i++){
int i;
for(i = 0; i < NUM_SOLVERS; i++){
if(opt_solver_name(i, GMSH_GET, "") == name) return i;
}
// overwrite last one
opt_solver_name(NUM_SOLVERS - 1, GMSH_SET|GMSH_GUI, name);
return NUM_SOLVERS - 1;
opt_solver_name(i - 1, GMSH_SET|GMSH_GUI, name);
return i - 1;
}
#endif
......
......@@ -53,6 +53,11 @@
#include "FlGui.h"
#endif
#if defined(HAVE_ONELAB)
#include "onelab.h"
#include "onelabUtils.h"
#endif
#include "gmsh.h" // automatically generated, in gmsh/api
static int _initialized = 0;
......@@ -72,13 +77,13 @@ static bool _isInitialized()
// gmsh
void gmsh::initialize(int argc, char **argv)
void gmsh::initialize(int argc, char **argv, bool readConfigFiles)
{
if(_initialized){
Msg::Error("Gmsh has aleady been initialized");
throw 1;
}
if(GmshInitialize(argc, argv)){
if(GmshInitialize(argc, argv, readConfigFiles)){
_initialized = 1;
_argc = argc;
_argv = new char*[_argc + 1];
......@@ -2288,3 +2293,41 @@ void gmsh::fltk::run()
throw -1;
#endif
}
// gmsh::onelab
void gmsh::onelab::get(std::string &data, const std::string &format)
{
if(!_isInitialized()){ throw -1; }
#if defined(HAVE_ONELAB)
if(format == "json")
::onelab::server::instance()->toJSON(data, "Gmsh");
else
Msg::Error("Unknown data format");
#else
Msg::Error("Onelab not available");
throw -1;
#endif
}
void gmsh::onelab::set(const std::string &data, const std::string &format)
{
if(!_isInitialized()){ throw -1; }
#if defined(HAVE_ONELAB)
if(format == "json")
::onelab::server::instance()->fromJSON(data);
else
Msg::Error("Unknown data format");
#else
Msg::Error("Onelab not available");
throw -1;
#endif
}
void gmsh::onelab::run(const std::string &name, const std::string &command)
{
if(!_isInitialized()){ throw -1; }
#if defined(HAVE_ONELAB)
onelabUtils::runClient(name, command);
#endif
}
......@@ -646,310 +646,5 @@ bool gmshLocalNetworkClient::kill()
return false;
}
void initializeLoops()
{
onelabUtils::initializeLoop("1");
onelabUtils::initializeLoop("2");
onelabUtils::initializeLoop("3");
#if defined(HAVE_FLTK)
if(FlGui::available() && onelab::server::instance()->getChanged())
FlGui::instance()->rebuildTree(false);
#endif
}
bool incrementLoops()
{
bool ret = false;
if(onelabUtils::incrementLoop("3")) ret = true;
else if(onelabUtils::incrementLoop("2")) ret = true;
else if(onelabUtils::incrementLoop("1")) ret = true;
//Define ONELAB parameter indicating whether or not in a loop
onelab::number n("0Metamodel/Loop",ret?1:0);
n.setVisible(false);
onelab::server::instance()->set(n);
#if defined(HAVE_FLTK)
if(FlGui::available() && onelab::server::instance()->getChanged())
FlGui::instance()->rebuildTree(false);
#endif
return ret;
}
void updateGraphs()
{
bool redraw = false;
for(int i = 0; i < 18; i++){
std::ostringstream tmp;
tmp << i;
bool ret = onelabUtils::updateGraph(tmp.str());
redraw = redraw || ret;
}
if(redraw){
// don't delete the widgets, as this is called in widget callbacks
#if defined(HAVE_FLTK)
FlGui::instance()->updateViews(true, false);
drawContext::global()->draw();
#endif
}
}
std::string timeStamp()
{
time_t now;
time(&now);
tm *t = localtime(&now);
char stamp[32];
// stamp.size() is always 20
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);
}
void saveDb(const std::string &fileName)
{
FILE *fp = Fopen(fileName.c_str(), "wb");
if(fp){
Msg::StatusBar(true, "Saving database '%s'...", fileName.c_str());
onelab::server::instance()->toFile(fp);
fclose(fp);
Msg::StatusBar(true, "Done saving database '%s'", fileName.c_str());
}
else
Msg::Error("Could not save database '%s'", fileName.c_str());
#if 0
fp = Fopen((fileName + ".json").c_str(), "wb");
if(fp){
std::string json;
onelab::server::instance()->toJSON(json, "Gmsh");
fwrite(json.c_str(), sizeof(char), json.size(), fp);
fclose(fp);
}
#endif
}
void archiveOutputFiles(const std::string &fileName)
{
std::string stamp;
std::vector<onelab::string> ps;
onelab::server::instance()->get(ps,"0Metamodel/9Tag");
if(ps.size() && ps[0].getValue().size())
stamp.assign(timeStamp() + "_" + ps[0].getValue());
else
stamp.assign(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();
names.push_back(strings[i].getValue());
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];
CreateSingleDir(split[0] + "archive/");
names[j] = split[0] + "archive/" + 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());
}
}
strings[i].setValue(names.back());
names.pop_back();
strings[i].setChoices(names);
onelab::server::instance()->set(strings[i]);
}
}
// save stamped db
{
std::vector<std::string> split = SplitFileName(fileName);
CreateSingleDir(split[0] + "archive/");
saveDb(split[0] + "archive/" + split[1] + stamp + split[2]);
}
#if defined(HAVE_FLTK)
FlGui::instance()->rebuildTree(true);
#endif
}
void archiveSolutionFiles(const std::string &fileName)
{
// extract tag from db fileName, use fileName as tag otherwise
std::vector<std::string> split = SplitFileName(fileName);
std::string dir = split[0] + "archive/";
std::string tag = split[1];
if (!tag.compare(0,6,"onelab"))
tag.assign(tag.substr(6)); // cut off 'onelab' if present
// add tag to all solution files in the db, and rename them on disk
std::vector<onelab::string> strings;
onelab::server::instance()->get(strings,"0Metamodel/9Solution files");
if(strings.size()){
std::vector<std::string> names = strings[0].getChoices();
if(names.size()){
for(unsigned int j = 0; j < names.size(); j++){
std::vector<std::string> split = SplitFileName(names[j]);
std::string old = names[j];
CreateSingleDir(dir);
names[j] = dir + split[1] + tag + split[2];
Msg::Info("Renaming '%s' into '%s'", old.c_str(), names[j].c_str());
rename(old.c_str(), names[j].c_str());
}
strings[0].setValue(names[0]);
strings[0].setChoices(names);
onelab::server::instance()->set(strings[0]);
#if defined(HAVE_FLTK)
FlGui::instance()->rebuildTree(true);
#endif
}
}
}
void loadDb(const std::string &name)
{
Msg::StatusBar(true, "Loading database '%s'...", name.c_str());
FILE *fp = Fopen(name.c_str(), "rb");
if(fp){
onelab::server::instance()->fromFile(fp);
fclose(fp);
Msg::StatusBar(true, "Done loading database '%s'", name.c_str());
}
else
Msg::Error("Could not load database '%s'", name.c_str());
}
void resetDb(bool runGmshClient)
{
Msg::Info("Resetting database");
// clear everything except persistent parameters
std::vector<onelab::number> allNumbers, persistentNumbers;
std::vector<onelab::string> allStrings, persistentStrings;
onelab::server::instance()->get(allNumbers);
onelab::server::instance()->get(allStrings);
for(unsigned int i = 0; i < allNumbers.size(); i++){
if(allNumbers[i].getAttribute("Persistent") == "1")
persistentNumbers.push_back(allNumbers[i]);
}
for(unsigned int i = 0; i < allStrings.size(); i++){
if(allStrings[i].getAttribute("Persistent") == "1")
persistentStrings.push_back(allStrings[i]);
}
// clear the db
onelab::server::instance()->clear();
// run Gmsh client for non-python metamodels
if(runGmshClient && onelab::server::instance()->findClient("Gmsh") !=
onelab::server::instance()->lastClient())
onelabUtils::runGmshClient("reset", CTX::instance()->solver.autoMesh);
for(unsigned int i = 0; i < persistentNumbers.size(); i++){
Msg::Debug("Restoring persistent parameter %s",
persistentNumbers[i].getName().c_str());
onelab::server::instance()->set(persistentNumbers[i]);
}
for(unsigned int i = 0; i < persistentStrings.size(); i++){
Msg::Debug("Restoring persistent parameter %s",
persistentStrings[i].getName().c_str());
onelab::server::instance()->set(persistentStrings[i]);
}
// mark all parameters as changed
onelab::server::instance()->setChanged(3);
}
void solver_batch_cb(void *data)
{
int num = (intptr_t)data;
std::string name, exe, host;
if(num == -1){
// no solver to run
return;
}
else if(num == -2){
// just run local Gmsh client
}
else if(num >= 0){
// run local Gmsh client + solver num
name = opt_solver_name(num, GMSH_GET, "");
exe = opt_solver_executable(num, GMSH_GET, "");
host = opt_solver_remote_login(num, GMSH_GET, "");
if(exe.empty()){
Msg::Error("Solver executable name not provided");
return;
}
}
else{
Msg::Error("Unknown client to run in batch mode (%d)", num);
return;
}
onelab::number n("0Metamodel/Batch", CTX::instance()->batch);
n.setVisible(false);
onelab::server::instance()->set(n);
// create client
onelab::localNetworkClient *c = 0;
onelab::string o;
if(name.size()){
c = new gmshLocalNetworkClient(name, exe, host);
c->setIndex(num);
o = c->getName() + "/Action";
}
// initialize
onelabUtils::runGmshClient("initialize", CTX::instance()->solver.autoMesh);
if(c){
o.setValue("initialize");
onelab::server::instance()->set(o);
c->run();
}
// load db
if(CTX::instance()->solver.autoLoadDatabase){
std::vector<std::string> split = SplitFileName(GModel::current()->getFileName());
std::string db = split[0] + split[1] + ".db";
if(!StatFile(db)) loadDb(db);
}
// check
onelabUtils::runGmshClient("check", CTX::instance()->solver.autoMesh);
if(c){
onelabUtils::guessModelName(c);
o.setValue("check");
onelab::server::instance()->set(o);
c->run();
}
// compute
initializeLoops();
do{
onelabUtils::runGmshClient("compute", CTX::instance()->solver.autoMesh);
if(c){
onelabUtils::guessModelName(c);
o.setValue("compute");
onelab::server::instance()->set(o);
c->run();
onelab::server::instance()->setChanged(0, c->getName());
}
} while(incrementLoops());
if(CTX::instance()->solver.autoSaveDatabase ||
CTX::instance()->solver.autoArchiveOutputFiles){
std::vector<std::string> split = SplitFileName(GModel::current()->getFileName());
std::string db = split[0] + split[1] + ".db";
if(CTX::instance()->solver.autoArchiveOutputFiles) archiveOutputFiles(db);
if(CTX::instance()->solver.autoSaveDatabase) saveDb(db);
}
}
#endif
......@@ -69,18 +69,6 @@ class gmshLocalNetworkClient : public onelab::localNetworkClient{
bool kill();
};
// FIXME: move this to onelabUtils
void initializeLoops();
bool incrementLoops();
void updateGraphs();
std::string timeStamp();
void saveDb(const std::string &fileName);
void archiveOutputFiles(const std::string &fileName);
void archiveSolutionFiles(const std::string &fileName);
void loadDb(const std::string &name);
void resetDb(bool runGmshClient);
void solver_batch_cb(void *data);
#endif
#endif
......@@ -871,11 +871,6 @@ namespace onelab{
}
return NULL;
}
void _getAllParameters(std::set<parameter*, parameterLessThan> &ps) const
{
ps.insert(_numbers.begin(), _numbers.end());
ps.insert(_strings.begin(), _strings.end());
}
public:
parameterSpace(){}
~parameterSpace(){ clear(); }
......@@ -883,7 +878,7 @@ namespace onelab{
{
if(name.empty() && client.empty()){
std::set<parameter*, parameterLessThan> ps;
_getAllParameters(ps);
getAllParameters(ps);
for(std::set<parameter*, parameterLessThan>::iterator it = ps.begin();
it != ps.end(); it++)
delete *it;
......@@ -934,7 +929,7 @@ namespace onelab{
bool hasClient(const std::string &client) const
{
std::set<parameter*, parameterLessThan> ps;
_getAllParameters(ps);
getAllParameters(ps);
for(std::set<parameter*, parameterLessThan>::iterator it = ps.begin();
it != ps.end(); it++)
if((*it)->hasClient(client)) return true;
......@@ -945,7 +940,7 @@ namespace onelab{
int getChanged(const std::string &client="") const
{
std::set<parameter*, parameterLessThan> ps;
_getAllParameters(ps);
getAllParameters(ps);
int changed = 0;
for(std::set<parameter*, parameterLessThan>::iterator it = ps.begin();
it != ps.end(); it++){
......@@ -958,7 +953,7 @@ namespace onelab{
void setChanged(int changed, const std::string &client="")
{
std::set<parameter*, parameterLessThan> ps;
_getAllParameters(ps);
getAllParameters(ps);
for(std::set<parameter*, parameterLessThan>::iterator it = ps.begin();
it != ps.end(); it++)
(*it)->setChanged(changed, client);
......@@ -966,7 +961,7 @@ namespace onelab{
void thresholdChanged(int threshold, const std::string &client="")
{
std::set<parameter*, parameterLessThan> ps;
_getAllParameters(ps);
getAllParameters(ps);
for(std::set<parameter*, parameterLessThan>::iterator it = ps.begin();
it != ps.end(); it++){
int changed = (*it)->getChanged(client);
......@@ -980,7 +975,7 @@ namespace onelab{
{
std::vector<std::string> s;
std::set<parameter*, parameterLessThan> ps;
_getAllParameters(ps);
getAllParameters(ps);
for(std::set<parameter*, parameterLessThan>::const_iterator it = ps.begin();
it != ps.end(); it++)
if(client.empty() || (*it)->hasClient(client)){
......@@ -1021,7 +1016,7 @@ namespace onelab{
json += " \"version\":\"" + parameter::version() + "\",\n";
json += " \"parameters\":[\n";
std::set<parameter*, parameterLessThan> ps;
_getAllParameters(ps);
getAllParameters(ps);
for(std::set<parameter*, parameterLessThan>::const_iterator it = ps.begin();
it != ps.end(); it++){
if(it != ps.begin()) json += ",\n";
......@@ -1034,9 +1029,9 @@ namespace onelab{
json += "\n ] }\n}\n";
return true;
}
#if defined(HAVE_PICOJSON)
bool fromJSON(const std::string &json, const std::string &client="")
{
#if defined(HAVE_PICOJSON)
picojson::value v;
std::string err = picojson::parse(v, json);
if(err.size()) return false;
......@@ -1071,8 +1066,10 @@ namespace onelab{
}
}
return true;
}
#else
return false;
#endif
}
};
// The onelab client: a class that communicates with the onelab server. Each
......@@ -1237,12 +1234,10 @@ namespace onelab{
{
return _parameterSpace.toJSON(json, client);
}
#if defined(HAVE_PICOJSON)
bool fromJSON(const std::string &json, const std::string &client="")
{
return _parameterSpace.fromJSON(json, client);
}
#endif
};
// A local client, which lives in the same memory space as the server.
......
......@@ -20,12 +20,21 @@ namespace onelabUtils {
std::vector<double> getRange(onelab::number &p);
bool updateGraph(const std::string &graphNum);
bool runGmshClient(const std::string &action, int meshAuto);
void runClient(const std::string &name = "", const std::string &command = "");