OpenLB 1.7
Loading...
Searching...
No Matches
superParticleSystem.hh
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2022-2023 Nicolas Hafen, Jan E. Marquardt
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
24#ifndef SUPER_PARTICLE_SYSTEM_HH
25#define SUPER_PARTICLE_SYSTEM_HH
26
27namespace olb {
28
29namespace particles {
30
31template <typename T, typename PARTICLETYPE>
33 SuperStructure<T, PARTICLETYPE::d>& superStructure, T maximalCircumRadius)
34 : _superStructure(superStructure)
35 , _serialSize(ParticleSystem<T, PARTICLETYPE>(1).getSerialSize())
36 , _maximalCircumRadius(maximalCircumRadius)
37{
38 static_assert(access::providesValid<PARTICLETYPE>(), "Field GENERAL:VALID has to be provided");
39 auto loadBalancer = superStructure.getLoadBalancer();
40 // always create at least one BlockParticleSystem to counteract possible problems
41 // (for example in creator functions, where the first blockParticleSystem is hard coded)
42 _blockParticleSystems.push_back(new ParticleSystem<T, PARTICLETYPE>);
43 for (int iC = 1; iC < loadBalancer.size(); ++iC) {
44 _blockParticleSystems.push_back(new ParticleSystem<T, PARTICLETYPE>);
45 }
46
47 _cuboidNeighborhood.resize(_superStructure.getCuboidGeometry().getNc());
48 updateCuboidNeighborhood();
49}
51template <typename T, typename PARTICLETYPE>
53 SuperGeometry<T, PARTICLETYPE::d>& superGeometry, T maximalCircumRadius)
54 : SuperParticleSystem<T, PARTICLETYPE>(
55 static_cast<SuperStructure<T, PARTICLETYPE::d>&>(superGeometry), maximalCircumRadius)
56{}
58template <typename T, typename PARTICLETYPE>
61 OstreamManager clout(std::cout, "SuperParticleSystem");
62 auto loadBalancer = _superStructure.getLoadBalancer();
63 auto rank = singleton::mpi().getRank();
64 clout << "---SuperParticleSystem---" << std::endl;
65 clout.setMultiOutput(true);
66#ifdef PARALLEL_MODE_MPI
68#endif
69 for (int iC = 0; iC < loadBalancer.size(); ++iC) {
70 int globiC = loadBalancer.glob(iC);
71 auto& bParticleSystem = *_blockParticleSystems[iC];
72 size_t size = bParticleSystem.size();
73 clout << "BlockParticleSystem " << globiC << " (" << rank << "," << iC
74 << ")"
75 << ": nop=" << size << std::endl;
76 }
77 clout.setMultiOutput(false);
78#ifdef PARALLEL_MODE_MPI
80#endif
81 clout << "-------------------------" << std::endl;
82}
83
84template <typename T, typename PARTICLETYPE>
86 std::shared_ptr<dynamics::ParticleDynamics<T,PARTICLETYPE>>& dynamicsSPtr )
87{
88 auto loadBalancer = _superStructure.getLoadBalancer();
89 for (int iC = 0; iC < loadBalancer.size(); ++iC) {
90 auto& bParticleSystem = *_blockParticleSystems[iC];
91 bParticleSystem.addDynamics( dynamicsSPtr );
92 }
93}
94
95template<typename T, typename PARTICLETYPE>
96template <typename DYNAMICS, typename ...Args>
98 auto loadBalancer = _superStructure.getLoadBalancer();
99 for (int iC = 0; iC < loadBalancer.size(); ++iC) {
100 auto& bParticleSystem = *_blockParticleSystems[iC];
101 bParticleSystem.template defineDynamics<DYNAMICS>( std::forward<Args>(args)... );
102 }
103}
104
105template <typename T, typename PARTICLETYPE>
107{
108 return _neighbourRanks;
109}
110
111template <typename T, typename PARTICLETYPE>
113{
114 return _extendedNeighbourRanks;
115}
116
117template <typename T, typename PARTICLETYPE>
118const std::vector<std::unordered_set<int>>& SuperParticleSystem<T, PARTICLETYPE>::getCuboidNeighborhood()
119{
120 return _cuboidNeighborhood;
121}
122
123template <typename T, typename PARTICLETYPE>
124std::vector<ParticleSystem<T, PARTICLETYPE>*>&
126{
127 return _blockParticleSystems;
128}
129
130template <typename T, typename PARTICLETYPE>
133{
134 return _superStructure;
135}
136
137template <typename T, typename PARTICLETYPE>
139{
140 return _currentGlobalID++;
141}
142
143template <typename T, typename PARTICLETYPE>
145{
146 return _serialSize;
147}
148
149//TODO: consider using searchParticle() in here instead
150template <typename T, typename PARTICLETYPE>
152SuperParticleSystem<T, PARTICLETYPE>::get(std::size_t globalParticleID)
153{
154 using namespace descriptors;
155
156 for (ParticleSystem<T, PARTICLETYPE>* blockParticleSystem :
157 _blockParticleSystems) {
158 for (std::size_t localiP = 0; localiP < blockParticleSystem->size();
159 ++localiP) {
160 auto particle = blockParticleSystem->get(localiP);
161 const std::size_t currentGlobalParticleID =
162 particle.template getField<PARALLELIZATION, ID>();
163 if (globalParticleID == currentGlobalParticleID) {
164 return particle;
165 }
166 }
167 }
168
169 std::cerr << "ERROR: Rank " << singleton::mpi().getRank()
170 << " cannot find particle with global id " << globalParticleID
171 << std::endl;
172 assert(false);
173 return _blockParticleSystems[0]->get(0);
174}
175
176template <typename T, typename PARTICLETYPE>
177template <typename PCONDITION>
179{
180 std::size_t size = 0;
181 communication::forSystemsInSuperParticleSystem<T,PARTICLETYPE>(
182 *this,
183 [&](ParticleSystem<T, PARTICLETYPE>& particleSystem, int iC, int globiC) {
184 size += particleSystem.template size<PCONDITION>(globiC);
185 });
186#ifdef PARALLEL_MODE_MPI
187 singleton::mpi().reduceAndBcast(size, MPI_SUM);
188#endif
189 return size;
190}
191
192template <typename T, typename PARTICLETYPE>
194{
195 //Check, whether at least one ParticleDynamics present
196#ifdef PARALLEL_MODE_MPI
197 if(singleton::mpi().isMainProcessor()){
198#endif
199 _blockParticleSystems[0]->checkForErrors();
200#ifdef PARALLEL_MODE_MPI
201 }
202#endif
203}
204
205template <typename T, typename PARTICLETYPE>
207 T circumRadius)
208{
209 if(_maximalCircumRadius < circumRadius) {
210 _maximalCircumRadius = circumRadius;
211 updateCuboidNeighborhood();
212 }
213}
214
215template <typename T, typename PARTICLETYPE>
217{
218 auto& cuboidGeometry = _superStructure.getCuboidGeometry();
219 const T physDeltaX = cuboidGeometry.getMotherCuboid().getDeltaR();
220 unsigned offset = util::max( util::ceil(_maximalCircumRadius/physDeltaX),
221 _superStructure.getOverlap() );
222 return offset;
223}
224
225
226template <typename T, typename PARTICLETYPE>
227void SuperParticleSystem<T, PARTICLETYPE>::updateCuboidNeighborhood()
228{
229 auto& cuboidGeometry = _superStructure.getCuboidGeometry();
230 unsigned offset = getOffset();
231
232 std::map<int,std::vector<int>> neighbourhood;
233 evaluateCuboidGeometryNeighbourhood( cuboidGeometry, neighbourhood, offset);
234
235 constexpr bool correctFaultyNeighbourhood = true;
236 checkCuboidNeighbourhoodConsistency( neighbourhood, correctFaultyNeighbourhood );
237
238 for ( const auto& cuboidNeighbourPair: neighbourhood){
239 const int globiC = cuboidNeighbourPair.first;
240
241 _cuboidNeighborhood[globiC] =
242 std::unordered_set<int>(cuboidNeighbourPair.second.begin(),
243 cuboidNeighbourPair.second.end());
244
245 }
246
247 _neighbourRanks = communication::getNeighbourRanksFromCuboidNeighbourhood<T, PARTICLETYPE::d, false>(
248 _superStructure, _cuboidNeighborhood);
249
250 _extendedNeighbourRanks = _neighbourRanks;
251 for(int rank : _neighbourRanks) {
252 const std::unordered_set<int> neighborRanks = communication::getNeighbourRanksFromCuboidNeighbourhood<
253 T, PARTICLETYPE::d, false>(_superStructure, rank, _cuboidNeighborhood);
254 _extendedNeighbourRanks.insert(neighborRanks.begin(), neighborRanks.end());
255 }
256}
257
258
259} //namespace particles
260
261} //namespace olb
262
263#endif
class for marking output with some text
Representation of a statistic for a parallel 2D geometry.
CuboidGeometry< T, D > & getCuboidGeometry()
Read and write access to cuboid geometry.
LoadBalancer< T > & getLoadBalancer()
Read and write access to the load balancer.
SuperParticleSystem(SuperStructure< T, PARTICLETYPE::d > &superStructure, T maximalCircumRadius=T{0.})
SuperStructure< T, PARTICLETYPE::d > & getSuperStructure()
Particle< T, PARTICLETYPE > get(std::size_t globalParticleID)
const std::unordered_set< int > & getNeighbourRanks()
void addDynamics(std::shared_ptr< dynamics::ParticleDynamics< T, PARTICLETYPE > > &dynamicsSPtr)
const std::vector< std::unordered_set< int > > & getCuboidNeighborhood()
std::vector< ParticleSystem< T, PARTICLETYPE > * > & getBlockParticleSystems()
const std::unordered_set< int > & getExtendedNeighbourRanks()
void synchronizeIO(unsigned tDelay=100, MPI_Comm comm=MPI_COMM_WORLD)
Synchronizes the processes and wait to ensure correct cout order.
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.
std::unordered_set< int > getNeighbourRanksFromCuboidNeighbourhood(SuperStructure< T, D > &superStructure, int rank, std::map< int, std::vector< int > > neighbourhood)
Get neighbour ranks.
Definition utilities.h:55
MpiManager & mpi()
ADf< T, DIM > ceil(const ADf< T, DIM > &a)
Definition aDiff.h:900
cpu::simd::Pack< T > max(cpu::simd::Pack< T > rhs, cpu::simd::Pack< T > lhs)
Definition pack.h:130
Top level namespace for all of OpenLB.
void evaluateCuboidGeometryNeighbourhood(CuboidGeometry2D< T > &cuboidGeometry, std::map< int, std::vector< int > > &neighbourhood, int offset=0)
Evaluate complete neighbourhood and store in std::map.
bool checkCuboidNeighbourhoodConsistency(std::map< int, std::vector< int > > &neighbourhood, bool correct=false, bool verbose=false)
Consistency check for neighbour retrieval.