hemocell
Loading...
Searching...
No Matches
leesEdwardsBC.h
Go to the documentation of this file.
1/*
2This file is part of the HemoCell library
3
4HemoCell is developed and maintained by the Computational Science Lab
5in the University of Amsterdam. Any questions or remarks regarding this library
6can be sent to: info@hemocell.eu
7
8When using the HemoCell library in scientific work please cite the
9corresponding paper: https://doi.org/10.3389/fphys.2017.00563
10
11The HemoCell library is free software: you can redistribute it and/or
12modify it under the terms of the GNU Affero General Public License as
13published by the Free Software Foundation, either version 3 of the
14License, or (at your option) any later version.
15
16The library is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19GNU Affero General Public License for more details.
20
21You should have received a copy of the GNU Affero General Public License
22along with this program. If not, see <http://www.gnu.org/licenses/>.
23*/
24
25/*
26Lees-Edwards boundary condition class which makes use of two data processors
27for calculating and writing of the populations according to the Lees-Edwards algorithm.
28
29Populations are read and writen between two static 2D arrays (topPopulations & bottomPopulations).
30The memory address for the current Lees-Edwards displacement is shared with the hemoCell class.
31
32The 2D arrays and Lees-Edwards displacement are static in order to guarantee data consistency
33after subdivision of the code over the individual lattice blocks.
34
35The velocity in the system comes from setting the macroscopic velocity in the boundary nodes
36
37NOTE: currently the Lees-Edwards algorithm works only in one direction (z-direction)
38
39* @author Daan van Ingen
40*/
41
42#ifndef LEESEDWARDSBC
43#define LEESEDWARDSBC
44
45#include "hemocell.h"
46#include "palabos3D.h"
47#include "palabos3D.hh"
48
49namespace hemo
50{
51
52/* Calculate the streaming of the populations according to the Lees-Edwards algorithm
53 Inherits from data processing functional which handles the subdivision of the code
54 onto individual lattice blocks
55*/
56template <typename T, template <typename U> class Descriptor>
57class LeesEdwardsBCGetPopulations : public plb::BoxProcessingFunctional3D_L<T, Descriptor>
58{
59public:
60 plint nx; // dimension in x direction
61 plint nz; // dimension in z direction
62 double * LEcurrentDisplacement; // Current Lees-Edwards displacement
63 std::vector<std::vector<std::vector<T>>> * topPopulations; // Data structure containing the top populations
64 std::vector<std::vector<std::vector<T>>> * bottomPopulations; // Data structure containing the bottom populations
65 T topVelocity; // Macroscopic top velocity
66 T bottomVelocity; // Macroscopic bottom velocity
67
69 std::vector<std::vector<std::vector<T>>> * topPopulations,
70 std::vector<std::vector<std::vector<T>>> * bottomPopulations)
71 {
72 this->nx = nx;
73 this->nz = nz;
74 this->LEcurrentDisplacement = LEcurrentDisplacement;
75 this->topVelocity = topVelocity;
76 this->bottomVelocity = bottomVelocity;
77 this->topPopulations = topPopulations;
78 this->bottomPopulations = bottomPopulations;
79 }
80
81 /* Convert Palabos array to vector
82
83 * @param populations Palabos array containing lattice node populations
84 * @return vector containing lattice node populations
85 */
86 std::vector<T> populationsArrayToVector(plb::Array<T, Descriptor<T>::q> populations) {
87 std::vector<T> pop(Descriptor<T>::q);
88 for(plint i = 0; i < Descriptor<T>::q; i++) {
89 pop[i] = populations[i];
90 }
91 return pop;
92 }
93
94 /* Non-negative modulo (-a % b gives a negative number in C++)
95 */
97 {
98 return (a % b + b) % b;
99 }
100
101 /* Process function containg the code to be executed onto the individual lattice block.
102 Set macroscopic velocity
103 Calculate new populations according to the Lees-Edwards algorithm
104
105 * @param domain Domain on which to execute code
106 * @param lattice individual block lattice
107 */
108 virtual void process(plb::Box3D domain, plb::BlockLattice3D<T, Descriptor> &lattice)
109 {
110 Dot3D absoluteOffset = lattice.getLocation(); // Location of this block lattice {x, y, z}
111
112 // The portion of the population streamed from node S1 or S2 is determined by the overlap with the reference node
113 double gfrac = std::fmod((*this->LEcurrentDisplacement), 1.0);
114 plint globalX, globalY;
115 plint globalZ0 = absoluteOffset.z + domain.z0;
116 plint globalZ1 = absoluteOffset.z + domain.z1;
117 Cell<T, Descriptor> curCell;
118 Cell<T, Descriptor> s1Cell;
119 Cell<T, Descriptor> s2Cell;
120
121 // Variables for setting the macroscopic velocity
122 T rhoBar;
123 plb::Array<T, Descriptor<T>::d> j;
124
125 if (globalZ1 == this->nz - 1) // Top
126 {
127 for (plint iX = domain.x0; iX <= domain.x1; ++iX)
128 {
129 globalX = absoluteOffset.x + iX;
130 for (plint iY = domain.y0; iY <= domain.y1; ++iY)
131 {
132 globalY = absoluteOffset.y + iY;
133 curCell = lattice.get(iX, iY, domain.z1);
134
135 // Set macroscopic velocity
136 curCell.getDynamics().computeRhoBarJ(curCell, rhoBar, j);
137 curCell.getDynamics().collideExternal(curCell, rhoBar, plb::Array<T,3>(this->topVelocity, 0.0, 0.0), T(), lattice.getInternalStatistics());
138 (*this->topPopulations)[globalX][globalY] = populationsArrayToVector(curCell.getRawPopulations());
139
140 // Determine reference nodes coordinates according to the current displacement
141 plint s1 = domain.x0 + (plint)modNonNegative(std::ceil((*this->LEcurrentDisplacement) + globalX), this->nx);
142 plint s2 = domain.x0 + (plint)modNonNegative(std::floor((*this->LEcurrentDisplacement) + globalX), this->nx);
143
144 // Get the nodes
145 s1Cell = lattice.get(s1, iY, domain.z1);
146 s2Cell = lattice.get(s2, iY, domain.z1);
147
148 // Write resulting LE stream to data structure
149 (*this->topPopulations)[globalX][globalY][3] = gfrac * s1Cell[3] + (1 - gfrac) * s2Cell[3];
150 (*this->topPopulations)[globalX][globalY][6] = gfrac * s1Cell[16] + (1 - gfrac) * s2Cell[16];
151 (*this->topPopulations)[globalX][globalY][8] = gfrac * s1Cell[8] + (1 - gfrac) * s2Cell[8];
152 (*this->topPopulations)[globalX][globalY][16] = gfrac * s1Cell[6] + (1 - gfrac) * s2Cell[6];
153 (*this->topPopulations)[globalX][globalY][18] = gfrac * s1Cell[18] + (1 - gfrac) * s2Cell[18];
154 }
155 }
156 }
157 if (globalZ0 == 0) // Bottom
158 {
159 for (plint iX = domain.x0; iX <= domain.x1; ++iX)
160 {
161 globalX = absoluteOffset.x + iX;
162 for (plint iY = domain.y0; iY <= domain.y1; ++iY)
163 {
164 globalY = absoluteOffset.y + iY;
165 curCell = lattice.get(iX, iY, domain.z0);
166
167 // Set macroscopic velocity
168 curCell.getDynamics().computeRhoBarJ(curCell, rhoBar, j);
169 curCell.getDynamics().collideExternal(curCell, rhoBar, plb::Array<T,3>(this->bottomVelocity, 0.0, 0.0), T(), lattice.getInternalStatistics());
170 (*this->bottomPopulations)[globalX][globalY] = populationsArrayToVector(curCell.getRawPopulations());
171
172 // Determine reference nodes coordinates according to the current displacement
173 plint s1 = domain.x0 + (plint)modNonNegative(std::floor(-(*this->LEcurrentDisplacement) + globalX), this->nx);
174 plint s2 = domain.x0 + (plint)modNonNegative(std::ceil(-(*this->LEcurrentDisplacement) + globalX), this->nx);
175
176 // Get the nodes
177 s1Cell = lattice.get(s1, iY, domain.z0);
178 s2Cell = lattice.get(s2, iY, domain.z0);
179
180 // Write resulting LE stream to data structure
181 (*this->bottomPopulations)[globalX][globalY][7] = gfrac * s1Cell[15] + (1 - gfrac) * s2Cell[15];
182 (*this->bottomPopulations)[globalX][globalY][9] = gfrac * s1Cell[9] + (1 - gfrac) * s2Cell[9];
183 (*this->bottomPopulations)[globalX][globalY][12] = gfrac * s1Cell[12] + (1 - gfrac) * s2Cell[12];
184 (*this->bottomPopulations)[globalX][globalY][15] = gfrac * s1Cell[7] + (1 - gfrac) * s2Cell[7];
185 (*this->bottomPopulations)[globalX][globalY][17] = gfrac * s1Cell[17] + (1 - gfrac) * s2Cell[17];
186 }
187 }
188 }
189 // cout << global::mpi().getRank() << " " << bottomPopulations[5][5][10] << endl;
190 }
191
192 // Clone class to individual lattice blocks
197
198 // Return the type of data that is modified
199 virtual void getTypeOfModification(std::vector<plb::modif::ModifT> &modified) const
200 {
201 modified[0] = modif::nothing;
202 }
203
204 // Only need the bulk of the domain
205 virtual plb::BlockDomain::DomainT appliesTo() const
206 {
207 return BlockDomain::bulk;
208 }
209};
210
211/* Write the streaming of the populations according to the Lees-Edwards algorithm
212 Inherits from data processing functional which handles the subdivision of the code
213 onto individual lattice blocks
214*/
215template <typename T, template <typename U> class Descriptor>
216class LeesEdwardsBCSetPopulations : public plb::BoxProcessingFunctional3D_L<T, Descriptor>
217{
218public:
219 plint nz; // dimension in z direction
220 std::vector<std::vector<std::vector<T>>> * topPopulations; // Data structure containing the top populations
221 std::vector<std::vector<std::vector<T>>> * bottomPopulations; // Data structure containing the bottom populations
222
224 std::vector<std::vector<std::vector<T>>> * topPopulations,
225 std::vector<std::vector<std::vector<T>>> * bottomPopulations) {
226 this->nz = nz;
227 this->topPopulations = topPopulations;
228 this->bottomPopulations = bottomPopulations;
229 }
230
231 /* Convert vector to Palabos array
232
233 * @param populations vector containing lattice node populations
234 * @return Palabos array containing lattice node populations
235 */
236 plb::Array<T, Descriptor<T>::q> populationsVectorToArray(std::vector<T> populations)
237 {
238 plb::Array<T, Descriptor<T>::q> pop;
239 for (plint i = 0; i < DESCRIPTOR<T>::q; i++)
240 {
241 pop[i] = populations[i];
242 }
243 return pop;
244 }
245
246 /* Process function containg the code to be executed onto the individual lattice block.
247 Write new populations to lattice.
248
249 * @param domain Domain on which to execute code
250 * @param lattice individual block lattice
251 */
252 virtual void process(plb::Box3D domain, plb::BlockLattice3D<T, Descriptor> &lattice)
253 {
254 Dot3D absoluteOffset = lattice.getLocation(); // Location of this block lattice {x, y, z}
255
256 plint globalZ0 = absoluteOffset.z + domain.z0;
257 plint globalZ1 = absoluteOffset.z + domain.z1;
258 plint globalX, globalY;
259 plb::Array<T, Descriptor<T>::q> populations;
260
261 if (globalZ1 == this->nz - 1) { // Top
262 for (plint iX = domain.x0; iX <= domain.x1; ++iX) {
263 globalX = absoluteOffset.x + iX;
264 for (plint iY = domain.y0; iY <= domain.y1; ++iY) {
265 globalY = absoluteOffset.y + iY;
266 populations = populationsVectorToArray((*this->topPopulations)[globalX][globalY]);
267 lattice.get(iX, iY, domain.z1).setPopulations(populations);
268 }
269 }
270 }
271 if (globalZ0 == 0) { // Bottom
272 for (plint iX = domain.x0; iX <= domain.x1; ++iX) {
273 globalX = absoluteOffset.x + iX;
274 for (plint iY = domain.y0; iY <= domain.y1; ++iY) {
275 globalY = absoluteOffset.y + iY;
276 populations = populationsVectorToArray((*this->bottomPopulations)[globalX][globalY]);
277 lattice.get(iX, iY, domain.z0).setPopulations(populations);
278 }
279 }
280 }
281 }
282
283 // Clone class to individual lattice blocks
288
289 // Return the type of data that is modified
290 virtual void getTypeOfModification(std::vector<plb::modif::ModifT> &modified) const
291 {
292 modified[0] = modif::staticVariables;
293 }
294
295 // Only need the bulk of the domain
296 virtual plb::BlockDomain::DomainT appliesTo() const
297 {
298 return BlockDomain::bulk;
299 }
300};
301
302
303/* Lees-Edwards boundary conditions base class responsible for the setup and initialization of the data processors
304 */
305template<typename T, template<class U> class Descriptor>
307{
308public:
309 plb::MultiBlockLattice3D<T,Descriptor> &lattice;
310 plint nx; // Dimension in x direction
311 plint ny; // Dimension in y direction
312 plint nz; // Dimension in z direction
313 // int direction; // TODO direction of the LE boundary x = 0, y = 1, z = 2
314 double LEdisplacement; // Displacement per timestep
315 static double LEcurrentDisplacement; // Current total displacement
316 T dt; // Timestep size
317 T topVelocity; // Macroscopic velocity top boundary layer
318 T bottomVelocity; // Macroscopic velocity bottom boundary layer
319 plint dataProcessorLevel; // level of operation of the Lees-Edwards data processors
320
321 static std::vector<std::vector<std::vector<T>>> topPopulations; // Data structure containing the top populations
322 static std::vector<std::vector<std::vector<T>>> bottomPopulations; // Data structure containing the bottom populations
323
324 LeesEdwardsBC(plb::MultiBlockLattice3D<T, Descriptor> &lattice, T shearRate, T dt, double ** hemoCellLEcurrentDisplacement, plint dataProcessorLevel = 1) : lattice(lattice) {
325 this->lattice = lattice;
326 this->nx = lattice.getNx();
327 this->ny = lattice.getNy();
328 this->nz = lattice.getNz();
329 this->dt = dt;
330 this->LEdisplacement = shearRate * dt;
331 T vHalf = (nz - 1) * shearRate * 0.5;
332 this->topVelocity = -vHalf;
333 this->bottomVelocity = vHalf;
334 this->dataProcessorLevel = dataProcessorLevel;
335 *hemoCellLEcurrentDisplacement = &LEcurrentDisplacement; // Let the hemocell LE displacement point to this memory address
336 }
337
339 {
340 // Uses the default periodicity because otherwise a form of bounceback boundary will be initialized per default
341 this->lattice.periodicity().toggleAll(true);
342
343 this->topPopulations.resize(this->nx, std::vector<std::vector<T>>(this->ny, std::vector<T>(Descriptor<T>::q)));
344 this->bottomPopulations.resize(this->nx, std::vector<std::vector<T>>(this->ny, std::vector<T>(Descriptor<T>::q)));
345
346 // set data processors
347 integrateProcessingFunctional(
348 new LeesEdwardsBCGetPopulations<T, DESCRIPTOR>(this->nx, this->nz, this->topVelocity, this->bottomVelocity, &LEcurrentDisplacement, &topPopulations, &bottomPopulations),
349 this->lattice.getBoundingBox(), this->lattice, this->dataProcessorLevel);
350
351 integrateProcessingFunctional(
353 this->lattice.getBoundingBox(), this->lattice, this->dataProcessorLevel + 1);
354 }
355
356 /* Update the current Lees-Edwards displacement
357
358 * @param iter current hemocell iteration counter
359 */
360 void updateLECurDisplacement(unsigned int iter)
361 {
362 LEcurrentDisplacement = std::fmod(this->LEdisplacement * iter, (double)this->nx);
363 }
364};
365
366#ifndef LEBC_STATICS
367#define LEBC_STATICS
368// Initialize static variables
369// Lees-Edwards displacement
370template <typename T, template <typename U> class Descriptor>
372// Top populations data storage for separate writing and reading across different data processors
373template <typename T, template <typename U> class Descriptor>
374std::vector<std::vector<std::vector<T>>> LeesEdwardsBC<T, Descriptor>::topPopulations;
375// Bottom populations data storage for separate writing and reading across different data processors
376template <typename T, template <typename U> class Descriptor>
377std::vector<std::vector<std::vector<T>>> LeesEdwardsBC<T, Descriptor>::bottomPopulations;
378#else
379#endif
380
381}; // namespace hemo
382
383#endif
Definition leesEdwardsBC.h:58
T topVelocity
Definition leesEdwardsBC.h:65
LeesEdwardsBCGetPopulations(plint nx, plint nz, T topVelocity, T bottomVelocity, double *LEcurrentDisplacement, std::vector< std::vector< std::vector< T > > > *topPopulations, std::vector< std::vector< std::vector< T > > > *bottomPopulations)
Definition leesEdwardsBC.h:68
plint nz
Definition leesEdwardsBC.h:61
double * LEcurrentDisplacement
Definition leesEdwardsBC.h:62
plint nx
Definition leesEdwardsBC.h:60
std::vector< std::vector< std::vector< T > > > * topPopulations
Definition leesEdwardsBC.h:63
plint modNonNegative(plint a, plint b)
Definition leesEdwardsBC.h:96
std::vector< std::vector< std::vector< T > > > * bottomPopulations
Definition leesEdwardsBC.h:64
virtual void getTypeOfModification(std::vector< plb::modif::ModifT > &modified) const
Definition leesEdwardsBC.h:199
virtual plb::BlockDomain::DomainT appliesTo() const
Definition leesEdwardsBC.h:205
virtual LeesEdwardsBCGetPopulations< T, Descriptor > * clone() const
Definition leesEdwardsBC.h:193
virtual void process(plb::Box3D domain, plb::BlockLattice3D< T, Descriptor > &lattice)
Definition leesEdwardsBC.h:108
std::vector< T > populationsArrayToVector(plb::Array< T, Descriptor< T >::q > populations)
Definition leesEdwardsBC.h:86
T bottomVelocity
Definition leesEdwardsBC.h:66
Definition leesEdwardsBC.h:217
plint nz
Definition leesEdwardsBC.h:219
LeesEdwardsBCSetPopulations(plint nz, std::vector< std::vector< std::vector< T > > > *topPopulations, std::vector< std::vector< std::vector< T > > > *bottomPopulations)
Definition leesEdwardsBC.h:223
std::vector< std::vector< std::vector< T > > > * topPopulations
Definition leesEdwardsBC.h:220
plb::Array< T, Descriptor< T >::q > populationsVectorToArray(std::vector< T > populations)
Definition leesEdwardsBC.h:236
virtual LeesEdwardsBCSetPopulations< T, Descriptor > * clone() const
Definition leesEdwardsBC.h:284
virtual plb::BlockDomain::DomainT appliesTo() const
Definition leesEdwardsBC.h:296
std::vector< std::vector< std::vector< T > > > * bottomPopulations
Definition leesEdwardsBC.h:221
virtual void getTypeOfModification(std::vector< plb::modif::ModifT > &modified) const
Definition leesEdwardsBC.h:290
virtual void process(plb::Box3D domain, plb::BlockLattice3D< T, Descriptor > &lattice)
Definition leesEdwardsBC.h:252
Definition leesEdwardsBC.h:307
T dt
Definition leesEdwardsBC.h:316
double LEdisplacement
Definition leesEdwardsBC.h:314
T topVelocity
Definition leesEdwardsBC.h:317
plb::MultiBlockLattice3D< T, Descriptor > & lattice
Definition leesEdwardsBC.h:309
plint ny
Definition leesEdwardsBC.h:311
void updateLECurDisplacement(unsigned int iter)
Definition leesEdwardsBC.h:360
T bottomVelocity
Definition leesEdwardsBC.h:318
plint nx
Definition leesEdwardsBC.h:310
static std::vector< std::vector< std::vector< T > > > bottomPopulations
Definition leesEdwardsBC.h:322
static std::vector< std::vector< std::vector< T > > > topPopulations
Definition leesEdwardsBC.h:321
LeesEdwardsBC(plb::MultiBlockLattice3D< T, Descriptor > &lattice, T shearRate, T dt, double **hemoCellLEcurrentDisplacement, plint dataProcessorLevel=1)
Definition leesEdwardsBC.h:324
static double LEcurrentDisplacement
Definition leesEdwardsBC.h:315
plint nz
Definition leesEdwardsBC.h:312
void initialize()
Definition leesEdwardsBC.h:338
plint dataProcessorLevel
Definition leesEdwardsBC.h:319
double T
Definition constant_defaults.h:118
long int plint
Definition constant_defaults.h:127
Definition config.cpp:34