def __init__(self): self.LAYER = TypeKeyword('LAYER', (float, float), comment='Z_lower and Z_higher') self.CENTER = TypeKeyword('CENTER', (float, float), comment='X_centre and Y_centre') keyword = TypeKeyword('CYLIND', (int, float, float), comment='Material, R_inner and R_outer') self.CYLIND = KeywordSequence(keyword)
class GeometryDefinitionGroup(KeywordGroup): """ This block of lines defines the geometrical structure. The only allowed keywords in the geometry definition list are 'GSTART', 'LAYER_', 'CENTRE', 'CYLIND' and 'GEND__' (notice the blanks). The definition list must begin with the 'GSTART' line and terminate with the 'GEND__' line. The second line must be a 'LAYER_' line, which initiates the definition of the layer structure. Each 'LAYER_' line is followed by a 'CENTRE' line (optional) and by one or several 'CYLIND' lines, which define the various concentric rings in the layer; a layer may be void. No blank lines are allowed in the geometry definition list. Layers must be defined in increasing order of heights, from bottom to top of the structure. If the 'CENTRE' line is not entered, cylinders are assumed to be centred on the Z-axis (XCEN=YCEN=0.0). Cylinders have to be defined in increasing radial order, from the centre to the periphery. The two lengths in each 'LAYER_' and 'CYLIND' line must be entered in increasing order. All numerical data are read in free format. """ def __init__(self): self.LAYER = TypeKeyword('LAYER', (float, float), comment='Z_lower and Z_higher') self.CENTER = TypeKeyword('CENTER', (float, float), comment='X_centre and Y_centre') keyword = TypeKeyword('CYLIND', (int, float, float), comment='Material, R_inner and R_outer') self.CYLIND = KeywordSequence(keyword) def get_keywords(self): return (self.LAYER, self.CENTER, self.CYLIND) def set(self, zlow, zhigh, xcen=None, ycen=None, cylinders=None): self.LAYER.set(zlow, zhigh) self.CENTER.set(xcen, ycen) self._set_keyword_sequence(self.CYLIND, cylinders)
def __init__(self): super().__init__() self.PDANGL = TypeKeyword('PDANGL', (float, float, float, float, int), comment='Angular window, in deg, IPSF') self.PDENER = TypeKeyword('PDENER', (float, float, int), comment='Energy window, no. of channels') self.XRORIG = TypeKeyword( 'XRORIG', (str, ), comment='Map of emission sites of detected x rays')
def __init__(self): keyword = TypeKeyword( 'XRAYE', (float, float), comment='Energy interval where x rays are mapped') super().__init__(keyword)
def __init__(self): keyword = TypeKeyword('SEXTND', (int, int, float), comment='Extended source in KL,KC, rel. activity dens.') super().__init__(keyword)
def __init__(self): keyword = TypeKeyword('DOSE2D', (int, int, int, int), comment='Tally distributions in KL,KC with NZ,NR bins') super().__init__(keyword)
def __init__(self): self.ENDETC = penelope_keywords.ENDETC() self.EDSPC = penelope_keywords.EDSPC() keyword = TypeKeyword('EDBODY', (int, int), comment='Active cylinder') self.EDBODY = KeywordSequence(keyword)
class ImpactDetectorGroup(KeywordGroup): """ Each impact detector consists of a set of active bodies, which must have been defined as parts of the geometry. The output spectrum is the energy distribution of particles that entered any of the active bodies coming from a body that is not active (i.e. that is not part of the detector). Notice that a detected particle can re-enter the detector volume and, consequently, be 'counted' several times (except when the flag IDCUT is set equal to 0, see below). Active bodies cannot be void, because the geometry routines would not stop particles at their limiting surfaces. In case you need to define detectors outside the material system, fill them with an arbitrary material of very small density to avoid perturbing the transport process. To define each impact detector, insert the following block of lines; IMPDET : Starts the definition of a new detector. Up to 25 different detectors can be considered. EL and EU are the lower and upper limits of the energy window covered by the impact detector. NBE is the number of bins in the output energy spectrum of the detector (.LE. 1000). If NBE is positive, energy bins have uniform width, DE=(EU-EL)/NBE. When NBE is negative, the bin width increases geometrically with the energy, i.e., the energy bins have uniform width on a logarithmic scale. The integer flag IPSF serves to activate the creation of a phase-space file (psf), which contains the state variables of all particles that enter the detector. Use this option with care, because psf's may grow very fast. IPSF=0; no psf is created. IPSF=1; the psf is created. Only one PSF can be created in each simulation run. The integer flag IDCUT allows discontinuing the tracking of particles that enter the detector. IDCUT=0; the simulation of a particle is discontinued when it enters the detector (useful to stop the simulation of particles recorded in a psf). IDCUT=1; the presence of the detector does not affect the tracking of particles. IDCUT=2; the presence of the detector does not affect the tracking of particles. The distribution of particle fluence with respect to energy (integrated over the volume of the detector) is tallied. The calculated distribution has dimensions of length/energy. DEFAULTS: None IDPSF_ : Name of the output phase-space file (up to 20 characters). DEFAULT: 'psf-impdet-##.dat' IDSPC_ : Name of the output energy spectrum file (up to 20 characters). DEFAULT: 'spc-impdet-##.dat' IDFLNC : Name of the output file with the energy distribution of particle fluence (20 characters). This file is generated only when IDCUT=2. DEFAULT: 'fln-impdet-##.dat' IDAGEL : Activates the evaluation of the age of particles, defined as the time elapsed since the start of the primary particle that originated the shower. The program generates the age distribution of detected particles, i.e., particles of the types declared in lines IDKPAR (see below) that enter the detector with energy in the window (EL,EU). The distribution is tallied for ages in the interval between AGEL and AGEU (both in seconds), which is partitioned into NAGE bins. If NAGE is positive, the age bins have uniform width. When NAGE is negative, the width of age bins is uniform on a logarithmic scale. DEFAULTS: NAGE=100, AGEL=0.0, AGEU must always be specified IDAGEF : Name of the output age distribution file (up to 20 characters) DEFAULT: 'age-impdet-##.dat' IDBODY : Active body of the detector. One line for each active body. DEFAULT: None --> Notice that a body cannot be part of more than one impact detector. IDKPAR : Type of particle that is detected (1=electrons, 2=photons or 3=positrons). One line for each type. The detector has no effect for particles that are not detected. This feature can be used, e.g., to make a body or a set of bodies opaque to particles of a certain type. DEFAULT: All particles are detected """ def __init__(self): self.IMPDET = TypeKeyword('IMPDET', (float, float, int, int, int), comment='E-window, no. of bins, IPSF, IDCUT') self.IDSPC = TypeKeyword('IDSPC', (str, ), comment='Spectrum file name, 20 chars') self.IDPSF = TypeKeyword('IDPSF', (str, ), comment='Phase-space file name, 20 chars') self.IDFLNC = TypeKeyword( 'IDFLNC', (str, ), comment='Fluence spectrum file name, 20 chars') self.IDAGEL = TypeKeyword('IDAGEL', (float, float, int), comment='Age interval and no. of bins') self.IDAGEF = TypeKeyword( 'IDAGEF', (str, ), comment='Age-distribution file name, 20 chars') keyword = TypeKeyword('IDBODY', (int, ), comment='Active body') self.IDBODY = KeywordSequence(keyword) keyword = TypeKeyword('IDKPAR', (int, ), comment='Kind of detected particles') self.IDKPAR = KeywordSequence(keyword) def get_keywords(self): return (self.IMPDET, self.IDSPC, self.IDPSF, self.IDFLNC, self.IDAGEL, self.IDAGEF, self.IDBODY, self.IDKPAR) def set(self, el, eu, nbe, ipsf, idcut, spectrum_filename=None, psf_filename=None, fln_filename=None, agel=None, ageu=None, nage=None, age_filename=None, kb=None, kpar=None): self.IMPDET.set(el, eu, nbe, ipsf, idcut) self.IDSPC.set(spectrum_filename) self.IDPSF.set(psf_filename) self.IDFLNC.set(fln_filename) self.IDAGEL.set(agel, ageu, nage) self.IDAGEF.set(age_filename) self._set_keyword_sequence(self.IDBODY, kb) self._set_keyword_sequence(self.IDKPAR, kpar)
def __init__(self): keyword = TypeKeyword("IFORCE", (int, int, int, int, float, float, float), comment="KL,KC,KPAR,ICOL,FORCER,WLOW,WHIG") super().__init__(keyword)
def __init__(self): keyword = TypeKeyword("EABSB", (int, int, float, float, float), comment="Local EABSB(1:3) in body KL,KC") super().__init__(keyword)
def __init__(self): keyword = TypeKeyword("DSMAX", (int, int, float), comment="Maximum step length in body KL,KC") super().__init__(keyword)
def __init__(self): keyword = TypeKeyword("IPSFN", (str, ), comment="Input psf name, up to 20 characters") super().__init__(keyword)
def __init__(self): keyword = TypeKeyword( "SBODY", (int, ), comment='Active source body; one line for each body') super().__init__(keyword)
def __init__(self): self.IMPDET = TypeKeyword('IMPDET', (float, float, int, int, int), comment='E-window, no. of bins, IPSF, IDCUT') self.IDSPC = TypeKeyword('IDSPC', (str, ), comment='Spectrum file name, 20 chars') self.IDPSF = TypeKeyword('IDPSF', (str, ), comment='Phase-space file name, 20 chars') self.IDFLNC = TypeKeyword( 'IDFLNC', (str, ), comment='Fluence spectrum file name, 20 chars') self.IDAGEL = TypeKeyword('IDAGEL', (float, float, int), comment='Age interval and no. of bins') self.IDAGEF = TypeKeyword( 'IDAGEF', (str, ), comment='Age-distribution file name, 20 chars') keyword = TypeKeyword('IDBODY', (int, ), comment='Active body') self.IDBODY = KeywordSequence(keyword) keyword = TypeKeyword('IDKPAR', (int, ), comment='Kind of detected particles') self.IDKPAR = KeywordSequence(keyword)
def __init__(self): keyword = TypeKeyword('XRLINE', (int, ), comment='X-ray line, IZ*1e6+S1*1e4+S2*1e2') super().__init__(keyword)
def __init__(self): keyword = TypeKeyword("IXRSPL", (int, int, float), comment="KL,KC,splitting factor") super().__init__(keyword)
class PhotonDetectorGroup(KeywordGroup): """ Each detector collects photons that leave the sample with directions within a 'rectangle' on the unit sphere, limited by the 'parallels' THETA1 and THETA2 and the 'meridians' PHI1 and PHI2. The output spectrum is the energy distribution of photons that emerge within the acceptance solid angle of the detector with energies in the interval from EDEL to EDEU, recorded using NCHE channels. Notice that the spectrum is given in absolute units (per incident electron, per eV and per unit solid angle). PDANGL : Starts the definition of a new detector. Up to 25 different detectors can be defined. THETA1,THETA2 and PHI1,PHI2 are the limits of the angular intervals covered by the detector, in degrees. The integer flag IPSF serves to activate the creation of a phase-space file (psf), which contains the state variables and weigths of particles that enter the detector. Use this option with care, because psf's may grow very fast. IPSF=0, the psf is not created. IPSF=1, a psf is created. IPSF>1, a psf is created, but contains only state variables of detected photons that have ILB(4)=IPSF (used for studying angular distributions of x rays). Generating the psf is useful for tuning interaction forcing, which requires knowing the weights of detected particles. DEFAULTS: THETA1=35, THETA2=45, PHI1=0, PHI2=360, IPSF=0 NOTE: PHI1 and PHI2 must be both either in the interval (0,360) or in the interval (-180,180). PDENER : EDEL and EDEU are the lower and upper limits of the energy window covered by the detector. NCHE is the number of energy channels in the output spectrum (.LE. 1000). DEFAULT: EDEL=0.0, EDU=E0, NCHE=1000 XRORIG : This line in the input file activates the generation of a file with the position coordinates of the emission sites of the photons that reach the detector. The file name must be explicitly defined. Notice that the file may grow very fast, so use this option only in short runs. The output file is overwritten when a simulation is resumed. DEFAULT: NONE """ def __init__(self): super().__init__() self.PDANGL = TypeKeyword('PDANGL', (float, float, float, float, int), comment='Angular window, in deg, IPSF') self.PDENER = TypeKeyword('PDENER', (float, float, int), comment='Energy window, no. of channels') self.XRORIG = TypeKeyword( 'XRORIG', (str, ), comment='Map of emission sites of detected x rays') def set(self, theta1, theta2, phi1, phi2, ipsf, edel, edeu, nche, emission_filename=None): self.PDANGL.set(theta1, theta2, phi1, phi2, ipsf) self.PDENER.set(edel, edeu, nche) self.XRORIG.set(emission_filename) def get_keywords(self): return (self.PDANGL, self.PDENER, self.XRORIG)
def __init__(self): keyword = TypeKeyword("PARINP", (int, float), comment="Replacement parameter") super().__init__(keyword)