Xyst test code coverage report
Current view: top level - IO - GmshMeshWriter.cpp (source / functions) Hit Total Coverage
Commit: 5689ba12dc66a776d3d75f1ee48cc7d78eaa18dc Lines: 80 80 100.0 %
Date: 2024-11-22 19:17:03 Functions: 5 5 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 68 136 50.0 %

           Branch data     Line data    Source code
       1                 :            : // *****************************************************************************
       2                 :            : /*!
       3                 :            :   \file      src/IO/GmshMeshWriter.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     Gmsh mesh writer class definition
      10                 :            :   \details   Gmsh mesh writer class definition. Currently, this class supports
      11                 :            :     line, triangle, tetrahedron, and point Gmsh element types.
      12                 :            : */
      13                 :            : // *****************************************************************************
      14                 :            : 
      15                 :            : #include <iterator>
      16                 :            : #include <iomanip>
      17                 :            : #include <algorithm>
      18                 :            : #include <cstddef>
      19                 :            : #include <ostream>
      20                 :            : #include <string>
      21                 :            : #include <utility>
      22                 :            : 
      23                 :            : #include "Exception.hpp"
      24                 :            : #include "UnsMesh.hpp"
      25                 :            : #include "PrintUtil.hpp"
      26                 :            : #include "GmshMeshWriter.hpp"
      27                 :            : #include "GmshMeshIO.hpp"
      28                 :            : 
      29                 :            : using tk::GmshMeshWriter;
      30                 :            : 
      31                 :          6 : GmshMeshWriter::GmshMeshWriter( const std::string& filename,
      32                 :            :                                 GmshFileType type,
      33                 :            :                                 tk::real version,
      34                 :          6 :                                 int datasize ) :
      35                 :          6 :   Writer( filename ), m_type( type )
      36                 :            : // *****************************************************************************
      37                 :            : //  Constructor: write mandatory "$MeshFormat" section
      38                 :            : //! \param[in] filename File to open as a Gmsh file
      39                 :            : //! \param[in] type Gmsh file type: ASCII or binary
      40                 :            : //! \param[in] version Gmsh file version
      41                 :            : //! \param[in] datasize Size of double precision number on machine
      42                 :            : // *****************************************************************************
      43                 :            : {
      44                 :            :   using tk::operator<<;
      45                 :            : 
      46                 :            :   // Write beginning of header: $MeshFormat
      47         [ +  - ]:          6 :   m_outFile << "$MeshFormat\n";
      48 [ +  - ][ -  + ]:          6 :   ErrChk( !m_outFile.bad(), "Failed to write to file: " + m_filename );
         [ -  - ][ -  - ]
                 [ -  - ]
      49                 :            : 
      50                 :            :   // Write "version-number file-type data-size"
      51 [ +  - ][ +  - ]:          6 :   m_outFile << version << " " << type << " " << datasize << "\n";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
      52 [ +  - ][ -  + ]:          6 :   ErrChk( !m_outFile.bad(), "Failed to write to file: " + m_filename );
         [ -  - ][ -  - ]
                 [ -  - ]
      53                 :            : 
      54         [ +  + ]:          6 :   if (isBinary()) {
      55                 :          5 :     int one = 1;
      56         [ +  - ]:          5 :     m_outFile.write( reinterpret_cast<char*>(&one), sizeof(int) );
      57         [ +  - ]:          5 :     m_outFile << std::endl;
      58                 :            :   }
      59                 :            : 
      60                 :            :   // Write end of header: $EndMeshFormat
      61 [ +  - ][ +  - ]:          6 :   m_outFile << "$EndMeshFormat" << std::endl;
      62 [ +  - ][ -  + ]:          6 :   ErrChk( !m_outFile.bad(), "Failed to write to file: " + m_filename );
         [ -  - ][ -  - ]
                 [ -  - ]
      63                 :          6 : }
      64                 :            : 
      65                 :            : void
      66                 :          6 : GmshMeshWriter::writeMesh( const UnsMesh& mesh )
      67                 :            : // *****************************************************************************
      68                 :            : //  Write Gmsh mesh file
      69                 :            : //! \param[in] mesh Unstructured mesh object
      70                 :            : // *****************************************************************************
      71                 :            : {
      72                 :            :   // Write sections
      73                 :          6 :   writeNodes( mesh );
      74                 :          6 :   writeElements( mesh );
      75                 :          6 : }
      76                 :            : 
      77                 :            : void
      78                 :          6 : GmshMeshWriter::writeNodes( const UnsMesh& mesh )
      79                 :            : // *****************************************************************************
      80                 :            : //  Write "$Nodes--$EndNodes" section
      81                 :            : //! \param[in] mesh Unstructured mesh object
      82                 :            : // *****************************************************************************
      83                 :            : {
      84                 :          6 :   m_outFile << "$Nodes" << std::endl;
      85                 :            : 
      86                 :            :   // Write out number of nodes
      87                 :          6 :   m_outFile << mesh.nnode() << std::endl;
      88                 :            : 
      89                 :            :   // Write node ids and coordinates: node-number x-coord y-coord z-coord
      90         [ +  + ]:          6 :   if (isASCII()) {
      91         [ +  + ]:         15 :     for (std::size_t i=0; i<mesh.nnode(); ++i) {
      92                 :         14 :       m_outFile << i+1 << " " << std::setprecision(16)
      93                 :         14 :                 << mesh.x()[i] << " "
      94                 :         14 :                 << mesh.y()[i] << " "
      95                 :         14 :                 << mesh.z()[i] << std::endl;
      96                 :            :     }
      97                 :            :   } else {
      98         [ +  + ]:      19262 :     for (std::size_t i=0; i<mesh.nnode(); ++i) {
      99                 :            :       // gmsh likes one-based node ids
     100                 :      19257 :       int I = static_cast< int >( i+1 );
     101         [ +  - ]:      19257 :       m_outFile.write(
     102                 :            :         reinterpret_cast<const char*>(&I), sizeof(int) );
     103         [ +  - ]:      19257 :       m_outFile.write(
     104                 :      19257 :         reinterpret_cast<const char*>(&mesh.x()[i]), sizeof(double) );
     105         [ +  - ]:      19257 :       m_outFile.write(
     106                 :      19257 :         reinterpret_cast<const char*>(&mesh.y()[i]), sizeof(double) );
     107         [ +  - ]:      19257 :       m_outFile.write(
     108                 :      19257 :         reinterpret_cast<const char*>(&mesh.z()[i]), sizeof(double) );
     109                 :            :     }
     110                 :          5 :     m_outFile << std::endl;
     111                 :            :   }
     112                 :            : 
     113                 :          6 :   m_outFile << "$EndNodes" << std::endl;
     114                 :          6 : }
     115                 :            : 
     116                 :            : void
     117                 :          6 : GmshMeshWriter::writeElements( const UnsMesh& mesh )
     118                 :            : // *****************************************************************************
     119                 :            : //  Write "$Elements--$EndElements" section
     120                 :            : //! \param[in] mesh Unstructured mesh object
     121                 :            : // *****************************************************************************
     122                 :            : {
     123                 :          6 :   m_outFile << "$Elements" << std::endl;
     124                 :            : 
     125                 :            :   // Write out number of elements
     126                 :          6 :   m_outFile << mesh.triinpoel().size()/3 + mesh.tetinpoel().size()/4
     127                 :          6 :             << std::endl;
     128                 :            : 
     129                 :            :   // Write out triangle element ids and connectivity (node list)
     130                 :          6 :   writeElemBlock( 3, GmshElemType::TRI, mesh.triinpoel() );
     131                 :            : 
     132                 :            :   // Write out terahedron element ids and connectivity (node list)
     133                 :          6 :   writeElemBlock( 4, GmshElemType::TET, mesh.tetinpoel() );
     134                 :            : 
     135         [ +  + ]:          6 :   if (isBinary()) m_outFile << std::endl;
     136                 :          6 :   m_outFile << "$EndElements" << std::endl;
     137                 :          6 : }
     138                 :            : 
     139                 :            : void
     140                 :         12 : GmshMeshWriter::writeElemBlock( std::size_t nnpe,
     141                 :            :                                 GmshElemType type,
     142                 :            :                                 const std::vector< std::size_t >& inpoel )
     143                 :            : // *****************************************************************************
     144                 :            : //  Write element block: element ids and connectivity (node list)
     145                 :            : //! \param[in] nnpe Number of nodes per element
     146                 :            : //! \param[in] type Element type
     147                 :            : //! \param[in] inpoel Element connectivity (must be zero-based)
     148                 :            : // *****************************************************************************
     149                 :            : {
     150                 :            :   // Return if connectivity is empty, there is no such element block in mesh
     151         [ +  + ]:         12 :   if (inpoel.empty()) return;
     152                 :            : 
     153                 :            :   // Make sure element connectivity starts with zero
     154 [ +  - ][ -  + ]:         10 :   Assert( *std::minmax_element( begin(inpoel), end(inpoel) ).first == 0,
         [ -  - ][ -  - ]
                 [ -  - ]
     155                 :            :           "node ids should start from zero" );
     156                 :            : 
     157                 :            :   // Get number of elements in mesh
     158                 :         10 :   auto n = inpoel.size()/nnpe;
     159                 :            : 
     160                 :            :   // Ignore element tags
     161                 :         10 :   std::vector< std::vector< int > > tg;
     162         [ +  - ]:         10 :   tg.resize( n );
     163 [ +  - ][ +  + ]:     109390 :   for (auto& t : tg) t.push_back( 0 );
     164                 :            : 
     165         [ +  + ]:         10 :   if (isASCII()) {
     166                 :            : 
     167         [ +  + ]:         25 :     for (std::size_t i=0; i<n; i++) {
     168                 :            :       // elm-number elm-type number-of-tags < tag > ... node-number-list
     169 [ +  - ][ +  - ]:         24 :       m_outFile << i+1 << " " << type << " " << tg[i].size() << " ";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     170         [ +  - ]:         24 :       copy( tg[i].begin(), tg[i].end()-1,
     171                 :         24 :             std::ostream_iterator< int >( m_outFile, " " ) );
     172 [ +  - ][ +  - ]:         24 :       m_outFile << tg[i].back() << " ";
     173                 :            : 
     174                 :            :       // gmsh likes one-based node ids
     175 [ +  - ][ +  - ]:        120 :       for (std::size_t k=0; k<nnpe; k++) m_outFile << inpoel[i*nnpe+k]+1 << " ";
                 [ +  + ]
     176         [ +  - ]:         24 :       m_outFile << std::endl;
     177                 :            :     }
     178                 :            : 
     179                 :            :   } else {
     180                 :            : 
     181                 :          9 :     int ntags = static_cast< int >( tg[0].size() );
     182                 :          9 :     int nel = static_cast< int >( n );
     183                 :            :     // elm-type num-of-elm-follow number-of-tags
     184         [ +  - ]:          9 :     m_outFile.write( reinterpret_cast<char*>(&type), sizeof(int) );
     185         [ +  - ]:          9 :     m_outFile.write( reinterpret_cast<char*>(&nel), sizeof(int) );
     186         [ +  - ]:          9 :     m_outFile.write( reinterpret_cast<char*>(&ntags), sizeof(int) );
     187         [ +  + ]:     109365 :     for (std::size_t i=0; i<n; i++) {
     188                 :     109356 :       int I = static_cast< int >( i );
     189                 :            :       // gmsh likes one-based node ids
     190                 :     109356 :       std::vector< int > Inpoel;
     191         [ +  + ]:     536652 :       for (std::size_t k=0; k<nnpe; ++k)
     192         [ +  - ]:     427296 :          Inpoel.push_back( static_cast< int >( inpoel[i*nnpe+k]+1 ) );
     193                 :            :       // element id
     194         [ +  - ]:     109356 :       m_outFile.write( reinterpret_cast<const char*>(&I), sizeof(int) );
     195                 :            :       // element tags
     196         [ +  - ]:     109356 :       m_outFile.write( reinterpret_cast<const char*>(tg[i].data()),
     197                 :     109356 :                        static_cast<std::streamsize>(tg[i].size()*sizeof(int)) );
     198                 :            :       // element node list (i.e. connectivity)
     199         [ +  - ]:     109356 :       m_outFile.write( reinterpret_cast<const char*>(Inpoel.data()),
     200                 :     109356 :                        static_cast<std::streamsize>(nnpe*sizeof(int)) );
     201                 :     109356 :     }
     202                 :            : 
     203                 :            :   }
     204                 :         10 : }

Generated by: LCOV version 1.16