From cc6ee8e8867177ef70895711a121b4ccc864132a Mon Sep 17 00:00:00 2001 From: Jannick Wolters Date: Mon, 22 Feb 2021 12:51:43 +0100 Subject: [PATCH 01/67] fixed elastic cross section computation Former-commit-id: 3e7dd30a0dad940f275cffe1423a148137cfe325 --- code/src/problems/icru.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/code/src/problems/icru.cpp b/code/src/problems/icru.cpp index 3466bab..17bc9ee 100644 --- a/code/src/problems/icru.cpp +++ b/code/src/problems/icru.cpp @@ -404,8 +404,8 @@ void ICRU::SPLINE( const std::vector& X, if( N < 4 ) { ErrorMessages::Error( "Too few points", CURRENT_FUNCTION ); } - unsigned N1 = N - 2; - unsigned N2 = N - 3; + unsigned N1 = N - 1; + unsigned N2 = N - 2; A.resize( N ); B.resize( N ); @@ -423,21 +423,21 @@ void ICRU::SPLINE( const std::vector& X, for( unsigned I = 0; I < N2; ++I ) { B[I] = 2.0e0 * ( A[I] + A[I + 1] ); - unsigned K = N1 - I; + unsigned K = N1 - I - 1; D[K] = 6.0e0 * ( D[K] - D[K - 1] ); } D[1] -= A[0] * S1; - D[N1] = D[N1] - A[N1] * SN; + D[N1 - 1] -= A[N1 - 1] * SN; - for( unsigned I = 1; I < N2 + 1; ++I ) { + for( unsigned I = 1; I < N2; ++I ) { double R = A[I] / B[I - 1]; B[I] -= R * A[I]; D[I + 1] -= R * D[I]; } - D[N1] = D[N1] / B[N2]; + D[N1 - 1] /= B[N2 - 1]; for( unsigned I = 1; I < N2; ++I ) { - unsigned K = N1 - I; + unsigned K = N1 - I - 1; D[K] = ( D[K] - A[K] * D[K + 1] ) / B[K - 1]; } D[N - 1] = SN; @@ -473,7 +473,7 @@ void ICRU::FINDI( std::vector X, double XC, unsigned N, unsigned& I ) { return; } I = 0; - unsigned I1 = N; + unsigned I1 = N - 1; while( I1 - I > 1 ) { double IT = ( I + I1 ) / 2; if( XC > X[IT] ) -- GitLab From 92f2614cca6bbb9cc7a3f6e1704202ab15b2bd80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Tue, 23 Feb 2021 09:43:38 +0100 Subject: [PATCH 02/67] re-added sphericalBasisTest Former-commit-id: 9e0455b723847f4e7affc6d11ea1250dcb12807c --- code/ext/neuralEntropy | 2 +- code/input/DataGenerator.cfg | 4 +- code/src/toolboxes/sphericalmonomials.cpp | 7 +- code/tests/test_sphericalBasis.cpp | 382 ++++++++++++++++++++++ 4 files changed, 388 insertions(+), 7 deletions(-) create mode 100644 code/tests/test_sphericalBasis.cpp diff --git a/code/ext/neuralEntropy b/code/ext/neuralEntropy index e1eab3b..c17aef3 160000 --- a/code/ext/neuralEntropy +++ b/code/ext/neuralEntropy @@ -1 +1 @@ -Subproject commit e1eab3b76738638e7db7a5f2bd62e72c923c717a +Subproject commit c17aef38149a57d92781c91643375fd891d2a4cb diff --git a/code/input/DataGenerator.cfg b/code/input/DataGenerator.cfg index d795d33..2ffd940 100644 --- a/code/input/DataGenerator.cfg +++ b/code/input/DataGenerator.cfg @@ -37,9 +37,9 @@ ENTROPY_OPTIMIZER = NEWTON % NEWTON_FAST_MODE = NO NEWTON_ITER = 1000000 -NEWTON_EPSILON = 0.01 +NEWTON_EPSILON = 0.0001 NEWTON_STEP_SIZE = 0.7 -NEWTON_LINE_SEARCH_ITER = 1000 +NEWTON_LINE_SEARCH_ITER = 100000 % % ----- Quadrature ---- % diff --git a/code/src/toolboxes/sphericalmonomials.cpp b/code/src/toolboxes/sphericalmonomials.cpp index 25c3847..a50a8a9 100644 --- a/code/src/toolboxes/sphericalmonomials.cpp +++ b/code/src/toolboxes/sphericalmonomials.cpp @@ -66,15 +66,14 @@ Vector SphericalMonomials::ComputeSphericalBasis2D( double my, double phi ) { Vector SphericalMonomials::ComputeSphericalBasis3D( double my, double phi ) { unsigned idx_vector = 0; - double omega_X, omega_Y, omega_Z; unsigned a, b, c; + double omega_X = Omega_x( my, phi ); + double omega_Y = Omega_y( my, phi ); + double omega_Z = Omega_z( my ); // go over all degrees of polynomials for( unsigned idx_degree = 0; idx_degree <= _LMaxDegree; idx_degree++ ) { // elem = Omega_x^a+ Omega_y^b +Omega_z^c : a+b+c = idx_degree - omega_X = Omega_x( my, phi ); - omega_Y = Omega_y( my, phi ); - omega_Z = Omega_z( my ); for( a = 0; a <= idx_degree; a++ ) { for( b = 0; b <= idx_degree - a; b++ ) { c = idx_degree - a - b; // c uniquely defined diff --git a/code/tests/test_sphericalBasis.cpp b/code/tests/test_sphericalBasis.cpp new file mode 100644 index 0000000..7aec172 --- /dev/null +++ b/code/tests/test_sphericalBasis.cpp @@ -0,0 +1,382 @@ +#include "catch.hpp" +#include "common/config.h" +#include "quadratures/qgausslegendretensorized.h" +#include "toolboxes/sphericalharmonics.h" +#include "toolboxes/sphericalmonomials.h" + +#include +#include +#include + +double Y0_0( double, double ) { return sqrt( 1 / ( 4 * M_PI ) ); } + +double Y1_m1( double my, double phi ) { return -sqrt( 3 / ( 4 * M_PI ) ) * sqrt( 1 - my * my ) * sin( phi ); } +double Y1_0( double my, double /*phi*/ ) { return sqrt( 3 / ( 4 * M_PI ) ) * my; } +double Y1_1( double my, double phi ) { return -sqrt( 3 / ( 4 * M_PI ) ) * sqrt( 1 - my * my ) * cos( phi ); } + +double Y2_m2( double my, double phi ) { return sqrt( 15 / ( 16 * M_PI ) ) * ( 1 - my * my ) * sin( 2 * phi ); } +double Y2_m1( double my, double phi ) { return -1 * sqrt( 15 / ( 4 * M_PI ) ) * my * sqrt( 1 - my * my ) * sin( phi ); } +double Y2_0( double my, double /*phi*/ ) { return sqrt( 5 / ( 16 * M_PI ) ) * ( 3 * my * my - 1 ); } +double Y2_1( double my, double phi ) { return -1 * sqrt( 15 / ( 4 * M_PI ) ) * my * sqrt( 1 - my * my ) * cos( phi ); } +double Y2_2( double my, double phi ) { return sqrt( 15 / ( 16 * M_PI ) ) * ( 1 - my * my ) * cos( 2 * phi ); } + +double P0_0( double /*my*/ ) { return sqrt( 1 / ( 2 * M_PI ) ); } +double P1_0( double my ) { return sqrt( 3 / ( 2 * M_PI ) ) * my; } +double P1_1( double my ) { return -sqrt( 3 / ( 4 * M_PI ) ) * sqrt( 1 - my * my ); } + +double P2_0( double my ) { return sqrt( 5 / ( 8 * M_PI ) ) * ( 3 * my * my - 1 ); } +double P2_1( double my ) { return -1 * sqrt( 15 / ( 4 * M_PI ) ) * my * sqrt( 1 - my * my ); } +double P2_2( double my ) { return sqrt( 15 / ( 16 * M_PI ) ) * ( 1 - my * my ); } + +TEST_CASE( "test spherical harmonics basis ", "[spherical_harmonics]" ) { + + std::string filename = std::string( TESTS_PATH ) + "input/unit_tests/solvers/unit_harmonics.cfg"; + + // Load Settings from File + Config* config = new Config( filename ); + + unsigned maxMomentDegree = 2; + + SphericalHarmonics testBase( maxMomentDegree ); + + SECTION( "Test Global Indexing" ) { + bool indexingRight = true; + if( testBase.GetGlobalIndexBasis( 0, 0 ) != 0 ) indexingRight = false; + if( testBase.GetGlobalIndexBasis( 1, -1 ) != 1 ) indexingRight = false; + if( testBase.GetGlobalIndexBasis( 1, 0 ) != 2 ) indexingRight = false; + if( testBase.GetGlobalIndexBasis( 1, 1 ) != 3 ) indexingRight = false; + if( testBase.GetGlobalIndexBasis( 2, -2 ) != 4 ) indexingRight = false; + if( testBase.GetGlobalIndexBasis( 2, -1 ) != 5 ) indexingRight = false; + if( testBase.GetGlobalIndexBasis( 2, 0 ) != 6 ) indexingRight = false; + if( testBase.GetGlobalIndexBasis( 2, 1 ) != 7 ) indexingRight = false; + if( testBase.GetGlobalIndexBasis( 2, 2 ) != 8 ) indexingRight = false; + + REQUIRE( indexingRight ); + } + + SECTION( "Test against analytical solution" ) { + std::vector legendre; + Vector moment; + std::vector validLegendrePoly( 6, true ); + std::vector validMoment( 9, true ); + for( double my = -1.0; my < 1.0; my += 0.1 ) { + + legendre = testBase.GetAssLegendrePoly( my ); + + if( std::fabs( legendre[0] - P0_0( my ) ) > 1e2 * std::numeric_limits::epsilon() ) validLegendrePoly[0] = false; + if( std::fabs( legendre[1] - P1_0( my ) ) > 1e2 * std::numeric_limits::epsilon() ) validLegendrePoly[1] = false; + if( std::fabs( legendre[2] - P1_1( my ) ) > 1e2 * std::numeric_limits::epsilon() ) validLegendrePoly[2] = false; + if( std::fabs( legendre[3] - P2_0( my ) ) > 1e2 * std::numeric_limits::epsilon() ) validLegendrePoly[3] = false; + if( std::fabs( legendre[4] - P2_1( my ) ) > 1e2 * std::numeric_limits::epsilon() ) validLegendrePoly[4] = false; + if( std::fabs( legendre[5] - P2_2( my ) ) > 1e2 * std::numeric_limits::epsilon() ) validLegendrePoly[5] = false; + + for( double phi = 0.0; phi < 2 * M_PI; phi += 0.1 ) { + moment = testBase.ComputeSphericalBasis( my, phi ); + + if( std::fabs( moment[0] - Y0_0( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[0] = false; + if( std::fabs( moment[1] - Y1_m1( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[1] = false; + if( std::fabs( moment[2] - Y1_0( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[2] = false; + if( std::fabs( moment[3] - Y1_1( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[3] = false; + if( std::fabs( moment[4] - Y2_m2( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[4] = false; + if( std::fabs( moment[5] - Y2_m1( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[5] = false; + if( std::fabs( moment[6] - Y2_0( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[6] = false; + if( std::fabs( moment[7] - Y2_1( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[7] = false; + if( std::fabs( moment[8] - Y2_2( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[8] = false; + } + } + REQUIRE( std::all_of( validLegendrePoly.begin(), validLegendrePoly.end(), []( bool v ) { return v; } ) ); + REQUIRE( std::all_of( validMoment.begin(), validMoment.end(), []( bool v ) { return v; } ) ); + } + + // Remove title line + + SECTION( "test to reference solution" ) { + + std::string text_line; + std::ifstream case_file; + + double my = 0.0; + double phi = 0.0; + + Vector values( 9, 0.0 ); + Vector result( 4, 0.0 ); + + case_file.open( "unit_test/solvers/harmonicBasis_reference.csv", std::ios::in ); + + getline( case_file, text_line ); + + bool errorWithinBounds = true; + while( getline( case_file, text_line ) ) { + + // give line to stringstream + std::stringstream ss( text_line ); + + // Read values + ss >> my >> phi >> values[0] >> values[1] >> values[2] >> values[3] >> values[4] >> values[5] >> values[6] >> values[7] >> values[8]; + + result = testBase.ComputeSphericalBasis( my, phi ); + + for( unsigned idx = 0; idx < 9; idx++ ) { + if( std::fabs( result[idx] - values[idx] ) > 1e2 * std::numeric_limits::epsilon() ) errorWithinBounds = false; + } + } + REQUIRE( errorWithinBounds ); + case_file.close(); + } + + SECTION( "test orthonormality - spherical coordinates" ) { + // Caution: Integration only works with spherical coordinates! + + QGaussLegendreTensorized quad( config ); + + double my, phi, w; + Vector moment = testBase.ComputeSphericalBasis( 0, 1, 0 ); + // 9 basis moments if degree = 2 + + Matrix results( moment.size(), moment.size(), 0.0 ); + + for( unsigned idx_quad = 0; idx_quad < quad.GetNq(); idx_quad++ ) { + my = quad.GetPointsSphere()[idx_quad][0]; + phi = quad.GetPointsSphere()[idx_quad][1]; + // z = quad.GetPoints()[idx_quad][2]; + w = quad.GetWeights()[idx_quad]; + moment = testBase.ComputeSphericalBasis( my, phi ); + + for( unsigned idx_row = 0; idx_row < 9; idx_row++ ) { + for( unsigned idx_col = 0; idx_col < 9; idx_col++ ) { + results( idx_row, idx_col ) += w * moment[idx_row] * moment[idx_col]; + } + } + } + + bool errorWithinBounds = true; + bool orthogonality = true; + for( unsigned idx_row = 0; idx_row < 9; idx_row++ ) { + for( unsigned idx_col = 0; idx_col < 9; idx_col++ ) { + if( idx_row == idx_col ) { + // Orthogonality + if( std::fabs( results( idx_row, idx_col ) - 1.0 ) > 1e2 * std::numeric_limits::epsilon() ) orthogonality = false; + } + else { + // Normality + if( std::fabs( results( idx_row, idx_col ) ) > 1e2 * std::numeric_limits::epsilon() ) errorWithinBounds = false; + } + } + } + REQUIRE( errorWithinBounds ); + REQUIRE( orthogonality ); + } + + SECTION( "test parity - carthesian coordinates" ) { + + Vector moment1 = testBase.ComputeSphericalBasis( 0, 0 ); + Vector moment2 = testBase.ComputeSphericalBasis( 0, 0 ); + + // Parity in carthesian coordinates + QGaussLegendreTensorized quad( config ); + + double x, y, z; + + bool errorWithinBounds = true; + for( unsigned idx_quad = 0; idx_quad < quad.GetNq(); idx_quad++ ) { + x = quad.GetPoints()[idx_quad][0]; + y = quad.GetPoints()[idx_quad][1]; + z = quad.GetPoints()[idx_quad][2]; + moment1 = testBase.ComputeSphericalBasis( x, y, z ); + moment2 = testBase.ComputeSphericalBasis( -x, -y, -z ); + + unsigned idx_sys; + double result = 0.; + + for( int l_idx = 0; l_idx <= int( maxMomentDegree ); l_idx++ ) { + for( int k_idx = -l_idx; k_idx <= l_idx; k_idx++ ) { + idx_sys = testBase.GetGlobalIndexBasis( l_idx, k_idx ); + + if( l_idx % 2 == 0 ) + result = moment2[idx_sys] - moment1[idx_sys]; + else + result = moment2[idx_sys] + moment1[idx_sys]; + + if( std::fabs( result ) > 1e2 * std::numeric_limits::epsilon() ) errorWithinBounds = false; + } + } + } + REQUIRE( errorWithinBounds ); + } + + SECTION( "test parity - polar coordinates" ) { + + Vector moment1 = testBase.ComputeSphericalBasis( 0, 0 ); + Vector moment2 = testBase.ComputeSphericalBasis( 0, 0 ); + + unsigned idx_sys; + double result = 0.; + + // // test in polar coordinates + bool errorWithinBounds = true; + for( double my = -1.0; my < 1.0; my += 0.1 ) { + for( double phi = 0.0; phi < 2 * M_PI; phi += 0.1 ) { + moment2 = testBase.ComputeSphericalBasis( my, phi ); + moment1 = testBase.ComputeSphericalBasis( -my, M_PI + phi ); + + for( int l_idx = 0; l_idx <= int( maxMomentDegree ); l_idx++ ) { + for( int k_idx = -l_idx; k_idx <= l_idx; k_idx++ ) { + idx_sys = testBase.GetGlobalIndexBasis( l_idx, k_idx ); + + if( l_idx % 2 == 0 ) + result = moment2[idx_sys] - moment1[idx_sys]; + else + result = moment2[idx_sys] + moment1[idx_sys]; + + if( std::fabs( result ) > 1e2 * std::numeric_limits::epsilon() ) errorWithinBounds = false; + } + } + } + } + REQUIRE( errorWithinBounds ); + } +} + +double Omega_xBase( double my, double phi ) { return sqrt( 1 - my * my ) * sin( phi ); } +double Omega_yBase( double my, double phi ) { return sqrt( 1 - my * my ) * cos( phi ); } +double Omega_zBase( double my ) { return my; } + +double SphericalMonomial_0( double /* my */, double /* phi */ ) { return 1; } +double SphericalMonomial_1( double my, double /*phi*/ ) { return Omega_zBase( my ); } // omega_z +double SphericalMonomial_2( double my, double phi ) { return Omega_yBase( my, phi ); } // omega_y +double SphericalMonomial_3( double my, double phi ) { return Omega_xBase( my, phi ); } // omega_x +double SphericalMonomial_4( double my, double /*phi*/ ) { return Omega_zBase( my ) * Omega_zBase( my ); } // omega_z^2 +double SphericalMonomial_5( double my, double phi ) { return Omega_yBase( my, phi ) * Omega_zBase( my ); } // omega_y*omega_z +double SphericalMonomial_6( double my, double phi ) { return Omega_yBase( my, phi ) * Omega_yBase( my, phi ); } // omega_y^2 +double SphericalMonomial_7( double my, double phi ) { return Omega_xBase( my, phi ) * Omega_zBase( my ); } // omega_x*omega_z +double SphericalMonomial_8( double my, double phi ) { return Omega_xBase( my, phi ) * Omega_yBase( my, phi ); } // omega_x*omega_y +double SphericalMonomial_9( double my, double phi ) { return Omega_xBase( my, phi ) * Omega_xBase( my, phi ); } // omega_x^2 + +TEST_CASE( "test spherical monomial basis", "[spherical_monomials]" ) { + unsigned maxMomentDegree = 2; //==> 6+3+1 basis functions + SphericalMonomials testBase( maxMomentDegree ); // Default constructor => _spatialDim = 3 + + SECTION( "Test Global Indexing Dim 3" ) { + + bool currDimRight = true; + if( testBase.GetCurrDegreeSize( 0 ) != 1 ) currDimRight = false; + if( testBase.GetCurrDegreeSize( 1 ) != 3 ) currDimRight = false; + if( testBase.GetCurrDegreeSize( 2 ) != 6 ) currDimRight = false; + + REQUIRE( currDimRight ); + + bool indexingRight = true; + if( testBase.GetGlobalIndexBasis( 0, 0 ) != 0 ) indexingRight = false; + if( testBase.GetGlobalIndexBasis( 1, 0 ) != 1 ) indexingRight = false; + if( testBase.GetGlobalIndexBasis( 1, 1 ) != 2 ) indexingRight = false; + if( testBase.GetGlobalIndexBasis( 1, 2 ) != 3 ) indexingRight = false; + if( testBase.GetGlobalIndexBasis( 2, 0 ) != 4 ) indexingRight = false; + if( testBase.GetGlobalIndexBasis( 2, 1 ) != 5 ) indexingRight = false; + if( testBase.GetGlobalIndexBasis( 2, 2 ) != 6 ) indexingRight = false; + if( testBase.GetGlobalIndexBasis( 2, 3 ) != 7 ) indexingRight = false; + if( testBase.GetGlobalIndexBasis( 2, 4 ) != 8 ) indexingRight = false; + if( testBase.GetGlobalIndexBasis( 2, 5 ) != 9 ) indexingRight = false; + + REQUIRE( indexingRight ); + } + + SECTION( "Test against analytical solution Dim 3" ) { + Vector moment; + std::vector validMoment( 10, true ); + for( double my = -1.0; my < 1.0; my += 0.1 ) { + + for( double phi = 0.0; phi < 2 * M_PI; phi += 0.1 ) { + moment = testBase.ComputeSphericalBasis( my, phi ); + + if( std::fabs( moment[0] - SphericalMonomial_0( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[0] = false; + if( std::fabs( moment[1] - SphericalMonomial_1( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[1] = false; + if( std::fabs( moment[2] - SphericalMonomial_2( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[2] = false; + if( std::fabs( moment[3] - SphericalMonomial_3( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[3] = false; + if( std::fabs( moment[4] - SphericalMonomial_4( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[4] = false; + if( std::fabs( moment[5] - SphericalMonomial_5( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[5] = false; + if( std::fabs( moment[6] - SphericalMonomial_6( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[6] = false; + if( std::fabs( moment[7] - SphericalMonomial_7( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[7] = false; + if( std::fabs( moment[8] - SphericalMonomial_8( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[8] = false; + if( std::fabs( moment[9] - SphericalMonomial_9( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[8] = false; + } + } + REQUIRE( std::all_of( validMoment.begin(), validMoment.end(), []( bool v ) { return v; } ) ); + } + + SphericalMonomials testBase2D( maxMomentDegree, 2 ); + + SECTION( "Test Global Indexing Dim 2" ) { + + bool currDimRight = true; + if( testBase2D.GetCurrDegreeSize( 0 ) != 1 ) currDimRight = false; + if( testBase2D.GetCurrDegreeSize( 1 ) != 2 ) currDimRight = false; + if( testBase2D.GetCurrDegreeSize( 2 ) != 3 ) currDimRight = false; + + REQUIRE( currDimRight ); + + bool indexingRight = true; + if( testBase2D.GetGlobalIndexBasis( 0, 0 ) != 0 ) indexingRight = false; + if( testBase2D.GetGlobalIndexBasis( 1, 0 ) != 1 ) indexingRight = false; + if( testBase2D.GetGlobalIndexBasis( 1, 1 ) != 2 ) indexingRight = false; + if( testBase2D.GetGlobalIndexBasis( 2, 0 ) != 3 ) indexingRight = false; + if( testBase2D.GetGlobalIndexBasis( 2, 1 ) != 4 ) indexingRight = false; + if( testBase2D.GetGlobalIndexBasis( 2, 2 ) != 5 ) indexingRight = false; + + REQUIRE( indexingRight ); + } + + SECTION( "Test against analytical solution Dim 2" ) { + Vector moment; + std::vector validMoment( 6, true ); + for( double my = -1.0; my < 1.0; my += 0.1 ) { + + for( double phi = 0.0; phi < 2 * M_PI; phi += 0.1 ) { + moment = testBase2D.ComputeSphericalBasis( my, phi ); + + if( std::fabs( moment[0] - SphericalMonomial_0( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[0] = false; + if( std::fabs( moment[1] - SphericalMonomial_2( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[1] = false; + if( std::fabs( moment[2] - SphericalMonomial_3( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[2] = false; + if( std::fabs( moment[3] - SphericalMonomial_6( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[3] = false; + if( std::fabs( moment[4] - SphericalMonomial_8( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[4] = false; + if( std::fabs( moment[5] - SphericalMonomial_9( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[5] = false; + } + } + REQUIRE( std::all_of( validMoment.begin(), validMoment.end(), []( bool v ) { return v; } ) ); + } + + SphericalMonomials testBase1D( maxMomentDegree, 1 ); + + SECTION( "Test Global Indexing Dim 1" ) { + + bool currDimRight = true; + if( testBase1D.GetCurrDegreeSize( 0 ) != 1 ) currDimRight = false; + if( testBase1D.GetCurrDegreeSize( 1 ) != 1 ) currDimRight = false; + if( testBase1D.GetCurrDegreeSize( 2 ) != 1 ) currDimRight = false; + + REQUIRE( currDimRight ); + + bool indexingRight = true; + if( testBase1D.GetGlobalIndexBasis( 0, 0 ) != 0 ) indexingRight = false; + if( testBase1D.GetGlobalIndexBasis( 1, 0 ) != 1 ) indexingRight = false; + if( testBase1D.GetGlobalIndexBasis( 2, 0 ) != 2 ) indexingRight = false; + + REQUIRE( indexingRight ); + } + + SECTION( "Test against analytical solution Dim 1" ) { + Vector moment; + std::vector validMoment( 3, true ); + for( double my = -1.0; my < 1.0; my += 0.1 ) { + + for( double phi = 0.0; phi < 2 * M_PI; phi += 0.1 ) { + moment = testBase1D.ComputeSphericalBasis( my, phi ); + + if( std::fabs( moment[0] - SphericalMonomial_0( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[0] = false; + if( std::fabs( moment[1] - SphericalMonomial_3( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[1] = false; + if( std::fabs( moment[2] - SphericalMonomial_9( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[2] = false; + } + } + + REQUIRE( std::all_of( validMoment.begin(), validMoment.end(), []( bool v ) { return v; } ) ); + } +} -- GitLab From d899c75dcf1ef6160bc81d0447123346ef88e240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Tue, 23 Feb 2021 19:03:07 +0100 Subject: [PATCH 03/67] added 1D deg2&3 datagenerator. Not yet tested Former-commit-id: de50a41d6cff01e36c0a9639fd9acfd8170cebde --- code/include/common/config.h | 2 + code/include/toolboxes/datagenerator.h | 3 +- code/include/toolboxes/sphericalmonomials.h | 4 +- code/input/DataGenerator.cfg | 4 +- code/input/checkerboard_MN.cfg | 2 +- code/src/common/config.cpp | 3 + code/src/main.cpp | 2 +- code/src/toolboxes/datagenerator.cpp | 222 ++++++++++++++++---- code/src/toolboxes/sphericalmonomials.cpp | 10 +- 9 files changed, 201 insertions(+), 51 deletions(-) diff --git a/code/include/common/config.h b/code/include/common/config.h index afc0718..9af724a 100644 --- a/code/include/common/config.h +++ b/code/include/common/config.h @@ -127,6 +127,7 @@ class Config unsigned long _maxValFirstMoment; /*!< @brief Size of training data set for data generator */ double _RealizableSetEpsilonU0; /*! @brief Distance to 0 of the sampled moments to the boundary of the realizable set */ double _RealizableSetEpsilonU1; /*!< @brief: norm(u_1)/u_0 !< _RealizableSetEpsilonU1 */ + bool _normalizedSampling; /*!< @brief: Flag for sampling of normalized moments, i.e. u_0 =1 */ // --- Parsing Functionality and Initializing of Options --- /*! @@ -324,6 +325,7 @@ class Config unsigned long inline GetMaxValFirstMoment() { return _maxValFirstMoment; } double GetRealizableSetEpsilonU0() { return _RealizableSetEpsilonU0; } double GetRealizableSetEpsilonU1() { return _RealizableSetEpsilonU1; } + bool inline GetNormalizedSampling() { return _normalizedSampling; } // ---- Setters for option structure // This section is dangerous diff --git a/code/include/toolboxes/datagenerator.h b/code/include/toolboxes/datagenerator.h index 4592b20..f3c2188 100644 --- a/code/include/toolboxes/datagenerator.h +++ b/code/include/toolboxes/datagenerator.h @@ -30,7 +30,7 @@ class nnDataGenerator /*! @brief: computes the training data set. * Realizable set is sampled uniformly. * Prototype: 1D, u\in[0,100] */ - void computeTrainingData(); + void ComputeTrainingData(); /*! @brief: Writes the training data to file * Filename encryption: [TODO] */ @@ -74,6 +74,7 @@ class nnDataGenerator void ComputeMoments(); /*! @brief: Pre-Compute Moments at all quadrature points. */ void CheckRealizability(); // Debugging helper void ComputeRealizableSolution(); /*! @brief: make u the realizable moment to alpha, since Newton has roundoff errors. */ + void ComputeSetSize(); /*! @brief: Computes the size of the training set, depending on the chosen settings.*/ inline VectorVector GetuSol() { return _uSol; } /*! @brief: Get the computed solution vector uSol */ inline VectorVector GetAlpha() { return _alpha; } /*! @brief: Get the computed vector alpha */ diff --git a/code/include/toolboxes/sphericalmonomials.h b/code/include/toolboxes/sphericalmonomials.h index 23ce98a..4df71ba 100644 --- a/code/include/toolboxes/sphericalmonomials.h +++ b/code/include/toolboxes/sphericalmonomials.h @@ -90,8 +90,8 @@ class SphericalMonomials : public SphericalBase double Power( double basis, unsigned exponent ); /*! @brief: Helper to compute the basis in 1D, 2D or 3D, depending on choice of _spatialDim */ - Vector ComputeSphericalBasis1D( double my, double phi ); - Vector ComputeSphericalBasis2D( double my, double phi ); + Vector ComputeSphericalBasis1D( double my ); /*! @brief: Only Z achsis of the 3D case */ + Vector ComputeSphericalBasis2D( double my, double phi ); /*! @brief: Only X and Y achsis of the 3D case */ Vector ComputeSphericalBasis3D( double my, double phi ); }; #endif // SPHERICALMONOMIALS_H diff --git a/code/input/DataGenerator.cfg b/code/input/DataGenerator.cfg index 2ffd940..aadf5b9 100644 --- a/code/input/DataGenerator.cfg +++ b/code/input/DataGenerator.cfg @@ -7,8 +7,8 @@ % % ---- Global settings ---- DATA_GENERATOR_MODE = YES -TRAINING_SET_SIZE = 500 -MAX_VALUE_FIRST_MOMENT = 20 +TRAINING_SET_SIZE = 20 +MAX_VALUE_FIRST_MOMENT = 5 REALIZABLE_SET_EPSILON_U0 = 0.05 REALIZABLE_SET_EPSILON_U1 = 0.97 % diff --git a/code/input/checkerboard_MN.cfg b/code/input/checkerboard_MN.cfg index eb0bd63..0e3043b 100644 --- a/code/input/checkerboard_MN.cfg +++ b/code/input/checkerboard_MN.cfg @@ -8,7 +8,7 @@ % OUTPUT_DIR = ../result % Output file -OUTPUT_FILE = MN_checkerboard_Monomials +OUTPUT_FILE = MN_checkerboard % Log directory LOG_DIR = ../result/logs % Mesh File diff --git a/code/src/common/config.cpp b/code/src/common/config.cpp index bb65b5c..8f3760a 100644 --- a/code/src/common/config.cpp +++ b/code/src/common/config.cpp @@ -330,6 +330,9 @@ void Config::SetConfigOptions() { /*! @brief norm(u_1)/u_0 is enforced to be smaller than _RealizableSetEpsilonU1 \n DESCRIPTION: Distance to the boundary of the realizable set \n * DEFAULT 0.1 \ingroup Config */ AddDoubleOption( "REALIZABLE_SET_EPSILON_U1", _RealizableSetEpsilonU1, 0.9 ); + /*! @brief Flag for sampling of normalized moments, i.e. u_0 =1 \n DESCRIPTION: Flag for sampling of normalized moments, i.e. u_0 =1 \n + * DEFAULT False \ingroup Config */ + AddBoolOption( "NORMALIZED_SAMPLING", _normalizedSampling, false ); } void Config::SetConfigParsing( string case_filename ) { diff --git a/code/src/main.cpp b/code/src/main.cpp index 0598d6b..b8f7835 100644 --- a/code/src/main.cpp +++ b/code/src/main.cpp @@ -44,7 +44,7 @@ int main( int argc, char** argv ) { // Build Data generator nnDataGenerator* datagen = new nnDataGenerator( config ); // Generate Data and export - datagen->computeTrainingData(); + datagen->ComputeTrainingData(); } else { // Build solver diff --git a/code/src/toolboxes/datagenerator.cpp b/code/src/toolboxes/datagenerator.cpp index 3d5272a..c600b39 100644 --- a/code/src/toolboxes/datagenerator.cpp +++ b/code/src/toolboxes/datagenerator.cpp @@ -10,11 +10,10 @@ #include "optimizers/newtonoptimizer.h" #include "quadratures/qlebedev.h" #include "quadratures/quadraturebase.h" +#include "spdlog/spdlog.h" #include "toolboxes/errormessages.h" #include "toolboxes/sphericalbase.h" -#include "spdlog/spdlog.h" - #include #include @@ -25,6 +24,17 @@ nnDataGenerator::nnDataGenerator( Config* settings ) { _LMaxDegree = settings->GetMaxMomentDegree(); + // Check consistency between dimension of quadrature and sample basis + if( _settings->GetDim() == 1 ) { + if( _settings->GetQuadName() != QUAD_GaussLegendre1D && _settings->GetQuadName() != QUAD_GaussChebyshev1D ) { + ErrorMessages::Error( "For 1D Sampling, please choose a 1D quadrature rule.", CURRENT_FUNCTION ); + } + } + else { + if( _settings->GetQuadName() == QUAD_GaussLegendre1D || _settings->GetQuadName() == QUAD_GaussChebyshev1D ) { + ErrorMessages::Error( "For 3D Sampling, please choose a 3D quadrature rule.", CURRENT_FUNCTION ); + } + } // Quadrature _quadrature = QuadratureBase::Create( settings ); _nq = _quadrature->GetNq(); @@ -51,37 +61,7 @@ nnDataGenerator::nnDataGenerator( Config* settings ) { _entropy = EntropyBase::Create( _settings ); // Initialize Training Data - if( _LMaxDegree == 0 ) { - } - else if( _LMaxDegree == 1 ) { - // Sample points on unit sphere. - QuadratureBase* quad = QuadratureBase::Create( _settings ); - unsigned long nq = (unsigned long)quad->GetNq(); - - // Allocate memory. - _setSize = nq * _gridSize * ( _gridSize - 1 ) / 2; - - delete quad; - } - else if( _LMaxDegree == 2 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetDim() == 1 ) { - // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 - unsigned c = 1; - double N1 = -1.0 + _settings->GetRealizableSetEpsilonU0(); - double N2; - double dN = 2.0 / (double)_gridSize; - while( N1 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { - N2 = N1 * N1 + _settings->GetRealizableSetEpsilonU0(); - while( N2 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { - c++; - N2 += dN; - } - N1 += dN; - } - _setSize = c; - } - else { - ErrorMessages::Error( "Sampling of training data of degree higher than 1 is not yet implemented.", CURRENT_FUNCTION ); - } + ComputeSetSize(); _uSol = VectorVector( _setSize, Vector( _nTotalEntries, 0.0 ) ); _alpha = VectorVector( _setSize, Vector( _nTotalEntries, 0.0 ) ); @@ -93,7 +73,7 @@ nnDataGenerator::~nnDataGenerator() { delete _entropy; } -void nnDataGenerator::computeTrainingData() { +void nnDataGenerator::ComputeTrainingData() { // Prototype: Only for _LMaxDegree == 1 // Prototype: u is sampled from [0,100] @@ -104,7 +84,6 @@ void nnDataGenerator::computeTrainingData() { // ---- Check realizability --- CheckRealizability(); - // --- compute alphas --- _optimizer->SolveMultiCell( _alpha, _uSol, _moments ); @@ -122,9 +101,14 @@ void nnDataGenerator::ComputeMoments() { double my, phi; for( unsigned idx_quad = 0; idx_quad < _nq; idx_quad++ ) { - my = _quadPointsSphere[idx_quad][0]; - phi = _quadPointsSphere[idx_quad][1]; - + if( _settings->GetDim() == 1 ) { + my = _quadPointsSphere[idx_quad][0]; + phi = 0; // placeholder. will not be used + } + else { + my = _quadPointsSphere[idx_quad][0]; + phi = _quadPointsSphere[idx_quad][1]; + } _moments[idx_quad] = _basis->ComputeSphericalBasis( my, phi ); } } @@ -196,7 +180,8 @@ void nnDataGenerator::SampleSolutionU() { } } } - else if( _LMaxDegree == 2 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetDim() == 1 ) { + else if( _LMaxDegree == 2 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetDim() == 1 && + _settings->GetNormalizedSampling() ) { // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 unsigned c = 0; double N1 = -1.0 + _settings->GetRealizableSetEpsilonU0(); @@ -214,6 +199,69 @@ void nnDataGenerator::SampleSolutionU() { N1 += dN; } } + else if( _LMaxDegree == 2 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetDim() == 1 && + !_settings->GetNormalizedSampling() ) { + unsigned c = 0; + double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; + + double u0 = _settings->GetRealizableSetEpsilonU0(); + double u1, u2; + double N1, N2; // helper + while( u0 < _settings->GetMaxValFirstMoment() ) { + u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N1 = u1 / u0; + while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + u2 = u1 * u1 / u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N2 = u2 / u0; + while( N2 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + _uSol[c][0] = u0; // u0 (normalized i.e. N0) by Monreals notation + _uSol[c][1] = u1; // u1 (normalized i.e. N1) by Monreals notation + _uSol[c][2] = u2; // u2 (normalized i.e. N2) by Monreals notation + u2 += du; + N2 = u2 / u0; + c++; + } + u1 += du; + N1 = u1 / u0; + } + u0 += du; + } + } + else if( _LMaxDegree == 3 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetDim() == 1 && + !_settings->GetNormalizedSampling() ) { + // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 + unsigned c = 0; + double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; + double u0 = _settings->GetRealizableSetEpsilonU0(); + double u1, u2, u3; + double N1, N2, N3; // helper + while( u0 < _settings->GetMaxValFirstMoment() ) { + u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N1 = u1 / u0; + while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + u2 = u1 * u1 / u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N2 = u2 / u0; + while( u2 < u0 - _settings->GetRealizableSetEpsilonU0() ) { + u3 = -u2 + u0 * ( N1 + N2 ) * ( N1 + N2 ) / ( 1 + N1 ) + u0 * _settings->GetRealizableSetEpsilonU0(); + N3 = u3 / u0; + while( N3 < N2 - ( N1 - N2 ) * ( N1 - N2 ) / ( 1 - N1 ) - _settings->GetRealizableSetEpsilonU0() ) { + _uSol[c][0] = u0; // u0 by Monreals notation + _uSol[c][1] = u1; // u1 by Monreals notation + _uSol[c][2] = u2; // u2 by Monreals notation + _uSol[c][2] = u3; // u3 by Monreals notation + u3 += du; + N3 = u3 / u0; + c++; + } + u2 += du; + N2 = N3 / u0; + } + u1 += du; + N1 = u1 / u0; + } + u0 += du; + } + } else { ErrorMessages::Error( "Sampling for this configuration is not yet supported", CURRENT_FUNCTION ); } @@ -319,3 +367,99 @@ void nnDataGenerator::PrintLoadScreen() { log->info( "------------------------ Data Generation Starts --------------------------" ); log->info( "| Generating {} datapoints.", _setSize ); } + +void nnDataGenerator::ComputeSetSize() { + if( _LMaxDegree == 0 ) { + } + else if( _LMaxDegree == 1 ) { + // Sample points on unit sphere. + QuadratureBase* quad = QuadratureBase::Create( _settings ); + unsigned long nq = (unsigned long)quad->GetNq(); + + // Allocate memory. + _setSize = nq * _gridSize * ( _gridSize - 1 ) / 2; + + delete quad; + } + else if( _LMaxDegree == 2 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetDim() == 1 && + _settings->GetNormalizedSampling() ) { + // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 + unsigned c = 1; + double N1 = -1.0 + _settings->GetRealizableSetEpsilonU0(); + double N2; + double dN = 2.0 / (double)_gridSize; + while( N1 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { + N2 = N1 * N1 + _settings->GetRealizableSetEpsilonU0(); + while( N2 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { + c++; + N2 += dN; + } + N1 += dN; + } + _setSize = c; + } + else if( _LMaxDegree == 2 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetDim() == 1 && + !_settings->GetNormalizedSampling() ) { + unsigned c = 0; + double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; + + double u0 = _settings->GetRealizableSetEpsilonU0(); + double u1, u2; + double N1, N2; // helper + while( u0 < _settings->GetMaxValFirstMoment() ) { + u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N1 = u1 / u0; + if( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + u2 = u1 * u1 / u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N2 = u2 / u0; + if( N2 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + while( N2 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + c++; + u2 += du; + N2 = u2 / u0; + } + } + u1 += du; + N1 = u1 / u0; + } + } + u0 += du; + } + _setSize = c; + } + else if( _LMaxDegree == 3 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetDim() == 1 && + !_settings->GetNormalizedSampling() ) { + // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 + unsigned c = 0; + double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; + double u0 = _settings->GetRealizableSetEpsilonU0(); + double u1, u2, u3; + double N1, N2, N3; // helper + while( u0 < _settings->GetMaxValFirstMoment() ) { + u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N1 = u1 / u0; + while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + u2 = u1 * u1 / u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N2 = u2 / u0; + while( u2 < u0 - _settings->GetRealizableSetEpsilonU0() ) { + u3 = -u2 + u0 * ( N1 + N2 ) * ( N1 + N2 ) / ( 1 + N1 ) + u0 * _settings->GetRealizableSetEpsilonU0(); + N3 = u3 / u0; + while( N3 < N2 - ( N1 - N2 ) * ( N1 - N2 ) / ( 1 - N1 ) - _settings->GetRealizableSetEpsilonU0() ) { + u3 += du; + c++; + } + u2 += du; + N2 = u2 / u0; + } + u1 += du; + N1 = u1 / u0; + } + u0 += du; + } + _setSize = c; + } + else { + ErrorMessages::Error( "Sampling of training data of degree higher than 1 is not yet implemented.", CURRENT_FUNCTION ); + } +} diff --git a/code/src/toolboxes/sphericalmonomials.cpp b/code/src/toolboxes/sphericalmonomials.cpp index a50a8a9..df76dfd 100644 --- a/code/src/toolboxes/sphericalmonomials.cpp +++ b/code/src/toolboxes/sphericalmonomials.cpp @@ -24,22 +24,22 @@ SphericalMonomials::SphericalMonomials( unsigned L_degree, unsigned short spatia Vector SphericalMonomials::ComputeSphericalBasis( double my, double phi ) { switch( _spatialDim ) { - case 1: return ComputeSphericalBasis1D( my, phi ); break; + case 1: return ComputeSphericalBasis1D( my ); break; case 2: return ComputeSphericalBasis2D( my, phi ); break; default: return ComputeSphericalBasis3D( my, phi ); break; } } -Vector SphericalMonomials::ComputeSphericalBasis1D( double my, double phi ) { +Vector SphericalMonomials::ComputeSphericalBasis1D( double my ) { unsigned idx_vector = 0; unsigned a; - double omega_X; + double omega_Z; // go over all degrees of polynomials for( unsigned idx_degree = 0; idx_degree <= _LMaxDegree; idx_degree++ ) { // elem = Omega_x^a : a = idx_degree - omega_X = Omega_x( my, phi ); + omega_Z = Omega_z( my ); a = idx_degree; // a uniquely defined - _YBasis[idx_vector] = Power( omega_X, a ); + _YBasis[idx_vector] = Power( omega_Z, a ); idx_vector++; } return _YBasis; -- GitLab From 97153af577268019d3e6c22ff33b7ededf2c1489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Tue, 23 Feb 2021 19:09:17 +0100 Subject: [PATCH 04/67] repaired test cases. (adapted monomial 1d quad) Former-commit-id: 7ae7b6e3d7bc254bf997b6c688230e40bfb79144 --- code/tests/test_cases.cpp | 2 +- code/tests/test_sphericalBasis.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/tests/test_cases.cpp b/code/tests/test_cases.cpp index 14780b6..a97fe49 100644 --- a/code/tests/test_cases.cpp +++ b/code/tests/test_cases.cpp @@ -372,7 +372,7 @@ TEST_CASE( "Test the Data Generator", "[dataGen]" ) { // Build Data generator nnDataGenerator* datagen = new nnDataGenerator( config ); // Generate Data and export - datagen->computeTrainingData(); + datagen->ComputeTrainingData(); // --- Force Logger to flush auto log = spdlog::get( "event" ); diff --git a/code/tests/test_sphericalBasis.cpp b/code/tests/test_sphericalBasis.cpp index 7aec172..dc33c9e 100644 --- a/code/tests/test_sphericalBasis.cpp +++ b/code/tests/test_sphericalBasis.cpp @@ -372,8 +372,8 @@ TEST_CASE( "test spherical monomial basis", "[spherical_monomials]" ) { moment = testBase1D.ComputeSphericalBasis( my, phi ); if( std::fabs( moment[0] - SphericalMonomial_0( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[0] = false; - if( std::fabs( moment[1] - SphericalMonomial_3( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[1] = false; - if( std::fabs( moment[2] - SphericalMonomial_9( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[2] = false; + if( std::fabs( moment[1] - SphericalMonomial_1( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[1] = false; + if( std::fabs( moment[2] - SphericalMonomial_4( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[2] = false; } } -- GitLab From 46c946d414cb378cda5e5398b6ae1186f2ad8b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Wed, 24 Feb 2021 10:43:56 +0100 Subject: [PATCH 05/67] tidy up of input folder Former-commit-id: 4092a0c2a2aff7fb4448bc37699d342011f7354d --- code/input/aircavity1D.cfg | 18 +++++++++++++++ code/input/waterphantomCSD.cfg | 20 ++++++++++++++++ code/input/waterphantom_1D.cfg | 25 ++++++++++++++++++++ code/input/waterphantom_2D.cfg | 42 ++++++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+) create mode 100644 code/input/aircavity1D.cfg create mode 100644 code/input/waterphantomCSD.cfg create mode 100644 code/input/waterphantom_1D.cfg create mode 100644 code/input/waterphantom_2D.cfg diff --git a/code/input/aircavity1D.cfg b/code/input/aircavity1D.cfg new file mode 100644 index 0000000..ddcb634 --- /dev/null +++ b/code/input/aircavity1D.cfg @@ -0,0 +1,18 @@ +OUTPUT_DIR = ../result +OUTPUT_FILE = example_csd_1d_10MeV_fine +LOG_DIR = ../result/logs +MESH_FILE = 1DMesh.su2 +PROBLEM = AIRCAVITY +SOLVER = CSD_SN_FOKKERPLANCK_TRAFO_SOLVER +CONTINUOUS_SLOWING_DOWN = YES +HYDROGEN_FILE = ENDL_H.txt +OXYGEN_FILE = ENDL_O.txt +KERNEL = ISOTROPIC_1D +CFL_NUMBER = 0.0001 +TIME_FINAL = 1.0 +CLEAN_FLUX_MATRICES = NO + +BC_DIRICHLET = ( dirichlet ) +BC_NEUMANN = ( wall_low, wall_up ) +QUAD_TYPE = GAUSS_LEGENDRE_1D +QUAD_ORDER = 26 diff --git a/code/input/waterphantomCSD.cfg b/code/input/waterphantomCSD.cfg new file mode 100644 index 0000000..d5c9cdc --- /dev/null +++ b/code/input/waterphantomCSD.cfg @@ -0,0 +1,20 @@ +% +% +% +OUTPUT_DIR = ../result +OUTPUT_FILE = example_csdSN_1d_NOScatter +LOG_DIR = ../result/logs +MESH_FILE = meshes/1DMesh.su2 +PROBLEM = WATERPHANTOM +SOLVER = CSD_SN_SOLVER + +% ? +KERNEL = ISOTROPIC_1D +CFL_NUMBER = 0.001 +TIME_FINAL = 1 + +BC_DIRICHLET = ( dirichlet ) +BC_NEUMANN = ( wall_low, wall_up ) + +QUAD_TYPE = GAUSS_LEGENDRE_1D +QUAD_ORDER = 6 diff --git a/code/input/waterphantom_1D.cfg b/code/input/waterphantom_1D.cfg new file mode 100644 index 0000000..1a30831 --- /dev/null +++ b/code/input/waterphantom_1D.cfg @@ -0,0 +1,25 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Checkerboard Benchmarking File SN % +% Author % +% Date 01.12.2020 % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% + +OUTPUT_DIR = ../result +OUTPUT_FILE = example_csd_1d_10MeV_fine +LOG_DIR = ../result/logs +MESH_FILE = meshes/1DMesh.su2 +PROBLEM = WATERPHANTOM +SOLVER = CSD_SN_FOKKERPLANCK_TRAFO_SOLVER +CONTINUOUS_SLOWING_DOWN = YES +HYDROGEN_FILE = ENDL_H.txt +OXYGEN_FILE = ENDL_O.txt +KERNEL = ISOTROPIC_1D +CFL_NUMBER = 0.008 +TIME_FINAL = 1.0 +CLEAN_FLUX_MATRICES = NO + +BC_DIRICHLET = ( dirichlet ) +BC_NEUMANN = ( wall_low, wall_up ) +QUAD_TYPE = GAUSS_LEGENDRE_1D +QUAD_ORDER = 26 diff --git a/code/input/waterphantom_2D.cfg b/code/input/waterphantom_2D.cfg new file mode 100644 index 0000000..b134319 --- /dev/null +++ b/code/input/waterphantom_2D.cfg @@ -0,0 +1,42 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Waterphantom Benchmarking File CSD % +% Author % +% Date 15.01.2020 % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% ---- File specifications ---- +% +OUTPUT_DIR = ../result +OUTPUT_FILE = phantom2d_csd_10MeV_fine +LOG_DIR = ../result/logs +MESH_FILE = meshes/phantom2D.su2 +CT_FILE = phantom.png + +% +% ---- Problem specifications ---- +% +PROBLEM = PHANTOM2D +HYDROGEN_FILE = ENDL_H.txt +OXYGEN_FILE = ENDL_O.txt +% +% ---- Solver specifications ---- +% +SOLVER = CSD_SN_FOKKERPLANCK_TRAFO_SOLVER_2D +KERNEL = ISOTROPIC +CFL_NUMBER = 0.15 +TIME_FINAL = 1.0 +% +% --- Boundary Conditions --- +% +BC_DIRICHLET = ( void ) +QUAD_TYPE = PRODUCT +QUAD_ORDER = 6 +% +% ----- Output ---- +% +VOLUME_OUTPUT = (MINIMAL, MEDICAL) +VOLUME_OUTPUT_FREQUENCY = 1 +SCREEN_OUTPUT = (ITER, MASS, RMS_FLUX, VTK_OUTPUT, CSV_OUTPUT) +SCREEN_OUTPUT_FREQUENCY = 1 +HISTORY_OUTPUT = (ITER, MASS, RMS_FLUX, VTK_OUTPUT, CSV_OUTPUT) +HISTORY_OUTPUT_FREQUENCY = 1 -- GitLab From 744b0cab3016e09ae39fd75f7773f8206b5131bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Wed, 24 Feb 2021 10:59:53 +0100 Subject: [PATCH 06/67] added 1D datagneretor file Former-commit-id: bef971f683d7523d93401c4097203402fddb7452 --- code/input/DataGenerator1D.cfg | 53 +++++++++++++++++++++++++++ code/input/aircavity_csd_1d.cfg | 18 --------- code/input/exampleWaterphantomCSD.cfg | 20 ---------- code/input/phantom2d_csd.cfg | 16 -------- 4 files changed, 53 insertions(+), 54 deletions(-) create mode 100644 code/input/DataGenerator1D.cfg delete mode 100644 code/input/aircavity_csd_1d.cfg delete mode 100644 code/input/exampleWaterphantomCSD.cfg delete mode 100644 code/input/phantom2d_csd.cfg diff --git a/code/input/DataGenerator1D.cfg b/code/input/DataGenerator1D.cfg new file mode 100644 index 0000000..ddf6144 --- /dev/null +++ b/code/input/DataGenerator1D.cfg @@ -0,0 +1,53 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Data Generator for % +% Neural Entropy Closure % +% Author % +% Date 17.12.2020 % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% ---- Datagenerator settings ---- +DATA_GENERATOR_MODE = YES +TRAINING_SET_SIZE = 500 +MAX_VALUE_FIRST_MOMENT = 1 +SPATIAL_DIM = 1 +REALIZABLE_SET_EPSILON_U0 = 0.001 +NORMALIZED_SAMPLING = NO +% +% ---- File specifications ---- +% +% Output directory +OUTPUT_DIR = ../result +% Output file +OUTPUT_FILE = trainM01D +% Log directory +LOG_DIR = ../result/logs +LOG_FILE = dataGen1D + +% +% --- Spherical Basis ---- +% +% Choice of basis functions +SPHERICAL_BASIS = SPHERICAL_MONOMIALS +% +% Maximal Moment degree +MAX_MOMENT_SOLVER = 2 +% +% --- Entropy settings ---- +ENTROPY_FUNCTIONAL = MAXWELL_BOLTZMANN +ENTROPY_OPTIMIZER = NEWTON +% +% ----- Newton Solver Specifications ---- +% +NEWTON_FAST_MODE = NO +NEWTON_ITER = 1000000 +NEWTON_EPSILON = 0.0001 +NEWTON_STEP_SIZE = 0.7 +NEWTON_LINE_SEARCH_ITER = 100000 +% +% ----- Quadrature ---- +% +% Quadrature Rule +QUAD_TYPE = GAUSS_LEGENDRE_1D +% Quadrature Order +QUAD_ORDER = 200 +% diff --git a/code/input/aircavity_csd_1d.cfg b/code/input/aircavity_csd_1d.cfg deleted file mode 100644 index ddcb634..0000000 --- a/code/input/aircavity_csd_1d.cfg +++ /dev/null @@ -1,18 +0,0 @@ -OUTPUT_DIR = ../result -OUTPUT_FILE = example_csd_1d_10MeV_fine -LOG_DIR = ../result/logs -MESH_FILE = 1DMesh.su2 -PROBLEM = AIRCAVITY -SOLVER = CSD_SN_FOKKERPLANCK_TRAFO_SOLVER -CONTINUOUS_SLOWING_DOWN = YES -HYDROGEN_FILE = ENDL_H.txt -OXYGEN_FILE = ENDL_O.txt -KERNEL = ISOTROPIC_1D -CFL_NUMBER = 0.0001 -TIME_FINAL = 1.0 -CLEAN_FLUX_MATRICES = NO - -BC_DIRICHLET = ( dirichlet ) -BC_NEUMANN = ( wall_low, wall_up ) -QUAD_TYPE = GAUSS_LEGENDRE_1D -QUAD_ORDER = 26 diff --git a/code/input/exampleWaterphantomCSD.cfg b/code/input/exampleWaterphantomCSD.cfg deleted file mode 100644 index d5c9cdc..0000000 --- a/code/input/exampleWaterphantomCSD.cfg +++ /dev/null @@ -1,20 +0,0 @@ -% -% -% -OUTPUT_DIR = ../result -OUTPUT_FILE = example_csdSN_1d_NOScatter -LOG_DIR = ../result/logs -MESH_FILE = meshes/1DMesh.su2 -PROBLEM = WATERPHANTOM -SOLVER = CSD_SN_SOLVER - -% ? -KERNEL = ISOTROPIC_1D -CFL_NUMBER = 0.001 -TIME_FINAL = 1 - -BC_DIRICHLET = ( dirichlet ) -BC_NEUMANN = ( wall_low, wall_up ) - -QUAD_TYPE = GAUSS_LEGENDRE_1D -QUAD_ORDER = 6 diff --git a/code/input/phantom2d_csd.cfg b/code/input/phantom2d_csd.cfg deleted file mode 100644 index 1d416f4..0000000 --- a/code/input/phantom2d_csd.cfg +++ /dev/null @@ -1,16 +0,0 @@ -OUTPUT_DIR = ../result -OUTPUT_FILE = phantom2d_csd_1MeV_fine_nosh_nq8 -LOG_DIR = ../result/logs -MESH_FILE = phantom2D.su2 -PROBLEM = PHANTOM2D -SOLVER = CSD_SN_FOKKERPLANCK_TRAFO_SOLVER_2D -HYDROGEN_FILE = ENDL_H.txt -OXYGEN_FILE = ENDL_O.txt -KERNEL = ISOTROPIC -CFL_NUMBER = 0.15 -TIME_FINAL = 1.0 -CLEAN_FLUX_MATRICES = NO - -BC_DIRICHLET = ( void ) -QUAD_TYPE = PRODUCT -QUAD_ORDER = 6 -- GitLab From f78cf8f10fa26a088d5753ed695eb95413f25321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Wed, 24 Feb 2021 14:51:28 +0100 Subject: [PATCH 07/67] split datagenerator into 3D and 1D case Former-commit-id: 70ef133790442a70e0bb25c5d6d485345de4b2aa --- code/include/toolboxes/datagenerator1D.h | 32 ++ code/include/toolboxes/datagenerator3D.h | 32 ++ .../{datagenerator.h => datageneratorbase.h} | 38 +- code/input/DataGenerator1D.cfg | 2 +- code/src/main.cpp | 4 +- code/src/toolboxes/datagenerator.cpp | 465 ------------------ code/src/toolboxes/datagenerator1D.cpp | 264 ++++++++++ code/src/toolboxes/datagenerator3D.cpp | 165 +++++++ code/src/toolboxes/datageneratorbase.cpp | 167 +++++++ code/tests/test_cases.cpp | 6 +- 10 files changed, 687 insertions(+), 488 deletions(-) create mode 100644 code/include/toolboxes/datagenerator1D.h create mode 100644 code/include/toolboxes/datagenerator3D.h rename code/include/toolboxes/{datagenerator.h => datageneratorbase.h} (74%) delete mode 100644 code/src/toolboxes/datagenerator.cpp create mode 100644 code/src/toolboxes/datagenerator1D.cpp create mode 100644 code/src/toolboxes/datagenerator3D.cpp create mode 100644 code/src/toolboxes/datageneratorbase.cpp diff --git a/code/include/toolboxes/datagenerator1D.h b/code/include/toolboxes/datagenerator1D.h new file mode 100644 index 0000000..241147d --- /dev/null +++ b/code/include/toolboxes/datagenerator1D.h @@ -0,0 +1,32 @@ +/*! + * \file datagenerator1D.h + * \brief Class to generate data for the neural entropy closure in 1D spatial dimensions + * \author S. Schotthoefer + */ + +#ifndef DATAGENERATOR1D_H +#define DATAGENERATOR1D_H + +#include "toolboxes/datageneratorbase.h" + +class DataGenerator1D : public DataGeneratorBase +{ + public: + /*! @brief: Class constructor. Generates training data for neural network approaches using + * spherical harmonics and an entropy functional and the quadrature specified by + * the options file. + * @param: setSize: number of elements in training set + * basisSize: length of spherical harmonics basis (maybe redundant)*/ + DataGenerator1D( Config* settings ); + ~DataGenerator1D(); + + private: + // Main methods + void SampleSolutionU() override; /*! @brief: Samples solution vectors u */ + + // Helper functions + void ComputeMoments() override; /*! @brief: Pre-Compute Moments at all quadrature points. */ + void ComputeSetSize() override; /*! @brief: Computes the size of the training set, depending on the chosen settings.*/ + void CheckRealizability() override; // Debugging helper +}; +#endif // DATAGENERATOR1D_H diff --git a/code/include/toolboxes/datagenerator3D.h b/code/include/toolboxes/datagenerator3D.h new file mode 100644 index 0000000..7934000 --- /dev/null +++ b/code/include/toolboxes/datagenerator3D.h @@ -0,0 +1,32 @@ +/*! + * \file datagenerator3D.h + * \brief Class to generate data for the neural entropy closure in 3D spatial dimensions + * \author S. Schotthoefer + */ + +#ifndef DATAGENERATOR3D_H +#define DATAGENERATOR3D_H + +#include "toolboxes/datageneratorbase.h" + +class DataGenerator3D : public DataGeneratorBase +{ + public: + /*! @brief: Class constructor. Generates training data for neural network approaches using + * spherical harmonics and an entropy functional and the quadrature specified by + * the options file. + * @param: setSize: number of elements in training set + * basisSize: length of spherical harmonics basis (maybe redundant)*/ + DataGenerator3D( Config* settings ); + ~DataGenerator3D(); + + private: + // Main methods + void SampleSolutionU() override; /*! @brief: Samples solution vectors u */ + + // Helper functions + void ComputeMoments() override; /*! @brief: Pre-Compute Moments at all quadrature points. */ + void ComputeSetSize() override; /*! @brief: Computes the size of the training set, depending on the chosen settings.*/ + void CheckRealizability() override; // Debugging helper +}; +#endif // DATAGENERATOR3D_H diff --git a/code/include/toolboxes/datagenerator.h b/code/include/toolboxes/datageneratorbase.h similarity index 74% rename from code/include/toolboxes/datagenerator.h rename to code/include/toolboxes/datageneratorbase.h index f3c2188..19de06c 100644 --- a/code/include/toolboxes/datagenerator.h +++ b/code/include/toolboxes/datageneratorbase.h @@ -16,7 +16,7 @@ class Config; class NewtonOptimizer; class EntropyBase; -class nnDataGenerator +class DataGeneratorBase { public: /*! @brief: Class constructor. Generates training data for neural network approaches using @@ -24,19 +24,24 @@ class nnDataGenerator * the options file. * @param: setSize: number of elements in training set * basisSize: length of spherical harmonics basis (maybe redundant)*/ - nnDataGenerator( Config* settings ); - ~nnDataGenerator(); + DataGeneratorBase( Config* settings ); + ~DataGeneratorBase(); + + /*! @brief: Create a datagenerator (1D or 3D) + * @param: Pointer to the config file + * @returns: Pointer to the createt basis class */ + static DataGeneratorBase* Create( Config* settings ); /*! @brief: computes the training data set. * Realizable set is sampled uniformly. * Prototype: 1D, u\in[0,100] */ void ComputeTrainingData(); - /*! @brief: Writes the training data to file - * Filename encryption: [TODO] */ - void writeTrainingDataToCSV(); + inline VectorVector GetuSol() { return _uSol; } /*! @brief: Get the computed solution vector uSol */ + inline VectorVector GetAlpha() { return _alpha; } /*! @brief: Get the computed vector alpha */ + inline std::vector GethEntropy() { return _hEntropy; } /*! @brief: Get the computed entropy value h */ - private: + protected: Config* _settings; /*! @brief config class for global information */ VectorVector _uSol; /*! @brief: vector with moments. Size: (setSize,basisSize)*/ @@ -63,21 +68,18 @@ class nnDataGenerator EntropyBase* _entropy; /*! @brief: Class to handle entropy functional evaluations */ // Main methods - void SampleSolutionU(); /*! @brief: Samples solution vectors u */ - void ComputeEntropyH_dual(); /*! @brief: Compute the entropy functional at (u,alpha) in dual formulation */ - void ComputeEntropyH_primal(); /*! @brief: Compute the entropy functional at (u,alpha) in primal formulation */ + virtual void SampleSolutionU() = 0; /*! @brief: Samples solution vectors u */ + void ComputeEntropyH_dual(); /*! @brief: Compute the entropy functional at (u,alpha) in dual formulation */ + void ComputeEntropyH_primal(); /*! @brief: Compute the entropy functional at (u,alpha) in primal formulation */ + void ComputeRealizableSolution(); /*! @brief: make u the realizable moment to alpha, since Newton has roundoff errors. */ // IO routines void PrintTrainingData(); /*! @brief : Print computed training data to csv file and screen */ void PrintLoadScreen(); /*! @brief: Print screen IO*/ - // Helper functions - void ComputeMoments(); /*! @brief: Pre-Compute Moments at all quadrature points. */ - void CheckRealizability(); // Debugging helper - void ComputeRealizableSolution(); /*! @brief: make u the realizable moment to alpha, since Newton has roundoff errors. */ - void ComputeSetSize(); /*! @brief: Computes the size of the training set, depending on the chosen settings.*/ - inline VectorVector GetuSol() { return _uSol; } /*! @brief: Get the computed solution vector uSol */ - inline VectorVector GetAlpha() { return _alpha; } /*! @brief: Get the computed vector alpha */ - inline std::vector GethEntropy() { return _hEntropy; } /*! @brief: Get the computed entropy value h */ + // Helper functions + virtual void ComputeMoments() = 0; /*! @brief: Pre-Compute Moments at all quadrature points. */ + virtual void CheckRealizability() = 0; // Debugging helper + virtual void ComputeSetSize() = 0; /*! @brief: Computes the size of the training set, depending on the chosen settings.*/ }; #endif // DATAGENERATOR_H diff --git a/code/input/DataGenerator1D.cfg b/code/input/DataGenerator1D.cfg index ddf6144..04a9bcc 100644 --- a/code/input/DataGenerator1D.cfg +++ b/code/input/DataGenerator1D.cfg @@ -30,7 +30,7 @@ LOG_FILE = dataGen1D SPHERICAL_BASIS = SPHERICAL_MONOMIALS % % Maximal Moment degree -MAX_MOMENT_SOLVER = 2 +MAX_MOMENT_SOLVER = 1 % % --- Entropy settings ---- ENTROPY_FUNCTIONAL = MAXWELL_BOLTZMANN diff --git a/code/src/main.cpp b/code/src/main.cpp index b8f7835..09272cf 100644 --- a/code/src/main.cpp +++ b/code/src/main.cpp @@ -12,7 +12,7 @@ #include "common/io.h" #include "solvers/solverbase.h" -#include "toolboxes/datagenerator.h" +#include "toolboxes/datageneratorbase.h" #ifdef BUILD_GUI #include @@ -42,7 +42,7 @@ int main( int argc, char** argv ) { if( config->GetDataGeneratorMode() ) { // Build Data generator - nnDataGenerator* datagen = new nnDataGenerator( config ); + DataGeneratorBase* datagen = DataGeneratorBase::Create( config ); // Generate Data and export datagen->ComputeTrainingData(); } diff --git a/code/src/toolboxes/datagenerator.cpp b/code/src/toolboxes/datagenerator.cpp deleted file mode 100644 index c600b39..0000000 --- a/code/src/toolboxes/datagenerator.cpp +++ /dev/null @@ -1,465 +0,0 @@ -/*! - * \file datagenerator.cpp - * \brief Class to generate data for the neural entropy closure - * \author S. Schotthoefer - */ - -#include "toolboxes/datagenerator.h" -#include "common/config.h" -#include "entropies/entropybase.h" -#include "optimizers/newtonoptimizer.h" -#include "quadratures/qlebedev.h" -#include "quadratures/quadraturebase.h" -#include "spdlog/spdlog.h" -#include "toolboxes/errormessages.h" -#include "toolboxes/sphericalbase.h" - -#include -#include - -nnDataGenerator::nnDataGenerator( Config* settings ) { - _settings = settings; - _setSize = settings->GetTrainingDataSetSize(); - _gridSize = _setSize; - - _LMaxDegree = settings->GetMaxMomentDegree(); - - // Check consistency between dimension of quadrature and sample basis - if( _settings->GetDim() == 1 ) { - if( _settings->GetQuadName() != QUAD_GaussLegendre1D && _settings->GetQuadName() != QUAD_GaussChebyshev1D ) { - ErrorMessages::Error( "For 1D Sampling, please choose a 1D quadrature rule.", CURRENT_FUNCTION ); - } - } - else { - if( _settings->GetQuadName() == QUAD_GaussLegendre1D || _settings->GetQuadName() == QUAD_GaussChebyshev1D ) { - ErrorMessages::Error( "For 3D Sampling, please choose a 3D quadrature rule.", CURRENT_FUNCTION ); - } - } - // Quadrature - _quadrature = QuadratureBase::Create( settings ); - _nq = _quadrature->GetNq(); - _quadPoints = _quadrature->GetPoints(); - _weights = _quadrature->GetWeights(); - _quadPointsSphere = _quadrature->GetPointsSphere(); - - // Spherical Harmonics - if( _settings->GetSphericalBasisName() == SPHERICAL_HARMONICS && _LMaxDegree > 0 ) { - ErrorMessages::Error( "No sampling algorithm for spherical harmonics basis with degree higher than 0 implemented", CURRENT_FUNCTION ); - } - _basis = SphericalBase::Create( _settings ); - - _nTotalEntries = _basis->GetBasisSize(); - - _moments = VectorVector( _nq, Vector( _nTotalEntries, 0.0 ) ); - - ComputeMoments(); - - // Optimizer - _optimizer = new NewtonOptimizer( _settings ); - - // Entropy - _entropy = EntropyBase::Create( _settings ); - - // Initialize Training Data - ComputeSetSize(); - - _uSol = VectorVector( _setSize, Vector( _nTotalEntries, 0.0 ) ); - _alpha = VectorVector( _setSize, Vector( _nTotalEntries, 0.0 ) ); - _hEntropy = std::vector( _setSize, 0.0 ); -} - -nnDataGenerator::~nnDataGenerator() { - delete _quadrature; - delete _entropy; -} - -void nnDataGenerator::ComputeTrainingData() { - // Prototype: Only for _LMaxDegree == 1 - // Prototype: u is sampled from [0,100] - - // --- sample u --- - SampleSolutionU(); - - PrintLoadScreen(); - - // ---- Check realizability --- - CheckRealizability(); - // --- compute alphas --- - _optimizer->SolveMultiCell( _alpha, _uSol, _moments ); - - // --- Postprocessing - ComputeRealizableSolution(); - - // --- compute entropy functional --- - ComputeEntropyH_primal(); - - // --- Print everything ---- - PrintTrainingData(); -} - -void nnDataGenerator::ComputeMoments() { - double my, phi; - - for( unsigned idx_quad = 0; idx_quad < _nq; idx_quad++ ) { - if( _settings->GetDim() == 1 ) { - my = _quadPointsSphere[idx_quad][0]; - phi = 0; // placeholder. will not be used - } - else { - my = _quadPointsSphere[idx_quad][0]; - phi = _quadPointsSphere[idx_quad][1]; - } - _moments[idx_quad] = _basis->ComputeSphericalBasis( my, phi ); - } -} - -void nnDataGenerator::SampleSolutionU() { - // Use necessary conditions from Monreal, Dissertation, Chapter 3.2.1, Page 26 - - // --- Determine stepsizes etc --- - double du0 = _settings->GetMaxValFirstMoment() / (double)_gridSize; - - // different processes for different - if( _LMaxDegree == 0 ) { - // --- sample u in order 0 --- - // u_0 = <1*psi> - - for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { - _uSol[idx_set][0] = du0 * idx_set; - } - } - else if( _LMaxDegree == 1 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS ) { - // Sample points on unit sphere. - QuadratureBase* quad = QuadratureBase::Create( _settings ); - VectorVector qpoints = quad->GetPoints(); // carthesian coordinates. - unsigned long nq = (unsigned long)quad->GetNq(); - - // --- sample u in order 0 --- - // u_0 = <1*psi> - -#pragma omp parallel for schedule( guided ) - for( unsigned long idx_set = 0; idx_set < _gridSize; idx_set++ ) { - unsigned long outerIdx = ( idx_set - 1 ) * ( idx_set ) / 2; // sum over all radii up to current - outerIdx *= nq; // in each radius step, use all quad points - - // --- sample u in order 1 --- - /* order 1 has 3 elements. (omega_x, omega_y, omega_z) = omega, let u_1 = (u_x, u_y, u_z) = - * Condition u_0 >= norm(u_1) */ - double radiusU0 = du0 * ( idx_set + 1 ); - // Boundary correction - if( radiusU0 < _settings->GetRealizableSetEpsilonU0() ) { - radiusU0 = _settings->GetRealizableSetEpsilonU0(); // Boundary close to 0 - } - - unsigned long localIdx = 0; - double radius = 0.0; - unsigned long innerIdx = 0; - // loop over all radii - for( unsigned long idx_subset = 0; idx_subset < idx_set; idx_subset++ ) { - radius = du0 * ( idx_subset + 1 ); // dont use radius 0 ==> shift by one - // Boundary correction - if( radius < _settings->GetRealizableSetEpsilonU0() ) { - radius = _settings->GetRealizableSetEpsilonU0(); // Boundary close to 0 - } - if( radius / radiusU0 > 0.95 * _settings->GetRealizableSetEpsilonU1() ) { - // small offset to take care of rounding errors in quadrature - radius = radiusU0 * 0.95 * _settings->GetRealizableSetEpsilonU1(); // "outer" boundary - } - - localIdx = outerIdx + idx_subset * nq; - - for( unsigned long quad_idx = 0; quad_idx < nq; quad_idx++ ) { - innerIdx = localIdx + quad_idx; // gives the global index - - _uSol[innerIdx][0] = radiusU0; // Prevent 1st order moments to be too close to the boundary - // scale quadpoints with radius - _uSol[innerIdx][1] = radius * qpoints[quad_idx][0]; - _uSol[innerIdx][2] = radius * qpoints[quad_idx][1]; - _uSol[innerIdx][3] = radius * qpoints[quad_idx][2]; - } - } - } - } - else if( _LMaxDegree == 2 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetDim() == 1 && - _settings->GetNormalizedSampling() ) { - // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 - unsigned c = 0; - double N1 = -1.0 + _settings->GetRealizableSetEpsilonU0(); - double N2; - double dN = 2.0 / (double)_gridSize; - while( N1 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { - N2 = N1 * N1 + _settings->GetRealizableSetEpsilonU0(); - while( N2 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { - _uSol[c][0] = 1; // u0 (normalized i.e. N0) by Monreals notation - _uSol[c][1] = N1; // u1 (normalized i.e. N1) by Monreals notation - _uSol[c][2] = N2; // u2 (normalized i.e. N2) by Monreals notation - N2 += dN; - c++; - } - N1 += dN; - } - } - else if( _LMaxDegree == 2 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetDim() == 1 && - !_settings->GetNormalizedSampling() ) { - unsigned c = 0; - double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; - - double u0 = _settings->GetRealizableSetEpsilonU0(); - double u1, u2; - double N1, N2; // helper - while( u0 < _settings->GetMaxValFirstMoment() ) { - u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); - N1 = u1 / u0; - while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { - u2 = u1 * u1 / u0 + u0 * _settings->GetRealizableSetEpsilonU0(); - N2 = u2 / u0; - while( N2 < 1 - _settings->GetRealizableSetEpsilonU0() ) { - _uSol[c][0] = u0; // u0 (normalized i.e. N0) by Monreals notation - _uSol[c][1] = u1; // u1 (normalized i.e. N1) by Monreals notation - _uSol[c][2] = u2; // u2 (normalized i.e. N2) by Monreals notation - u2 += du; - N2 = u2 / u0; - c++; - } - u1 += du; - N1 = u1 / u0; - } - u0 += du; - } - } - else if( _LMaxDegree == 3 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetDim() == 1 && - !_settings->GetNormalizedSampling() ) { - // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 - unsigned c = 0; - double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; - double u0 = _settings->GetRealizableSetEpsilonU0(); - double u1, u2, u3; - double N1, N2, N3; // helper - while( u0 < _settings->GetMaxValFirstMoment() ) { - u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); - N1 = u1 / u0; - while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { - u2 = u1 * u1 / u0 + u0 * _settings->GetRealizableSetEpsilonU0(); - N2 = u2 / u0; - while( u2 < u0 - _settings->GetRealizableSetEpsilonU0() ) { - u3 = -u2 + u0 * ( N1 + N2 ) * ( N1 + N2 ) / ( 1 + N1 ) + u0 * _settings->GetRealizableSetEpsilonU0(); - N3 = u3 / u0; - while( N3 < N2 - ( N1 - N2 ) * ( N1 - N2 ) / ( 1 - N1 ) - _settings->GetRealizableSetEpsilonU0() ) { - _uSol[c][0] = u0; // u0 by Monreals notation - _uSol[c][1] = u1; // u1 by Monreals notation - _uSol[c][2] = u2; // u2 by Monreals notation - _uSol[c][2] = u3; // u3 by Monreals notation - u3 += du; - N3 = u3 / u0; - c++; - } - u2 += du; - N2 = N3 / u0; - } - u1 += du; - N1 = u1 / u0; - } - u0 += du; - } - } - else { - ErrorMessages::Error( "Sampling for this configuration is not yet supported", CURRENT_FUNCTION ); - } -} - -void nnDataGenerator::ComputeEntropyH_dual() { -#pragma omp parallel for schedule( guided ) - for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { - _hEntropy[idx_set] = _optimizer->ComputeObjFunc( _alpha[idx_set], _uSol[idx_set], _moments ); - } -} - -void nnDataGenerator::ComputeEntropyH_primal() { -#pragma omp parallel for schedule( guided ) - for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { - double result = 0.0; - // Integrate (eta(eta'_*(alpha*m)) - for( unsigned idx_quad = 0; idx_quad < _nq; idx_quad++ ) { - result += _entropy->Entropy( _entropy->EntropyPrimeDual( dot( _alpha[idx_set], _moments[idx_quad] ) ) ) * _weights[idx_quad]; - } - _hEntropy[idx_set] = result; - } -} - -void nnDataGenerator::PrintTrainingData() { - auto log = spdlog::get( "event" ); - auto logCSV = spdlog::get( "tabular" ); - log->info( "---------------------- Data Generation Successful ------------------------" ); - - std::string uSolString = ""; - std::string alphaString = ""; - for( unsigned idx_sys = 0; idx_sys < _nTotalEntries; idx_sys++ ) { - uSolString += "u_" + std::to_string( idx_sys ) + ","; - alphaString += "alpha_" + std::to_string( idx_sys ) + ","; - } - // log->info( uSolString + alphaString + "h" ); - logCSV->info( uSolString + alphaString + "h" ); - - for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { - std::string uSolString = ""; - std::string alphaString = ""; - for( unsigned idx_sys = 0; idx_sys < _nTotalEntries; idx_sys++ ) { - uSolString += std::to_string( _uSol[idx_set][idx_sys] ) + ","; - alphaString += std::to_string( _alpha[idx_set][idx_sys] ) + ","; - } - // log->info( uSolString + alphaString + "{}", _hEntropy[idx_set] ); - logCSV->info( uSolString + alphaString + "{}", _hEntropy[idx_set] ); - } -} - -void nnDataGenerator::CheckRealizability() { - double epsilon = _settings->GetRealizableSetEpsilonU0(); - if( _LMaxDegree == 1 ) { -#pragma omp parallel for schedule( guided ) - for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { - double normU1 = 0.0; - Vector u1( 3, 0.0 ); - if( _uSol[idx_set][0] < epsilon ) { - if( std::abs( _uSol[idx_set][1] ) > 0 || std::abs( _uSol[idx_set][2] ) > 0 || std::abs( _uSol[idx_set][3] ) > 0 ) { - ErrorMessages::Error( "Moment not realizable [code 0]. Values: (" + std::to_string( _uSol[idx_set][0] ) + "|" + - std::to_string( _uSol[idx_set][1] ) + "|" + std::to_string( _uSol[idx_set][2] ) + "|" + - std::to_string( _uSol[idx_set][3] ) + ")", - CURRENT_FUNCTION ); - } - } - else { - u1 = { _uSol[idx_set][1], _uSol[idx_set][2], _uSol[idx_set][3] }; - normU1 = norm( u1 ); - if( normU1 / _uSol[idx_set][0] > _settings->GetRealizableSetEpsilonU1() ) { // Danger Hardcoded - std::cout << "normU1 / _uSol[" << idx_set << "][0]: " << normU1 / _uSol[idx_set][0] << "\n"; - std::cout << "normU1: " << normU1 << " | _uSol[idx_set][0] " << _uSol[idx_set][0] << "\n"; - ErrorMessages::Error( "Moment to close to boundary of realizable set [code 1].\nBoundary ratio: " + - std::to_string( normU1 / _uSol[idx_set][0] ), - CURRENT_FUNCTION ); - } - if( normU1 / _uSol[idx_set][0] <= 0 /*+ 0.5 * epsilon*/ ) { - // std::cout << "_uSol" << _uSol[idx_set][1] << " | " << _uSol[idx_set][2] << " | " << _uSol[idx_set][3] << " \n"; - // std::cout << "normU1 / _uSol[" << idx_set << "][0]: " << normU1 / _uSol[idx_set][0] << "\n"; - // std::cout << "normU1: " << normU1 << " | _uSol[idx_set][0] " << _uSol[idx_set][0] << "\n"; - ErrorMessages::Error( "Moment to close to boundary of realizable set [code 2].\nBoundary ratio: " + - std::to_string( normU1 / _uSol[idx_set][0] ), - CURRENT_FUNCTION ); - } - } - } - } -} - -void nnDataGenerator::ComputeRealizableSolution() { -#pragma omp parallel for schedule( guided ) - for( unsigned idx_sol = 0; idx_sol < _setSize; idx_sol++ ) { - double entropyReconstruction = 0.0; - _uSol[idx_sol] = 0; - for( unsigned idx_quad = 0; idx_quad < _nq; idx_quad++ ) { - // Make entropyReconstruction a member vector, s.t. it does not have to be re-evaluated in ConstructFlux - entropyReconstruction = _entropy->EntropyPrimeDual( blaze::dot( _alpha[idx_sol], _moments[idx_quad] ) ); - _uSol[idx_sol] += _moments[idx_quad] * ( _weights[idx_quad] * entropyReconstruction ); - } - } -} -void nnDataGenerator::PrintLoadScreen() { - auto log = spdlog::get( "event" ); - log->info( "------------------------ Data Generation Starts --------------------------" ); - log->info( "| Generating {} datapoints.", _setSize ); -} - -void nnDataGenerator::ComputeSetSize() { - if( _LMaxDegree == 0 ) { - } - else if( _LMaxDegree == 1 ) { - // Sample points on unit sphere. - QuadratureBase* quad = QuadratureBase::Create( _settings ); - unsigned long nq = (unsigned long)quad->GetNq(); - - // Allocate memory. - _setSize = nq * _gridSize * ( _gridSize - 1 ) / 2; - - delete quad; - } - else if( _LMaxDegree == 2 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetDim() == 1 && - _settings->GetNormalizedSampling() ) { - // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 - unsigned c = 1; - double N1 = -1.0 + _settings->GetRealizableSetEpsilonU0(); - double N2; - double dN = 2.0 / (double)_gridSize; - while( N1 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { - N2 = N1 * N1 + _settings->GetRealizableSetEpsilonU0(); - while( N2 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { - c++; - N2 += dN; - } - N1 += dN; - } - _setSize = c; - } - else if( _LMaxDegree == 2 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetDim() == 1 && - !_settings->GetNormalizedSampling() ) { - unsigned c = 0; - double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; - - double u0 = _settings->GetRealizableSetEpsilonU0(); - double u1, u2; - double N1, N2; // helper - while( u0 < _settings->GetMaxValFirstMoment() ) { - u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); - N1 = u1 / u0; - if( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { - while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { - u2 = u1 * u1 / u0 + u0 * _settings->GetRealizableSetEpsilonU0(); - N2 = u2 / u0; - if( N2 < 1 - _settings->GetRealizableSetEpsilonU0() ) { - while( N2 < 1 - _settings->GetRealizableSetEpsilonU0() ) { - c++; - u2 += du; - N2 = u2 / u0; - } - } - u1 += du; - N1 = u1 / u0; - } - } - u0 += du; - } - _setSize = c; - } - else if( _LMaxDegree == 3 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetDim() == 1 && - !_settings->GetNormalizedSampling() ) { - // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 - unsigned c = 0; - double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; - double u0 = _settings->GetRealizableSetEpsilonU0(); - double u1, u2, u3; - double N1, N2, N3; // helper - while( u0 < _settings->GetMaxValFirstMoment() ) { - u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); - N1 = u1 / u0; - while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { - u2 = u1 * u1 / u0 + u0 * _settings->GetRealizableSetEpsilonU0(); - N2 = u2 / u0; - while( u2 < u0 - _settings->GetRealizableSetEpsilonU0() ) { - u3 = -u2 + u0 * ( N1 + N2 ) * ( N1 + N2 ) / ( 1 + N1 ) + u0 * _settings->GetRealizableSetEpsilonU0(); - N3 = u3 / u0; - while( N3 < N2 - ( N1 - N2 ) * ( N1 - N2 ) / ( 1 - N1 ) - _settings->GetRealizableSetEpsilonU0() ) { - u3 += du; - c++; - } - u2 += du; - N2 = u2 / u0; - } - u1 += du; - N1 = u1 / u0; - } - u0 += du; - } - _setSize = c; - } - else { - ErrorMessages::Error( "Sampling of training data of degree higher than 1 is not yet implemented.", CURRENT_FUNCTION ); - } -} diff --git a/code/src/toolboxes/datagenerator1D.cpp b/code/src/toolboxes/datagenerator1D.cpp new file mode 100644 index 0000000..9df797a --- /dev/null +++ b/code/src/toolboxes/datagenerator1D.cpp @@ -0,0 +1,264 @@ +/*! + * \file datagenerator1D.cpp + * \brief Class to generate data for the neural entropy closure + * \author S. Schotthoefer + */ + +#include "toolboxes/datagenerator1D.h" +#include "common/config.h" +#include "quadratures/quadraturebase.h" +#include "toolboxes/errormessages.h" +#include "toolboxes/sphericalbase.h" + +#include +#include + +DataGenerator1D::DataGenerator1D( Config* settings ) : DataGeneratorBase( settings ) { + ComputeMoments(); + + // Initialize Training Data + ComputeSetSize(); + + _uSol = VectorVector( _setSize, Vector( _nTotalEntries, 0.0 ) ); + _alpha = VectorVector( _setSize, Vector( _nTotalEntries, 0.0 ) ); + _hEntropy = std::vector( _setSize, 0.0 ); +} + +DataGenerator1D::~DataGenerator1D() {} + +void DataGenerator1D::ComputeMoments() { + double my, phi; + phi = 0; // placeholder. will not be used + + for( unsigned idx_quad = 0; idx_quad < _nq; idx_quad++ ) { + my = _quadPointsSphere[idx_quad][0]; + _moments[idx_quad] = _basis->ComputeSphericalBasis( my, phi ); + } +} + +void DataGenerator1D::SampleSolutionU() { + // Use necessary conditions from Monreal, Dissertation, Chapter 3.2.1, Page 26 + + // --- Determine stepsizes etc --- + + if( _LMaxDegree == 0 ) { + // --- sample u in order 0 --- + // u_0 = <1*psi> + double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; + + for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { + _uSol[idx_set][0] = du * idx_set; + } + } + else if( _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && !_settings->GetNormalizedSampling() ) { + if( _LMaxDegree == 1 ) { + unsigned c = 0; + double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; + + double u0 = _settings->GetRealizableSetEpsilonU0(); + double u1; + double N1; // helper + while( u0 < _settings->GetMaxValFirstMoment() ) { + u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N1 = u1 / u0; + while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + _uSol[c][0] = u0; // u0 by Monreals notation + _uSol[c][1] = u1; // u1 by Monreals notation + u1 += du; + N1 = u1 / u0; + c++; + } + u0 += du; + } + } + else if( _LMaxDegree == 2 ) { + unsigned c = 0; + double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; + + double u0 = _settings->GetRealizableSetEpsilonU0(); + double u1, u2; + double N1, N2; // helper + while( u0 < _settings->GetMaxValFirstMoment() ) { + u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N1 = u1 / u0; + while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + u2 = u1 * u1 / u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N2 = u2 / u0; + while( N2 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + _uSol[c][0] = u0; // u0 (normalized i.e. N0) by Monreals notation + _uSol[c][1] = u1; // u1 (normalized i.e. N1) by Monreals notation + _uSol[c][2] = u2; // u2 (normalized i.e. N2) by Monreals notation + u2 += du; + N2 = u2 / u0; + c++; + } + u1 += du; + N1 = u1 / u0; + } + u0 += du; + } + } + else if( _LMaxDegree == 3 ) { + unsigned c = 0; + double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; + double u0 = _settings->GetRealizableSetEpsilonU0(); + double u1, u2, u3; + double N1, N2, N3; // helper + while( u0 < _settings->GetMaxValFirstMoment() ) { + u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N1 = u1 / u0; + while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + u2 = u1 * u1 / u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N2 = u2 / u0; + while( u2 < u0 - _settings->GetRealizableSetEpsilonU0() ) { + u3 = -u2 + u0 * ( N1 + N2 ) * ( N1 + N2 ) / ( 1 + N1 ) + u0 * _settings->GetRealizableSetEpsilonU0(); + N3 = u3 / u0; + while( N3 < N2 - ( N1 - N2 ) * ( N1 - N2 ) / ( 1 - N1 ) - _settings->GetRealizableSetEpsilonU0() ) { + _uSol[c][0] = u0; // u0 by Monreals notation + _uSol[c][1] = u1; // u1 by Monreals notation + _uSol[c][2] = u2; // u2 by Monreals notation + _uSol[c][2] = u3; // u3 by Monreals notation + u3 += du; + N3 = u3 / u0; + c++; + } + u2 += du; + N2 = N3 / u0; + } + u1 += du; + N1 = u1 / u0; + } + u0 += du; + } + } + } + else if( _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetNormalizedSampling() ) { + if( _LMaxDegree == 2 ) { + // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 + unsigned c = 0; + double N1 = -1.0 + _settings->GetRealizableSetEpsilonU0(); + double N2; + double dN = 2.0 / (double)_gridSize; + while( N1 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { + N2 = N1 * N1 + _settings->GetRealizableSetEpsilonU0(); + while( N2 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { + _uSol[c][0] = 1; // u0 (normalized i.e. N0) by Monreals notation + _uSol[c][1] = N1; // u1 (normalized i.e. N1) by Monreals notation + _uSol[c][2] = N2; // u2 (normalized i.e. N2) by Monreals notation + N2 += dN; + c++; + } + N1 += dN; + } + } + } + else { + ErrorMessages::Error( "Sampling for this configuration is not yet supported", CURRENT_FUNCTION ); + } +} + +void DataGenerator1D::CheckRealizability() { + // Todo +} + +void DataGenerator1D::ComputeSetSize() { + if( _LMaxDegree == 0 ) { + } + else if( _LMaxDegree == 1 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && !_settings->GetNormalizedSampling() ) { + unsigned c = 0; + double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; + + double u0 = _settings->GetRealizableSetEpsilonU0(); + double u1; + double N1; // helper + while( u0 < _settings->GetMaxValFirstMoment() ) { + u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N1 = u1 / u0; + while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + u1 += du; + N1 = u1 / u0; + c++; + } + u0 += du; + } + _setSize = c; + } + else if( _LMaxDegree == 2 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && !_settings->GetNormalizedSampling() ) { + unsigned c = 0; + double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; + + double u0 = _settings->GetRealizableSetEpsilonU0(); + double u1, u2; + double N1, N2; // helper + while( u0 < _settings->GetMaxValFirstMoment() ) { + u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N1 = u1 / u0; + if( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + u2 = u1 * u1 / u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N2 = u2 / u0; + if( N2 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + while( N2 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + c++; + u2 += du; + N2 = u2 / u0; + } + } + u1 += du; + N1 = u1 / u0; + } + } + u0 += du; + } + _setSize = c; + } + else if( _LMaxDegree == 3 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && !_settings->GetNormalizedSampling() ) { + // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 + unsigned c = 0; + double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; + double u0 = _settings->GetRealizableSetEpsilonU0(); + double u1, u2, u3; + double N1, N2, N3; // helper + while( u0 < _settings->GetMaxValFirstMoment() ) { + u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N1 = u1 / u0; + while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + u2 = u1 * u1 / u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N2 = u2 / u0; + while( u2 < u0 - _settings->GetRealizableSetEpsilonU0() ) { + u3 = -u2 + u0 * ( N1 + N2 ) * ( N1 + N2 ) / ( 1 + N1 ) + u0 * _settings->GetRealizableSetEpsilonU0(); + N3 = u3 / u0; + while( N3 < N2 - ( N1 - N2 ) * ( N1 - N2 ) / ( 1 - N1 ) - _settings->GetRealizableSetEpsilonU0() ) { + u3 += du; + c++; + } + u2 += du; + N2 = u2 / u0; + } + u1 += du; + N1 = u1 / u0; + } + u0 += du; + } + _setSize = c; + } + else if( _LMaxDegree == 2 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetNormalizedSampling() ) { + // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 + unsigned c = 1; + double N1 = -1.0 + _settings->GetRealizableSetEpsilonU0(); + double N2; + double dN = 2.0 / (double)_gridSize; + while( N1 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { + N2 = N1 * N1 + _settings->GetRealizableSetEpsilonU0(); + while( N2 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { + c++; + N2 += dN; + } + N1 += dN; + } + _setSize = c; + } + else { + ErrorMessages::Error( "Sampling of training data of degree higher than 3 is not yet implemented.", CURRENT_FUNCTION ); + } +} diff --git a/code/src/toolboxes/datagenerator3D.cpp b/code/src/toolboxes/datagenerator3D.cpp new file mode 100644 index 0000000..d6e7df2 --- /dev/null +++ b/code/src/toolboxes/datagenerator3D.cpp @@ -0,0 +1,165 @@ +/*! + * \file datagenerator3D.cpp + * \brief Class to generate data for the neural entropy closure + * \author S. Schotthoefer + */ + +#include "toolboxes/datagenerator3D.h" +#include "common/config.h" +#include "quadratures/quadraturebase.h" +#include "toolboxes/errormessages.h" +#include "toolboxes/sphericalbase.h" + +#include +#include + +DataGenerator3D::DataGenerator3D( Config* settings ) : DataGeneratorBase( settings ) { + ComputeMoments(); + + // Initialize Training Data + ComputeSetSize(); + + _uSol = VectorVector( _setSize, Vector( _nTotalEntries, 0.0 ) ); + _alpha = VectorVector( _setSize, Vector( _nTotalEntries, 0.0 ) ); + _hEntropy = std::vector( _setSize, 0.0 ); +} + +DataGenerator3D::~DataGenerator3D() {} + +void DataGenerator3D::ComputeMoments() { + double my, phi; + + for( unsigned idx_quad = 0; idx_quad < _nq; idx_quad++ ) { + my = _quadPointsSphere[idx_quad][0]; + phi = _quadPointsSphere[idx_quad][1]; + _moments[idx_quad] = _basis->ComputeSphericalBasis( my, phi ); + } +} + +void DataGenerator3D::SampleSolutionU() { + // Use necessary conditions from Monreal, Dissertation, Chapter 3.2.1, Page 26 + + // --- Determine stepsizes etc --- + double du0 = _settings->GetMaxValFirstMoment() / (double)_gridSize; + + // different processes for different + if( _LMaxDegree == 0 ) { + // --- sample u in order 0 --- + // u_0 = <1*psi> + + for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { + _uSol[idx_set][0] = du0 * idx_set; + } + } + else if( _LMaxDegree == 1 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS ) { + // Sample points on unit sphere. + QuadratureBase* quad = QuadratureBase::Create( _settings ); + VectorVector qpoints = quad->GetPoints(); // carthesian coordinates. + unsigned long nq = (unsigned long)quad->GetNq(); + + // --- sample u in order 0 --- + // u_0 = <1*psi> + +#pragma omp parallel for schedule( guided ) + for( unsigned long idx_set = 0; idx_set < _gridSize; idx_set++ ) { + unsigned long outerIdx = ( idx_set - 1 ) * ( idx_set ) / 2; // sum over all radii up to current + outerIdx *= nq; // in each radius step, use all quad points + + // --- sample u in order 1 --- + /* order 1 has 3 elements. (omega_x, omega_y, omega_z) = omega, let u_1 = (u_x, u_y, u_z) = + * Condition u_0 >= norm(u_1) */ + double radiusU0 = du0 * ( idx_set + 1 ); + // Boundary correction + if( radiusU0 < _settings->GetRealizableSetEpsilonU0() ) { + radiusU0 = _settings->GetRealizableSetEpsilonU0(); // Boundary close to 0 + } + + unsigned long localIdx = 0; + double radius = 0.0; + unsigned long innerIdx = 0; + // loop over all radii + for( unsigned long idx_subset = 0; idx_subset < idx_set; idx_subset++ ) { + radius = du0 * ( idx_subset + 1 ); // dont use radius 0 ==> shift by one + // Boundary correction + if( radius < _settings->GetRealizableSetEpsilonU0() ) { + radius = _settings->GetRealizableSetEpsilonU0(); // Boundary close to 0 + } + if( radius / radiusU0 > 0.95 * _settings->GetRealizableSetEpsilonU1() ) { + // small offset to take care of rounding errors in quadrature + radius = radiusU0 * 0.95 * _settings->GetRealizableSetEpsilonU1(); // "outer" boundary + } + + localIdx = outerIdx + idx_subset * nq; + + for( unsigned long quad_idx = 0; quad_idx < nq; quad_idx++ ) { + innerIdx = localIdx + quad_idx; // gives the global index + + _uSol[innerIdx][0] = radiusU0; // Prevent 1st order moments to be too close to the boundary + // scale quadpoints with radius + _uSol[innerIdx][1] = radius * qpoints[quad_idx][0]; + _uSol[innerIdx][2] = radius * qpoints[quad_idx][1]; + _uSol[innerIdx][3] = radius * qpoints[quad_idx][2]; + } + } + } + } + else { + ErrorMessages::Error( "Sampling for this configuration is not yet supported", CURRENT_FUNCTION ); + } +} + +void DataGenerator3D::CheckRealizability() { + double epsilon = _settings->GetRealizableSetEpsilonU0(); + if( _LMaxDegree == 1 ) { +#pragma omp parallel for schedule( guided ) + for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { + double normU1 = 0.0; + Vector u1( 3, 0.0 ); + if( _uSol[idx_set][0] < epsilon ) { + if( std::abs( _uSol[idx_set][1] ) > 0 || std::abs( _uSol[idx_set][2] ) > 0 || std::abs( _uSol[idx_set][3] ) > 0 ) { + ErrorMessages::Error( "Moment not realizable [code 0]. Values: (" + std::to_string( _uSol[idx_set][0] ) + "|" + + std::to_string( _uSol[idx_set][1] ) + "|" + std::to_string( _uSol[idx_set][2] ) + "|" + + std::to_string( _uSol[idx_set][3] ) + ")", + CURRENT_FUNCTION ); + } + } + else { + u1 = { _uSol[idx_set][1], _uSol[idx_set][2], _uSol[idx_set][3] }; + normU1 = norm( u1 ); + if( normU1 / _uSol[idx_set][0] > _settings->GetRealizableSetEpsilonU1() ) { // Danger Hardcoded + std::cout << "normU1 / _uSol[" << idx_set << "][0]: " << normU1 / _uSol[idx_set][0] << "\n"; + std::cout << "normU1: " << normU1 << " | _uSol[idx_set][0] " << _uSol[idx_set][0] << "\n"; + ErrorMessages::Error( "Moment to close to boundary of realizable set [code 1].\nBoundary ratio: " + + std::to_string( normU1 / _uSol[idx_set][0] ), + CURRENT_FUNCTION ); + } + if( normU1 / _uSol[idx_set][0] <= 0 /*+ 0.5 * epsilon*/ ) { + // std::cout << "_uSol" << _uSol[idx_set][1] << " | " << _uSol[idx_set][2] << " | " << _uSol[idx_set][3] << " \n"; + // std::cout << "normU1 / _uSol[" << idx_set << "][0]: " << normU1 / _uSol[idx_set][0] << "\n"; + // std::cout << "normU1: " << normU1 << " | _uSol[idx_set][0] " << _uSol[idx_set][0] << "\n"; + ErrorMessages::Error( "Moment to close to boundary of realizable set [code 2].\nBoundary ratio: " + + std::to_string( normU1 / _uSol[idx_set][0] ), + CURRENT_FUNCTION ); + } + } + } + } +} + +void DataGenerator3D::ComputeSetSize() { + if( _LMaxDegree == 0 ) { + } + else if( _LMaxDegree == 1 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS ) { + // Sample points on unit sphere. + QuadratureBase* quad = QuadratureBase::Create( _settings ); + unsigned long nq = (unsigned long)quad->GetNq(); + + // Allocate memory. + _setSize = nq * _gridSize * ( _gridSize - 1 ) / 2; + + delete quad; + } + else { + ErrorMessages::Error( "Sampling of training data of degree higher than 1 is not yet implemented.", CURRENT_FUNCTION ); + } +} diff --git a/code/src/toolboxes/datageneratorbase.cpp b/code/src/toolboxes/datageneratorbase.cpp new file mode 100644 index 0000000..cb68730 --- /dev/null +++ b/code/src/toolboxes/datageneratorbase.cpp @@ -0,0 +1,167 @@ +/*! + * \file datagenerator.cpp + * \brief Class to generate data for the neural entropy closure + * \author S. Schotthoefer + */ + +#include "toolboxes/datageneratorbase.h" +#include "common/config.h" +#include "entropies/entropybase.h" +#include "optimizers/newtonoptimizer.h" +#include "quadratures/quadraturebase.h" +#include "spdlog/spdlog.h" +#include "toolboxes/datagenerator1D.h" +#include "toolboxes/datagenerator3D.h" +#include "toolboxes/errormessages.h" +#include "toolboxes/sphericalbase.h" + +#include + +DataGeneratorBase::DataGeneratorBase( Config* settings ) { + _settings = settings; + _setSize = settings->GetTrainingDataSetSize(); + _gridSize = _setSize; + + _LMaxDegree = settings->GetMaxMomentDegree(); + + // Check consistency between dimension of quadrature and sample basis + if( _settings->GetDim() == 1 ) { + if( _settings->GetQuadName() != QUAD_GaussLegendre1D && _settings->GetQuadName() != QUAD_GaussChebyshev1D ) { + ErrorMessages::Error( "For 1D Sampling, please choose a 1D quadrature rule.", CURRENT_FUNCTION ); + } + } + else { + if( _settings->GetQuadName() == QUAD_GaussLegendre1D || _settings->GetQuadName() == QUAD_GaussChebyshev1D ) { + ErrorMessages::Error( "For 3D Sampling, please choose a 3D quadrature rule.", CURRENT_FUNCTION ); + } + } + // Quadrature + _quadrature = QuadratureBase::Create( settings ); + _nq = _quadrature->GetNq(); + _quadPoints = _quadrature->GetPoints(); + _weights = _quadrature->GetWeights(); + _quadPointsSphere = _quadrature->GetPointsSphere(); + + // Spherical Harmonics + if( _settings->GetSphericalBasisName() == SPHERICAL_HARMONICS && _LMaxDegree > 0 ) { + ErrorMessages::Error( "No sampling algorithm for spherical harmonics basis with degree higher than 0 implemented", CURRENT_FUNCTION ); + } + _basis = SphericalBase::Create( _settings ); + + _nTotalEntries = _basis->GetBasisSize(); + + _moments = VectorVector( _nq, Vector( _nTotalEntries, 0.0 ) ); + + // Optimizer + _optimizer = new NewtonOptimizer( _settings ); + + // Entropy + _entropy = EntropyBase::Create( _settings ); +} + +DataGeneratorBase::~DataGeneratorBase() { + delete _quadrature; + delete _entropy; +} + +DataGeneratorBase* DataGeneratorBase::Create( Config* settings ) { + switch( settings->GetDim() ) { + case 1: return new DataGenerator1D( settings ); + case 2: ErrorMessages::Error( "2D Sampling is not yet supported.", CURRENT_FUNCTION ); + case 3: return new DataGenerator3D( settings ); + default: ErrorMessages::Error( "Sampling for more than 3 dimensions is not yet supported.", CURRENT_FUNCTION ); + } + return nullptr; +} + +void DataGeneratorBase::ComputeTrainingData() { + // Prototype: Only for _LMaxDegree == 1 + // Prototype: u is sampled from [0,100] + + // --- sample u --- + SampleSolutionU(); + + PrintLoadScreen(); + + // ---- Check realizability --- + CheckRealizability(); + // _uSol = VectorVector( 2, Vector( _nTotalEntries, 0.0 ) ); + // _alpha = VectorVector( 2, Vector( _nTotalEntries, 0.0 ) ); + // _uSol[0][0] = { 1, 1, 1 }; + + // --- compute alphas --- + _optimizer->SolveMultiCell( _alpha, _uSol, _moments ); + + // --- Postprocessing + ComputeRealizableSolution(); + + // --- compute entropy functional --- + ComputeEntropyH_primal(); + + // --- Print everything ---- + PrintTrainingData(); +} + +void DataGeneratorBase::ComputeEntropyH_dual() { +#pragma omp parallel for schedule( guided ) + for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { + _hEntropy[idx_set] = _optimizer->ComputeObjFunc( _alpha[idx_set], _uSol[idx_set], _moments ); + } +} + +void DataGeneratorBase::ComputeEntropyH_primal() { +#pragma omp parallel for schedule( guided ) + for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { + double result = 0.0; + // Integrate (eta(eta'_*(alpha*m)) + for( unsigned idx_quad = 0; idx_quad < _nq; idx_quad++ ) { + result += _entropy->Entropy( _entropy->EntropyPrimeDual( dot( _alpha[idx_set], _moments[idx_quad] ) ) ) * _weights[idx_quad]; + } + _hEntropy[idx_set] = result; + } +} + +void DataGeneratorBase::PrintTrainingData() { + auto log = spdlog::get( "event" ); + auto logCSV = spdlog::get( "tabular" ); + log->info( "---------------------- Data Generation Successful ------------------------" ); + + std::string uSolString = ""; + std::string alphaString = ""; + for( unsigned idx_sys = 0; idx_sys < _nTotalEntries; idx_sys++ ) { + uSolString += "u_" + std::to_string( idx_sys ) + ","; + alphaString += "alpha_" + std::to_string( idx_sys ) + ","; + } + // log->info( uSolString + alphaString + "h" ); + logCSV->info( uSolString + alphaString + "h" ); + + for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { + std::string uSolString = ""; + std::string alphaString = ""; + for( unsigned idx_sys = 0; idx_sys < _nTotalEntries; idx_sys++ ) { + uSolString += std::to_string( _uSol[idx_set][idx_sys] ) + ","; + alphaString += std::to_string( _alpha[idx_set][idx_sys] ) + ","; + } + // log->info( uSolString + alphaString + "{}", _hEntropy[idx_set] ); + logCSV->info( uSolString + alphaString + "{}", _hEntropy[idx_set] ); + } +} + +void DataGeneratorBase::ComputeRealizableSolution() { +#pragma omp parallel for schedule( guided ) + for( unsigned idx_sol = 0; idx_sol < _setSize; idx_sol++ ) { + double entropyReconstruction = 0.0; + _uSol[idx_sol] = 0; + for( unsigned idx_quad = 0; idx_quad < _nq; idx_quad++ ) { + // Make entropyReconstruction a member vector, s.t. it does not have to be re-evaluated in ConstructFlux + entropyReconstruction = _entropy->EntropyPrimeDual( blaze::dot( _alpha[idx_sol], _moments[idx_quad] ) ); + _uSol[idx_sol] += _moments[idx_quad] * ( _weights[idx_quad] * entropyReconstruction ); + } + } +} + +void DataGeneratorBase::PrintLoadScreen() { + auto log = spdlog::get( "event" ); + log->info( "------------------------ Data Generation Starts --------------------------" ); + log->info( "| Generating {} datapoints.", _setSize ); +} diff --git a/code/tests/test_cases.cpp b/code/tests/test_cases.cpp index a97fe49..39a60de 100644 --- a/code/tests/test_cases.cpp +++ b/code/tests/test_cases.cpp @@ -7,7 +7,7 @@ #include "common/config.h" #include "solvers/solverbase.h" -#include "toolboxes/datagenerator.h" +#include "toolboxes/datageneratorbase.h" using vtkUnstructuredGridReaderSP = vtkSmartPointer; @@ -370,7 +370,7 @@ TEST_CASE( "Test the Data Generator", "[dataGen]" ) { // Load Settings from File Config* config = new Config( config_file_name ); // Build Data generator - nnDataGenerator* datagen = new nnDataGenerator( config ); + DataGeneratorBase* datagen = DataGeneratorBase::Create( config ); // Generate Data and export datagen->ComputeTrainingData(); @@ -417,4 +417,6 @@ TEST_CASE( "Test the Data Generator", "[dataGen]" ) { count++; } REQUIRE( testPassed ); + + delete datagen; } -- GitLab From 90e14413dabbbf5fa36c2f70b8748b9bd0b29200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Wed, 24 Feb 2021 17:09:02 +0100 Subject: [PATCH 08/67] added nan check for 1D datagenerator (for h data) Former-commit-id: 88e04d634fdd08fc1c139590368997d76824c42b --- code/input/DataGenerator1D.cfg | 15 +++++++-------- code/src/toolboxes/datageneratorbase.cpp | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/code/input/DataGenerator1D.cfg b/code/input/DataGenerator1D.cfg index 04a9bcc..ea2cd46 100644 --- a/code/input/DataGenerator1D.cfg +++ b/code/input/DataGenerator1D.cfg @@ -1,17 +1,18 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Data Generator for % -% Neural Entropy Closure % +% 1D Data Generator for % +% Neural Entropy Closure % % Author % % Date 17.12.2020 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ---- Datagenerator settings ---- DATA_GENERATOR_MODE = YES -TRAINING_SET_SIZE = 500 -MAX_VALUE_FIRST_MOMENT = 1 +TRAINING_SET_SIZE = 5000 +MAX_VALUE_FIRST_MOMENT = 2 SPATIAL_DIM = 1 -REALIZABLE_SET_EPSILON_U0 = 0.001 +REALIZABLE_SET_EPSILON_U0 = 0.003 NORMALIZED_SAMPLING = NO +MAX_MOMENT_SOLVER = 1 % % ---- File specifications ---- % @@ -29,10 +30,8 @@ LOG_FILE = dataGen1D % Choice of basis functions SPHERICAL_BASIS = SPHERICAL_MONOMIALS % -% Maximal Moment degree -MAX_MOMENT_SOLVER = 1 -% % --- Entropy settings ---- +% ENTROPY_FUNCTIONAL = MAXWELL_BOLTZMANN ENTROPY_OPTIMIZER = NEWTON % diff --git a/code/src/toolboxes/datageneratorbase.cpp b/code/src/toolboxes/datageneratorbase.cpp index cb68730..b319d2d 100644 --- a/code/src/toolboxes/datageneratorbase.cpp +++ b/code/src/toolboxes/datageneratorbase.cpp @@ -15,6 +15,7 @@ #include "toolboxes/errormessages.h" #include "toolboxes/sphericalbase.h" +#include #include DataGeneratorBase::DataGeneratorBase( Config* settings ) { @@ -119,6 +120,25 @@ void DataGeneratorBase::ComputeEntropyH_primal() { } _hEntropy[idx_set] = result; } + + for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { + if( isnan( _hEntropy[idx_set] ) ) { + std::string msgU = "("; + std::string msgAlpha = "("; + for( unsigned idx_basis = 0; idx_basis < _nTotalEntries - 1; idx_basis++ ) { + msgU += std::to_string( _uSol[idx_set][idx_basis] ) + "|"; + msgAlpha += std::to_string( _alpha[idx_set][idx_basis] ) + "|"; + } + msgU += std::to_string( _uSol[idx_set][_nTotalEntries - 1] ) + ")"; + msgAlpha += std::to_string( _uSol[idx_set][_nTotalEntries - 1] ) + ")"; + + ErrorMessages::Error( "Value for h is NaN. This can happen near the boundary of the realizable set.\nu= " + msgU + + "\nalpha= " + msgAlpha + + "\nPlease adjust the Options " + "REALIZABLE_SET_EPSILON_U0 and REALIZABLE_SET_EPSILON_U1.", + CURRENT_FUNCTION ); + } + } } void DataGeneratorBase::PrintTrainingData() { -- GitLab From f84194ef2a881b3e9af3b71decb0869c23020739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Thu, 25 Feb 2021 21:51:31 +0100 Subject: [PATCH 09/67] added further tests and D1M3 sampling normalized Former-commit-id: 179b0459bc0271ec6419e7d238ed293e64bbbb7f --- code/include/optimizers/newtonoptimizer.h | 4 +- code/input/DataGenerator1D.cfg | 12 +- code/src/optimizers/newtonoptimizer.cpp | 75 +++++---- code/src/toolboxes/datagenerator1D.cpp | 195 +++++++++++++--------- code/src/toolboxes/datageneratorbase.cpp | 18 +- code/tests/test_sphericalBasis.cpp | 25 +++ 6 files changed, 205 insertions(+), 124 deletions(-) diff --git a/code/include/optimizers/newtonoptimizer.h b/code/include/optimizers/newtonoptimizer.h index 728911f..236aaf2 100644 --- a/code/include/optimizers/newtonoptimizer.h +++ b/code/include/optimizers/newtonoptimizer.h @@ -18,8 +18,8 @@ class NewtonOptimizer : public OptimizerBase ~NewtonOptimizer(); - void Solve( Vector& lambda, Vector& sol, const VectorVector& moments, unsigned idx_cell = 0 ) override; - void SolveMultiCell( VectorVector& lambda, VectorVector& sol, const VectorVector& moments ) override; + void Solve( Vector& alpha, Vector& sol, const VectorVector& moments, unsigned idx_cell = 0 ) override; + void SolveMultiCell( VectorVector& alpha, VectorVector& sol, const VectorVector& moments ) override; /*! @brief: Computes the objective function grad = - alpha*sol */ diff --git a/code/input/DataGenerator1D.cfg b/code/input/DataGenerator1D.cfg index ea2cd46..963f0e0 100644 --- a/code/input/DataGenerator1D.cfg +++ b/code/input/DataGenerator1D.cfg @@ -2,17 +2,18 @@ % 1D Data Generator for % % Neural Entropy Closure % % Author % -% Date 17.12.2020 % +% Date 17.02.2021 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ---- Datagenerator settings ---- DATA_GENERATOR_MODE = YES -TRAINING_SET_SIZE = 5000 -MAX_VALUE_FIRST_MOMENT = 2 +TRAINING_SET_SIZE = 100 +MAX_VALUE_FIRST_MOMENT = 1 SPATIAL_DIM = 1 +REALIZABLE_SET_EPSILON_U1 = 0.003 REALIZABLE_SET_EPSILON_U0 = 0.003 NORMALIZED_SAMPLING = NO -MAX_MOMENT_SOLVER = 1 +MAX_MOMENT_SOLVER = 3 % % ---- File specifications ---- % @@ -48,5 +49,6 @@ NEWTON_LINE_SEARCH_ITER = 100000 % Quadrature Rule QUAD_TYPE = GAUSS_LEGENDRE_1D % Quadrature Order -QUAD_ORDER = 200 +%QUAD_ORDER = 200 +QUAD_ORDER = 100 % diff --git a/code/src/optimizers/newtonoptimizer.cpp b/code/src/optimizers/newtonoptimizer.cpp index 104b59d..1050c27 100644 --- a/code/src/optimizers/newtonoptimizer.cpp +++ b/code/src/optimizers/newtonoptimizer.cpp @@ -68,25 +68,28 @@ void NewtonOptimizer::ComputeHessian( Vector& alpha, const VectorVector& moments } } -void NewtonOptimizer::SolveMultiCell( VectorVector& lambda, VectorVector& sol, const VectorVector& moments ) { +void NewtonOptimizer::SolveMultiCell( VectorVector& alpha, VectorVector& sol, const VectorVector& moments ) { - unsigned nCells = lambda.size(); + unsigned nCells = alpha.size(); // if we have quadratic entropy, then alpha = u; if( _settings->GetEntropyName() == QUADRATIC && _settings->GetNewtonFastMode() ) { for( unsigned idx_cell = 0; idx_cell < nCells; idx_cell++ ) { - lambda[idx_cell] = sol[idx_cell]; + alpha[idx_cell] = sol[idx_cell]; } return; } #pragma omp parallel for schedule( guided ) for( unsigned idx_cell = 0; idx_cell < nCells; idx_cell++ ) { - Solve( lambda[idx_cell], sol[idx_cell], moments, idx_cell ); + Solve( alpha[idx_cell], sol[idx_cell], moments, idx_cell ); + // if( idx_cell % 10000 == 0 ) { + // printf( "%d\n", idx_cell ); + //} } } -void NewtonOptimizer::Solve( Vector& lambda, Vector& sol, const VectorVector& moments, unsigned idx_cell ) { +void NewtonOptimizer::Solve( Vector& alpha, Vector& sol, const VectorVector& moments, unsigned idx_cell ) { /* solve the problem argmin ( -alpha*u)) * where alpha = Lagrange multiplier @@ -96,18 +99,18 @@ void NewtonOptimizer::Solve( Vector& lambda, Vector& sol, const VectorVector& mo // if we have quadratic entropy, then alpha = u; if( _settings->GetEntropyName() == QUADRATIC && _settings->GetNewtonFastMode() ) { - lambda = sol; + alpha = sol; return; } // Start Newton Algorithm - unsigned nSize = lambda.size(); + unsigned nSize = alpha.size(); Vector grad( nSize, 0.0 ); // check if initial guess is good enough - ComputeGradient( lambda, sol, moments, grad ); + ComputeGradient( alpha, sol, moments, grad ); if( norm( grad ) < _epsilon ) { return; @@ -117,60 +120,60 @@ void NewtonOptimizer::Solve( Vector& lambda, Vector& sol, const VectorVector& mo Matrix H( nSize, nSize, 0.0 ); // calculate initial Hessian and gradient - Vector dlambda = -grad; - ComputeHessian( lambda, moments, H ); + Vector dalpha = -grad; + ComputeHessian( alpha, moments, H ); // invert Hessian invert( H ); if( _maxIterations == 1 ) { - lambda = lambda - _alpha * H * grad; + alpha = alpha - _alpha * H * grad; return; } - Vector lambdaNew( nSize, 0.0 ); // New newton step - Vector dlambdaNew( nSize ); // Gradient at New newton step + Vector alphaNew( nSize, 0.0 ); // New newton step + Vector dalphaNew( nSize ); // Gradient at New newton step - lambdaNew = lambda - _alpha * H * grad; + alphaNew = alpha - _alpha * H * grad; // Compute Gradient of new point; - ComputeGradient( lambdaNew, sol, moments, dlambdaNew ); + ComputeGradient( alphaNew, sol, moments, dalphaNew ); // perform Newton iterations for( unsigned l = 0; l < _maxIterations; ++l ) { double stepSize = 1.0; if( l != 0 ) { - ComputeGradient( lambda, sol, moments, grad ); + ComputeGradient( alpha, sol, moments, grad ); - dlambda = -grad; - ComputeHessian( lambda, moments, H ); + dalpha = -grad; + ComputeHessian( alpha, moments, H ); invert( H ); - lambdaNew = lambda - _alpha * H * grad; - ComputeGradient( lambdaNew, sol, moments, dlambdaNew ); + alphaNew = alpha - _alpha * H * grad; + ComputeGradient( alphaNew, sol, moments, dalphaNew ); } // Line Search int lineSearchCounter = 0; - while( norm( dlambda ) < norm( dlambdaNew ) || !std::isfinite( norm( dlambdaNew ) ) ) { + while( norm( dalpha ) < norm( dalphaNew ) || !std::isfinite( norm( dalphaNew ) ) ) { stepSize *= 0.5; - lambdaNew = lambda - stepSize * _alpha * H * grad; - ComputeGradient( lambdaNew, sol, moments, dlambdaNew ); + alphaNew = alpha - stepSize * _alpha * H * grad; + ComputeGradient( alphaNew, sol, moments, dalphaNew ); // Check if FONC is fullfilled - if( norm( dlambdaNew ) < _epsilon ) { - lambda = lambdaNew; + if( norm( dalphaNew ) < _epsilon ) { + alpha = alphaNew; return; } else if( ++lineSearchCounter > _maxLineSearches ) { ErrorMessages::Error( "Newton needed too many refinement steps! at cell " + std::to_string( idx_cell ), CURRENT_FUNCTION ); } } - lambda = lambdaNew; - if( norm( dlambdaNew ) < _epsilon ) { - lambda = lambdaNew; + alpha = alphaNew; + if( norm( dalphaNew ) < _epsilon ) { + alpha = alphaNew; return; } } @@ -180,10 +183,14 @@ void NewtonOptimizer::Solve( Vector& lambda, Vector& sol, const VectorVector& mo } uSolString += ")."; - Vector u1 = { sol[1], sol[2], sol[3] }; - double normU1 = norm( u1 ); - ErrorMessages::Error( "Newton did not converge at cell " + std::to_string( idx_cell ) + "\n" + uSolString + - "\nNorm of gradient: " + std::to_string( norm( dlambdaNew ) ) + "\nObjective function value: " + - std::to_string( ComputeObjFunc( lambda, sol, moments ) ) + "\nBoundary Ratio: " + std::to_string( normU1 / sol[0] ), - CURRENT_FUNCTION ); + if( _settings->GetDim() != 1 ) { + Vector u1 = { sol[1], sol[2], sol[3] }; + double normU1 = norm( u1 ); + ErrorMessages::Error( "Newton did not converge at cell " + std::to_string( idx_cell ) + "\n" + uSolString + + "\nNorm of gradient: " + std::to_string( norm( dalphaNew ) ) + "\nObjective function value: " + + std::to_string( ComputeObjFunc( alpha, sol, moments ) ) + "\nBoundary Ratio: " + std::to_string( normU1 / sol[0] ), + CURRENT_FUNCTION ); + } + if( _settings->GetDim() == 1 ) { + } } diff --git a/code/src/toolboxes/datagenerator1D.cpp b/code/src/toolboxes/datagenerator1D.cpp index 9df797a..166d6b1 100644 --- a/code/src/toolboxes/datagenerator1D.cpp +++ b/code/src/toolboxes/datagenerator1D.cpp @@ -58,6 +58,7 @@ void DataGenerator1D::SampleSolutionU() { double u0 = _settings->GetRealizableSetEpsilonU0(); double u1; double N1; // helper + // for( double u0 = _settings->GetRealizableSetEpsilonU0(); u0 < _settings->GetMaxValFirstMoment(); u0 += du ) { while( u0 < _settings->GetMaxValFirstMoment() ) { u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); N1 = u1 / u0; @@ -111,16 +112,16 @@ void DataGenerator1D::SampleSolutionU() { u2 = u1 * u1 / u0 + u0 * _settings->GetRealizableSetEpsilonU0(); N2 = u2 / u0; while( u2 < u0 - _settings->GetRealizableSetEpsilonU0() ) { - u3 = -u2 + u0 * ( N1 + N2 ) * ( N1 + N2 ) / ( 1 + N1 ) + u0 * _settings->GetRealizableSetEpsilonU0(); + u3 = -u2 + u0 * ( N1 + N2 ) * ( N1 + N2 ) / ( 1 + N1 ) + u0 * _settings->GetRealizableSetEpsilonU1(); N3 = u3 / u0; - while( N3 < N2 - ( N1 - N2 ) * ( N1 - N2 ) / ( 1 - N1 ) - _settings->GetRealizableSetEpsilonU0() ) { + while( N3 < N2 - ( N1 - N2 ) * ( N1 - N2 ) / ( 1 - N1 ) - _settings->GetRealizableSetEpsilonU1() ) { _uSol[c][0] = u0; // u0 by Monreals notation _uSol[c][1] = u1; // u1 by Monreals notation _uSol[c][2] = u2; // u2 by Monreals notation - _uSol[c][2] = u3; // u3 by Monreals notation + _uSol[c][3] = u3; // u3 by Monreals notation + c++; u3 += du; N3 = u3 / u0; - c++; } u2 += du; N2 = N3 / u0; @@ -151,6 +152,26 @@ void DataGenerator1D::SampleSolutionU() { N1 += dN; } } + if( _LMaxDegree == 3 ) { + // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1, N1=0 + unsigned c = 0; + double N1 = 0 + _settings->GetRealizableSetEpsilonU0(); + double N2, N3; + double dN = 1.0 / (double)_gridSize; + N2 = N1 * N1 + _settings->GetRealizableSetEpsilonU0(); + while( N2 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { + N3 = -N2 + ( N1 + N2 ) * ( N1 + N2 ) / ( 1 + N1 ) + _settings->GetRealizableSetEpsilonU1(); + while( N3 < N2 - ( N1 - N2 ) * ( N1 - N2 ) / ( 1 - N1 ) - _settings->GetRealizableSetEpsilonU1() ) { + _uSol[c][0] = 1; // u0 by Monreals notation + _uSol[c][1] = N1; // u1 by Monreals notation + _uSol[c][2] = N2; // u2 by Monreals notation + _uSol[c][3] = N3; // u3 by Monreals notation + c++; + N3 += dN; + } + N2 += dN; + } + } } else { ErrorMessages::Error( "Sampling for this configuration is not yet supported", CURRENT_FUNCTION ); @@ -164,101 +185,123 @@ void DataGenerator1D::CheckRealizability() { void DataGenerator1D::ComputeSetSize() { if( _LMaxDegree == 0 ) { } - else if( _LMaxDegree == 1 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && !_settings->GetNormalizedSampling() ) { - unsigned c = 0; - double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; + else if( _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && !_settings->GetNormalizedSampling() ) { + if( _LMaxDegree == 1 ) { + unsigned c = 0; + double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; - double u0 = _settings->GetRealizableSetEpsilonU0(); - double u1; - double N1; // helper - while( u0 < _settings->GetMaxValFirstMoment() ) { - u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); - N1 = u1 / u0; - while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { - u1 += du; + double u0 = _settings->GetRealizableSetEpsilonU0(); + double u1; + double N1; // helper + while( u0 < _settings->GetMaxValFirstMoment() ) { + u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); N1 = u1 / u0; - c++; + while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + u1 += du; + N1 = u1 / u0; + c++; + } + u0 += du; } - u0 += du; + _setSize = c; } - _setSize = c; - } - else if( _LMaxDegree == 2 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && !_settings->GetNormalizedSampling() ) { - unsigned c = 0; - double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; + else if( _LMaxDegree == 2 ) { + unsigned c = 0; + double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; - double u0 = _settings->GetRealizableSetEpsilonU0(); - double u1, u2; - double N1, N2; // helper - while( u0 < _settings->GetMaxValFirstMoment() ) { - u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); - N1 = u1 / u0; - if( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + double u0 = _settings->GetRealizableSetEpsilonU0(); + double u1, u2; + double N1, N2; // helper + while( u0 < _settings->GetMaxValFirstMoment() ) { + u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N1 = u1 / u0; + if( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + u2 = u1 * u1 / u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N2 = u2 / u0; + if( N2 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + while( N2 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + c++; + u2 += du; + N2 = u2 / u0; + } + } + u1 += du; + N1 = u1 / u0; + } + } + u0 += du; + } + _setSize = c; + } + else if( _LMaxDegree == 3 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && !_settings->GetNormalizedSampling() ) { + // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 + unsigned c = 0; + double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; + double u0 = _settings->GetRealizableSetEpsilonU0(); + double u1, u2, u3; + double N1, N2, N3; // helper + while( u0 < _settings->GetMaxValFirstMoment() ) { + u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); + N1 = u1 / u0; while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { u2 = u1 * u1 / u0 + u0 * _settings->GetRealizableSetEpsilonU0(); N2 = u2 / u0; - if( N2 < 1 - _settings->GetRealizableSetEpsilonU0() ) { - while( N2 < 1 - _settings->GetRealizableSetEpsilonU0() ) { + while( u2 < u0 - _settings->GetRealizableSetEpsilonU0() ) { + u3 = -u2 + u0 * ( N1 + N2 ) * ( N1 + N2 ) / ( 1 + N1 ) + u0 * _settings->GetRealizableSetEpsilonU1(); + N3 = u3 / u0; + while( N3 < N2 - ( N1 - N2 ) * ( N1 - N2 ) / ( 1 - N1 ) - _settings->GetRealizableSetEpsilonU1() ) { + u3 += du; + N3 = u3 / u0; c++; - u2 += du; - N2 = u2 / u0; } + u2 += du; + N2 = u2 / u0; } u1 += du; N1 = u1 / u0; } + u0 += du; } - u0 += du; + _setSize = c; } - _setSize = c; } - else if( _LMaxDegree == 3 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && !_settings->GetNormalizedSampling() ) { - // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 - unsigned c = 0; - double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; - double u0 = _settings->GetRealizableSetEpsilonU0(); - double u1, u2, u3; - double N1, N2, N3; // helper - while( u0 < _settings->GetMaxValFirstMoment() ) { - u1 = -u0 + u0 * _settings->GetRealizableSetEpsilonU0(); - N1 = u1 / u0; - while( N1 < 1 - _settings->GetRealizableSetEpsilonU0() ) { - u2 = u1 * u1 / u0 + u0 * _settings->GetRealizableSetEpsilonU0(); - N2 = u2 / u0; - while( u2 < u0 - _settings->GetRealizableSetEpsilonU0() ) { - u3 = -u2 + u0 * ( N1 + N2 ) * ( N1 + N2 ) / ( 1 + N1 ) + u0 * _settings->GetRealizableSetEpsilonU0(); - N3 = u3 / u0; - while( N3 < N2 - ( N1 - N2 ) * ( N1 - N2 ) / ( 1 - N1 ) - _settings->GetRealizableSetEpsilonU0() ) { - u3 += du; - c++; - } - u2 += du; - N2 = u2 / u0; + else if( _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetNormalizedSampling() ) { + if( _LMaxDegree == 2 ) { + // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 + unsigned c = 1; + double N1 = -1.0 + _settings->GetRealizableSetEpsilonU0(); + double N2; + double dN = 2.0 / (double)_gridSize; + while( N1 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { + N2 = N1 * N1 + _settings->GetRealizableSetEpsilonU0(); + while( N2 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { + c++; + N2 += dN; } - u1 += du; - N1 = u1 / u0; + N1 += dN; } - u0 += du; + _setSize = c; } - _setSize = c; - } - else if( _LMaxDegree == 2 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetNormalizedSampling() ) { - // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 - unsigned c = 1; - double N1 = -1.0 + _settings->GetRealizableSetEpsilonU0(); - double N2; - double dN = 2.0 / (double)_gridSize; - while( N1 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { - N2 = N1 * N1 + _settings->GetRealizableSetEpsilonU0(); + if( _LMaxDegree == 3 ) { + // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1, N1=0 + unsigned c = 1; + double N1 = 0 + _settings->GetRealizableSetEpsilonU0(); + double N2, N3; + double dN = 1.0 / (double)_gridSize; + N2 = N1 * N1 + _settings->GetRealizableSetEpsilonU0(); while( N2 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { - c++; + N3 = -N2 + ( N1 + N2 ) * ( N1 + N2 ) / ( 1 + N1 ) + _settings->GetRealizableSetEpsilonU1(); + while( N3 < N2 - ( N1 - N2 ) * ( N1 - N2 ) / ( 1 - N1 ) - _settings->GetRealizableSetEpsilonU1() ) { + c++; + N3 += dN; + } N2 += dN; } - N1 += dN; + _setSize = c; + } + else { + ErrorMessages::Error( "Sampling of training data of degree higher than 3 is not yet implemented.", CURRENT_FUNCTION ); } - _setSize = c; - } - else { - ErrorMessages::Error( "Sampling of training data of degree higher than 3 is not yet implemented.", CURRENT_FUNCTION ); } } diff --git a/code/src/toolboxes/datageneratorbase.cpp b/code/src/toolboxes/datageneratorbase.cpp index b319d2d..daa28a5 100644 --- a/code/src/toolboxes/datageneratorbase.cpp +++ b/code/src/toolboxes/datageneratorbase.cpp @@ -14,6 +14,7 @@ #include "toolboxes/datagenerator3D.h" #include "toolboxes/errormessages.h" #include "toolboxes/sphericalbase.h" +#include "toolboxes/textprocessingtoolbox.h" #include #include @@ -76,29 +77,32 @@ DataGeneratorBase* DataGeneratorBase::Create( Config* settings ) { } void DataGeneratorBase::ComputeTrainingData() { - // Prototype: Only for _LMaxDegree == 1 - // Prototype: u is sampled from [0,100] + PrintLoadScreen(); // --- sample u --- SampleSolutionU(); - - PrintLoadScreen(); + auto log = spdlog::get( "event" ); + log->info( "| Moments sampled." ); + log->info( "| Start solving the optimization problems. This may take some minutes." ); // ---- Check realizability --- CheckRealizability(); - // _uSol = VectorVector( 2, Vector( _nTotalEntries, 0.0 ) ); - // _alpha = VectorVector( 2, Vector( _nTotalEntries, 0.0 ) ); - // _uSol[0][0] = { 1, 1, 1 }; // --- compute alphas --- _optimizer->SolveMultiCell( _alpha, _uSol, _moments ); + log->info( "| Making moments realizable problems." ); + // --- Postprocessing ComputeRealizableSolution(); + log->info( "| Compute entropies." ); + // --- compute entropy functional --- ComputeEntropyH_primal(); + log->info( "| Print Solution." ); + // --- Print everything ---- PrintTrainingData(); } diff --git a/code/tests/test_sphericalBasis.cpp b/code/tests/test_sphericalBasis.cpp index dc33c9e..4d829d3 100644 --- a/code/tests/test_sphericalBasis.cpp +++ b/code/tests/test_sphericalBasis.cpp @@ -252,6 +252,11 @@ double SphericalMonomial_7( double my, double phi ) { return Omega_xBase( my, ph double SphericalMonomial_8( double my, double phi ) { return Omega_xBase( my, phi ) * Omega_yBase( my, phi ); } // omega_x*omega_y double SphericalMonomial_9( double my, double phi ) { return Omega_xBase( my, phi ) * Omega_xBase( my, phi ); } // omega_x^2 +double SphericalMonomial_10( double my, double /*phi*/ ) { return Omega_zBase( my ) * Omega_zBase( my ) * Omega_zBase( my ); } // omega_z^3 +double SphericalMonomial_11( double my, double /*phi*/ ) { + return Omega_zBase( my ) * Omega_zBase( my ) * Omega_zBase( my ) * Omega_zBase( my ); +} // omega_z^4 + TEST_CASE( "test spherical monomial basis", "[spherical_monomials]" ) { unsigned maxMomentDegree = 2; //==> 6+3+1 basis functions SphericalMonomials testBase( maxMomentDegree ); // Default constructor => _spatialDim = 3 @@ -379,4 +384,24 @@ TEST_CASE( "test spherical monomial basis", "[spherical_monomials]" ) { REQUIRE( std::all_of( validMoment.begin(), validMoment.end(), []( bool v ) { return v; } ) ); } + + SphericalMonomials testBase1D_M4( 4, 1 ); + SECTION( "Test against analytical solution Dim 1 M4" ) { + Vector moment; + std::vector validMoment( 3, true ); + for( double my = -1.0; my < 1.0; my += 0.1 ) { + + for( double phi = 0.0; phi < 2 * M_PI; phi += 0.1 ) { + moment = testBase1D_M4.ComputeSphericalBasis( my, phi ); + + if( std::fabs( moment[0] - SphericalMonomial_0( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[0] = false; + if( std::fabs( moment[1] - SphericalMonomial_1( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[1] = false; + if( std::fabs( moment[2] - SphericalMonomial_4( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[2] = false; + if( std::fabs( moment[3] - SphericalMonomial_10( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[3] = false; + if( std::fabs( moment[4] - SphericalMonomial_11( my, phi ) ) > 1e2 * std::numeric_limits::epsilon() ) validMoment[4] = false; + } + } + + REQUIRE( std::all_of( validMoment.begin(), validMoment.end(), []( bool v ) { return v; } ) ); + } } -- GitLab From d8d7e3c27c8f55117560db9670884bfa141f32d6 Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 09:46:12 +0100 Subject: [PATCH 10/67] Test subtitle Former-commit-id: 9eef9e31bf49d10a2685e2f3877546eed2e4d6bf --- doc/physics.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/physics.rst b/doc/physics.rst index 64668d9..f2f33f4 100644 --- a/doc/physics.rst +++ b/doc/physics.rst @@ -79,3 +79,7 @@ the two-body collision results in nonlinear Boltzmann equation Q(f)=\int_{\mathbb R^3} \int_{\mathcal S^2} \mathcal B(\cos \beta, |\mathbf{v}-\mathbf{v_*}|) \left[ f(\mathbf v')f(\mathbf v_*')-f(\mathbf v)f(\mathbf v_*)\right] d\mathbf \Omega d\mathbf v_* + + +The continuous slowing down approximation +--------- \ No newline at end of file -- GitLab From 783bc285c7f1f1b0decfcc4b5a5d7d2d642ae658 Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 09:57:57 +0100 Subject: [PATCH 11/67] Add csd content Former-commit-id: 787607a7399cc9bb242e0c91efaf2f3c60f19b9c --- doc/physics.rst | 128 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 1 deletion(-) diff --git a/doc/physics.rst b/doc/physics.rst index f2f33f4..4c3a1b6 100644 --- a/doc/physics.rst +++ b/doc/physics.rst @@ -82,4 +82,130 @@ the two-body collision results in nonlinear Boltzmann equation The continuous slowing down approximation ---------- \ No newline at end of file +--------- + +Our main goal is to compute the radiation dose +\begin{align} + D(x)=\frac{1}{\rho(x)}\int_0^{\infty}\int_{\mathbb{S}^2}S(E,x)\psi(E,x,\Omega)\,d\Omega dE. +\end{align} +The angular flux $\psi$ can be approximated by the continuous slowing down (CSD) equation, which reads +\begin{align} + -\partial_E\left(S(E,x)\psi(E,x,\Omega)\right)+\Omega\cdot\nabla_x\psi(E,x,\Omega)+\Sigma_t(E,x)\psi(E,x,\Omega) = \int_{\mathbb{S}^2}\Sigma_s(E,x,\Omega\cdot\Omega')\psi(E,x,\Omega')d\Omega'. +\end{align} +Here $E\in\mathbb{R}_+$ is energy, $x\in D\subset \mathbb{R}^3$ is the spatial domain and $\Omega\in\mathbb{S}^2$ is the direction of travel. The stopping power $S$ is given by +\begin{align} + S(E,x) = \int_0^{\infty} E'\int_{-1}^1\Sigma(E,E',x,\mu)d\mu dE'. +\end{align} +Since there are no absorption effects, the total cross section is given by +\begin{align} + \Sigma_t(E,x) = \Sigma_{s,0}(E,x)=2\pi \int_{-1}^1\Sigma_s(E,x,\mu)d\mu. +\end{align} +\jknote{We can double check this in our code.} +\jknote{Check if we need to transform when intgrating w.r.t. $\mu$ instead of $\Omega'$.} +\txnote{Why the integral deduces from $\Omega$ to $\mu$ automatically?} +\ssnote{Fixed that issue} +With a given background material density $\rho(x)$ now make the following assumptions +\begin{align} + S(E,x) = S^{H_2O}(E)\rho(x), \\ + \Sigma_t(E,x) = \Sigma_t^{H_2O}(E)\rho(x), \\ + \Sigma_s(E,x,\Omega\cdot\Omega') = \Sigma_s(E,\Omega\cdot\Omega')\rho(x). +\end{align} +Leaving out the superscript $H_2O$, the CSD equation simplifies to +\begin{align}\label{eq:CSD2} + -\partial_E\left(\rho(x)S(E)\psi(E,x,\Omega)\right)+\Omega\cdot\nabla_x\psi(E,x,\Omega)+\rho(x)\Sigma_t(E)\psi(E,x,\Omega) = \int_{\mathbb{S}^2}\rho(x)\Sigma_s(E,\Omega\cdot\Omega')\psi(E,x,\Omega')d\Omega'. +\end{align} +Now, we bring this system in a form which resembles the standard Boltzmann equation. Multiplying \eqref{eq:CSD2} with $S(E)$ gives +\begin{subequations}\label{eq:CSD3} +\begin{align} + -S(E)\partial_E\left(S(E)\rho(x)\psi(E,x,\Omega)\right)+&\Omega\cdot\nabla_x S(E)\psi(E,x,\Omega)+\Sigma_t(E)S(E)\rho(x)\psi(E,x,\Omega)\\ + &= \int_{\mathbb{S}^2}\Sigma_s(E,\Omega\cdot\Omega')S(E)\rho(x)\psi(E,x,\Omega')d\Omega'. +\end{align} +\end{subequations} +Then, we substitute +\begin{align} + \widehat{\psi}(E,x,\Omega):= S(E)\rho(x)\psi(E,x,\Omega) +\end{align} +into \eqref{eq:CSD3}, which yields +\begin{align}\label{eq:CSD4} + -S(E)\partial_E\widehat{\psi}(E,x,\Omega)+\Omega\cdot\nabla_x \frac{\widehat{\psi}(E,x,\Omega)}{\rho}+\Sigma_t(E)\widehat{\psi}(E,x,\Omega) = \int_{\mathbb{S}^2}\Sigma_s(E,\Omega\cdot\Omega')\widehat{\psi}(E,x,\Omega')d\Omega'. +\end{align} +Now, to get rid of the stopping power in front of the energy derivative, we make use of the transformation +\begin{align}\label{eq:TildeE} + \widetilde{E}(E) = \int_0^E \frac{1}{S(E')}\,dE'. +\end{align} +Now let us change to +\begin{align} + \widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) := \widehat{\psi}(E(\widetilde E),x,\Omega) +\end{align} +In this case, the energy derivative becomes +\begin{align*} + \partial_{\widetilde{E}}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) = \partial_{E}\widetilde{\widehat{\psi}}( E,x,\Omega)\partial_{\widetlde E }E(\widetilde E(\widetilde E) = \partial_{ E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega){S(E(\widetilde E))}. +\end{align*} +And by rearranging the terms, we finally get +\begin{align*} + \partial_{ E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) = \partial_{\widetilde{E}}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)\frac{1}{S(E(\widetilde E))}, +\end{align*} +since $S(E(\widetilde E))$ is nonzero \ssnote{Is S always nonzero? Would make sense, physically.}. +Therefore, substituting $\widetilde E$ in \eqref{eq:CSD4} gives +\begin{align}\label{eq:CSD5} + -\partial_{\widetilde E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)+\Omega\cdot\nabla_x \frac{\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)}{\rho}+\widetilde\Sigma_t(\widetilde E)\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) = \int_{\mathbb{S}^2}\widetilde\Sigma_s(\widetilde E,\Omega\cdot\Omega')\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega')d\Omega'. +\end{align} +Here, we define $\widetilde\Sigma_{t}(\widetilde E):=\Sigma_t(E(\widetilde E))$ and $\widetilde\Sigma_{s}(\widetilde E,\Omega\cdot\Omega'):=\Sigma_s(E(\widetilde E),\Omega\cdot\Omega')$. Finally, to obtain a positive sign in front of the energy derivative, we transform to +\begin{align} + \bar{E}(\widetilde{E}) = \widetilde{E}_{\text{max}}-\widetilde{E}. +\end{align} +Then, with $\bar{\psi}(\bar{E},x,\Omega):=\widetilde{\widehat{\psi}}(\widetilde{E}(\bar{E}),x,\Omega)$ and $\bar\Sigma_{t}(\bar E):=\widetilde{\Sigma}_t(\widetilde{E}(\bar{E}))$ as well as $\bar\Sigma_{s}(\bar E,\Omega\cdot\Omega'):=\widetilde{\Sigma}_s(\widetilde{E}(\bar{E}),\Omega\cdot\Omega')$ equation \eqref{eq:CSD4} becomes +\begin{align}\label{eq:CSD5} + \partial_{\bar{E}}\bar{\psi}(\bar{E},x,\Omega)+\Omega\cdot\nabla_x \frac{\bar{\psi}(\bar{E},x,\Omega)}{\rho}+\bar\Sigma_t(\bar E)\bar{\psi}(\bar{E},x,\Omega) = \int_{\mathbb{S}^2}\bar\Sigma_s(\bar{E},\Omega\cdot\Omega')\bar{\psi}(\bar{E},x,\Omega')d\Omega'. +\end{align} +Dropping the bar notation and treating $\bar E$ as a pseudo-time $t$ gives a slightly modified version of the Boltzmann equation +\begin{align}\label{eq:CSDBoltzmann} + \partial_{t}\psi(t,x,\Omega)+&\Omega\cdot\nabla_x \frac{\psi(t,x,\Omega)}{\rho}+\Sigma_t(t)\psi(t,x,\Omega) = \int_{\mathbb{S}^2}\Sigma_s(t,\Omega\cdot\Omega')\psi(t,x,\Omega')d\Omega'\\ + &\psi(t=0,x,\Omega) = S(E_{\text{max}})\rho(x)\psi(E_{\text{max}},x,\Omega). +\end{align} +We are interested in computing the dose, which (when again using the original energy $E$ and angular flux $\psi$) reads +\begin{align} + D(x) = \int_0^{\infty} \int_{\mathbb{S}^2} S(E)\psi(E,x,\Omega)\,d\Omega dE = \int_0^{\infty} \int_{\mathbb{S}^2} \frac{1}{\rho(x)}\widehat\psi(E,x,\Omega)\,d\Omega dE. +\end{align} +So let us check how we can compute the dose from our solution $\bar \psi(\bar E,x,\Omega)$. For this, let us substitute +\begin{align}\label{eq:BarE} + \bar E(E) = \tilde{E}(E_{max}) - \int_0^E \frac{1}{S(E')}dE'. +\end{align} +We have +\begin{align} + \frac{d\bar E(E)}{dE} = -\frac{1}{S(E)} +\end{align} +which gives +\begin{align} + D(x) =& -\int_{\infty}^{0} \int_{\mathbb{S}^2} \frac{1}{\rho(x)}\bar \psi(\bar E,x,\Omega)\frac{1}{S(E(\bar E))}\,d\Omega d\bar E\\ + =& \int_{0}^{\infty} \frac{1}{\rho(x)S(E(\bar E))}\int_{\mathbb{S}^2} \bar \psi(\bar E,x,\Omega)\,d\Omega d\bar E. +\end{align} +\jknote{@all: Can you double check this formulation of the dose? Kerstin had a different version in her thesis.} +\txnote{Kerstin (1.27)} +\begin{align} + &\widehat{\psi}(E,x,\Omega) := \widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) :=\bar{\psi}(\bar{E},x,\Omega),\\ + &dE = -S(E) d\bar E(E), \\ + &D(x) = -\int_{\infty}^{0} \int_{\mathbb{S}^2} \frac{1}{\rho(x)}\bar \psi(\bar E,x,\Omega)S(E(\bar E))d\Omega d\bar E + = \int_{0}^{\infty} \frac{S(E(\bar E))}{\rho(x)}\int_{\mathbb{S}^2} \bar \psi(\bar E,x,\Omega)\,d\Omega d\bar E. +\end{align} + + +\section{Numerical Implementation} +\subsection{Quadrature Grid} +In the field of radiation therapy, the radiative transfer equation is often discretized by Monte-Carlo methods, which commonly yield an increased runtime and stochastic noise. Therefore, we choose a discrete ordinates (S$_N$) discretization (which has its own disadvantages such as ray-effects) instead. The first step to obtain a discretized system is to derive a finite dimensional, nodal representation of the angular variable $\bm\Omega\in\mathbb{S}^2$. Here, different strategies to obtain an accurate discretization exist and we are going to start with a straight forward product quadrature rule on the sphere. To obtain a finite set of directions in $\mathbb{S}^2$, we describe the angular variable +\begin{align*} +\bm\Omega = (\cos\phi \sin \theta, \sin\phi \sin \theta, \cos \theta)^T\; +\end{align*} +at finite positions of $\theta$ and $\phi$. + +\subsection{Energy Grid} +Furthermore, we choose a modal discretization of the energy (or pseudo-time) variable. Dividing the original energy $E$ into an equidistant mesh $E_{\text{min}} = E_1 < \cdots < E_{N_E} = E_{\text{max}}$ lets us define the transformed energies $\widetilde E$ according to \eqref{eq:TildeE} by +\begin{align} + \widetilde E(E_n)\approx\widetilde E_n := \sum_{\ell=1}^n \Delta E \frac{1}{S(E_{\ell})} \qquad\text{for }n = 1,\cdots,N_E. +\end{align} +\jknote{We could also use a more accurate quadrature here in the code!} +Then, we change to $\bar{E}$ according to \eqref{eq:BarE}, i.e. on a discrete level we get +\begin{align} + \bar E_n := \widetilde E_{N_E} - \widetilde E_n \qquad\text{for }n = 1,\cdots,N_E. +\end{align} +The cross section $\Sigma_t$ evaluated at $\bar E_n$, i.e. $\bar \Sigma_t(\bar E_n) = \Sigma_t(E(\bar E_n))$ is then simply given by evaluating $\Sigma_t$ at $E_{N_E-n}$. The same holds for the scattering cross section $\Sigma_s$. \ No newline at end of file -- GitLab From 1ec34a748fa8bf683345863483d0581cff9c25e0 Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 10:06:41 +0100 Subject: [PATCH 12/67] Adjust math Former-commit-id: be3b93960a0829bc3743bee22b68245047be229b --- doc/physics.rst | 115 +++++++++++++++++++++++++----------------------- 1 file changed, 61 insertions(+), 54 deletions(-) diff --git a/doc/physics.rst b/doc/physics.rst index 4c3a1b6..cb50715 100644 --- a/doc/physics.rst +++ b/doc/physics.rst @@ -85,109 +85,116 @@ The continuous slowing down approximation --------- Our main goal is to compute the radiation dose -\begin{align} +.. math:: D(x)=\frac{1}{\rho(x)}\int_0^{\infty}\int_{\mathbb{S}^2}S(E,x)\psi(E,x,\Omega)\,d\Omega dE. -\end{align} + The angular flux $\psi$ can be approximated by the continuous slowing down (CSD) equation, which reads -\begin{align} +.. math:: -\partial_E\left(S(E,x)\psi(E,x,\Omega)\right)+\Omega\cdot\nabla_x\psi(E,x,\Omega)+\Sigma_t(E,x)\psi(E,x,\Omega) = \int_{\mathbb{S}^2}\Sigma_s(E,x,\Omega\cdot\Omega')\psi(E,x,\Omega')d\Omega'. -\end{align} + Here $E\in\mathbb{R}_+$ is energy, $x\in D\subset \mathbb{R}^3$ is the spatial domain and $\Omega\in\mathbb{S}^2$ is the direction of travel. The stopping power $S$ is given by -\begin{align} +.. math:: S(E,x) = \int_0^{\infty} E'\int_{-1}^1\Sigma(E,E',x,\mu)d\mu dE'. -\end{align} + Since there are no absorption effects, the total cross section is given by -\begin{align} +.. math:: \Sigma_t(E,x) = \Sigma_{s,0}(E,x)=2\pi \int_{-1}^1\Sigma_s(E,x,\mu)d\mu. -\end{align} -\jknote{We can double check this in our code.} -\jknote{Check if we need to transform when intgrating w.r.t. $\mu$ instead of $\Omega'$.} -\txnote{Why the integral deduces from $\Omega$ to $\mu$ automatically?} -\ssnote{Fixed that issue} + With a given background material density $\rho(x)$ now make the following assumptions -\begin{align} +.. math:: S(E,x) = S^{H_2O}(E)\rho(x), \\ \Sigma_t(E,x) = \Sigma_t^{H_2O}(E)\rho(x), \\ \Sigma_s(E,x,\Omega\cdot\Omega') = \Sigma_s(E,\Omega\cdot\Omega')\rho(x). -\end{align} + Leaving out the superscript $H_2O$, the CSD equation simplifies to -\begin{align}\label{eq:CSD2} +.. math:: + :label: CSD2 + -\partial_E\left(\rho(x)S(E)\psi(E,x,\Omega)\right)+\Omega\cdot\nabla_x\psi(E,x,\Omega)+\rho(x)\Sigma_t(E)\psi(E,x,\Omega) = \int_{\mathbb{S}^2}\rho(x)\Sigma_s(E,\Omega\cdot\Omega')\psi(E,x,\Omega')d\Omega'. -\end{align} + Now, we bring this system in a form which resembles the standard Boltzmann equation. Multiplying \eqref{eq:CSD2} with $S(E)$ gives -\begin{subequations}\label{eq:CSD3} -\begin{align} - -S(E)\partial_E\left(S(E)\rho(x)\psi(E,x,\Omega)\right)+&\Omega\cdot\nabla_x S(E)\psi(E,x,\Omega)+\Sigma_t(E)S(E)\rho(x)\psi(E,x,\Omega)\\ - &= \int_{\mathbb{S}^2}\Sigma_s(E,\Omega\cdot\Omega')S(E)\rho(x)\psi(E,x,\Omega')d\Omega'. -\end{align} -\end{subequations} +.. math:: + :label: CSD3 + \begin{align} + -S(E)\partial_E\left(S(E)\rho(x)\psi(E,x,\Omega)\right)+&\Omega\cdot\nabla_x S(E)\psi(E,x,\Omega)+\Sigma_t(E)S(E)\rho(x)\psi(E,x,\Omega)\\ + &= \int_{\mathbb{S}^2}\Sigma_s(E,\Omega\cdot\Omega')S(E)\rho(x)\psi(E,x,\Omega')d\Omega'. + \end{align} + Then, we substitute -\begin{align} +.. math:: \widehat{\psi}(E,x,\Omega):= S(E)\rho(x)\psi(E,x,\Omega) -\end{align} + into \eqref{eq:CSD3}, which yields -\begin{align}\label{eq:CSD4} +.. math:: + :label: CSD4 -S(E)\partial_E\widehat{\psi}(E,x,\Omega)+\Omega\cdot\nabla_x \frac{\widehat{\psi}(E,x,\Omega)}{\rho}+\Sigma_t(E)\widehat{\psi}(E,x,\Omega) = \int_{\mathbb{S}^2}\Sigma_s(E,\Omega\cdot\Omega')\widehat{\psi}(E,x,\Omega')d\Omega'. -\end{align} + Now, to get rid of the stopping power in front of the energy derivative, we make use of the transformation -\begin{align}\label{eq:TildeE} +.. math:: + :label: TildeE + \widetilde{E}(E) = \int_0^E \frac{1}{S(E')}\,dE'. -\end{align} + Now let us change to -\begin{align} +.. math:: \widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) := \widehat{\psi}(E(\widetilde E),x,\Omega) -\end{align} + In this case, the energy derivative becomes -\begin{align*} +.. math:: \partial_{\widetilde{E}}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) = \partial_{E}\widetilde{\widehat{\psi}}( E,x,\Omega)\partial_{\widetlde E }E(\widetilde E(\widetilde E) = \partial_{ E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega){S(E(\widetilde E))}. -\end{align*} + And by rearranging the terms, we finally get -\begin{align*} +.. math:: \partial_{ E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) = \partial_{\widetilde{E}}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)\frac{1}{S(E(\widetilde E))}, -\end{align*} + since $S(E(\widetilde E))$ is nonzero \ssnote{Is S always nonzero? Would make sense, physically.}. Therefore, substituting $\widetilde E$ in \eqref{eq:CSD4} gives -\begin{align}\label{eq:CSD5} +.. math:: + :label: CSD5 + -\partial_{\widetilde E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)+\Omega\cdot\nabla_x \frac{\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)}{\rho}+\widetilde\Sigma_t(\widetilde E)\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) = \int_{\mathbb{S}^2}\widetilde\Sigma_s(\widetilde E,\Omega\cdot\Omega')\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega')d\Omega'. -\end{align} + Here, we define $\widetilde\Sigma_{t}(\widetilde E):=\Sigma_t(E(\widetilde E))$ and $\widetilde\Sigma_{s}(\widetilde E,\Omega\cdot\Omega'):=\Sigma_s(E(\widetilde E),\Omega\cdot\Omega')$. Finally, to obtain a positive sign in front of the energy derivative, we transform to -\begin{align} +.. math:: \bar{E}(\widetilde{E}) = \widetilde{E}_{\text{max}}-\widetilde{E}. -\end{align} + Then, with $\bar{\psi}(\bar{E},x,\Omega):=\widetilde{\widehat{\psi}}(\widetilde{E}(\bar{E}),x,\Omega)$ and $\bar\Sigma_{t}(\bar E):=\widetilde{\Sigma}_t(\widetilde{E}(\bar{E}))$ as well as $\bar\Sigma_{s}(\bar E,\Omega\cdot\Omega'):=\widetilde{\Sigma}_s(\widetilde{E}(\bar{E}),\Omega\cdot\Omega')$ equation \eqref{eq:CSD4} becomes -\begin{align}\label{eq:CSD5} +.. math:: + :label: CSD6 \partial_{\bar{E}}\bar{\psi}(\bar{E},x,\Omega)+\Omega\cdot\nabla_x \frac{\bar{\psi}(\bar{E},x,\Omega)}{\rho}+\bar\Sigma_t(\bar E)\bar{\psi}(\bar{E},x,\Omega) = \int_{\mathbb{S}^2}\bar\Sigma_s(\bar{E},\Omega\cdot\Omega')\bar{\psi}(\bar{E},x,\Omega')d\Omega'. -\end{align} + Dropping the bar notation and treating $\bar E$ as a pseudo-time $t$ gives a slightly modified version of the Boltzmann equation -\begin{align}\label{eq:CSDBoltzmann} +.. math:: + :label: CSDBoltzmann + \partial_{t}\psi(t,x,\Omega)+&\Omega\cdot\nabla_x \frac{\psi(t,x,\Omega)}{\rho}+\Sigma_t(t)\psi(t,x,\Omega) = \int_{\mathbb{S}^2}\Sigma_s(t,\Omega\cdot\Omega')\psi(t,x,\Omega')d\Omega'\\ &\psi(t=0,x,\Omega) = S(E_{\text{max}})\rho(x)\psi(E_{\text{max}},x,\Omega). -\end{align} + We are interested in computing the dose, which (when again using the original energy $E$ and angular flux $\psi$) reads -\begin{align} +.. math:: D(x) = \int_0^{\infty} \int_{\mathbb{S}^2} S(E)\psi(E,x,\Omega)\,d\Omega dE = \int_0^{\infty} \int_{\mathbb{S}^2} \frac{1}{\rho(x)}\widehat\psi(E,x,\Omega)\,d\Omega dE. -\end{align} + So let us check how we can compute the dose from our solution $\bar \psi(\bar E,x,\Omega)$. For this, let us substitute -\begin{align}\label{eq:BarE} +.. math:: + :label: BarE + \bar E(E) = \tilde{E}(E_{max}) - \int_0^E \frac{1}{S(E')}dE'. -\end{align} + We have -\begin{align} +.. math:: \frac{d\bar E(E)}{dE} = -\frac{1}{S(E)} -\end{align} + which gives -\begin{align} +.. math:: D(x) =& -\int_{\infty}^{0} \int_{\mathbb{S}^2} \frac{1}{\rho(x)}\bar \psi(\bar E,x,\Omega)\frac{1}{S(E(\bar E))}\,d\Omega d\bar E\\ =& \int_{0}^{\infty} \frac{1}{\rho(x)S(E(\bar E))}\int_{\mathbb{S}^2} \bar \psi(\bar E,x,\Omega)\,d\Omega d\bar E. -\end{align} -\jknote{@all: Can you double check this formulation of the dose? Kerstin had a different version in her thesis.} -\txnote{Kerstin (1.27)} -\begin{align} + +.. math:: &\widehat{\psi}(E,x,\Omega) := \widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) :=\bar{\psi}(\bar{E},x,\Omega),\\ &dE = -S(E) d\bar E(E), \\ &D(x) = -\int_{\infty}^{0} \int_{\mathbb{S}^2} \frac{1}{\rho(x)}\bar \psi(\bar E,x,\Omega)S(E(\bar E))d\Omega d\bar E = \int_{0}^{\infty} \frac{S(E(\bar E))}{\rho(x)}\int_{\mathbb{S}^2} \bar \psi(\bar E,x,\Omega)\,d\Omega d\bar E. -\end{align} + \section{Numerical Implementation} -- GitLab From f65be98320e757ddebc6f0682eddf8dd0672efbf Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 10:09:20 +0100 Subject: [PATCH 13/67] Add implementation Former-commit-id: 2dca19369d6513956564d49e9f0829554413ec6c --- doc/implement.rst | 144 ++++++++++++++++++++++++++++++++++++++++++++++ doc/index.rst | 1 + 2 files changed, 145 insertions(+) create mode 100644 doc/implement.rst diff --git a/doc/implement.rst b/doc/implement.rst new file mode 100644 index 0000000..f6bf486 --- /dev/null +++ b/doc/implement.rst @@ -0,0 +1,144 @@ +.. _implementation: + +Implementation +------------------------ +***** +Build +***** + +Required dependencies +===================== + - Compiler with C++17 support + - cmake >= v3.12.4 + - LAPACK + - OpenMP + - MPI + - VTK + - git + - ninja or make + +Obtain submodules +================== +Note that an **active internet connection is required for the first build** in order to download the latest versions of the required submodules! +For the first build only, download all submodules: + +.. code-block:: bash + + git submodule update --init --recursive + +Compile the code +================ +**Make** build system (available on most systems) + + +.. code-block:: bash + + cd code/build/release + cmake -DCMAKE_BUILD_TYPE=Release ../../ + make + +If building in parallel is desired, change the last line to `make -jN`, where `N` optimally is equal to the number of available threads+1. + +**Ninja** build system: + +.. code-block:: bash + + cd code/build/release + cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ../../ + ninja + + + +The resulting executable will automatically be placed in the `code/bin` folder. + +---------------------------------------------------------- + +********** +Run +********** + +Local +=========== + +Execute the compiled binary from the `bin` folder and hand over a valid *TOML*-styled config file. +Example from inside the `code` directory: + +```bash +./KiT-RT ../input/example.cfg +``` + +In order to run the code in parallel execute: + +```bash +OMP_NUM_THREADS=N mpirun -np J ./KiT-RT ../input/example.cfg +``` + +with `N` equal to the number of shared memory threads and `J` equal to the number of distrubuted memory threads. + +BwUniCluster +============== + +As VTK is not available on the bwUniCluster, it needs to be installed first. This just needs to be done once. Example: + +.. code-block:: bash + + module load devel/cmake/3.16 + module load compiler/gnu/9.2 + wget --no-check-certificate --quiet https://www.vtk.org/files/release/8.2/VTK-8.2.0.tar.gz + tar xzf VTK-8.2.0.tar.gz + mkdir VTK-build + cd VTK-build + cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_DOCUMENTATION=OFF -DBUILD_TESTING=OFF - + DCMAKE_INSTALL_PREFIX=~/VTK-install ../VTK-8.2.0 + make -j + make install + cd - + rm -r VTK-8.2.0 VTK-build + + +Example for build and run on bwUniCluster: +Get the code + +.. code-block:: bash + + git clone https://git.scc.kit.edu/rtsn/rtsn.git KiT-RT + cd KiT-RT/ + git submodule init + git submodule update + +Append ``HINTS VTK_INSTALL_DIR` to the ``find_package( VTK ... )`` line in the CMakeLists.txt. E.g.: + +.. code-block:: bash + + find_package( VTK REQUIRED COMPONENTS vtkIOGeometry vtkFiltersCore HINTS ~/VTK-install ) + + +Compile it + +.. code-block:: bash + + module load devel/cmake/3.16 + module load compiler/gnu/9.2 + module load mpi/openmpi/4.0 + cd code/build/release/ + cmake -DCMAKE_BUILD_TYPE=Release ../../ + make -j + + +--------------------------------------------------------------- + +Tests +============================ + +After compiling the framework as described above just run: + +.. code-block:: bash + + make test + + +The ``unit_tests`` executable will also be placed in in the build folder. + + + + diff --git a/doc/index.rst b/doc/index.rst index df99a89..82fd7f3 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -15,6 +15,7 @@ Contents installation physics + implement configFiles cpp_doc developer_guide -- GitLab From 72bd3a49c7d350b8b781ade8decf6ac7d109684b Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 10:15:26 +0100 Subject: [PATCH 14/67] Update index Former-commit-id: 5b20c9b9d198d437440d21a8da7ba3e756fbd580 --- doc/index.rst | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/doc/index.rst b/doc/index.rst index 82fd7f3..c3844d0 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -1,10 +1,15 @@ =========================================================== -KiT-RT - The kinetic transport solver for radiation therapy +KiT-RT: a kinetic transport solver for radiation therapy =========================================================== -The KiT-RT framework is a powerful open source platform for radiation transport. Its main focus is on radiotherapy planning in cancer treatment. To allow problem-specific method selection, the framework provides different deterministic solver types. This not only facilitates treatment planning, but also provides tools to investigate various research questions in the field of radiative transfer. This goal is supported by an easily extensible code structure that allows straightforward implementation of additional methods and techniques. +The KiT-RT framework is a powerful open source platform for radiation transport. +Its main focus is on radiotherapy planning in cancer treatment. +To allow problem-specific method selection, the framework provides different deterministic solver types. +This not only facilitates treatment planning, but also provides tools to investigate various research questions in the field of radiative transfer. +This goal is supported by an easily extensible code structure that allows straightforward implementation of additional methods and techniques. -The software is being developed by members of the group `CSMM `_ at the Karlsruhe Institute of Technology (KIT). For more information, please contact any of our authors (link to authors page). +The software is being developed by members of the group `CSMM `_ at the Karlsruhe Institute of Technology (KIT). +For more information, please feel free to get in touch with us (link to authors page). -------- Contents -- GitLab From fed855021440ed15a7935441d7fefea88bf1a058 Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 10:20:46 +0100 Subject: [PATCH 15/67] Update physics.rst Former-commit-id: 1539dfbb9512eaac2926ada4b1d71e4feedf2f65 --- doc/physics.rst | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/doc/physics.rst b/doc/physics.rst index cb50715..ddc0c0f 100644 --- a/doc/physics.rst +++ b/doc/physics.rst @@ -1,5 +1,5 @@ ================ -Kinetic Theory +Theory ================ The kinetic theory is dedicated to describe the dynamical behavior of a many-particle system through ensemble averaging. @@ -85,34 +85,43 @@ The continuous slowing down approximation --------- Our main goal is to compute the radiation dose + .. math:: + D(x)=\frac{1}{\rho(x)}\int_0^{\infty}\int_{\mathbb{S}^2}S(E,x)\psi(E,x,\Omega)\,d\Omega dE. The angular flux $\psi$ can be approximated by the continuous slowing down (CSD) equation, which reads + .. math:: -\partial_E\left(S(E,x)\psi(E,x,\Omega)\right)+\Omega\cdot\nabla_x\psi(E,x,\Omega)+\Sigma_t(E,x)\psi(E,x,\Omega) = \int_{\mathbb{S}^2}\Sigma_s(E,x,\Omega\cdot\Omega')\psi(E,x,\Omega')d\Omega'. Here $E\in\mathbb{R}_+$ is energy, $x\in D\subset \mathbb{R}^3$ is the spatial domain and $\Omega\in\mathbb{S}^2$ is the direction of travel. The stopping power $S$ is given by + .. math:: S(E,x) = \int_0^{\infty} E'\int_{-1}^1\Sigma(E,E',x,\mu)d\mu dE'. Since there are no absorption effects, the total cross section is given by + .. math:: + \Sigma_t(E,x) = \Sigma_{s,0}(E,x)=2\pi \int_{-1}^1\Sigma_s(E,x,\mu)d\mu. With a given background material density $\rho(x)$ now make the following assumptions + .. math:: S(E,x) = S^{H_2O}(E)\rho(x), \\ \Sigma_t(E,x) = \Sigma_t^{H_2O}(E)\rho(x), \\ \Sigma_s(E,x,\Omega\cdot\Omega') = \Sigma_s(E,\Omega\cdot\Omega')\rho(x). Leaving out the superscript $H_2O$, the CSD equation simplifies to + .. math:: :label: CSD2 -\partial_E\left(\rho(x)S(E)\psi(E,x,\Omega)\right)+\Omega\cdot\nabla_x\psi(E,x,\Omega)+\rho(x)\Sigma_t(E)\psi(E,x,\Omega) = \int_{\mathbb{S}^2}\rho(x)\Sigma_s(E,\Omega\cdot\Omega')\psi(E,x,\Omega')d\Omega'. Now, we bring this system in a form which resembles the standard Boltzmann equation. Multiplying \eqref{eq:CSD2} with $S(E)$ gives + .. math:: :label: CSD3 \begin{align} @@ -120,50 +129,60 @@ Now, we bring this system in a form which resembles the standard Boltzmann equat &= \int_{\mathbb{S}^2}\Sigma_s(E,\Omega\cdot\Omega')S(E)\rho(x)\psi(E,x,\Omega')d\Omega'. \end{align} -Then, we substitute +Then, we substitute + .. math:: \widehat{\psi}(E,x,\Omega):= S(E)\rho(x)\psi(E,x,\Omega) into \eqref{eq:CSD3}, which yields + .. math:: :label: CSD4 -S(E)\partial_E\widehat{\psi}(E,x,\Omega)+\Omega\cdot\nabla_x \frac{\widehat{\psi}(E,x,\Omega)}{\rho}+\Sigma_t(E)\widehat{\psi}(E,x,\Omega) = \int_{\mathbb{S}^2}\Sigma_s(E,\Omega\cdot\Omega')\widehat{\psi}(E,x,\Omega')d\Omega'. Now, to get rid of the stopping power in front of the energy derivative, we make use of the transformation + .. math:: :label: TildeE \widetilde{E}(E) = \int_0^E \frac{1}{S(E')}\,dE'. Now let us change to + .. math:: \widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) := \widehat{\psi}(E(\widetilde E),x,\Omega) In this case, the energy derivative becomes + .. math:: \partial_{\widetilde{E}}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) = \partial_{E}\widetilde{\widehat{\psi}}( E,x,\Omega)\partial_{\widetlde E }E(\widetilde E(\widetilde E) = \partial_{ E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega){S(E(\widetilde E))}. And by rearranging the terms, we finally get + .. math:: \partial_{ E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) = \partial_{\widetilde{E}}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)\frac{1}{S(E(\widetilde E))}, since $S(E(\widetilde E))$ is nonzero \ssnote{Is S always nonzero? Would make sense, physically.}. Therefore, substituting $\widetilde E$ in \eqref{eq:CSD4} gives + .. math:: :label: CSD5 -\partial_{\widetilde E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)+\Omega\cdot\nabla_x \frac{\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)}{\rho}+\widetilde\Sigma_t(\widetilde E)\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) = \int_{\mathbb{S}^2}\widetilde\Sigma_s(\widetilde E,\Omega\cdot\Omega')\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega')d\Omega'. Here, we define $\widetilde\Sigma_{t}(\widetilde E):=\Sigma_t(E(\widetilde E))$ and $\widetilde\Sigma_{s}(\widetilde E,\Omega\cdot\Omega'):=\Sigma_s(E(\widetilde E),\Omega\cdot\Omega')$. Finally, to obtain a positive sign in front of the energy derivative, we transform to + .. math:: \bar{E}(\widetilde{E}) = \widetilde{E}_{\text{max}}-\widetilde{E}. Then, with $\bar{\psi}(\bar{E},x,\Omega):=\widetilde{\widehat{\psi}}(\widetilde{E}(\bar{E}),x,\Omega)$ and $\bar\Sigma_{t}(\bar E):=\widetilde{\Sigma}_t(\widetilde{E}(\bar{E}))$ as well as $\bar\Sigma_{s}(\bar E,\Omega\cdot\Omega'):=\widetilde{\Sigma}_s(\widetilde{E}(\bar{E}),\Omega\cdot\Omega')$ equation \eqref{eq:CSD4} becomes + .. math:: :label: CSD6 \partial_{\bar{E}}\bar{\psi}(\bar{E},x,\Omega)+\Omega\cdot\nabla_x \frac{\bar{\psi}(\bar{E},x,\Omega)}{\rho}+\bar\Sigma_t(\bar E)\bar{\psi}(\bar{E},x,\Omega) = \int_{\mathbb{S}^2}\bar\Sigma_s(\bar{E},\Omega\cdot\Omega')\bar{\psi}(\bar{E},x,\Omega')d\Omega'. Dropping the bar notation and treating $\bar E$ as a pseudo-time $t$ gives a slightly modified version of the Boltzmann equation + .. math:: :label: CSDBoltzmann @@ -171,20 +190,24 @@ Dropping the bar notation and treating $\bar E$ as a pseudo-time $t$ gives a sli &\psi(t=0,x,\Omega) = S(E_{\text{max}})\rho(x)\psi(E_{\text{max}},x,\Omega). We are interested in computing the dose, which (when again using the original energy $E$ and angular flux $\psi$) reads + .. math:: D(x) = \int_0^{\infty} \int_{\mathbb{S}^2} S(E)\psi(E,x,\Omega)\,d\Omega dE = \int_0^{\infty} \int_{\mathbb{S}^2} \frac{1}{\rho(x)}\widehat\psi(E,x,\Omega)\,d\Omega dE. So let us check how we can compute the dose from our solution $\bar \psi(\bar E,x,\Omega)$. For this, let us substitute + .. math:: :label: BarE \bar E(E) = \tilde{E}(E_{max}) - \int_0^E \frac{1}{S(E')}dE'. We have + .. math:: \frac{d\bar E(E)}{dE} = -\frac{1}{S(E)} which gives + .. math:: D(x) =& -\int_{\infty}^{0} \int_{\mathbb{S}^2} \frac{1}{\rho(x)}\bar \psi(\bar E,x,\Omega)\frac{1}{S(E(\bar E))}\,d\Omega d\bar E\\ =& \int_{0}^{\infty} \frac{1}{\rho(x)S(E(\bar E))}\int_{\mathbb{S}^2} \bar \psi(\bar E,x,\Omega)\,d\Omega d\bar E. @@ -195,24 +218,3 @@ which gives &D(x) = -\int_{\infty}^{0} \int_{\mathbb{S}^2} \frac{1}{\rho(x)}\bar \psi(\bar E,x,\Omega)S(E(\bar E))d\Omega d\bar E = \int_{0}^{\infty} \frac{S(E(\bar E))}{\rho(x)}\int_{\mathbb{S}^2} \bar \psi(\bar E,x,\Omega)\,d\Omega d\bar E. - - -\section{Numerical Implementation} -\subsection{Quadrature Grid} -In the field of radiation therapy, the radiative transfer equation is often discretized by Monte-Carlo methods, which commonly yield an increased runtime and stochastic noise. Therefore, we choose a discrete ordinates (S$_N$) discretization (which has its own disadvantages such as ray-effects) instead. The first step to obtain a discretized system is to derive a finite dimensional, nodal representation of the angular variable $\bm\Omega\in\mathbb{S}^2$. Here, different strategies to obtain an accurate discretization exist and we are going to start with a straight forward product quadrature rule on the sphere. To obtain a finite set of directions in $\mathbb{S}^2$, we describe the angular variable -\begin{align*} -\bm\Omega = (\cos\phi \sin \theta, \sin\phi \sin \theta, \cos \theta)^T\; -\end{align*} -at finite positions of $\theta$ and $\phi$. - -\subsection{Energy Grid} -Furthermore, we choose a modal discretization of the energy (or pseudo-time) variable. Dividing the original energy $E$ into an equidistant mesh $E_{\text{min}} = E_1 < \cdots < E_{N_E} = E_{\text{max}}$ lets us define the transformed energies $\widetilde E$ according to \eqref{eq:TildeE} by -\begin{align} - \widetilde E(E_n)\approx\widetilde E_n := \sum_{\ell=1}^n \Delta E \frac{1}{S(E_{\ell})} \qquad\text{for }n = 1,\cdots,N_E. -\end{align} -\jknote{We could also use a more accurate quadrature here in the code!} -Then, we change to $\bar{E}$ according to \eqref{eq:BarE}, i.e. on a discrete level we get -\begin{align} - \bar E_n := \widetilde E_{N_E} - \widetilde E_n \qquad\text{for }n = 1,\cdots,N_E. -\end{align} -The cross section $\Sigma_t$ evaluated at $\bar E_n$, i.e. $\bar \Sigma_t(\bar E_n) = \Sigma_t(E(\bar E_n))$ is then simply given by evaluating $\Sigma_t$ at $E_{N_E-n}$. The same holds for the scattering cross section $\Sigma_s$. \ No newline at end of file -- GitLab From 70c43a5b2c95eca2d942807e50fde4390f766339 Mon Sep 17 00:00:00 2001 From: "jonas.kusch" Date: Fri, 26 Feb 2021 11:08:40 +0100 Subject: [PATCH 16/67] fixed dosis computation Former-commit-id: 12fd60ec19d2ec372318c2d4ea190f60705c1dca --- code/include/solvers/csdsolvertrafofp.h | 2 +- code/include/solvers/csdsolvertrafofp2d.h | 2 +- code/include/solvers/csdsolvertrafofpsh2d.h | 2 +- code/include/solvers/mnsolver.h | 2 +- code/include/solvers/pnsolver.h | 2 +- code/include/solvers/snsolver.h | 2 +- code/include/solvers/solverbase.h | 2 +- code/input/waterphantom_1D.cfg | 3 ++- code/src/solvers/csdsolvertrafofp.cpp | 27 ++++++++++++--------- code/src/solvers/csdsolvertrafofp2d.cpp | 27 ++++++++++++--------- code/src/solvers/csdsolvertrafofpsh2d.cpp | 27 ++++++++++++--------- code/src/solvers/mnsolver.cpp | 2 +- code/src/solvers/pnsolver.cpp | 2 +- code/src/solvers/snsolver.cpp | 2 +- code/src/solvers/solverbase.cpp | 2 +- 15 files changed, 61 insertions(+), 45 deletions(-) diff --git a/code/include/solvers/csdsolvertrafofp.h b/code/include/solvers/csdsolvertrafofp.h index fe42ec9..1e4e818 100644 --- a/code/include/solvers/csdsolvertrafofp.h +++ b/code/include/solvers/csdsolvertrafofp.h @@ -60,7 +60,7 @@ class CSDSolverTrafoFP : public SNSolver void FVMUpdate( unsigned idx_energy ) override final; void FluxUpdate() override final; void IterPreprocessing( unsigned idx_pseudotime ) override final; - void virtual IterPostprocessing() override final; + void virtual IterPostprocessing( unsigned idx_pseudotime ) override final; void SolverPreprocessing() override final; }; diff --git a/code/include/solvers/csdsolvertrafofp2d.h b/code/include/solvers/csdsolvertrafofp2d.h index 4531194..62526a9 100644 --- a/code/include/solvers/csdsolvertrafofp2d.h +++ b/code/include/solvers/csdsolvertrafofp2d.h @@ -72,7 +72,7 @@ class CSDSolverTrafoFP2D : public SNSolver void FVMUpdate( unsigned idx_energy ) override final; void FluxUpdate() override final; void IterPreprocessing( unsigned idx_pseudotime ) override final; - void virtual IterPostprocessing() override final; + void virtual IterPostprocessing( unsigned idx_pseudotime ) override final; void SolverPreprocessing() override final; }; diff --git a/code/include/solvers/csdsolvertrafofpsh2d.h b/code/include/solvers/csdsolvertrafofpsh2d.h index 51fb4ea..127d070 100644 --- a/code/include/solvers/csdsolvertrafofpsh2d.h +++ b/code/include/solvers/csdsolvertrafofpsh2d.h @@ -89,7 +89,7 @@ class CSDSolverTrafoFPSH2D : public SNSolver void FVMUpdate( unsigned idx_energy ) override final; void FluxUpdate() override final; void IterPreprocessing( unsigned idx_pseudotime ) override final; - void virtual IterPostprocessing() override final; + void virtual IterPostprocessing( unsigned idx_pseudotime ) override final; void SolverPreprocessing() override final; }; diff --git a/code/include/solvers/mnsolver.h b/code/include/solvers/mnsolver.h index 560a5f6..99ae1d8 100644 --- a/code/include/solvers/mnsolver.h +++ b/code/include/solvers/mnsolver.h @@ -55,7 +55,7 @@ class MNSolver : public Solver void FVMUpdate( unsigned idx_energy ) override; void FluxUpdate() override; void IterPreprocessing( unsigned idx_pseudotime ) override; - void IterPostprocessing(); + void IterPostprocessing( unsigned idx_pseudotime ); /*! @brief : Construct flux by computing the Moment of the sum of FVM discretization at the interface of cell * @param : idx_cell = current cell id * @returns : sum over all neighbors of flux for all moments at interface of idx_cell, idx_neighbor */ diff --git a/code/include/solvers/pnsolver.h b/code/include/solvers/pnsolver.h index 188af18..ac38dc1 100644 --- a/code/include/solvers/pnsolver.h +++ b/code/include/solvers/pnsolver.h @@ -54,7 +54,7 @@ class PNSolver : public Solver void FVMUpdate( unsigned idx_energy ) override; void FluxUpdate() override; void IterPreprocessing( unsigned idx_pseudotime ) override; - void IterPostprocessing(); + void IterPostprocessing( unsigned idx_pseudotime ); // Helper void ComputeRadFlux(); diff --git a/code/include/solvers/snsolver.h b/code/include/solvers/snsolver.h index b527119..3009ce4 100644 --- a/code/include/solvers/snsolver.h +++ b/code/include/solvers/snsolver.h @@ -30,7 +30,7 @@ class SNSolver : public Solver void virtual FVMUpdate( unsigned idx_energy ) override; void virtual FluxUpdate() override; void virtual IterPreprocessing( unsigned idx_pseudotime ) override; - void virtual IterPostprocessing() override; + void virtual IterPostprocessing( unsigned idx_pseudotime ) override; // Helper void ComputeRadFlux(); diff --git a/code/include/solvers/solverbase.h b/code/include/solvers/solverbase.h index b536004..9371e84 100644 --- a/code/include/solvers/solverbase.h +++ b/code/include/solvers/solverbase.h @@ -92,7 +92,7 @@ class Solver /*! @brief Performs preprocessing for the current solver iteration */ virtual void IterPreprocessing( unsigned idx_pseudotime ) = 0; /*! @brief Performs postprocessing for the current solver iteration */ - virtual void IterPostprocessing() = 0; + virtual void IterPostprocessing( unsigned idx_pseudotime ) = 0; /*! @brief Constructs the flux update for the current iteration and stores it in psiNew*/ virtual void FluxUpdate() = 0; /*! @brief Computes the finite Volume update step for the current iteration */ diff --git a/code/input/waterphantom_1D.cfg b/code/input/waterphantom_1D.cfg index 1a30831..71c374a 100644 --- a/code/input/waterphantom_1D.cfg +++ b/code/input/waterphantom_1D.cfg @@ -11,13 +11,14 @@ LOG_DIR = ../result/logs MESH_FILE = meshes/1DMesh.su2 PROBLEM = WATERPHANTOM SOLVER = CSD_SN_FOKKERPLANCK_TRAFO_SOLVER -CONTINUOUS_SLOWING_DOWN = YES HYDROGEN_FILE = ENDL_H.txt OXYGEN_FILE = ENDL_O.txt KERNEL = ISOTROPIC_1D CFL_NUMBER = 0.008 TIME_FINAL = 1.0 CLEAN_FLUX_MATRICES = NO +MAX_ENERGY_CSD = 5 +VOLUME_OUTPUT = (MINIMAL, MEDICAL) BC_DIRICHLET = ( dirichlet ) BC_NEUMANN = ( wall_low, wall_up ) diff --git a/code/src/solvers/csdsolvertrafofp.cpp b/code/src/solvers/csdsolvertrafofp.cpp index d15ac76..33a803f 100644 --- a/code/src/solvers/csdsolvertrafofp.cpp +++ b/code/src/solvers/csdsolvertrafofp.cpp @@ -183,10 +183,24 @@ void CSDSolverTrafoFP::FVMUpdate( unsigned /*idx_energy*/ ) { } } -void CSDSolverTrafoFP::IterPostprocessing() { +void CSDSolverTrafoFP::IterPostprocessing( unsigned idx_pseudotime ) { // --- Update Solution --- _sol = _solNew; + unsigned n = idx_pseudotime; + for( unsigned j = 0; j < _nCells; ++j ) { + _fluxNew[j] = dot( _sol[j], _weights ); + if( n > 0 ) { + _dose[j] += 0.5 * _dE * ( _fluxNew[j] * _s[_nEnergies - n - 1] + _flux[j] * _s[_nEnergies - n] ) / + _density[j]; // update dose with trapezoidal rule + } + else { + _dose[j] += _dE * _fluxNew[j] * _s[_nEnergies - n - 1] / _density[j]; + } + _solverOutput[j] = _fluxNew[j]; + _flux[j] = _fluxNew[j]; + } + // --- Compute Flux for solution and Screen Output --- ComputeRadFlux(); } @@ -340,16 +354,7 @@ void CSDSolverTrafoFP::WriteVolumeOutput( unsigned idx_pseudoTime ) { case MEDICAL: // Compute Dose for( unsigned idx_cell = 0; idx_cell < _nCells; ++idx_cell ) { - if( idx_cell > 0 ) { - _outputFields[idx_group][0][idx_cell] += - 0.5 * _dE * - ( _fluxNew[idx_cell] * _s[_nEnergies - idx_pseudoTime - 1] + _flux[idx_cell] * _s[_nEnergies - idx_pseudoTime] ) / - _density[idx_cell]; // update dose with trapezoidal rule - } - else { - _outputFields[idx_group][0][idx_cell] += - _dE * _fluxNew[idx_cell] * _s[_nEnergies - idx_pseudoTime - 1] / _density[idx_cell]; - } + _outputFields[idx_group][0][idx_cell] += _dose[idx_cell]; } // Compute normalized dose _outputFields[idx_group][1] = _outputFields[idx_group][0]; diff --git a/code/src/solvers/csdsolvertrafofp2d.cpp b/code/src/solvers/csdsolvertrafofp2d.cpp index 1e80a25..efd642f 100644 --- a/code/src/solvers/csdsolvertrafofp2d.cpp +++ b/code/src/solvers/csdsolvertrafofp2d.cpp @@ -247,16 +247,7 @@ void CSDSolverTrafoFP2D::WriteVolumeOutput( unsigned idx_pseudoTime ) { case MEDICAL: // Compute Dose for( unsigned idx_cell = 0; idx_cell < _nCells; ++idx_cell ) { - if( idx_cell > 0 ) { - _outputFields[idx_group][0][idx_cell] += - 0.5 * _dE * - ( _fluxNew[idx_cell] * _s[_nEnergies - idx_pseudoTime - 1] + _flux[idx_cell] * _s[_nEnergies - idx_pseudoTime] ) / - _density[idx_cell]; // update dose with trapezoidal rule - } - else { - _outputFields[idx_group][0][idx_cell] += - _dE * _fluxNew[idx_cell] * _s[_nEnergies - idx_pseudoTime - 1] / _density[idx_cell]; - } + _outputFields[idx_group][0][idx_cell] += _dose[idx_cell]; } // Compute normalized dose _outputFields[idx_group][1] = _outputFields[idx_group][0]; @@ -358,13 +349,27 @@ void CSDSolverTrafoFP2D::IterPreprocessing( unsigned idx_pseudotime ) { } } -void CSDSolverTrafoFP2D::IterPostprocessing() { +void CSDSolverTrafoFP2D::IterPostprocessing( unsigned idx_pseudotime ) { + unsigned n = idx_pseudotime; // --- Update Solution --- for( unsigned j = 0; j < _nCells; ++j ) { if( _boundaryCells[j] == BOUNDARY_TYPE::DIRICHLET ) continue; _sol[j] = _solNew[j]; } + for( unsigned j = 0; j < _nCells; ++j ) { + _fluxNew[j] = dot( _sol[j], _weights ); + if( n > 0 ) { + _dose[j] += 0.5 * _dE * ( _fluxNew[j] * _s[_nEnergies - n - 1] + _flux[j] * _s[_nEnergies - n] ) / + _density[j]; // update dose with trapezoidal rule + } + else { + _dose[j] += _dE * _fluxNew[j] * _s[_nEnergies - n - 1] / _density[j]; + } + _solverOutput[j] = _fluxNew[j]; + _flux[j] = _fluxNew[j]; + } + // --- Compute Flux for solution and Screen Output --- ComputeRadFlux(); } diff --git a/code/src/solvers/csdsolvertrafofpsh2d.cpp b/code/src/solvers/csdsolvertrafofpsh2d.cpp index c46c84a..71bacaa 100644 --- a/code/src/solvers/csdsolvertrafofpsh2d.cpp +++ b/code/src/solvers/csdsolvertrafofpsh2d.cpp @@ -357,16 +357,7 @@ void CSDSolverTrafoFPSH2D::WriteVolumeOutput( unsigned idx_pseudoTime ) { case MEDICAL: // Compute Dose for( unsigned idx_cell = 0; idx_cell < _nCells; ++idx_cell ) { - if( idx_cell > 0 ) { - _outputFields[idx_group][0][idx_cell] += - 0.5 * _dE * - ( _fluxNew[idx_cell] * _s[_nEnergies - idx_pseudoTime - 1] + _flux[idx_cell] * _s[_nEnergies - idx_pseudoTime] ) / - _density[idx_cell]; // update dose with trapezoidal rule - } - else { - _outputFields[idx_group][0][idx_cell] += - _dE * _fluxNew[idx_cell] * _s[_nEnergies - idx_pseudoTime - 1] / _density[idx_cell]; - } + _outputFields[idx_group][0][idx_cell] += _dose[idx_cell]; } // Compute normalized dose _outputFields[idx_group][1] = _outputFields[idx_group][0]; @@ -468,7 +459,8 @@ void CSDSolverTrafoFPSH2D::IterPreprocessing( unsigned idx_pseudotime ) { } } -void CSDSolverTrafoFPSH2D::IterPostprocessing() { +void CSDSolverTrafoFPSH2D::IterPostprocessing( unsigned idx_pseudotime ) { + unsigned n = idx_pseudotime; for( unsigned j = 0; j < _nCells; ++j ) { if( _boundaryCells[j] == BOUNDARY_TYPE::DIRICHLET ) continue; _sol[j] = _solNew[j]; @@ -476,6 +468,19 @@ void CSDSolverTrafoFPSH2D::IterPostprocessing() { // --- Compute Flux for solution and Screen Output --- ComputeRadFlux(); + + for( unsigned j = 0; j < _nCells; ++j ) { + _fluxNew[j] = dot( _sol[j], _weights ); + if( n > 0 ) { + _dose[j] += 0.5 * _dE * ( _fluxNew[j] * _s[_nEnergies - n - 1] + _flux[j] * _s[_nEnergies - n] ) / + _density[j]; // update dose with trapezoidal rule + } + else { + _dose[j] += _dE * _fluxNew[j] * _s[_nEnergies - n - 1] / _density[j]; + } + _solverOutput[j] = _fluxNew[j]; + _flux[j] = _fluxNew[j]; + } } void CSDSolverTrafoFPSH2D::SolverPreprocessing() { diff --git a/code/src/solvers/mnsolver.cpp b/code/src/solvers/mnsolver.cpp index 688c926..4784d4f 100644 --- a/code/src/solvers/mnsolver.cpp +++ b/code/src/solvers/mnsolver.cpp @@ -152,7 +152,7 @@ void MNSolver::IterPreprocessing( unsigned /*idx_pseudotime*/ ) { } } -void MNSolver::IterPostprocessing() { +void MNSolver::IterPostprocessing( unsigned idx_pseudotime ) { // --- Update Solution --- _sol = _solNew; diff --git a/code/src/solvers/pnsolver.cpp b/code/src/solvers/pnsolver.cpp index 4c99e59..0c793cf 100644 --- a/code/src/solvers/pnsolver.cpp +++ b/code/src/solvers/pnsolver.cpp @@ -57,7 +57,7 @@ void PNSolver::IterPreprocessing( unsigned /*idx_pseudotime*/ ) { // Nothing to preprocess for PNSolver } -void PNSolver::IterPostprocessing() { +void PNSolver::IterPostprocessing( unsigned idx_pseudotime ) { // --- Update Solution --- _sol = _solNew; diff --git a/code/src/solvers/snsolver.cpp b/code/src/solvers/snsolver.cpp index a3de1bf..c149eff 100644 --- a/code/src/solvers/snsolver.cpp +++ b/code/src/solvers/snsolver.cpp @@ -27,7 +27,7 @@ void SNSolver::IterPreprocessing( unsigned /*idx_pseudotime*/ ) { // Nothing to do for SNSolver } -void SNSolver::IterPostprocessing() { +void SNSolver::IterPostprocessing( unsigned idx_pseudotime ) { // --- Update Solution --- _sol = _solNew; diff --git a/code/src/solvers/solverbase.cpp b/code/src/solvers/solverbase.cpp index e11e652..931b944 100644 --- a/code/src/solvers/solverbase.cpp +++ b/code/src/solvers/solverbase.cpp @@ -146,7 +146,7 @@ void Solver::Solve() { FVMUpdate( iter ); // --- Iter Postprocessing --- - IterPostprocessing(); + IterPostprocessing( iter ); // --- Solver Output --- WriteVolumeOutput( iter ); -- GitLab From 3dea3304e4dd79488e2f00d07aa49fb34d87ea09 Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 11:30:33 +0100 Subject: [PATCH 17/67] Update physics.rst Former-commit-id: c62d2409a6c6752987171394c09208d020b7c4c0 --- doc/physics.rst | 88 +++++++++++++++++++------------------------------ 1 file changed, 33 insertions(+), 55 deletions(-) diff --git a/doc/physics.rst b/doc/physics.rst index ddc0c0f..398e677 100644 --- a/doc/physics.rst +++ b/doc/physics.rst @@ -2,83 +2,60 @@ Theory ================ -The kinetic theory is dedicated to describe the dynamical behavior of a many-particle system through ensemble averaging. -Particles, e.g. molecules, photons, neutrons, electrons and plasmas, travel along the trajectories and undergo occasional collisions that change their directions and energies. -Such dynamics can be formulated via operator splitting approach in the Boltzmann equation, i.e. - -.. math:: - :label: boltzmann - - \frac{\partial \psi}{\partial t}+v \cdot \nabla_x \psi = Q(\psi) - -where :math:`\psi` is the one-particle probability distribution function, :math:`v` is velocity and :math:`Q(\psi)` is the scattering term. -In the Kit-RT solver, we consider the liner Boltzmann equation - -.. math:: - :label: linearbz - - \partial_{t} f(v)+v \cdot \nabla_{x} f(v)=\sigma \int k\left(v, v^{\prime}\right)\left(f\left(v^{\prime}\right)-f(v)\right) d v^{\prime}-\tau f(v) - -where the particles don't interact with one another but scatter with the background material. -For convenience, we reformulate the particle velocity into polar coordinates. - -The physical world shows a diverse set of behaviors on different -characteristic scales. Consider the molecular motion of gases as an -example. Down to the finest scale of a many-particle system, the -Newton’s second law depicts particle motions via +A physical system exhibit different behaviors at characteristic different scales. +We are interested in the transport phenomena of many particle systems. +Down to the finest scale of a many-particle system, the Newton’s second law depicts particle motions via .. math:: \mathbf{F} = m \mathbf{a} -As a first order system it reads +which leads .. math:: \frac{d \mathbf x}{dt} = \mathbf v, \ \frac{d \mathbf v}{dt} = \frac{\mathbf F}{m} -An intuitive numerical algorithm is to get the numerous particles on -board and track the trajectories of them. A typical example is the -`Molecular Dynamics`_. This is not going to be efficient since there are -more than ``2e25`` molecules per cubic meter in normal atmosphere, and -things get even more complicated when you count on the N-body -interactions all the time. Some methods have been proposed to simplify -the computation. As an example, the `Direct simulation Monte Carlo`_ -employs certain molecular models and conduct the intermolecular -collisions in a stochastic manner. It significantly reduces the -computational cost, while the trade-off is the artificial fluctuations. -Many realizations must be simulated successively to average the -solutions and reduce the errors. +An intuitive numerical solution algorithm is to get the numerous particles on board and track the trajectories of them. +A typical example is the molecular dynamics (MD) method. +This is not going to be efficient since there are more than :math:`2\times 10^25` molecules per cubic meter in normal atmosphere, +and things get extremely complicated if the N-body interactions are counted all the time. +Some methods have been proposed to simplify the computation. +As an example, the Monte Carlo method employs certain particle models and conduct the interactions in a stochastic manner. +It significantly reduces the computational cost, while the trade-off is the artificial fluctuations. +Many realizations must be simulated successively to average the solutions and reduce the errors. -An alternative strategy is made from ensemble averaging, where the -coarse-grained modeling is used to provide a bottom-up view. At the mean -free path and collision time scale of molecules, particles travel freely -during most of time with mild intermolecular collisions. Such dynamics -can be described with an operator splitting approach, i.e. the kinetic -transport equation +An alternative strategy can be made from ensemble averaging, where the +coarse-grained modeling is used to provide a bottom-up view. +At the mean free path and collision time scale of particles. Such dynamics can be described with kinetic theory. +The Boltzmann equation can be formulated via an operator splitting approach. .. math:: + \partial_{t} f(v)+v \cdot \nabla_{x} f(v)=\int_{\mathcal R^3} \int_{\mathcal S^2} k\left(v, v^{\prime}\right) \left(f\left(v^{\prime}\right)f\left(v_*^{\prime}\right)-f(v)f(v_*)\right) d\Omega d v_* - \frac{\partial f}{\partial t}+ \mathbf v \cdot \nabla_\mathbf x f + \mathbf a \cdot \nabla_\mathbf v f = Q(f) - -where the left and right hand sides model particle transports and -collisions correspondingly. Different collision models can be inserted -into such equation. If the particles only collide with a background -material one obtains linear Boltzmann collision operator +where the left and right hand sides model particle transports and collisions correspondingly. +The distribution function :math:`f` is the probability of finding a particle with certain location, and :math:`{v, v_*}` denotes the velocities of two classes of colliding particles. +The collision kernel :math:`k` models the strength of collisions at different velocities. +Different collision models can be inserted into this framework. +In the KiT-RT solver, we are interested in the linear Boltzmann equation, where the particles don't interact with one another but scatter with the background material. +Therefore, the Boltzmann can be simplified as the linear equation with respect to :math:`f`. .. math:: + :label: linbz + \partial_{t} f(v)+v \cdot \nabla_{x} f(v)=\sigma \int k\left(v, v^{\prime}\right)\left(f\left(v^{\prime}\right)-f(v)\right) d v^{\prime}-\tau f(v) - Q(f)=\int_{\mathbb R^3} \mathcal B(\mathbf v_*, \mathbf v) \left[ f(\mathbf v_*)-f(\mathbf v)\right] d\mathbf v_* +It is often reformulated with polar coordinates -where the collision kernel ``\mathcal B`` models the strength of -collisions at different velocities. If the interactions among particles -are considered, the collision operator becomes nonlinear. For example, -the two-body collision results in nonlinear Boltzmann equation + +where the particles don't interact with one another but scatter with the background material. +For convenience, we reformulate the particle velocity into polar coordinates. .. math:: + :label: boltzmann - Q(f)=\int_{\mathbb R^3} \int_{\mathcal S^2} \mathcal B(\cos \beta, |\mathbf{v}-\mathbf{v_*}|) \left[ f(\mathbf v')f(\mathbf v_*')-f(\mathbf v)f(\mathbf v_*)\right] d\mathbf \Omega d\mathbf v_* + \frac{\partial \psi}{\partial t}+v \cdot \nabla_x \psi = Q(\psi) +The particle distribution :math:`\psi` is often called angular flux. The continuous slowing down approximation @@ -124,6 +101,7 @@ Now, we bring this system in a form which resembles the standard Boltzmann equat .. math:: :label: CSD3 + \begin{align} -S(E)\partial_E\left(S(E)\rho(x)\psi(E,x,\Omega)\right)+&\Omega\cdot\nabla_x S(E)\psi(E,x,\Omega)+\Sigma_t(E)S(E)\rho(x)\psi(E,x,\Omega)\\ &= \int_{\mathbb{S}^2}\Sigma_s(E,\Omega\cdot\Omega')S(E)\rho(x)\psi(E,x,\Omega')d\Omega'. -- GitLab From 83cc9c8d7f13f88e066cd11ba5f5ba20527a05f7 Mon Sep 17 00:00:00 2001 From: "jonas.kusch" Date: Fri, 26 Feb 2021 11:31:38 +0100 Subject: [PATCH 18/67] max energy corrected Former-commit-id: 6bceea72886dda0d18c2ed0198a9f63f013f010a --- code/src/solvers/csdsolvertrafofp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/src/solvers/csdsolvertrafofp.cpp b/code/src/solvers/csdsolvertrafofp.cpp index 33a803f..7027f51 100644 --- a/code/src/solvers/csdsolvertrafofp.cpp +++ b/code/src/solvers/csdsolvertrafofp.cpp @@ -17,7 +17,7 @@ CSDSolverTrafoFP::CSDSolverTrafoFP( Config* settings ) : SNSolver( settings ) { // Set angle and energies _energies = Vector( _nEnergies, 0.0 ); // equidistant _energyMin = 1e-4 * 0.511; - _energyMax = 10e0; + _energyMax = _settings->GetMaxEnergyCSD(); // write equidistant energy grid (false) or refined grid (true) GenerateEnergyGrid( false ); @@ -354,7 +354,7 @@ void CSDSolverTrafoFP::WriteVolumeOutput( unsigned idx_pseudoTime ) { case MEDICAL: // Compute Dose for( unsigned idx_cell = 0; idx_cell < _nCells; ++idx_cell ) { - _outputFields[idx_group][0][idx_cell] += _dose[idx_cell]; + _outputFields[idx_group][0][idx_cell] = _dose[idx_cell]; } // Compute normalized dose _outputFields[idx_group][1] = _outputFields[idx_group][0]; -- GitLab From bf3daef5b3eff181695a683d9363709d8d0f952c Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 11:36:14 +0100 Subject: [PATCH 19/67] Update physics.rst Former-commit-id: 4331ea9889d80136f5c486016d9de2f17e556117 --- doc/physics.rst | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/doc/physics.rst b/doc/physics.rst index 398e677..270c424 100644 --- a/doc/physics.rst +++ b/doc/physics.rst @@ -2,6 +2,9 @@ Theory ================ +The Boltzmann equation +--------- + A physical system exhibit different behaviors at characteristic different scales. We are interested in the transport phenomena of many particle systems. Down to the finest scale of a many-particle system, the Newton’s second law depicts particle motions via @@ -18,9 +21,9 @@ which leads An intuitive numerical solution algorithm is to get the numerous particles on board and track the trajectories of them. A typical example is the molecular dynamics (MD) method. -This is not going to be efficient since there are more than :math:`2\times 10^25` molecules per cubic meter in normal atmosphere, +This is not going to be efficient since there are more than :math:`2\times 10^{25}` molecules per cubic meter in normal atmosphere, and things get extremely complicated if the N-body interactions are counted all the time. -Some methods have been proposed to simplify the computation. +Simplifications can be conducted to accelerate the numerical computation. As an example, the Monte Carlo method employs certain particle models and conduct the interactions in a stochastic manner. It significantly reduces the computational cost, while the trade-off is the artificial fluctuations. Many realizations must be simulated successively to average the solutions and reduce the errors. @@ -34,14 +37,16 @@ The Boltzmann equation can be formulated via an operator splitting approach. \partial_{t} f(v)+v \cdot \nabla_{x} f(v)=\int_{\mathcal R^3} \int_{\mathcal S^2} k\left(v, v^{\prime}\right) \left(f\left(v^{\prime}\right)f\left(v_*^{\prime}\right)-f(v)f(v_*)\right) d\Omega d v_* where the left and right hand sides model particle transports and collisions correspondingly. -The distribution function :math:`f` is the probability of finding a particle with certain location, and :math:`{v, v_*}` denotes the velocities of two classes of colliding particles. +The distribution function :math:`f` is the probability of finding a particle with certain location, and :math:`\{v, v_*\}` denotes the velocities of two classes of colliding particles. The collision kernel :math:`k` models the strength of collisions at different velocities. -Different collision models can be inserted into this framework. + +Different collision models can be inserted into the Boltzmann equation. In the KiT-RT solver, we are interested in the linear Boltzmann equation, where the particles don't interact with one another but scatter with the background material. Therefore, the Boltzmann can be simplified as the linear equation with respect to :math:`f`. .. math:: :label: linbz + \partial_{t} f(v)+v \cdot \nabla_{x} f(v)=\sigma \int k\left(v, v^{\prime}\right)\left(f\left(v^{\prime}\right)-f(v)\right) d v^{\prime}-\tau f(v) It is often reformulated with polar coordinates @@ -53,9 +58,9 @@ For convenience, we reformulate the particle velocity into polar coordinates. .. math:: :label: boltzmann - \frac{\partial \psi}{\partial t}+v \cdot \nabla_x \psi = Q(\psi) + \frac{\partial \psi}{\partial t}+\Omega \cdot \nabla_x \psi = Q(\psi) -The particle distribution :math:`\psi` is often called angular flux. +The particle distribution :math:`\psi(t, x, \Omega, E)` is often called angular flux. The continuous slowing down approximation -- GitLab From f35b90cb574bf99e30708cbf1db9dd617a25a4c7 Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 11:58:42 +0100 Subject: [PATCH 20/67] Update physics.rst Former-commit-id: b8c5a54c9a4a18e08a4a55f1c609c57e10c1241a --- doc/physics.rst | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/doc/physics.rst b/doc/physics.rst index 270c424..c54caff 100644 --- a/doc/physics.rst +++ b/doc/physics.rst @@ -11,13 +11,13 @@ Down to the finest scale of a many-particle system, the Newton’s second law de .. math:: - \mathbf{F} = m \mathbf{a} + F = m a which leads .. math:: - \frac{d \mathbf x}{dt} = \mathbf v, \ \frac{d \mathbf v}{dt} = \frac{\mathbf F}{m} + \frac{d x}{dt} = v, \ \frac{d v}{dt} = \frac{F}{m} An intuitive numerical solution algorithm is to get the numerous particles on board and track the trajectories of them. A typical example is the molecular dynamics (MD) method. @@ -47,13 +47,13 @@ Therefore, the Boltzmann can be simplified as the linear equation with respect t .. math:: :label: linbz - \partial_{t} f(v)+v \cdot \nabla_{x} f(v)=\sigma \int k\left(v, v^{\prime}\right)\left(f\left(v^{\prime}\right)-f(v)\right) d v^{\prime}-\tau f(v) + \partial_{t} f(v)+v \cdot \nabla_{x} f(v)=\int k\left(v, v^{\prime}\right)\left(f\left(v^{\prime}\right)-f(v)\right) d v^{\prime}-\tau f(v) It is often reformulated with polar coordinates where the particles don't interact with one another but scatter with the background material. -For convenience, we reformulate the particle velocity into polar coordinates. +For convenience, we reformulate the particle velocity into polar coordinates :math:`\{r, \phi, \theta \}` .. math:: :label: boltzmann @@ -66,18 +66,20 @@ The particle distribution :math:`\psi(t, x, \Omega, E)` is often called angular The continuous slowing down approximation --------- -Our main goal is to compute the radiation dose +For the radiation therapy, the main goal is to compute the radiation dose accurately, which is defined as .. math:: D(x)=\frac{1}{\rho(x)}\int_0^{\infty}\int_{\mathbb{S}^2}S(E,x)\psi(E,x,\Omega)\,d\Omega dE. -The angular flux $\psi$ can be approximated by the continuous slowing down (CSD) equation, which reads +The angular flux $\psi$ can be approximated by a further approximation equation, i.e. the continuous slowing down (CSD) equation which reads .. math:: - -\partial_E\left(S(E,x)\psi(E,x,\Omega)\right)+\Omega\cdot\nabla_x\psi(E,x,\Omega)+\Sigma_t(E,x)\psi(E,x,\Omega) = \int_{\mathbb{S}^2}\Sigma_s(E,x,\Omega\cdot\Omega')\psi(E,x,\Omega')d\Omega'. + &-\partial_E\left(S(E,x)\psi(E,x,\Omega)\right)+\Omega\cdot\nabla_x\psi(E,x,\Omega)+\Sigma_t(E,x)\psi(E,x,\Omega) \\ + &= \int_{\mathbb{S}^2}\Sigma_s(E,x,\Omega\cdot\Omega')\psi(E,x,\Omega')d\Omega'. -Here $E\in\mathbb{R}_+$ is energy, $x\in D\subset \mathbb{R}^3$ is the spatial domain and $\Omega\in\mathbb{S}^2$ is the direction of travel. The stopping power $S$ is given by +Here :math:`E\in\mathbb{R}_+` is energy, :math:`x\in D\subset \mathbb{R}^3` is the spatial domain and :math:`\Omega\in\mathbb{S}^2` is the direction of travel. +The stopping power :math:`S` is given by .. math:: S(E,x) = \int_0^{\infty} E'\int_{-1}^1\Sigma(E,E',x,\mu)d\mu dE'. @@ -88,21 +90,21 @@ Since there are no absorption effects, the total cross section is given by \Sigma_t(E,x) = \Sigma_{s,0}(E,x)=2\pi \int_{-1}^1\Sigma_s(E,x,\mu)d\mu. -With a given background material density $\rho(x)$ now make the following assumptions +With a given background material density :math:`\rho(x)` now make the following assumptions .. math:: S(E,x) = S^{H_2O}(E)\rho(x), \\ \Sigma_t(E,x) = \Sigma_t^{H_2O}(E)\rho(x), \\ \Sigma_s(E,x,\Omega\cdot\Omega') = \Sigma_s(E,\Omega\cdot\Omega')\rho(x). -Leaving out the superscript $H_2O$, the CSD equation simplifies to +Leaving out the superscript :math:`H_2O`, the CSD equation simplifies to .. math:: :label: CSD2 -\partial_E\left(\rho(x)S(E)\psi(E,x,\Omega)\right)+\Omega\cdot\nabla_x\psi(E,x,\Omega)+\rho(x)\Sigma_t(E)\psi(E,x,\Omega) = \int_{\mathbb{S}^2}\rho(x)\Sigma_s(E,\Omega\cdot\Omega')\psi(E,x,\Omega')d\Omega'. -Now, we bring this system in a form which resembles the standard Boltzmann equation. Multiplying \eqref{eq:CSD2} with $S(E)$ gives +Now, we bring this system in a form which resembles the standard Boltzmann equation. Multiplying \eqref{eq:CSD2} with :math:`S(E)` gives .. math:: :label: CSD3 @@ -145,15 +147,15 @@ And by rearranging the terms, we finally get .. math:: \partial_{ E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) = \partial_{\widetilde{E}}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)\frac{1}{S(E(\widetilde E))}, -since $S(E(\widetilde E))$ is nonzero \ssnote{Is S always nonzero? Would make sense, physically.}. -Therefore, substituting $\widetilde E$ in \eqref{eq:CSD4} gives +since :math:`S(E(\widetilde E))` is nonzero. +Therefore, substituting :math:`\widetilde E` in \eqref{eq:CSD4} gives .. math:: :label: CSD5 -\partial_{\widetilde E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)+\Omega\cdot\nabla_x \frac{\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)}{\rho}+\widetilde\Sigma_t(\widetilde E)\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) = \int_{\mathbb{S}^2}\widetilde\Sigma_s(\widetilde E,\Omega\cdot\Omega')\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega')d\Omega'. -Here, we define $\widetilde\Sigma_{t}(\widetilde E):=\Sigma_t(E(\widetilde E))$ and $\widetilde\Sigma_{s}(\widetilde E,\Omega\cdot\Omega'):=\Sigma_s(E(\widetilde E),\Omega\cdot\Omega')$. Finally, to obtain a positive sign in front of the energy derivative, we transform to +Here, we define :math:`\widetilde\Sigma_{t}(\widetilde E):=\Sigma_t(E(\widetilde E))` and :math:`\widetilde\Sigma_{s}(\widetilde E,\Omega\cdot\Omega'):=\Sigma_s(E(\widetilde E),\Omega\cdot\Omega')`. Finally, to obtain a positive sign in front of the energy derivative, we transform to .. math:: \bar{E}(\widetilde{E}) = \widetilde{E}_{\text{max}}-\widetilde{E}. @@ -162,9 +164,10 @@ Then, with $\bar{\psi}(\bar{E},x,\Omega):=\widetilde{\widehat{\psi}}(\widetilde{ .. math:: :label: CSD6 + \partial_{\bar{E}}\bar{\psi}(\bar{E},x,\Omega)+\Omega\cdot\nabla_x \frac{\bar{\psi}(\bar{E},x,\Omega)}{\rho}+\bar\Sigma_t(\bar E)\bar{\psi}(\bar{E},x,\Omega) = \int_{\mathbb{S}^2}\bar\Sigma_s(\bar{E},\Omega\cdot\Omega')\bar{\psi}(\bar{E},x,\Omega')d\Omega'. -Dropping the bar notation and treating $\bar E$ as a pseudo-time $t$ gives a slightly modified version of the Boltzmann equation +Dropping the bar notation and treating :math:`\bar E` as a pseudo-time :math:`t` gives a slightly modified version of the Boltzmann equation .. math:: :label: CSDBoltzmann @@ -177,7 +180,7 @@ We are interested in computing the dose, which (when again using the original en .. math:: D(x) = \int_0^{\infty} \int_{\mathbb{S}^2} S(E)\psi(E,x,\Omega)\,d\Omega dE = \int_0^{\infty} \int_{\mathbb{S}^2} \frac{1}{\rho(x)}\widehat\psi(E,x,\Omega)\,d\Omega dE. -So let us check how we can compute the dose from our solution $\bar \psi(\bar E,x,\Omega)$. For this, let us substitute +So let us check how we can compute the dose from our solution :math:`\bar \psi(\bar E,x,\Omega)`. For this, let us substitute .. math:: :label: BarE @@ -187,6 +190,7 @@ So let us check how we can compute the dose from our solution $\bar \psi(\bar E, We have .. math:: + \frac{d\bar E(E)}{dE} = -\frac{1}{S(E)} which gives -- GitLab From dd2a12f46020c50a1897c305046226146e9e9d34 Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 12:08:10 +0100 Subject: [PATCH 21/67] Update physics.rst Former-commit-id: 3ff149f4528f585e3005222164ef9da1c8122e86 --- doc/physics.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/physics.rst b/doc/physics.rst index c54caff..aa89372 100644 --- a/doc/physics.rst +++ b/doc/physics.rst @@ -56,11 +56,12 @@ where the particles don't interact with one another but scatter with the backgro For convenience, we reformulate the particle velocity into polar coordinates :math:`\{r, \phi, \theta \}` .. math:: - :label: boltzmann + :label: porbz + + &\left[\frac{1}{\mathrm{~V}} \frac{\partial}{\partial t}+\Omega \cdot \nabla+\Sigma(r, E, t)\right] \psi(r, \Omega, E, t) \\ + &=\int_{0}^{\infty} d E^{\prime} \int_{\mathcal R^2} d \Omega^{\prime} \Sigma_{s}\left(r, \Omega^{\prime} \bullet \Omega, E^{\prime} \rightarrow E\right) \psi\left(r, \Omega^{\prime}, E^{\prime}, t\right) - \frac{\partial \psi}{\partial t}+\Omega \cdot \nabla_x \psi = Q(\psi) - -The particle distribution :math:`\psi(t, x, \Omega, E)` is often called angular flux. +The particle distribution :math:`\psi(t, r, \Omega, E)` here is often named as angular flux. The continuous slowing down approximation -- GitLab From daac2d5dcb6330eba4bb13a0c2a4357599e26e60 Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 12:54:22 +0100 Subject: [PATCH 22/67] Update theory Former-commit-id: 3bb9e46d786bfa1bff615b96494778d8395c75a7 --- doc/physics.rst | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/doc/physics.rst b/doc/physics.rst index aa89372..6d3c0ea 100644 --- a/doc/physics.rst +++ b/doc/physics.rst @@ -5,8 +5,8 @@ Theory The Boltzmann equation --------- -A physical system exhibit different behaviors at characteristic different scales. -We are interested in the transport phenomena of many particle systems. +The particle transport phenomena enjoy rich academic research value and application prospects. +A many-particle system can exhibit different behaviors at characteristic different scales. Down to the finest scale of a many-particle system, the Newton’s second law depicts particle motions via .. math:: @@ -23,6 +23,7 @@ An intuitive numerical solution algorithm is to get the numerous particles on bo A typical example is the molecular dynamics (MD) method. This is not going to be efficient since there are more than :math:`2\times 10^{25}` molecules per cubic meter in normal atmosphere, and things get extremely complicated if the N-body interactions are counted all the time. + Simplifications can be conducted to accelerate the numerical computation. As an example, the Monte Carlo method employs certain particle models and conduct the interactions in a stochastic manner. It significantly reduces the computational cost, while the trade-off is the artificial fluctuations. @@ -53,15 +54,15 @@ It is often reformulated with polar coordinates where the particles don't interact with one another but scatter with the background material. -For convenience, we reformulate the particle velocity into polar coordinates :math:`\{r, \phi, \theta \}` +For convenience, we reformulate the particle velocity into polar coordinates :math:`\{r, \phi, \theta \}`. .. math:: :label: porbz - &\left[\frac{1}{\mathrm{~V}} \frac{\partial}{\partial t}+\Omega \cdot \nabla+\Sigma(r, E, t)\right] \psi(r, \Omega, E, t) \\ - &=\int_{0}^{\infty} d E^{\prime} \int_{\mathcal R^2} d \Omega^{\prime} \Sigma_{s}\left(r, \Omega^{\prime} \bullet \Omega, E^{\prime} \rightarrow E\right) \psi\left(r, \Omega^{\prime}, E^{\prime}, t\right) + &\left[\frac{1}{\mathrm{~V}} \frac{\partial}{\partial t}+\Omega \cdot \nabla+\Sigma(r, E, t)\right] \psi(r, \Omega, E, t) \\ + &=\int_{0}^{\infty} d E^{\prime} \int_{\mathcal R^2} d \Omega^{\prime} \Sigma_{s}\left(r, \Omega^{\prime} \bullet \Omega, E^{\prime} \rightarrow E\right) \psi\left(r, \Omega^{\prime}, E^{\prime}, t\right) -The particle distribution :math:`\psi(t, r, \Omega, E)` here is often named as angular flux. +The particle distribution :math:`\psi(r, \Omega, E, t)` here is often named as angular flux. The continuous slowing down approximation @@ -199,10 +200,3 @@ which gives .. math:: D(x) =& -\int_{\infty}^{0} \int_{\mathbb{S}^2} \frac{1}{\rho(x)}\bar \psi(\bar E,x,\Omega)\frac{1}{S(E(\bar E))}\,d\Omega d\bar E\\ =& \int_{0}^{\infty} \frac{1}{\rho(x)S(E(\bar E))}\int_{\mathbb{S}^2} \bar \psi(\bar E,x,\Omega)\,d\Omega d\bar E. - -.. math:: - &\widehat{\psi}(E,x,\Omega) := \widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) :=\bar{\psi}(\bar{E},x,\Omega),\\ - &dE = -S(E) d\bar E(E), \\ - &D(x) = -\int_{\infty}^{0} \int_{\mathbb{S}^2} \frac{1}{\rho(x)}\bar \psi(\bar E,x,\Omega)S(E(\bar E))d\Omega d\bar E - = \int_{0}^{\infty} \frac{S(E(\bar E))}{\rho(x)}\int_{\mathbb{S}^2} \bar \psi(\bar E,x,\Omega)\,d\Omega d\bar E. - -- GitLab From 5efeb31b2935266e892a36bae2799d391bc53d55 Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 13:28:27 +0100 Subject: [PATCH 23/67] Update index Former-commit-id: e16f14670744dfcdfa910f0e8ba368c255b2e9a2 --- doc/index.rst | 38 +++++++++++++++++++++++++++++++------- doc/physics.rst | 35 +++++++++++++++++------------------ 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/doc/index.rst b/doc/index.rst index c3844d0..2910971 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -2,15 +2,39 @@ KiT-RT: a kinetic transport solver for radiation therapy =========================================================== -The KiT-RT framework is a powerful open source platform for radiation transport. -Its main focus is on radiotherapy planning in cancer treatment. -To allow problem-specific method selection, the framework provides different deterministic solver types. -This not only facilitates treatment planning, but also provides tools to investigate various research questions in the field of radiative transfer. -This goal is supported by an easily extensible code structure that allows straightforward implementation of additional methods and techniques. +The KiT-RT framework is an open source project for radiation transport written in C++ programming language. +It is interested in the evolution of many-particle systems, e.g. photons, neutrons, electrons, etc. +Based on the finite volume method (FVM), it provides an efficient tool to solve the Boltzmann and related equations in multiple dimensions. +Special attention has been paid to the application of radiation therapy and treatment planning. +The framework provides rich deterministic solver types for different domain-specific problems. +A list of current supported models and equations is as follows. +- linear Boltzmann (:math:`S_N`) equation +- spherical harmonics (:math:`P_N`) equations +- entropy-closure moment (:math:`M_N`) equations +- continuous slowing down equation +Design philosophy +------------------------ +The code hierarchy is designed as intuitive and neat as possible. +It's dedicated to providing a friendly interface for educational usage in kinetic theory and rich functionality for scientific research. +Benefiting from the brilliant expressiveness and low-overhead abstraction provided by the C++ programming language, we implement the easily extensible code structure, +which allow the users to focus on physics or easily extend the codes with their own methods. + + +What is new? +------------------------ +Finite volume method is a proven approach for simulating conservation laws. +Compared with the existing open-source softwares, e.g. OpenFOAM, SU2 and Clawpack, Kit-RT holds the novelty through the following points: +- Comprehensive support for kinetic theory and phase-space equations +- radiation therapy +- Lightweight design to ensure the flexibility for secondary development + +How to get help? +------------------------ The software is being developed by members of the group `CSMM `_ at the Karlsruhe Institute of Technology (KIT). -For more information, please feel free to get in touch with us (link to authors page). - +If you are interested in using KiT-RT or are trying to figure out how to use it, please feel free to get in touch with `us `_. +Do open an issue or pull request if you have questions, suggestions or solutions. + -------- Contents -------- diff --git a/doc/physics.rst b/doc/physics.rst index 6d3c0ea..b81acbb 100644 --- a/doc/physics.rst +++ b/doc/physics.rst @@ -50,19 +50,15 @@ Therefore, the Boltzmann can be simplified as the linear equation with respect t \partial_{t} f(v)+v \cdot \nabla_{x} f(v)=\int k\left(v, v^{\prime}\right)\left(f\left(v^{\prime}\right)-f(v)\right) d v^{\prime}-\tau f(v) -It is often reformulated with polar coordinates - - -where the particles don't interact with one another but scatter with the background material. -For convenience, we reformulate the particle velocity into polar coordinates :math:`\{r, \phi, \theta \}`. +For convenience, it is often reformulated with polar coordinates :math:`\{r, \phi, \theta \}`. .. math:: :label: porbz - &\left[\frac{1}{\mathrm{~V}} \frac{\partial}{\partial t}+\Omega \cdot \nabla+\Sigma(r, E, t)\right] \psi(r, \Omega, E, t) \\ - &=\int_{0}^{\infty} d E^{\prime} \int_{\mathcal R^2} d \Omega^{\prime} \Sigma_{s}\left(r, \Omega^{\prime} \bullet \Omega, E^{\prime} \rightarrow E\right) \psi\left(r, \Omega^{\prime}, E^{\prime}, t\right) + &\left[\frac{1}{v(E)} \frac{\partial}{\partial t}+\Omega \cdot \nabla+\Sigma_t (r, E, t)\right] \psi(r, \Omega, E, t) \\ + &=\int_{0}^{\infty} d E^{\prime} \int_{\mathcal R^2} d \Omega^{\prime} \Sigma_{s}\left(r, \Omega^{\prime} \bullet \Omega, E^{\prime} \rightarrow E\right) \psi\left(r, \Omega^{\prime}, E^{\prime}, t\right) + Q(r, \Omega, E, t) -The particle distribution :math:`\psi(r, \Omega, E, t)` here is often named as angular flux. +The particle distribution :math:`\psi(r, \Omega, E, t)` here is often named as angular flux, :math:`\{\Sigma_s, \Sigma_t \}` are the scattering and total cross sections correspondingly, and :math:`Q` denotes a source term. The continuous slowing down approximation @@ -74,7 +70,8 @@ For the radiation therapy, the main goal is to compute the radiation dose accura D(x)=\frac{1}{\rho(x)}\int_0^{\infty}\int_{\mathbb{S}^2}S(E,x)\psi(E,x,\Omega)\,d\Omega dE. -The angular flux $\psi$ can be approximated by a further approximation equation, i.e. the continuous slowing down (CSD) equation which reads +where :math:`\rho(x)` is the background material density. +The angular flux :math:`\psi` can be approximated by a further approximation equation, i.e. the continuous slowing down (CSD) equation which reads .. math:: &-\partial_E\left(S(E,x)\psi(E,x,\Omega)\right)+\Omega\cdot\nabla_x\psi(E,x,\Omega)+\Sigma_t(E,x)\psi(E,x,\Omega) \\ @@ -86,27 +83,29 @@ The stopping power :math:`S` is given by .. math:: S(E,x) = \int_0^{\infty} E'\int_{-1}^1\Sigma(E,E',x,\mu)d\mu dE'. -Since there are no absorption effects, the total cross section is given by +Let us assume there are no absorption effects, and thus the total cross section is given by .. math:: \Sigma_t(E,x) = \Sigma_{s,0}(E,x)=2\pi \int_{-1}^1\Sigma_s(E,x,\mu)d\mu. -With a given background material density :math:`\rho(x)` now make the following assumptions +With a given :math:`\rho(x)`, we now make the following assumptions .. math:: - S(E,x) = S^{H_2O}(E)\rho(x), \\ - \Sigma_t(E,x) = \Sigma_t^{H_2O}(E)\rho(x), \\ - \Sigma_s(E,x,\Omega\cdot\Omega') = \Sigma_s(E,\Omega\cdot\Omega')\rho(x). + &S(E,x) = S^{H_2O}(E)\rho(x), \\ + &\Sigma_t(E,x) = \Sigma_t^{H_2O}(E)\rho(x), \\ + &\Sigma_s(E,x,\Omega\cdot\Omega') = \Sigma_s(E,\Omega\cdot\Omega')\rho(x). -Leaving out the superscript :math:`H_2O`, the CSD equation simplifies to +Leaving out the superscript :math:`H_2O`, the CSD equation can be simplified as .. math:: :label: CSD2 - -\partial_E\left(\rho(x)S(E)\psi(E,x,\Omega)\right)+\Omega\cdot\nabla_x\psi(E,x,\Omega)+\rho(x)\Sigma_t(E)\psi(E,x,\Omega) = \int_{\mathbb{S}^2}\rho(x)\Sigma_s(E,\Omega\cdot\Omega')\psi(E,x,\Omega')d\Omega'. + &-\partial_E\left(\rho(x)S(E)\psi(E,x,\Omega)\right)+\Omega\cdot\nabla_x\psi(E,x,\Omega)+\rho(x)\Sigma_t(E)\psi(E,x,\Omega) \\ + &= \int_{\mathbb{S}^2}\rho(x)\Sigma_s(E,\Omega\cdot\Omega')\psi(E,x,\Omega')d\Omega'. -Now, we bring this system in a form which resembles the standard Boltzmann equation. Multiplying \eqref{eq:CSD2} with :math:`S(E)` gives +Now, we bring this system in a form which resembles the standard Boltzmann equation. +Multiplying :ref:`CSD2` with :math:`S(E)` gives .. math:: :label: CSD3 @@ -150,7 +149,7 @@ And by rearranging the terms, we finally get \partial_{ E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) = \partial_{\widetilde{E}}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)\frac{1}{S(E(\widetilde E))}, since :math:`S(E(\widetilde E))` is nonzero. -Therefore, substituting :math:`\widetilde E` in \eqref{eq:CSD4} gives +Therefore, substituting :math:`\widetilde E` in :ref:`CSD4` gives .. math:: :label: CSD5 -- GitLab From 6a97b0a1df568fefa48fc35789055b1a91c1f67f Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 13:44:35 +0100 Subject: [PATCH 24/67] Fix index Former-commit-id: a363c5d2e33a139a8dd70a828adcf39ad76332d7 --- doc/index.rst | 12 ++++++++---- doc/physics.rst | 12 ++++++------ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/doc/index.rst b/doc/index.rst index 2910971..4339960 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -1,5 +1,5 @@ =========================================================== -KiT-RT: a kinetic transport solver for radiation therapy +KiT-RT: A kinetic transport solver for radiation therapy =========================================================== The KiT-RT framework is an open source project for radiation transport written in C++ programming language. @@ -8,11 +8,13 @@ Based on the finite volume method (FVM), it provides an efficient tool to solve Special attention has been paid to the application of radiation therapy and treatment planning. The framework provides rich deterministic solver types for different domain-specific problems. A list of current supported models and equations is as follows. + - linear Boltzmann (:math:`S_N`) equation - spherical harmonics (:math:`P_N`) equations - entropy-closure moment (:math:`M_N`) equations - continuous slowing down equation + Design philosophy ------------------------ The code hierarchy is designed as intuitive and neat as possible. @@ -25,18 +27,20 @@ What is new? ------------------------ Finite volume method is a proven approach for simulating conservation laws. Compared with the existing open-source softwares, e.g. OpenFOAM, SU2 and Clawpack, Kit-RT holds the novelty through the following points: + - Comprehensive support for kinetic theory and phase-space equations -- radiation therapy +- Special focus on radiation therapy - Lightweight design to ensure the flexibility for secondary development + How to get help? ------------------------ The software is being developed by members of the group `CSMM `_ at the Karlsruhe Institute of Technology (KIT). -If you are interested in using KiT-RT or are trying to figure out how to use it, please feel free to get in touch with `us `_. +If you are interested in using KiT-RT or are trying to figure out how to use it, please feel free to get in touch with `us `_. Do open an issue or pull request if you have questions, suggestions or solutions. -------- -Contents +Table of contents -------- .. toctree:: diff --git a/doc/physics.rst b/doc/physics.rst index b81acbb..6a76d23 100644 --- a/doc/physics.rst +++ b/doc/physics.rst @@ -35,6 +35,7 @@ At the mean free path and collision time scale of particles. Such dynamics can b The Boltzmann equation can be formulated via an operator splitting approach. .. math:: + \partial_{t} f(v)+v \cdot \nabla_{x} f(v)=\int_{\mathcal R^3} \int_{\mathcal S^2} k\left(v, v^{\prime}\right) \left(f\left(v^{\prime}\right)f\left(v_*^{\prime}\right)-f(v)f(v_*)\right) d\Omega d v_* where the left and right hand sides model particle transports and collisions correspondingly. @@ -46,16 +47,14 @@ In the KiT-RT solver, we are interested in the linear Boltzmann equation, where Therefore, the Boltzmann can be simplified as the linear equation with respect to :math:`f`. .. math:: - :label: linbz - + \partial_{t} f(v)+v \cdot \nabla_{x} f(v)=\int k\left(v, v^{\prime}\right)\left(f\left(v^{\prime}\right)-f(v)\right) d v^{\prime}-\tau f(v) For convenience, it is often reformulated with polar coordinates :math:`\{r, \phi, \theta \}`. .. math:: - :label: porbz - - &\left[\frac{1}{v(E)} \frac{\partial}{\partial t}+\Omega \cdot \nabla+\Sigma_t (r, E, t)\right] \psi(r, \Omega, E, t) \\ + + &\left[\frac{1}{v(E)} \partial_{t} +\Omega \cdot \nabla+\Sigma_t (r, E, t)\right] \psi(r, \Omega, E, t) \\ &=\int_{0}^{\infty} d E^{\prime} \int_{\mathcal R^2} d \Omega^{\prime} \Sigma_{s}\left(r, \Omega^{\prime} \bullet \Omega, E^{\prime} \rightarrow E\right) \psi\left(r, \Omega^{\prime}, E^{\prime}, t\right) + Q(r, \Omega, E, t) The particle distribution :math:`\psi(r, \Omega, E, t)` here is often named as angular flux, :math:`\{\Sigma_s, \Sigma_t \}` are the scattering and total cross sections correspondingly, and :math:`Q` denotes a source term. @@ -154,7 +153,8 @@ Therefore, substituting :math:`\widetilde E` in :ref:`CSD4` gives .. math:: :label: CSD5 - -\partial_{\widetilde E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)+\Omega\cdot\nabla_x \frac{\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)}{\rho}+\widetilde\Sigma_t(\widetilde E)\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) = \int_{\mathbb{S}^2}\widetilde\Sigma_s(\widetilde E,\Omega\cdot\Omega')\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega')d\Omega'. + &-\partial_{\widetilde E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)+\Omega\cdot\nabla_x \frac{\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)}{\rho}+\widetilde\Sigma_t(\widetilde E)\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) + &= \int_{\mathbb{S}^2}\widetilde\Sigma_s(\widetilde E,\Omega\cdot\Omega')\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega')d\Omega'. Here, we define :math:`\widetilde\Sigma_{t}(\widetilde E):=\Sigma_t(E(\widetilde E))` and :math:`\widetilde\Sigma_{s}(\widetilde E,\Omega\cdot\Omega'):=\Sigma_s(E(\widetilde E),\Omega\cdot\Omega')`. Finally, to obtain a positive sign in front of the energy derivative, we transform to -- GitLab From 0cba1d18b23036df4aeec00851a4dd18ab9ee9c7 Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 13:57:54 +0100 Subject: [PATCH 25/67] Fix physics.rst Former-commit-id: 7d1e77c0117865ab0421b60b3b2864b08821332b --- doc/authors.rst | 18 +++++++++--------- doc/index.rst | 4 ++-- doc/physics.rst | 29 ++++++++++++++--------------- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/doc/authors.rst b/doc/authors.rst index c74a7e5..990d9b9 100644 --- a/doc/authors.rst +++ b/doc/authors.rst @@ -7,15 +7,15 @@ Authors KiT-RT Software ***************** -+--------------------+------------------------+ -|Main contributors | - Jannick Wolters | -| | - Jonas Kusch | -| | - Steffen Schotthöfer | -| | - Tianbai Xiao | -| | - Pia Stammer | -+--------------------+------------------------+ -|Other contributors | | -+--------------------+------------------------+ ++--------------------+----------------------------------------+ +|Main contributors | - Jannick Wolters | +| | - Jonas Kusch | +| | - Steffen Schotthöfer | +| | - Tianbai Xiao (tianbai.xiao@kit.edu) | +| | - Pia Stammer | ++--------------------+----------------------------------------+ +|Other contributors | | ++--------------------+----------------------------------------+ ********************* KiT-RT Dokumentation diff --git a/doc/index.rst b/doc/index.rst index 4339960..a2c14dc 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -39,9 +39,9 @@ The software is being developed by members of the group `CSMM `_. Do open an issue or pull request if you have questions, suggestions or solutions. --------- + Table of contents --------- +------------------------ .. toctree:: :maxdepth: 1 diff --git a/doc/physics.rst b/doc/physics.rst index 6a76d23..90dec79 100644 --- a/doc/physics.rst +++ b/doc/physics.rst @@ -11,13 +11,13 @@ Down to the finest scale of a many-particle system, the Newton’s second law de .. math:: - F = m a + F = m a, which leads .. math:: - \frac{d x}{dt} = v, \ \frac{d v}{dt} = \frac{F}{m} + \frac{d x}{dt} = v, \ \frac{d v}{dt} = \frac{F}{m}. An intuitive numerical solution algorithm is to get the numerous particles on board and track the trajectories of them. A typical example is the molecular dynamics (MD) method. @@ -32,11 +32,11 @@ Many realizations must be simulated successively to average the solutions and re An alternative strategy can be made from ensemble averaging, where the coarse-grained modeling is used to provide a bottom-up view. At the mean free path and collision time scale of particles. Such dynamics can be described with kinetic theory. -The Boltzmann equation can be formulated via an operator splitting approach. +The Boltzmann equation can be formulated via an operator splitting approach, i.e. .. math:: - \partial_{t} f(v)+v \cdot \nabla_{x} f(v)=\int_{\mathcal R^3} \int_{\mathcal S^2} k\left(v, v^{\prime}\right) \left(f\left(v^{\prime}\right)f\left(v_*^{\prime}\right)-f(v)f(v_*)\right) d\Omega d v_* + \partial_{t} f(v)+v \cdot \nabla_{x} f(v)=\int_{\mathcal R^3} \int_{\mathcal S^2} k\left(v, v^{\prime}\right) \left(f\left(v^{\prime}\right)f\left(v_*^{\prime}\right)-f(v)f(v_*)\right) d\Omega d v_*, where the left and right hand sides model particle transports and collisions correspondingly. The distribution function :math:`f` is the probability of finding a particle with certain location, and :math:`\{v, v_*\}` denotes the velocities of two classes of colliding particles. @@ -44,18 +44,18 @@ The collision kernel :math:`k` models the strength of collisions at different ve Different collision models can be inserted into the Boltzmann equation. In the KiT-RT solver, we are interested in the linear Boltzmann equation, where the particles don't interact with one another but scatter with the background material. -Therefore, the Boltzmann can be simplified as the linear equation with respect to :math:`f`. +Therefore, the Boltzmann can be simplified as the linear equation with respect to :math:`f` .. math:: - \partial_{t} f(v)+v \cdot \nabla_{x} f(v)=\int k\left(v, v^{\prime}\right)\left(f\left(v^{\prime}\right)-f(v)\right) d v^{\prime}-\tau f(v) + \partial_{t} f(v)+v \cdot \nabla_{x} f(v)=\int k\left(v, v^{\prime}\right)\left(f\left(v^{\prime}\right)-f(v)\right) d v^{\prime}-\tau f(v). -For convenience, it is often reformulated with polar coordinates :math:`\{r, \phi, \theta \}`. +For convenience, it is often reformulated with polar coordinates :math:`\{r, \phi, \theta \}`, .. math:: &\left[\frac{1}{v(E)} \partial_{t} +\Omega \cdot \nabla+\Sigma_t (r, E, t)\right] \psi(r, \Omega, E, t) \\ - &=\int_{0}^{\infty} d E^{\prime} \int_{\mathcal R^2} d \Omega^{\prime} \Sigma_{s}\left(r, \Omega^{\prime} \bullet \Omega, E^{\prime} \rightarrow E\right) \psi\left(r, \Omega^{\prime}, E^{\prime}, t\right) + Q(r, \Omega, E, t) + &=\int_{0}^{\infty} d E^{\prime} \int_{\mathcal R^2} d \Omega^{\prime} \Sigma_{s}\left(r, \Omega^{\prime} \bullet \Omega, E^{\prime} \rightarrow E\right) \psi\left(r, \Omega^{\prime}, E^{\prime}, t\right) + Q(r, \Omega, E, t). The particle distribution :math:`\psi(r, \Omega, E, t)` here is often named as angular flux, :math:`\{\Sigma_s, \Sigma_t \}` are the scattering and total cross sections correspondingly, and :math:`Q` denotes a source term. @@ -104,7 +104,7 @@ Leaving out the superscript :math:`H_2O`, the CSD equation can be simplified as &= \int_{\mathbb{S}^2}\rho(x)\Sigma_s(E,\Omega\cdot\Omega')\psi(E,x,\Omega')d\Omega'. Now, we bring this system in a form which resembles the standard Boltzmann equation. -Multiplying :ref:`CSD2` with :math:`S(E)` gives +Multiplying :eq:`CSD2` with :math:`S(E)` gives .. math:: :label: CSD3 @@ -148,20 +148,20 @@ And by rearranging the terms, we finally get \partial_{ E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) = \partial_{\widetilde{E}}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)\frac{1}{S(E(\widetilde E))}, since :math:`S(E(\widetilde E))` is nonzero. -Therefore, substituting :math:`\widetilde E` in :ref:`CSD4` gives +Therefore, substituting :math:`\widetilde E` in :eq:`CSD4` gives .. math:: :label: CSD5 - &-\partial_{\widetilde E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)+\Omega\cdot\nabla_x \frac{\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)}{\rho}+\widetilde\Sigma_t(\widetilde E)\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) - &= \int_{\mathbb{S}^2}\widetilde\Sigma_s(\widetilde E,\Omega\cdot\Omega')\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega')d\Omega'. + & -\partial_{\widetilde E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)+\Omega\cdot\nabla_x \frac{\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega)}{\rho}+\widetilde\Sigma_t(\widetilde E)\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) \\ + & = \int_{\mathbb{S}^2}\widetilde\Sigma_s(\widetilde E,\Omega\cdot\Omega')\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega')d\Omega'. Here, we define :math:`\widetilde\Sigma_{t}(\widetilde E):=\Sigma_t(E(\widetilde E))` and :math:`\widetilde\Sigma_{s}(\widetilde E,\Omega\cdot\Omega'):=\Sigma_s(E(\widetilde E),\Omega\cdot\Omega')`. Finally, to obtain a positive sign in front of the energy derivative, we transform to .. math:: \bar{E}(\widetilde{E}) = \widetilde{E}_{\text{max}}-\widetilde{E}. -Then, with $\bar{\psi}(\bar{E},x,\Omega):=\widetilde{\widehat{\psi}}(\widetilde{E}(\bar{E}),x,\Omega)$ and $\bar\Sigma_{t}(\bar E):=\widetilde{\Sigma}_t(\widetilde{E}(\bar{E}))$ as well as $\bar\Sigma_{s}(\bar E,\Omega\cdot\Omega'):=\widetilde{\Sigma}_s(\widetilde{E}(\bar{E}),\Omega\cdot\Omega')$ equation \eqref{eq:CSD4} becomes +Then, with :math:`\bar{\psi}(\bar{E},x,\Omega):=\widetilde{\widehat{\psi}}(\widetilde{E}(\bar{E}),x,\Omega)`, :math:`\bar\Sigma_{t}(\bar E):=\widetilde{\Sigma}_t(\widetilde{E}(\bar{E}))` as well as :math:`\bar\Sigma_{s}(\bar E,\Omega\cdot\Omega'):=\widetilde{\Sigma}_s(\widetilde{E}(\bar{E}),\Omega\cdot\Omega')` equation \eqref{eq:CSD4} becomes .. math:: :label: CSD6 @@ -176,7 +176,7 @@ Dropping the bar notation and treating :math:`\bar E` as a pseudo-time :math:`t` \partial_{t}\psi(t,x,\Omega)+&\Omega\cdot\nabla_x \frac{\psi(t,x,\Omega)}{\rho}+\Sigma_t(t)\psi(t,x,\Omega) = \int_{\mathbb{S}^2}\Sigma_s(t,\Omega\cdot\Omega')\psi(t,x,\Omega')d\Omega'\\ &\psi(t=0,x,\Omega) = S(E_{\text{max}})\rho(x)\psi(E_{\text{max}},x,\Omega). -We are interested in computing the dose, which (when again using the original energy $E$ and angular flux $\psi$) reads +We are interested in computing the dose, which (when again using the original energy :math:`E` and angular flux :math:`\psi`) reads .. math:: D(x) = \int_0^{\infty} \int_{\mathbb{S}^2} S(E)\psi(E,x,\Omega)\,d\Omega dE = \int_0^{\infty} \int_{\mathbb{S}^2} \frac{1}{\rho(x)}\widehat\psi(E,x,\Omega)\,d\Omega dE. @@ -184,7 +184,6 @@ We are interested in computing the dose, which (when again using the original en So let us check how we can compute the dose from our solution :math:`\bar \psi(\bar E,x,\Omega)`. For this, let us substitute .. math:: - :label: BarE \bar E(E) = \tilde{E}(E_{max}) - \int_0^E \frac{1}{S(E')}dE'. -- GitLab From 3fa0a78be955d4cbda959ee830c06574ad9683a9 Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 14:03:23 +0100 Subject: [PATCH 26/67] Fix physics.rst Former-commit-id: 3018795ed534780ff7a7db74d3cb3a8f9e9b0ad2 --- doc/physics.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/physics.rst b/doc/physics.rst index 90dec79..af28dca 100644 --- a/doc/physics.rst +++ b/doc/physics.rst @@ -119,10 +119,11 @@ Then, we substitute .. math:: \widehat{\psi}(E,x,\Omega):= S(E)\rho(x)\psi(E,x,\Omega) -into \eqref{eq:CSD3}, which yields +into :eq:`CSD3`, which yields .. math:: :label: CSD4 + -S(E)\partial_E\widehat{\psi}(E,x,\Omega)+\Omega\cdot\nabla_x \frac{\widehat{\psi}(E,x,\Omega)}{\rho}+\Sigma_t(E)\widehat{\psi}(E,x,\Omega) = \int_{\mathbb{S}^2}\Sigma_s(E,\Omega\cdot\Omega')\widehat{\psi}(E,x,\Omega')d\Omega'. Now, to get rid of the stopping power in front of the energy derivative, we make use of the transformation @@ -140,7 +141,7 @@ Now let us change to In this case, the energy derivative becomes .. math:: - \partial_{\widetilde{E}}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) = \partial_{E}\widetilde{\widehat{\psi}}( E,x,\Omega)\partial_{\widetlde E }E(\widetilde E(\widetilde E) = \partial_{ E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega){S(E(\widetilde E))}. + \partial_{\widetilde{E}}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega) = \partial_{E}\widetilde{\widehat{\psi}}( E,x,\Omega)\partial_{\widetilde E }E(\widetilde E(\widetilde E) = \partial_{ E}\widetilde{\widehat{\psi}}(\widetilde E,x,\Omega){S(E(\widetilde E))}. And by rearranging the terms, we finally get @@ -161,7 +162,7 @@ Here, we define :math:`\widetilde\Sigma_{t}(\widetilde E):=\Sigma_t(E(\widetilde .. math:: \bar{E}(\widetilde{E}) = \widetilde{E}_{\text{max}}-\widetilde{E}. -Then, with :math:`\bar{\psi}(\bar{E},x,\Omega):=\widetilde{\widehat{\psi}}(\widetilde{E}(\bar{E}),x,\Omega)`, :math:`\bar\Sigma_{t}(\bar E):=\widetilde{\Sigma}_t(\widetilde{E}(\bar{E}))` as well as :math:`\bar\Sigma_{s}(\bar E,\Omega\cdot\Omega'):=\widetilde{\Sigma}_s(\widetilde{E}(\bar{E}),\Omega\cdot\Omega')` equation \eqref{eq:CSD4} becomes +Then, with :math:`\bar{\psi}(\bar{E},x,\Omega):=\widetilde{\widehat{\psi}}(\widetilde{E}(\bar{E}),x,\Omega)`, :math:`\bar\Sigma_{t}(\bar E):=\widetilde{\Sigma}_t(\widetilde{E}(\bar{E}))` as well as :math:`\bar\Sigma_{s}(\bar E,\Omega\cdot\Omega'):=\widetilde{\Sigma}_s(\widetilde{E}(\bar{E}),\Omega\cdot\Omega')` equation :eq:`CSD4` becomes .. math:: :label: CSD6 -- GitLab From 0882c5933eae797154e54a15472639c4af2898b0 Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 14:13:16 +0100 Subject: [PATCH 27/67] Finish theory documentation Former-commit-id: 148aafc67166865946d021b89528fb47d935a670 --- doc/installation.rst | 57 -------------------------------------------- doc/physics.rst | 3 ++- 2 files changed, 2 insertions(+), 58 deletions(-) diff --git a/doc/installation.rst b/doc/installation.rst index 2a890cb..29ca464 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -57,9 +57,6 @@ The resulting executable will automatically be placed in the `code/bin` folder. Run ********** -Local -=========== - Execute the compiled binary from the `bin` folder and hand over a valid *TOML*-styled config file. Example from inside the `code` directory: @@ -75,56 +72,6 @@ OMP_NUM_THREADS=N mpirun -np J ./KiT-RT ../input/example.cfg with `N` equal to the number of shared memory threads and `J` equal to the number of distrubuted memory threads. -BwUniCluster -============== - -As VTK is not available on the bwUniCluster, it needs to be installed first. This just needs to be done once. Example: - -.. code-block:: bash - - module load devel/cmake/3.16 - module load compiler/gnu/9.2 - wget --no-check-certificate --quiet https://www.vtk.org/files/release/8.2/VTK-8.2.0.tar.gz - tar xzf VTK-8.2.0.tar.gz - mkdir VTK-build - cd VTK-build - cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_DOCUMENTATION=OFF -DBUILD_TESTING=OFF - - DCMAKE_INSTALL_PREFIX=~/VTK-install ../VTK-8.2.0 - make -j - make install - cd - - rm -r VTK-8.2.0 VTK-build - - -Example for build and run on bwUniCluster: -Get the code - -.. code-block:: bash - - git clone https://git.scc.kit.edu/rtsn/rtsn.git KiT-RT - cd KiT-RT/ - git submodule init - git submodule update - -Append ``HINTS VTK_INSTALL_DIR` to the ``find_package( VTK ... )`` line in the CMakeLists.txt. E.g.: - -.. code-block:: bash - - find_package( VTK REQUIRED COMPONENTS vtkIOGeometry vtkFiltersCore HINTS ~/VTK-install ) - - -Compile it - -.. code-block:: bash - - module load devel/cmake/3.16 - module load compiler/gnu/9.2 - module load mpi/openmpi/4.0 - cd code/build/release/ - cmake -DCMAKE_BUILD_TYPE=Release ../../ - make -j - - --------------------------------------------------------------- Tests @@ -138,7 +85,3 @@ After compiling the framework as described above just run: The ``unit_tests`` executable will also be placed in in the build folder. - - - - diff --git a/doc/physics.rst b/doc/physics.rst index af28dca..9606706 100644 --- a/doc/physics.rst +++ b/doc/physics.rst @@ -124,7 +124,8 @@ into :eq:`CSD3`, which yields .. math:: :label: CSD4 - -S(E)\partial_E\widehat{\psi}(E,x,\Omega)+\Omega\cdot\nabla_x \frac{\widehat{\psi}(E,x,\Omega)}{\rho}+\Sigma_t(E)\widehat{\psi}(E,x,\Omega) = \int_{\mathbb{S}^2}\Sigma_s(E,\Omega\cdot\Omega')\widehat{\psi}(E,x,\Omega')d\Omega'. + & -S(E)\partial_E\widehat{\psi}(E,x,\Omega)+\Omega\cdot\nabla_x \frac{\widehat{\psi}(E,x,\Omega)}{\rho}+\Sigma_t(E)\widehat{\psi}(E,x,\Omega) \\ + & = \int_{\mathbb{S}^2}\Sigma_s(E,\Omega\cdot\Omega')\widehat{\psi}(E,x,\Omega')d\Omega'. Now, to get rid of the stopping power in front of the energy derivative, we make use of the transformation -- GitLab From 9f26f65eb6f5b5cd8981ca31a70993b016a4751a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Fri, 26 Feb 2021 14:36:46 +0100 Subject: [PATCH 28/67] added private and protected members to documentation. revised solverbase documentation Former-commit-id: da107902343e886329c7f2877d51902d4ad7a3d5 --- code/include/solvers/mnsolver.h | 2 +- code/include/solvers/pnsolver.h | 2 +- code/include/solvers/snsolver.h | 2 +- code/include/solvers/solverbase.h | 148 ++++++++++++++++-------------- code/src/main.cpp | 2 +- code/src/solvers/mnsolver.cpp | 2 +- code/src/solvers/pnsolver.cpp | 2 +- code/src/solvers/snsolver.cpp | 2 +- code/src/solvers/solverbase.cpp | 31 +++---- code/tests/test_cases.cpp | 38 ++++---- doc/Doxyfile.in | 6 +- doc/solvers/index.rst | 2 +- doc/solvers/solver.rst | 5 - 13 files changed, 122 insertions(+), 122 deletions(-) delete mode 100644 doc/solvers/solver.rst diff --git a/code/include/solvers/mnsolver.h b/code/include/solvers/mnsolver.h index 560a5f6..dc69abe 100644 --- a/code/include/solvers/mnsolver.h +++ b/code/include/solvers/mnsolver.h @@ -7,7 +7,7 @@ class EntropyBase; class SphericalBase; class OptimizerBase; -class MNSolver : public Solver +class MNSolver : public SolverBase { public: /** diff --git a/code/include/solvers/pnsolver.h b/code/include/solvers/pnsolver.h index 188af18..ab362f6 100644 --- a/code/include/solvers/pnsolver.h +++ b/code/include/solvers/pnsolver.h @@ -3,7 +3,7 @@ #include "solvers/solverbase.h" -class PNSolver : public Solver +class PNSolver : public SolverBase { public: /*! @brief PNSolver constructor diff --git a/code/include/solvers/snsolver.h b/code/include/solvers/snsolver.h index b527119..d1e9d95 100644 --- a/code/include/solvers/snsolver.h +++ b/code/include/solvers/snsolver.h @@ -3,7 +3,7 @@ #include "solvers/solverbase.h" -class SNSolver : public Solver +class SNSolver : public SolverBase { protected: Matrix _scatteringKernel; /*! @brief scattering kernel for the quadrature */ diff --git a/code/include/solvers/solverbase.h b/code/include/solvers/solverbase.h index b536004..78bafb5 100644 --- a/code/include/solvers/solverbase.h +++ b/code/include/solvers/solverbase.h @@ -16,90 +16,90 @@ class ProblemBase; class QuadratureBase; class Reconstructor; -class Solver +/*! @brief Base class for all solvers. */ +class SolverBase { protected: - Mesh* _mesh; /*! @brief mesh object for writing out information */ - NumericalFlux* _g; /*! @brief class for numerical flux */ - Config* _settings; /*! @brief config class for global information */ - ProblemBase* _problem; /*! @brief problem class for initial conditions */ + NumericalFlux* _g; /*!< @brief class for numerical flux */ + Config* _settings; /*!< @brief config class for global information */ + ProblemBase* _problem; /*!< @brief problem class for initial conditions */ // --------- Often used variables of member classes for faster access ---- - unsigned _nEnergies; /*! @brief number of energysteps, number of nodal energy values for CSD */ - unsigned _maxIter; /*! @brief number of time steps, for non CSD, this equals _nEnergies, for _csd, _maxIter = _nEnergies-1*/ + // Time or Energystepping + unsigned _maxIter; /*!< @brief number of time steps, for non CSD, this equals _nEnergies, for _csd, _maxIter = _nEnergies-1*/ + unsigned _nEnergies; /*!< @brief number of energysteps, number of nodal energy values for CSD */ + double _dE; /*!< @brief energy/time step size */ + Vector _energies; /*!< @brief energy groups used in the simulation [keV] */ - double _dE; /*! @brief energy/time step size */ - Vector _energies; // energy groups used in the simulation [keV] - std::vector _density; // patient density, dim(_density) = _nCells - Vector _s; // stopping power, dim(_s) = _nTimeSteps (only for csdsolver) - std::vector _Q; /*! @brief external source term */ - - VectorVector _sigmaS; /*! @brief scattering cross section for all energies. len: _nEnergies x numCells */ - VectorVector _sigmaT; /*! @brief total cross section for all energies. len: _nEnergies x numCells*/ + // Mesh related members + Mesh* _mesh; /*!< @brief mesh object for writing out information */ + unsigned _nCells; /*!< @brief number of spatial cells */ + std::vector _boundaryCells; /*!< @brief boundary type for all cells, dim(_boundary) = (_NCells) */ + std::vector _areas; /*!< @brief surface area of all spatial cells, dim(_areas) = _NCells */ + std::vector> + _normals; /*!< @brief edge normals multiplied by edge length, dim(_normals) = (_NCells,nEdgesPerCell,spatialDim) */ + std::vector> _neighbors; /*!< @brief edge neighbor cell ids, dim(_neighbors) = (_NCells,nEdgesPerCell) */ - // quadrature related numbers - QuadratureBase* _quadrature; /*! @brief quadrature to create members below */ - unsigned _nq; /*! @brief number of quadrature points */ + // slope related params + Reconstructor* _reconstructor; /*!< @brief reconstructor object for high-order scheme */ + unsigned _reconsOrder; /*!< @brief reconstruction order (current: 1 & 2) */ + VectorVector _psiDx; /*!< @brief slope of solutions in X direction */ + VectorVector _psiDy; /*!< @brief slope of solutions in Y direction */ + VectorVector _cellMidPoints; /*!< @brief middle point locations of elements */ + std::vector> _interfaceMidPoints; /*!< @brief middle point locations of edges */ - // VectorVector _quadPoints; /*! @brief quadrature points, dim(_quadPoints) = (_nSystem,spatialDim) */ - // Vector _weights; /*! @brief quadrature weights, dim(_weights) = (_NCells) */ + std::vector _density; /*!< @brief patient density, dim(_density) = _nCells (only for csdsolver) */ + Vector _s; /*!< @brief stopping power, dim(_s) = _maxIter (only for csdsolver) */ - // Mesh related members - unsigned _nCells; /*! @brief number of spatial cells */ - std::vector _boundaryCells; /*! boundary type for all cells, dim(_boundary) = (_NCells) */ - std::vector _areas; /*! @brief surface area of all spatial cells, dim(_areas) = _NCells */ - /*! @brief edge normals multiplied by edge length, dim(_normals) = (_NCells,nEdgesPerCell,spatialDim) */ - std::vector> _normals; - /*! @brief edge neighbor cell ids, dim(_neighbors) = (_NCells,nEdgesPerCell) */ - std::vector> _neighbors; + std::vector _Q; /*!< @brief external source term. Dim(_Q) = _maxIter x (_nCells x _nSystem) */ + VectorVector _sigmaS; /*!< @brief scattering cross section for all energies. len: _nEnergies x _nCells */ + VectorVector _sigmaT; /*!< @brief total cross section for all energies. len: _nEnergies x _nCells*/ - // slope related params - Reconstructor* _reconstructor; /*! @brief reconstructor object for high-order scheme */ - unsigned _reconsOrder; /*! @brief reconstruction order (current: 1 & 2) */ - VectorVector _psiDx; /*! @brief slope of solutions in X direction */ - VectorVector _psiDy; /*! @brief slope of solutions in Y direction */ - VectorVector _cellMidPoints; /*! @brief middle point locations of elements */ - std::vector> _interfaceMidPoints; /*! @brief middle point locations of edges */ + // quadrature related numbers + QuadratureBase* _quadrature; /*!< @brief pointer to quadrature class */ + unsigned _nq; /*!< @brief number of quadrature points */ // Solution related members - VectorVector _sol; /*! @brief solution of the PDE, e.g. angular flux or moments */ - std::vector _solverOutput; /*! @brief LEGACY: Outputfield for solver ==> Will be replaced by _outputFields in the near future */ + VectorVector _sol; /*!< @brief solution of the PDE, e.g. angular flux or moments */ + VectorVector _solNew; /*!< @brief VectorVector to store the new flux and later the new solution per iteration */ + Vector _fluxNew; /*!< @brief Vector to store the new Flux. Dim _nCells */ + Vector _flux; /*!< @brief Vector to store the old Flux. Dim _nCells*/ + + std::vector _solverOutput; /*!< @brief LEGACY: Outputfield for solver ==> Will be replaced by _outputFields in the near future */ // Output related members - std::vector>> _outputFields; /*! @brief: Solver Output: dimensions (GroupID,FieldID,CellID).*/ - std::vector> _outputFieldNames; /*! @brief: Names of the outputFields: dimensions (GroupID,FieldID) */ + std::vector>> _outputFields; /*!< @brief: Solver Output: dimensions (GroupID,FieldID,CellID).*/ + std::vector> _outputFieldNames; /*!< @brief: Names of the outputFields: dimensions (GroupID,FieldID) */ // we will have to add a further dimension for quadPoints and weights once we start with multilevel SN // Output related members - std::vector _screenOutputFields; /*! @brief: Solver Output: dimensions (FieldID). */ - std::vector _screenOutputFieldNames; /*! @brief: Names of the outputFields: dimensions (FieldID) */ + std::vector _screenOutputFields; /*!< @brief: Solver Output: dimensions (FieldID). */ + std::vector _screenOutputFieldNames; /*!< @brief: Names of the outputFields: dimensions (FieldID) */ // Output related members - std::vector _historyOutputFields; /*! @brief: Solver Output: dimensions (FieldID). */ - std::vector _historyOutputFieldNames; /*! @brief: Names of the outputFields: dimensions (FieldID) */ - - // Internal Members - VectorVector _solNew; /*! @brief: VectorVector to store the new flux and later the new solution per iteration */ // REPLACES psiNEW - Vector _fluxNew; /*! @brief: Vector to store the new Flux. Dim _nCells */ - Vector _flux; /*! @brief: Vector to store the old Flux. Dim _nCells*/ + std::vector _historyOutputFields; /*!< @brief: Solver Output: dimensions (FieldID). */ + std::vector _historyOutputFieldNames; /*!< @brief: Names of the outputFields: dimensions (FieldID) */ // ---- Member functions ---- // Solver - /*! @brief Performs preprocessing steps before the pseudo time iteration is started */ + /*! @brief Performs preprocessing steps before the pseudo time iteration is started*/ virtual void SolverPreprocessing(); - /*! @brief Performs preprocessing for the current solver iteration */ - virtual void IterPreprocessing( unsigned idx_pseudotime ) = 0; + /*! @brief Performs preprocessing for the current solver iteration + @param idx_iter : current (peudo) time iteration */ + virtual void IterPreprocessing( unsigned idx_iter ) = 0; /*! @brief Performs postprocessing for the current solver iteration */ virtual void IterPostprocessing() = 0; /*! @brief Constructs the flux update for the current iteration and stores it in psiNew*/ virtual void FluxUpdate() = 0; - /*! @brief Computes the finite Volume update step for the current iteration */ - virtual void FVMUpdate( unsigned idx_energy ) = 0; + /*! @brief Computes the finite Volume update step for the current iteration + @param idx_iter : current (peudo) time iteration */ + virtual void FVMUpdate( unsigned idx_iter ) = 0; // Helper - /*! @brief ComputeTimeStep calculates the maximal stable time step */ + /*! @brief ComputeTimeStep calculates the maximal stable time step using the cfl number + @param used cfl number */ double ComputeTimeStep( double cfl ) const; /*! @brief: Computes the flux of the solution to check conservation properties */ virtual void ComputeRadFlux() = 0; @@ -107,23 +107,29 @@ class Solver // IO /*! @brief Initializes the output groups and fields of this solver and names the fields */ virtual void PrepareVolumeOutput() = 0; - /*! @brief Function that prepares VTK export and csv export of the current solver iteration */ - virtual void WriteVolumeOutput( unsigned iteration ) = 0; + /*! @brief Function that prepares VTK export and csv export of the current solver iteration + @param idx_iter : current (pseudo) time iteration */ + virtual void WriteVolumeOutput( unsigned idx_iter ) = 0; /*! @brief Save Output solution at given energy (pseudo time) to VTK file. Write frequency is given by - option VOLUME_OUTPUT_FREQUENCY. Always prints last iteration without iteration affix.*/ - void PrintVolumeOutput( int currEnergy ) const; + option VOLUME_OUTPUT_FREQUENCY. Always prints last iteration without iteration affix. + @param idx_iter : current (pseudo) time iteration */ + void PrintVolumeOutput( int idx_iter ) const; /*! @brief: Initialized the output fields and their Names for the screenoutput */ void PrepareScreenOutput(); - /*! @brief Function that writes screen and history output fields */ - void WriteScalarOutput( unsigned iteration ); + + /*! @brief Function that writes screen and history output fields + @param idx_iter : current (pseudo) time iteration */ + void WriteScalarOutput( unsigned idx_iter ); /*! @brief Prints ScreenOutputFields to Screen and to logger. Write frequency is given by - option SCREEN_OUTPUT_FREQUENCY. Always prints last iteration. */ - void PrintScreenOutput( unsigned iteration ); + option SCREEN_OUTPUT_FREQUENCY. Always prints last iteration. + @param idx_iter : current (pseudo) time iteration */ + void PrintScreenOutput( unsigned idx_iter ); /*! @brief: Initialized the historyOutputFields and their Names for history output. Write frequency is given by option HISTORY_OUTPUT_FREQUENCY. Always prints last iteration. */ void PrepareHistoryOutput(); - /*! @brief Prints HistoryOutputFields to logger */ - void PrintHistoryOutput( unsigned iteration ); + /*! @brief Prints HistoryOutputFields to logger + @param idx_iter : current (pseudo) time iteration */ + void PrintHistoryOutput( unsigned idx_iter ); /*! @brief Pre Solver Screen and Logger Output */ void DrawPreSolverOutput(); /*! @brief Post Solver Screen and Logger Output */ @@ -131,17 +137,17 @@ class Solver public: /*! @brief Solver constructor - * @param settings stores all needed information */ - Solver( Config* settings ); + * @param settings :config class that stores all needed config information */ + SolverBase( Config* settings ); - virtual ~Solver(); + virtual ~SolverBase(); /*! @brief Create constructor - * @param settings stores all needed information - * @return pointer to Solver */ - static Solver* Create( Config* settings ); + * @param settings :config class that stores all needed config information + * @return pointer to SolverBase */ + static SolverBase* Create( Config* settings ); - /*! @brief Solve functions runs main time loop */ + /*! @brief Solve functions runs main iteration loop. Components of the solve loop are pure virtual and subclassed by the child solvers. */ virtual void Solve(); /*! @brief Save Output solution to VTK file */ diff --git a/code/src/main.cpp b/code/src/main.cpp index 09272cf..1142342 100644 --- a/code/src/main.cpp +++ b/code/src/main.cpp @@ -48,7 +48,7 @@ int main( int argc, char** argv ) { } else { // Build solver - Solver* solver = Solver::Create( config ); + SolverBase* solver = SolverBase::Create( config ); // Run solver and export solver->Solve(); diff --git a/code/src/solvers/mnsolver.cpp b/code/src/solvers/mnsolver.cpp index 688c926..91191c2 100644 --- a/code/src/solvers/mnsolver.cpp +++ b/code/src/solvers/mnsolver.cpp @@ -17,7 +17,7 @@ #include -MNSolver::MNSolver( Config* settings ) : Solver( settings ) { +MNSolver::MNSolver( Config* settings ) : SolverBase( settings ) { _LMaxDegree = settings->GetMaxMomentDegree(); _basis = SphericalBase::Create( _settings ); diff --git a/code/src/solvers/pnsolver.cpp b/code/src/solvers/pnsolver.cpp index 4c99e59..944d4fd 100644 --- a/code/src/solvers/pnsolver.cpp +++ b/code/src/solvers/pnsolver.cpp @@ -10,7 +10,7 @@ #include "spdlog/spdlog.h" #include -PNSolver::PNSolver( Config* settings ) : Solver( settings ) { +PNSolver::PNSolver( Config* settings ) : SolverBase( settings ) { _LMaxDegree = settings->GetMaxMomentDegree(); _nTotalEntries = GlobalIndex( int( _LMaxDegree ), int( _LMaxDegree ) ) + 1; diff --git a/code/src/solvers/snsolver.cpp b/code/src/solvers/snsolver.cpp index a3de1bf..8f98e01 100644 --- a/code/src/solvers/snsolver.cpp +++ b/code/src/solvers/snsolver.cpp @@ -13,7 +13,7 @@ #include #include -SNSolver::SNSolver( Config* settings ) : Solver( settings ) { +SNSolver::SNSolver( Config* settings ) : SolverBase( settings ) { _quadPoints = _quadrature->GetPoints(); _weights = _quadrature->GetWeights(); diff --git a/code/src/solvers/solverbase.cpp b/code/src/solvers/solverbase.cpp index e11e652..fef9048 100644 --- a/code/src/solvers/solverbase.cpp +++ b/code/src/solvers/solverbase.cpp @@ -18,7 +18,7 @@ #include -Solver::Solver( Config* settings ) { +SolverBase::SolverBase( Config* settings ) { _settings = settings; // @TODO save parameters from settings class @@ -94,13 +94,13 @@ Solver::Solver( Config* settings ) { //_density = std::vector( _mesh->GetCellMidPoints().size(), 0.0 ); } -Solver::~Solver() { +SolverBase::~SolverBase() { delete _quadrature; delete _mesh; delete _problem; } -Solver* Solver::Create( Config* settings ) { +SolverBase* SolverBase::Create( Config* settings ) { switch( settings->GetSolverName() ) { case SN_SOLVER: return new SNSolver( settings ); @@ -116,7 +116,7 @@ Solver* Solver::Create( Config* settings ) { return nullptr; // This code is never reached. Just to disable compiler warnings. } -void Solver::Solve() { +void SolverBase::Solve() { // --- Preprocessing --- @@ -161,9 +161,9 @@ void Solver::Solve() { DrawPostSolverOutput(); } -void Solver::PrintVolumeOutput() const { ExportVTK( _settings->GetOutputFile(), _outputFields, _outputFieldNames, _mesh ); } +void SolverBase::PrintVolumeOutput() const { ExportVTK( _settings->GetOutputFile(), _outputFields, _outputFieldNames, _mesh ); } -void Solver::PrintVolumeOutput( int currEnergy ) const { +void SolverBase::PrintVolumeOutput( int currEnergy ) const { if( _settings->GetVolumeOutputFrequency() != 0 && currEnergy % (unsigned)_settings->GetVolumeOutputFrequency() == 0 ) { ExportVTK( _settings->GetOutputFile() + "_" + std::to_string( currEnergy ), _outputFields, _outputFieldNames, _mesh ); } @@ -173,7 +173,7 @@ void Solver::PrintVolumeOutput( int currEnergy ) const { } // --- Helper --- -double Solver::ComputeTimeStep( double cfl ) const { +double SolverBase::ComputeTimeStep( double cfl ) const { double maxEdge = -1.0; for( unsigned j = 0; j < _nCells; j++ ) { for( unsigned l = 0; l < _normals[j].size(); l++ ) { @@ -185,7 +185,7 @@ double Solver::ComputeTimeStep( double cfl ) const { } // --- IO ---- -void Solver::PrepareScreenOutput() { +void SolverBase::PrepareScreenOutput() { unsigned nFields = (unsigned)_settings->GetNScreenOutput(); _screenOutputFieldNames.resize( nFields ); @@ -212,7 +212,7 @@ void Solver::PrepareScreenOutput() { } } -void Solver::WriteScalarOutput( unsigned iteration ) { +void SolverBase::WriteScalarOutput( unsigned iteration ) { unsigned nFields = (unsigned)_settings->GetNScreenOutput(); double mass = 0.0; @@ -251,7 +251,6 @@ void Solver::WriteScalarOutput( unsigned iteration ) { _screenOutputFields[idx_field] = 1; } break; - default: ErrorMessages::Error( "Screen output group not defined!", CURRENT_FUNCTION ); break; } } @@ -314,7 +313,7 @@ void Solver::WriteScalarOutput( unsigned iteration ) { } } -void Solver::PrintScreenOutput( unsigned iteration ) { +void SolverBase::PrintScreenOutput( unsigned iteration ) { int rank; MPI_Comm_rank( MPI_COMM_WORLD, &rank ); auto log = spdlog::get( "event" ); @@ -366,7 +365,7 @@ void Solver::PrintScreenOutput( unsigned iteration ) { } } -void Solver::PrepareHistoryOutput() { +void SolverBase::PrepareHistoryOutput() { unsigned nFields = (unsigned)_settings->GetNHistoryOutput(); _historyOutputFieldNames.resize( nFields ); @@ -393,7 +392,7 @@ void Solver::PrepareHistoryOutput() { } } -void Solver::PrintHistoryOutput( unsigned iteration ) { +void SolverBase::PrintHistoryOutput( unsigned iteration ) { int rank; MPI_Comm_rank( MPI_COMM_WORLD, &rank ); auto log = spdlog::get( "tabular" ); @@ -418,7 +417,7 @@ void Solver::PrintHistoryOutput( unsigned iteration ) { } } -void Solver::DrawPreSolverOutput() { +void SolverBase::DrawPreSolverOutput() { // MPI int rank; MPI_Comm_rank( MPI_COMM_WORLD, &rank ); @@ -463,7 +462,7 @@ void Solver::DrawPreSolverOutput() { } } -void Solver::DrawPostSolverOutput() { +void SolverBase::DrawPostSolverOutput() { // MPI int rank; MPI_Comm_rank( MPI_COMM_WORLD, &rank ); @@ -497,4 +496,4 @@ void Solver::DrawPostSolverOutput() { } } -void Solver::SolverPreprocessing() {} +void SolverBase::SolverPreprocessing() {} diff --git a/code/tests/test_cases.cpp b/code/tests/test_cases.cpp index 39a60de..9fad188 100644 --- a/code/tests/test_cases.cpp +++ b/code/tests/test_cases.cpp @@ -36,8 +36,8 @@ TEST_CASE( "SN_SOLVER", "[validation_tests]" ) { SECTION( "checkerboard" ) { std::string config_file_name = std::string( TESTS_PATH ) + sn_fileDir + "checkerboard_SN.cfg"; - Config* config = new Config( config_file_name ); - Solver* solver = Solver::Create( config ); + Config* config = new Config( config_file_name ); + SolverBase* solver = SolverBase::Create( config ); solver->Solve(); solver->PrintVolumeOutput(); @@ -57,8 +57,8 @@ TEST_CASE( "SN_SOLVER", "[validation_tests]" ) { SECTION( "linesource" ) { std::string config_file_name = std::string( TESTS_PATH ) + sn_fileDir + "linesource_SN.cfg"; - Config* config = new Config( config_file_name ); - Solver* solver = Solver::Create( config ); + Config* config = new Config( config_file_name ); + SolverBase* solver = SolverBase::Create( config ); solver->Solve(); solver->PrintVolumeOutput(); @@ -80,8 +80,8 @@ TEST_CASE( "PN_SOLVER", "[validation_tests]" ) { SECTION( "checkerboard" ) { std::string config_file_name = std::string( TESTS_PATH ) + pn_fileDir + "checkerboard_PN.cfg"; - Config* config = new Config( config_file_name ); - Solver* solver = Solver::Create( config ); + Config* config = new Config( config_file_name ); + SolverBase* solver = SolverBase::Create( config ); solver->Solve(); solver->PrintVolumeOutput(); @@ -100,8 +100,8 @@ TEST_CASE( "PN_SOLVER", "[validation_tests]" ) { SECTION( "linesource" ) { std::string config_file_name = std::string( TESTS_PATH ) + pn_fileDir + "linesource_PN.cfg"; - Config* config = new Config( config_file_name ); - Solver* solver = Solver::Create( config ); + Config* config = new Config( config_file_name ); + SolverBase* solver = SolverBase::Create( config ); solver->Solve(); solver->PrintVolumeOutput(); @@ -125,8 +125,8 @@ TEST_CASE( "MN_SOLVER", "[validation_tests]" ) { SECTION( "checkerboard" ) { std::string config_file_name = std::string( TESTS_PATH ) + mn_fileDir + "checkerboard_MN.cfg"; - Config* config = new Config( config_file_name ); - Solver* solver = Solver::Create( config ); + Config* config = new Config( config_file_name ); + SolverBase* solver = SolverBase::Create( config ); solver->Solve(); solver->PrintVolumeOutput(); @@ -149,8 +149,8 @@ TEST_CASE( "MN_SOLVER", "[validation_tests]" ) { { std::string config_file_name = std::string( TESTS_PATH ) + mn_fileDir + "linesource_MN_Quad.cfg"; - Config* config = new Config( config_file_name ); - Solver* solver = Solver::Create( config ); + Config* config = new Config( config_file_name ); + SolverBase* solver = SolverBase::Create( config ); solver->Solve(); solver->PrintVolumeOutput(); @@ -170,8 +170,8 @@ TEST_CASE( "MN_SOLVER", "[validation_tests]" ) { { // --- Maxwell Boltzmann Entropy --- std::string config_file_name = std::string( TESTS_PATH ) + mn_fileDir + "linesource_MN_MB.cfg"; - Config* config = new Config( config_file_name ); - Solver* solver = Solver::Create( config ); + Config* config = new Config( config_file_name ); + SolverBase* solver = SolverBase::Create( config ); solver->Solve(); solver->PrintVolumeOutput(); @@ -197,7 +197,7 @@ TEST_CASE( "CSD_SN_FP_SOLVER", "[validation_tests]" ) { std::string config_file_name = std::string( TESTS_PATH ) + csd_sn_fileDir + "waterphantom_1D.cfg"; Config* config = new Config( config_file_name ); - Solver* solver = Solver::Create( config ); + SolverBase* solver = SolverBase::Create( config ); solver->Solve(); solver->PrintVolumeOutput(); auto test = readVTKFile( std::string( TESTS_PATH ) + "result/rtsn_test_waterphantom_1D_CSD_FP.vtk" ); @@ -220,7 +220,7 @@ TEST_CASE( "CSD_SN_FP_2D_SOLVER", "[validation_tests]" ) { std::string config_file_name = std::string( TESTS_PATH ) + csd_sn_fileDir + "waterphantom_2D.cfg"; Config* config = new Config( config_file_name ); - Solver* solver = Solver::Create( config ); + SolverBase* solver = SolverBase::Create( config ); solver->Solve(); solver->PrintVolumeOutput(); auto test = readVTKFile( std::string( TESTS_PATH ) + "result/rtsn_test_waterphantom_2D_CSD_FP.vtk" ); @@ -243,7 +243,7 @@ TEST_CASE( "CSD_SN_FP_SH_2D_SOLVER", "[validation_tests]" ) { std::string config_file_name = std::string( TESTS_PATH ) + csd_sn_fileDir + "waterphantom_2D_sh.cfg"; Config* config = new Config( config_file_name ); - Solver* solver = Solver::Create( config ); + SolverBase* solver = SolverBase::Create( config ); solver->Solve(); solver->PrintVolumeOutput(); // solver->Save(); @@ -281,8 +281,8 @@ TEST_CASE( "screen_output", "[output]" ) { std::string historyLoggerReference = std::string( TESTS_PATH ) + out_fileDir + "validate_logger_csv_reference"; std::string historyLogger = std::string( TESTS_PATH ) + "result/logs/validate_logger_output_csv"; - Config* config = new Config( config_file_name ); - Solver* solver = Solver::Create( config ); + Config* config = new Config( config_file_name ); + SolverBase* solver = SolverBase::Create( config ); solver->Solve(); // Force Logger to flush diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index cff5808..de0f731 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -482,19 +482,19 @@ NUM_PROC_THREADS = 1 # normally produced when WARNINGS is set to YES. # The default value is: NO. -EXTRACT_ALL = NO +EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. -EXTRACT_PRIVATE = NO +EXTRACT_PRIVATE = YES # If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual # methods of a class will be included in the documentation. # The default value is: NO. -EXTRACT_PRIV_VIRTUAL = NO +EXTRACT_PRIV_VIRTUAL = YES # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. diff --git a/doc/solvers/index.rst b/doc/solvers/index.rst index 7cd552b..05e20fb 100644 --- a/doc/solvers/index.rst +++ b/doc/solvers/index.rst @@ -4,7 +4,7 @@ Solvers .. toctree:: :maxdepth: 1 - solver + solverbase csdsnsolver csdsnsolverfp csdsnsolvernotrafo diff --git a/doc/solvers/solver.rst b/doc/solvers/solver.rst deleted file mode 100644 index bdfef8c..0000000 --- a/doc/solvers/solver.rst +++ /dev/null @@ -1,5 +0,0 @@ -Solver -========== - -.. doxygenclass:: Solver - :members: -- GitLab From 3930d6e92ca32f761faad430a62822d7bb3ab200 Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 14:56:26 +0100 Subject: [PATCH 29/67] Add PN docs Former-commit-id: 433274cdc27551aec7fc92b0bbb929fa7f182e99 --- doc/physics.rst | 70 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/doc/physics.rst b/doc/physics.rst index 9606706..53e3490 100644 --- a/doc/physics.rst +++ b/doc/physics.rst @@ -54,12 +54,78 @@ For convenience, it is often reformulated with polar coordinates :math:`\{r, \ph .. math:: - &\left[\frac{1}{v(E)} \partial_{t} +\Omega \cdot \nabla+\Sigma_t (r, E, t)\right] \psi(r, \Omega, E, t) \\ - &=\int_{0}^{\infty} d E^{\prime} \int_{\mathcal R^2} d \Omega^{\prime} \Sigma_{s}\left(r, \Omega^{\prime} \bullet \Omega, E^{\prime} \rightarrow E\right) \psi\left(r, \Omega^{\prime}, E^{\prime}, t\right) + Q(r, \Omega, E, t). + &\left[\frac{1}{v(E)} \partial_{t} +\Omega \cdot \nabla+\Sigma_t (t, r, E)\right] \psi(t, r, \Omega, E) \\ + &=\int_{0}^{\infty} d E^{\prime} \int_{\mathcal R^2} d \Omega^{\prime} \Sigma_{s}\left(r, \Omega^{\prime} \bullet \Omega, E^{\prime} \rightarrow E\right) \psi\left(t, r, \Omega^{\prime}, E^{\prime}\right) + Q(t, r, \Omega, E). The particle distribution :math:`\psi(r, \Omega, E, t)` here is often named as angular flux, :math:`\{\Sigma_s, \Sigma_t \}` are the scattering and total cross sections correspondingly, and :math:`Q` denotes a source term. +The spherical harmonics moment equations +--------- + +The spherical harmonics (:math:`P_N`) method (cf. Brunner and Holloway [2005]) is one of several ways to solve the equation of radiative transfer. +It serves as an approximate method, i.e. the method of moments, to reduce the high dimensionality when the original kinetic equation of radiative transfer, which is formulated on a seven-dimensional domain. +Let us consider the radiative transfer equation in one-dimensional physical space with only one energy group, i.e. + +.. math:: + + \partial_{t} \psi(t, z, \mu) &+\mu \nabla_{z} \psi(t, z, \mu)+\Sigma_{t}(t, z) \psi(t, z, \mu) \\ + &=\int_{\mathcal S^{2}} \Sigma_{s}\left(t, z, \mu \cdot \Omega^{\prime}\right) \psi\left(t, z, \mu^{\prime}\right) d \mu^{\prime}+q(t, z, \mu), + +where :math:`\mu` is the projected angular variable on :math:`z` axis. + +To obtain the :math:`P_N` equations, we express the angular dependence of the distribution function in terms of a Fourier series, +.. math:: + + \psi(t, z, \mu)=\sum_{\ell=0}^{\infty} \psi_{\ell}(t, z) \frac{2 \ell+1}{2} P_{\ell}(\mu), + +where :math:`P_{\ell}` are the Legendre polynomials. +These form an orthogonal basis of the space +of polynomials with respect to the standard scalar product on :math:`[−1, 1]`. +We can then obtain +.. math:: + + \partial_{t} \psi_{\ell}+\partial_{z} \int_{=1}^{1} \mu P_{\ell} \psi \mathrm{d} \mu+\Sigma_{t \ell} \psi_{\ell}=q_{\ell}, + +where + +.. math:: + + \Sigma_{t \ell}=\Sigma_{t}-\Sigma_{s \ell}=\Sigma_{a}+\Sigma_{s 0}-\Sigma_{s \ell}, \quad \Sigma_{s \ell}=2 \pi \int_{-1}^{1} P_{\ell}(\mu) \Sigma_{s}(\mu) \mathrm{d} \mu. + +Two properties of the spherical harmonics are crucial for our method. These appear here as properties of the Legendre polynomials. First, we observe that, by this +procedure, we have diagonalized the scattering operator on the right-hand side (the +Legendre polynomials are the eigenfunctions of scattering operator). +Second, a general property of orthogonal polynomials is that they satisfy a recursion relation. In +particular, the Legendre polynomials satisfy + +.. math:: + + \mu P_{\ell}(\mu)=\frac{\ell}{2 \ell+1} P_{\ell-1}(\mu)+\frac{\ell+1}{2 \ell+1} P_{\ell+1}(\mu). + +Using this fact and truncating the expansion at :math:`\ell = N`, we arrive at the slab-geometry +:math:`P_N` equations, + +.. math:: + + \partial_{t} \psi_{\ell}+\partial_{z}\left(\frac{\ell+1}{2 \ell+1} \psi_{\ell+1}+\frac{\ell}{2 \ell+1} \psi_{\ell-1}\right)+\Sigma_{t \ell} \psi_{\ell}=q_{\ell}. + +The above method can be extended to multi-dimensional case with the help of spherical harmonics, which are defined as + +.. math:: + + Y_{\ell}^{m}(\mu, \phi)=(-1)^{m} \sqrt{\frac{2 \ell+1}{4 \pi} \frac{(\ell-m) !}{(\ell+m) !}} e^{i m \phi} P_{\ell}^{m}(\mu), + +where :math:`\ell \leq 0` and :math:`\ell \leq m \leq -\ell`. + + +The entropy closure moment equations +--------- + + + + + The continuous slowing down approximation --------- -- GitLab From 00f8bc089cdccdcd869bd0a940325ae5d57d0dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Fri, 26 Feb 2021 15:11:32 +0100 Subject: [PATCH 30/67] add documentation for mn and pn solver Former-commit-id: f44236751f711f9db5f51a3ae9867fbd0666af6b --- code/include/common/config.h | 12 +-- code/include/problems/problembase.h | 10 +-- code/include/solvers/mnsolver.h | 46 ++++++------ code/include/solvers/pnsolver.h | 109 +++++++++++++++++++--------- code/include/solvers/solverbase.h | 34 ++++----- code/src/solvers/mnsolver.cpp | 66 ++++++++--------- code/src/solvers/pnsolver.cpp | 78 ++++++++++---------- code/src/solvers/snsolver.cpp | 2 +- doc/solvers/mnsolver.rst | 2 + doc/solvers/pnsolver.rst | 3 + 10 files changed, 204 insertions(+), 158 deletions(-) diff --git a/code/include/common/config.h b/code/include/common/config.h index 9af724a..f04c8de 100644 --- a/code/include/common/config.h +++ b/code/include/common/config.h @@ -125,7 +125,7 @@ class Config bool _dataGeneratorMode; unsigned long _tainingSetSize; /*!< @brief Size of training data set for data generator */ unsigned long _maxValFirstMoment; /*!< @brief Size of training data set for data generator */ - double _RealizableSetEpsilonU0; /*! @brief Distance to 0 of the sampled moments to the boundary of the realizable set */ + double _RealizableSetEpsilonU0; /*!< @brief Distance to 0 of the sampled moments to the boundary of the realizable set */ double _RealizableSetEpsilonU1; /*!< @brief: norm(u_1)/u_0 !< _RealizableSetEpsilonU1 */ bool _normalizedSampling; /*!< @brief: Flag for sampling of normalized moments, i.e. u_0 =1 */ @@ -330,10 +330,12 @@ class Config // ---- Setters for option structure // This section is dangerous // Quadrature Structure - void SetNQuadPoints( unsigned nq ) { _nQuadPoints = nq; } /*! @brief Never change the nq! This is only for the test framework. */ - void SetQuadName( QUAD_NAME quadName ) { _quadName = quadName; } /*! @brief Never change the quadName! This is only for the test framework. */ - void SetQuadOrder( unsigned quadOrder ) { _quadOrder = quadOrder; } /*! @brief Never change the quadOrder! This is only for the test framework. */ - void SetSNAllGaussPts( bool useall ) { _allGaussPts = useall; } /*! @brief Never change the this! This is only for the test framework. */ + void SetNQuadPoints( unsigned nq ) { _nQuadPoints = nq; } /*!< @brief Never change the nq! This is only for the test framework. */ + void SetQuadName( QUAD_NAME quadName ) { _quadName = quadName; } /*!< @brief Never change the quadName! This is only for the test framework. */ + void SetQuadOrder( unsigned quadOrder ) { + _quadOrder = quadOrder; + } /*!< @brief Never change the quadOrder! This is only for the test framework. */ + void SetSNAllGaussPts( bool useall ) { _allGaussPts = useall; } /*!< @brief Never change the this! This is only for the test framework. */ // Mesh Structure void SetNCells( unsigned nCells ) { _nCells = nCells; } }; diff --git a/code/include/problems/problembase.h b/code/include/problems/problembase.h index 30f302f..300edfa 100644 --- a/code/include/problems/problembase.h +++ b/code/include/problems/problembase.h @@ -87,11 +87,11 @@ class ProblemBase */ virtual VectorVector SetupIC() = 0; - /*!< @brief: Exact analytical solution for the Line Source Test Case at - @param: x: x coordinate of exact solution - y: y coordinate of exact solution - t: time of the exact solution - scatteringXS: scattering cross section of the exact solution + /*! @brief: Exact analytical solution for the Line Source Test Case at + @param: x: x coordinate of exact solution + y: y coordinate of exact solution + t: time of the exact solution + scatteringXS: scattering cross section of the exact solution @return: exact solution at x,y,t,scatteringXS */ // Default is set to 0. ~> if no analytical solution is available. double virtual GetAnalyticalSolution( double /*x*/, double /*y*/, double /*t*/, double /*scatteringXS*/ ) { return 0.0; } diff --git a/code/include/solvers/mnsolver.h b/code/include/solvers/mnsolver.h index 0c73ca7..77230f1 100644 --- a/code/include/solvers/mnsolver.h +++ b/code/include/solvers/mnsolver.h @@ -12,7 +12,7 @@ class MNSolver : public SolverBase public: /** * @brief MNSolver constructor - * @param settings stores all needed information + * @param settings : Config class that stores all needed information */ MNSolver( Config* settings ); @@ -21,15 +21,15 @@ class MNSolver : public SolverBase private: // --- Private member variables --- - unsigned _nTotalEntries; /*! @brief: Total number of equations in the system */ - unsigned short _LMaxDegree; /*! @brief: Max Order of Spherical Harmonics */ + unsigned _nSystem; /*! @brief Total number of equations in the system */ + unsigned short _polyDegreeBasis; /*! @brief Max polynomial degree of the basis */ // Moment basis - SphericalBase* _basis; /*! @brief: Class to compute and store current spherical harmonics basis */ - VectorVector _moments; /*! @brief: Moment Vector pre-computed at each quadrature point: dim= _nq x _nTotalEntries */ + SphericalBase* _basis; /*! @brief Class to compute and store current spherical harmonics basis */ + VectorVector _moments; /*! @brief Moment Vector pre-computed at each quadrature point: dim= _nq x _nTotalEntries */ // Scattering - Vector _scatterMatDiag; /*! @brief: Diagonal of the scattering matrix (its a diagonal matrix by construction) */ + Vector _scatterMatDiag; /*! @brief Diagonal of the scattering matrix (its a diagonal matrix by construction) */ // Quadrature related members VectorVector _quadPoints; /*! @brief quadrature points, dim(_quadPoints) = (_nq,spatialDim) */ @@ -37,41 +37,41 @@ class MNSolver : public SolverBase VectorVector _quadPointsSphere; /*! @brief (my,phi), dim(_quadPoints) = (_nq,2) */ // Entropy Optimization related members - EntropyBase* _entropy; /*! @brief: Class to handle entropy functionals */ - VectorVector _alpha; /*! @brief: Lagrange Multipliers for Minimal Entropy problem for each gridCell - Layout: _nCells x _nTotalEntries*/ - OptimizerBase* _optimizer; /*! @brief: Class to solve minimal entropy problem */ + EntropyBase* _entropy; /*! @brief Class to handle entropy functionals */ + VectorVector _alpha; /*! @brief Lagrange Multipliers for Minimal Entropy problem for each gridCell + Layout: _nCells x _nTotalEntries*/ + OptimizerBase* _optimizer; /*! @brief Class to solve minimal entropy problem */ - VectorVector _solDx; /*! @brief: temporary storage of x-derivatives of alpha */ - VectorVector _solDy; /*! @brief: temporary storage of y-derivatives of alpha */ + VectorVector _solDx; /*! @brief temporary storage of x-derivatives of alpha */ + VectorVector _solDy; /*! @brief temporary storage of y-derivatives of alpha */ // ---- Private Member functions --- // IO void PrepareVolumeOutput() override; - void WriteVolumeOutput( unsigned idx_pseudoTime ) override; + void WriteVolumeOutput( unsigned idx_iter ) override; // Solver - void FVMUpdate( unsigned idx_energy ) override; + void FVMUpdate( unsigned idx_iter ) override; void FluxUpdate() override; - void IterPreprocessing( unsigned idx_pseudotime ) override; - void IterPostprocessing( unsigned idx_pseudotime ); - /*! @brief : Construct flux by computing the Moment of the sum of FVM discretization at the interface of cell - * @param : idx_cell = current cell id - * @returns : sum over all neighbors of flux for all moments at interface of idx_cell, idx_neighbor */ + void IterPreprocessing( unsigned /*idx_iter*/ ) override; + void IterPostprocessing( unsigned /*idx_iter*/ ) override; + /*! @brief Construct flux by computing the Moment of the sum of FVM discretization at the interface of cell + * @param idx_cell current cell id + * @returns sum over all neighbors of flux for all moments at interface of idx_cell, idx_neighbor */ Vector ConstructFlux( unsigned idx_cell ); /*! @brief Corrects the solution _sol[idx_cell] to be realizable w.r.t. the reconstructed entropy (eta'(alpha*m)) - @param idx_cell = cell where the correction happens*/ + @param idx_cell cell where the correction happens*/ void ComputeRealizableSolution( unsigned idx_cell ); // Initialization of the solver - /*! @brief : Pre-Compute Moments at all quadrature points. */ + /*! @brief Pre-Compute Moments at all quadrature points. */ void ComputeMoments(); - /*! @brief: fucntion for computing and setting up EV matrix for scattering kernel */ + /*! @brief Function for computing and setting up EV matrix for scattering kernel */ void ComputeScatterMatrix(); // Helper - /*! @brief: Computes the radiative flux from the solution vector of the moment system */ + /*! @brief Computes the radiative flux from the solution vector of the moment system */ void ComputeRadFlux(); }; #endif // MNSOLVER_H diff --git a/code/include/solvers/pnsolver.h b/code/include/solvers/pnsolver.h index 15a8bf4..1165196 100644 --- a/code/include/solvers/pnsolver.h +++ b/code/include/solvers/pnsolver.h @@ -15,93 +15,132 @@ class PNSolver : public SolverBase virtual ~PNSolver() {} private: - unsigned _nTotalEntries; /*! @brief: total number of equations in the system */ - unsigned _LMaxDegree; /*! @brief: maximal degree of the spherical harmonics basis*/ + unsigned _nSystem; /*!< @brief total number of equations in the system */ + unsigned _polyDegreeBasis; /*!< @brief maximal degree of the spherical harmonics basis*/ // System Matrix for x, y and z flux // ==> not needed after computation of A+ and A- ==> maybe safe only temporarly and remove as member? - SymMatrix _Ax; /*! @brief: Flux Jacbioan in x direction */ - SymMatrix _Ay; /*! @brief: Flux Jacbioan in x direction */ - SymMatrix _Az; /*! @brief: Flux Jacbioan in x direction */ + SymMatrix _Ax; /*!< @brief Flux Jacbioan in x direction */ + SymMatrix _Ay; /*!< @brief Flux Jacbioan in x direction */ + SymMatrix _Az; /*!< @brief Flux Jacbioan in x direction */ // Upwinding Matrices - Matrix _AxPlus; /*! @brief: Flux Jacbioan in x direction, positive part */ - Matrix _AxMinus; /*! @brief: Flux Jacbioan in x direction, negative part */ - Matrix _AxAbs; /*! @brief: Flux Jacbioan in x direction, absolute part */ - Matrix _AyPlus; /*! @brief: Flux Jacbioan in y direction, positive part */ - Matrix _AyMinus; /*! @brief: Flux Jacbioan in y direction, negative part */ - Matrix _AyAbs; /*! @brief: Flux Jacbioan in y direction, absolute part */ - Matrix _AzPlus; /*! @brief: Flux Jacbioan in z direction, positive part */ - Matrix _AzMinus; /*! @brief: Flux Jacbioan in z direction, negative part */ - Matrix _AzAbs; /*! @brief: Flux Jacbioan in z direction, absolute part */ - - Vector _scatterMatDiag; /*! @brief: diagonal of the scattering matrix (its a diagonal matrix by construction). Contains eigenvalues of the + Matrix _AxPlus; /*!< @brief Flux Jacbioan in x direction, positive part */ + Matrix _AxMinus; /*!< @brief Flux Jacbioan in x direction, negative part */ + Matrix _AxAbs; /*!< @brief Flux Jacbioan in x direction, absolute part */ + Matrix _AyPlus; /*!< @brief Flux Jacbioan in y direction, positive part */ + Matrix _AyMinus; /*!< @brief Flux Jacbioan in y direction, negative part */ + Matrix _AyAbs; /*!< @brief Flux Jacbioan in y direction, absolute part */ + Matrix _AzPlus; /*!< @brief Flux Jacbioan in z direction, positive part */ + Matrix _AzMinus; /*!< @brief Flux Jacbioan in z direction, negative part */ + Matrix _AzAbs; /*!< @brief Flux Jacbioan in z direction, absolute part */ + + Vector _scatterMatDiag; /*!< @brief diagonal of the scattering matrix (its a diagonal matrix by construction). Contains eigenvalues of the scattering kernel. */ - VectorVector _solDx; /*! @brief: temporary storage of x-derivatives of solution */ - VectorVector _solDy; /*! @brief: temporary storage of y-derivatives of solution */ + VectorVector _solDx; /*!< @brief Temporary storage of x-derivatives of solution */ + VectorVector _solDy; /*!< @brief Temporary storage of y-derivatives of solution */ // ---- Member functions ---- // IO - /*! @brief Initializes the output groups and fields of this solver and names the fields */ void PrepareVolumeOutput() override; - /*! @brief Function that prepares VTK export and csv export of the current solver iteration - @returns: Mass of current iteration */ void WriteVolumeOutput( unsigned idx_pseudoTime ) override; // Solver void FVMUpdate( unsigned idx_energy ) override; void FluxUpdate() override; void IterPreprocessing( unsigned idx_pseudotime ) override; - void IterPostprocessing( unsigned idx_pseudotime ); + void IterPostprocessing( unsigned idx_pseudotime ) override; // Helper void ComputeRadFlux(); // Initialization of the Solver - /*! @brief: parameter functions for setting up system matrix - * @param: degree l, it must hold: 0 <= l <=_nq - * @param : order k, it must hold: -l <=k <= l + /*! @brief parameter functions for setting up system matrix + * @param l degree , it must hold: 0 <= l <=_nq + * @param k order , it must hold: -l <=k <= l */ double AParam( int l, int k ) const; + /*! @brief parameter functions for setting up system matrix + * @param l degree , it must hold: 0 <= l <=_nq + * @param k order , it must hold: -l <=k <= l + */ double BParam( int l, int k ) const; + /*! @brief parameter functions for setting up system matrix + * @param l degree , it must hold: 0 <= l <=_nq + * @param k order , it must hold: -l <=k <= l + */ double CParam( int l, int k ) const; + /*! @brief parameter functions for setting up system matrix + * @param l degree , it must hold: 0 <= l <=_nq + * @param k order , it must hold: -l <=k <= l + */ double DParam( int l, int k ) const; + /*! @brief parameter functions for setting up system matrix + * @param l degree , it must hold: 0 <= l <=_nq + * @param k order , it must hold: -l <=k <= l + */ double EParam( int l, int k ) const; + /*! @brief parameter functions for setting up system matrix + * @param l degree , it must hold: 0 <= l <=_nq + * @param k order , it must hold: -l <=k <= l + */ double FParam( int l, int k ) const; + /*! @brief parameter functions for setting up system matrix + * @param l degree , it must hold: 0 <= l <=_nq + * @param k order , it must hold: -l <=k <= l + */ double CTilde( int l, int k ) const; + /*! @brief parameter functions for setting up system matrix + * @param l degree , it must hold: 0 <= l <=_nq + * @param k order , it must hold: -l <=k <= l + */ double DTilde( int l, int k ) const; + /*! @brief parameter functions for setting up system matrix + * @param l degree , it must hold: 0 <= l <=_nq + * @param k order , it must hold: -l <=k <= l + */ double ETilde( int l, int k ) const; + /*! @brief parameter functions for setting up system matrix + * @param l degree , it must hold: 0 <= l <=_nq + * @param k order , it must hold: -l <=k <= l + */ double FTilde( int l, int k ) const; /*! @brief: mathematical + index functions. Helper functions for setting up system matrix. * @param: k: arbitrary integer */ int Sgn( int k ) const; + /*! @brief mathematical + index functions. Helper functions for setting up system matrix. + * @param k arbitrary integer + */ int kPlus( int k ) const; + /*! @brief mathematical + index functions. Helper functions for setting up system matrix. + * @param k arbitrary integer + */ int kMinus( int k ) const; - /*! @brief : computes the global index of the moment corresponding to basis function (l,k) - * @param : degree l, it must hold: 0 <= l <=_nq - * @param : order k, it must hold: -l <=k <= l - * @returns : global index + /*! @brief computes the global index of the moment corresponding to basis function (l,k) + * @param l degree l, it must hold: 0 <= l <=_nq + * @param k order k, it must hold: -l <=k <= l + * @returns global index */ int GlobalIndex( int l, int k ) const; - /*! @brief : Checks, if index invariant for global index holds - * @returns : True, if invariant holds, else false + /*! @brief Checks, if index invariant for global index holds + * @returns True, if invariant holds, else false */ bool CheckIndex( int l, int k ) const; - /*! @brief: function for computing and setting up system matrices */ + /*! @brief Function for computing and setting up system matrices */ void ComputeSystemMatrices(); - /*! @brief: function for computing and setting up flux matrices for upwinding */ + /*! @brief Function for computing and setting up flux matrices for upwinding */ void ComputeFluxComponents(); - /*! @brief: fucntion for computing and setting up EV matrix for scattering kernel */ + /*! @brief Function for computing and setting up EV matrix for scattering kernel */ void ComputeScatterMatrix(); - /*! @brief: Computes Legedre polinomial of oder l at point x */ + /*! @brief Computes Legedre polinomial of oder l at point x */ double LegendrePoly( double x, int l ); /*! @brief: Sets Entries of FluxMatrices to zero, if they are below double precision, diff --git a/code/include/solvers/solverbase.h b/code/include/solvers/solverbase.h index 73befe2..c7b16ff 100644 --- a/code/include/solvers/solverbase.h +++ b/code/include/solvers/solverbase.h @@ -69,17 +69,17 @@ class SolverBase std::vector _solverOutput; /*!< @brief LEGACY: Outputfield for solver ==> Will be replaced by _outputFields in the near future */ // Output related members - std::vector>> _outputFields; /*!< @brief: Solver Output: dimensions (GroupID,FieldID,CellID).*/ - std::vector> _outputFieldNames; /*!< @brief: Names of the outputFields: dimensions (GroupID,FieldID) */ + std::vector>> _outputFields; /*!< @brief Solver Output: dimensions (GroupID,FieldID,CellID).*/ + std::vector> _outputFieldNames; /*!< @brief Names of the outputFields: dimensions (GroupID,FieldID) */ // we will have to add a further dimension for quadPoints and weights once we start with multilevel SN // Output related members - std::vector _screenOutputFields; /*!< @brief: Solver Output: dimensions (FieldID). */ - std::vector _screenOutputFieldNames; /*!< @brief: Names of the outputFields: dimensions (FieldID) */ + std::vector _screenOutputFields; /*!< @brief Solver Output: dimensions (FieldID). */ + std::vector _screenOutputFieldNames; /*!< @brief Names of the outputFields: dimensions (FieldID) */ // Output related members - std::vector _historyOutputFields; /*!< @brief: Solver Output: dimensions (FieldID). */ - std::vector _historyOutputFieldNames; /*!< @brief: Names of the outputFields: dimensions (FieldID) */ + std::vector _historyOutputFields; /*!< @brief Solver Output: dimensions (FieldID). */ + std::vector _historyOutputFieldNames; /*!< @brief Names of the outputFields: dimensions (FieldID) */ // ---- Member functions ---- @@ -87,19 +87,19 @@ class SolverBase /*! @brief Performs preprocessing steps before the pseudo time iteration is started*/ virtual void SolverPreprocessing(); /*! @brief Performs preprocessing for the current solver iteration - @param idx_iter : current (peudo) time iteration */ + @param idx_iter current (peudo) time iteration */ virtual void IterPreprocessing( unsigned idx_iter ) = 0; /*! @brief Performs postprocessing for the current solver iteration */ virtual void IterPostprocessing( unsigned idx_pseudotime ) = 0; /*! @brief Constructs the flux update for the current iteration and stores it in psiNew*/ virtual void FluxUpdate() = 0; /*! @brief Computes the finite Volume update step for the current iteration - @param idx_iter : current (peudo) time iteration */ + @param idx_iter current (peudo) time iteration */ virtual void FVMUpdate( unsigned idx_iter ) = 0; // Helper /*! @brief ComputeTimeStep calculates the maximal stable time step using the cfl number - @param used cfl number */ + @param cfl Courant-Friedrichs-Levy condition number */ double ComputeTimeStep( double cfl ) const; /*! @brief: Computes the flux of the solution to check conservation properties */ virtual void ComputeRadFlux() = 0; @@ -108,27 +108,27 @@ class SolverBase /*! @brief Initializes the output groups and fields of this solver and names the fields */ virtual void PrepareVolumeOutput() = 0; /*! @brief Function that prepares VTK export and csv export of the current solver iteration - @param idx_iter : current (pseudo) time iteration */ + @param idx_iter current (pseudo) time iteration */ virtual void WriteVolumeOutput( unsigned idx_iter ) = 0; /*! @brief Save Output solution at given energy (pseudo time) to VTK file. Write frequency is given by option VOLUME_OUTPUT_FREQUENCY. Always prints last iteration without iteration affix. - @param idx_iter : current (pseudo) time iteration */ + @param idx_iter current (pseudo) time iteration */ void PrintVolumeOutput( int idx_iter ) const; /*! @brief: Initialized the output fields and their Names for the screenoutput */ void PrepareScreenOutput(); /*! @brief Function that writes screen and history output fields - @param idx_iter : current (pseudo) time iteration */ + @param idx_iter current (pseudo) time iteration */ void WriteScalarOutput( unsigned idx_iter ); /*! @brief Prints ScreenOutputFields to Screen and to logger. Write frequency is given by option SCREEN_OUTPUT_FREQUENCY. Always prints last iteration. - @param idx_iter : current (pseudo) time iteration */ + @param idx_iter current (pseudo) time iteration */ void PrintScreenOutput( unsigned idx_iter ); - /*! @brief: Initialized the historyOutputFields and their Names for history output. Write frequency is given by + /*! @brief Initialized the historyOutputFields and their Names for history output. Write frequency is given by option HISTORY_OUTPUT_FREQUENCY. Always prints last iteration. */ void PrepareHistoryOutput(); /*! @brief Prints HistoryOutputFields to logger - @param idx_iter : current (pseudo) time iteration */ + @param idx_iter current (pseudo) time iteration */ void PrintHistoryOutput( unsigned idx_iter ); /*! @brief Pre Solver Screen and Logger Output */ void DrawPreSolverOutput(); @@ -137,13 +137,13 @@ class SolverBase public: /*! @brief Solver constructor - * @param settings :config class that stores all needed config information */ + * @param settings config class that stores all needed config information */ SolverBase( Config* settings ); virtual ~SolverBase(); /*! @brief Create constructor - * @param settings :config class that stores all needed config information + * @param settings config class that stores all needed config information * @return pointer to SolverBase */ static SolverBase* Create( Config* settings ); diff --git a/code/src/solvers/mnsolver.cpp b/code/src/solvers/mnsolver.cpp index 6839c40..5a1e855 100644 --- a/code/src/solvers/mnsolver.cpp +++ b/code/src/solvers/mnsolver.cpp @@ -19,9 +19,9 @@ MNSolver::MNSolver( Config* settings ) : SolverBase( settings ) { - _LMaxDegree = settings->GetMaxMomentDegree(); - _basis = SphericalBase::Create( _settings ); - _nTotalEntries = _basis->GetBasisSize(); + _polyDegreeBasis = settings->GetMaxMomentDegree(); + _basis = SphericalBase::Create( _settings ); + _nSystem = _basis->GetBasisSize(); // build quadrature object and store quadrature points and weights _quadPoints = _quadrature->GetPoints(); @@ -31,11 +31,11 @@ MNSolver::MNSolver( Config* settings ) : SolverBase( settings ) { //_settings->SetNQuadPoints( _nq ); // Initialize temporary storages of alpha derivatives - _solDx = VectorVector( _nCells, Vector( _nTotalEntries, 0.0 ) ); - _solDy = VectorVector( _nCells, Vector( _nTotalEntries, 0.0 ) ); + _solDx = VectorVector( _nCells, Vector( _nSystem, 0.0 ) ); + _solDy = VectorVector( _nCells, Vector( _nSystem, 0.0 ) ); // Initialize Scatter Matrix -- - _scatterMatDiag = Vector( _nTotalEntries, 0.0 ); + _scatterMatDiag = Vector( _nSystem, 0.0 ); ComputeScatterMatrix(); // Initialize Entropy @@ -45,10 +45,10 @@ MNSolver::MNSolver( Config* settings ) : SolverBase( settings ) { _optimizer = OptimizerBase::Create( _settings ); // Initialize lagrange Multiplier - _alpha = VectorVector( _nCells, Vector( _nTotalEntries, 0.0 ) ); + _alpha = VectorVector( _nCells, Vector( _nSystem, 0.0 ) ); // Initialize and Pre-Compute Moments at quadrature points - _moments = VectorVector( _nq, Vector( _nTotalEntries, 0.0 ) ); + _moments = VectorVector( _nq, Vector( _nSystem, 0.0 ) ); ComputeMoments(); } @@ -63,7 +63,7 @@ void MNSolver::ComputeScatterMatrix() { // --- Isotropic --- _scatterMatDiag[0] = -1.0; - for( unsigned idx_diag = 1; idx_diag < _nTotalEntries; idx_diag++ ) { + for( unsigned idx_diag = 1; idx_diag < _nSystem; idx_diag++ ) { _scatterMatDiag[idx_diag] = 0.0; } } @@ -84,11 +84,11 @@ Vector MNSolver::ConstructFlux( unsigned idx_cell ) { //--- Integration of moments of flux --- double entropyL, entropyR, entropyFlux; - Vector flux( _nTotalEntries, 0.0 ); + Vector flux( _nSystem, 0.0 ); //--- Temporary storages of reconstructed alpha --- - Vector alphaL( _nTotalEntries, 0.0 ); - Vector alphaR( _nTotalEntries, 0.0 ); + Vector alphaL( _nSystem, 0.0 ); + Vector alphaR( _nSystem, 0.0 ); for( unsigned idx_quad = 0; idx_quad < _nq; idx_quad++ ) { entropyFlux = 0.0; // reset temorary flux @@ -152,7 +152,7 @@ void MNSolver::IterPreprocessing( unsigned /*idx_pseudotime*/ ) { } } -void MNSolver::IterPostprocessing( unsigned idx_pseudotime ) { +void MNSolver::IterPostprocessing( unsigned /*idx_iter*/ ) { // --- Update Solution --- _sol = _solNew; @@ -170,7 +170,7 @@ void MNSolver::ComputeRadFlux() { void MNSolver::FluxUpdate() { if( _reconsOrder > 1 ) { - _mesh->ReconstructSlopesU( _nTotalEntries, _solDx, _solDy, _alpha ); // unstructured reconstruction + _mesh->ReconstructSlopesU( _nSystem, _solDx, _solDy, _alpha ); // unstructured reconstruction } // Loop over the grid cells @@ -182,19 +182,19 @@ void MNSolver::FluxUpdate() { } } -void MNSolver::FVMUpdate( unsigned idx_energy ) { +void MNSolver::FVMUpdate( unsigned idx_iter ) { // Loop over the grid cells //#pragma omp parallel for for( unsigned idx_cell = 0; idx_cell < _nCells; idx_cell++ ) { // Dirichlet Boundaries stay if( _boundaryCells[idx_cell] == BOUNDARY_TYPE::DIRICHLET ) continue; // Flux update - for( unsigned idx_system = 0; idx_system < _nTotalEntries; idx_system++ ) { + for( unsigned idx_system = 0; idx_system < _nSystem; idx_system++ ) { _solNew[idx_cell][idx_system] = _sol[idx_cell][idx_system] - ( _dE / _areas[idx_cell] ) * _solNew[idx_cell][idx_system] /* cell averaged flux */ - _dE * _sol[idx_cell][idx_system] * - ( _sigmaT[idx_energy][idx_cell] /* absorbtion influence */ - + _sigmaS[idx_energy][idx_cell] * _scatterMatDiag[idx_system] ); /* scattering influence */ + ( _sigmaT[idx_iter][idx_cell] /* absorbtion influence */ + + _sigmaS[idx_iter][idx_cell] * _scatterMatDiag[idx_system] ); /* scattering influence */ } // Source Term _solNew[idx_cell][0] += _dE * _Q[0][idx_cell][0]; @@ -224,11 +224,11 @@ void MNSolver::PrepareVolumeOutput() { case MOMENTS: // As many entries as there are moments in the system - _outputFields[idx_group].resize( _nTotalEntries ); - _outputFieldNames[idx_group].resize( _nTotalEntries ); + _outputFields[idx_group].resize( _nSystem ); + _outputFieldNames[idx_group].resize( _nSystem ); if( _settings->GetSphericalBasisName() == SPHERICAL_HARMONICS ) { - for( int idx_l = 0; idx_l <= (int)_LMaxDegree; idx_l++ ) { + for( int idx_l = 0; idx_l <= (int)_polyDegreeBasis; idx_l++ ) { for( int idx_k = -idx_l; idx_k <= idx_l; idx_k++ ) { _outputFields[idx_group][_basis->GetGlobalIndexBasis( idx_l, idx_k )].resize( _nCells ); _outputFieldNames[idx_group][_basis->GetGlobalIndexBasis( idx_l, idx_k )] = @@ -237,7 +237,7 @@ void MNSolver::PrepareVolumeOutput() { } } else { - for( unsigned idx_l = 0; idx_l <= _LMaxDegree; idx_l++ ) { + for( unsigned idx_l = 0; idx_l <= _polyDegreeBasis; idx_l++ ) { unsigned maxOrder_k = _basis->GetCurrDegreeSize( idx_l ); for( unsigned idx_k = 0; idx_k < maxOrder_k; idx_k++ ) { _outputFields[idx_group][_basis->GetGlobalIndexBasis( idx_l, idx_k )].resize( _nCells ); @@ -250,11 +250,11 @@ void MNSolver::PrepareVolumeOutput() { case DUAL_MOMENTS: // As many entries as there are moments in the system - _outputFields[idx_group].resize( _nTotalEntries ); - _outputFieldNames[idx_group].resize( _nTotalEntries ); + _outputFields[idx_group].resize( _nSystem ); + _outputFieldNames[idx_group].resize( _nSystem ); if( _settings->GetSphericalBasisName() == SPHERICAL_HARMONICS ) { - for( int idx_l = 0; idx_l <= (int)_LMaxDegree; idx_l++ ) { + for( int idx_l = 0; idx_l <= (int)_polyDegreeBasis; idx_l++ ) { for( int idx_k = -idx_l; idx_k <= idx_l; idx_k++ ) { _outputFields[idx_group][_basis->GetGlobalIndexBasis( idx_l, idx_k )].resize( _nCells ); _outputFieldNames[idx_group][_basis->GetGlobalIndexBasis( idx_l, idx_k )] = @@ -263,7 +263,7 @@ void MNSolver::PrepareVolumeOutput() { } } else { - for( int idx_l = 0; idx_l <= (int)_LMaxDegree; idx_l++ ) { + for( int idx_l = 0; idx_l <= (int)_polyDegreeBasis; idx_l++ ) { unsigned maxOrder_k = _basis->GetCurrDegreeSize( idx_l ); for( unsigned idx_k = 0; idx_k < maxOrder_k; idx_k++ ) { _outputFields[idx_group][_basis->GetGlobalIndexBasis( idx_l, idx_k )].resize( _nCells ); @@ -287,12 +287,12 @@ void MNSolver::PrepareVolumeOutput() { } } -void MNSolver::WriteVolumeOutput( unsigned idx_pseudoTime ) { +void MNSolver::WriteVolumeOutput( unsigned idx_iter ) { unsigned nGroups = (unsigned)_settings->GetNVolumeOutput(); // Check if volume output fields are written to file this iteration - if( ( _settings->GetVolumeOutputFrequency() != 0 && idx_pseudoTime % (unsigned)_settings->GetVolumeOutputFrequency() == 0 ) || - ( idx_pseudoTime == _nEnergies - 1 ) /* need sol at last iteration */ ) { + if( ( _settings->GetVolumeOutputFrequency() != 0 && idx_iter % (unsigned)_settings->GetVolumeOutputFrequency() == 0 ) || + ( idx_iter == _nEnergies - 1 ) /* need sol at last iteration */ ) { for( unsigned idx_group = 0; idx_group < nGroups; idx_group++ ) { switch( _settings->GetVolumeOutput()[idx_group] ) { @@ -302,14 +302,14 @@ void MNSolver::WriteVolumeOutput( unsigned idx_pseudoTime ) { } break; case MOMENTS: - for( unsigned idx_sys = 0; idx_sys < _nTotalEntries; idx_sys++ ) { + for( unsigned idx_sys = 0; idx_sys < _nSystem; idx_sys++ ) { for( unsigned idx_cell = 0; idx_cell < _nCells; ++idx_cell ) { _outputFields[idx_group][idx_sys][idx_cell] = _sol[idx_cell][idx_sys]; } } break; case DUAL_MOMENTS: - for( unsigned idx_sys = 0; idx_sys < _nTotalEntries; idx_sys++ ) { + for( unsigned idx_sys = 0; idx_sys < _nSystem; idx_sys++ ) { for( unsigned idx_cell = 0; idx_cell < _nCells; ++idx_cell ) { _outputFields[idx_group][idx_sys][idx_cell] = _alpha[idx_cell][idx_sys]; } @@ -319,10 +319,10 @@ void MNSolver::WriteVolumeOutput( unsigned idx_pseudoTime ) { // Compute total "mass" of the system ==> to check conservation properties for( unsigned idx_cell = 0; idx_cell < _nCells; ++idx_cell ) { - double time = idx_pseudoTime * _dE; + double time = idx_iter * _dE; _outputFields[idx_group][0][idx_cell] = _problem->GetAnalyticalSolution( - _mesh->GetCellMidPoints()[idx_cell][0], _mesh->GetCellMidPoints()[idx_cell][1], time, _sigmaS[idx_pseudoTime][idx_cell] ); + _mesh->GetCellMidPoints()[idx_cell][0], _mesh->GetCellMidPoints()[idx_cell][1], time, _sigmaS[idx_iter][idx_cell] ); } break; diff --git a/code/src/solvers/pnsolver.cpp b/code/src/solvers/pnsolver.cpp index 549952e..29fe8e6 100644 --- a/code/src/solvers/pnsolver.cpp +++ b/code/src/solvers/pnsolver.cpp @@ -11,30 +11,30 @@ #include PNSolver::PNSolver( Config* settings ) : SolverBase( settings ) { - _LMaxDegree = settings->GetMaxMomentDegree(); - _nTotalEntries = GlobalIndex( int( _LMaxDegree ), int( _LMaxDegree ) ) + 1; + _polyDegreeBasis = settings->GetMaxMomentDegree(); + _nSystem = GlobalIndex( int( _polyDegreeBasis ), int( _polyDegreeBasis ) ) + 1; // Initialize System Matrices - _Ax = SymMatrix( _nTotalEntries ); - _Ay = SymMatrix( _nTotalEntries ); - _Az = SymMatrix( _nTotalEntries ); - - _AxPlus = Matrix( _nTotalEntries, _nTotalEntries, 0 ); - _AxMinus = Matrix( _nTotalEntries, _nTotalEntries, 0 ); - _AxAbs = Matrix( _nTotalEntries, _nTotalEntries, 0 ); - _AyPlus = Matrix( _nTotalEntries, _nTotalEntries, 0 ); - _AyMinus = Matrix( _nTotalEntries, _nTotalEntries, 0 ); - _AyAbs = Matrix( _nTotalEntries, _nTotalEntries, 0 ); - _AzPlus = Matrix( _nTotalEntries, _nTotalEntries, 0 ); - _AzMinus = Matrix( _nTotalEntries, _nTotalEntries, 0 ); - _AzAbs = Matrix( _nTotalEntries, _nTotalEntries, 0 ); + _Ax = SymMatrix( _nSystem ); + _Ay = SymMatrix( _nSystem ); + _Az = SymMatrix( _nSystem ); + + _AxPlus = Matrix( _nSystem, _nSystem, 0 ); + _AxMinus = Matrix( _nSystem, _nSystem, 0 ); + _AxAbs = Matrix( _nSystem, _nSystem, 0 ); + _AyPlus = Matrix( _nSystem, _nSystem, 0 ); + _AyMinus = Matrix( _nSystem, _nSystem, 0 ); + _AyAbs = Matrix( _nSystem, _nSystem, 0 ); + _AzPlus = Matrix( _nSystem, _nSystem, 0 ); + _AzMinus = Matrix( _nSystem, _nSystem, 0 ); + _AzAbs = Matrix( _nSystem, _nSystem, 0 ); // Initialize Scatter Matrix - _scatterMatDiag = Vector( _nTotalEntries, 0 ); + _scatterMatDiag = Vector( _nSystem, 0 ); // Initialize temporary storages of solution derivatives - _solDx = VectorVector( _nCells, Vector( _nTotalEntries, 0.0 ) ); - _solDy = VectorVector( _nCells, Vector( _nTotalEntries, 0.0 ) ); + _solDx = VectorVector( _nCells, Vector( _nSystem, 0.0 ) ); + _solDy = VectorVector( _nCells, Vector( _nSystem, 0.0 ) ); // Fill System Matrices ComputeSystemMatrices(); @@ -53,11 +53,11 @@ PNSolver::PNSolver( Config* settings ) : SolverBase( settings ) { // TODO } -void PNSolver::IterPreprocessing( unsigned /*idx_pseudotime*/ ) { +void PNSolver::IterPreprocessing( unsigned /*idx_iter*/ ) { // Nothing to preprocess for PNSolver } -void PNSolver::IterPostprocessing( unsigned idx_pseudotime ) { +void PNSolver::IterPostprocessing( unsigned /*idx_iter*/ ) { // --- Update Solution --- _sol = _solNew; @@ -74,7 +74,7 @@ void PNSolver::ComputeRadFlux() { void PNSolver::FluxUpdate() { if( _reconsOrder > 1 ) { - _mesh->ReconstructSlopesU( _nTotalEntries, _solDx, _solDy, _sol ); // unstructured reconstruction + _mesh->ReconstructSlopesU( _nSystem, _solDx, _solDy, _sol ); // unstructured reconstruction //_mesh->ComputeSlopes( _nTotalEntries, _solDx, _solDy, _sol ); // unstructured reconstruction } // Vector solL( _nTotalEntries ); @@ -89,7 +89,7 @@ void PNSolver::FluxUpdate() { if( _boundaryCells[idx_cell] == BOUNDARY_TYPE::DIRICHLET ) continue; // Reset temporary variable psiNew - for( unsigned idx_sys = 0; idx_sys < _nTotalEntries; idx_sys++ ) { + for( unsigned idx_sys = 0; idx_sys < _nSystem; idx_sys++ ) { _solNew[idx_cell][idx_sys] = 0.0; } @@ -159,7 +159,7 @@ void PNSolver::FVMUpdate( unsigned idx_energy ) { // Dirichlet cells stay at IC, farfield assumption if( _boundaryCells[idx_cell] == BOUNDARY_TYPE::DIRICHLET ) continue; // Flux update - for( unsigned idx_sys = 0; idx_sys < _nTotalEntries; idx_sys++ ) { + for( unsigned idx_sys = 0; idx_sys < _nSystem; idx_sys++ ) { _solNew[idx_cell][idx_sys] = _sol[idx_cell][idx_sys] - ( _dE / _areas[idx_cell] ) * _solNew[idx_cell][idx_sys] /* cell averaged flux */ - _dE * _sol[idx_cell][idx_sys] * ( _sigmaT[idx_energy][idx_cell] /* absorbtion influence */ @@ -175,7 +175,7 @@ void PNSolver::ComputeSystemMatrices() { unsigned idx_row = 0; // loop over columns of A - for( int idx_lOrder = 0; idx_lOrder <= int( _LMaxDegree ); idx_lOrder++ ) { // index of legendre polynom + for( int idx_lOrder = 0; idx_lOrder <= int( _polyDegreeBasis ); idx_lOrder++ ) { // index of legendre polynom for( int idx_kOrder = -idx_lOrder; idx_kOrder <= idx_lOrder; idx_kOrder++ ) { // second index of legendre function idx_row = unsigned( GlobalIndex( idx_lOrder, idx_kOrder ) ); @@ -247,17 +247,17 @@ void PNSolver::ComputeSystemMatrices() { } void PNSolver::ComputeFluxComponents() { - Vector eigenValues( _nTotalEntries, 0 ); - Vector eigenValuesX( _nTotalEntries, 0 ); - Vector eigenValuesY( _nTotalEntries, 0 ); + Vector eigenValues( _nSystem, 0 ); + Vector eigenValuesX( _nSystem, 0 ); + Vector eigenValuesY( _nSystem, 0 ); - MatrixCol eigenVectors( _nTotalEntries, _nTotalEntries, 0 ); // ColumnMatrix for _AxPlus * eigenVectors Multiplication via SIMD + MatrixCol eigenVectors( _nSystem, _nSystem, 0 ); // ColumnMatrix for _AxPlus * eigenVectors Multiplication via SIMD // --- For x Direction --- { blaze::eigen( _Ax, eigenValues, eigenVectors ); // Compute Eigenvalues and Eigenvectors // Compute Flux Matrices A+ and A- - for( unsigned idx_ij = 0; idx_ij < _nTotalEntries; idx_ij++ ) { + for( unsigned idx_ij = 0; idx_ij < _nSystem; idx_ij++ ) { if( eigenValues[idx_ij] >= 0 ) { _AxPlus( idx_ij, idx_ij ) = eigenValues[idx_ij]; // positive part of Diagonal Matrix stored in _AxPlus _AxAbs( idx_ij, idx_ij ) = eigenValues[idx_ij]; @@ -283,7 +283,7 @@ void PNSolver::ComputeFluxComponents() { blaze::eigen( _Ay, eigenValues, eigenVectors ); // Compute Eigenvalues and Eigenvectors // Compute Flux Matrices A+ and A- - for( unsigned idx_ij = 0; idx_ij < _nTotalEntries; idx_ij++ ) { + for( unsigned idx_ij = 0; idx_ij < _nSystem; idx_ij++ ) { if( eigenValues[idx_ij] >= 0 ) { _AyPlus( idx_ij, idx_ij ) = eigenValues[idx_ij]; // positive part of Diagonal Matrix stored in _AxPlus _AyAbs( idx_ij, idx_ij ) = eigenValues[idx_ij]; @@ -309,7 +309,7 @@ void PNSolver::ComputeFluxComponents() { blaze::eigen( _Az, eigenValues, eigenVectors ); // Compute Eigenvalues and Eigenvectors // Compute Flux Matrices A+ and A- - for( unsigned idx_ij = 0; idx_ij < _nTotalEntries; idx_ij++ ) { + for( unsigned idx_ij = 0; idx_ij < _nSystem; idx_ij++ ) { if( eigenValues[idx_ij] >= 0 ) { _AzPlus( idx_ij, idx_ij ) = eigenValues[idx_ij]; // positive part of Diagonal Matrix stored in _AxPlus _AzAbs( idx_ij, idx_ij ) = eigenValues[idx_ij]; @@ -346,7 +346,7 @@ void PNSolver::ComputeScatterMatrix() { // --- Isotropic --- _scatterMatDiag[0] = -1.0; - for( unsigned idx_diag = 1; idx_diag < _nTotalEntries; idx_diag++ ) { + for( unsigned idx_diag = 1; idx_diag < _nSystem; idx_diag++ ) { _scatterMatDiag[idx_diag] = 0.0; } } @@ -393,10 +393,10 @@ void PNSolver::PrepareVolumeOutput() { case MOMENTS: // As many entries as there are moments in the system - _outputFields[idx_group].resize( _nTotalEntries ); - _outputFieldNames[idx_group].resize( _nTotalEntries ); + _outputFields[idx_group].resize( _nSystem ); + _outputFieldNames[idx_group].resize( _nSystem ); - for( int idx_l = 0; idx_l <= (int)_LMaxDegree; idx_l++ ) { + for( int idx_l = 0; idx_l <= (int)_polyDegreeBasis; idx_l++ ) { for( int idx_k = -idx_l; idx_k <= idx_l; idx_k++ ) { _outputFields[idx_group][GlobalIndex( idx_l, idx_k )].resize( _nCells ); @@ -423,7 +423,7 @@ void PNSolver::WriteVolumeOutput( unsigned idx_pseudoTime ) { } break; case MOMENTS: - for( unsigned idx_sys = 0; idx_sys < _nTotalEntries; idx_sys++ ) { + for( unsigned idx_sys = 0; idx_sys < _nSystem; idx_sys++ ) { for( unsigned idx_cell = 0; idx_cell < _nCells; ++idx_cell ) { _outputFields[idx_group][idx_sys][idx_cell] = _sol[idx_cell][idx_sys]; } @@ -436,8 +436,8 @@ void PNSolver::WriteVolumeOutput( unsigned idx_pseudoTime ) { } void PNSolver::CleanFluxMatrices() { - for( unsigned idx_row = 0; idx_row < _nTotalEntries; idx_row++ ) { - for( unsigned idx_col = 0; idx_col < _nTotalEntries; idx_col++ ) { + for( unsigned idx_row = 0; idx_row < _nSystem; idx_row++ ) { + for( unsigned idx_col = 0; idx_col < _nSystem; idx_col++ ) { if( std::abs( _AxAbs( idx_row, idx_col ) ) < 0.00000000001 ) _AxAbs( idx_row, idx_col ) = 0.0; if( std::abs( _AxPlus( idx_row, idx_col ) ) < 0.00000000001 ) _AxPlus( idx_row, idx_col ) = 0.0; if( std::abs( _AxMinus( idx_row, idx_col ) ) < 0.00000000001 ) _AxMinus( idx_row, idx_col ) = 0.0; @@ -514,7 +514,7 @@ int PNSolver::GlobalIndex( int l, int k ) const { } bool PNSolver::CheckIndex( int l, int k ) const { - if( l >= 0 && l <= int( _LMaxDegree ) ) { + if( l >= 0 && l <= int( _polyDegreeBasis ) ) { if( k >= -l && k <= l ) return true; } return false; diff --git a/code/src/solvers/snsolver.cpp b/code/src/solvers/snsolver.cpp index a3c4739..d24ec13 100644 --- a/code/src/solvers/snsolver.cpp +++ b/code/src/solvers/snsolver.cpp @@ -23,7 +23,7 @@ SNSolver::SNSolver( Config* settings ) : SolverBase( settings ) { delete k; } -void SNSolver::IterPreprocessing( unsigned /*idx_pseudotime*/ ) { +void SNSolver::IterPreprocessing( unsigned /*idx_iter*/ ) { // Nothing to do for SNSolver } diff --git a/doc/solvers/mnsolver.rst b/doc/solvers/mnsolver.rst index 0260e2b..2ccbe0e 100644 --- a/doc/solvers/mnsolver.rst +++ b/doc/solvers/mnsolver.rst @@ -3,3 +3,5 @@ MNSolver .. doxygenclass:: MNSolver :members: + :protected-members: + :private-members: diff --git a/doc/solvers/pnsolver.rst b/doc/solvers/pnsolver.rst index f52b587..f64e425 100644 --- a/doc/solvers/pnsolver.rst +++ b/doc/solvers/pnsolver.rst @@ -3,3 +3,6 @@ PNSolver .. doxygenclass:: PNSolver :members: + :protected-members: + :private-members: + -- GitLab From 6692a69bc4a66e149a9be9b4f64c76f0ca7a41bc Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 15:18:07 +0100 Subject: [PATCH 31/67] Add MN doc Former-commit-id: 359e017b6a107b23eeada87d3bfd560eabfc4c1c --- doc/index.rst | 4 ++-- doc/physics.rst | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/doc/index.rst b/doc/index.rst index a2c14dc..78f4837 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -10,8 +10,8 @@ The framework provides rich deterministic solver types for different domain-spec A list of current supported models and equations is as follows. - linear Boltzmann (:math:`S_N`) equation -- spherical harmonics (:math:`P_N`) equations -- entropy-closure moment (:math:`M_N`) equations +- spherical harmonics (:math:`P_N`) moment equations +- entropy-closure (:math:`M_N`) moment equations - continuous slowing down equation diff --git a/doc/physics.rst b/doc/physics.rst index 53e3490..3624263 100644 --- a/doc/physics.rst +++ b/doc/physics.rst @@ -75,6 +75,7 @@ Let us consider the radiative transfer equation in one-dimensional physical spac where :math:`\mu` is the projected angular variable on :math:`z` axis. To obtain the :math:`P_N` equations, we express the angular dependence of the distribution function in terms of a Fourier series, + .. math:: \psi(t, z, \mu)=\sum_{\ell=0}^{\infty} \psi_{\ell}(t, z) \frac{2 \ell+1}{2} P_{\ell}(\mu), @@ -83,6 +84,7 @@ where :math:`P_{\ell}` are the Legendre polynomials. These form an orthogonal basis of the space of polynomials with respect to the standard scalar product on :math:`[−1, 1]`. We can then obtain + .. math:: \partial_{t} \psi_{\ell}+\partial_{z} \int_{=1}^{1} \mu P_{\ell} \psi \mathrm{d} \mu+\Sigma_{t \ell} \psi_{\ell}=q_{\ell}, @@ -122,8 +124,63 @@ where :math:`\ell \leq 0` and :math:`\ell \leq m \leq -\ell`. The entropy closure moment equations --------- +Another method of moments comes from the minimal principle of a convex entropy to close the moment system. +Derivation of such moment system begins with the choice of a vector-valued function +:math:`m: \mathbb{S}^{2} \rightarrow \mathbb{R}^{n}, \Omega \mapsto\left[m_{0}(\Omega), \ldots, m_{n-1}(\Omega)\right]^{T}`, +whose n components are linearly independent functions of :math:`\Omega`. +Evolution equations for the moments u(x, t) := +hmψ(x, ·, t)i are found by multiplying the transport equation by m and integrating +over all angles to give + +.. math:: + + \frac{1}{v} \partial_{t} u+\nabla_{x} \cdot\langle\Omega m \psi\rangle=\langle m \mathcal{C}(\psi)\rangle + +The system above is not closed; a recipe, or closure, must be prescribed to express +unknown quantities in terms of the given moments. Often this is done via an +approximation for :math:`\psi` that depends on :math:`u`, + +.. math:: + + \psi(x, \Omega, t) \simeq \mathcal{E}(u(x, t))(\Omega) + +A general strategy for prescribing a closure is to +use the solution of a constrained optimization problem + +.. math:: + :label: closure + + \min_{g \in \operatorname{Dom}(\mathcal{H})} & \mathcal{H}(g) \\ + \quad \text { s.t. } & \langle\mathbf{m} g\rangle=\langle\mathbf{m} \psi\rangle=u + \end{array} + +where :math:`\mathcal H(g)=\langle \eta(g) \rangle` and $\eta: \mathbb R \rightarrow \mathbb R$ +is a convex function that is related to +the entropy of the system. For photons, the physically relevant entropy comes from +Bose-Einstein statistics +.. math:: + + \eta(g)=\frac{2 k \nu^{2}}{c^{3}}\left[n_{g} \log \left(n_{g}\right)-\left(n_{g}+1\right) \log \left(n_{g}+1\right)\right] + +The solution of :eq:`closure` is expressed in terms of the Legendre dual + +.. math:: + + \eta_{*}(f)=-\frac{2 k \nu^{2}}{c^{3}} \log \left(1-\exp \left(-\frac{h \nu c}{k} f\right)\right) + +Let + +.. math:: + + \mathcal{B}(\boldsymbol{\alpha}):=\eta_{*}^{\prime}\left(\boldsymbol{\alpha}^{T} \mathbf{m}\right)=\frac{2 h \nu^{3}}{c^{2}} \frac{1}{\exp \left(-\frac{h \nu c}{k} \boldsymbol{\alpha}^{T} \mathbf{m}\right)-1} + +The solution of :eq:`closure` is given by :math:`\mathcal B(\hat \alpha)`, where :math:`\hat \alpha= \hat \alpha(u)` solves the +dual problem + +.. math:: + \min _{\boldsymbol{\alpha} \in \mathbb{R}^{n}}\left\{\left\langle\eta_{*}\left(\boldsymbol{\alpha}^{T} \mathbf{m}\right)\right\rangle-\boldsymbol{\alpha}^{T} \mathbf{u}\right\}. The continuous slowing down approximation -- GitLab From f5a65b8270637e6400a084d5da9c54a88847f71e Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 15:23:40 +0100 Subject: [PATCH 32/67] Finish theory part Former-commit-id: 2fbcd7a219e5323e69d09bfc5b8376f7840df6a9 --- doc/physics.rst | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/doc/physics.rst b/doc/physics.rst index 3624263..5f70088 100644 --- a/doc/physics.rst +++ b/doc/physics.rst @@ -134,7 +134,7 @@ over all angles to give .. math:: - \frac{1}{v} \partial_{t} u+\nabla_{x} \cdot\langle\Omega m \psi\rangle=\langle m \mathcal{C}(\psi)\rangle + \frac{1}{v} \partial_{t} u+\nabla_{x} \cdot\langle\Omega m \psi\rangle=\langle m \mathcal{C}(\psi)\rangle. The system above is not closed; a recipe, or closure, must be prescribed to express unknown quantities in terms of the given moments. Often this is done via an @@ -142,7 +142,7 @@ approximation for :math:`\psi` that depends on :math:`u`, .. math:: - \psi(x, \Omega, t) \simeq \mathcal{E}(u(x, t))(\Omega) + \psi(x, \Omega, t) \simeq \mathcal{E}(u(x, t))(\Omega). A general strategy for prescribing a closure is to use the solution of a constrained optimization problem @@ -151,8 +151,7 @@ use the solution of a constrained optimization problem :label: closure \min_{g \in \operatorname{Dom}(\mathcal{H})} & \mathcal{H}(g) \\ - \quad \text { s.t. } & \langle\mathbf{m} g\rangle=\langle\mathbf{m} \psi\rangle=u - \end{array} + \quad \text { s.t. } & \langle\mathbf{m} g\rangle=\langle\mathbf{m} \psi\rangle=u, where :math:`\mathcal H(g)=\langle \eta(g) \rangle` and $\eta: \mathbb R \rightarrow \mathbb R$ is a convex function that is related to @@ -161,21 +160,27 @@ Bose-Einstein statistics .. math:: - \eta(g)=\frac{2 k \nu^{2}}{c^{3}}\left[n_{g} \log \left(n_{g}\right)-\left(n_{g}+1\right) \log \left(n_{g}+1\right)\right] + \eta(g)=\frac{2 k \nu^{2}}{v^{3}}\left[n_{g} \log \left(n_{g}\right)-\left(n_{g}+1\right) \log \left(n_{g}+1\right)\right], + +where :math:`n_g` is the occupation number associated with g, + +.. math:: + + n_{g}:=\frac{v^{2}}{2 h \nu^{3}} g. The solution of :eq:`closure` is expressed in terms of the Legendre dual .. math:: - \eta_{*}(f)=-\frac{2 k \nu^{2}}{c^{3}} \log \left(1-\exp \left(-\frac{h \nu c}{k} f\right)\right) + \eta_{*}(f)=-\frac{2 k \nu^{2}}{v^{3}} \log \left(1-\exp \left(-\frac{h \nu c}{k} f\right)\right). Let .. math:: - \mathcal{B}(\boldsymbol{\alpha}):=\eta_{*}^{\prime}\left(\boldsymbol{\alpha}^{T} \mathbf{m}\right)=\frac{2 h \nu^{3}}{c^{2}} \frac{1}{\exp \left(-\frac{h \nu c}{k} \boldsymbol{\alpha}^{T} \mathbf{m}\right)-1} + \mathcal{B}(\boldsymbol{\alpha}):=\eta_{*}^{\prime}\left(\boldsymbol{\alpha}^{T} \mathbf{m}\right)=\frac{2 h \nu^{3}}{v^{2}} \frac{1}{\exp \left(-\frac{h \nu c}{k} \boldsymbol{\alpha}^{T} \mathbf{m}\right)-1}, -The solution of :eq:`closure` is given by :math:`\mathcal B(\hat \alpha)`, where :math:`\hat \alpha= \hat \alpha(u)` solves the +then the solution of :eq:`closure` is given by :math:`\mathcal B(\hat \alpha)`, where :math:`\hat \alpha= \hat \alpha(u)` solves the dual problem .. math:: -- GitLab From 61f75dffe97482a277a191c017ab38cc13657eb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Fri, 26 Feb 2021 15:26:52 +0100 Subject: [PATCH 33/67] regex changes formatting. More documentation Former-commit-id: 6e5e6011d5d6bd3c714c19cc4985c7f7365b8d79 --- code/include/common/config.h | 16 ++--- code/include/common/io.h | 10 +-- code/include/common/mesh.h | 62 ++++++++-------- code/include/common/optionstructure.h | 76 ++++++++++---------- code/include/entropies/entropybase.h | 30 ++++---- code/include/kernels/scatteringkernelbase.h | 10 +-- code/include/optimizers/mloptimizer.h | 26 +++---- code/include/optimizers/newtonoptimizer.h | 20 +++--- code/include/optimizers/optimizerbase.h | 12 ++-- code/include/problems/checkerboard.h | 16 ++--- code/include/problems/icru.h | 14 ++-- code/include/problems/linesource.h | 16 ++--- code/include/problems/problembase.h | 10 +-- code/include/quadratures/qlookupquadrature.h | 16 ++--- code/include/quadratures/qproduct.h | 2 +- code/include/quadratures/quadraturebase.h | 42 +++++------ code/include/solvers/csdsnsolver.h | 10 +-- code/include/solvers/csdsnsolverfp.h | 26 +++---- code/include/solvers/csdsnsolvernotrafo.h | 10 +-- code/include/solvers/csdsolvertrafofp.h | 34 ++++----- code/include/solvers/csdsolvertrafofp2d.h | 20 +++--- code/include/solvers/csdsolvertrafofpsh2d.h | 20 +++--- code/include/solvers/mnsolver.h | 30 ++++---- code/include/solvers/pnsolver.h | 6 +- code/include/solvers/snsolver.h | 6 +- code/include/solvers/solverbase.h | 4 +- code/include/toolboxes/datagenerator1D.h | 10 +-- code/include/toolboxes/datagenerator3D.h | 10 +-- code/include/toolboxes/datageneratorbase.h | 66 ++++++++--------- code/include/toolboxes/reconstructor.h | 2 +- code/include/toolboxes/sphericalbase.h | 16 ++--- code/include/toolboxes/sphericalharmonics.h | 16 ++--- code/include/toolboxes/sphericalmonomials.h | 42 +++++------ code/src/common/config.cpp | 2 +- code/src/main.cpp | 2 +- code/src/solvers/snsolver.cpp | 2 +- doc/common/config.rst | 2 + doc/solvers/csdsnsolverfp.rst | 1 + doc/solvers/csdsolvertrafofpsh2d.rst | 2 + doc/solvers/snsolver.rst | 2 + doc/solvers/solverbase.rst | 7 ++ 41 files changed, 370 insertions(+), 356 deletions(-) create mode 100644 doc/solvers/solverbase.rst diff --git a/code/include/common/config.h b/code/include/common/config.h index f04c8de..65b9931 100644 --- a/code/include/common/config.h +++ b/code/include/common/config.h @@ -1,6 +1,6 @@ /*! * @file config.h - * @brief: Class to handle all options and their pre and postprocessing. + * @brief Class to handle all options and their pre and postprocessing. * DO NOT CREATE SETTERS FOR THIS CLASS! ALL OPTIONS ARE CONSTANT (after SetPostprocessing). * * @author S. Schotthöfer @@ -48,8 +48,8 @@ class Config unsigned _nQuadPoints; // Mesh - unsigned _nCells; /*!< @brief: Number of cells in the mesh */ - unsigned short _dim; /*!< @brief: spatial dimensionality of the mesh/test case */ + unsigned _nCells; /*!< @brief Number of cells in the mesh */ + unsigned short _dim; /*!< @brief spatial dimensionality of the mesh/test case */ // Boundary Conditions /*!< @brief List of all Pairs (marker, BOUNDARY_TYPE), e.g. (farfield,DIRICHLET). @@ -95,7 +95,7 @@ class Config KERNEL_NAME _kernelName; /*!< @brief Scattering Kernel Name*/ // Spherical Basis - SPHERICAL_BASIS_NAME _sphericalBasisName; /*!< @brief: Name of the basis on the unit sphere */ + SPHERICAL_BASIS_NAME _sphericalBasisName; /*!< @brief Name of the basis on the unit sphere */ // Optimizer OPTIMIZER_NAME _entropyOptimizerName; /*!< @brief Choice of optimizer */ @@ -106,7 +106,7 @@ class Config bool _newtonFastMode; /*!< @brief If true, we skip the NewtonOptimizer for quadratic entropy and assign alpha = u */ // NeuralModel - unsigned short _neuralModel; /*!< @brief: Version number of the employed neural model */ + unsigned short _neuralModel; /*!< @brief Version number of the employed neural model */ // Output Options unsigned short _nVolumeOutput; /*!< @brief Number of volume outputs */ std::vector _volumeOutput; /*!< @brief Output groups for volume output*/ @@ -126,8 +126,8 @@ class Config unsigned long _tainingSetSize; /*!< @brief Size of training data set for data generator */ unsigned long _maxValFirstMoment; /*!< @brief Size of training data set for data generator */ double _RealizableSetEpsilonU0; /*!< @brief Distance to 0 of the sampled moments to the boundary of the realizable set */ - double _RealizableSetEpsilonU1; /*!< @brief: norm(u_1)/u_0 !< _RealizableSetEpsilonU1 */ - bool _normalizedSampling; /*!< @brief: Flag for sampling of normalized moments, i.e. u_0 =1 */ + double _RealizableSetEpsilonU1; /*!< @brief norm(u_1)/u_0 !< _RealizableSetEpsilonU1 */ + bool _normalizedSampling; /*!< @brief Flag for sampling of normalized moments, i.e. u_0 =1 */ // --- Parsing Functionality and Initializing of Options --- /*! @@ -299,7 +299,7 @@ class Config unsigned short inline GetNeuralModel() { return _neuralModel; } // Boundary Conditions - BOUNDARY_TYPE GetBoundaryType( std::string nameMarker ) const; /*! @brief Get Boundary Type of given marker */ + BOUNDARY_TYPE GetBoundaryType( std::string nameMarker ) const; /*!< @brief Get Boundary Type of given marker */ // Scattering Kernel KERNEL_NAME inline GetKernelName() const { return _kernelName; } diff --git a/code/include/common/io.h b/code/include/common/io.h index 4560823..abf26dd 100644 --- a/code/include/common/io.h +++ b/code/include/common/io.h @@ -9,11 +9,11 @@ class Config; class Mesh; -/*! @brief: Function to export solver Volume output to VTK file. - * @param: filename: Filename of output file - * @param: outputFields: numerical output of the solver. Dimensions: (OutputGroupSize, OutputFieldSize, NumberMeshCells) - * @param: outputFieldNames: names of the outputfields. Dimensions: (OutputGroupSize, OutputFieldSize) - * @param: mesh: Mesh with cells (the mesh used for the computation) +/*! @brief Function to export solver Volume output to VTK file. + * @param filename: Filename of output file + * @param outputFields: numerical output of the solver. Dimensions: (OutputGroupSize, OutputFieldSize, NumberMeshCells) + * @param outputFieldNames: names of the outputfields. Dimensions: (OutputGroupSize, OutputFieldSize) + * @param mesh: Mesh with cells (the mesh used for the computation) */ void ExportVTK( const std::string fileName, const std::vector>>& outputFields, diff --git a/code/include/common/mesh.h b/code/include/common/mesh.h index 0de9c63..416ae9f 100644 --- a/code/include/common/mesh.h +++ b/code/include/common/mesh.h @@ -18,51 +18,51 @@ class Mesh { protected: - const unsigned _dim; /*! @brief: spatial dimension of the mesh, i.e. 1D,2D,3D */ - const unsigned _numCells; /*! @brief: number of cells in the mesh */ - const unsigned _numNodes; /*! @brief: number of nodes in the mesh (for node centered view)*/ - const unsigned _numNodesPerCell; /*! @brief: number of nodes per cell */ - const unsigned _numBoundaries; /*! @brief: number of boundary cells in the mesh */ - const unsigned _ghostCellID; /*! @brief: Id of the ghost cell. (we use only one ghost cell). equal to _numCells and therefore has the ID of the + const unsigned _dim; /*!< @brief spatial dimension of the mesh, i.e. 1D,2D,3D */ + const unsigned _numCells; /*!< @brief number of cells in the mesh */ + const unsigned _numNodes; /*!< @brief number of nodes in the mesh (for node centered view)*/ + const unsigned _numNodesPerCell; /*!< @brief number of nodes per cell */ + const unsigned _numBoundaries; /*!< @brief number of boundary cells in the mesh */ + const unsigned _ghostCellID; /*!< @brief Id of the ghost cell. (we use only one ghost cell). equal to _numCells and therefore has the ID of the last cell + 1 */ unsigned _numNodesPerBoundary; std::vector> _bounds; // ??? - std::vector _nodes; /*! @brief: nodes in the mesh. dimension:_numNodes<_dim> */ - std::vector> _cells; /*! @brief: cells in the mesh. dimension:_numCells<_numNodesPerCell> */ + std::vector _nodes; /*!< @brief nodes in the mesh. dimension:_numNodes<_dim> */ + std::vector> _cells; /*!< @brief cells in the mesh. dimension:_numCells<_numNodesPerCell> */ - /*! @brief: boundary cells in the mesh. Pair defines boundary type of the boundary nodes of the cell. numBoundaries<(1,numBoundaryNodes)>*/ + /*! @brief boundary cells in the mesh. Pair defines boundary type of the boundary nodes of the cell. numBoundaries<(1,numBoundaryNodes)>*/ std::vector>> _boundaries; - std::vector _cellAreas; /*! @brief: cell areas of the mesh. dimension: numCells*/ - std::vector _cellMidPoints; /*! @brief: cell midpoints of the mesh. dimension: numCells*/ - std::vector> _cellNeighbors; /*! @brief: neighbors of each cell. dimension: numCells*/ + std::vector _cellAreas; /*!< @brief cell areas of the mesh. dimension: numCells*/ + std::vector _cellMidPoints; /*!< @brief cell midpoints of the mesh. dimension: numCells*/ + std::vector> _cellNeighbors; /*!< @brief neighbors of each cell. dimension: numCells*/ - /*! @brief: outward facing normals of each side of each cell. dimension: numCells>, all + /*! @brief outward facing normals of each side of each cell. dimension: numCells>, all normals are facing away from the cell center, and scaled with the edge length */ std::vector> _cellNormals; - /*! @brief: Tags each cell with its boundary type. None means no boundary. dimension: numCells */ + /*! @brief Tags each cell with its boundary type. None means no boundary. dimension: numCells */ std::vector _cellBoundaryTypes; - std::vector _colors; /*! @brief: Color of each cell (for MPI mesh partitioning). dimension: numCells */ - blaze::CompressedMatrix _nodeNeighbors; /*! @brief: neighborshood relationship of nodes for (par-)metis */ + std::vector _colors; /*!< @brief Color of each cell (for MPI mesh partitioning). dimension: numCells */ + blaze::CompressedMatrix _nodeNeighbors; /*!< @brief neighborshood relationship of nodes for (par-)metis */ - void ComputeCellAreas(); /*! @brief: Computes only the areas of the mesh cells. Write to _cellAreas. */ - void ComputeCellMidpoints(); /*! @brief: Compute only the midpoints of the cells. Write to _cellMidPoints*/ - void ComputeConnectivity(); /*! @brief: Computes _cellNeighbors and _nodeNeighbors, i.e. neighborship relation in mesh*/ - void ComputePartitioning(); /*! @brief: Computes local partitioning for openMP */ + void ComputeCellAreas(); /*!< @brief Computes only the areas of the mesh cells. Write to _cellAreas. */ + void ComputeCellMidpoints(); /*!< @brief Compute only the midpoints of the cells. Write to _cellMidPoints*/ + void ComputeConnectivity(); /*!< @brief Computes _cellNeighbors and _nodeNeighbors, i.e. neighborship relation in mesh*/ + void ComputePartitioning(); /*!< @brief Computes local partitioning for openMP */ - /*! @brief: Computes outward facing normal of two neighboring nodes nodeA and nodeB with common cellCellcenter. + /*! @brief Computes outward facing normal of two neighboring nodes nodeA and nodeB with common cellCellcenter. * Normals are scaled with their respective edge length - * @param: nodeA: first node - * @param: nodeB: neighboring node to nodeA - * @param: cellCenter: Center of the cell that has nodeA and nodeB as nodes. - * @return: outward facing normal */ + * @param nodeA: first node + * @param nodeB: neighboring node to nodeA + * @param cellCenter: Center of the cell that has nodeA and nodeB as nodes. + * @return outward facing normal */ Vector ComputeOutwardFacingNormal( const Vector& nodeA, const Vector& nodeB, const Vector& cellCenter ); - void ComputeBounds(); /*! @brief: Computes the spatial bounds of a 2D domain. */ + void ComputeBounds(); /*!< @brief Computes the spatial bounds of a 2D domain. */ public: Mesh() = delete; // no default constructor - /*! @brief: Constructor of mesh. Needs nodes, cells, and boundary descriptions as specified above. + /*! @brief Constructor of mesh. Needs nodes, cells, and boundary descriptions as specified above. * See LoadSU2MeshFromFile in io.cpp for setup information*/ Mesh( std::vector nodes, std::vector> cells, @@ -74,8 +74,8 @@ class Mesh inline unsigned GetNumNodes() const { return _numNodes; } inline unsigned GetNumNodesPerCell() const { return _numNodesPerCell; } - /*! @brief: Returns all node coordinates - * @return: dimension: numNodes x dim */ + /*! @brief Returns all node coordinates + * @return dimension: numNodes x dim */ const std::vector& GetNodes() const; /*! @brief Returns the mid point coordinates of each cell @@ -122,13 +122,13 @@ class Mesh // Not used void ComputeSlopes( unsigned nq, VectorVector& psiDerX, VectorVector& psiDerY, const VectorVector& psi ) const; - /*! @brief:Structured mesh slope reconstruction with flux limiters. + /*! @briefStructured mesh slope reconstruction with flux limiters. * @param nq is number of quadrature points * @param psiDerX is slope in x direction (gets computed. Slope is stored here) * @param psiDerY is slope in y direction (gets computed. Slope is stored here) * @param psi is solution for which slope is computed */ void ReconstructSlopesS( unsigned nq, VectorVector& psiDerX, VectorVector& psiDerY, const VectorVector& psi ) const; - /*! @brief: Use gauss theorem and limiters. For unstructured mesh * + /*! @brief Use gauss theorem and limiters. For unstructured mesh * * @param nq is number of quadrature points * @param psiDerX is slope in x direction (gets computed. Slope is stored here) * @param psiDerY is slope in y direction (gets computed. Slope is stored here) diff --git a/code/include/common/optionstructure.h b/code/include/common/optionstructure.h index fd588bd..6681923 100644 --- a/code/include/common/optionstructure.h +++ b/code/include/common/optionstructure.h @@ -19,28 +19,28 @@ class OptionBase { private: - std::vector _value; /*! @brief: String name of the option */ + std::vector _value; /*!< @brief String name of the option */ public: OptionBase() {} virtual ~OptionBase() = 0; - virtual std::string SetValue( std::vector value ); /*! @brief: Set string name of the option */ + virtual std::string SetValue( std::vector value ); /*!< @brief Set string name of the option */ - std::vector GetValue(); /*! @brief: Get string name of the option */ + std::vector GetValue(); /*!< @brief Get string name of the option */ - virtual void SetDefault() = 0; /*! @brief: Set default name for the option */ - /*! @brief: Check if an option is defined multiple times in a config file, if yes, return a string stating this. */ + virtual void SetDefault() = 0; /*!< @brief Set default name for the option */ + /*! @brief Check if an option is defined multiple times in a config file, if yes, return a string stating this. */ std::string OptionCheckMultipleValues( std::vector& option_value, std::string type_id, std::string option_name ); - /*! @brief: If a bad value for an option is detected, this function creates the corresponding output string. */ + /*! @brief If a bad value for an option is detected, this function creates the corresponding output string. */ std::string BadValue( std::vector& option_value, std::string type_id, std::string option_name ); }; class OptionDouble : public OptionBase { - double& _field; /*! @brief: Reference to the double field value */ - double _def; /*! @brief: Default value */ - std::string _name; /*! @brief: String identifier for the option */ + double& _field; /*!< @brief Reference to the double field value */ + double _def; /*!< @brief Default value */ + std::string _name; /*!< @brief String identifier for the option */ public: OptionDouble( std::string option_field_name, double& option_field, double default_value ); @@ -54,9 +54,9 @@ class OptionDouble : public OptionBase class OptionString : public OptionBase { - std::string& _field; /*! @brief: Reference to the string field value */ - std::string _def; /*! @brief: Default value */ - std::string _name; /*! @brief: string identifier for the option */ + std::string& _field; /*!< @brief Reference to the string field value */ + std::string _def; /*!< @brief Default value */ + std::string _name; /*!< @brief string identifier for the option */ public: OptionString( std::string option_field_name, std::string& option_field, std::string default_value ); @@ -70,9 +70,9 @@ class OptionString : public OptionBase class OptionInt : public OptionBase { - int& _field; /*! @brief: Reference to the int field value */ - int _def; /*! @brief: Default value */ - std::string _name; /*! @brief: string identifier for the option */ + int& _field; /*!< @brief Reference to the int field value */ + int _def; /*!< @brief Default value */ + std::string _name; /*!< @brief string identifier for the option */ public: OptionInt( std::string option_field_name, int& option_field, int default_value ); @@ -86,9 +86,9 @@ class OptionInt : public OptionBase class OptionULong : public OptionBase { - unsigned long& _field; /*! @brief: Reference to the unsigned long field value */ - unsigned long _def; /*! @brief: Default value */ - std::string _name; /*! @brief: string identifier for the option */ + unsigned long& _field; /*!< @brief Reference to the unsigned long field value */ + unsigned long _def; /*!< @brief Default value */ + std::string _name; /*!< @brief string identifier for the option */ public: OptionULong( std::string option_field_name, unsigned long& option_field, unsigned long default_value ); @@ -102,9 +102,9 @@ class OptionULong : public OptionBase class OptionUShort : public OptionBase { - unsigned short& _field; /*! @brief: Reference to the unsigned short field value */ - unsigned short _def; /*! @brief: Default value */ - std::string _name; /*! @brief: string identifier for the option */ + unsigned short& _field; /*!< @brief Reference to the unsigned short field value */ + unsigned short _def; /*!< @brief Default value */ + std::string _name; /*!< @brief string identifier for the option */ public: OptionUShort( std::string option_field_name, unsigned short& option_field, unsigned short default_value ); @@ -118,9 +118,9 @@ class OptionUShort : public OptionBase class OptionLong : public OptionBase { - long& _field; /*! @brief: Reference to the long field value */ - long _def; /*! @brief: Default value */ - std::string _name; /*! @brief: string identifier for the option */ + long& _field; /*!< @brief Reference to the long field value */ + long _def; /*!< @brief Default value */ + std::string _name; /*!< @brief string identifier for the option */ public: OptionLong( std::string option_field_name, long& option_field, long default_value ); @@ -134,9 +134,9 @@ class OptionLong : public OptionBase class OptionBool : public OptionBase { - bool& _field; /*! @brief: Reference to the bool field value */ - bool _def; /*! @brief: Default value */ - std::string _name; /*! @brief: string identifier for the option */ + bool& _field; /*!< @brief Reference to the bool field value */ + bool _def; /*!< @brief Default value */ + std::string _name; /*!< @brief string identifier for the option */ public: OptionBool( std::string option_field_name, bool& option_field, bool default_value ); @@ -150,9 +150,9 @@ class OptionBool : public OptionBase class OptionStringList : public OptionBase { - std::vector& _field; /*! @brief: Reference to the string list field value. no default value */ - std::string _name; /*! @brief: string identifier for the option */ - unsigned short& _size; /*! @brief: Size of string list */ + std::vector& _field; /*!< @brief Reference to the string list field value. no default value */ + std::string _name; /*!< @brief string identifier for the option */ + unsigned short& _size; /*!< @brief Size of string list */ public: OptionStringList( std::string option_field_name, unsigned short& list_size, std::vector& option_field ); @@ -169,10 +169,10 @@ class OptionStringList : public OptionBase template class OptionEnum : public OptionBase { - std::map _map; /*! @brief: Map */ - Tenum& _field; /*! @brief: Reference to the enum fieldname */ - Tenum _def; /*! @brief: Default value */ - std::string _name; /*! @brief: string identifier for the option */ + std::map _map; /*!< @brief Map */ + Tenum& _field; /*!< @brief Reference to the enum fieldname */ + Tenum _def; /*!< @brief Default value */ + std::string _name; /*!< @brief string identifier for the option */ public: OptionEnum( std::string option_field_name, const std::map m, Tenum& option_field, Tenum default_value ) @@ -212,10 +212,10 @@ template class OptionEnum : public OptionBase template class OptionEnumList : public OptionBase { - std::map _map; /*! @brief: Map */ - std::vector& _field; /*! @brief: Reference to the enum list fieldname. No default value */ - std::string _name; /*! @brief: string identifier for the option */ - unsigned short& _size; /*! @brief: Size of enum list */ + std::map _map; /*!< @brief Map */ + std::vector& _field; /*!< @brief Reference to the enum list fieldname. No default value */ + std::string _name; /*!< @brief string identifier for the option */ + unsigned short& _size; /*!< @brief Size of enum list */ public: OptionEnumList( std::string option_field_name, const std::map m, std::vector& option_field, unsigned short& list_size ) diff --git a/code/include/entropies/entropybase.h b/code/include/entropies/entropybase.h index 1c2c3f9..5eb8b17 100644 --- a/code/include/entropies/entropybase.h +++ b/code/include/entropies/entropybase.h @@ -13,40 +13,40 @@ class EntropyBase static EntropyBase* Create( Config* settings ); - /*! @brief: computes the entropy functional - * @param: z = point where the functional should be evaluated. + /*! @brief computes the entropy functional + * @param z = point where the functional should be evaluated. * z must be in domain of the functional * @returns: value of entropy functional at z */ virtual double Entropy( double z ) = 0; - /*! @brief: computes eta'(z).z must be in domain of the functional. - * @param: z = point where the derivative should be evaluated. */ + /*! @brief computes eta'(z).z must be in domain of the functional. + * @param z = point where the derivative should be evaluated. */ virtual double EntropyPrime( double z ) = 0; - /*! @brief: computes the dual of the entropy functional - * @param: z = point where the dual of the functional should be evaluated. + /*! @brief computes the dual of the entropy functional + * @param z = point where the dual of the functional should be evaluated. * z must be in domain of the duaö functional * @returns: value of entropy functional at z */ virtual double EntropyDual( double y ) = 0; - // /*! @brief: computes m*eta_*'(alpha*m). alpha*m must be in domain of the functional + // /*! @brief computes m*eta_*'(alpha*m). alpha*m must be in domain of the functional // * alpha, m and grad must be of same size. - // * @param: alpha = point where the derivative should be evaluated. - // * @param: m = moment vector - // * @param: grad: vector in which the resulting gradient is stored */ + // * @param alpha = point where the derivative should be evaluated. + // * @param m = moment vector + // * @param grad: vector in which the resulting gradient is stored */ // virtual void EntropyPrimeDual( Vector& alpha, Vector& m, Vector& grad ) = 0; - /*! @brief: computes eta_*'(y). - * @param: y = point where the derivative should be evaluated. + /*! @brief computes eta_*'(y). + * @param y = point where the derivative should be evaluated. * @returns: value of the derivative of the entropy functional at y */ virtual double EntropyPrimeDual( double z ) = 0; - /*! @brief: computes the hessian of the dual entropy functional - * @param: y = point where the hessian should be evaluated; + /*! @brief computes the hessian of the dual entropy functional + * @param y = point where the hessian should be evaluated; * @returns: value of the hessian at y */ virtual double EntropyHessianDual( double y ) = 0; - /*! @brief: checks, if value is in domain of entropy */ + /*! @brief checks, if value is in domain of entropy */ virtual bool CheckDomain( double z ) = 0; }; diff --git a/code/include/kernels/scatteringkernelbase.h b/code/include/kernels/scatteringkernelbase.h index 7ff60be..18038ca 100644 --- a/code/include/kernels/scatteringkernelbase.h +++ b/code/include/kernels/scatteringkernelbase.h @@ -19,19 +19,19 @@ class ScatteringKernel ScatteringKernel() = delete; protected: - QuadratureBase* _quad; /*! @brief: Pointer to the quadrature used to compute the scattering integral */ + QuadratureBase* _quad; /*!< @brief Pointer to the quadrature used to compute the scattering integral */ public: - /*! @brief: Copies the pointer of quad. Does not create an own quad */ + /*! @brief Copies the pointer of quad. Does not create an own quad */ ScatteringKernel( QuadratureBase* quad ); virtual ~ScatteringKernel(); - /*! @brief: Computes the scattering kernel and for the whole SN system and stores it in a Matrix - @return: Matrix with discretized scattering kernel */ + /*! @brief Computes the scattering kernel and for the whole SN system and stores it in a Matrix + @return Matrix with discretized scattering kernel */ virtual Matrix GetScatteringKernel() = 0; - /*! @brief: Creates an object of the child class of ScatteringKernelBase corresponding to the enum KERNEL_NAME */ + /*! @brief Creates an object of the child class of ScatteringKernelBase corresponding to the enum KERNEL_NAME */ static ScatteringKernel* CreateScatteringKernel( KERNEL_NAME name, QuadratureBase* quad ); }; diff --git a/code/include/optimizers/mloptimizer.h b/code/include/optimizers/mloptimizer.h index 1eb5a29..2adce16 100644 --- a/code/include/optimizers/mloptimizer.h +++ b/code/include/optimizers/mloptimizer.h @@ -20,28 +20,28 @@ class MLOptimizer : public OptimizerBase void SolveMultiCell( VectorVector& lambda, VectorVector& u, const VectorVector& moments ) override; private: - /*! @brief: Calls the tensorflow neural network for the entropy closure - * @param: inputDim : dimension of moment vector for a single cell - * @param: double* nnInput : moment vector as double array - * @return: Lagrange multiplyer alpha with size input_size + /*! @brief Calls the tensorflow neural network for the entropy closure + * @param inputDim : dimension of moment vector for a single cell + * @param double* nnInput : moment vector as double array + * @return Lagrange multiplyer alpha with size input_size */ double* callNetwork( const unsigned inputDim, double* nnInput ); - /*! @brief: Calls the tensorflow neural network for the entropy closure for the whole mesh - * @param: batchSize : number of cells in the mesh ==> batchsize for the network - * @param: inputDim : dimension of moment vector for a single cell - * @param: double* nnInput : moment vector as double array - * @return: Lagrange multiplyer alpha with size input_size + /*! @brief Calls the tensorflow neural network for the entropy closure for the whole mesh + * @param batchSize : number of cells in the mesh ==> batchsize for the network + * @param inputDim : dimension of moment vector for a single cell + * @param double* nnInput : moment vector as double array + * @return Lagrange multiplyer alpha with size input_size */ double* callNetworkMultiCell( const unsigned batchSize, const unsigned inputDim, double* nnInput ); - /*! @brief: Initializes the Python module. Sets Path for Python, references Python module */ + /*! @brief Initializes the Python module. Sets Path for Python, references Python module */ void initializePython(); - /*! @brief: Initilizes numpy python module. */ + /*! @brief Initilizes numpy python module. */ void initNumpy(); - /*! @brief: Calls Python Funaction to initialize the tensorflow network. */ + /*! @brief Calls Python Funaction to initialize the tensorflow network. */ void initializeNetwork(); - /*! @brief: Finalizes the Python module. Dereferences Python */ + /*! @brief Finalizes the Python module. Dereferences Python */ void finalizePython(); // Python members diff --git a/code/include/optimizers/newtonoptimizer.h b/code/include/optimizers/newtonoptimizer.h index 236aaf2..010c8dd 100644 --- a/code/include/optimizers/newtonoptimizer.h +++ b/code/include/optimizers/newtonoptimizer.h @@ -21,27 +21,27 @@ class NewtonOptimizer : public OptimizerBase void Solve( Vector& alpha, Vector& sol, const VectorVector& moments, unsigned idx_cell = 0 ) override; void SolveMultiCell( VectorVector& alpha, VectorVector& sol, const VectorVector& moments ) override; - /*! @brief: Computes the objective function + /*! @brief Computes the objective function grad = - alpha*sol */ double ComputeObjFunc( Vector& alpha, Vector& sol, const VectorVector& moments ); private: - /*! @brief: Computes gradient of objective function and stores it in grad + /*! @brief Computes gradient of objective function and stores it in grad grad = - sol */ void ComputeGradient( Vector& alpha, Vector& sol, const VectorVector& moments, Vector& grad ); - /*! @brief: Computes hessian of objective function and stores it in hessian + /*! @brief Computes hessian of objective function and stores it in hessian grad = */ void ComputeHessian( Vector& alpha, const VectorVector& moments, Matrix& hessian ); - QuadratureBase* _quadrature; /*! @brief: used quadrature */ // THis is memory doubling! Try to use a pointer. - unsigned _nq; /*! @brief: number of quadrature points */ - Vector _weights; /*! @brief quadrature weights, dim(_weights) = (_nq) */ + QuadratureBase* _quadrature; /*!< @brief used quadrature */ // THis is memory doubling! Try to use a pointer. + unsigned _nq; /*!< @brief number of quadrature points */ + Vector _weights; /*!< @brief quadrature weights, dim(_weights) = (_nq) */ - double _epsilon; /*! @brief: Termination criterion for newton optimizer */ - unsigned short _maxIterations; /*! @brief: Max iterations of the newton solver */ - double _alpha; /*! @brief: Newton Step Size */ - unsigned short _maxLineSearches; /*! @brief: Max amount of line searches for Newton Algo */ + double _epsilon; /*!< @brief Termination criterion for newton optimizer */ + unsigned short _maxIterations; /*!< @brief Max iterations of the newton solver */ + double _alpha; /*!< @brief Newton Step Size */ + unsigned short _maxLineSearches; /*!< @brief Max amount of line searches for Newton Algo */ }; #endif // NEWTONOPTIMIZER_H diff --git a/code/include/optimizers/optimizerbase.h b/code/include/optimizers/optimizerbase.h index 10d3dbd..067b685 100644 --- a/code/include/optimizers/optimizerbase.h +++ b/code/include/optimizers/optimizerbase.h @@ -20,19 +20,19 @@ class OptimizerBase virtual ~OptimizerBase(); - /*! @brief: Optimizer creator: Depending on the chosen option, this function creates an object of the chosen child class of OptimizerBase */ + /*! @brief Optimizer creator: Depending on the chosen option, this function creates an object of the chosen child class of OptimizerBase */ static OptimizerBase* Create( Config* settings ); - /*! @brief : Computes the optimal Lagrange multilpiers for the dual entropy minimization problem - * @param : Vector u = pointer to vector of given moments. // Maybe use pointer for performance? - * @return : Vector alpha = optimal lagrange multipliers. Has the same length as Vector u. */ + /*! @brief Computes the optimal Lagrange multilpiers for the dual entropy minimization problem + * @param Vector u = pointer to vector of given moments. // Maybe use pointer for performance? + * @return Vector alpha = optimal lagrange multipliers. Has the same length as Vector u. */ virtual void Solve( Vector& lambda, Vector& u, const VectorVector& moments, unsigned idx_cell = 0 ) = 0; virtual void SolveMultiCell( VectorVector& lambda, VectorVector& u, const VectorVector& moments ) = 0; protected: - EntropyBase* _entropy; /*! @brief: Class to handle entropy functional evaluations */ - Config* _settings; /*! @biref: Pointer to settings class of the solver */ + EntropyBase* _entropy; /*!< @brief Class to handle entropy functional evaluations */ + Config* _settings; /*!< @biref: Pointer to settings class of the solver */ }; #endif // OPTIMIZERBASE_H diff --git a/code/include/problems/checkerboard.h b/code/include/problems/checkerboard.h index 96deded..3b5671a 100644 --- a/code/include/problems/checkerboard.h +++ b/code/include/problems/checkerboard.h @@ -6,13 +6,13 @@ class Checkerboard_SN : public ProblemBase { private: - Vector _scatteringXS; /*! @brief Vector of scattering crosssections */ - Vector _totalXS; /*! @brief Vector of total crosssections */ + Vector _scatteringXS; /*!< @brief Vector of scattering crosssections */ + Vector _totalXS; /*!< @brief Vector of total crosssections */ Checkerboard_SN() = delete; - bool isAbsorption( const Vector& pos ) const; /*! @return True if pos is in absorption region, False otherwise */ - bool isSource( const Vector& pos ) const; /*! @return True if pos is in source region, False otherwise */ + bool isAbsorption( const Vector& pos ) const; /*!< @return True if pos is in absorption region, False otherwise */ + bool isSource( const Vector& pos ) const; /*!< @return True if pos is in source region, False otherwise */ public: Checkerboard_SN( Config* settings, Mesh* mesh ); @@ -27,13 +27,13 @@ class Checkerboard_SN : public ProblemBase class Checkerboard_PN : public ProblemBase { private: - Vector _scatteringXS; /*! @brief Vector of scattering crosssections len: numCells */ - Vector _totalXS; /*! @brief Vector of total crosssections. len: numCells*/ + Vector _scatteringXS; /*!< @brief Vector of scattering crosssections len: numCells */ + Vector _totalXS; /*!< @brief Vector of total crosssections. len: numCells*/ Checkerboard_PN() = delete; - bool isAbsorption( const Vector& pos ) const; /*! @return True if pos is in absorption region, False otherwise */ - bool isSource( const Vector& pos ) const; /*! @return True if pos is in source region, False otherwise */ + bool isAbsorption( const Vector& pos ) const; /*!< @return True if pos is in absorption region, False otherwise */ + bool isSource( const Vector& pos ) const; /*!< @return True if pos is in source region, False otherwise */ /** * @brief Gets the global index for given order l of Legendre polynomials and given diff --git a/code/include/problems/icru.h b/code/include/problems/icru.h index 17d0acc..c0eda74 100644 --- a/code/include/problems/icru.h +++ b/code/include/problems/icru.h @@ -25,7 +25,7 @@ class Config; class ICRU { private: - Config* _settings; /*! @brief: Pointer to settings file of the solver */ + Config* _settings; /*!< @brief Pointer to settings file of the solver */ const unsigned materialID = 278; const ParticleType particle = ParticleType::ELECTRON; @@ -65,8 +65,8 @@ class ICRU double _BETA2; double _R1; - Vector _E, /*! @brief: User queried Energy */ - _QMU; /*! @brief:User queried mu */ + Vector _E, /*! @brief User queried Energy */ + _QMU; /*!< @briefUser queried mu */ std::vector _ET, _ETL; std::vector _XMU, /* angular variable mu of dataset */ @@ -104,7 +104,7 @@ class ICRU ICRU() = delete; public: - /*! @brief: Constructor of ICRU class + /*! @brief Constructor of ICRU class * @arg: Vector& mu, = Vector of angles * @arg: Vector& energy, = Vector of energies * @arg: Config* settings = pointer to programm settings class @@ -113,18 +113,18 @@ class ICRU ~ICRU(){}; - /*! @brief: Computes the angular scattering cross sections and integrated XS by interpolating tabular data + /*! @brief Computes the angular scattering cross sections and integrated XS by interpolating tabular data * @arg: Matrix& angularXS = Matrix where the angular XS will be saved * @arg: Vector& integratedXS = Vector, where the integratedXS will be saved * @returns: void */ void GetAngularScatteringXS( Matrix& angularXS, Vector& integratedXS ); - /*! @brief: Computes the stopping power by interpolating tabular data + /*! @brief Computes the stopping power by interpolating tabular data * @arg: Vector& stoppingPower = Vector, where the stopping power will be saved * @returns: void */ void GetStoppingPower( Vector& stoppingPower ); - /*! @brief: Computes the transport coefficients by interpolating tabular data + /*! @brief Computes the transport coefficients by interpolating tabular data * @arg: Matrix& xi = Vector, where the stopping power will be saved * @returns: void */ void GetTransportCoefficients( Matrix& xi ); diff --git a/code/include/problems/linesource.h b/code/include/problems/linesource.h index 9a258cf..76ad7f3 100644 --- a/code/include/problems/linesource.h +++ b/code/include/problems/linesource.h @@ -9,28 +9,28 @@ class LineSource : public ProblemBase LineSource() = delete; protected: - double _sigmaS; /*!< @brief: Scattering coefficient */ + double _sigmaS; /*!< @brief Scattering coefficient */ public: LineSource( Config* settings, Mesh* mesh ); ~LineSource(); - /*!< @brief: Exact analytical solution for the Line Source Test Case at - @param: x: x coordinate of exact solution + /*!< @brief Exact analytical solution for the Line Source Test Case at + @param x: x coordinate of exact solution y: y coordinate of exact solution t: time of the exact solution sigma_s: scattering cross section of the exact solution - @return: exact solution at x,y,t,scatteringXS + @return exact solution at x,y,t,scatteringXS */ double GetAnalyticalSolution( double x, double y, double t, double sigma_s ) override; private: - /*!< @brief: Helper Functions to compute the analytic solution for sigma != 0 + /*!< @brief Helper Functions to compute the analytic solution for sigma != 0 * (See publication: Garret,Hauck; Momentum Closures for Linear Kinetic Transport Equations) - @param: R = distance to origin - @param: t = time - @param: sigma = R/t + @param R = distance to origin + @param t = time + @param sigma = R/t */ double HelperIntRho_ptc( double R, double t ); double HelperRho_ptc( double R, double t ); diff --git a/code/include/problems/problembase.h b/code/include/problems/problembase.h index 300edfa..8ac2b5a 100644 --- a/code/include/problems/problembase.h +++ b/code/include/problems/problembase.h @@ -17,8 +17,8 @@ class ProblemBase Mesh* _mesh; EPICS* _physics; - std::vector _density; /*! @brief: vector with patient densities */ - std::vector _stoppingPower; /*! @brief: vector with stopping powers*/ + std::vector _density; /*!< @brief vector with patient densities */ + std::vector _stoppingPower; /*!< @brief vector with stopping powers*/ ProblemBase() = delete; @@ -87,12 +87,12 @@ class ProblemBase */ virtual VectorVector SetupIC() = 0; - /*! @brief: Exact analytical solution for the Line Source Test Case at - @param: x: x coordinate of exact solution + /*! @brief Exact analytical solution for the Line Source Test Case at + @param x: x coordinate of exact solution y: y coordinate of exact solution t: time of the exact solution scatteringXS: scattering cross section of the exact solution - @return: exact solution at x,y,t,scatteringXS + @return exact solution at x,y,t,scatteringXS */ // Default is set to 0. ~> if no analytical solution is available. double virtual GetAnalyticalSolution( double /*x*/, double /*y*/, double /*t*/, double /*scatteringXS*/ ) { return 0.0; } diff --git a/code/include/quadratures/qlookupquadrature.h b/code/include/quadratures/qlookupquadrature.h index fe6e50f..d924946 100644 --- a/code/include/quadratures/qlookupquadrature.h +++ b/code/include/quadratures/qlookupquadrature.h @@ -14,18 +14,18 @@ class QLookupQuadrature : public QuadratureBase inline std::vector getAvailOrders() const { return _availableOrders; } /*! @returns: Vector with avalable orders for level symmetric quadrature */ - void printAvailOrders() const; /*! @brief: prints available orders */ + void printAvailOrders() const; /*!< @brief prints available orders */ protected: - bool CheckOrder(); /*! @brief checks if given order is available for this quadrature rule. */ - void SetNq() override; /*! @brief: Assumes, that _order is available in lookup table */ - void SetPointsAndWeights() override; /*! @brief reads in n_points gridpoints and -weights from given filename. */ + bool CheckOrder(); /*!< @brief checks if given order is available for this quadrature rule. */ + void SetNq() override; /*!< @brief Assumes, that _order is available in lookup table */ + void SetPointsAndWeights() override; /*!< @brief reads in n_points gridpoints and -weights from given filename. */ - virtual void SetAvailOrders() = 0; /*! @brief Sets vector with avaialbe Orders and corresponding vector with Nq. */ + virtual void SetAvailOrders() = 0; /*!< @brief Sets vector with avaialbe Orders and corresponding vector with Nq. */ - virtual std::string GetLookupTable() = 0; /*! @brief returns lookuptable of _order. Assumes order is available */ + virtual std::string GetLookupTable() = 0; /*!< @brief returns lookuptable of _order. Assumes order is available */ - std::vector _availableOrders; /*! @brief: Vector with available orders for lookup table */ - std::vector _nqByOrder; /*! @brief: Vector with number of quadrature points of each listed order */ + std::vector _availableOrders; /*!< @brief Vector with available orders for lookup table */ + std::vector _nqByOrder; /*!< @brief Vector with number of quadrature points of each listed order */ }; #endif // QLOOKUPQUADRATURE_H diff --git a/code/include/quadratures/qproduct.h b/code/include/quadratures/qproduct.h index d18d1ba..0422b6e 100644 --- a/code/include/quadratures/qproduct.h +++ b/code/include/quadratures/qproduct.h @@ -1,5 +1,5 @@ /*! @file: qproduct.h - * @brief: Product quadrature implementation. Implementation is done accordingly to Kendall Atkinson 1981, Australian Matematical Society. + * @brief Product quadrature implementation. Implementation is done accordingly to Kendall Atkinson 1981, Australian Matematical Society. * @author: J. Kusch */ diff --git a/code/include/quadratures/quadraturebase.h b/code/include/quadratures/quadraturebase.h index 01e73fd..ee1e35b 100644 --- a/code/include/quadratures/quadraturebase.h +++ b/code/include/quadratures/quadraturebase.h @@ -1,5 +1,5 @@ /*! @file: quadraturebase.h - * @brief: Base class for all quadrature rules in KiT-RT + * @brief Base class for all quadrature rules in KiT-RT * @author: S. Schotthöfer */ @@ -14,19 +14,19 @@ class Config; class QuadratureBase { public: - /*! @brief: Constructor using settings class. This is the recommended constructor. - * @param: Config* settings: Settings class storing all important options. + /*! @brief Constructor using settings class. This is the recommended constructor. + * @param Config* settings: Settings class storing all important options. */ QuadratureBase( Config* settings ); - /*! @brief: Constructor using directly the order of the quadrature. Not applicable for GaussLegendre, that need additional options. + /*! @brief Constructor using directly the order of the quadrature. Not applicable for GaussLegendre, that need additional options. It sets member _settings = nulltpr.*/ QuadratureBase( unsigned order ); virtual ~QuadratureBase() {} // Aux functions - void PrintWeights(); /*! @brief prints: Weight vector */ - void PrintPoints(); /*! @brief prints: Point vectorVector */ - void PrintPointsAndWeights(); /*! @brief prints: Point vectorVector with corresponding weight vector */ + void PrintWeights(); /*!< @brief prints: Weight vector */ + void PrintPoints(); /*!< @brief prints: Point vectorVector */ + void PrintPointsAndWeights(); /*!< @brief prints: Point vectorVector with corresponding weight vector */ /*! @brief sums up all entries of the weight vector. * @returns sum of all weights */ @@ -50,13 +50,13 @@ class QuadratureBase // Quadrature Hub /*! @brief Creates a quadrature rule with a given name and a given order. - * @param: Config* settings: Settings to handle quadrature options + * @param Config* settings: Settings to handle quadrature options * @returns Quadrature* quadrature: returns pointer to instance of the given derived quadrature class */ static QuadratureBase* Create( Config* settings ); /*! @brief Creates a quadrature rule with a given name and a given order. - * @param: name: name of quadrature as enum - * @param: quadOrder: order of quadrature + * @param name: name of quadrature as enum + * @param quadOrder: order of quadrature * @returns Quadrature* quadrature: returns pointer to instance of the given derived quadrature class */ static QuadratureBase* Create( QUAD_NAME name, unsigned quadOrder ); @@ -76,9 +76,9 @@ class QuadratureBase protected: // Setter inline void SetOrder( unsigned order ) { _order = order; } /*! @brief sets: order of the quadrature */ - virtual void SetName() = 0; /*! @brief Sets: name of the quadrature */ - virtual void SetNq() = 0; /*! @brief sets: number of gridpoints of the quadrature */ - virtual void SetConnectivity() = 0; /*! @brief sets: Connectivity Adjacency Matrix as VektorVektor*/ + virtual void SetName() = 0; /*!< @brief Sets: name of the quadrature */ + virtual void SetNq() = 0; /*!< @brief sets: number of gridpoints of the quadrature */ + virtual void SetConnectivity() = 0; /*!< @brief sets: Connectivity Adjacency Matrix as VektorVektor*/ /*! @brief Computes the a vector (length: nq) of (coordinates of) gridpoints used for the quadrature rule. * Computes the a vector (length: nq) of weights for the gridpoints. The indices match the gridpoints VectorVector. @@ -86,14 +86,14 @@ class QuadratureBase virtual void SetPointsAndWeights() = 0; // Member variables - Config* _settings; /*! @brief pointer to settings class that manages the solver */ - std::string _name; /*! @brief name of the quadrature */ - unsigned _order; /*! @brief order of the quadrature */ - unsigned _nq; /*! @brief number of gridpoints of the quadrature */ - VectorVector _points; /*! @brief gridpoints of the quadrature */ - VectorVector _pointsSphere; /*! @brief (my,phi)gridpoints of the quadrature in spherical cordinates */ - Vector _weights; /*! @brief weights of the gridpoints of the quadrature */ - VectorVectorU _connectivity; /*! @brief connectivity of the gripoints of the quadrature */ + Config* _settings; /*!< @brief pointer to settings class that manages the solver */ + std::string _name; /*!< @brief name of the quadrature */ + unsigned _order; /*!< @brief order of the quadrature */ + unsigned _nq; /*!< @brief number of gridpoints of the quadrature */ + VectorVector _points; /*!< @brief gridpoints of the quadrature */ + VectorVector _pointsSphere; /*!< @brief (my,phi)gridpoints of the quadrature in spherical cordinates */ + Vector _weights; /*!< @brief weights of the gridpoints of the quadrature */ + VectorVectorU _connectivity; /*!< @brief connectivity of the gripoints of the quadrature */ }; #endif // QUADRATURE_H diff --git a/code/include/solvers/csdsnsolver.h b/code/include/solvers/csdsnsolver.h index a972ed4..dad3ff7 100644 --- a/code/include/solvers/csdsnsolver.h +++ b/code/include/solvers/csdsnsolver.h @@ -6,14 +6,14 @@ class CSDSNSolver : public SNSolver { private: - std::vector _dose; /*! @brief: TODO */ + std::vector _dose; /*!< @brief TODO */ // Physics acess - Vector _energies; /*! @brief: energy levels for CSD, lenght = _nEnergies */ - Vector _angle; /*! @brief: angles for SN */ + Vector _energies; /*!< @brief energy levels for CSD, lenght = _nEnergies */ + Vector _angle; /*!< @brief angles for SN */ - std::vector _sigmaSE; /*! @brief scattering cross section for all energies*/ - Vector _sigmaTE; /*! @brief total cross section for all energies*/ + std::vector _sigmaSE; /*!< @brief scattering cross section for all energies*/ + Vector _sigmaTE; /*!< @brief total cross section for all energies*/ public: /** diff --git a/code/include/solvers/csdsnsolverfp.h b/code/include/solvers/csdsnsolverfp.h index f1fd1ee..bd6531f 100644 --- a/code/include/solvers/csdsnsolverfp.h +++ b/code/include/solvers/csdsnsolverfp.h @@ -8,27 +8,27 @@ class Physics; class CSDSNSolverFP : public SNSolver { private: - std::vector _dose; /*! @brief: TODO */ + std::vector _dose; /*!< @brief TODO */ // Physics acess - Vector _energies; /*! @brief: energy levels for CSD, length = _nEnergies */ - Vector _angle; /*! @brief: angles for SN */ + Vector _energies; /*!< @brief energy levels for CSD, length = _nEnergies */ + Vector _angle; /*!< @brief angles for SN */ - std::vector _sigmaSE; /*! @brief scattering cross section for all energies*/ - Vector _sigmaTE; /*! @brief total cross section for all energies*/ + std::vector _sigmaSE; /*!< @brief scattering cross section for all energies*/ + Vector _sigmaTE; /*!< @brief total cross section for all energies*/ - Matrix _L; /*! @brief Laplace Beltrami Matrix */ - Matrix _IL; /*! @brief Laplace Beltrami Matrix */ + Matrix _L; /*!< @brief Laplace Beltrami Matrix */ + Matrix _IL; /*!< @brief Laplace Beltrami Matrix */ - double _alpha; /*! @brief Coefficient of GFP operators (see Olbrant 2010, eq. (8)*/ - double _beta; /*! @brief Coefficient of GFP operators (see Olbrant 2010, eq. (8)*/ + double _alpha; /*!< @brief Coefficient of GFP operators (see Olbrant 2010, eq. (8)*/ + double _beta; /*!< @brief Coefficient of GFP operators (see Olbrant 2010, eq. (8)*/ - Matrix _xi; /*! @brief matrix of transport coefficients */ + Matrix _xi; /*!< @brief matrix of transport coefficients */ - bool _RT; /*! @brief radiotherapy application (on/off), if true use crosssections + stopping powers from database */ + bool _RT; /*!< @brief radiotherapy application (on/off), if true use crosssections + stopping powers from database */ - double _energyMin; /*! @brief minimal energy in energy grid*/ - double _energyMax; /*! @brief maximal energy in energy grid*/ + double _energyMin; /*!< @brief minimal energy in energy grid*/ + double _energyMax; /*!< @brief maximal energy in energy grid*/ public: /** diff --git a/code/include/solvers/csdsnsolvernotrafo.h b/code/include/solvers/csdsnsolvernotrafo.h index a2e8f0e..e02a356 100644 --- a/code/include/solvers/csdsnsolvernotrafo.h +++ b/code/include/solvers/csdsnsolvernotrafo.h @@ -8,14 +8,14 @@ class Physics; class CSDSNSolverNoTrafo : public SNSolver { private: - std::vector _dose; /*! @brief: TODO */ + std::vector _dose; /*!< @brief TODO */ // Physics acess - Vector _energies; /*! @brief: energy levels for CSD, lenght = _nEnergies */ - Vector _angle; /*! @brief: angles for SN */ + Vector _energies; /*!< @brief energy levels for CSD, lenght = _nEnergies */ + Vector _angle; /*!< @brief angles for SN */ - std::vector _sigmaSE; /*! @brief scattering cross section for all energies*/ - Vector _sigmaTE; /*! @brief total cross section for all energies*/ + std::vector _sigmaSE; /*!< @brief scattering cross section for all energies*/ + Vector _sigmaTE; /*!< @brief total cross section for all energies*/ public: /** diff --git a/code/include/solvers/csdsolvertrafofp.h b/code/include/solvers/csdsolvertrafofp.h index 1e4e818..0b94939 100644 --- a/code/include/solvers/csdsolvertrafofp.h +++ b/code/include/solvers/csdsolvertrafofp.h @@ -8,39 +8,39 @@ class Physics; class CSDSolverTrafoFP : public SNSolver { private: - std::vector _dose; /*! @brief: TODO */ + std::vector _dose; /*!< @brief TODO */ // Physics acess - Vector _energies; /*! @brief: energy levels for CSD, lenght = _nEnergies */ - Vector _angle; /*! @brief: angles for SN */ + Vector _energies; /*!< @brief energy levels for CSD, lenght = _nEnergies */ + Vector _angle; /*!< @brief angles for SN */ - std::vector _sigmaSE; /*! @brief scattering cross section for all energies*/ - Vector _sigmaTE; /*! @brief total cross section for all energies*/ + std::vector _sigmaSE; /*!< @brief scattering cross section for all energies*/ + Vector _sigmaTE; /*!< @brief total cross section for all energies*/ - Matrix _L; /*! @brief Laplace Beltrami Matrix */ - Matrix _IL; /*! @brief Laplace Beltrami Matrix */ + Matrix _L; /*!< @brief Laplace Beltrami Matrix */ + Matrix _IL; /*!< @brief Laplace Beltrami Matrix */ - double _alpha; /*! @brief Coefficient of GFP operators (see Olbrant 2010, Appendix B)*/ - double _alpha2; /*! @brief Coefficient of GFP operators (see Olbrant 2010, Appendix B)*/ - double _beta; /*! @brief Coefficient of GFP operators (see Olbrant 2010, Appendix B)*/ + double _alpha; /*!< @brief Coefficient of GFP operators (see Olbrant 2010, Appendix B)*/ + double _alpha2; /*!< @brief Coefficient of GFP operators (see Olbrant 2010, Appendix B)*/ + double _beta; /*!< @brief Coefficient of GFP operators (see Olbrant 2010, Appendix B)*/ - Matrix _xi; /*! @brief matrix of transport coefficients */ + Matrix _xi; /*!< @brief matrix of transport coefficients */ Vector _xi1; Vector _xi2; - unsigned _FPMethod; /*! @brief Encodes different ways of computing coefficients alpha, alpha2 & beta, _FPMethod == 1, 2 ,3 stand for methods with + unsigned _FPMethod; /*!< @brief Encodes different ways of computing coefficients alpha, alpha2 & beta, _FPMethod == 1, 2 ,3 stand for methods with increasing accuracy (see Olbrant 2010, Appendix B)*/ - bool _RT; /*! @brief radiotherapy application (on/off), if true use crosssections + stopping powers from database */ + bool _RT; /*!< @brief radiotherapy application (on/off), if true use crosssections + stopping powers from database */ - double _energyMin; /*! @brief minimal energy in energy grid*/ - double _energyMax; /*! @brief maximal energy in energy grid*/ + double _energyMin; /*!< @brief minimal energy in energy grid*/ + double _energyMax; /*!< @brief maximal energy in energy grid*/ void GenerateEnergyGrid( bool refinement ); // Helper variables - Vector _energiesOrig; /*! @brief: original energy levels for CSD, lenght = _nEnergies */ - Matrix _identity; /*! @brif: identity matrix for FP scattering. Dim (_nq,_nq)*/ + Vector _energiesOrig; /*!< @brief original energy levels for CSD, lenght = _nEnergies */ + Matrix _identity; /*!< @brif: identity matrix for FP scattering. Dim (_nq,_nq)*/ public: /** diff --git a/code/include/solvers/csdsolvertrafofp2d.h b/code/include/solvers/csdsolvertrafofp2d.h index 62526a9..e5a6d85 100644 --- a/code/include/solvers/csdsolvertrafofp2d.h +++ b/code/include/solvers/csdsolvertrafofp2d.h @@ -8,17 +8,17 @@ class Physics; class CSDSolverTrafoFP2D : public SNSolver { private: - std::vector _dose; /*! @brief: TODO */ + std::vector _dose; /*!< @brief TODO */ // Physics acess - Vector _energies; /*! @brief: energy levels for CSD, lenght = _nEnergies */ - Vector _angle; /*! @brief: angles for SN */ + Vector _energies; /*!< @brief energy levels for CSD, lenght = _nEnergies */ + Vector _angle; /*!< @brief angles for SN */ - std::vector _sigmaSE; /*! @brief scattering cross section for all energies*/ - Vector _sigmaTE; /*! @brief total cross section for all energies*/ + std::vector _sigmaSE; /*!< @brief scattering cross section for all energies*/ + Vector _sigmaTE; /*!< @brief total cross section for all energies*/ - Matrix _L; /*! @brief Laplace Beltrami Matrix */ - Matrix _IL; /*! @brief Laplace Beltrami Matrix */ + Matrix _L; /*!< @brief Laplace Beltrami Matrix */ + Matrix _IL; /*!< @brief Laplace Beltrami Matrix */ VectorVector _quadPoints; VectorVector _quadPointsSphere; @@ -44,9 +44,9 @@ class CSDSolverTrafoFP2D : public SNSolver double _energyMax; // Helper variables - Vector _energiesOrig; /*! @brief: original energy levels for CSD, lenght = _nEnergies */ - Matrix _identity; /*! @brif: identity matrix for FP scattering. Dim (_nq,_nq)*/ - double _densityMin; /*! @brief: Minimal density of _density vector */ + Vector _energiesOrig; /*!< @brief original energy levels for CSD, lenght = _nEnergies */ + Matrix _identity; /*!< @brif: identity matrix for FP scattering. Dim (_nq,_nq)*/ + double _densityMin; /*!< @brief Minimal density of _density vector */ void GenerateEnergyGrid( bool refinement ); diff --git a/code/include/solvers/csdsolvertrafofpsh2d.h b/code/include/solvers/csdsolvertrafofpsh2d.h index 127d070..ddb3df6 100644 --- a/code/include/solvers/csdsolvertrafofpsh2d.h +++ b/code/include/solvers/csdsolvertrafofpsh2d.h @@ -19,17 +19,17 @@ class Physics; class CSDSolverTrafoFPSH2D : public SNSolver { private: - std::vector _dose; /*! @brief: TODO */ + std::vector _dose; /*!< @brief TODO */ // Physics acess - Vector _energies; /*! @brief: energy levels for CSD, lenght = _nEnergies */ - Vector _angle; /*! @brief: angles for SN */ + Vector _energies; /*!< @brief energy levels for CSD, lenght = _nEnergies */ + Vector _angle; /*!< @brief angles for SN */ - std::vector _sigmaSE; /*! @brief scattering cross section for all energies*/ - Vector _sigmaTE; /*! @brief total cross section for all energies*/ + std::vector _sigmaSE; /*!< @brief scattering cross section for all energies*/ + Vector _sigmaTE; /*!< @brief total cross section for all energies*/ - Matrix _L; /*! @brief Laplace Beltrami Matrix */ - Matrix _IL; /*! @brief Laplace Beltrami Matrix */ + Matrix _L; /*!< @brief Laplace Beltrami Matrix */ + Matrix _IL; /*!< @brief Laplace Beltrami Matrix */ Matrix _O; Matrix _S; @@ -59,9 +59,9 @@ class CSDSolverTrafoFPSH2D : public SNSolver double _energyMax; // Helper variables - Vector _energiesOrig; /*! @brief: original energy levels for CSD, lenght = _nEnergies */ - Matrix _identity; /*! @brif: identity matrix for FP scattering. Dim (_nq,_nq)*/ - double _densityMin; /*! @brief: Minimal density of _density vector */ + Vector _energiesOrig; /*!< @brief original energy levels for CSD, lenght = _nEnergies */ + Matrix _identity; /*!< @brif: identity matrix for FP scattering. Dim (_nq,_nq)*/ + double _densityMin; /*!< @brief Minimal density of _density vector */ public: /** diff --git a/code/include/solvers/mnsolver.h b/code/include/solvers/mnsolver.h index 77230f1..6617200 100644 --- a/code/include/solvers/mnsolver.h +++ b/code/include/solvers/mnsolver.h @@ -12,7 +12,7 @@ class MNSolver : public SolverBase public: /** * @brief MNSolver constructor - * @param settings : Config class that stores all needed information + * @param settings Config class that stores all needed information */ MNSolver( Config* settings ); @@ -21,29 +21,29 @@ class MNSolver : public SolverBase private: // --- Private member variables --- - unsigned _nSystem; /*! @brief Total number of equations in the system */ - unsigned short _polyDegreeBasis; /*! @brief Max polynomial degree of the basis */ + unsigned _nSystem; /*!< @brief Total number of equations in the system */ + unsigned short _polyDegreeBasis; /*!< @brief Max polynomial degree of the basis */ // Moment basis - SphericalBase* _basis; /*! @brief Class to compute and store current spherical harmonics basis */ - VectorVector _moments; /*! @brief Moment Vector pre-computed at each quadrature point: dim= _nq x _nTotalEntries */ + SphericalBase* _basis; /*!< @brief Class to compute and store current spherical harmonics basis */ + VectorVector _moments; /*!< @brief Moment Vector pre-computed at each quadrature point: dim= _nq x _nTotalEntries */ // Scattering - Vector _scatterMatDiag; /*! @brief Diagonal of the scattering matrix (its a diagonal matrix by construction) */ + Vector _scatterMatDiag; /*!< @brief Diagonal of the scattering matrix (its a diagonal matrix by construction) */ // Quadrature related members - VectorVector _quadPoints; /*! @brief quadrature points, dim(_quadPoints) = (_nq,spatialDim) */ - Vector _weights; /*! @brief quadrature weights, dim(_weights) = (_nq) */ - VectorVector _quadPointsSphere; /*! @brief (my,phi), dim(_quadPoints) = (_nq,2) */ + VectorVector _quadPoints; /*!< @brief quadrature points, dim(_quadPoints) = (_nq,spatialDim) */ + Vector _weights; /*!< @brief quadrature weights, dim(_weights) = (_nq) */ + VectorVector _quadPointsSphere; /*!< @brief (my,phi), dim(_quadPoints) = (_nq,2) */ // Entropy Optimization related members - EntropyBase* _entropy; /*! @brief Class to handle entropy functionals */ - VectorVector _alpha; /*! @brief Lagrange Multipliers for Minimal Entropy problem for each gridCell - Layout: _nCells x _nTotalEntries*/ - OptimizerBase* _optimizer; /*! @brief Class to solve minimal entropy problem */ + EntropyBase* _entropy; /*!< @brief Class to handle entropy functionals */ + VectorVector _alpha; /*!< @brief Lagrange Multipliers for Minimal Entropy problem for each gridCell + Layout: _nCells x _nTotalEntries*/ + OptimizerBase* _optimizer; /*!< @brief Class to solve minimal entropy problem */ - VectorVector _solDx; /*! @brief temporary storage of x-derivatives of alpha */ - VectorVector _solDy; /*! @brief temporary storage of y-derivatives of alpha */ + VectorVector _solDx; /*!< @brief temporary storage of x-derivatives of alpha */ + VectorVector _solDy; /*!< @brief temporary storage of y-derivatives of alpha */ // ---- Private Member functions --- diff --git a/code/include/solvers/pnsolver.h b/code/include/solvers/pnsolver.h index 1165196..0312202 100644 --- a/code/include/solvers/pnsolver.h +++ b/code/include/solvers/pnsolver.h @@ -109,8 +109,8 @@ class PNSolver : public SolverBase */ double FTilde( int l, int k ) const; - /*! @brief: mathematical + index functions. Helper functions for setting up system matrix. - * @param: k: arbitrary integer + /*! @brief mathematical + index functions. Helper functions for setting up system matrix. + * @param k: arbitrary integer */ int Sgn( int k ) const; /*! @brief mathematical + index functions. Helper functions for setting up system matrix. @@ -143,7 +143,7 @@ class PNSolver : public SolverBase /*! @brief Computes Legedre polinomial of oder l at point x */ double LegendrePoly( double x, int l ); - /*! @brief: Sets Entries of FluxMatrices to zero, if they are below double precision, + /*! @brief Sets Entries of FluxMatrices to zero, if they are below double precision, * to prevent floating point inaccuracies later in the solver */ void CleanFluxMatrices(); diff --git a/code/include/solvers/snsolver.h b/code/include/solvers/snsolver.h index 1e8be83..853142d 100644 --- a/code/include/solvers/snsolver.h +++ b/code/include/solvers/snsolver.h @@ -6,12 +6,12 @@ class SNSolver : public SolverBase { protected: - Matrix _scatteringKernel; /*! @brief scattering kernel for the quadrature */ + Matrix _scatteringKernel; /*!< @brief scattering kernel for the quadrature */ // quadrature related numbers - VectorVector _quadPoints; /*! @brief quadrature points, dim(_quadPoints) = (_nq,spatialDim) */ - Vector _weights; /*! @brief quadrature weights, dim(_weights) = (_nq) */ + VectorVector _quadPoints; /*!< @brief quadrature points, dim(_quadPoints) = (_nq,spatialDim) */ + Vector _weights; /*!< @brief quadrature weights, dim(_weights) = (_nq) */ public: /*! @brief SNSolver constructor diff --git a/code/include/solvers/solverbase.h b/code/include/solvers/solverbase.h index c7b16ff..ac1a76e 100644 --- a/code/include/solvers/solverbase.h +++ b/code/include/solvers/solverbase.h @@ -101,7 +101,7 @@ class SolverBase /*! @brief ComputeTimeStep calculates the maximal stable time step using the cfl number @param cfl Courant-Friedrichs-Levy condition number */ double ComputeTimeStep( double cfl ) const; - /*! @brief: Computes the flux of the solution to check conservation properties */ + /*! @brief Computes the flux of the solution to check conservation properties */ virtual void ComputeRadFlux() = 0; // IO @@ -114,7 +114,7 @@ class SolverBase option VOLUME_OUTPUT_FREQUENCY. Always prints last iteration without iteration affix. @param idx_iter current (pseudo) time iteration */ void PrintVolumeOutput( int idx_iter ) const; - /*! @brief: Initialized the output fields and their Names for the screenoutput */ + /*! @brief Initialized the output fields and their Names for the screenoutput */ void PrepareScreenOutput(); /*! @brief Function that writes screen and history output fields diff --git a/code/include/toolboxes/datagenerator1D.h b/code/include/toolboxes/datagenerator1D.h index 241147d..9acfae0 100644 --- a/code/include/toolboxes/datagenerator1D.h +++ b/code/include/toolboxes/datagenerator1D.h @@ -12,21 +12,21 @@ class DataGenerator1D : public DataGeneratorBase { public: - /*! @brief: Class constructor. Generates training data for neural network approaches using + /*! @brief Class constructor. Generates training data for neural network approaches using * spherical harmonics and an entropy functional and the quadrature specified by * the options file. - * @param: setSize: number of elements in training set + * @param setSize: number of elements in training set * basisSize: length of spherical harmonics basis (maybe redundant)*/ DataGenerator1D( Config* settings ); ~DataGenerator1D(); private: // Main methods - void SampleSolutionU() override; /*! @brief: Samples solution vectors u */ + void SampleSolutionU() override; /*!< @brief Samples solution vectors u */ // Helper functions - void ComputeMoments() override; /*! @brief: Pre-Compute Moments at all quadrature points. */ - void ComputeSetSize() override; /*! @brief: Computes the size of the training set, depending on the chosen settings.*/ + void ComputeMoments() override; /*!< @brief Pre-Compute Moments at all quadrature points. */ + void ComputeSetSize() override; /*!< @brief Computes the size of the training set, depending on the chosen settings.*/ void CheckRealizability() override; // Debugging helper }; #endif // DATAGENERATOR1D_H diff --git a/code/include/toolboxes/datagenerator3D.h b/code/include/toolboxes/datagenerator3D.h index 7934000..857c6d9 100644 --- a/code/include/toolboxes/datagenerator3D.h +++ b/code/include/toolboxes/datagenerator3D.h @@ -12,21 +12,21 @@ class DataGenerator3D : public DataGeneratorBase { public: - /*! @brief: Class constructor. Generates training data for neural network approaches using + /*! @brief Class constructor. Generates training data for neural network approaches using * spherical harmonics and an entropy functional and the quadrature specified by * the options file. - * @param: setSize: number of elements in training set + * @param setSize: number of elements in training set * basisSize: length of spherical harmonics basis (maybe redundant)*/ DataGenerator3D( Config* settings ); ~DataGenerator3D(); private: // Main methods - void SampleSolutionU() override; /*! @brief: Samples solution vectors u */ + void SampleSolutionU() override; /*!< @brief Samples solution vectors u */ // Helper functions - void ComputeMoments() override; /*! @brief: Pre-Compute Moments at all quadrature points. */ - void ComputeSetSize() override; /*! @brief: Computes the size of the training set, depending on the chosen settings.*/ + void ComputeMoments() override; /*!< @brief Pre-Compute Moments at all quadrature points. */ + void ComputeSetSize() override; /*!< @brief Computes the size of the training set, depending on the chosen settings.*/ void CheckRealizability() override; // Debugging helper }; #endif // DATAGENERATOR3D_H diff --git a/code/include/toolboxes/datageneratorbase.h b/code/include/toolboxes/datageneratorbase.h index 19de06c..d1f1e6f 100644 --- a/code/include/toolboxes/datageneratorbase.h +++ b/code/include/toolboxes/datageneratorbase.h @@ -19,67 +19,67 @@ class EntropyBase; class DataGeneratorBase { public: - /*! @brief: Class constructor. Generates training data for neural network approaches using + /*! @brief Class constructor. Generates training data for neural network approaches using * spherical harmonics and an entropy functional and the quadrature specified by * the options file. - * @param: setSize: number of elements in training set + * @param setSize: number of elements in training set * basisSize: length of spherical harmonics basis (maybe redundant)*/ DataGeneratorBase( Config* settings ); ~DataGeneratorBase(); - /*! @brief: Create a datagenerator (1D or 3D) - * @param: Pointer to the config file + /*! @brief Create a datagenerator (1D or 3D) + * @param Pointer to the config file * @returns: Pointer to the createt basis class */ static DataGeneratorBase* Create( Config* settings ); - /*! @brief: computes the training data set. + /*! @brief computes the training data set. * Realizable set is sampled uniformly. * Prototype: 1D, u\in[0,100] */ void ComputeTrainingData(); - inline VectorVector GetuSol() { return _uSol; } /*! @brief: Get the computed solution vector uSol */ - inline VectorVector GetAlpha() { return _alpha; } /*! @brief: Get the computed vector alpha */ - inline std::vector GethEntropy() { return _hEntropy; } /*! @brief: Get the computed entropy value h */ + inline VectorVector GetuSol() { return _uSol; } /*! @brief Get the computed solution vector uSol */ + inline VectorVector GetAlpha() { return _alpha; } /*! @brief Get the computed vector alpha */ + inline std::vector GethEntropy() { return _hEntropy; } /*! @brief Get the computed entropy value h */ protected: - Config* _settings; /*! @brief config class for global information */ + Config* _settings; /*!< @brief config class for global information */ - VectorVector _uSol; /*! @brief: vector with moments. Size: (setSize,basisSize)*/ - VectorVector _alpha; /*! @brief: vector with Lagrange multipliers. Size: (setSize,basisSize)*/ - std::vector _hEntropy; /*! @brief: vector with entropy values. Size: (setSize) */ + VectorVector _uSol; /*!< @brief vector with moments. Size: (setSize,basisSize)*/ + VectorVector _alpha; /*!< @brief vector with Lagrange multipliers. Size: (setSize,basisSize)*/ + std::vector _hEntropy; /*!< @brief vector with entropy values. Size: (setSize) */ - unsigned long _setSize; /*! @brief: Size of the whole training Set */ + unsigned long _setSize; /*!< @brief Size of the whole training Set */ unsigned long - _gridSize; /*! @brief: Size of the grid discretizing moment U0 for higher order sampling (has different uses for different samplers)*/ + _gridSize; /*!< @brief Size of the grid discretizing moment U0 for higher order sampling (has different uses for different samplers)*/ - unsigned short _LMaxDegree; /*! @brief: Max Order of Spherical Harmonics */ - unsigned _nTotalEntries; /*! @brief: Total number of equations in the system */ + unsigned short _LMaxDegree; /*!< @brief Max Order of Spherical Harmonics */ + unsigned _nTotalEntries; /*!< @brief Total number of equations in the system */ - QuadratureBase* _quadrature; /*! @brief quadrature to create members below */ - unsigned _nq; /*! @brief number of quadrature points */ - VectorVector _quadPoints; /*! @brief quadrature points, dim(_quadPoints) = (_nq,spatialDim) */ - Vector _weights; /*! @brief quadrature weights, dim(_weights) = (_nq) */ - VectorVector _quadPointsSphere; /*! @brief (my,phi), dim(_quadPoints) = (_nq,2) */ + QuadratureBase* _quadrature; /*!< @brief quadrature to create members below */ + unsigned _nq; /*!< @brief number of quadrature points */ + VectorVector _quadPoints; /*!< @brief quadrature points, dim(_quadPoints) = (_nq,spatialDim) */ + Vector _weights; /*!< @brief quadrature weights, dim(_weights) = (_nq) */ + VectorVector _quadPointsSphere; /*!< @brief (my,phi), dim(_quadPoints) = (_nq,2) */ - SphericalBase* _basis; /*! @brief: Class to compute and store current spherical harmonics basis */ - VectorVector _moments; /*! @brief: Moment Vector pre-computed at each quadrature point: dim= _nq x _nTotalEntries */ + SphericalBase* _basis; /*!< @brief Class to compute and store current spherical harmonics basis */ + VectorVector _moments; /*!< @brief Moment Vector pre-computed at each quadrature point: dim= _nq x _nTotalEntries */ - NewtonOptimizer* _optimizer; /*! @brief: Class to solve minimal entropy problem */ - EntropyBase* _entropy; /*! @brief: Class to handle entropy functional evaluations */ + NewtonOptimizer* _optimizer; /*!< @brief Class to solve minimal entropy problem */ + EntropyBase* _entropy; /*!< @brief Class to handle entropy functional evaluations */ // Main methods - virtual void SampleSolutionU() = 0; /*! @brief: Samples solution vectors u */ - void ComputeEntropyH_dual(); /*! @brief: Compute the entropy functional at (u,alpha) in dual formulation */ - void ComputeEntropyH_primal(); /*! @brief: Compute the entropy functional at (u,alpha) in primal formulation */ - void ComputeRealizableSolution(); /*! @brief: make u the realizable moment to alpha, since Newton has roundoff errors. */ + virtual void SampleSolutionU() = 0; /*!< @brief Samples solution vectors u */ + void ComputeEntropyH_dual(); /*!< @brief Compute the entropy functional at (u,alpha) in dual formulation */ + void ComputeEntropyH_primal(); /*!< @brief Compute the entropy functional at (u,alpha) in primal formulation */ + void ComputeRealizableSolution(); /*!< @brief make u the realizable moment to alpha, since Newton has roundoff errors. */ // IO routines - void PrintTrainingData(); /*! @brief : Print computed training data to csv file and screen */ - void PrintLoadScreen(); /*! @brief: Print screen IO*/ + void PrintTrainingData(); /*!< @brief : Print computed training data to csv file and screen */ + void PrintLoadScreen(); /*!< @brief Print screen IO*/ // Helper functions - virtual void ComputeMoments() = 0; /*! @brief: Pre-Compute Moments at all quadrature points. */ + virtual void ComputeMoments() = 0; /*!< @brief Pre-Compute Moments at all quadrature points. */ virtual void CheckRealizability() = 0; // Debugging helper - virtual void ComputeSetSize() = 0; /*! @brief: Computes the size of the training set, depending on the chosen settings.*/ + virtual void ComputeSetSize() = 0; /*!< @brief Computes the size of the training set, depending on the chosen settings.*/ }; #endif // DATAGENERATOR_H diff --git a/code/include/toolboxes/reconstructor.h b/code/include/toolboxes/reconstructor.h index 9ad2a8a..cb74b94 100644 --- a/code/include/toolboxes/reconstructor.h +++ b/code/include/toolboxes/reconstructor.h @@ -1,6 +1,6 @@ /*! * @file: reconstructor.h - * @brief: Class to create second order (in space) schemes for the advection solver. + * @brief Class to create second order (in space) schemes for the advection solver. * This class is currently unused. But in the future, the second order capabilities of the code * may be stored here. * @author: T. Xiao diff --git a/code/include/toolboxes/sphericalbase.h b/code/include/toolboxes/sphericalbase.h index acd54d3..760334e 100644 --- a/code/include/toolboxes/sphericalbase.h +++ b/code/include/toolboxes/sphericalbase.h @@ -17,8 +17,8 @@ class SphericalBase SphericalBase() {} virtual ~SphericalBase() {} - /*! @brief: Create a set of basis functions on the unit sphere defined in settings - * @param: Pointer to the config file + /*! @brief Create a set of basis functions on the unit sphere defined in settings + * @param Pointer to the config file * @returns: Pointer to the createt basis class */ static SphericalBase* Create( Config* settings ); @@ -38,17 +38,17 @@ class SphericalBase /*! @brief : Return size of complete Basisvector */ virtual unsigned GetBasisSize() = 0; - /*! @brief: Return number of basis functions with degree equals to currDegree - * @param: currDegree must be smaller equals _LMaxDegree */ + /*! @brief Return number of basis functions with degree equals to currDegree + * @param currDegree must be smaller equals _LMaxDegree */ virtual unsigned GetCurrDegreeSize( unsigned currDegree ) = 0; - /*! @brief: Computes global index of basis vector depending on order k and degree l - * @param: l_degree = degree of polynomials l = 0,1,2,3,... - * @param: k_order = order of element of degree l. !ATTENTION. Requirements are different for monomials and harmonics! */ + /*! @brief Computes global index of basis vector depending on order k and degree l + * @param l_degree = degree of polynomials l = 0,1,2,3,... + * @param k_order = order of element of degree l. !ATTENTION. Requirements are different for monomials and harmonics! */ virtual unsigned GetGlobalIndexBasis( int l_degree, int k_order ) = 0; protected: - /*! @brief: maximal (polynomial) degree of the spherical basis (this is "L" in the comments)*/ + /*! @brief maximal (polynomial) degree of the spherical basis (this is "L" in the comments)*/ unsigned _LMaxDegree; }; diff --git a/code/include/toolboxes/sphericalharmonics.h b/code/include/toolboxes/sphericalharmonics.h index 9c4dc2d..f6f9c91 100644 --- a/code/include/toolboxes/sphericalharmonics.h +++ b/code/include/toolboxes/sphericalharmonics.h @@ -46,11 +46,11 @@ class SphericalHarmonics : public SphericalBase */ std::vector GetAssLegendrePoly( const double my ); - /*! @brief: Returns length of the basis, i.e. number of elements of the basis */ + /*! @brief Returns length of the basis, i.e. number of elements of the basis */ unsigned GetBasisSize() override; - /*! @brief: Return number of basis functions with degree equals to currDegree - * @param: currDegreeL = degree of polynomials that are counted */ + /*! @brief Return number of basis functions with degree equals to currDegree + * @param currDegreeL = degree of polynomials that are counted */ unsigned GetCurrDegreeSize( unsigned currDegree ) override; /*! @brief : helper function to get the global index for given k and l of @@ -60,10 +60,10 @@ class SphericalHarmonics : public SphericalBase unsigned GetGlobalIndexBasis( int l_degree, int k_order ) override; private: - /*! @brief: maximal degree of the spherical harmonics basis (this is "L" in the comments)*/ + /*! @brief maximal degree of the spherical harmonics basis (this is "L" in the comments)*/ unsigned _LMaxDegree; - /*! @brief: coefficients for the computations of the basis + /*! @brief coefficients for the computations of the basis * length of _aParam, _bParam : L + (L*(L+1))/2 */ std::vector _aParam; @@ -75,7 +75,7 @@ class SphericalHarmonics : public SphericalBase */ std::vector _assLegendreP; - /*! @brief: spherical harmonic basis functions of + /*! @brief spherical harmonic basis functions of * degree 0 <= l <= L and order -l <= k <= l * length : N = L² +2L */ @@ -98,9 +98,9 @@ class SphericalHarmonics : public SphericalBase */ void ComputeAssLegendrePoly( const double my ); - /*! @brief: Computes the spherical harmonics basis function up to degree _LmaxDegree at + /*! @brief Computes the spherical harmonics basis function up to degree _LmaxDegree at * polar coordinates (theta, psi) and stores the result in _YBasis; - * @param: spherical coordinate phi + * @param spherical coordinate phi */ void ComputeYBasis( const double phi ); }; diff --git a/code/include/toolboxes/sphericalmonomials.h b/code/include/toolboxes/sphericalmonomials.h index 4df71ba..84414a3 100644 --- a/code/include/toolboxes/sphericalmonomials.h +++ b/code/include/toolboxes/sphericalmonomials.h @@ -42,56 +42,56 @@ class SphericalMonomials : public SphericalBase */ Vector ComputeSphericalBasis( double x, double y, double z ) override; - /*! @brief: Computes the length of the basis vector for a given max degree and + /*! @brief Computes the length of the basis vector for a given max degree and * spatial dimension dim. len of a single oder: (degree + _spatialDim -1) over (degree) - * @return: lenght of whole basis */ + * @return lenght of whole basis */ unsigned GetBasisSize() override; - /*! @brief: Computes the amount of lin. independent monomials of degree currDegreeL and + /*! @brief Computes the amount of lin. independent monomials of degree currDegreeL and * spatial dimension dim. len of a single oder: (currDegreeL + _spatialDim -1) over (currDegreeL) - * @param: currDegreeL = degree of polynomials that are counted - * @return: lenght of a single dimension */ + * @param currDegreeL = degree of polynomials that are counted + * @return lenght of a single dimension */ unsigned GetCurrDegreeSize( unsigned currDegreeL ) override; - /*! @brief: Computes global index of basis vector depending on order k and degree l - * @param: l = degree of polynomials l = 0,1,2,3,... - * @param: k = order of element of degree l. 0 <=k <=GetCurrDegreeSize(l) */ + /*! @brief Computes global index of basis vector depending on order k and degree l + * @param l = degree of polynomials l = 0,1,2,3,... + * @param k = order of element of degree l. 0 <=k <=GetCurrDegreeSize(l) */ unsigned GetGlobalIndexBasis( int l_degree, int k_order ) override; private: - /*! @brief: Spatial dimension of the unit sphere (1,2,3) */ + /*! @brief Spatial dimension of the unit sphere (1,2,3) */ unsigned _spatialDim; - /*! @brief: spherical monomial basis function vector of + /*! @brief spherical monomial basis function vector of * degree 0 <= l <= L * length : COmputed with ComputeBasisSize */ Vector _YBasis; - /*! @brief: Function to compute factorial of n (n!) in recursive manner */ + /*! @brief Function to compute factorial of n (n!) in recursive manner */ unsigned Factorial( unsigned n ); - /*! @brief: Function to compute first component of spherical unit vector + /*! @brief Function to compute first component of spherical unit vector * Omega_x = sqrt(1-my*my)*cos(phi) - * @return: first component of spherical unit vector */ + * @return first component of spherical unit vector */ double Omega_x( double my, double phi ); - /*! @brief: Function to compute first component of spherical unit vector + /*! @brief Function to compute first component of spherical unit vector * Omega_x = sqrt(1-my*my)*sin(phi) - * @return: first component of spherical unit vector */ + * @return first component of spherical unit vector */ double Omega_y( double my, double phi ); - /*! @brief: Function to compute first component of spherical unit vector + /*! @brief Function to compute first component of spherical unit vector * Omega_z = my - * @return: first component of spherical unit vector */ + * @return first component of spherical unit vector */ double Omega_z( double my ); - /*! @brief: Helper Function to compute basis^exponent. */ + /*! @brief Helper Function to compute basis^exponent. */ double Power( double basis, unsigned exponent ); - /*! @brief: Helper to compute the basis in 1D, 2D or 3D, depending on choice of _spatialDim */ - Vector ComputeSphericalBasis1D( double my ); /*! @brief: Only Z achsis of the 3D case */ - Vector ComputeSphericalBasis2D( double my, double phi ); /*! @brief: Only X and Y achsis of the 3D case */ + /*! @brief Helper to compute the basis in 1D, 2D or 3D, depending on choice of _spatialDim */ + Vector ComputeSphericalBasis1D( double my ); /*!< @brief Only Z achsis of the 3D case */ + Vector ComputeSphericalBasis2D( double my, double phi ); /*!< @brief Only X and Y achsis of the 3D case */ Vector ComputeSphericalBasis3D( double my, double phi ); }; #endif // SPHERICALMONOMIALS_H diff --git a/code/src/common/config.cpp b/code/src/common/config.cpp index 8f3760a..7fe7c69 100644 --- a/code/src/common/config.cpp +++ b/code/src/common/config.cpp @@ -262,7 +262,7 @@ void Config::SetConfigOptions() { AddDoubleOption( "SCATTER_COEFF", _sigmaS, 0.0 ); // CSD related options - /*! @brief: MAX_ENERGY_CSD \n DESCRIPTION: Sets maximum energy for the CSD simulation.\n DEFAULT \ingroup Config */ + /*! @brief MAX_ENERGY_CSD \n DESCRIPTION: Sets maximum energy for the CSD simulation.\n DEFAULT \ingroup Config */ AddDoubleOption( "MAX_ENERGY_CSD", _maxEnergyCSD, 5.0 ); // Entropy related options diff --git a/code/src/main.cpp b/code/src/main.cpp index 1142342..757d40b 100644 --- a/code/src/main.cpp +++ b/code/src/main.cpp @@ -1,5 +1,5 @@ /*! @file: main.cpp - * @brief: Main method to call the KiT-RT solver suite + * @brief Main method to call the KiT-RT solver suite * @author: J. Kusch, S. Schotthöfer, P. Stammer, J. Wolters, T. Xiao * @version: 0.1 */ diff --git a/code/src/solvers/snsolver.cpp b/code/src/solvers/snsolver.cpp index d24ec13..a7cdf5e 100644 --- a/code/src/solvers/snsolver.cpp +++ b/code/src/solvers/snsolver.cpp @@ -27,7 +27,7 @@ void SNSolver::IterPreprocessing( unsigned /*idx_iter*/ ) { // Nothing to do for SNSolver } -void SNSolver::IterPostprocessing( unsigned idx_pseudotime ) { +void SNSolver::IterPostprocessing( unsigned /*idx_iter*/ ) { // --- Update Solution --- _sol = _solNew; diff --git a/doc/common/config.rst b/doc/common/config.rst index e0a517d..0697106 100644 --- a/doc/common/config.rst +++ b/doc/common/config.rst @@ -3,3 +3,5 @@ Config .. doxygenclass:: Config :members: + :protected-members: + :private-members: diff --git a/doc/solvers/csdsnsolverfp.rst b/doc/solvers/csdsnsolverfp.rst index d29fa52..f666f23 100644 --- a/doc/solvers/csdsnsolverfp.rst +++ b/doc/solvers/csdsnsolverfp.rst @@ -3,3 +3,4 @@ CSDSNSolverFP .. doxygenclass:: CSDSNSolverFP :members: + diff --git a/doc/solvers/csdsolvertrafofpsh2d.rst b/doc/solvers/csdsolvertrafofpsh2d.rst index 4a7a30b..cbaf4fb 100644 --- a/doc/solvers/csdsolvertrafofpsh2d.rst +++ b/doc/solvers/csdsolvertrafofpsh2d.rst @@ -3,3 +3,5 @@ CSDSolverTrafoFPSH2D .. doxygenclass:: CSDSolverTrafoFPSH2D :members: + :protected-members: + :private-members: diff --git a/doc/solvers/snsolver.rst b/doc/solvers/snsolver.rst index 1c120ec..66772e9 100644 --- a/doc/solvers/snsolver.rst +++ b/doc/solvers/snsolver.rst @@ -3,3 +3,5 @@ SNSolver .. doxygenclass:: SNSolver :members: + :protected-members: + :private-members: diff --git a/doc/solvers/solverbase.rst b/doc/solvers/solverbase.rst new file mode 100644 index 0000000..db2ff8e --- /dev/null +++ b/doc/solvers/solverbase.rst @@ -0,0 +1,7 @@ +SolverBase +========== + +.. doxygenclass:: SolverBase + :members: + :protected-members: + :private-members: -- GitLab From 3ac7e043ca6024024592dbcdb51ab37ca18cc43d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Fri, 26 Feb 2021 15:29:39 +0100 Subject: [PATCH 34/67] removed some compiler warnings Former-commit-id: 7bc98290e6dfef920ae4949483cd1764b08185ba --- doc/physics.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/physics.rst b/doc/physics.rst index 5f70088..c8081c3 100644 --- a/doc/physics.rst +++ b/doc/physics.rst @@ -3,7 +3,7 @@ Theory ================ The Boltzmann equation ---------- +---------------------- The particle transport phenomena enjoy rich academic research value and application prospects. A many-particle system can exhibit different behaviors at characteristic different scales. @@ -61,7 +61,7 @@ The particle distribution :math:`\psi(r, \Omega, E, t)` here is often named as a The spherical harmonics moment equations ---------- +---------------------------------------- The spherical harmonics (:math:`P_N`) method (cf. Brunner and Holloway [2005]) is one of several ways to solve the equation of radiative transfer. It serves as an approximate method, i.e. the method of moments, to reduce the high dimensionality when the original kinetic equation of radiative transfer, which is formulated on a seven-dimensional domain. @@ -122,7 +122,7 @@ where :math:`\ell \leq 0` and :math:`\ell \leq m \leq -\ell`. The entropy closure moment equations ---------- +------------------------------------ Another method of moments comes from the minimal principle of a convex entropy to close the moment system. Derivation of such moment system begins with the choice of a vector-valued function @@ -189,7 +189,7 @@ dual problem The continuous slowing down approximation ---------- +----------------------------------------- For the radiation therapy, the main goal is to compute the radiation dose accurately, which is defined as -- GitLab From 2557dcb8074b901ddd4946f3027365d5f67429e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Fri, 26 Feb 2021 16:24:23 +0100 Subject: [PATCH 35/67] more documentation Former-commit-id: 89068dc9bc70cbc7f870e96fdb427569237fce19 --- code/include/common/config.h | 2 +- code/include/common/globalconstants.h | 2 +- code/include/common/io.h | 8 +-- code/include/common/mesh.h | 22 ++++---- code/include/common/optionstructure.h | 51 +++++++++--------- code/include/fluxes/numericalflux.h | 26 +++++----- code/include/fluxes/upwindflux.h | 52 +++++++++---------- code/include/optimizers/newtonoptimizer.h | 10 ++-- code/include/problems/checkerboard.h | 24 ++++----- code/include/problems/icru.h | 2 +- code/include/problems/isotropicsource2d.h | 3 +- code/include/problems/problembase.h | 2 +- code/include/quadratures/qlookupquadrature.h | 6 +-- code/include/quadratures/quadraturebase.h | 24 ++++----- code/include/solvers/csdsnsolver.h | 4 +- code/include/solvers/csdsnsolverfp.h | 8 +-- code/include/solvers/csdsnsolvernotrafo.h | 4 +- code/include/solvers/csdsolvertrafofp.h | 16 +++--- code/include/solvers/csdsolvertrafofp2d.h | 10 ++-- code/include/solvers/csdsolvertrafofpsh2d.h | 10 ++-- code/include/solvers/snsolver.h | 2 +- code/include/toolboxes/datagenerator1D.h | 7 ++- code/include/toolboxes/datagenerator3D.h | 7 ++- code/include/toolboxes/datageneratorbase.h | 33 ++++++------ code/include/toolboxes/errormessages.h | 8 +-- code/include/toolboxes/sphericalmonomials.h | 2 +- .../include/toolboxes/textprocessingtoolbox.h | 4 +- code/src/common/config.cpp | 4 +- code/src/common/mesh.cpp | 29 +++++------ code/src/common/optionstructure.cpp | 2 +- code/src/problems/linesource.cpp | 1 - code/src/toolboxes/datageneratorbase.cpp | 2 +- code/src/toolboxes/sphericalharmonics.cpp | 1 - doc/common/mesh.rst | 3 ++ doc/entropies/entropybase.rst | 2 + doc/entropies/maxwellboltzmannentropy.rst | 2 + doc/entropies/quadraticentropy.rst | 2 + doc/fluxes/laxfriedrichsflux.rst | 2 + doc/fluxes/numericalflux.rst | 2 + doc/fluxes/upwindflux.rst | 2 + doc/kernels/isotropic.rst | 2 + doc/kernels/isotropic1D.rst | 2 + doc/kernels/scatteringkernel.rst | 2 + doc/optimizers/mloptimizer.rst | 2 + doc/optimizers/newtonoptimizer.rst | 2 + doc/optimizers/optimizerbase.rst | 2 + doc/problems/aircavity1d.rst | 2 + doc/problems/checkerboardpn.rst | 2 + doc/problems/checkerboardsn.rst | 2 + doc/problems/electronrt.rst | 2 + doc/problems/icru.rst | 2 + doc/problems/linesource.rst | 2 + doc/problems/linesourcepn.rst | 2 + doc/problems/linesourcesn.rst | 2 + doc/problems/linesourcesnpseudo1d.rst | 2 + doc/problems/linesourcesnpseudo1dphysics.rst | 2 + doc/problems/musclebonelung.rst | 2 + doc/problems/phantom2d.rst | 2 + doc/problems/problembase.rst | 2 + doc/problems/slabgeohg.rst | 2 + doc/problems/waterphantom.rst | 2 + doc/quadratures/qgausslegendre1D.rst | 2 + doc/quadratures/qgausslegendretensorized.rst | 2 + doc/quadratures/qldfesa.rst | 2 + doc/quadratures/qlebedev.rst | 2 + doc/quadratures/qlevelsymmetric.rst | 2 + doc/quadratures/qlookupquadrature.rst | 2 + doc/quadratures/qmontecarlo.rst | 2 + doc/quadratures/qproduct.rst | 2 + doc/quadratures/quadraturebase.rst | 2 + doc/solvers/csdsnsolver.rst | 2 + doc/solvers/csdsnsolverfp.rst | 3 +- doc/solvers/csdsnsolvernotrafo.rst | 2 + doc/solvers/csdsolvertrafofp.rst | 2 + doc/solvers/csdsolvertrafofp2d.rst | 2 + doc/solvers/snsolvermpi.rst | 2 + doc/toolboxes/errormessages.rst | 2 + doc/toolboxes/interpolation.rst | 2 + doc/toolboxes/physics.rst | 2 + doc/toolboxes/reconstructor.rst | 2 + doc/toolboxes/sphericalharmonics.rst | 2 + 81 files changed, 285 insertions(+), 201 deletions(-) diff --git a/code/include/common/config.h b/code/include/common/config.h index 65b9931..b1bce95 100644 --- a/code/include/common/config.h +++ b/code/include/common/config.h @@ -27,7 +27,7 @@ class OptionBase; class Config { private: - std::string _fileName; /*!< @rief Name of the current file without extension */ + std::string _fileName; /*!< @brief Name of the current file without extension */ bool _baseConfig; // int _commRank, _commSize; /*!< @brief MPI rank and size.*/ // Not yet used!! diff --git a/code/include/common/globalconstants.h b/code/include/common/globalconstants.h index f3df798..c34a4a4 100644 --- a/code/include/common/globalconstants.h +++ b/code/include/common/globalconstants.h @@ -1,5 +1,5 @@ /*! - * \file GlobalConstants.h + * \file globalconstants.h * \brief All global defined (physical) constants, enums etc * \author * \version 0.0 diff --git a/code/include/common/io.h b/code/include/common/io.h index abf26dd..1f5153e 100644 --- a/code/include/common/io.h +++ b/code/include/common/io.h @@ -10,10 +10,10 @@ class Config; class Mesh; /*! @brief Function to export solver Volume output to VTK file. - * @param filename: Filename of output file - * @param outputFields: numerical output of the solver. Dimensions: (OutputGroupSize, OutputFieldSize, NumberMeshCells) - * @param outputFieldNames: names of the outputfields. Dimensions: (OutputGroupSize, OutputFieldSize) - * @param mesh: Mesh with cells (the mesh used for the computation) + * @param fileName Filename of output file + * @param outputFields numerical output of the solver. Dimensions: (OutputGroupSize, OutputFieldSize, NumberMeshCells) + * @param outputFieldNames names of the outputfields. Dimensions: (OutputGroupSize, OutputFieldSize) + * @param mesh Mesh with cells (the mesh used for the computation) */ void ExportVTK( const std::string fileName, const std::vector>>& outputFields, diff --git a/code/include/common/mesh.h b/code/include/common/mesh.h index 416ae9f..0f15c1a 100644 --- a/code/include/common/mesh.h +++ b/code/include/common/mesh.h @@ -18,23 +18,23 @@ class Mesh { protected: - const unsigned _dim; /*!< @brief spatial dimension of the mesh, i.e. 1D,2D,3D */ - const unsigned _numCells; /*!< @brief number of cells in the mesh */ - const unsigned _numNodes; /*!< @brief number of nodes in the mesh (for node centered view)*/ + const unsigned _dim; /*!< @brief spatial dimension of the mesh, i.e. 1D,2D,3D */ + const unsigned _numCells; /*!< @brief number of cells in the mesh */ + const unsigned _numNodes; /*!< @brief number of nodes in the mesh (for node centered view)*/ const unsigned _numNodesPerCell; /*!< @brief number of nodes per cell */ - const unsigned _numBoundaries; /*!< @brief number of boundary cells in the mesh */ + const unsigned _numBoundaries; /*!< @brief number of boundary cells in the mesh */ const unsigned _ghostCellID; /*!< @brief Id of the ghost cell. (we use only one ghost cell). equal to _numCells and therefore has the ID of the last cell + 1 */ unsigned _numNodesPerBoundary; std::vector> _bounds; // ??? - std::vector _nodes; /*!< @brief nodes in the mesh. dimension:_numNodes<_dim> */ + std::vector _nodes; /*!< @brief nodes in the mesh. dimension:_numNodes<_dim> */ std::vector> _cells; /*!< @brief cells in the mesh. dimension:_numCells<_numNodesPerCell> */ /*! @brief boundary cells in the mesh. Pair defines boundary type of the boundary nodes of the cell. numBoundaries<(1,numBoundaryNodes)>*/ std::vector>> _boundaries; - std::vector _cellAreas; /*!< @brief cell areas of the mesh. dimension: numCells*/ - std::vector _cellMidPoints; /*!< @brief cell midpoints of the mesh. dimension: numCells*/ + std::vector _cellAreas; /*!< @brief cell areas of the mesh. dimension: numCells*/ + std::vector _cellMidPoints; /*!< @brief cell midpoints of the mesh. dimension: numCells*/ std::vector> _cellNeighbors; /*!< @brief neighbors of each cell. dimension: numCells*/ /*! @brief outward facing normals of each side of each cell. dimension: numCells>, all @@ -42,13 +42,13 @@ class Mesh std::vector> _cellNormals; /*! @brief Tags each cell with its boundary type. None means no boundary. dimension: numCells */ std::vector _cellBoundaryTypes; - std::vector _colors; /*!< @brief Color of each cell (for MPI mesh partitioning). dimension: numCells */ + std::vector _colors; /*!< @brief Color of each cell (for MPI mesh partitioning). dimension: numCells */ blaze::CompressedMatrix _nodeNeighbors; /*!< @brief neighborshood relationship of nodes for (par-)metis */ - void ComputeCellAreas(); /*!< @brief Computes only the areas of the mesh cells. Write to _cellAreas. */ + void ComputeCellAreas(); /*!< @brief Computes only the areas of the mesh cells. Write to _cellAreas. */ void ComputeCellMidpoints(); /*!< @brief Compute only the midpoints of the cells. Write to _cellMidPoints*/ - void ComputeConnectivity(); /*!< @brief Computes _cellNeighbors and _nodeNeighbors, i.e. neighborship relation in mesh*/ - void ComputePartitioning(); /*!< @brief Computes local partitioning for openMP */ + void ComputeConnectivity(); /*!< @brief Computes _cellNeighbors and _nodeNeighbors, i.e. neighborship relation in mesh*/ + void ComputePartitioning(); /*!< @brief Computes local partitioning for openMP */ /*! @brief Computes outward facing normal of two neighboring nodes nodeA and nodeB with common cellCellcenter. * Normals are scaled with their respective edge length diff --git a/code/include/common/optionstructure.h b/code/include/common/optionstructure.h index 6681923..70db632 100644 --- a/code/include/common/optionstructure.h +++ b/code/include/common/optionstructure.h @@ -1,9 +1,6 @@ /*! - * \file OptionStructure.h - * \brief Classes for different Options in rtsn - * \author S. Schotthoefer - * - * Disclaimer: This class structure was copied and modifed with open source permission from SU2 v7.0.3 https://su2code.github.io/ + * \file optionstructure.h + * \brief Classes for different Options in KiT-RT */ #ifndef OPTION_STRUCTURE_H @@ -38,8 +35,8 @@ class OptionBase class OptionDouble : public OptionBase { - double& _field; /*!< @brief Reference to the double field value */ - double _def; /*!< @brief Default value */ + double& _field; /*!< @brief Reference to the double field value */ + double _def; /*!< @brief Default value */ std::string _name; /*!< @brief String identifier for the option */ public: @@ -55,8 +52,8 @@ class OptionDouble : public OptionBase class OptionString : public OptionBase { std::string& _field; /*!< @brief Reference to the string field value */ - std::string _def; /*!< @brief Default value */ - std::string _name; /*!< @brief string identifier for the option */ + std::string _def; /*!< @brief Default value */ + std::string _name; /*!< @brief string identifier for the option */ public: OptionString( std::string option_field_name, std::string& option_field, std::string default_value ); @@ -70,8 +67,8 @@ class OptionString : public OptionBase class OptionInt : public OptionBase { - int& _field; /*!< @brief Reference to the int field value */ - int _def; /*!< @brief Default value */ + int& _field; /*!< @brief Reference to the int field value */ + int _def; /*!< @brief Default value */ std::string _name; /*!< @brief string identifier for the option */ public: @@ -87,8 +84,8 @@ class OptionInt : public OptionBase class OptionULong : public OptionBase { unsigned long& _field; /*!< @brief Reference to the unsigned long field value */ - unsigned long _def; /*!< @brief Default value */ - std::string _name; /*!< @brief string identifier for the option */ + unsigned long _def; /*!< @brief Default value */ + std::string _name; /*!< @brief string identifier for the option */ public: OptionULong( std::string option_field_name, unsigned long& option_field, unsigned long default_value ); @@ -103,8 +100,8 @@ class OptionULong : public OptionBase class OptionUShort : public OptionBase { unsigned short& _field; /*!< @brief Reference to the unsigned short field value */ - unsigned short _def; /*!< @brief Default value */ - std::string _name; /*!< @brief string identifier for the option */ + unsigned short _def; /*!< @brief Default value */ + std::string _name; /*!< @brief string identifier for the option */ public: OptionUShort( std::string option_field_name, unsigned short& option_field, unsigned short default_value ); @@ -118,8 +115,8 @@ class OptionUShort : public OptionBase class OptionLong : public OptionBase { - long& _field; /*!< @brief Reference to the long field value */ - long _def; /*!< @brief Default value */ + long& _field; /*!< @brief Reference to the long field value */ + long _def; /*!< @brief Default value */ std::string _name; /*!< @brief string identifier for the option */ public: @@ -134,8 +131,8 @@ class OptionLong : public OptionBase class OptionBool : public OptionBase { - bool& _field; /*!< @brief Reference to the bool field value */ - bool _def; /*!< @brief Default value */ + bool& _field; /*!< @brief Reference to the bool field value */ + bool _def; /*!< @brief Default value */ std::string _name; /*!< @brief string identifier for the option */ public: @@ -151,8 +148,8 @@ class OptionBool : public OptionBase class OptionStringList : public OptionBase { std::vector& _field; /*!< @brief Reference to the string list field value. no default value */ - std::string _name; /*!< @brief string identifier for the option */ - unsigned short& _size; /*!< @brief Size of string list */ + std::string _name; /*!< @brief string identifier for the option */ + unsigned short& _size; /*!< @brief Size of string list */ public: OptionStringList( std::string option_field_name, unsigned short& list_size, std::vector& option_field ); @@ -170,9 +167,9 @@ template class OptionEnum : public OptionBase { std::map _map; /*!< @brief Map */ - Tenum& _field; /*!< @brief Reference to the enum fieldname */ - Tenum _def; /*!< @brief Default value */ - std::string _name; /*!< @brief string identifier for the option */ + Tenum& _field; /*!< @brief Reference to the enum fieldname */ + Tenum _def; /*!< @brief Default value */ + std::string _name; /*!< @brief string identifier for the option */ public: OptionEnum( std::string option_field_name, const std::map m, Tenum& option_field, Tenum default_value ) @@ -213,9 +210,9 @@ template class OptionEnumList : public OptionBase { std::map _map; /*!< @brief Map */ - std::vector& _field; /*!< @brief Reference to the enum list fieldname. No default value */ - std::string _name; /*!< @brief string identifier for the option */ - unsigned short& _size; /*!< @brief Size of enum list */ + std::vector& _field; /*!< @brief Reference to the enum list fieldname. No default value */ + std::string _name; /*!< @brief string identifier for the option */ + unsigned short& _size; /*!< @brief Size of enum list */ public: OptionEnumList( std::string option_field_name, const std::map m, std::vector& option_field, unsigned short& list_size ) diff --git a/code/include/fluxes/numericalflux.h b/code/include/fluxes/numericalflux.h index 2a5835e..ecea614 100644 --- a/code/include/fluxes/numericalflux.h +++ b/code/include/fluxes/numericalflux.h @@ -20,19 +20,19 @@ class NumericalFlux virtual double Flux( const Vector& Omega, double psiL, double psiR, const Vector& n ) const = 0; /** - * @brief Flux : Computes upwinding scheme for given flux jacobians of the PN Solver at a given edge and stores it in - * resultFlux - * @param AxPlus : Positive part of the flux jacobian in x direction - * @param AxMinus : Negative part of the flux jacobian in x direction - * @param AyPlus : Positive part of the flux jacobian in y direction - * @param AyMinus : Negative part of the flux jacobian in y direction - * @param AzPlus : Positive part of the flux jacobian in z direction - * @param AzMinus : Negative part of the flux jacobian in z direction - * @param psiL : Solution state of left hand side control volume - * @param psiR : Solution state of right hand side control volume - * @param n : Normal vector at the edge between left and right control volume - * @param resultFlux: Vector with resulting flux. - * @return : void + * @brief Flux Computes "Steger Warming" upwinding scheme for given flux jacobians of the PN Solver at a given edge and stores it in + * resultFlux + * @param AxPlus Positive part of the flux jacobian in x direction + * @param AxMinus Negative part of the flux jacobian in x direction + * @param AyPlus Positive part of the flux jacobian in y direction + * @param AyMinus Negative part of the flux jacobian in y direction + * @param AzPlus Positive part of the flux jacobian in z direction + * @param AzMinus Negative part of the flux jacobian in z direction + * @param psiL Solution state of left hand side control volume + * @param psiR Solution state of right hand side control volume + * @param n Normal vector at the edge between left and right control volume + * @param resultFlux Vector with resulting flux. + * @return void */ virtual Vector Flux( const Matrix AxPlus, const Matrix AxMinus, diff --git a/code/include/fluxes/upwindflux.h b/code/include/fluxes/upwindflux.h index fe40f19..6377eee 100644 --- a/code/include/fluxes/upwindflux.h +++ b/code/include/fluxes/upwindflux.h @@ -23,19 +23,19 @@ class UpwindFlux : public NumericalFlux double Flux( const Vector& Omega, double psiL, double psiR, const Vector& n ) const override; /** - * @brief Flux : Computes upwinding scheme for given flux jacobians of the PN Solver at a given edge and stores it in - * resultFlux - * @param AxPlus : Positive part of the flux jacobian in x direction - * @param AxMinus : Negative part of the flux jacobian in x direction - * @param AyPlus : Positive part of the flux jacobian in y direction - * @param AyMinus : Negative part of the flux jacobian in y direction - * @param AzPlus : Positive part of the flux jacobian in z direction - * @param AzMinus : Negative part of the flux jacobian in z direction - * @param psiL : Solution state of left hand side control volume - * @param psiR : Solution state of right hand side control volume - * @param n : Normal vector at the edge between left and right control volume - * @param resultFlux: Vector with resulting flux. - * @return : void + * @brief Flux Computes "Steger Warming" upwinding scheme for given flux jacobians of the PN Solver at a given edge and stores it in + * resultFlux + * @param AxPlus Positive part of the flux jacobian in x direction + * @param AxMinus Negative part of the flux jacobian in x direction + * @param AyPlus Positive part of the flux jacobian in y direction + * @param AyMinus Negative part of the flux jacobian in y direction + * @param AzPlus Positive part of the flux jacobian in z direction + * @param AzMinus Negative part of the flux jacobian in z direction + * @param psiL Solution state of left hand side control volume + * @param psiR Solution state of right hand side control volume + * @param n Normal vector at the edge between left and right control volume + * @param resultFlux Vector with resulting flux. + * @return void */ Vector Flux( const Matrix AxPlus, const Matrix AxMinus, @@ -48,19 +48,19 @@ class UpwindFlux : public NumericalFlux const Vector n ) const override; /** - * @brief Flux : Computes upwinding scheme for given flux jacobians of the PN Solver at a given edge and stores it in - * resultFlux - * @param AxPlus : Positive part of the flux jacobian in x direction - * @param AxMinus : Negative part of the flux jacobian in x direction - * @param AyPlus : Positive part of the flux jacobian in y direction - * @param AyMinus : Negative part of the flux jacobian in y direction - * @param AzPlus : Positive part of the flux jacobian in z direction - * @param AzMinus : Negative part of the flux jacobian in z direction - * @param psiL : Solution state of left hand side control volume - * @param psiR : Solution state of right hand side control volume - * @param n : Normal vector at the edge between left and right control volume - * @param resultFlux: Vector with resulting flux. - * @return : void + * @brief Flux Computes "VanLeer" upwinding scheme for given flux jacobians of the PN Solver at a given edge and stores it in + * resultFlux + * @param AxPlus Positive part of the flux jacobian in x direction + * @param AxMinus Negative part of the flux jacobian in x direction + * @param AyPlus Positive part of the flux jacobian in y direction + * @param AyMinus Negative part of the flux jacobian in y direction + * @param AzPlus Positive part of the flux jacobian in z direction + * @param AzMinus Negative part of the flux jacobian in z direction + * @param psiL Solution state of left hand side control volume + * @param psiR Solution state of right hand side control volume + * @param n Normal vector at the edge between left and right control volume + * @param resultFlux Vector with resulting flux. + * @return void */ void FluxVanLeer( const Matrix& Ax, const Matrix& AxAbs, diff --git a/code/include/optimizers/newtonoptimizer.h b/code/include/optimizers/newtonoptimizer.h index 010c8dd..8be0368 100644 --- a/code/include/optimizers/newtonoptimizer.h +++ b/code/include/optimizers/newtonoptimizer.h @@ -35,12 +35,12 @@ class NewtonOptimizer : public OptimizerBase void ComputeHessian( Vector& alpha, const VectorVector& moments, Matrix& hessian ); QuadratureBase* _quadrature; /*!< @brief used quadrature */ // THis is memory doubling! Try to use a pointer. - unsigned _nq; /*!< @brief number of quadrature points */ - Vector _weights; /*!< @brief quadrature weights, dim(_weights) = (_nq) */ + unsigned _nq; /*!< @brief number of quadrature points */ + Vector _weights; /*!< @brief quadrature weights, dim(_weights) = (_nq) */ - double _epsilon; /*!< @brief Termination criterion for newton optimizer */ - unsigned short _maxIterations; /*!< @brief Max iterations of the newton solver */ - double _alpha; /*!< @brief Newton Step Size */ + double _epsilon; /*!< @brief Termination criterion for newton optimizer */ + unsigned short _maxIterations; /*!< @brief Max iterations of the newton solver */ + double _alpha; /*!< @brief Newton Step Size */ unsigned short _maxLineSearches; /*!< @brief Max amount of line searches for Newton Algo */ }; diff --git a/code/include/problems/checkerboard.h b/code/include/problems/checkerboard.h index 3b5671a..629873a 100644 --- a/code/include/problems/checkerboard.h +++ b/code/include/problems/checkerboard.h @@ -7,33 +7,33 @@ class Checkerboard_SN : public ProblemBase { private: Vector _scatteringXS; /*!< @brief Vector of scattering crosssections */ - Vector _totalXS; /*!< @brief Vector of total crosssections */ + Vector _totalXS; /*!< @brief Vector of total crosssections */ Checkerboard_SN() = delete; bool isAbsorption( const Vector& pos ) const; /*!< @return True if pos is in absorption region, False otherwise */ - bool isSource( const Vector& pos ) const; /*!< @return True if pos is in source region, False otherwise */ + bool isSource( const Vector& pos ) const; /*!< @return True if pos is in source region, False otherwise */ public: Checkerboard_SN( Config* settings, Mesh* mesh ); virtual ~Checkerboard_SN(); - virtual VectorVector GetScatteringXS( const Vector& energies ); - virtual VectorVector GetTotalXS( const Vector& energies ); - virtual std::vector GetExternalSource( const Vector& energies ); - virtual VectorVector SetupIC(); + virtual VectorVector GetScatteringXS( const Vector& energies ) override; + virtual VectorVector GetTotalXS( const Vector& energies ) override; + virtual std::vector GetExternalSource( const Vector& energies ) override; + virtual VectorVector SetupIC() override; }; class Checkerboard_PN : public ProblemBase { private: Vector _scatteringXS; /*!< @brief Vector of scattering crosssections len: numCells */ - Vector _totalXS; /*!< @brief Vector of total crosssections. len: numCells*/ + Vector _totalXS; /*!< @brief Vector of total crosssections. len: numCells*/ Checkerboard_PN() = delete; bool isAbsorption( const Vector& pos ) const; /*!< @return True if pos is in absorption region, False otherwise */ - bool isSource( const Vector& pos ) const; /*!< @return True if pos is in source region, False otherwise */ + bool isSource( const Vector& pos ) const; /*!< @return True if pos is in source region, False otherwise */ /** * @brief Gets the global index for given order l of Legendre polynomials and given @@ -49,10 +49,10 @@ class Checkerboard_PN : public ProblemBase Checkerboard_PN( Config* settings, Mesh* mesh ); virtual ~Checkerboard_PN(); - virtual VectorVector GetScatteringXS( const Vector& energies ); - virtual VectorVector GetTotalXS( const Vector& energies ); - virtual std::vector GetExternalSource( const Vector& energies ); - virtual VectorVector SetupIC(); + virtual VectorVector GetScatteringXS( const Vector& energies ) override; + virtual VectorVector GetTotalXS( const Vector& energies ) override; + virtual std::vector GetExternalSource( const Vector& energies ) override; + virtual VectorVector SetupIC() override; }; #endif // CHECKERBOARD_H diff --git a/code/include/problems/icru.h b/code/include/problems/icru.h index c0eda74..c245ff6 100644 --- a/code/include/problems/icru.h +++ b/code/include/problems/icru.h @@ -66,7 +66,7 @@ class ICRU double _R1; Vector _E, /*! @brief User queried Energy */ - _QMU; /*!< @briefUser queried mu */ + _QMU; /*!< @briefUser queried mu */ std::vector _ET, _ETL; std::vector _XMU, /* angular variable mu of dataset */ diff --git a/code/include/problems/isotropicsource2d.h b/code/include/problems/isotropicsource2d.h index adea0bc..07ff120 100644 --- a/code/include/problems/isotropicsource2d.h +++ b/code/include/problems/isotropicsource2d.h @@ -23,5 +23,4 @@ class IsotropicSource2D : public ElectronRT std::vector GetDensity( const VectorVector& cellMidPoints ); }; - -#endif // ISOTROPICSOURCE2D_H +#endif // ISOTROPICSOURCE2D_H diff --git a/code/include/problems/problembase.h b/code/include/problems/problembase.h index 8ac2b5a..7dbbcc1 100644 --- a/code/include/problems/problembase.h +++ b/code/include/problems/problembase.h @@ -17,7 +17,7 @@ class ProblemBase Mesh* _mesh; EPICS* _physics; - std::vector _density; /*!< @brief vector with patient densities */ + std::vector _density; /*!< @brief vector with patient densities */ std::vector _stoppingPower; /*!< @brief vector with stopping powers*/ ProblemBase() = delete; diff --git a/code/include/quadratures/qlookupquadrature.h b/code/include/quadratures/qlookupquadrature.h index d924946..85d3dd9 100644 --- a/code/include/quadratures/qlookupquadrature.h +++ b/code/include/quadratures/qlookupquadrature.h @@ -17,8 +17,8 @@ class QLookupQuadrature : public QuadratureBase void printAvailOrders() const; /*!< @brief prints available orders */ protected: - bool CheckOrder(); /*!< @brief checks if given order is available for this quadrature rule. */ - void SetNq() override; /*!< @brief Assumes, that _order is available in lookup table */ + bool CheckOrder(); /*!< @brief checks if given order is available for this quadrature rule. */ + void SetNq() override; /*!< @brief Assumes, that _order is available in lookup table */ void SetPointsAndWeights() override; /*!< @brief reads in n_points gridpoints and -weights from given filename. */ virtual void SetAvailOrders() = 0; /*!< @brief Sets vector with avaialbe Orders and corresponding vector with Nq. */ @@ -26,6 +26,6 @@ class QLookupQuadrature : public QuadratureBase virtual std::string GetLookupTable() = 0; /*!< @brief returns lookuptable of _order. Assumes order is available */ std::vector _availableOrders; /*!< @brief Vector with available orders for lookup table */ - std::vector _nqByOrder; /*!< @brief Vector with number of quadrature points of each listed order */ + std::vector _nqByOrder; /*!< @brief Vector with number of quadrature points of each listed order */ }; #endif // QLOOKUPQUADRATURE_H diff --git a/code/include/quadratures/quadraturebase.h b/code/include/quadratures/quadraturebase.h index ee1e35b..eac63c7 100644 --- a/code/include/quadratures/quadraturebase.h +++ b/code/include/quadratures/quadraturebase.h @@ -24,8 +24,8 @@ class QuadratureBase virtual ~QuadratureBase() {} // Aux functions - void PrintWeights(); /*!< @brief prints: Weight vector */ - void PrintPoints(); /*!< @brief prints: Point vectorVector */ + void PrintWeights(); /*!< @brief prints: Weight vector */ + void PrintPoints(); /*!< @brief prints: Point vectorVector */ void PrintPointsAndWeights(); /*!< @brief prints: Point vectorVector with corresponding weight vector */ /*! @brief sums up all entries of the weight vector. @@ -76,9 +76,9 @@ class QuadratureBase protected: // Setter inline void SetOrder( unsigned order ) { _order = order; } /*! @brief sets: order of the quadrature */ - virtual void SetName() = 0; /*!< @brief Sets: name of the quadrature */ - virtual void SetNq() = 0; /*!< @brief sets: number of gridpoints of the quadrature */ - virtual void SetConnectivity() = 0; /*!< @brief sets: Connectivity Adjacency Matrix as VektorVektor*/ + virtual void SetName() = 0; /*!< @brief Sets: name of the quadrature */ + virtual void SetNq() = 0; /*!< @brief sets: number of gridpoints of the quadrature */ + virtual void SetConnectivity() = 0; /*!< @brief sets: Connectivity Adjacency Matrix as VektorVektor*/ /*! @brief Computes the a vector (length: nq) of (coordinates of) gridpoints used for the quadrature rule. * Computes the a vector (length: nq) of weights for the gridpoints. The indices match the gridpoints VectorVector. @@ -86,13 +86,13 @@ class QuadratureBase virtual void SetPointsAndWeights() = 0; // Member variables - Config* _settings; /*!< @brief pointer to settings class that manages the solver */ - std::string _name; /*!< @brief name of the quadrature */ - unsigned _order; /*!< @brief order of the quadrature */ - unsigned _nq; /*!< @brief number of gridpoints of the quadrature */ - VectorVector _points; /*!< @brief gridpoints of the quadrature */ - VectorVector _pointsSphere; /*!< @brief (my,phi)gridpoints of the quadrature in spherical cordinates */ - Vector _weights; /*!< @brief weights of the gridpoints of the quadrature */ + Config* _settings; /*!< @brief pointer to settings class that manages the solver */ + std::string _name; /*!< @brief name of the quadrature */ + unsigned _order; /*!< @brief order of the quadrature */ + unsigned _nq; /*!< @brief number of gridpoints of the quadrature */ + VectorVector _points; /*!< @brief gridpoints of the quadrature */ + VectorVector _pointsSphere; /*!< @brief (my,phi)gridpoints of the quadrature in spherical cordinates */ + Vector _weights; /*!< @brief weights of the gridpoints of the quadrature */ VectorVectorU _connectivity; /*!< @brief connectivity of the gripoints of the quadrature */ }; diff --git a/code/include/solvers/csdsnsolver.h b/code/include/solvers/csdsnsolver.h index dad3ff7..a939e7c 100644 --- a/code/include/solvers/csdsnsolver.h +++ b/code/include/solvers/csdsnsolver.h @@ -10,10 +10,10 @@ class CSDSNSolver : public SNSolver // Physics acess Vector _energies; /*!< @brief energy levels for CSD, lenght = _nEnergies */ - Vector _angle; /*!< @brief angles for SN */ + Vector _angle; /*!< @brief angles for SN */ std::vector _sigmaSE; /*!< @brief scattering cross section for all energies*/ - Vector _sigmaTE; /*!< @brief total cross section for all energies*/ + Vector _sigmaTE; /*!< @brief total cross section for all energies*/ public: /** diff --git a/code/include/solvers/csdsnsolverfp.h b/code/include/solvers/csdsnsolverfp.h index bd6531f..a6aaa99 100644 --- a/code/include/solvers/csdsnsolverfp.h +++ b/code/include/solvers/csdsnsolverfp.h @@ -12,16 +12,16 @@ class CSDSNSolverFP : public SNSolver // Physics acess Vector _energies; /*!< @brief energy levels for CSD, length = _nEnergies */ - Vector _angle; /*!< @brief angles for SN */ + Vector _angle; /*!< @brief angles for SN */ std::vector _sigmaSE; /*!< @brief scattering cross section for all energies*/ - Vector _sigmaTE; /*!< @brief total cross section for all energies*/ + Vector _sigmaTE; /*!< @brief total cross section for all energies*/ - Matrix _L; /*!< @brief Laplace Beltrami Matrix */ + Matrix _L; /*!< @brief Laplace Beltrami Matrix */ Matrix _IL; /*!< @brief Laplace Beltrami Matrix */ double _alpha; /*!< @brief Coefficient of GFP operators (see Olbrant 2010, eq. (8)*/ - double _beta; /*!< @brief Coefficient of GFP operators (see Olbrant 2010, eq. (8)*/ + double _beta; /*!< @brief Coefficient of GFP operators (see Olbrant 2010, eq. (8)*/ Matrix _xi; /*!< @brief matrix of transport coefficients */ diff --git a/code/include/solvers/csdsnsolvernotrafo.h b/code/include/solvers/csdsnsolvernotrafo.h index e02a356..4de19f0 100644 --- a/code/include/solvers/csdsnsolvernotrafo.h +++ b/code/include/solvers/csdsnsolvernotrafo.h @@ -12,10 +12,10 @@ class CSDSNSolverNoTrafo : public SNSolver // Physics acess Vector _energies; /*!< @brief energy levels for CSD, lenght = _nEnergies */ - Vector _angle; /*!< @brief angles for SN */ + Vector _angle; /*!< @brief angles for SN */ std::vector _sigmaSE; /*!< @brief scattering cross section for all energies*/ - Vector _sigmaTE; /*!< @brief total cross section for all energies*/ + Vector _sigmaTE; /*!< @brief total cross section for all energies*/ public: /** diff --git a/code/include/solvers/csdsolvertrafofp.h b/code/include/solvers/csdsolvertrafofp.h index 0b94939..1cda2f7 100644 --- a/code/include/solvers/csdsolvertrafofp.h +++ b/code/include/solvers/csdsolvertrafofp.h @@ -12,24 +12,24 @@ class CSDSolverTrafoFP : public SNSolver // Physics acess Vector _energies; /*!< @brief energy levels for CSD, lenght = _nEnergies */ - Vector _angle; /*!< @brief angles for SN */ + Vector _angle; /*!< @brief angles for SN */ std::vector _sigmaSE; /*!< @brief scattering cross section for all energies*/ - Vector _sigmaTE; /*!< @brief total cross section for all energies*/ + Vector _sigmaTE; /*!< @brief total cross section for all energies*/ - Matrix _L; /*!< @brief Laplace Beltrami Matrix */ + Matrix _L; /*!< @brief Laplace Beltrami Matrix */ Matrix _IL; /*!< @brief Laplace Beltrami Matrix */ - double _alpha; /*!< @brief Coefficient of GFP operators (see Olbrant 2010, Appendix B)*/ + double _alpha; /*!< @brief Coefficient of GFP operators (see Olbrant 2010, Appendix B)*/ double _alpha2; /*!< @brief Coefficient of GFP operators (see Olbrant 2010, Appendix B)*/ - double _beta; /*!< @brief Coefficient of GFP operators (see Olbrant 2010, Appendix B)*/ + double _beta; /*!< @brief Coefficient of GFP operators (see Olbrant 2010, Appendix B)*/ Matrix _xi; /*!< @brief matrix of transport coefficients */ Vector _xi1; Vector _xi2; - unsigned _FPMethod; /*!< @brief Encodes different ways of computing coefficients alpha, alpha2 & beta, _FPMethod == 1, 2 ,3 stand for methods with - increasing accuracy (see Olbrant 2010, Appendix B)*/ + unsigned _FPMethod; /*!< @brief Encodes different ways of computing coefficients alpha, alpha2 & beta, _FPMethod == 1, 2 ,3 stand for methods + with increasing accuracy (see Olbrant 2010, Appendix B)*/ bool _RT; /*!< @brief radiotherapy application (on/off), if true use crosssections + stopping powers from database */ @@ -40,7 +40,7 @@ class CSDSolverTrafoFP : public SNSolver // Helper variables Vector _energiesOrig; /*!< @brief original energy levels for CSD, lenght = _nEnergies */ - Matrix _identity; /*!< @brif: identity matrix for FP scattering. Dim (_nq,_nq)*/ + Matrix _identity; /*!< @brief: identity matrix for FP scattering. Dim (_nq,_nq)*/ public: /** diff --git a/code/include/solvers/csdsolvertrafofp2d.h b/code/include/solvers/csdsolvertrafofp2d.h index e5a6d85..fe01331 100644 --- a/code/include/solvers/csdsolvertrafofp2d.h +++ b/code/include/solvers/csdsolvertrafofp2d.h @@ -12,12 +12,12 @@ class CSDSolverTrafoFP2D : public SNSolver // Physics acess Vector _energies; /*!< @brief energy levels for CSD, lenght = _nEnergies */ - Vector _angle; /*!< @brief angles for SN */ + Vector _angle; /*!< @brief angles for SN */ std::vector _sigmaSE; /*!< @brief scattering cross section for all energies*/ - Vector _sigmaTE; /*!< @brief total cross section for all energies*/ + Vector _sigmaTE; /*!< @brief total cross section for all energies*/ - Matrix _L; /*!< @brief Laplace Beltrami Matrix */ + Matrix _L; /*!< @brief Laplace Beltrami Matrix */ Matrix _IL; /*!< @brief Laplace Beltrami Matrix */ VectorVector _quadPoints; @@ -45,8 +45,8 @@ class CSDSolverTrafoFP2D : public SNSolver // Helper variables Vector _energiesOrig; /*!< @brief original energy levels for CSD, lenght = _nEnergies */ - Matrix _identity; /*!< @brif: identity matrix for FP scattering. Dim (_nq,_nq)*/ - double _densityMin; /*!< @brief Minimal density of _density vector */ + Matrix _identity; /*!< @brief: identity matrix for FP scattering. Dim (_nq,_nq)*/ + double _densityMin; /*!< @brief Minimal density of _density vector */ void GenerateEnergyGrid( bool refinement ); diff --git a/code/include/solvers/csdsolvertrafofpsh2d.h b/code/include/solvers/csdsolvertrafofpsh2d.h index ddb3df6..c10910a 100644 --- a/code/include/solvers/csdsolvertrafofpsh2d.h +++ b/code/include/solvers/csdsolvertrafofpsh2d.h @@ -23,12 +23,12 @@ class CSDSolverTrafoFPSH2D : public SNSolver // Physics acess Vector _energies; /*!< @brief energy levels for CSD, lenght = _nEnergies */ - Vector _angle; /*!< @brief angles for SN */ + Vector _angle; /*!< @brief angles for SN */ std::vector _sigmaSE; /*!< @brief scattering cross section for all energies*/ - Vector _sigmaTE; /*!< @brief total cross section for all energies*/ + Vector _sigmaTE; /*!< @brief total cross section for all energies*/ - Matrix _L; /*!< @brief Laplace Beltrami Matrix */ + Matrix _L; /*!< @brief Laplace Beltrami Matrix */ Matrix _IL; /*!< @brief Laplace Beltrami Matrix */ Matrix _O; @@ -60,8 +60,8 @@ class CSDSolverTrafoFPSH2D : public SNSolver // Helper variables Vector _energiesOrig; /*!< @brief original energy levels for CSD, lenght = _nEnergies */ - Matrix _identity; /*!< @brif: identity matrix for FP scattering. Dim (_nq,_nq)*/ - double _densityMin; /*!< @brief Minimal density of _density vector */ + Matrix _identity; /*!< @brief: identity matrix for FP scattering. Dim (_nq,_nq)*/ + double _densityMin; /*!< @brief Minimal density of _density vector */ public: /** diff --git a/code/include/solvers/snsolver.h b/code/include/solvers/snsolver.h index 853142d..2794135 100644 --- a/code/include/solvers/snsolver.h +++ b/code/include/solvers/snsolver.h @@ -11,7 +11,7 @@ class SNSolver : public SolverBase // quadrature related numbers VectorVector _quadPoints; /*!< @brief quadrature points, dim(_quadPoints) = (_nq,spatialDim) */ - Vector _weights; /*!< @brief quadrature weights, dim(_weights) = (_nq) */ + Vector _weights; /*!< @brief quadrature weights, dim(_weights) = (_nq) */ public: /*! @brief SNSolver constructor diff --git a/code/include/toolboxes/datagenerator1D.h b/code/include/toolboxes/datagenerator1D.h index 9acfae0..8ce7347 100644 --- a/code/include/toolboxes/datagenerator1D.h +++ b/code/include/toolboxes/datagenerator1D.h @@ -15,8 +15,7 @@ class DataGenerator1D : public DataGeneratorBase /*! @brief Class constructor. Generates training data for neural network approaches using * spherical harmonics and an entropy functional and the quadrature specified by * the options file. - * @param setSize: number of elements in training set - * basisSize: length of spherical harmonics basis (maybe redundant)*/ + * @param settings config class with global information*/ DataGenerator1D( Config* settings ); ~DataGenerator1D(); @@ -25,8 +24,8 @@ class DataGenerator1D : public DataGeneratorBase void SampleSolutionU() override; /*!< @brief Samples solution vectors u */ // Helper functions - void ComputeMoments() override; /*!< @brief Pre-Compute Moments at all quadrature points. */ - void ComputeSetSize() override; /*!< @brief Computes the size of the training set, depending on the chosen settings.*/ + void ComputeMoments() override; /*!< @brief Pre-Compute Moments at all quadrature points. */ + void ComputeSetSize() override; /*!< @brief Computes the size of the training set, depending on the chosen settings.*/ void CheckRealizability() override; // Debugging helper }; #endif // DATAGENERATOR1D_H diff --git a/code/include/toolboxes/datagenerator3D.h b/code/include/toolboxes/datagenerator3D.h index 857c6d9..4dc08c5 100644 --- a/code/include/toolboxes/datagenerator3D.h +++ b/code/include/toolboxes/datagenerator3D.h @@ -15,8 +15,7 @@ class DataGenerator3D : public DataGeneratorBase /*! @brief Class constructor. Generates training data for neural network approaches using * spherical harmonics and an entropy functional and the quadrature specified by * the options file. - * @param setSize: number of elements in training set - * basisSize: length of spherical harmonics basis (maybe redundant)*/ + * @param settings config class with global information*/ DataGenerator3D( Config* settings ); ~DataGenerator3D(); @@ -25,8 +24,8 @@ class DataGenerator3D : public DataGeneratorBase void SampleSolutionU() override; /*!< @brief Samples solution vectors u */ // Helper functions - void ComputeMoments() override; /*!< @brief Pre-Compute Moments at all quadrature points. */ - void ComputeSetSize() override; /*!< @brief Computes the size of the training set, depending on the chosen settings.*/ + void ComputeMoments() override; /*!< @brief Pre-Compute Moments at all quadrature points. */ + void ComputeSetSize() override; /*!< @brief Computes the size of the training set, depending on the chosen settings.*/ void CheckRealizability() override; // Debugging helper }; #endif // DATAGENERATOR3D_H diff --git a/code/include/toolboxes/datageneratorbase.h b/code/include/toolboxes/datageneratorbase.h index d1f1e6f..aff3abb 100644 --- a/code/include/toolboxes/datageneratorbase.h +++ b/code/include/toolboxes/datageneratorbase.h @@ -1,5 +1,5 @@ /*! - * \file datagenerator.h + * \file datageneratorbase.h * \brief Class to generate data for the neural entropy closure * \author S. Schotthoefer */ @@ -22,8 +22,7 @@ class DataGeneratorBase /*! @brief Class constructor. Generates training data for neural network approaches using * spherical harmonics and an entropy functional and the quadrature specified by * the options file. - * @param setSize: number of elements in training set - * basisSize: length of spherical harmonics basis (maybe redundant)*/ + * @param settings config class with global information*/ DataGeneratorBase( Config* settings ); ~DataGeneratorBase(); @@ -34,7 +33,7 @@ class DataGeneratorBase /*! @brief computes the training data set. * Realizable set is sampled uniformly. - * Prototype: 1D, u\in[0,100] */ + * Prototype: 1D, u in [0,100] */ void ComputeTrainingData(); inline VectorVector GetuSol() { return _uSol; } /*! @brief Get the computed solution vector uSol */ @@ -44,8 +43,8 @@ class DataGeneratorBase protected: Config* _settings; /*!< @brief config class for global information */ - VectorVector _uSol; /*!< @brief vector with moments. Size: (setSize,basisSize)*/ - VectorVector _alpha; /*!< @brief vector with Lagrange multipliers. Size: (setSize,basisSize)*/ + VectorVector _uSol; /*!< @brief vector with moments. Size: (setSize,basisSize)*/ + VectorVector _alpha; /*!< @brief vector with Lagrange multipliers. Size: (setSize,basisSize)*/ std::vector _hEntropy; /*!< @brief vector with entropy values. Size: (setSize) */ unsigned long _setSize; /*!< @brief Size of the whole training Set */ @@ -53,33 +52,33 @@ class DataGeneratorBase _gridSize; /*!< @brief Size of the grid discretizing moment U0 for higher order sampling (has different uses for different samplers)*/ unsigned short _LMaxDegree; /*!< @brief Max Order of Spherical Harmonics */ - unsigned _nTotalEntries; /*!< @brief Total number of equations in the system */ + unsigned _nTotalEntries; /*!< @brief Total number of equations in the system */ - QuadratureBase* _quadrature; /*!< @brief quadrature to create members below */ - unsigned _nq; /*!< @brief number of quadrature points */ - VectorVector _quadPoints; /*!< @brief quadrature points, dim(_quadPoints) = (_nq,spatialDim) */ - Vector _weights; /*!< @brief quadrature weights, dim(_weights) = (_nq) */ + QuadratureBase* _quadrature; /*!< @brief quadrature to create members below */ + unsigned _nq; /*!< @brief number of quadrature points */ + VectorVector _quadPoints; /*!< @brief quadrature points, dim(_quadPoints) = (_nq,spatialDim) */ + Vector _weights; /*!< @brief quadrature weights, dim(_weights) = (_nq) */ VectorVector _quadPointsSphere; /*!< @brief (my,phi), dim(_quadPoints) = (_nq,2) */ SphericalBase* _basis; /*!< @brief Class to compute and store current spherical harmonics basis */ VectorVector _moments; /*!< @brief Moment Vector pre-computed at each quadrature point: dim= _nq x _nTotalEntries */ NewtonOptimizer* _optimizer; /*!< @brief Class to solve minimal entropy problem */ - EntropyBase* _entropy; /*!< @brief Class to handle entropy functional evaluations */ + EntropyBase* _entropy; /*!< @brief Class to handle entropy functional evaluations */ // Main methods virtual void SampleSolutionU() = 0; /*!< @brief Samples solution vectors u */ - void ComputeEntropyH_dual(); /*!< @brief Compute the entropy functional at (u,alpha) in dual formulation */ - void ComputeEntropyH_primal(); /*!< @brief Compute the entropy functional at (u,alpha) in primal formulation */ - void ComputeRealizableSolution(); /*!< @brief make u the realizable moment to alpha, since Newton has roundoff errors. */ + void ComputeEntropyH_dual(); /*!< @brief Compute the entropy functional at (u,alpha) in dual formulation */ + void ComputeEntropyH_primal(); /*!< @brief Compute the entropy functional at (u,alpha) in primal formulation */ + void ComputeRealizableSolution(); /*!< @brief make u the realizable moment to alpha, since Newton has roundoff errors. */ // IO routines void PrintTrainingData(); /*!< @brief : Print computed training data to csv file and screen */ - void PrintLoadScreen(); /*!< @brief Print screen IO*/ + void PrintLoadScreen(); /*!< @brief Print screen IO*/ // Helper functions virtual void ComputeMoments() = 0; /*!< @brief Pre-Compute Moments at all quadrature points. */ - virtual void CheckRealizability() = 0; // Debugging helper + virtual void CheckRealizability() = 0; /*!< @brief Debugging helper. Will be removed */ virtual void ComputeSetSize() = 0; /*!< @brief Computes the size of the training set, depending on the chosen settings.*/ }; #endif // DATAGENERATOR_H diff --git a/code/include/toolboxes/errormessages.h b/code/include/toolboxes/errormessages.h index 81936b4..597936a 100644 --- a/code/include/toolboxes/errormessages.h +++ b/code/include/toolboxes/errormessages.h @@ -1,11 +1,11 @@ /*! - * \file CRTSNError.h + * \file errormessages.h * \brief Class to handle Error Messages * \author S. Schotthoefer */ -#ifndef CRTSNERROR_H -#define CRTSNERROR_H +#ifndef ERRORMESSAGES_H +#define ERRORMESSAGES_H #include "spdlog/spdlog.h" @@ -106,7 +106,7 @@ class ErrorMessages } }; -#endif // CRTSNERROR_H +#endif // ERRORMESSAGES_H /* Depending on the compiler, define the correct macro to get the current function name */ diff --git a/code/include/toolboxes/sphericalmonomials.h b/code/include/toolboxes/sphericalmonomials.h index 84414a3..6d18a3a 100644 --- a/code/include/toolboxes/sphericalmonomials.h +++ b/code/include/toolboxes/sphericalmonomials.h @@ -90,7 +90,7 @@ class SphericalMonomials : public SphericalBase double Power( double basis, unsigned exponent ); /*! @brief Helper to compute the basis in 1D, 2D or 3D, depending on choice of _spatialDim */ - Vector ComputeSphericalBasis1D( double my ); /*!< @brief Only Z achsis of the 3D case */ + Vector ComputeSphericalBasis1D( double my ); /*!< @brief Only Z achsis of the 3D case */ Vector ComputeSphericalBasis2D( double my, double phi ); /*!< @brief Only X and Y achsis of the 3D case */ Vector ComputeSphericalBasis3D( double my, double phi ); }; diff --git a/code/include/toolboxes/textprocessingtoolbox.h b/code/include/toolboxes/textprocessingtoolbox.h index 3388f9b..8e01a2f 100644 --- a/code/include/toolboxes/textprocessingtoolbox.h +++ b/code/include/toolboxes/textprocessingtoolbox.h @@ -1,8 +1,6 @@ /*! - * \file TextProcessingToolbox.h + * \file textprocessingtoolbox.h * \brief File with helper functions for text processing - * - * */ #ifndef TEXTPROCESSINGTOOLBOX_H diff --git a/code/src/common/config.cpp b/code/src/common/config.cpp index 7fe7c69..29658b1 100644 --- a/code/src/common/config.cpp +++ b/code/src/common/config.cpp @@ -1,5 +1,5 @@ /*! - * \file Config.cpp + * \file config.cpp * \brief Class for different Options in rtsn * \author S. Schotthoefer * @@ -198,7 +198,7 @@ void Config::SetConfigOptions() { /* BEGIN_CONFIG_OPTIONS */ - /*! @par CONFIG_CATEGORY: Problem Definition @ingroup Config */ + /*! @par CONFIG_CATEGORY: Problem Definition \ingroup Config */ /*--- Options related to problem definition and partitioning ---*/ // File Structure related options diff --git a/code/src/common/mesh.cpp b/code/src/common/mesh.cpp index 8f62bb4..93a569f 100644 --- a/code/src/common/mesh.cpp +++ b/code/src/common/mesh.cpp @@ -403,8 +403,8 @@ void Mesh::ReconstructSlopesS( unsigned nq, VectorVector& psiDerX, VectorVector& void Mesh::ReconstructSlopesU( unsigned nq, VectorVector& psiDerX, VectorVector& psiDerY, const VectorVector& psi ) const { double phi; - //VectorVector dPsiMax = std::vector( _numCells, Vector( nq, 0.0 ) ); - //VectorVector dPsiMin = std::vector( _numCells, Vector( nq, 0.0 ) ); + // VectorVector dPsiMax = std::vector( _numCells, Vector( nq, 0.0 ) ); + // VectorVector dPsiMin = std::vector( _numCells, Vector( nq, 0.0 ) ); VectorVector dPsiMax( _numCells, Vector( nq, 0.0 ) ); VectorVector dPsiMin( _numCells, Vector( nq, 0.0 ) ); @@ -434,7 +434,7 @@ void Mesh::ReconstructSlopesU( unsigned nq, VectorVector& psiDerX, VectorVector& for( unsigned l = 0; l < _cellNeighbors[j].size(); ++l ) { // step 2: choose sample points // psiSample[j][k][l] = 0.5 * ( psi[j][k] + psi[_cellNeighbors[j][l]][k] ); // interface central points - psiSample[j][k][l] = psi[j][k] + + psiSample[j][k][l] = psi[j][k] + psiDerX[j][k] * ( _nodes[_cells[j][l]][0] - _cellMidPoints[j][0] ) + psiDerY[j][k] * ( _nodes[_cells[j][l]][1] - _cellMidPoints[j][1] ); // vertex points @@ -457,7 +457,7 @@ void Mesh::ReconstructSlopesU( unsigned nq, VectorVector& psiDerX, VectorVector& psiDerX[j][k] *= phi; psiDerY[j][k] *= phi; */ - + double eps = 1e-6; // version 2: Venkatakrishnan limiter // step 1: calculate psi difference around neighbors and theoretical derivatives by Gauss theorem @@ -471,19 +471,20 @@ void Mesh::ReconstructSlopesU( unsigned nq, VectorVector& psiDerX, VectorVector& for( unsigned l = 0; l < _cellNeighbors[j].size(); ++l ) { // step 2: choose sample points - psiSample[j][k][l] = 10.0 * psiDerX[j][k] * (_cellMidPoints[_cellNeighbors[j][l]][0] - _cellMidPoints[j][0]) + - 10.0 * psiDerY[j][k] * (_cellMidPoints[_cellNeighbors[j][l]][1] - _cellMidPoints[j][1]); + psiSample[j][k][l] = 10.0 * psiDerX[j][k] * ( _cellMidPoints[_cellNeighbors[j][l]][0] - _cellMidPoints[j][0] ) + + 10.0 * psiDerY[j][k] * ( _cellMidPoints[_cellNeighbors[j][l]][1] - _cellMidPoints[j][1] ); // step 3: calculate Phi_ij at sample points if( psiSample[j][k][l] > 0.0 ) { - phiSample[j][k][l] = - (dPsiMax[j][k]*dPsiMax[j][k] + 2.0 * dPsiMax[j][k] * psiSample[j][k][l] + eps)/ - (dPsiMax[j][k]*dPsiMax[j][k] + dPsiMax[j][k] * psiSample[j][k][l] + 2.0 * psiSample[j][k][l] * psiSample[j][k][l] + eps); + phiSample[j][k][l] = + ( dPsiMax[j][k] * dPsiMax[j][k] + 2.0 * dPsiMax[j][k] * psiSample[j][k][l] + eps ) / + ( dPsiMax[j][k] * dPsiMax[j][k] + dPsiMax[j][k] * psiSample[j][k][l] + 2.0 * psiSample[j][k][l] * psiSample[j][k][l] + eps ); } else if( psiSample[j][k][l] < 0.0 ) { - phiSample[j][k][l] = - (dPsiMin[j][k]*dPsiMin[j][k] + 2.0 * dPsiMin[j][k] * psiSample[j][k][l] + eps)/ - (dPsiMin[j][k]*dPsiMin[j][k] + dPsiMin[j][k] * psiSample[j][k][l] + 2.0 * psiSample[j][k][l] * psiSample[j][k][l] + eps);; + phiSample[j][k][l] = + ( dPsiMin[j][k] * dPsiMin[j][k] + 2.0 * dPsiMin[j][k] * psiSample[j][k][l] + eps ) / + ( dPsiMin[j][k] * dPsiMin[j][k] + dPsiMin[j][k] * psiSample[j][k][l] + 2.0 * psiSample[j][k][l] * psiSample[j][k][l] + eps ); + ; } else { phiSample[j][k][l] = 1.0; @@ -492,15 +493,13 @@ void Mesh::ReconstructSlopesU( unsigned nq, VectorVector& psiDerX, VectorVector& // step 4: find minimum limiter function phi phi = min( phiSample[j][k] ); - //phi = fmin( 0.5, abs(phi) ); + // phi = fmin( 0.5, abs(phi) ); // step 5: limit the slope reconstructed from Gauss theorem psiDerX[j][k] *= phi; psiDerY[j][k] *= phi; - } } - } void Mesh::ComputeBounds() { diff --git a/code/src/common/optionstructure.cpp b/code/src/common/optionstructure.cpp index ac39e7f..048fa15 100644 --- a/code/src/common/optionstructure.cpp +++ b/code/src/common/optionstructure.cpp @@ -1,5 +1,5 @@ /*! - * \file Config.cpp + * \file config.cpp * \brief Classes for different Optiontypes in rtsn * \author S. Schotthoefer * diff --git a/code/src/problems/linesource.cpp b/code/src/problems/linesource.cpp index 7678f12..8c257dc 100644 --- a/code/src/problems/linesource.cpp +++ b/code/src/problems/linesource.cpp @@ -163,7 +163,6 @@ Vector LineSource_SN_Pseudo1D_Physics::GetTotalXSE( const Vector& energies ) { r // ---- LineSource_PN ---- - LineSource_PN::LineSource_PN( Config* settings, Mesh* mesh ) : LineSource( settings, mesh ) {} LineSource_PN::~LineSource_PN() {} diff --git a/code/src/toolboxes/datageneratorbase.cpp b/code/src/toolboxes/datageneratorbase.cpp index daa28a5..e48ff2b 100644 --- a/code/src/toolboxes/datageneratorbase.cpp +++ b/code/src/toolboxes/datageneratorbase.cpp @@ -1,5 +1,5 @@ /*! - * \file datagenerator.cpp + * \file datageneratorbase.cpp * \brief Class to generate data for the neural entropy closure * \author S. Schotthoefer */ diff --git a/code/src/toolboxes/sphericalharmonics.cpp b/code/src/toolboxes/sphericalharmonics.cpp index e6b4745..c0f7336 100644 --- a/code/src/toolboxes/sphericalharmonics.cpp +++ b/code/src/toolboxes/sphericalharmonics.cpp @@ -130,5 +130,4 @@ void SphericalHarmonics::ComputeYBasis( const double phi ) { _YBasis[GetGlobalIndexBasis( l_idx, k_idx )] = _assLegendreP[GlobalIdxAssLegendreP( l_idx, k_idx )] * c; } } - } diff --git a/doc/common/mesh.rst b/doc/common/mesh.rst index 5a01740..81cbdd8 100644 --- a/doc/common/mesh.rst +++ b/doc/common/mesh.rst @@ -3,3 +3,6 @@ Mesh .. doxygenclass:: Mesh :members: + :protected-members: + :private-members: + diff --git a/doc/entropies/entropybase.rst b/doc/entropies/entropybase.rst index 5bf20b0..9e12724 100644 --- a/doc/entropies/entropybase.rst +++ b/doc/entropies/entropybase.rst @@ -3,3 +3,5 @@ EntropyBase .. doxygenclass:: EntropyBase :members: + :protected-members: + :private-members: diff --git a/doc/entropies/maxwellboltzmannentropy.rst b/doc/entropies/maxwellboltzmannentropy.rst index afe7edd..499442e 100644 --- a/doc/entropies/maxwellboltzmannentropy.rst +++ b/doc/entropies/maxwellboltzmannentropy.rst @@ -3,3 +3,5 @@ MaxwellBoltzmannEntropy .. doxygenclass:: MaxwellBoltzmannEntropy :members: + :protected-members: + :private-members: diff --git a/doc/entropies/quadraticentropy.rst b/doc/entropies/quadraticentropy.rst index 643efaf..1224c44 100644 --- a/doc/entropies/quadraticentropy.rst +++ b/doc/entropies/quadraticentropy.rst @@ -3,3 +3,5 @@ QuadraticEntropy .. doxygenclass:: QuadraticEntropy :members: + :protected-members: + :private-members: diff --git a/doc/fluxes/laxfriedrichsflux.rst b/doc/fluxes/laxfriedrichsflux.rst index 51373de..fba3789 100644 --- a/doc/fluxes/laxfriedrichsflux.rst +++ b/doc/fluxes/laxfriedrichsflux.rst @@ -3,3 +3,5 @@ LaxFriedrichsFlux .. doxygenclass:: LaxFriedrichsFlux :members: + :protected-members: + :private-members: diff --git a/doc/fluxes/numericalflux.rst b/doc/fluxes/numericalflux.rst index 5cbf947..b765bc1 100644 --- a/doc/fluxes/numericalflux.rst +++ b/doc/fluxes/numericalflux.rst @@ -3,3 +3,5 @@ NumericalFlux .. doxygenclass:: NumericalFlux :members: + :protected-members: + :private-members: diff --git a/doc/fluxes/upwindflux.rst b/doc/fluxes/upwindflux.rst index 48d9d35..b9d6f1e 100644 --- a/doc/fluxes/upwindflux.rst +++ b/doc/fluxes/upwindflux.rst @@ -3,3 +3,5 @@ UpwindFlux .. doxygenclass:: UpwindFlux :members: + :protected-members: + :private-members: diff --git a/doc/kernels/isotropic.rst b/doc/kernels/isotropic.rst index fa77e61..d1ababd 100644 --- a/doc/kernels/isotropic.rst +++ b/doc/kernels/isotropic.rst @@ -3,3 +3,5 @@ Isotropic .. doxygenclass:: Isotropic :members: + :protected-members: + :private-members: diff --git a/doc/kernels/isotropic1D.rst b/doc/kernels/isotropic1D.rst index 5ab7cf1..d113bde 100644 --- a/doc/kernels/isotropic1D.rst +++ b/doc/kernels/isotropic1D.rst @@ -3,3 +3,5 @@ Isotropic1D .. doxygenclass:: Isotropic1D :members: + :protected-members: + :private-members: diff --git a/doc/kernels/scatteringkernel.rst b/doc/kernels/scatteringkernel.rst index 50037ed..2fb1ad0 100644 --- a/doc/kernels/scatteringkernel.rst +++ b/doc/kernels/scatteringkernel.rst @@ -3,3 +3,5 @@ ScatteringKernel .. doxygenclass:: ScatteringKernel :members: + :protected-members: + :private-members: diff --git a/doc/optimizers/mloptimizer.rst b/doc/optimizers/mloptimizer.rst index b6e7e82..f3ce06d 100644 --- a/doc/optimizers/mloptimizer.rst +++ b/doc/optimizers/mloptimizer.rst @@ -3,3 +3,5 @@ MLOptimizer .. doxygenclass:: MLOptimizer :members: + :protected-members: + :private-members: diff --git a/doc/optimizers/newtonoptimizer.rst b/doc/optimizers/newtonoptimizer.rst index 6ea3e8f..d639d53 100644 --- a/doc/optimizers/newtonoptimizer.rst +++ b/doc/optimizers/newtonoptimizer.rst @@ -3,3 +3,5 @@ NewtonOptimizer .. doxygenclass:: NewtonOptimizer :members: + :protected-members: + :private-members: diff --git a/doc/optimizers/optimizerbase.rst b/doc/optimizers/optimizerbase.rst index 83e902d..9f648fc 100644 --- a/doc/optimizers/optimizerbase.rst +++ b/doc/optimizers/optimizerbase.rst @@ -3,3 +3,5 @@ OptimizerBase .. doxygenclass:: OptimizerBase :members: + :protected-members: + :private-members: diff --git a/doc/problems/aircavity1d.rst b/doc/problems/aircavity1d.rst index 2e295be..dbd1a7c 100644 --- a/doc/problems/aircavity1d.rst +++ b/doc/problems/aircavity1d.rst @@ -3,3 +3,5 @@ AirCavity1D .. doxygenclass:: AirCavity1D :members: + :protected-members: + :private-members: diff --git a/doc/problems/checkerboardpn.rst b/doc/problems/checkerboardpn.rst index d7a3535..c702699 100644 --- a/doc/problems/checkerboardpn.rst +++ b/doc/problems/checkerboardpn.rst @@ -3,3 +3,5 @@ Checkerboard_PN .. doxygenclass:: Checkerboard_PN :members: + :protected-members: + :private-members: diff --git a/doc/problems/checkerboardsn.rst b/doc/problems/checkerboardsn.rst index dde91b4..ef0141e 100644 --- a/doc/problems/checkerboardsn.rst +++ b/doc/problems/checkerboardsn.rst @@ -3,3 +3,5 @@ Checkerboard_SN .. doxygenclass:: Checkerboard_SN :members: + :protected-members: + :private-members: diff --git a/doc/problems/electronrt.rst b/doc/problems/electronrt.rst index 1cdfc63..c6f514f 100644 --- a/doc/problems/electronrt.rst +++ b/doc/problems/electronrt.rst @@ -3,3 +3,5 @@ ElectronRT .. doxygenclass:: ElectronRT :members: + :protected-members: + :private-members: diff --git a/doc/problems/icru.rst b/doc/problems/icru.rst index 1094a7a..7959a63 100644 --- a/doc/problems/icru.rst +++ b/doc/problems/icru.rst @@ -3,3 +3,5 @@ ICRU .. doxygenclass:: ICRU :members: + :protected-members: + :private-members: diff --git a/doc/problems/linesource.rst b/doc/problems/linesource.rst index 0fbf744..54ff448 100644 --- a/doc/problems/linesource.rst +++ b/doc/problems/linesource.rst @@ -3,3 +3,5 @@ LineSource .. doxygenclass:: LineSource :members: + :protected-members: + :private-members: diff --git a/doc/problems/linesourcepn.rst b/doc/problems/linesourcepn.rst index b1edbe6..ecd74a2 100644 --- a/doc/problems/linesourcepn.rst +++ b/doc/problems/linesourcepn.rst @@ -3,3 +3,5 @@ LineSource_PN .. doxygenclass:: LineSource_PN :members: + :protected-members: + :private-members: diff --git a/doc/problems/linesourcesn.rst b/doc/problems/linesourcesn.rst index 31b35ac..d23c4a9 100644 --- a/doc/problems/linesourcesn.rst +++ b/doc/problems/linesourcesn.rst @@ -3,3 +3,5 @@ LineSource_SN .. doxygenclass:: LineSource_SN :members: + :protected-members: + :private-members: diff --git a/doc/problems/linesourcesnpseudo1d.rst b/doc/problems/linesourcesnpseudo1d.rst index e152d59..f30a0c6 100644 --- a/doc/problems/linesourcesnpseudo1d.rst +++ b/doc/problems/linesourcesnpseudo1d.rst @@ -3,3 +3,5 @@ LineSource_SN_Pseudo1D .. doxygenclass:: LineSource_SN_Pseudo1D :members: + :protected-members: + :private-members: diff --git a/doc/problems/linesourcesnpseudo1dphysics.rst b/doc/problems/linesourcesnpseudo1dphysics.rst index 16a6ed7..5a19bcf 100644 --- a/doc/problems/linesourcesnpseudo1dphysics.rst +++ b/doc/problems/linesourcesnpseudo1dphysics.rst @@ -3,3 +3,5 @@ LineSource_SN_Pseudo1D_Physics .. doxygenclass:: LineSource_SN_Pseudo1D_Physics :members: + :protected-members: + :private-members: diff --git a/doc/problems/musclebonelung.rst b/doc/problems/musclebonelung.rst index b824b1f..1670a40 100644 --- a/doc/problems/musclebonelung.rst +++ b/doc/problems/musclebonelung.rst @@ -3,3 +3,5 @@ MuscleBoneLung .. doxygenclass:: MuscleBoneLung :members: + :protected-members: + :private-members: diff --git a/doc/problems/phantom2d.rst b/doc/problems/phantom2d.rst index e98bfbd..00084d7 100644 --- a/doc/problems/phantom2d.rst +++ b/doc/problems/phantom2d.rst @@ -3,3 +3,5 @@ Phantom2D .. doxygenclass:: Phantom2D :members: + :protected-members: + :private-members: diff --git a/doc/problems/problembase.rst b/doc/problems/problembase.rst index e99e68a..817e5be 100644 --- a/doc/problems/problembase.rst +++ b/doc/problems/problembase.rst @@ -3,3 +3,5 @@ ProblemBase .. doxygenclass:: ProblemBase :members: + :protected-members: + :private-members: diff --git a/doc/problems/slabgeohg.rst b/doc/problems/slabgeohg.rst index ec36edb..efae7d9 100644 --- a/doc/problems/slabgeohg.rst +++ b/doc/problems/slabgeohg.rst @@ -3,3 +3,5 @@ SlabGeoHG .. doxygenclass:: SlabGeoHG :members: + :protected-members: + :private-members: diff --git a/doc/problems/waterphantom.rst b/doc/problems/waterphantom.rst index 3084ff5..b89fa5c 100644 --- a/doc/problems/waterphantom.rst +++ b/doc/problems/waterphantom.rst @@ -3,3 +3,5 @@ WaterPhantom .. doxygenclass:: WaterPhantom :members: + :protected-members: + :private-members: diff --git a/doc/quadratures/qgausslegendre1D.rst b/doc/quadratures/qgausslegendre1D.rst index 384e4c6..34858cc 100644 --- a/doc/quadratures/qgausslegendre1D.rst +++ b/doc/quadratures/qgausslegendre1D.rst @@ -3,3 +3,5 @@ QGaussLegendre1D .. doxygenclass:: QGaussLegendre1D :members: + :protected-members: + :private-members: diff --git a/doc/quadratures/qgausslegendretensorized.rst b/doc/quadratures/qgausslegendretensorized.rst index 3998595..8dd1432 100644 --- a/doc/quadratures/qgausslegendretensorized.rst +++ b/doc/quadratures/qgausslegendretensorized.rst @@ -3,3 +3,5 @@ QGaussLegendreTensorized .. doxygenclass:: QGaussLegendreTensorized :members: + :protected-members: + :private-members: diff --git a/doc/quadratures/qldfesa.rst b/doc/quadratures/qldfesa.rst index eedea39..8859bc2 100644 --- a/doc/quadratures/qldfesa.rst +++ b/doc/quadratures/qldfesa.rst @@ -3,3 +3,5 @@ QLDFESA .. doxygenclass:: QLDFESA :members: + :protected-members: + :private-members: diff --git a/doc/quadratures/qlebedev.rst b/doc/quadratures/qlebedev.rst index 123e6b4..6e5b424 100644 --- a/doc/quadratures/qlebedev.rst +++ b/doc/quadratures/qlebedev.rst @@ -3,3 +3,5 @@ QLebedev .. doxygenclass:: QLebedev :members: + :protected-members: + :private-members: diff --git a/doc/quadratures/qlevelsymmetric.rst b/doc/quadratures/qlevelsymmetric.rst index ef6c46f..c6f7ddd 100644 --- a/doc/quadratures/qlevelsymmetric.rst +++ b/doc/quadratures/qlevelsymmetric.rst @@ -3,3 +3,5 @@ QLevelSymmetric .. doxygenclass:: QLevelSymmetric :members: + :protected-members: + :private-members: diff --git a/doc/quadratures/qlookupquadrature.rst b/doc/quadratures/qlookupquadrature.rst index 1b430e9..55bb5a1 100644 --- a/doc/quadratures/qlookupquadrature.rst +++ b/doc/quadratures/qlookupquadrature.rst @@ -3,3 +3,5 @@ QLookupQuadrature .. doxygenclass:: QLookupQuadrature :members: + :protected-members: + :private-members: diff --git a/doc/quadratures/qmontecarlo.rst b/doc/quadratures/qmontecarlo.rst index 1252566..2c448dc 100644 --- a/doc/quadratures/qmontecarlo.rst +++ b/doc/quadratures/qmontecarlo.rst @@ -3,3 +3,5 @@ QMonteCarlo .. doxygenclass:: QMonteCarlo :members: + :protected-members: + :private-members: diff --git a/doc/quadratures/qproduct.rst b/doc/quadratures/qproduct.rst index 039fffc..c8ed8ab 100644 --- a/doc/quadratures/qproduct.rst +++ b/doc/quadratures/qproduct.rst @@ -3,3 +3,5 @@ QProduct .. doxygenclass:: QProduct :members: + :protected-members: + :private-members: diff --git a/doc/quadratures/quadraturebase.rst b/doc/quadratures/quadraturebase.rst index cffd8f0..16710be 100644 --- a/doc/quadratures/quadraturebase.rst +++ b/doc/quadratures/quadraturebase.rst @@ -3,3 +3,5 @@ QuadratureBase .. doxygenclass:: QuadratureBase :members: + :protected-members: + :private-members: diff --git a/doc/solvers/csdsnsolver.rst b/doc/solvers/csdsnsolver.rst index e8324bc..a348387 100644 --- a/doc/solvers/csdsnsolver.rst +++ b/doc/solvers/csdsnsolver.rst @@ -3,3 +3,5 @@ CSDSNSolver .. doxygenclass:: CSDSNSolver :members: + :protected-members: + :private-members: diff --git a/doc/solvers/csdsnsolverfp.rst b/doc/solvers/csdsnsolverfp.rst index f666f23..5d88347 100644 --- a/doc/solvers/csdsnsolverfp.rst +++ b/doc/solvers/csdsnsolverfp.rst @@ -3,4 +3,5 @@ CSDSNSolverFP .. doxygenclass:: CSDSNSolverFP :members: - + :protected-members: + :private-members: diff --git a/doc/solvers/csdsnsolvernotrafo.rst b/doc/solvers/csdsnsolvernotrafo.rst index e44332f..44597e8 100644 --- a/doc/solvers/csdsnsolvernotrafo.rst +++ b/doc/solvers/csdsnsolvernotrafo.rst @@ -3,3 +3,5 @@ CSDSNSolverNoTrafo .. doxygenclass:: CSDSNSolverNoTrafo :members: + :protected-members: + :private-members: diff --git a/doc/solvers/csdsolvertrafofp.rst b/doc/solvers/csdsolvertrafofp.rst index ca81643..fa88fb3 100644 --- a/doc/solvers/csdsolvertrafofp.rst +++ b/doc/solvers/csdsolvertrafofp.rst @@ -3,3 +3,5 @@ CSDSolverTrafoFP .. doxygenclass:: CSDSolverTrafoFP :members: + :protected-members: + :private-members: diff --git a/doc/solvers/csdsolvertrafofp2d.rst b/doc/solvers/csdsolvertrafofp2d.rst index 4c2752c..e9c013f 100644 --- a/doc/solvers/csdsolvertrafofp2d.rst +++ b/doc/solvers/csdsolvertrafofp2d.rst @@ -3,3 +3,5 @@ CSDSolverTrafoFP2D .. doxygenclass:: CSDSolverTrafoFP2D :members: + :protected-members: + :private-members: diff --git a/doc/solvers/snsolvermpi.rst b/doc/solvers/snsolvermpi.rst index 176f519..4b6895c 100644 --- a/doc/solvers/snsolvermpi.rst +++ b/doc/solvers/snsolvermpi.rst @@ -3,3 +3,5 @@ SNSolverMPI .. doxygenclass:: SNSolverMPI :members: + :protected-members: + :private-members: diff --git a/doc/toolboxes/errormessages.rst b/doc/toolboxes/errormessages.rst index 9d05d5a..8dbe403 100644 --- a/doc/toolboxes/errormessages.rst +++ b/doc/toolboxes/errormessages.rst @@ -3,3 +3,5 @@ ErrorMessages .. doxygenclass:: ErrorMessages :members: + :protected-members: + :private-members: diff --git a/doc/toolboxes/interpolation.rst b/doc/toolboxes/interpolation.rst index 9877c13..a03740a 100644 --- a/doc/toolboxes/interpolation.rst +++ b/doc/toolboxes/interpolation.rst @@ -3,3 +3,5 @@ Interpolation .. doxygenclass:: Interpolation :members: + :protected-members: + :private-members: diff --git a/doc/toolboxes/physics.rst b/doc/toolboxes/physics.rst index ddb7116..8ce04b4 100644 --- a/doc/toolboxes/physics.rst +++ b/doc/toolboxes/physics.rst @@ -3,3 +3,5 @@ Physics .. doxygenclass:: Physics :members: + :protected-members: + :private-members: diff --git a/doc/toolboxes/reconstructor.rst b/doc/toolboxes/reconstructor.rst index 69a5518..7231c44 100644 --- a/doc/toolboxes/reconstructor.rst +++ b/doc/toolboxes/reconstructor.rst @@ -3,3 +3,5 @@ Reconstructor .. doxygenclass:: Reconstructor :members: + :protected-members: + :private-members: diff --git a/doc/toolboxes/sphericalharmonics.rst b/doc/toolboxes/sphericalharmonics.rst index 071bcf9..92db111 100644 --- a/doc/toolboxes/sphericalharmonics.rst +++ b/doc/toolboxes/sphericalharmonics.rst @@ -3,3 +3,5 @@ SphericalHamonics .. doxygenclass:: SphericalHarmonics :members: + :protected-members: + :private-members: -- GitLab From 218f3f712089047100e06d6da92111f1dd821dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Fri, 26 Feb 2021 16:24:47 +0100 Subject: [PATCH 36/67] more documentation Former-commit-id: 2c0555989afb9300769627ece3743240cac09620 --- code/include/problems/checkerboard.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/include/problems/checkerboard.h b/code/include/problems/checkerboard.h index 629873a..f521b6b 100644 --- a/code/include/problems/checkerboard.h +++ b/code/include/problems/checkerboard.h @@ -35,13 +35,13 @@ class Checkerboard_PN : public ProblemBase bool isAbsorption( const Vector& pos ) const; /*!< @return True if pos is in absorption region, False otherwise */ bool isSource( const Vector& pos ) const; /*!< @return True if pos is in source region, False otherwise */ - /** + /*! * @brief Gets the global index for given order l of Legendre polynomials and given * order k of Legendre functions. * Note: This is code doubling from PNSolver::GlobalIndex - * @param l : order of Legendre polynomial - * @param k : order of Legendre function - * @returns global index + * @param l order of Legendre polynomial + * @param k order of Legendre function + * @returns globalIndex */ int GlobalIndex( int l, int k ) const; -- GitLab From 60a445608ad01ef52fa045cd433dbc90a7ef80b4 Mon Sep 17 00:00:00 2001 From: Jannick Wolters Date: Fri, 26 Feb 2021 16:42:02 +0100 Subject: [PATCH 37/67] purged parmetis Former-commit-id: d420677c6b9c4069638939d312e2e3ec5701a909 --- .gitmodules | 3 - code/CMakeLists.txt | 9 +-- code/ext/parmetis | 1 - code/include/common/mesh.h | 8 --- code/src/common/mesh.cpp | 138 ------------------------------------- 5 files changed, 1 insertion(+), 158 deletions(-) delete mode 160000 code/ext/parmetis diff --git a/.gitmodules b/.gitmodules index a55e5ce..b00681c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,9 +7,6 @@ [submodule "code/ext/blaze"] path = code/ext/blaze url = https://bitbucket.org/blaze-lib/blaze.git -[submodule "code/ext/parmetis"] - path = code/ext/parmetis - url = https://github.com/slydex/parmetis.git [submodule "code/ext/neuralEntropy"] path = code/ext/neuralEntropy url = https://github.com/ScSteffen/neuralEntropy.git diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 2d787c8..3bd8355 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -49,17 +49,10 @@ endif() include( blaze-cache-config ) include_directories( ${CMAKE_SOURCE_DIR}/ext/blaze ) -add_compile_definitions( METIS_EXPORT= ) -set( DISABLE_PARMETIS_PROGRAMS ON ) -set( ParMETIS_PATH ${CMAKE_CURRENT_SOURCE_DIR}/ext/parmetis ) -include_directories( ${ParMETIS_PATH}/include ) -include_directories( ${ParMETIS_PATH}/metis/include ) -add_subdirectory( ${ParMETIS_PATH} ) - include_directories( ${CMAKE_SOURCE_DIR}/ext/cpptoml/include ) include_directories( ${CMAKE_SOURCE_DIR}/ext/spdlog/include ) -set( CORE_LIBRARIES ${Python3_LIBRARIES} ${LAPACK_LIBRARIES} ${BLAS_LIBRARIES} ${MPI_LIBRARIES} ${VTK_LIBRARIES} OpenMP::OpenMP_CXX parmetis -lstdc++fs ) +set( CORE_LIBRARIES ${Python3_LIBRARIES} ${LAPACK_LIBRARIES} ${BLAS_LIBRARIES} ${MPI_LIBRARIES} ${VTK_LIBRARIES} OpenMP::OpenMP_CXX -lstdc++fs ) ################################################# diff --git a/code/ext/parmetis b/code/ext/parmetis deleted file mode 160000 index 263c94a..0000000 --- a/code/ext/parmetis +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 263c94a262be616484b0bbeb33a6677411f25fbb diff --git a/code/include/common/mesh.h b/code/include/common/mesh.h index 0f15c1a..b83f23c 100644 --- a/code/include/common/mesh.h +++ b/code/include/common/mesh.h @@ -10,8 +10,6 @@ #include #include -#include "metis.h" -#include "parmetis.h" #include "toolboxes/errormessages.h" #include "toolboxes/reconstructor.h" @@ -42,13 +40,11 @@ class Mesh std::vector> _cellNormals; /*! @brief Tags each cell with its boundary type. None means no boundary. dimension: numCells */ std::vector _cellBoundaryTypes; - std::vector _colors; /*!< @brief Color of each cell (for MPI mesh partitioning). dimension: numCells */ blaze::CompressedMatrix _nodeNeighbors; /*!< @brief neighborshood relationship of nodes for (par-)metis */ void ComputeCellAreas(); /*!< @brief Computes only the areas of the mesh cells. Write to _cellAreas. */ void ComputeCellMidpoints(); /*!< @brief Compute only the midpoints of the cells. Write to _cellMidPoints*/ void ComputeConnectivity(); /*!< @brief Computes _cellNeighbors and _nodeNeighbors, i.e. neighborship relation in mesh*/ - void ComputePartitioning(); /*!< @brief Computes local partitioning for openMP */ /*! @brief Computes outward facing normal of two neighboring nodes nodeA and nodeB with common cellCellcenter. * Normals are scaled with their respective edge length @@ -90,10 +86,6 @@ class Mesh * @return dimension: numCells */ const std::vector& GetCellAreas() const; - /*! @brief Return the color/ID of the mesh partition - * @return dimension: numCells */ - const std::vector& GetPartitionIDs() const; - /*! @brief Returns the neighbor cell IDs for every cell * @return dimension: numCells x numNodes */ const std::vector>& GetNeighbours() const; diff --git a/code/src/common/mesh.cpp b/code/src/common/mesh.cpp index 93a569f..ba56486 100644 --- a/code/src/common/mesh.cpp +++ b/code/src/common/mesh.cpp @@ -17,7 +17,6 @@ Mesh::Mesh( std::vector nodes, ComputeCellAreas(); ComputeCellMidpoints(); ComputeConnectivity(); - // ComputePartitioning(); ComputeBounds(); } @@ -219,142 +218,6 @@ Vector Mesh::ComputeOutwardFacingNormal( const Vector& nodeA, const Vector& node return n; } -void Mesh::ComputePartitioning() { - int comm_size, comm_rank; - MPI_Comm comm = MPI_COMM_WORLD; - MPI_Comm_size( comm, &comm_size ); - MPI_Comm_rank( comm, &comm_rank ); - unsigned ompNumThreads = omp_get_max_threads(); - - // only run coloring if multiple OpenMP threads are present - if( ompNumThreads > 1 ) { - // setup adjacency relationship of nodes - blaze::CompressedMatrix adjMatrix( _numNodes, _numNodes ); - for( unsigned i = 0; i < _numNodes; ++i ) { - for( unsigned j = 0; j < _numCells; ++j ) { - for( unsigned k = 0; k < _numNodesPerCell; ++k ) { - if( i == _cells[j][k] ) { - if( k == 0 ) { - adjMatrix.set( i, _cells[j][_numNodesPerCell - 1], true ); - adjMatrix.set( i, _cells[j][1], true ); - } - else if( k == _numNodesPerCell - 1 ) { - adjMatrix.set( i, _cells[j][_numNodesPerCell - 2], true ); - adjMatrix.set( i, _cells[j][0], true ); - } - else { - adjMatrix.set( i, _cells[j][k - 1], true ); - adjMatrix.set( i, _cells[j][k + 1], true ); - } - } - } - } - } - - // for xadj and adjncy structure see parmetis documentation - std::vector xadj( _numNodes + 1 ); - int ctr = 0; - std::vector adjncy; - for( unsigned i = 0; i < _numNodes; ++i ) { - xadj[i] = ctr; - for( unsigned j = 0; j < _numNodes; ++j ) { - if( adjMatrix( i, j ) ) { - adjncy.push_back( static_cast( j ) ); - ctr++; - } - } - } - xadj[_numNodes] = ctr; - - std::vector partitions; - int edgecut = 0; - int ncon = 1; - int nparts = ompNumThreads; - real_t ubvec = static_cast( 1.05 ); // parameter taken from SU2 - - if( comm_size > 1 ) { // if multiple MPI threads -> use parmetis - // split adjacency information for each MPI thread -> see 'local' variables - std::vector local_xadj{ 0 }; - unsigned xadjChunk = std::ceil( static_cast( _numNodes ) / static_cast( comm_size ) ); - unsigned xadjStart = comm_rank * xadjChunk + 1; - unsigned adjncyStart; - for( unsigned i = 0; i < xadjChunk; ++i ) { - if( i == 0 ) adjncyStart = xadj[i + xadjStart - 1]; - local_xadj.push_back( xadj[i + xadjStart] ); - } - unsigned adjncyEnd = local_xadj.back(); - for( unsigned i = 1; i < local_xadj.size(); ++i ) { - local_xadj[i] -= xadj[xadjStart - 1]; - } - std::vector local_adjncy( adjncy.begin() + adjncyStart, adjncy.begin() + adjncyEnd ); - - // vtxdist describes what nodes are on which processor - see parmetis doc - std::vector vtxdist{ 0 }; - for( unsigned i = 1; i <= static_cast( comm_size ); i++ ) { - vtxdist.push_back( std::min( i * xadjChunk, _numNodes ) ); - } - - // weights setup set as in SU2 - real_t* tpwgts = new real_t[nparts]; - for( unsigned i = 0; i < static_cast( nparts ); ++i ) { - tpwgts[i] = 1.0 / static_cast( nparts ); - } - - // setup as in SU2 - int wgtflag = 0; - int numflag = 0; - int options[1]; - options[0] = 0; - - unsigned chunkSize = local_xadj.size() - 1; - int* part = new int[chunkSize]; - ParMETIS_V3_PartKway( vtxdist.data(), - local_xadj.data(), - local_adjncy.data(), - nullptr, - nullptr, - &wgtflag, - &numflag, - &ncon, - &nparts, - tpwgts, - &ubvec, - options, - &edgecut, - part, - &comm ); - partitions.resize( chunkSize * comm_size ); - MPI_Allgather( part, chunkSize, MPI_INT, partitions.data(), chunkSize, MPI_INT, comm ); // gather all information in partitions - partitions.resize( _numNodes ); - - // free memory - delete[] tpwgts; - } - else { // with a singular MPI thread -> use metis - int options[METIS_NOPTIONS]; - METIS_SetDefaultOptions( options ); - int nvtxs = _numNodes; - int vsize; - partitions.resize( _numNodes ); - METIS_PartGraphKway( - &nvtxs, &ncon, xadj.data(), adjncy.data(), nullptr, &vsize, nullptr, &nparts, nullptr, &ubvec, options, &edgecut, partitions.data() ); - } - - // extract coloring information - _colors.resize( _numCells ); - for( unsigned i = 0; i < _numCells; ++i ) { - std::map occurances; - for( unsigned j = 0; j < _numNodesPerCell; ++j ) { - ++occurances[partitions[_cells[i][j]]]; - } - _colors[i] = occurances.rbegin()->first; - } - } - else { - _colors.resize( _numCells, 0u ); - } -} - void Mesh::ComputeSlopes( unsigned nq, VectorVector& psiDerX, VectorVector& psiDerY, const VectorVector& psi ) const { for( unsigned k = 0; k < nq; ++k ) { for( unsigned j = 0; j < _numCells; ++j ) { @@ -516,7 +379,6 @@ const std::vector& Mesh::GetNodes() const { return _nodes; } const std::vector& Mesh::GetCellMidPoints() const { return _cellMidPoints; } const std::vector>& Mesh::GetCells() const { return _cells; } const std::vector& Mesh::GetCellAreas() const { return _cellAreas; } -const std::vector& Mesh::GetPartitionIDs() const { return _colors; } const std::vector>& Mesh::GetNeighbours() const { return _cellNeighbors; } const std::vector>& Mesh::GetNormals() const { return _cellNormals; } const std::vector& Mesh::GetBoundaryTypes() const { return _cellBoundaryTypes; } -- GitLab From d01a0c7d926fc3d887fffb4262c96d46b436f131 Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 16:46:58 +0100 Subject: [PATCH 38/67] Add fvm implementation doc Former-commit-id: 63dfbaf9021eb4cbb2a5f2198fba162e3af1c0b5 --- doc/implement.rst | 152 +++++++--------------------------------------- 1 file changed, 21 insertions(+), 131 deletions(-) diff --git a/doc/implement.rst b/doc/implement.rst index f6bf486..75d4ff3 100644 --- a/doc/implement.rst +++ b/doc/implement.rst @@ -1,144 +1,34 @@ .. _implementation: -Implementation +Finite volume method ------------------------ -***** -Build -***** -Required dependencies -===================== - - Compiler with C++17 support - - cmake >= v3.12.4 - - LAPACK - - OpenMP - - MPI - - VTK - - git - - ninja or make +In the KiT-RT, we employ the finite volume method (FVM) to model and compute the particle evolutions. +It's a generic method for conservation laws. +Consider the following PDE, -Obtain submodules -================== -Note that an **active internet connection is required for the first build** in order to download the latest versions of the required submodules! -For the first build only, download all submodules: +.. math:: + + \frac{\partial \mathbf{u}}{\partial t}+\nabla \cdot \mathbf{f}(\mathbf{u})=\mathbf{0} -.. code-block:: bash +Here, :math:`\mathbf{u}` represents any vector of states and +:math:`\mathbf{f}` represents the corresponding flux tensor. +To solve the equation numerically, we can sub-divide the spatial domain into finite cells. +For a particular cell :math:`i`, we take the volume integral over the total volume of the cell, which gives, - git submodule update --init --recursive +.. math:: + + \int_{v_{i}} \frac{\partial \mathbf{u}}{\partial t} d v+\int_{v_{i}} \nabla \cdot \mathbf{f}(\mathbf{u}) d v=\mathbf{0}. -Compile the code -================ -**Make** build system (available on most systems) - - -.. code-block:: bash +On integrating the first term to get the volume average and applying the divergence theorem to the second, this yields - cd code/build/release - cmake -DCMAKE_BUILD_TYPE=Release ../../ - make - -If building in parallel is desired, change the last line to `make -jN`, where `N` optimally is equal to the number of available threads+1. - -**Ninja** build system: - -.. code-block:: bash - - cd code/build/release - cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ../../ - ninja - - - -The resulting executable will automatically be placed in the `code/bin` folder. - ----------------------------------------------------------- - -********** -Run -********** - -Local -=========== - -Execute the compiled binary from the `bin` folder and hand over a valid *TOML*-styled config file. -Example from inside the `code` directory: - -```bash -./KiT-RT ../input/example.cfg -``` - -In order to run the code in parallel execute: - -```bash -OMP_NUM_THREADS=N mpirun -np J ./KiT-RT ../input/example.cfg -``` - -with `N` equal to the number of shared memory threads and `J` equal to the number of distrubuted memory threads. - -BwUniCluster -============== - -As VTK is not available on the bwUniCluster, it needs to be installed first. This just needs to be done once. Example: - -.. code-block:: bash - - module load devel/cmake/3.16 - module load compiler/gnu/9.2 - wget --no-check-certificate --quiet https://www.vtk.org/files/release/8.2/VTK-8.2.0.tar.gz - tar xzf VTK-8.2.0.tar.gz - mkdir VTK-build - cd VTK-build - cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_DOCUMENTATION=OFF -DBUILD_TESTING=OFF - - DCMAKE_INSTALL_PREFIX=~/VTK-install ../VTK-8.2.0 - make -j - make install - cd - - rm -r VTK-8.2.0 VTK-build - - -Example for build and run on bwUniCluster: -Get the code - -.. code-block:: bash - - git clone https://git.scc.kit.edu/rtsn/rtsn.git KiT-RT - cd KiT-RT/ - git submodule init - git submodule update - -Append ``HINTS VTK_INSTALL_DIR` to the ``find_package( VTK ... )`` line in the CMakeLists.txt. E.g.: - -.. code-block:: bash - - find_package( VTK REQUIRED COMPONENTS vtkIOGeometry vtkFiltersCore HINTS ~/VTK-install ) - - -Compile it - -.. code-block:: bash - - module load devel/cmake/3.16 - module load compiler/gnu/9.2 - module load mpi/openmpi/4.0 - cd code/build/release/ - cmake -DCMAKE_BUILD_TYPE=Release ../../ - make -j - - ---------------------------------------------------------------- - -Tests -============================ - -After compiling the framework as described above just run: - -.. code-block:: bash - - make test - - -The ``unit_tests`` executable will also be placed in in the build folder. +.. math:: + v_{i} \frac{d \overline{\mathbf{u}}_{i}}{d t}+\oint_{S_{i}} \mathbf{f}(\mathbf{u}) \cdot \mathbf{n} d S=\mathbf{0}, +where :math:`S_i` represents the total surface area of the cell and :math:`\mathbf n` is a unit vector normal to the surface and pointing outward. +The equivalent formulation results +.. math:: + \frac{d \overline{\mathbf{u}}_{i}}{d t}+\frac{1}{v_{i}} \oint_{S_{i}} \mathbf{f}(\mathbf{u}) \cdot \mathbf{n} d S=\mathbf{0}. \ No newline at end of file -- GitLab From 0037b1756ee117b41f4daa2e7981ac50046f85bf Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Fri, 26 Feb 2021 16:52:35 +0100 Subject: [PATCH 39/67] Update implement.rst Former-commit-id: e79b8f50fd5c7988df8bb87258ccaa86f654ac8c --- doc/implement.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/implement.rst b/doc/implement.rst index 75d4ff3..3fc58ee 100644 --- a/doc/implement.rst +++ b/doc/implement.rst @@ -1,5 +1,9 @@ .. _implementation: +================ +Implementation +================ + Finite volume method ------------------------ -- GitLab From b288f50df56f174ab7cb40eba3d17ab1de09063f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Fri, 26 Feb 2021 17:40:34 +0100 Subject: [PATCH 40/67] more documentation Former-commit-id: 5a43eebe7dbef648ec85d5adb3737251c74dadaf --- code/include/common/globalconstants.h | 1 - code/include/common/mesh.h | 2 +- code/include/entropies/entropybase.h | 13 +---- code/include/fluxes/numericalflux.h | 7 +-- code/include/optimizers/mloptimizer.h | 18 +++--- code/include/optimizers/optimizerbase.h | 18 ++++-- code/include/problems/electronrt.h | 19 ++++--- code/include/problems/epics.h | 2 - code/include/problems/icru.h | 2 +- code/include/problems/linesource.h | 43 ++++++++------ code/include/problems/problembase.h | 24 ++++---- code/include/quadratures/qgausschebyshev1D.h | 2 +- code/include/quadratures/quadraturebase.h | 2 +- code/include/toolboxes/datageneratorbase.h | 4 +- code/include/toolboxes/interpolation.h | 22 ++++---- code/include/toolboxes/sphericalharmonics.h | 56 ++++++++++--------- code/include/toolboxes/sphericalmonomials.h | 26 +++++---- .../include/toolboxes/textprocessingtoolbox.h | 8 +-- code/src/fluxes/upwindflux.cpp | 48 ++++++++-------- code/src/optimizers/mloptimizer.cpp | 8 +-- 20 files changed, 169 insertions(+), 156 deletions(-) diff --git a/code/include/common/globalconstants.h b/code/include/common/globalconstants.h index c34a4a4..ea29b9a 100644 --- a/code/include/common/globalconstants.h +++ b/code/include/common/globalconstants.h @@ -1,7 +1,6 @@ /*! * \file globalconstants.h * \brief All global defined (physical) constants, enums etc - * \author * \version 0.0 * */ diff --git a/code/include/common/mesh.h b/code/include/common/mesh.h index 0f15c1a..0164cb9 100644 --- a/code/include/common/mesh.h +++ b/code/include/common/mesh.h @@ -122,7 +122,7 @@ class Mesh // Not used void ComputeSlopes( unsigned nq, VectorVector& psiDerX, VectorVector& psiDerY, const VectorVector& psi ) const; - /*! @briefStructured mesh slope reconstruction with flux limiters. + /*! @brief Structured mesh slope reconstruction with flux limiters. * @param nq is number of quadrature points * @param psiDerX is slope in x direction (gets computed. Slope is stored here) * @param psiDerY is slope in y direction (gets computed. Slope is stored here) diff --git a/code/include/entropies/entropybase.h b/code/include/entropies/entropybase.h index 5eb8b17..23da4e4 100644 --- a/code/include/entropies/entropybase.h +++ b/code/include/entropies/entropybase.h @@ -24,22 +24,15 @@ class EntropyBase virtual double EntropyPrime( double z ) = 0; /*! @brief computes the dual of the entropy functional - * @param z = point where the dual of the functional should be evaluated. - * z must be in domain of the duaö functional + * @param y point where the dual of the functional should be evaluated. + * y must be in domain of the duaö functional * @returns: value of entropy functional at z */ virtual double EntropyDual( double y ) = 0; - // /*! @brief computes m*eta_*'(alpha*m). alpha*m must be in domain of the functional - // * alpha, m and grad must be of same size. - // * @param alpha = point where the derivative should be evaluated. - // * @param m = moment vector - // * @param grad: vector in which the resulting gradient is stored */ - // virtual void EntropyPrimeDual( Vector& alpha, Vector& m, Vector& grad ) = 0; - /*! @brief computes eta_*'(y). * @param y = point where the derivative should be evaluated. * @returns: value of the derivative of the entropy functional at y */ - virtual double EntropyPrimeDual( double z ) = 0; + virtual double EntropyPrimeDual( double y ) = 0; /*! @brief computes the hessian of the dual entropy functional * @param y = point where the hessian should be evaluated; diff --git a/code/include/fluxes/numericalflux.h b/code/include/fluxes/numericalflux.h index ecea614..2cdbe9d 100644 --- a/code/include/fluxes/numericalflux.h +++ b/code/include/fluxes/numericalflux.h @@ -31,8 +31,7 @@ class NumericalFlux * @param psiL Solution state of left hand side control volume * @param psiR Solution state of right hand side control volume * @param n Normal vector at the edge between left and right control volume - * @param resultFlux Vector with resulting flux. - * @return void + * @return Vector with resulting flux. */ virtual Vector Flux( const Matrix AxPlus, const Matrix AxMinus, @@ -40,8 +39,8 @@ class NumericalFlux const Matrix AyMinus, const Matrix AzPlus, const Matrix AzMinus, - const Vector, - const Vector, + const Vector psiL, + const Vector psiR, const Vector n ) const = 0; virtual void FluxVanLeer( const Matrix& Ax, diff --git a/code/include/optimizers/mloptimizer.h b/code/include/optimizers/mloptimizer.h index 2adce16..4dcd59b 100644 --- a/code/include/optimizers/mloptimizer.h +++ b/code/include/optimizers/mloptimizer.h @@ -16,22 +16,22 @@ class MLOptimizer : public OptimizerBase inline ~MLOptimizer(); - void Solve( Vector& lambda, Vector& u, const VectorVector& moments, unsigned idx_cell = 0 ) override; - void SolveMultiCell( VectorVector& lambda, VectorVector& u, const VectorVector& moments ) override; + void Solve( Vector& alpha, Vector& u, const VectorVector& moments, unsigned idx_cell = 0 ) override; + void SolveMultiCell( VectorVector& alpha, VectorVector& u, const VectorVector& moments ) override; private: /*! @brief Calls the tensorflow neural network for the entropy closure - * @param inputDim : dimension of moment vector for a single cell - * @param double* nnInput : moment vector as double array - * @return Lagrange multiplyer alpha with size input_size + * @param inputDim dimension of moment vector for a single cell + * @param nnInput moment vector as double array (input to the neural network) + * @return alpha Lagrange multiplyer with size input_size */ double* callNetwork( const unsigned inputDim, double* nnInput ); /*! @brief Calls the tensorflow neural network for the entropy closure for the whole mesh - * @param batchSize : number of cells in the mesh ==> batchsize for the network - * @param inputDim : dimension of moment vector for a single cell - * @param double* nnInput : moment vector as double array - * @return Lagrange multiplyer alpha with size input_size + * @param batchSize number of cells in the mesh ==> batchsize for the network + * @param inputDim dimension of moment vector for a single cell + * @param nnInput moment vector as double array (input to the neural network) + * @return alpha Lagrange multiplyer with size input_size */ double* callNetworkMultiCell( const unsigned batchSize, const unsigned inputDim, double* nnInput ); diff --git a/code/include/optimizers/optimizerbase.h b/code/include/optimizers/optimizerbase.h index 067b685..c4ce64f 100644 --- a/code/include/optimizers/optimizerbase.h +++ b/code/include/optimizers/optimizerbase.h @@ -23,16 +23,22 @@ class OptimizerBase /*! @brief Optimizer creator: Depending on the chosen option, this function creates an object of the chosen child class of OptimizerBase */ static OptimizerBase* Create( Config* settings ); - /*! @brief Computes the optimal Lagrange multilpiers for the dual entropy minimization problem - * @param Vector u = pointer to vector of given moments. // Maybe use pointer for performance? - * @return Vector alpha = optimal lagrange multipliers. Has the same length as Vector u. */ - virtual void Solve( Vector& lambda, Vector& u, const VectorVector& moments, unsigned idx_cell = 0 ) = 0; + /*! @brief Computes the optimal Lagrange multilpiers for the dual entropy minimization problem + * @param alpha vector where the solution Lagrange multipliers are saved to. + * @param u moment vector + * @param moments VectorVector to the moment basis evaluated at all quadpoints + * @param idx_cell index of the cell where alpha should be computed (out of u) */ + virtual void Solve( Vector& alpha, Vector& u, const VectorVector& moments, unsigned idx_cell = 0 ) = 0; - virtual void SolveMultiCell( VectorVector& lambda, VectorVector& u, const VectorVector& moments ) = 0; + /*! @brief Computes the optimal Lagrange multilpiers for the dual entropy minimization problem + * @param alpha vector where the solution Lagrange multipliers are saved to. + * @param u moment vector + * @param moments VectorVector to the moment basis evaluated at all quadpoints */ + virtual void SolveMultiCell( VectorVector& alpha, VectorVector& u, const VectorVector& moments ) = 0; protected: EntropyBase* _entropy; /*!< @brief Class to handle entropy functional evaluations */ - Config* _settings; /*!< @biref: Pointer to settings class of the solver */ + Config* _settings; /*!< @brief Pointer to settings class of the solver */ }; #endif // OPTIMIZERBASE_H diff --git a/code/include/problems/electronrt.h b/code/include/problems/electronrt.h index 0b5cd93..e1e373a 100644 --- a/code/include/problems/electronrt.h +++ b/code/include/problems/electronrt.h @@ -20,13 +20,18 @@ class ElectronRT : public ProblemBase ElectronRT( Config* settings, Mesh* mesh ); virtual ~ElectronRT(); - virtual VectorVector GetScatteringXS( const Vector& energies ); - virtual VectorVector GetTotalXS( const Vector& energies ); - virtual std::vector GetScatteringXSE( const Vector& energies, const Matrix& angles ); - virtual Vector GetTotalXSE( const Vector& energies ); - virtual std::vector GetExternalSource( const Vector& energies ); - virtual VectorVector SetupIC(); - std::vector GetDensity( const VectorVector& cellMidPoints ); + VectorVector GetScatteringXS( const Vector& energies ) override; + VectorVector GetTotalXS( const Vector& energies ) override; + std::vector GetScatteringXSE( const Vector& energies, const Matrix& angles ) override; + /** + * @brief GetTotalXSE gives back vector of total cross sections for + * energies in vector energy + * @param energies is the energy the cross section is queried for + */ + Vector GetTotalXSE( const Vector& energies ) override; + std::vector GetExternalSource( const Vector& energies ) override; + VectorVector SetupIC() override; + std::vector GetDensity( const VectorVector& cellMidPoints ) override; }; #endif // ELECTRONRT_H diff --git a/code/include/problems/epics.h b/code/include/problems/epics.h index c886de9..cac05c4 100644 --- a/code/include/problems/epics.h +++ b/code/include/problems/epics.h @@ -53,8 +53,6 @@ class EPICS /** * @brief GetStoppingPower gives back vector of vectors of stopping powers for materials defined by density and energies in vector energy * @param energies is vector with energies - * @param density is vector with patient densities (at different spatial cells) - * @param sH2O is vector of stopping powers in water */ Vector GetStoppingPower( Vector energies ); diff --git a/code/include/problems/icru.h b/code/include/problems/icru.h index c245ff6..9879586 100644 --- a/code/include/problems/icru.h +++ b/code/include/problems/icru.h @@ -66,7 +66,7 @@ class ICRU double _R1; Vector _E, /*! @brief User queried Energy */ - _QMU; /*!< @briefUser queried mu */ + _QMU; /*!< @brief User queried mu */ std::vector _ET, _ETL; std::vector _XMU, /* angular variable mu of dataset */ diff --git a/code/include/problems/linesource.h b/code/include/problems/linesource.h index 76ad7f3..dc78f4f 100644 --- a/code/include/problems/linesource.h +++ b/code/include/problems/linesource.h @@ -16,27 +16,30 @@ class LineSource : public ProblemBase ~LineSource(); - /*!< @brief Exact analytical solution for the Line Source Test Case at - @param x: x coordinate of exact solution - y: y coordinate of exact solution - t: time of the exact solution - sigma_s: scattering cross section of the exact solution + /*! @brief Exact analytical solution for the Line Source Test Case at + @param x coordinate of exact solution + @param y coordinate of exact solution + @param t time of the exact solution + @param sigma_s scattering cross section of the exact solution @return exact solution at x,y,t,scatteringXS */ double GetAnalyticalSolution( double x, double y, double t, double sigma_s ) override; private: - /*!< @brief Helper Functions to compute the analytic solution for sigma != 0 + /*! @brief Helper Functions to compute the analytic solution for sigma != 0 * (See publication: Garret,Hauck; Momentum Closures for Linear Kinetic Transport Equations) - @param R = distance to origin - @param t = time - @param sigma = R/t + @param R distance to origin + @param t time */ double HelperIntRho_ptc( double R, double t ); - double HelperRho_ptc( double R, double t ); - double HelperRho_ptc1( double R, double t ); - double HelperRho_ptc2( double R, double t ); - double HelperIntRho_ptc2( double t, double gamma ); + double HelperRho_ptc( double R, + double t ); /*!< @brief helper to comput analytic line source solution. @param R distance to origin @param t time */ + double HelperRho_ptc1( double R, + double t ); /*!< @brief helper to comput analytic line source solution. @param R distance to origin @param t time */ + double HelperRho_ptc2( double R, + double t ); /*!< @brief helper to comput analytic line source solution. @param R distance to origin @param t time */ + double HelperIntRho_ptc2( double t, + double gamma ); /*!< @brief helper to comput analytic line source solution @param t time @param gamma equals R/t */ }; class LineSource_SN : public LineSource @@ -48,10 +51,10 @@ class LineSource_SN : public LineSource LineSource_SN( Config* settings, Mesh* mesh ); ~LineSource_SN(); - virtual VectorVector GetScatteringXS( const Vector& energies ); - virtual VectorVector GetTotalXS( const Vector& energies ); - virtual std::vector GetExternalSource( const Vector& energies ); - virtual VectorVector SetupIC(); + virtual VectorVector GetScatteringXS( const Vector& energies ) override; + virtual VectorVector GetTotalXS( const Vector& energies ) override; + virtual std::vector GetExternalSource( const Vector& energies ) override; + virtual VectorVector SetupIC() override; }; class LineSource_SN_Pseudo1D : public LineSource_SN @@ -74,6 +77,12 @@ class LineSource_SN_Pseudo1D_Physics : public LineSource_SN_Pseudo1D LineSource_SN_Pseudo1D_Physics( Config* settings, Mesh* mesh ); std::vector GetScatteringXSE( const Vector& energies, const Matrix& angles ) override; + + /** + * @brief GetTotalXSE gives back vector of total cross sections for + * energies in vector energy + * @param energies is the energy the cross section is queried for + */ Vector GetTotalXSE( const Vector& energies ) override; }; diff --git a/code/include/problems/problembase.h b/code/include/problems/problembase.h index 7dbbcc1..2125739 100644 --- a/code/include/problems/problembase.h +++ b/code/include/problems/problembase.h @@ -27,29 +27,28 @@ class ProblemBase * @brief GetScatteringXS gives back vector (each energy) of vectors (each grid cell) * of scattering cross sections for materials defined by density and energies * in vector energy - * @param energy is the energy the cross section is queried for + * @param energies is the energy the cross section is queried for */ virtual VectorVector GetScatteringXS( const Vector& energies ) = 0; /** * @brief GetTotalXS gives back vector of vectors of total cross sections for * materials defined by density and energies in vector energy - * @param energy is the energy the cross section is queried for - * @param density is vector with patient densities (at different spatial cells) + * @param energies is the energy the cross section is queried for */ virtual VectorVector GetTotalXS( const Vector& energies ) = 0; /** * @brief GetTotalXSE gives back vector of total cross sections for * energies in vector energy - * @param energy is the energy the cross section is queried for */ virtual Vector GetTotalXSE( const Vector& /*energies*/ ) { return Vector( 1 ); } /** * @brief GetScatteringXSE gives back vector (each energy) of scattering cross sections for energies * in vector energy - * @param energy is the energy the cross section is queried for + * @param energies is the energy the cross section is queried for + * @param angles are the queried angles */ virtual std::vector GetScatteringXSE( const Vector& energies, const Matrix& angles ) { return std::vector( energies.size(), Matrix( angles.rows(), angles.columns() ) ); @@ -58,14 +57,15 @@ class ProblemBase /** * @brief GetScatteringXSE gives back vector (each energy) of scattering cross sections for energies * in vector energy - * @param energy is the energy the cross section is queried for + * @param energies is the energy the cross section is queried for + * @param angles are the queried angles */ virtual VectorVector GetScatteringXSE( const Vector& energies, const Vector& angles ); /** * @brief GetExternalSource gives back vector of vectors of source terms for each * energy, cell and angle - * @param energies is vector with energies + * @param energies is the energy the cross section is queried for */ virtual std::vector GetExternalSource( const Vector& energies ) = 0; @@ -87,11 +87,7 @@ class ProblemBase */ virtual VectorVector SetupIC() = 0; - /*! @brief Exact analytical solution for the Line Source Test Case at - @param x: x coordinate of exact solution - y: y coordinate of exact solution - t: time of the exact solution - scatteringXS: scattering cross section of the exact solution + /*! @brief Exact analytical solution for the Line Source Test Case. Returns 0 for all other test cases. @return exact solution at x,y,t,scatteringXS */ // Default is set to 0. ~> if no analytical solution is available. double virtual GetAnalyticalSolution( double /*x*/, double /*y*/, double /*t*/, double /*scatteringXS*/ ) { return 0.0; } @@ -99,6 +95,7 @@ class ProblemBase /** * @brief Physics constructor * @param settings stores all needed user information + * @param mesh for the test case */ ProblemBase( Config* settings, Mesh* mesh ); virtual ~ProblemBase(); @@ -106,7 +103,8 @@ class ProblemBase /** * @brief Create constructor * @param settings stores all needed information - * @return pointer to Physics + * @param mesh for the test case + * @return pointer to ProblemBase */ static ProblemBase* Create( Config* settings, Mesh* mesh ); }; diff --git a/code/include/quadratures/qgausschebyshev1D.h b/code/include/quadratures/qgausschebyshev1D.h index 4ef1b33..8d473de 100644 --- a/code/include/quadratures/qgausschebyshev1D.h +++ b/code/include/quadratures/qgausschebyshev1D.h @@ -28,7 +28,7 @@ class QGaussChebyshev1D : public QuadratureBase void SetConnectivity() override; /*! @brief Integrates f(x,y,z) with the quadrature. - * @param double(f)( double x0, double x1, double x2 ) : density function that depends on a three spatial dimensions. + * @param double (f)( double x0, double x1, double x2 ) : density function that depends on a three spatial dimensions. * @returns double result: result of the quadrature rule */ double Integrate( double( f )( double x0, double x1, double x2 ) ) override; diff --git a/code/include/quadratures/quadraturebase.h b/code/include/quadratures/quadraturebase.h index eac63c7..3fdde9e 100644 --- a/code/include/quadratures/quadraturebase.h +++ b/code/include/quadratures/quadraturebase.h @@ -50,7 +50,7 @@ class QuadratureBase // Quadrature Hub /*! @brief Creates a quadrature rule with a given name and a given order. - * @param Config* settings: Settings to handle quadrature options + * @param settings Settings to handle quadrature options * @returns Quadrature* quadrature: returns pointer to instance of the given derived quadrature class */ static QuadratureBase* Create( Config* settings ); diff --git a/code/include/toolboxes/datageneratorbase.h b/code/include/toolboxes/datageneratorbase.h index aff3abb..81f652b 100644 --- a/code/include/toolboxes/datageneratorbase.h +++ b/code/include/toolboxes/datageneratorbase.h @@ -27,8 +27,8 @@ class DataGeneratorBase ~DataGeneratorBase(); /*! @brief Create a datagenerator (1D or 3D) - * @param Pointer to the config file - * @returns: Pointer to the createt basis class */ + * @param settings Pointer to the config file + * @returns Pointer to the createt basis class */ static DataGeneratorBase* Create( Config* settings ); /*! @brief computes the training data set. diff --git a/code/include/toolboxes/interpolation.h b/code/include/toolboxes/interpolation.h index bfcb545..b8558f5 100644 --- a/code/include/toolboxes/interpolation.h +++ b/code/include/toolboxes/interpolation.h @@ -14,9 +14,10 @@ class Interpolation private: unsigned _dim; - Vector _x, _y; - Matrix _data; - TYPE _type; + Vector _x; /*!< @brief x input data */ + Vector _y; /*!< @brief y input data */ + Matrix _data; /*!< @brief data matrix w.r.t. x and y grid */ + TYPE _type; /*!< @brief type of interpolation (linear, loglinear, cubic) */ Interpolation() = delete; @@ -53,9 +54,10 @@ class Interpolation /*! * @brief constructor cubic interpolation - * @param[in] x - table values for x - * @param[in] y - table values for y - * @param[in] type - linear or cubic interpolation + * @param[in] x table values for x + * @param[in] y table values for y + * @param[in] data matrix w.r.t x y grid + * @param[in] type of interpolation (linear, loglinear, cubic) */ Interpolation( const Vector& x, const Vector& y, const Matrix& data, TYPE type = cubic ); @@ -63,21 +65,21 @@ class Interpolation /*! * @brief defines one dimensional interpolation at x * @param[in] x - value at which to interpolate - * @param[out] y - corresponding interpolated y value + * @returns y - corresponding interpolated y value */ double operator()( double x ) const; /*! * @brief defines interpolation for a Vector of values * @param[in] v - values at which to interpolate - * @param[out] y - corresponding interpolated values + * @returns y - corresponding interpolated values */ Vector operator()( Vector v ) const; /*! * @brief defines interpolation for a std::vector of values * @param[in] v - values at which to interpolate - * @param[out] y - corresponding interpolated values + * @returns y - corresponding interpolated values */ std::vector operator()( std::vector v ) const; @@ -85,7 +87,7 @@ class Interpolation * @brief defines 2D interpolation at x and y * @param[in] x - value at which to interpolate * @param[in] y - value at which to interpolate - * @param[out] data - corresponding interpolated value + * @returns data - corresponding interpolated value */ double operator()( double x, double y ) const; }; diff --git a/code/include/toolboxes/sphericalharmonics.h b/code/include/toolboxes/sphericalharmonics.h index f6f9c91..f717eaa 100644 --- a/code/include/toolboxes/sphericalharmonics.h +++ b/code/include/toolboxes/sphericalharmonics.h @@ -18,31 +18,33 @@ class SphericalHarmonics : public SphericalBase { public: - /*! @brief : Sets up class for spherical harmonics basis based on legendre - * polynoms and associated legendre polynoms up to degree L. - * The basis then consists of N = L² +2L basis functions. - * @param : L_degree - maximum degree of spherical harmonics basis, 0 <= L <= 1000 (upper bound + /*! @brief Sets up class for spherical harmonics basis based on legendre + * polynoms and associated legendre polynoms up to degree L. + * The basis then consists of N = L² +2L basis functions. + * @param L_degree - maximum degree of spherical harmonics basis, 0 <= L <= 1000 (upper bound * due to numerical stability) * */ SphericalHarmonics( unsigned L_degree ); - /*! @brief : Computes all N = L² +2L basis functions at point (my, phi) - * @param : my = cos(theta) - spherical coordinate, -1 <= x <= 1 - * @param : phi - spherical coordinate, 0 <= phi <= 2*pi - * @return : vector of basis functions at point (my, phi) with size N = L² +2L + /*! @brief Computes all N = L² +2L basis functions at point (my, phi) + * @param my = cos(theta) - spherical coordinate, -1 <= x <= 1 + * @param phi - spherical coordinate, 0 <= phi <= 2*pi + * @return vector of basis functions at point (my, phi) with size N = L² +2L */ Vector ComputeSphericalBasis( double my, double phi ) override; - /*! @brief : Computes all N = L² +2L basis functions at point (x, y, z) on the unit sphere - * @param : x,y,z = coordinates on unit sphere - * @return : vector of basis functions at point (x,y,z) with size N = L² +2L + /*! @brief Computes all N = L² +2L basis functions at point (x, y, z) on the unit sphere + * @param x coordinates on unit sphere + * @param y coordinates on unit sphere + * @param z coordinates on unit sphere + * @return vector of basis functions at point (x,y,z) with size N = L² +2L */ Vector ComputeSphericalBasis( double x, double y, double z ) override; - /*! @brief : Computes an entire set of (komplex congjugate) P_l^k and stores - * it in the vector _assLegendreP - * @param : my = cos(theta) - spherical coordinate, -1 <= my <= 1 - * @return : Associated Legendre Polynomial at my for all l and k + /*! @brief Computes an entire set of (komplex congjugate) P_l^k and stores + * it in the vector _assLegendreP + * @param my = cos(theta) - spherical coordinate, -1 <= my <= 1 + * @return Associated Legendre Polynomial at my for all l and k */ std::vector GetAssLegendrePoly( const double my ); @@ -53,10 +55,10 @@ class SphericalHarmonics : public SphericalBase * @param currDegreeL = degree of polynomials that are counted */ unsigned GetCurrDegreeSize( unsigned currDegree ) override; - /*! @brief : helper function to get the global index for given k and l of - * the basis function Y_k^l. - * @param : l_degree - current degree of basis function, 0 <= l <= L - * @param : k_order - current order of basis function, -l <= k <= l */ + /*! @brief helper function to get the global index for given k and l of + * the basis function Y_k^l. + * @param l_degree - current degree of basis function, 0 <= l <= L + * @param k_order - current order of basis function, -l <= k <= l */ unsigned GetGlobalIndexBasis( int l_degree, int k_order ) override; private: @@ -81,20 +83,20 @@ class SphericalHarmonics : public SphericalBase */ Vector _YBasis; - /*! @brief : helper function to get the global index for given k and l of - * the associated legendre polynomial P_k^l. - * @param : l_degree - current degree of basis function, 0 <= l <= L - * @param : k_order - current order of basis function, 0 <= k <= l + /*! @brief helper function to get the global index for given k and l of + * the associated legendre polynomial P_k^l. + * @param l_degree - current degree of basis function, 0 <= l <= L + * @param k_order - current order of basis function, 0 <= k <= l */ unsigned inline GlobalIdxAssLegendreP( unsigned l_degree, unsigned k_order ) { return k_order + ( l_degree * ( l_degree + 1 ) ) / 2; } - /*! @brief : computes values of a_param and b_param + /*! @brief computes values of a_param and b_param */ void ComputeCoefficients(); - /*! @brief : Computes an entire set of (komplex congjugate) P_l^k and stores - * it in the vector _assLegendreP - * @param : my = cos(theta) - spherical coordinate, -1 <= my <= 1 + /*! @brief Computes an entire set of (komplex congjugate) P_l^k and stores + * it in the vector _assLegendreP + * @param my equals cos(theta) - spherical coordinate, -1 <= my <= 1 */ void ComputeAssLegendrePoly( const double my ); diff --git a/code/include/toolboxes/sphericalmonomials.h b/code/include/toolboxes/sphericalmonomials.h index 6d18a3a..4b2b8fd 100644 --- a/code/include/toolboxes/sphericalmonomials.h +++ b/code/include/toolboxes/sphericalmonomials.h @@ -21,24 +21,26 @@ class SphericalMonomials : public SphericalBase * */ SphericalMonomials( unsigned L_degree ); - /*! @brief : Sets up class for monomial basis on sphere up to degree L. - * The basis then consists of N = L. - * @param : L_degree - maximum degree of spherical harmonics basis, 0 <= L <= 1000 (upper bound - * due to numerical stability) - * @param : spatialDim - spatial dimensioniality of the simulation + /*! @brief Sets up class for monomial basis on sphere up to degree L. + * The basis then consists of N = L. + * @param L_degree - maximum degree of spherical harmonics basis, 0 <= L <= 1000 (upper bound + * due to numerical stability) + * @param spatialDim - spatial dimensioniality of the simulation * */ SphericalMonomials( unsigned L_degree, unsigned short spatialDim ); - /*! @brief : Computes all N = L² +2L basis functions at point (my, phi) - * @param : my = cos(theta) - spherical coordinate, -1 <= x <= 1 - * @param : phi - spherical coordinate, 0 <= phi <= 2*pi - * @return : vector of basis functions at point (my, phi) with size N = L² +2L + /*! @brief Computes all N = L² +2L basis functions at point (my, phi) + * @param my = cos(theta) - spherical coordinate, -1 <= x <= 1 + * @param phi - spherical coordinate, 0 <= phi <= 2*pi + * @return vector of basis functions at point (my, phi) with size N = L² +2L */ Vector ComputeSphericalBasis( double my, double phi ) override; - /*! @brief : Computes all N = L² +2L basis functions at point (x, y, z) on the unit sphere - * @param : x,y,z = coordinates on unit sphere - * @return : vector of basis functions at point (x,y,z) with size N = L² +2L + /*! @brief Computes all N = L² +2L basis functions at point (x, y, z) on the unit sphere + * @param x = coordinates on unit sphere + * @param y = coordinates on unit sphere + * @param z = coordinates on unit sphere + * @return vector of basis functions at point (x,y,z) with size N = L² +2L */ Vector ComputeSphericalBasis( double x, double y, double z ) override; diff --git a/code/include/toolboxes/textprocessingtoolbox.h b/code/include/toolboxes/textprocessingtoolbox.h index 8e01a2f..383f415 100644 --- a/code/include/toolboxes/textprocessingtoolbox.h +++ b/code/include/toolboxes/textprocessingtoolbox.h @@ -42,7 +42,7 @@ inline std::vector Split( const std::string& s, char delimiter ) { /*! * \brief utility function for printing a VectorVector - * \param [in] VectorVector we want to print + * \param vectorIn VectorVector we want to print */ inline void PrintVectorVector( const VectorVector vectorIn ) { unsigned dimOuter = vectorIn.size(); @@ -61,14 +61,14 @@ inline void PrintVectorVector( const VectorVector vectorIn ) { /*! * \brief utility function for returning the last number in a string - * \param [in] string to be checked + * \param str string to be checked */ inline int GetTrailingNumber( std::string const& str ) { return std::stoi( str.substr( str.find_first_of( "0123456789" ), str.length() - 1 ) ); } /*! * \brief utility function for checking if a string has a certain ending - * \param [in] string to be checked - * \param [in] ending to be checked for + * \param value string to be checked + * \param ending string to be checked for */ inline bool StringEndsWith( std::string const& value, std::string const& ending ) { if( ending.size() > value.size() ) return false; diff --git a/code/src/fluxes/upwindflux.cpp b/code/src/fluxes/upwindflux.cpp index 5c3078d..24d7e7c 100644 --- a/code/src/fluxes/upwindflux.cpp +++ b/code/src/fluxes/upwindflux.cpp @@ -13,18 +13,18 @@ double UpwindFlux::Flux( const Vector& Omega, double psiL, double psiR, const Ve } /** - * @brief Flux : Computes upwinding scheme for given flux jacobians of the PN Solver at a given edge and stores it in + * @brief Flux Computes upwinding scheme for given flux jacobians of the PN Solver at a given edge and stores it in * resultFlux - * @param AxPlus : Positive part of the flux jacobian in x direction - * @param AxMinus : Negative part of the flux jacobian in x direction - * @param AyPlus : Positive part of the flux jacobian in y direction - * @param AyMinus : Negative part of the flux jacobian in y direction - * @param AzPlus : Positive part of the flux jacobian in z direction - * @param AzMinus : Negative part of the flux jacobian in z direction - * @param psiL : Solution state of left hand side control volume - * @param psiR : Solution state of right hand side control volume - * @param n : Normal vector at the edge between left and right control volume - * @return resultFlux: Vector with resulting flux. + * @param AxPlus Positive part of the flux jacobian in x direction + * @param AxMinus Negative part of the flux jacobian in x direction + * @param AyPlus Positive part of the flux jacobian in y direction + * @param AyMinus Negative part of the flux jacobian in y direction + * @param AzPlus Positive part of the flux jacobian in z direction + * @param AzMinus Negative part of the flux jacobian in z direction + * @param psiL Solution state of left hand side control volume + * @param psiR Solution state of right hand side control volume + * @param n Normal vector at the edge between left and right control volume + * @return resultFlux Vector with resulting flux. */ Vector UpwindFlux::Flux( const Matrix AxPlus, @@ -58,19 +58,19 @@ Vector UpwindFlux::Flux( const Matrix AxPlus, } /** - * @brief Flux : Computes upwinding scheme for given flux jacobians of the PN Solver at a given edge and stores it in - * resultFlux - * @param AxPlus : Positive part of the flux jacobian in x direction - * @param AxMinus : Negative part of the flux jacobian in x direction - * @param AyPlus : Positive part of the flux jacobian in y direction - * @param AyMinus : Negative part of the flux jacobian in y direction - * @param AzPlus : Positive part of the flux jacobian in z direction - * @param AzMinus : Negative part of the flux jacobian in z direction - * @param psiL : Solution state of left hand side control volume - * @param psiR : Solution state of right hand side control volume - * @param n : Normal vector at the edge between left and right control volume - * @param resultFlux: Vector with resulting flux. - * @return : void + * @brief Flux Computes upwinding scheme for given flux jacobians of the PN Solver at a given edge and stores it in + * resultFlux + * @param AxPlus Positive part of the flux jacobian in x direction + * @param AxMinus Negative part of the flux jacobian in x direction + * @param AyPlus Positive part of the flux jacobian in y direction + * @param AyMinus Negative part of the flux jacobian in y direction + * @param AzPlus Positive part of the flux jacobian in z direction + * @param AzMinus Negative part of the flux jacobian in z direction + * @param psiL Solution state of left hand side control volume + * @param psiR Solution state of right hand side control volume + * @param n Normal vector at the edge between left and right control volume + * @param resultFlux Vector with resulting flux. + * @return void */ void UpwindFlux::FluxVanLeer( const Matrix& Ax, const Matrix& AxAbs, diff --git a/code/src/optimizers/mloptimizer.cpp b/code/src/optimizers/mloptimizer.cpp index 24fedd7..e0f7954 100644 --- a/code/src/optimizers/mloptimizer.cpp +++ b/code/src/optimizers/mloptimizer.cpp @@ -29,7 +29,7 @@ MLOptimizer::MLOptimizer( Config* settings ) : OptimizerBase( settings ) { MLOptimizer::~MLOptimizer() { finalizePython(); } -void MLOptimizer::Solve( Vector& lambda, Vector& u, const VectorVector& /*moments*/, unsigned /*idx_cell*/ ) { +void MLOptimizer::Solve( Vector& alpha, Vector& u, const VectorVector& /*moments*/, unsigned /*idx_cell*/ ) { // Convert Vector to array const unsigned input_size = u.size(); @@ -47,13 +47,13 @@ void MLOptimizer::Solve( Vector& lambda, Vector& u, const VectorVector& /*moment for( unsigned i = 0; i < input_size; i++ ) { // std::cout << nn_output[i] << ", "; - lambda[i] = nn_output[i]; + alpha[i] = nn_output[i]; } // std::cout << std::endl; delete[] nn_input; } -void MLOptimizer::SolveMultiCell( VectorVector& lambda, VectorVector& u, const VectorVector& /*moments*/ ) { +void MLOptimizer::SolveMultiCell( VectorVector& alpha, VectorVector& u, const VectorVector& /*moments*/ ) { const unsigned batch_size = u.size(); // batch size = number of cells const unsigned sol_dim = u[0].size(); // dimension of input vector = nTotalEntries @@ -76,7 +76,7 @@ void MLOptimizer::SolveMultiCell( VectorVector& lambda, VectorVector& u, const V unsigned idx_output = 0; for( unsigned idx_cell = 0; idx_cell < batch_size; idx_cell++ ) { for( unsigned idx_sys = 0; idx_sys < sol_dim; idx_sys++ ) { - lambda[idx_cell][idx_sys] = nn_output[idx_output]; + alpha[idx_cell][idx_sys] = nn_output[idx_output]; idx_output++; } } -- GitLab From e11f4cc69551962edc75f1dff8c91e096d68aefb Mon Sep 17 00:00:00 2001 From: Jannick Wolters Date: Sun, 28 Feb 2021 13:16:37 +0100 Subject: [PATCH 41/67] resolved all doxygen/sphinx warnings Former-commit-id: 00c2b208193975172467443d862f09cab04cad3a --- code/include/fluxes/upwindflux.h | 15 +++++----- code/include/quadratures/qgausschebyshev1D.h | 19 ++++++------ code/include/quadratures/qgausslegendre1D.h | 19 ++++++------ code/include/quadratures/quadraturebase.h | 28 ++++++++--------- code/include/toolboxes/reconstructor.h | 20 ++++--------- code/include/toolboxes/sphericalbase.h | 21 ++++++------- code/include/toolboxes/sphericalharmonics.h | 4 +-- code/include/toolboxes/sphericalmonomials.h | 16 +++++----- .../include/toolboxes/textprocessingtoolbox.h | 30 ++++++++----------- code/src/common/config.cpp | 9 +++--- code/src/fluxes/upwindflux.cpp | 30 ------------------- code/src/quadratures/qgausschebyshev1D.cpp | 6 ++-- code/src/quadratures/qgausslegendre1D.cpp | 6 ++-- code/src/quadratures/quadraturebase.cpp | 6 ++-- doc/problems/phantom2d.rst | 2 +- doc/solvers/index.rst | 1 - doc/solvers/snsolvermpi.rst | 7 ----- doc/toolboxes/index.rst | 1 - doc/toolboxes/physics.rst | 7 ----- 19 files changed, 93 insertions(+), 154 deletions(-) delete mode 100644 doc/solvers/snsolvermpi.rst delete mode 100644 doc/toolboxes/physics.rst diff --git a/code/include/fluxes/upwindflux.h b/code/include/fluxes/upwindflux.h index 6377eee..842aff9 100644 --- a/code/include/fluxes/upwindflux.h +++ b/code/include/fluxes/upwindflux.h @@ -34,8 +34,7 @@ class UpwindFlux : public NumericalFlux * @param psiL Solution state of left hand side control volume * @param psiR Solution state of right hand side control volume * @param n Normal vector at the edge between left and right control volume - * @param resultFlux Vector with resulting flux. - * @return void + * @return Vector with resulting flux */ Vector Flux( const Matrix AxPlus, const Matrix AxMinus, @@ -50,12 +49,12 @@ class UpwindFlux : public NumericalFlux /** * @brief Flux Computes "VanLeer" upwinding scheme for given flux jacobians of the PN Solver at a given edge and stores it in * resultFlux - * @param AxPlus Positive part of the flux jacobian in x direction - * @param AxMinus Negative part of the flux jacobian in x direction - * @param AyPlus Positive part of the flux jacobian in y direction - * @param AyMinus Negative part of the flux jacobian in y direction - * @param AzPlus Positive part of the flux jacobian in z direction - * @param AzMinus Negative part of the flux jacobian in z direction + * @param Ax Flux jacobian in x direction + * @param AxAbs Absolute value of the flux jacobian in x direction + * @param Ay Flux jacobian in y direction + * @param AyAbs Absolute value of the flux jacobian in y direction + * @param Az Flux jacobian in z direction + * @param AzAbs Absolute value of the flux jacobian in z direction * @param psiL Solution state of left hand side control volume * @param psiR Solution state of right hand side control volume * @param n Normal vector at the edge between left and right control volume diff --git a/code/include/quadratures/qgausschebyshev1D.h b/code/include/quadratures/qgausschebyshev1D.h index 8d473de..bce30b6 100644 --- a/code/include/quadratures/qgausschebyshev1D.h +++ b/code/include/quadratures/qgausschebyshev1D.h @@ -28,20 +28,19 @@ class QGaussChebyshev1D : public QuadratureBase void SetConnectivity() override; /*! @brief Integrates f(x,y,z) with the quadrature. - * @param double (f)( double x0, double x1, double x2 ) : density function that depends on a three spatial dimensions. - * @returns double result: result of the quadrature rule */ - double Integrate( double( f )( double x0, double x1, double x2 ) ) override; + * @param f density function that depends on a three spatial dimensions. + * @returns result of the quadrature rule */ + double Integrate( double ( *f )( double, double, double ) ) override; /*! @brief Integrates f(x,y,z) with the quadrature. - * @param double(f)( double my, double phi ) : density function that depends on a spherical coordinates. - * @returns double result: result of the quadrature rule */ - double IntegrateSpherical( double( f )( double my, double phi ) ) override; + * @param f density function that depends on a spherical coordinates. + * @returns result of the quadrature rule */ + double IntegrateSpherical( double ( *f )( double, double ) ) override; /*! @brief Integrates vector valued f(x,y,z) with the quadrature. Each dimension is integrated by itself. - * @param : double(f)( double x0, double x1, double x2 ) : density function that depends on a three spatial dimensions. - * @param : len : lenght of vector - * @returns double result: result of the quadrature rule (vector valued) */ - std::vector Integrate( std::vector( f )( double x0, double x1, double x2 ), unsigned /* len */ ) override; + * @param f density function that depends on a three spatial dimensions. + * @returns result of the quadrature rule (vector valued) */ + std::vector Integrate( std::vector ( *f )( double, double, double ), unsigned /* len */ ) override; }; #endif // QGAUSSCHEBYSHEV_H diff --git a/code/include/quadratures/qgausslegendre1D.h b/code/include/quadratures/qgausslegendre1D.h index 7df4e3c..3296fb0 100644 --- a/code/include/quadratures/qgausslegendre1D.h +++ b/code/include/quadratures/qgausslegendre1D.h @@ -29,20 +29,19 @@ class QGaussLegendre1D : public QuadratureBase void SetConnectivity() override; /*! @brief Integrates f(x,y,z) with the quadrature. - * @param double(f)( double x0, double x1, double x2 ) : density function that depends on a three spatial dimensions. - * @returns double result: result of the quadrature rule */ - double Integrate( double( f )( double x0, double x1, double x2 ) ) override; + * @param f density function that depends on a three spatial dimensions. + * @returns result of the quadrature rule */ + double Integrate( double ( *f )( double, double, double ) ) override; /*! @brief Integrates f(x,y,z) with the quadrature. - * @param double(f)( double my, double phi ) : density function that depends on a spherical coordinates. - * @returns double result: result of the quadrature rule */ - double IntegrateSpherical( double( f )( double my, double phi ) ) override; + * @param f density function that depends on a spherical coordinates. + * @returns result of the quadrature rule */ + double IntegrateSpherical( double ( *f )( double, double ) ) override; /*! @brief Integrates vector valued f(x,y,z) with the quadrature. Each dimension is integrated by itself. - * @param : double(f)( double x0, double x1, double x2 ) : density function that depends on a three spatial dimensions. - * @param : len : lenght of vector - * @returns double result: result of the quadrature rule (vector valued) */ - std::vector Integrate( std::vector( f )( double x0, double x1, double x2 ), unsigned /* len */ ) override; + * @param f density function that depends on a three spatial dimensions. + * @returns result of the quadrature rule (vector valued) */ + std::vector Integrate( std::vector ( *f )( double, double, double ), unsigned /* len */ ) override; }; #endif // QGAUSSLEGENDRE1D_H diff --git a/code/include/quadratures/quadraturebase.h b/code/include/quadratures/quadraturebase.h index 3fdde9e..2367818 100644 --- a/code/include/quadratures/quadraturebase.h +++ b/code/include/quadratures/quadraturebase.h @@ -15,7 +15,7 @@ class QuadratureBase { public: /*! @brief Constructor using settings class. This is the recommended constructor. - * @param Config* settings: Settings class storing all important options. + * @param settings Settings class storing all important options. */ QuadratureBase( Config* settings ); /*! @brief Constructor using directly the order of the quadrature. Not applicable for GaussLegendre, that need additional options. @@ -33,20 +33,20 @@ class QuadratureBase double SumUpWeights(); /*! @brief Integrates f(x,y,z) with the quadrature. - * @param double(f)( double x0, double x1, double x2 ) : density function that depends on a three spatial dimensions. - * @returns double result: result of the quadrature rule */ - virtual double Integrate( double( f )( double x0, double x1, double x2 ) ); + * @param f density function that depends on a three spatial dimensions. + * @returns result of the quadrature rule */ + virtual double Integrate( double ( *f )( double, double, double ) ); /*! @brief Integrates f(x,y,z) with the quadrature. - * @param double(f)( double my, double phi ) : density function that depends on a spherical coordinates. - * @returns double result: result of the quadrature rule */ - virtual double IntegrateSpherical( double( f )( double my, double phi ) ); + * @param f density function that depends on a spherical coordinates. + * @returns result of the quadrature rule */ + virtual double IntegrateSpherical( double ( *f )( double, double ) ); /*! @brief Integrates vector valued f(x,y,z) with the quadrature. Each dimension is integrated by itself. - * @param : double(f)( double x0, double x1, double x2 ) : density function that depends on a three spatial dimensions. - * @param : len : lenght of vector - * @returns double result: result of the quadrature rule (vector valued) */ - virtual std::vector Integrate( std::vector( f )( double x0, double x1, double x2 ), unsigned len ); + * @param f density function that depends on a three spatial dimensions. + * @param len lenght of vector + * @returns result of the quadrature rule (vector valued) */ + virtual std::vector Integrate( std::vector ( *f )( double, double, double ), unsigned len ); // Quadrature Hub /*! @brief Creates a quadrature rule with a given name and a given order. @@ -55,9 +55,9 @@ class QuadratureBase static QuadratureBase* Create( Config* settings ); /*! @brief Creates a quadrature rule with a given name and a given order. - * @param name: name of quadrature as enum - * @param quadOrder: order of quadrature - * @returns Quadrature* quadrature: returns pointer to instance of the given derived quadrature class */ + * @param name name of quadrature as enum + * @param quadOrder order of quadrature + * @returns pointer to instance of the given derived quadrature class */ static QuadratureBase* Create( QUAD_NAME name, unsigned quadOrder ); // Getter diff --git a/code/include/toolboxes/reconstructor.h b/code/include/toolboxes/reconstructor.h index cb74b94..0f61968 100644 --- a/code/include/toolboxes/reconstructor.h +++ b/code/include/toolboxes/reconstructor.h @@ -30,22 +30,14 @@ class Reconstructor /*! Method 1: structured developing * @brief Slope of angular flux psi inside a given cell - * @param Omega fixed ordinate for flux computation - * @param psiL left solution state - * @param psiR right solution state - * @param n scaled normal vector of given edge + * @param uL left solution state + * @param uC center solution state + * @param uR right solution state + * @param dxL left slope + * @param dxR right slope + * @param limiter name of the applied limiter (invalid argument results in disabled limiter) * @return reconstructed slope */ - - /** Method 2: unstructured developing - * @brief Slope of angular flux psi inside a given cell - * @param Omega fixed ordinate for flux computation - * @param psiL left solution state - * @param psiR right solution state - * @param n scaled normal vector of given edge - * @return reconstructed slope - */ - virtual double ReconstructSlopeStruct( double uL, double uC, double uR, double dxL, double dxR, std::string limiter ) const; }; diff --git a/code/include/toolboxes/sphericalbase.h b/code/include/toolboxes/sphericalbase.h index 760334e..534375d 100644 --- a/code/include/toolboxes/sphericalbase.h +++ b/code/include/toolboxes/sphericalbase.h @@ -18,24 +18,25 @@ class SphericalBase virtual ~SphericalBase() {} /*! @brief Create a set of basis functions on the unit sphere defined in settings - * @param Pointer to the config file - * @returns: Pointer to the createt basis class */ + * @param settings pointer to the config object + * @returns Pointer to the createt basis class + */ static SphericalBase* Create( Config* settings ); - /*! @brief : Computes all N basis functions at point (my, phi) - * @param : my = cos(theta) - spherical coordinate, -1 <= x <= 1 - * @param : phi - spherical coordinate, 0 <= phi <= 2*pi - * @return : vector of basis functions at point (my, phi) with size N + /*! @brief Computes all N basis functions at point (my, phi) + * @param my cos(theta) - spherical coordinate, -1 <= x <= 1 + * @param phi spherical coordinate, 0 <= phi <= 2*pi + * @return vector of basis functions at point (my, phi) with size N */ virtual Vector ComputeSphericalBasis( double my, double phi ) = 0; - /*! @brief : Computes all basis functions at point (x, y, z) on the unit sphere - * @param : x,y,z = coordinates on unit sphere - * @return : vector of basis functions at point (x,y,z) with size N + /*! @brief Computes all basis functions at point (x, y, z) on the unit sphere + * @param x,y,z coordinates on unit sphere + * @return vector of basis functions at point (x,y,z) with size N */ virtual Vector ComputeSphericalBasis( double x, double y, double z ) = 0; - /*! @brief : Return size of complete Basisvector */ + /*! @brief Return size of complete Basisvector */ virtual unsigned GetBasisSize() = 0; /*! @brief Return number of basis functions with degree equals to currDegree diff --git a/code/include/toolboxes/sphericalharmonics.h b/code/include/toolboxes/sphericalharmonics.h index f717eaa..b5dd73e 100644 --- a/code/include/toolboxes/sphericalharmonics.h +++ b/code/include/toolboxes/sphericalharmonics.h @@ -52,7 +52,7 @@ class SphericalHarmonics : public SphericalBase unsigned GetBasisSize() override; /*! @brief Return number of basis functions with degree equals to currDegree - * @param currDegreeL = degree of polynomials that are counted */ + * @param currDegree degree of polynomials that are counted */ unsigned GetCurrDegreeSize( unsigned currDegree ) override; /*! @brief helper function to get the global index for given k and l of @@ -102,7 +102,7 @@ class SphericalHarmonics : public SphericalBase /*! @brief Computes the spherical harmonics basis function up to degree _LmaxDegree at * polar coordinates (theta, psi) and stores the result in _YBasis; - * @param spherical coordinate phi + * @param phi spherical coordinate */ void ComputeYBasis( const double phi ); }; diff --git a/code/include/toolboxes/sphericalmonomials.h b/code/include/toolboxes/sphericalmonomials.h index 4b2b8fd..5e8e331 100644 --- a/code/include/toolboxes/sphericalmonomials.h +++ b/code/include/toolboxes/sphericalmonomials.h @@ -14,24 +14,24 @@ class SphericalMonomials : public SphericalBase { public: - /*! @brief : Sets up class for monomial basis on sphere up to degree L. + /*! @brief Sets up class for monomial basis on sphere up to degree L. * The basis then consists of N = L. - * @param : L_degree - maximum degree of spherical harmonics basis, 0 <= L <= 1000 (upper bound + * @param L_degree maximum degree of spherical harmonics basis, 0 <= L <= 1000 (upper bound * due to numerical stability) * */ SphericalMonomials( unsigned L_degree ); /*! @brief Sets up class for monomial basis on sphere up to degree L. * The basis then consists of N = L. - * @param L_degree - maximum degree of spherical harmonics basis, 0 <= L <= 1000 (upper bound + * @param L_degree maximum degree of spherical harmonics basis, 0 <= L <= 1000 (upper bound * due to numerical stability) - * @param spatialDim - spatial dimensioniality of the simulation + * @param spatialDim spatial dimensioniality of the simulation * */ SphericalMonomials( unsigned L_degree, unsigned short spatialDim ); /*! @brief Computes all N = L² +2L basis functions at point (my, phi) - * @param my = cos(theta) - spherical coordinate, -1 <= x <= 1 - * @param phi - spherical coordinate, 0 <= phi <= 2*pi + * @param my cos(theta) - spherical coordinate, -1 <= x <= 1 + * @param phi spherical coordinate, 0 <= phi <= 2*pi * @return vector of basis functions at point (my, phi) with size N = L² +2L */ Vector ComputeSphericalBasis( double my, double phi ) override; @@ -56,8 +56,8 @@ class SphericalMonomials : public SphericalBase unsigned GetCurrDegreeSize( unsigned currDegreeL ) override; /*! @brief Computes global index of basis vector depending on order k and degree l - * @param l = degree of polynomials l = 0,1,2,3,... - * @param k = order of element of degree l. 0 <=k <=GetCurrDegreeSize(l) */ + * @param l_degree degree of polynomials l = 0,1,2,3,... + * @param k_order order of element of degree l. 0 <=k <=GetCurrDegreeSize(l) */ unsigned GetGlobalIndexBasis( int l_degree, int k_order ) override; private: diff --git a/code/include/toolboxes/textprocessingtoolbox.h b/code/include/toolboxes/textprocessingtoolbox.h index 383f415..ef17079 100644 --- a/code/include/toolboxes/textprocessingtoolbox.h +++ b/code/include/toolboxes/textprocessingtoolbox.h @@ -14,15 +14,15 @@ namespace TextProcessingToolbox { /*! - * \brief utility function for converting strings to uppercase - * \param[in,out] str - string we want to convert + * @brief utility function for converting strings to uppercase + * @param str - string to be converted */ inline void StringToUpperCase( std::string& str ) { std::transform( str.begin(), str.end(), str.begin(), ::toupper ); } /*! - * \brief utility function for splitting strings to at delimiter - * \param [in] str - string we want to split, delimiter - delimiter character - * [out] vector of string tokens that were separated by the delimiter + * @brief utility function for splitting strings to at delimiter + * @param s string to be split + * @param delimiter delimiter character */ inline std::vector Split( const std::string& s, char delimiter ) { std::vector tokens; @@ -35,14 +35,8 @@ inline std::vector Split( const std::string& s, char delimiter ) { } /*! - * \brief utility function for getting walltime - * \param [in,out] V - */ -// TODO - -/*! - * \brief utility function for printing a VectorVector - * \param vectorIn VectorVector we want to print + * @brief utility function for printing a VectorVector + * @param vectorIn VectorVector we want to print */ inline void PrintVectorVector( const VectorVector vectorIn ) { unsigned dimOuter = vectorIn.size(); @@ -60,15 +54,15 @@ inline void PrintVectorVector( const VectorVector vectorIn ) { } /*! - * \brief utility function for returning the last number in a string - * \param str string to be checked + * @brief utility function for returning the last number in a string + * @param str string to be checked */ inline int GetTrailingNumber( std::string const& str ) { return std::stoi( str.substr( str.find_first_of( "0123456789" ), str.length() - 1 ) ); } /*! - * \brief utility function for checking if a string has a certain ending - * \param value string to be checked - * \param ending string to be checked for + * @brief utility function for checking if a string has a certain ending + * @param value string to be checked + * @param ending string to be checked for */ inline bool StringEndsWith( std::string const& value, std::string const& ending ) { if( ending.size() > value.size() ) return false; diff --git a/code/src/common/config.cpp b/code/src/common/config.cpp index 29658b1..ef391a4 100644 --- a/code/src/common/config.cpp +++ b/code/src/common/config.cpp @@ -216,8 +216,9 @@ void Config::SetConfigOptions() { AddStringOption( "CT_FILE", _ctFile, string( "../tests/input/phantom.png" ) ); // Quadrature relatated options - /*! @brief QUAD_TYPE \n DESCRIPTION: Type of Quadrature rule \n Options: see @link QUAD_NAME \endlink \n DEFAULT: QUAD_MonteCarlo \ingroup - * Config*/ + /*! @brief QUAD_TYPE \n DESCRIPTION: Type of Quadrature rule \n Options: see @link QUAD_NAME \endlink \n DEFAULT: QUAD_MonteCarlo + * \ingroup Config + */ AddEnumOption( "QUAD_TYPE", _quadName, Quadrature_Map, QUAD_MonteCarlo ); /*!\brief QUAD_ORDER \n DESCRIPTION: Order of Quadrature rule \n DEFAULT 2 \ingroup Config.*/ AddUnsignedShortOption( "QUAD_ORDER", _quadOrder, 1 ); @@ -278,8 +279,8 @@ void Config::SetConfigOptions() { AddUnsignedLongOption( "NEWTON_ITER", _newtonIter, 100 ); /*! @brief Step Size Newton Optmizers \n DESCRIPTION: Step size for Newton optimizer \n DEFAULT 10 \ingroup Config */ AddDoubleOption( "NEWTON_STEP_SIZE", _newtonStepSize, 0.1 ); - /*! @brief Max Iter for line search in Newton Optmizers \n DESCRIPTION: Max number of line search iter for newton optimizer \n DEFAULT 10 \ingroup - * Config */ + /*! @brief Max Iter for line search in Newton Optmizers \n DESCRIPTION: Max number of line search iter for newton optimizer \n DEFAULT 10 + * \ingroup Config */ AddUnsignedLongOption( "NEWTON_LINE_SEARCH_ITER", _newtonLineSearchIter, 100 ); /*! @brief Newton Fast mode \n DESCRIPTION: If true, we skip the Newton optimizer for Quadratic entropy and set alpha = u \n DEFAULT false * \ingroup Config */ diff --git a/code/src/fluxes/upwindflux.cpp b/code/src/fluxes/upwindflux.cpp index 24d7e7c..c3ddb74 100644 --- a/code/src/fluxes/upwindflux.cpp +++ b/code/src/fluxes/upwindflux.cpp @@ -12,21 +12,6 @@ double UpwindFlux::Flux( const Vector& Omega, double psiL, double psiR, const Ve } } -/** - * @brief Flux Computes upwinding scheme for given flux jacobians of the PN Solver at a given edge and stores it in - * resultFlux - * @param AxPlus Positive part of the flux jacobian in x direction - * @param AxMinus Negative part of the flux jacobian in x direction - * @param AyPlus Positive part of the flux jacobian in y direction - * @param AyMinus Negative part of the flux jacobian in y direction - * @param AzPlus Positive part of the flux jacobian in z direction - * @param AzMinus Negative part of the flux jacobian in z direction - * @param psiL Solution state of left hand side control volume - * @param psiR Solution state of right hand side control volume - * @param n Normal vector at the edge between left and right control volume - * @return resultFlux Vector with resulting flux. - */ - Vector UpwindFlux::Flux( const Matrix AxPlus, const Matrix AxMinus, const Matrix AyPlus, @@ -57,21 +42,6 @@ Vector UpwindFlux::Flux( const Matrix AxPlus, return resultFlux; } -/** - * @brief Flux Computes upwinding scheme for given flux jacobians of the PN Solver at a given edge and stores it in - * resultFlux - * @param AxPlus Positive part of the flux jacobian in x direction - * @param AxMinus Negative part of the flux jacobian in x direction - * @param AyPlus Positive part of the flux jacobian in y direction - * @param AyMinus Negative part of the flux jacobian in y direction - * @param AzPlus Positive part of the flux jacobian in z direction - * @param AzMinus Negative part of the flux jacobian in z direction - * @param psiL Solution state of left hand side control volume - * @param psiR Solution state of right hand side control volume - * @param n Normal vector at the edge between left and right control volume - * @param resultFlux Vector with resulting flux. - * @return void - */ void UpwindFlux::FluxVanLeer( const Matrix& Ax, const Matrix& AxAbs, const Matrix& /*Ay*/, diff --git a/code/src/quadratures/qgausschebyshev1D.cpp b/code/src/quadratures/qgausschebyshev1D.cpp index 83fed6c..dd3e51c 100644 --- a/code/src/quadratures/qgausschebyshev1D.cpp +++ b/code/src/quadratures/qgausschebyshev1D.cpp @@ -40,7 +40,7 @@ bool QGaussChebyshev1D::CheckOrder() { return true; // All orders viable } -double QGaussChebyshev1D::Integrate( double( f )( double x0, double x1, double x2 ) ) { // Not Safe! +double QGaussChebyshev1D::Integrate( double ( *f )( double, double, double ) ) { // Not Safe! double result = 0.0; double x = 0.0; double y = 0.0; @@ -54,12 +54,12 @@ double QGaussChebyshev1D::Integrate( double( f )( double x0, double x1, double x return result; } -double QGaussChebyshev1D::IntegrateSpherical( double( f )( double my, double phi ) ) { +double QGaussChebyshev1D::IntegrateSpherical( double ( *f )( double, double ) ) { ErrorMessages::Error( "This method is not applicable for 1D quadratures.\n", CURRENT_FUNCTION ); return f( 0, 0 ); } -std::vector QGaussChebyshev1D::Integrate( std::vector( f )( double x0, double x1, double x2 ), unsigned /* len */ ) { +std::vector QGaussChebyshev1D::Integrate( std::vector ( *f )( double, double, double ), unsigned /* len */ ) { ErrorMessages::Error( "This method is not applicable for 1D quadratures.\n", CURRENT_FUNCTION ); return { f( 0, 0, 0 ) }; } diff --git a/code/src/quadratures/qgausslegendre1D.cpp b/code/src/quadratures/qgausslegendre1D.cpp index bcd75e8..4ebe7de 100644 --- a/code/src/quadratures/qgausslegendre1D.cpp +++ b/code/src/quadratures/qgausslegendre1D.cpp @@ -144,7 +144,7 @@ bool QGaussLegendre1D::CheckOrder() { return true; // All orders viable } -double QGaussLegendre1D::Integrate( double( f )( double x0, double x1, double x2 ) ) { // Not Safe! +double QGaussLegendre1D::Integrate( double ( *f )( double, double, double ) ) { // Not Safe! double result = 0.0; double x = 0.0; double y = 0.0; @@ -158,12 +158,12 @@ double QGaussLegendre1D::Integrate( double( f )( double x0, double x1, double x2 return result; } -double QGaussLegendre1D::IntegrateSpherical( double( f )( double my, double phi ) ) { +double QGaussLegendre1D::IntegrateSpherical( double ( *f )( double, double ) ) { ErrorMessages::Error( "This method is not applicable for 1D quadratures.\n", CURRENT_FUNCTION ); return f( 0, 0 ); } -std::vector QGaussLegendre1D::Integrate( std::vector( f )( double x0, double x1, double x2 ), unsigned /* len */ ) { +std::vector QGaussLegendre1D::Integrate( std::vector ( *f )( double, double, double ), unsigned /* len */ ) { ErrorMessages::Error( "This method is not applicable for 1D quadratures.\n", CURRENT_FUNCTION ); return { f( 0, 0, 0 ) }; } diff --git a/code/src/quadratures/quadraturebase.cpp b/code/src/quadratures/quadraturebase.cpp index 9e01bac..252fa38 100644 --- a/code/src/quadratures/quadraturebase.cpp +++ b/code/src/quadratures/quadraturebase.cpp @@ -52,7 +52,7 @@ QuadratureBase* QuadratureBase::Create( QUAD_NAME name, unsigned quadOrder ) { return nullptr; } -double QuadratureBase::Integrate( double( f )( double x0, double x1, double x2 ) ) { +double QuadratureBase::Integrate( double ( *f )( double, double, double ) ) { double result = 0.0; for( unsigned i = 0; i < _nq; i++ ) { result += _weights[i] * f( _points[i][0], _points[i][1], _points[i][2] ); @@ -60,7 +60,7 @@ double QuadratureBase::Integrate( double( f )( double x0, double x1, double x2 ) return result; } -double QuadratureBase::IntegrateSpherical( double( f )( double my, double phi ) ) { +double QuadratureBase::IntegrateSpherical( double ( *f )( double, double ) ) { double result = 0.0; for( unsigned i = 0; i < _nq; i++ ) { result += _weights[i] * f( _pointsSphere[i][0], _pointsSphere[i][1] ); @@ -68,7 +68,7 @@ double QuadratureBase::IntegrateSpherical( double( f )( double my, double phi ) return result; } -std::vector QuadratureBase::Integrate( std::vector( f )( double x0, double x1, double x2 ), unsigned len ) { +std::vector QuadratureBase::Integrate( std::vector ( *f )( double, double, double ), unsigned len ) { std::vector result( len, 0.0 ); std::vector funcEval( len, 0.0 ); diff --git a/doc/problems/phantom2d.rst b/doc/problems/phantom2d.rst index 00084d7..d7711de 100644 --- a/doc/problems/phantom2d.rst +++ b/doc/problems/phantom2d.rst @@ -1,5 +1,5 @@ Phantom2D -====== +========= .. doxygenclass:: Phantom2D :members: diff --git a/doc/solvers/index.rst b/doc/solvers/index.rst index 05e20fb..76a094c 100644 --- a/doc/solvers/index.rst +++ b/doc/solvers/index.rst @@ -14,4 +14,3 @@ Solvers mnsolver pnsolver snsolver - snsolvermpi diff --git a/doc/solvers/snsolvermpi.rst b/doc/solvers/snsolvermpi.rst deleted file mode 100644 index 4b6895c..0000000 --- a/doc/solvers/snsolvermpi.rst +++ /dev/null @@ -1,7 +0,0 @@ -SNSolverMPI -=========== - -.. doxygenclass:: SNSolverMPI - :members: - :protected-members: - :private-members: diff --git a/doc/toolboxes/index.rst b/doc/toolboxes/index.rst index 48ee538..ab666f1 100644 --- a/doc/toolboxes/index.rst +++ b/doc/toolboxes/index.rst @@ -6,6 +6,5 @@ Toolboxes errormessages interpolation - physics reconstructor sphericalharmonics diff --git a/doc/toolboxes/physics.rst b/doc/toolboxes/physics.rst deleted file mode 100644 index 8ce04b4..0000000 --- a/doc/toolboxes/physics.rst +++ /dev/null @@ -1,7 +0,0 @@ -Physics -======= - -.. doxygenclass:: Physics - :members: - :protected-members: - :private-members: -- GitLab From 2a245d789f7b913d82c40410b90a10a3ee16d311 Mon Sep 17 00:00:00 2001 From: Jannick Wolters Date: Sun, 28 Feb 2021 13:35:36 +0100 Subject: [PATCH 42/67] disabled doxygen html generation Former-commit-id: 5feed9eb7f58efeed4e25e02b72bf44903e54200 --- code/CMakeLists.txt | 2 +- doc/Doxyfile.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 3bd8355..54e9779 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -146,7 +146,7 @@ if( BUILD_DOC ) set( DOXYGEN_INPUT_DIR ${PROJECT_SOURCE_DIR} ) set( DOXYGEN_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/docs/doxygen ) - set( DOXYGEN_INDEX_FILE ${DOXYGEN_OUTPUT_DIR}/html/index.html ) + set( DOXYGEN_INDEX_FILE ${DOXYGEN_OUTPUT_DIR}/xml/index.xml ) set( DOXYFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/../doc/Doxyfile.in ) set( DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile ) configure_file( ${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY ) diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index de0f731..bef0cf3 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -1125,7 +1125,7 @@ IGNORE_PREFIX = # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. -GENERATE_HTML = YES +GENERATE_HTML = NO # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of -- GitLab From 9347ea1e8ec8791d78b67c0c627c139db51dd9a9 Mon Sep 17 00:00:00 2001 From: Jannick Wolters Date: Sun, 28 Feb 2021 13:43:51 +0100 Subject: [PATCH 43/67] removed [in/out] doc tags Former-commit-id: cf127ebb2c6d1624f68f76265e98fa919239edf3 --- code/include/common/config.h | 6 ++-- code/include/toolboxes/interpolation.h | 38 +++++++++++++------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/code/include/common/config.h b/code/include/common/config.h index b1bce95..6211bcd 100644 --- a/code/include/common/config.h +++ b/code/include/common/config.h @@ -163,9 +163,9 @@ class Config /*! * @brief breaks an input line from the config file into a set of tokens - * @param[in] str - the input line string - * @param[out] option_name - the name of the option found at the beginning of the line - * @param[out] option_value - the tokens found after the "=" sign on the line + * @param str the input line string + * @param option_name the name of the option found at the beginning of the line + * @param option_value the tokens found after the "=" sign on the line * @return false if the line is empty or a commment, true otherwise */ bool TokenizeString( std::string& str, std::string& option_name, std::vector& option_value ); diff --git a/code/include/toolboxes/interpolation.h b/code/include/toolboxes/interpolation.h index b8558f5..1c54e2b 100644 --- a/code/include/toolboxes/interpolation.h +++ b/code/include/toolboxes/interpolation.h @@ -38,56 +38,56 @@ class Interpolation // In constructor tabulated values are initialised /*! * @brief constructor linear interpolation for std::vector input - * @param[in] x - table values for x - * @param[in] y - table values for y - * @param[in] type - linear or cubic interpolation + * @param x table values for x + * @param y table values for y + * @param type linear or cubic interpolation */ Interpolation( const std::vector& x, const std::vector& y, TYPE type = linear ); /*! * @brief constructor linear interpolation for Vector input - * @param[in] x - table values for x - * @param[in] y - table values for y - * @param[in] type - linear or cubic interpolation + * @param x table values for x + * @param y table values for y + * @param type linear or cubic interpolation */ Interpolation( const Vector& x, const Vector& y, TYPE type = linear ); /*! * @brief constructor cubic interpolation - * @param[in] x table values for x - * @param[in] y table values for y - * @param[in] data matrix w.r.t x y grid - * @param[in] type of interpolation (linear, loglinear, cubic) + * @param x table values for x + * @param y table values for y + * @param data matrix w.r.t x y grid + * @param type of interpolation (linear, loglinear, cubic) */ Interpolation( const Vector& x, const Vector& y, const Matrix& data, TYPE type = cubic ); // Here the interpolation between the previously defined table values is performed /*! * @brief defines one dimensional interpolation at x - * @param[in] x - value at which to interpolate - * @returns y - corresponding interpolated y value + * @param x value at which to interpolate + * @returns corresponding interpolated y value */ double operator()( double x ) const; /*! * @brief defines interpolation for a Vector of values - * @param[in] v - values at which to interpolate - * @returns y - corresponding interpolated values + * @param v values at which to interpolate + * @returns corresponding interpolated values */ Vector operator()( Vector v ) const; /*! * @brief defines interpolation for a std::vector of values - * @param[in] v - values at which to interpolate - * @returns y - corresponding interpolated values + * @param v values at which to interpolate + * @returns corresponding interpolated values */ std::vector operator()( std::vector v ) const; /*! * @brief defines 2D interpolation at x and y - * @param[in] x - value at which to interpolate - * @param[in] y - value at which to interpolate - * @returns data - corresponding interpolated value + * @param x value at which to interpolate + * @param y value at which to interpolate + * @returns corresponding interpolated value */ double operator()( double x, double y ) const; }; -- GitLab From 8d5648d79ada0cb0c3156406b886a951990aea2a Mon Sep 17 00:00:00 2001 From: Jannick Wolters Date: Mon, 1 Mar 2021 13:47:06 +0100 Subject: [PATCH 44/67] removed compiler warnings Former-commit-id: 48647056578bba15cf8c1295d2aa584f9a32fce0 --- code/include/fluxes/laxfriedrichsflux.h | 2 +- code/include/solvers/mnsolver.h | 2 +- code/include/solvers/pnsolver.h | 2 +- code/include/solvers/snsolver.h | 2 +- code/src/common/config.cpp | 2 +- code/src/common/io.cpp | 3 ++- 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/code/include/fluxes/laxfriedrichsflux.h b/code/include/fluxes/laxfriedrichsflux.h index 287684d..b723719 100644 --- a/code/include/fluxes/laxfriedrichsflux.h +++ b/code/include/fluxes/laxfriedrichsflux.h @@ -5,7 +5,7 @@ class LaxFriedrichsFlux : public NumericalFlux { - double _dt; + // double _dt; public: /** diff --git a/code/include/solvers/mnsolver.h b/code/include/solvers/mnsolver.h index 6617200..683c6b1 100644 --- a/code/include/solvers/mnsolver.h +++ b/code/include/solvers/mnsolver.h @@ -72,6 +72,6 @@ class MNSolver : public SolverBase // Helper /*! @brief Computes the radiative flux from the solution vector of the moment system */ - void ComputeRadFlux(); + void ComputeRadFlux() override; }; #endif // MNSOLVER_H diff --git a/code/include/solvers/pnsolver.h b/code/include/solvers/pnsolver.h index 0312202..f9bd715 100644 --- a/code/include/solvers/pnsolver.h +++ b/code/include/solvers/pnsolver.h @@ -54,7 +54,7 @@ class PNSolver : public SolverBase void IterPostprocessing( unsigned idx_pseudotime ) override; // Helper - void ComputeRadFlux(); + void ComputeRadFlux() override; // Initialization of the Solver /*! @brief parameter functions for setting up system matrix diff --git a/code/include/solvers/snsolver.h b/code/include/solvers/snsolver.h index 2794135..a1f82e1 100644 --- a/code/include/solvers/snsolver.h +++ b/code/include/solvers/snsolver.h @@ -33,7 +33,7 @@ class SNSolver : public SolverBase void virtual IterPostprocessing( unsigned idx_pseudotime ) override; // Helper - void ComputeRadFlux(); + void ComputeRadFlux() override; // --- Member variables --- }; diff --git a/code/src/common/config.cpp b/code/src/common/config.cpp index ef391a4..70fc7b3 100644 --- a/code/src/common/config.cpp +++ b/code/src/common/config.cpp @@ -694,7 +694,7 @@ bool Config::TokenizeString( string& str, string& option_name, vector& o pos = str.find( "=" ); if( pos == string::npos ) { string errmsg = "Error in Config::TokenizeString(): line in the configuration file with no \"=\" sign. "; - errmsg += "\nLook for: \n str.length() = " + str.length(); + errmsg += "\nLook for: \n str.length() = " + std::to_string(str.length()); spdlog::error( errmsg ); throw( -1 ); } diff --git a/code/src/common/io.cpp b/code/src/common/io.cpp index 6609804..0c6b43b 100644 --- a/code/src/common/io.cpp +++ b/code/src/common/io.cpp @@ -197,7 +197,8 @@ Mesh* LoadSU2MeshFromFile( const Config* settings ) { getline( ifs, line ); if( line.find( "MARKER_TAG", 0 ) != std::string::npos ) { markerTag = line.substr( line.find( "=" ) + 1 ); - auto end_pos = std::remove_if( markerTag.begin(), markerTag.end(), isspace ); + auto end_pos = std::remove_if( + markerTag.begin(), markerTag.end(), []( char c ) { return std::isspace( static_cast( c ) ); } ); markerTag.erase( end_pos, markerTag.end() ); btype = settings->GetBoundaryType( markerTag ); if( btype == BOUNDARY_TYPE::INVALID ) { -- GitLab From fec51eef2bed747a417592d17e074b8f570b59e8 Mon Sep 17 00:00:00 2001 From: Jannick Wolters Date: Wed, 3 Mar 2021 11:39:01 +0100 Subject: [PATCH 45/67] added unity builds and new/changed cmake options Former-commit-id: fa18c4dd1c949842cad67620e869cf93b2b85492 --- .gitlab-ci.yml | 2 +- code/CMakeLists.txt | 22 ++++++++++++++++------ code/include/toolboxes/datageneratorbase.h | 2 +- code/src/common/io.cpp | 3 --- code/src/main.cpp | 1 + code/src/optimizers/mloptimizer.cpp | 1 - code/tests/catch2_main.cpp | 1 + 7 files changed, 20 insertions(+), 12 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7743c8b..8b24551 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,7 +8,7 @@ unit_tests: script: - git submodule update --init --recursive - cd code/build/debug - - cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=ON ../../ + - cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -DCODE_COV=ON ../../ - ninja - OMP_NUM_THREADS=1 ./unit_tests -r junit > unit_tests_report.xml - gcovr -e ../../ext/ -e ../../tests/ -r ../../ diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 54e9779..0d64051 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -2,9 +2,11 @@ cmake_minimum_required( VERSION 3.12.4 ) project( KiT-RT VERSION 0.1.0 LANGUAGES CXX ) ### OPTIONS ##################################### -option( BUILD_TESTS "builds all available unit tests" OFF ) +option( BUILD_TESTING "builds all available unit tests" OFF ) option( BUILD_GUI "additionally builds a user interface" OFF ) option( BUILD_DOC "builds Doxygen and Sphinx documentation" OFF ) +option( BUILD_UNITY "enables unity build for faster compile times" ON ) +option( BUILD_CODE_COV "enables compiler option required for code coverage analysis" OFF ) ################################################# @@ -14,6 +16,10 @@ set( CMAKE_CXX_STANDARD_REQUIRED ON ) set( KITRT_RELEASE_OPTIONS -march=native -w ) set( KITRT_RELWITHDEBINFO_OPTIONS -march=native -pg -no-pie ) set( KITRT_DEBUG_OPTIONS -Wall -Wextra -Wpedantic ) +if( BUILD_UNITY AND NOT CODE_COV ) + set( CMAKE_UNITY_BUILD ON ) + set( CMAKE_UNITY_BUILD_BATCH_SIZE 10 ) +endif() ################################################# @@ -87,7 +93,7 @@ target_compile_options( ${CMAKE_PROJECT_NAME} PUBLIC "$<$:${KITR ### BUILD UNIT TESTS ############################ -if( BUILD_TESTS ) +if( BUILD_TESTING ) include( CTest ) set( CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/ext/Catch2/contrib ${CMAKE_MODULE_PATH} ) include( Catch ) @@ -103,10 +109,14 @@ if( BUILD_TESTS ) target_compile_definitions( unit_tests PUBLIC TESTS_PATH="${CMAKE_SOURCE_DIR}/tests/" ) target_link_libraries( unit_tests Catch ${CORE_LIBRARIES} ) target_compile_options( unit_tests PUBLIC "$<$:${KITRT_DEBUG_OPTIONS}>" ) - if( CMAKE_COMPILER_IS_GNUCXX ) - set( CODE_COVERAGE_OPTIONS --coverage -g -O0 -w ) - target_compile_options( unit_tests PUBLIC "$<$:${CODE_COVERAGE_OPTIONS}>" ) - target_link_libraries( unit_tests Catch gcov ) + if( BUILD_CODE_COV ) + if( CMAKE_COMPILER_IS_GNUCXX ) + set( CODE_COVERAGE_OPTIONS --coverage -g -O0 -w ) + target_compile_options( unit_tests PUBLIC "$<$:${CODE_COVERAGE_OPTIONS}>" ) + target_link_libraries( unit_tests Catch gcov ) + else() + message( FATAL_ERROR "Code coverage is currently only supported for gcc!" ) + endif() endif() target_compile_options( unit_tests PUBLIC "$<$:${KITRT_RELWITHDEBINFO_OPTIONS}>" ) target_compile_options( unit_tests PUBLIC "$<$:${KITRT_RELEASE_OPTIONS}>" ) diff --git a/code/include/toolboxes/datageneratorbase.h b/code/include/toolboxes/datageneratorbase.h index 81f652b..cf2752a 100644 --- a/code/include/toolboxes/datageneratorbase.h +++ b/code/include/toolboxes/datageneratorbase.h @@ -24,7 +24,7 @@ class DataGeneratorBase * the options file. * @param settings config class with global information*/ DataGeneratorBase( Config* settings ); - ~DataGeneratorBase(); + virtual ~DataGeneratorBase(); /*! @brief Create a datagenerator (1D or 3D) * @param settings Pointer to the config file diff --git a/code/src/common/io.cpp b/code/src/common/io.cpp index 0c6b43b..ec1b8dd 100644 --- a/code/src/common/io.cpp +++ b/code/src/common/io.cpp @@ -22,7 +22,6 @@ #include #include #include -//#include #include #include #include @@ -31,7 +30,6 @@ #include #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION -#define PY_ARRAY_UNIQUE_SYMBOL KITRT_IO_ARRAY_API #include using vtkPointsSP = vtkSmartPointer; @@ -41,7 +39,6 @@ using vtkCellArraySP = vtkSmartPointer; using vtkDoubleArraySP = vtkSmartPointer; using vtkUnstructuredGridWriterSP = vtkSmartPointer; using vtkCellDataToPointDataSP = vtkSmartPointer; -// using vtkPointDataToCellDataSP = vtkSmartPointer; void ExportVTK( const std::string fileName, const std::vector>>& outputFields, diff --git a/code/src/main.cpp b/code/src/main.cpp index 757d40b..0a51c19 100644 --- a/code/src/main.cpp +++ b/code/src/main.cpp @@ -5,6 +5,7 @@ */ #include +#define PY_ARRAY_UNIQUE_SYMBOL KITRT_ARRAY_API #include #include diff --git a/code/src/optimizers/mloptimizer.cpp b/code/src/optimizers/mloptimizer.cpp index e0f7954..9153dfc 100644 --- a/code/src/optimizers/mloptimizer.cpp +++ b/code/src/optimizers/mloptimizer.cpp @@ -1,7 +1,6 @@ #define PY_SSIZE_T_CLEAN #include #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION -#define PY_ARRAY_UNIQUE_SYMBOL KITRT_MLOPT_ARRAY_API #include #include "common/config.h" diff --git a/code/tests/catch2_main.cpp b/code/tests/catch2_main.cpp index ea5a741..40dbb5b 100644 --- a/code/tests/catch2_main.cpp +++ b/code/tests/catch2_main.cpp @@ -2,6 +2,7 @@ #include "catch.hpp" #include +#define PY_ARRAY_UNIQUE_SYMBOL KITRT_ARRAY_API #include #include -- GitLab From 29b953788f73a050c1a765a8294689d1ff67ebac Mon Sep 17 00:00:00 2001 From: Jannick Wolters Date: Wed, 3 Mar 2021 10:58:59 +0000 Subject: [PATCH 46/67] Updated .gitlab-ci.yml Former-commit-id: a2316859e7101709150a754ecaa2e0e51530b4d5 --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8b24551..75e883e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,7 +8,7 @@ unit_tests: script: - git submodule update --init --recursive - cd code/build/debug - - cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -DCODE_COV=ON ../../ + - cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -DBUILD_CODE_COV=ON ../../ - ninja - OMP_NUM_THREADS=1 ./unit_tests -r junit > unit_tests_report.xml - gcovr -e ../../ext/ -e ../../tests/ -r ../../ -- GitLab From 0fb07b46361b2b8d95e79fab2d87a40300597e91 Mon Sep 17 00:00:00 2001 From: Jannick Wolters Date: Wed, 3 Mar 2021 12:38:40 +0100 Subject: [PATCH 47/67] configured to unity build to bundle all files Former-commit-id: 08cdd8133a29fd01e109fa6460305159c2b5b0d9 --- code/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 0d64051..04ee477 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -18,7 +18,7 @@ set( KITRT_RELWITHDEBINFO_OPTIONS -march=native -pg -no-pie ) set( KITRT_DEBUG_OPTIONS -Wall -Wextra -Wpedantic ) if( BUILD_UNITY AND NOT CODE_COV ) set( CMAKE_UNITY_BUILD ON ) - set( CMAKE_UNITY_BUILD_BATCH_SIZE 10 ) + set( CMAKE_UNITY_BUILD_BATCH_SIZE 0 ) endif() ################################################# -- GitLab From 22fe242225a0e3535c5708330a7a339468e84759 Mon Sep 17 00:00:00 2001 From: Jannick Wolters Date: Wed, 3 Mar 2021 12:49:28 +0100 Subject: [PATCH 48/67] increased cmake minimum version to 3.16 Former-commit-id: df96a4acd9a0af9a9431883fb8658adb6c7c3fb2 --- code/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 04ee477..357161e 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required( VERSION 3.12.4 ) +cmake_minimum_required( VERSION 3.16 ) project( KiT-RT VERSION 0.1.0 LANGUAGES CXX ) ### OPTIONS ##################################### -- GitLab From 4565f789abaec95dcb78362476627b4bc3bcca0e Mon Sep 17 00:00:00 2001 From: Jannick Wolters Date: Wed, 3 Mar 2021 14:05:13 +0100 Subject: [PATCH 49/67] patched code coverage issue with unity build Former-commit-id: 79cb2b7fa3f122fc6574b6e12b8441e30fe8c465 --- code/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 357161e..4b8ed4e 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -16,7 +16,8 @@ set( CMAKE_CXX_STANDARD_REQUIRED ON ) set( KITRT_RELEASE_OPTIONS -march=native -w ) set( KITRT_RELWITHDEBINFO_OPTIONS -march=native -pg -no-pie ) set( KITRT_DEBUG_OPTIONS -Wall -Wextra -Wpedantic ) -if( BUILD_UNITY AND NOT CODE_COV ) +if( BUILD_UNITY AND NOT BUILD_CODE_COV ) + message( STATUS "Unity build enabled" ) set( CMAKE_UNITY_BUILD ON ) set( CMAKE_UNITY_BUILD_BATCH_SIZE 0 ) endif() @@ -117,6 +118,8 @@ if( BUILD_TESTING ) else() message( FATAL_ERROR "Code coverage is currently only supported for gcc!" ) endif() + else() + target_link_libraries( unit_tests Catch ) endif() target_compile_options( unit_tests PUBLIC "$<$:${KITRT_RELWITHDEBINFO_OPTIONS}>" ) target_compile_options( unit_tests PUBLIC "$<$:${KITRT_RELEASE_OPTIONS}>" ) -- GitLab From a6abc7358b8436e7bef9f30b2ba334f9578e428a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Mon, 8 Mar 2021 18:50:19 +0100 Subject: [PATCH 50/67] added 2D Data Generator and example cfg file Former-commit-id: 03bec8b657ecf25aa711bc0ced2264ef338c7de7 --- code/include/toolboxes/datagenerator2D.h | 31 ++++ code/include/toolboxes/sphericalharmonics.h | 6 +- code/input/DataGenerator2D.cfg | 51 ++++++ ...{DataGenerator.cfg => DataGenerator3D.cfg} | 0 code/src/solvers/csdsolvertrafofpsh2d.cpp | 2 +- code/src/toolboxes/datagenerator2D.cpp | 164 ++++++++++++++++++ code/src/toolboxes/datageneratorbase.cpp | 3 +- code/src/toolboxes/sphericalmonomials.cpp | 6 +- 8 files changed, 255 insertions(+), 8 deletions(-) create mode 100644 code/include/toolboxes/datagenerator2D.h create mode 100644 code/input/DataGenerator2D.cfg rename code/input/{DataGenerator.cfg => DataGenerator3D.cfg} (100%) create mode 100644 code/src/toolboxes/datagenerator2D.cpp diff --git a/code/include/toolboxes/datagenerator2D.h b/code/include/toolboxes/datagenerator2D.h new file mode 100644 index 0000000..f0c96c2 --- /dev/null +++ b/code/include/toolboxes/datagenerator2D.h @@ -0,0 +1,31 @@ +/*! + * \file datagenerator3D.h + * \brief Class to generate data for the neural entropy closure in 3D spatial dimensions + * \author S. Schotthoefer + */ + +#ifndef DATAGENERATOR2D_H +#define DATAGENERATOR2D_H + +#include "toolboxes/datageneratorbase.h" + +class DataGenerator2D : public DataGeneratorBase +{ + public: + /*! @brief Class constructor. Generates training data for neural network approaches using + * spherical harmonics and an entropy functional and the quadrature specified by + * the options file. + * @param settings config class with global information*/ + DataGenerator2D( Config* settings ); + ~DataGenerator2D(); + + private: + // Main methods + void SampleSolutionU() override; /*!< @brief Samples solution vectors u */ + + // Helper functions + void ComputeMoments() override; /*!< @brief Pre-Compute Moments at all quadrature points. */ + void ComputeSetSize() override; /*!< @brief Computes the size of the training set, depending on the chosen settings.*/ + void CheckRealizability() override; // Debugging helper +}; +#endif // DATAGENERATOR2D_H diff --git a/code/include/toolboxes/sphericalharmonics.h b/code/include/toolboxes/sphericalharmonics.h index f717eaa..3cd6a1d 100644 --- a/code/include/toolboxes/sphericalharmonics.h +++ b/code/include/toolboxes/sphericalharmonics.h @@ -49,17 +49,17 @@ class SphericalHarmonics : public SphericalBase std::vector GetAssLegendrePoly( const double my ); /*! @brief Returns length of the basis, i.e. number of elements of the basis */ - unsigned GetBasisSize() override; + unsigned GetBasisSize() override final; /*! @brief Return number of basis functions with degree equals to currDegree * @param currDegreeL = degree of polynomials that are counted */ - unsigned GetCurrDegreeSize( unsigned currDegree ) override; + unsigned GetCurrDegreeSize( unsigned currDegree ) override final; /*! @brief helper function to get the global index for given k and l of * the basis function Y_k^l. * @param l_degree - current degree of basis function, 0 <= l <= L * @param k_order - current order of basis function, -l <= k <= l */ - unsigned GetGlobalIndexBasis( int l_degree, int k_order ) override; + unsigned GetGlobalIndexBasis( int l_degree, int k_order ) override final; private: /*! @brief maximal degree of the spherical harmonics basis (this is "L" in the comments)*/ diff --git a/code/input/DataGenerator2D.cfg b/code/input/DataGenerator2D.cfg new file mode 100644 index 0000000..59a0a98 --- /dev/null +++ b/code/input/DataGenerator2D.cfg @@ -0,0 +1,51 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Data Generator for % +% Neural Entropy Closure % +% Author % +% Date 17.12.2020 % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% ---- Global settings ---- +DATA_GENERATOR_MODE = YES +TRAINING_SET_SIZE = 20 +MAX_VALUE_FIRST_MOMENT = 5 +REALIZABLE_SET_EPSILON_U0 = 0.05 +REALIZABLE_SET_EPSILON_U1 = 0.97 +SPATIAL_DIM = 2 +% +% ---- File specifications ---- +% +% Output directory +OUTPUT_DIR = ../result +% Output file +OUTPUT_FILE = DataGenerator2D +% Log directory +LOG_DIR = ../result/logs +% +% --- Spherical Basis ---- +% +% Choice of basis functions +SPHERICAL_BASIS = SPHERICAL_MONOMIALS +% +% Maximal Moment degree +MAX_MOMENT_SOLVER = 1 +% +% --- Entropy settings ---- +ENTROPY_FUNCTIONAL = MAXWELL_BOLTZMANN +ENTROPY_OPTIMIZER = NEWTON +% +% ----- Newton Solver Specifications ---- +% +NEWTON_FAST_MODE = NO +NEWTON_ITER = 1000000 +NEWTON_EPSILON = 0.0001 +NEWTON_STEP_SIZE = 0.7 +NEWTON_LINE_SEARCH_ITER = 100000 +% +% ----- Quadrature ---- +% +% Quadrature Rule +QUAD_TYPE = GAUSS_LEGENDRE_TENSORIZED +% Quadrature Order +QUAD_ORDER = 8 +% diff --git a/code/input/DataGenerator.cfg b/code/input/DataGenerator3D.cfg similarity index 100% rename from code/input/DataGenerator.cfg rename to code/input/DataGenerator3D.cfg diff --git a/code/src/solvers/csdsolvertrafofpsh2d.cpp b/code/src/solvers/csdsolvertrafofpsh2d.cpp index 71bacaa..4a811d6 100644 --- a/code/src/solvers/csdsolvertrafofpsh2d.cpp +++ b/code/src/solvers/csdsolvertrafofpsh2d.cpp @@ -95,7 +95,7 @@ CSDSolverTrafoFPSH2D::CSDSolverTrafoFPSH2D( Config* settings ) : SNSolver( setti blaze::column( Y, q ) = sph.ComputeSphericalBasis( _quadPointsSphere[q][0], _quadPointsSphere[q][1] ); } - _O = Y; + //_O = Y; _O = blaze::trans( Y ); _M = _O; // transposed to simplify weight multiplication. We will transpose _M later again diff --git a/code/src/toolboxes/datagenerator2D.cpp b/code/src/toolboxes/datagenerator2D.cpp new file mode 100644 index 0000000..7b68df2 --- /dev/null +++ b/code/src/toolboxes/datagenerator2D.cpp @@ -0,0 +1,164 @@ +/*! + * \file datagenerator3D.cpp + * \brief Class to generate data for the neural entropy closure + * \author S. Schotthoefer + */ + +#include "toolboxes/datagenerator2D.h" +#include "common/config.h" +#include "quadratures/quadraturebase.h" +#include "toolboxes/errormessages.h" +#include "toolboxes/sphericalbase.h" + +#include +#include + +DataGenerator2D::DataGenerator2D( Config* settings ) : DataGeneratorBase( settings ) { + ComputeMoments(); + + // Initialize Training Data + ComputeSetSize(); + + _uSol = VectorVector( _setSize, Vector( _nTotalEntries, 0.0 ) ); + _alpha = VectorVector( _setSize, Vector( _nTotalEntries, 0.0 ) ); + _hEntropy = std::vector( _setSize, 0.0 ); +} + +DataGenerator2D::~DataGenerator2D() {} + +void DataGenerator2D::ComputeMoments() { + double my, phi; + + for( unsigned idx_quad = 0; idx_quad < _nq; idx_quad++ ) { + my = _quadPointsSphere[idx_quad][0]; + phi = _quadPointsSphere[idx_quad][1]; + _moments[idx_quad] = _basis->ComputeSphericalBasis( my, phi ); + } +} + +void DataGenerator2D::SampleSolutionU() { + // Use necessary conditions from Monreal, Dissertation, Chapter 3.2.1, Page 26 + + // --- Determine stepsizes etc --- + double du0 = _settings->GetMaxValFirstMoment() / (double)_gridSize; + + // different processes for different + if( _LMaxDegree == 0 ) { + // --- sample u in order 0 --- + // u_0 = <1*psi> + + for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { + _uSol[idx_set][0] = du0 * idx_set; + } + } + else if( _LMaxDegree == 1 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS ) { + // Sample points on unit sphere. + QuadratureBase* quad = QuadratureBase::Create( _settings ); + VectorVector qpoints = quad->GetPoints(); // carthesian coordinates. + unsigned long nq = (unsigned long)quad->GetNq(); + + // --- sample u in order 0 --- + // u_0 = <1*psi> + +#pragma omp parallel for schedule( guided ) + for( unsigned long idx_set = 0; idx_set < _gridSize; idx_set++ ) { + unsigned long outerIdx = ( idx_set - 1 ) * ( idx_set ) / 2; // sum over all radii up to current + outerIdx *= nq; // in each radius step, use all quad points + + // --- sample u in order 1 --- + /* order 1 has 3 elements. (omega_x, omega_y, omega_z) = omega, let u_1 = (u_x, u_y, u_z) = + * Condition u_0 >= norm(u_1) */ + double radiusU0 = du0 * ( idx_set + 1 ); + // Boundary correction + if( radiusU0 < _settings->GetRealizableSetEpsilonU0() ) { + radiusU0 = _settings->GetRealizableSetEpsilonU0(); // Boundary close to 0 + } + + unsigned long localIdx = 0; + double radius = 0.0; + unsigned long innerIdx = 0; + // loop over all radii + for( unsigned long idx_subset = 0; idx_subset < idx_set; idx_subset++ ) { + radius = du0 * ( idx_subset + 1 ); // dont use radius 0 ==> shift by one + // Boundary correction + if( radius < _settings->GetRealizableSetEpsilonU0() ) { + radius = _settings->GetRealizableSetEpsilonU0(); // Boundary close to 0 + } + if( radius / radiusU0 > 0.95 * _settings->GetRealizableSetEpsilonU1() ) { + // small offset to take care of rounding errors in quadrature + radius = radiusU0 * 0.95 * _settings->GetRealizableSetEpsilonU1(); // "outer" boundary + } + + localIdx = outerIdx + idx_subset * nq; + + for( unsigned long quad_idx = 0; quad_idx < nq; quad_idx++ ) { + innerIdx = localIdx + quad_idx; // gives the global index + + _uSol[innerIdx][0] = radiusU0; // Prevent 1st order moments to be too close to the boundary + // scale quadpoints with radius + _uSol[innerIdx][1] = radius * qpoints[quad_idx][0]; + _uSol[innerIdx][2] = radius * qpoints[quad_idx][1]; + //_uSol[innerIdx][3] = radius * qpoints[quad_idx][2]; + } + } + } + } + else { + ErrorMessages::Error( "Sampling for this configuration is not yet supported", CURRENT_FUNCTION ); + } +} + +void DataGenerator2D::CheckRealizability() { + double epsilon = _settings->GetRealizableSetEpsilonU0(); + if( _LMaxDegree == 1 ) { +#pragma omp parallel for schedule( guided ) + for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { + double normU1 = 0.0; + Vector u1( 3, 0.0 ); + if( _uSol[idx_set][0] < epsilon ) { + if( std::abs( _uSol[idx_set][1] ) > 0 || std::abs( _uSol[idx_set][2] ) > 0 ) { + ErrorMessages::Error( "Moment not realizable [code 0]. Values: (" + std::to_string( _uSol[idx_set][0] ) + "|" + + std::to_string( _uSol[idx_set][1] ) + "|" + std::to_string( _uSol[idx_set][2] ) + ")", + CURRENT_FUNCTION ); + } + } + else { + u1 = { _uSol[idx_set][1], _uSol[idx_set][2] }; + normU1 = norm( u1 ); + if( normU1 / _uSol[idx_set][0] > _settings->GetRealizableSetEpsilonU1() ) { // Danger Hardcoded + std::cout << "normU1 / _uSol[" << idx_set << "][0]: " << normU1 / _uSol[idx_set][0] << "\n"; + std::cout << "normU1: " << normU1 << " | _uSol[idx_set][0] " << _uSol[idx_set][0] << "\n"; + ErrorMessages::Error( "Moment to close to boundary of realizable set [code 1].\nBoundary ratio: " + + std::to_string( normU1 / _uSol[idx_set][0] ), + CURRENT_FUNCTION ); + } + if( normU1 / _uSol[idx_set][0] <= 0 /*+ 0.5 * epsilon*/ ) { + // std::cout << "_uSol" << _uSol[idx_set][1] << " | " << _uSol[idx_set][2] << " | " << _uSol[idx_set][3] << " \n"; + // std::cout << "normU1 / _uSol[" << idx_set << "][0]: " << normU1 / _uSol[idx_set][0] << "\n"; + // std::cout << "normU1: " << normU1 << " | _uSol[idx_set][0] " << _uSol[idx_set][0] << "\n"; + ErrorMessages::Error( "Moment to close to boundary of realizable set [code 2].\nBoundary ratio: " + + std::to_string( normU1 / _uSol[idx_set][0] ), + CURRENT_FUNCTION ); + } + } + } + } +} + +void DataGenerator2D::ComputeSetSize() { + if( _LMaxDegree == 0 ) { + } + else if( _LMaxDegree == 1 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS ) { + // Sample points on unit sphere. + QuadratureBase* quad = QuadratureBase::Create( _settings ); + unsigned long nq = (unsigned long)quad->GetNq(); + + // Allocate memory. + _setSize = nq * _gridSize * ( _gridSize - 1 ) / 2; + + delete quad; + } + else { + ErrorMessages::Error( "Sampling of training data of degree higher than 1 is not yet implemented.", CURRENT_FUNCTION ); + } +} diff --git a/code/src/toolboxes/datageneratorbase.cpp b/code/src/toolboxes/datageneratorbase.cpp index e48ff2b..cee1808 100644 --- a/code/src/toolboxes/datageneratorbase.cpp +++ b/code/src/toolboxes/datageneratorbase.cpp @@ -11,6 +11,7 @@ #include "quadratures/quadraturebase.h" #include "spdlog/spdlog.h" #include "toolboxes/datagenerator1D.h" +#include "toolboxes/datagenerator2D.h" #include "toolboxes/datagenerator3D.h" #include "toolboxes/errormessages.h" #include "toolboxes/sphericalbase.h" @@ -69,7 +70,7 @@ DataGeneratorBase::~DataGeneratorBase() { DataGeneratorBase* DataGeneratorBase::Create( Config* settings ) { switch( settings->GetDim() ) { case 1: return new DataGenerator1D( settings ); - case 2: ErrorMessages::Error( "2D Sampling is not yet supported.", CURRENT_FUNCTION ); + case 2: return new DataGenerator2D( settings ); case 3: return new DataGenerator3D( settings ); default: ErrorMessages::Error( "Sampling for more than 3 dimensions is not yet supported.", CURRENT_FUNCTION ); } diff --git a/code/src/toolboxes/sphericalmonomials.cpp b/code/src/toolboxes/sphericalmonomials.cpp index df76dfd..280c740 100644 --- a/code/src/toolboxes/sphericalmonomials.cpp +++ b/code/src/toolboxes/sphericalmonomials.cpp @@ -130,9 +130,9 @@ double SphericalMonomials::Omega_y( double my, double phi ) { return sqrt( 1 - m double SphericalMonomials::Omega_z( double my ) { return my; } double SphericalMonomials::Power( double basis, unsigned exponent ) { - if( exponent == 0 ) return 1.0; - double result = basis; - for( unsigned i = 1; i < exponent; i++ ) { + if( exponent == 0 ) return 1.0; // basis^0 + double result = basis; // basis^1 + for( unsigned i = 1; i < exponent; i++ ) { // exp> 1 result = result * basis; } return result; -- GitLab From c9d6a1451edcdf522d196d89b75a6b9661c4d107 Mon Sep 17 00:00:00 2001 From: Steffen Date: Tue, 9 Mar 2021 10:13:01 +0100 Subject: [PATCH 51/67] checkerboard IC supports monomial basis now. Renamed to checkerboard_moment for clarity. mn solver works with 2d quadrature now Former-commit-id: 45f3488d58ea1b8320323a1fb21b89cf4eac9847 --- code/include/problems/checkerboard.h | 11 ++++++---- code/input/checkerboard_MN.cfg | 1 + code/src/fluxes/upwindflux.cpp | 2 +- code/src/problems/checkerboard.cpp | 32 ++++++++++++++-------------- code/src/problems/problembase.cpp | 2 +- 5 files changed, 26 insertions(+), 22 deletions(-) diff --git a/code/include/problems/checkerboard.h b/code/include/problems/checkerboard.h index f521b6b..41bb833 100644 --- a/code/include/problems/checkerboard.h +++ b/code/include/problems/checkerboard.h @@ -3,6 +3,8 @@ #include "problembase.h" +class SphericalBase; + class Checkerboard_SN : public ProblemBase { private: @@ -24,13 +26,14 @@ class Checkerboard_SN : public ProblemBase virtual VectorVector SetupIC() override; }; -class Checkerboard_PN : public ProblemBase +class Checkerboard_Moment : public ProblemBase { private: Vector _scatteringXS; /*!< @brief Vector of scattering crosssections len: numCells */ Vector _totalXS; /*!< @brief Vector of total crosssections. len: numCells*/ + SphericalBase* _basis; /*!< @brief Class to compute and store current spherical harmonics basis */ - Checkerboard_PN() = delete; + Checkerboard_Moment() = delete; bool isAbsorption( const Vector& pos ) const; /*!< @return True if pos is in absorption region, False otherwise */ bool isSource( const Vector& pos ) const; /*!< @return True if pos is in source region, False otherwise */ @@ -46,8 +49,8 @@ class Checkerboard_PN : public ProblemBase int GlobalIndex( int l, int k ) const; public: - Checkerboard_PN( Config* settings, Mesh* mesh ); - virtual ~Checkerboard_PN(); + Checkerboard_Moment( Config* settings, Mesh* mesh ); + virtual ~Checkerboard_Moment(); virtual VectorVector GetScatteringXS( const Vector& energies ) override; virtual VectorVector GetTotalXS( const Vector& energies ) override; diff --git a/code/input/checkerboard_MN.cfg b/code/input/checkerboard_MN.cfg index 0e3043b..bac1944 100644 --- a/code/input/checkerboard_MN.cfg +++ b/code/input/checkerboard_MN.cfg @@ -18,6 +18,7 @@ MESH_FILE = meshes/checkerboard.su2 % ---- Problem specifications ---- % PROBLEM = CHECKERBOARD +SPATIAL_DIM = 2 % % ---- Solver specifications ---- % diff --git a/code/src/fluxes/upwindflux.cpp b/code/src/fluxes/upwindflux.cpp index c3ddb74..b46d91d 100644 --- a/code/src/fluxes/upwindflux.cpp +++ b/code/src/fluxes/upwindflux.cpp @@ -3,7 +3,7 @@ UpwindFlux::UpwindFlux() : NumericalFlux() {} double UpwindFlux::Flux( const Vector& Omega, double psiL, double psiR, const Vector& n ) const { - double inner = Omega[0] * n[0] + Omega[1] * n[1]; + double inner = Omega[0] * n[0] + Omega[1] * n[1]; // Only use x and y axis in 2d case if( inner > 0 ) { return inner * psiL; } diff --git a/code/src/problems/checkerboard.cpp b/code/src/problems/checkerboard.cpp index b986348..5e939e9 100644 --- a/code/src/problems/checkerboard.cpp +++ b/code/src/problems/checkerboard.cpp @@ -1,6 +1,7 @@ #include "problems/checkerboard.h" #include "common/config.h" #include "common/mesh.h" +#include "toolboxes/sphericalbase.h" // ---- Checkerboard Sn ---- // Constructor for Ckeckerboard case with Sn @@ -66,9 +67,12 @@ bool Checkerboard_SN::isSource( const Vector& pos ) const { //////////////////////////////////////////////////////////////////////////////////////////////////// -// ---- Checkerboard Pn ---- +// ---- Checkerboard Moments ---- + // Constructor for checkerboard case with Pn -Checkerboard_PN::Checkerboard_PN( Config* settings, Mesh* mesh ) : ProblemBase( settings, mesh ) { +Checkerboard_Moment::Checkerboard_Moment( Config* settings, Mesh* mesh ) : ProblemBase( settings, mesh ) { + + _basis = SphericalBase::Create(_settings); _physics = nullptr; // Initialise crosssections = 1 (scattering) @@ -85,13 +89,15 @@ Checkerboard_PN::Checkerboard_PN( Config* settings, Mesh* mesh ) : ProblemBase( } } -Checkerboard_PN::~Checkerboard_PN() {} +Checkerboard_Moment::~Checkerboard_Moment() { + delete _basis; +} -VectorVector Checkerboard_PN::GetScatteringXS( const Vector& energies ) { return VectorVector( energies.size(), _scatteringXS ); } +VectorVector Checkerboard_Moment::GetScatteringXS( const Vector& energies ) { return VectorVector( energies.size(), _scatteringXS ); } -VectorVector Checkerboard_PN::GetTotalXS( const Vector& energies ) { return VectorVector( energies.size(), _totalXS ); } +VectorVector Checkerboard_Moment::GetTotalXS( const Vector& energies ) { return VectorVector( energies.size(), _totalXS ); } -std::vector Checkerboard_PN::GetExternalSource( const Vector& /*energies*/ ) { +std::vector Checkerboard_Moment::GetExternalSource( const Vector& /*energies*/ ) { VectorVector Q( _mesh->GetNumCells(), Vector( 1u, 0.0 ) ); auto cellMids = _mesh->GetCellMidPoints(); for( unsigned j = 0; j < cellMids.size(); ++j ) { @@ -100,13 +106,13 @@ std::vector Checkerboard_PN::GetExternalSource( const Vector& /*en return std::vector( 1u, Q ); } -VectorVector Checkerboard_PN::SetupIC() { - int ntotalEquations = GlobalIndex( _settings->GetMaxMomentDegree(), _settings->GetMaxMomentDegree() ) + 1; +VectorVector Checkerboard_Moment::SetupIC() { + int ntotalEquations = _basis->GetBasisSize(); VectorVector psi( _mesh->GetNumCells(), Vector( ntotalEquations, 1e-10 ) ); return psi; } -bool Checkerboard_PN::isAbsorption( const Vector& pos ) const { +bool Checkerboard_Moment::isAbsorption( const Vector& pos ) const { // Check whether pos is in absorption region std::vector lbounds{ 1, 2, 3, 4, 5 }; std::vector ubounds{ 2, 3, 4, 5, 6 }; @@ -121,16 +127,10 @@ bool Checkerboard_PN::isAbsorption( const Vector& pos ) const { return false; } -bool Checkerboard_PN::isSource( const Vector& pos ) const { +bool Checkerboard_Moment::isSource( const Vector& pos ) const { // Check whether pos is in source region if( pos[0] >= 3 && pos[0] <= 4 && pos[1] >= 3 && pos[1] <= 4 ) return true; else return false; } - -int Checkerboard_PN::GlobalIndex( int l, int k ) const { - int numIndicesPrevLevel = l * l; // number of previous indices untill level l-1 - int prevIndicesThisLevel = k + l; // number of previous indices in current level - return numIndicesPrevLevel + prevIndicesThisLevel; -} diff --git a/code/src/problems/problembase.cpp b/code/src/problems/problembase.cpp index b678716..66b6280 100644 --- a/code/src/problems/problembase.cpp +++ b/code/src/problems/problembase.cpp @@ -30,7 +30,7 @@ ProblemBase* ProblemBase::Create( Config* settings, Mesh* mesh ) { } case PROBLEM_Checkerboard: { if( settings->GetSolverName() == PN_SOLVER || settings->GetSolverName() == MN_SOLVER ) - return new Checkerboard_PN( settings, mesh ); + return new Checkerboard_Moment( settings, mesh ); else return new Checkerboard_SN( settings, mesh ); // default } -- GitLab From 030be19238fc9ef79150ed1fd6cac95826087b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Fri, 12 Mar 2021 11:00:00 +0100 Subject: [PATCH 52/67] added logo to repo Former-commit-id: f93f4a95adaef009626c86ac01a95a12cf75bd30 --- kitrt.png | Bin 0 -> 97383 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 kitrt.png diff --git a/kitrt.png b/kitrt.png new file mode 100644 index 0000000000000000000000000000000000000000..676cec225e77e0ce8015a7986ee1b62db468a64d GIT binary patch literal 97383 zcmeFYXH=6x*Df4DEJ&3qRY5?yNbf2H5D=sW>4Nm$I{`%vB_PriDN1jlNUx!Xj`R-F zdkGyvlJE9;-}CcZ>-;}YR+3q{*P7XTX7;{zO~h+W6*3Y=5)cSP_EJ?z2L!rN_V081 zCh%nEVZ{&#MDWpGQStRlMa2hh91f=$U#IcI zA|)MYBVRupBSA=iGr79;it#HAy-I7<-@ika`|{~e^W1QPxv^aeWasY3lGv4D#->h9aIJh`pcfn!tsKt*WKQoD-wgm$;9dRg+~kg zmv5IF+F9km-wcnz@?cqoxw_3?(1vS`op1OcZ;sQiKmJN>{@w4L(ynSjrT*o?i|4eQ z32!-+8#E(7(xjn+uN6zo*^^(C++&cUdmVOj`t$?7^oT=ua~dDw^m8%$+;d^_4=Yfpa-Cr zO3(HDW_IWOQ<-i3xeqrG``?G71=X8{<)xg65nKUohvxC}D;tz5+ z?C*)fX|lGR^K}#cJ=6mX?z6R=hrtRw;Sdo2XA;2h=D+s}Cn@fwG0P!%!wqUzA_jzx zH2iHz8)0bs|DAz0n7jeX+F95;@9J+3WQ@Z^=0T{ z@=Oi1f-5s2fh%bom9(f5_Dg|d4a@i|-d#eXG@Bs5EKSC@^W@~@IZjL_=5n{hs2*buTT-#5MucAEVy1JI+N72k92gmh+77Tua{_S6a=Qv8`m z&SF+>Qds)f@nIw3PY9qBa^iAwEHXa3u+AkNZ5s6D5L6g`1Iei6e{^@HHr_zUG$a7Jo0bljahaJe{;9UMlD9B!M)s+aT^BjF(en;zo)JQ2 z=I!FfSIT@2iWVfGdv+)AY&Qa7Tr==lAFSOm4uQ&~U+h5dqZXm2*^(y`M|n|n&Z#|i9fAvX-G(huS@2PU25YvsTki5X*g zsT_G@Mv#bzcQL9wHLOd`lrO3p#H2Q0dR3o=NAIp!aVx7;RmTi!#_r>KP2ZsAlDYNF zjh3qOdqd==s!27cwl5(d?86p9$(DsCk#g(4`D6M~aNIIx5h=)ezG>UpwZg^0Zn@Yz zou5-aRc~*;^SgmoKBxR~<^*mJT6b!stweSDSlaJ4X8CjNId2PZ=E8B0iU7Py?ABlb z6%Qj~D*w8Ma@|g85DxR<&0iJjuNzld0)b;HgoCg{R+-_L{9B+0@8yhZh*Jc?VHTQNh zi7sk3OezDDc|eqr033BTP@#?sMptIuXB<}}HY_+DVvo!RH)Vkwmbf}BL$2yZs8pz| zQdKt$#8frc+VkqHZ{-z+Yrcxfm>`J^ z{LYt6a>LMHn|_EhrfvfLRd;tDs=ju9yyOCRnQ)|wQ;Rj{oOLH&+`B&b&6hL|xtVxe z8KPEmyDT*BDZQQ;H_p?ul15@NNL_Xbf@kmI-Y$3LLN#x}f=AW4?|epD3k;yNz`X7l z^GH>HK_7>Y7CCK2bv&_2#%7?o3<<=wwG?K|3{6-uX^s;Q9VhIs(`@G_J* zI^oq1ag-2l&b6~7O+=mBUb_Qe=KGe(_AI{e7y-qWeq$g`3n_Xlk()7{9h-i3)>;*~ zezPHNpM@$NO8iHHkl$i;cSedjFwZtws2L`djr%S$fJ z1$+!~HTS6^~i^hKx>39 zgqHI|*7|Qxq)tJ^;@l2>RCV5U5`Xc-PBn;5w!DVdkG)FSI{nK8BZW0Fqf!&480FRK zMc?$rv$^M{hDJKS^5`7DdfRZq5}Ve6fZZu$_edNqb*QTH+U?|=h^M*>z92& zhl%v;#bz1-k#m^$3q~b1v=(dK#{wgdr5+AxSF)EW@8tD6r+Z37BpHW<$Q2CFuu{)F zuL>Cdz@9Vn+$z##f-EV$a;Pa}TQ@Y3L#J20ZK2cnx95fG;aA4 zNt@hw2t~a()x(AwAIvly3VIX~I^x7z)`rg4c?BJ$zyc21JDUbw>qV3GPYKNSd$K7A z3|u5ydWY>gA@FYkVvydrtT-FMF&KF1U2w;H|HVZDy?{^)qo~TObfzi>ncdJY($XQi zlP|(5{b&p3%^24(wvn(#(MF@7MyJK#f!AknuWt@DHg4mv1f7W4CdiWbc zYY3*1LxS?b2zbOvTScjds2Xy8j;3C!KnN|17%Rp(?&rANFeIZjB(iBAyNuIuUqwIi zHnNUS5=NVC@jTyGgV7dHMIl=~XHRNWJlGR;%=Ch-+s668Mpbizh20U@Q?oFCh#yYP# zL01eN0|ox6j5DD1?^uFQy8Px`uO-L`iff09nzu_3ql+WAK~I)%7`CW7it3eu_|*M~ ziKMlSCIB_woUSdt0|FU*IxO@w&MTd`4GIP1-g##N0Y?T*uZZ3F_T0NchvTdbeJU0|Yw0Vfci-1c|$f44xPJ+L#0;Y7F>4z8rY0Zvnt$gzt zyl5Go+$<2XPCIWX{WleONo1feuBk=kNVAf9z;8A}X zA_F+{bzY$9G?bG+S&HpqTEI4c>t?b%+J{s9@KNp!TUu|IS-|G}R^aX%xed!%8CQ9J19yesSKoK6f+pW- zxGcD3AZ42QmLrC+Q5UT!1&Jd910^MwcPzIzVZdPm7xMQta1M`L8ZUD%KKq)pmiq6_ zW`=ZOEl)pa#(1sZ6mi%Y318*CxV%pN#b)UksjE%H3Y&rMnzu19=79%%;BB{81?|pT zT|Q+xP1#I+8}cs1^OJyHyDaAZlCnus@dNAs!*j7aWfm>-exq=A48SOL#+61Rj!l8C zC{}@U#Mg#>xtoHEZ82>*Lg@O(#gc!`h6Fbigb< z!PWCnVxo5e0n#qD=ucDiD+?F>w(@Mrjh9Wr%?^si%{#T#rD8feBDez6Q@^7{{40}l zs|=Pc5Z?x~m4C5P=(xsn9T!bWM{Om6@m|0qy5B2GRJ^`gHE&|)(idgGFj3Su6u`FK z*)=QqajiSfGiKU=|4BnMNv9$rj}8prE&LvV-k_(WeZR_UYeqq~TJo#)+HnQyD$#{C zd#k#`tG`*#6}U5{Ua&bI%YGpj3CV`pRq7PK2(Nk(DLTC_9G}eWyA~54!kVYTs;-=D zMT*UG0L1EnOa0~g#f(Hrq*lmw1$vkQ%E^^Gfl5K3d_}7wRE1AZnMLsE)r%TFBpp+X zw8J~L&1Uo_85&X=7}U7Fg*PlAETWAbTjwi_td`eG3#_UmDK>I&R-6TVIqCd5;(?ym zLh_S{8hx^H7OOtVj{=S7HgmfDlRaW;rh%*7!c0|m9Zsubq@6R!x$jXKjKeR94HQGi zeb0@LGcwb=4BoYUOVZO?vx7eRhG}Ax;K(z~hsXvgAiX!}y|Q!AJ->{_*4FVuRN5Zb zZ*#5!xv6JFpB=c4y$Itq=xVj2ws_t-?=||$eFY(bN^U;GFOMfT$#D5PM~gMYMop!y zw?}wP-t?r-W}ncYM+XjJe_Y_Su2;Kn8mh2V$%ib_vr(1CY9*xX(;nAQxPXn$g-zCvt;rsh=bcS-KJ)e# zmPSg#$Tm{>k*^q@#FZznZV+ytLdaxiKBdR+(ZEe!J{vrb{z$ zk;8C_4oC?uz~nl{w`+CEz1(IoB2Iiju&(%Vpnu%D!gnFdqaQprtnNlMr^BrGY;2j1 zYbcZKhw3Pcb}RC9lxTRsaYi-x9FLlZ;*+DK;{jr=JXeQfTRt;>`){=CyzNcAu6GM; z%zHQ|hhfSzR4n0Ibz&c#Z(!?91P$Eg)8GepInh`K_ex1L2xA z{3Sl9{ZY$i{>4;a)9uoF;bw^U14;nytO05ywWq+gep56`uwth2y7+`JZpAOTJ63(S zwHtiQwQ8(P_r6^mDa88FPVDX$liy+1D+Q1qw67jY9PHI6P}7m8fUonLRFS7Cty|72 z-ygfxvFcrv8Da{3kx&jWx3>&IHOZ(*v`DW{!O_JM`1-*+{0|$qQvtXACp97eX8i1a zt=s~j&|R+b=RzxAeS>5T4(2GUm@xQf>tal?Q9>bW87kEzj{mln2VD&pzLY1_AAjLp+zKaGKu(K87^C{3&u`xDhs)qz0zQE0!W*4m|?L_b-g z1wHcy%rNnM$Oa2KhN4M9u=WHYEam>9xG00BiUq@qoL_kW(OW8j32n~C?Kv_T`2wmL(TW3d_@7(ga%Bz>DTsisI8Qn zt+aWSsNAJ}OB=I*gKgUQC33KPzul^vU86%3!5C&!m+edI9QmdN|74DDFLHr{uuLyqrqFj-?tnIV7hl{q^+BcicCE4Dp2=Re(RVnSoyHkf*$0m` zBkxhzX_*>H&-Sa0q$2K>qQq3BhKd#up5ax^3vYqMx(?x+9i?Cyv0QQ%ry z4uK4lsRxS1w*!L2Rb4E>YdVS+4_ggumOAq1n|=c;-nyGHV}kplPEU3E3VglgC>Wt4 zca*GrAl~NfxZKDV*!|mBLg1@gZ9(W)yq>ze?$HvpM$oTg_?V+=t zpAY1QVhOxPc^uhj=OsOKP;qy($GTY*vX4w z)0$581$??;V7s1%%Nr*5oo2(H3k&pWZvQ*UwK_2x^$96FSx^NP_2M^pJZrGp*mjnb zo+u;STI*UzRNaUkZ)VeG+>gzMCG;Y!&;dHJ>j*4NTjvK#-7_*S>l;PJ3`8krPFhpP z3}?X4oaJwy|7X3m;ex@LwE_M!P}B67&-6}UA(dH9jKZqjWULR4Ee#f?OEZ5FS~42T znJBGumi3P9e7M9GP9%kC6#tIjTJbOJxAx< zPhxWT&290=-0|h&3nnqJRQAZZ=<~?0^a5~MdQ7ezf8n;n0cAhJI;vYrrLMiUE=ieB zC(Dz<@OaURze}1qqoMpAKjUHpttA1UXXT(k21Nj30@LGH_r*66ty?9F9^$`#{=g**=7pOKf^RY8VvR=?P*&CS!@{(Wo}gR*1iZGFYq)_5Z;aw{9G?3@B38RmoH!&9PT}SBIEt&rVe7t zuchawiQR}vA#aU0gr}vKvj*z&<{_P1%PEp8bZxrQUN`9Mt~qRWe~u>E>~KqReO1?L zx7w?v$EPlDtzA#9%G-ZrYfqr>+aoddZAgwEE`@KIn>EBtc6ax4$JEr6>h3Xf`L0@F z-57zOqqw)1{oI^E7>DO&_K1Q{O_s}Q`gvJA(saP-L&`yNfLVuIq| zIzaJ*`pyG*QZ%P3@AQW5>e1{Eqn++ylApcBJig4&Ho&ckcTbK6jj`F7-Ork+4X>7f zEAJSXpc5)C$oc9ipvU5~wJIE>-`No(x2fWeL*Om1?^(3I?cbeeT14*GU#vo!DN8R; zY*(g&^H5V7-mEEe6@PwG37@4IH3rW^R>Evk@5MrQT{}|596yENOU*=RZRJm*xA!PM zJB*CH}?HxMB@oq?)VDl~w}`Qu2)FB#r&&@3Z=T@H;txZdo#*!^4@ku~WWeMM0u z_I7v6>VKYN%O0Hzy4C$fJcPIFxd38vN47zVAS}eT2oK1(P95>&1XUozkwZL zZD~V|Q$!7LsOaA{A(G99!#kEoNn*l2@XND8wrJGuj96Uc@O^1b>C14xtH6-a=LCwD zlx;munT+~ctoRna!nN-*2?>)okxt49k*FY{6vhWrjz_5v9!fXu-^`XRbuovIDCJ96ly z*kJzZ-8tHWpaJ@o{2p&@Oq`EYv9i+MC!7>JXnHfb2&;V-4lgd)3a1tgZp5HTO#lj#G2WS1%fyKezheUu7{q zUXz=rfY0%<#C=T+hk+?17LljbX?+j^xkeu-a84Az5gEfi-U#X*Q^;B8CIm-5)`?_K zoM!UulYr_tC}gS*&&1fdII1;$zfB+f&9&w@MM`CrW*7!b=z|7~!e|P{tK)Pkbhw1@ zhxYPn0##-TDltb^+A(uM3h#?Ceiz%^D%!tIrCBmYpDRy#>}+=3Uc^nYQlVW(T_+wC$i-A_N`%UPjNt|)9J|;6JKK$377rHGUbMiK@wagdz#}( z{o|e;^=u_E=T6wXiwrH?{I3J8ymWWG-vq5z^rRe`=-mDbJG(={rLIsf@gq+H13BjA)ls>A$75 z=1QwR+$|N^ome+t%p2lydH|MlV2O#ql9%a-R&0#boD+avixKjFnrJ#-U~&b#Q*@V5 z&_m678^z-J%K9w(g%_v#HC$0?(BBIKprSF43MwlJn)1C?ARY->A4Turu@EZ<2M0UM z*y?IwEuM$F<6^lmcYi_4=G%!W_%8x_KvhDKhw8cY6hPfTtYlBNY?&N`9MgFtloP>A$G$QnLM z#HGPp!>L4!JBFpC;Rmf@TKbO$S_^OSmr<%xouAl>qbNd7sL`7$*xuK-45R) zUW6tB&P9RoZBH5=%i`{1TD=^XhZ3C08y%Tcw7A`73{W6?$qR!A`*2QlINv!YJJ zb!Zqy15dRS->_R9J2U)ZCD`KNqP1_qpVIL0Pt|3nJe8Fx6NNg&BIo0pOx=f?O}ERO z18aZz@)fu=)sv}_Ooew3=}4If=oD=?N=(t!zD+_UxIcUDGhJC$%k?u~r9Tc9mhs-R z0DEom8121sA+I(`fq!fCm#t2#KuUdQz1qp7srt~*8)X>4^mf|TVnE-0T-xvEgo&TN zy8rMEKkGnefm2+5ewF{-x4l%us&TrPP3B4+PJER7fiD}~?!LVRWU?1XzI*Kd#gZnQ z8)3P%ciMbMy;kVjY)Pe~(lUb3VfD-;U;ZoB z7Y1rG)a5vt6?8#qu-rdH^fzQ9Su2?S11T((=JhwYt^h$;s>Hfl)RuhwEWlq!m<=?e_n!kO-^*0aiHC)r?rg z?3u?1;NJ$Wx;y{=IPO8qMNwr@N<%N`H)5?#|02)Fa@B$ZF{_E zB@TI*!R~P0k()6~<)0}2Mi|4!?gIMa;QyhpCdf|-v6FX_YK2nWfh@F z$gCT4*qSLFgM#>Dqyw;#yRlBq7*JS)&28LQ+g^U< zlrs_kBmS~(PxV&GJJ(2k2pu|x4ASwPBFLiHw87^wMsGM^5v(+(qZH>sW50wHDm^{E z&Y(+j#ib`9W!Br{EQbShwqLzAKKZqtJ>At8IA15!(T@m@S7()z5-QA8TjO;;%4C^1 zqxY_^SJy1K6v(ii5VpYer6}01_-(uKJMAUc4U4h3MOTZ-=MBCuUba|qh}b_G4*Upd z$=5k1ZC4KM>@FC0aBp)*b#kz}2VARTb0yKUD5V+SRZ2%RLctn{{nM3`HOr(kRukSl z?#u-3wBV5nnY9R*>tYp8$#s{+vMn1L#=yo_!o5ikjtt;?z^fzDQdkp`q_8xo9#Wde zY{jF3Fnk>6YAc?14UY=AE1AxH?^m0 zckZIXtME$gm>Tin+e`No39e=Ajy#NQ$fE!&Q=<@>5Xfi&&s#8m5JOvsAgNL|+bkM5e4Hr#DQfPzXE-Eu zoLNOj)I&)?qNZRhj7^GBip=|TytFhhAUZG8hj z4_Xtr@qrg`AHF(N8OdHer-3UMGrCRj7RPTi5&TVzpHLtHj`K zj*Etl^zG6ljWcrLZl{t?3D*WO!TJk*bR!bC^DQNXF(u?5i0w!e!_hNs0^z5b_lpzm zmZgjvTY*Kod1q#j19yu*&Qku^QI$*SjLA{XW;Or&YHTLI#o;4(V3t?6ZaZ%xz{b-v zznimdR~9KC#fac7@gP!5p+J5@|Gv7Tf_)R6ED59gtdgdouj9zc0*9w9yqH=#N}k6W zaR*x5@Rn(jo(fPOAPf}*@c6d_;&Z+E)yUoD`}m!Yw29Px zatYGpY%ki}t<$zgPbEn+(PQq1n$}<5{}eo_tQFLV8cfZ`dNz3@W@`dPZlMSM{5+HL<46y&-|^ zBA+Zx_9g}InF&9FP=MUn0Hj?o;hgwLk1ws=BJfpW?fV=}Txj!pIl?j*CQ>3LUV>eq zFwUqaj}2&Ib(|=Dqm!uXWA2k@O{emfi${Na>+O@`q2_I0zwrV0Dz*kyzfLz(IZzA1 zvDz!p0Od};_m1Uye&EWwXSEWmuluAvkjdK$h(?&xW6lpISzChj9yT(*`-ikscglXQ zg`78-n_TrqSuJj}xc6x}#mfGARWCi&PgB0V*tOgSF=1}-J(zgV(zpn8T7cZLrE<7J zbJr2!wkTskzc>Awd(p;Fn>^*MTxF$lu}+GEIhw%pK|6|2L2V#Fj3y+Y<9|wT*|c>j z6j>k_$U*PIxw{=IqTA5{*>PX$GndlSH>@%e*jB;lKprdpr|1f5>F(ziBjDHPiMM=$c;5Q>IifurHPel1cJXu-JU`1VT~`k4of z+tEP0!T>nTl4GsfH03S>+uf+$h#x}@+(*0*4Ine#kVxugsrwQx%`#_$yDTZZ{1%u0 zLcmJ7n)c>{CS=#syu;eM64v%KCQ zj@p+C{FF(u6GjpITJ}sI>AXS6rv~^N(Yx0s)GbuxKvUW0)LzW~WxxUD7ez)TM zE$O2ks#CeDTK@oPvy*xNH3~LK}{K+_JoFAVLCMEKNUkU^yY`j!pFw|p%#FU zT>3v&yCx@5EI$q+f-&b5V1)wsxYc!bVYp!~@wwDLO4(!op`@1P+V|joxbZFB&WVa| zhmm7f;|FFlh&|P%EIQDP?&OU!*#R}+;{2ibJoIiJQgR=Py`#PBf*;}YoN%8_)lD2|e*vzZGt8>T#e@>ZZ~z#l1!Nb|r>>J|L;{%n@2^^Ay$fWUQv z{UnW4C{<50sxFr)3(ZwzU~fl;W+km!ixotOSSt2j3Criqt+dL?3+K2rqQZ!ig&8rYGx z@+1!F;>?uU7!wbfk*|}kl?!ncW}CT{o4bqf3ewlag#30JZBJ>-13aEOaIe=o?o~^! zrDSD(GsB5mqr)qh@`hvhB*`zD`Z=AZdyHaWrE85?#x^aJZc_w8geDR z&zA%hT}#cRq5|`&@_1B?&!&m4F_$B0EyX-|#kP9u0K3u+^x7qUQxMOC6S>t!)2f6B znX=r|{j8r;a9t}75!3e)6%@o;{LP#-+vt!{qhI&mz1_qygi=`xfXH`?6wgTM4vd?K zW!{%dBrOAai{O`4N|20$PCNA|+?ajoz0l`tgYhY#8M50tvb(=1;1Jxn=gRx!My|6( zC{$yixnHq>)pFy4B~stV>F&u_KkAn|5TLJKu|%)e2S-(NZd!aMd_EeTzFJn_d171h)4)ha4UA z3LzOC$l!nv(ZqZ_D_06ztO05V%x_@(U@WrY(DLuN+dAZzkZT z!EraAjtGOHUyKIk7@4}xWwFNlbDg)$L(u$rBE7SUeqPX!Ec&}#6IlsU4W&UAVNqR7 z^6gS(9ry49NH3x=@Apu2%H2r1Nu9(uD3f_TZT8#7jeGVz;@?(B=RIG@cOa{fHxmtC zryW0fEuH^w7x%RA=1>|1X>_%nM)ZCJVpM(bYMY`d!9` zw(Gxsm&Z7H8!Zj@6~zO1SGG702RPESWBN@Yk420IT5b%c5t)8W)QP;h_?AXe zxt3GYXaJN)nSu7g`k(hL<@nR_y9%)dr>EZpY{b+WJd_aH9TNjG%boPi{AXl-v~d7VonF9Jj$Wjkl%fa9^1HnI~TM*@h#2HEtoSf!0@)EsiezgV@>00i(sZYrg-0B zs6GQQ?4b*k7Of_f$s9!-8f)kfA(Kko|HzC?{cdcw*bB&BSeWj&}Lzs1mFadCRPhcYm&00LYq( zm+2dV5jM6@E7K8I{}`73Rm~Kt{RpTwdo4(9bdBP!DXfNwJo{rVZQ6WF`W*{kK#3`W z-u&Ws7^3a{Tc8>oeHf|9`3lr>8z>`?$m~3)h%v`Bp*qM=^C4e0-jW^J=KF(%vUg-6 z{Wc{gJ4=EwRy)-QqBkGK$^)L}4oc+;HE@2`+B_H)^zRnW(mJq}Y%f|6%LNuy`9ecg z*Dn8q&-;_=!>>dZQa23C+H!MqfmDGO{HkteIrr8aHQXDnin#k{U2A_<%j-nMw@%9U z`TUx5x0FNNa;}UxN?owg?LkqQrqo9NMS-nc2}0cTDlj60M*U3XdpO{f zlzI!Ymg+~>WLTQXS>6$}{2CV{C~ou|lH$hg52dpR1t0IMoRtTzBtXsS?XOy*s^x2ZZwpL5AzHvHy-7?)iV}PukBfQJ8;oob4oWA>9ISQ=y!8^>D1}KP{DF=$Lp(t`>qQ^%=LjGT%iGn}CE7(IiN8Kx@rNGSy7&B8U~cf)kH~`7 z7D`tjbv9aZTJ^c}hTA_Hf}7}orUqM+!{2vT66sAv-LRe>1A0z=7v;j(J(=Y3+|w~w zxsgbRS^@lyTl$Yi3B@9I;7nFk z1|E%G56JFmJn(esvV}ML^-in@9GUn{Gz?p1`h>r6C;n7+rkK_EPS%lC;jWcVgXz0p zg=fvPN0XDt;fOCBjIrhIv24c=4eDBKAJ%V+wm5WY-F<8L-CHyh=&3z@L_o*quKj~9 z&0Kf3sq!v;-?N$x=9EyFjo)c*O*3c6Wn66ZKP}uAGqvJOh3@;K`xX2h8aMQl!R{;j z`4ZbXf)608?4=(li&j8<7U@N{CssoO#3Y>pN2>p@|;DPI)H#0o8FFI$3Y5 zM^*ROqNF7F${6eBj?^bc+ewP)Q_oHq_{fDBa!5$QQAz3r{nF(3EOMUCmWei|7@--O)LuvtvVDW_w5@rl>$?x7@0KPBF3N`Vx~fq5_xQ-J)I;5t ztu9w)-m+>nP+EWs%H?Ws-({ksJXY5YCGmmZ#rUO;ZWwx@1H=Wk4-tW9>S_1MuM_g6 zC({coXNj5~r7^hA*0{z>AooTtu93lFAy+Y3Rs(xgexv3{b}lxbpz9_4HCFPtU*w}9 zp9OZtTNnddS-E1`kGQo^CA=*&D|1IcqYDEi6gZ#z{y~Fz=DC7@URQ~1AC=&bkyIM(qN#uGL6VJ!;y7g84NUoqK(wfL-lv3)SI z0{3?^utvmWviN5ZOo3uCXGdKVdZikp62tZhYL>xUD@QI1N)qNCyOFhnS;U*ox%aW4 z*<9r0C!CG)?OsYP7w=4<6uY!w3eZAA1E>Gf3(&gQ37BYFciiO$$`iM##i3y5JQp%j z5+={+Ns+|1s2erTws@~J=(Nbn$H(XIOulW6-1_bFx5c}9JAa|9#a1rg)*?kqw)qMJ zqgP2>VztTsxeoAr#B6n^tpfhzV;p+Iu*PvbIL}UMx!)0jnm)B!SsQ}BGzr|RDi1v0 z4=V~PsQ;V+4Uxs1XD}9NO*1r1^xJ*mATzWA?+UR4Z3VJ!!NYOw5AKg`7ZqNJ3^fsg zHgQ3(siV`K0UEOl{{BJuEIeHicP{zmxemuN0VEcsWgh6&cqv8SmE3%tSbLddtY_st z-998ElzxHIikzqT0Si8TL*~Iy_1JQ<%D0nGsO}NaN&n0lv#Pygd8(D>z^&sCl%ZvH zfgrw&{e~fj4ba+-p6FX(&A==tFXJnG7tro{kVSmj_wkZ!{VJ1pZ#)iO{Vop+-QqlH z)JmuMN_jgh9OQpQN%-qN(~qQ^4`stO^Mx$}?ldu3k?xa0oO(PCOr19xp}YNbZ>%>4 z?RyWr<+(rfFLjFdpH(TeJat$l$S5Hxltaj|$y;AA$&Y#`v7_ z2Jrs%fs&vo9^LC$y8NMLvHjxJ{1>FQ)`h&KMMp|d^x%HjqExeF z_^_5?IkfXonjJqSRgr#H&dyY$57B0%5Y>DqZ1Jz~>a_$K+(3YU6tE$9b!=S7GQNhGR>PhAe zF>4GZiQ13KaH!BPkC&96qq&@B8s7|BQ{SMkMJy(c{AYE5KpqvqewpWn=Jn3BZ5b}^ z&Ex!`SBE9-qu_4PCn1u*`L8(rHtQAMZjD&yBM^yB{K@%@A~zwXCw%WHwj$?0ejdpj zOnr|L%ZL#ulK6YD_3b0)J5a)i)QXSPccsD^rQfCD@8Adhzu7E1{~gy4cVIi~75}04 zJr6znnT_N1J8r~hW9&{bHhjtP82z`ZW`#Q$N2tDL!awXP3zgs?({G(CUkjr7FGSbqmf%w zWzqztO_w+2{q__XY6|#B9I9YMV+*uC0#l9TcswIfmP6zd={y>|%+^i*H`O$+9$wPO zN#rxiF`{srdc{18A9IqMQhF`_Yy=0@q?c&=_IahDm` zys__cH(AbOr;&kBac%C%Utzzf6gi${CGB12)7Je_xjLL=%KKX{1 z8mBxHT{W`w!Ts?1z_PVpA5od-A4he0-{#4H__}j8>9Xpxh2fVDNg2cBfq-Ep3Zse<#8c1obwkw<>2^n*A-aECEKR$bv&975sOFGbqlnXp* zNTlesc;T5n~!{!BaNy&q*!uRQiqUdcDOsTlkpiygwM$OxoRYefU5jP zD~J1UK#+a|f}{bxw044CJD%KL`_OHcPeXnLf-}eqq}(6*dRbypxbn=MiWS#Rlj=5o zDd}+?m!F>>n)~u=2JeSkWNnul!EE@NK>EUDS5znhe0U%{n_<;1kGWeIsQyIdJy<87 zsPkqiuk{VlaK^A1GN#wsX6bY<=)#spUmzsGq^2T2;|YMTIF>jrqZs9zq64A1ABi{L z{dDXZdVg%M+?MtIyTvy(vWj{>2g)!~Li-y;H*9{(fLcJLld`&~QYl{atjaOnp91&RBk5!?WT1))`1;PoO24LgBLz5=TOhzh)<85+|)MQUCn- zsZBq_HHB#;R5OsUVZ%xB5@!+ZmqSPv2qpMTLBSlHGV=H<3D@=mb)P{({$@ zlXmwox^2kFAU|&>oLzRKm|uW~s_foii{;LuM{4MJ(%~*wy^Z8dZ*FC%{V$(eq@B_J z9|)f6^9y|aYUA3^KpGCCwEX{=ddsM|qNNKEr*VhIEx2oNmjt&UAwc8q?oQ(p0>Rx9 z2=4A~!QI{6WjgPDZ)VowA3y4J-8#4SuG&?X>p%_p4XOusW}$1eicGu^9XiGsu2REz zE@&YT3Qq)wvYKbHy&O2CKNEp7+=(3$+qvE!)p60fe=x!5JciqWMhAo64f6v!tjlUw z`yM=ceihLjFWJ-VTdqF1Rw~I!yJc;-yh&kR{X<5W# zDE_fRii^MBcC068cec@Mi~Mr_m%GtUcmkCXKS<#VUU`AR#%kL%XvQws;JS`VVo^I% zPn|nYcjX6HB|Y6P?IWX1q&aBve=gfC*48RT)9&{clcJxXpGImtBu5QZ}_k z#3#mUFkVBL2;a{9}B_R&dI*eDTKo)bOf$mVfqaC5hjirhM@p2_pLLP2+-T=sq7YEzcq)8$?mylKF#n zQ0QOWyb9iJ4UP$`&J@U!TuN;}HNvipef+!mM*(SVqBA9p3nXm!$n7X6du>lI?Uby`=J7$A=~BM&LF?C)R160Bc3^E5qqD{uk^QG z7q{CPW@wEsYDp3_dQ^QF|3*@AUXbYPk3!M>-v4!_TU>FQpcDNlAT$b!u_h ztbP*sA992Dq3cMaxq>5pNIG$ze+1S~Xh&zVA*g$dbIzOq8{VJ^f;KGBrA3ejo^Y7V z1#u!AXaM?>==8(v5QS7MU9ob{5u%8Up(Oj(WeH7TuRm>crg92Iz3Wtnv7L5xadWHA zZhl7M0}hKg|+xoie8Z}?nMHFxa9C0SdpKI@(FA)l>Qql6(}?#tfFnb@(9cE8w&5E_@4W-5Th9tDhM*kxC7_D16Tx{Tdt!y^K8 z1jae6e*4j`2~c{^2y9tSn>&E!d@FY#&NQ%9IuttCLf8e+7cbIt>`Ex3#j*} zT^sKM{f!_vBNm93DTatt1L-Td;5f01bj&B=W)o zlEiJ6t4O^YPP-RkR#jDwGs|aF9D3J`Zq`==h>O-jXym1P)l5fII2y0=fkMdMnTJWryh^%(^Z?}g!Dr3$8CXTP{zEwMkKqN<;z8&q3S|*R7nA) zK#nh88efV##6TMScf_t!6tscyv1?2iM&mC{!^=e9kLpJr2tsPbsw@5>7jewiK!7%3 z=iDFN%N^(U{@?z7LEU9S=jgn!C0~zwu+W-P{H{;68yzS$D|DzOl3|P)OC8Q=L}9Zv zW4*ZLf+;dWllTHOBZi+&fZD8qfE`yw}hL@L*8V&I8~^?!DR3K%}&6o_)Q zKagZA`J;7_NoQ3s5sIB#fo$q9rYjoJ6KR!uxB8+Wt^?Va;yq&O9n7P@ne0jrAS-@22=rV^gcHhhY%@Cmb=Ea21 zf`v80YTO^)l|*0=*?-wqRsBphLm-#_;7VTWxxO`Io`sMwFwu<-Eq?$d)#}tgku1U* z^Y7q*pbcp>@iYqGN25C%pSzdiK_&*Jb!Z^WZ(cZ++4#`?q8Fqn0yY^*$zYdqw0?~* zn~^Af5&gfBPo^+jp6&((06)$FAo~*ZQq77xmt=K)PeNoRQl?<-{{Z=aSYG&5ER8~V zvDuc%t!zE|_o*rULQe5Lg$;~M#guBDYENn6dx%brIRp$BR<{i!d`U`bJb6J$5H5nb z4I??q+P%)T{A(q|b-JE4-pxqJ4OLjI7!S?d7-nL?zb!G;j{P4mT`-GS2HhB6C$o6$ z6&@};Y?#wmoF^|RqEeVT3PFP$MzgwW`nY7A#H@bq`mL2~f)txE=yWSog zq;cqEGqJVMXb0j<63)7lblrM~Y9ITm2TZa6mK<7~$2vQvg%AhF^L-CY3iIJ{M;FO{ zBSMyIUWjT^JIVWieRrq;)Lkb{0{b-Hp1T`$b;Ey;Fb)2#n*Z1LMTL1{Ip_)GG>&r} z-9A-D<(G}2c&%x)bUjgIZjLS0dS&7*px(XpTRel%c|y`nsxF;P|E^>dD_4CC?_4N~ z+2!BMV(SxvW?Gf!2)>PO1GKT*jl?G9pD{5xYIFmDfg4ULfP|%|RU=3kCOAA78fjLX zD}Y0{CIQc)d)s|IChGkHQ6nZ*22$n_W0Y`(71b=SmjsL|4zX%!%XF>d(J!8o7Y!UkB$)^*6!b*MB z0{_!hzfHBFR_xYbCEH~V+I{DF2Mf{eTL5wA!qWnWhyoOs^wo9GS{_B?7AZyAJd-^v zJmoYdG*iq%t0z~M=Oet0?}NI=jH~Vbsc?@hDmmeWC8{0=<{Z6GMLA(43_cZ1GHF6L zU_*^E%^iWJWY&!Gj_{b9TmwFbm#&Q|kv;YnkLm_QO*nu>uII8Njlwrct*y0^+tMlxwHdo%q^5z%! zlHWwsRGNYsnwncq%|N!WESXjCv1-XK$sEtzrQiv@gDVHDd=(KcVJR3z+w)e;)EIMC zq&rL4TSZ&@psAhlWS+RsoHWMw+z$(Xs}|E`EWj>OxjsFlyF1A&LVF0ilAHSQ39QUz zqeIP!D9jbe&9j)4Dz<0J9(bBzY&yoz<=qA1+|SK}>ihdRVl_R1C%93&Y;53Eg0h(G zu{%SHBw;l)wPe8ar>P=K7#=uQ-E`vRKDx=tjfWKt7)7NG>L-D`PCUgNf*qnU$&96l zQqVBDm#LY(WOU2IlNe3h0200LKWRT<%$4ay)j1Pv4*HtX|1Pc^n2gPxj@X<=eNcdw zS6`7R8ThgJfiEH)g?D7gXamR?);I6^vhW-gUuOr<=d4;hNE?iRa%mm z;B$XF5ik}VNC(8NlH=NnWwi<*tEWP} z<$4aP)Z8#NRUM(!MmiedDvSYiSe62zLd9ItM^u!}8{cKIFTqB#{L5n&_Iss8xOd}4 z{^Fl_s6d6##2@W?m&x1WB*|GMEhRq(!Kl0}ei10VKxK{;&i<4eePKr$y}k`*Qvttw zUy!}rU6r!eTa}^4x|NXd5Ix`-n%%h^ocl!uY+9T0YbNpK1(qhVgp6}Gjdmt|6**>U zNSHh>RZJ0dfmRYc-!I|(H+G?}8$~m`isMTQ1E|kN%RZ`Rzu*uo2q07z zd`e;<|7FhHmxbDkZYGqv{H`(o(?Qeb#tdl$e%|MI3VZ3&c2fQ(2cqIUSQ3ap2kc>_HFxn&|CK-Cm(i>Q!o7k_;z6H zg|uYiFr_d>%|o;gZt@S_kIYlq%{e{odYe?b=WsO7nq=;QIYU8p*@XezQGWaGvlTW7 zHY`XKPd2WH|A*7CphvcCR%)@*lPkI!VcS$|7xmrw(L+~9_s!hD;j~3?_`n+XrnNn6 zWxe;5v6&lob%%1QEE)RD0#5|30LgBv;AWqRuuSwY%jF7(8e-R-wp%oP|7S(zJLR{| zw?WZuILFPzfN3A@Gr)675dZ$6#oXbmEq83VR?r52F!M6v|4z}v&BJ4Ox6-8Tx~@x) zyek*nyFra6sd?5NO>Ezreg4R`HTvW{wMvpN{a|OkA4;{ZpIKO zkX5QHzAi#9VwHia@gJZFN%J9^n9w6VWu?FRmqO)L)zp|{{=$gRM%yy>F9;(#OiNU?^bsXN=5cG@pFn@ad~sn|^SWnIo|^!Kn#3bZAW|)A{Rg`N z4r2h?WTp_wsK@T=J7{^?S*3QF4Q&d!ofb5TPTp_39Q7{bAiBpAuTWMG=2iDKu)QD%zoI&2D$H~#O^(n7GnR{;%(Y zD7YoznB%IfZmoPS526l^n7;R`d?-aKS@{|4nC`Zb2`2Add30jcl#eFiN7nl0frK7& z7AzU#nz`3hg8>ta4yW4U%!SYT?ci7Q?tQtK_?JRdC2b9 zAS4-{TiLFDg(D)lC;L$=ljxPbp32!}_Wd{T6#e7;4$*UU&li=%+-495TgB zGoM`*eB}18k@q4V>)vra%&_VwsguyJR8-0TLC+Fi)G*0lZM`;plrvvMX>btXoyjkx z!6A?fe@X89l;XqF9z)~%C79iOoP^L~49H;wcg2WkY?+NPgBY#E(O!)K1AD(q(ZDz1 zt!xbBr0>f@BAsEQGWsv8C}5)kd4?>-5LX(F8~xaGKgMhjDWoI-zbF3oG7%pD9tA;{ z&Tqcak@v4OQ5o^b1E(D0}fZMt{kE2KPs*PXw z2_0;cLQ86`dHT>@OW$(8hV^*G-^Sn_Z?=l)#6%DK@&i>{@RUVwfqR3SXO1`L>*O8n z8%8JOYlu8P9-L||B{$)&_cv^xr&$H%TWNhy{wtYSD6I5}AFNu8 z`6Y0ykz8Tu{ol%j>kJT52}piyu0dKwYdw8ciOhl&0R5l8ma54a+QV0u6(nbJD3YA3-K{5(%`iBE) znN#-!o*!?JL>R^ZIJRClIPip4W|tLBkC@l!EjZ3-8KWUr_h&iKy_b(L1WG2FB;vho z=i|e^dfdk3Tnyl7F`x_SrUHk2#%Y-Jhh&kueXOJ4{r)4Yg|=Q4d=!43RV^4@*&HDO z%Mz#My8bZ*quMg_oqi)brXLY244kM$5Bj#e+hcOasjZHFK$M{r!TnZvb;29zE2K4dH>-%&HMM zAW6L;qb%*$d%`_;9tQL9t}~c5bGWI>S$Y zKw|T#4=$3qWPh2V6}LZ;{xJ43_kv16YR5F})Xy<=N84jb2`My|-I8mE+3t@BhllC` zV+PXd*P{FaIrgFP6{p{`Ykon%vP@|9C!{!kg zkQE>b8Y21$wp~I@85hC1lv|H{lac&eO z&NNZ{COgr~DkT{dPY9{V7+G1(8+UE9fo!@Q9!8s@gAAqzRZkvIstA2ubCO zSaI~&8WtvE^AeL0xt3uP!rdqVWLSTVVk#5GM&8Coas8}^;Ia`&2oJ)_(ujm^Zm21s zWWyou1B%%2@n(4=?475_LPxn%VNNX@q;K071>QxHhnVsh62?ERyzMl2=2fQk+1TpQtSyQ*$#KS@InCmp1d) zm82o`XPT=iBWCs>E>6wDCI%-KdW=B-{vJY#)5)IQ*g= z@RO%};#Ml?g;HJF(Q&#@=JT5ZXaHvqDqo`yaHwBO7~AazOMB6|%N9`C7oC{^5KI^k znL}WHePN2WKZy(agX`GX6U!%A?4VLo8#?K-_2-X2q%EDd%)#x7}6lgn8AgO1*34uWT^{ac)S+Kxa~uV z!-D0|Wya%r3nM)Onm4@-k{DwXt4J+n3DC z$B=Ww?){30O#-1nrPEQ*k!)3V;woKm#E*5lwB?+!s6jW7-7K{l!oNs5jMHW-r7Gnu z`{|8bDi3Mc;qFE8Z>Vq5AxY3ufg6kCm&S;zw%*)Tfx{8YLE=@qoZ;!O9dN8xcQtsx z58n{T-?+r9$SzYkE(2Y$EBFGbzkZJj>UeBCZ%6psm4ad-J0?haePe{J<3{S4Ai7-YqKuqTSiLMh z>5wvzv?VOXb_Q#?fN#x6{c*@ln5rYuW^G6P!R^$0T zy4_Bv6tR)8(Q+$KEwz_6oH0$mhHi=e!uZG26ZzKSkPxm*k1~pC{Zt?K-s{UNmD*@+ z?4?`ADjOswkXTjJTgc=^(qr`Xn(HizR&;vx0Qy|Rn)NGWZwRokcheQ?P5;vZU_G%s z<6GOMM}o=y;hgtI4{wZJ9xgT?UhUrym!I!tY%8%8-?)LOkzYn_DQddxre$z)C!kBGmhG)aISVgeWEU!c7aVB%l{TB;V`IRG`}ylnsR9hKOqdOQpIc< zRv)9?h?eA^PuW);{VKlLDrNIDx7Ii>4uJy5YKzkgCxL|c2jp>{b}k9{GXx;Yf9 zFV8pXaD5#N~mcs``BpQf#ff`aA#kS*4v@hA2T%px?y3uf$$!yUINK zV1{ZAQrEfwGnIFbM{;t{d^FkN!Vh)1dA1V4XVv*})w~l&8n;s8PnD=r85*wrUziKI z-w^*mn*DuQ74C60S-4k-n`j@*LiGKY#s^zb6CS9Ma*aRK`HOL!tA32G+!X{PFSCP-OBE2=tl+CtPcR7IBn~)`C1U>sb)c$U^d2ACNR-*reOCJhPLvNTxU}?!GbW zH}mbfZmN8u&88^8gmi=d!@B;J=RfB(HxrS!-?D}s77i|_MLGw!I%+0-6lodP(LIQX z{$9lVV?r;+zDTjB1JcCFQ1WVgK2XiCqGTgBxGRxt6ZL(rrGY_bECQ6X z6eNfhCF*ka`@O&l*L7O8W!56VR4kmHHpFq zq5S;(jW1dqU2|7iDXXO%q1g%x9NR5X38A?)dq#&-Gz_-p{tb2)S~vLM5iaAtF*jFD zB`RJX9V&eO_I1+b6Kw;VZGDI@*dA1Ok|F^TOQXP#_y~kIK^u5dokyVG)>ao!-u9I4 zpOhca*#Su3;4mE@B2yGaMo}C5Qs0yL_RO!(8M*{g-tqUO%_e1LUTkH&wI19DUJ1+G z5|-e5-%xj*s7zCLO(lDPjNOww>syxuS^Y1Mnbz`@Sca21;*D>=t*c6F5$oY4*?rue z@xU=G&&JdO?Nr+UBO9}DMel4D z$=Suim$X7J@df*-O&OMYw9}We!V7KOajbqWxP58Ksg|jmk{v#lE?@;$kXBiTQ+(js z5jn}Lye2!RruDN-Xfk^vyc>yVlXX_ZxYj9?{{Yjqs)PG(2a8Odv?W8spg(54b>k;~ zumZv00?DK;Zh23k?i{S6Y$<~xMQe9OUuASI19~UgO)JAk9{WI>j5G z-2FRi{a1p|3~WQqf;XY`%ErsxFuF%!!4c=W_f~HF>KtNEsOac(3J~O|iueeZxC=2Eb#%X?UF;E_O zmVK*~d=l1=R!{BVfC2W|(AILqMF0!>%5);PBL>-Fuaf6mJd1q@j75F4GKh0~CYP(M zlVvTuQ?1QpxY^9fsm1{JcpQsi*CCJ;bt?jkC~Rw2otRaTsf8q zE`M}XKs~7q!;{>2`IgAqX@t1(nUGBb-bJiN9Mp_LRbBEY4MZv96PhzNp~#LojTzESj=)Gv9V!WePV>kd2B)G1+hvsp7^ z$sZc#vH8^U&ZUPIXGad-i(t~p9$>zt{XHADtW2F4x;t$#^+!$Njb^4?$s*<{)+QAHE+ zBfpOi^{=sl9lFa>7tMp?A$zI>0#dru@S_JXs#^q z^WZ0^g>D!bs?qO`MtZM+^`c@VD>XU%%96`7a#fdTXw*iJWUeATk0MwhU-l=Mi11Wo zq`F3_`=UVvUsl#3GhqC*zY>*Knpv%ubnew=IX2`N)Q$j>0VLy&@g8Hc()Aj0L}zA) z&;bnB1FETDW5!UKHOI3e{rE?^ooMwPqk#l?({Q=Yko1PAs;3u2uU?D50 zi@k>S>tO33ykRRFhS!*r(A.twYg0dROydU{l;pF5u2`^afZY75$c{q%;tLYYBk z1jX36k2(vrU8(iW`wn}2jRWNz$#v!rB<(6!1&e}yQ^T%=X%q8iI^CXXV+^WIJZOb7 zAE*z(T~ZWNxZNUB)s1<&0l0mAgL4+%_vH7Fr74~(_ut5VstjgC8eG#u#QbBMgLk51 z4&P+*Zngc!k$_Ko#akDEGl4xM8%l1FY2t5BbyTS{^U$$y1;fiB3YaPhVfr+987V;3 zpL{a-TvFX~9^z9apPWj2LN=pc0~|`#kS*%H2q3c`ND}7K=#J+UZl{Yew$tnV8>`6K zLMegdZkwS4j@C?gbvOm49|?ieIor`RQI$Kt2H5>KgOs+|F%eLK0TJ`7Au+3Rm!_$) z2>#VxS%NM(c!n%jc*^DqewgW?&&17@LZ)>;X(N1sS&UKuf0PDkVLwMO~`*qbzz zo+lEgF(srEW5uKJx0fNHB{)tb#M61-E%I``;~nbTJD9ktP~M%JC+z!;?k`Eiuk2Fv z+U(@VR&!qdA&?0Hp5a;0VhaED^^Dh3&<6IIxsj{V2Ne1LmP+{{zYoiiHsFO;lI2-$kgxjl zfQK+f5)acwh2?v9kWzJFWosTxsZR*T_3>m*VaLPNpDYfmGa-$N3ZWlszOldC;VjZ z@bLdBSN}a6)Ps*u_wU{Uv@dr*A1dw8M96$FXJ1X8mCfmjDMQvMNqY!bB~Br7injap zD0mdkkHk^olNAP{E1ZtVyvZ&DbZsu&CWQ?-%lTw{MrT4ZWfh+l;Z2BhC!xc`cgaR3 z`1Sw)I$T%)Lh!+K%g0z@I~cp{H|Fu?8*HCyUp$eM4vbk}RLdMCRKjSXF|grm9sSdb zq|imLq;|@tF7oruX;j2VrS9<{Rsc`v)RWFj41yOf?sim#XpcFUNFp?g2`ZIQ(?BGI zL;bf_djNodDzTs@@tg9J&WHihxaVwdEc5p#HJ{2y;?{L@jNjf-@w2HzVPVw#1k_fV z+ndE?U3t^# z&o#&Y$%5?$B&XnpsDY?dK-4_lhBM%TKU5kjto+_+U(|aeLC@=|ifXAmwJT>eG3w2% z??F9?KUwIJZ;h1&vW_l0V)$=9*BQh#Wc0jO&g|r5DqP+Dc~g0sG_+6#-)hYdkt@=B zqY(+mgaU=I2Xfha{;_hjO&F$$^nk7ke^xZg|H?hEA!-B|m_R5mm-9gVLSc^0f<*S+ zLpqL|YVz&V?~2+2IY@|61u+7%A5b~2ZkcZ~8{ppV*Lp?C-{|n!hDU9fvnRmB_RWOE z^39w1S)Z1bX>Y&*Ww)~_cT-#sMssBaZ)e@x%E`7N5@0G_q*deDd#Mfl|F8)M7Pn;D zPb^&^Ow&SP#}|g;je7I!{*)-c5cgmB252_D<94h*M#QiIvLcUTur2*5LprZb+gUW} zE+nBs(F+eOXZ|nH%sSP4*Ql{Yx$e^NMGEa`>Bw>ypUFjuNc}k}o0jM@K&qySMExw< z;Y%@fpKT=#{GfgGKmH5<#eCf23^$_kmUDd_u%XtAYych}UW(8q{>d1F1pUqp z37=b?GB%ojO&XBK^U>ot_~YeaakiJp3|8xWx&BWA9Gt3!OmoN6Z$jYL?M5;)Z*J>< zl&tzMDrX7Z zZ}bP1_FulTfzX&hDUw$uo8`~pYXogSNYV$}_M{DAM|npmxf)e?*Lp#;1N{cmz|pjz zk$ws);AlWDG`pBfu_vDkkgX#gSdX1DVHI@NO7vILwi1qN4$68XZ! zBEVca^XP~xF$OUxfy#LNdz3fts&w_NnKAh*!K~c6Cn*X+bftCA86;IBR@ZUV*UC{k z#e@B;b4xjvX8dUq>$R2oj64-O=!4%R`~G0r6Kl1`i zlO(@#A5iZ);p)+hh#TFW(u~5H9SbhAg7d4$P>li@m`Ca=P5bOaHtsEfttK4pWjdiP zKUunVJDN$TWn)K45Q712!y}GwV~Lk5r-_a?5Qj3c4U-_@e+dn>fLdifu*pwmX^zR#&5P7RRzoF z8qwMqVNfyW^KOCa@hI=;6v8_+C2_ih(Njx)()k7?8Ot^yE*f}hkSQQh!$v6EpG?Iv za&qeprs(Yx)xm19i%>2D3bI$}M1DbFQWPj9nFaPY$0>@+U<%Y}QYmiOUR_XYh5H(p(qU}YPgy?{b;FyVf@-eLWJpW?btk&~1 z*&^0{x5OTELpA?FQzh}4_T?qQ%rJBys>m|HFo0*Qo!T-fA1mA#_LH~0Mk*FoW$H;s zj3TeB?-ltd|KsRf%c^*?T><=1_(*59y?nQ|#cH+y}4_|8o5DSohTpntNx1| zghGC)Ub?K~Q{q#*mW&P$z#C($igMHzwprptK&1^4n?%}+5*K&q`WPP4V7N)oX!7eM z6U5Ghter4ws}5((gT@U6h}(MK_3W|R?yWNS z2X3AJM`$GM*KbCQlqaLdy^|3=i^}z=X3+tKsXv29@gr@{0~C8~GwpYnVMmrYq)67~ z>Ipda!UGDO7VPF?X!TrPC>Pv8da3 zgWrT7&XT=MXg(M@)?8ZID!cM2*~U7H64NtW^jsW&w*5F&$Ja&ShLXE`p}p*y02lKC zFIL0F+9?Q~0yb=uB5~SBWsJRHBA(}`tsP=c3F)VwDYh%J_Qr3&%xkMPr5Yj=k5(ja z;1T}?Er|)4Ov7uRU4(`j;#PG7`uT>dC{bMdbO-)`j70+TpG=kz8~E7*-0rXU#G0B- zOZ13|3`Tvn)Af`)>Gzf-EV7s@Vsr*lKGnTUvM~5MFv*7A8Q@p8QUqM;kVU;LAOfld z1yBm2_RJ*W?-d>!92t>puv@)obDro4u4oH2_P;}EwLKY#T1~6`)rsp>`*5m(Thm5e z6=mG+T+>nG?Z~wL<*Y7<=J{5v)b;a=#Ap+}+qtcu^tjdMi*<8nzyOI=FFX^0;Ti0E z=f{x_j=tI(f8$@4M8hK^9Hv*K3klQk=_u8mL=4e53ncqvBjI5%Zs(^sfV|7T!-o$M z;3k5M2fdvPXPs71=mS4?F|#UmIW9nZs7jhc>*O4MW<<=H`1nK)!C1tj*frg4fl!T? zErxV?c7cHP?mVUecKj%?@h2;b-mEAY8)TFCRhq?kaWd<1VS$Y8dy88|<2q~|%G^Cf zXxG{i>IDcgUWXzA5OH4%O1E=+6ZE~MrujDLDlI%P`KAUc?05$m1W~{wZ}3x=TF;mB z?Uy+_%-2jiUK=Y1`MvlmpqveSCletV{hO2WVdqquA#?&q7>14~yD@PZSAy~oSZBt7 zFXSd_m*s=g{%EEXcEgmbRiWQ_xA#kXsZKEMN6l-7rqt=ZSzvsdA&=YnVrnh#bg;O^ zV`xN-PM0*F42B7!v50Wr{_p#BSI@V;R=oR9>GAT}QuF{)Tk!X`xhBy?qtjm$E(M6n zStX$qfN@CKeGCbb<>%^{xVqFA=LXIfN9&XCm6xJ@-`ILBu0d z#74?95}0uN{}kUlySusaKe2tz5k)&Ql@$lVwNNY+5b4q zhggUZ`;+$IQ4sm-g>2*T5CQv6uk(ePx^ULv-oTy>8iLf|FdPhmad#kXMr##Og@^-& zX8AYh9`>oXZ_HE@hK?MXyjW{zN3y|LBB_jT<*OHKf^3^O7^a3u60#Ij{~w8o2STPp z*gd<1a0v*u=|ta<-tI=DfKFFUDQgaZi6n$7nt3`2O$1B}&dGNWfR4=|mW})Y@y+A4 zPP@uUdPx+b9zdsEcOvH9N!nEK6G*pg zsrO-h^P11DG?Mm;(oQSNEh{6SRcsUSD zv`Ii>r|>jXAD6Y2p$HDOAL%)r-RN9X$m3m4yT*zph2M6fkBaICnS8ex&Sl=Y7Dnx zSv>09C;5W66K(2)19K#9LO>9^+bv_6=Oy6^-({S3o0scT>;woC@}+P(UVN86!NNrg zEAd{Zl_HYIIAfO{F~fOQ?N$rcWHy7fTw8UIqeYgC;J#1w@zPyJ_TEwDJV-4XIfyoC zBao9y-o`pwzVYjt8`-on8B4YC&%JHXJ1T_45*j-U#5vZGeJ~21tRj<>lLdafCV>-o z2m@$KkTey=-yX~R$B2qP;SS3xcA~VCw6f=ryY21eMF2@S`XaumPAlTJL$&;DdQrLV zR4pVyG?hBC{}Wv1!|#u;bfEJh#b@Qqf?!wCpZ)HpyA-LtDY-hrZaSP@DOe1&j)VnS zS^Dr<$Og%8Gx?wa2oK&L1xxe|R;z4r0AeFUwvsBF=pFPGh|S+z5pO_#kt^N3du;TV zP19MzPHXK@3F*E&XfkcrxnJA#tWa)U`~QeIdiam>={*PM_c0v)$mMPDlJ58X@WH%~ zNnmbvWMi=QOIycd1~t+-yw;w|1CwTBUP?#9d+4BhZ&Lb#s|SM{n>eOX!UTxmD_%9! z#>by}v6D0%FaVEDgE-LZQ7E7BvKcOk03ZhNmAIlgRZ%rpM@*ctKE)^)hpvm2@~U}a zFHbDG(xVtF9LbHT8-$tYNt=WapIgt))ddPekfWcbAnyEyc(jRf(&_8p0o&2?By)2t z3MF+|M~{u=1&McSy46@ZyUdWc7ORbqTLXB~PnsMS6z0aG%|F98Ve|PwP%=0RAQeP1 z3FSAaoWlStE6Q*snSG1N>nkXhp>wG+5oMD%4(S0TegfY?&)FW{E;PhhV|ATr)aPs3 zxpo{`33x$-uha+$hRM10GE#8tPLpLjpg-Fd*__1M5VuX9_bqPyaG|=X-@^clS`2_- z5`$KZo5c~pufQ>q0>)h+oP`4W;Fa{C{%12`R9YaGr&5q>S17+pSOdu;=cwo}LK9d7 zKBvWO4pfBj9F9;?dU+bflrDkl>`SlpI=gy)a#HPLljV-rNlK(0`b(OGemltCsZ`}yRmZc$Bb2+BZi!UGsi^P z#@DdyeS>!Q$%@(CGa?6MG^FZ#ZR(ff$KaTyDMwYoX`i)~8YGbqBMdO=n%-aox>RaJ ziwIGlDGfJ2&0-kJXnPo`RU2;#P{?#*U&=Xvnc=9qvC^*+Z|Rn|e*lT1!@~=yLO6h< zlt5e%zUbNl^g7xoA_`j&*S*a#j4^yk;ssbvsJ{KV>*&7PTI^;BO-W(Nznh& zi&Z{*#$i9A&v4vZq(4+b&2Aq@Huya+Fy;lhEZVmjDxn<0g;HTE1=m9X!7_mU_k>6aCFb%H~h3O}pjQ-pIDvH_bSMojV=ln0y|1E1tO z5;00m!BHPRgARzfDv#btt?kbmIo?N6nd#i1IPTTI!!z3zwO~Q>h?2#vP584YeKL0( zU4~Gbmw*G>*4}|{Qcx)7B070kOaQ~MM~MjvwPw+bKs+{31fcOP(FL~KuI7=) z{Hm|&dhM<4H3i~M=W-i1a?a4TPF%8}L+=3n%}J$Mx_oE2!p{`5bcYM4Xlz%K!vQcJ zG{=JMSY={KB93VlyJFl$0S0|Q1vcgZ*|ulnY|#K2#V8_ACt8uehT_IouxC9mMCs=2 z{cq!+;){UCYA1L2p!G=K6Ia)|(FF2!yHD)GaMpoNQpf;pOimBK< zlV;?uAWxwI_%KXxnogsZ?a#7kE_;gQeD{TMsqT+s^V^FfXM&*g#cIFmxXBoyrU3HN zS7MSREUt;N(`LIlNz9Ci+#U=?cP}5oCKY@h!G+av%8RPNkWn0QIA(E&fQfxcJ3Ceg zrnq=6t?1hEChO-QcqJo8CyOI^M(-l?=Or3!lhQf|p3X!F@2DBWEp%G8+;2qtreChC z7v-6)3P9H87RAKl;a3eiTo>p%4jM%FYoI{SJV9U4!1tvHpBj#4@aJzYQIC*|jIJhL z(VIs5H$nMpqdJsoj|OOtWkvu!ThJcOu}ra3GMS zQASA#J;>7&$l-)r-nfaM;s1F1;BoNxL8}tjlAGHFf8Q&3rg(&p;r5FI7_iRHe$fe? zq25AtzRCj+(cHq-+bn+9r_!_}WNkmxY}M0<_5x#-A<)es9w&6_jo#se5<)q*c=WcQU#x>T_lw0dc|2^Flk7=F~{RY-QQe_}N z5ug0H?qhzx8EZ0^pwxu*I%56II|>oV2C7)D1OBD}Hd%za4Swvg|I=wh#Qoc(mN2>b zlRRjikB^OSVZ@Ht>*Qj0o%t6UYoOK{W86CxsM|`BZk-DlKX#?nCQ|BXy@%t>kNHK- z0>2g|lm;gz1|Z7qkfWe1k9_uUuT}3N+s?pOKG$V|6VXPDT$K_@KiN(93F+}vf)NnD zPy|FiL-~L585bF;PHcgUlM@?UT-=TRblR=CXYxKg_4inJgzRtvFHNITHUe-?uKx9B z&1A$uqkeby^PY%X!ONY@#7d(_PRQoB^=k=ytlU~zh9adloMY#f?aXp`fai&cwULbY zy_$meULg8NH7&Sj zJ8DtVm#xD*&J!B)qt67COnoMV2oQDvKDU3vCtq_V_H*AgEz#*%yVgbiqfDD2^vF8{ z-)!Vve;<<3g?P8wN;=EuVBrsjaIm0x$cU)0)PGwoxm=Vm$?@2bF2EJamE&!%uEXt4 zN1%Mz#v>WT-Ic_560)R2lL|C*P15Woe1E+GC4~yZzb#eS3pPbaeOcMK~$Bw}nS_ZSieTn~#YuA2bDj{Xg7dH#_ z2M8k(pu^CQv5^tx72T`9;&-g54Ur&6b7NLD|M;;nh{D>X`}kOLy^wnbi*eH9?p`qv z*c|*ll*Z-j{~CGXl~EQP^mk zj0gC2h*Fv9`Cj9Gb2!y#<=l{JU3&+X-4Gaxx{ypwJx*RC2 zr$rTRL`t-4?w_WDM7Oym1FcdwxrP8 z*{jDrAB`uBWqa6PW#K1A47$H0Ty#L&T5E#$dbkufHZFi;jLud9PC2-fQn8^LKc`}y ze}DBUo$3aG8)u#g46SMKsq3_rt_)NQN7Y0~kq&`s!mX;pLz6BH>6$!xbc#cKCgB_ld;Dw-HNQj zX@Y;i+Q`AX1iOKEpBIOz4ZlI>AfMdJR~#Y!W_V3OVjc$UzaW4)1(27$q@f-Jm2B$YRrXUD@!WNc ztGsi3J3Jd`KAY&D;n=?`qRj{gG(^I*<;nSI0)+8*3hw=mWy)V>+}XdYryUjvaKLz| zof5HDgr7qH6_ej<&VYvojDu4OK-{;!zR}#MmZ1_78OCL4lEz%MpV_;`zEI(noArS$ z5RlHzM1Vh%%YiD*EL7Fd>%X-H(N59*GJ06P8{kPd^5{SgOpw0d6@9A6pj?Uh-mCBl zEi%&6krIv$e25mRw_71-iVqB=azAmNt+nC)+_*F6$32Nzhsto+yjZw8C2(pk3F@B5 zpf(ai0BR%{K^i5omG6)F{1zbGxARZIYeI|Iv7o+FD0H9JZ4P)yU^TwY;z*e~^mlCAeMF;65Wic0$a8SC zWc*Tde{O+0Uk`3=dS~uChgi#KjpG?&We>;p`{|BSV&`MbH5r>Xj_~v>|3Pr-#|Dt= z4mW8gPuDFq`Mdon{+X2sW_Jd=*HbfJCp0!Xx`o7Q&aPkP3T4qR`oOhB7TXLVWFPGN z3l?a|4uDUmEu>u%M?*oh^EqItgJz((u6xTP>CE~5Wie5YuG+Qh2|GFeY=Nx3I&eJ2 zVeuJUm7CT)Z2nSc`j-HwHoVORT)4jk-tLBy?l5_ZCmn{ zZ#JU@=WW_pgs)EC+~q}%EZpS31Lxd)BXFs8 zgJ8&niZE1f z1wrEY$xOKUp<&+?{kagpWKvxGsIXFswG5JLOU|a?Q_&GA9CYJT{#PUCAGOu9i>ymg zfFX6UN7j$UgR5};k6)>{h6sy87}=_|#pIAUXhz7vw88Md2~8XUVvjX@^rB?eBhO2) zNP*K>=)GrE^I%c{P8bS(g(+Y{fjVzEL}LZF2b!#4QOXjMEDKD%JbC}4b!KLM!v171 zb+O@o_Wr5W(v{n6AY|HABpDXEnKj)<{QLUay_gY2ee%FI%c`SOm-H(EMQQAy;b(v; zDMrxcH>58aNSQ76m;_Kysk~3Tvgyy}x7UA@duwai*4_KQzV6%q{2So2z-_){XF=p; zC(i+Av-uDP8v~F)X;1{a=59|@L4PYWrYo>8qj?q^%ooC2{eN%#3eaYEe_uoAGIB#7 z95;iB>YvZjt%iyw?0#zT)hk?@L##Q@pJ^0@4&M+={mmH`st)isdVql$U_eG^Vlg0^oL`= zC;z>90{>0}3!&AwIIs`(+ywN9-ElUL{1D7eDVN81Ph7e_)15B9P2P96C3)Jw$Y>g5 zE>)BES)g8II6-mR-X3gUfGJhbkhOiF(lV~LkDYHkC4G}^icRiuw;l%vM>8O!cWzSr zZy;%yql3q@RJ?!6_WT37M;Q^h!3Jt{d|sU6eS`q3EU_O3oA{FK3JRsm**F<$5=C_A z7j7`XAiGJXC4Y1wrqpfQNe^q<`8`%O5MB#%2R_g~YMh351V{5S28rObxpvhB%~#Y> z8U1WFsrlvnaM7D~mjQaUyVgK-SOhmeDYpx zO|8z;xe9NcW%<{%Ec>@WjOycW9h-YpI=)hNU?9G}mmK&VGH)<-lXWn0IW4F8Hg$HE`ExVvf$wrWt(Rh-`WmBUJ_EKQSdxHl zg1bRn+#1pRY;!oF>kWUc$<9#0$ERy-kdA?9@b+m51g3EtNZ|zVeLq)BAX`rKvN<6t zrimLR_WJi{hf)&3{r7UlI|3j2NS?fb<-NTkzHVb(&QDQ7CdS(wIEgv^1$!#?1obrN zwX>@S7V8?`9xuEkt^3;EA8lMU6*;EHEgN>Dqx8#4>}lpic3Q+fUSAEA0RDdO$A{%V zjBx;yBhH|4UVS8Gyz2k27;*u#S}Z0D}im->@2aDd4^9S=s()n8B9k`@XUY>dBb12Dy6Jr=OwN>mo0>5|Do#Q*{ zMZbmFhaLzm)-O%^-%FiE5gkGXuhs=lvo9EVH$>#AvYpgc4&YbJ;Y_%J_YqV>Pc6p7BjazVC1D~ z)V7)$(Z7vU-O}*#zQASuw~W2t#h@7shv&#lk`fag#-={9PVJvb?h530KsC4^`32hf zMoG(BEUmEAr1-iSkaJCAh3R(JW;bf*2QoPCaJEXUoLTRMtdVGT3pvUhc z@?ld(0S9m&X8xDwfPwY9VK;@Q#<92DwMo zbj!{fKkor~vf7lPSDRGUe&N8Cv@y_MTRU?`YlyopTK|2g*k+@(VJlQauPR0t)9l7Y zb#BMuR*HDA@tXtP1V=qb(P3Di^e+r`W+asV(3LP=>km~5xR?Hynn(s9mg)Zf>t1ma zi}gE~CdYvY35hR3M7hn$-bfJb_9Bk+S_Yo&qSIED@8G>JxlvMb@^!%F2V$FqoO#@w zT*TZ0_1*9k*yt~bTkUqP#fl@m47RMyhM0g69oT`)5(|dtXec6*0Dy-n<;V4$cJo>7 zsU@BxKk8!UV18`O>Ysegkp#r^zm2j7i%U*c=djt2=Up{-Hxp-@9c@!V<=3@roi|aJ zHEkz9^zJ;3@nu8OYPPAUY`g;&72EK_znp#k=gyzhch9@XzHDt8C2*em{rKshpwbFC9JS`a; zO~K=U%@6w{$llNo5>m@p*inE<;~4H2MT-w31;Rslak&trO7_Zwf;i{p4U!^w zC|f)lpptZ-p3r$G3$JgJVlWJd4fRertc#Gh#2QsqUQ)Bfmm0{SCwmaAjYqsXvh}gM z^*n%yFg7-t=DYHZe{No+u8-U0r5_3*sR*m>cP5gEYnz3&wMzr`44r{dPfCgAEvt$WpEe2&8f=}&jDLiU{46m z&b{!u1d6R>22&~-l$XB3c#`0e3_gLVCa6n$qzj2&PaeV4MQ2GLb}`4VFNN}& zn)vE^K8(_|oaOpcD)=yo^=IHTEb5VKcMujzqmVp<;0O-&BZ55B=`yQa(4hJOULitb)s z=Sf`IA_O%DE#;}xW`=*+$#Q|DfMl4~L`r(^Z%tPROa>=PD$0@OpY;u5Z3u_PAhq=Kz79q5-WP>=d0~y-S@p#DKxD0Z}uSF%eviBP*#3a1(llAM+}q;d&iQGn$*(^ z(~Mxt>AkvrkOY*p=23H(V7=Uk`{rR!Qy>2yOqp1j^XBYSwPT-l#o4~FMFdg$`o+eR z{BIgsdG&*{uv+vhUnvV=Qk?oHbd4>8f`Whzj4!hmMj)VjgKJAVu7Yt>K{ zxu+d3nIuKwL{rG<4aCXOPfky1X=u>s(PlAahs@t8B%=5Dww}pOmn!yK4iPLYN(#I; z=w+P)M;v(D0?So<@0`7`FgZ^AHwvl4U~xOirj}@ z7+!n!%Mn!_ZxsCGH9b6XLjV1by(zN4DPDVz!4>if;RzmW(nl|&cWB5#FIdq|MuLXq zShy&xs6ft{GT&NBSu)s*>Mq@234F0wKT4DyZdDrD%n$r71XMAx35V77k%ca23f_1k zNIa55&aAS7PFYnID7Cfw?~|~GP6#U47;=qPm{d}$46JquMPJ~x9eF`2zyKWssca( zI!TN05V`Uf&w)-DpRGw9qGx&&7&D$G{9eJe-INSk=BlFvFHI$-9=Ro-EU$}4_A)Le z(_s9~%b!wUFGzl`Lsf>j-zz%PM-GqK0V`f`hm_1B$T`%vGwyyMK(br9G|E-Iyok5h z|GrKqv4Y;^w@Gq%mW!=ggsmi&AEC93?F(#)&w7gVWR9z)d~9k)aROTmlU&{$;CyCV z9g}`GZ{t320#_brwCx05*zWCW6i5`hKu*2Yz^wK9J@b*B~3|2_w=JW8(!LdNFKpJA$6eiAlSj^nff05Md4M~}=;l#+4M*gLD9>0$%eTM;5KM4=btuT$7%GS8053||V9*kO@$v3fXULd34OB?pe zHh`}7&Aa+p*UBnbMOlX-Yt*jo#Ew^3>q6nW!|rk`0lTKPv6L<;eVBEb=JAxkO`mV@ z-e7Mk*VJ?e{`LhXbut_kq0( zO(L1T2jb&xE`rIHaoZ0G%tpxu0j$P@;8wF5f*bW=ex1q_r)Hrix`eb(M@qFm;AKU9 zs4M2Zk+o+9S3dT0m%J)yoYx+zd%~-aehM8H+P~q&3`t5!jTm-?faS~Mt@nfs9b*HJ z3o^sJvY#gb&mHByJIppho&agchuW6t< zP_I#4&Qm@bD{%8B^sTR>?45lYPK1CL8&jIFDap{eLTz%fi#D|XpV*h$J zHcMPBI_G}>W3N&@yPy&nHhaUo+gqiB#fLOqKRiDERY*vmLF$NgK}}6n-xvE6soyPG z)q&bTQ2CIfxk;R@MzhP~7dkP|leoq_g@^Y$`7sk&FQ_D2dXJ+u+#AagG2hqSjFLZp z_|G1y^2>h@-gFK++Y1g@{$i*d|54><=IBL{z%DRciSuy5FFIH* zpX{*zbC`T7%p!Y$gJQSB(5%TkZeWzUY#p|Za2Ujm8n=yhsC2td%E!>T?Ckwbs?+zT zo;9_G_%8f*n6Xm-#4fmTOPgb}J`B#XfeYy~vg{Sc=kkSI(!Ftw=Do4DN%g^;Qp@bU zrivgg3UL!9p@|Ju(9Yb4V{LV$`1uav0$Yxrs+aO=^WzCCTjB(EV~o?>4DdTHrEf$g zBBv${AMPva>+6@9hvSp@3@u{)+Wc0_&iOg1DmXjpl?SN zs3L?&Rm|9X*7$f&_LGzU1&?0eJJXbedPdjF;=_o`$Q+7kP;^D%MeG#j{j_~kF#)oCaPR*iGbWGKh=cD8H# z)sVj9y4=>#% zl~iUgphkmF5JwaPI&a8^-;e5B3`0`zzf!KeOQVCl`yk|yU-YRkd<34r*WTEHbw#}W zy8>&vm0Dkzs<(UF@l{W^G%9-S2M16Tm-B2GwXsA2SSpB)1UrBcWG9>M0-Zob+%uX) zuXzvn)+P{M8+FNMvzD>fs`FTH!|0-|6m3&gYW5=vXHQ_FaJ~-<%mACU1qy89y_8*B6O&V zVm=ig;{N)ge*Gw?zk4quZwSgaUv9Rf00*j?|FmV)f|P@}dU+%A8ne1 zO_kbrz?d_)zHU>6W-C>U5sc+T0`QDu|363m5n^znKM>0V>o(`CDE`1rer;pi@*KyU zmp@ZoApBk&(fwLd{bn!890bCQsde2TShQd7ZoNCzs53(bXP{7H#5up zJAph>W}F6NTI`qM+n>Z4GqgnNQ9ykyZ-7JK?_5BH-C%MFo`>|qgtjK?uJMh;;?5c%kK>flu74A!|Xzq70NFIoK)4YbF`uapL8(MQf z)}KhLlFDX^FqXo6*pZZ=k+7Zj9>6uC*_CRjY4G>)sgdMW2Q(jt1SDEdH{FBk)`u#;Fbt59@8`XOEjE69%-Fswu`nD9fqUWd~{hgbd zA<%}sZ_H?Esoux!=%_SP*B%03-CX%&QU#j7K516bnIu`Xmo-1PY zS>;IX5J+| zlYOUeU(=uR@{_w4MNK966x}}Ql!)}7*uR3kIloXN=JIn72Jj-1G>-rk2T zvx8Q1+NsH+e$$*qE!gJ(9Pa!DJ;Apm?lE=eEHGa>R z52sDnt=!uD(xppbQx6zE1@5Q;=JkQh--dgshHc1RiltC1^FFP=imt;8gRJBT5~`nV zP?AcWR#TFeHilro{Uz}G4t9!3kj|DZHz+?>ZtA-xCuvx* zEp8fKf`qhy4n8}H+Mbat9QbUI$)fnpZ2W%)uY~0*mp}TTg7sD*qP5(xgzRSH z27{6KNLBbF)P%)#e>Z^Rn^)YXD?Ewr*d(@jjEce7?Dr;zxpaaN3le7~Zdxn#ZW}zT z)0|YW4p$@IMc4;e41#Yq`1bF}TFfo!-{t*xc6K(AV{Z^FQhjJ;0L%wsRWaWS8PARS zE&BG-wtN!SPt4O;m_|fbOP{RGe3`ET6D!ytPZ4mQUA!$VMDRejF7v zRhd4x7Ti0BB-*|x9xdm0lL@HU&k6Jm*a;ZBgAFTrXwX9*sm4!Wj{2ksYF7tH*AVqjs-aHhNPBwhoiQK{dyq1~KC!1U4B^>9^%;`%{sJ04uG6O~ z(kA95HWIJz1#68U4*e!d%7C!V&~Sd4D7T71tEead(#rOH6EawzF91DxA3ds^Nkrn2 zX=(+8;RpT*X+WuJ}vDl{|ZD+>ffsnRZ)C#_sr1rqcuM| znLL9@5=pLnV-@+ND6s^)H(AIHHa7`0#JCsc?Mf?nM#IeetW)papiwA23b5qpv1FZu zY~mD1qxU%;Ip$k0%PVWn>o#VGS6FmcV+OPX*$T<&+o|}5H zHS~SD5mHjt`Q69?J}MKFlXsk23Y(A|qO*At3d|=98yk~HlJl&< z?9D`rN+z(dA}5Dis%Mp{jJPI6N2aD?m~n+Gz;R=L&dM|4!7AoS*StLuvD>(V;nH!& zR8#AqHc|rs9G?bmJcuKhH+@qvnyAlf4lO7~**~5buS0}}9?u*FI+>gY8AM1sWM~*6 z0s1AVBV7&bRT69C)JnSVJl{SlF~!RF%JPp!J24=}1U;H6i|+@~v)0(^8*_XX8Y&7X zGE{-}@T`*?72S#)%NqYiLA^zBHvnQ`y z!g#el-Zb7)Km!+fPRt4#*hT-0vtj}o;y*~mrcQwiqv*ac@BF3gH>tK(jqh6ukLAEP z(`cmY;wi(6WApf=w5Udo0?DYs(>v)Y{9y=fJre31Z-h@Wh-1s0yDown_mB%Y9p3@> zETd|OB*YhKrX}++{!zt@%S|_rf#hz{gL!hHQ{9`N+6g+9(SO~)as%V`kdE+ z%UvysVhk_7dBtx$x-lOOD)K|A8ilA+vrUshrKkx8v-*wn7RD zJ^9*2f;Oi6TAQvlv8_tgQG;I%C|Q znEy@`G0?|sUM7Pv=nnhXgp|-5sgu(UEBG~TH5f%4F|-?(&G9{r$C(PeiZUym zyC&Jbr{eO<^{Ktz1(PHQFGS%qv+z}EC(_ic_Fa;Jp5>4xT88qDben7SiTi#{79B@U z2-il3J$JBb*hw}SuH+Fp9Z@_3`_SbMT4SWgs{Btwm&&ZyD}~SumwWhPLLQ{fW1~Gn zdFS>j9jd4fF{o%++|ROz}vF<(mdrV$&g1=iqr36<(nC} zCs^4Y@z)w_Qm;B3w)U?V&m>MKNz)O1*7-tm+nS=fA)Itau`mDxy`>25 zI-aj{Nyc0Xk&53nL%?< ze!SCSxxT2Slx2)~d8FmgY^UcFct2rp7M;K6~}`+d_Its8CVC~{K-EP|*U7G(3U-wdAsoA=D~ zoK5HzWz;rWWVqkw z4r#})70)4l_WGA#`px**WYWg&yEurL@J$JUsO{F8f1Osg=BbO7pPX1#wx1zfxZ$;T zUh_oXxQ~PvD)bXvID#HYJBOB)MobN*=2^Ol>*D30kH20n-qD6>w34O;e?fxArRs}i zQG7N00A0=+2IfuVs$(zmdo-l< zeguUiVx`<_^v@R2y!`%hi;~gFn^pRGe(^#WSs53ZMA~h9^3Vh_DyE{!^q9k z^=a=Jd}4F?d=wsuj(^?^Uv>^W*2s7=7(5kC_O9Qu9vohV_aH)o7|Ks2r9=zE{;k%L z{fCKvWRcZWmElb^55n?L@3FAgHYCSc3_ImJ{lcsP#1#vJo(YL ze{Gb86AT6}6w%#i!e#nSXX6@xMex|?x#mG5H;6QAPb34HD|;Cg0U}=}!yDOUM0a1N zYTXx3Q|qR-*Xt&MMMYEs4^JZG3#4~zRfwc&NEA?^LwN7ko zY$zUbgNX%}e)c7B8oy(|Z|W~9dA(U!hH`+8)y)*&uGlQ${$+iYjiwPbf+35iq87=} ztDi9{(&k$!?)%G;zEC8bU!Y~!zX@(9=;At?pb#qK`K(mKsc>8f6Y2GR;zg$!9VzN+RaJS*{wMRKf6TT zeDNtJJTswmhDQfY|Uz+V48eXK@kunm6XqBh+2}w z!ohLs4WovP&BD*kEBWP>-Ja9psttFL!ZK>r9anVj=p&qre;^iB$-N_vTrv;ILtt#xouWqs-v3iP58MkyHZ%- z`PBfzVhn=U{ht{P4NcE zq*F306Xm1PVuAXo4Zr5_`$n@yfN$Ep2Uk90kg3+=8-9G&!sqd90m6!JD`_hn-?*HX zey{PEPvJOShvT2x2>8b?bb0-mi&W10GGq+8CRDij{1bwe1TEtKgf>nc}NgV?Psl zVJ2brL}ia}Gl1;o8yupbf$>yMsF)$=>4z8dtjLx-%<-w@2nf`~N7fDAAO}THCZjuC zzvN2KLaoX7DqM7HmT~5RC%8B7%=r@BxXJBRUwmoL%r7oSp8{6x@mV1v7R|hNorF@q zxMZnik3%a{!@(b;)yy`$=gv8tzmKuhOKG~GnxcGJ^FLz{$wPGqGg#EK^WU3WvIg@h z9&aOMXlZGO*cj^<_x2B19e2b)&>ah(lZ@`mHESZv%ZXN3wIL#!E}oIo;us^RT#P?y zt^J@pPEGw2cyo@GYm0Ij?#^?P`^LBy?qC!gvrpRIjfjXv?R}>#F^?pPFClH4l#?@c zT%0|*;o9b5IDna%c}&eUo35N@d~>bY@MtN4L@Fia2ol~p&EW`I1Qvv(`kPX-EWJDf zv=dB_>E3HMdW<@isOm#vL?bjjnFAC38{xljBq;YhWHozUcP}tp z+mD*JE%&rXC-rv6_?1cY>ic1MvKum`K!qQ(wuIH{W0qo2YLm1?spkq^CWSjg=1bch zD`oRh!}@tVN?XDng6R+$VA^6X^0+@rB9f^szcEGVD0eiKui8 z^MvFfrFl96wqlxwh!dKDSRdh26cE`3p||D>5-jWkjtJ1X6lbO9bKK1qj zJMNM`kP`n7ZB}o1&V|c^G-WBYlzd-O*8P!Q48z8tOO?das~8bUFrn~Cdh*<>P>d2G zt2;SXuJ=w@Cf|d1zEVQ(Z;`=vHl&446MWExH<0 z7-^BgOO)ZOH^BZaQ6kLWRb%93jMu7))YZSOfX@{IXtOtT+$>k>&Ka)Uh*68xsxsYF z2P!-*a1AF^ck#lU3Baj2}NGhdRVWb#~7fd-&{h{Mua4Yl1f1<#*Y6*iL@aonA(-8 zKx>w2%Z*$%G@1W0I{)2RC{6v0Qirl8x9lF_KJo2IY6-!?Xiy|(S7O6k^?(j_`(I{QRxSl4D#tp@DwW8R?cD?ZSfcO})>4kHZ7L=G z)#nqVUZ_bcqE3!?7jWDjy?_)J!4FOfuGkT&-Fq`7cIArX&HX;jqj$&gMd3&A3_QMu zGQ{LFf3Fx?|>m%&?^bLy?)emikdL?O{ z!=~vN4gPF_B3Umx`S1(v{mT_mj-6@kCJ|=+wT{N<6mFZo=?k$;wH6`knurbWwb2Q| z6eU44MwAveF^W~GHMk~@r4T=BveCmjL=s_{Zt~1#X=iybx%M95yhZ?b0GoOw@Telj z*MxTRc*%(bWS2N|`z|t73=7elnYp`Lu`mUSG<0|tzbTP&GvejuqXLoC~HU>vVTM7+OIbp4wpx`Xe1rX4l%x(Lzn(j z+>hv<<)3gsJXL!?iCeAZW*p4OiBH+i^`cCrz>C0clrI-idSWFJML=0(3>DG`UeNx) zawI>hBGdeQGQGC*A?VBs+3Vwg0jpePjy0?tK!R~2>)NUDm{-hI9z>3O#sqlz)((wm zfvKK*Sc2TgyxD#)=m&d`@DgjbNowaDnhq~rEGMbV#H!t+kJtFAe1b#k&8kS(EZkp{ z8m)d@EvcU|8oBAoZOAZ<%4|Nr$c!7@Mhr_u8WKF&njsRz?;HgCwp$-Yjo)sjwEe`A`NZUka{O1; zC#ZP+W@ri2!yog{Bf(KMUWe#7%$+%03eAx+%$4`O5C3|il1ty z6j*F7M*<7zgX>Nv)Zq{Ih!p#;qcX%~q>|t?LPp4dV>u(dHe2yDM#pck^ib=AsO;oM z#KCK;Q_&;S1Yv_gn|H>%0^&!46`}Gf|4!9?s$2Q*ZEK#I6c?^%kd0RA4wScGZ*WW; zZ%FG@_HR@>W6AlUcpPSm=(fPLxoAoZ6n3M2n&2g*lwg@bVV*1^=UZ8@cx&v6Oifrt4yQXoj<+X5#*JF-e(PM1XT!!d051)XCu(CPi7-RKLGvUivYb^9yYPu#U^wJZfV$(Bxgags`UdQ8a8xZtrL&&5y? zp(JG8eb!pl(gdB{oawyNJoS9Sv^?c*%u zm*cU8M0xJ_ zekgki{yXpSRc00;50yw+@Zw)KHk@_3MRJIx|8MnCV1ZzP0d!p*oP--0syPNM!c#Qh zy3U`0*;az8V4NXcuo-i6bAXq9cq~eu)4nY@u1^vjAt;U0m6vjWa@N7W@A%An)tCmW z*XL#;vmA~*rv?Z=tXjgGo+0|zpHPCh|Hy^tJT5PpkJ?qwTS=x+o|eZ2k? z-9x~h<7*&es5X_=Tvu5AxN?*E+dtDu* zm%bST$^Nh4FgyGgt2%Meq4j&TBRVWRL`R7KDwJ>cC1rRBGhkEVP214r4>~;(>HJ6H z!>AR@T0tN=)e3%^YzAkP0r*x~8$SiH><<@M*xL{7zp;~6`o<(FtdF8=qLf1M_|Tca z6xhmwnwJ}F$VhpS05RG9dr}EtiQADQzNzVcrsuZz<~OWPE}YoY!`VN&d#Pip54KFZ7~_<8-OJr9ck{2$k%<>{^vDZ1YH;4EMP zrh@YFNIx7kkc$tyISzJwnV0Xul1kM9V*GWQPXuA_$?O zNqYbHQT$Ue#sae+-PNE_kG!TIDY45-zfC@H#6oyh@o=W5A!+8<{&<}?9W6?n$R((2 z-TbkA#SsU0%qj}P|HcFAPZ*w^R!uAW({Te`Z0Z4*F2ILcHg2`M zkR$^qX}^B?@eqwC=PVqS8L)8q=Fc#H`}0}8UwV!#x7ClBijEwRZf7n1pavZ3bRjrb zMY}iFYelWPv^%^8&^UF!&%4c~;?py1Pjz__3gr2w~zL zN{5OKpqj9M!)@&di>dI|vv-_Zt_^uzha^W&NRa3E_)q{6nt+>yMW=gzwY9ZHBE0Vc zcf3pr>UyH8gA|m8f*6!U`B?1DjdpNKPVuYM>xYsLi0Jaf$Ho@GtO2(sY;k&5Ti<1I z_gx@AXnupHU=(P*ZbRxdBe2+z`#(kYibY5eMBGEk99S zxc}sek9IW(gOutvKdRUwk1h*)W?9c3BTOBwmHi01T#=?<_vc5@%7QQwP>B{LazyrH zRuFnE%j@JK0TO8A`JFhYIe*vm_LlHsN_4FSH*EiiqtS_A(O5a%<@h$TH0z<5nz$p& zseqX6mn;`>w8vyld~f1IBqV(qQ>mSx6(%V`;j0lwSZb!{XvyB*9+KAK;muPjw;_3- zb+F27NXT-l4?XJZwWry>nF;m((q!H~f)5-G@>6VioxJ zaXTRZL88Qfeo5l5aF~3NkD?(>4c??4KR--}Hj#j61(KZ|wS4g66j_ zYS30)bBH8qtr5Zm`8}6o#ZN$~zN$ZaZiTLty z5|%|$ecfqR&{xx&_`uvBD-2TS*heKM1Wr}oSq(*sY?9`%%ME`z72m5gsTTbj9sK6y z*T`!Fn5n?wX^kd=8dm)K6J1HK)BOguK1lS)fqo|RK<*|bkUb!9tw1av=c&bGJpCJD z*Ot(q*PyM-!%&K7gT3K6Fn+ZZ+-ePi;hHixv%^tqff#JdAKBOp{6wY+xs3y9hwBAq zxKa6;l9Q1Rk1W~2B^KVj1|SeP-sUbiR!+k+M)Gy(^hAk)g)(*|V@hyDO1~x5zz8;5 z*(A#q9{H{aiS}46( zs;D(^xI|ZJTe^2R=Fj$B69H(nlLUyjCNGSpzu;oTK9vtf$BlEj7AXT59BCN3ah+*P z51nN`@=QoQn{Dur<5^VfQd*$b1d@$`&n{`KafHjkyzxS|koqF$FA_hI1_geqd*;MQ z8-BS+7B@AYFz{oC@%oihOTXOD9;nJ6P{uyj4G_RkKR)C9BhLtuibLx*Vy`~JxU(@I z1X}35Fu2e;%*eM8I?RDc8#|u7v_#0t?*aK#?Rfmr%x<;=yZ46Tj7X*q2kR{+CMHM- zUE2>YX&jaq;1Iv!*JxZ;BG|he`<;?49Z5M*wJ4&dRh5?wwH&{%{%?}c3_kt?6*xcb zoBioK-Na+E6*aW9MkB{64~SC`!R43A(`f~&^8d%)TQJ4dMC-zX2PX*-2%g}s!97@T zhrxrpLvRQhY!ckv-Q5Z99^7qkcldVlo^z|dzi{hL)f7E!>)pNjS<*`)>rQ8tT^$bb zO`YFWfNV!3lN^GtHk1l};1E`ev~5Vi`R`33u@4z_3u} zTDc_#%~xlWetn+<-QDX7?BBAnk^3@(ydzDhnjSYmSg%~(R$Hw9pm?}0c7@Ydl`>Ts zmoKabQm@BWCQ+Dyb&;Aer-*4xVUlGrPfL+Q)er&s5qFFwwds-{b;3mSBb(@b8&SMf z57Y6RtSF*OXBqNYTwL+T6QE3)DBz7#$CTqsPlYW;z!DP?#<9$L;w;e-^%Sy9iRcdqqC?GHx=3%5qjs>d7D)mM%V8ro9_*V(ao>mlZu8?3FBRF8IXcCgg| z`(Fvbbbv-;RpFmo67I(YwhQ(2f}5+7XxoD)kho4;wMr6<*8Z$>sw|N@q$1`cvVB{B z+HG{r>}&z#^Oly!pW89G@fBS4A^BS9JBa-7nD)dOi>znpbn8G4@~vXM#t zEz;CfV=%NJ5~|B$oR1e(3x%t;5rxSzO$9w&S(O_5hJ0&voP2yrkP*D@-vhZv{-49V|7 z%TSPX5{-Z~v$Ld16*1j={gHCVlL7Q@rG`kHq3>7m?(qCnYI)9<-01= z>3&`W-($0_ql$q52fnVj1QdgiFvme}1Af>=?)>)7v&XO{(qy(rT|w8y?DauRwA}ir zb^66&(JuG$CIz0g;NC+!wz<*zTh~dKoq70I7{`k8zZ_nak>?g1Dv6%01hYJ=%5+_p z&}7bS1${$eGu{xOAY&0atTlX4VhiL#weV6alH%7io z_$9NpH#C-9M-1;At&1T5#hBVdF^4b0Q&RrW9hU*)`^hgvkFiN~Bm4|D9HVd4N}(Tz z)w0ST-_uPFGG>SDnsqz5hXgRhIM^M}?{1uZL(G{sHZfuKKIEbuqQld@!am@%S<75q z>fg%xAa3G@Z~f_V!4&CZsZlf0G=s;_SUG==XcN2Xt!yCaGVdA(fc4rOFBZp5>St#~ zrrd-3y_UpWZ;PpyWE2%&L-^0A-|0E+3uqztKn_|tZG!m1SFMe}(BU#^S*Lo&w6x7rP&wyGLQ`~k-3MM9$hJBH_B`qn6 z-Fo^X_qBYdVMB@9+MNl$=@T`VgS$NR(Xi!!?iSc`Js?r?tdFC|f70b|LqktPvmWZE zezxTmdT)%Wu*H2FjSS&T21*C>nh8F5N@7*i82=#Q_9c<5CCGPr(!Ih$Bt{zUg33SZ z;H4ek z&aB9Js9abL5Y}0*qQ&`{YZ~3Mahl9rk5RR(HWjiYJIVq^ub6y8j&C8qixU~3S#c^5S$;a0iWA@+ktZ{g%|^K9`ewo=NRyW({xK;8-?*06 z=vRKiwF2A%Yya@z`eF5G=epgcyad!qNk!%JYe2ie$TnIEvwF1SfIOevyoyt08!g0N z(T%SgL;bv%u;)^_n;J;(N*kvNF}$vi)nG zqZa34YdR#7oR?5S3Uu`UggF@4u@=D72Y%>2>9*q~qm@`f?(((&%p-!2z6LqsrDvAO z(^{<5ePmE$|17#AN&JKTH4E9B(5O@*Ag}mn5A(fVk+F-*r}_DLG&*Xd-vJaQ?miTd z=P?MLrqbYN$k%UX@?e2JV{u?F+a6fAJtyj?bIv4=ce&~cU~tpwO}g{W{8FVQm3*mN zVk4t}2MlYsT*#+$=toqpyNw}ac-Tto0KL|z`yKZzOTD*-IPeBSKz^EkqukYCU*Sa- z+}&ZvMMlf1j)h3et;WU;(gk6@u8l}#dM2iO(}fajKK6c8^p|+oYgsOAVM~8SAfnJ? z)+z={5*%+) zThSb!yD0MtX@I46yi|R!Jr2dHI={F`bl(zm^XTEFzkRC5*HP`pP8W90Vc8ygwf8FD zEv4k~8#3l9s$QZi0|f=eLrZxc)azUuPEbAp`(Wx ze(t8k!Qn`8hnjmSEvBRpIyg9hUTwkSvlvnyth%QL-aIDRy9tZ$e_G0G)Pcus)w$RSV8Y0lq$5NUQ2f=I>)_(T+DtgM~cM z5P9bwWO|o*M37&fHdVw3`@PO=bwXjEykKh;xc<}&h$aix?OeLYZ`||Qs zn3iZnnYhG;y!G9|83ry3$RaL`EsU!TA0wuYp7l-ZX6M__+2#mj*@Wr$teBgYF4Y8oyT^zq?WBvyT9Y)u0#)FL{LjGnIpdn*ntcW*p<`)y$zh$&HRWTgmOly+& ze=MlTJf0uRGf-7l^Z%}TooO9e?S2f2IZufkT1=9$iH@Jh%2ER>T0~FJ78y5_On=uR z`E`TYj}*GFP$wzq{%pVOF}D1Ek7RmHU(s^5O$P9st^z6vuy9Cp%Y?mSn5;aAoDjCe zob2#moGABpD=uq1XX9}?vS?knpPpHbF4D!teQ@#&E8a~b*^A#%j^I>Z<|`vu zIAmAeX0jz|`XgxMiAa;8cHMG9a{2HncjfD?qVHLJa*Ub!=y&gy`r2muJ&3ffAUBgJ ze&mZ#VS2M?|cB z=IA?!;cUs=3C^pnRn-}amyR0cdpP2`i^xB?)_c^R(|*z71Kf%Z>D_Gz66#O85! z+x-Daut-b?sefl=M+Co?uNzI}{^5+6oQRLj0c z)SYZwbeTZ_A%3wT_k>o>jd<)^mqYnL<0xxz?WdO2p#$#~Q(=v(T%FPPM2a~3qsJOPxD73vZ*j+g#r1y~NsX{YK ziUFLY?bH!abvuM}fq=FK*T`>(zQ>lVgwM1Y{bleM{&uRV+dgi2B2TtQ(cSVNGAUyi zjsn7q%Q?**LwE)5m4reUn3$121`Kmj3#Ua+nfu)k>m;C|z0ozyruR8sZc~`_Lg6^B z2rO;OAHMos#*w`sR)BhhM$!=lY{9@&aDu$whEy{K_r#b`e$bpg`4O^`zw-11ZhwYP z{WdwkA*d3D%P^TG7IqoD`}|9e_lcotf0uKAp;$0~28lRB`MYi@<8g75J%fei1n&ak z<)*~R_*@&M*R3eYTxhI)NNtIVm*a@&>c={A! zrJ@6{%6o$qBxR&ElU#TX3BtZJc*8j&mQ}EHi=X?o&w=`{u52?q@K&@)u+{egx|Lm| zuKF=0N&Rnx-1bF=s)FQk{30|*4K2Bc`seF{>QB(>U1OkRchfU$E06E^gS&^TR|oZ@ z0`Jm8_v2d9$;0Vhw335rL_{YEmCf?X^d%pfIS1>X^Q|fh-qi~h4RP{ke0}k~J~^2C zL6uhWR@XJFQ)u_+I9nS%SDYQ4)cG|VomPygF4sWYO(i|=6E&l*sV=X%4K4Q7)Ke~~E7jm`aEKsA zQql>UzMOyMR`&7yC@7*5T=@X!lTl{-+=c;1UtY$;mUcZ%j!8!{7=3(8UOGt6ZA<&G z{Gvvztmzd9rcp`R<(EnG#R)7g^#3S@lEX}|N0-+oQ)_0k-+9Vy()1L9cs(Ap`qk(V6t*5%u7+?6RT$WjpHh)5#a;Q0L=mN=L&{g8ItVjuXS|ZK-^Y%s| zp=%IYGjDg*QD222E8GK1NxN#LwQwd+x2|*2MsODrxW+m=&h{z7(@X)%1no(chlWZV ztFAtKUtM9C*-5%zXsu*zM)ESM7sSGAzDse2_aX28v8 zp^W#@x&Ol4(_SrZLn@maYkv(LA$bgFYHA{v@;N`g*)QhzxXjM?DRm9t&kb%WN4v3H zJb703?-`nI@(lbQiO@ZmUg?|_=SbLJ?X|<|ISrj=*C(*~UtfTd2ZK*+hObP-=Qw@J zkK&(&uQs!)^dw?N-#WVxDTQ6w7~?N8J;5=wx3r1S7n`u;M?7axTyakglI0pV)DF_G zI)8R>HQ!%4V7u)kejlnz|3xxQ$5^wxk#3=oX7L-|QE==Hm2|y5lVF&%+F<%VtC=|Z zJN?4ipA5w1gi^Q6%{$S4hO*7F2I=Zzm! z<^xd_xeCP#LUhPgE6(f9m%*m#*&<})se;db-uF|*PWM@Ar5HDKr)ReN8qCwh2&H}t z#0|Rjy06U~$1`tQPu`U7K_?{y&hzi@IonF!dA~T0R0|xG1yuC{0Z(NV)I{eoNkX-aaP-3Ix^dFQS2c*w0gO&F+DELB>{ zBY-!pDF5>1dCyyuWg4#2^XW3M?`r(1T~TXM`{>|cZr-$Ar;pgfs)!kQVe)<1lNJrC z)+eI-ZAe>r`qQOFDY#LE3hj6{s&nP6-qw1e__$eE9((s-=)wK+4Dy@^(3I1Bus|M( zk0{vX1s$yY6Si?>saa?4@mP?9%Z}!VC_z{?P-ECeDKV97_E69m?vemxju3G!j);VG zwG}PjpW3&;L1-$-C0?yBNO?Q&*bT#Q;mu%6XQt^|wLx7IT{h z`HZxe=9!q#!#1M(opRerb-h1jm?U*7s0%2BGWtO|jj34CmUXHcAkeTlx-+VQ?Ma(c zJ2DE$L}M*;$E|%wN-0dL)UjsmjMwRpVbr^@s!lTgP5!3MNLA?aYI&O%oCDonSJ<;g zFtK|<*RA?yI9d%Zqc*ja`-#U&{xd4mB*)7x@BM7V9MpFP2|B#N$Ut{Yf@{P;eSLuW zovhStPkh;_(P<|)eH@9gQAO|eQO@h7@xdwcWTI=sHx6J9V|vgTto9Q^A%C*pu%L`K z4jEsZpv=1V+Ye(ju*}Vk#ofWvWKsyxC=3=phZsaPQWLh^gtXAINJg*Sg;p?gzB1gC zKa_|b8pD}VbXD$Ey5l+u@kv(3Hlq-p4Z6|EdJbb$Q+VYxYDpKY z30iRl5CV(}^1Yu?fSIix<13wk8S8)@*I4kPZrZNs$%(^lmGYRm`D1xcf(u9E6ipF+gdC*5VI865ZPl||<-i@vjH zhl*jrC|h8xhFQUH(P#p_%gBP4F#>-uAiI22-^l&TgQ3{a$b|nL!eVVNT)^UU(L1kD&NQaTq zEI_DCk+^7#2}#K7dNImus7^~D%6Mx6}`XWfV*FR6r(*RP&jE5Xg%>K znei)DFLw0KU((sNZjf2`5X_(}d(11l8#w~E*d>la7t6$Yyi-@(Md2Kgocr{f%T}wT z7iSr##H?Gv?&C1$nL1I3$wed{`+MNj6t3HG#9wEk^b3+=eWl>1@~$e%mph>(7E&#b zE1t%4(`%TRTK0ux&63Q+{OP7)DpqahneAA^Y;730t7Y2}oeNLW`#S`wK-^a7P5psc zJUcr%6UM$@aadEPm*4f_f%-`sOs&iC90kc^24m|MD|(x$e_9KauIVb0fW5*Yca-=~ zp_t#nbe*@gR;$X*@gKTUoxGKvu*(z3$!s&PcB;G%@3Wo37feg(ShKgt)46!aD({j zD9^*)!&RJ|a-~nOcOCC^+P02+-8N*V`|#D%J6GuUOk##Zyy+DEx)PboP>bsZ z6V}Kvd(G|Ask-<*KEp&FIb$z2zu$HPwDi(JU3`WQ754KcEvs=ZWCuSDiPOs_Ths4R zDrv`TKfVk*b`3bDk&%jdA#a>9G1E9fUTSWa_}zT)?@*L$tg+&M-j`T!n=7OV(c`&1 z!LpYJf&DmK3-pj~brEpmDDhO&yCpExgcEoQ$D-UKIKEQOrNr$fWtCBeJQdTmX0QGf6L-T&&MDQdTMa*M=G-;#xnX# zZ$=q=l8i3B?vAmgaMJ9poaaB*V@s30t+?>nImmkL)uVL%@J`SvAkOP)B9UZH``n<9 zV(4yi(0Rjc?8U8I%JWadt7(zWmg%f0%HuOzQ@O>_C`hqL;+9f^0iSGBl9suOTr1{) zx_({0H}i>m?VAXlfSWH47TrD4z`A8fh@u9uD6xoWdJ z*nD4|Bss|5`f)Yy$YgtIpqdzwDHdnuhf?`I^>Qh*gQ|8YVVfuaj`PK5VfOy5SrHmd zXBf?tAc$eOvcwb(rK*F% z2c3OYob=lP21ceu7N?o>?Al9&5o9C|2}T4Z2`p%rU9gDbU5Y}f!^oKeW#OJurNa1J zIurB-ITv9{;5Z+RepAYh<`pD*3L04x@4ch3KDG6>V=%VB{#I2{JnlxfjmmFGBfReM zT!L1l#A#ELTcN+1uw~=Xmb;gENK?EgSby6RC6`z*PmEbkKgQEYrLly(`}R2YgsKr& z%B{_z`WrpbnVWU!K?pes1A^x9UHK1?RH^WEny71{mS<9U*^tue>4_2+mHdukqIqC0 zRp#&F239nRGYX5EH}p<{A38)XSY2&Hu1NsV!FoBX`1wZ9vch$YUGA!vF@w^TnvE5` z`A_A0-Oph3PbJBy3_#K1ZEnts_m5^{^CuQp=4vYr+E-5j{@-BVHqp^HeQMsv=_4!` zeE6MSTwSdU0zS+X%D=>sD{`oRFErOn$eqH0rtA=Ze6JJ1D#*?j6~NM$^C>R z4DR112=pG4Bp&WxE2HeSKFt4X{a-f*wF(G-MV-T!hwaUmY-!>b8qLS}xaZ)8tu*_^ z!Ka_bOxZT%C%>g<%yZjQf9MS8rXNQwWtFoyJzuEtXuMr;8a>FyJ&tM~XmvO|bsCu} zy)=!hgXW%PI|xqJUu<~=mp52pari@4 zep zf>P*vrHLRF6-66^!6TjHGKEYL^j;6uWr3E88%D%2!dDd_kdR}A#mjswjm4Q+TRfFZ zsCSjBoRn#!*}W>aR2BX_YB5(?BgSY#aPDrox@-dtjJiJt4P|5VF#XLRGHFDta>e$c zxvB3;mxqZ5;`pnPbWO7TBXqD8PKp{>@o$sp`frJ~m8g|T)%CZTX{=M>cTk4EJjA%e zJJVF0tDg%8=N4cQ9MH)ICSm{fi%%Tbc#*sD&N`CG>&Rx)`Pn3pwfTAwhgxCJ;Bj3t zPMWv|zC}UyeH~ zVzp5PU(mcvaorD><|LL^qEzFrSRbb?4o^d)*be2z#-mQW8fjAeJ{;fK{|*tzA~SDpJi<xq(2B1xJAL+k8lh>6oBTB|9)FGzdUA4`ft7S zIy0w*2aU)4dy=o_*WEtMxOb>g$#I^}Z*f@RqIUIQKzZ-}K@>A;>*ad4^y*s^7|?s7 z|Nb@f`tJ`NA)LQx6|tF%Ng_Z$4(MgCD`5XV*G#Bnu!uj+2LZ$ujPrN2g#11ByMrzJ zj7tV#LBqQLMo=jF+nK0D0bp(u5(9xuh+yeKAYZV3k*^^SM<6)jW-aiBBzJe!mA$VX zS7It3N^NYd`l*_ColTI~9lgm;XPS!A+~_XSdNzvhnIw^~=3ETPbR6qFGp-oOBXlD3lO z`s5KyHpV7>jMnbTic8fHWM^cUWmOx7qTFi|z2GS0hq7{6v=Jtw?4-pdX?NnQ(7nB~g+Tz@60l%ZgfCzRP0o++k3;hoS7D?O*Xlslf&kt+cCTKX^u>$FI3HHNuOrQYGkhVC(deWXhc(9 zk$1+7>HM-tsYeVB1(js!+=XCSeO6w+UZL*iS)=`4Qi<8KXJ|~B=%Jl| z_m#Z*(3&4vLU!Qn3e78bNg$|xirqM2IEOjh@S}3x(@!MYm?*^J`{fvcFuUkLzu_!1 zvf(P|1UV|4o4yiWAY+>Q7HcDdL$pZsW&S%lq&);j9EQ-HmO(>9dwohr99i0gLWTQg z_C@t$iA&w@gK8$`k&vEslZ>xH@2|MLEfmR6WY}`<6tT@%*%Fhxl$!LsvUbmvO7M%Q z@n6q6k^Xym-n$Y-aV5D|7C&cIKBFduI^#skKLyPt8mB4DIm}h7mo?@vZ`#r*h!33KSYwg;iz}g6G!vSa8W|KioYt!{rn(Pz5ehTK?7$D^5v>g2)iv% zkurgd{Avve`??M{Ko?IqVV2aNYa1XwrZuxc6P#8Mo^k$^pcH4& zZQDGgQ0^yIj{)8;^@-a_pk5K6=^o_OFy{7)IvP5m81W`IP*r)SrbzPT?(Vz9BAvy@ z{S)Ev-mN{{&tbME!?^mY&rCzD+uK^N4i1VkC;o{-vHMxE_u4n?i6^P8~3v5J$fabEWE0rN0^y6Go5Zj*tFUHU5m8vYNXRi&`f zc~`irAJlX^6OYm3>Q&vgRq_nqE(@4RQJUiOXcKOjE<+rcibGPT0?cq8h!GUx?oR)N zl+#}ss67u>X^cl#(MhX%qCyG@cju1-FGb z=oO3SZOO5H1Yf9|4x!$#z(1S>6;%OKbGejGC<@?Y-hT+}tCHq%Q>g+A(g*)1GfG+? zH0y~`04JdTgJ@rwI$cj~(e`%abO44E)c(5_tK}tNl~N%22m7Eckr3dJ#eat!J_3d{ z8H&He17hdOM#+=<7^tzI?qiHTx#DPbvgwK0+s(7pSeNTJ2LJCQW?A78_LDF4wm+Zx zD_bKj_|5X2`yH&M;nI=+-4V~jA^HT`CO|oT#jbhbne6^JVwK?iNjAjzYI?M#*K33= z-e3nm7?Vl8*e&t~`^j_YQ6TE+^!=>$^^S4(btjvxEwHC%%pJErt#25&-3aa3cttZb z*FQP=Y`c|~LxXTv^G~kgrcCmLrg*~^ACkq*>3b9}{V3@hqy2PcwJ0x!?$IW?nYJ1H zfL#}lqQ&GLtES^1wGuG|#W&fs!ZlT_kIy*~bB%28W zTkDj2Td^@5ZF>=5zAxH(-dy<_CR}}yR$2=a)1FVAO_tzm1dgxRgUZvxDT}vvhE=6D zDWsmQF}Z8n6d`O;QYDi9C+{5Il;2<8%N}fwT48bOX!0lu9&0BV2=8XlYK{3+y)d0m zmo)DY8Cg!F8&+nythGyEtQnJ~pcP*cE?7kA$tB%cn3g(<9wB|GYh>ydT zL)RyRqJzTs(<9-zwP8ywGE}B0#H(nP#I;zX+~}+==O~X66BfY$FBp3eD@M|<5jISu zhIFOg0*=F#hMmSvom8C+rCBncpO;S?dNb{PK@PvTz4{)@#h%_we5Z56* z$}*0a;(lQF^#HaBbl?zk zv`^U|bjyM|=ux_dhdAN#P_${)eiq8`fK|sN#RVYwMBkMTl>Oe8hRf1YL*=YQGE$%<;2pVesM+ECE__;V5^Y!&c zACg?ferWcDmbn9V0<9QZp(^)p1bHf%8&;^5lkgfQ_BJtR4djcv{1tACV*6e(u+&2; zw#T^T*Qmzk-?KyGgY1VDFghnAN*SZINHMcA$gcRm+F!Ud(wAuP$DaGb6PLcOy7k~3 zQy?nqpx5n*jfrkEfT#7z)m3@l{s|CSXV+V?$^rd%+7crg$62YMt71`gsuiE$+6!;) zhx$`EE#yU=INq&p#)<47pECfbqZ&FZ^~wz1p_QDc%s3JWm5a5yGY|xA^L1#FWNT*! zah&77(1dy%FPBgHtv1%L_l6lwM4MXc4rI}cxqjo@y(p&@Z5R$~pl!CC?TL?tR90ER z{lGl1VPqR(e8OxtV%yTGBr9(+s5kTQEa9+U>#mavU9BX%G9R& zx?AZJRPgn&v5>dX$HMyQs-5|4bRv5vLF8ek-l0EO0`ea z`FBGA0jD|sYfVLJA;W;ovHt0#39kb*K)x3L0j`-l-wO%|O7I`r;#Xg7Y!(E# zZ?q6i+j_af#rj=>3%(b=4a&TKc&PQbv9Vrl(}D0`ClGtz8t`9^i!RidM;|xt64N51 zmjkwg{1k`Km9t3Ky$D;+Y{1N(9Tx`;O3Tb7NKlK$I(wb-d)TrEYPxT`oe;k5dapDqNdYbYp+w$o0Q7= zXR$EsKIKSo^?e3$5)RBP_I$M|B<j5+g)bfGYT5D;> z9r2ms*A`>ij+<-Oxqxk;nsw!WdbJ&f+DIrHO>N0cqK1r)&tv@M&C5r&Cggsvn(`v5 z(Xw0f66v~9mKV&$^i9f`40!xF_+4BIaUfc#C@(qcrW-766QI>nKEGg)D3^^4bE~_y zIjf`GUV&tM)xJcdNN606{Ybs5`A{HI zWU??nt*ESwQOyvh+Qk99eLyd9=LT0YSbRUvHLY>Xrym~vJH~)gJDX_WPk8UbG+pRv zxZt8`k)BzK_&$djvm*ZgaIBMX_C< zQ{Bb%&K%~=>(y1tbJq$6dFlooqB3%`QY?ype_@GM4Uo{ie}H-f)2U$3!gtGI?ytxj zkH68l*G)#__sjX7qd>_SyHUfAfPm|T6T@&U>;0A5xM0FaE514Q{Hr|obL>qwcCURB z@4;gp9E=+J(R{T;{jy7PS?e`;+4EvV*`@d`bMjv*a=)H8r9uOCmy$VcXW=mU6y80w z7$fZD1^llsz!0vE*VRnZ#VD^cK>pB;Fs9ii=Y#2mg+Uku6Uz$Ld2#_uU)3ZABb^_a z=Y3O+*A%;TwS(las;%b+OROT&CU^7i8m29D(=9y+_~E1pVy5|W`W>`s)sW}={bN~4 z3N`&pJ5TlT=jvlu!i*Q%Qbra+D!bW8(zHvvC|tvaq}rQ$qw9|SwhVfoPpUew8*)hd zD~g73e#1!XQ*uH!B59Lbdjv;EaKITt#PREj`kQL1Vp@+2q$?286-?J+9)*kB40z%r z2{Oxe<;x3H6BM>O2=lW!LNuRUAbzB^M&*Ip-73w3nM#-%OH2;QSk#pAni7jHkg0H3oowQRC+!MObjsLWI2%<_ z?qzwY31V~+MvRc|mXb4Pv#3BNJPjJmVQ>(FltvPx+)YC&?j|PZ_iqO^oXt%#epyHU zmk0eZzZ1nYv6W1y;pVaQXM|i`>&qH<-h16orJKy)F#i}Gm2-A+k^6?Kiv^z~=+nl- z%X?t+5^d`4?CN?z^1M#s1T0F6>dA@4wu-4_kz^88|xh`OPw zV-6*AI~hPJ%ZMTHfYuQuV8iE;8r~Y6F{^|euv?}PYiyT>Xa+LtipN85W!+?N}%RJ6jDPb%-JHMv%RMnUF$@_YWF|HE|E2d_~9%!R`+8@Rk zzx7o1E8^=`_vvkyPXB^1)FmFFmK~0H4lYVix*Q|L zU!O=A_#iQ6?)-dwVd}eV2E&(0Z|Mzi!c{cu2ry(YoFoI0$a@ zY>ec;*1%vLKeYNRr|6$$;^Dk?_qpkjFV&r|f5gMrK~TP34LwJAf!o&Nds-a*-GENq z_Pr{?)v2_Bv~b&8fsLgC3ERYIiFoYK06(Rc4d#RWwlcNrPe`yO;lTPdgz)G6orb2} zG>@W%Jb;-W%$80iaagk3uJGZYAke;%HCSnJ`^%~21n!JlAGevxp~@I+Q}qq-TbNiI0X=<)Nra;1~2BOhVipN0LCE>>tnXl2S$?Lz{mEL# zz6a;6jpNJH%>f|mOtJJ4D$gAK0)g}$rYcb^0eZ{Kg3*s7?HJ5xZ`b2oc8X5(JRd;T zo12-*^|{aYndIJ0$?gezck$CyKaQD=L9^;JRjN~zS}8a;G7`h0otI!PsXCza|r$_;q@(7Xlf<64-TPjn)Y zlt8>Mv+p+rpEr^97N@4N^&U6gy~o4L*Z_>Juhk@BKyPwrX&Rf;+@UnUi2WW)loxz* zN(JhSEXlzSUkkIoa_T1w-uuh-fZ3<=JOW0f-obP;~)+^<|{z7l%`B>Iz z!vNtS)nSl^XX~eE0dodSO9Tmj1P zbM|(*sCc0Sti}3JmhLa+`uakmqM~oxc7BRtC<6QpxH@5bDBcpl>dj{lTif#MlT{|y z{3>6QtxZoz(A?epNG_8MdYU={h_vHNp$5I&dwm9t3g1xJ_X=8C$w2Z`O3#sw4iF6P zc!^cY$%M+QDiA2){gOz6631I*wlc6^P)f4eL_Ko3ucn&|gxBrd)VNPQbVfyhr{PQU zQ-6B8d4-bopfICUh^kNhyCzSK?iwrW65RY|C2l!?v52ynmZho@<8w2s8#LL)oUKVF z+Bu~d7TjXM97B{ z(Eu(MOWwb55nua=UYl0z7n9c=ms#S#^V3?;!AN!S*(ep`_WFsPHhi^-u2&vadna>P z)C;7rj&1`%W|sUD%|^( zk+qyK-W4WiqqMO88T6LfIogRc5SO+Buv>EfE~-MJEJv3?88+HM!OnwrmQgpL&@1Sd ziL9Xnmx6OvGaCPDOujn_e`Fe}1|$&V3-h-POFIU6GRqZxdz8_kLs?9G3{vj>3j;IDk8*!g1z6W+C~7_G=Ss!rSJ`zpR*Mn! z4wgl2%-M0CcRz-Y<{a2xCezg>2ulXbL+8Z3eiyIS1?e$aaU~%JoGrRJ4C(FDne(P? z((NIOZ;%^dQrh<~HUXt;jNI(i4B7oJcs9SW2s>0{R z+j^x%lh^fFrBWj%(Hw9(gdQKK*)@+Oa{}7mu@cr#OxTF7;Tiz0S}!N1-?kkC?$zU| zt}BH=D!kgdI*YsW?Y}Atun-D9gE|u8Jh$yzFDFC`Lugwo*3C*AHiT(mK}l#Zvv^B7 zTJ<(FwR5_~TDGmK@_c6jh=_>fQUC*rM%3V3vhzP~*ugK+P7JJw7cnQR_kh;$wzZH9T3)dcnZjYuD+@Sf$&If8Y0#?+wUTPoc}1a zutKtzmzR4BmgO_mV*+%p#GS~%DPw@CQr`+*!>|ERTK{U-zPD3nL_Zb$v~XCJMYh@L?tGc;9W`N0fhk?eh0>LXX2rp3@FE zV-pob;0AyfA4s1IxHQGC3;C~XAteSXNJM37Q9vSc!uqH5gN!~cPI39oJ6XVDk#)Qm#e)CKD6ejOUT*#}uFK0Q z`C@?oMb%i&G3q#uaQu}#dY7NW*+$3jcGJhcpl0|bBsMkwQ|Au`sL}~>#qQjPy<9l7D>g$0VDezWchsn z+7*cEJSj!BpA#)dn@+9wO&HL0QudIb(Lt%28M?caYwQ1UKxyH#T6L8j9A?~6NXlEHPa1n z+ZPyY-p$XtOm~ZP@0nJALik9KAOAiiacG#rZArNV`bl}^g9QM!*6HW2d!GJFpQsNvj|5g2>vfu?lW}jC_7cqu_dv z&l7>x$!EyzR`-rACCH))S4S@nV#$sp|5hk=XZg&CN6V0eyF9HC^kXNY@*z|m{v;?u`RAw=2&3C9yezBFnMe@->M%^lL4{K)A< zxabS|3+AIImajz?XWzSG=(q<*IvwSG&D9FV zyx**9TgJk~Wsw&otvPEjTYVH^rYjF9sY>a{VQzCCFZnu?l}jsbgIm6J{+d4yggQcz zfdT?{?}x2=@1n$!#N(>8Y4mQ{)wtc>AaoT6Rqsj5$5E}tZP0l?^~X}hT@|xtlm;{D zmt+duF$>c!6Wh={gw6LGOiTL+?#Bn&>fJa0T2-G~-MC?P*UHz**#Bo|QyKL%ad-d& zPBG#8cmE$v-yKi&|Gs~WY_dak3Q<`hgzzRSdt~pZ>>1fJGa(cSA!L)iGqPvO9@&m9 zEBx+PpYQKH`l~wUyv}pn_jO;_bw8gGB_|$NQ|JaZ{z(?(;;l%yMVTn|8%K_HOw5k> zS;--x7G5Qi5($E(3i(=jM*g5D08!n(^x$KbV&YS9`P0iFVMDSN zTtphq?zU4kS{LVA7lmG%)p8K6M@lWb_s7Q?w0)04eLurHyZFQ^9N}XdPp7tArd-EX z(?b~nDET3k**{BLvt;U^NOkKz3@>MANKt6TQfi`4Z;^ARW8p%P!HxU@grECZSj(CSEz#F@>M z$3j%=IU3%QjMP%im#$a?w#w}SH~%o8*=ycQ{Aq({hcm_}r?7DmZt`TJ@l3yd>28r4 z*hlD)ZywO~z@dKkV_@Jl@P6lt635?FLV|VPj7&`x^m}hQp8yM%lb)Wgxwtt|se=5g zEd1*}xb@egdSS6$8y#$r5~0E3rspLZ?5 z{C(skGfB6BNWFI0cu|kwd)|wBphO_#C^49TH(qDV*!QgJ;(Vj5ANh?+T2?e6<2A1N zg0|xVo6iaxPM)GCtK+Z`AHx4eOfN7naJ8(X|V2J%aVO;RsRoGOKX z<{2@^y{An2-fO{mnv!@@_#I2$RMI0jTNc?XCf6FQ@*=yGnmcKDjIQEm{(A9FIpaDf zaV2KNrvIQVD@j^UXt3_%am~fGTyFHO$ZouzMd~i9Z~3ix3*bu%z;ymDRb3);r8nZA zu+{y=%JWHEbpVgKPr%Omhaq3*?mizs2)xRwW;pY3;)&RKBL^yfMJQVnL(@h$rnP+6 zGtWg-<96%3mRY&C06Vf<{q$abw7ttsm=y5pe&c7FUg7d5)l?IF=MyqHZ->yYXb)R& zp77?-2ypojvcM3(O~!|1((dwzSkjvrJbfSfdnmCf-2LCarG7mAL`ie!-`qx^Cq3-@=ltzt$u*{7%%pF#6sSO~Ko(xNzX)pj6aFdb%K6GVeAotpL!OhO`UCJ%bMQ^UcLis|a&0`|*5ETLX#A_82%Zmalj%*W?_uAx2;^`(kd*v~XLUewpu z-#@%5iu_xXbx$ekBf(~&9Fw=^ora_Npd$S`4_*XZhC9}Z@T?bJ&v_yGk&L$+)9>a6 z(6}*TyJ4PQULD@O(1Ke2@_2Wov6>v@_;N|}GMi}T z0^`EyVTy-FOrucDpXN#V@_`XZjV2l0m)+s?73Z4Gn)UsOnRB<6F-9PE^h(SwCE%cv z^xm5C86|5)okT!0HLbX`&d4Pm?TP*HqH?s@c>8Zh4=P->w{{W+j@uULnEb)HCokHJ z-v4&`-Xg$DGvI)HL7n1dcZ5uZ&;ANQb`4+0Sbpg0%#kcijD{o1FE@d=JQrPFNfK}^ zj@o<9W*kda$VrD%FuD8pn`*J++Pp%HxLF&QFfDJIB?1d4=SxfKq(Fz(yt{NGcrXoC zgcZa+p0$j&(Xp`{q}a*JFC0p2*w2!0%|{kN(Tm<^9_LiR8Z56+_ZR1<4tTvVlXzLi zonLe_Fd#f2=i+&9fhJ9ky-Y73!N-h7XO%L~JbIVwme@N494cf+*Uz|kVx*U!55~R! z1eG%1GQNkk9k%XgFH@R4U2dc-z|wH1-6(8sMjEhm`Xw&v7(G{541LcIPRN(c-?v1N#BQjkz1#U|zWmAp)nebQ%ex6&UNtYB>U;~EL;0W2 zv`G|ib=!tf7tEG^@owwJ&|}8r77)VZ9x)6XfFFwNDcI11OTF(a%sWV+Z~%o({Xr5R zJXKMV3Zx{@?PlDA*}%(rNI8K9Ui+VJa<}M36jI?mL^X}5^d&cAjvijAVHn`SD^|S% zoMfS4E#&dbtBn_@jjo4N?)kN~`Uq|SP{UsDO_;<94Qu(x2klPaVxWct9}DoH&w}l6 zM{qH@dp7R18A91P?0qY1j_F zvjV8(qZH4x6t{635fE5ie>{G&y4`wNN0G4gpFvycij_%{_MQ6uH-$B8Hw}G`7d3I# zrsqPL3Nxcc6cDi%36=HpR7JCIAE25dR}hX21BGlw9@~(R5SQgt_qCJtB9(eH@+QD! z+wZ5@5ZMg2X#b}J*I9pDLCZ5JOVQKy`iC>V7ePg$kYOrZR)^Hz!-1ls0hb8NT~^f@ zJZAm%>OCur&UX{nfx=aXU%J$vc88xaMa2kMY64IC=qt+0KdW+(8epKTMpj03QW8<9-cWb|Gf+$q zr@e|ml6fa@?6s8qWG!{;Wlo>)0+Fk$D+J)1JWHFNbHP_`Y>wQz1(a$oP_m=(uD}T% zz<4MhMdm?-M^Z?>c7Zw^I!#Q7;+ZJK8`)s_(b6v=%@64V(xXiY0P-oHQ*_*Udvj$y z+VT(&jY2SlpZjFd0A)7-3 zb1Z)F!fN<-IgB~?-_MzW``9QN>_9m=`Nl4uK32c!`XwAVj5$_z$;EH?l7(vjn_2cz z@{3AJdXhSTRrc{>h2KSU7MaD(Jgjdu}Vbd)rw@+Dq;BDUBA^1ai zb?oVZ93@e_8%9!Iq4@{#{ferr_ngH%=k|(Ix`ww2m2PnM)D-_%=m-nC?f!u{atV2C zAz@+R)xeI+_kNRtdBCj&*B)SkK*WcO^(HmvMfDMjw`l4XCyaN$CStqh5-jmbL?rg; ziLpm3kK@t#P8$3%I;vXbQv#N3`8k-0V(}KM)B##98gbqC<7;1aOl3Tdr8eoJg7rOF z?c6f<1*l=LC!_-vi~6KSG4lHu{dSqU#k2PAXkEF4QYWvWckbHee1fHgS6FR__YW?+ zzul#x{-1d8y{~KE%CITHA=Bua8l9Pun0p440$3arEP-Flt~|UDci3mE8=SUi<4)No zIG9mV{*~xxx%JKb4>5Go&|pw!`^*YyczK-yt-rN3Hap9l05kJ$Tz5{(JO@jXqFgPr z8mmGQ21JL0vfO$w1K+sJenuSXfi$oxqm=V=Tevuf7b=%7DEb?vyekKHx*VTUbVkAK z6joHY4lV1W$14;eTxKG_4R8Yo#5AW{u*$0(=7Ne|?6h5}aNjbz3AOar@R+Xb$)gHcKvG z0$I$XJnGVw&8y~kqPVS$`t zLuO*Cr$lWcKlI_gmwtore)nabTd-y-oEE$AjfX+AIY0Ng`HUR!zsSLe zMs65=wD^g2fkE|~2|P%JW*0NAynzhgKNAW_i!v>Hp_0MUKAfS-Vcix^MbTij+?Tqx zwUt;)!L9TWU~ZA`*?I+dacn26VhQAt95Tk4lac}K-c76~hY!vHvF^ZRXsnmM)}u7I zj+;KOqEU{SJC0u*b2KeB^C$BUr)_55=x_1D2nz`%int{A$+et5BzEYGAJU5c=82rt`u zb-KyE7MtgfjPH%gw7e9*d;R4T7l++)<@o($vTJ#^p0-^NTk_@Ctj{lMqi}+W(8D*+ zMW4LCoA~%M8L`{E@=YUZHZRlk$ujr$CaLNwVp`=7T&kCn-iG`b$^gPw<>(!dw;!l< zwe-rZWBVj7ULrdo?c(q9i)pQd+YLu%^>DnwDA1$1L?3A%Clr;?$DMl$d%qxd#?iFB zxX=?c73Gm<{6@(0MoW|PEq#JeiBg23!A{<-d|Rw;1B23cY$T;syVB^;mxf0$+6NWeJ0;g3l4&v?#HD!xH-wN|v4Qd)iLo zB4-YDo$Q1&;avRM+5V7P-005bS6bh+R$KDb_xQd~l?gfT(P6)*it2WHYf3RTQFn2M z8AY@@{^CC`rwB}TeibSs;yWFbNgXV@Cm45+t2akye2y;4+_&azHQgDv8|AKamtHqE z(|<*Q+tEjbOCQEtO@=35ZGok%L2#>lk}ymEEBa5C{py5wO>O;#n_{BTSMI5yQclWo z;({T;!*Ug!JM$)bZ!p5OeL?1|5ZC$C@i(MR>A z@bfR{@IPtqzIK8ofu$RdrfJHMH?7c{bE}0vRC0uuFfn9U$#l72Hb~A>g{rFj1uR~&HBIf!WV58so&${uzN zlcq_XO5ouQVmXhL-bJUm0K(f%0B#quS65a{9%Sh$mR@@6pF?7#-*islCM660p$h0n;yNQ%~N zl29x-(Q?~EtXQw$d7MoAOD6wPg_*d8m zBKAU^cM7&yiQSZlxZ3Nm{kZGiLECp2y4sjAWX!r`EFX7;h4mSIvGeBi3q#=q*NE}# z|B{|y(X{Va+2kg(9Ois5d{RUFZoVWG&jiJ_+UMfz%>UJXCi=eDpV>RU#}Q^HAmz}8 zk}#N|o<%}GlyoQwXZ8!ACU-!WiMlD8KS~hO5eQc^kNo&y24OM@t|?AqO=L~%4hG~q zTfO`Na*On&3uqT4B#dHV5w~kNY$rT-f6LeX-R;ItE3SekS4!p!7EKI8UL38wm>(q- zUI8Yo1BvSh*u~I#ufrP~s#t#g%ZfJ{QVXi9X?uHn9cMsCku@}Au&Y1NHgNl8=}>LJ zUC#EHn;Kbp06oJozQ9Ij@;%>6D{+{U5>D-tpXu}W$AF|_0yRqbDqyM@;CK06%ge~b zn|howlaWPDdZ1<39&s`hOo!8A z8ERPqI4Ra)SXt=0QY8q9<&~8xYhNz~K6w7C^uHZJb(l>cXVNn=0#vBkSXsN6iHyj| zV#(nn2dAc@o}_ud^(Uk7I2hI00ZKiys3;~lmaTRw8j^zf*~vlps*&%RtAL;&lm!k$ zU(vJ8fj@zGHG3BxPB1b$nqF0vBpUa>iB{zCyBiI+BG;X)<#Xf30S(`@v(WLFRGwVw zV_h9RQVpaK=EG#$*X`h7`Zs-gt^?ux9Q>&BP5xNnVANQ107BbAj+~6lk~F%3l{G_# zrire@_~K+te!V=-4S<;Ni(NKC)=PGkSFad(umEXAH4OD5{^{YCoG|@|0W^MS>(54C z3Ac@(7>zSURa0X|Ubooo*;!fR<_or9x}NSF?=4u{+Wu#6Z$Ei>pYif$?UuMwsz^fc zU3@q6c<{{MB_T(wtKQz;D{E^~Y~=oJElJP$xTy)BK7FdHqZ67c>fWwAHZl^FcDC_E z*l`{k=qkdT;oS8)4Rr;W&xOv|YaUP=6+`{swvT-K+WLAm)~m42Pi!>bM6SvilaZwS0EV=+O8 za@orZjBmw&3YF5t8IF&SYwYECXk_H%aKQ~mIl+K30R1qD&yv8Mk&O2%&)_1n`FUU1 z9ZJQ|JyLnbX;j>Wf46u&{%aTac^HM(PPk(p{i8v1pMD>$M7Oo%5Trd*ZJQ zmtFZoAPYK;Qok0|^ya!^vB%DQ&}DAxr%x45rHOwO=!e4cD4QZ1#Ac-7&+WeZ=kk5N z_n!{hdu6OURjp@uFeC}0jFnb2g{5*1DweKAsXhp!jHVsD82e$=S5E1Aj7LUnhL1%r z5!Mrh!JWaat*#ybET{>TzT3xTQPW{0;_AJc?UsFy_ zCDK!iGsDrFv!8K}RsBMoFGG4p?S{Lp{e`-(l>la}#XBY8p3d*NSL05D%OhXX>Eo(z zJhbYZ#pPY=UQx}K(noP$croq#Rua+K9YlMtkjp%M%J1~4;M25GA9fKc?4c5~*l5&i zNg0a)`S6DfIK^S5$0(DsIRG4Ou49Iwp-etMizi+nDHSHhK_qq3W_3;Ik!G<;=~v5* zklf8OdGCfq6sg*vZzS4T&xPZ%X*qM-r~Tb9)#iq{Xr&iWX}e`bNKeojHj9DGxOv^EJ|&DO2hUgC@3)n zuU^*C``qBolNoSD!~p%DXrWZAt&n=CZ7j{nU0uZ|f)fEcxzt{Q?j)a@=ZQond9RgI zcQ~-CD{gamUVSrAWB*MCz43kFZwJYTIBThxy}{-;C#g3o`b2XodSCJTd*BptM3l%q zlqsG-SAn`V=Tz+gj2Y1LA0*Aq&BwpyWMp7gPC5}HE@+5rj`MDOLs>fmxA4_lPdr^| z4muS&dcS`%?BVkhcg|U_xbw*|Tv}f|pqJQhkLkrav$9kz74PNCTEk(Pm8@nS`)}L* z$0YaDHCPX}cy}iry9m&z{V_vDgoTjc2wsIVJjHsFc(EWNwg6XH0-jFDG4c~QfMURV z4?E$xq_Q%xf}$e8x@zanrux&3DQwmZP1wBIqQ+~abwdlLt72#h;={*}v1KSNOLSFX z2SNQLiRTXjC1 zoA~>yIGko6=AuKEb1^8{>MTiOX1LzP9%;Z$6d!}Q`WY0&7p?dvcE z*Kpu%)&Ljb4S*CkpoZe@1=8fMcROT%su>A~SrpK3%-5Odlw@QqZXl_6P{tG%hU`7p zHA*P^Xxjt;c@OW??k)H0yqsA-nEzQ~ju+ZG$wC+8+dYBHPq$DjbAyfVWC9jLh?txL z!`@JN!$4BhtWVaL4rCzj@hZFmu*Z=Nw^XU#ztGZjb-fGOYrbIy(iXr~$WqQZq?S)4 zk~j!GN0Wn_x%f8jsjnm@W*=m=KR@cGijDeDQbr9@pa;Y_s$oqnt+^9(V=-qwYQDv| z(@WF96=?;xx3^c>ynFYK6c2mWsk+Ksz%`y`ao{XKmjIorn%=rOx0zb?D2(QbvE`mA z8@l6K!g~8xeol;Zrzc%WaOcM#1&;LFX|ZNJMp-UCwSgU1_*NW^Nzy7SQi?3s(00Pr zq-NF%L>PE@52(s*b?A>D+C8bFSG4mJMA`qFn^_{p73JgDHVGn=BY%Ra=K1n+F3UB}gZGKo^b1{Y zac*+mDxn)a=$1T{E{YAH+v3Qw^ODym zoz2P`kJ9T4hPP$juWfr|@!z^tfwj@;r%2|tnP^TD{hdA_MAn2j>YKXz)!Bg(b8By# z*MC&vZxfm1uF{0G;sr}l2sW3GJ`Elic<@FYkROkES8Zb>Q@Uyxm3_d$!9jXO1r?L` zzS^V!W6Trl&Ag?b(5>|}NLEXW3h)k9n#a+f343!;JmC}T10trMzKJF&N&2`Izxhni z^tBjU`AipwxlaF^2-Aq9qZ1Y_%H_{SZv}qbCL3>vdFx>>(9Z8PmNG7NFMsBymThFv zxcR_K35w4r|de5N0PKu7rF)95=X0Cc(sw7BqkpX}ow|INr?MXqsQ zTwLUIoy5h#nLY3v92yD$mJDtye+pF53K|_{{K{4kuC}r!I3XJt9Sw$wY%BdB>VCV> zuG(k+ug*<5lUq|4ygg~Yfo7=nQ61wp5WTL)C%|D|xdd;*1}h~kdk*KX2s_8#F1L^F z$@pG=>&aRTo-AEpC#cn)q2HC3wreD@L1&Cwgc<)&=gmAK(u(S6&`U>@zSR8dT z5v8$)K5|w!r~?W&MF6nn+J3IT+)MV^7LGibpy8cBpO$9njpBTHFt1 zRXeohY$x}>#DTek42VC5A1noN1s5C{@^#xSgxkk2e`&x^qok&8F`J9G(}N-+v!ddz zU46_CJQq*%a~ospjYfY;E_Ftsr4GELmcL|6EPrxdLjxlKT4^IAMy^5} ze@PTB3B9UPna7UVm%r;XE9dZN{n{@ZtE(S7n!SKDGnBS)ZinQLPF1K6LVK-RfgN;! zpa02Q9}d(f-;#;Ap8KMdPZ{EQ!*Q=Y!lHgDr+dihc(QMU)Ox&AK+fJ{Nt1Z?gS+i8 zhCwuBp(ExR`74JfWMpK@m@qV9ongYb+VpL0ZB<}y92_1FgwsEXjEdZcDx1-6nNUoc zl6C_D19fgs-kFBJegxw7Z_U%npLGz{HN8tiPcH*SGjKCGNt;kD;@&V}9zjfxM?U-C z-$7Nac=O|Xbc@RGGSaZHhgAQ*v6H4LTpG_G(EPmp#UFcKF!qR@Zj}A3c$PR%F~0wM z$HM_ss|CP^fum2gl%7@Sm4NqQ5@Z*T{Xsc?&qhs6O%s^$D$v3mpi0gB_|Y#xE7RZK zKgih_R={ppW0TjEmJbqaKjcEC;W}%^^ zwe5;=BxFdF{tx#(fYPUuv#6fhOz&$TxOC}K60qiQ(q=eUQ5`vi0{pZFYT~cp{`dZz zo7)V0=#%pDa%LJLx`xOY#`}3RlrFVXx>XJ=R(&b2;Evz_V=9tF-R-oe1@Dpl^^y3q zIhCJe1tu-slSHl?zxON$m33>s;=UJb^R1afs35TX7B07-(j zbb`-+`T<01?WY}?nTcWl;DL$QxaPByfy+5xG(NwyoZ?I}X(t4KQXa8$WkuH+-63HT z|DucJD_-3{FLWn-vQC#H`q)dXdVK*-A_Nj#!()oTrEw})PEku$GyPJ`tgITQD6U_R zzLIwK_siMXaPICUEGKbtaY+MyeJ=PuyI(P(&Fld}g@uPJsbzzC%LDp<0MQ8wW&o7Z z($dQ73L@VML;|Tk9w8wiFDzc&3C5&iv@ZCP=TCv~1FotCYEYUc&Hte?GMqvVLNBLD zk_@8ebRr5@4|1vDH+}sdzO-4Dr56{IGRDa5oF1L|;1u0>=<6#1LGXSXy@L`^RtKK^5QxhAhNRM($= zWB9Vd2mXU|%5X`kcD*k;$S(ABMTk7QMdW{&PWOsOluSH>ZH%q%3}&qCPm+79qCa+s zFFK{-Q$wSa@Qvg@P=__?<8k&Ptf093HVC?A50qa6BKtSD%9fT{yJ1hr%0BbfZEpN3 zo7?f2-8*hq{sDm!nh8k(6)uF;S#&4xd0i+FpFVD1V)=P{e`5hJb(g%enECC9X~%bg z#GD`Kuv|YgGxx%U3*v2I`Ns;;Hishg5-#_`tR;L>eqn}`a(Drrwb9bm4FgQxCeRVX z6dM2LK?FXy)z5=eMhqHW-WxbrKUy~9odjEX)4RvK6o9lMt~Q1D1%mFP&=+_&dONPL z42z7lJAfkYR_cHGa*6;weTVl0Qp>~Y$I&Mm1XwABu6o8&z-)Qg%KeJK;8w^F2*4DkCutLqi>5bypzH_w z2fdgFk6jZU4FL~yIbqs&)IKCV!7fI9xmSUakf37%HG^ZEpn$+^`&D}jSc}p3itIn? zay-S7WR)fmzG~l5p_kAtE#-xJ%BIRPI(jQNeVO9wc4?DtvwUywe+xdbA}`A|Pc8do zt_8=B6UclxbMG7Td|}N_w?%oM+~aND#KeGM*qX00>9u2PeI|9uhv_0r8A{D4>a2wB zMJYSGLbG?Uc!`LJ*oa)zo<8~@_6k|c0*MAr_|$d!OcxJ%$?JxW_TJK*sK5-Hl|olr z^YWf)S3KvWzxiVi-ngMGTLF(Ok!_J1Ol9AH)L#DLn0+4KDlsf)oZe8Dc@Hn!wd(Z% zXYJ4PcW=q$$gCR|wPH>RpP>}9a|YX<%k}A;cnGu89adfIxNn&M)ZUZ6c3;o;_up^p z_q*(nh5QTc2Ka+Bdv$$XnwiuDr6?Es5E~|44x9jHH4%3jXr%rYNwLeP9A`1n$(7-m zKw1gkGpVSkNC#UvsX zcCx=3ZUeS2U?F>3hSXrEMngpPIQ=+*ZU>Ygr!pk&*77H|@xQ+=uihpxc7YR%GEHIi z@N@^fwWcN}exk7g22)Sr)yybeA1)wuzzYa>*x%QK{3g&L!>f_+Z%`66Zyic2obP`O1q~w*_wvnb$J(hR311(* zuUpVf51H-NsSg-6Kv*Ti!>;0g6~@6u{Fgg17;5y#p|C4Of&2%KxoRs^iUrEr=&C_^ zm@cGGEolj%#nvd8R3-#JK%wtAvv+!iWZ;2czrLpe4-c>S>(99{6@(JI6C4=7NHY7W za$tuB?ulEwu8nZk{TY82ZbQwji<+${w_SkVgqE!Y44dYGo2c%?bKTP^#hHl@va~aaNjspt z&dZaJ9ShAV_ne1nqFyb{j8{9eL#At)bI{&W?DPFkCb`o`MS{>D2Cc6JHnbr?HMl8i zp<(OrbP%2&^_B$IX9+k6+63Tkdz;H91?$J$z}Vy@WtWtYd3*m|Ob+9q;0;Tl?+gA< zM&?%#GFCam_>~g{N!hTpnh6*XAf1)A+5Z_!U)MJ2`#;|u6BpqqePmkHGuB+u{(Z3BZypx%Eky}Q8N0Zv5t z2ln;vn-}7^C^nnh;%Pc6F^6+hbd)IYumL);WCfAt;wk_O4P3=GFyv;3n^VG0zwsWW z2>XK?-iFeC^oZmp7gx#C(VH*-E-;05EU5k3;lBI-y#NQtvZN%TgX81j@bqmiWmdiF zWmjBhroma8{`IT&&fAWV5FBpsrgCBFrd)(S?57yqekMSDr^14*!Zvh-oomQ_jD~^T zg`G9yIgmqH7w^>ZJj58=1OP>Y*PIi#_*4AK#>O}BdLqkZwxDvl1r#3jnuF(1r+J_& z#*pGnbgPa6fK@j4vMNUq7B0!`w^tO7!|*w9SUjGvmAu%sD8ykcjE93XO z?lG5@^zusmxf&GHn}JU#AtN#poz`kfg)@=^Ka^C7W@UMhs7Lw#aSPUbSL`tY2A zq?D`*e%;?pZdg;aA0;?dH8npaW#{JN1M$cA{n3AHN-XE87z)}<;L*OSO zKo_P777MV7Z354Je8G6$`+c*Dzlb{hEK;OzEg>NRBwMIb9oK_FG!!=0mQ^SCt&qHm zOYHqag_DWb)4Lbr%g?5waa6HUW|LW<2d$4~3Wpz6EQ)n);x)aIM21{^Kx=WvhWnxU ztd2-ji^B4W=krFpy$UkRlj{LWF3HK`ESlEB;@xw^aeC2Pkp^TKL?*E;j|4F7D)o6) zF^HyQ!DEG2JN1F5AD&Ze=NknWqsD)8IWf#QaP!tJt(1@TNSXX?N;-8-Q>1}{rU|T8EFh#)9scQuRyy_+iCfn! z*U^DeTV!%li-Iev%Lmq?*CxpKQit>ktv*XTM%zna4h5t)#kC**mFc;_OCaOUwVL{Q zuHSQ#ET9$saA8>?@a4ta10RJ6%JVF&ueG$_GBz4Cg`H7iUgO;sm+z`aGYlq-H_vXo z)GWM=&vNM#&AY@1j`xs6+dqd1>bK;~q>6jfrK@t78iihFYFF{ujl=)dx3skMX=%t4 zbaMde4z0vOv!&g)TZ69{g+Z0cM%1AEX?NG@i%~tDefDQT@xU(1v984s1|$kXN9p)){Y%gTL+fJ$FWmXlP(M z!u>mU*|(|0yn{zrIO#3gQJ7x0*6kLee10*gCI>bQVL;Sh?!BM+RzG_2^ykS=%*9cR zZne{OzjTucSg+fV(C3HK&IJr^U%5)EeEU0b26nB~I=c4FX+rtkW3VT1v$Gm`ky;u} z`u!&Ee`qek0J_SCHcCrRFTDTd62I=(=d{uE_W~ZW1;F4UWZlnm ziq;=7wNJd6xXu?W>F;||O5w#PCT7;u&;~DUKgyY@CtYm_PVwrSc!;}=yu~@rz(Tncr468O-O-WpkKMh*c84C)WUJU zZ#3feuR?#FDE2u!37UDq3WYjS_JjO@Lg{i-!yg*&oBIg=1-2#nieAXE0^E5hq1`F$jt9C-$Mm#m`n%7S{5MWQ~lbA5ZYmK8S^iVGgWK zGCVZjz(t)~t|WCk$gkI`aH;yWKbcprfP4NRsP`{jlK(ROuhhXRDM;JF0Y}!zWyYN+OI0J%*>{m zxB$kU>GWp@5173vuUu(`kmKM$3IhanU^5s8!8gw|3oZc&vG{v?p7lSg9IsjRB>6up ztj4)_@7@<880GH<-*&a7z%{TTa#)7fi5El)>1?75IivT#r^B$;c%8 z!8{V>48QvO_hp*^`=b;|;gp8uMYt%D6^7rf*8BHN21Ulib3qV0q4xUcXIe}&jt0Jw z5lVT7mO)*h_2_TcZA$^Uwc;6JKE#G<7I`QmbEEe4A_q5X7ad&0Gp~A?FES;C9yr;X zeVkN8I8^L5Lg7#!a~sxB8lSD{?0}U<2pBUr=mx2@b$?RF!77$ul?&k5C z&oFjz1`tcoJ}d&9$zNz=4C-Hwc>f2E5ov~VGSu|-MQtV$?_gV;-^Cw(^&!#x(e!-J z=UXg&*u_DpH%XaFB1PI21sR7_E^cmXyY<1O;M9T-@BIGV--I-pW3QHfXZ-kc>su7F zD^1c(^{tJtSmI0AqFfYGz0pziy+(8<6InHDmrz(2i+*Q>DTEPxClAwRFAl8z;#?ll z)Sf@27Q3g4h_OVic9pG*PMqSe`j_`uNb!<3Yn7AvF2T8Ha^~jOkRw~FRv{=s<4C$Z zu?dFpqnin%CscqR5oeUzL%4sPsq_ve@#WRs zf&%UJ&bT`{;3$HuU;-5{6rRPuJgnKedS?Gi@n4q0jP2YmQEL6Crb5*he3OY==8n?b%<0k`HjV?`n_*0zbF?+i`JDT6< zb^kkgx6$b+{rM;9y}zeCzgIM*1J>;_BJa<@PT&Cg_;p%Z5lz$6=g$Q!QHpr}z_&mD zS&U)dcqT}9_3A?QRJjcW^juo}+$#Ma`x;ZyuyR$JeNYYK%g))?V;`~IPH&G>bS3d| zD&%m)3Ui5&dKS9g+M(+W=H6a4$V%!;EM%(5QM`pv|rSl?bBSD>GF0 zilF^;B$T?zGv4G^{!BS7QMU*;K5ra6)%bhb=sP+v^K1Q}1>_O%vbEN|*aLHm*(9WJ z-HNAFPMTd)Pi!U=Em@)xZwZ{kXRCa z5$j6QnR9Tcojlruc=!fnCkS|4*{e{`%+7w~Y&14CWfA{V5_A1PQ|g)*3^}5?&&BGz zO@EY5NAW5H#We!4VYEba`JsHZo<+4q2rQ^0QoT3;Da3E7o7_ z_$ocTp&U};UC936I1est{460qcKKj}{5_SLApO!P<2f0Beg4u?5iir-99~wiyWHSx zic3s{8aFeuwH)Kp``!=$Vo1);o>qZ~j7Fo)MQoqk8FIuIKbplF_UT9ZijLqUAwT4B zJs=~Vf0Ut}TBkh?4QKQVi{kk_iD#HW7^(Vgs?qGt*l7KeLeq=zLElhcv`PKPFV?4e z?;}h}OvMT*5Xhyjs`{G8Z*lKfNfb^Wht8uAIJc)`|Fmn->ALu@5H~Y8Ycc!$1A;c; zxScQvd*(m|Ma73H4efoO{t%5WYwjsD*!V_HruG)u<86yh&8sdqv+ucWB;{i10@%^W zR^mPIfrczO7({g&oiDl=F&*Y>Tc=1RDRHqUF*rF%#CdNSMRuLJnoPj|RI9`A>N%C1 zDF_KKklZ-$R81b;1aKg`A+_7A36*Fh_9k232?XwEWGpuEm2Yhz77POxJ3T zq05dMItn`n3gSTYw@$uKplD2F1|MhBw*^Z;Gr0U0`LvTD4-X1Ns?yTZ$XlV{)-VOk z4dEh$cE=p>6qFM4^JbHtZQQyl)40jsxMPEReFFjI#UO?+C?SdXLmvYvgOupdaK~QX z2dy;Ggtx0uaP|il1c09=AYH-h2A5G2EAurnsac@IK{yDR*=Ae{<&I6l9b2f7M zsx#>BXa=*S7C@=1H~hd}0`kx7cq6@V@_5blTRQWFg#JwdLIX21_F-F;uVkS2Efn!r zg8bAB2Wa6GjpbKG0|tdN&4R#`VglmF^I{np*@n)u=cIG&yI={#yXeB0SU!DB3Inp? zEE?e#X|*9gz^I)&9bn9g$bXF8Kkk0Cv!irKN8Wycg+{-px!6j=T0*dR+_QS9Zi3>+Adn zVlohsTL2HwH*C3xsOjo<&UUhqN;Sb;e*B2iF?w;m0WjVIa!8p$4pgtT?pxYKQs7EV zCSGoV%$jKq3o8du%+8r4Gb*kBN!OMj7)!uOYYLK*<1h%sO$$40DLo(dEz5o(vGR`h zs^aIuLT#m5+X=xGVaI@ASs9Cv1yObv6*?gPWGpP8*qo!Jq-2Qy$&oc07Z(>; zQzOzQ0CWlH)^|q_->A=njMWB|3Ds~yVj?>|h73i=stY2f0s*L|gm_0d>37Qh?nQOD zX+ZbYDE6jVbPMY{j)4CpKLK}YA?#Mm0EKwC4W_@}DyA-z&k+mKD+S}tk&U#|Le0rza<#Z7zW2`4>4PS-V0W5s1pu8W&VWyiy92xJ_!anO}m}Y5hg}Sxe3q zczaoB1p13|p^XEvsBiCf-(gomTA+pLan27k@Fejbn$jL$ZFw_k7IN-S+S%PLEieDd ztOhtM&^L>l$&+tml9q+>7S+gJ8u@+Q^{=(8aQl!Tf#T!KXaw3L~paBQ5ICXP5 z`IOa<*7vd%7 z>{)izrp#&IQGD^wo&D2CGFJCvAcu!F2LgC&Lp%$BfnTdfW0SGQK2*mDe#qwZqmz~e z`%^r=+=$FD8~?7X!Yk;#t^=3bzn~0ou5BMsEK>6k5D-M(FYS1G-+3)Ex}}s&sHKbh z+S@k;ir+_)tCunk%p-J0B7n5K0aE1KM725RMfZ9(Cz71VFDcDeh%PKvc|xAz{|!KMS|aSlBrKehx%L4I6}?d^5Zn zG=a8yp!x#=P&=(m=cLg2$KN|l_kW2JEQS^j1>X~c>SF#tRU0f9K7p{*5`l8(VY9~o zcfrv*ade9U9Rdy1Y7q2N_t63sQ98nOzK#2L>*D;*qcri}7G~CWk_=7eY-CtnT?P`~R35s4(WCt=X@)y;T6zc6fQoTJ(h5 zl!4z~mp2MT4Fsr|_odt;l`0jn!|C00$_;a1sRK) z6?}%q?gsy6hC7Tc$QSL0?(?C>24~3m@w@*dL%t*lUL_z*xWncx&IE5#Gd8{)5$xXj z#!;RVxXEH@>OkD(9=~JdioH+W+FX&&2?O^jSHy1sdKF>pzwA>g`UpW6rMlcuc>f<| zJAAOeFNxPoB2If@@~n&nN@O_nn-0deva|4#J#xL6p*UA)zaZiMQL(l`}}&0#~*- zB$0vX={~7ztgNX!<1n8+AY<`;0l^y}4Og}eC`-u7i1_zb*iGLM+h|f@W+oOiqHy!D zX2_epV<)F$J{Q;~6pww~=|Y^?`J1MRwbcpy7B_FID>-lc(Wm56~7h3BHcSPBj<{^Uur3(oJp)H!b3<%81wc5Zvw}FHnp&7I8_@I|C+yuo`r@Z zJZxQ6nHtyUG6C0<1qc+&b6DS;)$RNk`>DoiNOPjy68nHUH@b<==y4GSODm2~yP9tN ztL2E22+c~FtC0igb8>qWk@Ol!0UhbJV_gQuAue(M0#G~Qd;@N7zAROacphcYhX}*1 z)xEg&v}16J+HpRq>w+ii-NS`Th5MZmojjqAxmy_rU+dHw?LT*4^L$Er&A*(jfn6;G z`B?pXx2T~e%7mupYXvYEh!zJw0uXojwJ$&|h%sI!41ZV|9fdDz!W&{qlbt+pzdnk< zuc@iu=`p26bnDBT5hTZ^J?Vz%lUyH(jL0amV!X~Oc4mJlw%YCm_@%Q~kR`)(wE!9# z{PBZYNEvD_1ik>=8R@Hf^tc%Jfy}qE@b+QFjh^toj)7sYdYl%^byZbW{U#@m8rOj5 zXhWf5$&luqiOS1>(gJ6;V%{SvB-pyF{K=9FbEJ|3GK=4Ir~$qcnB&ESxc}8jj~k3K zp~I`1O774xMNOR?5>NjBffRD^2rn9(Eq$5}qcW>H>8Cba9*neD4x~Xhi8*0%O%TuwLK8j3CM{D!L3FKBQyBGZm>) zq5U9WR%QTLG5BL|PqD|B-r4(Aw@_bJB^ZXUh zJ->LRYv!7+b6w|rm-pv$ewLGm-AdL?!1T5JA|{fSdE&0(s?T4%=o41DX#&52OK~U5 zRuGDb2x`cShs5MBdQPDL8n#gR;9+>XPfmSN41@H^br`_-{7?K`H)_SHRKD;oJjiwj z444a%3HC@xHFy&aAD&rZ5MTXlRmP>_oXgJQtFsVhQ8eNm$V0?BE~6V)oQ+U1_z?GepE@rZ``Q9c=zfj&yqZVza4No zD8ig>aPVM#J9}_Y<7u`#T*^|x+FVwyDqe|g8nq&V;VD05kO}1!70IVlB5OY%KHMA# z`zk$oYSWNs*xAK4c&d=eeH``P;`Wa&QB6SaxD36%@VL0=T#D zLL1t~_qJb;qyhk)cO4fJ{&zhl2Hgrkin#_p z(KBE{PJtsk{m?76Xi!wN37js`T7h~U^86gJSGp3S>75&+kLH=#JbHiq#*O)zEe%!c z8oUiHXI1EDZoO|&3C&p*Zm+Mjb#>dLi)LDTgaj-5DUrG!yKFNC+C&8Re|YfD{b-IO zE5=?|Rm(MwqLt61w!~LF_}=8ZCQq&<&l0m(2qDTNJ{%|XACzOucD%rfLO4zKCqa*~ z_;G3e#=}NZx}HcoyCZ7<|ex&LDM&OIuy!^Zf!MXV+2uCI!E*Ff}-83 zhwd*bs*CYNlb6JN#7vjP1J6J2GbC|3R;R7<@^$mDYA0&rqv{9!uah)h!UHFiM4V|0 zo9PheCnY6Y=aw~`m0mQnwl9wt$E=?_rnlDyJZOkB+8=WOXyRi$;rO`VY7AFA?>xwV zf&YYjg-7z-?`iblGJiLMt4cWk?+4sXOVc8aHB2b@j;}-J8b=%0@pmjj0u06^#F-RX z3?!aa;S0=tfTX=BI21$7D@M8Rk4s1ymsN1F2OuQ7bTeY11_tD7$%&ZU{bm<0?FCT- z&W*0Ao=+ANN?0xb4n2MSr6|Zl(1JdWCqMtQhQ?#J%f2tqtHOtVDxxsYH&z_YuNv}1 zv6`g^SB7g!B1AI7w^d$gg@q!Ip}vXL$!mW%uWOnpwH>zowDWS1z&r z3d@qYYz6+&xzRy2h0&yMP^MznrE+EH^X6x2!WYz2Z1T;+6ToIx^X}pj*^!LWj_;KbC$*i}Z?DwZ_RSk{k+Obtku_m-ELel+&-8&!v8wWLIZI-d|@~Qf# zzI`59J;>a4L8jG&Zt+E|>$eyy+)O3(s+n$j%vBe+i!OoCO*3`Z$;jxtQoSg^Ow{Cs zTbl~^dpYo`wCjs~{bP}zkX`$Q%BQE0OcAuzJpA>xVsqLdW20<`JT{s1A;F3~WvLdn zte*IyjNLU^;&uTxO5eRgdZxymTUQur_In94b~z+ThpbC1Y*(?2-IiJox$<(@kA)%fy4j| zlFUAqXNJ}MN<;*eRa{xK4R|}$>h2yM$-*Q2Dk6xGk!?swNEobc1f`}7Z*H)!DCY{AW( z#lvxD`TQEw_lP+^GhOd)9<}+Vds?`H$$h7%W@>h(8-Lz9tve(*P+({5c6bZ(;qP+| zG?7On0asSOU>j?cx-VIvBEm2cViKA1DSFqrpL&z$%5Kir#&fpK@#V8+2P`fS4jY1f zZQmTEMvc#<(p?C!6^Fn@cA4Tj*dpUO$4&&gqdIBq!%vlJz~?qrU;-4 zg%i>pAS(pymJ*CVN{pARg~kBR05#-ji0-MlI;5CLj1C}psuon~?Fb#2WHk`pGeg}oF2*Ap2VhKCgT^lJqDwWF<+$Up zA;M(ZN0YZ0&r!ImVSWrNIU&MZ0bkQ=sQw-4@ST7?|2?pg`g!YUiClIi`C*roZt8g- z)J_7VStpxVn6p0CF(Wf`Q~DG{gH7PHQEKZfXvU}^{Mdh6^B7v#XUD%?csJNG=C%}G z31DMbuUw!$2YY)WVQ}KF>&FT<5Q5^j7}Vg8P^|^6vj6e>+$0%r*MRGWI_Kb}M(*Q| zscu{dXi!4`b^&xd1#wwXLMglnAU>4uJG2uSu9GcnI2I9@Q3D0w6hkl*uU{L^6%4hn zC9V(_HkRu-OM|M9OZ?(e_JBXuy<_7W{c>(nr>Cc5<6q0i8~@yWx;N<4U)&LEc9es$ zP!hR2c@U$5yw3Hx`2J#!c^7Vqk3vhYb7^S%Tp`CW0881ePoF*o@)sB8=dZsNRozno zFbznIdpiT<&rY|0Djb-KrMFqOm0)^3Wa7}x(Hzx20}K~=hALz;ISGfXtk9UQN_wOJ zi!;@mO+xZW)klGV16U1fs^*fX*HI39*JDT@oN;6cC3LM~ys;G)a&#$_q0%|gUPy`) zFpLOsMj?W9)d~3W#CP~I&#GLfW*UnU$vY2n%35sW;r_QHHg+YbQg)DmS+{Wx?T4K& z$ywAS6BLnc2^`!!aX_szNRXADhDx3rtL^DSQnI~??&Lqu~*W?g?Tb%itTr`+d zVqj$zKjMa~77G5A0~JOhn{)-lXOeITT^mAJ7j~W5^b$IzBK>Zroz0EUr5JQ!;MDk6RF85OUcY-1)X@0R9vBG!61N)cp>2?i4Z!Ai#ouMW~Z zk@x*0yZHIt$5&79{U?&;&HsL}C>6%R{l2usq+NX)ZM^L4jV33lo9k1UkLvP#lr7^8 zhqfQS{VFQ`q~>?8l-#nW-k{a%<;TApM>_Q_Gi>+dCAfrJo_V%}l$0?cZiOo7xzG-= zCeW2qIB}g^2h>zvx{&d-u-H9(7WJ->3;H(wUqkA3tMt_zc&K%g&GWGxYT)@gEna50 zRJHZ>?&d2a4_0$cICqE`FB((Pp@jFSFY@r%JI^qrXN=WU9&A5g|8218k65?ldn<*^ zZIXNnCfA*|(^AS(BD{VK2m_g&C|}q3mP0iEJWA$Db&rr&_bUuBZf&cMsRPK*fs4C#$1!{r1f?y6 zb_C^PJ%r>H0bdZ^JVVvU@C74w?NvD{vr&}l7{2vE-rjX%>Y)t>k|OmRJ?r|Ptkkf* zlUYZ3zxCd_;kE~6(YJM40qln#i$B?!GgSrg>xz#B0b zHvOdnQBF-qlTw&(qnf*A#yo=P0~YlNk6eo_qUq{BGXZm?yzH>n8l49SUW^cz?-T@k@fsE+h+{(C z?&ITwxHIUl-^r8TwNRw-wiI1J3~O3U4jhIvGm2Q4sz^(3-@biSd<5S@&>(HccMFr|toBIznqL3f+KVDLEEWV* ziqo#O*@?ZWfBu|#Hcp5F773v&{rr(rqzP1Czu)WQ!}rvEb!#R*D02eTV)?u!>7J)6 zqYD`$T@gx5+0W=2D-;(Oa|JB_m!h*n6&k>P?ng!4BS`s=2f;TnTXM!`7f5LFYM>Fs@MbYdZy&Y~rDbIq>%IXQ_{uKW`8z3dMI&7eb7_ay#!~<+S4@nRA{7qefz#( z`gK?pq+}J5&IRN$5Wy})fI}vDohGsC_y6uu)5ytK`KMKNka^ET%y!aRy{!}`uS4|eb1WBbS{ML)*MH-n!6H3c%3AT=6V0W_U0^O&Xc>1DUe zhd5|Lix}xv6mE^#0`BQM4b->;vO?Q`#5U44xSU_CdH9Ivy*JdjwR|hYm!Jz`6dxC; z3 zFgNK}eA#(K{ygB<4APkh5F^)7V%yoa*vpY=jp8e_E;jk>+Q5#p9$KrMu-;t#l5@M_ zeg{$~J9C-}^pWdJC4xyL>*Quz|0UD>%jDap=9X;#-9D>b*z>gXhJ=VDE9XCt-sANI63=WXXnG3|`Ku*`ZFwV}~4t zYI-zJe`_*a^+aHi6}NikHhazsQk?;X$EP`0(02+bM60}8G9y^28k8z!IZxC-vhDtx z2-b$C`n*6Dd(G4U*DFm51ve@--x-{zufPxtvvQvNEnMp1?d?6V^?q|2dw{a#6Z;#r zGGF`q(;OTf_4hbn7pWynmJIaw*HuieyR$F#a`oYB8uyLD&`<7+VTel~b#O?Lwl1^i z%$ZfBJbvGCr%>+C^ris$`<1V{-|Z+b-OhQQt97922fC+cW~O}h`20vhD*e(u`Q<73 zEQE3KXBw-oEIqbGsK|V9@v0?P#!%ff3iClgmz|T-+R<_Q!e~9%_dz(z&;Ip>%M^@5 zK462kn3$MXGZQ79CpJqwpym5S zHoHg{CNR{=TaesAEPg0IH`hkul*SeRsgdrbvM)wod0ULl_?m1hYuj-ZKYkDEwm#=r zedEj46J`B7rKf+jUW}%GDPEMh^L_BCj_IU3l(?l{Tb@=>vs2v8#lITa9qV?x+QjUQ z%j9#fgdvOBoHrRuw@b^v(q?#lFMYr5ilae3D^1EuDZeFX^g|W#|y9bPqZrr#c^B!-vu`KuN%v?Gt zJRe(nQL=f=;9S%)IF?1Rp^cp>ed6;oMHv>X*-anLdtjL`x3pZAcRu*d;Mf4%Z1SHz zJuZaJ12(zG{*!oCR=*&{IivggJFL|Ml>r?2(9~md9@7Q9gS{DNc7S{tyx6@|j9S3!)aMPkXm3KS(-He$+r-f132kV0u*F!z>3 zE^L-fp{ViC`TPg{_s0J&4sM74?wtRgj{k2{$76qr)X%G14*h1#k{MB3eV Date: Fri, 12 Mar 2021 12:02:39 +0100 Subject: [PATCH 53/67] a) fixed small error in computeSetSize1D, b) DataGenerator output now with 12 decimals precision, d)datagenerator scripts now with more precision Former-commit-id: 52dd0f3760e314f140249a0aed612a5db6600e54 --- code/input/DataGenerator1D.cfg | 2 +- code/src/toolboxes/datagenerator1D.cpp | 2 +- code/src/toolboxes/datageneratorbase.cpp | 21 +++++++++++++++------ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/code/input/DataGenerator1D.cfg b/code/input/DataGenerator1D.cfg index 963f0e0..7e0cae0 100644 --- a/code/input/DataGenerator1D.cfg +++ b/code/input/DataGenerator1D.cfg @@ -40,7 +40,7 @@ ENTROPY_OPTIMIZER = NEWTON % NEWTON_FAST_MODE = NO NEWTON_ITER = 1000000 -NEWTON_EPSILON = 0.0001 +NEWTON_EPSILON = 1e-7 NEWTON_STEP_SIZE = 0.7 NEWTON_LINE_SEARCH_ITER = 100000 % diff --git a/code/src/toolboxes/datagenerator1D.cpp b/code/src/toolboxes/datagenerator1D.cpp index 166d6b1..366c669 100644 --- a/code/src/toolboxes/datagenerator1D.cpp +++ b/code/src/toolboxes/datagenerator1D.cpp @@ -283,7 +283,7 @@ void DataGenerator1D::ComputeSetSize() { } _setSize = c; } - if( _LMaxDegree == 3 ) { + else if( _LMaxDegree == 3 ) { // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1, N1=0 unsigned c = 1; double N1 = 0 + _settings->GetRealizableSetEpsilonU0(); diff --git a/code/src/toolboxes/datageneratorbase.cpp b/code/src/toolboxes/datageneratorbase.cpp index cee1808..59ae0ee 100644 --- a/code/src/toolboxes/datageneratorbase.cpp +++ b/code/src/toolboxes/datageneratorbase.cpp @@ -17,8 +17,10 @@ #include "toolboxes/sphericalbase.h" #include "toolboxes/textprocessingtoolbox.h" +#include #include #include +#include DataGeneratorBase::DataGeneratorBase( Config* settings ) { _settings = settings; @@ -161,14 +163,21 @@ void DataGeneratorBase::PrintTrainingData() { logCSV->info( uSolString + alphaString + "h" ); for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { - std::string uSolString = ""; - std::string alphaString = ""; + + std::stringstream streamU, streamAlpha, streamH; + for( unsigned idx_sys = 0; idx_sys < _nTotalEntries; idx_sys++ ) { - uSolString += std::to_string( _uSol[idx_set][idx_sys] ) + ","; - alphaString += std::to_string( _alpha[idx_set][idx_sys] ) + ","; + streamU << std::fixed << std::setprecision( 12 ) << _uSol[idx_set][idx_sys] << ","; + streamAlpha << std::fixed << std::setprecision( 12 ) << _alpha[idx_set][idx_sys] << ","; } - // log->info( uSolString + alphaString + "{}", _hEntropy[idx_set] ); - logCSV->info( uSolString + alphaString + "{}", _hEntropy[idx_set] ); + streamH << std::fixed << std::setprecision( 12 ) << _hEntropy[idx_set]; + + std::string uSolString = streamU.str(); + std::string alphaString = streamAlpha.str(); + std::string hString = streamH.str(); + + // log->info( uSolString + alphaString + hString ); + logCSV->info( uSolString + alphaString + hString ); } } -- GitLab From e863d0492bbd248a4db919fadc14f031b73c44b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Fri, 12 Mar 2021 12:19:05 +0100 Subject: [PATCH 54/67] adapted reference file to increased presicion Former-commit-id: ba514b4c4d04403719e0e2495bcfcfeb515cf33e --- .../validate_dataGen_csv_reference | 258 +++++++++--------- 1 file changed, 129 insertions(+), 129 deletions(-) diff --git a/code/tests/input/validation_tests/dataGenerator/validate_dataGen_csv_reference b/code/tests/input/validation_tests/dataGenerator/validate_dataGen_csv_reference index 542e60f..b4e0046 100644 --- a/code/tests/input/validation_tests/dataGenerator/validate_dataGen_csv_reference +++ b/code/tests/input/validation_tests/dataGenerator/validate_dataGen_csv_reference @@ -1,129 +1,129 @@ -2021-02-19 15:26:51.242706 ,u_0,u_1,u_2,u_3,alpha_0,alpha_1,alpha_2,alpha_3,h -2021-02-19 15:26:51.242728 ,20.360217,2.775457,0.552073,-9.739846,-0.002440,0.489071,0.097282,-1.716286,-2.282440083785514 -2021-02-19 15:26:51.242735 ,20.360217,2.352919,1.572170,-9.739846,-0.002440,0.414615,0.277037,-1.716286,-2.2824400837855188 -2021-02-19 15:26:51.242741 ,20.360217,1.572170,2.352919,-9.739846,-0.002440,0.277037,0.414615,-1.716286,-2.2824400837855228 -2021-02-19 15:26:51.242747 ,20.360217,0.552073,2.775457,-9.739846,-0.002440,0.097282,0.489071,-1.716286,-2.282440083785519 -2021-02-19 15:26:51.242754 ,20.360217,-0.552073,2.775457,-9.739846,-0.002440,-0.097282,0.489071,-1.716286,-2.282440083785519 -2021-02-19 15:26:51.242760 ,20.360217,-1.572170,2.352919,-9.739846,-0.002440,-0.277037,0.414615,-1.716286,-2.282440083785528 -2021-02-19 15:26:51.242766 ,20.360217,-2.352919,1.572170,-9.739846,-0.002440,-0.414615,0.277037,-1.716286,-2.282440083785539 -2021-02-19 15:26:51.242772 ,20.360217,-2.775457,0.552073,-9.739846,-0.002440,-0.489071,0.097282,-1.716286,-2.2824400837855183 -2021-02-19 15:26:51.242778 ,20.360217,-2.775457,-0.552073,-9.739846,-0.002440,-0.489071,-0.097282,-1.716286,-2.282440083785521 -2021-02-19 15:26:51.242784 ,20.360217,-2.352919,-1.572170,-9.739846,-0.002440,-0.414615,-0.277037,-1.716286,-2.282440083785545 -2021-02-19 15:26:51.242791 ,20.360217,-1.572170,-2.352919,-9.739846,-0.002440,-0.277037,-0.414615,-1.716286,-2.282440083785531 -2021-02-19 15:26:51.242797 ,20.360217,-0.552073,-2.775457,-9.739846,-0.002440,-0.097282,-0.489071,-1.716286,-2.282440083785522 -2021-02-19 15:26:51.242803 ,20.360217,0.552073,-2.775457,-9.739846,-0.002440,0.097282,-0.489071,-1.716286,-2.2824400837855143 -2021-02-19 15:26:51.242809 ,20.360217,1.572170,-2.352919,-9.739846,-0.002440,0.277037,-0.414615,-1.716286,-2.282440083785516 -2021-02-19 15:26:51.242815 ,20.360217,2.352919,-1.572170,-9.739846,-0.002440,0.414615,-0.277037,-1.716286,-2.2824400837855174 -2021-02-19 15:26:51.242821 ,20.360217,2.775457,-0.552073,-9.739846,-0.002440,0.489071,-0.097282,-1.716286,-2.2824400837855134 -2021-02-19 15:26:51.242827 ,20.360217,6.012595,1.195979,-8.080278,-0.002440,1.059496,0.210747,-1.423849,-2.282440083785506 -2021-02-19 15:26:51.242834 ,20.360217,5.097232,3.405861,-8.080278,-0.002440,0.898198,0.600156,-1.423849,-2.2824400837855103 -2021-02-19 15:26:51.242840 ,20.360217,3.405861,5.097232,-8.080278,-0.002440,0.600156,0.898198,-1.423849,-2.2824400837855157 -2021-02-19 15:26:51.242846 ,20.360217,1.195979,6.012595,-8.080278,-0.002440,0.210747,1.059496,-1.423849,-2.2824400837855254 -2021-02-19 15:26:51.242852 ,20.360217,-1.195979,6.012595,-8.080278,-0.002440,-0.210747,1.059496,-1.423849,-2.282440083785526 -2021-02-19 15:26:51.242858 ,20.360217,-3.405861,5.097232,-8.080278,-0.002440,-0.600156,0.898198,-1.423849,-2.2824400837855223 -2021-02-19 15:26:51.242864 ,20.360217,-5.097232,3.405861,-8.080278,-0.002440,-0.898198,0.600156,-1.423849,-2.282440083785532 -2021-02-19 15:26:51.242870 ,20.360217,-6.012595,1.195979,-8.080278,-0.002440,-1.059496,0.210747,-1.423849,-2.2824400837855263 -2021-02-19 15:26:51.242876 ,20.360217,-6.012595,-1.195979,-8.080278,-0.002440,-1.059496,-0.210747,-1.423849,-2.2824400837855268 -2021-02-19 15:26:51.242882 ,20.360217,-5.097232,-3.405861,-8.080278,-0.002440,-0.898198,-0.600156,-1.423849,-2.282440083785532 -2021-02-19 15:26:51.242889 ,20.360217,-3.405861,-5.097232,-8.080278,-0.002440,-0.600156,-0.898198,-1.423849,-2.282440083785522 -2021-02-19 15:26:51.242895 ,20.360217,-1.195979,-6.012595,-8.080278,-0.002440,-0.210747,-1.059496,-1.423849,-2.282440083785527 -2021-02-19 15:26:51.242901 ,20.360217,1.195979,-6.012595,-8.080278,-0.002440,0.210747,-1.059496,-1.423849,-2.282440083785523 -2021-02-19 15:26:51.242907 ,20.360217,3.405861,-5.097232,-8.080278,-0.002440,0.600156,-0.898198,-1.423849,-2.2824400837855157 -2021-02-19 15:26:51.242913 ,20.360217,5.097232,-3.405861,-8.080278,-0.002440,0.898198,-0.600156,-1.423849,-2.282440083785511 -2021-02-19 15:26:51.242919 ,20.360217,6.012595,-1.195979,-8.080278,-0.002440,1.059496,-0.210747,-1.423849,-2.282440083785505 -2021-02-19 15:26:51.242925 ,20.360217,8.463260,1.683447,-5.330271,-0.002440,1.491335,0.296645,-0.939262,-2.2824400837854895 -2021-02-19 15:26:51.242946 ,20.360217,7.174806,4.794052,-5.330271,-0.002440,1.264293,0.844773,-0.939262,-2.2824400837854943 -2021-02-19 15:26:51.242952 ,20.360217,4.794052,7.174806,-5.330271,-0.002440,0.844773,1.264293,-0.939262,-2.282440083785509 -2021-02-19 15:26:51.242958 ,20.360217,1.683447,8.463260,-5.330271,-0.002440,0.296645,1.491335,-0.939262,-2.282440083785525 -2021-02-19 15:26:51.242964 ,20.360217,-1.683447,8.463260,-5.330271,-0.002440,-0.296645,1.491335,-0.939262,-2.282440083785528 -2021-02-19 15:26:51.242970 ,20.360217,-4.794052,7.174806,-5.330271,-0.002440,-0.844773,1.264293,-0.939262,-2.2824400837855214 -2021-02-19 15:26:51.242976 ,20.360217,-7.174806,4.794052,-5.330271,-0.002440,-1.264293,0.844773,-0.939262,-2.2824400837855197 -2021-02-19 15:26:51.242982 ,20.360217,-8.463260,1.683447,-5.330271,-0.002440,-1.491335,0.296645,-0.939262,-2.2824400837855294 -2021-02-19 15:26:51.242988 ,20.360217,-8.463260,-1.683447,-5.330271,-0.002440,-1.491335,-0.296645,-0.939262,-2.2824400837855294 -2021-02-19 15:26:51.242995 ,20.360217,-7.174806,-4.794052,-5.330271,-0.002440,-1.264293,-0.844773,-0.939262,-2.2824400837855197 -2021-02-19 15:26:51.243001 ,20.360217,-4.794052,-7.174806,-5.330271,-0.002440,-0.844773,-1.264293,-0.939262,-2.2824400837855245 -2021-02-19 15:26:51.243007 ,20.360217,-1.683447,-8.463260,-5.330271,-0.002440,-0.296645,-1.491335,-0.939262,-2.282440083785533 -2021-02-19 15:26:51.243013 ,20.360217,1.683447,-8.463260,-5.330271,-0.002440,0.296645,-1.491335,-0.939262,-2.282440083785527 -2021-02-19 15:26:51.243019 ,20.360217,4.794052,-7.174806,-5.330271,-0.002440,0.844773,-1.264293,-0.939262,-2.282440083785512 -2021-02-19 15:26:51.243025 ,20.360217,7.174806,-4.794052,-5.330271,-0.002440,1.264293,-0.844773,-0.939262,-2.2824400837854952 -2021-02-19 15:26:51.243031 ,20.360217,8.463260,-1.683447,-5.330271,-0.002440,1.491335,-0.296645,-0.939262,-2.282440083785491 -2021-02-19 15:26:51.243037 ,20.360217,9.778929,1.945150,-1.860506,-0.002440,1.723173,0.342760,-0.327845,-2.2824400837854912 -2021-02-19 15:26:51.243044 ,20.360217,8.290176,5.539319,-1.860506,-0.002440,1.460835,0.976099,-0.327845,-2.2824400837854997 -2021-02-19 15:26:51.243050 ,20.360217,5.539319,8.290176,-1.860506,-0.002440,0.976099,1.460835,-0.327845,-2.2824400837855126 -2021-02-19 15:26:51.243056 ,20.360217,1.945150,9.778929,-1.860506,-0.002440,0.342760,1.723173,-0.327845,-2.2824400837855237 -2021-02-19 15:26:51.243062 ,20.360217,-1.945150,9.778929,-1.860506,-0.002440,-0.342760,1.723173,-0.327845,-2.282440083785537 -2021-02-19 15:26:51.243068 ,20.360217,-5.539319,8.290176,-1.860506,-0.002440,-0.976099,1.460835,-0.327845,-2.282440083785529 -2021-02-19 15:26:51.243074 ,20.360217,-8.290176,5.539319,-1.860506,-0.002440,-1.460835,0.976099,-0.327845,-2.282440083785525 -2021-02-19 15:26:51.243080 ,20.360217,-9.778929,1.945150,-1.860506,-0.002440,-1.723173,0.342760,-0.327845,-2.282440083785531 -2021-02-19 15:26:51.243086 ,20.360217,-9.778929,-1.945150,-1.860506,-0.002440,-1.723173,-0.342760,-0.327845,-2.2824400837855365 -2021-02-19 15:26:51.243093 ,20.360217,-8.290176,-5.539319,-1.860506,-0.002440,-1.460835,-0.976099,-0.327845,-2.2824400837855245 -2021-02-19 15:26:51.243099 ,20.360217,-5.539319,-8.290176,-1.860506,-0.002440,-0.976099,-1.460835,-0.327845,-2.2824400837855294 -2021-02-19 15:26:51.243105 ,20.360217,-1.945150,-9.778929,-1.860506,-0.002440,-0.342760,-1.723173,-0.327845,-2.2824400837855374 -2021-02-19 15:26:51.243111 ,20.360217,1.945150,-9.778929,-1.860506,-0.002440,0.342760,-1.723173,-0.327845,-2.282440083785522 -2021-02-19 15:26:51.243117 ,20.360217,5.539319,-8.290176,-1.860506,-0.002440,0.976099,-1.460835,-0.327845,-2.282440083785511 -2021-02-19 15:26:51.243123 ,20.360217,8.290176,-5.539319,-1.860506,-0.002440,1.460835,-0.976099,-0.327845,-2.2824400837854983 -2021-02-19 15:26:51.243129 ,20.360217,9.778929,-1.945150,-1.860506,-0.002440,1.723173,-0.342760,-0.327845,-2.282440083785499 -2021-02-19 15:26:51.243135 ,20.360217,9.778929,1.945150,1.860506,-0.002440,1.723173,0.342760,0.327845,-2.2824400837854903 -2021-02-19 15:26:51.243147 ,20.360217,8.290176,5.539319,1.860506,-0.002440,1.460835,0.976099,0.327845,-2.2824400837854983 -2021-02-19 15:26:51.243153 ,20.360217,5.539319,8.290176,1.860506,-0.002440,0.976099,1.460835,0.327845,-2.282440083785513 -2021-02-19 15:26:51.243159 ,20.360217,1.945150,9.778929,1.860506,-0.002440,0.342760,1.723173,0.327845,-2.2824400837855228 -2021-02-19 15:26:51.243165 ,20.360217,-1.945150,9.778929,1.860506,-0.002440,-0.342760,1.723173,0.327845,-2.2824400837855356 -2021-02-19 15:26:51.243172 ,20.360217,-5.539319,8.290176,1.860506,-0.002440,-0.976099,1.460835,0.327845,-2.2824400837855348 -2021-02-19 15:26:51.243178 ,20.360217,-8.290176,5.539319,1.860506,-0.002440,-1.460835,0.976099,0.327845,-2.282440083785527 -2021-02-19 15:26:51.243184 ,20.360217,-9.778929,1.945150,1.860506,-0.002440,-1.723173,0.342760,0.327845,-2.2824400837855374 -2021-02-19 15:26:51.243190 ,20.360217,-9.778929,-1.945150,1.860506,-0.002440,-1.723173,-0.342760,0.327845,-2.282440083785535 -2021-02-19 15:26:51.243196 ,20.360217,-8.290176,-5.539319,1.860506,-0.002440,-1.460835,-0.976099,0.327845,-2.282440083785528 -2021-02-19 15:26:51.243202 ,20.360217,-5.539319,-8.290176,1.860506,-0.002440,-0.976099,-1.460835,0.327845,-2.28244008378553 -2021-02-19 15:26:51.243208 ,20.360217,-1.945150,-9.778929,1.860506,-0.002440,-0.342760,-1.723173,0.327845,-2.28244008378554 -2021-02-19 15:26:51.243214 ,20.360217,1.945150,-9.778929,1.860506,-0.002440,0.342760,-1.723173,0.327845,-2.2824400837855316 -2021-02-19 15:26:51.243220 ,20.360217,5.539319,-8.290176,1.860506,-0.002440,0.976099,-1.460835,0.327845,-2.2824400837855165 -2021-02-19 15:26:51.243227 ,20.360217,8.290176,-5.539319,1.860506,-0.002440,1.460835,-0.976099,0.327845,-2.2824400837854997 -2021-02-19 15:26:51.243233 ,20.360217,9.778929,-1.945150,1.860506,-0.002440,1.723173,-0.342760,0.327845,-2.2824400837854912 -2021-02-19 15:26:51.243239 ,20.360217,8.463260,1.683447,5.330271,-0.002440,1.491335,0.296645,0.939262,-2.2824400837854966 -2021-02-19 15:26:51.243245 ,20.360217,7.174806,4.794052,5.330271,-0.002440,1.264293,0.844773,0.939262,-2.2824400837854895 -2021-02-19 15:26:51.243251 ,20.360217,4.794052,7.174806,5.330271,-0.002440,0.844773,1.264293,0.939262,-2.282440083785509 -2021-02-19 15:26:51.243257 ,20.360217,1.683447,8.463260,5.330271,-0.002440,0.296645,1.491335,0.939262,-2.2824400837855263 -2021-02-19 15:26:51.243263 ,20.360217,-1.683447,8.463260,5.330271,-0.002440,-0.296645,1.491335,0.939262,-2.2824400837855343 -2021-02-19 15:26:51.243270 ,20.360217,-4.794052,7.174806,5.330271,-0.002440,-0.844773,1.264293,0.939262,-2.2824400837855183 -2021-02-19 15:26:51.243276 ,20.360217,-7.174806,4.794052,5.330271,-0.002440,-1.264293,0.844773,0.939262,-2.282440083785526 -2021-02-19 15:26:51.243282 ,20.360217,-8.463260,1.683447,5.330271,-0.002440,-1.491335,0.296645,0.939262,-2.28244008378553 -2021-02-19 15:26:51.243288 ,20.360217,-8.463260,-1.683447,5.330271,-0.002440,-1.491335,-0.296645,0.939262,-2.282440083785531 -2021-02-19 15:26:51.243294 ,20.360217,-7.174806,-4.794052,5.330271,-0.002440,-1.264293,-0.844773,0.939262,-2.2824400837855237 -2021-02-19 15:26:51.243300 ,20.360217,-4.794052,-7.174806,5.330271,-0.002440,-0.844773,-1.264293,0.939262,-2.2824400837855197 -2021-02-19 15:26:51.243306 ,20.360217,-1.683447,-8.463260,5.330271,-0.002440,-0.296645,-1.491335,0.939262,-2.28244008378553 -2021-02-19 15:26:51.243312 ,20.360217,1.683447,-8.463260,5.330271,-0.002440,0.296645,-1.491335,0.939262,-2.2824400837855254 -2021-02-19 15:26:51.243318 ,20.360217,4.794052,-7.174806,5.330271,-0.002440,0.844773,-1.264293,0.939262,-2.2824400837855165 -2021-02-19 15:26:51.243325 ,20.360217,7.174806,-4.794052,5.330271,-0.002440,1.264293,-0.844773,0.939262,-2.2824400837854957 -2021-02-19 15:26:51.243331 ,20.360217,8.463260,-1.683447,5.330271,-0.002440,1.491335,-0.296645,0.939262,-2.2824400837854872 -2021-02-19 15:26:51.243337 ,20.360217,6.012595,1.195979,8.080278,-0.002440,1.059496,0.210747,1.423849,-2.282440083785509 -2021-02-19 15:26:51.243343 ,20.360217,5.097232,3.405861,8.080278,-0.002440,0.898198,0.600156,1.423849,-2.2824400837855117 -2021-02-19 15:26:51.243352 ,20.360217,3.405861,5.097232,8.080278,-0.002440,0.600156,0.898198,1.423849,-2.2824400837855126 -2021-02-19 15:26:51.243358 ,20.360217,1.195979,6.012595,8.080278,-0.002440,0.210747,1.059496,1.423849,-2.282440083785519 -2021-02-19 15:26:51.243364 ,20.360217,-1.195979,6.012595,8.080278,-0.002440,-0.210747,1.059496,1.423849,-2.282440083785529 -2021-02-19 15:26:51.243371 ,20.360217,-3.405861,5.097232,8.080278,-0.002440,-0.600156,0.898198,1.423849,-2.2824400837855223 -2021-02-19 15:26:51.243377 ,20.360217,-5.097232,3.405861,8.080278,-0.002440,-0.898198,0.600156,1.423849,-2.282440083785531 -2021-02-19 15:26:51.243383 ,20.360217,-6.012595,1.195979,8.080278,-0.002440,-1.059496,0.210747,1.423849,-2.2824400837855263 -2021-02-19 15:26:51.243389 ,20.360217,-6.012595,-1.195979,8.080278,-0.002440,-1.059496,-0.210747,1.423849,-2.2824400837855294 -2021-02-19 15:26:51.243395 ,20.360217,-5.097232,-3.405861,8.080278,-0.002440,-0.898198,-0.600156,1.423849,-2.2824400837855308 -2021-02-19 15:26:51.243401 ,20.360217,-3.405861,-5.097232,8.080278,-0.002440,-0.600156,-0.898198,1.423849,-2.282440083785522 -2021-02-19 15:26:51.243408 ,20.360217,-1.195979,-6.012595,8.080278,-0.002440,-0.210747,-1.059496,1.423849,-2.282440083785531 -2021-02-19 15:26:51.243414 ,20.360217,1.195979,-6.012595,8.080278,-0.002440,0.210747,-1.059496,1.423849,-2.282440083785527 -2021-02-19 15:26:51.243420 ,20.360217,3.405861,-5.097232,8.080278,-0.002440,0.600156,-0.898198,1.423849,-2.2824400837855148 -2021-02-19 15:26:51.243426 ,20.360217,5.097232,-3.405861,8.080278,-0.002440,0.898198,-0.600156,1.423849,-2.2824400837855148 -2021-02-19 15:26:51.243432 ,20.360217,6.012595,-1.195979,8.080278,-0.002440,1.059496,-0.210747,1.423849,-2.282440083785507 -2021-02-19 15:26:51.243438 ,20.360217,2.775457,0.552073,9.739846,-0.002440,0.489071,0.097282,1.716286,-2.282440083785508 -2021-02-19 15:26:51.243445 ,20.360217,2.352919,1.572170,9.739846,-0.002440,0.414615,0.277037,1.716286,-2.282440083785513 -2021-02-19 15:26:51.243451 ,20.360217,1.572170,2.352919,9.739846,-0.002440,0.277037,0.414615,1.716286,-2.282440083785519 -2021-02-19 15:26:51.243457 ,20.360217,0.552073,2.775457,9.739846,-0.002440,0.097282,0.489071,1.716286,-2.2824400837855108 -2021-02-19 15:26:51.243463 ,20.360217,-0.552073,2.775457,9.739846,-0.002440,-0.097282,0.489071,1.716286,-2.2824400837855205 -2021-02-19 15:26:51.243469 ,20.360217,-1.572170,2.352919,9.739846,-0.002440,-0.277037,0.414615,1.716286,-2.282440083785531 -2021-02-19 15:26:51.243476 ,20.360217,-2.352919,1.572170,9.739846,-0.002440,-0.414615,0.277037,1.716286,-2.282440083785541 -2021-02-19 15:26:51.243482 ,20.360217,-2.775457,0.552073,9.739846,-0.002440,-0.489071,0.097282,1.716286,-2.2824400837855237 -2021-02-19 15:26:51.243488 ,20.360217,-2.775457,-0.552073,9.739846,-0.002440,-0.489071,-0.097282,1.716286,-2.2824400837855245 -2021-02-19 15:26:51.243494 ,20.360217,-2.352919,-1.572170,9.739846,-0.002440,-0.414615,-0.277037,1.716286,-2.282440083785536 -2021-02-19 15:26:51.243500 ,20.360217,-1.572170,-2.352919,9.739846,-0.002440,-0.277037,-0.414615,1.716286,-2.28244008378553 -2021-02-19 15:26:51.243507 ,20.360217,-0.552073,-2.775457,9.739846,-0.002440,-0.097282,-0.489071,1.716286,-2.282440083785516 -2021-02-19 15:26:51.243513 ,20.360217,0.552073,-2.775457,9.739846,-0.002440,0.097282,-0.489071,1.716286,-2.2824400837855148 -2021-02-19 15:26:51.243519 ,20.360217,1.572170,-2.352919,9.739846,-0.002440,0.277037,-0.414615,1.716286,-2.2824400837855174 -2021-02-19 15:26:51.243525 ,20.360217,2.352919,-1.572170,9.739846,-0.002440,0.414615,-0.277037,1.716286,-2.2824400837855126 -2021-02-19 15:26:51.243533 ,20.360217,2.775457,-0.552073,9.739846,-0.002440,0.489071,-0.097282,1.716286,-2.282440083785507 +2021-03-12 12:17:12.895981 ,u_0,u_1,u_2,u_3,alpha_0,alpha_1,alpha_2,alpha_3,h +2021-03-12 12:17:12.896029 ,20.360217192149,2.775457455351,0.552072813005,-9.739846265576,-0.002440446044,0.489071247650,0.097282319687,-1.716285996688,-2.282440083786 +2021-03-12 12:17:12.896045 ,20.360217192149,2.352919217358,1.572170357789,-9.739846265576,-0.002440446044,0.414614583637,0.277036607756,-1.716285996688,-2.282440083786 +2021-03-12 12:17:12.896059 ,20.360217192149,1.572170357789,2.352919217358,-9.739846265576,-0.002440446044,0.277036607756,0.414614583637,-1.716285996688,-2.282440083786 +2021-03-12 12:17:12.896073 ,20.360217192149,0.552072813005,2.775457455351,-9.739846265576,-0.002440446044,0.097282319687,0.489071247650,-1.716285996688,-2.282440083786 +2021-03-12 12:17:12.896087 ,20.360217192149,-0.552072813005,2.775457455351,-9.739846265576,-0.002440446044,-0.097282319687,0.489071247650,-1.716285996688,-2.282440083786 +2021-03-12 12:17:12.896100 ,20.360217192149,-1.572170357789,2.352919217358,-9.739846265576,-0.002440446044,-0.277036607756,0.414614583637,-1.716285996688,-2.282440083786 +2021-03-12 12:17:12.896114 ,20.360217192149,-2.352919217358,1.572170357789,-9.739846265576,-0.002440446044,-0.414614583637,0.277036607756,-1.716285996688,-2.282440083786 +2021-03-12 12:17:12.896128 ,20.360217192149,-2.775457455351,0.552072813005,-9.739846265576,-0.002440446044,-0.489071247650,0.097282319687,-1.716285996688,-2.282440083786 +2021-03-12 12:17:12.896141 ,20.360217192149,-2.775457455351,-0.552072813005,-9.739846265576,-0.002440446044,-0.489071247650,-0.097282319687,-1.716285996688,-2.282440083786 +2021-03-12 12:17:12.896155 ,20.360217192149,-2.352919217358,-1.572170357789,-9.739846265576,-0.002440446044,-0.414614583637,-0.277036607756,-1.716285996688,-2.282440083786 +2021-03-12 12:17:12.896168 ,20.360217192149,-1.572170357789,-2.352919217358,-9.739846265576,-0.002440446044,-0.277036607756,-0.414614583637,-1.716285996688,-2.282440083786 +2021-03-12 12:17:12.896182 ,20.360217192149,-0.552072813005,-2.775457455351,-9.739846265576,-0.002440446044,-0.097282319687,-0.489071247650,-1.716285996688,-2.282440083786 +2021-03-12 12:17:12.896195 ,20.360217192149,0.552072813005,-2.775457455351,-9.739846265576,-0.002440446044,0.097282319687,-0.489071247650,-1.716285996688,-2.282440083786 +2021-03-12 12:17:12.896209 ,20.360217192149,1.572170357789,-2.352919217358,-9.739846265576,-0.002440446044,0.277036607756,-0.414614583637,-1.716285996688,-2.282440083786 +2021-03-12 12:17:12.896222 ,20.360217192149,2.352919217358,-1.572170357789,-9.739846265576,-0.002440446044,0.414614583637,-0.277036607756,-1.716285996688,-2.282440083786 +2021-03-12 12:17:12.896236 ,20.360217192149,2.775457455351,-0.552072813005,-9.739846265576,-0.002440446044,0.489071247650,-0.097282319687,-1.716285996688,-2.282440083786 +2021-03-12 12:17:12.896252 ,20.360217192149,6.012594628191,1.195979431588,-8.080278014440,-0.002440446044,1.059496390677,0.210746935300,-1.423848757710,-2.282440083786 +2021-03-12 12:17:12.896271 ,20.360217192149,5.097231600355,3.405861267884,-8.080278014440,-0.002440446044,0.898197669555,0.600156495426,-1.423848757710,-2.282440083786 +2021-03-12 12:17:12.896287 ,20.360217192149,3.405861267884,5.097231600355,-8.080278014440,-0.002440446044,0.600156495426,0.898197669555,-1.423848757710,-2.282440083786 +2021-03-12 12:17:12.896303 ,20.360217192149,1.195979431588,6.012594628191,-8.080278014440,-0.002440446044,0.210746935300,1.059496390677,-1.423848757710,-2.282440083786 +2021-03-12 12:17:12.896319 ,20.360217192149,-1.195979431588,6.012594628191,-8.080278014440,-0.002440446044,-0.210746935300,1.059496390677,-1.423848757710,-2.282440083786 +2021-03-12 12:17:12.896335 ,20.360217192149,-3.405861267884,5.097231600355,-8.080278014440,-0.002440446044,-0.600156495426,0.898197669555,-1.423848757710,-2.282440083786 +2021-03-12 12:17:12.896351 ,20.360217192149,-5.097231600355,3.405861267884,-8.080278014440,-0.002440446044,-0.898197669555,0.600156495426,-1.423848757710,-2.282440083786 +2021-03-12 12:17:12.896366 ,20.360217192149,-6.012594628191,1.195979431588,-8.080278014440,-0.002440446044,-1.059496390677,0.210746935300,-1.423848757710,-2.282440083786 +2021-03-12 12:17:12.896478 ,20.360217192149,-6.012594628191,-1.195979431588,-8.080278014440,-0.002440446044,-1.059496390677,-0.210746935300,-1.423848757710,-2.282440083786 +2021-03-12 12:17:12.896495 ,20.360217192149,-5.097231600355,-3.405861267884,-8.080278014440,-0.002440446044,-0.898197669555,-0.600156495426,-1.423848757710,-2.282440083786 +2021-03-12 12:17:12.896511 ,20.360217192149,-3.405861267884,-5.097231600355,-8.080278014440,-0.002440446044,-0.600156495426,-0.898197669555,-1.423848757710,-2.282440083786 +2021-03-12 12:17:12.896527 ,20.360217192149,-1.195979431588,-6.012594628191,-8.080278014440,-0.002440446044,-0.210746935300,-1.059496390677,-1.423848757710,-2.282440083786 +2021-03-12 12:17:12.896543 ,20.360217192149,1.195979431588,-6.012594628191,-8.080278014440,-0.002440446044,0.210746935300,-1.059496390677,-1.423848757710,-2.282440083786 +2021-03-12 12:17:12.896559 ,20.360217192149,3.405861267884,-5.097231600355,-8.080278014440,-0.002440446044,0.600156495426,-0.898197669555,-1.423848757710,-2.282440083786 +2021-03-12 12:17:12.896575 ,20.360217192149,5.097231600355,-3.405861267884,-8.080278014440,-0.002440446044,0.898197669555,-0.600156495426,-1.423848757710,-2.282440083786 +2021-03-12 12:17:12.896591 ,20.360217192149,6.012594628191,-1.195979431588,-8.080278014440,-0.002440446044,1.059496390677,-0.210746935300,-1.423848757710,-2.282440083786 +2021-03-12 12:17:12.896607 ,20.360217192149,8.463260237138,1.683447129519,-5.330270694342,-0.002440446044,1.491335143827,0.296645004015,-0.939262150737,-2.282440083785 +2021-03-12 12:17:12.896623 ,20.360217192149,7.174805585679,4.794051823575,-5.330270694342,-0.002440446044,1.264292887166,0.844773499278,-0.939262150737,-2.282440083785 +2021-03-12 12:17:12.896639 ,20.360217192149,4.794051823575,7.174805585679,-5.330270694342,-0.002440446044,0.844773499278,1.264292887166,-0.939262150737,-2.282440083786 +2021-03-12 12:17:12.896654 ,20.360217192149,1.683447129519,8.463260237138,-5.330270694342,-0.002440446044,0.296645004015,1.491335143827,-0.939262150737,-2.282440083786 +2021-03-12 12:17:12.896670 ,20.360217192149,-1.683447129519,8.463260237138,-5.330270694342,-0.002440446044,-0.296645004015,1.491335143827,-0.939262150737,-2.282440083786 +2021-03-12 12:17:12.896686 ,20.360217192149,-4.794051823575,7.174805585679,-5.330270694342,-0.002440446044,-0.844773499278,1.264292887166,-0.939262150737,-2.282440083786 +2021-03-12 12:17:12.896702 ,20.360217192149,-7.174805585679,4.794051823575,-5.330270694342,-0.002440446044,-1.264292887166,0.844773499278,-0.939262150737,-2.282440083786 +2021-03-12 12:17:12.896718 ,20.360217192149,-8.463260237138,1.683447129519,-5.330270694342,-0.002440446044,-1.491335143827,0.296645004015,-0.939262150737,-2.282440083786 +2021-03-12 12:17:12.896734 ,20.360217192149,-8.463260237138,-1.683447129519,-5.330270694342,-0.002440446044,-1.491335143827,-0.296645004015,-0.939262150737,-2.282440083786 +2021-03-12 12:17:12.896749 ,20.360217192149,-7.174805585679,-4.794051823575,-5.330270694342,-0.002440446044,-1.264292887166,-0.844773499278,-0.939262150737,-2.282440083786 +2021-03-12 12:17:12.896765 ,20.360217192149,-4.794051823575,-7.174805585679,-5.330270694342,-0.002440446044,-0.844773499278,-1.264292887166,-0.939262150737,-2.282440083786 +2021-03-12 12:17:12.896781 ,20.360217192149,-1.683447129519,-8.463260237138,-5.330270694342,-0.002440446044,-0.296645004015,-1.491335143827,-0.939262150737,-2.282440083786 +2021-03-12 12:17:12.896796 ,20.360217192149,1.683447129519,-8.463260237138,-5.330270694342,-0.002440446044,0.296645004015,-1.491335143827,-0.939262150737,-2.282440083786 +2021-03-12 12:17:12.896812 ,20.360217192149,4.794051823575,-7.174805585679,-5.330270694342,-0.002440446044,0.844773499278,-1.264292887166,-0.939262150737,-2.282440083786 +2021-03-12 12:17:12.896828 ,20.360217192149,7.174805585679,-4.794051823575,-5.330270694342,-0.002440446044,1.264292887166,-0.844773499278,-0.939262150737,-2.282440083785 +2021-03-12 12:17:12.896844 ,20.360217192149,8.463260237138,-1.683447129519,-5.330270694342,-0.002440446044,1.491335143827,-0.296645004015,-0.939262150737,-2.282440083785 +2021-03-12 12:17:12.896896 ,20.360217192149,9.778929486875,1.945150014673,-1.860506185294,-0.002440446044,1.723172962210,0.342760413318,-0.327845083537,-2.282440083785 +2021-03-12 12:17:12.896913 ,20.360217192149,8.290176118715,5.539318587114,-1.860506185294,-0.002440446044,1.460835499315,0.976099074157,-0.327845083537,-2.282440083785 +2021-03-12 12:17:12.896929 ,20.360217192149,5.539318587114,8.290176118715,-1.860506185294,-0.002440446044,0.976099074157,1.460835499315,-0.327845083537,-2.282440083786 +2021-03-12 12:17:12.896944 ,20.360217192149,1.945150014673,9.778929486875,-1.860506185294,-0.002440446044,0.342760413318,1.723172962210,-0.327845083536,-2.282440083786 +2021-03-12 12:17:12.896960 ,20.360217192149,-1.945150014673,9.778929486875,-1.860506185294,-0.002440446044,-0.342760413318,1.723172962210,-0.327845083536,-2.282440083786 +2021-03-12 12:17:12.896976 ,20.360217192149,-5.539318587114,8.290176118715,-1.860506185294,-0.002440446044,-0.976099074157,1.460835499315,-0.327845083537,-2.282440083786 +2021-03-12 12:17:12.896992 ,20.360217192149,-8.290176118715,5.539318587114,-1.860506185294,-0.002440446044,-1.460835499315,0.976099074157,-0.327845083537,-2.282440083786 +2021-03-12 12:17:12.897008 ,20.360217192149,-9.778929486875,1.945150014673,-1.860506185294,-0.002440446044,-1.723172962210,0.342760413318,-0.327845083537,-2.282440083786 +2021-03-12 12:17:12.897024 ,20.360217192149,-9.778929486875,-1.945150014673,-1.860506185294,-0.002440446044,-1.723172962210,-0.342760413318,-0.327845083537,-2.282440083786 +2021-03-12 12:17:12.897040 ,20.360217192149,-8.290176118715,-5.539318587114,-1.860506185294,-0.002440446044,-1.460835499315,-0.976099074157,-0.327845083537,-2.282440083786 +2021-03-12 12:17:12.897056 ,20.360217192149,-5.539318587114,-8.290176118715,-1.860506185294,-0.002440446044,-0.976099074157,-1.460835499315,-0.327845083537,-2.282440083786 +2021-03-12 12:17:12.897072 ,20.360217192149,-1.945150014673,-9.778929486875,-1.860506185294,-0.002440446044,-0.342760413318,-1.723172962210,-0.327845083536,-2.282440083786 +2021-03-12 12:17:12.897088 ,20.360217192149,1.945150014673,-9.778929486875,-1.860506185294,-0.002440446044,0.342760413318,-1.723172962210,-0.327845083536,-2.282440083786 +2021-03-12 12:17:12.897103 ,20.360217192149,5.539318587114,-8.290176118715,-1.860506185294,-0.002440446044,0.976099074157,-1.460835499315,-0.327845083537,-2.282440083786 +2021-03-12 12:17:12.897119 ,20.360217192149,8.290176118715,-5.539318587114,-1.860506185294,-0.002440446044,1.460835499315,-0.976099074157,-0.327845083537,-2.282440083785 +2021-03-12 12:17:12.897135 ,20.360217192149,9.778929486875,-1.945150014673,-1.860506185294,-0.002440446044,1.723172962210,-0.342760413318,-0.327845083537,-2.282440083785 +2021-03-12 12:17:12.897151 ,20.360217192149,9.778929486875,1.945150014673,1.860506185294,-0.002440446044,1.723172962210,0.342760413318,0.327845083537,-2.282440083785 +2021-03-12 12:17:12.897167 ,20.360217192149,8.290176118715,5.539318587114,1.860506185294,-0.002440446044,1.460835499315,0.976099074157,0.327845083537,-2.282440083785 +2021-03-12 12:17:12.897183 ,20.360217192149,5.539318587114,8.290176118715,1.860506185294,-0.002440446044,0.976099074157,1.460835499315,0.327845083537,-2.282440083786 +2021-03-12 12:17:12.897199 ,20.360217192149,1.945150014673,9.778929486875,1.860506185294,-0.002440446044,0.342760413318,1.723172962210,0.327845083536,-2.282440083786 +2021-03-12 12:17:12.897215 ,20.360217192149,-1.945150014673,9.778929486875,1.860506185294,-0.002440446044,-0.342760413318,1.723172962210,0.327845083536,-2.282440083786 +2021-03-12 12:17:12.897231 ,20.360217192149,-5.539318587114,8.290176118715,1.860506185294,-0.002440446044,-0.976099074157,1.460835499315,0.327845083537,-2.282440083786 +2021-03-12 12:17:12.897246 ,20.360217192149,-8.290176118715,5.539318587114,1.860506185294,-0.002440446044,-1.460835499315,0.976099074157,0.327845083537,-2.282440083786 +2021-03-12 12:17:12.897262 ,20.360217192149,-9.778929486875,1.945150014673,1.860506185294,-0.002440446044,-1.723172962210,0.342760413318,0.327845083537,-2.282440083786 +2021-03-12 12:17:12.897296 ,20.360217192149,-9.778929486875,-1.945150014673,1.860506185294,-0.002440446044,-1.723172962210,-0.342760413318,0.327845083537,-2.282440083786 +2021-03-12 12:17:12.897313 ,20.360217192149,-8.290176118715,-5.539318587114,1.860506185294,-0.002440446044,-1.460835499315,-0.976099074157,0.327845083537,-2.282440083786 +2021-03-12 12:17:12.897329 ,20.360217192149,-5.539318587114,-8.290176118715,1.860506185294,-0.002440446044,-0.976099074157,-1.460835499315,0.327845083537,-2.282440083786 +2021-03-12 12:17:12.897345 ,20.360217192149,-1.945150014673,-9.778929486875,1.860506185294,-0.002440446044,-0.342760413318,-1.723172962210,0.327845083536,-2.282440083786 +2021-03-12 12:17:12.897361 ,20.360217192149,1.945150014673,-9.778929486875,1.860506185294,-0.002440446044,0.342760413318,-1.723172962210,0.327845083536,-2.282440083786 +2021-03-12 12:17:12.897377 ,20.360217192149,5.539318587114,-8.290176118715,1.860506185294,-0.002440446044,0.976099074157,-1.460835499315,0.327845083537,-2.282440083786 +2021-03-12 12:17:12.897393 ,20.360217192149,8.290176118715,-5.539318587114,1.860506185294,-0.002440446044,1.460835499315,-0.976099074157,0.327845083537,-2.282440083785 +2021-03-12 12:17:12.897409 ,20.360217192149,9.778929486875,-1.945150014673,1.860506185294,-0.002440446044,1.723172962210,-0.342760413318,0.327845083537,-2.282440083785 +2021-03-12 12:17:12.897425 ,20.360217192149,8.463260237138,1.683447129519,5.330270694342,-0.002440446044,1.491335143827,0.296645004015,0.939262150737,-2.282440083785 +2021-03-12 12:17:12.897441 ,20.360217192149,7.174805585679,4.794051823575,5.330270694342,-0.002440446044,1.264292887166,0.844773499278,0.939262150737,-2.282440083785 +2021-03-12 12:17:12.897457 ,20.360217192149,4.794051823575,7.174805585679,5.330270694342,-0.002440446044,0.844773499278,1.264292887166,0.939262150737,-2.282440083786 +2021-03-12 12:17:12.897473 ,20.360217192149,1.683447129519,8.463260237138,5.330270694342,-0.002440446044,0.296645004015,1.491335143827,0.939262150737,-2.282440083786 +2021-03-12 12:17:12.897489 ,20.360217192149,-1.683447129519,8.463260237138,5.330270694342,-0.002440446044,-0.296645004015,1.491335143827,0.939262150737,-2.282440083786 +2021-03-12 12:17:12.897505 ,20.360217192149,-4.794051823575,7.174805585679,5.330270694342,-0.002440446044,-0.844773499278,1.264292887166,0.939262150737,-2.282440083786 +2021-03-12 12:17:12.897521 ,20.360217192149,-7.174805585679,4.794051823575,5.330270694342,-0.002440446044,-1.264292887166,0.844773499278,0.939262150737,-2.282440083786 +2021-03-12 12:17:12.897537 ,20.360217192149,-8.463260237138,1.683447129519,5.330270694342,-0.002440446044,-1.491335143827,0.296645004015,0.939262150737,-2.282440083786 +2021-03-12 12:17:12.897552 ,20.360217192149,-8.463260237138,-1.683447129519,5.330270694342,-0.002440446044,-1.491335143827,-0.296645004015,0.939262150737,-2.282440083786 +2021-03-12 12:17:12.897568 ,20.360217192149,-7.174805585679,-4.794051823575,5.330270694342,-0.002440446044,-1.264292887166,-0.844773499278,0.939262150737,-2.282440083786 +2021-03-12 12:17:12.897584 ,20.360217192149,-4.794051823575,-7.174805585679,5.330270694342,-0.002440446044,-0.844773499278,-1.264292887166,0.939262150737,-2.282440083786 +2021-03-12 12:17:12.897600 ,20.360217192149,-1.683447129519,-8.463260237138,5.330270694342,-0.002440446044,-0.296645004015,-1.491335143827,0.939262150737,-2.282440083786 +2021-03-12 12:17:12.897616 ,20.360217192149,1.683447129519,-8.463260237138,5.330270694342,-0.002440446044,0.296645004015,-1.491335143827,0.939262150737,-2.282440083786 +2021-03-12 12:17:12.897632 ,20.360217192149,4.794051823575,-7.174805585679,5.330270694342,-0.002440446044,0.844773499278,-1.264292887166,0.939262150737,-2.282440083786 +2021-03-12 12:17:12.897647 ,20.360217192149,7.174805585679,-4.794051823575,5.330270694342,-0.002440446044,1.264292887166,-0.844773499278,0.939262150737,-2.282440083785 +2021-03-12 12:17:12.897663 ,20.360217192149,8.463260237138,-1.683447129519,5.330270694342,-0.002440446044,1.491335143827,-0.296645004015,0.939262150737,-2.282440083785 +2021-03-12 12:17:12.897679 ,20.360217192149,6.012594628191,1.195979431588,8.080278014440,-0.002440446044,1.059496390677,0.210746935300,1.423848757710,-2.282440083786 +2021-03-12 12:17:12.897703 ,20.360217192149,5.097231600355,3.405861267884,8.080278014440,-0.002440446044,0.898197669555,0.600156495426,1.423848757710,-2.282440083786 +2021-03-12 12:17:12.897720 ,20.360217192149,3.405861267884,5.097231600355,8.080278014440,-0.002440446044,0.600156495426,0.898197669555,1.423848757710,-2.282440083786 +2021-03-12 12:17:12.897736 ,20.360217192149,1.195979431588,6.012594628191,8.080278014440,-0.002440446044,0.210746935300,1.059496390677,1.423848757710,-2.282440083786 +2021-03-12 12:17:12.897752 ,20.360217192149,-1.195979431588,6.012594628191,8.080278014440,-0.002440446044,-0.210746935300,1.059496390677,1.423848757710,-2.282440083786 +2021-03-12 12:17:12.897768 ,20.360217192149,-3.405861267884,5.097231600355,8.080278014440,-0.002440446044,-0.600156495426,0.898197669555,1.423848757710,-2.282440083786 +2021-03-12 12:17:12.897784 ,20.360217192149,-5.097231600355,3.405861267884,8.080278014440,-0.002440446044,-0.898197669555,0.600156495426,1.423848757710,-2.282440083786 +2021-03-12 12:17:12.897800 ,20.360217192149,-6.012594628191,1.195979431588,8.080278014440,-0.002440446044,-1.059496390677,0.210746935300,1.423848757710,-2.282440083786 +2021-03-12 12:17:12.897816 ,20.360217192149,-6.012594628191,-1.195979431588,8.080278014440,-0.002440446044,-1.059496390677,-0.210746935300,1.423848757710,-2.282440083786 +2021-03-12 12:17:12.897832 ,20.360217192149,-5.097231600355,-3.405861267884,8.080278014440,-0.002440446044,-0.898197669555,-0.600156495426,1.423848757710,-2.282440083786 +2021-03-12 12:17:12.897849 ,20.360217192149,-3.405861267884,-5.097231600355,8.080278014440,-0.002440446044,-0.600156495426,-0.898197669555,1.423848757710,-2.282440083786 +2021-03-12 12:17:12.897865 ,20.360217192149,-1.195979431588,-6.012594628191,8.080278014440,-0.002440446044,-0.210746935300,-1.059496390677,1.423848757710,-2.282440083786 +2021-03-12 12:17:12.897881 ,20.360217192149,1.195979431588,-6.012594628191,8.080278014440,-0.002440446044,0.210746935300,-1.059496390677,1.423848757710,-2.282440083786 +2021-03-12 12:17:12.897897 ,20.360217192149,3.405861267884,-5.097231600355,8.080278014440,-0.002440446044,0.600156495426,-0.898197669555,1.423848757710,-2.282440083786 +2021-03-12 12:17:12.897913 ,20.360217192149,5.097231600355,-3.405861267884,8.080278014440,-0.002440446044,0.898197669555,-0.600156495426,1.423848757710,-2.282440083786 +2021-03-12 12:17:12.897929 ,20.360217192149,6.012594628191,-1.195979431588,8.080278014440,-0.002440446044,1.059496390677,-0.210746935300,1.423848757710,-2.282440083786 +2021-03-12 12:17:12.897945 ,20.360217192149,2.775457455351,0.552072813005,9.739846265576,-0.002440446044,0.489071247650,0.097282319687,1.716285996688,-2.282440083786 +2021-03-12 12:17:12.897962 ,20.360217192149,2.352919217358,1.572170357789,9.739846265576,-0.002440446044,0.414614583637,0.277036607756,1.716285996688,-2.282440083786 +2021-03-12 12:17:12.897978 ,20.360217192149,1.572170357789,2.352919217358,9.739846265576,-0.002440446044,0.277036607756,0.414614583637,1.716285996688,-2.282440083786 +2021-03-12 12:17:12.897994 ,20.360217192149,0.552072813005,2.775457455351,9.739846265576,-0.002440446044,0.097282319687,0.489071247650,1.716285996688,-2.282440083786 +2021-03-12 12:17:12.898010 ,20.360217192149,-0.552072813005,2.775457455351,9.739846265576,-0.002440446044,-0.097282319687,0.489071247650,1.716285996688,-2.282440083786 +2021-03-12 12:17:12.898026 ,20.360217192149,-1.572170357789,2.352919217358,9.739846265576,-0.002440446044,-0.277036607756,0.414614583637,1.716285996688,-2.282440083786 +2021-03-12 12:17:12.898042 ,20.360217192149,-2.352919217358,1.572170357789,9.739846265576,-0.002440446044,-0.414614583637,0.277036607756,1.716285996688,-2.282440083786 +2021-03-12 12:17:12.898059 ,20.360217192149,-2.775457455351,0.552072813005,9.739846265576,-0.002440446044,-0.489071247650,0.097282319687,1.716285996688,-2.282440083786 +2021-03-12 12:17:12.898075 ,20.360217192149,-2.775457455351,-0.552072813005,9.739846265576,-0.002440446044,-0.489071247650,-0.097282319687,1.716285996688,-2.282440083786 +2021-03-12 12:17:12.898098 ,20.360217192149,-2.352919217358,-1.572170357789,9.739846265576,-0.002440446044,-0.414614583637,-0.277036607756,1.716285996688,-2.282440083786 +2021-03-12 12:17:12.898114 ,20.360217192149,-1.572170357789,-2.352919217358,9.739846265576,-0.002440446044,-0.277036607756,-0.414614583637,1.716285996688,-2.282440083786 +2021-03-12 12:17:12.898131 ,20.360217192149,-0.552072813005,-2.775457455351,9.739846265576,-0.002440446044,-0.097282319687,-0.489071247650,1.716285996688,-2.282440083786 +2021-03-12 12:17:12.898147 ,20.360217192149,0.552072813005,-2.775457455351,9.739846265576,-0.002440446044,0.097282319687,-0.489071247650,1.716285996688,-2.282440083786 +2021-03-12 12:17:12.898163 ,20.360217192149,1.572170357789,-2.352919217358,9.739846265576,-0.002440446044,0.277036607756,-0.414614583637,1.716285996688,-2.282440083786 +2021-03-12 12:17:12.898179 ,20.360217192149,2.352919217358,-1.572170357789,9.739846265576,-0.002440446044,0.414614583637,-0.277036607756,1.716285996688,-2.282440083786 +2021-03-12 12:17:12.898195 ,20.360217192149,2.775457455351,-0.552072813005,9.739846265576,-0.002440446044,0.489071247650,-0.097282319687,1.716285996688,-2.282440083786 -- GitLab From 9944514dd02e34fccc7bf5efc832a0fa8ade99ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Fri, 12 Mar 2021 15:33:29 +0100 Subject: [PATCH 55/67] csd option deleted Former-commit-id: 8acf866f3a1cce928a7fe623821246ac10cfb9ea --- code/input/example_csd.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/code/input/example_csd.cfg b/code/input/example_csd.cfg index 18a467f..fb5142a 100644 --- a/code/input/example_csd.cfg +++ b/code/input/example_csd.cfg @@ -4,7 +4,6 @@ LOG_DIR = ../result/logs MESH_FILE = linesource_pseudo_1D.su2 PROBLEM = WATERPHANTOM SOLVER = CSD_SN_SOLVER -CONTINUOUS_SLOWING_DOWN = YES HYDROGEN_FILE = ENDL_H.txt OXYGEN_FILE = ENDL_O.txt KERNEL = ISOTROPIC_1D -- GitLab From a871b08399e86f9837366171c580196c4486d65a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Mon, 15 Mar 2021 14:08:22 +0100 Subject: [PATCH 56/67] added d1 normalized datagenerator Former-commit-id: 1952c219155b399ae9398311e5446319445f709c --- code/input/DataGenerator1D.cfg | 14 ++++++------- code/src/toolboxes/datagenerator1D.cpp | 28 +++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/code/input/DataGenerator1D.cfg b/code/input/DataGenerator1D.cfg index 7e0cae0..29e4eec 100644 --- a/code/input/DataGenerator1D.cfg +++ b/code/input/DataGenerator1D.cfg @@ -1,22 +1,22 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% 1D Data Generator for % +% 1D Data Generator for % % Neural Entropy Closure % -% Author % +% Author % % Date 17.02.2021 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ---- Datagenerator settings ---- DATA_GENERATOR_MODE = YES -TRAINING_SET_SIZE = 100 +TRAINING_SET_SIZE = 2000 MAX_VALUE_FIRST_MOMENT = 1 SPATIAL_DIM = 1 REALIZABLE_SET_EPSILON_U1 = 0.003 REALIZABLE_SET_EPSILON_U0 = 0.003 -NORMALIZED_SAMPLING = NO -MAX_MOMENT_SOLVER = 3 +NORMALIZED_SAMPLING = YES +MAX_MOMENT_SOLVER = 1 % % ---- File specifications ---- -% +% % Output directory OUTPUT_DIR = ../result % Output file @@ -45,7 +45,7 @@ NEWTON_STEP_SIZE = 0.7 NEWTON_LINE_SEARCH_ITER = 100000 % % ----- Quadrature ---- -% +% % Quadrature Rule QUAD_TYPE = GAUSS_LEGENDRE_1D % Quadrature Order diff --git a/code/src/toolboxes/datagenerator1D.cpp b/code/src/toolboxes/datagenerator1D.cpp index 366c669..6723961 100644 --- a/code/src/toolboxes/datagenerator1D.cpp +++ b/code/src/toolboxes/datagenerator1D.cpp @@ -134,6 +134,18 @@ void DataGenerator1D::SampleSolutionU() { } } else if( _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetNormalizedSampling() ) { + if( _LMaxDegree == 1 ) { + // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 + unsigned c = 0; + double dN = 2.0 / (double)_gridSize; + double N1 = -1.0 + _settings->GetRealizableSetEpsilonU0(); + while( N1 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { + _uSol[c][0] = 1; // u0 (normalized i.e. N0) by Monreals notation + _uSol[c][1] = N1; // u1 (normalized i.e. N1) by Monreals notation + N1 += dN; + c++; + } + } if( _LMaxDegree == 2 ) { // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 unsigned c = 0; @@ -234,8 +246,7 @@ void DataGenerator1D::ComputeSetSize() { } _setSize = c; } - else if( _LMaxDegree == 3 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && !_settings->GetNormalizedSampling() ) { - // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 + else if( _LMaxDegree == 3 ) { unsigned c = 0; double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; double u0 = _settings->GetRealizableSetEpsilonU0(); @@ -267,7 +278,18 @@ void DataGenerator1D::ComputeSetSize() { } } else if( _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetNormalizedSampling() ) { - if( _LMaxDegree == 2 ) { + if( _LMaxDegree == 1 ) { + // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 + unsigned c = 0; + double dN = 2.0 / (double)_gridSize; + double N1 = -1.0 + _settings->GetRealizableSetEpsilonU0(); + while( N1 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { + N1 += dN; + c++; + } + _setSize = c; + } + else if( _LMaxDegree == 2 ) { // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 unsigned c = 1; double N1 = -1.0 + _settings->GetRealizableSetEpsilonU0(); -- GitLab From d41c8c19f0f0b5ec5234d796efbd084bb9eb3537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Mon, 15 Mar 2021 19:25:48 +0100 Subject: [PATCH 57/67] added 2d quadrature. variable renamings. added 2d gauss legendre quad to unit tests. added 2d MC sampling Former-commit-id: 580912816bcd71ae9b6c8b92741c6e30cf7d9ab4 --- code/include/common/globalconstants.h | 1 + .../quadratures/qgausslegendretensorized.h | 21 ++- code/include/toolboxes/datageneratorbase.h | 2 +- code/input/DataGenerator1D.cfg | 2 +- code/input/DataGenerator2D.cfg | 12 +- .../qgausslegendretensorized2D.cpp | 87 +++++++++ code/src/quadratures/quadraturebase.cpp | 2 + code/src/toolboxes/datagenerator1D.cpp | 31 ++-- code/src/toolboxes/datagenerator2D.cpp | 169 +++++++++++------- code/src/toolboxes/datagenerator3D.cpp | 10 +- code/src/toolboxes/datageneratorbase.cpp | 4 +- code/tests/test_quadrature.cpp | 59 ++++-- 12 files changed, 285 insertions(+), 115 deletions(-) create mode 100644 code/src/quadratures/qgausslegendretensorized2D.cpp diff --git a/code/include/common/globalconstants.h b/code/include/common/globalconstants.h index ea29b9a..f1fdb17 100644 --- a/code/include/common/globalconstants.h +++ b/code/include/common/globalconstants.h @@ -58,6 +58,7 @@ enum QUAD_NAME { QUAD_MonteCarlo, QUAD_GaussLegendreTensorized, QUAD_GaussLegendre1D, + QUAD_GaussLegendreTensorized2D, QUAD_LevelSymmetric, QUAD_Lebedev, QUAD_LDFESA, diff --git a/code/include/quadratures/qgausslegendretensorized.h b/code/include/quadratures/qgausslegendretensorized.h index 50b0c3a..23fa7cc 100644 --- a/code/include/quadratures/qgausslegendretensorized.h +++ b/code/include/quadratures/qgausslegendretensorized.h @@ -6,20 +6,35 @@ class QGaussLegendreTensorized : public QuadratureBase { // Implementation is done accordingly to Kendall Atkinson 1981, Australian Matematical Society. - private: + protected: double Pythag( const double a, const double b ); std::pair ComputeEigenValTriDiagMatrix( const Matrix& mat ); - bool CheckOrder(); + virtual bool CheckOrder(); public: QGaussLegendreTensorized( Config* settings ); virtual ~QGaussLegendreTensorized() {} - inline void SetName() override { _name = "Tensorized Gauss-Legendre quadrature"; } + virtual inline void SetName() override { _name = "Tensorized Gauss-Legendre quadrature"; } void SetNq() override; void SetPointsAndWeights() override; void SetConnectivity() override; }; +class QGaussLegendreTensorized2D : public QGaussLegendreTensorized +{ + // Implementation is done accordingly to Kendall Atkinson 1981, Australian Matematical Society. + private: + bool CheckOrder() override; + + public: + QGaussLegendreTensorized2D( Config* settings ); + + virtual ~QGaussLegendreTensorized2D() {} + + inline void SetName() override { _name = "Tensorized Gauss-Legendre quadrature 2D projection"; } + void SetNq() override; + void SetPointsAndWeights() override; +}; #endif // QGAUSSLEGENDRETENSORIZED_H diff --git a/code/include/toolboxes/datageneratorbase.h b/code/include/toolboxes/datageneratorbase.h index cf2752a..b6d9d3c 100644 --- a/code/include/toolboxes/datageneratorbase.h +++ b/code/include/toolboxes/datageneratorbase.h @@ -51,7 +51,7 @@ class DataGeneratorBase unsigned long _gridSize; /*!< @brief Size of the grid discretizing moment U0 for higher order sampling (has different uses for different samplers)*/ - unsigned short _LMaxDegree; /*!< @brief Max Order of Spherical Harmonics */ + unsigned short _maxPolyDegree; /*!< @brief Max Order of Spherical Harmonics */ unsigned _nTotalEntries; /*!< @brief Total number of equations in the system */ QuadratureBase* _quadrature; /*!< @brief quadrature to create members below */ diff --git a/code/input/DataGenerator1D.cfg b/code/input/DataGenerator1D.cfg index 29e4eec..75a5673 100644 --- a/code/input/DataGenerator1D.cfg +++ b/code/input/DataGenerator1D.cfg @@ -7,7 +7,7 @@ % % ---- Datagenerator settings ---- DATA_GENERATOR_MODE = YES -TRAINING_SET_SIZE = 2000 +TRAINING_SET_SIZE = 100000 MAX_VALUE_FIRST_MOMENT = 1 SPATIAL_DIM = 1 REALIZABLE_SET_EPSILON_U1 = 0.003 diff --git a/code/input/DataGenerator2D.cfg b/code/input/DataGenerator2D.cfg index 59a0a98..e8ed20c 100644 --- a/code/input/DataGenerator2D.cfg +++ b/code/input/DataGenerator2D.cfg @@ -7,11 +7,13 @@ % % ---- Global settings ---- DATA_GENERATOR_MODE = YES -TRAINING_SET_SIZE = 20 -MAX_VALUE_FIRST_MOMENT = 5 -REALIZABLE_SET_EPSILON_U0 = 0.05 +TRAINING_SET_SIZE = 10000 +MAX_VALUE_FIRST_MOMENT = 1 +REALIZABLE_SET_EPSILON_U0 = 0.003 REALIZABLE_SET_EPSILON_U1 = 0.97 SPATIAL_DIM = 2 +NORMALIZED_SAMPLING = YES + % % ---- File specifications ---- % @@ -38,7 +40,7 @@ ENTROPY_OPTIMIZER = NEWTON % NEWTON_FAST_MODE = NO NEWTON_ITER = 1000000 -NEWTON_EPSILON = 0.0001 +NEWTON_EPSILON = 1e-7 NEWTON_STEP_SIZE = 0.7 NEWTON_LINE_SEARCH_ITER = 100000 % @@ -47,5 +49,5 @@ NEWTON_LINE_SEARCH_ITER = 100000 % Quadrature Rule QUAD_TYPE = GAUSS_LEGENDRE_TENSORIZED % Quadrature Order -QUAD_ORDER = 8 +QUAD_ORDER = 20 % diff --git a/code/src/quadratures/qgausslegendretensorized2D.cpp b/code/src/quadratures/qgausslegendretensorized2D.cpp new file mode 100644 index 0000000..35e2b3e --- /dev/null +++ b/code/src/quadratures/qgausslegendretensorized2D.cpp @@ -0,0 +1,87 @@ +#include "common/config.h" +#include "quadratures/qgausslegendretensorized.h" +#include "toolboxes/errormessages.h" + +QGaussLegendreTensorized2D::QGaussLegendreTensorized2D( Config* settings ) : QGaussLegendreTensorized( settings ) { + SetName(); + CheckOrder(); + SetNq(); + SetPointsAndWeights(); +} + +void QGaussLegendreTensorized2D::SetNq() { _nq = pow( GetOrder(), 2 ); } + +bool QGaussLegendreTensorized2D::CheckOrder() { + if( _order % 2 == 1 ) { // order needs to be even + ErrorMessages::Error( "ERROR! Order " + std::to_string( _order ) + " for " + GetName() + " not available. \n Order must be an even number. ", + CURRENT_FUNCTION ); + } + return true; +} + +void QGaussLegendreTensorized2D::SetPointsAndWeights() { + Vector nodes1D( _order ), weights1D( _order ); + + // construct companion matrix + Matrix CM( _order, _order, 0.0 ); + for( unsigned i = 0; i < _order - 1; ++i ) { + CM( i + 1, i ) = std::sqrt( 1 / ( 4 - 1 / std::pow( static_cast( i + 1 ), 2 ) ) ); + CM( i, i + 1 ) = std::sqrt( 1 / ( 4 - 1 / std::pow( static_cast( i + 1 ), 2 ) ) ); + } + + // compute eigenvalues and -vectors of the companion matrix + auto evSys = ComputeEigenValTriDiagMatrix( CM ); + + for( unsigned i = 0; i < _order; ++i ) { + if( std::fabs( evSys.first[i] ) < 1e-15 ) // avoid rounding errors + nodes1D[i] = 0; + else + nodes1D[i] = evSys.first[i]; + weights1D[i] = 2 * std::pow( evSys.second( 0, i ), 2 ); + } + + // sort nodes increasingly and also reorder weigths for consistency + std::vector sortOrder( nodes1D.size() ); + std::iota( sortOrder.begin(), sortOrder.end(), 0 ); + std::sort( sortOrder.begin(), sortOrder.end(), [&]( unsigned i, unsigned j ) { return nodes1D[i] < nodes1D[j]; } ); + Vector sorted_nodes( static_cast( sortOrder.size() ) ), sorted_weights( static_cast( sortOrder.size() ) ); + std::transform( sortOrder.begin(), sortOrder.end(), sorted_nodes.begin(), [&]( unsigned i ) { return nodes1D[i]; } ); + std::transform( sortOrder.begin(), sortOrder.end(), sorted_weights.begin(), [&]( unsigned i ) { return weights1D[i]; } ); + nodes1D = sorted_nodes; + weights1D = sorted_weights; + + // setup equidistant angle phi around z axis + Vector phi( 2 * _order ); + for( unsigned i = 0; i < 2 * _order; ++i ) { + phi[i] = ( i + 0.5 ) * M_PI / _order; + } + + unsigned range = std::floor( _order / 2.0 ); // comment (steffen): Only half of the points, due to projection + double normalizationFactor = .5; + + // resize points and weights + _points.resize( _nq ); + _pointsSphere.resize( _nq ); + for( auto& p : _points ) { + p.resize( 3 ); + } + for( auto& p : _pointsSphere ) { + p.resize( 2 ); + } + + _weights.resize( _nq ); + + // transform tensorized (x,y,z)-grid to spherical grid points + for( unsigned j = 0; j < range; ++j ) { + for( unsigned i = 0; i < 2 * _order; ++i ) { + _points[j * ( 2 * _order ) + i][0] = sqrt( 1 - nodes1D[j] * nodes1D[j] ) * std::cos( phi[i] ); + _points[j * ( 2 * _order ) + i][1] = sqrt( 1 - nodes1D[j] * nodes1D[j] ) * std::sin( phi[i] ); + _points[j * ( 2 * _order ) + i][2] = 0; + + _pointsSphere[j * ( 2 * _order ) + i][0] = nodes1D[j]; // my + _pointsSphere[j * ( 2 * _order ) + i][1] = phi[i]; // phi + + _weights[j * ( 2 * _order ) + i] = normalizationFactor * M_PI / _order * weights1D[j]; + } + } +} diff --git a/code/src/quadratures/quadraturebase.cpp b/code/src/quadratures/quadraturebase.cpp index 252fa38..21ceac9 100644 --- a/code/src/quadratures/quadraturebase.cpp +++ b/code/src/quadratures/quadraturebase.cpp @@ -24,6 +24,8 @@ QuadratureBase* QuadratureBase::Create( Config* settings ) { case QUAD_MonteCarlo: return new QMonteCarlo( settings ); case QUAD_GaussLegendreTensorized: return new QGaussLegendreTensorized( settings ); case QUAD_GaussLegendre1D: return new QGaussLegendre1D( settings ); + case QUAD_GaussLegendreTensorized2D: return new QGaussLegendreTensorized2D( settings ); + case QUAD_GaussChebyshev1D: return new QGaussChebyshev1D( settings ); case QUAD_LevelSymmetric: return new QLevelSymmetric( settings ); case QUAD_LDFESA: return new QLDFESA( settings ); diff --git a/code/src/toolboxes/datagenerator1D.cpp b/code/src/toolboxes/datagenerator1D.cpp index 6723961..85455a4 100644 --- a/code/src/toolboxes/datagenerator1D.cpp +++ b/code/src/toolboxes/datagenerator1D.cpp @@ -41,7 +41,7 @@ void DataGenerator1D::SampleSolutionU() { // --- Determine stepsizes etc --- - if( _LMaxDegree == 0 ) { + if( _maxPolyDegree == 0 ) { // --- sample u in order 0 --- // u_0 = <1*psi> double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; @@ -51,7 +51,7 @@ void DataGenerator1D::SampleSolutionU() { } } else if( _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && !_settings->GetNormalizedSampling() ) { - if( _LMaxDegree == 1 ) { + if( _maxPolyDegree == 1 ) { unsigned c = 0; double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; @@ -72,7 +72,7 @@ void DataGenerator1D::SampleSolutionU() { u0 += du; } } - else if( _LMaxDegree == 2 ) { + else if( _maxPolyDegree == 2 ) { unsigned c = 0; double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; @@ -99,7 +99,7 @@ void DataGenerator1D::SampleSolutionU() { u0 += du; } } - else if( _LMaxDegree == 3 ) { + else if( _maxPolyDegree == 3 ) { unsigned c = 0; double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; double u0 = _settings->GetRealizableSetEpsilonU0(); @@ -134,7 +134,7 @@ void DataGenerator1D::SampleSolutionU() { } } else if( _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetNormalizedSampling() ) { - if( _LMaxDegree == 1 ) { + if( _maxPolyDegree == 1 ) { // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 unsigned c = 0; double dN = 2.0 / (double)_gridSize; @@ -146,7 +146,7 @@ void DataGenerator1D::SampleSolutionU() { c++; } } - if( _LMaxDegree == 2 ) { + if( _maxPolyDegree == 2 ) { // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 unsigned c = 0; double N1 = -1.0 + _settings->GetRealizableSetEpsilonU0(); @@ -164,7 +164,7 @@ void DataGenerator1D::SampleSolutionU() { N1 += dN; } } - if( _LMaxDegree == 3 ) { + if( _maxPolyDegree == 3 ) { // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1, N1=0 unsigned c = 0; double N1 = 0 + _settings->GetRealizableSetEpsilonU0(); @@ -195,10 +195,10 @@ void DataGenerator1D::CheckRealizability() { } void DataGenerator1D::ComputeSetSize() { - if( _LMaxDegree == 0 ) { + if( _maxPolyDegree == 0 ) { } else if( _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && !_settings->GetNormalizedSampling() ) { - if( _LMaxDegree == 1 ) { + if( _maxPolyDegree == 1 ) { unsigned c = 0; double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; @@ -217,7 +217,7 @@ void DataGenerator1D::ComputeSetSize() { } _setSize = c; } - else if( _LMaxDegree == 2 ) { + else if( _maxPolyDegree == 2 ) { unsigned c = 0; double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; @@ -246,7 +246,7 @@ void DataGenerator1D::ComputeSetSize() { } _setSize = c; } - else if( _LMaxDegree == 3 ) { + else if( _maxPolyDegree == 3 ) { unsigned c = 0; double du = _settings->GetMaxValFirstMoment() / (double)_gridSize; double u0 = _settings->GetRealizableSetEpsilonU0(); @@ -276,9 +276,12 @@ void DataGenerator1D::ComputeSetSize() { } _setSize = c; } + else { + ErrorMessages::Error( "Sampling of training data of degree higher than 3 is not yet implemented.", CURRENT_FUNCTION ); + } } else if( _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS && _settings->GetNormalizedSampling() ) { - if( _LMaxDegree == 1 ) { + if( _maxPolyDegree == 1 ) { // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 unsigned c = 0; double dN = 2.0 / (double)_gridSize; @@ -289,7 +292,7 @@ void DataGenerator1D::ComputeSetSize() { } _setSize = c; } - else if( _LMaxDegree == 2 ) { + else if( _maxPolyDegree == 2 ) { // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 unsigned c = 1; double N1 = -1.0 + _settings->GetRealizableSetEpsilonU0(); @@ -305,7 +308,7 @@ void DataGenerator1D::ComputeSetSize() { } _setSize = c; } - else if( _LMaxDegree == 3 ) { + else if( _maxPolyDegree == 3 ) { // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1, N1=0 unsigned c = 1; double N1 = 0 + _settings->GetRealizableSetEpsilonU0(); diff --git a/code/src/toolboxes/datagenerator2D.cpp b/code/src/toolboxes/datagenerator2D.cpp index 7b68df2..80ddab4 100644 --- a/code/src/toolboxes/datagenerator2D.cpp +++ b/code/src/toolboxes/datagenerator2D.cpp @@ -39,79 +39,97 @@ void DataGenerator2D::ComputeMoments() { void DataGenerator2D::SampleSolutionU() { // Use necessary conditions from Monreal, Dissertation, Chapter 3.2.1, Page 26 - // --- Determine stepsizes etc --- - double du0 = _settings->GetMaxValFirstMoment() / (double)_gridSize; - // different processes for different - if( _LMaxDegree == 0 ) { + if( _maxPolyDegree == 0 ) { // --- sample u in order 0 --- // u_0 = <1*psi> + // --- Determine stepsizes etc --- + double du0 = _settings->GetMaxValFirstMoment() / (double)_gridSize; + for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { _uSol[idx_set][0] = du0 * idx_set; } } - else if( _LMaxDegree == 1 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS ) { - // Sample points on unit sphere. - QuadratureBase* quad = QuadratureBase::Create( _settings ); - VectorVector qpoints = quad->GetPoints(); // carthesian coordinates. - unsigned long nq = (unsigned long)quad->GetNq(); - - // --- sample u in order 0 --- - // u_0 = <1*psi> - -#pragma omp parallel for schedule( guided ) - for( unsigned long idx_set = 0; idx_set < _gridSize; idx_set++ ) { - unsigned long outerIdx = ( idx_set - 1 ) * ( idx_set ) / 2; // sum over all radii up to current - outerIdx *= nq; // in each radius step, use all quad points - - // --- sample u in order 1 --- - /* order 1 has 3 elements. (omega_x, omega_y, omega_z) = omega, let u_1 = (u_x, u_y, u_z) = - * Condition u_0 >= norm(u_1) */ - double radiusU0 = du0 * ( idx_set + 1 ); - // Boundary correction - if( radiusU0 < _settings->GetRealizableSetEpsilonU0() ) { - radiusU0 = _settings->GetRealizableSetEpsilonU0(); // Boundary close to 0 + else if( _settings->GetNormalizedSampling() ) { + if( _maxPolyDegree == 1 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS ) { + // Sample points on unit sphere. + // Use MC sampling: x randUniform ==> r = sqrt(x)*u_0Max + // y radnUniform ==> a = 2*pi*y, + + // Create generator + std::default_random_engine generator; + std::uniform_real_distribution distribution( 0.0, 1.0 ); + + //#pragma omp parallel for schedule( guided ) + for( unsigned long idx_set = 0; idx_set < _setSize; idx_set++ ) { + double mu = std::sqrt( distribution( generator ) ); + double phi = 2 * M_PI * distribution( generator ); + + if( std::sqrt( 1 - mu * mu ) > _settings->GetRealizableSetEpsilonU1() ) { + idx_set--; + continue; + } + else { + _uSol[idx_set][0] = 1.0; + _uSol[idx_set][1] = std::sqrt( 1 - mu * mu ) * std::cos( phi ); + _uSol[idx_set][2] = std::sqrt( 1 - mu * mu ) * std::sin( phi ); + } } - - unsigned long localIdx = 0; - double radius = 0.0; - unsigned long innerIdx = 0; - // loop over all radii - for( unsigned long idx_subset = 0; idx_subset < idx_set; idx_subset++ ) { - radius = du0 * ( idx_subset + 1 ); // dont use radius 0 ==> shift by one + } + else { + ErrorMessages::Error( "Sampling for this configuration is not yet supported", CURRENT_FUNCTION ); + } + } + else if( !_settings->GetNormalizedSampling() ) { + if( _maxPolyDegree == 1 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS ) { + // Sample points on unit sphere. + // Use MC sampling: x randUniform ==> r = sqrt(x)*u_0Max + // y radnUniform ==> a = 2*pi*y, + + // Create generator + std::default_random_engine generator; + std::uniform_real_distribution distribution( 0.0, 1.0 ); + + double du = 0.001; + long gridSize = (long)( (double)_settings->GetMaxValFirstMoment() / du ); + long c = 0; + for( long idx_set = 0; idx_set < gridSize; idx_set++ ) { + + double radiusU0 = du * ( idx_set + 1 ); // Boundary correction - if( radius < _settings->GetRealizableSetEpsilonU0() ) { - radius = _settings->GetRealizableSetEpsilonU0(); // Boundary close to 0 + if( radiusU0 < _settings->GetRealizableSetEpsilonU0() ) { + radiusU0 = _settings->GetRealizableSetEpsilonU0(); // Boundary close to 0 } - if( radius / radiusU0 > 0.95 * _settings->GetRealizableSetEpsilonU1() ) { - // small offset to take care of rounding errors in quadrature - radius = radiusU0 * 0.95 * _settings->GetRealizableSetEpsilonU1(); // "outer" boundary - } - - localIdx = outerIdx + idx_subset * nq; - - for( unsigned long quad_idx = 0; quad_idx < nq; quad_idx++ ) { - innerIdx = localIdx + quad_idx; // gives the global index - - _uSol[innerIdx][0] = radiusU0; // Prevent 1st order moments to be too close to the boundary - // scale quadpoints with radius - _uSol[innerIdx][1] = radius * qpoints[quad_idx][0]; - _uSol[innerIdx][2] = radius * qpoints[quad_idx][1]; - //_uSol[innerIdx][3] = radius * qpoints[quad_idx][2]; + // number of points for unit circle should scale with (u_0)^2, + long currSetSize = ( (long)( radiusU0 * radiusU0 ) ) * _gridSize; + + for( long idx_currSet = 0; idx_currSet < currSetSize; idx_currSet++ ) { + double mu = std::sqrt( distribution( generator ) ); + double phi = 2 * M_PI * distribution( generator ); + if( std::sqrt( 1 - mu * mu ) > _settings->GetRealizableSetEpsilonU1() ) { + idx_set--; + continue; + } + else { + _uSol[c][0] = radiusU0; + _uSol[c][1] = radiusU0 * std::sqrt( 1 - mu * mu ) * std::cos( phi ); + _uSol[c][2] = radiusU0 * std::sqrt( 1 - mu * mu ) * std::sin( phi ); + c++; + } } } } - } - else { - ErrorMessages::Error( "Sampling for this configuration is not yet supported", CURRENT_FUNCTION ); + else { + ErrorMessages::Error( "Sampling for this configuration is not yet supported", CURRENT_FUNCTION ); + } } } void DataGenerator2D::CheckRealizability() { double epsilon = _settings->GetRealizableSetEpsilonU0(); - if( _LMaxDegree == 1 ) { -#pragma omp parallel for schedule( guided ) + if( _maxPolyDegree == 1 ) { + //#pragma omp parallel for schedule( guided ) for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { double normU1 = 0.0; Vector u1( 3, 0.0 ); @@ -146,19 +164,40 @@ void DataGenerator2D::CheckRealizability() { } void DataGenerator2D::ComputeSetSize() { - if( _LMaxDegree == 0 ) { + if( _maxPolyDegree == 0 ) { } - else if( _LMaxDegree == 1 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS ) { - // Sample points on unit sphere. - QuadratureBase* quad = QuadratureBase::Create( _settings ); - unsigned long nq = (unsigned long)quad->GetNq(); + else if( _settings->GetNormalizedSampling() ) { + if( _maxPolyDegree == 1 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS ) { + // Do nothing. Setsize is already given. + } + else { + ErrorMessages::Error( "Sampling for this configuration is not yet supported", CURRENT_FUNCTION ); + } + } + else if( !_settings->GetNormalizedSampling() ) { + if( _maxPolyDegree == 1 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS ) { - // Allocate memory. - _setSize = nq * _gridSize * ( _gridSize - 1 ) / 2; + double du = 0.001; + long gridSize = (long)( (double)_settings->GetMaxValFirstMoment() / du ); // Hardcoded + long c = 0; + for( long idx_set = 0; idx_set < gridSize; idx_set++ ) { - delete quad; - } - else { - ErrorMessages::Error( "Sampling of training data of degree higher than 1 is not yet implemented.", CURRENT_FUNCTION ); + double radiusU0 = du * ( idx_set + 1 ); + // Boundary correction + if( radiusU0 < _settings->GetRealizableSetEpsilonU0() ) { + radiusU0 = _settings->GetRealizableSetEpsilonU0(); // Boundary close to 0 + } + // number of points for unit circle should scale with (u_0)^2, + long currSetSize = ( (long)( radiusU0 * radiusU0 ) ) * _gridSize; + + for( long idx_currSet = 0; idx_currSet < currSetSize; idx_currSet++ ) { + c++; + } + } + _setSize = c; + } + else { + ErrorMessages::Error( "Sampling for this configuration is not yet supported", CURRENT_FUNCTION ); + } } } diff --git a/code/src/toolboxes/datagenerator3D.cpp b/code/src/toolboxes/datagenerator3D.cpp index d6e7df2..3dfdaf6 100644 --- a/code/src/toolboxes/datagenerator3D.cpp +++ b/code/src/toolboxes/datagenerator3D.cpp @@ -43,7 +43,7 @@ void DataGenerator3D::SampleSolutionU() { double du0 = _settings->GetMaxValFirstMoment() / (double)_gridSize; // different processes for different - if( _LMaxDegree == 0 ) { + if( _maxPolyDegree == 0 ) { // --- sample u in order 0 --- // u_0 = <1*psi> @@ -51,7 +51,7 @@ void DataGenerator3D::SampleSolutionU() { _uSol[idx_set][0] = du0 * idx_set; } } - else if( _LMaxDegree == 1 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS ) { + else if( _maxPolyDegree == 1 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS ) { // Sample points on unit sphere. QuadratureBase* quad = QuadratureBase::Create( _settings ); VectorVector qpoints = quad->GetPoints(); // carthesian coordinates. @@ -110,7 +110,7 @@ void DataGenerator3D::SampleSolutionU() { void DataGenerator3D::CheckRealizability() { double epsilon = _settings->GetRealizableSetEpsilonU0(); - if( _LMaxDegree == 1 ) { + if( _maxPolyDegree == 1 ) { #pragma omp parallel for schedule( guided ) for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { double normU1 = 0.0; @@ -147,9 +147,9 @@ void DataGenerator3D::CheckRealizability() { } void DataGenerator3D::ComputeSetSize() { - if( _LMaxDegree == 0 ) { + if( _maxPolyDegree == 0 ) { } - else if( _LMaxDegree == 1 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS ) { + else if( _maxPolyDegree == 1 && _settings->GetSphericalBasisName() == SPHERICAL_MONOMIALS ) { // Sample points on unit sphere. QuadratureBase* quad = QuadratureBase::Create( _settings ); unsigned long nq = (unsigned long)quad->GetNq(); diff --git a/code/src/toolboxes/datageneratorbase.cpp b/code/src/toolboxes/datageneratorbase.cpp index 59ae0ee..d32b33c 100644 --- a/code/src/toolboxes/datageneratorbase.cpp +++ b/code/src/toolboxes/datageneratorbase.cpp @@ -27,7 +27,7 @@ DataGeneratorBase::DataGeneratorBase( Config* settings ) { _setSize = settings->GetTrainingDataSetSize(); _gridSize = _setSize; - _LMaxDegree = settings->GetMaxMomentDegree(); + _maxPolyDegree = settings->GetMaxMomentDegree(); // Check consistency between dimension of quadrature and sample basis if( _settings->GetDim() == 1 ) { @@ -48,7 +48,7 @@ DataGeneratorBase::DataGeneratorBase( Config* settings ) { _quadPointsSphere = _quadrature->GetPointsSphere(); // Spherical Harmonics - if( _settings->GetSphericalBasisName() == SPHERICAL_HARMONICS && _LMaxDegree > 0 ) { + if( _settings->GetSphericalBasisName() == SPHERICAL_HARMONICS && _maxPolyDegree > 0 ) { ErrorMessages::Error( "No sampling algorithm for spherical harmonics basis with degree higher than 0 implemented", CURRENT_FUNCTION ); } _basis = SphericalBase::Create( _settings ); diff --git a/code/tests/test_quadrature.cpp b/code/tests/test_quadrature.cpp index e795af3..10ae57a 100644 --- a/code/tests/test_quadrature.cpp +++ b/code/tests/test_quadrature.cpp @@ -5,13 +5,20 @@ #include -std::vector quadraturenames = { - QUAD_MonteCarlo, QUAD_GaussLegendreTensorized, QUAD_GaussLegendre1D, QUAD_LevelSymmetric, QUAD_Lebedev, QUAD_LDFESA, QUAD_Product }; +std::vector quadraturenames = { QUAD_MonteCarlo, + QUAD_GaussLegendreTensorized, + QUAD_GaussLegendre1D, + QUAD_GaussLegendreTensorized2D, + QUAD_LevelSymmetric, + QUAD_Lebedev, + QUAD_LDFESA, + QUAD_Product }; std::vector> quadratureorders = { { 4, 5, 6, 7 }, // Monte Carlo { 4, 6, 8, 10 }, // Gauss Legendre { 4, 6, 8, 10 }, // Gauss Legendre 1D + { 4, 6, 8, 10 }, // Gauss Legendre 2D { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 }, // Available Orders for LevelSymmetric { 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 35, 41, 47, 53, 59, 65, 71, 77, 83, 89, 95, 101, 107, 113, 119, 125, 131 }, // Available orders for Lebedev @@ -67,8 +74,9 @@ TEST_CASE( "Quadrature Tests", "[quadrature]" ) { config->SetQuadName( quadraturename ); lowAccuracyTesting = false; - if( quadraturename == QUAD_GaussLegendreTensorized || quadraturename == QUAD_GaussLegendre1D || quadraturename == QUAD_LevelSymmetric || - quadraturename == QUAD_Lebedev || quadraturename == QUAD_LDFESA || quadraturename == QUAD_Product ) + if( quadraturename == QUAD_GaussLegendreTensorized || quadraturename == QUAD_GaussLegendre1D || + quadraturename == QUAD_GaussLegendreTensorized2D || quadraturename == QUAD_LevelSymmetric || quadraturename == QUAD_Lebedev || + quadraturename == QUAD_LDFESA || quadraturename == QUAD_Product ) lowAccuracyTesting = true; for( auto quadratureorder : quadratureorders[quadraturename] ) { @@ -82,14 +90,18 @@ TEST_CASE( "Quadrature Tests", "[quadrature]" ) { testPassed = false; PrintErrorMsg( config, std::abs( Q->SumUpWeights() - 2 ), Q->SumUpWeights(), lowAccuracyTesting ); } - + } + else if( quadraturename == QUAD_GaussLegendreTensorized2D ) { + if( !approxequal( Q->SumUpWeights(), M_PI, lowAccuracyTesting ) ) { + testPassed = false; + PrintErrorMsg( config, std::abs( Q->SumUpWeights() - M_PI ), Q->SumUpWeights(), lowAccuracyTesting ); + } } else { if( !approxequal( Q->SumUpWeights(), 4 * M_PI, lowAccuracyTesting ) ) { testPassed = false; PrintErrorMsg( config, std::abs( Q->SumUpWeights() - 4 * M_PI ), Q->SumUpWeights(), lowAccuracyTesting ); } - } // Special case for Gauss Legendre with half weights if( quadraturename == QUAD_GaussLegendreTensorized ) { @@ -118,11 +130,13 @@ TEST_CASE( "Quadrature Tests", "[quadrature]" ) { config->SetQuadName( quadraturename ); lowAccuracyTesting = false; - if( quadraturename == QUAD_GaussLegendreTensorized || quadraturename == QUAD_GaussLegendre1D || quadraturename == QUAD_LevelSymmetric || - quadraturename == QUAD_Lebedev || quadraturename == QUAD_LDFESA ) + if( quadraturename == QUAD_GaussLegendreTensorized || quadraturename == QUAD_GaussLegendre1D || + quadraturename == QUAD_GaussLegendreTensorized2D || quadraturename == QUAD_LevelSymmetric || quadraturename == QUAD_Lebedev || + quadraturename == QUAD_LDFESA ) lowAccuracyTesting = true; - if( quadraturename == QUAD_GaussLegendre1D ) continue; // 1D test case not meaningful here + if( quadraturename == QUAD_GaussLegendre1D || quadraturename == QUAD_GaussLegendreTensorized2D ) + continue; // 1D and 2D test case not meaningful here for( auto quadratureorder : quadratureorders[quadraturename] ) { // Set quadOrder @@ -233,7 +247,13 @@ TEST_CASE( "Quadrature Tests", "[quadrature]" ) { testPassed = false; PrintErrorMsg( config, std::abs( result - 0 ), result, lowAccuracyTesting ); } - + } + else if( quadraturename == QUAD_GaussLegendreTensorized2D ) { + result = Q->Integrate( sin ); + if( !approxequal( result, 0, lowAccuracyTesting ) ) { + testPassed = false; + PrintErrorMsg( config, std::abs( result - 0 ), result, lowAccuracyTesting ); + } } else { result = Q->Integrate( f ); @@ -241,7 +261,6 @@ TEST_CASE( "Quadrature Tests", "[quadrature]" ) { testPassed = false; PrintErrorMsg( config, std::abs( result - 4.0 * M_PI ), result, lowAccuracyTesting ); } - } // Special case for Gauss Legendre with half weights @@ -256,7 +275,6 @@ TEST_CASE( "Quadrature Tests", "[quadrature]" ) { printf( "Reduced number of quadrature was points used. \n" ); } - config->SetSNAllGaussPts( true ); } } @@ -295,12 +313,14 @@ TEST_CASE( "Quadrature Tests", "[quadrature]" ) { printf( "y component incorrectly computed.\n" ); printf( "Faulty index is %d.\n", idx_nq ); } - result = Omega_z( pointsSphere[idx_nq][0], pointsSphere[idx_nq][1] ); - if( !approxequal( points[idx_nq][2], result, lowAccuracyTesting ) ) { - testPassed = false; - PrintErrorMsg( config, std::abs( result - points[idx_nq][2] ), result, lowAccuracyTesting ); - printf( "z component incorrectly computed.\n" ); - printf( "Faulty index is %d.\n", idx_nq ); + if( quadraturename != QUAD_GaussLegendreTensorized2D ) { + result = Omega_z( pointsSphere[idx_nq][0], pointsSphere[idx_nq][1] ); + if( !approxequal( points[idx_nq][2], result, lowAccuracyTesting ) ) { + testPassed = false; + PrintErrorMsg( config, std::abs( result - points[idx_nq][2] ), result, lowAccuracyTesting ); + printf( "z component incorrectly computed.\n" ); + printf( "Faulty index is %d.\n", idx_nq ); + } } } delete Q; @@ -335,7 +355,8 @@ TEST_CASE( "Quadrature Tests", "[quadrature]" ) { QuadratureBase* Q = QuadratureBase::Create( config ); // Note: Leaving out Quad_GaussLegendreTensorized with half weights... (to be added) - if( quadraturename != QUAD_GaussLegendre1D && quadraturename != QUAD_MonteCarlo ) // MonteCarlo is too low order... + if( quadraturename != QUAD_GaussLegendreTensorized2D && quadraturename != QUAD_GaussLegendre1D && + quadraturename != QUAD_MonteCarlo ) // MonteCarlo is too low order... { if( quadraturename == QUAD_LevelSymmetric && quadratureorder == 20 ) continue; // Order 20 is somehow errorous result = Q->IntegrateSpherical( Omega_0 ); -- GitLab From a8cff6fc7e19906fa7366d6d60095bd66a126fc1 Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Mon, 22 Mar 2021 11:58:26 +0100 Subject: [PATCH 58/67] Remove CSD in cfg Former-commit-id: ea42e3e6a416efb76f8bf0e39933fa2f8be3a9f9 --- code/input/pointSource_sph_csd.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/code/input/pointSource_sph_csd.cfg b/code/input/pointSource_sph_csd.cfg index c5988b1..eda1cde 100644 --- a/code/input/pointSource_sph_csd.cfg +++ b/code/input/pointSource_sph_csd.cfg @@ -4,7 +4,6 @@ LOG_DIR = ../result/logs MESH_FILE = phantom2D_fine.su2 PROBLEM = ISOTROPICPOINTSOURCE2D SOLVER = CSD_SN_FOKKERPLANCK_TRAFO_SH_SOLVER_2D -CONTINUOUS_SLOWING_DOWN = YES HYDROGEN_FILE = ENDL_H.txt OXYGEN_FILE = ENDL_O.txt KERNEL = ISOTROPIC -- GitLab From 97a035864bb855379056e49349d2b6222bc4052b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Sat, 27 Mar 2021 12:23:18 +0100 Subject: [PATCH 59/67] implemented dimension reduction strategies Former-commit-id: 300652ecd75413ee05769dc68ef3644bd74ee13a --- code/include/toolboxes/datageneratorbase.h | 3 ++- code/input/DataGenerator1D.cfg | 6 +++--- code/src/optimizers/newtonoptimizer.cpp | 4 ++++ code/src/toolboxes/datagenerator1D.cpp | 22 +++++++++++----------- code/src/toolboxes/datagenerator2D.cpp | 7 ++++--- code/src/toolboxes/datagenerator3D.cpp | 2 ++ code/src/toolboxes/datageneratorbase.cpp | 17 +++++++++++++++++ 7 files changed, 43 insertions(+), 18 deletions(-) diff --git a/code/include/toolboxes/datageneratorbase.h b/code/include/toolboxes/datageneratorbase.h index b6d9d3c..f7b86e9 100644 --- a/code/include/toolboxes/datageneratorbase.h +++ b/code/include/toolboxes/datageneratorbase.h @@ -52,7 +52,7 @@ class DataGeneratorBase _gridSize; /*!< @brief Size of the grid discretizing moment U0 for higher order sampling (has different uses for different samplers)*/ unsigned short _maxPolyDegree; /*!< @brief Max Order of Spherical Harmonics */ - unsigned _nTotalEntries; /*!< @brief Total number of equations in the system */ + unsigned _nTotalEntries; /*!< @brief Total number of equations in the system */ QuadratureBase* _quadrature; /*!< @brief quadrature to create members below */ unsigned _nq; /*!< @brief number of quadrature points */ @@ -80,5 +80,6 @@ class DataGeneratorBase virtual void ComputeMoments() = 0; /*!< @brief Pre-Compute Moments at all quadrature points. */ virtual void CheckRealizability() = 0; /*!< @brief Debugging helper. Will be removed */ virtual void ComputeSetSize() = 0; /*!< @brief Computes the size of the training set, depending on the chosen settings.*/ + void AdaptBasisSize(); /*!< @brief In case of normal sampling, deletes zero order basis for dimension reduction. */ }; #endif // DATAGENERATOR_H diff --git a/code/input/DataGenerator1D.cfg b/code/input/DataGenerator1D.cfg index 75a5673..752dd83 100644 --- a/code/input/DataGenerator1D.cfg +++ b/code/input/DataGenerator1D.cfg @@ -7,20 +7,20 @@ % % ---- Datagenerator settings ---- DATA_GENERATOR_MODE = YES -TRAINING_SET_SIZE = 100000 +TRAINING_SET_SIZE = 100 MAX_VALUE_FIRST_MOMENT = 1 SPATIAL_DIM = 1 REALIZABLE_SET_EPSILON_U1 = 0.003 REALIZABLE_SET_EPSILON_U0 = 0.003 NORMALIZED_SAMPLING = YES -MAX_MOMENT_SOLVER = 1 +MAX_MOMENT_SOLVER = 2 % % ---- File specifications ---- % % Output directory OUTPUT_DIR = ../result % Output file -OUTPUT_FILE = trainM01D +OUTPUT_FILE = trainM11D % Log directory LOG_DIR = ../result/logs LOG_FILE = dataGen1D diff --git a/code/src/optimizers/newtonoptimizer.cpp b/code/src/optimizers/newtonoptimizer.cpp index 1050c27..e686480 100644 --- a/code/src/optimizers/newtonoptimizer.cpp +++ b/code/src/optimizers/newtonoptimizer.cpp @@ -9,6 +9,7 @@ #include "entropies/entropybase.h" #include "quadratures/quadraturebase.h" #include "toolboxes/errormessages.h" +#include "toolboxes/textprocessingtoolbox.h" #include @@ -82,6 +83,9 @@ void NewtonOptimizer::SolveMultiCell( VectorVector& alpha, VectorVector& sol, co #pragma omp parallel for schedule( guided ) for( unsigned idx_cell = 0; idx_cell < nCells; idx_cell++ ) { + // std::cout << "Sol Vector" + // << "|" << sol[idx_cell] << "\n"; + Solve( alpha[idx_cell], sol[idx_cell], moments, idx_cell ); // if( idx_cell % 10000 == 0 ) { // printf( "%d\n", idx_cell ); diff --git a/code/src/toolboxes/datagenerator1D.cpp b/code/src/toolboxes/datagenerator1D.cpp index 85455a4..825d4d4 100644 --- a/code/src/toolboxes/datagenerator1D.cpp +++ b/code/src/toolboxes/datagenerator1D.cpp @@ -16,6 +16,8 @@ DataGenerator1D::DataGenerator1D( Config* settings ) : DataGeneratorBase( settings ) { ComputeMoments(); + AdaptBasisSize(); + // Initialize Training Data ComputeSetSize(); @@ -140,8 +142,8 @@ void DataGenerator1D::SampleSolutionU() { double dN = 2.0 / (double)_gridSize; double N1 = -1.0 + _settings->GetRealizableSetEpsilonU0(); while( N1 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { - _uSol[c][0] = 1; // u0 (normalized i.e. N0) by Monreals notation - _uSol[c][1] = N1; // u1 (normalized i.e. N1) by Monreals notation + + _uSol[c][0] = N1; // u1 (normalized i.e. N1) by Monreals notation N1 += dN; c++; } @@ -155,9 +157,8 @@ void DataGenerator1D::SampleSolutionU() { while( N1 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { N2 = N1 * N1 + _settings->GetRealizableSetEpsilonU0(); while( N2 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { - _uSol[c][0] = 1; // u0 (normalized i.e. N0) by Monreals notation - _uSol[c][1] = N1; // u1 (normalized i.e. N1) by Monreals notation - _uSol[c][2] = N2; // u2 (normalized i.e. N2) by Monreals notation + _uSol[c][0] = N1; // u1 (normalized i.e. N1) by Monreals notation + _uSol[c][1] = N2; // u2 (normalized i.e. N2) by Monreals notation N2 += dN; c++; } @@ -174,10 +175,9 @@ void DataGenerator1D::SampleSolutionU() { while( N2 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { N3 = -N2 + ( N1 + N2 ) * ( N1 + N2 ) / ( 1 + N1 ) + _settings->GetRealizableSetEpsilonU1(); while( N3 < N2 - ( N1 - N2 ) * ( N1 - N2 ) / ( 1 - N1 ) - _settings->GetRealizableSetEpsilonU1() ) { - _uSol[c][0] = 1; // u0 by Monreals notation - _uSol[c][1] = N1; // u1 by Monreals notation - _uSol[c][2] = N2; // u2 by Monreals notation - _uSol[c][3] = N3; // u3 by Monreals notation + _uSol[c][0] = N1; // u1 by Monreals notation + _uSol[c][1] = N2; // u2 by Monreals notation + _uSol[c][2] = N3; // u3 by Monreals notation c++; N3 += dN; } @@ -294,7 +294,7 @@ void DataGenerator1D::ComputeSetSize() { } else if( _maxPolyDegree == 2 ) { // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1 - unsigned c = 1; + unsigned c = 0; double N1 = -1.0 + _settings->GetRealizableSetEpsilonU0(); double N2; double dN = 2.0 / (double)_gridSize; @@ -310,7 +310,7 @@ void DataGenerator1D::ComputeSetSize() { } else if( _maxPolyDegree == 3 ) { // Carefull: This computes only normalized moments, i.e. sampling for u_0 = 1, N1=0 - unsigned c = 1; + unsigned c = 0; double N1 = 0 + _settings->GetRealizableSetEpsilonU0(); double N2, N3; double dN = 1.0 / (double)_gridSize; diff --git a/code/src/toolboxes/datagenerator2D.cpp b/code/src/toolboxes/datagenerator2D.cpp index 80ddab4..34642cb 100644 --- a/code/src/toolboxes/datagenerator2D.cpp +++ b/code/src/toolboxes/datagenerator2D.cpp @@ -16,6 +16,8 @@ DataGenerator2D::DataGenerator2D( Config* settings ) : DataGeneratorBase( settings ) { ComputeMoments(); + AdaptBasisSize(); + // Initialize Training Data ComputeSetSize(); @@ -71,9 +73,8 @@ void DataGenerator2D::SampleSolutionU() { continue; } else { - _uSol[idx_set][0] = 1.0; - _uSol[idx_set][1] = std::sqrt( 1 - mu * mu ) * std::cos( phi ); - _uSol[idx_set][2] = std::sqrt( 1 - mu * mu ) * std::sin( phi ); + _uSol[idx_set][0] = std::sqrt( 1 - mu * mu ) * std::cos( phi ); + _uSol[idx_set][1] = std::sqrt( 1 - mu * mu ) * std::sin( phi ); } } } diff --git a/code/src/toolboxes/datagenerator3D.cpp b/code/src/toolboxes/datagenerator3D.cpp index 3dfdaf6..19647df 100644 --- a/code/src/toolboxes/datagenerator3D.cpp +++ b/code/src/toolboxes/datagenerator3D.cpp @@ -16,6 +16,8 @@ DataGenerator3D::DataGenerator3D( Config* settings ) : DataGeneratorBase( settings ) { ComputeMoments(); + AdaptBasisSize(); + // Initialize Training Data ComputeSetSize(); diff --git a/code/src/toolboxes/datageneratorbase.cpp b/code/src/toolboxes/datageneratorbase.cpp index d32b33c..a04701c 100644 --- a/code/src/toolboxes/datageneratorbase.cpp +++ b/code/src/toolboxes/datageneratorbase.cpp @@ -92,6 +92,7 @@ void DataGeneratorBase::ComputeTrainingData() { CheckRealizability(); // --- compute alphas --- + _optimizer->SolveMultiCell( _alpha, _uSol, _moments ); log->info( "| Making moments realizable problems." ); @@ -199,3 +200,19 @@ void DataGeneratorBase::PrintLoadScreen() { log->info( "------------------------ Data Generation Starts --------------------------" ); log->info( "| Generating {} datapoints.", _setSize ); } + +void DataGeneratorBase::AdaptBasisSize() { + // Remove zero order Moment for dimension reduction + + if( _settings->GetNormalizedSampling() ) { + VectorVector momentTemp = _moments; + _nTotalEntries = _nTotalEntries - 1; + _moments = VectorVector( _nq, Vector( _nTotalEntries, 0.0 ) ); + + for( unsigned idx_quad = 0; idx_quad < _nq; idx_quad++ ) { + for( unsigned idx_sys = 0; idx_sys < _nTotalEntries; idx_sys++ ) { + _moments[idx_quad][idx_sys] = momentTemp[idx_quad][idx_sys + 1]; + } + } + } +} -- GitLab From c6b5877d1627077c4b6f4f888cd70f862b18d605 Mon Sep 17 00:00:00 2001 From: Tianbai Xiao Date: Sun, 28 Mar 2021 22:54:28 +0200 Subject: [PATCH 60/67] Set default sigmas=1 in line source case Former-commit-id: 30154592e91e52cb43e7a5ed987f94e9f6bbcd62 --- code/input/linesource_SN.cfg | 2 +- code/src/common/config.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/input/linesource_SN.cfg b/code/input/linesource_SN.cfg index a4eb0d0..8255eb9 100644 --- a/code/input/linesource_SN.cfg +++ b/code/input/linesource_SN.cfg @@ -27,7 +27,7 @@ CFL_NUMBER = 0.7 % Final time for simulation TIME_FINAL = 0.5 % Reconstruction order -RECONS_ORDER = 2 +RECONS_ORDER = 1 % % ---- Boundary Conditions ---- diff --git a/code/src/common/config.cpp b/code/src/common/config.cpp index 70fc7b3..eee06f7 100644 --- a/code/src/common/config.cpp +++ b/code/src/common/config.cpp @@ -260,7 +260,7 @@ void Config::SetConfigOptions() { // Linesource Testcase Options /*! @brief SCATTER_COEFF \n DESCRIPTION: Sets the scattering coefficient for the Linesource test case. \n DEFAULT 0.0 \ingroup Config */ - AddDoubleOption( "SCATTER_COEFF", _sigmaS, 0.0 ); + AddDoubleOption( "SCATTER_COEFF", _sigmaS, 1.0 ); // CSD related options /*! @brief MAX_ENERGY_CSD \n DESCRIPTION: Sets maximum energy for the CSD simulation.\n DEFAULT \ingroup Config */ -- GitLab From 0bc4098cd996a01e35c628eba43449b5a455e680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Fri, 9 Apr 2021 20:47:52 +0200 Subject: [PATCH 61/67] remove python submodule Former-commit-id: cfd730f2e202ef2c7a5bd67083955609dad68cba --- .gitmodules | 3 --- code/ext/Catch2 | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.gitmodules b/.gitmodules index b00681c..74d819b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,6 +7,3 @@ [submodule "code/ext/blaze"] path = code/ext/blaze url = https://bitbucket.org/blaze-lib/blaze.git -[submodule "code/ext/neuralEntropy"] - path = code/ext/neuralEntropy - url = https://github.com/ScSteffen/neuralEntropy.git diff --git a/code/ext/Catch2 b/code/ext/Catch2 index 0e9bae1..e8cdfdc 160000 --- a/code/ext/Catch2 +++ b/code/ext/Catch2 @@ -1 +1 @@ -Subproject commit 0e9bae1cdb5d7bcd967bcab10539805cc3bccb32 +Subproject commit e8cdfdca87ebacd993befdd08ea6aa7e8068ef3d -- GitLab From 6bd89c3deaf3f53aaa90d62e82724a4334763969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Wed, 14 Apr 2021 11:16:37 +0200 Subject: [PATCH 62/67] removed basis reduction Former-commit-id: dceec7214d31e610fa928115bb3c4f89be2c7d30 --- code/ext/neuralEntropy | 1 - code/src/toolboxes/datagenerator1D.cpp | 18 ++++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) delete mode 160000 code/ext/neuralEntropy diff --git a/code/ext/neuralEntropy b/code/ext/neuralEntropy deleted file mode 160000 index c17aef3..0000000 --- a/code/ext/neuralEntropy +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c17aef38149a57d92781c91643375fd891d2a4cb diff --git a/code/src/toolboxes/datagenerator1D.cpp b/code/src/toolboxes/datagenerator1D.cpp index 825d4d4..af428df 100644 --- a/code/src/toolboxes/datagenerator1D.cpp +++ b/code/src/toolboxes/datagenerator1D.cpp @@ -16,7 +16,7 @@ DataGenerator1D::DataGenerator1D( Config* settings ) : DataGeneratorBase( settings ) { ComputeMoments(); - AdaptBasisSize(); + // AdaptBasisSize(); // Initialize Training Data ComputeSetSize(); @@ -142,8 +142,8 @@ void DataGenerator1D::SampleSolutionU() { double dN = 2.0 / (double)_gridSize; double N1 = -1.0 + _settings->GetRealizableSetEpsilonU0(); while( N1 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { - - _uSol[c][0] = N1; // u1 (normalized i.e. N1) by Monreals notation + _uSol[c][0] = 1; // u0 (normalized i.e. N0) by Monreals notation + _uSol[c][1] = N1; // u1 (normalized i.e. N1) by Monreals notation N1 += dN; c++; } @@ -157,8 +157,9 @@ void DataGenerator1D::SampleSolutionU() { while( N1 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { N2 = N1 * N1 + _settings->GetRealizableSetEpsilonU0(); while( N2 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { - _uSol[c][0] = N1; // u1 (normalized i.e. N1) by Monreals notation - _uSol[c][1] = N2; // u2 (normalized i.e. N2) by Monreals notation + _uSol[c][0] = 1; // u0 (normalized i.e. N0) by Monreals notation + _uSol[c][1] = N1; // u1 (normalized i.e. N1) by Monreals notation + _uSol[c][2] = N2; // u2 (normalized i.e. N2) by Monreals notation N2 += dN; c++; } @@ -175,9 +176,10 @@ void DataGenerator1D::SampleSolutionU() { while( N2 < 1.0 - _settings->GetRealizableSetEpsilonU0() ) { N3 = -N2 + ( N1 + N2 ) * ( N1 + N2 ) / ( 1 + N1 ) + _settings->GetRealizableSetEpsilonU1(); while( N3 < N2 - ( N1 - N2 ) * ( N1 - N2 ) / ( 1 - N1 ) - _settings->GetRealizableSetEpsilonU1() ) { - _uSol[c][0] = N1; // u1 by Monreals notation - _uSol[c][1] = N2; // u2 by Monreals notation - _uSol[c][2] = N3; // u3 by Monreals notation + _uSol[c][0] = 1; // u0 by Monreals notation + _uSol[c][1] = N1; // u1 by Monreals notation + _uSol[c][2] = N2; // u2 by Monreals notation + _uSol[c][3] = N3; // u3 by Monreals notation c++; N3 += dN; } -- GitLab From 34264bbaefd1ab049201f422a0ae6a01c3f7e2a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schotth=C3=B6fer?= Date: Fri, 16 Apr 2021 12:52:40 +0200 Subject: [PATCH 63/67] now able to sample multipliers alpha and able to sample without realizability reconstruction Former-commit-id: c0c71a9b9c2c46b68512e75cee92bb3e2a17fdf9 --- code/include/common/config.h | 4 + code/include/toolboxes/datageneratorbase.h | 1 + code/input/DataGenerator1D.cfg | 11 ++- code/src/common/config.cpp | 8 +- code/src/toolboxes/datageneratorbase.cpp | 90 +++++++++++++++++++--- 5 files changed, 97 insertions(+), 17 deletions(-) diff --git a/code/include/common/config.h b/code/include/common/config.h index 6211bcd..420b143 100644 --- a/code/include/common/config.h +++ b/code/include/common/config.h @@ -128,6 +128,8 @@ class Config double _RealizableSetEpsilonU0; /*!< @brief Distance to 0 of the sampled moments to the boundary of the realizable set */ double _RealizableSetEpsilonU1; /*!< @brief norm(u_1)/u_0 !< _RealizableSetEpsilonU1 */ bool _normalizedSampling; /*!< @brief Flag for sampling of normalized moments, i.e. u_0 =1 */ + bool _alphaSampling; /*!< @brief Flag for sampling alpha instead of u */ + bool _realizabilityRecons; /*!< @brief Turns realizability reconstruction on/off for u sampling */ // --- Parsing Functionality and Initializing of Options --- /*! @@ -326,6 +328,8 @@ class Config double GetRealizableSetEpsilonU0() { return _RealizableSetEpsilonU0; } double GetRealizableSetEpsilonU1() { return _RealizableSetEpsilonU1; } bool inline GetNormalizedSampling() { return _normalizedSampling; } + bool inline GetAlphaSampling() { return _alphaSampling; } + bool inline GetRelizabilityReconsU() { return _realizabilityRecons; } // ---- Setters for option structure // This section is dangerous diff --git a/code/include/toolboxes/datageneratorbase.h b/code/include/toolboxes/datageneratorbase.h index f7b86e9..d865296 100644 --- a/code/include/toolboxes/datageneratorbase.h +++ b/code/include/toolboxes/datageneratorbase.h @@ -68,6 +68,7 @@ class DataGeneratorBase // Main methods virtual void SampleSolutionU() = 0; /*!< @brief Samples solution vectors u */ + void SampleMultiplierAlpha(); /*!< @brief Sample Lagrange multipliers alpha */ void ComputeEntropyH_dual(); /*!< @brief Compute the entropy functional at (u,alpha) in dual formulation */ void ComputeEntropyH_primal(); /*!< @brief Compute the entropy functional at (u,alpha) in primal formulation */ void ComputeRealizableSolution(); /*!< @brief make u the realizable moment to alpha, since Newton has roundoff errors. */ diff --git a/code/input/DataGenerator1D.cfg b/code/input/DataGenerator1D.cfg index 752dd83..6d8141e 100644 --- a/code/input/DataGenerator1D.cfg +++ b/code/input/DataGenerator1D.cfg @@ -7,13 +7,16 @@ % % ---- Datagenerator settings ---- DATA_GENERATOR_MODE = YES -TRAINING_SET_SIZE = 100 +TRAINING_SET_SIZE = 100000 MAX_VALUE_FIRST_MOMENT = 1 SPATIAL_DIM = 1 -REALIZABLE_SET_EPSILON_U1 = 0.003 -REALIZABLE_SET_EPSILON_U0 = 0.003 +MAX_MOMENT_SOLVER = 1 +REALIZABLE_SET_EPSILON_U1 = 0.01 +REALIZABLE_SET_EPSILON_U0 = 0.01 NORMALIZED_SAMPLING = YES -MAX_MOMENT_SOLVER = 2 +ALPHA_SAMPLING = YES +REALIZABILITY_RECONS_U = NO + % % ---- File specifications ---- % diff --git a/code/src/common/config.cpp b/code/src/common/config.cpp index eee06f7..09cc41d 100644 --- a/code/src/common/config.cpp +++ b/code/src/common/config.cpp @@ -334,6 +334,12 @@ void Config::SetConfigOptions() { /*! @brief Flag for sampling of normalized moments, i.e. u_0 =1 \n DESCRIPTION: Flag for sampling of normalized moments, i.e. u_0 =1 \n * DEFAULT False \ingroup Config */ AddBoolOption( "NORMALIZED_SAMPLING", _normalizedSampling, false ); + /*! @brief Flag for sampling the space of Legendre multipliers instead of the moments \n DESCRIPTION: Sample alpha instead of u \n DEFAULT False + * \ingroup Config */ + AddBoolOption( "ALPHA_SAMPLING", _alphaSampling, false ); + /*! @brief Flag for sampling the space of Legendre multipliers instead of the moments \n DESCRIPTION: Sample alpha instead of u \n DEFAULT False + * \ingroup Config */ + AddBoolOption( "REALIZABILITY_RECONS_U", _realizabilityRecons, true ); } void Config::SetConfigParsing( string case_filename ) { @@ -694,7 +700,7 @@ bool Config::TokenizeString( string& str, string& option_name, vector& o pos = str.find( "=" ); if( pos == string::npos ) { string errmsg = "Error in Config::TokenizeString(): line in the configuration file with no \"=\" sign. "; - errmsg += "\nLook for: \n str.length() = " + std::to_string(str.length()); + errmsg += "\nLook for: \n str.length() = " + std::to_string( str.length() ); spdlog::error( errmsg ); throw( -1 ); } diff --git a/code/src/toolboxes/datageneratorbase.cpp b/code/src/toolboxes/datageneratorbase.cpp index a04701c..0c286f7 100644 --- a/code/src/toolboxes/datageneratorbase.cpp +++ b/code/src/toolboxes/datageneratorbase.cpp @@ -81,24 +81,38 @@ DataGeneratorBase* DataGeneratorBase::Create( Config* settings ) { void DataGeneratorBase::ComputeTrainingData() { PrintLoadScreen(); - - // --- sample u --- - SampleSolutionU(); auto log = spdlog::get( "event" ); - log->info( "| Moments sampled." ); - log->info( "| Start solving the optimization problems. This may take some minutes." ); - // ---- Check realizability --- - CheckRealizability(); + if( _settings->GetAlphaSampling() ) { + // --- sample alpha --- + SampleMultiplierAlpha(); + log->info( "| Multipliers sampled." ); + + log->info( "| Making moments realizable problems." ); - // --- compute alphas --- + // --- Postprocessing + ComputeRealizableSolution(); + } + else { + // --- sample u --- + SampleSolutionU(); + log->info( "| Moments sampled." ); + log->info( "| Start solving the optimization problems. This may take some minutes." ); - _optimizer->SolveMultiCell( _alpha, _uSol, _moments ); + // ---- Check realizability --- + CheckRealizability(); - log->info( "| Making moments realizable problems." ); + // --- compute alphas --- - // --- Postprocessing - ComputeRealizableSolution(); + _optimizer->SolveMultiCell( _alpha, _uSol, _moments ); + + log->info( "| Making moments realizable problems." ); + + // --- Postprocessing + if( _settings->GetRelizabilityReconsU() ) { + ComputeRealizableSolution(); + } + } log->info( "| Compute entropies." ); @@ -111,6 +125,58 @@ void DataGeneratorBase::ComputeTrainingData() { PrintTrainingData(); } +void DataGeneratorBase::SampleMultiplierAlpha() { + double minAlphaValue = -50; + double maxAlphaValue = 50; + + if( _settings->GetNormalizedSampling() ) { + // compute reduced version of alpha and m + if( _maxPolyDegree == 0 ) { + ErrorMessages::Error( "Normalized sampling not meaningful for M0 closure", CURRENT_FUNCTION ); + } + VectorVector alphaRed = VectorVector( _setSize, Vector( _nTotalEntries - 1, 0.0 ) ); + VectorVector momentsRed = VectorVector( _nq, Vector( _nTotalEntries - 1, 0.0 ) ); + + for( unsigned idx_nq = 0; idx_nq < _nq; idx_nq++ ) { // copy (reduced) moments + for( unsigned idx_sys = 1; idx_sys < _nTotalEntries; idx_sys++ ) { + momentsRed[idx_nq][idx_sys - 1] = _moments[idx_nq][idx_sys]; + } + } + double dalpha = 0; + switch( _maxPolyDegree ) { + case 1: + // Sample alpha1 from [minAlphaValue, maxAlphaValue], then compute alpha_0 s.t. u_0 = 1 + dalpha = ( maxAlphaValue - minAlphaValue ) / (double)_setSize; + + for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { + alphaRed[idx_set][0] = minAlphaValue + idx_set * dalpha; + } + break; + default: ErrorMessages::Error( "Not yet implemented!", CURRENT_FUNCTION ); + } + + // Compute alpha_0 = log() // for maxwell boltzmann! only + for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { + double integral = 0.0; + // Integrate (eta(eta'_*(alpha*m)) + for( unsigned idx_quad = 0; idx_quad < _nq; idx_quad++ ) { + integral += _entropy->EntropyPrimeDual( dot( alphaRed[idx_set], momentsRed[idx_quad] ) ) * _weights[idx_quad]; + } + _alpha[idx_set][0] = -log( integral ); // log trafo + + // copy all other alphas to the member + for( unsigned idx_sys = 1; idx_sys < _nTotalEntries; idx_sys++ ) { + _alpha[idx_set][idx_sys] = alphaRed[idx_set][idx_sys - 1]; + } + } + } + else { + // non normalized sampling + // TODO + ErrorMessages::Error( "Not yet implemented!", CURRENT_FUNCTION ); + } +} + void DataGeneratorBase::ComputeEntropyH_dual() { #pragma omp parallel for schedule( guided ) for( unsigned idx_set = 0; idx_set < _setSize; idx_set++ ) { -- GitLab From 1f6a935e05fcb75edf30d63d5d8b0d50f0ccd523 Mon Sep 17 00:00:00 2001 From: Jannick Wolters Date: Mon, 3 May 2021 11:29:59 +0200 Subject: [PATCH 64/67] added github link --- doc/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/index.rst b/doc/index.rst index 78f4837..9667987 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -14,6 +14,7 @@ A list of current supported models and equations is as follows. - entropy-closure (:math:`M_N`) moment equations - continuous slowing down equation +The source code is publicly available on [Github](https://github.com/CSMMLab/KiT-RT)]. Design philosophy ------------------------ -- GitLab From 9ad1763da36d100a68dc01df08662e5180d73bf1 Mon Sep 17 00:00:00 2001 From: Jannick Wolters Date: Mon, 3 May 2021 11:32:18 +0200 Subject: [PATCH 65/67] fixed typo --- doc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/index.rst b/doc/index.rst index 9667987..83862e2 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -14,7 +14,7 @@ A list of current supported models and equations is as follows. - entropy-closure (:math:`M_N`) moment equations - continuous slowing down equation -The source code is publicly available on [Github](https://github.com/CSMMLab/KiT-RT)]. +The source code is publicly available on [Github](https://github.com/CSMMLab/KiT-RT). Design philosophy ------------------------ -- GitLab From 62b3bda3084da1bb770d3b121123bdc29b70148b Mon Sep 17 00:00:00 2001 From: Jannick Wolters Date: Mon, 3 May 2021 11:36:27 +0200 Subject: [PATCH 66/67] updated rst link def --- doc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/index.rst b/doc/index.rst index 83862e2..6e4fe79 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -14,7 +14,7 @@ A list of current supported models and equations is as follows. - entropy-closure (:math:`M_N`) moment equations - continuous slowing down equation -The source code is publicly available on [Github](https://github.com/CSMMLab/KiT-RT). +The source code is publicly available on `Github `_.` Design philosophy ------------------------ -- GitLab From b0af67003e1910cb45d9d332ba4d60a5ecffa23f Mon Sep 17 00:00:00 2001 From: Jannick Wolters Date: Mon, 3 May 2021 11:37:52 +0200 Subject: [PATCH 67/67] fixed typo --- doc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/index.rst b/doc/index.rst index 6e4fe79..6cf4303 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -14,7 +14,7 @@ A list of current supported models and equations is as follows. - entropy-closure (:math:`M_N`) moment equations - continuous slowing down equation -The source code is publicly available on `Github `_.` +The source code is publicly available on `Github `_. Design philosophy ------------------------ -- GitLab