moab
ReadMCNP5.cpp
Go to the documentation of this file.
00001 
00016 #include "ReadMCNP5.hpp"
00017 #include "moab/Interface.hpp"
00018 #include "moab/ReadUtilIface.hpp"
00019 #include "Internals.hpp" // for MB_START_ID
00020 #include "moab/Range.hpp"
00021 #include "moab/FileOptions.hpp"
00022 
00023 #include <iostream>
00024 #include <sstream>
00025 #include <fstream>
00026 #include <vector>
00027 #include <cstdlib>
00028 #include "assert.h"
00029 #include "math.h"
00030 
00031 namespace moab {
00032 
00033 // parameters
00034 const double ReadMCNP5::PI   = 3.141592653589793;
00035 const double ReadMCNP5::C2PI = 0.1591549430918954;
00036 const double ReadMCNP5::CPI  = 0.3183098861837907;
00037 
00038 ReaderIface* ReadMCNP5::factory( Interface* iface ) { 
00039   return new ReadMCNP5( iface );
00040 }
00041 
00042 // constructor
00043 ReadMCNP5::ReadMCNP5(Interface* impl)
00044   : MBI(impl), fileIDTag(0) {
00045     assert( NULL!=impl);
00046     MBI->query_interface(readMeshIface);
00047     assert( NULL!=readMeshIface );
00048 }
00049 
00050 // destructor
00051 ReadMCNP5::~ReadMCNP5() {
00052   if (readMeshIface) {
00053     MBI->release_interface(readMeshIface);
00054     readMeshIface = 0;
00055   }
00056 }
00057 
00058 
00059 ErrorCode ReadMCNP5::read_tag_values( const char* /* file_name */,
00060                                       const char* /* tag_name */,
00061                                       const FileOptions& /* opts */,
00062                                       std::vector<int>& /* tag_values_out */,
00063                                       const SubsetList* /* subset_list */ )
00064 {
00065   return MB_NOT_IMPLEMENTED;
00066 }
00067 
00068 
00069 // load the file as called by the Interface function
00070 ErrorCode ReadMCNP5::load_file(const char                    *filename, 
00071                                const EntityHandle            *input_meshset, 
00072                                const FileOptions             &options,
00073                                const ReaderIface::SubsetList *subset_list,
00074                                const Tag                     *file_id_tag) {
00075   // at this time there is no support for reading a subset of the file
00076   if (subset_list) {
00077     readMeshIface->report_error( "Reading subset of files not supported for meshtal." );
00078     return MB_UNSUPPORTED_OPERATION;
00079   }
00080   
00081   nodeId = elemId = 0;
00082   fileIDTag = file_id_tag;
00083 
00084   // Average several meshtal files if the AVERAGE_TALLY option is givin.
00085   // In this case, the integer value is the number of files to average.
00086   // If averaging, the filename passed to load_file is assumed to be the
00087   // root filename. The files are indexed as "root_filename""index".meshtal.
00088   // Indices start with 1.
00089   int n_files;
00090   bool average = false;
00091   ErrorCode result;
00092   if(MB_SUCCESS == options.get_int_option("AVERAGE_TALLY", n_files)) {
00093    
00094     // read the first file (but do not average -> can't average a single file)
00095     result = load_one_file( filename, 
00096                             input_meshset, 
00097                             options, 
00098                             average );
00099     if(MB_SUCCESS != result) return result;
00100 
00101     // get the root filename
00102     std::string root_filename(filename);
00103     int length = root_filename.length();
00104     root_filename.erase(length - sizeof(".meshtal"));
00105 
00106     // average the first file with the rest of the files
00107     average = true;
00108     for(int i=2; i<=n_files; i++) {
00109       std::stringstream index;
00110       index << i;
00111       std::string subsequent_filename = root_filename + index.str() + ".meshtal";
00112       result = load_one_file( subsequent_filename.c_str(), 
00113                               input_meshset, 
00114                               options, 
00115                               average );
00116       if(MB_SUCCESS != result) return result;
00117     }
00118  
00119   // if not averaging, read a single file
00120   } else {
00121     result = load_one_file( filename, 
00122                             input_meshset, 
00123                             options, 
00124                             average );
00125     if(MB_SUCCESS != result) return result;
00126   }
00127   
00128   return MB_SUCCESS;
00129 }
00130 
00131 // This actually reads the file. It creates the mesh elements unless
00132 // the file is being averaged with a pre-existing mesh.
00133 ErrorCode ReadMCNP5::load_one_file(const char           *fname,
00134                                      const EntityHandle *input_meshset,
00135                                      const FileOptions    &options,
00136                                      const bool           average ) {
00137 
00138   bool debug = false;
00139   if (debug) std::cout << "begin ReadMCNP5::load_one_file" << std::endl;
00140 
00141   ErrorCode result;
00142   std::fstream file;
00143   file.open( fname, std::fstream::in );
00144   char line[10000];
00145 
00146   // create tags
00147   Tag date_and_time_tag,  
00148         title_tag,           
00149         nps_tag,  
00150         tally_number_tag,    
00151         tally_comment_tag, 
00152         tally_particle_tag, 
00153         tally_coord_sys_tag, 
00154         tally_tag, 
00155         error_tag;
00156 
00157   result = create_tags( date_and_time_tag,   
00158                         title_tag,         
00159                         nps_tag,            
00160                         tally_number_tag,    
00161                         tally_comment_tag, 
00162                         tally_particle_tag, 
00163                         tally_coord_sys_tag, 
00164                         tally_tag,         
00165                         error_tag );
00166   if(MB_SUCCESS != result) return result;
00167 
00168   // ******************************************************************
00169   // This info exists only at the top of each meshtal file
00170   // ******************************************************************
00171 
00172   // define characteristics of the entire file
00173   char date_and_time[100] = "";
00174   char title[100] = "";
00175   // this file's number of particles
00176   unsigned long int nps;
00177   // sum of this file's and existing file's nps for averaging
00178   unsigned long int new_nps;
00179 
00180   // read the file header
00181   result = read_file_header( file, 
00182                              debug, 
00183                              date_and_time, 
00184                              title,
00185                              nps );
00186   if(MB_SUCCESS != result) return result;
00187 
00188   // blank line
00189   file.getline(line, 10000);
00190 
00191   // Everything stored in the file being read will be in the input_meshset.
00192   // if this is being saved in MOAB, set header tags
00193   if (!average && 0 != input_meshset) {
00194     result = set_header_tags( *input_meshset, 
00195                               date_and_time,
00196                               title,
00197                               nps,
00198                               date_and_time_tag,
00199                               title_tag,
00200                               nps_tag );
00201     if(MB_SUCCESS != result) return result;
00202   }
00203 
00204   // ******************************************************************
00205   // This info is repeated for each tally in the meshtal file.
00206   // ******************************************************************
00207 
00208   // If averaging, nps will hold the sum of particles simulated in both tallies.
00209   while( !file.eof() ) {
00210 
00211     // define characteristics of this tally
00212     unsigned int        tally_number;
00213     char                tally_comment[100] = "";
00214     particle            tally_particle;
00215     coordinate_system   tally_coord_sys;
00216     std::vector<double> planes[3];
00217     unsigned int        n_chopped_x0_planes; 
00218     unsigned int        n_chopped_x2_planes;
00219     
00220     // read tally header
00221     result = read_tally_header( file, 
00222                                 debug, 
00223                                 tally_number, 
00224                                 tally_comment,
00225                                 tally_particle );
00226     if(MB_SUCCESS != result) return result;
00227     
00228     // blank line
00229     file.getline(line, 10000);
00230 
00231     // read mesh planes
00232     result = read_mesh_planes( file, 
00233                                debug, 
00234                                planes, 
00235                                tally_coord_sys );
00236     if(MB_SUCCESS != result) return result;
00237 
00238     // get energy boundaries
00239     file.getline(line, 10000);
00240     std::string a = line;
00241     if (debug) std::cout << "Energy bin boundaries:=| " << a << std::endl;
00242 
00243     // blank
00244     file.getline(line, 10000);
00245 
00246     // column headers
00247     file.getline(line, 10000);
00248 
00249     // If using cylidrical mesh, it may be necessary to chop off the last theta element.
00250     // We chop off the last theta plane because the elements will be wrong and skew up
00251     // the tree building code. This is
00252     // because the hex elements are a linear approximation to the cylindrical elements.
00253     // Chopping off the last plane is problem-dependent, and due to MCNP5's mandate 
00254     // that the cylidrical mesh must span 360 degrees.
00255     if (CYLINDRICAL==tally_coord_sys &&
00256         MB_SUCCESS ==options.get_null_option("REMOVE_LAST_AZIMUTHAL_PLANE")) {
00257       planes[2].pop_back();
00258       n_chopped_x2_planes = 1;
00259       if (debug) std::cout << "remove last cylindrical plane option found" << std::endl;
00260     } else {
00261       n_chopped_x2_planes = 0;
00262     }
00263     
00264     // If using cylindrical mesh, it may be necessary to chop off the first radial element.
00265     // These elements extend from the axis and often do not cover areas of interest. For 
00266     // example, if the mesh was meant to cover r=390-400, the first layer will go from
00267     // 0-390 and serve as incorrect source elements for interpolation.  
00268     if (CYLINDRICAL==tally_coord_sys &&   
00269         MB_SUCCESS ==options.get_null_option("REMOVE_FIRST_RADIAL_PLANE")) {   
00270       std::vector<double>::iterator front=planes[0].begin();
00271       planes[0].erase( front );
00272       n_chopped_x0_planes = 1;   
00273       if (debug) std::cout << "remove first radial plane option found" << std::endl;  
00274     } else {          
00275       n_chopped_x0_planes = 0;  
00276     }  
00277 
00278     // Read the values and errors of each element from the file.
00279     // Do not read values that are chopped off.
00280     unsigned int n_elements = (planes[0].size()-1)*(planes[1].size()-1)*(planes[2].size()-1);
00281     double *values = new double [n_elements];
00282     double *errors = new double [n_elements];
00283     result = read_element_values_and_errors( file, 
00284                                              debug, 
00285                                              planes,
00286                                              n_chopped_x0_planes,
00287                                              n_chopped_x2_planes,
00288                                              tally_particle,
00289                                              values, 
00290                                              errors );
00291     if(MB_SUCCESS != result) return result;
00292     
00293     // blank line
00294     file.getline(line, 10000);
00295    
00296     // ****************************************************************
00297     // This tally has been read. If it is not being averaged, build tags,
00298     // vertices and elements. If it is being averaged, average the data 
00299     // with a tally already existing in the MOAB instance.
00300     // ****************************************************************
00301     if (!average) {
00302       EntityHandle tally_meshset;
00303       result = MBI->create_meshset(MESHSET_SET, tally_meshset);
00304       if(MB_SUCCESS != result) return result;
00305       
00306       // set tags on the tally
00307       result = set_tally_tags( tally_meshset,
00308                                tally_number,
00309                                tally_comment,
00310                                tally_particle,
00311                                tally_coord_sys,
00312                                tally_number_tag, 
00313                                tally_comment_tag,
00314                                tally_particle_tag,
00315                                tally_coord_sys_tag );
00316       if(MB_SUCCESS != result) return result;
00317 
00318       // The only info needed to build elements is the mesh plane boundaries.
00319       // Build vertices...
00320       EntityHandle start_vert = 0;
00321       result = create_vertices( planes, 
00322                                 debug,
00323                                 start_vert, 
00324                                 tally_coord_sys,
00325                                 tally_meshset );
00326       if(MB_SUCCESS != result) return result; 
00327       
00328       // Build elements and tag them with tally values and errors, then add
00329       // them to the tally_meshset.
00330       result = create_elements( debug, 
00331                                 planes,
00332                                 n_chopped_x0_planes, 
00333                                 n_chopped_x2_planes,
00334                                 start_vert, 
00335                                 values, 
00336                                 errors, 
00337                                 tally_tag, 
00338                                 error_tag, 
00339                                 tally_meshset,
00340                                 tally_coord_sys );
00341       if(MB_SUCCESS != result) return result; 
00342       
00343       // add this tally's meshset to the output meshset
00344       if (debug) std::cout << "not averaging tally" << std::endl;
00345 
00346     // average the tally values, then delete stuff that was created
00347     } else {
00348       if (debug) std::cout << "averaging tally" << std::endl;
00349       result = average_with_existing_tally( debug, 
00350                                             new_nps,
00351                                             nps,
00352                                             tally_number,
00353                                             tally_number_tag,          
00354                                             nps_tag,
00355                                             tally_tag,
00356                                             error_tag,
00357                                             values,
00358                                             errors,
00359                                             n_elements );
00360       if(MB_SUCCESS != result) return result;
00361     }
00362 
00363     // clean up
00364     delete[] values;
00365     delete[] errors;
00366   }
00367 
00368   // If we are averaging, delete the remainder of this file's information.
00369   // Add the new nps to the existing file's nps if we are averaging.
00370   // This is calculated during every tally averaging but only used after the last one.
00371   if (average) {
00372     Range matching_nps_sets;
00373     result = MBI->get_entities_by_type_and_tag( 0, MBENTITYSET, &nps_tag, 
00374                                                 0, 1, matching_nps_sets );
00375     if(MB_SUCCESS != result) return result;
00376     if (debug) std::cout << "number of matching nps meshsets=" 
00377                          << matching_nps_sets.size() << std::endl;
00378     assert(1 == matching_nps_sets.size());
00379     result = MBI->tag_set_data( nps_tag, matching_nps_sets, &new_nps );
00380     if(MB_SUCCESS != result) return result;
00381 
00382   // If this file is not being averaged, return the output meshset.
00383   } 
00384   file.close();
00385   return MB_SUCCESS;
00386 }
00387 
00388 // create tags needed for this reader
00389 ErrorCode ReadMCNP5::create_tags( Tag &date_and_time_tag,
00390                                     Tag &title_tag,
00391                                     Tag &nps_tag,
00392                                     Tag &tally_number_tag,
00393                                     Tag &tally_comment_tag,
00394                                     Tag &tally_particle_tag,
00395                                     Tag &tally_coord_sys_tag,
00396                                     Tag &tally_tag,
00397                                     Tag &error_tag ) {
00398   ErrorCode result;
00399   result = MBI->tag_get_handle("DATE_AND_TIME_TAG", 100, MB_TYPE_OPAQUE, 
00400                            date_and_time_tag, MB_TAG_SPARSE|MB_TAG_CREAT);
00401   if(MB_SUCCESS!=result) return result;
00402   result = MBI->tag_get_handle("TITLE_TAG", 100, MB_TYPE_OPAQUE, title_tag,
00403                            MB_TAG_SPARSE|MB_TAG_CREAT);
00404   if(MB_SUCCESS!=result) return result;
00405   result = MBI->tag_get_handle("NPS_TAG", sizeof(unsigned long int), MB_TYPE_OPAQUE,
00406                            nps_tag, MB_TAG_SPARSE|MB_TAG_CREAT);
00407   if(MB_SUCCESS!=result) return result;
00408   result = MBI->tag_get_handle("TALLY_NUMBER_TAG", 1, MB_TYPE_INTEGER, 
00409                            tally_number_tag, MB_TAG_SPARSE|MB_TAG_CREAT);
00410   if(MB_SUCCESS!=result) return result;
00411   result = MBI->tag_get_handle("TALLY_COMMENT_TAG", 100, MB_TYPE_OPAQUE, 
00412                            tally_comment_tag, MB_TAG_SPARSE|MB_TAG_CREAT);
00413   if(MB_SUCCESS!=result) return result;
00414   result = MBI->tag_get_handle("TALLY_PARTICLE_TAG", sizeof(particle), MB_TYPE_OPAQUE,
00415                            tally_particle_tag, MB_TAG_SPARSE|MB_TAG_CREAT);
00416   if(MB_SUCCESS!=result) return result;
00417   result = MBI->tag_get_handle("TALLY_COORD_SYS_TAG", sizeof(coordinate_system), MB_TYPE_OPAQUE,
00418                            tally_coord_sys_tag, MB_TAG_SPARSE|MB_TAG_CREAT);
00419   if(MB_SUCCESS!=result) return result;
00420   result = MBI->tag_get_handle("TALLY_TAG", 1, MB_TYPE_DOUBLE, tally_tag,
00421                            MB_TAG_DENSE|MB_TAG_CREAT);
00422   if(MB_SUCCESS!=result) return result;
00423   result = MBI->tag_get_handle("ERROR_TAG", 1, MB_TYPE_DOUBLE, error_tag,
00424                            MB_TAG_DENSE|MB_TAG_CREAT);
00425   if(MB_SUCCESS!=result) return result;
00426   return MB_SUCCESS;
00427 }
00428 
00429 ErrorCode ReadMCNP5::read_file_header( std::fstream      &file,
00430                                          bool              debug,
00431                                          char              date_and_time[100],  
00432                                          char              title[100], 
00433                                          unsigned long int &nps ) {
00434 
00435   // get simulation date and time
00436   // mcnp   version 5     ld=11242008  probid =  03/23/09 13:38:56
00437   char line[100];
00438   file.getline(line, 100);
00439   date_and_time = line;
00440   if (debug) std::cout << "date_and_time=| " << date_and_time << std::endl;
00441 
00442   // get simulation title
00443   // iter Module 4                                                                   
00444   file.getline(line, 100);
00445   title = line;
00446   if (debug) std::cout << "title=| " << title  << std::endl;
00447 
00448   // get number of histories
00449   // Number of histories used for normalizing tallies =      50000000.00
00450   file.getline(line, 100);
00451   std::string a = line;
00452   std::string::size_type b = a.find("Number of histories used for normalizing tallies =");
00453   if (std::string::npos!=b) {
00454     std::istringstream nps_ss( 
00455       a.substr(b+sizeof("Number of histories used for normalizing tallies ="),100) );
00456     nps_ss >> nps;
00457     if (debug) std::cout << "nps=| " << nps << std::endl;
00458   } else return MB_FAILURE;
00459 
00460   return MB_SUCCESS;
00461 }
00462 
00463 ErrorCode ReadMCNP5::set_header_tags( EntityHandle    output_meshset, 
00464                                         char              date_and_time[100],
00465                                         char              title[100],
00466                                         unsigned long int nps,
00467                                         Tag             data_and_time_tag,
00468                                         Tag             title_tag,
00469                                         Tag             nps_tag ) {
00470   ErrorCode result;
00471   result = MBI->tag_set_data( data_and_time_tag, &output_meshset, 1, &date_and_time);
00472   if(MB_SUCCESS != result) return result;
00473   result = MBI->tag_set_data( title_tag, &output_meshset, 1, &title);
00474   if(MB_SUCCESS != result) return result;
00475   result = MBI->tag_set_data( nps_tag, &output_meshset, 1, &nps);
00476   if(MB_SUCCESS != result) return result;
00477   return MB_SUCCESS;
00478 }
00479 
00480 ErrorCode ReadMCNP5::read_tally_header( std::fstream   &file,
00481                                           bool           debug,
00482                                           unsigned int   &tally_number,
00483                                           char           tally_comment[100],
00484                                           particle       &tally_particle ) {
00485 
00486   // get tally number
00487   // Mesh Tally Number 104
00488   ErrorCode result;
00489   char line[100];
00490   file.getline(line, 100);
00491   std::string a = line;
00492   std::string::size_type b = a.find("Mesh Tally Number");
00493   if (std::string::npos != b) {
00494     std::istringstream tally_number_ss( a.substr(b+sizeof("Mesh Tally Number"),100) );
00495     tally_number_ss >> tally_number;
00496     if (debug) std::cout << "tally_number=| " << tally_number << std::endl;
00497   } else {
00498     std::cout << "tally number not found" << std::endl;
00499     return MB_FAILURE;
00500   }
00501  
00502   // next get the tally comment (optional) and particle type
00503   // 3mm neutron heating in Be (W/cc)     
00504   // This is a neutron mesh tally.
00505   // std::string tally_comment;
00506   
00507   // get tally particle
00508   file.getline(line, 100);
00509   a = line;
00510   result = get_tally_particle(a, debug, tally_particle);
00511   if (MB_FAILURE == result) {
00512     // If this line does not specify the particle type, then it is a tally comment.
00513     // Get the comment, then get the particle type from the next line.
00514     tally_comment = line;
00515     file.getline(line, 100);
00516     a = line;
00517     result = get_tally_particle(a, debug, tally_particle);
00518     if(MB_SUCCESS != result) return result;
00519   }
00520   if (debug) std::cout << "tally_comment=| " << tally_comment << std::endl;
00521   return MB_SUCCESS;
00522 }
00523 
00524 ErrorCode ReadMCNP5::get_tally_particle( std::string    a,
00525                                            bool           debug,
00526                                            particle       &tally_particle ) {
00527   
00528   if        (std::string::npos != a.find("This is a neutron mesh tally.")) {
00529     tally_particle = NEUTRON;
00530   } else if (std::string::npos != a.find("This is a photon mesh tally.")) {
00531     tally_particle = PHOTON;
00532   } else if (std::string::npos != a.find("This is an electron mesh tally.")) {
00533     tally_particle = ELECTRON;
00534   } else return MB_FAILURE;
00535 
00536   if (debug) std::cout << "tally_particle=| " << tally_particle << std::endl;
00537   return MB_SUCCESS;
00538 }
00539 
00540 ErrorCode ReadMCNP5::read_mesh_planes( std::fstream        &file, 
00541                                          bool                debug, 
00542                                          std::vector<double> planes[3], 
00543                                          coordinate_system   &coord_sys ) {
00544 
00545   // Tally bin boundaries:
00546   ErrorCode result;
00547   char line[10000];
00548   file.getline(line, 10000);
00549   std::string a = line;
00550   if (std::string::npos == a.find("Tally bin boundaries:"))
00551     return MB_FAILURE;
00552  
00553   // decide what coordinate system the tally is using
00554   // first check for Cylindrical coordinates:
00555   file.getline(line, 10000);
00556   a = line;
00557   std::string::size_type b = a.find("Cylinder origin at");
00558   if (std::string::npos != b) {
00559     coord_sys = CYLINDRICAL;
00560     if (debug) std::cout << "origin, axis, direction=| " << a << std::endl;
00561     std::istringstream ss(a.substr(b+sizeof("Cylinder origin at"),10000));
00562     // The meshtal file does not contain sufficient information to transform
00563     // the particle. Although origin, axs, and vec is needed only origin and
00564     // axs appear in the meshtal file. Why was vec omitted?.
00565     // get origin (not used)
00566     // Cylinder origin at   0.00E+00  0.00E+00  0.00E+00, 
00567     // axis in  0.000E+00 0.000E+00 1.000E+00 direction
00568     double origin[3];
00569     if (debug) std::cout << "origin=| ";
00570     for (int i=0; i<3; i++) {
00571       ss >> origin[i];
00572       if (debug) std::cout << origin[i] << " ";
00573     }
00574     if (debug) std::cout << std::endl;
00575     int length_of_string = 10;
00576     ss.ignore( length_of_string, ' ');
00577     ss.ignore( length_of_string, ' ');
00578     ss.ignore( length_of_string, ' ');
00579     // get axis (not used)
00580     double axis[3];
00581     if (debug) std::cout << "axis=| ";
00582     for (int i=0; i<3; i++) {
00583       ss >> axis[i];
00584       if (debug) std::cout << axis[i] << " ";
00585     }
00586     if (debug) std::cout << std::endl;
00587     file.getline(line, 10000);
00588     a = line;
00589 
00590     // get r planes
00591     if (debug) std::cout << "R direction:=| ";
00592     b = a.find("R direction:");
00593     if (std::string::npos != b) {
00594       std::istringstream ss2(a.substr(b+sizeof("R direction"),10000));
00595       result = get_mesh_plane( ss2, debug, planes[0] );
00596       if(MB_SUCCESS != result) return result;
00597     } else return MB_FAILURE;
00598 
00599     // get z planes
00600     file.getline(line, 10000);
00601     a = line;
00602     if (debug) std::cout << "Z direction:=| ";
00603     b = a.find("Z direction:");
00604     if (std::string::npos != b) {
00605       std::istringstream ss2(a.substr(b+sizeof("Z direction"),10000));
00606       result = get_mesh_plane( ss2, debug, planes[1] );
00607       if(MB_SUCCESS != result) return result;
00608     } else return MB_FAILURE;
00609 
00610     // get theta planes
00611     file.getline(line, 10000);
00612     a = line;
00613     if (debug) std::cout << "Theta direction:=| ";
00614     b = a.find("Theta direction (revolutions):");
00615     if (std::string::npos != b) {
00616       std::istringstream ss2(a.substr(b+sizeof("Theta direction (revolutions):"),10000));
00617       result = get_mesh_plane( ss2, debug, planes[2] );
00618       if(MB_SUCCESS != result) return result;
00619     } else return MB_FAILURE;
00620     
00621   // Cartesian coordinate system:
00622   }  else if (std::string::npos != a.find("X direction:") ) {
00623     coord_sys = CARTESIAN;
00624     // get x planes
00625     if (debug) std::cout << "X direction:=| ";
00626     b = a.find("X direction:");
00627     if (std::string::npos != b) {
00628       std::istringstream ss2(a.substr(b+sizeof("X direction"),10000));
00629       result = get_mesh_plane( ss2, debug, planes[0] );
00630       if(MB_SUCCESS != result) return result;
00631     } else return MB_FAILURE;
00632 
00633     // get y planes
00634     file.getline(line, 10000);
00635     a = line;
00636     if (debug) std::cout << "Y direction:=| ";
00637     b = a.find("Y direction:");
00638     if (std::string::npos != b) {
00639       std::istringstream ss2(a.substr(b+sizeof("Y direction"),10000));
00640       result = get_mesh_plane( ss2, debug, planes[1] );
00641       if(MB_SUCCESS != result) return result;
00642     } else return MB_FAILURE;
00643 
00644     // get z planes
00645     file.getline(line, 10000);
00646     a = line;
00647     if (debug) std::cout << "Z direction:=| ";
00648     b = a.find("Z direction:");
00649     if (std::string::npos != b) {
00650       std::istringstream ss2(a.substr(b+sizeof("Z direction"),10000));
00651       result = get_mesh_plane( ss2, debug, planes[2] );
00652       if(MB_SUCCESS != result) return result;
00653     } else return MB_FAILURE;
00654 
00655   // Spherical coordinate system not yet implemented:
00656   } else return MB_FAILURE;
00657     
00658   return MB_SUCCESS;
00659 }
00660 
00661 // Given a stringstream, return a vector of values in the string.
00662 ErrorCode ReadMCNP5::get_mesh_plane( std::istringstream  &ss,
00663                                        bool                debug, 
00664                                        std::vector<double> &plane) {
00665   double value;
00666   plane.clear();
00667   while (!ss.eof()) {
00668     ss >> value;
00669     plane.push_back( value );
00670     if (debug) std::cout << value << " ";
00671   }
00672   if (debug) std::cout << std::endl;
00673   return MB_SUCCESS;
00674 }
00675 
00676 ErrorCode ReadMCNP5::read_element_values_and_errors( 
00677                                             std::fstream        &file,
00678                                             bool                /*debug*/,
00679                                             std::vector<double> planes[3],
00680                                             unsigned int        n_chopped_x0_planes,
00681                                             unsigned int        n_chopped_x2_planes,
00682                             particle            tally_particle,
00683                                             double              values[],
00684                                             double              errors[] ) {
00685 
00686   unsigned int index = 0;
00687   // need to read every line in the file, even if we chop off some elements 
00688   for (unsigned int i=0; i<planes[0].size()-1+n_chopped_x0_planes; i++) {
00689     for (unsigned int j=0; j<planes[1].size()-1; j++) {
00690       for (unsigned int k=0; k<planes[2].size()-1+n_chopped_x2_planes; k++) {
00691         char line[100];
00692         file.getline(line, 100);
00693         // if this element has been chopped off, skip it
00694         if (i<n_chopped_x0_planes) continue;
00695         if (k>=planes[2].size()-1 && k<planes[2].size()-1+n_chopped_x2_planes) continue;
00696         std::string a=line;
00697         std::stringstream ss(a);
00698         double centroid[3];
00699         double energy;
00700         // for some reason, photon tallies print the energy in the first column
00701         if (PHOTON==tally_particle) ss >> energy;
00702         // the centroid is not used in this reader
00703         ss >> centroid[0];
00704         ss >> centroid[1];
00705         ss >> centroid[2];
00706         // only the tally values and errors are used
00707         ss >> values[index];
00708         ss >> errors[index];
00709 
00710         // make sure that input data is good
00711     if( !finite(errors[index]) ) {
00712       std::cerr << "found nan error while reading file" << std::endl;
00713           errors[index] = 1.0;
00714         }
00715     if( !finite(values[index]) ) {
00716       std::cerr << "found nan value while reading file" << std::endl;
00717           values[index] = 0.0;
00718         }
00719 
00720         index++;
00721       }
00722     }
00723   }
00724   return MB_SUCCESS;
00725 }
00726 
00727 ErrorCode ReadMCNP5::set_tally_tags( EntityHandle    tally_meshset,
00728                                        unsigned int      tally_number,
00729                                        char              tally_comment[100],
00730                                        particle          tally_particle,
00731                                        coordinate_system tally_coord_sys,
00732                                        Tag             tally_number_tag, 
00733                                        Tag             tally_comment_tag,
00734                                        Tag             tally_particle_tag,
00735                                        Tag             tally_coord_sys_tag ) {
00736   ErrorCode result;
00737   result = MBI->tag_set_data( tally_number_tag,    &tally_meshset, 1, &tally_number);
00738   if(MB_SUCCESS != result) return result;
00739   result = MBI->tag_set_data( tally_comment_tag,   &tally_meshset, 1, &tally_comment);
00740   if(MB_SUCCESS != result) return result;
00741   result = MBI->tag_set_data( tally_particle_tag,  &tally_meshset, 1, &tally_particle);
00742   if(MB_SUCCESS != result) return result;
00743   result = MBI->tag_set_data( tally_coord_sys_tag, &tally_meshset, 1, &tally_coord_sys);
00744   if(MB_SUCCESS != result) return result;
00745   return MB_SUCCESS;
00746 }
00747 
00748 ErrorCode ReadMCNP5::create_vertices( std::vector<double> planes[3],
00749                                         bool                debug,
00750                                         EntityHandle      &start_vert,
00751                                         coordinate_system   coord_sys,
00752                                         EntityHandle      tally_meshset ) {
00753                                          
00754   // The only info needed to build elements is the mesh plane boundaries.
00755   ErrorCode result;
00756   int n_verts = planes[0].size() * planes[1].size() * planes[2].size();
00757   if (debug) std::cout << "n_verts=" << n_verts << std::endl;
00758   std::vector<double*> coord_arrays(3);
00759   result = readMeshIface->get_node_coords( 3, n_verts, MB_START_ID, 
00760                                            start_vert, coord_arrays );
00761   if(MB_SUCCESS != result) return result;
00762   assert(0 != start_vert); // check for NULL
00763 
00764   for (unsigned int k=0; k < planes[2].size(); k++) {
00765     for (unsigned int j=0; j < planes[1].size(); j++) {
00766       for (unsigned int i=0; i < planes[0].size(); i++) {
00767 
00768         unsigned int idx = (k*planes[0].size()*planes[1].size() + j*planes[0].size() + i);
00769         double in[3], out[3];
00770 
00771         in[0] = planes[0][i];
00772         in[1] = planes[1][j];
00773         in[2] = planes[2][k];
00774         result = transform_point_to_cartesian( in, out, coord_sys );
00775         if(MB_SUCCESS != result) return result;
00776 
00777         coord_arrays[0][idx] = out[0];
00778         coord_arrays[1][idx] = out[1];
00779         coord_arrays[2][idx] = out[2];
00780       }
00781     }
00782   }
00783   Range vert_range(start_vert, start_vert+n_verts-1);
00784   result = MBI->add_entities( tally_meshset, vert_range );
00785   if(MB_SUCCESS != result) return result;
00786   
00787   if (fileIDTag) {
00788     result = readMeshIface->assign_ids( *fileIDTag, vert_range, nodeId );
00789     if (MB_SUCCESS != result)
00790       return result;
00791     nodeId += vert_range.size();
00792   }
00793   
00794   return MB_SUCCESS;
00795 }
00796 
00797 ErrorCode ReadMCNP5::create_elements( bool                debug, 
00798                                         std::vector<double> planes[3],
00799                                         unsigned int        /*n_chopped_x0_planes*/,
00800                                         unsigned int        /*n_chopped_x2_planes*/,
00801                                         EntityHandle      start_vert,
00802                                         double              *values,
00803                                         double              *errors,
00804                                         Tag               tally_tag,
00805                                         Tag               error_tag,
00806                                         EntityHandle      tally_meshset,
00807                                         coordinate_system   tally_coord_sys ) {
00808   ErrorCode result;
00809   unsigned int index;
00810   EntityHandle start_element = 0;
00811   unsigned int n_elements = (planes[0].size()-1) * (planes[1].size()-1) 
00812                                                  * (planes[2].size()-1);
00813   EntityHandle *connect;
00814   result = readMeshIface->get_element_connect( n_elements, 8, MBHEX, MB_START_ID, 
00815                                              start_element, connect );
00816   if(MB_SUCCESS != result) return result;
00817   assert(0 != start_element); // check for NULL
00818 
00819   unsigned int counter = 0;
00820   for (unsigned int i=0; i<planes[0].size()-1; i++) {
00821     for (unsigned int j=0; j<planes[1].size()-1; j++) {
00822       for (unsigned int k=0; k<planes[2].size()-1; k++) {
00823           
00824         index = start_vert + i + j*planes[0].size() + k*planes[0].size()*planes[1].size();
00825         // for rectangular mesh, the file prints: x y z
00826         // z changes the fastest and x changes the slowest.
00827         // This means that the connectivitiy ordering is not consistent between
00828         // rectangular and cylindrical mesh.
00829         if(CARTESIAN == tally_coord_sys) {
00830           connect[0] = index;
00831           connect[1] = index + 1;  
00832           connect[2] = index + 1 + planes[0].size();     
00833           connect[3] = index +     planes[0].size();
00834           connect[4] = index +                        planes[0].size()*planes[1].size();
00835           connect[5] = index + 1 +                    planes[0].size()*planes[1].size();    
00836           connect[6] = index + 1 + planes[0].size() + planes[0].size()*planes[1].size();
00837           connect[7] = index +     planes[0].size() + planes[0].size()*planes[1].size();        
00838         // for cylindrical mesh, the file prints: r z theta
00839         // Theta changes the fastest and r changes the slowest.
00840         } else if(CYLINDRICAL == tally_coord_sys) {
00841           connect[0] = index;
00842           connect[1] = index + 1;  
00843           connect[2] = index + 1 +                    planes[0].size()*planes[1].size();     
00844           connect[3] = index +                        planes[0].size()*planes[1].size();
00845           connect[4] = index +     planes[0].size();
00846           connect[5] = index + 1 + planes[0].size();    
00847           connect[6] = index + 1 + planes[0].size() + planes[0].size()*planes[1].size();
00848           connect[7] = index +     planes[0].size() + planes[0].size()*planes[1].size();
00849     } else return MB_NOT_IMPLEMENTED;
00850 
00851     connect += 8;
00852     counter++;
00853       }
00854     }
00855   }
00856   if (counter != n_elements) std::cout << "counter=" << counter << " n_elements=" 
00857                                        << n_elements << std::endl;
00858 
00859   Range element_range(start_element, start_element+n_elements-1);
00860   result = MBI->tag_set_data(tally_tag, element_range, values);
00861   if(MB_SUCCESS != result) return result;
00862   result = MBI->tag_set_data(error_tag, element_range, errors);
00863   if(MB_SUCCESS != result) return result;
00864   
00865   // add the elements to the tally set
00866   result = MBI->add_entities( tally_meshset, element_range );
00867   if(MB_SUCCESS != result) return result;
00868   if (debug) std::cout << "Read " << n_elements << " elements from tally." << std::endl;
00869   
00870   if (fileIDTag) {
00871     result = readMeshIface->assign_ids( *fileIDTag, element_range, elemId );
00872     if (MB_SUCCESS != result)
00873       return result;
00874     elemId += element_range.size();
00875   }
00876 
00877   return MB_SUCCESS;
00878 }
00879 
00880 // Average a tally that was recently read in with one that alread exists in
00881 // the interface. Only the existing values will be updated.
00882 ErrorCode ReadMCNP5::average_with_existing_tally( bool         debug,
00883                                                     unsigned long int &new_nps,
00884                                                     unsigned long int nps1,
00885                                                     unsigned int tally_number,
00886                                                     Tag        tally_number_tag,
00887                                                     Tag        nps_tag,
00888                                                     Tag        tally_tag,
00889                                                     Tag        error_tag,
00890                                                     double       *values1,
00891                                                     double       *errors1,
00892                                                     unsigned int n_elements ) {
00893     
00894   // get the tally number
00895   ErrorCode result;
00896 
00897   // match the tally number with one from the existing meshtal file
00898   Range matching_tally_number_sets;
00899   const void* const tally_number_val[] = {&tally_number};
00900   result = MBI->get_entities_by_type_and_tag( 0, MBENTITYSET, &tally_number_tag, 
00901                                               tally_number_val, 1, 
00902                                               matching_tally_number_sets );
00903   if(MB_SUCCESS != result) return result;
00904   if (debug) std::cout << "number of matching meshsets=" 
00905                        << matching_tally_number_sets.size() << std::endl;
00906   assert(1 == matching_tally_number_sets.size());
00907 
00908   // identify which of the meshsets is existing
00909   EntityHandle existing_meshset;
00910   existing_meshset = matching_tally_number_sets.front();
00911 
00912   // get the existing elements from the set
00913   Range existing_elements;
00914   result = MBI->get_entities_by_type( existing_meshset, MBHEX, existing_elements );
00915   if(MB_SUCCESS != result) return result;
00916   assert(existing_elements.size() == n_elements);
00917 
00918   // get the nps of the existing and new tally
00919   unsigned long int nps0;
00920   Range sets_with_this_tag;
00921   result = MBI->get_entities_by_type_and_tag( 0, MBENTITYSET, &nps_tag, 0, 1, 
00922                                               sets_with_this_tag);
00923   if(MB_SUCCESS != result) return result;
00924   if (debug) std::cout << "number of nps sets=" << sets_with_this_tag.size() << std::endl;
00925   assert(1 == sets_with_this_tag.size());
00926   result = MBI->tag_get_data( nps_tag, &sets_with_this_tag.front(), 1, &nps0);
00927   if(MB_SUCCESS != result) return result;
00928   if (debug) std::cout << "nps0=" << nps0 << " nps1=" << nps1 << std::endl;
00929   new_nps = nps0 + nps1;
00930 
00931   // get tally values from the existing elements
00932   double *values0 = new double [existing_elements.size()];
00933   double *errors0 = new double [existing_elements.size()];
00934   result = MBI->tag_get_data( tally_tag, existing_elements, values0 );
00935   if(MB_SUCCESS != result) return result;
00936   result = MBI->tag_get_data( error_tag, existing_elements, errors0 );
00937   if(MB_SUCCESS != result) return result;
00938 
00939   // average the values and errors
00940   result = average_tally_values( nps0, nps1, values0, values1, 
00941                                  errors0, errors1, n_elements );
00942   if(MB_SUCCESS != result) return result;
00943   
00944   // set the averaged information back onto the existing elements
00945   result = MBI->tag_set_data( tally_tag, existing_elements, values0 );
00946   if(MB_SUCCESS != result) return result;
00947   result = MBI->tag_set_data( error_tag, existing_elements, errors0 );
00948   if(MB_SUCCESS != result) return result;
00949   
00950   // cleanup
00951   delete[] values0;
00952   delete[] errors0;
00953 
00954   return MB_SUCCESS;
00955 }
00956 
00957 ErrorCode ReadMCNP5::transform_point_to_cartesian(double *in, double *out, 
00958                                                     coordinate_system coord_sys ) {
00959   // Transform coordinate system
00960   switch(coord_sys) {
00961     case CARTESIAN :
00962       out[0] = in[0]; // x
00963       out[1] = in[1]; // y
00964       out[2] = in[2]; // z
00965       break;
00966     // theta is in rotations
00967     case CYLINDRICAL :
00968       out[0] = in[0]*cos( 2*PI*in[2] ); // x
00969       out[1] = in[0]*sin( 2*PI*in[2] ); // y
00970       out[2] = in[1];                  // z
00971       break;
00972     case SPHERICAL :
00973       return MB_NOT_IMPLEMENTED;
00974     default :
00975       return MB_NOT_IMPLEMENTED;
00976   }
00977   
00978   return MB_SUCCESS;
00979 }
00980 
00981 // Average two tally values and their error. Return average values in the
00982 // place of first tally values.
00983 ErrorCode ReadMCNP5::average_tally_values(const unsigned long int nps0, 
00984                                             const unsigned long int nps1,
00985                                             double                  *values0,
00986                                             const double            *values1,
00987                                             double                  *errors0,
00988                                             const double            *errors1,
00989                                             const unsigned long int n_values) {
00990   
00991   for(unsigned long int i=0; i<n_values; i++) {
00992     //std::cout << " values0=" << values0[i] << " values1=" << values1[i] 
00993     //          << " errors0=" << errors0[i] << " errors1=" << errors1[i] 
00994     //          << " nps0=" << nps0 << " nps1=" << nps1 << std::endl;
00995     errors0[i] = sqrt( pow(values0[i]*errors0[i]*nps0,2) + 
00996                        pow(values1[i]*errors1[i]*nps1,2) ) / 
00997                  (values0[i]*nps0 + values1[i]*nps1);
00998 
00999     // It is possible to introduce nans if the values are zero.
01000     if(!finite(errors0[i])) errors0[i] = 1.0;
01001 
01002     values0[i] = ( values0[i]*nps0 + values1[i]*nps1 ) / (nps0 + nps1);
01003 
01004     //std::cout << " values0=" << values0[i] << " errors0=" << errors0[i] << std::endl;
01005   }
01006   // REMEMBER TO UPDATE NPS0 = NPS0 + NPS1 after this
01007   return MB_SUCCESS;
01008 }
01009 
01010 } // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines