moab
|
00001 00017 #ifdef WIN32 00018 #ifdef _DEBUG 00019 // turn off warnings that say they debugging identifier has been truncated 00020 // this warning comes up when using some STL containers 00021 #pragma warning(disable : 4786) 00022 #endif 00023 #endif 00024 00025 #ifndef NETCDF_FILE 00026 # error Attempt to compile WriteSLAC with NetCDF disabled. 00027 #endif 00028 00029 #include "WriteSLAC.hpp" 00030 00031 #include <utility> 00032 #include <algorithm> 00033 #include <time.h> 00034 #include <string> 00035 #include <vector> 00036 #include <stdio.h> 00037 #include <string.h> 00038 #include <iostream> 00039 #include <assert.h> 00040 00041 #include "netcdf.h" 00042 #include "moab/Interface.hpp" 00043 #include "moab/Range.hpp" 00044 #include "moab/CN.hpp" 00045 #include "Internals.hpp" 00046 #include "ExoIIUtil.hpp" 00047 #include "MBTagConventions.hpp" 00048 #include "moab/WriteUtilIface.hpp" 00049 00050 namespace moab { 00051 00052 #define INS_ID(stringvar, prefix, id) \ 00053 sprintf(stringvar, prefix, id) 00054 00055 #define GET_VAR(name, id, dims) \ 00056 { \ 00057 id = -1;\ 00058 int gvfail = nc_inq_varid(ncFile, name, &id); \ 00059 if (NC_NOERR == gvfail) { \ 00060 int ndims;\ 00061 gvfail = nc_inq_varndims(ncFile, id, &ndims);\ 00062 if (NC_NOERR == gvfail) {\ 00063 dims.resize(ndims); \ 00064 gvfail = nc_inq_vardimid(ncFile, id, &dims[0]);}}} 00065 00066 WriterIface* WriteSLAC::factory( Interface* iface ) 00067 { return new WriteSLAC( iface ); } 00068 00069 WriteSLAC::WriteSLAC(Interface *impl) 00070 : mbImpl(impl), ncFile(0), mCurrentMeshHandle(0) 00071 { 00072 assert(impl != NULL); 00073 00074 impl->query_interface( mWriteIface ); 00075 00076 // initialize in case tag_get_handle fails below 00078 int negone = -1, zero = 0; 00079 impl->tag_get_handle(MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, 00080 mMaterialSetTag, MB_TAG_SPARSE|MB_TAG_CREAT, &negone); 00081 00082 impl->tag_get_handle(DIRICHLET_SET_TAG_NAME, 1, MB_TYPE_INTEGER, 00083 mDirichletSetTag, MB_TAG_SPARSE|MB_TAG_CREAT, &negone); 00084 00085 impl->tag_get_handle(NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, 00086 mNeumannSetTag, MB_TAG_SPARSE|MB_TAG_CREAT, &negone); 00087 00088 impl->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, 00089 mGlobalIdTag, MB_TAG_SPARSE|MB_TAG_CREAT, &zero); 00090 00091 int dum_val = -1; 00092 impl->tag_get_handle("__matSetIdTag", 1, MB_TYPE_INTEGER, mMatSetIdTag, 00093 MB_TAG_DENSE|MB_TAG_CREAT, &dum_val); 00094 00095 impl->tag_get_handle("WriteSLAC element mark", 1, MB_TYPE_BIT, mEntityMark, MB_TAG_CREAT); 00096 00097 } 00098 00099 WriteSLAC::~WriteSLAC() 00100 { 00101 mbImpl->release_interface(mWriteIface); 00102 00103 mbImpl->tag_delete(mEntityMark); 00104 } 00105 00106 void WriteSLAC::reset_matset(std::vector<WriteSLAC::MaterialSetData> &matset_info) 00107 { 00108 std::vector<WriteSLAC::MaterialSetData>::iterator iter; 00109 00110 for (iter = matset_info.begin(); iter != matset_info.end(); iter++) 00111 { 00112 delete (*iter).elements; 00113 } 00114 } 00115 00116 ErrorCode WriteSLAC::write_file(const char *file_name, 00117 const bool overwrite, 00118 const FileOptions&, 00119 const EntityHandle *ent_handles, 00120 const int num_sets, 00121 const std::vector<std::string>&, 00122 const Tag*, 00123 int, 00124 int ) 00125 { 00126 assert(0 != mMaterialSetTag && 00127 0 != mNeumannSetTag && 00128 0 != mDirichletSetTag); 00129 00130 // check the file name 00131 if (NULL == strstr(file_name, ".ncdf")) 00132 return MB_FAILURE; 00133 00134 std::vector<EntityHandle> matsets, dirsets, neusets, entities; 00135 00136 fileName = file_name; 00137 00138 // separate into material sets, dirichlet sets, neumann sets 00139 00140 if (num_sets == 0) { 00141 // default to all defined sets 00142 Range this_range; 00143 mbImpl->get_entities_by_type_and_tag(0, MBENTITYSET, &mMaterialSetTag, NULL, 1, this_range); 00144 std::copy(this_range.begin(), this_range.end(), std::back_inserter(matsets)); 00145 this_range.clear(); 00146 mbImpl->get_entities_by_type_and_tag(0, MBENTITYSET, &mDirichletSetTag, NULL, 1, this_range); 00147 std::copy(this_range.begin(), this_range.end(), std::back_inserter(dirsets)); 00148 this_range.clear(); 00149 mbImpl->get_entities_by_type_and_tag(0, MBENTITYSET, &mNeumannSetTag, NULL, 1, this_range); 00150 std::copy(this_range.begin(), this_range.end(), std::back_inserter(neusets)); 00151 } 00152 else { 00153 int dummy; 00154 for (const EntityHandle *iter = ent_handles; iter < ent_handles+num_sets; iter++) 00155 { 00156 if (MB_SUCCESS == mbImpl->tag_get_data(mMaterialSetTag, &(*iter), 1, &dummy)) 00157 matsets.push_back(*iter); 00158 else if (MB_SUCCESS == mbImpl->tag_get_data(mDirichletSetTag, &(*iter), 1, &dummy)) 00159 dirsets.push_back(*iter); 00160 else if (MB_SUCCESS == mbImpl->tag_get_data(mNeumannSetTag, &(*iter), 1, &dummy)) 00161 neusets.push_back(*iter); 00162 } 00163 } 00164 00165 // if there is nothing to write just return. 00166 if (matsets.empty() && dirsets.empty() && neusets.empty()) 00167 return MB_FILE_WRITE_ERROR; 00168 00169 std::vector<WriteSLAC::MaterialSetData> matset_info; 00170 std::vector<WriteSLAC::DirichletSetData> dirset_info; 00171 std::vector<WriteSLAC::NeumannSetData> neuset_info; 00172 00173 MeshInfo mesh_info; 00174 00175 matset_info.clear(); 00176 if(gather_mesh_information(mesh_info, matset_info, neuset_info, dirset_info, 00177 matsets, neusets, dirsets) != MB_SUCCESS) 00178 { 00179 reset_matset(matset_info); 00180 return MB_FAILURE; 00181 } 00182 00183 00184 // try to open the file after gather mesh info succeeds 00185 int fail = nc_create(file_name, overwrite ? NC_CLOBBER : NC_NOCLOBBER, &ncFile); 00186 if (NC_NOERR != fail) { 00187 reset_matset(matset_info); 00188 return MB_FAILURE; 00189 } 00190 00191 if( initialize_file(mesh_info) != MB_SUCCESS) 00192 { 00193 reset_matset(matset_info); 00194 return MB_FAILURE; 00195 } 00196 00197 if( write_nodes(mesh_info.num_nodes, mesh_info.nodes, mesh_info.num_dim) != MB_SUCCESS ) 00198 { 00199 reset_matset(matset_info); 00200 return MB_FAILURE; 00201 } 00202 00203 if( write_matsets(mesh_info, matset_info, neuset_info) ) 00204 { 00205 reset_matset(matset_info); 00206 return MB_FAILURE; 00207 } 00208 00209 fail = nc_close(ncFile); 00210 if (NC_NOERR != fail) 00211 return MB_FAILURE; 00212 00213 return MB_SUCCESS; 00214 } 00215 00216 ErrorCode WriteSLAC::gather_mesh_information(MeshInfo &mesh_info, 00217 std::vector<WriteSLAC::MaterialSetData> &matset_info, 00218 std::vector<WriteSLAC::NeumannSetData> &neuset_info, 00219 std::vector<WriteSLAC::DirichletSetData> &dirset_info, 00220 std::vector<EntityHandle> &matsets, 00221 std::vector<EntityHandle> &neusets, 00222 std::vector<EntityHandle> &dirsets) 00223 { 00224 00225 std::vector<EntityHandle>::iterator vector_iter, end_vector_iter; 00226 00227 mesh_info.num_nodes = 0; 00228 mesh_info.num_elements = 0; 00229 mesh_info.num_matsets = 0; 00230 00231 int id = 0; 00232 00233 vector_iter= matsets.begin(); 00234 end_vector_iter = matsets.end(); 00235 00236 mesh_info.num_matsets = matsets.size(); 00237 00238 std::vector<EntityHandle> parent_meshsets; 00239 00240 // clean out the bits for the element mark 00241 mbImpl->tag_delete(mEntityMark); 00242 mbImpl->tag_get_handle("WriteSLAC element mark", 1, MB_TYPE_BIT, mEntityMark, MB_TAG_CREAT); 00243 00244 int highest_dimension_of_element_matsets = 0; 00245 00246 for(vector_iter = matsets.begin(); vector_iter != matsets.end(); vector_iter++) 00247 { 00248 00249 WriteSLAC::MaterialSetData matset_data; 00250 matset_data.elements = new Range; 00251 00252 //for the purpose of qa records, get the parents of these matsets 00253 if( mbImpl->get_parent_meshsets( *vector_iter, parent_meshsets ) != MB_SUCCESS ) 00254 return MB_FAILURE; 00255 00256 // get all Entity Handles in the mesh set 00257 Range dummy_range; 00258 mbImpl->get_entities_by_handle(*vector_iter, dummy_range, true ); 00259 00260 00261 00262 // wait a minute, we are doing some filtering here that doesn't make sense at this level CJS 00263 00264 // find the dimension of the last entity in this range 00265 Range::iterator entity_iter = dummy_range.end(); 00266 entity_iter = dummy_range.end(); 00267 entity_iter--; 00268 int this_dim = CN::Dimension(TYPE_FROM_HANDLE(*entity_iter)); 00269 entity_iter = dummy_range.begin(); 00270 while (entity_iter != dummy_range.end() && 00271 CN::Dimension(TYPE_FROM_HANDLE(*entity_iter)) != this_dim) 00272 entity_iter++; 00273 00274 if (entity_iter != dummy_range.end()) 00275 std::copy(entity_iter, dummy_range.end(), range_inserter(*(matset_data.elements))); 00276 00277 assert(matset_data.elements->begin() == matset_data.elements->end() || 00278 CN::Dimension(TYPE_FROM_HANDLE(*(matset_data.elements->begin()))) == this_dim); 00279 00280 // get the matset's id 00281 if(mbImpl->tag_get_data(mMaterialSetTag, &(*vector_iter), 1, &id) != MB_SUCCESS ) { 00282 mWriteIface->report_error("Couldn't get matset id from a tag for an element matset."); 00283 return MB_FAILURE; 00284 } 00285 00286 matset_data.id = id; 00287 matset_data.number_attributes = 0; 00288 00289 // iterate through all the elements in the meshset 00290 Range::iterator elem_range_iter, end_elem_range_iter; 00291 elem_range_iter = matset_data.elements->begin(); 00292 end_elem_range_iter = matset_data.elements->end(); 00293 00294 // get the entity type for this matset, verifying that it's the same for all elements 00295 // THIS ASSUMES HANDLES SORT BY TYPE!!! 00296 EntityType entity_type = TYPE_FROM_HANDLE(*elem_range_iter); 00297 end_elem_range_iter--; 00298 if (entity_type != TYPE_FROM_HANDLE(*(end_elem_range_iter++))) { 00299 mWriteIface->report_error("Entities in matset %i not of common type", id); 00300 return MB_FAILURE; 00301 } 00302 00303 int dimension = -1; 00304 if(entity_type == MBQUAD || entity_type == MBTRI) 00305 dimension = 3; // output shells by default 00306 else if(entity_type == MBEDGE) 00307 dimension = 2; 00308 else 00309 dimension = CN::Dimension(entity_type); 00310 00311 if( dimension > highest_dimension_of_element_matsets ) 00312 highest_dimension_of_element_matsets = dimension; 00313 00314 matset_data.moab_type = mbImpl->type_from_handle(*(matset_data.elements->begin())); 00315 if (MBMAXTYPE == matset_data.moab_type) return MB_FAILURE; 00316 00317 std::vector<EntityHandle> tmp_conn; 00318 mbImpl->get_connectivity(&(*(matset_data.elements->begin())), 1, tmp_conn); 00319 matset_data.element_type = 00320 ExoIIUtil::get_element_type_from_num_verts(tmp_conn.size(), entity_type, dimension); 00321 00322 if (matset_data.element_type == EXOII_MAX_ELEM_TYPE) { 00323 mWriteIface->report_error("Element type in matset %i didn't get set correctly", id); 00324 return MB_FAILURE; 00325 } 00326 00327 matset_data.number_nodes_per_element = ExoIIUtil::VerticesPerElement[matset_data.element_type]; 00328 00329 // number of nodes for this matset 00330 matset_data.number_elements = matset_data.elements->size(); 00331 00332 // total number of elements 00333 mesh_info.num_elements += matset_data.number_elements; 00334 00335 // get the nodes for the elements 00336 mWriteIface->gather_nodes_from_elements(*matset_data.elements, mEntityMark, mesh_info.nodes); 00337 00338 if(!neusets.empty()) 00339 { 00340 // if there are neusets, keep track of which elements are being written out 00341 for(Range::iterator iter = matset_data.elements->begin(); 00342 iter != matset_data.elements->end(); ++iter) 00343 { 00344 unsigned char bit = 0x1; 00345 mbImpl->tag_set_data(mEntityMark, &(*iter), 1, &bit); 00346 } 00347 } 00348 00349 matset_info.push_back( matset_data ); 00350 00351 } 00352 00353 00354 //if user hasn't entered dimension, we figure it out 00355 if( mesh_info.num_dim == 0 ) 00356 { 00357 //never want 1 or zero dimensions 00358 if( highest_dimension_of_element_matsets < 2 ) 00359 mesh_info.num_dim = 3; 00360 else 00361 mesh_info.num_dim = highest_dimension_of_element_matsets; 00362 } 00363 00364 Range::iterator range_iter, end_range_iter; 00365 range_iter = mesh_info.nodes.begin(); 00366 end_range_iter = mesh_info.nodes.end(); 00367 00368 mesh_info.num_nodes = mesh_info.nodes.size(); 00369 00370 //------dirsets-------- 00371 00372 vector_iter= dirsets.begin(); 00373 end_vector_iter = dirsets.end(); 00374 00375 for(; vector_iter != end_vector_iter; vector_iter++) 00376 { 00377 00378 WriteSLAC::DirichletSetData dirset_data; 00379 dirset_data.id = 0; 00380 dirset_data.number_nodes = 0; 00381 00382 // get the dirset's id 00383 if(mbImpl->tag_get_data(mDirichletSetTag,&(*vector_iter), 1,&id) != MB_SUCCESS) { 00384 mWriteIface->report_error("Couldn't get id tag for dirset %i", id); 00385 return MB_FAILURE; 00386 } 00387 00388 dirset_data.id = id; 00389 00390 std::vector<EntityHandle> node_vector; 00391 //get the nodes of the dirset that are in mesh_info.nodes 00392 if( mbImpl->get_entities_by_handle(*vector_iter, node_vector, true) != MB_SUCCESS ) { 00393 mWriteIface->report_error("Couldn't get nodes in dirset %i", id); 00394 return MB_FAILURE; 00395 } 00396 00397 std::vector<EntityHandle>::iterator iter, end_iter; 00398 iter = node_vector.begin(); 00399 end_iter= node_vector.end(); 00400 00401 int j=0; 00402 unsigned char node_marked = 0; 00403 ErrorCode result; 00404 for(; iter != end_iter; iter++) 00405 { 00406 if (TYPE_FROM_HANDLE(*iter) != MBVERTEX) continue; 00407 result = mbImpl->tag_get_data(mEntityMark, &(*iter), 1, &node_marked); 00408 if (MB_SUCCESS != result) { 00409 mWriteIface->report_error("Couldn't get mark data."); 00410 return result; 00411 } 00412 00413 if(node_marked == 0x1) dirset_data.nodes.push_back( *iter ); 00414 j++; 00415 } 00416 00417 dirset_data.number_nodes = dirset_data.nodes.size(); 00418 dirset_info.push_back( dirset_data ); 00419 } 00420 00421 //------neusets-------- 00422 vector_iter= neusets.begin(); 00423 end_vector_iter = neusets.end(); 00424 00425 for(; vector_iter != end_vector_iter; vector_iter++) 00426 { 00427 WriteSLAC::NeumannSetData neuset_data; 00428 00429 // get the neuset's id 00430 if(mbImpl->tag_get_data(mNeumannSetTag,&(*vector_iter), 1,&id) != MB_SUCCESS) 00431 return MB_FAILURE; 00432 00433 neuset_data.id = id; 00434 neuset_data.mesh_set_handle = *vector_iter; 00435 00436 //get the sides in two lists, one forward the other reverse; starts with forward sense 00437 // by convention 00438 Range forward_elems, reverse_elems; 00439 if(get_neuset_elems(*vector_iter, 0, forward_elems, reverse_elems) == MB_FAILURE) 00440 return MB_FAILURE; 00441 00442 ErrorCode result = get_valid_sides(forward_elems, 1, neuset_data); 00443 if (MB_SUCCESS != result) { 00444 mWriteIface->report_error("Couldn't get valid sides data."); 00445 return result; 00446 } 00447 result = get_valid_sides(reverse_elems, -1, neuset_data); 00448 if (MB_SUCCESS != result) { 00449 mWriteIface->report_error("Couldn't get valid sides data."); 00450 return result; 00451 } 00452 00453 neuset_data.number_elements = neuset_data.elements.size(); 00454 neuset_info.push_back( neuset_data ); 00455 } 00456 00457 // get information about interior/exterior tets/hexes, and mark matset ids 00458 return gather_interior_exterior(mesh_info, matset_info, neuset_info); 00459 } 00460 00461 ErrorCode WriteSLAC::get_valid_sides(Range &elems, const int sense, 00462 WriteSLAC::NeumannSetData &neuset_data) 00463 { 00464 // this is where we see if underlying element of side set element is included in output 00465 00466 unsigned char element_marked = 0; 00467 ErrorCode result; 00468 for(Range::iterator iter = elems.begin(); iter != elems.end(); iter++) 00469 { 00470 // should insert here if "side" is a quad/tri on a quad/tri mesh 00471 result = mbImpl->tag_get_data(mEntityMark, &(*iter), 1, &element_marked); 00472 if (MB_SUCCESS != result) { 00473 mWriteIface->report_error("Couldn't get mark data."); 00474 return result; 00475 } 00476 00477 if(element_marked == 0x1) 00478 { 00479 neuset_data.elements.push_back( *iter ); 00480 00481 // TJT TODO: the sense should really be # edges + 1or2 00482 neuset_data.side_numbers.push_back((sense == 1 ? 1 : 2)); 00483 } 00484 else //then "side" is probably a quad/tri on a hex/tet mesh 00485 { 00486 std::vector<EntityHandle> parents; 00487 int dimension = CN::Dimension( TYPE_FROM_HANDLE(*iter)); 00488 00489 //get the adjacent parent element of "side" 00490 if( mbImpl->get_adjacencies( &(*iter), 1, dimension+1, false, parents) != MB_SUCCESS ) { 00491 mWriteIface->report_error("Couldn't get adjacencies for neuset."); 00492 return MB_FAILURE; 00493 } 00494 00495 if(!parents.empty()) 00496 { 00497 //make sure the adjacent parent element will be output 00498 for(unsigned int k=0; k<parents.size(); k++) 00499 { 00500 result = mbImpl->tag_get_data(mEntityMark, &(parents[k]), 1, &element_marked); 00501 if (MB_SUCCESS != result) { 00502 mWriteIface->report_error("Couldn't get mark data."); 00503 return result; 00504 } 00505 00506 int side_no, this_sense, this_offset; 00507 if(element_marked == 0x1 && 00508 mbImpl->side_number(parents[k], *iter, side_no, 00509 this_sense, this_offset) == MB_SUCCESS && 00510 this_sense == sense) { 00511 neuset_data.elements.push_back(parents[k]); 00512 neuset_data.side_numbers.push_back(side_no+1); 00513 break; 00514 } 00515 } 00516 } 00517 else 00518 { 00519 mWriteIface->report_error("No parent element exists for element in neuset %i", neuset_data.id); 00520 return MB_FAILURE; 00521 } 00522 } 00523 } 00524 00525 return MB_SUCCESS; 00526 } 00527 00528 ErrorCode WriteSLAC::write_nodes(const int num_nodes, const Range& nodes, const int dimension) 00529 { 00530 //see if should transform coordinates 00531 ErrorCode result; 00532 Tag trans_tag; 00533 result = mbImpl->tag_get_handle( MESH_TRANSFORM_TAG_NAME, 16, MB_TYPE_DOUBLE, trans_tag); 00534 bool transform_needed = true; 00535 if( result == MB_TAG_NOT_FOUND ) 00536 transform_needed = false; 00537 00538 int num_coords_to_fill = transform_needed ? 3 : dimension; 00539 00540 std::vector<double*> coord_arrays(3); 00541 coord_arrays[0] = new double[num_nodes]; 00542 coord_arrays[1] = new double[num_nodes]; 00543 coord_arrays[2] = NULL; 00544 00545 if( num_coords_to_fill == 3 ) 00546 coord_arrays[2] = new double[num_nodes]; 00547 00548 result = mWriteIface->get_node_coords(dimension, num_nodes, nodes, 00549 mGlobalIdTag, 0, coord_arrays); 00550 if(result != MB_SUCCESS) 00551 { 00552 delete [] coord_arrays[0]; 00553 delete [] coord_arrays[1]; 00554 if(coord_arrays[2]) delete [] coord_arrays[2]; 00555 return result; 00556 } 00557 00558 if( transform_needed ) 00559 { 00560 double trans_matrix[16]; 00561 const EntityHandle mesh = 0; 00562 result = mbImpl->tag_get_data( trans_tag, &mesh, 1, trans_matrix ); 00563 if (MB_SUCCESS != result) { 00564 mWriteIface->report_error("Couldn't get transform data."); 00565 return result; 00566 } 00567 00568 for( int i=0; i<num_nodes; i++) 00569 { 00570 00571 double vec1[3]; 00572 double vec2[3]; 00573 00574 vec2[0] = coord_arrays[0][i]; 00575 vec2[1] = coord_arrays[1][i]; 00576 vec2[2] = coord_arrays[2][i]; 00577 00578 for( int row=0; row<3; row++ ) 00579 { 00580 vec1[row] = 0.0; 00581 for( int col = 0; col<3; col++ ) 00582 { 00583 vec1[row] += ( trans_matrix[ (row*4)+col ] * vec2[col] ); 00584 } 00585 } 00586 00587 coord_arrays[0][i] = vec1[0]; 00588 coord_arrays[1][i] = vec1[1]; 00589 coord_arrays[2][i] = vec1[2]; 00590 00591 } 00592 } 00593 00594 00595 // write the nodes 00596 int nc_var = -1; 00597 std::vector<int> dims; 00598 GET_VAR("coords", nc_var, dims); 00599 if (-1 == nc_var) return MB_FAILURE; 00600 size_t start[2] = {0, 0}, count[2] = {static_cast<size_t>(num_nodes), 1}; 00601 int fail = nc_put_vara_double(ncFile, nc_var, start, count, coord_arrays[0]) != 0; 00602 if (NC_NOERR != fail) 00603 return MB_FAILURE; 00604 start[1] = 1; 00605 fail = nc_put_vara_double(ncFile, nc_var, start, count, coord_arrays[1]) != 0; 00606 if (NC_NOERR != fail) 00607 return MB_FAILURE; 00608 start[1] = 2; 00609 fail = nc_put_vara_double(ncFile, nc_var, start, count, coord_arrays[2]) != 0; 00610 if (NC_NOERR != fail) 00611 00612 delete [] coord_arrays[0]; 00613 delete [] coord_arrays[1]; 00614 if(coord_arrays[2]) 00615 delete [] coord_arrays[2]; 00616 00617 return MB_SUCCESS; 00618 00619 } 00620 00621 00622 ErrorCode WriteSLAC::gather_interior_exterior(MeshInfo &mesh_info, 00623 std::vector<WriteSLAC::MaterialSetData> &matset_data, 00624 std::vector<WriteSLAC::NeumannSetData> &neuset_data) 00625 { 00626 // need to assign a tag with the matset id 00627 Tag matset_id_tag; 00628 unsigned int i; 00629 int dum = -1; 00630 ErrorCode result = mbImpl->tag_get_handle("__matset_id", 4, MB_TYPE_INTEGER, matset_id_tag, MB_TAG_DENSE|MB_TAG_CREAT, &dum); 00631 if (MB_SUCCESS != result) return result; 00632 00633 Range::iterator rit; 00634 mesh_info.num_int_hexes = mesh_info.num_int_tets = 0; 00635 00636 for(i=0; i< matset_data.size(); i++) 00637 { 00638 WriteSLAC::MaterialSetData matset = matset_data[i]; 00639 if (matset.moab_type == MBHEX) 00640 mesh_info.num_int_hexes += matset.elements->size(); 00641 00642 else if (matset.moab_type == MBTET) 00643 mesh_info.num_int_tets += matset.elements->size(); 00644 else { 00645 std::cout << "WriteSLAC doesn't support elements of type " 00646 << CN::EntityTypeName(matset.moab_type) << std::endl; 00647 continue; 00648 } 00649 00650 for (rit = matset.elements->begin(); rit != matset.elements->end(); rit++) { 00651 result = mbImpl->tag_set_data(mMatSetIdTag, &(*rit), 1, &(matset.id)); 00652 if (MB_SUCCESS != result) return result; 00653 } 00654 } 00655 00656 // now go through the neumann sets, pulling out the hexes with faces on the 00657 // boundary 00658 std::vector<EntityHandle>::iterator vit; 00659 for(i=0; i< neuset_data.size(); i++) 00660 { 00661 WriteSLAC::NeumannSetData neuset = neuset_data[i]; 00662 for (vit = neuset.elements.begin(); vit != neuset.elements.end(); vit++) { 00663 if (TYPE_FROM_HANDLE(*vit) == MBHEX) mesh_info.bdy_hexes.insert(*vit); 00664 else if (TYPE_FROM_HANDLE(*vit) == MBTET) mesh_info.bdy_tets.insert(*vit); 00665 } 00666 } 00667 00668 // now we have the number of bdy hexes and tets, we know how many interior ones 00669 // there are too 00670 mesh_info.num_int_hexes -= mesh_info.bdy_hexes.size(); 00671 mesh_info.num_int_tets -= mesh_info.bdy_tets.size(); 00672 00673 return MB_SUCCESS; 00674 } 00675 00676 00677 ErrorCode WriteSLAC::write_matsets(MeshInfo &mesh_info, 00678 std::vector<WriteSLAC::MaterialSetData> &matset_data, 00679 std::vector<WriteSLAC::NeumannSetData> &neuset_data) 00680 { 00681 00682 unsigned int i; 00683 std::vector<int> connect; 00684 const EntityHandle *connecth; 00685 int num_connecth; 00686 ErrorCode result; 00687 00688 // first write the interior hexes 00689 int hex_conn = -1; 00690 std::vector<int> dims; 00691 if (mesh_info.bdy_hexes.size() != 0 || mesh_info.num_int_hexes != 0) { 00692 GET_VAR("hexahedron_interior", hex_conn, dims); 00693 if (-1 == hex_conn) return MB_FAILURE; 00694 } 00695 connect.reserve(13); 00696 Range::iterator rit; 00697 00698 int elem_num = 0; 00699 WriteSLAC::MaterialSetData matset; 00700 size_t start[2] = {0, 0}, count[2] = {1, 1}; 00701 int fail; 00702 for (i = 0; i < matset_data.size(); i++) { 00703 matset = matset_data[i]; 00704 if (matset.moab_type != MBHEX) continue; 00705 00706 int id = matset.id; 00707 connect[0] = id; 00708 00709 for (rit = matset.elements->begin(); rit != matset.elements->end(); rit++) { 00710 // skip if it's on the bdy 00711 if (mesh_info.bdy_hexes.find(*rit) != mesh_info.bdy_hexes.end()) continue; 00712 00713 // get the connectivity of this element 00714 result = mbImpl->get_connectivity(*rit, connecth, num_connecth); 00715 if (MB_SUCCESS != result) return result; 00716 00717 // get the vertex ids 00718 result = mbImpl->tag_get_data(mGlobalIdTag, connecth, num_connecth, &connect[1]); 00719 if (MB_SUCCESS != result) return result; 00720 00721 // put the variable at the right position 00722 start[0] = elem_num++; 00723 count[1] = 9; 00724 00725 // write the data 00726 fail = nc_put_vara_int(ncFile, hex_conn, start, count, &connect[0]); 00727 if(NC_NOERR != fail) 00728 return MB_FAILURE; 00729 } 00730 } 00731 00732 int tet_conn = -1; 00733 if (mesh_info.bdy_tets.size() != 0 || mesh_info.num_int_tets != 0) { 00734 GET_VAR("tetrahedron_interior", tet_conn, dims); 00735 if (-1 == tet_conn) return MB_FAILURE; 00736 } 00737 00738 // now the interior tets 00739 elem_num = 0; 00740 for (i = 0; i < matset_data.size(); i++) { 00741 matset = matset_data[i]; 00742 if (matset.moab_type != MBTET) continue; 00743 00744 int id = matset.id; 00745 connect[0] = id; 00746 elem_num = 0; 00747 for (rit = matset.elements->begin(); rit != matset.elements->end(); rit++) { 00748 // skip if it's on the bdy 00749 if (mesh_info.bdy_tets.find(*rit) != mesh_info.bdy_tets.end()) continue; 00750 00751 // get the connectivity of this element 00752 result = mbImpl->get_connectivity(*rit, connecth, num_connecth); 00753 if (MB_SUCCESS != result) return result; 00754 00755 // get the vertex ids 00756 result = mbImpl->tag_get_data(mGlobalIdTag, connecth, num_connecth, &connect[1]); 00757 if (MB_SUCCESS != result) return result; 00758 00759 // put the variable at the right position 00760 start[0] = elem_num++; 00761 count[1] = 5; 00762 fail = nc_put_vara_int(ncFile, tet_conn, start, count, &connect[0]); 00763 // write the data 00764 if(NC_NOERR != fail) 00765 return MB_FAILURE; 00766 } 00767 } 00768 00769 // now the exterior hexes 00770 if (mesh_info.bdy_hexes.size() != 0) { 00771 hex_conn = -1; 00772 GET_VAR("hexahedron_exterior", hex_conn, dims); 00773 if (-1 == hex_conn) return MB_FAILURE; 00774 00775 connect.reserve(15); 00776 elem_num = 0; 00777 00778 // write the elements 00779 for (rit = mesh_info.bdy_hexes.begin(); rit != mesh_info.bdy_hexes.end(); rit++) { 00780 00781 // get the material set for this hex 00782 result = mbImpl->tag_get_data(mMatSetIdTag, &(*rit), 1, &connect[0]); 00783 if (MB_SUCCESS != result) return result; 00784 00785 // get the connectivity of this element 00786 result = mbImpl->get_connectivity(*rit, connecth, num_connecth); 00787 if (MB_SUCCESS != result) return result; 00788 00789 // get the vertex ids 00790 result = mbImpl->tag_get_data(mGlobalIdTag, connecth, num_connecth, &connect[1]); 00791 if (MB_SUCCESS != result) return result; 00792 00793 // preset side numbers 00794 for (i = 9; i < 15; i++) 00795 connect[i] = -1; 00796 00797 // now write the side numbers 00798 for (i = 0; i < neuset_data.size(); i++) { 00799 std::vector<EntityHandle>::iterator vit = 00800 std::find(neuset_data[i].elements.begin(), neuset_data[i].elements.end(), *rit); 00801 while (vit != neuset_data[i].elements.end()) { 00802 // have a side - get the side # and put in connect array 00803 int side_no = neuset_data[i].side_numbers[vit-neuset_data[i].elements.begin()]; 00804 connect[9+side_no] = neuset_data[i].id; 00805 vit++; 00806 vit = std::find(vit, neuset_data[i].elements.end(), *rit); 00807 } 00808 } 00809 00810 // put the variable at the right position 00811 start[0] = elem_num++; 00812 count[1] = 15; 00813 fail = nc_put_vara_int(ncFile, hex_conn, start, count, &connect[0]); 00814 // write the data 00815 if(NC_NOERR != fail) 00816 return MB_FAILURE; 00817 } 00818 } 00819 00820 // now the exterior tets 00821 if (mesh_info.bdy_tets.size() != 0) { 00822 tet_conn = -1; 00823 GET_VAR("tetrahedron_exterior", tet_conn, dims); 00824 if (-1 == tet_conn) return MB_FAILURE; 00825 00826 connect.reserve(9); 00827 elem_num = 0; 00828 00829 // write the elements 00830 for (rit = mesh_info.bdy_tets.begin(); rit != mesh_info.bdy_tets.end(); rit++) { 00831 00832 // get the material set for this tet 00833 result = mbImpl->tag_get_data(mMatSetIdTag, &(*rit), 1, &connect[0]); 00834 if (MB_SUCCESS != result) return result; 00835 00836 // get the connectivity of this element 00837 result = mbImpl->get_connectivity(*rit, connecth, num_connecth); 00838 if (MB_SUCCESS != result) return result; 00839 00840 // get the vertex ids 00841 result = mbImpl->tag_get_data(mGlobalIdTag, connecth, num_connecth, &connect[1]); 00842 if (MB_SUCCESS != result) return result; 00843 00844 // preset side numbers 00845 for (i = 5; i < 9; i++) 00846 connect[i] = -1; 00847 00848 // now write the side numbers 00849 for (i = 0; i < neuset_data.size(); i++) { 00850 std::vector<EntityHandle>::iterator vit = 00851 std::find(neuset_data[i].elements.begin(), neuset_data[i].elements.end(), *rit); 00852 while (vit != neuset_data[i].elements.end()) { 00853 // have a side - get the side # and put in connect array 00854 int side_no = neuset_data[i].side_numbers[vit-neuset_data[i].elements.begin()]; 00855 connect[5+side_no] = neuset_data[i].id; 00856 vit++; 00857 vit = std::find(vit, neuset_data[i].elements.end(), *rit); 00858 } 00859 } 00860 00861 // put the variable at the right position 00862 start[0] = elem_num++; 00863 count[1] = 9; 00864 fail = nc_put_vara_int(ncFile, tet_conn, start, count, &connect[0]); 00865 // write the data 00866 if(NC_NOERR != fail) 00867 return MB_FAILURE; 00868 } 00869 } 00870 00871 return MB_SUCCESS; 00872 } 00873 00874 ErrorCode WriteSLAC::initialize_file(MeshInfo &mesh_info) 00875 { 00876 // perform the initializations 00877 00878 int coord_size = -1, ncoords = -1; 00879 // initialization to avoid warnings on linux 00880 int hexinterior = -1, hexinteriorsize, hexexterior = -1, hexexteriorsize = -1; 00881 int tetinterior = -1, tetinteriorsize, tetexterior = -1, tetexteriorsize = -1; 00882 00883 if (nc_def_dim(ncFile, "coord_size", (size_t)mesh_info.num_dim, &coord_size) != NC_NOERR) 00884 { 00885 mWriteIface->report_error("WriteSLAC: failed to define number of dimensions"); 00886 return (MB_FAILURE); 00887 } 00888 00889 if (nc_def_dim(ncFile, "ncoords", (size_t)mesh_info.num_nodes, &ncoords) != NC_NOERR) 00890 { 00891 mWriteIface->report_error("WriteSLAC: failed to define number of nodes"); 00892 return (MB_FAILURE); 00893 } 00894 00895 if (0 != mesh_info.num_int_hexes && 00896 nc_def_dim(ncFile, "hexinterior", (size_t)mesh_info.num_int_hexes, &hexinterior) != NC_NOERR) 00897 { 00898 mWriteIface->report_error("WriteSLAC: failed to define number of interior hex elements"); 00899 return (MB_FAILURE); 00900 } 00901 00902 if (nc_def_dim(ncFile, "hexinteriorsize", (size_t)9, &hexinteriorsize) != NC_NOERR) 00903 { 00904 mWriteIface->report_error("WriteSLAC: failed to define interior hex element size"); 00905 return (MB_FAILURE); 00906 } 00907 00908 if (0 != mesh_info.bdy_hexes.size() && 00909 nc_def_dim(ncFile, "hexexterior", (size_t)mesh_info.bdy_hexes.size(), &hexexterior) != NC_NOERR) 00910 { 00911 mWriteIface->report_error("WriteSLAC: failed to define number of exterior hex elements"); 00912 return (MB_FAILURE); 00913 } 00914 00915 if (nc_def_dim(ncFile, "hexexteriorsize", (size_t)15, &hexexteriorsize) != NC_NOERR) 00916 { 00917 mWriteIface->report_error("WriteSLAC: failed to define exterior hex element size"); 00918 return (MB_FAILURE); 00919 } 00920 00921 if (0 != mesh_info.num_int_tets && 00922 nc_def_dim(ncFile, "tetinterior", (size_t)mesh_info.num_int_tets, &tetinterior) != NC_NOERR) 00923 { 00924 mWriteIface->report_error("WriteSLAC: failed to define number of interior tet elements"); 00925 return (MB_FAILURE); 00926 } 00927 00928 if (nc_def_dim(ncFile, "tetinteriorsize", (size_t)5, &tetinteriorsize) != NC_NOERR) 00929 { 00930 mWriteIface->report_error("WriteSLAC: failed to define interior tet element size"); 00931 return (MB_FAILURE); 00932 } 00933 00934 if (0 != mesh_info.bdy_tets.size() && 00935 nc_def_dim(ncFile, "tetexterior", (size_t)mesh_info.bdy_tets.size(), &tetexterior) != NC_NOERR) 00936 { 00937 mWriteIface->report_error("WriteSLAC: failed to define number of exterior tet elements"); 00938 return (MB_FAILURE); 00939 } 00940 00941 if (nc_def_dim(ncFile, "tetexteriorsize", (size_t)9, &tetexteriorsize) != NC_NOERR) 00942 { 00943 mWriteIface->report_error("WriteSLAC: failed to define exterior tet element size"); 00944 return (MB_FAILURE); 00945 } 00946 00947 /* ...and some variables */ 00948 00949 int dims[2]; 00950 dims[0] = hexinterior; 00951 dims[1] = hexinteriorsize; 00952 int dum_var; 00953 if (0 != mesh_info.num_int_hexes && 00954 NC_NOERR != nc_def_var(ncFile, "hexahedron_interior", NC_LONG, 2, dims, &dum_var)) 00955 { 00956 mWriteIface->report_error("WriteSLAC: failed to create connectivity array for interior hexes."); 00957 return (MB_FAILURE); 00958 } 00959 00960 dims[0] = hexexterior; 00961 dims[1] = hexexteriorsize; 00962 if (0 != mesh_info.bdy_hexes.size() && 00963 NC_NOERR != nc_def_var(ncFile, "hexahedron_exterior", NC_LONG, 2, dims, &dum_var)) 00964 { 00965 mWriteIface->report_error("WriteSLAC: failed to create connectivity array for exterior hexes."); 00966 return (MB_FAILURE); 00967 } 00968 00969 dims[0] = tetinterior; 00970 dims[1] = tetinteriorsize; 00971 if (0 != mesh_info.num_int_tets && 00972 NC_NOERR != nc_def_var(ncFile, "tetrahedron_exterior", NC_LONG, 2, dims, &dum_var)) 00973 { 00974 mWriteIface->report_error("WriteSLAC: failed to create connectivity array for interior tets."); 00975 return (MB_FAILURE); 00976 } 00977 00978 dims[0] = tetexterior; 00979 dims[1] = tetexteriorsize; 00980 if (0 != mesh_info.bdy_tets.size() && 00981 NC_NOERR != nc_def_var(ncFile, "tetrahedron_exterior", NC_LONG, 2, dims, &dum_var)) 00982 { 00983 mWriteIface->report_error("WriteSLAC: failed to create connectivity array for exterior tets."); 00984 return (MB_FAILURE); 00985 } 00986 00987 /* node coordinate arrays: */ 00988 00989 dims[0] = ncoords; 00990 dims[1] = coord_size; 00991 if (NC_NOERR != nc_def_var(ncFile, "coords", NC_DOUBLE, 2, dims, &dum_var)) 00992 { 00993 mWriteIface->report_error("WriteSLAC: failed to define node coordinate array"); 00994 return (MB_FAILURE); 00995 } 00996 00997 return MB_SUCCESS; 00998 } 00999 01000 01001 ErrorCode WriteSLAC::open_file(const char* filename) 01002 { 01003 // not a valid filname 01004 if(strlen((const char*)filename) == 0) 01005 { 01006 mWriteIface->report_error("Output filename not specified"); 01007 return MB_FAILURE; 01008 } 01009 01010 int fail = nc_create(filename, NC_CLOBBER, &ncFile); 01011 // file couldn't be opened 01012 if(NC_NOERR != fail) 01013 { 01014 mWriteIface->report_error("Cannot open %s", filename); 01015 return MB_FAILURE; 01016 } 01017 return MB_SUCCESS; 01018 } 01019 01020 ErrorCode WriteSLAC::get_neuset_elems(EntityHandle neuset, int current_sense, 01021 Range &forward_elems, Range &reverse_elems) 01022 { 01023 Range ss_elems, ss_meshsets; 01024 01025 // get the sense tag; don't need to check return, might be an error if the tag 01026 // hasn't been created yet 01027 Tag sense_tag = 0; 01028 mbImpl->tag_get_handle("SENSE", 1, MB_TYPE_INTEGER, sense_tag); 01029 01030 // get the entities in this set 01031 ErrorCode result = mbImpl->get_entities_by_handle(neuset, ss_elems, true); 01032 if (MB_FAILURE == result) return result; 01033 01034 // now remove the meshsets into the ss_meshsets; first find the first meshset, 01035 Range::iterator range_iter = ss_elems.begin(); 01036 while (TYPE_FROM_HANDLE(*range_iter) != MBENTITYSET && range_iter != ss_elems.end()) 01037 range_iter++; 01038 01039 // then, if there are some, copy them into ss_meshsets and erase from ss_elems 01040 if (range_iter != ss_elems.end()) { 01041 std::copy(range_iter, ss_elems.end(), range_inserter(ss_meshsets)); 01042 ss_elems.erase(range_iter, ss_elems.end()); 01043 } 01044 01045 01046 // ok, for the elements, check the sense of this set and copy into the right range 01047 // (if the sense is 0, copy into both ranges) 01048 01049 // need to step forward on list until we reach the right dimension 01050 Range::iterator dum_it = ss_elems.end(); 01051 dum_it--; 01052 int target_dim = CN::Dimension(TYPE_FROM_HANDLE(*dum_it)); 01053 dum_it = ss_elems.begin(); 01054 while (target_dim != CN::Dimension(TYPE_FROM_HANDLE(*dum_it)) && 01055 dum_it != ss_elems.end()) 01056 dum_it++; 01057 01058 if (current_sense == 1 || current_sense == 0) 01059 std::copy(dum_it, ss_elems.end(), range_inserter(forward_elems)); 01060 if (current_sense == -1 || current_sense == 0) 01061 std::copy(dum_it, ss_elems.end(), range_inserter(reverse_elems)); 01062 01063 // now loop over the contained meshsets, getting the sense of those and calling this 01064 // function recursively 01065 for (range_iter = ss_meshsets.begin(); range_iter != ss_meshsets.end(); range_iter++) { 01066 01067 // first get the sense; if it's not there, by convention it's forward 01068 int this_sense; 01069 if (0 == sense_tag || 01070 MB_FAILURE == mbImpl->tag_get_data(sense_tag, &(*range_iter), 1, &this_sense)) 01071 this_sense = 1; 01072 01073 // now get all the entities on this meshset, with the proper (possibly reversed) sense 01074 get_neuset_elems(*range_iter, this_sense*current_sense, 01075 forward_elems, reverse_elems); 01076 } 01077 01078 return result; 01079 } 01080 01081 } // namespace moab 01082 01083