Loading [MathJax]/extensions/TeX/AMSmath.js
ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
LatticeWalberla.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2021-2023 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo 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 General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
22
24
25#include <blockforest/Initialization.h>
26#include <blockforest/StructuredBlockForest.h>
27#include <core/DataTypes.h>
28#include <core/cell/Cell.h>
29#include <domain_decomposition/IBlock.h>
30
31#include <utils/Vector.hpp>
32
33#include <cmath>
34#include <initializer_list>
35#include <limits>
36#include <optional>
37#include <stdexcept>
38#include <string>
39#include <utility>
40
42 Utils::Vector3i const &node_grid,
43 Utils::Vector3i const &block_grid,
44 unsigned int n_ghost_layers)
45 : m_grid_dimensions{grid_dimensions}, m_node_grid{node_grid},
46 m_n_ghost_layers{n_ghost_layers} {
47 using walberla::real_t;
48 using walberla::uint_c;
49
50 for (auto const i : {0u, 1u, 2u}) {
51 if (m_grid_dimensions[i] % node_grid[i] != 0) {
52 throw std::runtime_error(
53 "Lattice grid dimensions and MPI node grid are not compatible.");
54 }
55 if (m_grid_dimensions[i] % block_grid[i] != 0) {
56 throw std::runtime_error(
57 "Lattice grid dimensions and block grid are not compatible.");
58 }
59 }
60
61 auto constexpr lattice_constant = real_t{1};
62 auto const cells_per_block =
63 Utils::hadamard_division(grid_dimensions, block_grid);
64
65 m_blocks = walberla::blockforest::createUniformBlockGrid(
66 // number of blocks in each direction
67 uint_c(block_grid[0]), uint_c(block_grid[1]), uint_c(block_grid[2]),
68 // number of cells per block in each direction
69 uint_c(cells_per_block[0]), uint_c(cells_per_block[1]),
70 uint_c(cells_per_block[2]), lattice_constant,
71 // number of cpus per direction
72 uint_c(node_grid[0]), uint_c(node_grid[1]), uint_c(node_grid[2]),
73 // periodicity
74 true, true, true,
75 // keep global block information
76 false);
77 for (IBlock &block : *m_blocks) {
78 m_cached_blocks.push_back(&block);
79 }
80}
81
82[[nodiscard]] std::pair<Utils::Vector3d, Utils::Vector3d>
85 // Get upper and lower corner of BlockForest assigned to a mpi rank.
86 // Since we can allocate multiple blocks per mpi rank,
87 // the corners of all Blocks are compared.
88 auto aa = to_vector3d(m_blocks->begin()->getAABB().min());
89 auto bb = to_vector3d(m_blocks->begin()->getAABB().max());
90 for (auto const &block : *m_blocks) {
91 auto cc = block.getAABB();
92 for (auto const i : {0u, 1u, 2u}) {
93 aa[i] = std::min(aa[i], cc.min()[i]);
94 bb[i] = std::max(bb[i], cc.max()[i]);
95 }
96 }
97 return {aa, bb};
98}
99
100[[nodiscard]] std::pair<Utils::Vector3i, Utils::Vector3i>
102 auto const [lower_corner, upper_corner] = get_local_domain();
103 return {walberla::convert_cell_corner_to_coord(lower_corner),
105}
106
107[[nodiscard]] Utils::Vector3i
108LatticeWalberla::get_block_corner(IBlock const &block, bool lower) const {
109 if (lower) {
111 }
113}
114
115[[nodiscard]] bool
117 // Note: Lattice constant =1, cell centers offset by .5
118 return ::walberla::get_block_and_cell(*this, node, false) != std::nullopt;
119}
120[[nodiscard]] bool
122 return ::walberla::get_block_and_cell(*this, node, true) != std::nullopt;
123}
124[[nodiscard]] bool
126 return ::walberla::get_block(*this, pos, false) != nullptr;
127}
128[[nodiscard]] bool
130 return ::walberla::get_block(*this, pos, true) != nullptr;
131}
132
133[[nodiscard]] Utils::Vector3i
135 double agrid) {
136 auto const grid_dimensions =
137 Utils::Vector3i{{static_cast<int>(std::round(box_size[0] / agrid)),
138 static_cast<int>(std::round(box_size[1] / agrid)),
139 static_cast<int>(std::round(box_size[2] / agrid))}};
140 for (auto const i : {0u, 1u, 2u}) {
141 if (std::abs(grid_dimensions[i] * agrid - box_size[i]) / box_size[i] >
142 std::numeric_limits<double>::epsilon()) {
143 throw std::runtime_error(
144 "Box length not commensurate with agrid in direction " +
145 std::to_string(i) + " length " + std::to_string(box_size[i]) +
146 " agrid " + std::to_string(agrid));
147 }
148 }
149 return grid_dimensions;
150}
Vector implementation and trait types for boost qvm interoperability.
bool pos_in_local_halo(Utils::Vector3d const &pos) const
std::pair< Utils::Vector3i, Utils::Vector3i > get_local_grid_range() const
static Utils::Vector3i calc_grid_dimensions(Utils::Vector3d const &box_size, double agrid)
bool node_in_local_halo(Utils::Vector3i const &node) const
std::pair< Utils::Vector3d, Utils::Vector3d > get_local_domain() const
bool node_in_local_domain(Utils::Vector3i const &node) const
Utils::Vector3i get_block_corner(IBlock const &block, bool lower) const
LatticeWalberla(Utils::Vector3i const &grid_dimensions, Utils::Vector3i const &node_grid, Utils::Vector3i const &block_grid, unsigned int n_ghost_layers)
bool pos_in_local_domain(Utils::Vector3d const &pos) const
static double * block(double *p, std::size_t index, std::size_t size)
Definition elc.cpp:172
auto hadamard_division(Vector< T, N > const &a, Vector< U, N > const &b)
Definition Vector.hpp:423
auto to_vector3d(Vector3< T > const &v) noexcept
auto convert_cell_corner_to_coord(real_vector auto const &corner)
Get the block-local coordinates of a block corner.
auto get_min_corner(IBlock const &block)
Get the block-local coordinates of the lower corner of a block.
auto get_max_corner(IBlock const &block)
Get the block-local coordinates of the upper corner of a block.