double integralOverMesh(LinearTermPtr testTerm, VarPtr testVar, FunctionPtr fxnToSubstitute) { map<int, FunctionPtr > varAsFunction; varAsFunction[testVar->ID()] = fxnToSubstitute; FunctionPtr substituteOnBoundary = testTerm->evaluate(varAsFunction, true); FunctionPtr substituteOnInterior = testTerm->evaluate(varAsFunction, false); double integral = substituteOnBoundary->integrate(mesh); integral += substituteOnInterior->integrate(mesh); return integral; }
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 LinearTermTests::testBoundaryPlusVolumeTerms() { bool success = true; // notion is integration by parts: // (div f, v) = < f * n, v > - (f, grad v) // We perform two subtests for each test: first we try with a particular // function substituted for the variable. Second, we integrate over the // basis for the mesh (i.e. we test a whole bunch of functions, whose // precise definition is a bit complicated). // A third test is against the two-term LinearTerm::integrate() method. // This doesn't do integration by parts, but rather tests that // (u + u->dot_normal(), v) = (u,v) + (u->dot_normal(), v) ///////////// FIRST TEST //////////////// // start simply: define f to be (x, 0) // (div f, v) = (1, v) // < f * n, v > - (f, grad v) = < x n1, v > - ( x, v->dx() ) FunctionPtr x = Function::xn(1); FunctionPtr y = Function::yn(1); FunctionPtr x2 = Function::xn(2); FunctionPtr y2 = Function::yn(2); FunctionPtr x3 = Function::xn(3); FunctionPtr y3 = Function::yn(3); vector< FunctionPtr > f_fxns; f_fxns.push_back( Function::vectorize( x, Function::zero() ) ); // div of this = 1 f_fxns.push_back( Function::vectorize( x2 / 6.0, x2 * y / 2.0 ) ); // div of this = x / 3 + x^2 / 2 for ( vector< FunctionPtr >::iterator fIt = f_fxns.begin(); fIt != f_fxns.end(); fIt++) { FunctionPtr vector_fxn = *fIt; LinearTermPtr lt_v = vector_fxn->div()*v1; // part a: substitute v1 = x*y^2 FunctionPtr v1_value = x*y2; map< int, FunctionPtr > var_values; var_values[v1->ID()] = v1_value; double expectedValue = lt_v->evaluate(var_values, false)->integrate(mesh); FunctionPtr n = Function::normal(); LinearTermPtr ibp = vector_fxn * n * v1 - vector_fxn * v1->grad(); int numCells = basisCache->getPhysicalCubaturePoints().dimension(0); int numPoints = basisCache->getPhysicalCubaturePoints().dimension(1); int spaceDim = basisCache->getSpaceDim(); FieldContainer<double> vector_fxn_values(numCells,numPoints,spaceDim); vector_fxn->values(vector_fxn_values,basisCache); // cout << "vector_fxn values: \n" << vector_fxn_values; double boundaryIntegralSum = ibp->evaluate(var_values,true)->integrate(mesh); double volumeIntegralSum = ibp->evaluate(var_values,false)->integrate(mesh); double actualValue = boundaryIntegralSum + volumeIntegralSum; double tol = 1e-14; if (abs(expectedValue - actualValue)>tol) { success = false; } // part b: integrate the bases over each of the cells: int num_dofs = testOrder->totalDofs(); FieldContainer<double> integrals_expected( mesh->numActiveElements(), num_dofs ); FieldContainer<double> integrals_actual( mesh->numActiveElements(), num_dofs ); lt_v->integrate(integrals_expected,testOrder,basisCache); ibp->integrate(integrals_actual,testOrder,basisCache); double maxDiff = 0; if (! fcsAgree(integrals_actual, integrals_expected, tol, maxDiff) ) { cout << "LT integrated by parts does not agree with the original; maxDiff: " << maxDiff << endl; success = false; } // just on the odd chance that ordering makes a difference, repeat this test with the opposite order in ibp: ibp = - vector_fxn * v1->grad() + vector_fxn * n * v1; ibp->integrate(integrals_actual,testOrder,basisCache, false, false); maxDiff = 0; if (! fcsAgree(integrals_actual, integrals_expected, tol, maxDiff) ) { cout << "LT integrated by parts does not agree with the original; maxDiff: " << maxDiff << endl; success = false; } // part c: two-term integrals FieldContainer<double> integrals_expected_two_term( mesh->numActiveElements(), num_dofs, num_dofs); FieldContainer<double> integrals_actual_two_term( mesh->numActiveElements(), num_dofs, num_dofs ); LinearTermPtr ibp1 = vector_fxn * n * v1; LinearTermPtr ibp2 = - vector_fxn * v1->grad(); lt_v->integrate(integrals_expected_two_term, testOrder, ibp1 + ibp2, testOrder, basisCache, false, false); lt_v->integrate(integrals_actual_two_term, testOrder, ibp1, testOrder, basisCache, false, false); // don't forceBoundary, don't sumInto lt_v->integrate(integrals_actual_two_term, testOrder, ibp2, testOrder, basisCache, false, true); // DO sumInto maxDiff = 0; if (! fcsAgree(integrals_actual_two_term, integrals_expected_two_term, tol, maxDiff) ) { cout << "two-term integration is not bilinear; maxDiff: " << maxDiff << endl; success = false; } // now, same thing but with the roles of ibp{1|2} and lt_v reversed: (ibp1 + ibp2)->integrate(integrals_expected_two_term, testOrder, lt_v, testOrder, basisCache, false, false); ibp1->integrate(integrals_actual_two_term, testOrder, lt_v, testOrder, basisCache, false, false); // don't forceBoundary, don't sumInto ibp2->integrate(integrals_actual_two_term, testOrder, lt_v, testOrder, basisCache, false, true); // DO sumInto maxDiff = 0; if (! fcsAgree(integrals_actual_two_term, integrals_expected_two_term, tol, maxDiff) ) { cout << "two-term integration is not bilinear; maxDiff: " << maxDiff << endl; success = false; } // now, test that two-term integration commutes in the two terms: ibp1->integrate(integrals_expected_two_term, testOrder, lt_v, testOrder, basisCache, false, false); lt_v->integrate(integrals_actual_two_term, testOrder, ibp1, testOrder, basisCache, false, false); // we expect the integrals to commute up to a transpose, so let's transpose one of the containers: transposeFieldContainer(integrals_expected_two_term); maxDiff = 0; if (! fcsAgree(integrals_actual_two_term, integrals_expected_two_term, tol, maxDiff) ) { cout << "two-term integration does not commute for boundary value (ibp1); maxDiff: " << maxDiff << endl; success = false; } ibp2->integrate(integrals_expected_two_term, testOrder, lt_v, testOrder, basisCache, false, false); lt_v->integrate(integrals_actual_two_term, testOrder, ibp2, testOrder, basisCache, false, false); // we expect the integrals to commute up to a transpose, so let's transpose one of the containers: transposeFieldContainer(integrals_expected_two_term); maxDiff = 0; if (! fcsAgree(integrals_actual_two_term, integrals_expected_two_term, tol, maxDiff) ) { cout << "two-term integration does not commute for volume value (ibp2); maxDiff: " << maxDiff << endl; success = false; } // part d: to suss out where the integration failure happens in the non-commuting case: // 1. Substitute v1 = 1 in ibp2; get a function ibp2_at_v1_equals_one back. // 2. Substitute v1 = 1 in lt_v; get a function lt_v_at_v1_equals_one back. // 3. Integrate ibp2_at_v1_equals_one * lt_v_at_v1_equals_one over the mesh. Get a double result. // 4. Because basis is nodal, the representation for v1 = 1 is just all 1s for coefficients. // Therefore, the sum of the entries in the integrals_*_two_term matrices will should match // the function integral. Whichever doesn't match is wrong. // first, let's confirm that the v1 basis *is* nodal: BasisPtr v1Basis = testOrder->getBasis(v1->ID()); if (! v1Basis->isNodal()) { cout << "testBoundaryPlusVolumeTerms: final part of test relies on a nodal basis, but the basis is not nodal."; cout << " Exiting test early (with whatever success value we have thus far).\n"; return success; } map< int, FunctionPtr > v1_equals_one; v1_equals_one[v1->ID()] = Function::constant(1.0); FunctionPtr ibp1_at_v1_equals_one = ibp1->evaluate(v1_equals_one,true); // ibp1 has only a boundary term, so we just ask for this FunctionPtr ibp2_at_v1_equals_one = ibp2->evaluate(v1_equals_one,false); // ibp2 has no boundary terms, so we don't ask for these FunctionPtr lt_v_at_v1_equals_one = lt_v->evaluate(v1_equals_one,false); // lt_v also has no boundary terms if (ibp1_at_v1_equals_one->isZero()) { cout << "ibp1_at_v1_equals_one->isZero() = true.\n"; } if (lt_v_at_v1_equals_one->isZero()) { cout << "lt_v_at_v1_equals_one->isZero() = true.\n"; } FieldContainer<double> integrals_lt_v_first( mesh->numActiveElements(), num_dofs, num_dofs ); FieldContainer<double> integrals_ibp1_first( mesh->numActiveElements(), num_dofs, num_dofs ); FieldContainer<double> integrals_ibp2_first( mesh->numActiveElements(), num_dofs, num_dofs ); double lt_v_first_integral = 0.0, ibp1_first_integral = 0.0, ibp2_first_integral = 0.0; double integral = (ibp1_at_v1_equals_one * lt_v_at_v1_equals_one)->integrate(mesh); ibp1->integrate(integrals_ibp1_first, testOrder, lt_v, testOrder, basisCache, false, false); lt_v->integrate(integrals_lt_v_first, testOrder, ibp1, testOrder, basisCache, false, false); for (int i=0; i<integrals_lt_v_first.size(); i++) { lt_v_first_integral += integrals_lt_v_first[i]; ibp1_first_integral += integrals_ibp1_first[i]; } if (abs(lt_v_first_integral - integral) > tol) { double diff = abs(lt_v_first_integral - integral); success = false; cout << "Integral with v1=1 substituted does not match two-term integration of (lt_v,ibp1) with lt_v as this. diff = " << diff << "\n"; cout << "lt_v_first_integral = " << lt_v_first_integral << endl; cout << " (true) integral = " << integral << endl; } if (abs(ibp1_first_integral - integral) > tol) { double diff = abs(ibp1_first_integral - integral); success = false; cout << "Integral with v1=1 substituted does not match two-term integration of (lt_v,ibp1) with ibp1 as this. diff = " << diff << "\n"; cout << "ibp1_first_integral = " << ibp1_first_integral << endl; cout << " (true) integral = " << integral << endl; } // now, do the same but for ibp2 integral = (ibp2_at_v1_equals_one * lt_v_at_v1_equals_one)->integrate(mesh); ibp2->integrate(integrals_ibp2_first, testOrder, lt_v, testOrder, basisCache, false, false); lt_v->integrate(integrals_lt_v_first, testOrder, ibp2, testOrder, basisCache, false, false); // reset the sums: lt_v_first_integral = 0.0; ibp1_first_integral = 0.0; ibp2_first_integral = 0.0; for (int i=0; i<integrals_lt_v_first.size(); i++) { lt_v_first_integral += integrals_lt_v_first[i]; ibp2_first_integral += integrals_ibp2_first[i]; } if (abs(lt_v_first_integral - integral) > tol) { double diff = abs(lt_v_first_integral - integral); success = false; cout << "Integral with v1=1 substituted does not match two-term integration of (lt_v,ibp2) with lt_v as this. diff = " << diff << "\n"; cout << "lt_v_first_integral = " << lt_v_first_integral << endl; cout << " (true) integral = " << integral << endl; } if (abs(ibp2_first_integral - integral) > tol) { double diff = abs(ibp2_first_integral - integral); success = false; cout << "Integral with v1=1 substituted does not match two-term integration of (lt_v,ibp2) with ibp2 as this. diff = " << diff << "\n"; cout << "ibp1_first_integral = " << ibp1_first_integral << endl; cout << " (true) integral = " << integral << endl; } } return success; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); choice::MpiArgs args( argc, argv ); #else choice::Args args( argc, argv ); #endif int rank = Teuchos::GlobalMPISession::getRank(); int numProcs = Teuchos::GlobalMPISession::getNProc(); int nCells = args.Input<int>("--nCells", "num cells",2); int numRefs = args.Input<int>("--numRefs","num adaptive refinements",0); int numPreRefs = args.Input<int>("--numPreRefs","num preemptive adaptive refinements",0); int order = args.Input<int>("--order","order of approximation",2); double eps = args.Input<double>("--epsilon","diffusion parameter",1e-2); double energyThreshold = args.Input<double>("-energyThreshold","energy thresh for adaptivity", .5); double rampHeight = args.Input<double>("--rampHeight","ramp height at x = 2", 0.0); double ipSwitch = args.Input<double>("--ipSwitch","point at which to switch to graph norm", 0.0); // default to 0 to remain on robust norm bool useAnisotropy = args.Input<bool>("--useAnisotropy","aniso flag ", false); int H1Order = order+1; int pToAdd = args.Input<int>("--pToAdd","test space enrichment", 2); FunctionPtr zero = Function::constant(0.0); FunctionPtr one = Function::constant(1.0); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); vector<double> e1,e2; e1.push_back(1.0);e1.push_back(0.0); e2.push_back(0.0);e2.push_back(1.0); //////////////////// 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; beta.push_back(1.0); beta.push_back(0.0); //////////////////// 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); // first order term with magnitude alpha double alpha = 0.0; // confusionBF->addTerm(alpha * u, v); //////////////////// BUILD MESH /////////////////////// // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = MeshUtilities::buildUnitQuadMesh(nCells,confusionBF, H1Order, H1Order+pToAdd); mesh->setPartitionPolicy(Teuchos::rcp(new ZoltanMeshPartitionPolicy("HSFC"))); MeshInfo meshInfo(mesh); // gets info like cell measure, etc //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = Teuchos::rcp(new IP); /* // robust test norm FunctionPtr C_h = Teuchos::rcp( new EpsilonScaling(eps) ); FunctionPtr invH = Teuchos::rcp(new InvHScaling); FunctionPtr invSqrtH = Teuchos::rcp(new InvSqrtHScaling); FunctionPtr sqrtH = Teuchos::rcp(new SqrtHScaling); FunctionPtr hSwitch = Teuchos::rcp(new HSwitch(ipSwitch,mesh)); ip->addTerm(hSwitch*sqrt(eps) * v->grad() ); ip->addTerm(hSwitch*beta * v->grad() ); ip->addTerm(hSwitch*tau->div() ); // graph norm ip->addTerm( (one-hSwitch)*((1.0/eps) * tau + v->grad())); ip->addTerm( (one-hSwitch)*(beta * v->grad() - tau->div())); // regularizing terms ip->addTerm(C_h/sqrt(eps) * tau ); ip->addTerm(invSqrtH*v); */ // robust test norm IPPtr robIP = Teuchos::rcp(new IP); FunctionPtr C_h = Teuchos::rcp( new EpsilonScaling(eps) ); FunctionPtr invH = Teuchos::rcp(new InvHScaling); FunctionPtr invSqrtH = Teuchos::rcp(new InvSqrtHScaling); FunctionPtr sqrtH = Teuchos::rcp(new SqrtHScaling); FunctionPtr hSwitch = Teuchos::rcp(new HSwitch(ipSwitch,mesh)); robIP->addTerm(sqrt(eps) * v->grad() ); robIP->addTerm(beta * v->grad() ); robIP->addTerm(tau->div() ); // regularizing terms robIP->addTerm(C_h/sqrt(eps) * tau ); robIP->addTerm(invSqrtH*v); IPPtr graphIP = confusionBF->graphNorm(); graphIP->addTerm(invSqrtH*v); // graphIP->addTerm(C_h/sqrt(eps) * tau ); IPPtr switchIP = Teuchos::rcp(new IPSwitcher(robIP,graphIP,ipSwitch)); // rob IP for h>ipSwitch mesh size, graph norm o/w ip = switchIP; LinearTermPtr vVecLT = Teuchos::rcp(new LinearTerm); LinearTermPtr tauVecLT = Teuchos::rcp(new LinearTerm); vVecLT->addTerm(sqrt(eps)*v->grad()); tauVecLT->addTerm(C_h/sqrt(eps)*tau); LinearTermPtr restLT = Teuchos::rcp(new LinearTerm); restLT->addTerm(alpha*v); restLT->addTerm(invSqrtH*v); restLT = restLT + beta * v->grad(); restLT = restLT + tau->div(); //////////////////// SPECIFY RHS /////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr f = zero; // f = one; 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 Inflow = Teuchos::rcp(new LeftInflow); SpatialFilterPtr wallBoundary = Teuchos::rcp(new WallBoundary);//MeshUtilities::rampBoundary(rampHeight); SpatialFilterPtr freeStream = Teuchos::rcp(new FreeStreamBoundary); bc->addDirichlet(uhat, wallBoundary, one); // bc->addDirichlet(uhat, wallBoundary, Teuchos::rcp(new WallSmoothBC(eps))); bc->addDirichlet(beta_n_u_minus_sigma_n, Inflow, zero); bc->addDirichlet(beta_n_u_minus_sigma_n, freeStream, zero); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution; solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); BCPtr nullBC = Teuchos::rcp((BC*)NULL); RHSPtr nullRHS = Teuchos::rcp((RHS*)NULL); IPPtr nullIP = Teuchos::rcp((IP*)NULL); SolutionPtr backgroundFlow = Teuchos::rcp(new Solution(mesh, nullBC, nullRHS, nullIP) ); mesh->registerSolution(backgroundFlow); // to trigger issue with p-refinements map<int, Teuchos::RCP<Function> > functionMap; functionMap[u->ID()] = Function::constant(3.14); backgroundFlow->projectOntoMesh(functionMap); // lower p to p = 1 at SINGULARITY only vector<int> ids; /* for (int i = 0;i<mesh->numActiveElements();i++){ bool cellIDset = false; int cellID = mesh->activeElements()[i]->cellID(); int elemOrder = mesh->cellPolyOrder(cellID)-1; FieldContainer<double> vv(4,2); mesh->verticesForCell(vv, cellID); bool vertexOnWall = false; bool vertexAtSingularity = false; for (int j = 0;j<4;j++){ if ((abs(vv(j,0)-.5) + abs(vv(j,1)))<1e-10){ vertexAtSingularity = true; cellIDset = true; } } if (!vertexAtSingularity && elemOrder<2 && !cellIDset ){ ids.push_back(cellID); cout << "celliD = " << cellID << endl; } } */ ids.push_back(1); ids.push_back(3); mesh->pRefine(ids); // to put order = 1 return 0; LinearTermPtr residual = rhs->linearTermCopy(); residual->addTerm(-confusionBF->testFunctional(solution)); RieszRepPtr rieszResidual = Teuchos::rcp(new RieszRep(mesh, ip, residual)); rieszResidual->computeRieszRep(); FunctionPtr e_v = Teuchos::rcp(new RepFunction(v,rieszResidual)); FunctionPtr e_tau = Teuchos::rcp(new RepFunction(tau,rieszResidual)); map<int,FunctionPtr> errRepMap; errRepMap[v->ID()] = e_v; errRepMap[tau->ID()] = e_tau; FunctionPtr errTau = tauVecLT->evaluate(errRepMap,false); FunctionPtr errV = vVecLT->evaluate(errRepMap,false); FunctionPtr errRest = restLT->evaluate(errRepMap,false); FunctionPtr xErr = (errTau->x())*(errTau->x()) + (errV->dx())*(errV->dx()); FunctionPtr yErr = (errTau->y())*(errTau->y()) + (errV->dy())*(errV->dy()); FunctionPtr restErr = errRest*errRest; RefinementStrategy refinementStrategy( solution, energyThreshold ); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // PRE REFINEMENTS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if (rank==0){ cout << "Number of pre-refinements = " << numPreRefs << endl; } for (int i =0;i<=numPreRefs;i++){ vector<ElementPtr> elems = mesh->activeElements(); vector<ElementPtr>::iterator elemIt; vector<int> wallCells; for (elemIt=elems.begin();elemIt != elems.end();elemIt++){ int cellID = (*elemIt)->cellID(); int numSides = mesh->getElement(cellID)->numSides(); FieldContainer<double> vertices(numSides,2); //for quads mesh->verticesForCell(vertices, cellID); bool cellIDset = false; for (int j = 0;j<numSides;j++){ if ((abs(vertices(j,0)-.5)<1e-7) && (abs(vertices(j,1))<1e-7) && !cellIDset){ // if at singularity, i.e. if a vertex is (1,0) wallCells.push_back(cellID); cellIDset = true; } } } if (i<numPreRefs){ refinementStrategy.refineCells(wallCells); } } double minSideLength = meshInfo.getMinCellSideLength() ; double minCellMeasure = meshInfo.getMinCellMeasure() ; if (rank==0){ cout << "after prerefs, sqrt min cell measure = " << sqrt(minCellMeasure) << ", min side length = " << minSideLength << endl; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// VTKExporter exporter(solution, mesh, varFactory); for (int refIndex=0;refIndex<numRefs;refIndex++){ if (rank==0){ cout << "on ref index " << refIndex << endl; } rieszResidual->computeRieszRep(); // in preparation to get anisotropy vector<int> cellIDs; refinementStrategy.getCellsAboveErrorThreshhold(cellIDs); map<int,double> energyError = solution->energyError(); map<int,double> xErrMap = xErr->cellIntegrals(cellIDs,mesh,5,true); map<int,double> yErrMap = yErr->cellIntegrals(cellIDs,mesh,5,true); map<int,double> restErrMap = restErr->cellIntegrals(cellIDs,mesh,5,true); for (vector<ElementPtr>::iterator elemIt = mesh->activeElements().begin();elemIt!=mesh->activeElements().end();elemIt++){ int cellID = (*elemIt)->cellID(); double err = xErrMap[cellID]+ yErrMap[cellID] + restErrMap[cellID]; // if (rank==0) // cout << "err thru LT = " << sqrt(err) << ", while energy err = " << energyError[cellID] << endl; } /* map<int,double> ratio,xErr,yErr; vector<ElementPtr> elems = mesh->activeElements(); for (vector<ElementPtr>::iterator elemIt = elems.begin();elemIt!=elems.end();elemIt++){ int cellID = (*elemIt)->cellID(); ratio[cellID] = 0.0; xErr[cellID] = 0.0; yErr[cellID] = 0.0; if (std::find(cellIDs.begin(),cellIDs.end(),cellID)!=cellIDs.end()){ // if this cell is above energy thresh ratio[cellID] = yErrMap[cellID]/xErrMap[cellID]; xErr[cellID] = xErrMap[cellID]; yErr[cellID] = yErrMap[cellID]; } } FunctionPtr ratioFxn = Teuchos::rcp(new EnergyErrorFunction(ratio)); FunctionPtr xErrFxn = Teuchos::rcp(new EnergyErrorFunction(xErr)); FunctionPtr yErrFxn = Teuchos::rcp(new EnergyErrorFunction(yErr)); exporter.exportFunction(ratioFxn, string("ratio")+oss.str()); exporter.exportFunction(xErrFxn, string("xErr")+oss.str()); exporter.exportFunction(yErrFxn, string("yErr")+oss.str()); */ if (useAnisotropy){ refinementStrategy.refine(rank==0,xErrMap,yErrMap); //anisotropic refinements }else{ refinementStrategy.refine(rank==0); // no anisotropy } // lower p to p = 1 at SINGULARITY only vector<int> ids; for (int i = 0;i<mesh->numActiveElements();i++){ int cellID = mesh->activeElements()[i]->cellID(); int elemOrder = mesh->cellPolyOrder(cellID)-1; FieldContainer<double> vv(4,2); mesh->verticesForCell(vv, cellID); bool vertexOnWall = false; bool vertexAtSingularity = false; for (int j = 0;j<4;j++){ if ((abs(vv(j,0)-.5) + abs(vv(j,1)))<1e-10) vertexAtSingularity = true; } if (!vertexAtSingularity && elemOrder<2){ ids.push_back(cellID); } } mesh->pRefine(ids); // to put order = 1 /* if (elemOrder>1){ if (vertexAtSingularity){ vector<int> ids; ids.push_back(cellID); mesh->pRefine(ids,1-(elemOrder-1)); // to put order = 1 // mesh->pRefine(ids); // to put order = 1 if (rank==0) cout << "p unrefining elem with elemOrder = " << elemOrder << endl; } }else{ if (!vertexAtSingularity){ vector<int> ids; ids.push_back(cellID); mesh->pRefine(ids,2-elemOrder); } } */ double minSideLength = meshInfo.getMinCellSideLength() ; if (rank==0) cout << "minSideLength is " << minSideLength << endl; solution->condensedSolve(); std::ostringstream oss; oss << refIndex; } // final solve on final mesh solution->setWriteMatrixToFile(true,"K.mat"); solution->condensedSolve(); //////////////////////////////////////////////////////////////////////////////////////////////////////////// // CHECK CONDITIONING //////////////////////////////////////////////////////////////////////////////////////////////////////////// bool checkConditioning = true; if (checkConditioning){ double minSideLength = meshInfo.getMinCellSideLength() ; StandardAssembler assembler(solution); double maxCond = 0.0; int maxCellID = 0; for (int i = 0;i<mesh->numActiveElements();i++){ int cellID = mesh->getActiveElement(i)->cellID(); FieldContainer<double> ipMat = assembler.getIPMatrix(mesh->getElement(cellID)); double cond = SerialDenseWrapper::getMatrixConditionNumber(ipMat); if (cond>maxCond){ maxCond = cond; maxCellID = cellID; } } if (rank==0){ cout << "cell ID " << maxCellID << " has minCellLength " << minSideLength << " and condition estimate " << maxCond << endl; } string ipMatName = string("ipMat.mat"); ElementPtr maxCondElem = mesh->getElement(maxCellID); FieldContainer<double> ipMat = assembler.getIPMatrix(maxCondElem); SerialDenseWrapper::writeMatrixToMatlabFile(ipMatName,ipMat); } //////////////////// print to file /////////////////////// if (rank==0){ exporter.exportSolution(string("robustIP")); cout << endl; } return 0; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); choice::MpiArgs args( argc, argv ); #else choice::Args args( argc, argv ); #endif int rank = Teuchos::GlobalMPISession::getRank(); int numProcs = Teuchos::GlobalMPISession::getNProc(); int nCells = args.Input<int>("--nCells", "num cells",2); int numRefs = args.Input<int>("--numRefs","num adaptive refinements",0); int numPreRefs = args.Input<int>("--numPreRefs","num preemptive adaptive refinements",0); int order = args.Input<int>("--order","order of approximation",2); double eps = args.Input<double>("--epsilon","diffusion parameter",1e-2); double energyThreshold = args.Input<double>("-energyThreshold","energy thresh for adaptivity", .5); double rampHeight = args.Input<double>("--rampHeight","ramp height at x = 2", 0.0); bool useAnisotropy = args.Input<bool>("--useAnisotropy","aniso flag ", false); FunctionPtr zero = Function::constant(0.0); FunctionPtr one = Function::constant(1.0); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); vector<double> e1,e2; e1.push_back(1.0); e1.push_back(0.0); e2.push_back(0.0); e2.push_back(1.0); //////////////////// 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; beta.push_back(1.0); beta.push_back(0.0); //////////////////// 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); // first order term with magnitude alpha double alpha = 0.0; confusionBF->addTerm(alpha * u, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// // robust test norm IPPtr robIP = Teuchos::rcp(new IP); FunctionPtr C_h = Teuchos::rcp( new EpsilonScaling(eps) ); FunctionPtr invH = Teuchos::rcp(new InvHScaling); FunctionPtr invSqrtH = Teuchos::rcp(new InvSqrtHScaling); FunctionPtr sqrtH = Teuchos::rcp(new SqrtHScaling); robIP->addTerm(v*alpha); robIP->addTerm(invSqrtH*v); // robIP->addTerm(v); robIP->addTerm(sqrt(eps) * v->grad() ); robIP->addTerm(beta * v->grad() ); robIP->addTerm(tau->div() ); robIP->addTerm(C_h/sqrt(eps) * tau ); LinearTermPtr vVecLT = Teuchos::rcp(new LinearTerm); LinearTermPtr tauVecLT = Teuchos::rcp(new LinearTerm); vVecLT->addTerm(sqrt(eps)*v->grad()); tauVecLT->addTerm(C_h/sqrt(eps)*tau); LinearTermPtr restLT = Teuchos::rcp(new LinearTerm); restLT->addTerm(alpha*v); restLT->addTerm(invSqrtH*v); restLT = restLT + beta * v->grad(); restLT = restLT + tau->div(); //////////////////// SPECIFY RHS /////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr f = zero; // f = one; 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); // bc->addDirichlet(beta_n_u_minus_sigma_n, inflowBoundary, zero); // bc->addDirichlet(uhat, outflowBoundary, zero); SpatialFilterPtr rampInflow = Teuchos::rcp(new LeftInflow); SpatialFilterPtr rampBoundary = MeshUtilities::rampBoundary(rampHeight); SpatialFilterPtr freeStream = Teuchos::rcp(new FreeStreamBoundary); SpatialFilterPtr outflowBoundary = Teuchos::rcp(new OutflowBoundary); bc->addDirichlet(uhat, rampBoundary, one); // bc->addDirichlet(uhat, outflowBoundary, one); bc->addDirichlet(beta_n_u_minus_sigma_n, rampInflow, zero); bc->addDirichlet(beta_n_u_minus_sigma_n, freeStream, zero); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int H1Order = order+1; int pToAdd = 2; // create a pointer to a new mesh: // Teuchos::RCP<Mesh> mesh = MeshUtilities::buildUnitQuadMesh(nCells,confusionBF, H1Order, H1Order+pToAdd); Teuchos::RCP<Mesh> mesh = MeshUtilities::buildRampMesh(rampHeight,confusionBF, H1Order, H1Order+pToAdd); mesh->setPartitionPolicy(Teuchos::rcp(new ZoltanMeshPartitionPolicy("HSFC"))); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution; solution = Teuchos::rcp( new Solution(mesh, bc, rhs, robIP) ); // solution->solve(false); solution->condensedSolve(); LinearTermPtr residual = rhs->linearTermCopy(); residual->addTerm(-confusionBF->testFunctional(solution)); RieszRepPtr rieszResidual = Teuchos::rcp(new RieszRep(mesh, robIP, residual)); rieszResidual->computeRieszRep(); FunctionPtr e_v = Teuchos::rcp(new RepFunction(v,rieszResidual)); FunctionPtr e_tau = Teuchos::rcp(new RepFunction(tau,rieszResidual)); map<int,FunctionPtr> errRepMap; errRepMap[v->ID()] = e_v; errRepMap[tau->ID()] = e_tau; FunctionPtr errTau = tauVecLT->evaluate(errRepMap,false); FunctionPtr errV = vVecLT->evaluate(errRepMap,false); FunctionPtr errRest = restLT->evaluate(errRepMap,false); FunctionPtr xErr = (errTau->x())*(errTau->x()) + (errV->dx())*(errV->dx()); FunctionPtr yErr = (errTau->y())*(errTau->y()) + (errV->dy())*(errV->dy()); FunctionPtr restErr = errRest*errRest; RefinementStrategy refinementStrategy( solution, energyThreshold ); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // PRE REFINEMENTS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if (rank==0) { cout << "Number of pre-refinements = " << numPreRefs << endl; } for (int i =0; i<=numPreRefs; i++) { vector<ElementPtr> elems = mesh->activeElements(); vector<ElementPtr>::iterator elemIt; vector<int> wallCells; for (elemIt=elems.begin(); elemIt != elems.end(); elemIt++) { int cellID = (*elemIt)->cellID(); int numSides = mesh->getElement(cellID)->numSides(); FieldContainer<double> vertices(numSides,2); //for quads mesh->verticesForCell(vertices, cellID); bool cellIDset = false; for (int j = 0; j<numSides; j++) { if ((abs(vertices(j,0)-1.0)<1e-7) && (abs(vertices(j,1))<1e-7) && !cellIDset) // if at singularity, i.e. if a vertex is (1,0) { wallCells.push_back(cellID); cellIDset = true; } } } if (i<numPreRefs) { refinementStrategy.refineCells(wallCells); } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// VTKExporter exporter(solution, mesh, varFactory); for (int refIndex=0; refIndex<numRefs; refIndex++) { if (rank==0) { cout << "on ref index " << refIndex << endl; } rieszResidual->computeRieszRep(); // in preparation to get anisotropy vector<int> cellIDs; refinementStrategy.getCellsAboveErrorThreshhold(cellIDs); map<int,double> energyError = solution->energyError(); map<int,double> xErrMap = xErr->cellIntegrals(cellIDs,mesh,5,true); map<int,double> yErrMap = yErr->cellIntegrals(cellIDs,mesh,5,true); map<int,double> restErrMap = restErr->cellIntegrals(cellIDs,mesh,5,true); for (vector<ElementPtr>::iterator elemIt = mesh->activeElements().begin(); elemIt!=mesh->activeElements().end(); elemIt++) { int cellID = (*elemIt)->cellID(); double err = xErrMap[cellID]+ yErrMap[cellID] + restErrMap[cellID]; if (rank==0) cout << "err thru LT = " << sqrt(err) << ", while energy err = " << energyError[cellID] << endl; } map<int,double> ratio,xErr,yErr; vector<ElementPtr> elems = mesh->activeElements(); for (vector<ElementPtr>::iterator elemIt = elems.begin(); elemIt!=elems.end(); elemIt++) { int cellID = (*elemIt)->cellID(); ratio[cellID] = 0.0; xErr[cellID] = 0.0; yErr[cellID] = 0.0; if (std::find(cellIDs.begin(),cellIDs.end(),cellID)!=cellIDs.end()) // if this cell is above energy thresh { ratio[cellID] = yErrMap[cellID]/xErrMap[cellID]; xErr[cellID] = xErrMap[cellID]; yErr[cellID] = yErrMap[cellID]; } } FunctionPtr ratioFxn = Teuchos::rcp(new EnergyErrorFunction(ratio)); FunctionPtr xErrFxn = Teuchos::rcp(new EnergyErrorFunction(xErr)); FunctionPtr yErrFxn = Teuchos::rcp(new EnergyErrorFunction(yErr)); std::ostringstream oss; oss << refIndex; exporter.exportFunction(ratioFxn, string("ratio")+oss.str()); exporter.exportFunction(xErrFxn, string("xErr")+oss.str()); exporter.exportFunction(yErrFxn, string("yErr")+oss.str()); if (useAnisotropy) { refinementStrategy.refine(rank==0,xErrMap,yErrMap); //anisotropic refinements } else { refinementStrategy.refine(rank==0); // no anisotropy } solution->condensedSolve(); } // final solve on final mesh solution->condensedSolve(); //////////////////// print to file /////////////////////// FunctionPtr orderFxn = Teuchos::rcp(new MeshPolyOrderFunction(mesh)); std::ostringstream oss; oss << nCells; if (rank==0) { exporter.exportSolution(string("robustIP")+oss.str()); exporter.exportFunction(orderFxn, "meshOrder"); cout << endl; } return 0; }
// tests to make sure that the rieszNorm computed via matrices is the same as the one computed thru direct integration bool ScratchPadTests::testRieszIntegration() { double tol = 1e-11; bool success = true; int nCells = 2; double eps = .25; //////////////////// 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); //////////////////// 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); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// // robust test norm IPPtr ip = Teuchos::rcp(new IP); // just H1 projection ip->addTerm(v->grad()); ip->addTerm(v); ip->addTerm(tau); ip->addTerm(tau->div()); //////////////////// SPECIFY RHS AND HELPFUL FUNCTIONS /////////////////////// FunctionPtr n = Function::normal(); vector<double> e1,e2; e1.push_back(1.0); e1.push_back(0.0); e2.push_back(0.0); e2.push_back(1.0); FunctionPtr one = Function::constant(1.0); FunctionPtr zero = Function::constant(0.0); RHSPtr rhs = RHS::rhs(); FunctionPtr f = one; rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////// CREATE BCs /////////////////////// BCPtr bc = BC::bc(); SpatialFilterPtr squareBoundary = Teuchos::rcp( new SquareBoundary ); bc->addDirichlet(uhat, squareBoundary, zero); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int order = 2; int H1Order = order+1; int pToAdd = 2; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = MeshUtilities::buildUnitQuadMesh(nCells,confusionBF, H1Order, H1Order+pToAdd); //////////////////// SOLVE & REFINE /////////////////////// LinearTermPtr lt = Teuchos::rcp(new LinearTerm); FunctionPtr fxn = Function::xn(1); // fxn = x lt->addTerm(fxn*v + fxn->grad()*v->grad()); lt->addTerm(fxn*tau->x() + fxn*tau->y() + (fxn->dx() + fxn->dy())*tau->div()); Teuchos::RCP<RieszRep> rieszLT = Teuchos::rcp(new RieszRep(mesh, ip, lt)); rieszLT->computeRieszRep(); double rieszNorm = rieszLT->getNorm(); FunctionPtr e_v = RieszRep::repFunction(v,rieszLT); FunctionPtr e_tau = RieszRep::repFunction(tau,rieszLT); map<int,FunctionPtr> repFxns; repFxns[v->ID()] = e_v; repFxns[tau->ID()] = e_tau; double integratedNorm = sqrt((lt->evaluate(repFxns,false))->integrate(mesh,5,true)); success = abs(rieszNorm-integratedNorm)<tol; if (success==false) { cout << "Failed testRieszIntegration; riesz norm is computed to be = " << rieszNorm << ", while using integration it's computed to be " << integratedNorm << endl; return success; } return success; }
// tests whether a mixed type LT bool ScratchPadTests::testIntegrateDiscontinuousFunction() { bool success = true; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr v = varFactory->testVar("v", HGRAD); vector<double> beta; beta.push_back(1.0); beta.push_back(1.0); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// // robust test norm IPPtr ip = Teuchos::rcp(new IP); ip->addTerm(v); ip->addTerm(beta*v->grad()); // for projections IPPtr ipL2 = Teuchos::rcp(new IP); ipL2->addTerm(v); // define trial variables VarPtr beta_n_u = varFactory->fluxVar("\\widehat{\\beta \\cdot n }"); VarPtr u = varFactory->fieldVar("u"); //////////////////// BUILD MESH /////////////////////// BFPtr convectionBF = Teuchos::rcp( new BF(varFactory) ); // v terms: convectionBF->addTerm( -u, beta * v->grad() ); convectionBF->addTerm( beta_n_u, v); // define nodes for mesh int order = 1; int H1Order = order+1; int pToAdd = 1; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = MeshUtilities::buildUnitQuadMesh(2, 1, convectionBF, H1Order, H1Order+pToAdd); //////////////////// integrate discontinuous function - cellIDFunction /////////////////////// // FunctionPtr cellIDFxn = Teuchos::rcp(new CellIDFunction); // should be 0 on cellID 0, 1 on cellID 1 set<int> cellIDs; cellIDs.insert(1); // 0 on cell 0, 1 on cell 1 FunctionPtr indicator = Teuchos::rcp(new IndicatorFunction(cellIDs)); // should be 0 on cellID 0, 1 on cellID 1 double jumpWeight = 13.3; // some random number FunctionPtr edgeRestrictionFxn = Teuchos::rcp(new EdgeFunction); FunctionPtr X = Function::xn(1); LinearTermPtr integrandLT = Function::constant(1.0)*v + Function::constant(jumpWeight)*X*edgeRestrictionFxn*v; // make riesz representation function to more closely emulate the error rep LinearTermPtr indicatorLT = Teuchos::rcp(new LinearTerm);// residual indicatorLT->addTerm(indicator*v); Teuchos::RCP<RieszRep> riesz = Teuchos::rcp(new RieszRep(mesh, ipL2, indicatorLT)); riesz->computeRieszRep(); map<int,FunctionPtr> vmap; vmap[v->ID()] = RieszRep::repFunction(v,riesz); // SHOULD BE L2 projection = same thing!!! FunctionPtr volumeIntegrand = integrandLT->evaluate(vmap,false); FunctionPtr edgeRestrictedIntegrand = integrandLT->evaluate(vmap,true); double edgeRestrictedValue = volumeIntegrand->integrate(mesh,10) + edgeRestrictedIntegrand->integrate(mesh,10); double expectedValue = .5 + .5*jumpWeight; double diff = abs(expectedValue-edgeRestrictedValue); if (abs(diff)>1e-11) { success = false; cout << "Failed testIntegrateDiscontinuousFunction() with expectedValue = " << expectedValue << " and actual value = " << edgeRestrictedValue << endl; } return success; }
// tests whether a mixed type LT bool ScratchPadTests::testLinearTermEvaluationConsistency() { bool success = true; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr v = varFactory->testVar("v", HGRAD); vector<double> beta; beta.push_back(1.0); beta.push_back(1.0); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// // robust test norm IPPtr ip = Teuchos::rcp(new IP); ip->addTerm(v); ip->addTerm(beta*v->grad()); // define trial variables VarPtr beta_n_u = varFactory->fluxVar("\\widehat{\\beta \\cdot n }"); VarPtr u = varFactory->fieldVar("u"); //////////////////// BUILD MESH /////////////////////// BFPtr convectionBF = Teuchos::rcp( new BF(varFactory) ); // v terms: convectionBF->addTerm( -u, beta * v->grad() ); convectionBF->addTerm( beta_n_u, v); // define nodes for mesh int order = 1; int H1Order = order+1; int pToAdd = 1; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = MeshUtilities::buildUnitQuadMesh(1, convectionBF, H1Order, H1Order+pToAdd); //////////////////// get fake residual /////////////////////// LinearTermPtr lt = Teuchos::rcp(new LinearTerm); FunctionPtr edgeFxn = Teuchos::rcp(new EdgeFunction); FunctionPtr Xsq = Function::xn(2); FunctionPtr Ysq = Function::yn(2); FunctionPtr XYsq = Xsq*Ysq; lt->addTerm(edgeFxn*v + (beta*XYsq)*v->grad()); Teuchos::RCP<RieszRep> ltRiesz = Teuchos::rcp(new RieszRep(mesh, ip, lt)); ltRiesz->computeRieszRep(); FunctionPtr repFxn = RieszRep::repFunction(v,ltRiesz); map<int,FunctionPtr> rep_map; rep_map[v->ID()] = repFxn; FunctionPtr edgeLt = lt->evaluate(rep_map, true) ; FunctionPtr elemLt = lt->evaluate(rep_map, false); double edgeVal = edgeLt->integrate(mesh,10); double elemVal = elemLt->integrate(mesh,10); LinearTermPtr edgeOnlyLt = Teuchos::rcp(new LinearTerm);// residual edgeOnlyLt->addTerm(edgeFxn*v); FunctionPtr edgeOnly = edgeOnlyLt->evaluate(rep_map,true); double edgeOnlyVal = edgeOnly->integrate(mesh,10); double diff = edgeOnlyVal-edgeVal; if (abs(diff)>1e-11) { success = false; cout << "Failed testLinearTermEvaluationConsistency() with diff = " << diff << endl; } return success; }