OpenLB 1.7
Loading...
Searching...
No Matches
superGeometryStatistics3D.hh
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2013, 2014 Mathias J. Krause
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
28#include <iostream>
29#include "utilities/omath.h"
30#include <math.h>
31#include <sstream>
32
36#include "core/vector.h"
37
38
39namespace olb {
40
41template<typename T>
43 : _superGeometry(superGeometry), _statisticsUpdateNeeded(true),
44 _nMaterials(0), _minOverMaterial(0), _maxOverMaterial(0),
45 clout(std::cout,"SuperGeometryStatistics3D")
46{
47}
48
49template<typename T>
51 : _superGeometry(rhs._superGeometry), _statisticsUpdateNeeded(true),
52 _nMaterials(rhs._nMaterials),
53 _minOverMaterial(rhs._minOverMaterial), _maxOverMaterial(rhs._maxOverMaterial),
54 clout(std::cout,"SuperGeometryStatistics3D")
55{
56}
57
58template<typename T>
60{
61 _superGeometry = rhs._superGeometry;
62 _statisticsUpdateNeeded = true;
63 _nMaterials = rhs._nMaterials;
64 _minOverMaterial = rhs._minOverMaterial;
65 _maxOverMaterial = rhs._maxOverMaterial;
66 return *this;
67}
68
69
70template<typename T>
72{
73 return _statisticsUpdateNeeded;
74}
75
76template<typename T>
78{
79 return _statisticsUpdateNeeded;
80}
81
82
83template<typename T>
85{
86 const_this = const_cast<const SuperGeometryStatistics3D<T>*>(this);
87
88#ifdef PARALLEL_MODE_MPI
89 // This needs to be done with integers due to undesired behaviour with bool and LOR implicated by the MPI standard
90 int updateReallyNeededGlobal = 0;
91 if (_statisticsUpdateNeeded) {
92 updateReallyNeededGlobal = 1;
93 }
94 singleton::mpi().reduceAndBcast(updateReallyNeededGlobal, MPI_SUM);
95
96 if (updateReallyNeededGlobal>0) {
97 _statisticsUpdateNeeded = true;
98 }
99 //singleton::mpi().reduceAndBcast(_statisticsUpdateNeeded, MPI_LOR);
100#endif
101
102 // check if update is really needed
103 if (_statisticsUpdateNeeded ) {
104 int updateReallyNeeded = 0;
105 for (int iCloc=0; iCloc<_superGeometry->getLoadBalancer().size(); iCloc++) {
106 if (_superGeometry->getBlockGeometry(iCloc).getStatistics().getStatisticsStatus() ) {
107 auto& blockGeometry = const_cast<BlockGeometry<T,3>&>(_superGeometry->getBlockGeometry(iCloc));
108 blockGeometry.getStatistics().update(false);
109 updateReallyNeeded++;
110 }
111 }
112
113
114#ifdef PARALLEL_MODE_MPI
115 singleton::mpi().reduceAndBcast(updateReallyNeeded, MPI_SUM);
116#endif
117
118 if (updateReallyNeeded==0) {
119 _statisticsUpdateNeeded = false;
120 // clout << "almost updated" << std::endl;
121 return;
122 }
123
124
125 // get total number of different materials right
126 _nMaterials = int();
127 {
128 std::set<int> tmpMaterials{};
129 for (int iCloc=0; iCloc<_superGeometry->getLoadBalancer().size(); iCloc++) {
130 const auto& blockMaterial2n = _superGeometry->getBlockGeometry(iCloc).getStatistics().getMaterial2n();
131 for (auto [material, _] : blockMaterial2n) {
132 tmpMaterials.insert(material);
133 }
134 }
135 _nMaterials = tmpMaterials.size();
136 }
137
138 _material2n = std::map<int, std::size_t>();
139
140#ifdef PARALLEL_MODE_MPI
141 singleton::mpi().reduceAndBcast(_nMaterials, MPI_SUM);
142#endif
143
144 // store the number and min., max. possition for each rank
145 for (int iCloc=0; iCloc<_superGeometry->getLoadBalancer().size(); iCloc++) {
146 std::map<int, std::size_t> material2n = _superGeometry->getBlockGeometry(iCloc).getStatistics().getMaterial2n();
147 std::map<int, std::size_t>::iterator iter;
148
149 for (iter = material2n.begin(); iter != material2n.end(); iter++) {
150 if (iter->second!=0) {
151 std::vector<T> minPhysR = _superGeometry->getBlockGeometry(iCloc).getStatistics().getMinPhysR(iter->first);
152 std::vector<T> maxPhysR = _superGeometry->getBlockGeometry(iCloc).getStatistics().getMaxPhysR(iter->first);
153 if (_material2n.count(iter->first) == 0) {
154 _material2n[iter->first] = iter->second;
155 _material2min[iter->first] = minPhysR;
156 _material2max[iter->first] = maxPhysR;
157 }
158 else {
159 _material2n[iter->first] += iter->second;
160 for (int iDim=0; iDim<3; iDim++) {
161 if (_material2min[iter->first][iDim] > minPhysR[iDim]) {
162 _material2min[iter->first][iDim] = minPhysR[iDim];
163 }
164 if (_material2max[iter->first][iDim] < maxPhysR[iDim]) {
165 _material2max[iter->first][iDim] = maxPhysR[iDim];
166 }
167 }
168 }
169 }
170 }
171 }
172
173 // store the number and min., max. possition for all ranks
174#ifdef PARALLEL_MODE_MPI
175 std::ptrdiff_t materials[_nMaterials];
176 std::ptrdiff_t materialsInBuf[_nMaterials];
177 std::ptrdiff_t materialCount[_nMaterials];
178 std::ptrdiff_t materialCountInBuf[_nMaterials];
179 T materialMinR[3*_nMaterials];
180 T materialMaxR[3*_nMaterials];
181 T materialMinRinBuf[3*_nMaterials];
182 T materialMaxRinBuf[3*_nMaterials];
183
184 for (int iM=0; iM<_nMaterials; iM++) {
185 materials[iM]=-1;
186 materialCount[iM]=0;
187 for (int iDim=0; iDim<3; iDim++) {
188 materialMinRinBuf[3*iM + iDim] = T();
189 materialMaxRinBuf[3*iM + iDim] = T();
190 }
191 }
192 std::size_t counter = 0;
193 std::map<int, std::size_t>::iterator iMaterial;
194 for (iMaterial = _material2n.begin(); iMaterial != _material2n.end(); iMaterial++) {
195 materials[counter] = iMaterial->first;
196 materialCount[counter] = iMaterial->second;
197 for (int iDim=0; iDim<3; iDim++) {
198 materialMinR[3*counter + iDim] = _material2min[iMaterial->first][iDim];
199 materialMaxR[3*counter + iDim] = _material2max[iMaterial->first][iDim];
200 }
201 counter++;
202 }
203
204 for (int iRank=1; iRank<singleton::mpi().getSize(); iRank++) {
205 int myRank = singleton::mpi().getRank();
206 singleton::mpi().sendRecv(materials, materialsInBuf, _nMaterials,
207 (myRank+iRank)%singleton::mpi().getSize(),
208 (myRank-iRank+singleton::mpi().getSize())%singleton::mpi().getSize(), 0);
209 singleton::mpi().sendRecv(materialCount, materialCountInBuf, _nMaterials,
210 (myRank+iRank)%singleton::mpi().getSize(),
211 (myRank-iRank+singleton::mpi().getSize())%singleton::mpi().getSize(), 1);
212 singleton::mpi().sendRecv(materialMinR, materialMinRinBuf, 3*_nMaterials,
213 (myRank+iRank)%singleton::mpi().getSize(),
214 (myRank-iRank+singleton::mpi().getSize())%singleton::mpi().getSize(), 2);
215 singleton::mpi().sendRecv(materialMaxR, materialMaxRinBuf, 3*_nMaterials,
216 (myRank+iRank)%singleton::mpi().getSize(),
217 (myRank-iRank+singleton::mpi().getSize())%singleton::mpi().getSize(), 3);
218 for (int iM=0; iM<_nMaterials; iM++) {
219 if (materialsInBuf[iM]!=-1) {
220 std::vector<T> minPhysR(3,T());
221 std::vector<T> maxPhysR(3,T());
222 for (int iDim=0; iDim<3; iDim++) {
223 minPhysR[iDim] = materialMinRinBuf[3*iM + iDim];
224 maxPhysR[iDim] = materialMaxRinBuf[3*iM + iDim];
225 }
226 if (_material2n.count(materialsInBuf[iM]) == 0) {
227 _material2n[materialsInBuf[iM]] = materialCountInBuf[iM];
228 _material2min[materialsInBuf[iM]] = minPhysR;
229 _material2max[materialsInBuf[iM]] = maxPhysR;
230 }
231 else {
232 _material2n[materialsInBuf[iM]] += materialCountInBuf[iM];
233 for (int iDim=0; iDim<3; iDim++) {
234 if (_material2min[materialsInBuf[iM]][iDim] > minPhysR[iDim]) {
235 _material2min[materialsInBuf[iM]][iDim] = minPhysR[iDim];
236 }
237 if (_material2max[materialsInBuf[iM]][iDim] < maxPhysR[iDim]) {
238 _material2max[materialsInBuf[iM]][iDim] = maxPhysR[iDim];
239 }
240 }
241 }
242 }
243 }
244 }
245#endif
246
247 // update _minOverMaterial and _maxOverMaterial
248 typename std::map< int, olb::Vector<T, 3> >::const_iterator iter;
249 // find componentwise minimal extension over all material numbers
250 for ( int iDim = 0; iDim < 3; iDim++ ) {
251 // minimum
252 for ( iter = _material2min.begin(); iter != _material2min.end(); iter++ ) {
253 if ( iter->first != 0 ) { // only relevant material number are considered
254 if ( _minOverMaterial[iDim] > iter->second[iDim] ) {
255 _minOverMaterial[iDim] = iter->second[iDim];
256 }
257 }
258 }
259 // maximum
260 for ( iter = _material2max.begin(); iter != _material2max.end(); iter++ ) {
261 if ( iter->first != 0 ) { // only relevant material number are considered
262 if ( _maxOverMaterial[iDim] < iter->second[iDim] ) {
263 _maxOverMaterial[iDim] = iter->second[iDim];
264 }
265 }
266 }
267 }
268
269 //clout.setMultiOutput(true);
270// print();
271 //clout.setMultiOutput(false);
272
273 if (verbose) {
274 clout << "updated" << std::endl;
275 }
276 _statisticsUpdateNeeded = false;
277 }
278}
279
280template<typename T>
282{
283 update();
284 return const_this->getNmaterials();
285}
286
287template<typename T>
289{
290 return _nMaterials;
291}
292
293template<typename T>
295{
296 update(true);
297 return const_this->getNvoxel(material);
298}
299
300template<typename T>
301std::size_t SuperGeometryStatistics3D<T>::getNvoxel(int material) const
302{
303 try {
304 return _material2n.at(material);
305 }
306 catch (std::out_of_range& ex) {
307 return 0;
308 }
309}
310
311template<typename T>
313{
314 update();
315 return const_this->getNvoxel();
316}
317
318template<typename T>
320{
321 std::size_t total = 0;
322 for (const auto& material : _material2n) {
323 if (material.first!=0) {
324 total += material.second;
325 }
326 }
327 return total;
328}
329
330template<typename T>
332{
333 update();
334 return const_this->getMinPhysR(material);
335}
336
337template<typename T>
339{
340 try {
341 return _material2min.at(material);
342 }
343 catch (std::out_of_range& ex) {
344 return {0, 0, 0};
345 }
346}
347
348
349template<typename T>
351{
352 update();
353 return const_this->getMinPhysR();
354}
355
356template<typename T>
358{
359 return _minOverMaterial;
360}
361
362template<typename T>
364{
365 update();
366 return const_this->getMaxPhysR(material);
367}
368
369template<typename T>
371{
372 try {
373 return _material2max.at(material);
374 }
375 catch (std::out_of_range& ex) {
376 return {0, 0, 0};
377 }
378}
379
380template<typename T>
382{
383 update();
384 return const_this->getMaxPhysR();
385}
386
387template<typename T>
389{
390 return _maxOverMaterial;
391}
392
393template<typename T>
395{
396 update();
397 return const_this->getPhysExtend(material);
398}
399
400template<typename T>
401std::vector<T> SuperGeometryStatistics3D<T>::getPhysExtend(int material) const
402{
403 try {
404 std::vector<T> extend;
405 for (int iDim = 0; iDim < 3; iDim++) {
406 extend.push_back(_material2max.at(material)[iDim] - _material2min.at(material)[iDim]);
407 }
408 return extend;
409 }
410 catch (std::out_of_range& ex) {
411 return { 0, 0, 0 };
412 }
413}
414
415template<typename T>
417{
418 update();
419 return const_this->getPhysRadius(material);
420}
421
422template<typename T>
424{
425 olb::Vector<T, 3> radius;
426 for (int iDim=0; iDim<3; iDim++) {
427 //radius.push_back((getMaxPhysR(material)[iDim] - getMinPhysR(material)[iDim])/2.);
428 radius[iDim] = (getMaxPhysR(material)[iDim] - getMinPhysR(material)[iDim])/2.;
429 }
430 return radius;
431}
432
433template<typename T>
435{
436 update();
437 return const_this->getCenterPhysR(material);
438}
439
440template<typename T>
442{
443 olb::Vector<T, 3> center;
444 for (int iDim=0; iDim<3; iDim++) {
445 center[iDim] = getMinPhysR(material)[iDim] + getPhysRadius(material)[iDim];
446 }
447 return center;
448}
449
450template<typename T>
452{
453 update();
454 return const_this->getType(iC, iX, iY, iZ);
455}
456
457template<typename T>
459{
460 int iCloc=_superGeometry->getLoadBalancer().loc(iC);
461 olb::Vector<int, 3> discreteNormal = _superGeometry->getBlockGeometry(iCloc).getStatistics().getType(iX, iY, iZ);
462 return discreteNormal;
463}
464
465template<typename T>
467{
468 update();
469 return const_this->computeNormal(material);
470}
471
472template<typename T>
474{
475 std::vector<T> normal (3,int());
476 for (int iCloc=0; iCloc<_superGeometry->getLoadBalancer().size(); iCloc++) {
477 for (int iDim=0; iDim<3; iDim++) {
478 if (_superGeometry->getBlockGeometry(iCloc).getStatistics().getNvoxel(material)!=0) {
479 normal[iDim] += _superGeometry->getBlockGeometry(iCloc).getStatistics().computeNormal(material)[iDim]*_superGeometry->getBlockGeometry(iCloc).getStatistics().getNvoxel(material);
480 }
481 }
482 }
483
484#ifdef PARALLEL_MODE_MPI
485 for (int iDim=0; iDim<3; iDim++) {
486 singleton::mpi().reduceAndBcast((normal[iDim]), MPI_SUM);
487 }
488#endif
489
490 if (getNvoxel(material) == 0) {
491 std::cerr << "Unkown material number: " << material << std::endl;
492 std::exit(-1);
493 }
494
495 for (int iDim=0; iDim<3; iDim++) {
496 normal[iDim] /= getNvoxel(material);
497 }
498
499 T norm = util::sqrt(normal[0]*normal[0]+normal[1]*normal[1]+normal[2]*normal[2]);
500 if (norm>0.) {
501 normal[0]/=norm;
502 normal[1]/=norm;
503 normal[2]/=norm;
504 }
505 return normal;
506}
507
508template<typename T>
510{
511 update();
512 return const_this->computeDiscreteNormal(material, maxNorm);
513}
514
515template<typename T>
517{
518 olb::Vector<T,3> normal = computeNormal(material);
519 olb::Vector<int, 3> discreteNormal(0);
520
521 T smallestAngle = T(0);
522 for (int iX = -1; iX<=1; iX++) {
523 for (int iY = -1; iY<=1; iY++) {
524 for (int iZ = -1; iZ<=1; iZ++) {
525 T norm = util::sqrt(iX*iX+iY*iY+iZ*iZ);
526 if (norm>0.&& norm<maxNorm) {
527 T angle = (iX*normal[0] + iY*normal[1] + iZ*normal[2])/norm;
528 if (angle>=smallestAngle) {
529 smallestAngle=angle;
530 discreteNormal[0] = iX;
531 discreteNormal[1] = iY;
532 discreteNormal[2] = iZ;
533 }
534 }
535 }
536 }
537 }
538 return discreteNormal;
539}
540
541template<typename T>
543{
544 Vector<T,3> vec(getMaxPhysR(material)[0] -getMinPhysR(material)[0], getMaxPhysR(material)[1] -getMinPhysR(material)[1], getMaxPhysR(material)[2] -getMinPhysR(material)[2]);
545 return norm(vec);
546}
547
548template<typename T>
550{
551 Vector<T,3> vec(getMaxPhysR()[0] -getMinPhysR()[0], getMaxPhysR()[1] -getMinPhysR()[1], getMaxPhysR()[2] -getMinPhysR()[2]);
552 return norm(vec);
553}
554
555template<typename T>
557{
558 update();
559 return const_this->print();
560}
561
562template<typename T>
564{
565 try {
566 std::size_t nCells = 0;
567 for (const auto& material : _material2n) {
568 clout << "materialNumber=" << material.first
569 << "; count=" << material.second
570 << "; minPhysR=(" << _material2min.at(material.first)[0] <<","<< _material2min.at(material.first)[1] <<","<< _material2min.at(material.first)[2] <<")"
571 << "; maxPhysR=(" << _material2max.at(material.first)[0] <<","<< _material2max.at(material.first)[1] <<","<< _material2max.at(material.first)[2] <<")"
572 << std::endl;
573 nCells += material.second;
574 }
575 clout << "countTotal[1e6]=" << nCells / 1.e6 << std::endl;
576 }
577 catch (std::out_of_range& ex) {
578 }
579}
580
581
582
583} // namespace olb
Representation of a block geometry.
const BlockGeometryStatistics< T, D > & getStatistics() const
Read only access to the associated block statistic.
olb::Vector< T, 3 > getCenterPhysR(int material)
Returns the center position.
void print()
Prints some statistic information, i.e. the number of voxels and min. max. physical position for each...
olb::Vector< T, 3 > getMinPhysR()
Returns the min. phys position in each direction corresponding to all non-zero material numbers.
void update(bool verbose=false)
Updates the statistics if it is really needed.
olb::Vector< T, 3 > getMaxPhysR()
Returns the max. phys position in each direction corresponding to all non-zero material numbers.
olb::Vector< int, 3 > getType(int iC, int iX, int iY, int iZ)
Returns the boundary type which is characterized by a discrte normal (c.f. Zimny)
std::size_t getNvoxel()
Returns the number of voxels with material!=0.
olb::Vector< T, 3 > computeNormal(int material)
Returns normal that points into the fluid for paraxial surfaces.
int getNmaterials()
Returns the number of different materials.
SuperGeometryStatistics3D< T > & operator=(SuperGeometryStatistics3D const &rhs)
Copy assignment.
olb::Vector< int, 3 > computeDiscreteNormal(int material, T maxNorm=1.1)
Returns discrete normal with norm maxNorm that points into the fluid for paraxial surfaces maxNorm=1....
bool & getStatisticsStatus()
Read and write access to a flag, which indicates if an uptate is needed (=true)
olb::Vector< T, 3 > getPhysExtend(int material)
Returns the phys extend as length in each direction.
SuperGeometryStatistics3D(SuperGeometry< T, 3 > *superGeometry)
Constructor.
T computeMaxPhysDistance() const
Returns util::sqrt( maxX^2 + maxY^2 + maxZ^2 ) max over all material numbers.
olb::Vector< T, 3 > getPhysRadius(int material)
Returns the phys radius as length in each direction.
Representation of a statistic for a parallel 2D geometry.
Plain old scalar vector.
Definition vector.h:47
int getSize() const
Returns the number of processes.
void reduceAndBcast(T &reductVal, MPI_Op op, int root=0, MPI_Comm comm=MPI_COMM_WORLD)
Reduction operation, followed by a broadcast.
int getRank() const
Returns the process ID.
void sendRecv(T *sendBuf, T *recvBuf, int count, int dest, int source, int tag=0, MPI_Comm comm=MPI_COMM_WORLD)
Send and receive data between two partners.
MpiManager & mpi()
cpu::simd::Pack< T > sqrt(cpu::simd::Pack< T > value)
Definition pack.h:100
Top level namespace for all of OpenLB.
constexpr T norm(const ScalarVector< T, D, IMPL > &a)
Euclidean vector norm.
Representation of a statistic for a parallel 3D geometry – header file.
Representation of a parallel 2D geometry – header file.
efficient implementation of a vector class