legacy_xdr_io.C
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 00020 // C++ includes 00021 #include <iostream> 00022 #include <iomanip> 00023 00024 #include <vector> 00025 #include <string> 00026 00027 // Local includes 00028 #include "libmesh/legacy_xdr_io.h" 00029 #include "libmesh/mesh_base.h" 00030 #include "libmesh/mesh_data.h" 00031 #include "libmesh/mesh_tools.h" // MeshTools::n_levels(mesh) 00032 #include "libmesh/parallel.h" // - which makes write parallel-only 00033 #include "libmesh/cell_hex27.h" // Needed for MGF-style Hex27 meshes 00034 #include "libmesh/boundary_info.h" 00035 #include "libmesh/libmesh_logging.h" 00036 #include "libmesh/xdr_mgf.h" 00037 #include "libmesh/xdr_mesh.h" 00038 #include "libmesh/xdr_mhead.h" 00039 #include "libmesh/xdr_soln.h" 00040 #include "libmesh/xdr_shead.h" 00041 00042 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 00043 #include "libmesh/utility.h" 00044 #endif 00045 00046 00047 namespace libMesh 00048 { 00049 00050 00051 00052 00053 00054 00055 // ------------------------------------------------------------ 00056 // LegacyXdrIO members 00057 LegacyXdrIO::LegacyXdrIO (MeshBase& mesh, const bool binary_in) : 00058 MeshInput<MeshBase> (mesh), 00059 MeshOutput<MeshBase>(mesh), 00060 _binary (binary_in) 00061 { 00062 } 00063 00064 00065 00066 00067 LegacyXdrIO::LegacyXdrIO (const MeshBase& mesh, const bool binary_in) : 00068 MeshOutput<MeshBase>(mesh), 00069 _binary (binary_in) 00070 { 00071 } 00072 00073 00074 00075 00076 LegacyXdrIO::~LegacyXdrIO () 00077 { 00078 } 00079 00080 00081 00082 00083 bool & LegacyXdrIO::binary () 00084 { 00085 return _binary; 00086 } 00087 00088 00089 00090 00091 bool LegacyXdrIO::binary () const 00092 { 00093 return _binary; 00094 } 00095 00096 00097 00098 void LegacyXdrIO::read (const std::string& name) 00099 { 00100 // This is a serial-only process for now; 00101 // the Mesh should be read on processor 0 and 00102 // broadcast later 00103 if (libMesh::processor_id() != 0) 00104 return; 00105 00106 if (this->binary()) 00107 this->read_binary (name); 00108 else 00109 this->read_ascii (name); 00110 } 00111 00112 00113 00114 void LegacyXdrIO::read_mgf (const std::string& name) 00115 { 00116 if (this->binary()) 00117 this->read_binary (name, LegacyXdrIO::MGF); 00118 else 00119 this->read_ascii (name, LegacyXdrIO::MGF); 00120 } 00121 00122 00123 00124 void LegacyXdrIO::write (const std::string& name) 00125 { 00126 if (this->binary()) 00127 this->write_binary (name); 00128 else 00129 this->write_ascii (name); 00130 } 00131 00132 00133 00134 void LegacyXdrIO::write_mgf (const std::string& name) 00135 { 00136 if (this->binary()) 00137 this->write_binary (name, LegacyXdrIO::MGF); 00138 else 00139 this->write_ascii (name, LegacyXdrIO::MGF); 00140 } 00141 00142 00143 00144 void LegacyXdrIO::read_mgf_soln (const std::string& name, 00145 std::vector<Number>& soln, 00146 std::vector<std::string>& var_names) const 00147 { 00148 libmesh_deprecated(); 00149 00150 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 00151 00152 // buffer for writing separately 00153 std::vector<Real> real_soln; 00154 std::vector<Real> imag_soln; 00155 00156 Utility::prepare_complex_data (soln, real_soln, imag_soln); 00157 00158 this->read_soln (Utility::complex_filename(name, 0), 00159 real_soln, 00160 var_names); 00161 00162 this->read_soln (Utility::complex_filename(name, 1), 00163 imag_soln, 00164 var_names); 00165 00166 #else 00167 00168 this->read_soln (name, soln, var_names); 00169 00170 #endif 00171 } 00172 00173 00174 00175 void LegacyXdrIO::write_mgf_soln (const std::string& name, 00176 std::vector<Number>& soln, 00177 std::vector<std::string>& var_names) const 00178 { 00179 libmesh_deprecated(); 00180 00181 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 00182 00183 // buffer for writing separately 00184 std::vector<Real> real_soln; 00185 std::vector<Real> imag_soln; 00186 00187 Utility::prepare_complex_data (soln, real_soln, imag_soln); 00188 00189 this->write_soln (Utility::complex_filename(name, 0), 00190 real_soln, 00191 var_names); 00192 00193 this->write_soln (Utility::complex_filename(name, 1), 00194 imag_soln, 00195 var_names); 00196 00197 #else 00198 00199 this->write_soln (name, soln, var_names); 00200 00201 #endif 00202 } 00203 00204 00205 00206 void LegacyXdrIO::read_ascii (const std::string& name, const LegacyXdrIO::FileFormat originator) 00207 { 00208 // get a writeable reference to the underlying mesh 00209 MeshBase& mesh = MeshInput<MeshBase>::mesh(); 00210 00211 // clear any existing mesh data 00212 mesh.clear(); 00213 00214 // read the mesh 00215 this->read_mesh (name, originator); 00216 } 00217 00218 00219 00220 #ifndef LIBMESH_HAVE_XDR 00221 void LegacyXdrIO::read_binary (const std::string& name, const LegacyXdrIO::FileFormat) 00222 { 00223 00224 libMesh::err << "WARNING: Compiled without XDR binary support.\n" 00225 << "Will try ASCII instead" << std::endl << std::endl; 00226 00227 this->read_ascii (name); 00228 } 00229 #else 00230 void LegacyXdrIO::read_binary (const std::string& name, const LegacyXdrIO::FileFormat originator) 00231 { 00232 // get a writeable reference to the underlying mesh 00233 MeshBase& mesh = MeshInput<MeshBase>::mesh(); 00234 00235 // clear any existing mesh data 00236 mesh.clear(); 00237 00238 // read the mesh 00239 this->read_mesh (name, originator); 00240 } 00241 #endif 00242 00243 00244 00245 void LegacyXdrIO::write_ascii (const std::string& name, const LegacyXdrIO::FileFormat originator) 00246 { 00247 this->write_mesh (name, originator); 00248 } 00249 00250 00251 00252 #ifndef LIBMESH_HAVE_XDR 00253 void LegacyXdrIO::write_binary (const std::string& name, const LegacyXdrIO::FileFormat) 00254 { 00255 libMesh::err << "WARNING: Compiled without XDR binary support.\n" 00256 << "Will try ASCII instead" << std::endl << std::endl; 00257 00258 this->write_ascii (name); 00259 } 00260 #else 00261 void LegacyXdrIO::write_binary (const std::string& name, const LegacyXdrIO::FileFormat originator) 00262 { 00263 this->write_mesh (name, originator); 00264 } 00265 #endif 00266 00267 00268 00269 void LegacyXdrIO::read_mesh (const std::string& name, 00270 const LegacyXdrIO::FileFormat originator, 00271 MeshData* mesh_data) 00272 { 00273 // This is a serial-only process for now; 00274 // the Mesh should be read on processor 0 and 00275 // broadcast later 00276 libmesh_assert_equal_to (libMesh::processor_id(), 0); 00277 00278 // get a writeable reference to the mesh 00279 MeshBase& mesh = MeshInput<MeshBase>::mesh(); 00280 00281 // clear any data in the mesh 00282 mesh.clear(); 00283 00284 // Keep track of what kinds of elements this file contains 00285 elems_of_dimension.clear(); 00286 elems_of_dimension.resize(4, false); 00287 00288 // Create an XdrMESH object. 00289 XdrMESH m; 00290 00291 // Create a pointer 00292 // to an XdrMESH file 00293 // header. 00294 XdrMHEAD mh; 00295 00296 // Open the XDR file for reading. 00297 // Note 1: Provide an additional argument 00298 // to specify the dimension. 00299 // 00300 // Note 2: Has to do the right thing for 00301 // both binary and ASCII files. 00302 m.set_orig_flag(originator); 00303 m.init((this->binary() ? XdrMGF::DECODE : XdrMGF::R_ASCII), name.c_str(), 0); // mesh files are always number 0 ... 00304 00305 // From here on, things depend 00306 // on whether we are reading or 00307 // writing! First, we define 00308 // header variables that may 00309 // be read OR written. 00310 unsigned int n_blocks = 0; 00311 unsigned int n_levels = 0; 00312 00313 if (m.get_orig_flag() == LegacyXdrIO::LIBM) 00314 n_levels = m.get_num_levels(); 00315 00316 00317 std::vector<ElemType> etypes; 00318 std::vector<unsigned int> neeb; 00319 00320 // Get the information from 00321 // the header, and place it 00322 // in the header pointer. 00323 m.header(&mh); 00324 00325 // Read information from the 00326 // file header. This depends on 00327 // whether its a libMesh or MGF mesh. 00328 const int numElem = mh.getNumEl(); 00329 const int numNodes = mh.getNumNodes(); 00330 const int totalWeight = mh.getSumWghts(); 00331 const int numBCs = mh.getNumBCs(); 00332 00333 // If a libMesh-type mesh, read the augmented mesh information 00334 if ((m.get_orig_flag() == LegacyXdrIO::DEAL) || (m.get_orig_flag() == LegacyXdrIO::LIBM)) 00335 { 00336 // Read augmented header 00337 n_blocks = mh.get_n_blocks(); 00338 00339 etypes.resize(n_blocks); 00340 mh.get_block_elt_types(etypes); 00341 00342 mh.get_num_elem_each_block(neeb); 00343 } 00344 00345 00346 00347 // Read the connectivity 00348 std::vector<int> conn; 00349 00350 // Now that we know the 00351 // number of nodes and elements, 00352 // we can resize the 00353 // appropriate vectors if we are 00354 // reading information in. 00355 mesh.reserve_nodes (numNodes); 00356 mesh.reserve_elem (numElem); 00357 00358 // Each element stores two extra 00359 // locations: one which tells 00360 // what type of element it is, 00361 // and one which tells how many 00362 // nodes it has. Therefore, 00363 // the total number of nodes 00364 // (totalWeight) must be augmented 00365 // by 2 times the number of elements 00366 // in order to read in the entire 00367 // connectivity array. 00368 00369 // Note: This section now depends on 00370 // whether we are reading an old-style libMesh, 00371 // MGF, or a new-style libMesh mesh. 00372 if (m.get_orig_flag() == LegacyXdrIO::DEAL) 00373 { 00374 conn.resize(totalWeight); 00375 m.Icon(&conn[0], 1, totalWeight); 00376 } 00377 00378 else if (m.get_orig_flag() == LegacyXdrIO::MGF) 00379 { 00380 conn.resize(totalWeight+(2*numElem)); 00381 m.Icon(&conn[0], 1, totalWeight+(2*numElem)); 00382 } 00383 00384 else if (m.get_orig_flag() == LegacyXdrIO::LIBM) 00385 { 00386 conn.resize(totalWeight); 00387 m.Icon(&conn[0], 1, totalWeight); 00388 } 00389 00390 else 00391 { 00392 // I don't know what type of mesh it is. 00393 libmesh_error(); 00394 } 00395 00396 // read in the nodal coordinates and form points. 00397 { 00398 std::vector<Real> coords(numNodes*3); // Always use three coords per node 00399 m.coord(&coords[0], 3, numNodes); 00400 00401 00402 00403 // Form Nodes out of 00404 // the coordinates. If the 00405 // MeshData object is active, 00406 // add the nodes and ids also 00407 // to its map. 00408 for (int innd=0; innd<numNodes; ++innd) 00409 { 00410 Node* node = mesh.add_point (Point(coords[0+innd*3], 00411 coords[1+innd*3], 00412 coords[2+innd*3]), innd); 00413 00414 if (mesh_data != NULL) 00415 if (mesh_data->active()) 00416 { 00417 // add the id to the MeshData, so that 00418 // it knows the foreign id, even when 00419 // the underlying mesh got re-numbered, 00420 // refined, elements/nodes added... 00421 mesh_data->add_foreign_node_id(node, innd); 00422 } 00423 } 00424 } 00425 00426 00427 00428 // Build the elements. 00429 // Note: If the originator was MGF, we don't 00430 // have to do much checking ... 00431 // all the elements are Hex27. 00432 // If the originator was 00433 // this code, we have to loop over 00434 // et and neeb to read in all the 00435 // elements correctly. 00436 // 00437 // (This used to be before the coords block, but it 00438 // had to change now that elements store pointers to 00439 // nodes. The nodes must exist before we assign them to 00440 // the elements. BSK, 1/13/2003) 00441 if ((m.get_orig_flag() == LegacyXdrIO::DEAL) || (m.get_orig_flag() == LegacyXdrIO::LIBM)) 00442 { 00443 unsigned int lastConnIndex = 0; 00444 unsigned int lastFaceIndex = 0; 00445 00446 // This map keeps track of elements we've previously 00447 // constructed, to avoid O(n) lookup times for parent pointers 00448 // and to enable elements to be added in ascending ID order 00449 std::map<unsigned int, Elem*> parents; 00450 00451 { 00452 // Keep track of Element ids in MGF-style meshes; 00453 unsigned int next_elem_id = 0; 00454 00455 for (unsigned int level=0; level<=n_levels; level++) 00456 { 00457 for (unsigned int idx=0; idx<n_blocks; idx++) 00458 { 00459 for (unsigned int e=lastFaceIndex; e<lastFaceIndex+neeb[level*n_blocks+idx]; e++) 00460 { 00461 // Build a temporary element of the right type, so we know how 00462 // connectivity entries will be on the line for this element. 00463 AutoPtr<Elem> temp_elem = Elem::build(etypes[idx]); 00464 00465 // A pointer to the element which will eventually be added to the mesh. 00466 Elem* elem; 00467 00468 // New-style libMesh mesh 00469 if (m.get_orig_flag() == LegacyXdrIO::LIBM) 00470 { 00471 unsigned int self_ID = conn[lastConnIndex + temp_elem->n_nodes()]; 00472 00473 #ifdef LIBMESH_ENABLE_AMR 00474 unsigned int parent_ID = conn[lastConnIndex + temp_elem->n_nodes()+1]; 00475 00476 if (level > 0) 00477 { 00478 // Do a linear search for the parent 00479 Elem* my_parent; 00480 00481 // Search for parent in the parents map (log(n)) 00482 START_LOG("log(n) search for parent", "LegacyXdrIO::read_mesh"); 00483 std::map<unsigned int, Elem*>::iterator it = parents.find(parent_ID); 00484 STOP_LOG("log(n) search for parent", "LegacyXdrIO::read_mesh"); 00485 00486 // If the parent was not previously added, we cannot continue. 00487 if (it == parents.end()) 00488 { 00489 libMesh::err << "Parent element with ID " << parent_ID 00490 << " not found." << std::endl; 00491 libmesh_error(); 00492 } 00493 00494 // Set the my_parent pointer 00495 my_parent = (*it).second; 00496 00497 // my_parent is now INACTIVE, since he has children 00498 my_parent->set_refinement_flag(Elem::INACTIVE); 00499 00500 // Now that we know the parent, build the child 00501 elem = Elem::build(etypes[idx],my_parent).release(); 00502 00503 // The new child is marked as JUST_REFINED 00504 elem->set_refinement_flag(Elem::JUST_REFINED); 00505 00506 // Tell the parent about his new child 00507 my_parent->add_child(elem); 00508 00509 // sanity check 00510 libmesh_assert_equal_to (my_parent->type(), elem->type()); 00511 } 00512 00513 // Add level-0 elements to the mesh 00514 else 00515 #endif // #ifdef LIBMESH_ENABLE_AMR 00516 { 00517 elem = Elem::build(etypes[idx]).release(); 00518 } 00519 00520 // Assign the newly-added element's ID so that future 00521 // children which may be added can find it correctly. 00522 elem->set_id() = self_ID; 00523 00524 // Add this element to the map, it may be a parent for a future element 00525 START_LOG("insert elem into map", "LegacyXdrIO::read_mesh"); 00526 parents[self_ID] = elem; 00527 STOP_LOG("insert elem into map", "LegacyXdrIO::read_mesh"); 00528 } 00529 00530 // MGF-style meshes 00531 else 00532 { 00533 elem = Elem::build(etypes[idx]).release(); 00534 elem->set_id(next_elem_id++); 00535 00536 elems_of_dimension[elem->dim()] = true; 00537 00538 mesh.add_elem(elem); 00539 } 00540 00541 // Add elements with the same id as in libMesh. 00542 // Provided the data files that MeshData reads 00543 // were only written with MeshData, then this 00544 // should work properly. This is an inline 00545 // function, so that for disabled MeshData, this 00546 // should not induce too much cost 00547 if (mesh_data != NULL) 00548 mesh_data->add_foreign_elem_id (elem, e); 00549 00550 // Set the node pointers of the newly-created element 00551 for (unsigned int innd=0; innd < elem->n_nodes(); innd++) 00552 { 00553 elem->set_node(innd) = mesh.node_ptr(conn[innd+lastConnIndex]); 00554 } 00555 00556 lastConnIndex += (m.get_orig_flag() == LegacyXdrIO::LIBM) ? (elem->n_nodes()+2) : elem->n_nodes(); 00557 } 00558 lastFaceIndex += neeb[idx]; 00559 } 00560 } 00561 } 00562 00563 if (m.get_orig_flag() == LegacyXdrIO::LIBM) 00564 { 00565 { 00566 // Iterate in ascending elem ID order 00567 unsigned int next_elem_id = 0; 00568 for (std::map<unsigned int, Elem *>::iterator i = 00569 parents.begin(); 00570 i != parents.end(); ++i) 00571 { 00572 Elem *elem = i->second; 00573 if (elem) 00574 { 00575 elem->set_id(next_elem_id++); 00576 00577 elems_of_dimension[elem->dim()] = true; 00578 00579 mesh.add_elem(elem); 00580 } 00581 else 00582 // We can probably handle this, but we don't expect it 00583 libmesh_error(); 00584 } 00585 } 00586 } 00587 } 00588 00589 // MGF-style (1) Hex27 mesh 00590 else if (m.get_orig_flag() == LegacyXdrIO::MGF) 00591 { 00592 00593 #ifdef DEBUG 00594 if (mesh_data != NULL) 00595 if (mesh_data->active()) 00596 { 00597 libMesh::err << "ERROR: MeshData not implemented for MGF-style mesh." 00598 << std::endl; 00599 libmesh_error(); 00600 } 00601 #endif 00602 00603 for (int ielm=0; ielm < numElem; ++ielm) 00604 { 00605 Elem* elem = new Hex27; 00606 elem->set_id(ielm); 00607 00608 elems_of_dimension[elem->dim()] = true; 00609 00610 mesh.add_elem(elem); 00611 00612 for (int innd=0; innd < 27; ++innd) 00613 elem->set_node(innd) = mesh.node_ptr(conn[innd+2+(27+2)*ielm]); 00614 } 00615 } 00616 00617 // Set the mesh dimension to the largest encountered for an element 00618 for (unsigned int i=0; i!=4; ++i) 00619 if (elems_of_dimension[i]) 00620 mesh.set_mesh_dimension(i); 00621 00622 #if LIBMESH_DIM < 3 00623 if (mesh.mesh_dimension() > LIBMESH_DIM) 00624 { 00625 libMesh::err << "Cannot open dimension " << 00626 mesh.mesh_dimension() << 00627 " mesh file when configured without " << 00628 mesh.mesh_dimension() << "D support." << 00629 std::endl; 00630 libmesh_error(); 00631 } 00632 #endif 00633 00634 // tell the MeshData object that we are finished 00635 // reading data 00636 if (mesh_data != NULL) 00637 mesh_data->close_foreign_id_maps (); 00638 00639 // Free memory used in 00640 // the connectivity 00641 // vector. 00642 conn.clear(); 00643 00644 00645 // If we are reading, 00646 // read in the BCs 00647 // from the mesh file, 00648 // otherwise write the 00649 // boundary conditions 00650 // if the BoundaryInfo 00651 // object exists. 00652 if (numBCs > 0) 00653 { 00654 std::vector<int> bcs(numBCs*3); 00655 00656 // Read the BCs from the XDR file 00657 m.BC(&bcs[0], numBCs); 00658 00659 // Add to the boundary_info 00660 for (int ibc=0; ibc < numBCs; ibc++) 00661 mesh.boundary_info->add_side(bcs[0+ibc*3], bcs[1+ibc*3], bcs[2+ibc*3]); 00662 } 00663 } 00664 00665 00666 00667 void LegacyXdrIO::write_mesh (const std::string& name, 00668 const LegacyXdrIO::FileFormat originator) 00669 { 00670 // get a read-only reference to the mesh 00671 const MeshBase& mesh = MeshOutput<MeshBase>::mesh(); 00672 00673 // n_levels is a parallel-only method 00674 parallel_only(); 00675 const unsigned int n_levels = MeshTools::n_levels(mesh); 00676 00677 // The Legacy Xdr IO code only works if we have a serialized mesh 00678 libmesh_assert (mesh.is_serial()); 00679 00680 // In which case only processor 0 needs to do any writing 00681 if (libMesh::processor_id() != 0) 00682 return; 00683 00684 // Create an XdrMESH object. 00685 XdrMESH m; 00686 00687 // Create a pointer 00688 // to an XdrMESH file 00689 // header. 00690 XdrMHEAD mh; 00691 00692 // Open the XDR file for writing. 00693 // Note 1: Provide an additional argument 00694 // to specify the dimension. 00695 // 00696 // Note 2: Has to do the right thing for 00697 // both binary and ASCII files. 00698 m.set_orig_flag(originator); 00699 00700 // From here on, things depend 00701 // on whether we are reading or 00702 // writing! First, we define 00703 // header variables that may 00704 // be read OR written. 00705 std::vector<unsigned int> neeb; 00706 std::vector<ElemType> etypes; 00707 00708 00709 int n_non_subactive = 0; 00710 int non_subactive_weight = 0; 00711 00712 // This map will associate 00713 // the distance from the beginning of the set 00714 // to each node ID with the node ID itself. 00715 std::map<dof_id_type, dof_id_type> node_map; 00716 00717 { 00718 // For each non-subactive element: 00719 // 1.) Increment the number of non subactive elements 00720 // 2.) Accumulate the total weight 00721 // 3.) Add the node ids to a set of non subactive node ids 00722 std::set<dof_id_type> not_subactive_node_ids; 00723 MeshBase::const_element_iterator el = mesh.elements_begin(); 00724 const MeshBase::const_element_iterator end_el = mesh.elements_end(); 00725 for( ; el != end_el; ++el) 00726 { 00727 const Elem* elem = (*el); 00728 if(!elem->subactive()) 00729 { 00730 n_non_subactive++; 00731 non_subactive_weight += elem->n_nodes(); 00732 00733 for (unsigned int n=0; n<elem->n_nodes(); ++n) 00734 not_subactive_node_ids.insert(elem->node(n)); 00735 } 00736 } 00737 00738 // Now that the set is built, most of the hard work is done. We build 00739 // the map next and let the set go out of scope. 00740 std::set<dof_id_type>::iterator it = not_subactive_node_ids.begin(); 00741 const std::set<dof_id_type>::iterator end = not_subactive_node_ids.end(); 00742 dof_id_type cnt=0; 00743 for (; it!=end; ++it) 00744 node_map[*it] = cnt++; 00745 } 00746 00747 00748 const int numElem = n_non_subactive; 00749 const int numBCs = mesh.boundary_info->n_boundary_conds(); 00750 00751 // Fill the etypes vector with all of the element types found in the mesh 00752 MeshTools::elem_types(mesh, etypes); 00753 00754 // store number of elements in each block at each refinement level 00755 neeb.resize((n_levels+1)*etypes.size()); 00756 00757 // Store a variable for the number of element types 00758 const unsigned int n_el_types = 00759 libmesh_cast_int<unsigned int>(etypes.size()); 00760 00761 m.set_num_levels(n_levels); 00762 00763 // The last argument is zero because mesh files are always number 0 ... 00764 m.init((this->binary() ? XdrMGF::ENCODE : XdrMGF::W_ASCII), name.c_str(), 0); 00765 00766 // Loop over all levels and all element types to set the entries of neeb 00767 for(unsigned int level=0; level<=n_levels; level++) 00768 for (unsigned int el_type=0; el_type<n_el_types; el_type++) 00769 neeb[level*n_el_types + el_type] = 00770 MeshTools::n_non_subactive_elem_of_type_at_level(mesh, etypes[el_type], level); 00771 // gotta change this function name!!! 00772 00773 00774 // Now we check to see if we're doing 00775 // MGF-style headers or libMesh-style 00776 // "augmented" headers. An 00777 // augmented header contains 00778 // information about mesh blocks, 00779 // allowing us to optimize storage 00780 // and minimize IO requirements 00781 // for these meshes. 00782 if ((m.get_orig_flag() == LegacyXdrIO::DEAL) || (m.get_orig_flag() == LegacyXdrIO::LIBM)) 00783 { 00784 mh.set_n_blocks(etypes.size()); 00785 mh.set_block_elt_types(etypes); 00786 mh.set_num_elem_each_block(neeb); 00787 } 00788 else 00789 libmesh_assert_equal_to (etypes.size(), 1); 00790 00791 mh.setNumEl(numElem); 00792 mh.setNumNodes(node_map.size()); 00793 mh.setStrSize(65536); 00794 00795 // set a local variable for the total weight of the mesh 00796 int totalWeight =0; 00797 00798 if (m.get_orig_flag() == LegacyXdrIO::DEAL) // old-style LibMesh 00799 totalWeight=MeshTools::total_weight(mesh); 00800 00801 else if (m.get_orig_flag() == LegacyXdrIO::MGF) // MGF-style 00802 totalWeight = MeshTools::total_weight(mesh)+2*numElem; 00803 00804 else if (m.get_orig_flag() == LegacyXdrIO::LIBM) // new-style LibMesh 00805 totalWeight = non_subactive_weight+2*numElem; 00806 00807 else 00808 libmesh_error(); 00809 00810 // Set the total weight in the header 00811 mh.setSumWghts(totalWeight); 00812 00813 mh.setNumBCs(numBCs); 00814 mh.setId("Id String"); // You can put whatever you want, it will be ignored 00815 mh.setTitle("Title String"); // You can put whatever you want, it will be ignored 00816 00817 // Put the information 00818 // in the XDR file. 00819 m.header(&mh); 00820 00821 00822 // Write the connectivity 00823 { 00824 std::vector<int> conn; 00825 LegacyXdrIO::FileFormat orig_type = m.get_orig_flag(); 00826 00827 // Resize the connectivity vector to hold all the connectivity for the mesh 00828 conn.resize(totalWeight); 00829 00830 unsigned int lastConnIndex = 0; 00831 unsigned int nn = 0; 00832 00833 // Loop over levels and types again, write connectivity information to conn. 00834 for (unsigned int level=0; level<=n_levels; level++) 00835 for (unsigned int idx=0; idx<etypes.size(); idx++) 00836 { 00837 nn = lastConnIndex = 0; 00838 00839 for (unsigned int e=0; e<mesh.n_elem(); e++) 00840 if ((mesh.elem(e)->type() == etypes[idx]) && 00841 (mesh.elem(e)->level() == level) && 00842 !mesh.elem(e)->subactive()) 00843 { 00844 int nstart=0; 00845 00846 if (orig_type == LegacyXdrIO::DEAL) 00847 nn = mesh.elem(e)->n_nodes(); 00848 00849 else if (orig_type == LegacyXdrIO::MGF) 00850 { 00851 nstart=2; // ignore the 27 and 0 entries 00852 nn = mesh.elem(e)->n_nodes()+2; 00853 conn[lastConnIndex + 0] = 27; 00854 conn[lastConnIndex + 1] = 0; 00855 } 00856 00857 else if (orig_type == LegacyXdrIO::LIBM) // LIBMESH format 00858 nn = mesh.elem(e)->n_nodes() + 2; 00859 00860 else 00861 libmesh_error(); 00862 00863 // Loop over the connectivity entries for this element and write to conn. 00864 START_LOG("set connectivity", "LegacyXdrIO::write_mesh"); 00865 const unsigned int loopmax = (orig_type==LegacyXdrIO::LIBM) ? nn-2 : nn; 00866 for (unsigned int n=nstart; n<loopmax; n++) 00867 { 00868 unsigned int connectivity_value=0; 00869 00870 // old-style Libmesh and MGF meshes 00871 if (orig_type != LegacyXdrIO::LIBM) 00872 connectivity_value = mesh.elem(e)->node(n-nstart); 00873 00874 // new-style libMesh meshes: compress the connectivity entries to account for 00875 // subactive nodes that will not be in the mesh we write out. 00876 else 00877 { 00878 std::map<dof_id_type, dof_id_type>::iterator pos = 00879 node_map.find(mesh.elem(e)->node(n-nstart)); 00880 00881 libmesh_assert (pos != node_map.end()); 00882 00883 connectivity_value = (*pos).second; 00884 } 00885 conn[lastConnIndex + n] = connectivity_value; 00886 } 00887 STOP_LOG("set connectivity", "LegacyXdrIO::write_mesh"); 00888 00889 // In the case of an adaptive mesh, set last 2 entries to this ID and parent ID 00890 if (orig_type == LegacyXdrIO::LIBM) 00891 { 00892 int self_ID = mesh.elem(e)->id(); 00893 int parent_ID = -1; 00894 if(level != 0) 00895 parent_ID = mesh.elem(e)->parent()->id(); 00896 00897 // Self ID is the second-to-last entry, Parent ID is the last 00898 // entry on each connectivity line 00899 conn[lastConnIndex+nn-2] = self_ID; 00900 conn[lastConnIndex+nn-1] = parent_ID; 00901 } 00902 00903 lastConnIndex += nn; 00904 } 00905 00906 // Send conn to the XDR file. If there are no elements of this level and type, 00907 // then nn will be zero, and we there is no connectivity to write. 00908 if (nn != 0) 00909 m.Icon(&conn[0], nn, lastConnIndex/nn); 00910 } 00911 } 00912 00913 // create the vector of coords and send 00914 // it to the XDR file. 00915 { 00916 std::vector<Real> coords; 00917 00918 coords.resize(3*node_map.size()); 00919 int lastIndex=0; 00920 00921 std::map<dof_id_type,dof_id_type>::iterator it = node_map.begin(); 00922 const std::map<dof_id_type,dof_id_type>::iterator end = node_map.end(); 00923 for (; it != end; ++it) 00924 { 00925 const Point& p = mesh.node((*it).first); 00926 00927 coords[lastIndex+0] = p(0); 00928 coords[lastIndex+1] = p(1); 00929 coords[lastIndex+2] = p(2); 00930 lastIndex += 3; 00931 } 00932 00933 // Put the nodes in the XDR file 00934 m.coord(&coords[0], 3, node_map.size()); 00935 } 00936 00937 00938 // write the 00939 // boundary conditions 00940 // if the BoundaryInfo 00941 // object exists. 00942 if (numBCs > 0) 00943 { 00944 std::vector<int> bcs(numBCs*3); 00945 00946 //libMesh::out << "numBCs=" << numBCs << std::endl; 00947 00948 //libMesh::out << "Preparing to write boundary conditions." << std::endl; 00949 std::vector<dof_id_type> elem_list; 00950 std::vector<unsigned short int> side_list; 00951 std::vector<boundary_id_type> elem_id_list; 00952 00953 mesh.boundary_info->build_side_list (elem_list, side_list, elem_id_list); 00954 00955 for (int ibc=0; ibc<numBCs; ibc++) 00956 { 00957 bcs[0+ibc*3] = elem_list[ibc]; 00958 bcs[1+ibc*3] = side_list[ibc]; 00959 bcs[2+ibc*3] = elem_id_list[ibc]; 00960 } 00961 00962 // Put the BCs in the XDR file 00963 m.BC(&bcs[0], numBCs); 00964 } 00965 } 00966 00967 00968 00969 void LegacyXdrIO::read_soln (const std::string& name, 00970 std::vector<Real>& soln, 00971 std::vector<std::string>& var_names) const 00972 { 00973 // Create an XdrSOLN object. 00974 XdrSOLN s; 00975 00976 // Create an XdrSHEAD object. 00977 XdrSHEAD sh; 00978 00979 // Open the XDR file for 00980 // reading or writing. 00981 // Note 1: Provide an additional argument 00982 // to specify the dimension. 00983 // 00984 // Note 2: Has to do the right thing for 00985 // both binary and ASCII files. 00986 s.init((this->binary() ? XdrMGF::DECODE : XdrMGF::R_ASCII), name.c_str(), 0); // mesh files are always number 0 ... 00987 00988 // From here on, things depend 00989 // on whether we are reading or 00990 // writing! First, we define 00991 // header variables that may 00992 // be read OR written. 00993 int numVar = 0; 00994 int numNodes = 0; 00995 const char* varNames; 00996 00997 // Get the information from 00998 // the header, and place it 00999 // in the header pointer. 01000 s.header(&sh); 01001 01002 // Read information from the 01003 // file header. This depends on 01004 // whether its a libMesh or MGF mesh. 01005 numVar = sh.getWrtVar(); 01006 numNodes = sh.getNumNodes(); 01007 varNames = sh.getVarTitle(); 01008 01009 // Get the variable names 01010 { 01011 var_names.resize(numVar); 01012 01013 const char* p = varNames; 01014 01015 for (int i=0; i<numVar; i++) 01016 { 01017 var_names[i] = p; 01018 p += std::strlen(p) + 1; 01019 } 01020 } 01021 01022 // Read the soln vector 01023 soln.resize(numVar*numNodes); 01024 01025 s.values(&soln[0], numNodes); 01026 } 01027 01028 01029 01030 void LegacyXdrIO::write_soln (const std::string& name, 01031 std::vector<Real>& soln, 01032 std::vector<std::string>& var_names) const 01033 { 01034 // get a read-only reference to the mesh 01035 const MeshBase& mesh = MeshOutput<MeshBase>::mesh(); 01036 01037 // Create an XdrSOLN object. 01038 XdrSOLN s; 01039 01040 // Create an XdrSHEAD object. 01041 XdrSHEAD sh; 01042 01043 // Open the XDR file for 01044 // reading or writing. 01045 // Note 1: Provide an additional argument 01046 // to specify the dimension. 01047 // 01048 // Note 2: Has to do the right thing for 01049 // both binary and ASCII files. 01050 s.init((this->binary() ? XdrMGF::ENCODE : XdrMGF::W_ASCII), name.c_str(), 0); // mesh files are always number 0 ... 01051 01052 // Build the header 01053 sh.setWrtVar(var_names.size()); 01054 sh.setNumVar(var_names.size()); 01055 sh.setNumNodes(mesh.n_nodes()); 01056 sh.setNumBCs(mesh.boundary_info->n_boundary_conds()); 01057 sh.setMeshCnt(0); 01058 sh.setKstep(0); 01059 sh.setTime(0.); 01060 sh.setStrSize(65536); 01061 sh.setId("Id String"); // Ignored 01062 sh.setTitle("Title String"); // Ignored 01063 sh.setUserTitle("User Title String"); // Ignored 01064 01065 // create the variable array 01066 { 01067 std::string var_title; 01068 01069 for (unsigned int var=0; var<var_names.size(); var++) 01070 { 01071 for (unsigned int c=0; c<var_names[var].size(); c++) 01072 var_title += var_names[var][c]; 01073 01074 var_title += '\0'; 01075 } 01076 01077 sh.setVarTitle(var_title.c_str(), var_title.size()); 01078 } 01079 01080 // Put the informationin the XDR file. 01081 s.header(&sh); // Needs to work for both types of file 01082 01083 // Write the solution vector 01084 libmesh_assert_equal_to (soln.size(), var_names.size()*mesh.n_nodes()); 01085 01086 s.values(&soln[0], mesh.n_nodes()); 01087 } 01088 01089 } // namespace libMesh
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:47 UTC
Hosted By: