moab
DataCoupler.cpp
Go to the documentation of this file.
00001 #include "DataCoupler.hpp"
00002 #include "moab/Tree.hpp"
00003 #include "moab/TupleList.hpp"
00004 #include "moab/SpatialLocator.hpp"
00005 #include "moab/ElemEvaluator.hpp"
00006 #include "moab/Error.hpp"
00007 
00008 #ifdef USE_MPI
00009 #include "moab/ParallelComm.hpp"
00010 #endif
00011 
00012 #include "iostream"
00013 #include <algorithm>
00014 #include <sstream>
00015 
00016 #include <stdio.h>
00017 #include "assert.h"
00018 
00019 namespace moab {
00020 
00021 DataCoupler::DataCoupler(Interface *impl,
00022                          Range &source_ents,
00023                          int coupler_id,
00024                          ParallelComm *pc,
00025                          bool init_locator,
00026                          int dim)
00027         : mbImpl(impl), myPcomm(pc), myId(coupler_id), myDim(dim)
00028 {
00029   assert(NULL != mbImpl && (myPcomm || !source_ents.empty()));
00030 
00031     // now initialize the tree
00032   if (init_locator) {
00033     myLocator = new SpatialLocator(mbImpl, source_ents);
00034     myLocator->elem_eval(new ElemEvaluator(mbImpl));
00035 
00036       // initialize element evaluator with the default for the entity types in source_ents; 
00037       // can be replaced later by application if desired
00038     if (!source_ents.empty()) {
00039       Range::pair_iterator pit = source_ents.pair_begin();
00040       EntityType last_type = MBMAXTYPE;
00041       for (; pit != source_ents.pair_end(); pit++) {
00042         EntityType this_type = mbImpl->type_from_handle(pit->first);
00043         if (last_type == this_type) continue;
00044         ErrorCode rval = myLocator->elem_eval()->set_eval_set(pit->first);
00045         if (MB_SUCCESS != rval) throw(rval);
00046         last_type = this_type;
00047       }
00048     }
00049   }
00050   
00051   if (-1 == dim && !source_ents.empty()) 
00052     dim = mbImpl->dimension_from_handle(*source_ents.rbegin());
00053 
00054   ErrorCode rval = impl->query_interface(mError);
00055   if (MB_SUCCESS != rval) throw(rval);
00056 }
00057 
00058   /* destructor
00059    */
00060 DataCoupler::~DataCoupler()
00061 {
00062   delete myLocator;
00063 }
00064 
00065 ErrorCode DataCoupler::locate_points(Range &targ_ents,
00066                                      const double rel_iter_tol, const double abs_iter_tol,
00067                                      const double inside_tol)
00068 {
00069   targetEnts = targ_ents;
00070 
00071 #ifdef USE_MPI
00072   if (myPcomm && myPcomm->size() > 1) 
00073     return myLocator->par_locate_points(myPcomm, targ_ents, rel_iter_tol, abs_iter_tol, inside_tol);
00074 #endif
00075 
00076   return myLocator->locate_points(targ_ents, rel_iter_tol, abs_iter_tol, inside_tol);
00077 }
00078 
00079 ErrorCode DataCoupler::locate_points(double *xyz, int num_points,
00080                                      const double rel_iter_tol, const double abs_iter_tol,
00081                                      const double inside_tol)
00082 {
00083 #ifdef USE_MPI
00084   if (myPcomm && myPcomm->size() > 1) 
00085     return myLocator->par_locate_points(myPcomm, xyz, num_points, rel_iter_tol, abs_iter_tol, inside_tol);
00086 #endif
00087 
00088   return myLocator->locate_points(xyz, num_points, rel_iter_tol, abs_iter_tol, inside_tol);
00089 }
00090 
00091 ErrorCode DataCoupler::interpolate(/*DataCoupler::Method*/ int method,
00092                                    const std::string &interp_tag,
00093                                    double *interp_vals,
00094                                    std::vector<int> *point_indices,
00095                                    bool normalize)
00096 {
00097     // tag name input, translate to tag handle and pass down the chain
00098 
00099     // not inlined because of call to set_last_error, class Error isn't in public interface
00100   Tag tag;
00101   ErrorCode result = mbImpl->tag_get_handle(interp_tag.c_str(), tag);
00102   if (MB_SUCCESS != result) {
00103     std::ostringstream str;
00104     str << "Failed to get handle for interpolation tag \"" << interp_tag << "\"";
00105     mError->set_last_error(str.str());
00106     return result;
00107   }
00108   return interpolate(method, tag, interp_vals, point_indices, normalize);
00109 }
00110   
00111 ErrorCode DataCoupler::interpolate(/*DataCoupler::Method*/ int */* methods */,
00112                                    Tag *tags,
00113                                    int *points_per_method,
00114                                    int num_methods,
00115                                    double *interp_vals,
00116                                    std::vector<int> *point_indices,
00117                                    bool /*normalize*/)
00118 {
00119     // lowest-level interpolate function, does actual interpolation using calls to ElemEvaluator
00120 
00121   ErrorCode result = MB_SUCCESS;
00122 
00123   unsigned int pts_total = 0;
00124   for (int i = 0; i < num_methods; i++) pts_total += (points_per_method ? points_per_method[i] : targetEnts.size());
00125 
00126   unsigned int num_indices = (point_indices ? point_indices->size() : targetEnts.size());
00127     // # points and indices should be identical
00128   if (pts_total != num_indices)
00129     return MB_FAILURE;
00130 
00131     // since each tuple contains one interpolated tag, if we're interpolating multiple tags, every tuple
00132     // needs to be able to store up to max tag size
00133   int max_tsize = -1;
00134   for (int i = 0; i < num_methods; i++) {
00135     int tmp_tsize;
00136     result = mbImpl->tag_get_length(tags[i], tmp_tsize);
00137     if (MB_SUCCESS != result) return MB_FAILURE;
00138     max_tsize = std::max(max_tsize, tmp_tsize);
00139   }
00140 
00141   if (myPcomm && myPcomm->size() > 1) {
00142       // build up the tuple list to distribute from my target points; assume that
00143       // all procs use same method/tag input
00144     TupleList TLob; // TLob structure: (pto_i, ridx_i, lidx_i, meth_tagidx_i)
00145     TLob.initialize(4, 0, 0, 0, num_indices);
00146     int tn = 0; // the tuple number we're currently on
00147     TLob.enableWriteAccess();
00148     for (int m = 0; m < num_methods; m++) {
00149       int num_points = (points_per_method ? points_per_method[m] : targetEnts.size());
00150       for (int j = 0; j < num_points; j++) {
00151         int idx = (point_indices ? (*point_indices)[j] : j); // the index in my targetEnts for this interpolation point
00152 
00153           // remote proc/idx from myLocator->parLocTable
00154         TLob.vi_wr[4*tn]   = myLocator->par_loc_table().vi_rd[2*idx]; // proc
00155         TLob.vi_wr[4*tn+1] = myLocator->par_loc_table().vi_rd[2*idx+1]; // remote idx
00156   
00157           // local entity index, tag/method index from my data
00158         TLob.vi_wr[4*tn+2] = idx;
00159         TLob.vi_wr[4*tn+3] = m;
00160         TLob.inc_n();
00161         tn++;
00162       }
00163     }
00164 
00165       // scatter/gather interpolation points
00166     myPcomm->proc_config().crystal_router()->gs_transfer(1, TLob, 0);
00167 
00168       // perform interpolation on local source mesh; put results into TLinterp
00169     TupleList TLinterp; // TLinterp structure: (pto_i, ridx_i, vals[max_tsize]_d)
00170     TLinterp.initialize(2, 0, 0, max_tsize, TLob.get_n());
00171     TLinterp.set_n(TLob.get_n()); // set the size right away
00172     TLinterp.enableWriteAccess();
00173 
00174     for (unsigned int i = 0; i < TLob.get_n(); i++) {
00175       int lidx = TLob.vi_rd[4*i+1]; // index into myLocator's local table
00176         // method and tag indexed with same index
00177 //      /*Method*/ int method = methods[TLob.vi_rd[4*i+3]];
00178       Tag tag = tags[TLob.vi_rd[4*i+3]];
00179         // copy proc/remote index from TLob
00180       TLinterp.vi_wr[2*i] = TLob.vi_rd[4*i];
00181       TLinterp.vi_wr[2*i+1] = TLob.vi_rd[4*i+2]; 
00182 
00183         // set up the evaluator for the tag and entity, then interpolate, putting result in TLinterp
00184       myLocator->elem_eval()->set_tag_handle(tag);
00185       myLocator->elem_eval()->set_ent_handle(myLocator->loc_table().vul_rd[lidx]);
00186       result = myLocator->elem_eval()->eval(myLocator->loc_table().vr_rd+3*lidx, TLinterp.vr_rd+i*max_tsize);
00187       if (MB_SUCCESS != result) return result;
00188     }
00189 
00190       // scatter/gather interpolation data
00191     myPcomm->proc_config().crystal_router()->gs_transfer(1, TLinterp, 0);
00192 
00193       // copy the interpolated field as a unit
00194     std::copy(TLinterp.vr_rd, TLinterp.vr_rd+TLinterp.get_n()*max_tsize, interp_vals);
00195   }
00196   else {
00197       // if called serially, interpolate directly from local locations/entities,
00198       // into either interp_vals or by setting data directly on tags on those entities
00199     std::vector<double> tmp_vals;
00200     std::vector<EntityHandle> tmp_ents;
00201     double *tmp_dbl = interp_vals;
00202     for (int i = 0; i < num_methods; i++) {
00203       int num_points = (points_per_method ? points_per_method[i] : targetEnts.size());
00204 
00205         // interpolated data is tsize long, which is either max size (if data passed back to caller in interp_vals)
00206         // or tag size (if data will be set on entities, in which case it shouldn't have padding)
00207         // set sizes here, inside loop over methods, to reduce memory usage
00208       int tsize = max_tsize, tsize_bytes = 0;
00209       if (!interp_vals) {
00210         tmp_vals.resize(num_points*max_tsize);
00211         tmp_dbl = &tmp_vals[0];
00212         tmp_ents.resize(num_points);
00213         result = mbImpl->tag_get_length(tags[i], tsize);
00214         if (MB_SUCCESS != result) return result;
00215         result = mbImpl->tag_get_bytes(tags[i], tsize_bytes);
00216         if (MB_SUCCESS != result) return result;
00217       }
00218       
00219       for (int j = 0; j < num_points; j++) {
00220         int lidx;
00221         if (point_indices) {
00222           lidx = (*point_indices)[j];
00223         }
00224         else {
00225           lidx = j;
00226         }
00227 
00228         myLocator->elem_eval()->set_tag_handle(tags[i]);
00229         myLocator->elem_eval()->set_ent_handle(myLocator->loc_table().vul_rd[lidx]);
00230         if (!interp_vals) tmp_ents[j] = targetEnts[lidx]; // could be performance-sensitive, thus the if test
00231         result = myLocator->elem_eval()->eval(myLocator->loc_table().vr_rd+3*lidx, tmp_dbl);
00232         tmp_dbl += tsize;
00233         if (MB_SUCCESS != result) return result;
00234       } // for j over points
00235 
00236       if (!interp_vals) {
00237           // set tags on tmp_ents; data is already w/o padding, due to tsize setting above
00238         result = mbImpl->tag_set_data(tags[i], &tmp_ents[0], tmp_ents.size(), &tmp_vals[0]);
00239         if (MB_SUCCESS != result) return result;
00240       }
00241 
00242     } // for i over methods
00243   } // if myPcomm
00244   
00245       // done
00246   return MB_SUCCESS;
00247 }
00248 
00249 } // namespace_moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines