Go::SplineCurve* SplineUtils::project (const Go::SplineCurve* curve, const FunctionBase& f, int nComp, Real time) { if (!curve || nComp < 1) return nullptr; const Go::BsplineBasis& basis = curve->basis(); const int nPoints = basis.numCoefs(); Go::Point X; RealArray gpar(nPoints), fval, fOfX; fval.reserve(nComp*nPoints); // Compute parameter values of the function sampling points (Greville points) // and evaluate the function at these points for (int i = 0; i < nPoints; i++) { gpar[i] = basis.grevilleParameter(i); curve->point(X,gpar[i]); fOfX = f.getValue(toVec4(X,time)); fval.insert(fval.end(),fOfX.begin(),fOfX.begin()+nComp); } // Get weights for rational spline curves (NURBS) RealArray weights; if (curve->rational()) curve->getWeights(weights); // Project the function onto the spline basis to find control point values return Go::CurveInterpolator::regularInterpolation(basis,gpar,fval,nComp, curve->rational(),weights); }
void SparseTileLayoutData<Dim>::initialize(const Domain_t &bbox, const PatchList_t &plist, const ContextMapper<Dim> &cmap) { this->blocks_m = Loc<Dim>(); initialize(bbox); TilePartition<Dim> gpar(plist); gpar.partition(bbox,this->all_m,cmap); syncPatch(); }
TEST(TestSplineUtils, ExtractBasisVolume) { Go::SphereVolume sphere(1.0, Go::Point(0.0, 0.0, 0.0), Go::Point(0.0, 0.0, 1.0), Go::Point(1.0, 0.0, 0.0)); Go::SplineVolume* vol = sphere.geometryVolume(); vol->setParameterDomain(0.0, 1.0, 0.0, 1.0, 0.0, 1.0); std::vector<Go::BasisDerivs> spline; std::vector<Go::BasisDerivs2> spline2; Matrix gpar(1, 1); gpar(1,1) = 0.3; vol->computeBasisGrid(gpar,gpar,gpar,spline); vol->raiseOrder(1,1,1); vol->computeBasisGrid(gpar,gpar,gpar,spline2); Vector N; Matrix dNdU; Matrix3D d2NdU2; SplineUtils::extractBasis(spline[0],N,dNdU); CHECK_VECTORS_EQUAL(N, "src/Utility/Test/refdata/ExtractBasis_vol_N.asc"); CHECK_MATRICES_EQUAL(dNdU, "src/Utility/Test/refdata/ExtractBasis_vol_dNdU.asc"); SplineUtils::extractBasis(spline2[0],N,dNdU,d2NdU2); CHECK_MATRICES3D_EQUAL(d2NdU2, "src/Utility/Test/refdata/ExtractBasis_vol_d2NdU2.asc"); }
TEST(TestSplineUtils, ExtractBasisSurface) { Go::Plane plane(Go::Point(0.0, 0.0, 0.0), Go::Point(0.0, 0.0, 1.0), Go::Point(sqrt(2.0), sqrt(2.0), 0.0)); Go::SplineSurface* srf = plane.createSplineSurface(); srf->setParameterDomain(0.0, 1.0, 0.0, 1.0); std::vector<Go::BasisDerivsSf> spline; std::vector<Go::BasisDerivsSf2> spline2; Matrix gpar(1, 1); gpar(1,1) = 0.3; srf->computeBasisGrid(gpar,gpar,spline); srf->raiseOrder(1,1); srf->computeBasisGrid(gpar,gpar,spline2); Vector N; Matrix dNdU; Matrix3D d2NdU2; SplineUtils::extractBasis(spline[0],N,dNdU); CHECK_VECTORS_EQUAL(N, "src/Utility/Test/refdata/ExtractBasis_srf_N.asc"); CHECK_MATRICES_EQUAL(dNdU, "src/Utility/Test/refdata/ExtractBasis_srf_dNdU.asc"); SplineUtils::extractBasis(spline2[0],N,dNdU,d2NdU2); CHECK_MATRICES3D_EQUAL(d2NdU2, "src/Utility/Test/refdata/ExtractBasis_srf_d2NdU2.asc"); }
bool ASMs1D::integrate (Integrand& integrand, GlobalIntegral& glInt, const TimeDomain& time) { if (!curv) return true; // silently ignore empty patches // Get Gaussian quadrature points and weights const double* xg = GaussQuadrature::getCoord(nGauss); const double* wg = GaussQuadrature::getWeight(nGauss); if (!xg || !wg) return false; // Get the reduced integration quadrature points, if needed const double* xr = nullptr; const double* wr = nullptr; int nRed = integrand.getReducedIntegration(nGauss); if (nRed > 0) { xr = GaussQuadrature::getCoord(nRed); wr = GaussQuadrature::getWeight(nRed); if (!xr || !wr) return false; } else if (nRed < 0) nRed = nGauss; // The integrand needs to know nGauss if (integrand.getIntegrandType() & Integrand::SECOND_DERIVATIVES) if (curv->rational()) { std::cerr <<" *** ASMs1D::integrate: Second-derivatives of NURBS " <<" is not implemented yet, sorry..."<< std::endl; return false; } // Compute parameter values of the Gauss points over the whole patch Matrix gpar, redpar; this->getGaussPointParameters(gpar,nGauss,xg); if (xr) this->getGaussPointParameters(redpar,nRed,xr); const int p1 = curv->order(); FiniteElement fe(p1); Matrix dNdu, Jac; Matrix3D d2Ndu2, Hess; Vec4 X; if (nsd > 1 && (integrand.getIntegrandType() & Integrand::SECOND_DERIVATIVES)) fe.G.resize(nsd,2); // For storing d{X}/du and d2{X}/du2 // === Assembly loop over all elements in the patch ========================== for (size_t iel = 0; iel < nel; iel++) { fe.iel = MLGE[iel]; if (fe.iel < 1) continue; // zero-length element // Check that the current element has nonzero length double dL = this->getParametricLength(1+iel); if (dL < 0.0) return false; // topology error (probably logic error) // Set up control point coordinates for current element if (!this->getElementCoordinates(fe.Xn,1+iel)) return false; if (integrand.getIntegrandType() & Integrand::ELEMENT_CORNERS) this->getElementEnds(p1+iel,fe.XC); if (integrand.getIntegrandType() & Integrand::NODAL_ROTATIONS) { this->getElementNodalRotations(fe.Tn,iel); if (!elmCS.empty()) fe.Te = elmCS[iel]; } // Initialize element matrices LocalIntegral* A = integrand.getLocalIntegral(fe.N.size(),fe.iel); bool ok = integrand.initElement(MNPC[iel],fe,X,nRed,*A); if (xr) { // --- Selective reduced integration loop -------------------------------- for (int i = 0; i < nRed && ok; i++) { // Local element coordinates of current integration point fe.xi = xr[i]; // Parameter values of current integration point fe.u = redpar(1+i,1+iel); if (integrand.getIntegrandType() & Integrand::NO_DERIVATIVES) this->extractBasis(fe.u,fe.N); else { // Fetch basis function derivatives at current point this->extractBasis(fe.u,fe.N,dNdu); // Compute Jacobian inverse and derivatives dNdu.multiply(0.5*dL); // Derivatives w.r.t. xi=[-1,1] fe.detJxW = utl::Jacobian(Jac,fe.dNdX,fe.Xn,dNdu)*wr[i]; } // Cartesian coordinates of current integration point X = fe.Xn * fe.N; X.t = time.t; // Compute the reduced integration terms of the integrand ok = integrand.reducedInt(*A,fe,X); } } // --- Integration loop over all Gauss points in current element ----------- int jp = iel*nGauss; fe.iGP = firstIp + jp; // Global integration point counter for (int i = 0; i < nGauss && ok; i++, fe.iGP++) { // Local element coordinate of current integration point fe.xi = xg[i]; // Parameter value of current integration point fe.u = gpar(1+i,1+iel); // Compute basis functions and derivatives 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); if (!dNdu.empty()) { // Compute derivatives in terms of physical coordinates dNdu.multiply(0.5*dL); // Derivatives w.r.t. xi=[-1,1] fe.detJxW = utl::Jacobian(Jac,fe.dNdX,fe.Xn,dNdu)*wg[i]; if (fe.detJxW == 0.0) continue; // skip singular points // Compute Hessian of coordinate mapping and 2nd order derivatives if (integrand.getIntegrandType() & Integrand::SECOND_DERIVATIVES) { d2Ndu2.multiply(0.25*dL*dL); // 2nd derivatives w.r.t. xi=[-1,1] if (!utl::Hessian(Hess,fe.d2NdX2,Jac,fe.Xn,d2Ndu2,fe.dNdX)) ok = false; 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()); } } } // Cartesian coordinates of current integration point X = fe.Xn * fe.N; X.t = time.t; // Evaluate the integrand and accumulate element contributions if (ok && !integrand.evalInt(*A,fe,time,X)) ok = false; } // Finalize the element quantities if (ok && !integrand.finalizeElement(*A,fe,time,firstIp+jp)) ok = false; // Assembly of global system integral if (ok && !glInt.assemble(A->ref(),fe.iel)) ok = false; A->destruct(); if (!ok) return false; } return true; }
int main(int argc, char *argv[]) { // Initialize POOMA and output stream, using Tester class Pooma::initialize(argc, argv); Pooma::Tester tester(argc, argv); tester.out() << argv[0] << ": MP DynamicArray w/ shared layouts." << std::endl; tester.out() << "-------------------------------------------" << std::endl; // Create some Interval objects to create and index into Array's with tester.out() << "Creating Interval<1> objects ..." << std::endl; Interval<1> D1(3); tester.out() << "D1 = " << D1 << std::endl; // Create MultiPatch dynamic arrays that share a layout. tester.out() << "Creating MP DynamicArray using domain D1 ... " << std::endl; Loc<1> blocks(3); GridPartition<1> gpar(blocks); LocalMapper<1> cmap(gpar); DynamicLayout dynlayout(D1,gpar,cmap); DynamicArray< int, MultiPatch<DynamicTag,Dynamic> > a2(dynlayout); tester.check("a2 size", a2.domain().size() == D1.size()); tester.check("a2 patches", a2.layout().sizeLocal() == 3); tester.out() << "Creating MP DynamicArray w/ same layout ..." << std::endl; DynamicArray< int, MultiPatch<DynamicTag,Dynamic> > b2(a2.layout()); tester.check("b2 size", b2.domain().size() == D1.size()); tester.check("b2 patches", b2.layout().sizeLocal() == 3); // Test looping over layout nodes tester.out() << "DynamicArray< MultiPatch<DynamicTag,Dynamic> > layout:\n"; tester.out() << a2.layout() << std::endl; // Initialize dynamic arrays with scalars. a2 = 30; b2 = 40; Pooma::blockAndEvaluate(); tester.out() << "Initialized MP DynamicArray's to 30, 40:" << std::endl; tester.out() << "a2 = " << a2 << std::endl; tester.out() << "b2 = " << b2 << std::endl; tester.check("a2 initial sum", sum(a2) == (a2.domain().size() * 30)); tester.check("b2 initial sum", sum(b2) == (b2.domain().size() * 40)); // Create elements in the shared-layout MPE arrays tester.out() << "Creating 2 elements at end of a2 and b2 ..." << std::endl; a2.create(2); a2.sync(); a2(3)=a2(4)=-50; b2(3)=b2(4)=-60; a2(a2.engine().domain().last()-1)=0; a2(a2.engine().domain().last())=0; tester.out() << "a2 = " << a2 << std::endl; tester.out() << "b2 = " << b2 << std::endl; tester.check("a2 size after create", a2.domain().size() == (D1.size() + 2)); tester.check("b2 size after create", b2.domain().size() == (D1.size() + 2)); // Delete an element in the shared-layout MPE arrays tester.out() << "Deleting 2nd element of a2 & b2 w/backfill ..."<<std::endl; b2.destroy(Interval<1>(1,1), BackFill()); b2.sync(); tester.out() << "a2 = " << a2 << std::endl; tester.out() << "b2 = " << b2 << std::endl; tester.check("a2 size after BackFill",a2.domain().size() == (D1.size() + 1)); tester.check("b2 size after BackFill",b2.domain().size() == (D1.size() + 1)); // Copy values from the beginning of a2 and b2 to their end tester.out() << "Copying first three elements of a2 and b2 ..." << std::endl; a2.copy(Interval<1>(3)); a2.sync(); tester.out() << "a2 = " << a2 << std::endl; tester.out() << "b2 = " << b2 << std::endl; tester.check("a2 size after copy", a2.domain().size() == (D1.size() + 4)); tester.check("b2 size after copy", b2.domain().size() == (D1.size() + 4)); // Return resulting error code and exit; Tester will shut down POOMA. tester.out() << "-------------------------------------------" << std::endl; int retval = tester.results("MP DynamicArray w/ shared layouts"); Pooma::finalize(); return retval; }