BioDynaMo  v1.05.119-a4ff3934
vtk_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 
16 // ParaView
17 #include <vtkCPDataDescription.h>
18 #include <vtkCPInputDataDescription.h>
19 #include <vtkDoubleArray.h>
20 #include <vtkExtentTranslator.h>
21 #include <vtkFloatArray.h>
22 #include <vtkNew.h>
23 #include <vtkPointData.h>
24 #include <vtkPoints.h>
25 // BioDynaMo
26 #include "core/param/param.h"
27 #include "core/simulation.h"
28 #include "core/util/log.h"
29 #include "core/util/thread_info.h"
31 
32 namespace bdm {
33 
34 using vtkRealArray =
35  typename type_ternary_operator<std::is_same<real_t, double>::value,
36  vtkDoubleArray, vtkFloatArray>::type;
37 
38 // -----------------------------------------------------------------------------
39 VtkDiffusionGrid::VtkDiffusionGrid(const std::string& name,
40  vtkCPDataDescription* data_description) {
41  auto* param = Simulation::GetActive()->GetParam();
42  if (param->export_visualization) {
43  auto* tinfo = ThreadInfo::GetInstance();
44  data_.resize(tinfo->GetMaxThreads());
45  } else {
46  data_.resize(1);
47  }
48 
49 #pragma omp parallel for schedule(static, 1)
50  for (uint64_t i = 0; i < data_.size(); ++i) {
51  data_[i] = vtkImageData::New();
52  }
53  name_ = name;
54 
55  // get visualization config
56  const Param::VisualizeDiffusion* vd = nullptr;
57  for (auto& entry : param->visualize_diffusion) {
58  if (entry.name == name) {
59  vd = &entry;
60  break;
61  }
62  }
63 
64  // If statement to prevent possible dereferencing of nullptr
65  if (vd) {
66  for (uint64_t i = 0; i < data_.size(); ++i) {
67  // Add attribute data
68  if (vd->concentration) {
69  vtkNew<vtkRealArray> concentration;
70  concentration->SetName("Substance Concentration");
72  data_[i]->GetPointData()->AddArray(concentration.GetPointer());
73  }
74  if (vd->gradient) {
75  vtkNew<vtkRealArray> gradient;
76  gradient->SetName("Diffusion Gradient");
77  gradient->SetNumberOfComponents(3);
79  data_[i]->GetPointData()->AddArray(gradient.GetPointer());
80  }
81  }
82 
83  if (!param->export_visualization) {
84  data_description->AddInput(name.c_str());
85  data_description->GetInputDescriptionByName(name.c_str())
86  ->SetGrid(data_[0]);
87  }
88  } else {
89  Log::Warning("VtkDiffusionGrid::VtkDiffusionGrid", "Variable `name` (",
90  name, ") not found in `param->visualize_diffusion`.");
91  }
92 }
93 
94 // -----------------------------------------------------------------------------
96  name_ = "";
97  for (auto& el : data_) {
98  el->Delete();
99  }
100  data_.clear();
101 }
102 
103 // -----------------------------------------------------------------------------
104 bool VtkDiffusionGrid::IsUsed() const { return used_; }
105 
106 // -----------------------------------------------------------------------------
108  used_ = true;
109 
110  auto num_boxes = grid->GetNumBoxesArray();
111  auto grid_dimensions = grid->GetDimensions();
112  auto box_length = grid->GetBoxLength();
113  auto total_boxes = grid->GetNumBoxes();
114 
115  auto* tinfo = ThreadInfo::GetInstance();
116  whole_extent_ = {{0, std::max(static_cast<int>(num_boxes[0]) - 1, 0), 0,
117  std::max(static_cast<int>(num_boxes[1]) - 1, 0), 0,
118  std::max(static_cast<int>(num_boxes[2]) - 1, 0)}};
119  Dissect(num_boxes[2], tinfo->GetMaxThreads());
120  CalcPieceExtents(num_boxes);
121  uint64_t xy_num_boxes = num_boxes[0] * num_boxes[1];
122  real_t origin_x = grid_dimensions[0] + box_length / 2.;
123  real_t origin_y = grid_dimensions[2] + box_length / 2.;
124  real_t origin_z = grid_dimensions[4] + box_length / 2.;
125 
126  // do not partition data for insitu visualization
127  if (data_.size() == 1) {
128  data_[0]->SetOrigin(origin_x, origin_y, origin_z);
129  data_[0]->SetDimensions(num_boxes[0], num_boxes[1], num_boxes[2]);
130  data_[0]->SetSpacing(box_length, box_length, box_length);
131 
132  if (concentration_array_idx_ != -1) {
133  auto* co_ptr = const_cast<real_t*>(grid->GetAllConcentrations());
134  auto elements = static_cast<vtkIdType>(total_boxes);
135  auto* array = static_cast<vtkRealArray*>(
136  data_[0]->GetPointData()->GetArray(concentration_array_idx_));
137  array->SetArray(co_ptr, elements, 1);
138  }
139  if (gradient_array_idx_ != -1) {
140  auto gr_ptr = const_cast<real_t*>(grid->GetAllGradients());
141  auto elements = static_cast<vtkIdType>(total_boxes * 3);
142  auto* array = static_cast<vtkRealArray*>(
143  data_[0]->GetPointData()->GetArray(gradient_array_idx_));
144  array->SetArray(gr_ptr, elements, 1);
145  }
146  return;
147  }
148 
149 #pragma omp parallel for schedule(static, 1)
150  for (uint64_t i = 0; i < num_pieces_; ++i) {
151  uint64_t piece_elements;
152  auto* e = piece_extents_[i].data();
153  if (i < num_pieces_ - 1) {
154  piece_elements = piece_boxes_z_ * xy_num_boxes;
155  data_[i]->SetDimensions(num_boxes[0], num_boxes[1], piece_boxes_z_);
156  data_[i]->SetExtent(e[0], e[1], e[2], e[3], e[4],
157  e[4] + piece_boxes_z_ - 1);
158  } else {
159  piece_elements = piece_boxes_z_last_ * xy_num_boxes;
160  data_[i]->SetDimensions(num_boxes[0], num_boxes[1], piece_boxes_z_last_);
161  data_[i]->SetExtent(e[0], e[1], e[2], e[3], e[4],
162  e[4] + piece_boxes_z_last_ - 1);
163  }
164  real_t piece_origin_z = origin_z + box_length * piece_boxes_z_ * i;
165  data_[i]->SetOrigin(origin_x, origin_y, piece_origin_z);
166  data_[i]->SetSpacing(box_length, box_length, box_length);
167 
168  if (concentration_array_idx_ != -1) {
169  auto* co_ptr = const_cast<real_t*>(grid->GetAllConcentrations());
170  auto elements = static_cast<vtkIdType>(piece_elements);
171  auto* array = static_cast<vtkRealArray*>(
172  data_[i]->GetPointData()->GetArray(concentration_array_idx_));
173  if (i < num_pieces_ - 1) {
174  array->SetArray(co_ptr + (elements * i), elements, 1);
175  } else {
176  array->SetArray(co_ptr + total_boxes - elements, elements, 1);
177  }
178  }
179  if (gradient_array_idx_ != -1) {
180  auto gr_ptr = const_cast<real_t*>(grid->GetAllGradients());
181  auto elements = static_cast<vtkIdType>(piece_elements * 3);
182  auto* array = static_cast<vtkRealArray*>(
183  data_[i]->GetPointData()->GetArray(gradient_array_idx_));
184  if (i < num_pieces_ - 1) {
185  array->SetArray(gr_ptr + (elements * i), elements, 1);
186  } else {
187  array->SetArray(gr_ptr + total_boxes - elements, elements, 1);
188  }
189  }
190  }
191 }
192 
193 // -----------------------------------------------------------------------------
194 void VtkDiffusionGrid::WriteToFile(uint64_t step) const {
195  auto* sim = Simulation::GetActive();
196  auto filename_prefix = Concat(name_, "-", step);
197 
198  ParallelVtiWriter writer;
199  writer(sim->GetOutputDir(), filename_prefix, data_, num_pieces_,
201 }
202 
203 // -----------------------------------------------------------------------------
204 void VtkDiffusionGrid::Dissect(uint64_t boxes_z, uint64_t num_pieces_target) {
205  if (num_pieces_target == 1) {
206  piece_boxes_z_last_ = boxes_z;
207  piece_boxes_z_ = 1;
208  num_pieces_ = 1;
209  } else if (boxes_z <= num_pieces_target) {
211  piece_boxes_z_ = 1;
212  num_pieces_ = std::max<unsigned long long>(1ULL, boxes_z - 1);
213  } else {
214  auto boxes_per_piece = static_cast<real_t>(boxes_z) / num_pieces_target;
215  piece_boxes_z_ = static_cast<uint64_t>(std::ceil(boxes_per_piece));
216  num_pieces_ = boxes_z / piece_boxes_z_;
217  piece_boxes_z_last_ = boxes_z - (num_pieces_ - 1) * piece_boxes_z_;
218  }
219  assert(num_pieces_ > 0);
220  assert(piece_boxes_z_last_ >= 1);
221  assert((num_pieces_ - 1) * piece_boxes_z_ + piece_boxes_z_last_ == boxes_z);
222 }
223 
224 // -----------------------------------------------------------------------------
226  const std::array<size_t, 3>& num_boxes) {
227  piece_extents_.resize(num_pieces_);
228  if (num_pieces_ == 1) {
230  return;
231  }
232  int c = piece_boxes_z_;
233  piece_extents_[0] = {{0, static_cast<int>(num_boxes[0]) - 1, 0,
234  static_cast<int>(num_boxes[1]) - 1, 0, c}};
235  for (uint64_t i = 1; i < num_pieces_ - 1; ++i) {
236  piece_extents_[i] = {{0, static_cast<int>(num_boxes[0]) - 1, 0,
237  static_cast<int>(num_boxes[1]) - 1, c,
238  c + static_cast<int>(piece_boxes_z_)}};
239  c += piece_boxes_z_;
240  }
241  piece_extents_.back() = {{0, static_cast<int>(num_boxes[0]) - 1, 0,
242  static_cast<int>(num_boxes[1]) - 1, c,
243  static_cast<int>(num_boxes[2]) - 1}};
244 }
245 
246 } // namespace bdm
parallel_vti_writer.h
bdm::Param::VisualizeDiffusion
Definition: param.h:388
bdm::VtkDiffusionGrid::~VtkDiffusionGrid
~VtkDiffusionGrid()
Definition: vtk_diffusion_grid.cc:95
bdm::VtkDiffusionGrid::name_
std::string name_
Definition: vtk_diffusion_grid.h:48
bdm::DiffusionGrid::GetBoxLength
real_t GetBoxLength() const
Definition: diffusion_grid.h:270
vtk_diffusion_grid.h
bdm::VtkDiffusionGrid::used_
bool used_
Definition: vtk_diffusion_grid.h:49
bdm::ThreadInfo::GetInstance
static ThreadInfo * GetInstance()
Definition: thread_info.cc:21
bdm::ParallelVtiWriter
Definition: parallel_vti_writer.h:68
bdm
Definition: agent.cc:39
thread_info.h
bdm::DiffusionGrid::GetNumBoxes
size_t GetNumBoxes() const
Definition: diffusion_grid.h:268
bdm::VtkDiffusionGrid::piece_boxes_z_
uint64_t piece_boxes_z_
Definition: vtk_diffusion_grid.h:59
bdm::VtkDiffusionGrid::whole_extent_
std::array< int, 6 > whole_extent_
Definition: vtk_diffusion_grid.h:61
bdm::real_t
double real_t
Definition: real_t.h:21
bdm::DiffusionGrid
Definition: diffusion_grid.h:90
bdm::Param::VisualizeDiffusion::gradient
bool gradient
Definition: param.h:391
bdm::VtkDiffusionGrid::Update
void Update(const DiffusionGrid *grid)
Definition: vtk_diffusion_grid.cc:107
bdm::VtkDiffusionGrid::piece_boxes_z_last_
uint64_t piece_boxes_z_last_
Definition: vtk_diffusion_grid.h:60
bdm::VtkDiffusionGrid::IsUsed
bool IsUsed() const
Definition: vtk_diffusion_grid.cc:104
bdm::Log::Warning
static void Warning(const std::string &location, const Args &... parts)
Prints warning message.
Definition: log.h:67
bdm::VtkDiffusionGrid::VtkDiffusionGrid
VtkDiffusionGrid(const std::string &name, vtkCPDataDescription *data_description)
Definition: vtk_diffusion_grid.cc:39
bdm::VtkDiffusionGrid::WriteToFile
void WriteToFile(uint64_t step) const
Definition: vtk_diffusion_grid.cc:194
bdm::Concat
std::string Concat(const Args &... parts)
Concatenates all arguments into a string. Equivalent to streaming all arguments into a stringstream a...
Definition: string.h:70
bdm::VtkDiffusionGrid::Dissect
void Dissect(uint64_t boxes_z, uint64_t num_pieces_target)
Definition: vtk_diffusion_grid.cc:204
bdm::DiffusionGrid::GetNumBoxesArray
std::array< size_t, 3 > GetNumBoxesArray() const
Definition: diffusion_grid.h:260
bdm::VtkDiffusionGrid::piece_extents_
std::vector< std::array< int, 6 > > piece_extents_
Definition: vtk_diffusion_grid.h:62
bdm::VtkDiffusionGrid::CalcPieceExtents
void CalcPieceExtents(const std::array< size_t, 3 > &num_boxes)
Definition: vtk_diffusion_grid.cc:225
log.h
bdm::VtkDiffusionGrid::concentration_array_idx_
int concentration_array_idx_
Definition: vtk_diffusion_grid.h:50
bdm::VtkDiffusionGrid::data_
std::vector< vtkImageData * > data_
Definition: vtk_diffusion_grid.h:47
bdm::DiffusionGrid::GetDimensions
std::array< int32_t, 6 > GetDimensions() const
Definition: diffusion_grid.h:285
bdm::vtkRealArray
typename type_ternary_operator< std::is_same< real_t, double >::value, vtkDoubleArray, vtkFloatArray >::type vtkRealArray
Definition: vtk_diffusion_grid.cc:36
bdm::DiffusionGrid::GetAllConcentrations
const real_t * GetAllConcentrations() const
Definition: diffusion_grid.h:256
simulation.h
bdm::Simulation::GetParam
const Param * GetParam() const
Returns the simulation parameters.
Definition: simulation.cc:254
bdm::Param::VisualizeDiffusion::concentration
bool concentration
Definition: param.h:390
bdm::VtkDiffusionGrid::gradient_array_idx_
int gradient_array_idx_
Definition: vtk_diffusion_grid.h:51
param.h
bdm::Simulation::GetActive
static Simulation * GetActive()
This function returns the currently active Simulation simulation.
Definition: simulation.cc:68
bdm::VtkDiffusionGrid::num_pieces_
uint64_t num_pieces_
Definition: vtk_diffusion_grid.h:58
bdm::DiffusionGrid::GetAllGradients
const real_t * GetAllGradients() const
Definition: diffusion_grid.h:258