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

Free Surface Processor 1 Mass Flow Cleans up leftover flags from the previous simulation step. More...

#include <freeSurfacePostProcessor2D.h>

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

Public Member Functions

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

Static Public Attributes

static constexpr OperatorScope scope = OperatorScope::PerCell
 

Detailed Description

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

Free Surface Processor 1 Mass Flow Cleans up leftover flags from the previous simulation step.

This post processor is responsible for the calculation of exchange mass with the help of the distribution functions. This whole step should be included in the collideAndStream step, though heavy modification of openlb would be necessary

Definition at line 43 of file freeSurfacePostProcessor2D.h.

Member Function Documentation

◆ apply()

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

Free Surface Processor 1: Mass Flow.

Definition at line 38 of file freeSurfacePostProcessor2D.hh.

38 {
39
40 using namespace olb::FreeSurface;
41
42 // Reset CELL_FLAGS and TEMP_MASS_EXCHANGE here, as they are needed in the final post-processor step
44 Vector<T, DESCRIPTOR::q> zero_mass_exchange{};
45 cell.template setField<FreeSurface::TEMP_MASS_EXCHANGE>(zero_mass_exchange);
46
47 // Skip if the current cell is not an interface cell.
49 return;
50 }
51
52 // Check if the current interface cell has gas or fluid neighbours
54 bool hasNoGasNeighbours = !nbrInfo.has_gas_neighbours;
55 bool hasNoFluidNeighbours = !nbrInfo.has_fluid_neighbours;
56 bool isHealthyInterfaceCell = isHealthyInterface(cell);
57
58 // The cell has only interface cells as neighbours
59 if (hasNoGasNeighbours && hasNoFluidNeighbours) {
60 hasNoGasNeighbours = false;
61 hasNoFluidNeighbours = false;
62 isHealthyInterfaceCell = true;
63 }
64
65 // The notation used here differs from that in N. Thuerey's dissertation (2007), specifically in Section 4.1.
66 // This is because the free-surface post-processors are scheduled for execution during the PostStream stage,
67 // which occurs after the collideAndStream step. However, mass exchange computations require access to
68 // post-collision distribution functions at this stage.
69 // Since the post-collision distribution functions are not directly available here, we rely on the fact that,
70 // for the current cell, the post-collision f_(i) is equal to that of the corresponding neighbouring cell
71 // post-stream, i.e., cell[i](*) = nbrCell[i].
72 // Keep in mind that each cell has DESCRIPTOR::q neighbours, and each neighbor contains DESCRIPTOR::q
73 // distribution functions.
74 T mass_exchange = T(0);
75 for (int iPop = 1; iPop < DESCRIPTOR::q; ++iPop) {
76 auto nbrCell = cell.neighbor(descriptors::c<DESCRIPTOR>(iPop));
77
78 // Skip if the neighbour is a gas cell, i.e., no mass exchange
79 if (isCellType(nbrCell, FreeSurface::Type::Gas)) { continue; }
80
81 // Mass exchange with a liquid neighbour, i.e., computed uisng the difference between incoming and outgoing DFs
83 mass_exchange += cell[descriptors::opposite<DESCRIPTOR>(iPop)] - nbrCell[iPop];
84 continue;
85 }
86
87 // Check if the neighbour cell has gas or fluid neighbours
88 FreeSurface::NeighbourInfo nbrNeighbourInfo = getNeighbourInfo(nbrCell);
89 bool nbrHasNoGasNeighbours = !nbrNeighbourInfo.has_gas_neighbours;
90 bool nbrHasNoFluidNeighbours = !nbrNeighbourInfo.has_fluid_neighbours;
91 bool nbrIsHealthyInterfaceCell = isHealthyInterface(nbrCell);
92
93 // Neighbour cell has only interface cells as neighbours
94 if (nbrHasNoGasNeighbours && nbrHasNoFluidNeighbours) {
95 nbrHasNoGasNeighbours = false;
96 nbrHasNoFluidNeighbours = false;
97 nbrIsHealthyInterfaceCell = true;
98 }
99
100 T pdf_difference = T(0);
102 // Simple mass exchange if both current cell and neighbour cell are healthy interfaces
103 if (isHealthyInterfaceCell && nbrIsHealthyInterfaceCell) {
104 pdf_difference = cell[descriptors::opposite<DESCRIPTOR>(iPop)] - nbrCell[iPop];
105 }
106 else {
107 // A healthy interface cell with a neighbour that has no gas neighbours itself,
108 // or an interface cell with no liquid neighbours, but its neighbor has a liquid neighbour.
109 // make this cell empty, ref. N. Thuerey dissertation, 2007.
110 if ((isHealthyInterfaceCell && nbrHasNoGasNeighbours) || (hasNoFluidNeighbours && !nbrHasNoFluidNeighbours)) {
111 pdf_difference = -nbrCell[iPop];
112 }
113 else {
114 // A healthy interface cell with a neighbour that has no fluid neighbours itself,
115 // or an interface cell with no gas neighbours, but its neighbour has a gas neighbour.
116 // make the neighbour cell empty, ref. N. Thuerey dissertation, 2007.
117 if ((isHealthyInterfaceCell && nbrHasNoFluidNeighbours) || (hasNoGasNeighbours && !nbrHasNoGasNeighbours)) {
118 pdf_difference = cell[descriptors::opposite<DESCRIPTOR>(iPop)];
119 }
120 else {
121 // An interface cell with no liquid neighbors, whose neighbor also has no liquid neighbors,
122 // or an interface cell with no gas neighbors, whose neighbor also has no liquid neighbors.
123 // ref. N. Thuerey dissertation, 2007.
124 if ((hasNoFluidNeighbours && nbrHasNoFluidNeighbours) || (hasNoGasNeighbours && nbrHasNoGasNeighbours)) {
125 pdf_difference = cell[descriptors::opposite<DESCRIPTOR>(iPop)] - nbrCell[iPop];
126 }
127 }
128 }
129 }
130 }
131
132 const T epsilon_average = T(0.5) * (getClampedEpsilon(cell) + getClampedEpsilon(nbrCell));
133 mass_exchange += pdf_difference * epsilon_average;
134 }
135
136 // Update the mass of interface cell
137 const auto mass = cell.template getField<FreeSurface::MASS>();
138 cell.template setField<FreeSurface::MASS>(mass + mass_exchange);
139}
Plain old scalar vector.
V getClampedEpsilon(const CELL &cell)
bool isCellType(CELL &cell, const FreeSurface::Type &type)
bool isHealthyInterface(CELL &cell)
void setCellFlags(CELL &cell, const FreeSurface::Flags &flags)
NeighbourInfo getNeighbourInfo(CELL &cell)
constexpr int c(unsigned iPop, unsigned iDim) any_platform
Definition functions.h:83
constexpr int opposite(unsigned iPop) any_platform
Definition functions.h:95

References olb::descriptors::c(), olb::FreeSurface::Fluid, olb::FreeSurface::Gas, olb::FreeSurface::NeighbourInfo::has_fluid_neighbours, olb::FreeSurface::NeighbourInfo::has_gas_neighbours, olb::FreeSurface::Interface, olb::FreeSurface::None, and olb::descriptors::opposite().

+ Here is the call graph for this function:

◆ getPriority()

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

Definition at line 47 of file freeSurfacePostProcessor2D.h.

47 {
48 return 1;
49 }

Member Data Documentation

◆ scope

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

Definition at line 45 of file freeSurfacePostProcessor2D.h.


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