// NOTE THAT THIS DOENS'T DO THE EXPANSION IN THE NORMAL DIRECTION BBox::BBox(_field &coords, const MeshObj &obj) : isempty(false) { if (obj.get_type() != MeshObj::ELEMENT) Throw() << "Not able to create BBOx for non element"; const MeshObjTopo &topo = *GetMeshObjTopo(obj); const UInt npe = topo.num_nodes; if (topo.spatial_dim != topo.parametric_dim) Throw() << "Won't work for shell elements !!!!"; dim = topo.spatial_dim; for (UInt i =0; i < dim; i++) { min[i] = std::numeric_limits<double>::max(); max[i] = -std::numeric_limits<double>::max(); } // Loop the nodes for (UInt n = 0; n < topo.num_nodes; n++) { const MeshObj &node = *(obj.Relations[n].obj); const double *coord = coords.data(node); for (UInt j = 0; j < dim; j++) { if (coord[j] < min[j]) min[j] = coord[j]; if (coord[j] > max[j]) max[j] = coord[j]; } } }
BBox::BBox(const MEField<> &coords, const MeshObj &obj, double normexp) : isempty(false) { if (obj.get_type() != MeshObj::ELEMENT) Throw() << "Not able to create BBOx for non element"; const MeshObjTopo &topo = *GetMeshObjTopo(obj); const UInt npe = topo.num_nodes; dim = topo.spatial_dim; // Is a shell? TODO expand shell in normal directions if (topo.spatial_dim != topo.parametric_dim) { // Shell, expand by normexp in normal direction for (UInt i =0; i < dim; i++) { min[i] = std::numeric_limits<double>::max(); max[i] = -std::numeric_limits<double>::max(); } double nr[3]; MasterElement<> *me = GetME(coords, obj)(METraits<>()); std::vector<double> cd(3*me->num_functions()); GatherElemData<>(*me, coords, obj, &cd[0]); double pc[] = {0,0}; const Mapping<> *mp = GetMapping(obj)(MPTraits<>()); mp->normal(1,&cd[0], &pc[0], &nr[0]); double ns = std::sqrt(nr[0]*nr[0]+nr[1]*nr[1]+nr[2]*nr[2]); // Only normalize if bigger than 0.0 if (ns >1.0E-19) { nr[0] /= ns; nr[1] /= ns; nr[2] /= ns; } else { nr[0] =0.0; nr[1] =0.0; nr[2] =0.0; } /* if (obj.get_id() == 2426) { std::cout << "elem 2426 coords:"; std::copy(&cd[0], &cd[0] + 3*me->num_functions(), std::ostream_iterator<double>(std::cout, " ")); std::cout << std::endl; }*/ // Get cell diameter double diam = 0; for (UInt n = 1; n < me->num_functions(); n++) { double dist = std::sqrt( (cd[0]-cd[3*n])*(cd[0]-cd[3*n]) + (cd[1]-cd[3*n+1])*(cd[1]-cd[3*n+1]) + (cd[2]-cd[3*n+2])*(cd[2]-cd[3*n+2])); if (dist > diam) diam = dist; } normexp *= diam; for (UInt n = 0; n < npe; n++) { for (UInt j = 0; j < dim; j++) { double lm; if ((lm = (cd[n*dim + j] + normexp*nr[j])) < min[j]) min[j] = lm; if ((lm =(cd[n*dim + j] - normexp*nr[j])) < min[j]) min[j] = lm; if ((lm=(cd[n*dim + j] + normexp*nr[j])) > max[j]) max[j] = lm; if ((lm=(cd[n*dim + j] - normexp*nr[j])) > max[j]) max[j] = lm; } } // for n } else { // Good old fashioned element for (UInt i =0; i < dim; i++) { min[i] = std::numeric_limits<double>::max(); max[i] = -std::numeric_limits<double>::max(); } // Loop the nodes for (UInt n = 0; n < topo.num_nodes; n++) { const MeshObj &node = *(obj.Relations[n].obj); const double *coord = coords.data(node); for (UInt j = 0; j < dim; j++) { if (coord[j] < min[j]) min[j] = coord[j]; if (coord[j] > max[j]) max[j] = coord[j]; } } } // nonshell }
void point_serial_transfer(Mesh &srcrend, Interp::UserFunc *ufunc, UInt num_fields, MEField<> *const *sfields, _field *const *dfields, int *iflag, SearchResult &sres) { Trace __trace("point_serial_transfer(Interp::UserFunc *ufunc, UInt num_fields, MEField<> *const *sfields, _field *const *dfields, int *iflag, SearchResult &sres)"); if (num_fields == 0) return; SearchResult::iterator sb = sres.begin(), se = sres.end(); for (; sb != se; sb++) { Search_result &sres = **sb; // Trick: Gather the data from the source field so we may call interpolate point const MeshObj &elem = *(*sb)->elem; UInt pdim = GetMeshObjTopo(elem)->parametric_dim; // Inner loop through fields for (UInt i = 0; i < num_fields; i++) { if (iflag[i] != Interp::INTERP_STD) continue; MEField<> &sfield = *sfields[i]; _field &dfield = *dfields[i]; // Load Parametric coords UInt npts = sres.nodes.size(); // number of points to interpolate std::vector<double> pcoord(pdim*npts); for (UInt np = 0; np < npts; np++) { for (UInt pd = 0; pd < pdim; pd++) pcoord[np*pdim+pd] = sres.nodes[np].pcoord[pd]; } std::vector<double> ires(npts*sfield.dim()); if (!ufunc) { MEValues<> mev(sfield.GetMEFamily()); arbq pintg(pdim, npts, &pcoord[0]); mev.Setup(elem, MEV::update_sf, &pintg); mev.ReInit(elem); mev.GetFunctionValues(sfield, &ires[0]); } else { ufunc->evaluate(srcrend, elem, sfield, npts, &pcoord[0], &ires[0]); } // Copy data to nodes for (UInt n = 0; n < npts; n++) { const MeshObj &node = *sres.nodes[n].node; for (UInt d = 0; d < dfield.dim(node); d++) ((double*)dfield.data(node))[d] = ires[n*dfield.dim(node)+d]; } } // for fields } // for searchresult }
/* * Patch interpolation, where destination and source fields are nodal. */ void patch_serial_transfer(MEField<> &src_coord_field, UInt _nfields, MEField<>* const* _sfields, _field* const *_dfields, const std::vector<Interp::FieldPair> &fpairs, SearchResult &sres, Mesh &srcmesh) { Trace __trace("patch_serial_transfer(MEField<> &src_coord_field, UInt _nfields, MEField<>* const* _sfields, _field* const *_dfields, int *iflag, SearchResult &sres)"); std::set<int> pdeg_set; std::map<int, ElemPatch<>*> patch_map; if (_nfields == 0) return; // Get mask field pointer MEField<> *src_mask_ptr = srcmesh.GetField("mask"); std::vector<MEField<>* > fields; std::vector<_field* > dfields; std::vector<int> orders; UInt nrhs = 0; for (UInt i = 0; i < _nfields; i++) { // Only process interp_patch if (fpairs[i].idata != Interp::INTERP_PATCH) continue; pdeg_set.insert(fpairs[i].patch_order); //ThrowRequire(_sfields[i]->is_nodal()); fields.push_back(_sfields[i]); dfields.push_back(_dfields[i]); orders.push_back(fpairs[i].patch_order); nrhs += _sfields[i]->dim(); // how many rhs for recovery } // Create the recovery field SearchResult::iterator sb = sres.begin(), se = sres.end(); for (; sb != se; sb++) { Search_result &sres = **sb; // Trick: Gather the data from the source field so we may call interpolate point const MeshObj &elem = *(*sb)->elem; //std::cout << "Transfer: elem:" << elem.get_id() << std::endl; { std::set<int>::iterator pi = pdeg_set.begin(), pe = pdeg_set.end(); for (; pi != pe; ++pi) { ElemPatch<> *epatch = new ElemPatch<>(); epatch->CreateElemPatch(*pi, ElemPatch<>::GAUSS_PATCH, elem, src_coord_field, src_mask_ptr, fields.size(), &fields[0], 700000 ); patch_map[*pi] = epatch; } } // Gather parametric coords into an array. UInt pdim = GetMeshObjTopo(elem)->parametric_dim; UInt npts = sres.nodes.size(); // number of points to interpolate std::vector<double> pc(pdim*npts); for (UInt np = 0; np < npts; np++) { for (UInt pd = 0; pd < pdim; pd++) { pc[np*pdim+pd] = sres.nodes[np].pcoord[pd]; } } std::map<int, std::vector<double> > result; { std::set<int>::iterator pi = pdeg_set.begin(), pe = pdeg_set.end(); for (; pi != pe; ++pi) { std::pair<std::map<int, std::vector<double> >::iterator, bool> ri = result.insert(std::make_pair(*pi, std::vector<double>())); ThrowRequire(ri.second == true); ri.first->second.resize(nrhs*npts); ElemPatch<> &epatch = *patch_map[*pi]; epatch.Eval(npts, &pc[0], &(ri.first->second[0])); } } std::vector<std::vector<double>* > field_results; for (UInt i = 0; i < dfields.size(); i++) field_results.push_back(&result[orders[i]]); // Now copy data into fields for (UInt np = 0; np < npts; np++) { const MeshObj &snode = *sres.nodes[np].node; UInt cur_field = 0; for (UInt i = 0; i < dfields.size(); i++) { const _field &dfield = *dfields[i]; std::vector<double> &results = *field_results[i]; if (dfield.OnObj(snode)) { UInt fdim = dfield.dim(snode); double *data = dfield.data(snode); for (UInt f = 0; f < fdim; f++) { data[f] = results[np*nrhs+(cur_field+f)]; } } cur_field += dfield.dim(snode); } // for fi } // for np std::map<int, ElemPatch<>*>::iterator pi = patch_map.begin(), pe = patch_map.end(); for (; pi != pe; ++pi) delete pi->second; } // for searchresult }