46 #include "iaea_phsp.h"
48 static bool EGS_PHSP_SCORING_LOCAL inputSet =
false;
50 EGS_PhspScoring::EGS_PhspScoring(
const string &Name,
53 count(0), countg(0), emin(1.e30), emax(-1.e30), first_flush(true), is_resume(false) {
54 otype =
"EGS_PhspScoring";
57 EGS_PhspScoring::~EGS_PhspScoring() {
69 p_stack =
new Particle[store_max];
71 description =
"\n*******************************************\n";
75 description +=
"*******************************************\n";
77 description +=
"\n Will output phase space for particles crossing surfaces of geometry:\n";
81 description +=
"entering and exiting phase space geometry";
83 else if (scoredir == 1) {
86 else if (scoredir == 2) {
90 else if (score_type==1) {
91 description +=
"\n Will output phase space for the following exit/entry region pairs:\n";
93 for (
int i=0; i<fromreg.size(); i++) {
94 sprintf(buf,
"%d ",fromreg[i]);
98 for (
int i=0; i<fromreg.size(); i++) {
99 sprintf(buf,
"%d ",toreg[i]);
104 int nreg =
app->getnRegions();
105 for (
int ir=0; ir<nreg; ir++) {
107 for (
int i=0; i<fromreg.size(); i++) {
108 if (fromreg[i]==ir) {
109 tolist.push_back(toreg[i]);
112 from_to.push_back(tolist);
117 if (phspoutdir ==
"") {
121 description +=
"\n Data will be output in EGSnrc format.\n";
132 else if (oformat==1) {
133 description +=
"\n Data will be output in IAEA format.\n";
143 len = phsp_fname.length();
144 phsp_fname_char =
new char[len+1];
145 phsp_fname.copy(phsp_fname_char,len,0);
146 phsp_fname_char[len]=
'\0';
160 iaea_n_extra_float=1;
165 iaea_n_extra_float=0;
169 description +=
" Header file: " + phsp_fname +
".IAEAheader\n";
170 description +=
" Data file: " + phsp_fname +
".IAEAphsp";
171 string xyzname[3] = {
"X",
"Y",
"Z"};
172 for (
int i=0; i<3; i++) {
173 if (xyz_is_const[i]) {
176 description +=
"\n Data scored at constant " + xyzname[i] +
" = " + xyz.str() +
" cm";
184 else if (ocharge == 1) {
187 else if (ocharge == 2) {
190 if (oformat ==1 && score_time) {
191 description +=
"\n time index will be scored (if available)";
193 if (oformat ==0 && score_mc) {
194 description +=
"\n will score multiple crossers (and descendents)";
201 void EGS_PhspScoring::reportResults() {
205 iaea_destroy_source(&iaea_id,&iaea_iostat);
207 egsFatal(
"\n EGS_PhspScoring: Error closing phase space file.\n");
210 else if (oformat == 0) {
213 egsInformation(
"\n======================================================\n");
215 egsInformation(
"======================================================\n");
218 egsInformation(
" Header file: %s.IAEAheader\n",phsp_fname.c_str());
221 else if (oformat == 0) {
226 if (count == countg) {
236 egsInformation(
"=> min. k.e. of charged particles = %g MeV\n",emintmp);
237 egsInformation(
"=> no. of primary histories represented = %lld\n",last_case);
238 egsInformation(
"\n======================================================\n");
245 void EGS_PhspScoring::storeParticle(EGS_I64 ncase) {
249 egsWarning(
"\nEGS_PhspScoring: User requested time index scoring, but time is inavailable with this source.\n");
250 egsWarning(
"Turning off time index scoring.\n");
255 EGS_Float prm =
app->getRM();
273 else if (oformat == 1) {
278 if (ncase != last_case) {
284 p_stack[phsp_index].E = E;
298 if (phsp_index > store_max - 1) {
305 void EGS_PhspScoring::openPhspFile()
const {
309 phsp_file.open(phsp_fname.c_str(),ios::binary|ios::out|ios::in);
311 egsFatal(
"\nEGS_PhspScoring: Failed to open phase space file %s for appending.\n",
315 phsp_file.seekg(5,ios::beg);
316 phsp_file.read((
char *) &count4,
sizeof(
unsigned int));
317 if (count4 != countprev) {
318 egsFatal(
"\nEGS_PhspScoring: Particle no. mismatch between %s and .egsdat file.\n",phsp_fname.c_str());
321 phsp_file.seekp(0,ios::end);
322 if (phsp_file.tellp() != 28 + countprev*
sizeof(egs_phsp_write_struct)) {
323 egsFatal(
"\nEGS_PhspScoring: File size mismatch in %s and .egsdat file.\n",phsp_fname.c_str());
327 phsp_file.open(phsp_fname.c_str(),ios::binary|ios::out);
329 egsFatal(
"\nEGS_PhspScoring: Failed to open phase space file %s for writing.\n",
332 phsp_file.write(
"MODE0",5);
334 phsp_file.seekp(28,ios::beg);
337 else if (oformat == 1) {
343 iaea_new_source(&iaea_id,phsp_fname_char,&rwmode,&iaea_iostat,len);
344 if (iaea_iostat < 0) {
345 egsFatal(
"\nEGS_PhspScoring: Failed to open phase space file %s.IAEAphsp for appending.\n",phsp_fname.c_str());
351 iaea_get_max_particles(&iaea_id,&type,&nparticle);
352 if (nparticle != countprev) {
353 egsFatal(
"\nEGS_PhspScoring: Particle no. mismatch between %s.IAEAphsp and .egsdat file.\n",phsp_fname.c_str());
355 iaea_check_file_size_byte_order(&iaea_id,&iaea_iostat);
356 if (iaea_iostat != 0) {
357 egsFatal(
"\nEGS_PhspScoring: Byte order/file size mismatch in %s.IAEAphsp.\n",phsp_fname.c_str());
362 iaea_new_source(&iaea_id,phsp_fname_char,&rwmode,&iaea_iostat,len);
363 if (iaea_iostat < 0) {
364 egsFatal(
"\nEGS_PhspScoring: Failed to open phase space file %s.IAEAphsp for writing.\n",phsp_fname.c_str());
370 for (
int i=0; i<3; i++) {
371 if (xyz_is_const[i]) {
373 float constval = xyzscore[i];
374 iaea_set_constant_variable(&iaea_id,&index,&constval);
379 int latch_ind_tmp = latch_ind;
380 int iaea_n_extra_long_tmp=iaea_n_extra_long;
381 int iaea_i_latch_tmp=iaea_i_latch;
382 int time_ind_tmp = time_ind;
383 int iaea_i_time_tmp = iaea_i_time;
384 int iaea_n_extra_float_tmp=iaea_n_extra_float;
386 iaea_set_extra_numbers(&iaea_id,&iaea_n_extra_float_tmp,&iaea_n_extra_long_tmp);
387 iaea_set_type_extralong_variable(&iaea_id,&iaea_i_latch_tmp,&latch_ind_tmp);
389 iaea_set_type_extrafloat_variable(&iaea_id,&iaea_i_time_tmp,&time_ind_tmp);
396 int EGS_PhspScoring::flushBuffer()
const {
406 for (
int j=0; j<phsp_index; j++) {
409 int n_stat = p_stack[j].E < 0 ? 1 : 0;
410 float E = abs(p_stack[j].E);
412 int type = iaea_q_type[p_stack[j].q+1];
415 EGS_I32 *iaea_extra_long =
new EGS_I32[iaea_n_extra_long];
416 iaea_extra_long[iaea_i_latch]=p_stack[j].latch;
417 float *iaea_extra_float =
new float[iaea_n_extra_float];
419 iaea_extra_float[iaea_i_time] = p_stack[j].time;
423 float wt = p_stack[j].wt;
424 float x = p_stack[j].x;
425 float y = p_stack[j].y;
426 float z = p_stack[j].z;
427 float u = p_stack[j].u;
428 float v = p_stack[j].v;
429 float w = p_stack[j].w;
432 iaea_write_particle(&iaea_id,&n_stat,&type,&E,&wt,&x,&y,&z,&u,&v,&w,iaea_extra_float,iaea_extra_long);
434 egsFatal(
"\nEGS_PhspScoring: Failed to write particle data to phase space file.");
438 EGS_I64 last_case_tmp = last_case;
439 iaea_set_total_original_particles(&iaea_id,&last_case_tmp);
442 iaea_update_header(&iaea_id,&iaea_iostat);
444 egsFatal(
"\nEGS_PhspScoring: Failed to update phase space header file.");
447 else if (oformat == 0) {
449 egsFatal(
"\nEGS_PhspScoring: phase space file is not open for writing.");
452 for (
int j=0; j<phsp_index; j++) {
453 egs_phsp_write_struct ws(p_stack[j]);
454 phsp_file.write((
char *) &ws,
sizeof(ws));
457 iostream::off_type pos = (count+1)*
sizeof(egs_phsp_write_struct);
459 phsp_file.seekp(5,ios::beg);
460 unsigned int count4 = count, countg4 = countg;
461 float pinc = last_case;
463 if (countg4==count4) {
469 phsp_file.write((
char *) &count4,
sizeof(
unsigned int));
470 phsp_file.write((
char *) &countg4,
sizeof(
unsigned int));
471 phsp_file.write((
char *) &emax,
sizeof(float));
472 phsp_file.write((
char *) &emintmp,
sizeof(float));
473 phsp_file.write((
char *) &pinc,
sizeof(float));
474 phsp_file.seekp(pos,ios::beg);
482 bool EGS_PhspScoring::storeState(ostream &data)
const {
494 bool EGS_PhspScoring::setState(istream &data) {
506 bool EGS_PhspScoring::addState(istream &data) {
526 static void setInputs() {
529 setBaseAusgabObjectInputs();
531 ausBlockInput->getSingleInput(
"library")->setValues({
"egs_phsp_scoring"});
534 auto formatPtr = ausBlockInput->addSingleInput(
"output format",
false,
"The phase-space format to output. Defaults to EGSnrc", {
"EGSnrc",
"IAEA"});
536 auto xPtr = ausBlockInput->addSingleInput(
"constant X",
false,
"X values(cm) at which all particles are scored.");
537 xPtr->addDependency(formatPtr,
"IAEA");
538 auto yPtr = ausBlockInput->addSingleInput(
"constant Y",
false,
"Y values(cm) at which all particles are scored.");
539 yPtr->addDependency(formatPtr,
"IAEA");
540 auto zPtr = ausBlockInput->addSingleInput(
"constant Z",
false,
"Z values(cm) at which all particles are scored.");
541 zPtr->addDependency(formatPtr,
"IAEA");
542 auto muPtr = ausBlockInput->addSingleInput(
"score time index",
false,
"Whether to score the time index for each particle. Only valid for IAEA phase-spaces. Default is no.", {
"yes",
"no"});
543 muPtr->addDependency(formatPtr,
"IAEA");
545 auto multiPtr = ausBlockInput->addSingleInput(
"score multiple crossers",
false,
"Whether to score the same particle multiple times, if it happens to cross the phase-space surface more than once. Default is no.", {
"yes",
"no"});
546 multiPtr->addDependency(formatPtr,
"EGSnrc");
548 ausBlockInput->addSingleInput(
"particle type",
true,
"The type of particle to score", {
"all",
"photons",
"charged"});
549 ausBlockInput->addSingleInput(
"output directory",
true,
"The name of the output directory");
552 auto spacePtr = ausBlockInput->addSingleInput(
"phase space geometry",
true,
"The name of a previously defined geometry");
553 auto scorePtr = ausBlockInput->addSingleInput(
"score particles on",
false,
"Which situation to score particles as they cross the geometry boundary. On entry, exit, or entry and exit. Default is entry and exit.", {
"entry",
"exit",
"entry and exit"});
556 auto fromPtr = ausBlockInput->addSingleInput(
"from regions",
true,
"A list of exit region numbers");
557 auto toPtr = ausBlockInput->addSingleInput(
"to regions",
true,
"A list of entry region numbers");
560 spacePtr->addDependency(fromPtr,
"",
true);
561 spacePtr->addDependency(toPtr,
"",
true);
562 scorePtr->addDependency(fromPtr,
"",
true);
563 scorePtr->addDependency(toPtr,
"",
true);
564 fromPtr->addDependency(spacePtr,
"",
true);
565 fromPtr->addDependency(scorePtr,
"",
true);
566 toPtr->addDependency(spacePtr,
"",
true);
567 toPtr->addDependency(scorePtr,
"",
true);
570 EGS_PHSP_SCORING_EXPORT
string getExample() {
574 # Example of egs_phsp_scoring
575 #:start ausgab object:
576 library = egs_phsp_scoring
583 score time index = no
586 #:start ausgab object:
587 library = egs_phsp_scoring
589 phase space geometry = scoreplane
590 output format = EGSnrc
592 score particles on = entry
593 score multiple crossers = yes
599 EGS_PHSP_SCORING_EXPORT shared_ptr<EGS_BlockInput> getInputs() {
603 return ausBlockInput;
608 const static char *func =
"createAusgabObject(phsp_scoring)";
616 vector <int> from_reg, to_reg;
623 bool xyzisconst[3] = {
false,
false,
false};
626 int err01 = input->
getInput(
"phase space geometry",gname);
633 egsWarning(
"\nEGS_PhspScoring: %s does not name an existing geometry.\n"
634 "Will assume you want to use exit/entry region pairs.\n",gname.c_str());
638 if (input->
getInput(
"score particles on", str) < 0) {
639 egsInformation(
"EGS_PhspScoring: No input for scoring direction.\n");
640 egsInformation(
"Will score on entry and exit from phase space geometry.\n");
645 vector<string> allowed_sdir;
646 allowed_sdir.push_back(
"entry and exit");
647 allowed_sdir.push_back(
"entry");
648 allowed_sdir.push_back(
"exit");
649 sdir = input->
getInput(
"score particles on",allowed_sdir,-1);
651 egsFatal(
"\nEGS_PhspScoring: Invalid scoring direction.\n");
658 int err05 = input->
getInput(
"from regions",from_reg);
659 int err06 = input->
getInput(
"to regions",to_reg);
660 if (err05 || err06) {
661 egsFatal(
"\nEGS_PhspScoring: Missing/incorrect input for scoring method\n"
662 "(scoring geometry or pairs of exit/entry regions)\n");
666 vector<int>::iterator p,p1;
667 if (from_reg.size() > to_reg.size()) {
668 p = from_reg.begin();
669 egsWarning(
"\nEGS_PhspScoring: Mismatch in no. of exit/entry regions.\n"
670 "Will only score for matched pairs.\n");
672 from_reg.erase(p,p+from_reg.size()-to_reg.size());
674 else if (to_reg.size() > from_reg.size()) {
676 egsWarning(
"\nEGS_PhspScoring: Mismatch in no. of exit/entry regions.\n"
677 "Will only score for matched pairs.\n");
678 p += from_reg.size();
679 to_reg.erase(p,p+to_reg.size()-from_reg.size());
683 while (i<from_reg.size()) {
684 if (from_reg[i]==to_reg[i]) {
685 egsInformation(
"\nEGS_PhspScoring: Cannot have entry region = exit region (reg no. %d)\n",from_reg[i]);
687 p=from_reg.begin()+i;
688 p1 =to_reg.begin()+i;
700 if (input->
getInput(
"output format", str) < 0) {
701 egsInformation(
"EGS_PhspScoring: No input for output format type. Will default to EGSnrc.\n");
705 vector<string> allowed_oformat;
706 allowed_oformat.push_back(
"EGSnrc");
707 allowed_oformat.push_back(
"IAEA");
708 phspouttype = input->
getInput(
"output format", allowed_oformat, -1);
709 if (phspouttype < 0) {
710 egsFatal(
"\nEGS_PhspScoring: Invalid output format.\n");
713 if (phspouttype == 1) {
714 int err02 = input->
getInput(
"constant X",xyzconst[0]);
715 int err03 = input->
getInput(
"constant Y",xyzconst[1]);
716 int err04 = input->
getInput(
"constant Z",xyzconst[2]);
718 xyzisconst[0] =
true;
721 xyzisconst[1] =
true;
724 xyzisconst[2] =
true;
729 if (!input->
getInput(
"score mu", str)) {
730 vector<string> allowed_timescore;
731 allowed_timescore.push_back(
"no");
732 allowed_timescore.push_back(
"yes");
733 itimescore = input->
getInput(
"score mu",allowed_timescore,-1);
734 if (itimescore < 0) {
735 egsWarning(
"\nEGS_PhspScoring: Invalid input for time index scoring. Will not score time.\n");
740 if (!input->
getInput(
"score time index", str)) {
741 vector<string> allowed_timescore;
742 allowed_timescore.push_back(
"no");
743 allowed_timescore.push_back(
"yes");
744 itimescore = input->
getInput(
"score time index",allowed_timescore,-1);
745 if (itimescore < 0) {
746 egsWarning(
"\nEGS_PhspScoring: Invalid input for time index scoring. Will not score time.\n");
752 if (phspouttype == 0) {
754 if (!input->
getInput(
"score multiple crossers", str)) {
755 vector<string> allowed_scoremc;
756 allowed_scoremc.push_back(
"no");
757 allowed_scoremc.push_back(
"yes");
758 iscoremc = input->
getInput(
"score multiple crossers",allowed_scoremc,-1);
760 egsWarning(
"\nEGS_PhspScoring: Invalid input for score multiple crossers. Will not score.\n");
765 if (input->
getInput(
"output directory",outdir) < 0) {
768 if (input->
getInput(
"particle type", str) < 0) {
769 egsInformation(
"EGS_PhspScoring: No input for particle type. Will score all.\n");
774 vector<string> allowed_ptype;
775 allowed_ptype.push_back(
"all");
776 allowed_ptype.push_back(
"photons");
777 allowed_ptype.push_back(
"charged");
778 ptype = input->
getInput(
"particle type",allowed_ptype,-1);
780 egsFatal(
"\nEGS_PhspScoring: Invalid particle type.\n");
790 result->setGeom(phspgeom);
793 result->setEntryExitReg(from_reg,to_reg);
795 result->setOType(phspouttype);
796 result->setXYZconst(xyzisconst,xyzconst);
797 result->setOutDir(outdir);
798 result->setParticleType(ptype);
799 result->setScoreDir(sdir);
800 result->setTimeScore(itimescore);
801 result->setScoreMC(iscoremc);
Base class for advanced EGSnrc C++ applications.
int getNparallel() const
Returns the number of parallel jobs executing.
EGS_Float getTimeIndex()
Returns the value of the time synchronization parameter.
const string & getAppDir() const
Returns the absolute path to the user code directory.
int getIparallel() const
Returns the job number in a parallel run.
EGS_Particle top_p
The top particle on the stack (i.e., the particle being transported)
virtual void setApplication(EGS_Application *App)
Set the application this object belongs to.
string description
A short ausgab object description.
EGS_Application * app
The application this object belongs to.
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
const string & getName() const
Get the name of this geometry.
static EGS_BaseGeometry * getGeometry(const string &Name)
Get a pointer to the geometry named Name.
void setName(EGS_Input *inp)
Set the name of the object from the information provided by inp.
const string & getObjectName() const
Get the object name.
string name
The object name.
A phase space scoring object: header.
Global egspp functions header file.
A phase space scoring ausgab object.
EGS_RADIATIVE_SPLITTING_EXPORT EGS_AusgabObject * createAusgabObject(EGS_Input *input, EGS_ObjectFactory *f)
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.
EGS_Float E
particle energy in MeV
int latch
latch variable (useful as a flag on many occasions)
EGS_Float wt
statistical weight