![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
This class couples data between meshes. More...
#include <DataCoupler.hpp>
Public Types | |
enum | Method { CONSTANT, LINEAR_FE, QUADRATIC_FE, SPECTRAL } |
enum | IntegType { VOLUME } |
Public Member Functions | |
DataCoupler (Interface *impl, Range &source_ents, int coupler_id, ParallelComm *pc=NULL, bool init_locator=true, int dim=-1) | |
virtual | ~DataCoupler () |
ErrorCode | locate_points (double *xyz, int num_points, const double rel_iter_tol=1.0e-10, const double abs_iter_tol=1.0e-10, const double inside_tol=1.0e-6) |
ErrorCode | locate_points (Range &ents, const double rel_iter_tol=1.0e-10, const double abs_iter_tol=1.0e-10, const double inside_tol=1.0e-6) |
ErrorCode | interpolate (int method, Tag tag, double *interp_vals=NULL, std::vector< int > *point_indices=NULL, bool normalize=true) |
ErrorCode | interpolate (int method, const std::string &tag_name, double *interp_vals=NULL, std::vector< int > *point_indices=NULL, bool normalize=true) |
ErrorCode | interpolate (int *methods, const std::string *tag_names, int *points_per_method, int num_methods, double *interp_vals=NULL, std::vector< int > *point_indices=NULL, bool normalize=true) |
ErrorCode | interpolate (int *methods, Tag *tag_names, int *points_per_method, int num_methods, double *interp_vals=NULL, std::vector< int > *point_indices=NULL, bool normalize=true) |
SpatialLocator * | spatial_locator () |
int | my_id () const |
const Range & | target_ents () const |
Range & | target_ents () |
int | get_dim () const |
Private Attributes | |
Interface * | mbImpl |
ParallelComm * | myPcomm |
SpatialLocator * | myLocator |
int | myId |
Range | targetEnts |
int | myDim |
This class couples data between meshes.
The coupler interpolates solution data at a set of points. Data being interpolated resides on a "source" mesh, in a tag or in vertex coords. Applications calling this coupler send in entities, and receive back data interpolated at those points. Entities in the source mesh containing those points do not have to reside on the same processor.
To use, an application should:
Multiple interpolations (of multiple tags, or element-average vs. true interpolation) can be done after locating the points.
SpatialLocator is used for the spatial location portion of this work.
This class is a next-generation implementation of Coupler.
Definition at line 39 of file DataCoupler.hpp.
Definition at line 42 of file DataCoupler.hpp.
{
CONSTANT,
LINEAR_FE,
QUADRATIC_FE,
SPECTRAL
};
moab::DataCoupler::DataCoupler | ( | Interface * | impl, |
Range & | source_ents, | ||
int | coupler_id, | ||
ParallelComm * | pc = NULL , |
||
bool | init_locator = true , |
||
int | dim = -1 |
||
) |
Definition at line 22 of file DataCoupler.cpp.
References moab::Interface::dimension_from_handle(), moab::SpatialLocator::elem_eval(), moab::Range::empty(), ErrorCode, MB_SUCCESS, mbImpl, MBMAXTYPE, myDim, myLocator, myPcomm, moab::Range::pair_begin(), moab::Range::pair_end(), moab::Range::rbegin(), moab::ElemEvaluator::set_eval_set(), and moab::Interface::type_from_handle().
: mbImpl( impl ), myPcomm( pc ), myId( coupler_id ), myDim( dim )
{
assert( NULL != mbImpl && ( myPcomm || !source_ents.empty() ) );
// Now initialize the tree
if( init_locator )
{
myLocator = new SpatialLocator( mbImpl, source_ents );
myLocator->elem_eval( new ElemEvaluator( mbImpl ) );
// Initialize element evaluator with the default for the entity types in source_ents;
// can be replaced later by application if desired
if( !source_ents.empty() )
{
Range::pair_iterator pit = source_ents.pair_begin();
EntityType last_type = MBMAXTYPE;
for( ; pit != source_ents.pair_end(); ++pit )
{
EntityType this_type = mbImpl->type_from_handle( pit->first );
if( last_type == this_type ) continue;
ErrorCode rval = myLocator->elem_eval()->set_eval_set( pit->first );
if( MB_SUCCESS != rval ) throw( rval );
last_type = this_type;
}
}
}
if( -1 == dim && !source_ents.empty() ) myDim = mbImpl->dimension_from_handle( *source_ents.rbegin() );
}
moab::DataCoupler::~DataCoupler | ( | ) | [virtual] |
Definition at line 60 of file DataCoupler.cpp.
References moab::SpatialLocator::elem_eval(), and myLocator.
{
delete myLocator->elem_eval();
delete myLocator;
}
int moab::DataCoupler::get_dim | ( | ) | const [inline] |
ErrorCode moab::DataCoupler::interpolate | ( | int | method, |
Tag | tag, | ||
double * | interp_vals = NULL , |
||
std::vector< int > * | point_indices = NULL , |
||
bool | normalize = true |
||
) | [inline] |
Definition at line 266 of file DataCoupler.hpp.
References moab::Range::size(), and targetEnts.
Referenced by DeformMeshRemap::execute(), and interpolate().
{
// No point indices input,
int num_pts = ( point_indices ? point_indices->size() : targetEnts.size() );
return interpolate( &method, &tag, &num_pts, 1, interp_vals, point_indices, normalize );
}
ErrorCode moab::DataCoupler::interpolate | ( | int | method, |
const std::string & | tag_name, | ||
double * | interp_vals = NULL , |
||
std::vector< int > * | point_indices = NULL , |
||
bool | normalize = true |
||
) |
Definition at line 95 of file DataCoupler.cpp.
References ErrorCode, interpolate(), MB_CHK_SET_ERR, mbImpl, and moab::Interface::tag_get_handle().
{
// Tag name input, translate to tag handle and pass down the chain
Tag tag;
ErrorCode result = mbImpl->tag_get_handle( interp_tag.c_str(), tag );MB_CHK_SET_ERR( result, "Failed to get handle for interpolation tag \"" << interp_tag << "\"" );
return interpolate( method, tag, interp_vals, point_indices, normalize );
}
ErrorCode moab::DataCoupler::interpolate | ( | int * | methods, |
const std::string * | tag_names, | ||
int * | points_per_method, | ||
int | num_methods, | ||
double * | interp_vals = NULL , |
||
std::vector< int > * | point_indices = NULL , |
||
bool | normalize = true |
||
) |
ErrorCode moab::DataCoupler::interpolate | ( | int * | methods, |
Tag * | tag_names, | ||
int * | points_per_method, | ||
int | num_methods, | ||
double * | interp_vals = NULL , |
||
std::vector< int > * | point_indices = NULL , |
||
bool | normalize = true |
||
) |
*Method*/ int method = methods[TLob.vi_rd[4*i + 3]];
Definition at line 109 of file DataCoupler.cpp.
References moab::ProcConfig::crystal_router(), moab::SpatialLocator::elem_eval(), moab::TupleList::enableWriteAccess(), ErrorCode, moab::ElemEvaluator::eval(), moab::TupleList::get_n(), moab::TupleList::inc_n(), moab::TupleList::initialize(), moab::SpatialLocator::loc_table(), MB_SUCCESS, mbImpl, myLocator, myPcomm, moab::SpatialLocator::par_loc_table(), moab::ParallelComm::proc_config(), moab::ElemEvaluator::set_ent_handle(), moab::TupleList::set_n(), moab::ElemEvaluator::set_tag_handle(), moab::Range::size(), moab::ParallelComm::size(), moab::Interface::tag_get_bytes(), moab::Interface::tag_get_length(), moab::Interface::tag_set_data(), targetEnts, moab::TupleList::vi_rd, moab::TupleList::vi_wr, moab::TupleList::vr_rd, and moab::TupleList::vul_rd.
{
// Lowest-level interpolate function, does actual interpolation using calls to ElemEvaluator
ErrorCode result = MB_SUCCESS;
unsigned int pts_total = 0;
for( int i = 0; i < num_methods; i++ )
pts_total += ( points_per_method ? points_per_method[i] : targetEnts.size() );
unsigned int num_indices = ( point_indices ? point_indices->size() : targetEnts.size() );
// # points and indices should be identical
if( pts_total != num_indices ) return MB_FAILURE;
// Since each tuple contains one interpolated tag, if we're interpolating multiple tags, every
// tuple needs to be able to store up to max tag size
int max_tsize = -1;
for( int i = 0; i < num_methods; i++ )
{
int tmp_tsize;
result = mbImpl->tag_get_length( tags[i], tmp_tsize );
if( MB_SUCCESS != result ) return MB_FAILURE;
max_tsize = std::max( max_tsize, tmp_tsize );
}
if( myPcomm && myPcomm->size() > 1 )
{
// Build up the tuple list to distribute from my target points; assume that
// all procs use same method/tag input
TupleList TLob; // TLob structure: (pto_i, ridx_i, lidx_i, meth_tagidx_i)
TLob.initialize( 4, 0, 0, 0, num_indices );
int tn = 0; // The tuple number we're currently on
TLob.enableWriteAccess();
for( int m = 0; m < num_methods; m++ )
{
int num_points = ( points_per_method ? points_per_method[m] : targetEnts.size() );
for( int j = 0; j < num_points; j++ )
{
int idx = ( point_indices ? ( *point_indices )[j]
: j ); // The index in my targetEnts for this interpolation point
// Remote proc/idx from myLocator->parLocTable
TLob.vi_wr[4 * tn] = myLocator->par_loc_table().vi_rd[2 * idx]; // proc
TLob.vi_wr[4 * tn + 1] = myLocator->par_loc_table().vi_rd[2 * idx + 1]; // Remote idx
// Local entity index, tag/method index from my data
TLob.vi_wr[4 * tn + 2] = idx;
TLob.vi_wr[4 * tn + 3] = m;
TLob.inc_n();
tn++;
}
}
// Scatter/gather interpolation points
myPcomm->proc_config().crystal_router()->gs_transfer( 1, TLob, 0 );
// Perform interpolation on local source mesh; put results into TLinterp
TupleList TLinterp; // TLinterp structure: (pto_i, ridx_i, vals[max_tsize]_d)
TLinterp.initialize( 2, 0, 0, max_tsize, TLob.get_n() );
TLinterp.set_n( TLob.get_n() ); // Set the size right away
TLinterp.enableWriteAccess();
for( unsigned int i = 0; i < TLob.get_n(); i++ )
{
int lidx = TLob.vi_rd[4 * i + 1]; // Index into myLocator's local table
// Method and tag indexed with same index
///*Method*/ int method = methods[TLob.vi_rd[4*i + 3]];
Tag tag = tags[TLob.vi_rd[4 * i + 3]];
// Copy proc/remote index from TLob
TLinterp.vi_wr[2 * i] = TLob.vi_rd[4 * i];
TLinterp.vi_wr[2 * i + 1] = TLob.vi_rd[4 * i + 2];
// Set up the evaluator for the tag and entity, then interpolate, putting result in
// TLinterp
myLocator->elem_eval()->set_tag_handle( tag );
myLocator->elem_eval()->set_ent_handle( myLocator->loc_table().vul_rd[lidx] );
result =
myLocator->elem_eval()->eval( myLocator->loc_table().vr_rd + 3 * lidx, TLinterp.vr_rd + i * max_tsize );
if( MB_SUCCESS != result ) return result;
}
// Scatter/gather interpolation data
myPcomm->proc_config().crystal_router()->gs_transfer( 1, TLinterp, 0 );
// Copy the interpolated field as a unit
std::copy( TLinterp.vr_rd, TLinterp.vr_rd + TLinterp.get_n() * max_tsize, interp_vals );
}
else
{
// If called serially, interpolate directly from local locations/entities,
// into either interp_vals or by setting data directly on tags on those entities
std::vector< double > tmp_vals;
std::vector< EntityHandle > tmp_ents;
double* tmp_dbl = interp_vals;
for( int i = 0; i < num_methods; i++ )
{
int num_points = ( points_per_method ? points_per_method[i] : targetEnts.size() );
// Interpolated data is tsize long, which is either max size (if data passed back to
// caller in interp_vals) or tag size (if data will be set on entities, in which case it
// shouldn't have padding) set sizes here, inside loop over methods, to reduce memory
// usage
int tsize = max_tsize, tsize_bytes = 0;
if( !interp_vals )
{
tmp_vals.resize( num_points * max_tsize );
tmp_dbl = &tmp_vals[0];
tmp_ents.resize( num_points );
result = mbImpl->tag_get_length( tags[i], tsize );
if( MB_SUCCESS != result ) return result;
result = mbImpl->tag_get_bytes( tags[i], tsize_bytes );
if( MB_SUCCESS != result ) return result;
}
for( int j = 0; j < num_points; j++ )
{
int lidx;
if( point_indices )
lidx = ( *point_indices )[j];
else
lidx = j;
myLocator->elem_eval()->set_tag_handle( tags[i] );
myLocator->elem_eval()->set_ent_handle( myLocator->loc_table().vul_rd[lidx] );
if( !interp_vals ) tmp_ents[j] = targetEnts[lidx]; // Could be performance-sensitive, thus the if test
result = myLocator->elem_eval()->eval( myLocator->loc_table().vr_rd + 3 * lidx, tmp_dbl );
tmp_dbl += tsize;
if( MB_SUCCESS != result ) return result;
} // for j over points
if( !interp_vals )
{
// Set tags on tmp_ents; data is already w/o padding, due to tsize setting above
result = mbImpl->tag_set_data( tags[i], &tmp_ents[0], tmp_ents.size(), &tmp_vals[0] );
if( MB_SUCCESS != result ) return result;
}
} // for i over methods
} // if myPcomm
// Done
return MB_SUCCESS;
}
ErrorCode moab::DataCoupler::locate_points | ( | double * | xyz, |
int | num_points, | ||
const double | rel_iter_tol = 1.0e-10 , |
||
const double | abs_iter_tol = 1.0e-10 , |
||
const double | inside_tol = 1.0e-6 |
||
) |
Definition at line 81 of file DataCoupler.cpp.
References moab::SpatialLocator::locate_points(), myLocator, myPcomm, and moab::ParallelComm::size().
Referenced by DeformMeshRemap::execute().
{
#ifdef MOAB_HAVE_MPI
if( myPcomm && myPcomm->size() > 1 )
return myLocator->par_locate_points( myPcomm, xyz, num_points, rel_iter_tol, abs_iter_tol, inside_tol );
#endif
return myLocator->locate_points( xyz, num_points, rel_iter_tol, abs_iter_tol, inside_tol );
}
ErrorCode moab::DataCoupler::locate_points | ( | Range & | ents, |
const double | rel_iter_tol = 1.0e-10 , |
||
const double | abs_iter_tol = 1.0e-10 , |
||
const double | inside_tol = 1.0e-6 |
||
) |
Definition at line 66 of file DataCoupler.cpp.
References moab::SpatialLocator::locate_points(), myLocator, myPcomm, moab::ParallelComm::size(), and targetEnts.
{
targetEnts = targ_ents;
#ifdef MOAB_HAVE_MPI
if( myPcomm && myPcomm->size() > 1 )
return myLocator->par_locate_points( myPcomm, targ_ents, rel_iter_tol, abs_iter_tol, inside_tol );
#endif
return myLocator->locate_points( targ_ents, rel_iter_tol, abs_iter_tol, inside_tol );
}
int moab::DataCoupler::my_id | ( | ) | const [inline] |
SpatialLocator* moab::DataCoupler::spatial_locator | ( | ) | [inline] |
Definition at line 220 of file DataCoupler.hpp.
References myLocator.
Referenced by DeformMeshRemap::execute().
{
return myLocator;
}
const Range& moab::DataCoupler::target_ents | ( | ) | const [inline] |
Range& moab::DataCoupler::target_ents | ( | ) | [inline] |
Interface* moab::DataCoupler::mbImpl [private] |
Definition at line 244 of file DataCoupler.hpp.
Referenced by DataCoupler(), and interpolate().
int moab::DataCoupler::myDim [private] |
Definition at line 263 of file DataCoupler.hpp.
Referenced by DataCoupler(), and get_dim().
int moab::DataCoupler::myId [private] |
Definition at line 256 of file DataCoupler.hpp.
Referenced by my_id().
SpatialLocator* moab::DataCoupler::myLocator [private] |
Definition at line 252 of file DataCoupler.hpp.
Referenced by DataCoupler(), interpolate(), locate_points(), spatial_locator(), and ~DataCoupler().
ParallelComm* moab::DataCoupler::myPcomm [private] |
Definition at line 248 of file DataCoupler.hpp.
Referenced by DataCoupler(), interpolate(), and locate_points().
Range moab::DataCoupler::targetEnts [private] |
Definition at line 260 of file DataCoupler.hpp.
Referenced by interpolate(), locate_points(), and target_ents().