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 bool useCompliantGraphNorm = false; bool enforceOneIrregularity = true; bool writeStiffnessMatrices = false; bool writeWorstCaseGramMatrices = false; int numRefs = 10; // problem parameters: double eps = 1e-8; vector<double> beta_const; beta_const.push_back(2.0); beta_const.push_back(1.0); int k = 2, delta_k = 2; Teuchos::CommandLineProcessor cmdp(false,true); // false: don't throw exceptions; true: do return errors for unrecognized options cmdp.setOption("polyOrder",&k,"polynomial order for field variable u"); cmdp.setOption("delta_k", &delta_k, "test space polynomial order enrichment"); cmdp.setOption("numRefs",&numRefs,"number of refinements"); cmdp.setOption("eps", &eps, "epsilon"); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { #ifdef HAVE_MPI MPI_Finalize(); #endif return -1; } int H1Order = k + 1; if (rank==0) { string normChoice = useCompliantGraphNorm ? "unit-compliant graph norm" : "standard graph norm"; cout << "Using " << normChoice << "." << endl; cout << "eps = " << eps << endl; cout << "numRefs = " << numRefs << endl; cout << "p = " << k << endl; } //////////////////// 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; if (useCompliantGraphNorm) { u = varFactory.fieldVar("u",HGRAD); } else { u = varFactory.fieldVar("u"); } VarPtr sigma1 = varFactory.fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory.fieldVar("\\sigma_2"); //////////////////// 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) /////////////////////// // mathematician's norm IPPtr mathIP = Teuchos::rcp(new IP()); mathIP->addTerm(tau); mathIP->addTerm(tau->div()); mathIP->addTerm(v); mathIP->addTerm(v->grad()); // quasi-optimal norm IPPtr qoptIP = Teuchos::rcp(new IP); if (!useCompliantGraphNorm) { qoptIP->addTerm( tau / eps + v->grad() ); qoptIP->addTerm( beta_const * v->grad() - tau->div() ); qoptIP->addTerm( v ); } else { FunctionPtr h = Teuchos::rcp( new hFunction ); // here, we're aiming at optimality in 1/h^2 |u|^2 + 1/eps^2 |sigma|^2 qoptIP->addTerm( tau + eps * v->grad() ); qoptIP->addTerm( h * beta_const * v->grad() - tau->div() ); qoptIP->addTerm(v); qoptIP->addTerm(tau); } //////////////////// SPECIFY RHS /////////////////////// RHSPtr rhs = RHS::rhs(); FunctionPtr f = Teuchos::rcp( new ConstantScalarFunction(0.0) ); 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 InflowSquareBoundary ); SpatialFilterPtr outflowBoundary = Teuchos::rcp( new OutflowSquareBoundary ); FunctionPtr u0 = Teuchos::rcp( new U0 ); bc->addDirichlet(uhat, outflowBoundary, u0); bc->addDirichlet(uhat, inflowBoundary, u0); // Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp(new PenaltyConstraints); // pc->addConstraint(uhat==u0,inflowBoundary); //////////////////// BUILD MESH /////////////////////// // create a new mesh on a single-cell, unit square domain Teuchos::RCP<Mesh> mesh = MeshFactory::quadMeshMinRule(confusionBF, H1Order, delta_k); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, qoptIP) ); // solution->setFilter(pc); double energyThreshold = 0.2; // for mesh refinements bool useRieszRepBasedRefStrategy = true; if (rank==0) { if (useRieszRepBasedRefStrategy) { cout << "using RieszRep-based refinement strategy.\n"; } else { cout << "using solution-based refinement strategy.\n"; } } Teuchos::RCP<RefinementStrategy> refinementStrategy; if (!useRieszRepBasedRefStrategy) { refinementStrategy = Teuchos::rcp( new RefinementStrategy( solution, energyThreshold ) ); } else { LinearTermPtr residual = confusionBF->testFunctional(solution) - rhs->linearTerm(); refinementStrategy = Teuchos::rcp( new RefinementStrategy( mesh, residual, qoptIP, energyThreshold ) ); } refinementStrategy->setReportPerCellErrors(true); refinementStrategy->setEnforceOneIrregularity(enforceOneIrregularity); for (int refIndex=0; refIndex<numRefs; refIndex++){ if (writeStiffnessMatrices) { string stiffnessFile = fileNameForRefinement("confusion_stiffness", refIndex); solution->setWriteMatrixToFile(true, stiffnessFile); } solution->solve(); if (writeWorstCaseGramMatrices) { string gramFile = fileNameForRefinement("confusion_gram", refIndex); bool jacobiScaling = true; double condNum = MeshUtilities::computeMaxLocalConditionNumber(qoptIP, mesh, jacobiScaling, gramFile); if (rank==0) { cout << "estimated worst-case Gram matrix condition number: " << condNum << endl; cout << "putative worst-case Gram matrix written to file " << gramFile << endl; } } if (refIndex == numRefs-1) { // write out second-to-last mesh if (rank==0) GnuPlotUtil::writeComputationalMeshSkeleton("confusionMesh", mesh, true); } refinementStrategy->refine(rank==0); // print to console on rank 0 } if (writeStiffnessMatrices) { string stiffnessFile = fileNameForRefinement("confusion_stiffness", numRefs); solution->setWriteMatrixToFile(true, stiffnessFile); } if (writeWorstCaseGramMatrices) { string gramFile = fileNameForRefinement("confusion_gram", numRefs); bool jacobiScaling = true; double condNum = MeshUtilities::computeMaxLocalConditionNumber(qoptIP, mesh, jacobiScaling, gramFile); if (rank==0) { cout << "estimated worst-case Gram matrix condition number: " << condNum << endl; cout << "putative worst-case Gram matrix written to file " << gramFile << endl; } } // one more solve on the final refined mesh: solution->solve(); #ifdef HAVE_EPETRAEXT_HDF5 ostringstream dir_name; dir_name << "confusion_eps" << eps; HDF5Exporter exporter(mesh,dir_name.str()); exporter.exportSolution(solution, varFactory, 0); if (rank==0) cout << "wrote solution to " << dir_name.str() << endl; #endif return 0; }
// 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; }
// tests to make sure the energy error calculated thru direct integration works for vector valued test functions too bool ScratchPadTests::testLTResidual() { double tol = 1e-11; int rank = Teuchos::GlobalMPISession::getRank(); bool success = true; int nCells = 2; double eps = .1; //////////////////// 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); // choose the mesh-independent norm even though it may have boundary layers 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; // if this is set to zero instead, we pass the test (a clue?) rhs->addTerm( f * v ); //////////////////// CREATE BCs /////////////////////// BCPtr bc = BC::bc(); SpatialFilterPtr squareBoundary = Teuchos::rcp( new SquareBoundary ); bc->addDirichlet(uhat, squareBoundary, one); //////////////////// 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 /////////////////////// Teuchos::RCP<Solution> solution; solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); solution->solve(false); double energyError = solution->energyErrorTotal(); LinearTermPtr residual = rhs->linearTermCopy(); residual->addTerm(-confusionBF->testFunctional(solution),true); // FunctionPtr uh = Function::solution(uhat,solution); // FunctionPtr fn = Function::solution(beta_n_u_minus_sigma_n,solution); // FunctionPtr uF = Function::solution(u,solution); // FunctionPtr sigma = e1*Function::solution(sigma1,solution)+e2*Function::solution(sigma2,solution); // residual->addTerm(- (fn*v - uh*tau->dot_normal())); // residual->addTerm(- (uF*(tau->div() - beta*v->grad()) + sigma*((1/eps)*tau + v->grad()))); // residual->addTerm(-(fn*v - uF*beta*v->grad() + sigma*v->grad())); // just v portion // residual->addTerm(uh*tau->dot_normal() - uF*tau->div() - sigma*((1/eps)*tau)); // just tau portion Teuchos::RCP<RieszRep> rieszResidual = Teuchos::rcp(new RieszRep(mesh, ip, residual)); rieszResidual->computeRieszRep(); double energyErrorLT = rieszResidual->getNorm(); int cubEnrich = 0; bool testVsTest = true; FunctionPtr e_v = RieszRep::repFunction(v,rieszResidual); FunctionPtr e_tau = RieszRep::repFunction(tau,rieszResidual); // experiment by Nate: manually specify the error (this appears to produce identical results, as it should) // FunctionPtr err = e_v * e_v + e_tau * e_tau + e_v->grad() * e_v->grad() + e_tau->div() * e_tau->div(); map<int,FunctionPtr> errFxns; errFxns[v->ID()] = e_v; errFxns[tau->ID()] = e_tau; LinearTermPtr ipAtErrFxns = ip->evaluate(errFxns); FunctionPtr err = ip->evaluate(errFxns)->evaluate(errFxns); double energyErrorIntegrated = sqrt(err->integrate(mesh,cubEnrich,testVsTest)); // check that energy error computed thru Solution and through rieszRep are the same bool success1 = abs(energyError-energyErrorLT)<tol; // checks that matrix-computed and integrated errors are the same bool success2 = abs(energyErrorLT-energyErrorIntegrated)<tol; success = success1==true && success2==true; if (!success) { if (rank==0) cout << "Failed testLTResidual; energy error = " << energyError << ", while linearTerm error is computed to be " << energyErrorLT << ", and when computing through integration of the Riesz rep function, error = " << energyErrorIntegrated << endl; } // VTKExporter exporter(solution, mesh, varFactory); // exporter.exportSolution("testLTRes"); // cout << 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 int polyOrder = 3; int pToAdd = 2; // for tests // define our manufactured solution or problem bilinear form: double epsilon = 1e-2; bool useTriangles = false; 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 = polyOrder + 1; int horizontalCells = 1, verticalCells = 1; double energyThreshold = 0.2; // for mesh refinements double nonlinearStepSize = 0.5; double nonlinearRelativeEnergyTolerance = 0.015; // used to determine convergence of the nonlinear solution //////////////////////////////////////////////////////////////////// // SET UP PROBLEM //////////////////////////////////////////////////////////////////// Teuchos::RCP<BurgersBilinearForm> oldBurgersBF = Teuchos::rcp(new BurgersBilinearForm(epsilon)); // new-style bilinear form definition VarFactory varFactory; VarPtr uhat = varFactory.traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_hat = varFactory.fluxVar("\\widehat{\\beta_n u - \\sigma_n}"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma1 = varFactory.fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory.fieldVar("\\sigma_2"); VarPtr tau = varFactory.testVar("\\tau",HDIV); VarPtr v = varFactory.testVar("v",HGRAD); BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = Mesh::buildQuadMesh(quadPoints, horizontalCells, verticalCells, bf, H1Order, H1Order+pToAdd, useTriangles); mesh->setPartitionPolicy(Teuchos::rcp(new ZoltanMeshPartitionPolicy("HSFC"))); Teuchos::RCP<Solution> backgroundFlow = Teuchos::rcp(new Solution(mesh, Teuchos::rcp((BC*)NULL) , Teuchos::rcp((RHS*)NULL), Teuchos::rcp((DPGInnerProduct*)NULL))); // create null solution oldBurgersBF->setBackgroundFlow(backgroundFlow); // tau parts: // 1/eps (sigma, tau)_K + (u, div tau)_K - (u_hat, tau_n)_dK bf->addTerm(sigma1 / epsilon, tau->x()); bf->addTerm(sigma2 / epsilon, tau->y()); bf->addTerm(u, tau->div()); bf->addTerm( - uhat, tau->dot_normal() ); vector<double> e1(2); // (1,0) e1[0] = 1; vector<double> e2(2); // (0,1) e2[1] = 1; FunctionPtr u_prev = Teuchos::rcp( new PreviousSolutionFunction(backgroundFlow, u) ); FunctionPtr beta = e1 * u_prev + Teuchos::rcp( new ConstantVectorFunction( e2 ) ); // v: // (sigma, grad v)_K - (sigma_hat_n, v)_dK - (u, beta dot grad v) + (u_hat * n dot beta, v)_dK bf->addTerm( sigma1, v->dx() ); bf->addTerm( sigma2, v->dy() ); bf->addTerm( -u, beta * v->grad()); bf->addTerm( beta_n_u_minus_sigma_hat, v); // ==================== SET INITIAL GUESS ========================== mesh->registerSolution(backgroundFlow); map<int, Teuchos::RCP<AbstractFunction> > functionMap; functionMap[BurgersBilinearForm::U] = Teuchos::rcp(new InitialGuess()); functionMap[BurgersBilinearForm::SIGMA_1] = Teuchos::rcp(new ZeroFunction()); functionMap[BurgersBilinearForm::SIGMA_2] = Teuchos::rcp(new ZeroFunction()); backgroundFlow->projectOntoMesh(functionMap); // ==================== END SET INITIAL GUESS ========================== // compare stiffness matrices for first linear step: int trialOrder = 1; pToAdd = 0; int testOrder = trialOrder + pToAdd; CellTopoPtr quadTopoPtr = Teuchos::rcp(new shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >() )); DofOrderingFactory dofOrderingFactory(bf); DofOrderingPtr testOrdering = dofOrderingFactory.testOrdering(testOrder, *quadTopoPtr); DofOrderingPtr trialOrdering = dofOrderingFactory.trialOrdering(trialOrder, *quadTopoPtr); int numCells = 1; // just use testOrdering for both trial and test spaces (we only use to define BasisCache) ElementTypePtr elemType = Teuchos::rcp( new ElementType(trialOrdering, testOrdering, quadTopoPtr) ); BasisCachePtr basisCache = Teuchos::rcp( new BasisCache(elemType) ); quadPoints.resize(1,quadPoints.dimension(0),quadPoints.dimension(1)); basisCache->setPhysicalCellNodes(quadPoints,vector<int>(1),true); // true: do create side cache FieldContainer<double> cellSideParities(numCells,quadTopoPtr->getSideCount()); cellSideParities.initialize(1.0); // not worried here about neighbors actually having opposite parity -- just want the two BF implementations to agree... FieldContainer<double> expectedValues(numCells, testOrdering->totalDofs(), trialOrdering->totalDofs() ); FieldContainer<double> actualValues(numCells, testOrdering->totalDofs(), trialOrdering->totalDofs() ); oldBurgersBF->stiffnessMatrix(expectedValues, elemType, cellSideParities, basisCache); bf->stiffnessMatrix(actualValues, elemType, cellSideParities, basisCache); // compare beta's as well FieldContainer<double> expectedBeta = oldBurgersBF->getBeta(basisCache); Teuchos::Array<int> dim; expectedBeta.dimensions(dim); FieldContainer<double> actualBeta(dim); beta->values(actualBeta,basisCache); double tol = 1e-14; double maxDiff; if (rank == 0) { if ( ! TestSuite::fcsAgree(expectedBeta,actualBeta,tol,maxDiff) ) { cout << "Test failed: old Burgers beta differs from new; maxDiff " << maxDiff << ".\n"; cout << "Old beta: \n" << expectedBeta; cout << "New beta: \n" << actualBeta; } else { cout << "Old and new Burgers beta agree!!\n"; } if ( ! TestSuite::fcsAgree(expectedValues,actualValues,tol,maxDiff) ) { cout << "Test failed: old Burgers stiffness differs from new; maxDiff " << maxDiff << ".\n"; cout << "Old: \n" << expectedValues; cout << "New: \n" << actualValues; cout << "TrialDofOrdering: \n" << *trialOrdering; cout << "TestDofOrdering:\n" << *testOrdering; } else { cout << "Old and new Burgers stiffness agree!!\n"; } } // define our inner product: // Teuchos::RCP<BurgersInnerProduct> ip = Teuchos::rcp( new BurgersInnerProduct( bf, mesh ) ); // function to scale the squared guy by epsilon/h FunctionPtr epsilonOverHScaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); IPPtr ip = Teuchos::rcp( new IP ); ip->addTerm(tau); ip->addTerm(tau->div()); ip->addTerm( epsilonOverHScaling * v ); ip->addTerm( sqrt(sqrt(epsilon)) * v->grad() ); ip->addTerm( beta * v->grad() ); // use old IP instead, for now... Teuchos::RCP<BurgersInnerProduct> oldIP = Teuchos::rcp( new BurgersInnerProduct( oldBurgersBF, mesh ) ); expectedValues.resize(numCells, testOrdering->totalDofs(), testOrdering->totalDofs() ); actualValues.resize (numCells, testOrdering->totalDofs(), testOrdering->totalDofs() ); BasisCachePtr ipBasisCache = Teuchos::rcp( new BasisCache(elemType, true) ); // true: test vs. test ipBasisCache->setPhysicalCellNodes(quadPoints,vector<int>(1),false); // false: don't create side cache oldIP->computeInnerProductMatrix(expectedValues,testOrdering,ipBasisCache); ip->computeInnerProductMatrix(actualValues,testOrdering,ipBasisCache); tol = 1e-14; maxDiff = 0.0; if (rank==0) { if ( ! TestSuite::fcsAgree(expectedValues,actualValues,tol,maxDiff) ) { cout << "Test failed: old inner product differs from new IP; maxDiff " << maxDiff << ".\n"; cout << "Old: \n" << expectedValues; cout << "New IP: \n" << actualValues; cout << "testOrdering: \n" << *testOrdering; } else { cout << "Old inner product and new IP agree!!\n"; } } Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); // the RHS as implemented by BurgersProblem divides the first component of beta by 2.0 // so we follow that. I've not done the math; just imitating the code... Teuchos::RCP<RHSEasy> otherRHS = Teuchos::rcp( new RHSEasy ); vector<double> e1_div2 = e1; e1_div2[0] /= 2.0; FunctionPtr rhsBeta = (e1_div2 * beta * e1 + Teuchos::rcp( new ConstantVectorFunction( e2 ) )) * u_prev; otherRHS->addTerm( rhsBeta * v->grad() - u_prev * tau->div() ); Teuchos::RCP<BurgersProblem> problem = Teuchos::rcp( new BurgersProblem(oldBurgersBF) ); expectedValues.resize(numCells, testOrdering->totalDofs() ); actualValues.resize (numCells, testOrdering->totalDofs() ); problem->integrateAgainstStandardBasis(expectedValues,testOrdering,basisCache); otherRHS->integrateAgainstStandardBasis(actualValues,testOrdering,basisCache); tol = 1e-14; maxDiff = 0.0; if (rank==0) { if ( ! TestSuite::fcsAgree(expectedValues,actualValues,tol,maxDiff) ) { cout << "Test failed: old RHS differs from new (\"otherRHS\"); maxDiff " << maxDiff << ".\n"; cout << "Old: \n" << expectedValues; cout << "New: \n" << actualValues; cout << "testOrdering: \n" << *testOrdering; } else { cout << "Old and new RHS (\"otherRHS\") agree!!\n"; } } FunctionPtr u_prev_squared_div2 = 0.5 * u_prev * u_prev; rhs->addTerm( (e1 * u_prev_squared_div2 + e2 * u_prev) * v->grad() - u_prev * tau->div()); if (! functionsAgree(e2 * u_prev, Teuchos::rcp( new ConstantVectorFunction( e2 ) ) * u_prev, basisCache) ) { cout << "two like functions differ...\n"; } FunctionPtr e1_f = Teuchos::rcp( new ConstantVectorFunction( e1 ) ); FunctionPtr e2_f = Teuchos::rcp( new ConstantVectorFunction( e2 ) ); FunctionPtr one = Teuchos::rcp( new ConstantScalarFunction( 1.0 ) ); if (! functionsAgree( Teuchos::rcp( new ProductFunction(e1_f, (e1_f + e2_f)) ), // e1_f * (e1_f + e2_f) one, basisCache) ) { cout << "two like functions differ...\n"; } if (! functionsAgree(u_prev_squared_div2, (e1_div2 * beta) * u_prev, basisCache) ) { cout << "two like functions differ...\n"; } if (! functionsAgree(e1 * u_prev_squared_div2, (e1_div2 * beta * e1) * u_prev, basisCache) ) { cout << "two like functions differ...\n"; } if (! functionsAgree(e1 * u_prev_squared_div2 + e2 * u_prev, (e1_div2 * beta * e1 + Teuchos::rcp( new ConstantVectorFunction( e2 ) )) * u_prev, basisCache) ) { cout << "two like functions differ...\n"; } problem->integrateAgainstStandardBasis(expectedValues,testOrdering,basisCache); rhs->integrateAgainstStandardBasis(actualValues,testOrdering,basisCache); tol = 1e-14; maxDiff = 0.0; if (rank==0) { if ( ! TestSuite::fcsAgree(expectedValues,actualValues,tol,maxDiff) ) { cout << "Test failed: old RHS differs from new (\"rhs\"); maxDiff " << maxDiff << ".\n"; cout << "Old: \n" << expectedValues; cout << "New: \n" << actualValues; cout << "testOrdering: \n" << *testOrdering; } else { cout << "Old and new RHS (\"rhs\") agree!!\n"; } } SpatialFilterPtr outflowBoundary = Teuchos::rcp( new TopBoundary ); SpatialFilterPtr inflowBoundary = Teuchos::rcp( new NegatedSpatialFilter(outflowBoundary) ); Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp(new PenaltyConstraints); LinearTermPtr sigma_hat = beta * uhat->times_normal() - beta_n_u_minus_sigma_hat; FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); pc->addConstraint(sigma_hat==zero,outflowBoundary); FunctionPtr u0 = Teuchos::rcp( new U0 ); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); Teuchos::RCP<BCEasy> inflowBC = Teuchos::rcp( new BCEasy ); FunctionPtr u0_squared_div_2 = 0.5 * u0 * u0; inflowBC->addDirichlet(beta_n_u_minus_sigma_hat,inflowBoundary, ( e1 * u0_squared_div_2 + e2 * u0) * n ); // create a solution object Teuchos::RCP<Solution> solution = Teuchos::rcp(new Solution(mesh, inflowBC, rhs, ip)); mesh->registerSolution(solution); solution->setFilter(pc); // old penalty filter: Teuchos::RCP<LocalStiffnessMatrixFilter> penaltyBC = Teuchos::rcp(new PenaltyMethodFilter(problem)); // solution->setFilter(penaltyBC); // compare old and new filters elemType = mesh->getElement(0)->elementType(); trialOrdering = elemType->trialOrderPtr; testOrdering = elemType->testOrderPtr; // stiffness expectedValues.resize(numCells, trialOrdering->totalDofs(), trialOrdering->totalDofs() ); actualValues.resize (numCells, trialOrdering->totalDofs(), trialOrdering->totalDofs() ); expectedValues.initialize(0.0); actualValues.initialize(0.0); // load FieldContainer<double> expectedLoad(numCells, trialOrdering->totalDofs() ); FieldContainer<double> actualLoad(numCells, trialOrdering->totalDofs() ); penaltyBC->filter(expectedValues,expectedLoad,basisCache,mesh,problem); pc->filter(actualValues,actualLoad,basisCache,mesh,problem); maxDiff = 0.0; if (rank==0) { if ( ! TestSuite::fcsAgree(expectedValues,actualValues,tol,maxDiff) ) { cout << "Test failed: old penalty stiffness differs from new; maxDiff " << maxDiff << ".\n"; cout << "Old: \n" << expectedValues; cout << "New: \n" << actualValues; cout << "trialOrdering: \n" << *trialOrdering; } else { cout << "Old and new penalty stiffness agree!!\n"; } } if (rank==0) { if ( ! TestSuite::fcsAgree(expectedLoad,actualLoad,tol,maxDiff) ) { cout << "Test failed: old penalty load differs from new; maxDiff " << maxDiff << ".\n"; cout << "Old: \n" << expectedValues; cout << "New: \n" << actualValues; cout << "trialOrdering: \n" << *trialOrdering; } else { cout << "Old and new penalty load agree!!\n"; } } // define refinement strategy: Teuchos::RCP<RefinementStrategy> refinementStrategy = Teuchos::rcp(new RefinementStrategy(solution,energyThreshold)); // =================== END INITIALIZATION CODE ========================== // refine the spectral mesh, for comparability with the original Burgers' driver mesh->hRefine(vector<int>(1),RefinementPattern::regularRefinementPatternQuad()); int numRefs = 5; Teuchos::RCP<NonlinearStepSize> stepSize = Teuchos::rcp(new NonlinearStepSize(nonlinearStepSize)); Teuchos::RCP<NonlinearSolveStrategy> solveStrategy = Teuchos::rcp( new NonlinearSolveStrategy(backgroundFlow, solution, stepSize, nonlinearRelativeEnergyTolerance) ); for (int refIndex=0; refIndex<numRefs; refIndex++) { solveStrategy->solve(rank==0); refinementStrategy->refine(rank==0); // print to console on rank 0 } // one more nonlinear solve on refined mesh int numNRSteps = 5; for (int i=0; i<numNRSteps; i++) { solution->solve(false); backgroundFlow->addSolution(solution,1.0); } if (rank==0) { backgroundFlow->writeFieldsToFile(BurgersBilinearForm::U, "u_ref.m"); backgroundFlow->writeFieldsToFile(BurgersBilinearForm::SIGMA_1, "sigmax.m"); backgroundFlow->writeFieldsToFile(BurgersBilinearForm::SIGMA_2, "sigmay.m"); solution->writeFluxesToFile(BurgersBilinearForm::U_HAT, "du_hat_ref.dat"); } return 0; }
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); }
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 commRank = Teuchos::GlobalMPISession::getRank(); int numProcs = Teuchos::GlobalMPISession::getNProc(); // Required arguments double epsilon = args.Input<double>("--epsilon", "diffusion parameter"); int numRefs = args.Input<int>("--numRefs", "number of refinement steps"); bool enforceLocalConservation = args.Input<bool>("--conserve", "enforce local conservation"); int norm = args.Input<int>("--norm", "0 = graph\n 1 = robust\n 2 = modified robust"); // Optional arguments (have defaults) halfwidth = args.Input("--halfwidth", "half the width of the wedge", 0.5); bool allQuads = args.Input("--allQuads", "use only quads in mesh", false); bool zeroL2 = args.Input("--zeroL2", "take L2 term on v in robust norm to zero", enforceLocalConservation); args.Process(); //////////////////// 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("uhat"); VarPtr beta_n_u_minus_sigma_n = varFactory.fluxVar("fhat"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma = varFactory.fieldVar("sigma", VECTOR_L2); vector<double> beta; beta.push_back(1.0); beta.push_back(0.0); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // tau terms: bf->addTerm(sigma / epsilon, tau); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma, v->grad() ); bf->addTerm( beta * u, - v->grad() ); bf->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = Teuchos::rcp(new IP); // Graph norm if (norm == 0) { ip = bf->graphNorm(); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); ip->addZeroMeanTerm( h2_scaling*v ); } // Robust norm else if (norm == 1) { // robust test norm FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); if (!zeroL2) ip->addTerm( v ); ip->addTerm( sqrt(epsilon) * v->grad() ); // Weight these two terms for inflow ip->addTerm( beta * v->grad() ); ip->addTerm( tau->div() ); ip->addTerm( ip_scaling/sqrt(epsilon) * tau ); if (zeroL2) ip->addZeroMeanTerm( h2_scaling*v ); } // Modified robust norm else if (norm == 2) { // robust test norm FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); if (!zeroL2) ip->addTerm( v ); ip->addTerm( sqrt(epsilon) * v->grad() ); ip->addTerm( tau->div() - beta*v->grad() ); ip->addTerm( ip_scaling/sqrt(epsilon) * tau ); if (zeroL2) ip->addZeroMeanTerm( h2_scaling*v ); } //////////////////// SPECIFY RHS /////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr f = Teuchos::rcp( new ConstantScalarFunction(0.0) ); rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////// CREATE BCs /////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp( new PenaltyConstraints ); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); SpatialFilterPtr inflow = Teuchos::rcp( new Inflow ); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); bc->addDirichlet(beta_n_u_minus_sigma_n, inflow, zero); SpatialFilterPtr leadingWedge = Teuchos::rcp( new LeadingWedge ); FunctionPtr one = Teuchos::rcp( new ConstantScalarFunction(1.0) ); bc->addDirichlet(uhat, leadingWedge, one); SpatialFilterPtr trailingWedge = Teuchos::rcp( new TrailingWedge ); bc->addDirichlet(beta_n_u_minus_sigma_n, trailingWedge, beta*n*one); // bc->addDirichlet(uhat, trailingWedge, one); SpatialFilterPtr top = Teuchos::rcp( new Top ); bc->addDirichlet(uhat, top, zero); // bc->addDirichlet(beta_n_u_minus_sigma_n, top, zero); SpatialFilterPtr outflow = Teuchos::rcp( new Outflow ); pc->addConstraint(beta*uhat->times_normal() - beta_n_u_minus_sigma_n == zero, outflow); //////////////////// BUILD MESH /////////////////////// int H1Order = 3, pToAdd = 2; // define nodes for mesh vector< FieldContainer<double> > vertices; FieldContainer<double> pt(2); vector< vector<int> > elementIndices; vector<int> q(4); vector<int> t(3); if (allQuads) { pt(0) = -halfwidth; pt(1) = -1; vertices.push_back(pt); pt(0) = 0; pt(1) = 0; vertices.push_back(pt); pt(0) = halfwidth; pt(1) = -1; vertices.push_back(pt); pt(0) = halfwidth; pt(1) = halfwidth; vertices.push_back(pt); pt(0) = 0; pt(1) = halfwidth; vertices.push_back(pt); pt(0) = -halfwidth; pt(1) = halfwidth; vertices.push_back(pt); q[0] = 0; q[1] = 1; q[2] = 4; q[3] = 5; elementIndices.push_back(q); q[0] = 1; q[1] = 2; q[2] = 3; q[3] = 4; elementIndices.push_back(q); } else { pt(0) = -halfwidth; pt(1) = -1; vertices.push_back(pt); pt(0) = 0; pt(1) = 0; vertices.push_back(pt); pt(0) = halfwidth; pt(1) = -1; vertices.push_back(pt); pt(0) = halfwidth; pt(1) = 0; vertices.push_back(pt); pt(0) = halfwidth; pt(1) = halfwidth; vertices.push_back(pt); pt(0) = 0; pt(1) = halfwidth; vertices.push_back(pt); pt(0) = -halfwidth; pt(1) = halfwidth; vertices.push_back(pt); pt(0) = -halfwidth; pt(1) = 0; vertices.push_back(pt); t[0] = 0; t[1] = 1; t[2] = 7; elementIndices.push_back(t); t[0] = 1; t[1] = 2; t[2] = 3; elementIndices.push_back(t); q[0] = 1; q[1] = 3; q[2] = 4; q[3] = 5; elementIndices.push_back(q); q[0] = 7; q[1] = 1; q[2] = 5; q[3] = 6; elementIndices.push_back(q); } Teuchos::RCP<Mesh> mesh = Teuchos::rcp( new Mesh(vertices, elementIndices, bf, H1Order, pToAdd) ); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); 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 ); VTKExporter exporter(solution, mesh, varFactory); ofstream errOut; if (commRank == 0) errOut.open("singularwedge_err.txt"); for (int refIndex=0; refIndex<=numRefs; refIndex++){ solution->solve(false); double energy_error = solution->energyErrorTotal(); if (commRank==0){ stringstream outfile; outfile << "singularwedge_" << refIndex; exporter.exportSolution(outfile.str()); // Check local conservation FunctionPtr flux = Teuchos::rcp( new PreviousSolutionFunction(solution, beta_n_u_minus_sigma_n) ); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); Teuchos::Tuple<double, 3> fluxImbalances = checkConservation(flux, zero, varFactory, mesh); cout << "Mass flux: Largest Local = " << fluxImbalances[0] << ", Global = " << fluxImbalances[1] << ", Sum Abs = " << fluxImbalances[2] << endl; errOut << mesh->numGlobalDofs() << " " << energy_error << " " << fluxImbalances[0] << " " << fluxImbalances[1] << " " << fluxImbalances[2] << endl; } if (refIndex < numRefs) refinementStrategy.refine(commRank==0); // print to console on commRank 0 } if (commRank == 0) errOut.close(); return 0; }
int main(int argc, char *argv[]) { // Process command line arguments if (argc > 1) numRefs = atof(argv[1]); #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 FunctionPtr beta = Teuchos::rcp(new Beta()); //////////////////////////////////////////////////////////////////// // DEFINE VARIABLES //////////////////////////////////////////////////////////////////// // test variables VarFactory varFactory; VarPtr tau = varFactory.testVar("\\tau", HDIV); VarPtr v = varFactory.testVar("v", HGRAD); // 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"); //////////////////////////////////////////////////////////////////// // CREATE MESH //////////////////////////////////////////////////////////////////// BFPtr confusionBF = Teuchos::rcp( new BF(varFactory) ); FieldContainer<double> meshBoundary(4,2); meshBoundary(0,0) = 0.0; // x1 meshBoundary(0,1) = -2.0; // y1 meshBoundary(1,0) = 4.0; meshBoundary(1,1) = -2.0; meshBoundary(2,0) = 4.0; meshBoundary(2,1) = 2.0; meshBoundary(3,0) = 0.0; meshBoundary(3,1) = 2.0; int horizontalCells = 4, verticalCells = 4; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = Mesh::buildQuadMesh(meshBoundary, horizontalCells, verticalCells, confusionBF, H1Order, H1Order+pToAdd, false); //////////////////////////////////////////////////////////////////// // INITIALIZE BACKGROUND FLOW FUNCTIONS //////////////////////////////////////////////////////////////////// BCPtr nullBC = Teuchos::rcp((BC*)NULL); RHSPtr nullRHS = Teuchos::rcp((RHS*)NULL); IPPtr nullIP = Teuchos::rcp((IP*)NULL); SolutionPtr prevTimeFlow = Teuchos::rcp(new Solution(mesh, nullBC, nullRHS, nullIP) ); SolutionPtr flowResidual = Teuchos::rcp(new Solution(mesh, nullBC, nullRHS, nullIP) ); FunctionPtr u_prev_time = Teuchos::rcp( new PreviousSolutionFunction(prevTimeFlow, u) ); // ==================== SET INITIAL GUESS ========================== double u_free = 0.0; double sigma1_free = 0.0; double sigma2_free = 0.0; map<int, Teuchos::RCP<Function> > functionMap; functionMap[u->ID()] = Teuchos::rcp( new ConstantScalarFunction(u_free) ); functionMap[sigma1->ID()] = Teuchos::rcp( new ConstantScalarFunction(sigma1_free) ); functionMap[sigma2->ID()] = Teuchos::rcp( new ConstantScalarFunction(sigma2_free) ); prevTimeFlow->projectOntoMesh(functionMap); // ==================== END SET INITIAL GUESS ========================== //////////////////////////////////////////////////////////////////// // DEFINE BILINEAR FORM //////////////////////////////////////////////////////////////////// // tau terms: confusionBF->addTerm(sigma1 / epsilon, tau->x()); confusionBF->addTerm(sigma2 / epsilon, 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 * u, - v->grad() ); confusionBF->addTerm( beta_n_u_minus_sigma_n, v); //////////////////////////////////////////////////////////////////// // TIMESTEPPING TERMS //////////////////////////////////////////////////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); double dt = 0.25; FunctionPtr invDt = Teuchos::rcp(new ScalarParamFunction(1.0/dt)); if (rank==0){ cout << "Timestep dt = " << dt << endl; } if (transient) { confusionBF->addTerm( u, invDt*v ); rhs->addTerm( u_prev_time * invDt * v ); } //////////////////////////////////////////////////////////////////// // DEFINE INNER PRODUCT //////////////////////////////////////////////////////////////////// // mathematician's norm IPPtr mathIP = Teuchos::rcp(new IP()); mathIP->addTerm(tau); mathIP->addTerm(tau->div()); mathIP->addTerm(v); mathIP->addTerm(v->grad()); // quasi-optimal norm IPPtr qoptIP = Teuchos::rcp(new IP); qoptIP->addTerm( v ); qoptIP->addTerm( tau / epsilon + v->grad() ); qoptIP->addTerm( beta * v->grad() - tau->div() ); // robust test norm IPPtr robIP = Teuchos::rcp(new IP); FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); if (!enforceLocalConservation) { robIP->addTerm( ip_scaling * v ); if (transient) robIP->addTerm( invDt * v ); } robIP->addTerm( sqrt(epsilon) * v->grad() ); // Weight these two terms for inflow FunctionPtr ip_weight = Teuchos::rcp( new IPWeight() ); robIP->addTerm( ip_weight * beta * v->grad() ); robIP->addTerm( ip_weight * tau->div() ); robIP->addTerm( ip_scaling/sqrt(epsilon) * tau ); if (enforceLocalConservation) robIP->addZeroMeanTerm( v ); //////////////////////////////////////////////////////////////////// // DEFINE RHS //////////////////////////////////////////////////////////////////// FunctionPtr f = Teuchos::rcp( new ConstantScalarFunction(0.0) ); rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////////////////////////////////////////////////////// // DEFINE BC //////////////////////////////////////////////////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); // Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp( new PenaltyConstraints ); SpatialFilterPtr lBoundary = Teuchos::rcp( new LeftBoundary ); SpatialFilterPtr tbBoundary = Teuchos::rcp( new TopBottomBoundary ); SpatialFilterPtr rBoundary = Teuchos::rcp( new RightBoundary ); FunctionPtr u0 = Teuchos::rcp( new ZeroBC ); FunctionPtr u_inlet = Teuchos::rcp( new InletBC ); // FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); bc->addDirichlet(beta_n_u_minus_sigma_n, lBoundary, u_inlet); bc->addDirichlet(beta_n_u_minus_sigma_n, tbBoundary, u0); bc->addDirichlet(uhat, rBoundary, u0); // pc->addConstraint(beta_n_u_minus_sigma_n - uhat == u0, rBoundary); //////////////////////////////////////////////////////////////////// // CREATE SOLUTION OBJECT //////////////////////////////////////////////////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, robIP) ); // solution->setFilter(pc); // ==================== Enforce Local Conservation ================== if (enforceLocalConservation) { if (transient) { FunctionPtr conserved_rhs = u_prev_time * invDt; LinearTermPtr conserved_quantity = invDt * u; LinearTermPtr flux_part = Teuchos::rcp(new LinearTerm(-1.0, beta_n_u_minus_sigma_n)); conserved_quantity->addTerm(flux_part, true); // conserved_quantity = conserved_quantity - beta_n_u_minus_sigma_n; solution->lagrangeConstraints()->addConstraint(conserved_quantity == conserved_rhs); } else { FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); solution->lagrangeConstraints()->addConstraint(beta_n_u_minus_sigma_n == zero); } } // ==================== Register Solutions ========================== mesh->registerSolution(solution); mesh->registerSolution(prevTimeFlow); // u_t(i-1) mesh->registerSolution(flowResidual); // u_t(i-1) double energyThreshold = 0.25; // for mesh refinements Teuchos::RCP<RefinementStrategy> refinementStrategy; refinementStrategy = Teuchos::rcp(new RefinementStrategy(solution,energyThreshold)); //////////////////////////////////////////////////////////////////// // PSEUDO-TIME SOLVE STRATEGY //////////////////////////////////////////////////////////////////// double time_tol = 1e-8; for (int refIndex=0; refIndex<=numRefs; refIndex++) { double L2_time_residual = 1e7; int timestepCount = 0; if (!transient) numTimeSteps = 1; while((L2_time_residual > time_tol) && (timestepCount < numTimeSteps)) { solution->solve(false); // subtract solutions to get residual flowResidual->setSolution(solution); // reset previous time solution to current time sol flowResidual->addSolution(prevTimeFlow, -1.0); double L2u = flowResidual->L2NormOfSolutionGlobal(u->ID()); double L2sigma1 = flowResidual->L2NormOfSolutionGlobal(sigma1->ID()); double L2sigma2 = flowResidual->L2NormOfSolutionGlobal(sigma2->ID()); L2_time_residual = sqrt(L2u*L2u + L2sigma1*L2sigma1 + L2sigma2*L2sigma2); cout << endl << "Timestep: " << timestepCount << ", dt = " << dt << ", Time residual = " << L2_time_residual << endl; if (rank == 0) { stringstream outfile; if (transient) outfile << "TransientConfusion_" << refIndex << "_" << timestepCount; else outfile << "TransientConfusion_" << refIndex; solution->writeToVTK(outfile.str(), 5); } ////////////////////////////////////////////////////////////////////////// // Check conservation by testing against one ////////////////////////////////////////////////////////////////////////// VarPtr testOne = varFactory.testVar("1", CONSTANT_SCALAR); // Create a fake bilinear form for the testing BFPtr fakeBF = Teuchos::rcp( new BF(varFactory) ); // Define our mass flux FunctionPtr flux_current_time = Teuchos::rcp( new PreviousSolutionFunction(solution, beta_n_u_minus_sigma_n) ); FunctionPtr delta_u = Teuchos::rcp( new PreviousSolutionFunction(flowResidual, u) ); LinearTermPtr surfaceFlux = -1.0 * flux_current_time * testOne; LinearTermPtr volumeChange = invDt * delta_u * testOne; LinearTermPtr massFluxTerm; if (transient) { massFluxTerm = volumeChange; // massFluxTerm->addTerm(surfaceFlux); } else { massFluxTerm = surfaceFlux; } // cout << "surface case = " << surfaceFlux->summands()[0].first->boundaryValueOnly() << " volume case = " << volumeChange->summands()[0].first->boundaryValueOnly() << endl; // FunctionPtr massFlux= Teuchos::rcp( new PreviousSolutionFunction(solution, beta_n_u_minus_sigma_n) ); // LinearTermPtr massFluxTerm = massFlux * testOne; Teuchos::RCP<shards::CellTopology> quadTopoPtr = Teuchos::rcp(new shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >() )); DofOrderingFactory dofOrderingFactory(fakeBF); int fakeTestOrder = H1Order; DofOrderingPtr testOrdering = dofOrderingFactory.testOrdering(fakeTestOrder, *quadTopoPtr); int testOneIndex = testOrdering->getDofIndex(testOne->ID(),0); vector< ElementTypePtr > elemTypes = mesh->elementTypes(); // global element types map<int, double> massFluxIntegral; // cellID -> integral double maxMassFluxIntegral = 0.0; double totalMassFlux = 0.0; double totalAbsMassFlux = 0.0; for (vector< ElementTypePtr >::iterator elemTypeIt = elemTypes.begin(); elemTypeIt != elemTypes.end(); elemTypeIt++) { ElementTypePtr elemType = *elemTypeIt; vector< ElementPtr > elems = mesh->elementsOfTypeGlobal(elemType); vector<int> cellIDs; for (int i=0; i<elems.size(); i++) { cellIDs.push_back(elems[i]->cellID()); } FieldContainer<double> physicalCellNodes = mesh->physicalCellNodesGlobal(elemType); BasisCachePtr basisCache = Teuchos::rcp( new BasisCache(elemType,mesh) ); basisCache->setPhysicalCellNodes(physicalCellNodes,cellIDs,true); // true: create side caches FieldContainer<double> cellMeasures = basisCache->getCellMeasures(); FieldContainer<double> fakeRHSIntegrals(elems.size(),testOrdering->totalDofs()); massFluxTerm->integrate(fakeRHSIntegrals,testOrdering,basisCache,true); // true: force side evaluation for (int i=0; i<elems.size(); i++) { int cellID = cellIDs[i]; // pick out the ones for testOne: massFluxIntegral[cellID] = fakeRHSIntegrals(i,testOneIndex); } // find the largest: for (int i=0; i<elems.size(); i++) { int cellID = cellIDs[i]; maxMassFluxIntegral = max(abs(massFluxIntegral[cellID]), maxMassFluxIntegral); } for (int i=0; i<elems.size(); i++) { int cellID = cellIDs[i]; maxMassFluxIntegral = max(abs(massFluxIntegral[cellID]), maxMassFluxIntegral); totalMassFlux += massFluxIntegral[cellID]; totalAbsMassFlux += abs( massFluxIntegral[cellID] ); } } // Print results from processor with rank 0 if (rank == 0) { cout << "largest mass flux: " << maxMassFluxIntegral << endl; cout << "total mass flux: " << totalMassFlux << endl; cout << "sum of mass flux absolute value: " << totalAbsMassFlux << endl; } prevTimeFlow->setSolution(solution); // reset previous time solution to current time sol timestepCount++; } if (refIndex < numRefs){ if (rank==0){ cout << "Performing refinement number " << refIndex << endl; } refinementStrategy->refine(rank==0); // RESET solution every refinement - make sure discretization error doesn't creep in // prevTimeFlow->projectOntoMesh(functionMap); } } return 0; }
ConvectionDiffusionFormulation::ConvectionDiffusionFormulation(int spaceDim, bool useConformingTraces, FunctionPtr beta, double epsilon) { _spaceDim = spaceDim; _epsilon = epsilon; _beta = beta; FunctionPtr zero = Function::constant(1); FunctionPtr one = Function::constant(1); Space tauSpace = (spaceDim > 1) ? HDIV : HGRAD; Space uhat_space = useConformingTraces ? HGRAD : L2; Space vSpace = (spaceDim > 1) ? VECTOR_L2 : L2; // fields VarPtr u; VarPtr sigma; // traces VarPtr uhat, tc; // tests VarPtr v; VarPtr tau; _vf = VarFactory::varFactory(); u = _vf->fieldVar(s_u); sigma = _vf->fieldVar(s_sigma, vSpace); if (spaceDim > 1) uhat = _vf->traceVar(s_uhat, u, uhat_space); else uhat = _vf->fluxVar(s_uhat, u, uhat_space); // for spaceDim==1, the "normal" component is in the flux-ness of uhat (it's a plus or minus 1) TFunctionPtr<double> n = TFunction<double>::normal(); TFunctionPtr<double> parity = TFunction<double>::sideParity(); if (spaceDim > 1) tc = _vf->fluxVar(s_tc, (_beta*u-sigma) * (n * parity)); else tc = _vf->fluxVar(s_tc, _beta*u-sigma); v = _vf->testVar(s_v, HGRAD); tau = _vf->testVar(s_tau, tauSpace); _bf = Teuchos::rcp( new BF(_vf) ); if (spaceDim==1) { // for spaceDim==1, the "normal" component is in the flux-ness of uhat (it's a plus or minus 1) _bf->addTerm(sigma/_epsilon, tau); _bf->addTerm(u, tau->dx()); _bf->addTerm(-uhat, tau); _bf->addTerm(-_beta*u + sigma, v->dx()); _bf->addTerm(tc, v); } else { _bf->addTerm(sigma/_epsilon, tau); _bf->addTerm(u, tau->div()); _bf->addTerm(-uhat, tau->dot_normal()); _bf->addTerm(-_beta*u + sigma, v->grad()); _bf->addTerm(tc, v); } _ips["Graph"] = _bf->graphNorm(); if (spaceDim > 1) { _ips["Robust"] = Teuchos::rcp(new IP); _ips["Robust"]->addTerm(tau->div()); _ips["Robust"]->addTerm(Function::min(one/Function::h(),Function::constant(1./sqrt(_epsilon)))*tau); _ips["Robust"]->addTerm(sqrt(_epsilon)*v->grad()); _ips["Robust"]->addTerm(_beta*v->grad()); _ips["Robust"]->addTerm(Function::min(sqrt(_epsilon)*one/Function::h(),one)*v); } else { _ips["Robust"] = Teuchos::rcp(new IP); _ips["Robust"]->addTerm(tau->dx()); _ips["Robust"]->addTerm(Function::min(one/Function::h(),Function::constant(1./sqrt(_epsilon)))*tau); _ips["Robust"]->addTerm(sqrt(_epsilon)*v->dx()); _ips["Robust"]->addTerm(_beta*v->dx()); _ips["Robust"]->addTerm(Function::min(sqrt(_epsilon)*one/Function::h(),one)*v); } if (spaceDim > 1) { _ips["CoupledRobust"] = Teuchos::rcp(new IP); _ips["CoupledRobust"]->addTerm(tau->div()-_beta*v->grad()); _ips["CoupledRobust"]->addTerm(Function::min(one/Function::h(),Function::constant(1./sqrt(_epsilon)))*tau); _ips["CoupledRobust"]->addTerm(sqrt(_epsilon)*v->grad()); _ips["CoupledRobust"]->addTerm(_beta*v->grad()); _ips["CoupledRobust"]->addTerm(Function::min(sqrt(_epsilon)*one/Function::h(),one)*v); } else { _ips["CoupledRobust"] = Teuchos::rcp(new IP); _ips["CoupledRobust"]->addTerm(tau->dx()-_beta*v->dx()); _ips["CoupledRobust"]->addTerm(Function::min(one/Function::h(),Function::constant(1./sqrt(_epsilon)))*tau); _ips["CoupledRobust"]->addTerm(sqrt(_epsilon)*v->dx()); _ips["CoupledRobust"]->addTerm(_beta*v->dx()); _ips["CoupledRobust"]->addTerm(Function::min(sqrt(_epsilon)*one/Function::h(),one)*v); } }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); #endif { // 1D tests CellTopoPtr line_2 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Line<2> >() ) ); // let's draw a line vector<double> v0 = makeVertex(0); vector<double> v1 = makeVertex(1); vector<double> v2 = makeVertex(2); vector< vector<double> > vertices; vertices.push_back(v0); vertices.push_back(v1); vertices.push_back(v2); vector<unsigned> line1VertexList; vector<unsigned> line2VertexList; line1VertexList.push_back(0); line1VertexList.push_back(1); line2VertexList.push_back(1); line2VertexList.push_back(2); vector< vector<unsigned> > elementVertices; elementVertices.push_back(line1VertexList); elementVertices.push_back(line2VertexList); vector< CellTopoPtr > cellTopos; cellTopos.push_back(line_2); cellTopos.push_back(line_2); MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); MeshTopologyPtr meshTopology = Teuchos::rcp( new MeshTopology(meshGeometry) ); FunctionPtr x = Function::xn(1); FunctionPtr function = x; FunctionPtr fbdr = Function::restrictToCellBoundary(function); vector<FunctionPtr> functions; functions.push_back(function); functions.push_back(function); vector<string> functionNames; functionNames.push_back("function1"); functionNames.push_back("function2"); { XDMFExporter exporter(meshTopology, "function1", false); exporter.exportFunction(function, "function1"); } { XDMFExporter exporter(meshTopology, "boundary1", false); exporter.exportFunction(fbdr, "boundary1"); } { XDMFExporter exporter(meshTopology, "functions1", false); exporter.exportFunction(functions, functionNames); } } { // 2D tests CellTopoPtr quad_4 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >() ) ); CellTopoPtr tri_3 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Triangle<3> >() ) ); // let's draw a little house vector<double> v0 = makeVertex(-1,0); vector<double> v1 = makeVertex(1,0); vector<double> v2 = makeVertex(1,2); vector<double> v3 = makeVertex(-1,2); vector<double> v4 = makeVertex(0.0,3); vector< vector<double> > vertices; vertices.push_back(v0); vertices.push_back(v1); vertices.push_back(v2); vertices.push_back(v3); vertices.push_back(v4); vector<unsigned> quadVertexList; quadVertexList.push_back(0); quadVertexList.push_back(1); quadVertexList.push_back(2); quadVertexList.push_back(3); vector<unsigned> triVertexList; triVertexList.push_back(3); triVertexList.push_back(2); triVertexList.push_back(4); vector< vector<unsigned> > elementVertices; elementVertices.push_back(quadVertexList); elementVertices.push_back(triVertexList); vector< CellTopoPtr > cellTopos; cellTopos.push_back(quad_4); cellTopos.push_back(tri_3); MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); MeshTopologyPtr meshTopology = Teuchos::rcp( new MeshTopology(meshGeometry) ); FunctionPtr x2 = Function::xn(2); FunctionPtr y2 = Function::yn(2); FunctionPtr function = x2 + y2; FunctionPtr vect = Function::vectorize(x2, y2); FunctionPtr fbdr = Function::restrictToCellBoundary(function); vector<FunctionPtr> functions; functions.push_back(function); functions.push_back(vect); vector<string> functionNames; functionNames.push_back("function"); functionNames.push_back("vect"); vector<FunctionPtr> bdrfunctions; bdrfunctions.push_back(fbdr); bdrfunctions.push_back(fbdr); vector<string> bdrfunctionNames; bdrfunctionNames.push_back("bdr1"); bdrfunctionNames.push_back("bdr2"); map<int, int> cellIDToNum1DPts; cellIDToNum1DPts[1] = 4; { XDMFExporter exporter(meshTopology, "Grid2D", false); // exporter.exportFunction(function, "function2", 0, 10); // exporter.exportFunction(vect, "vect2", 1, 10, cellIDToNum1DPts); // exporter.exportFunction(fbdr, "boundary2", 0); exporter.exportFunction(functions, functionNames, 1, 10); } { XDMFExporter exporter(meshTopology, "BdrGrid2D", false); // exporter.exportFunction(function, "function2", 0, 10); // exporter.exportFunction(vect, "vect2", 1, 10, cellIDToNum1DPts); // exporter.exportFunction(fbdr, "boundary2", 0); exporter.exportFunction(bdrfunctions, bdrfunctionNames, 1, 10); } //////////////////// 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("uhat"); VarPtr fhat = varFactory.fluxVar("fhat"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma = varFactory.fieldVar("sigma", VECTOR_L2); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // tau terms: bf->addTerm(sigma, tau); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma, v->grad() ); bf->addTerm( fhat, v); //////////////////// BUILD MESH /////////////////////// int H1Order = 4, pToAdd = 2; Teuchos::RCP<Mesh> mesh = Teuchos::rcp( new Mesh (meshTopology, bf, H1Order, pToAdd) ); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = bf->graphNorm(); //////////////////// SPECIFY RHS /////////////////////// RHSPtr rhs = RHS::rhs(); // Teuchos::RCP<RHS> rhs = Teuchos::rcp( new RHS ); FunctionPtr one = Function::constant(1.0); rhs->addTerm( one * v ); //////////////////// CREATE BCs /////////////////////// // Teuchos::RCP<BC> bc = Teuchos::rcp( new BCEasy ); BCPtr bc = BC::bc(); FunctionPtr zero = Function::zero(); SpatialFilterPtr entireBoundary = Teuchos::rcp( new EntireBoundary ); bc->addDirichlet(uhat, entireBoundary, zero); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); solution->solve(false); RefinementStrategy refinementStrategy( solution, 0.2); // Output solution FunctionPtr uSoln = Function::solution(u, solution); FunctionPtr sigmaSoln = Function::solution(sigma, solution); FunctionPtr uhatSoln = Function::solution(uhat, solution); FunctionPtr fhatSoln = Function::solution(fhat, solution); { XDMFExporter exporter(meshTopology, "Poisson", false); exporter.exportFunction(uSoln, "u", 0, 4); exporter.exportFunction(uSoln, "u", 1, 5); exporter.exportFunction(uhatSoln, "uhat", 0, 4); exporter.exportFunction(uhatSoln, "uhat", 1, 5); // exporter.exportFunction(fhatSoln, "fhat", 0, 4); // exporter.exportFunction(fhatSoln, "fhat", 1, 5); } { XDMFExporter exporter(meshTopology, "PoissonSolution", false); exporter.exportSolution(solution, mesh, varFactory, 0, 2, cellIDToSubdivision(mesh, 10)); refinementStrategy.refine(true); solution->solve(false); exporter.exportSolution(solution, mesh, varFactory, 1, 2, cellIDToSubdivision(mesh, 10)); } // exporter.exportFunction(sigmaSoln, "Poisson-s", "sigma", 0, 5); // exporter.exportFunction(uhatSoln, "Poisson-uhat", "uhat", 1, 6); } { // 3D tests CellTopoPtr hex = Teuchos::rcp(new shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<8> >() )); // let's draw a little box vector<double> v0 = makeVertex(0,0,0); vector<double> v1 = makeVertex(1,0,0); vector<double> v2 = makeVertex(1,1,0); vector<double> v3 = makeVertex(0,1,0); vector<double> v4 = makeVertex(0,0,1); vector<double> v5 = makeVertex(1,0,1); vector<double> v6 = makeVertex(1,1,1); vector<double> v7 = makeVertex(0,1,1); vector< vector<double> > vertices; vertices.push_back(v0); vertices.push_back(v1); vertices.push_back(v2); vertices.push_back(v3); vertices.push_back(v4); vertices.push_back(v5); vertices.push_back(v6); vertices.push_back(v7); vector<unsigned> hexVertexList; hexVertexList.push_back(0); hexVertexList.push_back(1); hexVertexList.push_back(2); hexVertexList.push_back(3); hexVertexList.push_back(4); hexVertexList.push_back(5); hexVertexList.push_back(6); hexVertexList.push_back(7); // vector<unsigned> triVertexList; // triVertexList.push_back(2); // triVertexList.push_back(3); // triVertexList.push_back(4); vector< vector<unsigned> > elementVertices; elementVertices.push_back(hexVertexList); // elementVertices.push_back(triVertexList); vector< CellTopoPtr > cellTopos; cellTopos.push_back(hex); // cellTopos.push_back(tri_3); MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); MeshTopologyPtr meshTopology = Teuchos::rcp( new MeshTopology(meshGeometry) ); FunctionPtr x = Function::xn(1); FunctionPtr y = Function::yn(1); FunctionPtr z = Function::zn(1); FunctionPtr function = x + y + z; FunctionPtr fbdr = Function::restrictToCellBoundary(function); FunctionPtr vect = Function::vectorize(x, y, z); vector<FunctionPtr> functions; functions.push_back(function); functions.push_back(vect); vector<string> functionNames; functionNames.push_back("function"); functionNames.push_back("vect"); { XDMFExporter exporter(meshTopology, "function3", false); exporter.exportFunction(function, "function3"); } { XDMFExporter exporter(meshTopology, "boundary3", false); exporter.exportFunction(fbdr, "boundary3"); } { XDMFExporter exporter(meshTopology, "vect3", false); exporter.exportFunction(vect, "vect3"); } { XDMFExporter exporter(meshTopology, "functions3", false); exporter.exportFunction(functions, functionNames); } } }
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; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); choice::MpiArgs args( argc, argv ); int rank=mpiSession.getRank(); int numProcs=mpiSession.getNProc(); #else choice::Args args( argc, argv ); int rank = 0; int numProcs = 1; #endif int nCells = args.Input<int>("--nCells", "num cells",2); int numRefs = args.Input<int>("--numRefs","num adaptive refinements",0); double eps = args.Input<double>("--epsilon","diffusion parameter",1e-2); double energyThreshold = args.Input<double>("--energyThreshold","adaptivity thresh",.5); if (rank==0){ cout << "nCells = " << nCells << ", numRefs = " << numRefs << ", eps = " << eps << endl; } //////////////////// 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); //////////////////// 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 * v->grad() - tau->div() ); // robust test norm IPPtr robIP = Teuchos::rcp(new IP); FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(eps) ); FunctionPtr invSqrtH = Teuchos::rcp(new InvSqrtHScaling); robIP->addTerm( ip_scaling * v); robIP->addTerm( ip_scaling/sqrt(eps) * tau ); robIP->addTerm( sqrt(eps) * v->grad() ); robIP->addTerm( beta * v->grad() ); robIP->addTerm( tau->div() ); /* robIP->addTerm(v); robIP->addTerm(v->grad()); robIP->addTerm(tau->div()); robIP->addTerm(invSqrtH*tau); */ FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); // see what effect this has // robIP->addZeroMeanTerm( h2_scaling*v ); //////////////////// 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(beta) ); SpatialFilterPtr inflowBoundary = Teuchos::rcp( new InflowSquareBoundary ); SpatialFilterPtr outflowBoundary = Teuchos::rcp( new OutflowSquareBoundary); FunctionPtr u_exact = Teuchos::rcp( new Uex(eps,0) ); FunctionPtr sig1_exact = Teuchos::rcp( new Uex(eps,1) ); FunctionPtr sig2_exact = Teuchos::rcp( new Uex(eps,2) ); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); vector<double> e1(2); // (1,0) vector<double> e2(2); // (0,1) e1[0] = 1; e2[1] = 1; FunctionPtr sigma = sig1_exact*e1 + sig2_exact*e2; bc->addDirichlet(uhat, outflowBoundary, zero); bc->addDirichlet(beta_n_u_minus_sigma_n, inflowBoundary, beta*n*u_exact-sigma*n); // bc->addDirichlet(beta_n_u_minus_sigma_n, inflowBoundary, beta*n*u_exact); // ignoring sigma FunctionPtr u_disc = Teuchos::rcp( new Udisc ); // bc->addDirichlet(beta_n_u_minus_sigma_n, inflowBoundary, beta*n*u_disc); // bc->addDirichlet(uhat, inflowBoundary, u_exact); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int H1Order = 2, pToAdd = 3; int horizontalCells = nCells, verticalCells = nCells; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = MeshUtilities::buildUnitQuadMesh(nCells,confusionBF, H1Order, H1Order+pToAdd); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution; solution = Teuchos::rcp( new Solution(mesh, bc, rhs, robIP) ); // solution = Teuchos::rcp( new Solution(mesh, bc, rhs, qoptIP) ); if (enforceLocalConservation) { FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); solution->lagrangeConstraints()->addConstraint(beta_n_u_minus_sigma_n == zero); } RefinementStrategy refinementStrategy( solution, energyThreshold ); ofstream convOut; stringstream convOutFile; convOutFile << "erickson_conv_" << round(-log(eps)/log(10.0)) <<".txt"; convOut.open(convOutFile.str().c_str()); for (int refIndex=0; refIndex < numRefs; refIndex++){ solution->condensedSolve(false); // solution->solve(false); double quadTol = 1e-7; int cubEnrich = 25; FunctionPtr u_soln = Teuchos::rcp( new PreviousSolutionFunction(solution, u) ); FunctionPtr sigma1_soln = Teuchos::rcp( new PreviousSolutionFunction(solution, sigma1) ); FunctionPtr sigma2_soln = Teuchos::rcp( new PreviousSolutionFunction(solution, sigma2) ); FunctionPtr u_diff = (u_soln - u_exact)*(u_soln - u_exact); FunctionPtr sig1_diff = (sigma1_soln - sig1_exact)*(sigma1_soln - sig1_exact); FunctionPtr sig2_diff = (sigma2_soln - sig2_exact)*(sigma2_soln - sig2_exact); double u_L2_error = u_diff->integrate(mesh,cubEnrich); double sigma_L2_error = sig1_diff->integrate(mesh,cubEnrich) + sig2_diff->integrate(mesh,cubEnrich); double L2_error = sqrt(u_L2_error + sigma_L2_error); double energy_error = solution->energyErrorTotal(); u_soln->writeValuesToMATLABFile(mesh, "u_soln.m"); u_diff->writeValuesToMATLABFile(mesh, "u_diff.m"); u_exact->writeValuesToMATLABFile(mesh, "u_exact.m"); sig1_exact->writeValuesToMATLABFile(mesh, "s1_exact.m"); sig2_exact->writeValuesToMATLABFile(mesh, "s2_exact.m"); convOut << mesh->numGlobalDofs() << " " << L2_error << " " << energy_error << endl; if (rank==0){ cout << "L2 error = " << L2_error << ", energy error = " << energy_error << ", ratio = " << L2_error/energy_error << endl; cout << "u squared L2 error = " << u_L2_error << ", sigma squared l2 error = " << sigma_L2_error << ", num dofs = " << mesh->numGlobalDofs() << endl; } refinementStrategy.refine(rank==0); // print to console on rank 0 } convOut.close(); // one more solve on the final refined mesh: solution->condensedSolve(false); VTKExporter exporter(solution, mesh, varFactory); if (rank==0){ exporter.exportSolution("robustIP"); cout << endl; } return 0; /* // determine trialIDs vector< int > trialIDs = mesh->bilinearForm()->trialIDs(); vector< int > fieldIDs; vector< int > fluxIDs; vector< int >::iterator idIt; for (idIt = trialIDs.begin();idIt!=trialIDs.end();idIt++){ int trialID = *(idIt); if (!mesh->bilinearForm()->isFluxOrTrace(trialID)){ // if field fieldIDs.push_back(trialID); } else { fluxIDs.push_back(trialID); } } int numFieldInds = 0; map<int,vector<int> > globalFluxInds; // from cellID to localDofInd vector map<int,vector<int> > globalFieldInds; // from cellID to localDofInd vector map<int,vector<int> > localFieldInds; // from cellID to localDofInd vector map<int,vector<int> > localFluxInds; // from cellID to localDofInd vector set<int> allFluxInds; // unique set of all flux inds mesh->getDofIndices(allFluxInds,globalFluxInds,globalFieldInds,localFluxInds,localFieldInds); if (rank==0){ vector< ElementPtr > activeElems = mesh->activeElements(); vector< ElementPtr >::iterator elemIt; cout << "num flux dofs = " << allFluxInds.size() << endl; cout << "num field dofs = " << mesh->numFieldDofs() << endl; cout << "num flux dofs = " << mesh->numFluxDofs() << endl; elemIt = activeElems.begin(); int cellID = (*elemIt)->cellID(); cout << "num LOCAL field dofs = " << localFieldInds[cellID].size() << endl; ofstream fieldInds; fieldInds.open("fieldInds.dat"); for (elemIt = activeElems.begin();elemIt!=activeElems.end();elemIt++){ int cellID = (*elemIt)->cellID(); vector<int> inds = globalFieldInds[cellID]; vector<int> locFieldInds = localFieldInds[cellID]; cout << "local field inds for cell ID " << cellID << endl; for (int i = 0;i<inds.size();++i){ fieldInds << inds[i]+1 << endl; cout << locFieldInds[i] << endl; } vector<int> finds = globalFluxInds[cellID]; vector<int> locFluxInds = localFluxInds[cellID]; cout << "local flux inds for cell ID " << cellID << endl; for (int i = 0;i<finds.size();++i){ cout << locFluxInds[i] << endl; } cout << "global flux inds for cell ID " << cellID << endl; for (int i = 0;i<finds.size();++i){ cout << globalFluxInds[cellID][i] << endl; } } fieldInds.close(); ofstream fluxInds; fluxInds.open("fluxInds.dat"); set<int>::iterator fluxIt; for (fluxIt = allFluxInds.begin();fluxIt!=allFluxInds.end();fluxIt++){ fluxInds << (*fluxIt)+1 << endl; // offset by 1 for matlab } fluxInds.close(); } 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 commRank = Teuchos::GlobalMPISession::getRank(); int numProcs = Teuchos::GlobalMPISession::getNProc(); // Required arguments double epsilon = args.Input<double>("--epsilon", "diffusion parameter"); int numRefs = args.Input<int>("--numRefs", "number of refinement steps"); bool enforceLocalConservation = args.Input<bool>("--conserve", "enforce local conservation"); bool graphNorm = args.Input<bool>("--graphNorm", "use the graph norm rather than robust test norm"); // Optional arguments (have defaults) bool highLiftAirfoil = args.Input("--highLift", "use high lift airfoil rather than NACA0012", false); args.Process(); //////////////////// 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("uhat"); VarPtr beta_n_u_minus_sigma_n = varFactory.fluxVar("fhat"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma = varFactory.fieldVar("sigma", VECTOR_L2); vector<double> beta; beta.push_back(1.0); beta.push_back(0.25); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // tau terms: bf->addTerm(sigma / epsilon, tau); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma, v->grad() ); bf->addTerm( beta * u, - v->grad() ); bf->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = Teuchos::rcp(new IP); if (graphNorm) { ip = bf->graphNorm(); } else { // robust test norm FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); if (!enforceLocalConservation) ip->addTerm( ip_scaling * v ); ip->addTerm( sqrt(epsilon) * v->grad() ); // Weight these two terms for inflow ip->addTerm( beta * v->grad() ); ip->addTerm( tau->div() ); ip->addTerm( ip_scaling/sqrt(epsilon) * tau ); if (enforceLocalConservation) ip->addZeroMeanTerm( v ); } //////////////////// SPECIFY RHS /////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr f = Teuchos::rcp( new ConstantScalarFunction(0.0) ); rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////// CREATE BCs /////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp( new PenaltyConstraints ); SpatialFilterPtr lBoundary = Teuchos::rcp( new LeftBoundary ); SpatialFilterPtr tBoundary = Teuchos::rcp( new TopBoundary ); SpatialFilterPtr bBoundary = Teuchos::rcp( new BottomBoundary ); SpatialFilterPtr rBoundary = Teuchos::rcp( new RightBoundary ); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); SpatialFilterPtr airfoilInflowBoundary = Teuchos::rcp( new AirfoilInflowBoundary(beta) ); SpatialFilterPtr airfoilOutflowBoundary = Teuchos::rcp( new AirfoilOutflowBoundary(beta) ); FunctionPtr u0 = Teuchos::rcp( new ZeroBC ); FunctionPtr u1 = Teuchos::rcp( new OneBC ); bc->addDirichlet(beta_n_u_minus_sigma_n, lBoundary, u0); bc->addDirichlet(beta_n_u_minus_sigma_n, bBoundary, u0); // bc->addDirichlet(uhat, airfoilInflowBoundary, u1); // bc->addDirichlet(uhat, tBoundary, u0); bc->addDirichlet(beta_n_u_minus_sigma_n, airfoilInflowBoundary, beta*n*u1); bc->addDirichlet(uhat, airfoilOutflowBoundary, u1); // pc->addConstraint(beta*uhat->times_normal() - beta_n_u_minus_sigma_n == u0, rBoundary); // pc->addConstraint(beta*uhat->times_normal() - beta_n_u_minus_sigma_n == u0, tBoundary); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int H1Order = 3, pToAdd = 2; Teuchos::RCP<Mesh> mesh; if (highLiftAirfoil) mesh = Mesh::readTriangle(Camellia_MeshDir+"HighLift/HighLift.1", bf, H1Order, pToAdd); else mesh = Mesh::readTriangle(Camellia_MeshDir+"NACA0012/NACA0012.1", bf, H1Order, pToAdd); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); // 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 ); VTKExporter exporter(solution, mesh, varFactory); for (int refIndex=0; refIndex<=numRefs; refIndex++) { solution->solve(false); if (commRank == 0) { stringstream outfile; if (highLiftAirfoil) outfile << "highlift_" << refIndex; else outfile << "naca0012_" << refIndex; exporter.exportSolution(outfile.str()); // Check local conservation FunctionPtr flux = Teuchos::rcp( new PreviousSolutionFunction(solution, beta_n_u_minus_sigma_n) ); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); Teuchos::Tuple<double, 3> fluxImbalances = checkConservation(flux, zero, varFactory, mesh); cout << "Mass flux: Largest Local = " << fluxImbalances[0] << ", Global = " << fluxImbalances[1] << ", Sum Abs = " << fluxImbalances[2] << endl; } if (refIndex < numRefs) { // refinementStrategy.refine(commRank==0); // print to console on commRank 0 // Try pseudo-hp adaptive vector<int> cellsToRefine; vector<int> cells_h; vector<int> cells_p; refinementStrategy.getCellsAboveErrorThreshhold(cellsToRefine); for (int i=0; i < cellsToRefine.size(); i++) if (sqrt(mesh->getCellMeasure(cellsToRefine[i])) < epsilon) { int pOrder = mesh->cellPolyOrder(cellsToRefine[i]); if (pOrder < 8) cells_p.push_back(cellsToRefine[i]); else cells_h.push_back(cellsToRefine[i]); } else cells_h.push_back(cellsToRefine[i]); refinementStrategy.pRefineCells(mesh, cells_p); refinementStrategy.hRefineCells(mesh, cells_h); } } 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; }
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; }
PoissonFormulation::PoissonFormulation(int spaceDim, bool useConformingTraces, PoissonFormulationChoice formulationChoice) { _spaceDim = spaceDim; if (formulationChoice == ULTRAWEAK) { Space tauSpace = (spaceDim > 1) ? HDIV : HGRAD; Space phi_hat_space = useConformingTraces ? HGRAD : L2; Space psiSpace = (spaceDim > 1) ? VECTOR_L2 : L2; // fields VarPtr phi; VarPtr psi; // traces VarPtr phi_hat, psi_n_hat; // tests VarPtr q; VarPtr tau; VarFactoryPtr vf = VarFactory::varFactory(); phi = vf->fieldVar(S_PHI); psi = vf->fieldVar(S_PSI, psiSpace); TFunctionPtr<double> parity = TFunction<double>::sideParity(); if (spaceDim > 1) phi_hat = vf->traceVar(S_PHI_HAT, phi, phi_hat_space); else phi_hat = vf->fluxVar(S_PHI_HAT, phi * (Function::normal_1D() * parity), phi_hat_space); // for spaceDim==1, the "normal" component is in the flux-ness of phi_hat (it's a plus or minus 1) TFunctionPtr<double> n = TFunction<double>::normal(); if (spaceDim > 1) psi_n_hat = vf->fluxVar(S_PSI_N_HAT, psi * (n * parity)); else psi_n_hat = vf->fluxVar(S_PSI_N_HAT, psi * (Function::normal_1D() * parity)); q = vf->testVar(S_Q, HGRAD); tau = vf->testVar(S_TAU, tauSpace); _poissonBF = Teuchos::rcp( new BF(vf) ); if (spaceDim==1) { // for spaceDim==1, the "normal" component is in the flux-ness of phi_hat (it's a plus or minus 1) _poissonBF->addTerm(phi, tau->dx()); _poissonBF->addTerm(psi, tau); _poissonBF->addTerm(-phi_hat, tau); _poissonBF->addTerm(-psi, q->dx()); _poissonBF->addTerm(psi_n_hat, q); } else { _poissonBF->addTerm(phi, tau->div()); _poissonBF->addTerm(psi, tau); _poissonBF->addTerm(-phi_hat, tau->dot_normal()); _poissonBF->addTerm(-psi, q->grad()); _poissonBF->addTerm(psi_n_hat, q); } } else if ((formulationChoice == PRIMAL) || (formulationChoice == CONTINUOUS_GALERKIN)) { // field VarPtr phi; // flux VarPtr psi_n_hat; // tests VarPtr q; VarFactoryPtr vf = VarFactory::varFactory(); phi = vf->fieldVar(S_PHI, HGRAD); TFunctionPtr<double> parity = TFunction<double>::sideParity(); TFunctionPtr<double> n = TFunction<double>::normal(); if (formulationChoice == PRIMAL) { if (spaceDim > 1) psi_n_hat = vf->fluxVar(S_PSI_N_HAT, phi->grad() * (n * parity)); else psi_n_hat = vf->fluxVar(S_PSI_N_HAT, phi->dx() * (Function::normal_1D() * parity)); } q = vf->testVar(S_Q, HGRAD); _poissonBF = BF::bf(vf); _poissonBF->addTerm(-phi->grad(), q->grad()); if (formulationChoice == CONTINUOUS_GALERKIN) { FunctionPtr boundaryIndicator = Function::meshBoundaryCharacteristic(); _poissonBF->addTerm(phi->grad() * n, boundaryIndicator * q); } else // primal { _poissonBF->addTerm(psi_n_hat, q); } } else { TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "Unsupported PoissonFormulationChoice"); } }
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 ); }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); #endif int commRank = Teuchos::GlobalMPISession::getRank(); int numProcs = Teuchos::GlobalMPISession::getNProc(); // { // // 1D tests // CellTopoPtrLegacy line_2 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Line<2> >() ) ); // // let's draw a line // vector<double> v0 = makeVertex(0); // vector<double> v1 = makeVertex(1); // vector<double> v2 = makeVertex(2); // vector< vector<double> > vertices; // vertices.push_back(v0); // vertices.push_back(v1); // vertices.push_back(v2); // vector<unsigned> line1VertexList; // vector<unsigned> line2VertexList; // line1VertexList.push_back(0); // line1VertexList.push_back(1); // line2VertexList.push_back(1); // line2VertexList.push_back(2); // vector< vector<unsigned> > elementVertices; // elementVertices.push_back(line1VertexList); // elementVertices.push_back(line2VertexList); // vector< CellTopoPtrLegacy > cellTopos; // cellTopos.push_back(line_2); // cellTopos.push_back(line_2); // MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); // MeshTopologyPtr meshTopology = Teuchos::rcp( new MeshTopology(meshGeometry) ); // FunctionPtr x = Function::xn(1); // FunctionPtr function = x; // FunctionPtr fbdr = Function::restrictToCellBoundary(function); // vector<FunctionPtr> functions; // functions.push_back(function); // functions.push_back(function); // vector<string> functionNames; // functionNames.push_back("function1"); // functionNames.push_back("function2"); // // { // // HDF5Exporter exporter(mesh, "function1", false); // // exporter.exportFunction(function, "function1"); // // } // // { // // HDF5Exporter exporter(mesh, "boundary1", false); // // exporter.exportFunction(fbdr, "boundary1"); // // } // // { // // HDF5Exporter exporter(mesh, "functions1", false); // // exporter.exportFunction(functions, functionNames); // // } // } { // 2D tests // CellTopoPtrLegacy quad_4 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >() ) ); // CellTopoPtrLegacy tri_3 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Triangle<3> >() ) ); CellTopoPtr quad_4 = CellTopology::quad(); CellTopoPtr tri_3 = CellTopology::triangle(); // let's draw a little house vector<double> v0 = makeVertex(-1,0); vector<double> v1 = makeVertex(1,0); vector<double> v2 = makeVertex(1,2); vector<double> v3 = makeVertex(-1,2); vector<double> v4 = makeVertex(0.0,3); vector< vector<double> > vertices; vertices.push_back(v0); vertices.push_back(v1); vertices.push_back(v2); vertices.push_back(v3); vertices.push_back(v4); vector<unsigned> quadVertexList; quadVertexList.push_back(0); quadVertexList.push_back(1); quadVertexList.push_back(2); quadVertexList.push_back(3); vector<unsigned> triVertexList; triVertexList.push_back(3); triVertexList.push_back(2); triVertexList.push_back(4); vector< vector<unsigned> > elementVertices; elementVertices.push_back(quadVertexList); elementVertices.push_back(triVertexList); // vector< CellTopoPtrLegacy > cellTopos; vector< CellTopoPtr> cellTopos; cellTopos.push_back(quad_4); cellTopos.push_back(tri_3); MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); MeshTopologyPtr meshTopology = Teuchos::rcp( new MeshTopology(meshGeometry) ); //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr vf = VarFactory::varFactory(); VarPtr tau = vf->testVar("tau", HDIV); VarPtr v = vf->testVar("v", HGRAD); // define trial variables VarPtr uhat = vf->traceVar("uhat"); VarPtr fhat = vf->fluxVar("fhat"); VarPtr u = vf->fieldVar("u"); VarPtr sigma = vf->fieldVar("sigma", VECTOR_L2); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr bf = Teuchos::rcp( new BF(vf) ); // tau terms: bf->addTerm(sigma, tau); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma, v->grad() ); bf->addTerm( fhat, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = bf->graphNorm(); //////////////////// SPECIFY RHS /////////////////////// RHSPtr rhs = RHS::rhs(); FunctionPtr one = Function::constant(1.0); rhs->addTerm( one * v ); //////////////////// CREATE BCs /////////////////////// BCPtr bc = BC::bc(); FunctionPtr zero = Function::zero(); SpatialFilterPtr entireBoundary = SpatialFilter::allSpace(); bc->addDirichlet(uhat, entireBoundary, zero); //////////////////// SOLVE & REFINE /////////////////////// // Output solution Intrepid::FieldContainer<GlobalIndexType> savedCellPartition; Teuchos::RCP<Epetra_FEVector> savedLHSVector; { //////////////////// BUILD MESH /////////////////////// int H1Order = 4, pToAdd = 2; Teuchos::RCP<Mesh> mesh = Teuchos::rcp( new Mesh (meshTopology, bf, H1Order, pToAdd) ); Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); solution->solve(false); RefinementStrategy refinementStrategy( solution, 0.2); HDF5Exporter exporter(mesh, "Poisson"); // exporter.exportSolution(solution, vf, 0, 2, cellIDToSubdivision(mesh, 4)); exporter.exportSolution(solution, 0, 2); mesh->saveToHDF5("MeshSave.h5"); solution->saveToHDF5("SolnSave.h5"); solution->save("PoissonProblem"); // int numRefs = 1; // for (int ref = 1; ref <= numRefs; ref++) // { // refinementStrategy.refine(commRank==0); // solution->solve(false); // mesh->saveToHDF5("MeshSave.h5"); // solution->saveToHDF5("SolnSave.h5"); // exporter.exportSolution(solution, vf, ref, 2, cellIDToSubdivision(mesh, 4)); // } mesh->globalDofAssignment()->getPartitions(savedCellPartition); savedLHSVector = solution->getLHSVector(); } { SolutionPtr loadedSolution = Solution::load(bf, "PoissonProblem"); HDF5Exporter exporter(loadedSolution->mesh(), "ProblemLoaded"); // exporter.exportSolution(loadedSolution, vf, 0, 2, cellIDToSubdivision(loadedSolution->mesh(), 4)); exporter.exportSolution(loadedSolution, 0, 2); } // { // MeshPtr loadedMesh = MeshFactory::loadFromHDF5(bf, "Test0.h5"); // Teuchos::RCP<Solution> loadedSolution = Teuchos::rcp( new Solution(loadedMesh, bc, rhs, ip) ); // loadedSolution->solve(false); // HDF5Exporter exporter(loadedMesh, "MeshLoaded"); // exporter.exportSolution(loadedSolution, vf, 0, 2, cellIDToSubdivision(loadedMesh, 4)); // } { MeshPtr loadedMesh = MeshFactory::loadFromHDF5(bf, "MeshSave.h5"); Intrepid::FieldContainer<GlobalIndexType> loadedCellPartition; loadedMesh->globalDofAssignment()->getPartitions(loadedCellPartition); if (loadedCellPartition.size() != savedCellPartition.size()) { cout << "Error: the loaded partition has different size/shape than the saved one.\n"; cout << "loaded size: " << loadedCellPartition.size() << "; saved size: " << savedCellPartition.size() << endl; } else { bool partitionsMatch = true; for (int i=0; i<loadedCellPartition.size(); i++) { if (loadedCellPartition[i] != savedCellPartition[i]) { partitionsMatch = false; break; } } if (partitionsMatch) cout << "Saved and loaded cell partitions match!\n"; else { cout << "Saved and loaded cell partitions differ.\n"; cout << "saved:\n" << savedCellPartition; cout << "loaded:\n" << loadedCellPartition; } } Teuchos::RCP<Solution> loadedSolution = Teuchos::rcp( new Solution(loadedMesh, bc, rhs, ip) ); loadedSolution->loadFromHDF5("SolnSave.h5"); Teuchos::RCP<Epetra_FEVector> loadedLHSVector = loadedSolution->getLHSVector(); if (loadedLHSVector->Map().MinLID() != savedLHSVector->Map().MinLID()) { cout << "On rank " << commRank << ", loaded min LID = " << loadedLHSVector->Map().MinLID(); cout << ", but saved min LID = " << savedLHSVector->Map().MinLID() << endl; } else if (loadedLHSVector->Map().MaxLID() != savedLHSVector->Map().MaxLID()) { cout << "On rank " << commRank << ", loaded max LID = " << loadedLHSVector->Map().MaxLID(); cout << ", but saved max LID = " << savedLHSVector->Map().MaxLID() << endl; } else { bool globalIDsMatch = true; for (int lid = loadedLHSVector->Map().MinLID(); lid <= loadedLHSVector->Map().MaxLID(); lid++) { if (loadedLHSVector->Map().GID(lid) != savedLHSVector->Map().GID(lid)) { globalIDsMatch = false; } } if (! globalIDsMatch) { cout << "On rank " << commRank << ", loaded and saved solution vector maps differ in their global IDs.\n"; } else { cout << "On rank " << commRank << ", loaded and saved solution vector maps match in their global IDs.\n"; } bool entriesMatch = true; double tol = 1e-16; if (loadedLHSVector->Map().MinLID() != loadedLHSVector->Map().MaxLID()) { for (int lid = loadedLHSVector->Map().MinLID(); lid <= loadedLHSVector->Map().MaxLID(); lid++) { double loadedValue = (*loadedLHSVector)[0][lid]; double savedValue = (*savedLHSVector)[0][lid]; double diff = abs( loadedValue - savedValue ); if (diff > tol) { entriesMatch = false; cout << "On rank " << commRank << ", loaded and saved solution vectors differ in entry with lid " << lid; cout << "; loaded value = " << loadedValue << "; saved value = " << savedValue << ".\n"; } } if (entriesMatch) { cout << "On rank " << commRank << ", loaded and saved solution vectors match!\n"; } else { cout << "On rank " << commRank << ", loaded and saved solution vectors do not match.\n"; } } } HDF5Exporter exporter(loadedMesh, "SolutionLoaded"); // exporter.exportSolution(loadedSolution, vf, 0, 2, cellIDToSubdivision(loadedMesh, 4)); exporter.exportSolution(loadedSolution, 0, 2); } } // { // // 3D tests // CellTopoPtrLegacy hex = Teuchos::rcp(new shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<8> >() )); // // let's draw a little box // vector<double> v0 = makeVertex(0,0,0); // vector<double> v1 = makeVertex(1,0,0); // vector<double> v2 = makeVertex(1,1,0); // vector<double> v3 = makeVertex(0,1,0); // vector<double> v4 = makeVertex(0,0,1); // vector<double> v5 = makeVertex(1,0,1); // vector<double> v6 = makeVertex(1,1,1); // vector<double> v7 = makeVertex(0,1,1); // vector< vector<double> > vertices; // vertices.push_back(v0); // vertices.push_back(v1); // vertices.push_back(v2); // vertices.push_back(v3); // vertices.push_back(v4); // vertices.push_back(v5); // vertices.push_back(v6); // vertices.push_back(v7); // vector<unsigned> hexVertexList; // hexVertexList.push_back(0); // hexVertexList.push_back(1); // hexVertexList.push_back(2); // hexVertexList.push_back(3); // hexVertexList.push_back(4); // hexVertexList.push_back(5); // hexVertexList.push_back(6); // hexVertexList.push_back(7); // // vector<unsigned> triVertexList; // // triVertexList.push_back(2); // // triVertexList.push_back(3); // // triVertexList.push_back(4); // vector< vector<unsigned> > elementVertices; // elementVertices.push_back(hexVertexList); // // elementVertices.push_back(triVertexList); // vector< CellTopoPtrLegacy > cellTopos; // cellTopos.push_back(hex); // // cellTopos.push_back(tri_3); // MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); // MeshTopologyPtr meshTopology = Teuchos::rcp( new MeshTopology(meshGeometry) ); // FunctionPtr x = Function::xn(1); // FunctionPtr y = Function::yn(1); // FunctionPtr z = Function::zn(1); // FunctionPtr function = x + y + z; // FunctionPtr fbdr = Function::restrictToCellBoundary(function); // FunctionPtr vect = Function::vectorize(x, y, z); // vector<FunctionPtr> functions; // functions.push_back(function); // functions.push_back(vect); // vector<string> functionNames; // functionNames.push_back("function"); // functionNames.push_back("vect"); // // { // // HDF5Exporter exporter(mesh, "function3", false); // // exporter.exportFunction(function, "function3"); // // } // // { // // HDF5Exporter exporter(mesh, "boundary3", false); // // exporter.exportFunction(fbdr, "boundary3"); // // } // // { // // HDF5Exporter exporter(mesh, "vect3", false); // // exporter.exportFunction(vect, "vect3"); // // } // // { // // HDF5Exporter exporter(mesh, "functions3", false); // // exporter.exportFunction(functions, functionNames); // // } // } }
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 int polyOrder = 2; // define our manufactured solution or problem bilinear form: double epsilon = 1e-3; bool useTriangles = false; int pToAdd = 2; int nCells = 2; if ( argc > 1) { nCells = atoi(argv[1]); if (rank==0) { cout << "numCells = " << nCells << endl; } } int numSteps = 20; if ( argc > 2) { numSteps = atoi(argv[2]); if (rank==0) { cout << "num NR steps = " << numSteps << endl; } } int useHessian = 0; // defaults to "not use" if ( argc > 3) { useHessian = atoi(argv[3]); if (rank==0) { cout << "useHessian = " << useHessian << endl; } } int thresh = numSteps; // threshhold for when to apply linesearch/hessian if ( argc > 4) { thresh = atoi(argv[4]); if (rank==0) { cout << "thresh = " << thresh << endl; } } int H1Order = polyOrder + 1; double energyThreshold = 0.2; // for mesh refinements double nonlinearStepSize = 0.5; double nonlinearRelativeEnergyTolerance = 1e-8; // used to determine convergence of the nonlinear solution //////////////////////////////////////////////////////////////////// // DEFINE VARIABLES //////////////////////////////////////////////////////////////////// // new-style bilinear form definition VarFactory varFactory; VarPtr uhat = varFactory.traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_hat = varFactory.fluxVar("\\widehat{\\beta_n u - \\sigma_n}"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma1 = varFactory.fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory.fieldVar("\\sigma_2"); VarPtr tau = varFactory.testVar("\\tau",HDIV); VarPtr v = varFactory.testVar("v",HGRAD); BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // initialize bilinear form //////////////////////////////////////////////////////////////////// // CREATE MESH //////////////////////////////////////////////////////////////////// // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = MeshUtilities::buildUnitQuadMesh(nCells, bf, H1Order, H1Order+pToAdd); mesh->setPartitionPolicy(Teuchos::rcp(new ZoltanMeshPartitionPolicy("HSFC"))); //////////////////////////////////////////////////////////////////// // INITIALIZE BACKGROUND FLOW FUNCTIONS //////////////////////////////////////////////////////////////////// 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) ); vector<double> e1(2); // (1,0) e1[0] = 1; vector<double> e2(2); // (0,1) e2[1] = 1; FunctionPtr u_prev = Teuchos::rcp( new PreviousSolutionFunction(backgroundFlow, u) ); FunctionPtr beta = e1 * u_prev + Teuchos::rcp( new ConstantVectorFunction( e2 ) ); //////////////////////////////////////////////////////////////////// // DEFINE BILINEAR FORM //////////////////////////////////////////////////////////////////// // tau parts: // 1/eps (sigma, tau)_K + (u, div tau)_K - (u_hat, tau_n)_dK bf->addTerm(sigma1 / epsilon, tau->x()); bf->addTerm(sigma2 / epsilon, tau->y()); bf->addTerm(u, tau->div()); bf->addTerm( - uhat, tau->dot_normal() ); // v: // (sigma, grad v)_K - (sigma_hat_n, v)_dK - (u, beta dot grad v) + (u_hat * n dot beta, v)_dK bf->addTerm( sigma1, v->dx() ); bf->addTerm( sigma2, v->dy() ); bf->addTerm( -u, beta * v->grad()); bf->addTerm( beta_n_u_minus_sigma_hat, v); // ==================== SET INITIAL GUESS ========================== mesh->registerSolution(backgroundFlow); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); FunctionPtr u0 = Teuchos::rcp( new U0 ); map<int, Teuchos::RCP<Function> > functionMap; functionMap[u->ID()] = u0; functionMap[sigma1->ID()] = zero; functionMap[sigma2->ID()] = zero; backgroundFlow->projectOntoMesh(functionMap); // ==================== END SET INITIAL GUESS ========================== //////////////////////////////////////////////////////////////////// // DEFINE INNER PRODUCT //////////////////////////////////////////////////////////////////// // function to scale the squared guy by epsilon/h FunctionPtr epsilonOverHScaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); IPPtr ip = Teuchos::rcp( new IP ); ip->addTerm( epsilonOverHScaling * (1.0/sqrt(epsilon))* tau); ip->addTerm( tau->div()); // ip->addTerm( epsilonOverHScaling * v ); ip->addTerm( v ); ip->addTerm( sqrt(epsilon) * v->grad() ); ip->addTerm(v->grad()); // ip->addTerm( beta * v->grad() ); //////////////////////////////////////////////////////////////////// // DEFINE RHS //////////////////////////////////////////////////////////////////// RHSPtr rhs = RHS::rhs(); FunctionPtr u_prev_squared_div2 = 0.5 * u_prev * u_prev; rhs->addTerm((e1 * u_prev_squared_div2 + e2 * u_prev) * v->grad() - u_prev * tau->div()); //////////////////////////////////////////////////////////////////// // DEFINE DIRICHLET BC //////////////////////////////////////////////////////////////////// FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); SpatialFilterPtr outflowBoundary = Teuchos::rcp( new TopBoundary); SpatialFilterPtr inflowBoundary = Teuchos::rcp( new NegatedSpatialFilter(outflowBoundary) ); BCPtr inflowBC = BC::bc(); FunctionPtr u0_squared_div_2 = 0.5 * u0 * u0; inflowBC->addDirichlet(beta_n_u_minus_sigma_hat,inflowBoundary, ( e1 * u0_squared_div_2 + e2 * u0) * n ); //////////////////////////////////////////////////////////////////// // CREATE SOLUTION OBJECT //////////////////////////////////////////////////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp(new Solution(mesh, inflowBC, rhs, ip)); mesh->registerSolution(solution); //////////////////////////////////////////////////////////////////// // WARNING: UNFINISHED HESSIAN BIT //////////////////////////////////////////////////////////////////// VarFactory hessianVars = varFactory.getBubnovFactory(VarFactory::BUBNOV_TRIAL); VarPtr du = hessianVars.test(u->ID()); BFPtr hessianBF = Teuchos::rcp( new BF(hessianVars) ); // initialize bilinear form // FunctionPtr e_v = Function::constant(1.0); // dummy error rep function for now - should do nothing FunctionPtr u_current = Teuchos::rcp( new PreviousSolutionFunction(solution, u) ); FunctionPtr sig1_prev = Teuchos::rcp( new PreviousSolutionFunction(solution, sigma1) ); FunctionPtr sig2_prev = Teuchos::rcp( new PreviousSolutionFunction(solution, sigma2) ); FunctionPtr sig_prev = (e1*sig1_prev + e2*sig2_prev); FunctionPtr fnhat = Teuchos::rcp(new PreviousSolutionFunction(solution,beta_n_u_minus_sigma_hat)); FunctionPtr uhat_prev = Teuchos::rcp(new PreviousSolutionFunction(solution,uhat)); LinearTermPtr residual = Teuchos::rcp(new LinearTerm);// residual residual->addTerm(fnhat*v - (e1 * (u_prev_squared_div2 - sig1_prev) + e2 * (u_prev - sig2_prev)) * v->grad()); residual->addTerm((1/epsilon)*sig_prev * tau + u_prev * tau->div() - uhat_prev*tau->dot_normal()); LinearTermPtr Bdu = Teuchos::rcp(new LinearTerm);// residual Bdu->addTerm( u_current*tau->div() - u_current*(beta*v->grad())); Teuchos::RCP<RieszRep> riesz = Teuchos::rcp(new RieszRep(mesh, ip, residual)); Teuchos::RCP<RieszRep> duRiesz = Teuchos::rcp(new RieszRep(mesh, ip, Bdu)); riesz->computeRieszRep(); FunctionPtr e_v = Teuchos::rcp(new RepFunction(v,riesz)); e_v->writeValuesToMATLABFile(mesh, "e_v.m"); FunctionPtr posErrPart = Teuchos::rcp(new PositivePart(e_v->dx())); hessianBF->addTerm(e_v->dx()*u,du); // hessianBF->addTerm(posErrPart*u,du); Teuchos::RCP<HessianFilter> hessianFilter = Teuchos::rcp(new HessianFilter(hessianBF)); if (useHessian) { solution->setWriteMatrixToFile(true,"hessianStiffness.dat"); } else { solution->setWriteMatrixToFile(true,"stiffness.dat"); } Teuchos::RCP< LineSearchStep > LS_Step = Teuchos::rcp(new LineSearchStep(riesz)); ofstream out; out.open("Burgers.txt"); double NL_residual = 9e99; for (int i = 0; i<numSteps; i++) { solution->solve(false); // do one solve to initialize things... double stepLength = 1.0; stepLength = LS_Step->stepSize(backgroundFlow,solution, NL_residual); if (useHessian) { solution->setFilter(hessianFilter); } backgroundFlow->addSolution(solution,stepLength); NL_residual = LS_Step->getNLResidual(); if (rank==0) { cout << "NL residual after adding = " << NL_residual << " with step size " << stepLength << endl; out << NL_residual << endl; // saves initial NL error } } out.close(); //////////////////////////////////////////////////////////////////// // DEFINE REFINEMENT STRATEGY //////////////////////////////////////////////////////////////////// Teuchos::RCP<RefinementStrategy> refinementStrategy; refinementStrategy = Teuchos::rcp(new RefinementStrategy(solution,energyThreshold)); int numRefs = 0; Teuchos::RCP<NonlinearStepSize> stepSize = Teuchos::rcp(new NonlinearStepSize(nonlinearStepSize)); Teuchos::RCP<NonlinearSolveStrategy> solveStrategy; solveStrategy = Teuchos::rcp( new NonlinearSolveStrategy(backgroundFlow, solution, stepSize, nonlinearRelativeEnergyTolerance)); //////////////////////////////////////////////////////////////////// // SOLVE //////////////////////////////////////////////////////////////////// for (int refIndex=0; refIndex<numRefs; refIndex++) { solveStrategy->solve(rank==0); // print to console on rank 0 refinementStrategy->refine(rank==0); // print to console on rank 0 } // solveStrategy->solve(rank==0); if (rank==0) { backgroundFlow->writeToVTK("Burgers.vtu",min(H1Order+1,4)); solution->writeFluxesToFile(uhat->ID(), "burgers.dat"); cout << "wrote solution files" << 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 commRank = Teuchos::GlobalMPISession::getRank(); int numProcs = Teuchos::GlobalMPISession::getNProc(); // Required arguments double epsilon = args.Input<double>("--epsilon", "diffusion parameter"); int numRefs = args.Input<int>("--numRefs", "number of refinement steps"); bool enforceLocalConservation = args.Input<bool>("--conserve", "enforce local conservation"); int norm = args.Input<int>("--norm", "0 = graph\n 1 = robust\n 2 = modified robust"); // Optional arguments (have defaults) bool zeroL2 = args.Input("--zeroL2", "take L2 term on v in robust norm to zero", false); args.Process(); //////////////////// 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 sigma = varFactory.fieldVar("sigma", VECTOR_L2); vector<double> beta; beta.push_back(1.0); beta.push_back(0.0); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // tau terms: bf->addTerm(sigma / epsilon, tau); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma, v->grad() ); bf->addTerm( beta * u, - v->grad() ); bf->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = Teuchos::rcp(new IP); if (norm == 0) { ip = bf->graphNorm(); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); ip->addZeroMeanTerm( h2_scaling*v ); } // Robust norm else if (norm == 1) { // robust test norm FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); if (!zeroL2) ip->addTerm( v ); ip->addTerm( sqrt(epsilon) * v->grad() ); // Weight these two terms for inflow ip->addTerm( beta * v->grad() ); ip->addTerm( tau->div() ); ip->addTerm( ip_scaling/sqrt(epsilon) * tau ); if (zeroL2) ip->addZeroMeanTerm( h2_scaling*v ); } // Modified robust norm else if (norm == 2) { // robust test norm FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); // FunctionPtr ip_weight = Teuchos::rcp( new IPWeight() ); if (!zeroL2) ip->addTerm( v ); ip->addTerm( sqrt(epsilon) * v->grad() ); ip->addTerm( beta * v->grad() ); ip->addTerm( tau->div() - beta*v->grad() ); ip->addTerm( ip_scaling/sqrt(epsilon) * tau ); if (zeroL2) ip->addZeroMeanTerm( h2_scaling*v ); } // // robust test norm // IPPtr robIP = Teuchos::rcp(new IP); // FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); // if (!enforceLocalConservation) // robIP->addTerm( ip_scaling * v ); // robIP->addTerm( sqrt(epsilon) * v->grad() ); // // Weight these two terms for inflow // FunctionPtr ip_weight = Teuchos::rcp( new IPWeight() ); // robIP->addTerm( ip_weight * beta * v->grad() ); // robIP->addTerm( ip_weight * tau->div() ); // robIP->addTerm( ip_scaling/sqrt(epsilon) * tau ); // if (enforceLocalConservation) // robIP->addZeroMeanTerm( v ); //////////////////// SPECIFY RHS /////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr f = Teuchos::rcp( new ConstantScalarFunction(0.0) ); rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////// CREATE BCs /////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp( new PenaltyConstraints ); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); FunctionPtr one = Teuchos::rcp( new ConstantScalarFunction(1.0) ); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); SpatialFilterPtr lBoundary = Teuchos::rcp( new LeftBoundary ); SpatialFilterPtr tbBoundary = Teuchos::rcp( new TopBottomBoundary ); SpatialFilterPtr rBoundary = Teuchos::rcp( new RightBoundary ); // SpatialFilterPtr leftCircleBoundary = Teuchos::rcp( new LeftCircleBoundary ); // SpatialFilterPtr rightCircleBoundary = Teuchos::rcp( new RightCircleBoundary ); SpatialFilterPtr circleBoundary = Teuchos::rcp( new CircleBoundary ); bc->addDirichlet(beta_n_u_minus_sigma_n, lBoundary, zero); bc->addDirichlet(beta_n_u_minus_sigma_n, tbBoundary, zero); pc->addConstraint(beta*uhat->times_normal() - beta_n_u_minus_sigma_n == zero, rBoundary); // bc->addDirichlet(uhat, leftCircleBoundary, one); // bc->addDirichlet(beta_n_u_minus_sigma_n, rightCircleBoundary, beta*n*one); bc->addDirichlet(uhat, circleBoundary, one); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int H1Order = 3, pToAdd = 2; Teuchos::RCP<Mesh> mesh; mesh = MeshFactory::shiftedHemkerMesh(-3, 9, 6, 1, bf, H1Order, pToAdd); // mesh = BuildHemkerMesh(bf, nseg, circleMesh, triangulateMesh, H1Order, pToAdd); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); 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.25; // for mesh refinements RefinementStrategy refinementStrategy( solution, energyThreshold ); Teuchos::RCP<RefinementHistory> refHistory = Teuchos::rcp( new RefinementHistory ); mesh->registerObserver(refHistory); #ifdef saveVTK VTKExporter exporter(solution, mesh, varFactory); #endif ofstream errOut; if (commRank == 0) errOut.open("hemker_err.txt"); for (int refIndex=0; refIndex<=numRefs; refIndex++) { solution->solve(false); double energy_error = solution->energyErrorTotal(); if (commRank==0) { stringstream outfile; outfile << "hemker_" << refIndex; #ifdef saveVTK exporter.exportSolution(outfile.str()); #endif // Check local conservation FunctionPtr flux = Teuchos::rcp( new PreviousSolutionFunction(solution, beta_n_u_minus_sigma_n) ); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); Teuchos::Tuple<double, 3> fluxImbalances = checkConservation(flux, zero, varFactory, mesh); cout << "Mass flux: Largest Local = " << fluxImbalances[0] << ", Global = " << fluxImbalances[1] << ", Sum Abs = " << fluxImbalances[2] << endl; errOut << mesh->numGlobalDofs() << " " << energy_error << " " << fluxImbalances[0] << " " << fluxImbalances[1] << " " << fluxImbalances[2] << endl; } if (refIndex < numRefs) refinementStrategy.refine(commRank==0); // print to console on commRank 0 } if (commRank == 0) errOut.close(); return 0; }
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; beta_const.push_back(1.0); beta_const.push_back(0.0); // FunctionPtr beta = Teuchos::rcp(new Beta()); double eps = 1e-2; //////////////////// 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) /////////////////////// // mathematician's norm IPPtr mathIP = Teuchos::rcp(new IP()); mathIP->addTerm(tau); mathIP->addTerm(tau->div()); mathIP->addTerm(v); mathIP->addTerm(v->grad()); // 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() ); robIP->addTerm( beta_const * v->grad() ); robIP->addTerm( tau->div() ); robIP->addTerm( 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 ); SpatialFilterPtr inflowTop = Teuchos::rcp(new InflowLshapeTop); SpatialFilterPtr inflowBot = Teuchos::rcp(new InflowLshapeBottom); SpatialFilterPtr LshapeBot1 = Teuchos::rcp(new LshapeBottom1); SpatialFilterPtr LshapeBot2 = Teuchos::rcp(new LshapeBottom2); SpatialFilterPtr Top = Teuchos::rcp(new LshapeTop); SpatialFilterPtr Out = Teuchos::rcp(new LshapeOutflow); FunctionPtr u0 = Teuchos::rcp( new U0 ); bc->addDirichlet(uhat, LshapeBot1, u0); bc->addDirichlet(uhat, LshapeBot2, u0); bc->addDirichlet(uhat, Top, u0); bc->addDirichlet(uhat, Out, u0); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); // bc->addDirichlet(uhat, inflowBot, u0); FunctionPtr u0Top = Teuchos::rcp(new ParabolicProfile); FunctionPtr u0Bot = Teuchos::rcp(new LinearProfile); bc->addDirichlet(beta_n_u_minus_sigma_n, inflowTop, beta_const*n*u0Top); // bc->addDirichlet(beta_n_u_minus_sigma_n, inflowBot, beta_const*n*u0Bot); bc->addDirichlet(beta_n_u_minus_sigma_n, inflowBot, beta_const*n*zero); //////////////////// 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 horizontalCells = 1, verticalCells = 1; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = Mesh::buildQuadMesh(quadPoints, horizontalCells, verticalCells, confusionBF, H1Order, H1Order+pToAdd); */ Teuchos::RCP<Mesh> mesh; // L-shaped domain for double ramp problem FieldContainer<double> A(2), B(2), C(2), D(2), E(2), F(2), G(2), H(2); A(0) = 0.0; A(1) = 0.5; B(0) = 0.0; B(1) = 1.0; C(0) = 0.5; C(1) = 1.0; D(0) = 1.0; D(1) = 1.0; E(0) = 1.0; E(1) = 0.5; F(0) = 1.0; F(1) = 0.0; G(0) = 0.5; G(1) = 0.0; H(0) = 0.5; H(1) = 0.5; vector<FieldContainer<double> > vertices; vertices.push_back(A); int A_index = 0; vertices.push_back(B); int B_index = 1; vertices.push_back(C); int C_index = 2; vertices.push_back(D); int D_index = 3; vertices.push_back(E); int E_index = 4; vertices.push_back(F); int F_index = 5; vertices.push_back(G); int G_index = 6; vertices.push_back(H); int H_index = 7; vector< vector<int> > elementVertices; vector<int> el1, el2, el3, el4, el5; // left patch: el1.push_back(A_index); el1.push_back(H_index); el1.push_back(C_index); el1.push_back(B_index); // top right: el2.push_back(H_index); el2.push_back(E_index); el2.push_back(D_index); el2.push_back(C_index); // bottom right: el3.push_back(G_index); el3.push_back(F_index); el3.push_back(E_index); el3.push_back(H_index); elementVertices.push_back(el1); elementVertices.push_back(el2); elementVertices.push_back(el3); mesh = Teuchos::rcp( new Mesh(vertices, elementVertices, confusionBF, H1Order, pToAdd) ); //////////////////// SOLVE & REFINE /////////////////////// // Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, qoptIP) ); 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 = 8; 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("step.vtu",min(H1Order+1,4)); solution->writeFluxesToFile(uhat->ID(), "uhat.dat"); cout << "wrote files: u.m, uhat.dat\n"; } return 0; }
int main(int argc, char *argv[]) { Teuchos::GlobalMPISession mpiSession(&argc, &argv, 0); int spaceDim = 2; int meshWidth = 2; bool conformingTraces = true; int H1Order = 2, delta_k = 3; double domainWidth = 1.0e-3; bool diagScaling = false; double h = domainWidth / meshWidth; double weight = h / 4.0; // ratio of area of square with sidelength h to its perimeter double sigma_weight = 1.0; // h / 4.0; // sigma = sigma_weight * u->grad() Space uHatSpace = conformingTraces ? HGRAD : L2; VarFactoryPtr vf = VarFactory::varFactory(); // fields VarPtr u = vf->fieldVar("u"); VarPtr sigma = vf->fieldVar("sigma", VECTOR_L2); // traces VarPtr u_hat = vf->traceVar("u_hat", uHatSpace); VarPtr sigma_n = vf->fluxVar("sigma_n"); // tests VarPtr v = vf->testVar("v", HGRAD); VarPtr tau = vf->testVar("tau", HDIV); BFPtr bf = BF::bf(vf); // standard BF: // bf->addTerm(sigma, v->grad()); // bf->addTerm(sigma_n, v); // // bf->addTerm(sigma, tau); // bf->addTerm(u, tau->div()); // bf->addTerm(-u_hat, tau->dot_normal()); // weighted BF: bf->addTerm(sigma, v->grad()); bf->addTerm(weight * sigma_n, v); bf->addTerm(sigma, tau); bf->addTerm(sigma_weight * u, tau->div()); bf->addTerm(- sigma_weight * weight * u_hat, tau->dot_normal()); IPPtr ip = IP::ip(); // standard IP: ip->addTerm(tau + v->grad()); ip->addTerm(tau->div()); ip->addTerm(v); ip->addTerm(tau); // weighted IP: // ip->addTerm(tau + v->grad()); // ip->addTerm(sigma_weight * tau->div()); // ip->addTerm(max(sigma_weight,1e-3) * v); // ip->addTerm(sigma_weight * weight * tau); BCPtr bc = BC::bc(); bc->addDirichlet(u_hat, SpatialFilter::allSpace(), Function::zero()); RHSPtr rhs = RHS::rhs(); rhs->addTerm(1.0 * sigma_weight * v); vector<double> dimensions(spaceDim,domainWidth); vector<int> elementCounts(spaceDim,meshWidth); MeshPtr mesh = MeshFactory::rectilinearMesh(bf, dimensions, elementCounts, H1Order, delta_k); SolutionPtr soln = Solution::solution(mesh, bc, rhs, ip); soln->setUseCondensedSolve(true); soln->initializeLHSVector(); soln->initializeStiffnessAndLoad(); soln->populateStiffnessAndLoad(); Teuchos::RCP<Epetra_RowMatrix> stiffness = soln->getStiffnessMatrix(); double condNumber = conditionNumberLAPACK(*stiffness, diagScaling); cout << "condest (1-norm): " << condNumber << endl; return 0; }
bool VectorizedBasisTestSuite::testPoisson() { bool success = true; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr tau = varFactory->testVar("\\tau", HDIV); VarPtr v = varFactory->testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory->traceVar("\\widehat{u}"); VarPtr sigma_n = varFactory->fluxVar("\\widehat{\\sigma_{n}}"); VarPtr u = varFactory->fieldVar("u"); VarPtr sigma = varFactory->fieldVar("\\sigma", VECTOR_L2); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // tau terms: bf->addTerm(sigma, tau); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma, v->grad() ); bf->addTerm( -sigma_n, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = bf->graphNorm(); //////////////////// SPECIFY RHS /////////////////////// RHSPtr rhs = RHS::rhs(); FunctionPtr f = Function::constant(1.0); rhs->addTerm( f * v ); //////////////////// CREATE BCs /////////////////////// BCPtr bc = BC::bc(); SpatialFilterPtr boundary = SpatialFilter::allSpace(); FunctionPtr zero = Function::zero(); bc->addDirichlet(uhat, boundary, zero); //////////////////// BUILD MESH /////////////////////// int H1Order = 3, pToAdd = 2; // define nodes for mesh FieldContainer<double> meshBoundary(4,2); meshBoundary(0,0) = 0.0; // x1 meshBoundary(0,1) = 0.0; // y1 meshBoundary(1,0) = 1.0; meshBoundary(1,1) = 0.0; meshBoundary(2,0) = 1.0; meshBoundary(2,1) = 1.0; meshBoundary(3,0) = 0.0; meshBoundary(3,1) = 1.0; int horizontalCells = 1, verticalCells = 1; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = MeshFactory::buildQuadMesh(meshBoundary, horizontalCells, verticalCells, bf, H1Order, H1Order+pToAdd, false); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); double energyThreshold = 0.2; // for mesh refinements RefinementStrategy refinementStrategy( solution, energyThreshold ); #ifdef USE_VTK VTKExporter exporter(solution, mesh, varFactory); #endif for (int refIndex=0; refIndex<=4; refIndex++) { solution->solve(false); #ifdef USE_VTK // output commented out because it's not properly part of the test. // stringstream outfile; // outfile << "test_" << refIndex; // exporter.exportSolution(outfile.str()); #endif if (refIndex < 4) refinementStrategy.refine(false); // don't print to console } return success; }
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; }
bool LinearTermTests::testMixedTermConsistency() { bool success = true; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr tau = varFactory->testVar("\\tau", HDIV); VarPtr v = varFactory->testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory->traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_n = varFactory->fluxVar("\\widehat{\\beta \\cdot n u - \\sigma_{n}}"); VarPtr u = varFactory->fieldVar("u"); VarPtr sigma1 = varFactory->fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory->fieldVar("\\sigma_2"); vector<double> beta; beta.push_back(1.0); beta.push_back(0.0); double eps = .01; //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr confusionBF = Teuchos::rcp( new BF(varFactory) ); // tau terms: confusionBF->addTerm(sigma1 / eps, tau->x()); confusionBF->addTerm(sigma2 / eps, tau->y()); confusionBF->addTerm(u, tau->div()); confusionBF->addTerm(uhat, -tau->dot_normal()); // v terms: confusionBF->addTerm( sigma1, v->dx() ); confusionBF->addTerm( sigma2, v->dy() ); confusionBF->addTerm( -u, beta * v->grad() ); confusionBF->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int H1Order = 1; int pToAdd = 1; FieldContainer<double> quadPoints(4,2); quadPoints(0,0) = 0.0; // x1 quadPoints(0,1) = 0.0; // y1 quadPoints(1,0) = 1.0; quadPoints(1,1) = 0.0; quadPoints(2,0) = 1.0; quadPoints(2,1) = 1.0; quadPoints(3,0) = 0.0; quadPoints(3,1) = 1.0; int nCells = 1; int horizontalCells = nCells, verticalCells = nCells; // create a pointer to a new mesh: Teuchos::RCP<Mesh> myMesh = MeshFactory::buildQuadMesh(quadPoints, horizontalCells, verticalCells, confusionBF, H1Order, H1Order+pToAdd); ElementTypePtr elemType = myMesh->getElement(0)->elementType(); // DofOrderingPtr testOrder = elemType->testOrderPtr; BasisCachePtr basisCache = Teuchos::rcp(new BasisCache(elemType, myMesh, true)); LinearTermPtr integrandIBP = Teuchos::rcp(new LinearTerm);// residual vector<double> e1(2); // (1,0) vector<double> e2(2); // (0,1) e1[0] = 1; e2[1] = 1; FunctionPtr n = Function::normal(); FunctionPtr X = Function::xn(1); FunctionPtr Y = Function::yn(1); FunctionPtr testFxn1 = X; FunctionPtr testFxn2 = Y; FunctionPtr divTestFxn = testFxn1->dx() + testFxn2->dy(); FunctionPtr vectorTest = testFxn1*e1 + testFxn2*e2; integrandIBP->addTerm(vectorTest*n*v + -vectorTest*v->grad()); // boundary term // define dummy IP to initialize riesz rep class, but just integrate RHS IPPtr dummyIP = Teuchos::rcp(new IP); dummyIP->addTerm(v); Teuchos::RCP<RieszRep> riesz = Teuchos::rcp(new RieszRep(myMesh, dummyIP, integrandIBP)); map<GlobalIndexType,FieldContainer<double> > rieszRHS = riesz->integrateFunctional(); set<GlobalIndexType> cellIDs = myMesh->cellIDsInPartition(); for (set<GlobalIndexType>::iterator cellIDIt=cellIDs.begin(); cellIDIt !=cellIDs.end(); cellIDIt++) { GlobalIndexType cellID = *cellIDIt; ElementTypePtr elemTypePtr = myMesh->getElementType(cellID); DofOrderingPtr testOrderingPtr = elemTypePtr->testOrderPtr; int numTestDofs = testOrderingPtr->totalDofs(); BasisCachePtr basisCache = BasisCache::basisCacheForCell(myMesh, cellID, true); FieldContainer<double> rhsIBPValues(1,numTestDofs); integrandIBP->integrate(rhsIBPValues, testOrderingPtr, basisCache); FieldContainer<double> rieszValues(1,numTestDofs); (riesz->getFunctional())->integrate(rieszValues, testOrderingPtr, basisCache); double maxDiff; double tol = 1e-13; FieldContainer<double> rhsIBPVals(numTestDofs); for (int i = 0; i< numTestDofs; i++) { rhsIBPVals(i) = rhsIBPValues(0,i); // cout << "riesz rhs values = " << rieszRHS[cellID](i) << ", rhsIBPValues = " << rhsIBPVals(i) << ", riesz returned values = " << rieszValues(0,i) << endl; } bool fcsAgree = TestSuite::fcsAgree(rieszRHS[cellID],rhsIBPVals,tol,maxDiff); if (!fcsAgree) { success=false; cout << "Failed mixed term consistency test with maxDiff = " << maxDiff << " on cellID " << cellID<< endl; } } return allSuccess(success); }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); 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("uhat"); VarPtr sigma_n = varFactory.fluxVar("fhat"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma1 = varFactory.fieldVar("sigma1"); VarPtr sigma2 = varFactory.fieldVar("sigma2"); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // tau terms: bf->addTerm(sigma1, tau->x()); bf->addTerm(sigma2, tau->y()); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma1, v->dx() ); bf->addTerm( sigma2, v->dy() ); bf->addTerm( -sigma_n, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = bf->graphNorm(); //////////////////// SPECIFY RHS /////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr f = Teuchos::rcp( new ConstantScalarFunction(1.0) ); rhs->addTerm( f * v ); //////////////////// CREATE BCs /////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp( new PenaltyConstraints ); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); FunctionPtr one = Teuchos::rcp( new ConstantScalarFunction(1.0) ); SpatialFilterPtr inflow = Teuchos::rcp( new Inflow ); bc->addDirichlet(uhat, inflow, zero); SpatialFilterPtr leadingWedge = Teuchos::rcp( new LeadingWedge ); bc->addDirichlet(uhat, leadingWedge, zero); SpatialFilterPtr trailingWedge = Teuchos::rcp( new TrailingWedge ); bc->addDirichlet(sigma_n, trailingWedge, zero); // bc->addDirichlet(uhat, trailingWedge, zero); SpatialFilterPtr top = Teuchos::rcp( new Top ); bc->addDirichlet(uhat, top, zero); SpatialFilterPtr outflow = Teuchos::rcp( new Outflow ); bc->addDirichlet(uhat, outflow, zero); //////////////////// BUILD MESH /////////////////////// bool allQuads = true; int H1Order = 3, pToAdd = 2; // define nodes for mesh vector< FieldContainer<double> > vertices; FieldContainer<double> pt(2); vector< vector<int> > elementIndices; vector<int> q(4); vector<int> t(3); if (allQuads) { pt(0) = -halfwidth; pt(1) = -1; vertices.push_back(pt); pt(0) = 0; pt(1) = 0; vertices.push_back(pt); pt(0) = halfwidth; pt(1) = -1; vertices.push_back(pt); pt(0) = halfwidth; pt(1) = halfwidth; vertices.push_back(pt); pt(0) = 0; pt(1) = halfwidth; vertices.push_back(pt); pt(0) = -halfwidth; pt(1) = halfwidth; vertices.push_back(pt); q[0] = 0; q[1] = 1; q[2] = 4; q[3] = 5; elementIndices.push_back(q); q[0] = 1; q[1] = 2; q[2] = 3; q[3] = 4; elementIndices.push_back(q); } else { pt(0) = -halfwidth; pt(1) = -1; vertices.push_back(pt); pt(0) = 0; pt(1) = 0; vertices.push_back(pt); pt(0) = halfwidth; pt(1) = -1; vertices.push_back(pt); pt(0) = halfwidth; pt(1) = 0; vertices.push_back(pt); pt(0) = halfwidth; pt(1) = halfwidth; vertices.push_back(pt); pt(0) = 0; pt(1) = halfwidth; vertices.push_back(pt); pt(0) = -halfwidth; pt(1) = halfwidth; vertices.push_back(pt); pt(0) = -halfwidth; pt(1) = 0; vertices.push_back(pt); t[0] = 0; t[1] = 1; t[2] = 7; elementIndices.push_back(t); t[0] = 1; t[1] = 2; t[2] = 3; elementIndices.push_back(t); q[0] = 1; q[1] = 3; q[2] = 4; q[3] = 5; elementIndices.push_back(q); q[0] = 7; q[1] = 1; q[2] = 5; q[3] = 6; elementIndices.push_back(q); } Teuchos::RCP<Mesh> mesh = Teuchos::rcp( new Mesh(vertices, elementIndices, bf, H1Order, pToAdd) ); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); solution->setFilter(pc); if (enforceLocalConservation) { FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); solution->lagrangeConstraints()->addConstraint(sigma_n == zero); } double energyThreshold = 0.2; // for mesh refinements RefinementStrategy refinementStrategy( solution, energyThreshold ); for (int refIndex=0; refIndex<=numRefs; refIndex++) { solution->solve(false); if (rank==0) { stringstream outfile; outfile << "poissonwedge_" << refIndex; solution->writeToVTK(outfile.str()); // Check local conservation FunctionPtr flux = Teuchos::rcp( new PreviousSolutionFunction(solution, sigma_n) ); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); Teuchos::Tuple<double, 3> fluxImbalances = checkConservation(flux, zero, varFactory, mesh); cout << "Mass flux: Largest Local = " << fluxImbalances[0] << ", Global = " << fluxImbalances[1] << ", Sum Abs = " << fluxImbalances[2] << endl; } if (refIndex < numRefs) { // refinementStrategy.refine(rank==0); // print to console on rank 0 vector<int> cellsToRefine; vector<int> cells_h; vector<int> cells_p; refinementStrategy.getCellsAboveErrorThreshhold(cellsToRefine); for (int i=0; i < cellsToRefine.size(); i++) if (sqrt(mesh->getCellMeasure(cellsToRefine[i])) < 1e-3) { int pOrder = mesh->cellPolyOrder(cellsToRefine[i]); if (allQuads) cells_p.push_back(cellsToRefine[i]); else if (pOrder < 8) cells_p.push_back(cellsToRefine[i]); else cout << "Reached cell size and polynomial order limits" << endl; // cells_h.push_back(cellsToRefine[i]); } else cells_h.push_back(cellsToRefine[i]); refinementStrategy.pRefineCells(mesh, cells_p); refinementStrategy.hRefineCells(mesh, cells_h); } } return 0; }
int main(int argc, char *argv[]) { #ifdef ENABLE_INTEL_FLOATING_POINT_EXCEPTIONS cout << "NOTE: enabling floating point exceptions for divide by zero.\n"; _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_INVALID); #endif Teuchos::GlobalMPISession mpiSession(&argc, &argv); int rank = Teuchos::GlobalMPISession::getRank(); #ifdef HAVE_MPI Epetra_MpiComm Comm(MPI_COMM_WORLD); //cout << "rank: " << rank << " of " << numProcs << endl; #else Epetra_SerialComm Comm; #endif Comm.Barrier(); // set breakpoint here to allow debugger attachment to other MPI processes than the one you automatically attached to. Teuchos::CommandLineProcessor cmdp(false,true); // false: don't throw exceptions; true: do return errors for unrecognized options double minTol = 1e-8; bool use3D = false; int refCount = 10; int k = 4; // poly order for field variables int delta_k = use3D ? 3 : 2; // test space enrichment int k_coarse = 0; bool useMumps = true; bool useGMGSolver = true; bool enforceOneIrregularity = true; bool useStaticCondensation = false; bool conformingTraces = false; bool useDiagonalScaling = false; // of the global stiffness matrix in GMGSolver bool printRefinementDetails = false; bool useWeightedGraphNorm = true; // graph norm scaled according to units, more or less int numCells = 2; int AztecOutputLevel = 1; int gmgMaxIterations = 10000; int smootherOverlap = 0; double relativeTol = 1e-6; double D = 1.0; // characteristic length scale cmdp.setOption("polyOrder",&k,"polynomial order for field variable u"); cmdp.setOption("delta_k", &delta_k, "test space polynomial order enrichment"); cmdp.setOption("k_coarse", &k_coarse, "polynomial order for field variables on coarse mesh"); cmdp.setOption("numRefs",&refCount,"number of refinements"); cmdp.setOption("D", &D, "domain dimension"); cmdp.setOption("useConformingTraces", "useNonConformingTraces", &conformingTraces); cmdp.setOption("enforceOneIrregularity", "dontEnforceOneIrregularity", &enforceOneIrregularity); cmdp.setOption("smootherOverlap", &smootherOverlap, "overlap for smoother"); cmdp.setOption("printRefinementDetails", "dontPrintRefinementDetails", &printRefinementDetails); cmdp.setOption("azOutput", &AztecOutputLevel, "Aztec output level"); cmdp.setOption("numCells", &numCells, "number of cells in the initial mesh"); cmdp.setOption("useScaledGraphNorm", "dontUseScaledGraphNorm", &useWeightedGraphNorm); // cmdp.setOption("gmgTol", &gmgTolerance, "tolerance for GMG convergence"); cmdp.setOption("relativeTol", &relativeTol, "Energy error-relative tolerance for iterative solver."); cmdp.setOption("gmgMaxIterations", &gmgMaxIterations, "tolerance for GMG convergence"); bool enhanceUField = false; cmdp.setOption("enhanceUField", "dontEnhanceUField", &enhanceUField); cmdp.setOption("useStaticCondensation", "dontUseStaticCondensation", &useStaticCondensation); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { #ifdef HAVE_MPI MPI_Finalize(); #endif return -1; } double width = D, height = D, depth = D; VarFactory varFactory; // fields: VarPtr u = varFactory.fieldVar("u", L2); VarPtr sigma = varFactory.fieldVar("\\sigma", VECTOR_L2); FunctionPtr n = Function::normal(); // traces: VarPtr u_hat; if (conformingTraces) { u_hat = varFactory.traceVar("\\widehat{u}", u); } else { cout << "Note: using non-conforming traces.\n"; u_hat = varFactory.traceVar("\\widehat{u}", u, L2); } VarPtr sigma_n_hat = varFactory.fluxVar("\\widehat{\\sigma}_{n}", sigma * n); // test functions: VarPtr tau = varFactory.testVar("\\tau", HDIV); VarPtr v = varFactory.testVar("v", HGRAD); BFPtr poissonBF = Teuchos::rcp( new BF(varFactory) ); FunctionPtr alpha = Function::constant(1); // viscosity // tau terms: poissonBF->addTerm(sigma / alpha, tau); poissonBF->addTerm(-u, tau->div()); // (sigma1, tau1) poissonBF->addTerm(u_hat, tau * n); // v terms: poissonBF->addTerm(- sigma, v->grad()); // (mu sigma1, grad v1) poissonBF->addTerm( sigma_n_hat, v); int horizontalCells = numCells, verticalCells = numCells, depthCells = numCells; vector<double> domainDimensions; domainDimensions.push_back(width); domainDimensions.push_back(height); vector<int> elementCounts; elementCounts.push_back(horizontalCells); elementCounts.push_back(verticalCells); if (use3D) { domainDimensions.push_back(depth); elementCounts.push_back(depthCells); } MeshPtr mesh, k0Mesh; int H1Order = k + 1; int H1Order_coarse = k_coarse + 1; if (!use3D) { Teuchos::ParameterList pl; map<int,int> trialOrderEnhancements; if (enhanceUField) { trialOrderEnhancements[u->ID()] = 1; } BFPtr poissonBilinearForm = poissonBF; pl.set("useMinRule", true); pl.set("bf",poissonBilinearForm); pl.set("H1Order", H1Order); pl.set("delta_k", delta_k); pl.set("horizontalElements", horizontalCells); pl.set("verticalElements", verticalCells); pl.set("divideIntoTriangles", false); pl.set("useConformingTraces", conformingTraces); pl.set("trialOrderEnhancements", &trialOrderEnhancements); pl.set("x0",(double)0); pl.set("y0",(double)0); pl.set("width", width); pl.set("height",height); mesh = MeshFactory::quadMesh(pl); pl.set("H1Order", H1Order_coarse); k0Mesh = MeshFactory::quadMesh(pl); } else { mesh = MeshFactory::rectilinearMesh(poissonBF, domainDimensions, elementCounts, H1Order, delta_k); k0Mesh = MeshFactory::rectilinearMesh(poissonBF, domainDimensions, elementCounts, H1Order_coarse, delta_k); } mesh->registerObserver(k0Mesh); // ensure that the k0 mesh refinements track those of the solution mesh RHSPtr rhs = RHS::rhs(); // zero FunctionPtr sin_pi_x = Teuchos::rcp( new Sin_ax(PI/D) ); FunctionPtr sin_pi_y = Teuchos::rcp( new Sin_ay(PI/D) ); FunctionPtr u_exact = sin_pi_x * sin_pi_y; FunctionPtr f = -(2.0 * PI * PI / (D * D)) * sin_pi_x * sin_pi_y; rhs->addTerm( f * v ); BCPtr bc = BC::bc(); SpatialFilterPtr boundary = SpatialFilter::allSpace(); bc->addDirichlet(u_hat, boundary, u_exact); IPPtr graphNorm; FunctionPtr h = Teuchos::rcp( new hFunction() ); if (useWeightedGraphNorm) { graphNorm = IP::ip(); graphNorm->addTerm( tau->div() ); // u graphNorm->addTerm( (h / alpha) * tau - h * v->grad() ); // sigma graphNorm->addTerm( v ); // boundary term (adjoint to u) graphNorm->addTerm( h * tau ); // // new effort, with the idea that the test norm should be considered in reference space, basically // graphNorm = IP::ip(); // graphNorm->addTerm( tau->div() ); // u // graphNorm->addTerm( tau / h - v->grad() ); // sigma // graphNorm->addTerm( v / h ); // boundary term (adjoint to u) // graphNorm->addTerm( tau / h ); } else { map<int, double> trialWeights; // on the squared terms in the trial space norm trialWeights[u->ID()] = 1.0 / (D * D); trialWeights[sigma->ID()] = 1.0; graphNorm = poissonBF->graphNorm(trialWeights, 1.0); // 1.0: weight on the L^2 terms } SolutionPtr solution = Solution::solution(mesh, bc, rhs, graphNorm); solution->setUseCondensedSolve(useStaticCondensation); mesh->registerSolution(solution); // sign up for projection of old solution onto refined cells. double energyThreshold = 0.2; RefinementStrategy refinementStrategy( solution, energyThreshold ); refinementStrategy.setReportPerCellErrors(true); refinementStrategy.setEnforceOneIrregularity(enforceOneIrregularity); Teuchos::RCP<Solver> coarseSolver, fineSolver; if (useMumps) { #ifdef HAVE_AMESOS_MUMPS coarseSolver = Teuchos::rcp( new MumpsSolver(512, true) ); #else cout << "useMumps=true, but MUMPS is not available!\n"; exit(0); #endif } else { coarseSolver = Teuchos::rcp( new KluSolver ); } GMGSolver* gmgSolver; if (useGMGSolver) { double tol = relativeTol; int maxIters = gmgMaxIterations; BCPtr zeroBCs = bc->copyImposingZero(); gmgSolver = new GMGSolver(zeroBCs, k0Mesh, graphNorm, mesh, solution->getDofInterpreter(), solution->getPartitionMap(), maxIters, tol, coarseSolver, useStaticCondensation); gmgSolver->setAztecOutput(AztecOutputLevel); gmgSolver->setUseConjugateGradient(true); gmgSolver->gmgOperator()->setSmootherType(GMGOperator::IFPACK_ADDITIVE_SCHWARZ); gmgSolver->gmgOperator()->setSmootherOverlap(smootherOverlap); fineSolver = Teuchos::rcp( gmgSolver ); } else { fineSolver = coarseSolver; } // if (rank==0) cout << "experimentally starting by solving with MUMPS on the fine mesh.\n"; // solution->solve( Teuchos::rcp( new MumpsSolver) ); solution->solve(fineSolver); #ifdef HAVE_EPETRAEXT_HDF5 ostringstream dir_name; dir_name << "poissonCavityFlow_k" << k; HDF5Exporter exporter(mesh,dir_name.str()); exporter.exportSolution(solution,varFactory,0); #endif #ifdef HAVE_AMESOS_MUMPS if (useMumps) coarseSolver = Teuchos::rcp( new MumpsSolver(512, true) ); #endif solution->reportTimings(); if (useGMGSolver) gmgSolver->gmgOperator()->reportTimings(); for (int refIndex=0; refIndex < refCount; refIndex++) { double energyError = solution->energyErrorTotal(); GlobalIndexType numFluxDofs = mesh->numFluxDofs(); if (rank==0) { cout << "Before refinement " << refIndex << ", energy error = " << energyError; cout << " (using " << numFluxDofs << " trace degrees of freedom)." << endl; } bool printToConsole = printRefinementDetails && (rank==0); refinementStrategy.refine(printToConsole); if (useStaticCondensation) { CondensedDofInterpreter* condensedDofInterpreter = dynamic_cast<CondensedDofInterpreter*>(solution->getDofInterpreter().get()); if (condensedDofInterpreter != NULL) { condensedDofInterpreter->reinitialize(); } } GlobalIndexType fineDofs = mesh->globalDofCount(); GlobalIndexType coarseDofs = k0Mesh->globalDofCount(); if (rank==0) { cout << "After refinement, coarse mesh has " << k0Mesh->numActiveElements() << " elements and " << coarseDofs << " dofs.\n"; cout << " Fine mesh has " << mesh->numActiveElements() << " elements and " << fineDofs << " dofs.\n"; } if (!use3D) { ostringstream fineMeshLocation, coarseMeshLocation; fineMeshLocation << "poissonFineMesh_k" << k << "_ref" << refIndex; GnuPlotUtil::writeComputationalMeshSkeleton(fineMeshLocation.str(), mesh, true); // true: label cells coarseMeshLocation << "poissonCoarseMesh_k" << k << "_ref" << refIndex; GnuPlotUtil::writeComputationalMeshSkeleton(coarseMeshLocation.str(), k0Mesh, true); // true: label cells } if (useGMGSolver) // create fresh fineSolver now that the meshes have changed: { #ifdef HAVE_AMESOS_MUMPS if (useMumps) coarseSolver = Teuchos::rcp( new MumpsSolver(512, true) ); #endif double tol = max(relativeTol * energyError, minTol); int maxIters = gmgMaxIterations; BCPtr zeroBCs = bc->copyImposingZero(); gmgSolver = new GMGSolver(zeroBCs, k0Mesh, graphNorm, mesh, solution->getDofInterpreter(), solution->getPartitionMap(), maxIters, tol, coarseSolver, useStaticCondensation); gmgSolver->setAztecOutput(AztecOutputLevel); gmgSolver->setUseDiagonalScaling(useDiagonalScaling); fineSolver = Teuchos::rcp( gmgSolver ); } solution->solve(fineSolver); solution->reportTimings(); if (useGMGSolver) gmgSolver->gmgOperator()->reportTimings(); #ifdef HAVE_EPETRAEXT_HDF5 exporter.exportSolution(solution,varFactory,refIndex+1); #endif } double energyErrorTotal = solution->energyErrorTotal(); GlobalIndexType numFluxDofs = mesh->numFluxDofs(); GlobalIndexType numGlobalDofs = mesh->numGlobalDofs(); if (rank==0) { cout << "Final mesh has " << mesh->numActiveElements() << " elements and " << numFluxDofs << " trace dofs ("; cout << numGlobalDofs << " total dofs, including fields).\n"; cout << "Final energy error: " << energyErrorTotal << endl; } #ifdef HAVE_EPETRAEXT_HDF5 exporter.exportSolution(solution,varFactory,0); #endif if (!use3D) { GnuPlotUtil::writeComputationalMeshSkeleton("poissonRefinedMesh", mesh, true); } coarseSolver = Teuchos::rcp((Solver*) NULL); // without this when useMumps = true and running on one rank, we see a crash on exit, which may have to do with MPI being finalized before coarseSolver is deleted. 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 commRank = Teuchos::GlobalMPISession::getRank(); int numProcs = Teuchos::GlobalMPISession::getNProc(); // Required arguments double epsilon = args.Input<double>("--epsilon", "diffusion parameter"); int numRefs = args.Input<int>("--numRefs", "number of refinement steps"); bool enforceLocalConservation = args.Input<bool>("--conserve", "enforce local conservation"); int norm = args.Input<int>("--norm", "0 = graph\n 1 = robust\n 2 = modified robust"); // Optional arguments (have defaults) bool zeroL2 = args.Input("--zeroL2", "take L2 term on v in robust norm to zero", true); args.Process(); //////////////////// 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("uhat"); VarPtr fhat = varFactory.fluxVar("fhat"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma = varFactory.fieldVar("sigma", VECTOR_L2); //////////////////// BUILD MESH /////////////////////// BFPtr bf = Teuchos::rcp( new BF(varFactory) ); int H1Order = 3, pToAdd = 2; // define nodes for mesh FieldContainer<double> meshBoundary(4,2); meshBoundary(0,0) = 0.0; // x1 meshBoundary(0,1) = 0.0; // y1 meshBoundary(1,0) = 1.0; meshBoundary(1,1) = 0.0; meshBoundary(2,0) = 1.0; meshBoundary(2,1) = 1.0; meshBoundary(3,0) = 0.0; meshBoundary(3,1) = 1.0; int horizontalCells = 4, verticalCells = 4; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = Mesh::buildQuadMesh(meshBoundary, horizontalCells, verticalCells, bf, H1Order, H1Order+pToAdd, false); vector<double> beta; beta.push_back(2.0); beta.push_back(1.0); //////////////////// DEFINE BILINEAR FORM /////////////////////// // tau terms: bf->addTerm(sigma / epsilon, tau); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma, v->grad() ); bf->addTerm( beta * u, - v->grad() ); bf->addTerm( fhat, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = Teuchos::rcp(new IP); if (norm == 0) { ip = bf->graphNorm(); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); ip->addZeroMeanTerm( h2_scaling*v ); } // Robust norm else if (norm == 1) { // robust test norm FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); if (!zeroL2) ip->addTerm( v ); ip->addTerm( sqrt(epsilon) * v->grad() ); // Weight these two terms for inflow ip->addTerm( beta * v->grad() ); ip->addTerm( tau->div() ); ip->addTerm( ip_scaling/sqrt(epsilon) * tau ); if (zeroL2) ip->addZeroMeanTerm( h2_scaling*v ); } // Modified robust norm else if (norm == 2) { // robust test norm FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); // FunctionPtr ip_weight = Teuchos::rcp( new IPWeight() ); if (!zeroL2) ip->addTerm( v ); ip->addTerm( sqrt(epsilon) * v->grad() ); ip->addTerm( beta * v->grad() ); ip->addTerm( tau->div() - beta*v->grad() ); ip->addTerm( ip_scaling/sqrt(epsilon) * tau ); if (zeroL2) ip->addZeroMeanTerm( h2_scaling*v ); } //////////////////// SPECIFY RHS /////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr f = Teuchos::rcp( new ConstantScalarFunction(0.0) ); 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 InflowBoundary ); SpatialFilterPtr outflowBoundary = Teuchos::rcp( new OutflowBoundary ); FunctionPtr u0 = Teuchos::rcp( new U0 ); bc->addDirichlet(uhat, outflowBoundary, u0); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); bc->addDirichlet(fhat, inflowBoundary, beta*n*u0); // Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp(new PenaltyConstraints); // pc->addConstraint(uhat==u0,inflowBoundary); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); // solution->setFilter(pc); if (enforceLocalConservation) { FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); solution->lagrangeConstraints()->addConstraint(fhat == zero); } double energyThreshold = 0.2; // for mesh refinements RefinementStrategy refinementStrategy( solution, energyThreshold ); VTKExporter exporter(solution, mesh, varFactory); ofstream errOut; if (commRank == 0) errOut.open("confusion_err.txt"); for (int refIndex=0; refIndex<=numRefs; refIndex++){ solution->solve(false); double energy_error = solution->energyErrorTotal(); if (commRank==0){ stringstream outfile; outfile << "confusion_" << refIndex; exporter.exportSolution(outfile.str()); // solution->writeToVTK(outfile.str()); // Check local conservation FunctionPtr flux = Function::solution(fhat, solution); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); Teuchos::Tuple<double, 3> fluxImbalances = checkConservation(flux, zero, varFactory, mesh); cout << "Mass flux: Largest Local = " << fluxImbalances[0] << ", Global = " << fluxImbalances[1] << ", Sum Abs = " << fluxImbalances[2] << endl; errOut << mesh->numGlobalDofs() << " " << energy_error << " " << fluxImbalances[0] << " " << fluxImbalances[1] << " " << fluxImbalances[2] << endl; } if (refIndex < numRefs) refinementStrategy.refine(commRank==0); // print to console on commRank 0 } if (commRank == 0) errOut.close(); return 0; }