51 vector<EGS_Library *> rc_libs;
52 static int n_run_controls = 0;
55 geomErrorMax(0), app(a), input(0), ncase(0), ndone(0), maxt(-1), accu(-1),
56 nbatch(10), restart(0), nchunk(1), cpu_time(0), previous_cpu_time(0),
59 if (!app)
egsFatal(
"EGS_RunControl::EGS_RunControl: it is not allowed\n"
60 " to construct a run control object on a NULL application\n");
63 egsWarning(
"EGS_RunControl::EGS_RunControl: the application has no"
69 egsWarning(
"EGS_RunControl::EGS_RunControl: no 'run control' "
74 int err = input->
getInput(
"number of histories", ncase_double);
76 err = input->
getInput(
"ncase", ncase_double);
78 egsWarning(
"EGS_RunControl: missing/wrong 'ncase' or "
79 "'number of histories' input\n");
81 ncase = EGS_I64(ncase_double);
91 err = input->
getInput(
"nbatch",nbatch);
95 err = input->
getInput(
"max cpu hours allowed",maxt);
99 err = input->
getInput(
"statistical accuracy sought",accu);
103 err = input->
getInput(
"geometry error limit", geomErrorMax);
108 vector<string> ctype;
109 ctype.push_back(
"first");
110 ctype.push_back(
"restart");
111 ctype.push_back(
"analyze");
112 ctype.push_back(
"combine");
113 restart = input->
getInput(
"calculation",ctype,0);
121 if (!n_run_controls) {
122 while (rc_libs.size() > 0) {
123 delete rc_libs[rc_libs.size()-1];
129 void EGS_RunControl::describeRCO() {
131 "Run Control Object (RCO):\n"
132 "=========================\n");
146 bool EGS_RunControl::storeState(ostream &data) {
150 data <<
" " << (cpu_time+previous_cpu_time) << endl;
154 bool EGS_RunControl::setState(istream &data) {
161 data >> previous_cpu_time;
165 bool EGS_RunControl::addState(istream &data) {
166 EGS_Float previous_cpu_time_save = previous_cpu_time;
167 if (!setState(data)) {
170 previous_cpu_time += previous_cpu_time_save;
174 void EGS_RunControl::resetCounter() {
175 previous_cpu_time = 0;
183 if (restart == 1 || restart == 2) {
193 else if (restart == 3) {
202 time_t tinfo = time(0);
204 asctime(localtime(&tinfo)));
206 egsInformation(
" Fresh simulation of %lld histories\n\n\n",ncase);
210 " new histories\n\n\n",ndone,ncase-ndone);
218 " Batch CPU time Result Uncertainty(%c)\n"
219 "==========================================================\n",
'%');
220 if (maxt > 0 && ndone > 0) {
221 EGS_Float time_per_shower = (cpu_time + previous_cpu_time)/ndone;
222 EGS_Float extra_time = time_per_shower*ncase_per_batch;
223 if (cpu_time + extra_time > maxt*3600) {
224 egsWarning(
"\n\n*** Not enough time to finish another batch\n"
225 " => terminating simulation.\n\n");
230 ndone += ncase_per_batch;
235 cpu_time = timer.
time();
238 egsWarning(
"\n\noutputData() returned error code %d ?\n",out);
240 double sum, sum2, norm, count;
243 if (sum > 0 && sum2 > 0 && norm > 0 && count > 1) {
245 df = count*sum2/(sum*sum)-1;
247 df = 100*sqrt(df/(count-1));
258 if (df < 100 && accu > 0 && df < accu) {
260 egsWarning(
"\n\n*** Reached the requested uncertainty of %g%c\n"
261 " => terminating simulation.\n\n",accu,c);
269 ipar(app->getIparallel()), ifirst(app->getFirstParallel()),
270 milliseconds(1000), check_intervals(5), check_egsdat(true),
279 int err = input->
getInput(
"interval wait time", dummy);
281 milliseconds = dummy;
285 err = input->
getInput(
"number of intervals", dummy);
287 check_intervals = dummy;
292 err = input->
getInput(
"watcher jobs", w_jobs);
294 for (
int i = 0; i < w_jobs.size(); i++) {
295 if (ipar == w_jobs[i]) {
303 if (ipar == ifirst + npar - 1) {
312 vector<string> check_options;
313 check_options.push_back(
"yes");
314 check_options.push_back(
"no");
315 int ichk = input->
getInput(
"check jobs completed",check_options,0);
317 check_egsdat =
false;
323 if (ipar == ifirst + npar - 1) {
329 int EGS_UniformRunControl::startSimulation() {
339 if (
remove(datFile.c_str()) == 0) {
340 egsWarning(
"EGS_UniformRunControl: %s deleted\n",
348 void EGS_UniformRunControl::describeRCO() {
350 EGS_RunControl::describeRCO();
355 " Watcher job: remains running after completion checking\n"
356 " for other jobs finishing every %d s for %d s!\n",
357 milliseconds/1000, check_intervals*milliseconds/1000);
361 " Option to check for finishing jobs is OFF!\n\n");
372 #include <sys/types.h>
373 #include <sys/stat.h>
374 #include <sys/locking.h>
377 #define OPEN_FILE _open
378 #define CLOSE_FILE _close
379 #define CREATE_FLAGS _O_CREAT | _O_EXCL | _O_RDWR, _S_IREAD | _S_IWRITE
380 #define OPEN_FLAGS _O_RDWR,_S_IREAD | _S_IWRITE
381 #define WAIT_FOR_FILE _sleep(1000)
382 #define WRITE_FILE _write
383 #define READ_FILE _read
389 #include <sys/types.h>
390 #include <sys/stat.h>
395 #define OPEN_FILE open
396 #define CLOSE_FILE close
397 #define CREATE_FLAGS O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR
398 #define OPEN_FLAGS O_RDWR
399 #define WAIT_FOR_FILE sleep(1)
400 #define WRITE_FILE write
401 #define READ_FILE read
411 class EGS_LOCAL EGS_FileLocking {
417 struct flock fl_write, fl_unlock;
419 EGS_FileLocking() : fd(-1), is_locked(false), ntry(15) {
421 fl_write.l_type = F_WRLCK;
422 fl_write.l_whence = SEEK_SET;
423 fl_write.l_start = 0;
425 fl_unlock.l_type = F_UNLCK;
426 fl_unlock.l_whence = SEEK_SET;
427 fl_unlock.l_start = 0;
436 bool createControlFile(
const char *fname) {
441 fd = OPEN_FILE(fname,CREATE_FLAGS);
442 egsWarning(
"createControlFile: file=%s fd=%d\n",fname,fd);
444 egsWarning(
"createControlFile(): open failed! (fd=%d)\n",fd);
446 perror(
"System error was");
449 return lockControlFile();
451 bool openControlFile(
const char *fname) {
456 for (
int t=0; t<ntry; t++) {
457 fd = OPEN_FILE(fname,OPEN_FLAGS);
465 bool closeControlFile() {
467 int res = CLOSE_FILE(fd);
473 bool lockControlFile() {
481 long np = _lseek(fd,0L,SEEK_SET);
483 egsWarning(
"lockControlFile: _lseek returned %d?\n",np);
486 int res = _locking(fd,_LK_LOCK,1000000L);
493 for (
int i1=0; i1<5; i1++) {
494 for (
int i2=0; i2<12; i2++) {
495 int res = fcntl(fd,F_SETLK,&fl_write);
502 egsWarning(
"lockControlFile: failed to lock file for "
508 bool unlockControlFile() {
516 int np = _lseek(fd,0L,SEEK_SET);
518 egsWarning(
"unlockControlFile: _lseek returned %d?\n",np);
521 int res = _locking(fd,_LK_UNLCK,1000000L);
523 int res = fcntl(fd,F_SETLKW,&fl_unlock);
531 bool rewindControlFile() {
536 if (!lockControlFile()) {
541 return !_lseek(fd,0,SEEK_SET);
543 return !lseek(fd,0,SEEK_SET);
551 EGS_RunControl(a), tsum(0), tsum2(0), tcount(0), norm(1), last_sum(0),
552 last_sum2(0), last_count(0), njob(0), npar(app->getNparallel()),
553 ipar(app->getIparallel()), ifirst(app->getFirstParallel()),
554 first_time(true), removed_jcf(false), nbuf(Nbuf), p(new EGS_FileLocking) {
564 int err = input->
getInput(
"nchunk",nchunk);
575 buf =
new char [nbuf];
583 bool EGS_JCFControl::createControlFile() {
586 if (!p->createControlFile(cfile.c_str())) {
587 egsWarning(
"EGS_JCFControl: failed to create or lock the "
588 " job control file %s\n\n",cfile.c_str());
594 writeControlString();
595 int nwant = strlen(buf)+1;
596 int nwrite = WRITE_FILE(p->fd,buf,nwant);
597 if (nwrite != nwant) {
600 return p->unlockControlFile();
603 bool EGS_JCFControl::openControlFile() {
606 if (!p->openControlFile(cfile.c_str())) {
607 egsWarning(
"EGS_JCFControl: failed to open the "
608 " job control file %s\n\n",cfile.c_str());
616 #define MY_OSTREAM std::ostrstream
617 #define MY_ISTREAM std::istrstream
620 #define MY_OSTREAM std::ostringstream
621 #define MY_ISTREAM std::istringstream
624 bool EGS_JCFControl::writeControlString() {
627 start_time = time(0);
646 double f = tsum*norm, df;
647 if (tsum > 0 && tsum2 > 0 && norm > 0 && tcount > 1) {
648 f = tsum*norm/tcount;
649 df = tcount*tsum2/(tsum*tsum)-1;
651 df = 100*sqrt(df/(tcount-1));
660 sprintf(buf,
"%lld %lld %d %lg %lg %lg %lg %lg %ld ",ntot,nleft,njob,tsum,
661 tsum2,tcount,f,df,start_time);
665 bool EGS_JCFControl::getCombinedResult(
double &f,
double &df)
const {
666 if (tsum > 0 && tsum2 > 0 && norm > 0 && tcount > 1) {
667 f = tsum*norm/tcount;
668 df = tcount*tsum2/(tsum*tsum)-1;
670 df = 100*sqrt(df/(tcount-1));
682 bool EGS_JCFControl::readControlString() {
692 int res = sscanf(buf,
"%lld %lld %d %lg %lg %lg %lg %lg %ld",
693 &ntot,&nleft,&njob,&tsum,&tsum2,&tcount,&f,&df,&start_time);
694 if (res == EOF || res != 9) {
700 int EGS_JCFControl::startSimulation() {
705 bool ok = (ipar == ifirst) ? createControlFile() : openControlFile();
708 "job\n\n\n",npar,nchunk);
714 bool EGS_JCFControl::readControlFile() {
715 if (!p->rewindControlFile()) {
716 egsWarning(
"EGS_JCFControl: failed to rewind the job control file\n");
719 int res = READ_FILE(p->fd,buf,nbuf-1);
721 p->unlockControlFile();
722 egsWarning(
"EGS_JCFControl: failed to read the job control file\n");
726 if (!readControlString()) {
727 p->unlockControlFile();
728 egsWarning(
"EGS_JCFControl: failed to read from the control string"
735 bool EGS_JCFControl::writeControlFile() {
736 if (!writeControlString()) {
737 egsWarning(
"EGS_JCFControl::writeControlFile: failed to write to the "
741 if (!p->rewindControlFile()) {
742 egsWarning(
"EGS_JCFControl: failed to rewind the job control file\n");
745 int nwant = strlen(buf)+1;
746 int nwrite = WRITE_FILE(p->fd,buf,nwant);
747 if (!p->unlockControlFile()) {
748 egsWarning(
"EGS_JCFControl::writeControlFile: failed to unlock the "
752 if (nwrite != nwant) {
753 egsWarning(
"EGS_JCFControl::getNextChunk: could write only %d "
754 "instead of %d chars to the job control file?\n",nwrite,nwant);
760 EGS_I64 EGS_JCFControl::getNextChunk() {
761 if (!readControlFile()) {
768 double sum, sum2, count;
770 tsum += sum - last_sum;
771 tsum2 += sum2 - last_sum2;
772 tcount += count - last_count;
776 EGS_I64 nrun = ncase/(npar*nchunk);
790 if (accu > 0 && getCombinedResult(f,df)) {
791 if (df < 100 && df < accu) {
793 egsWarning(
"\n\n*** After combining the results of all parallel "
794 "jobs the requested\n uncertainty of %g%c was reached: %g%c\n"
795 " => terminating simulation.\n\n",accu,c,df,c);
819 usleep(mscnds * 1000);
824 cpu_time = timer.
time();
827 "Total cpu time for this run:",cpu_time,cpu_time/3600);
830 if (previous_cpu_time > 0)
832 "CPU time including previous runs:",cpu_time+previous_cpu_time,
833 (cpu_time+previous_cpu_time)/3600);
835 (cpu_time+previous_cpu_time));
838 double ch_steps, all_steps;
851 return (n_par && i_par == i_first + n_par - 1) ? 1 : 0;
861 int interval = 0, njobs_done = 0, njobs_done_old= 0;
862 while (interval < check_intervals) {
867 if (njobs_done == npar - 1) {
872 if (njobs_done_old < njobs_done) {
876 njobs_done_old = njobs_done;
886 int EGS_JCFControl::finishSimulation() {
894 if (!readControlFile()) {
899 p->closeControlFile();
900 if (njob > 0 || removed_jcf) {
906 int res = _unlink(cfile.c_str());
908 int res = unlink(cfile.c_str());
910 if (res)
egsWarning(
"EGS_JCFControl::finishSimulation: failed to remove "
911 " the job control file %s\n",cfile.c_str());
916 EGS_JCFControl::~EGS_JCFControl() {
920 bool EGS_JCFControl::closeControlFile() {
921 return p->closeControlFile();
924 bool EGS_JCFControl::lockControlFile() {
925 return p->lockControlFile();
928 bool EGS_JCFControl::unlockControlFile() {
929 return p->unlockControlFile();
932 bool EGS_JCFControl::rewindControlFile() {
933 return p->rewindControlFile();
940 egsWarning(
"EGS_RunControl::getRunControlObject(): "
941 "null application?\n");
974 int err = irc->
getInput(
"library",libname);
978 for (
unsigned int j=0; j<rc_libs.size(); j++) {
979 if (libname == rc_libs[j]->libraryName()) {
988 lib =
new EGS_Library(libname.c_str(),dsodir.c_str());
990 if (!lib->isLoaded()) {
991 egsWarning(
"EGS_RunControl::getRunControlObject: failed to"
992 " load the library %s from %s\n",libname.c_str(),
997 rc_libs.push_back(lib);
999 EGS_RunControlCreationFunction create =
1000 (EGS_RunControlCreationFunction) lib->resolve(
"createRunControl");
1002 egsWarning(
"EGS_RunControl::getRunControlObject: failed to"
1003 " resolve the run control creation function of library %s\n",
1013 vector<string> allowed_types;
1014 allowed_types.push_back(
"simple");
1015 allowed_types.push_back(
"uniform");
1016 allowed_types.push_back(
"balanced");
1017 int rco_t = irc->
getInput(
"rco type",allowed_types,2);
const string & getFinalOutputFile() const
Returns the base name of the final output file(s)
virtual int startSimulation()
Starts the simulation.
A class for dynamically loading shared libraries.
virtual int readData()
Read intermediate results.
bool EGS_EXPORT egsGetI64(istream &data, EGS_I64 &n)
Reads a 64 bit integer from the stream data and assigns it to n. Returns true on success, false on failure.
virtual void getElectronSteps(double &ch_steps, double &all_steps) const
Get the number of electron steps taken.
A simple run control object for advanced EGSnrc C++ applications.
virtual void describeSimulation()
Describe the simulation.
EGS_Float time()
Returns the CPU time in seconds since start() was called.
virtual int combineResults()
Combine results from parallel runs.
virtual ~EGS_RunControl()
Destructor.
bool EGS_EXPORT egsStoreI64(ostream &data, EGS_I64 n)
Writes the 64 bit integer n to the output stream data and returns true on success, false on failure.
virtual int combinePartialResults()
Combine intermediate results from parallel runs.
string egsJoinPath(const string &first, const string &second)
Join two path variables (or a path and a file name) using the platform specific directory separator a...
int getIparallel() const
Returns the job number in a parallel run.
Global egspp functions header file.
virtual void setSimulationChunk(EGS_I64 nstart, EGS_I64 nrun)
Set the simulation chunk.
int getNparallel() const
Returns the number of parallel jobs executing.
RCOType rco_type
RCO type to use.
parallel jobs with same numbe of histories
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
virtual void getCurrentResult(double &sum, double &sum2, double &norm, double &count)
Report the current result.
virtual bool finishBatch()
Finish a batch.
EGS_InfoFunction EGS_EXPORT egsInformation
Always use this function for reporting the progress of a simulation and any other type of information...
EGS_Library class header file.
virtual bool startBatch(int, EGS_I64)
Start a new batch.
virtual int outputData()
Output intermediate results.
parallel jobs with balanced load via JCF
single job or multiple independent jobs
int getFirstParallel() const
Returns the first job number in a parallel run.
virtual EGS_I64 randomNumbersUsed() const
Returns the number of random numbers used.
void start()
Starts the time measurement.
bool load()
Loads the library.
const string & getHenHouse() const
Returns the HEN_HOUSE directory.
void rco_sleep(const int &mscnds)
Suspend execution for a given time (in ms)
EGS_Input * getInput()
Returns a pointer to the EGS_Input object containing the user input to the application found in the i...
const string & getAppDir() const
Returns the absolute path to the user code directory.
A 'job control file' (JCF) RCO.
EGS_Application class header file.
virtual int finishSimulation()
Finish the simulation.
EGS_RunControl(EGS_Application *app)
Creates an RCO for the application app.
Base class for advanced EGSnrc C++ applications.
EGS_RunControl and EGS_JCFControl class header file.
int howManyJobsDone()
Counts how many *.egsdat files in app folder.
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.