double FiniteDifferenceUtilities::finiteDifferenceGradient(MeshPtr mesh, RieszRepPtr residual, TSolutionPtr<double> backgroundSoln, int dofIndex) { residual->computeRieszRep(); double fx = residual->getNorm(); TSolutionPtr<double> solnPerturbation = TestingUtilities::makeNullSolution(mesh); // create perturbation in direction du solnPerturbation->clear(); // clear all solns TestingUtilities::initializeSolnCoeffs(solnPerturbation); TestingUtilities::setSolnCoeffForGlobalDofIndex(solnPerturbation,1.0,dofIndex); double h = 1e-7; backgroundSoln->addSolution(solnPerturbation,h); residual->computeRieszRep(); double fxh = residual->getNorm(); // get 1/2 squared norm (cost function) for each quantity double f = fx*fx*.5; double fh = fxh*fxh*.5; double fd_gradient = (fh-f)/h; // remove contribution backgroundSoln->addSolution(solnPerturbation,-h); return fd_gradient; }
int main(int argc, char *argv[]) { // TODO: figure out the right thing to do here... // may want to modify argc and argv before we make the following call: Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); int rank=mpiSession.getRank(); int numProcs=mpiSession.getNProc(); #ifdef HAVE_MPI choice::MpiArgs args( argc, argv ); #else choice::Args args(argc, argv ); #endif int polyOrder, pToAdd; try { // read args: polyOrder = args.Input<int>("--polyOrder", "L^2 (field) polynomial order"); pToAdd = args.Input<int>("--delta_p", "delta p for test enrichment", 2); args.Process(); } catch ( choice::ArgException& e ) { exit(0); } int H1Order = polyOrder + 1; bool useCompliantGraphNorm = false; // weights to improve conditioning of the local problems bool useExtendedPrecisionForOptimalTestInversion = false; /////////////////////////// "VGP_CONFORMING" VERSION /////////////////////// // fluxes and traces: VarPtr u1hat, u2hat, t1n, t2n; // fields for SGP: VarPtr phi, p, sigma11, sigma12, sigma21, sigma22; // fields specific to VGP: VarPtr u1, u2; BFPtr stokesBF; IPPtr qoptIP; double mu = 1; FunctionPtr h = Teuchos::rcp( new hFunction() ); VarPtr tau1,tau2,v1,v2,q; VarFactory varFactory; tau1 = varFactory.testVar("\\tau_1", HDIV); tau2 = varFactory.testVar("\\tau_2", HDIV); v1 = varFactory.testVar("v_1", HGRAD); v2 = varFactory.testVar("v_2", HGRAD); q = varFactory.testVar("q", HGRAD); u1hat = varFactory.traceVar("\\widehat{u}_1"); u2hat = varFactory.traceVar("\\widehat{u}_2"); t1n = varFactory.fluxVar("\\widehat{t_{1n}}"); t2n = varFactory.fluxVar("\\widehat{t_{2n}}"); if (!useCompliantGraphNorm) { u1 = varFactory.fieldVar("u_1"); u2 = varFactory.fieldVar("u_2"); } else { u1 = varFactory.fieldVar("u_1", HGRAD); u2 = varFactory.fieldVar("u_2", HGRAD); } sigma11 = varFactory.fieldVar("\\sigma_11"); sigma12 = varFactory.fieldVar("\\sigma_12"); sigma21 = varFactory.fieldVar("\\sigma_21"); sigma22 = varFactory.fieldVar("\\sigma_22"); p = varFactory.fieldVar("p"); stokesBF = Teuchos::rcp( new BF(varFactory) ); // tau1 terms: stokesBF->addTerm(u1,tau1->div()); stokesBF->addTerm(sigma11,tau1->x()); // (sigma1, tau1) stokesBF->addTerm(sigma12,tau1->y()); stokesBF->addTerm(-u1hat, tau1->dot_normal()); // tau2 terms: stokesBF->addTerm(u2, tau2->div()); stokesBF->addTerm(sigma21,tau2->x()); // (sigma2, tau2) stokesBF->addTerm(sigma22,tau2->y()); stokesBF->addTerm(-u2hat, tau2->dot_normal()); // v1: stokesBF->addTerm(mu * sigma11,v1->dx()); // (mu sigma1, grad v1) stokesBF->addTerm(mu * sigma12,v1->dy()); stokesBF->addTerm( - p, v1->dx() ); stokesBF->addTerm( -t1n, v1); // v2: stokesBF->addTerm(mu * sigma21,v2->dx()); // (mu sigma2, grad v2) stokesBF->addTerm(mu * sigma22,v2->dy()); stokesBF->addTerm( -p, v2->dy()); stokesBF->addTerm( -t2n, v2); // q: stokesBF->addTerm(-u1,q->dx()); // (-u, grad q) stokesBF->addTerm(-u2,q->dy()); stokesBF->addTerm(u1hat->times_normal_x() + u2hat->times_normal_y(), q); if (rank==0) stokesBF->printTrialTestInteractions(); stokesBF->setUseExtendedPrecisionSolveForOptimalTestFunctions(useExtendedPrecisionForOptimalTestInversion); mesh = MeshFactory::quadMesh(stokesBF, H1Order, pToAdd); //////////////////// CREATE BCs /////////////////////// BCPtr bc = BC::bc(); //////////////////// CREATE RHS /////////////////////// RHSPtr rhs = RHS::rhs(); // zero for now... IPPtr ip; qoptIP = Teuchos::rcp(new IP()); if (useCompliantGraphNorm) { qoptIP->addTerm( mu * v1->dx() + tau1->x() ); // sigma11 qoptIP->addTerm( mu * v1->dy() + tau1->y() ); // sigma12 qoptIP->addTerm( mu * v2->dx() + tau2->x() ); // sigma21 qoptIP->addTerm( mu * v2->dy() + tau2->y() ); // sigma22 qoptIP->addTerm( mu * v1->dx() + mu * v2->dy() ); // pressure qoptIP->addTerm( h * tau1->div() - h * q->dx() ); // u1 qoptIP->addTerm( h * tau2->div() - h * q->dy()); // u2 qoptIP->addTerm( (mu / h) * v1 ); qoptIP->addTerm( (mu / h) * v2 ); qoptIP->addTerm( q ); qoptIP->addTerm( tau1 ); qoptIP->addTerm( tau2 ); } else { // standard graph norm, then qoptIP = stokesBF->graphNorm(); } ip = qoptIP; if (rank==0) ip->printInteractions(); // aim is just to answer one simple question: // have I figured out a trial-space preimage for optimal test function (q=1, tau=0, v=0)? SolutionPtr soln = Teuchos::rcp(new Solution(mesh)); FunctionPtr x = Function::xn(); FunctionPtr y = Function::yn(); // u1 = u1_hat = x / 2 FunctionPtr u1_exact = x / 2; // u2 = u2_hat = y / 2 FunctionPtr u2_exact = y / 2; // sigma = 0.5 * I FunctionPtr sigma11_exact = Function::constant(0.5); FunctionPtr sigma22_exact = Function::constant(0.5); // tn_hat = 0.5 * n FunctionPtr n = Function::normal(); FunctionPtr t1n_exact = n->x() / 2; FunctionPtr t2n_exact = n->y() / 2; map<int, FunctionPtr > exact_soln; exact_soln[u1->ID()] = u1_exact; exact_soln[u1hat->ID()] = u1_exact; exact_soln[u2->ID()] = u2_exact; exact_soln[u2hat->ID()] = u2_exact; exact_soln[sigma11->ID()] = sigma11_exact; exact_soln[sigma22->ID()] = sigma22_exact; exact_soln[t1n->ID()] = t1n_exact; exact_soln[t2n->ID()] = t2n_exact; exact_soln[p->ID()] = Function::zero(); exact_soln[sigma12->ID()] = Function::zero(); exact_soln[sigma21->ID()] = Function::zero(); soln->projectOntoMesh(exact_soln); LinearTermPtr soln_functional = stokesBF->testFunctional(soln); RieszRepPtr rieszRep = Teuchos::rcp( new RieszRep(mesh, ip, soln_functional) ); rieszRep->computeRieszRep(); // get test functions: FunctionPtr q_fxn = Teuchos::rcp( new RepFunction(q, rieszRep) ); FunctionPtr v1_fxn = Teuchos::rcp( new RepFunction(v1, rieszRep) ); FunctionPtr v2_fxn = Teuchos::rcp( new RepFunction(v2, rieszRep) ); FunctionPtr tau1_fxn = Teuchos::rcp( new RepFunction(tau1, rieszRep) ); FunctionPtr tau2_fxn = Teuchos::rcp( new RepFunction(tau2, rieszRep) ); cout << "L2 norm of (q-1) : " << (q_fxn - 1)->l2norm(mesh) << endl; cout << "L2 norm of (v1) : " << (v1_fxn)->l2norm(mesh) << endl; cout << "L2 norm of (v2) : " << (v2_fxn)->l2norm(mesh) << endl; cout << "L2 norm of (tau1) : " << (tau1_fxn)->l2norm(mesh) << endl; cout << "L2 norm of (tau2) : " << (tau2_fxn)->l2norm(mesh) << endl; VTKExporter exporter(soln, mesh, varFactory); exporter.exportSolution("conservationPreimage", H1Order*2); cout << "Checking that the soln_functional is what I expect:\n"; FunctionPtr xyVector = Function::vectorize(x, y); cout << "With v1 = x, integral: " << integralOverMesh(soln_functional, v1, x) << endl; cout << "With v2 = y, integral: " << integralOverMesh(soln_functional, v2, y) << endl; cout << "With tau1=(x,y), integral: " << integralOverMesh(soln_functional, tau1, xyVector) << endl; cout << "With tau2=(x,y), integral: " << integralOverMesh(soln_functional, tau2, xyVector) << endl; cout << "With q =x, integral: " << integralOverMesh(soln_functional, q, x) << endl; cout << "(Expect 0s all around, except for q, where we expect (1,x) == 0.5.)\n"; 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; }
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; }
bool ScratchPadTests::testResidualMemoryError() { int rank = Teuchos::GlobalMPISession::getRank(); double tol = 1e-11; bool success = true; int nCells = 2; double eps = 1e-2; //////////////////// 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 robIP = Teuchos::rcp(new IP); robIP->addTerm(tau); robIP->addTerm(tau->div()); robIP->addTerm(v->grad()); robIP->addTerm(v); //////////////////// SPECIFY RHS /////////////////////// FunctionPtr zero = Function::constant(0.0); FunctionPtr one = Function::constant(1.0); RHSPtr rhs = RHS::rhs(); FunctionPtr f = zero; // FunctionPtr f = one; rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////// CREATE BCs /////////////////////// BCPtr bc = BC::bc(); SpatialFilterPtr inflowBoundary = Teuchos::rcp( new LRInflowSquareBoundary ); SpatialFilterPtr outflowBoundary = Teuchos::rcp( new LROutflowSquareBoundary); 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); bc->addDirichlet(beta_n_u_minus_sigma_n, inflowBoundary, beta*n*one); bc->addDirichlet(uhat, outflowBoundary, 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); // 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); mesh->registerSolution(solution); double energyErr1 = solution->energyErrorTotal(); LinearTermPtr residual = rhs->linearTermCopy(); residual->addTerm(-confusionBF->testFunctional(solution)); RieszRepPtr rieszResidual = Teuchos::rcp(new RieszRep(mesh, robIP, residual)); rieszResidual->computeRieszRep(); FunctionPtr e_v = RieszRep::repFunction(v,rieszResidual); FunctionPtr e_tau = RieszRep::repFunction(tau,rieszResidual); double energyThreshold = 0.2; // for mesh refinements RefinementStrategy refinementStrategy( solution, energyThreshold ); refinementStrategy.refine(); solution->solve(false); double energyErr2 = solution->energyErrorTotal(); // if energy error rises if (energyErr1 < energyErr2) { if (rank==0) cout << "energy error increased from " << energyErr1 << " to " << energyErr2 << " after refinement.\n"; success = false; } return success; }