// 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

}
Exemple #3
0
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
}
Exemple #4
0
/*
 * 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
  
}