void PreviousSolutionFunction::values(FieldContainer<double> &values, BasisCachePtr basisCache) { int rank = Teuchos::GlobalMPISession::getRank(); if (_overrideMeshCheck) { _solnExpression->evaluate(values, _soln, basisCache); return; } if (!basisCache.get()) cout << "basisCache is nil!\n"; if (!_soln.get()) cout << "_soln is nil!\n"; // values are stored in (C,P,D) order if (basisCache->mesh().get() == _soln->mesh().get()) { _solnExpression->evaluate(values, _soln, basisCache); } else { static bool warningIssued = false; if (!warningIssued) { if (rank==0) cout << "NOTE: In PreviousSolutionFunction, basisCache's mesh doesn't match solution's. If this is not what you intended, it would be a good idea to make sure that the mesh is passed in on BasisCache construction; the evaluation will be a lot slower without it...\n"; warningIssued = true; } // get the physicalPoints, and make a basisCache for each... FieldContainer<double> physicalPoints = basisCache->getPhysicalCubaturePoints(); FieldContainer<double> value(1,1); // assumes scalar-valued solution function. int numCells = physicalPoints.dimension(0); int numPoints = physicalPoints.dimension(1); int spaceDim = physicalPoints.dimension(2); physicalPoints.resize(numCells*numPoints,spaceDim); vector< ElementPtr > elements = _soln->mesh()->elementsForPoints(physicalPoints, false); // false: don't make elements null just because they're off-rank. FieldContainer<double> point(1,spaceDim); FieldContainer<double> refPoint(1,spaceDim); int combinedIndex = 0; vector<GlobalIndexType> cellID; cellID.push_back(-1); BasisCachePtr basisCacheOnePoint; for (int cellIndex=0; cellIndex<numCells; cellIndex++) { for (int ptIndex=0; ptIndex<numPoints; ptIndex++, combinedIndex++) { if (elements[combinedIndex].get()==NULL) continue; // no element found for point; skip it… ElementTypePtr elemType = elements[combinedIndex]->elementType(); for (int d=0; d<spaceDim; d++) { point(0,d) = physicalPoints(combinedIndex,d); } if (elements[combinedIndex]->cellID() != cellID[0]) { cellID[0] = elements[combinedIndex]->cellID(); basisCacheOnePoint = Teuchos::rcp( new BasisCache(elemType, _soln->mesh()) ); basisCacheOnePoint->setPhysicalCellNodes(_soln->mesh()->physicalCellNodesForCell(cellID[0]),cellID,false); // false: don't createSideCacheToo } // compute the refPoint: typedef CellTools<double> CellTools; int whichCell = 0; CellTools::mapToReferenceFrame(refPoint,point,_soln->mesh()->physicalCellNodesForCell(cellID[0]), *(elemType->cellTopoPtr),whichCell); basisCacheOnePoint->setRefCellPoints(refPoint); // cout << "refCellPoints:\n " << refPoint; // cout << "physicalCubaturePoints:\n " << basisCacheOnePoint->getPhysicalCubaturePoints(); _solnExpression->evaluate(value, _soln, basisCacheOnePoint); // cout << "value at point (" << point(0,0) << ", " << point(0,1) << ") = " << value(0,0) << endl; values(cellIndex,ptIndex) = value(0,0); } } } }
void values(FieldContainer<double> &values, BasisCachePtr basisCache) { // sets values(_cellIndex,P,D) TEUCHOS_TEST_FOR_EXCEPTION(_cellIndex == -1, std::invalid_argument, "must call setCellIndex before calling values!"); // cout << "_basisCoefficients:\n" << _basisCoefficients; BasisCachePtr spaceTimeBasisCache; if (basisCache->cellTopologyIsSpaceTime()) { // then we require that the basisCache provided be a space-time basis cache SpaceTimeBasisCache* spaceTimeCache = dynamic_cast<SpaceTimeBasisCache*>(basisCache.get()); TEUCHOS_TEST_FOR_EXCEPTION(!spaceTimeCache, std::invalid_argument, "space-time requires a SpaceTimeBasisCache"); spaceTimeBasisCache = basisCache; basisCache = spaceTimeCache->getSpatialBasisCache(); } int numDofs = _basis->getCardinality(); int spaceDim = basisCache->getSpaceDim(); bool basisIsVolumeBasis = (spaceDim == _basis->domainTopology()->getDimension()); bool useCubPointsSideRefCell = basisIsVolumeBasis && basisCache->isSideCache(); int numPoints = values.dimension(1); // check if we're taking a temporal derivative int component; Intrepid::EOperator relatedOp = BasisEvaluation::relatedOperator(_op, _basis->functionSpace(), spaceDim, component); if ((relatedOp == Intrepid::OPERATOR_GRAD) && (component==spaceDim)) { // then we are taking the temporal part of the Jacobian of the reference to curvilinear-reference space // based on our assumptions that curvilinearity is just in the spatial direction (and is orthogonally extruded in the // temporal direction), this is always the identity. for (int ptIndex=0; ptIndex<numPoints; ptIndex++) { for (int d=0; d<values.dimension(2); d++) { if (d < spaceDim) values(_cellIndex,ptIndex,d) = 0.0; else values(_cellIndex,ptIndex,d) = 1.0; } } return; } constFCPtr transformedValues = basisCache->getTransformedValues(_basis, _op, useCubPointsSideRefCell); // transformedValues has dimensions (C,F,P,[D,D]) // therefore, the rank of the sum is transformedValues->rank() - 3 int rank = transformedValues->rank() - 3; TEUCHOS_TEST_FOR_EXCEPTION(rank != values.rank()-2, std::invalid_argument, "values rank is incorrect."); int spaceTimeSideOrdinal = (spaceTimeBasisCache != Teuchos::null) ? spaceTimeBasisCache->getSideIndex() : -1; // I'm pretty sure much of this treatment of the time dimension could be simplified by taking advantage of SpaceTimeBasisCache::getTemporalBasisCache()... double t0 = -1, t1 = -1; if ((spaceTimeSideOrdinal != -1) && (!spaceTimeBasisCache->cellTopology()->sideIsSpatial(spaceTimeSideOrdinal))) { unsigned sideTime0 = spaceTimeBasisCache->cellTopology()->getTemporalSideOrdinal(0); unsigned sideTime1 = spaceTimeBasisCache->cellTopology()->getTemporalSideOrdinal(1); // get first node of each of the time-orthogonal sides, and use that to determine t0 and t1: unsigned spaceTimeNodeTime0 = spaceTimeBasisCache->cellTopology()->getNodeMap(spaceDim, sideTime0, 0); unsigned spaceTimeNodeTime1 = spaceTimeBasisCache->cellTopology()->getNodeMap(spaceDim, sideTime1, 0); t0 = spaceTimeBasisCache->getPhysicalCellNodes()(_cellIndex,spaceTimeNodeTime0,spaceDim); t1 = spaceTimeBasisCache->getPhysicalCellNodes()(_cellIndex,spaceTimeNodeTime1,spaceDim); } // initialize the values we're responsible for setting if (_op == OP_VALUE) { for (int ptIndex=0; ptIndex<numPoints; ptIndex++) { for (int d=0; d<values.dimension(2); d++) { if (d < spaceDim) values(_cellIndex,ptIndex,d) = 0.0; else if ((spaceTimeBasisCache != Teuchos::null) && (spaceTimeSideOrdinal == -1)) values(_cellIndex,ptIndex,spaceDim) = spaceTimeBasisCache->getPhysicalCubaturePoints()(_cellIndex,ptIndex,spaceDim); else if ((spaceTimeBasisCache != Teuchos::null) && (spaceTimeSideOrdinal != -1)) { if (spaceTimeBasisCache->cellTopology()->sideIsSpatial(spaceTimeSideOrdinal)) { values(_cellIndex,ptIndex,spaceDim) = spaceTimeBasisCache->getPhysicalCubaturePoints()(_cellIndex,ptIndex,spaceDim-1); } else { double temporalPoint; unsigned temporalNode = spaceTimeBasisCache->cellTopology()->getTemporalComponentSideOrdinal(spaceTimeSideOrdinal); if (temporalNode==0) temporalPoint = t0; else temporalPoint = t1; values(_cellIndex,ptIndex,spaceDim) = temporalPoint; } } } } } else if ((_op == OP_DX) || (_op == OP_DY) || (_op == OP_DZ)) { for (int ptIndex=0; ptIndex<numPoints; ptIndex++) { for (int d=0; d<values.dimension(2); d++) { if (d < spaceDim) values(_cellIndex,ptIndex,d) = 0.0; else if (_op == OP_DZ) values(_cellIndex,ptIndex,d) = 1.0; else values(_cellIndex,ptIndex,d) = 0.0; } } } else { TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "Unhandled _op"); } int numSpatialPoints = transformedValues->dimension(2); int numTemporalPoints = numPoints / numSpatialPoints; TEUCHOS_TEST_FOR_EXCEPTION(numTemporalPoints * numSpatialPoints != numPoints, std::invalid_argument, "numPoints is not evenly divisible by numSpatialPoints"); for (int i=0; i<numDofs; i++) { double weight = _basisCoefficients(i); for (int timePointOrdinal=0; timePointOrdinal<numTemporalPoints; timePointOrdinal++) { for (int spacePointOrdinal=0; spacePointOrdinal<numSpatialPoints; spacePointOrdinal++) { int spaceTimePointOrdinal = TENSOR_POINT_ORDINAL(spacePointOrdinal, timePointOrdinal, numSpatialPoints); for (int d=0; d<spaceDim; d++) { values(_cellIndex,spaceTimePointOrdinal,d) += weight * (*transformedValues)(_cellIndex,i,spacePointOrdinal,d); } } } } }