libpspm
size_integrals.tpp
Go to the documentation of this file.
1 
32 
33 // _xm
34 // Calculate _/ w(z,t)u(z)dz
35 // xlow
36 // implementation from orig plant model
37 // ----
38 // I += (x_hi - x_lo) * (f_hi + f_lo);
39 // x_hi = x_lo;
40 // f_hi = f_lo;
41 // if (x_lo < xlow) break;
42 // ----
43 template<typename wFunc>
44 double Solver::integrate_wudx_above(wFunc w, double t, double xlow, int species_id){
45 
46  Species_Base* spp = species_vec[species_id];
47 
48  // cohorts are inserted at the end, hence sorted in descending order
49  // FIXME: should there be an optional "sort_cohorts" control parameter? Maybe some freak models are such that cohorts dont remain in sorted order?
50  if (method == SOLVER_CM){
51  // integrate using trapezoidal rule
52  // Note, new cohorts are inserted at the end, so x will be descending
53  bool integration_completed = false;
54  double I = 0;
55  double u_hi = spp->getU(0);
56  double x_hi = spp->getX(0);
57  double f_hi = w(0, t)*u_hi;
58 
59  for (int i=1; i<spp->J; ++i){ // going from high ----> low
60  double u_lo = spp->getU(i);
61  double x_lo = spp->getX(i);
62  double f_lo = w(i, t)*u_lo;
63 
64  if (x_lo <= xlow){ // check if xlow falls within the current interval.
65  // * if interpolation is on, stop exactly at xlow, else take the full interval
66  double f = (control.integral_interpolate)? f_lo + (f_hi-f_lo)/(x_hi-x_lo)*(xlow - x_lo) : f_lo;
67  double x = (control.integral_interpolate)? xlow : x_lo;
68  I += (x_hi - x) * (f_hi + f);
69  integration_completed = true;
70  }
71  else{
72  I += (x_hi - x_lo) * (f_hi + f_lo);
73  }
74 
75  x_hi = x_lo;
76  f_hi = f_lo;
77  if (integration_completed) break;
78  }
79 
80  //if (integration_completed) assert(x_hi < xlow);
81  //if (!integration_completed) assert(x_hi >= xlow || spp.J == 1);
82 
83  // if integration has not completed, continue to the boundary interval
84  if (spp->J == 1 || !integration_completed){
85  // boundary at xb
86  double u0 = spp->get_boundary_u();
87  double x_lo = spp->xb;
88  if (x_hi > x_lo){
89  double f_lo = w(-1, t)*u0; // -1 is boundary cohort
90  double f = (control.integral_interpolate)? f_lo + (f_hi-f_lo)/(x_hi-x_lo)*(xlow - x_lo) : f_lo;
91  double x = (control.integral_interpolate)? xlow : x_lo;
92  I += (x_hi-x)*(f_hi+f);
93  }
94  }
95 
96  return I*0.5;
97  }
98 
99  else if (method == SOLVER_FMU || method == SOLVER_IFMU){
100  //if (xlow < spp->xb) throw std::runtime_error("integral lower bound must be >= xb");
101  if (xlow > spp->x[spp->J]) return 0; // if xlow is above the maximum size, integral is 0
102 
103  // integrate using midpoint quadrature rule
104  double I=0;
105  for (int i=spp->J-1; i>=0; --i){ // in FMU, cohorts are sorted ascending
106  if (spp->x[i] <= xlow){ // check if last interval is reached
107  double h = (control.integral_interpolate)? spp->x[i+1]-xlow : spp->h[i];
108  I += h * w(i,t) * spp->getU(i);
109  break;
110  }
111  else{
112  I += spp->h[i] * w(i,t) * spp->getU(i);
113  }
114  }
115 
116  return I;
117  }
118 
119  else if (method == SOLVER_EBT){
120  // set up cohorts to integrate
121  // backup pi0, N0 from last (youngest) cohort <-- cohorts are sorted descending
122  double pi0 = spp->getX(spp->J-1);
123  double N0 = spp->getU(spp->J-1);
124 
125  // real-ize pi0-cohort with actual x0 value
126  double x0 = spp->xb + pi0/(N0+1e-12);
127  spp->setX(spp->J-1, x0);
128 
129  // calculate integral
130  double I = 0;
131  for (int i=0; i<spp->J; ++i){ // in EBT, cohorts are sorted descending
132  if (spp->getX(i) < xlow) break; // if X == xlow, we still include it in the intgral
133  else I += w(i, t)*spp->getU(i);
134  }
135 
136  // restore the original pi0-cohort
137  spp->setX(spp->J-1, pi0);
138 
139  return I;
140  }
141 
142  else{
143  throw std::runtime_error("Unsupported solver method");
144  }
145 }
146 
147 
148 
149 
150 
151 // _xm
152 // Calculate _/ w(z,t)u(z,t)dz
153 // xb
154 // This will eventually be replaced with a call to integrate_wudx_above
155 template<typename wFunc>
156 double Solver::integrate_x(wFunc w, double t, int species_id){
157  Species_Base* spp = species_vec[species_id];
158 
159  if (method == SOLVER_FMU || method == SOLVER_IFMU){
160  // integrate using midpoint quadrature rule
161  double I=0;
162  for (unsigned int i=0; i<spp->J; ++i){
163  I += spp->h[i]*w(i, t)*spp->getU(i); // TODO: Replace with std::transform after profiling
164  }
165  return I;
166  }
167 
168  else if (method == SOLVER_EBT){
169  // integrate using EBT rule (sum over cohorts)
170 
171  // backup pi0, N0 from last cohort
172  double pi0 = spp->getX(spp->J-1);
173  double N0 = spp->getU(spp->J-1);
174 
175  // real-ize pi0-cohort with actual x0 value
176  double x0 = spp->xb + pi0/(N0+1e-12);
177  spp->setX(spp->J-1, x0);
178 
179  // calculate integral
180  double I = 0;
181  for (int i=0; i<spp->J; ++i) I += w(i, t)*spp->getU(i);
182 
183  // restore the original pi0-cohort
184  spp->setX(spp->J-1, pi0);
185 
186  return I;
187  }
188 
189  if (method == SOLVER_CM){
190  // integrate using trapezoidal rule
191  // Note, new cohorts are inserted at the beginning, so x will be ascending
192  double I = 0;
193  double u_hi = spp->getU(0);
194  double x_hi = spp->getX(0);
195  double f_hi = w(0, t)*u_hi;
196 
197  for (int i=1; i<spp->J; ++i){
198  double u_lo = spp->getU(i);
199  double x_lo = spp->getX(i);
200  double f_lo = w(i, t)*u_lo;
201 
202  I += (x_hi - x_lo) * (f_hi + f_lo);
203  x_hi = x_lo;
204  f_hi = f_lo;
205  }
206 
207  // boundary at xb
208  double u0 = spp->get_boundary_u();
209  double x_lo = spp->xb;
210  double f_lo = w(-1, t)*u0; // -1 is boundary cohort
211  I += (x_hi-x_lo)*(f_hi+f_lo);
212 
213  return I*0.5;
214  }
215 
216  else{
217  throw std::runtime_error("Unsupported solver method");
218  }
219 }
220 
221 
virtual double get_boundary_u()=0
std::vector< double > h
Definition: species.h:30
virtual double getU(int i)=0
virtual double getX(int i)=0
double integrate_wudx_above(wFunc w, double t, double xlow, int species_id)
Computes the partial integral for the specified species.
double integrate_x(wFunc w, double t, int species_id)
Computes the integral for the specified species. For details, see integrate_wudx_above.
std::vector< double > x
Definition: species.h:29
PSPM_SolverType method
Definition: solver.h:17
double xb
Definition: species.h:41
std::vector< Species_Base * > species_vec
Definition: solver.h:31
virtual void setX(int i, double _x)=0
struct Solver::@1 control