moab
|
00001 /* 00002 * CCMIO file structure 00003 * 00004 * Root 00005 * State(kCCMIOState) 00006 * Processor* 00007 * VerticesID 00008 * TopologyID 00009 * InitialID 00010 * SolutionID 00011 * Vertices* 00012 * ->WriteVerticesx, WriteMap 00013 * Topology* 00014 * Boundary faces*(kCCMIOBoundaryFaces) 00015 * ->WriteFaces, WriteFaceCells, WriteMap 00016 * Internal faces(kCCMIOInternalFaces) 00017 * Cells (kCCMIOCells) 00018 * ->WriteCells (mapID), WriteMap, WriteCells 00019 * Solution 00020 * Phase 00021 * Field 00022 * FieldData 00023 * Problem(kCCMIOProblemDescription) 00024 * CellType* (kCCMIOCellType) 00025 * Index (GetEntityIndex), MaterialId(WriteOpti), MaterialType(WriteOptstr), 00026 * PorosityId(WriteOpti), SpinId(WriteOpti), GroupId(WriteOpti) 00027 * 00028 * MaterialType (CCMIOWriteOptstr in readexample) 00029 * constants (see readexample) 00030 * lagrangian data (CCMIOWriteLagrangianData) 00031 * vertices label (CCMIOEntityDescription) 00032 * restart info: char solver[], iteratoins, time, char timeUnits[], angle 00033 * (CCMIOWriteRestartInfo, kCCMIORestartData), reference data? 00034 * phase: 00035 * field: char name[], dims, CCMIODataType datatype, char units[] 00036 * dims = kCCMIOScalar (CCMIOWriteFieldDataf), 00037 * kCCMIOVector (CCMIOWriteMultiDimensionalFieldData), 00038 * kCCMIOTensor 00039 * MonitoringSets: num, name (CellSet, VertexSet, BoundarySet, BlockSet, SplineSet, CoupleSet) 00040 * CCMIOGetProstarSet, CCMIOWriteOpt1i, 00041 */ 00042 00043 #ifdef WIN32 00044 #ifdef _DEBUG 00045 // turn off warnings that say they debugging identifier has been truncated 00046 // this warning comes up when using some STL containers 00047 #pragma warning(disable : 4786) 00048 #endif 00049 #endif 00050 00051 00052 #include "WriteCCMIO.hpp" 00053 #include "ccmio.h" 00054 #include "ccmioutility.h" 00055 #include "ccmiocore.h" 00056 #include <utility> 00057 #include <algorithm> 00058 #include <time.h> 00059 #include <string> 00060 #include <vector> 00061 #include <stdio.h> 00062 #include <iostream> 00063 #include <algorithm> 00064 #include <sstream> 00065 00066 #include "moab/Interface.hpp" 00067 #include "moab/Range.hpp" 00068 #include "moab/CN.hpp" 00069 #include "moab/Skinner.hpp" 00070 #include "assert.h" 00071 #include "Internals.hpp" 00072 #include "ExoIIUtil.hpp" 00073 #include "MBTagConventions.hpp" 00074 #ifdef USE_MPI 00075 #include "MBParallelConventions.h" 00076 #endif 00077 #include "moab/WriteUtilIface.hpp" 00078 00079 namespace moab { 00080 00081 static char const kStateName[] = "default"; 00082 00083 static const int ccm_types[] = { 00084 1, // MBVERTEX 00085 2, // MBEDGE 00086 -1, // MBTRI 00087 -1, // MBQUAD 00088 -1, // MBPOLYGON 00089 13, // MBTET 00090 14, // MBPYRAMID 00091 12, // MBPRISM 00092 -1, // MBKNIFE 00093 11, // MBHEX 00094 255 // MBPOLYHEDRON 00095 }; 00096 00097 #define INS_ID(stringvar, prefix, id) \ 00098 sprintf(stringvar, prefix, id) 00099 00100 #define CHKERR(a, b) \ 00101 {if (MB_SUCCESS != a) {if (b) mWriteIface->report_error(b); return a;}} 00102 00103 #define CHKCCMERR(a, b) \ 00104 {if (kCCMIONoErr != a) {if (b) mWriteIface->report_error(b); return MB_FAILURE;}} 00105 00106 WriterIface* WriteCCMIO::factory( Interface* iface ) 00107 { return new WriteCCMIO( iface ); } 00108 00109 WriteCCMIO::WriteCCMIO(Interface *impl) 00110 : mbImpl(impl), mCurrentMeshHandle(0), mNameTag(0), mMaterialIdTag(0), 00111 mMaterialTypeTag(0), 00112 mRadiationTag(0), mPorosityIdTag(0), mSpinIdTag(0), mGroupIdTag(0), mColorIdxTag(0), 00113 mProcessorIdTag(0), mLightMaterialTag(0), mFreeSurfaceMaterialTag(0), 00114 mThicknessTag(0), mProstarRegionNumberTag(0), mBoundaryTypeTag(0), mCreatingProgramTag(0), 00115 mWholeMesh(false) 00116 { 00117 assert(impl != NULL); 00118 00119 impl->query_interface( mWriteIface ); 00120 00121 // initialize in case tag_get_handle fails below 00123 int zero = 0, negone = -1; 00124 impl->tag_get_handle(MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, 00125 mMaterialSetTag, MB_TAG_SPARSE|MB_TAG_CREAT, &negone); 00126 00127 impl->tag_get_handle(DIRICHLET_SET_TAG_NAME, 1, MB_TYPE_INTEGER, 00128 mDirichletSetTag, MB_TAG_SPARSE|MB_TAG_CREAT, &negone); 00129 00130 impl->tag_get_handle(NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, 00131 mNeumannSetTag, MB_TAG_SPARSE|MB_TAG_CREAT, &negone); 00132 00133 impl->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, 00134 mGlobalIdTag, MB_TAG_SPARSE|MB_TAG_CREAT, &zero); 00135 00136 #ifdef USE_MPI 00137 impl->tag_get_handle(PARALLEL_PARTITION_TAG_NAME, 00138 1, MB_TYPE_INTEGER, mPartitionSetTag, 00139 MB_TAG_SPARSE); 00140 // no need to check result, if it's not there, we don't create one 00141 #endif 00142 00143 int dum_val_array[] = {-1, -1, -1, -1}; 00144 impl->tag_get_handle(HAS_MID_NODES_TAG_NAME, 4, MB_TYPE_INTEGER, 00145 mHasMidNodesTag, MB_TAG_SPARSE|MB_TAG_CREAT, dum_val_array); 00146 00147 impl->tag_get_handle("__WriteCCMIO element mark", 1, MB_TYPE_BIT, mEntityMark, MB_TAG_CREAT); 00148 00149 // don't need to check return of following, since it doesn't matter if there isn't one 00150 mbImpl->tag_get_handle(NAME_TAG_NAME, NAME_TAG_SIZE, MB_TYPE_OPAQUE, mNameTag); 00151 } 00152 00153 WriteCCMIO::~WriteCCMIO() 00154 { 00155 mbImpl->release_interface(mWriteIface); 00156 00157 mbImpl->tag_delete(mEntityMark); 00158 00159 } 00160 00161 ErrorCode WriteCCMIO::write_file(const char *file_name, 00162 const bool overwrite, 00163 const FileOptions& , 00164 const EntityHandle *ent_handles, 00165 const int num_sets, 00166 const std::vector<std::string>&, 00167 const Tag* , 00168 int , 00169 int ) 00170 { 00171 assert(0 != mMaterialSetTag && 00172 0 != mNeumannSetTag && 00173 0 != mDirichletSetTag); 00174 00175 ErrorCode result; 00176 00177 // check overwrite flag and file existence 00178 if (!overwrite) { 00179 FILE *file = fopen(file_name, "r"); 00180 if (file) { 00181 fclose(file); 00182 result = MB_FILE_WRITE_ERROR; 00183 CHKERR(result, "File exists but overwrite set to false."); 00184 } 00185 } 00186 00187 mDimension = 3; 00188 00189 std::vector<EntityHandle> matsets, dirsets, neusets, partsets, entities; 00190 00191 // separate into material, dirichlet, neumann, partition sets 00192 result = get_sets(ent_handles, num_sets, matsets, 00193 dirsets, neusets, partsets); 00194 CHKERR(result, "Failed to get material/etc. sets."); 00195 00196 // if entity handles were input but didn't contain matsets, return error 00197 if (ent_handles && matsets.empty()) { 00198 result = MB_FILE_WRITE_ERROR; 00199 CHKERR(result, "Sets input to write but no material sets found."); 00200 } 00201 00202 // otherwise, if no matsets, use root set 00203 if (matsets.empty()) matsets.push_back(0); 00204 00205 std::vector<MaterialSetData> matset_info; 00206 Range all_verts; 00207 result = gather_matset_info(matsets, matset_info, all_verts); 00208 CHKERR(result, "gathering matset info failed."); 00209 00210 // assign vertex gids 00211 result = mWriteIface->assign_ids(all_verts, mGlobalIdTag, 1); 00212 CHKERR(result, "Failed to assign vertex global ids."); 00213 00214 // some CCMIO descriptors 00215 CCMIOID rootID, topologyID, stateID, problemID, verticesID, processorID; 00216 00217 // try to open the file and establish state 00218 result = open_file(file_name, overwrite, rootID); 00219 CHKERR(result, "Couldn't open file or create state."); 00220 00221 result = create_ccmio_structure(rootID, stateID, processorID); 00222 CHKERR(result, "Problem creating CCMIO file structure."); 00223 00224 result = write_nodes(rootID, all_verts, mDimension, verticesID); 00225 CHKERR(result, "write_nodes failed."); 00226 00227 std::vector<NeumannSetData> neuset_info; 00228 result = gather_neuset_info(neusets, neuset_info); 00229 CHKERR(result, "Failed to get neumann set info."); 00230 00231 result = write_cells_and_faces(rootID, matset_info, neuset_info, all_verts, topologyID); 00232 CHKERR(result, "write_cells_and_faces failed."); 00233 00234 result = write_problem_description(rootID, stateID, problemID, processorID, 00235 matset_info, neuset_info); 00236 CHKERR(result, "write_problem_description failed."); 00237 00238 result = write_solution_data(); 00239 CHKERR(result, "trouble writing solution data."); 00240 00241 result = write_processor(processorID, verticesID, topologyID); 00242 CHKERR(result, "trouble writing processor."); 00243 00244 result = close_and_compress(file_name, rootID); 00245 CHKERR(result, "close or compress failed."); 00246 00247 return MB_SUCCESS; 00248 } 00249 00250 ErrorCode WriteCCMIO::write_solution_data() 00251 { 00252 // for now, no solution (tag) data 00253 return MB_SUCCESS; 00254 } 00255 00256 ErrorCode WriteCCMIO::write_processor(CCMIOID processorID, CCMIOID verticesID, CCMIOID topologyID) 00257 { 00258 CCMIOError error = kCCMIONoErr; 00259 00260 // Now we have the mesh (vertices and topology) and the post data written. 00261 // Since we now have their IDs, we can write out the processor information. 00262 CCMIOWriteProcessor(&error, processorID, NULL, &verticesID, NULL, &topologyID, 00263 NULL, NULL, NULL, NULL); 00264 CHKCCMERR(error, "Problem writing CCMIO processor."); 00265 00266 return MB_SUCCESS; 00267 } 00268 00269 ErrorCode WriteCCMIO::create_ccmio_structure(CCMIOID rootID, CCMIOID &stateID, 00270 CCMIOID &processorID) 00271 { 00272 // create problem state and other CCMIO nodes under it 00273 CCMIOError error = kCCMIONoErr; 00274 00275 // Create a new state (or re-use an existing one). 00276 if (CCMIOGetState(NULL, rootID, kStateName, NULL, &stateID) != kCCMIONoErr) 00277 CCMIONewState(&error, rootID, kStateName, NULL, NULL, &stateID); 00278 CHKCCMERR(error, "Trouble creating state."); 00279 00280 // Create or get an old processor for this state 00281 CCMIOSize_t i = CCMIOSIZEC(0); 00282 if (CCMIONextEntity(NULL, stateID, kCCMIOProcessor, &i, &processorID) != kCCMIONoErr) 00283 CCMIONewEntity(&error, stateID, kCCMIOProcessor, NULL, &processorID); 00284 00285 // Get rid of any data that may be in this processor (if the state was 00286 // not new). 00287 else 00288 CCMIOClearProcessor(&error, stateID, processorID, TRUE, TRUE, TRUE, TRUE, TRUE); 00289 00290 /* 00291 00292 00293 // for (; i < CCMIOSIZEC(partsets.size()); i++) { 00294 CCMIOSize_t id = CCMIOSIZEC(0); 00295 if (CCMIONextEntity(NULL, stateID, kCCMIOProcessor, &id, &processorID) != kCCMIONoErr) 00296 CCMIONewEntity(&error, stateID, kCCMIOProcessor, NULL, &processorID); 00297 CHKCCMERR(error, "Trouble creating processor node."); 00298 */ 00299 return MB_SUCCESS; 00300 } 00301 00302 ErrorCode WriteCCMIO::close_and_compress(const char *, CCMIOID rootID) 00303 { 00304 CCMIOError error = kCCMIONoErr; 00305 CCMIOCloseFile(&error, rootID); 00306 CHKCCMERR(error, "File close failed."); 00307 00308 // The CCMIO library uses ADF to store the actual data. Unfortunately, 00309 // ADF leaks disk space; deleting a node does not recover all the disk 00310 // space. Now that everything is successfully written it might be useful 00311 // to call CCMIOCompress() here to ensure that the file is as small as 00312 // possible. Please see the Core API documentation for caveats on its 00313 // usage. 00314 // CCMIOCompress(&error, const_cast<char*>(filename)); 00315 // CHKCCMERR(error, "Error compressing file."); 00316 00317 return MB_SUCCESS; 00318 } 00319 00320 ErrorCode WriteCCMIO::open_file(const char *filename, bool , CCMIOID &rootID) 00321 { 00322 CCMIOError error = kCCMIONoErr; 00323 CCMIOOpenFile(&error, filename, kCCMIOWrite, &rootID); 00324 CHKCCMERR(error, "Cannot open file."); 00325 00326 return MB_SUCCESS; 00327 } 00328 00329 ErrorCode WriteCCMIO::get_sets(const EntityHandle *ent_handles, 00330 int num_sets, 00331 std::vector<EntityHandle> &matsets, 00332 std::vector<EntityHandle> &dirsets, 00333 std::vector<EntityHandle> &neusets, 00334 std::vector<EntityHandle> &partsets) 00335 { 00336 if (num_sets == 0) { 00337 // default to all defined sets 00338 Range this_range; 00339 mbImpl->get_entities_by_type_and_tag(0, MBENTITYSET, &mMaterialSetTag, NULL, 1, this_range); 00340 std::copy(this_range.begin(), this_range.end(), std::back_inserter(matsets)); 00341 this_range.clear(); 00342 mbImpl->get_entities_by_type_and_tag(0, MBENTITYSET, &mDirichletSetTag, NULL, 1, this_range); 00343 std::copy(this_range.begin(), this_range.end(), std::back_inserter(dirsets)); 00344 this_range.clear(); 00345 mbImpl->get_entities_by_type_and_tag(0, MBENTITYSET, &mNeumannSetTag, NULL, 1, this_range); 00346 std::copy(this_range.begin(), this_range.end(), std::back_inserter(neusets)); 00347 if (mPartitionSetTag) { 00348 this_range.clear(); 00349 mbImpl->get_entities_by_type_and_tag(0, MBENTITYSET, &mPartitionSetTag, NULL, 1, this_range); 00350 std::copy(this_range.begin(), this_range.end(), std::back_inserter(partsets)); 00351 } 00352 } 00353 00354 else { 00355 int dummy; 00356 for (const EntityHandle *iter = ent_handles; iter < ent_handles+num_sets; iter++) 00357 { 00358 if (MB_SUCCESS == mbImpl->tag_get_data(mMaterialSetTag, &(*iter), 1, &dummy)) 00359 matsets.push_back(*iter); 00360 else if (MB_SUCCESS == mbImpl->tag_get_data(mDirichletSetTag, &(*iter), 1, &dummy)) 00361 dirsets.push_back(*iter); 00362 else if (MB_SUCCESS == mbImpl->tag_get_data(mNeumannSetTag, &(*iter), 1, &dummy)) 00363 neusets.push_back(*iter); 00364 else if (mPartitionSetTag && 00365 MB_SUCCESS == mbImpl->tag_get_data(mPartitionSetTag, &(*iter), 1, &dummy)) 00366 partsets.push_back(*iter); 00367 } 00368 } 00369 00370 return MB_SUCCESS; 00371 } 00372 00373 ErrorCode WriteCCMIO::write_problem_description(CCMIOID rootID, CCMIOID stateID, CCMIOID &problemID, 00374 CCMIOID processorID, 00375 std::vector<WriteCCMIO::MaterialSetData> &matset_data, 00376 std::vector<WriteCCMIO::NeumannSetData> &neuset_data) 00377 { 00378 // Write out a dummy problem description. If we happen to know that 00379 // there already is a problem description previously recorded that 00380 // is valid we could skip this step. 00381 CCMIOID id; 00382 CCMIOError error = kCCMIONoErr; 00383 ErrorCode rval; 00384 const EntityHandle mesh = 0; 00385 00386 bool root_tagged = false, other_set_tagged = false; 00387 Tag simname; 00388 Range dum_sets; 00389 rval = mbImpl->tag_get_handle("Title", 0, MB_TYPE_OPAQUE, simname, MB_TAG_ANY); 00390 if (MB_SUCCESS == rval) { 00391 int tag_size; 00392 rval = mbImpl->tag_get_bytes(simname, tag_size); 00393 if (MB_SUCCESS == rval) { 00394 std::vector<char> title_tag(tag_size+1); 00395 rval = mbImpl->get_entities_by_type_and_tag(0, MBENTITYSET, &simname, NULL, 1, dum_sets); 00396 if (MB_SUCCESS == rval && !dum_sets.empty()) { 00397 rval = mbImpl->tag_get_data(simname, &(*dum_sets.begin()), 1, &title_tag[0]); 00398 CHKERR(rval, "Problem getting simulation name tag."); 00399 other_set_tagged = true; 00400 } 00401 else if (MB_SUCCESS == rval) { 00402 // check to see if interface was tagged 00403 rval = mbImpl->tag_get_data(simname, &mesh, 1, &title_tag[0]); 00404 if (MB_SUCCESS == rval) root_tagged = true; 00405 else rval = MB_SUCCESS; 00406 } 00407 *title_tag.rbegin() = '\0'; 00408 if (root_tagged || other_set_tagged) { 00409 CCMIONode rootNode; 00410 if (kCCMIONoErr == CCMIOGetEntityNode(&error, rootID, &rootNode)) { 00411 CCMIOSetTitle(&error, rootNode, &title_tag[0]); 00412 CHKCCMERR(error, "Trouble setting title."); 00413 } 00414 } 00415 } 00416 } 00417 00418 rval = mbImpl->tag_get_handle("CreatingProgram", 0, MB_TYPE_OPAQUE, mCreatingProgramTag, MB_TAG_ANY); 00419 if (MB_SUCCESS == rval) { 00420 int tag_size; 00421 rval = mbImpl->tag_get_bytes(mCreatingProgramTag, tag_size); 00422 if (MB_SUCCESS == rval) { 00423 std::vector<char> cp_tag(tag_size+1); 00424 rval = mbImpl->get_entities_by_type_and_tag(0, MBENTITYSET, &mCreatingProgramTag, NULL, 1, dum_sets); 00425 if (MB_SUCCESS == rval && !dum_sets.empty()) { 00426 rval = mbImpl->tag_get_data(mCreatingProgramTag, &(*dum_sets.begin()), 1, &cp_tag[0]); 00427 CHKERR(rval, "Problem getting creating program tag."); 00428 other_set_tagged = true; 00429 } 00430 else if (MB_SUCCESS == rval) { 00431 // check to see if interface was tagged 00432 rval = mbImpl->tag_get_data(mCreatingProgramTag, &mesh, 1, &cp_tag[0]); 00433 if (MB_SUCCESS == rval) root_tagged = true; 00434 else rval = MB_SUCCESS; 00435 } 00436 *cp_tag.rbegin() = '\0'; 00437 if (root_tagged || other_set_tagged) { 00438 CCMIONode rootNode; 00439 if (kCCMIONoErr == CCMIOGetEntityNode(&error, rootID, &rootNode)) { 00440 CCMIOWriteOptstr(&error, processorID, "CreatingProgram", &cp_tag[0]); 00441 CHKCCMERR(error, "Trouble setting creating program."); 00442 } 00443 } 00444 } 00445 } 00446 00447 CCMIONewEntity(&error, rootID, kCCMIOProblemDescription, NULL, 00448 &problemID); 00449 CHKCCMERR(error, "Trouble creating problem node."); 00450 00451 // write material types and other info 00452 for (unsigned int i = 0; i < matset_data.size(); i++) { 00453 if (!matset_data[i].setName.empty()){ 00454 CCMIONewIndexedEntity(&error, problemID, kCCMIOCellType, matset_data[i].matsetId, 00455 matset_data[i].setName.c_str(), &id); 00456 CHKCCMERR(error, "Failure creating celltype node."); 00457 00458 CCMIOWriteOptstr(&error, id, "MaterialType", matset_data[i].setName.c_str()); 00459 CHKCCMERR(error, "Error assigning material name."); 00460 } 00461 else{ 00462 char dum_name[NAME_TAG_SIZE]; 00463 std::ostringstream os; 00464 std::string mat_name = "Material", temp_str; 00465 os << mat_name << (i+1); 00466 temp_str = os.str(); 00467 strcpy(dum_name,temp_str.c_str()); 00468 CCMIONewIndexedEntity(&error, problemID, kCCMIOCellType, matset_data[i].matsetId, 00469 dum_name, &id); 00470 CHKCCMERR(error, "Failure creating celltype node."); 00471 00472 CCMIOWriteOptstr(&error, id, "MaterialType", dum_name); 00473 CHKCCMERR(error, "Error assigning material name."); 00474 00475 os.str(""); 00476 } 00477 rval = write_int_option("MaterialId", matset_data[i].setHandle, mMaterialIdTag, id); 00478 CHKERR(rval, "Trouble writing MaterialId option."); 00479 00480 rval = write_int_option("Radiation", matset_data[i].setHandle, mRadiationTag, id); 00481 CHKERR(rval, "Trouble writing Radiation option."); 00482 00483 rval = write_int_option("PorosityId", matset_data[i].setHandle, mPorosityIdTag, id); 00484 CHKERR(rval, "Trouble writing PorosityId option."); 00485 00486 rval = write_int_option("SpinId", matset_data[i].setHandle, mSpinIdTag, id); 00487 CHKERR(rval, "Trouble writing SpinId option."); 00488 00489 rval = write_int_option("GroupId", matset_data[i].setHandle, mGroupIdTag, id); 00490 CHKERR(rval, "Trouble writing GroupId option."); 00491 00492 rval = write_int_option("ColorIdx", matset_data[i].setHandle, mColorIdxTag, id); 00493 CHKERR(rval, "Trouble writing ColorIdx option."); 00494 00495 rval = write_int_option("ProcessorId", matset_data[i].setHandle, mProcessorIdTag, id); 00496 CHKERR(rval, "Trouble writing ProcessorId option."); 00497 00498 rval = write_int_option("LightMaterial", matset_data[i].setHandle, mLightMaterialTag, id); 00499 CHKERR(rval, "Trouble writing LightMaterial option."); 00500 00501 rval = write_int_option("FreeSurfaceMaterial", matset_data[i].setHandle, mFreeSurfaceMaterialTag, id); 00502 CHKERR(rval, "Trouble writing FreeSurfaceMaterial option."); 00503 00504 rval = write_dbl_option("Thickness", matset_data[i].setHandle, mThicknessTag, id); 00505 CHKERR(rval, "Trouble writing Thickness option."); 00506 00507 rval = write_str_option("MaterialType", matset_data[i].setHandle, mMaterialTypeTag, id); 00508 CHKERR(rval, "Trouble writing MaterialType option."); 00509 } 00510 00511 // write neumann set info 00512 for (unsigned int i = 0; i < neuset_data.size(); i++) { 00513 // use the label to encode the id 00514 std::ostringstream dum_id; 00515 dum_id << neuset_data[i].neusetId; 00516 CCMIONewIndexedEntity(&error, problemID, kCCMIOBoundaryRegion, neuset_data[i].neusetId, 00517 dum_id.str().c_str(), &id); 00518 CHKCCMERR(error, "Failure creating BoundaryRegion node."); 00519 00520 rval = write_str_option("BoundaryName", neuset_data[i].setHandle, mNameTag, 00521 id); 00522 CHKERR(rval, "Trouble writing boundary type number."); 00523 00524 rval = write_str_option("BoundaryType", neuset_data[i].setHandle, mBoundaryTypeTag, 00525 id); 00526 CHKERR(rval, "Trouble writing boundary type number."); 00527 00528 rval = write_int_option("ProstarRegionNumber", neuset_data[i].setHandle, mProstarRegionNumberTag, 00529 id); 00530 CHKERR(rval, "Trouble writing prostar region number."); 00531 } 00532 00533 CCMIOWriteState(&error, stateID, problemID, "Example state"); 00534 CHKCCMERR(error, "Failure writing problem state."); 00535 00536 // get cell types; reuse cell ids array 00537 // for (i = 0, rit = all_elems.begin(); i < num_elems; i++, rit++) { 00538 // egids[i] = ccm_types[mbImpl->type_from_handle(*rit)]; 00539 // assert(-1 != egids[i]); 00540 // } 00541 00542 return MB_SUCCESS; 00543 } 00544 00545 ErrorCode WriteCCMIO::write_int_option(const char *opt_name, 00546 EntityHandle seth, 00547 Tag &tag, CCMIOID &node) 00548 { 00549 ErrorCode rval; 00550 00551 if (!tag) { 00552 rval = mbImpl->tag_get_handle(opt_name, 1, MB_TYPE_INTEGER, tag); 00553 // return success since that just means we don't have to write this option 00554 if (MB_SUCCESS != rval) return MB_SUCCESS; 00555 } 00556 00557 int dum_val; 00558 rval = mbImpl->tag_get_data(tag, &seth, 1, &dum_val); 00559 // return success since that just means we don't have to write this option 00560 if (MB_SUCCESS != rval) return MB_SUCCESS; 00561 00562 CCMIOError error = kCCMIONoErr; 00563 CCMIOWriteOpti(&error, node, opt_name, dum_val); 00564 CHKCCMERR(error, "Trouble writing int option."); 00565 00566 return MB_SUCCESS; 00567 } 00568 00569 ErrorCode WriteCCMIO::write_dbl_option(const char *opt_name, 00570 EntityHandle seth, 00571 Tag &tag, CCMIOID &node) 00572 { 00573 ErrorCode rval; 00574 00575 if (!tag) { 00576 rval = mbImpl->tag_get_handle(opt_name, 1, MB_TYPE_DOUBLE, tag); 00577 // return success since that just means we don't have to write this option 00578 if (MB_SUCCESS != rval) return MB_SUCCESS; 00579 } 00580 00581 double dum_val; 00582 rval = mbImpl->tag_get_data(tag, &seth, 1, &dum_val); 00583 // return success since that just means we don't have to write this option 00584 if (MB_SUCCESS != rval) return MB_SUCCESS; 00585 00586 CCMIOError error = kCCMIONoErr; 00587 CCMIOWriteOptf(&error, node, opt_name, dum_val); 00588 CHKCCMERR(error, "Trouble writing int option."); 00589 00590 return MB_SUCCESS; 00591 } 00592 00593 ErrorCode WriteCCMIO::write_str_option(const char *opt_name, 00594 EntityHandle seth, 00595 Tag &tag, CCMIOID &node, 00596 const char *other_name) 00597 { 00598 int tag_size; 00599 ErrorCode rval; 00600 00601 if (!tag) { 00602 rval = mbImpl->tag_get_handle(opt_name, 0, MB_TYPE_OPAQUE, tag, MB_TAG_ANY); 00603 // return success since that just means we don't have to write this option 00604 if (MB_SUCCESS != rval) return MB_SUCCESS; 00605 } 00606 00607 rval = mbImpl->tag_get_bytes(tag, tag_size); 00608 if (MB_SUCCESS != rval) return MB_SUCCESS; 00609 std::vector<char> opt_val(tag_size+1); 00610 00611 rval = mbImpl->tag_get_data(tag, &seth, 1, &opt_val[0]); 00612 if (MB_SUCCESS != rval) return MB_SUCCESS; 00613 00614 // null-terminate if necessary 00615 if (std::find(opt_val.begin(), opt_val.end(), '\0') == opt_val.end()) 00616 *opt_val.rbegin() = '\0'; 00617 00618 CCMIOError error = kCCMIONoErr; 00619 if (other_name) 00620 CCMIOWriteOptstr(&error, node, other_name, &opt_val[0]); 00621 else 00622 CCMIOWriteOptstr(&error, node, opt_name, &opt_val[0]); 00623 CHKCCMERR(error, "Failure writing an option string MaterialType."); 00624 00625 return MB_SUCCESS; 00626 } 00627 00628 ErrorCode WriteCCMIO::gather_matset_info(std::vector<EntityHandle> &matsets, 00629 std::vector<MaterialSetData> &matset_data, 00630 Range &all_verts) 00631 { 00632 ErrorCode result; 00633 matset_data.resize(matsets.size()); 00634 if (1 == matsets.size() && 0 == matsets[0]) { 00635 // whole mesh 00636 mWholeMesh = true; 00637 00638 result = mbImpl->get_entities_by_dimension(0, mDimension, matset_data[0].elems); 00639 CHKERR(result, "Trouble getting all elements in mesh."); 00640 result = mWriteIface->gather_nodes_from_elements(matset_data[0].elems, 00641 mEntityMark, all_verts); 00642 CHKERR(result, "Trouble gathering nodes from elements."); 00643 00644 return result; 00645 } 00646 00647 std::vector<unsigned char> marks; 00648 for(unsigned int i = 0; i < matsets.size(); i++) 00649 { 00650 EntityHandle this_set = matset_data[i].setHandle = matsets[i]; 00651 00652 // get all Entity Handles in the set 00653 result = mbImpl->get_entities_by_dimension(this_set, mDimension, matset_data[i].elems, true); 00654 CHKERR(result, "Trouble getting m-dimensional ents."); 00655 00656 // get all connected vertices 00657 result = mWriteIface->gather_nodes_from_elements(matset_data[i].elems, 00658 mEntityMark, all_verts); 00659 CHKERR(result, "Trouble getting vertices for a matset."); 00660 00661 // check for consistent entity type 00662 EntityType start_type = mbImpl->type_from_handle(*matset_data[i].elems.begin()); 00663 if (start_type == mbImpl->type_from_handle(*matset_data[i].elems.rbegin())) 00664 matset_data[i].entityType = start_type; 00665 00666 // mark elements in this matset 00667 marks.resize(matset_data[i].elems.size(), 0x1); 00668 result = mbImpl->tag_set_data(mEntityMark, matset_data[i].elems, &marks[0]); 00669 CHKERR(result, "Couln't mark entities being output."); 00670 00671 // get id for this matset 00672 result = mbImpl->tag_get_data(mMaterialSetTag, &this_set, 1, &matset_data[i].matsetId); 00673 CHKERR(result, "Couln't get global id for material set."); 00674 00675 // get name for this matset 00676 if (mNameTag) { 00677 char dum_name[NAME_TAG_SIZE]; 00678 result = mbImpl->tag_get_data(mNameTag, &this_set, 1, dum_name); 00679 if (MB_SUCCESS == result) matset_data[i].setName = dum_name; 00680 00681 // reset success, so later checks don't fail 00682 result = MB_SUCCESS; 00683 } 00684 } 00685 00686 00687 if (all_verts.empty()) { 00688 result = MB_FILE_WRITE_ERROR; 00689 CHKERR(result, "No vertices from elements."); 00690 } 00691 00692 return MB_SUCCESS; 00693 } 00694 00695 ErrorCode WriteCCMIO::gather_neuset_info(std::vector<EntityHandle> &neusets, 00696 std::vector<NeumannSetData> &neuset_info) 00697 { 00698 ErrorCode result; 00699 00700 std::vector<unsigned char> marks; 00701 neuset_info.resize(neusets.size()); 00702 for(unsigned int i = 0; i < neusets.size(); i++) 00703 { 00704 EntityHandle this_set = neuset_info[i].setHandle = neusets[i]; 00705 00706 // get all Entity Handles of one less dimension than that being output 00707 result = mbImpl->get_entities_by_dimension(this_set, mDimension-1, neuset_info[i].elems, true); 00708 CHKERR(result, "Trouble getting (m-1)-dimensional ents for neuset."); 00709 00710 result = mbImpl->tag_get_data(mGlobalIdTag, &this_set, 1, &neuset_info[i].neusetId); 00711 if (MB_TAG_NOT_FOUND == result) { 00712 result = mbImpl->tag_get_data(mNeumannSetTag, &this_set, 1, &neuset_info[i].neusetId); 00713 if (MB_SUCCESS != result) 00714 // need some id; use the loop iteration number 00715 neuset_info[i].neusetId = i; 00716 } 00717 00718 // get name for this neuset 00719 if (mNameTag) { 00720 char dum_name[NAME_TAG_SIZE]; 00721 result = mbImpl->tag_get_data(mNameTag, &this_set, 1, dum_name); 00722 if (MB_SUCCESS == result) neuset_info[i].setName = dum_name; 00723 00724 // reset success, so later checks don't fail 00725 result = MB_SUCCESS; 00726 } 00727 } 00728 00729 return MB_SUCCESS; 00730 } 00731 00732 ErrorCode WriteCCMIO::get_gids(const Range &ents, int *&gids, 00733 int &minid, int &maxid) 00734 { 00735 int num_ents = ents.size(); 00736 gids = new int[num_ents]; 00737 ErrorCode result = mbImpl->tag_get_data(mGlobalIdTag, ents, &gids[0]); 00738 if (MB_SUCCESS != result) { 00739 mWriteIface->report_error("Couldn't get global id data."); 00740 return result; 00741 } 00742 minid = *std::min_element(gids, gids+num_ents); 00743 maxid = *std::max_element(gids, gids+num_ents); 00744 if (0 == minid) { 00745 // gids need to be assigned 00746 for (int i = 1; i <= num_ents; i++) gids[i] = i; 00747 result = mbImpl->tag_set_data(mGlobalIdTag, ents, &gids[0]); 00748 if (MB_SUCCESS != result) { 00749 mWriteIface->report_error("Couldn't set global id data."); 00750 return result; 00751 } 00752 maxid = num_ents; 00753 } 00754 return MB_SUCCESS; 00755 } 00756 00757 ErrorCode WriteCCMIO::write_nodes(CCMIOID rootID, 00758 const Range &verts, 00759 const int dimension, 00760 CCMIOID &verticesID) 00761 { 00762 // get/write map (global ids) first (gids already assigned) 00763 unsigned int num_verts = verts.size(); 00764 std::vector<int> vgids(num_verts); 00765 ErrorCode result = mbImpl->tag_get_data(mGlobalIdTag, verts, &vgids[0]); 00766 CHKERR(result, "Failed to get global ids for vertices."); 00767 00768 // create the map node for vertex ids, and write them to that node 00769 CCMIOID mapID; 00770 CCMIOError error = kCCMIONoErr; 00771 CCMIONewEntity(&error, rootID, kCCMIOMap, "Vertex map", &mapID); 00772 CHKCCMERR(error, "Failure creating Vertex map node."); 00773 00774 int maxid = *std::max_element(vgids.begin(), vgids.end()); 00775 00776 CCMIOWriteMap(&error, mapID, CCMIOSIZEC(num_verts), 00777 CCMIOSIZEC(maxid), &vgids[0], 00778 CCMIOINDEXC(kCCMIOStart), CCMIOINDEXC(kCCMIOEnd)); 00779 CHKCCMERR(error, "Problem writing node map."); 00780 00781 // create the vertex coordinate node, and write it 00782 CCMIONewEntity(&error, rootID, kCCMIOVertices, "Vertices", &verticesID); 00783 CHKCCMERR(error, "Trouble creating vertices node."); 00784 00785 // get the vertex locations 00786 double *coords = new double[3*num_verts]; 00787 std::vector<double*> coord_arrays(3); 00788 coord_arrays[0] = coords; 00789 coord_arrays[1] = coords+num_verts; 00790 coord_arrays[2] = (dimension == 3 ? coords+2*num_verts : NULL); 00791 result = mWriteIface->get_node_coords(-1, verts.begin(), verts.end(), 00792 3*num_verts, coords); 00793 if(result != MB_SUCCESS) 00794 { 00795 delete [] coords; 00796 return result; 00797 } 00798 00799 // transform coordinates, if necessary 00800 result = transform_coords(dimension, num_verts, coords); 00801 if(result != MB_SUCCESS) 00802 { 00803 delete [] coords; 00804 CHKERR(result, "Trouble transforming vertex coordinates."); 00805 } 00806 00807 // write the vertices 00808 CCMIOWriteVerticesd(&error, verticesID, 00809 CCMIOSIZEC(dimension), 1.0, mapID, coords, 00810 CCMIOINDEXC(kCCMIOStart), CCMIOINDEXC(kCCMIOEnd)); 00811 CHKCCMERR(error, "CCMIOWriteVertices failed."); 00812 00813 // clean up 00814 delete [] coords; 00815 00816 return MB_SUCCESS; 00817 } 00818 00819 ErrorCode WriteCCMIO::transform_coords(const int dimension, const int num_nodes, double *coords) 00820 { 00821 Tag trans_tag; 00822 ErrorCode result = mbImpl->tag_get_handle( MESH_TRANSFORM_TAG_NAME, 16, MB_TYPE_DOUBLE, trans_tag); 00823 if( result == MB_TAG_NOT_FOUND ) return MB_SUCCESS; 00824 else if (MB_SUCCESS != result) return result; 00825 double trans_matrix[16]; 00826 const EntityHandle mesh = 0; 00827 result = mbImpl->tag_get_data( trans_tag, &mesh, 1, trans_matrix ); 00828 if (MB_SUCCESS != result) { 00829 mWriteIface->report_error("Couldn't get transform data."); 00830 return result; 00831 } 00832 00833 double *tmp_coords = coords; 00834 for( int i=0; i<num_nodes; i++, tmp_coords += 1) { 00835 double vec1[3] = {0.0, 0.0, 0.0}; 00836 for( int row=0; row<3; row++ ) { 00837 vec1[row] += ( trans_matrix[ (row*4)+0 ] * coords[0]); 00838 vec1[row] += ( trans_matrix[ (row*4)+1 ] * coords[num_nodes]); 00839 if (3 == dimension) vec1[row] += ( trans_matrix[ (row*4)+2 ] * coords[2*num_nodes]); 00840 } 00841 00842 coords[0] = vec1[0]; 00843 coords[num_nodes] = vec1[1]; 00844 coords[2*num_nodes] = vec1[2]; 00845 } 00846 00847 return MB_SUCCESS; 00848 } 00849 00850 ErrorCode WriteCCMIO::write_cells_and_faces(CCMIOID rootID, 00851 std::vector<MaterialSetData> &matset_data, 00852 std::vector<NeumannSetData> &neuset_data, 00853 Range &, 00854 CCMIOID &topologyID) 00855 { 00856 std::vector<int> connect; 00857 ErrorCode result; 00858 CCMIOID cellMapID, cells; 00859 CCMIOError error = kCCMIONoErr; 00860 00861 // don't usually have anywhere near 31 nodes per element 00862 connect.reserve(31); 00863 Range::const_iterator rit; 00864 00865 // create the topology node, and the cell and cell map nodes 00866 CCMIONewEntity(&error, rootID, kCCMIOTopology, "Topology", &topologyID); 00867 CHKCCMERR(error, "Trouble creating topology node."); 00868 00869 CCMIONewEntity(&error, rootID, kCCMIOMap, "Cell map", &cellMapID); 00870 CHKCCMERR(error, "Failure creating Cell Map node."); 00871 00872 CCMIONewEntity(&error, topologyID, kCCMIOCells, "Cells", &cells); 00873 CHKCCMERR(error, "Trouble creating Cell node under Topology node."); 00874 00875 //================================================ 00876 // loop over material sets, doing each one at a time 00877 //================================================ 00878 Range all_elems; 00879 unsigned int i, num_elems = 0; 00880 int max_id = 1; 00881 std::vector<int> egids; 00882 int tot_elems = 0; 00883 00884 for (unsigned int m = 0; m < matset_data.size(); m++) 00885 tot_elems += matset_data[m].elems.size(); 00886 00887 for (unsigned int m = 0; m < matset_data.size(); m++) { 00888 00889 unsigned int this_num = matset_data[m].elems.size(); 00890 00891 //================================================ 00892 // save all elements being output 00893 //================================================ 00894 all_elems.merge(matset_data[m].elems); 00895 00896 //================================================ 00897 // Assign global ids for elements being written 00898 //================================================ 00899 egids.resize(matset_data[m].elems.size()); 00900 for (i = 0; i < this_num; i++) egids[i] = max_id++; 00901 result = mbImpl->tag_set_data(mGlobalIdTag, matset_data[m].elems, &egids[0]); 00902 CHKERR(result, "Failed to assign global ids for all elements being written."); 00903 00904 //================================================ 00905 // Write cell ids and material types for this matset; reuse egids for cell mat type 00906 //================================================ 00907 CCMIOWriteMap(&error, cellMapID, CCMIOSIZEC(tot_elems), 00908 CCMIOSIZEC(tot_elems), &egids[0], 00909 CCMIOINDEXC(0 == m ? kCCMIOStart : num_elems), 00910 CCMIOINDEXC(matset_data.size() == m ? kCCMIOEnd : 00911 num_elems + this_num)); 00912 CHKCCMERR(error, "Trouble writing cell map."); 00913 00914 if (-1 == matset_data[m].matsetId) 00915 for (i = 0; i < this_num; i++) egids[i] = m; 00916 else 00917 for (i = 0; i < this_num; i++) egids[i] = matset_data[m].matsetId; 00918 00919 CCMIOWriteCells(&error, cells, cellMapID, &egids[0], 00920 CCMIOINDEXC(0 == m ? kCCMIOStart : num_elems), 00921 CCMIOINDEXC(matset_data.size() == m ? kCCMIOEnd : 00922 num_elems + this_num)); 00923 CHKCCMERR(error, "Trouble writing Cell node."); 00924 00925 //================================================ 00926 // Write cell entity types 00927 //================================================ 00928 const EntityHandle *conn; 00929 int num_conn; 00930 int has_mid_nodes[4]; 00931 std::vector<EntityHandle> storage; 00932 for (i = 0, rit = matset_data[m].elems.begin(); i < this_num; i++, rit++) { 00933 result = mbImpl->get_connectivity(*rit, conn, num_conn, false, &storage); 00934 CHKERR(result, "Trouble getting connectivity for entity type check."); 00935 CN::HasMidNodes(mbImpl->type_from_handle(*rit), num_conn, has_mid_nodes); 00936 egids[i] = moab_to_ccmio_type(mbImpl->type_from_handle(*rit), has_mid_nodes); 00937 } 00938 00939 CCMIOWriteOpt1i(&error, cells, "CellTopologyType", CCMIOSIZEC(tot_elems), &egids[0], 00940 CCMIOINDEXC(0 == m ? kCCMIOStart : num_elems), 00941 CCMIOINDEXC(matset_data.size() == m ? kCCMIOEnd : 00942 num_elems + this_num)); 00943 CHKCCMERR(error, "Failed to write cell topo types."); 00944 00945 num_elems += this_num; 00946 } 00947 00948 //================================================ 00949 // get skin and neumann set faces 00950 //================================================ 00951 Range neuset_facets, skin_facets; 00952 Skinner skinner(mbImpl); 00953 result = skinner.find_skin(0, all_elems, mDimension-1, skin_facets); 00954 CHKERR(result, "Failed to get skin facets."); 00955 00956 // remove neumann set facets from skin facets, we have to output these 00957 // separately 00958 for (i = 0; i < neuset_data.size(); i++) 00959 neuset_facets.merge(neuset_data[i].elems); 00960 00961 skin_facets -= neuset_facets; 00962 // make neuset_facets the union, and get ids for them 00963 neuset_facets.merge(skin_facets); 00964 result = mWriteIface->assign_ids(neuset_facets, mGlobalIdTag, 1); 00965 00966 int fmaxid = neuset_facets.size(); 00967 00968 //================================================ 00969 // write external faces 00970 //================================================ 00971 for (i = 0; i < neuset_data.size(); i++) { 00972 Range::reverse_iterator rrit; 00973 unsigned char cmarks[2]; 00974 Range ext_faces; 00975 std::vector<EntityHandle> mcells; 00976 // removing the faces connected to two regions 00977 for (rrit = neuset_data[i].elems.rbegin(); rrit != neuset_data[i].elems.rend(); ++rrit) { 00978 mcells.clear(); 00979 result = mbImpl->get_adjacencies(&(*rrit), 1, mDimension, false, mcells); 00980 CHKERR(result, "Trouble getting bounding cells."); 00981 00982 result = mbImpl->tag_get_data(mEntityMark, &mcells[0], mcells.size(), cmarks); 00983 CHKERR(result, "Trouble getting mark tags on cells bounding facets."); 00984 00985 if( mcells.size() == 2 && (mWholeMesh || (cmarks[0] && cmarks[1]))) { 00986 } 00987 else{ 00988 // external face 00989 ext_faces.insert(*rrit); 00990 } 00991 } 00992 if (ext_faces.size() != 0 && neuset_data[i].neusetId != 0) 00993 result = write_external_faces(rootID, topologyID, neuset_data[i].neusetId, 00994 ext_faces); 00995 CHKERR(result, "Trouble writing Neumann set facets."); 00996 ext_faces.clear (); 00997 } 00998 00999 if (!skin_facets.empty()) { 01000 result = write_external_faces(rootID, topologyID, 0, skin_facets); 01001 CHKERR(result, "Trouble writing skin facets."); 01002 } 01003 01004 //================================================ 01005 // now inernal faces; loop over elements, do each face on the element 01006 //================================================ 01007 // mark tag, for face marking on each non-polyhedral element 01008 01009 if (num_elems > 1){ // no internal faces for just one element 01010 01011 Tag fmark_tag; 01012 unsigned char mval = 0x0, omval; 01013 result = mbImpl->tag_get_handle("__fmark", 1, MB_TYPE_OPAQUE, 01014 fmark_tag, MB_TAG_DENSE|MB_TAG_CREAT, &mval); 01015 CHKERR(result, "Couldn't create mark tag."); 01016 01017 std::vector<EntityHandle> tmp_face_cells, storage; 01018 std::vector<int> iface_connect, iface_cells; 01019 EntityHandle tmp_connect[CN::MAX_NODES_PER_ELEMENT]; // tmp connect vector 01020 const EntityHandle *connectc, *oconnectc; int num_connectc; // cell connectivity 01021 const EntityHandle *connectf; int num_connectf; // face connectivity 01022 01023 for (i = 0, rit = all_elems.begin(); i < num_elems; i++, rit++) { 01024 EntityType etype = TYPE_FROM_HANDLE(*rit); 01025 01026 //----------------------- 01027 // if not polyh, get mark 01028 //----------------------- 01029 if (MBPOLYHEDRON != etype && MBPOLYGON != etype) { 01030 result = mbImpl->tag_get_data(fmark_tag, &(*rit), 1, &mval); 01031 if (MB_SUCCESS != result) { 01032 mWriteIface->report_error("Couldn't get mark data."); 01033 return result; 01034 } 01035 } 01036 01037 //----------------------- 01038 // get cell connectivity, and whether it's a polyhedron 01039 //----------------------- 01040 result = mbImpl->get_connectivity(*rit, connectc, num_connectc, false, &storage); 01041 CHKERR(result, "Couldn't get entity connectivity."); 01042 01043 // if polyh, write faces directly 01044 bool is_polyh = (MBPOLYHEDRON == etype); 01045 01046 int num_facets = (is_polyh ? num_connectc : 01047 CN::NumSubEntities(etype, mDimension-1)); 01048 01049 //---------------------------------------------------------- 01050 // loop over each facet of element, outputing it if not marked 01051 //---------------------------------------------------------- 01052 for (int f = 0; f < num_facets; f++) { 01053 01054 //............................................. 01055 // if this face marked, skip 01056 //............................................. 01057 if (!is_polyh && ((mval >> f) & 0x1)) continue; 01058 01059 //................. 01060 // get face connect and adj cells 01061 //................. 01062 if (!is_polyh) { 01063 // (from CN) 01064 CN::SubEntityConn(connectc, etype, mDimension-1, f, tmp_connect, num_connectf); 01065 connectf = tmp_connect; 01066 } 01067 else { 01068 // directly 01069 result = mbImpl->get_connectivity(connectc[f], connectf, num_connectf, false); 01070 CHKERR(result, "Couldn't get polyhedron connectivity."); 01071 } 01072 01073 //............................ 01074 // get adj cells from face connect (same for poly's and not, since both usually 01075 // go through vertices anyway) 01076 //............................ 01077 tmp_face_cells.clear(); 01078 result = mbImpl->get_adjacencies(connectf, num_connectf, mDimension, false, tmp_face_cells); 01079 CHKERR(result, "Error getting adj hexes."); 01080 01081 //............................... 01082 // if this face only bounds one cell, skip, since we exported external faces 01083 // before this loop 01084 //............................... 01085 if (tmp_face_cells.size() != 2) continue; 01086 01087 //................. 01088 // switch cells so that *rit is always 1st (face connectivity is always written such 01089 // that that one is with forward sense) 01090 //................. 01091 int side_num, sense, offset; 01092 if (!is_polyh && tmp_face_cells[0] != *rit) { 01093 EntityHandle tmph = tmp_face_cells[0]; 01094 tmp_face_cells[0] = tmp_face_cells[1]; 01095 tmp_face_cells[1] = tmph; 01096 } 01097 01098 //................. 01099 // save ids of cells 01100 //................. 01101 assert(tmp_face_cells[0] != tmp_face_cells[1]); 01102 iface_cells.resize(iface_cells.size()+2); 01103 result = mbImpl->tag_get_data(mGlobalIdTag, &tmp_face_cells[0], tmp_face_cells.size(), 01104 &iface_cells[iface_cells.size()-2]); 01105 CHKERR(result, "Trouble getting global ids for bounded cells."); 01106 iface_connect.push_back(num_connectf); 01107 01108 //................. 01109 // save indices of face vertices 01110 //................. 01111 unsigned int tmp_size = iface_connect.size(); 01112 iface_connect.resize(tmp_size+num_connectf); 01113 result = mbImpl->tag_get_data(mGlobalIdTag, connectf, num_connectf, 01114 &iface_connect[tmp_size]); 01115 CHKERR(result, "Trouble getting global id for internal face."); 01116 01117 //................. 01118 // mark other cell with the right side # 01119 //................. 01120 if (!is_polyh) { 01121 // mark other cell for this face, if there is another cell 01122 01123 result = mbImpl->get_connectivity(tmp_face_cells[1], oconnectc, num_connectc, 01124 false, &storage); 01125 CHKERR(result, "Couldn't get other entity connectivity."); 01126 01127 // get side number in other cell 01128 CN::SideNumber(TYPE_FROM_HANDLE(tmp_face_cells[1]), oconnectc, connectf, num_connectf, 01129 mDimension-1, side_num, sense, offset); 01130 // set mark for that face on the other cell 01131 result = mbImpl->tag_get_data(fmark_tag, &tmp_face_cells[1], 1, &omval); 01132 CHKERR(result, "Couldn't get mark data for other cell."); 01133 } 01134 01135 omval |= (0x1 << (unsigned int)side_num); 01136 result = mbImpl->tag_set_data(fmark_tag, &tmp_face_cells[1], 1, &omval); 01137 CHKERR(result, "Couldn't set mark data for other cell."); 01138 01139 } // loop over faces in elem 01140 } // loop over elems 01141 01142 //================================================ 01143 // write internal faces 01144 //================================================ 01145 01146 CCMIOID mapID; 01147 CCMIONewEntity(&error, rootID, kCCMIOMap, NULL, &mapID); 01148 CHKCCMERR(error, "Trouble creating Internal Face map node."); 01149 01150 unsigned int num_ifaces = iface_cells.size()/2; 01151 01152 // set gids for internal faces; reuse egids 01153 egids.resize(num_ifaces); 01154 for (i = 1; i <= num_ifaces; i++) egids[i-1] = fmaxid + i; 01155 CCMIOWriteMap(&error, mapID, CCMIOSIZEC(num_ifaces), 01156 CCMIOSIZEC(fmaxid + num_ifaces), 01157 &egids[0], 01158 CCMIOINDEXC(kCCMIOStart), CCMIOINDEXC(kCCMIOEnd)); 01159 CHKCCMERR(error, "Trouble writing Internal Face map node."); 01160 01161 CCMIOID id; 01162 CCMIONewEntity(&error, topologyID, kCCMIOInternalFaces, "Internal faces", &id); 01163 CHKCCMERR(error, "Failed to create Internal face node under Topology node."); 01164 CCMIOWriteFaces(&error, id, kCCMIOInternalFaces, mapID, 01165 CCMIOSIZEC(iface_connect.size()), &iface_connect[0], 01166 CCMIOINDEXC(kCCMIOStart), CCMIOINDEXC(kCCMIOEnd)); 01167 CHKCCMERR(error, "Failure writing Internal face connectivity."); 01168 CCMIOWriteFaceCells(&error, id, kCCMIOInternalFaces, mapID, &iface_cells[0], 01169 CCMIOINDEXC(kCCMIOStart), CCMIOINDEXC(kCCMIOEnd)); 01170 CHKCCMERR(error, "Failure writing Internal face cells."); 01171 } 01172 return MB_SUCCESS; 01173 } 01174 01175 int WriteCCMIO::moab_to_ccmio_type(EntityType etype, int has_mid_nodes[]) 01176 { 01177 int ctype = -1; 01178 if (has_mid_nodes[0] || has_mid_nodes[2] || has_mid_nodes[3]) return ctype; 01179 01180 switch (etype) { 01181 case MBVERTEX: 01182 ctype = 1; 01183 break; 01184 case MBEDGE: 01185 if (!has_mid_nodes[1]) ctype = 2; 01186 else ctype = 28; 01187 break; 01188 case MBQUAD: 01189 if (has_mid_nodes[1]) ctype = 4; 01190 else ctype = 3; 01191 break; 01192 case MBTET: 01193 if (has_mid_nodes[1]) ctype = 23; 01194 else ctype = 13; 01195 break; 01196 case MBPRISM: 01197 if (has_mid_nodes[1]) ctype = 22; 01198 else ctype = 12; 01199 break; 01200 case MBPYRAMID: 01201 if (has_mid_nodes[1]) ctype = 24; 01202 else ctype = 14; 01203 break; 01204 case MBHEX: 01205 if (has_mid_nodes[1]) ctype = 21; 01206 else ctype = 11; 01207 break; 01208 case MBPOLYHEDRON: 01209 ctype = 255; 01210 break; 01211 default: 01212 break; 01213 } 01214 01215 return ctype; 01216 } 01217 01218 ErrorCode WriteCCMIO::write_external_faces(CCMIOID rootID, CCMIOID topologyID, 01219 int set_num, Range &facets) 01220 { 01221 CCMIOError error = kCCMIONoErr; 01222 CCMIOID mapID, id; 01223 01224 // get gids for these faces 01225 int *gids = NULL, minid, maxid; 01226 ErrorCode result = get_gids(facets, gids, minid, maxid); 01227 CHKERR(result, "Trouble getting global ids for facets."); 01228 01229 // write the face id map 01230 CCMIONewEntity(&error, rootID, kCCMIOMap, NULL, &mapID); 01231 CHKCCMERR(error, "Problem creating face id map."); 01232 01233 CCMIOWriteMap(&error, mapID, CCMIOSIZEC(facets.size()), 01234 CCMIOSIZEC(maxid), gids, 01235 CCMIOINDEXC(kCCMIOStart), CCMIOINDEXC(kCCMIOEnd)); 01236 CHKCCMERR(error, "Problem writing face id map."); 01237 01238 // get the connectivity of the faces; set size by how many verts in last facet 01239 const EntityHandle *connect; 01240 int num_connect; 01241 result = mbImpl->get_connectivity(*facets.rbegin(), connect, num_connect); 01242 CHKERR(result, "Failed to get connectivity of last facet."); 01243 std::vector<int> fconnect(facets.size() * (num_connect+1)); 01244 01245 result = mWriteIface->get_element_connect(facets.begin(), facets.end(), 01246 num_connect, mGlobalIdTag, fconnect.size(), 01247 &fconnect[0], true); 01248 CHKERR(result, "Failed to get facet connectivity."); 01249 01250 // get and write a new external face entity 01251 CCMIONewIndexedEntity(&error, topologyID, kCCMIOBoundaryFaces, set_num, 01252 "Boundary faces", &id); 01253 CHKCCMERR(error, "Problem creating boundary face entity."); 01254 01255 CCMIOWriteFaces(&error, id, kCCMIOBoundaryFaces, mapID, 01256 CCMIOSIZEC(fconnect.size()), &fconnect[0], 01257 CCMIOINDEXC(kCCMIOStart), CCMIOINDEXC(kCCMIOEnd)); 01258 CHKCCMERR(error, "Problem writing boundary faces."); 01259 01260 // get info on bounding cells; reuse fconnect 01261 std::vector<EntityHandle> cells; 01262 unsigned char cmarks[2]; 01263 int i, j = 0; 01264 Range dead_facets; 01265 Range::iterator rit; 01266 01267 // about error checking in this loop: if any facets have no bounding cells, 01268 // this is an error, since global ids for facets are computed outside this loop 01269 for (rit = facets.begin(), i = 0; rit != facets.end(); rit++, i++) { 01270 cells.clear(); 01271 01272 // get cell then gid of cell 01273 result = mbImpl->get_adjacencies(&(*rit), 1, mDimension, false, cells); 01274 CHKERR(result, "Trouble getting bounding cells."); 01275 if (cells.empty()) { 01276 result = MB_FILE_WRITE_ERROR; 01277 CHKERR(result, "External facet with no output bounding cell."); 01278 } 01279 01280 // check we don't bound more than one cell being output 01281 result = mbImpl->tag_get_data(mEntityMark, &cells[0], cells.size(), cmarks); 01282 CHKERR(result, "Trouble getting mark tags on cells bounding facets."); 01283 if (cells.size() == 2 && (mWholeMesh || (cmarks[0] && cmarks[1]))) { 01284 result = MB_FILE_WRITE_ERROR; 01285 CHKERR(result, "External facet with two output bounding cells."); 01286 } 01287 else if (1 == cells.size() && !mWholeMesh && !cmarks[0]) { 01288 result = MB_FILE_WRITE_ERROR; 01289 CHKERR(result, "External facet with no output bounding cells."); 01290 } 01291 01292 // make sure 1st cell is the one being output 01293 if (2 == cells.size() && !(cmarks[0] | 0x0) && (cmarks[1] & 0x1)) 01294 cells[0] = cells[1]; 01295 01296 // get gid for bounded cell 01297 result = mbImpl->tag_get_data(mGlobalIdTag, &cells[0], 1, &fconnect[j]); 01298 CHKERR(result, "Couldn't get global id tag for bounded cell."); 01299 01300 j++; 01301 } 01302 01303 // write the bounding cell data 01304 CCMIOWriteFaceCells(&error, id, kCCMIOBoundaryFaces, mapID, &fconnect[0], 01305 CCMIOINDEXC(kCCMIOStart), CCMIOINDEXC(kCCMIOEnd)); 01306 CHKCCMERR(error, "Problem writing boundary cell data."); 01307 01308 return MB_SUCCESS; 01309 } 01310 01311 ErrorCode WriteCCMIO::get_neuset_elems(EntityHandle neuset, int current_sense, 01312 Range &forward_elems, Range &reverse_elems) 01313 { 01314 Range neuset_elems, neuset_meshsets; 01315 01316 // get the sense tag; don't need to check return, might be an error if the tag 01317 // hasn't been created yet 01318 Tag sense_tag = 0; 01319 mbImpl->tag_get_handle("SENSE", 1, MB_TYPE_INTEGER, sense_tag); 01320 01321 // get the entities in this set, non-recursive 01322 ErrorCode result = mbImpl->get_entities_by_handle(neuset, neuset_elems); 01323 if (MB_FAILURE == result) return result; 01324 01325 // now remove the meshsets into the neuset_meshsets; first find the first meshset, 01326 Range::iterator range_iter = neuset_elems.begin(); 01327 while (TYPE_FROM_HANDLE(*range_iter) != MBENTITYSET && range_iter != neuset_elems.end()) 01328 range_iter++; 01329 01330 // then, if there are some, copy them into neuset_meshsets and erase from neuset_elems 01331 if (range_iter != neuset_elems.end()) { 01332 std::copy(range_iter, neuset_elems.end(), range_inserter(neuset_meshsets)); 01333 neuset_elems.erase(range_iter, neuset_elems.end()); 01334 } 01335 01336 01337 // ok, for the elements, check the sense of this set and copy into the right range 01338 // (if the sense is 0, copy into both ranges) 01339 01340 // need to step forward on list until we reach the right dimension 01341 Range::iterator dum_it = neuset_elems.end(); 01342 dum_it--; 01343 int target_dim = CN::Dimension(TYPE_FROM_HANDLE(*dum_it)); 01344 dum_it = neuset_elems.begin(); 01345 while (target_dim != CN::Dimension(TYPE_FROM_HANDLE(*dum_it)) && 01346 dum_it != neuset_elems.end()) 01347 dum_it++; 01348 01349 if (current_sense == 1 || current_sense == 0) 01350 std::copy(dum_it, neuset_elems.end(), range_inserter(forward_elems)); 01351 if (current_sense == -1 || current_sense == 0) 01352 std::copy(dum_it, neuset_elems.end(), range_inserter(reverse_elems)); 01353 01354 // now loop over the contained meshsets, getting the sense of those and calling this 01355 // function recursively 01356 for (range_iter = neuset_meshsets.begin(); range_iter != neuset_meshsets.end(); range_iter++) { 01357 01358 // first get the sense; if it's not there, by convention it's forward 01359 int this_sense; 01360 if (0 == sense_tag || 01361 MB_FAILURE == mbImpl->tag_get_data(sense_tag, &(*range_iter), 1, &this_sense)) 01362 this_sense = 1; 01363 01364 // now get all the entities on this meshset, with the proper (possibly reversed) sense 01365 get_neuset_elems(*range_iter, this_sense*current_sense, 01366 forward_elems, reverse_elems); 01367 } 01368 01369 return result; 01370 } 01371 01372 01373 } // namespace moab 01374 01375