54 vector<EGS_Library *> rc_libs;
55 static int n_run_controls = 0;
58 geomErrorMax(0), app(a), input(0), ncase(0), ndone(0), maxt(-1), accu(-1),
59 nbatch(10), restart(0), nchunk(1), cpu_time(0), previous_cpu_time(0),
62 if (!app)
egsFatal(
"EGS_RunControl::EGS_RunControl: it is not allowed\n"
63 " to construct a run control object on a NULL application\n");
66 egsWarning(
"EGS_RunControl::EGS_RunControl: the application has no"
72 egsWarning(
"EGS_RunControl::EGS_RunControl: no 'run control' "
77 int err = input->
getInput(
"number of histories", ncase_double);
79 err = input->
getInput(
"ncase", ncase_double);
81 egsWarning(
"EGS_RunControl: missing/wrong 'ncase' or "
82 "'number of histories' input\n");
84 ncase = EGS_I64(ncase_double);
94 err = input->
getInput(
"nbatch",nbatch);
98 err = input->
getInput(
"max cpu hours allowed",maxt);
102 err = input->
getInput(
"statistical accuracy sought",accu);
106 err = input->
getInput(
"geometry error limit", geomErrorMax);
111 vector<string> ctype;
112 ctype.push_back(
"first");
113 ctype.push_back(
"restart");
114 ctype.push_back(
"analyze");
115 ctype.push_back(
"combine");
116 restart = input->
getInput(
"calculation",ctype,0);
124 if (!n_run_controls) {
125 while (rc_libs.size() > 0) {
126 delete rc_libs[rc_libs.size()-1];
132 void EGS_RunControl::describeRCO() {
134 "Run Control Object (RCO):\n"
135 "=========================\n");
149 bool EGS_RunControl::storeState(ostream &data) {
153 data <<
" " << (cpu_time+previous_cpu_time) << endl;
157 bool EGS_RunControl::setState(istream &data) {
164 data >> previous_cpu_time;
168 bool EGS_RunControl::addState(istream &data) {
169 EGS_Float previous_cpu_time_save = previous_cpu_time;
170 if (!setState(data)) {
173 previous_cpu_time += previous_cpu_time_save;
177 void EGS_RunControl::resetCounter() {
178 previous_cpu_time = 0;
186 if (restart == 1 || restart == 2) {
196 else if (restart == 3) {
205 time_t tinfo = time(0);
207 asctime(localtime(&tinfo)));
209 egsInformation(
" Fresh simulation of %lld histories\n\n\n",ncase);
213 " new histories\n\n\n",ndone,ncase-ndone);
221 " Batch CPU time Result Uncertainty(%c)\n"
222 "==========================================================\n",
'%');
223 if (maxt > 0 && ndone > 0) {
224 EGS_Float time_per_shower = (cpu_time + previous_cpu_time)/ndone;
225 EGS_Float extra_time = time_per_shower*ncase_per_batch;
226 if (cpu_time + extra_time > maxt*3600) {
227 egsWarning(
"\n\n*** Not enough time to finish another batch\n"
228 " => terminating simulation.\n\n");
233 ndone += ncase_per_batch;
238 cpu_time = timer.
time();
241 egsWarning(
"\n\noutputData() returned error code %d ?\n",out);
243 double sum, sum2, norm, count;
246 if (sum > 0 && sum2 > 0 && norm > 0 && count > 1) {
248 df = count*sum2/(sum*sum)-1;
250 df = 100*sqrt(df/(count-1));
261 if (df < 100 && accu > 0 && df < accu) {
263 egsWarning(
"\n\n*** Reached the requested uncertainty of %g%c\n"
264 " => terminating simulation.\n\n",accu,c);
272 ipar(app->getIparallel()), ifirst(app->getFirstParallel()),
273 milliseconds(1000), check_intervals(5), check_egsdat(true),
282 int err = input->
getInput(
"interval wait time", dummy);
284 milliseconds = dummy;
288 err = input->
getInput(
"number of intervals", dummy);
290 check_intervals = dummy;
295 err = input->
getInput(
"watcher jobs", w_jobs);
297 for (
int i = 0; i < w_jobs.size(); i++) {
298 if (ipar == w_jobs[i]) {
306 if (ipar == ifirst + npar - 1) {
315 vector<string> check_options;
316 check_options.push_back(
"yes");
317 check_options.push_back(
"no");
318 int ichk = input->
getInput(
"check jobs completed",check_options,0);
320 check_egsdat =
false;
326 if (ipar == ifirst + npar - 1) {
332 int EGS_UniformRunControl::startSimulation() {
342 if (remove(datFile.c_str()) == 0) {
343 egsWarning(
"EGS_UniformRunControl: %s deleted\n",
351 void EGS_UniformRunControl::describeRCO() {
353 EGS_RunControl::describeRCO();
358 " Watcher job: remains running after completion checking\n"
359 " for other jobs finishing every %d s for %d s!\n",
360 milliseconds/1000, check_intervals*milliseconds/1000);
364 " Option to check for finishing jobs is OFF!\n\n");
375 #include <sys/types.h>
376 #include <sys/stat.h>
377 #include <sys/locking.h>
380 #define OPEN_FILE _open
381 #define CLOSE_FILE _close
382 #define CREATE_FLAGS _O_CREAT | _O_EXCL | _O_RDWR, _S_IREAD | _S_IWRITE
383 #define OPEN_FLAGS _O_RDWR,_S_IREAD | _S_IWRITE
384 #define WAIT_FOR_FILE Sleep(1000)
385 #define WRITE_FILE _write
386 #define READ_FILE _read
392 #include <sys/types.h>
393 #include <sys/stat.h>
398 #define OPEN_FILE open
399 #define CLOSE_FILE close
400 #define CREATE_FLAGS O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR
401 #define OPEN_FLAGS O_RDWR
402 #define WAIT_FOR_FILE sleep(1)
403 #define WRITE_FILE write
404 #define READ_FILE read
414 class EGS_LOCAL EGS_FileLocking {
420 struct flock fl_write, fl_unlock;
422 EGS_FileLocking() : fd(-1), is_locked(false), ntry(15) {
424 fl_write.l_type = F_WRLCK;
425 fl_write.l_whence = SEEK_SET;
426 fl_write.l_start = 0;
428 fl_unlock.l_type = F_UNLCK;
429 fl_unlock.l_whence = SEEK_SET;
430 fl_unlock.l_start = 0;
439 bool createControlFile(
const char *fname) {
444 fd = OPEN_FILE(fname,CREATE_FLAGS);
445 egsWarning(
"createControlFile: file=%s fd=%d\n",fname,fd);
447 egsWarning(
"createControlFile(): open failed! (fd=%d)\n",fd);
449 perror(
"System error was");
452 return lockControlFile();
454 bool openControlFile(
const char *fname) {
459 for (
int t=0; t<ntry; t++) {
460 fd = OPEN_FILE(fname,OPEN_FLAGS);
468 bool closeControlFile() {
470 int res = CLOSE_FILE(fd);
476 bool lockControlFile() {
484 long np = _lseek(fd,0L,SEEK_SET);
486 egsWarning(
"lockControlFile: _lseek returned %d?\n",np);
489 int res = _locking(fd,_LK_LOCK,1000000L);
496 for (
int i1=0; i1<5; i1++) {
497 for (
int i2=0; i2<12; i2++) {
498 int res = fcntl(fd,F_SETLK,&fl_write);
505 egsWarning(
"lockControlFile: failed to lock file for "
511 bool unlockControlFile() {
519 int np = _lseek(fd,0L,SEEK_SET);
521 egsWarning(
"unlockControlFile: _lseek returned %d?\n",np);
524 int res = _locking(fd,_LK_UNLCK,1000000L);
526 int res = fcntl(fd,F_SETLKW,&fl_unlock);
534 bool rewindControlFile() {
539 if (!lockControlFile()) {
544 return !_lseek(fd,0,SEEK_SET);
546 return !lseek(fd,0,SEEK_SET);
554 EGS_RunControl(a), tsum(0), tsum2(0), tcount(0), norm(1), last_sum(0),
555 last_sum2(0), last_count(0), njob(0), npar(app->getNparallel()),
556 ipar(app->getIparallel()), ifirst(app->getFirstParallel()),
557 first_time(true), removed_jcf(false), nbuf(Nbuf), p(new EGS_FileLocking) {
567 int err = input->
getInput(
"nchunk",nchunk);
578 buf =
new char [nbuf];
586 bool EGS_JCFControl::createControlFile() {
589 if (!p->createControlFile(cfile.c_str())) {
590 egsWarning(
"EGS_JCFControl: failed to create or lock the "
591 " job control file %s\n\n",cfile.c_str());
597 writeControlString();
598 int nwant = strlen(buf)+1;
599 int nwrite = WRITE_FILE(p->fd,buf,nwant);
600 if (nwrite != nwant) {
603 return p->unlockControlFile();
606 bool EGS_JCFControl::openControlFile() {
609 if (!p->openControlFile(cfile.c_str())) {
610 egsWarning(
"EGS_JCFControl: failed to open the "
611 " job control file %s\n\n",cfile.c_str());
619 #define MY_OSTREAM std::ostrstream
620 #define MY_ISTREAM std::istrstream
623 #define MY_OSTREAM std::ostringstream
624 #define MY_ISTREAM std::istringstream
627 bool EGS_JCFControl::writeControlString() {
630 start_time = time(0);
649 double f = tsum*norm, df;
650 if (tsum > 0 && tsum2 > 0 && norm > 0 && tcount > 1) {
651 f = tsum*norm/tcount;
652 df = tcount*tsum2/(tsum*tsum)-1;
654 df = 100*sqrt(df/(tcount-1));
663 sprintf(buf,
"%lld %lld %d %lg %lg %lg %lg %lg %ld ",ntot,nleft,njob,tsum,
664 tsum2,tcount,f,df,start_time);
668 bool EGS_JCFControl::getCombinedResult(
double &f,
double &df)
const {
669 if (tsum > 0 && tsum2 > 0 && norm > 0 && tcount > 1) {
670 f = tsum*norm/tcount;
671 df = tcount*tsum2/(tsum*tsum)-1;
673 df = 100*sqrt(df/(tcount-1));
685 bool EGS_JCFControl::readControlString() {
695 int res = sscanf(buf,
"%lld %lld %d %lg %lg %lg %lg %lg %ld",
696 &ntot,&nleft,&njob,&tsum,&tsum2,&tcount,&f,&df,&start_time);
697 if (res == EOF || res != 9) {
703 int EGS_JCFControl::startSimulation() {
708 bool ok = (ipar == ifirst) ? createControlFile() : openControlFile();
711 "job\n\n\n",npar,nchunk);
717 bool EGS_JCFControl::readControlFile() {
718 if (!p->rewindControlFile()) {
719 egsWarning(
"EGS_JCFControl: failed to rewind the job control file\n");
722 int res = READ_FILE(p->fd,buf,nbuf-1);
724 p->unlockControlFile();
725 egsWarning(
"EGS_JCFControl: failed to read the job control file\n");
729 if (!readControlString()) {
730 p->unlockControlFile();
731 egsWarning(
"EGS_JCFControl: failed to read from the control string"
738 bool EGS_JCFControl::writeControlFile() {
739 if (!writeControlString()) {
740 egsWarning(
"EGS_JCFControl::writeControlFile: failed to write to the "
744 if (!p->rewindControlFile()) {
745 egsWarning(
"EGS_JCFControl: failed to rewind the job control file\n");
748 int nwant = strlen(buf)+1;
749 int nwrite = WRITE_FILE(p->fd,buf,nwant);
750 if (!p->unlockControlFile()) {
751 egsWarning(
"EGS_JCFControl::writeControlFile: failed to unlock the "
755 if (nwrite != nwant) {
756 egsWarning(
"EGS_JCFControl::getNextChunk: could write only %d "
757 "instead of %d chars to the job control file?\n",nwrite,nwant);
763 EGS_I64 EGS_JCFControl::getNextChunk() {
764 if (!readControlFile()) {
771 double sum, sum2, count;
773 tsum += sum - last_sum;
774 tsum2 += sum2 - last_sum2;
775 tcount += count - last_count;
779 EGS_I64 nrun = ncase/(npar*nchunk);
793 if (accu > 0 && getCombinedResult(f,df)) {
794 if (df < 100 && df < accu) {
796 egsWarning(
"\n\n*** After combining the results of all parallel "
797 "jobs the requested\n uncertainty of %g%c was reached: %g%c\n"
798 " => terminating simulation.\n\n",accu,c,df,c);
822 usleep(mscnds * 1000);
827 cpu_time = timer.
time();
830 "Total cpu time for this run:",cpu_time,cpu_time/3600);
833 if (previous_cpu_time > 0)
835 "CPU time including previous runs:",cpu_time+previous_cpu_time,
836 (cpu_time+previous_cpu_time)/3600);
838 (cpu_time+previous_cpu_time));
841 double ch_steps, all_steps;
854 return (n_par && i_par == i_first + n_par - 1) ? 1 : 0;
864 int interval = 0, njobs_done = 0, njobs_done_old= 0;
865 while (interval < check_intervals) {
870 if (njobs_done == npar - 1) {
875 if (njobs_done_old < njobs_done) {
879 njobs_done_old = njobs_done;
889 int EGS_JCFControl::finishSimulation() {
897 if (!readControlFile()) {
902 p->closeControlFile();
903 if (njob > 0 || removed_jcf) {
909 int res = _unlink(cfile.c_str());
911 int res = unlink(cfile.c_str());
913 if (res)
egsWarning(
"EGS_JCFControl::finishSimulation: failed to remove "
914 " the job control file %s\n",cfile.c_str());
919 EGS_JCFControl::~EGS_JCFControl() {
923 bool EGS_JCFControl::closeControlFile() {
924 return p->closeControlFile();
927 bool EGS_JCFControl::lockControlFile() {
928 return p->lockControlFile();
931 bool EGS_JCFControl::unlockControlFile() {
932 return p->unlockControlFile();
935 bool EGS_JCFControl::rewindControlFile() {
936 return p->rewindControlFile();
943 egsWarning(
"EGS_RunControl::getRunControlObject(): "
944 "null application?\n");
977 int err = irc->
getInput(
"library",libname);
981 for (
unsigned int j=0; j<rc_libs.size(); j++) {
982 if (libname == rc_libs[j]->libraryName()) {
991 lib =
new EGS_Library(libname.c_str(),dsodir.c_str());
994 egsWarning(
"EGS_RunControl::getRunControlObject: failed to"
995 " load the library %s from %s\n",libname.c_str(),
1000 rc_libs.push_back(lib);
1002 EGS_RunControlCreationFunction create =
1003 (EGS_RunControlCreationFunction) lib->
resolve(
"createRunControl");
1005 egsWarning(
"EGS_RunControl::getRunControlObject: failed to"
1006 " resolve the run control creation function of library %s\n",
1016 vector<string> allowed_types;
1017 allowed_types.push_back(
"simple");
1018 allowed_types.push_back(
"uniform");
1019 allowed_types.push_back(
"balanced");
1020 int rco_t = irc->
getInput(
"rco type",allowed_types,2);
Base class for advanced EGSnrc C++ applications.
virtual EGS_I64 randomNumbersUsed() const
Returns the number of random numbers used.
virtual void describeSimulation()
Describe the simulation.
virtual int outputData()
Output intermediate results.
int getNparallel() const
Returns the number of parallel jobs executing.
EGS_Input * getInput()
Returns a pointer to the EGS_Input object containing the user input to the application found in the i...
virtual void getElectronSteps(double &ch_steps, double &all_steps) const
Get the number of electron steps taken.
virtual void getCurrentResult(double &sum, double &sum2, double &norm, double &count)
Report the current result.
int getFirstParallel() const
Returns the first job number in a parallel run.
int howManyJobsDone()
Counts how many *.egsdat files in app folder.
virtual void setSimulationChunk(EGS_I64 nstart, EGS_I64 nrun, int npar, int nchunk)
Set the simulation chunk.
const string & getFinalOutputFile() const
Returns the base name of the final output file(s)
const string & getAppDir() const
Returns the absolute path to the user code directory.
virtual int combineResults()
Combine results from parallel runs.
const string & getHenHouse() const
Returns the HEN_HOUSE directory.
int getIparallel() const
Returns the job number in a parallel run.
virtual int combinePartialResults()
Combine intermediate results from parallel runs.
virtual int readData()
Read intermediate results.
A 'job control file' (JCF) RCO.
A class for dynamically loading shared libraries.
bool isLoaded() const
Returns true if the library is loaded, false otherwise.
bool load()
Loads the library.
void * resolve(const char *func)
Returns the address of the exported symbol func.
A simple run control object for advanced EGSnrc C++ applications.
RCOType rco_type
RCO type to use.
@ balanced
parallel jobs with balanced load via JCF
@ uniform
parallel jobs with same numbe of histories
@ simple
single job or multiple independent jobs
EGS_RunControl(EGS_Application *app)
Creates an RCO for the application app.
virtual int startSimulation()
Starts the simulation.
virtual bool startBatch(int, EGS_I64)
Start a new batch.
virtual ~EGS_RunControl()
Destructor.
virtual bool finishBatch()
Finish a batch.
virtual int finishSimulation()
Finish the simulation.
EGS_Float time()
Returns the CPU time in seconds since start() was called.
void start()
Starts the time measurement.
EGS_Application class header file.
Global egspp functions header file.
EGS_Library class header file.
void rco_sleep(const int &mscnds)
Suspend execution for a given time (in ms)
EGS_RunControl and EGS_JCFControl class header file.
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,...
EGS_InfoFunction EGS_EXPORT egsInformation
Always use this function for reporting the progress of a simulation and any other type of information...
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
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,...
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...
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.