void Projector::projectFunctionOntoBasis(FieldContainer<double> &basisCoefficients, FunctionPtr fxn, BasisPtr basis, BasisCachePtr basisCache, IPPtr ip, VarPtr v, set<int> fieldIndicesToSkip) { CellTopoPtr cellTopo = basis->domainTopology(); DofOrderingPtr dofOrderPtr = Teuchos::rcp(new DofOrdering()); if (! fxn.get()) { TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "fxn cannot be null!"); } int cardinality = basis->getCardinality(); int numCells = basisCache->getPhysicalCubaturePoints().dimension(0); int numDofs = cardinality - fieldIndicesToSkip.size(); if (numDofs==0) { // we're skipping all the fields, so just initialize basisCoefficients to 0 and return basisCoefficients.resize(numCells,cardinality); basisCoefficients.initialize(0); return; } FieldContainer<double> gramMatrix(numCells,cardinality,cardinality); FieldContainer<double> ipVector(numCells,cardinality); // fake a DofOrdering DofOrderingPtr dofOrdering = Teuchos::rcp( new DofOrdering ); if (! basisCache->isSideCache()) { dofOrdering->addEntry(v->ID(), basis, v->rank()); } else { dofOrdering->addEntry(v->ID(), basis, v->rank(), basisCache->getSideIndex()); } ip->computeInnerProductMatrix(gramMatrix, dofOrdering, basisCache); ip->computeInnerProductVector(ipVector, v, fxn, dofOrdering, basisCache); // cout << "physical points for projection:\n" << basisCache->getPhysicalCubaturePoints(); // cout << "gramMatrix:\n" << gramMatrix; // cout << "ipVector:\n" << ipVector; map<int,int> oldToNewIndices; if (fieldIndicesToSkip.size() > 0) { // the code to do with fieldIndicesToSkip might not be terribly efficient... // (but it's not likely to be called too frequently) int i_indices_skipped = 0; for (int i=0; i<cardinality; i++) { int new_index; if (fieldIndicesToSkip.find(i) != fieldIndicesToSkip.end()) { i_indices_skipped++; new_index = -1; } else { new_index = i - i_indices_skipped; } oldToNewIndices[i] = new_index; } FieldContainer<double> gramMatrixFiltered(numCells,numDofs,numDofs); FieldContainer<double> ipVectorFiltered(numCells,numDofs); // now filter out the values that we're to skip for (int cellIndex=0; cellIndex<numCells; cellIndex++) { for (int i=0; i<cardinality; i++) { int i_filtered = oldToNewIndices[i]; if (i_filtered == -1) { continue; } ipVectorFiltered(cellIndex,i_filtered) = ipVector(cellIndex,i); for (int j=0; j<cardinality; j++) { int j_filtered = oldToNewIndices[j]; if (j_filtered == -1) { continue; } gramMatrixFiltered(cellIndex,i_filtered,j_filtered) = gramMatrix(cellIndex,i,j); } } } // cout << "gramMatrixFiltered:\n" << gramMatrixFiltered; // cout << "ipVectorFiltered:\n" << ipVectorFiltered; gramMatrix = gramMatrixFiltered; ipVector = ipVectorFiltered; } for (int cellIndex=0; cellIndex<numCells; cellIndex++){ // TODO: rewrite to take advantage of SerialDenseWrapper... Epetra_SerialDenseSolver solver; Epetra_SerialDenseMatrix A(Copy, &gramMatrix(cellIndex,0,0), gramMatrix.dimension(2), gramMatrix.dimension(2), gramMatrix.dimension(1)); // stride -- fc stores in row-major order (a.o.t. SDM) Epetra_SerialDenseVector b(Copy, &ipVector(cellIndex,0), ipVector.dimension(1)); Epetra_SerialDenseVector x(gramMatrix.dimension(1)); solver.SetMatrix(A); int info = solver.SetVectors(x,b); if (info!=0){ cout << "projectFunctionOntoBasis: failed to SetVectors with error " << info << endl; } bool equilibrated = false; if (solver.ShouldEquilibrate()){ solver.EquilibrateMatrix(); solver.EquilibrateRHS(); equilibrated = true; } info = solver.Solve(); if (info!=0){ cout << "projectFunctionOntoBasis: failed to solve with error " << info << endl; } if (equilibrated) { int successLocal = solver.UnequilibrateLHS(); if (successLocal != 0) { cout << "projection: unequilibration FAILED with error: " << successLocal << endl; } } basisCoefficients.resize(numCells,cardinality); for (int i=0;i<cardinality;i++) { if (fieldIndicesToSkip.size()==0) { basisCoefficients(cellIndex,i) = x(i); } else { int i_filtered = oldToNewIndices[i]; if (i_filtered==-1) { basisCoefficients(cellIndex,i) = 0.0; } else { basisCoefficients(cellIndex,i) = x(i_filtered); } } } } }
bool FunctionTests::testValuesDottedWithTensor() { bool success = true; vector< FunctionPtr > vectorFxns; double xValue = 3, yValue = 4; FunctionPtr simpleVector = Function::vectorize(Function::constant(xValue), Function::constant(yValue)); vectorFxns.push_back(simpleVector); FunctionPtr x = Function::xn(1); FunctionPtr y = Function::yn(1); vectorFxns.push_back( Function::vectorize(x*x, x*y) ); VGPStokesFormulation vgpStokes = VGPStokesFormulation(1.0); BFPtr bf = vgpStokes.bf(); int h1Order = 1; MeshPtr mesh = MeshFactory::quadMesh(bf, h1Order); int cellID=0; // the only cell BasisCachePtr basisCache = BasisCache::basisCacheForCell(mesh, cellID); for (int i=0; i<vectorFxns.size(); i++) { FunctionPtr vectorFxn_i = vectorFxns[i]; for (int j=0; j<vectorFxns.size(); j++) { FunctionPtr vectorFxn_j = vectorFxns[j]; FunctionPtr dotProduct = vectorFxn_i * vectorFxn_j; FunctionPtr expectedDotProduct = vectorFxn_i->x() * vectorFxn_j->x() + vectorFxn_i->y() * vectorFxn_j->y(); if (! expectedDotProduct->equals(dotProduct, basisCache)) { cout << "testValuesDottedWithTensor() failed: expected dot product does not match dotProduct.\n"; success = false; double tol = 1e-14; reportFunctionValueDifferences(dotProduct, expectedDotProduct, basisCache, tol); } } } // now, let's try the same thing, but for a LinearTerm dot product VarFactoryPtr vf = VarFactory::varFactory(); VarPtr v = vf->testVar("v", HGRAD); DofOrderingPtr dofOrdering = Teuchos::rcp( new DofOrdering(CellTopology::quad()) ); shards::CellTopology quad_4(shards::getCellTopologyData<shards::Quadrilateral<4> >() ); BasisPtr basis = BasisFactory::basisFactory()->getBasis(h1Order, quad_4.getKey(), Camellia::FUNCTION_SPACE_HGRAD); dofOrdering->addEntry(v->ID(), basis, v->rank()); int numCells = 1; int numFields = basis->getCardinality(); for (int i=0; i<vectorFxns.size(); i++) { FunctionPtr f_i = vectorFxns[i]; LinearTermPtr lt_i = f_i * v; LinearTermPtr lt_i_x = f_i->x() * v; LinearTermPtr lt_i_y = f_i->y() * v; for (int j=0; j<vectorFxns.size(); j++) { FunctionPtr f_j = vectorFxns[j]; LinearTermPtr lt_j = f_j * v; LinearTermPtr lt_j_x = f_j->x() * v; LinearTermPtr lt_j_y = f_j->y() * v; FieldContainer<double> values(numCells,numFields,numFields); lt_i->integrate(values, dofOrdering, lt_j, dofOrdering, basisCache); FieldContainer<double> values_expected(numCells,numFields,numFields); lt_i_x->integrate(values_expected,dofOrdering,lt_j_x,dofOrdering,basisCache); lt_i_y->integrate(values_expected,dofOrdering,lt_j_y,dofOrdering,basisCache); double tol = 1e-14; double maxDiff = 0; if (!fcsAgree(values, values_expected, tol, maxDiff)) { cout << "FunctionTests::testValuesDottedWithTensor: "; cout << "dot product and sum of the products of scalar components differ by maxDiff " << maxDiff; cout << " in LinearTerm::integrate().\n"; success = false; } } } // // finally, let's try the same sort of thing, but now with a vector-valued basis // BasisPtr vectorBasisTemp = BasisFactory::basisFactory()->getBasis(h1Order, quad_4.getKey(), Camellia::FUNCTION_SPACE_VECTOR_HGRAD); // VectorBasisPtr vectorBasis = Teuchos::rcp( (VectorizedBasis<double, FieldContainer<double> > *)vectorBasisTemp.get(),false); // // BasisPtr compBasis = vectorBasis->getComponentBasis(); // // // create a new v, and a new dofOrdering // VarPtr v_vector = vf->testVar("v_vector", VECTOR_HGRAD); // dofOrdering = Teuchos::rcp( new DofOrdering ); // dofOrdering->addEntry(v_vector->ID(), vectorBasis, v_vector->rank()); // // DofOrderingPtr dofOrderingComp = Teuchos::rcp( new DofOrdering ); // dofOrderingComp->addEntry(v->ID(), compBasis, v->rank()); // return success; }
PreviousSolutionFunction<Scalar>::PreviousSolutionFunction(TSolutionPtr<Scalar> soln, VarPtr var, bool multiplyFluxesByCellParity) : TFunction<Scalar>(var->rank()) { _soln = soln; _solnExpression = 1.0 * var; _overrideMeshCheck = false; if ((var->varType() == FLUX) && multiplyFluxesByCellParity) { TFunctionPtr<double> parity = TFunction<double>::sideParity(); _solnExpression = parity * var; } }
PreviousSolutionFunction::PreviousSolutionFunction(SolutionPtr soln, VarPtr var, bool multiplyFluxesByCellParity) : Function(var->rank()) { _soln = soln; _solnExpression = 1.0 * var; _overrideMeshCheck = false; if ((var->varType() == FLUX) && multiplyFluxesByCellParity) { FunctionPtr parity = Teuchos::rcp( new SideParityFunction ); _solnExpression = parity * var; } }