World Builder  1.1.0-pre
A geodynamic initial conditions generator
main.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2018 - 2021 by the authors of the World Builder code.
3 
4  This file is part of the World Builder.
5 
6  This program is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published
8  by the Free Software Foundation, either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public License
17  along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19 
26 #include "visualization/main.h"
27 
28 #include "world_builder/assert.h"
30 #include "world_builder/nan.h"
31 #include "world_builder/point.h"
33 #include "world_builder/world.h"
34 #include "world_builder/config.h"
35 
36 #include <algorithm>
37 #include <limits>
38 
39 
40 #include "vtu11/vtu11.hpp"
41 #undef max
42 #undef min
43 
44 #ifdef WB_WITH_MPI
45 // we don't need the c++ MPI wrappers
46 #define OMPI_SKIP_MPICXX 1
47 #define MPICH_SKIP_MPICXX
48 #include <mpi.h>
49 #endif
50 
51 #ifndef NDEBUG
52 #ifdef WB_USE_FP_EXCEPTIONS
53 #include <cfenv>
54 #endif
55 #endif
56 
57 #include <algorithm>
58 #include <array>
59 #include <cmath>
60 #include <iostream>
61 #include <iterator>
62 #include <memory>
63 #include <string>
64 #include <thread>
65 #include <vector>
66 
67 using namespace WorldBuilder;
68 using namespace WorldBuilder::Utilities;
69 
70 
71 
75 void filter_vtu_mesh(int dim,
76  const std::vector<bool> &include_tag,
77  vtu11::Vtu11UnstructuredMesh &input_mesh,
78  const std::vector<vtu11::DataSetData> &input_data,
79  vtu11::Vtu11UnstructuredMesh &output_mesh,
80  std::vector<vtu11::DataSetData> &output_data);
81 
82 void filter_vtu_mesh(int dim,
83  const std::vector<bool> &include_tag,
84  vtu11::Vtu11UnstructuredMesh &input_mesh,
85  const std::vector<vtu11::DataSetData> &input_data,
86  vtu11::Vtu11UnstructuredMesh &output_mesh,
87  std::vector<vtu11::DataSetData> &output_data)
88 {
89  output_data.resize(input_data.size());
90  const std::int64_t invalid = -1;
91  std::vector<std::int64_t> vertex_index_map(input_mesh.points().size(), invalid);
92 
93  const unsigned int n_vert_per_cell = (dim==3)?8:4;
94 
95  const std::size_t n_cells = input_mesh.types().size();
96  std::uint64_t dst_cellid = 0;
97  unsigned int tag_index = 3;
98  for (std::size_t cellidx = 0; cellidx <n_cells; ++cellidx)
99  {
100  int highest_tag = -1;
101  for (size_t idx=cellidx*n_vert_per_cell; idx<(cellidx+1)*n_vert_per_cell; ++idx)
102  {
103  const std::size_t src_vid = static_cast<size_t>(input_mesh.connectivity()[idx]);
104  highest_tag = std::max(highest_tag,static_cast<int>(input_data[tag_index][src_vid]));
105  }
106  if (highest_tag < 0 || include_tag[static_cast<size_t>(highest_tag)]==false)
107  continue;
108 
109  ++dst_cellid;
110 
111  for (size_t idx=cellidx*n_vert_per_cell; idx<(cellidx+1)*n_vert_per_cell; ++idx)
112  {
113  const size_t src_vid = static_cast<size_t>(input_mesh.connectivity()[idx]);
114 
115  std::int64_t dst_vid = vertex_index_map[src_vid];
116  if (dst_vid == invalid)
117  {
118  dst_vid = static_cast<std::int64_t>(output_mesh.points().size()/3);
119  vertex_index_map[src_vid] = dst_vid;
120 
121  for (unsigned int i=0; i<3; ++i)
122  output_mesh.points().emplace_back(input_mesh.points()[src_vid*3+i]);
123 
124  for (unsigned int d=0; d<input_data.size(); ++d)
125  // The following line checks if we are accessing the velocity data, which is
126  // currently stored as the third property after depth and temperature, and if so,
127  // we need to copy all 3 components.
128  if (d == 2)
129  {
130  for (unsigned int i=0; i<3; ++i)
131  output_data[d].push_back(input_data[d][src_vid*3+i]);
132  }
133  else
134  {
135  output_data[d].push_back(input_data[d][src_vid]);
136  }
137  }
138 
139  output_mesh.connectivity().push_back(dst_vid);
140 
141  }
142  output_mesh.offsets().push_back(static_cast<long int>(dst_cellid*n_vert_per_cell));
143 
144  output_mesh.types().push_back(input_mesh.types()[cellidx]);
145  }
146 }
147 
155 {
156  public:
157 
161  explicit ThreadPool(size_t number_of_threads)
162  {
163  pool.resize(number_of_threads);
164  }
165 
169  template<typename Callable>
170  void parallel_for(size_t start, size_t end, Callable func)
171  {
172  // Determine the size of the slice for the loop
173  const size_t n = end - start + 1;
174  size_t slice = static_cast<size_t>(std::round(n / static_cast<size_t>((pool.size()))));
175  slice = std::max(slice, static_cast<size_t>(1));
176 
177  // Function which loops the passed function func
178  auto loop_function = [&func] (size_t k1, size_t k2)
179  {
180  for (size_t k = k1; k < k2; k++)
181  {
182  func(k);
183  }
184  };
185 
186  // Launch jobs
187  size_t i1 = start;
188  size_t i2 = std::min(start + slice, end);
189  for (size_t i = 0; i + 1 < pool.size() && i1 < end; ++i)
190  {
191  pool[i] = std::thread(loop_function, i1, i2);
192  i1 = i2;
193  i2 = std::min(i2 + slice, end);
194  }
195  if (i1 < end)
196  {
197  pool[pool.size()-1] = std::thread(loop_function, i1, end);
198  }
199 
200  // Wait for jobs to finish
201  for (std::thread &t : pool)
202  {
203  if (t.joinable())
204  {
205  t.join();
206  }
207  }
208  }
209 
210  private:
211  std::vector<std::thread> pool;
212 
213 };
214 
215 
216 void project_on_sphere(double radius, double &x_, double &y_, double &z_)
217 {
218  double x = x_;
219  double y = y_;
220  double z = z_;
221  const WorldBuilder::Point<3> in_point(std::array<double,3> {{x,y,z}}, WorldBuilder::CoordinateSystem::cartesian);
222  const WorldBuilder::Point<3> output_point(std::array<double,3> {{0,0,0}}, WorldBuilder::CoordinateSystem::cartesian);
223  const double r = in_point.norm();
224  const double theta = std::atan2(in_point[1],in_point[0]);
225  const double phi = std::acos(in_point[2]/r);
226 
227  x_ = radius * std::cos(theta) * std::sin(phi);
228  y_ = radius * std::sin(theta) * std::sin(phi);
229  z_ = radius * std::cos(phi);
230 
231 }
232 
233 void lay_points(double x1, double y1, double z1,
234  double x2, double y2, double z2,
235  double x3, double y3, double z3,
236  double x4, double y4, double z4,
237  std::vector<double> &x, std::vector<double> &y, std::vector<double> &z,
238  std::vector<bool> &hull, size_t level)
239 {
240  // TODO: Assert that the vectors have the correct size;
241  size_t counter = 0;
242  for (size_t j = 0; j < level+1; ++j)
243  {
244  for (size_t i = 0; i < level+1; ++i)
245  {
246  // equidistant (is this irrelevant?)
247  // double r = -1.0 + (2.0 / level) * i;
248  // double s = -1.0 + (2.0 / level) * j;
249 
250  // equiangular
251  const double pi4 = Consts::PI*0.25;
252  const double x0 = -pi4 + static_cast<double>(i) * 2.0 * static_cast<double>(pi4)/static_cast<double>(level);
253  const double y0 = -pi4 + static_cast<double>(j) * 2.0 * static_cast<double>(pi4)/static_cast<double>(level);
254  const double r = std::tan(x0);
255  const double s = std::tan(y0);
256 
257 
258  const double N1 = 0.25 * (1.0 - r) * (1.0 - s);
259  const double N2 = 0.25 * (1.0 + r) * (1.0 - s);
260  const double N3 = 0.25 * (1.0 + r) * (1.0 + s);
261  const double N4 = 0.25 * (1.0 - r) * (1.0 + s);
262 
263  x[counter] = x1 * N1 + x2 * N2 + x3 * N3 + x4 * N4;
264  y[counter] = y1 * N1 + y2 * N2 + y3 * N3 + y4 * N4;
265  z[counter] = z1 * N1 + z2 * N2 + z3 * N3 + z4 * N4;
266 
267  if (i == 0) hull[counter] = true;
268  if (j == 0) hull[counter] = true;
269  if (i == level) hull[counter] = true;
270  if (j == level) hull[counter] = true;
271  counter++;
272  }
273  }
274 }
275 
276 
277 std::vector<std::string> get_command_line_options_vector(int argc, char **argv)
278 {
279  std::vector<std::string> vector;
280  for (int i=1; i < argc; ++i)
281  vector.emplace_back(argv[i]);
282 
283  return vector;
284 }
285 
286 bool find_command_line_option(char **begin, char **end, const std::string &option)
287 {
288  return std::find(begin, end, option) != end;
289 }
290 
291 int main(int argc, char **argv)
292 {
293 
294 #ifndef NDEBUG
295 #ifdef WB_USE_FP_EXCEPTIONS
296  // Some implementations seem to not initialize the floating point exception
297  // bits to zero. Make sure we start from a clean state.
298  feclearexcept(FE_DIVBYZERO|FE_INVALID);
299 
300  // enable floating point exceptions
301  feenableexcept(FE_DIVBYZERO|FE_INVALID);
302 #endif
303 #endif
304 
308  std::string wb_file;
309  std::string data_file;
310 
311  // If set to true, we will output one visualization file per "tag"
312  // with only the cells corresponding to that tag included.
313  bool output_by_tag = false;
314  // If set to true, we output a .filtered.vtu file without the background/mantle
315  bool output_filtered = false;
316 
317  size_t dim = 3;
318  size_t compositions = 0;
319 
320  // common
321  std::string grid_type = "chunk";
322 
323  size_t n_cell_x = NaN::ISNAN; // x or long
324  size_t n_cell_y = NaN::ISNAN; // y or lat
325  size_t n_cell_z = NaN::ISNAN; // z or depth
326 
327 
328  // spherical
329  double x_min = NaN::DSNAN; // x or long
330  double x_max = NaN::DSNAN; // x or long
331  double y_min = NaN::DSNAN; // y or lat
332  double y_max = NaN::DSNAN; // y or lat
333  double z_min = NaN::DSNAN; // z or inner_radius
334  double z_max = NaN::DSNAN; // z or outer_radius
335 
336  // Conservative choice for the number of threads to use:
337  size_t number_of_threads = std::min(20u,1+std::thread::hardware_concurrency()/2);
338  unsigned int max_resolution = std::numeric_limits<unsigned int>::max();
339 
340  try
341  {
342  if (find_command_line_option(argv, argv+argc, "-v") || find_command_line_option(argv, argv+argc, "--version"))
343  {
344  std::cout << "World Builder Grid Visualization tool.\n"
345  << "GWB Version: " << WorldBuilder::Version::MAJOR << "."
346  << WorldBuilder::Version::MINOR << "."
347  << WorldBuilder::Version::PATCH << "."
348  << WorldBuilder::Version::LABEL << "\n"
349  << "git hash: " << WorldBuilder::Version::GIT_SHA1 << " branch: " << WorldBuilder::Version::GIT_BRANCH
350  << std::endl;
351  return 0;
352  }
353 
354  if (find_command_line_option(argv, argv+argc, "-h") || find_command_line_option(argv, argv+argc, "--help"))
355  {
356  std::cout << "World Builder Grid Visualization tool.\n"
357  << "This program loads a world builder file and generates a visualization on a structured grid "
358  << "based on information specified in a separate .grid configuration file.\n\n"
359  << "Usage:\n"
360  << argv[0] << " [-j N] [--filtered] [--by-tag] example.wb example.grid\n\n"
361  << "Available options:\n"
362  << " -j N Specify the number of threads the visualizer is allowed to use. Default: " << number_of_threads << ".\n"
363  << " --filtered Also produce a .filtered.vtu that removes cells only containing mantle or background.\n"
364  << " --by-tag Also produce a sequence of .N.vtu files that only contain cells of a specific tag.\n"
365  << " --resolution-limit X Specify a maximum resolution."
366  << " -h or --help To get this help screen.\n"
367  << " -v or --version To see version information.\n";
368  return 0;
369  }
370 
371  std::vector<std::string> options_vector = get_command_line_options_vector(argc, argv);
372 
373  for (size_t i = 0; i < options_vector.size(); ++i)
374  {
375  if (options_vector[i] == "-j")
376  {
377  number_of_threads = Utilities::string_to_unsigned_int(options_vector[i+1]);
378  options_vector.erase(options_vector.begin()+static_cast<std::vector<std::string>::difference_type>(i));
379  options_vector.erase(options_vector.begin()+static_cast<std::vector<std::string>::difference_type>(i));
380  --i;
381  continue;
382  }
383  if (options_vector[i] == "--filtered")
384  {
385  output_filtered = true;
386  options_vector.erase(options_vector.begin()+static_cast<std::vector<std::string>::difference_type>(i));
387  --i;
388  continue;
389  }
390  if (options_vector[i] == "--by-tag")
391  {
392  output_by_tag = true;
393  options_vector.erase(options_vector.begin()+static_cast<std::vector<std::string>::difference_type>(i));
394  --i;
395  continue;
396  }
397  if (options_vector[i] == "--resolution-limit")
398  {
399  max_resolution = Utilities::string_to_unsigned_int(options_vector[i+1]);
400  options_vector.erase(options_vector.begin()+static_cast<std::vector<std::string>::difference_type>(i));
401  options_vector.erase(options_vector.begin()+static_cast<std::vector<std::string>::difference_type>(i));
402  --i;
403  continue;
404  }
405  }
406 
407  if (options_vector.size() != 2)
408  {
409  std::cout << "World Builder Grid Visualization tool.\n"
410  << "Usage: " << argv[0] << " example.wb example.grid\n"
411  << "Try '" << argv[0] << " --help' for more information." << std::endl;
412  return 0;
413  }
414 
415 
416  wb_file = options_vector[0];
417  data_file = options_vector[1];
418 
419  }
420  catch (std::exception &e)
421  {
422  std::cerr << "error: " << e.what() << "\n";
423  return 1;
424  }
425  catch (...)
426  {
427  std::cerr << "Exception of unknown type!\n";
428  return 1;
429  }
430 
431 
432  int MPI_RANK = 0;
433 #ifdef WB_WITH_MPI
434  MPI_Init(&argc,&argv);
435  MPI_Comm_rank(MPI_COMM_WORLD, &MPI_RANK);
436 #endif
437 
438  std::cout << "[1/6] Parsing file... \r";
439 
440  if (MPI_RANK == 0)
441  {
445  std::cout << "[2/6] Starting the world builder with " << number_of_threads << " threads... \r";
446  std::cout.flush();
447 
448  std::unique_ptr<WorldBuilder::World> world;
449  try
450  {
451  world = std::make_unique<WorldBuilder::World>(wb_file);
452  }
453  catch (std::exception &e)
454  {
455  std::cerr << "Could not start the World builder from file '" << wb_file << "', error: " << e.what() << "\n";
456 
457 #ifdef WB_WITH_MPI
458  MPI_Finalize();
459 #endif
460  return 1;
461  }
462  catch (...)
463  {
464  std::cerr << "Exception of unknown type!\n";
465 
466 #ifdef WB_WITH_MPI
467  MPI_Finalize();
468 #endif
469  return 1;
470  }
471 
475  ThreadPool pool(number_of_threads);
476 
480  std::cout << "[3/6] Reading grid file... \r";
481  std::cout.flush();
482 
483 
484  std::ifstream data_stream(data_file);
485 
486  // if config file is available, parse it
487  WBAssertThrow(data_stream.good(),
488  "Could not find the provided config file at the specified location: " + data_file);
489 
490 
491  // move the data into a vector of strings
492  std::vector<std::vector<std::string> > data;
493  std::string temp;
494 
495  while (std::getline(data_stream, temp))
496  {
497  std::istringstream buffer(temp);
498  std::vector<std::string> line((std::istream_iterator<std::string>(buffer)),
499  std::istream_iterator<std::string>());
500 
501  // remove the comma's in case it is a comma separated file.
502  // TODO: make it split for comma's and/or spaces
503  for (auto &line_i : line)
504  line_i.erase(std::remove(line_i.begin(), line_i.end(), ','), line_i.end());
505 
506  data.push_back(line);
507  }
508 
509  std::string vtu_output_format = "ASCII";//"RawBinaryCompressed";
510  // Read config from data if present
511  for (auto &line_i : data)
512  {
513  if (line_i.empty())
514  continue;
515 
516  if (line_i[0] == "#")
517  continue;
518 
519  if (line_i[0] == "grid_type" && line_i[1] == "=")
520  {
521  grid_type = line_i[2];
522  }
523 
524  if (line_i[0] == "dim" && line_i[1] == "=")
525  {
526  dim = string_to_unsigned_int(line_i[2]);
527  }
528 
529  if (line_i[0] == "vtu_output_format" && line_i[1] == "=")
530  {
531  vtu_output_format = line_i[2];
532  }
533 
534  if (line_i[0] == "compositions" && line_i[1] == "=")
535  compositions = string_to_unsigned_int(line_i[2]);
536 
537  if (line_i[0] == "x_min" && line_i[1] == "=")
538  x_min = string_to_double(line_i[2]);
539  if (line_i[0] == "x_max" && line_i[1] == "=")
540  x_max = string_to_double(line_i[2]);
541  if (line_i[0] == "y_min" && line_i[1] == "=")
542  y_min = string_to_double(line_i[2]);
543  if (line_i[0] == "y_max" && line_i[1] == "=")
544  y_max = string_to_double(line_i[2]);
545  if (line_i[0] == "z_min" && line_i[1] == "=")
546  z_min = string_to_double(line_i[2]);
547  if (line_i[0] == "z_max" && line_i[1] == "=")
548  z_max = string_to_double(line_i[2]);
549 
550  if (line_i[0] == "n_cell_x" && line_i[1] == "=")
551  n_cell_x = std::min(string_to_unsigned_int(line_i[2]),max_resolution);
552  if (line_i[0] == "n_cell_y" && line_i[1] == "=")
553  n_cell_y = std::min(string_to_unsigned_int(line_i[2]),max_resolution);
554  if (line_i[0] == "n_cell_z" && line_i[1] == "=")
555  n_cell_z = std::min(string_to_unsigned_int(line_i[2]),max_resolution);
556 
557  }
558 
559  WBAssertThrow(dim == 2 || dim == 3, "dim should be set in the grid file and can only be 2 or 3.");
560 
561  WBAssertThrow(!std::isnan(x_min), "x_min is not a number:" << x_min << ". This value has probably not been provided in the grid file.");
562  WBAssertThrow(!std::isnan(x_max), "x_max is not a number:" << x_max << ". This value has probably not been provided in the grid file.");
563  WBAssertThrow(dim == 2 || !std::isnan(y_min), "y_min is not a number:" << y_min << ". This value has probably not been provided in the grid file.");
564  WBAssertThrow(dim == 2 || !std::isnan(y_max), "y_max is not a number:" << y_max << ". This value has probably not been provided in the grid file.");
565  WBAssertThrow(!std::isnan(z_min), "z_min is not a number:" << z_min << ". This value has probably not been provided in the grid file.");
566  WBAssertThrow(!std::isnan(z_max), "z_max is not a number:" << z_max << ". This value has probably not been provided in the grid file.");
567 
568 
569  WBAssertThrow(n_cell_x != 0, "n_cell_z may not be equal to zero: " << n_cell_x << '.');
570  // int's cannot generally be nan's (see https://stackoverflow.com/questions/3949457/can-an-integer-be-nan-in-c),
571  // but visual studio is giving problems over this, so it is taken out for now.
572  //WBAssertThrow(!std::isnan(n_cell_x), "n_cell_z is not a number:" << n_cell_x << '.');
573 
574  WBAssertThrow(dim == 3 || n_cell_z != 0, "In 3d n_cell_z may not be equal to zero: " << n_cell_y << '.');
575  // int's cannot generally be nan's (see https://stackoverflow.com/questions/3949457/can-an-integer-be-nan-in-c),
576  // but visual studio is giving problems over this, so it is taken out for now.
577  //WBAssertThrow(!std::isnan(n_cell_z), "n_cell_z is not a number:" << n_cell_y << '.');
578 
579  WBAssertThrow(n_cell_z != 0, "n_cell_z may not be equal to zero: " << n_cell_z << '.');
580  // int's cannot generally be nan's (see https://stackoverflow.com/questions/3949457/can-an-integer-be-nan-in-c),
581  // but visual studio is giving problems over this, so it is taken out for now.
582  //WBAssertThrow(!std::isnan(n_cell_z), "n_cell_z is not a number:" << n_cell_z << '.');
583 
584 
585 
586 
587 
592  if (grid_type == "sphere")
593  WBAssert(n_cell_x == n_cell_y, "For the sphere grid the amount of cells in the x (long) and y (lat) direction have to be the same.");
594 
595  if (grid_type == "spherical" ||
596  grid_type == "chunk" ||
597  grid_type == "annulus")
598  {
599  x_min *= (Consts::PI/180);
600  x_max *= (Consts::PI/180);
601  y_min *= (Consts::PI/180);
602  y_max *= (Consts::PI/180);
603  }
604 
605 
606 
610  size_t n_cell = NaN::ISNAN;
611  size_t n_p = NaN::ISNAN;
612 
613  std::vector<double> grid_x(0);
614  std::vector<double> grid_y(0);
615  std::vector<double> grid_z(0);
616  std::vector<double> grid_depth(0);
617 
618  std::vector<std::vector<size_t> > grid_connectivity(0);
619 
620 
621  const bool compress_size = true;
622 
623 
624 
625 
629  std::cout << "[4/6] Building the grid... \r";
630  std::cout.flush();
631  WBAssertThrow(dim == 2 || dim == 3, "Dimension should be 2d or 3d.");
632  if (grid_type == "cartesian")
633  {
634  n_cell = n_cell_x * n_cell_z * (dim == 3 ? n_cell_y : 1);
635  if (!compress_size && dim == 3)
636  n_p = n_cell * 8 ; // it shouldn't matter for 2d in the output, so just do 3d.
637  else
638  n_p = (n_cell_x + 1) * (n_cell_z + 1) * (dim == 3 ? (n_cell_y + 1) : 1);
639 
640 
641  const double dx = (x_max - x_min) / static_cast<double>(n_cell_x);
642  const double dy = dim == 2 ? 0 : (y_max - y_min) / static_cast<double>(n_cell_y);
643  const double dz = (z_max - z_min) / static_cast<double>(n_cell_z);
644 
645 
646  WBAssertThrow(!std::isnan(dx), "dz is not a number:" << dz << '.');
647  WBAssertThrow(dim == 2 || !std::isnan(dy), "dz is not a number:" << dz << '.');
648  WBAssertThrow(!std::isnan(dz), "dz is not a number:" << dz << '.');
649 
650  // todo: determine whether a input variable is desirable for this.
651  const double surface = z_max;
652 
653  grid_x.resize(n_p);
654  grid_z.resize(n_p);
655 
656  if (dim == 3)
657  grid_y.resize(n_p);
658 
659  grid_depth.resize(n_p);
660 
661  // compute positions
662  size_t counter = 0;
663  if (dim == 2)
664  {
665  for (size_t j = 0; j <= n_cell_z; ++j)
666  {
667  for (size_t i = 0; i <= n_cell_x; ++i)
668  {
669  grid_x[counter] = x_min + static_cast<double>(i) * dx;
670  grid_z[counter] = z_min + static_cast<double>(j) * dz;
671  grid_depth[counter] = (surface - z_min) - static_cast<double>(j) * dz;
672  counter++;
673  }
674  }
675  }
676  else
677  {
678  if (compress_size)
679  {
680  for (size_t i = 0; i <= n_cell_x; ++i)
681  {
682  for (size_t j = 0; j <= n_cell_y; ++j)
683  {
684  for (size_t k = 0; k <= n_cell_z; ++k)
685  {
686  grid_x[counter] = x_min + static_cast<double>(i) * dx;
687  grid_y[counter] = y_min + static_cast<double>(j) * dy;
688  grid_z[counter] = z_min + static_cast<double>(k) * dz;
689  grid_depth[counter] = (surface - z_min) - static_cast<double>(k) * dz;
690  counter++;
691  }
692  }
693  }
694  }
695  else
696  {
697  for (size_t i = 0; i < n_cell_x; ++i)
698  {
699  for (size_t j = 0; j < n_cell_y; ++j)
700  {
701  for (size_t k = 0; k < n_cell_z; ++k)
702  {
703  // position is defined by the vtk file format
704  // position 0 of this cell
705  grid_x[counter] = x_min + static_cast<double>(i) * dx;
706  grid_y[counter] = y_min + static_cast<double>(j) * dy;
707  grid_z[counter] = z_min + static_cast<double>(k) * dz;
708  grid_depth[counter] = (surface - z_min) - static_cast<double>(k) * dz;
709  counter++;
710  // position 1 of this cell
711  grid_x[counter] = x_min + (static_cast<double>(i) + 1.0) * dx;
712  grid_y[counter] = y_min + static_cast<double>(j) * dy;
713  grid_z[counter] = z_min + static_cast<double>(k) * dz;
714  grid_depth[counter] = (surface - z_min) - static_cast<double>(k) * dz;
715  counter++;
716  // position 2 of this cell
717  grid_x[counter] = x_min + (static_cast<double>(i) + 1.0) * dx;
718  grid_y[counter] = y_min + (static_cast<double>(j) + 1.0) * dy;
719  grid_z[counter] = z_min + static_cast<double>(k) * dz;
720  grid_depth[counter] = (surface - z_min) - static_cast<double>(k) * dz;
721  counter++;
722  // position 3 of this cell
723  grid_x[counter] = x_min + static_cast<double>(i) * dx;
724  grid_y[counter] = y_min + (static_cast<double>(j) + 1.0) * dy;
725  grid_z[counter] = z_min + static_cast<double>(k) * dz;
726  grid_depth[counter] = (surface - z_min) - static_cast<double>(k) * dz;
727  counter++;
728  // position 0 of this cell
729  grid_x[counter] = x_min + static_cast<double>(i) * dx;
730  grid_y[counter] = y_min + static_cast<double>(j) * dy;
731  grid_z[counter] = z_min + (static_cast<double>(k) + 1.0) * dz;
732  grid_depth[counter] = (surface - z_min) - (static_cast<double>(k) + 1.0) * dz;
733  counter++;
734  // position 1 of this cell
735  grid_x[counter] = x_min + (static_cast<double>(i) + 1.0) * dx;
736  grid_y[counter] = y_min + static_cast<double>(j) * dy;
737  grid_z[counter] = z_min + (static_cast<double>(k) + 1.0) * dz;
738  grid_depth[counter] = (surface - z_min) - (static_cast<double>(k) + 1.0) * dz;
739  counter++;
740  // position 2 of this cell
741  grid_x[counter] = x_min + (static_cast<double>(i) + 1.0) * dx;
742  grid_y[counter] = y_min + (static_cast<double>(j) + 1.0) * dy;
743  grid_z[counter] = z_min + (static_cast<double>(k) + 1.0) * dz;
744  grid_depth[counter] = (surface - z_min) - (static_cast<double>(k) + 1.0) * dz;
745  counter++;
746  // position 3 of this cell
747  grid_x[counter] = x_min + static_cast<double>(i) * dx;
748  grid_y[counter] = y_min + (static_cast<double>(j) + 1.0) * dy;
749  grid_z[counter] = z_min + (static_cast<double>(k) + 1.0) * dz;
750  grid_depth[counter] = (surface - z_min) - (static_cast<double>(k) + 1.0) * dz;
751  WBAssert(counter < n_p, "Assert counter smaller then n_P: counter = " << counter << ", n_p = " << n_p);
752  counter++;
753  }
754  }
755  }
756  }
757  }
758 
759  // compute connectivity. Local to global mapping.
760  grid_connectivity.resize(n_cell,std::vector<size_t>((dim-1)*4));
761 
762  counter = 0;
763  if (dim == 2)
764  {
765  for (size_t j = 1; j <= n_cell_z; ++j)
766  {
767  for (size_t i = 1; i <= n_cell_x; ++i)
768  {
769  grid_connectivity[counter][0] = i + (j - 1) * (n_cell_x + 1) - 1;
770  grid_connectivity[counter][1] = i + 1 + (j - 1) * (n_cell_x + 1) - 1;
771  grid_connectivity[counter][2] = i + 1 + j * (n_cell_x + 1) - 1;
772  grid_connectivity[counter][3] = i + j * (n_cell_x + 1) - 1;
773  counter++;
774  }
775  }
776  }
777  else
778  {
779  if (compress_size)
780  {
781  for (size_t i = 1; i <= n_cell_x; ++i)
782  {
783  for (size_t j = 1; j <= n_cell_y; ++j)
784  {
785  for (size_t k = 1; k <= n_cell_z; ++k)
786  {
787  grid_connectivity[counter][0] = (n_cell_y + 1) * (n_cell_z + 1) * (i - 1) + (n_cell_z + 1) * (j - 1) + k - 1;
788  grid_connectivity[counter][1] = (n_cell_y + 1) * (n_cell_z + 1) * (i ) + (n_cell_z + 1) * (j - 1) + k - 1;
789  grid_connectivity[counter][2] = (n_cell_y + 1) * (n_cell_z + 1) * (i ) + (n_cell_z + 1) * (j ) + k - 1;
790  grid_connectivity[counter][3] = (n_cell_y + 1) * (n_cell_z + 1) * (i - 1) + (n_cell_z + 1) * (j ) + k - 1;
791  grid_connectivity[counter][4] = (n_cell_y + 1) * (n_cell_z + 1) * (i - 1) + (n_cell_z + 1) * (j - 1) + k;
792  grid_connectivity[counter][5] = (n_cell_y + 1) * (n_cell_z + 1) * (i ) + (n_cell_z + 1) * (j - 1) + k;
793  grid_connectivity[counter][6] = (n_cell_y + 1) * (n_cell_z + 1) * (i ) + (n_cell_z + 1) * (j ) + k;
794  grid_connectivity[counter][7] = (n_cell_y + 1) * (n_cell_z + 1) * (i - 1) + (n_cell_z + 1) * (j ) + k;
795  counter++;
796  }
797  }
798  }
799  }
800  else
801  {
802  for (size_t i = 0; i < n_cell; ++i)
803  {
804  grid_connectivity[i][0] = counter;
805  grid_connectivity[i][1] = counter + 1;
806  grid_connectivity[i][2] = counter + 2;
807  grid_connectivity[i][3] = counter + 3;
808  grid_connectivity[i][4] = counter + 4;
809  grid_connectivity[i][5] = counter + 5;
810  grid_connectivity[i][6] = counter + 6;
811  grid_connectivity[i][7] = counter + 7;
812  counter = counter + 8;
813  }
814  }
815  }
816  }
817  else if (grid_type == "annulus")
818  {
823  WBAssertThrow(dim == 2, "The annulus only works in 2d.");
824 
825 
826  const double inner_radius = z_min;
827  const double outer_radius = z_max;
828 
829  const double l_outer = 2.0 * Consts::PI * outer_radius;
830 
831  const double lr = outer_radius - inner_radius;
832  const double dr = lr / static_cast<double>(n_cell_z);
833 
834  const size_t n_cell_t = static_cast<size_t>((2.0 * Consts::PI * outer_radius)/dr);
835 
836  // compute the amount of cells
837  n_cell = n_cell_t *n_cell_z;
838  n_p = n_cell_t *(n_cell_z + 1); // one less then cartesian because two cells overlap.
839 
840  const double sx = l_outer / static_cast<double>(n_cell_t);
841  const double sz = dr;
842 
843  grid_x.resize(n_p);
844  grid_z.resize(n_p);
845  grid_depth.resize(n_p);
846 
847  size_t counter = 0;
848  for (size_t j = 0; j <= n_cell_z; ++j)
849  {
850  for (size_t i = 1; i <= n_cell_t; ++i)
851  {
852  grid_x[counter] = (static_cast<double>(i) - 1.0) * sx;
853  grid_z[counter] = static_cast<double>(j) * sz;
854  counter++;
855  }
856  }
857 
858  counter = 0;
859  for (size_t j = 1; j <= n_cell_z+1; ++j)
860  {
861  for (size_t i = 1; i <= n_cell_t; ++i)
862  {
863  const double xi = grid_x[counter];
864  const double zi = grid_z[counter];
865  const double theta = xi / l_outer * 2.0 * Consts::PI;
866  grid_x[counter] = std::cos(theta) * (inner_radius + zi);
867  grid_z[counter] = std::sin(theta) * (inner_radius + zi);
868  grid_depth[counter] = outer_radius - std::sqrt(grid_x[counter] * grid_x[counter] + grid_z[counter] * grid_z [counter]);
869  grid_depth[counter] = (std::fabs(grid_depth[counter]) < 1e-8 ? 0 : grid_depth[counter]);
870  counter++;
871  }
872  }
873 
874  grid_connectivity.resize(n_cell,std::vector<size_t>(4));
875  counter = 0;
876  for (size_t j = 1; j <= n_cell_z; ++j)
877  {
878  for (size_t i = 1; i <= n_cell_t; ++i)
879  {
880  std::vector<size_t> cell_connectivity(4);
881  cell_connectivity[0] = counter + 1;
882  cell_connectivity[1] = counter + 1 + 1;
883  cell_connectivity[2] = i + j * n_cell_t + 1;
884  cell_connectivity[3] = i + j * n_cell_t;
885  if (i == n_cell_t)
886  {
887  cell_connectivity[1] = cell_connectivity[1] - n_cell_t;
888  cell_connectivity[2] = cell_connectivity[2] - n_cell_t;
889  }
890  grid_connectivity[counter][0] = cell_connectivity[1] - 1;
891  grid_connectivity[counter][1] = cell_connectivity[0] - 1;
892  grid_connectivity[counter][2] = cell_connectivity[3] - 1;
893  grid_connectivity[counter][3] = cell_connectivity[2] - 1;
894  counter++;
895  }
896  }
897  }
898  else if (grid_type == "chunk")
899  {
900  const double inner_radius = z_min;
901  const double outer_radius = z_max;
902 
903  WBAssertThrow(x_min <= x_max, "The minimum longitude must be less than the maximum longitude.");
904  WBAssertThrow(y_min <= y_max, "The minimum latitude must be less than the maximum latitude.");
905  WBAssertThrow(inner_radius < outer_radius, "The inner radius must be less than the outer radius.");
906 
907  WBAssertThrow(x_min - x_max <= 2.0 * Consts::PI, "The difference between the minimum and maximum longitude "
908  " must be less than or equal to 360 degree.");
909 
910  WBAssertThrow(y_min >= - 0.5 * Consts::PI, "The minimum latitude must be larger then or equal to -90 degree.");
911  WBAssertThrow(y_min <= 0.5 * Consts::PI, "The maximum latitude must be smaller then or equal to 90 degree.");
912 
913  const double opening_angle_long_rad = (x_max - x_min);
914  const double opening_angle_lat_rad = (y_max - y_min);
915 
916  n_cell = n_cell_x * n_cell_z * (dim == 3 ? n_cell_y : 1);
917  if (!compress_size && dim == 3)
918  n_p = n_cell * 8 ; // it shouldn't matter for 2d in the output, so just do 3d.
919  else
920  n_p = (n_cell_x + 1) * (n_cell_z + 1) * (dim == 3 ? (n_cell_y + 1) : 1);
921 
922  const double dlong = opening_angle_long_rad / static_cast<double>(n_cell_x);
923  const double dlat = dim == 3 ? opening_angle_lat_rad / static_cast<double>(n_cell_y) : 0.;
924  const double lr = outer_radius - inner_radius;
925  const double dr = lr / static_cast<double>(n_cell_z);
926 
927  grid_x.resize(n_p);
928  grid_y.resize(dim == 3 ? n_p : 0);
929  grid_z.resize(n_p);
930  grid_depth.resize(n_p);
931 
932  std::cout << "[4/6] Building the grid: stage 1 of 3 \r";
933  std::cout.flush();
934  size_t counter = 0;
935  if (dim == 2)
936  {
937  for (size_t i = 1; i <= n_cell_x + 1; ++i)
938  for (size_t j = 1; j <= n_cell_z + 1; ++j)
939  {
940  grid_x[counter] = x_min + (static_cast<double>(i) - 1.0) * dlong;
941  grid_z[counter] = inner_radius + (static_cast<double>(j) - 1.0) * dr;
942  grid_depth[counter] = lr - (static_cast<double>(j) - 1.0) * dr;
943  counter++;
944  }
945  }
946  else
947  {
948  if (compress_size)
949  {
950  for (size_t i = 1; i <= n_cell_x + 1; ++i)
951  for (size_t j = 1; j <= n_cell_y + 1; ++j)
952  for (size_t k = 1; k <= n_cell_z + 1; ++k)
953  {
954  grid_x[counter] = x_min + (static_cast<double>(i) - 1.0) * dlong;
955  grid_y[counter] = y_min + (static_cast<double>(j) - 1.0) * dlat;
956  grid_z[counter] = inner_radius + (static_cast<double>(k) - 1.0) * dr;
957  grid_depth[counter] = lr - (static_cast<double>(k) - 1.0) * dr;
958  counter++;
959  }
960  }
961  else
962  {
963  for (size_t i = 0; i < n_cell_x; ++i)
964  {
965  for (size_t j = 0; j < n_cell_y; ++j)
966  {
967  for (size_t k = 0; k < n_cell_z; ++k)
968  {
969  // position is defined by the vtk file format
970  // position 0 of this cell
971  grid_x[counter] = x_min + static_cast<double>(i) * dlong;
972  grid_y[counter] = y_min + static_cast<double>(j) * dlat;
973  grid_z[counter] = inner_radius + static_cast<double>(k) * dr;
974  grid_depth[counter] = lr - static_cast<double>(k) * dr;
975  counter++;
976  // position 1 of this cell
977  grid_x[counter] = x_min + (static_cast<double>(i) + 1.0) * dlong;
978  grid_y[counter] = y_min + static_cast<double>(j) * dlat;
979  grid_z[counter] = inner_radius + static_cast<double>(k) * dr;
980  grid_depth[counter] = lr - static_cast<double>(k) * dr;
981  counter++;
982  // position 2 of this cell
983  grid_x[counter] = x_min + (static_cast<double>(i) + 1.0) * dlong;
984  grid_y[counter] = y_min + (static_cast<double>(j) + 1.0) * dlat;
985  grid_z[counter] = inner_radius + static_cast<double>(k) * dr;
986  grid_depth[counter] = lr - static_cast<double>(k) * dr;
987  counter++;
988  // position 3 of this cell
989  grid_x[counter] = x_min + static_cast<double>(i) * dlong;
990  grid_y[counter] = y_min + (static_cast<double>(j) + 1.0) * dlat;
991  grid_z[counter] = inner_radius + static_cast<double>(k) * dr;
992  grid_depth[counter] = lr - static_cast<double>(k) * dr;
993  counter++;
994  // position 0 of this cell
995  grid_x[counter] = x_min + static_cast<double>(i) * dlong;
996  grid_y[counter] = y_min + static_cast<double>(j) * dlat;
997  grid_z[counter] = inner_radius + (static_cast<double>(k) + 1.0) * dr;
998  grid_depth[counter] = lr - (static_cast<double>(k) + 1.0) * dr;
999  counter++;
1000  // position 1 of this cell
1001  grid_x[counter] = x_min + (static_cast<double>(i) + 1.0) * dlong;
1002  grid_y[counter] = y_min + static_cast<double>(j) * dlat;
1003  grid_z[counter] = inner_radius + (static_cast<double>(k) + 1.0) * dr;
1004  grid_depth[counter] = lr - (static_cast<double>(k) + 1.0) * dr;
1005  counter++;
1006  // position 2 of this cell
1007  grid_x[counter] = x_min + (static_cast<double>(i) + 1.0) * dlong;
1008  grid_y[counter] = y_min + (static_cast<double>(j) + 1.0) * dlat;
1009  grid_z[counter] = inner_radius + (static_cast<double>(k) + 1.0) * dr;
1010  grid_depth[counter] = lr - (static_cast<double>(k) + 1.0) * dr;
1011  counter++;
1012  // position 3 of this cell
1013  grid_x[counter] = x_min + static_cast<double>(i) * dlong;
1014  grid_y[counter] = y_min + (static_cast<double>(j) + 1.0) * dlat;
1015  grid_z[counter] = inner_radius + (static_cast<double>(k) + 1.0) * dr;
1016  grid_depth[counter] = lr - (static_cast<double>(k) + 1.0) * dr;
1017  WBAssert(counter < n_p, "Assert counter smaller then n_P: counter = " << counter << ", n_p = " << n_p);
1018  counter++;
1019  }
1020  }
1021  }
1022  }
1023  }
1024 
1025  std::cout << "[4/6] Building the grid: stage 2 of 3 \r";
1026  std::cout.flush();
1027  if (dim == 2)
1028  {
1029  for (size_t i = 0; i < n_p; ++i)
1030  {
1031 
1032  const double longitude = grid_x[i];
1033  const double radius = grid_z[i];
1034 
1035  grid_x[i] = radius * std::cos(longitude);
1036  grid_z[i] = radius * std::sin(longitude);
1037  }
1038  }
1039  else
1040  {
1041  for (size_t i = 0; i < n_p; ++i)
1042  {
1043 
1044  const double longitude = grid_x[i];
1045  const double latitutde = grid_y[i];
1046  const double radius = grid_z[i];
1047 
1048  grid_x[i] = radius * std::cos(latitutde) * std::cos(longitude);
1049  grid_y[i] = radius * std::cos(latitutde) * std::sin(longitude);
1050  grid_z[i] = radius * std::sin(latitutde);
1051  }
1052  }
1053  std::cout << "[4/6] Building the grid: stage 3 of 3 \r";
1054  std::cout.flush();
1055  // compute connectivity. Local to global mapping.
1056  grid_connectivity.resize(n_cell,std::vector<size_t>((dim-1)*4));
1057 
1058  counter = 0;
1059  if (dim == 2)
1060  {
1061  for (size_t i = 1; i <= n_cell_x; ++i)
1062  {
1063  for (size_t j = 1; j <= n_cell_z; ++j)
1064  {
1065  grid_connectivity[counter][0] = (n_cell_z + 1) * (i - 1) + j - 1;
1066  grid_connectivity[counter][1] = (n_cell_z + 1) * (i - 1) + j;
1067  grid_connectivity[counter][2] = (n_cell_z + 1) * (i ) + j;
1068  grid_connectivity[counter][3] = (n_cell_z + 1) * (i ) + j - 1;
1069 
1070  counter = counter+1;
1071  std::cout << "[4/6] Building the grid: stage 3 of 3 [" << (static_cast<double>(i)/static_cast<double>(n_cell))*100.0 << "%] \r";
1072  std::cout.flush();
1073  }
1074  }
1075  }
1076  else
1077  {
1078  if (compress_size)
1079  {
1080  for (size_t i = 1; i <= n_cell_x; ++i)
1081  {
1082  for (size_t j = 1; j <= n_cell_y; ++j)
1083  {
1084  for (size_t k = 1; k <= n_cell_z; ++k)
1085  {
1086  grid_connectivity[counter][0] = (n_cell_y + 1) * (n_cell_z + 1) * (i - 1) + (n_cell_z + 1) * (j - 1) + k - 1;
1087  grid_connectivity[counter][1] = (n_cell_y + 1) * (n_cell_z + 1) * (i ) + (n_cell_z + 1) * (j - 1) + k - 1;
1088  grid_connectivity[counter][2] = (n_cell_y + 1) * (n_cell_z + 1) * (i ) + (n_cell_z + 1) * (j ) + k - 1;
1089  grid_connectivity[counter][3] = (n_cell_y + 1) * (n_cell_z + 1) * (i - 1) + (n_cell_z + 1) * (j ) + k - 1;
1090  grid_connectivity[counter][4] = (n_cell_y + 1) * (n_cell_z + 1) * (i - 1) + (n_cell_z + 1) * (j - 1) + k;
1091  grid_connectivity[counter][5] = (n_cell_y + 1) * (n_cell_z + 1) * (i ) + (n_cell_z + 1) * (j - 1) + k;
1092  grid_connectivity[counter][6] = (n_cell_y + 1) * (n_cell_z + 1) * (i ) + (n_cell_z + 1) * (j ) + k;
1093  grid_connectivity[counter][7] = (n_cell_y + 1) * (n_cell_z + 1) * (i - 1) + (n_cell_z + 1) * (j ) + k;
1094  counter++;
1095  }
1096  }
1097  }
1098  }
1099  else
1100  {
1101  for (size_t i = 0; i < n_cell; ++i)
1102  {
1103  grid_connectivity[i][0] = counter;
1104  grid_connectivity[i][1] = counter + 1;
1105  grid_connectivity[i][2] = counter + 2;
1106  grid_connectivity[i][3] = counter + 3;
1107  grid_connectivity[i][4] = counter + 4;
1108  grid_connectivity[i][5] = counter + 5;
1109  grid_connectivity[i][6] = counter + 6;
1110  grid_connectivity[i][7] = counter + 7;
1111  counter = counter + 8;
1112  std::cout << "[4/6] Building the grid: stage 3 of 3 [" << (static_cast<double>(i)/static_cast<double>(n_cell))*100.0 << "%] \r";
1113  std::cout.flush();
1114  }
1115  }
1116  }
1117  }
1118  else if (grid_type == "sphere")
1119  {
1120 
1121  WBAssertThrow(dim == 3, "The sphere only works in 3d.");
1122 
1123 
1124  const double inner_radius = z_min;
1125  const double outer_radius = z_max;
1126 
1127  const size_t n_block = 12;
1128 
1129  const size_t block_n_cell = n_cell_x*n_cell_x;
1130  const size_t block_n_p = (n_cell_x + 1) * (n_cell_x + 1);
1131  const size_t block_n_v = 4;
1132 
1133 
1134  std::vector<std::vector<double> > block_grid_x(n_block,std::vector<double>(block_n_p));
1135  std::vector<std::vector<double> > block_grid_y(n_block,std::vector<double>(block_n_p));
1136  std::vector<std::vector<double> > block_grid_z(n_block,std::vector<double>(block_n_p));
1137  std::vector<std::vector<std::vector<size_t> > > block_grid_connectivity(n_block,std::vector<std::vector<size_t> >(block_n_cell,std::vector<size_t>(block_n_v)));
1138  std::vector<std::vector<bool> > block_grid_hull(n_block,std::vector<bool>(block_n_p));
1139 
1143  for (size_t i_block = 0; i_block < n_block; ++i_block)
1144  {
1145  const size_t block_n_cell_x = n_cell_x;
1146  const size_t block_n_cell_y = n_cell_x;
1147  const double Lx = 1.0;
1148  const double Ly = 1.0;
1149 
1150  size_t counter = 0;
1151  for (size_t j = 0; j <= block_n_cell_y; ++j)
1152  {
1153  for (size_t i = 0; i <= block_n_cell_y; ++i)
1154  {
1155  block_grid_x[i_block][counter] = static_cast<double>(i) * Lx / static_cast<double>(block_n_cell_x);
1156  block_grid_y[i_block][counter] = static_cast<double>(j) * Ly / static_cast<double>(block_n_cell_y);
1157  block_grid_z[i_block][counter] = 0.0;
1158  counter++;
1159  }
1160  }
1161 
1162  counter = 0;
1163  // using i=1 and j=1 here because i an j are not used in lookup and storage
1164  // so the code can remain very similar to ghost and the cartesian code.
1165  for (size_t j = 1; j <= block_n_cell_y; ++j)
1166  {
1167  for (size_t i = 1; i <= block_n_cell_x; ++i)
1168  {
1169  block_grid_connectivity[i_block][counter][0] = i + (j - 1) * (block_n_cell_x + 1) - 1;
1170  block_grid_connectivity[i_block][counter][1] = i + 1 + (j - 1) * (block_n_cell_x + 1) - 1;
1171  block_grid_connectivity[i_block][counter][2] = i + 1 + j * (block_n_cell_x + 1) - 1;
1172  block_grid_connectivity[i_block][counter][3] = i + j * (block_n_cell_x + 1) - 1;
1173  counter++;
1174  }
1175  }
1176  }
1177 
1181  double radius = 1;
1182 
1183  // four corners
1184  double xA = -1.0;
1185  double yA = 0.0;
1186  double zA = -1.0 / std::sqrt(2.0);
1187 
1188  double xB = 1.0;
1189  double yB = 0.0;
1190  double zB = -1.0 / std::sqrt(2.0);
1191 
1192  double xC = 0.0;
1193  double yC = -1.0;
1194  double zC = 1.0 / std::sqrt(2.0);
1195 
1196  double xD = 0.0;
1197  double yD = 1.0;
1198  double zD = 1.0 / std::sqrt(2.0);
1199 
1200  // middles of faces
1201  double xM = (xA+xB+xC)/3.0;
1202  double yM = (yA+yB+yC)/3.0;
1203  double zM = (zA+zB+zC)/3.0;
1204 
1205  double xN = (xA+xD+xC)/3.0;
1206  double yN = (yA+yD+yC)/3.0;
1207  double zN = (zA+zD+zC)/3.0;
1208 
1209  double xP = (xA+xD+xB)/3.0;
1210  double yP = (yA+yD+yB)/3.0;
1211  double zP = (zA+zD+zB)/3.0;
1212 
1213  double xQ = (xC+xD+xB)/3.0;
1214  double yQ = (yC+yD+yB)/3.0;
1215  double zQ = (zC+zD+zB)/3.0;
1216 
1217  // middle of edges
1218  double xF = (xB+xC)/2.0;
1219  double yF = (yB+yC)/2.0;
1220  double zF = (zB+zC)/2.0;
1221 
1222  double xG = (xA+xC)/2.0;
1223  double yG = (yA+yC)/2.0;
1224  double zG = (zA+zC)/2.0;
1225 
1226  double xE = (xB+xA)/2.0;
1227  double yE = (yB+yA)/2.0;
1228  double zE = (zB+zA)/2.0;
1229 
1230  double xH = (xD+xC)/2.0;
1231  double yH = (yD+yC)/2.0;
1232  double zH = (zD+zC)/2.0;
1233 
1234  double xJ = (xD+xA)/2.0;
1235  double yJ = (yD+yA)/2.0;
1236  double zJ = (zD+zA)/2.0;
1237 
1238  double xK = (xD+xB)/2.0;
1239  double yK = (yD+yB)/2.0;
1240  double zK = (zD+zB)/2.0;
1241 
1242  // Making sure points A..Q are on a sphere
1243  project_on_sphere(radius,xA,yA,zA);
1244  project_on_sphere(radius,xB,yB,zB);
1245  project_on_sphere(radius,xC,yC,zC);
1246  project_on_sphere(radius,xD,yD,zD);
1247  project_on_sphere(radius,xE,yE,zE);
1248  project_on_sphere(radius,xF,yF,zF);
1249  project_on_sphere(radius,xG,yG,zG);
1250  project_on_sphere(radius,xH,yH,zH);
1251  project_on_sphere(radius,xJ,yJ,zJ);
1252  project_on_sphere(radius,xK,yK,zK);
1253  project_on_sphere(radius,xM,yM,zM);
1254  project_on_sphere(radius,xN,yN,zN);
1255  project_on_sphere(radius,xP,yP,zP);
1256  project_on_sphere(radius,xQ,yQ,zQ);
1257 
1258  lay_points(xM,yM,zM,xG,yG,zG,xA,yA,zA,xE,yE,zE,block_grid_x[0], block_grid_y[0], block_grid_z[0],block_grid_hull[0], n_cell_x);
1259  lay_points(xF,yF,zF,xM,yM,zM,xE,yE,zE,xB,yB,zB,block_grid_x[1], block_grid_y[1], block_grid_z[1],block_grid_hull[1], n_cell_x);
1260  lay_points(xC,yC,zC,xG,yG,zG,xM,yM,zM,xF,yF,zF,block_grid_x[2], block_grid_y[2], block_grid_z[2],block_grid_hull[2], n_cell_x);
1261  lay_points(xG,yG,zG,xN,yN,zN,xJ,yJ,zJ,xA,yA,zA,block_grid_x[3], block_grid_y[3], block_grid_z[3],block_grid_hull[3], n_cell_x);
1262  lay_points(xC,yC,zC,xH,yH,zH,xN,yN,zN,xG,yG,zG,block_grid_x[4], block_grid_y[4], block_grid_z[4],block_grid_hull[4], n_cell_x);
1263  lay_points(xH,yH,zH,xD,yD,zD,xJ,yJ,zJ,xN,yN,zN,block_grid_x[5], block_grid_y[5], block_grid_z[5],block_grid_hull[5], n_cell_x);
1264  lay_points(xA,yA,zA,xJ,yJ,zJ,xP,yP,zP,xE,yE,zE,block_grid_x[6], block_grid_y[6], block_grid_z[6],block_grid_hull[6], n_cell_x);
1265  lay_points(xJ,yJ,zJ,xD,yD,zD,xK,yK,zK,xP,yP,zP,block_grid_x[7], block_grid_y[7], block_grid_z[7],block_grid_hull[7], n_cell_x);
1266  lay_points(xP,yP,zP,xK,yK,zK,xB,yB,zB,xE,yE,zE,block_grid_x[8], block_grid_y[8], block_grid_z[8],block_grid_hull[8], n_cell_x);
1267  lay_points(xQ,yQ,zQ,xK,yK,zK,xD,yD,zD,xH,yH,zH,block_grid_x[9], block_grid_y[9], block_grid_z[9],block_grid_hull[9], n_cell_x);
1268  lay_points(xQ,yQ,zQ,xH,yH,zH,xC,yC,zC,xF,yF,zF,block_grid_x[10], block_grid_y[10], block_grid_z[10],block_grid_hull[10], n_cell_x);
1269  lay_points(xQ,yQ,zQ,xF,yF,zF,xB,yB,zB,xK,yK,zK,block_grid_x[11], block_grid_y[11], block_grid_z[11],block_grid_hull[11], n_cell_x);
1270 
1271  // make sure all points end up on a sphere
1272  for (size_t i_block = 0; i_block < n_block; ++i_block)
1273  {
1274  for (size_t i_point = 0; i_point < block_n_p; ++i_point)
1275  {
1276  project_on_sphere(radius,block_grid_x[i_block][i_point],block_grid_y[i_block][i_point],block_grid_z[i_block][i_point]);
1277  }
1278  }
1279 
1283  std::vector<double> temp_x(n_block * block_n_p);
1284  std::vector<double> temp_y(n_block * block_n_p);
1285  std::vector<double> temp_z(n_block * block_n_p);
1286  std::vector<bool> sides(n_block * block_n_p);
1287 
1288  for (size_t i = 0; i < n_block; ++i)
1289  {
1290  size_t counter = 0;
1291  for (size_t j = i * block_n_p; j < i * block_n_p + block_n_p; ++j)
1292  {
1293  WBAssert(j < temp_x.size(), "j should be smaller then the size of the array temp_x.");
1294  WBAssert(j < temp_y.size(), "j should be smaller then the size of the array temp_y.");
1295  WBAssert(j < temp_z.size(), "j should be smaller then the size of the array temp_z.");
1296  temp_x[j] = block_grid_x[i][counter];
1297  temp_y[j] = block_grid_y[i][counter];
1298  temp_z[j] = block_grid_z[i][counter];
1299  sides[j] = block_grid_hull[i][counter];
1300  counter++;
1301  }
1302  }
1303 
1304 
1305  std::vector<bool> double_points(n_block * block_n_p,false);
1306  std::vector<size_t> point_to(n_block * block_n_p);
1307 
1308  for (size_t i = 0; i < n_block * block_n_p; ++i)
1309  point_to[i] = i;
1310 
1311  // TODO: This becomes problematic with too large values of outer radius. Find a better way, maybe through an epsilon.
1312  const double distance = 1e-12*outer_radius;
1313 
1314  size_t counter = 0;
1315  size_t amount_of_double_points = 0;
1316  for (size_t i = 1; i < n_block * block_n_p; ++i)
1317  {
1318  if (sides[i])
1319  {
1320  const double gxip = temp_x[i];
1321  const double gyip = temp_y[i];
1322  const double gzip = temp_z[i];
1323  for (size_t j = 0; j < i-1; ++j)
1324  {
1325  if (sides[j])
1326  {
1327  if (std::fabs(gxip-temp_x[j]) < distance &&
1328  std::fabs(gyip-temp_y[j]) < distance &&
1329  std::fabs(gzip-temp_z[j]) < distance)
1330  {
1331  double_points[i] = true;
1332  point_to[i] = j;
1333  amount_of_double_points++;
1334  break;
1335  }
1336  }
1337  }
1338  }
1339  }
1340 
1341 
1342  const size_t shell_n_p = n_block * block_n_p - amount_of_double_points;
1343  const size_t shell_n_cell = n_block * block_n_cell;
1344  const size_t shell_n_v = block_n_v;
1345 
1346  std::vector<double> shell_grid_x(shell_n_p);
1347  std::vector<double> shell_grid_y(shell_n_p);
1348  std::vector<double> shell_grid_z(shell_n_p);
1349  std::vector<std::vector<size_t> > shell_grid_connectivity(shell_n_cell,std::vector<size_t>(shell_n_v));
1350 
1351  counter = 0;
1352  for (size_t i = 0; i < n_block * block_n_p; ++i)
1353  {
1354  if (!double_points[i])
1355  {
1356  shell_grid_x[counter] = fabs(temp_x[i]) < 1e-8 ? 0. : temp_x[i];
1357  shell_grid_y[counter] = fabs(temp_y[i]) < 1e-8 ? 0. : temp_y[i];
1358  shell_grid_z[counter] = fabs(temp_z[i]) < 1e-8 ? 0. : temp_z[i];
1359 
1360  counter++;
1361  }
1362  }
1363 
1364  for (size_t i = 0; i < n_block; ++i)
1365  {
1366  counter = 0;
1367  for (size_t j = i * block_n_cell; j < i * block_n_cell + block_n_cell; ++j)
1368  {
1369  for (size_t k = 0; k < shell_n_v; ++k)
1370  {
1371  shell_grid_connectivity[j][k] = block_grid_connectivity[i][counter][k] + i * block_n_p;
1372  }
1373  counter++;
1374  }
1375  }
1376 
1377  for (size_t i = 0; i < shell_n_cell; ++i)
1378  {
1379  for (size_t j = 0; j < shell_n_v; ++j)
1380  {
1381  shell_grid_connectivity[i][j] = point_to[shell_grid_connectivity[i][j]];
1382  }
1383  }
1384 
1385  std::vector<size_t> compact(n_block * block_n_p);
1386 
1387  counter = 0;
1388  for (size_t i = 0; i < n_block * block_n_p; ++i)
1389  {
1390  if (!double_points[i])
1391  {
1392  compact[i] = counter;
1393  counter++;
1394  }
1395  }
1396 
1397 
1398  for (size_t i = 0; i < shell_n_cell; ++i)
1399  {
1400  for (size_t j = 0; j < shell_n_v; ++j)
1401  {
1402  shell_grid_connectivity[i][j] = compact[shell_grid_connectivity[i][j]];
1403  }
1404  }
1405 
1406 
1411  std::vector<double> temp_shell_grid_x(shell_n_p);
1412  std::vector<double> temp_shell_grid_y(shell_n_p);
1413  std::vector<double> temp_shell_grid_z(shell_n_p);
1414 
1415  const size_t n_v = shell_n_v * 2;
1416  n_p = (n_cell_z + 1) * shell_n_p;
1417  n_cell = (n_cell_z) * shell_n_cell;
1418 
1419  grid_x.resize(n_p);
1420  grid_y.resize(n_p);
1421  grid_z.resize(n_p);
1422  grid_depth.resize(n_p);
1423  grid_connectivity.resize(n_cell,std::vector<size_t>(n_v));
1424 
1425 
1426  for (size_t i = 0; i < n_cell_z + 1; ++i)
1427  {
1428  temp_shell_grid_x = shell_grid_x;
1429  temp_shell_grid_y = shell_grid_y;
1430  temp_shell_grid_z = shell_grid_z;
1431 
1432  // We do not need to copy the shell_grid_connectivity into a
1433  // temperorary variable, because we do not change it. We can
1434  // directly use it.
1435 
1436  radius = inner_radius + ((outer_radius - inner_radius) / static_cast<double>(n_cell_z)) * static_cast<double>(i);
1437  for (size_t j = 0; j < shell_n_p; ++j)
1438  {
1439  WBAssert(j < temp_shell_grid_x.size(), "ERROR: j = " << j << ", temp_shell_grid_x.size() = " << temp_shell_grid_x.size());
1440  WBAssert(j < temp_shell_grid_y.size(), "ERROR: j = " << j << ", temp_shell_grid_y.size() = " << temp_shell_grid_y.size());
1441  WBAssert(j < temp_shell_grid_z.size(), "ERROR: j = " << j << ", temp_shell_grid_z.size() = " << temp_shell_grid_z.size());
1442  project_on_sphere(radius, temp_shell_grid_x[j], temp_shell_grid_y[j], temp_shell_grid_z[j]);
1443  }
1444 
1445  const size_t i_beg = i * shell_n_p;
1446  const size_t i_end = (i+1) * shell_n_p;
1447  counter = 0;
1448  for (size_t j = i_beg; j < i_end; ++j)
1449  {
1450  WBAssert(j < grid_x.size(), "ERROR: j = " << j << ", grid_x.size() = " << grid_x.size());
1451  WBAssert(j < grid_y.size(), "ERROR: j = " << j << ", grid_y.size() = " << grid_y.size());
1452  WBAssert(j < grid_z.size(), "ERROR: j = " << j << ", grid_z.size() = " << grid_z.size());
1453  grid_x[j] = temp_shell_grid_x[counter];
1454  grid_y[j] = temp_shell_grid_y[counter];
1455  grid_z[j] = temp_shell_grid_z[counter];
1456  grid_depth[j] = outer_radius - std::sqrt(grid_x[j] * grid_x[j] + grid_y[j] * grid_y[j] + grid_z[j] * grid_z[j]);
1457  grid_depth[j] = (std::fabs(grid_depth[j]) < 1e-8 ? 0 : grid_depth[j]);
1458 
1459  counter++;
1460  }
1461  }
1462 
1463  for (size_t i = 0; i < n_cell_z; ++i)
1464  {
1465  const size_t i_beg = i * shell_n_cell;
1466  const size_t i_end = (i+1) * shell_n_cell;
1467  counter = 0;
1468  for (size_t j = i_beg; j < i_end; ++j)
1469  {
1470  for (size_t k = 0; k < shell_n_v; ++k)
1471  {
1472  grid_connectivity[j][k] = shell_grid_connectivity[counter][k] + i * shell_n_p;
1473  }
1474  counter++;
1475  }
1476 
1477 
1478  counter = 0;
1479  for (size_t j = i_beg; j < i_end; ++j)
1480  {
1481  for (size_t k = shell_n_v ; k < 2 * shell_n_v; ++k)
1482  {
1483  WBAssert(k-shell_n_v < shell_grid_connectivity[counter].size(), "k - shell_n_v is larger then shell_grid_connectivity[counter]: k= " << k << ", shell_grid_connectivity[counter].size() = " << shell_grid_connectivity[counter].size());
1484  grid_connectivity[j][k] = shell_grid_connectivity[counter][k-shell_n_v] + (i+1) * shell_n_p;
1485  }
1486  counter++;
1487  }
1488  }
1489  }
1490  else
1491  {
1492  WBAssertThrow(false, "Geometry type '" << grid_type << "' is not a valid geometry type. Valid geometry types are: "
1493  << "'cartesian', 'annulus', 'chunk' and 'sphere'. "
1494  << "Please note that the annulus can only be used in 2d and the sphere can only be used in 3d.");
1495  }
1496 
1497  // create paraview file.
1498  std::cout << "[5/6] Preparing to write the paraview file... \r";
1499  std::cout.flush();
1500 
1501  const std::string base_filename = wb_file.substr(wb_file.find_last_of("/\\") + 1);
1502  std::string::size_type const p(base_filename.find_last_of('.'));
1503  const std::string file_without_extension = base_filename.substr(0, p);
1504 
1505  const std::stringstream buffer;
1506  const std::ofstream myfile;
1507 
1508  std::cout << "[5/6] Preparing to write the paraview file: stage 1 of 6, converting the points \r";
1509  std::cout.flush();
1510  std::vector<double> points(grid_x.size()*3, 0.0);
1511  if (dim == 2)
1512  for (size_t i = 0; i < n_p; ++i)
1513  {
1514  points[i*3] = grid_x[i];
1515  points[i*3+1] = grid_z[i];
1516  // third one is zero
1517  }
1518  else
1519  {
1520  for (size_t i = 0; i < n_p; ++i)
1521  {
1522  points[i*3] = grid_x[i];
1523  points[i*3+1] = grid_y[i];
1524  points[i*3+2] = grid_z[i];
1525  }
1526  }
1527  std::cout << "[5/6] Preparing to write the paraview file: stage 2 of 6, converting the connectivity \r";
1528  std::cout.flush();
1529  const size_t pow_2_dim = dim == 2 ? 4 : 8;
1530  std::vector<vtu11::VtkIndexType> connectivity(n_cell*pow_2_dim);
1531  if (dim == 2)
1532  for (size_t i = 0; i < n_cell; ++i)
1533  {
1534  connectivity[i*pow_2_dim] = static_cast<vtu11::VtkIndexType>(grid_connectivity[i][0]);
1535  connectivity[i*pow_2_dim+1] = static_cast<vtu11::VtkIndexType>(grid_connectivity[i][1]);
1536  connectivity[i*pow_2_dim+2] = static_cast<vtu11::VtkIndexType>(grid_connectivity[i][2]);
1537  connectivity[i*pow_2_dim+3] = static_cast<vtu11::VtkIndexType>(grid_connectivity[i][3]);
1538  }
1539  else
1540  for (size_t i = 0; i < n_cell; ++i)
1541  {
1542 
1543  connectivity[i*pow_2_dim] = static_cast<vtu11::VtkIndexType>(grid_connectivity[i][0]);
1544  connectivity[i*pow_2_dim+1] = static_cast<vtu11::VtkIndexType>(grid_connectivity[i][1]);
1545  connectivity[i*pow_2_dim+2] = static_cast<vtu11::VtkIndexType>(grid_connectivity[i][2]);
1546  connectivity[i*pow_2_dim+3] = static_cast<vtu11::VtkIndexType>(grid_connectivity[i][3]);
1547  connectivity[i*pow_2_dim+4] = static_cast<vtu11::VtkIndexType>(grid_connectivity[i][4]);
1548  connectivity[i*pow_2_dim+5] = static_cast<vtu11::VtkIndexType>(grid_connectivity[i][5]);
1549  connectivity[i*pow_2_dim+6] = static_cast<vtu11::VtkIndexType>(grid_connectivity[i][6]);
1550  connectivity[i*pow_2_dim+7] = static_cast<vtu11::VtkIndexType>(grid_connectivity[i][7]);
1551  }
1552  std::cout << "[5/6] Preparing to write the paraview file: stage 3 of 6, creating the offsets \r";
1553  std::cout.flush();
1554  std::vector<vtu11::VtkIndexType> offsets(n_cell);
1555  if (dim == 2)
1556  for (size_t i = 0; i < n_cell; ++i)
1557  offsets[i] = static_cast<vtu11::VtkIndexType>((i+1) * 4);
1558  else
1559  for (size_t i = 0; i < n_cell; ++i)
1560  offsets[i] = static_cast<vtu11::VtkIndexType>((i+1) * 8);
1561 
1562  std::cout << "[5/6] Preparing to write the paraview file: stage 4 of 6, creating the Data set info \r";
1563  std::cout.flush();
1564  std::vector<vtu11::VtkCellType> types(n_cell, dim == 2 ? 9 : 12);
1565 
1566  // Create tuples with (name, association, number of components) for each data set
1567  std::vector<vtu11::DataSetInfo> dataSetInfo
1568  {
1569  { "Depth", vtu11::DataSetType::PointData, 1 },
1570  { "Temperature", vtu11::DataSetType::PointData, 1 },
1571  { "velocity", vtu11::DataSetType::PointData, 3 },
1572  { "Tag", vtu11::DataSetType::PointData, 1 },
1573  };
1574  for (size_t c = 0; c < compositions; ++c)
1575  {
1576  dataSetInfo.emplace_back( "Composition "+std::to_string(c), vtu11::DataSetType::PointData, 1 );
1577  }
1578 
1579  std::cout << "[5/6] Preparing to write the paraview file: stage 5 of 5, computing the properties \r";
1580  std::cout.flush();
1581 
1582  std::vector<std::array<unsigned ,3>> properties;
1583  properties.push_back({{1,0,0}}); // temperature
1584 
1585  properties.push_back({{5,0,0}}); // velocity
1586 
1587  properties.push_back({{4,0,0}}); // tag
1588 
1589  for (unsigned int c = 0; c < compositions; ++c)
1590  properties.push_back({{2,c,0}}); // composition c
1591 
1592 
1593  // compute temperature
1594  std::vector<vtu11::DataSetData> data_set(4+compositions);
1595  data_set[0] = grid_depth;
1596  data_set[1].resize(n_p);
1597  data_set[2].resize(n_p*3);
1598  data_set[3].resize(n_p);
1599  for (size_t c = 0; c < compositions; ++c)
1600  data_set[4+c].resize(n_p);
1601 
1602  if (dim == 2)
1603  {
1604  pool.parallel_for(0, n_p, [&] (size_t i)
1605  {
1606  const std::array<double,2> coords = {{grid_x[i], grid_z[i]}};
1607  std::vector<double> output = world->properties(coords, grid_depth[i],properties);
1608  data_set[1][i] = output[0];
1609  data_set[2][3*i] = output[1];
1610  data_set[2][3*i+1] = output[2];
1611  data_set[2][3*i+2] = output[3];
1612  data_set[3][i] = output[4];
1613  for (size_t c = 0; c < compositions; ++c)
1614  {
1615  data_set[4+c][i] = output[5+c];
1616  }
1617  });
1618  }
1619  else
1620  {
1621  pool.parallel_for(0, n_p, [&] (size_t i)
1622  {
1623  const std::array<double,3> coords = {{grid_x[i], grid_y[i], grid_z[i]}};
1624  std::vector<double> output = world->properties(coords, grid_depth[i],properties);
1625  data_set[1][i] = output[0];
1626  data_set[2][3*i] = output[1];
1627  data_set[2][3*i+1] = output[2];
1628  data_set[2][3*i+2] = output[3];
1629  data_set[3][i] = output[4];
1630  for (size_t c = 0; c < compositions; ++c)
1631  {
1632  data_set[4+c][i] = output[5+c];
1633  }
1634  });
1635  }
1636  std::cout << "[6/6] Writing the paraview file \r";
1637  std::cout.flush();
1638 
1639  {
1640  vtu11::Vtu11UnstructuredMesh mesh { points, connectivity, offsets, types };
1641  vtu11::writeVtu( file_without_extension + ".vtu", mesh, dataSetInfo, data_set, vtu_output_format );
1642 
1643  if (output_filtered)
1644  {
1645  std::vector<bool> include_tag(world->feature_tags.size(), true);
1646  for (unsigned int idx = 0; idx<include_tag.size(); ++idx)
1647  {
1648  if (world->feature_tags[idx]=="mantle layer")
1649  include_tag[idx] = false;
1650  }
1651  std::vector<double> filtered_points;
1652  std::vector<vtu11::VtkIndexType> filtered_connectivity;
1653  std::vector<vtu11::VtkIndexType> filtered_offsets;
1654  std::vector<vtu11::VtkCellType> filtered_types;
1655 
1656  vtu11::Vtu11UnstructuredMesh filtered_mesh {filtered_points, filtered_connectivity, filtered_offsets, filtered_types};
1657  std::vector<vtu11::DataSetData> filtered_data_set;
1658 
1659  filter_vtu_mesh(static_cast<int>(dim), include_tag, mesh, data_set, filtered_mesh, filtered_data_set);
1660  vtu11::writeVtu( file_without_extension + ".filtered.vtu", filtered_mesh, dataSetInfo, filtered_data_set, vtu_output_format );
1661  }
1662 
1663  if (output_by_tag)
1664  {
1665  for (unsigned int idx = 0; idx<world->feature_tags.size(); ++idx)
1666  {
1667  if (world->feature_tags[idx]=="mantle layer")
1668  continue;
1669 
1670  std::vector<double> filtered_points;
1671  std::vector<vtu11::VtkIndexType> filtered_connectivity;
1672  std::vector<vtu11::VtkIndexType> filtered_offsets;
1673  std::vector<vtu11::VtkCellType> filtered_types;
1674 
1675  vtu11::Vtu11UnstructuredMesh filtered_mesh {filtered_points, filtered_connectivity, filtered_offsets, filtered_types};
1676  std::vector<vtu11::DataSetData> filtered_data_set;
1677 
1678  std::vector<bool> include_tag(world->feature_tags.size(), false);
1679  include_tag[idx]=true;
1680  filter_vtu_mesh(static_cast<int>(dim), include_tag, mesh, data_set, filtered_mesh, filtered_data_set);
1681  const std::string filename = file_without_extension + "."+ std::to_string(idx)+".vtu";
1682  vtu11::writeVtu( filename, filtered_mesh, dataSetInfo, filtered_data_set, vtu_output_format );
1683  }
1684  }
1685  }
1686  std::cout << " \r";
1687  std::cout.flush();
1688  }
1689 
1690 #ifdef WB_WITH_MPI
1691  MPI_Finalize();
1692 #endif
1693  return 0;
1694 }
const double DSNAN
Definition: nan.h:41
void project_on_sphere(double radius, double &x_, double &y_, double &z_)
Definition: main.cc:216
ThreadPool(size_t number_of_threads)
Definition: main.cc:161
void lay_points(double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3, double x4, double y4, double z4, std::vector< double > &x, std::vector< double > &y, std::vector< double > &z, std::vector< bool > &hull, size_t level)
Definition: main.cc:233
void parallel_for(size_t start, size_t end, Callable func)
Definition: main.cc:170
const unsigned int ISNAN
Definition: nan.h:46
bool find_command_line_option(char **begin, char **end, const std::string &option)
Definition: main.cc:49
#define WBAssert(condition, message)
Definition: assert.h:27
double norm() const
Definition: point.h:413
int main(int argc, char **argv)
Definition: main.cc:54
double cos(const double angle)
Definition: point.h:97
#define WBAssertThrow(condition, message)
Definition: assert.h:40
double string_to_double(const std::string &string)
Definition: utilities.cc:310
unsigned int string_to_unsigned_int(const std::string &string)
Definition: utilities.cc:349
std::vector< std::thread > pool
Definition: main.cc:211
double sin(const double raw_angle)
Definition: point.h:81
constexpr double PI
Definition: consts.h:30
void filter_vtu_mesh(int dim, const std::vector< bool > &include_tag, vtu11::Vtu11UnstructuredMesh &input_mesh, const std::vector< vtu11::DataSetData > &input_data, vtu11::Vtu11UnstructuredMesh &output_mesh, std::vector< vtu11::DataSetData > &output_data)
Definition: main.cc:82
std::vector< std::string > get_command_line_options_vector(int argc, char **argv)
Definition: main.cc:277