]> git.treefish.org Git - phys/latlib.git/blob - o815/o815.cpp
Added resetconfig routine.
[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     Sim->_resetConfig();
149     
150     progress measProg(comargs.nmeas);
151
152     *out->log << "OBS: Starting measurement of observables:";
153     for (vector<obs*>::iterator obsit = observables.begin(); obsit != observables.end(); ++obsit)
154       *out->log << " " << (*obsit)->obsid;
155     *out->log << endl << flush;
156
157     for( int imeas=0; imeas<comargs.nmeas; imeas++ ) {
158       bool nextAlready = false;
159
160       for (vector<obs*>::iterator obsit = observables.begin(); obsit != observables.end(); ++obsit) {
161         bool readnewObs;
162         int nequileftNewObs;
163         
164         hypercache::readO( (*obsit)->ocid, &readnewObs, &nequileftNewObs );
165
166         if ( readnewObs && nequileftNewObs < 0 ) {
167           (*obsit)->meas(true, imeas);
168         }
169         else {
170           if (!nextAlready) {
171             Sim->nextConfig();
172             nextAlready = true;
173           }
174           (*obsit)->meas(false, imeas);
175           hypercache::writeO( (*obsit)->ocid );
176         }         
177       }
178
179       if ( observables.size() == 0 )
180         Sim->nextConfig();
181
182       while( measProg.madeStep(imeas) ) 
183         *out->log << "O815: " << measProg.done()*100 << "% of measurements done." << endl << flush;
184     }
185     for (vector<obs*>::iterator obsit = observables.begin(); obsit != observables.end(); ++obsit)
186       (*obsit)->finish();
187   }
188 }
189
190 void o815::addComOption(const char* name, int has_arg, int *flag, int val, const char* optdesc, const char* argdesc) {
191   comoption newop = { name, has_arg, flag, val, optdesc, argdesc };
192   comOptions.push_back(newop);
193 }
194
195 void o815::parseArgs(int argc, char **argv, comoption specOps[]) {
196   int opt;
197   int indexptr=0;
198   stringstream optargstr;
199   option allOptions[comOptions.size()+1];
200
201   for (int iop=0; iop < comOptions.size(); iop++) {
202     allOptions[iop].name = comOptions[iop].name.c_str();
203     allOptions[iop].has_arg = comOptions[iop].has_arg;
204     //allOptions[iop].flag = NULL;
205     allOptions[iop].flag = comOptions[iop].flag;
206     allOptions[iop].val = comOptions[iop].val;
207
208     optargstr << char(allOptions[iop].val);
209     if (allOptions[iop].has_arg == required_argument)
210       optargstr << ":";
211     else if (allOptions[iop].has_arg == optional_argument)
212       optargstr << "::";
213   }
214
215   allOptions[comOptions.size()].name = 0;
216   allOptions[comOptions.size()].has_arg = 0;
217   allOptions[comOptions.size()].flag = 0;
218   allOptions[comOptions.size()].val = 0;
219
220   while((opt = getopt_long( argc, argv, optargstr.str().c_str(), allOptions, &indexptr )) != -1)
221     switch(opt) {
222     case 'L':
223       listArg(comargs.lsize, 2, optarg);
224       break;
225     case 'N':
226       comargs.nmeas = atoi(optarg);
227       break;
228     case 'S':
229       comargs.nskip = atoi(optarg);
230       break;
231     case 'E':
232       comargs.nequi = atoi(optarg);
233       break;
234     case 'O':
235       readCacheArgs(optarg, comargs.obscache.first, comargs.obscache.second);
236       break;
237     case 'C':
238       readCacheArgs(optarg, comargs.confcache.first, comargs.confcache.second);
239       break;
240     case 'W':
241       comargs.outdir = optarg;
242       break;
243     case 'X':
244       comargs.startconfig = optarg;
245       break;
246     default:
247       if ( opt != 0) {
248         comoption* thisop = getOptionByVal(opt);
249         if (thisop->flag != 0)
250           *thisop->flag = thisop->val;
251         else
252           parsedSpecOps.push_back( pair<int,char*>(thisop->val, optarg) );
253       }
254       break;
255     }
256
257   for (int ilon=0; optind+ilon < argc; ilon++)
258     lonelyArgs.push_back(argv[optind+ilon]);
259 }
260
261 o815::comoption* o815::getOptionByVal(int val) {
262   for (vector<comoption>::iterator opit = comOptions.begin(); opit != comOptions.end(); ++opit)
263     if ( opit->val == val )
264       return &(*opit);
265   exit(1);
266 }
267
268 void o815::listArg(int *target, int tlen, char *listarg) {
269   int nargs=0;
270   
271   for( int pos=0; pos<strlen(listarg); pos++ ) 
272     if( listarg[pos] == ':' ) nargs++;
273   
274   if(nargs==0) 
275     for(int i=0; i<tlen; i++) target[i] = atoi(listarg);
276   else
277     {
278       target[0] = atoi(strtok(listarg, ":"));
279       for(int i=0; i<nargs; i++)
280         target[i+1] = atoi(strtok(NULL, ":"));
281     }
282 }
283
284 string o815::headMaster(bool hashedrange)
285 {
286   stringstream hm;
287   
288   hm << "_L" << comargs.lsize[0] << "x" << comargs.lsize[1] << "_E" << comargs.nequi << "_S" << comargs.nskip << "_N" << comargs.nmeas;
289
290   if( ! hashedrange )
291     hm << paraQ->rangeString();
292   else
293     hm << "_" << hash( paraQ->rangeString() );
294   
295   return hm.str();
296 }
297
298 o815::~o815() {
299   if(comargs.outdir=="") {
300 #ifndef MPI_DISABLED
301     MPI_Barrier(MPI_COMM_WORLD);
302 #endif
303     if(rank==0)
304       cout << "#end" << endl << flush;
305   }
306   hypercache::finalize();
307   delete out;
308 #ifndef MPI_DISABLED
309   MPI_Finalize();
310 #endif
311 }
312
313 int o815::nextParas()
314 {
315   if( paraQ->nextParas() ) {
316     for (vector<string>::iterator parait = paraQ->allParaIds.begin(); parait != paraQ->allParaIds.end(); ++parait)
317       hypercache::setPara(*parait, (*paraQ)[*parait]);
318     return 1;
319   }
320   else
321     return 0;
322 }
323
324 void o815::addPara(const string& paraid, const double& paraDefault) {
325   hypercache::addPara(paraid);
326   paraQ->setDefault(paraid, paraDefault);
327 }
328
329 void o815::readCacheArgs(const string& arg, string& cachedir, int& cachemode)
330 {
331   if ( arg.rfind(":") == string::npos ) {
332     cerr << "O815: Invalid cache argument!" << endl;
333     exit(1);
334   }
335
336   string arg_mode = arg.substr( arg.rfind(":")+1 );
337   if ( arg_mode == "oo" )
338     cachemode = CACHE_MODE_OO;
339   else if ( arg_mode == "ro" )
340     cachemode = CACHE_MODE_RO;
341   else if ( arg_mode == "wo" )
342     cachemode = CACHE_MODE_WO;
343   else if ( arg_mode == "rw" )
344     cachemode = CACHE_MODE_RW;
345   else {
346     cerr << "O815: Unknown cache mode " << arg_mode << "!" << endl;
347     exit(1);
348   }
349
350   cachedir = arg.substr( 0, arg.rfind(":") );
351 }
352
353 unsigned long o815::hash(const string& str)
354 {
355   unsigned long hash = 5381;
356
357   for(string::const_iterator it=str.begin();it!=str.end();it++) 
358     hash = ((hash << 5) + hash) + *it; /* hash * 33 + character */
359
360   return hash;
361 }