bool LinearTermTests::testLinearTermEvaluation() { bool success = true; double eps = .1; FunctionPtr one = Function::constant(1.0); vector<double> e1,e2; e1.push_back(1.0); e1.push_back(0.0); e2.push_back(0.0); e2.push_back(1.0); // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr tau = varFactory->testVar("\\tau", HDIV); VarPtr v = varFactory->testVar("v", HGRAD); // define a couple LinearTerms LinearTermPtr vVecLT = Teuchos::rcp(new LinearTerm); LinearTermPtr tauVecLT = Teuchos::rcp(new LinearTerm); vVecLT->addTerm(sqrt(eps)*v->grad()); tauVecLT->addTerm((1/sqrt(eps))*tau); //////////////////// evaluate LinearTerms ///////////////// map<int,FunctionPtr> errRepMap; errRepMap[v->ID()] = one; errRepMap[tau->ID()] = one*e1+one*e2; // vector valued fxn (1,1) FunctionPtr errTau = tauVecLT->evaluate(errRepMap,false); FunctionPtr errV = vVecLT->evaluate(errRepMap,false); try { bool xTauZero = errTau->x()->isZero(); bool yTauZero = errTau->y()->isZero(); bool xVZero = errV->dx()->isZero(); bool yVZero = errV->dy()->isZero(); } catch (...) { cout << "testLinearTermEvaluation: Caught exception.\n"; success = false; } /* FunctionPtr xErr = (errTau->x())*(errTau->x()) + (errV->dx())*(errV->dx()); FunctionPtr yErr = (errTau->y())*(errTau->y()) + (errV->dy())*(errV->dy()); double xErrVal = xErr->integrate(mesh,15,true); */ // if we don't crash, return success return success; }
void Boundary::bcsToImpose( map< GlobalIndexType, Scalar > &globalDofIndicesAndValues, TBC<Scalar> &bc, GlobalIndexType cellID, DofInterpreter* dofInterpreter) { // this is where we actually compute the BCs; the other bcsToImpose variants call this one. CellPtr cell = _mesh->getTopology()->getCell(cellID); // define a couple of important inner products: TIPPtr<Scalar> ipL2 = Teuchos::rcp( new TIP<Scalar> ); TIPPtr<Scalar> ipH1 = Teuchos::rcp( new TIP<Scalar> ); VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr trace = varFactory->traceVar("trace"); VarPtr flux = varFactory->traceVar("flux"); ipL2->addTerm(flux); ipH1->addTerm(trace); ipH1->addTerm(trace->grad()); ElementTypePtr elemType = _mesh->getElementType(cellID); DofOrderingPtr trialOrderingPtr = elemType->trialOrderPtr; vector< int > trialIDs = _mesh->bilinearForm()->trialIDs(); vector<unsigned> boundarySides = cell->boundarySides(); if (boundarySides.size() > 0) { BasisCachePtr basisCache = BasisCache::basisCacheForCell(_mesh, cellID); for (vector< int >::iterator trialIt = trialIDs.begin(); trialIt != trialIDs.end(); trialIt++) { int trialID = *(trialIt); if ( bc.bcsImposed(trialID) ) { // // DEBUGGING: keep track of which sides we impose BCs on: // set<unsigned> bcImposedSides; // // Determine global dof indices and values, in one pass per side for (int i=0; i<boundarySides.size(); i++) { unsigned sideOrdinal = boundarySides[i]; // TODO: here, we need to treat the volume basis case. /* To do this: 1. (Determine which dofs in the basis have support on the side.) 2. (Probably should resize dirichletValues to match number of dofs with support on the side.) 3. (Within coefficientsForBC, and the projection method it calls, when it's a side cache, check whether the basis being projected has a higher dimension. If so, do the same determination regarding the support of basis on the side as #1.) 4. DofInterpreter::interpretLocalBasisCoefficients() needs to handle the case that trialID has volume support, and in this case interpret the provided data appropriately. */ BasisPtr basis; int numDofsSide; if (trialOrderingPtr->getSidesForVarID(trialID).size() == 1) { // volume basis basis = trialOrderingPtr->getBasis(trialID); // get the dof ordinals for the side (interpreted as a "continuous" basis) numDofsSide = basis->dofOrdinalsForSide(sideOrdinal).size(); } else if (! trialOrderingPtr->hasBasisEntry(trialID, sideOrdinal)) { continue; } else { basis = trialOrderingPtr->getBasis(trialID,sideOrdinal); numDofsSide = basis->getCardinality(); } GlobalIndexType numCells = 1; if (numCells > 0) { FieldContainer<double> dirichletValues(numCells,numDofsSide); // project bc function onto side basis: BCPtr bcPtr = Teuchos::rcp(&bc, false); Teuchos::RCP<BCFunction<double>> bcFunction = BCFunction<double>::bcFunction(bcPtr, trialID); bcPtr->coefficientsForBC(dirichletValues, bcFunction, basis, basisCache->getSideBasisCache(sideOrdinal)); dirichletValues.resize(numDofsSide); if (bcFunction->imposeOnCell(0)) { FieldContainer<double> globalData; FieldContainer<GlobalIndexType> globalDofIndices; dofInterpreter->interpretLocalBasisCoefficients(cellID, trialID, sideOrdinal, dirichletValues, globalData, globalDofIndices); for (int globalDofOrdinal=0; globalDofOrdinal<globalDofIndices.size(); globalDofOrdinal++) { GlobalIndexType globalDofIndex = globalDofIndices(globalDofOrdinal); Scalar value = globalData(globalDofOrdinal); // sanity check: if this has been previously set, do the two values roughly agree? if (globalDofIndicesAndValues.find(globalDofIndex) != globalDofIndicesAndValues.end()) { double tol = 1e-10; Scalar prevValue = globalDofIndicesAndValues[globalDofIndex]; double absDiff = abs(prevValue - value); if (absDiff > tol) { double relativeDiff = absDiff / max(abs(prevValue),abs(value)); int rank = _mesh->Comm()->MyPID(); if (relativeDiff > tol) { cout << "WARNING: in Boundary::bcsToImpose(), inconsistent values for BC: " << prevValue << " and "; cout << value << " prescribed for global dof index " << globalDofIndex; cout << " on rank " << rank << endl; } } } globalDofIndicesAndValues[globalDofIndex] = value; } } } } } } } }
// tests Riesz inversion by integration by parts bool LinearTermTests::testRieszInversion() { bool success = true; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr tau = varFactory->testVar("\\tau", HDIV); VarPtr v = varFactory->testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory->traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_n = varFactory->fluxVar("\\widehat{\\beta \\cdot n u - \\sigma_{n}}"); VarPtr u = varFactory->fieldVar("u"); VarPtr sigma1 = varFactory->fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory->fieldVar("\\sigma_2"); vector<double> beta; beta.push_back(1.0); beta.push_back(0.0); double eps = .01; //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr confusionBF = Teuchos::rcp( new BF(varFactory) ); // tau terms: confusionBF->addTerm(sigma1 / eps, tau->x()); confusionBF->addTerm(sigma2 / eps, tau->y()); confusionBF->addTerm(u, tau->div()); confusionBF->addTerm(uhat, -tau->dot_normal()); // v terms: confusionBF->addTerm( sigma1, v->dx() ); confusionBF->addTerm( sigma2, v->dy() ); confusionBF->addTerm( -u, beta * v->grad() ); confusionBF->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int H1Order = 1; int pToAdd = 1; FieldContainer<double> quadPoints(4,2); quadPoints(0,0) = 0.0; // x1 quadPoints(0,1) = 0.0; // y1 quadPoints(1,0) = 1.0; quadPoints(1,1) = 0.0; quadPoints(2,0) = 1.0; quadPoints(2,1) = 1.0; quadPoints(3,0) = 0.0; quadPoints(3,1) = 1.0; int nCells = 1; int horizontalCells = nCells, verticalCells = nCells; // create a pointer to a new mesh: Teuchos::RCP<Mesh> myMesh = MeshFactory::buildQuadMesh(quadPoints, horizontalCells, verticalCells, confusionBF, H1Order, H1Order+pToAdd); ElementTypePtr elemType = myMesh->getElement(0)->elementType(); BasisCachePtr basisCache = Teuchos::rcp(new BasisCache(elemType, myMesh)); vector<GlobalIndexType> cellIDs; vector<ElementPtr> elems = myMesh->activeElements(); vector<ElementPtr>::iterator elemIt; for (elemIt=elems.begin(); elemIt!=elems.end(); elemIt++) { int cellID = (*elemIt)->cellID(); cellIDs.push_back(cellID); } bool createSideCacheToo = true; basisCache->setPhysicalCellNodes(myMesh->physicalCellNodesGlobal(elemType), cellIDs, createSideCacheToo); LinearTermPtr integrand = Teuchos::rcp(new LinearTerm);// residual LinearTermPtr integrandIBP = Teuchos::rcp(new LinearTerm);// residual vector<double> e1(2); // (1,0) vector<double> e2(2); // (0,1) e1[0] = 1; e2[1] = 1; FunctionPtr n = Function::normal(); FunctionPtr X = Function::xn(1); FunctionPtr Y = Function::yn(1); FunctionPtr testFxn1 = X; FunctionPtr testFxn2 = Y; FunctionPtr divTestFxn = testFxn1->dx() + testFxn2->dy(); FunctionPtr vectorTest = testFxn1*e1 + testFxn2*e2; integrand->addTerm(divTestFxn*v); integrandIBP->addTerm(vectorTest*n*v - vectorTest*v->grad()); // boundary term IPPtr sobolevIP = Teuchos::rcp(new IP); sobolevIP->addTerm(v); sobolevIP->addTerm(tau); Teuchos::RCP<RieszRep> riesz = Teuchos::rcp(new RieszRep(myMesh, sobolevIP, integrand)); // riesz->setPrintOption(true); riesz->computeRieszRep(); Teuchos::RCP<RieszRep> rieszIBP = Teuchos::rcp(new RieszRep(myMesh, sobolevIP, integrandIBP)); riesz->setFunctional(integrandIBP); // rieszIBP->setPrintOption(true); rieszIBP->computeRieszRep(); FunctionPtr rieszOrigFxn = RieszRep::repFunction(v,riesz); FunctionPtr rieszIBPFxn = RieszRep::repFunction(v,rieszIBP); int numCells = basisCache->getPhysicalCubaturePoints().dimension(0); int numPts = basisCache->getPhysicalCubaturePoints().dimension(1); FieldContainer<double> valOriginal( numCells, numPts); FieldContainer<double> valIBP( numCells, numPts); rieszOrigFxn->values(valOriginal,basisCache); rieszIBPFxn->values(valIBP,basisCache); double maxDiff; double tol = 1e-14; success = TestSuite::fcsAgree(valOriginal,valIBP,tol,maxDiff); if (success==false) { cout << "Failed TestRieszInversion with maxDiff = " << maxDiff << endl; } return success; }
bool LinearTermTests::testRieszInversionAsProjection() { bool success = true; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr tau = varFactory->testVar("\\tau", HDIV); VarPtr v = varFactory->testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory->traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_n = varFactory->fluxVar("\\widehat{\\beta \\cdot n u - \\sigma_{n}}"); VarPtr u = varFactory->fieldVar("u"); VarPtr sigma1 = varFactory->fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory->fieldVar("\\sigma_2"); vector<double> beta; beta.push_back(1.0); beta.push_back(0.0); double eps = .01; //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr confusionBF = Teuchos::rcp( new BF(varFactory) ); // tau terms: confusionBF->addTerm(sigma1 / eps, tau->x()); confusionBF->addTerm(sigma2 / eps, tau->y()); confusionBF->addTerm(u, tau->div()); confusionBF->addTerm(uhat, -tau->dot_normal()); // v terms: confusionBF->addTerm( sigma1, v->dx() ); confusionBF->addTerm( sigma2, v->dy() ); confusionBF->addTerm( -u, beta * v->grad() ); confusionBF->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int H1Order = 2; int pToAdd = 2; FieldContainer<double> quadPoints(4,2); quadPoints(0,0) = 0.0; // x1 quadPoints(0,1) = 0.0; // y1 quadPoints(1,0) = 1.0; quadPoints(1,1) = 0.0; quadPoints(2,0) = 1.0; quadPoints(2,1) = 1.0; quadPoints(3,0) = 0.0; quadPoints(3,1) = 1.0; int nCells = 2; int horizontalCells = nCells, verticalCells = nCells; // create a new mesh: MeshPtr myMesh = MeshFactory::buildQuadMesh(quadPoints, horizontalCells, verticalCells, confusionBF, H1Order, H1Order+pToAdd); ElementTypePtr elemType = myMesh->getElement(0)->elementType(); BasisCachePtr basisCache = Teuchos::rcp(new BasisCache(elemType, myMesh)); vector<GlobalIndexType> cellIDs = myMesh->cellIDsOfTypeGlobal(elemType); bool createSideCacheToo = true; basisCache->setPhysicalCellNodes(myMesh->physicalCellNodesGlobal(elemType), cellIDs, createSideCacheToo); LinearTermPtr integrand = Teuchos::rcp(new LinearTerm); // residual FunctionPtr x = Function::xn(1); FunctionPtr y = Function::yn(1); FunctionPtr testFxn1 = x; FunctionPtr testFxn2 = y; FunctionPtr fxnToProject = x * y + 1.0; integrand->addTerm(fxnToProject * v); IPPtr ip_L2 = Teuchos::rcp(new IP); ip_L2->addTerm(v); ip_L2->addTerm(tau); Teuchos::RCP<RieszRep> riesz = Teuchos::rcp(new RieszRep(myMesh, ip_L2, integrand)); riesz->computeRieszRep(); FunctionPtr rieszFxn = RieszRep::repFunction(v,riesz); int numCells = basisCache->getPhysicalCubaturePoints().dimension(0); int numPts = basisCache->getPhysicalCubaturePoints().dimension(1); FieldContainer<double> valProject( numCells, numPts ); FieldContainer<double> valExpected( numCells, numPts ); rieszFxn->values(valProject,basisCache); fxnToProject->values(valExpected,basisCache); // int rank = Teuchos::GlobalMPISession::getRank(); // if (rank==0) cout << "physicalCubaturePoints:\n" << basisCache->getPhysicalCubaturePoints(); double maxDiff; double tol = 1e-12; success = TestSuite::fcsAgree(valProject,valExpected,tol,maxDiff); if (success==false) { cout << "Failed Riesz Inversion Projection test with maxDiff = " << maxDiff << endl; serializeOutput("valExpected", valExpected); serializeOutput("valProject", valProject); serializeOutput("physicalPoints", basisCache->getPhysicalCubaturePoints()); } return allSuccess(success); }
bool LinearTermTests::testIntegrateMixedBasis() { bool success = true; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = 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(1.0); //////////////////// DEFINE BILINEAR FORM/Mesh /////////////////////// BFPtr convectionBF = Teuchos::rcp( new BF(varFactory) ); // v terms: convectionBF->addTerm( -u, beta * v->grad() ); convectionBF->addTerm( beta_n_u_hat, v); convectionBF->addTerm( u, v); // build CONSTANT SINGLE ELEMENT MESH int order = 0; int H1Order = order+1; int pToAdd = 1; int nCells = 2; // along a side // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = MeshUtilities::buildUnitQuadMesh(nCells,convectionBF, H1Order, H1Order+pToAdd); ElementTypePtr elemType = mesh->getElement(0)->elementType(); BasisCachePtr basisCache = Teuchos::rcp(new BasisCache(elemType, mesh)); vector<GlobalIndexType> cellIDs; vector< ElementPtr > allElems = mesh->activeElements(); vector< ElementPtr >::iterator elemIt; for (elemIt=allElems.begin(); elemIt!=allElems.end(); elemIt++) { cellIDs.push_back((*elemIt)->cellID()); } bool createSideCacheToo = true; basisCache->setPhysicalCellNodes(mesh->physicalCellNodesGlobal(elemType), cellIDs, createSideCacheToo); int numTrialDofs = elemType->trialOrderPtr->totalDofs(); int numCells = mesh->numActiveElements(); double areaPerCell = 1.0 / numCells; FieldContainer<double> integrals(numCells,numTrialDofs); FieldContainer<double> expectedIntegrals(numCells,numTrialDofs); double sidelengthOfCell = 1.0 / nCells; DofOrderingPtr trialOrdering = elemType->trialOrderPtr; int dofForField = trialOrdering->getDofIndex(u->ID(), 0); vector<int> dofsForFlux; const vector<int>* sidesForFlux = &trialOrdering->getSidesForVarID(beta_n_u_hat->ID()); for (vector<int>::const_iterator sideIt = sidesForFlux->begin(); sideIt != sidesForFlux->end(); sideIt++) { int sideIndex = *sideIt; dofsForFlux.push_back(trialOrdering->getDofIndex(beta_n_u_hat->ID(), 0, sideIndex)); } for (int cellIndex = 0; cellIndex < numCells; cellIndex++) { expectedIntegrals(cellIndex, dofForField) = areaPerCell; for (vector<int>::iterator dofIt = dofsForFlux.begin(); dofIt != dofsForFlux.end(); dofIt++) { int fluxDofIndex = *dofIt; expectedIntegrals(cellIndex, fluxDofIndex) = sidelengthOfCell; } } // cout << "expectedIntegrals:\n" << expectedIntegrals; // setup: with constant degrees of freedom, we expect that the integral of int_dK (flux) + int_K (field) will be ones for each degree of freedom, assuming the basis functions for these constants field/flux variables are just C = 1.0. // //On a unit square, int_K (constant) = 1.0, and int_dK (u_i) = 1, for i = 0,...,3. LinearTermPtr lt = 1.0 * beta_n_u_hat; LinearTermPtr field = 1.0 * u; lt->addTerm(field,true); lt->integrate(integrals, elemType->trialOrderPtr, basisCache); double tol = 1e-12; double maxDiff; success = TestSuite::fcsAgree(integrals,expectedIntegrals,tol,maxDiff); if (success==false) { cout << "Failed testIntegrateMixedBasis with maxDiff = " << maxDiff << endl; } return success; }
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 rank = Teuchos::GlobalMPISession::getRank(); int numProcs = Teuchos::GlobalMPISession::getNProc(); int nCells = args.Input<int>("--nCells", "num cells",2); int numRefs = args.Input<int>("--numRefs","num adaptive refinements",0); int numPreRefs = args.Input<int>("--numPreRefs","num preemptive adaptive refinements",0); int order = args.Input<int>("--order","order of approximation",2); double eps = args.Input<double>("--epsilon","diffusion parameter",1e-2); double energyThreshold = args.Input<double>("-energyThreshold","energy thresh for adaptivity", .5); double rampHeight = args.Input<double>("--rampHeight","ramp height at x = 2", 0.0); double ipSwitch = args.Input<double>("--ipSwitch","point at which to switch to graph norm", 0.0); // default to 0 to remain on robust norm bool useAnisotropy = args.Input<bool>("--useAnisotropy","aniso flag ", false); int H1Order = order+1; int pToAdd = args.Input<int>("--pToAdd","test space enrichment", 2); FunctionPtr zero = Function::constant(0.0); FunctionPtr one = Function::constant(1.0); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); vector<double> e1,e2; e1.push_back(1.0);e1.push_back(0.0); e2.push_back(0.0);e2.push_back(1.0); //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactory varFactory; VarPtr tau = varFactory.testVar("\\tau", HDIV); VarPtr v = varFactory.testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory.traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_n = varFactory.fluxVar("\\widehat{\\beta \\cdot n u - \\sigma_{n}}"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma1 = varFactory.fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory.fieldVar("\\sigma_2"); vector<double> beta; beta.push_back(1.0); beta.push_back(0.0); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr confusionBF = Teuchos::rcp( new BF(varFactory) ); // tau terms: confusionBF->addTerm(sigma1 / eps, tau->x()); confusionBF->addTerm(sigma2 / eps, tau->y()); confusionBF->addTerm(u, tau->div()); confusionBF->addTerm(uhat, -tau->dot_normal()); // v terms: confusionBF->addTerm( sigma1, v->dx() ); confusionBF->addTerm( sigma2, v->dy() ); confusionBF->addTerm( -u, beta * v->grad() ); confusionBF->addTerm( beta_n_u_minus_sigma_n, v); // first order term with magnitude alpha double alpha = 0.0; // confusionBF->addTerm(alpha * u, v); //////////////////// BUILD MESH /////////////////////// // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = MeshUtilities::buildUnitQuadMesh(nCells,confusionBF, H1Order, H1Order+pToAdd); mesh->setPartitionPolicy(Teuchos::rcp(new ZoltanMeshPartitionPolicy("HSFC"))); MeshInfo meshInfo(mesh); // gets info like cell measure, etc //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = Teuchos::rcp(new IP); /* // robust test norm FunctionPtr C_h = Teuchos::rcp( new EpsilonScaling(eps) ); FunctionPtr invH = Teuchos::rcp(new InvHScaling); FunctionPtr invSqrtH = Teuchos::rcp(new InvSqrtHScaling); FunctionPtr sqrtH = Teuchos::rcp(new SqrtHScaling); FunctionPtr hSwitch = Teuchos::rcp(new HSwitch(ipSwitch,mesh)); ip->addTerm(hSwitch*sqrt(eps) * v->grad() ); ip->addTerm(hSwitch*beta * v->grad() ); ip->addTerm(hSwitch*tau->div() ); // graph norm ip->addTerm( (one-hSwitch)*((1.0/eps) * tau + v->grad())); ip->addTerm( (one-hSwitch)*(beta * v->grad() - tau->div())); // regularizing terms ip->addTerm(C_h/sqrt(eps) * tau ); ip->addTerm(invSqrtH*v); */ // robust test norm IPPtr robIP = Teuchos::rcp(new IP); FunctionPtr C_h = Teuchos::rcp( new EpsilonScaling(eps) ); FunctionPtr invH = Teuchos::rcp(new InvHScaling); FunctionPtr invSqrtH = Teuchos::rcp(new InvSqrtHScaling); FunctionPtr sqrtH = Teuchos::rcp(new SqrtHScaling); FunctionPtr hSwitch = Teuchos::rcp(new HSwitch(ipSwitch,mesh)); robIP->addTerm(sqrt(eps) * v->grad() ); robIP->addTerm(beta * v->grad() ); robIP->addTerm(tau->div() ); // regularizing terms robIP->addTerm(C_h/sqrt(eps) * tau ); robIP->addTerm(invSqrtH*v); IPPtr graphIP = confusionBF->graphNorm(); graphIP->addTerm(invSqrtH*v); // graphIP->addTerm(C_h/sqrt(eps) * tau ); IPPtr switchIP = Teuchos::rcp(new IPSwitcher(robIP,graphIP,ipSwitch)); // rob IP for h>ipSwitch mesh size, graph norm o/w ip = switchIP; LinearTermPtr vVecLT = Teuchos::rcp(new LinearTerm); LinearTermPtr tauVecLT = Teuchos::rcp(new LinearTerm); vVecLT->addTerm(sqrt(eps)*v->grad()); tauVecLT->addTerm(C_h/sqrt(eps)*tau); LinearTermPtr restLT = Teuchos::rcp(new LinearTerm); restLT->addTerm(alpha*v); restLT->addTerm(invSqrtH*v); restLT = restLT + beta * v->grad(); restLT = restLT + tau->div(); //////////////////// SPECIFY RHS /////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr f = zero; // f = one; rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////// CREATE BCs /////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); SpatialFilterPtr Inflow = Teuchos::rcp(new LeftInflow); SpatialFilterPtr wallBoundary = Teuchos::rcp(new WallBoundary);//MeshUtilities::rampBoundary(rampHeight); SpatialFilterPtr freeStream = Teuchos::rcp(new FreeStreamBoundary); bc->addDirichlet(uhat, wallBoundary, one); // bc->addDirichlet(uhat, wallBoundary, Teuchos::rcp(new WallSmoothBC(eps))); bc->addDirichlet(beta_n_u_minus_sigma_n, Inflow, zero); bc->addDirichlet(beta_n_u_minus_sigma_n, freeStream, zero); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution; solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); BCPtr nullBC = Teuchos::rcp((BC*)NULL); RHSPtr nullRHS = Teuchos::rcp((RHS*)NULL); IPPtr nullIP = Teuchos::rcp((IP*)NULL); SolutionPtr backgroundFlow = Teuchos::rcp(new Solution(mesh, nullBC, nullRHS, nullIP) ); mesh->registerSolution(backgroundFlow); // to trigger issue with p-refinements map<int, Teuchos::RCP<Function> > functionMap; functionMap[u->ID()] = Function::constant(3.14); backgroundFlow->projectOntoMesh(functionMap); // lower p to p = 1 at SINGULARITY only vector<int> ids; /* for (int i = 0;i<mesh->numActiveElements();i++){ bool cellIDset = false; int cellID = mesh->activeElements()[i]->cellID(); int elemOrder = mesh->cellPolyOrder(cellID)-1; FieldContainer<double> vv(4,2); mesh->verticesForCell(vv, cellID); bool vertexOnWall = false; bool vertexAtSingularity = false; for (int j = 0;j<4;j++){ if ((abs(vv(j,0)-.5) + abs(vv(j,1)))<1e-10){ vertexAtSingularity = true; cellIDset = true; } } if (!vertexAtSingularity && elemOrder<2 && !cellIDset ){ ids.push_back(cellID); cout << "celliD = " << cellID << endl; } } */ ids.push_back(1); ids.push_back(3); mesh->pRefine(ids); // to put order = 1 return 0; LinearTermPtr residual = rhs->linearTermCopy(); residual->addTerm(-confusionBF->testFunctional(solution)); RieszRepPtr rieszResidual = Teuchos::rcp(new RieszRep(mesh, ip, residual)); rieszResidual->computeRieszRep(); FunctionPtr e_v = Teuchos::rcp(new RepFunction(v,rieszResidual)); FunctionPtr e_tau = Teuchos::rcp(new RepFunction(tau,rieszResidual)); map<int,FunctionPtr> errRepMap; errRepMap[v->ID()] = e_v; errRepMap[tau->ID()] = e_tau; FunctionPtr errTau = tauVecLT->evaluate(errRepMap,false); FunctionPtr errV = vVecLT->evaluate(errRepMap,false); FunctionPtr errRest = restLT->evaluate(errRepMap,false); FunctionPtr xErr = (errTau->x())*(errTau->x()) + (errV->dx())*(errV->dx()); FunctionPtr yErr = (errTau->y())*(errTau->y()) + (errV->dy())*(errV->dy()); FunctionPtr restErr = errRest*errRest; RefinementStrategy refinementStrategy( solution, energyThreshold ); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // PRE REFINEMENTS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if (rank==0){ cout << "Number of pre-refinements = " << numPreRefs << endl; } for (int i =0;i<=numPreRefs;i++){ vector<ElementPtr> elems = mesh->activeElements(); vector<ElementPtr>::iterator elemIt; vector<int> wallCells; for (elemIt=elems.begin();elemIt != elems.end();elemIt++){ int cellID = (*elemIt)->cellID(); int numSides = mesh->getElement(cellID)->numSides(); FieldContainer<double> vertices(numSides,2); //for quads mesh->verticesForCell(vertices, cellID); bool cellIDset = false; for (int j = 0;j<numSides;j++){ if ((abs(vertices(j,0)-.5)<1e-7) && (abs(vertices(j,1))<1e-7) && !cellIDset){ // if at singularity, i.e. if a vertex is (1,0) wallCells.push_back(cellID); cellIDset = true; } } } if (i<numPreRefs){ refinementStrategy.refineCells(wallCells); } } double minSideLength = meshInfo.getMinCellSideLength() ; double minCellMeasure = meshInfo.getMinCellMeasure() ; if (rank==0){ cout << "after prerefs, sqrt min cell measure = " << sqrt(minCellMeasure) << ", min side length = " << minSideLength << endl; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// VTKExporter exporter(solution, mesh, varFactory); for (int refIndex=0;refIndex<numRefs;refIndex++){ if (rank==0){ cout << "on ref index " << refIndex << endl; } rieszResidual->computeRieszRep(); // in preparation to get anisotropy vector<int> cellIDs; refinementStrategy.getCellsAboveErrorThreshhold(cellIDs); map<int,double> energyError = solution->energyError(); map<int,double> xErrMap = xErr->cellIntegrals(cellIDs,mesh,5,true); map<int,double> yErrMap = yErr->cellIntegrals(cellIDs,mesh,5,true); map<int,double> restErrMap = restErr->cellIntegrals(cellIDs,mesh,5,true); for (vector<ElementPtr>::iterator elemIt = mesh->activeElements().begin();elemIt!=mesh->activeElements().end();elemIt++){ int cellID = (*elemIt)->cellID(); double err = xErrMap[cellID]+ yErrMap[cellID] + restErrMap[cellID]; // if (rank==0) // cout << "err thru LT = " << sqrt(err) << ", while energy err = " << energyError[cellID] << endl; } /* map<int,double> ratio,xErr,yErr; vector<ElementPtr> elems = mesh->activeElements(); for (vector<ElementPtr>::iterator elemIt = elems.begin();elemIt!=elems.end();elemIt++){ int cellID = (*elemIt)->cellID(); ratio[cellID] = 0.0; xErr[cellID] = 0.0; yErr[cellID] = 0.0; if (std::find(cellIDs.begin(),cellIDs.end(),cellID)!=cellIDs.end()){ // if this cell is above energy thresh ratio[cellID] = yErrMap[cellID]/xErrMap[cellID]; xErr[cellID] = xErrMap[cellID]; yErr[cellID] = yErrMap[cellID]; } } FunctionPtr ratioFxn = Teuchos::rcp(new EnergyErrorFunction(ratio)); FunctionPtr xErrFxn = Teuchos::rcp(new EnergyErrorFunction(xErr)); FunctionPtr yErrFxn = Teuchos::rcp(new EnergyErrorFunction(yErr)); exporter.exportFunction(ratioFxn, string("ratio")+oss.str()); exporter.exportFunction(xErrFxn, string("xErr")+oss.str()); exporter.exportFunction(yErrFxn, string("yErr")+oss.str()); */ if (useAnisotropy){ refinementStrategy.refine(rank==0,xErrMap,yErrMap); //anisotropic refinements }else{ refinementStrategy.refine(rank==0); // no anisotropy } // lower p to p = 1 at SINGULARITY only vector<int> ids; for (int i = 0;i<mesh->numActiveElements();i++){ int cellID = mesh->activeElements()[i]->cellID(); int elemOrder = mesh->cellPolyOrder(cellID)-1; FieldContainer<double> vv(4,2); mesh->verticesForCell(vv, cellID); bool vertexOnWall = false; bool vertexAtSingularity = false; for (int j = 0;j<4;j++){ if ((abs(vv(j,0)-.5) + abs(vv(j,1)))<1e-10) vertexAtSingularity = true; } if (!vertexAtSingularity && elemOrder<2){ ids.push_back(cellID); } } mesh->pRefine(ids); // to put order = 1 /* if (elemOrder>1){ if (vertexAtSingularity){ vector<int> ids; ids.push_back(cellID); mesh->pRefine(ids,1-(elemOrder-1)); // to put order = 1 // mesh->pRefine(ids); // to put order = 1 if (rank==0) cout << "p unrefining elem with elemOrder = " << elemOrder << endl; } }else{ if (!vertexAtSingularity){ vector<int> ids; ids.push_back(cellID); mesh->pRefine(ids,2-elemOrder); } } */ double minSideLength = meshInfo.getMinCellSideLength() ; if (rank==0) cout << "minSideLength is " << minSideLength << endl; solution->condensedSolve(); std::ostringstream oss; oss << refIndex; } // final solve on final mesh solution->setWriteMatrixToFile(true,"K.mat"); solution->condensedSolve(); //////////////////////////////////////////////////////////////////////////////////////////////////////////// // CHECK CONDITIONING //////////////////////////////////////////////////////////////////////////////////////////////////////////// bool checkConditioning = true; if (checkConditioning){ double minSideLength = meshInfo.getMinCellSideLength() ; StandardAssembler assembler(solution); double maxCond = 0.0; int maxCellID = 0; for (int i = 0;i<mesh->numActiveElements();i++){ int cellID = mesh->getActiveElement(i)->cellID(); FieldContainer<double> ipMat = assembler.getIPMatrix(mesh->getElement(cellID)); double cond = SerialDenseWrapper::getMatrixConditionNumber(ipMat); if (cond>maxCond){ maxCond = cond; maxCellID = cellID; } } if (rank==0){ cout << "cell ID " << maxCellID << " has minCellLength " << minSideLength << " and condition estimate " << maxCond << endl; } string ipMatName = string("ipMat.mat"); ElementPtr maxCondElem = mesh->getElement(maxCellID); FieldContainer<double> ipMat = assembler.getIPMatrix(maxCondElem); SerialDenseWrapper::writeMatrixToMatlabFile(ipMatName,ipMat); } //////////////////// print to file /////////////////////// if (rank==0){ exporter.exportSolution(string("robustIP")); cout << endl; } return 0; }
int main(int argc, char *argv[]) { Teuchos::GlobalMPISession mpiSession(&argc, &argv, 0); int spaceDim = 2; int meshWidth = 2; bool conformingTraces = true; int H1Order = 2, delta_k = 3; double domainWidth = 1.0e-3; bool diagScaling = false; double h = domainWidth / meshWidth; double weight = h / 4.0; // ratio of area of square with sidelength h to its perimeter double sigma_weight = 1.0; // h / 4.0; // sigma = sigma_weight * u->grad() Space uHatSpace = conformingTraces ? HGRAD : L2; VarFactoryPtr vf = VarFactory::varFactory(); // fields VarPtr u = vf->fieldVar("u"); VarPtr sigma = vf->fieldVar("sigma", VECTOR_L2); // traces VarPtr u_hat = vf->traceVar("u_hat", uHatSpace); VarPtr sigma_n = vf->fluxVar("sigma_n"); // tests VarPtr v = vf->testVar("v", HGRAD); VarPtr tau = vf->testVar("tau", HDIV); BFPtr bf = BF::bf(vf); // standard BF: // bf->addTerm(sigma, v->grad()); // bf->addTerm(sigma_n, v); // // bf->addTerm(sigma, tau); // bf->addTerm(u, tau->div()); // bf->addTerm(-u_hat, tau->dot_normal()); // weighted BF: bf->addTerm(sigma, v->grad()); bf->addTerm(weight * sigma_n, v); bf->addTerm(sigma, tau); bf->addTerm(sigma_weight * u, tau->div()); bf->addTerm(- sigma_weight * weight * u_hat, tau->dot_normal()); IPPtr ip = IP::ip(); // standard IP: ip->addTerm(tau + v->grad()); ip->addTerm(tau->div()); ip->addTerm(v); ip->addTerm(tau); // weighted IP: // ip->addTerm(tau + v->grad()); // ip->addTerm(sigma_weight * tau->div()); // ip->addTerm(max(sigma_weight,1e-3) * v); // ip->addTerm(sigma_weight * weight * tau); BCPtr bc = BC::bc(); bc->addDirichlet(u_hat, SpatialFilter::allSpace(), Function::zero()); RHSPtr rhs = RHS::rhs(); rhs->addTerm(1.0 * sigma_weight * v); vector<double> dimensions(spaceDim,domainWidth); vector<int> elementCounts(spaceDim,meshWidth); MeshPtr mesh = MeshFactory::rectilinearMesh(bf, dimensions, elementCounts, H1Order, delta_k); SolutionPtr soln = Solution::solution(mesh, bc, rhs, ip); soln->setUseCondensedSolve(true); soln->initializeLHSVector(); soln->initializeStiffnessAndLoad(); soln->populateStiffnessAndLoad(); Teuchos::RCP<Epetra_RowMatrix> stiffness = soln->getStiffnessMatrix(); double condNumber = conditionNumberLAPACK(*stiffness, diagScaling); cout << "condest (1-norm): " << condNumber << endl; return 0; }
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; }
bool VectorizedBasisTestSuite::testPoisson() { bool success = true; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr tau = varFactory->testVar("\\tau", HDIV); VarPtr v = varFactory->testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory->traceVar("\\widehat{u}"); VarPtr sigma_n = varFactory->fluxVar("\\widehat{\\sigma_{n}}"); VarPtr u = varFactory->fieldVar("u"); VarPtr sigma = varFactory->fieldVar("\\sigma", VECTOR_L2); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // tau terms: bf->addTerm(sigma, tau); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma, v->grad() ); bf->addTerm( -sigma_n, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = bf->graphNorm(); //////////////////// SPECIFY RHS /////////////////////// RHSPtr rhs = RHS::rhs(); FunctionPtr f = Function::constant(1.0); rhs->addTerm( f * v ); //////////////////// CREATE BCs /////////////////////// BCPtr bc = BC::bc(); SpatialFilterPtr boundary = SpatialFilter::allSpace(); FunctionPtr zero = Function::zero(); bc->addDirichlet(uhat, boundary, zero); //////////////////// BUILD MESH /////////////////////// int H1Order = 3, pToAdd = 2; // define nodes for mesh FieldContainer<double> meshBoundary(4,2); meshBoundary(0,0) = 0.0; // x1 meshBoundary(0,1) = 0.0; // y1 meshBoundary(1,0) = 1.0; meshBoundary(1,1) = 0.0; meshBoundary(2,0) = 1.0; meshBoundary(2,1) = 1.0; meshBoundary(3,0) = 0.0; meshBoundary(3,1) = 1.0; int horizontalCells = 1, verticalCells = 1; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = MeshFactory::buildQuadMesh(meshBoundary, horizontalCells, verticalCells, bf, H1Order, H1Order+pToAdd, false); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); double energyThreshold = 0.2; // for mesh refinements RefinementStrategy refinementStrategy( solution, energyThreshold ); #ifdef USE_VTK VTKExporter exporter(solution, mesh, varFactory); #endif for (int refIndex=0; refIndex<=4; refIndex++) { solution->solve(false); #ifdef USE_VTK // output commented out because it's not properly part of the test. // stringstream outfile; // outfile << "test_" << refIndex; // exporter.exportSolution(outfile.str()); #endif if (refIndex < 4) refinementStrategy.refine(false); // don't print to console } return success; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); int rank=mpiSession.getRank(); int numProcs=mpiSession.getNProc(); #else int rank = 0; int numProcs = 1; #endif //////////////////// 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 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; }
void FunctionTests::setup() { //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr tau = varFactory->testVar("\\tau", HDIV); VarPtr v = varFactory->testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory->traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_n = varFactory->fluxVar("\\widehat{\\beta \\cdot n u - \\sigma_{n}}"); VarPtr u = varFactory->fieldVar("u"); VarPtr sigma1 = varFactory->fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory->fieldVar("\\sigma_2"); vector<double> beta_const; beta_const.push_back(2.0); beta_const.push_back(1.0); double eps = 1e-2; // standard confusion bilinear form _confusionBF = Teuchos::rcp( new BF(varFactory) ); // tau terms: _confusionBF->addTerm(sigma1 / eps, tau->x()); _confusionBF->addTerm(sigma2 / eps, tau->y()); _confusionBF->addTerm(u, tau->div()); _confusionBF->addTerm(-uhat, tau->dot_normal()); // v terms: _confusionBF->addTerm( sigma1, v->dx() ); _confusionBF->addTerm( sigma2, v->dy() ); _confusionBF->addTerm( beta_const * u, - v->grad() ); _confusionBF->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh FieldContainer<double> quadPoints(4,2); quadPoints(0,0) = -1.0; // x1 quadPoints(0,1) = -1.0; // y1 quadPoints(1,0) = 1.0; quadPoints(1,1) = -1.0; quadPoints(2,0) = 1.0; quadPoints(2,1) = 1.0; quadPoints(3,0) = -1.0; quadPoints(3,1) = 1.0; int H1Order = 1, pToAdd = 0; int horizontalCells = 1, verticalCells = 1; // create a pointer to a new mesh: _spectralConfusionMesh = MeshFactory::buildQuadMesh(quadPoints, horizontalCells, verticalCells, _confusionBF, H1Order, H1Order+pToAdd); // some 2D test points: // setup test points: static const int NUM_POINTS_1D = 10; double x[NUM_POINTS_1D] = {-1.0,-0.8,-0.6,-.4,-.2,0,0.2,0.4,0.6,0.8}; double y[NUM_POINTS_1D] = {-0.8,-0.6,-.4,-.2,0,0.2,0.4,0.6,0.8,1.0}; _testPoints = FieldContainer<double>(NUM_POINTS_1D*NUM_POINTS_1D,2); for (int i=0; i<NUM_POINTS_1D; i++) { for (int j=0; j<NUM_POINTS_1D; j++) { _testPoints(i*NUM_POINTS_1D + j, 0) = x[i]; _testPoints(i*NUM_POINTS_1D + j, 1) = y[j]; } } _elemType = _spectralConfusionMesh->getElementType(0); vector<GlobalIndexType> cellIDs; GlobalIndexType cellID = 0; cellIDs.push_back(cellID); _basisCache = Teuchos::rcp( new BasisCache( _elemType, _spectralConfusionMesh ) ); _basisCache->setRefCellPoints(_testPoints); _basisCache->setPhysicalCellNodes( _spectralConfusionMesh->physicalCellNodesForCell(cellID), cellIDs, true ); }
SpaceTimeIncompressibleFormulation::SpaceTimeIncompressibleFormulation(Teuchos::RCP<IncompressibleProblem> problem, Teuchos::ParameterList ¶meters) { int spaceDim = parameters.get<int>("spaceDim", 2); bool steady = parameters.get<bool>("steady", true); double mu = parameters.get<double>("mu", 1e-2); bool useConformingTraces = parameters.get<bool>("useConformingTraces", false); int fieldPolyOrder = parameters.get<int>("fieldPolyOrder", 2); int delta_p = parameters.get<int>("delta_p", 2); int numTElems = parameters.get<int>("numTElems", 2); string norm = parameters.get<string>("norm", "Graph"); string savedSolutionAndMeshPrefix = parameters.get<string>("savedSolutionAndMeshPrefix", ""); _spaceDim = spaceDim; _steady = steady; _mu = mu; _useConformingTraces = useConformingTraces; MeshTopologyPtr meshTopo = problem->meshTopology(numTElems); MeshGeometryPtr meshGeometry = problem->meshGeometry(); if (!steady) { TEUCHOS_TEST_FOR_EXCEPTION(meshTopo->getDimension() != _spaceDim + 1, std::invalid_argument, "MeshTopo must be space-time mesh for transient"); } else { TEUCHOS_TEST_FOR_EXCEPTION(meshTopo->getDimension() != _spaceDim, std::invalid_argument, "MeshTopo must be spatial mesh for steady"); } TEUCHOS_TEST_FOR_EXCEPTION(mu==0, std::invalid_argument, "mu may not be 0!"); TEUCHOS_TEST_FOR_EXCEPTION(spaceDim==1, std::invalid_argument, "Incompressible Navier-Stokes is trivial for spaceDim=1"); TEUCHOS_TEST_FOR_EXCEPTION((spaceDim != 2) && (spaceDim != 3), std::invalid_argument, "spaceDim must be 2 or 3"); Space uHatSpace = useConformingTraces ? HGRAD : L2; FunctionPtr zero = Function::constant(1); FunctionPtr one = Function::constant(1); FunctionPtr n_x = TFunction<double>::normal(); // spatial normal // FunctionPtr n_x_parity = n_x * TFunction<double>::sideParity(); FunctionPtr n_xt = TFunction<double>::normalSpaceTime(); // FunctionPtr n_xt_parity = n_xt * TFunction<double>::sideParity(); // declare all possible variables -- will only create the ones we need for spaceDim // fields VarPtr u1, u2, u3; VarPtr sigma11, sigma12, sigma13; VarPtr sigma21, sigma22, sigma23; VarPtr sigma31, sigma32, sigma33; VarPtr p; // traces VarPtr u1hat, u2hat, u3hat; VarPtr tm1hat, tm2hat, tm3hat; // tests VarPtr v1, v2, v3; VarPtr tau1, tau2, tau3; VarPtr q; _vf = VarFactory::varFactory(); if (spaceDim == 1) { u1 = _vf->fieldVar(s_u1); sigma11 = _vf->fieldVar(s_sigma11); p = _vf->fieldVar(s_p); u1hat = _vf->traceVarSpaceOnly(s_u1hat, 1.0 * u1, uHatSpace); tm1hat = _vf->fluxVar(s_tm1hat); v1 = _vf->testVar(s_v1, HGRAD); tau1 = _vf->testVar(s_tau1, HGRAD); // scalar q = _vf->testVar(s_q, HGRAD); } if (spaceDim == 2) { u1 = _vf->fieldVar(s_u1); u2 = _vf->fieldVar(s_u2); sigma11 = _vf->fieldVar(s_sigma11); sigma12 = _vf->fieldVar(s_sigma12); sigma21 = _vf->fieldVar(s_sigma21); sigma22 = _vf->fieldVar(s_sigma22); p = _vf->fieldVar(s_p); u1hat = _vf->traceVarSpaceOnly(s_u1hat, 1.0 * u1, uHatSpace); u2hat = _vf->traceVarSpaceOnly(s_u2hat, 1.0 * u2, uHatSpace); // LinearTermPtr tm1_lt, tm2_lt; // tm1_lt = p * n_x->x() - sigma11 * n_x->x() - sigma12 * n_x->y(); // tm2_lt = p * n_x->y() - sigma21 * n_x->x() - sigma22 * n_x->y(); // tm1hat = _vf->fluxVar(s_tm1hat, tm1_lt); // tm2hat = _vf->fluxVar(s_tm2hat, tm2_lt); tm1hat = _vf->fluxVar(s_tm1hat); tm2hat = _vf->fluxVar(s_tm2hat); v1 = _vf->testVar(s_v1, HGRAD); v2 = _vf->testVar(s_v2, HGRAD); tau1 = _vf->testVar(s_tau1, HDIV); // vector tau2 = _vf->testVar(s_tau2, HDIV); // vector q = _vf->testVar(s_q, HGRAD); } if (spaceDim == 3) { u1 = _vf->fieldVar(s_u1); u2 = _vf->fieldVar(s_u2); u3 = _vf->fieldVar(s_u3); sigma11 = _vf->fieldVar(s_sigma11); sigma12 = _vf->fieldVar(s_sigma12); sigma13 = _vf->fieldVar(s_sigma13); sigma21 = _vf->fieldVar(s_sigma21); sigma22 = _vf->fieldVar(s_sigma22); sigma23 = _vf->fieldVar(s_sigma23); sigma31 = _vf->fieldVar(s_sigma31); sigma32 = _vf->fieldVar(s_sigma32); sigma33 = _vf->fieldVar(s_sigma33); p = _vf->fieldVar(s_p); u1hat = _vf->traceVarSpaceOnly(s_u1hat, 1.0 * u1, uHatSpace); u2hat = _vf->traceVarSpaceOnly(s_u2hat, 1.0 * u2, uHatSpace); u3hat = _vf->traceVarSpaceOnly(s_u3hat, 1.0 * u3, uHatSpace); tm1hat = _vf->fluxVar(s_tm1hat); tm2hat = _vf->fluxVar(s_tm2hat); tm3hat = _vf->fluxVar(s_tm3hat); v1 = _vf->testVar(s_v1, HGRAD); v2 = _vf->testVar(s_v2, HGRAD); v3 = _vf->testVar(s_v3, HGRAD); tau1 = _vf->testVar(s_tau1, HDIV); // vector tau2 = _vf->testVar(s_tau2, HDIV); // vector tau3 = _vf->testVar(s_tau3, HDIV); // vector q = _vf->testVar(s_q, HGRAD); } // LinearTermPtr tc_lt; // if (spaceDim == 1) // { // tc_lt = beta->x()*n_x_parity->x()*u // -sigma1 * n_x_parity->x() // + u*n_xt_parity->t(); // } // else if (spaceDim == 2) // { // tc_lt = beta->x()*n_x_parity->x()*u // + beta->y()*n_x_parity->y()*u // - sigma1 * n_x_parity->x() // - sigma2 * n_x_parity->y() // + u*n_xt_parity->t(); // } // else if (spaceDim == 3) // { // tc_lt = beta->x()*n_x_parity->x()*u // + beta->y()*n_x_parity->y()*u // + beta->z()*n_x_parity->z()*u // - sigma1 * n_x_parity->x() // - sigma2 * n_x_parity->y() // - sigma3 * n_x_parity->z() // + u*n_xt_parity->t(); // } // tc = _vf->fluxVar(s_tc, tc_lt); _bf = Teuchos::rcp( new BF(_vf) ); // Define mesh BCPtr bc = BC::bc(); vector<int> H1Order(2); H1Order[0] = fieldPolyOrder + 1; H1Order[1] = fieldPolyOrder + 1; // for now, use same poly. degree for temporal bases... if (savedSolutionAndMeshPrefix == "") { map<int,int> trialOrderEnhancements; // trialOrderEnhancements[tm1hat->ID()] = fieldPolyOrder; // trialOrderEnhancements[tm2hat->ID()] = fieldPolyOrder; // trialOrderEnhancements[u1hat->ID()] = fieldPolyOrder; // trialOrderEnhancements[u2hat->ID()] = fieldPolyOrder; // MeshPtr proxyMesh = Teuchos::rcp( new Mesh(meshTopo->deepCopy(), _bf, H1Order, delta_p) ) ; _mesh = Teuchos::rcp( new Mesh(meshTopo, _bf, H1Order, delta_p, trialOrderEnhancements) ) ; if (meshGeometry != Teuchos::null) _mesh->setEdgeToCurveMap(meshGeometry->edgeToCurveMap()); // problem->preprocessMesh(_mesh); // proxyMesh->registerObserver(_mesh); // problem->preprocessMesh(proxyMesh); // _mesh->enforceOneIrregularity(); _solutionUpdate = Solution::solution(_bf, _mesh, bc); _solutionBackground = Solution::solution(_bf, _mesh, bc); map<int, FunctionPtr> initialGuess; initialGuess[u(1)->ID()] = problem->u1_exact(); initialGuess[u(2)->ID()] = problem->u2_exact(); initialGuess[sigma(1,1)->ID()] = problem->sigma1_exact()->x(); initialGuess[sigma(1,2)->ID()] = problem->sigma1_exact()->y(); initialGuess[sigma(2,1)->ID()] = problem->sigma2_exact()->x(); initialGuess[sigma(2,2)->ID()] = problem->sigma2_exact()->y(); // initialGuess[p()->ID()] = problem->p_exact(); initialGuess[uhat(1)->ID()] = problem->u1_exact(); initialGuess[uhat(2)->ID()] = problem->u2_exact(); // initialGuess[tmhat(1)->ID()] = // (problem->u1_exact()*problem->u1_exact()-problem->sigma1_exact()->x()+problem->p_exact())*n_x->x() // + (problem->u1_exact()*problem->u2_exact()-problem->sigma1_exact()->y())*n_x->y(); // initialGuess[tmhat(2)->ID()] = // (problem->u1_exact()*problem->u2_exact()-problem->sigma2_exact()->x())*n_x->x() // + (problem->u2_exact()*problem->u2_exact()-problem->sigma2_exact()->y()+problem->p_exact())*n_x->y(); _solutionBackground->projectOntoMesh(initialGuess); } else { // // BFPTR version should be deprecated _mesh = MeshFactory::loadFromHDF5(_bf, savedSolutionAndMeshPrefix+".mesh"); _solutionBackground = Solution::solution(_bf, _mesh, bc); _solutionBackground->loadFromHDF5(savedSolutionAndMeshPrefix+".soln"); _solutionUpdate = Solution::solution(_bf, _mesh, bc); // _solutionUpdate->loadFromHDF5(savedSolutionAndMeshPrefix+"_update.soln"); } // _solutionUpdate->setFilter(problem->pc()); // _solutionBackground->setFilter(problem->pc()); FunctionPtr u1_prev = Function::solution(u1, _solutionBackground); FunctionPtr u2_prev = Function::solution(u2, _solutionBackground); FunctionPtr u_prev = Function::vectorize(u1_prev, u2_prev); if (spaceDim == 2) { // stress equation _bf->addTerm((1.0 / _mu) * sigma11, tau1->x()); _bf->addTerm((1.0 / _mu) * sigma12, tau1->y()); _bf->addTerm((1.0 / _mu) * sigma21, tau2->x()); _bf->addTerm((1.0 / _mu) * sigma22, tau2->y()); _bf->addTerm(u1, tau1->div()); _bf->addTerm(u2, tau2->div()); _bf->addTerm(-u1hat, tau1 * n_x); _bf->addTerm(-u2hat, tau2 * n_x); // momentum equation if (!steady) { _bf->addTerm(-u1, v1->dt()); _bf->addTerm(-u2, v2->dt()); } _bf->addTerm(-u1_prev*u1, v1->dx()); _bf->addTerm(-u1_prev*u1, v1->dx()); _bf->addTerm(-u2_prev*u1, v1->dy()); _bf->addTerm(-u1_prev*u2, v1->dy()); _bf->addTerm(-u2_prev*u1, v2->dx()); _bf->addTerm(-u1_prev*u2, v2->dx()); _bf->addTerm(-u2_prev*u2, v2->dy()); _bf->addTerm(-u2_prev*u2, v2->dy()); _bf->addTerm(sigma11, v1->dx()); _bf->addTerm(sigma12, v1->dy()); _bf->addTerm(sigma21, v2->dx()); _bf->addTerm(sigma22, v2->dy()); _bf->addTerm(-p, v1->dx()); _bf->addTerm(-p, v2->dy()); _bf->addTerm(tm1hat, v1); _bf->addTerm(tm2hat, v2); // _bf->addTerm(2*u1_prev*u1hat*n_x->x(), v1); // _bf->addTerm((u2_prev*u1hat+u1_prev*u2hat)*n_x->y(), v1); // _bf->addTerm((u2_prev*u1hat+u1_prev*u2hat)*n_x->x(), v2); // _bf->addTerm(2*u2_prev*u2hat*n_x->y(), 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()); _bf->addTerm(u1hat*n_x->x(), q); _bf->addTerm(u2hat*n_x->y(), q); } // Add residual to RHS _rhs = RHS::rhs(); // stress equation _rhs->addTerm( -u1_prev * tau1->div() ); _rhs->addTerm( -u2_prev * tau2->div() ); // momentum equation if (!steady) { _rhs->addTerm( u1_prev * v1->dt()); _rhs->addTerm( u2_prev * v2->dt()); } _rhs->addTerm( u1_prev * u1_prev*v1->dx() ); _rhs->addTerm( u1_prev * u2_prev*v1->dy() ); _rhs->addTerm( u2_prev * u1_prev*v2->dx() ); _rhs->addTerm( u2_prev * u2_prev*v2->dy() ); // _rhs->addTerm( -u1_prev*u1_prev*n_x->x() * v1 ); // _rhs->addTerm( -u2_prev*u1_prev*n_x->y() * v1 ); // _rhs->addTerm( -u2_prev*u1_prev*n_x->x() * v2 ); // _rhs->addTerm( -u2_prev*u2_prev*n_x->y() * v2 ); // continuity equation _rhs->addTerm( u1_prev*q->dx()); _rhs->addTerm( u2_prev*q->dy()); _ips["Graph"] = _bf->graphNorm(); _ips["CoupledRobust"] = Teuchos::rcp(new IP); // _ips["CoupledRobust"]->addTerm(_beta*v->grad()); _ips["CoupledRobust"]->addTerm(u_prev*v1->grad()); _ips["CoupledRobust"]->addTerm(u_prev*v2->grad()); _ips["CoupledRobust"]->addTerm(u1_prev*v1->dx() + u2_prev*v2->dx()); _ips["CoupledRobust"]->addTerm(u1_prev*v1->dy() + u2_prev*v2->dy()); // _ips["CoupledRobust"]->addTerm(Function::min(one/Function::h(),Function::constant(1./sqrt(_mu)))*tau); _ips["CoupledRobust"]->addTerm(Function::min(one/Function::h(),Function::constant(1./sqrt(_mu)))*tau1); _ips["CoupledRobust"]->addTerm(Function::min(one/Function::h(),Function::constant(1./sqrt(_mu)))*tau2); // _ips["CoupledRobust"]->addTerm(sqrt(_mu)*v->grad()); _ips["CoupledRobust"]->addTerm(sqrt(_mu)*v1->grad()); _ips["CoupledRobust"]->addTerm(sqrt(_mu)*v2->grad()); // _ips["CoupledRobust"]->addTerm(Function::min(sqrt(_mu)*one/Function::h(),one)*v); _ips["CoupledRobust"]->addTerm(Function::min(sqrt(_mu)*one/Function::h(),one)*v1); _ips["CoupledRobust"]->addTerm(Function::min(sqrt(_mu)*one/Function::h(),one)*v2); // _ips["CoupledRobust"]->addTerm(tau->div() - v->dt() - beta*v->grad()); if (!steady) { _ips["CoupledRobust"]->addTerm(tau1->div() -v1->dt() - u_prev*v1->grad() - u1_prev*v1->dx() - u2_prev*v2->dx()); _ips["CoupledRobust"]->addTerm(tau2->div() -v2->dt() - u_prev*v2->grad() - u1_prev*v1->dy() - u2_prev*v2->dy()); } else { _ips["CoupledRobust"]->addTerm(tau1->div() - u_prev*v1->grad() - u1_prev*v1->dx() - u2_prev*v2->dx()); _ips["CoupledRobust"]->addTerm(tau2->div() - u_prev*v2->grad() - u1_prev*v1->dy() - u2_prev*v2->dy()); } // _ips["CoupledRobust"]->addTerm(v1->dx() + v2->dy()); _ips["CoupledRobust"]->addTerm(q->grad()); _ips["CoupledRobust"]->addTerm(q); _ips["NSDecoupledH1"] = Teuchos::rcp(new IP); // _ips["NSDecoupledH1"]->addTerm(one/Function::h()*tau); _ips["NSDecoupledH1"]->addTerm(one/Function::h()*tau1); _ips["NSDecoupledH1"]->addTerm(one/Function::h()*tau2); // _ips["NSDecoupledH1"]->addTerm(v->grad()); _ips["NSDecoupledH1"]->addTerm(v1->grad()); _ips["NSDecoupledH1"]->addTerm(v2->grad()); // _ips["NSDecoupledH1"]->addTerm(_beta*v->grad()+v->dt()); if (!steady) { _ips["NSDecoupledH1"]->addTerm(v1->dt() + u_prev*v1->grad() + u1_prev*v1->dx() + u2_prev*v2->dx()); _ips["NSDecoupledH1"]->addTerm(v2->dt() + u_prev*v2->grad() + u1_prev*v1->dy() + u2_prev*v2->dy()); } else { _ips["NSDecoupledH1"]->addTerm(u_prev*v1->grad() + u1_prev*v1->dx() + u2_prev*v2->dx()); _ips["NSDecoupledH1"]->addTerm(u_prev*v2->grad() + u1_prev*v1->dy() + u2_prev*v2->dy()); } // _ips["NSDecoupledH1"]->addTerm(tau->div()); _ips["NSDecoupledH1"]->addTerm(tau1->div()); _ips["NSDecoupledH1"]->addTerm(tau2->div()); // _ips["NSDecoupledH1"]->addTerm(v); _ips["NSDecoupledH1"]->addTerm(v1); _ips["NSDecoupledH1"]->addTerm(v2); // _ips["CoupledRobust"]->addTerm(v1->dx() + v2->dy()); _ips["NSDecoupledH1"]->addTerm(q->grad()); _ips["NSDecoupledH1"]->addTerm(q); IPPtr ip = _ips.at(norm); if (problem->forcingFunction != Teuchos::null) { _rhs->addTerm(problem->forcingFunction->x() * v1); _rhs->addTerm(problem->forcingFunction->y() * v2); } _solutionUpdate->setRHS(_rhs); _solutionUpdate->setIP(ip); // impose zero mean constraint // if (problem->imposeZeroMeanPressure()) // _solutionUpdate->bc()->shouldImposeZeroMeanConstraint(p->ID()); // _solutionUpdate->bc()->singlePointBC(p->ID()); _mesh->registerSolution(_solutionBackground); _mesh->registerSolution(_solutionUpdate); LinearTermPtr residual = _rhs->linearTerm() - _bf->testFunctional(_solutionUpdate, false); // false: don't exclude boundary terms // double energyThreshold = 0.2; double energyThreshold = 0; _refinementStrategy = Teuchos::rcp( new RefinementStrategy( _mesh, residual, ip, energyThreshold ) ); }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); #endif { // 1D tests CellTopoPtr line_2 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Line<2> >() ) ); // let's draw a line vector<double> v0 = makeVertex(0); vector<double> v1 = makeVertex(1); vector<double> v2 = makeVertex(2); vector< vector<double> > vertices; vertices.push_back(v0); vertices.push_back(v1); vertices.push_back(v2); vector<unsigned> line1VertexList; vector<unsigned> line2VertexList; line1VertexList.push_back(0); line1VertexList.push_back(1); line2VertexList.push_back(1); line2VertexList.push_back(2); vector< vector<unsigned> > elementVertices; elementVertices.push_back(line1VertexList); elementVertices.push_back(line2VertexList); vector< CellTopoPtr > cellTopos; cellTopos.push_back(line_2); cellTopos.push_back(line_2); MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); MeshTopologyPtr meshTopology = Teuchos::rcp( new MeshTopology(meshGeometry) ); FunctionPtr x = Function::xn(1); FunctionPtr function = x; FunctionPtr fbdr = Function::restrictToCellBoundary(function); vector<FunctionPtr> functions; functions.push_back(function); functions.push_back(function); vector<string> functionNames; functionNames.push_back("function1"); functionNames.push_back("function2"); { XDMFExporter exporter(meshTopology, "function1", false); exporter.exportFunction(function, "function1"); } { XDMFExporter exporter(meshTopology, "boundary1", false); exporter.exportFunction(fbdr, "boundary1"); } { XDMFExporter exporter(meshTopology, "functions1", false); exporter.exportFunction(functions, functionNames); } } { // 2D tests CellTopoPtr quad_4 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >() ) ); CellTopoPtr tri_3 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Triangle<3> >() ) ); // let's draw a little house vector<double> v0 = makeVertex(-1,0); vector<double> v1 = makeVertex(1,0); vector<double> v2 = makeVertex(1,2); vector<double> v3 = makeVertex(-1,2); vector<double> v4 = makeVertex(0.0,3); vector< vector<double> > vertices; vertices.push_back(v0); vertices.push_back(v1); vertices.push_back(v2); vertices.push_back(v3); vertices.push_back(v4); vector<unsigned> quadVertexList; quadVertexList.push_back(0); quadVertexList.push_back(1); quadVertexList.push_back(2); quadVertexList.push_back(3); vector<unsigned> triVertexList; triVertexList.push_back(3); triVertexList.push_back(2); triVertexList.push_back(4); vector< vector<unsigned> > elementVertices; elementVertices.push_back(quadVertexList); elementVertices.push_back(triVertexList); vector< CellTopoPtr > cellTopos; cellTopos.push_back(quad_4); cellTopos.push_back(tri_3); MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); MeshTopologyPtr meshTopology = Teuchos::rcp( new MeshTopology(meshGeometry) ); FunctionPtr x2 = Function::xn(2); FunctionPtr y2 = Function::yn(2); FunctionPtr function = x2 + y2; FunctionPtr vect = Function::vectorize(x2, y2); FunctionPtr fbdr = Function::restrictToCellBoundary(function); vector<FunctionPtr> functions; functions.push_back(function); functions.push_back(vect); vector<string> functionNames; functionNames.push_back("function"); functionNames.push_back("vect"); vector<FunctionPtr> bdrfunctions; bdrfunctions.push_back(fbdr); bdrfunctions.push_back(fbdr); vector<string> bdrfunctionNames; bdrfunctionNames.push_back("bdr1"); bdrfunctionNames.push_back("bdr2"); map<int, int> cellIDToNum1DPts; cellIDToNum1DPts[1] = 4; { XDMFExporter exporter(meshTopology, "Grid2D", false); // exporter.exportFunction(function, "function2", 0, 10); // exporter.exportFunction(vect, "vect2", 1, 10, cellIDToNum1DPts); // exporter.exportFunction(fbdr, "boundary2", 0); exporter.exportFunction(functions, functionNames, 1, 10); } { XDMFExporter exporter(meshTopology, "BdrGrid2D", false); // exporter.exportFunction(function, "function2", 0, 10); // exporter.exportFunction(vect, "vect2", 1, 10, cellIDToNum1DPts); // exporter.exportFunction(fbdr, "boundary2", 0); exporter.exportFunction(bdrfunctions, bdrfunctionNames, 1, 10); } //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactory varFactory; VarPtr tau = varFactory.testVar("tau", HDIV); VarPtr v = varFactory.testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory.traceVar("uhat"); VarPtr fhat = varFactory.fluxVar("fhat"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma = varFactory.fieldVar("sigma", VECTOR_L2); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // tau terms: bf->addTerm(sigma, tau); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma, v->grad() ); bf->addTerm( fhat, v); //////////////////// BUILD MESH /////////////////////// int H1Order = 4, pToAdd = 2; Teuchos::RCP<Mesh> mesh = Teuchos::rcp( new Mesh (meshTopology, bf, H1Order, pToAdd) ); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = bf->graphNorm(); //////////////////// SPECIFY RHS /////////////////////// RHSPtr rhs = RHS::rhs(); // Teuchos::RCP<RHS> rhs = Teuchos::rcp( new RHS ); FunctionPtr one = Function::constant(1.0); rhs->addTerm( one * v ); //////////////////// CREATE BCs /////////////////////// // Teuchos::RCP<BC> bc = Teuchos::rcp( new BCEasy ); BCPtr bc = BC::bc(); FunctionPtr zero = Function::zero(); SpatialFilterPtr entireBoundary = Teuchos::rcp( new EntireBoundary ); bc->addDirichlet(uhat, entireBoundary, zero); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); solution->solve(false); RefinementStrategy refinementStrategy( solution, 0.2); // Output solution FunctionPtr uSoln = Function::solution(u, solution); FunctionPtr sigmaSoln = Function::solution(sigma, solution); FunctionPtr uhatSoln = Function::solution(uhat, solution); FunctionPtr fhatSoln = Function::solution(fhat, solution); { XDMFExporter exporter(meshTopology, "Poisson", false); exporter.exportFunction(uSoln, "u", 0, 4); exporter.exportFunction(uSoln, "u", 1, 5); exporter.exportFunction(uhatSoln, "uhat", 0, 4); exporter.exportFunction(uhatSoln, "uhat", 1, 5); // exporter.exportFunction(fhatSoln, "fhat", 0, 4); // exporter.exportFunction(fhatSoln, "fhat", 1, 5); } { XDMFExporter exporter(meshTopology, "PoissonSolution", false); exporter.exportSolution(solution, mesh, varFactory, 0, 2, cellIDToSubdivision(mesh, 10)); refinementStrategy.refine(true); solution->solve(false); exporter.exportSolution(solution, mesh, varFactory, 1, 2, cellIDToSubdivision(mesh, 10)); } // exporter.exportFunction(sigmaSoln, "Poisson-s", "sigma", 0, 5); // exporter.exportFunction(uhatSoln, "Poisson-uhat", "uhat", 1, 6); } { // 3D tests CellTopoPtr hex = Teuchos::rcp(new shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<8> >() )); // let's draw a little box vector<double> v0 = makeVertex(0,0,0); vector<double> v1 = makeVertex(1,0,0); vector<double> v2 = makeVertex(1,1,0); vector<double> v3 = makeVertex(0,1,0); vector<double> v4 = makeVertex(0,0,1); vector<double> v5 = makeVertex(1,0,1); vector<double> v6 = makeVertex(1,1,1); vector<double> v7 = makeVertex(0,1,1); vector< vector<double> > vertices; vertices.push_back(v0); vertices.push_back(v1); vertices.push_back(v2); vertices.push_back(v3); vertices.push_back(v4); vertices.push_back(v5); vertices.push_back(v6); vertices.push_back(v7); vector<unsigned> hexVertexList; hexVertexList.push_back(0); hexVertexList.push_back(1); hexVertexList.push_back(2); hexVertexList.push_back(3); hexVertexList.push_back(4); hexVertexList.push_back(5); hexVertexList.push_back(6); hexVertexList.push_back(7); // vector<unsigned> triVertexList; // triVertexList.push_back(2); // triVertexList.push_back(3); // triVertexList.push_back(4); vector< vector<unsigned> > elementVertices; elementVertices.push_back(hexVertexList); // elementVertices.push_back(triVertexList); vector< CellTopoPtr > cellTopos; cellTopos.push_back(hex); // cellTopos.push_back(tri_3); MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); MeshTopologyPtr meshTopology = Teuchos::rcp( new MeshTopology(meshGeometry) ); FunctionPtr x = Function::xn(1); FunctionPtr y = Function::yn(1); FunctionPtr z = Function::zn(1); FunctionPtr function = x + y + z; FunctionPtr fbdr = Function::restrictToCellBoundary(function); FunctionPtr vect = Function::vectorize(x, y, z); vector<FunctionPtr> functions; functions.push_back(function); functions.push_back(vect); vector<string> functionNames; functionNames.push_back("function"); functionNames.push_back("vect"); { XDMFExporter exporter(meshTopology, "function3", false); exporter.exportFunction(function, "function3"); } { XDMFExporter exporter(meshTopology, "boundary3", false); exporter.exportFunction(fbdr, "boundary3"); } { XDMFExporter exporter(meshTopology, "vect3", false); exporter.exportFunction(vect, "vect3"); } { XDMFExporter exporter(meshTopology, "functions3", false); exporter.exportFunction(functions, functionNames); } } }
bool LobattoBasisTests::testSimpleStiffnessMatrix() { bool success = true; int rank = Teuchos::GlobalMPISession::getRank(); VarFactory varFactory; VarPtr u = varFactory.fieldVar("u"); VarPtr un = varFactory.fluxVar("un_hat"); VarPtr v = varFactory.testVar("v", HGRAD); BFPtr bf = Teuchos::rcp( new BF(varFactory) ); vector<double> beta; beta.push_back(1); beta.push_back(1); bf->addTerm(beta * u, v->grad()); bf->addTerm(un, v); DofOrderingPtr trialSpace = Teuchos::rcp( new DofOrdering ); DofOrderingPtr testSpace = Teuchos::rcp( new DofOrdering ); const int numSides = 4; const int spaceDim = 2; int fieldOrder = 3; int testOrder = fieldOrder+2; BasisPtr fieldBasis = Camellia::intrepidQuadHGRAD(fieldOrder); BasisPtr fluxBasis = Camellia::intrepidLineHGRAD(fieldOrder); trialSpace->addEntry(u->ID(), fieldBasis, fieldBasis->rangeRank()); for (int i=0; i<numSides; i++) { trialSpace->addEntry(un->ID(), fluxBasis, fluxBasis->rangeRank(), i); } BasisPtr testBasis = Camellia::lobattoQuadHGRAD(testOrder+1,false); // +1 because it lives in HGRAD testSpace->addEntry(v->ID(), testBasis, testBasis->rangeRank()); int numTrialDofs = trialSpace->totalDofs(); int numTestDofs = testSpace->totalDofs(); int numCells = 1; FieldContainer<double> cellNodes(numCells,numSides,spaceDim); cellNodes(0,0,0) = 0; cellNodes(0,0,1) = 0; cellNodes(0,1,0) = 1; cellNodes(0,1,1) = 0; cellNodes(0,2,0) = 1; cellNodes(0,2,1) = 1; cellNodes(0,3,0) = 0; cellNodes(0,3,1) = 1; FieldContainer<double> stiffness(numCells,numTestDofs,numTrialDofs); FieldContainer<double> cellSideParities(numCells,numSides); cellSideParities.initialize(1.0); Teuchos::RCP<shards::CellTopology> quad_4 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >() ) ); Teuchos::RCP<ElementType> elemType = Teuchos::rcp( new ElementType(trialSpace, testSpace, quad_4)); BasisCachePtr basisCache = Teuchos::rcp( new BasisCache(elemType) ); vector<GlobalIndexType> cellIDs; cellIDs.push_back(0); basisCache->setPhysicalCellNodes(cellNodes, cellIDs, true); bf->stiffnessMatrix(stiffness, elemType, cellSideParities, basisCache); // TODO: finish this test // cout << stiffness; if (rank==0) cout << "Warning: testSimpleStiffnessMatrix() unfinished.\n"; return success; }
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 rank = Teuchos::GlobalMPISession::getRank(); int numProcs = Teuchos::GlobalMPISession::getNProc(); int nCells = args.Input<int>("--nCells", "num cells",2); int numRefs = args.Input<int>("--numRefs","num adaptive refinements",0); int numPreRefs = args.Input<int>("--numPreRefs","num preemptive adaptive refinements",0); int order = args.Input<int>("--order","order of approximation",2); double eps = args.Input<double>("--epsilon","diffusion parameter",1e-2); double energyThreshold = args.Input<double>("-energyThreshold","energy thresh for adaptivity", .5); double rampHeight = args.Input<double>("--rampHeight","ramp height at x = 2", 0.0); bool useAnisotropy = args.Input<bool>("--useAnisotropy","aniso flag ", false); FunctionPtr zero = Function::constant(0.0); FunctionPtr one = Function::constant(1.0); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); vector<double> e1,e2; e1.push_back(1.0); e1.push_back(0.0); e2.push_back(0.0); e2.push_back(1.0); //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactory varFactory; VarPtr tau = varFactory.testVar("\\tau", HDIV); VarPtr v = varFactory.testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory.traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_n = varFactory.fluxVar("\\widehat{\\beta \\cdot n u - \\sigma_{n}}"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma1 = varFactory.fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory.fieldVar("\\sigma_2"); vector<double> beta; beta.push_back(1.0); beta.push_back(0.0); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr confusionBF = Teuchos::rcp( new BF(varFactory) ); // tau terms: confusionBF->addTerm(sigma1 / eps, tau->x()); confusionBF->addTerm(sigma2 / eps, tau->y()); confusionBF->addTerm(u, tau->div()); confusionBF->addTerm(uhat, -tau->dot_normal()); // v terms: confusionBF->addTerm( sigma1, v->dx() ); confusionBF->addTerm( sigma2, v->dy() ); confusionBF->addTerm( -u, beta * v->grad() ); confusionBF->addTerm( beta_n_u_minus_sigma_n, v); // first order term with magnitude alpha double alpha = 0.0; confusionBF->addTerm(alpha * u, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// // robust test norm IPPtr robIP = Teuchos::rcp(new IP); FunctionPtr C_h = Teuchos::rcp( new EpsilonScaling(eps) ); FunctionPtr invH = Teuchos::rcp(new InvHScaling); FunctionPtr invSqrtH = Teuchos::rcp(new InvSqrtHScaling); FunctionPtr sqrtH = Teuchos::rcp(new SqrtHScaling); robIP->addTerm(v*alpha); robIP->addTerm(invSqrtH*v); // robIP->addTerm(v); robIP->addTerm(sqrt(eps) * v->grad() ); robIP->addTerm(beta * v->grad() ); robIP->addTerm(tau->div() ); robIP->addTerm(C_h/sqrt(eps) * tau ); LinearTermPtr vVecLT = Teuchos::rcp(new LinearTerm); LinearTermPtr tauVecLT = Teuchos::rcp(new LinearTerm); vVecLT->addTerm(sqrt(eps)*v->grad()); tauVecLT->addTerm(C_h/sqrt(eps)*tau); LinearTermPtr restLT = Teuchos::rcp(new LinearTerm); restLT->addTerm(alpha*v); restLT->addTerm(invSqrtH*v); restLT = restLT + beta * v->grad(); restLT = restLT + tau->div(); //////////////////// SPECIFY RHS /////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr f = zero; // f = one; rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////// CREATE BCs /////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); // SpatialFilterPtr inflowBoundary = Teuchos::rcp( new InflowSquareBoundary ); // SpatialFilterPtr outflowBoundary = Teuchos::rcp( new OutflowSquareBoundary); // bc->addDirichlet(beta_n_u_minus_sigma_n, inflowBoundary, zero); // bc->addDirichlet(uhat, outflowBoundary, zero); SpatialFilterPtr rampInflow = Teuchos::rcp(new LeftInflow); SpatialFilterPtr rampBoundary = MeshUtilities::rampBoundary(rampHeight); SpatialFilterPtr freeStream = Teuchos::rcp(new FreeStreamBoundary); SpatialFilterPtr outflowBoundary = Teuchos::rcp(new OutflowBoundary); bc->addDirichlet(uhat, rampBoundary, one); // bc->addDirichlet(uhat, outflowBoundary, one); bc->addDirichlet(beta_n_u_minus_sigma_n, rampInflow, zero); bc->addDirichlet(beta_n_u_minus_sigma_n, freeStream, zero); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int H1Order = order+1; int pToAdd = 2; // create a pointer to a new mesh: // Teuchos::RCP<Mesh> mesh = MeshUtilities::buildUnitQuadMesh(nCells,confusionBF, H1Order, H1Order+pToAdd); Teuchos::RCP<Mesh> mesh = MeshUtilities::buildRampMesh(rampHeight,confusionBF, H1Order, H1Order+pToAdd); mesh->setPartitionPolicy(Teuchos::rcp(new ZoltanMeshPartitionPolicy("HSFC"))); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution; solution = Teuchos::rcp( new Solution(mesh, bc, rhs, robIP) ); // solution->solve(false); solution->condensedSolve(); LinearTermPtr residual = rhs->linearTermCopy(); residual->addTerm(-confusionBF->testFunctional(solution)); RieszRepPtr rieszResidual = Teuchos::rcp(new RieszRep(mesh, robIP, residual)); rieszResidual->computeRieszRep(); FunctionPtr e_v = Teuchos::rcp(new RepFunction(v,rieszResidual)); FunctionPtr e_tau = Teuchos::rcp(new RepFunction(tau,rieszResidual)); map<int,FunctionPtr> errRepMap; errRepMap[v->ID()] = e_v; errRepMap[tau->ID()] = e_tau; FunctionPtr errTau = tauVecLT->evaluate(errRepMap,false); FunctionPtr errV = vVecLT->evaluate(errRepMap,false); FunctionPtr errRest = restLT->evaluate(errRepMap,false); FunctionPtr xErr = (errTau->x())*(errTau->x()) + (errV->dx())*(errV->dx()); FunctionPtr yErr = (errTau->y())*(errTau->y()) + (errV->dy())*(errV->dy()); FunctionPtr restErr = errRest*errRest; RefinementStrategy refinementStrategy( solution, energyThreshold ); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // PRE REFINEMENTS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if (rank==0) { cout << "Number of pre-refinements = " << numPreRefs << endl; } for (int i =0; i<=numPreRefs; i++) { vector<ElementPtr> elems = mesh->activeElements(); vector<ElementPtr>::iterator elemIt; vector<int> wallCells; for (elemIt=elems.begin(); elemIt != elems.end(); elemIt++) { int cellID = (*elemIt)->cellID(); int numSides = mesh->getElement(cellID)->numSides(); FieldContainer<double> vertices(numSides,2); //for quads mesh->verticesForCell(vertices, cellID); bool cellIDset = false; for (int j = 0; j<numSides; j++) { if ((abs(vertices(j,0)-1.0)<1e-7) && (abs(vertices(j,1))<1e-7) && !cellIDset) // if at singularity, i.e. if a vertex is (1,0) { wallCells.push_back(cellID); cellIDset = true; } } } if (i<numPreRefs) { refinementStrategy.refineCells(wallCells); } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// VTKExporter exporter(solution, mesh, varFactory); for (int refIndex=0; refIndex<numRefs; refIndex++) { if (rank==0) { cout << "on ref index " << refIndex << endl; } rieszResidual->computeRieszRep(); // in preparation to get anisotropy vector<int> cellIDs; refinementStrategy.getCellsAboveErrorThreshhold(cellIDs); map<int,double> energyError = solution->energyError(); map<int,double> xErrMap = xErr->cellIntegrals(cellIDs,mesh,5,true); map<int,double> yErrMap = yErr->cellIntegrals(cellIDs,mesh,5,true); map<int,double> restErrMap = restErr->cellIntegrals(cellIDs,mesh,5,true); for (vector<ElementPtr>::iterator elemIt = mesh->activeElements().begin(); elemIt!=mesh->activeElements().end(); elemIt++) { int cellID = (*elemIt)->cellID(); double err = xErrMap[cellID]+ yErrMap[cellID] + restErrMap[cellID]; if (rank==0) cout << "err thru LT = " << sqrt(err) << ", while energy err = " << energyError[cellID] << endl; } map<int,double> ratio,xErr,yErr; vector<ElementPtr> elems = mesh->activeElements(); for (vector<ElementPtr>::iterator elemIt = elems.begin(); elemIt!=elems.end(); elemIt++) { int cellID = (*elemIt)->cellID(); ratio[cellID] = 0.0; xErr[cellID] = 0.0; yErr[cellID] = 0.0; if (std::find(cellIDs.begin(),cellIDs.end(),cellID)!=cellIDs.end()) // if this cell is above energy thresh { ratio[cellID] = yErrMap[cellID]/xErrMap[cellID]; xErr[cellID] = xErrMap[cellID]; yErr[cellID] = yErrMap[cellID]; } } FunctionPtr ratioFxn = Teuchos::rcp(new EnergyErrorFunction(ratio)); FunctionPtr xErrFxn = Teuchos::rcp(new EnergyErrorFunction(xErr)); FunctionPtr yErrFxn = Teuchos::rcp(new EnergyErrorFunction(yErr)); std::ostringstream oss; oss << refIndex; exporter.exportFunction(ratioFxn, string("ratio")+oss.str()); exporter.exportFunction(xErrFxn, string("xErr")+oss.str()); exporter.exportFunction(yErrFxn, string("yErr")+oss.str()); if (useAnisotropy) { refinementStrategy.refine(rank==0,xErrMap,yErrMap); //anisotropic refinements } else { refinementStrategy.refine(rank==0); // no anisotropy } solution->condensedSolve(); } // final solve on final mesh solution->condensedSolve(); //////////////////// print to file /////////////////////// FunctionPtr orderFxn = Teuchos::rcp(new MeshPolyOrderFunction(mesh)); std::ostringstream oss; oss << nCells; if (rank==0) { exporter.exportSolution(string("robustIP")+oss.str()); exporter.exportFunction(orderFxn, "meshOrder"); cout << endl; } return 0; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); int rank=mpiSession.getRank(); int numProcs=mpiSession.getNProc(); #else int rank = 0; int numProcs = 1; #endif int polyOrder = 3; int pToAdd = 2; // for tests // define our manufactured solution or problem bilinear form: double epsilon = 1e-2; bool useTriangles = false; FieldContainer<double> quadPoints(4,2); quadPoints(0,0) = 0.0; // x1 quadPoints(0,1) = 0.0; // y1 quadPoints(1,0) = 1.0; quadPoints(1,1) = 0.0; quadPoints(2,0) = 1.0; quadPoints(2,1) = 1.0; quadPoints(3,0) = 0.0; quadPoints(3,1) = 1.0; int H1Order = polyOrder + 1; int horizontalCells = 1, verticalCells = 1; double energyThreshold = 0.2; // for mesh refinements double nonlinearStepSize = 0.5; double nonlinearRelativeEnergyTolerance = 0.015; // used to determine convergence of the nonlinear solution //////////////////////////////////////////////////////////////////// // SET UP PROBLEM //////////////////////////////////////////////////////////////////// Teuchos::RCP<BurgersBilinearForm> oldBurgersBF = Teuchos::rcp(new BurgersBilinearForm(epsilon)); // new-style bilinear form definition VarFactory varFactory; VarPtr uhat = varFactory.traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_hat = varFactory.fluxVar("\\widehat{\\beta_n u - \\sigma_n}"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma1 = varFactory.fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory.fieldVar("\\sigma_2"); VarPtr tau = varFactory.testVar("\\tau",HDIV); VarPtr v = varFactory.testVar("v",HGRAD); BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = Mesh::buildQuadMesh(quadPoints, horizontalCells, verticalCells, bf, H1Order, H1Order+pToAdd, useTriangles); mesh->setPartitionPolicy(Teuchos::rcp(new ZoltanMeshPartitionPolicy("HSFC"))); Teuchos::RCP<Solution> backgroundFlow = Teuchos::rcp(new Solution(mesh, Teuchos::rcp((BC*)NULL) , Teuchos::rcp((RHS*)NULL), Teuchos::rcp((DPGInnerProduct*)NULL))); // create null solution oldBurgersBF->setBackgroundFlow(backgroundFlow); // tau parts: // 1/eps (sigma, tau)_K + (u, div tau)_K - (u_hat, tau_n)_dK bf->addTerm(sigma1 / epsilon, tau->x()); bf->addTerm(sigma2 / epsilon, tau->y()); bf->addTerm(u, tau->div()); bf->addTerm( - uhat, tau->dot_normal() ); vector<double> e1(2); // (1,0) e1[0] = 1; vector<double> e2(2); // (0,1) e2[1] = 1; FunctionPtr u_prev = Teuchos::rcp( new PreviousSolutionFunction(backgroundFlow, u) ); FunctionPtr beta = e1 * u_prev + Teuchos::rcp( new ConstantVectorFunction( e2 ) ); // v: // (sigma, grad v)_K - (sigma_hat_n, v)_dK - (u, beta dot grad v) + (u_hat * n dot beta, v)_dK bf->addTerm( sigma1, v->dx() ); bf->addTerm( sigma2, v->dy() ); bf->addTerm( -u, beta * v->grad()); bf->addTerm( beta_n_u_minus_sigma_hat, v); // ==================== SET INITIAL GUESS ========================== mesh->registerSolution(backgroundFlow); map<int, Teuchos::RCP<AbstractFunction> > functionMap; functionMap[BurgersBilinearForm::U] = Teuchos::rcp(new InitialGuess()); functionMap[BurgersBilinearForm::SIGMA_1] = Teuchos::rcp(new ZeroFunction()); functionMap[BurgersBilinearForm::SIGMA_2] = Teuchos::rcp(new ZeroFunction()); backgroundFlow->projectOntoMesh(functionMap); // ==================== END SET INITIAL GUESS ========================== // compare stiffness matrices for first linear step: int trialOrder = 1; pToAdd = 0; int testOrder = trialOrder + pToAdd; CellTopoPtr quadTopoPtr = Teuchos::rcp(new shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >() )); DofOrderingFactory dofOrderingFactory(bf); DofOrderingPtr testOrdering = dofOrderingFactory.testOrdering(testOrder, *quadTopoPtr); DofOrderingPtr trialOrdering = dofOrderingFactory.trialOrdering(trialOrder, *quadTopoPtr); int numCells = 1; // just use testOrdering for both trial and test spaces (we only use to define BasisCache) ElementTypePtr elemType = Teuchos::rcp( new ElementType(trialOrdering, testOrdering, quadTopoPtr) ); BasisCachePtr basisCache = Teuchos::rcp( new BasisCache(elemType) ); quadPoints.resize(1,quadPoints.dimension(0),quadPoints.dimension(1)); basisCache->setPhysicalCellNodes(quadPoints,vector<int>(1),true); // true: do create side cache FieldContainer<double> cellSideParities(numCells,quadTopoPtr->getSideCount()); cellSideParities.initialize(1.0); // not worried here about neighbors actually having opposite parity -- just want the two BF implementations to agree... FieldContainer<double> expectedValues(numCells, testOrdering->totalDofs(), trialOrdering->totalDofs() ); FieldContainer<double> actualValues(numCells, testOrdering->totalDofs(), trialOrdering->totalDofs() ); oldBurgersBF->stiffnessMatrix(expectedValues, elemType, cellSideParities, basisCache); bf->stiffnessMatrix(actualValues, elemType, cellSideParities, basisCache); // compare beta's as well FieldContainer<double> expectedBeta = oldBurgersBF->getBeta(basisCache); Teuchos::Array<int> dim; expectedBeta.dimensions(dim); FieldContainer<double> actualBeta(dim); beta->values(actualBeta,basisCache); double tol = 1e-14; double maxDiff; if (rank == 0) { if ( ! TestSuite::fcsAgree(expectedBeta,actualBeta,tol,maxDiff) ) { cout << "Test failed: old Burgers beta differs from new; maxDiff " << maxDiff << ".\n"; cout << "Old beta: \n" << expectedBeta; cout << "New beta: \n" << actualBeta; } else { cout << "Old and new Burgers beta agree!!\n"; } if ( ! TestSuite::fcsAgree(expectedValues,actualValues,tol,maxDiff) ) { cout << "Test failed: old Burgers stiffness differs from new; maxDiff " << maxDiff << ".\n"; cout << "Old: \n" << expectedValues; cout << "New: \n" << actualValues; cout << "TrialDofOrdering: \n" << *trialOrdering; cout << "TestDofOrdering:\n" << *testOrdering; } else { cout << "Old and new Burgers stiffness agree!!\n"; } } // define our inner product: // Teuchos::RCP<BurgersInnerProduct> ip = Teuchos::rcp( new BurgersInnerProduct( bf, mesh ) ); // function to scale the squared guy by epsilon/h FunctionPtr epsilonOverHScaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); IPPtr ip = Teuchos::rcp( new IP ); ip->addTerm(tau); ip->addTerm(tau->div()); ip->addTerm( epsilonOverHScaling * v ); ip->addTerm( sqrt(sqrt(epsilon)) * v->grad() ); ip->addTerm( beta * v->grad() ); // use old IP instead, for now... Teuchos::RCP<BurgersInnerProduct> oldIP = Teuchos::rcp( new BurgersInnerProduct( oldBurgersBF, mesh ) ); expectedValues.resize(numCells, testOrdering->totalDofs(), testOrdering->totalDofs() ); actualValues.resize (numCells, testOrdering->totalDofs(), testOrdering->totalDofs() ); BasisCachePtr ipBasisCache = Teuchos::rcp( new BasisCache(elemType, true) ); // true: test vs. test ipBasisCache->setPhysicalCellNodes(quadPoints,vector<int>(1),false); // false: don't create side cache oldIP->computeInnerProductMatrix(expectedValues,testOrdering,ipBasisCache); ip->computeInnerProductMatrix(actualValues,testOrdering,ipBasisCache); tol = 1e-14; maxDiff = 0.0; if (rank==0) { if ( ! TestSuite::fcsAgree(expectedValues,actualValues,tol,maxDiff) ) { cout << "Test failed: old inner product differs from new IP; maxDiff " << maxDiff << ".\n"; cout << "Old: \n" << expectedValues; cout << "New IP: \n" << actualValues; cout << "testOrdering: \n" << *testOrdering; } else { cout << "Old inner product and new IP agree!!\n"; } } Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); // the RHS as implemented by BurgersProblem divides the first component of beta by 2.0 // so we follow that. I've not done the math; just imitating the code... Teuchos::RCP<RHSEasy> otherRHS = Teuchos::rcp( new RHSEasy ); vector<double> e1_div2 = e1; e1_div2[0] /= 2.0; FunctionPtr rhsBeta = (e1_div2 * beta * e1 + Teuchos::rcp( new ConstantVectorFunction( e2 ) )) * u_prev; otherRHS->addTerm( rhsBeta * v->grad() - u_prev * tau->div() ); Teuchos::RCP<BurgersProblem> problem = Teuchos::rcp( new BurgersProblem(oldBurgersBF) ); expectedValues.resize(numCells, testOrdering->totalDofs() ); actualValues.resize (numCells, testOrdering->totalDofs() ); problem->integrateAgainstStandardBasis(expectedValues,testOrdering,basisCache); otherRHS->integrateAgainstStandardBasis(actualValues,testOrdering,basisCache); tol = 1e-14; maxDiff = 0.0; if (rank==0) { if ( ! TestSuite::fcsAgree(expectedValues,actualValues,tol,maxDiff) ) { cout << "Test failed: old RHS differs from new (\"otherRHS\"); maxDiff " << maxDiff << ".\n"; cout << "Old: \n" << expectedValues; cout << "New: \n" << actualValues; cout << "testOrdering: \n" << *testOrdering; } else { cout << "Old and new RHS (\"otherRHS\") agree!!\n"; } } FunctionPtr u_prev_squared_div2 = 0.5 * u_prev * u_prev; rhs->addTerm( (e1 * u_prev_squared_div2 + e2 * u_prev) * v->grad() - u_prev * tau->div()); if (! functionsAgree(e2 * u_prev, Teuchos::rcp( new ConstantVectorFunction( e2 ) ) * u_prev, basisCache) ) { cout << "two like functions differ...\n"; } FunctionPtr e1_f = Teuchos::rcp( new ConstantVectorFunction( e1 ) ); FunctionPtr e2_f = Teuchos::rcp( new ConstantVectorFunction( e2 ) ); FunctionPtr one = Teuchos::rcp( new ConstantScalarFunction( 1.0 ) ); if (! functionsAgree( Teuchos::rcp( new ProductFunction(e1_f, (e1_f + e2_f)) ), // e1_f * (e1_f + e2_f) one, basisCache) ) { cout << "two like functions differ...\n"; } if (! functionsAgree(u_prev_squared_div2, (e1_div2 * beta) * u_prev, basisCache) ) { cout << "two like functions differ...\n"; } if (! functionsAgree(e1 * u_prev_squared_div2, (e1_div2 * beta * e1) * u_prev, basisCache) ) { cout << "two like functions differ...\n"; } if (! functionsAgree(e1 * u_prev_squared_div2 + e2 * u_prev, (e1_div2 * beta * e1 + Teuchos::rcp( new ConstantVectorFunction( e2 ) )) * u_prev, basisCache) ) { cout << "two like functions differ...\n"; } problem->integrateAgainstStandardBasis(expectedValues,testOrdering,basisCache); rhs->integrateAgainstStandardBasis(actualValues,testOrdering,basisCache); tol = 1e-14; maxDiff = 0.0; if (rank==0) { if ( ! TestSuite::fcsAgree(expectedValues,actualValues,tol,maxDiff) ) { cout << "Test failed: old RHS differs from new (\"rhs\"); maxDiff " << maxDiff << ".\n"; cout << "Old: \n" << expectedValues; cout << "New: \n" << actualValues; cout << "testOrdering: \n" << *testOrdering; } else { cout << "Old and new RHS (\"rhs\") agree!!\n"; } } SpatialFilterPtr outflowBoundary = Teuchos::rcp( new TopBoundary ); SpatialFilterPtr inflowBoundary = Teuchos::rcp( new NegatedSpatialFilter(outflowBoundary) ); Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp(new PenaltyConstraints); LinearTermPtr sigma_hat = beta * uhat->times_normal() - beta_n_u_minus_sigma_hat; FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); pc->addConstraint(sigma_hat==zero,outflowBoundary); FunctionPtr u0 = Teuchos::rcp( new U0 ); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); Teuchos::RCP<BCEasy> inflowBC = Teuchos::rcp( new BCEasy ); FunctionPtr u0_squared_div_2 = 0.5 * u0 * u0; inflowBC->addDirichlet(beta_n_u_minus_sigma_hat,inflowBoundary, ( e1 * u0_squared_div_2 + e2 * u0) * n ); // create a solution object Teuchos::RCP<Solution> solution = Teuchos::rcp(new Solution(mesh, inflowBC, rhs, ip)); mesh->registerSolution(solution); solution->setFilter(pc); // old penalty filter: Teuchos::RCP<LocalStiffnessMatrixFilter> penaltyBC = Teuchos::rcp(new PenaltyMethodFilter(problem)); // solution->setFilter(penaltyBC); // compare old and new filters elemType = mesh->getElement(0)->elementType(); trialOrdering = elemType->trialOrderPtr; testOrdering = elemType->testOrderPtr; // stiffness expectedValues.resize(numCells, trialOrdering->totalDofs(), trialOrdering->totalDofs() ); actualValues.resize (numCells, trialOrdering->totalDofs(), trialOrdering->totalDofs() ); expectedValues.initialize(0.0); actualValues.initialize(0.0); // load FieldContainer<double> expectedLoad(numCells, trialOrdering->totalDofs() ); FieldContainer<double> actualLoad(numCells, trialOrdering->totalDofs() ); penaltyBC->filter(expectedValues,expectedLoad,basisCache,mesh,problem); pc->filter(actualValues,actualLoad,basisCache,mesh,problem); maxDiff = 0.0; if (rank==0) { if ( ! TestSuite::fcsAgree(expectedValues,actualValues,tol,maxDiff) ) { cout << "Test failed: old penalty stiffness differs from new; maxDiff " << maxDiff << ".\n"; cout << "Old: \n" << expectedValues; cout << "New: \n" << actualValues; cout << "trialOrdering: \n" << *trialOrdering; } else { cout << "Old and new penalty stiffness agree!!\n"; } } if (rank==0) { if ( ! TestSuite::fcsAgree(expectedLoad,actualLoad,tol,maxDiff) ) { cout << "Test failed: old penalty load differs from new; maxDiff " << maxDiff << ".\n"; cout << "Old: \n" << expectedValues; cout << "New: \n" << actualValues; cout << "trialOrdering: \n" << *trialOrdering; } else { cout << "Old and new penalty load agree!!\n"; } } // define refinement strategy: Teuchos::RCP<RefinementStrategy> refinementStrategy = Teuchos::rcp(new RefinementStrategy(solution,energyThreshold)); // =================== END INITIALIZATION CODE ========================== // refine the spectral mesh, for comparability with the original Burgers' driver mesh->hRefine(vector<int>(1),RefinementPattern::regularRefinementPatternQuad()); int numRefs = 5; Teuchos::RCP<NonlinearStepSize> stepSize = Teuchos::rcp(new NonlinearStepSize(nonlinearStepSize)); Teuchos::RCP<NonlinearSolveStrategy> solveStrategy = Teuchos::rcp( new NonlinearSolveStrategy(backgroundFlow, solution, stepSize, nonlinearRelativeEnergyTolerance) ); for (int refIndex=0; refIndex<numRefs; refIndex++) { solveStrategy->solve(rank==0); refinementStrategy->refine(rank==0); // print to console on rank 0 } // one more nonlinear solve on refined mesh int numNRSteps = 5; for (int i=0; i<numNRSteps; i++) { solution->solve(false); backgroundFlow->addSolution(solution,1.0); } if (rank==0) { backgroundFlow->writeFieldsToFile(BurgersBilinearForm::U, "u_ref.m"); backgroundFlow->writeFieldsToFile(BurgersBilinearForm::SIGMA_1, "sigmax.m"); backgroundFlow->writeFieldsToFile(BurgersBilinearForm::SIGMA_2, "sigmay.m"); solution->writeFluxesToFile(BurgersBilinearForm::U_HAT, "du_hat_ref.dat"); } return 0; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); int rank=mpiSession.getRank(); int numProcs=mpiSession.getNProc(); #else int rank = 0; int numProcs = 1; #endif bool useCompliantGraphNorm = false; bool enforceOneIrregularity = true; bool writeStiffnessMatrices = false; bool writeWorstCaseGramMatrices = false; int numRefs = 10; // problem parameters: double eps = 1e-8; vector<double> beta_const; beta_const.push_back(2.0); beta_const.push_back(1.0); int k = 2, delta_k = 2; Teuchos::CommandLineProcessor cmdp(false,true); // false: don't throw exceptions; true: do return errors for unrecognized options cmdp.setOption("polyOrder",&k,"polynomial order for field variable u"); cmdp.setOption("delta_k", &delta_k, "test space polynomial order enrichment"); cmdp.setOption("numRefs",&numRefs,"number of refinements"); cmdp.setOption("eps", &eps, "epsilon"); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { #ifdef HAVE_MPI MPI_Finalize(); #endif return -1; } int H1Order = k + 1; if (rank==0) { string normChoice = useCompliantGraphNorm ? "unit-compliant graph norm" : "standard graph norm"; cout << "Using " << normChoice << "." << endl; cout << "eps = " << eps << endl; cout << "numRefs = " << numRefs << endl; cout << "p = " << k << endl; } //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactory varFactory; VarPtr tau = varFactory.testVar("\\tau", HDIV); VarPtr v = varFactory.testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory.traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_n = varFactory.fluxVar("\\widehat{\\beta \\cdot n u - \\sigma_{n}}"); VarPtr u; if (useCompliantGraphNorm) { u = varFactory.fieldVar("u",HGRAD); } else { u = varFactory.fieldVar("u"); } VarPtr sigma1 = varFactory.fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory.fieldVar("\\sigma_2"); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr confusionBF = Teuchos::rcp( new BF(varFactory) ); // tau terms: confusionBF->addTerm(sigma1 / eps, tau->x()); confusionBF->addTerm(sigma2 / eps, tau->y()); confusionBF->addTerm(u, tau->div()); confusionBF->addTerm(-uhat, tau->dot_normal()); // v terms: confusionBF->addTerm( sigma1, v->dx() ); confusionBF->addTerm( sigma2, v->dy() ); confusionBF->addTerm( beta_const * u, - v->grad() ); confusionBF->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// // mathematician's norm IPPtr mathIP = Teuchos::rcp(new IP()); mathIP->addTerm(tau); mathIP->addTerm(tau->div()); mathIP->addTerm(v); mathIP->addTerm(v->grad()); // quasi-optimal norm IPPtr qoptIP = Teuchos::rcp(new IP); if (!useCompliantGraphNorm) { qoptIP->addTerm( tau / eps + v->grad() ); qoptIP->addTerm( beta_const * v->grad() - tau->div() ); qoptIP->addTerm( v ); } else { FunctionPtr h = Teuchos::rcp( new hFunction ); // here, we're aiming at optimality in 1/h^2 |u|^2 + 1/eps^2 |sigma|^2 qoptIP->addTerm( tau + eps * v->grad() ); qoptIP->addTerm( h * beta_const * v->grad() - tau->div() ); qoptIP->addTerm(v); qoptIP->addTerm(tau); } //////////////////// SPECIFY RHS /////////////////////// RHSPtr rhs = RHS::rhs(); FunctionPtr f = Teuchos::rcp( new ConstantScalarFunction(0.0) ); rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////// CREATE BCs /////////////////////// BCPtr bc = BC::bc(); SpatialFilterPtr inflowBoundary = Teuchos::rcp( new InflowSquareBoundary ); SpatialFilterPtr outflowBoundary = Teuchos::rcp( new OutflowSquareBoundary ); FunctionPtr u0 = Teuchos::rcp( new U0 ); bc->addDirichlet(uhat, outflowBoundary, u0); bc->addDirichlet(uhat, inflowBoundary, u0); // Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp(new PenaltyConstraints); // pc->addConstraint(uhat==u0,inflowBoundary); //////////////////// BUILD MESH /////////////////////// // create a new mesh on a single-cell, unit square domain Teuchos::RCP<Mesh> mesh = MeshFactory::quadMeshMinRule(confusionBF, H1Order, delta_k); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, qoptIP) ); // solution->setFilter(pc); double energyThreshold = 0.2; // for mesh refinements bool useRieszRepBasedRefStrategy = true; if (rank==0) { if (useRieszRepBasedRefStrategy) { cout << "using RieszRep-based refinement strategy.\n"; } else { cout << "using solution-based refinement strategy.\n"; } } Teuchos::RCP<RefinementStrategy> refinementStrategy; if (!useRieszRepBasedRefStrategy) { refinementStrategy = Teuchos::rcp( new RefinementStrategy( solution, energyThreshold ) ); } else { LinearTermPtr residual = confusionBF->testFunctional(solution) - rhs->linearTerm(); refinementStrategy = Teuchos::rcp( new RefinementStrategy( mesh, residual, qoptIP, energyThreshold ) ); } refinementStrategy->setReportPerCellErrors(true); refinementStrategy->setEnforceOneIrregularity(enforceOneIrregularity); for (int refIndex=0; refIndex<numRefs; refIndex++){ if (writeStiffnessMatrices) { string stiffnessFile = fileNameForRefinement("confusion_stiffness", refIndex); solution->setWriteMatrixToFile(true, stiffnessFile); } solution->solve(); if (writeWorstCaseGramMatrices) { string gramFile = fileNameForRefinement("confusion_gram", refIndex); bool jacobiScaling = true; double condNum = MeshUtilities::computeMaxLocalConditionNumber(qoptIP, mesh, jacobiScaling, gramFile); if (rank==0) { cout << "estimated worst-case Gram matrix condition number: " << condNum << endl; cout << "putative worst-case Gram matrix written to file " << gramFile << endl; } } if (refIndex == numRefs-1) { // write out second-to-last mesh if (rank==0) GnuPlotUtil::writeComputationalMeshSkeleton("confusionMesh", mesh, true); } refinementStrategy->refine(rank==0); // print to console on rank 0 } if (writeStiffnessMatrices) { string stiffnessFile = fileNameForRefinement("confusion_stiffness", numRefs); solution->setWriteMatrixToFile(true, stiffnessFile); } if (writeWorstCaseGramMatrices) { string gramFile = fileNameForRefinement("confusion_gram", numRefs); bool jacobiScaling = true; double condNum = MeshUtilities::computeMaxLocalConditionNumber(qoptIP, mesh, jacobiScaling, gramFile); if (rank==0) { cout << "estimated worst-case Gram matrix condition number: " << condNum << endl; cout << "putative worst-case Gram matrix written to file " << gramFile << endl; } } // one more solve on the final refined mesh: solution->solve(); #ifdef HAVE_EPETRAEXT_HDF5 ostringstream dir_name; dir_name << "confusion_eps" << eps; HDF5Exporter exporter(mesh,dir_name.str()); exporter.exportSolution(solution, varFactory, 0); if (rank==0) cout << "wrote solution to " << dir_name.str() << endl; #endif return 0; }
void TransientTests::SetUp() { //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarPtr v = varFactory.testVar("v", HGRAD); // define trial variables beta_n_u_hat = varFactory.fluxVar("\\widehat{\\beta \\cdot n }"); u = varFactory.fieldVar("u"); vector<double> beta; beta.push_back(1.0); beta.push_back(0.0); //////////////////// BUILD MESH /////////////////////// bf = Teuchos::rcp( new BF(varFactory) ); // define nodes for mesh FieldContainer<double> meshBoundary(4,2); meshBoundary(0,0) = 0.0; // x1 meshBoundary(0,1) = -2.0; // y1 meshBoundary(1,0) = 4.0; meshBoundary(1,1) = -2.0; meshBoundary(2,0) = 4.0; meshBoundary(2,1) = 2.0; meshBoundary(3,0) = 0.0; meshBoundary(3,1) = 2.0; int horizontalCells = 4, verticalCells = 4; // create a pointer to a new mesh: mesh = MeshFactory::buildQuadMesh(meshBoundary, horizontalCells, verticalCells, bf, H1Order, H1Order+pToAdd); //////////////////////////////////////////////////////////////////// // INITIALIZE FLOW FUNCTIONS //////////////////////////////////////////////////////////////////// BCPtr nullBC = Teuchos::rcp((BC*)NULL); RHSPtr nullRHS = Teuchos::rcp((RHS*)NULL); IPPtr nullIP = Teuchos::rcp((IP*)NULL); prevTimeFlow = Teuchos::rcp(new Solution(mesh, nullBC, nullRHS, nullIP) ); flowResidual = Teuchos::rcp(new Solution(mesh, nullBC, nullRHS, nullIP) ); FunctionPtr u_prev_time = Teuchos::rcp( new PreviousSolutionFunction(prevTimeFlow, u) ); //////////////////// DEFINE BILINEAR FORM /////////////////////// RHSPtr rhs = RHS::rhs(); FunctionPtr invDt = Teuchos::rcp(new ScalarParamFunction(1.0/dt)); // v terms: bf->addTerm( beta * u, - v->grad() ); bf->addTerm( beta_n_u_hat, v); // transient terms bf->addTerm( u, invDt*v ); rhs->addTerm( u_prev_time * invDt * v ); //////////////////// SPECIFY RHS /////////////////////// FunctionPtr f = Teuchos::rcp( new ConstantScalarFunction(0.0) ); rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = bf->graphNorm(); //////////////////// CREATE BCs /////////////////////// BCPtr bc = BC::bc(); SpatialFilterPtr lBoundary = Teuchos::rcp( new LeftBoundary ); FunctionPtr u1 = Teuchos::rcp( new InletBC ); bc->addDirichlet(beta_n_u_hat, lBoundary, -u1); solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); // ==================== Register Solutions ========================== mesh->registerSolution(solution); mesh->registerSolution(prevTimeFlow); mesh->registerSolution(flowResidual); // ==================== SET INITIAL GUESS ========================== double u_free = 0.0; map<int, Teuchos::RCP<Function> > functionMap; functionMap[u->ID()] = Teuchos::rcp( new ConstantScalarFunction(u_free) ); // prevTimeFlow->projectOntoMesh(functionMap); }
PoissonFormulation::PoissonFormulation(int spaceDim, bool useConformingTraces, PoissonFormulationChoice formulationChoice) { _spaceDim = spaceDim; if (formulationChoice == ULTRAWEAK) { Space tauSpace = (spaceDim > 1) ? HDIV : HGRAD; Space phi_hat_space = useConformingTraces ? HGRAD : L2; Space psiSpace = (spaceDim > 1) ? VECTOR_L2 : L2; // fields VarPtr phi; VarPtr psi; // traces VarPtr phi_hat, psi_n_hat; // tests VarPtr q; VarPtr tau; VarFactoryPtr vf = VarFactory::varFactory(); phi = vf->fieldVar(S_PHI); psi = vf->fieldVar(S_PSI, psiSpace); TFunctionPtr<double> parity = TFunction<double>::sideParity(); if (spaceDim > 1) phi_hat = vf->traceVar(S_PHI_HAT, phi, phi_hat_space); else phi_hat = vf->fluxVar(S_PHI_HAT, phi * (Function::normal_1D() * parity), phi_hat_space); // for spaceDim==1, the "normal" component is in the flux-ness of phi_hat (it's a plus or minus 1) TFunctionPtr<double> n = TFunction<double>::normal(); if (spaceDim > 1) psi_n_hat = vf->fluxVar(S_PSI_N_HAT, psi * (n * parity)); else psi_n_hat = vf->fluxVar(S_PSI_N_HAT, psi * (Function::normal_1D() * parity)); q = vf->testVar(S_Q, HGRAD); tau = vf->testVar(S_TAU, tauSpace); _poissonBF = Teuchos::rcp( new BF(vf) ); if (spaceDim==1) { // for spaceDim==1, the "normal" component is in the flux-ness of phi_hat (it's a plus or minus 1) _poissonBF->addTerm(phi, tau->dx()); _poissonBF->addTerm(psi, tau); _poissonBF->addTerm(-phi_hat, tau); _poissonBF->addTerm(-psi, q->dx()); _poissonBF->addTerm(psi_n_hat, q); } else { _poissonBF->addTerm(phi, tau->div()); _poissonBF->addTerm(psi, tau); _poissonBF->addTerm(-phi_hat, tau->dot_normal()); _poissonBF->addTerm(-psi, q->grad()); _poissonBF->addTerm(psi_n_hat, q); } } else if ((formulationChoice == PRIMAL) || (formulationChoice == CONTINUOUS_GALERKIN)) { // field VarPtr phi; // flux VarPtr psi_n_hat; // tests VarPtr q; VarFactoryPtr vf = VarFactory::varFactory(); phi = vf->fieldVar(S_PHI, HGRAD); TFunctionPtr<double> parity = TFunction<double>::sideParity(); TFunctionPtr<double> n = TFunction<double>::normal(); if (formulationChoice == PRIMAL) { if (spaceDim > 1) psi_n_hat = vf->fluxVar(S_PSI_N_HAT, phi->grad() * (n * parity)); else psi_n_hat = vf->fluxVar(S_PSI_N_HAT, phi->dx() * (Function::normal_1D() * parity)); } q = vf->testVar(S_Q, HGRAD); _poissonBF = BF::bf(vf); _poissonBF->addTerm(-phi->grad(), q->grad()); if (formulationChoice == CONTINUOUS_GALERKIN) { FunctionPtr boundaryIndicator = Function::meshBoundaryCharacteristic(); _poissonBF->addTerm(phi->grad() * n, boundaryIndicator * q); } else // primal { _poissonBF->addTerm(psi_n_hat, q); } } else { TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "Unsupported PoissonFormulationChoice"); } }
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[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); Epetra_MpiComm Comm(MPI_COMM_WORLD); #else Epetra_SerialComm Comm; #endif int commRank = Teuchos::GlobalMPISession::getRank(); Comm.Barrier(); // set breakpoint here to allow debugger attachment to other MPI processes than the one you automatically attached to. Teuchos::CommandLineProcessor cmdp(false,true); // false: don't throw exceptions; true: do return errors for unrecognized options // problem parameters: double mu = 0.1; double permCoef = 1e4; int numRefs = 0; int k = 2, delta_k = 2; string norm = "Graph"; cmdp.setOption("polyOrder",&k,"polynomial order for field variable u"); cmdp.setOption("delta_k", &delta_k, "test space polynomial order enrichment"); cmdp.setOption("numRefs",&numRefs,"number of refinements"); cmdp.setOption("norm", &norm, "norm"); cmdp.setOption("mu", &mu, "mu"); cmdp.setOption("permCoef", &permCoef, "Permeability coefficient"); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { #ifdef HAVE_MPI MPI_Finalize(); #endif return -1; } FunctionPtr zero = TFunction<double>::zero(); FunctionPtr one = TFunction<double>::constant(1); FunctionPtr sin2pix = Teuchos::rcp( new Sin_ax(2*pi) ); FunctionPtr cos2pix = Teuchos::rcp( new Cos_ax(2*pi) ); FunctionPtr sin2piy = Teuchos::rcp( new Sin_ay(2*pi) ); FunctionPtr cos2piy = Teuchos::rcp( new Cos_ay(2*pi) ); FunctionPtr u1_exact = sin2pix*cos2piy; FunctionPtr u2_exact = -cos2pix*sin2piy; FunctionPtr x2 = TFunction<double>::xn(2); FunctionPtr y2 = TFunction<double>::yn(2); FunctionPtr p_exact = x2*y2 - 1./9; FunctionPtr permInv = permCoef*(sin2pix + 1.1); VarFactoryPtr vf = VarFactory::varFactory(); //fields: VarPtr sigma1 = vf->fieldVar("sigma1", VECTOR_L2); VarPtr sigma2 = vf->fieldVar("sigma2", VECTOR_L2); VarPtr u1 = vf->fieldVar("u1", L2); VarPtr u2 = vf->fieldVar("u2", L2); VarPtr p = vf->fieldVar("p", L2); // traces: VarPtr u1hat = vf->traceVar("u1hat"); VarPtr u2hat = vf->traceVar("u2hat"); VarPtr t1c = vf->fluxVar("t1c"); VarPtr t2c = vf->fluxVar("t2c"); // test: VarPtr v1 = vf->testVar("v1", HGRAD); VarPtr v2 = vf->testVar("v2", HGRAD); VarPtr tau1 = vf->testVar("tau1", HDIV); VarPtr tau2 = vf->testVar("tau2", HDIV); VarPtr q = vf->testVar("q", HGRAD); BFPtr bf = Teuchos::rcp( new BF(vf) ); bf->addTerm(1./mu*sigma1, tau1); bf->addTerm(1./mu*sigma2, tau2); bf->addTerm(u1, tau1->div()); bf->addTerm(u2, tau2->div()); bf->addTerm(-u1hat, tau1->dot_normal()); bf->addTerm(-u2hat, tau2->dot_normal()); bf->addTerm(sigma1, v1->grad()); bf->addTerm(sigma2, v2->grad()); bf->addTerm(-p, v1->dx()); bf->addTerm(-p, v2->dy()); bf->addTerm(t1c, v1); bf->addTerm(t2c, v2); bf->addTerm(mu*permInv*u1, v1); bf->addTerm(mu*permInv*u2, v2); bf->addTerm(-u1, q->dx()); bf->addTerm(-u2, q->dy()); bf->addTerm(u1hat, q->times_normal_x()); bf->addTerm(u2hat, q->times_normal_y()); RHSPtr rhs = RHS::rhs(); BCPtr bc = BC::bc(); SpatialFilterPtr y_equals_one = SpatialFilter::matchingY(1.0); SpatialFilterPtr y_equals_zero = SpatialFilter::matchingY(0); SpatialFilterPtr x_equals_one = SpatialFilter::matchingX(1.0); SpatialFilterPtr x_equals_zero = SpatialFilter::matchingX(0.0); bc->addDirichlet(u1hat, y_equals_zero, u1_exact); bc->addDirichlet(u2hat, y_equals_zero, u2_exact); bc->addDirichlet(u1hat, x_equals_zero, u1_exact); bc->addDirichlet(u2hat, x_equals_zero, u2_exact); bc->addDirichlet(u1hat, y_equals_one, u1_exact); bc->addDirichlet(u2hat, y_equals_one, u2_exact); bc->addDirichlet(u1hat, x_equals_one, u1_exact); bc->addDirichlet(u2hat, x_equals_one, u2_exact); bc->addZeroMeanConstraint(p); MeshPtr mesh = MeshFactory::quadMesh(bf, k+1, delta_k, 1, 1, 4, 4); map<string, IPPtr> brinkmanIPs; brinkmanIPs["Graph"] = bf->graphNorm(); brinkmanIPs["Decoupled"] = Teuchos::rcp(new IP); brinkmanIPs["Decoupled"]->addTerm(tau1); brinkmanIPs["Decoupled"]->addTerm(tau2); brinkmanIPs["Decoupled"]->addTerm(tau1->div()); brinkmanIPs["Decoupled"]->addTerm(tau2->div()); brinkmanIPs["Decoupled"]->addTerm(permInv*v1); brinkmanIPs["Decoupled"]->addTerm(permInv*v2); brinkmanIPs["Decoupled"]->addTerm(v1->grad()); brinkmanIPs["Decoupled"]->addTerm(v2->grad()); brinkmanIPs["Decoupled"]->addTerm(q); brinkmanIPs["Decoupled"]->addTerm(q->grad()); // brinkmanIPs["CoupledRobust"] = Teuchos::rcp(new IP); // brinkmanIPs["CoupledRobust"]->addTerm(tau->div()-beta*v->grad()); // brinkmanIPs["CoupledRobust"]->addTerm(Function<double>::min(one/Function<double>::h(),Function<double>::constant(1./sqrt(epsilon)))*tau); // brinkmanIPs["CoupledRobust"]->addTerm(sqrt(epsilon)*v->grad()); // brinkmanIPs["CoupledRobust"]->addTerm(beta*v->grad()); // brinkmanIPs["CoupledRobust"]->addTerm(Function<double>::min(sqrt(epsilon)*one/Function<double>::h(),one)*v); IPPtr ip = brinkmanIPs[norm]; SolutionPtr soln = TSolution<double>::solution(mesh, bc, rhs, ip); double threshold = 0.20; RefinementStrategy refStrategy(soln, threshold); ostringstream refName; refName << "brinkman"; HDF5Exporter exporter(mesh,refName.str()); for (int refIndex=0; refIndex <= numRefs; refIndex++) { soln->solve(false); double energyError = soln->energyErrorTotal(); if (commRank == 0) { // if (refIndex > 0) // refStrategy.printRefinementStatistics(refIndex-1); cout << "Refinement:\t " << refIndex << " \tElements:\t " << mesh->numActiveElements() << " \tDOFs:\t " << mesh->numGlobalDofs() << " \tEnergy Error:\t " << energyError << endl; } exporter.exportSolution(soln, refIndex); if (refIndex != numRefs) refStrategy.refine(); } return 0; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); #endif int commRank = Teuchos::GlobalMPISession::getRank(); int numProcs = Teuchos::GlobalMPISession::getNProc(); // { // // 1D tests // CellTopoPtrLegacy line_2 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Line<2> >() ) ); // // let's draw a line // vector<double> v0 = makeVertex(0); // vector<double> v1 = makeVertex(1); // vector<double> v2 = makeVertex(2); // vector< vector<double> > vertices; // vertices.push_back(v0); // vertices.push_back(v1); // vertices.push_back(v2); // vector<unsigned> line1VertexList; // vector<unsigned> line2VertexList; // line1VertexList.push_back(0); // line1VertexList.push_back(1); // line2VertexList.push_back(1); // line2VertexList.push_back(2); // vector< vector<unsigned> > elementVertices; // elementVertices.push_back(line1VertexList); // elementVertices.push_back(line2VertexList); // vector< CellTopoPtrLegacy > cellTopos; // cellTopos.push_back(line_2); // cellTopos.push_back(line_2); // MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); // MeshTopologyPtr meshTopology = Teuchos::rcp( new MeshTopology(meshGeometry) ); // FunctionPtr x = Function::xn(1); // FunctionPtr function = x; // FunctionPtr fbdr = Function::restrictToCellBoundary(function); // vector<FunctionPtr> functions; // functions.push_back(function); // functions.push_back(function); // vector<string> functionNames; // functionNames.push_back("function1"); // functionNames.push_back("function2"); // // { // // HDF5Exporter exporter(mesh, "function1", false); // // exporter.exportFunction(function, "function1"); // // } // // { // // HDF5Exporter exporter(mesh, "boundary1", false); // // exporter.exportFunction(fbdr, "boundary1"); // // } // // { // // HDF5Exporter exporter(mesh, "functions1", false); // // exporter.exportFunction(functions, functionNames); // // } // } { // 2D tests // CellTopoPtrLegacy quad_4 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >() ) ); // CellTopoPtrLegacy tri_3 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Triangle<3> >() ) ); CellTopoPtr quad_4 = CellTopology::quad(); CellTopoPtr tri_3 = CellTopology::triangle(); // let's draw a little house vector<double> v0 = makeVertex(-1,0); vector<double> v1 = makeVertex(1,0); vector<double> v2 = makeVertex(1,2); vector<double> v3 = makeVertex(-1,2); vector<double> v4 = makeVertex(0.0,3); vector< vector<double> > vertices; vertices.push_back(v0); vertices.push_back(v1); vertices.push_back(v2); vertices.push_back(v3); vertices.push_back(v4); vector<unsigned> quadVertexList; quadVertexList.push_back(0); quadVertexList.push_back(1); quadVertexList.push_back(2); quadVertexList.push_back(3); vector<unsigned> triVertexList; triVertexList.push_back(3); triVertexList.push_back(2); triVertexList.push_back(4); vector< vector<unsigned> > elementVertices; elementVertices.push_back(quadVertexList); elementVertices.push_back(triVertexList); // vector< CellTopoPtrLegacy > cellTopos; vector< CellTopoPtr> cellTopos; cellTopos.push_back(quad_4); cellTopos.push_back(tri_3); MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); MeshTopologyPtr meshTopology = Teuchos::rcp( new MeshTopology(meshGeometry) ); //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr vf = VarFactory::varFactory(); VarPtr tau = vf->testVar("tau", HDIV); VarPtr v = vf->testVar("v", HGRAD); // define trial variables VarPtr uhat = vf->traceVar("uhat"); VarPtr fhat = vf->fluxVar("fhat"); VarPtr u = vf->fieldVar("u"); VarPtr sigma = vf->fieldVar("sigma", VECTOR_L2); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr bf = Teuchos::rcp( new BF(vf) ); // tau terms: bf->addTerm(sigma, tau); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma, v->grad() ); bf->addTerm( fhat, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = bf->graphNorm(); //////////////////// SPECIFY RHS /////////////////////// RHSPtr rhs = RHS::rhs(); FunctionPtr one = Function::constant(1.0); rhs->addTerm( one * v ); //////////////////// CREATE BCs /////////////////////// BCPtr bc = BC::bc(); FunctionPtr zero = Function::zero(); SpatialFilterPtr entireBoundary = SpatialFilter::allSpace(); bc->addDirichlet(uhat, entireBoundary, zero); //////////////////// SOLVE & REFINE /////////////////////// // Output solution Intrepid::FieldContainer<GlobalIndexType> savedCellPartition; Teuchos::RCP<Epetra_FEVector> savedLHSVector; { //////////////////// BUILD MESH /////////////////////// int H1Order = 4, pToAdd = 2; Teuchos::RCP<Mesh> mesh = Teuchos::rcp( new Mesh (meshTopology, bf, H1Order, pToAdd) ); Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); solution->solve(false); RefinementStrategy refinementStrategy( solution, 0.2); HDF5Exporter exporter(mesh, "Poisson"); // exporter.exportSolution(solution, vf, 0, 2, cellIDToSubdivision(mesh, 4)); exporter.exportSolution(solution, 0, 2); mesh->saveToHDF5("MeshSave.h5"); solution->saveToHDF5("SolnSave.h5"); solution->save("PoissonProblem"); // int numRefs = 1; // for (int ref = 1; ref <= numRefs; ref++) // { // refinementStrategy.refine(commRank==0); // solution->solve(false); // mesh->saveToHDF5("MeshSave.h5"); // solution->saveToHDF5("SolnSave.h5"); // exporter.exportSolution(solution, vf, ref, 2, cellIDToSubdivision(mesh, 4)); // } mesh->globalDofAssignment()->getPartitions(savedCellPartition); savedLHSVector = solution->getLHSVector(); } { SolutionPtr loadedSolution = Solution::load(bf, "PoissonProblem"); HDF5Exporter exporter(loadedSolution->mesh(), "ProblemLoaded"); // exporter.exportSolution(loadedSolution, vf, 0, 2, cellIDToSubdivision(loadedSolution->mesh(), 4)); exporter.exportSolution(loadedSolution, 0, 2); } // { // MeshPtr loadedMesh = MeshFactory::loadFromHDF5(bf, "Test0.h5"); // Teuchos::RCP<Solution> loadedSolution = Teuchos::rcp( new Solution(loadedMesh, bc, rhs, ip) ); // loadedSolution->solve(false); // HDF5Exporter exporter(loadedMesh, "MeshLoaded"); // exporter.exportSolution(loadedSolution, vf, 0, 2, cellIDToSubdivision(loadedMesh, 4)); // } { MeshPtr loadedMesh = MeshFactory::loadFromHDF5(bf, "MeshSave.h5"); Intrepid::FieldContainer<GlobalIndexType> loadedCellPartition; loadedMesh->globalDofAssignment()->getPartitions(loadedCellPartition); if (loadedCellPartition.size() != savedCellPartition.size()) { cout << "Error: the loaded partition has different size/shape than the saved one.\n"; cout << "loaded size: " << loadedCellPartition.size() << "; saved size: " << savedCellPartition.size() << endl; } else { bool partitionsMatch = true; for (int i=0; i<loadedCellPartition.size(); i++) { if (loadedCellPartition[i] != savedCellPartition[i]) { partitionsMatch = false; break; } } if (partitionsMatch) cout << "Saved and loaded cell partitions match!\n"; else { cout << "Saved and loaded cell partitions differ.\n"; cout << "saved:\n" << savedCellPartition; cout << "loaded:\n" << loadedCellPartition; } } Teuchos::RCP<Solution> loadedSolution = Teuchos::rcp( new Solution(loadedMesh, bc, rhs, ip) ); loadedSolution->loadFromHDF5("SolnSave.h5"); Teuchos::RCP<Epetra_FEVector> loadedLHSVector = loadedSolution->getLHSVector(); if (loadedLHSVector->Map().MinLID() != savedLHSVector->Map().MinLID()) { cout << "On rank " << commRank << ", loaded min LID = " << loadedLHSVector->Map().MinLID(); cout << ", but saved min LID = " << savedLHSVector->Map().MinLID() << endl; } else if (loadedLHSVector->Map().MaxLID() != savedLHSVector->Map().MaxLID()) { cout << "On rank " << commRank << ", loaded max LID = " << loadedLHSVector->Map().MaxLID(); cout << ", but saved max LID = " << savedLHSVector->Map().MaxLID() << endl; } else { bool globalIDsMatch = true; for (int lid = loadedLHSVector->Map().MinLID(); lid <= loadedLHSVector->Map().MaxLID(); lid++) { if (loadedLHSVector->Map().GID(lid) != savedLHSVector->Map().GID(lid)) { globalIDsMatch = false; } } if (! globalIDsMatch) { cout << "On rank " << commRank << ", loaded and saved solution vector maps differ in their global IDs.\n"; } else { cout << "On rank " << commRank << ", loaded and saved solution vector maps match in their global IDs.\n"; } bool entriesMatch = true; double tol = 1e-16; if (loadedLHSVector->Map().MinLID() != loadedLHSVector->Map().MaxLID()) { for (int lid = loadedLHSVector->Map().MinLID(); lid <= loadedLHSVector->Map().MaxLID(); lid++) { double loadedValue = (*loadedLHSVector)[0][lid]; double savedValue = (*savedLHSVector)[0][lid]; double diff = abs( loadedValue - savedValue ); if (diff > tol) { entriesMatch = false; cout << "On rank " << commRank << ", loaded and saved solution vectors differ in entry with lid " << lid; cout << "; loaded value = " << loadedValue << "; saved value = " << savedValue << ".\n"; } } if (entriesMatch) { cout << "On rank " << commRank << ", loaded and saved solution vectors match!\n"; } else { cout << "On rank " << commRank << ", loaded and saved solution vectors do not match.\n"; } } } HDF5Exporter exporter(loadedMesh, "SolutionLoaded"); // exporter.exportSolution(loadedSolution, vf, 0, 2, cellIDToSubdivision(loadedMesh, 4)); exporter.exportSolution(loadedSolution, 0, 2); } } // { // // 3D tests // CellTopoPtrLegacy hex = Teuchos::rcp(new shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<8> >() )); // // let's draw a little box // vector<double> v0 = makeVertex(0,0,0); // vector<double> v1 = makeVertex(1,0,0); // vector<double> v2 = makeVertex(1,1,0); // vector<double> v3 = makeVertex(0,1,0); // vector<double> v4 = makeVertex(0,0,1); // vector<double> v5 = makeVertex(1,0,1); // vector<double> v6 = makeVertex(1,1,1); // vector<double> v7 = makeVertex(0,1,1); // vector< vector<double> > vertices; // vertices.push_back(v0); // vertices.push_back(v1); // vertices.push_back(v2); // vertices.push_back(v3); // vertices.push_back(v4); // vertices.push_back(v5); // vertices.push_back(v6); // vertices.push_back(v7); // vector<unsigned> hexVertexList; // hexVertexList.push_back(0); // hexVertexList.push_back(1); // hexVertexList.push_back(2); // hexVertexList.push_back(3); // hexVertexList.push_back(4); // hexVertexList.push_back(5); // hexVertexList.push_back(6); // hexVertexList.push_back(7); // // vector<unsigned> triVertexList; // // triVertexList.push_back(2); // // triVertexList.push_back(3); // // triVertexList.push_back(4); // vector< vector<unsigned> > elementVertices; // elementVertices.push_back(hexVertexList); // // elementVertices.push_back(triVertexList); // vector< CellTopoPtrLegacy > cellTopos; // cellTopos.push_back(hex); // // cellTopos.push_back(tri_3); // MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); // MeshTopologyPtr meshTopology = Teuchos::rcp( new MeshTopology(meshGeometry) ); // FunctionPtr x = Function::xn(1); // FunctionPtr y = Function::yn(1); // FunctionPtr z = Function::zn(1); // FunctionPtr function = x + y + z; // FunctionPtr fbdr = Function::restrictToCellBoundary(function); // FunctionPtr vect = Function::vectorize(x, y, z); // vector<FunctionPtr> functions; // functions.push_back(function); // functions.push_back(vect); // vector<string> functionNames; // functionNames.push_back("function"); // functionNames.push_back("vect"); // // { // // HDF5Exporter exporter(mesh, "function3", false); // // exporter.exportFunction(function, "function3"); // // } // // { // // HDF5Exporter exporter(mesh, "boundary3", false); // // exporter.exportFunction(fbdr, "boundary3"); // // } // // { // // HDF5Exporter exporter(mesh, "vect3", false); // // exporter.exportFunction(vect, "vect3"); // // } // // { // // HDF5Exporter exporter(mesh, "functions3", false); // // exporter.exportFunction(functions, functionNames); // // } // } }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); 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; }
bool LinearTermTests::testMixedTermConsistency() { bool success = true; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr tau = varFactory->testVar("\\tau", HDIV); VarPtr v = varFactory->testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory->traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_n = varFactory->fluxVar("\\widehat{\\beta \\cdot n u - \\sigma_{n}}"); VarPtr u = varFactory->fieldVar("u"); VarPtr sigma1 = varFactory->fieldVar("\\sigma_1"); VarPtr sigma2 = varFactory->fieldVar("\\sigma_2"); vector<double> beta; beta.push_back(1.0); beta.push_back(0.0); double eps = .01; //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr confusionBF = Teuchos::rcp( new BF(varFactory) ); // tau terms: confusionBF->addTerm(sigma1 / eps, tau->x()); confusionBF->addTerm(sigma2 / eps, tau->y()); confusionBF->addTerm(u, tau->div()); confusionBF->addTerm(uhat, -tau->dot_normal()); // v terms: confusionBF->addTerm( sigma1, v->dx() ); confusionBF->addTerm( sigma2, v->dy() ); confusionBF->addTerm( -u, beta * v->grad() ); confusionBF->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int H1Order = 1; int pToAdd = 1; FieldContainer<double> quadPoints(4,2); quadPoints(0,0) = 0.0; // x1 quadPoints(0,1) = 0.0; // y1 quadPoints(1,0) = 1.0; quadPoints(1,1) = 0.0; quadPoints(2,0) = 1.0; quadPoints(2,1) = 1.0; quadPoints(3,0) = 0.0; quadPoints(3,1) = 1.0; int nCells = 1; int horizontalCells = nCells, verticalCells = nCells; // create a pointer to a new mesh: Teuchos::RCP<Mesh> myMesh = MeshFactory::buildQuadMesh(quadPoints, horizontalCells, verticalCells, confusionBF, H1Order, H1Order+pToAdd); ElementTypePtr elemType = myMesh->getElement(0)->elementType(); // DofOrderingPtr testOrder = elemType->testOrderPtr; BasisCachePtr basisCache = Teuchos::rcp(new BasisCache(elemType, myMesh, true)); LinearTermPtr integrandIBP = Teuchos::rcp(new LinearTerm);// residual vector<double> e1(2); // (1,0) vector<double> e2(2); // (0,1) e1[0] = 1; e2[1] = 1; FunctionPtr n = Function::normal(); FunctionPtr X = Function::xn(1); FunctionPtr Y = Function::yn(1); FunctionPtr testFxn1 = X; FunctionPtr testFxn2 = Y; FunctionPtr divTestFxn = testFxn1->dx() + testFxn2->dy(); FunctionPtr vectorTest = testFxn1*e1 + testFxn2*e2; integrandIBP->addTerm(vectorTest*n*v + -vectorTest*v->grad()); // boundary term // define dummy IP to initialize riesz rep class, but just integrate RHS IPPtr dummyIP = Teuchos::rcp(new IP); dummyIP->addTerm(v); Teuchos::RCP<RieszRep> riesz = Teuchos::rcp(new RieszRep(myMesh, dummyIP, integrandIBP)); map<GlobalIndexType,FieldContainer<double> > rieszRHS = riesz->integrateFunctional(); set<GlobalIndexType> cellIDs = myMesh->cellIDsInPartition(); for (set<GlobalIndexType>::iterator cellIDIt=cellIDs.begin(); cellIDIt !=cellIDs.end(); cellIDIt++) { GlobalIndexType cellID = *cellIDIt; ElementTypePtr elemTypePtr = myMesh->getElementType(cellID); DofOrderingPtr testOrderingPtr = elemTypePtr->testOrderPtr; int numTestDofs = testOrderingPtr->totalDofs(); BasisCachePtr basisCache = BasisCache::basisCacheForCell(myMesh, cellID, true); FieldContainer<double> rhsIBPValues(1,numTestDofs); integrandIBP->integrate(rhsIBPValues, testOrderingPtr, basisCache); FieldContainer<double> rieszValues(1,numTestDofs); (riesz->getFunctional())->integrate(rieszValues, testOrderingPtr, basisCache); double maxDiff; double tol = 1e-13; FieldContainer<double> rhsIBPVals(numTestDofs); for (int i = 0; i< numTestDofs; i++) { rhsIBPVals(i) = rhsIBPValues(0,i); // cout << "riesz rhs values = " << rieszRHS[cellID](i) << ", rhsIBPValues = " << rhsIBPVals(i) << ", riesz returned values = " << rieszValues(0,i) << endl; } bool fcsAgree = TestSuite::fcsAgree(rieszRHS[cellID],rhsIBPVals,tol,maxDiff); if (!fcsAgree) { success=false; cout << "Failed mixed term consistency test with maxDiff = " << maxDiff << " on cellID " << cellID<< endl; } } return allSuccess(success); }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); choice::MpiArgs args( argc, argv ); #else choice::Args args( argc, argv ); #endif int commRank = Teuchos::GlobalMPISession::getRank(); int numProcs = Teuchos::GlobalMPISession::getNProc(); // Required arguments double epsilon = args.Input<double>("--epsilon", "diffusion parameter"); int numRefs = args.Input<int>("--numRefs", "number of refinement steps"); bool enforceLocalConservation = args.Input<bool>("--conserve", "enforce local conservation"); int norm = args.Input<int>("--norm", "0 = graph\n 1 = robust\n 2 = modified robust"); // Optional arguments (have defaults) bool zeroL2 = args.Input("--zeroL2", "take L2 term on v in robust norm to zero", false); args.Process(); //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactory varFactory; VarPtr tau = varFactory.testVar("\\tau", HDIV); VarPtr v = varFactory.testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory.traceVar("\\widehat{u}"); VarPtr beta_n_u_minus_sigma_n = varFactory.fluxVar("\\widehat{\\beta \\cdot n u - \\sigma_{n}}"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma = varFactory.fieldVar("sigma", VECTOR_L2); vector<double> beta; beta.push_back(1.0); beta.push_back(0.0); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // tau terms: bf->addTerm(sigma / epsilon, tau); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma, v->grad() ); bf->addTerm( beta * u, - v->grad() ); bf->addTerm( beta_n_u_minus_sigma_n, v); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = Teuchos::rcp(new IP); if (norm == 0) { ip = bf->graphNorm(); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); ip->addZeroMeanTerm( h2_scaling*v ); } // Robust norm else if (norm == 1) { // robust test norm FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); if (!zeroL2) ip->addTerm( v ); ip->addTerm( sqrt(epsilon) * v->grad() ); // Weight these two terms for inflow ip->addTerm( beta * v->grad() ); ip->addTerm( tau->div() ); ip->addTerm( ip_scaling/sqrt(epsilon) * tau ); if (zeroL2) ip->addZeroMeanTerm( h2_scaling*v ); } // Modified robust norm else if (norm == 2) { // robust test norm FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); FunctionPtr h2_scaling = Teuchos::rcp( new ZeroMeanScaling ); // FunctionPtr ip_weight = Teuchos::rcp( new IPWeight() ); if (!zeroL2) ip->addTerm( v ); ip->addTerm( sqrt(epsilon) * v->grad() ); ip->addTerm( beta * v->grad() ); ip->addTerm( tau->div() - beta*v->grad() ); ip->addTerm( ip_scaling/sqrt(epsilon) * tau ); if (zeroL2) ip->addZeroMeanTerm( h2_scaling*v ); } // // robust test norm // IPPtr robIP = Teuchos::rcp(new IP); // FunctionPtr ip_scaling = Teuchos::rcp( new EpsilonScaling(epsilon) ); // if (!enforceLocalConservation) // robIP->addTerm( ip_scaling * v ); // robIP->addTerm( sqrt(epsilon) * v->grad() ); // // Weight these two terms for inflow // FunctionPtr ip_weight = Teuchos::rcp( new IPWeight() ); // robIP->addTerm( ip_weight * beta * v->grad() ); // robIP->addTerm( ip_weight * tau->div() ); // robIP->addTerm( ip_scaling/sqrt(epsilon) * tau ); // if (enforceLocalConservation) // robIP->addZeroMeanTerm( v ); //////////////////// SPECIFY RHS /////////////////////// Teuchos::RCP<RHSEasy> rhs = Teuchos::rcp( new RHSEasy ); FunctionPtr f = Teuchos::rcp( new ConstantScalarFunction(0.0) ); rhs->addTerm( f * v ); // obviously, with f = 0 adding this term is not necessary! //////////////////// CREATE BCs /////////////////////// Teuchos::RCP<BCEasy> bc = Teuchos::rcp( new BCEasy ); Teuchos::RCP<PenaltyConstraints> pc = Teuchos::rcp( new PenaltyConstraints ); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); FunctionPtr one = Teuchos::rcp( new ConstantScalarFunction(1.0) ); FunctionPtr n = Teuchos::rcp( new UnitNormalFunction ); SpatialFilterPtr lBoundary = Teuchos::rcp( new LeftBoundary ); SpatialFilterPtr tbBoundary = Teuchos::rcp( new TopBottomBoundary ); SpatialFilterPtr rBoundary = Teuchos::rcp( new RightBoundary ); // SpatialFilterPtr leftCircleBoundary = Teuchos::rcp( new LeftCircleBoundary ); // SpatialFilterPtr rightCircleBoundary = Teuchos::rcp( new RightCircleBoundary ); SpatialFilterPtr circleBoundary = Teuchos::rcp( new CircleBoundary ); bc->addDirichlet(beta_n_u_minus_sigma_n, lBoundary, zero); bc->addDirichlet(beta_n_u_minus_sigma_n, tbBoundary, zero); pc->addConstraint(beta*uhat->times_normal() - beta_n_u_minus_sigma_n == zero, rBoundary); // bc->addDirichlet(uhat, leftCircleBoundary, one); // bc->addDirichlet(beta_n_u_minus_sigma_n, rightCircleBoundary, beta*n*one); bc->addDirichlet(uhat, circleBoundary, one); //////////////////// BUILD MESH /////////////////////// // define nodes for mesh int H1Order = 3, pToAdd = 2; Teuchos::RCP<Mesh> mesh; mesh = MeshFactory::shiftedHemkerMesh(-3, 9, 6, 1, bf, H1Order, pToAdd); // mesh = BuildHemkerMesh(bf, nseg, circleMesh, triangulateMesh, H1Order, pToAdd); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); solution->setFilter(pc); if (enforceLocalConservation) { FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); solution->lagrangeConstraints()->addConstraint(beta_n_u_minus_sigma_n == zero); } double energyThreshold = 0.25; // for mesh refinements RefinementStrategy refinementStrategy( solution, energyThreshold ); Teuchos::RCP<RefinementHistory> refHistory = Teuchos::rcp( new RefinementHistory ); mesh->registerObserver(refHistory); #ifdef saveVTK VTKExporter exporter(solution, mesh, varFactory); #endif ofstream errOut; if (commRank == 0) errOut.open("hemker_err.txt"); for (int refIndex=0; refIndex<=numRefs; refIndex++) { solution->solve(false); double energy_error = solution->energyErrorTotal(); if (commRank==0) { stringstream outfile; outfile << "hemker_" << refIndex; #ifdef saveVTK exporter.exportSolution(outfile.str()); #endif // Check local conservation FunctionPtr flux = Teuchos::rcp( new PreviousSolutionFunction(solution, beta_n_u_minus_sigma_n) ); FunctionPtr zero = Teuchos::rcp( new ConstantScalarFunction(0.0) ); Teuchos::Tuple<double, 3> fluxImbalances = checkConservation(flux, zero, varFactory, mesh); cout << "Mass flux: Largest Local = " << fluxImbalances[0] << ", Global = " << fluxImbalances[1] << ", Sum Abs = " << fluxImbalances[2] << endl; errOut << mesh->numGlobalDofs() << " " << energy_error << " " << fluxImbalances[0] << " " << fluxImbalances[1] << " " << fluxImbalances[2] << endl; } if (refIndex < numRefs) refinementStrategy.refine(commRank==0); // print to console on commRank 0 } if (commRank == 0) errOut.close(); return 0; }
int main(int argc, char *argv[]) { #ifdef ENABLE_INTEL_FLOATING_POINT_EXCEPTIONS cout << "NOTE: enabling floating point exceptions for divide by zero.\n"; _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_INVALID); #endif Teuchos::GlobalMPISession mpiSession(&argc, &argv); int rank = Teuchos::GlobalMPISession::getRank(); #ifdef HAVE_MPI Epetra_MpiComm Comm(MPI_COMM_WORLD); //cout << "rank: " << rank << " of " << numProcs << endl; #else Epetra_SerialComm Comm; #endif Comm.Barrier(); // set breakpoint here to allow debugger attachment to other MPI processes than the one you automatically attached to. Teuchos::CommandLineProcessor cmdp(false,true); // false: don't throw exceptions; true: do return errors for unrecognized options double minTol = 1e-8; bool use3D = false; int refCount = 10; int k = 4; // poly order for field variables int delta_k = use3D ? 3 : 2; // test space enrichment int k_coarse = 0; bool useMumps = true; bool useGMGSolver = true; bool enforceOneIrregularity = true; bool useStaticCondensation = false; bool conformingTraces = false; bool useDiagonalScaling = false; // of the global stiffness matrix in GMGSolver bool printRefinementDetails = false; bool useWeightedGraphNorm = true; // graph norm scaled according to units, more or less int numCells = 2; int AztecOutputLevel = 1; int gmgMaxIterations = 10000; int smootherOverlap = 0; double relativeTol = 1e-6; double D = 1.0; // characteristic length scale cmdp.setOption("polyOrder",&k,"polynomial order for field variable u"); cmdp.setOption("delta_k", &delta_k, "test space polynomial order enrichment"); cmdp.setOption("k_coarse", &k_coarse, "polynomial order for field variables on coarse mesh"); cmdp.setOption("numRefs",&refCount,"number of refinements"); cmdp.setOption("D", &D, "domain dimension"); cmdp.setOption("useConformingTraces", "useNonConformingTraces", &conformingTraces); cmdp.setOption("enforceOneIrregularity", "dontEnforceOneIrregularity", &enforceOneIrregularity); cmdp.setOption("smootherOverlap", &smootherOverlap, "overlap for smoother"); cmdp.setOption("printRefinementDetails", "dontPrintRefinementDetails", &printRefinementDetails); cmdp.setOption("azOutput", &AztecOutputLevel, "Aztec output level"); cmdp.setOption("numCells", &numCells, "number of cells in the initial mesh"); cmdp.setOption("useScaledGraphNorm", "dontUseScaledGraphNorm", &useWeightedGraphNorm); // cmdp.setOption("gmgTol", &gmgTolerance, "tolerance for GMG convergence"); cmdp.setOption("relativeTol", &relativeTol, "Energy error-relative tolerance for iterative solver."); cmdp.setOption("gmgMaxIterations", &gmgMaxIterations, "tolerance for GMG convergence"); bool enhanceUField = false; cmdp.setOption("enhanceUField", "dontEnhanceUField", &enhanceUField); cmdp.setOption("useStaticCondensation", "dontUseStaticCondensation", &useStaticCondensation); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { #ifdef HAVE_MPI MPI_Finalize(); #endif return -1; } double width = D, height = D, depth = D; VarFactory varFactory; // fields: VarPtr u = varFactory.fieldVar("u", L2); VarPtr sigma = varFactory.fieldVar("\\sigma", VECTOR_L2); FunctionPtr n = Function::normal(); // traces: VarPtr u_hat; if (conformingTraces) { u_hat = varFactory.traceVar("\\widehat{u}", u); } else { cout << "Note: using non-conforming traces.\n"; u_hat = varFactory.traceVar("\\widehat{u}", u, L2); } VarPtr sigma_n_hat = varFactory.fluxVar("\\widehat{\\sigma}_{n}", sigma * n); // test functions: VarPtr tau = varFactory.testVar("\\tau", HDIV); VarPtr v = varFactory.testVar("v", HGRAD); BFPtr poissonBF = Teuchos::rcp( new BF(varFactory) ); FunctionPtr alpha = Function::constant(1); // viscosity // tau terms: poissonBF->addTerm(sigma / alpha, tau); poissonBF->addTerm(-u, tau->div()); // (sigma1, tau1) poissonBF->addTerm(u_hat, tau * n); // v terms: poissonBF->addTerm(- sigma, v->grad()); // (mu sigma1, grad v1) poissonBF->addTerm( sigma_n_hat, v); int horizontalCells = numCells, verticalCells = numCells, depthCells = numCells; vector<double> domainDimensions; domainDimensions.push_back(width); domainDimensions.push_back(height); vector<int> elementCounts; elementCounts.push_back(horizontalCells); elementCounts.push_back(verticalCells); if (use3D) { domainDimensions.push_back(depth); elementCounts.push_back(depthCells); } MeshPtr mesh, k0Mesh; int H1Order = k + 1; int H1Order_coarse = k_coarse + 1; if (!use3D) { Teuchos::ParameterList pl; map<int,int> trialOrderEnhancements; if (enhanceUField) { trialOrderEnhancements[u->ID()] = 1; } BFPtr poissonBilinearForm = poissonBF; pl.set("useMinRule", true); pl.set("bf",poissonBilinearForm); pl.set("H1Order", H1Order); pl.set("delta_k", delta_k); pl.set("horizontalElements", horizontalCells); pl.set("verticalElements", verticalCells); pl.set("divideIntoTriangles", false); pl.set("useConformingTraces", conformingTraces); pl.set("trialOrderEnhancements", &trialOrderEnhancements); pl.set("x0",(double)0); pl.set("y0",(double)0); pl.set("width", width); pl.set("height",height); mesh = MeshFactory::quadMesh(pl); pl.set("H1Order", H1Order_coarse); k0Mesh = MeshFactory::quadMesh(pl); } else { mesh = MeshFactory::rectilinearMesh(poissonBF, domainDimensions, elementCounts, H1Order, delta_k); k0Mesh = MeshFactory::rectilinearMesh(poissonBF, domainDimensions, elementCounts, H1Order_coarse, delta_k); } mesh->registerObserver(k0Mesh); // ensure that the k0 mesh refinements track those of the solution mesh RHSPtr rhs = RHS::rhs(); // zero FunctionPtr sin_pi_x = Teuchos::rcp( new Sin_ax(PI/D) ); FunctionPtr sin_pi_y = Teuchos::rcp( new Sin_ay(PI/D) ); FunctionPtr u_exact = sin_pi_x * sin_pi_y; FunctionPtr f = -(2.0 * PI * PI / (D * D)) * sin_pi_x * sin_pi_y; rhs->addTerm( f * v ); BCPtr bc = BC::bc(); SpatialFilterPtr boundary = SpatialFilter::allSpace(); bc->addDirichlet(u_hat, boundary, u_exact); IPPtr graphNorm; FunctionPtr h = Teuchos::rcp( new hFunction() ); if (useWeightedGraphNorm) { graphNorm = IP::ip(); graphNorm->addTerm( tau->div() ); // u graphNorm->addTerm( (h / alpha) * tau - h * v->grad() ); // sigma graphNorm->addTerm( v ); // boundary term (adjoint to u) graphNorm->addTerm( h * tau ); // // new effort, with the idea that the test norm should be considered in reference space, basically // graphNorm = IP::ip(); // graphNorm->addTerm( tau->div() ); // u // graphNorm->addTerm( tau / h - v->grad() ); // sigma // graphNorm->addTerm( v / h ); // boundary term (adjoint to u) // graphNorm->addTerm( tau / h ); } else { map<int, double> trialWeights; // on the squared terms in the trial space norm trialWeights[u->ID()] = 1.0 / (D * D); trialWeights[sigma->ID()] = 1.0; graphNorm = poissonBF->graphNorm(trialWeights, 1.0); // 1.0: weight on the L^2 terms } SolutionPtr solution = Solution::solution(mesh, bc, rhs, graphNorm); solution->setUseCondensedSolve(useStaticCondensation); mesh->registerSolution(solution); // sign up for projection of old solution onto refined cells. double energyThreshold = 0.2; RefinementStrategy refinementStrategy( solution, energyThreshold ); refinementStrategy.setReportPerCellErrors(true); refinementStrategy.setEnforceOneIrregularity(enforceOneIrregularity); Teuchos::RCP<Solver> coarseSolver, fineSolver; if (useMumps) { #ifdef HAVE_AMESOS_MUMPS coarseSolver = Teuchos::rcp( new MumpsSolver(512, true) ); #else cout << "useMumps=true, but MUMPS is not available!\n"; exit(0); #endif } else { coarseSolver = Teuchos::rcp( new KluSolver ); } GMGSolver* gmgSolver; if (useGMGSolver) { double tol = relativeTol; int maxIters = gmgMaxIterations; BCPtr zeroBCs = bc->copyImposingZero(); gmgSolver = new GMGSolver(zeroBCs, k0Mesh, graphNorm, mesh, solution->getDofInterpreter(), solution->getPartitionMap(), maxIters, tol, coarseSolver, useStaticCondensation); gmgSolver->setAztecOutput(AztecOutputLevel); gmgSolver->setUseConjugateGradient(true); gmgSolver->gmgOperator()->setSmootherType(GMGOperator::IFPACK_ADDITIVE_SCHWARZ); gmgSolver->gmgOperator()->setSmootherOverlap(smootherOverlap); fineSolver = Teuchos::rcp( gmgSolver ); } else { fineSolver = coarseSolver; } // if (rank==0) cout << "experimentally starting by solving with MUMPS on the fine mesh.\n"; // solution->solve( Teuchos::rcp( new MumpsSolver) ); solution->solve(fineSolver); #ifdef HAVE_EPETRAEXT_HDF5 ostringstream dir_name; dir_name << "poissonCavityFlow_k" << k; HDF5Exporter exporter(mesh,dir_name.str()); exporter.exportSolution(solution,varFactory,0); #endif #ifdef HAVE_AMESOS_MUMPS if (useMumps) coarseSolver = Teuchos::rcp( new MumpsSolver(512, true) ); #endif solution->reportTimings(); if (useGMGSolver) gmgSolver->gmgOperator()->reportTimings(); for (int refIndex=0; refIndex < refCount; refIndex++) { double energyError = solution->energyErrorTotal(); GlobalIndexType numFluxDofs = mesh->numFluxDofs(); if (rank==0) { cout << "Before refinement " << refIndex << ", energy error = " << energyError; cout << " (using " << numFluxDofs << " trace degrees of freedom)." << endl; } bool printToConsole = printRefinementDetails && (rank==0); refinementStrategy.refine(printToConsole); if (useStaticCondensation) { CondensedDofInterpreter* condensedDofInterpreter = dynamic_cast<CondensedDofInterpreter*>(solution->getDofInterpreter().get()); if (condensedDofInterpreter != NULL) { condensedDofInterpreter->reinitialize(); } } GlobalIndexType fineDofs = mesh->globalDofCount(); GlobalIndexType coarseDofs = k0Mesh->globalDofCount(); if (rank==0) { cout << "After refinement, coarse mesh has " << k0Mesh->numActiveElements() << " elements and " << coarseDofs << " dofs.\n"; cout << " Fine mesh has " << mesh->numActiveElements() << " elements and " << fineDofs << " dofs.\n"; } if (!use3D) { ostringstream fineMeshLocation, coarseMeshLocation; fineMeshLocation << "poissonFineMesh_k" << k << "_ref" << refIndex; GnuPlotUtil::writeComputationalMeshSkeleton(fineMeshLocation.str(), mesh, true); // true: label cells coarseMeshLocation << "poissonCoarseMesh_k" << k << "_ref" << refIndex; GnuPlotUtil::writeComputationalMeshSkeleton(coarseMeshLocation.str(), k0Mesh, true); // true: label cells } if (useGMGSolver) // create fresh fineSolver now that the meshes have changed: { #ifdef HAVE_AMESOS_MUMPS if (useMumps) coarseSolver = Teuchos::rcp( new MumpsSolver(512, true) ); #endif double tol = max(relativeTol * energyError, minTol); int maxIters = gmgMaxIterations; BCPtr zeroBCs = bc->copyImposingZero(); gmgSolver = new GMGSolver(zeroBCs, k0Mesh, graphNorm, mesh, solution->getDofInterpreter(), solution->getPartitionMap(), maxIters, tol, coarseSolver, useStaticCondensation); gmgSolver->setAztecOutput(AztecOutputLevel); gmgSolver->setUseDiagonalScaling(useDiagonalScaling); fineSolver = Teuchos::rcp( gmgSolver ); } solution->solve(fineSolver); solution->reportTimings(); if (useGMGSolver) gmgSolver->gmgOperator()->reportTimings(); #ifdef HAVE_EPETRAEXT_HDF5 exporter.exportSolution(solution,varFactory,refIndex+1); #endif } double energyErrorTotal = solution->energyErrorTotal(); GlobalIndexType numFluxDofs = mesh->numFluxDofs(); GlobalIndexType numGlobalDofs = mesh->numGlobalDofs(); if (rank==0) { cout << "Final mesh has " << mesh->numActiveElements() << " elements and " << numFluxDofs << " trace dofs ("; cout << numGlobalDofs << " total dofs, including fields).\n"; cout << "Final energy error: " << energyErrorTotal << endl; } #ifdef HAVE_EPETRAEXT_HDF5 exporter.exportSolution(solution,varFactory,0); #endif if (!use3D) { GnuPlotUtil::writeComputationalMeshSkeleton("poissonRefinedMesh", mesh, true); } coarseSolver = Teuchos::rcp((Solver*) NULL); // without this when useMumps = true and running on one rank, we see a crash on exit, which may have to do with MPI being finalized before coarseSolver is deleted. return 0; }
ConvectionDiffusionFormulation::ConvectionDiffusionFormulation(int spaceDim, bool useConformingTraces, FunctionPtr beta, double epsilon) { _spaceDim = spaceDim; _epsilon = epsilon; _beta = beta; FunctionPtr zero = Function::constant(1); FunctionPtr one = Function::constant(1); Space tauSpace = (spaceDim > 1) ? HDIV : HGRAD; Space uhat_space = useConformingTraces ? HGRAD : L2; Space vSpace = (spaceDim > 1) ? VECTOR_L2 : L2; // fields VarPtr u; VarPtr sigma; // traces VarPtr uhat, tc; // tests VarPtr v; VarPtr tau; _vf = VarFactory::varFactory(); u = _vf->fieldVar(s_u); sigma = _vf->fieldVar(s_sigma, vSpace); if (spaceDim > 1) uhat = _vf->traceVar(s_uhat, u, uhat_space); else uhat = _vf->fluxVar(s_uhat, u, uhat_space); // for spaceDim==1, the "normal" component is in the flux-ness of uhat (it's a plus or minus 1) TFunctionPtr<double> n = TFunction<double>::normal(); TFunctionPtr<double> parity = TFunction<double>::sideParity(); if (spaceDim > 1) tc = _vf->fluxVar(s_tc, (_beta*u-sigma) * (n * parity)); else tc = _vf->fluxVar(s_tc, _beta*u-sigma); v = _vf->testVar(s_v, HGRAD); tau = _vf->testVar(s_tau, tauSpace); _bf = Teuchos::rcp( new BF(_vf) ); if (spaceDim==1) { // for spaceDim==1, the "normal" component is in the flux-ness of uhat (it's a plus or minus 1) _bf->addTerm(sigma/_epsilon, tau); _bf->addTerm(u, tau->dx()); _bf->addTerm(-uhat, tau); _bf->addTerm(-_beta*u + sigma, v->dx()); _bf->addTerm(tc, v); } else { _bf->addTerm(sigma/_epsilon, tau); _bf->addTerm(u, tau->div()); _bf->addTerm(-uhat, tau->dot_normal()); _bf->addTerm(-_beta*u + sigma, v->grad()); _bf->addTerm(tc, v); } _ips["Graph"] = _bf->graphNorm(); if (spaceDim > 1) { _ips["Robust"] = Teuchos::rcp(new IP); _ips["Robust"]->addTerm(tau->div()); _ips["Robust"]->addTerm(Function::min(one/Function::h(),Function::constant(1./sqrt(_epsilon)))*tau); _ips["Robust"]->addTerm(sqrt(_epsilon)*v->grad()); _ips["Robust"]->addTerm(_beta*v->grad()); _ips["Robust"]->addTerm(Function::min(sqrt(_epsilon)*one/Function::h(),one)*v); } else { _ips["Robust"] = Teuchos::rcp(new IP); _ips["Robust"]->addTerm(tau->dx()); _ips["Robust"]->addTerm(Function::min(one/Function::h(),Function::constant(1./sqrt(_epsilon)))*tau); _ips["Robust"]->addTerm(sqrt(_epsilon)*v->dx()); _ips["Robust"]->addTerm(_beta*v->dx()); _ips["Robust"]->addTerm(Function::min(sqrt(_epsilon)*one/Function::h(),one)*v); } if (spaceDim > 1) { _ips["CoupledRobust"] = Teuchos::rcp(new IP); _ips["CoupledRobust"]->addTerm(tau->div()-_beta*v->grad()); _ips["CoupledRobust"]->addTerm(Function::min(one/Function::h(),Function::constant(1./sqrt(_epsilon)))*tau); _ips["CoupledRobust"]->addTerm(sqrt(_epsilon)*v->grad()); _ips["CoupledRobust"]->addTerm(_beta*v->grad()); _ips["CoupledRobust"]->addTerm(Function::min(sqrt(_epsilon)*one/Function::h(),one)*v); } else { _ips["CoupledRobust"] = Teuchos::rcp(new IP); _ips["CoupledRobust"]->addTerm(tau->dx()-_beta*v->dx()); _ips["CoupledRobust"]->addTerm(Function::min(one/Function::h(),Function::constant(1./sqrt(_epsilon)))*tau); _ips["CoupledRobust"]->addTerm(sqrt(_epsilon)*v->dx()); _ips["CoupledRobust"]->addTerm(_beta*v->dx()); _ips["CoupledRobust"]->addTerm(Function::min(sqrt(_epsilon)*one/Function::h(),one)*v); } }