OpenLB 1.7
Loading...
Searching...
No Matches
superLattice.hh
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2007 Mathias J. Krause
4 * 2021 Adrian Kummerlaender
5 * E-mail contact: info@openlb.net
6 * The most recent release of OpenLB can be downloaded at
7 * <http://www.openlb.net/>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public
20 * License along with this program; if not, write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 */
24
25#ifndef SUPER_LATTICE_HH
26#define SUPER_LATTICE_HH
27
28#include "superLattice.h"
29
31#include "cell.h"
32#include "io/base64.h"
33
35
40
41#include "io/serializerIO.h"
42
45
47
49
50namespace olb {
51
52
53template<typename T, typename DESCRIPTOR>
54void SuperLattice<T,DESCRIPTOR>::collectStatistics()
55{
56 T weight;
57 T sum_weight = 0;
58 T average_rho = 0;
59 T average_energy = 0;
60 T maxU = 0;
61 T delta = 0;
62
63 getStatistics().reset();
64
65 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
66 delta = this->_cuboidGeometry.get(this->_loadBalancer.glob(iC)).getDeltaR();
67 weight = _block[iC]->getStatistics().getNumCells() * delta
68 * delta * delta;
69 sum_weight += weight;
70 average_rho += _block[iC]->getStatistics().getAverageRho()
71 * weight;
72 average_energy += _block[iC]->getStatistics().getAverageEnergy()
73 * weight;
74 if (maxU < _block[iC]->getStatistics().getMaxU()) {
75 maxU = _block[iC]->getStatistics().getMaxU();
76 }
77 }
78
79#ifdef PARALLEL_MODE_MPI
80 singleton::mpi().reduceAndBcast(sum_weight, MPI_SUM);
81 singleton::mpi().reduceAndBcast(average_rho, MPI_SUM);
82 singleton::mpi().reduceAndBcast(average_energy, MPI_SUM);
83 singleton::mpi().reduceAndBcast(maxU, MPI_MAX);
84#endif
85
86 average_rho = average_rho / sum_weight;
87 average_energy = average_energy / sum_weight;
88
89 getStatistics().reset(average_rho, average_energy, maxU, (int) sum_weight);
90 getStatistics().incrementTime();
91
92 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
93 delta = this->_cuboidGeometry.get(this->_loadBalancer.glob(iC)).getDeltaR();
94 _block[iC]->getStatistics().reset(average_rho, average_energy,
95 maxU, (int) sum_weight);
96 _block[iC]->getStatistics().incrementTime();
97 }
98}
99
100template<typename T, typename DESCRIPTOR>
102 : SuperStructure<T,DESCRIPTOR::d>(superGeometry.getCuboidGeometry(),
103 superGeometry.getLoadBalancer(),
104 superGeometry.getOverlap()),
105 _statistics()
106{
107 using namespace stage;
108
109 auto& load = this->getLoadBalancer();
110
111 for (int iC = 0; iC < load.size(); ++iC) {
112 auto& cuboid = this->_cuboidGeometry.get(load.glob(iC));
113 #ifdef PLATFORM_GPU_CUDA
114 if (load.platform(iC) == Platform::GPU_CUDA) {
115 if (gpu::cuda::device::getCount() == 0) {
116 throw std::runtime_error("Load balancer requested GPU processing for cuboid "
117 + std::to_string(load.glob(iC))
118 + " but no CUDA device was found on rank "
119 + std::to_string(singleton::mpi().getRank()));
120
121 }
122 }
123 #endif
125 load.platform(iC), cuboid.getExtent(), this->getOverlap()));
126 }
127
128 {
129 auto& communicator = getCommunicator(PostCollide());
130 communicator.template requestField<descriptors::POPULATION>();
131 communicator.requestOverlap(1); // Required for inter-block propagation
132 communicator.exchangeRequests();
133 }
134
135 {
136 auto& communicator = getCommunicator(Full());
137 DESCRIPTOR::fields_t::for_each([&](auto field) {
138 communicator.template requestField<typename decltype(field)::type>();
139 });
140 // VTK output includes overlap of 1, some implicit dependencies for overlap of 2 exist
141 communicator.requestOverlap(std::min(2, this->getOverlap()));
142 communicator.exchangeRequests();
143 }
144
145 _statisticsEnabled = true;
146 _communicationNeeded = true;
147}
148
149template<typename T, typename DESCRIPTOR>
151{
152#ifdef PARALLEL_MODE_MPI
153 if (this->_loadBalancer.isLocal(latticeR[0])) {
154 if constexpr (DESCRIPTOR::d == 3) {
155 return _block[this->_loadBalancer.loc(latticeR[0])]->get(latticeR[1], latticeR[2], latticeR[3]);
156 } else {
157 return _block[this->_loadBalancer.loc(latticeR[0])]->get(latticeR[1], latticeR[2]);
158 }
160 else {
161 throw std::domain_error("Cuboid iC must be locally available");
163#else
164 if constexpr (DESCRIPTOR::d == 3) {
165 return _block[this->_loadBalancer.loc(latticeR[0])]->get(latticeR[1], latticeR[2], latticeR[3]);
166 } else {
167 return _block[this->_loadBalancer.loc(latticeR[0])]->get(latticeR[1], latticeR[2]);
168 }
169#endif
170}
171
172template<typename T, typename DESCRIPTOR>
173template<typename... R>
174std::enable_if_t<sizeof...(R) == DESCRIPTOR::d+1, Cell<T,DESCRIPTOR>>
176{
177 return get({latticeR...});
178}
179
180template<typename T, typename DESCRIPTOR>
182{
183 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
184 _block[iC]->initialize();
185 }
186 _communicationNeeded = true;
187}
188
189template<typename T, typename DESCRIPTOR>
190template<typename DYNAMICS>
193 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
194 _block[iC]->template defineDynamics<DYNAMICS>(indicator->getBlockIndicatorF(iC));
195 }
196}
197
198template<typename T, typename DESCRIPTOR>
199template<typename DYNAMICS>
201{
202 defineDynamics<DYNAMICS>(sGeometry.getMaterialIndicator(material));
203}
204
205template<typename T, typename DESCRIPTOR>
206template<template<typename...> typename DYNAMICS>
208{
209 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
210 _block[iC]->template defineDynamics<DYNAMICS<T,DESCRIPTOR>>(indicator->getBlockIndicatorF(iC));
212}
213
214template<typename T, typename DESCRIPTOR>
215template<template<typename...> typename DYNAMICS>
216void SuperLattice<T,DESCRIPTOR>::defineDynamics(SuperGeometry<T,DESCRIPTOR::d>& sGeometry, int material)
217{
218 defineDynamics<DYNAMICS>(sGeometry.getMaterialIndicator(material));
220
221template<typename T, typename DESCRIPTOR>
223 Dynamics<T,DESCRIPTOR>* dynamics)
224{
225 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
226 _block[iC]->defineDynamics(indicator->getBlockIndicatorF(iC), dynamics);
227 }
228}
229
230template<typename T, typename DESCRIPTOR>
232 Dynamics<T,DESCRIPTOR>* dynamics)
234 defineDynamics(sGeometry.getMaterialIndicator(material), dynamics);
235}
236
237template<typename T, typename DESCRIPTOR>
240{
241 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
242 _block[iC]->defineRho(indicator->getBlockIndicatorF(iC),
243 rho);
244 }
245 _communicationNeeded = true;
246}
248template<typename T, typename DESCRIPTOR>
252 defineRho(sGeometry.getMaterialIndicator(material), rho);
253}
254
255template<typename T, typename DESCRIPTOR>
258{
259 #ifdef PARALLEL_MODE_OMP
260 #pragma omp parallel for schedule(dynamic,1)
261 #endif
262 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
263 _block[iC]->defineU(indicator->getBlockIndicatorF(iC),
264 u);
265 }
266 _communicationNeeded = true;
267}
268
269template<typename T, typename DESCRIPTOR>
272{
273 defineU(sGeometry.getMaterialIndicator(material), u);
274}
275
276template<typename T, typename DESCRIPTOR>
281 #ifdef PARALLEL_MODE_OMP
282 #pragma omp parallel for schedule(dynamic,1)
283 #endif
284 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
285 _block[iC]->defineRhoU(indicator->getBlockIndicatorF(iC),
286 rho, u);
287 }
288 _communicationNeeded = true;
289}
290
291template<typename T, typename DESCRIPTOR>
295{
296 defineRhoU(sGeometry.getMaterialIndicator(material), rho, u);
297}
298
299template<typename T, typename DESCRIPTOR>
302{
303 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
304 _block[iC]->definePopulations(indicator->getBlockIndicatorF(iC), Pop);
305 }
306 _communicationNeeded = true;
307}
309template<typename T, typename DESCRIPTOR>
312{
313 definePopulations(sGeometry.getMaterialIndicator(material), Pop);
314}
315
316template<typename T, typename DESCRIPTOR>
319{
320 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
321 _block[iC]->definePopulations(indicator->getBlockIndicatorF(iC), Pop.getBlockF(iC));
322 }
323 _communicationNeeded = true;
324}
325
326template<typename T, typename DESCRIPTOR>
329{
330 definePopulations(sGeometry.getMaterialIndicator(material), Pop);
331}
332
333
334template<typename T, typename DESCRIPTOR>
335template <typename FIELD>
338{
339 if (field->getBlockFSize() == this->_loadBalancer.size()) {
340 for (int iC=0; iC < this->_loadBalancer.size(); ++iC) {
341 _block[iC]->template defineField<FIELD>(indicator->getBlockIndicatorF(iC),
342 field->getBlockF(iC));
343 }
344 }
345 else {
346 FieldD<T,DESCRIPTOR,FIELD> fieldTmp;
347 int coords[DESCRIPTOR::d+1];
348 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
349 _block[iC]->forSpatialLocations([&](LatticeR<DESCRIPTOR::d> loc) {
350 coords[0] = iC;
351 for (int j = 0; j < DESCRIPTOR::d; ++j) {
352 coords[j+1] = loc[j];
353 }
354 if (indicator(coords)) {
355 field(fieldTmp.data(), coords);
356 _block[iC]->get(loc).template setField<FIELD>(fieldTmp);
357 }
358 });
359 }
360 }
361 _communicationNeeded = true;
362}
363
364template<typename T, typename DESCRIPTOR>
365template <typename FIELD>
368{
369 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
370 _block[iC]->template defineField<FIELD>(indicator->getBlockIndicatorF(iC),
371 field);
372 }
373 _communicationNeeded = true;
374}
376template<typename T, typename DESCRIPTOR>
377template <typename FIELD>
380{
381 defineField<FIELD>(sGeometry.getMaterialIndicator(material), std::forward<decltype(field)>(field));
382}
383
384template<typename T, typename DESCRIPTOR>
385template <typename FIELD>
388
389{
390 defineField<FIELD>(sGeometry.getMaterialIndicator(material), field);
392
393template<typename T, typename DESCRIPTOR>
394template <typename FIELD>
397{
398 SuperIndicatorFfromIndicatorF2D<T> indicatorF(indicator, sGeometry);
399 defineField<FIELD>(indicatorF, field);
401
402template<typename T, typename DESCRIPTOR>
403template <typename FIELD>
406{
407 SuperIndicatorFfromIndicatorF3D<T> indicatorF(indicator, sGeometry);
408 defineField<FIELD>(indicatorF, field);
410
411template<typename T, typename DESCRIPTOR>
412template <typename PARAMETER>
415 for (int iC=0; iC < this->getLoadBalancer().size(); ++iC) {
416 _block[iC]->template setParameter<PARAMETER>(field);
417 }
418}
419
420template<typename T, typename DESCRIPTOR>
421template <typename PARAMETER, typename DYNAMICS>
423{
424 for (int iC=0; iC < this->getLoadBalancer().size(); ++iC) {
425 _block[iC]->template getData<OperatorParameters<DYNAMICS>>().template set<PARAMETER>(
426 std::forward<decltype(field)>(field));
427 }
428}
429
430template<typename T, typename DESCRIPTOR>
431template <typename PARAMETER, template<typename...> typename DYNAMICS>
432void SuperLattice<T,DESCRIPTOR>::setParameterOfDynamics(FieldD<T,DESCRIPTOR,PARAMETER>&& field)
434 setParameterOfDynamics<PARAMETER,DYNAMICS<T,DESCRIPTOR>>(std::forward<decltype(field)>(field));
435}
436
437template<typename T, typename DESCRIPTOR>
438template <typename PARAMETER, Platform PLATFORM, typename FIELD>
441 static_assert(DESCRIPTOR::template size<PARAMETER>() == DESCRIPTOR::template size<FIELD>(),
442 "PARAMETER size must equal FIELD size");
443 static_assert(std::is_same_v<typename PARAMETER::template value_type<T>,
444 typename FIELD::template value_type<T>*>,
445 "PARAMETER must store pointers to FIELD components");
446 for (int iC=0; iC < this->getLoadBalancer().size(); ++iC) {
447 _block[iC]->template setParameter<PARAMETER>(fieldArray);
448 }
449}
451template<typename T, typename DESCRIPTOR>
456 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
457 _block[iC]->iniEquilibrium(indicator->getBlockIndicatorF(iC), rho, u);
459 _communicationNeeded = true;
460}
461
462template<typename T, typename DESCRIPTOR>
466{
467 iniEquilibrium(sGeometry.getMaterialIndicator(material), rho, u);
468}
469
470template<typename T, typename DESCRIPTOR>
474{
475 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
476 _block[iC]->iniEquilibrium(indicator->getBlockIndicatorF(iC), rho, u.getBlockF(iC));
477 }
478 _communicationNeeded = true;
479}
480
481template<typename T, typename DESCRIPTOR>
485{
486 iniEquilibrium(sGeometry.getMaterialIndicator(material), rho, u);
487}
488
489
490template<typename T, typename DESCRIPTOR>
495{
496 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
497 _block[iC]->iniRegularized(indicator->getBlockIndicatorF(iC), rho, u, pi);
498 }
499 _communicationNeeded = true;
500}
501
502template<typename T, typename DESCRIPTOR>
507{
508 iniRegularized(sGeometry.getMaterialIndicator(material), rho, u, pi);
509}
510
511template<typename T, typename DESCRIPTOR>
513{
514 using namespace stage;
515
516 waitForBackgroundTasks(PreCollide());
517 auto& load = this->_loadBalancer;
518
519 if (_statisticsEnabled) {
520 setParameter<statistics::AVERAGE_RHO>(getStatistics().getAverageRho());
521 }
522
523 // Optional pre processing stage
524 executePostProcessors(PreCollide());
525
526 #ifdef PARALLEL_MODE_OMP
527 #pragma omp taskloop
528 #endif
529 for (int iC = 0; iC < load.size(); ++iC) {
530 _block[iC]->collide();
531 }
532
533 // Communicate propagation overlap, optional post processing
534 executePostProcessors(PostCollide());
535
536 // Block-local propagation
537 for (int iC = 0; iC < load.size(); ++iC) {
538 _block[iC]->stream();
539 }
540
541 // Communicate (default) post processor neighborhood and apply them
542 executePostProcessors(PostStream());
543
544 // Execute custom tasks (arbitrary callables)
545 // (used for multi-stage models such as free surface)
546 executeCustomTasks(PostStream());
547
548 // Final communication stage (e.g. for external coupling)
549 getCommunicator(PostPostProcess()).communicate();
550
551 if (_statisticsEnabled) {
552 collectStatistics();
553 }
554 _communicationNeeded = true;
555}
556
557template<typename T, typename DESCRIPTOR>
558template<typename STAGE>
560{
561 #ifdef PLATFORM_GPU_CUDA
563 #endif
564
565 getCommunicator(stage).communicate();
566
567 auto& load = this->_loadBalancer;
568
569 #ifdef PARALLEL_MODE_OMP
570 #pragma omp taskloop
571 #endif
572 for (int iC = 0; iC < load.size(); ++iC) {
573 _block[iC]->template postProcess<STAGE>();
574 }
575}
576
577template<typename T, typename DESCRIPTOR>
578template<typename STAGE>
580{
581 auto iter = _communicator.find(typeid(STAGE));
582 if (iter == _communicator.end()) {
583 iter = std::get<0>(_communicator.emplace(typeid(STAGE),
584 std::make_unique<SuperCommunicator<T,SuperLattice>>(*this)));
585 }
586 return *std::get<1>(*iter);
587}
588
589template<typename T, typename DESCRIPTOR>
591{
592 if (_communicationNeeded) {
593 getCommunicator(stage::Full()).communicate();
594 _communicationNeeded = false;
595 }
596}
597
598template<typename T, typename DESCRIPTOR>
600{
601 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
602 _block[iC]->stripeOffDensityOffset(offset);
603 }
604 _communicationNeeded = true;
605}
606
607template<typename T, typename DESCRIPTOR>
612
613template<typename T, typename DESCRIPTOR>
615{
616 return _statistics;
617}
618
619template<typename T, typename DESCRIPTOR>
620template<typename STAGE>
623{
624 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
625 int overlap = getBlock(iC).getPadding();
626 PostProcessorGenerator<T,DESCRIPTOR> *extractedPpGen = ppGen.clone();
627 extractedPpGen->reset(-overlap+1, getBlock(iC).getExtent()+overlap-2);
628 getBlock(iC).template addPostProcessor<STAGE>(*extractedPpGen);
629 delete extractedPpGen;
630 }
631}
632
633template<typename T, typename DESCRIPTOR>
634template<typename STAGE>
637{
638 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
639 getBlock(iC).template addPostProcessor<STAGE>(indicator->getBlockIndicatorF(iC),
640 ppGen);
641 }
642 _communicationNeeded = true;
643}
644
645template<typename T, typename DESCRIPTOR>
646template<typename STAGE>
649{
650 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
651 getBlock(iC).addPostProcessor(typeid(STAGE),
652 indicator->getBlockIndicatorF(iC),
653 std::forward<decltype(promise)>(promise));
654 }
655}
656
657template<typename T, typename DESCRIPTOR>
658template<typename STAGE>
660{
661 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
662 getBlock(iC).addPostProcessor(typeid(STAGE),
663 std::forward<decltype(promise)>(promise));
664 }
665}
666
667template<typename T, typename DESCRIPTOR>
668template<typename STAGE>
670 SuperGeometry<T,DESCRIPTOR::d>& sGeometry, int material,
672{
673 addPostProcessor<STAGE>(sGeometry.getMaterialIndicator(material), ppGen);
674}
675
676template<typename T, typename DESCRIPTOR>
677template<typename PARTNER_DESCRIPTOR>
680 std::vector<SuperLattice<T,PARTNER_DESCRIPTOR>*> partnerLattices)
681{
682 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
683 std::vector<BlockStructureD<DESCRIPTOR::d>*> partners;
684 for (auto partnerLattice: partnerLattices) {
685 partners.push_back(&partnerLattice->getBlock(iC));
686 }
687 int overlap = getBlock(iC).getPadding();
688 LatticeCouplingGenerator<T,DESCRIPTOR> *extractedLcGen = lcGen.clone();
689 extractedLcGen->reset(-overlap+1, getBlock(iC).getExtent()+overlap-2);
690 getBlock(iC).addLatticeCoupling(*extractedLcGen, partners);
691 delete extractedLcGen;
692 }
693 return;
694}
695
696template<typename T, typename DESCRIPTOR>
697template<typename PARTNER_DESCRIPTOR>
700 std::vector<SuperLattice<T,PARTNER_DESCRIPTOR>*> partnerLattices)
701{
702 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
703 std::vector<BlockStructureD<DESCRIPTOR::d>*> partners;
704 for (auto partnerLattice: partnerLattices) {
705 partners.push_back(&partnerLattice->getBlock(iC));
706 }
707 getBlock(iC).addLatticeCoupling(indicator->getBlockIndicatorF(iC),
708 lcGen,
709 partners);
710 }
711}
712
713template<typename T, typename DESCRIPTOR>
714template<typename PARTNER_DESCRIPTOR>
717 std::vector<SuperLattice<T,PARTNER_DESCRIPTOR>*> partnerLattices)
718{
719 addLatticeCoupling(sGeometry.getMaterialIndicator(material),
720 lcGen, partnerLattices);
721}
722
723template<typename T, typename DESCRIPTOR>
724template<typename... PARTNER_DESCRIPTORS>
727 PARTNER_DESCRIPTORS&... partnerLattices)
728{
729 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
730 std::vector<BlockStructureD<DESCRIPTOR::d>*> partners{&partnerLattices.getBlock(iC)...};
731 int overlap = getBlock(iC).getPadding();
732 LatticeCouplingGenerator<T,DESCRIPTOR> *extractedLcGen = lcGen.clone();
733 extractedLcGen->reset(-overlap+1, getBlock(iC).getExtent()+overlap-2);
734 getBlock(iC).addLatticeCoupling(*extractedLcGen, partners);
735 delete extractedLcGen;
736 }
737 return;
738}
739
740template<typename T, typename DESCRIPTOR>
741template<typename... PARTNER_DESCRIPTORS>
744 PARTNER_DESCRIPTORS&... partnerLattices)
745{
746 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
747 std::vector<BlockStructureD<DESCRIPTOR::d>*> partners{&partnerLattices.getBlock(iC)...};
748 getBlock(iC).addLatticeCoupling(indicator->getBlockIndicatorF(iC),
749 lcGen,
750 partners);
751 }
752}
753
754template<typename T, typename DESCRIPTOR>
755template<typename... PARTNER_DESCRIPTORS>
758 PARTNER_DESCRIPTORS&... partnerLattices)
759{
760 addLatticeCoupling(sGeometry.getMaterialIndicator(material),
761 lcGen, partnerLattices...);
762}
763
764template<typename T, typename DESCRIPTOR>
766{
767 getCommunicator(stage::PreCoupling()).communicate();
768 for (int iC = 0; iC < this->_loadBalancer.size(); ++iC) {
769 _block[iC]->executeCoupling();
770 }
771 executeCustomTasks(stage::Coupling());
772 getCommunicator(stage::PostCoupling()).communicate();
773 _communicationNeeded = true;
774}
775
776template<typename T, typename DESCRIPTOR>
777template<typename STAGE>
779{
780 for (auto& f : _customTasks[typeid(STAGE)]) {
781 f();
782 }
783}
784
785template<typename T, typename DESCRIPTOR>
786template <typename STAGE, typename F>
788{
789 _backgroundTasks[typeid(STAGE)].emplace_back(singleton::pool().schedule(f));
790}
791
792template<typename T, typename DESCRIPTOR>
793template <typename F>
795{
796 auto& load = this->getLoadBalancer();
797 for (int iC=0; iC < load.size(); ++iC) {
798 if (isPlatformCPU(load.platform(iC))) {
799 scheduleBackgroundTask<stage::PreCollide>(std::bind(f, iC));
800 }
801 }
802 for (int iC=0; iC < load.size(); ++iC) {
803 if (load.platform(iC) == Platform::GPU_CUDA) {
804 scheduleBackgroundTask<stage::PreContextSwitchTo<ProcessingContext::Evaluation>>(std::bind(f, iC));
805 }
806 }
807}
808
809template<typename T, typename DESCRIPTOR>
810template <typename CONTEXT>
812{
813 vtkContext([](auto& writer, std::size_t iT) {
814 writer.writePVD(iT);
815 });
816 scheduleBackgroundOutput([vtkContext](int iC) {
817 vtkContext([&](auto& writer, std::size_t iT) {
818 writer.writeVTI(iT, iC);
819 });
820 });
821}
822
823template<typename T, typename DESCRIPTOR>
824template <typename STAGE>
826{
827 if (!_backgroundTasks[typeid(STAGE)].empty()) {
828 singleton::pool().waitFor(_backgroundTasks[typeid(STAGE)]);
829 _backgroundTasks[typeid(STAGE)].clear();
830 }
831}
832
833template<typename T, typename DESCRIPTOR>
835{
836 return std::accumulate(_block.begin(), _block.end(), size_t(0), [](std::size_t sum, auto& b) -> std::size_t {
837 return sum + b->getNblock();
838 });
839}
840
841
842template<typename T, typename DESCRIPTOR>
844{
845 return std::accumulate(_block.begin(), _block.end(), size_t(0), [](std::size_t sum, auto& b) -> std::size_t {
846 return sum + b->getSerializableSize();
847 });
848}
849
850template<typename T, typename DESCRIPTOR>
851bool* SuperLattice<T,DESCRIPTOR>::getBlock(std::size_t iBlock, std::size_t& sizeBlock, bool loadingMode)
852{
853 std::size_t currentBlock = 0;
854 bool* dataPtr = nullptr;
855
856 for (std::size_t iC=0; iC < _block.size(); ++iC) {
857 registerSerializableOfConstSize(iBlock, sizeBlock, currentBlock, dataPtr, getBlock(iC), loadingMode);
858 }
859
860 return dataPtr;
861}
862
863template<typename T, typename DESCRIPTOR>
865{
866 for (int iC=0; iC < this->_loadBalancer.size(); ++iC) {
867 _block[iC]->postLoad();
868 }
869}
870
871
872}
873
874#endif
Definition of a LB cell – header file.
AnalyticalF are applications from DD to XD, where X is set by the constructor.
Highest-level interface to Cell data.
Definition cell.h:148
SoA storage for instances of a single FIELD.
Smart pointer for managing the various ways of passing functors around.
Definition functorPtr.h:60
IndicatorF2D is an application from .
IndicatorF3D is an application from .
Factory for instances of a specific POST_PROCESSOR type.
bool load(std::string fileName="", const bool enforceUint=false)
Load Serializable from file fileName
Generic communicator for overlaps between blocks of SUPER.
Representation of a statistic for a parallel 2D geometry.
std::unique_ptr< SuperIndicatorF< T, D > > getMaterialIndicator(std::vector< int > &&materials)
Returns a material indicator using the given vector of materials.
SuperIndicatorF2D from IndicatorF2D.
SuperIndicatorF3D from IndicatorF3D.
Super class maintaining block lattices for a cuboid decomposition.
void communicate() override
Perform full overlap communication if needed.
SuperCommunicator< T, SuperLattice > & getCommunicator(STAGE stage=STAGE())
Return communicator for given communication stage.
void waitForBackgroundTasks(STAGE stage=STAGE{})
Block until all background tasks scheduled for STAGE are completed.
LatticeStatistics< T > & getStatistics()
Return a handle to the LatticeStatistics object.
void iniRegularized(FunctorPtr< SuperIndicatorF< T, DESCRIPTOR::d > > &&indicator, AnalyticalF< DESCRIPTOR::d, T, T > &rho, AnalyticalF< DESCRIPTOR::d, T, T > &u, AnalyticalF< DESCRIPTOR::d, T, T > &pi)
Initialize by non- and equilibrium on a domain described by an indicator.
void collideAndStream()
Core implementation of a single iteration of the collide and stream loop.
void addPostProcessor(PostProcessorGenerator< T, DESCRIPTOR > const &ppGen)
Add a non-local post-processing step (legacy)
void executeCoupling()
Executes coupling with partner lattices (legacy)
void defineField(FunctorPtr< SuperIndicatorF< T, DESCRIPTOR::d > > &&indicator, FunctorPtr< SuperF< DESCRIPTOR::d, T, T > > &&field)
Define an external field on a domain described by an indicator.
void defineRho(FunctorPtr< SuperIndicatorF< T, DESCRIPTOR::d > > &&, AnalyticalF< DESCRIPTOR::d, T, T > &rho)
Define rho on a domain described by an indicator.
void addLatticeCoupling(LatticeCouplingGenerator< T, DESCRIPTOR > const &lcGen, std::vector< SuperLattice< T, PARTNER_DESCRIPTOR > * > partnerLattices)
Adds a coupling generator for a vector of partner superLattice (legacy)
void setParameter(FieldD< T, DESCRIPTOR, PARAMETER > field)
Update PARAMETER in all dynamics and post processors.
void stripeOffDensityOffset(T offset)
Subtract constant offset from the density.
void definePopulations(FunctorPtr< SuperIndicatorF< T, DESCRIPTOR::d > > &&indicator, AnalyticalF< DESCRIPTOR::d, T, T > &Pop)
Define a population on a domain described by an indicator.
std::size_t getSerializableSize() const override
Binary size for the serializer.
std::size_t getNblock() const override
Number of data blocks for the serializable interface.
void iniEquilibrium(FunctorPtr< SuperIndicatorF< T, DESCRIPTOR::d > > &&indicator, AnalyticalF< DESCRIPTOR::d, T, T > &rho, AnalyticalF< DESCRIPTOR::d, T, T > &u)
Initialize by equilibrium on a domain described by an indicator.
SuperLattice(SuperGeometry< T, DESCRIPTOR::d > &superGeometry)
Construct lattice for the cuboid decomposition of superGeometry.
void postLoad() override
void executeCustomTasks(STAGE stage=STAGE())
Executes custom tasks assigned to STAGE.
void defineDynamics(FunctorPtr< SuperIndicatorF< T, DESCRIPTOR::d > > &&indicator)
Set dynamics of indicated cells to DYNAMICS.
void initialize()
Initialize lattice to be ready for simulation.
BlockLattice< T, DESCRIPTOR > & getBlock(int locC)
Return BlockLattice with local index locC.
void defineU(FunctorPtr< SuperIndicatorF< T, DESCRIPTOR::d > > &&indicator, AnalyticalF< DESCRIPTOR::d, T, T > &u)
Define u on a domain described by an indicator.
void defineRhoU(FunctorPtr< SuperIndicatorF< T, DESCRIPTOR::d > > &&indicator, AnalyticalF< DESCRIPTOR::d, T, T > &rho, AnalyticalF< DESCRIPTOR::d, T, T > &u)
Define rho and u on a domain described by an indicator.
void scheduleBackgroundOutput(F &&f)
Schedule F(iC) for one-off background output of block data.
void scheduleBackgroundOutputVTK(CONTEXT &&vtkContext)
Schedule one-off background output of given VTK CONTEXT.
void setParameterOfDynamics(FieldD< T, DESCRIPTOR, PARAMETER > &&field)
Update PARAMETER in DYNAMICS.
void scheduleBackgroundTask(F &&f)
Schedule F for one-off background execution to be finished by STAGE.
Cell< T, DESCRIPTOR > get(LatticeR< DESCRIPTOR::d+1 > latticeR)
Get local cell interface.
void executePostProcessors(STAGE stage=STAGE())
Executes post processors for STAGE.
int getOverlap()
Read and write access to the overlap.
CuboidGeometry< T, D > & _cuboidGeometry
The grid structure is stored here.
LoadBalancer< T > & getLoadBalancer()
Read and write access to the load balancer.
std::future< R > schedule(F &&f)
Schedule F and return future of its return value.
Definition threadPool.h:145
void waitFor(std::vector< std::future< T > > &futures)
Blocks until all tasks producing the given futures are completed.
Definition threadPool.h:174
Plain old scalar vector.
Definition vector.h:47
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.
The description of a vector of 2D cuboid – header file.
The description of a vector of 3D cuboid – header file.
Wrapper functions that simplify the use of MPI.
std::enable_if_t< DESCRIPTOR::d==2, std::shared_ptr< SuperF2D< T > > > field(SuperLattice< T, DESCRIPTOR > &sLattice)
Returns external field functor.
int getCount()
Return number of available devices.
Definition device.hh:42
void synchronize()
Synchronize device.
Definition device.hh:64
ThreadPool & pool()
Definition olbInit.cpp:37
MpiManager & mpi()
Top level namespace for all of OpenLB.
std::conditional_t< DESCRIPTOR::d==2, LatticeCouplingGenerator2D< T, DESCRIPTOR >, LatticeCouplingGenerator3D< T, DESCRIPTOR > > LatticeCouplingGenerator
Definition aliases.h:168
@ GPU_CUDA
Vector CPU (AVX2 / AVX-512 collision)
std::conditional_t< D==2, SuperF2D< T, U >, SuperF3D< T, U > > SuperF
Definition aliases.h:198
constexpr bool isPlatformCPU(Platform platform)
Returns true if platform is equal to Platform::CPU_*.
Definition platform.h:154
CONCRETIZABLE::base_t * constructUsingConcretePlatform(Platform platform, ARGS &&... args)
Definition platform.h:133
std::conditional_t< DESCRIPTOR::d==2, PostProcessorGenerator2D< T, DESCRIPTOR >, PostProcessorGenerator3D< T, DESCRIPTOR > > PostProcessorGenerator
Definition aliases.h:77
std::conditional_t< D==2, SuperIndicatorF2D< T >, SuperIndicatorF3D< T > > SuperIndicatorF
Definition aliases.h:208
Curried ConcreteBlockLattice template for use in callUsingConcretePlatform.
Interface for per-cell dynamics.
Definition interface.h:54
Coupling post processors.
Definition stages.h:47
On-demand communication at SuperLattice::communicate.
Definition stages.h:44
Communication after coupling.
Definition stages.h:42
Communication prior to coupling.
Definition stages.h:40
Representation of the 2D geometry – generic implementation.