BioDynaMo  v1.05.119-a4ff3934
diffusion_grid.cc
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------
2 //
3 // Copyright (C) 2021 CERN & University of Surrey for the benefit of the
4 // BioDynaMo collaboration. All Rights Reserved.
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 //
9 // See the LICENSE file distributed with this work for details.
10 // See the NOTICE file distributed with this work for additional information
11 // regarding copyright ownership.
12 //
13 // -----------------------------------------------------------------------------
14 
15 #include <algorithm>
16 #include <mutex>
17 
20 #include "core/simulation.h"
21 #include "core/util/log.h"
22 
23 namespace bdm {
24 
26 std::string BoundaryTypeToString(const BoundaryConditionType& type) {
27  switch (type) {
29  return "Neumann";
31  return "open";
33  return "closed";
35  return "Dirichlet";
37  return "Periodic";
38  default:
39  return "unknown";
40  }
41 }
42 
44 BoundaryConditionType StringToBoundaryType(const std::string& type) {
45  if (type == "Neumann") {
47  } else if (type == "open") {
49  } else if (type == "closed") {
51  } else if (type == "Dirichlet") {
53  } else if (type == "Periodic") {
55  } else {
56  Log::Fatal("StringToBoundaryType", "Unknown boundary type: ", type);
58  }
59 }
60 
62  const std::string& substance_name, real_t dc,
63  real_t mu, int resolution)
64  : dc_({{1 - dc, dc / 6, dc / 6, dc / 6, dc / 6, dc / 6, dc / 6}}),
65  mu_(mu),
66  resolution_(resolution),
67  boundary_condition_(std::make_unique<ConstantBoundaryCondition>(0.0)) {
68  // Compatibility with new abstract interface
69  SetContinuumId(substance_id);
70  SetContinuumName(substance_name);
71 
72  // Get the default boundary type (set via parameter file)
73  auto* param = Simulation::GetActive()->GetParam();
74  bc_type_ = StringToBoundaryType(param->diffusion_boundary_condition);
75 }
76 
78  if (resolution_ == 0) {
79  Log::Fatal("DiffusionGrid::Initialize",
80  "Resolution cannot be zero. (substance '", GetContinuumName(),
81  "')");
82  }
83 
84  // Get neighbor grid dimensions
85  auto* env = Simulation::GetActive()->GetEnvironment();
86  auto bounds = env->GetDimensionThresholds();
87 
88  grid_dimensions_ = {bounds[0], bounds[1]};
89  if (bounds[0] > bounds[1]) {
90  Log::Fatal("DiffusionGrid::Initialize",
91  "The grid dimensions are not correct. Lower bound is greater",
92  " than upper bound. (substance '", GetContinuumName(), "')");
93  }
94 
95  auto adjusted_res =
96  resolution_ == 1 ? 2 : resolution_; // avoid division by 0
98  static_cast<real_t>(adjusted_res);
99 
100  // Check if box length is not too small
101  if (box_length_ <= 1e-13) {
102  Log::Fatal("DiffusionGrid::Initialize",
103  "The box length was found to be (close to) zero. Please check "
104  "the parameters for substance '",
105  GetContinuumName(), "'");
106  }
107 
109  parity_ = resolution_ % 2;
111 
112  // Allocate memory for the concentration and gradient arrays
113  locks_.resize(total_num_boxes_);
117 
118  // Print Info
119  initialized_ = true;
121  PrintInfo();
122  }
123 }
124 
126  // check if diffusion coefficient and decay constant are 0
127  // i.e. if we don't need to calculate diffusion update
128  if (IsFixedSubstance()) {
129  return;
130  }
131 
132  // Note down last timestep
133  last_dt_ = dt;
134  // Set timestep for this iteration.
135  ParametersCheck(dt);
136 
137  auto* param = Simulation::GetActive()->GetParam();
145  DiffuseWithNeumann(dt);
148  } else {
149  Log::Error(
150  "EulerGrid::Diffuse", "Boundary condition of type '",
151  param->diffusion_boundary_condition,
152  "' is not implemented. Defaulting to 'closed' boundary condition");
153  }
154 }
155 
157  // Get neighbor grid dimensions
158  auto* env = Simulation::GetActive()->GetEnvironment();
159  auto bounds = env->GetDimensionThresholds();
160  // Update the grid dimensions such that each dimension ranges from
161  // {bounds[0] - bounds[1]}
162  grid_dimensions_ = {bounds[0], bounds[1]};
163 
164  // If the grid is not perfectly divisible along each dimension by the
165  // box length, extend the grid so that it is
166  int dimension_length = bounds[1] - bounds[0];
167  for (int i = 0; i < 1; i++) {
168  int r = fmod(dimension_length, box_length_);
169  if (r > 1e-9) {
170  // std::abs for the case that box_length_ > dimension_length
171  grid_dimensions_[2 * i + 1] += (box_length_ - r);
172  }
173  }
174 
175  // Calculate new_dimension_length and new_resolution
176  int new_dimension_length = grid_dimensions_[1] - grid_dimensions_[0];
177  size_t new_resolution = std::ceil(new_dimension_length / box_length_);
178 
179  if (new_resolution > resolution_) {
180  // Store the old number of boxes along each axis for comparison
181  size_t tmp_resolution = resolution_;
182 
183  // Set new resolution
184  resolution_ = new_resolution;
185 
186  // We need to maintain the parity of the number of boxes along each
187  // dimension, otherwise copying of the substances to the increases grid
188  // will not be symmetrically done; resulting in shifting of boxes
189  // We add a box in the negative direction, because the only way the parity
190  // could have changed is because of adding a box in the positive direction
191  // (due to the grid not being perfectly divisible; see above)
192  if (resolution_ % 2 != parity_) {
194  resolution_++;
195  }
196 
197  // Temporarily save previous grid data
198  auto tmp_c1 = c1_;
199  auto tmp_gradients = gradients_;
200 
201  c1_.clear();
202  c2_.clear();
203  gradients_.clear();
204 
206 
207  CopyOldData(tmp_c1, tmp_gradients, tmp_resolution);
208  }
209 }
210 
212  const ParallelResizeVector<real_t>& old_c1,
213  const ParallelResizeVector<Real3>& old_gradients, size_t old_resolution) {
214  // Allocate more memory for the grid data arrays
215  locks_.resize(total_num_boxes_);
219 
220  Log::Warning(
221  "DiffusionGrid::CopyOldData",
222  "The size of the diffusion grid "
223  "increased. BioDynaMo adds a halo around the domain filled with zeros. "
224  "Depending your use-case, this might or might not be what you want. If "
225  "you have non-zero concentrations / temperatures in the surrounding, "
226  "this is likely to cause unphysical effects at the boundary. But if your "
227  "grid values are mostly zero this is likely to work fine. Evaluate your "
228  "results carefully.");
229 
230  auto incr_num_boxes = resolution_ - old_resolution;
231  int off_dim = incr_num_boxes / 2;
232 
233  int num_box_xy = resolution_ * resolution_;
234  int old_box_xy = old_resolution * old_resolution;
235  int new_origin = off_dim * num_box_xy + off_dim * resolution_ + off_dim;
236  for (size_t k = 0; k < old_resolution; k++) {
237  int offset = new_origin + k * num_box_xy;
238  for (size_t j = 0; j < old_resolution; j++) {
239  if (j != 0) {
240  offset += resolution_;
241  }
242  for (size_t i = 0; i < old_resolution; i++) {
243  auto idx = k * old_box_xy + j * old_resolution + i;
244  c1_[offset + i] = old_c1[idx];
245  gradients_[offset + i] = old_gradients[idx];
246  }
247  }
248  }
249  // TODO: here we also need to copy c1_ into c2_ such that the boundaries are
250  // equivalent once we introduce non-zero halos.
251 }
252 
254  // If there are no initializers, we don't need to do anything and can return
255  // immediately
256  if (initializers_.empty()) {
257  return;
258  }
259 
260  // Define variables for loop bounds & boundary condition check
261  const auto kNumBoxes = total_num_boxes_;
262  const auto kGridSize = resolution_;
263  // For certain boudaries, we also need to copy the values to the c2_ array
264  const bool kCopyToC2 =
268 
269 // Apply all functions that initialize this diffusion grid
270 #pragma omp parallel for schedule(static)
271  for (size_t idx = 0; idx < kNumBoxes; idx++) {
272  // Determine the coordinates of the box
273  const std::array<uint32_t, 3> box_coord = GetBoxCoordinates(idx);
274 
275  // Determine the real coordinates of the box
276  std::array<real_t, 3> real_coord;
277 #pragma omp simd
278  for (size_t i = 0; i < 3; i++) {
279  real_coord[i] = grid_dimensions_[0] +
280  static_cast<real_t>(box_coord[i]) * box_length_ +
281  box_length_ / 2.0;
282  }
283 
284  // Calculate the value of the substance in the box
285  real_t value{0};
287  (box_coord[0] == 0 || box_coord[0] == kGridSize - 1 ||
288  box_coord[1] == 0 || box_coord[1] == kGridSize - 1 ||
289  box_coord[2] == 0 || box_coord[2] == kGridSize - 1)) {
290  // Evaluate the boundary condition in case of Dirichlet boundary
291  value = boundary_condition_->Evaluate(real_coord[0], real_coord[1],
292  real_coord[2], 0);
293  } else {
294  for (size_t f = 0; f < initializers_.size(); f++) {
295  value += initializers_[f](real_coord[0], real_coord[1], real_coord[2]);
296  }
297  }
298 
299  // Allow only lower_threshold_ <= value <= upper_threshold_
300  value = std::max(value, lower_threshold_);
301  value = std::min(value, upper_threshold_);
302 
303  // Set the value of the substance in the box
304  c1_[idx] = value;
305 
306  // For certain boundaries, we need to copy the value to c2_
307  if (kCopyToC2) {
308  c2_[idx] = value;
309  }
310  }
311 
312  // Clear the initializer to free up space
313  initializers_.clear();
314  initializers_.shrink_to_fit();
315 }
316 
318  // check if gradient has been calculated once
319  // and if diffusion coefficient and decay constant are 0
320  // i.e. if we don't need to calculate gradient update
321  if (init_gradient_ && IsFixedSubstance()) {
322  return;
323  }
324  if (!precompute_gradients_) {
325  return;
326  }
327 
328 #pragma omp parallel for collapse(2)
329  for (uint32_t z = 0; z < resolution_; z++) {
330  for (uint32_t y = 0; y < resolution_; y++) {
331  for (uint32_t x = 0; x < resolution_; x++) {
332  size_t idx = x + y * resolution_ + z * resolution_ * resolution_;
333  const std::array<uint32_t, 3> box_coord = {x, y, z};
334  // Get the neighboring boxes
335  const auto neighbors = GetNeighboringBoxes(idx, box_coord);
336  std::array<int, 6> comparison; // array to determine discretization h
337  std::transform(neighbors.begin(), neighbors.end(), comparison.begin(),
338  [idx](size_t n) { return (n == idx) ? 0 : 1; });
339 
340  // Calculate the gradient (no thread safety issues here)
341  gradients_[idx][0] = (c1_[neighbors[1]] - c1_[neighbors[0]]) /
342  ((comparison[1] + comparison[0]) * box_length_);
343  gradients_[idx][1] = (c1_[neighbors[3]] - c1_[neighbors[2]]) /
344  ((comparison[3] + comparison[2]) * box_length_);
345  gradients_[idx][2] = (c1_[neighbors[5]] - c1_[neighbors[4]]) /
346  ((comparison[5] + comparison[4]) * box_length_);
347  }
348  }
349  }
350  if (!init_gradient_) {
351  init_gradient_ = true;
352  }
353 }
354 
355 void DiffusionGrid::ChangeConcentrationBy(const Real3& position, real_t amount,
356  InteractionMode mode,
357  bool scale_with_resolution) {
358  auto idx = GetBoxIndex(position);
359  ChangeConcentrationBy(idx, amount, mode, scale_with_resolution);
360 }
361 
364  InteractionMode mode,
365  bool scale_with_resolution) {
366  if (idx >= total_num_boxes_) {
367  Log::Error("DiffusionGrid::ChangeConcentrationBy",
368  "You tried to change the concentration outside the bounds of "
369  "the diffusion grid! The change was ignored.");
370  return;
371  }
372  if (scale_with_resolution) {
373  // Convert from amount to concentration of substance by dividing by
374  // volume of box
375  amount /= box_length_ * box_length_ * box_length_;
376  }
377  std::lock_guard<Spinlock> guard(locks_[idx]);
378  assert(idx < locks_.size());
379  switch (mode) {
381  c1_[idx] += amount;
382  break;
384  c1_[idx] *= amount;
385  break;
387  c1_[idx] += ((amount > 0) ? upper_threshold_ - c1_[idx]
388  : c1_[idx] - lower_threshold_) *
389  amount;
390  break;
391  default:
392  Log::Fatal("DiffusionGrid::ChangeConcentrationBy",
393  "Unknown interaction mode!");
394  }
395 
396  // Enforce upper and lower bounds.
397  c1_[idx] = std::clamp(c1_[idx], lower_threshold_, upper_threshold_);
398 }
399 
401 real_t DiffusionGrid::GetValue(const Real3& position) const {
402  auto idx = GetBoxIndex(position);
403  return GetConcentration(idx);
404 }
405 
407 real_t DiffusionGrid::GetConcentration(const size_t idx) const {
408  if (idx >= total_num_boxes_) {
409  Log::Error("DiffusionGrid::ChangeConcentrationBy",
410  "You tried to get the concentration outside the bounds of "
411  "the diffusion grid!");
412  return 0;
413  }
414  assert(idx < locks_.size());
415  std::lock_guard<Spinlock> guard(locks_[idx]);
416  return c1_[idx];
417 }
418 
419 void DiffusionGrid::GetGradient(const Real3& position, Real3* gradient,
420  bool normalize) const {
421  assert(gradient != nullptr);
422  auto idx = GetBoxIndex(position);
423  if (idx >= total_num_boxes_) {
424  Log::Error("DiffusionGrid::GetGradient",
425  "You tried to get the gradient outside the bounds of "
426  "the diffusion grid! Returning zero gradient.");
427  return;
428  }
429  if (init_gradient_) {
430  *gradient = gradients_[idx];
431  } else {
432  // Get the neighboring boxes
433  const auto neighbors = GetNeighboringBoxes(idx);
434  std::array<int, 6> comparison; // array to determine discretization h
435  std::transform(neighbors.begin(), neighbors.end(), comparison.begin(),
436  [idx](size_t n) { return (n == idx) ? 0 : 1; });
437 
438  // Calculate the gradient (GetConcentration for thread safety)
439  const real_t x_minus = GetConcentration(neighbors[0]);
440  const real_t x_plus = GetConcentration(neighbors[1]);
441  const real_t y_minus = GetConcentration(neighbors[2]);
442  const real_t y_plus = GetConcentration(neighbors[3]);
443  const real_t z_minus = GetConcentration(neighbors[4]);
444  const real_t z_plus = GetConcentration(neighbors[5]);
445 
446  real_t grad_x =
447  (x_plus - x_minus) / ((comparison[1] + comparison[0]) * box_length_);
448  real_t grad_y =
449  (y_plus - y_minus) / ((comparison[3] + comparison[2]) * box_length_);
450  real_t grad_z =
451  (z_plus - z_minus) / ((comparison[5] + comparison[4]) * box_length_);
452 
453  *gradient = Real3({grad_x, grad_y, grad_z});
454  }
455  if (normalize) {
456  auto norm = gradient->Norm();
457  if (norm > 1e-10) {
458  gradient->Normalize(norm);
459  }
460  }
461 }
462 
463 std::array<uint32_t, 3> DiffusionGrid::GetBoxCoordinates(
464  const Real3& position) const {
465  std::array<uint32_t, 3> box_coord;
466 
467  for (size_t i = 0; i < 3; i++) {
468 // Check if position is within boundaries
469 #ifndef NDEBUG
470  assert((position[i] >= grid_dimensions_[0]) &&
471  "You tried to get the box coordinates outside the bounds of the "
472  "diffusion grid!");
473  assert((position[i] <= grid_dimensions_[1]) &&
474  "You tried to get the box coordinates outside the bounds of the "
475  "diffusion grid!");
476 #endif // NDEBUG
477  // Get box coords (Note: conversion to uint32_t should be save for typical
478  // grid sizes)
479  box_coord[i] = static_cast<uint32_t>(
480  std::floor((position[i] - grid_dimensions_[0]) / box_length_));
481  }
482  return box_coord;
483 }
484 
485 std::array<uint32_t, 3> DiffusionGrid::GetBoxCoordinates(
486  const size_t idx) const {
487  // Resolution must be smaller than uint32_t max for the box coordinates to be
488  // representable
489  assert(resolution_ < std::numeric_limits<uint32_t>::max());
490  std::array<uint32_t, 3> box_coord;
491  box_coord[0] = static_cast<uint32_t>(idx % resolution_);
492  box_coord[1] = static_cast<uint32_t>((idx / resolution_) % resolution_);
493  box_coord[2] = static_cast<uint32_t>(idx / (resolution_ * resolution_));
494  return box_coord;
495 }
496 
498  const std::array<uint32_t, 3>& box_coord) const {
499  size_t ret = box_coord[2] * resolution_ * resolution_ +
500  box_coord[1] * resolution_ + box_coord[0];
501  return ret;
502 }
503 
505 size_t DiffusionGrid::GetBoxIndex(const Real3& position) const {
506  auto box_coord = GetBoxCoordinates(position);
507  return GetBoxIndex(box_coord);
508 }
509 
510 std::array<size_t, 6> DiffusionGrid::GetNeighboringBoxes(size_t index) const {
511  const auto box_coord = GetBoxCoordinates(index);
512  return GetNeighboringBoxes(index, box_coord);
513 };
514 
516  size_t index, const std::array<uint32_t, 3>& box_coord) const {
517  std::array<size_t, 6> neighbors;
518  neighbors[0] = (box_coord[0] == 0) ? index : index - 1;
519  neighbors[1] = (box_coord[0] == resolution_ - 1) ? index : index + 1;
520  neighbors[2] = (box_coord[1] == 0) ? index : index - resolution_;
521  neighbors[3] =
522  (box_coord[1] == resolution_ - 1) ? index : index + resolution_;
523  neighbors[4] =
524  (box_coord[2] == 0) ? index : index - resolution_ * resolution_;
525  neighbors[5] = (box_coord[2] == resolution_ - 1)
526  ? index
527  : index + resolution_ * resolution_;
528  return neighbors;
529 }
530 
532  std::unique_ptr<BoundaryCondition> bc) {
533  boundary_condition_ = std::move(bc);
534 }
535 
537  return boundary_condition_.get();
538 }
539 
541  auto previous_bc = BoundaryTypeToString(bc_type_);
542  auto new_bc = BoundaryTypeToString(bc_type);
543  Log::Info("DiffusionGrid::SetBoundaryConditionType",
544  "Changing boundary condition from ", previous_bc, " to ", new_bc);
545  bc_type_ = bc_type;
546 }
547 
549  return bc_type_;
550 }
551 
552 void DiffusionGrid::PrintInfo(std::ostream& out) {
553  auto continuum_name = GetContinuumName();
554  if (!IsInitialized()) {
555  // If the grid is not yet initialized, many of the variables have no valid
556  // values. We print a warning and print the info after the grid is
557  // initialized.
558  out << "DiffusionGrid" << continuum_name
559  << "is not yet initialized. Will print info after initialization."
560  << std::endl;
562  return;
563  }
564 
565  // Get all the info
566  auto box_length = GetBoxLength();
567  auto diffusion_coefficient = 1 - GetDiffusionCoefficients()[0];
568  auto decay = GetDecayConstant();
569  auto max_dt =
570  (box_length * box_length) / (decay + 12.0 * diffusion_coefficient) * 2.0;
571  auto domain = GetDimensions();
572  auto umin = GetLowerThreshold();
573  auto umax = GetUpperThreshold();
574  auto resolution = GetResolution();
575  auto num_boxes = GetNumBoxes();
576 
577  // Print the info
578  out << "DiffusionGrid: " << continuum_name << "\n";
579  out << " D = " << diffusion_coefficient << "\n";
580  out << " decay = " << decay << "\n";
581  out << " dx = " << box_length << "\n";
582  out << " max(dt) <= " << max_dt << "\n";
583  out << " bounds : " << umin << " < c < " << umax << "\n";
584  out << " domain : "
585  << "[" << domain[0] << ", " << domain[1] << "] x [" << domain[2] << ", "
586  << domain[3] << "] x [" << domain[4] << ", " << domain[5] << "]\n";
587  out << " resolution : " << resolution << " x " << resolution << " x "
588  << resolution << "\n";
589  out << " num boxes : " << num_boxes << "\n";
590  out << " boundary : " << BoundaryTypeToString(bc_type_) << "\n";
591 };
592 
594  // We evaluate a stability condition derived via a von Neumann stability
595  // analysis (https://en.wikipedia.org/wiki/Von_Neumann_stability_analysis,
596  // accessed 2022-10-27) of the diffusion equation. In comparison to the
597  // Wikipedia article, we use a 3D diffusion equation and also consider the
598  // decay. We end up with the following result:
599  const bool stability =
600  ((mu_ + 12.0 * (1 - dc_[0]) / (box_length_ * box_length_)) * dt <= 2.0);
601  if (!stability) {
602  const double max_dt =
603  2.0 / (mu_ + 12.0 * (1 - dc_[0])) * (box_length_ * box_length_);
604  Log::Fatal(
605  "DiffusionGrid", "Stability condition violated. ",
606  "The specified parameters of the diffusion grid with substance [",
608  "] will result in unphysical behavior (diffusion coefficient = ",
609  (1 - dc_[0]), ", resolution = ", resolution_,
610  ", decay constant = ", mu_, ", dt = ", dt,
611  "). For the given parameters, the time step must be smaller than ",
612  max_dt, ". Please refer to the user guide for more information.");
613  }
614 
615  // We also check if the decay constant is too large. This is not a stability
616  // condition, but it may result in unphysical behavior, e.g. negative values
617  // for the concentration. We obtain the condition by assuming that all
618  // concentration values of the previous time step are positive and demanding
619  // the same for the next time step. We arrive at the following condition:
620  const bool decay_safety =
621  (1 - (mu_ + 6 * (1 - dc_[0]) / (box_length_ * box_length_) * dt) >= 0);
622  if (!decay_safety) {
623  Log::Fatal(
624  "DiffusionGrid", "Decay may overstep into negative regime. ",
625  "The specified parameters of the diffusion grid with substance [",
627  "] may result in unphysical behavior (diffusion coefficient = ",
628  (1 - dc_[0]), ", resolution = ", resolution_,
629  ", decay constant = ", mu_, ", dt = ", dt,
630  "). Please refer to the user guide for more information.");
631  }
632 }
633 
634 } // namespace bdm
bdm::BoundaryConditionType::kPeriodic
@ kPeriodic
bdm::DiffusionGrid::gradients_
ParallelResizeVector< Real3 > gradients_
The array of gradients (x, y, z)
Definition: diffusion_grid.h:386
bdm::DiffusionGrid::boundary_condition_
std::unique_ptr< BoundaryCondition > boundary_condition_
Object that implements the boundary conditions.
Definition: diffusion_grid.h:417
bdm::DiffusionGrid::Update
void Update() override
Definition: diffusion_grid.cc:156
bdm::DiffusionGrid::GetConcentration
real_t GetConcentration(const Real3 &position) const
Definition: diffusion_grid.h:170
bdm::DiffusionGrid::precompute_gradients_
bool precompute_gradients_
Definition: diffusion_grid.h:425
bdm::DiffusionGrid::PrintInfo
void PrintInfo(std::ostream &out=std::cout)
Print information about the Diffusion Grid.
Definition: diffusion_grid.cc:552
bdm::DiffusionGrid::GetBoundaryCondition
BoundaryCondition * GetBoundaryCondition() const
Returns the boundary condition. Does not transfer ownership.
Definition: diffusion_grid.cc:536
bdm::BoundaryConditionType::kOpenBoundaries
@ kOpenBoundaries
bdm::DiffusionGrid::grid_dimensions_
std::array< int32_t, 2 > grid_dimensions_
The grid dimensions of the diffusion grid (cubic shaped)
Definition: diffusion_grid.h:396
bdm::DiffusionGrid::GetBoxLength
real_t GetBoxLength() const
Definition: diffusion_grid.h:270
bdm::DiffusionGrid::GetValue
real_t GetValue(const Real3 &position) const override
Get the value of the scalar field at specified position.
Definition: diffusion_grid.cc:401
bdm::DiffusionGrid::GetBoxIndex
size_t GetBoxIndex(const std::array< uint32_t, 3 > &box_coord) const
Calculates the box index at specified box coordinates.
Definition: diffusion_grid.cc:497
bdm::DiffusionGrid::parity_
bool parity_
If false, grid dimensions are even; if true, they are odd.
Definition: diffusion_grid.h:407
bdm::DiffusionGrid::CalculateGradient
void CalculateGradient()
Definition: diffusion_grid.cc:317
bdm
Definition: agent.cc:39
bdm::InteractionMode::kAdditive
@ kAdditive
bdm::DiffusionGrid::GetNumBoxes
size_t GetNumBoxes() const
Definition: diffusion_grid.h:268
bdm::DiffusionGrid::Diffuse
void Diffuse(real_t dt)
Definition: diffusion_grid.cc:125
bdm::DiffusionGrid::print_info_with_initialization_
bool print_info_with_initialization_
Definition: diffusion_grid.h:422
bdm::DiffusionGrid::lower_threshold_
real_t lower_threshold_
The minimum concentration value that a box can have.
Definition: diffusion_grid.h:390
bdm::DiffusionGrid::mu_
real_t mu_
The decay constant.
Definition: diffusion_grid.h:394
bdm::BoundaryConditionType::kClosedBoundaries
@ kClosedBoundaries
bdm::DiffusionGrid::locks_
ParallelResizeVector< Spinlock > locks_
Definition: diffusion_grid.h:380
bdm::real_t
double real_t
Definition: real_t.h:21
bdm::DiffusionGrid::DiffuseWithOpenEdge
virtual void DiffuseWithOpenEdge(real_t dt)=0
bdm::DiffusionGrid::GetDecayConstant
real_t GetDecayConstant() const
Definition: diffusion_grid.h:281
bdm::DiffusionGrid::c1_
ParallelResizeVector< real_t > c1_
The array of concentration values.
Definition: diffusion_grid.h:382
bdm::DiffusionGrid::box_volume_
real_t box_volume_
the volume of each box
Definition: diffusion_grid.h:377
bdm::InteractionMode::kLogistic
@ kLogistic
bdm::DiffusionGrid::init_gradient_
bool init_gradient_
Definition: diffusion_grid.h:413
bdm::DiffusionGrid::GetBoxCoordinates
std::array< uint32_t, 3 > GetBoxCoordinates(const Real3 &position) const
Get the coordinates of the box at the specified position.
Definition: diffusion_grid.cc:463
bdm::DiffusionGrid::SetBoundaryConditionType
void SetBoundaryConditionType(BoundaryConditionType bc_type)
Sets boundary condition type.
Definition: diffusion_grid.cc:540
bdm::ParallelResizeVector< real_t >
bdm::DiffusionGrid::ParametersCheck
void ParametersCheck(real_t dt)
Definition: diffusion_grid.cc:593
bdm::DiffusionGrid::total_num_boxes_
size_t total_num_boxes_
The total number of boxes in the diffusion grid.
Definition: diffusion_grid.h:400
bdm::DiffusionGrid::GetUpperThreshold
real_t GetUpperThreshold() const
Definition: diffusion_grid.h:248
bdm::DiffusionGrid::CopyOldData
void CopyOldData(const ParallelResizeVector< real_t > &old_c1, const ParallelResizeVector< Real3 > &old_gradients, size_t old_resolution)
Definition: diffusion_grid.cc:211
bdm::BoundaryConditionType
BoundaryConditionType
Available boundary conditions.
Definition: diffusion_grid.h:35
bdm::InteractionMode
InteractionMode
Definition: diffusion_grid.h:43
bdm::Continuum::GetContinuumName
const std::string & GetContinuumName() const
Returns the name of the continuum.
Definition: continuum_interface.h:93
bdm::DiffusionGrid::DiffuseWithPeriodic
virtual void DiffuseWithPeriodic(real_t dt)=0
bdm::DiffusionGrid::DiffuseWithClosedEdge
virtual void DiffuseWithClosedEdge(real_t dt)=0
bdm::DiffusionGrid::GetBoundaryConditionType
BoundaryConditionType GetBoundaryConditionType() const
Returns the BoundaryConditionType, see BoundaryConditionType
Definition: diffusion_grid.cc:548
bdm::Log::Warning
static void Warning(const std::string &location, const Args &... parts)
Prints warning message.
Definition: log.h:67
bdm::InteractionMode::kExponential
@ kExponential
bdm::DiffusionGrid::RunInitializers
void RunInitializers()
Definition: diffusion_grid.cc:253
bdm::BoundaryCondition
This class implements the boundary conditions. It is integrated into the diffusion grid as a smart po...
Definition: diffusion_grid.h:49
bdm::MathArray::Norm
T Norm() const
Definition: math_array.h:352
diffusion_grid.h
bdm::Log::Info
static void Info(const std::string &location, const Args &... parts)
Prints information message.
Definition: log.h:55
bdm::DiffusionGrid::initializers_
std::vector< std::function< real_t(real_t, real_t, real_t)> > initializers_
Definition: diffusion_grid.h:410
bdm::DiffusionGrid::initialized_
bool initialized_
Flag to indicate if the grid is initialized.
Definition: diffusion_grid.h:419
bdm::DiffusionGrid::Initialize
void Initialize() override
Definition: diffusion_grid.cc:77
bdm::DiffusionGrid::GetLowerThreshold
real_t GetLowerThreshold() const
Definition: diffusion_grid.h:254
bdm::StringToBoundaryType
BoundaryConditionType StringToBoundaryType(const std::string &type)
Transforms a string to the corresponding BoundaryConditionType.
Definition: diffusion_grid.cc:44
bdm::Environment::GetDimensionThresholds
virtual std::array< int32_t, 2 > GetDimensionThresholds() const =0
bdm::DiffusionGrid::GetNeighboringBoxes
std::array< size_t, 6 > GetNeighboringBoxes(size_t index) const
Definition: diffusion_grid.cc:510
bdm::DiffusionGrid::box_length_
real_t box_length_
The side length of each box.
Definition: diffusion_grid.h:375
bdm::Log::Fatal
static void Fatal(const std::string &location, const Args &... parts)
Prints fatal error message.
Definition: log.h:115
bdm::Log::Error
static void Error(const std::string &location, const Args &... parts)
Prints error message.
Definition: log.h:79
bdm::DiffusionGrid::GetDiffusionCoefficients
const std::array< real_t, 7 > & GetDiffusionCoefficients() const
Definition: diffusion_grid.h:304
bdm::ParallelResizeVector::resize
void resize(std::size_t new_size, const T &t=T())
Definition: parallel_resize_vector.h:122
log.h
bdm::DiffusionGrid::DiffusionGrid
DiffusionGrid()=default
bdm::DiffusionGrid::last_dt_
real_t last_dt_
The last timestep dt used for the diffusion grid update Diffuse(dt)
Definition: diffusion_grid.h:405
bdm::DiffusionGrid::GetDimensions
std::array< int32_t, 6 > GetDimensions() const
Definition: diffusion_grid.h:285
bdm::Simulation::GetEnvironment
Environment * GetEnvironment()
Definition: simulation.cc:260
bdm::DiffusionGrid::bc_type_
BoundaryConditionType bc_type_
Type of boundary conditions.
Definition: diffusion_grid.h:415
bdm::BoundaryConditionType::kNeumann
@ kNeumann
bdm::Real3
MathArray< real_t, 3 > Real3
Aliases for a size 3 MathArray.
Definition: math_array.h:434
bdm::DiffusionGrid::resolution_
size_t resolution_
Definition: diffusion_grid.h:403
environment.h
simulation.h
bdm::DiffusionGrid::DiffuseWithDirichlet
virtual void DiffuseWithDirichlet(real_t dt)=0
bdm::Simulation::GetParam
const Param * GetParam() const
Returns the simulation parameters.
Definition: simulation.cc:254
bdm::DiffusionGrid::DiffuseWithNeumann
virtual void DiffuseWithNeumann(real_t dt)=0
bdm::MathArray
Definition: math_array.h:36
bdm::DiffusionGrid::upper_threshold_
real_t upper_threshold_
The maximum concentration value that a box can have.
Definition: diffusion_grid.h:388
bdm::DiffusionGrid::IsInitialized
bool IsInitialized() const
Returns if the grid has been initialized.
Definition: diffusion_grid.h:345
bdm::DiffusionGrid::ChangeConcentrationBy
void ChangeConcentrationBy(const Real3 &position, real_t amount, InteractionMode mode=InteractionMode::kAdditive, bool scale_with_resolution=false)
Definition: diffusion_grid.cc:355
bdm::DiffusionGrid::SetBoundaryCondition
void SetBoundaryCondition(std::unique_ptr< BoundaryCondition > bc)
Set the boundary condition, takes ownership of the object.
Definition: diffusion_grid.cc:531
bdm::Simulation::GetActive
static Simulation * GetActive()
This function returns the currently active Simulation simulation.
Definition: simulation.cc:68
bdm::BoundaryConditionType::kDirichlet
@ kDirichlet
bdm::DiffusionGrid::GetGradient
Real3 GetGradient(const Real3 &position) const override
Definition: diffusion_grid.h:196
bdm::BoundaryTypeToString
std::string BoundaryTypeToString(const BoundaryConditionType &type)
Transforms a BoundaryConditionType to the corresponding string.
Definition: diffusion_grid.cc:26
bdm::DiffusionGrid::dc_
std::array< real_t, 7 > dc_
The diffusion coefficients [cc, cw, ce, cs, cn, cb, ct].
Definition: diffusion_grid.h:392
bdm::ParallelResizeVector::clear
void clear()
Definition: parallel_resize_vector.h:140
bdm::DiffusionGrid::c2_
ParallelResizeVector< real_t > c2_
An extra concentration data buffer for faster value updating.
Definition: diffusion_grid.h:384
bdm::DiffusionGrid::GetResolution
size_t GetResolution() const
Definition: diffusion_grid.h:306
bdm::MathArray::Normalize
void Normalize()
Normalize the array in-place.
Definition: math_array.h:364
bdm::DiffusionGrid::IsFixedSubstance
bool IsFixedSubstance()
Return if a substance is stationary, e.g. (mu == 0 && dc == 0)
Definition: diffusion_grid.h:316