59 const bool drop_isolated_cells = vars.template get<FreeSurface::DROP_ISOLATED_CELLS>();
60 const T transition = vars.template get<FreeSurface::TRANSITION>();
61 const T lonely_threshold = vars.template get<FreeSurface::LONELY_THRESHOLD>();
62 const bool has_surface_tension = vars.template get<FreeSurface::HAS_SURFACE_TENSION>();
63 const T surface_tension_parameter = vars.template get<FreeSurface::SURFACE_TENSION_PARAMETER>();
76 T mass_tmp = cell.template getField<FreeSurface::MASS>();
80 for (
int iPop = 1; iPop < DESCRIPTOR::q; ++iPop){
81 auto cellC = cell.neighbor({descriptors::c<DESCRIPTOR>(iPop, 0),
82 descriptors::c<DESCRIPTOR>(iPop, 1),
83 descriptors::c<DESCRIPTOR>(iPop, 2)});
84 int iPop_op = descriptors::opposite<DESCRIPTOR>(iPop);
93 mass_tmp += cell[iPop_op] - cellC[iPop];
102 mass_flow = -cellC[iPop];
104 mass_flow = cell[iPop_op];
106 mass_flow = cell[iPop_op] - cellC[iPop];
109 mass_flow = -cellC[iPop];
114 mass_flow = cell[iPop_op];
116 mass_flow = -cellC[iPop];
118 mass_flow = cell[iPop_op] - cellC[iPop];
121 mass_flow = cell[iPop_op];
125 mass_flow = cell[iPop_op];
127 mass_flow = -cellC[iPop];
129 mass_flow = cell[iPop_op] - cellC[iPop];
136 mass_tmp += mass_flow * 0.5 * (getClampedEpsilon(cell) + getClampedEpsilon(cellC));
140 cell.template setField<FreeSurface::MASS>(mass_tmp);
151 if(has_surface_tension){
154 curvature = calculateSurfaceTensionCurvature(cell);
160 T gas_pressure = 1. - 6. * surface_tension_parameter * curvature;
162 for(
int iPop=1; iPop < DESCRIPTOR::q; iPop++) {
163 auto cellC = cell.neighbor({descriptors::c<DESCRIPTOR>(iPop, 0),
164 descriptors::c<DESCRIPTOR>(iPop, 1),
165 descriptors::c<DESCRIPTOR>(iPop, 2)});
166 int iPop_op = descriptors::opposite<DESCRIPTOR>(iPop);
174 for(
size_t u_i = 0; u_i < DESCRIPTOR::d; ++u_i){
182 dfs[iPop_op] = cell[iPop_op];
186 for(
int iPop=1; iPop<DESCRIPTOR::q; iPop++) {
187 cell[iPop] = dfs[iPop];
194 T rho = cell.computeRho();
197 if ( mass_tmp < -transition * rho || (mass_tmp < lonely_threshold * rho && !neighbour_info.
has_fluid_neighbours) ){
200 else if ( mass_tmp > (1. + transition)*rho || ( mass_tmp > (1-lonely_threshold) * rho && !neighbour_info.
has_gas_neighbours) ){
239 T u_avg[DESCRIPTOR::d] = {0., 0.};
243 for(
int iPop=1; iPop<DESCRIPTOR::q; iPop++) {
244 auto cellC = cell.neighbor({descriptors::c<DESCRIPTOR>(iPop,0),
245 descriptors::c<DESCRIPTOR>(iPop,1),
246 descriptors::c<DESCRIPTOR>(iPop,2)});
250 T u_tmp[DESCRIPTOR::d] = {0., 0.};
252 cellC.computeRhoU(rho_tmp, u_tmp);
254 for(
size_t i = 0; i < DESCRIPTOR::d; ++i){
255 u_avg[i] += u_tmp[i];
261 rho_avg /=
static_cast<T
>(ctr);
262 for(
size_t i = 0; i < DESCRIPTOR::d; ++i){
263 u_avg[i] /=
static_cast<T
>(ctr);
267 cell.iniEquilibrium(rho_avg, u_avg);
332 T rho = cell.computeRho();
333 T mass = cell.template getField<FreeSurface::MASS>( );
336 auto normal = computeParkerYoungInterfaceNormal(cell);
344 cell.template setField<FreeSurface::MASS>( 0. );
347 mass_excess = mass - rho;
348 cell.template setField<FreeSurface::MASS>( rho );
353 std::array<T,DESCRIPTOR::q> products;
356 std::size_t product_total = 0;
358 for(
int iPop=1; iPop<DESCRIPTOR::q; iPop++) {
359 auto cellC = cell.neighbor({descriptors::c<DESCRIPTOR>(iPop,0),
360 descriptors::c<DESCRIPTOR>(iPop,1),
361 descriptors::c<DESCRIPTOR>(iPop,2)});
371 products[iPop] = (normal[0] * descriptors::c<DESCRIPTOR>(iPop, 0) + normal[1] * descriptors::c<DESCRIPTOR>(iPop,1) + normal[2] * descriptors::c<DESCRIPTOR>(iPop,2));
372 if(products[iPop] <= 0){
376 product_sum += products[iPop];
382 mass_excess_vector[0] = 0.;
393 if (product_total > 0) {
394 T product_fraction = 1. / product_total;
395 for(
int iPop=1; iPop < DESCRIPTOR::q; iPop++) {
396 auto cellC = cell.neighbor({descriptors::c<DESCRIPTOR>(iPop,0),
397 descriptors::c<DESCRIPTOR>(iPop,1),
398 descriptors::c<DESCRIPTOR>(iPop,2)});
403 mass_excess_vector[iPop] = mass_excess * product_fraction;
405 mass_excess_vector[iPop] = 0.;
408 cell.template setField<FreeSurface::TEMP_MASS_EXCHANGE>( mass_excess_vector );
410 mass_excess_vector[0] = mass_excess;
411 for(
int iPop=1; iPop < DESCRIPTOR::q; iPop++) {
412 mass_excess_vector[iPop] = 0.;
414 cell.template setField<FreeSurface::TEMP_MASS_EXCHANGE>( mass_excess_vector );
450 cell.template setField<FreeSurface::EPSILON>( 1. );
451 T mass_tmp = cell.template getField<FreeSurface::MASS>();
452 mass_tmp += cell.template getField<FreeSurface::TEMP_MASS_EXCHANGE>()[0];
453 cell.template setField<FreeSurface::MASS>(mass_tmp);
461 cell.template setField<FreeSurface::EPSILON>( 0. );
462 T mass_tmp = cell.template getField<FreeSurface::MASS>();
463 mass_tmp += cell.template getField<FreeSurface::TEMP_MASS_EXCHANGE>()[0];
464 cell.template setField<FreeSurface::MASS>(mass_tmp);
483 T collected_excess = 0.;
484 for(
int iPop = 1; iPop < DESCRIPTOR::q; ++iPop){
485 auto cellC = cell.neighbor({descriptors::c<DESCRIPTOR>(iPop,0),
486 descriptors::c<DESCRIPTOR>(iPop,1),
487 descriptors::c<DESCRIPTOR>(iPop,2)});
488 auto tempMassExchange = cellC.template getFieldPointer<FreeSurface::TEMP_MASS_EXCHANGE>();
490 if (hasCellFlags(cellC,
493 int iPop_op = descriptors::opposite<DESCRIPTOR>(iPop);
494 collected_excess += tempMassExchange[iPop_op];
498 T mass_tmp = cell.template getField<FreeSurface::MASS>();
500 mass_tmp += collected_excess;
502 T u_tmp[DESCRIPTOR::d];
503 cell.computeRhoU(rho, u_tmp);
507 cell.template setField<FreeSurface::EPSILON>( mass_tmp / rho );
508 cell.template setField<FreeSurface::MASS>(mass_tmp);
509 cell.template setField<FreeSurface::PREVIOUS_VELOCITY>(u_vel);
514 T collected_excess = 0.;
516 for(
int iPop = 1; iPop < DESCRIPTOR::q; ++iPop){
517 auto cellC = cell.neighbor({descriptors::c<DESCRIPTOR>(iPop,0),
518 descriptors::c<DESCRIPTOR>(iPop,1),
519 descriptors::c<DESCRIPTOR>(iPop,2)});
520 auto tempMassExchange = cellC.template getFieldPointer<FreeSurface::TEMP_MASS_EXCHANGE>();
521 if (hasCellFlags(cellC,
524 int iPop_op = descriptors::opposite<DESCRIPTOR>(iPop);
525 collected_excess += tempMassExchange[iPop_op];
529 T mass_tmp = cell.template getField<FreeSurface::MASS>();
530 mass_tmp += collected_excess;
531 cell.template setField<FreeSurface::MASS>(mass_tmp);
548 sLattice.template addPostProcessor<FreeSurface::Stage0>(
550 sLattice.template addPostProcessor<FreeSurface::Stage1>(
552 sLattice.template addPostProcessor<FreeSurface::Stage2>(
554 sLattice.template addPostProcessor<FreeSurface::Stage3>(
556 sLattice.template addPostProcessor<FreeSurface::Stage4>(
562 communicator.requestOverlap(2);
563 communicator.template requestField<FreeSurface::EPSILON>();
564 communicator.template requestField<FreeSurface::CELL_TYPE>();
565 communicator.template requestField<descriptors::POPULATION>();
566 communicator.exchangeRequests();
572 communicator.requestOverlap(2);
573 communicator.template requestField<FreeSurface::CELL_FLAGS>();
574 communicator.template requestField<descriptors::POPULATION>();
575 communicator.exchangeRequests();
581 communicator.requestOverlap(2);
582 communicator.template requestField<FreeSurface::CELL_FLAGS>();
583 communicator.exchangeRequests();
589 communicator.requestOverlap(2);
590 communicator.template requestField<FreeSurface::CELL_FLAGS>();
591 communicator.exchangeRequests();
597 communicator.requestOverlap(2);
598 communicator.template requestField<FreeSurface::TEMP_MASS_EXCHANGE>();
599 communicator.exchangeRequests();
602 sLattice.template addCustomTask<stage::PostStream>([&]() {
Free Surface Processor 7 Finishes up left over cell conversions and prepares the state for the next s...
Free Surface Processor 6 Calculates mass excess from the cell type conversions and distributes them t...
Free Surface Processor 1-3 Mass Flow Cleans up leftover flags from the previous simulation step.
void apply(CELL &cell, PARAMETERS ¶meters) any_platform
Free Surface Processor 5 ToGas Converts cells to interface from fluid if a neighbouring cell was conv...