OpenLB 1.7
Loading...
Searching...
No Matches
superGeometryStatistics2D.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
35#include "core/olbDebug.h"
36
37namespace olb {
38
39template<typename T>
41 : _superGeometry(superGeometry), _statisticsUpdateNeeded(true), clout(std::cout,"SuperGeometryStatistics2D")
42{
43}
44
45template<typename T>
47 : _superGeometry(rhs._superGeometry), _statisticsUpdateNeeded(true),
48 clout(std::cout,"SuperGeometryStatistics2D")
49{
50}
51
52template<typename T>
54{
55 _superGeometry = rhs._superGeometry;
56 _statisticsUpdateNeeded = true;
57 return *this;
58}
59
60
61template<typename T>
63{
64 return _statisticsUpdateNeeded;
65}
66
67template<typename T>
69{
70 return _statisticsUpdateNeeded;
71}
72
73
74template<typename T>
76{
77 const_this = const_cast<const SuperGeometryStatistics2D<T>*>(this);
78
79#ifdef PARALLEL_MODE_MPI
80 int updateReallyNeededGlobal = 0;
81 if (_statisticsUpdateNeeded ) {
82 updateReallyNeededGlobal = 1;
83 }
84 singleton::mpi().reduceAndBcast(updateReallyNeededGlobal, MPI_SUM);
85 if (updateReallyNeededGlobal>0) {
86 _statisticsUpdateNeeded = true;
87 }
88 //singleton::mpi().reduceAndBcast(_statisticsUpdateNeeded, MPI_LOR);
89#endif
90
91 // check if update is really needed
92 if (_statisticsUpdateNeeded ) {
93 int updateReallyNeeded = 0;
94 for (int iCloc=0; iCloc<_superGeometry->getLoadBalancer().size(); iCloc++) {
95 if (_superGeometry->getBlockGeometry(iCloc).getStatistics().getStatisticsStatus() ) {
96 auto& blockGeometry = const_cast<BlockGeometry<T,2>&>(_superGeometry->getBlockGeometry(iCloc));
97 blockGeometry.getStatistics().update(false);
98 updateReallyNeeded++;
99 }
100 }
101
102
103#ifdef PARALLEL_MODE_MPI
104 singleton::mpi().reduceAndBcast(updateReallyNeeded, MPI_SUM);
105#endif
106
107 if (updateReallyNeeded==0) {
108 _statisticsUpdateNeeded = false;
109 // clout << "almost updated" << std::endl;
110 return;
111 }
112
113
114 // get total number of different materials right
115 _nMaterials = int();
116 {
117 std::set<int> tmpMaterials{};
118 for (int iCloc=0; iCloc<_superGeometry->getLoadBalancer().size(); iCloc++) {
119 const auto& blockMaterial2n = _superGeometry->getBlockGeometry(iCloc).getStatistics().getMaterial2n();
120 for (auto [material, _] : blockMaterial2n) {
121 tmpMaterials.insert(material);
122 }
123 }
124 _nMaterials = tmpMaterials.size();
125 }
126
127 _material2n = std::map<int, int>();
128
129#ifdef PARALLEL_MODE_MPI
130 singleton::mpi().reduceAndBcast(_nMaterials, MPI_SUM);
131#endif
132
133 // store the number and min., max. possition for each rank
134 for (int iCloc=0; iCloc<_superGeometry->getLoadBalancer().size(); iCloc++) {
135 std::map<int, int> material2n = _superGeometry->getBlockGeometry(iCloc).getStatistics().getMaterial2n();
136 std::map<int, int>::iterator iter;
137
138 for (iter = material2n.begin(); iter != material2n.end(); iter++) {
139 if (iter->second!=0) {
140 std::vector<T> minPhysR = _superGeometry->getBlockGeometry(iCloc).getStatistics().getMinPhysR(iter->first);
141 std::vector<T> maxPhysR = _superGeometry->getBlockGeometry(iCloc).getStatistics().getMaxPhysR(iter->first);
142 if (_material2n.count(iter->first) == 0) {
143 _material2n[iter->first] = iter->second;
144 _material2min[iter->first] = minPhysR;
145 _material2max[iter->first] = maxPhysR;
146 //std::cout << iter->first<<":"<<_material2n[iter->first]<<std::endl;
147 }
148 else {
149 _material2n[iter->first] += iter->second;
150 for (int iDim=0; iDim<2; iDim++) {
151 if (_material2min[iter->first][iDim] > minPhysR[iDim]) {
152 _material2min[iter->first][iDim] = minPhysR[iDim];
153 }
154 if (_material2max[iter->first][iDim] < maxPhysR[iDim]) {
155 _material2max[iter->first][iDim] = maxPhysR[iDim];
156 }
157 }
158 //std::cout << iter->first<<":"<<_material2n[iter->first]<<std::endl;
159 }
160 }
161 }
162 }
163
164 // store the number and min., max. possition for all ranks
165#ifdef PARALLEL_MODE_MPI
166 int materials[_nMaterials];
167 int materialsInBuf[_nMaterials];
168 int materialCount[_nMaterials];
169 int materialCountInBuf[_nMaterials];
170 T materialMinR[2*_nMaterials];
171 T materialMaxR[2*_nMaterials];
172 T materialMinRinBuf[2*_nMaterials];
173 T materialMaxRinBuf[2*_nMaterials];
174
175 for (int iM=0; iM<_nMaterials; iM++) {
176 materials[iM]=-1;
177 materialCount[iM]=0;
178 for (int iDim=0; iDim<2; iDim++) {
179 materialMinRinBuf[2*iM + iDim] = T();
180 materialMaxRinBuf[2*iM + iDim] = T();
181 }
182 }
183 int counter = 0;
184 std::map<int, int>::iterator iMaterial;
185 for (iMaterial = _material2n.begin(); iMaterial != _material2n.end(); iMaterial++) {
186 materials[counter] = iMaterial->first;
187 materialCount[counter] = iMaterial->second;
188 for (int iDim=0; iDim<2; iDim++) {
189 materialMinR[2*counter + iDim] = _material2min[iMaterial->first][iDim];
190 materialMaxR[2*counter + iDim] = _material2max[iMaterial->first][iDim];
191 }
192 counter++;
193 }
194
195 for (int iRank=1; iRank<singleton::mpi().getSize(); iRank++) {
196 int myRank = singleton::mpi().getRank();
197 singleton::mpi().sendRecv(materials, materialsInBuf, _nMaterials, (myRank+iRank)%singleton::mpi().getSize(), (myRank-iRank+singleton::mpi().getSize())%singleton::mpi().getSize(), 0);
198 singleton::mpi().sendRecv(materialCount, materialCountInBuf, _nMaterials, (myRank+iRank)%singleton::mpi().getSize(), (myRank-iRank+singleton::mpi().getSize())%singleton::mpi().getSize(), 1);
199 singleton::mpi().sendRecv(materialMinR, materialMinRinBuf, 2*_nMaterials, (myRank+iRank)%singleton::mpi().getSize(), (myRank-iRank+singleton::mpi().getSize())%singleton::mpi().getSize(), 2);
200 singleton::mpi().sendRecv(materialMaxR, materialMaxRinBuf, 2*_nMaterials, (myRank+iRank)%singleton::mpi().getSize(), (myRank-iRank+singleton::mpi().getSize())%singleton::mpi().getSize(), 2);
201 for (int iM=0; iM<_nMaterials; iM++) {
202 if (materialsInBuf[iM]!=-1) {
203 std::vector<T> minPhysR(2,T());
204 std::vector<T> maxPhysR(2,T());
205 for (int iDim=0; iDim<2; iDim++) {
206 minPhysR[iDim] = materialMinRinBuf[2*iM + iDim];
207 maxPhysR[iDim] = materialMaxRinBuf[2*iM + iDim];
208 }
209 if (_material2n.count(materialsInBuf[iM]) == 0) {
210 _material2n[materialsInBuf[iM]] = materialCountInBuf[iM];
211 _material2min[materialsInBuf[iM]] = minPhysR;
212 _material2max[materialsInBuf[iM]] = maxPhysR;
213 }
214 else {
215 _material2n[materialsInBuf[iM]] += materialCountInBuf[iM];
216 for (int iDim=0; iDim<2; iDim++) {
217 if (_material2min[materialsInBuf[iM]][iDim] > minPhysR[iDim]) {
218 _material2min[materialsInBuf[iM]][iDim] = minPhysR[iDim];
219 }
220 if (_material2max[materialsInBuf[iM]][iDim] < maxPhysR[iDim]) {
221 _material2max[materialsInBuf[iM]][iDim] = maxPhysR[iDim];
222 }
223 }
224 }
225 }
226 }
227 }
228#endif
229
230 //clout.setMultiOutput(true);
231 //print();
232 //clout.setMultiOutput(false);
233
234 if (verbose) {
235 clout << "updated" << std::endl;
236 }
237 _statisticsUpdateNeeded = false;
238 }
239}
240
241template<typename T>
243{
244 update();
245 return const_this->getNmaterials();
246}
247
248template<typename T>
250{
251 return _nMaterials;
252}
253
254template<typename T>
256{
257 update(true);
258 return const_this->getNvoxel(material);
259}
260
261template<typename T>
263{
264 try {
265 return _material2n.at(material);
266 }
267 catch (std::out_of_range& ex) {
268 return 0;
269 }
270}
271
272template<typename T>
274{
275 update();
276 return const_this->getNvoxel();
277}
278
279template<typename T>
281{
282 int total = 0;
283 for (const auto& material : _material2n) {
284 if (material.first!=0) {
285 total+=material.second;
286 }
287 }
288 return total;
289}
290
291template<typename T>
293{
294 update();
295 return const_this->getMinPhysR(material);
296}
297
298template<typename T>
299std::vector<T> SuperGeometryStatistics2D<T>::getMinPhysR(int material) const
300{
301 try {
302 return _material2min.at(material);
303 }
304 catch (std::out_of_range& ex) {
305 return {0, 0};
306 }
307}
308
309template<typename T>
311{
312 update();
313 return const_this->getMaxPhysR(material);
314}
315
316template<typename T>
317std::vector<T> SuperGeometryStatistics2D<T>::getMaxPhysR(int material) const
318{
319 try {
320 return _material2max.at(material);
321 }
322 catch (std::out_of_range& ex) {
323 return {0, 0};
324 }
325}
326
327template<typename T>
329{
330 update();
331 return const_this->getPhysExtend(material);
332}
333
334template<typename T>
335std::vector<T> SuperGeometryStatistics2D<T>::getPhysExtend(int material) const
336{
337 try {
338 std::vector<T> extend;
339 for (int iDim = 0; iDim < 2; iDim++) {
340 extend.push_back(_material2max.at(material)[iDim] - _material2min.at(material)[iDim]);
341 }
342 return extend;
343 }
344 catch (std::out_of_range& ex) {
345 return std::vector<T> {};
346 }
347}
348
349template<typename T>
351{
352 update();
353 return const_this->getPhysRadius(material);
354}
355
356template<typename T>
357std::vector<T> SuperGeometryStatistics2D<T>::getPhysRadius(int material) const
358{
359 std::vector<T> radius;
360 for (int iDim=0; iDim<2; iDim++) {
361 radius.push_back((getMaxPhysR(material)[iDim] - getMinPhysR(material)[iDim])/2.);
362 }
363 return radius;
364}
365
366template<typename T>
368{
369 update();
370 return const_this->getCenterPhysR(material);
371}
372
373template<typename T>
374std::vector<T> SuperGeometryStatistics2D<T>::getCenterPhysR(int material) const
375{
376 std::vector<T> center;
377 for (int iDim=0; iDim<2; iDim++) {
378 center.push_back(getMinPhysR(material)[iDim] + getPhysRadius(material)[iDim]);
379 }
380 return center;
381}
382
383template<typename T>
384std::vector<int> SuperGeometryStatistics2D<T>::getType(int iC, int iX, int iY)
385{
386 return const_this->getType(iC, iX, iY);
387}
388
389template<typename T>
390std::vector<int> SuperGeometryStatistics2D<T>::getType(int iC, int iX, int iY) const
391{
392 int iCloc=_superGeometry->getLoadBalancer().loc(iC);
393 std::vector<int> discreteNormal = _superGeometry->getBlockGeometry(iCloc).getStatistics().getType(iX, iY);
394 return discreteNormal;
395}
396
397template<typename T>
399{
400 update();
401 return const_this->computeNormal(material);
402}
403
404template<typename T>
405std::vector<T> SuperGeometryStatistics2D<T>::computeNormal(int material) const
406{
407 std::vector<T> normal (2,int());
408 for (int iCloc=0; iCloc<_superGeometry->getLoadBalancer().size(); iCloc++) {
409 for (int iDim=0; iDim<2; iDim++) {
410 if (_superGeometry->getBlockGeometry(iCloc).getStatistics().getNvoxel(material)!=0) {
411 normal[iDim] += _superGeometry->getBlockGeometry(iCloc).getStatistics().computeNormal(material)[iDim]*_superGeometry->getBlockGeometry(iCloc).getStatistics().getNvoxel(material);
412 }
413 }
414 }
415
416#ifdef PARALLEL_MODE_MPI
417 for (int iDim=0; iDim<2; iDim++) {
418 singleton::mpi().reduceAndBcast((normal[iDim]), MPI_SUM);
419 }
420#endif
421
422 int nVoxel = getNvoxel(material);
423 if (nVoxel != 0) {
424 for (int iDim=0; iDim<2; iDim++) {
425 normal[iDim] /= nVoxel;
426 }
427 }
428 OLB_ASSERT(nVoxel || (normal[0] == 0 && normal[1] == 0), "if no voxels found we expect the normal to be zero");
429
430 T norm = util::sqrt(normal[0]*normal[0]+normal[1]*normal[1]);
431 if (norm>0.) {
432 normal[0]/=norm;
433 normal[1]/=norm;
434 }
435 return normal;
436}
437
438template<typename T>
439std::vector<int> SuperGeometryStatistics2D<T>::computeDiscreteNormal(int material, T maxNorm)
440{
441 update();
442 return const_this->computeDiscreteNormal(material, maxNorm);
443}
444
445template<typename T>
446std::vector<int> SuperGeometryStatistics2D<T>::computeDiscreteNormal(int material, T maxNorm) const
447{
448 std::vector<T> normal = computeNormal(material);
449 std::vector<int> discreteNormal(2,int(0));
450
451 T smallestAngle = T(0);
452 for (int iX = -1; iX<=1; iX++) {
453 for (int iY = -1; iY<=1; iY++) {
454 T norm = util::sqrt(iX*iX+iY*iY);
455 if (norm>0.&& norm<maxNorm) {
456 T angle = (iX*normal[0] + iY*normal[1])/norm;
457 if (angle>=smallestAngle) {
458 smallestAngle=angle;
459 discreteNormal[0] = iX;
460 discreteNormal[1] = iY;
461 }
462 }
463 }
464 }
465 return discreteNormal;
466}
467
468template<typename T>
470{
471 update();
472 return const_this->print();
473}
474
475template<typename T>
477{
478 for (const auto& material : _material2n) {
479 clout << "materialNumber=" << material.first
480 << "; count=" << material.second
481 << "; minPhysR=(" << _material2min.at(material.first)[0] <<","<< _material2min.at(material.first)[1] <<")"
482 << "; maxPhysR=(" << _material2max.at(material.first)[0] <<","<< _material2max.at(material.first)[1] <<")"
483 << std::endl;
484 }
485}
486
487
488} // namespace olb
Representation of a block geometry.
const BlockGeometryStatistics< T, D > & getStatistics() const
Read only access to the associated block statistic.
int getNvoxel()
Returns the number of voxels with material!=0.
std::vector< T > getPhysExtend(int material)
Returns the phys extend as length in each direction.
std::vector< int > getType(int iC, int iX, int iY)
Returns the boundary type which is characterized by a discrte normal (c.f. Zimny)
std::vector< int > computeDiscreteNormal(int material, T maxNorm=1.1)
Returns discrete normal with norm maxNorm that points into the fluid for paraxial surfaces maxNorm=1....
std::vector< T > getPhysRadius(int material)
Returns the phys radius as length in each direction.
std::vector< T > 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...
SuperGeometryStatistics2D< T > & operator=(SuperGeometryStatistics2D const &rhs)
Copy assignment.
void update(bool verbose=false)
Updates the statistics if it is really needed.
std::vector< T > getMinPhysR(int material)
Returns the min. phys position in each direction.
int getNmaterials()
Returns the number of different materials.
std::vector< T > getMaxPhysR(int material)
Returns the max. phys position in each direction.
std::vector< T > computeNormal(int material)
Returns normal that points into the fluid for paraxial surfaces.
SuperGeometryStatistics2D(SuperGeometry< T, 2 > *superGeometry)
Constructor.
bool & getStatisticsStatus()
Read and write access to a flag, which indicates if an uptate is needed (=true)
Representation of a statistic for a parallel 2D geometry.
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.
#define OLB_ASSERT(COND, MESSAGE)
Definition olbDebug.h:45
Representation of a statistic for a parallel 2D geometry – header file.
Representation of a parallel 2D geometry – header file.