OpenLB 1.7
Loading...
Searching...
No Matches
Classes | Enumerations | Functions
olb::FreeSurface Namespace Reference

Classes

struct  CELL_FLAGS
 
struct  CELL_TYPE
 
struct  DROP_ISOLATED_CELLS
 
struct  EPSILON
 
struct  FORCE_CONVERSION_FACTOR
 
struct  HAS_SURFACE_TENSION
 
struct  LATTICE_SIZE
 
struct  LONELY_THRESHOLD
 
struct  MASS
 
struct  NeighbourInfo
 
struct  PREVIOUS_VELOCITY
 
struct  Stage0
 
struct  Stage1
 
struct  Stage2
 
struct  Stage3
 
struct  Stage4
 
struct  SURFACE_TENSION_PARAMETER
 
struct  TEMP_MASS_EXCHANGE
 
struct  TRANSITION
 

Enumerations

enum class  Type : std::uint8_t { Gas = 0 , Interface = 1 , Fluid = 2 , Solid = 4 }
 
enum class  Flags : std::uint8_t { ToGas = 1 , ToFluid = 2 , NewInterface = 4 }
 

Functions

template<typename T , typename DESCRIPTOR >
void initialize (SuperLattice< T, DESCRIPTOR > &lattice)
 
template<typename T , typename DESCRIPTOR >
std::enable_if_t< DESCRIPTOR::d==2, T > offsetHelper (T volume, const Vector< T, DESCRIPTOR::d > &sorted_normal) any_platform
 
template<typename T , typename DESCRIPTOR >
std::enable_if_t< DESCRIPTOR::d==3, T > offsetHelper (T volume, const Vector< T, DESCRIPTOR::d > &sorted_normal) any_platform
 
template<typename T , typename DESCRIPTOR >
offsetHelperOpt (T vol, const Vector< T, DESCRIPTOR::d > &sn) any_platform
 
template<typename T , size_t S>
std::array< T, S > solvePivotedLU (std::array< std::array< T, S >, S > &matrix, const std::array< T, S > &b, size_t N)
 
template<typename CELL >
bool isCellType (CELL &cell, const FreeSurface::Type &type)
 
template<typename CELL >
bool hasCellFlags (CELL &cell, const FreeSurface::Flags &flags)
 
template<typename CELL >
bool hasNeighbour (CELL &cell, const FreeSurface::Type &type)
 
template<typename CELL >
bool hasNeighbourFlags (CELL &cell, const FreeSurface::Flags &flags)
 
template<typename CELL , typename V >
Vector< V, CELL::descriptor_t::d > computeInterfaceNormal (CELL &cell)
 
template<typename CELL , typename V >
Vector< V, CELL::descriptor_t::d > computeParkerYoungInterfaceNormal (CELL &cell)
 
template<typename CELL , typename V >
getClampedEpsilon (CELL &cell)
 
template<typename T , typename DESCRIPTOR >
calculateCubeOffset (T volume, const Vector< T, DESCRIPTOR::d > &normal)
 
template<typename T , typename DESCRIPTOR >
calculateCubeOffsetOpt (T volume, const Vector< T, DESCRIPTOR::d > &normal)
 
template<typename CELL , typename V >
calculateSurfaceTensionCurvature (CELL &cell)
 
template<typename CELL , typename V >
calculateSurfaceTensionCurvature2D (CELL &cell)
 
template<typename CELL , typename V >
calculateSurfaceTensionCurvature3D (CELL &cell)
 
template<typename T , typename DESCRIPTOR >
plicInverse (T d_o, const Vector< T, DESCRIPTOR::d > &normal)
 
template<typename CELL >
NeighbourInfo getNeighbourInfo (CELL &cell)
 
template<typename CELL , typename V >
bool isHealthyInterface (CELL &cell)
 
template<typename CELL , typename V >
void setCellType (CELL &cell, const FreeSurface::Type &type)
 
template<typename CELL , typename V >
void setCellFlags (CELL &cell, const FreeSurface::Flags &flags)
 

Enumeration Type Documentation

◆ Flags

enum class olb::FreeSurface::Flags : std::uint8_t
strong
Enumerator
ToGas 
ToFluid 
NewInterface 

Definition at line 49 of file freeSurfaceHelpers.h.

49 : std::uint8_t {
50 ToGas = 1,
51 ToFluid = 2,
52 NewInterface = 4
53};

◆ Type

enum class olb::FreeSurface::Type : std::uint8_t
strong
Enumerator
Gas 
Interface 
Fluid 
Solid 

Definition at line 42 of file freeSurfaceHelpers.h.

42 : std::uint8_t {
43 Gas = 0,
44 Interface = 1,
45 Fluid = 2,
46 Solid = 4
47};

Function Documentation

◆ calculateCubeOffset()

template<typename T , typename DESCRIPTOR >
T olb::FreeSurface::calculateCubeOffset ( T volume,
const Vector< T, DESCRIPTOR::d > & normal )

Definition at line 297 of file freeSurfaceHelpers.hh.

297 {
298 std::vector<T> abs_normal(DESCRIPTOR::d, T{0});
299 for(int i = 0; i < DESCRIPTOR::d; i++){
300 abs_normal[i] = util::abs(normal[i]);
301 }
302
303 T volume_symmetry = 0.5 - util::abs(volume - 0.5);
304
305 std::sort(abs_normal.begin(), abs_normal.end());
306
307 if constexpr (DESCRIPTOR::d == 2) {
308 abs_normal[0] = util::max(normal[0], 1e-5);
309 } else if (DESCRIPTOR::d == 3){
310 abs_normal[0] = util::max(normal[0], 1e-12);
311 abs_normal[1] = util::max(normal[1], 1e-12);
312 }
313
314 T d = offsetHelper<T,DESCRIPTOR>(volume_symmetry, abs_normal);
315
316 T sorted_normal_acc = 0;
317 for(int i = 0; i < DESCRIPTOR::d; i++){
318 sorted_normal_acc += abs_normal[i];
319 }
320
321 return std::copysign(d - 0.5 * sorted_normal_acc, volume - 0.5);
322}
constexpr int d() any_platform

References olb::util::abs(), and olb::util::max().

+ Here is the call graph for this function:

◆ calculateCubeOffsetOpt()

template<typename T , typename DESCRIPTOR >
T olb::FreeSurface::calculateCubeOffsetOpt ( T volume,
const Vector< T, DESCRIPTOR::d > & normal )

Definition at line 326 of file freeSurfaceHelpers.hh.

326 {
328
329 abs_normal[0] = util::abs(normal[0]);
330 abs_normal[1] = util::abs(normal[1]);
331 abs_normal[2] = util::abs(normal[2]);
332
333 T a_l1 = abs_normal[0] + abs_normal[1] + abs_normal[2];
334
335 T volume_symmetry = 0.5 - util::abs(volume - 0.5);
336
337 olb::Vector<T,DESCRIPTOR::d> sorted_normal;
338 sorted_normal[0] = util::min(util::min(abs_normal[0], abs_normal[1]), abs_normal[2]) / a_l1;
339 sorted_normal[1] = 0.;
340 sorted_normal[2] = util::max(util::max(abs_normal[0], abs_normal[1]), abs_normal[2]) / a_l1;
341
342 sorted_normal[1] = util::max(1. - sorted_normal[0] - sorted_normal[2], 0.);
343
344 T d = offsetHelperOpt<T,DESCRIPTOR>(volume_symmetry, sorted_normal);
345
346 return a_l1 * std::copysign(0.5 - d, volume - 0.5);
347}
Plain old scalar vector.
Definition vector.h:47

References olb::util::abs(), olb::util::max(), and olb::util::min().

+ Here is the call graph for this function:

◆ calculateSurfaceTensionCurvature()

template<typename CELL , typename V >
V olb::FreeSurface::calculateSurfaceTensionCurvature ( CELL & cell)

Definition at line 350 of file freeSurfaceHelpers.hh.

350 {
351 using DESCRIPTOR = typename CELL::descriptor_t;
352
353 if constexpr (DESCRIPTOR::d == 2) {
354 return calculateSurfaceTensionCurvature2D(cell);
355 } else if (DESCRIPTOR::d == 3){
356 return calculateSurfaceTensionCurvature3D(cell);
357 }
358
359 return 0;
360}

◆ calculateSurfaceTensionCurvature2D()

template<typename CELL , typename V >
V olb::FreeSurface::calculateSurfaceTensionCurvature2D ( CELL & cell)

Definition at line 363 of file freeSurfaceHelpers.hh.

363 {
364 auto normal = computeParkerYoungInterfaceNormal(cell);
365
366 using DESCRIPTOR = typename CELL::descriptor_t;
367 {
368 V norm = 0.;
369 for(size_t i = 0; i < DESCRIPTOR::d; ++i){
370 norm += normal[i] * normal[i];
371 }
372
373 norm = util::sqrt(norm);
374
375 if(norm < 1e-6){
376 return 0.;
377 }
378
379 for(size_t i = 0; i <DESCRIPTOR::d; ++i){
380 normal[i] /= norm;
381 }
382 }
383
384 // Rotation matrix is
385 // ( n1 | -n0 )
386 // ( n0 | n1 )
387
388 // It is 2 because of the amount of fitting parameters. Not because of the dimension
389 constexpr size_t S = 2;
390 std::array<std::array<V,S>, S> lq_matrix;
391 std::array<V,S> b_rhs;
392 for(size_t i = 0; i < S; ++i){
393 for(size_t j = 0; j < S; ++j){
394 lq_matrix[i][j] = 0.;
395 }
396 b_rhs[i] = 0.;
397 }
398
399 // Offset for the plic correction
400 V origin_offset = 0.;
401 {
402 V fill_level = getClampedEpsilon(cell);
403 origin_offset = calculateCubeOffset<V,DESCRIPTOR>(fill_level, normal);
404 }
405
406 // The amount of neighbouring interfaces. if less are available we will solve a reduced curve by setting the less important parameters to zero
407 std::size_t healthy_interfaces = 0;
408
409 for (int iPop=1; iPop < DESCRIPTOR::q; ++iPop) {
410 auto cellC = cell.neighbor(descriptors::c<DESCRIPTOR>(iPop));
411
412 if( !isCellType(cellC, FreeSurface::Type::Interface)
413 || !hasNeighbour(cellC, FreeSurface::Type::Gas)) {
414 continue;
415 }
416
417 ++healthy_interfaces;
418
419 V fill_level = getClampedEpsilon(cellC);
420
421 V cube_offset = calculateCubeOffset<V,DESCRIPTOR>(fill_level, normal);
422
423 V x_pos = descriptors::c<DESCRIPTOR>(iPop,0);
424 V y_pos = descriptors::c<DESCRIPTOR>(iPop,1);
425
426 // Rotation
427 V rot_x_pos = x_pos * normal[1] - y_pos * normal[0];
428 V rot_y_pos = x_pos * normal[0] + y_pos * normal[1] + (cube_offset - origin_offset);
429
430 V rot_x_pos_2 = rot_x_pos * rot_x_pos;
431 V rot_x_pos_3 = rot_x_pos_2 * rot_x_pos;
432 V rot_x_pos_4 = rot_x_pos_3 * rot_x_pos;
433
434 lq_matrix[1][1] += rot_x_pos_2;
435 lq_matrix[1][0] += rot_x_pos_3;
436 lq_matrix[0][0] += rot_x_pos_4;
437
438 b_rhs[0] += rot_x_pos_2*(rot_y_pos);
439 b_rhs[1] += rot_x_pos*(rot_y_pos);
440 }
441
442 lq_matrix[0][1] = lq_matrix[1][0];
443
444 // Thikonov regularization parameter
445 V alpha = 0.0;
446 for(size_t i = 0; i < DESCRIPTOR::d; ++i){
447 lq_matrix[i][i] += alpha;
448 }
449
450 // It is 2 because of the fitting parameters. Not dependent on the dimension
451 std::array<V,S> solved_fit = FreeSurface::solvePivotedLU<V,S>(lq_matrix, b_rhs, healthy_interfaces);
452
453 // signed curvature -> kappa = y'' / ( (1 + y'²)^(3/2) )
454 V denom = std::sqrt(1. + solved_fit[1]*solved_fit[1]);
455 denom = denom * denom * denom;
456 V curvature = 2.*solved_fit[0] / denom;
457 return util::max(-1., util::min(1., curvature));
458}
constexpr T norm(const ScalarVector< T, D, IMPL > &a)
Euclidean vector norm.

References Gas, Interface, olb::util::max(), olb::util::min(), olb::norm(), and olb::util::sqrt().

+ Here is the call graph for this function:

◆ calculateSurfaceTensionCurvature3D()

template<typename CELL , typename V >
V olb::FreeSurface::calculateSurfaceTensionCurvature3D ( CELL & cell)

Definition at line 461 of file freeSurfaceHelpers.hh.

461 {
462 // This is b_z
463 auto normal = computeParkerYoungInterfaceNormal(cell);
464
465 using DESCRIPTOR = typename CELL::descriptor_t;
466 {
467 V norm = 0.;
468 for(size_t i = 0; i < DESCRIPTOR::d; ++i){
469 norm += normal[i] * normal[i];
470 }
471
472 norm = util::sqrt(norm);
473
474 if(norm < 1e-12){
475 return 0.;
476 }
477
478 for(size_t i = 0; i <DESCRIPTOR::d; ++i){
479 normal[i] /= norm;
480 }
481 }
482
483 std::array<V,3> r_vec{
484 0.56270900, 0.32704452, 0.75921047
485 };
486 /*
487 std::array<T,DESCRIPTOR::d> r_vec{
488 0.,0.,1.
489 };
490 */
491 std::array<std::array<V,3>,3> rotation{{
492 {{0., 0., 0.}},
493 //{{normal[1], -normal[0], 0.}},
494 {{normal[1] * r_vec[2] - normal[2] * r_vec[1], normal[2] * r_vec[0] - normal[0] * r_vec[2], normal[0] * r_vec[1] - normal[1] * r_vec[0]}},
495 {{normal[0], normal[1], normal[2]}}
496 }};
497
498 // Cross product with (0,0,1) x normal
499 // This is b_y
500
501 // (normal[0], normal[1], normal[2])
502
503 V cross_norm = 0.;
504 for(size_t i = 0; i < DESCRIPTOR::d; ++i){
505 cross_norm += rotation[1][i] * rotation[1][i];
506 }
507
508 // If too close too each other use the identity matrix
509 if(cross_norm > 1e-6){
510
511 cross_norm = util::sqrt(cross_norm);
512
513 for(size_t i = 0; i <DESCRIPTOR::d; ++i){
514 rotation[1][i] /= cross_norm;
515 }
516 }else {
517
518 rotation[1] = {{
519 -normal[2],
520 0.,
521 normal[0]
522 }};
523
524 cross_norm = 0.;
525 for(size_t i = 0; i < DESCRIPTOR::d; ++i){
526 cross_norm += rotation[1][i] * rotation[1][i];
527 }
528
529 cross_norm = util::sqrt(cross_norm);
530
531 for(size_t i = 0; i <DESCRIPTOR::d; ++i){
532 rotation[1][i] /= cross_norm;
533 }
534 }
535
536 // Cross product of ((0,0,1) x normal / | (0,0,1) x normal |) x normal
537 // This is b_x
538 rotation[0] = {{
539 rotation[1][1] * normal[2] - rotation[1][2] * normal[1],
540 rotation[1][2] * normal[0] - rotation[1][0] * normal[2],
541 rotation[1][0] * normal[1] - rotation[1][1] * normal[0]
542 }};
543
544 // These three form a matrix and are entered into each row
545 // ( b_x )
546 // ( b_y )
547 // ( b_z )
548
549 constexpr size_t S = 5;
550 std::array<std::array<V,S>, S> lq_matrix;
551 std::array<V,S> b_rhs;
552 for(size_t i = 0; i < S; ++i){
553 for(size_t j = 0; j < S; ++j){
554 lq_matrix[i][j] = 0.;
555 }
556 b_rhs[i] = 0.;
557 }
558 V origin_offset = 0.;
559 {
560 V fill_level = getClampedEpsilon(cell);
561 origin_offset = calculateCubeOffsetOpt<V,DESCRIPTOR>(fill_level, normal);
562 }
563
564 size_t healthy_interfaces = 0;
565 for(int iPop = 1; iPop < DESCRIPTOR::q; iPop++){
566 auto cellC = cell.neighbor(descriptors::c<DESCRIPTOR>(iPop));
567
568 if(!isCellType(cellC, FreeSurface::Type::Interface) || !hasNeighbour(cellC, FreeSurface::Type::Gas)){
569 continue;
570 }
571
572 ++healthy_interfaces;
573
574 V fill_level = getClampedEpsilon(cellC);
575
576 V cube_offset = calculateCubeOffsetOpt<V, DESCRIPTOR>(fill_level, normal);
577
578 int i = descriptors::c<DESCRIPTOR>(iPop)[0];
579 int j = descriptors::c<DESCRIPTOR>(iPop)[1];
580 int k = descriptors::c<DESCRIPTOR>(iPop)[2];
581
582 std::array<V,3> pos{static_cast<V>(i),static_cast<V>(j),static_cast<V>(k)};
583 std::array<V,3> r_pos{0.,0.,cube_offset - origin_offset};
584
585 for(size_t a = 0; a < DESCRIPTOR::d; ++a){
586 for(size_t b = 0; b < DESCRIPTOR::d; ++b){
587 r_pos[a] += rotation[a][b] * pos[b];
588 }
589 }
590
591 V r_x_2 = r_pos[0] * r_pos[0];
592 V r_x_3 = r_x_2 * r_pos[0];
593 V r_x_4 = r_x_3 * r_pos[0];
594
595 V r_y_2 = r_pos[1] * r_pos[1];
596 V r_y_3 = r_y_2 * r_pos[1];
597 V r_y_4 = r_y_3 * r_pos[1];
598
599 V r_x_2_y_2 = r_x_2 * r_y_2;
600 V r_x_3_y = r_x_3 * r_pos[1];
601 V r_x_2_y = r_x_2 * r_pos[1];
602
603 V r_x_y_3 = r_pos[0] * r_y_3;
604 V r_x_y_2 = r_pos[0] * r_y_2;
605
606 V r_x_y = r_pos[0] * r_pos[1];
607
608 lq_matrix[0][0] += r_x_4;
609 lq_matrix[1][1] += r_y_4;
610 lq_matrix[2][2] += r_x_2_y_2;
611 lq_matrix[3][3] += r_x_2;
612 lq_matrix[4][4] += r_y_2;
613
614 // skip [1][0] copy later from [2][2]
615 lq_matrix[2][0] += r_x_3_y;
616 lq_matrix[3][0] += r_x_3;
617 lq_matrix[4][0] += r_x_2_y;
618
619 lq_matrix[2][1] += r_x_y_3;
620 lq_matrix[3][1] += r_x_y_2;
621 lq_matrix[4][1] += r_y_3;
622
623 // skip [3][2] copy from [4][0]
624 // skip [4][2] copy from [3][1]
625
626 lq_matrix[4][3] += r_x_y;
627
628 b_rhs[0] += r_x_2 * r_pos[2];
629 b_rhs[1] += r_y_2 * r_pos[2];
630 b_rhs[2] += r_x_y * r_pos[2];
631 b_rhs[3] += r_pos[0] * r_pos[2];
632 b_rhs[4] += r_pos[1] * r_pos[2];
633 }
634
635 lq_matrix[1][0] = lq_matrix[2][2];
636 lq_matrix[3][2] = lq_matrix[4][0];
637 lq_matrix[4][2] = lq_matrix[3][1];
638
639 for(size_t i = 0; i < S; ++i){
640 for(size_t j = i + 1; j < S; ++j){
641 lq_matrix[i][j] = lq_matrix[j][i];
642 }
643 }
644
645 // Consider using Thikonov regularization?
646 //T alpha = 1e-8;
647 V alpha = 0.0;
648 for(size_t i = 0; i < S; ++i){
649 lq_matrix[i][i] += alpha;
650 }
651
652 std::array<V,S> solved_fit = FreeSurface::solvePivotedLU<V,S>(lq_matrix, b_rhs, healthy_interfaces);
653
654 V denom = std::sqrt(1. + solved_fit[3]*solved_fit[3] + solved_fit[4]*solved_fit[4]);
655 denom = denom * denom * denom;
656 V curvature = ( (1.+solved_fit[4]*solved_fit[4]) * solved_fit[0] + (1. + solved_fit[3]*solved_fit[3] ) * solved_fit[1] - solved_fit[3] * solved_fit[4] * solved_fit[2] ) / denom;
657
658 return util::max(-1., util::min(1., curvature));
659}

References Gas, Interface, olb::util::max(), olb::util::min(), olb::norm(), and olb::util::sqrt().

+ Here is the call graph for this function:

◆ computeInterfaceNormal()

template<typename CELL , typename V >
Vector< V, CELL::descriptor_t::d > olb::FreeSurface::computeInterfaceNormal ( CELL & cell)

Definition at line 224 of file freeSurfaceHelpers.hh.

224 {
226 normal[0] = 0.5 * ( getClampedEpsilon(cell.neighbor({-1, 0, 0}))
227 - getClampedEpsilon(cell.neighbor({ 1, 0, 0})));
228 normal[1] = 0.5 * ( getClampedEpsilon(cell.neighbor({ 0,-1, 0}))
229 - getClampedEpsilon(cell.neighbor({ 0, 1, 0})));
230 normal[2] = 0.5 * ( getClampedEpsilon(cell.neighbor({ 0, 0,-1}))
231 - getClampedEpsilon(cell.neighbor({ 0, 0, 1})));
232 return normal;
233}

◆ computeParkerYoungInterfaceNormal()

template<typename CELL , typename V >
Vector< V, CELL::descriptor_t::d > olb::FreeSurface::computeParkerYoungInterfaceNormal ( CELL & cell)

Definition at line 236 of file freeSurfaceHelpers.hh.

236 {
237 using DESCRIPTOR = typename CELL::descriptor_t;
238
240
241 for(size_t dim = 0; dim < CELL::descriptor_t::d; ++dim){
242 normal[dim] = 0;
243 }
244
245 for(int iPop = 1; iPop < DESCRIPTOR::q; iPop++) {
246 int omega_weight = 1;
247 if(descriptors::c<DESCRIPTOR>(iPop, 0) != 0){
248 omega_weight *= 2;
249 }
250 if(descriptors::c<DESCRIPTOR>(iPop, 1) != 0){
251 omega_weight *= 2;
252 }
253
254 // For the 3D case
255 if(CELL::descriptor_t::d == 3 && descriptors::c<DESCRIPTOR>(iPop)[2] != 0){
256 omega_weight *= 2;
257 }
258
259 omega_weight /= 2;
260
261 auto cellC = cell.neighbor(descriptors::c<DESCRIPTOR>(iPop));
262 V epsilon = getClampedEpsilon(cellC);
263
264 normal[0] -= omega_weight * (descriptors::c<DESCRIPTOR>(iPop, 0) * epsilon);
265 normal[1] -= omega_weight * (descriptors::c<DESCRIPTOR>(iPop, 1) * epsilon);
266 if(CELL::descriptor_t::d == 3){
267 normal[2] -= omega_weight * (descriptors::c<DESCRIPTOR>(iPop, 2) * epsilon);
268 }
269
270 }
271
272 return normal;
273}

◆ getClampedEpsilon()

template<typename CELL , typename V >
V olb::FreeSurface::getClampedEpsilon ( CELL & cell)

Definition at line 276 of file freeSurfaceHelpers.hh.

276 {
277
278 V epsilon = cell.template getField<FreeSurface::EPSILON>();
279 return util::max(0., util::min(1., epsilon));
280}

References olb::util::max(), and olb::util::min().

+ Here is the call graph for this function:

◆ getNeighbourInfo()

template<typename CELL >
NeighbourInfo olb::FreeSurface::getNeighbourInfo ( CELL & cell)

Definition at line 717 of file freeSurfaceHelpers.hh.

717 {
718 NeighbourInfo info{};
719 using DESCRIPTOR = typename CELL::descriptor_t;
720
721 for(int iPop = 1; iPop < DESCRIPTOR::q; ++iPop){
722 auto cellC = cell.neighbor(descriptors::c<DESCRIPTOR>(iPop));
723
724 if(isCellType(cellC, FreeSurface::Type::Gas)){
725 info.has_gas_neighbours = true;
726 }
727 else if(isCellType(cellC, FreeSurface::Type::Fluid)){
728 info.has_fluid_neighbours = true;
729 }
730 else if(isCellType(cellC, FreeSurface::Type::Interface)){
731 ++info.interface_neighbours;
732 }
733 }
734 return info;
735}

References Fluid, Gas, olb::FreeSurface::NeighbourInfo::has_gas_neighbours, and Interface.

◆ hasCellFlags()

template<typename CELL >
bool olb::FreeSurface::hasCellFlags ( CELL & cell,
const FreeSurface::Flags & flags )

Definition at line 192 of file freeSurfaceHelpers.hh.

192 {
193 return static_cast<bool>(cell.template getField<FreeSurface::CELL_FLAGS>() & flags);
194}

◆ hasNeighbour()

template<typename CELL >
bool olb::FreeSurface::hasNeighbour ( CELL & cell,
const FreeSurface::Type & type )

Definition at line 197 of file freeSurfaceHelpers.hh.

197 {
198 using DESCRIPTOR = typename CELL::descriptor_t;
199 for(int iPop = 1; iPop < DESCRIPTOR::q; ++iPop) {
200 auto cellC = cell.neighbor(descriptors::c<DESCRIPTOR>(iPop));
201 if(isCellType(cellC, type)) {
202 return true;
203 }
204 }
205
206 return false;
207}

◆ hasNeighbourFlags()

template<typename CELL >
bool olb::FreeSurface::hasNeighbourFlags ( CELL & cell,
const FreeSurface::Flags & flags )

Definition at line 211 of file freeSurfaceHelpers.hh.

211 {
212 using DESCRIPTOR = typename CELL::descriptor_t;
213 for(int iPop = 1; iPop < DESCRIPTOR::q; ++iPop) {
214 auto cellC = cell.neighbor(descriptors::c<DESCRIPTOR>(iPop));
215 if(hasCellFlags(cellC, flags)) {
216 return true;
217 }
218 }
219
220 return false;
221}

◆ initialize()

template<typename T , typename DESCRIPTOR >
void olb::FreeSurface::initialize ( SuperLattice< T, DESCRIPTOR > & lattice)

◆ isCellType()

template<typename CELL >
bool olb::FreeSurface::isCellType ( CELL & cell,
const FreeSurface::Type & type )

Definition at line 187 of file freeSurfaceHelpers.hh.

187 {
188 return cell.template getField<FreeSurface::CELL_TYPE>() == type;
189}

◆ isHealthyInterface()

template<typename CELL , typename V >
bool olb::FreeSurface::isHealthyInterface ( CELL & cell)

Definition at line 738 of file freeSurfaceHelpers.hh.

738 {
739 bool has_fluid_neighbours = false;
740 bool has_gas_neighbours = false;
741
742 if(!isCellType(cell, FreeSurface::Type::Interface)){
743 return false;
744 }
745
746 using DESCRIPTOR = typename CELL::descriptor_t;
747 for(int iPop = 1; iPop < DESCRIPTOR::q; ++iPop){
748 auto cellC = cell.neighbor(descriptors::c<DESCRIPTOR>(iPop));
749 if(isCellType(cellC, FreeSurface::Type::Gas)){
750 has_gas_neighbours = true;
751 if(has_fluid_neighbours){
752 return true;
753 }
754 }
755 else if(isCellType(cellC, FreeSurface::Type::Fluid)){
756 has_fluid_neighbours = true;
757 if(has_gas_neighbours){
758 return true;
759 }
760 }
761 }
762 return false;
763}

References Fluid, Gas, and Interface.

◆ offsetHelper() [1/2]

template<typename T , typename DESCRIPTOR >
std::enable_if_t< DESCRIPTOR::d==2, T > olb::FreeSurface::offsetHelper ( T volume,
const Vector< T, DESCRIPTOR::d > & sorted_normal )

Definition at line 30 of file freeSurfaceHelpers.hh.

30 {
31 T d2 = volume * sorted_normal[1] + 0.5 * sorted_normal[0];
32 if(d2 >= sorted_normal[0]){
33 return d2;
34 }
35
36 T d1 = util::sqrt(2. * sorted_normal[0] * sorted_normal[1] * volume);
37
38 return d1;
39}

References olb::util::sqrt().

+ Here is the call graph for this function:

◆ offsetHelper() [2/2]

template<typename T , typename DESCRIPTOR >
std::enable_if_t< DESCRIPTOR::d==3, T > olb::FreeSurface::offsetHelper ( T volume,
const Vector< T, DESCRIPTOR::d > & sorted_normal )

Definition at line 45 of file freeSurfaceHelpers.hh.

45 {
46 T sn0_plus_sn1 = sorted_normal[0] + sorted_normal[1];
47 T sn0_times_sn1 = sorted_normal[0] * sorted_normal[1];
48 T sn2_volume = sorted_normal[2] * volume;
49
50 T min_sn0_plus_sn1_and_sn2 = util::min(sn0_plus_sn1, sorted_normal[2]);
51
52 T d5 = sn2_volume + 0.5 * sn0_plus_sn1;
53 if(d5 > min_sn0_plus_sn1_and_sn2 && d5 <= sorted_normal[2]){
54 return d5;
55 }
56
57 T d2 = 0.5 * sorted_normal[0] + 0.28867513 * util::sqrt( util::max(0., 24. * sorted_normal[1] * sn2_volume - sorted_normal[0]*sorted_normal[0]) );
58
59 if(d2 > sorted_normal[0] && d2 <= sorted_normal[1]){
60 return d2;
61 }
62
63 T d1 = std::cbrt(6.0 * sn0_times_sn1 * sn2_volume);
64 if(d1 <= sorted_normal[0]){
65 return d1;
66 }
67
68 T x3 = 81.0 * sn0_times_sn1 * (sn0_plus_sn1 - 2. * sn2_volume);
69 T y3 = util::sqrt(util::max(0., 23328. * sn0_times_sn1*sn0_times_sn1*sn0_times_sn1 - x3*x3 ));
70 T u3 = std::cbrt(x3*x3 + y3*y3);
71 T d3 = sn0_plus_sn1 - (7.5595264 * sn0_times_sn1 + 0.26456684 * u3) * (1./util::sqrt(u3)) * util::sin(0.5235988 - 0.3333334 * util::atan(y3 / x3));
72 if(d3 > sorted_normal[1] && d3 <= min_sn0_plus_sn1_and_sn2){
73 return d3;
74 }
75
76 T t4 = 9. * util::pow(sn0_plus_sn1 + sorted_normal[2], 2) - 18.;
77 T x4 = util::max(sn0_times_sn1 * sorted_normal[2] * (324. - 648. * volume), 1.1754944e-38);
78 T y4 = util::sqrt(util::max(4. * t4*t4*t4 - x4*x4, 0.));
79 T u4 = std::cbrt(x4*x4 + y4*y4);
80 T d4 = 0.5 * (sn0_plus_sn1 + sorted_normal[2]) - (0.20998684 * t4 + 0.13228342 * u4) * (1./util::sqrt(u4)) * util::sin(0.5235988- 0.3333334 * util::atan(y4/x4));
81
82 return d4;
83}

References olb::util::atan(), olb::util::max(), olb::util::min(), olb::util::pow(), olb::util::sin(), and olb::util::sqrt().

+ Here is the call graph for this function:

◆ offsetHelperOpt()

template<typename T , typename DESCRIPTOR >
T olb::FreeSurface::offsetHelperOpt ( T vol,
const Vector< T, DESCRIPTOR::d > & sn )

Definition at line 87 of file freeSurfaceHelpers.hh.

87 {
88 const T sn0_p_sn1 = sn[0] + sn[1];
89 const T sn2_t_V = sn[2] * vol;
90
91 if(sn0_p_sn1 <= 2. * sn2_t_V){
92 return sn2_t_V + 0.5 * sn0_p_sn1;
93 }
94
95 const T sq_sn0 = util::pow(sn[0],2), sn1_6 = 6. * sn[1], v1 = sq_sn0 / sn1_6;
96
97 if(v1 <= sn2_t_V && sn2_t_V < v1 + 0.5 * (sn[1]-sn[0])){
98 return 0.5 *(sn[0] + util::sqrt(sq_sn0 + 8.0 * sn[1] * (sn2_t_V - v1)));
99 }
100
101 const T v6 = sn[0] * sn1_6 * sn2_t_V;
102 if(sn2_t_V < v1){
103 return std::cbrt(v6);
104 }
105
106 const T v3 = sn[2] < sn0_p_sn1 ? (util::pow(sn[2],2) * (3. * sn0_p_sn1 - sn[2]) + sq_sn0 *(sn[0] - 3.0 * sn[2]) + util::pow(sn[1],2)*(sn[1]-3.0 * sn[2])) / (sn[0] * sn1_6) : 0.5 * sn0_p_sn1;
107
108 const T sq_sn0_sq_sn1 = sq_sn0 + util::pow(sn[1],2), v6_cb_sn0_sn1 = v6 - util::pow(sn[0],3) - util::pow(sn[1],3);
109
110 const bool case34 = sn2_t_V < v3;
111 const T a = case34 ? v6_cb_sn0_sn1 : 0.5 * (v6_cb_sn0_sn1 - util::pow(sn[2], 3));
112 const T b = case34 ? sq_sn0_sq_sn1 : 0.5 * (sq_sn0_sq_sn1 + util::pow(sn[2], 2));
113 const T c = case34 ? sn0_p_sn1 : 0.5;
114 const T t = util::sqrt(util::pow(c,2) - b);
115 return c - 2.0 * t * util::sin(0.33333334 * util::asin((util::pow(c,3) - 0.5 * a - 1.5 * b * c) / util::pow(t,3)));
116}
platform_constant Fraction t[Q]
platform_constant int c[Q][D]

References olb::util::asin(), olb::util::pow(), olb::util::sin(), and olb::util::sqrt().

+ Here is the call graph for this function:

◆ plicInverse()

template<typename T , typename DESCRIPTOR >
T olb::FreeSurface::plicInverse ( T d_o,
const Vector< T, DESCRIPTOR::d > & normal )

Definition at line 662 of file freeSurfaceHelpers.hh.

662 {
663
664 Vector<T,DESCRIPTOR::d> abs_normal;
665 for(int i = 0; i < DESCRIPTOR::d; i++){
666 abs_normal[i] = util::abs(normal[i]);
667 }
668
669 //const T n1 = std::min_element(abs_normal.begin(), abs_normal.end());
670 //const T n2 = std::max_element(abs_normal.begin(), abs_normal.end());
671
672 const T n1 = abs_normal[0];
673 const T n2 = abs_normal[1];
674
675 for(int i = 0; i < DESCRIPTOR::d; i++){
676 if(abs_normal[i] < n1){
677 n1 = abs_normal[i];
678 }
679
680 if(abs_normal[i] > n2){
681 n2 = abs_normal[i];
682 }
683 }
684
685 T abs_normal_acc = 0;
686 for(int i = 0; i < DESCRIPTOR::d; i++){
687 abs_normal_acc += abs_normal[i];
688 }
689 const T n3 = abs_normal_acc - n1 - n2;
690 const T d = 0.5 * (n1+n2+n3) - util::abs(d_o);
691 T vol;
692
693 if(DESCRIPTOR::d == 2){
694 if(d < n1){
695 vol = d * d / (2. * n1 * n2);
696 } else if(d >= n1){
697 vol = d / n2 - n1 / (2. * n2);
698 }
699 }
700
701 if(DESCRIPTOR::d == 3){
702 if(util::min(n1+n3,n2) <= d && d <= n2){
703 vol = (d-0.5 *(n1+n3))/n2;
704 } else if(d < n1){
705 vol = util::pow(d,3) / (6. * n1 * n2 * n3);
706 } else if(d <= n3){
707 vol = (3.0 * d * (d-n1) + std::pow(n1,2))/(6. * n2 * n3);
708 } else {
709 vol = (util::pow(d,3) - util::pow(d-n1,3) - util::pow(d-n3,3) - util::pow(util::max(0., d-n2),3)) / (6. * n1* n2 * n3);
710 }
711 }
712
713 return std::copysign(0.5 - vol, d_o) + 0.5;
714}

References olb::util::abs(), olb::util::max(), olb::util::min(), and olb::util::pow().

+ Here is the call graph for this function:

◆ setCellFlags()

template<typename CELL , typename V >
void olb::FreeSurface::setCellFlags ( CELL & cell,
const FreeSurface::Flags & flags )

Definition at line 771 of file freeSurfaceHelpers.hh.

771 {
772 cell.template setField<FreeSurface::CELL_FLAGS>(flags);
773}

◆ setCellType()

template<typename CELL , typename V >
void olb::FreeSurface::setCellType ( CELL & cell,
const FreeSurface::Type & type )

Definition at line 766 of file freeSurfaceHelpers.hh.

766 {
767 cell.template setField<FreeSurface::CELL_TYPE>(type);
768}

◆ solvePivotedLU()

template<typename T , size_t S>
std::array< T, S > olb::FreeSurface::solvePivotedLU ( std::array< std::array< T, S >, S > & matrix,
const std::array< T, S > & b,
size_t N )

Definition at line 119 of file freeSurfaceHelpers.hh.

119 {
120 std::array<T,S> x;
121 std::array<T,S> pivots;
122 for(size_t i = 0; i < S; ++i){
123 pivots[i] = i;
124 x[i] = 0.;
125 }
126
127 N = std::min(N,S);
128
129 for(size_t i = 0; i < N; ++i){
130
131 T max = 0.;
132 size_t max_index = i;
133
134 for(size_t j = i; j < N; ++j){
135 T abs = std::abs(matrix[pivots[j]][i]);
136 if(abs > max){
137 max_index = j;
138 max = abs;
139 }
140 }
141
142 if(max_index != i){
143 size_t tmp_index = pivots[i];
144 pivots[i] = pivots[max_index];
145 pivots[max_index] = tmp_index;
146 }
147
148 for(size_t j = i + 1; j < N; ++j){
149 matrix[pivots[j]][i] /= matrix[pivots[i]][i];
150
151 for(size_t k = i + 1; k < N; ++k){
152
153 matrix[pivots[j]][k] -= matrix[pivots[j]][i] * matrix[pivots[i]][k];
154 }
155 }
156 }
157
158 for(size_t i = 0; i < N; ++i){
159 x[i] = b[pivots[i]];
160
161 for(size_t j = 0; j < i; ++j){
162 x[i] -= matrix[pivots[i]][j] * x[j];
163 }
164 }
165
166 for(size_t i = N; i > 0; --i){
167 for(size_t j = i; j < N; ++j){
168 x[i-1] -= matrix[pivots[i-1]][j] * x[j];
169 }
170
171 x[i-1] /= matrix[pivots[i-1]][i-1];
172 }
173
174 return x;
175}
std::enable_if_t< std::is_arithmetic< T >::type::value, T > abs(T x)
Definition util.h:396

References olb::abs().

+ Here is the call graph for this function: