tstYieldResourceIO.cpp

./Core/io/tests/tstYieldResourceIO.cpp

#include <cmath>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <istream>
#include <string>
#include <vector>
#include "ScaleData/Core/Utils.h"
#include "ScaleFileUtils/FileUtils.h"
#include "Nemesis/gtest/nemesis_gtest.hh"
#include "Origen/Core/TestPaths.h"
namespace Origen
{
namespace test
{
// extended writer for testing
class STab1Writer : public ::Origen::STab1Writer
{
public:
static std::string as_string( double value )
{
std::string line;
STab1Writer::setRealValue( &line, value, 1 );
line.resize( 11 );
return line;
}
};
#define SEXPECT_EQ( a, b ) EXPECT_EQ( a, STab1Writer::as_string( b ) )
TEST( Ampx, FloatWriting )
{
// positive numbers with exponents
SEXPECT_EQ( " 1.0000-200", 1e-200 );
SEXPECT_EQ( " 1.0000-100", 1e-100 );
SEXPECT_EQ( " 1.00000-99", 1e-99 );
SEXPECT_EQ( " 1.00000-10", 1e-10 );
SEXPECT_EQ( " 1.000000-9", 1e-9 );
SEXPECT_EQ( " 1.000000-8", 1e-8 );
SEXPECT_EQ( " 1.000000-7", 1e-7 );
SEXPECT_EQ( " 1.000000-6", 1e-6 );
SEXPECT_EQ( " 1.000000-5", 1e-5 );
SEXPECT_EQ( " 1.000000-4", 1e-4 );
SEXPECT_EQ( " 1.000000-3", 1e-3 );
SEXPECT_EQ( " 1.000000-2", 1e-2 );
SEXPECT_EQ( " 1.000000-1", 1e-1 );
SEXPECT_EQ( " 1.000000-0", 1e+0 );
SEXPECT_EQ( " 1.000000+1", 1e+1 );
SEXPECT_EQ( " 1.000000+2", 1e+2 );
SEXPECT_EQ( " 1.000000+3", 1e+3 );
SEXPECT_EQ( " 1.000000+4", 1e+4 );
SEXPECT_EQ( " 1.000000+5", 1e+5 );
SEXPECT_EQ( " 1.000000+6", 1e+6 );
SEXPECT_EQ( " 1.000000+7", 1e+7 );
SEXPECT_EQ( " 1.000000+8", 1e+8 );
SEXPECT_EQ( " 1.000000+9", 1e+9 );
SEXPECT_EQ( " 1.00000+10", 1e+10 );
SEXPECT_EQ( " 1.00000+99", 1e+99 );
SEXPECT_EQ( " 1.0000+100", 1e+100 );
SEXPECT_EQ( " 1.0000+200", 1e+200 );
// negative numbers with exponents
SEXPECT_EQ( "-1.0000-200", -1e-200 );
SEXPECT_EQ( "-1.0000-100", -1e-100 );
SEXPECT_EQ( "-1.00000-99", -1e-99 );
SEXPECT_EQ( "-1.00000-10", -1e-10 );
SEXPECT_EQ( "-1.000000-9", -1e-9 );
SEXPECT_EQ( "-1.000000-8", -1e-8 );
SEXPECT_EQ( "-1.000000-7", -1e-7 );
SEXPECT_EQ( "-1.000000-6", -1e-6 );
SEXPECT_EQ( "-1.000000-5", -1e-5 );
SEXPECT_EQ( "-1.000000-4", -1e-4 );
SEXPECT_EQ( "-1.000000-3", -1e-3 );
SEXPECT_EQ( "-1.000000-2", -1e-2 );
SEXPECT_EQ( "-1.000000-1", -1e-1 );
SEXPECT_EQ( "-1.000000-0", -1e+0 );
SEXPECT_EQ( "-1.000000+1", -1e+1 );
SEXPECT_EQ( "-1.000000+2", -1e+2 );
SEXPECT_EQ( "-1.000000+3", -1e+3 );
SEXPECT_EQ( "-1.000000+4", -1e+4 );
SEXPECT_EQ( "-1.000000+5", -1e+5 );
SEXPECT_EQ( "-1.000000+6", -1e+6 );
SEXPECT_EQ( "-1.000000+7", -1e+7 );
SEXPECT_EQ( "-1.000000+8", -1e+8 );
SEXPECT_EQ( "-1.000000+9", -1e+9 );
SEXPECT_EQ( "-1.00000+10", -1e+10 );
SEXPECT_EQ( "-1.00000+99", -1e+99 );
SEXPECT_EQ( "-1.0000+100", -1e+100 );
SEXPECT_EQ( "-1.0000+200", -1e+200 );
// other numbers
SEXPECT_EQ( " 1.100000-0", 1.1e+0 );
SEXPECT_EQ( " 1.23456+10", 1.23456e+10 );
SEXPECT_EQ( "-1.23456+10", -1.23456e+10 );
SEXPECT_EQ( " 5.555555-0", 5.5555555 );
SEXPECT_EQ( " 5.555556-0", 5.55555555 );
}
class YieldResourceIO_F : public ::testing::Test
{
protected:
ScaleUtils::IO::DB opts;
};
TEST_F( YieldResourceIO_F, Basic )
{
// get yields resource
io.load( yr, yields_filepath, opts );
EXPECT_TRUE( opts.numError() == 0 );
// Check the yield resource for correctness.
std::vector<std::string> errors;
bool pass = yr.check( errors );
opts.appendErrorStack( &errors );
EXPECT_TRUE( pass ) << opts.dumpErrorStack();
// dump it out for inspection
if( !pass )
{
std::cout << "Error in yields: dumping yield table"
<< " output to yields.txt" << std::endl;
std::ofstream ofs( "yields.txt" );
printYields( yr, ofs );
ofs.close();
}
EXPECT_EQ( 30, yr.num_fissionables() );
EXPECT_TRUE( yr.has_fissionable( 92235 ) )
<< "must have U-235 as a parent fissionable nuclide";
EXPECT_EQ( 1151, yr.num_fps( 92235 ) )
<< "number of fission products for U-235";
const YieldParent* u235_ptr = yr.fissionable( 92235 );
EXPECT_TRUE( u235_ptr != nullptr );
const YieldParent& u235 = *u235_ptr;
EXPECT_TRUE( u235.has_fp( 54135 ) );
int i_xe135 = u235.fp_index( 54135 );
EXPECT_TRUE( i_xe135 != -1 );
// get yields and energies for Xe-135
std::vector<double> energies, yields;
u235.get_energies( &energies );
for( size_t j = 0; j < energies.size(); j++ )
{
yields.push_back( u235.data_at( j ).yield_at( i_xe135 ) );
// std::cout << energies[j] << ": "<< yields[j]<<std::endl;
}
EXPECT_FLOAT_EQ( 0.0253, energies[0] );
EXPECT_FLOAT_EQ( 2e6, energies[1] );
EXPECT_FLOAT_EQ( 1.4e7, energies[2] );
EXPECT_FLOAT_EQ( 0.00079801498, yields[0] );
EXPECT_FLOAT_EQ( 0.0011961, yields[1] );
EXPECT_FLOAT_EQ( 0.0045401901, yields[2] );
double my_energy = 1e6;
std::vector<double> yield_list;
std::vector<int> fp_list;
u235.get_interp_yields( &yield_list, my_energy );
u235.get_fp_ids( &fp_list );
EXPECT_EQ( 54135, fp_list[i_xe135] ) << "U-235 fp ids are consistent";
double by_hand = yields[0] + ( yields[1] - yields[0] ) *
( my_energy - energies[0] ) /
( energies[1] - energies[0] );
EXPECT_FLOAT_EQ( by_hand, yield_list[i_xe135] )
<< "U-235 by hand and set yield interpolation are same";
}
// Check that we fail properly when trying to load a different type of file.
TEST_F( YieldResourceIO_F, WrongTextFormat )
{
bool pass = io.load( yr, decay_filepath, opts );
EXPECT_FALSE( pass );
EXPECT_EQ( 3, opts.numError() ) << opts.writeErrorStack();
if( opts.numError() == 3 )
{
auto e = opts.errorStack();
EXPECT_EQ( "premature end of file with format='stab1'", e[0] );
EXPECT_EQ( "file is not ENDF-formatted yield data with format='ampx'",
e[1] );
EXPECT_EQ( "tried to load formats: (stab1|ampx) and failed", e[2] );
}
opts.clearErrorStack();
}
// Test loading using AMPX data.
TEST_F( YieldResourceIO_F, AmpxLoadingAndErrorCatching )
{
// load with defaults and check that we got endf
bool pass = io.load( yr, endfyields_filepath, opts );
EXPECT_TRUE( pass ) << opts;
EXPECT_EQ( "ampx", opts.get<std::string>( "loadedFileFormat", "" ) );
EXPECT_EQ( "endf", opts.get<std::string>( "ampxFormat", "" ) );
opts.clearErrorStack();
// try with gnd format
yr.clear();
opts.set<std::string>( "fileFormat", "ampx" );
opts.set<std::string>( "ampxFormat", "gnd" );
pass = io.load( yr, endfyields_filepath, opts );
EXPECT_FALSE( pass ) << opts;
opts.clearErrorStack();
}
TEST( YieldResourceIO, IntenseRoundTrip )
{
// list of possible formats
std::vector<std::string> fmts{"stab1"};
// Andrew, need to work to enable this line
// std::vector<std::string> fmts{"stab1","ampx"};
for( auto fmt1 : fmts )
{
for( auto fmt2 : fmts )
{
ScaleUtils::IO::DB opts;
// read it in whatever format it exists
SP_YieldResource yr1( loadYieldResource( yields_filepath, opts ) );
ASSERT_TRUE( yr1 != nullptr ) << opts.writeErrorStack();
// write it to format 1
opts.set<std::string>( "fileFormat", fmt1 );
bool status1 = saveYieldResource( *yr1, "out1." + fmt1, opts );
ASSERT_TRUE( status1 ) << opts.writeErrorStack();
// read it again (with automatic format finding)
// this is the first thing to compare
opts.remove<std::string>( "fileFormat" );
yr1 = SP_YieldResource( loadYieldResource( "out1." + fmt1, opts ) );
ASSERT_TRUE( yr1 != nullptr ) << opts.writeErrorStack();
// write it, now to format 2
opts.set<std::string>( "fileFormat", fmt2 );
bool status2 = saveYieldResource( *yr1, "out2." + fmt2, opts );
ASSERT_TRUE( status2 ) << opts.writeErrorStack();
// finally read it from format 2
// this is the second thing to compare
SP_YieldResource yr2( loadYieldResource( "out2." + fmt2, opts ) );
ASSERT_TRUE( yr2 != nullptr ) << opts.writeErrorStack();
// compare resources by using the JSON string dump as a middle man
std::vector<std::string> content( 2 );
content[0] = yr1->to_string();
content[1] = yr2->to_string();
std::vector<std::string> file( 2 );
file[0] = "out1." + fmt1 + ".json";
file[1] = "out2." + fmt2 + ".json";
bool print_contents =
false; // can change to true to get print out anyway
if( content[0] != content[1] )
{
print_contents = true;
EXPECT_TRUE( content[0] == content[1] )
<< "compare content of " << file[0] << " and " << file[1]
<< " for differences!";
}
if( print_contents )
{
for( auto i : {0, 1} )
{
std::ofstream ofs( file[i] );
ofs << content[i];
}
}
} // end fmt2 loop
} // end fmt1 loop
}
TEST( YieldResourceJobs, Rebaseline )
{
bool rebaseline = false;
if( rebaseline )
{
// get yields resource
ScaleUtils::IO::DB opts;
opts.set<std::string>( "fileFormat", "stab1" );
SP_YieldResource yr( loadYieldResource( yields_filepath, opts ) );
ASSERT_TRUE( yr != nullptr );
// Print the yield resource.
// When you need to rebaseline, do the following externally:
// diff yields.in.txt yields.in.gold
std::ofstream ofs( "yields.txt" );
printYields( *yr, ofs );
std::ofstream ofs2( "yields.in.txt" );
printInterpolatedYields( *yr, 92235, 1.4e6, INTERP_LINLIN, ofs2 );
std::ofstream ofs3( "yields.en.txt" );
printYieldEnergies( *yr, ofs3 );
}
}
TEST( YieldResourceJobs, ExperimentalCumulativeYields )
{
// load another
bool experimental_cumulative_yields = false;
if( experimental_cumulative_yields )
{
ScaleUtils::IO::DB opts;
opts.set<std::string>( "fileFormat", "stab1" );
"/Users/ww5/pkg/scale_tip/packages/Origen/Core/io/tests/"
"origen.revXX.e70.cyields.data",
opts ) );
std::cout << opts.toString();
std::ofstream ofs( "cyields.txt" );
printYields( *yr, ofs );
std::ofstream ofs2( "cyields.in.txt" );
printInterpolatedYields( *yr, 92235, 1.4e6, INTERP_LINLIN, ofs2 );
std::ofstream ofs3( "cyields.en.txt" );
printYieldEnergies( *yr, ofs3 );
}
}
} // namespace test
} // namespace Origen