1 // GetDP - Copyright (C) 1997-2021 P. Dular and C. Geuzaine, University of Liege
2 //
3 // See the LICENSE.txt file for license information. Please report all
4 // issues on https://gitlab.onelab.info/getdp/getdp/issues.
5 
6 #include <sstream>
7 #include <vector>
8 #include <string>
9 #include <string.h>
10 #include "GetDPConfig.h"
11 #include "GetDPVersion.h"
12 #include "onelab.h"
13 #include "ProData.h"
14 #include "ProParser.h"
15 #include "SolvingAnalyse.h"
16 #include "LinAlg.h"
17 #include "OS.h"
18 #include "MallocUtils.h"
19 #include "Message.h"
20 
21 #if defined(HAVE_GMSH)
22 #include <gmsh.h>
23 // these will disappear
24 #include <gmsh/GmshGlobal.h>
25 #include <gmsh/GmshVersion.h>
26 #include <gmsh/GmshConfig.h>
27 #include <gmsh/PView.h>
28 #endif
29 
30 int     Flag_PRE = 0, Flag_CAL = 0, Flag_POS = 0, Flag_RESTART = 0;
31 int     Flag_XDATA = 0, Flag_BIN = 0, Flag_SPLIT = 0, Flag_GMSH_VERSION = 1;
32 int     Flag_NETWORK_CACHE = 0, Flag_CALLED_WITH_ONELAB_SERVER = 0;
33 int     Flag_SLEPC = 0;
34 double  Flag_ORDER = -1., Flag_MSH_SCALING = 1.;
35 char   *Name_Generic = 0, *Name_Path = 0;
36 char   *Name_Resolution = 0;
37 char   *Name_MshFile = 0, *Name_AdaptFile = 0;
38 char   *Name_PostOperation[NBR_MAX_POS] = {0};
39 char   *Name_ResFile[NBR_MAX_RES] = {0};
40 char   *Name_GmshReadFile[NBR_MAX_RES] = {0};
41 int     Tag_GmshReadFile[NBR_MAX_RES] = {-1};
42 
Info(int level,char * arg0)43 static void Info(int level, char *arg0)
44 {
45   switch(level){
46   case 0 :
47     fprintf(stderr,
48 	    "GetDP, a General environment for the treatment of Discrete Problems\n"
49 	    "Copyright (C) 1997-2021 P. Dular and C. Geuzaine, University of Liege\n"
50 	    "Usage: %s [file] [options]\n"
51 	    "Processing options:\n"
52 	    "  -pre 'Resolution'         pre-processing\n"
53 	    "  -cal                      processing\n"
54 	    "  -pos 'PostOperation(s)'   post-processing\n"
55 	    "  -msh file                 read mesh (in msh format) from file\n"
56             "  -msh_scaling value        scale the input mesh by the given value\n"
57             "  -gmshread file(s)         read gmsh data (same as GmshRead in resolution)\n"
58             "  -gmshtag tag(s)           tag(s) associated to GmshRead data\n"
59 	    "  -restart                  resume processing from where it stopped\n"
60 	    "  -solve 'Resolution'       same as -pre 'Resolution' -cal\n"
61 	    "  -split                    save processing results in separate files\n"
62 	    "  -res file(s)              load processing results from file(s)\n"
63 	    "  -name string              use string as generic file name\n"
64 	    "  -adapt file               read adaptation constraints from file\n"
65 	    "  -order num                restrict maximum interpolation order\n"
66             "  -cache                    cache network computations to disk\n"
67 	    "Linear solver options:\n"
68 #if defined(HAVE_PETSC)
69 	    "  -solver file              specify parameter file (default: .petscrc)\n"
70 	    "  [PETsc options]           PETSc options (must be listed after [file])\n"
71 #endif
72 #if defined(HAVE_SLEPC)
73 	    "  -slepc                    use SLEPc instead of Arpack as eigensolver\n"
74 #endif
75 #if defined(HAVE_SPARSKIT)
76 	    "  -solver file              specify parameter file (default: solver.par)\n"
77 	    "  -'Parameter' num          override value of solver parameter 'Parameter'\n"
78 #endif
79 	    "Output options:\n"
80 	    "  -bin                      create binary output files\n"
81 	    "  -v2                       create mesh-based Gmsh output files when possible\n"
82 	    "Other options:\n"
83 	    "  -check                    interactive check of problem structure\n"
84 	    "  -v num                    set verbosity level (default: 5)\n"
85      	    "  -cpu                      report CPU times for all operations\n"
86 	    "  -p num                    set progress indicator update (default: 10)\n"
87 	    "  -onelab name [address]    communicate with ONELAB (file or server address)\n"
88             "  -setnumber name value     set constant number name=value (or -sn)\n"
89             "  -setstring name value     set constant string name=value (or -ss)\n"
90 	    "  -version                  show version number\n"
91 	    "  -info                     show detailed version information\n"
92 	    "  -help                     show this message\n", arg0);
93     break;
94   case 1:
95     fprintf(stderr, "%s\n", GETDP_VERSION);
96     break;
97   case 2:
98     fprintf(stderr, "Version          : %s\n", GETDP_VERSION);
99     fprintf(stderr, "License          : %s\n", GETDP_SHORT_LICENSE);
100     fprintf(stderr, "Build OS         : %s\n", GETDP_OS);
101     fprintf(stderr, "Build date       : %s\n", GETDP_DATE);
102     fprintf(stderr, "Build host       : %s\n", GETDP_HOST);
103     fprintf(stderr, "Build options    :%s\n", GETDP_CONFIG_OPTIONS);
104 #if defined(HAVE_PETSC)
105     fprintf(stderr, "PETSc version    : %d.%d.%d (%s arithmetic)\n", PETSC_VERSION_MAJOR,
106             PETSC_VERSION_MINOR, PETSC_VERSION_SUBMINOR,
107 #if defined(PETSC_USE_COMPLEX)
108             "complex"
109 #else
110             "real"
111 #endif
112             );
113 #endif
114 #if defined(HAVE_GMSH)
115     fprintf(stderr, "Gmsh lib version : %s%s (%s)\n",
116             GMSH_VERSION, GMSH_EXTRA_VERSION, GMSH_DATE);
117     fprintf(stderr, "Gmsh lib options :%s\n", GMSH_CONFIG_OPTIONS);
118 #endif
119     fprintf(stderr, "Packaged by      : %s\n", GETDP_PACKAGER);
120     fprintf(stderr, "Web site         : http://getdp.info\n");
121     fprintf(stderr, "Issue tracker    : https://gitlab.onelab.info/getdp/getdp/issues\n");
122     break;
123   }
124   Message::Exit(0);
125 }
126 
127 /* ------------------------------------------------------------------------ */
128 /*  G e t _ O p t i o n s                                                   */
129 /* ------------------------------------------------------------------------ */
130 
Get_Options(int argc,char * argv[],int * sargc,char ** sargv,char * pro,int * lres,int * lpos,int * check)131 static void Get_Options(int argc, char *argv[], int *sargc, char **sargv, char *pro,
132                         int *lres, int *lpos, int *check)
133 {
134   strcpy(pro, "");
135 
136   int i = *sargc = 1, j = 0;
137 
138   while (i < argc) {
139 
140     if (argv[i][0] == '-') {
141 
142       if      (!strcmp(argv[i]+1, "cal"))    { Flag_CAL     = 1; i++; }
143       else if (!strcmp(argv[i]+1, "check"))  { *check       = 1; i++; }
144       else if (!strcmp(argv[i]+1, "xdata"))  { Flag_XDATA   = 1; i++; }
145       else if (!strcmp(argv[i]+1, "cache"))  { Flag_NETWORK_CACHE = 1; i++; }
146       else if (!strcmp(argv[i]+1, "bin"))    { Flag_BIN     = 1; i++; }
147       else if (!strcmp(argv[i]+1, "v2"))     { Flag_GMSH_VERSION = 2; i++; }
148       else if (!strcmp(argv[i]+1, "ascii"))  { Flag_BIN     = 0; i++; }
149       else if (!strcmp(argv[i]+1, "split"))  { Flag_SPLIT   = 1; i++; }
150 
151       else if (!strcmp(argv[i]+1, "socket")) {
152         i++;
153         if (i < argc && argv[i][0] != '-') {
154           Message::InitializeSocket(argv[i]); i++;
155         }
156         else {
157           Message::Error("Missing socket name");
158         }
159       }
160 
161       else if (!strcmp(argv[i]+1, "onelab")) {
162         i++;
163         if (i + 1 < argc && argv[i][0] != '-' && argv[i + 1][0] != '-') {
164           Message::InitializeOnelab(argv[i], argv[i + 1]);
165           i += 2;
166         }
167         else if (i < argc && argv[i][0] != '-') {
168           Message::InitializeOnelab(argv[i], "");
169           i += 1;
170         }
171         else {
172           Message::Error("Missing client name and/or address of ONELAB server");
173         }
174       }
175 
176       else if (!strcmp(argv[i]+1, "setnumber") ||
177                !strcmp(argv[i]+1, "sn")) {
178         i++;
179 	if (i + 1 < argc && argv[i][0] != '-') {
180           CommandLineNumbers[argv[i]] = std::vector<double>(1, atof(argv[i + 1]));
181           i += 2;
182 	}
183         else{
184           Message::Error("Missing name and/or value for number definition");
185         }
186       }
187 
188       else if (!strcmp(argv[i]+1, "setstring") ||
189                !strcmp(argv[i]+1, "ss")) {
190         i++;
191 	if (i + 1 < argc && argv[i][0] != '-' && argv[i + 1][0] != '-') {
192           CommandLineStrings[argv[i]] = std::vector<std::string>(1, argv[i + 1]);
193           i += 2;
194 	}
195         else{
196           Message::Error("Missing name and/or value for string definition");
197         }
198       }
199 
200       else if (!strcmp(argv[i]+1, "setlist") ||
201                !strcmp(argv[i]+1, "setlistofnumbers")) {
202         i++;
203 	if (i + 1 < argc && argv[i][0] != '-') {
204           std::string n(argv[i]);
205           std::vector<double> v;
206           int s = atoi(argv[i + 1]), j = 0;
207           i += 2;
208           while(j < s && i < argc){
209             v.push_back(atof(argv[i]));
210             i++; j++;
211           }
212           if(j < s)
213             Message::Error("Missing values in list (got %d instead of %d)", j, s);
214           CommandLineNumbers[n] = v;
215 	}
216         else{
217           Message::Error("Missing name and/or value for definition of list of numbers");
218         }
219       }
220 
221       else if (!strcmp(argv[i]+1, "restart")){
222 	Flag_CAL = Flag_RESTART = 1; i++;
223       }
224 
225       else if (!strcmp(argv[i]+1, "verbose") ||
226 	       !strcmp(argv[i]+1, "v")) {
227 	i++;
228 	if (i < argc && argv[i][0] != '-') {
229 	  Message::SetVerbosity(atoi(argv[i])); i++;
230 	}
231 	else {
232 	  Message::Error("Missing number");
233 	}
234       }
235 
236       else if (!strcmp(argv[i]+1, "cpu")) {
237         Message::SetInfoCpu(true); i++;
238       }
239 
240       else if(!strcmp(argv[i] + 1, "nt")) {
241         i++;
242         if(argv[i])
243           Message::SetNumThreads(atoi(argv[i++]));
244         else
245           Message::Error("Missing number");
246       }
247 
248       else if (!strcmp(argv[i]+1, "help")  || !strcmp(argv[i]+1, "h") ||
249 	       !strcmp(argv[i]+1, "-help") || !strcmp(argv[i]+1, "-h")) {
250 	Info(0, argv[0]);
251       }
252 
253       else if (!strcmp(argv[i]+1, "version") ||
254 	       !strcmp(argv[i]+1, "-version")) {
255 	Info(1, argv[0]);
256       }
257 
258       else if (!strcmp(argv[i]+1, "info") ||
259                !strcmp(argv[i]+1, "-info")) {
260         Info(2, argv[0]);
261       }
262 
263       else if (!strcmp(argv[i]+1, "progress") ||
264 	       !strcmp(argv[i]+1, "p")) {
265 	i++;
266 	if (i < argc && argv[i][0] != '-') {
267 	  Message::SetProgressMeterStep(atoi(argv[i])); i++;
268 	}
269 	else {
270 	  Message::Error("Missing number");
271 	}
272       }
273 
274       else if (!strcmp(argv[i]+1, "pre")) {
275 	i++;
276 	if (i < argc && argv[i][0] == '#') {
277 	  Flag_PRE = 1; *lres = -atoi(argv[i]+1); i++;
278 	}
279 	else if (i < argc && argv[i][0] != '-') {
280 	  Flag_PRE = 1; Name_Resolution = strSave(argv[i]); i++;
281 	}
282 	else {
283 	  Flag_PRE = *lres = 1;
284 	}
285       }
286 
287       else if (!strcmp(argv[i]+1, "order") ||
288 	       !strcmp(argv[i]+1, "ord")) {
289 	i++;
290 	if (i < argc && argv[i][0] != '-') {
291 	  Flag_ORDER = atof(argv[i]); i++;
292 	}
293 	else {
294 	  Message::Error("Missing interpolation order");
295 	}
296       }
297 
298       else if (!strcmp(argv[i]+1, "solver")) {
299         // fix when calling getdp from gmsh (since the GUI forces us
300         // to put the -solver option before the .pro file!)
301 	sargv[(*sargc)++] = argv[i++];
302 	if (i < argc && argv[i][0] != '-') {
303           sargv[(*sargc)++] = argv[i++];
304 	}
305 	else {
306 	  Message::Error("Missing solver option file name");
307 	}
308       }
309 
310       else if (!strcmp(argv[i]+1, "slepc")) {
311         Flag_SLEPC = 1; i++;
312       }
313 
314       else if (!strcmp(argv[i]+1, "solve") ||
315 	       !strcmp(argv[i]+1, "sol")) {
316 	i++;
317 	if (i < argc && argv[i][0] == '#') {
318 	  Flag_PRE = Flag_CAL = 1; *lres = -atoi(argv[i]+1); i++;
319 	}
320 	else if (i < argc && argv[i][0] != '-') {
321 	  Flag_PRE = Flag_CAL = 1; Name_Resolution = strSave(argv[i]); i++;
322 	}
323 	else {
324 	  Flag_PRE = Flag_CAL = *lres = 1;
325 	}
326       }
327 
328       else if (!strcmp(argv[i]+1, "post") ||
329 	       !strcmp(argv[i]+1, "pos")) {
330 	i++; j = 0;
331 	if (i < argc && argv[i][0] == '#') {
332 	  Flag_POS = 1; *lpos = -atoi(argv[i]+1); i++;
333 	} /* Only one numbered (#) PostOperation allowed */
334 	else {
335 	  while (i < argc && argv[i][0] != '-') {
336 	    Name_PostOperation[j] = strSave(argv[i]); i++; j++;
337 	    if(j == NBR_MAX_POS){
338 	      Message::Error("Too many PostOperations");
339               break;
340             }
341 	  }
342 	  if(!j){
343 	    Flag_POS = *lpos = 1;
344 	  }
345 	  else{
346 	    Flag_POS = 1;
347 	    Name_PostOperation[j] = NULL;
348 	  }
349 	}
350       }
351 
352       else if (!strcmp(argv[i]+1, "mesh") ||
353 	       !strcmp(argv[i]+1, "msh") ||
354 	       !strcmp(argv[i]+1, "m")) {
355 	i++;
356 	if (i < argc && argv[i][0] != '-') {
357 	  Name_MshFile = strSave(argv[i]); i++;
358 	}
359 	else {
360 	  Message::Error("Missing file name");
361 	}
362       }
363 
364       else if (!strcmp(argv[i]+1, "msh_scaling")) {
365 	i++;
366 	if (i < argc && argv[i][0] != '-') {
367 	  Flag_MSH_SCALING = atof(argv[i]); i++;
368 	}
369 	else {
370 	  Message::Error("Missing scaling value");
371 	}
372       }
373 
374       else if (!strcmp(argv[i]+1, "adapt") ||
375 	       !strcmp(argv[i]+1, "adap") ||
376 	       !strcmp(argv[i]+1, "ada")) {
377 	i++;
378 	if (i < argc && argv[i][0] != '-') {
379 	  Name_AdaptFile = strSave(argv[i]); i++;
380 	}
381 	else {
382 	  Message::Error("Missing file name");
383 	}
384       }
385 
386       else if (!strcmp(argv[i]+1, "res")) {
387 	i++; j = 0;
388 	while (i < argc && argv[i][0] != '-') {
389 	  Name_ResFile[j] = strSave(argv[i]); i++; j++;
390 	  if(j == NBR_MAX_RES){
391 	    Message::Error("Too many '.res' files");
392             break;
393           }
394 	}
395 	if(!j)
396 	  Message::Error("Missing file name");
397 	else{
398 	  Name_ResFile[j] = NULL;
399 	}
400       }
401 
402       else if (!strcmp(argv[i]+1, "gmshread")) {
403         for(int k = 0; k < NBR_MAX_RES; k++) Tag_GmshReadFile[k] = -1;
404 	i++; j = 0;
405 	while (i < argc && argv[i][0] != '-') {
406 	  Name_GmshReadFile[j] = strSave(argv[i]); i++; j++;
407 	  if(j == NBR_MAX_RES){
408 	    Message::Error("Too many GmshRead files");
409             break;
410           }
411 	}
412 	if(!j)
413 	  Message::Error("Missing file name");
414 	else{
415 	  Name_GmshReadFile[j] = NULL;
416 	}
417       }
418 
419       else if (!strcmp(argv[i]+1, "gmshtag")) {
420         for(int k = 0; k < NBR_MAX_RES; k++) Tag_GmshReadFile[k] = -1;
421 	i++; j = 0;
422 	while (i < argc && argv[i][0] != '-') {
423 	  Tag_GmshReadFile[j] = atoi(argv[i]); i++; j++;
424 	  if(j == NBR_MAX_RES){
425 	    Message::Error("Too many tags");
426             break;
427           }
428 	}
429 	if(!j)
430 	  Message::Error("Missing tag");
431       }
432 
433       else if (!strcmp(argv[i]+1, "name")) {
434 	i++;
435 	if (i < argc && argv[i][0] != '-') {
436 	  Name_Generic = strSave(argv[i]); i++;
437 	}
438 	else {
439 	  Message::Error("Missing string");
440 	}
441       }
442 
443       else if (!strcmp(argv[i]+1, "petscinfo") ||
444 	       !strcmp(argv[i]+1, "-petscinfo")) {
445 	sargv[(*sargc)++] = (char*)"-info";
446 	i++;
447       }
448 
449       else {
450 	sargv[(*sargc)++] = argv[i++];
451       }
452 
453     }
454     else{
455       if (!strlen(pro)) {
456 	sargv[0] = argv[i];
457 	strcpy(pro, argv[i++]);
458       }
459       else{
460 	sargv[(*sargc)++] = argv[i++];
461       }
462     }
463 
464   }
465 
466   if(!strlen(pro)){
467     Message::Error("Missing input file name");
468     Name_Generic = strSave("");
469     *sargc = 0;
470   }
471   else{
472     if(!Name_Generic){
473       Name_Generic = strSave(pro);
474       if(strcmp(pro+(strlen(pro)-4), ".pro") &&
475 	 strcmp(pro+(strlen(pro)-4), ".PRO"))
476 	strcat(pro,".pro");
477       else
478 	Name_Generic[strlen(pro)-4] = '\0';
479     }
480     else{
481       std::string fix = Fix_RelativePath(Name_Generic, pro);
482       Free(Name_Generic);
483       Name_Generic = strSave(fix.c_str());
484       if(strcmp(pro+(strlen(pro)-4), ".pro") &&
485          strcmp(pro+(strlen(pro)-4), ".PRO"))
486         strcat(pro,".pro");
487     }
488 
489     Name_Path = strSave(Name_Generic);
490     i = strlen(Name_Path)-1;
491     while(i >= 0 && Name_Path[i] != '/' && Name_Path[i] != '\\') i--;
492     Name_Path[i+1] = '\0';
493   }
494 }
495 
496 #if defined(HAVE_GMSH)
497 class GmshMsg : public GmshMessage{
498 public:
operator ()(std::string level,std::string msg)499   void operator()(std::string level, std::string msg)
500   {
501     if(level == "Fatal")
502       Message::Fatal("%s", msg.c_str());
503     else if(level == "Error")
504       Message::Error("%s", msg.c_str());
505     else if(level == "Warning")
506       Message::Warning("%s", msg.c_str());
507     else if(level == "Progress"){
508     }
509     else
510       Message::Info("%s", msg.c_str());
511   }
512 };
513 #endif
514 
Free_GlobalVariables()515 static void Free_GlobalVariables()
516 {
517   Flag_PRE = 0; Flag_CAL = 0; Flag_POS = 0; Flag_RESTART = 0;
518   Flag_XDATA = 0; Flag_BIN = 0; Flag_SPLIT = 0; Flag_GMSH_VERSION = 1;
519   Flag_NETWORK_CACHE = 0;
520   Flag_ORDER = -1.;
521   Free(Name_Generic); Name_Generic = 0;
522   Free(Name_Path); Name_Path = 0;
523   Free(Name_Resolution); Name_Resolution = 0;
524   Free(Name_MshFile); Name_MshFile = 0;
525   Free(Name_AdaptFile); Name_AdaptFile = 0;
526   int i = 0;
527   while(Name_PostOperation[i]){
528     Free(Name_PostOperation[i]); Name_PostOperation[i] = 0; i++;
529   }
530   i = 0;
531   while(Name_ResFile[i]){
532     Free(Name_ResFile[i]); Name_ResFile[i] = 0; i++;
533   }
534   i = 0;
535   while(Name_GmshReadFile[i]){
536     Free(Name_GmshReadFile[i]); Name_GmshReadFile[i] = 0; i++;
537   }
538   Free_ProblemStructure();
539   Free_ParserVariables();
540 }
541 
getdpPrintNumbers()542 void getdpPrintNumbers()
543 {
544   for(std::map<std::string, std::vector<double> >::iterator
545         it = GetDPNumbers.begin(); it != GetDPNumbers.end(); it++){
546     printf("%s() = {", it->first.c_str());
547     for(unsigned int i = 0; i < it->second.size(); i++){
548       if(i) printf(", ");
549       printf("%g", it->second[i]);
550     }
551     printf("};\n");
552   }
553 }
554 
getdpPrintStrings()555 void getdpPrintStrings()
556 {
557   for(std::map<std::string, std::vector<std::string> >::iterator
558         it = GetDPStrings.begin(); it != GetDPStrings.end(); it++){
559     printf("%s() = {", it->first.c_str());
560     for(unsigned int i = 0; i < it->second.size(); i++){
561       if(i) printf(", ");
562       printf("%s", it->second[i].c_str());
563     }
564     printf("};\n");
565   }
566 }
567 
getdpClearNumbers()568 void getdpClearNumbers()
569 {
570   GetDPNumbers.clear();
571 }
572 
getdpSetNumber(const std::string & name,double value)573 void getdpSetNumber(const std::string &name, double value)
574 {
575   GetDPNumbers[name] = std::vector<double>(1, value);
576   CommandLineNumbers[name] = std::vector<double>(1, value);
577 }
578 
getdpSetNumber(const std::string & name,const std::vector<double> & value)579 void getdpSetNumber(const std::string &name, const std::vector<double> &value)
580 {
581   GetDPNumbers[name] = value;
582   CommandLineNumbers[name] = value;
583 }
584 
getdpGetNumber(const std::string & name)585 std::vector<double> &getdpGetNumber(const std::string &name)
586 {
587   return GetDPNumbers[name];
588 }
589 
getdpClearStrings()590 void getdpClearStrings()
591 {
592   GetDPStrings.clear();
593 }
594 
getdpSetString(const std::string & name,const std::string & value)595 void getdpSetString(const std::string &name, const std::string &value)
596 {
597   GetDPStrings[name] = std::vector<std::string>(1, value);
598   CommandLineStrings[name] = std::vector<std::string>(1, value);
599 }
600 
getdpSetString(const std::string & name,const std::vector<std::string> & value)601 void getdpSetString(const std::string &name, const std::vector<std::string> &value)
602 {
603   GetDPStrings[name] = value;
604   CommandLineStrings[name] = value;
605 }
606 
getdpGetString(const std::string & name)607 std::vector<std::string> &getdpGetString(const std::string &name)
608 {
609   return GetDPStrings[name];
610 }
611 
MainKernel(int argc,char * argv[])612 int MainKernel(int argc, char *argv[])
613 {
614   if(argc < 2) Info(0, argv[0]);
615 
616   std::string cmdline("");
617   for(int i = 0; i < argc; i++){
618     if(i) cmdline += " ";
619     cmdline += argv[i];
620   }
621 
622   Message::Initialize(argc, argv);
623 
624   char pro[256];
625   char **sargv = (char**)Malloc(256 * sizeof(char*));
626   int sargc, lres = 0, lpos = 0, check = 0;
627   Get_Options(argc, argv, &sargc, sargv, pro, &lres, &lpos, &check);
628 
629   if(Message::GetErrorCount()){
630     Message::Finalize();
631     return Message::GetErrorCount();
632   }
633   Message::Info("Running '%s' [GetDP %s, %d node%s, max. %d thread%s]",
634                 cmdline.c_str(), GETDP_VERSION,
635                 Message::GetCommSize(), Message::GetCommSize() > 1 ? "s" : "",
636                 Message::GetMaxThreads(), Message::GetMaxThreads() > 1 ? "s" : "");
637   Message::Cpu(3, true, true, true, true, true, "Started");
638 
639   if(sargc > 1){
640     std::string solveropt("");
641     for(int i = 1; i < sargc; i++){
642       if(i > 1) solveropt += " ";
643       solveropt += sargv[i];
644     }
645     Message::Debug("Passing unused options to solver: '%s'", solveropt.c_str());
646   }
647 
648   if(!Name_ResFile[0]){
649     Name_ResFile[0] = (char*)Malloc((strlen(Name_Generic)+5)*sizeof(char));
650     strcpy(Name_ResFile[0], Name_Generic);
651     strcat(Name_ResFile[0], ".res");
652     Name_ResFile[1] = 0;
653   }
654 
655   if(!Name_MshFile){
656     std::string name = Message::GetOnelabString("Gmsh/MshFileName");
657     if(name.size()){
658       Name_MshFile = strSave(name.c_str());
659       Message::Info("Got mesh name from Onelab: '%s'", Name_MshFile);
660     }
661   }
662   if(!Name_MshFile){
663     Name_MshFile = (char*)Malloc((strlen(Name_Generic)+5)*sizeof(char));
664     strcpy(Name_MshFile, Name_Generic);
665     strcat(Name_MshFile, ".msh");
666   }
667 
668 #if defined(HAVE_GMSH)
669   Message::Info("Initializing Gmsh");
670   gmsh::initialize();
671   gmsh::option::setNumber("General.Terminal", 0);
672   GmshMsg *msg = 0;
673   if(!GmshGetMessageHandler() && !Flag_CALLED_WITH_ONELAB_SERVER){
674     // do not set msg handler if one is provided (e.g. on Android/iOS)
675     msg = new GmshMsg;
676     GmshSetMessageHandler(msg);
677   }
678   int j = 0;
679   while(Name_GmshReadFile[j]){
680     if(Tag_GmshReadFile[j] >= 0){
681       PView::setGlobalTag(Tag_GmshReadFile[j]);
682       Message::Info("GmshRead[%s] -> View[%d]", Name_GmshReadFile[j], Tag_GmshReadFile[j]);
683     }
684     else{
685       Message::Info("GmshRead[%s]", Name_GmshReadFile[j]);
686     }
687     GmshMergePostProcessingFile(Name_GmshReadFile[j]);
688     j++;
689   }
690 #endif
691 
692   IncreaseStackSize();
693   LinAlg_InitializeSolver(&sargc, &sargv);
694 
695   Init_ProblemStructure();
696   Read_ProblemPreamble();
697   Read_ProblemStructure(pro);
698   Finalize_ProblemStructure();
699 
700   int choose = 1;
701   if (!Flag_PRE && !Flag_CAL && !Flag_POS && !check){
702     lres = lpos = 1;
703     choose = 0;
704   }
705 
706   if(lres)
707     Print_ListResolution(choose, lres, &Name_Resolution);
708 
709   if(lpos)
710     Print_ListPostOperation(choose, lpos, Name_PostOperation);
711 
712   if(check){
713     Print_ProblemStructure();
714   }
715   else{
716     check = Message::GetOnelabNumber
717       (Message::GetOnelabClientName() + "/}ModelCheck");
718     if(check) Print_Object(check - 1);
719   }
720 
721   if(Flag_PRE || Flag_CAL || Flag_POS)
722     SolvingAnalyse();
723 
724   // PETSc cannot be finalized if it will be re-initialized again in the same
725   // process - so just don't finalize it if we use getdp as a library with a
726   // provided onelab server (e.g. for the mobile apps)
727   if(!Flag_CALLED_WITH_ONELAB_SERVER)
728     LinAlg_FinalizeSolver();
729 
730   Message::PrintErrorCounter("Run");
731   Message::Cpu(3, true, true, true, true, true, "Stopped");
732 
733   if(Message::GetVerbosity() == 99){ // debug
734     getdpPrintNumbers();
735     getdpPrintStrings();
736   }
737 
738 #if defined(HAVE_GMSH)
739   if(!Flag_CALLED_WITH_ONELAB_SERVER) GmshFinalize();
740   if(msg) delete msg;
741 #endif
742 
743   Free_GlobalVariables();
744   Free(sargv);
745   Message::Finalize();
746   return Message::GetErrorCount();
747 }
748 
getdp(const std::vector<std::string> & args,void * ptr)749 int getdp(const std::vector<std::string> &args, void *ptr)
750 {
751   onelab::server *onelabServer = (onelab::server*) ptr;
752   if(onelabServer != NULL){
753     onelab::server::setInstance(onelabServer);
754     Flag_CALLED_WITH_ONELAB_SERVER = 1;
755     Message::SetExitOnError(2); // throw exception on error
756   }
757   int argc = args.size();
758   std::vector<char*> argv(argc + 1, (char*)0);
759   for(int i = 0; i < argc; i++) argv[i] = (char*)args[i].c_str();
760   return MainKernel(argc, &argv[0]);
761 }
762