MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
lslbsurface.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The m-AIA AUTHORS
2//
3// This file is part of m-AIA (https://git.rwth-aachen.de/aia/m-AIA/m-AIA)
4//
5// SPDX-License-Identifier: LGPL-3.0-only
6
7//#define COUPLING_DEBUG_
8#include "lslbsurface.h"
10#include "IO/parallelio.h"
12#include "MEMORY/alloc.h"
13#include "UTIL/functions.h"
14#include "globals.h"
15#include "globalvariables.h"
16
17#include <algorithm>
18#include <stack>
19#include <vector>
20
21using namespace std;
22
23template <MInt nDim, MInt nDist, class SysEqn>
25 : Coupling(couplingId), CouplingLS<nDim>(couplingId, ls), CouplingLB<nDim, nDist, SysEqn>(couplingId, lb) {
26 TRACE();
27
28 // Init timers as the first action
29 initTimers();
30
32
33 initData();
34
36
38
39 RECORD_TIMER_STOP(m_timers[Timers::Constructor]);
40}
41
42template <MInt nDim, MInt nDist, class SysEqn>
44 TRACE();
45
46 RECORD_TIMER_STOP(m_timers[Timers::Class]);
47}
48
49template <MInt nDim, MInt nDist, class SysEqn>
51 TRACE();
52
53 // Create timer group and coupler timer, and start the timer
54 NEW_TIMER_GROUP_NOCREATE(m_timers[Timers::TimerGroup], "Coupler LS LB Surface");
55 NEW_TIMER_NOCREATE(m_timers[Timers::Class], "Total object lifetime", m_timers[Timers::TimerGroup]);
56 RECORD_TIMER_START(m_timers[Timers::Class]);
57
58 // Create and start constructor timer
59 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Constructor], "Constructor", m_timers[Timers::Class]);
60 RECORD_TIMER_START(m_timers[Timers::Constructor]);
61
62 // Create PreCouple timers
63 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::PreCouple], "PreCouple", m_timers[Timers::Class]);
64 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::TransferToLevelSet], "TransferToLevelSet", m_timers[Timers::PreCouple]);
65 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::SetExtensionVelocity], "SetExtensionVelocity",
66 m_timers[Timers::TransferToLevelSet]);
67 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::ExtendVelocity], "ExtendVelocity", m_timers[Timers::TransferToLevelSet]);
68
69 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::FindBoundaryCells], "FindBoundaryCells", m_timers[Timers::PreCouple]);
70 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::InitOutsideDomain], "InitOutsideDomain", m_timers[Timers::PreCouple]);
71 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::SetBoundaryCondition], "SetBoundaryCondition", m_timers[Timers::PreCouple]);
72
73 // Create PostCouple timers
74 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::PostCouple], "PostCouple", m_timers[Timers::Class]);
75 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::ComputeBoundaryValues], "ComputeBoundaryValues",
76 m_timers[Timers::PostCouple]);
77 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::CreateComm], "CreateComm", m_timers[Timers::PostCouple]);
78 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::ApplyBoundaryCondition], "ApplyBoundaryCondition",
79 m_timers[Timers::PostCouple]);
80}
81
82
86template <MInt nDim, MInt nDist, class SysEqn>
88 TRACE();
89
90 // solver-specific data:
91 m_lbSolverId = lbSolver().solverId();
92 m_lsSolverId = lsSolver().solverId();
93
94 const MFloat dx = a_cellLengthAtLevel(lbSolver().maxLevel());
95
96 conversionLbLs.velocity = sqrt(3) / a_Ma();
97 conversionLsLb.velocity = 1 / conversionLbLs.velocity;
98
99 conversionLbLs.length = dx;
100 conversionLsLb.length = 1 / conversionLbLs.length;
101
102 conversionLbLs.time = conversionLbLs.length / conversionLbLs.velocity;
103 conversionLsLb.time = 1 / conversionLbLs.time;
104
105 conversionLbLs.pressure = POW2(conversionLbLs.velocity);
106 conversionLsLb.pressure = 1 / conversionLbLs.pressure;
107
108 if(!lbSolver().domainId()) {
109 std::cout << "CONVERSION" << std::endl
110 << "VEL LB LS " << conversionLbLs.velocity << std::endl
111 << "VEL LS LB " << conversionLsLb.velocity << std::endl
112 << "LEN LB LS " << conversionLbLs.length << std::endl
113 << "LEN LS LB " << conversionLsLb.length << std::endl
114 << "TIME LB LS " << conversionLbLs.time << std::endl
115 << "TIME LS LB " << conversionLsLb.time << std::endl
116 << "PRESSURE LB LS " << conversionLbLs.pressure << std::endl
117 << "PRESSURE LS LB " << conversionLsLb.pressure << std::endl;
118 }
119
120 lsSolver().m_timeStep = conversionLbLs.time;
121
122 const MFloat nu = a_Ma() * LBCS / a_Re() * lbSolver().m_referenceLength;
123
124 m_gravity = POW2(m_Ga) * POW2(nu) / POW3(lbSolver().m_referenceLength);
125
126 m_surfaceTension = 1.0 * m_gravity * POW2(lbSolver().m_referenceLength) / m_Eo;
127
128 // Some quality of life output
129
130 const MFloat tau = (1 + 6 * nu) / 2.0;
131
132 stringstream ss;
133 const MInt maxLineLength = 256;
134 MChar b[maxLineLength];
135 const MString divider = "-------------------------------------------------------------------------";
136
137 ss << "\n";
138 ss << "FREE SURFACE PROBLEM SUMARRY"
139 << "\n";
140 ss << divider << "\n";
141
142 snprintf(b, maxLineLength, " | %-45s | %-20E | \n", "Mach", a_Ma());
143 ss << b;
144 snprintf(b, maxLineLength, " | %-45s | %-20E | \n", "Reynolds", a_Re());
145 ss << b;
146 snprintf(b, maxLineLength, " | %-45s | %-20E | \n", "Galileo", m_Ga);
147 ss << b;
148 snprintf(b, maxLineLength, " | %-45s | %-20E | \n", "Eotvos", m_Eo);
149 ss << b;
150
151 ss << "\n";
152 snprintf(b, maxLineLength, " | %-45s | %-20E | \n", "viscosity nu", nu);
153 ss << b;
154 snprintf(b, maxLineLength, " | %-45s | %-20E | \n", "relaxation tau", tau);
155 ss << b;
156 snprintf(b, maxLineLength, " | %-45s | %-20E | \n", "gravity g", m_gravity);
157 ss << b;
158 snprintf(b, maxLineLength, " | %-45s | %-20E | \n", "surface tension sigma", m_surfaceTension);
159 ss << b;
160
161 if(!lbSolver().domainId()) {
162 cout << ss.str() << std::endl;
163 }
164}
165
169template <MInt nDim, MInt nDist, class SysEqn>
171 TRACE();
172
173 lbSolver().m_noLevelSetsUsedForMb = 1;
174 if(lsSolver().m_maxNoSets > 1) {
175 lbSolver().m_noLevelSetsUsedForMb = lsSolver().m_maxNoSets;
176 }
177
178 lbSolver().m_maxNoSets = lsSolver().m_maxNoSets;
179 lbSolver().m_constructGField = lsSolver().m_constructGField;
180
181 // Check that the lb-solver-cell-count is correct!
182 ASSERT(lbSolver().a_noCells(), "");
183}
184
188template <MInt nDim, MInt nDist, class SysEqn>
190 TRACE();
191
192 m_Ga = 0.0;
193 m_Ga = Context::getBasicProperty<MFloat>("Ga", AT_, &m_Ga);
194
195
196 m_Eo = 0.0;
197 m_Eo = Context::getBasicProperty<MFloat>("Eo", AT_, &m_Eo);
198
199 m_initCurvature = 0.0;
200 m_initCurvature = Context::getBasicProperty<MFloat>("initCurvature", AT_, &m_initCurvature);
201
202 m_initHeight = 0.0;
203 m_initHeight = Context::getBasicProperty<MFloat>("initHeight", AT_, &m_initHeight);
204 m_initHeight /= lbSolver().c_cellLengthAtLevel(lbSolver().maxLevel());
205}
206
207template <MInt nDim, MInt nDist, class SysEqn>
209 TRACE();
210
211 lbSolver().initializeMovingBoundaries();
212 lbBndCnd().initializeBndMovingBoundaries();
213}
214
215
216template <MInt nDim, MInt nDist, class SysEqn>
218 TRACE();
219 RECORD_TIMER_START(m_timers[Timers::PreCouple]);
220
221 // Pre LS
222 if(recipeStep == 0) {
223 if(!lbSolver().domainId()) {
224 std::cout << "Pre LS couple ..." << std::endl;
225 }
226
227 RECORD_TIMER_START(m_timers[Timers::TransferToLevelSet]);
228 // TODO labels:COUPLER Decide based on number of bnd cells
229 // FIXME labels:COUPLER julian
230 if(lbSolver().getCurrentTimeStep() > 1) {
231 // Reset, set and extend transport velocity for the LS
232 // FIXME labels:COUPLER julian
233 // lsSolver().resetExtensionVelocity();
234
235 RECORD_TIMER_START(m_timers[Timers::SetExtensionVelocity]);
236 setExtensionVelocity();
237 RECORD_TIMER_STOP(m_timers[Timers::SetExtensionVelocity]);
238
239 RECORD_TIMER_START(m_timers[Timers::ExtendVelocity]);
240 // FIXME labels:COUPLER julian
241 // lsSolver().extendVelocity(0);
242 RECORD_TIMER_STOP(m_timers[Timers::ExtendVelocity]);
243 }
244 RECORD_TIMER_STOP(m_timers[Timers::TransferToLevelSet]);
245 }
246
247 // Pre LB
248 else {
249 if(!lbSolver().domainId()) {
250 std::cout << "Pre LB couple ..." << std::endl;
251 }
252
253 std::vector<MInt> maxGCellLevels(lsSolver().m_maxNoSets);
254 for(MInt set = 0; set < lsSolver().m_maxNoSets; set++) {
255 maxGCellLevels[set] = lsSolver().a_maxGCellLevel(set);
256 }
257 RECORD_TIMER_START(m_timers[Timers::FindBoundaryCells]);
258 lbSolver().preCoupleLs(maxGCellLevels);
259 RECORD_TIMER_STOP(m_timers[Timers::FindBoundaryCells]);
260
261 RECORD_TIMER_START(m_timers[Timers::InitOutsideDomain]);
262 refillEmergedCells();
263 RECORD_TIMER_STOP(m_timers[Timers::InitOutsideDomain]);
264
265 // FIXME labels:COUPLER Curvature semms wrong for the first time step
266 for(MInt mbCell = 0; mbCell < a_mbCell().size(); mbCell++) {
267 a_mbCell().density(mbCell) = 1.0;
268 }
269 if(lbSolver().getCurrentTimeStep() == 1) {
270 return;
271 }
272
273 RECORD_TIMER_START(m_timers[Timers::SetBoundaryCondition]);
274 MFloatScratchSpace curvatureInterp(a_mbCell().size(), AT_, "curvature");
275
276 interpolateCurvature(curvatureInterp);
277 interpolateNormal();
278
279 if(a_mbCell().size() > 0) {
280 std::cout << "curv " << curvatureInterp[0] << std::endl;
281 }
282
283 // Compute and transfer pressure from curvature (Laplace)
284 MFloat l_curvature_sum = 0;
285 MFloat l_rho_sum = 0;
286 MFloat l_rho_hyd = 0;
287 MFloat l_drho_curv = 0;
288
289 for(MInt mbCell = 0; mbCell < a_mbCell().size(); mbCell++) {
290 l_curvature_sum += curvatureInterp[mbCell];
291 }
292
293 const MInt l_count = a_mbCell().size();
294 MInt g_count = 0;
295 MPI_Allreduce(&l_count, &g_count, 1, MPI_INT, MPI_SUM, lbSolver().mpiComm(), AT_, "count", "count");
296
297 MFloat g_curvature_sum = 0;
298 MPI_Allreduce(&l_curvature_sum, &g_curvature_sum, 1, MPI_DOUBLE, MPI_SUM, lbSolver().mpiComm(), AT_, "curv",
299 "curv");
300
301 const MFloat dpCorr = 0.1 * (POW3(g_curvature_sum / g_count / m_initCurvature) - 1.0);
302
303 for(MInt mbCell = 0; mbCell < a_mbCell().size(); mbCell++) {
304 const MFloat curvature = curvatureInterp[mbCell];
305
306 const MFloat dx = a_cellLengthAtLevel(lbSolver().maxLevel());
307
308 MFloat dpLB = -m_initHeight * m_gravity + dpCorr;
309
310 l_rho_hyd += 1 + 3.0 * dpLB;
311
312 // TODO labels:COUPLER Check Factor convention 2D/3D ...
313 IF_CONSTEXPR(nDim == 2) { dpLB += 2 * (curvature - m_initCurvature) * dx * m_surfaceTension; }
314 else {
315 dpLB += 1 * (curvature - m_initCurvature) * dx * m_surfaceTension;
316 l_drho_curv += 3 * (curvature - m_initCurvature) * dx * m_surfaceTension;
317 }
318
319 const MFloat rhoLB = 1 + 3.0 * dpLB;
320
321 a_mbCell().density(mbCell) = rhoLB;
322
323 l_rho_sum += rhoLB;
324 }
325
326 MFloat g_rho_sum = 0;
327 MPI_Allreduce(&l_rho_sum, &g_rho_sum, 1, MPI_DOUBLE, MPI_SUM, lbSolver().mpiComm(), AT_, "curv", "curv");
328
329 MFloat g_rho_hyd = 0;
330 MPI_Allreduce(&l_rho_hyd, &g_rho_hyd, 1, MPI_DOUBLE, MPI_SUM, lbSolver().mpiComm(), AT_, "curv", "curv");
331
332 MFloat g_drho_curv = 0;
333 MPI_Allreduce(&l_drho_curv, &g_drho_curv, 1, MPI_DOUBLE, MPI_SUM, lbSolver().mpiComm(), AT_, "curv", "curv");
334
335 if(!lbSolver().domainId()) {
336 std::cout << " AVG curv " << g_curvature_sum / g_count << " AVG rho " << g_rho_sum / g_count << " AVG hyd rho "
337 << g_rho_hyd / g_count << " AVG curv drho " << g_drho_curv / g_count << std::endl;
338 }
339
340 RECORD_TIMER_STOP(m_timers[Timers::SetBoundaryCondition]);
341 }
342 RECORD_TIMER_STOP(m_timers[Timers::PreCouple]);
343}
344
345template <MInt nDim, MInt nDist, class SysEqn>
347 TRACE();
348 RECORD_TIMER_START(m_timers[Timers::PostCouple]);
349
350 // Post LS
351 if(recipeStep == 0) {
352 if(!lbSolver().domainId()) {
353 std::cout << "Post LS couple ..." << std::endl;
354 }
355
356 // TODO labels:COUPLER,LS,LB Transfer LS FROM LS to LB in a more generalized manner
357 // TODO labels:COUPLER Only band cells ?
358 const MInt setId = 0;
359 for(MInt cellId = 0; cellId < a_noLsCells(); cellId++) {
360 // TODO labels:COUPLER Use id conversion
361 a_levelSetFunctionMb(cellId, setId) = a_levelSetFunctionG(cellId, setId);
362 }
363
364 evaluateContour();
365 }
366
367 // Post LB
368 else if(recipeStep == 1) {
369 if(!lbSolver().domainId()) {
370 std::cout << "Post LB couple ..." << std::endl;
371 }
372
373 RECORD_TIMER_START(m_timers[Timers::ComputeBoundaryValues]);
374 lbBndCnd().extrapolateVelocitiesMb();
375
376 // Exchange velocity between boundary cells
377 auto setVel = static_cast<MFloat& (CouplingLb::MbCellCollector::*)(const MInt, const MInt)>(
378 &CouplingLb::MbCellCollector::velocity);
379 auto getVel = static_cast<MFloat (CouplingLb::MbCellCollector::*)(const MInt, const MInt) const>(
380 &CouplingLb::MbCellCollector::velocity);
381 auto setData = std::bind(setVel, &a_mbCell(), std::placeholders::_1, std::placeholders::_2);
382 auto getData = std::bind(getVel, &a_mbCell(), std::placeholders::_1, std::placeholders::_2);
383
384 auto cellMapping = std::bind(&CouplingLb::a_boundaryCellMb, this, std::placeholders::_1, std::placeholders::_2);
385
386 lbSolver().exchangeSparseLeafValues(getData, setData, nDim, cellMapping);
387
388 // Check all vels in mbcellcollector for nan
389 for(MInt mbCell = 0; mbCell < a_mbCell().size(); mbCell++) {
390 const MFloat u = a_mbCell().velocity(mbCell, 0);
391
392 if(std::isnan(u)) {
393 mTerm(1, "Should not happen");
394 }
395 }
396 RECORD_TIMER_STOP(m_timers[Timers::ComputeBoundaryValues]);
397
398 RECORD_TIMER_START(m_timers[Timers::CreateComm]);
399 lbBndCnd().createMBComm();
400 RECORD_TIMER_STOP(m_timers[Timers::CreateComm]);
401
402 RECORD_TIMER_START(m_timers[Timers::ApplyBoundaryCondition]);
403 lbBndCnd().postCouple();
404 RECORD_TIMER_STOP(m_timers[Timers::ApplyBoundaryCondition]);
405 }
406
407 RECORD_TIMER_STOP(m_timers[Timers::PostCouple]);
408}
409
410template <MInt nDim, MInt nDist, class SysEqn>
412 // Revert the algorithm:
413 // Try to find a reasonable velocity value for every G0 cell...
414 for(MInt id = 0; id < a_noG0Cells(0); id++) {
415 const MInt cellId = a_G0CellId(id, 0);
416
417 if(lsSolver().a_isHalo(cellId)) {
418 continue;
419 }
420
421 const MInt mbCell = a_boundaryCellMb(cellId);
422
423 if(mbCell > -1) {
424 // Boundary cell found
425
426 for(MInt n = 0; n < nDim; n++) {
427 a_extensionVelocityG(cellId, n, 0) = a_mbCell().velocity(mbCell, n) * conversionLbLs.velocity;
428 }
429
430 if(std::isnan(a_extensionVelocityG(cellId, 0, 0))) {
431 std::cout << "Velocity nan in boundary cell..." << std::endl;
432 }
433
434 } else {
435 // No boundary cell found
436
437 // Find the nearest boundary cell by maximizing e * n
438 MFloat minBndDist = std::numeric_limits<MFloat>::min();
439 MInt minDistDir = -1;
440 for(MInt dist = 0; dist < a_noDistributions() - 1; dist++) {
441 MFloat bndDist = 0;
442 for(MInt n = 0; n < nDim; n++) {
443 bndDist += a_normalVectorG(cellId, n, 0) * LbLatticeDescriptor<nDim, nDist>::ppdfDir(dist, n);
444 }
445 IF_CONSTEXPR(nDim == 2) {
446 if(dist >= 4) {
447 bndDist /= SQRT2;
448 }
449 }
450 else {
451 if(dist >= 6 && dist < 18) {
452 bndDist /= SQRT2;
453 } else if(dist >= 18) {
454 bndDist /= SQRT3;
455 }
456 }
457 bndDist *= a_levelSetFunctionG(cellId, 0);
458
459 if(minBndDist < bndDist) {
460 minBndDist = bndDist;
461 minDistDir = dist;
462 }
463 }
464 const MInt neighbor = lbSolver().c_neighborId(cellId, minDistDir);
465
466 const MInt nextMbCell = a_boundaryCellMb(neighbor);
467
468 if(nextMbCell > -1) {
469 // Found the next possible boundary cell
470 for(MInt n = 0; n < nDim; n++) {
471 a_extensionVelocityG(cellId, n, 0) = a_mbCell().velocity(nextMbCell, n) * conversionLbLs.velocity;
472 }
473
474 if(std::isnan(a_extensionVelocityG(cellId, 0, 0))) {
475 std::cout << "Velocity nan in boundary cell..." << std::endl;
476 }
477
478 } else {
479 for(MInt n = 0; n < nDim; n++) {
480 a_extensionVelocityG(cellId, n, 0) = 0.0;
481 }
482 std::cout << "G0 cell " << lbSolver().c_globalId(cellId) << " neighbor " << lbSolver().c_globalId(neighbor)
483 << std::endl;
484
485 for(MInt dist = 0; dist < a_noDistributions() - 1; dist++) {
486 MFloat bndDist = 0;
487 for(MInt n = 0; n < nDim; n++) {
488 bndDist += a_normalVectorG(cellId, n, 0) * LbLatticeDescriptor<nDim, nDist>::ppdfDir(dist, n);
489 }
490 IF_CONSTEXPR(nDim == 2) {
491 if(dist >= 4) {
492 bndDist /= SQRT2;
493 }
494 }
495 else {
496 if(dist >= 6 && dist < 18) {
497 bndDist /= SQRT2;
498 } else if(dist >= 18) {
499 bndDist /= SQRT3;
500 }
501 }
502 bndDist *= a_levelSetFunctionG(cellId, 0);
503 std::cout << "Dist " << dist << " bndDist " << bndDist << " normal_y " << a_normalVectorG(cellId, 1, 0)
504 << " ppdfdir " << LbLatticeDescriptor<nDim, nDist>::ppdfDir(dist, 1) << std::endl;
505 }
506
507 mTerm(1, "Cant find corresponding LB bnd cell for given G0 cell. Should not happen.");
508 }
509 }
510 }
511}
512
513template <MInt nDim, MInt nDist, class SysEqn>
515 // Collector is created after this, such that these velocities are from the time step n-1
516 for(MInt mbCell = 0; mbCell < a_mbCell().size(); mbCell++) {
517 const MInt cellId = a_mbCell().cellId(mbCell);
518
519 const MFloat uLB = a_mbCell().velocity(mbCell, 0);
520 const MFloat vLB = a_mbCell().velocity(mbCell, 1);
521
522 const MFloat uLS = uLB * conversionLbLs.velocity;
523 const MFloat vLS = vLB * conversionLbLs.velocity;
524
525 if(!std::isnan(uLS) && !std::isnan(vLS)) {
526 a_extensionVelocityG(cellId, 0, 0) = uLS;
527 a_extensionVelocityG(cellId, 1, 0) = vLS;
528
529
530 MInt minDistDir = -1;
531 MFloat minWallDistance = F2;
532 for(MInt dist = 0; dist < a_noDistributions() - 1; dist++) {
533 if(minWallDistance > a_mbCell().distance(mbCell, dist)) {
534 minWallDistance = a_mbCell().distance(mbCell, dist);
535 minDistDir = dist;
536 }
537 }
538
539 ASSERT(minDistDir > -1, "minDistDir not found!");
540
541 const MInt neighbor = lbSolver().c_neighborId(cellId, minDistDir);
542
543 if(neighbor == -1 || lsSolver().a_isHalo(neighbor)) {
544 continue;
545 }
546
547 // a_extensionVelocityG(cellId, 0, 0) = 0.0;
548 // a_extensionVelocityG(cellId, 1, 0) = v;
549 a_extensionVelocityG(neighbor, 0, 0) = uLS;
550 a_extensionVelocityG(neighbor, 1, 0) = vLS;
551 }
552
553 if(!lsSolver().a_isHalo(cellId)) {
554 // Set value to LS cell correspondig to the LB interface cell
555 if(std::isnan(uLS) || std::isnan(vLS)) {
556 std::cout << "attempt to set nan at cell " << cellId << " which is an halo " << lsSolver().a_isHalo(cellId)
557 << " which is in " << (a_levelSetFunctionMb(cellId, 0) > 0) << std::endl;
558 mTerm(1, "nan set");
559 }
560
561 a_extensionVelocityG(cellId, 0, 0) = uLS;
562 a_extensionVelocityG(cellId, 1, 0) = vLS;
563 }
564
565 // The LS solver has two layers of interface cells
566
567 // Find direction to the missing cell
568 MInt minDistDir = -1;
569 MFloat minWallDistance = F2;
570 for(MInt dist = 0; dist < a_noDistributions() - 1; dist++) {
571 if(minWallDistance > a_mbCell().distance(mbCell, dist)) {
572 minWallDistance = a_mbCell().distance(mbCell, dist);
573 minDistDir = dist;
574 }
575 }
576
577
578 ASSERT(minDistDir > -1, "minDistDir not found!");
579
580 const MInt neighbor = lbSolver().c_neighborId(cellId, minDistDir);
581
582 const MInt opposite = LbLatticeDescriptor<nDim, nDist>::oppositeDist(minDistDir);
583 const MInt oppositeNeighbor = lbSolver().c_neighborId(cellId, opposite);
584
585 if(neighbor == -1 || lsSolver().a_isHalo(neighbor) || lsSolver().a_isHalo(oppositeNeighbor)) {
586 continue;
587 }
588
589 if(std::isnan(uLS) || std::isnan(vLS)) {
590 std::cout << "attempt to set nan at neighbor " << neighbor << std::endl;
591 std::cout << "cell itself is halo " << lsSolver().a_isHalo(cellId) << std::endl;
592 std::cout << "extrap neighbor is halo " << lsSolver().a_isHalo(oppositeNeighbor) << std::endl;
593 mTerm(1, "nan set");
594 }
595
596 a_extensionVelocityG(neighbor, 0, 0) = uLS;
597 a_extensionVelocityG(neighbor, 1, 0) = vLS;
598 }
599}
600
601
602// FIXME labels:COUPLER Only valid for congruent grids
603template <MInt nDim, MInt nDist, class SysEqn>
605 for(MInt mbCell = 0; mbCell < a_mbCell().size(); mbCell++) {
606 const MInt pCellId = a_mbCell().cellId(mbCell);
607
608 // Find minWallDistDir
609 MInt minDistDir = -1;
610 MFloat minWallDistance = F2;
611 for(MInt dist = 0; dist < a_noDistributions() - 1; dist++) {
612 if(minWallDistance > a_mbCell().distance(mbCell, dist)) {
613 minWallDistance = a_mbCell().distance(mbCell, dist);
614 minDistDir = dist;
615 }
616 }
617
618 ASSERT(minDistDir > -1, "minDistDir not found!");
619
620 const MFloat q = lbBndCnd().getDistanceMb(pCellId, mbCell, minDistDir);
621
622 const MInt neighbor = lbSolver().c_neighborId(pCellId, minDistDir);
623
624 if(neighbor == -1) {
625 continue;
626 }
627
628 // const MFloat lin = a_curvatureG(pCellId, 0) * (1-q) + a_curvatureG(neighbor, 0) * q;
629
630 /*const MFloat rad1 = maia::math::sgn(a_curvatureG(pCellId, 0))
631 * sqrt(1/abs(a_curvatureG(pCellId, 0)));
632 const MFloat rad2 = maia::math::sgn(a_curvatureG(neighbor,0))
633 * sqrt(1/abs(a_curvatureG(neighbor,0)));*/
634
635 const MFloat rad1 = 1 / a_curvatureG(pCellId, 0);
636 const MFloat rad2 = 1 / a_curvatureG(neighbor, 0);
637
638 const MFloat rad = rad1 * (1 - q) + rad2 * q;
639
640 // const MFloat lin = maia::math::sgn(rad)*1/POW2(rad);
641 const MFloat lin = 1 / rad;
642
643 curvature[mbCell] = lin;
644 }
645}
646
647template <MInt nDim, MInt nDist, class SysEqn>
649 for(MInt mbCell = 0; mbCell < a_mbCell().size(); mbCell++) {
650 const MInt pCellId = a_mbCell().cellId(mbCell);
651
652 // Find minWallDistDir
653 MInt minDistDir = -1;
654 MFloat minWallDistance = F2;
655 for(MInt dist = 0; dist < a_noDistributions() - 1; dist++) {
656 if(minWallDistance > a_mbCell().distance(mbCell, dist)) {
657 minWallDistance = a_mbCell().distance(mbCell, dist);
658 minDistDir = dist;
659 }
660 }
661
662 ASSERT(minDistDir > -1, "minDistDir not found!");
663
664 const MFloat q = lbBndCnd().getDistanceMb(pCellId, mbCell, minDistDir);
665
666 ASSERT(minDistDir > -1, "No min dist found.");
667
668 const MInt neighbor = lbSolver().c_neighborId(pCellId, minDistDir);
669
670 if(neighbor == -1) {
671 continue;
672 }
673
674 for(MInt n = 0; n < nDim; n++) {
675 const MFloat lin =
676 lsSolver().a_normalVectorG(pCellId, n, 0) * (1 - q) + lsSolver().a_normalVectorG(neighbor, n, 0) * q;
677
678 a_mbCell().normal(mbCell, n) = lin;
679 }
680 }
681}
682
683
687template <MInt nDim, MInt nDist, class SysEqn>
689 TRACE();
690
691 lbSolver().m_geometryIntersection->m_noEmbeddedBodies = lbSolver().m_noEmbeddedBodies;
692 lbSolver().m_geometryIntersection->m_noLevelSetsUsedForMb = lbSolver().m_noLevelSetsUsedForMb;
693 lbSolver().m_geometryIntersection->m_bodyToSetTable = lsSolver().m_bodyToSetTable;
694 lbSolver().m_geometryIntersection->m_setToBodiesTable = lsSolver().m_setToBodiesTable;
695 lbSolver().m_geometryIntersection->m_noBodiesInSet = lsSolver().m_noBodiesInSet;
696}
697
698// TODO labels:COUPLER Move up
699template <MInt nDim, MInt nDist, class SysEqn>
701 TRACE();
702
703 for(MInt i = 0; i < a_noCells(); i++) {
704 if(lbSolver().a_isHalo(i)) {
705 continue;
706 }
707
708 // Regular fluid cell
709 if(a_isActive(i) && a_wasActive(i)) {
710 continue;
711 }
712
713 // Regular outside cell
714 // TODO labels:COUPLER Access via PV
715 if(!a_isActive(i)) {
716 for(MInt n = 0; n < nDim; n++) {
717 lbSolver().a_variable(i, n) = 0.0;
718 }
719 lbSolver().a_variable(i, nDim) = 1.0;
720 }
721
722 if(a_isActive(i) && !a_wasActive(i)) {
723 lbBndCnd().refillEmergedCell(i);
724 }
725 }
726}
727
728template <MInt nDim, MInt nDist, class SysEqn>
730 MFloat COG[nDim]{0.0};
731 MFloat mass = 0.0;
732
733 for(MInt cellId = 0; cellId < a_noLsCells(); cellId++) {
734 if(lsSolver().a_isHalo(cellId)) {
735 continue;
736 }
737
738 if(a_levelSetFunctionG(cellId, 0) > 0) {
739 continue;
740 }
741
742 const MFloat dm = 1.0;
743
744 for(MInt n = 0; n < nDim; n++) {
745 COG[n] += dm * lsSolver().c_coordinate(cellId, n);
746 }
747 mass += dm;
748 }
749
750 if(lsSolver().noDomains() > 1) {
751 MPI_Allreduce(MPI_IN_PLACE, COG, 2, MPI_DOUBLE, MPI_SUM, lsSolver().mpiComm(), AT_, "COG", "COG");
752 MPI_Allreduce(MPI_IN_PLACE, &mass, 1, MPI_DOUBLE, MPI_SUM, lsSolver().mpiComm(), AT_, "mass", "mass");
753 }
754
755 for(MInt n = 0; n < nDim; n++) {
756 COG[n] /= mass;
757 }
758
759 const MFloat dx = a_cellLengthAtLevel(lbSolver().maxLevel());
760
761 if(!lsSolver().domainId()) {
762 std::cout << "Bubble COG " << COG[0] << " " << COG[1] << " mass " << mass << " hydrostatic pressure rho "
763 << 1.0 - 3.0 * COG[1] / dx * m_gravity << std::endl;
764 }
765
766 if(!lsSolver().domainId()) {
767 FILE* log;
768 log = fopen("bubble.log", "a+");
769 fprintf(log, "%d ", globalTimeStep);
770 fprintf(log, "%f ", COG[1]);
771 fprintf(log, "\n");
772 fclose(log);
773 }
774}
775
776// Explicit instantiations
This class represents all LB models.
Definition: lbsolverdxqy.h:29
void postCouple(MInt recipeStep=0) override
void setExtensionVelocity()
void initTimers()
Definition: lslbsurface.cpp:50
void initData()
Initialize coupling-class-specific Data.
Definition: lslbsurface.cpp:87
void setExtensionVelocityB()
void readProperties()
reads lsfvmb-coupling-specific data
void interpolateCurvature(MFloatScratchSpace &curvature)
std::array< MInt, Timers::_count > m_timers
Definition: lslbsurface.h:133
void interpolateNormal()
void evaluateContour()
LsLbSurface(MInt couplingId, LsSolver *ls, LbSolver *lb)
Definition: lslbsurface.cpp:24
void checkProperties()
Checks property-data which is read in by both ls-and Lb-Solver.
void updateGeometry()
Updates the member-variables in the geometry-intersection class.
void init() override
void refillEmergedCells()
void preCouple(MInt) override
This class is a ScratchSpace.
Definition: scratch.h:758
size_type size() const
Definition: scratch.h:302
Class that represents LB cell collector.
void mTerm(const MInt errorCode, const MString &location, const MString &message)
Definition: functions.cpp:29
constexpr Real POW3(const Real x)
Definition: functions.h:123
constexpr Real POW2(const Real x)
Definition: functions.h:119
MInt globalTimeStep
int32_t MInt
Definition: maiatypes.h:62
std::basic_string< char > MString
Definition: maiatypes.h:55
double MFloat
Definition: maiatypes.h:52
char MChar
Definition: maiatypes.h:56
int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allreduce
MFloat dist(const Point< DIM > &p, const Point< DIM > &q)
Definition: pointbox.h:54
static constexpr MFloat ppdfDir(MInt i, MInt j)
static constexpr MInt oppositeDist(MInt i)