moab
WriteCCMIO.cpp
Go to the documentation of this file.
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   
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines