// computes riesz representation over a single element - map is from int (testID) to FieldContainer of values (sized cellIndex, numPoints) void RieszRep::computeRepresentationValues(FieldContainer<double> &values, int testID, IntrepidExtendedTypes::EOperatorExtended op, BasisCachePtr basisCache){ if (_repsNotComputed){ cout << "Computing riesz rep dofs" << endl; computeRieszRep(); } int spaceDim = _mesh->getTopology()->getSpaceDim(); int numCells = values.dimension(0); int numPoints = values.dimension(1); vector<GlobalIndexType> cellIDs = basisCache->cellIDs(); // all elems coming in should be of same type ElementPtr elem = _mesh->getElement(cellIDs[0]); ElementTypePtr elemTypePtr = elem->elementType(); DofOrderingPtr testOrderingPtr = elemTypePtr->testOrderPtr; CellTopoPtrLegacy cellTopoPtr = elemTypePtr->cellTopoPtr; int numTestDofsForVarID = testOrderingPtr->getBasisCardinality(testID, 0); BasisPtr testBasis = testOrderingPtr->getBasis(testID); bool testBasisIsVolumeBasis = (spaceDim == testBasis->domainTopology()->getDimension()); bool useCubPointsSideRefCell = testBasisIsVolumeBasis && basisCache->isSideCache(); Teuchos::RCP< const FieldContainer<double> > transformedBasisValues = basisCache->getTransformedValues(testBasis,op,useCubPointsSideRefCell); int rank = values.rank() - 2; // if values are shaped as (C,P), scalar... if (rank > 1) { cout << "ranks greater than 1 not presently supported...\n"; TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "ranks greater than 1 not presently supported..."); } // Camellia::print("cellIDs",cellIDs); values.initialize(0.0); for (int cellIndex = 0;cellIndex<numCells;cellIndex++){ int cellID = cellIDs[cellIndex]; for (int j = 0;j<numTestDofsForVarID;j++) { int dofIndex = testOrderingPtr->getDofIndex(testID, j); for (int i = 0;i<numPoints;i++) { if (rank==0) { double basisValue = (*transformedBasisValues)(cellIndex,j,i); values(cellIndex,i) += basisValue*_rieszRepDofsGlobal[cellID](dofIndex); } else { for (int d = 0; d<spaceDim; d++) { double basisValue = (*transformedBasisValues)(cellIndex,j,i,d); values(cellIndex,i,d) += basisValue*_rieszRepDofsGlobal[cellID](dofIndex); } } } } } // TestSuite::serializeOutput("rep values", values); }
double RieszRep::computeAlternativeNormSqOnCell(IPPtr ip, ElementPtr elem){ GlobalIndexType cellID = elem->cellID(); Teuchos::RCP<DofOrdering> testOrdering= elem->elementType()->testOrderPtr; bool testVsTest = true; Teuchos::RCP<BasisCache> basisCache = BasisCache::basisCacheForCell(_mesh, cellID, testVsTest,1); int numDofs = testOrdering->totalDofs(); FieldContainer<double> ipMat(1,numDofs,numDofs); ip->computeInnerProductMatrix(ipMat,testOrdering,basisCache); double sum = 0.0; for (int i = 0;i<numDofs;i++){ for (int j = 0;j<numDofs;j++){ sum += _rieszRepDofsGlobal[cellID](i)*_rieszRepDofsGlobal[cellID](j)*ipMat(0,i,j); } } return sum; }
map< int, vector<DofInfo> > constructGlobalDofToLocalDofInfoMap(MeshPtr mesh) { // go through the mesh as a whole, and collect info for each dof map< int, vector<DofInfo> > infoMap; DofInfo info; set<GlobalIndexType> activeCellIDs = mesh->getActiveCellIDsGlobal(); for (set<GlobalIndexType>::iterator cellIt = activeCellIDs.begin(); cellIt != activeCellIDs.end(); cellIt++) { GlobalIndexType cellID = *cellIt; info.cellID = cellID; ElementPtr element = mesh->getElement(cellID); DofOrderingPtr trialOrder = element->elementType()->trialOrderPtr; set<int> trialIDs = trialOrder->getVarIDs(); info.totalDofs = trialOrder->totalDofs(); for (set<int>::iterator trialIt=trialIDs.begin(); trialIt != trialIDs.end(); trialIt++) { info.trialID = *trialIt; const vector<int>* sidesForVar = &trialOrder->getSidesForVarID(info.trialID); for (vector<int>::const_iterator sideIt = sidesForVar->begin(); sideIt != sidesForVar->end(); sideIt++) { int sideIndex = *sideIt; info.sideIndex = sideIndex; info.basisCardinality = trialOrder->getBasisCardinality(info.trialID, info.sideIndex); for (int basisOrdinal=0; basisOrdinal < info.basisCardinality; basisOrdinal++) { info.basisOrdinal = basisOrdinal; info.localDofIndex = trialOrder->getDofIndex(info.trialID, info.basisOrdinal, info.sideIndex); pair<int, int> localDofIndexKey = make_pair(info.cellID, info.localDofIndex); int globalDofIndex = mesh->getLocalToGlobalMap().find(localDofIndexKey)->second; // cout << "(" << info.cellID << "," << info.localDofIndex << ") --> " << globalDofIndex << endl; infoMap[globalDofIndex].push_back(info); } } } } return infoMap; }
bool ScratchPadTests::testGalerkinOrthogonality() { double tol = 1e-11; bool success = true; //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactoryPtr varFactory = VarFactory::varFactory(); VarPtr v = varFactory->testVar("v", HGRAD); vector<double> beta; beta.push_back(1.0); beta.push_back(1.0); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// // robust test norm IPPtr ip = Teuchos::rcp(new IP); ip->addTerm(v); ip->addTerm(beta*v->grad()); // define trial variables VarPtr beta_n_u = varFactory->fluxVar("\\widehat{\\beta \\cdot n }"); VarPtr u = varFactory->fieldVar("u"); //////////////////// BUILD MESH /////////////////////// BFPtr convectionBF = Teuchos::rcp( new BF(varFactory) ); FunctionPtr n = Function::normal(); // v terms: convectionBF->addTerm( -u, beta * v->grad() ); convectionBF->addTerm( beta_n_u, v); // define nodes for mesh int order = 2; int H1Order = order+1; int pToAdd = 1; // create a pointer to a new mesh: Teuchos::RCP<Mesh> mesh = MeshUtilities::buildUnitQuadMesh(4, convectionBF, H1Order, H1Order+pToAdd); //////////////////// SOLVE /////////////////////// RHSPtr rhs = RHS::rhs(); BCPtr bc = BC::bc(); SpatialFilterPtr inflowBoundary = Teuchos::rcp( new InflowSquareBoundary ); SpatialFilterPtr outflowBoundary = Teuchos::rcp( new NegatedSpatialFilter(inflowBoundary) ); FunctionPtr uIn; uIn = Teuchos::rcp(new Uinflow); // uses a discontinuous piecewise-constant basis function on left and bottom sides of square bc->addDirichlet(beta_n_u, inflowBoundary, beta*n*uIn); Teuchos::RCP<Solution> solution; solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); solution->solve(false); FunctionPtr uFxn = Function::solution(u, solution); FunctionPtr fnhatFxn = Function::solution(beta_n_u,solution); // make residual for riesz representation function LinearTermPtr residual = Teuchos::rcp(new LinearTerm);// residual FunctionPtr parity = Function::sideParity(); residual->addTerm(-fnhatFxn*v + (beta*uFxn)*v->grad()); Teuchos::RCP<RieszRep> riesz = Teuchos::rcp(new RieszRep(mesh, ip, residual)); riesz->computeRieszRep(); map<int,FunctionPtr> err_rep_map; err_rep_map[v->ID()] = RieszRep::repFunction(v,riesz); //////////////////// GET BOUNDARY CONDITION DATA /////////////////////// FieldContainer<GlobalIndexType> bcGlobalIndices; FieldContainer<double> bcGlobalValues; mesh->boundary().bcsToImpose(bcGlobalIndices,bcGlobalValues,*(solution->bc()), NULL); set<int> bcInds; for (int i=0; i<bcGlobalIndices.dimension(0); i++) { bcInds.insert(bcGlobalIndices(i)); } //////////////////// CHECK GALERKIN ORTHOGONALITY /////////////////////// BCPtr nullBC; RHSPtr nullRHS; IPPtr nullIP; SolutionPtr solnPerturbation = Teuchos::rcp(new Solution(mesh, nullBC, nullRHS, nullIP) ); map< int, vector<DofInfo> > infoMap = constructGlobalDofToLocalDofInfoMap(mesh); for (map< int, vector<DofInfo> >::iterator mapIt = infoMap.begin(); mapIt != infoMap.end(); mapIt++) { int dofIndex = mapIt->first; vector< DofInfo > dofInfoVector = mapIt->second; // all the local dofs that map to dofIndex // create perturbation in direction du solnPerturbation->clear(); // clear all solns // set each corresponding local dof to 1.0 for (vector< DofInfo >::iterator dofInfoIt = dofInfoVector.begin(); dofInfoIt != dofInfoVector.end(); dofInfoIt++) { DofInfo info = *dofInfoIt; FieldContainer<double> solnCoeffs(info.basisCardinality); solnCoeffs(info.basisOrdinal) = 1.0; solnPerturbation->setSolnCoeffsForCellID(solnCoeffs, info.cellID, info.trialID, info.sideIndex); } // solnPerturbation->setSolnCoeffForGlobalDofIndex(1.0,dofIndex); LinearTermPtr b_du = convectionBF->testFunctional(solnPerturbation); FunctionPtr gradient = b_du->evaluate(err_rep_map, TestingUtilities::isFluxOrTraceDof(mesh,dofIndex)); // use boundary part only if flux double grad = gradient->integrate(mesh,10); if (!TestingUtilities::isFluxOrTraceDof(mesh,dofIndex) && abs(grad)>tol) // if we're not single-precision zero FOR FIELDS { // int cellID = mesh->getGlobalToLocalMap()[dofIndex].first; cout << "Failed testGalerkinOrthogonality() for fields with diff " << abs(grad) << " at dof " << dofIndex << "; info:" << endl; cout << dofInfoString(infoMap[dofIndex]); success = false; } } FieldContainer<double> errorJumps(mesh->numGlobalDofs()); //initialized to zero // just test fluxes ON INTERNAL SKELETON here set<GlobalIndexType> activeCellIDs = mesh->getActiveCellIDsGlobal(); for (GlobalIndexType activeCellID : activeCellIDs) { ElementPtr elem = mesh->getElement(activeCellID); for (int sideIndex = 0; sideIndex < 4; sideIndex++) { ElementTypePtr elemType = elem->elementType(); vector<int> localDofIndices = elemType->trialOrderPtr->getDofIndices(beta_n_u->ID(), sideIndex); for (int i = 0; i<localDofIndices.size(); i++) { int globalDofIndex = mesh->globalDofIndex(elem->cellID(), localDofIndices[i]); vector< DofInfo > dofInfoVector = infoMap[globalDofIndex]; solnPerturbation->clear(); TestingUtilities::setSolnCoeffForGlobalDofIndex(solnPerturbation,1.0,globalDofIndex); // also add in BCs for (int i = 0; i<bcGlobalIndices.dimension(0); i++) { TestingUtilities::setSolnCoeffForGlobalDofIndex(solnPerturbation,bcGlobalValues(i),bcGlobalIndices(i)); } LinearTermPtr b_du = convectionBF->testFunctional(solnPerturbation); FunctionPtr gradient = b_du->evaluate(err_rep_map, TestingUtilities::isFluxOrTraceDof(mesh,globalDofIndex)); // use boundary part only if flux double jump = gradient->integrate(mesh,10); errorJumps(globalDofIndex) += jump; } } } for (int i = 0; i<mesh->numGlobalDofs(); i++) { if (abs(errorJumps(i))>tol) { cout << "Failing Galerkin orthogonality test for fluxes with diff " << errorJumps(i) << " at dof " << i << endl; cout << dofInfoString(infoMap[i]); success = false; } } return success; }