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