コード例 #1
0
ファイル: ASMs3DLag.C プロジェクト: OPM/IFEM
bool ASMs3DLag::evalSolution (Matrix& sField, const IntegrandBase& integrand,
			      const RealArray*, bool) const
{
  sField.resize(0,0);

  const int p1 = svol->order(0);
  const int p2 = svol->order(1);
  const int p3 = svol->order(2);
  double incx = 2.0/double(p1-1);
  double incy = 2.0/double(p2-1);
  double incz = 2.0/double(p3-1);

  size_t nPoints = coord.size();
  IntVec check(nPoints,0);

  FiniteElement fe(p1*p2*p3);
  Vector        solPt;
  Vectors       globSolPt(nPoints);
  Matrix        dNdu, Xnod, Jac;

  // Evaluate the secondary solution field at each point
  const int nel = this->getNoElms(true);
  for (int iel = 1; iel <= nel; iel++)
  {
    const IntVec& mnpc = MNPC[iel-1];
    this->getElementCoordinates(Xnod,iel);

    int i, j, k, loc = 0;
    for (k = 0; k < p3; k++)
      for (j = 0; j < p2; j++)
	for (i = 0; i < p1; i++, loc++)
	{
	  fe.xi   = -1.0 + i*incx;
	  fe.eta  = -1.0 + j*incy;
	  fe.zeta = -1.0 + k*incz;
	  if (!Lagrange::computeBasis(fe.N,dNdu,p1,fe.xi,p2,fe.eta,p3,fe.zeta))
	    return false;

	  // Compute the Jacobian inverse
	  fe.detJxW = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu);

	  // Now evaluate the solution field
	  if (!integrand.evalSol(solPt,fe,Xnod*fe.N,mnpc))
	    return false;
	  else if (sField.empty())
	    sField.resize(solPt.size(),nPoints,true);

	  if (++check[mnpc[loc]] == 1)
	    globSolPt[mnpc[loc]] = solPt;
	  else
	    globSolPt[mnpc[loc]] += solPt;
	}
  }

  for (size_t i = 0; i < nPoints; i++)
    sField.fillColumn(1+i,globSolPt[i] /= check[i]);

  return true;
}
コード例 #2
0
ファイル: ASMs2DSpec.C プロジェクト: kmokstad/IFEM-2
bool ASMs2DSpec::evalSolution (Matrix& sField, const IntegrandBase& integrand,
			       const RealArray*, bool) const
{
  sField.resize(0,0);

  Vector wg1,xg1,wg2,xg2;
  if (!Legendre::GLL(wg1,xg1,p1)) return false;
  if (!Legendre::GLL(wg2,xg2,p2)) return false;

  Matrix D1, D2;
  if (!Legendre::basisDerivatives(p1,D1)) return false;
  if (!Legendre::basisDerivatives(p2,D2)) return false;

  size_t nPoints = this->getNoNodes();
  IntVec check(nPoints,0);

  FiniteElement fe(p1*p2);
  Vector        solPt;
  Vectors       globSolPt(nPoints);
  Matrix        dNdu(p1*p2,2), Xnod, Jac;

  // Evaluate the secondary solution field at each point
  const int nel = this->getNoElms();
  for (int iel = 1; iel <= nel; iel++)
  {
    const IntVec& mnpc = MNPC[iel-1];
    this->getElementCoordinates(Xnod,iel);

    int i, j, loc = 0;
    for (j = 0; j < p2; j++)
      for (i = 0; i < p1; i++, loc++)
      {
	evalBasis(i+1,j+1,p1,p2,D1,D2,fe.N,dNdu);

	// Compute the Jacobian inverse
	fe.detJxW = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu);

	// Now evaluate the solution field
	if (!integrand.evalSol(solPt,fe,Xnod.getColumn(loc+1),mnpc))
	  return false;
	else if (sField.empty())
	  sField.resize(solPt.size(),nPoints,true);

	if (++check[mnpc[loc]] == 1)
	  globSolPt[mnpc[loc]] = solPt;
	else
	  globSolPt[mnpc[loc]] += solPt;
      }
  }

  for (size_t i = 0; i < nPoints; i++)
    sField.fillColumn(1+i,globSolPt[i] /= check[i]);

  return true;
}
コード例 #3
0
ファイル: ASMs1DSpec.C プロジェクト: OPM/IFEM
bool ASMs1DSpec::evalSolution (Matrix& sField, const IntegrandBase& integrand,
			       const RealArray*, bool) const
{
  sField.resize(0,0);
  if (!curv) return false;

  const int p1 = curv->order();

  Matrix D1;
  if (!Legendre::basisDerivatives(p1,D1))
    return false;

  size_t nPoints = this->getNoNodes();
  IntVec check(nPoints,0);

  FiniteElement fe(p1);
  Vector        solPt;
  Vectors       globSolPt(nPoints);
  Matrix        dNdu(p1,1), Xnod, Jac;

  // Evaluate the secondary solution field at each point
  const int nel = this->getNoElms();
  for (int iel = 1; iel <= nel; iel++)
  {
    const IntVec& mnpc = MNPC[iel-1];
    this->getElementCoordinates(Xnod,iel);

    for (int i = 0; i < p1; i++)
    {
      fe.N.fill(0.0);
      fe.N(i+1) = 1.0;
      dNdu.fillColumn(1,D1.getRow(i+1));

      // Compute the Jacobian inverse
      fe.detJxW = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu);

      // Now evaluate the solution field
      if (!integrand.evalSol(solPt,fe,Xnod.getColumn(i+1),mnpc))
	return false;
      else if (sField.empty())
	sField.resize(solPt.size(),nPoints,true);

      if (++check[mnpc[i]] == 1)
	globSolPt[mnpc[i]] = solPt;
      else
	globSolPt[mnpc[i]] += solPt;
    }
  }

  for (size_t i = 0; i < nPoints; i++)
    sField.fillColumn(1+i,globSolPt[i] /= check[i]);

  return true;
}
コード例 #4
0
ファイル: ASMs1D.C プロジェクト: OPM/IFEM
bool ASMs1D::evalSolution (Matrix& sField, const IntegrandBase& integrand,
			   const RealArray* gpar, bool) const
{
  sField.resize(0,0);

  const int p1 = curv->order();

  // Fetch nodal (control point) coordinates
  FiniteElement fe(p1,firstIp);
  this->getNodalCoordinates(fe.Xn);

  Vector   solPt;
  Matrix   dNdu, Jac, Xtmp;
  Matrix3D d2Ndu2, Hess;

  if (nsd > 1 && (integrand.getIntegrandType() & Integrand::SECOND_DERIVATIVES))
    fe.G.resize(nsd,2); // For storing d{X}/du and d2{X}/du2

  // Evaluate the secondary solution field at each point
  const RealArray& upar = *gpar;
  size_t nPoints = upar.size();
  for (size_t i = 0; i < nPoints; i++, fe.iGP++)
  {
    fe.u = upar[i];

    // Fetch basis function derivatives at current integration point
    if (integrand.getIntegrandType() & Integrand::NO_DERIVATIVES)
      this->extractBasis(fe.u,fe.N);
    else if (integrand.getIntegrandType() & Integrand::SECOND_DERIVATIVES)
      this->extractBasis(fe.u,fe.N,dNdu,d2Ndu2);
    else
      this->extractBasis(fe.u,fe.N,dNdu);

    // Fetch indices of the non-zero basis functions at this point
    IntVec ip;
    scatterInd(p1,curv->basis().lastKnotInterval(),ip);

    // Fetch associated control point coordinates
    utl::gather(ip,nsd,fe.Xn,Xtmp);

    if (!dNdu.empty())
    {
      // Compute the Jacobian inverse and derivatives
      fe.detJxW = utl::Jacobian(Jac,fe.dNdX,Xtmp,dNdu);

      // Compute Hessian of coordinate mapping and 2nd order derivatives
      if (integrand.getIntegrandType() & Integrand::SECOND_DERIVATIVES)
      {
        if (!utl::Hessian(Hess,fe.d2NdX2,Jac,Xtmp,d2Ndu2,fe.dNdX))
          continue;
        else if (fe.G.cols() == 2)
        {
          // Store the first and second derivatives of {X} w.r.t.
          // the parametric coordinate (xi), in the G-matrix
          fe.G.fillColumn(1,Jac.ptr());
          fe.G.fillColumn(2,Hess.ptr());
        }
      }
    }

    // Now evaluate the solution field
    if (!integrand.evalSol(solPt,fe,Xtmp*fe.N,ip))
      return false;
    else if (sField.empty())
      sField.resize(solPt.size(),nPoints,true);

    sField.fillColumn(1+i,solPt);
  }

  return true;
}
コード例 #5
0
ファイル: ASMs3Dmx.C プロジェクト: OPM/IFEM
bool ASMs3Dmx::evalSolution (Matrix& sField, const IntegrandBase& integrand,
			     const RealArray* gpar, bool regular) const
{
  sField.resize(0,0);

  if (m_basis.empty()) return false;

  // Evaluate the basis functions and their derivatives at all points
  std::vector<std::vector<Go::BasisDerivs>> splinex(m_basis.size());
  if (regular)
  {
    for (size_t b = 0; b < m_basis.size(); ++b)
      m_basis[b]->computeBasisGrid(gpar[0],gpar[1],gpar[2],splinex[b]);
  }
  else if (gpar[0].size() == gpar[1].size() && gpar[0].size() == gpar[2].size())
  {
    for (size_t b = 0; b < m_basis.size(); ++b) {
      splinex[b].resize(gpar[0].size());
      for (size_t i = 0; i < splinex[b].size(); i++)
        m_basis[b]->computeBasis(gpar[0][i],gpar[1][i],gpar[2][i],splinex[b][i]);
    }
  }

  std::vector<size_t> elem_sizes;
  for (auto& it : m_basis)
    elem_sizes.push_back(it->order(0)*it->order(1)*it->order(2));

  // Fetch nodal (control point) coordinates
  Matrix Xnod, Xtmp;
  this->getNodalCoordinates(Xnod);

  MxFiniteElement fe(elem_sizes,firstIp);
  Vector          solPt;
  std::vector<Matrix> dNxdu(m_basis.size());
  Matrix          Jac;
  Vec3            X;

  // Evaluate the secondary solution field at each point
  size_t nPoints = splinex[0].size();
  for (size_t i = 0; i < nPoints; i++, fe.iGP++)
  {
    // Fetch indices of the non-zero basis functions at this point
    std::vector<IntVec> ip(m_basis.size());
    IntVec ipa;
    size_t ofs = 0;
    for (size_t b = 0; b < m_basis.size(); ++b) {
      scatterInd(m_basis[b]->numCoefs(0),m_basis[b]->numCoefs(1),m_basis[b]->numCoefs(2),
                 m_basis[b]->order(0),m_basis[b]->order(1),m_basis[b]->order(2),
                 splinex[b][i].left_idx,ip[b]);

      // Fetch associated control point coordinates
      if (b == (size_t)geoBasis-1)
        utl::gather(ip[geoBasis-1], 3, Xnod, Xtmp);

      for (auto& it : ip[b])
        it += ofs;
      ipa.insert(ipa.end(), ip[b].begin(), ip[b].end());
      ofs += nb[b];
    }

    fe.u = splinex[0][i].param[0];
    fe.v = splinex[0][i].param[1];
    fe.w = splinex[0][i].param[2];

    // Fetch basis function derivatives at current integration point
    for (size_t b = 0; b < m_basis.size(); ++b)
      SplineUtils::extractBasis(splinex[b][i],fe.basis(b+1),dNxdu[b]);

    // Compute Jacobian inverse of the coordinate mapping and
    // basis function derivatives w.r.t. Cartesian coordinates
    fe.detJxW = utl::Jacobian(Jac,fe.grad(geoBasis),Xtmp,dNxdu[geoBasis-1]);

    for (size_t b = 1; b <= m_basis.size(); b++)
      if (b != (size_t)geoBasis)
      {
        if (fe.detJxW == 0.0)
          fe.grad(b).clear();
        else
          fe.grad(b).multiply(dNxdu[b-1],Jac);
      }

    // Cartesian coordinates of current integration point
    X = Xtmp * fe.basis(geoBasis);

    // Now evaluate the solution field
    if (!integrand.evalSol(solPt,fe,X,ipa,elem_sizes,nb))
      return false;
    else if (sField.empty())
      sField.resize(solPt.size(),nPoints,true);

    sField.fillColumn(1+i,solPt);
  }

  return true;
}
コード例 #6
0
ファイル: ASMu2Drecovery.C プロジェクト: akva2/IFEM
bool ASMu2D::globalL2projection (Matrix& sField,
				 const IntegrandBase& integrand,
				 bool continuous) const
{
  if (!lrspline) return true; // silently ignore empty patches

  PROFILE2("ASMu2D::globalL2");

  const int p1 = lrspline->order(0);
  const int p2 = lrspline->order(1);

  // Get Gaussian quadrature points
  const int ng1 = continuous ? nGauss : p1 - 1;
  const int ng2 = continuous ? nGauss : p2 - 1;
  const double* xg = GaussQuadrature::getCoord(ng1);
  const double* yg = GaussQuadrature::getCoord(ng2);
  const double* wg = continuous ? GaussQuadrature::getWeight(nGauss) : nullptr;
  if (!xg || !yg) return false;
  if (continuous && !wg) return false;


  // Set up the projection matrices
  const size_t nnod = this->getNoNodes();
  const size_t ncomp = integrand.getNoFields();
  SparseMatrix A(SparseMatrix::SUPERLU);
  StdVector B(nnod*ncomp);
  A.redim(nnod,nnod);

  double dA = 0.0;
  Vector phi;
  Matrix dNdu, Xnod, Jac;
  Go::BasisDerivsSf spl1;
  Go::BasisPtsSf    spl0;


  // === Assembly loop over all elements in the patch ==========================

  std::vector<LR::Element*>::iterator el = lrspline->elementBegin();
  for (int iel = 1; el != lrspline->elementEnd(); el++, iel++)
  {
    if (continuous)
    {
      // Set up control point (nodal) coordinates for current element
      if (!this->getElementCoordinates(Xnod,iel))
        return false;
      else if ((dA = 0.25*this->getParametricArea(iel)) < 0.0)
        return false; // topology error (probably logic error)
    }

    // Compute parameter values of the Gauss points over this element
    std::array<RealArray,2> gpar, unstrGpar;
    this->getGaussPointParameters(gpar[0],0,ng1,iel,xg);
    this->getGaussPointParameters(gpar[1],1,ng2,iel,yg);

    // convert to unstructred mesh representation
    expandTensorGrid(gpar.data(),unstrGpar.data());

    // Evaluate the secondary solution at all integration points
    if (!this->evalSolution(sField,integrand,unstrGpar.data()))
      return false;

    // set up basis function size (for extractBasis subroutine)
    phi.resize((**el).nBasisFunctions());

    // --- Integration loop over all Gauss points in each direction ----------
    int ip = 0;
    for (int j = 0; j < ng2; j++)
      for (int i = 0; i < ng1; i++, ip++)
      {
        if (continuous)
        {
          lrspline->computeBasis(gpar[0][i],gpar[1][j],spl1,iel-1);
          SplineUtils::extractBasis(spl1,phi,dNdu);
        }
        else
        {
          lrspline->computeBasis(gpar[0][i],gpar[1][j],spl0,iel-1);
          phi = spl0.basisValues;
        }

        // Compute the Jacobian inverse and derivatives
        double dJw = 1.0;
        if (continuous)
        {
          dJw = dA*wg[i]*wg[j]*utl::Jacobian(Jac,dNdu,Xnod,dNdu,false);
          if (dJw == 0.0) continue; // skip singular points
        }

        // Integrate the linear system A*x=B
        for (size_t ii = 0; ii < phi.size(); ii++)
        {
          int inod = MNPC[iel-1][ii]+1;
          for (size_t jj = 0; jj < phi.size(); jj++)
          {
            int jnod = MNPC[iel-1][jj]+1;
            A(inod,jnod) += phi[ii]*phi[jj]*dJw;
          }
          for (size_t r = 1; r <= ncomp; r++)
            B(inod+(r-1)*nnod) += phi[ii]*sField(r,ip+1)*dJw;
        }
      }
  }

#if SP_DEBUG > 2
  std::cout <<"---- Matrix A -----"<< A
            <<"-------------------"<< std::endl;
  std::cout <<"---- Vector B -----"<< B
            <<"-------------------"<< std::endl;
#endif

  // Solve the patch-global equation system
  if (!A.solve(B)) return false;

  // Store the control-point values of the projected field
  sField.resize(ncomp,nnod);
  for (size_t i = 1; i <= nnod; i++)
    for (size_t j = 1; j <= ncomp; j++)
      sField(j,i) = B(i+(j-1)*nnod);

  return true;
}
コード例 #7
0
ファイル: ASMs2DmxLag.C プロジェクト: kmokstad/IFEM-2
bool ASMs2DmxLag::evalSolution (Matrix& sField, const IntegrandBase& integrand,
				const RealArray*, bool) const
{
  sField.resize(0,0);

  double incx = 2.0/double(p1-1);
  double incy = 2.0/double(p2-1);

  size_t nPoints = nb[0];
  IntVec check(nPoints,0);

  MxFiniteElement fe(elem_size);
  Vector          solPt;
  Vectors         globSolPt(nPoints);
  Matrices        dNxdu(nxx.size());
  Matrix          Xnod, Jac;

  // Evaluate the secondary solution field at each point
  for (size_t iel = 1; iel <= nel; iel++)
  {
    IntVec::const_iterator f2start = geoBasis == 1? MNPC[iel-1].begin() :
                                     MNPC[iel-1].begin() +
                                     std::accumulate(elem_size.begin()+geoBasis-2,
                                                     elem_size.begin()+geoBasis-1, 0);
    IntVec::const_iterator f2end = f2start + elem_size[geoBasis-1];
    IntVec mnpc1(f2start,f2end);

    this->getElementCoordinates(Xnod,iel);

    int i, j, loc = 0;
    for (j = 0; j < p2; j++)
      for (i = 0; i < p1; i++, loc++)
      {
	double xi  = -1.0 + i*incx;
	double eta = -1.0 + j*incy;
        for (size_t b = 0; b < nxx.size(); ++b)
          if (!Lagrange::computeBasis(fe.basis(b+1),dNxdu[b],elem_sizes[b][0],xi,
                                      elem_sizes[b][1],eta))
	  return false;

	// Compute the Jacobian inverse
        fe.detJxW = utl::Jacobian(Jac,fe.grad(geoBasis),Xnod,dNxdu[geoBasis-1]);

        for (size_t b = 1; b <= nxx.size(); b++)
          if (b != (size_t)geoBasis)
          {
            if (fe.detJxW == 0.0)
              fe.grad(b).clear();
            else
              fe.grad(b).multiply(dNxdu[b-1],Jac);
          }

	// Now evaluate the solution field
	if (!integrand.evalSol(solPt,fe,Xnod*fe.basis(geoBasis),MNPC[iel-1],elem_size,nb))
	  return false;
	else if (sField.empty())
	  sField.resize(solPt.size(),nPoints,true);

	if (++check[mnpc1[loc]] == 1)
	  globSolPt[mnpc1[loc]] = solPt;
	else
	  globSolPt[mnpc1[loc]] += solPt;
      }
  }

  for (size_t i = 0; i < nPoints; i++)
    sField.fillColumn(1+i,globSolPt[i] /= check[i]);

  return true;
}