moab
|
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