libpspm is a C++ library to simulate Physiologically Structured Population Models (PSPMs).
It implements four numerical methods to discretize the McKendrick-von Foerster Partial Differential Equation (PDE), which forms the core of a PSPM, into a set of Ordinary Differential Equations (ODEs); see Zhang et al. 2017:
- Fixed Mesh Upwind (FMU)
- Implicit Fixed Mesh Upwind (IFMU)
- Escalator Boxcar Train (EBT)
- Characteristic Method (CM)
The resulting ODEs can be solved using different ODE-solvers. Two such are currently implemented:
- Runge-Kutta 4-5 Cash-Karp
- LSODA
libpspm supports multi-species systems with multiple size-structured and unstructured species.
Installation
To compile as a static library, just perform
make
make check
This will create a static library (libpspm.a
) in the
lib
folder. Link to this library as -lpspm
while compiling your program.
Alternatively, just include the contents of the src
and
include
folders in your respective project folders, compile
each cpp
file into an object file, and link with the
objects of your project.
Development version
Latest development version can be found here: https://github.com/jaideep777/pspm/tree/develop
Usage
To solve a PSPM, you need to define two classes for the
Environment
and the Individual
(not
necessarily with those names). The Environment
class must
be derived from the EnvironmentBase
class provided by the
library. Although the Individual
class can be defined as a
standalone class, the easiest way to define it is also to derive it from
the IndividualBase
class provided by the library. In these
derived classes you must implement the following member functions (one
in Environment
and four in Individual
):
class Environment : public EnvironmentBase{
public:
// This function should perform environment computation, given the current state
void computeEnv(double t, Solver * S, std::vector<double>::iterator s, std::vector<double>::iterator dsdt){
}
};
class Individual : public IndividualBase{
public:
// return the initial density (initial condition) as a function of
// the physiological variable x, environment _env, and input flux of newborns bf
double init_density(double x, void * _env, double bf){
}
// return the growth rate as a function of
// the physiological variable x, time t, and environment _env
double growthRate(double x, double t, void * _env){
}
// return the mortality rate as a function of
// the physiological variable x, time t, and environment _env
double mortalityRate(double x, double t, void * _env){
}
// return the fecundity (birth rate) as a function of
// the physiological variable x, time t, and environment _env
double birthRate(double x, double t, void * _env){
}
};
Having defined these classes, create an Environment
object and a species of Individual
s as follows:
;
Environment E<Individual> spp; Species
Then create a Solver
by specifying the PSPM method and
the ODE solver, e.g.,
(SOLVER_FMU, "rk45ck"); Solver S
Add the species and the environment to the solver:
// add the created Species 'spp' to the solver along with some species-specific properties
.addSpecies(25, xb, xm, false, &spp, 0, -1);
S.setEnvironment(&E); S
Initialize and run the PSPM:
.resetState();
S.initialize();
Sfor (double t=0; t < 10; t=t+1) {
.step_to(t);
S}
Concrete examples can be found in the demos
folder. For
more detailed tutorials explaining the demos, see:
- Daphnia model -
- RED model -
Author and contact
Jaideep Joshi joshi@iiasa.ac.at