OpenLB 1.8.1
Loading...
Searching...
No Matches
olb::FreeSurfaceMassExcessPostProcessor3D< T, DESCRIPTOR > Class Template Reference

Free Surface Processor 6 Calculates mass excess from the cell type conversions and distributes them to neighbouring interface cells Keeps mass local if no neighbour exists until an interface reappears at this position. More...

#include <freeSurfacePostProcessor3D.h>

+ Collaboration diagram for olb::FreeSurfaceMassExcessPostProcessor3D< T, DESCRIPTOR >:

Public Member Functions

int getPriority () const
 
template<typename CELL >
void apply (CELL &cell) any_platform
 Free Surface Processor 6: Mass Excess.
 

Static Public Attributes

static constexpr OperatorScope scope = OperatorScope::PerCell
 

Detailed Description

template<typename T, typename DESCRIPTOR>
class olb::FreeSurfaceMassExcessPostProcessor3D< T, DESCRIPTOR >

Free Surface Processor 6 Calculates mass excess from the cell type conversions and distributes them to neighbouring interface cells Keeps mass local if no neighbour exists until an interface reappears at this position.

Definition at line 128 of file freeSurfacePostProcessor3D.h.

Member Function Documentation

◆ apply()

template<typename T , typename DESCRIPTOR >
template<typename CELL >
void olb::FreeSurfaceMassExcessPostProcessor3D< T, DESCRIPTOR >::apply ( CELL & cell)

Free Surface Processor 6: Mass Excess.

Definition at line 352 of file freeSurfacePostProcessor3D.hh.

352 {
353 using namespace olb::FreeSurface;
354
355 // Note that EPSILON cannot be set in this operator because it is needed for the normal computation,
356 // thus MASS is set here and EPSILON is set by the next operator.
357 // Skip if the current cell is not an interface cell.
359 return;
360 }
361
362 T mass_excess = T(0);
363 // If an interface cell is flagged as toGas,
365 // Get mass of the current interface cell
366 const T mass = cell.template getField<FreeSurface::MASS>();
367 mass_excess = mass;
368 cell.template setField<FreeSurface::MASS>(T(0));
369 }
370 // If an interface cell is flagged as toFluid,
372 // Get density and mass of the current interface cell
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);
377 }
378 else { return; }
379
380 // Redistribute the excess mass among the neighbouring interface cells, note that
381 // if no neighbouring interface cells are found, the excess mass is lost or gained
382 // by the current cell.
383 // TODO: Thuerey Paper says we can't use new interface cells or flagged cells
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) {
387 auto nbrCell = cell.neighbor(descriptors::c<DESCRIPTOR>(iPop));
388
389 // Note that CELL_TYPE is not updated yet, and if no flag is set for this neighbour cell, it is an old interface cell
390 // This means that this neighbour cell will remain an interface cell for the next time step
392 ++oldIntefaceNbrs;
393 }
394 // If the neighbour cell is flagged as Newinterface, it is a new interface cell
396 ++newIntefaceNbrs;
397 }
398 }
399
400 // Return if no interface cell is available to distribute the excess mass, i.e., the mass is lost or gained.
401 const std::uint8_t intefaceNbrs = newIntefaceNbrs + oldIntefaceNbrs;
402 if (intefaceNbrs == std::uint8_t(0)) { return; }
403
404 // Distribution of excess mass among the neighbouring interface cells, weighted or evenly.
405 bool enableAllInterfaces = true;
406 constexpr bool weightedDistribution = true;
407 Vector<T, DESCRIPTOR::q> weights{};
408 T weightsSum = T(0);
409
410 // (1) Distribute excess mass among the neighbouring interface cells, weighted by normal vector.
411 if constexpr (weightedDistribution) {
412 // Compute the weights for the mass excess distribution using normal vector of the current interface cell.
413 auto normal = computeInterfaceNormal(cell);
414 computeMassExcessWeights(cell, normal, enableAllInterfaces, weights);
415
416 // Calculate sum of the computed weights
417 for (const auto& weight : weights) { weightsSum += weight; }
418
419 if (util::fabs(weightsSum) < zeroThreshold<T>()) {
420 // (a) If no old interface cell is available in normal direction,
421 // fall back to weighted all interface cells distribution model.
422 if (!enableAllInterfaces) {
423 enableAllInterfaces = true;
424 weightsSum = T(0);
425 computeMassExcessWeights(cell, normal, enableAllInterfaces, weights);
426 for (const auto& weight : weights) { weightsSum += weight; }
427
428 // (b) If no interface cell is available in normal direction,
429 // fall back to evenly all interface cells distribution model.
430 if (util::fabs(weightsSum) < zeroThreshold<T>()) {
431 for (auto& weight : weights) { weight = T(1); }
432 weightsSum = T(intefaceNbrs);
433 }
434 }
435 // (c) If all interface cells are selected but none is available in normal direction,
436 // fall back to evenly all interface cells distribution model.
437 else {
438 for (auto& weight : weights) { weight = T(1); }
439 weightsSum = T(intefaceNbrs);
440 }
441 }
442 }
443 // (2) Distribute excess mass among the neighbouring interface cells, evenly.
444 else {
445 // (a) Use old neighbouring interface cells to distribute excess mass.
446 if (!enableAllInterfaces && oldIntefaceNbrs > std::uint8_t(0)) {
447 for (auto& weight : weights) { weight = T(1); }
448 weightsSum = T(oldIntefaceNbrs);
449 }
450 // (b) Use all neighbouring interface cells to distribute excess mass.
451 else {
452 enableAllInterfaces = true;
453 for (auto& weight : weights) { weight = T(1); }
454 weightsSum = T(intefaceNbrs);
455 }
456 }
457
458 Vector<T, DESCRIPTOR::q> mass_exchange{};
459 for (int iPop = 1; iPop < DESCRIPTOR::q; ++iPop) {
460 auto nbrCell = cell.neighbor(descriptors::c<DESCRIPTOR>(iPop));
461
463 mass_exchange[iPop] = mass_excess * weights[iPop] / weightsSum;
464 }
465 else if (hasCellFlags(nbrCell, FreeSurface::Flags::NewInterface) && enableAllInterfaces) {
466 mass_exchange[iPop] = mass_excess * weights[iPop] / weightsSum;
467 }
468 else {
469 mass_exchange[iPop] = T(0);
470 }
471 }
472
473 cell.template setField<FreeSurface::TEMP_MASS_EXCHANGE>(mass_exchange);
474}
Plain old scalar vector.
void computeMassExcessWeights(CELL &cell, const Vector< V, CELL::descriptor_t::d > &normal, const bool &enableAllInterfaces, Vector< V, CELL::descriptor_t::q > &weights)
Vector< V, CELL::descriptor_t::d > computeInterfaceNormal(CELL &cell)
bool isCellType(CELL &cell, const FreeSurface::Type &type)
bool hasCellFlags(CELL &cell, const FreeSurface::Flags &flags)
constexpr int c(unsigned iPop, unsigned iDim) any_platform
Definition functions.h:83
Distribution< T > normal(T mean, T stddev)
Expr fabs(Expr x)
Definition expr.cpp:230

References olb::descriptors::c(), olb::util::fabs(), olb::FreeSurface::Interface, olb::FreeSurface::NewInterface, olb::FreeSurface::None, olb::FreeSurface::ToFluid, and olb::FreeSurface::ToGas.

+ Here is the call graph for this function:

◆ getPriority()

template<typename T , typename DESCRIPTOR >
int olb::FreeSurfaceMassExcessPostProcessor3D< T, DESCRIPTOR >::getPriority ( ) const
inline

Definition at line 132 of file freeSurfacePostProcessor3D.h.

132 {
133 return 5;
134 }

Member Data Documentation

◆ scope

template<typename T , typename DESCRIPTOR >
OperatorScope olb::FreeSurfaceMassExcessPostProcessor3D< T, DESCRIPTOR >::scope = OperatorScope::PerCell
staticconstexpr

Definition at line 130 of file freeSurfacePostProcessor3D.h.


The documentation for this class was generated from the following files: