LCOV - code coverage report
Current view: top level - ugbase/lib_algebra/common/matrixio - matrix_io_mtx.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 97.1 % 102 99
Test Date: 2025-09-21 23:31:46 Functions: 100.0 % 17 17

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2012-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Torbjörn Klatt
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3 §7):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : #include "matrix_io_mtx.h"
      34              : 
      35              : namespace ug
      36              : {
      37              : 
      38              : // /////////////////////////////////////////////////////////////////////////////
      39              : // Constructor / Destructor
      40            2 : MatrixIOMtx::MatrixIOMtx() :
      41            2 :   m_pMatFileName( NULL ), m_matFileStream(), m_firstDataLine(0),
      42              :   m_matFileType( MatrixFileType::MATRIX_MARKET ),
      43              :   m_mmTypeCode( MMTypeCode() ),
      44            2 :   m_rows( 0 ), m_cols( 0 ), m_lines( 0 )
      45            2 : {}
      46              : 
      47           10 : MatrixIOMtx::MatrixIOMtx( std::string mFile, int openMode ) :
      48           10 :   m_matFileStream(), m_firstDataLine(0),
      49              :   m_matFileType( MatrixFileType::MATRIX_MARKET ),
      50           20 :   m_mmTypeCode( MMTypeCode() ), m_rows( 0 ), m_cols( 0 ), m_lines( 0 )
      51              : {
      52              :   PROFILE_FUNC();
      53              :   // set the file name
      54           10 :   set_mat_file_name( mFile, openMode );
      55              : 
      56           10 :   if ( openMode == MatrixIO::EXISTING ) {
      57              :     // read matrix type information
      58            7 :     query_matrix_type();
      59              : 
      60              :     // read matrix size information
      61            7 :     query_matrix_characteristics();
      62              :   }
      63           10 : }
      64              : 
      65           12 : MatrixIOMtx::~MatrixIOMtx()
      66              : {
      67           12 :   close_file();
      68           23 :   delete m_pMatFileName;
      69           12 : }
      70              : 
      71              : // /////////////////////////////////////////////////////////////////////////////
      72              : // Public Functions
      73           11 : void MatrixIOMtx::set_mat_file_name( std::string mFile, int openMode )
      74              : {
      75              :   PROFILE_FUNC();
      76           11 :   if( !mFile.empty() ) {
      77           11 :     if ( openMode == MatrixIO::EXISTING ) {
      78              :       UG_ASSERT( FileExists( mFile.c_str() ),
      79              :                 "File " << mFile.c_str() << " could not be found." );
      80            3 :     } else if( openMode == MatrixIO::NEW ) {
      81            3 :       std::ofstream createFile;
      82            3 :       createFile.open( mFile.c_str(), std::ios_base::out );
      83              :       UG_ASSERT( createFile.is_open(), "File could not be created." );
      84            3 :       createFile.close();
      85            3 :     } else {
      86            0 :       UG_THROW( "Invalid open mode specified: " << openMode );
      87              :     }
      88           22 :     m_pMatFileName = new std::string( mFile );
      89              :   }
      90           11 : }
      91              : 
      92            1 : std::string MatrixIOMtx::get_mat_file_name() const
      93              : {
      94            1 :   return std::string( *m_pMatFileName );
      95              : }
      96              : 
      97           10 : void MatrixIOMtx::set_mat_dims( size_t rows, size_t cols, size_t lines )
      98              : {
      99              :   PROFILE_FUNC();
     100              :   UG_ASSERT( rows > 0, "Number rows must be positive." );
     101              :   UG_ASSERT( cols > 0, "Number columns must be positive." );
     102              :   UG_ASSERT( lines > 0, "Number data lines must be positive." );
     103              : 
     104           10 :   m_rows = rows;
     105           10 :   m_cols = cols;
     106           10 :   m_lines = lines;
     107           10 : }
     108              : 
     109            4 : size_t MatrixIOMtx::get_num_rows() const
     110              : {
     111            4 :   return (size_t)m_rows;
     112              : }
     113              : 
     114            4 : size_t MatrixIOMtx::get_num_cols() const
     115              : {
     116            4 :   return (size_t)m_cols;
     117              : }
     118              : 
     119            4 : size_t MatrixIOMtx::get_num_lines() const
     120              : {
     121            4 :   return (size_t)m_lines;
     122              : }
     123              : 
     124        15722 : bool MatrixIOMtx::is_sparse() const
     125              : {
     126        15722 :   return m_mmTypeCode.is_sparse();
     127              : }
     128              : 
     129              : 
     130              : // /////////////////////////////////////////////////////////////////////////////
     131              : // Private Functions
     132           26 : void MatrixIOMtx::open_file( std::ios_base::openmode mode )
     133              : {
     134              :   UG_ASSERT( !m_pMatFileName->empty(), "Matrix File not set." );
     135              : 
     136              :   UG_ASSERT( !m_matFileStream.is_open(), "File alread open." );
     137              : 
     138           26 :   m_matFileStream.open( m_pMatFileName->c_str(), mode );
     139              :   UG_ASSERT( !m_matFileStream.fail() || !m_matFileStream.bad(),
     140              :              "Matrix File could not be opend for reading/writing.\n"
     141              :              << "iostate: " << m_matFileStream.rdstate() );
     142           26 : }
     143              : 
     144           38 : void MatrixIOMtx::close_file()
     145              : {
     146           38 :   if( m_matFileStream.is_open() ) {
     147              : //     m_pMatFileStream->flush();
     148           26 :     m_matFileStream.close();
     149              :   }
     150           38 : }
     151              : 
     152            7 : void MatrixIOMtx::query_matrix_type()
     153              : {
     154              :   PROFILE_FUNC();
     155              :   // open the file
     156            7 :   open_file();
     157              : 
     158            7 :   std::stringstream first_line;
     159              :   // make sure we are at the beginning of the file
     160            7 :   m_matFileStream.seekg( 0 );
     161              : 
     162              :   // get the first line
     163              :   std::string s;
     164            7 :   std::getline( m_matFileStream, s );
     165              :   first_line.str( s );
     166              : 
     167              :   // split the line into its specified parts
     168            7 :   std::string buffer_str = "";
     169              :   std::vector<std::string> banner_items;
     170           42 :   while( first_line >> buffer_str ) {
     171           35 :     banner_items.push_back( buffer_str );
     172              :   };
     173              : 
     174              :   // and make sure the file is a valid MatrixMarket file
     175              :   // a) Banner
     176              :   UG_ASSERT( banner_items.at( 0 ).compare( MM_BANNER_STR ) == 0,
     177              :              "Given file is not a valid Matrix Market file.\n\t"
     178              :              << "First line must start with '" << MM_BANNER_STR
     179              :              << "' and not with '" << banner_items.at( 0 ) << "'." );
     180              :   // b) matrix
     181              :   UG_ASSERT( banner_items.at( 1 ).compare( MM_MTX_STR ) == 0,
     182              :              "Given file is not a valid Matrix Market file.\n\t"
     183              :              << "First line must contain '" << MM_MTX_STR
     184              :              << "' as second element and not '" << banner_items.at( 1 ) << "'." );
     185              : 
     186              :   // c) coordinate / array
     187           21 :   m_mmTypeCode.set_class_type( banner_items.at( 2 ) );
     188              : 
     189              :   // d) data type
     190           14 :   m_mmTypeCode.set_numeric_type( banner_items.at( 3 ) );
     191              : 
     192              :   // e) algebraic type
     193            7 :   m_mmTypeCode.set_algebraic_type( banner_items.at( 4 ) );
     194              : 
     195              :   // close it
     196            7 :   close_file();
     197           14 : }
     198              : 
     199            7 : void MatrixIOMtx::query_matrix_characteristics()
     200              : {
     201              :   PROFILE_FUNC();
     202              :   // open the file
     203            7 :   open_file();
     204              : 
     205              :   // reach end of comments
     206              :   std::string str;
     207              :   do {
     208              :     UG_ASSERT( !m_matFileStream.eof(), "Unexpected end of file." );
     209           14 :     std::getline( m_matFileStream, str );
     210           14 :     m_firstDataLine++;
     211           14 :   } while( str.at( 0 ) == '%' );
     212              : 
     213              :   // get next non-empty line
     214              :   while( str.empty() ) {
     215              :     UG_ASSERT( !m_matFileStream.eof(), "Unexpected end of file." );
     216              :     std::getline( m_matFileStream, str );
     217              :     m_firstDataLine++;
     218              :   }
     219              :   
     220              :   // split the line
     221              :   std::vector<std::string> entriesVec;
     222            7 :   if( m_mmTypeCode.is_sparse() ) {
     223           14 :     boost::algorithm::split( entriesVec, str, boost::is_any_of( " " ),
     224              :                              boost::algorithm::token_compress_on );
     225              :   } else {
     226            0 :     UG_THROW( "Other than sparse MatrixMarket matrices are not yet implemented." );
     227              :   }
     228              : 
     229           14 :   set_mat_dims( boost::lexical_cast<int>( entriesVec.at( 0 ) ),
     230            7 :                 boost::lexical_cast<int>( entriesVec.at( 1 ) ),
     231            7 :                 boost::lexical_cast<int>( entriesVec.at( 2 ) ) );
     232              : 
     233              :   // close the file
     234            7 :   close_file();
     235           14 : }
     236              : 
     237              : 
     238              : //template<typename matrix_type>
     239              : //  std::vector< std::vector<size_t> > determine_matrix_characteristics(const matrix_type &matrix );
     240              : 
     241        15722 : void MatrixIOMtx::read_entry( size_t *m, size_t *n,
     242              :                               CPUAlgebra::matrix_type::value_type *val )
     243              : {
     244              :   PROFILE_FUNC();
     245              :   // make sure, the file is open
     246              :   UG_ASSERT( m_matFileStream.is_open(), "File is not open." );
     247              : 
     248              :   // get the data line and split it
     249              :   std::string line;
     250        15722 :   std::getline( m_matFileStream, line );
     251              :   std::vector<std::string> elements;
     252        15722 :   boost::algorithm::split( elements, line, boost::is_any_of(" "), boost::algorithm::token_compress_on );
     253              : 
     254              :   // parse it according to the matrix type
     255        15722 :   if( is_sparse() ) {
     256              :     UG_ASSERT( elements.size() == 3,
     257              :                "Sparse matrix requires three values per line. Found: "
     258              :                << elements.size() );
     259        15722 :     *m = boost::lexical_cast<size_t>( elements.at( 0 ) );
     260        15722 :     *n = boost::lexical_cast<size_t>( elements.at( 1 ) );
     261        15722 :     *val = boost::lexical_cast<CPUAlgebra::matrix_type::value_type>( elements.at( 2 ) );
     262              :   } else {
     263            0 :     UG_THROW( "Other than sparse MatrixMarket matrices are not yet implemented." );
     264              :   }
     265        31444 : }
     266              : 
     267            3 : void MatrixIOMtx::write_banner()
     268              : {
     269              :   // Write the first lines (banner, comment, characteristics)
     270            3 :   open_file( std::ios_base::out | std::ios_base::trunc );
     271              : 
     272              :   // print out the banner
     273              :   m_matFileStream << MM_BANNER_STR << " " << MM_MTX_STR << " "
     274            6 :                   << MM_COORDINATE_STR << " " << MM_REAL_STR << " ";
     275            3 :   if ( m_mmTypeCode.is_general() ) {
     276            1 :     m_matFileStream << MM_GENERAL_STR;
     277            2 :   } else if ( m_mmTypeCode.is_symmetric() ) {
     278            1 :     m_matFileStream << MM_SYMMETRIC_STR;
     279            1 :   } else if ( m_mmTypeCode.is_skew_symmetric() ) {
     280            1 :     m_matFileStream << MM_SKEW_STR;
     281              :   }
     282            3 :   m_matFileStream << "\n";
     283              : 
     284            3 :   close_file();
     285            3 : }
     286              : 
     287         7861 : void MatrixIOMtx::write_entry( size_t m, size_t n ,
     288              :                                CPUAlgebra::matrix_type::value_type val )
     289              : {
     290              :   PROFILE_FUNC();
     291              :   UG_ASSERT( m_matFileStream.is_open(), "File is not open." );
     292              :   UG_ASSERT( m > 0, "Row index not positive." );
     293              :   UG_ASSERT( n > 0, "Column index not positive." );
     294              :   m_matFileStream.unsetf( std::ios_base::scientific );
     295         7861 :   m_matFileStream << m << " " << n;
     296        10430 :   m_matFileStream << ( (val < 0) ? " " : "  " );
     297              :   m_matFileStream.setf( std::ios_base::scientific);
     298              :   m_matFileStream << std::setprecision(13);
     299         7861 :   m_matFileStream << val << "\n";
     300         7861 :   m_matFileStream.flush();
     301         7861 : }
     302              : 
     303              : } // namespace ug
     304              : 
     305              : // EOF
        

Generated by: LCOV version 2.0-1