// builds a [0,1]x[0,1] square mesh with evenly spaced horizontal/vertical cells MeshPtr MeshUtilities::buildUnitQuadMesh(int horizontalCells, int verticalCells, Teuchos::RCP< BilinearForm > bilinearForm, int H1Order, int pTest){ FieldContainer<double> quadPoints(4,2); double squareSize = 1.0; quadPoints(0,0) = 0.0; // x1 quadPoints(0,1) = 0.0; // y1 quadPoints(1,0) = squareSize; quadPoints(1,1) = 0.0; quadPoints(2,0) = squareSize; quadPoints(2,1) = squareSize; quadPoints(3,0) = 0.0; quadPoints(3,1) = squareSize; // create a pointer to a new mesh: return MeshFactory::buildQuadMesh(quadPoints, horizontalCells, verticalCells, bilinearForm, H1Order, pTest); }
MeshTopologyPtr MeshTopologyTests::makeRectMesh(double x0, double y0, double width, double height, unsigned horizontalCells, unsigned verticalCells) { unsigned spaceDim = 2; Teuchos::RCP<MeshTopology> mesh = Teuchos::rcp( new MeshTopology(spaceDim) ); double dx = width / horizontalCells; double dy = height / verticalCells; CellTopoPtrLegacy quadTopo = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >() ) ); for (unsigned i=0; i<horizontalCells; i++) { double x = x0 + dx * i; for (unsigned j=0; j<verticalCells; j++) { double y = y0 + dy * j; vector< vector<double> > vertices = quadPoints(x, y, dx, dy); mesh->addCell(quadTopo, vertices); } } return mesh; }
// 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; }
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); }
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); }
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); }
void ElementTests::setup() { /********************************** _________________________________ | | | | | | | | | | 1 | 3 | | | | | | | | | | --------------------------------- | | | | | 7 | 6 | | | | | | |-------0-------| 2 | | | 11| 10| | | 4 |---5---| | | | 8 | 9 | | --------------------------------- in the code: _sw: 0 _nw: 1 _se: 2 _ne: 3 _sw_se: 5 _sw_ne: 6 _sw_se_se: 9 _sw_se_ne: 10 *********************************/ // first, build a simple mesh 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 = 2; int testOrder = H1Order; 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); _mesh = MeshFactory::buildQuadMesh(quadPoints, horizontalCells, verticalCells, confusionBF, H1Order, testOrder); // the right way to determine the southwest element, etc. is as follows: FieldContainer<double> points(4,2); // southwest center: points(0,0) = 0.25; points(0,1) = 0.25; // southeast center: points(1,0) = 0.75; points(1,1) = 0.25; // northwest center: points(2,0) = 0.25; points(2,1) = 0.75; // northeast center: points(3,0) = 0.75; points(3,1) = 0.75; vector<ElementPtr> elements = _mesh->elementsForPoints(points, false); _sw = elements[0]; // as presently implemented, cellID = 0 _se = elements[1]; // as presently implemented, cellID = 2 _nw = elements[2]; // as presently implemented, cellID = 1 _ne = elements[3]; // as presently implemented, cellID = 3 vector<GlobalIndexType> cellIDsToRefine; cellIDsToRefine.push_back(_sw->cellID()); _mesh->hRefine(cellIDsToRefine,RefinementPattern::regularRefinementPatternQuad()); // get the new elements; these are all within the original SW quadrant // southwest center: points(0,0) = 0.125; points(0,1) = 0.125; // southeast center: points(1,0) = 0.375; points(1,1) = 0.125; // northwest center: points(2,0) = 0.125; points(2,1) = 0.375; // northeast center: points(3,0) = 0.375; points(3,1) = 0.375; elements = _mesh->elementsForPoints(points, false); _sw_se = elements[1]; // as presently implemented, cellID = 5 _sw_ne = elements[3]; // as presently implemented, cellID = 6 cellIDsToRefine.clear(); cellIDsToRefine.push_back(_sw_se->cellID()); _mesh->hRefine(cellIDsToRefine,RefinementPattern::regularRefinementPatternQuad()); // get the new elements; these are all within the SE of the original SW quadrant // southwest center: points(0,0) = 0.31125; points(0,1) = 0.31125; // southeast center: points(1,0) = 0.4375; points(1,1) = 0.31125; // northwest center: points(2,0) = 0.31125; points(2,1) = 0.4375; // northeast center: points(3,0) = 0.4375; points(3,1) = 0.4375; elements = _mesh->elementsForPoints(points, false); _sw_se_se = elements[1]; // as presently implemented, cellID = 9 _sw_se_ne = elements[3]; // as presently implemented, cellID = 10 // setup test points: static const int NUM_POINTS_1D = 3; double x[NUM_POINTS_1D] = {-0.5,0.25,0.75}; _testPoints1D = FieldContainer<double>(NUM_POINTS_1D,1); for (int i=0; i<NUM_POINTS_1D; i++) { _testPoints1D(i, 0) = x[i]; } }
bool FunctionTests::testJumpIntegral() { bool success = true; double tol = 1e-14; // define nodes for mesh 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 = 1, pToAdd = 0; int horizontalCells = 2, verticalCells = 2; int numSides = 4; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = MeshFactory::buildQuadMesh(quadPoints, horizontalCells, verticalCells, _confusionBF, H1Order, H1Order+pToAdd); FieldContainer<double> points(1,2); // southwest center: points(0,0) = 0.25; points(0,1) = 0.25; vector< Teuchos::RCP<Element> > elements = mesh->elementsForPoints(points, false); int swCellID = elements[0]->cellID(); double val = 1.0; FunctionPtr valFxn = Function::constant(val); FunctionPtr valOnSWCell = Teuchos::rcp( new CellIDFilteredFunction(valFxn,swCellID) ); // the jump for this should be 1 along the two interior edges, each of length 0.5 double sideLength = 0.5; int cubEnrichment = 0; for (int sideIndex=0; sideIndex<numSides; sideIndex++) { double actualValue = valOnSWCell->integralOfJump(mesh, swCellID, sideIndex, cubEnrichment); double expectedValue; if (mesh->getTopology()->getCell(swCellID)->isBoundary(sideIndex)) { expectedValue = 0; } else { double sideParity = mesh->parityForSide(swCellID, sideIndex); expectedValue = sideParity * val * sideLength; } double diff = abs(actualValue-expectedValue); if (diff > tol) { cout << "testJumpFunction(): expected " << expectedValue << " but actualValue was " << actualValue << endl; success = false; } } return success; }
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 ); }
bool FunctionTests::testBasisSumFunction() { bool success = true; // on a single-element mesh, the BasisSumFunction should be identical to // the Solution with those coefficients // define a new mesh: more interesting if we're not on the ref cell int spaceDim = 2; FieldContainer<double> quadPoints(4,2); quadPoints(0,0) = 0.0; // x1 quadPoints(0,1) = 0.0; // y1 quadPoints(1,0) = 2.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 = 1, pToAdd = 0; int horizontalCells = 1, verticalCells = 1; // create a pointer to a new mesh: MeshPtr spectralConfusionMesh = MeshFactory::buildQuadMesh(quadPoints, horizontalCells, verticalCells, _confusionBF, H1Order, H1Order+pToAdd); BCPtr bc = BC::bc(); SolutionPtr soln = Teuchos::rcp( new Solution(spectralConfusionMesh, bc) ); soln->initializeLHSVector(); int cellID = 0; double tol = 1e-16; // overly restrictive, just for now. DofOrderingPtr trialSpace = spectralConfusionMesh->getElementType(cellID)->trialOrderPtr; set<int> trialIDs = trialSpace->getVarIDs(); BasisCachePtr volumeCache = BasisCache::basisCacheForCell(spectralConfusionMesh, cellID); for (set<int>::iterator trialIt=trialIDs.begin(); trialIt != trialIDs.end(); trialIt++) { int trialID = *trialIt; const vector<int>* sidesForVar = &trialSpace->getSidesForVarID(trialID); bool boundaryValued = sidesForVar->size() != 1; // note that for volume trialIDs, sideIndex = 0, and numSides = 1… for (vector<int>::const_iterator sideIt = sidesForVar->begin(); sideIt != sidesForVar->end(); sideIt++) { int sideIndex = *sideIt; BasisCachePtr sideCache = volumeCache->getSideBasisCache(sideIndex); BasisPtr basis = trialSpace->getBasis(trialID, sideIndex); int basisCardinality = basis->getCardinality(); for (int basisOrdinal = 0; basisOrdinal<basisCardinality; basisOrdinal++) { FieldContainer<double> basisCoefficients(basisCardinality); basisCoefficients(basisOrdinal) = 1.0; soln->setSolnCoeffsForCellID(basisCoefficients, cellID, trialID, sideIndex); VarPtr v = Var::varForTrialID(trialID, spectralConfusionMesh->bilinearForm()); FunctionPtr solnFxn = Function::solution(v, soln, false); FunctionPtr basisSumFxn = Teuchos::rcp( new BasisSumFunction(basis, basisCoefficients, Teuchos::rcp((BasisCache*)NULL), OP_VALUE, boundaryValued) ); if (!boundaryValued) { double l2diff = (solnFxn - basisSumFxn)->l2norm(spectralConfusionMesh); // cout << "l2diff = " << l2diff << endl; if (l2diff > tol) { success = false; cout << "testBasisSumFunction: l2diff of " << l2diff << " exceeds tol of " << tol << endl; cout << "l2norm of basisSumFxn: " << basisSumFxn->l2norm(spectralConfusionMesh) << endl; cout << "l2norm of solnFxn: " << solnFxn->l2norm(spectralConfusionMesh) << endl; } l2diff = (solnFxn->dx() - basisSumFxn->dx())->l2norm(spectralConfusionMesh); // cout << "l2diff = " << l2diff << endl; if (l2diff > tol) { success = false; cout << "testBasisSumFunction: l2diff of dx() " << l2diff << " exceeds tol of " << tol << endl; cout << "l2norm of basisSumFxn->dx(): " << basisSumFxn->dx()->l2norm(spectralConfusionMesh) << endl; cout << "l2norm of solnFxn->dx(): " << solnFxn->dx()->l2norm(spectralConfusionMesh) << endl; } // test that the restriction to a side works int numSides = volumeCache->cellTopology()->getSideCount(); for (int i=0; i<numSides; i++) { BasisCachePtr mySideCache = volumeCache->getSideBasisCache(i); if (! solnFxn->equals(basisSumFxn, mySideCache, tol)) { success = false; cout << "testBasisSumFunction: on side 0, l2diff of " << l2diff << " exceeds tol of " << tol << endl; reportFunctionValueDifferences(solnFxn, basisSumFxn, mySideCache, tol); } if (! solnFxn->grad(spaceDim)->equals(basisSumFxn->grad(spaceDim), mySideCache, tol)) { success = false; cout << "testBasisSumFunction: on side 0, l2diff of dx() " << l2diff << " exceeds tol of " << tol << endl; reportFunctionValueDifferences(solnFxn->grad(spaceDim), basisSumFxn->grad(spaceDim), mySideCache, tol); } } } else { FieldContainer<double> cellIntegral(1); // compute l2 diff of integral along the one side where we can legitimately assert equality: FunctionPtr diffFxn = solnFxn - basisSumFxn; (diffFxn*diffFxn)->integrate(cellIntegral, sideCache); double l2diff = sqrt(cellIntegral(0)); if (l2diff > tol) { success = false; cout << "testBasisSumFunction: on side " << sideIndex << ", l2diff of " << l2diff << " exceeds tol of " << tol << endl; int numCubPoints = sideCache->getPhysicalCubaturePoints().dimension(1); FieldContainer<double> solnFxnValues(1,numCubPoints); FieldContainer<double> basisFxnValues(1,numCubPoints); solnFxn->values(solnFxnValues, sideCache); basisSumFxn->values(basisFxnValues, sideCache); cout << "solnFxnValues:\n" << solnFxnValues; cout << "basisFxnValues:\n" << basisFxnValues; } else { // cout << "testBasisSumFunction: on side " << sideIndex << ", l2diff of " << l2diff << " is within tol of " << tol << endl; } } } } } return success; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); int rank=mpiSession.getRank(); int numProcs=mpiSession.getNProc(); #else int rank = 0; int numProcs = 1; #endif //////////////////// DECLARE VARIABLES /////////////////////// // define test variables 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; double c = sqrt(1.25); beta_const.push_back(1.0/c); beta_const.push_back(.5/c); // FunctionPtr beta = Teuchos::rcp(new Beta()); double eps = 1e-3; //////////////////// 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( beta_const * u, - v->grad() ); confusionBF->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// // quasi-optimal norm IPPtr qoptIP = Teuchos::rcp(new IP); qoptIP->addTerm( v ); qoptIP->addTerm( tau / eps + v->grad() ); qoptIP->addTerm( beta_const * v->grad() - tau->div() ); // robust test norm IPPtr robIP = Teuchos::rcp(new IP); FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(eps) ); if (enforceLocalConservation) { robIP->addZeroMeanTerm( v ); } else { robIP->addTerm( ip_scaling * v ); } robIP->addTerm( sqrt(eps) * v->grad() ); bool useNewBC = false; FunctionPtr weight = Teuchos::rcp( new SqrtWeight(eps) ); if (useNewBC) { robIP->addTerm( beta_const * v->grad() ); robIP->addTerm( tau->div() ); robIP->addTerm( ip_scaling/sqrt(eps) * tau ); } else { robIP->addTerm( weight * beta_const * v->grad() ); robIP->addTerm( weight * tau->div() ); robIP->addTerm( weight * ip_scaling/sqrt(eps) * tau ); } //////////////////// SPECIFY RHS /////////////////////// FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr f = zero; rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////// CREATE BCs /////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); SpatialFilterPtr inflowBoundary = Teuchos::rcp( new InflowSquareBoundary ); SpatialFilterPtr outflowBoundary = Teuchos::rcp( new OutflowSquareBoundary ); FunctionPtr u0 = Teuchos::rcp( new U0 ); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); bc->addDirichlet(uhat, outflowBoundary, zero); if (useNewBC) { bc->addDirichlet(beta_n_u_minus_sigma_n, inflowBoundary, beta_const*n*u0); } else { SpatialFilterPtr inflowBot = Teuchos::rcp( new InflowSquareBot ); SpatialFilterPtr inflowLeft = Teuchos::rcp( new InflowSquareLeft ); bc->addDirichlet(beta_n_u_minus_sigma_n, inflowLeft, beta_const*n*u0); bc->addDirichlet(uhat, inflowBot, u0); } // Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp(new PenaltyConstraints); // pc->addConstraint(uhat==u0,inflowBoundary); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int H1Order = 2, 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 pointer to a new mesh: Teuchos::RCP<Mesh> mesh = Mesh::buildQuadMesh(quadPoints, horizontalCells, verticalCells, confusionBF, H1Order, H1Order+pToAdd); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, robIP) ); // solution->setFilter(pc); if (enforceLocalConservation) { FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); solution->lagrangeConstraints()->addConstraint(beta_n_u_minus_sigma_n == zero); } double energyThreshold = 0.2; // for mesh refinements RefinementStrategy refinementStrategy( solution, energyThreshold ); int numRefs = 9; for (int refIndex=0; refIndex<numRefs; refIndex++) { solution->solve(false); refinementStrategy.refine(rank==0); // print to console on rank 0 } // one more solve on the final refined mesh: solution->solve(false); if (rank==0) { solution->writeToVTK("Hughes.vtu",min(H1Order+1,4)); solution->writeFluxesToFile(uhat->ID(), "uhat.dat"); cout << "wrote files: u.m, uhat.dat\n"; } return 0; }