45 cell.template setField<FreeSurface::TEMP_MASS_EXCHANGE>(zero_mass_exchange);
56 bool isHealthyInterfaceCell = isHealthyInterface(cell);
59 if (hasNoGasNeighbours && hasNoFluidNeighbours) {
60 hasNoGasNeighbours =
false;
61 hasNoFluidNeighbours =
false;
62 isHealthyInterfaceCell =
true;
74 T mass_exchange = T(0);
75 for (
int iPop = 1; iPop < DESCRIPTOR::q; ++iPop) {
91 bool nbrIsHealthyInterfaceCell = isHealthyInterface(nbrCell);
94 if (nbrHasNoGasNeighbours && nbrHasNoFluidNeighbours) {
95 nbrHasNoGasNeighbours =
false;
96 nbrHasNoFluidNeighbours =
false;
97 nbrIsHealthyInterfaceCell =
true;
100 T pdf_difference = T(0);
103 if (isHealthyInterfaceCell && nbrIsHealthyInterfaceCell) {
110 if ((isHealthyInterfaceCell && nbrHasNoGasNeighbours) || (hasNoFluidNeighbours && !nbrHasNoFluidNeighbours)) {
111 pdf_difference = -nbrCell[iPop];
117 if ((isHealthyInterfaceCell && nbrHasNoFluidNeighbours) || (hasNoGasNeighbours && !nbrHasNoGasNeighbours)) {
124 if ((hasNoFluidNeighbours && nbrHasNoFluidNeighbours) || (hasNoGasNeighbours && nbrHasNoGasNeighbours)) {
132 const T epsilon_average = T(0.5) * (getClampedEpsilon(cell) + getClampedEpsilon(nbrCell));
133 mass_exchange += pdf_difference * epsilon_average;
137 const auto mass = cell.template getField<FreeSurface::MASS>();
138 cell.template setField<FreeSurface::MASS>(mass + mass_exchange);
150 const bool drop_isolated_cells = params.template get<FreeSurface::DROP_ISOLATED_CELLS>();
151 const auto transition = params.template get<FreeSurface::TRANSITION>();
152 const auto lonely_threshold = params.template get<FreeSurface::LONELY_THRESHOLD>();
153 const bool has_surface_tension = params.template get<FreeSurface::HAS_SURFACE_TENSION>();
154 const auto surface_tension = params.template get<FreeSurface::SURFACE_TENSION_PARAMETER>();
165 const T curvature = computeCurvature(cell);
166 deltaRho = T(6) * surface_tension * curvature;
168 const T bubble_density = T(1);
169 const T gas_density = bubble_density - deltaRho;
176 for (
int iPop = 1; iPop < DESCRIPTOR::q; iPop++) {
184 constexpr bool usePrecise =
true;
191 if constexpr (usePrecise) {
206 T u[DESCRIPTOR::d] = {prev_velocity[0], prev_velocity[1]};
220 for (
int iPop = 1; iPop < DESCRIPTOR::q; iPop++) { cell[iPop] = dfs[iPop]; }
223 const auto rho = cell.computeRho();
224 const auto mass = cell.template getField<FreeSurface::MASS>();
227 if (mass < -transition * rho) {
233 if (mass > (T(1) + transition) * rho) {
282 T rho_average = T(0);
283 T u_average[DESCRIPTOR::d] = {T(0), T(0)};
284 std::uint8_t count = std::uint8_t(0);
286 for (
int iPop = 1; iPop < DESCRIPTOR::q; ++iPop) {
293 T u_tmp[DESCRIPTOR::d] = {T(0), T(0)};
295 nbrCell.computeRhoU(rho_tmp, u_tmp);
296 rho_average += rho_tmp;
297 for (std::size_t i = 0; i < DESCRIPTOR::d; ++i) { u_average[i] += u_tmp[i]; }
301 if (count > std::uint8_t(0)) {
302 rho_average /=
static_cast<T
>(count);
303 for (std::size_t i = 0; i < DESCRIPTOR::d; ++i) { u_average[i] /=
static_cast<T
>(count); }
308 for (std::size_t i = 0; i < DESCRIPTOR::d; ++i) { u_average[i] = T(0); }
311 cell.iniEquilibrium(rho_average, u_average);
362 T mass_excess = T(0);
366 const T mass = cell.template getField<FreeSurface::MASS>();
368 cell.template setField<FreeSurface::MASS>(T(0));
373 const T rho = cell.computeRho();
374 const T mass = cell.template getField<FreeSurface::MASS>();
375 mass_excess = mass - rho;
376 cell.template setField<FreeSurface::MASS>(rho);
384 std::uint8_t oldIntefaceNbrs = std::uint8_t(0);
385 std::uint8_t newIntefaceNbrs = std::uint8_t(0);
386 for (
int iPop = 1; iPop < DESCRIPTOR::q; ++iPop) {
401 const std::uint8_t intefaceNbrs = newIntefaceNbrs + oldIntefaceNbrs;
402 if (intefaceNbrs == std::uint8_t(0)) {
return; }
405 bool enableAllInterfaces =
true;
406 constexpr bool weightedDistribution =
true;
411 if constexpr (weightedDistribution) {
413 auto normal = computeInterfaceNormal(cell);
414 computeMassExcessWeights(cell, normal, enableAllInterfaces, weights);
417 for (
const auto& weight : weights) { weightsSum += weight; }
419 if (
util::fabs(weightsSum) < zeroThreshold<T>()) {
422 if (!enableAllInterfaces) {
423 enableAllInterfaces =
true;
425 computeMassExcessWeights(cell, normal, enableAllInterfaces, weights);
426 for (
const auto& weight : weights) { weightsSum += weight; }
430 if (
util::fabs(weightsSum) < zeroThreshold<T>()) {
431 for (
auto& weight : weights) { weight = T(1); }
432 weightsSum = T(intefaceNbrs);
438 for (
auto& weight : weights) { weight = T(1); }
439 weightsSum = T(intefaceNbrs);
446 if (!enableAllInterfaces && oldIntefaceNbrs > std::uint8_t(0)) {
447 for (
auto& weight : weights) { weight = T(1); }
448 weightsSum = T(oldIntefaceNbrs);
452 enableAllInterfaces =
true;
453 for (
auto& weight : weights) { weight = T(1); }
454 weightsSum = T(intefaceNbrs);
459 for (
int iPop = 1; iPop < DESCRIPTOR::q; ++iPop) {
463 mass_exchange[iPop] = mass_excess * weights[iPop] / weightsSum;
466 mass_exchange[iPop] = mass_excess * weights[iPop] / weightsSum;
469 mass_exchange[iPop] = T(0);
473 cell.template setField<FreeSurface::TEMP_MASS_EXCHANGE>(mass_exchange);
488 cell.template setField<FreeSurface::EPSILON>(T(1));
492 cell.template setField<FreeSurface::EPSILON>(T(0));
509 T collected_excess = T(0);
510 for (
int iPop = 1; iPop < DESCRIPTOR::q; ++iPop) {
514 auto tempMassExchange = nbrCell.template getField<FreeSurface::TEMP_MASS_EXCHANGE>();
519 T mass_tmp = cell.template getField<FreeSurface::MASS>();
520 mass_tmp += collected_excess;
522 T u_tmp[DESCRIPTOR::d] = {T(0), T(0)};
523 cell.computeRhoU(rho, u_tmp);
525 cell.template setField<FreeSurface::EPSILON>(mass_tmp / rho);
526 cell.template setField<FreeSurface::MASS>(mass_tmp);
527 cell.template setField<FreeSurface::PREVIOUS_VELOCITY>(u_vel);
539 _sLattice.template addPostProcessor<FreeSurface::Stage0>(
541 _sLattice.template addPostProcessor<FreeSurface::Stage1>(
543 _sLattice.template addPostProcessor<FreeSurface::Stage2>(
545 _sLattice.template addPostProcessor<FreeSurface::Stage3>(
547 _sLattice.template addPostProcessor<FreeSurface::Stage4>(
549 _sLattice.template addPostProcessor<FreeSurface::Stage5>(
555 communicator.requestOverlap(_sLattice.getOverlap());
556 communicator.template requestField<FreeSurface::EPSILON>();
557 communicator.template requestField<FreeSurface::CELL_TYPE>();
558 communicator.template requestField<descriptors::POPULATION>();
559 communicator.template requestField<FreeSurface::PREVIOUS_VELOCITY>();
560 communicator.exchangeRequests();
566 communicator.requestOverlap(_sLattice.getOverlap());
567 communicator.template requestField<FreeSurface::MASS>();
568 communicator.template requestField<FreeSurface::PREVIOUS_VELOCITY>();
569 communicator.exchangeRequests();
575 communicator.requestOverlap(_sLattice.getOverlap());
576 communicator.template requestField<FreeSurface::CELL_FLAGS>();
577 communicator.template requestField<descriptors::POPULATION>();
578 communicator.exchangeRequests();
584 communicator.requestOverlap(_sLattice.getOverlap());
585 communicator.template requestField<FreeSurface::CELL_FLAGS>();
586 communicator.exchangeRequests();
592 communicator.requestOverlap(_sLattice.getOverlap());
593 communicator.template requestField<FreeSurface::CELL_FLAGS>();
594 communicator.exchangeRequests();
600 communicator.requestOverlap(_sLattice.getOverlap());
601 communicator.template requestField<FreeSurface::TEMP_MASS_EXCHANGE>();
602 communicator.exchangeRequests();
606 _sLattice.template addCustomTask<stage::PostStream>([&]() {
Free Surface Processor 7 Finishes up left over cell conversions and prepares the state for the next s...
void apply(CELL &cell) any_platform
Free Surface Processor 7: Finalize Conversion.
Free Surface Processor 2-3 Interface Reconstruction Replaces incoming DFs by calculating equilibrium ...
void apply(CELL &cell, PARAMETERS ¶ms) any_platform
Free Surface Processor 2-3: Interface Reconstruction.
Free Surface Processor 6 Calculates mass excess from the cell type conversions and distributes them t...
void apply(CELL &cell) any_platform
Free Surface Processor 6: Mass Excess.
Free Surface Processor 1 Mass Flow Cleans up leftover flags from the previous simulation step.
void apply(CELL &cell) any_platform
Free Surface Processor 1: Mass Flow.
void apply(CELL &cell) any_platform
Free Surface Processor 5 ToGas Converts cells to interface from fluid if a neighbouring cell was conv...
void apply(CELL &cell) any_platform
Free Surface Processor 5: ToGas.
static V secondOrder(int iPop, const RHO &rho, const U &u, const USQR &uSqr) any_platform
Computation of equilibrium distribution, second order in u.