void RHSTests::setup() { FieldContainer<double> quadPoints(4,2); quadPoints(0,0) = 0.0; // x1 quadPoints(0,1) = 0.0; // y1 quadPoints(1,0) = 1.0; quadPoints(1,1) = 0.0; quadPoints(2,0) = 1.0; quadPoints(2,1) = 1.0; quadPoints(3,0) = 0.0; quadPoints(3,1) = 1.0; int H1Order = 3; int delta_p = 3; // for test functions int horizontalCells = 2; int verticalCells = 2; double eps = 1.0; // not really testing for sharp gradients right now--just want to see if things basically work double beta_x = 1.0; double beta_y = 1.0; BFPtr confusionBF = ConfusionBilinearForm::confusionBF(eps,beta_x,beta_y); Teuchos::RCP<ConfusionProblemLegacy> confusionProblem = Teuchos::rcp( new ConfusionProblemLegacy(confusionBF, beta_x, beta_y) ); _rhs = confusionProblem; _mesh = MeshFactory::buildQuadMesh(quadPoints, horizontalCells, verticalCells, confusionBF, H1Order, H1Order+delta_p); _mesh->setUsePatchBasis(false); VarFactoryPtr varFactory = confusionBF->varFactory(); // Create test IDs that match the enum in ConfusionBilinearForm _tau = varFactory->testVar(ConfusionBilinearForm::S_TAU,HDIV); _v = varFactory->testVar(ConfusionBilinearForm::S_V,HGRAD); _rhsEasy = RHS::rhs(); _rhsEasy->addTerm( _v ); }
void PoissonExactSolution::setUseSinglePointBCForPHI(bool useSinglePointBCForPhi, IndexType vertexIndexForZeroValue) { FunctionPtr phi_exact = phi(); VarFactoryPtr vf = _bf->varFactory(); VarPtr psi_hat_n = vf->fluxVar(PoissonBilinearForm::S_PSI_HAT_N); VarPtr q = vf->testVar(PoissonBilinearForm::S_Q, HGRAD); VarPtr phi = vf->fieldVar(PoissonBilinearForm::S_PHI); SpatialFilterPtr wholeBoundary = SpatialFilter::allSpace(); FunctionPtr n = Function::normal(); FunctionPtr psi_n_exact = phi_exact->grad() * n; _bc = BC::bc(); _bc->addDirichlet(psi_hat_n, wholeBoundary, psi_n_exact); if (!useSinglePointBCForPhi) { _bc->addZeroMeanConstraint(phi); } else { std::vector<double> point = getPointForBCImposition(); double value = Function::evaluate(phi_exact, point[0], point[1]); // cout << "PoissonExactSolution: imposing phi = " << value << " at (" << point[0] << ", " << point[1] << ")\n"; _bc->addSpatialPointBC(phi->ID(), value, point); } }
VarPtr PoissonFormulation::tau() { VarFactoryPtr vf = _poissonBF->varFactory(); if (_spaceDim > 1) return vf->testVar(S_TAU, HDIV); else return vf->testVar(S_TAU, HGRAD); }
BFPtr TestBilinearFormDx::bf() { VarFactoryPtr vf = VarFactory::varFactory(); VarPtr u = vf->fieldVar("u",HGRAD); VarPtr v = vf->testVar("v",HGRAD); BFPtr bf = BF::bf(vf); bf->addTerm(u->dx(), v->dx()); return bf; }
bool LinearTermTests::testLinearTermEvaluation() { bool success = true; double eps = .1; FunctionPtr one = Function::constant(1.0); vector<double> e1,e2; e1.push_back(1.0); e1.push_back(0.0); e2.push_back(0.0); e2.push_back(1.0); // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr tau = varFactory->testVar("\\tau", HDIV); VarPtr v = varFactory->testVar("v", HGRAD); // define a couple LinearTerms LinearTermPtr vVecLT = Teuchos::rcp(new LinearTerm); LinearTermPtr tauVecLT = Teuchos::rcp(new LinearTerm); vVecLT->addTerm(sqrt(eps)*v->grad()); tauVecLT->addTerm((1/sqrt(eps))*tau); //////////////////// evaluate LinearTerms ///////////////// map<int,FunctionPtr> errRepMap; errRepMap[v->ID()] = one; errRepMap[tau->ID()] = one*e1+one*e2; // vector valued fxn (1,1) FunctionPtr errTau = tauVecLT->evaluate(errRepMap,false); FunctionPtr errV = vVecLT->evaluate(errRepMap,false); try { bool xTauZero = errTau->x()->isZero(); bool yTauZero = errTau->y()->isZero(); bool xVZero = errV->dx()->isZero(); bool yVZero = errV->dy()->isZero(); } catch (...) { cout << "testLinearTermEvaluation: Caught exception.\n"; success = false; } /* FunctionPtr xErr = (errTau->x())*(errTau->x()) + (errV->dx())*(errV->dx()); FunctionPtr yErr = (errTau->y())*(errTau->y()) + (errV->dy())*(errV->dy()); double xErrVal = xErr->integrate(mesh,15,true); */ // if we don't crash, return success return success; }
bool LobattoBasisTests::testLobattoValues() { bool success = true; FunctionPtr x = Function::xn(1); vector< FunctionPtr > lobattoFunctionsExpected; // Pavel Solin's first two Lobatto functions: // lobattoFunctionsExpected.push_back( (1 - x) / 2 ); // lobattoFunctionsExpected.push_back( (1 + x) / 2 ); // Demkowicz's: lobattoFunctionsExpected.push_back( Function::constant(1.0) ); lobattoFunctionsExpected.push_back( x ); lobattoFunctionsExpected.push_back( (x*x - 1) / 2); lobattoFunctionsExpected.push_back( (x*x - 1) * x / 2); lobattoFunctionsExpected.push_back( (x*x - 1) * (5 * x * x - 1) / 8); lobattoFunctionsExpected.push_back( (x*x - 1) * (7 * x * x - 3) * x / 8); vector< FunctionPtr > lobattoFunctions; bool conformingFalse = false; int n_max = 4; for (int n=0; n<=n_max; n++) { lobattoFunctions.push_back( Teuchos::rcp( new LobattoFunction<>(n,conformingFalse,false) ) ); } VarFactoryPtr varFactory = VarFactory::varFactory(); varFactory->testVar("v", HGRAD); varFactory->fieldVar("u", L2); BFPtr bf = Teuchos::rcp( new BF(varFactory) ); MeshPtr mesh = MeshFactory::quadMesh(bf, n_max); BasisCachePtr basisCache = BasisCache::basisCacheForCell(mesh, 0); double tol = 1e-12; for (int n=0; n<=n_max; n++) { if (! lobattoFunctions[n]->equals(lobattoFunctionsExpected[n], basisCache, tol) ) { cout << "Lobatto function " << n << " does not match expected.\n"; success = false; } } return success; }
bool LobattoBasisTests::testLobattoDerivativeValues() { bool success = true; FunctionPtr x = Function::xn(1); vector< FunctionPtr > legendreFunctions; // manually specified vector< FunctionPtr > lobattoDerivatives; FunctionPtr one = Function::constant(1); legendreFunctions.push_back(one); legendreFunctions.push_back(x); legendreFunctions.push_back(0.5 * (3 * x * x - 1) ); legendreFunctions.push_back( (5 * x * x * x - 3 * x) / 2); legendreFunctions.push_back( (1.0 / 8.0) * (35 * x * x * x * x - 30 * x * x + 3) ); legendreFunctions.push_back( (1.0 / 8.0) * (63 * x * x * x * x * x - 70 * x * x * x + 15 * x) ); bool conformingFalse = false; int n_max = 4; for (int n=0; n<=n_max+1; n++) { lobattoDerivatives.push_back( Teuchos::rcp( new LobattoFunction<>(n,conformingFalse,true) ) ); } VarFactoryPtr varFactory = VarFactory::varFactory(); varFactory->testVar("v", HGRAD); varFactory->fieldVar("u", L2); BFPtr bf = Teuchos::rcp( new BF(varFactory) ); MeshPtr mesh = MeshFactory::quadMesh(bf, n_max); BasisCachePtr basisCache = BasisCache::basisCacheForCell(mesh, 0); double tol = 1e-8; for (int n=0; n<=n_max; n++) { if (! legendreFunctions[n]->equals(lobattoDerivatives[n+1], basisCache, tol) ) { cout << "Legendre function " << n << " != Lobatto function " << n + 1 << " derivative.\n"; cout << "L_" << n << "(0.5) = " << Function::evaluate(legendreFunctions[n],0.5) << endl; cout << "l'_" << n+1 << "(0.5) = " << Function::evaluate(lobattoDerivatives[n+1],0.5) << endl; success = false; } } return success; }
VarPtr PressurelessStokesFormulation::v(int i) { if (i > _spaceDim) { TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "i must be less than or equal to _spaceDim"); } VarFactoryPtr vf = _stokesBF->varFactory(); switch (i) { case 1: return vf->testVar(S_V1, HGRAD); case 2: return vf->testVar(S_V2, HGRAD); case 3: return vf->testVar(S_V3, HGRAD); } TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "unhandled i value"); }
bool LobattoBasisTests::testLegendreValues() { bool success = true; FunctionPtr x = Function::xn(1); vector< FunctionPtr > legendreFunctionsExpected; legendreFunctionsExpected.push_back( Function::constant(1.0) ); legendreFunctionsExpected.push_back( x ); legendreFunctionsExpected.push_back( (3 * x*x - 1) / 2); legendreFunctionsExpected.push_back( (5 * x*x*x - 3*x) / 2); legendreFunctionsExpected.push_back( (35 * x * x * x * x - 30 * x * x + 3) / 8); legendreFunctionsExpected.push_back( (63 * x * x * x * x * x - 70 * x * x * x + 15 * x) / 8); vector< FunctionPtr > legendreFunctions; int n_max = 4; for (int n=0; n<=n_max; n++) { legendreFunctions.push_back( Teuchos::rcp( new LegendreFunction(n) ) ); } VarFactoryPtr varFactory = VarFactory::varFactory(); varFactory->testVar("v", HGRAD); varFactory->fieldVar("u", L2); BFPtr bf = Teuchos::rcp( new BF(varFactory) ); MeshPtr mesh = MeshFactory::quadMesh(bf, n_max); BasisCachePtr basisCache = BasisCache::basisCacheForCell(mesh, 0); double tol = 1e-8; // relax to make sure that failure isn't just roundoff for (int n=0; n<=n_max; n++) { if (! legendreFunctions[n]->equals(legendreFunctionsExpected[n], basisCache, tol) ) { cout << "Legendre function " << n << " does not match expected.\n"; success = false; } } return success; }
ConfusionManufacturedSolution::ConfusionManufacturedSolution(double epsilon, double beta_x, double beta_y) { _epsilon = epsilon; _beta_x = beta_x; _beta_y = beta_y; // set the class variables from ExactSolution: // _bc = Teuchos::rcp(this,false); // false: don't let the RCP own the memory // _rhs = Teuchos::rcp(this,false); BFPtr bf = ConfusionBilinearForm::confusionBF(epsilon,beta_x,beta_y); _bilinearForm = bf; VarFactoryPtr vf = bf->varFactory(); VarPtr u = vf->fieldVar(ConfusionBilinearForm::S_U); VarPtr sigma1 = vf->fieldVar(ConfusionBilinearForm::S_SIGMA_1); VarPtr sigma2 = vf->fieldVar(ConfusionBilinearForm::S_SIGMA_2); _u_hat = vf->traceVar(ConfusionBilinearForm::S_U_HAT); _beta_n_u_minus_sigma_hat = vf->fluxVar(ConfusionBilinearForm::S_BETA_N_U_MINUS_SIGMA_HAT); _v = vf->testVar(ConfusionBilinearForm::S_V, HGRAD); FunctionPtr u_exact = this->u(); FunctionPtr sigma_exact = epsilon * u_exact->grad(); FunctionPtr u_exact_laplacian = u_exact->dx()->dx() + u_exact->dy()->dy(); _rhs = RHS::rhs(); FunctionPtr f = - _epsilon * u_exact_laplacian + _beta_x * u_exact->dx() + _beta_y * u_exact->dy(); _rhs->addTerm( f * _v ); _bc = BC::bc(); _bc->addDirichlet(_u_hat, SpatialFilter::allSpace(), u_exact); FunctionPtr beta = Function::vectorize(Function::constant(_beta_x), Function::constant(_beta_y)); FunctionPtr n = Function::normal(); FunctionPtr one_skeleton = Function::meshSkeletonCharacteristic(); // allows restriction to skeleton FunctionPtr sigma_flux_exact = beta * ( n * u_exact - sigma_exact * one_skeleton); this->setSolutionFunction(u, u_exact); this->setSolutionFunction(sigma1, sigma_exact->x()); this->setSolutionFunction(sigma2, sigma_exact->y()); this->setSolutionFunction(_u_hat, u_exact); this->setSolutionFunction(_beta_n_u_minus_sigma_hat, sigma_flux_exact); }
// test variables: VarPtr PressurelessStokesFormulation::tau(int i, int j) { if (i > j) // swap them { int k = i; i = j; j = k; } if (j > _spaceDim) { TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "i and j must be less than or equal to _spaceDim"); } VarFactoryPtr vf = _stokesBF->varFactory(); switch (i) { case 1: switch (j) { case 1: return vf->testVar(S_TAU11, HGRAD); case 2: return vf->testVar(S_TAU12, HGRAD); case 3: return vf->testVar(S_TAU13, HGRAD); } case 2: switch (j) { case 2: return vf->testVar(S_TAU22, HGRAD); case 3: return vf->testVar(S_TAU23, HGRAD); } case 3: switch (j) { case 3: return vf->testVar(S_TAU23, HGRAD); } } TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "unhandled (i,j) pair"); }
VarPtr PressurelessStokesFormulation::sigma(int i, int j) { if (i > j) // swap them { int k = i; i = j; j = k; } if (j > _spaceDim) { TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "i and j must be less than or equal to _spaceDim"); } VarFactoryPtr vf = _stokesBF->varFactory(); switch (i) { case 1: switch (j) { case 1: return vf->fieldVar(S_SIGMA11); case 2: return vf->fieldVar(S_SIGMA12); case 3: return vf->fieldVar(S_SIGMA13); } case 2: switch (j) { case 2: return vf->fieldVar(S_SIGMA22); case 3: return vf->fieldVar(S_SIGMA23); } case 3: switch (j) { case 3: return vf->fieldVar(S_SIGMA23); } } TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "unhandled (i,j) pair"); }
PoissonExactSolution::PoissonExactSolution(PoissonExactSolutionType type, int polyOrder, bool useConformingTraces) { // poly order here means that of phi _polyOrder = polyOrder; _type = type; _bf = PoissonBilinearForm::poissonBilinearForm(useConformingTraces); this->_bilinearForm = _bf; FunctionPtr phi_exact = phi(); VarFactoryPtr vf = _bf->varFactory(); VarPtr psi_hat_n = vf->fluxVar(PoissonBilinearForm::S_PSI_HAT_N); VarPtr phi_hat = vf->traceVar(PoissonBilinearForm::S_PHI_HAT); VarPtr phi = vf->fieldVar(PoissonBilinearForm::S_PHI); VarPtr psi_1 = vf->fieldVar(PoissonBilinearForm::S_PSI_1); VarPtr psi_2 = vf->fieldVar(PoissonBilinearForm::S_PSI_2); VarPtr q = vf->testVar(PoissonBilinearForm::S_Q, HGRAD); FunctionPtr psi_exact = phi_exact->grad(); FunctionPtr n = Function::normal(); this->setSolutionFunction(phi, phi_exact); this->setSolutionFunction(psi_1, psi_exact->x()); this->setSolutionFunction(psi_2, psi_exact->y()); this->setSolutionFunction(phi_hat, phi_exact); this->setSolutionFunction(psi_hat_n, psi_exact * n); SpatialFilterPtr wholeBoundary = SpatialFilter::allSpace(); _rhs = RHS::rhs(); FunctionPtr f = phi_exact->dx()->dx() + phi_exact->dy()->dy(); _rhs->addTerm(f * q); setUseSinglePointBCForPHI(false, -1); // sets _bc }
void LinearTermTests::setup() { // VarPtr v1, v2, v3; // HGRAD members (test variables) // VarPtr q1, q2, q3; // HDIV members (test variables) // VarPtr u1, u2, u3; // L2 members (trial variables) // VarPtr u1_hat, u2_hat; // trace variables // VarPtr u3_hat_n; // flux variable // // FunctionPtr sine_x; sine_x = Teuchos::rcp( new Sine_x ); cos_y = Teuchos::rcp( new Cosine_y ); VarFactoryPtr varFactory = VarFactory::varFactory(); q1 = varFactory->testVar("q_1", HDIV); q2 = varFactory->testVar("q_2", HDIV); q3 = varFactory->testVar("q_3", HDIV); v1 = varFactory->testVar("v_1", HGRAD); v2 = varFactory->testVar("v_2", HGRAD); v3 = varFactory->testVar("v_3", HGRAD); u1 = varFactory->fieldVar("u_1", HGRAD); u2 = varFactory->fieldVar("u_2", HGRAD); u3 = varFactory->fieldVar("u_3", HGRAD); u1_hat = varFactory->traceVar("\\widehat{u}_1"); u2_hat = varFactory->traceVar("\\widehat{u}_2"); u3_hat_n = varFactory->fluxVar("\\widehat{u}_3n"); bf = Teuchos::rcp(new BF(varFactory)); // made-up bf for Mesh + previous solution tests bf->addTerm(u1_hat, q1->dot_normal()); bf->addTerm(u1, q1->x()); bf->addTerm(u2, q1->y()); bf->addTerm(u3_hat_n, v1); bf->addTerm(u3, v1); // DofOrderingFactory discreteSpaceFactory(bf); int polyOrder = 3, testToAdd = 2; Teuchos::RCP<shards::CellTopology> quadTopoPtr; // quadTopoPtr = Teuchos::rcp(new shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >() )); // define nodes for mesh FieldContainer<double> quadPoints(4,2); quadPoints(0,0) = -1.0; // x1 quadPoints(0,1) = -1.0; // y1 quadPoints(1,0) = 1.0; quadPoints(1,1) = -1.0; quadPoints(2,0) = 1.0; quadPoints(2,1) = 1.0; quadPoints(3,0) = -1.0; quadPoints(3,1) = 1.0; int horizontalElements = 2, verticalElements = 2; mesh = MeshFactory::buildQuadMesh(quadPoints, horizontalElements, verticalElements, bf, polyOrder+1, polyOrder+1+testToAdd); ElementTypePtr elemType = mesh->getElement(0)->elementType(); trialOrder = elemType->trialOrderPtr; testOrder = elemType->testOrderPtr; basisCache = Teuchos::rcp(new BasisCache(elemType, mesh)); vector<GlobalIndexType> cellIDs; cellIDs.push_back(0); cellIDs.push_back(1); cellIDs.push_back(2); cellIDs.push_back(3); bool createSideCacheToo = true; basisCache->setPhysicalCellNodes(mesh->physicalCellNodesGlobal(elemType), cellIDs, createSideCacheToo); }
bool LinearTermTests::testIntegrateMixedBasis() { bool success = true; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr v = varFactory->testVar("v", HGRAD); // define trial variables VarPtr beta_n_u_hat = varFactory->fluxVar("\\widehat{\\beta \\cdot n }"); VarPtr u = varFactory->fieldVar("u"); vector<double> beta; beta.push_back(1.0); beta.push_back(1.0); //////////////////// DEFINE BILINEAR FORM/Mesh /////////////////////// BFPtr convectionBF = Teuchos::rcp( new BF(varFactory) ); // v terms: convectionBF->addTerm( -u, beta * v->grad() ); convectionBF->addTerm( beta_n_u_hat, v); convectionBF->addTerm( u, v); // build CONSTANT SINGLE ELEMENT MESH int order = 0; int H1Order = order+1; int pToAdd = 1; int nCells = 2; // along a side // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = MeshUtilities::buildUnitQuadMesh(nCells,convectionBF, H1Order, H1Order+pToAdd); ElementTypePtr elemType = mesh->getElement(0)->elementType(); BasisCachePtr basisCache = Teuchos::rcp(new BasisCache(elemType, mesh)); vector<GlobalIndexType> cellIDs; vector< ElementPtr > allElems = mesh->activeElements(); vector< ElementPtr >::iterator elemIt; for (elemIt=allElems.begin(); elemIt!=allElems.end(); elemIt++) { cellIDs.push_back((*elemIt)->cellID()); } bool createSideCacheToo = true; basisCache->setPhysicalCellNodes(mesh->physicalCellNodesGlobal(elemType), cellIDs, createSideCacheToo); int numTrialDofs = elemType->trialOrderPtr->totalDofs(); int numCells = mesh->numActiveElements(); double areaPerCell = 1.0 / numCells; FieldContainer<double> integrals(numCells,numTrialDofs); FieldContainer<double> expectedIntegrals(numCells,numTrialDofs); double sidelengthOfCell = 1.0 / nCells; DofOrderingPtr trialOrdering = elemType->trialOrderPtr; int dofForField = trialOrdering->getDofIndex(u->ID(), 0); vector<int> dofsForFlux; const vector<int>* sidesForFlux = &trialOrdering->getSidesForVarID(beta_n_u_hat->ID()); for (vector<int>::const_iterator sideIt = sidesForFlux->begin(); sideIt != sidesForFlux->end(); sideIt++) { int sideIndex = *sideIt; dofsForFlux.push_back(trialOrdering->getDofIndex(beta_n_u_hat->ID(), 0, sideIndex)); } for (int cellIndex = 0; cellIndex < numCells; cellIndex++) { expectedIntegrals(cellIndex, dofForField) = areaPerCell; for (vector<int>::iterator dofIt = dofsForFlux.begin(); dofIt != dofsForFlux.end(); dofIt++) { int fluxDofIndex = *dofIt; expectedIntegrals(cellIndex, fluxDofIndex) = sidelengthOfCell; } } // cout << "expectedIntegrals:\n" << expectedIntegrals; // setup: with constant degrees of freedom, we expect that the integral of int_dK (flux) + int_K (field) will be ones for each degree of freedom, assuming the basis functions for these constants field/flux variables are just C = 1.0. // //On a unit square, int_K (constant) = 1.0, and int_dK (u_i) = 1, for i = 0,...,3. LinearTermPtr lt = 1.0 * beta_n_u_hat; LinearTermPtr field = 1.0 * u; lt->addTerm(field,true); lt->integrate(integrals, elemType->trialOrderPtr, basisCache); double tol = 1e-12; double maxDiff; success = TestSuite::fcsAgree(integrals,expectedIntegrals,tol,maxDiff); if (success==false) { cout << "Failed testIntegrateMixedBasis with maxDiff = " << maxDiff << endl; } return success; }
int main(int argc, char *argv[]) { Teuchos::GlobalMPISession mpiSession(&argc, &argv, 0); int spaceDim = 2; int meshWidth = 2; bool conformingTraces = true; int H1Order = 2, delta_k = 3; double domainWidth = 1.0e-3; bool diagScaling = false; double h = domainWidth / meshWidth; double weight = h / 4.0; // ratio of area of square with sidelength h to its perimeter double sigma_weight = 1.0; // h / 4.0; // sigma = sigma_weight * u->grad() Space uHatSpace = conformingTraces ? HGRAD : L2; VarFactoryPtr vf = VarFactory::varFactory(); // fields VarPtr u = vf->fieldVar("u"); VarPtr sigma = vf->fieldVar("sigma", VECTOR_L2); // traces VarPtr u_hat = vf->traceVar("u_hat", uHatSpace); VarPtr sigma_n = vf->fluxVar("sigma_n"); // tests VarPtr v = vf->testVar("v", HGRAD); VarPtr tau = vf->testVar("tau", HDIV); BFPtr bf = BF::bf(vf); // standard BF: // bf->addTerm(sigma, v->grad()); // bf->addTerm(sigma_n, v); // // bf->addTerm(sigma, tau); // bf->addTerm(u, tau->div()); // bf->addTerm(-u_hat, tau->dot_normal()); // weighted BF: bf->addTerm(sigma, v->grad()); bf->addTerm(weight * sigma_n, v); bf->addTerm(sigma, tau); bf->addTerm(sigma_weight * u, tau->div()); bf->addTerm(- sigma_weight * weight * u_hat, tau->dot_normal()); IPPtr ip = IP::ip(); // standard IP: ip->addTerm(tau + v->grad()); ip->addTerm(tau->div()); ip->addTerm(v); ip->addTerm(tau); // weighted IP: // ip->addTerm(tau + v->grad()); // ip->addTerm(sigma_weight * tau->div()); // ip->addTerm(max(sigma_weight,1e-3) * v); // ip->addTerm(sigma_weight * weight * tau); BCPtr bc = BC::bc(); bc->addDirichlet(u_hat, SpatialFilter::allSpace(), Function::zero()); RHSPtr rhs = RHS::rhs(); rhs->addTerm(1.0 * sigma_weight * v); vector<double> dimensions(spaceDim,domainWidth); vector<int> elementCounts(spaceDim,meshWidth); MeshPtr mesh = MeshFactory::rectilinearMesh(bf, dimensions, elementCounts, H1Order, delta_k); SolutionPtr soln = Solution::solution(mesh, bc, rhs, ip); soln->setUseCondensedSolve(true); soln->initializeLHSVector(); soln->initializeStiffnessAndLoad(); soln->populateStiffnessAndLoad(); Teuchos::RCP<Epetra_RowMatrix> stiffness = soln->getStiffnessMatrix(); double condNumber = conditionNumberLAPACK(*stiffness, diagScaling); cout << "condest (1-norm): " << condNumber << endl; return 0; }
bool VectorizedBasisTestSuite::testPoisson() { bool success = true; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr tau = varFactory->testVar("\\tau", HDIV); VarPtr v = varFactory->testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory->traceVar("\\widehat{u}"); VarPtr sigma_n = varFactory->fluxVar("\\widehat{\\sigma_{n}}"); VarPtr u = varFactory->fieldVar("u"); VarPtr sigma = varFactory->fieldVar("\\sigma", VECTOR_L2); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // tau terms: bf->addTerm(sigma, tau); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma, v->grad() ); bf->addTerm( -sigma_n, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = bf->graphNorm(); //////////////////// SPECIFY RHS /////////////////////// RHSPtr rhs = RHS::rhs(); FunctionPtr f = Function::constant(1.0); rhs->addTerm( f * v ); //////////////////// CREATE BCs /////////////////////// BCPtr bc = BC::bc(); SpatialFilterPtr boundary = SpatialFilter::allSpace(); FunctionPtr zero = Function::zero(); bc->addDirichlet(uhat, boundary, zero); //////////////////// BUILD MESH /////////////////////// int H1Order = 3, pToAdd = 2; // define nodes for mesh FieldContainer<double> meshBoundary(4,2); meshBoundary(0,0) = 0.0; // x1 meshBoundary(0,1) = 0.0; // y1 meshBoundary(1,0) = 1.0; meshBoundary(1,1) = 0.0; meshBoundary(2,0) = 1.0; meshBoundary(2,1) = 1.0; meshBoundary(3,0) = 0.0; meshBoundary(3,1) = 1.0; int horizontalCells = 1, verticalCells = 1; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = MeshFactory::buildQuadMesh(meshBoundary, horizontalCells, verticalCells, bf, H1Order, H1Order+pToAdd, false); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); double energyThreshold = 0.2; // for mesh refinements RefinementStrategy refinementStrategy( solution, energyThreshold ); #ifdef USE_VTK VTKExporter exporter(solution, mesh, varFactory); #endif for (int refIndex=0; refIndex<=4; refIndex++) { solution->solve(false); #ifdef USE_VTK // output commented out because it's not properly part of the test. // stringstream outfile; // outfile << "test_" << refIndex; // exporter.exportSolution(outfile.str()); #endif if (refIndex < 4) refinementStrategy.refine(false); // don't print to console } return success; }
// tests Riesz inversion by integration by parts bool LinearTermTests::testRieszInversion() { bool success = true; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr tau = varFactory->testVar("\\tau", HDIV); VarPtr v = varFactory->testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory->traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_n = varFactory->fluxVar("\\widehat{\\beta \\cdot n u - \\sigma_{n}}"); VarPtr u = varFactory->fieldVar("u"); VarPtr sigma1 = varFactory->fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory->fieldVar("\\sigma_2"); vector<double> beta; beta.push_back(1.0); beta.push_back(0.0); double eps = .01; //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr confusionBF = Teuchos::rcp( new BF(varFactory) ); // tau terms: confusionBF->addTerm(sigma1 / eps, tau->x()); confusionBF->addTerm(sigma2 / eps, tau->y()); confusionBF->addTerm(u, tau->div()); confusionBF->addTerm(uhat, -tau->dot_normal()); // v terms: confusionBF->addTerm( sigma1, v->dx() ); confusionBF->addTerm( sigma2, v->dy() ); confusionBF->addTerm( -u, beta * v->grad() ); confusionBF->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int H1Order = 1; int pToAdd = 1; FieldContainer<double> quadPoints(4,2); quadPoints(0,0) = 0.0; // x1 quadPoints(0,1) = 0.0; // y1 quadPoints(1,0) = 1.0; quadPoints(1,1) = 0.0; quadPoints(2,0) = 1.0; quadPoints(2,1) = 1.0; quadPoints(3,0) = 0.0; quadPoints(3,1) = 1.0; int nCells = 1; int horizontalCells = nCells, verticalCells = nCells; // create a pointer to a new mesh: Teuchos::RCP<Mesh> myMesh = MeshFactory::buildQuadMesh(quadPoints, horizontalCells, verticalCells, confusionBF, H1Order, H1Order+pToAdd); ElementTypePtr elemType = myMesh->getElement(0)->elementType(); BasisCachePtr basisCache = Teuchos::rcp(new BasisCache(elemType, myMesh)); vector<GlobalIndexType> cellIDs; vector<ElementPtr> elems = myMesh->activeElements(); vector<ElementPtr>::iterator elemIt; for (elemIt=elems.begin(); elemIt!=elems.end(); elemIt++) { int cellID = (*elemIt)->cellID(); cellIDs.push_back(cellID); } bool createSideCacheToo = true; basisCache->setPhysicalCellNodes(myMesh->physicalCellNodesGlobal(elemType), cellIDs, createSideCacheToo); LinearTermPtr integrand = Teuchos::rcp(new LinearTerm);// residual LinearTermPtr integrandIBP = Teuchos::rcp(new LinearTerm);// residual vector<double> e1(2); // (1,0) vector<double> e2(2); // (0,1) e1[0] = 1; e2[1] = 1; FunctionPtr n = Function::normal(); FunctionPtr X = Function::xn(1); FunctionPtr Y = Function::yn(1); FunctionPtr testFxn1 = X; FunctionPtr testFxn2 = Y; FunctionPtr divTestFxn = testFxn1->dx() + testFxn2->dy(); FunctionPtr vectorTest = testFxn1*e1 + testFxn2*e2; integrand->addTerm(divTestFxn*v); integrandIBP->addTerm(vectorTest*n*v - vectorTest*v->grad()); // boundary term IPPtr sobolevIP = Teuchos::rcp(new IP); sobolevIP->addTerm(v); sobolevIP->addTerm(tau); Teuchos::RCP<RieszRep> riesz = Teuchos::rcp(new RieszRep(myMesh, sobolevIP, integrand)); // riesz->setPrintOption(true); riesz->computeRieszRep(); Teuchos::RCP<RieszRep> rieszIBP = Teuchos::rcp(new RieszRep(myMesh, sobolevIP, integrandIBP)); riesz->setFunctional(integrandIBP); // rieszIBP->setPrintOption(true); rieszIBP->computeRieszRep(); FunctionPtr rieszOrigFxn = RieszRep::repFunction(v,riesz); FunctionPtr rieszIBPFxn = RieszRep::repFunction(v,rieszIBP); int numCells = basisCache->getPhysicalCubaturePoints().dimension(0); int numPts = basisCache->getPhysicalCubaturePoints().dimension(1); FieldContainer<double> valOriginal( numCells, numPts); FieldContainer<double> valIBP( numCells, numPts); rieszOrigFxn->values(valOriginal,basisCache); rieszIBPFxn->values(valIBP,basisCache); double maxDiff; double tol = 1e-14; success = TestSuite::fcsAgree(valOriginal,valIBP,tol,maxDiff); if (success==false) { cout << "Failed TestRieszInversion with maxDiff = " << maxDiff << endl; } return success; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); Epetra_MpiComm Comm(MPI_COMM_WORLD); #else Epetra_SerialComm Comm; #endif int commRank = Teuchos::GlobalMPISession::getRank(); Comm.Barrier(); // set breakpoint here to allow debugger attachment to other MPI processes than the one you automatically attached to. Teuchos::CommandLineProcessor cmdp(false,true); // false: don't throw exceptions; true: do return errors for unrecognized options // problem parameters: double mu = 0.1; double permCoef = 1e4; int numRefs = 0; int k = 2, delta_k = 2; string norm = "Graph"; cmdp.setOption("polyOrder",&k,"polynomial order for field variable u"); cmdp.setOption("delta_k", &delta_k, "test space polynomial order enrichment"); cmdp.setOption("numRefs",&numRefs,"number of refinements"); cmdp.setOption("norm", &norm, "norm"); cmdp.setOption("mu", &mu, "mu"); cmdp.setOption("permCoef", &permCoef, "Permeability coefficient"); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { #ifdef HAVE_MPI MPI_Finalize(); #endif return -1; } FunctionPtr zero = TFunction<double>::zero(); FunctionPtr one = TFunction<double>::constant(1); FunctionPtr sin2pix = Teuchos::rcp( new Sin_ax(2*pi) ); FunctionPtr cos2pix = Teuchos::rcp( new Cos_ax(2*pi) ); FunctionPtr sin2piy = Teuchos::rcp( new Sin_ay(2*pi) ); FunctionPtr cos2piy = Teuchos::rcp( new Cos_ay(2*pi) ); FunctionPtr u1_exact = sin2pix*cos2piy; FunctionPtr u2_exact = -cos2pix*sin2piy; FunctionPtr x2 = TFunction<double>::xn(2); FunctionPtr y2 = TFunction<double>::yn(2); FunctionPtr p_exact = x2*y2 - 1./9; FunctionPtr permInv = permCoef*(sin2pix + 1.1); VarFactoryPtr vf = VarFactory::varFactory(); //fields: VarPtr sigma1 = vf->fieldVar("sigma1", VECTOR_L2); VarPtr sigma2 = vf->fieldVar("sigma2", VECTOR_L2); VarPtr u1 = vf->fieldVar("u1", L2); VarPtr u2 = vf->fieldVar("u2", L2); VarPtr p = vf->fieldVar("p", L2); // traces: VarPtr u1hat = vf->traceVar("u1hat"); VarPtr u2hat = vf->traceVar("u2hat"); VarPtr t1c = vf->fluxVar("t1c"); VarPtr t2c = vf->fluxVar("t2c"); // test: VarPtr v1 = vf->testVar("v1", HGRAD); VarPtr v2 = vf->testVar("v2", HGRAD); VarPtr tau1 = vf->testVar("tau1", HDIV); VarPtr tau2 = vf->testVar("tau2", HDIV); VarPtr q = vf->testVar("q", HGRAD); BFPtr bf = Teuchos::rcp( new BF(vf) ); bf->addTerm(1./mu*sigma1, tau1); bf->addTerm(1./mu*sigma2, tau2); bf->addTerm(u1, tau1->div()); bf->addTerm(u2, tau2->div()); bf->addTerm(-u1hat, tau1->dot_normal()); bf->addTerm(-u2hat, tau2->dot_normal()); bf->addTerm(sigma1, v1->grad()); bf->addTerm(sigma2, v2->grad()); bf->addTerm(-p, v1->dx()); bf->addTerm(-p, v2->dy()); bf->addTerm(t1c, v1); bf->addTerm(t2c, v2); bf->addTerm(mu*permInv*u1, v1); bf->addTerm(mu*permInv*u2, v2); bf->addTerm(-u1, q->dx()); bf->addTerm(-u2, q->dy()); bf->addTerm(u1hat, q->times_normal_x()); bf->addTerm(u2hat, q->times_normal_y()); RHSPtr rhs = RHS::rhs(); BCPtr bc = BC::bc(); SpatialFilterPtr y_equals_one = SpatialFilter::matchingY(1.0); SpatialFilterPtr y_equals_zero = SpatialFilter::matchingY(0); SpatialFilterPtr x_equals_one = SpatialFilter::matchingX(1.0); SpatialFilterPtr x_equals_zero = SpatialFilter::matchingX(0.0); bc->addDirichlet(u1hat, y_equals_zero, u1_exact); bc->addDirichlet(u2hat, y_equals_zero, u2_exact); bc->addDirichlet(u1hat, x_equals_zero, u1_exact); bc->addDirichlet(u2hat, x_equals_zero, u2_exact); bc->addDirichlet(u1hat, y_equals_one, u1_exact); bc->addDirichlet(u2hat, y_equals_one, u2_exact); bc->addDirichlet(u1hat, x_equals_one, u1_exact); bc->addDirichlet(u2hat, x_equals_one, u2_exact); bc->addZeroMeanConstraint(p); MeshPtr mesh = MeshFactory::quadMesh(bf, k+1, delta_k, 1, 1, 4, 4); map<string, IPPtr> brinkmanIPs; brinkmanIPs["Graph"] = bf->graphNorm(); brinkmanIPs["Decoupled"] = Teuchos::rcp(new IP); brinkmanIPs["Decoupled"]->addTerm(tau1); brinkmanIPs["Decoupled"]->addTerm(tau2); brinkmanIPs["Decoupled"]->addTerm(tau1->div()); brinkmanIPs["Decoupled"]->addTerm(tau2->div()); brinkmanIPs["Decoupled"]->addTerm(permInv*v1); brinkmanIPs["Decoupled"]->addTerm(permInv*v2); brinkmanIPs["Decoupled"]->addTerm(v1->grad()); brinkmanIPs["Decoupled"]->addTerm(v2->grad()); brinkmanIPs["Decoupled"]->addTerm(q); brinkmanIPs["Decoupled"]->addTerm(q->grad()); // brinkmanIPs["CoupledRobust"] = Teuchos::rcp(new IP); // brinkmanIPs["CoupledRobust"]->addTerm(tau->div()-beta*v->grad()); // brinkmanIPs["CoupledRobust"]->addTerm(Function<double>::min(one/Function<double>::h(),Function<double>::constant(1./sqrt(epsilon)))*tau); // brinkmanIPs["CoupledRobust"]->addTerm(sqrt(epsilon)*v->grad()); // brinkmanIPs["CoupledRobust"]->addTerm(beta*v->grad()); // brinkmanIPs["CoupledRobust"]->addTerm(Function<double>::min(sqrt(epsilon)*one/Function<double>::h(),one)*v); IPPtr ip = brinkmanIPs[norm]; SolutionPtr soln = TSolution<double>::solution(mesh, bc, rhs, ip); double threshold = 0.20; RefinementStrategy refStrategy(soln, threshold); ostringstream refName; refName << "brinkman"; HDF5Exporter exporter(mesh,refName.str()); for (int refIndex=0; refIndex <= numRefs; refIndex++) { soln->solve(false); double energyError = soln->energyErrorTotal(); if (commRank == 0) { // if (refIndex > 0) // refStrategy.printRefinementStatistics(refIndex-1); cout << "Refinement:\t " << refIndex << " \tElements:\t " << mesh->numActiveElements() << " \tDOFs:\t " << mesh->numGlobalDofs() << " \tEnergy Error:\t " << energyError << endl; } exporter.exportSolution(soln, refIndex); if (refIndex != numRefs) refStrategy.refine(); } return 0; }
PoissonFormulation::PoissonFormulation(int spaceDim, bool useConformingTraces, PoissonFormulationChoice formulationChoice) { _spaceDim = spaceDim; if (formulationChoice == ULTRAWEAK) { Space tauSpace = (spaceDim > 1) ? HDIV : HGRAD; Space phi_hat_space = useConformingTraces ? HGRAD : L2; Space psiSpace = (spaceDim > 1) ? VECTOR_L2 : L2; // fields VarPtr phi; VarPtr psi; // traces VarPtr phi_hat, psi_n_hat; // tests VarPtr q; VarPtr tau; VarFactoryPtr vf = VarFactory::varFactory(); phi = vf->fieldVar(S_PHI); psi = vf->fieldVar(S_PSI, psiSpace); TFunctionPtr<double> parity = TFunction<double>::sideParity(); if (spaceDim > 1) phi_hat = vf->traceVar(S_PHI_HAT, phi, phi_hat_space); else phi_hat = vf->fluxVar(S_PHI_HAT, phi * (Function::normal_1D() * parity), phi_hat_space); // for spaceDim==1, the "normal" component is in the flux-ness of phi_hat (it's a plus or minus 1) TFunctionPtr<double> n = TFunction<double>::normal(); if (spaceDim > 1) psi_n_hat = vf->fluxVar(S_PSI_N_HAT, psi * (n * parity)); else psi_n_hat = vf->fluxVar(S_PSI_N_HAT, psi * (Function::normal_1D() * parity)); q = vf->testVar(S_Q, HGRAD); tau = vf->testVar(S_TAU, tauSpace); _poissonBF = Teuchos::rcp( new BF(vf) ); if (spaceDim==1) { // for spaceDim==1, the "normal" component is in the flux-ness of phi_hat (it's a plus or minus 1) _poissonBF->addTerm(phi, tau->dx()); _poissonBF->addTerm(psi, tau); _poissonBF->addTerm(-phi_hat, tau); _poissonBF->addTerm(-psi, q->dx()); _poissonBF->addTerm(psi_n_hat, q); } else { _poissonBF->addTerm(phi, tau->div()); _poissonBF->addTerm(psi, tau); _poissonBF->addTerm(-phi_hat, tau->dot_normal()); _poissonBF->addTerm(-psi, q->grad()); _poissonBF->addTerm(psi_n_hat, q); } } else if ((formulationChoice == PRIMAL) || (formulationChoice == CONTINUOUS_GALERKIN)) { // field VarPtr phi; // flux VarPtr psi_n_hat; // tests VarPtr q; VarFactoryPtr vf = VarFactory::varFactory(); phi = vf->fieldVar(S_PHI, HGRAD); TFunctionPtr<double> parity = TFunction<double>::sideParity(); TFunctionPtr<double> n = TFunction<double>::normal(); if (formulationChoice == PRIMAL) { if (spaceDim > 1) psi_n_hat = vf->fluxVar(S_PSI_N_HAT, phi->grad() * (n * parity)); else psi_n_hat = vf->fluxVar(S_PSI_N_HAT, phi->dx() * (Function::normal_1D() * parity)); } q = vf->testVar(S_Q, HGRAD); _poissonBF = BF::bf(vf); _poissonBF->addTerm(-phi->grad(), q->grad()); if (formulationChoice == CONTINUOUS_GALERKIN) { FunctionPtr boundaryIndicator = Function::meshBoundaryCharacteristic(); _poissonBF->addTerm(phi->grad() * n, boundaryIndicator * q); } else // primal { _poissonBF->addTerm(psi_n_hat, q); } } else { TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "Unsupported PoissonFormulationChoice"); } }
int main(int argc, char *argv[]) { Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); int rank=mpiSession.getRank(); int numProcs=mpiSession.getNProc(); int spaceDim = 2; #ifdef HAVE_MPI choice::MpiArgs args( argc, argv ); #else choice::Args args(argc, argv ); #endif int minPolyOrder = args.Input<int>("--minPolyOrder", "L^2 (field) minimum polynomial order",0); int maxPolyOrder = args.Input<int>("--maxPolyOrder", "L^2 (field) maximum polynomial order",1); int minLogElements = args.Input<int>("--minLogElements", "base 2 log of the minimum number of elements in one mesh direction", 0); int maxLogElements = args.Input<int>("--maxLogElements", "base 2 log of the maximum number of elements in one mesh direction", 4); double Re = args.Input<double>("--Re", "Reynolds number", 40); // bool outputStiffnessMatrix = args.Input<bool>("--writeFinalStiffnessToDisk", "write the final stiffness matrix to disk.", false); bool computeMaxConditionNumber = args.Input<bool>("--computeMaxConditionNumber", "compute the maximum Gram matrix condition number for final mesh.", false); int maxIters = args.Input<int>("--maxIters", "maximum number of Newton-Raphson iterations to take to try to match tolerance", 50); double minL2Increment = args.Input<double>("--NRtol", "Newton-Raphson tolerance, L^2 norm of increment", 1e-12); string normChoice = args.Input<string>("--norm", "norm choice: graph, compliantGraph, stokesGraph, or stokesCompliantGraph", "graph"); bool useCondensedSolve = args.Input<bool>("--useCondensedSolve", "use static condensation", true); double dt = args.Input<double>("--timeStep", "time step (0 for none)", 0); double zmcRho = args.Input<double>("--zmcRho", "zero-mean constraint rho (stabilization parameter)", -1); // string replayFile = args.Input<string>("--replayFile", "file with refinement history to replay", ""); // string saveFile = args.Input<string>("--saveReplay", "file to which to save refinement history", ""); args.Process(); int pToAdd = 2; // for optimal test function approximation bool useLineSearch = false; bool computeRelativeErrors = true; // we'll say false when one of the exact solution components is 0 bool useEnrichedTraces = true; // enriched traces are the right choice, mathematically speaking BasisFactory::basisFactory()->setUseEnrichedTraces(useEnrichedTraces); // parse args: bool useTriangles = false, useGraphNorm = false, useCompliantNorm = false, useStokesCompliantNorm = false, useStokesGraphNorm = false; if (normChoice=="graph") { useGraphNorm = true; } else if (normChoice=="compliantGraph") { useCompliantNorm = true; } else if (normChoice=="stokesGraph") { useStokesGraphNorm = true; } else if (normChoice=="stokesCompliantGraph") { useStokesCompliantNorm = true; } else { if (rank==0) cout << "unknown norm choice. Exiting.\n"; exit(-1); } bool artificialTimeStepping = (dt > 0); if (rank == 0) { cout << "pToAdd = " << pToAdd << endl; cout << "useTriangles = " << (useTriangles ? "true" : "false") << "\n"; cout << "norm = " << normChoice << endl; } // define Kovasznay domain: FieldContainer<double> quadPointsKovasznay(4,2); // domain from Cockburn Kanschat for Stokes: quadPointsKovasznay(0,0) = -0.5; // x1 quadPointsKovasznay(0,1) = 0.0; // y1 quadPointsKovasznay(1,0) = 1.5; quadPointsKovasznay(1,1) = 0.0; quadPointsKovasznay(2,0) = 1.5; quadPointsKovasznay(2,1) = 2.0; quadPointsKovasznay(3,0) = -0.5; quadPointsKovasznay(3,1) = 2.0; // Domain from Evans Hughes for Navier-Stokes: // quadPointsKovasznay(0,0) = 0.0; // x1 // quadPointsKovasznay(0,1) = -0.5; // y1 // quadPointsKovasznay(1,0) = 1.0; // quadPointsKovasznay(1,1) = -0.5; // quadPointsKovasznay(2,0) = 1.0; // quadPointsKovasznay(2,1) = 0.5; // quadPointsKovasznay(3,0) = 0.0; // quadPointsKovasznay(3,1) = 0.5; // double Re = 10.0; // Cockburn Kanschat Stokes // double Re = 40.0; // Evans Hughes Navier-Stokes // double Re = 1000.0; string formulationTypeStr = "vgp"; FunctionPtr u1_exact, u2_exact, p_exact; int numCellsFineMesh = 20; // for computing a zero-mean pressure int H1OrderFineMesh = 5; // VGPNavierStokesProblem(double Re, Intrepid::FieldContainer<double> &quadPoints, int horizontalCells, // int verticalCells, int H1Order, int pToAdd, // TFunctionPtr<double> u1_0, TFunctionPtr<double> u2_0, TFunctionPtr<double> f1, TFunctionPtr<double> f2, // bool enrichVelocity = false, bool enhanceFluxes = false) FunctionPtr zero = Function::zero(); VGPNavierStokesProblem zeroProblem = VGPNavierStokesProblem(Re, quadPointsKovasznay, numCellsFineMesh, numCellsFineMesh, H1OrderFineMesh, pToAdd, zero, zero, zero, useCompliantNorm || useStokesCompliantNorm); VarFactoryPtr varFactory = VGPStokesFormulation::vgpVarFactory(); VarPtr u1_vgp = varFactory->fieldVar(VGP_U1_S); VarPtr u2_vgp = varFactory->fieldVar(VGP_U2_S); VarPtr sigma11_vgp = varFactory->fieldVar(VGP_SIGMA11_S); VarPtr sigma12_vgp = varFactory->fieldVar(VGP_SIGMA12_S); VarPtr sigma21_vgp = varFactory->fieldVar(VGP_SIGMA21_S); VarPtr sigma22_vgp = varFactory->fieldVar(VGP_SIGMA22_S); VarPtr p_vgp = varFactory->fieldVar(VGP_P_S); VarPtr v1_vgp = varFactory->testVar(VGP_V1_S, HGRAD); VarPtr v2_vgp = varFactory->testVar(VGP_V2_S, HGRAD); // if (rank==0) { // cout << "bilinear form with zero background flow:\n"; // zeroProblem.bf()->printTrialTestInteractions(); // } VGPStokesFormulation stokesForm(1/Re); NavierStokesFormulation::setKovasznay(Re, zeroProblem.mesh(), u1_exact, u2_exact, p_exact); // if (rank==0) cout << "Stokes bilinearForm: " << stokesForm.bf()->displayString() << endl; map< string, string > convergenceDataForMATLAB; // key: field file name for (int polyOrder = minPolyOrder; polyOrder <= maxPolyOrder; polyOrder++) { int H1Order = polyOrder + 1; int numCells1D = pow(2.0,minLogElements); if (rank==0) { cout << "L^2 order: " << polyOrder << endl; cout << "Re = " << Re << endl; } int kovasznayCubatureEnrichment = 20; // 20 is better than 10 for accurately measuring error on the coarser meshes. vector< VGPNavierStokesProblem > problems; do { VGPNavierStokesProblem problem = VGPNavierStokesProblem(Re,quadPointsKovasznay, numCells1D,numCells1D, H1Order, pToAdd, u1_exact, u2_exact, p_exact, useCompliantNorm || useStokesCompliantNorm); problem.backgroundFlow()->setCubatureEnrichmentDegree(kovasznayCubatureEnrichment); problem.solutionIncrement()->setCubatureEnrichmentDegree(kovasznayCubatureEnrichment); problem.backgroundFlow()->setZeroMeanConstraintRho(zmcRho); problem.solutionIncrement()->setZeroMeanConstraintRho(zmcRho); FunctionPtr dt_inv; if (artificialTimeStepping) { // // LHS gets u_inc / dt: BFPtr bf = problem.bf(); dt_inv = ParameterFunction::parameterFunction(1.0 / dt); //Teuchos::rcp( new ConstantScalarFunction(1.0 / dt, "\\frac{1}{dt}") ); bf->addTerm(-dt_inv * u1_vgp, v1_vgp); bf->addTerm(-dt_inv * u2_vgp, v2_vgp); problem.setIP( bf->graphNorm() ); // graph norm has changed... } else { dt_inv = Function::zero(); } problems.push_back(problem); if ( useCompliantNorm ) { problem.setIP(problem.vgpNavierStokesFormulation()->scaleCompliantGraphNorm(dt_inv)); } else if (useStokesCompliantNorm) { VGPStokesFormulation stokesForm(1.0); // pretend Re = 1 in the graph norm problem.setIP(stokesForm.scaleCompliantGraphNorm()); } else if (useStokesGraphNorm) { VGPStokesFormulation stokesForm(1.0); // pretend Re = 1 in the graph norm problem.setIP(stokesForm.graphNorm()); } else if (! useGraphNorm ) { // then use the naive: problem.setIP(problem.bf()->naiveNorm(spaceDim)); } if (rank==0) { cout << numCells1D << " x " << numCells1D << ": " << problem.mesh()->numGlobalDofs() << " dofs " << endl; } numCells1D *= 2; } while (pow(2.0,maxLogElements) >= numCells1D); // note that rhs and bilinearForm aren't really going to be right here, since they // involve a background flow which varies over the various problems... HConvergenceStudy study(problems[0].exactSolution(), problems[0].mesh()->bilinearForm(), problems[0].exactSolution()->rhs(), problems[0].backgroundFlow()->bc(), problems[0].bf()->graphNorm(), minLogElements, maxLogElements, H1Order, pToAdd, false, useTriangles, false); study.setReportRelativeErrors(computeRelativeErrors); study.setCubatureDegreeForExact(kovasznayCubatureEnrichment); vector< SolutionPtr > solutions; numCells1D = pow(2.0,minLogElements); for (vector< VGPNavierStokesProblem >::iterator problem = problems.begin(); problem != problems.end(); problem++) { SolutionPtr solnIncrement = problem->solutionIncrement(); FunctionPtr u1_incr = Function::solution(u1_vgp, solnIncrement); FunctionPtr u2_incr = Function::solution(u2_vgp, solnIncrement); FunctionPtr sigma11_incr = Function::solution(sigma11_vgp, solnIncrement); FunctionPtr sigma12_incr = Function::solution(sigma12_vgp, solnIncrement); FunctionPtr sigma21_incr = Function::solution(sigma21_vgp, solnIncrement); FunctionPtr sigma22_incr = Function::solution(sigma22_vgp, solnIncrement); FunctionPtr p_incr = Function::solution(p_vgp, solnIncrement); // LinearTermPtr rhsLT = problem->backgroundFlow()->rhs()->linearTerm(); // if (rank==0) cout << "bilinearForm: " << problems[0].mesh()->bilinearForm()->displayString() << endl; // if (rank==0) cout << "RHS: " << rhsLT->displayString() << endl; FunctionPtr l2_incr = u1_incr * u1_incr + u2_incr * u2_incr + p_incr * p_incr + sigma11_incr * sigma11_incr + sigma12_incr * sigma12_incr + sigma21_incr * sigma21_incr + sigma22_incr * sigma22_incr; double weight = 1.0; do { weight = problem->iterate(useLineSearch, useCondensedSolve); LinearTermPtr rhsLT = problem->backgroundFlow()->rhs()->linearTerm(); RieszRep rieszRep(problem->backgroundFlow()->mesh(), problem->backgroundFlow()->ip(), rhsLT); rieszRep.computeRieszRep(); double costFunction = rieszRep.getNorm(); double incr_norm = sqrt(l2_incr->integrate(problem->mesh())); if (rank==0) { cout << setprecision(6) << scientific; cout << "\x1B[2K"; // Erase the entire current line. cout << "\x1B[0E"; // Move to the beginning of the current line. cout << "Iteration: " << problem->iterationCount() << "; L^2(incr) = " << incr_norm; flush(cout); // cout << setprecision(6) << scientific; // cout << "Took " << weight << "-weighted step for " << numCells1D; // cout << " x " << numCells1D << " mesh: " << problem->iterationCount(); // cout << setprecision(6) << fixed; // cout << " iterations; cost function " << costFunction << endl; } } while ((sqrt(l2_incr->integrate(problem->mesh())) > minL2Increment ) && (problem->iterationCount() < maxIters) && (weight != 0)); if (rank==0) cout << endl; solutions.push_back( problem->backgroundFlow() ); // set the IP to the naive norm for clearer comparison with the best approximation energy error // problem->backgroundFlow()->setIP(problem->bf()->naiveNorm()); // double energyError = problem->backgroundFlow()->energyErrorTotal(); // if (rank==0) { // cout << setprecision(6) << fixed; // cout << numCells1D << " x " << numCells1D << ": " << problem->iterationCount(); // cout << " iterations; actual energy error " << energyError << endl; // } numCells1D *= 2; } study.setSolutions(solutions); for (int i=0; i<=maxLogElements-minLogElements; i++) { SolutionPtr bestApproximation = study.bestApproximations()[i]; VGPNavierStokesFormulation nsFormBest = VGPNavierStokesFormulation(Re, bestApproximation); SpatialFilterPtr entireBoundary = Teuchos::rcp( new SpatialFilterUnfiltered ); // SpatialFilterUnfiltered returns true everywhere Teuchos::RCP<ExactSolution<double>> exact = nsFormBest.exactSolution(u1_exact, u2_exact, p_exact, entireBoundary); // bestApproximation->setIP( nsFormBest.bf()->naiveNorm() ); // bestApproximation->setRHS( exact->rhs() ); // use backgroundFlow's IP so that they're comparable IPPtr ip = problems[i].backgroundFlow()->ip(); LinearTermPtr rhsLT = exact->rhs()->linearTerm(); RieszRep rieszRep(bestApproximation->mesh(), ip, rhsLT); rieszRep.computeRieszRep(); double bestCostFunction = rieszRep.getNorm(); if (rank==0) cout << "best energy error (measured according to the actual solution's test space IP): " << bestCostFunction << endl; } map< int, double > energyNormWeights; if (useCompliantNorm) { energyNormWeights[u1_vgp->ID()] = 1.0; // should be 1/h energyNormWeights[u2_vgp->ID()] = 1.0; // should be 1/h energyNormWeights[sigma11_vgp->ID()] = Re; // 1/mu energyNormWeights[sigma12_vgp->ID()] = Re; // 1/mu energyNormWeights[sigma21_vgp->ID()] = Re; // 1/mu energyNormWeights[sigma22_vgp->ID()] = Re; // 1/mu if (Re < 1) // assuming we're using the experimental small Re thing { energyNormWeights[p_vgp->ID()] = Re; } else { energyNormWeights[p_vgp->ID()] = 1.0; } } else { energyNormWeights[u1_vgp->ID()] = 1.0; energyNormWeights[u2_vgp->ID()] = 1.0; energyNormWeights[sigma11_vgp->ID()] = 1.0; energyNormWeights[sigma12_vgp->ID()] = 1.0; energyNormWeights[sigma21_vgp->ID()] = 1.0; energyNormWeights[sigma22_vgp->ID()] = 1.0; energyNormWeights[p_vgp->ID()] = 1.0; } vector<double> bestEnergy = study.weightedL2Error(energyNormWeights,true); vector<double> solnEnergy = study.weightedL2Error(energyNormWeights,false); map<int, double> velocityWeights; velocityWeights[u1_vgp->ID()] = 1.0; velocityWeights[u2_vgp->ID()] = 1.0; vector<double> bestVelocityError = study.weightedL2Error(velocityWeights,true); vector<double> solnVelocityError = study.weightedL2Error(velocityWeights,false); map<int, double> pressureWeight; pressureWeight[p_vgp->ID()] = 1.0; vector<double> bestPressureError = study.weightedL2Error(pressureWeight,true); vector<double> solnPressureError = study.weightedL2Error(pressureWeight,false); if (rank==0) { cout << setw(25); cout << "Solution Energy Error:" << setw(25) << "Best Energy Error:" << endl; cout << scientific << setprecision(1); for (int i=0; i<bestEnergy.size(); i++) { cout << setw(25) << solnEnergy[i] << setw(25) << bestEnergy[i] << endl; } cout << setw(25); cout << "Solution Velocity Error:" << setw(25) << "Best Velocity Error:" << endl; cout << scientific << setprecision(1); for (int i=0; i<bestEnergy.size(); i++) { cout << setw(25) << solnVelocityError[i] << setw(25) << bestVelocityError[i] << endl; } cout << setw(25); cout << "Solution Pressure Error:" << setw(25) << "Best Pressure Error:" << endl; cout << scientific << setprecision(1); for (int i=0; i<bestEnergy.size(); i++) { cout << setw(25) << solnPressureError[i] << setw(25) << bestPressureError[i] << endl; } vector< string > tableHeaders; vector< vector<double> > dataTable; vector< double > meshWidths; for (int i=minLogElements; i<=maxLogElements; i++) { double width = pow(2.0,i); meshWidths.push_back(width); } tableHeaders.push_back("mesh_width"); dataTable.push_back(meshWidths); tableHeaders.push_back("soln_energy_error"); dataTable.push_back(solnEnergy); tableHeaders.push_back("best_energy_error"); dataTable.push_back(bestEnergy); tableHeaders.push_back("soln_velocity_error"); dataTable.push_back(solnVelocityError); tableHeaders.push_back("best_velocity_error"); dataTable.push_back(bestVelocityError); tableHeaders.push_back("soln_pressure_error"); dataTable.push_back(solnPressureError); tableHeaders.push_back("best_pressure_error"); dataTable.push_back(bestPressureError); ostringstream fileNameStream; fileNameStream << "nsStudy_Re" << Re << "k" << polyOrder << "_results.dat"; DataIO::outputTableToFile(tableHeaders,dataTable,fileNameStream.str()); } if (rank == 0) { cout << study.TeXErrorRateTable(); vector<int> primaryVariables; stokesForm.primaryTrialIDs(primaryVariables); vector<int> fieldIDs,traceIDs; vector<string> fieldFileNames; stokesForm.trialIDs(fieldIDs,traceIDs,fieldFileNames); cout << "******** Best Approximation comparison: ********\n"; cout << study.TeXBestApproximationComparisonTable(primaryVariables); ostringstream filePathPrefix; filePathPrefix << "navierStokes/" << formulationTypeStr << "_p" << polyOrder << "_velpressure"; study.TeXBestApproximationComparisonTable(primaryVariables,filePathPrefix.str()); filePathPrefix.str(""); filePathPrefix << "navierStokes/" << formulationTypeStr << "_p" << polyOrder << "_all"; study.TeXBestApproximationComparisonTable(fieldIDs); for (int i=0; i<fieldIDs.size(); i++) { int fieldID = fieldIDs[i]; int traceID = traceIDs[i]; string fieldName = fieldFileNames[i]; ostringstream filePathPrefix; filePathPrefix << "navierStokes/" << fieldName << "_p" << polyOrder; bool writeMATLABplotData = false; study.writeToFiles(filePathPrefix.str(),fieldID,traceID, writeMATLABplotData); } for (int i=0; i<primaryVariables.size(); i++) { string convData = study.convergenceDataMATLAB(primaryVariables[i], minPolyOrder); cout << convData; convergenceDataForMATLAB[fieldFileNames[i]] += convData; } filePathPrefix.str(""); filePathPrefix << "navierStokes/" << formulationTypeStr << "_p" << polyOrder << "_numDofs"; cout << study.TeXNumGlobalDofsTable(); } if (computeMaxConditionNumber) { for (int i=minLogElements; i<=maxLogElements; i++) { SolutionPtr soln = study.getSolution(i); ostringstream fileNameStream; fileNameStream << "nsStudy_maxConditionIPMatrix_" << i << ".dat"; IPPtr ip = Teuchos::rcp( dynamic_cast< IP* >(soln->ip().get()), false ); bool jacobiScalingTrue = true; double maxConditionNumber = MeshUtilities::computeMaxLocalConditionNumber(ip, soln->mesh(), jacobiScalingTrue, fileNameStream.str()); if (rank==0) { cout << "max Gram matrix condition number estimate for logElements " << i << ": " << maxConditionNumber << endl; cout << "putative worst-conditioned Gram matrix written to: " << fileNameStream.str() << "." << endl; } } } } if (rank==0) { ostringstream filePathPrefix; filePathPrefix << "navierStokes/" << formulationTypeStr << "_"; for (map<string,string>::iterator convIt = convergenceDataForMATLAB.begin(); convIt != convergenceDataForMATLAB.end(); convIt++) { string fileName = convIt->first + ".m"; string data = convIt->second; fileName = filePathPrefix.str() + fileName; ofstream fout(fileName.c_str()); fout << data; fout.close(); } } }
void FunctionTests::setup() { //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr tau = varFactory->testVar("\\tau", HDIV); VarPtr v = varFactory->testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory->traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_n = varFactory->fluxVar("\\widehat{\\beta \\cdot n u - \\sigma_{n}}"); VarPtr u = varFactory->fieldVar("u"); VarPtr sigma1 = varFactory->fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory->fieldVar("\\sigma_2"); vector<double> beta_const; beta_const.push_back(2.0); beta_const.push_back(1.0); double eps = 1e-2; // standard confusion bilinear form _confusionBF = Teuchos::rcp( new BF(varFactory) ); // tau terms: _confusionBF->addTerm(sigma1 / eps, tau->x()); _confusionBF->addTerm(sigma2 / eps, tau->y()); _confusionBF->addTerm(u, tau->div()); _confusionBF->addTerm(-uhat, tau->dot_normal()); // v terms: _confusionBF->addTerm( sigma1, v->dx() ); _confusionBF->addTerm( sigma2, v->dy() ); _confusionBF->addTerm( beta_const * u, - v->grad() ); _confusionBF->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh FieldContainer<double> quadPoints(4,2); quadPoints(0,0) = -1.0; // x1 quadPoints(0,1) = -1.0; // y1 quadPoints(1,0) = 1.0; quadPoints(1,1) = -1.0; quadPoints(2,0) = 1.0; quadPoints(2,1) = 1.0; quadPoints(3,0) = -1.0; quadPoints(3,1) = 1.0; int H1Order = 1, pToAdd = 0; int horizontalCells = 1, verticalCells = 1; // create a pointer to a new mesh: _spectralConfusionMesh = MeshFactory::buildQuadMesh(quadPoints, horizontalCells, verticalCells, _confusionBF, H1Order, H1Order+pToAdd); // some 2D test points: // setup test points: static const int NUM_POINTS_1D = 10; double x[NUM_POINTS_1D] = {-1.0,-0.8,-0.6,-.4,-.2,0,0.2,0.4,0.6,0.8}; double y[NUM_POINTS_1D] = {-0.8,-0.6,-.4,-.2,0,0.2,0.4,0.6,0.8,1.0}; _testPoints = FieldContainer<double>(NUM_POINTS_1D*NUM_POINTS_1D,2); for (int i=0; i<NUM_POINTS_1D; i++) { for (int j=0; j<NUM_POINTS_1D; j++) { _testPoints(i*NUM_POINTS_1D + j, 0) = x[i]; _testPoints(i*NUM_POINTS_1D + j, 1) = y[j]; } } _elemType = _spectralConfusionMesh->getElementType(0); vector<GlobalIndexType> cellIDs; GlobalIndexType cellID = 0; cellIDs.push_back(cellID); _basisCache = Teuchos::rcp( new BasisCache( _elemType, _spectralConfusionMesh ) ); _basisCache->setRefCellPoints(_testPoints); _basisCache->setPhysicalCellNodes( _spectralConfusionMesh->physicalCellNodesForCell(cellID), cellIDs, true ); }
VarPtr PoissonFormulation::phi_hat() { VarFactoryPtr vf = _poissonBF->varFactory(); return vf->traceVar(S_PHI_HAT); }
// traces: VarPtr PoissonFormulation::psi_n_hat() { VarFactoryPtr vf = _poissonBF->varFactory(); return vf->fluxVar(S_PSI_N_HAT); }
VarPtr PoissonFormulation::psi() { VarFactoryPtr vf = _poissonBF->varFactory(); return vf->fieldVar(S_PSI); }
bool LinearTermTests::testRieszInversionAsProjection() { bool success = true; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr tau = varFactory->testVar("\\tau", HDIV); VarPtr v = varFactory->testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory->traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_n = varFactory->fluxVar("\\widehat{\\beta \\cdot n u - \\sigma_{n}}"); VarPtr u = varFactory->fieldVar("u"); VarPtr sigma1 = varFactory->fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory->fieldVar("\\sigma_2"); vector<double> beta; beta.push_back(1.0); beta.push_back(0.0); double eps = .01; //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr confusionBF = Teuchos::rcp( new BF(varFactory) ); // tau terms: confusionBF->addTerm(sigma1 / eps, tau->x()); confusionBF->addTerm(sigma2 / eps, tau->y()); confusionBF->addTerm(u, tau->div()); confusionBF->addTerm(uhat, -tau->dot_normal()); // v terms: confusionBF->addTerm( sigma1, v->dx() ); confusionBF->addTerm( sigma2, v->dy() ); confusionBF->addTerm( -u, beta * v->grad() ); confusionBF->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int H1Order = 2; int pToAdd = 2; FieldContainer<double> quadPoints(4,2); quadPoints(0,0) = 0.0; // x1 quadPoints(0,1) = 0.0; // y1 quadPoints(1,0) = 1.0; quadPoints(1,1) = 0.0; quadPoints(2,0) = 1.0; quadPoints(2,1) = 1.0; quadPoints(3,0) = 0.0; quadPoints(3,1) = 1.0; int nCells = 2; int horizontalCells = nCells, verticalCells = nCells; // create a new mesh: MeshPtr myMesh = MeshFactory::buildQuadMesh(quadPoints, horizontalCells, verticalCells, confusionBF, H1Order, H1Order+pToAdd); ElementTypePtr elemType = myMesh->getElement(0)->elementType(); BasisCachePtr basisCache = Teuchos::rcp(new BasisCache(elemType, myMesh)); vector<GlobalIndexType> cellIDs = myMesh->cellIDsOfTypeGlobal(elemType); bool createSideCacheToo = true; basisCache->setPhysicalCellNodes(myMesh->physicalCellNodesGlobal(elemType), cellIDs, createSideCacheToo); LinearTermPtr integrand = Teuchos::rcp(new LinearTerm); // residual FunctionPtr x = Function::xn(1); FunctionPtr y = Function::yn(1); FunctionPtr testFxn1 = x; FunctionPtr testFxn2 = y; FunctionPtr fxnToProject = x * y + 1.0; integrand->addTerm(fxnToProject * v); IPPtr ip_L2 = Teuchos::rcp(new IP); ip_L2->addTerm(v); ip_L2->addTerm(tau); Teuchos::RCP<RieszRep> riesz = Teuchos::rcp(new RieszRep(myMesh, ip_L2, integrand)); riesz->computeRieszRep(); FunctionPtr rieszFxn = RieszRep::repFunction(v,riesz); int numCells = basisCache->getPhysicalCubaturePoints().dimension(0); int numPts = basisCache->getPhysicalCubaturePoints().dimension(1); FieldContainer<double> valProject( numCells, numPts ); FieldContainer<double> valExpected( numCells, numPts ); rieszFxn->values(valProject,basisCache); fxnToProject->values(valExpected,basisCache); // int rank = Teuchos::GlobalMPISession::getRank(); // if (rank==0) cout << "physicalCubaturePoints:\n" << basisCache->getPhysicalCubaturePoints(); double maxDiff; double tol = 1e-12; success = TestSuite::fcsAgree(valProject,valExpected,tol,maxDiff); if (success==false) { cout << "Failed Riesz Inversion Projection test with maxDiff = " << maxDiff << endl; serializeOutput("valExpected", valExpected); serializeOutput("valProject", valProject); serializeOutput("physicalPoints", basisCache->getPhysicalCubaturePoints()); } return allSuccess(success); }
bool LinearTermTests::testMixedTermConsistency() { bool success = true; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr tau = varFactory->testVar("\\tau", HDIV); VarPtr v = varFactory->testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory->traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_n = varFactory->fluxVar("\\widehat{\\beta \\cdot n u - \\sigma_{n}}"); VarPtr u = varFactory->fieldVar("u"); VarPtr sigma1 = varFactory->fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory->fieldVar("\\sigma_2"); vector<double> beta; beta.push_back(1.0); beta.push_back(0.0); double eps = .01; //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr confusionBF = Teuchos::rcp( new BF(varFactory) ); // tau terms: confusionBF->addTerm(sigma1 / eps, tau->x()); confusionBF->addTerm(sigma2 / eps, tau->y()); confusionBF->addTerm(u, tau->div()); confusionBF->addTerm(uhat, -tau->dot_normal()); // v terms: confusionBF->addTerm( sigma1, v->dx() ); confusionBF->addTerm( sigma2, v->dy() ); confusionBF->addTerm( -u, beta * v->grad() ); confusionBF->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int H1Order = 1; int pToAdd = 1; FieldContainer<double> quadPoints(4,2); quadPoints(0,0) = 0.0; // x1 quadPoints(0,1) = 0.0; // y1 quadPoints(1,0) = 1.0; quadPoints(1,1) = 0.0; quadPoints(2,0) = 1.0; quadPoints(2,1) = 1.0; quadPoints(3,0) = 0.0; quadPoints(3,1) = 1.0; int nCells = 1; int horizontalCells = nCells, verticalCells = nCells; // create a pointer to a new mesh: Teuchos::RCP<Mesh> myMesh = MeshFactory::buildQuadMesh(quadPoints, horizontalCells, verticalCells, confusionBF, H1Order, H1Order+pToAdd); ElementTypePtr elemType = myMesh->getElement(0)->elementType(); // DofOrderingPtr testOrder = elemType->testOrderPtr; BasisCachePtr basisCache = Teuchos::rcp(new BasisCache(elemType, myMesh, true)); LinearTermPtr integrandIBP = Teuchos::rcp(new LinearTerm);// residual vector<double> e1(2); // (1,0) vector<double> e2(2); // (0,1) e1[0] = 1; e2[1] = 1; FunctionPtr n = Function::normal(); FunctionPtr X = Function::xn(1); FunctionPtr Y = Function::yn(1); FunctionPtr testFxn1 = X; FunctionPtr testFxn2 = Y; FunctionPtr divTestFxn = testFxn1->dx() + testFxn2->dy(); FunctionPtr vectorTest = testFxn1*e1 + testFxn2*e2; integrandIBP->addTerm(vectorTest*n*v + -vectorTest*v->grad()); // boundary term // define dummy IP to initialize riesz rep class, but just integrate RHS IPPtr dummyIP = Teuchos::rcp(new IP); dummyIP->addTerm(v); Teuchos::RCP<RieszRep> riesz = Teuchos::rcp(new RieszRep(myMesh, dummyIP, integrandIBP)); map<GlobalIndexType,FieldContainer<double> > rieszRHS = riesz->integrateFunctional(); set<GlobalIndexType> cellIDs = myMesh->cellIDsInPartition(); for (set<GlobalIndexType>::iterator cellIDIt=cellIDs.begin(); cellIDIt !=cellIDs.end(); cellIDIt++) { GlobalIndexType cellID = *cellIDIt; ElementTypePtr elemTypePtr = myMesh->getElementType(cellID); DofOrderingPtr testOrderingPtr = elemTypePtr->testOrderPtr; int numTestDofs = testOrderingPtr->totalDofs(); BasisCachePtr basisCache = BasisCache::basisCacheForCell(myMesh, cellID, true); FieldContainer<double> rhsIBPValues(1,numTestDofs); integrandIBP->integrate(rhsIBPValues, testOrderingPtr, basisCache); FieldContainer<double> rieszValues(1,numTestDofs); (riesz->getFunctional())->integrate(rieszValues, testOrderingPtr, basisCache); double maxDiff; double tol = 1e-13; FieldContainer<double> rhsIBPVals(numTestDofs); for (int i = 0; i< numTestDofs; i++) { rhsIBPVals(i) = rhsIBPValues(0,i); // cout << "riesz rhs values = " << rieszRHS[cellID](i) << ", rhsIBPValues = " << rhsIBPVals(i) << ", riesz returned values = " << rieszValues(0,i) << endl; } bool fcsAgree = TestSuite::fcsAgree(rieszRHS[cellID],rhsIBPVals,tol,maxDiff); if (!fcsAgree) { success=false; cout << "Failed mixed term consistency test with maxDiff = " << maxDiff << " on cellID " << cellID<< endl; } } return allSuccess(success); }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); #endif int commRank = Teuchos::GlobalMPISession::getRank(); int numProcs = Teuchos::GlobalMPISession::getNProc(); // { // // 1D tests // CellTopoPtrLegacy line_2 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Line<2> >() ) ); // // let's draw a line // vector<double> v0 = makeVertex(0); // vector<double> v1 = makeVertex(1); // vector<double> v2 = makeVertex(2); // vector< vector<double> > vertices; // vertices.push_back(v0); // vertices.push_back(v1); // vertices.push_back(v2); // vector<unsigned> line1VertexList; // vector<unsigned> line2VertexList; // line1VertexList.push_back(0); // line1VertexList.push_back(1); // line2VertexList.push_back(1); // line2VertexList.push_back(2); // vector< vector<unsigned> > elementVertices; // elementVertices.push_back(line1VertexList); // elementVertices.push_back(line2VertexList); // vector< CellTopoPtrLegacy > cellTopos; // cellTopos.push_back(line_2); // cellTopos.push_back(line_2); // MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); // MeshTopologyPtr meshTopology = Teuchos::rcp( new MeshTopology(meshGeometry) ); // FunctionPtr x = Function::xn(1); // FunctionPtr function = x; // FunctionPtr fbdr = Function::restrictToCellBoundary(function); // vector<FunctionPtr> functions; // functions.push_back(function); // functions.push_back(function); // vector<string> functionNames; // functionNames.push_back("function1"); // functionNames.push_back("function2"); // // { // // HDF5Exporter exporter(mesh, "function1", false); // // exporter.exportFunction(function, "function1"); // // } // // { // // HDF5Exporter exporter(mesh, "boundary1", false); // // exporter.exportFunction(fbdr, "boundary1"); // // } // // { // // HDF5Exporter exporter(mesh, "functions1", false); // // exporter.exportFunction(functions, functionNames); // // } // } { // 2D tests // CellTopoPtrLegacy quad_4 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >() ) ); // CellTopoPtrLegacy tri_3 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Triangle<3> >() ) ); CellTopoPtr quad_4 = CellTopology::quad(); CellTopoPtr tri_3 = CellTopology::triangle(); // let's draw a little house vector<double> v0 = makeVertex(-1,0); vector<double> v1 = makeVertex(1,0); vector<double> v2 = makeVertex(1,2); vector<double> v3 = makeVertex(-1,2); vector<double> v4 = makeVertex(0.0,3); vector< vector<double> > vertices; vertices.push_back(v0); vertices.push_back(v1); vertices.push_back(v2); vertices.push_back(v3); vertices.push_back(v4); vector<unsigned> quadVertexList; quadVertexList.push_back(0); quadVertexList.push_back(1); quadVertexList.push_back(2); quadVertexList.push_back(3); vector<unsigned> triVertexList; triVertexList.push_back(3); triVertexList.push_back(2); triVertexList.push_back(4); vector< vector<unsigned> > elementVertices; elementVertices.push_back(quadVertexList); elementVertices.push_back(triVertexList); // vector< CellTopoPtrLegacy > cellTopos; vector< CellTopoPtr> cellTopos; cellTopos.push_back(quad_4); cellTopos.push_back(tri_3); MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); MeshTopologyPtr meshTopology = Teuchos::rcp( new MeshTopology(meshGeometry) ); //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr vf = VarFactory::varFactory(); VarPtr tau = vf->testVar("tau", HDIV); VarPtr v = vf->testVar("v", HGRAD); // define trial variables VarPtr uhat = vf->traceVar("uhat"); VarPtr fhat = vf->fluxVar("fhat"); VarPtr u = vf->fieldVar("u"); VarPtr sigma = vf->fieldVar("sigma", VECTOR_L2); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr bf = Teuchos::rcp( new BF(vf) ); // tau terms: bf->addTerm(sigma, tau); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma, v->grad() ); bf->addTerm( fhat, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = bf->graphNorm(); //////////////////// SPECIFY RHS /////////////////////// RHSPtr rhs = RHS::rhs(); FunctionPtr one = Function::constant(1.0); rhs->addTerm( one * v ); //////////////////// CREATE BCs /////////////////////// BCPtr bc = BC::bc(); FunctionPtr zero = Function::zero(); SpatialFilterPtr entireBoundary = SpatialFilter::allSpace(); bc->addDirichlet(uhat, entireBoundary, zero); //////////////////// SOLVE & REFINE /////////////////////// // Output solution Intrepid::FieldContainer<GlobalIndexType> savedCellPartition; Teuchos::RCP<Epetra_FEVector> savedLHSVector; { //////////////////// BUILD MESH /////////////////////// int H1Order = 4, pToAdd = 2; Teuchos::RCP<Mesh> mesh = Teuchos::rcp( new Mesh (meshTopology, bf, H1Order, pToAdd) ); Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); solution->solve(false); RefinementStrategy refinementStrategy( solution, 0.2); HDF5Exporter exporter(mesh, "Poisson"); // exporter.exportSolution(solution, vf, 0, 2, cellIDToSubdivision(mesh, 4)); exporter.exportSolution(solution, 0, 2); mesh->saveToHDF5("MeshSave.h5"); solution->saveToHDF5("SolnSave.h5"); solution->save("PoissonProblem"); // int numRefs = 1; // for (int ref = 1; ref <= numRefs; ref++) // { // refinementStrategy.refine(commRank==0); // solution->solve(false); // mesh->saveToHDF5("MeshSave.h5"); // solution->saveToHDF5("SolnSave.h5"); // exporter.exportSolution(solution, vf, ref, 2, cellIDToSubdivision(mesh, 4)); // } mesh->globalDofAssignment()->getPartitions(savedCellPartition); savedLHSVector = solution->getLHSVector(); } { SolutionPtr loadedSolution = Solution::load(bf, "PoissonProblem"); HDF5Exporter exporter(loadedSolution->mesh(), "ProblemLoaded"); // exporter.exportSolution(loadedSolution, vf, 0, 2, cellIDToSubdivision(loadedSolution->mesh(), 4)); exporter.exportSolution(loadedSolution, 0, 2); } // { // MeshPtr loadedMesh = MeshFactory::loadFromHDF5(bf, "Test0.h5"); // Teuchos::RCP<Solution> loadedSolution = Teuchos::rcp( new Solution(loadedMesh, bc, rhs, ip) ); // loadedSolution->solve(false); // HDF5Exporter exporter(loadedMesh, "MeshLoaded"); // exporter.exportSolution(loadedSolution, vf, 0, 2, cellIDToSubdivision(loadedMesh, 4)); // } { MeshPtr loadedMesh = MeshFactory::loadFromHDF5(bf, "MeshSave.h5"); Intrepid::FieldContainer<GlobalIndexType> loadedCellPartition; loadedMesh->globalDofAssignment()->getPartitions(loadedCellPartition); if (loadedCellPartition.size() != savedCellPartition.size()) { cout << "Error: the loaded partition has different size/shape than the saved one.\n"; cout << "loaded size: " << loadedCellPartition.size() << "; saved size: " << savedCellPartition.size() << endl; } else { bool partitionsMatch = true; for (int i=0; i<loadedCellPartition.size(); i++) { if (loadedCellPartition[i] != savedCellPartition[i]) { partitionsMatch = false; break; } } if (partitionsMatch) cout << "Saved and loaded cell partitions match!\n"; else { cout << "Saved and loaded cell partitions differ.\n"; cout << "saved:\n" << savedCellPartition; cout << "loaded:\n" << loadedCellPartition; } } Teuchos::RCP<Solution> loadedSolution = Teuchos::rcp( new Solution(loadedMesh, bc, rhs, ip) ); loadedSolution->loadFromHDF5("SolnSave.h5"); Teuchos::RCP<Epetra_FEVector> loadedLHSVector = loadedSolution->getLHSVector(); if (loadedLHSVector->Map().MinLID() != savedLHSVector->Map().MinLID()) { cout << "On rank " << commRank << ", loaded min LID = " << loadedLHSVector->Map().MinLID(); cout << ", but saved min LID = " << savedLHSVector->Map().MinLID() << endl; } else if (loadedLHSVector->Map().MaxLID() != savedLHSVector->Map().MaxLID()) { cout << "On rank " << commRank << ", loaded max LID = " << loadedLHSVector->Map().MaxLID(); cout << ", but saved max LID = " << savedLHSVector->Map().MaxLID() << endl; } else { bool globalIDsMatch = true; for (int lid = loadedLHSVector->Map().MinLID(); lid <= loadedLHSVector->Map().MaxLID(); lid++) { if (loadedLHSVector->Map().GID(lid) != savedLHSVector->Map().GID(lid)) { globalIDsMatch = false; } } if (! globalIDsMatch) { cout << "On rank " << commRank << ", loaded and saved solution vector maps differ in their global IDs.\n"; } else { cout << "On rank " << commRank << ", loaded and saved solution vector maps match in their global IDs.\n"; } bool entriesMatch = true; double tol = 1e-16; if (loadedLHSVector->Map().MinLID() != loadedLHSVector->Map().MaxLID()) { for (int lid = loadedLHSVector->Map().MinLID(); lid <= loadedLHSVector->Map().MaxLID(); lid++) { double loadedValue = (*loadedLHSVector)[0][lid]; double savedValue = (*savedLHSVector)[0][lid]; double diff = abs( loadedValue - savedValue ); if (diff > tol) { entriesMatch = false; cout << "On rank " << commRank << ", loaded and saved solution vectors differ in entry with lid " << lid; cout << "; loaded value = " << loadedValue << "; saved value = " << savedValue << ".\n"; } } if (entriesMatch) { cout << "On rank " << commRank << ", loaded and saved solution vectors match!\n"; } else { cout << "On rank " << commRank << ", loaded and saved solution vectors do not match.\n"; } } } HDF5Exporter exporter(loadedMesh, "SolutionLoaded"); // exporter.exportSolution(loadedSolution, vf, 0, 2, cellIDToSubdivision(loadedMesh, 4)); exporter.exportSolution(loadedSolution, 0, 2); } } // { // // 3D tests // CellTopoPtrLegacy hex = Teuchos::rcp(new shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<8> >() )); // // let's draw a little box // vector<double> v0 = makeVertex(0,0,0); // vector<double> v1 = makeVertex(1,0,0); // vector<double> v2 = makeVertex(1,1,0); // vector<double> v3 = makeVertex(0,1,0); // vector<double> v4 = makeVertex(0,0,1); // vector<double> v5 = makeVertex(1,0,1); // vector<double> v6 = makeVertex(1,1,1); // vector<double> v7 = makeVertex(0,1,1); // vector< vector<double> > vertices; // vertices.push_back(v0); // vertices.push_back(v1); // vertices.push_back(v2); // vertices.push_back(v3); // vertices.push_back(v4); // vertices.push_back(v5); // vertices.push_back(v6); // vertices.push_back(v7); // vector<unsigned> hexVertexList; // hexVertexList.push_back(0); // hexVertexList.push_back(1); // hexVertexList.push_back(2); // hexVertexList.push_back(3); // hexVertexList.push_back(4); // hexVertexList.push_back(5); // hexVertexList.push_back(6); // hexVertexList.push_back(7); // // vector<unsigned> triVertexList; // // triVertexList.push_back(2); // // triVertexList.push_back(3); // // triVertexList.push_back(4); // vector< vector<unsigned> > elementVertices; // elementVertices.push_back(hexVertexList); // // elementVertices.push_back(triVertexList); // vector< CellTopoPtrLegacy > cellTopos; // cellTopos.push_back(hex); // // cellTopos.push_back(tri_3); // MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); // MeshTopologyPtr meshTopology = Teuchos::rcp( new MeshTopology(meshGeometry) ); // FunctionPtr x = Function::xn(1); // FunctionPtr y = Function::yn(1); // FunctionPtr z = Function::zn(1); // FunctionPtr function = x + y + z; // FunctionPtr fbdr = Function::restrictToCellBoundary(function); // FunctionPtr vect = Function::vectorize(x, y, z); // vector<FunctionPtr> functions; // functions.push_back(function); // functions.push_back(vect); // vector<string> functionNames; // functionNames.push_back("function"); // functionNames.push_back("vect"); // // { // // HDF5Exporter exporter(mesh, "function3", false); // // exporter.exportFunction(function, "function3"); // // } // // { // // HDF5Exporter exporter(mesh, "boundary3", false); // // exporter.exportFunction(fbdr, "boundary3"); // // } // // { // // HDF5Exporter exporter(mesh, "vect3", false); // // exporter.exportFunction(vect, "vect3"); // // } // // { // // HDF5Exporter exporter(mesh, "functions3", false); // // exporter.exportFunction(functions, functionNames); // // } // } }
// test variables: VarPtr PoissonFormulation::q() { VarFactoryPtr vf = _poissonBF->varFactory(); return vf->testVar(S_Q, HGRAD); }
bool FunctionTests::testValuesDottedWithTensor() { bool success = true; vector< FunctionPtr > vectorFxns; double xValue = 3, yValue = 4; FunctionPtr simpleVector = Function::vectorize(Function::constant(xValue), Function::constant(yValue)); vectorFxns.push_back(simpleVector); FunctionPtr x = Function::xn(1); FunctionPtr y = Function::yn(1); vectorFxns.push_back( Function::vectorize(x*x, x*y) ); VGPStokesFormulation vgpStokes = VGPStokesFormulation(1.0); BFPtr bf = vgpStokes.bf(); int h1Order = 1; MeshPtr mesh = MeshFactory::quadMesh(bf, h1Order); int cellID=0; // the only cell BasisCachePtr basisCache = BasisCache::basisCacheForCell(mesh, cellID); for (int i=0; i<vectorFxns.size(); i++) { FunctionPtr vectorFxn_i = vectorFxns[i]; for (int j=0; j<vectorFxns.size(); j++) { FunctionPtr vectorFxn_j = vectorFxns[j]; FunctionPtr dotProduct = vectorFxn_i * vectorFxn_j; FunctionPtr expectedDotProduct = vectorFxn_i->x() * vectorFxn_j->x() + vectorFxn_i->y() * vectorFxn_j->y(); if (! expectedDotProduct->equals(dotProduct, basisCache)) { cout << "testValuesDottedWithTensor() failed: expected dot product does not match dotProduct.\n"; success = false; double tol = 1e-14; reportFunctionValueDifferences(dotProduct, expectedDotProduct, basisCache, tol); } } } // now, let's try the same thing, but for a LinearTerm dot product VarFactoryPtr vf = VarFactory::varFactory(); VarPtr v = vf->testVar("v", HGRAD); DofOrderingPtr dofOrdering = Teuchos::rcp( new DofOrdering(CellTopology::quad()) ); shards::CellTopology quad_4(shards::getCellTopologyData<shards::Quadrilateral<4> >() ); BasisPtr basis = BasisFactory::basisFactory()->getBasis(h1Order, quad_4.getKey(), Camellia::FUNCTION_SPACE_HGRAD); dofOrdering->addEntry(v->ID(), basis, v->rank()); int numCells = 1; int numFields = basis->getCardinality(); for (int i=0; i<vectorFxns.size(); i++) { FunctionPtr f_i = vectorFxns[i]; LinearTermPtr lt_i = f_i * v; LinearTermPtr lt_i_x = f_i->x() * v; LinearTermPtr lt_i_y = f_i->y() * v; for (int j=0; j<vectorFxns.size(); j++) { FunctionPtr f_j = vectorFxns[j]; LinearTermPtr lt_j = f_j * v; LinearTermPtr lt_j_x = f_j->x() * v; LinearTermPtr lt_j_y = f_j->y() * v; FieldContainer<double> values(numCells,numFields,numFields); lt_i->integrate(values, dofOrdering, lt_j, dofOrdering, basisCache); FieldContainer<double> values_expected(numCells,numFields,numFields); lt_i_x->integrate(values_expected,dofOrdering,lt_j_x,dofOrdering,basisCache); lt_i_y->integrate(values_expected,dofOrdering,lt_j_y,dofOrdering,basisCache); double tol = 1e-14; double maxDiff = 0; if (!fcsAgree(values, values_expected, tol, maxDiff)) { cout << "FunctionTests::testValuesDottedWithTensor: "; cout << "dot product and sum of the products of scalar components differ by maxDiff " << maxDiff; cout << " in LinearTerm::integrate().\n"; success = false; } } } // // finally, let's try the same sort of thing, but now with a vector-valued basis // BasisPtr vectorBasisTemp = BasisFactory::basisFactory()->getBasis(h1Order, quad_4.getKey(), Camellia::FUNCTION_SPACE_VECTOR_HGRAD); // VectorBasisPtr vectorBasis = Teuchos::rcp( (VectorizedBasis<double, FieldContainer<double> > *)vectorBasisTemp.get(),false); // // BasisPtr compBasis = vectorBasis->getComponentBasis(); // // // create a new v, and a new dofOrdering // VarPtr v_vector = vf->testVar("v_vector", VECTOR_HGRAD); // dofOrdering = Teuchos::rcp( new DofOrdering ); // dofOrdering->addEntry(v_vector->ID(), vectorBasis, v_vector->rank()); // // DofOrderingPtr dofOrderingComp = Teuchos::rcp( new DofOrdering ); // dofOrderingComp->addEntry(v->ID(), compBasis, v->rank()); // return success; }