TestFunction::TestFunction(const BasisFamily& basis, const SpectralBasis& spBasis, const std::string& name) : TestFunctionStub(name, spBasis, vectorDimStructure(basis)[0].first, vectorDimStructure(basis)[0].second, rcp(new TestFunctionData(replicate(basis, spBasis.nterms())))), FuncWithBasis(replicate(basis, spBasis.nterms())) {;}
Expr Expr::operator/(const Expr& other) const { TimeMonitor t(opTimer()); /* if the right operand is a list, this operation * makes no sense */ TEUCHOS_TEST_FOR_EXCEPTION(other.size() != 1, std::runtime_error, "Expr::operator/ detected division by a non-scalar " "expression " << toString()); TEUCHOS_TEST_FOR_EXCEPTION(other.isSpectral(), std::logic_error, "Division by a Spectral Expr is not yet defined"); /* If other is complex, transform to make the denominator real */ if (other.isComplex()) { Expr magSq = other.real()*other.real() + other.imag()*other.imag(); return (*this) * other.conj() / magSq; } /* If I'm complex and the other is not, distribute division over re and im */ if (isComplex() && !other.isComplex()) { return new ComplexExpr(real()/other, imag()/other); } /* If I'm spectral and the other is not, distribute division over coefficients */ if (isSpectral() && !other.isSpectral() && !other.isComplex()) { const SpectralExpr* se = dynamic_cast<const SpectralExpr*>((*this)[0].ptr().get()); SpectralBasis basis = se->getSpectralBasis(); Array<Expr> coeff(basis.nterms()); for(int i=0; i<basis.nterms(); i++) { coeff[i] = se->getCoeff(i)/ other[0]; } Expr rtn = new SpectralExpr( basis, coeff); return rtn; } /* if we are a scalar, do simple scalar division */ if (this->size()==1) { return (*this)[0].divide(other[0]); } /* otherwise, divide each element of the left by the right operand */ Array<Expr> rtn(this->size()); for (int i=0; i<this->size(); i++) { rtn[i] = (*this)[i] / other; } return new ListExpr(rtn); }
DiscreteSpace::DiscreteSpace(const Mesh& mesh, const BasisArray& basis, const SpectralBasis& spBasis, const VectorType<double>& vecType, int setupVerb) : setupVerb_(setupVerb), map_(), mesh_(mesh), subdomains_(), basis_(), vecSpace_(), vecType_(vecType), ghostImporter_() ,transformationBuilder_(0) { init(maximalRegions(basis.size() * spBasis.nterms()), replicate(basis, spBasis.nterms())); }
SpectralExpr::SpectralExpr(const SpectralBasis& sbasis, const Expr& coeffs) : ScalarExpr(), coeffs_(), sbasis_(sbasis) { int nterms = sbasis.nterms(); coeffs_.resize(nterms); for (int i=0; i<nterms; i++) coeffs_[i] = coeffs[i]; }
Expr SpectralPreprocessor::projectSpectral( const Array<Array<Expr> >& terms) { Expr rtn = 0.0; for (int t=0; t<terms.size(); t++) { Expr test; Expr deterministic; Array<Expr> specs; Array<Expr> testCoeffs; Array<Array<Expr> > specCoeffs; Array<SpectralBasis> specBas; parseProduct(terms[t], test, deterministic, specs); const SpectralExpr* specTest = dynamic_cast<const SpectralExpr*>(test.ptr().get()); TEUCHOS_TEST_FOR_EXCEPT(specTest==0); SpectralBasis testBasis = specTest->getSpectralBasis(); for (int i=0; i<testBasis.nterms(); i++) { testCoeffs.append(specTest->getCoeff(i)); } for (int i=0; i<specs.size(); i++) { const SpectralExpr* s = dynamic_cast<const SpectralExpr*>(specs[i].ptr().get()); SpectralBasis bas = s->getSpectralBasis(); specBas.append(bas); Array<Expr> c; for (int j=0; j<bas.nterms(); j++) { c.append(s->getCoeff(j)); } specCoeffs.append(c); } if (specs.size()==0) { for (int i=0; i<testBasis.nterms(); i++) { rtn = rtn + testCoeffs[i]*deterministic; } } else if (specs.size()==1) { for (int i=0; i<testBasis.nterms(); i++) { rtn = rtn + testCoeffs[i]*specCoeffs[0][i]*deterministic; } } else if (specs.size()==2U) { for (int i=0; i<testBasis.nterms(); i++) { for (int j=0; j<specBas[0].nterms(); j++) { for (int k=0; k<specBas[1].nterms(); k++) { double w = testBasis.expectation( specBas[0].getElement(j), specBas[1].getElement(k), i) / testBasis.expectation(0,i,i); if (w==0.0) continue; rtn = rtn + w*testCoeffs[i] *specCoeffs[0][j]*specCoeffs[1][k]*deterministic; } } } } else { TEUCHOS_TEST_FOR_EXCEPTION(specs.size() > 2, std::runtime_error, "not ready to work with more than two spectral unks"); } } return rtn; }
int main(int argc, char** argv) { try { MPISession::init(&argc, (void***)&argv); Expr::showAllParens() = true; Expr x = new CoordExpr(0); Expr y = new CoordExpr(1); Expr z = new CoordExpr(2); Expr dx = new Derivative(0); int ndim = 2; int order = 2; SpectralBasis SB = new HermiteSpectralBasis(ndim, order); Expr u = new UnknownFunctionStub("u", SB); Expr v = new TestFunctionStub("v", SB); Expr w = new UnknownFunctionStub("w", SB); Array<Expr> Ex1(6); Ex1[0] = 1.0; Ex1[1] = x; Ex1[2] = 0.0; Ex1[3] = x*y; Ex1[4] = x+y; Ex1[5] = y; Expr SE1 = new SpectralExpr(SB, Ex1); Array<Expr> Ex2(6); Ex2[0] = -3.0*x; Ex2[1] = 0.0; Ex2[2] = -y; Ex2[3] = x-y; Ex2[4] = -4.0*y + 2.0*x; Ex2[5] = 0.0; Expr SE2 = new SpectralExpr(SB, Ex2); Expr G = x*x; Expr Sum = (dx*v) * (dx*u) + v*x; Handle<CellFilterStub> domain = rcp(new CellFilterStub()); Handle<QuadratureFamilyStub> quad = rcp(new QuadratureFamilyStub(1)); Expr eqn = Integral(domain, Sum, quad); const SpectralExpr* se = dynamic_cast<const SpectralExpr*>(Sum.ptr().get()); if (se != 0) { SpectralBasis basis = se->getSpectralBasis(); for(int i=0; i< basis.nterms(); i++) cout << se->getCoeff(i) << std::endl; } cout << Sum << std::endl << std::endl; cout << eqn << std::endl << std::endl; } catch(std::exception& e) { std::cerr << e.what() << std::endl; } MPISession::finalize(); }
bool BlockStochPoissonTest1D() { /* We will do our linear algebra using Epetra */ VectorType<double> vecType = new EpetraVectorType(); /* Read a mesh */ MeshType meshType = new BasicSimplicialMeshType(); int nx = 32; MeshSource mesher = new PartitionedLineMesher(0.0, 1.0, nx, meshType); Mesh mesh = mesher.getMesh(); /* Create a cell filter that will identify the maximal cells * in the interior of the domain */ CellFilter interior = new MaximalCellFilter(); CellFilter pts = new DimensionalCellFilter(0); CellFilter left = pts.subset(new CoordinateValueCellPredicate(0,0.0)); CellFilter right = pts.subset(new CoordinateValueCellPredicate(0,1.0)); Expr x = new CoordExpr(0); /* Create the stochastic coefficients */ int nDim = 1; int order = 6; #ifdef HAVE_SUNDANCE_STOKHOS Out::root() << "using Stokhos hermite basis" << std::endl; SpectralBasis pcBasis = new Stokhos::HermiteBasis<int,double>(order); #else Out::root() << "using George's hermite basis" << std::endl; SpectralBasis pcBasis = new HermiteSpectralBasis(nDim, order); #endif Array<Expr> q(pcBasis.nterms()); Array<Expr> kappa(pcBasis.nterms()); Array<Expr> uEx(pcBasis.nterms()); double a = 0.1; q[0] = -2 + pow(a,2)*(4 - 9*x)*x - 2*pow(a,3)*(-1 + x)*(1 + 3*x*(-3 + 4*x)); q[1] = -(a*(-3 + 10*x + 2*a*(-1 + x*(8 - 9*x + a*(-4 + 3*(5 - 4*x)*x + 12*a*(-1 + x)*(1 + 5*(-1 + x)*x)))))); q[2] = a*(-4 + 6*x + a*(1 - x*(2 + 3*x) + a*(4 - 28*x + 30*pow(x,2)))); q[3] = -(pow(a,2)*(-3 + x*(20 - 21*x + a*(-4 + 3*(5 - 4*x)*x + 24*a*(-1 + x)*(1 + 5*(-1 + x)*x))))); q[4] = pow(a,3)*(1 + x*(-6 + x*(3 + 4*x))); q[5] = -4*pow(a,4)*(-1 + x)*x*(1 + 5*(-1 + x)*x); q[6] = 0.0; uEx[0] = -((-1 + x)*x); uEx[1] = -(a*(-1 + x)*pow(x,2)); uEx[2] = a*pow(-1 + x,2)*x; uEx[3] = pow(a,2)*pow(-1 + x,2)*pow(x,2); uEx[4] = 0.0; uEx[5] = 0.0; uEx[6] = 0.0; kappa[0] = 1.0; kappa[1] = a*x; kappa[2] = -(pow(a,2)*(-1 + x)*x); kappa[3] = 1.0; // unused kappa[4] = 1.0; // unused kappa[5] = 1.0; // unused kappa[6] = 1.0; // unused Array<Expr> uBC(pcBasis.nterms()); for (int i=0; i<pcBasis.nterms(); i++) uBC[i] = 0.0; int L = nDim+2; int P = pcBasis.nterms(); Out::os() << "L = " << L << std::endl; Out::os() << "P = " << P << std::endl; /* Create the unknown and test functions. Do NOT use the spectral * basis here */ Expr u = new UnknownFunction(new Lagrange(4), "u"); Expr v = new TestFunction(new Lagrange(4), "v"); /* Create differential operator and coordinate function */ Expr dx = new Derivative(0); Expr grad = dx; /* We need a quadrature rule for doing the integrations */ QuadratureFamily quad = new GaussianQuadrature(12); /* Now we create problem objects to build each $K_j$ and $f_j$. * There will be L matrix-vector pairs */ Array<Expr> eqn(P); Array<Expr> bc(P); Array<LinearProblem> prob(P); Array<LinearOperator<double> > KBlock(L); Array<Vector<double> > fBlock(P); Array<Vector<double> > solnBlock; for (int j=0; j<P; j++) { eqn[j] = Integral(interior, kappa[j]*(grad*v)*(grad*u) + v*q[j], quad); bc[j] = EssentialBC(left+right, v*(u-uBC[j]), quad); prob[j] = LinearProblem(mesh, eqn[j], bc[j], v, u, vecType); if (j<L) KBlock[j] = prob[j].getOperator(); fBlock[j] = -1.0*prob[j].getSingleRHS(); } /* Read the solver to be used on the diagonal blocks */ LinearSolver<double> diagSolver = LinearSolverBuilder::createSolver("amesos.xml"); double convTol = 1.0e-12; int maxIters = 30; int verb = 1; StochBlockJacobiSolver solver(diagSolver, pcBasis, convTol, maxIters, verb); solver.solve(KBlock, fBlock, solnBlock); /* write the solution */ FieldWriter w = new MatlabWriter("Stoch1D"); w.addMesh(mesh); DiscreteSpace discSpace(mesh, new Lagrange(4), vecType); for (int i=0; i<P; i++) { L2Projector proj(discSpace, uEx[i]); Expr ue_i = proj.project(); Expr df = new DiscreteFunction(discSpace, solnBlock[i]); w.addField("u["+ Teuchos::toString(i)+"]", new ExprFieldWrapper(df)); w.addField("uEx["+ Teuchos::toString(i)+"]", new ExprFieldWrapper(ue_i)); } w.write(); double totalErr2 = 0.0; DiscreteSpace discSpace4(mesh, new Lagrange(4), vecType); for (int i=0; i<P; i++) { Expr df = new DiscreteFunction(discSpace4, solnBlock[i]); Expr errExpr = Integral(interior, pow(uEx[i]-df, 2.0), quad); Expr scaleExpr = Integral(interior, pow(uEx[i], 2.0), quad); double errSq = evaluateIntegral(mesh, errExpr); double scale = evaluateIntegral(mesh, scaleExpr); if (scale > 0.0) Out::os() << "mode i=" << i << " error=" << sqrt(errSq/scale) << std::endl; else Out::os() << "mode i=" << i << " error=" << sqrt(errSq) << std::endl; } double tol = 1.0e-12; return SundanceGlobal::checkTest(sqrt(totalErr2), tol); }
Expr Expr::operator-() const { TimeMonitor t(opTimer()); TimeMonitor t1(unaryMinusTimer()); Tabs tabs; if (this->isComplex()) { return new ComplexExpr(-real(), -imag()); } /* if we are a real scalar, process the unary minus here */ if (this->size()==1) { /* if we are spectral, thread unary minus over coeffs */ const SpectralExpr* se = dynamic_cast<const SpectralExpr*>((*this)[0].ptr().get()); if (se != 0) { SpectralBasis basis = se->getSpectralBasis(); Array<Expr> coeff(basis.nterms()); for(int i=0; i<basis.nterms(); i++) { coeff[i] = - se->getCoeff(i); } Expr rtn = new SpectralExpr( basis, coeff); return rtn; } /* Test for some special cases that can be dealt with efficiently */ const ConstantExpr* c = dynamic_cast<const ConstantExpr*>((*this)[0].ptr().get()); const UnaryMinus* u = dynamic_cast<const UnaryMinus*>((*this)[0].ptr().get()); /* if we are a constant, just modify the constant */ if (c != 0) { if (c->value()==0.0) { return new ZeroExpr(); } else { return new ConstantExpr(-1.0 * c->value()); } } else if (u != 0) /* if we are already a unary minus, apply -(-x) --> x */ { return u->arg(); } else /* no special structure, so return a UnaryMinusExpr */ { RCP<ScalarExpr> sThis = rcp_dynamic_cast<ScalarExpr>((*this)[0].ptr()); TEUCHOS_TEST_FOR_EXCEPTION(sThis.get()==NULL, std::logic_error, "Expr::operator-(): Operand " << (*this)[0].toString() << " is a non-scalar expression. All list structure " "should have been handled before this point"); return new UnaryMinus(sThis); } } /* otherwise, distribute the sign change over the list */ Array<Expr> rtn(this->size()); for (int i=0; i<this->size(); i++) { rtn[i] = -((*this)[i]); } return new ListExpr(rtn); }