|
Teuchos Package Browser (Single Doxygen Collection)
Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Teuchos: Common Tools Package 00005 // Copyright (2004) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00038 // 00039 // *********************************************************************** 00040 // @HEADER 00041 00042 #include <Teuchos_MatrixMarket_Raw_Checker.hpp> 00043 #include <Teuchos_MatrixMarket_Raw_Reader.hpp> 00044 #include <Teuchos_MatrixMarket_Raw_Writer.hpp> 00045 #include <Teuchos_MatrixMarket_SetScientific.hpp> 00046 #include <Teuchos_CommandLineProcessor.hpp> 00047 #include <Teuchos_GlobalMPISession.hpp> 00048 #include <Teuchos_oblackholestream.hpp> 00049 #include <Teuchos_DefaultSerialComm.hpp> 00050 #include <Teuchos_StandardCatchMacros.hpp> 00051 #include <algorithm> 00052 00053 using std::endl; 00054 00055 namespace { 00056 // Sample Matrix Market sparse matrix file. We include this so we 00057 // can test without needing to read in a file. Notice that all the 00058 // decimal floating-point values in this example can be represented 00059 // exactly in binary floating point. This example has correct 00060 // syntax, so you won't need to use tolerant mode to parse it. 00061 const char sampleMatrixMarketFile[] = 00062 "%%MatrixMarket matrix coordinate real general\n" 00063 "5 5 10\n" 00064 "5 5 55.0\n" 00065 "4 4 44.0\n" 00066 "3 3 33.0\n" 00067 "2 2 22.0\n" 00068 "1 1 11.0\n" 00069 "4 5 45.0\n" 00070 "3 4 34.0\n" 00071 "2 3 23.0\n" 00072 "1 2 12.0\n" 00073 "1 5 15.0\n"; 00074 00075 // Sample Matrix Market sparse matrix file for testing symmetric 00076 // storage. Matrix Market format for symmetric, skew-symemtric, 00077 // etc. specifies that only the lower triangle should be stored. 00078 const char symmetricMatrixMarketFile[] = 00079 "%%MatrixMarket matrix coordinate real symmetric\n" 00080 "5 5 10\n" 00081 "5 5 55.0\n" 00082 "4 4 44.0\n" 00083 "3 3 33.0\n" 00084 "2 2 22.0\n" 00085 "1 1 11.0\n" 00086 "5 4 54.0\n" 00087 "4 3 43.0\n" 00088 "3 2 32.0\n" 00089 "2 1 21.0\n" 00090 "5 1 51.0\n"; 00091 00092 } // namespace (anonymous) 00093 00094 // Benchmark driver 00095 int 00096 main (int argc, char *argv[]) 00097 { 00098 using Teuchos::MatrixMarket::Raw::Checker; 00099 using Teuchos::MatrixMarket::Raw::Reader; 00100 using Teuchos::ArrayRCP; 00101 using Teuchos::ArrayView; 00102 using Teuchos::Comm; 00103 using Teuchos::CommandLineProcessor; 00104 using Teuchos::ParameterList; 00105 using Teuchos::RCP; 00106 using Teuchos::rcp; 00107 using Teuchos::rcpFromRef; 00108 using Teuchos::SerialComm; 00109 using std::cout; 00110 using std::cerr; 00111 typedef double scalar_type; 00112 typedef int ordinal_type; 00113 00114 bool success = false; 00115 // Verbosity of output 00116 bool verbose = true; 00117 try { 00118 // Name of the Matrix Market sparse matrix file to read. If empty, 00119 // use the Matrix Market example embedded as a string in this file. 00120 std::string filename; 00121 // If true, just check the sparse matrix file. Otherwise, 00122 // do a full conversion to CSR (compressed sparse row) format. 00123 bool checkOnly = false; 00124 // Whether to echo the sparse matrix to stdout after reading it 00125 // successfully. 00126 bool echo = false; 00127 // Whether to parse the Matrix Market file tolerantly. 00128 bool tolerant = false; 00129 // Whether to print debugging-level output 00130 bool debug = false; 00131 00132 CommandLineProcessor cmdp (false, true); 00133 cmdp.setOption ("filename", &filename, 00134 "Name of the Matrix Market sparse matrix file to read."); 00135 cmdp.setOption ("checkOnly", "fullTest", &checkOnly, 00136 "If true, just check the syntax of the input file. " 00137 "Otherwise, do a full test."); 00138 cmdp.setOption ("echo", "noecho", &echo, 00139 "Whether to echo the sparse matrix contents to stdout " 00140 "after reading it successfully."); 00141 cmdp.setOption ("tolerant", "strict", &tolerant, 00142 "Whether to tolerate syntax errors in the Matrix Market file."); 00143 cmdp.setOption ("verbose", "quiet", &verbose, 00144 "Print status output to stdout."); 00145 cmdp.setOption ("debug", "nodebug", &debug, 00146 "Print possibly copious debugging output to stderr."); 00147 // Parse the command-line arguments. 00148 { 00149 const CommandLineProcessor::EParseCommandLineReturn parseResult = 00150 cmdp.parse (argc,argv); 00151 // If the caller asks us to print the documentation, or does not 00152 // explicitly say to run the benchmark, we let this "test" pass 00153 // trivially. 00154 if (parseResult == CommandLineProcessor::PARSE_HELP_PRINTED) { 00155 std::cout << "End Result: TEST PASSED" << endl; 00156 return EXIT_SUCCESS; 00157 } 00158 TEUCHOS_TEST_FOR_EXCEPTION( 00159 parseResult != CommandLineProcessor::PARSE_SUCCESSFUL, 00160 std::invalid_argument, "Failed to parse command-line arguments."); 00161 } 00162 00163 // Test reading in the sparse matrix. If no filename or an empty 00164 // filename is specified, the test passes trivially. 00165 success = true; 00166 if (checkOnly) { 00167 typedef Checker<scalar_type, ordinal_type> checker_type; 00168 checker_type checker (echo, tolerant, debug); 00169 00170 RCP<const Comm<int> > comm = rcp (new SerialComm<int>); 00171 if (filename != "") { 00172 if (verbose) { 00173 cout << "Checking syntax of the Matrix Market file \"" << filename 00174 << "\"" << endl; 00175 } 00176 success = success && checker.readFile (*comm, filename); 00177 if (verbose) { 00178 if (success) { 00179 cout << "The given file is a valid Matrix Market file." << endl; 00180 } 00181 else { 00182 cout << "The given file has syntax errors." << endl; 00183 } 00184 } 00185 } 00186 else { 00187 if (verbose) { 00188 cout << "Checking syntax of the first built-in Matrix Market example" << endl 00189 << std::flush;// for debug output next 00190 } 00191 if (debug) { 00192 cerr << "First built-in Matrix Market example: " << endl 00193 << sampleMatrixMarketFile << endl; 00194 } 00195 std::istringstream in (sampleMatrixMarketFile); 00196 RCP<std::istream> inStream = rcpFromRef (in); 00197 success = success && checker.read (*comm, inStream); 00198 if (verbose) { 00199 if (success) { 00200 cout << "The example has valid Matrix Market syntax." << endl; 00201 } 00202 else { 00203 cout << "The example has syntax errors." << endl; 00204 } 00205 } 00206 } 00207 } 00208 else { 00209 typedef Reader<scalar_type, ordinal_type> reader_type; 00210 reader_type reader (tolerant, debug); 00211 ArrayRCP<ordinal_type> ptr, ind; 00212 ArrayRCP<scalar_type> val; 00213 ordinal_type numRows, numCols; 00214 // 00215 // Read the Matrix Market data, either from a file or from a 00216 // built-in string. 00217 // 00218 if (filename != "") { 00219 if (verbose) { 00220 cout << "Reading the Matrix Market file \"" << filename << "\"" << endl; 00221 } 00222 success = success && reader.readFile (ptr, ind, val, 00223 numRows, numCols, filename); 00224 } 00225 else { 00226 if (verbose) { 00227 cout << "Reading the first built-in Matrix Market example" << endl; 00228 } 00229 if (debug) { 00230 cerr << "First built-in Matrix Market example:" << endl 00231 << sampleMatrixMarketFile << endl; 00232 } 00233 std::istringstream inStr (sampleMatrixMarketFile); 00234 success = success && reader.read (ptr, ind, val, numRows, numCols, inStr); 00235 } 00236 TEUCHOS_TEST_FOR_EXCEPTION(! success, std::runtime_error, "Matrix Market " 00237 "reader failed to read the given file or input stream."); 00238 if (success && verbose) { 00239 cout << "Returned from reading the Matrix Market data" << endl 00240 << std::flush; // for following debug output 00241 } 00242 if (debug) { 00243 cerr << "CSR output info:" << endl 00244 << " ptr.size() = " << ptr.size() 00245 << ", ind.size() = " << ind.size() 00246 << ", val.size() = " << val.size() 00247 << ", numRows = " << numRows 00248 << ", numCols = " << numCols 00249 << endl; 00250 } 00251 00252 // Here's the fun part. Output the CSR data to an output stream. 00253 // Then read in the output stream. The resulting matrix should be 00254 // exactly the same (unless the original file had elements at the 00255 // same location that were added together with rounding error). 00256 // This is a test for both Writer and Reader. 00257 std::ostringstream outStr; 00258 if (success && verbose) { 00259 cout << "Printing the CSR arrays to a Matrix Market output stream" 00260 << endl << std::flush; 00261 } 00262 Teuchos::MatrixMarket::Raw::Writer<scalar_type, ordinal_type> writer; 00263 writer.write (outStr, ptr (), ind (), val (), numRows, numCols); 00264 00265 if (debug && echo) { 00266 cerr << "CSR data:" << endl 00267 << "- ptr = ["; 00268 for (ordinal_type i = 0; i < ptr.size(); ++i) { 00269 cerr << ptr[i]; 00270 if (i+1 != ptr.size()) { // don't subtract from zero if unsigned 00271 cerr << ", "; 00272 } 00273 } 00274 cerr << "]" << endl 00275 << "- ind = ["; 00276 for (ordinal_type i = 0; i < ind.size(); ++i) { 00277 cerr << ind[i]; 00278 if (i+1 != ind.size()) { // don't subtract from zero if unsigned 00279 cerr << ", "; 00280 } 00281 } 00282 cerr << "]" << endl 00283 << "- val = ["; 00284 for (ordinal_type i = 0; i < val.size(); ++i) { 00285 cerr << val[i]; 00286 if (i+1 != val.size()) { // don't subtract from zero if unsigned 00287 cerr << ", "; 00288 } 00289 } 00290 cerr << "]" << endl; 00291 00292 cerr << "CSR data, converted back to Matrix Market format" << endl; 00293 writer.write (cerr, ptr (), ind (), val (), numRows, numCols); 00294 cerr << endl; 00295 } 00296 00297 ArrayRCP<ordinal_type> newptr, newind; 00298 ArrayRCP<scalar_type> newval; 00299 ordinal_type newNumRows, newNumCols; 00300 if (success && verbose) { 00301 cout << "Reading the Matrix Market output back into CSR arrays" << endl; 00302 } 00303 { 00304 std::istringstream inStr (outStr.str ()); 00305 success = success && reader.read (newptr, newind, newval, 00306 newNumRows, newNumCols, inStr); 00307 } 00308 TEUCHOS_TEST_FOR_EXCEPTION(! success, std::logic_error, "Matrix Market " 00309 "reader failed to read the output back into CSR arrays."); 00310 if (success && verbose) { 00311 cout << "Successfully read the Matrix Market output back into CSR arrays" 00312 << endl << std::flush; 00313 } 00314 if (debug) { 00315 cerr << "CSR output info:" << endl 00316 << " newptr.size() = " << newptr.size() 00317 << ", newind.size() = " << newind.size() 00318 << ", newval.size() = " << newval.size() 00319 << ", newNumRows = " << newNumRows 00320 << ", newNumCols = " << newNumCols 00321 << endl; 00322 } 00323 00324 // The old arrays should equal the new arrays. 00325 TEUCHOS_TEST_FOR_EXCEPTION(ptr.size () != newptr.size (), std::logic_error, 00326 "New ptr array has a different length than old ptr array"); 00327 TEUCHOS_TEST_FOR_EXCEPTION(ind.size () != newind.size (), std::logic_error, 00328 "New ind array has a different length than old ind array"); 00329 TEUCHOS_TEST_FOR_EXCEPTION(val.size () != newval.size (), std::logic_error, 00330 "New val array has a different length than old val array"); 00331 TEUCHOS_TEST_FOR_EXCEPTION(newNumRows != numRows || newNumCols != numCols, 00332 std::logic_error, "New dimensions differ from old dimensions"); 00333 TEUCHOS_TEST_FOR_EXCEPTION(ptr.size () != numRows+1, std::logic_error, 00334 "ptr.size() != numRows+1"); 00335 TEUCHOS_TEST_FOR_EXCEPTION(newptr.size () != newNumRows+1, std::logic_error, 00336 "newptr.size() != newNumRows+1"); 00337 00338 for (ordinal_type rowIndex = 0; rowIndex < numRows; ++rowIndex) { 00339 TEUCHOS_TEST_FOR_EXCEPTION(ptr[rowIndex] != newptr[rowIndex], 00340 std::logic_error, "At row index " << rowIndex << ", ptr[rowIndex] = " 00341 << ptr[rowIndex] << " != newptr[rowIndex] = " << newptr[rowIndex] 00342 << "."); 00343 TEUCHOS_TEST_FOR_EXCEPTION(ptr[rowIndex+1] != newptr[rowIndex+1], 00344 std::logic_error, "At row index " << rowIndex << ", ptr[rowIndex+1] = " 00345 << ptr[rowIndex+1] << " != newptr[rowIndex+1] = " << newptr[rowIndex+1] 00346 << "."); 00347 for (ordinal_type k = ptr[rowIndex]; k < ptr[rowIndex+1]; ++k) { 00348 TEUCHOS_TEST_FOR_EXCEPTION(ind[k] != newind[k], std::logic_error, 00349 "At row index " << rowIndex << ", ind[k=" << k << "] = " 00350 << ind[k] << " != newind[k] = " << newind[k] << "."); 00351 // You may want to relax this inequality if the original 00352 // Matrix Market file had multiple entries at the same 00353 // location and if adding them together resulted in rounding 00354 // error. 00355 TEUCHOS_TEST_FOR_EXCEPTION(val[k] != newval[k], std::logic_error, 00356 "At row index " << rowIndex << ", val[k=" << k << "] = " 00357 << val[k] << " != newval[k] = " << newval[k] << "."); 00358 } 00359 } 00360 00361 // Now test reading symmetric data, if no filename was specified. 00362 if (filename == "") { 00363 std::istringstream inStr (symmetricMatrixMarketFile); 00364 success = success && reader.read (ptr, ind, val, numRows, numCols, inStr); 00365 TEUCHOS_TEST_FOR_EXCEPTION(! success, std::logic_error, 00366 "Matrix Market reader failed to read the given example string."); 00367 if (success && verbose) { 00368 cout << "Returned from reading the Matrix Market data" << endl 00369 << std::flush; // for following debug output 00370 } 00371 if (debug) { 00372 cerr << "CSR output info:" << endl 00373 << " ptr.size() = " << ptr.size() 00374 << ", ind.size() = " << ind.size() 00375 << ", val.size() = " << val.size() 00376 << ", numRows = " << numRows 00377 << ", numCols = " << numCols 00378 << endl; 00379 } 00380 00381 // This is a bit of a hack, since we know the contents of the 00382 // example. Since we "symmetrize" when reading in symmetric 00383 // data, there should be 15 entries in the resulting matrix. 00384 const ordinal_type correctNumEntries = 15; 00385 TEUCHOS_TEST_FOR_EXCEPTION( 00386 val.size() != correctNumEntries, 00387 std::logic_error, 00388 "Incorrect number of entries after symmetrization: There should be " 00389 << correctNumEntries << ", but there are " << val.size() << " entries " 00390 "instead."); 00391 } 00392 } // end of the file / string Reader tests 00393 00394 if (success) 00395 std::cout << "End Result: TEST PASSED" << endl; 00396 else 00397 std::cout << "End Result: TEST FAILED" << endl; 00398 } 00399 TEUCHOS_STANDARD_CATCH_STATEMENTS(verbose, std::cerr, success); 00400 00401 return ( success ? EXIT_SUCCESS : EXIT_FAILURE ); 00402 }
1.7.6.1