Branch data Line data Source code
1 : : // *****************************************************************************
2 : : /*!
3 : : \file src/IO/ExodusIIMeshWriter.cpp
4 : : \copyright 2012-2015 J. Bakosi,
5 : : 2016-2018 Los Alamos National Security, LLC.,
6 : : 2019-2021 Triad National Security, LLC.
7 : : All rights reserved. See the LICENSE file for details.
8 : : \brief ExodusII mesh-based data writer
9 : : \details ExodusII mesh-based data writer class definition.
10 : : */
11 : : // *****************************************************************************
12 : :
13 : : #include <numeric>
14 : :
15 : : #include "NoWarning/exodusII.hpp"
16 : :
17 : : #include "ExodusIIMeshWriter.hpp"
18 : : #include "Exception.hpp"
19 : : #include "UnsMesh.hpp"
20 : :
21 : : using tk::ExodusIIMeshWriter;
22 : :
23 : 4757 : ExodusIIMeshWriter::ExodusIIMeshWriter( const std::string& filename,
24 : : ExoWriter mode,
25 : : int cpuwordsize,
26 : 4757 : int iowordsize ) :
27 : 4757 : m_filename( filename ), m_outFile( 0 )
28 : : // *****************************************************************************
29 : : // Constructor: create/open Exodus II file
30 : : //! \param[in] filename File to open as ExodusII file
31 : : //! \param[in] mode ExodusII writer constructor mode: ExoWriter::CREATE for
32 : : //! creating a new file, ExoWriter::OPEN for opening an existing file for
33 : : //! appending
34 : : //! \param[in] cpuwordsize Set CPU word size, see ExodusII documentation
35 : : //! \param[in] iowordsize Set I/O word size, see ExodusII documentation
36 : : // *****************************************************************************
37 : : {
38 : : // Increase verbosity from ExodusII library in debug mode
39 : : #ifndef NDEBUG
40 [ + - ]: 4757 : ex_opts( EX_DEBUG | EX_VERBOSE );
41 : : #endif
42 : :
43 [ + + ]: 4757 : if (mode == ExoWriter::CREATE) {
44 : :
45 [ + - ]: 999 : m_outFile = ex_create( filename.c_str(),
46 : : EX_CLOBBER | EX_LARGE_MODEL,
47 : : &cpuwordsize,
48 : : &iowordsize );
49 : :
50 [ + - ]: 3758 : } else if (mode == ExoWriter::OPEN) {
51 : :
52 : : float version;
53 [ + - ]: 3758 : m_outFile = ex_open( filename.c_str(),
54 : : EX_WRITE,
55 : : &cpuwordsize,
56 : : &iowordsize,
57 : : &version );
58 : :
59 [ - - ][ - - ]: 0 : } else Throw( "Unknown ExodusII writer constructor mode" );
[ - - ]
60 : :
61 [ - + ][ - - ]: 4757 : ErrChk( m_outFile > 0, "Failed to create/open ExodusII file: " + filename );
[ - - ][ - - ]
62 : 4757 : }
63 : :
64 : 4757 : ExodusIIMeshWriter::~ExodusIIMeshWriter() noexcept
65 : : // *****************************************************************************
66 : : // Destructor
67 : : // *****************************************************************************
68 : : {
69 [ - + ]: 4757 : if ( ex_close(m_outFile) < 0 )
70 : 0 : printf( ">>> WARNING: Failed to close ExodusII file: %s\n",
71 : : m_filename.c_str() );
72 : 4757 : }
73 : :
74 : : void
75 : 999 : ExodusIIMeshWriter::writeMesh( const UnsMesh& mesh ) const
76 : : // *****************************************************************************
77 : : // Write ExodusII mesh file taking a tk::UnsMesh object
78 : : //! \param[in] mesh Unstructured mesh object
79 : : // *****************************************************************************
80 : : {
81 : 999 : writeHeader( mesh );
82 : 999 : writeNodes( mesh );
83 : 999 : writeElements( mesh );
84 : 999 : writeSidesets( mesh );
85 : 999 : writeNodesets( mesh );
86 : 999 : writeTimeValues( mesh.vartimes() );
87 : 999 : writeNodeVarNames( mesh.nodevarnames() );
88 : 999 : writeElemVarNames( mesh.elemvarnames() );
89 : 999 : writeNodeScalars( mesh.nodevars() );
90 : 999 : writeElemScalars( mesh.elemvars() );
91 : 999 : }
92 : :
93 : : void
94 : 52 : ExodusIIMeshWriter::writeMesh(
95 : : const std::vector< std::size_t >& tetinp,
96 : : const UnsMesh::Coords& coord,
97 : : const std::map< int, std::vector< std::size_t > >& bface,
98 : : const std::vector< std::size_t >& triinp ) const
99 : : // *****************************************************************************
100 : : // Write ExodusII mesh file taking inputs to a tk::UnsMesh object
101 : : //! \param[in] tetinp Tetrahedron element connectivity
102 : : //! \param[in] coord Node coordinates
103 : : //! \param[in] bface Boundary face ids for each side set
104 : : //! \param[in] triinp Triangle face connectivity (for all faces in bface)
105 : : // *****************************************************************************
106 : : {
107 : : // Fill element-relative face ids (0,1,2,3) for all side sets with 0 (will
108 : : // use triangles as face elements for side sets)
109 : 104 : std::map< int, std::vector< std::size_t > > faceid;
110 [ + + ][ + - ]: 281 : for (const auto& s : bface) faceid[s.first].resize( s.second.size(), 0 );
[ + - ]
111 : :
112 : : // Generate file-internal Exodus (triangle face) element ids for all faces of
113 : : // all side sets. bface_exo:: face ids for each side set, triinpoel: triangle
114 : : // face connectivity for all side sets.
115 : 104 : std::map< int, std::vector< std::size_t > > bface_exo;
116 [ + - ]: 52 : std::vector< std::size_t > triinpoel( triinp.size() );
117 : : // Generate/start exodus-file-face ids from max number of tetrahedra because
118 : : // tet elem blocks will be written out first
119 : 52 : std::size_t exo_faceid = tetinp.size() / 4;
120 [ + + ]: 281 : for (const auto& s : bface) {
121 [ + - ]: 229 : auto& b = bface_exo[ s.first ];
122 [ + - ]: 229 : b.resize( s.second.size() );
123 : 229 : std::size_t j = 0; // side-set-relative face id
124 [ + + ]: 86631 : for (auto f : s.second) { // for all faces on side set s.first
125 : 86402 : b[ j++ ] = exo_faceid; // generate exo-file face id
126 : 86402 : auto k = exo_faceid - tetinp.size()/4;
127 : : // copy over triangle connectivity in order
128 : 86402 : triinpoel[ k*3+0 ] = triinp[ f*3+0 ];
129 : 86402 : triinpoel[ k*3+1 ] = triinp[ f*3+1 ];
130 : 86402 : triinpoel[ k*3+2 ] = triinp[ f*3+2 ];
131 : 86402 : ++exo_faceid;
132 : : }
133 : : }
134 : :
135 : : // Write mesh
136 [ + - ][ + - ]: 52 : writeMesh( tk::UnsMesh( tetinp, coord, bface_exo, triinpoel, faceid ) );
137 : 52 : }
138 : :
139 : : void
140 : 42 : ExodusIIMeshWriter::writeMesh(
141 : : const std::vector< std::size_t >& tetinp,
142 : : const UnsMesh::Coords& coord,
143 : : const std::map< int, std::vector< std::size_t > >& bnode ) const
144 : : // *****************************************************************************
145 : : // Write ExodusII mesh file taking inputs to a tk::UnsMesh object
146 : : //! \param[in] tetinp Tetrahedron element connectivity
147 : : //! \param[in] coord Node coordinates
148 : : //! \param[in] bnode Boundary node ids for each side set
149 : : // *****************************************************************************
150 : : {
151 [ + - ]: 42 : writeMesh( tk::UnsMesh( tetinp, coord, bnode ) );
152 : 42 : }
153 : :
154 : : void
155 : 999 : ExodusIIMeshWriter::writeHeader( const UnsMesh& mesh ) const
156 : : // *****************************************************************************
157 : : // Write ExodusII header
158 : : //! \param[in] mesh Unstructured mesh object
159 : : // *****************************************************************************
160 : : {
161 [ - + ][ - - ]: 999 : ErrChk(
[ - - ][ - - ]
162 : : ex_put_init( m_outFile,
163 : : "Written by Quinoa",
164 : : 3, // number of dimensions
165 : : static_cast< int64_t >( mesh.nnode() ),
166 : : static_cast< int64_t >( mesh.triinpoel().size()/3 +
167 : : mesh.tetinpoel().size()/4 ),
168 : : static_cast< int64_t >( mesh.neblk() ),
169 : : static_cast< int64_t >( mesh.bnode().size() ),
170 : : static_cast< int64_t >( mesh.bface().size() )
171 : : ) == 0,
172 : : "Failed to write header to file: " + m_filename );
173 : 999 : }
174 : :
175 : : void
176 : 0 : ExodusIIMeshWriter::writeHeader( const char* title,
177 : : int64_t ndim,
178 : : int64_t nnodes,
179 : : int64_t nelem,
180 : : int64_t nblk,
181 : : int64_t node_set,
182 : : int64_t side_set ) const
183 : : // *****************************************************************************
184 : : // Write ExodusII header
185 : : //! \param[in] title ExodusII file header 'title'
186 : : //! \param[in] ndim Number of spatial dimensions in ExodusII file
187 : : //! \param[in] nnodes Number of mesh nodes in ExodusII file
188 : : //! \param[in] nelem Number of mesh elements in ExodusII file
189 : : //! \param[in] nblk Number of mesh element blocks in ExodusII file
190 : : //! \param[in] node_set Number of node sets in ExodusII file
191 : : //! \param[in] side_set Number of side sets in ExodusII file
192 : : // *****************************************************************************
193 : : {
194 [ - - ][ - - ]: 0 : ErrChk(
[ - - ][ - - ]
195 : : ex_put_init( m_outFile, title, ndim, nnodes, nelem, nblk,
196 : : node_set, side_set) == 0,
197 : : "Failed to write header to file: " + m_filename );
198 : 0 : }
199 : :
200 : : void
201 : 999 : ExodusIIMeshWriter::writeNodes( const UnsMesh& mesh ) const
202 : : // *****************************************************************************
203 : : // Write node coordinates to ExodusII file
204 : : //! \param[in] mesh Unstructured mesh object
205 : : // *****************************************************************************
206 : : {
207 [ - + ][ - - ]: 999 : ErrChk( ex_put_coord( m_outFile, mesh.x().data(), mesh.y().data(),
[ - - ][ - - ]
208 : : mesh.z().data() ) == 0,
209 : : "Failed to write coordinates to ExodusII file: " + m_filename );
210 : 999 : }
211 : :
212 : : void
213 : 0 : ExodusIIMeshWriter::writeNodes( const std::vector< tk::real >& x,
214 : : const std::vector< tk::real >& y,
215 : : const std::vector< tk::real >& z ) const
216 : : // *****************************************************************************
217 : : // Write node coordinates to ExodusII file without Mesh
218 : : //! \param[in] x coordinates of mesh nodes
219 : : //! \param[in] y coordinates of mesh nodes
220 : : //! \param[in] z coordinates of mesh nodes
221 : : // *****************************************************************************
222 : : {
223 [ - - ][ - - ]: 0 : ErrChk( ex_put_coord( m_outFile, x.data(), y.data(), z.data() ) == 0,
[ - - ][ - - ]
224 : : "Failed to write coordinates to ExodusII file: " + m_filename );
225 : 0 : }
226 : :
227 : : void
228 : 999 : ExodusIIMeshWriter::writeElements( const UnsMesh& mesh ) const
229 : : // *****************************************************************************
230 : : // Write element connectivity to ExodusII file
231 : : //! \param[in] mesh Unstructured mesh object
232 : : // *****************************************************************************
233 : : {
234 : 999 : int elclass = 0;
235 : :
236 : : // For meshes that have no triangle element block (only tetrahedra), keeping
237 : : // the order as tets first followed by triangles allows keeping the tet ids
238 : : // associated to side sets the same when adding the missing triangle elements
239 : : // by meshconv. Hence this order should be kept as tets first triangles next.
240 : :
241 [ + - ][ + - ]: 999 : writeElemBlock( elclass, 4, "TETRAHEDRA", mesh.tetinpoel() );
242 [ + - ][ + - ]: 999 : writeElemBlock( elclass, 3, "TRIANGLES", mesh.triinpoel() );
243 : 999 : }
244 : :
245 : : void
246 : 1998 : ExodusIIMeshWriter::writeElemBlock( int& elclass,
247 : : int64_t nnpe,
248 : : const std::string& eltype,
249 : : const std::vector< std::size_t >& inpoel )
250 : : const
251 : : // *****************************************************************************
252 : : // Write element block to ExodusII file
253 : : //! \param[inout] elclass Count element class ids in file
254 : : //! \param[in] nnpe Number of nodes per element for block
255 : : //! \param[in] eltype String describing element type
256 : : //! \param[in] inpoel Element connectivity
257 : : // *****************************************************************************
258 : : {
259 [ + + ]: 1998 : if (inpoel.empty()) return;
260 : :
261 : : // increase number of element classes in file
262 : 1060 : ++elclass;
263 : :
264 : : // Compute number of edges and number of faces for triangles and tetrahedra
265 : 1060 : int nedge = 0, nface = 0;
266 [ + + ]: 1060 : if (nnpe == 4) {
267 : 986 : nedge = 6;
268 : 986 : nface = 4;
269 [ + - ]: 74 : } else if (nnpe == 3) {
270 : 74 : nedge = 3;
271 : 74 : nface = 1;
272 [ - - ][ - - ]: 0 : } else Throw( "Write ExodusII element block does not support elements with "
[ - - ][ - - ]
[ - - ]
273 : : + std::to_string(nnpe) + " nodes" );
274 : :
275 : : // Write element block information
276 [ + - ][ - + ]: 1060 : ErrChk(
[ - - ][ - - ]
[ - - ][ - - ]
[ - - ]
277 : : ex_put_block( m_outFile, // exo file handle
278 : : EX_ELEM_BLOCK, // block type: elem block
279 : : elclass, // element class id
280 : : eltype.c_str(), // element block description
281 : : static_cast< int64_t >( inpoel.size() ) / nnpe, // nof cells
282 : : nnpe, // number of nodes per element
283 : : nedge,// number of edges per element
284 : : nface,// number of faces per element
285 : : 0 // number of attributes per element
286 : : ) == 0,
287 : : "Failed to write " + eltype + " element block to ExodusII file: " +
288 : : m_filename );
289 : :
290 : : // Write element connectivity with 1-based node ids
291 [ + - ]: 2120 : std::vector< int > inp( inpoel.size() );
292 : 1060 : std::size_t i = 0;
293 [ + + ]: 5810062 : for (auto p : inpoel) inp[ i++ ] = static_cast< int >( p+1 );
294 [ + - ][ - + ]: 1060 : ErrChk( ex_put_conn( m_outFile, EX_ELEM_BLOCK, elclass, inp.data(),
[ - - ][ - - ]
[ - - ][ - - ]
[ - - ]
295 : : nullptr, nullptr ) == 0,
296 : : "Failed to write " + eltype + " element connectivity to ExodusII "
297 : : "file: " + m_filename );
298 : : }
299 : :
300 : : void
301 : 999 : ExodusIIMeshWriter::writeSidesets( const UnsMesh& mesh ) const
302 : : // *****************************************************************************
303 : : // Write side sets and their face connectivity to ExodusII file
304 : : //! \param[in] mesh Unstructured mesh object
305 : : // *****************************************************************************
306 : : {
307 : : // Write all side sets face list and connectivity in mesh
308 [ + + ]: 1233 : for (const auto& s : mesh.bface()) {
309 : : // Write side set parameters
310 [ + - ][ - + ]: 234 : ErrChk( ex_put_set_param( m_outFile, EX_SIDE_SET, s.first,
[ - - ][ - - ]
[ - - ]
311 : : static_cast<int64_t>(s.second.size()), 0 ) == 0,
312 : : "Failed to write side set parameters to ExodusII file: " + m_filename );
313 : :
314 : : // ExodusII wants 32-bit integers as IDs of element ids
315 [ + - ]: 468 : std::vector< int > bface( s.second.size() );
316 : 234 : std::size_t i = 0;
317 [ + + ]: 93918 : for (auto f : s.second) bface[ i++ ] = static_cast<int>(f)+1;
318 : : // ExodusII wants 32-bit integers as element-relative face IDs
319 [ + - ]: 234 : const auto& fi = tk::cref_find( mesh.faceid(), s.first );
320 [ + - ]: 468 : std::vector< int > faceid( fi.size() );
321 : 234 : i = 0;
322 [ + + ]: 93918 : for (auto f : fi) faceid[ i++ ] = static_cast<int>(f)+1;
323 : :
324 : : // Write side set data: ExodusII-file internal element ids adjacent to side
325 : : // set and face id relative to element indicating which face is aligned with
326 : : // the side set.
327 [ + - ][ - + ]: 234 : ErrChk( ex_put_set( m_outFile, EX_SIDE_SET, s.first, bface.data(),
[ - - ][ - - ]
[ - - ]
328 : : faceid.data() ) == 0,
329 : : "Failed to write side set face list to ExodusII file: " + m_filename );
330 : : }
331 : 999 : }
332 : :
333 : : void
334 : 999 : ExodusIIMeshWriter::writeNodesets( const UnsMesh& mesh ) const
335 : : // *****************************************************************************
336 : : // Write side sets and their node list to ExodusII file
337 : : //! \param[in] mesh Unstructured mesh object
338 : : // *****************************************************************************
339 : : {
340 : : // Write all side set node lists in mesh
341 [ + + ]: 1091 : for (const auto& s : mesh.bnode()) {
342 : : // Write side set parameters
343 [ + - ][ - + ]: 92 : ErrChk( ex_put_set_param( m_outFile, EX_NODE_SET, s.first,
[ - - ][ - - ]
[ - - ]
344 : : static_cast<int64_t>(s.second.size()), 0 ) == 0,
345 : : "Failed to write side set parameters to ExodusII file: " + m_filename );
346 : :
347 : : // ExodusII wants 32-bit integers as IDs of node ids
348 [ + - ]: 184 : std::vector< int > bnode( s.second.size() );
349 : 92 : std::size_t i = 0;
350 [ + + ]: 18225 : for (auto n : s.second) bnode[ i++ ] = static_cast<int>(n)+1;
351 : :
352 : : // Write side set data
353 [ + - ][ - + ]: 92 : ErrChk( ex_put_set( m_outFile, EX_NODE_SET, s.first, bnode.data(),
[ - - ][ - - ]
[ - - ]
354 : : nullptr ) == 0,
355 : : "Failed to write side set node list to ExodusII file: " + m_filename );
356 : : }
357 : 999 : }
358 : :
359 : : void
360 : 3758 : ExodusIIMeshWriter::writeTimeStamp( uint64_t it, tk::real time ) const
361 : : // *****************************************************************************
362 : : // Write time stamp to ExodusII file
363 : : //! \param[in] it Iteration number
364 : : //! \param[in] time Time
365 : : // *****************************************************************************
366 : : {
367 [ - + ][ - - ]: 3758 : ErrChk( ex_put_time( m_outFile, static_cast<int>(it), &time ) == 0,
[ - - ][ - - ]
368 : : "Failed to write time stamp to ExodusII file: " + m_filename );
369 : 3758 : }
370 : :
371 : : void
372 : 999 : ExodusIIMeshWriter::writeTimeValues( const std::vector< tk::real >& tv ) const
373 : : // *****************************************************************************
374 : : // Write time values to ExodusII file
375 : : //! \param[in] tv Time values for all time steps
376 : : // *****************************************************************************
377 : : {
378 : 999 : int i = 0;
379 [ + + ]: 1002 : for (const auto& v : tv) {
380 [ + - ][ - + ]: 3 : ErrChk( ex_put_time( m_outFile, ++i, &v ) == 0,
[ - - ][ - - ]
[ - - ]
381 : : "Failed to write time value for a time step to ExodusII file: " +
382 : : m_filename );
383 : : }
384 : 999 : }
385 : :
386 : : void
387 : 1987 : ExodusIIMeshWriter::writeNodeVarNames( const std::vector< std::string >& nv )
388 : : const
389 : : // *****************************************************************************
390 : : // Write the names of nodal output variables to ExodusII file
391 : : //! \param[in] nv Nodal variable names
392 : : // *****************************************************************************
393 : : {
394 [ + + ]: 1987 : if (!nv.empty()) {
395 : :
396 : : #if defined(__clang__)
397 : : #pragma clang diagnostic push
398 : : #pragma clang diagnostic ignored "-Wvla"
399 : : #pragma clang diagnostic ignored "-Wvla-extension"
400 : : #elif defined(STRICT_GNUC)
401 : : #pragma GCC diagnostic push
402 : : #pragma GCC diagnostic ignored "-Wvla"
403 : : #endif
404 : :
405 [ + - ][ - + ]: 388 : ErrChk(
[ - - ][ - - ]
[ - - ]
406 : : ex_put_variable_param( m_outFile, EX_NODE_BLOCK,
407 : : static_cast< int >( nv.size() ) ) == 0,
408 : : "Failed to write nodal output variable parameters to ExodusII file: " +
409 : : m_filename );
410 : :
411 : 388 : char* names[ nv.size() ];
412 : 388 : std::size_t i = 0;
413 [ + + ]: 2817 : for (const auto& n : nv) names[ i++ ] = const_cast< char* >( n.c_str() );
414 : :
415 [ + - ][ - + ]: 388 : ErrChk( ex_put_variable_names( m_outFile,
[ - - ][ - - ]
[ - - ]
416 : : EX_NODE_BLOCK,
417 : : static_cast< int >( nv.size() ),
418 : : names ) == 0,
419 : : "Failed to write nodal output variable names to ExodusII file: " +
420 : : m_filename );
421 : :
422 : : #if defined(__clang__)
423 : : #pragma clang diagnostic pop
424 : : #elif defined(STRICT_GNUC)
425 : 388 : #pragma GCC diagnostic pop
426 : : #endif
427 : : }
428 : 1987 : }
429 : :
430 : : void
431 : 1987 : ExodusIIMeshWriter::writeElemVarNames( const std::vector< std::string >& ev )
432 : : const
433 : : // *****************************************************************************
434 : : // Write the names of element output variables to ExodusII file
435 : : //! \param[in] ev Elem variable names
436 : : // *****************************************************************************
437 : : {
438 [ + + ]: 1987 : if (!ev.empty()) {
439 : :
440 : : #if defined(__clang__)
441 : : #pragma clang diagnostic push
442 : : #pragma clang diagnostic ignored "-Wvla"
443 : : #pragma clang diagnostic ignored "-Wvla-extension"
444 : : #elif defined(STRICT_GNUC)
445 : : #pragma GCC diagnostic push
446 : : #pragma GCC diagnostic ignored "-Wvla"
447 : : #endif
448 : :
449 [ + - ][ - + ]: 676 : ErrChk(
[ - - ][ - - ]
[ - - ]
450 : : ex_put_variable_param( m_outFile, EX_ELEM_BLOCK,
451 : : static_cast< int >( ev.size() ) ) == 0,
452 : : "Failed to write element output variable parameters to ExodusII file: " +
453 : : m_filename );
454 : :
455 : 676 : char* names[ ev.size() ];
456 : 676 : std::size_t i = 0;
457 [ + + ]: 4860 : for (const auto& n : ev) names[ i++ ] = const_cast< char* >( n.c_str() );
458 : :
459 [ + - ][ - + ]: 676 : ErrChk( ex_put_variable_names( m_outFile,
[ - - ][ - - ]
[ - - ]
460 : : EX_ELEM_BLOCK,
461 : : static_cast< int >( ev.size() ),
462 : : names ) == 0,
463 : : "Failed to write element output variable names to ExodusII file: " +
464 : : m_filename );
465 : :
466 : : #if defined(__clang__)
467 : : #pragma clang diagnostic pop
468 : : #elif defined(STRICT_GNUC)
469 : 676 : #pragma GCC diagnostic pop
470 : : #endif
471 : : }
472 : 1987 : }
473 : :
474 : : void
475 : 999 : ExodusIIMeshWriter::writeNodeScalars(
476 : : const std::vector< std::vector< std::vector< tk::real > > >& var ) const
477 : : // *****************************************************************************
478 : : // Write multiple node scalar fields to ExodusII file at multiple time steps
479 : : //! \param[in] var Vector of nodal variables to read to: inner vector: nodes,
480 : : //! middle vector: (physics) variable, outer vector: time step
481 : : // *****************************************************************************
482 : : {
483 : 999 : uint64_t time = 0;
484 : 999 : int varid = 0;
485 : :
486 [ + + ]: 1002 : for (const auto& t : var) { // for all times
487 : 3 : ++time;
488 [ + + ]: 21 : for (const auto& v : t) { // for all variables
489 [ + - ]: 18 : writeNodeScalar( time, ++varid, v );
490 : : }
491 : 3 : varid = 0;
492 : : }
493 : 999 : }
494 : :
495 : : void
496 : 11511 : ExodusIIMeshWriter::writeNodeScalar( uint64_t it,
497 : : int varid,
498 : : const std::vector< tk::real >& var ) const
499 : : // *****************************************************************************
500 : : // Write node scalar field to ExodusII file
501 : : //! \param[in] it Iteration number
502 : : //! \param[in] varid Variable id
503 : : //! \param[in] var Vector of variable to output
504 : : // *****************************************************************************
505 : : {
506 [ + - ]: 11511 : if (!var.empty()) {
507 [ - + ][ - - ]: 11511 : ErrChk( ex_put_var( m_outFile,
[ - - ][ - - ]
508 : : static_cast< int >( it ),
509 : : EX_NODE_BLOCK,
510 : : varid,
511 : : 1,
512 : : static_cast< int64_t >( var.size() ),
513 : : var.data() ) == 0,
514 : : "Failed to write node scalar to ExodusII file: " + m_filename );
515 : : }
516 : 11511 : }
517 : :
518 : : void
519 : 999 : ExodusIIMeshWriter::writeElemScalars(
520 : : const std::vector< std::vector< std::vector< tk::real > > >& var ) const
521 : : // *****************************************************************************
522 : : // Write multiple element scalar fields to ExodusII file at multiple time steps
523 : : //! \param[in] var Vector of elemental variables to read to: inner vector:
524 : : //! elements, middle vector: (physics) variable, outer vector: time step
525 : : // *****************************************************************************
526 : : {
527 : 999 : uint64_t time = 0;
528 : 999 : int varid = 0;
529 : :
530 [ + + ]: 1002 : for (const auto& t : var) { // for all times
531 : 3 : ++time;
532 [ - + ]: 3 : for (const auto& v : t) { // for all variables
533 [ - - ]: 0 : writeElemScalar( time, ++varid, v );
534 : : }
535 : 3 : varid = 0;
536 : : }
537 : 999 : }
538 : :
539 : : void
540 : 15505 : ExodusIIMeshWriter::writeElemScalar( uint64_t it,
541 : : int varid,
542 : : const std::vector< tk::real >& var ) const
543 : : // *****************************************************************************
544 : : // Write elem scalar field to ExodusII file
545 : : //! \param[in] it Iteration number
546 : : //! \param[in] varid Variable id
547 : : //! \param[in] var Vector of variable to output
548 : : // *****************************************************************************
549 : : {
550 [ + - ]: 15505 : if (!var.empty()) {
551 [ - + ][ - - ]: 15505 : ErrChk( ex_put_var( m_outFile,
[ - - ][ - - ]
552 : : static_cast< int >( it ),
553 : : EX_ELEM_BLOCK,
554 : : varid,
555 : : 1,
556 : : static_cast< int64_t >( var.size() ),
557 : : var.data() ) == 0,
558 : : "Failed to write elem scalar to ExodusII file: " + m_filename );
559 : : }
560 : 15505 : }
|