Xyst test code coverage report
Current view: top level - IO - MeshWriter.cpp (source / functions) Hit Total Coverage
Commit: 5689ba12dc66a776d3d75f1ee48cc7d78eaa18dc Lines: 78 79 98.7 %
Date: 2024-11-22 19:17:03 Functions: 2 2 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 99 190 52.1 %

           Branch data     Line data    Source code
       1                 :            : // *****************************************************************************
       2                 :            : /*!
       3                 :            :   \file      src/IO/MeshWriter.cpp
       4                 :            :   \copyright 2012-2015 J. Bakosi,
       5                 :            :              2016-2018 Los Alamos National Security, LLC.,
       6                 :            :              2019-2021 Triad National Security, LLC.,
       7                 :            :              2022-2024 J. Bakosi
       8                 :            :              All rights reserved. See the LICENSE file for details.
       9                 :            :   \brief     Charm++ group for outputing mesh data to file
      10                 :            :   \details   Charm++ group definition used to output data associated to
      11                 :            :      unstructured meshes to file(s). Charm++ chares (work units) send mesh and
      12                 :            :      field data associated to mesh entities to the MeshWriter class defined here
      13                 :            :      to write the data to file(s).
      14                 :            : */
      15                 :            : // *****************************************************************************
      16                 :            : 
      17                 :            : #include "XystBuildConfig.hpp"
      18                 :            : #include "MeshWriter.hpp"
      19                 :            : #include "Reorder.hpp"
      20                 :            : #include "ExodusIIMeshWriter.hpp"
      21                 :            : 
      22                 :            : using tk::MeshWriter;
      23                 :            : 
      24                 :            : void
      25                 :       3368 : MeshWriter::write(
      26                 :            :   std::size_t meshid,
      27                 :            :   bool meshoutput,
      28                 :            :   bool fieldoutput,
      29                 :            :   uint64_t itr,
      30                 :            :   uint64_t itf,
      31                 :            :   tk::real time,
      32                 :            :   int chareid,
      33                 :            :   const std::string& basefilename,
      34                 :            :   const std::vector< std::size_t >& inpoel,
      35                 :            :   const UnsMesh::Coords& coord,
      36                 :            :   const std::map< int, std::vector< std::size_t > >& bface,
      37                 :            :   const std::map< int, std::vector< std::size_t > >& bnode,
      38                 :            :   const std::vector< std::size_t >& triinpoel,
      39                 :            :   const std::vector< std::string >& elemfieldnames,
      40                 :            :   const std::vector< std::string >& nodefieldnames,
      41                 :            :   const std::vector< std::string >& elemsurfnames,
      42                 :            :   const std::vector< std::string >& nodesurfnames,
      43                 :            :   const std::vector< std::vector< tk::real > >& elemfields,
      44                 :            :   const std::vector< std::vector< tk::real > >& nodefields,
      45                 :            :   const std::vector< std::vector< tk::real > >& elemsurfs,
      46                 :            :   const std::vector< std::vector< tk::real > >& nodesurfs,
      47                 :            :   const std::set< int >& outsets,
      48                 :            :   CkCallback c )
      49                 :            : // *****************************************************************************
      50                 :            : //  Output unstructured mesh into file
      51                 :            : //! \param[in] meshid Mesh Id
      52                 :            : //! \param[in] meshoutput True if mesh is to be written
      53                 :            : //! \param[in] fieldoutput True if field data is to be written
      54                 :            : //! \param[in] itr Iteration count since a new mesh. New mesh in this context
      55                 :            : //!   means that either the mesh is moved and/or its topology has changed.
      56                 :            : //! \param[in] itf Field output iteration count
      57                 :            : //! \param[in] time Physical time this at this field output dump
      58                 :            : //! \param[in] chareid The chare id the write-to-file request is coming from
      59                 :            : //! \param[in] basefilename String to use as the base of the filename
      60                 :            : //! \param[in] inpoel Mesh connectivity for the mesh chunk to be written with
      61                 :            : //!   local ids
      62                 :            : //! \param[in] coord Node coordinates of the mesh chunk to be written
      63                 :            : //! \param[in] bface Map of boundary-face lists mapped to corresponding side set
      64                 :            : //!   ids for this mesh chunk
      65                 :            : //! \param[in] bnode Map of boundary-node lists mapped to corresponding side set
      66                 :            : //!   ids for this mesh chunk with local ids
      67                 :            : //! \param[in] triinpoel Interconnectivity of points and boundary-face in this
      68                 :            : //!   mesh chunk with local ids
      69                 :            : //! \param[in] elemfieldnames Names of element fields to be output to file
      70                 :            : //! \param[in] nodefieldnames Names of node fields to be output to file
      71                 :            : //! \param[in] elemsurfnames Names of eleme surface fields to be output to file
      72                 :            : //! \param[in] nodesurfnames Names of node surface fields to be output to file
      73                 :            : //! \param[in] elemfields Field data in mesh elements to output to file
      74                 :            : //! \param[in] nodefields Field data in mesh nodes to output to file
      75                 :            : //! \param[in] elemsurfs Surface field data in mesh elements to output to file
      76                 :            : //! \param[in] nodesurfs Surface field data in mesh nodes to output to file
      77                 :            : //! \param[in] outsets Unique set of surface side set ids along which to save
      78                 :            : //!   solution field variables
      79                 :            : //! \param[in] c Function to continue with after the write
      80                 :            : // *****************************************************************************
      81                 :            : {
      82 [ -  + ][ -  - ]:       3368 :   if (m_benchmark) { c.send(); return; }
      83                 :            : 
      84                 :            :   // Generate filenames for volume and surface field output
      85         [ +  - ]:       3368 :   auto vf = filename( basefilename, meshid, itr, chareid );
      86                 :            :   
      87         [ +  + ]:       3368 :   if (meshoutput) {
      88                 :            :     // Write volume mesh and field names
      89         [ +  - ]:        805 :     ExodusIIMeshWriter ev( vf, ExoWriter::CREATE );
      90                 :            :     // Write chare mesh (do not write side sets in parallel)
      91         [ +  + ]:        805 :     if (m_nchare == 1) {
      92 [ +  - ][ +  - ]:         77 :       ev.writeMesh( tk::UnsMesh( inpoel, coord, bnode ) );
      93                 :            :     } else {
      94         [ +  - ]:        728 :       ev.writeMesh< 4 >( inpoel, coord );
      95                 :            :     }
      96         [ +  - ]:        805 :     ev.writeElemVarNames( elemfieldnames );
      97 [ -  + ][ -  - ]:        805 :     Assert( nodefieldnames.size() == nodefields.size(), "Size mismatch" );
         [ -  - ][ -  - ]
      98         [ +  - ]:        805 :     ev.writeNodeVarNames( nodefieldnames );
      99                 :            : 
     100                 :            :     // Write surface meshes and surface variable field names
     101         [ +  + ]:        841 :     for (auto s : outsets) {
     102         [ +  - ]:         36 :       auto sf = filename( basefilename, meshid, itr, chareid, s );
     103         [ +  - ]:         36 :       ExodusIIMeshWriter es( sf, ExoWriter::CREATE );
     104         [ +  - ]:         36 :       auto b = bface.find(s);
     105         [ +  + ]:         36 :       if (b == end(bface)) {
     106                 :            :         // If a side set does not exist on a chare, write out a
     107                 :            :         // connectivity for a single triangle with its node coordinates of
     108                 :            :         // zero. This is so the paraview series reader can load side sets
     109                 :            :         // distributed across multiple files. See also
     110                 :            :         // https://www.paraview.org/Wiki/Restarted_Simulation_Readers.
     111 [ +  - ][ +  - ]:          3 :         es.writeMesh< 3 >( std::vector< std::size_t >{1,2,3},
     112                 :          3 :           UnsMesh::Coords{{ {{0,0,0}}, {{0,0,0}}, {{0,0,0}} }} );
     113                 :          3 :         es.writeElemVarNames( elemsurfnames );
     114         [ +  - ]:          3 :         es.writeNodeVarNames( nodesurfnames );
     115                 :          3 :         continue;
     116                 :            :       }
     117                 :         33 :       std::vector< std::size_t > nodes;
     118         [ +  + ]:       5493 :       for (auto f : b->second) {
     119         [ +  - ]:       5460 :         nodes.push_back( triinpoel[f*3+0] );
     120         [ +  - ]:       5460 :         nodes.push_back( triinpoel[f*3+1] );
     121         [ +  - ]:       5460 :         nodes.push_back( triinpoel[f*3+2] );
     122                 :            :       }
     123         [ +  - ]:         33 :       auto [inp,gid,lid] = tk::global2local( nodes );
     124         [ +  - ]:         33 :       tk::unique( nodes );
     125                 :         33 :       auto nnode = nodes.size();
     126                 :         33 :       UnsMesh::Coords scoord;
     127         [ +  - ]:         33 :       scoord[0].resize( nnode );
     128         [ +  - ]:         33 :       scoord[1].resize( nnode );
     129         [ +  - ]:         33 :       scoord[2].resize( nnode );
     130                 :         33 :       std::size_t j = 0;
     131         [ +  + ]:       3783 :       for (auto i : nodes) {
     132                 :       3750 :         scoord[0][j] = coord[0][i];
     133                 :       3750 :         scoord[1][j] = coord[1][i];
     134                 :       3750 :         scoord[2][j] = coord[2][i];
     135                 :       3750 :         ++j;
     136                 :            :       }
     137         [ +  - ]:         33 :       es.writeMesh< 3 >( inp, scoord );
     138         [ +  - ]:         33 :       es.writeElemVarNames( elemsurfnames );
     139         [ +  - ]:         33 :       es.writeNodeVarNames( nodesurfnames );
     140 [ +  + ][ +  + ]:         39 :     }
     141                 :        805 :   }
     142                 :            : 
     143         [ +  - ]:       3368 :   if (fieldoutput) {
     144                 :            :     // Write volume variable fields
     145         [ +  - ]:       3368 :     ExodusIIMeshWriter ev( vf, ExoWriter::OPEN );
     146         [ +  - ]:       3368 :     ev.writeTimeStamp( itf, time );
     147                 :            :     // Write volume element variable fields
     148                 :       3368 :     int varid = 0;
     149 [ +  - ][ +  + ]:       3662 :     for (const auto& v : elemfields) ev.writeElemScalar( itf, ++varid, v );
     150                 :            :     // Write volume node variable fields
     151                 :       3368 :     varid = 0;
     152 [ +  - ][ +  + ]:      36169 :     for (const auto& v : nodefields) ev.writeNodeScalar( itf, ++varid, v );
     153                 :            : 
     154                 :            :     // Write surface node variable fields
     155                 :       3368 :     std::size_t j = 0;
     156                 :       3368 :     std::size_t k = 0;
     157                 :       3368 :     auto nvar = static_cast< int >( nodesurfnames.size() ) ;
     158                 :       3368 :     auto nevar = static_cast< int >( elemsurfnames.size() ) ;
     159         [ +  + ]:       3524 :     for (auto s : outsets) {
     160         [ +  - ]:        156 :       auto sf = filename( basefilename, meshid, itr, chareid, s );
     161         [ +  - ]:        156 :       ExodusIIMeshWriter es( sf, ExoWriter::OPEN );
     162         [ +  - ]:        156 :       es.writeTimeStamp( itf, time );
     163 [ +  - ][ +  + ]:        156 :       if (bface.find(s) == end(bface)) {
     164                 :            :         // If a side set does not exist on a chare, write out a
     165                 :            :         // a node field for a single triangle with zeros. This is so the
     166                 :            :         // paraview series reader can load side sets distributed across
     167                 :            :         // multiple files. See also
     168                 :            :         // https://www.paraview.org/Wiki/Restarted_Simulation_Readers.
     169 [ +  - ][ +  - ]:        126 :         for (int i=1; i<=nvar; ++i) es.writeNodeScalar( itf, i, {0,0,0} );
                 [ +  + ]
     170 [ -  - ][ -  - ]:         18 :         for (int i=1; i<=nevar; ++i) es.writeElemScalar( itf, i, {0} );
                 [ -  + ]
     171                 :         18 :         continue;
     172                 :         18 :       }
     173         [ +  + ]:        966 :       for (int i=1; i<=nvar; ++i)
     174         [ +  - ]:        828 :         es.writeNodeScalar( itf, i, nodesurfs[j++] );
     175         [ -  + ]:        138 :       for (int i=1; i<=nevar; ++i)
     176         [ -  - ]:          0 :         es.writeElemScalar( itf, i, elemsurfs[k++] );
     177 [ +  + ][ +  + ]:        174 :     }
     178                 :       3368 :   }
     179                 :            : 
     180         [ +  - ]:       3368 :   c.send();
     181 [ +  - ][ +  - ]:       3374 : }
         [ +  - ][ +  - ]
         [ -  - ][ -  - ]
     182                 :            : 
     183                 :            : std::string
     184                 :       3560 : MeshWriter::filename( const std::string& basefilename,
     185                 :            :                       std::size_t meshid,
     186                 :            :                       uint64_t itr,
     187                 :            :                       int chareid,
     188                 :            :                       int surfid ) const
     189                 :            : // *****************************************************************************
     190                 :            : //  Compute filename
     191                 :            : //! \param[in] basefilename String use as the base filename.
     192                 :            : //! \param[in] meshid Mesh Id
     193                 :            : //! \param[in] itr Iteration count since a new mesh. New mesh in this context
     194                 :            : //!   means that either the mesh is moved and/or its topology has changed.
     195                 :            : //! \param[in] chareid The chare id the write-to-file request is coming from
     196                 :            : //! \param[in] surfid Surface ID if computing a surface filename
     197                 :            : //! \details We use a file naming convention for large field output data that
     198                 :            : //!   allows ParaView to glue multiple files into a single simulation output by
     199                 :            : //!   only loading a single file. The base filename is followed by ".e-s.",
     200                 :            : //!   which probably stands for Exodus Sequence, followed by 3 integers:
     201                 :            : //!   (1) {RS}: counts the number of "restart dumps", but we use this for
     202                 :            : //!   counting the number of outputs with a different mesh, e.g., due to
     203                 :            : //!   mesh refinement, thus if this first number is new the mesh is new
     204                 :            : //!   compared to the previous (first) number afer ".e-s.",
     205                 :            : //!   (2) {NP}: total number of partitions (workers, chares), this is more than
     206                 :            : //!   the number of PEs with nonzero virtualization (overdecomposition), and
     207                 :            : //!   (3) {RANK}: worker (chare) id.
     208                 :            : //!   Thus {RANK} does spatial partitioning, while {RS} partitions in time, but
     209                 :            : //!   a single {RS} id may contain multiple time steps, which equals to the
     210                 :            : //!   number of time steps at which field output is saved without refining the
     211                 :            : //!   mesh.
     212                 :            : //! \return Filename computed
     213                 :            : //! \see https://www.paraview.org/Wiki/Restarted_Simulation_Readers
     214                 :            : // *****************************************************************************
     215                 :            : {
     216 [ +  + ][ +  - ]:       7120 :   return basefilename + (surfid ? "-surf." + std::to_string(surfid) : "")
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
         [ -  - ][ -  - ]
     217 [ -  + ][ -  - ]:      14240 :          + (m_nmesh > 1 ? '.' + std::to_string(meshid) : "")
         [ -  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ -  - ]
                 [ -  - ]
     218         [ +  - ]:       7120 :          + ".e-s"
     219 [ +  - ][ +  - ]:      14240 :          + '.' + std::to_string( itr )        // iteration count with new mesh
                 [ +  - ]
     220 [ +  - ][ +  - ]:      14240 :          + '.' + std::to_string( m_nchare )   // total number of workers
     221 [ +  - ][ +  - ]:      14240 :          + '.' + std::to_string( chareid );   // new file per worker
     222                 :            : }
     223                 :            : 
     224                 :            : #include "NoWarning/meshwriter.def.h"

Generated by: LCOV version 1.16