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