int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); choice::MpiArgs args( argc, argv ); #else choice::Args args( argc, argv ); #endif int commRank = Teuchos::GlobalMPISession::getRank(); int numProcs = Teuchos::GlobalMPISession::getNProc(); // Required arguments double epsilon = args.Input<double>("--epsilon", "diffusion parameter"); int numRefs = args.Input<int>("--numRefs", "number of refinement steps"); bool enforceLocalConservation = args.Input<bool>("--conserve", "enforce local conservation"); int norm = args.Input<int>("--norm", "0 = graph\n 1 = robust\n 2 = modified robust"); // Optional arguments (have defaults) bool zeroL2 = args.Input("--zeroL2", "take L2 term on v in robust norm to zero", false); args.Process(); //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactory varFactory; VarPtr tau = varFactory.testVar("\\tau", HDIV); VarPtr v = varFactory.testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory.traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_n = varFactory.fluxVar("\\widehat{\\beta \\cdot n u - \\sigma_{n}}"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma = varFactory.fieldVar("sigma", VECTOR_L2); vector<double> beta; beta.push_back(1.0); beta.push_back(0.0); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // tau terms: bf->addTerm(sigma / epsilon, tau); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma, v->grad() ); bf->addTerm( beta * u, - v->grad() ); bf->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = Teuchos::rcp(new IP); if (norm == 0) { ip = bf->graphNorm(); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); ip->addZeroMeanTerm( h2_scaling*v ); } // Robust norm else if (norm == 1) { // robust test norm FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); if (!zeroL2) ip->addTerm( v ); ip->addTerm( sqrt(epsilon) * v->grad() ); // Weight these two terms for inflow ip->addTerm( beta * v->grad() ); ip->addTerm( tau->div() ); ip->addTerm( ip_scaling/sqrt(epsilon) * tau ); if (zeroL2) ip->addZeroMeanTerm( h2_scaling*v ); } // Modified robust norm else if (norm == 2) { // robust test norm FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); // FunctionPtr ip_weight = Teuchos::rcp( new IPWeight() ); if (!zeroL2) ip->addTerm( v ); ip->addTerm( sqrt(epsilon) * v->grad() ); ip->addTerm( beta * v->grad() ); ip->addTerm( tau->div() - beta*v->grad() ); ip->addTerm( ip_scaling/sqrt(epsilon) * tau ); if (zeroL2) ip->addZeroMeanTerm( h2_scaling*v ); } // // robust test norm // IPPtr robIP = Teuchos::rcp(new IP); // FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); // if (!enforceLocalConservation) // robIP->addTerm( ip_scaling * v ); // robIP->addTerm( sqrt(epsilon) * v->grad() ); // // Weight these two terms for inflow // FunctionPtr ip_weight = Teuchos::rcp( new IPWeight() ); // robIP->addTerm( ip_weight * beta * v->grad() ); // robIP->addTerm( ip_weight * tau->div() ); // robIP->addTerm( ip_scaling/sqrt(epsilon) * tau ); // if (enforceLocalConservation) // robIP->addZeroMeanTerm( v ); //////////////////// SPECIFY RHS /////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr f = Teuchos::rcp( new ConstantScalarFunction(0.0) ); rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////// CREATE BCs /////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp( new PenaltyConstraints ); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); FunctionPtr one = Teuchos::rcp( new ConstantScalarFunction(1.0) ); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); SpatialFilterPtr lBoundary = Teuchos::rcp( new LeftBoundary ); SpatialFilterPtr tbBoundary = Teuchos::rcp( new TopBottomBoundary ); SpatialFilterPtr rBoundary = Teuchos::rcp( new RightBoundary ); // SpatialFilterPtr leftCircleBoundary = Teuchos::rcp( new LeftCircleBoundary ); // SpatialFilterPtr rightCircleBoundary = Teuchos::rcp( new RightCircleBoundary ); SpatialFilterPtr circleBoundary = Teuchos::rcp( new CircleBoundary ); bc->addDirichlet(beta_n_u_minus_sigma_n, lBoundary, zero); bc->addDirichlet(beta_n_u_minus_sigma_n, tbBoundary, zero); pc->addConstraint(beta*uhat->times_normal() - beta_n_u_minus_sigma_n == zero, rBoundary); // bc->addDirichlet(uhat, leftCircleBoundary, one); // bc->addDirichlet(beta_n_u_minus_sigma_n, rightCircleBoundary, beta*n*one); bc->addDirichlet(uhat, circleBoundary, one); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int H1Order = 3, pToAdd = 2; Teuchos::RCP<Mesh> mesh; mesh = MeshFactory::shiftedHemkerMesh(-3, 9, 6, 1, bf, H1Order, pToAdd); // mesh = BuildHemkerMesh(bf, nseg, circleMesh, triangulateMesh, H1Order, pToAdd); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); solution->setFilter(pc); if (enforceLocalConservation) { FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); solution->lagrangeConstraints()->addConstraint(beta_n_u_minus_sigma_n == zero); } double energyThreshold = 0.25; // for mesh refinements RefinementStrategy refinementStrategy( solution, energyThreshold ); Teuchos::RCP<RefinementHistory> refHistory = Teuchos::rcp( new RefinementHistory ); mesh->registerObserver(refHistory); #ifdef saveVTK VTKExporter exporter(solution, mesh, varFactory); #endif ofstream errOut; if (commRank == 0) errOut.open("hemker_err.txt"); for (int refIndex=0; refIndex<=numRefs; refIndex++) { solution->solve(false); double energy_error = solution->energyErrorTotal(); if (commRank==0) { stringstream outfile; outfile << "hemker_" << refIndex; #ifdef saveVTK exporter.exportSolution(outfile.str()); #endif // Check local conservation FunctionPtr flux = Teuchos::rcp( new PreviousSolutionFunction(solution, beta_n_u_minus_sigma_n) ); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); Teuchos::Tuple<double, 3> fluxImbalances = checkConservation(flux, zero, varFactory, mesh); cout << "Mass flux: Largest Local = " << fluxImbalances[0] << ", Global = " << fluxImbalances[1] << ", Sum Abs = " << fluxImbalances[2] << endl; errOut << mesh->numGlobalDofs() << " " << energy_error << " " << fluxImbalances[0] << " " << fluxImbalances[1] << " " << fluxImbalances[2] << endl; } if (refIndex < numRefs) refinementStrategy.refine(commRank==0); // print to console on commRank 0 } if (commRank == 0) errOut.close(); return 0; }
int main(int argc, char *argv[]) { // 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 double epsilon = args.Input<double>("--epsilon", "diffusion parameter"); int numRefs = args.Input<int>("--numRefs", "number of refinement steps"); bool enforceLocalConservation = args.Input<bool>("--conserve", "enforce local conservation"); int norm = args.Input<int>("--norm", "0 = graph\n 1 = robust\n 2 = modified robust"); // Optional arguments (have defaults) halfwidth = args.Input("--halfwidth", "half the width of the wedge", 0.5); bool allQuads = args.Input("--allQuads", "use only quads in mesh", false); bool zeroL2 = args.Input("--zeroL2", "take L2 term on v in robust norm to zero", enforceLocalConservation); args.Process(); //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactory varFactory; VarPtr tau = varFactory.testVar("tau", HDIV); VarPtr v = varFactory.testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory.traceVar("uhat"); VarPtr beta_n_u_minus_sigma_n = varFactory.fluxVar("fhat"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma = varFactory.fieldVar("sigma", VECTOR_L2); vector<double> beta; beta.push_back(1.0); beta.push_back(0.0); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // tau terms: bf->addTerm(sigma / epsilon, tau); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma, v->grad() ); bf->addTerm( beta * u, - v->grad() ); bf->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = Teuchos::rcp(new IP); // Graph norm if (norm == 0) { ip = bf->graphNorm(); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); ip->addZeroMeanTerm( h2_scaling*v ); } // Robust norm else if (norm == 1) { // robust test norm FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); if (!zeroL2) ip->addTerm( v ); ip->addTerm( sqrt(epsilon) * v->grad() ); // Weight these two terms for inflow ip->addTerm( beta * v->grad() ); ip->addTerm( tau->div() ); ip->addTerm( ip_scaling/sqrt(epsilon) * tau ); if (zeroL2) ip->addZeroMeanTerm( h2_scaling*v ); } // Modified robust norm else if (norm == 2) { // robust test norm FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); if (!zeroL2) ip->addTerm( v ); ip->addTerm( sqrt(epsilon) * v->grad() ); ip->addTerm( tau->div() - beta*v->grad() ); ip->addTerm( ip_scaling/sqrt(epsilon) * tau ); if (zeroL2) ip->addZeroMeanTerm( h2_scaling*v ); } //////////////////// SPECIFY RHS /////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr f = Teuchos::rcp( new ConstantScalarFunction(0.0) ); rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////// CREATE BCs /////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp( new PenaltyConstraints ); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); SpatialFilterPtr inflow = Teuchos::rcp( new Inflow ); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); bc->addDirichlet(beta_n_u_minus_sigma_n, inflow, zero); SpatialFilterPtr leadingWedge = Teuchos::rcp( new LeadingWedge ); FunctionPtr one = Teuchos::rcp( new ConstantScalarFunction(1.0) ); bc->addDirichlet(uhat, leadingWedge, one); SpatialFilterPtr trailingWedge = Teuchos::rcp( new TrailingWedge ); bc->addDirichlet(beta_n_u_minus_sigma_n, trailingWedge, beta*n*one); // bc->addDirichlet(uhat, trailingWedge, one); SpatialFilterPtr top = Teuchos::rcp( new Top ); bc->addDirichlet(uhat, top, zero); // bc->addDirichlet(beta_n_u_minus_sigma_n, top, zero); SpatialFilterPtr outflow = Teuchos::rcp( new Outflow ); pc->addConstraint(beta*uhat->times_normal() - beta_n_u_minus_sigma_n == zero, outflow); //////////////////// BUILD MESH /////////////////////// int H1Order = 3, pToAdd = 2; // define nodes for mesh vector< FieldContainer<double> > vertices; FieldContainer<double> pt(2); vector< vector<int> > elementIndices; vector<int> q(4); vector<int> t(3); if (allQuads) { pt(0) = -halfwidth; pt(1) = -1; vertices.push_back(pt); pt(0) = 0; pt(1) = 0; vertices.push_back(pt); pt(0) = halfwidth; pt(1) = -1; vertices.push_back(pt); pt(0) = halfwidth; pt(1) = halfwidth; vertices.push_back(pt); pt(0) = 0; pt(1) = halfwidth; vertices.push_back(pt); pt(0) = -halfwidth; pt(1) = halfwidth; vertices.push_back(pt); q[0] = 0; q[1] = 1; q[2] = 4; q[3] = 5; elementIndices.push_back(q); q[0] = 1; q[1] = 2; q[2] = 3; q[3] = 4; elementIndices.push_back(q); } else { pt(0) = -halfwidth; pt(1) = -1; vertices.push_back(pt); pt(0) = 0; pt(1) = 0; vertices.push_back(pt); pt(0) = halfwidth; pt(1) = -1; vertices.push_back(pt); pt(0) = halfwidth; pt(1) = 0; vertices.push_back(pt); pt(0) = halfwidth; pt(1) = halfwidth; vertices.push_back(pt); pt(0) = 0; pt(1) = halfwidth; vertices.push_back(pt); pt(0) = -halfwidth; pt(1) = halfwidth; vertices.push_back(pt); pt(0) = -halfwidth; pt(1) = 0; vertices.push_back(pt); t[0] = 0; t[1] = 1; t[2] = 7; elementIndices.push_back(t); t[0] = 1; t[1] = 2; t[2] = 3; elementIndices.push_back(t); q[0] = 1; q[1] = 3; q[2] = 4; q[3] = 5; elementIndices.push_back(q); q[0] = 7; q[1] = 1; q[2] = 5; q[3] = 6; elementIndices.push_back(q); } Teuchos::RCP<Mesh> mesh = Teuchos::rcp( new Mesh(vertices, elementIndices, bf, H1Order, pToAdd) ); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); solution->setFilter(pc); if (enforceLocalConservation) { FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); solution->lagrangeConstraints()->addConstraint(beta_n_u_minus_sigma_n == zero); } double energyThreshold = 0.2; // for mesh refinements RefinementStrategy refinementStrategy( solution, energyThreshold ); VTKExporter exporter(solution, mesh, varFactory); ofstream errOut; if (commRank == 0) errOut.open("singularwedge_err.txt"); for (int refIndex=0; refIndex<=numRefs; refIndex++){ solution->solve(false); double energy_error = solution->energyErrorTotal(); if (commRank==0){ stringstream outfile; outfile << "singularwedge_" << refIndex; exporter.exportSolution(outfile.str()); // Check local conservation FunctionPtr flux = Teuchos::rcp( new PreviousSolutionFunction(solution, beta_n_u_minus_sigma_n) ); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); Teuchos::Tuple<double, 3> fluxImbalances = checkConservation(flux, zero, varFactory, mesh); cout << "Mass flux: Largest Local = " << fluxImbalances[0] << ", Global = " << fluxImbalances[1] << ", Sum Abs = " << fluxImbalances[2] << endl; errOut << mesh->numGlobalDofs() << " " << energy_error << " " << fluxImbalances[0] << " " << fluxImbalances[1] << " " << fluxImbalances[2] << endl; } if (refIndex < numRefs) refinementStrategy.refine(commRank==0); // print to console on commRank 0 } if (commRank == 0) errOut.close(); return 0; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); int rank=mpiSession.getRank(); int numProcs=mpiSession.getNProc(); #else int rank = 0; int numProcs = 1; #endif //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactory varFactory; VarPtr tau = varFactory.testVar("\\tau", HDIV); VarPtr v = varFactory.testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory.traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_n = varFactory.fluxVar("\\widehat{\\beta \\cdot n u - \\sigma_{n}}"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma1 = varFactory.fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory.fieldVar("\\sigma_2"); vector<double> beta_const; beta_const.push_back(1.0); beta_const.push_back(0.0); // FunctionPtr beta = Teuchos::rcp(new Beta()); double eps = 1e-2; //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr confusionBF = Teuchos::rcp( new BF(varFactory) ); // tau terms: confusionBF->addTerm(sigma1 / eps, tau->x()); confusionBF->addTerm(sigma2 / eps, tau->y()); confusionBF->addTerm(u, tau->div()); confusionBF->addTerm(-uhat, tau->dot_normal()); // v terms: confusionBF->addTerm( sigma1, v->dx() ); confusionBF->addTerm( sigma2, v->dy() ); confusionBF->addTerm( beta_const * u, - v->grad() ); confusionBF->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// // mathematician's norm IPPtr mathIP = Teuchos::rcp(new IP()); mathIP->addTerm(tau); mathIP->addTerm(tau->div()); mathIP->addTerm(v); mathIP->addTerm(v->grad()); // quasi-optimal norm IPPtr qoptIP = Teuchos::rcp(new IP); qoptIP->addTerm( v ); qoptIP->addTerm( tau / eps + v->grad() ); qoptIP->addTerm( beta_const * v->grad() - tau->div() ); // robust test norm IPPtr robIP = Teuchos::rcp(new IP); FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(eps) ); if (enforceLocalConservation) { robIP->addZeroMeanTerm( v ); } else { robIP->addTerm( ip_scaling * v ); } robIP->addTerm( sqrt(eps) * v->grad() ); robIP->addTerm( beta_const * v->grad() ); robIP->addTerm( tau->div() ); robIP->addTerm( ip_scaling/sqrt(eps) * tau ); //////////////////// SPECIFY RHS /////////////////////// FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr f = zero; rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////// CREATE BCs /////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); // SpatialFilterPtr inflowBoundary = Teuchos::rcp( new InflowSquareBoundary ); // SpatialFilterPtr outflowBoundary = Teuchos::rcp( new OutflowSquareBoundary ); SpatialFilterPtr inflowTop = Teuchos::rcp(new InflowLshapeTop); SpatialFilterPtr inflowBot = Teuchos::rcp(new InflowLshapeBottom); SpatialFilterPtr LshapeBot1 = Teuchos::rcp(new LshapeBottom1); SpatialFilterPtr LshapeBot2 = Teuchos::rcp(new LshapeBottom2); SpatialFilterPtr Top = Teuchos::rcp(new LshapeTop); SpatialFilterPtr Out = Teuchos::rcp(new LshapeOutflow); FunctionPtr u0 = Teuchos::rcp( new U0 ); bc->addDirichlet(uhat, LshapeBot1, u0); bc->addDirichlet(uhat, LshapeBot2, u0); bc->addDirichlet(uhat, Top, u0); bc->addDirichlet(uhat, Out, u0); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); // bc->addDirichlet(uhat, inflowBot, u0); FunctionPtr u0Top = Teuchos::rcp(new ParabolicProfile); FunctionPtr u0Bot = Teuchos::rcp(new LinearProfile); bc->addDirichlet(beta_n_u_minus_sigma_n, inflowTop, beta_const*n*u0Top); // bc->addDirichlet(beta_n_u_minus_sigma_n, inflowBot, beta_const*n*u0Bot); bc->addDirichlet(beta_n_u_minus_sigma_n, inflowBot, beta_const*n*zero); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int H1Order = 2, pToAdd = 2; /* FieldContainer<double> quadPoints(4,2); quadPoints(0,0) = 0.0; // x1 quadPoints(0,1) = 0.0; // y1 quadPoints(1,0) = 1.0; quadPoints(1,1) = 0.0; quadPoints(2,0) = 1.0; quadPoints(2,1) = 1.0; quadPoints(3,0) = 0.0; quadPoints(3,1) = 1.0; int horizontalCells = 1, verticalCells = 1; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = Mesh::buildQuadMesh(quadPoints, horizontalCells, verticalCells, confusionBF, H1Order, H1Order+pToAdd); */ Teuchos::RCP<Mesh> mesh; // L-shaped domain for double ramp problem FieldContainer<double> A(2), B(2), C(2), D(2), E(2), F(2), G(2), H(2); A(0) = 0.0; A(1) = 0.5; B(0) = 0.0; B(1) = 1.0; C(0) = 0.5; C(1) = 1.0; D(0) = 1.0; D(1) = 1.0; E(0) = 1.0; E(1) = 0.5; F(0) = 1.0; F(1) = 0.0; G(0) = 0.5; G(1) = 0.0; H(0) = 0.5; H(1) = 0.5; vector<FieldContainer<double> > vertices; vertices.push_back(A); int A_index = 0; vertices.push_back(B); int B_index = 1; vertices.push_back(C); int C_index = 2; vertices.push_back(D); int D_index = 3; vertices.push_back(E); int E_index = 4; vertices.push_back(F); int F_index = 5; vertices.push_back(G); int G_index = 6; vertices.push_back(H); int H_index = 7; vector< vector<int> > elementVertices; vector<int> el1, el2, el3, el4, el5; // left patch: el1.push_back(A_index); el1.push_back(H_index); el1.push_back(C_index); el1.push_back(B_index); // top right: el2.push_back(H_index); el2.push_back(E_index); el2.push_back(D_index); el2.push_back(C_index); // bottom right: el3.push_back(G_index); el3.push_back(F_index); el3.push_back(E_index); el3.push_back(H_index); elementVertices.push_back(el1); elementVertices.push_back(el2); elementVertices.push_back(el3); mesh = Teuchos::rcp( new Mesh(vertices, elementVertices, confusionBF, H1Order, pToAdd) ); //////////////////// SOLVE & REFINE /////////////////////// // Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, qoptIP) ); Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, robIP) ); // solution->setFilter(pc); if (enforceLocalConservation) { FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); solution->lagrangeConstraints()->addConstraint(beta_n_u_minus_sigma_n == zero); } double energyThreshold = 0.2; // for mesh refinements RefinementStrategy refinementStrategy( solution, energyThreshold ); int numRefs = 8; for (int refIndex=0; refIndex<numRefs; refIndex++) { solution->solve(false); refinementStrategy.refine(rank==0); // print to console on rank 0 } // one more solve on the final refined mesh: solution->solve(false); if (rank==0) { solution->writeToVTK("step.vtu",min(H1Order+1,4)); solution->writeFluxesToFile(uhat->ID(), "uhat.dat"); cout << "wrote files: u.m, uhat.dat\n"; } return 0; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); int rank=mpiSession.getRank(); int numProcs=mpiSession.getNProc(); #else int rank = 0; int numProcs = 1; #endif //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactory varFactory; VarPtr tau = varFactory.testVar("\\tau", HDIV); VarPtr v = varFactory.testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory.traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_n = varFactory.fluxVar("\\widehat{\\beta \\cdot n u - \\sigma_{n}}"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma1 = varFactory.fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory.fieldVar("\\sigma_2"); vector<double> beta_const; double c = sqrt(1.25); beta_const.push_back(1.0/c); beta_const.push_back(.5/c); // FunctionPtr beta = Teuchos::rcp(new Beta()); double eps = 1e-3; //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr confusionBF = Teuchos::rcp( new BF(varFactory) ); // tau terms: confusionBF->addTerm(sigma1 / eps, tau->x()); confusionBF->addTerm(sigma2 / eps, tau->y()); confusionBF->addTerm(u, tau->div()); confusionBF->addTerm(-uhat, tau->dot_normal()); // v terms: confusionBF->addTerm( sigma1, v->dx() ); confusionBF->addTerm( sigma2, v->dy() ); confusionBF->addTerm( beta_const * u, - v->grad() ); confusionBF->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// // quasi-optimal norm IPPtr qoptIP = Teuchos::rcp(new IP); qoptIP->addTerm( v ); qoptIP->addTerm( tau / eps + v->grad() ); qoptIP->addTerm( beta_const * v->grad() - tau->div() ); // robust test norm IPPtr robIP = Teuchos::rcp(new IP); FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(eps) ); if (enforceLocalConservation) { robIP->addZeroMeanTerm( v ); } else { robIP->addTerm( ip_scaling * v ); } robIP->addTerm( sqrt(eps) * v->grad() ); bool useNewBC = false; FunctionPtr weight = Teuchos::rcp( new SqrtWeight(eps) ); if (useNewBC) { robIP->addTerm( beta_const * v->grad() ); robIP->addTerm( tau->div() ); robIP->addTerm( ip_scaling/sqrt(eps) * tau ); } else { robIP->addTerm( weight * beta_const * v->grad() ); robIP->addTerm( weight * tau->div() ); robIP->addTerm( weight * ip_scaling/sqrt(eps) * tau ); } //////////////////// SPECIFY RHS /////////////////////// FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr f = zero; rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////// CREATE BCs /////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); SpatialFilterPtr inflowBoundary = Teuchos::rcp( new InflowSquareBoundary ); SpatialFilterPtr outflowBoundary = Teuchos::rcp( new OutflowSquareBoundary ); FunctionPtr u0 = Teuchos::rcp( new U0 ); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); bc->addDirichlet(uhat, outflowBoundary, zero); if (useNewBC) { bc->addDirichlet(beta_n_u_minus_sigma_n, inflowBoundary, beta_const*n*u0); } else { SpatialFilterPtr inflowBot = Teuchos::rcp( new InflowSquareBot ); SpatialFilterPtr inflowLeft = Teuchos::rcp( new InflowSquareLeft ); bc->addDirichlet(beta_n_u_minus_sigma_n, inflowLeft, beta_const*n*u0); bc->addDirichlet(uhat, inflowBot, u0); } // Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp(new PenaltyConstraints); // pc->addConstraint(uhat==u0,inflowBoundary); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int H1Order = 2, pToAdd = 2; FieldContainer<double> quadPoints(4,2); quadPoints(0,0) = 0.0; // x1 quadPoints(0,1) = 0.0; // y1 quadPoints(1,0) = 1.0; quadPoints(1,1) = 0.0; quadPoints(2,0) = 1.0; quadPoints(2,1) = 1.0; quadPoints(3,0) = 0.0; quadPoints(3,1) = 1.0; int nCells = 2; int horizontalCells = nCells, verticalCells = nCells; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = Mesh::buildQuadMesh(quadPoints, horizontalCells, verticalCells, confusionBF, H1Order, H1Order+pToAdd); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, robIP) ); // solution->setFilter(pc); if (enforceLocalConservation) { FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); solution->lagrangeConstraints()->addConstraint(beta_n_u_minus_sigma_n == zero); } double energyThreshold = 0.2; // for mesh refinements RefinementStrategy refinementStrategy( solution, energyThreshold ); int numRefs = 9; for (int refIndex=0; refIndex<numRefs; refIndex++) { solution->solve(false); refinementStrategy.refine(rank==0); // print to console on rank 0 } // one more solve on the final refined mesh: solution->solve(false); if (rank==0) { solution->writeToVTK("Hughes.vtu",min(H1Order+1,4)); solution->writeFluxesToFile(uhat->ID(), "uhat.dat"); cout << "wrote files: u.m, uhat.dat\n"; } return 0; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); choice::MpiArgs args( argc, argv ); #else choice::Args args( argc, argv ); #endif int commRank = Teuchos::GlobalMPISession::getRank(); int numProcs = Teuchos::GlobalMPISession::getNProc(); // Required arguments double epsilon = args.Input<double>("--epsilon", "diffusion parameter"); int numRefs = args.Input<int>("--numRefs", "number of refinement steps"); bool enforceLocalConservation = args.Input<bool>("--conserve", "enforce local conservation"); bool graphNorm = args.Input<bool>("--graphNorm", "use the graph norm rather than robust test norm"); // Optional arguments (have defaults) bool highLiftAirfoil = args.Input("--highLift", "use high lift airfoil rather than NACA0012", false); args.Process(); //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactory varFactory; VarPtr tau = varFactory.testVar("tau", HDIV); VarPtr v = varFactory.testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory.traceVar("uhat"); VarPtr beta_n_u_minus_sigma_n = varFactory.fluxVar("fhat"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma = varFactory.fieldVar("sigma", VECTOR_L2); vector<double> beta; beta.push_back(1.0); beta.push_back(0.25); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // tau terms: bf->addTerm(sigma / epsilon, tau); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma, v->grad() ); bf->addTerm( beta * u, - v->grad() ); bf->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = Teuchos::rcp(new IP); if (graphNorm) { ip = bf->graphNorm(); } else { // robust test norm FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); if (!enforceLocalConservation) ip->addTerm( ip_scaling * v ); ip->addTerm( sqrt(epsilon) * v->grad() ); // Weight these two terms for inflow ip->addTerm( beta * v->grad() ); ip->addTerm( tau->div() ); ip->addTerm( ip_scaling/sqrt(epsilon) * tau ); if (enforceLocalConservation) ip->addZeroMeanTerm( v ); } //////////////////// SPECIFY RHS /////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr f = Teuchos::rcp( new ConstantScalarFunction(0.0) ); rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////// CREATE BCs /////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp( new PenaltyConstraints ); SpatialFilterPtr lBoundary = Teuchos::rcp( new LeftBoundary ); SpatialFilterPtr tBoundary = Teuchos::rcp( new TopBoundary ); SpatialFilterPtr bBoundary = Teuchos::rcp( new BottomBoundary ); SpatialFilterPtr rBoundary = Teuchos::rcp( new RightBoundary ); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); SpatialFilterPtr airfoilInflowBoundary = Teuchos::rcp( new AirfoilInflowBoundary(beta) ); SpatialFilterPtr airfoilOutflowBoundary = Teuchos::rcp( new AirfoilOutflowBoundary(beta) ); FunctionPtr u0 = Teuchos::rcp( new ZeroBC ); FunctionPtr u1 = Teuchos::rcp( new OneBC ); bc->addDirichlet(beta_n_u_minus_sigma_n, lBoundary, u0); bc->addDirichlet(beta_n_u_minus_sigma_n, bBoundary, u0); // bc->addDirichlet(uhat, airfoilInflowBoundary, u1); // bc->addDirichlet(uhat, tBoundary, u0); bc->addDirichlet(beta_n_u_minus_sigma_n, airfoilInflowBoundary, beta*n*u1); bc->addDirichlet(uhat, airfoilOutflowBoundary, u1); // pc->addConstraint(beta*uhat->times_normal() - beta_n_u_minus_sigma_n == u0, rBoundary); // pc->addConstraint(beta*uhat->times_normal() - beta_n_u_minus_sigma_n == u0, tBoundary); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int H1Order = 3, pToAdd = 2; Teuchos::RCP<Mesh> mesh; if (highLiftAirfoil) mesh = Mesh::readTriangle(Camellia_MeshDir+"HighLift/HighLift.1", bf, H1Order, pToAdd); else mesh = Mesh::readTriangle(Camellia_MeshDir+"NACA0012/NACA0012.1", bf, H1Order, pToAdd); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); // solution->setFilter(pc); if (enforceLocalConservation) { FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); solution->lagrangeConstraints()->addConstraint(beta_n_u_minus_sigma_n == zero); } double energyThreshold = 0.2; // for mesh refinements RefinementStrategy refinementStrategy( solution, energyThreshold ); VTKExporter exporter(solution, mesh, varFactory); for (int refIndex=0; refIndex<=numRefs; refIndex++) { solution->solve(false); if (commRank == 0) { stringstream outfile; if (highLiftAirfoil) outfile << "highlift_" << refIndex; else outfile << "naca0012_" << refIndex; exporter.exportSolution(outfile.str()); // Check local conservation FunctionPtr flux = Teuchos::rcp( new PreviousSolutionFunction(solution, beta_n_u_minus_sigma_n) ); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); Teuchos::Tuple<double, 3> fluxImbalances = checkConservation(flux, zero, varFactory, mesh); cout << "Mass flux: Largest Local = " << fluxImbalances[0] << ", Global = " << fluxImbalances[1] << ", Sum Abs = " << fluxImbalances[2] << endl; } if (refIndex < numRefs) { // refinementStrategy.refine(commRank==0); // print to console on commRank 0 // Try pseudo-hp adaptive vector<int> cellsToRefine; vector<int> cells_h; vector<int> cells_p; refinementStrategy.getCellsAboveErrorThreshhold(cellsToRefine); for (int i=0; i < cellsToRefine.size(); i++) if (sqrt(mesh->getCellMeasure(cellsToRefine[i])) < epsilon) { int pOrder = mesh->cellPolyOrder(cellsToRefine[i]); if (pOrder < 8) cells_p.push_back(cellsToRefine[i]); else cells_h.push_back(cellsToRefine[i]); } else cells_h.push_back(cellsToRefine[i]); refinementStrategy.pRefineCells(mesh, cells_p); refinementStrategy.hRefineCells(mesh, cells_h); } } return 0; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); choice::MpiArgs args( argc, argv ); #else choice::Args args( argc, argv ); #endif int commRank = Teuchos::GlobalMPISession::getRank(); int numProcs = Teuchos::GlobalMPISession::getNProc(); // Required arguments double epsilon = args.Input<double>("--epsilon", "diffusion parameter"); int numRefs = args.Input<int>("--numRefs", "number of refinement steps"); bool enforceLocalConservation = args.Input<bool>("--conserve", "enforce local conservation"); int norm = args.Input<int>("--norm", "0 = graph\n 1 = robust\n 2 = modified robust"); // Optional arguments (have defaults) bool zeroL2 = args.Input("--zeroL2", "take L2 term on v in robust norm to zero", true); args.Process(); //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactory varFactory; VarPtr tau = varFactory.testVar("tau", HDIV); VarPtr v = varFactory.testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory.traceVar("uhat"); VarPtr fhat = varFactory.fluxVar("fhat"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma = varFactory.fieldVar("sigma", VECTOR_L2); //////////////////// BUILD MESH /////////////////////// BFPtr bf = Teuchos::rcp( new BF(varFactory) ); int H1Order = 3, pToAdd = 2; // define nodes for mesh FieldContainer<double> meshBoundary(4,2); meshBoundary(0,0) = 0.0; // x1 meshBoundary(0,1) = 0.0; // y1 meshBoundary(1,0) = 1.0; meshBoundary(1,1) = 0.0; meshBoundary(2,0) = 1.0; meshBoundary(2,1) = 1.0; meshBoundary(3,0) = 0.0; meshBoundary(3,1) = 1.0; int horizontalCells = 4, verticalCells = 4; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = Mesh::buildQuadMesh(meshBoundary, horizontalCells, verticalCells, bf, H1Order, H1Order+pToAdd, false); vector<double> beta; beta.push_back(2.0); beta.push_back(1.0); //////////////////// DEFINE BILINEAR FORM /////////////////////// // tau terms: bf->addTerm(sigma / epsilon, tau); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma, v->grad() ); bf->addTerm( beta * u, - v->grad() ); bf->addTerm( fhat, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = Teuchos::rcp(new IP); if (norm == 0) { ip = bf->graphNorm(); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); ip->addZeroMeanTerm( h2_scaling*v ); } // Robust norm else if (norm == 1) { // robust test norm FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); if (!zeroL2) ip->addTerm( v ); ip->addTerm( sqrt(epsilon) * v->grad() ); // Weight these two terms for inflow ip->addTerm( beta * v->grad() ); ip->addTerm( tau->div() ); ip->addTerm( ip_scaling/sqrt(epsilon) * tau ); if (zeroL2) ip->addZeroMeanTerm( h2_scaling*v ); } // Modified robust norm else if (norm == 2) { // robust test norm FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); // FunctionPtr ip_weight = Teuchos::rcp( new IPWeight() ); if (!zeroL2) ip->addTerm( v ); ip->addTerm( sqrt(epsilon) * v->grad() ); ip->addTerm( beta * v->grad() ); ip->addTerm( tau->div() - beta*v->grad() ); ip->addTerm( ip_scaling/sqrt(epsilon) * tau ); if (zeroL2) ip->addZeroMeanTerm( h2_scaling*v ); } //////////////////// SPECIFY RHS /////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr f = Teuchos::rcp( new ConstantScalarFunction(0.0) ); rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////// CREATE BCs /////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); SpatialFilterPtr inflowBoundary = Teuchos::rcp( new InflowBoundary ); SpatialFilterPtr outflowBoundary = Teuchos::rcp( new OutflowBoundary ); FunctionPtr u0 = Teuchos::rcp( new U0 ); bc->addDirichlet(uhat, outflowBoundary, u0); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); bc->addDirichlet(fhat, inflowBoundary, beta*n*u0); // Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp(new PenaltyConstraints); // pc->addConstraint(uhat==u0,inflowBoundary); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); // solution->setFilter(pc); if (enforceLocalConservation) { FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); solution->lagrangeConstraints()->addConstraint(fhat == zero); } double energyThreshold = 0.2; // for mesh refinements RefinementStrategy refinementStrategy( solution, energyThreshold ); VTKExporter exporter(solution, mesh, varFactory); ofstream errOut; if (commRank == 0) errOut.open("confusion_err.txt"); for (int refIndex=0; refIndex<=numRefs; refIndex++){ solution->solve(false); double energy_error = solution->energyErrorTotal(); if (commRank==0){ stringstream outfile; outfile << "confusion_" << refIndex; exporter.exportSolution(outfile.str()); // solution->writeToVTK(outfile.str()); // Check local conservation FunctionPtr flux = Function::solution(fhat, solution); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); Teuchos::Tuple<double, 3> fluxImbalances = checkConservation(flux, zero, varFactory, mesh); cout << "Mass flux: Largest Local = " << fluxImbalances[0] << ", Global = " << fluxImbalances[1] << ", Sum Abs = " << fluxImbalances[2] << endl; errOut << mesh->numGlobalDofs() << " " << energy_error << " " << fluxImbalances[0] << " " << fluxImbalances[1] << " " << fluxImbalances[2] << endl; } if (refIndex < numRefs) refinementStrategy.refine(commRank==0); // print to console on commRank 0 } if (commRank == 0) errOut.close(); return 0; }