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), resume(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(
"resume");
114 ctype.push_back(
"analyze");
115 ctype.push_back(
"combine");
116 ctype.push_back(
"restart");
117 resume = input->
getInput(
"calculation",ctype,0);
125 if (!n_run_controls) {
126 while (rc_libs.size() > 0) {
127 delete rc_libs[rc_libs.size()-1];
133 void EGS_RunControl::describeRCO() {
135 "Run Control Object (RCO):\n"
136 "=========================\n");
150 bool EGS_RunControl::storeState(ostream &data) {
154 data <<
" " << (cpu_time+previous_cpu_time) << endl;
158 bool EGS_RunControl::setState(istream &data) {
165 data >> previous_cpu_time;
169 bool EGS_RunControl::addState(istream &data) {
170 EGS_Float previous_cpu_time_save = previous_cpu_time;
171 if (!setState(data)) {
174 previous_cpu_time += previous_cpu_time_save;
178 void EGS_RunControl::resetCounter() {
179 previous_cpu_time = 0;
187 if (resume == 1 || resume == 2 || resume == 4) {
197 else if (resume == 3) {
206 time_t tinfo = time(0);
208 asctime(localtime(&tinfo)));
210 egsInformation(
" Fresh simulation of %lld histories\n\n\n",ncase);
214 " new histories\n\n\n",ndone,ncase-ndone);
222 " Batch CPU time Result Uncertainty(%c)\n"
223 "==========================================================\n",
'%');
224 if (maxt > 0 && ndone > 0) {
225 EGS_Float time_per_shower = (cpu_time + previous_cpu_time)/ndone;
226 EGS_Float extra_time = time_per_shower*ncase_per_batch;
227 if (cpu_time + extra_time > maxt*3600) {
228 egsWarning(
"\n\n*** Not enough time to finish another batch\n"
229 " => terminating simulation.\n\n");
234 ndone += ncase_per_batch;
239 cpu_time = timer.
time();
242 egsWarning(
"\n\noutputData() returned error code %d ?\n",out);
244 double sum, sum2, norm, count;
247 if (sum > 0 && sum2 > 0 && norm > 0 && count > 1) {
249 df = count*sum2/(sum*sum)-1;
251 df = 100*sqrt(df/(count-1));
262 if (df < 100 && accu > 0 && df < accu) {
264 egsWarning(
"\n\n*** Reached the requested uncertainty of %g%c\n"
265 " => terminating simulation.\n\n",accu,c);
273 ipar(app->getIparallel()), ifirst(app->getFirstParallel()),
274 milliseconds(1000), check_intervals(5), check_egsdat(true),
283 int err = input->
getInput(
"interval wait time", dummy);
285 milliseconds = dummy;
289 err = input->
getInput(
"number of intervals", dummy);
291 check_intervals = dummy;
296 err = input->
getInput(
"watcher jobs", w_jobs);
298 for (
int i = 0; i < w_jobs.size(); i++) {
299 if (ipar == w_jobs[i]) {
307 if (ipar == ifirst + npar - 1) {
316 vector<string> check_options;
317 check_options.push_back(
"yes");
318 check_options.push_back(
"no");
319 int ichk = input->
getInput(
"check jobs completed",check_options,0);
321 check_egsdat =
false;
327 if (ipar == ifirst + npar - 1) {
333 int EGS_UniformRunControl::startSimulation() {
343 if (remove(datFile.c_str()) == 0) {
344 egsWarning(
"EGS_UniformRunControl: %s deleted\n",
352 void EGS_UniformRunControl::describeRCO() {
354 EGS_RunControl::describeRCO();
359 " Watcher job: remains running after completion checking\n"
360 " for other jobs finishing every %d s for %d s!\n",
361 milliseconds/1000, check_intervals*milliseconds/1000);
365 " Option to check for finishing jobs is OFF!\n\n");
376 #include <sys/types.h>
377 #include <sys/stat.h>
378 #include <sys/locking.h>
381 #define OPEN_FILE _open
382 #define CLOSE_FILE _close
383 #define CREATE_FLAGS _O_CREAT | _O_EXCL | _O_RDWR, _S_IREAD | _S_IWRITE
384 #define OPEN_FLAGS _O_RDWR,_S_IREAD | _S_IWRITE
385 #define WAIT_FOR_FILE Sleep(1000)
386 #define WRITE_FILE _write
387 #define READ_FILE _read
393 #include <sys/types.h>
394 #include <sys/stat.h>
399 #define OPEN_FILE open
400 #define CLOSE_FILE close
401 #define CREATE_FLAGS O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR
402 #define OPEN_FLAGS O_RDWR
403 #define WAIT_FOR_FILE sleep(1)
404 #define WRITE_FILE write
405 #define READ_FILE read
415 class EGS_LOCAL EGS_FileLocking {
421 struct flock fl_write, fl_unlock;
423 EGS_FileLocking() : fd(-1), is_locked(false), ntry(15) {
425 fl_write.l_type = F_WRLCK;
426 fl_write.l_whence = SEEK_SET;
427 fl_write.l_start = 0;
429 fl_unlock.l_type = F_UNLCK;
430 fl_unlock.l_whence = SEEK_SET;
431 fl_unlock.l_start = 0;
440 bool createControlFile(
const char *fname) {
445 fd = OPEN_FILE(fname,CREATE_FLAGS);
446 egsWarning(
"createControlFile: file=%s fd=%d\n",fname,fd);
448 egsWarning(
"createControlFile(): open failed! (fd=%d)\n",fd);
450 perror(
"System error was");
453 return lockControlFile();
455 bool openControlFile(
const char *fname) {
460 for (
int t=0; t<ntry; t++) {
461 fd = OPEN_FILE(fname,OPEN_FLAGS);
469 bool closeControlFile() {
471 int res = CLOSE_FILE(fd);
477 bool lockControlFile() {
485 long np = _lseek(fd,0L,SEEK_SET);
487 egsWarning(
"lockControlFile: _lseek returned %d?\n",np);
490 int res = _locking(fd,_LK_LOCK,1000000L);
497 for (
int i1=0; i1<5; i1++) {
498 for (
int i2=0; i2<12; i2++) {
499 int res = fcntl(fd,F_SETLK,&fl_write);
506 egsWarning(
"lockControlFile: failed to lock file for "
512 bool unlockControlFile() {
520 int np = _lseek(fd,0L,SEEK_SET);
522 egsWarning(
"unlockControlFile: _lseek returned %d?\n",np);
525 int res = _locking(fd,_LK_UNLCK,1000000L);
527 int res = fcntl(fd,F_SETLKW,&fl_unlock);
535 bool rewindControlFile() {
540 if (!lockControlFile()) {
545 return !_lseek(fd,0,SEEK_SET);
547 return !lseek(fd,0,SEEK_SET);
555 EGS_RunControl(a), tsum(0), tsum2(0), tcount(0), norm(1), last_sum(0),
556 last_sum2(0), last_count(0), njob(0), npar(app->getNparallel()),
557 ipar(app->getIparallel()), ifirst(app->getFirstParallel()),
558 first_time(true), removed_jcf(false), nbuf(Nbuf), p(new EGS_FileLocking) {
568 int err = input->
getInput(
"nchunk",nchunk);
579 buf =
new char [nbuf];
587 bool EGS_JCFControl::createControlFile() {
590 if (!p->createControlFile(cfile.c_str())) {
591 egsWarning(
"EGS_JCFControl: failed to create or lock the "
592 " job control file %s\n\n",cfile.c_str());
598 writeControlString();
599 int nwant = strlen(buf)+1;
600 int nwrite = WRITE_FILE(p->fd,buf,nwant);
601 if (nwrite != nwant) {
604 return p->unlockControlFile();
607 bool EGS_JCFControl::openControlFile() {
610 if (!p->openControlFile(cfile.c_str())) {
611 egsWarning(
"EGS_JCFControl: failed to open the "
612 " job control file %s\n\n",cfile.c_str());
620 #define MY_OSTREAM std::ostrstream
621 #define MY_ISTREAM std::istrstream
624 #define MY_OSTREAM std::ostringstream
625 #define MY_ISTREAM std::istringstream
628 bool EGS_JCFControl::writeControlString() {
631 start_time = time(0);
650 double f = tsum*norm, df;
651 if (tsum > 0 && tsum2 > 0 && norm > 0 && tcount > 1) {
652 f = tsum*norm/tcount;
653 df = tcount*tsum2/(tsum*tsum)-1;
655 df = 100*sqrt(df/(tcount-1));
664 sprintf(buf,
"%lld %lld %d %lg %lg %lg %lg %lg %ld ",ntot,nleft,njob,tsum,
665 tsum2,tcount,f,df,start_time);
669 bool EGS_JCFControl::getCombinedResult(
double &f,
double &df)
const {
670 if (tsum > 0 && tsum2 > 0 && norm > 0 && tcount > 1) {
671 f = tsum*norm/tcount;
672 df = tcount*tsum2/(tsum*tsum)-1;
674 df = 100*sqrt(df/(tcount-1));
686 bool EGS_JCFControl::readControlString() {
696 int res = sscanf(buf,
"%lld %lld %d %lg %lg %lg %lg %lg %ld",
697 &ntot,&nleft,&njob,&tsum,&tsum2,&tcount,&f,&df,&start_time);
698 if (res == EOF || res != 9) {
704 int EGS_JCFControl::startSimulation() {
709 bool ok = (ipar == ifirst) ? createControlFile() : openControlFile();
712 "job\n\n\n",npar,nchunk);
718 bool EGS_JCFControl::readControlFile() {
719 if (!p->rewindControlFile()) {
720 egsWarning(
"EGS_JCFControl: failed to rewind the job control file\n");
723 int res = READ_FILE(p->fd,buf,nbuf-1);
725 p->unlockControlFile();
726 egsWarning(
"EGS_JCFControl: failed to read the job control file\n");
730 if (!readControlString()) {
731 p->unlockControlFile();
732 egsWarning(
"EGS_JCFControl: failed to read from the control string"
739 bool EGS_JCFControl::writeControlFile() {
740 if (!writeControlString()) {
741 egsWarning(
"EGS_JCFControl::writeControlFile: failed to write to the "
745 if (!p->rewindControlFile()) {
746 egsWarning(
"EGS_JCFControl: failed to rewind the job control file\n");
749 int nwant = strlen(buf)+1;
750 int nwrite = WRITE_FILE(p->fd,buf,nwant);
751 if (!p->unlockControlFile()) {
752 egsWarning(
"EGS_JCFControl::writeControlFile: failed to unlock the "
756 if (nwrite != nwant) {
757 egsWarning(
"EGS_JCFControl::getNextChunk: could write only %d "
758 "instead of %d chars to the job control file?\n",nwrite,nwant);
764 EGS_I64 EGS_JCFControl::getNextChunk() {
765 if (!readControlFile()) {
772 double sum, sum2, count;
774 tsum += sum - last_sum;
775 tsum2 += sum2 - last_sum2;
776 tcount += count - last_count;
780 EGS_I64 nrun = ncase/(npar*nchunk);
794 if (accu > 0 && getCombinedResult(f,df)) {
795 if (df < 100 && df < accu) {
797 egsWarning(
"\n\n*** After combining the results of all parallel "
798 "jobs the requested\n uncertainty of %g%c was reached: %g%c\n"
799 " => terminating simulation.\n\n",accu,c,df,c);
823 usleep(mscnds * 1000);
828 cpu_time = timer.
time();
831 "Total cpu time for this run:",cpu_time,cpu_time/3600);
834 if (previous_cpu_time > 0)
836 "CPU time including previous runs:",cpu_time+previous_cpu_time,
837 (cpu_time+previous_cpu_time)/3600);
839 (cpu_time+previous_cpu_time));
842 double ch_steps, all_steps;
855 return (n_par && i_par == i_first + n_par - 1) ? 1 : 0;
865 int interval = 0, njobs_done = 0, njobs_done_old= 0;
866 while (interval < check_intervals) {
871 if (njobs_done == npar - 1) {
876 if (njobs_done_old < njobs_done) {
880 njobs_done_old = njobs_done;
890 int EGS_JCFControl::finishSimulation() {
898 if (!readControlFile()) {
903 p->closeControlFile();
904 if (njob > 0 || removed_jcf) {
910 int res = _unlink(cfile.c_str());
912 int res = unlink(cfile.c_str());
914 if (res)
egsWarning(
"EGS_JCFControl::finishSimulation: failed to remove "
915 " the job control file %s\n",cfile.c_str());
920 EGS_JCFControl::~EGS_JCFControl() {
924 bool EGS_JCFControl::closeControlFile() {
925 return p->closeControlFile();
928 bool EGS_JCFControl::lockControlFile() {
929 return p->lockControlFile();
932 bool EGS_JCFControl::unlockControlFile() {
933 return p->unlockControlFile();
936 bool EGS_JCFControl::rewindControlFile() {
937 return p->rewindControlFile();
944 egsWarning(
"EGS_RunControl::getRunControlObject(): "
945 "null application?\n");
951 irc = inp->getInputItem(
"run control");
978 int err = irc->
getInput(
"library",libname);
982 for (
unsigned int j=0; j<rc_libs.size(); j++) {
983 if (libname == rc_libs[j]->libraryName()) {
992 lib =
new EGS_Library(libname.c_str(),dsodir.c_str());
995 egsWarning(
"EGS_RunControl::getRunControlObject: failed to"
996 " load the library %s from %s\n",libname.c_str(),
1001 rc_libs.push_back(lib);
1003 EGS_RunControlCreationFunction create =
1004 (EGS_RunControlCreationFunction) lib->
resolve(
"createRunControl");
1006 egsWarning(
"EGS_RunControl::getRunControlObject: failed to"
1007 " resolve the run control creation function of library %s\n",
1017 vector<string> allowed_types;
1018 allowed_types.push_back(
"simple");
1019 allowed_types.push_back(
"uniform");
1020 allowed_types.push_back(
"balanced");
1021 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.