예제 #1
0
void DofOrdering::copyLikeCoefficients( FieldContainer<double> &newValues, Teuchos::RCP<DofOrdering> oldDofOrdering,
                          const FieldContainer<double> &oldValues ) {
  // copy the coefficients for the bases that agree between the two DofOrderings
  // requires that "like" bases are actually pointers to the same memory location
  TEUCHOS_TEST_FOR_EXCEPTION( newValues.rank() != 1, std::invalid_argument, "newValues.rank() != 1");
  TEUCHOS_TEST_FOR_EXCEPTION( newValues.size() != totalDofs(), std::invalid_argument, "newValues.size() != totalDofs()");
  TEUCHOS_TEST_FOR_EXCEPTION( oldValues.rank() != 1, std::invalid_argument, "oldValues.rank() != 1");
  TEUCHOS_TEST_FOR_EXCEPTION( oldValues.size() != oldDofOrdering->totalDofs(), std::invalid_argument, "oldValues.size() != oldDofOrdering->totalDofs()");
  
  newValues.initialize(0.0);
  
  for (set<int>::iterator varIDIt = varIDs.begin(); varIDIt != varIDs.end(); varIDIt++) {
    int varID = *varIDIt;
    int numSides = getNumSidesForVarID(varID);
    if ( numSides == oldDofOrdering->getNumSidesForVarID(varID) ) {
      for (int sideIndex=0; sideIndex < numSides; sideIndex++) {
        BasisPtr basis = getBasis(varID,sideIndex);
        if (basis.get() == oldDofOrdering->getBasis(varID,sideIndex).get() ) {
          // bases alike: copy coefficients
          int cardinality = basis->getCardinality();
          for (int dofOrdinal=0; dofOrdinal < cardinality; dofOrdinal++) {
            int dofIndex = getDofIndex(varID,dofOrdinal,sideIndex);
            newValues(dofIndex) = oldValues( oldDofOrdering->getDofIndex(varID,dofOrdinal,sideIndex) );
          }
        }
      }
    }
  }
}
예제 #2
0
int DofOrdering::getDofIndex(int varID, int basisDofOrdinal, int sideIndex, int subSideIndex) { 
  TEUCHOS_TEST_FOR_EXCEPTION( ( _indexNeedsToBeRebuilt ),
                     std::invalid_argument,
                     "getDofIndex called when _indexNeedsToBeRebuilt = true.  Call rebuildIndex() first.");
  if (subSideIndex >= 0) {
    // then we've got a MultiBasis, and the basisDofOrdinal we have is *relative* to the subbasis
    BasisPtr basis = getBasis(varID,sideIndex);
    if ( ! BasisFactory::basisFactory()->isMultiBasis(basis) ) {
      TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "subSideIndex >= 0 for non-MultiBasis...");
    }
    MultiBasis<>* multiBasis = (MultiBasis<>*) basis.get();
    //cout << "(basisDofOrdinal, subSideIndex) : (" << basisDofOrdinal << ", " << subSideIndex << ") --> ";
    basisDofOrdinal = multiBasis->relativeToAbsoluteDofOrdinal(basisDofOrdinal,subSideIndex);
    //cout << basisDofOrdinal << endl;
  }
  
  pair<int,int> key = make_pair(varID, sideIndex);
  map< pair<int,int>, vector<int> >::iterator entryIt = indices.find(key);
  if ( entryIt != indices.end() ) {
    int dofIndex = ((*entryIt).second)[basisDofOrdinal];
    if ((dofIndex < 0) || (dofIndex >= _nextIndex)) {
      cout << "dofIndex out of bounds.\n";
      TEUCHOS_TEST_FOR_EXCEPTION( (dofIndex < 0) || (dofIndex >= _nextIndex), std::invalid_argument, "dofIndex out of bounds.");
    }
    return dofIndex;
  } else {
    cout << "No entry found for dofIndex\n";
    TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "No entry found for DofIndex.");
    return -1;
  }
}
예제 #3
0
int DofOrdering::getTotalBasisCardinality() { // total number of *distinct* basis functions
  int totalBasisCardinality = 0;
  set< ::Camellia::Basis<>* > basesCounted;
  for (map< pair<int, int>, BasisPtr >::iterator basisIt = bases.begin(); basisIt != bases.end(); basisIt++) {
    BasisPtr basis = basisIt->second;
    if (basesCounted.find(basis.get())==basesCounted.end()) {
      basesCounted.insert(basis.get());
      totalBasisCardinality += basis->getCardinality();
    }
  }
  return totalBasisCardinality;
}
VectorBasisPtr basisForTransformation(ElementTypePtr cellType)
{
  // int polyOrder = std::max(cellType->trialOrderPtr->maxBasisDegree(), cellType->testOrderPtr->maxBasisDegree());
  int polyOrder = cellType->trialOrderPtr->maxBasisDegree();

  CellTopoPtr cellTopo = cellType->cellTopoPtr;
  if (cellTopo->getTensorialDegree() > 0)
  {
    // for now, we assume that this means space-time.  (At some point, we may support tensor-product spatial cell topologies for
    // things like fast quadrature support, and this would need revisiting then.)
    // we also assume that the curvilinearity is purely spatial (and in fact, just 2D for now).
    cellTopo = CellTopology::cellTopology(cellTopo->getShardsTopology(), cellTopo->getTensorialDegree() - 1);
  }

  BasisPtr basis = BasisFactory::basisFactory()->getBasis(polyOrder, cellTopo, Camellia::FUNCTION_SPACE_VECTOR_HGRAD);
  VectorBasisPtr vectorBasis = Teuchos::rcp( (VectorizedBasis<> *)basis.get(),false); // dynamic cast would be better
  return vectorBasis;
}
bool VectorizedBasisTestSuite::testVectorizedBasis()
{
  bool success = true;

  string myName = "testVectorizedBasis";

  shards::CellTopology quad_4(shards::getCellTopologyData<shards::Quadrilateral<4> >() );

  int polyOrder = 3, numPoints = 5, spaceDim = 2;

  BasisPtr hgradBasis = BasisFactory::basisFactory()->getBasis(polyOrder, quad_4.getKey(), Camellia::FUNCTION_SPACE_HGRAD);

  // first test: make a single-component vector basis.  This should agree in every entry with the basis itself, but its field container will have one higher rank...
  VectorizedBasis<> oneComp(hgradBasis, 1);

  FieldContainer<double> linePoints(numPoints, spaceDim);
  for (int i=0; i<numPoints; i++)
  {
    for (int j=0; j<spaceDim; j++)
    {
      linePoints(i,j) = ((double)(i + j)) / (numPoints + spaceDim);
    }
  }

  FieldContainer<double> compValues(hgradBasis->getCardinality(),numPoints);
  hgradBasis->getValues(compValues, linePoints, Intrepid::OPERATOR_VALUE);

  FieldContainer<double> values(hgradBasis->getCardinality(),linePoints.dimension(0),1); // one component
  oneComp.getValues(values, linePoints, Intrepid::OPERATOR_VALUE);

  for (int i=0; i<compValues.size(); i++)
  {
    double diff = abs(values[i]-compValues[i]);
    if (diff != 0.0)
    {
      success = false;
      cout << myName << ": one-component vector basis doesn't produce same values as component basis." << endl;
      cout << "difference: " << diff << " in enumerated value " << i << endl;
      cout << "values:\n" << values;
      cout << "compValues:\n" << compValues;
      return success;
    }
  }

  vector< BasisPtr > twoComps;
  twoComps.push_back( Teuchos::rcp( new VectorizedBasis<>(hgradBasis, 2) ) );
  twoComps.push_back( BasisFactory::basisFactory()->getBasis( polyOrder,
                      quad_4.getKey(), Camellia::FUNCTION_SPACE_VECTOR_HGRAD) );


  vector< BasisPtr >::iterator twoCompIt;
  for (twoCompIt = twoComps.begin(); twoCompIt != twoComps.end(); twoCompIt++)
  {
    BasisPtr twoComp = *twoCompIt;

    int componentCardinality = hgradBasis->getCardinality();

    if (twoComp->getCardinality() != 2 * hgradBasis->getCardinality() )
    {
      success = false;
      cout << myName << ": two-component vector basis cardinality != one-component cardinality * 2." << endl;
      cout << "twoComp->getCardinality(): " << twoComp->getCardinality() << endl;
      cout << "oneComp->getCardinality(): " << oneComp.getCardinality() << endl;
    }

    values.resize(twoComp->getCardinality(),linePoints.dimension(0),2); // two components
    twoComp->getValues(values, linePoints, Intrepid::OPERATOR_VALUE);
    for (int basisIndex=0; basisIndex<twoComp->getCardinality(); basisIndex++)
    {
      for (int k=0; k<numPoints; k++)
      {
        double xValueExpected = (basisIndex < componentCardinality) ? compValues(basisIndex,k) : 0;
        double xValueActual = values(basisIndex,k,0);
        double yValueExpected = (basisIndex >= componentCardinality) ? compValues(basisIndex - componentCardinality,k) : 0;
        double yValueActual = values(basisIndex,k,1);
        if ( ( abs(xValueActual - xValueExpected) != 0) || ( abs(yValueActual - yValueExpected) != 0) )
        {
          success = false;
          cout << myName << ": expected differs from actual\n";
          cout << "component\n" << compValues;
          cout << "vector values:\n" << values;
          return success;
        }
      }
    }

    // test the mapping from oneComp dofOrdinal to twoComp:
    VectorizedBasis<>* twoCompAsVectorBasis = (VectorizedBasis<>  *) twoComp.get();

    for (int compDofOrdinal=0; compDofOrdinal<oneComp.getCardinality(); compDofOrdinal++)
    {
      int dofOrdinal_0 = twoCompAsVectorBasis->getDofOrdinalFromComponentDofOrdinal(compDofOrdinal, 0);
      int dofOrdinal_1 = twoCompAsVectorBasis->getDofOrdinalFromComponentDofOrdinal(compDofOrdinal, 1);
      // we expect the lists to be stacked (this is implicit in the test above)
      // dofOrdinal_0 we expect to be == compDofOrdinal
      // dofOrdinal_1 we expect to be == compDofOrdinal + oneComp.getCardinality()
      if (dofOrdinal_0 != compDofOrdinal)
      {
        success = false;
        cout << "getDofOrdinalFromComponentDofOrdinal() not returning expected value in first component.\n";
      }
      if (dofOrdinal_1 != compDofOrdinal + oneComp.getCardinality())
      {
        success = false;
        cout << "getDofOrdinalFromComponentDofOrdinal() not returning expected value in second component.\n";
      }
    }

    // finally, test the ordering of gradient values
    // these should be in the order f_i,j
    FieldContainer<double> compGradValues(hgradBasis->getCardinality(),numPoints,spaceDim);
    FieldContainer<double> vectorGradValues(twoComp->getCardinality(),numPoints,spaceDim,spaceDim);

    hgradBasis->getValues(compGradValues, linePoints, OPERATOR_GRAD);
    twoCompAsVectorBasis->getValues(vectorGradValues, linePoints, OPERATOR_GRAD);

    for (int compDofOrdinal=0; compDofOrdinal<oneComp.getCardinality(); compDofOrdinal++)
    {
      for (int comp=0; comp<2; comp++)
      {
        int vectorDofOrdinal = twoCompAsVectorBasis->getDofOrdinalFromComponentDofOrdinal(compDofOrdinal, comp);
        for (int k=0; k<numPoints; k++)
        {
          double dfi_d0_expected = compGradValues(compDofOrdinal,k,0); // i: the comp index
          double dfi_d1_expected = compGradValues(compDofOrdinal,k,1);

          double dfi_d0_actual = vectorGradValues(vectorDofOrdinal,k,comp,0);
          double dfi_d1_actual = vectorGradValues(vectorDofOrdinal,k,comp,1);

          if ( ( abs(dfi_d0_expected - dfi_d0_actual) != 0) || ( abs(dfi_d1_expected - dfi_d1_actual) != 0) )
          {
            success = false;
            cout << myName << ": expected gradient differs from actual\n";
            cout << "component grad values\n" << compGradValues;
            cout << "vector grad values:\n" << vectorGradValues;
            return success;
          }
        }
      }

    }


  }
  return success;
}
예제 #6
0
void ParametricSurface::basisWeightsForEdgeInterpolant(FieldContainer<double> &edgeInterpolationCoefficients,
    VectorBasisPtr basis,
    MeshPtr mesh, int cellID)
{
  vector< ParametricCurvePtr > curves = mesh->parametricEdgesForCell(cellID);
  Teuchos::RCP<TransfiniteInterpolatingSurface> exactSurface = Teuchos::rcp( new TransfiniteInterpolatingSurface(curves) );
  exactSurface->setNeglectVertices(false);

  int basisDegree = basis->getDegree();
  shards::CellTopology line_2(shards::getCellTopologyData<shards::Line<2> >() );
  BasisPtr basis1D = BasisFactory::basisFactory()->getBasis(basisDegree, line_2.getKey(),
                     Camellia::FUNCTION_SPACE_HGRAD);

  BasisPtr compBasis = basis->getComponentBasis();
  int numComponents = basis->getNumComponents();
  if (numComponents != 2)
  {
    TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "Only 2D surfaces supported right now");
  }

  edgeInterpolationCoefficients.resize(basis->getCardinality());

  set<int> edgeNodeFieldIndices = BasisFactory::basisFactory()->sideFieldIndices(basis,true); // true: include vertex dofs

  FieldContainer<double> dofCoords(compBasis->getCardinality(),2);
  IntrepidBasisWrapper< double, Intrepid::FieldContainer<double> >* intrepidBasisWrapper = dynamic_cast< IntrepidBasisWrapper< double, Intrepid::FieldContainer<double> >* >(compBasis.get());
  if (!intrepidBasisWrapper)
  {
    TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "compBasis does not appear to be an instance of IntrepidBasisWrapper");
  }
  Basis_HGRAD_QUAD_Cn_FEM<double, Intrepid::FieldContainer<double> >* intrepidBasis = dynamic_cast< Basis_HGRAD_QUAD_Cn_FEM<double, Intrepid::FieldContainer<double> >* >(intrepidBasisWrapper->intrepidBasis().get());
  if (!intrepidBasis)
  {
    TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "IntrepidBasisWrapper does not appear to wrap Basis_HGRAD_QUAD_Cn_FEM.");
  }
  intrepidBasis->getDofCoords(dofCoords);

  int edgeDim = 1;
  int vertexDim = 0;

  // set vertex dofs:
  for (int vertexIndex=0; vertexIndex<curves.size(); vertexIndex++)
  {
    double x = exactSurface->vertices()[vertexIndex].first;
    double y = exactSurface->vertices()[vertexIndex].second;
    int compDofOrdinal = compBasis->getDofOrdinal(vertexDim, vertexIndex, 0);
    int basisDofOrdinal_x = basis->getDofOrdinalFromComponentDofOrdinal(compDofOrdinal, 0);
    int basisDofOrdinal_y = basis->getDofOrdinalFromComponentDofOrdinal(compDofOrdinal, 1);
    edgeInterpolationCoefficients[basisDofOrdinal_x] = x;
    edgeInterpolationCoefficients[basisDofOrdinal_y] = y;
  }

  for (int edgeIndex=0; edgeIndex<curves.size(); edgeIndex++)
  {
    bool edgeDofsFlipped = edgeIndex >= 2; // because Intrepid's ordering of dofs on the quad is not CCW but tensor-product, we need to flip for the opposite edges
    // (what makes things worse is that the vertex/edge numbering *is* CCW)
    if (curves.size() != 4)
    {
      cout << "WARNING: have not worked out the rule for flipping or not flipping edge dofs for anything but quads.\n";
    }
    double edgeLength = curves[edgeIndex]->linearLength();

    //    cout << "edgeIndex " << edgeIndex << endl;
    for (int comp=0; comp<numComponents; comp++)
    {
      FieldContainer<double> basisCoefficients_comp;
      bool useH1ForEdgeInterpolant = true; // an experiment
      curves[edgeIndex]->projectionBasedInterpolant(basisCoefficients_comp, basis1D, comp, edgeLength, useH1ForEdgeInterpolant);
      //      cout << "for edge " << edgeIndex << " and comp " << comp << ", projection-based interpolant dofs:\n";
      //      cout << basisCoefficients_comp;
      ////      cout << "basis dof coords:\n" << dofCoords;
      //      int basisDofOrdinal = basis->getDofOrdinalFromComponentDofOrdinal(v0_dofOrdinal_comp, comp);
      //      edgeInterpolationCoefficients[basisDofOrdinal] = basisCoefficients_comp[v0_dofOrdinal_1D];

      if (compBasis->getDegree() >= 2)   // then there are some "middle" nodes on the edge
      {
        // get the first dofOrdinal for the edge, so we can check the number of edge basis functions
        int firstEdgeDofOrdinal = compBasis->getDofOrdinal(edgeDim, edgeIndex, 0);

        //        cout << "first edge dofOrdinal: " << firstEdgeDofOrdinal << endl;

        int numEdgeDofs = compBasis->getDofTag(firstEdgeDofOrdinal)[3];
        if (numEdgeDofs != basis1D->getCardinality() - 2)
        {
          TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "numEdgeDofs does not match 1D basis cardinality");
        }
        for (int edgeDofOrdinal=0; edgeDofOrdinal<numEdgeDofs; edgeDofOrdinal++)
        {
          // determine the index into basisCoefficients_comp:
          int edgeDofOrdinalIn1DBasis = edgeDofsFlipped ? numEdgeDofs - 1 - edgeDofOrdinal : edgeDofOrdinal;
          int dofOrdinal1D = basis1D->getDofOrdinal(edgeDim, 0, edgeDofOrdinalIn1DBasis);
          // determine the ordinal of the edge dof in the component basis:
          int compDofOrdinal = compBasis->getDofOrdinal(edgeDim, edgeIndex, edgeDofOrdinal);
          // now, determine its ordinal in the vector basis
          int basisDofOrdinal = basis->getDofOrdinalFromComponentDofOrdinal(compDofOrdinal, comp);

          //          cout << "edge dof ordinal " << edgeDofOrdinal << " has basis weight " << basisCoefficients_comp[dofOrdinal1D] << " for component " << comp << endl;
          //          cout << "node on cell is at (" << dofCoords(compDofOrdinal,0) << ", " << dofCoords(compDofOrdinal,1) << ")\n";
          //          cout << "mapping to basisDofOrdinal " << basisDofOrdinal << endl;

          edgeInterpolationCoefficients[basisDofOrdinal] = basisCoefficients_comp[dofOrdinal1D];
        }
      }
    }
  }
  edgeInterpolationCoefficients.resize(edgeInterpolationCoefficients.size());

  // print out a report of what the edge interpolation is doing:
  /*cout << "projection-based interpolation of edges maps the following points:\n";
  for (int compDofOrdinal=0; compDofOrdinal<compBasis->getCardinality(); compDofOrdinal++) {
    double x_ref = dofCoords(compDofOrdinal,0);
    double y_ref = dofCoords(compDofOrdinal,1);
    int basisDofOrdinal_x = basis->getDofOrdinalFromComponentDofOrdinal(compDofOrdinal, 0);
    int basisDofOrdinal_y = basis->getDofOrdinalFromComponentDofOrdinal(compDofOrdinal, 1);
    if (edgeNodeFieldIndices.find(basisDofOrdinal_x) != edgeNodeFieldIndices.end()) {
      double x_phys = edgeInterpolationCoefficients[basisDofOrdinal_x];
      double y_phys = edgeInterpolationCoefficients[basisDofOrdinal_y];
      cout << "(" << x_ref << ", " << y_ref << ") --> (" << x_phys << ", " << y_phys << ")\n";
    }
  }*/
}