• 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

67.89
/src/common/io.cpp
1
/*!
2
 * \file io.cpp
3
 * \brief Set of utility io functions for KiT-RT
4
 * \author  J. Kusch, S. Schotthoefer, P. Stammer,  J. Wolters, T. Xiao
5
 */
6

7
#include "common/io.hpp"
8
#include "common/config.hpp"
9
#include "common/mesh.hpp"
10
#include "common/typedef.hpp"
11
#include "toolboxes/errormessages.hpp"
12
#include "toolboxes/textprocessingtoolbox.hpp"
13

14
#include <filesystem>
15
#include <fstream>
16
#include <iomanip>
17
#include <iostream>
18
#include <sstream>
19

20
#ifdef IMPORT_MPI
21
#include <mpi.h>
22
#endif
23

24
#include <omp.h>
25
#include <sstream>
26
#include <vector>
27
#include <vtkCellArray.h>
28
#include <vtkCellData.h>
29
#include <vtkCellDataToPointData.h>
30
#include <vtkDoubleArray.h>
31
#include <vtkPointData.h>
32
#include <vtkQuad.h>
33
#include <vtkSmartPointer.h>
34
#include <vtkTriangle.h>
35
#include <vtkUnstructuredGrid.h>
36
#include <vtkUnstructuredGridWriter.h>
37

38
// #include <Python.h>
39
// #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
40
// #include <numpy/arrayobject.h>
41

42
using vtkPointsSP                 = vtkSmartPointer<vtkPoints>;
43
using vtkUnstructuredGridSP       = vtkSmartPointer<vtkUnstructuredGrid>;
44
using vtkTriangleSP               = vtkSmartPointer<vtkTriangle>;
45
using vtkCellArraySP              = vtkSmartPointer<vtkCellArray>;
46
using vtkDoubleArraySP            = vtkSmartPointer<vtkDoubleArray>;
47
using vtkUnstructuredGridWriterSP = vtkSmartPointer<vtkUnstructuredGridWriter>;
48
using vtkCellDataToPointDataSP    = vtkSmartPointer<vtkCellDataToPointData>;
49

50
void ExportVTK( const std::string fileName,
42✔
51
                const std::vector<std::vector<std::vector<double>>>& outputFields,
52
                const std::vector<std::vector<std::string>>& outputFieldNames,
53
                const Mesh* mesh ) {
54
    int rank   = 0;
42✔
55
    int nprocs = 1;
42✔
56
#ifdef IMPORT_MPI
57
    // Initialize MPI
58
    MPI_Comm_size( MPI_COMM_WORLD, &nprocs );
59
    MPI_Comm_rank( MPI_COMM_WORLD, &rank );
60
#endif
61
    if( rank == 0 ) {
42✔
62
        unsigned dim             = mesh->GetDim();
42✔
63
        unsigned numCells        = mesh->GetNumCells();
42✔
64
        unsigned numNodes        = mesh->GetNumNodes();
42✔
65
        auto nodes               = mesh->GetNodes();
84✔
66
        auto cells               = mesh->GetCells();
84✔
67
        unsigned numNodesPerCell = mesh->GetNumNodesPerCell();
42✔
68

69
        auto writer                 = vtkUnstructuredGridWriterSP::New();
84✔
70
        std::string fileNameWithExt = fileName;
84✔
71
        if( !TextProcessingToolbox::StringEndsWith( fileNameWithExt, ".vtk" ) ) {
42✔
72
            fileNameWithExt.append( ".vtk" );
42✔
73
        }
74
        writer->SetFileName( fileNameWithExt.c_str() );
42✔
75
        auto grid = vtkUnstructuredGridSP::New();
84✔
76
        auto pts  = vtkPointsSP::New();
84✔
77
        pts->SetDataTypeToDouble();
42✔
78
        pts->SetNumberOfPoints( static_cast<int>( numNodes ) );
42✔
79
        unsigned nodeID = 0;
42✔
80
        for( const auto& node : nodes ) {
15,852✔
81
            if( dim == 2 ) {
15,810✔
82
                pts->SetPoint( nodeID++, node[0], node[1], 0.0 );
15,810✔
83
            }
84
            else if( dim == 3 ) {
×
85
                pts->SetPoint( nodeID++, node[0], node[1], node[2] );
×
86
            }
87
            else {
88
                ErrorMessages::Error( "Unsupported dimension (d=" + std::to_string( dim ) + ")!", CURRENT_FUNCTION );
×
89
            }
90
        }
91
        vtkCellArraySP cellArray = vtkCellArraySP::New();
84✔
92
        if( numNodesPerCell == 3 ) {
42✔
93
            auto tri = vtkTriangleSP::New();
68✔
94
            for( unsigned i = 0; i < numCells; ++i ) {
14,818✔
95
                for( unsigned j = 0; j < numNodesPerCell; ++j ) {
59,136✔
96
                    tri->GetPointIds()->SetId( j, cells[i][j] );
44,352✔
97
                }
98
                cellArray->InsertNextCell( tri );
14,784✔
99
            }
100
        }
101

102
        if( numNodesPerCell == 4 ) {
42✔
103
            auto quad = vtkQuad::New();
8✔
104
            for( unsigned i = 0; i < numCells; ++i ) {
7,208✔
105
                for( unsigned j = 0; j < numNodesPerCell; ++j ) {
36,000✔
106
                    quad->GetPointIds()->SetId( j, cells[i][j] );
28,800✔
107
                }
108
                cellArray->InsertNextCell( quad );
7,200✔
109
            }
110
        }
111
        if( numNodesPerCell == 3 ) {
42✔
112
            grid->SetCells( VTK_TRIANGLE, cellArray );
34✔
113
        }
114
        else if( numNodesPerCell == 4 ) {
8✔
115
            grid->SetCells( VTK_QUAD, cellArray );
8✔
116
        }
117

118
        // Write the output
119
        auto cellData = vtkDoubleArraySP::New();
84✔
120

121
        for( unsigned idx_group = 0; idx_group < outputFields.size(); idx_group++ ) {
92✔
122

123
            for( unsigned idx_field = 0; idx_field < outputFields[idx_group].size(); idx_field++ ) {    // Loop over all output fields
108✔
124
                cellData = vtkDoubleArraySP::New();
58✔
125
                cellData->SetName( outputFieldNames[idx_group][idx_field].c_str() );
58✔
126

127
                for( unsigned idx_cell = 0; idx_cell < numCells; idx_cell++ ) {
36,442✔
128
                    cellData->InsertNextValue( outputFields[idx_group][idx_field][idx_cell] );
36,384✔
129
                }
130

131
                grid->GetCellData()->AddArray( cellData );
58✔
132
            }
133
        }
134

135
        grid->SetPoints( pts );
42✔
136
        grid->Squeeze();
42✔
137

138
        auto converter = vtkCellDataToPointDataSP::New();
84✔
139
        converter->AddInputDataObject( grid );
42✔
140
        converter->PassCellDataOn();
42✔
141
        converter->Update();
42✔
142

143
        writer->SetInputData( converter->GetOutput() );
42✔
144

145
        writer->Write();
42✔
146

147
        //  auto log = spdlog::get( "event" );
148
        //  log->info( "Result successfully exported to '{0}'!", fileNameWithExt );
149
    }
150
}
42✔
151

152
Mesh* LoadSU2MeshFromFile( const Config* settings ) {
34✔
153
    auto log = spdlog::get( "event" );
102✔
154
    // log->info( "| Importing mesh. This may take a while for large meshes." );
155
    unsigned dim;
156
    std::vector<Vector> nodes;
68✔
157
    std::vector<std::vector<unsigned>> cells;
68✔
158
    std::vector<std::pair<BOUNDARY_TYPE, std::vector<unsigned>>> boundaries;
68✔
159

160
    if( !std::filesystem::exists( settings->GetMeshFile() ) )
34✔
161
        ErrorMessages::Error( "Cannot find mesh file '" + settings->GetMeshFile() + "!", CURRENT_FUNCTION );
×
162
    std::ifstream ifs( settings->GetMeshFile(), std::ios::in );
68✔
163
    std::string line;
34✔
164

165
    if( ifs.is_open() ) {
34✔
166
        while( getline( ifs, line ) ) {
34✔
167
            if( line.find( "NDIME", 0 ) != std::string::npos ) {
34✔
168
                dim = static_cast<unsigned>( TextProcessingToolbox::GetTrailingNumber( line ) );
34✔
169
                // if( settings->GetDim() != dim ) {
170
                //     log->info( "Warning: Mesh dimension does not coinside with problem dimension! Proceed with caution!" );
171
                // }
172
                break;
34✔
173
            }
174
        }
175
        ifs.clear();
34✔
176
        ifs.seekg( 0, std::ios::beg );
34✔
177
        while( getline( ifs, line ) ) {
11,358✔
178
            if( line.find( "NPOIN", 0 ) != std::string::npos ) {
11,358✔
179
                unsigned numPoints = static_cast<unsigned>( TextProcessingToolbox::GetTrailingNumber( line ) );
34✔
180
                nodes.resize( numPoints, Vector( dim, 0.0 ) );
34✔
181
                for( unsigned i = 0; i < numPoints; ++i ) {
8,144✔
182
                    getline( ifs, line );
8,110✔
183
                    std::stringstream ss;
16,220✔
184
                    ss << line;
8,110✔
185
                    unsigned id = 0;
8,110✔
186
                    Vector coords( dim, 0.0 );
8,110✔
187
                    while( !ss.eof() ) {
16,220✔
188
                        for( unsigned d = 0; d < dim; ++d ) {
24,330✔
189
                            ss >> coords[d];
16,220✔
190
                        }
191
                        ss >> id;
8,110✔
192
                    }
193

194
                    nodes[id] = Vector( coords );
8,110✔
195
                }
196
                break;
34✔
197
            }
198
        }
199
        ifs.clear();
34✔
200
        ifs.seekg( 0, std::ios::beg );
34✔
201
        while( getline( ifs, line ) ) {
19,502✔
202
            if( line.find( "NMARK", 0 ) != std::string::npos ) {
19,502✔
203
                unsigned numBCs = static_cast<unsigned>( TextProcessingToolbox::GetTrailingNumber( line ) );
34✔
204
                boundaries.resize( numBCs );
34✔
205
                for( unsigned i = 0; i < numBCs; ++i ) {
68✔
206
                    std::string markerTag;
68✔
207
                    BOUNDARY_TYPE btype;
208
                    std::vector<unsigned> bnodes;
34✔
209
                    for( unsigned k = 0; k < 2; ++k ) {
102✔
210
                        getline( ifs, line );
68✔
211
                        if( line.find( "MARKER_TAG", 0 ) != std::string::npos ) {
68✔
212
                            markerTag    = line.substr( line.find( "=" ) + 1 );
34✔
213
                            auto end_pos = std::remove_if(
214
                                markerTag.begin(), markerTag.end(), []( char c ) { return std::isspace( static_cast<unsigned char>( c ) ); } );
204✔
215
                            markerTag.erase( end_pos, markerTag.end() );
34✔
216
                            btype = settings->GetBoundaryType( markerTag );
34✔
217
                            if( btype == BOUNDARY_TYPE::INVALID ) {
34✔
218
                                std::string errorMsg = std::string( "Invalid Boundary at marker \"" + markerTag + "\"." );
×
219
                                ErrorMessages::Error( errorMsg, CURRENT_FUNCTION );
×
220
                            }
221
                        }
222
                        else if( line.find( "MARKER_ELEMS", 0 ) != std::string::npos ) {
34✔
223
                            unsigned numMarkerElements = static_cast<unsigned>( TextProcessingToolbox::GetTrailingNumber( line ) );
34✔
224
                            for( unsigned j = 0; j < numMarkerElements; ++j ) {
1,330✔
225
                                getline( ifs, line );
1,296✔
226
                                std::stringstream ss;
2,592✔
227
                                ss << line;
1,296✔
228
                                unsigned type = 0, id = 0;
1,296✔
229
                                while( !ss.eof() ) {
3,888✔
230
                                    ss >> type;
2,592✔
231
                                    for( unsigned d = 0; d < dim; ++d ) {
7,776✔
232
                                        ss >> id;
5,184✔
233
                                        bnodes.push_back( id );
5,184✔
234
                                    }
235
                                }
236
                            }
237
                        }
238
                        else {
239
                            ErrorMessages::Error( "Invalid mesh file detected! Make sure boundaries are provided.'", CURRENT_FUNCTION );
×
240
                        }
241
                    }
242
                    std::sort( bnodes.begin(), bnodes.end() );
34✔
243
                    auto last = std::unique( bnodes.begin(), bnodes.end() );
34✔
244
                    bnodes.erase( last, bnodes.end() );
34✔
245
                    boundaries[i] = std::make_pair( btype, bnodes );
34✔
246
                }
247
                break;
34✔
248
            }
249
        }
250
        ifs.clear();
34✔
251
        ifs.seekg( 0, std::ios::beg );
34✔
252
        std::vector<unsigned> numNodesPerCell;
68✔
253
        while( getline( ifs, line ) ) {
68✔
254
            if( line.find( "NELEM", 0 ) != std::string::npos ) {
68✔
255
                unsigned numCells = static_cast<unsigned>( TextProcessingToolbox::GetTrailingNumber( line ) );
34✔
256
                numNodesPerCell.resize( numCells, 0u );
34✔
257
                for( unsigned i = 0; i < numCells; ++i ) {
11,290✔
258
                    getline( ifs, line );
11,256✔
259
                    std::stringstream ss;
22,512✔
260
                    ss << line;
11,256✔
261
                    unsigned type = 0;
11,256✔
262
                    ss >> type;
11,256✔
263
                    switch( type ) {
11,256✔
264
                        case 5: {
7,656✔
265
                            numNodesPerCell[i] = 3;
7,656✔
266
                            break;
7,656✔
267
                        }
268
                        case 9: {
3,600✔
269
                            numNodesPerCell[i] = 4;
3,600✔
270
                            break;
3,600✔
271
                        }
272
                        default: {
×
273
                            ErrorMessages::Error( "Unsupported mesh type!'", CURRENT_FUNCTION );
×
274
                        }
275
                    }
276
                }
277
                break;
34✔
278
            }
279
        }
280
        bool mixedElementMesh = !std::equal( numNodesPerCell.begin() + 1, numNodesPerCell.end(), numNodesPerCell.begin() );
34✔
281
        if( mixedElementMesh ) {
34✔
282
            ErrorMessages::Error( "Mixed element meshes are currently not supported!'", CURRENT_FUNCTION );
×
283
        }
284
        ifs.clear();
34✔
285
        ifs.seekg( 0, std::ios::beg );
34✔
286
        while( getline( ifs, line ) ) {
68✔
287
            if( line.find( "NELEM", 0 ) != std::string::npos ) {
68✔
288
                unsigned numCells = static_cast<unsigned>( TextProcessingToolbox::GetTrailingNumber( line ) );
34✔
289
                cells.resize( numCells, std::vector<unsigned>( numNodesPerCell[0], 0u ) );
34✔
290
                for( unsigned i = 0; i < numCells; ++i ) {
11,290✔
291
                    getline( ifs, line );
11,256✔
292
                    std::stringstream ss;
22,512✔
293
                    ss << line;
11,256✔
294
                    unsigned type = 0, id = 0;
11,256✔
295
                    std::vector<unsigned> buffer( numNodesPerCell[0], 0u );
22,512✔
296
                    while( !ss.eof() ) {
22,512✔
297
                        ss >> type;
11,256✔
298
                        for( unsigned d = 0; d < numNodesPerCell[i]; ++d ) {
48,624✔
299
                            ss >> buffer[d];
37,368✔
300
                        }
301
                        ss >> id;
11,256✔
302
                    }
303
                    std::copy( buffer.begin(), buffer.end(), cells[id].begin() );
11,256✔
304
                }
305
                break;
34✔
306
            }
307
        }
308
    }
309
    else {
310
        ErrorMessages::Error( "Cannot open mesh file '" + settings->GetMeshFile() + "!", CURRENT_FUNCTION );
×
311
    }
312
    ifs.close();
34✔
313
    // log->info( "| Mesh imported." );
314
    return new Mesh( settings, nodes, cells, boundaries );
68✔
315
}
316

317
void LoadConnectivityFromFile( const std::string inputFile,
15✔
318
                               std::vector<std::vector<unsigned>>& cellNeighbors,
319
                               std::vector<std::vector<Vector>>& cellInterfaceMidPoints,
320
                               std::vector<std::vector<Vector>>& cellNormals,
321
                               std::vector<BOUNDARY_TYPE>& cellBoundaryTypes,
322
                               unsigned nCells,
323
                               unsigned nNodesPerCell,
324
                               unsigned nDim ) {
325
    // File has nCells lines, each line is a comma separated entry containing:
326
    // cellNeighbors (nNodesPerCell elements),
327
    // cellInterfaceMidPoints (nNodesPerCell x nDim elements),
328
    // cellNormals (nNodesPerCell x nDim elements),
329
    // cellBoundaryTypes (1 element), (tranlated from  unsigned to enum BOUNDARY_TYPE)
330

331
    std::ifstream inFile( inputFile );
15✔
332

333
    if( !inFile.is_open() ) {
15✔
NEW
334
        ErrorMessages::Error( "Error opening connectivity file.", CURRENT_FUNCTION );
×
NEW
335
        return;
×
336
    }
337
    for( unsigned i = 0; i < nCells; ++i ) {
6,173✔
338
        std::string line;
12,316✔
339
        unsigned count = 1;
6,158✔
340

341
        std::getline( inFile, line );
6,158✔
342
        for( char ch : line ) {
1,434,012✔
343
            if( ch == ',' ) {
1,427,854✔
344
                count++;
92,370✔
345
            }
346
        }
347

348
        unsigned correctedNodesPerCell = nNodesPerCell;
6,158✔
349
        if( count < nNodesPerCell + nNodesPerCell * nDim * 2 + 1 ) {
6,158✔
NEW
350
            correctedNodesPerCell = nNodesPerCell - 1;
×
NEW
351
            ErrorMessages::Error( "Error opening connectivity file.", CURRENT_FUNCTION );
×
352
        }
353

354
        std::istringstream iss( line );
12,316✔
355
        // Load cellNeighbors
356
        cellNeighbors[i].resize( correctedNodesPerCell );
6,158✔
357

358
        for( unsigned j = 0; j < correctedNodesPerCell; ++j ) {
24,632✔
359
            std::getline( iss, line, ',' );
18,474✔
360
            std::istringstream converter( line );
36,948✔
361
            converter >> std::fixed >> setprecision( 15 ) >> cellNeighbors[i][j];
18,474✔
362
        }
363

364
        // Load cellInterfaceMidPoints
365
        cellInterfaceMidPoints[i].resize( correctedNodesPerCell );
6,158✔
366
        for( unsigned j = 0; j < correctedNodesPerCell; ++j ) {
24,632✔
367
            cellInterfaceMidPoints[i][j] = Vector( nDim, 0.0 );
18,474✔
368
            for( unsigned k = 0; k < nDim; ++k ) {
55,422✔
369
                std::getline( iss, line, ',' );
36,948✔
370
                std::istringstream converter( line );
73,896✔
371
                converter >> std::fixed >> setprecision( 15 ) >> cellInterfaceMidPoints[i][j][k];    // Replace with appropriate member of Vector
36,948✔
372
                // std::cout << std::fixed << setprecision( 15 ) << cellInterfaceMidPoints[i][j][k] << std::endl;
373
            }
374
        }
375
        // Load cellNormals
376
        cellNormals[i].resize( correctedNodesPerCell );
6,158✔
377
        for( unsigned j = 0; j < correctedNodesPerCell; ++j ) {
24,632✔
378
            cellNormals[i][j] = Vector( nDim, 0.0 );
18,474✔
379
            for( unsigned k = 0; k < nDim; ++k ) {
55,422✔
380
                std::getline( iss, line, ',' );
36,948✔
381
                std::istringstream converter( line );
73,896✔
382
                converter >> std::fixed >> setprecision( 15 ) >> cellNormals[i][j][k];    // Replace with appropriate member of Vector
36,948✔
383
            }
384
        }
385
        // Load cellBoundaryTypes
386
        std::getline( iss, line, ',' );
6,158✔
387
        std::istringstream converter( line );
6,158✔
388
        unsigned boundaryTypeValue;
389
        converter >> boundaryTypeValue;
6,158✔
390
        cellBoundaryTypes[i] = static_cast<BOUNDARY_TYPE>( boundaryTypeValue );
6,158✔
391
    }
392
    inFile.close();
15✔
393
}
394

395
void WriteConnecitivityToFile( const std::string outputFile,
3✔
396
                               const std::vector<std::vector<unsigned>>& cellNeighbors,
397
                               const std::vector<std::vector<Vector>>& cellInterfaceMidPoints,
398
                               const std::vector<std::vector<Vector>>& cellNormals,
399
                               const std::vector<BOUNDARY_TYPE>& cellBoundaryTypes,
400
                               unsigned nCells,
401
                               unsigned nDim ) {
402
    // File has nCells lines, each line is a comma separated entry containing:
403
    // cellNeighbors (nNodesPerCell elements),
404
    // cellInterfaceMidPoints (nNodesPerCell x nDim elements),
405
    // cellNormals (nNodesPerCell x nDim elements),
406
    // cellBoundaryTypes (1 element), (tranlated from BOUNDARY_TYPE to unsigned)
407

408
    std::ofstream outFile( outputFile );
6✔
409
    outFile << std::fixed << setprecision( 15 );
3✔
410
    // const std::size_t bufferSize = 10000;    // Adjust as needed
411
    // outFile.rdbuf()->pubsetbuf( 0, bufferSize );
412
    if( outFile.is_open() ) {
3✔
413
        // Write data to the file
414
        for( unsigned i = 0; i < nCells; ++i ) {
1,169✔
415
            // Write cellNeighbors
416
            for( unsigned j = 0; j < cellNeighbors[i].size(); ++j ) {
4,664✔
417
                outFile << cellNeighbors[i][j];
3,498✔
418
                if( j < cellNeighbors[i].size() - 1 ) {
3,498✔
419
                    outFile << ",";
2,332✔
420
                }
421
            }
422
            // Write cellInterfaceMidPoints
423
            for( unsigned j = 0; j < cellInterfaceMidPoints[i].size(); ++j ) {
4,664✔
424
                for( unsigned k = 0; k < nDim; ++k ) {
10,494✔
425
                    outFile << "," << cellInterfaceMidPoints[i][j][k];
6,996✔
426
                }
427
            }
428
            // Write cellNormals
429
            for( unsigned j = 0; j < cellNormals[i].size(); ++j ) {
4,664✔
430
                for( unsigned k = 0; k < nDim; ++k ) {
10,494✔
431
                    outFile << "," << cellNormals[i][j][k];
6,996✔
432
                }
433
            }
434

435
            // Write cellBoundaryTypes
436
            outFile << "," << static_cast<unsigned>( cellBoundaryTypes[i] );
1,166✔
437
            outFile << std::endl;
1,166✔
438
        }
439
        outFile.close();
3✔
440
    }
441
    else {
NEW
442
        ErrorMessages::Error( "Error opening connectivity file.", CURRENT_FUNCTION );
×
443
    }
444
}
3✔
445

NEW
446
void WriteRestartSolution( const std::string& baseOutputFile,
×
447
                           const std::vector<double>& solution,
448
                           const std::vector<double>& scalarFlux,
449
                           int rank,
450
                           int idx_iter,
451
                           double totalAbsorptionHohlraumCenter,
452
                           double totalAbsorptionHohlraumVertical,
453
                           double totalAbsorptionHohlraumHorizontal,
454
                           double totalAbsorption ) {
455
    // Generate filename with rank number
NEW
456
    std::string outputFile = baseOutputFile + "_restart_rank_" + std::to_string( rank );
×
457

458
    // Check if the file exists and delete it
NEW
459
    if( std::filesystem::exists( outputFile ) ) {
×
NEW
460
        std::filesystem::remove( outputFile );
×
461
    }
462

463
    // Open the file for binary writing
NEW
464
    std::ofstream outFile( outputFile, std::ios::out | std::ios::binary );
×
NEW
465
    if( !outFile ) {
×
NEW
466
        std::cerr << "Error opening restart solution file." << std::endl;
×
NEW
467
        return;
×
468
    }
469

470
    // Write the iteration number as the first item (in binary)
NEW
471
    outFile.write( reinterpret_cast<const char*>( &idx_iter ), sizeof( idx_iter ) );
×
NEW
472
    outFile.write( reinterpret_cast<const char*>( &totalAbsorptionHohlraumCenter ), sizeof( totalAbsorptionHohlraumCenter ) );
×
NEW
473
    outFile.write( reinterpret_cast<const char*>( &totalAbsorptionHohlraumVertical ), sizeof( totalAbsorptionHohlraumVertical ) );
×
NEW
474
    outFile.write( reinterpret_cast<const char*>( &totalAbsorptionHohlraumHorizontal ), sizeof( totalAbsorptionHohlraumHorizontal ) );
×
NEW
475
    outFile.write( reinterpret_cast<const char*>( &totalAbsorption ), sizeof( totalAbsorption ) );
×
476

477
    // Write the size of the solution and scalarFlux vectors (optional but useful for reading)
NEW
478
    size_t solution_size   = solution.size();
×
NEW
479
    size_t scalarFlux_size = scalarFlux.size();
×
NEW
480
    outFile.write( reinterpret_cast<const char*>( &solution_size ), sizeof( solution_size ) );
×
NEW
481
    outFile.write( reinterpret_cast<const char*>( &scalarFlux_size ), sizeof( scalarFlux_size ) );
×
482

483
    // Write each element of the solution vector in binary
NEW
484
    outFile.write( reinterpret_cast<const char*>( solution.data() ), solution_size * sizeof( double ) );
×
485

486
    // Write each element of the scalarFlux vector in binary
NEW
487
    outFile.write( reinterpret_cast<const char*>( scalarFlux.data() ), scalarFlux_size * sizeof( double ) );
×
488

489
    // Close the file
NEW
490
    outFile.close();
×
491
}
492

NEW
493
int LoadRestartSolution( const std::string& baseInputFile,
×
494
                         std::vector<double>& solution,
495
                         std::vector<double>& scalarFlux,
496
                         int rank,
497
                         unsigned long nCells,
498
                         double& totalAbsorptionHohlraumCenter,
499
                         double& totalAbsorptionHohlraumVertical,
500
                         double& totalAbsorptionHohlraumHorizontal,
501
                         double& totalAbsorption ) {
502
    // Generate filename with rank number
NEW
503
    std::string inputFile = baseInputFile + "_restart_rank_" + std::to_string( rank );
×
504

505
    // Open the file for binary reading
NEW
506
    std::ifstream inFile( inputFile, std::ios::in | std::ios::binary );
×
NEW
507
    if( !inFile ) {
×
NEW
508
        std::cerr << "Error opening restart solution file for reading." << std::endl;
×
NEW
509
        return 0;    // Signal failure
×
510
    }
511

512
    // Read the iteration number
NEW
513
    int idx_iter = 0;
×
NEW
514
    inFile.read( reinterpret_cast<char*>( &idx_iter ), sizeof( idx_iter ) );
×
NEW
515
    inFile.read( reinterpret_cast<char*>( &totalAbsorptionHohlraumCenter ), sizeof( totalAbsorptionHohlraumCenter ) );
×
NEW
516
    inFile.read( reinterpret_cast<char*>( &totalAbsorptionHohlraumVertical ), sizeof( totalAbsorptionHohlraumVertical ) );
×
NEW
517
    inFile.read( reinterpret_cast<char*>( &totalAbsorptionHohlraumHorizontal ), sizeof( totalAbsorptionHohlraumHorizontal ) );
×
NEW
518
    inFile.read( reinterpret_cast<char*>( &totalAbsorption ), sizeof( totalAbsorption ) );
×
519

520
    // Read the size of the solution and scalarFlux vectors
521
    size_t solution_size, scalarFlux_size;
NEW
522
    inFile.read( reinterpret_cast<char*>( &solution_size ), sizeof( solution_size ) );
×
NEW
523
    inFile.read( reinterpret_cast<char*>( &scalarFlux_size ), sizeof( scalarFlux_size ) );
×
524

525
    // Temporary vector to hold the full data
NEW
526
    std::vector<double> tempData( solution_size + scalarFlux_size );
×
527

528
    // Read the entire data block in binary form
NEW
529
    inFile.read( reinterpret_cast<char*>( tempData.data() ), ( solution_size + scalarFlux_size ) * sizeof( double ) );
×
530

531
    // Close the file
NEW
532
    inFile.close();
×
533

534
    // Verify that we have enough entries to populate scalarFlux
NEW
535
    if( tempData.size() < nCells ) {
×
NEW
536
        std::cerr << "Not enough data to populate scalar flux vector." << std::endl;
×
NEW
537
        return 0;    // Signal failure
×
538
    }
539

540
    // Allocate the last nCells entries to scalarFlux and the rest to solution
NEW
541
    solution.assign( tempData.begin(), tempData.end() - nCells );
×
NEW
542
    scalarFlux.assign( tempData.end() - nCells, tempData.end() );
×
543

NEW
544
    return idx_iter;    // Return the iteration index
×
545
}
546

547
std::string ParseArguments( int argc, char* argv[] ) {
×
548
    std::string inputFile;
×
NEW
549
    std::string usage_help = "\nUsage: " + std::string( argv[0] ) + " inputfile\n";
×
550

551
    if( argc < 2 ) {
×
552
        std::cout << usage_help;
×
553
        exit( EXIT_FAILURE );
×
554
    }
555
    for( int i = 1; i < argc; i++ ) {
×
556
        std::string arg = argv[i];
×
557
        if( arg == "-h" ) {
×
558
            std::cout << usage_help;
×
559
            exit( EXIT_SUCCESS );
×
560
        }
561
        else {
562
            inputFile = std::string( argv[i] );
×
563
            std::ifstream f( inputFile );
×
564
            if( !f.is_open() ) {
×
565
                ErrorMessages::Error( "Unable to open inputfile '" + inputFile + "' !", CURRENT_FUNCTION );
×
566
            }
567
        }
568
    }
569
    return inputFile;
×
570
}
571

572
void PrintLogHeader( std::string inputFile ) {
×
NEW
573
    int nprocs = 1;
×
NEW
574
    int rank   = 0;
×
575
#ifdef IMPORT_MPI
576
    // Initialize MPI
577
    MPI_Comm_size( MPI_COMM_WORLD, &nprocs );
578
    MPI_Comm_rank( MPI_COMM_WORLD, &rank );
579
#endif
580
    if( rank == 0 ) {
×
581
        auto log = spdlog::get( "event" );
×
582

583
        // New design
584
        log->info( "------------------------------------------------------------------------" );
×
585
        log->info( "|    _  _____ _____     ____ _____                                     |" );
×
586
        log->info( "|   | |/ /_ _|_   _|   |  _ \\_   _|                                    |" );
×
587
        log->info( "|   | ' / | |  | |_____| |_) || |            Version                   |" );
×
588
        log->info( "|   | . \\ | |  | |_____|  _ < | |             1.0.0                    |" );
×
589
        log->info( "|   |_|\\_\\___| |_|     |_| \\_\\|_|                                      |" );
×
590
        log->info( "|                                                                      |" );
×
591
        log->info( "------------------------------------------------------------------------" );
×
592
        log->info( "|  Copyright: MIT Licence                                              |" );
×
593
        // log->info( "|  Authors: S. Schotthöfer, J. Kusch, J. Wolters, P. Stammer ad T. Xiao |" );
594
        log->info( "|  Date: 21th April 2022                                               |" );
×
595
        log->info( "------------------------------------------------------------------------" );
×
596
        log->info( "|" );
×
597
        log->info( "| Git commit :\t{0}", GIT_HASH );
×
598
        log->info( "| Config file:\t{0}", inputFile );
×
599
        log->info( "| MPI Threads:\t{0}", nprocs );
×
600
        log->info( "| OMP Threads:\t{0}", omp_get_max_threads() );
×
601
        log->info( "|" );
×
602
        log->info( "-------------------------- Config File Info ----------------------------" );
×
603
        log->info( "|" );
×
604
        // print file content while omitting comments
605
        std::ifstream ifs( inputFile );
×
606
        if( ifs.is_open() ) {
×
607
            std::string line;
×
608
            while( !ifs.eof() ) {
×
609
                std::getline( ifs, line );
×
610
                if( line[0] != '%' ) log->info( "| {0}", line );
×
611
            }
612
        }
613
        // log->info( "------------------------------------------------------------------------" );
614
    }
615
#ifdef IMPORT_MPI
616
    MPI_Barrier( MPI_COMM_WORLD );
617
#endif
618
}
619

620
/*
621
Matrix createSU2MeshFromImage( std::string imageName, std::string SU2Filename ) {
622
    auto log = spdlog::get( "event" );
623

624
    // std::cout << "imageName" << imageName << "\n";
625
    // std::cout << "pyhtonPath" << KITRT_PYTHON_PATH;
626

627
    if( !std::filesystem::exists( imageName ) ) {
628
        ErrorMessages::Error( "Can not open image '" + imageName + "'!", CURRENT_FUNCTION );
629
    }
630
    std::filesystem::path outDir( std::filesystem::path( SU2Filename ).parent_path() );
631
    if( !std::filesystem::exists( outDir ) ) {
632
        ErrorMessages::Error( "Output directory '" + outDir.string() + "' does not exists!", CURRENT_FUNCTION );
633
    }
634

635
    std::string pyPath = KITRT_PYTHON_PATH;
636

637
    if( !Py_IsInitialized() ) {
638
        Py_InitializeEx( 0 );
639
        if( !Py_IsInitialized() ) {
640
            ErrorMessages::Error( "Python init failed!", CURRENT_FUNCTION );
641
        }
642
        PyRun_SimpleString( ( "import sys\nsys.path.append('" + pyPath + "')" ).c_str() );
643
    }
644

645
    PyObject *pArgs, *pReturn, *pModule, *pFunc;
646
    PyArrayObject* np_ret;
647

648
    auto image = PyUnicode_FromString( imageName.c_str() );
649
    auto su2   = PyUnicode_FromString( SU2Filename.c_str() );
650

651
    std::string moduleName = "mesh_from_image";
652
    pModule                = PyImport_ImportModule( moduleName.c_str() );
653
    if( !pModule ) {
654
        PyErr_Print();
655
        ErrorMessages::Error( "'" + moduleName + "' can not be imported!", CURRENT_FUNCTION );
656
    }
657

658
    pFunc = PyObject_GetAttrString( pModule, "generate" );
659
    if( !pFunc || !PyCallable_Check( pFunc ) ) {
660
        PyErr_Print();
661
        Py_DecRef( pModule );
662
        Py_DecRef( pFunc );
663
        ErrorMessages::Error( "'generate' is null or not callable!", CURRENT_FUNCTION );
664
    }
665

666
    pArgs = PyTuple_New( 2 );
667
    PyTuple_SetItem( pArgs, 0, reinterpret_cast<PyObject*>( image ) );
668
    PyTuple_SetItem( pArgs, 1, reinterpret_cast<PyObject*>( su2 ) );
669
    pReturn = PyObject_CallObject( pFunc, pArgs );
670
    np_ret  = reinterpret_cast<PyArrayObject*>( pReturn );
671

672
    size_t m{ static_cast<size_t>( PyArray_SHAPE( np_ret )[0] ) };
673
    size_t n{ static_cast<size_t>( PyArray_SHAPE( np_ret )[1] ) };
674
    double* c_out = reinterpret_cast<double*>( PyArray_DATA( np_ret ) );
675

676
    Matrix gsImage( m, n, c_out );
677

678
    // Finalizing
679
    Py_DecRef( pFunc );
680
    Py_DecRef( pModule );
681
    Py_DECREF( np_ret );
682

683
    return gsImage.transpose();
684
}
685
*/
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