#ifdef USE_MPI
#endif
#include <iostream>
#include <set>
#include <sstream>
#include <cassert>
using namespace std;
#ifndef MESH_DIR
#define MESH_DIR "."
#endif
Range& solids,
Range& solid_elems,
Range& fluids,
Range& fluid_elems );
void deform_func(
const BoundBox& bbox,
double* xold,
double* xnew );
{
public:
enum
{
MASTER = 0,
SLAVE,
FLUID
};
DeformMeshRemap( Interface* impl, ParallelComm* master = NULL, ParallelComm* slave = NULL );
ErrorCode add_set_no(
int m_or_s,
int fluid_or_solid,
int set_no );
ErrorCode remove_set_no(
int m_or_s,
int fluid_or_solid,
int set_no );
ErrorCode get_set_nos(
int m_or_s,
int fluid_or_solid, set< int >& set_nos )
const;
{
return xNew;
}
string x_new_name() const
{
return xNewName;
}
void x_new_name( const string& name )
{
xNewName = name;
}
string get_file_name( int m_or_s ) const;
void set_file_name( int m_or_s, const string& name );
string xdisp_name( int idx = 0 );
void xdisp_name( const string& nm, int idx = 0 );
private:
const char* filename,
bool restore_coords = false );
Interface* mbImpl;
#ifdef USE_MPI
ParallelComm *pcMaster, *pcSlave;
#endif
set< int > fluidSetNos[2];
set< int > solidSetNos[2];
Range fluidSets[2], solidSets[2];
Range fluidElems[2], solidElems[2];
string masterFileName, slaveFileName;
string xDispNames[3];
string xNewName;
};
{
set< int >* this_set;
assert( ( m_or_s == MASTER || m_or_s == SLAVE ) && "m_or_s should be MASTER or SLAVE." );
switch( f_or_s )
{
case FLUID:
this_set = &fluidSetNos[m_or_s];
break;
this_set = &solidSetNos[m_or_s];
break;
default:
assert( false && "f_or_s should be FLUID or SOLID." );
return MB_FAILURE;
}
this_set->insert( set_no );
}
{
set< int >* this_set;
assert( ( m_or_s == MASTER || m_or_s == SLAVE ) && "m_or_s should be MASTER or SLAVE." );
switch( f_or_s )
{
case FLUID:
this_set = &fluidSetNos[m_or_s];
break;
this_set = &solidSetNos[m_or_s];
break;
default:
assert( false && "f_or_s should be FLUID or SOLID." );
return MB_FAILURE;
}
set< int >::iterator sit = this_set->find( set_no );
if( sit != this_set->end() )
{
this_set->erase( *sit );
}
return MB_FAILURE;
}
{
const set< int >* this_set;
assert( ( m_or_s == MASTER || m_or_s == SLAVE ) && "m_or_s should be MASTER or SLAVE." );
switch( f_or_s )
{
case FLUID:
this_set = &fluidSetNos[m_or_s];
break;
this_set = &solidSetNos[m_or_s];
break;
default:
assert( false && "f_or_s should be FLUID or SOLID." );
return MB_FAILURE;
}
set_nos = *this_set;
}
{
return xDispNames[idx];
}
{
xDispNames[idx] = nm;
}
{
if( solidSetNos[MASTER].empty() || fluidSetNos[MASTER].empty() )
{
rval = find_other_sets( MASTER, masterSet );
MB_CHK_SET_ERR( rval,
"Failed to find other sets in master mesh" );
}
bool have_slave = !( slaveFileName == "none" );
if( have_slave )
{
if( solidSetNos[SLAVE].empty() || fluidSetNos[SLAVE].empty() )
{
rval = find_other_sets( SLAVE, slaveSet );
MB_CHK_SET_ERR( rval,
"Failed to find other sets in slave mesh" );
}
}
if(
debug ) cout <<
"Constructing data coupler/search tree on master mesh..." << endl;
Range src_elems = solidElems[MASTER];
src_elems.merge( fluidElems[MASTER] );
DataCoupler dc_master( mbImpl, src_elems, 0, NULL );
Range tgt_verts;
if( have_slave )
{
Range tmp_range = solidElems[SLAVE];
tmp_range.merge( fluidElems[SLAVE] );
if(
debug ) cout <<
"Locating slave vertices in master mesh..." << endl;
rval = dc_master.locate_points( tgt_verts );
MB_CHK_SET_ERR( rval,
"Point location of tgt verts failed" );
int num_located = dc_master.spatial_locator()->local_num_located();
if( num_located != (int)tgt_verts.size() )
{
rval = MB_FAILURE;
cout << "Only " << num_located << " out of " << tgt_verts.size() << " target points successfully located."
<< endl;
return rval;
}
}
if(
debug ) cout <<
"Deforming fluid elements in master mesh..." << endl;
{
{
Skinner skinner( mbImpl );
Range skin;
rval = skinner.find_skin( 0, fluidElems[MASTER],
false, skin );
MB_CHK_SET_ERR( rval,
"Unable to find skin" );
cout << "Writing skin_mesh.g and fluid_mesh.g." << endl;
rval = mbImpl->add_entities( skin_set, skin );
MB_CHK_SET_ERR( rval,
"Failed to add skin entities to set" );
rval = mbImpl->write_file(
"skin_mesh.vtk", NULL, NULL, &skin_set, 1 );
MB_CHK_SET_ERR( rval,
"Failure to write skin set" );
rval = mbImpl->remove_entities( skin_set, skin );
MB_CHK_SET_ERR( rval,
"Failed to remove skin entities from set" );
rval = mbImpl->add_entities( skin_set, fluidElems[MASTER] );
MB_CHK_SET_ERR( rval,
"Failed to add fluid entities to set" );
rval = mbImpl->write_file(
"fluid_mesh.vtk", NULL, NULL, &skin_set, 1 );
MB_CHK_SET_ERR( rval,
"Failure to write fluid set" );
rval = mbImpl->delete_entities( &skin_set, 1 );
MB_CHK_SET_ERR( rval,
"Failed to delete skin set" );
}
if(
debug ) cout <<
"Smoothing fluid elements in master mesh..." << endl;
LloydSmoother ll( mbImpl, NULL, fluidElems[MASTER], xNew );
rval = ll.perform_smooth();
MB_CHK_SET_ERR( rval,
"Failed in lloyd smoothing" );
cout << "Lloyd smoothing required " << ll.num_its() << " iterations." << endl;
}
if(
debug ) cout <<
"Transferring coords tag to vertex coordinates in master mesh..." << endl;
if( have_slave )
{
if(
debug ) cout <<
"Interpolating new coordinates to slave vertices..." << endl;
if(
debug ) cout <<
"Transferring coords tag to vertex coordinates in slave mesh..." << endl;
}
{
string str;
#ifdef USE_MPI
if( pcMaster && pcMaster->size() > 1 ) str = "PARALLEL=WRITE_PART";
#endif
if(
debug ) cout <<
"Writing smoothed_master.h5m..." << endl;
rval = mbImpl->write_file( "smoothed_master.h5m", NULL, str.c_str(), &masterSet, 1 );
if( have_slave )
{
#ifdef USE_MPI
str.clear();
if( pcSlave && pcSlave->size() > 1 ) str = "PARALLEL=WRITE_PART";
#endif
if(
debug ) cout <<
"Writing slave_interp.h5m..." << endl;
rval = mbImpl->write_file( "slave_interp.h5m", NULL, str.c_str(), &slaveSet, 1 );
}
}
if(
debug ) dc_master.spatial_locator()->get_tree()->tree_stats().print();
}
{
switch( m_or_s )
{
case MASTER:
return masterFileName;
case SLAVE:
return slaveFileName;
default:
assert( false && "m_or_s should be MASTER or SLAVE." );
return string();
}
}
{
switch( m_or_s )
{
case MASTER:
masterFileName = name;
break;
case SLAVE:
slaveFileName = name;
break;
default:
assert( false && "m_or_s should be MASTER or SLAVE." );
}
}
: mbImpl( impl ), pcMaster( master ), pcSlave( slave ), masterSet( 0 ), slaveSet( 0 ), xNew( 0 ), xNewName( "xnew" )
{
xDisp[0] = xDisp[1] = xDisp[2] = 0;
if( !pcSlave && pcMaster ) pcSlave = pcMaster;
}
int main(
int argc,
char** argv )
{
po.addOpt< string >( "master,m", "Specify the master meshfile name" );
po.addOpt< string >( "worker,w", "Specify the slave/worker meshfile name, or 'none' (no quotes) if master only" );
po.addOpt< string >( "d1,", "Tag name for displacement x or xyz" );
po.addOpt< string >( "d2,", "Tag name for displacement y" );
po.addOpt< string >( "d3,", "Tag name for displacement z" );
po.addOpt< int >( "fm,", "Specify master fluid material set number(s). If none specified, "
"fluid sets derived from complement of solid sets." );
po.addOpt< int >( "fs,", "Specify master solid material set number(s). If none specified, "
"solid sets derived from complement of fluid sets." );
po.addOpt< int >( "sm,", "Specify slave fluid material set number(s). If none specified, fluid "
"sets derived from complement of solid sets." );
po.addOpt< int >( "ss,", "Specify slave solid material set number(s). If none specified, solid "
"sets derived from complement of fluid sets." );
po.parseCommandLine( argc, argv );
#ifdef USE_MPI
ParallelComm* pc =
new ParallelComm(
mb, MPI_COMM_WORLD );
#else
#endif
string masterf, slavef;
if( !po.getOpt(
"master", &masterf ) ) masterf = string(
MESH_DIR ) + string(
"/rodquad.g" );
if( !po.getOpt(
"worker", &slavef ) ) slavef = string(
MESH_DIR ) + string(
"/rodtri.g" );
if( slavef.empty() )
{
cerr << "Empty slave file name; if no slave, use filename 'none' (no quotes)." << endl;
return 1;
}
vector< int > set_nos;
po.getOptAllArgs( "fm", set_nos );
for( vector< int >::iterator vit = set_nos.begin(); vit != set_nos.end(); ++vit )
set_nos.clear();
po.getOptAllArgs( "fs", set_nos );
for( vector< int >::iterator vit = set_nos.begin(); vit != set_nos.end(); ++vit )
set_nos.clear();
po.getOptAllArgs( "sm", set_nos );
for( vector< int >::iterator vit = set_nos.begin(); vit != set_nos.end(); ++vit )
po.getOptAllArgs( "ss", set_nos );
for( vector< int >::iterator vit = set_nos.begin(); vit != set_nos.end(); ++vit )
string tnames[3];
po.getOpt( "d1", &tnames[0] );
po.getOpt( "d2", &tnames[1] );
po.getOpt( "d3", &tnames[2] );
for( int i = 0; i < 3; i++ )
if( !tnames[i].empty() ) dfr->
xdisp_name( tnames[i], i );
delete dfr;
return rval;
}
const char* filename,
bool restore_coords )
{
if( restore_coords )
{
}
return rval;
}
{
Range verts;
vector< double > coords( 3 * verts.size() );
if( tmp_tag )
{
rval =
mbImpl->get_coords( verts, &coords[0] );
MB_CHK_SET_ERR( rval,
"Failed to get tmp copy of coords" );
rval =
mbImpl->tag_set_data( tmp_tag, verts, &coords[0] );
MB_CHK_SET_ERR( rval,
"Failed to save tmp copy of coords" );
}
rval =
mbImpl->tag_get_data( tagh, verts, &coords[0] );
MB_CHK_SET_ERR( rval,
"Failed to get tag data" );
}
void deform_func(
const BoundBox& bbox,
double* xold,
double* xnew )
{
double frac = 0.01;
CartVect *xo = reinterpret_cast< CartVect* >( xold ), *xn = reinterpret_cast< CartVect* >( xnew );
CartVect disp = frac * ( *xo - bbox.bMin );
*xn = *xo + disp;
}
{
Range solid_verts, fluid_verts;
rval =
mbImpl->get_adjacencies( solid_elems, 0,
false, solid_verts, Interface::UNION );
MB_CHK_SET_ERR( rval,
"Failed to get vertices" );
vector< double > coords( 3 * solid_verts.size() ), new_coords( 3 * solid_verts.size() );
rval =
mbImpl->get_coords( solid_verts, &coords[0] );
MB_CHK_SET_ERR( rval,
"Failed to get vertex coords" );
unsigned int num_verts = solid_verts.size();
{
vector< double > disps( num_verts );
for( int i = 0; i < 3; i++ )
{
for( unsigned int j = 0; j < num_verts; j++ )
new_coords[3 * j + i] = coords[3 * j + i] + disps[j];
}
}
{
vector< double > disps( 3 * num_verts );
rval =
mbImpl->tag_get_data(
xDisp[0], solid_verts, &disps[0] );
for( unsigned int j = 0; j < 3 * num_verts; j++ )
new_coords[j] = coords[j] + disps[j];
}
else
{
BoundBox bbox;
bbox.update( *
mbImpl, solid_elems );
for( unsigned int j = 0; j < num_verts; j++ )
deform_func( bbox, &coords[3 * j], &new_coords[3 * j] );
}
{
double len = 0.0;
for( unsigned int i = 0; i < num_verts; i++ )
{
CartVect dx = CartVect( &new_coords[3 * i] ) - CartVect( &coords[3 * i] );
double tmp_len = dx.length_squared();
if( tmp_len > len ) len = tmp_len;
}
Range tmp_elems( fluid_elems );
tmp_elems.merge( solid_elems );
BoundBox box;
box.update( *
mbImpl, tmp_elems );
double max_len =
std::max( box.bMax[2] - box.bMin[2], std::max( box.bMax[1] - box.bMin[1], box.bMax[0] - box.bMin[0] ) );
cout << "Max displacement = " << len << " (" << 100.0 * len / max_len << "% of max box length)" << endl;
}
{
}
rval =
mbImpl->get_adjacencies( fluid_elems, 0,
false, fluid_verts, Interface::UNION );
MB_CHK_SET_ERR( rval,
"Failed to get vertices" );
fluid_verts =
subtract( fluid_verts, solid_verts );
if( coords.size() < 3 * fluid_verts.size() ) coords.resize( 3 * fluid_verts.size() );
rval =
mbImpl->get_coords( fluid_verts, &coords[0] );
MB_CHK_SET_ERR( rval,
"Failed to get vertex coords" );
rval =
mbImpl->tag_set_data(
xNew, fluid_verts, &coords[0] );
MB_CHK_SET_ERR( rval,
"Failed to set xnew tag on fluid verts" );
{
}
}
{
ostringstream options;
#ifdef USE_MPI
ParallelComm* pc = ( m_or_s ==
MASTER ? pcMaster : pcSlave );
if( pc && pc->size() > 1 )
{
if(
debug ) options <<
"DEBUG_IO=1;CPUTIME;";
options << "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARALLEL_RESOLVE_SHARED_ENTS;"
<< "PARALLEL_GHOSTS=2.0.1;PARALLEL_COMM=" << pc->get_id();
}
#endif
rval =
mbImpl->load_file( fname.c_str(), &seth, options.str().c_str() );
MB_CHK_SET_ERR( rval,
"Couldn't load master/slave mesh" );
{
Range sets;
int set_no = *sit;
const void* setno_ptr = &set_no;
rval =
mbImpl->get_entities_by_type_and_tag( seth,
MBENTITYSET, &tagh, &setno_ptr, 1, sets );
{
MB_SET_ERR( MB_FAILURE,
"Couldn't find solid set #" << *sit );
}
else
}
Range tmp_range;
for( Range::iterator rit =
solidSets[m_or_s].begin(); rit !=
solidSets[m_or_s].end(); ++rit )
{
rval =
mbImpl->get_entities_by_handle( *rit, tmp_range,
true );
MB_CHK_SET_ERR( rval,
"Failed to get entities in solid" );
}
if( !tmp_range.empty() )
{
int dim =
mbImpl->dimension_from_handle( *tmp_range.rbegin() );
}
cout <<
"Read " <<
solidElems[m_or_s].size() <<
" solid elements from " <<
solidSets[m_or_s].size()
<<
" sets in " << ( m_or_s ==
MASTER ?
"master" :
"slave" ) <<
" mesh." << endl;
{
Range sets;
int set_no = *sit;
const void* setno_ptr = &set_no;
rval =
mbImpl->get_entities_by_type_and_tag( seth,
MBENTITYSET, &tagh, &setno_ptr, 1, sets );
{
MB_SET_ERR( MB_FAILURE,
"Couldn't find fluid set #" << *sit );
}
else
}
tmp_range.clear();
for( Range::iterator rit =
fluidSets[m_or_s].begin(); rit !=
fluidSets[m_or_s].end(); ++rit )
{
rval =
mbImpl->get_entities_by_handle( *rit, tmp_range,
true );
MB_CHK_SET_ERR( rval,
"Failed to get entities in fluid" );
}
if( !tmp_range.empty() )
{
int dim =
mbImpl->dimension_from_handle( *tmp_range.rbegin() );
}
cout <<
"Read " <<
fluidElems[m_or_s].size() <<
" fluid elements from " <<
fluidSets[m_or_s].size()
<<
" sets in " << ( m_or_s ==
MASTER ?
"master" :
"slave" ) <<
" mesh." << endl;
return rval;
}
{
Range *filled_sets = NULL, *unfilled_sets = NULL, *unfilled_elems = NULL;
{
cout <<
"Finding unspecified fluid elements in " << ( m_or_s ==
MASTER ?
"master" :
"slave" ) <<
" mesh...";
}
{
cout <<
"Finding unspecified solid elements in " << ( m_or_s ==
MASTER ?
"master" :
"slave" ) <<
" mesh...";
}
Range matsets;
rval =
mbImpl->get_entities_by_type_and_tag( file_set,
MBENTITYSET, &tagh, NULL, 1, matsets );
{
MB_SET_ERR( MB_FAILURE,
"Couldn't get any material sets" );
}
*unfilled_sets =
subtract( matsets, *filled_sets );
if( unfilled_sets->empty() )
{
MB_SET_ERR( MB_FAILURE,
"Failed to find any unfilled material sets" );
}
Range tmp_range;
for( Range::iterator rit = unfilled_sets->begin(); rit != unfilled_sets->end(); ++rit )
{
rval =
mbImpl->get_entities_by_handle( *rit, tmp_range,
true );
MB_CHK_SET_ERR( rval,
"Failed to get entities in unfilled set" );
}
int dim =
mbImpl->dimension_from_handle( *tmp_range.rbegin() );
*unfilled_elems = tmp_range.subset_by_dimension(
dim );
if( unfilled_elems->empty() )
{
MB_SET_ERR( MB_FAILURE,
"Failed to find any unfilled set entities" );
}
cout << "found " << unfilled_sets->size() << " sets and " << unfilled_elems->size() << " elements." << endl;
}