|
Call Type and Specification Function Name Format in model.dat |
Arguments and Type | Meaning |
Single precision Fortran |
real*4 ear(0:ne) | Energy array |
integer ne | Size of flux array | |
real*4 param(*) | Parameter values (Dimension must be specified inside the function) | |
integer ifl | The spectrum number of model component being calculated | |
real*4 photar(ne) | Output flux array | |
real*4 photer(ne) | Output flux error array (optional) | |
Double precision Fortran |
real*8 ear(0:ne) | Energy array |
integer ne | Size of flux array | |
real*8 param(*) | Parameter values (Dimension must be specified inside the function) | |
integer ifl | The spectrum number of model component being calculated | |
real*8 photar(ne) | Output flux array | |
real*8 photer(ne) | Output flux error array (optional) | |
C and C++ in C style |
const Real* energy | Energy array (size Nflux+1) |
int Nflux | Size of flux array | |
const Real* parameter | Parameter values | |
int spectrum | The spectrum number of model component being calculated | |
Real* flux | Output flux array | |
Real* fluxError | Output flux error array (optional) | |
const char* init | Initialization string (see below) | |
C++ in C++ style |
const RealArray& energy | Energy array |
const RealArray& parameter | Parameter values | |
int spectrum | The spectrum number of model component being calculated | |
RealArray& flux | Output flux array | |
RealArray& fluxError | Output flux error array (optional) | |
const string& init | Initialization string (see below) | |
The second entry in the first column is the way the function name should be included in the model.dat entry. Note that the prefix is only to be included in model.dat - the actual function name in the source code is the base funcName.
For example, a model component in double precision Fortran is specified by:
modelentry 5 0. 1.e20 F_funcName add 0 0XSPEC sees the F_ and picks out the right function definition, calling the Fortran function funcName, which expects double precision arguments. The C-style call can clearly be compiled and implemented by either a C or a C++ compiler. We recommend using the C++ call if the model is written in C++ as it will reduce overhead in copying C arrays in and out the XSPEC internal data structures. To prevent unresolved symbol linkage errors, we also recommend prefacing C++ local model function definitions with the extern “C” directive.
Example C/C++ function definitions:
/* C style */ extern “C” void modelfunc(const Real* energy, int Nflux, const Real* parameter, int spectrum, Real* flux, Real* fluxVariance, const char* init) { /* Model code: Do not allocate memory for flux and fluxVariance arrays. XSPEC's C-function wrapper will allocate arrays prior to calling the function (and will free them afterwards). */ } // C++ style extern “C” void modelfunc(const RealArray& energy, const RealArray& parameter, int spectrum, RealArray& flux, RealArray& fluxVariance, const string& init) { // Model code: Should resize flux RealArray to energy.size()-1. // Do the same for fluxVariance array if calculating errors, otherwise // leave it at size 0. }
Note on type definitions for (C and C++): XSPEC provides a typedef for Real, in the xsTypes.h header file. The distributed code has
typedef double Real;i.e. all calculations are performed in double precision. This is used for C models and C++ models with C-style arguments.
The type RealArray is a dynamic (resizeable) array of type Real. XSPEC uses the std::valarray template class to implement RealArray. The internal details of XSPEC require that the RealArray typedef supports vectorized assignments and mathematical operations, and indirect addressing (see C++ documentation for details). However, we do not recommend using specific features of the std::valarray class, such as array slicing, in case the typedef is changed in future.
The input energies are set by the response matrices of the detectors in use. The parameter ifl / spectrum (for Fortran / C or C++) is an integer which specifies to which response (and therefore which spectrum) these energies correspond. It exists to allow multi-dimensional models where the function might also depend on e.g. pulse-phase in a variable source. The output flux array should not be assumed to have any particular values on input. It is assumed to contain previously calculated values only by convolution/pileup models, which have the nature of operators. The output flux error array allows the function to return model variances.
The C and C++ call types allow one extra argument, which is a character string that can be appended to the top line of the model component description. This string is read on initialization and available to the model during execution. An example of its use might be the name of a file with specific data used in the model calculation: this allows different models to be implemented the same way except for different input data by specifying different names and input strings.
Function utility routines
There are a number of internal XSPEC routines which may be useful for local models written in either C++ or Fortran. These are defined in FunctionUtility.h and xsFortran.cxx, respectively, in the directory Xspec/src/XSFunctions/Utilities. Documentation is available at: https://heasarc.gsfc.nasa.gov/docs/xanadu/xspec/internal/XspecInternalFunctionsGuide.html.
These functions allow the model to find out the Solar abundances in use, get any information defined using the xset command, find the cosmological parameters currently set, get the contents of the XFLT#### keywords in the spectrum files, and load information into an internal database which can be accessed using tclout.
There are also C++ classes and associated methods for equilibrium and non-equilibrium collisional plasmas, photo-electric opacity from neutral and ionized materials, and Compton scattering. Descriptions of these can be found in XSFunctions_guide.pdf in Xspec/src/help.
Multi-dimensional models
Typically, an XSPEC model depends only on the energy (and the model parameters) but more complicated models are sometimes required. The model might depend on energy and, for a variable source, the time at which the spectrum was obtained or, for an extended source, its spatial position. The extra information about the spectrum must be stored in the XFLT#### keywords in the spectrum files. For instance, if the model has a dependence on time then for one spectrum XFLT0001 could be set to “start: 1345.54” and XFLT0002 to “end: 1356.43” and another have XFLT0001 set to “start: 1356.43” and XFLT0002 to “end: 1368.21”. An example C++ routine might then include the code
#include <XSFunctions/Utilities/FunctionUtility.h> ... extern “C” void mymodel(const RealArray& energyArray, const RealArray& params, int spectrum, RealArray& flux, RealArray& fluxVariance, const string& initString) ... Real tstart = FunctionUtility::getXFLT(spectrum,“start”); Real tend = FunctionUtility::getXFLT(spectrum,“end”); ...
Third-Party Libraries In Local Models Build
The Makefile that initpackage creates for building your local models library is based on the template file
heasoft-[ver]/Xspec/src/tools/initpackage/xspackage.tmplIf you need to add a path to a third-party library's header files, add:
-I/path/to/your/3rdParty/library/includeto the HD_CXXFLAGS setting. Then type hmake and hmake install from the
heasoft-[ver]/Xspec/src/tools/initpackagedirectory.
To make sure the linker pulls in the library on Mac OS X further edit the xspackage.tmpl file by adding a “-l” flag for the library (e.g. -lgsl) in the HD_SHLIB_LIBS settings. Then reinstall xspackage.tmpl as mentioned above. On Linux/Unix the XSPEC executable itself should be relinked with the new library included. So, edit the file
heasoft-[ver]/Xspec/src/main/Makefileby adding a “-l” flag for the library to the HD_CXXLIBS setting. Then from the same directory do:
rm xspec hmake local hmake publish hmake installAfter these modifications, you should be able to use initpackage and lmod in the normal way to build and load your local models library.
Writing new mixing models
Mixing models are fundamentally different from the other kinds of models since they apply a transformation to a set of modeled fluxes (as enumerated by the spectra in the fit), rather than modify the flux designed to fit a single spectrum. The need to store temporary results, as well as the requirements of the model calculation, lead to many workspace arrays: further, the transformations applied are often fixed during a fit, or can be split to avoid redundant calculations into parts that are fixed and parts that change during iteration in order. XSPEC's internal organization (data structures) can be mapped straightforwardly to the requirements of these models so to implement them efficiently and handle memory allocation, we recommend that mixing models be written in C++ or C. At present only a C++ implementation is available.
Mixing models are listed in a mixmodel.dat file in the src/manager directory. This is similar to the standard model.dat file except that the class required to run the model is preceded by U_. If a template function is used to run multiple models (e.g. U_Psf) then the template value is added (e.g. U_psf<XMM>). Finally, if other header classes are required to build the models then their names should be included in parentheses. For instance the clmass model requires Potential.h and Potential.cxx so this is indicated by U_MIClusterMassModel(Potential).
The mixing model class requires a constructor taking a single argument:
ModelClassName (const string& name);and three public methods
void initialize (const std::vector<Real>& params, const IntegerVector& specNums, const std::string& modelName); void perform (const EnergyPointer& energy, const std::vector<Real>& params, GroupFluxContainer& flux, GroupFluxContainer& fluxVariance); void initializeForFit (const std::vector<Real>& params, bool paramsAreFrozen);where initialize is run the first time the model is called, initializeForFit at the start of any fit command, and perform for each model calculation.
The MixUtility class from which all these mixing model classes inherit contains a number of members and methods which can make writing mixing models easier. If the following arrays are set then the doMix method does all the hard work and just needs to be called from perform.
// sets of spectrum numbers to be mixed together. each set is in the order // of the mixing matrix std::vector<IntegerVector> m_specNumsMixSets; // mixing factors NxNxNe. note that the outer vector is the spectrum number // of the output and the inner vector is the spectrum number of the input std::vector<std::vector<RealArray> > m_mixingFactors; // energies if the mixing factors are energy-dependent. this must be the same // size as the RealArray in m_mixingFactors RealArray m_mixingEnergies;
The useful MixUtility methods are:
// do all the hard work to mix the models void doMix(const EnergyPointer& energy, GroupFluxContainer& flux); // return the total number of data groups size_t numberOfDataGroups() const; // return the total number of spectra size_t numberOfSpectra() const; // return true if there is valid data, false if not bool isAnyData() const; // return the datagroup number (1-based) for the spectrum (1-based) size_t dataGroupNumber(const size_t spectrumNumber) const; // return a map of all the xflt names and values for the spectrum std::map<string, Real> allXfltValues(const size_t spectrumNumber) const; // return the value for the input xflt name and spectrum Real xfltValue(const size_t spectrumNumber, const string xfltName) const; // return the value for the input xflt number and spectrum Real xfltValue(const size_t spectrumNumber, const int xfltNumber) const; // return true if the intput xflt name exists in the spectrum bool isInXflt(const size_t spectrumNumber, const string xfltName) const; // return true if the intput xflt number exists in the spectrum bool isInXflt(const size_t spectrumNumber, const int xfltNumber) const; // return the name of the spectrum (1-based) string dataName(const size_t spectrumNumber) const; // return the complete pathname of the spectrum (1-based) string fullPathName(const size_t spectrumNumber) const; // return the source number (1-based) for this model size_t sourceNumber() const; // return the data group map for this source number const std::map<size_t, size_t>& sourceToDataGroups( const size_t sourceNumber) const; // return true if the spectrum is active for the source number bool isSpectrumActive(const size_t spectrumNumber, const size_t sourceNumber) const; // return the response name for the spectrum and source number string rmfName(const size_t spectrumNumber, const size_t sourceNumber) const; // return the EnergyPointer object for this model EnergyPointer allEnergies();
Users considering adding new mixing model types should contact the developers of XSPEC at xspec12@athena.gsfc.nasa.gov.
HEASARC Home | Observatories | Archive | Calibration | Software | Tools | Students/Teachers/Public
Last modified: Friday, 23-Aug-2024 14:07:29 EDT