]> git.treefish.org Git - phys/latlib.git/blob - o815/o815.cpp
73e3497aeb51b1b71962bd6a6eb6dec1d286e538
[phys/latlib.git] / o815 / o815.cpp
1 #include "o815.h"
2
3 #include <sstream>
4 #include <iomanip>
5 #include <cstring>
6
7 #ifndef MPI_DISABLED
8 #include <mpi.h>
9 #endif
10
11 #include "latlib/progress.h"
12
13 using namespace std;
14
15 extern int opterr;
16
17 o815::o815(int argc, char **argv, const string& _programid, comoption specOps[], void (*helpHeader)()) {
18   programid = _programid;
19
20   comargs.nmeas = 100;
21   comargs.nskip = 10;
22   comargs.nequi = 100;
23   comargs.lsize[0] = 4;
24   comargs.lsize[1] = 4;
25   comargs.obscache = make_pair("",0);
26   comargs.confcache = make_pair("",0);
27   comargs.outdir="";
28   comargs.idonly = false;
29   comargs.showjobnum = false;
30   comargs.startconfig = "";
31   
32 #ifndef MPI_DISABLED
33   MPI_Init(&argc, &argv);
34   MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
35   MPI_Comm_rank(MPI_COMM_WORLD, &rank);
36 #else
37   numprocs = 1;
38   rank = 0;
39 #endif
40
41   addComOption("lsize",       required_argument, NULL,                'L', "define lattice size",                     "xsize:tsize");
42   addComOption("nmeas",       required_argument, NULL,                'N', "set number of measurements",              "nmeas");
43   addComOption("skip",        required_argument, NULL,                'S', "set number of skips between configs",     "nskip");
44   addComOption("nequi",       required_argument, NULL,                'E', "set number of equilibrations",            "nequi");
45   addComOption("ocache",      required_argument, NULL,                'O', "set observable cache (mode=oo|ro|wo|rw)", "dir:mode");
46   addComOption("ccache",      required_argument, NULL,                'C', "set config cache (mode=oo|ro|wo|rw)",     "dir:mode");
47   addComOption("write",       required_argument, NULL,                'W', "data writeout directory",                 "dir");
48   addComOption("idonly",      no_argument,       &comargs.idonly,     'I', "show output-id only",                     "");
49   addComOption("jobnum",      no_argument,       &comargs.showjobnum, 'J', "show jobnumber only",                     "");
50   addComOption("startconfig", required_argument, NULL,                'X', "read start config from file",             "startconfigfile");
51   
52   vector<comoption>::iterator lastO815Opt = comOptions.end()-1;
53
54   if (specOps != NULL)
55     for (int ispecop = 0; specOps[ispecop].name != ""; ispecop++)
56       comOptions.push_back(specOps[ispecop]);
57
58   if (argc > 1)
59     parseArgs(argc, argv, specOps);
60   else {
61     int longestCombinedLong=0;
62     
63     if (helpHeader != NULL)
64       helpHeader();
65
66     cout << "General options:" << endl;
67
68     for (vector<comoption>::iterator opit = comOptions.begin(); opit != comOptions.end(); ++opit) {
69       stringstream combinedLong;
70
71       combinedLong << opit->name;
72       if (opit->has_arg == required_argument)
73         combinedLong << "=" << opit->argdesc;
74       else if (opit->has_arg == optional_argument)
75         combinedLong << "[=" << opit->argdesc << "]";
76
77       if (longestCombinedLong < combinedLong.str().size())
78         longestCombinedLong = combinedLong.str().size();
79     }
80
81     for (vector<comoption>::iterator opit = comOptions.begin(); opit != comOptions.end(); ++opit) {
82       stringstream combinedLong;
83
84       cout << "  -" << char(opit->val) << ", --";
85
86       combinedLong << opit->name;
87       if (opit->has_arg == required_argument)
88         combinedLong << "=" << opit->argdesc;
89       else if (opit->has_arg == optional_argument)
90         combinedLong << "[=" << opit->argdesc << "]";
91
92       cout << setw(longestCombinedLong) << setiosflags(ios::left) << combinedLong.str();
93
94       cout << "\t" << opit->optdesc;
95       
96       cout << endl;
97
98       if ( opit == lastO815Opt && (opit+1) != comOptions.end() ) {
99         cout << endl;
100         cout << "Simulation specific options:" << endl;
101       }
102     }
103     exit(0);
104   }
105
106   paraQ = new paraq(numprocs, rank);
107
108   hypercache::addPara("lx", comargs.lsize[0]);
109   hypercache::addPara("lt", comargs.lsize[1]);
110 }
111
112 void o815::postParaInit() {
113   long timestamp;
114
115   if(comargs.idonly) {
116     cout << programid << headMaster(true) << endl << flush;
117     exit(0);
118   }
119
120   if( comargs.showjobnum ) {
121     for( int i=1; i<=paraQ->getTotalJobs(); i++ ) {
122       if( paraQ->getTotalJobs()%i == 0 ) cout << paraQ->getTotalJobs()/i << "@" << i << " ";
123     }
124     cout << endl;
125     exit(0);
126   }
127   
128   out = new writeout(comargs.outdir, programid+headMaster(true), rank, numprocs);
129 }
130
131 void o815::mainLoop() {
132   *out->log << "OBS: Starting main loop." << endl;
133
134   if ( observables.size() == 0 )
135     *out->log << "O815: Running in 0-observable-mode." << endl;
136
137   for (vector<obs*>::iterator obsit = observables.begin(); obsit != observables.end(); ++obsit)
138     (*obsit)->start();
139
140   while( nextParas() ) {
141     *out->log << endl << "O815: < ";
142     for (vector<string>::iterator parait = paraQ->allParaIds.begin(); parait != paraQ->allParaIds.end(); ++parait)
143       *out->log << *parait << "=" << (*paraQ)[*parait] << " ";
144     *out->log << ">" << endl << flush;
145
146     Sim->_newParas();
147     
148     progress measProg(comargs.nmeas);
149
150     *out->log << "OBS: Starting measurement of observables:";
151     for (vector<obs*>::iterator obsit = observables.begin(); obsit != observables.end(); ++obsit)
152       *out->log << " " << (*obsit)->obsid;
153     *out->log << endl << flush;
154
155     for( int imeas=0; imeas<comargs.nmeas; imeas++ ) {
156       bool nextAlready = false;
157
158       for (vector<obs*>::iterator obsit = observables.begin(); obsit != observables.end(); ++obsit) {
159         bool readnewObs;
160         int nequileftNewObs;
161         
162         hypercache::readO( (*obsit)->ocid, &readnewObs, &nequileftNewObs );
163
164         if ( readnewObs && nequileftNewObs < 0 ) {
165           (*obsit)->meas(true, imeas);
166         }
167         else {
168           if (!nextAlready) {
169             Sim->nextConfig();
170             nextAlready = true;
171           }
172           (*obsit)->meas(false, imeas);
173           hypercache::writeO( (*obsit)->ocid );
174         }         
175       }
176
177       if ( observables.size() == 0 )
178         Sim->nextConfig();
179
180       while( measProg.madeStep(imeas) ) 
181         *out->log << "O815: " << measProg.done()*100 << "% of measurements done." << endl << flush;
182     }
183     for (vector<obs*>::iterator obsit = observables.begin(); obsit != observables.end(); ++obsit)
184       (*obsit)->finish();
185   }
186 }
187
188 void o815::addComOption(const char* name, int has_arg, int *flag, int val, const char* optdesc, const char* argdesc) {
189   comoption newop = { name, has_arg, flag, val, optdesc, argdesc };
190   comOptions.push_back(newop);
191 }
192
193 void o815::parseArgs(int argc, char **argv, comoption specOps[]) {
194   int opt;
195   int indexptr=0;
196   stringstream optargstr;
197   option allOptions[comOptions.size()+1];
198
199   for (int iop=0; iop < comOptions.size(); iop++) {
200     allOptions[iop].name = comOptions[iop].name.c_str();
201     allOptions[iop].has_arg = comOptions[iop].has_arg;
202     //allOptions[iop].flag = NULL;
203     allOptions[iop].flag = comOptions[iop].flag;
204     allOptions[iop].val = comOptions[iop].val;
205
206     optargstr << char(allOptions[iop].val);
207     if (allOptions[iop].has_arg == required_argument)
208       optargstr << ":";
209     else if (allOptions[iop].has_arg == optional_argument)
210       optargstr << "::";
211   }
212
213   allOptions[comOptions.size()].name = 0;
214   allOptions[comOptions.size()].has_arg = 0;
215   allOptions[comOptions.size()].flag = 0;
216   allOptions[comOptions.size()].val = 0;
217
218   while((opt = getopt_long( argc, argv, optargstr.str().c_str(), allOptions, &indexptr )) != -1)
219     switch(opt) {
220     case 'L':
221       listArg(comargs.lsize, 2, optarg);
222       break;
223     case 'N':
224       comargs.nmeas = atoi(optarg);
225       break;
226     case 'S':
227       comargs.nskip = atoi(optarg);
228       break;
229     case 'E':
230       comargs.nequi = atoi(optarg);
231       break;
232     case 'O':
233       readCacheArgs(optarg, comargs.obscache.first, comargs.obscache.second);
234       break;
235     case 'C':
236       readCacheArgs(optarg, comargs.confcache.first, comargs.confcache.second);
237       break;
238     case 'W':
239       comargs.outdir = optarg;
240       break;
241     case 'X':
242       comargs.startconfig = optarg;
243       break;
244     default:
245       if ( opt != 0) {
246         comoption* thisop = getOptionByVal(opt);
247         if (thisop->flag != 0)
248           *thisop->flag = thisop->val;
249         else
250           parsedSpecOps.push_back( pair<int,char*>(thisop->val, optarg) );
251       }
252       break;
253     }
254
255   for (int ilon=0; optind+ilon < argc; ilon++)
256     lonelyArgs.push_back(argv[optind+ilon]);
257 }
258
259 o815::comoption* o815::getOptionByVal(int val) {
260   for (vector<comoption>::iterator opit = comOptions.begin(); opit != comOptions.end(); ++opit)
261     if ( opit->val == val )
262       return &(*opit);
263   exit(1);
264 }
265
266 void o815::listArg(int *target, int tlen, char *listarg) {
267   int nargs=0;
268   
269   for( int pos=0; pos<strlen(listarg); pos++ ) 
270     if( listarg[pos] == ':' ) nargs++;
271   
272   if(nargs==0) 
273     for(int i=0; i<tlen; i++) target[i] = atoi(listarg);
274   else
275     {
276       target[0] = atoi(strtok(listarg, ":"));
277       for(int i=0; i<nargs; i++)
278         target[i+1] = atoi(strtok(NULL, ":"));
279     }
280 }
281
282 string o815::headMaster(bool hashedrange)
283 {
284   stringstream hm;
285   
286   hm << "_L" << comargs.lsize[0] << "x" << comargs.lsize[1] << "_E" << comargs.nequi << "_S" << comargs.nskip << "_N" << comargs.nmeas;
287
288   if( ! hashedrange )
289     hm << paraQ->rangeString();
290   else
291     hm << "_" << hash( paraQ->rangeString() );
292   
293   return hm.str();
294 }
295
296 o815::~o815() {
297   if(comargs.outdir=="") {
298 #ifndef MPI_DISABLED
299     MPI_Barrier(MPI_COMM_WORLD);
300 #endif
301     if(rank==0)
302       cout << "#end" << endl << flush;
303   }
304   hypercache::finalize();
305   delete out;
306 #ifndef MPI_DISABLED
307   MPI_Finalize();
308 #endif
309 }
310
311 int o815::nextParas()
312 {
313   if( paraQ->nextParas() ) {
314     for (vector<string>::iterator parait = paraQ->allParaIds.begin(); parait != paraQ->allParaIds.end(); ++parait)
315       hypercache::setPara(*parait, (*paraQ)[*parait]);
316     return 1;
317   }
318   else
319     return 0;
320 }
321
322 void o815::addPara(const string& paraid, const double& paraDefault) {
323   hypercache::addPara(paraid);
324   paraQ->setDefault(paraid, paraDefault);
325 }
326
327 void o815::readCacheArgs(const string& arg, string& cachedir, int& cachemode)
328 {
329   if ( arg.rfind(":") == string::npos ) {
330     cerr << "O815: Invalid cache argument!" << endl;
331     exit(1);
332   }
333
334   string arg_mode = arg.substr( arg.rfind(":")+1 );
335   if ( arg_mode == "oo" )
336     cachemode = CACHE_MODE_OO;
337   else if ( arg_mode == "ro" )
338     cachemode = CACHE_MODE_RO;
339   else if ( arg_mode == "wo" )
340     cachemode = CACHE_MODE_WO;
341   else if ( arg_mode == "rw" )
342     cachemode = CACHE_MODE_RW;
343   else {
344     cerr << "O815: Unknown cache mode " << arg_mode << "!" << endl;
345     exit(1);
346   }
347
348   cachedir = arg.substr( 0, arg.rfind(":") );
349 }
350
351 unsigned long o815::hash(const string& str)
352 {
353   unsigned long hash = 5381;
354
355   for(string::const_iterator it=str.begin();it!=str.end();it++) 
356     hash = ((hash << 5) + hash) + *it; /* hash * 33 + character */
357
358   return hash;
359 }