• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

CSMMLab / KiT-RT / #95

28 May 2025 02:06AM UTC coverage: 46.655% (-11.1%) from 57.728%
#95

push

travis-ci

web-flow
Release 2025 (#44)

* New neural models (#30)

* extend kitrt script

* added new neural models

* extend to m3 models

* added M3_2D models

* added M2 and M4 models

* configure ml optimizer for high order models

* added configuration for high order models

* add option for rotation postprcessing in neural networks. remove unneccessary python scripts

* started rotational symmetric postprocessing

* added rotational invariance postprocessing for m2 and m1 models

* fix post merge bugs

* created hohlraum mesh

* add hohlraum tes case

* add hohlraum test case

* add hohlraum cfg filees

* fixed hohlraum testcase

* add hohlraum cfg files

* changed hohlraum cfg

* changed hohlraum testcase to isotropic inflow source boundary condition

* added ghost cell bonudary for hohlraum testcase

* update readme and linesource mesh creator

* added proper scaling for linesource reference solution

* regularized newton debugging

* Data generator with reduced objective functional (#33)

* added reduced optimizer for sampling

* remove old debugging comments

* mesh acceleration (#38)

* added new ansatz (#36)

* added new ansatz

* debug new ansatz

* branch should be abandoned here

* debug new ansatz

* fix scaling error new ansatz

* fix config errors

* temporarily fixed dynamic ansatz rotation bug

* fix inheritance error for new ansatz

* mesh acceleration

* add structured hohlraum

* Mesh acc (#41)

* mesh acceleration

* added floor value for starmap moment methods

* enable accelleration

* delete minimum value starmap

* Update README.md

* Spherical harmonics nn (#40)

* added new ansatz

* debug new ansatz

* branch should be abandoned here

* debug new ansatz

* fix scaling error new ansatz

* fix config errors

* temporarily fixed dynamic ansatz rotation bug

* fix inheritance error for new ansatz

* mesh acceleration

* add structured hohlraum

* added sph... (continued)

767 of 3019 new or added lines in 51 files covered. (25.41%)

131 existing lines in 8 files now uncovered.

4422 of 9478 relevant lines covered (46.66%)

57163.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/solvers/snsolver_hpc.cpp
1
#ifdef IMPORT_MPI
2
#include <mpi.h>
3
#endif
4
#include "common/config.hpp"
5
#include "common/io.hpp"
6
#include "common/mesh.hpp"
7
#include "kernels/scatteringkernelbase.hpp"
8
#include "problems/problembase.hpp"
9
#include "quadratures/quadraturebase.hpp"
10
#include "solvers/snsolver_hpc.hpp"
11
#include "toolboxes/textprocessingtoolbox.hpp"
12

NEW
13
SNSolverHPC::SNSolverHPC( Config* settings ) {
×
14
#ifdef IMPORT_MPI
15
    // Initialize MPI
16
    MPI_Comm_size( MPI_COMM_WORLD, &_numProcs );
17
    MPI_Comm_rank( MPI_COMM_WORLD, &_rank );
18
#endif
19
#ifndef IMPORT_MPI
NEW
20
    _numProcs = 1;    // default values
×
NEW
21
    _rank     = 0;
×
22
#endif
NEW
23
    _settings       = settings;
×
NEW
24
    _currTime       = 0.0;
×
NEW
25
    _idx_start_iter = 0;
×
NEW
26
    _nOutputMoments = 2;    //  Currently only u_1 (x direction) and u_1 (y direction) are supported
×
27
    // Create Mesh
NEW
28
    _mesh = LoadSU2MeshFromFile( settings );
×
NEW
29
    _settings->SetNCells( _mesh->GetNumCells() );
×
NEW
30
    auto quad = QuadratureBase::Create( settings );
×
NEW
31
    _settings->SetNQuadPoints( quad->GetNq() );
×
32

NEW
33
    _nCells = static_cast<unsigned long>( _mesh->GetNumCells() );
×
NEW
34
    _nNbr   = static_cast<unsigned long>( _mesh->GetNumNodesPerCell() );
×
NEW
35
    _nDim   = static_cast<unsigned long>( _mesh->GetDim() );
×
NEW
36
    _nNodes = static_cast<unsigned long>( _mesh->GetNumNodes() );
×
37

NEW
38
    _nq   = static_cast<unsigned long>( quad->GetNq() );
×
NEW
39
    _nSys = _nq;
×
40

NEW
41
    if( _numProcs > _nq ) {
×
NEW
42
        ErrorMessages::Error( "The number of processors must be less than or equal to the number of quadrature points.", CURRENT_FUNCTION );
×
43
    }
44

NEW
45
    if( _numProcs == 1 ) {
×
NEW
46
        _localNSys   = _nSys;
×
NEW
47
        _startSysIdx = 0;
×
NEW
48
        _endSysIdx   = _nSys;
×
49
    }
50
    else {
NEW
51
        _localNSys   = _nSys / ( _numProcs - 1 );
×
NEW
52
        _startSysIdx = _rank * _localNSys;
×
NEW
53
        _endSysIdx   = _rank * _localNSys + _localNSys;
×
54

NEW
55
        if( _rank == _numProcs - 1 ) {
×
NEW
56
            _localNSys = _nSys - _startSysIdx;
×
NEW
57
            _endSysIdx = _nSys;
×
58
        }
59
    }
60

61
    // std::cout << "Rank: " << _rank << " startSysIdx: " << _startSysIdx << " endSysIdx: " << _endSysIdx <<  " localNSys: " << _localNSys <<
62
    // std::endl;
63

NEW
64
    _spatialOrder  = _settings->GetSpatialOrder();
×
NEW
65
    _temporalOrder = _settings->GetTemporalOrder();
×
66

NEW
67
    _areas                  = std::vector<double>( _nCells );
×
NEW
68
    _normals                = std::vector<double>( _nCells * _nNbr * _nDim );
×
NEW
69
    _neighbors              = std::vector<unsigned>( _nCells * _nNbr );
×
NEW
70
    _cellMidPoints          = std::vector<double>( _nCells * _nDim );
×
NEW
71
    _interfaceMidPoints     = std::vector<double>( _nCells * _nNbr * _nDim );
×
NEW
72
    _cellBoundaryTypes      = std::vector<BOUNDARY_TYPE>( _nCells );
×
NEW
73
    _relativeInterfaceMidPt = std::vector<double>( _nCells * _nNbr * _nDim );
×
NEW
74
    _relativeCellVertices   = std::vector<double>( _nCells * _nNbr * _nDim );
×
75

76
    // Slope
NEW
77
    _solDx   = std::vector<double>( _nCells * _localNSys * _nDim, 0.0 );
×
NEW
78
    _limiter = std::vector<double>( _nCells * _localNSys, 0.0 );
×
79

80
    // Physics
NEW
81
    _sigmaS = std::vector<double>( _nCells );
×
NEW
82
    _sigmaT = std::vector<double>( _nCells );
×
NEW
83
    _source = std::vector<double>( _nCells * _localNSys );
×
84

85
    // Quadrature
NEW
86
    _quadPts     = std::vector<double>( _localNSys * _nDim );
×
NEW
87
    _quadWeights = std::vector<double>( _localNSys );
×
88

89
    // Solution
NEW
90
    _sol  = std::vector<double>( _nCells * _localNSys );
×
NEW
91
    _flux = std::vector<double>( _nCells * _localNSys );
×
92

NEW
93
    _scalarFlux              = std::vector<double>( _nCells );
×
NEW
94
    _localMaxOrdinateOutflow = std::vector<double>( _nCells );
×
95

NEW
96
    auto areas           = _mesh->GetCellAreas();
×
NEW
97
    auto neighbors       = _mesh->GetNeighbours();
×
NEW
98
    auto normals         = _mesh->GetNormals();
×
NEW
99
    auto cellMidPts      = _mesh->GetCellMidPoints();
×
NEW
100
    auto interfaceMidPts = _mesh->GetInterfaceMidPoints();
×
NEW
101
    auto boundaryTypes   = _mesh->GetBoundaryTypes();
×
NEW
102
    auto nodes           = _mesh->GetNodes();
×
NEW
103
    auto cells           = _mesh->GetCells();
×
104

NEW
105
#pragma omp parallel for
×
106
    for( unsigned long idx_cell = 0; idx_cell < _nCells; idx_cell++ ) {
107
        _areas[idx_cell] = areas[idx_cell];
108
    }
109

NEW
110
    _dT    = ComputeTimeStep( _settings->GetCFL() );
×
NEW
111
    _nIter = unsigned( _settings->GetTEnd() / _dT ) + 1;
×
112

NEW
113
    auto quadPoints  = quad->GetPoints();
×
NEW
114
    auto quadWeights = quad->GetWeights();
×
115

NEW
116
    _problem    = ProblemBase::Create( _settings, _mesh, quad );
×
NEW
117
    auto sigmaT = _problem->GetTotalXS( Vector( _nIter, 0.0 ) );
×
NEW
118
    auto sigmaS = _problem->GetScatteringXS( Vector( _nIter, 0.0 ) );
×
NEW
119
    auto source = _problem->GetExternalSource( Vector( _nIter, 0.0 ) );
×
120

121
    // Copy to everything to solver
NEW
122
    _mass = 0;
×
NEW
123
#pragma omp parallel for
×
124
    for( unsigned long idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
125
        for( unsigned long idx_dim = 0; idx_dim < _nDim; idx_dim++ ) {
126
            _quadPts[Idx2D( idx_sys, idx_dim, _nDim )] = quadPoints[idx_sys + _startSysIdx][idx_dim];
127
        }
128
        if( _settings->GetQuadName() == QUAD_GaussLegendreTensorized2D ) {
129
            _quadWeights[idx_sys] =
130
                2.0 * quadWeights[idx_sys + _startSysIdx];    // Rescaling of quadweights TODO: Check if this needs general refactoring
131
        }
132
        else {
133
            _quadWeights[idx_sys] = quadWeights[idx_sys + _startSysIdx];    // Rescaling of quadweights TODO: Check if this needs general refactoring}
134
        }
135
    }
136

NEW
137
#pragma omp parallel for
×
138
    for( unsigned long idx_cell = 0; idx_cell < _nCells; idx_cell++ ) {
139
        _cellBoundaryTypes[idx_cell] = boundaryTypes[idx_cell];
140

141
        for( unsigned long idx_dim = 0; idx_dim < _nDim; idx_dim++ ) {
142
            _cellMidPoints[Idx2D( idx_cell, idx_dim, _nDim )] = cellMidPts[idx_cell][idx_dim];
143
        }
144

145
        for( unsigned long idx_nbr = 0; idx_nbr < _nNbr; idx_nbr++ ) {
146

147
            _neighbors[Idx2D( idx_cell, idx_nbr, _nNbr )] = neighbors[idx_cell][idx_nbr];
148

149
            for( unsigned long idx_dim = 0; idx_dim < _nDim; idx_dim++ ) {
150
                _normals[Idx3D( idx_cell, idx_nbr, idx_dim, _nNbr, _nDim )]            = normals[idx_cell][idx_nbr][idx_dim];
151
                _interfaceMidPoints[Idx3D( idx_cell, idx_nbr, idx_dim, _nNbr, _nDim )] = interfaceMidPts[idx_cell][idx_nbr][idx_dim];
152
                _relativeInterfaceMidPt[Idx3D( idx_cell, idx_nbr, idx_dim, _nNbr, _nDim )] =
153
                    _interfaceMidPoints[Idx3D( idx_cell, idx_nbr, idx_dim, _nNbr, _nDim )] - _cellMidPoints[Idx2D( idx_cell, idx_dim, _nDim )];
154
                _relativeCellVertices[Idx3D( idx_cell, idx_nbr, idx_dim, _nNbr, _nDim )] =
155
                    nodes[cells[idx_cell][idx_nbr]][idx_dim] - cellMidPts[idx_cell][idx_dim];
156
            }
157
        }
158

159
        _sigmaS[idx_cell]     = sigmaS[0][idx_cell];
160
        _sigmaT[idx_cell]     = sigmaT[0][idx_cell];
161
        _scalarFlux[idx_cell] = 0;
162

163
        for( unsigned long idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
164
            _source[Idx2D( idx_cell, idx_sys, _localNSys )] = source[0][idx_cell][0];    // CAREFUL HERE hardcoded to isotropic source
165
            _sol[Idx2D( idx_cell, idx_sys, _localNSys )]    = 0.0;                       // initial condition is zero
166

167
            _scalarFlux[idx_cell] += _sol[Idx2D( idx_cell, idx_sys, _localNSys )] * _quadWeights[idx_sys];
168
        }
169
        // _mass += _scalarFlux[idx_cell] * _areas[idx_cell];
170
    }
171

172
    // Lattice
173
    {
NEW
174
        _curAbsorptionLattice    = 0;
×
NEW
175
        _totalAbsorptionLattice  = 0;
×
NEW
176
        _curMaxAbsorptionLattice = 0;
×
NEW
177
        _curScalarOutflow        = 0;
×
NEW
178
        _totalScalarOutflow      = 0;
×
NEW
179
        _curMaxOrdinateOutflow   = 0;
×
NEW
180
        _curScalarOutflowPeri1   = 0;
×
NEW
181
        _totalScalarOutflowPeri1 = 0;
×
NEW
182
        _curScalarOutflowPeri2   = 0;
×
NEW
183
        _totalScalarOutflowPeri2 = 0;
×
NEW
184
        ComputeCellsPerimeterLattice();
×
185
    }
186
    // Hohlraum
187
    {
NEW
188
        _totalAbsorptionHohlraumCenter     = 0;
×
NEW
189
        _totalAbsorptionHohlraumVertical   = 0;
×
NEW
190
        _totalAbsorptionHohlraumHorizontal = 0;
×
NEW
191
        _curAbsorptionHohlraumCenter       = 0;
×
NEW
192
        _curAbsorptionHohlraumVertical     = 0;
×
NEW
193
        _curAbsorptionHohlraumHorizontal   = 0;
×
NEW
194
        _varAbsorptionHohlraumGreen        = 0;
×
195
    }
196

NEW
197
    if( _settings->GetLoadRestartSolution() )
×
NEW
198
        _idx_start_iter = LoadRestartSolution( _settings->GetOutputFile(),
×
NEW
199
                                               _sol,
×
NEW
200
                                               _scalarFlux,
×
201
                                               _rank,
202
                                               _nCells,
NEW
203
                                               _totalAbsorptionHohlraumCenter,
×
NEW
204
                                               _totalAbsorptionHohlraumVertical,
×
NEW
205
                                               _totalAbsorptionHohlraumHorizontal,
×
NEW
206
                                               _totalAbsorptionLattice ) +
×
207
                          1;
208

209
#ifdef IMPORT_MPI
210
    MPI_Barrier( MPI_COMM_WORLD );
211
#endif
NEW
212
    SetGhostCells();
×
NEW
213
    if( _rank == 0 ) {
×
NEW
214
        PrepareScreenOutput();     // Screen Output
×
NEW
215
        PrepareHistoryOutput();    // History Output
×
216
    }
217
#ifdef IMPORT_MPI
218
    MPI_Barrier( MPI_COMM_WORLD );
219
#endif
NEW
220
    delete quad;
×
221

222
    // Initialiye QOIS
NEW
223
    _mass    = 0;
×
NEW
224
    _rmsFlux = 0;
×
225

226
    {    // Hohlraum
227

NEW
228
        unsigned n_probes = 4;
×
NEW
229
        if( _settings->GetProblemName() == PROBLEM_SymmetricHohlraum ) n_probes = 4;
×
230
        // if( _settings->GetProblemName() == PROBLEM_QuarterHohlraum ) n_probes = 2;
231

NEW
232
        _probingMoments = std::vector<double>( n_probes * 3, 0. );    // 10 time horizons
×
233

NEW
234
        if( _settings->GetProblemName() == PROBLEM_SymmetricHohlraum ) {
×
NEW
235
            _probingCellsHohlraum = {
×
NEW
236
                _mesh->GetCellsofBall( -0.4, 0., 0.01 ),
×
NEW
237
                _mesh->GetCellsofBall( 0.4, 0., 0.01 ),
×
NEW
238
                _mesh->GetCellsofBall( 0., -0.5, 0.01 ),
×
NEW
239
                _mesh->GetCellsofBall( 0., 0.5, 0.01 ),
×
240
            };
241
        }
242
        // else if( _settings->GetProblemName() == PROBLEM_QuarterHohlraum ) {
243
        //     _probingCellsHohlraum = {
244
        //         _mesh->GetCellsofBall( 0.4, 0., 0.01 ),
245
        //         _mesh->GetCellsofBall( 0., 0.5, 0.01 ),
246
        //     };
247
        // }
248

249
        // Green
NEW
250
        _thicknessGreen = 0.05;
×
251

NEW
252
        if( _settings->GetProblemName() == PROBLEM_SymmetricHohlraum ) {
×
NEW
253
            _centerGreen           = { _settings->GetPosXCenterGreenHohlraum(), _settings->GetPosYCenterGreenHohlraum() };
×
NEW
254
            _cornerUpperLeftGreen  = { -0.2 + _centerGreen[0], 0.4 + _centerGreen[1] };
×
NEW
255
            _cornerLowerLeftGreen  = { -0.2 + _centerGreen[0], -0.4 + _centerGreen[1] };
×
NEW
256
            _cornerUpperRightGreen = { 0.2 + _centerGreen[0], 0.4 + _centerGreen[1] };
×
NEW
257
            _cornerLowerRightGreen = { 0.2 + _centerGreen[0], -0.4 + _centerGreen[1] };
×
258
        }
259
        // else {
260
        //     _centerGreen           = { 0.0, 0.0 };
261
        //     _cornerUpperLeftGreen  = { 0., 0.4 - _thicknessGreen / 2.0 };
262
        //     _cornerLowerLeftGreen  = { 0., +_thicknessGreen / 2.0 };
263
        //     _cornerUpperRightGreen = { 0.2 - _thicknessGreen / 2.0, 0.4 - _thicknessGreen / 2.0 };
264
        //     _cornerLowerRightGreen = { 0.2 - _thicknessGreen / 2.0, 0. + _thicknessGreen / 2.0 };
265
        // }
266

NEW
267
        _nProbingCellsLineGreen = _settings->GetNumProbingCellsLineHohlraum();
×
268

NEW
269
        _nProbingCellsBlocksGreen  = 44;
×
NEW
270
        _absorptionValsBlocksGreen = std::vector<double>( _nProbingCellsBlocksGreen, 0. );
×
NEW
271
        _absorptionValsLineSegment = std::vector<double>( _nProbingCellsLineGreen, 0.0 );
×
272

NEW
273
        SetProbingCellsLineGreen();    // ONLY FOR HOHLRAUM
×
274
    }
275
}
276

NEW
277
SNSolverHPC::~SNSolverHPC() {
×
NEW
278
    delete _mesh;
×
NEW
279
    delete _problem;
×
280
}
281

NEW
282
void SNSolverHPC::Solve() {
×
283

284
    // --- Preprocessing ---
NEW
285
    if( _rank == 0 ) {
×
NEW
286
        PrepareVolumeOutput();
×
NEW
287
        DrawPreSolverOutput();
×
288
    }
289

NEW
290
    auto start = std::chrono::high_resolution_clock::now();    // Start timing
×
291

292
    std::chrono::duration<double> duration;
293
    // Loop over energies (pseudo-time of continuous slowing down approach)
NEW
294
    for( unsigned iter = (unsigned)_idx_start_iter; iter < _nIter; iter++ ) {
×
295

NEW
296
        if( iter == _nIter - 1 ) {    // last iteration
×
NEW
297
            _dT = _settings->GetTEnd() - iter * _dT;
×
298
        }
NEW
299
        if( _temporalOrder == 2 ) {
×
NEW
300
            std::vector<double> solRK0( _sol );
×
NEW
301
            ( _spatialOrder == 2 ) ? FluxOrder2() : FluxOrder1();
×
NEW
302
            FVMUpdate();
×
NEW
303
            ( _spatialOrder == 2 ) ? FluxOrder2() : FluxOrder1();
×
NEW
304
            FVMUpdate();
×
NEW
305
#pragma omp parallel for
×
306
            for( unsigned long idx_cell = 0; idx_cell < _nCells; ++idx_cell ) {
307
#pragma omp simd
308
                for( unsigned long idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
309
                    _sol[Idx2D( idx_cell, idx_sys, _localNSys )] =
310
                        0.5 * ( solRK0[Idx2D( idx_cell, idx_sys, _localNSys )] +
311
                                _sol[Idx2D( idx_cell, idx_sys, _localNSys )] );    // Solution averaging with HEUN
312
                }
313
            }
314
        }
315
        else {
316

NEW
317
            ( _spatialOrder == 2 ) ? FluxOrder2() : FluxOrder1();
×
NEW
318
            FVMUpdate();
×
319
        }
NEW
320
        IterPostprocessing();
×
321
        // --- Wall time measurement
NEW
322
        duration  = std::chrono::high_resolution_clock::now() - start;
×
NEW
323
        _currTime = std::chrono::duration_cast<std::chrono::duration<double>>( duration ).count();
×
324

325
        // --- Write Output ---
NEW
326
        if( _rank == 0 ) {
×
327

NEW
328
            WriteScalarOutput( iter );
×
329

330
            // --- Update Scalar Fluxes
331

332
            // --- Print Output ---
NEW
333
            PrintScreenOutput( iter );
×
NEW
334
            PrintHistoryOutput( iter );
×
335
        }
336
#ifdef BUILD_MPI
337
        MPI_Barrier( MPI_COMM_WORLD );
338
#endif
339

NEW
340
        PrintVolumeOutput( iter );
×
341
#ifdef BUILD_MPI
342
        MPI_Barrier( MPI_COMM_WORLD );
343
#endif
344
    }
345
    // --- Postprocessing ---
NEW
346
    if( _rank == 0 ) {
×
NEW
347
        DrawPostSolverOutput();
×
348
    }
349
}
350

NEW
351
void SNSolverHPC::FluxOrder2() {
×
352

NEW
353
    double const eps = 1e-10;
×
354

NEW
355
#pragma omp parallel for
×
356
    for( unsigned long idx_cell = 0; idx_cell < _nCells; ++idx_cell ) {            // Compute Slopes
357
        if( _cellBoundaryTypes[idx_cell] == BOUNDARY_TYPE::NONE ) {                // skip ghost cells
358
                                                                                   // #pragma omp simd
359
            for( unsigned long idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {    //
360
                _limiter[Idx2D( idx_cell, idx_sys, _localNSys )]         = 1.;     // limiter should be zero at boundary//
361
                _solDx[Idx3D( idx_cell, idx_sys, 0, _localNSys, _nDim )] = 0.;
362
                _solDx[Idx3D( idx_cell, idx_sys, 1, _localNSys, _nDim )] = 0.;    //
363
                double solInterfaceAvg                                   = 0.0;
364
                for( unsigned long idx_nbr = 0; idx_nbr < _nNbr; ++idx_nbr ) {            // Compute slopes and mininum and maximum
365
                    unsigned nbr_glob = _neighbors[Idx2D( idx_cell, idx_nbr, _nNbr )];    //
366
                    // Slopes
367
                    solInterfaceAvg = 0.5 * ( _sol[Idx2D( idx_cell, idx_sys, _localNSys )] + _sol[Idx2D( nbr_glob, idx_sys, _localNSys )] );
368
                    _solDx[Idx3D( idx_cell, idx_sys, 0, _localNSys, _nDim )] +=
369
                        solInterfaceAvg * _normals[Idx3D( idx_cell, idx_nbr, 0, _nNbr, _nDim )];
370
                    _solDx[Idx3D( idx_cell, idx_sys, 1, _localNSys, _nDim )] +=
371
                        solInterfaceAvg * _normals[Idx3D( idx_cell, idx_nbr, 1, _nNbr, _nDim )];
372
                }    //
373
                _solDx[Idx3D( idx_cell, idx_sys, 0, _localNSys, _nDim )] /= _areas[idx_cell];
374
                _solDx[Idx3D( idx_cell, idx_sys, 1, _localNSys, _nDim )] /= _areas[idx_cell];
375
            }
376
        }
377
    }
NEW
378
#pragma omp parallel for
×
379
    for( unsigned long idx_cell = 0; idx_cell < _nCells; ++idx_cell ) {    // Compute Limiter
380
        if( _cellBoundaryTypes[idx_cell] == BOUNDARY_TYPE::NONE ) {        // skip ghost cells
381

382
#pragma omp simd
383
            for( unsigned long idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
384

385
                double gaussPoint = 0;
386
                double r          = 0;
387
                double minSol     = _sol[Idx2D( idx_cell, idx_sys, _localNSys )];
388
                double maxSol     = _sol[Idx2D( idx_cell, idx_sys, _localNSys )];
389

390
                for( unsigned long idx_nbr = 0; idx_nbr < _nNbr; ++idx_nbr ) {    // Compute slopes and mininum and maximum
391
                    unsigned nbr_glob = _neighbors[Idx2D( idx_cell, idx_nbr, _nNbr )];
392
                    // Compute ptswise max and minimum solultion values of current and neighbor cells
393
                    maxSol = std::max( _sol[Idx2D( nbr_glob, idx_sys, _localNSys )], maxSol );
394
                    minSol = std::min( _sol[Idx2D( nbr_glob, idx_sys, _localNSys )], minSol );
395
                }
396

397
                for( unsigned long idx_nbr = 0; idx_nbr < _nNbr; idx_nbr++ ) {    // Compute limiter, see https://arxiv.org/pdf/1710.07187.pdf
398

399
                    // Compute test value at cell vertex, called gaussPt
400
                    gaussPoint =
401
                        _solDx[Idx3D( idx_cell, idx_sys, 0, _localNSys, _nDim )] *
402
                            _relativeCellVertices[Idx3D( idx_cell, idx_nbr, 0, _nNbr, _nDim )] +
403
                        _solDx[Idx3D( idx_cell, idx_sys, 1, _localNSys, _nDim )] * _relativeCellVertices[Idx3D( idx_cell, idx_nbr, 1, _nNbr, _nDim )];
404

405
                    // BARTH-JESPERSEN LIMITER
406
                    // r = ( gaussPoint > 0 ) ? std::min( ( maxSol - _sol[Idx2D( idx_cell, idx_sys, _localNSys )] ) / ( gaussPoint + eps ), 1.0 )
407
                    //                       : std::min( ( minSol - _sol[Idx2D( idx_cell, idx_sys, _localNSys )] ) / ( gaussPoint - eps ), 1.0 );
408
                    //
409
                    // r = ( std::abs( gaussPoint ) < eps ) ? 1 : r;
410
                    //_limiter[Idx2D( idx_cell, idx_sys, _localNSys )] = std::min( r, _limiter[Idx2D( idx_cell, idx_sys, _localNSys )] );
411

412
                    // VENKATAKRISHNAN LIMITER
413
                    double delta1Max = maxSol - _sol[Idx2D( idx_cell, idx_sys, _localNSys )];
414
                    double delta1Min = minSol - _sol[Idx2D( idx_cell, idx_sys, _localNSys )];
415

416
                    r = ( gaussPoint > 0 ) ? ( ( delta1Max * delta1Max + _areas[idx_cell] ) * gaussPoint + 2 * gaussPoint * gaussPoint * delta1Max ) /
417
                                                 ( delta1Max * delta1Max + 2 * gaussPoint * gaussPoint + delta1Max * gaussPoint + _areas[idx_cell] ) /
418
                                                 ( gaussPoint + eps )
419
                                           : ( ( delta1Min * delta1Min + _areas[idx_cell] ) * gaussPoint + 2 * gaussPoint * gaussPoint * delta1Min ) /
420
                                                 ( delta1Min * delta1Min + 2 * gaussPoint * gaussPoint + delta1Min * gaussPoint + _areas[idx_cell] ) /
421
                                                 ( gaussPoint - eps );
422

423
                    r = ( std::abs( gaussPoint ) < eps ) ? 1 : r;
424

425
                    _limiter[Idx2D( idx_cell, idx_sys, _localNSys )] = std::min( r, _limiter[Idx2D( idx_cell, idx_sys, _localNSys )] );
426
                }
427
            }
428
        }
429
        else {
430
#pragma omp simd
431
            for( unsigned long idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
432
                _limiter[Idx2D( idx_cell, idx_sys, _localNSys )]         = 0.;    // limiter should be zero at boundary
433
                _solDx[Idx3D( idx_cell, idx_sys, 0, _localNSys, _nDim )] = 0.;
434
                _solDx[Idx3D( idx_cell, idx_sys, 1, _localNSys, _nDim )] = 0.;
435
            }
436
        }
437
    }
NEW
438
#pragma omp parallel for
×
439
    for( unsigned long idx_cell = 0; idx_cell < _nCells; ++idx_cell ) {    // Compute Flux
440
#pragma omp simd
441
        for( unsigned long idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
442
            _flux[Idx2D( idx_cell, idx_sys, _localNSys )] = 0.;
443
        }
444

445
        // Fluxes
446
        for( unsigned long idx_nbr = 0; idx_nbr < _nNbr; ++idx_nbr ) {
447
            if( _cellBoundaryTypes[idx_cell] == BOUNDARY_TYPE::NEUMANN && _neighbors[Idx2D( idx_cell, idx_nbr, _nNbr )] == _nCells ) {
448
                // #pragma omp simd
449
                for( unsigned long idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
450
                    double localInner = _quadPts[Idx2D( idx_sys, 0, _nDim )] * _normals[Idx3D( idx_cell, idx_nbr, 0, _nNbr, _nDim )] +
451
                                        _quadPts[Idx2D( idx_sys, 1, _nDim )] * _normals[Idx3D( idx_cell, idx_nbr, 1, _nNbr, _nDim )];
452
                    if( localInner > 0 ) {
453
                        _flux[Idx2D( idx_cell, idx_sys, _localNSys )] += localInner * _sol[Idx2D( idx_cell, idx_sys, _localNSys )];
454
                    }
455
                    else {
456
                        double ghostCellValue = _ghostCells[idx_cell][idx_sys];    // fixed boundary
457
                        _flux[Idx2D( idx_cell, idx_sys, _localNSys )] += localInner * ghostCellValue;
458
                    }
459
                }
460
            }
461
            else {
462

463
                unsigned long nbr_glob = _neighbors[Idx2D( idx_cell, idx_nbr, _nNbr )];    // global idx of neighbor cell
464
                                                                                           // Second order
465
#pragma omp simd
466
                for( unsigned long idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
467
                    // store flux contribution on psiNew_sigmaS to save memory
468
                    double localInner = _quadPts[Idx2D( idx_sys, 0, _nDim )] * _normals[Idx3D( idx_cell, idx_nbr, 0, _nNbr, _nDim )] +
469
                                        _quadPts[Idx2D( idx_sys, 1, _nDim )] * _normals[Idx3D( idx_cell, idx_nbr, 1, _nNbr, _nDim )];
470

471
                    _flux[Idx2D( idx_cell, idx_sys, _localNSys )] +=
472
                        ( localInner > 0 ) ? localInner * ( _sol[Idx2D( idx_cell, idx_sys, _localNSys )] +
473
                                                            _limiter[Idx2D( idx_cell, idx_sys, _localNSys )] *
474
                                                                ( _solDx[Idx3D( idx_cell, idx_sys, 0, _localNSys, _nDim )] *
475
                                                                      _relativeInterfaceMidPt[Idx3D( idx_cell, idx_nbr, 0, _nNbr, _nDim )] +
476
                                                                  _solDx[Idx3D( idx_cell, idx_sys, 1, _localNSys, _nDim )] *
477
                                                                      _relativeInterfaceMidPt[Idx3D( idx_cell, idx_nbr, 1, _nNbr, _nDim )] ) )
478
                                           : localInner * ( _sol[Idx2D( nbr_glob, idx_sys, _localNSys )] +
479
                                                            _limiter[Idx2D( nbr_glob, idx_sys, _localNSys )] *
480
                                                                ( _solDx[Idx3D( nbr_glob, idx_sys, 0, _localNSys, _nDim )] *
481
                                                                      ( _interfaceMidPoints[Idx3D( idx_cell, idx_nbr, 0, _nNbr, _nDim )] -
482
                                                                        _cellMidPoints[Idx2D( nbr_glob, 0, _nDim )] ) +
483
                                                                  _solDx[Idx3D( nbr_glob, idx_sys, 1, _localNSys, _nDim )] *
484
                                                                      ( _interfaceMidPoints[Idx3D( idx_cell, idx_nbr, 1, _nNbr, _nDim )] -
485
                                                                        _cellMidPoints[Idx2D( nbr_glob, 1, _nDim )] ) ) );
486
                }
487
            }
488
        }
489
    }
490
}
491

NEW
492
void SNSolverHPC::FluxOrder1() {
×
493

NEW
494
#pragma omp parallel for
×
495
    for( unsigned long idx_cell = 0; idx_cell < _nCells; ++idx_cell ) {
496

497
#pragma omp simd
498
        for( unsigned long idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
499
            _flux[Idx2D( idx_cell, idx_sys, _localNSys )] = 0.0;    // Reset temporary variable
500
        }
501

502
        // Fluxes
503
        for( unsigned long idx_nbr = 0; idx_nbr < _nNbr; ++idx_nbr ) {
504
            if( _cellBoundaryTypes[idx_cell] == BOUNDARY_TYPE::NEUMANN && _neighbors[Idx2D( idx_cell, idx_nbr, _nNbr )] == _nCells ) {
505
#pragma omp simd
506
                for( unsigned long idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
507
                    double localInner = _quadPts[Idx2D( idx_sys, 0, _nDim )] * _normals[Idx3D( idx_cell, idx_nbr, 0, _nNbr, _nDim )] +
508
                                        _quadPts[Idx2D( idx_sys, 1, _nDim )] * _normals[Idx3D( idx_cell, idx_nbr, 1, _nNbr, _nDim )];
509
                    if( localInner > 0 ) {
510
                        _flux[Idx2D( idx_cell, idx_sys, _localNSys )] += localInner * _sol[Idx2D( idx_cell, idx_sys, _localNSys )];
511
                    }
512
                    else {
513
                        double ghostCellValue = _ghostCells[idx_cell][idx_sys];    // fixed boundary
514
                        _flux[Idx2D( idx_cell, idx_sys, _localNSys )] += localInner * ghostCellValue;
515
                    }
516
                }
517
            }
518
            else {
519
                unsigned long nbr_glob = _neighbors[Idx2D( idx_cell, idx_nbr, _nNbr )];    // global idx of neighbor cell
520
#pragma omp simd
521
                for( unsigned long idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
522

523
                    double localInner = _quadPts[Idx2D( idx_sys, 0, _nDim )] * _normals[Idx3D( idx_cell, idx_nbr, 0, _nNbr, _nDim )] +
524
                                        _quadPts[Idx2D( idx_sys, 1, _nDim )] * _normals[Idx3D( idx_cell, idx_nbr, 1, _nNbr, _nDim )];
525

526
                    _flux[Idx2D( idx_cell, idx_sys, _localNSys )] += ( localInner > 0 ) ? localInner * _sol[Idx2D( idx_cell, idx_sys, _localNSys )]
527
                                                                                        : localInner * _sol[Idx2D( nbr_glob, idx_sys, _localNSys )];
528
                }
529
            }
530
        }
531
    }
532
}
533

NEW
534
void SNSolverHPC::FVMUpdate() {
×
NEW
535
    _mass    = 0.0;
×
NEW
536
    _rmsFlux = 0.0;
×
NEW
537
    std::vector<double> temp_scalarFlux( _nCells );    // for MPI allreduce
×
538

NEW
539
#pragma omp parallel for reduction( + : _mass, _rmsFlux )
×
540
    for( unsigned long idx_cell = 0; idx_cell < _nCells; ++idx_cell ) {
541

542
#pragma omp simd
543
        for( unsigned long idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
544
            // Update
545
            _sol[Idx2D( idx_cell, idx_sys, _localNSys )] =
546
                ( 1 - _dT * _sigmaT[idx_cell] ) * _sol[Idx2D( idx_cell, idx_sys, _localNSys )] -
547
                _dT / _areas[idx_cell] * _flux[Idx2D( idx_cell, idx_sys, _localNSys )] +
548
                _dT * ( _sigmaS[idx_cell] * _scalarFlux[idx_cell] / ( 2 * M_PI ) + _source[Idx2D( idx_cell, idx_sys, _localNSys )] );
549
        }
550
        double localScalarFlux = 0;
551

552
#pragma omp simd reduction( + : localScalarFlux )
553
        for( unsigned long idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
554
            _sol[Idx2D( idx_cell, idx_sys, _localNSys )] = std::max( _sol[Idx2D( idx_cell, idx_sys, _localNSys )], 0.0 );
555
            localScalarFlux += _sol[Idx2D( idx_cell, idx_sys, _localNSys )] * _quadWeights[idx_sys];
556
        }
557
        _mass += localScalarFlux * _areas[idx_cell];
558
        _rmsFlux += ( localScalarFlux - _scalarFlux[idx_cell] ) * ( localScalarFlux - _scalarFlux[idx_cell] );
559
        temp_scalarFlux[idx_cell] = localScalarFlux;    // set flux
560
    }
561
// MPI Allreduce: _scalarFlux
562
#ifdef IMPORT_MPI
563
    MPI_Barrier( MPI_COMM_WORLD );
564
    MPI_Allreduce( temp_scalarFlux.data(), _scalarFlux.data(), _nCells, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
565
    MPI_Barrier( MPI_COMM_WORLD );
566
#endif
567
#ifndef IMPORT_MPI
NEW
568
    _scalarFlux = temp_scalarFlux;
×
569
#endif
570
}
571

NEW
572
void SNSolverHPC::IterPostprocessing() {
×
573
    // ALREDUCE NEEDED
574

NEW
575
    _curAbsorptionLattice            = 0.0;
×
NEW
576
    _curScalarOutflow                = 0.0;
×
NEW
577
    _curScalarOutflowPeri1           = 0.0;
×
NEW
578
    _curScalarOutflowPeri2           = 0.0;
×
NEW
579
    _curAbsorptionHohlraumCenter     = 0.0;    // Green and blue areas of symmetric hohlraum
×
NEW
580
    _curAbsorptionHohlraumVertical   = 0.0;    // Red areas of symmetric hohlraum
×
NEW
581
    _curAbsorptionHohlraumHorizontal = 0.0;    // Black areas of symmetric hohlraum
×
NEW
582
    _varAbsorptionHohlraumGreen      = 0.0;
×
NEW
583
    double a_g                       = 0.0;
×
584

NEW
585
#pragma omp parallel for reduction( + : _curAbsorptionLattice,                                                                                       \
×
586
                                        _curScalarOutflow,                                                                                           \
587
                                        _curScalarOutflowPeri1,                                                                                      \
588
                                        _curScalarOutflowPeri2,                                                                                      \
589
                                        _curAbsorptionHohlraumCenter,                                                                                \
590
                                        _curAbsorptionHohlraumVertical,                                                                              \
591
                                        _curAbsorptionHohlraumHorizontal,                                                                            \
NEW
592
                                        a_g ) reduction( max : _curMaxOrdinateOutflow, _curMaxAbsorptionLattice )
×
593
    for( unsigned long idx_cell = 0; idx_cell < _nCells; ++idx_cell ) {
594

595
        if( _settings->GetProblemName() == PROBLEM_Lattice || _settings->GetProblemName() == PROBLEM_HalfLattice ) {
596
            if( IsAbsorptionLattice( _cellMidPoints[Idx2D( idx_cell, 0, _nDim )], _cellMidPoints[Idx2D( idx_cell, 1, _nDim )] ) ) {
597
                double sigmaAPsi = _scalarFlux[idx_cell] * ( _sigmaT[idx_cell] - _sigmaS[idx_cell] ) * _areas[idx_cell];
598
                _curAbsorptionLattice += sigmaAPsi;
599
                _curMaxAbsorptionLattice = ( _curMaxAbsorptionLattice < sigmaAPsi ) ? sigmaAPsi : _curMaxAbsorptionLattice;
600
            }
601
        }
602

603
        if( _settings->GetProblemName() == PROBLEM_SymmetricHohlraum ) {    //} || _settings->GetProblemName() == PROBLEM_QuarterHohlraum ) {
604

605
            double x = _cellMidPoints[Idx2D( idx_cell, 0, _nDim )];
606
            double y = _cellMidPoints[Idx2D( idx_cell, 1, _nDim )];
607
            _curAbsorptionLattice += _scalarFlux[idx_cell] * ( _sigmaT[idx_cell] - _sigmaS[idx_cell] ) * _areas[idx_cell];
608
            if( x > -0.2 + _settings->GetPosXCenterGreenHohlraum() && x < 0.2 + _settings->GetPosXCenterGreenHohlraum() &&
609
                y > -0.4 + _settings->GetPosYCenterGreenHohlraum() && y < 0.4 + _settings->GetPosYCenterGreenHohlraum() ) {
610
                _curAbsorptionHohlraumCenter += _scalarFlux[idx_cell] * ( _sigmaT[idx_cell] - _sigmaS[idx_cell] ) * _areas[idx_cell];
611
            }
612
            if( ( x < _settings->GetPosRedLeftBorderHohlraum() && y > _settings->GetPosRedLeftBottomHohlraum() &&
613
                  y < _settings->GetPosRedLeftTopHohlraum() ) ||
614
                ( x > _settings->GetPosRedRightBorderHohlraum() && y > _settings->GetPosRedLeftBottomHohlraum() &&
615
                  y < _settings->GetPosRedRightTopHohlraum() ) ) {
616
                _curAbsorptionHohlraumVertical += _scalarFlux[idx_cell] * ( _sigmaT[idx_cell] - _sigmaS[idx_cell] ) * _areas[idx_cell];
617
            }
618
            if( y > 0.6 || y < -0.6 ) {
619
                _curAbsorptionHohlraumHorizontal += _scalarFlux[idx_cell] * ( _sigmaT[idx_cell] - _sigmaS[idx_cell] ) * _areas[idx_cell];
620
            }
621

622
            // Variation in absorption of center (part 1)
623
            // green area 1 (lower boundary)
624
            bool green1 = x > -0.2 + _settings->GetPosXCenterGreenHohlraum() && x < 0.2 + _settings->GetPosXCenterGreenHohlraum() &&
625
                          y > -0.4 + _settings->GetPosYCenterGreenHohlraum() && y < -0.35 + _settings->GetPosYCenterGreenHohlraum();
626
            // green area 2 (upper boundary)
627
            bool green2 = x > -0.2 + _settings->GetPosXCenterGreenHohlraum() && x < 0.2 + _settings->GetPosXCenterGreenHohlraum() &&
628
                          y > 0.35 + _settings->GetPosYCenterGreenHohlraum() && y < 0.4 + _settings->GetPosYCenterGreenHohlraum();
629
            // green area 3 (left boundary)
630
            bool green3 = x > -0.2 + _settings->GetPosXCenterGreenHohlraum() && x < -0.15 + _settings->GetPosXCenterGreenHohlraum() &&
631
                          y > -0.35 + _settings->GetPosYCenterGreenHohlraum() && y < 0.35 + _settings->GetPosYCenterGreenHohlraum();
632
            // green area 4 (right boundary)
633
            bool green4 = x > 0.15 + _settings->GetPosXCenterGreenHohlraum() && x < 0.2 + _settings->GetPosXCenterGreenHohlraum() &&
634
                          y > -0.35 + _settings->GetPosYCenterGreenHohlraum() && y < 0.35 + _settings->GetPosYCenterGreenHohlraum();
635
            if( green1 || green2 || green3 || green4 ) {
636
                a_g += ( _sigmaT[idx_cell] - _sigmaS[idx_cell] ) * _scalarFlux[idx_cell] * _areas[idx_cell] /
637
                       ( 44 * 0.05 * 0.05 );    // divisor is area of the green
638
            }
639
        }
640

641
        if( _settings->GetProblemName() == PROBLEM_Lattice ) {
642
            // Outflow out of inner and middle perimeter
643
            if( _isPerimeterLatticeCell1[idx_cell] ) {    // inner
644
                for( unsigned long idx_nbr_helper = 0; idx_nbr_helper < _cellsLatticePerimeter1[idx_cell].size(); ++idx_nbr_helper ) {
645
#pragma omp simd reduction( + : _curScalarOutflowPeri1 )
646
                    for( unsigned long idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
647
                        double localInner = _quadPts[Idx2D( idx_sys, 0, _nDim )] *
648
                                                _normals[Idx3D( idx_cell, _cellsLatticePerimeter1[idx_cell][idx_nbr_helper], 0, _nNbr, _nDim )] +
649
                                            _quadPts[Idx2D( idx_sys, 1, _nDim )] *
650
                                                _normals[Idx3D( idx_cell, _cellsLatticePerimeter1[idx_cell][idx_nbr_helper], 1, _nNbr, _nDim )];
651
                        // Find outward facing transport directions
652

653
                        if( localInner > 0.0 ) {
654
                            _curScalarOutflowPeri1 +=
655
                                localInner * _sol[Idx2D( idx_cell, idx_sys, _localNSys )] * _quadWeights[idx_sys];    // Integrate flux
656
                        }
657
                    }
658
                }
659
            }
660
            if( _isPerimeterLatticeCell2[idx_cell] ) {    // middle
661
                for( unsigned long idx_nbr_helper = 0; idx_nbr_helper < _cellsLatticePerimeter2[idx_cell].size(); ++idx_nbr_helper ) {
662
#pragma omp simd reduction( + : _curScalarOutflowPeri2 )
663
                    for( unsigned long idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
664
                        double localInner = _quadPts[Idx2D( idx_sys, 0, _nDim )] *
665
                                                _normals[Idx3D( idx_cell, _cellsLatticePerimeter2[idx_cell][idx_nbr_helper], 0, _nNbr, _nDim )] +
666
                                            _quadPts[Idx2D( idx_sys, 1, _nDim )] *
667
                                                _normals[Idx3D( idx_cell, _cellsLatticePerimeter2[idx_cell][idx_nbr_helper], 1, _nNbr, _nDim )];
668
                        // Find outward facing transport directions
669

670
                        if( localInner > 0.0 ) {
671
                            _curScalarOutflowPeri2 +=
672
                                localInner * _sol[Idx2D( idx_cell, idx_sys, _localNSys )] * _quadWeights[idx_sys];    // Integrate flux
673
                        }
674
                    }
675
                }
676
            }
677
        }
678
        // Outflow out of domain
679
        if( _cellBoundaryTypes[idx_cell] == BOUNDARY_TYPE::NEUMANN ) {
680
            // Iterate over face cell faces
681
            double currOrdinatewiseOutflow = 0.0;
682

683
            for( unsigned long idx_nbr = 0; idx_nbr < _nNbr; ++idx_nbr ) {
684
                // Find face that points outward
685
                if( _neighbors[Idx2D( idx_cell, idx_nbr, _nNbr )] == _nCells ) {
686
#pragma omp simd reduction( + : _curScalarOutflow ) reduction( max : _curMaxOrdinateOutflow )
687
                    for( unsigned long idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
688

689
                        double localInner = _quadPts[Idx2D( idx_sys, 0, _nDim )] * _normals[Idx3D( idx_cell, idx_nbr, 0, _nNbr, _nDim )] +
690
                                            _quadPts[Idx2D( idx_sys, 1, _nDim )] * _normals[Idx3D( idx_cell, idx_nbr, 1, _nNbr, _nDim )];
691
                        // Find outward facing transport directions
692

693
                        if( localInner > 0.0 ) {
694
                            _curScalarOutflow +=
695
                                localInner * _sol[Idx2D( idx_cell, idx_sys, _localNSys )] * _quadWeights[idx_sys];    // Integrate flux
696

697
                            currOrdinatewiseOutflow =
698
                                _sol[Idx2D( idx_cell, idx_sys, _localNSys )] * localInner /
699
                                sqrt( (
700
                                    _normals[Idx3D( idx_cell, idx_nbr, 0, _nNbr, _nDim )] * _normals[Idx3D( idx_cell, idx_nbr, 0, _nNbr, _nDim )] +
701
                                    _normals[Idx3D( idx_cell, idx_nbr, 1, _nNbr, _nDim )] * _normals[Idx3D( idx_cell, idx_nbr, 1, _nNbr, _nDim )] ) );
702

703
                            _curMaxOrdinateOutflow =
704
                                ( currOrdinatewiseOutflow > _curMaxOrdinateOutflow ) ? currOrdinatewiseOutflow : _curMaxOrdinateOutflow;
705
                        }
706
                    }
707
                }
708
            }
709
        }
710
    }
711
// MPI Allreduce
712
#ifdef IMPORT_MPI
713
    double tmp_curScalarOutflow      = 0.0;
714
    double tmp_curScalarOutflowPeri1 = 0.0;
715
    double tmp_curScalarOutflowPeri2 = 0.0;
716
    double tmp_mass                  = 0.0;
717
    double tmp_rmsFlux               = 0.0;
718
    MPI_Barrier( MPI_COMM_WORLD );
719
    MPI_Allreduce( &_curScalarOutflow, &tmp_curScalarOutflow, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
720
    _curScalarOutflow = tmp_curScalarOutflow;
721
    MPI_Barrier( MPI_COMM_WORLD );
722
    MPI_Allreduce( &_curScalarOutflowPeri1, &tmp_curScalarOutflowPeri1, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
723
    _curScalarOutflowPeri1 = tmp_curScalarOutflowPeri1;
724
    MPI_Barrier( MPI_COMM_WORLD );
725
    MPI_Allreduce( &_curScalarOutflowPeri2, &tmp_curScalarOutflowPeri2, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
726
    _curScalarOutflowPeri2 = tmp_curScalarOutflowPeri2;
727
    MPI_Barrier( MPI_COMM_WORLD );
728
    MPI_Allreduce( &_mass, &tmp_mass, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
729
    _mass = tmp_mass;
730
    MPI_Barrier( MPI_COMM_WORLD );
731
    MPI_Allreduce( &_rmsFlux, &tmp_rmsFlux, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
732
    _rmsFlux = tmp_rmsFlux;
733
    MPI_Barrier( MPI_COMM_WORLD );
734
#endif
735
    // Variation absorption (part II)
NEW
736
    if( _settings->GetProblemName() == PROBLEM_SymmetricHohlraum ) {
×
NEW
737
        unsigned n_probes = 4;
×
NEW
738
        std::vector<double> temp_probingMoments( 3 * n_probes );    // for MPI allreduce
×
739

NEW
740
#pragma omp parallel for reduction( + : _varAbsorptionHohlraumGreen )
×
741
        for( unsigned long idx_cell = 0; idx_cell < _nCells; ++idx_cell ) {
742
            double x = _cellMidPoints[Idx2D( idx_cell, 0, _nDim )];
743
            double y = _cellMidPoints[Idx2D( idx_cell, 1, _nDim )];
744

745
            // green area 1 (lower boundary)
746
            bool green1 = x > -0.2 + _settings->GetPosXCenterGreenHohlraum() && x < 0.2 + _settings->GetPosXCenterGreenHohlraum() &&
747
                          y > -0.4 + _settings->GetPosYCenterGreenHohlraum() && y < -0.35 + _settings->GetPosYCenterGreenHohlraum();
748
            // green area 2 (upper boundary)
749
            bool green2 = x > -0.2 + _settings->GetPosXCenterGreenHohlraum() && x < 0.2 + _settings->GetPosXCenterGreenHohlraum() &&
750
                          y > 0.35 + _settings->GetPosYCenterGreenHohlraum() && y < 0.4 + _settings->GetPosYCenterGreenHohlraum();
751
            // green area 3 (left boundary)
752
            bool green3 = x > -0.2 + _settings->GetPosXCenterGreenHohlraum() && x < -0.15 + _settings->GetPosXCenterGreenHohlraum() &&
753
                          y > -0.35 + _settings->GetPosYCenterGreenHohlraum() && y < 0.35 + _settings->GetPosYCenterGreenHohlraum();
754
            // green area 4 (right boundary)
755
            bool green4 = x > 0.15 + _settings->GetPosXCenterGreenHohlraum() && x < 0.2 + _settings->GetPosXCenterGreenHohlraum() &&
756
                          y > -0.35 + _settings->GetPosYCenterGreenHohlraum() && y < 0.35 + _settings->GetPosYCenterGreenHohlraum();
757
            if( green1 || green2 || green3 || green4 ) {
758
                _varAbsorptionHohlraumGreen += ( a_g - _scalarFlux[idx_cell] * ( _sigmaT[idx_cell] - _sigmaS[idx_cell] ) ) *
759
                                               ( a_g - _scalarFlux[idx_cell] * ( _sigmaT[idx_cell] - _sigmaS[idx_cell] ) ) * _areas[idx_cell];
760
            }
761
        }
762
        // Probes value moments
763
        // #pragma omp parallel for
NEW
764
        for( unsigned long idx_probe = 0; idx_probe < n_probes; idx_probe++ ) {    // Loop over probing cells
×
NEW
765
            temp_probingMoments[Idx2D( idx_probe, 0, 3 )] = 0.0;
×
NEW
766
            temp_probingMoments[Idx2D( idx_probe, 1, 3 )] = 0.0;
×
NEW
767
            temp_probingMoments[Idx2D( idx_probe, 2, 3 )] = 0.0;
×
768
            // for( unsigned long idx_ball = 0; idx_ball < _probingCellsHohlraum[idx_probe].size(); idx_ball++ ) {
769
            //   std::cout << idx_ball << _areas[_probingCellsHohlraum[idx_probe][idx_ball]] / ( 0.01 * 0.01 * M_PI ) << std::endl;
770
            //}
NEW
771
            for( unsigned long idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
×
NEW
772
                for( unsigned long idx_ball = 0; idx_ball < _probingCellsHohlraum[idx_probe].size(); idx_ball++ ) {
×
NEW
773
                    temp_probingMoments[Idx2D( idx_probe, 0, 3 )] += _sol[Idx2D( _probingCellsHohlraum[idx_probe][idx_ball], idx_sys, _localNSys )] *
×
NEW
774
                                                                     _quadWeights[idx_sys] * _areas[_probingCellsHohlraum[idx_probe][idx_ball]] /
×
775
                                                                     ( 0.01 * 0.01 * M_PI );
NEW
776
                    temp_probingMoments[Idx2D( idx_probe, 1, 3 )] +=
×
NEW
777
                        _quadPts[Idx2D( idx_sys, 0, _nDim )] * _sol[Idx2D( _probingCellsHohlraum[idx_probe][idx_ball], idx_sys, _localNSys )] *
×
NEW
778
                        _quadWeights[idx_sys] * _areas[_probingCellsHohlraum[idx_probe][idx_ball]] / ( 0.01 * 0.01 * M_PI );
×
NEW
779
                    temp_probingMoments[Idx2D( idx_probe, 2, 3 )] +=
×
NEW
780
                        _quadPts[Idx2D( idx_sys, 1, _nDim )] * _sol[Idx2D( _probingCellsHohlraum[idx_probe][idx_ball], idx_sys, _localNSys )] *
×
NEW
781
                        _quadWeights[idx_sys] * _areas[_probingCellsHohlraum[idx_probe][idx_ball]] / ( 0.01 * 0.01 * M_PI );
×
782
                }
783
            }
784
        }
785

786
#ifdef IMPORT_MPI
787
        MPI_Barrier( MPI_COMM_WORLD );
788
        MPI_Allreduce( temp_probingMoments.data(), _probingMoments.data(), 3 * n_probes, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
789
        MPI_Barrier( MPI_COMM_WORLD );
790
#endif
791
#ifndef IMPORT_MPI
NEW
792
        for( unsigned long idx_probe = 0; idx_probe < n_probes; idx_probe++ ) {    // Loop over probing cells
×
NEW
793
            _probingMoments[Idx2D( idx_probe, 0, 3 )] = temp_probingMoments[Idx2D( idx_probe, 0, 3 )];
×
NEW
794
            _probingMoments[Idx2D( idx_probe, 1, 3 )] = temp_probingMoments[Idx2D( idx_probe, 1, 3 )];
×
NEW
795
            _probingMoments[Idx2D( idx_probe, 2, 3 )] = temp_probingMoments[Idx2D( idx_probe, 2, 3 )];
×
796
        }
797
#endif
798
    }
799
    // probe values green
NEW
800
    if( _settings->GetProblemName() == PROBLEM_SymmetricHohlraum ) {
×
NEW
801
        ComputeQOIsGreenProbingLine();
×
802
    }
803
    // Update time integral values on rank 0
NEW
804
    if( _rank == 0 ) {
×
NEW
805
        _totalScalarOutflow += _curScalarOutflow * _dT;
×
NEW
806
        _totalScalarOutflowPeri1 += _curScalarOutflowPeri1 * _dT;
×
NEW
807
        _totalScalarOutflowPeri2 += _curScalarOutflowPeri2 * _dT;
×
NEW
808
        _totalAbsorptionLattice += _curAbsorptionLattice * _dT;
×
809

NEW
810
        _totalAbsorptionHohlraumCenter += _curAbsorptionHohlraumCenter * _dT;
×
NEW
811
        _totalAbsorptionHohlraumVertical += _curAbsorptionHohlraumVertical * _dT;
×
NEW
812
        _totalAbsorptionHohlraumHorizontal += _curAbsorptionHohlraumHorizontal * _dT;
×
813

NEW
814
        _rmsFlux = sqrt( _rmsFlux );
×
815
    }
816
}
817

NEW
818
bool SNSolverHPC::IsAbsorptionLattice( double x, double y ) const {
×
819
    // Check whether pos is inside absorbing squares
NEW
820
    double xy_corrector = -3.5;
×
NEW
821
    std::vector<double> lbounds{ 1 + xy_corrector, 2 + xy_corrector, 3 + xy_corrector, 4 + xy_corrector, 5 + xy_corrector };
×
NEW
822
    std::vector<double> ubounds{ 2 + xy_corrector, 3 + xy_corrector, 4 + xy_corrector, 5 + xy_corrector, 6 + xy_corrector };
×
NEW
823
    for( unsigned k = 0; k < lbounds.size(); ++k ) {
×
NEW
824
        for( unsigned l = 0; l < lbounds.size(); ++l ) {
×
NEW
825
            if( ( l + k ) % 2 == 1 || ( k == 2 && l == 2 ) || ( k == 2 && l == 4 ) ) continue;
×
NEW
826
            if( x >= lbounds[k] && x <= ubounds[k] && y >= lbounds[l] && y <= ubounds[l] ) {
×
NEW
827
                return true;
×
828
            }
829
        }
830
    }
NEW
831
    return false;
×
832
}
833

834
// --- Helper ---
NEW
835
double SNSolverHPC::ComputeTimeStep( double cfl ) const {
×
836
    // for pseudo 1D, set timestep to dx
837
    double dx, dy;
NEW
838
    switch( _settings->GetProblemName() ) {
×
NEW
839
        case PROBLEM_Checkerboard1D:
×
NEW
840
            dx = 7.0 / (double)_nCells;
×
NEW
841
            dy = 0.3;
×
NEW
842
            return cfl * ( dx * dy ) / ( dx + dy );
×
843
            break;
NEW
844
        case PROBLEM_Linesource1D:     // Fallthrough
×
845
        case PROBLEM_Meltingcube1D:    // Fallthrough
846
        case PROBLEM_Aircavity1D:
NEW
847
            dx = 3.0 / (double)_nCells;
×
NEW
848
            dy = 0.3;
×
NEW
849
            return cfl * ( dx * dy ) / ( dx + dy );
×
850
            break;
NEW
851
        default: break;    // 2d as normal
×
852
    }
853
    // 2D case
NEW
854
    double charSize = __DBL_MAX__;    // minimum char size of all mesh cells in the mesh
×
855

NEW
856
#pragma omp parallel for reduction( min : charSize )
×
857
    for( unsigned long j = 0; j < _nCells; j++ ) {
858
        double currCharSize = sqrt( _areas[j] );
859
        if( currCharSize < charSize ) {
860
            charSize = currCharSize;
861
        }
862
    }
NEW
863
    if( _rank == 0 ) {
×
NEW
864
        auto log         = spdlog::get( "event" );
×
NEW
865
        std::string line = "| Smallest characteristic length of a grid cell in this mesh: " + std::to_string( charSize );
×
NEW
866
        log->info( line );
×
NEW
867
        line = "| Corresponding maximal time-step: " + std::to_string( cfl * charSize );
×
NEW
868
        log->info( line );
×
869
    }
NEW
870
    return cfl * charSize;
×
871
}
872

873
// --- IO ----
NEW
874
void SNSolverHPC::PrepareScreenOutput() {
×
NEW
875
    unsigned nFields = (unsigned)_settings->GetNScreenOutput();
×
876

NEW
877
    _screenOutputFieldNames.resize( nFields );
×
NEW
878
    _screenOutputFields.resize( nFields );
×
879

880
    // Prepare all output Fields ==> Specified in option SCREEN_OUTPUT
NEW
881
    for( unsigned idx_field = 0; idx_field < nFields; idx_field++ ) {
×
882
        // Prepare all Output Fields per group
883

884
        // Different procedure, depending on the Group...
NEW
885
        switch( _settings->GetScreenOutput()[idx_field] ) {
×
NEW
886
            case MASS: _screenOutputFieldNames[idx_field] = "Mass"; break;
×
NEW
887
            case ITER: _screenOutputFieldNames[idx_field] = "Iter"; break;
×
NEW
888
            case WALL_TIME: _screenOutputFieldNames[idx_field] = "Wall time [s]"; break;
×
NEW
889
            case RMS_FLUX: _screenOutputFieldNames[idx_field] = "RMS flux"; break;
×
NEW
890
            case VTK_OUTPUT: _screenOutputFieldNames[idx_field] = "VTK out"; break;
×
NEW
891
            case CSV_OUTPUT: _screenOutputFieldNames[idx_field] = "CSV out"; break;
×
NEW
892
            case CUR_OUTFLOW: _screenOutputFieldNames[idx_field] = "Cur. outflow"; break;
×
NEW
893
            case TOTAL_OUTFLOW: _screenOutputFieldNames[idx_field] = "Tot. outflow"; break;
×
NEW
894
            case CUR_OUTFLOW_P1: _screenOutputFieldNames[idx_field] = "Cur. outflow P1"; break;
×
NEW
895
            case TOTAL_OUTFLOW_P1: _screenOutputFieldNames[idx_field] = "Tot. outflow P1"; break;
×
NEW
896
            case CUR_OUTFLOW_P2: _screenOutputFieldNames[idx_field] = "Cur. outflow P2"; break;
×
NEW
897
            case TOTAL_OUTFLOW_P2: _screenOutputFieldNames[idx_field] = "Tot. outflow P2"; break;
×
NEW
898
            case MAX_OUTFLOW: _screenOutputFieldNames[idx_field] = "Max outflow"; break;
×
NEW
899
            case CUR_PARTICLE_ABSORPTION: _screenOutputFieldNames[idx_field] = "Cur. absorption"; break;
×
NEW
900
            case TOTAL_PARTICLE_ABSORPTION: _screenOutputFieldNames[idx_field] = "Tot. absorption"; break;
×
NEW
901
            case MAX_PARTICLE_ABSORPTION: _screenOutputFieldNames[idx_field] = "Max absorption"; break;
×
NEW
902
            case TOTAL_PARTICLE_ABSORPTION_CENTER: _screenOutputFieldNames[idx_field] = "Tot. abs. center"; break;
×
NEW
903
            case TOTAL_PARTICLE_ABSORPTION_VERTICAL: _screenOutputFieldNames[idx_field] = "Tot. abs. vertical wall"; break;
×
NEW
904
            case TOTAL_PARTICLE_ABSORPTION_HORIZONTAL: _screenOutputFieldNames[idx_field] = "Tot. abs. horizontal wall"; break;
×
NEW
905
            case PROBE_MOMENT_TIME_TRACE:
×
NEW
906
                _screenOutputFieldNames[idx_field] = "Probe 1 u_0";
×
NEW
907
                idx_field++;
×
NEW
908
                _screenOutputFieldNames[idx_field] = "Probe 2 u_0";
×
NEW
909
                if( _settings->GetProblemName() == PROBLEM_SymmetricHohlraum ) {
×
NEW
910
                    idx_field++;
×
NEW
911
                    _screenOutputFieldNames[idx_field] = "Probe 3 u_0";
×
NEW
912
                    idx_field++;
×
NEW
913
                    _screenOutputFieldNames[idx_field] = "Probe 4 u_0";
×
914
                }
NEW
915
                break;
×
NEW
916
            case VAR_ABSORPTION_GREEN: _screenOutputFieldNames[idx_field] = "Var. absorption green"; break;
×
917

NEW
918
            default: ErrorMessages::Error( "Screen output field not defined!", CURRENT_FUNCTION ); break;
×
919
        }
920
    }
921
}
922

NEW
923
void SNSolverHPC::WriteScalarOutput( unsigned idx_iter ) {
×
NEW
924
    unsigned n_probes = 4;
×
925

NEW
926
    unsigned nFields                  = (unsigned)_settings->GetNScreenOutput();
×
NEW
927
    const VectorVector probingMoments = _problem->GetCurrentProbeMoment();
×
928
    // -- Screen Output
NEW
929
    for( unsigned idx_field = 0; idx_field < nFields; idx_field++ ) {
×
930
        // Prepare all Output Fields per group
931
        // Different procedure, depending on the Group...
NEW
932
        switch( _settings->GetScreenOutput()[idx_field] ) {
×
NEW
933
            case MASS: _screenOutputFields[idx_field] = _mass; break;
×
NEW
934
            case ITER: _screenOutputFields[idx_field] = idx_iter; break;
×
NEW
935
            case WALL_TIME: _screenOutputFields[idx_field] = _currTime; break;
×
NEW
936
            case RMS_FLUX: _screenOutputFields[idx_field] = _rmsFlux; break;
×
NEW
937
            case VTK_OUTPUT:
×
NEW
938
                _screenOutputFields[idx_field] = 0;
×
NEW
939
                if( ( _settings->GetVolumeOutputFrequency() != 0 && idx_iter % (unsigned)_settings->GetVolumeOutputFrequency() == 0 ) ||
×
NEW
940
                    ( idx_iter == _nIter - 1 ) /* need sol at last iteration */ ) {
×
NEW
941
                    _screenOutputFields[idx_field] = 1;
×
942
                }
NEW
943
                break;
×
NEW
944
            case CSV_OUTPUT:
×
NEW
945
                _screenOutputFields[idx_field] = 0;
×
NEW
946
                if( ( _settings->GetHistoryOutputFrequency() != 0 && idx_iter % (unsigned)_settings->GetHistoryOutputFrequency() == 0 ) ||
×
NEW
947
                    ( idx_iter == _nIter - 1 ) /* need sol at last iteration */ ) {
×
NEW
948
                    _screenOutputFields[idx_field] = 1;
×
949
                }
NEW
950
                break;
×
NEW
951
            case CUR_OUTFLOW: _screenOutputFields[idx_field] = _curScalarOutflow; break;
×
NEW
952
            case TOTAL_OUTFLOW: _screenOutputFields[idx_field] = _totalScalarOutflow; break;
×
NEW
953
            case CUR_OUTFLOW_P1: _screenOutputFields[idx_field] = _curScalarOutflowPeri1; break;
×
NEW
954
            case TOTAL_OUTFLOW_P1: _screenOutputFields[idx_field] = _totalScalarOutflowPeri1; break;
×
NEW
955
            case CUR_OUTFLOW_P2: _screenOutputFields[idx_field] = _curScalarOutflowPeri2; break;
×
NEW
956
            case TOTAL_OUTFLOW_P2: _screenOutputFields[idx_field] = _totalScalarOutflowPeri2; break;
×
NEW
957
            case MAX_OUTFLOW: _screenOutputFields[idx_field] = _curMaxOrdinateOutflow; break;
×
NEW
958
            case CUR_PARTICLE_ABSORPTION: _screenOutputFields[idx_field] = _curAbsorptionLattice; break;
×
NEW
959
            case TOTAL_PARTICLE_ABSORPTION: _screenOutputFields[idx_field] = _totalAbsorptionLattice; break;
×
NEW
960
            case MAX_PARTICLE_ABSORPTION: _screenOutputFields[idx_field] = _curMaxAbsorptionLattice; break;
×
NEW
961
            case TOTAL_PARTICLE_ABSORPTION_CENTER: _screenOutputFields[idx_field] = _totalAbsorptionHohlraumCenter; break;
×
NEW
962
            case TOTAL_PARTICLE_ABSORPTION_VERTICAL: _screenOutputFields[idx_field] = _totalAbsorptionHohlraumVertical; break;
×
NEW
963
            case TOTAL_PARTICLE_ABSORPTION_HORIZONTAL: _screenOutputFields[idx_field] = _totalAbsorptionHohlraumHorizontal; break;
×
NEW
964
            case PROBE_MOMENT_TIME_TRACE:
×
NEW
965
                if( _settings->GetProblemName() == PROBLEM_SymmetricHohlraum ) n_probes = 4;
×
966
                // if( _settings->GetProblemName() == PROBLEM_QuarterHohlraum ) n_probes = 2;
NEW
967
                for( unsigned i = 0; i < n_probes; i++ ) {
×
NEW
968
                    _screenOutputFields[idx_field] = _probingMoments[Idx2D( i, 0, 3 )];
×
NEW
969
                    idx_field++;
×
970
                }
NEW
971
                idx_field--;
×
NEW
972
                break;
×
NEW
973
            case VAR_ABSORPTION_GREEN: _screenOutputFields[idx_field] = _absorptionValsBlocksGreen[0]; break;
×
NEW
974
            default: ErrorMessages::Error( "Screen output group not defined!", CURRENT_FUNCTION ); break;
×
975
        }
976
    }
977

978
    // --- History output ---
NEW
979
    nFields = (unsigned)_settings->GetNHistoryOutput();
×
980

NEW
981
    std::vector<SCALAR_OUTPUT> screenOutputFields = _settings->GetScreenOutput();
×
NEW
982
    for( unsigned idx_field = 0; idx_field < nFields; idx_field++ ) {
×
983

984
        // Prepare all Output Fields per group
985
        // Different procedure, depending on the Group...
NEW
986
        switch( _settings->GetHistoryOutput()[idx_field] ) {
×
NEW
987
            case MASS: _historyOutputFields[idx_field] = _mass; break;
×
NEW
988
            case ITER: _historyOutputFields[idx_field] = idx_iter; break;
×
NEW
989
            case WALL_TIME: _historyOutputFields[idx_field] = _currTime; break;
×
NEW
990
            case RMS_FLUX: _historyOutputFields[idx_field] = _rmsFlux; break;
×
NEW
991
            case VTK_OUTPUT:
×
NEW
992
                _historyOutputFields[idx_field] = 0;
×
NEW
993
                if( ( _settings->GetVolumeOutputFrequency() != 0 && idx_iter % (unsigned)_settings->GetVolumeOutputFrequency() == 0 ) ||
×
NEW
994
                    ( idx_iter == _nIter - 1 ) /* need sol at last iteration */ ) {
×
NEW
995
                    _historyOutputFields[idx_field] = 1;
×
996
                }
NEW
997
                break;
×
998

NEW
999
            case CSV_OUTPUT:
×
NEW
1000
                _historyOutputFields[idx_field] = 0;
×
NEW
1001
                if( ( _settings->GetHistoryOutputFrequency() != 0 && idx_iter % (unsigned)_settings->GetHistoryOutputFrequency() == 0 ) ||
×
NEW
1002
                    ( idx_iter == _nIter - 1 ) /* need sol at last iteration */ ) {
×
NEW
1003
                    _historyOutputFields[idx_field] = 1;
×
1004
                }
NEW
1005
                break;
×
NEW
1006
            case CUR_OUTFLOW: _historyOutputFields[idx_field] = _curScalarOutflow; break;
×
NEW
1007
            case TOTAL_OUTFLOW: _historyOutputFields[idx_field] = _totalScalarOutflow; break;
×
NEW
1008
            case CUR_OUTFLOW_P1: _historyOutputFields[idx_field] = _curScalarOutflowPeri1; break;
×
NEW
1009
            case TOTAL_OUTFLOW_P1: _historyOutputFields[idx_field] = _totalScalarOutflowPeri1; break;
×
NEW
1010
            case CUR_OUTFLOW_P2: _historyOutputFields[idx_field] = _curScalarOutflowPeri2; break;
×
NEW
1011
            case TOTAL_OUTFLOW_P2: _historyOutputFields[idx_field] = _totalScalarOutflowPeri2; break;
×
NEW
1012
            case MAX_OUTFLOW: _historyOutputFields[idx_field] = _curMaxOrdinateOutflow; break;
×
NEW
1013
            case CUR_PARTICLE_ABSORPTION: _historyOutputFields[idx_field] = _curAbsorptionLattice; break;
×
NEW
1014
            case TOTAL_PARTICLE_ABSORPTION: _historyOutputFields[idx_field] = _totalAbsorptionLattice; break;
×
NEW
1015
            case MAX_PARTICLE_ABSORPTION: _historyOutputFields[idx_field] = _curMaxAbsorptionLattice; break;
×
NEW
1016
            case TOTAL_PARTICLE_ABSORPTION_CENTER: _historyOutputFields[idx_field] = _totalAbsorptionHohlraumCenter; break;
×
NEW
1017
            case TOTAL_PARTICLE_ABSORPTION_VERTICAL: _historyOutputFields[idx_field] = _totalAbsorptionHohlraumVertical; break;
×
NEW
1018
            case TOTAL_PARTICLE_ABSORPTION_HORIZONTAL: _historyOutputFields[idx_field] = _totalAbsorptionHohlraumHorizontal; break;
×
NEW
1019
            case PROBE_MOMENT_TIME_TRACE:
×
NEW
1020
                if( _settings->GetProblemName() == PROBLEM_SymmetricHohlraum ) n_probes = 4;
×
1021
                // if( _settings->GetProblemName() == PROBLEM_QuarterHohlraum ) n_probes = 2;
NEW
1022
                for( unsigned i = 0; i < n_probes; i++ ) {
×
NEW
1023
                    for( unsigned j = 0; j < 3; j++ ) {
×
NEW
1024
                        _historyOutputFields[idx_field] = _probingMoments[Idx2D( i, j, 3 )];
×
NEW
1025
                        idx_field++;
×
1026
                    }
1027
                }
NEW
1028
                idx_field--;
×
NEW
1029
                break;
×
NEW
1030
            case VAR_ABSORPTION_GREEN: _historyOutputFields[idx_field] = _varAbsorptionHohlraumGreen; break;
×
NEW
1031
            case ABSORPTION_GREEN_LINE:
×
NEW
1032
                for( unsigned i = 0; i < _settings->GetNumProbingCellsLineHohlraum(); i++ ) {
×
NEW
1033
                    _historyOutputFields[idx_field] = _absorptionValsLineSegment[i];
×
NEW
1034
                    idx_field++;
×
1035
                }
NEW
1036
                idx_field--;
×
NEW
1037
                break;
×
NEW
1038
            case ABSORPTION_GREEN_BLOCK:
×
NEW
1039
                for( unsigned i = 0; i < 44; i++ ) {
×
NEW
1040
                    _historyOutputFields[idx_field] = _absorptionValsBlocksGreen[i];
×
1041
                    // std::cout << _absorptionValsBlocksGreen[i] << "/" << _historyOutputFields[idx_field] << std::endl;
NEW
1042
                    idx_field++;
×
1043
                }
NEW
1044
                idx_field--;
×
NEW
1045
                break;
×
NEW
1046
            default: ErrorMessages::Error( "History output group not defined!", CURRENT_FUNCTION ); break;
×
1047
        }
1048
    }
1049
}
1050

NEW
1051
void SNSolverHPC::PrintScreenOutput( unsigned idx_iter ) {
×
NEW
1052
    auto log = spdlog::get( "event" );
×
1053

NEW
1054
    unsigned strLen  = 15;    // max width of one column
×
NEW
1055
    char paddingChar = ' ';
×
1056

1057
    // assemble the line to print
NEW
1058
    std::string lineToPrint = "| ";
×
NEW
1059
    std::string tmp;
×
NEW
1060
    for( unsigned idx_field = 0; idx_field < _settings->GetNScreenOutput(); idx_field++ ) {
×
NEW
1061
        tmp = std::to_string( _screenOutputFields[idx_field] );
×
1062

1063
        // Format outputs correctly
NEW
1064
        std::vector<SCALAR_OUTPUT> integerFields    = { ITER };
×
1065
        std::vector<SCALAR_OUTPUT> scientificFields = { RMS_FLUX,
1066
                                                        MASS,
1067
                                                        WALL_TIME,
1068
                                                        CUR_OUTFLOW,
1069
                                                        TOTAL_OUTFLOW,
1070
                                                        CUR_OUTFLOW_P1,
1071
                                                        TOTAL_OUTFLOW_P1,
1072
                                                        CUR_OUTFLOW_P2,
1073
                                                        TOTAL_OUTFLOW_P2,
1074
                                                        MAX_OUTFLOW,
1075
                                                        CUR_PARTICLE_ABSORPTION,
1076
                                                        TOTAL_PARTICLE_ABSORPTION,
1077
                                                        MAX_PARTICLE_ABSORPTION,
1078
                                                        TOTAL_PARTICLE_ABSORPTION_CENTER,
1079
                                                        TOTAL_PARTICLE_ABSORPTION_VERTICAL,
1080
                                                        TOTAL_PARTICLE_ABSORPTION_HORIZONTAL,
1081
                                                        PROBE_MOMENT_TIME_TRACE,
1082
                                                        VAR_ABSORPTION_GREEN,
1083
                                                        ABSORPTION_GREEN_BLOCK,
NEW
1084
                                                        ABSORPTION_GREEN_LINE };
×
NEW
1085
        std::vector<SCALAR_OUTPUT> booleanFields    = { VTK_OUTPUT, CSV_OUTPUT };
×
1086

NEW
1087
        if( !( integerFields.end() == std::find( integerFields.begin(), integerFields.end(), _settings->GetScreenOutput()[idx_field] ) ) ) {
×
NEW
1088
            tmp = std::to_string( (int)_screenOutputFields[idx_field] );
×
1089
        }
NEW
1090
        else if( !( booleanFields.end() == std::find( booleanFields.begin(), booleanFields.end(), _settings->GetScreenOutput()[idx_field] ) ) ) {
×
NEW
1091
            tmp = "no";
×
NEW
1092
            if( (bool)_screenOutputFields[idx_field] ) tmp = "yes";
×
1093
        }
NEW
1094
        else if( !( scientificFields.end() ==
×
NEW
1095
                    std::find( scientificFields.begin(), scientificFields.end(), _settings->GetScreenOutput()[idx_field] ) ) ) {
×
1096

NEW
1097
            std::stringstream ss;
×
NEW
1098
            ss << TextProcessingToolbox::DoubleToScientificNotation( _screenOutputFields[idx_field] );
×
NEW
1099
            tmp = ss.str();
×
NEW
1100
            tmp.erase( std::remove( tmp.begin(), tmp.end(), '+' ), tmp.end() );    // removing the '+' sign
×
1101
        }
1102

NEW
1103
        if( strLen > tmp.size() )    // Padding
×
NEW
1104
            tmp.insert( 0, strLen - tmp.size(), paddingChar );
×
NEW
1105
        else if( strLen < tmp.size() )    // Cutting
×
NEW
1106
            tmp.resize( strLen );
×
1107

NEW
1108
        lineToPrint += tmp + " |";
×
1109
    }
NEW
1110
    if( _settings->GetScreenOutputFrequency() != 0 && idx_iter % (unsigned)_settings->GetScreenOutputFrequency() == 0 ) {
×
NEW
1111
        log->info( lineToPrint );
×
1112
    }
NEW
1113
    else if( idx_iter == _nIter - 1 ) {    // Always print last iteration
×
NEW
1114
        log->info( lineToPrint );
×
1115
    }
1116
}
1117

NEW
1118
void SNSolverHPC::PrepareHistoryOutput() {
×
NEW
1119
    unsigned n_probes = 4;
×
1120

NEW
1121
    unsigned nFields = (unsigned)_settings->GetNHistoryOutput();
×
1122

NEW
1123
    _historyOutputFieldNames.resize( nFields );
×
NEW
1124
    _historyOutputFields.resize( nFields );
×
1125

1126
    // Prepare all output Fields ==> Specified in option SCREEN_OUTPUT
NEW
1127
    for( unsigned idx_field = 0; idx_field < nFields; idx_field++ ) {
×
1128
        // Prepare all Output Fields per group
1129

1130
        // Different procedure, depending on the Group...
NEW
1131
        switch( _settings->GetHistoryOutput()[idx_field] ) {
×
NEW
1132
            case MASS: _historyOutputFieldNames[idx_field] = "Mass"; break;
×
NEW
1133
            case ITER: _historyOutputFieldNames[idx_field] = "Iter"; break;
×
NEW
1134
            case WALL_TIME: _historyOutputFieldNames[idx_field] = "Wall_time_[s]"; break;
×
NEW
1135
            case RMS_FLUX: _historyOutputFieldNames[idx_field] = "RMS_flux"; break;
×
NEW
1136
            case VTK_OUTPUT: _historyOutputFieldNames[idx_field] = "VTK_out"; break;
×
NEW
1137
            case CSV_OUTPUT: _historyOutputFieldNames[idx_field] = "CSV_out"; break;
×
NEW
1138
            case CUR_OUTFLOW: _historyOutputFieldNames[idx_field] = "Cur_outflow"; break;
×
NEW
1139
            case TOTAL_OUTFLOW: _historyOutputFieldNames[idx_field] = "Total_outflow"; break;
×
NEW
1140
            case CUR_OUTFLOW_P1: _historyOutputFieldNames[idx_field] = "Cur_outflow_P1"; break;
×
NEW
1141
            case TOTAL_OUTFLOW_P1: _historyOutputFieldNames[idx_field] = "Total_outflow_P1"; break;
×
NEW
1142
            case CUR_OUTFLOW_P2: _historyOutputFieldNames[idx_field] = "Cur_outflow_P2"; break;
×
NEW
1143
            case TOTAL_OUTFLOW_P2: _historyOutputFieldNames[idx_field] = "Total_outflow_P2"; break;
×
NEW
1144
            case MAX_OUTFLOW: _historyOutputFieldNames[idx_field] = "Max_outflow"; break;
×
NEW
1145
            case CUR_PARTICLE_ABSORPTION: _historyOutputFieldNames[idx_field] = "Cur_absorption"; break;
×
NEW
1146
            case TOTAL_PARTICLE_ABSORPTION: _historyOutputFieldNames[idx_field] = "Total_absorption"; break;
×
NEW
1147
            case MAX_PARTICLE_ABSORPTION: _historyOutputFieldNames[idx_field] = "Max_absorption"; break;
×
NEW
1148
            case TOTAL_PARTICLE_ABSORPTION_CENTER: _historyOutputFieldNames[idx_field] = "Cumulated_absorption_center"; break;
×
NEW
1149
            case TOTAL_PARTICLE_ABSORPTION_VERTICAL: _historyOutputFieldNames[idx_field] = "Cumulated_absorption_vertical_wall"; break;
×
NEW
1150
            case TOTAL_PARTICLE_ABSORPTION_HORIZONTAL: _historyOutputFieldNames[idx_field] = "Cumulated_absorption_horizontal_wall"; break;
×
NEW
1151
            case PROBE_MOMENT_TIME_TRACE:
×
NEW
1152
                if( _settings->GetProblemName() == PROBLEM_SymmetricHohlraum ) n_probes = 4;
×
1153
                // if( _settings->GetProblemName() == PROBLEM_QuarterHohlraum ) n_probes = 2;
NEW
1154
                for( unsigned i = 0; i < n_probes; i++ ) {
×
NEW
1155
                    for( unsigned j = 0; j < 3; j++ ) {
×
NEW
1156
                        _historyOutputFieldNames[idx_field] = "Probe " + std::to_string( i ) + " u_" + std::to_string( j );
×
NEW
1157
                        idx_field++;
×
1158
                    }
1159
                }
NEW
1160
                idx_field--;
×
NEW
1161
                break;
×
NEW
1162
            case VAR_ABSORPTION_GREEN: _historyOutputFieldNames[idx_field] = "Var. absorption green"; break;
×
NEW
1163
            case ABSORPTION_GREEN_BLOCK:
×
NEW
1164
                for( unsigned i = 0; i < 44; i++ ) {
×
NEW
1165
                    _historyOutputFieldNames[idx_field] = "Probe Green Block " + std::to_string( i );
×
NEW
1166
                    idx_field++;
×
1167
                }
NEW
1168
                idx_field--;
×
NEW
1169
                break;
×
1170

NEW
1171
            case ABSORPTION_GREEN_LINE:
×
NEW
1172
                for( unsigned i = 0; i < _settings->GetNumProbingCellsLineHohlraum(); i++ ) {
×
NEW
1173
                    _historyOutputFieldNames[idx_field] = "Probe Green Line " + std::to_string( i );
×
NEW
1174
                    idx_field++;
×
1175
                }
NEW
1176
                idx_field--;
×
NEW
1177
                break;
×
NEW
1178
            default: ErrorMessages::Error( "History output field not defined!", CURRENT_FUNCTION ); break;
×
1179
        }
1180
    }
1181
}
1182

NEW
1183
void SNSolverHPC::PrintHistoryOutput( unsigned idx_iter ) {
×
1184

NEW
1185
    auto log = spdlog::get( "tabular" );
×
1186

1187
    // assemble the line to print
NEW
1188
    std::string lineToPrint = "";
×
NEW
1189
    std::string tmp;
×
NEW
1190
    for( int idx_field = 0; idx_field < _settings->GetNHistoryOutput() - 1; idx_field++ ) {
×
NEW
1191
        if( idx_field == 0 ) {
×
NEW
1192
            tmp = std::to_string( _historyOutputFields[idx_field] );    // Iteration count
×
1193
        }
1194
        else {
NEW
1195
            tmp = TextProcessingToolbox::DoubleToScientificNotation( _historyOutputFields[idx_field] );
×
1196
        }
NEW
1197
        lineToPrint += tmp + ",";
×
1198
    }
NEW
1199
    tmp = TextProcessingToolbox::DoubleToScientificNotation( _historyOutputFields[_settings->GetNHistoryOutput() - 1] );
×
NEW
1200
    lineToPrint += tmp;    // Last element without comma
×
1201
    // std::cout << lineToPrint << std::endl;
NEW
1202
    if( _settings->GetHistoryOutputFrequency() != 0 && idx_iter % (unsigned)_settings->GetHistoryOutputFrequency() == 0 ) {
×
NEW
1203
        log->info( lineToPrint );
×
1204
    }
NEW
1205
    else if( idx_iter == _nIter - 1 ) {    // Always print last iteration
×
NEW
1206
        log->info( lineToPrint );
×
1207
    }
1208
}
1209

NEW
1210
void SNSolverHPC::DrawPreSolverOutput() {
×
1211

1212
    // Logger
NEW
1213
    auto log    = spdlog::get( "event" );
×
NEW
1214
    auto logCSV = spdlog::get( "tabular" );
×
1215

NEW
1216
    std::string hLine = "--";
×
1217

NEW
1218
    unsigned strLen  = 15;    // max width of one column
×
NEW
1219
    char paddingChar = ' ';
×
1220

1221
    // Assemble Header for Screen Output
NEW
1222
    std::string lineToPrint = "| ";
×
NEW
1223
    std::string tmpLine     = "-----------------";
×
NEW
1224
    for( unsigned idxFields = 0; idxFields < _settings->GetNScreenOutput(); idxFields++ ) {
×
NEW
1225
        std::string tmp = _screenOutputFieldNames[idxFields];
×
1226

NEW
1227
        if( strLen > tmp.size() )    // Padding
×
NEW
1228
            tmp.insert( 0, strLen - tmp.size(), paddingChar );
×
NEW
1229
        else if( strLen < tmp.size() )    // Cutting
×
NEW
1230
            tmp.resize( strLen );
×
1231

NEW
1232
        lineToPrint += tmp + " |";
×
NEW
1233
        hLine += tmpLine;
×
1234
    }
NEW
1235
    log->info( "---------------------------- Solver Starts -----------------------------" );
×
NEW
1236
    log->info( "| The simulation will run for {} iterations.", _nIter );
×
NEW
1237
    log->info( "| The spatial grid contains {} cells.", _nCells );
×
NEW
1238
    if( _settings->GetSolverName() != PN_SOLVER && _settings->GetSolverName() != CSD_PN_SOLVER ) {
×
NEW
1239
        log->info( "| The velocity grid contains {} points.", _nq );
×
1240
    }
NEW
1241
    log->info( hLine );
×
NEW
1242
    log->info( lineToPrint );
×
NEW
1243
    log->info( hLine );
×
1244

NEW
1245
    std::string lineToPrintCSV = "";
×
NEW
1246
    for( int idxFields = 0; idxFields < _settings->GetNHistoryOutput() - 1; idxFields++ ) {
×
NEW
1247
        std::string tmp = _historyOutputFieldNames[idxFields];
×
NEW
1248
        lineToPrintCSV += tmp + ",";
×
1249
    }
NEW
1250
    lineToPrintCSV += _historyOutputFieldNames[_settings->GetNHistoryOutput() - 1];
×
NEW
1251
    logCSV->info( lineToPrintCSV );
×
1252
}
1253

NEW
1254
void SNSolverHPC::DrawPostSolverOutput() {
×
1255

1256
    // Logger
NEW
1257
    auto log = spdlog::get( "event" );
×
1258

NEW
1259
    std::string hLine = "--";
×
1260

NEW
1261
    unsigned strLen  = 10;    // max width of one column
×
NEW
1262
    char paddingChar = ' ';
×
1263

1264
    // Assemble Header for Screen Output
NEW
1265
    std::string lineToPrint = "| ";
×
NEW
1266
    std::string tmpLine     = "------------";
×
NEW
1267
    for( unsigned idxFields = 0; idxFields < _settings->GetNScreenOutput(); idxFields++ ) {
×
NEW
1268
        std::string tmp = _screenOutputFieldNames[idxFields];
×
1269

NEW
1270
        if( strLen > tmp.size() )    // Padding
×
NEW
1271
            tmp.insert( 0, strLen - tmp.size(), paddingChar );
×
NEW
1272
        else if( strLen < tmp.size() )    // Cutting
×
NEW
1273
            tmp.resize( strLen );
×
1274

NEW
1275
        lineToPrint += tmp + " |";
×
NEW
1276
        hLine += tmpLine;
×
1277
    }
NEW
1278
    log->info( hLine );
×
1279
#ifndef BUILD_TESTING
1280
    log->info( "| The volume output files have been stored at " + _settings->GetOutputFile() );
1281
    log->info( "| The log files have been stored at " + _settings->GetLogDir() + _settings->GetLogFile() );
1282
#endif
NEW
1283
    log->info( "--------------------------- Solver Finished ----------------------------" );
×
1284
}
1285

NEW
1286
unsigned long SNSolverHPC::Idx2D( unsigned long idx1, unsigned long idx2, unsigned long len2 ) { return idx1 * len2 + idx2; }
×
1287

NEW
1288
unsigned long SNSolverHPC::Idx3D( unsigned long idx1, unsigned long idx2, unsigned long idx3, unsigned long len2, unsigned long len3 ) {
×
NEW
1289
    return ( idx1 * len2 + idx2 ) * len3 + idx3;
×
1290
}
1291

NEW
1292
void SNSolverHPC::WriteVolumeOutput( unsigned idx_iter ) {
×
NEW
1293
    unsigned nGroups = (unsigned)_settings->GetNVolumeOutput();
×
NEW
1294
    if( ( _settings->GetVolumeOutputFrequency() != 0 && idx_iter % (unsigned)_settings->GetVolumeOutputFrequency() == 0 ) ||
×
NEW
1295
        ( idx_iter == _nIter - 1 ) /* need sol at last iteration */ ) {
×
NEW
1296
        for( unsigned idx_group = 0; idx_group < nGroups; idx_group++ ) {
×
NEW
1297
            switch( _settings->GetVolumeOutput()[idx_group] ) {
×
NEW
1298
                case MINIMAL:
×
NEW
1299
                    if( _rank == 0 ) {
×
NEW
1300
                        _outputFields[idx_group][0] = _scalarFlux;
×
1301
                    }
NEW
1302
                    break;
×
1303

NEW
1304
                case MOMENTS:
×
NEW
1305
#pragma omp parallel for
×
1306
                    for( unsigned idx_cell = 0; idx_cell < _nCells; ++idx_cell ) {
1307
                        _outputFields[idx_group][0][idx_cell] = 0.0;
1308
                        _outputFields[idx_group][1][idx_cell] = 0.0;
1309
                        for( unsigned idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
1310
                            _outputFields[idx_group][0][idx_cell] +=
1311
                                _quadPts[Idx2D( idx_sys, 0, _nDim )] * _sol[Idx2D( idx_cell, idx_sys, _localNSys )] * _quadWeights[idx_sys];
1312
                            _outputFields[idx_group][1][idx_cell] +=
1313
                                _quadPts[Idx2D( idx_sys, 1, _nDim )] * _sol[Idx2D( idx_cell, idx_sys, _localNSys )] * _quadWeights[idx_sys];
1314
                        }
1315
                    }
1316
#ifdef BUILD_MPI
1317
                    MPI_Barrier( MPI_COMM_WORLD );
1318
                    MPI_Allreduce(
1319
                        _outputFields[idx_group][0].data(), _outputFields[idx_group][0].data(), _nCells, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
1320
                    MPI_Allreduce(
1321
                        _outputFields[idx_group][1].data(), _outputFields[idx_group][1].data(), _nCells, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
1322
                    MPI_Barrier( MPI_COMM_WORLD );
1323
#endif
NEW
1324
                    break;
×
NEW
1325
                default: ErrorMessages::Error( "Volume Output Group not defined for HPC SN Solver!", CURRENT_FUNCTION ); break;
×
1326
            }
1327
        }
1328
    }
1329
}
1330

NEW
1331
void SNSolverHPC::PrintVolumeOutput( int idx_iter ) {
×
NEW
1332
    if( _settings->GetSaveRestartSolutionFrequency() != 0 && idx_iter % (int)_settings->GetSaveRestartSolutionFrequency() == 0 ) {
×
1333
        // std::cout << "Saving restart solution at iteration " << idx_iter << std::endl;
NEW
1334
        WriteRestartSolution( _settings->GetOutputFile(),
×
NEW
1335
                              _sol,
×
NEW
1336
                              _scalarFlux,
×
1337
                              _rank,
1338
                              idx_iter,
1339
                              _totalAbsorptionHohlraumCenter,
1340
                              _totalAbsorptionHohlraumVertical,
1341
                              _totalAbsorptionHohlraumHorizontal,
1342
                              _totalAbsorptionLattice );
1343
    }
1344

NEW
1345
    if( _settings->GetVolumeOutputFrequency() != 0 && idx_iter % (int)_settings->GetVolumeOutputFrequency() == 0 ) {
×
NEW
1346
        WriteVolumeOutput( idx_iter );
×
NEW
1347
        if( _rank == 0 ) {
×
NEW
1348
            ExportVTK( _settings->GetOutputFile() + "_" + std::to_string( idx_iter ), _outputFields, _outputFieldNames, _mesh );    // slow
×
1349
        }
1350
    }
NEW
1351
    if( idx_iter == (int)_nIter - 1 ) {    // Last iteration write without suffix.
×
NEW
1352
        WriteVolumeOutput( idx_iter );
×
NEW
1353
        if( _rank == 0 ) {
×
NEW
1354
            ExportVTK( _settings->GetOutputFile(), _outputFields, _outputFieldNames, _mesh );
×
1355
        }
1356
    }
1357
}
1358

NEW
1359
void SNSolverHPC::PrepareVolumeOutput() {
×
NEW
1360
    unsigned nGroups = (unsigned)_settings->GetNVolumeOutput();
×
1361

NEW
1362
    _outputFieldNames.resize( nGroups );
×
NEW
1363
    _outputFields.resize( nGroups );
×
1364

1365
    // Prepare all OutputGroups ==> Specified in option VOLUME_OUTPUT
NEW
1366
    for( unsigned idx_group = 0; idx_group < nGroups; idx_group++ ) {
×
1367
        // Prepare all Output Fields per group
1368

1369
        // Different procedure, depending on the Group...
NEW
1370
        switch( _settings->GetVolumeOutput()[idx_group] ) {
×
NEW
1371
            case MINIMAL:
×
1372
                // Currently only one entry ==> rad flux
NEW
1373
                _outputFields[idx_group].resize( 1 );
×
NEW
1374
                _outputFieldNames[idx_group].resize( 1 );
×
1375

NEW
1376
                _outputFields[idx_group][0].resize( _nCells );
×
NEW
1377
                _outputFieldNames[idx_group][0] = "scalar flux";
×
NEW
1378
                break;
×
NEW
1379
            case MOMENTS:
×
1380
                // As many entries as there are moments in the system
NEW
1381
                _outputFields[idx_group].resize( _nOutputMoments );
×
NEW
1382
                _outputFieldNames[idx_group].resize( _nOutputMoments );
×
1383

NEW
1384
                for( unsigned idx_moment = 0; idx_moment < _nOutputMoments; idx_moment++ ) {
×
NEW
1385
                    _outputFieldNames[idx_group][idx_moment] = std::string( "u_" + std::to_string( idx_moment ) );
×
NEW
1386
                    _outputFields[idx_group][idx_moment].resize( _nCells );
×
1387
                }
NEW
1388
                break;
×
1389

NEW
1390
            default: ErrorMessages::Error( "Volume Output Group not defined for HPC SN Solver!", CURRENT_FUNCTION ); break;
×
1391
        }
1392
    }
1393
}
1394

NEW
1395
void SNSolverHPC::SetGhostCells() {
×
NEW
1396
    if( _settings->GetProblemName() == PROBLEM_Lattice ) {
×
1397
        // #pragma omp parallel for
NEW
1398
        for( unsigned idx_cell = 0; idx_cell < _nCells; idx_cell++ ) {
×
NEW
1399
            if( _cellBoundaryTypes[idx_cell] == BOUNDARY_TYPE::NEUMANN || _cellBoundaryTypes[idx_cell] == BOUNDARY_TYPE::DIRICHLET ) {
×
NEW
1400
                _ghostCells[idx_cell] = std::vector<double>( _localNSys, 0.0 );
×
1401
            }
1402
        }
1403
    }
NEW
1404
    else if( _settings->GetProblemName() == PROBLEM_HalfLattice ) {    // HALF LATTICE NOT WORKING
×
NEW
1405
        ErrorMessages::Error( "Test case does not work with MPI", CURRENT_FUNCTION );
×
1406
    }
NEW
1407
    else if( _settings->GetProblemName() == PROBLEM_SymmetricHohlraum ) {
×
1408

NEW
1409
        auto nodes = _mesh->GetNodes();
×
NEW
1410
        double tol = 1e-12;    // For distance to boundary
×
1411

1412
        // #pragma omp parallel for
NEW
1413
        for( unsigned idx_cell = 0; idx_cell < _nCells; idx_cell++ ) {
×
1414

NEW
1415
            if( _cellBoundaryTypes[idx_cell] == BOUNDARY_TYPE::NEUMANN || _cellBoundaryTypes[idx_cell] == BOUNDARY_TYPE::DIRICHLET ) {
×
NEW
1416
                _ghostCells[idx_cell] = std::vector<double>( _localNSys, 0.0 );
×
1417

NEW
1418
                auto localCellNodes = _mesh->GetCells()[idx_cell];
×
1419

NEW
1420
                for( unsigned idx_node = 0; idx_node < _mesh->GetNumNodesPerCell(); idx_node++ ) {    // Check if corner node is in this cell
×
NEW
1421
                    if( nodes[localCellNodes[idx_node]][0] < -0.65 + tol ) {                          // close to 0 => left boundary
×
NEW
1422
                        for( unsigned idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
×
NEW
1423
                            if( _quadPts[Idx2D( idx_sys, 0, _nDim )] > 0.0 ) _ghostCells[idx_cell][idx_sys] = 1.0;
×
1424
                        }
NEW
1425
                        break;
×
1426
                    }
NEW
1427
                    else if( nodes[localCellNodes[idx_node]][0] > 0.65 - tol ) {    // right boundary
×
NEW
1428
                        for( unsigned idx_sys = 0; idx_sys < _localNSys; idx_sys++ ) {
×
NEW
1429
                            if( _quadPts[Idx2D( idx_sys, 0, _nDim )] < 0.0 ) _ghostCells[idx_cell][idx_sys] = 1.0;
×
1430
                        }
NEW
1431
                        break;
×
1432
                    }
NEW
1433
                    else if( nodes[localCellNodes[idx_node]][1] < -0.65 + tol ) {    // lower boundary
×
NEW
1434
                        break;
×
1435
                    }
NEW
1436
                    else if( nodes[localCellNodes[idx_node]][1] > 0.65 - tol ) {    // upper boundary
×
NEW
1437
                        break;
×
1438
                    }
NEW
1439
                    else if( idx_node == _mesh->GetNumNodesPerCell() - 1 ) {
×
NEW
1440
                        ErrorMessages::Error( " Problem with ghost cell setup and  boundary of this mesh ", CURRENT_FUNCTION );
×
1441
                    }
1442
                }
1443
            }
1444
        }
1445
    }
NEW
1446
    else if( _settings->GetProblemName() == PROBLEM_QuarterHohlraum ) {
×
NEW
1447
        ErrorMessages::Error( "Test case does not work with MPI", CURRENT_FUNCTION );
×
1448
    }
1449
}
1450

NEW
1451
void SNSolverHPC::SetProbingCellsLineGreen() {
×
1452

1453
    // if( _settings->GetProblemName() == PROBLEM_QuarterHohlraum ) {
1454
    //     double verticalLineWidth   = std::abs( _cornerUpperLeftGreen[1] - _cornerLowerLeftGreen[1] );
1455
    //     double horizontalLineWidth = std::abs( _cornerUpperLeftGreen[0] - _cornerUpperRightGreen[0] );
1456
    //
1457
    //     // double dx = 2 * ( horizontalLineWidth + verticalLineWidth ) / ( (double)_nProbingCellsLineGreen );
1458
    //
1459
    //     unsigned nHorizontalProbingCells =
1460
    //         (unsigned)std::ceil( _nProbingCellsLineGreen * ( horizontalLineWidth / ( horizontalLineWidth + verticalLineWidth ) ) );
1461
    //     unsigned nVerticalProbingCells = _nProbingCellsLineGreen - nHorizontalProbingCells;
1462
    //
1463
    //     _probingCellsLineGreen = std::vector<unsigned>( _nProbingCellsLineGreen );
1464
    //
1465
    //     // Sample points on each side of the rectangle
1466
    //     std::vector<unsigned> side3 = linspace2D( _cornerLowerRightGreen, _cornerUpperRightGreen, nVerticalProbingCells );
1467
    //     std::vector<unsigned> side4 = linspace2D( _cornerUpperRightGreen, _cornerUpperLeftGreen, nHorizontalProbingCells );
1468
    //
1469
    //     //  Combine the points from each side
1470
    //     _probingCellsLineGreen.insert( _probingCellsLineGreen.end(), side3.begin(), side3.end() );
1471
    //     _probingCellsLineGreen.insert( _probingCellsLineGreen.end(), side4.begin(), side4.end() );
1472
    // }
1473
    // else
NEW
1474
    if( _settings->GetProblemName() == PROBLEM_SymmetricHohlraum ) {
×
1475

NEW
1476
        std::vector<double> p1 = { _cornerUpperLeftGreen[0] + _thicknessGreen / 2.0, _cornerUpperLeftGreen[1] - _thicknessGreen / 2.0 };
×
NEW
1477
        std::vector<double> p2 = { _cornerUpperRightGreen[0] - _thicknessGreen / 2.0, _cornerUpperRightGreen[1] - _thicknessGreen / 2.0 };
×
NEW
1478
        std::vector<double> p3 = { _cornerLowerRightGreen[0] - _thicknessGreen / 2.0, _cornerLowerRightGreen[1] + _thicknessGreen / 2.0 };
×
NEW
1479
        std::vector<double> p4 = { _cornerLowerLeftGreen[0] + _thicknessGreen / 2.0, _cornerLowerLeftGreen[1] + _thicknessGreen / 2.0 };
×
1480

NEW
1481
        double verticalLineWidth   = std::abs( p1[1] - p4[1] );
×
NEW
1482
        double horizontalLineWidth = std::abs( p1[0] - p2[0] );
×
1483

NEW
1484
        double pt_ratio_h = horizontalLineWidth / ( horizontalLineWidth + verticalLineWidth );
×
NEW
1485
        double pt_ratio_v = verticalLineWidth / ( horizontalLineWidth + verticalLineWidth );
×
1486

NEW
1487
        unsigned nHorizontalProbingCells = (unsigned)std::ceil( _nProbingCellsLineGreen / 2 * pt_ratio_h );
×
NEW
1488
        unsigned nVerticalProbingCells   = _nProbingCellsLineGreen / 2 - nHorizontalProbingCells;
×
1489

NEW
1490
        _probingCellsLineGreen = std::vector<unsigned>( 2 * ( nVerticalProbingCells + nHorizontalProbingCells ) );
×
1491

1492
        // Sample points on each side of the rectangle
NEW
1493
        std::vector<unsigned> side1 = linspace2D( p1, p2, nHorizontalProbingCells );    // upper horizontal
×
NEW
1494
        std::vector<unsigned> side2 = linspace2D( p2, p3, nVerticalProbingCells );      // right vertical
×
NEW
1495
        std::vector<unsigned> side3 = linspace2D( p3, p4, nHorizontalProbingCells );    // lower horizontal
×
NEW
1496
        std::vector<unsigned> side4 = linspace2D( p4, p1, nVerticalProbingCells );      // left vertical
×
1497

NEW
1498
        for( unsigned i = 0; i < nHorizontalProbingCells; ++i ) {
×
NEW
1499
            _probingCellsLineGreen[i] = side1[i];
×
1500
        }
NEW
1501
        for( unsigned i = 0; i < nVerticalProbingCells; ++i ) {
×
NEW
1502
            _probingCellsLineGreen[i + nHorizontalProbingCells] = side2[i];
×
1503
        }
NEW
1504
        for( unsigned i = 0; i < nHorizontalProbingCells; ++i ) {
×
NEW
1505
            _probingCellsLineGreen[i + nVerticalProbingCells + nHorizontalProbingCells] = side3[i];
×
1506
        }
NEW
1507
        for( unsigned i = 0; i < nVerticalProbingCells; ++i ) {
×
NEW
1508
            _probingCellsLineGreen[i + nVerticalProbingCells + 2 * nHorizontalProbingCells] = side4[i];
×
1509
        }
1510

1511
        // Block-wise approach
1512
        // Initialize the vector to store the corner points of each block
NEW
1513
        std::vector<std::vector<std::vector<double>>> block_corners;
×
1514

NEW
1515
        double block_size = 0.05;
×
1516

1517
        // Loop to fill the blocks
NEW
1518
        for( int i = 0; i < 8; ++i ) {    // 8 blocks in the x-direction (horizontal) (upper) (left to right)
×
1519

1520
            // Top row
NEW
1521
            double x1 = -0.2 + i * block_size;
×
NEW
1522
            double y1 = 0.4;
×
NEW
1523
            double x2 = x1 + block_size;
×
NEW
1524
            double y2 = y1 - block_size;
×
1525

1526
            std::vector<std::vector<double>> corners = {
1527
                { x1, y1 },    // top-left
1528
                { x2, y1 },    // top-right
1529
                { x2, y2 },    // bottom-right
1530
                { x1, y2 }     // bottom-left
1531
            };
NEW
1532
            block_corners.push_back( corners );
×
1533
        }
1534

NEW
1535
        for( int j = 0; j < 14; ++j ) {    // 14 blocks in the y-direction (vertical)
×
1536
            // right column double x1 = 0.15;
NEW
1537
            double x1 = 0.15;
×
NEW
1538
            double y1 = 0.35 - j * block_size;
×
NEW
1539
            double x2 = x1 + block_size;
×
NEW
1540
            double y2 = y1 - block_size;
×
1541

1542
            // Store the four corner points for this block
1543
            std::vector<std::vector<double>> corners = {
1544
                { x1, y1 },    // top-left
1545
                { x2, y1 },    // top-right
1546
                { x2, y2 },    // bottom-right
1547
                { x1, y2 }     // bottom-left
1548
            };
1549

NEW
1550
            block_corners.push_back( corners );
×
1551
        }
1552

NEW
1553
        for( int i = 0; i < 8; ++i ) {    // 8 blocks in the x-direction (horizontal) (lower) (right to left)
×
1554
            // bottom row
NEW
1555
            double x1 = 0.15 - i * block_size;
×
NEW
1556
            double y1 = -0.35;
×
NEW
1557
            double x2 = x1 + block_size;
×
NEW
1558
            double y2 = y1 - block_size;
×
1559

1560
            std::vector<std::vector<double>> corners = {
1561
                { x1, y1 },    // top-left
1562
                { x2, y1 },    // top-right
1563
                { x2, y2 },    // bottom-right
1564
                { x1, y2 }     // bottom-left
1565
            };
NEW
1566
            block_corners.push_back( corners );
×
1567
        }
1568

NEW
1569
        for( int j = 0; j < 14; ++j ) {    // 14 blocks in the y-direction (vertical) (down to up)
×
1570

1571
            // left column
NEW
1572
            double x1 = -0.2;
×
NEW
1573
            double y1 = -0.3 + j * block_size;
×
NEW
1574
            double x2 = x1 + block_size;
×
NEW
1575
            double y2 = y1 - block_size;
×
1576

1577
            // Store the four corner points for this block
1578
            std::vector<std::vector<double>> corners = {
1579
                { x1, y1 },    // top-left
1580
                { x2, y1 },    // top-right
1581
                { x2, y2 },    // bottom-right
1582
                { x1, y2 }     // bottom-left
1583
            };
1584

NEW
1585
            block_corners.push_back( corners );
×
1586
        }
1587

1588
        // Compute the probing cells for each block
NEW
1589
        for( int i = 0; i < _nProbingCellsBlocksGreen; i++ ) {
×
NEW
1590
            _probingCellsBlocksGreen.push_back( _mesh->GetCellsofRectangle( block_corners[i] ) );
×
1591
        }
1592
    }
1593
}
1594

NEW
1595
void SNSolverHPC::ComputeQOIsGreenProbingLine() {
×
NEW
1596
    double verticalLineWidth   = std::abs( _cornerUpperLeftGreen[1] - _cornerLowerLeftGreen[1] - _thicknessGreen );
×
NEW
1597
    double horizontalLineWidth = std::abs( _cornerUpperLeftGreen[0] - _cornerUpperRightGreen[0] - _thicknessGreen );
×
1598

NEW
1599
    double dl    = 2 * ( horizontalLineWidth + verticalLineWidth ) / ( (double)_nProbingCellsLineGreen );
×
NEW
1600
    double area  = dl * _thicknessGreen;
×
NEW
1601
    double l_max = _nProbingCellsLineGreen * dl;
×
1602

NEW
1603
#pragma omp parallel for
×
1604
    for( unsigned i = 0; i < _nProbingCellsLineGreen; i++ ) {    // Loop over probing cells
1605
        _absorptionValsLineSegment[i] =
1606
            ( _sigmaT[_probingCellsLineGreen[i]] - _sigmaS[_probingCellsLineGreen[i]] ) * _scalarFlux[_probingCellsLineGreen[i]];
1607
    }
1608

1609
    // Block-wise approach
1610
    // #pragma omp parallel for
NEW
1611
    for( unsigned i = 0; i < _nProbingCellsBlocksGreen; i++ ) {
×
NEW
1612
        _absorptionValsBlocksGreen[i] = 0.0;
×
NEW
1613
        for( unsigned j = 0; j < _probingCellsBlocksGreen[i].size(); j++ ) {
×
NEW
1614
            _absorptionValsBlocksGreen[i] += ( _sigmaT[_probingCellsBlocksGreen[i][j]] - _sigmaS[_probingCellsBlocksGreen[i][j]] ) *
×
NEW
1615
                                             _scalarFlux[_probingCellsBlocksGreen[i][j]] * _areas[_probingCellsBlocksGreen[i][j]];
×
1616
        }
1617
    }
1618
    // std::cout << _absorptionValsBlocksGreen[1] << std::endl;
1619
    // std::cout << _absorptionValsLineSegment[1] << std::endl;
1620
}
1621

NEW
1622
std::vector<unsigned> SNSolverHPC::linspace2D( const std::vector<double>& start, const std::vector<double>& end, unsigned num_points ) {
×
1623
    /**
1624
     * Generate a 2D linspace based on the start and end points with a specified number of points.
1625
     *
1626
     * @param start vector of starting x and y coordinates
1627
     * @param end vector of ending x and y coordinates
1628
     * @param num_points number of points to generate
1629
     *
1630
     * @return vector of unsigned integers representing the result
1631
     */
1632

NEW
1633
    std::vector<unsigned> result;
×
NEW
1634
    result.resize( num_points );
×
NEW
1635
    double stepX = ( end[0] - start[0] ) / ( num_points - 1 );
×
NEW
1636
    double stepY = ( end[1] - start[1] ) / ( num_points - 1 );
×
NEW
1637
#pragma omp parallel for
×
1638
    for( unsigned i = 0; i < num_points; ++i ) {
1639
        double x = start[0] + i * stepX;
1640
        double y = start[1] + i * stepY;
1641

1642
        result[i] = _mesh->GetCellOfKoordinate( x, y );
1643
    }
1644

NEW
1645
    return result;
×
1646
}
1647

NEW
1648
void SNSolverHPC::ComputeCellsPerimeterLattice() {
×
NEW
1649
    double l_1    = 1.5;    // perimeter 1
×
NEW
1650
    double l_2    = 2.5;    // perimeter 2
×
NEW
1651
    auto nodes    = _mesh->GetNodes();
×
NEW
1652
    auto cells    = _mesh->GetCells();
×
NEW
1653
    auto cellMids = _mesh->GetCellMidPoints();
×
NEW
1654
    auto normals  = _mesh->GetNormals();
×
NEW
1655
    auto neigbors = _mesh->GetNeighbours();
×
1656

NEW
1657
    _isPerimeterLatticeCell1.resize( _mesh->GetNumCells(), false );
×
NEW
1658
    _isPerimeterLatticeCell2.resize( _mesh->GetNumCells(), false );
×
1659

NEW
1660
    for( unsigned idx_cell = 0; idx_cell < _mesh->GetNumCells(); ++idx_cell ) {
×
NEW
1661
        if( abs( cellMids[idx_cell][0] ) < l_1 && abs( cellMids[idx_cell][1] ) < l_1 ) {
×
1662
            // Cell is within perimeter
NEW
1663
            for( unsigned idx_nbr = 0; idx_nbr < _mesh->GetNumNodesPerCell(); ++idx_nbr ) {
×
NEW
1664
                if( neigbors[idx_cell][idx_nbr] == _mesh->GetNumCells() ) {
×
NEW
1665
                    continue;    // Skip boundary - ghost cells
×
1666
                }
1667

NEW
1668
                if( abs( ( cellMids[neigbors[idx_cell][idx_nbr]][0] ) > l_1 && abs( cellMids[idx_cell][0] ) < l_1 ) ||
×
NEW
1669
                    abs( ( cellMids[neigbors[idx_cell][idx_nbr]][1] ) > l_1 && abs( cellMids[idx_cell][1] ) < l_1 ) ) {
×
1670
                    // neighbor is outside perimeter
NEW
1671
                    _cellsLatticePerimeter1[idx_cell].push_back( idx_nbr );
×
NEW
1672
                    _isPerimeterLatticeCell1[idx_cell] = true;
×
1673
                }
1674
            }
1675
        }
NEW
1676
        if( abs( cellMids[idx_cell][0] ) < l_2 && abs( cellMids[idx_cell][1] ) < l_2 && abs( cellMids[idx_cell][0] ) > l_1 &&
×
NEW
1677
            abs( cellMids[idx_cell][1] ) > l_1 ) {
×
1678
            // Cell is within perimeter
NEW
1679
            for( unsigned idx_nbr = 0; idx_nbr < _mesh->GetNumNodesPerCell(); ++idx_nbr ) {
×
NEW
1680
                if( neigbors[idx_cell][idx_nbr] == _mesh->GetNumCells() ) {
×
NEW
1681
                    continue;    // Skip boundary - ghost cells
×
1682
                }
NEW
1683
                if( abs( ( cellMids[neigbors[idx_cell][idx_nbr]][0] ) > l_2 && abs( cellMids[idx_cell][0] ) < l_2 ) ||
×
NEW
1684
                    abs( ( cellMids[neigbors[idx_cell][idx_nbr]][1] ) > l_2 && abs( cellMids[idx_cell][1] ) < l_2 ) ) {
×
1685
                    // neighbor is outside perimeter
NEW
1686
                    _cellsLatticePerimeter2[idx_cell].push_back( idx_nbr );
×
NEW
1687
                    _isPerimeterLatticeCell2[idx_cell] = true;
×
1688
                }
1689
            }
1690
        }
1691
    }
1692
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc