A point source is a special case of an isotropic source . Due to its simplicity, it provides a good example for discussing the implementation of a new source class.
The point source header file egs_point_source.h
includes the base source header file, the header file of the EGS_Vector class to gain access to the methods manipulating 3D vectors, and the random number generator (RNG) header file to get access to the declaration of the various RNG methods needed to sample particles
EGS_BaseSource class header file.
EGS_RandomGenerator class header file.
EGS_Vector methods for the manipulation of 3D vectors in cartesian co-ordinates.
It then defines a macro EGS_POINT_SOURCE_EXPORT
that will be used to mark DSO symbols as exports when building the point source DSO and as imports when linking against the DSO:
#ifdef WIN32
#ifdef BUILD_POINT_SOURCE_DLL
#define EGS_POINT_SOURCE_EXPORT __declspec(dllexport)
#else
#define EGS_POINT_SOURCE_EXPORT __declspec(dllimport)
#endif
#define EGS_POINT_SOURCE_LOCAL
#else
#ifdef HAVE_VISIBILITY
#define EGS_POINT_SOURCE_EXPORT __attribute__ ((visibility ("default")))
#define EGS_POINT_SOURCE_LOCAL __attribute__ ((visibility ("hidden")))
#else
#define EGS_POINT_SOURCE_EXPORT
#define EGS_POINT_SOURCE_LOCAL
#endif
#endif
We derive the point source class from EGS_BaseSimpleSource instead of EGS_BaseSource because a point source is a "simple" source (i.e consists of a spectrum and an energy-independent probability distribution for position and direction):
bool valid;
public:
Base class for 'simple' particle sources.
A class representing 3D vectors.
The private variables xo
(point source position) and valid
will be set in the constructors (see below). We provide two methods for constructing a point source: directly by passing a charge, a spectrum, a source position and a name to the constructor,
setUp();
};
Base class for energy spectra. All energy spectra in the EGSnrc C++ class library are derived from th...
and from the information provided by an EGS_Input object
The implementation of the second constructor is in the .cpp file and will be discussed below.
The main method that must be implemented in a derived simple source class is getPositionDirection() to sample the position and direction of a single particle and to set its statistical weight
Base random number generator class. All random number generators should be derived from this class.
Sampling the particle position for a point source is easy: it is simply the point source position
Sampling the direction is also easy: one samples
uniformely between -1 and 1, picks a random azimuthal angle
between 0 and
and sets
:
EGS_Float sinz = 1-u.z*u.z;
sinz = sqrt(sinz);
EGS_Float cphi, sphi;
u.x = sinz*cphi;
u.y = sinz*sphi;
}
else {
void getAzimuth(EGS_Float &cphi, EGS_Float &sphi)
Sets cphi and sphi to the cosine and sine of a random angle uniformely distributed between 0 and .
EGS_Float getUniform()
Returns a random number uniformly distributed between zero (inclusive) and 1 (exclusive).
const EGS_Float epsilon
The epsilon constant for floating point comparisons.
The statistical weight of the particle is always unity
u.x = 0;
u.y = 0;
}
wt = 1;
};
The next function to implement is getFluence
(), which should return the particle "fluence" emitted so far by the source. We arbitrarily decide to define the "fluence" of our point source to be the number of particles emitted by the source (we also could have picked the number of particles per unit solid angle or real fluence at a certain distance from the source) and therefore the getFluence
() implementation is very easy:
EGS_Float getFluence() const {
return count;
};
Here, count
is a protected data member inhereted from EGS_BaseSimpleSource, which is initialized to zero in the simple source constructor and is incremented by one in each invocation of the getNextParticle() function.
The next task is to implement the functions that store the state of a point source object to a data stream and restore the state from a data stream. This is needed for the ability to restart simulations. Because our source class is very simple, no data needs to be stored/restored in addition to the data already stored/restored by EGS_BaseSource and EGS_BaseSimpleSource. The implementation of these functions is therefore extremely simple:
bool storeFluenceState(ostream &) const {
return true;
};
bool setFluenceState(istream &) {
The next step in the header file is to provide a isValid
function, which should return true
, if the source object is valid and false
otherwise (e.g. it does not have a spectrum). isValid
() is needed so that the createSource
() function that must be provided by the source DSO (see below) can be implemented by simply using the template createSourceTemplate():
return true;
};
bool isValid() const {
The final step in the point source declaration is to specify a protected function that will be used to set up the source type and description
return (valid && s != 0);
};
The egs_point_source.cpp
file provides implementation of the constructor that creates a point source object from information stored in an EGS_Input object, the setUp
() function and the C-style source creation function createSource
() that must be provided by each source DSO. It includes the point source header file and the input object header file
The point source constructor calls the base simple source constructor passing the input as argument
EGS_PointSource(int Q, EGS_BaseSpectrum *Spec, const EGS_Vector &Xo, const string &Name="", EGS_ObjectFactory *f=0)
Constructor.
This sets the name of the source from the name
key, sets the charge from a charge
key and constructs the spectrum from the information in a spectrum
composite property using EGS_BaseSpectrum::createSpectrum(). The only task remaining for a complete point source definition is to determine the position of the source:
vector<EGS_Float> pos;
int err = input->
getInput(
"position",pos);
The position was successfully set if err=0
and the number of inputs to the position
key is exactly 3 (defining a 3D position), otherwise a warning is issued and the source is set to be invalid:
if (!err && pos.size() == 3) {
}
The source type and description is then set using setUp
().
else {
egsWarning(
"EGS_PointSource: missing/wrong 'position' input\n");
valid = false;
}
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.
The implementation of the setUp
function sets the type string to "EGS_PointSource" and the description string to a short sentence constructed from the charge and spectrum type:
setUp();
}
otype =
"EGS_PointSource";
if (!isValid()) {
}
string description
A short source description.
string otype
The object type.
void setUp()
Sets up the source type and description.
The createSource
C-style function implementation simply uses the createSourceTemplate() function:
else {
description = "Point source with ";
description += s->getType();
if (q == -1) {
description += ", electrons";
}
else if (q == 0) {
description += ", photons";
}
The conditions for being able to use createSourceTemplate() to construct a source are
- The source provides a constructor that takes pointers to an EGS_Input object and an object factory as arguments
- The source provides a
isValid
() function returning a boolean value.
This completes the implementation of our point source class.
The Makefile is very similar to the Makefile of a geometry DSO (see e.g. this example): we include the egspp config setting for the make system,
include $(EGS_CONFIG)
include $(SPEC_DIR)egspp.spec
include $(SPEC_DIR)egspp_$(my_machine).conf
set the pre-processor defines to include the BUILD_POINT_SOURCE_DLL
macro,
DEFS = $(DEF1) -DBUILD_POINT_SOURCE_DLL
define the DSO name and files needed to build the DSO,
library = egs_point_source
lib_files = egs_point_source
set the dependences to be set of header files common for all sources,
my_deps = $(common_source_deps)
extra_dep = $(addprefix $(DSOLIBS), $(my_deps))
include the rules for building a DSO,
include $(SPEC_DIR)egspp_libs.spec
and make the dependences take effect
We can now build our point source DSO by typing make
and use it for simulations by including input such as
:start source:
library = egs_points_source
name = some_name
charge = -1
:start spectrum:
definition of a spectrum
:stop spectrum:
position = 15 -3 7
:stop source:
in the source definition section of the input file.
This is the complete Makefile:
###############################################################################
#
# EGSnrc egs++ makefile to build point source
# Copyright (C) 2015 National Research Council Canada
#
# This file is part of EGSnrc.
#
# EGSnrc is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# EGSnrc is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
# more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with EGSnrc. If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
#
# Author: Iwan Kawrakow, 2005
#
# Contributors:
#
###############################################################################
include $(EGS_CONFIG)
include $(SPEC_DIR)egspp.spec
include $(SPEC_DIR)egspp_$(my_machine).conf
DEFS = $(DEF1) -DBUILD_POINT_SOURCE_DLL
library = egs_point_source
lib_files = egs_point_source
my_deps = $(common_source_deps)
extra_dep = $(addprefix $(DSOLIBS), $(my_deps))
include $(SPEC_DIR)egspp_libs.spec
$(make_depend)
This is the complete header file:
#ifndef EGS_POINT_SOURCE_
#define EGS_POINT_SOURCE_
#ifdef WIN32
#ifdef BUILD_POINT_SOURCE_DLL
#define EGS_POINT_SOURCE_EXPORT __declspec(dllexport)
#else
#define EGS_POINT_SOURCE_EXPORT __declspec(dllimport)
#endif
#define EGS_POINT_SOURCE_LOCAL
#else
#ifdef HAVE_VISIBILITY
#define EGS_POINT_SOURCE_EXPORT __attribute__ ((visibility ("default")))
#define EGS_POINT_SOURCE_LOCAL __attribute__ ((visibility ("hidden")))
#else
#define EGS_POINT_SOURCE_EXPORT
#define EGS_POINT_SOURCE_LOCAL
#endif
#endif
bool valid;
public:
setUp();
};
x = xo;
EGS_Float sinz = 1-u.
z*u.
z;
sinz = sqrt(sinz);
EGS_Float cphi, sphi;
}
else {
}
wt = 1;
};
};
return true;
};
return true;
};
return (valid && s != 0);
};
protected:
void setUp();
};
#endif
EGS_BaseSimpleSource(int Q, EGS_BaseSpectrum *Spec, const string &Name="", EGS_ObjectFactory *f=0)
Constructor.
virtual void getPositionDirection(EGS_RandomGenerator *rndm, EGS_Vector &x, EGS_Vector &u, EGS_Float &wt)=0
Sample a particle position and direction.
virtual bool isValid() const
Is this a valid source?
virtual bool storeFluenceState(ostream &data_out) const
Store the fluence state of this source to the data stream data_out.
virtual bool setFluenceState(istream &data)
Set the data related to the sampling of positions and directions to a state contained in the stream d...
EGS_I64 count
Number of statistically independent particles delivered so far.
virtual EGS_Float getFluence() const =0
Return the fluence this source has emitted so far.
This is the complete source file:
vector<EGS_Float> pos;
int err = input->
getInput(
"position",pos);
if (!err && pos.size() == 3) {
}
else {
egsWarning(
"EGS_PointSource: missing/wrong 'position' input\n");
valid = false;
}
setUp();
}
otype =
"EGS_PointSource";
if (!isValid()) {
}
else {
}
}
}
else {
}
}
}
extern "C" {
return createSourceTemplate<EGS_PointSource>(input,f,"point source");
}
}
int q
The charge of this simple source.
EGS_BaseSpectrum * s
The energy spectrum of this source.
Base source class. All particle sources must be derived from this class.
const string & getType() const
Get the spectrum type.