OpenLB 1.7
Loading...
Searching...
No Matches
serialization.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2023-24 Julius Jeßberger
4 * E-mail contact: info@openlb.net
5 * The most recent release of OpenLB can be downloaded at
6 * <http://www.openlb.net/>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22*/
23
29 #ifndef SERIALIZATION_H
30 #define SERIALIZATION_H
31
32#include <cstdlib>
33
34#include "controller.h"
36#include "utilities/aliases.h"
38
39namespace olb {
40
41namespace opti {
42
43template<typename S>
44class Controller;
45
50template<typename S, unsigned dim>
52{
53public:
59
61 virtual std::size_t getSerializedCellIndex(const int latticeR[]) const = 0;
62
64 std::size_t getSerializedCellIndex(LatticeR<dim+1> latticeR) const {
65 return getSerializedCellIndex(latticeR.data());
66 }
67
69 virtual LatticeR<dim+1> getLatticeR(std::size_t index) const = 0;
70
72 std::size_t getSerializedComponentIndex(const int latticeR[],
73 unsigned iD, unsigned fieldDim) const {
74 return fieldDim * getSerializedCellIndex(latticeR) + iD;
75 }
76
79 unsigned iD, unsigned fieldDim) const {
80 return fieldDim * getSerializedCellIndex(latticeR) + iD;
81 }
82
85 unsigned fieldDim) const {
86 return getSerializedComponentIndex(coords.latticeR, coords.fieldComponent, fieldDim);
87 }
88
90 LatticeAndFieldR getLatticeAndFieldR(std::size_t index, unsigned fieldDim) const {
91 // index = fieldDim * cellIndex + fieldComponent
92 const auto fieldCoord = std::div((long int) index, (long int) fieldDim);
93 const auto geomCoord = getLatticeR(fieldCoord.quot);
94 return {geomCoord, (std::size_t) fieldCoord.rem};
95 }
96
97 virtual unsigned getNoCells() const = 0;
98};
99
108template<typename S, unsigned dim>
110{
111protected:
113 const unsigned _noCuboids;
114
115private:
116 std::vector<unsigned> _cuboidSizes; // number of cells per cuboid
117 std::vector<unsigned> _offsets; // accumulated cuboid sizes
118 unsigned _noCells;
119
120public:
122 : _cGeometry(cGeometry),
123 _noCuboids(_cGeometry.getNc())
124 {
125 _cuboidSizes.reserve(_noCuboids);
126 _offsets.reserve(_noCuboids);
127 for (unsigned i = 0; i < _noCuboids; ++i) {
128 _cuboidSizes.push_back(_cGeometry.get(i).getLatticeVolume());
129 }
130 _offsets.push_back(0);
131 for (unsigned i = 1; i < _noCuboids; ++i) {
132 _offsets.push_back(_offsets[i-1] + _cuboidSizes[i-1]);
133 }
134
135 const auto mc = _cGeometry.getMotherCuboid();
136 if constexpr (dim == 2) {
137 _noCells = (mc.getNx() + 1) * (mc.getNy() + 1);
138 } else {
139 _noCells = (mc.getNx() + 1) * (mc.getNy() + 1) * (mc.getNz() + 1);
140 }
141 }
142
144 : SimpleGeometrySerializer(sGeometry.getCuboidGeometry())
145 { }
146
148 std::size_t getSerializedCellIndex(const int latticeR[]) const override {
149 const Cuboid<S,dim>& c = _cGeometry.get(latticeR[0]);
150 const int nX = c.getNx();
151 const int nY = c.getNy();
152 std::size_t res;
153 if constexpr (dim == 2) {
154 // cuboid_offset + NX*y + x
155 res = _offsets[latticeR[0]] + nX*latticeR[2] + latticeR[1];
156 } else {
157 // cuboid_offset + NX*NY*z + NX*y + x
158 res = _offsets[latticeR[0]] + nX*nY*latticeR[3] + nX*latticeR[2] + latticeR[1];
159 }
160 return res;
161 }
162
164
166 LatticeR<dim+1> getLatticeR(std::size_t index) const override {
167 const auto cuboidIt = std::upper_bound(_offsets.begin(), _offsets.end(), index) - 1;
168 LatticeR<dim+1> res;
169 res[0] = std::distance(_offsets.begin(), cuboidIt);
170
171 const Cuboid<S,dim>& c = _cGeometry.get(res[0]);
172 const std::size_t nX = c.getNx();
173 if constexpr (dim == 2) {
174 // index = cuboid_offset + NX*y + x
175 const auto divByNx = std::div((long int) index - *cuboidIt, (long int) nX);
176 res[2] = divByNx.quot;
177 res[1] = divByNx.rem;
178 } else {
179 // index = cuboid_offset + NX*NY*z + NX*y + x
180 const std::size_t nY = c.getNy();
181 const auto divByNxNy = std::div((long int) index - *cuboidIt, (long int) nX*nY);
182 res[3] = divByNxNy.quot;
183 const auto divByNx = std::div(divByNxNy.rem, (long int) nX);
184 res[2] = divByNx.quot;
185 res[1] = divByNx.rem;
186 }
187 return res;
188 }
189
190 unsigned getNoCells() const override {
191 return _noCells;
192 }
193};
194
195
203template<typename S, unsigned dim>
205{
206private:
207 using L = LatticeR<dim+1>;
208 std::vector<L> _coords;
209 mutable FunctorPtr<SuperIndicatorF<S,dim>> _indicator; // indicates which cells are serialized
210 // the _indicator should never be changed, otherwise this class loses its
211 // correctness. The "mutable" keyword is only necessary because FunctorPtr
212 // does not support const arithmetic and should be removed if possible.
213
214public:
217 : _indicator(std::move(indicator))
218 {
219 const auto cGeometry = superGeometry.getCuboidGeometry();
220 L latticeR;
221 for (unsigned iC = 0; iC < cGeometry.getNc(); ++iC) {
222 latticeR[0] = iC;
223 const int nX = cGeometry.get(iC).getNx();
224 const int nY = cGeometry.get(iC).getNy();
225 for (int iX=0; iX<nX; iX++) {
226 latticeR[1] = iX;
227 for (int iY=0; iY<nY; iY++) {
228 latticeR[2] = iY;
229 if constexpr (dim == 2) {
230 if (_indicator(latticeR.data())) {
231 _coords.push_back(latticeR);
232 }
233 } else {
234 const int nZ = cGeometry.get(iC).getNz();
235 for (int iZ=0; iZ<nZ; iZ++) {
236 latticeR[3] = iZ;
237
238 if (_indicator(latticeR.data())) {
239 _coords.push_back(latticeR);
240 }
241 }
242 }
243 }
244 }
245 }
246 }
247
249 FunctorPtr<IndicatorF<S,dim>>&& indicator)
250 : SparseGeometrySerializer(superGeometry,
251 new SuperIndicatorFfromIndicatorF<S,dim>(std::move(indicator), superGeometry))
252 { }
253
255 std::size_t getSerializedCellIndex(const int latticeR[]) const override {
256#ifdef OLB_DEBUG
257 // check if cell lies in indicated domain
258 bool isInside;
259 _indicator(&isInside, latticeR);
260 if (! isInside) {
261 OstreamManager clout (std::cout, "SparseGeometrySerializer");
262 clout << "Warning: the passed cell does not lie in the indicated domain "
263 << "and can therefore not be accessed." << std::endl;
264 std::exit(1);
265 }
266#endif
267 const L point (latticeR);
268 const auto upper = std::upper_bound(
269 _coords.begin(), _coords.end(), point, [](const L& a, const L& b){
270 return lex_smaller(a, b);
271 });
272 return std::distance(_coords.begin(), upper - 1);
273 }
274
276
278 LatticeR<dim+1> getLatticeR(std::size_t index) const override {
279#ifdef OLB_DEBUG
280 // check if index lies in accessible range
281 if (index >= _coords.size()) {
282 OstreamManager clout (std::cout, "SparseGeometrySerializer");
283 clout << "Warning: the passed index is higher than the number of cells "
284 << "which are marked by indicator." << std::endl;
285 std::exit(1);
286 }
287#endif
288 return _coords[index];
289 }
290
291 unsigned getNoCells() const override {
292 return _coords.size();
293 }
294};
295
297template<typename S, unsigned dim>
299{
300 int material = 0;
301 if ( sGeometry.getLoadBalancer().rank(latticeR[0]) == singleton::mpi().getRank() ) {
302 material = sGeometry.get(latticeR);
303 }
304#ifdef PARALLEL_MODE_MPI
305 singleton::mpi().bCast(&material, 1, sGeometry.getLoadBalancer().rank(latticeR[0]));
306#endif
307 return material;
308}
309
310
311template <typename T, typename DESCRIPTOR>
312class BlockLatticeSerialDataF : public BlockLatticeF<T,DESCRIPTOR> {
313protected:
314 static constexpr unsigned d = DESCRIPTOR::d;
317 const int _iC;
318 std::function<T(T)> _projection;
319public:
321 Controller<T>& controller, const GeometrySerializer<T,d>& serializer,
322 int iC, unsigned dataDim, std::function<T(T)> projection)
323 : BlockLatticeF<T,DESCRIPTOR>(blockLattice, dataDim),
324 _controller(controller), _serializer(serializer), _iC(iC),
325 _projection(projection)
326 {
327 this->getName() = "BlockLatticeSerialDataF";
328 }
329
330 bool operator() (T output[], const int input[])
331 {
332 if (this->getBlock().isInsideCore(input)) {
333 int latticeR[4] = {_iC, input[0], input[1], 0};
334 if constexpr (d == 3) {
335 latticeR[3] = input[2];
336 }
337 const auto index = _serializer.getSerializedComponentIndex(latticeR, 0, this->getTargetDim());
338 for (int i = 0; i < this->getTargetDim(); ++i) { // todo: benutze std::copy_n?
339 output[i] = _projection(_controller.getControl(index + i));
340 }
341 return true;
342 }
343 return false;
344 }
345};
346
347
352// Controller stores field values, which are (component-wise, point by point)
353// transformed by the projection function and then returned.
354// The controller is global, it is expected to have data for the entire domain.
355// Hence, every process must have access to the ''same'' controller.
356template <typename T, typename DESCRIPTOR>
357class SuperLatticeSerialDataF : public SuperLatticeF<T,DESCRIPTOR> {
358protected:
359 std::shared_ptr<const GeometrySerializer<T,DESCRIPTOR::d>> _serializer;
360public:
362 Controller<T>& controller, unsigned dataDim,
363 std::shared_ptr<const GeometrySerializer<T,DESCRIPTOR::d>> serializer,
364 std::function<T(T)> projection = [](T x){ return x; })
365 : SuperLatticeF<T,DESCRIPTOR>(superLattice, dataDim),
366 _serializer(serializer)
367 {
368 this->getName() = "SuperLatticeSerialDataF";
369
370 const int maxC = superLattice.getLoadBalancer().size();
371 this->_blockF.reserve(maxC);
372
373 for (int iC = 0; iC < maxC; ++iC) {
374 this->_blockF.emplace_back(
376 superLattice.getBlock(iC),
377 controller,
379 superLattice.getLoadBalancer().glob(iC),
380 dataDim,
381 projection)
382 );
383 }
384 }
385
387 Controller<T>& controller, unsigned dataDim,
388 std::function<T(T)> projection = [](T x){ return x; })
389 : SuperLatticeSerialDataF(superLattice, controller, dataDim,
390 std::make_shared<const SimpleGeometrySerializer<T,DESCRIPTOR::d>>(superLattice),
391 projection)
392 { }
393};
394
395
396
397}
398}
399#endif
Platform-abstracted block lattice for external access and inter-block interaction.
Smart pointer for managing the various ways of passing functors around.
Definition functorPtr.h:60
class for marking output with some text
Representation of a statistic for a parallel 2D geometry.
int get(int iCglob, LatticeR< D > latticeR) const
Read only access to the material numbers, error handling: returns 0 if data is not available.
Super class maintaining block lattices for a cuboid decomposition.
BlockLattice< T, DESCRIPTOR > & getBlock(int locC)
Return BlockLattice with local index locC.
CuboidGeometry< T, D > & getCuboidGeometry()
Read and write access to cuboid geometry.
LoadBalancer< T > & getLoadBalancer()
Read and write access to the load balancer.
Plain old scalar vector.
Definition vector.h:47
constexpr const T * data() const any_platform
Definition vector.h:161
static constexpr unsigned d
const GeometrySerializer< T, d > & _serializer
bool operator()(T output[], const int input[])
BlockLatticeSerialDataF(BlockLattice< T, DESCRIPTOR > &blockLattice, Controller< T > &controller, const GeometrySerializer< T, d > &serializer, int iC, unsigned dataDim, std::function< T(T)> projection)
S const & getControl(int i) const
Definition controller.h:59
This class serializes the cells inside the geometry.
virtual unsigned getNoCells() const =0
std::size_t getSerializedCellIndex(LatticeR< dim+1 > latticeR) const
Compute serialized cell index from lattice coordinates.
virtual std::size_t getSerializedCellIndex(const int latticeR[]) const =0
Compute serialized cell index from lattice coordinates.
std::size_t getSerializedComponentIndex(LatticeAndFieldR coords, unsigned fieldDim) const
Get index of field component from lattice coordinates and component index.
std::size_t getSerializedComponentIndex(LatticeR< dim+1 > latticeR, unsigned iD, unsigned fieldDim) const
Get index of field component from lattice coordinates and component index.
virtual LatticeR< dim+1 > getLatticeR(std::size_t index) const =0
Get lattice coordinates from serialized cell index.
LatticeAndFieldR getLatticeAndFieldR(std::size_t index, unsigned fieldDim) const
Get lattice coordinates and field component from serialized field index.
std::size_t getSerializedComponentIndex(const int latticeR[], unsigned iD, unsigned fieldDim) const
Get index of field component from lattice coordinates and component index.
This class serializes the cells inside the geometry.
SimpleGeometrySerializer(SuperGeometry< S, dim > &sGeometry)
std::size_t getSerializedCellIndex(const int latticeR[]) const override
Compute serialized cell index from lattice coordinates.
LatticeR< dim+1 > getLatticeR(std::size_t index) const override
Get lattice coordinates from serialized cell index.
unsigned getNoCells() const override
CuboidGeometry< S, dim > & _cGeometry
SimpleGeometrySerializer(CuboidGeometry< S, dim > &cGeometry)
This class serializes the cells which are marked by indicator.
SparseGeometrySerializer(SuperGeometry< S, dim > &superGeometry, FunctorPtr< SuperIndicatorF< S, dim > > &&indicator)
SparseGeometrySerializer(SuperGeometry< S, dim > &superGeometry, FunctorPtr< IndicatorF< S, dim > > &&indicator)
unsigned getNoCells() const override
std::size_t getSerializedCellIndex(const int latticeR[]) const override
Compute serialized cell index from lattice coordinates.
LatticeR< dim+1 > getLatticeR(std::size_t index) const override
Get lattice coordinates from serialized cell index.
A data field whose values are managed by a controller.
SuperLatticeSerialDataF(SuperLattice< T, DESCRIPTOR > &superLattice, Controller< T > &controller, unsigned dataDim, std::shared_ptr< const GeometrySerializer< T, DESCRIPTOR::d > > serializer, std::function< T(T)> projection=[](T x){ return x;})
std::shared_ptr< const GeometrySerializer< T, DESCRIPTOR::d > > _serializer
SuperLatticeSerialDataF(SuperLattice< T, DESCRIPTOR > &superLattice, Controller< T > &controller, unsigned dataDim, std::function< T(T)> projection=[](T x){ return x;})
void bCast(T *sendBuf, int sendCount, int root=0, MPI_Comm comm=MPI_COMM_WORLD)
Broadcast data from one processor to multiple processors.
int getRank() const
Returns the process ID.
The description of a Controller – header file.
int getMaterialGlobally(SuperGeometry< S, dim > &sGeometry, LatticeR< dim+1 > latticeR)
Helper that gives global access to material numbers.
MpiManager & mpi()
Top level namespace for all of OpenLB.
std::conditional_t< DESCRIPTOR::d==2, SuperLatticeF2D< T, DESCRIPTOR >, SuperLatticeF3D< T, DESCRIPTOR > > SuperLatticeF
Definition aliases.h:148
std::conditional_t< D==2, SuperIndicatorFfromIndicatorF2D< T >, SuperIndicatorFfromIndicatorF3D< T > > SuperIndicatorFfromIndicatorF
Definition aliases.h:288
std::conditional_t< DESCRIPTOR::d==2, BlockLatticeF2D< T, DESCRIPTOR >, BlockLatticeF3D< T, DESCRIPTOR > > BlockLatticeF
Definition aliases.h:158
std::conditional_t< D==2, CuboidGeometry2D< T >, CuboidGeometry3D< T > > CuboidGeometry
Definition aliases.h:47
std::conditional_t< D==2, IndicatorF2D< T >, IndicatorF3D< T > > IndicatorF
Definition aliases.h:258
std::conditional_t< D==2, SuperIndicatorF2D< T >, SuperIndicatorF3D< T > > SuperIndicatorF
Definition aliases.h:208
std::conditional_t< D==2, Cuboid2D< T >, Cuboid3D< T > > Cuboid
Definition aliases.h:37
Optimization Code.
Bundle for lattice coordinates + field component.
Representation of a parallel 2D geometry – header file.