int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); choice::MpiArgs args( argc, argv ); #else choice::Args args( argc, argv ); #endif int rank = Teuchos::GlobalMPISession::getRank(); int numProcs = Teuchos::GlobalMPISession::getNProc(); int nCells = args.Input<int>("--nCells", "num cells",2); int numSteps = args.Input<int>("--numSteps", "num NR steps",20); int polyOrder = 0; // define our manufactured solution or problem bilinear form: bool useTriangles = false; int pToAdd = 1; args.Process(); int H1Order = polyOrder + 1; //////////////////////////////////////////////////////////////////// // DEFINE VARIABLES //////////////////////////////////////////////////////////////////// // new-style bilinear form definition VarFactory varFactory; VarPtr fn = varFactory.fluxVar("\\widehat{\\beta_n_u}"); VarPtr u = varFactory.fieldVar("u"); 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); //////////////////////////////////////////////////////////////////// // 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) ); SolutionPtr solnPerturbation = Teuchos::rcp(new Solution(mesh, nullBC, nullRHS, nullIP) ); vector<double> e1(2),e2(2); e1[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 //////////////////////////////////////////////////////////////////// // v: bf->addTerm( -u, beta * v->grad()); bf->addTerm( fn, v); //////////////////////////////////////////////////////////////////// // DEFINE RHS //////////////////////////////////////////////////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr u_prev_squared_div2 = 0.5 * u_prev * u_prev; rhs->addTerm((e1 * u_prev_squared_div2 + e2 * u_prev) * v->grad()); // ==================== SET INITIAL GUESS ========================== mesh->registerSolution(backgroundFlow); FunctionPtr zero = Function::constant(0.0); FunctionPtr u0 = Teuchos::rcp( new U0 ); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); // FunctionPtr parity = Teuchos::rcp(new SideParityFunction); FunctionPtr u0_squared_div_2 = 0.5 * u0 * u0; map<int, Teuchos::RCP<Function> > functionMap; functionMap[u->ID()] = u0; // functionMap[fn->ID()] = -(e1 * u0_squared_div_2 + e2 * u0) * n * parity; backgroundFlow->projectOntoMesh(functionMap); // ==================== END SET INITIAL GUESS ========================== //////////////////////////////////////////////////////////////////// // DEFINE INNER PRODUCT //////////////////////////////////////////////////////////////////// IPPtr ip = Teuchos::rcp( new IP ); ip->addTerm( v ); ip->addTerm(v->grad()); // ip->addTerm( beta * v->grad() ); // omitting term to make IP non-dependent on u //////////////////////////////////////////////////////////////////// // DEFINE DIRICHLET BC //////////////////////////////////////////////////////////////////// SpatialFilterPtr outflowBoundary = Teuchos::rcp( new TopBoundary); SpatialFilterPtr inflowBoundary = Teuchos::rcp( new NegatedSpatialFilter(outflowBoundary) ); Teuchos::RCP<BCEasy> inflowBC = Teuchos::rcp( new BCEasy ); inflowBC->addDirichlet(fn,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); solution->setCubatureEnrichmentDegree(10); //////////////////////////////////////////////////////////////////// // HESSIAN BIT + CHECKS ON GRADIENT + HESSIAN //////////////////////////////////////////////////////////////////// VarFactory hessianVars = varFactory.getBubnovFactory(VarFactory::BUBNOV_TRIAL); VarPtr du = hessianVars.test(u->ID()); // BFPtr hessianBF = Teuchos::rcp( new BF(hessianVars) ); // initialize bilinear form FunctionPtr du_current = Teuchos::rcp( new PreviousSolutionFunction(solution, u) ); FunctionPtr fnhat = Teuchos::rcp(new PreviousSolutionFunction(solution,fn)); LinearTermPtr residual = Teuchos::rcp(new LinearTerm);// residual residual->addTerm(fnhat*v,true); residual->addTerm( - (e1 * (u_prev_squared_div2) + e2 * (u_prev)) * v->grad(),true); LinearTermPtr Bdu = Teuchos::rcp(new LinearTerm);// residual Bdu->addTerm( - du_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<NullFilter> nullFilter = Teuchos::rcp(new NullFilter); // Teuchos::RCP<HessianFilter> hessianFilter = Teuchos::rcp(new HessianFilter(hessianBF)); Teuchos::RCP< LineSearchStep > LS_Step = Teuchos::rcp(new LineSearchStep(riesz)); double NL_residual = 9e99; for (int i = 0;i<numSteps;i++){ // write matrix to file and then resollve without hessian /* solution->setFilter(hessianFilter); stringstream oss; oss << "hessianMatrix" << i << ".dat"; solution->setWriteMatrixToFile(true,oss.str()); solution->solve(false); solution->setFilter(nullFilter); oss.str(""); // clear oss << "stiffnessMatrix" << i << ".dat"; solution->setWriteMatrixToFile(false,oss.str()); */ solution->solve(false); // do one solve to initialize things... double stepLength = 1.0; stepLength = LS_Step->stepSize(backgroundFlow,solution, NL_residual); // solution->setWriteMatrixToFile(true,"stiffness.dat"); backgroundFlow->addSolution(solution,stepLength); NL_residual = LS_Step->getNLResidual(); if (rank==0){ cout << "NL residual after adding = " << NL_residual << " with step size " << stepLength << endl; } double fd_gradient; for (int dofIndex = 0;dofIndex<mesh->numGlobalDofs();dofIndex++){ TestingUtilities::initializeSolnCoeffs(solnPerturbation); TestingUtilities::setSolnCoeffForGlobalDofIndex(solnPerturbation,1.0,dofIndex); fd_gradient = FiniteDifferenceUtilities::finiteDifferenceGradient(mesh, riesz, backgroundFlow, dofIndex); // CHECK GRADIENT LinearTermPtr b_u = bf->testFunctional(solnPerturbation); map<int,FunctionPtr> NL_err_rep_map; NL_err_rep_map[v->ID()] = Teuchos::rcp(new RepFunction(v,riesz)); FunctionPtr gradient = b_u->evaluate(NL_err_rep_map, TestingUtilities::isFluxOrTraceDof(mesh,dofIndex)); // use boundary part only if flux or trace double grad; if (TestingUtilities::isFluxOrTraceDof(mesh,dofIndex)){ grad = gradient->integralOfJump(mesh,10); }else{ grad = gradient->integrate(mesh,10); } double fdgrad = fd_gradient; double diff = grad-fdgrad; if (abs(diff)>1e-6 && i>0){ cout << "Found difference of " << diff << ", " << " with fd val = " << fdgrad << " and gradient = " << grad << " in dof " << dofIndex << ", isTraceDof = " << TestingUtilities::isFluxOrTraceDof(mesh,dofIndex) << endl; } } } VTKExporter exporter(solution, mesh, varFactory); if (rank==0){ exporter.exportSolution("qopt"); cout << endl; } return 0; }
int main(int argc, char *argv[]) { // Process command line arguments #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); int rank=mpiSession.getRank(); int numProcs=mpiSession.getNProc(); #else int rank = 0; int numProcs = 1; #endif //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactory varFactory; VarPtr v = varFactory.testVar("v", HGRAD); // define trial variables VarPtr beta_n_u_hat = varFactory.fluxVar("\\widehat{\\beta \\cdot n }"); VarPtr u = varFactory.fieldVar("u"); FunctionPtr beta = Teuchos::rcp(new Beta()); //////////////////// BUILD MESH /////////////////////// BFPtr confusionBF = Teuchos::rcp( new BF(varFactory) ); // define nodes for mesh FieldContainer<double> meshBoundary(4,2); meshBoundary(0,0) = -1.0; // x1 meshBoundary(0,1) = -1.0; // y1 meshBoundary(1,0) = 1.0; meshBoundary(1,1) = -1.0; meshBoundary(2,0) = 1.0; meshBoundary(2,1) = 1.0; meshBoundary(3,0) = -1.0; meshBoundary(3,1) = 1.0; int horizontalCells = 32, verticalCells = 32; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = Mesh::buildQuadMesh(meshBoundary, horizontalCells, verticalCells, confusionBF, H1Order, H1Order+pToAdd); //////////////////////////////////////////////////////////////////// // INITIALIZE FLOW FUNCTIONS //////////////////////////////////////////////////////////////////// BCPtr nullBC = Teuchos::rcp((BC*)NULL); RHSPtr nullRHS = Teuchos::rcp((RHS*)NULL); IPPtr nullIP = Teuchos::rcp((IP*)NULL); SolutionPtr prevTimeFlow = Teuchos::rcp(new Solution(mesh, nullBC, nullRHS, nullIP) ); SolutionPtr flowResidual = Teuchos::rcp(new Solution(mesh, nullBC, nullRHS, nullIP) ); FunctionPtr u_prev_time = Teuchos::rcp( new PreviousSolutionFunction(prevTimeFlow, u) ); //////////////////// DEFINE BILINEAR FORM /////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr invDt = Teuchos::rcp(new ScalarParamFunction(1.0/dt)); // v terms: confusionBF->addTerm( beta * u, - v->grad() ); confusionBF->addTerm( beta_n_u_hat, v); confusionBF->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) /////////////////////// // robust test norm IPPtr ip = confusionBF->graphNorm(); // IPPtr ip = Teuchos::rcp(new IP); // ip->addTerm(v); // ip->addTerm(invDt*v - beta*v->grad()); //////////////////// CREATE BCs /////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); SpatialFilterPtr inflowBoundary = Teuchos::rcp( new InflowSquareBoundary(beta) ); FunctionPtr u0 = Teuchos::rcp( new ConstantScalarFunction(0) ); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); bc->addDirichlet(beta_n_u_hat, inflowBoundary, beta*n*u0); Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); // ==================== Register Solutions ========================== mesh->registerSolution(solution); mesh->registerSolution(prevTimeFlow); mesh->registerSolution(flowResidual); // ==================== SET INITIAL GUESS ========================== FunctionPtr u_init = Teuchos::rcp(new InitialCondition()); map<int, Teuchos::RCP<Function> > functionMap; functionMap[u->ID()] = u_init; prevTimeFlow->projectOntoMesh(functionMap); //////////////////// SOLVE & REFINE /////////////////////// // if (enforceLocalConservation) { // // FunctionPtr parity = Teuchos::rcp<Function>( new SideParityFunction ); // // LinearTermPtr conservedQuantity = Teuchos::rcp<LinearTerm>( new LinearTerm(parity, beta_n_u_minus_sigma_n) ); // LinearTermPtr conservedQuantity = Teuchos::rcp<LinearTerm>( new LinearTerm(1.0, beta_n_u_minus_sigma_n) ); // LinearTermPtr sourcePart = Teuchos::rcp<LinearTerm>( new LinearTerm(invDt, u) ); // conservedQuantity->addTerm(sourcePart, true); // solution->lagrangeConstraints()->addConstraint(conservedQuantity == u_prev_time * invDt); // } int timestepCount = 0; double time_tol = 1e-8; double L2_time_residual = 1e9; while((L2_time_residual > time_tol) && (timestepCount < numTimeSteps)) { solution->solve(false); // Subtract solutions to get residual flowResidual->setSolution(solution); flowResidual->addSolution(prevTimeFlow, -1.0); L2_time_residual = flowResidual->L2NormOfSolutionGlobal(u->ID()); if (rank == 0) { cout << endl << "Timestep: " << timestepCount << ", dt = " << dt << ", Time residual = " << L2_time_residual << endl; stringstream outfile; outfile << "rotatingCylinder_" << timestepCount; solution->writeToVTK(outfile.str(), 5); // Check local conservation FunctionPtr flux = Teuchos::rcp( new PreviousSolutionFunction(solution, beta_n_u_hat) ); FunctionPtr source = Teuchos::rcp( new PreviousSolutionFunction(flowResidual, u) ); source = invDt * source; Teuchos::Tuple<double, 3> fluxImbalances = checkConservation(flux, source, varFactory, mesh); cout << "Mass flux: Largest Local = " << fluxImbalances[0] << ", Global = " << fluxImbalances[1] << ", Sum Abs = " << fluxImbalances[2] << endl; } prevTimeFlow->setSolution(solution); // reset previous time solution to current time sol timestepCount++; } 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 tau1 = varFactory.testVar("tau1", HDIV); VarPtr tau2 = varFactory.testVar("tau2", HDIV); VarPtr v1 = varFactory.testVar("v1", HGRAD); VarPtr v2 = varFactory.testVar("v2", HGRAD); VarPtr q = varFactory.testVar("q", 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 sigma1 = varFactory.fieldVar("sigma1", VECTOR_L2); VarPtr sigma2 = varFactory.fieldVar("sigma2", VECTOR_L2); VarPtr u1hat = varFactory.traceVar("u1hat"); VarPtr u2hat = varFactory.traceVar("u2hat"); VarPtr t1hat = varFactory.fluxVar("t1hat"); VarPtr t2hat = varFactory.fluxVar("t2hat"); VarPtr p = varFactory.fieldVar("p"); //////////////////// 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 = Mesh::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 sigma1_prev = Function::solution(sigma1, backgroundFlow); FunctionPtr sigma2_prev = Function::solution(sigma2, backgroundFlow); FunctionPtr p_prev = Function::solution(p, 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) ); // FunctionPtr beta = e1 * u1_prev + e2 * u2_prev; // ==================== SET INITIAL GUESS ========================== map<int, Teuchos::RCP<Function> > functionMap; functionMap[u1->ID()] = u1Exact; functionMap[u2->ID()] = u2Exact; // functionMap[sigma1->ID()] = Function::vectorize(zero,zero); // functionMap[sigma2->ID()] = Function::vectorize(zero,zero); // functionMap[p->ID()] = zero; backgroundFlow->projectOntoMesh(functionMap); //////////////////// DEFINE BILINEAR FORM /////////////////////// // // stress equation bf->addTerm( 1./nu*sigma1, tau1 ); bf->addTerm( 1./nu*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( 1./(2*nu)*sigma11, tau11 ); // bf->addTerm( 1./(2*nu)*sigma12, tau12 ); // bf->addTerm( 1./(2*nu)*sigma12, tau12 ); // bf->addTerm( 1./(2*nu)*sigma22, tau22 ); // bf->addTerm( u1, tau11->dx() ); // bf->addTerm( u1, tau12->dy() ); // bf->addTerm( u2, tau12->dx() ); // bf->addTerm( u2, tau22->dy() ); // bf->addTerm( -u1hat, tau11->times_normal_x() ); // bf->addTerm( -u1hat, tau12->times_normal_y() ); // bf->addTerm( -u2hat, tau12->times_normal_x() ); // bf->addTerm( -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, v1->dy() ); bf->addTerm( -2.*u2_prev*u2, v2->dy() ); bf->addTerm( -p, v1->dx() ); bf->addTerm( -p, v2->dy() ); // bf->addTerm( sigma11, v1->dx() ); // bf->addTerm( sigma12, v1->dy() ); // bf->addTerm( sigma12, v2->dx() ); // bf->addTerm( sigma22, v2->dy() ); bf->addTerm( sigma1, v1->grad() ); bf->addTerm( sigma2, v2->grad() ); bf->addTerm( t1hat, v1); bf->addTerm( t2hat, v2); // continuity equation bf->addTerm( -u1, q->dx() ); bf->addTerm( -u2, q->dy() ); bf->addTerm( u1hat, q->times_normal_x() ); bf->addTerm( u2hat, q->times_normal_y() ); //////////////////// SPECIFY RHS /////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); // stress equation rhs->addTerm( -u1_prev * tau1->div() ); rhs->addTerm( -u2_prev * tau2->div() ); // momentum equation rhs->addTerm( 2.*u1_prev*u1_prev * v1->dx() ); rhs->addTerm( u2_prev*u1_prev * v1->dy() ); rhs->addTerm( u1_prev*u2_prev * v1->dy() ); rhs->addTerm( u2_prev*u1_prev * v2->dx() ); rhs->addTerm( u1_prev*u2_prev * v1->dy() ); rhs->addTerm( 2.*u2_prev*u2_prev * v2->dy() ); // rhs->addTerm( p_prev * v1->dx() ); // rhs->addTerm( p_prev * v2->dy() ); // rhs->addTerm( -sigma1_prev * v1->grad() ); // rhs->addTerm( -sigma2_prev * v2->grad() ); // rhs->addTerm( -sigma11_prev * v1->dx() ); // rhs->addTerm( -sigma12_prev * v1->dy() ); // rhs->addTerm( -sigma12_prev * v2->dx() ); // rhs->addTerm( -sigma22_prev * v2->dy() ); // continuity equation rhs->addTerm( u1_prev * q->dx() ); rhs->addTerm( u2_prev * q->dy() ); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = Teuchos::rcp(new IP); if (norm == 0) { ip = bf->graphNorm(); } else if (norm == 1) { // ip = bf->l2Norm(); } //////////////////// CREATE BCs /////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); // 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); // zero mean constraint on pressure bc->addZeroMeanConstraint(p); // 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 ); VTKExporter exporter(backgroundFlow, mesh, varFactory); stringstream outfile; outfile << "kovasznay" << "_" << 0; exporter.exportSolution(outfile.str()); 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); iterCount++; } if (commRank == 0) { stringstream outfile; outfile << "kovasznay" << "_" << refIndex+1; exporter.exportSolution(outfile.str()); } if (refIndex < numRefs) refinementStrategy.refine(commRank==0); // print to console on commRank 0 } return 0; }
int main(int argc, char *argv[]) { // Process command line arguments if (argc > 1) numRefs = atof(argv[1]); #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); int rank=mpiSession.getRank(); int numProcs=mpiSession.getNProc(); #else int rank = 0; int numProcs = 1; #endif FunctionPtr beta = Teuchos::rcp(new Beta()); //////////////////////////////////////////////////////////////////// // DEFINE VARIABLES //////////////////////////////////////////////////////////////////// // test variables VarFactory varFactory; VarPtr tau = varFactory.testVar("\\tau", HDIV); VarPtr v = varFactory.testVar("v", HGRAD); // trial variables VarPtr uhat = varFactory.traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_n = varFactory.fluxVar("\\widehat{\\beta \\cdot n u - \\sigma_{n}}"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma1 = varFactory.fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory.fieldVar("\\sigma_2"); //////////////////////////////////////////////////////////////////// // CREATE MESH //////////////////////////////////////////////////////////////////// BFPtr confusionBF = Teuchos::rcp( new BF(varFactory) ); FieldContainer<double> meshBoundary(4,2); meshBoundary(0,0) = 0.0; // x1 meshBoundary(0,1) = -2.0; // y1 meshBoundary(1,0) = 4.0; meshBoundary(1,1) = -2.0; meshBoundary(2,0) = 4.0; meshBoundary(2,1) = 2.0; meshBoundary(3,0) = 0.0; meshBoundary(3,1) = 2.0; int horizontalCells = 4, verticalCells = 4; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = Mesh::buildQuadMesh(meshBoundary, horizontalCells, verticalCells, confusionBF, H1Order, H1Order+pToAdd, false); //////////////////////////////////////////////////////////////////// // INITIALIZE BACKGROUND FLOW FUNCTIONS //////////////////////////////////////////////////////////////////// BCPtr nullBC = Teuchos::rcp((BC*)NULL); RHSPtr nullRHS = Teuchos::rcp((RHS*)NULL); IPPtr nullIP = Teuchos::rcp((IP*)NULL); SolutionPtr prevTimeFlow = Teuchos::rcp(new Solution(mesh, nullBC, nullRHS, nullIP) ); SolutionPtr flowResidual = Teuchos::rcp(new Solution(mesh, nullBC, nullRHS, nullIP) ); FunctionPtr u_prev_time = Teuchos::rcp( new PreviousSolutionFunction(prevTimeFlow, u) ); // ==================== SET INITIAL GUESS ========================== double u_free = 0.0; double sigma1_free = 0.0; double sigma2_free = 0.0; map<int, Teuchos::RCP<Function> > functionMap; functionMap[u->ID()] = Teuchos::rcp( new ConstantScalarFunction(u_free) ); functionMap[sigma1->ID()] = Teuchos::rcp( new ConstantScalarFunction(sigma1_free) ); functionMap[sigma2->ID()] = Teuchos::rcp( new ConstantScalarFunction(sigma2_free) ); prevTimeFlow->projectOntoMesh(functionMap); // ==================== END SET INITIAL GUESS ========================== //////////////////////////////////////////////////////////////////// // DEFINE BILINEAR FORM //////////////////////////////////////////////////////////////////// // tau terms: confusionBF->addTerm(sigma1 / epsilon, tau->x()); confusionBF->addTerm(sigma2 / epsilon, tau->y()); confusionBF->addTerm(u, tau->div()); confusionBF->addTerm(-uhat, tau->dot_normal()); // v terms: confusionBF->addTerm( sigma1, v->dx() ); confusionBF->addTerm( sigma2, v->dy() ); confusionBF->addTerm( beta * u, - v->grad() ); confusionBF->addTerm( beta_n_u_minus_sigma_n, v); //////////////////////////////////////////////////////////////////// // TIMESTEPPING TERMS //////////////////////////////////////////////////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); double dt = 0.25; FunctionPtr invDt = Teuchos::rcp(new ScalarParamFunction(1.0/dt)); if (rank==0){ cout << "Timestep dt = " << dt << endl; } if (transient) { confusionBF->addTerm( u, invDt*v ); rhs->addTerm( u_prev_time * invDt * v ); } //////////////////////////////////////////////////////////////////// // DEFINE INNER PRODUCT //////////////////////////////////////////////////////////////////// // mathematician's norm IPPtr mathIP = Teuchos::rcp(new IP()); mathIP->addTerm(tau); mathIP->addTerm(tau->div()); mathIP->addTerm(v); mathIP->addTerm(v->grad()); // quasi-optimal norm IPPtr qoptIP = Teuchos::rcp(new IP); qoptIP->addTerm( v ); qoptIP->addTerm( tau / epsilon + v->grad() ); qoptIP->addTerm( beta * v->grad() - tau->div() ); // robust test norm IPPtr robIP = Teuchos::rcp(new IP); FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); if (!enforceLocalConservation) { robIP->addTerm( ip_scaling * v ); if (transient) robIP->addTerm( invDt * v ); } robIP->addTerm( sqrt(epsilon) * v->grad() ); // Weight these two terms for inflow FunctionPtr ip_weight = Teuchos::rcp( new IPWeight() ); robIP->addTerm( ip_weight * beta * v->grad() ); robIP->addTerm( ip_weight * tau->div() ); robIP->addTerm( ip_scaling/sqrt(epsilon) * tau ); if (enforceLocalConservation) robIP->addZeroMeanTerm( v ); //////////////////////////////////////////////////////////////////// // DEFINE RHS //////////////////////////////////////////////////////////////////// FunctionPtr f = Teuchos::rcp( new ConstantScalarFunction(0.0) ); rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////////////////////////////////////////////////////// // DEFINE BC //////////////////////////////////////////////////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); // Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp( new PenaltyConstraints ); SpatialFilterPtr lBoundary = Teuchos::rcp( new LeftBoundary ); SpatialFilterPtr tbBoundary = Teuchos::rcp( new TopBottomBoundary ); SpatialFilterPtr rBoundary = Teuchos::rcp( new RightBoundary ); FunctionPtr u0 = Teuchos::rcp( new ZeroBC ); FunctionPtr u_inlet = Teuchos::rcp( new InletBC ); // FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); bc->addDirichlet(beta_n_u_minus_sigma_n, lBoundary, u_inlet); bc->addDirichlet(beta_n_u_minus_sigma_n, tbBoundary, u0); bc->addDirichlet(uhat, rBoundary, u0); // pc->addConstraint(beta_n_u_minus_sigma_n - uhat == u0, rBoundary); //////////////////////////////////////////////////////////////////// // CREATE SOLUTION OBJECT //////////////////////////////////////////////////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, robIP) ); // solution->setFilter(pc); // ==================== Enforce Local Conservation ================== if (enforceLocalConservation) { if (transient) { FunctionPtr conserved_rhs = u_prev_time * invDt; LinearTermPtr conserved_quantity = invDt * u; LinearTermPtr flux_part = Teuchos::rcp(new LinearTerm(-1.0, beta_n_u_minus_sigma_n)); conserved_quantity->addTerm(flux_part, true); // conserved_quantity = conserved_quantity - beta_n_u_minus_sigma_n; solution->lagrangeConstraints()->addConstraint(conserved_quantity == conserved_rhs); } else { FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); solution->lagrangeConstraints()->addConstraint(beta_n_u_minus_sigma_n == zero); } } // ==================== Register Solutions ========================== mesh->registerSolution(solution); mesh->registerSolution(prevTimeFlow); // u_t(i-1) mesh->registerSolution(flowResidual); // u_t(i-1) double energyThreshold = 0.25; // for mesh refinements Teuchos::RCP<RefinementStrategy> refinementStrategy; refinementStrategy = Teuchos::rcp(new RefinementStrategy(solution,energyThreshold)); //////////////////////////////////////////////////////////////////// // PSEUDO-TIME SOLVE STRATEGY //////////////////////////////////////////////////////////////////// double time_tol = 1e-8; for (int refIndex=0; refIndex<=numRefs; refIndex++) { double L2_time_residual = 1e7; int timestepCount = 0; if (!transient) numTimeSteps = 1; while((L2_time_residual > time_tol) && (timestepCount < numTimeSteps)) { solution->solve(false); // subtract solutions to get residual flowResidual->setSolution(solution); // reset previous time solution to current time sol flowResidual->addSolution(prevTimeFlow, -1.0); double L2u = flowResidual->L2NormOfSolutionGlobal(u->ID()); double L2sigma1 = flowResidual->L2NormOfSolutionGlobal(sigma1->ID()); double L2sigma2 = flowResidual->L2NormOfSolutionGlobal(sigma2->ID()); L2_time_residual = sqrt(L2u*L2u + L2sigma1*L2sigma1 + L2sigma2*L2sigma2); cout << endl << "Timestep: " << timestepCount << ", dt = " << dt << ", Time residual = " << L2_time_residual << endl; if (rank == 0) { stringstream outfile; if (transient) outfile << "TransientConfusion_" << refIndex << "_" << timestepCount; else outfile << "TransientConfusion_" << refIndex; solution->writeToVTK(outfile.str(), 5); } ////////////////////////////////////////////////////////////////////////// // Check conservation by testing against one ////////////////////////////////////////////////////////////////////////// VarPtr testOne = varFactory.testVar("1", CONSTANT_SCALAR); // Create a fake bilinear form for the testing BFPtr fakeBF = Teuchos::rcp( new BF(varFactory) ); // Define our mass flux FunctionPtr flux_current_time = Teuchos::rcp( new PreviousSolutionFunction(solution, beta_n_u_minus_sigma_n) ); FunctionPtr delta_u = Teuchos::rcp( new PreviousSolutionFunction(flowResidual, u) ); LinearTermPtr surfaceFlux = -1.0 * flux_current_time * testOne; LinearTermPtr volumeChange = invDt * delta_u * testOne; LinearTermPtr massFluxTerm; if (transient) { massFluxTerm = volumeChange; // massFluxTerm->addTerm(surfaceFlux); } else { massFluxTerm = surfaceFlux; } // cout << "surface case = " << surfaceFlux->summands()[0].first->boundaryValueOnly() << " volume case = " << volumeChange->summands()[0].first->boundaryValueOnly() << endl; // FunctionPtr massFlux= Teuchos::rcp( new PreviousSolutionFunction(solution, beta_n_u_minus_sigma_n) ); // LinearTermPtr massFluxTerm = massFlux * testOne; Teuchos::RCP<shards::CellTopology> quadTopoPtr = Teuchos::rcp(new shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >() )); DofOrderingFactory dofOrderingFactory(fakeBF); int fakeTestOrder = H1Order; DofOrderingPtr testOrdering = dofOrderingFactory.testOrdering(fakeTestOrder, *quadTopoPtr); int testOneIndex = testOrdering->getDofIndex(testOne->ID(),0); vector< ElementTypePtr > elemTypes = mesh->elementTypes(); // global element types map<int, double> massFluxIntegral; // cellID -> integral double maxMassFluxIntegral = 0.0; double totalMassFlux = 0.0; double totalAbsMassFlux = 0.0; for (vector< ElementTypePtr >::iterator elemTypeIt = elemTypes.begin(); elemTypeIt != elemTypes.end(); elemTypeIt++) { ElementTypePtr elemType = *elemTypeIt; vector< ElementPtr > elems = mesh->elementsOfTypeGlobal(elemType); vector<int> cellIDs; for (int i=0; i<elems.size(); i++) { cellIDs.push_back(elems[i]->cellID()); } FieldContainer<double> physicalCellNodes = mesh->physicalCellNodesGlobal(elemType); BasisCachePtr basisCache = Teuchos::rcp( new BasisCache(elemType,mesh) ); basisCache->setPhysicalCellNodes(physicalCellNodes,cellIDs,true); // true: create side caches FieldContainer<double> cellMeasures = basisCache->getCellMeasures(); FieldContainer<double> fakeRHSIntegrals(elems.size(),testOrdering->totalDofs()); massFluxTerm->integrate(fakeRHSIntegrals,testOrdering,basisCache,true); // true: force side evaluation for (int i=0; i<elems.size(); i++) { int cellID = cellIDs[i]; // pick out the ones for testOne: massFluxIntegral[cellID] = fakeRHSIntegrals(i,testOneIndex); } // find the largest: for (int i=0; i<elems.size(); i++) { int cellID = cellIDs[i]; maxMassFluxIntegral = max(abs(massFluxIntegral[cellID]), maxMassFluxIntegral); } for (int i=0; i<elems.size(); i++) { int cellID = cellIDs[i]; maxMassFluxIntegral = max(abs(massFluxIntegral[cellID]), maxMassFluxIntegral); totalMassFlux += massFluxIntegral[cellID]; totalAbsMassFlux += abs( massFluxIntegral[cellID] ); } } // Print results from processor with rank 0 if (rank == 0) { cout << "largest mass flux: " << maxMassFluxIntegral << endl; cout << "total mass flux: " << totalMassFlux << endl; cout << "sum of mass flux absolute value: " << totalAbsMassFlux << endl; } prevTimeFlow->setSolution(solution); // reset previous time solution to current time sol timestepCount++; } if (refIndex < numRefs){ if (rank==0){ cout << "Performing refinement number " << refIndex << endl; } refinementStrategy->refine(rank==0); // RESET solution every refinement - make sure discretization error doesn't creep in // prevTimeFlow->projectOntoMesh(functionMap); } } return 0; }
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) int uniformRefinements = args.Input("--uniformRefinements", "number of uniform refinements", 0); bool enforceLocalConservation = args.Input<bool>("--conserve", "enforce local conservation", false); double radius = args.Input("--r", "cylinder radius", 0.6); int Re = args.Input("--Re", "Reynolds number", 1); int maxNewtonIterations = args.Input("--maxIterations", "maximum number of Newton iterations", 1); 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(); //////////////////// PROBLEM DEFINITIONS /////////////////////// int H1Order = polyOrder+1; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactory varFactory; VarPtr tau1 = varFactory.testVar("tau1", HDIV); VarPtr tau2 = varFactory.testVar("tau2", HDIV); VarPtr v1 = varFactory.testVar("v1", HGRAD); VarPtr v2 = varFactory.testVar("v2", HGRAD); VarPtr vc = varFactory.testVar("vc", HGRAD); // define trial variables VarPtr u1 = varFactory.fieldVar("u1"); VarPtr u2 = varFactory.fieldVar("u2"); VarPtr p = varFactory.fieldVar("p"); VarPtr u1hat = varFactory.traceVar("u1hat"); VarPtr u2hat = varFactory.traceVar("u2hat"); VarPtr t1hat = varFactory.fluxVar("t1hat"); VarPtr t2hat = varFactory.fluxVar("t2hat"); VarPtr sigma1 = varFactory.fieldVar("sigma1", VECTOR_L2); VarPtr sigma2 = varFactory.fieldVar("sigma2", VECTOR_L2); //////////////////// BUILD MESH /////////////////////// BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = MeshFactory::shiftedHemkerMesh(-1, 3, 2, radius, bf, 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 sigma1_prev = Function::solution(sigma1, backgroundFlow); FunctionPtr sigma2_prev = Function::solution(sigma2, backgroundFlow); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); FunctionPtr one = Teuchos::rcp( new ConstantScalarFunction(1.0) ); FunctionPtr beta = e1 * u1_prev + e2 * u2_prev; // ==================== SET INITIAL GUESS ========================== map<int, Teuchos::RCP<Function> > functionMap; functionMap[u1->ID()] = one; functionMap[u2->ID()] = zero; functionMap[sigma1->ID()] = Function::vectorize(zero,zero); functionMap[sigma2->ID()] = Function::vectorize(zero,zero); functionMap[p->ID()] = zero; backgroundFlow->projectOntoMesh(functionMap); //////////////////// DEFINE BILINEAR FORM /////////////////////// // // stress equation bf->addTerm( sigma1, tau1 ); bf->addTerm( sigma2, tau2 ); bf->addTerm( u1, tau1->div() ); bf->addTerm( u2, tau2->div() ); bf->addTerm( -u1hat, tau1->dot_normal() ); bf->addTerm( -u2hat, tau2->dot_normal() ); // momentum equation // bf->addTerm( Function::xPart(sigma1_prev)*u1, v1 ); // bf->addTerm( Function::yPart(sigma1_prev)*u2, v1 ); // bf->addTerm( Function::xPart(sigma2_prev)*u1, v2 ); // bf->addTerm( Function::yPart(sigma2_prev)*u2, v2 ); // bf->addTerm( beta*sigma1, v1); // bf->addTerm( beta*sigma2, v2); bf->addTerm( 1./Re*sigma1, v1->grad() ); bf->addTerm( 1./Re*sigma2, v2->grad() ); bf->addTerm( t1hat, v1); bf->addTerm( t2hat, v2); bf->addTerm( -p, v1->dx() ); bf->addTerm( -p, v2->dy() ); // continuity equation bf->addTerm( -u1, vc->dx() ); bf->addTerm( -u2, vc->dy() ); bf->addTerm( u1hat, vc->times_normal_x() ); bf->addTerm( u2hat, vc->times_normal_y() ); //////////////////// SPECIFY RHS /////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); // stress equation rhs->addTerm( -sigma1_prev * tau1 ); rhs->addTerm( -sigma2_prev * tau2 ); rhs->addTerm( -u1_prev * tau1->div() ); rhs->addTerm( -u2_prev * tau2->div() ); // momentum equation // rhs->addTerm( -beta*sigma1_prev * v1 ); // rhs->addTerm( -beta*sigma2_prev * v2 ); rhs->addTerm( -1./Re*sigma1_prev * v1->grad() ); rhs->addTerm( -1./Re*sigma2_prev * v2->grad() ); // continuity equation rhs->addTerm( u1_prev * vc->dx() ); rhs->addTerm( u2_prev * vc->dy() ); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = Teuchos::rcp(new IP); if (norm == 0) { ip = bf->graphNorm(); } else if (norm == 1) { // ip = bf->l2Norm(); } //////////////////// CREATE BCs /////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); SpatialFilterPtr left = Teuchos::rcp( new ConstantXBoundary(-1) ); SpatialFilterPtr right = Teuchos::rcp( new ConstantXBoundary(3) ); SpatialFilterPtr top = Teuchos::rcp( new ConstantYBoundary(1) ); SpatialFilterPtr bottom = Teuchos::rcp( new ConstantYBoundary(-1) ); SpatialFilterPtr circle = Teuchos::rcp( new CircleBoundary(radius) ); FunctionPtr boundaryU1 = Teuchos::rcp( new BoundaryU1 ); bc->addDirichlet(u1hat, left, boundaryU1); bc->addDirichlet(u2hat, left, zero); bc->addDirichlet(u1hat, right, boundaryU1); 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); bc->addDirichlet(u1hat, circle, zero); bc->addDirichlet(u2hat, circle, zero); // zero mean constraint on pressure bc->addZeroMeanConstraint(p); Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); 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 ); VTKExporter exporter(backgroundFlow, mesh, varFactory); ofstream errOut; ofstream fluxOut; if (commRank == 0) { errOut.open("stokeshemker_err.txt"); fluxOut.open("stokeshemker_flux.txt"); } errOut.precision(15); fluxOut.precision(15); // Cell IDs for flux calculations vector< pair<ElementPtr, int> > cellFace0; vector< pair<ElementPtr, int> > cellFace1; vector< pair<ElementPtr, int> > cellFace2; vector< pair<ElementPtr, int> > cellFace3; vector< pair<ElementPtr, int> > cellFace4; cellFace0.push_back(make_pair(mesh->getElement(12), 3)); cellFace0.push_back(make_pair(mesh->getElement(13), 3)); cellFace0.push_back(make_pair(mesh->getElement(14), 3)); cellFace0.push_back(make_pair(mesh->getElement(15), 3)); cellFace1.push_back(make_pair(mesh->getElement(12), 1)); cellFace1.push_back(make_pair(mesh->getElement(13), 1)); cellFace1.push_back(make_pair(mesh->getElement(14), 1)); cellFace1.push_back(make_pair(mesh->getElement(15), 1)); cellFace2.push_back(make_pair(mesh->getElement(11), 1)); cellFace2.push_back(make_pair(mesh->getElement(2 ), 0)); cellFace2.push_back(make_pair(mesh->getElement(5 ), 2)); cellFace2.push_back(make_pair(mesh->getElement(16), 1)); cellFace3.push_back(make_pair(mesh->getElement(9 ), 3)); cellFace3.push_back(make_pair(mesh->getElement(8 ), 3)); cellFace3.push_back(make_pair(mesh->getElement(19), 3)); cellFace3.push_back(make_pair(mesh->getElement(18), 3)); cellFace4.push_back(make_pair(mesh->getElement(9 ), 1)); cellFace4.push_back(make_pair(mesh->getElement(8 ), 1)); cellFace4.push_back(make_pair(mesh->getElement(19), 1)); cellFace4.push_back(make_pair(mesh->getElement(18), 1)); // // for loading refinement history // if (replayFile.length() > 0) { // RefinementHistory refHistory; // replayFile = replayFile; // refHistory.loadFromFile(replayFile); // refHistory.playback(mesh); // int numElems = mesh->numActiveElements(); // if (commRank==0){ // double minSideLength = meshInfo.getMinCellSideLength() ; // cout << "after replay, num elems = " << numElems << " and min side length = " << minSideLength << endl; // } // } for (int i = 0; i < uniformRefinements; i++) refinementStrategy.hRefineUniformly(mesh); 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); double energy_error = solution->energyErrorTotal(); // Check local conservation if (commRank == 0) { FunctionPtr n = Function::normal(); FunctionPtr u1_prev = Function::solution(u1hat, solution); FunctionPtr u2_prev = Function::solution(u2hat, solution); FunctionPtr flux = u1_prev*n->x() + u2_prev*n->y(); Teuchos::Tuple<double, 3> fluxImbalances = checkConservation(flux, zero, mesh); // cout << "Mass flux: Largest Local = " << fluxImbalances[0] // << ", Global = " << fluxImbalances[1] << ", Sum Abs = " << fluxImbalances[2] << endl; errOut << mesh->numGlobalDofs() << " " << energy_error << " " << fluxImbalances[0] << " " << fluxImbalances[1] << " " << fluxImbalances[2] << endl; double massFlux0 = computeFluxOverElementSides(u1_prev, mesh, cellFace0); double massFlux1 = computeFluxOverElementSides(u1_prev, mesh, cellFace1); double massFlux2 = computeFluxOverElementSides(u1_prev, mesh, cellFace2); double massFlux3 = computeFluxOverElementSides(u1_prev, mesh, cellFace3); double massFlux4 = computeFluxOverElementSides(u1_prev, mesh, cellFace4); fluxOut << massFlux0 << " " << massFlux1 << " " << massFlux2 << " " << massFlux3 << " " << massFlux4 << " " << endl; cout << "Total mass flux = " << massFlux0 << " " << massFlux1 << " " << massFlux2 << " " << massFlux3 << " " << massFlux4 << " " << 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; // bool useLineSearch = false; // int posEnrich = 5; // amount of enriching of grid points on which to ensure positivity // if (useLineSearch){ // to enforce positivity of density rho // double lineSearchFactor = .5; double eps = .001; // arbitrary // FunctionPtr rhoTemp = Function::solution(rho,backgroundFlow) + alpha*Function::solution(rho,solution) - Function::constant(eps); // FunctionPtr eTemp = Function::solution(e,backgroundFlow) + alpha*Function::solution(e,solution) - Function::constant(eps); // bool rhoIsPositive = rhoTemp->isPositive(mesh,posEnrich); // bool eIsPositive = eTemp->isPositive(mesh,posEnrich); // int iter = 0; int maxIter = 20; // while (!(rhoIsPositive && eIsPositive) && iter < maxIter){ // alpha = alpha*lineSearchFactor; // rhoTemp = Function::solution(rho,backgroundFlow) + alpha*Function::solution(rho,solution); // eTemp = Function::solution(e,backgroundFlow) + alpha*Function::solution(e,solution); // rhoIsPositive = rhoTemp->isPositive(mesh,posEnrich); // eIsPositive = eTemp->isPositive(mesh,posEnrich); // iter++; // } // if (commRank==0 && alpha < 1.0){ // cout << "line search factor alpha = " << alpha << endl; // } // } backgroundFlow->addSolution(solution, alpha, false, true); iterCount++; // if (commRank == 0) // cout << "L2 Norm of Update = " << L2Update << endl; } if (commRank == 0) cout << endl; if (commRank == 0) { stringstream outfile; outfile << "stokeshemker" << uniformRefinements << "_" << refIndex; exporter.exportSolution(outfile.str()); } if (refIndex < numRefs) refinementStrategy.refine(commRank==0); // print to console on commRank 0 } if (commRank == 0) { errOut.close(); fluxOut.close(); } return 0; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); choice::MpiArgs args( argc, argv ); #else choice::Args args( argc, argv ); #endif int commRank = Teuchos::GlobalMPISession::getRank(); int numProcs = Teuchos::GlobalMPISession::getNProc(); // Required arguments int numRefs = args.Input<int>("--numRefs", "number of refinement steps"); bool enforceLocalConservation = args.Input<bool>("--conserve", "enforce local conservation"); bool steady = args.Input<bool>("--steady", "run steady rather than transient"); // Optional arguments (have defaults) double dt = args.Input("--dt", "time step", 0.25); int numTimeSteps = args.Input("--nt", "number of time steps", 20); halfWidth = args.Input("--halfWidth", "half width of inlet profile", 1.0); args.Process(); //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactory varFactory; VarPtr v = varFactory.testVar("v", HGRAD); // define trial variables VarPtr beta_n_u_hat = varFactory.fluxVar("\\widehat{\\beta \\cdot n }"); VarPtr u = varFactory.fieldVar("u"); vector<double> beta; beta.push_back(1.0); beta.push_back(0.0); //////////////////// BUILD MESH /////////////////////// BFPtr 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 = 8, verticalCells = 8; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = Mesh::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); SolutionPtr prevTimeFlow = Teuchos::rcp(new Solution(mesh, nullBC, nullRHS, nullIP) ); SolutionPtr flowResidual = Teuchos::rcp(new Solution(mesh, nullBC, nullRHS, nullIP) ); FunctionPtr u_prev_time = Teuchos::rcp( new PreviousSolutionFunction(prevTimeFlow, u) ); //////////////////// DEFINE BILINEAR FORM /////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr invDt = Teuchos::rcp(new ScalarParamFunction(1.0/dt)); // v terms: bf->addTerm( beta * u, - v->grad() ); bf->addTerm( beta_n_u_hat, v); if (!steady) { 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(); // ip->addTerm(v); // ip->addTerm(beta*v->grad()); //////////////////// CREATE BCs /////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); SpatialFilterPtr lBoundary = Teuchos::rcp( new LeftBoundary ); FunctionPtr u1 = Teuchos::rcp( new InletBC ); bc->addDirichlet(beta_n_u_hat, lBoundary, -u1); Teuchos::RCP<Solution> 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 ConInletBC functionMap[u->ID()] = Teuchos::rcp( new InletBC ); prevTimeFlow->projectOntoMesh(functionMap); //////////////////// SOLVE & REFINE /////////////////////// if (enforceLocalConservation) { if (steady) { FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); solution->lagrangeConstraints()->addConstraint(beta_n_u_hat == zero); } else { // FunctionPtr parity = Teuchos::rcp<Function>( new SideParityFunction ); // LinearTermPtr conservedQuantity = Teuchos::rcp<LinearTerm>( new LinearTerm(parity, beta_n_u_minus_sigma_n) ); LinearTermPtr conservedQuantity = Teuchos::rcp<LinearTerm>( new LinearTerm(1.0, beta_n_u_hat) ); LinearTermPtr sourcePart = Teuchos::rcp<LinearTerm>( new LinearTerm(invDt, u) ); conservedQuantity->addTerm(sourcePart, true); solution->lagrangeConstraints()->addConstraint(conservedQuantity == u_prev_time * invDt); } } double energyThreshold = 0.2; // for mesh refinements RefinementStrategy refinementStrategy( solution, energyThreshold ); VTKExporter exporter(solution, mesh, varFactory); for (int refIndex=0; refIndex<=numRefs; refIndex++) { if (steady) { solution->solve(false); if (commRank == 0) { stringstream outfile; outfile << "Convection_" << refIndex; exporter.exportSolution(outfile.str()); // Check local conservation FunctionPtr flux = Teuchos::rcp( new PreviousSolutionFunction(solution, beta_n_u_hat) ); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); Teuchos::Tuple<double, 3> fluxImbalances = checkConservation(flux, zero, varFactory, mesh); cout << "Mass flux: Largest Local = " << fluxImbalances[0] << ", Global = " << fluxImbalances[1] << ", Sum Abs = " << fluxImbalances[2] << endl; } } else { int timestepCount = 0; double time_tol = 1e-8; double L2_time_residual = 1e9; // cout << L2_time_residual <<" "<< time_tol << timestepCount << numTimeSteps << endl; while((L2_time_residual > time_tol) && (timestepCount < numTimeSteps)) { solution->solve(false); // Subtract solutions to get residual flowResidual->setSolution(solution); flowResidual->addSolution(prevTimeFlow, -1.0); L2_time_residual = flowResidual->L2NormOfSolutionGlobal(u->ID()); if (commRank == 0) { cout << endl << "Timestep: " << timestepCount << ", dt = " << dt << ", Time residual = " << L2_time_residual << endl; stringstream outfile; outfile << "TransientConvection_" << refIndex << "-" << timestepCount; exporter.exportSolution(outfile.str()); // Check local conservation FunctionPtr flux = Teuchos::rcp( new PreviousSolutionFunction(solution, beta_n_u_hat) ); FunctionPtr source = Teuchos::rcp( new PreviousSolutionFunction(flowResidual, u) ); source = -invDt * source; Teuchos::Tuple<double, 3> fluxImbalances = checkConservation(flux, source, varFactory, mesh); cout << "Mass flux: Largest Local = " << fluxImbalances[0] << ", Global = " << fluxImbalances[1] << ", Sum Abs = " << fluxImbalances[2] << endl; } prevTimeFlow->setSolution(solution); // reset previous time solution to current time sol timestepCount++; } } if (refIndex < numRefs) refinementStrategy.refine(commRank==0); // print to console on commRank 0 } 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 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); int rank=mpiSession.getRank(); int numProcs=mpiSession.getNProc(); #else int rank = 0; int numProcs = 1; #endif int polyOrder = 3; int pToAdd = 2; // for tests // define our manufactured solution or problem bilinear form: bool useTriangles = false; FieldContainer<double> meshPoints(4,2); meshPoints(0,0) = 0.0; // x1 meshPoints(0,1) = 0.0; // y1 meshPoints(1,0) = 1.0; meshPoints(1,1) = 0.0; meshPoints(2,0) = 1.0; meshPoints(2,1) = 1.0; meshPoints(3,0) = 0.0; meshPoints(3,1) = 1.0; int H1Order = polyOrder + 1; int horizontalCells = 4, verticalCells = 4; 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 fhat = varFactory.fluxVar("\\widehat{f}"); VarPtr u = varFactory.fieldVar("u"); 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 = Mesh::buildQuadMesh(meshPoints, horizontalCells, verticalCells, bf, H1Order, H1Order+pToAdd, useTriangles); 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 //////////////////////////////////////////////////////////////////// // v: // (sigma, grad v)_K - (sigma_hat_n, v)_dK - (u, beta dot grad v) + (u_hat * n dot beta, v)_dK bf->addTerm( -u, beta * v->grad()); bf->addTerm( fhat, 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; backgroundFlow->projectOntoMesh(functionMap); // ==================== END SET INITIAL GUESS ========================== //////////////////////////////////////////////////////////////////// // DEFINE INNER PRODUCT //////////////////////////////////////////////////////////////////// IPPtr ip = Teuchos::rcp( new IP ); ip->addTerm( v ); ip->addTerm( beta * v->grad() ); //////////////////////////////////////////////////////////////////// // DEFINE RHS //////////////////////////////////////////////////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr u_prev_squared_div2 = 0.5 * u_prev * u_prev; rhs->addTerm( (e1 * u_prev_squared_div2 + e2 * u_prev) * v->grad()); //////////////////////////////////////////////////////////////////// // DEFINE DIRICHLET BC //////////////////////////////////////////////////////////////////// Teuchos::RCP<BCEasy> inflowBC = Teuchos::rcp( new BCEasy ); // Create spatial filters SpatialFilterPtr bottomBoundary = Teuchos::rcp( new BottomBoundary ); SpatialFilterPtr leftBoundary = Teuchos::rcp( new LeftBoundary ); SpatialFilterPtr rightBoundary = Teuchos::rcp( new LeftBoundary ); // Create BCs FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); FunctionPtr u0_squared_div_2 = 0.5 * u0 * u0; SimpleFunction* u0Ptr = static_cast<SimpleFunction *>(u0.get()); double u0Left = u0Ptr->value(0,0); double u0Right = u0Ptr->value(1.0,0); FunctionPtr leftVal = Teuchos::rcp( new ConstantScalarFunction( -0.5*u0Left*u0Left ) ); FunctionPtr rightVal = Teuchos::rcp( new ConstantScalarFunction( 0.5*u0Right*u0Right ) ); inflowBC->addDirichlet(fhat, bottomBoundary, -u0 ); inflowBC->addDirichlet(fhat, leftBoundary, leftVal ); inflowBC->addDirichlet(fhat, rightBoundary, rightVal ); //////////////////////////////////////////////////////////////////// // CREATE SOLUTION OBJECT //////////////////////////////////////////////////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp(new Solution(mesh, inflowBC, rhs, ip)); mesh->registerSolution(solution); if (enforceLocalConservation) { FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); solution->lagrangeConstraints()->addConstraint(fhat == zero); } //////////////////////////////////////////////////////////////////// // DEFINE REFINEMENT STRATEGY //////////////////////////////////////////////////////////////////// Teuchos::RCP<RefinementStrategy> refinementStrategy; refinementStrategy = Teuchos::rcp(new RefinementStrategy(solution,energyThreshold)); //////////////////////////////////////////////////////////////////// // SOLVE //////////////////////////////////////////////////////////////////// for (int refIndex=0; refIndex<=numRefs; refIndex++) { double L2Update = 1e7; int iterCount = 0; while (L2Update > nonlinearRelativeEnergyTolerance && iterCount < maxNewtonIterations) { solution->solve(); L2Update = solution->L2NormOfSolutionGlobal(u->ID()); cout << "L2 Norm of Update = " << L2Update << endl; // backgroundFlow->clear(); backgroundFlow->addSolution(solution, newtonStepSize); iterCount++; } cout << endl; // check conservation VarPtr testOne = varFactory.testVar("1", CONSTANT_SCALAR); // Create a fake bilinear form for the testing BFPtr fakeBF = Teuchos::rcp( new BF(varFactory) ); // Define our mass flux FunctionPtr massFlux = Teuchos::rcp( new PreviousSolutionFunction(solution, fhat) ); LinearTermPtr massFluxTerm = massFlux * testOne; Teuchos::RCP<shards::CellTopology> quadTopoPtr = Teuchos::rcp(new shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >() )); DofOrderingFactory dofOrderingFactory(fakeBF); int fakeTestOrder = H1Order; DofOrderingPtr testOrdering = dofOrderingFactory.testOrdering(fakeTestOrder, *quadTopoPtr); int testOneIndex = testOrdering->getDofIndex(testOne->ID(),0); vector< ElementTypePtr > elemTypes = mesh->elementTypes(); // global element types map<int, double> massFluxIntegral; // cellID -> integral double maxMassFluxIntegral = 0.0; double totalMassFlux = 0.0; double totalAbsMassFlux = 0.0; for (vector< ElementTypePtr >::iterator elemTypeIt = elemTypes.begin(); elemTypeIt != elemTypes.end(); elemTypeIt++) { ElementTypePtr elemType = *elemTypeIt; vector< ElementPtr > elems = mesh->elementsOfTypeGlobal(elemType); vector<int> cellIDs; for (int i=0; i<elems.size(); i++) { cellIDs.push_back(elems[i]->cellID()); } FieldContainer<double> physicalCellNodes = mesh->physicalCellNodesGlobal(elemType); BasisCachePtr basisCache = Teuchos::rcp( new BasisCache(elemType,mesh) ); basisCache->setPhysicalCellNodes(physicalCellNodes,cellIDs,true); // true: create side caches FieldContainer<double> cellMeasures = basisCache->getCellMeasures(); FieldContainer<double> fakeRHSIntegrals(elems.size(),testOrdering->totalDofs()); massFluxTerm->integrate(fakeRHSIntegrals,testOrdering,basisCache,true); // true: force side evaluation for (int i=0; i<elems.size(); i++) { int cellID = cellIDs[i]; // pick out the ones for testOne: massFluxIntegral[cellID] = fakeRHSIntegrals(i,testOneIndex); } // find the largest: for (int i=0; i<elems.size(); i++) { int cellID = cellIDs[i]; maxMassFluxIntegral = max(abs(massFluxIntegral[cellID]), maxMassFluxIntegral); } for (int i=0; i<elems.size(); i++) { int cellID = cellIDs[i]; maxMassFluxIntegral = max(abs(massFluxIntegral[cellID]), maxMassFluxIntegral); totalMassFlux += massFluxIntegral[cellID]; totalAbsMassFlux += abs( massFluxIntegral[cellID] ); } } if (rank==0) { cout << endl; cout << "largest mass flux: " << maxMassFluxIntegral << endl; cout << "total mass flux: " << totalMassFlux << endl; cout << "sum of mass flux absolute value: " << totalAbsMassFlux << endl; cout << endl; stringstream outfile; outfile << "burgers_" << refIndex; backgroundFlow->writeToVTK(outfile.str(), 5); } if (refIndex < numRefs) refinementStrategy->refine(rank==0); // print to console on rank 0 } return 0; }