libpspm
fmu.cpp
Go to the documentation of this file.
1 #include <cassert>
2 #include "solver.h"
3 using namespace std;
4 
5 // ~~~~~~~~~~~ FMU Solver ~~~~~~~~~~~
6 double phi(double r){
7  return max(max(0.0,min(2*r,1.0)),min(r,2.0));
8 }
9 
10 
11 void Solver::calcRates_FMU(double t, vector<double>::iterator S, vector<double>::iterator dSdt){
12 
13  vector<double>::iterator its = S + n_statevars_system; // Skip system variables
14  vector<double>::iterator itr = dSdt + n_statevars_system;
15 
16  for (int s = 0; s<species_vec.size(); ++s){
17  Species_Base* spp = species_vec[s];
18 
19  // [S S S u u u u u a b c a b c a b c a b c a b c] <--- full SV for species is this
20  // ^ its, itr
21  double *U = &(*its); // Since FMU only has U in state, start of species is actually U
22  double *dUdt = &(*itr);
23  int J = spp->J; // xsize of species.
24  vector<double> &x = spp->x;
25  vector<double> &X = spp->X;
26  vector<double> &h = spp->h;
27 
28  vector <double> growthArray(J+1);
29  growthArray[0] = spp->growthRate(-1, x[0], t, env); // growth rate of boundary cohort
30  for (int i=1; i<J+1; ++i) growthArray[i] = spp->growthRateOffset(i-1, x[i], t, env);
31 
32  vector <double> u(J+1);
33 
34  // i=0
35  double pe = spp->establishmentProbability(t, env);
36  if (spp->birth_flux_in < 0){
37  double birthFlux = calcSpeciesBirthFlux(s,t) * pe;
38  u[0] = birthFlux/(growthArray[0]+1e-12); // Q: is this correct? or g(X0,env)? - A: It is g(xb,env) - growthArray[] indexes x, so (0) is xb. Hence correct.
39  }
40  else{
41  u[0] = spp->calc_boundary_u(growthArray[0], pe);
42  }
43 
44  // i=1 (calc u1 assuming linear u(x) in first interval)
45  u[1] = 2*U[0]-u[0]; // NOTE: for g(x) < 0 this can be calculated with upwind scheme
46 
47  for (int i=2; i<J-1; ++i){ // dU[i] ~ u[i+1] <-- U[i],U[i-1], u[i] <-- U[i-1],U[i-2]
48  if(growthArray[i] >=0){
49  double rMinus = ((U[i]-U[i-1])/(x[i]-x[i-1]))/((U[i-1]-U[i-2]+1e-12)/(x[i-1]-x[i-2]));
50  u[i] = U[i-1] + phi(rMinus)*(U[i-1]-U[i-2])*(x[i]-x[i-1])/(x[i+1]-x[i-1]);
51  }
52  else{
53  double rPlus = ((U[i]-U[i-1])/(x[i]-x[i-1]))/((U[i+1]-U[i]+1e-12)/(x[i+1]-x[i]));
54  u[i] = U[i] - phi(rPlus)*(U[i+1]-U[i])*(x[i+1]-x[i])/(x[i+2]-x[i]);
55  }
56  }
57 
58  u[J-1] = 2*U[J-2] - u[J-2]; // NOTE: for g(x) > 0 This can be calc with upwind scheme
59  u[J] = 2*U[J-1] - u[J-1];
60 
61  // [S S S u u u u u a b c a b c a b c a b c a b c] <--- full SV for species is this
62  // ^ itr, its. Therefore, advance 1 at a time while setting dUdt, and advance its by 3*5 after.
63  for (int i=0; i<spp->J; ++i){ // dU[i] ~ u[i+1] <-- U[i],U[i-1], u[i] <-- U[i-1],U[i-2]
64  dUdt[i] = -spp->mortalityRate(i,X[i], t, env)*U[i] - (growthArray[i+1]*u[i+1] - growthArray[i]*u[i])/h[i];
65  ++itr; ++its;
66  }
67  if (spp->n_extra_statevars > 0){
68  auto itr_prev = itr;
69  spp->getExtraRates(itr);
70  assert(distance(itr_prev, itr) == spp->n_extra_statevars*spp->J);
71  its += spp->n_extra_statevars*spp->J;
72  }
73 
74 
75  }
76 }
77 
78 
79 
virtual double growthRate(int i, double x, double t, void *env)=0
double phi(double r)
Definition: fmu.cpp:6
void calcRates_FMU(double t, std::vector< double >::iterator S, std::vector< double >::iterator dSdt)
Definition: fmu.cpp:11
std::vector< double > h
Definition: species.h:30
STL namespace.
int n_extra_statevars
Definition: species.h:21
virtual void getExtraRates(std::vector< double >::iterator &it)=0
virtual double establishmentProbability(double t, void *env)=0
virtual double growthRateOffset(int i, double x, double t, void *env)=0
std::vector< double > x
Definition: species.h:29
virtual double mortalityRate(int i, double x, double t, void *env)=0
double birth_flux_in
Definition: species.h:34
virtual double calc_boundary_u(double gb, double pe)=0
std::vector< double > X
Definition: species.h:28