Langevin C++ source
Loading...
Searching...
No Matches
sim_dplangevin_private.cpp
Go to the documentation of this file.
1
5
6#include "sim_dplangevin.hpp"
7
8// double round_up(const double value, const int n_decimals) {
9// const double multiplier = std::pow(10, 10);
10// const unsigned int int_value
11// = static_cast<unsigned int>((value) * multiplier);
12// const double rounded_value = (static_cast<double>(int_value)) / multiplier;
13// return rounded_value;
14// // return std::round((value+1e-14) * multiplier) / multiplier;
15// }
16
17double round_time(const double time) {
18 const double multiplier = std::pow(10, 15);
19 if (std::abs(time)<std::pow(10, -15)) {
20 return 0.0;
21 }
22 else {
23 return std::round((std::abs(time)*multiplier+0.5))/multiplier;
24 }
25 // const unsigned int int_value
26 // = static_cast<unsigned int>((value) * multiplier);
27 // const double rounded_value = (static_cast<double>(int_value)) / multiplier;
28 // return rounded_value;
29}
30
33{
34 int n_epochs;
35 double t=0;
36 for (n_epochs=0; t<p.t_final; t=round_time(t+p.dt))
37 {
38 n_epochs++;
39 }
40 return n_epochs+1;
41}
42
44{
45 switch (p.integration_method)
46 {
47 case (IntegrationMethod::RUNGE_KUTTA):
49 return true;
50 case (IntegrationMethod::EULER):
52 return true;
53 default:
54 return false;
55 }
56}
57
58bool SimDP::integrate(const int n_next_epochs)
59{
60 // Check a further n_next_epochs won't exceed total permitted steps
61 if (t_epochs.size() < i_next_epoch+n_next_epochs)
62 {
63 std::cout << "Too many epochs: "
64 << t_epochs.size()
65 << " < "
66 << i_next_epoch+n_next_epochs
67 << std::endl;
68 return false;
69 }
70
71 // Perform (possibly another another) n_next_epochs integration steps
72 int i;
73 double t;
74 // For the very first epoch, record mean density right now
75 if (i_next_epoch==1) {
76 dpLangevin->apply_boundary_conditions(p, 0);
77 mean_densities[0] = dpLangevin->get_mean_density();
80 }
81 // Loop over integration steps.
82 // Effectively increment epoch counter and add to Δt to time counter
83 // so that both point the state *after* each integration step is complete.
84 // In so doing, we will record t_epochs.size() + 1 total integration steps.
85 t_epochs[0] = 0;
86 for (
88 i<i_next_epoch+n_next_epochs;
89 t=round_time(t+p.dt), i++
90 )
91 {
92 // Reapply boundary conditions prior to integrating
93 dpLangevin->apply_boundary_conditions(p, i);
94 // Perform a single integration over Δt
96 // Record this epoch
97 t_epochs[i] = t;
98 mean_densities[i] = dpLangevin->get_mean_density();
100 t_current_epoch = t;
101 };
102 // Set epoch and time counters to point to *after* the last integration step
103 i_next_epoch = i;
104 t_next_epoch = t;
105 return true;
106}
107
109{
110 py_array_t epochs_array(n_epochs);
111 auto epochs_proxy = epochs_array.mutable_unchecked();
112 for (auto i=0; i<n_epochs; i++)
113 {
114 epochs_proxy(i) = t_epochs[i];
115 };
116 pyarray_t_epochs = epochs_array;
117 return true;
118}
119
121{
122 py_array_t mean_densities_array(n_epochs);
123 auto mean_densities_proxy = mean_densities_array.mutable_unchecked();
124 for (auto i=0; i<n_epochs; i++)
125 {
126 mean_densities_proxy(i) = mean_densities[i];
127 };
128 pyarray_mean_densities = mean_densities_array;
129 return true;
130}
131
133{
134 if (not (p.n_cells == p.n_x * p.n_y * p.n_z))
135 {
136 std::cout << "prep_density: grid size problem" << std::endl;
137 return false;
138 }
139 // Assume we're working with a <=2d grid for now
140 py_array_t density_array({p.n_x, p.n_y});
141 auto density_proxy = density_array.mutable_unchecked();
142 for (auto i=0; i<p.n_cells; i++)
143 {
144 int x = i % p.n_x;
145 int y = i / p.n_x;
146 density_proxy(x, y) = dpLangevin->get_density_grid_value(i);
147 };
148 pyarray_density = density_array;
149 return true;
150}
void integrate_rungekutta(rng_t &rng)
Runge-Kutta + stochastic integration + grid update.
void integrate_euler(rng_t &rng)
Explicit Euler + stochastic integration + grid update.
int i_current_epoch
Index of current epoch aka time step.
int i_next_epoch
Index of next epoch aka time step.
Parameters p
Model simulation parameters.
py_array_t pyarray_t_epochs
Python-compatible array of epochs time-series.
dbl_vec_t mean_densities
Vector time-series of grid-averaged field density values.
int count_epochs() const
Count upcoming number of epochs by running a dummy time-stepping loop.
bool choose_integrator()
Chooses function implementing either Runge-Kutta or Euler integration methods.
double t_next_epoch
Time of next epoch.
void(DPLangevin::* integrator)(rng_t &)
Integrator: either a Runge-Kutta or an Euler method.
bool pyprep_mean_densities()
Generate a Python-compatible version of the mean densities time-series vector.
int n_epochs
Total number of simulation time steps aka "epochs".
dbl_vec_t t_epochs
Vector time-series of epochs.
py_array_t pyarray_density
Python-compatible array of current density grid.
py_array_t pyarray_mean_densities
Python-compatible array of mean density time-series.
bool pyprep_t_epochs()
Generate a Python-compatible version of the epochs time-series vector.
DPLangevin * dpLangevin
Instance of DP Langevin integrator class (pointer to instance)
bool pyprep_density_grid()
Generate a Python-compatible version of the current density grid.
rng_t * rng
Random number generation function (Mersenne prime) (pointer to RNG)
bool integrate(const int n_next_epochs)
Perform Dornic-type integration of the DP Langevin equation for n_next_epochs
double t_current_epoch
Time of current epoch.
py::array_t< double, py::array::c_style > py_array_t
Type for Python arrays of doubles.
Class that manages simulation of DPLangevin equation.