Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 /** @example DeformMeshRemap.cpp 00002 * Description: Account for mesh deformation of a solid due to structural mechanics\n 00003 * In this example there are two meshes, a "master" and "slave" mesh. In the master mesh, 00004 * the solid material is deformed, to mimic what happens when a solid heats up and deforms. 00005 * The fluid mesh is smoothed to account for those deformations, and tags on the fluid are 00006 * remapped to those new positions. Then mesh positions and state variables are transferred 00007 * to the slave mesh, mimicing another mesh used by some other physics. 00008 * 00009 * To run: ./DeformMeshRemap [<master_meshfile> <slave_meshfile>]\n 00010 * (default values can run if users don't specify the mesh files) 00011 */ 00012 00013 #include "moab/Core.hpp" 00014 #include "moab/Range.hpp" 00015 #include "moab/Skinner.hpp" 00016 #include "moab/LloydSmoother.hpp" 00017 #include "moab/ProgOptions.hpp" 00018 #include "moab/BoundBox.hpp" 00019 #include "moab/SpatialLocator.hpp" 00020 #include "MBTagConventions.hpp" 00021 #include "DataCoupler.hpp" 00022 00023 #ifdef USE_MPI 00024 #include "moab/ParallelComm.hpp" 00025 #endif 00026 00027 #include <iostream> 00028 #include <set> 00029 #include <sstream> 00030 #include <cassert> 00031 00032 using namespace moab; 00033 using namespace std; 00034 00035 #ifndef MESH_DIR 00036 #define MESH_DIR "." 00037 #endif 00038 00039 ErrorCode read_file( string& fname, 00040 EntityHandle& seth, 00041 Range& solids, 00042 Range& solid_elems, 00043 Range& fluids, 00044 Range& fluid_elems ); 00045 void deform_func( const BoundBox& bbox, double* xold, double* xnew ); 00046 ErrorCode deform_master( Range& fluid_elems, Range& solid_elems, Tag& xnew ); 00047 ErrorCode smooth_master( int dim, Tag xnew, EntityHandle& master, Range& fluids ); 00048 ErrorCode write_to_coords( Range& elems, Tag tagh ); 00049 00050 const int SOLID_SETNO = 100, FLUID_SETNO = 200; 00051 00052 Interface* mb; 00053 00054 const bool debug = true; 00055 00056 class DeformMeshRemap 00057 { 00058 public: 00059 //! Enumerator for solid/fluid, master/slave 00060 enum 00061 { 00062 MASTER = 0, 00063 SLAVE, 00064 SOLID, 00065 FLUID 00066 }; 00067 00068 //! Constructor 00069 //! If master is NULL, the MOAB part is run in serial; 00070 //! If slave is NULL but the master isn't, the slave is copied from the master 00071 //! Create communicators using moab::ParallelComm::get_pcomm 00072 DeformMeshRemap( Interface* impl, ParallelComm* master = NULL, ParallelComm* slave = NULL ); 00073 00074 //! Destructor 00075 ~DeformMeshRemap(); 00076 00077 //! Execute the deformed mesh process 00078 ErrorCode execute(); 00079 00080 //! Add a set number 00081 ErrorCode add_set_no( int m_or_s, int fluid_or_solid, int set_no ); 00082 00083 //! Remove a set number 00084 ErrorCode remove_set_no( int m_or_s, int fluid_or_solid, int set_no ); 00085 00086 //! Get the set numbers 00087 ErrorCode get_set_nos( int m_or_s, int fluid_or_solid, set< int >& set_nos ) const; 00088 00089 //! Get the xNew tag handle 00090 inline Tag x_new() const 00091 { 00092 return xNew; 00093 } 00094 00095 //! Get the tag name 00096 string x_new_name() const 00097 { 00098 return xNewName; 00099 } 00100 00101 //! Set the tag name 00102 void x_new_name( const string& name ) 00103 { 00104 xNewName = name; 00105 } 00106 00107 //! Get/set the file name 00108 string get_file_name( int m_or_s ) const; 00109 00110 //! Get/set the file name 00111 void set_file_name( int m_or_s, const string& name ); 00112 00113 //! Get/set the x displacement tag names 00114 string xdisp_name( int idx = 0 ); 00115 void xdisp_name( const string& nm, int idx = 0 ); 00116 00117 private: 00118 //! Apply a known deformation to the solid elements, putting the results in the xNew tag; also 00119 //! write current coordinates to the xNew tag for fluid elements 00120 ErrorCode deform_master( Range& fluid_elems, Range& solid_elems, const char* tag_name = NULL ); 00121 00122 //! Read a file and establish proper ranges 00123 ErrorCode read_file( int m_or_s, string& fname, EntityHandle& seth ); 00124 00125 //! Write the input tag to the coordinates for the vertices in the input elems 00126 //! If non-zero tmp_tag is input, save coords to tmp_tag before over-writing with tag value 00127 ErrorCode write_to_coords( Range& elems, Tag tagh, Tag tmp_tag = 0 ); 00128 00129 //! Write the tag to the vertices, then save to the specified file 00130 //! If restore_coords is true, coords are restored to their initial state after file is written 00131 ErrorCode write_and_save( Range& ents, 00132 EntityHandle seth, 00133 Tag tagh, 00134 const char* filename, 00135 bool restore_coords = false ); 00136 00137 //! Find fluid/solid sets from complement of solid/fluid sets 00138 ErrorCode find_other_sets( int m_or_s, EntityHandle file_set ); 00139 00140 //! moab interface 00141 Interface* mbImpl; 00142 00143 #ifdef USE_MPI 00144 //! ParallelComm for master, slave meshes 00145 ParallelComm *pcMaster, *pcSlave; 00146 #endif 00147 00148 //! Material set numbers for fluid materials, for master/slave 00149 set< int > fluidSetNos[2]; 00150 00151 //! Material set numbers for solid materials, for master/slave 00152 set< int > solidSetNos[2]; 00153 00154 //! Sets defining master/slave meshes 00155 EntityHandle masterSet, slaveSet; 00156 00157 //! Sets in master/slave meshes 00158 Range fluidSets[2], solidSets[2]; 00159 00160 //! Elements in master/slave meshes 00161 Range fluidElems[2], solidElems[2]; 00162 00163 //! Filenames for master/slave meshes 00164 string masterFileName, slaveFileName; 00165 00166 //! Tag from file, might be 3 00167 Tag xDisp[3]; 00168 00169 //! Tag used for new positions 00170 Tag xNew; 00171 00172 //! Tag name used to read disps from file 00173 string xDispNames[3]; 00174 00175 //! Tag name used for new positions 00176 string xNewName; 00177 }; 00178 00179 //! Add a set number 00180 inline ErrorCode DeformMeshRemap::add_set_no( int m_or_s, int f_or_s, int set_no ) 00181 { 00182 set< int >* this_set; 00183 assert( ( m_or_s == MASTER || m_or_s == SLAVE ) && "m_or_s should be MASTER or SLAVE." ); 00184 if( m_or_s != MASTER && m_or_s != SLAVE ) return MB_INDEX_OUT_OF_RANGE; 00185 00186 switch( f_or_s ) 00187 { 00188 case FLUID: 00189 this_set = &fluidSetNos[m_or_s]; 00190 break; 00191 case SOLID: 00192 this_set = &solidSetNos[m_or_s]; 00193 break; 00194 default: 00195 assert( false && "f_or_s should be FLUID or SOLID." ); 00196 return MB_FAILURE; 00197 } 00198 00199 this_set->insert( set_no ); 00200 00201 return MB_SUCCESS; 00202 } 00203 00204 //! Remove a set number 00205 inline ErrorCode DeformMeshRemap::remove_set_no( int m_or_s, int f_or_s, int set_no ) 00206 { 00207 set< int >* this_set; 00208 assert( ( m_or_s == MASTER || m_or_s == SLAVE ) && "m_or_s should be MASTER or SLAVE." ); 00209 if( m_or_s != MASTER && m_or_s != SLAVE ) return MB_INDEX_OUT_OF_RANGE; 00210 switch( f_or_s ) 00211 { 00212 case FLUID: 00213 this_set = &fluidSetNos[m_or_s]; 00214 break; 00215 case SOLID: 00216 this_set = &solidSetNos[m_or_s]; 00217 break; 00218 default: 00219 assert( false && "f_or_s should be FLUID or SOLID." ); 00220 return MB_FAILURE; 00221 } 00222 set< int >::iterator sit = this_set->find( set_no ); 00223 if( sit != this_set->end() ) 00224 { 00225 this_set->erase( *sit ); 00226 return MB_SUCCESS; 00227 } 00228 00229 return MB_FAILURE; 00230 } 00231 00232 //! Get the set numbers 00233 inline ErrorCode DeformMeshRemap::get_set_nos( int m_or_s, int f_or_s, set< int >& set_nos ) const 00234 { 00235 const set< int >* this_set; 00236 assert( ( m_or_s == MASTER || m_or_s == SLAVE ) && "m_or_s should be MASTER or SLAVE." ); 00237 if( m_or_s != MASTER && m_or_s != SLAVE ) return MB_INDEX_OUT_OF_RANGE; 00238 switch( f_or_s ) 00239 { 00240 case FLUID: 00241 this_set = &fluidSetNos[m_or_s]; 00242 break; 00243 case SOLID: 00244 this_set = &solidSetNos[m_or_s]; 00245 break; 00246 default: 00247 assert( false && "f_or_s should be FLUID or SOLID." ); 00248 return MB_FAILURE; 00249 } 00250 00251 set_nos = *this_set; 00252 00253 return MB_SUCCESS; 00254 } 00255 00256 inline string DeformMeshRemap::xdisp_name( int idx ) 00257 { 00258 return xDispNames[idx]; 00259 } 00260 00261 void DeformMeshRemap::xdisp_name( const string& nm, int idx ) 00262 { 00263 xDispNames[idx] = nm; 00264 } 00265 00266 ErrorCode DeformMeshRemap::execute() 00267 { 00268 // Read master/slave files and get fluid/solid material sets 00269 ErrorCode rval = read_file( MASTER, masterFileName, masterSet );MB_CHK_ERR( rval ); 00270 00271 if( solidSetNos[MASTER].empty() || fluidSetNos[MASTER].empty() ) 00272 { 00273 rval = find_other_sets( MASTER, masterSet );MB_CHK_SET_ERR( rval, "Failed to find other sets in master mesh" ); 00274 } 00275 00276 bool have_slave = !( slaveFileName == "none" ); 00277 if( have_slave ) 00278 { 00279 rval = read_file( SLAVE, slaveFileName, slaveSet );MB_CHK_ERR( rval ); 00280 00281 if( solidSetNos[SLAVE].empty() || fluidSetNos[SLAVE].empty() ) 00282 { 00283 rval = find_other_sets( SLAVE, slaveSet );MB_CHK_SET_ERR( rval, "Failed to find other sets in slave mesh" ); 00284 } 00285 } 00286 00287 if( debug ) cout << "Constructing data coupler/search tree on master mesh..." << endl; 00288 00289 Range src_elems = solidElems[MASTER]; 00290 src_elems.merge( fluidElems[MASTER] ); 00291 00292 // Initialize data coupler on source elements 00293 DataCoupler dc_master( mbImpl, src_elems, 0, NULL ); 00294 00295 Range tgt_verts; 00296 if( have_slave ) 00297 { 00298 // Locate slave vertices in master, orig coords; do this with a data coupler, so you can 00299 // later interpolate 00300 Range tmp_range = solidElems[SLAVE]; 00301 tmp_range.merge( fluidElems[SLAVE] ); 00302 rval = mbImpl->get_adjacencies( tmp_range, 0, false, tgt_verts, Interface::UNION );MB_CHK_SET_ERR( rval, "Failed to get target verts" ); 00303 00304 // Locate slave vertices, caching results in dc 00305 if( debug ) cout << "Locating slave vertices in master mesh..." << endl; 00306 rval = dc_master.locate_points( tgt_verts );MB_CHK_SET_ERR( rval, "Point location of tgt verts failed" ); 00307 int num_located = dc_master.spatial_locator()->local_num_located(); 00308 if( num_located != (int)tgt_verts.size() ) 00309 { 00310 rval = MB_FAILURE; 00311 cout << "Only " << num_located << " out of " << tgt_verts.size() << " target points successfully located." 00312 << endl; 00313 return rval; 00314 } 00315 } 00316 00317 // Deform the master's solid mesh, put results in a new tag 00318 if( debug ) cout << "Deforming fluid elements in master mesh..." << endl; 00319 rval = deform_master( fluidElems[MASTER], solidElems[MASTER], "xnew" );MB_CHK_ERR( rval ); 00320 00321 { // To isolate the lloyd smoother & delete when done 00322 if( debug ) 00323 { 00324 // Output the skin of smoothed elems, as a check 00325 // Get the skin; get facets, because we might need to filter on shared entities 00326 Skinner skinner( mbImpl ); 00327 Range skin; 00328 rval = skinner.find_skin( 0, fluidElems[MASTER], false, skin );MB_CHK_SET_ERR( rval, "Unable to find skin" ); 00329 EntityHandle skin_set; 00330 cout << "Writing skin_mesh.g and fluid_mesh.g." << endl; 00331 rval = mbImpl->create_meshset( MESHSET_SET, skin_set );MB_CHK_SET_ERR( rval, "Failed to create skin set" ); 00332 rval = mbImpl->add_entities( skin_set, skin );MB_CHK_SET_ERR( rval, "Failed to add skin entities to set" ); 00333 rval = mbImpl->write_file( "skin_mesh.vtk", NULL, NULL, &skin_set, 1 );MB_CHK_SET_ERR( rval, "Failure to write skin set" ); 00334 rval = mbImpl->remove_entities( skin_set, skin );MB_CHK_SET_ERR( rval, "Failed to remove skin entities from set" ); 00335 rval = mbImpl->add_entities( skin_set, fluidElems[MASTER] );MB_CHK_SET_ERR( rval, "Failed to add fluid entities to set" ); 00336 rval = mbImpl->write_file( "fluid_mesh.vtk", NULL, NULL, &skin_set, 1 );MB_CHK_SET_ERR( rval, "Failure to write fluid set" ); 00337 rval = mbImpl->delete_entities( &skin_set, 1 );MB_CHK_SET_ERR( rval, "Failed to delete skin set" ); 00338 } 00339 00340 // Smooth the master mesh 00341 if( debug ) cout << "Smoothing fluid elements in master mesh..." << endl; 00342 LloydSmoother ll( mbImpl, NULL, fluidElems[MASTER], xNew ); 00343 rval = ll.perform_smooth();MB_CHK_SET_ERR( rval, "Failed in lloyd smoothing" ); 00344 cout << "Lloyd smoothing required " << ll.num_its() << " iterations." << endl; 00345 } 00346 00347 // Transfer xNew to coords, for master 00348 if( debug ) cout << "Transferring coords tag to vertex coordinates in master mesh..." << endl; 00349 rval = write_to_coords( solidElems[MASTER], xNew );MB_CHK_SET_ERR( rval, "Failed writing tag to master fluid verts" ); 00350 rval = write_to_coords( fluidElems[MASTER], xNew );MB_CHK_SET_ERR( rval, "Failed writing tag to master fluid verts" ); 00351 00352 if( have_slave ) 00353 { 00354 // Map new locations to slave 00355 // Interpolate xNew to slave points 00356 if( debug ) cout << "Interpolating new coordinates to slave vertices..." << endl; 00357 rval = dc_master.interpolate( (int)DataCoupler::VOLUME, "xnew" );MB_CHK_SET_ERR( rval, "Failed to interpolate target solution" ); 00358 // Transfer xNew to coords, for slave 00359 if( debug ) cout << "Transferring coords tag to vertex coordinates in slave mesh..." << endl; 00360 rval = write_to_coords( tgt_verts, xNew );MB_CHK_SET_ERR( rval, "Failed writing tag to slave verts" ); 00361 } 00362 00363 if( debug ) 00364 { 00365 string str; 00366 #ifdef USE_MPI 00367 if( pcMaster && pcMaster->size() > 1 ) str = "PARALLEL=WRITE_PART"; 00368 #endif 00369 if( debug ) cout << "Writing smoothed_master.h5m..." << endl; 00370 rval = mbImpl->write_file( "smoothed_master.h5m", NULL, str.c_str(), &masterSet, 1 ); 00371 00372 if( have_slave ) 00373 { 00374 #ifdef USE_MPI 00375 str.clear(); 00376 if( pcSlave && pcSlave->size() > 1 ) str = "PARALLEL=WRITE_PART"; 00377 #endif 00378 if( debug ) cout << "Writing slave_interp.h5m..." << endl; 00379 rval = mbImpl->write_file( "slave_interp.h5m", NULL, str.c_str(), &slaveSet, 1 ); 00380 } // if have_slave 00381 } // if debug 00382 00383 if( debug ) dc_master.spatial_locator()->get_tree()->tree_stats().print(); 00384 00385 return MB_SUCCESS; 00386 } 00387 00388 string DeformMeshRemap::get_file_name( int m_or_s ) const 00389 { 00390 switch( m_or_s ) 00391 { 00392 case MASTER: 00393 return masterFileName; 00394 case SLAVE: 00395 return slaveFileName; 00396 default: 00397 assert( false && "m_or_s should be MASTER or SLAVE." ); 00398 return string(); 00399 } 00400 } 00401 00402 void DeformMeshRemap::set_file_name( int m_or_s, const string& name ) 00403 { 00404 switch( m_or_s ) 00405 { 00406 case MASTER: 00407 masterFileName = name; 00408 break; 00409 case SLAVE: 00410 slaveFileName = name; 00411 break; 00412 default: 00413 assert( false && "m_or_s should be MASTER or SLAVE." ); 00414 } 00415 } 00416 00417 DeformMeshRemap::DeformMeshRemap( Interface* impl, ParallelComm* master, ParallelComm* slave ) 00418 : mbImpl( impl ), pcMaster( master ), pcSlave( slave ), masterSet( 0 ), slaveSet( 0 ), xNew( 0 ), xNewName( "xnew" ) 00419 { 00420 xDisp[0] = xDisp[1] = xDisp[2] = 0; 00421 00422 if( !pcSlave && pcMaster ) pcSlave = pcMaster; 00423 } 00424 00425 DeformMeshRemap::~DeformMeshRemap() {} 00426 00427 int main( int argc, char** argv ) 00428 { 00429 ErrorCode rval; 00430 00431 ProgOptions po( "Deformed mesh options" ); 00432 po.addOpt< string >( "master,m", "Specify the master meshfile name" ); 00433 po.addOpt< string >( "worker,w", "Specify the slave/worker meshfile name, or 'none' (no quotes) if master only" ); 00434 po.addOpt< string >( "d1,", "Tag name for displacement x or xyz" ); 00435 po.addOpt< string >( "d2,", "Tag name for displacement y" ); 00436 po.addOpt< string >( "d3,", "Tag name for displacement z" ); 00437 po.addOpt< int >( "fm,", "Specify master fluid material set number(s). If none specified, " 00438 "fluid sets derived from complement of solid sets." ); 00439 po.addOpt< int >( "fs,", "Specify master solid material set number(s). If none specified, " 00440 "solid sets derived from complement of fluid sets." ); 00441 po.addOpt< int >( "sm,", "Specify slave fluid material set number(s). If none specified, fluid " 00442 "sets derived from complement of solid sets." ); 00443 po.addOpt< int >( "ss,", "Specify slave solid material set number(s). If none specified, solid " 00444 "sets derived from complement of fluid sets." ); 00445 00446 po.parseCommandLine( argc, argv ); 00447 00448 mb = new Core(); 00449 00450 DeformMeshRemap* dfr; 00451 #ifdef USE_MPI 00452 ParallelComm* pc = new ParallelComm( mb, MPI_COMM_WORLD ); 00453 dfr = new DeformMeshRemap( mb, pc ); 00454 #else 00455 dfr = new DeformMeshRemap( mb ); 00456 #endif 00457 00458 string masterf, slavef; 00459 if( !po.getOpt( "master", &masterf ) ) masterf = string( MESH_DIR ) + string( "/rodquad.g" ); 00460 dfr->set_file_name( DeformMeshRemap::MASTER, masterf ); 00461 00462 if( !po.getOpt( "worker", &slavef ) ) slavef = string( MESH_DIR ) + string( "/rodtri.g" ); 00463 dfr->set_file_name( DeformMeshRemap::SLAVE, slavef ); 00464 if( slavef.empty() ) 00465 { 00466 cerr << "Empty slave file name; if no slave, use filename 'none' (no quotes)." << endl; 00467 return 1; 00468 } 00469 00470 vector< int > set_nos; 00471 po.getOptAllArgs( "fm", set_nos ); 00472 for( vector< int >::iterator vit = set_nos.begin(); vit != set_nos.end(); ++vit ) 00473 dfr->add_set_no( DeformMeshRemap::MASTER, DeformMeshRemap::FLUID, *vit ); 00474 set_nos.clear(); 00475 00476 po.getOptAllArgs( "fs", set_nos ); 00477 for( vector< int >::iterator vit = set_nos.begin(); vit != set_nos.end(); ++vit ) 00478 dfr->add_set_no( DeformMeshRemap::SLAVE, DeformMeshRemap::FLUID, *vit ); 00479 set_nos.clear(); 00480 00481 po.getOptAllArgs( "sm", set_nos ); 00482 for( vector< int >::iterator vit = set_nos.begin(); vit != set_nos.end(); ++vit ) 00483 dfr->add_set_no( DeformMeshRemap::MASTER, DeformMeshRemap::SOLID, *vit ); 00484 00485 po.getOptAllArgs( "ss", set_nos ); 00486 for( vector< int >::iterator vit = set_nos.begin(); vit != set_nos.end(); ++vit ) 00487 dfr->add_set_no( DeformMeshRemap::SLAVE, DeformMeshRemap::SOLID, *vit ); 00488 00489 string tnames[3]; 00490 po.getOpt( "d1", &tnames[0] ); 00491 po.getOpt( "d2", &tnames[1] ); 00492 po.getOpt( "d3", &tnames[2] ); 00493 for( int i = 0; i < 3; i++ ) 00494 if( !tnames[i].empty() ) dfr->xdisp_name( tnames[i], i ); 00495 00496 rval = dfr->execute(); 00497 00498 delete dfr; 00499 delete mb; 00500 00501 return rval; 00502 } 00503 00504 ErrorCode DeformMeshRemap::write_and_save( Range& ents, 00505 EntityHandle seth, 00506 Tag tagh, 00507 const char* filename, 00508 bool restore_coords ) 00509 { 00510 Tag tmp_tag = 0; 00511 ErrorCode rval; 00512 if( restore_coords ) rval = mbImpl->tag_get_handle( "", 3, MB_TYPE_DOUBLE, tmp_tag, MB_TAG_CREAT | MB_TAG_DENSE ); 00513 00514 rval = write_to_coords( ents, tagh, tmp_tag );MB_CHK_ERR( rval ); 00515 rval = mbImpl->write_file( filename, NULL, NULL, &seth, 1 );MB_CHK_ERR( rval ); 00516 if( restore_coords ) 00517 { 00518 rval = write_to_coords( ents, tmp_tag );MB_CHK_ERR( rval ); 00519 rval = mbImpl->tag_delete( tmp_tag );MB_CHK_ERR( rval ); 00520 } 00521 00522 return rval; 00523 } 00524 00525 ErrorCode DeformMeshRemap::write_to_coords( Range& elems, Tag tagh, Tag tmp_tag ) 00526 { 00527 // Write the tag to coordinates 00528 Range verts; 00529 ErrorCode rval = mbImpl->get_adjacencies( elems, 0, false, verts, Interface::UNION );MB_CHK_SET_ERR( rval, "Failed to get adj vertices" ); 00530 vector< double > coords( 3 * verts.size() ); 00531 00532 if( tmp_tag ) 00533 { 00534 // Save the coords to tmp_tag first 00535 rval = mbImpl->get_coords( verts, &coords[0] );MB_CHK_SET_ERR( rval, "Failed to get tmp copy of coords" ); 00536 rval = mbImpl->tag_set_data( tmp_tag, verts, &coords[0] );MB_CHK_SET_ERR( rval, "Failed to save tmp copy of coords" ); 00537 } 00538 00539 rval = mbImpl->tag_get_data( tagh, verts, &coords[0] );MB_CHK_SET_ERR( rval, "Failed to get tag data" ); 00540 rval = mbImpl->set_coords( verts, &coords[0] );MB_CHK_SET_ERR( rval, "Failed to set coordinates" ); 00541 return MB_SUCCESS; 00542 } 00543 00544 void deform_func( const BoundBox& bbox, double* xold, double* xnew ) 00545 { 00546 /* Deformation function based on max delx and dely at top of rod 00547 const double RODWIDTH = 0.2, RODHEIGHT = 0.5; 00548 // function: origin is at middle base of rod, and is .5 high 00549 // top of rod is (0,.55) on left and (.2,.6) on right 00550 double delx = 0.5*RODWIDTH; 00551 00552 double xfrac = (xold[0] + .5*RODWIDTH)/RODWIDTH, yfrac = xold[1]/RODHEIGHT; 00553 xnew[0] = xold[0] + yfrac * delx; 00554 xnew[1] = xold[1] + yfrac * (1.0 + xfrac) * 0.05; 00555 */ 00556 /* Deformation function based on fraction of bounding box dimension in each direction */ 00557 double frac = 0.01; // taken from approximate relative deformation from LLNL Diablo of XX09 assys 00558 CartVect *xo = reinterpret_cast< CartVect* >( xold ), *xn = reinterpret_cast< CartVect* >( xnew ); 00559 CartVect disp = frac * ( *xo - bbox.bMin ); 00560 *xn = *xo + disp; 00561 } 00562 00563 ErrorCode DeformMeshRemap::deform_master( Range& fluid_elems, Range& solid_elems, const char* tag_name ) 00564 { 00565 // Deform elements with an analytic function 00566 ErrorCode rval; 00567 00568 // Get all the vertices and coords in the solid 00569 Range solid_verts, fluid_verts; 00570 rval = mbImpl->get_adjacencies( solid_elems, 0, false, solid_verts, Interface::UNION );MB_CHK_SET_ERR( rval, "Failed to get vertices" ); 00571 vector< double > coords( 3 * solid_verts.size() ), new_coords( 3 * solid_verts.size() ); 00572 rval = mbImpl->get_coords( solid_verts, &coords[0] );MB_CHK_SET_ERR( rval, "Failed to get vertex coords" ); 00573 unsigned int num_verts = solid_verts.size(); 00574 00575 // Get or create the tag 00576 if( !xDispNames[0].empty() && !xDispNames[1].empty() && !xDispNames[2].empty() ) 00577 { 00578 // 3 tags, specifying xyz individual data, integrate into one tag 00579 rval = mbImpl->tag_get_handle( ( tag_name ? tag_name : "" ), 3, MB_TYPE_DOUBLE, xNew, 00580 MB_TAG_CREAT | MB_TAG_DENSE );MB_CHK_SET_ERR( rval, "Failed to create xnew tag" ); 00581 vector< double > disps( num_verts ); 00582 for( int i = 0; i < 3; i++ ) 00583 { 00584 rval = mbImpl->tag_get_handle( xDispNames[0].c_str(), 1, MB_TYPE_DOUBLE, xDisp[i] );MB_CHK_SET_ERR( rval, "Failed to get xDisp tag" ); 00585 rval = mbImpl->tag_get_data( xDisp[i], solid_verts, &disps[0] );MB_CHK_SET_ERR( rval, "Failed to get xDisp tag values" ); 00586 for( unsigned int j = 0; j < num_verts; j++ ) 00587 new_coords[3 * j + i] = coords[3 * j + i] + disps[j]; 00588 } 00589 } 00590 else if( !xDispNames[0].empty() ) 00591 { 00592 rval = mbImpl->tag_get_handle( xDispNames[0].c_str(), 3, MB_TYPE_DOUBLE, xDisp[0] );MB_CHK_SET_ERR( rval, "Failed to get first xDisp tag" ); 00593 xNew = xDisp[0]; 00594 vector< double > disps( 3 * num_verts ); 00595 rval = mbImpl->tag_get_data( xDisp[0], solid_verts, &disps[0] ); 00596 for( unsigned int j = 0; j < 3 * num_verts; j++ ) 00597 new_coords[j] = coords[j] + disps[j]; 00598 } 00599 else 00600 { 00601 // Get the bounding box of the solid mesh 00602 BoundBox bbox; 00603 bbox.update( *mbImpl, solid_elems ); 00604 00605 for( unsigned int j = 0; j < num_verts; j++ ) 00606 deform_func( bbox, &coords[3 * j], &new_coords[3 * j] ); 00607 } 00608 00609 if( debug ) 00610 { 00611 double len = 0.0; 00612 for( unsigned int i = 0; i < num_verts; i++ ) 00613 { 00614 CartVect dx = CartVect( &new_coords[3 * i] ) - CartVect( &coords[3 * i] ); 00615 double tmp_len = dx.length_squared(); 00616 if( tmp_len > len ) len = tmp_len; 00617 } 00618 Range tmp_elems( fluid_elems ); 00619 tmp_elems.merge( solid_elems ); 00620 BoundBox box; 00621 box.update( *mbImpl, tmp_elems ); 00622 double max_len = 00623 std::max( box.bMax[2] - box.bMin[2], std::max( box.bMax[1] - box.bMin[1], box.bMax[0] - box.bMin[0] ) ); 00624 00625 cout << "Max displacement = " << len << " (" << 100.0 * len / max_len << "% of max box length)" << endl; 00626 } 00627 00628 if( !xNew ) 00629 { 00630 rval = mbImpl->tag_get_handle( ( tag_name ? tag_name : "" ), 3, MB_TYPE_DOUBLE, xDisp[0], 00631 MB_TAG_CREAT | MB_TAG_DENSE );MB_CHK_SET_ERR( rval, "Failed to get xNew tag" ); 00632 xNew = xDisp[0]; 00633 } 00634 00635 // Set the new tag to those coords 00636 rval = mbImpl->tag_set_data( xNew, solid_verts, &new_coords[0] );MB_CHK_SET_ERR( rval, "Failed to set tag data" ); 00637 00638 // Get all the vertices and coords in the fluid, set xnew to them 00639 rval = mbImpl->get_adjacencies( fluid_elems, 0, false, fluid_verts, Interface::UNION );MB_CHK_SET_ERR( rval, "Failed to get vertices" ); 00640 fluid_verts = subtract( fluid_verts, solid_verts ); 00641 00642 if( coords.size() < 3 * fluid_verts.size() ) coords.resize( 3 * fluid_verts.size() ); 00643 rval = mbImpl->get_coords( fluid_verts, &coords[0] );MB_CHK_SET_ERR( rval, "Failed to get vertex coords" ); 00644 rval = mbImpl->tag_set_data( xNew, fluid_verts, &coords[0] );MB_CHK_SET_ERR( rval, "Failed to set xnew tag on fluid verts" ); 00645 00646 if( debug ) 00647 { 00648 // Save deformed mesh coords to new file for visualizing 00649 Range tmp_range( fluidElems[MASTER] ); 00650 tmp_range.merge( solidElems[MASTER] ); 00651 rval = write_and_save( tmp_range, masterSet, xNew, "deformed_master.h5m", true );MB_CHK_ERR( rval ); 00652 } 00653 00654 return MB_SUCCESS; 00655 } 00656 00657 ErrorCode DeformMeshRemap::read_file( int m_or_s, string& fname, EntityHandle& seth ) 00658 { 00659 // Create meshset 00660 ErrorCode rval = mbImpl->create_meshset( 0, seth );MB_CHK_SET_ERR( rval, "Couldn't create master/slave set" ); 00661 ostringstream options; 00662 #ifdef USE_MPI 00663 ParallelComm* pc = ( m_or_s == MASTER ? pcMaster : pcSlave ); 00664 if( pc && pc->size() > 1 ) 00665 { 00666 if( debug ) options << "DEBUG_IO=1;CPUTIME;"; 00667 options << "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARALLEL_RESOLVE_SHARED_ENTS;" 00668 << "PARALLEL_GHOSTS=2.0.1;PARALLEL_COMM=" << pc->get_id(); 00669 } 00670 #endif 00671 rval = mbImpl->load_file( fname.c_str(), &seth, options.str().c_str() );MB_CHK_SET_ERR( rval, "Couldn't load master/slave mesh" ); 00672 00673 if( *solidSetNos[m_or_s].begin() == -1 || *fluidSetNos[m_or_s].begin() == -1 ) return MB_SUCCESS; 00674 00675 // Get material sets for solid/fluid 00676 Tag tagh; 00677 rval = mbImpl->tag_get_handle( MATERIAL_SET_TAG_NAME, tagh );MB_CHK_SET_ERR( rval, "Couldn't get material set tag name" ); 00678 for( set< int >::iterator sit = solidSetNos[m_or_s].begin(); sit != solidSetNos[m_or_s].end(); ++sit ) 00679 { 00680 Range sets; 00681 int set_no = *sit; 00682 const void* setno_ptr = &set_no; 00683 rval = mbImpl->get_entities_by_type_and_tag( seth, MBENTITYSET, &tagh, &setno_ptr, 1, sets ); 00684 if( MB_SUCCESS != rval || sets.empty() ) 00685 { 00686 MB_SET_ERR( MB_FAILURE, "Couldn't find solid set #" << *sit ); 00687 } 00688 else 00689 solidSets[m_or_s].merge( sets ); 00690 } 00691 00692 // Get solid entities, and dimension 00693 Range tmp_range; 00694 for( Range::iterator rit = solidSets[m_or_s].begin(); rit != solidSets[m_or_s].end(); ++rit ) 00695 { 00696 rval = mbImpl->get_entities_by_handle( *rit, tmp_range, true );MB_CHK_SET_ERR( rval, "Failed to get entities in solid" ); 00697 } 00698 if( !tmp_range.empty() ) 00699 { 00700 int dim = mbImpl->dimension_from_handle( *tmp_range.rbegin() ); 00701 assert( dim > 0 && dim < 4 ); 00702 solidElems[m_or_s] = tmp_range.subset_by_dimension( dim ); 00703 } 00704 00705 if( debug ) 00706 cout << "Read " << solidElems[m_or_s].size() << " solid elements from " << solidSets[m_or_s].size() 00707 << " sets in " << ( m_or_s == MASTER ? "master" : "slave" ) << " mesh." << endl; 00708 00709 for( set< int >::iterator sit = fluidSetNos[m_or_s].begin(); sit != fluidSetNos[m_or_s].end(); ++sit ) 00710 { 00711 Range sets; 00712 int set_no = *sit; 00713 const void* setno_ptr = &set_no; 00714 rval = mbImpl->get_entities_by_type_and_tag( seth, MBENTITYSET, &tagh, &setno_ptr, 1, sets ); 00715 if( MB_SUCCESS != rval || sets.empty() ) 00716 { 00717 MB_SET_ERR( MB_FAILURE, "Couldn't find fluid set #" << *sit ); 00718 } 00719 else 00720 fluidSets[m_or_s].merge( sets ); 00721 } 00722 00723 // Get fluid entities, and dimension 00724 tmp_range.clear(); 00725 for( Range::iterator rit = fluidSets[m_or_s].begin(); rit != fluidSets[m_or_s].end(); ++rit ) 00726 { 00727 rval = mbImpl->get_entities_by_handle( *rit, tmp_range, true );MB_CHK_SET_ERR( rval, "Failed to get entities in fluid" ); 00728 } 00729 if( !tmp_range.empty() ) 00730 { 00731 int dim = mbImpl->dimension_from_handle( *tmp_range.rbegin() ); 00732 assert( dim > 0 && dim < 4 ); 00733 fluidElems[m_or_s] = tmp_range.subset_by_dimension( dim ); 00734 } 00735 00736 if( debug ) 00737 cout << "Read " << fluidElems[m_or_s].size() << " fluid elements from " << fluidSets[m_or_s].size() 00738 << " sets in " << ( m_or_s == MASTER ? "master" : "slave" ) << " mesh." << endl; 00739 00740 return rval; 00741 } 00742 00743 ErrorCode DeformMeshRemap::find_other_sets( int m_or_s, EntityHandle file_set ) 00744 { 00745 // Solid or fluid sets are missing; find the other 00746 Range *filled_sets = NULL, *unfilled_sets = NULL, *unfilled_elems = NULL; 00747 00748 if( fluidSets[m_or_s].empty() && !solidSets[m_or_s].empty() ) 00749 { 00750 unfilled_sets = &fluidSets[m_or_s]; 00751 filled_sets = &solidSets[m_or_s]; 00752 unfilled_elems = &fluidElems[m_or_s]; 00753 if( debug ) 00754 cout << "Finding unspecified fluid elements in " << ( m_or_s == MASTER ? "master" : "slave" ) << " mesh..."; 00755 } 00756 else if( !fluidSets[m_or_s].empty() && solidSets[m_or_s].empty() ) 00757 { 00758 filled_sets = &fluidSets[m_or_s]; 00759 unfilled_sets = &solidSets[m_or_s]; 00760 unfilled_elems = &solidElems[m_or_s]; 00761 if( debug ) 00762 cout << "Finding unspecified solid elements in " << ( m_or_s == MASTER ? "master" : "slave" ) << " mesh..."; 00763 } 00764 00765 // Ok, we know the filled sets, now fill the unfilled sets, and the elems from those 00766 Tag tagh; 00767 ErrorCode rval = mbImpl->tag_get_handle( MATERIAL_SET_TAG_NAME, tagh );MB_CHK_SET_ERR( rval, "Couldn't get material set tag name" ); 00768 Range matsets; 00769 rval = mbImpl->get_entities_by_type_and_tag( file_set, MBENTITYSET, &tagh, NULL, 1, matsets ); 00770 if( MB_SUCCESS != rval || matsets.empty() ) 00771 { 00772 MB_SET_ERR( MB_FAILURE, "Couldn't get any material sets" ); 00773 } 00774 *unfilled_sets = subtract( matsets, *filled_sets ); 00775 if( unfilled_sets->empty() ) 00776 { 00777 MB_SET_ERR( MB_FAILURE, "Failed to find any unfilled material sets" ); 00778 } 00779 Range tmp_range; 00780 for( Range::iterator rit = unfilled_sets->begin(); rit != unfilled_sets->end(); ++rit ) 00781 { 00782 rval = mbImpl->get_entities_by_handle( *rit, tmp_range, true );MB_CHK_SET_ERR( rval, "Failed to get entities in unfilled set" ); 00783 } 00784 int dim = mbImpl->dimension_from_handle( *tmp_range.rbegin() ); 00785 assert( dim > 0 && dim < 4 ); 00786 *unfilled_elems = tmp_range.subset_by_dimension( dim ); 00787 if( unfilled_elems->empty() ) 00788 { 00789 MB_SET_ERR( MB_FAILURE, "Failed to find any unfilled set entities" ); 00790 } 00791 00792 if( debug ) 00793 cout << "found " << unfilled_sets->size() << " sets and " << unfilled_elems->size() << " elements." << endl; 00794 00795 return MB_SUCCESS; 00796 }