$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 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 (MeshOutput<MeshBase>::mesh().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 (MeshOutput<MeshBase>::mesh().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_msg("Unrecognized flag " << m.get_orig_flag()); 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 // This map keeps track of elements we've previously 00444 // constructed, to avoid O(n) lookup times for parent pointers 00445 // and to enable elements to be added in ascending ID order 00446 std::map<unsigned int, Elem*> parents; 00447 00448 { 00449 unsigned int lastConnIndex = 0; 00450 unsigned int lastFaceIndex = 0; 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 UniquePtr<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 libmesh_error_msg("Parent element with ID " << parent_ID << " not found."); 00489 00490 // Set the my_parent pointer 00491 my_parent = (*it).second; 00492 00493 // my_parent is now INACTIVE, since he has children 00494 my_parent->set_refinement_flag(Elem::INACTIVE); 00495 00496 // Now that we know the parent, build the child 00497 elem = Elem::build(etypes[idx],my_parent).release(); 00498 00499 // The new child is marked as JUST_REFINED 00500 elem->set_refinement_flag(Elem::JUST_REFINED); 00501 00502 // Tell the parent about his new child 00503 my_parent->add_child(elem); 00504 00505 // sanity check 00506 libmesh_assert_equal_to (my_parent->type(), elem->type()); 00507 } 00508 00509 // Add level-0 elements to the mesh 00510 else 00511 #endif // #ifdef LIBMESH_ENABLE_AMR 00512 { 00513 elem = Elem::build(etypes[idx]).release(); 00514 } 00515 00516 // Assign the newly-added element's ID so that future 00517 // children which may be added can find it correctly. 00518 elem->set_id() = self_ID; 00519 00520 // Add this element to the map, it may be a parent for a future element 00521 START_LOG("insert elem into map", "LegacyXdrIO::read_mesh"); 00522 parents[self_ID] = elem; 00523 STOP_LOG("insert elem into map", "LegacyXdrIO::read_mesh"); 00524 } 00525 00526 // MGF-style meshes 00527 else 00528 { 00529 elem = Elem::build(etypes[idx]).release(); 00530 elem->set_id(next_elem_id++); 00531 00532 elems_of_dimension[elem->dim()] = true; 00533 00534 mesh.add_elem(elem); 00535 } 00536 00537 // Add elements with the same id as in libMesh. 00538 // Provided the data files that MeshData reads 00539 // were only written with MeshData, then this 00540 // should work properly. This is an inline 00541 // function, so that for disabled MeshData, this 00542 // should not induce too much cost 00543 if (mesh_data != NULL) 00544 mesh_data->add_foreign_elem_id (elem, e); 00545 00546 // Set the node pointers of the newly-created element 00547 for (unsigned int innd=0; innd < elem->n_nodes(); innd++) 00548 { 00549 elem->set_node(innd) = mesh.node_ptr(conn[innd+lastConnIndex]); 00550 } 00551 00552 lastConnIndex += (m.get_orig_flag() == LegacyXdrIO::LIBM) ? (elem->n_nodes()+2) : elem->n_nodes(); 00553 } 00554 lastFaceIndex += neeb[idx]; 00555 } 00556 } 00557 } 00558 00559 if (m.get_orig_flag() == LegacyXdrIO::LIBM) 00560 { 00561 { 00562 // Iterate in ascending elem ID order 00563 unsigned int next_elem_id = 0; 00564 for (std::map<unsigned int, Elem *>::iterator i = 00565 parents.begin(); 00566 i != parents.end(); ++i) 00567 { 00568 Elem *elem = i->second; 00569 if (elem) 00570 { 00571 elem->set_id(next_elem_id++); 00572 00573 elems_of_dimension[elem->dim()] = true; 00574 00575 mesh.add_elem(elem); 00576 } 00577 else 00578 // We can probably handle this, but we don't expect it 00579 libmesh_error_msg("Unexpected NULL elem encountered while reading libmesh XDR file."); 00580 } 00581 } 00582 } 00583 } 00584 00585 // MGF-style (1) Hex27 mesh 00586 else if (m.get_orig_flag() == LegacyXdrIO::MGF) 00587 { 00588 00589 #ifdef DEBUG 00590 if (mesh_data != NULL) 00591 if (mesh_data->active()) 00592 libmesh_error_msg("ERROR: MeshData not implemented for MGF-style mesh."); 00593 #endif 00594 00595 for (int ielm=0; ielm < numElem; ++ielm) 00596 { 00597 Elem* elem = new Hex27; 00598 elem->set_id(ielm); 00599 00600 elems_of_dimension[elem->dim()] = true; 00601 00602 mesh.add_elem(elem); 00603 00604 for (int innd=0; innd < 27; ++innd) 00605 elem->set_node(innd) = mesh.node_ptr(conn[innd+2+(27+2)*ielm]); 00606 } 00607 } 00608 00609 // Set the mesh dimension to the largest encountered for an element 00610 for (unsigned char i=0; i!=4; ++i) 00611 if (elems_of_dimension[i]) 00612 mesh.set_mesh_dimension(i); 00613 00614 #if LIBMESH_DIM < 3 00615 if (mesh.mesh_dimension() > LIBMESH_DIM) 00616 libmesh_error_msg("Cannot open dimension " \ 00617 << mesh.mesh_dimension() \ 00618 << " mesh file when configured without " \ 00619 << mesh.mesh_dimension() \ 00620 << "D support." ); 00621 #endif 00622 00623 // tell the MeshData object that we are finished 00624 // reading data 00625 if (mesh_data != NULL) 00626 mesh_data->close_foreign_id_maps (); 00627 00628 // Free memory used in 00629 // the connectivity 00630 // vector. 00631 conn.clear(); 00632 00633 00634 // If we are reading, 00635 // read in the BCs 00636 // from the mesh file, 00637 // otherwise write the 00638 // boundary conditions 00639 // if the BoundaryInfo 00640 // object exists. 00641 if (numBCs > 0) 00642 { 00643 std::vector<int> bcs(numBCs*3); 00644 00645 // Read the BCs from the XDR file 00646 m.BC(&bcs[0], numBCs); 00647 00648 // Add to the boundary_info 00649 for (int ibc=0; ibc < numBCs; ibc++) 00650 mesh.get_boundary_info().add_side 00651 (cast_int<dof_id_type>(bcs[0+ibc*3]), 00652 cast_int<unsigned short>(bcs[1+ibc*3]), 00653 cast_int<boundary_id_type>(bcs[2+ibc*3])); 00654 } 00655 } 00656 00657 00658 00659 void LegacyXdrIO::write_mesh (const std::string& name, 00660 const LegacyXdrIO::FileFormat originator) 00661 { 00662 // get a read-only reference to the mesh 00663 const MeshBase& mesh = MeshOutput<MeshBase>::mesh(); 00664 00665 // n_levels is a parallel-only method 00666 libmesh_parallel_only(mesh.comm()); 00667 const unsigned int n_levels = MeshTools::n_levels(mesh); 00668 00669 // The Legacy Xdr IO code only works if we have a serialized mesh 00670 libmesh_assert (mesh.is_serial()); 00671 00672 // In which case only processor 0 needs to do any writing 00673 if (MeshOutput<MeshBase>::mesh().processor_id() != 0) 00674 return; 00675 00676 // Create an XdrMESH object. 00677 XdrMESH m; 00678 00679 // Create a pointer 00680 // to an XdrMESH file 00681 // header. 00682 XdrMHEAD mh; 00683 00684 // Open the XDR file for writing. 00685 // Note 1: Provide an additional argument 00686 // to specify the dimension. 00687 // 00688 // Note 2: Has to do the right thing for 00689 // both binary and ASCII files. 00690 m.set_orig_flag(originator); 00691 00692 // From here on, things depend 00693 // on whether we are reading or 00694 // writing! First, we define 00695 // header variables that may 00696 // be read OR written. 00697 std::vector<unsigned int> neeb; 00698 std::vector<ElemType> etypes; 00699 00700 00701 int n_non_subactive = 0; 00702 int non_subactive_weight = 0; 00703 00704 // This map will associate 00705 // the distance from the beginning of the set 00706 // to each node ID with the node ID itself. 00707 std::map<dof_id_type, dof_id_type> node_map; 00708 00709 { 00710 // For each non-subactive element: 00711 // 1.) Increment the number of non subactive elements 00712 // 2.) Accumulate the total weight 00713 // 3.) Add the node ids to a set of non subactive node ids 00714 std::set<dof_id_type> not_subactive_node_ids; 00715 MeshBase::const_element_iterator el = mesh.elements_begin(); 00716 const MeshBase::const_element_iterator end_el = mesh.elements_end(); 00717 for( ; el != end_el; ++el) 00718 { 00719 const Elem* elem = (*el); 00720 if(!elem->subactive()) 00721 { 00722 n_non_subactive++; 00723 non_subactive_weight += elem->n_nodes(); 00724 00725 for (unsigned int n=0; n<elem->n_nodes(); ++n) 00726 not_subactive_node_ids.insert(elem->node(n)); 00727 } 00728 } 00729 00730 // Now that the set is built, most of the hard work is done. We build 00731 // the map next and let the set go out of scope. 00732 std::set<dof_id_type>::iterator it = not_subactive_node_ids.begin(); 00733 const std::set<dof_id_type>::iterator end = not_subactive_node_ids.end(); 00734 dof_id_type cnt=0; 00735 for (; it!=end; ++it) 00736 node_map[*it] = cnt++; 00737 } 00738 00739 00740 const int numElem = n_non_subactive; 00741 const int numBCs = 00742 cast_int<int>(mesh.get_boundary_info().n_boundary_conds()); 00743 00744 // Fill the etypes vector with all of the element types found in the mesh 00745 MeshTools::elem_types(mesh, etypes); 00746 00747 // store number of elements in each block at each refinement level 00748 neeb.resize((n_levels+1)*etypes.size()); 00749 00750 // Store a variable for the number of element types 00751 const unsigned int n_el_types = 00752 cast_int<unsigned int>(etypes.size()); 00753 00754 m.set_num_levels(n_levels); 00755 00756 // The last argument is zero because mesh files are always number 0 ... 00757 m.init((this->binary() ? XdrMGF::ENCODE : XdrMGF::W_ASCII), name.c_str(), 0); 00758 00759 // Loop over all levels and all element types to set the entries of neeb 00760 for(unsigned int level=0; level<=n_levels; level++) 00761 for (unsigned int el_type=0; el_type<n_el_types; el_type++) 00762 neeb[level*n_el_types + el_type] = 00763 MeshTools::n_non_subactive_elem_of_type_at_level(mesh, etypes[el_type], level); 00764 // gotta change this function name!!! 00765 00766 00767 // Now we check to see if we're doing 00768 // MGF-style headers or libMesh-style 00769 // "augmented" headers. An 00770 // augmented header contains 00771 // information about mesh blocks, 00772 // allowing us to optimize storage 00773 // and minimize IO requirements 00774 // for these meshes. 00775 if ((m.get_orig_flag() == LegacyXdrIO::DEAL) || (m.get_orig_flag() == LegacyXdrIO::LIBM)) 00776 { 00777 mh.set_n_blocks(cast_int<unsigned int>(etypes.size())); 00778 mh.set_block_elt_types(etypes); 00779 mh.set_num_elem_each_block(neeb); 00780 } 00781 else 00782 libmesh_assert_equal_to (etypes.size(), 1); 00783 00784 mh.setNumEl(numElem); 00785 mh.setNumNodes(cast_int<int>(node_map.size())); 00786 mh.setStrSize(65536); 00787 00788 // set a local variable for the total weight of the mesh 00789 int totalWeight =0; 00790 00791 if (m.get_orig_flag() == LegacyXdrIO::DEAL) // old-style LibMesh 00792 totalWeight=MeshTools::total_weight(mesh); 00793 00794 else if (m.get_orig_flag() == LegacyXdrIO::MGF) // MGF-style 00795 totalWeight = MeshTools::total_weight(mesh)+2*numElem; 00796 00797 else if (m.get_orig_flag() == LegacyXdrIO::LIBM) // new-style LibMesh 00798 totalWeight = non_subactive_weight+2*numElem; 00799 00800 else 00801 libmesh_error_msg("Unrecognized flag " << m.get_orig_flag()); 00802 00803 // Set the total weight in the header 00804 mh.setSumWghts(totalWeight); 00805 00806 mh.setNumBCs(numBCs); 00807 mh.setId("Id String"); // You can put whatever you want, it will be ignored 00808 mh.setTitle("Title String"); // You can put whatever you want, it will be ignored 00809 00810 // Put the information 00811 // in the XDR file. 00812 m.header(&mh); 00813 00814 00815 // Write the connectivity 00816 { 00817 std::vector<int> conn; 00818 LegacyXdrIO::FileFormat orig_type = m.get_orig_flag(); 00819 00820 // Resize the connectivity vector to hold all the connectivity for the mesh 00821 conn.resize(totalWeight); 00822 00823 unsigned int lastConnIndex = 0; 00824 unsigned int nn = 0; 00825 00826 // Loop over levels and types again, write connectivity information to conn. 00827 for (unsigned int level=0; level<=n_levels; level++) 00828 for (unsigned int idx=0; idx<etypes.size(); idx++) 00829 { 00830 nn = lastConnIndex = 0; 00831 00832 for (unsigned int e=0; e<mesh.n_elem(); e++) 00833 if ((mesh.elem(e)->type() == etypes[idx]) && 00834 (mesh.elem(e)->level() == level) && 00835 !mesh.elem(e)->subactive()) 00836 { 00837 int nstart=0; 00838 00839 if (orig_type == LegacyXdrIO::DEAL) 00840 nn = mesh.elem(e)->n_nodes(); 00841 00842 else if (orig_type == LegacyXdrIO::MGF) 00843 { 00844 nstart=2; // ignore the 27 and 0 entries 00845 nn = mesh.elem(e)->n_nodes()+2; 00846 conn[lastConnIndex + 0] = 27; 00847 conn[lastConnIndex + 1] = 0; 00848 } 00849 00850 else if (orig_type == LegacyXdrIO::LIBM) // LIBMESH format 00851 nn = mesh.elem(e)->n_nodes() + 2; 00852 00853 else 00854 libmesh_error_msg("Unrecognized orig_type = " << orig_type); 00855 00856 // Loop over the connectivity entries for this element and write to conn. 00857 START_LOG("set connectivity", "LegacyXdrIO::write_mesh"); 00858 const unsigned int loopmax = (orig_type==LegacyXdrIO::LIBM) ? nn-2 : nn; 00859 for (unsigned int n=nstart; n<loopmax; n++) 00860 { 00861 unsigned int connectivity_value=0; 00862 00863 // old-style Libmesh and MGF meshes 00864 if (orig_type != LegacyXdrIO::LIBM) 00865 connectivity_value = mesh.elem(e)->node(n-nstart); 00866 00867 // new-style libMesh meshes: compress the connectivity entries to account for 00868 // subactive nodes that will not be in the mesh we write out. 00869 else 00870 { 00871 std::map<dof_id_type, dof_id_type>::iterator pos = 00872 node_map.find(mesh.elem(e)->node(n-nstart)); 00873 00874 libmesh_assert (pos != node_map.end()); 00875 00876 connectivity_value = (*pos).second; 00877 } 00878 conn[lastConnIndex + n] = connectivity_value; 00879 } 00880 STOP_LOG("set connectivity", "LegacyXdrIO::write_mesh"); 00881 00882 // In the case of an adaptive mesh, set last 2 entries to this ID and parent ID 00883 if (orig_type == LegacyXdrIO::LIBM) 00884 { 00885 int self_ID = mesh.elem(e)->id(); 00886 int parent_ID = -1; 00887 if(level != 0) 00888 parent_ID = mesh.elem(e)->parent()->id(); 00889 00890 // Self ID is the second-to-last entry, Parent ID is the last 00891 // entry on each connectivity line 00892 conn[lastConnIndex+nn-2] = self_ID; 00893 conn[lastConnIndex+nn-1] = parent_ID; 00894 } 00895 00896 lastConnIndex += nn; 00897 } 00898 00899 // Send conn to the XDR file. If there are no elements of this level and type, 00900 // then nn will be zero, and we there is no connectivity to write. 00901 if (nn != 0) 00902 m.Icon(&conn[0], nn, lastConnIndex/nn); 00903 } 00904 } 00905 00906 // create the vector of coords and send 00907 // it to the XDR file. 00908 { 00909 std::vector<Real> coords; 00910 00911 coords.resize(3*node_map.size()); 00912 int lastIndex=0; 00913 00914 std::map<dof_id_type,dof_id_type>::iterator it = node_map.begin(); 00915 const std::map<dof_id_type,dof_id_type>::iterator end = node_map.end(); 00916 for (; it != end; ++it) 00917 { 00918 const Point& p = mesh.node((*it).first); 00919 00920 coords[lastIndex+0] = p(0); 00921 coords[lastIndex+1] = p(1); 00922 coords[lastIndex+2] = p(2); 00923 lastIndex += 3; 00924 } 00925 00926 // Put the nodes in the XDR file 00927 m.coord(&coords[0], 3, cast_int<int>(node_map.size())); 00928 } 00929 00930 00931 // write the 00932 // boundary conditions 00933 // if the BoundaryInfo 00934 // object exists. 00935 if (numBCs > 0) 00936 { 00937 std::vector<int> bcs(numBCs*3); 00938 00939 //libMesh::out << "numBCs=" << numBCs << std::endl; 00940 00941 //libMesh::out << "Preparing to write boundary conditions." << std::endl; 00942 std::vector<dof_id_type> elem_list; 00943 std::vector<unsigned short int> side_list; 00944 std::vector<boundary_id_type> elem_id_list; 00945 00946 mesh.get_boundary_info().build_side_list (elem_list, side_list, elem_id_list); 00947 00948 for (int ibc=0; ibc<numBCs; ibc++) 00949 { 00950 bcs[0+ibc*3] = elem_list[ibc]; 00951 bcs[1+ibc*3] = side_list[ibc]; 00952 bcs[2+ibc*3] = elem_id_list[ibc]; 00953 } 00954 00955 // Put the BCs in the XDR file 00956 m.BC(&bcs[0], numBCs); 00957 } 00958 } 00959 00960 00961 00962 void LegacyXdrIO::read_soln (const std::string& name, 00963 std::vector<Real>& soln, 00964 std::vector<std::string>& var_names) const 00965 { 00966 // Create an XdrSOLN object. 00967 XdrSOLN s; 00968 00969 // Create an XdrSHEAD object. 00970 XdrSHEAD sh; 00971 00972 // Open the XDR file for 00973 // reading or writing. 00974 // Note 1: Provide an additional argument 00975 // to specify the dimension. 00976 // 00977 // Note 2: Has to do the right thing for 00978 // both binary and ASCII files. 00979 s.init((this->binary() ? XdrMGF::DECODE : XdrMGF::R_ASCII), name.c_str(), 0); // mesh files are always number 0 ... 00980 00981 // From here on, things depend 00982 // on whether we are reading or 00983 // writing! First, we define 00984 // header variables that may 00985 // be read OR written. 00986 int numVar = 0; 00987 int numNodes = 0; 00988 const char* varNames; 00989 00990 // Get the information from 00991 // the header, and place it 00992 // in the header pointer. 00993 s.header(&sh); 00994 00995 // Read information from the 00996 // file header. This depends on 00997 // whether its a libMesh or MGF mesh. 00998 numVar = sh.getWrtVar(); 00999 numNodes = sh.getNumNodes(); 01000 varNames = sh.getVarTitle(); 01001 01002 // Get the variable names 01003 { 01004 var_names.resize(numVar); 01005 01006 const char* p = varNames; 01007 01008 for (int i=0; i<numVar; i++) 01009 { 01010 var_names[i] = p; 01011 p += std::strlen(p) + 1; 01012 } 01013 } 01014 01015 // Read the soln vector 01016 soln.resize(numVar*numNodes); 01017 01018 s.values(&soln[0], numNodes); 01019 } 01020 01021 01022 01023 void LegacyXdrIO::write_soln (const std::string& name, 01024 std::vector<Real>& soln, 01025 std::vector<std::string>& var_names) const 01026 { 01027 // get a read-only reference to the mesh 01028 const MeshBase& mesh = MeshOutput<MeshBase>::mesh(); 01029 01030 // Create an XdrSOLN object. 01031 XdrSOLN s; 01032 01033 // Create an XdrSHEAD object. 01034 XdrSHEAD sh; 01035 01036 // Open the XDR file for 01037 // reading or writing. 01038 // Note 1: Provide an additional argument 01039 // to specify the dimension. 01040 // 01041 // Note 2: Has to do the right thing for 01042 // both binary and ASCII files. 01043 s.init((this->binary() ? XdrMGF::ENCODE : XdrMGF::W_ASCII), name.c_str(), 0); // mesh files are always number 0 ... 01044 01045 // Build the header 01046 sh.setWrtVar(cast_int<int>(var_names.size())); 01047 sh.setNumVar(cast_int<int>(var_names.size())); 01048 sh.setNumNodes(cast_int<int>(mesh.n_nodes())); 01049 sh.setNumBCs(cast_int<int>(mesh.get_boundary_info().n_boundary_conds())); 01050 sh.setMeshCnt(0); 01051 sh.setKstep(0); 01052 sh.setTime(0.); 01053 sh.setStrSize(65536); 01054 sh.setId("Id String"); // Ignored 01055 sh.setTitle("Title String"); // Ignored 01056 sh.setUserTitle("User Title String"); // Ignored 01057 01058 // create the variable array 01059 { 01060 std::string var_title; 01061 01062 for (unsigned int var=0; var<var_names.size(); var++) 01063 { 01064 for (unsigned int c=0; c<var_names[var].size(); c++) 01065 var_title += var_names[var][c]; 01066 01067 var_title += '\0'; 01068 } 01069 01070 sh.setVarTitle(var_title.c_str(), cast_int<int>(var_title.size())); 01071 } 01072 01073 // Put the informationin the XDR file. 01074 s.header(&sh); // Needs to work for both types of file 01075 01076 // Write the solution vector 01077 libmesh_assert_equal_to (soln.size(), var_names.size()*mesh.n_nodes()); 01078 01079 s.values(&soln[0], mesh.n_nodes()); 01080 } 01081 01082 } // namespace libMesh