int main(int argc, char *argv[]) { Teuchos::GlobalMPISession mpiSession(&argc, &argv, NULL); // initialize MPI Teuchos::CommandLineProcessor cmdp(false,true); // false: don't throw exceptions; true: do return errors for unrecognized options int numElements = 3; double xLeft = 0.0, xRight = 1.0; int polyOrder = 1, delta_k = 1; cmdp.setOption("numElements", &numElements ); cmdp.setOption("polyOrder", &polyOrder ); cmdp.setOption("delta_k", &delta_k ); cmdp.setOption("xLeft", &xLeft ); cmdp.setOption("xRight", &xRight ); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { #ifdef HAVE_MPI MPI_Finalize(); #endif return -1; } int spaceDim = 1; bool conformingTraces = true; // conformingTraces argument has no effect in 1D PoissonFormulation poissonForm(spaceDim, conformingTraces); MeshPtr mesh = MeshFactory::intervalMesh(poissonForm.bf(), xLeft, xRight, numElements, polyOrder + 1, delta_k); // 1D equispaced RHSPtr rhs = RHS::rhs(); // zero RHS IPPtr ip = poissonForm.bf()->graphNorm(); BCPtr bc = BC::bc(); bc->addDirichlet(poissonForm.phi_hat(), SpatialFilter::allSpace(), Function::zero()); SolutionPtr solution = Solution::solution(poissonForm.bf(), mesh, bc, rhs, ip); solution->solve(); GDAMinimumRule* minRule = dynamic_cast<GDAMinimumRule*>(mesh->globalDofAssignment().get()); // minRule->printGlobalDofInfo(); Teuchos::RCP<Epetra_CrsMatrix> A = solution->getStiffnessMatrix(); EpetraExt::RowMatrixToMatrixMarketFile("A.dat",*A, NULL, NULL, false); HDF5Exporter exporter(mesh); 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 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; }
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); 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); #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 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(); Teuchos::CommandLineProcessor cmdp(false,true); // false: don't throw exceptions; true: do return errors for unrecognized options const static double PI = 3.141592653589793238462; bool useCondensedSolve = true; // condensed solve not yet compatible with minimum rule meshes int k = 2; // poly order for u in every direction, including temporal int numCells = 32; // in x, y int numTimeCells = 1; int numTimeSlabs = -1; int numFrames = 201; int delta_k = 3; // test space enrichment: should be 3 for 3D int maxRefinements = 0; // maximum # of refinements on each time slab bool useMumpsIfAvailable = true; bool useConstantConvection = false; double refinementTolerance = 0.1; int checkPointFrequency = 50; // output solution and mesh every 50 time slabs int previousSolutionTimeSlabNumber = -1; string previousSolutionFile = ""; string previousMeshFile = ""; cmdp.setOption("polyOrder",&k,"polynomial order for field variable u"); cmdp.setOption("delta_k", &delta_k, "test space polynomial order enrichment"); cmdp.setOption("numCells",&numCells,"number of cells in x and y directions"); cmdp.setOption("numTimeCells",&numTimeCells,"number of time axis cells"); cmdp.setOption("numTimeSlabs",&numTimeSlabs,"number of time slabs"); cmdp.setOption("numFrames",&numFrames,"number of frames for export"); cmdp.setOption("useConstantConvection", "useVariableConvection", &useConstantConvection); cmdp.setOption("useCondensedSolve", "useUncondensedSolve", &useCondensedSolve, "use static condensation to reduce the size of the global solve"); cmdp.setOption("useMumps", "useKLU", &useMumpsIfAvailable, "use MUMPS (if available)"); cmdp.setOption("refinementTolerance", &refinementTolerance, "relative error beyond which to stop refining"); cmdp.setOption("maxRefinements", &maxRefinements, "maximum # of refinements on each time slab"); cmdp.setOption("previousSlabNumber", &previousSolutionTimeSlabNumber, "time slab number of previous solution"); cmdp.setOption("previousSolution", &previousSolutionFile, "file with previous solution"); cmdp.setOption("previousMesh", &previousMeshFile, "file with previous mesh"); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { #ifdef HAVE_MPI MPI_Finalize(); #endif return -1; } int H1Order = k + 1; VarFactory varFactory; // traces: VarPtr qHat = varFactory.fluxVar("\\widehat{q}"); // fields: VarPtr u = varFactory.fieldVar("u", L2); // test functions: VarPtr v = varFactory.testVar("v", HGRAD); FunctionPtr x = Function::xn(1); FunctionPtr y = Function::yn(1); FunctionPtr c; if (useConstantConvection) { c = Function::vectorize(Function::constant(0.5), Function::constant(0.5), Function::constant(1.0)); } else { c = Function::vectorize(y-0.5, 0.5-x, Function::constant(1.0)); } FunctionPtr n = Function::normal(); BFPtr bf = Teuchos::rcp( new BF(varFactory) ); bf->addTerm( u, c * v->grad()); bf->addTerm(qHat, v); double width = 2.0, height = 2.0; int horizontalCells = numCells, verticalCells = numCells; int depthCells = numTimeCells; double x0 = -0.5; double y0 = -0.5; double t0 = 0; double totalTime = 2.0 * PI; vector<double> frameTimes; for (int i=0; i<numFrames; i++) { frameTimes.push_back((totalTime*i) / (numFrames-1)); } if (numTimeSlabs==-1) { // want the number of grid points in temporal direction to be about 2000. The temporal length is 2 * PI numTimeSlabs = (int) 2000 / k; } double timeLengthPerSlab = totalTime / numTimeSlabs; if (rank==0) { cout << "solving on " << numCells << " x " << numCells << " x " << numTimeCells << " mesh " << "of order " << k << ".\n"; cout << "numTimeSlabs: " << numTimeSlabs << endl; } SpatialFilterPtr inflowFilter = Teuchos::rcp( new InflowFilterForClockwisePlanarRotation (x0,x0+width,y0,y0+height,0.5,0.5)); vector<double> dimensions; dimensions.push_back(width); dimensions.push_back(height); dimensions.push_back(timeLengthPerSlab); vector<int> elementCounts(3); elementCounts[0] = horizontalCells; elementCounts[1] = verticalCells; elementCounts[2] = depthCells; vector<double> origin(3); origin[0] = x0; origin[1] = y0; origin[2] = t0; Teuchos::RCP<Solver> solver = Teuchos::rcp( new KluSolver ); #ifdef HAVE_AMESOS_MUMPS if (useMumpsIfAvailable) solver = Teuchos::rcp( new MumpsSolver ); #endif // double errorPercentage = 0.5; // for mesh refinements: ask to refine elements that account for 80% of the error in each step // Teuchos::RCP<RefinementStrategy> refinementStrategy; // refinementStrategy = Teuchos::rcp( new ErrorPercentageRefinementStrategy( soln, errorPercentage )); if (maxRefinements != 0) { cout << "Warning: maxRefinements is not 0, but the slice exporter implicitly assumes there won't be any refinements.\n"; } MeshPtr mesh; MeshPtr prevMesh; SolutionPtr prevSoln; mesh = MeshFactory::rectilinearMesh(bf, dimensions, elementCounts, H1Order, delta_k, origin); if (rank==0) cout << "Initial mesh has " << mesh->getTopology()->activeCellCount() << " active (leaf) cells " << "and " << mesh->globalDofCount() << " degrees of freedom.\n"; FunctionPtr sideParity = Function::sideParity(); int lastFrameOutputted = -1; SolutionPtr soln; IPPtr ip; ip = bf->graphNorm(); FunctionPtr u0 = Teuchos::rcp( new Cone_U0(0.0, 0.25, 0.1, 1.0, false) ); BCPtr bc = BC::bc(); bc->addDirichlet(qHat, inflowFilter, Function::zero()); // zero BCs enforced at the inflow boundary. bc->addDirichlet(qHat, SpatialFilter::matchingZ(t0), u0); MeshPtr initialMesh = mesh; int startingSlabNumber; if (previousSolutionTimeSlabNumber != -1) { startingSlabNumber = previousSolutionTimeSlabNumber + 1; if (rank==0) cout << "Loading mesh from " << previousMeshFile << endl; prevMesh = MeshFactory::loadFromHDF5(bf, previousMeshFile); prevSoln = Solution::solution(mesh, bc, RHS::rhs(), ip); // include BC and IP objects for sake of condensed dof interpreter setup... prevSoln->setUseCondensedSolve(useCondensedSolve); if (rank==0) cout << "Loading solution from " << previousSolutionFile << endl; prevSoln->loadFromHDF5(previousSolutionFile); double tn = (previousSolutionTimeSlabNumber+1) * timeLengthPerSlab; origin[2] = tn; mesh = MeshFactory::rectilinearMesh(bf, dimensions, elementCounts, H1Order, delta_k, origin); FunctionPtr q_prev = Function::solution(qHat, prevSoln); FunctionPtr q_transfer = Teuchos::rcp( new MeshTransferFunction(-q_prev, prevMesh, mesh, tn) ); // negate because the normals go in opposite directions bc = BC::bc(); bc->addDirichlet(qHat, inflowFilter, Function::zero()); // zero BCs enforced at the inflow boundary. bc->addDirichlet(qHat, SpatialFilter::matchingZ(tn), q_transfer); double t_slab_final = (previousSolutionTimeSlabNumber+1) * timeLengthPerSlab; int frameOrdinal = 0; while (frameTimes[frameOrdinal] < t_slab_final) { lastFrameOutputted = frameOrdinal++; } } else { startingSlabNumber = 0; } #ifdef HAVE_EPETRAEXT_HDF5 ostringstream dir_name; dir_name << "spacetime_slice_convectingCone_k" << k << "_startSlab" << startingSlabNumber; map<GlobalIndexType,GlobalIndexType> cellMap; MeshPtr meshSlice = MeshTools::timeSliceMesh(initialMesh, 0, cellMap, H1Order); HDF5Exporter sliceExporter(meshSlice,dir_name.str()); #endif soln = Solution::solution(mesh, bc, RHS::rhs(), ip); soln->setUseCondensedSolve(useCondensedSolve); for(int timeSlab = startingSlabNumber; timeSlab<numTimeSlabs; timeSlab++) { double energyThreshold = 0.2; // for mesh refinements: ask to refine elements that account for 80% of the error in each step Teuchos::RCP<RefinementStrategy> refinementStrategy; refinementStrategy = Teuchos::rcp( new RefinementStrategy( soln, energyThreshold )); FunctionPtr u_spacetime = Function::solution(u, soln); double relativeEnergyError; int refNumber = 0; // { // // DEBUGGING: just to try running the time slicing: // double t_slab_final = (timeStep+1) * timeLengthPerSlab; // int frameOrdinal = lastFrameOutputted + 1; // while (frameTimes[frameOrdinal] < t_slab_final) { // FunctionPtr u_spacetime = Function::solution(u, soln); // ostringstream dir_name; // dir_name << "spacetime_slice_convectingCone_k" << k; // MeshTools::timeSliceExport(dir_name.str(), mesh, u_spacetime, frameTimes[frameOrdinal], "u_slice"); // // cout << "Exported frame " << frameOrdinal << ", t=" << frameTimes[frameOrdinal] << endl; // frameOrdinal++; // } // } do { soln->solve(solver); soln->reportTimings(); #ifdef HAVE_EPETRAEXT_HDF5 ostringstream dir_name; dir_name << "spacetime_convectingCone_k" << k << "_t" << timeSlab; HDF5Exporter exporter(soln->mesh(),dir_name.str()); exporter.exportSolution(soln, varFactory); if (rank==0) cout << "Exported HDF solution for time slab to directory " << dir_name.str() << endl; // string u_name = "u_spacetime"; // exporter.exportFunction(u_spacetime, u_name); ostringstream file_name; file_name << dir_name.str(); bool saveSolutionAndMeshForThisSlab = ((timeSlab + 1) % checkPointFrequency == 0); // +1 so that first output is nth, not first if (saveSolutionAndMeshForThisSlab) { dir_name << ".soln"; soln->saveToHDF5(dir_name.str()); if (rank==0) cout << endl << "wrote " << dir_name.str() << endl; file_name << ".mesh"; soln->mesh()->saveToHDF5(file_name.str()); } #endif FunctionPtr u_soln = Function::solution(u, soln); double solnNorm = u_soln->l2norm(mesh); double energyError = soln->energyErrorTotal(); relativeEnergyError = energyError / solnNorm; if (rank==0) { cout << "Relative energy error for refinement " << refNumber++ << ": " << relativeEnergyError << endl; } if ((relativeEnergyError > refinementTolerance) && (refNumber < maxRefinements)) { refinementStrategy->refine(); if (rank==0) { cout << "After refinement, mesh has " << mesh->getTopology()->activeCellCount() << " active (leaf) cells " << "and " << mesh->globalDofCount() << " degrees of freedom.\n"; } } } while ((relativeEnergyError > refinementTolerance) && (refNumber < maxRefinements)); double t_slab_final = (timeSlab+1) * timeLengthPerSlab; int frameOrdinal = lastFrameOutputted + 1; vector<double> timesForSlab; while (frameTimes[frameOrdinal] < t_slab_final) { double t = frameTimes[frameOrdinal]; if (rank==0) cout << "exporting t=" << t << " on slab " << timeSlab << endl; FunctionPtr sliceFunction = MeshTools::timeSliceFunction(mesh, cellMap, u_spacetime, t); sliceExporter.exportFunction(sliceFunction, "u_slice", t); lastFrameOutputted = frameOrdinal++; } // set up next mesh/solution: FunctionPtr q_prev = Function::solution(qHat, soln); // cout << "Error in setup of q_prev: simple solution doesn't know about the map from the previous time slab to the current one. (TODO: fix this.)\n"; double tn = (timeSlab+1) * timeLengthPerSlab; origin[2] = tn; mesh = MeshFactory::rectilinearMesh(bf, dimensions, elementCounts, H1Order, delta_k, origin); FunctionPtr q_transfer = Teuchos::rcp( new MeshTransferFunction(-q_prev, soln->mesh(), mesh, tn) ); // negate because the normals go in opposite directions bc = BC::bc(); bc->addDirichlet(qHat, inflowFilter, Function::zero()); // zero BCs enforced at the inflow boundary. bc->addDirichlet(qHat, SpatialFilter::matchingZ(tn), q_transfer); // IMPORTANT: now that we are ready to step to next soln, nullify BC. If we do not do this, then we have an RCP chain // that extends back to the first time slab, effectively a memory leak. soln->setBC(BC::bc()); soln = Solution::solution(mesh, bc, RHS::rhs(), ip); soln->setUseCondensedSolve(useCondensedSolve); } return 0; }
void TransientTests::SetUp() { //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarPtr v = varFactory.testVar("v", HGRAD); // define trial variables beta_n_u_hat = varFactory.fluxVar("\\widehat{\\beta \\cdot n }"); u = varFactory.fieldVar("u"); vector<double> beta; beta.push_back(1.0); beta.push_back(0.0); //////////////////// BUILD MESH /////////////////////// bf = Teuchos::rcp( new BF(varFactory) ); // define nodes for mesh 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: mesh = MeshFactory::buildQuadMesh(meshBoundary, horizontalCells, verticalCells, bf, H1Order, H1Order+pToAdd); //////////////////////////////////////////////////////////////////// // INITIALIZE FLOW FUNCTIONS //////////////////////////////////////////////////////////////////// BCPtr nullBC = Teuchos::rcp((BC*)NULL); RHSPtr nullRHS = Teuchos::rcp((RHS*)NULL); IPPtr nullIP = Teuchos::rcp((IP*)NULL); prevTimeFlow = Teuchos::rcp(new Solution(mesh, nullBC, nullRHS, nullIP) ); flowResidual = Teuchos::rcp(new Solution(mesh, nullBC, nullRHS, nullIP) ); FunctionPtr u_prev_time = Teuchos::rcp( new PreviousSolutionFunction(prevTimeFlow, u) ); //////////////////// DEFINE BILINEAR FORM /////////////////////// RHSPtr rhs = RHS::rhs(); FunctionPtr invDt = Teuchos::rcp(new ScalarParamFunction(1.0/dt)); // v terms: bf->addTerm( beta * u, - v->grad() ); bf->addTerm( beta_n_u_hat, v); // transient terms bf->addTerm( u, invDt*v ); rhs->addTerm( u_prev_time * invDt * v ); //////////////////// SPECIFY RHS /////////////////////// FunctionPtr f = Teuchos::rcp( new ConstantScalarFunction(0.0) ); rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = bf->graphNorm(); //////////////////// CREATE BCs /////////////////////// BCPtr bc = BC::bc(); SpatialFilterPtr lBoundary = Teuchos::rcp( new LeftBoundary ); FunctionPtr u1 = Teuchos::rcp( new InletBC ); bc->addDirichlet(beta_n_u_hat, lBoundary, -u1); solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); // ==================== Register Solutions ========================== mesh->registerSolution(solution); mesh->registerSolution(prevTimeFlow); mesh->registerSolution(flowResidual); // ==================== SET INITIAL GUESS ========================== double u_free = 0.0; map<int, Teuchos::RCP<Function> > functionMap; functionMap[u->ID()] = Teuchos::rcp( new ConstantScalarFunction(u_free) ); // prevTimeFlow->projectOntoMesh(functionMap); }
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; }
// 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; }
// tests residual computation on simple convection bool ScratchPadTests::testLTResidualSimple() { double tol = 1e-11; int rank = Teuchos::GlobalMPISession::getRank(); bool success = true; int nCells = 2; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr v = varFactory->testVar("v", HGRAD); // define trial variables VarPtr beta_n_u = varFactory->fluxVar("\\widehat{\\beta \\cdot n u - \\sigma_{n}}"); VarPtr u = varFactory->fieldVar("u"); vector<double> beta; beta.push_back(1.0); beta.push_back(1.0); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr confusionBF = Teuchos::rcp( new BF(varFactory) ); // v terms: confusionBF->addTerm( -u, beta * v->grad() ); confusionBF->addTerm( beta_n_u, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// // robust test norm IPPtr ip = Teuchos::rcp(new IP); // choose the mesh-independent norm even though it may have BLs ip->addTerm(v->grad()); ip->addTerm(v); //////////////////// 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 ); //////////////////// CREATE BCs /////////////////////// BCPtr bc = BC::bc(); SpatialFilterPtr boundary = Teuchos::rcp( new InflowSquareBoundary ); FunctionPtr u_in = Teuchos::rcp(new Uinflow); bc->addDirichlet(beta_n_u, boundary, beta*n*u_in); //////////////////// 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 /////////////////////// int cubEnrich = 0; 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); Teuchos::RCP<RieszRep> rieszResidual = Teuchos::rcp(new RieszRep(mesh, ip, residual)); rieszResidual->computeRieszRep(cubEnrich); double energyErrorLT = rieszResidual->getNorm(); bool testVsTest = true; FunctionPtr e_v = RieszRep::repFunction(v,rieszResidual); map<int,FunctionPtr> errFxns; errFxns[v->ID()] = e_v; FunctionPtr err = (ip->evaluate(errFxns,false))->evaluate(errFxns,false); // don't need boundary terms unless they're in IP double energyErrorIntegrated = sqrt(err->integrate(mesh,cubEnrich,testVsTest)); // check that energy error computed thru Solution and through rieszRep are the same success = abs(energyError-energyErrorLT) < tol; if (success==false) { if (rank==0) cout << "Failed testLTResidualSimple; energy error = " << energyError << ", while linearTerm error is computed to be " << energyErrorLT << endl; return success; } // checks that matrix-computed and integrated errors are the same success = abs(energyErrorLT-energyErrorIntegrated)<tol; if (success==false) { if (rank==0) cout << "Failed testLTResidualSimple; energy error = " << energyError << ", while error computed via integration is " << energyErrorIntegrated << endl; return success; } return success; }
int main(int argc, char *argv[]) { Teuchos::GlobalMPISession mpiSession(&argc, &argv, NULL); // initialize MPI Teuchos::CommandLineProcessor cmdp(false,true); // false: don't throw exceptions; true: do return errors for unrecognized options int numElements = 3; vector<vector<double>> domainDim(3,vector<double>{0.0,1.0}); // first index: spaceDim; second: 0/1 for x0, x1, etc. int polyOrder = 2, delta_k = 1; int spaceDim = 2; cmdp.setOption("numElements", &numElements ); cmdp.setOption("polyOrder", &polyOrder ); cmdp.setOption("delta_k", &delta_k ); cmdp.setOption("x0", &domainDim[0][0] ); cmdp.setOption("x1", &domainDim[0][1] ); cmdp.setOption("y0", &domainDim[1][0] ); cmdp.setOption("y1", &domainDim[1][1] ); cmdp.setOption("z0", &domainDim[2][0] ); cmdp.setOption("z1", &domainDim[2][1] ); cmdp.setOption("spaceDim", &spaceDim); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { #ifdef HAVE_MPI MPI_Finalize(); #endif return -1; } vector<double> x0(spaceDim); vector<double> domainSize(spaceDim); vector<int> elementCounts(spaceDim); for (int d=0; d<spaceDim; d++) { x0[d] = domainDim[d][0]; domainSize[d] = domainDim[d][1] - x0[d]; elementCounts[d] = numElements; } bool conformingTraces = true; // no difference for primal/continuous formulations PoissonFormulation formCG(spaceDim, conformingTraces, PoissonFormulation::CONTINUOUS_GALERKIN); VarPtr q = formCG.q(); VarPtr phi = formCG.phi(); BFPtr bf = formCG.bf(); MeshPtr bubnovMesh = MeshFactory::rectilinearMesh(bf, domainSize, elementCounts, polyOrder, 0, x0); // Right now, hanging nodes don't work with continuous field variables // there is a GDAMinimumRule test demonstrating the failure, SolvePoisson2DContinuousGalerkinHangingNode. // make a mesh with hanging nodes (when spaceDim > 1) // { // set<GlobalIndexType> cellsToRefine = {0}; // bubnovMesh->hRefine(cellsToRefine); // } RHSPtr rhs = RHS::rhs(); rhs->addTerm(1.0 * q); // unit forcing IPPtr ip = Teuchos::null; // will give Bubnov-Galerkin BCPtr bc = BC::bc(); bc->addDirichlet(phi, SpatialFilter::allSpace(), Function::zero()); SolutionPtr solution = Solution::solution(bf, bubnovMesh, bc, rhs, ip); solution->solve(); HDF5Exporter exporter(bubnovMesh, "PoissonContinuousGalerkin"); exporter.exportSolution(solution); /**** Sort-of-primal experiment ****/ // an experiment: try doing "primal" DPG with IBP to the boundary // ip = IP::ip(); // ip->addTerm(q->grad()); // ip->addTerm(q); // // solution = Solution::solution(bf, bubnovMesh, bc, rhs, ip); // solution->solve(); // // HDF5Exporter primalNoFluxExporter(bubnovMesh, "PoissonPrimalNoFlux"); // primalNoFluxExporter.exportSolution(solution); //*** Primal Formulation ***// PoissonFormulation form(spaceDim, conformingTraces, PoissonFormulation::PRIMAL); q = form.q(); phi = form.phi(); bf = form.bf(); bc = BC::bc(); bc->addDirichlet(phi, SpatialFilter::allSpace(), Function::zero()); rhs = RHS::rhs(); rhs->addTerm(1.0 * q); // unit forcing MeshPtr primalMesh = MeshFactory::rectilinearMesh(bf, domainSize, elementCounts, polyOrder, delta_k, x0); ip = IP::ip(); ip->addTerm(q->grad()); ip->addTerm(q); // Right now, hanging nodes don't work with continuous field variables // there is a GDAMinimumRule test demonstrating the failure, SolvePoisson2DContinuousGalerkinHangingNode. // make a mesh with hanging nodes (when spaceDim > 1) // { // set<GlobalIndexType> cellsToRefine = {0}; // primalMesh->hRefine(cellsToRefine); // } solution = Solution::solution(bf, primalMesh, bc, rhs, ip); solution->solve(); HDF5Exporter primalExporter(primalMesh, "PoissonPrimal"); primalExporter.exportSolution(solution); 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 int numRefs = args.Input<int>("--numRefs", "number of refinement steps"); int norm = args.Input<int>("--norm", "0 = graph\n 1 = robust\n 2 = coupled robust"); // Optional arguments (have defaults) bool enforceLocalConservation = args.Input<bool>("--conserve", "enforce local conservation", false); double Re = args.Input("--Re", "Reynolds number", 40); double nu = 1./Re; double lambda = Re/2.-sqrt(Re*Re/4+4*pi*pi); int maxNewtonIterations = args.Input("--maxIterations", "maximum number of Newton iterations", 20); int polyOrder = args.Input("--polyOrder", "polynomial order for field variables", 2); int deltaP = args.Input("--deltaP", "how much to enrich test space", 2); // string saveFile = args.Input<string>("--meshSaveFile", "file to which to save refinement history", ""); // string replayFile = args.Input<string>("--meshLoadFile", "file with refinement history to replay", ""); args.Process(); // if (commRank==0) // { // cout << "saveFile is " << saveFile << endl; // cout << "loadFile is " << replayFile << endl; // } //////////////////// PROBLEM DEFINITIONS /////////////////////// int H1Order = polyOrder+1; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactory varFactory; VarPtr tau11 = varFactory.testVar("tau11", HGRAD); VarPtr tau12 = varFactory.testVar("tau12", HGRAD); VarPtr tau22 = varFactory.testVar("tau22", HGRAD); VarPtr v1 = varFactory.testVar("v1", HGRAD); VarPtr v2 = varFactory.testVar("v2", HGRAD); // define trial variables VarPtr u1 = varFactory.fieldVar("u1"); VarPtr u2 = varFactory.fieldVar("u2"); VarPtr sigma11 = varFactory.fieldVar("sigma11"); VarPtr sigma12 = varFactory.fieldVar("sigma12"); VarPtr sigma22 = varFactory.fieldVar("sigma22"); VarPtr u1hat = varFactory.traceVar("u1hat"); VarPtr u2hat = varFactory.traceVar("u2hat"); VarPtr t1hat = varFactory.fluxVar("t1hat"); VarPtr t2hat = varFactory.fluxVar("t2hat"); //////////////////// BUILD MESH /////////////////////// BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // define nodes for mesh FieldContainer<double> meshBoundary(4,2); double xmin = -0.5; double xmax = 1.0; double ymin = -0.5; double ymax = 1.5; meshBoundary(0,0) = xmin; // x1 meshBoundary(0,1) = ymin; // y1 meshBoundary(1,0) = xmax; meshBoundary(1,1) = ymin; meshBoundary(2,0) = xmax; meshBoundary(2,1) = ymax; meshBoundary(3,0) = xmin; meshBoundary(3,1) = ymax; int horizontalCells = 6, verticalCells = 8; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = MeshFactory::buildQuadMesh(meshBoundary, horizontalCells, verticalCells, bf, H1Order, H1Order+deltaP); //////////////////////////////////////////////////////////////////// // 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 u1_prev = Function::solution(u1, backgroundFlow); FunctionPtr u2_prev = Function::solution(u2, backgroundFlow); // FunctionPtr sigma11_prev = Function::solution(sigma11, backgroundFlow); // FunctionPtr sigma12_prev = Function::solution(sigma12, backgroundFlow); // FunctionPtr sigma22_prev = Function::solution(sigma22, backgroundFlow); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); FunctionPtr one = Teuchos::rcp( new ConstantScalarFunction(1.0) ); FunctionPtr u1Exact = Teuchos::rcp( new ExactU1(lambda) ); FunctionPtr u2Exact = Teuchos::rcp( new ExactU2(lambda) ); // ==================== SET INITIAL GUESS ========================== map<int, Teuchos::RCP<Function> > functionMap; // functionMap[u1->ID()] = u1Exact; // functionMap[u2->ID()] = u2Exact; functionMap[u1->ID()] = zero; functionMap[u2->ID()] = zero; backgroundFlow->projectOntoMesh(functionMap); //////////////////// DEFINE BILINEAR FORM /////////////////////// // stress equation bf->addTerm( 1./nu*sigma11, tau11 ); bf->addTerm( 1./nu*sigma12, tau12 ); bf->addTerm( 1./nu*sigma12, tau12 ); bf->addTerm( 1./nu*sigma22, tau22 ); bf->addTerm( -0.5/nu*sigma11, tau11 ); bf->addTerm( -0.5/nu*sigma22, tau11 ); bf->addTerm( -0.5/nu*sigma11, tau22 ); bf->addTerm( -0.5/nu*sigma22, tau22 ); bf->addTerm( 2*u1, tau11->dx() ); bf->addTerm( 2*u1, tau12->dy() ); bf->addTerm( 2*u2, tau12->dx() ); bf->addTerm( 2*u2, tau22->dy() ); bf->addTerm( -2*u1hat, tau11->times_normal_x() ); bf->addTerm( -2*u1hat, tau12->times_normal_y() ); bf->addTerm( -2*u2hat, tau12->times_normal_x() ); bf->addTerm( -2*u2hat, tau22->times_normal_y() ); // momentum equation bf->addTerm( -2.*u1_prev*u1, v1->dx() ); bf->addTerm( -u2_prev*u1, v1->dy() ); bf->addTerm( -u1_prev*u2, v1->dy() ); bf->addTerm( -u2_prev*u1, v2->dx() ); bf->addTerm( -u1_prev*u2, v2->dx() ); bf->addTerm( -2.*u2_prev*u2, v2->dy() ); bf->addTerm( sigma11, v1->dx() ); bf->addTerm( sigma12, v1->dy() ); bf->addTerm( sigma12, v2->dx() ); bf->addTerm( sigma22, v2->dy() ); bf->addTerm( t1hat, v1); bf->addTerm( t2hat, v2); //////////////////// SPECIFY RHS /////////////////////// RHSPtr rhs = RHS::rhs(); // stress equation rhs->addTerm( -2*u1_prev * tau11->dx() ); rhs->addTerm( -2*u1_prev * tau12->dy() ); rhs->addTerm( -2*u2_prev * tau12->dx() ); rhs->addTerm( -2*u2_prev * tau22->dy() ); // momentum equation rhs->addTerm( u1_prev*u1_prev * v1->dx() ); rhs->addTerm( u2_prev*u1_prev * v1->dy() ); rhs->addTerm( u2_prev*u1_prev * v2->dx() ); rhs->addTerm( u2_prev*u2_prev * v2->dy() ); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = Teuchos::rcp(new IP); if (norm == 0) { ip = bf->graphNorm(); } else if (norm == 1) { ip->addTerm( 0.5/nu*tau11-0.5/nu*tau22 + v1->dx() ); ip->addTerm( 1./nu*tau12 + v1->dy() ); ip->addTerm( 1./nu*tau12 + v2->dx() ); ip->addTerm( 0.5/nu*tau22-0.5/nu*tau11 + v2->dy() ); ip->addTerm( 2*tau11->dx() + 2*tau12->dy() - 2*u1_prev*v1->dx() - u2_prev*v1->dy() - u2_prev*v2->dx() ); ip->addTerm( 2*tau12->dx() + 2*tau22->dy() - 2*u2_prev*v2->dy() - u1_prev*v1->dy() - u1_prev*v2->dx() ); ip->addTerm( v1 ); ip->addTerm( v2 ); ip->addTerm( tau11 ); ip->addTerm( tau12 ); ip->addTerm( tau12 ); ip->addTerm( tau22 ); } else if (norm == 2) { // ip->addTerm( 0.5/sqrt(nu)*tau11-0.5/nu*tau22 ); // ip->addTerm( 1./sqrt(nu)*tau12 ); // ip->addTerm( 1./sqrt(nu)*tau12 ); // ip->addTerm( 0.5/sqrt(nu)*tau22-0.5/nu*tau11 ); ip->addTerm( tau11 ); ip->addTerm( tau12 ); ip->addTerm( tau12 ); ip->addTerm( tau22 ); ip->addTerm( 2*tau11->dx() + 2*tau12->dy() - 2*u1_prev*v1->dx() - u2_prev*v1->dy() - u2_prev*v2->dx() ); ip->addTerm( 2*tau12->dx() + 2*tau22->dy() - 2*u2_prev*v2->dy() - u1_prev*v1->dy() - u1_prev*v2->dx() ); ip->addTerm( 2*u1_prev*v1->dx() + u2_prev*v1->dy() + u2_prev*v2->dx() ); ip->addTerm( 2*u2_prev*v2->dy() + u1_prev*v1->dy() + u1_prev*v2->dx() ); ip->addTerm( sqrt(nu)*v1->grad() ); ip->addTerm( sqrt(nu)*v2->grad() ); ip->addTerm( v1 ); ip->addTerm( v2 ); } //////////////////// CREATE BCs /////////////////////// BCPtr bc = BC::bc(); // Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp( new PenaltyConstraints ); SpatialFilterPtr left = Teuchos::rcp( new ConstantXBoundary(-0.5) ); SpatialFilterPtr right = Teuchos::rcp( new ConstantXBoundary(1) ); SpatialFilterPtr top = Teuchos::rcp( new ConstantYBoundary(-0.5) ); SpatialFilterPtr bottom = Teuchos::rcp( new ConstantYBoundary(1.5) ); bc->addDirichlet(u1hat, left, u1Exact); bc->addDirichlet(u2hat, left, u2Exact); bc->addDirichlet(u1hat, right, u1Exact); bc->addDirichlet(u2hat, right, u2Exact); bc->addDirichlet(u1hat, top, u1Exact); bc->addDirichlet(u2hat, top, u2Exact); bc->addDirichlet(u1hat, bottom, u1Exact); bc->addDirichlet(u2hat, bottom, u2Exact); // bc->addDirichlet(u1hat, left, zero); // bc->addDirichlet(u2hat, left, zero); // bc->addDirichlet(u1hat, right, zero); // bc->addDirichlet(u2hat, right, zero); // bc->addDirichlet(u1hat, top, zero); // bc->addDirichlet(u2hat, top, zero); // bc->addDirichlet(u1hat, bottom, zero); // bc->addDirichlet(u2hat, bottom, zero); // pc->addConstraint(u1hat*u2hat-t1hat == zero, top); // pc->addConstraint(u2hat*u2hat-t2hat == zero, top); Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); // solution->setFilter(pc); // if (enforceLocalConservation) { // solution->lagrangeConstraints()->addConstraint(u1hat->times_normal_x() + u2hat->times_normal_y() == zero); // } // ==================== Register Solutions ========================== mesh->registerSolution(solution); mesh->registerSolution(backgroundFlow); // Teuchos::RCP< RefinementHistory > refHistory = Teuchos::rcp( new RefinementHistory ); // mesh->registerObserver(refHistory); //////////////////// SOLVE & REFINE /////////////////////// double energyThreshold = 0.2; // for mesh refinements RefinementStrategy refinementStrategy( solution, energyThreshold ); HDF5Exporter exporter(mesh, "Kovasznay_np"); ofstream convOut; stringstream convOutFile; convOutFile << "Kovasznay_conv_" << Re <<".txt"; if (commRank == 0) convOut.open(convOutFile.str().c_str()); set<int> nonlinearVars; nonlinearVars.insert(u1->ID()); nonlinearVars.insert(u2->ID()); double nonlinearRelativeEnergyTolerance = 1e-5; // used to determine convergence of the nonlinear solution for (int refIndex=0; refIndex<=numRefs; refIndex++) { double L2Update = 1e10; int iterCount = 0; while (L2Update > nonlinearRelativeEnergyTolerance && iterCount < maxNewtonIterations) { solution->solve(false); double u1L2Update = solution->L2NormOfSolutionGlobal(u1->ID()); double u2L2Update = solution->L2NormOfSolutionGlobal(u2->ID()); L2Update = sqrt(u1L2Update*u1L2Update + u2L2Update*u2L2Update); // Check local conservation if (commRank == 0) { cout << "L2 Norm of Update = " << L2Update << endl; // if (saveFile.length() > 0) { // std::ostringstream oss; // oss << string(saveFile) << refIndex ; // cout << "on refinement " << refIndex << " saving mesh file to " << oss.str() << endl; // refHistory->saveToFile(oss.str()); // } } // line search algorithm double alpha = 1.0; backgroundFlow->addSolution(solution, alpha, nonlinearVars); iterCount++; } exporter.exportSolution(backgroundFlow, varFactory, refIndex, 2, cellIDToSubdivision(mesh, 4)); FunctionPtr u1Soln = Function::solution(u1, backgroundFlow); FunctionPtr u2Soln = Function::solution(u2, backgroundFlow); FunctionPtr u1Sqr = (u1Soln-u1Exact)*(u1Soln-u1Exact); FunctionPtr u2Sqr = (u2Soln-u2Exact)*(u2Soln-u2Exact); double u1L2Error = u1Sqr->integrate(mesh, 1e-5); double u2L2Error = u2Sqr->integrate(mesh, 1e-5); double l2Error = sqrt(u1L2Error+u2L2Error); double energyError = solution->energyErrorTotal(); cout << "L2 Error: " << l2Error << " Energy Error: " << energyError << endl; if (refIndex < numRefs) refinementStrategy.refine(commRank==0); // print to console on commRank 0 } 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(); Teuchos::CommandLineProcessor cmdp(false,true); // false: don't throw exceptions; true: do return errors for unrecognized options bool useCondensedSolve = false; // condensed solve not yet compatible with minimum rule meshes int numGridPoints = 32; // in x,y -- idea is to keep the overall order of approximation constant int k = 4; // poly order for u double theta = 0.5; int numTimeSteps = 2000; int numCells = -1; // in x, y (-1 so we can set a default if unset from the command line.) int numFrames = 50; int delta_k = 2; // test space enrichment: should be 2 for 2D bool useMumpsIfAvailable = true; bool convertSolutionsToVTK = false; // when true assumes we've already run with precisely the same options, except without VTK support (so we have a bunch of .soln files) bool usePeriodicBCs = false; bool useConstantConvection = false; cmdp.setOption("polyOrder",&k,"polynomial order for field variable u"); cmdp.setOption("delta_k", &delta_k, "test space polynomial order enrichment"); cmdp.setOption("numCells",&numCells,"number of cells in x and y directions"); cmdp.setOption("theta",&theta,"theta weight for time-stepping"); cmdp.setOption("numTimeSteps",&numTimeSteps,"number of time steps"); cmdp.setOption("numFrames",&numFrames,"number of frames for export"); cmdp.setOption("usePeriodicBCs", "useDirichletBCs", &usePeriodicBCs); cmdp.setOption("useConstantConvection", "useVariableConvection", &useConstantConvection); cmdp.setOption("useCondensedSolve", "useUncondensedSolve", &useCondensedSolve, "use static condensation to reduce the size of the global solve"); cmdp.setOption("useMumps", "useKLU", &useMumpsIfAvailable, "use MUMPS (if available)"); cmdp.setOption("convertPreComputedSolutionsToVTK", "computeSolutions", &convertSolutionsToVTK); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { #ifdef HAVE_MPI MPI_Finalize(); #endif return -1; } bool saveSolutionFiles = true; if (numCells==-1) numCells = numGridPoints / k; if (rank==0) { cout << "solving on " << numCells << " x " << numCells << " mesh " << "of order " << k << ".\n"; } set<int> timeStepsToExport; timeStepsToExport.insert(numTimeSteps); int timeStepsPerFrame = numTimeSteps / (numFrames - 1); if (timeStepsPerFrame==0) timeStepsPerFrame = 1; for (int n=0; n<numTimeSteps; n += timeStepsPerFrame) { timeStepsToExport.insert(n); } int H1Order = k + 1; const static double PI = 3.141592653589793238462; double dt = 2 * PI / numTimeSteps; VarFactory varFactory; // traces: VarPtr qHat = varFactory.fluxVar("\\widehat{q}"); // fields: VarPtr u = varFactory.fieldVar("u", L2); // test functions: VarPtr v = varFactory.testVar("v", HGRAD); FunctionPtr x = Function::xn(1); FunctionPtr y = Function::yn(1); FunctionPtr c; if (useConstantConvection) { c = Function::vectorize(Function::constant(0.5), Function::constant(0.5)); } else { c = Function::vectorize(y-0.5, 0.5-x); } // FunctionPtr c = Function::vectorize(y, x); FunctionPtr n = Function::normal(); BFPtr bf = Teuchos::rcp( new BF(varFactory) ); bf->addTerm(u / dt, v); bf->addTerm(- theta * u, c * v->grad()); // bf->addTerm(theta * u_hat, (c * n) * v); bf->addTerm(qHat, v); double width = 2.0, height = 2.0; int horizontalCells = numCells, verticalCells = numCells; double x0 = -0.5; double y0 = -0.5; if (usePeriodicBCs) { x0 = 0.0; y0 = 0.0; width = 1.0; height = 1.0; } BCPtr bc = BC::bc(); SpatialFilterPtr inflowFilter = Teuchos::rcp( new InflowFilterForClockwisePlanarRotation (x0,x0+width,y0,y0+height,0.5,0.5)); vector< PeriodicBCPtr > periodicBCs; if (! usePeriodicBCs) { // bc->addDirichlet(u_hat, SpatialFilter::allSpace(), Function::zero()); bc->addDirichlet(qHat, inflowFilter, Function::zero()); // zero BCs enforced at the inflow boundary. } else { periodicBCs.push_back(PeriodicBC::xIdentification(x0, x0+width)); periodicBCs.push_back(PeriodicBC::yIdentification(y0, y0+height)); } MeshPtr mesh = MeshFactory::quadMeshMinRule(bf, H1Order, delta_k, width, height, horizontalCells, verticalCells, false, x0, y0, periodicBCs); FunctionPtr u0 = Teuchos::rcp( new Cone_U0(0.0, 0.25, 0.1, 1.0, usePeriodicBCs) ); RHSPtr initialRHS = RHS::rhs(); initialRHS->addTerm(u0 / dt * v); initialRHS->addTerm((1-theta) * u0 * c * v->grad()); IPPtr ip; // ip = Teuchos::rcp( new IP ); // ip->addTerm(v); // ip->addTerm(c * v->grad()); ip = bf->graphNorm(); // create two Solution objects; we'll switch between these for time steps SolutionPtr soln0 = Solution::solution(mesh, bc, initialRHS, ip); soln0->setCubatureEnrichmentDegree(5); FunctionPtr u_soln0 = Function::solution(u, soln0); FunctionPtr qHat_soln0 = Function::solution(qHat, soln0); RHSPtr rhs1 = RHS::rhs(); rhs1->addTerm(u_soln0 / dt * v); rhs1->addTerm((1-theta) * u_soln0 * c * v->grad()); SolutionPtr soln1 = Solution::solution(mesh, bc, rhs1, ip); soln1->setCubatureEnrichmentDegree(5); FunctionPtr u_soln1 = Function::solution(u, soln1); FunctionPtr qHat_soln1 = Function::solution(qHat, soln1); RHSPtr rhs2 = RHS::rhs(); // after the first solve on soln0, we'll swap out initialRHS for rhs2 rhs2->addTerm(u_soln1 / dt * v); rhs2->addTerm((1-theta) * u_soln1 * c * v->grad()); Teuchos::RCP<Solver> solver = Teuchos::rcp( new KluSolver ); #ifdef HAVE_AMESOS_MUMPS if (useMumpsIfAvailable) solver = Teuchos::rcp( new MumpsSolver ); #endif // double energyErrorSum = 0; ostringstream filePrefix; filePrefix << "convectingCone_k" << k << "_t"; int frameNumber = 0; #ifdef USE_HDF5 ostringstream dir_name; dir_name << "convectingCone_k" << k; HDF5Exporter exporter(mesh,dir_name.str()); #endif #ifdef USE_VTK VTKExporter soln0Exporter(soln0,mesh,varFactory); VTKExporter soln1Exporter(soln1,mesh,varFactory); #endif if (convertSolutionsToVTK) { #ifdef USE_VTK if (rank==0) { cout << "Converting .soln files to VTK.\n"; for (int frameNumber=0; frameNumber<=numFrames; frameNumber++) { ostringstream filename; filename << filePrefix.str() << frameNumber << ".soln"; soln0->readFromFile(filename.str()); filename.str(""); filename << filePrefix.str() << frameNumber; soln0Exporter.exportFields(filename.str()); } } #else if (rank==0) cout << "Driver was built without USE_VTK defined. This must be defined to convert solution files to VTK files.\n"; #endif exit(0); } if (timeStepsToExport.find(0) != timeStepsToExport.end()) { map<int,FunctionPtr> solnMap; solnMap[u->ID()] = u0; // project field variables if (rank==0) cout << "About to project initial solution onto mesh.\n"; soln0->projectOntoMesh(solnMap); if (rank==0) cout << "...projected initial solution onto mesh.\n"; ostringstream filename; filename << filePrefix.str() << frameNumber++; if (rank==0) cout << "About to export initial solution.\n"; #ifdef USE_VTK if (rank==0) soln0Exporter.exportFields(filename.str()); #endif #ifdef USE_HDF5 exporter.exportSolution(soln0, varFactory,0); #endif if (saveSolutionFiles) { if (rank==0) { filename << ".soln"; soln0->writeToFile(filename.str()); cout << endl << "wrote " << filename.str() << endl; } } if (rank==0) cout << "...exported initial solution.\n"; } if (rank==0) cout << "About to solve initial time step.\n"; // first time step: soln0->setReportTimingResults(true); // added to gain insight into why MPI blocks in some cases on the server... if (useCondensedSolve) soln0->condensedSolve(solver); else soln0->solve(solver); soln0->setReportTimingResults(false); // energyErrorSum += soln0->energyErrorTotal(); soln0->setRHS(rhs2); if (rank==0) cout << "Solved initial time step.\n"; if (timeStepsToExport.find(1) != timeStepsToExport.end()) { ostringstream filename; filename << filePrefix.str() << frameNumber++; #ifdef USE_VTK if (rank==0) soln0Exporter.exportFields(filename.str()); #endif #ifdef USE_HDF5 exporter.exportSolution(soln0, varFactory); #endif if (saveSolutionFiles) { if (rank==0) { filename << ".soln"; soln0->writeToFile(filename.str()); cout << endl << "wrote " << filename.str() << endl; } } } bool reportTimings = false; for (int n=1; n<numTimeSteps; n++) { bool odd = (n%2)==1; SolutionPtr soln_n = odd ? soln1 : soln0; if (useCondensedSolve) soln_n->solve(solver); else soln_n->solve(solver); if (reportTimings) { if (rank==0) cout << "time step " << n << ", timing report:\n"; soln_n->reportTimings(); } if (rank==0) { cout << "\x1B[2K"; // Erase the entire current line. cout << "\x1B[0E"; // Move to the beginning of the current line. cout << "Solved time step: " << n; flush(cout); } if (timeStepsToExport.find(n+1)!=timeStepsToExport.end()) { ostringstream filename; filename << filePrefix.str() << frameNumber++; #ifdef USE_VTK if (rank==0) { if (odd) { soln1Exporter.exportFields(filename.str()); } else { soln0Exporter.exportFields(filename.str()); } } #endif #ifdef USE_HDF5 double t = n * dt; if (odd) { exporter.exportSolution(soln1, varFactory, t); } else { exporter.exportSolution(soln0, varFactory, t); } #endif if (saveSolutionFiles) { if (rank==0) { filename << ".soln"; if (odd) { soln1->writeToFile(filename.str()); } else { soln0->writeToFile(filename.str()); } cout << endl << "wrote " << filename.str() << endl; } } } // energyErrorSum += soln_n->energyErrorTotal(); } // if (rank==0) cout << "energy error, sum over all time steps: " << energyErrorSum << endl; return 0; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); Epetra_MpiComm Comm(MPI_COMM_WORLD); #else Epetra_SerialComm Comm; #endif int commRank = Teuchos::GlobalMPISession::getRank(); Comm.Barrier(); // set breakpoint here to allow debugger attachment to other MPI processes than the one you automatically attached to. Teuchos::CommandLineProcessor cmdp(false,true); // false: don't throw exceptions; true: do return errors for unrecognized options // problem parameters: double mu = 0.1; double permCoef = 1e4; int numRefs = 0; int k = 2, delta_k = 2; string norm = "Graph"; cmdp.setOption("polyOrder",&k,"polynomial order for field variable u"); cmdp.setOption("delta_k", &delta_k, "test space polynomial order enrichment"); cmdp.setOption("numRefs",&numRefs,"number of refinements"); cmdp.setOption("norm", &norm, "norm"); cmdp.setOption("mu", &mu, "mu"); cmdp.setOption("permCoef", &permCoef, "Permeability coefficient"); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { #ifdef HAVE_MPI MPI_Finalize(); #endif return -1; } FunctionPtr zero = TFunction<double>::zero(); FunctionPtr one = TFunction<double>::constant(1); FunctionPtr sin2pix = Teuchos::rcp( new Sin_ax(2*pi) ); FunctionPtr cos2pix = Teuchos::rcp( new Cos_ax(2*pi) ); FunctionPtr sin2piy = Teuchos::rcp( new Sin_ay(2*pi) ); FunctionPtr cos2piy = Teuchos::rcp( new Cos_ay(2*pi) ); FunctionPtr u1_exact = sin2pix*cos2piy; FunctionPtr u2_exact = -cos2pix*sin2piy; FunctionPtr x2 = TFunction<double>::xn(2); FunctionPtr y2 = TFunction<double>::yn(2); FunctionPtr p_exact = x2*y2 - 1./9; FunctionPtr permInv = permCoef*(sin2pix + 1.1); VarFactoryPtr vf = VarFactory::varFactory(); //fields: VarPtr sigma1 = vf->fieldVar("sigma1", VECTOR_L2); VarPtr sigma2 = vf->fieldVar("sigma2", VECTOR_L2); VarPtr u1 = vf->fieldVar("u1", L2); VarPtr u2 = vf->fieldVar("u2", L2); VarPtr p = vf->fieldVar("p", L2); // traces: VarPtr u1hat = vf->traceVar("u1hat"); VarPtr u2hat = vf->traceVar("u2hat"); VarPtr t1c = vf->fluxVar("t1c"); VarPtr t2c = vf->fluxVar("t2c"); // test: VarPtr v1 = vf->testVar("v1", HGRAD); VarPtr v2 = vf->testVar("v2", HGRAD); VarPtr tau1 = vf->testVar("tau1", HDIV); VarPtr tau2 = vf->testVar("tau2", HDIV); VarPtr q = vf->testVar("q", HGRAD); BFPtr bf = Teuchos::rcp( new BF(vf) ); bf->addTerm(1./mu*sigma1, tau1); bf->addTerm(1./mu*sigma2, tau2); bf->addTerm(u1, tau1->div()); bf->addTerm(u2, tau2->div()); bf->addTerm(-u1hat, tau1->dot_normal()); bf->addTerm(-u2hat, tau2->dot_normal()); bf->addTerm(sigma1, v1->grad()); bf->addTerm(sigma2, v2->grad()); bf->addTerm(-p, v1->dx()); bf->addTerm(-p, v2->dy()); bf->addTerm(t1c, v1); bf->addTerm(t2c, v2); bf->addTerm(mu*permInv*u1, v1); bf->addTerm(mu*permInv*u2, v2); bf->addTerm(-u1, q->dx()); bf->addTerm(-u2, q->dy()); bf->addTerm(u1hat, q->times_normal_x()); bf->addTerm(u2hat, q->times_normal_y()); RHSPtr rhs = RHS::rhs(); BCPtr bc = BC::bc(); SpatialFilterPtr y_equals_one = SpatialFilter::matchingY(1.0); SpatialFilterPtr y_equals_zero = SpatialFilter::matchingY(0); SpatialFilterPtr x_equals_one = SpatialFilter::matchingX(1.0); SpatialFilterPtr x_equals_zero = SpatialFilter::matchingX(0.0); bc->addDirichlet(u1hat, y_equals_zero, u1_exact); bc->addDirichlet(u2hat, y_equals_zero, u2_exact); bc->addDirichlet(u1hat, x_equals_zero, u1_exact); bc->addDirichlet(u2hat, x_equals_zero, u2_exact); bc->addDirichlet(u1hat, y_equals_one, u1_exact); bc->addDirichlet(u2hat, y_equals_one, u2_exact); bc->addDirichlet(u1hat, x_equals_one, u1_exact); bc->addDirichlet(u2hat, x_equals_one, u2_exact); bc->addZeroMeanConstraint(p); MeshPtr mesh = MeshFactory::quadMesh(bf, k+1, delta_k, 1, 1, 4, 4); map<string, IPPtr> brinkmanIPs; brinkmanIPs["Graph"] = bf->graphNorm(); brinkmanIPs["Decoupled"] = Teuchos::rcp(new IP); brinkmanIPs["Decoupled"]->addTerm(tau1); brinkmanIPs["Decoupled"]->addTerm(tau2); brinkmanIPs["Decoupled"]->addTerm(tau1->div()); brinkmanIPs["Decoupled"]->addTerm(tau2->div()); brinkmanIPs["Decoupled"]->addTerm(permInv*v1); brinkmanIPs["Decoupled"]->addTerm(permInv*v2); brinkmanIPs["Decoupled"]->addTerm(v1->grad()); brinkmanIPs["Decoupled"]->addTerm(v2->grad()); brinkmanIPs["Decoupled"]->addTerm(q); brinkmanIPs["Decoupled"]->addTerm(q->grad()); // brinkmanIPs["CoupledRobust"] = Teuchos::rcp(new IP); // brinkmanIPs["CoupledRobust"]->addTerm(tau->div()-beta*v->grad()); // brinkmanIPs["CoupledRobust"]->addTerm(Function<double>::min(one/Function<double>::h(),Function<double>::constant(1./sqrt(epsilon)))*tau); // brinkmanIPs["CoupledRobust"]->addTerm(sqrt(epsilon)*v->grad()); // brinkmanIPs["CoupledRobust"]->addTerm(beta*v->grad()); // brinkmanIPs["CoupledRobust"]->addTerm(Function<double>::min(sqrt(epsilon)*one/Function<double>::h(),one)*v); IPPtr ip = brinkmanIPs[norm]; SolutionPtr soln = TSolution<double>::solution(mesh, bc, rhs, ip); double threshold = 0.20; RefinementStrategy refStrategy(soln, threshold); ostringstream refName; refName << "brinkman"; HDF5Exporter exporter(mesh,refName.str()); for (int refIndex=0; refIndex <= numRefs; refIndex++) { soln->solve(false); double energyError = soln->energyErrorTotal(); if (commRank == 0) { // if (refIndex > 0) // refStrategy.printRefinementStatistics(refIndex-1); cout << "Refinement:\t " << refIndex << " \tElements:\t " << mesh->numActiveElements() << " \tDOFs:\t " << mesh->numGlobalDofs() << " \tEnergy Error:\t " << energyError << endl; } exporter.exportSolution(soln, refIndex); if (refIndex != numRefs) refStrategy.refine(); } return 0; }
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; }
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); // // } // } }
bool ScratchPadTests::testGalerkinOrthogonality() { double tol = 1e-11; bool success = true; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr v = varFactory->testVar("v", HGRAD); vector<double> beta; beta.push_back(1.0); beta.push_back(1.0); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// // robust test norm IPPtr ip = Teuchos::rcp(new IP); ip->addTerm(v); ip->addTerm(beta*v->grad()); // define trial variables VarPtr beta_n_u = varFactory->fluxVar("\\widehat{\\beta \\cdot n }"); VarPtr u = varFactory->fieldVar("u"); //////////////////// BUILD MESH /////////////////////// BFPtr convectionBF = Teuchos::rcp( new BF(varFactory) ); FunctionPtr n = Function::normal(); // v terms: convectionBF->addTerm( -u, beta * v->grad() ); convectionBF->addTerm( beta_n_u, v); // define nodes for mesh int order = 2; int H1Order = order+1; int pToAdd = 1; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = MeshUtilities::buildUnitQuadMesh(4, convectionBF, H1Order, H1Order+pToAdd); //////////////////// SOLVE /////////////////////// RHSPtr rhs = RHS::rhs(); BCPtr bc = BC::bc(); SpatialFilterPtr inflowBoundary = Teuchos::rcp( new InflowSquareBoundary ); SpatialFilterPtr outflowBoundary = Teuchos::rcp( new NegatedSpatialFilter(inflowBoundary) ); FunctionPtr uIn; uIn = Teuchos::rcp(new Uinflow); // uses a discontinuous piecewise-constant basis function on left and bottom sides of square bc->addDirichlet(beta_n_u, inflowBoundary, beta*n*uIn); Teuchos::RCP<Solution> solution; solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); solution->solve(false); FunctionPtr uFxn = Function::solution(u, solution); FunctionPtr fnhatFxn = Function::solution(beta_n_u,solution); // make residual for riesz representation function LinearTermPtr residual = Teuchos::rcp(new LinearTerm);// residual FunctionPtr parity = Function::sideParity(); residual->addTerm(-fnhatFxn*v + (beta*uFxn)*v->grad()); Teuchos::RCP<RieszRep> riesz = Teuchos::rcp(new RieszRep(mesh, ip, residual)); riesz->computeRieszRep(); map<int,FunctionPtr> err_rep_map; err_rep_map[v->ID()] = RieszRep::repFunction(v,riesz); //////////////////// GET BOUNDARY CONDITION DATA /////////////////////// FieldContainer<GlobalIndexType> bcGlobalIndices; FieldContainer<double> bcGlobalValues; mesh->boundary().bcsToImpose(bcGlobalIndices,bcGlobalValues,*(solution->bc()), NULL); set<int> bcInds; for (int i=0; i<bcGlobalIndices.dimension(0); i++) { bcInds.insert(bcGlobalIndices(i)); } //////////////////// CHECK GALERKIN ORTHOGONALITY /////////////////////// BCPtr nullBC; RHSPtr nullRHS; IPPtr nullIP; SolutionPtr solnPerturbation = Teuchos::rcp(new Solution(mesh, nullBC, nullRHS, nullIP) ); map< int, vector<DofInfo> > infoMap = constructGlobalDofToLocalDofInfoMap(mesh); for (map< int, vector<DofInfo> >::iterator mapIt = infoMap.begin(); mapIt != infoMap.end(); mapIt++) { int dofIndex = mapIt->first; vector< DofInfo > dofInfoVector = mapIt->second; // all the local dofs that map to dofIndex // create perturbation in direction du solnPerturbation->clear(); // clear all solns // set each corresponding local dof to 1.0 for (vector< DofInfo >::iterator dofInfoIt = dofInfoVector.begin(); dofInfoIt != dofInfoVector.end(); dofInfoIt++) { DofInfo info = *dofInfoIt; FieldContainer<double> solnCoeffs(info.basisCardinality); solnCoeffs(info.basisOrdinal) = 1.0; solnPerturbation->setSolnCoeffsForCellID(solnCoeffs, info.cellID, info.trialID, info.sideIndex); } // solnPerturbation->setSolnCoeffForGlobalDofIndex(1.0,dofIndex); LinearTermPtr b_du = convectionBF->testFunctional(solnPerturbation); FunctionPtr gradient = b_du->evaluate(err_rep_map, TestingUtilities::isFluxOrTraceDof(mesh,dofIndex)); // use boundary part only if flux double grad = gradient->integrate(mesh,10); if (!TestingUtilities::isFluxOrTraceDof(mesh,dofIndex) && abs(grad)>tol) // if we're not single-precision zero FOR FIELDS { // int cellID = mesh->getGlobalToLocalMap()[dofIndex].first; cout << "Failed testGalerkinOrthogonality() for fields with diff " << abs(grad) << " at dof " << dofIndex << "; info:" << endl; cout << dofInfoString(infoMap[dofIndex]); success = false; } } FieldContainer<double> errorJumps(mesh->numGlobalDofs()); //initialized to zero // just test fluxes ON INTERNAL SKELETON here set<GlobalIndexType> activeCellIDs = mesh->getActiveCellIDsGlobal(); for (GlobalIndexType activeCellID : activeCellIDs) { ElementPtr elem = mesh->getElement(activeCellID); for (int sideIndex = 0; sideIndex < 4; sideIndex++) { ElementTypePtr elemType = elem->elementType(); vector<int> localDofIndices = elemType->trialOrderPtr->getDofIndices(beta_n_u->ID(), sideIndex); for (int i = 0; i<localDofIndices.size(); i++) { int globalDofIndex = mesh->globalDofIndex(elem->cellID(), localDofIndices[i]); vector< DofInfo > dofInfoVector = infoMap[globalDofIndex]; solnPerturbation->clear(); TestingUtilities::setSolnCoeffForGlobalDofIndex(solnPerturbation,1.0,globalDofIndex); // also add in BCs for (int i = 0; i<bcGlobalIndices.dimension(0); i++) { TestingUtilities::setSolnCoeffForGlobalDofIndex(solnPerturbation,bcGlobalValues(i),bcGlobalIndices(i)); } LinearTermPtr b_du = convectionBF->testFunctional(solnPerturbation); FunctionPtr gradient = b_du->evaluate(err_rep_map, TestingUtilities::isFluxOrTraceDof(mesh,globalDofIndex)); // use boundary part only if flux double jump = gradient->integrate(mesh,10); errorJumps(globalDofIndex) += jump; } } } for (int i = 0; i<mesh->numGlobalDofs(); i++) { if (abs(errorJumps(i))>tol) { cout << "Failing Galerkin orthogonality test for fluxes with diff " << errorJumps(i) << " at dof " << i << endl; cout << dofInfoString(infoMap[i]); success = false; } } return success; }
int main(int argc, char *argv[]) { int rank = 0; #ifdef HAVE_MPI // TODO: figure out the right thing to do here... // may want to modify argc and argv before we make the following call: Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); rank=mpiSession.getRank(); #else #endif bool useLineSearch = false; int pToAdd = 2; // for optimal test function approximation int pToAddForStreamFunction = 2; double nonlinearStepSize = 1.0; double dt = 0.5; double nonlinearRelativeEnergyTolerance = 0.015; // used to determine convergence of the nonlinear solution // double nonlinearRelativeEnergyTolerance = 0.15; // used to determine convergence of the nonlinear solution double eps = 1.0/64.0; // width of ramp up to 1.0 for top BC; eps == 0 ==> soln not in H1 // epsilon above is chosen to match our initial 16x16 mesh, to avoid quadrature errors. // double eps = 0.0; // John Evans's problem: not in H^1 bool enforceLocalConservation = false; bool enforceOneIrregularity = true; bool reportPerCellErrors = true; bool useMumps = true; int horizontalCells, verticalCells; int maxIters = 50; // for nonlinear steps vector<double> ReValues; // usage: polyOrder [numRefinements] // parse args: if (argc < 6) { cout << "Usage: NavierStokesCavityFlowContinuationFixedMesh fieldPolyOrder hCells vCells energyErrorGoal Re0 [Re1 ...]\n"; return -1; } int polyOrder = atoi(argv[1]); horizontalCells = atoi(argv[2]); verticalCells = atoi(argv[3]); double energyErrorGoal = atof(argv[4]); for (int i=5; i<argc; i++) { ReValues.push_back(atof(argv[i])); } if (rank == 0) { cout << "L^2 order: " << polyOrder << endl; cout << "initial mesh size: " << horizontalCells << " x " << verticalCells << endl; cout << "energy error goal: " << energyErrorGoal << endl; cout << "Reynolds number values for continuation:\n"; for (int i=0; i<ReValues.size(); i++) { cout << ReValues[i] << ", "; } cout << endl; } 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; // define meshes: int H1Order = polyOrder + 1; bool useTriangles = false; bool meshHasTriangles = useTriangles; double minL2Increment = 1e-8; // get variable definitions: VarFactory varFactory = VGPStokesFormulation::vgpVarFactory(); u1 = varFactory.fieldVar(VGP_U1_S); u2 = varFactory.fieldVar(VGP_U2_S); sigma11 = varFactory.fieldVar(VGP_SIGMA11_S); sigma12 = varFactory.fieldVar(VGP_SIGMA12_S); sigma21 = varFactory.fieldVar(VGP_SIGMA21_S); sigma22 = varFactory.fieldVar(VGP_SIGMA22_S); p = varFactory.fieldVar(VGP_P_S); u1hat = varFactory.traceVar(VGP_U1HAT_S); u2hat = varFactory.traceVar(VGP_U2HAT_S); t1n = varFactory.fluxVar(VGP_T1HAT_S); t2n = varFactory.fluxVar(VGP_T2HAT_S); v1 = varFactory.testVar(VGP_V1_S, HGRAD); v2 = varFactory.testVar(VGP_V2_S, HGRAD); tau1 = varFactory.testVar(VGP_TAU1_S, HDIV); tau2 = varFactory.testVar(VGP_TAU2_S, HDIV); q = varFactory.testVar(VGP_Q_S, HGRAD); FunctionPtr u1_0 = Teuchos::rcp( new U1_0(eps) ); FunctionPtr u2_0 = Teuchos::rcp( new U2_0 ); FunctionPtr zero = Function::zero(); ParameterFunctionPtr Re_param = ParameterFunction::parameterFunction(1); VGPNavierStokesProblem problem = VGPNavierStokesProblem(Re_param,quadPoints, horizontalCells,verticalCells, H1Order, pToAdd, u1_0, u2_0, // BC for u zero, zero); // zero forcing function SolutionPtr solution = problem.backgroundFlow(); SolutionPtr solnIncrement = problem.solutionIncrement(); Teuchos::RCP<Mesh> mesh = problem.mesh(); mesh->registerSolution(solution); mesh->registerSolution(solnIncrement); /////////////////////////////////////////////////////////////////////////// // define bilinear form for stream function: VarFactory streamVarFactory; VarPtr phi_hat = streamVarFactory.traceVar("\\widehat{\\phi}"); VarPtr psin_hat = streamVarFactory.fluxVar("\\widehat{\\psi}_n"); VarPtr psi_1 = streamVarFactory.fieldVar("\\psi_1"); VarPtr psi_2 = streamVarFactory.fieldVar("\\psi_2"); VarPtr phi = streamVarFactory.fieldVar("\\phi"); VarPtr q_s = streamVarFactory.testVar("q_s", HGRAD); VarPtr v_s = streamVarFactory.testVar("v_s", HDIV); BFPtr streamBF = Teuchos::rcp( new BF(streamVarFactory) ); streamBF->addTerm(psi_1, q_s->dx()); streamBF->addTerm(psi_2, q_s->dy()); streamBF->addTerm(-psin_hat, q_s); streamBF->addTerm(psi_1, v_s->x()); streamBF->addTerm(psi_2, v_s->y()); streamBF->addTerm(phi, v_s->div()); streamBF->addTerm(-phi_hat, v_s->dot_normal()); Teuchos::RCP<Mesh> streamMesh, overkillMesh; streamMesh = MeshFactory::buildQuadMesh(quadPoints, horizontalCells, verticalCells, streamBF, H1Order+pToAddForStreamFunction, H1Order+pToAdd+pToAddForStreamFunction, useTriangles); mesh->registerObserver(streamMesh); // will refine streamMesh in the same way as mesh. map<int, double> dofsToL2error; // key: numGlobalDofs, value: total L2error compared with overkill vector< VarPtr > fields; fields.push_back(u1); fields.push_back(u2); fields.push_back(sigma11); fields.push_back(sigma12); fields.push_back(sigma21); fields.push_back(sigma22); fields.push_back(p); if (rank == 0) { cout << "Starting mesh has " << horizontalCells << " x " << verticalCells << " elements and "; cout << mesh->numGlobalDofs() << " total dofs.\n"; cout << "polyOrder = " << polyOrder << endl; cout << "pToAdd = " << pToAdd << endl; cout << "eps for top BC = " << eps << endl; if (useTriangles) { cout << "Using triangles.\n"; } if (enforceLocalConservation) { cout << "Enforcing local conservation.\n"; } else { cout << "NOT enforcing local conservation.\n"; } if (enforceOneIrregularity) { cout << "Enforcing 1-irregularity.\n"; } else { cout << "NOT enforcing 1-irregularity.\n"; } } //////////////////// CREATE BCs /////////////////////// SpatialFilterPtr entireBoundary = Teuchos::rcp( new SpatialFilterUnfiltered ); FunctionPtr u1_prev = Function::solution(u1,solution); FunctionPtr u2_prev = Function::solution(u2,solution); FunctionPtr u1hat_prev = Function::solution(u1hat,solution); FunctionPtr u2hat_prev = Function::solution(u2hat,solution); //////////////////// SOLVE & REFINE /////////////////////// FunctionPtr vorticity = Teuchos::rcp( new PreviousSolutionFunction(solution, - u1->dy() + u2->dx() ) ); // FunctionPtr vorticity = Teuchos::rcp( new PreviousSolutionFunction(solution,sigma12 - sigma21) ); RHSPtr streamRHS = RHS::rhs(); streamRHS->addTerm(vorticity * q_s); ((PreviousSolutionFunction*) vorticity.get())->setOverrideMeshCheck(true); ((PreviousSolutionFunction*) u1_prev.get())->setOverrideMeshCheck(true); ((PreviousSolutionFunction*) u2_prev.get())->setOverrideMeshCheck(true); BCPtr streamBC = BC::bc(); // streamBC->addDirichlet(psin_hat, entireBoundary, u0_cross_n); streamBC->addDirichlet(phi_hat, entireBoundary, zero); // streamBC->addZeroMeanConstraint(phi); IPPtr streamIP = Teuchos::rcp( new IP ); streamIP->addTerm(q_s); streamIP->addTerm(q_s->grad()); streamIP->addTerm(v_s); streamIP->addTerm(v_s->div()); SolutionPtr streamSolution = Teuchos::rcp( new Solution( streamMesh, streamBC, streamRHS, streamIP ) ); if (enforceLocalConservation) { FunctionPtr zero = Function::zero(); solution->lagrangeConstraints()->addConstraint(u1hat->times_normal_x() + u2hat->times_normal_y()==zero); solnIncrement->lagrangeConstraints()->addConstraint(u1hat->times_normal_x() + u2hat->times_normal_y()==zero); } if (true) { FunctionPtr u1_incr = Function::solution(u1, solnIncrement); FunctionPtr u2_incr = Function::solution(u2, solnIncrement); FunctionPtr sigma11_incr = Function::solution(sigma11, solnIncrement); FunctionPtr sigma12_incr = Function::solution(sigma12, solnIncrement); FunctionPtr sigma21_incr = Function::solution(sigma21, solnIncrement); FunctionPtr sigma22_incr = Function::solution(sigma22, solnIncrement); FunctionPtr p_incr = Function::solution(p, solnIncrement); FunctionPtr l2_incr = u1_incr * u1_incr + u2_incr * u2_incr + p_incr * p_incr + sigma11_incr * sigma11_incr + sigma12_incr * sigma12_incr + sigma21_incr * sigma21_incr + sigma22_incr * sigma22_incr; double energyThreshold = 0.20; Teuchos::RCP< RefinementStrategy > refinementStrategy = Teuchos::rcp( new RefinementStrategy( solnIncrement, energyThreshold )); for (int i=0; i<ReValues.size(); i++) { double Re = ReValues[i]; Re_param->setValue(Re); if (rank==0) cout << "Solving with Re = " << Re << ":\n"; double energyErrorTotal; do { double incr_norm; do { problem.iterate(useLineSearch); incr_norm = sqrt(l2_incr->integrate(problem.mesh())); if (rank==0) { cout << "\x1B[2K"; // Erase the entire current line. cout << "\x1B[0E"; // Move to the beginning of the current line. cout << "Iteration: " << problem.iterationCount() << "; L^2(incr) = " << incr_norm; flush(cout); } } while ((incr_norm > minL2Increment ) && (problem.iterationCount() < maxIters)); if (rank==0) cout << endl; problem.setIterationCount(1); // 1 means reuse background flow (which we must, given that we want continuation in Re...) energyErrorTotal = solnIncrement->energyErrorTotal(); //solution->energyErrorTotal(); if (energyErrorTotal > energyErrorGoal) { refinementStrategy->refine(false); } if (rank==0) { cout << "Energy error: " << energyErrorTotal << endl; } } while (energyErrorTotal > energyErrorGoal); } } double energyErrorTotal = solution->energyErrorTotal(); double incrementalEnergyErrorTotal = solnIncrement->energyErrorTotal(); if (rank == 0) { cout << "final mesh has " << mesh->numActiveElements() << " elements and " << mesh->numGlobalDofs() << " dofs.\n"; cout << "energy error: " << energyErrorTotal << endl; cout << " (Incremental solution's energy error is " << incrementalEnergyErrorTotal << ".)\n"; } FunctionPtr u1_sq = u1_prev * u1_prev; FunctionPtr u_dot_u = u1_sq + (u2_prev * u2_prev); FunctionPtr u_mag = Teuchos::rcp( new SqrtFunction( u_dot_u ) ); FunctionPtr u_div = Teuchos::rcp( new PreviousSolutionFunction(solution, u1->dx() + u2->dy() ) ); FunctionPtr massFlux = Teuchos::rcp( new PreviousSolutionFunction(solution, u1hat->times_normal_x() + u2hat->times_normal_y()) ); // check that the zero mean pressure is being correctly imposed: FunctionPtr p_prev = Teuchos::rcp( new PreviousSolutionFunction(solution,p) ); double p_avg = p_prev->integrate(mesh); if (rank==0) cout << "Integral of pressure: " << p_avg << endl; // integrate massFlux over each element (a test): // fake a new bilinear form so we can integrate against 1 VarPtr testOne = varFactory.testVar("1",CONSTANT_SCALAR); BFPtr fakeBF = Teuchos::rcp( new BF(varFactory) ); LinearTermPtr massFluxTerm = massFlux * testOne; CellTopoPtrLegacy 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; double maxCellMeasure = 0; double minCellMeasure = 1; for (vector< ElementTypePtr >::iterator elemTypeIt = elemTypes.begin(); elemTypeIt != elemTypes.end(); elemTypeIt++) { ElementTypePtr elemType = *elemTypeIt; vector< ElementPtr > elems = mesh->elementsOfTypeGlobal(elemType); vector<GlobalIndexType> 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,polyOrder) ); // enrich by trial space order 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 // cout << "fakeRHSIntegrals:\n" << fakeRHSIntegrals; 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]; maxCellMeasure = max(maxCellMeasure,cellMeasures(i)); minCellMeasure = min(minCellMeasure,cellMeasures(i)); maxMassFluxIntegral = max(abs(massFluxIntegral[cellID]), maxMassFluxIntegral); totalMassFlux += massFluxIntegral[cellID]; totalAbsMassFlux += abs( massFluxIntegral[cellID] ); } } if (rank==0) { cout << "largest mass flux: " << maxMassFluxIntegral << endl; cout << "total mass flux: " << totalMassFlux << endl; cout << "sum of mass flux absolute value: " << totalAbsMassFlux << endl; cout << "largest h: " << sqrt(maxCellMeasure) << endl; cout << "smallest h: " << sqrt(minCellMeasure) << endl; cout << "ratio of largest / smallest h: " << sqrt(maxCellMeasure) / sqrt(minCellMeasure) << endl; } if (rank == 0) { cout << "phi ID: " << phi->ID() << endl; cout << "psi1 ID: " << psi_1->ID() << endl; cout << "psi2 ID: " << psi_2->ID() << endl; cout << "streamMesh has " << streamMesh->numActiveElements() << " elements.\n"; cout << "solving for approximate stream function...\n"; } streamSolution->solve(useMumps); energyErrorTotal = streamSolution->energyErrorTotal(); if (rank == 0) { cout << "...solved.\n"; cout << "Stream mesh has energy error: " << energyErrorTotal << endl; } if (rank==0) { solution->writeToVTK("nsCavitySoln.vtk"); if (! meshHasTriangles ) { massFlux->writeBoundaryValuesToMATLABFile(solution->mesh(), "massFlux.dat"); u_mag->writeValuesToMATLABFile(solution->mesh(), "u_mag.m"); u_div->writeValuesToMATLABFile(solution->mesh(), "u_div.m"); solution->writeFieldsToFile(u1->ID(), "u1.m"); solution->writeFluxesToFile(u1hat->ID(), "u1_hat.dat"); solution->writeFieldsToFile(u2->ID(), "u2.m"); solution->writeFluxesToFile(u2hat->ID(), "u2_hat.dat"); solution->writeFieldsToFile(p->ID(), "p.m"); streamSolution->writeFieldsToFile(phi->ID(), "phi.m"); streamSolution->writeFluxesToFile(phi_hat->ID(), "phi_hat.dat"); streamSolution->writeFieldsToFile(psi_1->ID(), "psi1.m"); streamSolution->writeFieldsToFile(psi_2->ID(), "psi2.m"); vorticity->writeValuesToMATLABFile(streamMesh, "vorticity.m"); FunctionPtr ten = Teuchos::rcp( new ConstantScalarFunction(10) ); ten->writeBoundaryValuesToMATLABFile(solution->mesh(), "skeleton.dat"); cout << "wrote files: u_mag.m, u_div.m, u1.m, u1_hat.dat, u2.m, u2_hat.dat, p.m, phi.m, vorticity.m.\n"; } else { solution->writeToFile(u1->ID(), "u1.dat"); solution->writeToFile(u2->ID(), "u2.dat"); solution->writeToFile(u2->ID(), "p.dat"); cout << "wrote files: u1.dat, u2.dat, p.dat\n"; } FieldContainer<double> points = pointGrid(0, 1, 0, 1, 100); FieldContainer<double> pointData = solutionData(points, streamSolution, phi); GnuPlotUtil::writeXYPoints("phi_patch_navierStokes_cavity.dat", pointData); set<double> patchContourLevels = diagonalContourLevels(pointData,1); vector<string> patchDataPath; patchDataPath.push_back("phi_patch_navierStokes_cavity.dat"); GnuPlotUtil::writeContourPlotScript(patchContourLevels, patchDataPath, "lidCavityNavierStokes.p"); GnuPlotUtil::writeExactMeshSkeleton("lid_navierStokes_continuation_adaptive", mesh, 2); writePatchValues(0, 1, 0, 1, streamSolution, phi, "phi_patch.m"); writePatchValues(0, .1, 0, .1, streamSolution, phi, "phi_patch_detail.m"); writePatchValues(0, .01, 0, .01, streamSolution, phi, "phi_patch_minute_detail.m"); writePatchValues(0, .001, 0, .001, streamSolution, phi, "phi_patch_minute_minute_detail.m"); } 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; }
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); Epetra_MpiComm Comm(MPI_COMM_WORLD); #else Epetra_SerialComm Comm; #endif int commRank = Teuchos::GlobalMPISession::getRank(); Comm.Barrier(); // set breakpoint here to allow debugger attachment to other MPI processes than the one you automatically attached to. Teuchos::CommandLineProcessor cmdp(false,true); // false: don't throw exceptions; true: do return errors for unrecognized options // problem parameters: int spaceDim = 2; double epsilon = 1e-2; int numRefs = 0; int k = 2, delta_k = 2; int numXElems = 1; bool useConformingTraces = true; string solverChoice = "KLU"; string coarseSolverChoice = "KLU"; // often this beats SuperLU_Dist as coarse solver (true on BG/Q with 6000 3D elements on 256 ranks) double solverTolerance = 1e-6; string norm = "CoupledRobust"; cmdp.setOption("spaceDim", &spaceDim, "spatial dimension"); 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("numXElems",&numXElems,"number of elements in x direction"); cmdp.setOption("epsilon", &epsilon, "epsilon"); cmdp.setOption("norm", &norm, "norm"); cmdp.setOption("conformingTraces", "nonconformingTraces", &useConformingTraces, "use conforming traces"); cmdp.setOption("coarseSolver", &coarseSolverChoice, "KLU, SuperLU"); cmdp.setOption("solver", &solverChoice, "KLU, SuperLU, MUMPS, GMG-Direct, GMG-ILU, GMG-IC"); cmdp.setOption("solverTolerance", &solverTolerance, "iterative solver tolerance"); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { #ifdef HAVE_MPI MPI_Finalize(); #endif return -1; } FunctionPtr beta; FunctionPtr beta_x = Function::constant(1); FunctionPtr beta_y = Function::constant(2); FunctionPtr beta_z = Function::constant(3); if (spaceDim == 1) beta = beta_x; else if (spaceDim == 2) beta = Function::vectorize(beta_x, beta_y); else if (spaceDim == 3) beta = Function::vectorize(beta_x, beta_y, beta_z); ConvectionDiffusionFormulation form(spaceDim, useConformingTraces, beta, epsilon); // Define right hand side RHSPtr rhs = RHS::rhs(); // Set up boundary conditions BCPtr bc = BC::bc(); VarPtr uhat = form.uhat(); VarPtr tc = form.tc(); SpatialFilterPtr inflowX = SpatialFilter::matchingX(-1); SpatialFilterPtr inflowY = SpatialFilter::matchingY(-1); SpatialFilterPtr inflowZ = SpatialFilter::matchingZ(-1); SpatialFilterPtr outflowX = SpatialFilter::matchingX(1); SpatialFilterPtr outflowY = SpatialFilter::matchingY(1); SpatialFilterPtr outflowZ = SpatialFilter::matchingZ(1); FunctionPtr zero = Function::zero(); FunctionPtr one = Function::constant(1); FunctionPtr x = Function::xn(1); FunctionPtr y = Function::yn(1); FunctionPtr z = Function::zn(1); if (spaceDim == 1) { bc->addDirichlet(tc, inflowX, -one); bc->addDirichlet(uhat, outflowX, zero); } if (spaceDim == 2) { bc->addDirichlet(tc, inflowX, -1*.5*(one-y)); bc->addDirichlet(uhat, outflowX, zero); bc->addDirichlet(tc, inflowY, -2*.5*(one-x)); bc->addDirichlet(uhat, outflowY, zero); } if (spaceDim == 3) { bc->addDirichlet(tc, inflowX, -1*.25*(one-y)*(one-z)); bc->addDirichlet(uhat, outflowX, zero); bc->addDirichlet(tc, inflowY, -2*.25*(one-x)*(one-z)); bc->addDirichlet(uhat, outflowY, zero); bc->addDirichlet(tc, inflowZ, -3*.25*(one-x)*(one-y)); bc->addDirichlet(uhat, outflowZ, zero); } // Build mesh vector<double> x0 = vector<double>(spaceDim,-1.0); double width = 2.0; vector<double> dimensions; vector<int> elementCounts; for (int d=0; d<spaceDim; d++) { dimensions.push_back(width); elementCounts.push_back(numXElems); } MeshPtr mesh = MeshFactory::rectilinearMesh(form.bf(), dimensions, elementCounts, k+1, delta_k, x0); MeshPtr k0Mesh = Teuchos::rcp( new Mesh (mesh->getTopology()->deepCopy(), form.bf(), 1, delta_k) ); mesh->registerObserver(k0Mesh); // Set up solution SolutionPtr soln = Solution::solution(form.bf(), mesh, bc, rhs, form.ip(norm)); double threshold = 0.20; RefinementStrategy refStrategy(soln, threshold); ostringstream refName; refName << "confusion" << spaceDim << "D_" << norm << "_" << epsilon << "_k" << k << "_" << solverChoice; // HDF5Exporter exporter(mesh,refName.str()); Teuchos::RCP<Time> solverTime = Teuchos::TimeMonitor::getNewCounter("Solve Time"); if (commRank == 0) Solver::printAvailableSolversReport(); map<string, SolverPtr> solvers; solvers["KLU"] = Solver::getSolver(Solver::KLU, true); SolverPtr superluSolver = Solver::getSolver(Solver::SuperLUDist, true); solvers["SuperLU"] = superluSolver; int maxIters = 2000; bool useStaticCondensation = false; int azOutput = 20; // print residual every 20 CG iterations ofstream dataFile(refName.str()+".txt"); dataFile << "ref\t " << "elements\t " << "dofs\t " << "error\t " << "solvetime\t" << "iterations\t " << endl; for (int refIndex=0; refIndex <= numRefs; refIndex++) { solverTime->start(true); Teuchos::RCP<GMGSolver> gmgSolver; if (solverChoice[0] == 'G') { gmgSolver = Teuchos::rcp( new GMGSolver(soln, k0Mesh, maxIters, solverTolerance, solvers[coarseSolverChoice], useStaticCondensation)); gmgSolver->setAztecOutput(azOutput); if (solverChoice == "GMG-Direct") gmgSolver->gmgOperator().setSchwarzFactorizationType(GMGOperator::Direct); if (solverChoice == "GMG-ILU") gmgSolver->gmgOperator().setSchwarzFactorizationType(GMGOperator::ILU); if (solverChoice == "GMG-IC") gmgSolver->gmgOperator().setSchwarzFactorizationType(GMGOperator::IC); soln->solve(gmgSolver); } else soln->condensedSolve(solvers[solverChoice]); double solveTime = solverTime->stop(); double energyError = soln->energyErrorTotal(); if (commRank == 0) { // if (refIndex > 0) // refStrategy.printRefinementStatistics(refIndex-1); if (solverChoice[0] == 'G') { cout << "Refinement: " << refIndex << " \tElements: " << mesh->numActiveElements() << " \tDOFs: " << mesh->numGlobalDofs() << " \tEnergy Error: " << energyError << " \tSolve Time: " << solveTime << " \tIteration Count: " << gmgSolver->iterationCount() << endl; dataFile << refIndex << " " << mesh->numActiveElements() << " " << mesh->numGlobalDofs() << " " << energyError << " " << solveTime << " " << gmgSolver->iterationCount() << endl; } else { cout << "Refinement: " << refIndex << " \tElements: " << mesh->numActiveElements() << " \tDOFs: " << mesh->numGlobalDofs() << " \tEnergy Error: " << energyError << " \tSolve Time: " << solveTime << endl; dataFile << refIndex << " " << mesh->numActiveElements() << " " << mesh->numGlobalDofs() << " " << energyError << " " << solveTime << endl; } } // exporter.exportSolution(soln, refIndex); if (refIndex != numRefs) refStrategy.refine(); } dataFile.close(); return 0; }