void EricksonManufacturedSolution::rhs(int testVarID, const FieldContainer<double> &physicalPoints, FieldContainer<double> &values) {
  int numCells = physicalPoints.dimension(0);
  int numPoints = physicalPoints.dimension(1);
  int spaceDim = physicalPoints.dimension(2);
  if (testVarID == ConfusionBilinearForm::V) {
    // f = - eps * (d^2/dx^2 + d^2/dy^2) ( u ) + beta_x du/dx + beta_y du/dy
    values.resize(numCells,numPoints);
    for (int cellIndex=0; cellIndex<numCells; cellIndex++) {
      for (int ptIndex=0; ptIndex<numPoints; ptIndex++) {
        double x = physicalPoints(cellIndex,ptIndex,0);
        double y = physicalPoints(cellIndex,ptIndex,1);
        F2_2 sx(2,0,x), sy(2,1,y), su; // s for Sacado 
        sx.val() = F2(2,0,x);
        sy.val() = F2(2,1,y);
        su = u(sx,sy);

	/* these are values of convection-diffusion
	   values(cellIndex,ptIndex) = - _epsilon * ( su.dx(0).dx(0) + su.dx(1).dx(1) ) 
	   + _beta_x * su.dx(0).val() + _beta_y * su.dx(1).val();
	*/

	// this RHS corresponds to only convection
	//values(cellIndex,ptIndex) = _beta_x * su.dx(0).val() + _beta_y * su.dx(1).val();
	
	// exact RHS
	double pi = acos(0.0)*2.0;
	double epsSquared = _epsilon*_epsilon;
	//	values(cellIndex,ptIndex) = exp((1.0-x)/_epsilon)*(pi*pi - 2*epsSquared)*sin(pi*y/epsSquared)/(epsSquared*_epsilon);
	values(cellIndex,ptIndex) = 0.0;
	
      }
    }
  }
}
Пример #2
0
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);
      }
    }
  }
}
Пример #3
0
/** This example whows how to get vertex IDs for all the elements
  */
int main( int argc, char **argv )
{  
  using Teuchos::RCP;

  Teuchos::oblackholestream blackhole;
  Teuchos::GlobalMPISession mpiSession(&argc,&argv,&blackhole);

  RCP<const Teuchos::Comm<int> > comm = Teuchos::DefaultComm<int>::getComm();

  RCP<Teuchos::ParameterList> pl = rcp(new Teuchos::ParameterList);
  pl->set("X Blocks",2);
  pl->set("Y Blocks",1);
  pl->set("X Elements",6);
  pl->set("Y Elements",4);

  panzer_stk_classic::SquareQuadMeshFactory factory;
  factory.setParameterList(pl);
  RCP<panzer_stk_classic::STK_Interface> mesh = factory.buildMesh(MPI_COMM_WORLD);
  if(mesh->isWritable())
     mesh->writeToExodus("blocked_mesh.exo");
  unsigned dim = mesh->getDimension();

  std::vector<std::string> eBlocks; 
  mesh->getElementBlockNames(eBlocks);

  // loop over all blocks
  for(std::size_t blk=0;blk<eBlocks.size();++blk) {
     std::string blockName = eBlocks[blk];

     std::vector<stk_classic::mesh::Entity*> elements;
     std::vector<std::size_t> localIds;
     mesh->getMyElements(blockName,elements);

     FieldContainer vertices;
     vertices.resize(elements.size(),4,dim);  

     // loop over elements of this block
     for(std::size_t elm=0;elm<elements.size();++elm) {
        std::vector<stk_classic::mesh::EntityId> nodes;
        stk_classic::mesh::Entity * element = elements[elm];

        localIds.push_back(mesh->elementLocalId(element));
        getNodeIds(element,mesh->getNodeRank(),nodes);

        TEUCHOS_ASSERT(nodes.size()==4);

        for(std::size_t v=0;v<nodes.size();++v) {
           const double * coord = mesh->getNodeCoordinates(nodes[v]);
           
           for(unsigned d=0;d<dim;++d) 
              vertices(elm,v,d) = coord[d]; 
        }
     }
  }

  return 0;
}
Пример #4
0
void BilinearFormUtility::computeStiffnessMatrixForCell(FieldContainer<double> &stiffness, Teuchos::RCP<Mesh> mesh, int cellID) {
  Teuchos::RCP<DofOrdering> trialOrder = mesh->getElement(cellID)->elementType()->trialOrderPtr;
  Teuchos::RCP<DofOrdering> testOrder  = mesh->getElement(cellID)->elementType()->testOrderPtr;
  shards::CellTopology     cellTopo  = *(mesh->getElement(cellID)->elementType()->cellTopoPtr);
  FieldContainer<double> physicalCellNodes = mesh->physicalCellNodesForCell(cellID);
  FieldContainer<double> cellSideParities  = mesh->cellSideParitiesForCell(cellID);
  int numCells = 1;
  stiffness.resize(numCells,testOrder->totalDofs(),trialOrder->totalDofs());
  computeStiffnessMatrix(stiffness,mesh->bilinearForm(),trialOrder,testOrder,cellTopo,physicalCellNodes,cellSideParities);
}
Пример #5
0
void MPIWrapper::allGatherCompact(const Epetra_Comm &Comm, FieldContainer<Scalar> &gatheredValues,
                                  FieldContainer<Scalar> &myValues, FieldContainer<int> &offsets)
{
  int mySize = myValues.size();
  int totalSize;
  Comm.SumAll(&mySize, &totalSize, 1);

  int myOffset = 0;
  Comm.ScanSum(&mySize,&myOffset,1);

  myOffset -= mySize;

  gatheredValues.resize(totalSize);
  for (int i=0; i<mySize; i++)
  {
    gatheredValues[myOffset+i] = myValues[i];
  }
  MPIWrapper::entryWiseSum(Comm, gatheredValues);

  offsets.resize(Comm.NumProc());
  offsets[Comm.MyPID()] = myOffset;
  MPIWrapper::entryWiseSum(Comm, offsets);
}
Пример #6
0
void LinearTermTests::transposeFieldContainer(FieldContainer<double> &fc)
{
  // this is NOT meant for production code.  Could do the transpose in place if we were concerned with efficiency.
  FieldContainer<double> fcCopy = fc;
  int numCells = fc.dimension(0);
  int dim1 = fc.dimension(1);
  int dim2 = fc.dimension(2);
  fc.resize(numCells,dim2,dim1);
  for (int i=0; i<numCells; i++)
  {
    for (int j=0; j<dim1; j++)
    {
      for (int k=0; k<dim2; k++)
      {
        fc(i,k,j) = fcCopy(i,j,k);
      }
    }
  }
}
void EricksonManufacturedSolution::getValues(FieldContainer<double> &functionValues, const FieldContainer<double> &physicalPoints){
  int numCells = physicalPoints.dimension(0);
  int numPoints = physicalPoints.dimension(1);
  int spaceDim = physicalPoints.dimension(2);
  functionValues.resize(numCells,numPoints);

  Teuchos::Array<int> pointDimensions;
  pointDimensions.push_back(spaceDim);    
  for (int i=0;i<numCells;i++){
    for (int j=0;j<numPoints;j++){
      double x = physicalPoints(i,j,0);
      double y = physicalPoints(i,j,1);
      FieldContainer<double> physicalPoint(pointDimensions);
      physicalPoint(0) = x;
      physicalPoint(1) = y;
      
      functionValues(i,j) = solutionValue(ConfusionBilinearForm::U,physicalPoint);
    }
  }
  
}
Пример #8
0
int main(int argc, char *argv[]) {

  Teuchos::GlobalMPISession mpiSession(&argc, &argv);

  // This little trick lets us print to std::cout only if
  // a (dummy) command-line argument is provided.
  int iprint     = argc - 1;
  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing
  if (iprint > 0)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs, false);

  // Save the format state of the original std::cout.
  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);

  *outStream \
    << "===============================================================================\n" \
    << "|                                                                             |\n" \
    << "|             Unit Test (Basis_HGRAD_TET_COMP12_FEM)                          |\n" \
    << "|                                                                             |\n" \
    << "|     1) Evaluation of Basis Function Values                                  |\n" \
    << "|                                                                             |\n" \
    << "|  Questions? Contact  Pavel Bochev  ([email protected]),                    |\n" \
    << "|                      Denis Ridzal  ([email protected]),                    |\n" \
    << "|                      Kara Peterson ([email protected]),                    |\n" \
    << "|                      Jake Ostien   ([email protected]).                    |\n" \
    << "|                                                                             |\n" \
    << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n" \
    << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
    << "|                                                                             |\n" \
    << "===============================================================================\n"\
    << "| TEST 1: Basis creation, values                                              |\n"\
    << "===============================================================================\n";

  // Define basis and error flag
  Basis_HGRAD_TET_COMP12_FEM<double, FieldContainer<double> > tetBasis;
  int errorFlag = 0;

  // Initialize throw counter for exception testing
  //int nException     = 0;
  //int throwCounter   = 0;

  // Define array containing the 10 vertices of the reference TET
  FieldContainer<double> tetNodes(10, 3);
  tetNodes(0,0) = 0.0;  tetNodes(0,1) = 0.0;  tetNodes(0,2) = 0.0;
  tetNodes(1,0) = 1.0;  tetNodes(1,1) = 0.0;  tetNodes(1,2) = 0.0;
  tetNodes(2,0) = 0.0;  tetNodes(2,1) = 1.0;  tetNodes(2,2) = 0.0;
  tetNodes(3,0) = 0.0;  tetNodes(3,1) = 0.0;  tetNodes(3,2) = 1.0;
  tetNodes(4,0) = 0.5;  tetNodes(4,1) = 0.0;  tetNodes(4,2) = 0.0;
  tetNodes(5,0) = 0.5;  tetNodes(5,1) = 0.5;  tetNodes(5,2) = 0.0;
  tetNodes(6,0) = 0.0;  tetNodes(6,1) = 0.5;  tetNodes(6,2) = 0.0;
  tetNodes(7,0) = 0.0;  tetNodes(7,1) = 0.0;  tetNodes(7,2) = 0.5;
  tetNodes(8,0) = 0.5;  tetNodes(8,1) = 0.0;  tetNodes(8,2) = 0.5;
  tetNodes(9,0) = 0.0;  tetNodes(9,1) = 0.5;  tetNodes(9,2) = 0.5;
  // Define array containing 5 integration points
  FieldContainer<double> tetPoints(9, 3);
  // from the 5 point integration
  tetPoints(0,0) = 0.25;     tetPoints(0,1) = 0.25;     tetPoints(0,2) = 0.25;
  tetPoints(1,0) = 0.5;      tetPoints(1,1) = (1./6.);  tetPoints(1,2) = (1./6.);
  tetPoints(2,0) = (1./6.);  tetPoints(2,1) = 0.5;      tetPoints(2,2) = (1./6.);
  tetPoints(3,0) = (1./6.);  tetPoints(3,1) = (1./6.);  tetPoints(3,2) = 0.5;
  tetPoints(4,0) = (1./6.);  tetPoints(4,1) = (1./6.);  tetPoints(4,2) = (1./6.);
  // from the 4 point integration
  tetPoints(5,0) = 0.1381966011250105151795413165634361882280;
  tetPoints(5,1) = 0.1381966011250105151795413165634361882280;
  tetPoints(5,2) = 0.1381966011250105151795413165634361882280;

  tetPoints(6,0) = 0.5854101966249684544613760503096914353161;
  tetPoints(6,1) = 0.1381966011250105151795413165634361882280;
  tetPoints(6,2) = 0.1381966011250105151795413165634361882280;

  tetPoints(7,0) = 0.1381966011250105151795413165634361882280;
  tetPoints(7,1) = 0.5854101966249684544613760503096914353161;
  tetPoints(7,2) = 0.1381966011250105151795413165634361882280;

  tetPoints(8,0) = 0.1381966011250105151795413165634361882280;
  tetPoints(8,1) = 0.1381966011250105151795413165634361882280;
  tetPoints(8,2) = 0.5854101966249684544613760503096914353161;

  // output precision
  outStream -> precision(20);

  // VALUE: Each row gives the 10 correct basis set values at an evaluation point
  double nodalBasisValues[] = {
    // first 4 vertices
    1.0, 0.0, 0.0, 0.0,  0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 1.0, 0.0, 0.0,  0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 1.0, 0.0,  0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 1.0,  0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    // second 6 vertices
    0.0, 0.0, 0.0, 0.0,  1.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0,  0.0, 1.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0,  0.0, 0.0, 1.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0,  0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0,  0.0, 0.0, 0.0, 0.0, 1.0, 0.0,
    0.0, 0.0, 0.0, 0.0,  0.0, 0.0, 0.0, 0.0, 0.0, 1.0
  };
  double pointBasisValues[] = {
    // pt 0 {0.25, 0.25, 0.25}
    0.0, 0.0, 0.0, 0.0,  1./6., 1./6., 1./6., 1./6., 1./6., 1./6.,
    // pt 1 {0.5, 1/6, 1/6}
    0.0, 0.0, 0.0, 0.0,  1./3., 1./3., 0.0, 0.0, 1./3., 0.0,
    // pt 2 {1/6, 0.5, 0.1/6}
    0.0, 0.0, 0.0, 0.0,  0.0, 1./3., 1./3., 0.0, 0.0, 1./3.,
    // pt 3 {1/6, 1/6, 0.5}
    0.0, 0.0, 0.0, 0.0,  0.0, 0.0, 0.0, 1./3., 1./3., 1./3.,
    // pt 4 {1/6, 1/6, 1/6}
    0.0, 0.0, 0.0, 0.0,  1./3., 0.0, 1./3., 1./3., 0.0, 0.0,
    // pt 5
    0.170820393249936908922752100619382870632, 0.0, 0.0, 0.0, 0.276393202250021030359082633126872376456, 0.0, 0.276393202250021030359082633126872376456, 0.276393202250021030359082633126872376456, 0.0, 0.0,
    // pt 6
    0.0, 0.170820393249936908922752100619382870632, 0.0, 0.0, 0.276393202250021030359082633126872376456, 0.276393202250021030359082633126872376456, 0.0, 0.0, 0.276393202250021030359082633126872376456, 0.0,
    // pt 7
    0.0, 0.0, 0.170820393249936908922752100619382870632, 0.0, 0.0, 0.276393202250021030359082633126872376456, 0.276393202250021030359082633126872376456, 0.0, 0.0, 0.276393202250021030359082633126872376456,
    // pt 8
    0.0, 0.0, 0.0, 0.170820393249936908922752100619382870632, 0.0, 0.0, 0.0, 0.276393202250021030359082633126872376456, 0.276393202250021030359082633126872376456, 0.276393202250021030359082633126872376456,
  };

  // GRAD and D1: each row gives the 3x10 correct values of the gradients of the 10 basis functions
  double pointBasisGrads[] = {
    // point 0
      -1./4.,   -1./4.,   -1./4., \
       1./4.,      0.0,      0.0, \
         0.0,    1./4.,      0.0, \
         0.0,      0.0,    1./4., \
         0.0,   -3./4.,   -3./4., \
       3./4.,    3./4.,      0.0, \
      -3./4.,      0.0,   -3./4., \
      -3./4.,   -3./4.,      0.0, \
       3./4.,      0.0,    3./4., \
         0.0,    3./4.,    3./4., \

    // point 1
     -1./24.,  -1./24.,  -1./24., \
       7./8.,      0.0,      0.0, \
         0.0,   1./24.,      0.0, \
         0.0,      0.0,   1./24., \
    -35./36., -19./12., -19./12., \
     11./18.,  19./12.,      0.0, \
    -17./36.,      0.0,   -1./3., \
    -17./36.,   -1./3.,      0.0, \
     11./18.,      0.0,  19./12., \
     -5./36.,    1./3.,    1./3., \

    // point 2
     -1./24.,  -1./24.,  -1./24., \
      1./24.,      0.0,      0.0, \
         0.0,    7./8.,      0.0, \
         0.0,      0.0,   1./24., \
         0.0, -17./36.,   -1./3., \
     19./12.,  11./18.,      0.0, \
    -19./12., -35./36., -19./12., \
      -1./3., -17./36.,      0.0, \
       1./3.,  -5./36.,    1./3., \
         0.0,  11./18.,  19./12., \

    // point 3
     -1./24.,  -1./24.,  -1./24., \
      1./24.,      0.0,      0.0, \
         0.0,   1./24.,      0.0, \
         0.0,      0.0,    7./8., \
         0.0,   -1./3., -17./36., \
       1./3.,    1./3.,  -5./36., \
      -1./3.,      0.0, -17./36., \
    -19./12., -19./12., -35./36., \
     19./12.,      0.0,  11./18., \
         0.0,  19./12.,  11./18., \

    // point 4
      -7./8.,   -7./8.,   -7./8., \
      1./24.,      0.0,      0.0, \
         0.0,   1./24.,      0.0, \
         0.0,      0.0,   1./24., \
     35./36., -11./18., -11./18., \
     17./36.,  17./36.,   5./36., \
    -11./18.,  35./36., -11./18., \
    -11./18., -11./18.,  35./36., \
     17./36.,   5./36.,  17./36., \
      5./36.,  17./36.,  17./36., \

    // point 5
      -1.088525491562421136153440125774228588290, -1.088525491562421136153440125774228588290, -1.088525491562421136153440125774228588290, \
      -0.029508497187473712051146708591409529430, 0.0, 0.0, \
      0.0, -0.029508497187473712051146708591409529430, 0.0, \
      0.0, 0.0, -0.029508497187473712051146708591409529430, \
      1.30437298687487732290535130675991113734, -0.563661001875017525299235527605726980380, -0.563661001875017525299235527605726980380, \
      0.377322003750035050598471055211453960760, 0.377322003750035050598471055211453960760, 0.186338998124982474700764472394273019620, \
      -0.563661001875017525299235527605726980380, 1.30437298687487732290535130675991113734, -0.563661001875017525299235527605726980380, \
      -0.563661001875017525299235527605726980380, -0.563661001875017525299235527605726980380, 1.30437298687487732290535130675991113734, \
      0.377322003750035050598471055211453960760, 0.186338998124982474700764472394273019620, 0.377322003750035050598471055211453960760, \
      0.186338998124982474700764472394273019620, 0.377322003750035050598471055211453960760, 0.377322003750035050598471055211453960760, \

    // point 6
      0.029508497187473712051146708591409529430, 0.029508497187473712051146708591409529430, 0.029508497187473712051146708591409529430, \
      1.088525491562421136153440125774228588290, 0.0, 0.0, \
      0.0, -0.029508497187473712051146708591409529430, 0.0, \
      0.0, 0.0, -0.029508497187473712051146708591409529430, \
      -1.30437298687487732290535130675991113734, -1.868033988749894848204586834365638117720, -1.868033988749894848204586834365638117720, \
      0.563661001875017525299235527605726980380, 1.868033988749894848204586834365638117720, 0.0, \
      -0.377322003750035050598471055211453960760, 0.0, -0.190983005625052575897706582817180941140, \
      -0.377322003750035050598471055211453960760, -0.190983005625052575897706582817180941140, 0.0, \
      0.563661001875017525299235527605726980380, 0.0, 1.868033988749894848204586834365638117720, \
      -0.186338998124982474700764472394273019620, 0.190983005625052575897706582817180941140, 0.19098300562505257589770658281718094114, \

    // point 7
      0.029508497187473712051146708591409529430, 0.029508497187473712051146708591409529430, 0.029508497187473712051146708591409529430, \
      -0.029508497187473712051146708591409529430, 0.0, 0.0, \
      0.0, 1.088525491562421136153440125774228588290, 0.0, \
      0.0, 0.0, -0.029508497187473712051146708591409529430, \
      0.0, -0.377322003750035050598471055211453960760, -0.190983005625052575897706582817180941140, \
      1.868033988749894848204586834365638117720, 0.563661001875017525299235527605726980380, 0.0, \
      -1.868033988749894848204586834365638117720, -1.30437298687487732290535130675991113734, -1.868033988749894848204586834365638117720, \
      -0.190983005625052575897706582817180941140, -0.377322003750035050598471055211453960760, 0.0, \
      0.190983005625052575897706582817180941140, -0.186338998124982474700764472394273019620, 0.190983005625052575897706582817180941140, \
      0.0, 0.563661001875017525299235527605726980380, 1.868033988749894848204586834365638117720, \

    // point 8
      0.029508497187473712051146708591409529430, 0.029508497187473712051146708591409529430, 0.029508497187473712051146708591409529430, \
      -0.029508497187473712051146708591409529430, 0.0, 0.0, \
      0.0, -0.029508497187473712051146708591409529430, 0.0, \
      0.0, 0.0, 1.088525491562421136153440125774228588290, \
      0.0, -0.190983005625052575897706582817180941140, -0.377322003750035050598471055211453960760, \
      0.190983005625052575897706582817180941140, 0.190983005625052575897706582817180941140, -0.186338998124982474700764472394273019620, \
      -0.190983005625052575897706582817180941140, 0.0, -0.377322003750035050598471055211453960760, \
      -1.868033988749894848204586834365638117720, -1.868033988749894848204586834365638117720, -1.30437298687487732290535130675991113734,
      1.868033988749894848204586834365638117720, 0.0, 0.563661001875017525299235527605726980380, \
      0.0, 1.868033988749894848204586834365638117720, 0.563661001875017525299235527605726980380, \
  };

  try{

    // Dimensions for the output arrays:
    int numFields = tetBasis.getCardinality();
    int numNodes  = tetNodes.dimension(0);
    int spaceDim  = tetBasis.getBaseCellTopology().getDimension();

    // Generic array for values, grads, curls, etc. that will be properly sized before each call
    FieldContainer<double> vals;

    // Check VALUE of basis functions at nodes: resize vals to rank-2 container:\n";
    *outStream << " check VALUE of basis functions at nodes\n";
    vals.resize(numFields, numNodes);
    tetBasis.getValues(vals, tetNodes, OPERATOR_VALUE);

    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numNodes; j++) {
          int l =  i + j * numFields;
          if (std::abs(vals(i,j) - nodalBasisValues[l]) > INTREPID_TOL) {
             errorFlag++;
             *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

             // Output the multi-index of the value where the error is:
             *outStream << " At multi-index { ";
             *outStream << i << " ";*outStream << j << " ";
             *outStream << "}  computed value: " << vals(i,j)
               << " but reference value: " << nodalBasisValues[l] << "\n";
         }
      }
    }

    // Check VALUE of basis functions at points: resize vals to rank-2 container:\n";
    *outStream << " check VALUE of basis functions at points\n";
    int numPoints = tetPoints.dimension(0);
    vals.resize(numFields, numPoints);
    vals.initialize(0.0);
    tetBasis.getValues(vals, tetPoints, OPERATOR_VALUE);

    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
          int l =  i + j * numFields;
          if (std::abs(vals(i,j) - pointBasisValues[l]) > INTREPID_TOL) {
             errorFlag++;
             *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

             // Output the multi-index of the value where the error is:
             *outStream << " At multi-index { ";
             *outStream << i << " ";*outStream << j << " ";
             *outStream << "}  computed value: " << vals(i,j)
               << " but reference value: " << pointBasisValues[l] << "\n";
         }
      }
    }

    // Check VALUE of basis functions at random points: resize vals to rank-2 container:\n";
    *outStream << " check VALUE of basis functions at random points\n";
    int numRandomPoints = 16384;
    FieldContainer<double> tetRandomPoints(numRandomPoints, 3);
    vals.resize(numFields, numRandomPoints);
    vals.initialize(0.0);

    int point = 0;
    int count = 0;
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<> dis(0, 1);
    while (point < numRandomPoints) {
      
      count++;
      double r = dis(gen);
      double s = dis(gen);
      double t = dis(gen);
      if (r + s + t > 1.0) continue; 

      tetRandomPoints(point, 0) = r;
      tetRandomPoints(point, 1) = s;
      tetRandomPoints(point, 2) = t;

      point++;
    }
    
    tetBasis.getValues(vals, tetRandomPoints, OPERATOR_VALUE);

    for (int j = 0; j < numRandomPoints; j++) {
      double sum = 0.0;
      for (int i = 0; i < numFields; i++) {
        sum += vals(i,j);
      }
      if (std::abs(sum - 1.0) > INTREPID_TOL) {
        errorFlag++;
        *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
        
        // Just indicate something bad happened
        *outStream << " Composite tet basis functions";
        *outStream << " are not summing to 1.0\n";
        *outStream << " sum : " << sum << "\n";
      }
    }

    // Check GRAD of basis functions at points: resize vals to rank-3 container:\n";
    numPoints = tetPoints.dimension(0);
    vals.resize(numFields, numPoints, spaceDim);
    vals.initialize(0.0);
    tetBasis.getValues(vals, tetPoints, OPERATOR_GRAD);

     for (int i = 0; i < numFields; i++) {
       for (int j = 0; j < numPoints; j++) {
         for (int k = 0; k < spaceDim; k++) {
           int l = k + i * spaceDim + j * spaceDim * numFields;
           if (std::abs(vals(i,j,k) - pointBasisGrads[l]) > INTREPID_TOL) {
             errorFlag++;
             *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

             // Output the multi-index of the value where the error is:
             *outStream << " At multi-index { ";
             *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
             *outStream << "}  computed grad component: " << vals(i,j,k)
                        << " but reference grad component: " << pointBasisGrads[l] << "\n";
           }
         }
       }
     }
  }
  // Catch unexpected errors
  catch (std::logic_error err) {
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  };


  if (errorFlag != 0)
    std::cout << "End Result: TEST FAILED\n";
  else
    std::cout << "End Result: TEST PASSED\n";

  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);

  return errorFlag;
}
Пример #9
0
int main(int argc, char *argv[]) {
  
  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
Kokkos::initialize();
  // This little trick lets us print to std::cout only if
  // a (dummy) command-line argument is provided.
  int iprint     = argc - 1;
  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing
  if (iprint > 0)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs, false);
  
  // Save the format state of the original std::cout.
  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);
  
  *outStream \
    << "===============================================================================\n" \
    << "|                                                                             |\n" \
    << "|                 Unit Test (Basis_HCURL_TET_I1_FEM)                          |\n" \
    << "|                                                                             |\n" \
    << "|     1) Conversion of Dof tags into Dof ordinals and back                    |\n" \
    << "|     2) Basis values for VALUE and CURL operators                            |\n" \
    << "|                                                                             |\n" \
    << "|  Questions? Contact  Pavel Bochev ([email protected]) or                   |\n" \
    << "|                      Denis Ridzal ([email protected]).                     |\n" \
    << "|                                                                             |\n" \
    << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n" \
    << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
    << "|                                                                             |\n" \
    << "===============================================================================\n"\
    << "| TEST 1: Basis creation, exception testing                                   |\n"\
    << "===============================================================================\n";
  
  // Define basis and error flag
  Basis_HCURL_TET_I1_FEM<double, FieldContainer<double> > tetBasis;
  int errorFlag = 0;

// Define throw number for exception testing
  int nException     = 0;
  int throwCounter   = 0;

  // Define array containing the 4 vertices of the reference TET and its 6 edge centers.
  FieldContainer<double> tetNodes(10, 3);
  tetNodes(0,0) =  0.0;  tetNodes(0,1) =  0.0;  tetNodes(0,2) =  0.0;
  tetNodes(1,0) =  1.0;  tetNodes(1,1) =  0.0;  tetNodes(1,2) =  0.0;
  tetNodes(2,0) =  0.0;  tetNodes(2,1) =  1.0;  tetNodes(2,2) =  0.0;
  tetNodes(3,0) =  0.0;  tetNodes(3,1) =  0.0;  tetNodes(3,2) =  1.0;
  tetNodes(4,0) =  0.5;  tetNodes(4,1) =  0.0;  tetNodes(4,2) =  0.0;
  tetNodes(5,0) =  0.5;  tetNodes(5,1) =  0.5;  tetNodes(5,2) =  0.0;
  tetNodes(6,0) =  0.0;  tetNodes(6,1) =  0.5;  tetNodes(6,2) =  0.0;
  tetNodes(7,0) =  0.0;  tetNodes(7,1) =  0.0;  tetNodes(7,2) =  0.5;
  tetNodes(8,0) =  0.5;  tetNodes(8,1) =  0.0;  tetNodes(8,2) =  0.5;
  tetNodes(9,0) =  0.0;  tetNodes(9,1) =  0.5;  tetNodes(9,2) =  0.5;


  // Generic array for the output values; needs to be properly resized depending on the operator type
  FieldContainer<double> vals;


  try{
    // exception #1: GRAD cannot be applied to HCURL functions 
    // resize vals to rank-3 container with dimensions (num. basis functions, num. points, arbitrary)
     vals.resize(tetBasis.getCardinality(), tetNodes.dimension(0), 3 );
     INTREPID_TEST_COMMAND(  tetBasis.getValues(vals, tetNodes, OPERATOR_GRAD), throwCounter, nException );

    // exception #2: DIV cannot be applied to HCURL functions
    // resize vals to rank-2 container with dimensions (num. basis functions, num. points)
     vals.resize(tetBasis.getCardinality(), tetNodes.dimension(0) );
     INTREPID_TEST_COMMAND(  tetBasis.getValues(vals, tetNodes, OPERATOR_DIV), throwCounter, nException );
        
    // Exceptions 3-7: all bf tags/bf Ids below are wrong and should cause getDofOrdinal() and 
    // getDofTag() to access invalid array elements thereby causing bounds check exception
    // exception #3
    INTREPID_TEST_COMMAND( tetBasis.getDofOrdinal(3,0,0), throwCounter, nException );
    // exception #4
    INTREPID_TEST_COMMAND( tetBasis.getDofOrdinal(1,1,1), throwCounter, nException );
    // exception #5
    INTREPID_TEST_COMMAND( tetBasis.getDofOrdinal(0,4,1), throwCounter, nException );
    // exception #6
    INTREPID_TEST_COMMAND( tetBasis.getDofTag(7), throwCounter, nException );
    // exception #7
    INTREPID_TEST_COMMAND( tetBasis.getDofTag(-1), throwCounter, nException );

#ifdef HAVE_INTREPID2_DEBUG  
    // Exceptions 8-15 test exception handling with incorrectly dimensioned input/output arrays
    // exception #8: input points array must be of rank-2
    FieldContainer<double> badPoints1(4, 5, 3);
    INTREPID_TEST_COMMAND( tetBasis.getValues(vals,badPoints1,OPERATOR_VALUE), throwCounter, nException );

    // exception #9 dimension 1 in the input point array must equal space dimension of the cell
    FieldContainer<double> badPoints2(4, 2);
    INTREPID_TEST_COMMAND( tetBasis.getValues(vals,badPoints2,OPERATOR_VALUE), throwCounter, nException );
    
    // exception #10 output values must be of rank-3 for OPERATOR_VALUE
    FieldContainer<double> badVals1(4, 3);
    INTREPID_TEST_COMMAND( tetBasis.getValues(badVals1,tetNodes,OPERATOR_VALUE), throwCounter, nException );
 
    // exception #11 output values must be of rank-3 for OPERATOR_CURL
    INTREPID_TEST_COMMAND( tetBasis.getValues(badVals1,tetNodes,OPERATOR_CURL), throwCounter, nException );
    
    // exception #12 incorrect 0th dimension of output array (must equal number of basis functions)
    FieldContainer<double> badVals2(tetBasis.getCardinality() + 1, tetNodes.dimension(0), 3);
    INTREPID_TEST_COMMAND( tetBasis.getValues(badVals2,tetNodes,OPERATOR_VALUE), throwCounter, nException );
    
    // exception #13 incorrect 1st dimension of output array (must equal number of points)
    FieldContainer<double> badVals3(tetBasis.getCardinality(), tetNodes.dimension(0) + 1, 3);
    INTREPID_TEST_COMMAND( tetBasis.getValues(badVals3,tetNodes,OPERATOR_VALUE), throwCounter, nException );

    // exception #14: incorrect 2nd dimension of output array (must equal the space dimension)
    FieldContainer<double> badVals4(tetBasis.getCardinality(), tetNodes.dimension(0), 4);
    INTREPID_TEST_COMMAND( tetBasis.getValues(badVals4,tetNodes,OPERATOR_VALUE), throwCounter, nException );
    
    // exception #15: incorrect 2nd dimension of output array (must equal the space dimension)
    INTREPID_TEST_COMMAND( tetBasis.getValues(badVals4,tetNodes,OPERATOR_CURL), throwCounter, nException );
#endif
    
  }
  catch (std::logic_error err) {
    *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
    *outStream << err.what() << '\n';
    *outStream << "-------------------------------------------------------------------------------" << "\n\n";
    errorFlag = -1000;
  };
  
  // Check if number of thrown exceptions matches the one we expect
  // Note Teuchos throw number will not pick up exceptions 3-7 and therefore will not match.
  if (throwCounter != nException) {
    errorFlag++;
    *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
  }
  
  *outStream \
    << "\n"
    << "===============================================================================\n"\
    << "| TEST 2: correctness of tag to enum and enum to tag lookups                  |\n"\
    << "===============================================================================\n";
  
  try{
    std::vector<std::vector<int> > allTags = tetBasis.getAllDofTags();
    
    // Loop over all tags, lookup the associated dof enumeration and then lookup the tag again
    for (unsigned i = 0; i < allTags.size(); i++) {
      int bfOrd  = tetBasis.getDofOrdinal(allTags[i][0], allTags[i][1], allTags[i][2]);
      
      std::vector<int> myTag = tetBasis.getDofTag(bfOrd);
       if( !( (myTag[0] == allTags[i][0]) &&
              (myTag[1] == allTags[i][1]) &&
              (myTag[2] == allTags[i][2]) &&
              (myTag[3] == allTags[i][3]) ) ) {
        errorFlag++;
        *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
        *outStream << " getDofOrdinal( {" 
          << allTags[i][0] << ", " 
          << allTags[i][1] << ", " 
          << allTags[i][2] << ", " 
          << allTags[i][3] << "}) = " << bfOrd <<" but \n";   
        *outStream << " getDofTag(" << bfOrd << ") = { "
          << myTag[0] << ", " 
          << myTag[1] << ", " 
          << myTag[2] << ", " 
          << myTag[3] << "}\n";        
      }
    }
    
    // Now do the same but loop over basis functions
    for( int bfOrd = 0; bfOrd < tetBasis.getCardinality(); bfOrd++) {
      std::vector<int> myTag  = tetBasis.getDofTag(bfOrd);
      int myBfOrd = tetBasis.getDofOrdinal(myTag[0], myTag[1], myTag[2]);
      if( bfOrd != myBfOrd) {
        errorFlag++;
        *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
        *outStream << " getDofTag(" << bfOrd << ") = { "
          << myTag[0] << ", " 
          << myTag[1] << ", " 
          << myTag[2] << ", " 
          << myTag[3] << "} but getDofOrdinal({" 
          << myTag[0] << ", " 
          << myTag[1] << ", " 
          << myTag[2] << ", " 
          << myTag[3] << "} ) = " << myBfOrd << "\n";
      }
    }
  }
  catch (std::logic_error err){
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  };
  
  *outStream \
    << "\n"
    << "===============================================================================\n"\
    << "| TEST 3: correctness of basis function values                                |\n"\
    << "===============================================================================\n";
  
  outStream -> precision(20);
  
  // VALUE: Each row pair gives the 6x3 correct basis set values at an evaluation point: (P,F,D) layout
  double basisValues[] = {
    // 4 vertices
     1.0,0.,0.,  0.,0.,0.,  0.,-1.0,0.,  0.,0.,1.0, 
     0.,0.,0.,  0.,0.,0.,

     1.0,1.0,1.0,  0.,1.,0.,  0.,0.,0.,  0.,0.,0.,
     0.,0.,1.,  0.,0.,0.,

     0.,0.,0.,  -1.,0.,0.,  -1.0,-1.0,-1.0,
     0.,0.,0.,  0.,0.,0.,  0.,0.,1.,

     0.,0.,0.,  0.,0.,0.,  0.,0.,0.,  1.0,1.0,1.0,
     -1.,0.,0.,  0.,-1.,0.,

    // 6 edge centers
     1.0,0.5,0.5,  0.,0.5,0.,  0.,-0.5,0.,
     0.,0.,0.5,  0.,0.,0.5,  0.,0.,0.,

     0.5,0.5,0.5,  -0.5,0.5,0.,
    -0.5,-0.5,-0.5,  0.,0.,0.,  0.,0.,0.5,  0.,0.,0.5,

     0.5,0.,0.,  -0.5,0.,0.,  -0.5,-1.0,-0.5,
     0.,0.,0.5,  0.,0.,0.,  0.,0.,0.5,
 
     0.5,0.,0.,  0.,0.,0.,  0.,-0.5,0.,  0.5,0.5,1.0,
     -0.5,0.,0.,  0.,-0.5,0.,

     0.5,0.5,0.5,  0.,0.5,0.,  0.,0.,0., 0.5,0.5,0.5,
    -0.5,0.,0.5,  0.,-0.5,0.,

     0.,0.,0.,  -0.5,0.,0.,  -0.5,-0.5,-0.5,  0.5,0.5,0.5,
    -0.5,0.,0.,  0.,-0.5,0.5
  };
  
  // CURL: each row pair gives the 3x12 correct values of the curls of the 12 basis functions: (P,F,D) layout
  double basisCurls[] = {   
    // 4 vertices
     0.,-2.0,2.0,  0.,0.,2.0,  -2.0,0.,2.0,  -2.0,2.0,0.,
     0.,-2.0,0.,  2.0,0.,0.,

     0.,-2.0,2.0,  0.,0.,2.0,  -2.0,0.,2.0,  -2.0,2.0,0.,
     0.,-2.0,0.,  2.0,0.,0.,

     0.,-2.0,2.0,  0.,0.,2.0,  -2.0,0.,2.0,  -2.0,2.0,0.,
     0.,-2.0,0.,  2.0,0.,0.,

     0.,-2.0,2.0,  0.,0.,2.0,  -2.0,0.,2.0,  -2.0,2.0,0.,
     0.,-2.0,0.,  2.0,0.,0.,

    // 6 edge centers
     0.,-2.0,2.0,  0.,0.,2.0,  -2.0,0.,2.0,  -2.0,2.0,0.,
     0.,-2.0,0.,  2.0,0.,0.,

     0.,-2.0,2.0,  0.,0.,2.0,  -2.0,0.,2.0,  -2.0,2.0,0.,
     0.,-2.0,0.,  2.0,0.,0.,

     0.,-2.0,2.0,  0.,0.,2.0,  -2.0,0.,2.0,  -2.0,2.0,0.,
     0.,-2.0,0.,  2.0,0.,0.,

     0.,-2.0,2.0,  0.,0.,2.0,  -2.0,0.,2.0,  -2.0,2.0,0.,
     0.,-2.0,0.,  2.0,0.,0.,

     0.,-2.0,2.0,  0.,0.,2.0,  -2.0,0.,2.0,  -2.0,2.0,0.,
     0.,-2.0,0.,  2.0,0.,0.,

     0.,-2.0,2.0,  0.,0.,2.0,  -2.0,0.,2.0,  -2.0,2.0,0.,
     0.,-2.0,0.,  2.0,0.,0.,
  };
  
  try{
        
    // Dimensions for the output arrays:
    int numFields = tetBasis.getCardinality();
    int numPoints = tetNodes.dimension(0);
    int spaceDim  = tetBasis.getBaseCellTopology().getDimension();
    
    // Generic array for values and curls that will be properly sized before each call
    FieldContainer<double> vals;
    
    // Check VALUE of basis functions: resize vals to rank-3 container:
    vals.resize(numFields, numPoints, spaceDim);
    tetBasis.getValues(vals, tetNodes, OPERATOR_VALUE);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < spaceDim; k++) {
          
          // compute offset for (P,F,D) data layout: indices are P->j, F->i, D->k
           int l = k + i * spaceDim + j * spaceDim * numFields;
           if (std::abs(vals(i,j,k) - basisValues[l]) > INTREPID_TOL) {
             errorFlag++;
             *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

             // Output the multi-index of the value where the error is:
             *outStream << " At multi-index { ";
             *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
             *outStream << "}  computed value: " << vals(i,j,k)
               << " but reference value: " << basisValues[l] << "\n";
            }
         }
      }
    }
    
    // Check CURL of basis function: resize vals to rank-3 container
    vals.resize(numFields, numPoints, spaceDim);
    tetBasis.getValues(vals, tetNodes, OPERATOR_CURL);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < spaceDim; k++) {
          
          // compute offset for (P,F,D) data layout: indices are P->j, F->i, D->k
           int l = k + i * spaceDim + j * spaceDim * numFields;
           if (std::abs(vals(i,j,k) - basisCurls[l]) > INTREPID_TOL) {
             errorFlag++;
             *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

             // Output the multi-index of the value where the error is:
             *outStream << " At multi-index { ";
             *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
             *outStream << "}  computed curl component: " << vals(i,j,k)
               << " but reference curl component: " << basisCurls[l] << "\n";
            }
         }
      }
    }

   }    
  
  // Catch unexpected errors
  catch (std::logic_error err) {
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  };
 
  *outStream \
    << "\n"
    << "===============================================================================\n"\
    << "| TEST 4: correctness of DoF locations                                        |\n"\
    << "===============================================================================\n";

  try{
    Teuchos::RCP<Basis<double, FieldContainer<double> > > basis =
      Teuchos::rcp(new Basis_HCURL_TET_I1_FEM<double, FieldContainer<double> >);
    Teuchos::RCP<DofCoordsInterface<FieldContainer<double> > > coord_iface =
      Teuchos::rcp_dynamic_cast<DofCoordsInterface<FieldContainer<double> > >(basis);

    int spaceDim = 3;
    FieldContainer<double> cvals;
    FieldContainer<double> bvals(basis->getCardinality(), basis->getCardinality(),spaceDim); // last dimension is spatial dim
 
    // Check exceptions.
#ifdef HAVE_INTREPID2_DEBUG
    cvals.resize(1,2,3);
    INTREPID_TEST_COMMAND( coord_iface->getDofCoords(cvals), throwCounter, nException );
    cvals.resize(3,2);
    INTREPID_TEST_COMMAND( coord_iface->getDofCoords(cvals), throwCounter, nException );
    cvals.resize(4,2);
    INTREPID_TEST_COMMAND( coord_iface->getDofCoords(cvals), throwCounter, nException );
#endif
    cvals.resize(6,spaceDim);
    INTREPID_TEST_COMMAND( coord_iface->getDofCoords(cvals), throwCounter, nException ); nException--;
    // Check if number of thrown exceptions matches the one we expect
    if (throwCounter != nException) {
      errorFlag++;
      *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
    }

    // Check mathematical correctness
    FieldContainer<double> tangents(basis->getCardinality(),spaceDim); // tangents at each point basis point
    tangents(0,0)  =  1.0; tangents(0,1)  =  0.0; tangents(0,2)  =  0.0;
    tangents(1,0)  = -1.0; tangents(1,1)  =  1.0; tangents(1,2)  =  0.0;
    tangents(2,0)  =  0.0; tangents(2,1)  = -1.0; tangents(2,2)  =  0.0;
    tangents(3,0)  =  0.0; tangents(3,1)  =  0.0; tangents(3,2)  =  1.0;
    tangents(4,0)  = -1.0; tangents(4,1)  =  0.0; tangents(4,2)  =  1.0;
    tangents(5,0)  =  0.0; tangents(5,1)  = -1.0; tangents(5,2)  =  1.0;

    basis->getValues(bvals, cvals, OPERATOR_VALUE);
    char buffer[120];
    for (int i=0; i<bvals.dimension(0); i++) {
      for (int j=0; j<bvals.dimension(1); j++) {

        double tangent = 0.0;
        for(int d=0;d<spaceDim;d++)
           tangent += bvals(i,j,d)*tangents(j,d);

        if ((i != j) && (std::abs(tangent - 0.0) > INTREPID_TOL)) {
          errorFlag++;
          sprintf(buffer, "\nValue of basis function %d at (%6.4e, %6.4e, %6.4e) is %6.4e but should be %6.4e!\n", i, cvals(i,0), cvals(i,1), cvals(i,2), tangent, 0.0);
          *outStream << buffer;
        }
        else if ((i == j) && (std::abs(tangent - 1.0) > INTREPID_TOL)) {
          errorFlag++;
          sprintf(buffer, "\nValue of basis function %d at (%6.4e, %6.4e, %6.4e) is %6.4e but should be %6.4e!\n", i, cvals(i,0), cvals(i,1), cvals(i,2), tangent, 1.0);
          *outStream << buffer;
        }
      }
    }

  }
  catch (std::logic_error err){
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  };

  if (errorFlag != 0)
    std::cout << "End Result: TEST FAILED\n";
  else
    std::cout << "End Result: TEST PASSED\n";
  
  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);
  Kokkos::finalize();
  return errorFlag;
}
Пример #10
0
void Projector::projectFunctionOntoBasisInterpolating(FieldContainer<double> &basisCoefficients, FunctionPtr fxn,
                                                      BasisPtr basis, BasisCachePtr domainBasisCache) {
  basisCoefficients.initialize(0);
  CellTopoPtr domainTopo = basis->domainTopology();
  unsigned domainDim = domainTopo->getDimension();
  
  IPPtr ip;
  
  bool traceVar = domainBasisCache->isSideCache();
  
  pair<IPPtr, VarPtr> ipVarPair = IP::standardInnerProductForFunctionSpace(basis->functionSpace(), traceVar, domainDim);
  ip = ipVarPair.first;
  VarPtr v = ipVarPair.second;
  
  IPPtr ip_l2 = Teuchos::rcp( new IP );
  ip_l2->addTerm(v);
  
  // for now, make all projections use L^2... (having some issues with gradients and cell Jacobians--I think we need the restriction of the cell Jacobian to the subcell, e.g., and it's not clear how to do that...)
  ip = ip_l2;
  
  FieldContainer<double> referenceDomainNodes(domainTopo->getVertexCount(),domainDim);
  CamelliaCellTools::refCellNodesForTopology(referenceDomainNodes, domainTopo);
  
  int basisCardinality = basis->getCardinality();
  
  set<int> allDofs;
  for (int i=0; i<basisCardinality; i++) {
    allDofs.insert(i);
  }
  
  for (int d=0; d<=domainDim; d++) {
    FunctionPtr projectionThusFar = NewBasisSumFunction::basisSumFunction(basis, basisCoefficients);
    FunctionPtr fxnToApproximate = fxn - projectionThusFar;
    int subcellCount = domainTopo->getSubcellCount(d);
    for (int subcord=0; subcord<subcellCount; subcord++) {
      set<int> subcellDofOrdinals = basis->dofOrdinalsForSubcell(d, subcord);
      if (subcellDofOrdinals.size() > 0) {
        FieldContainer<double> refCellPoints;
        FieldContainer<double> cubatureWeightsSubcell; // allows us to integrate over the fine subcell even when domain is higher-dimensioned
        if (d == 0) {
          refCellPoints.resize(1,domainDim);
          for (int d1=0; d1<domainDim; d1++) {
            refCellPoints(0,d1) = referenceDomainNodes(subcord,d1);
          }
          cubatureWeightsSubcell.resize(1);
          cubatureWeightsSubcell(0) = 1.0;
        } else {
          CellTopoPtr subcellTopo = domainTopo->getSubcell(d, subcord);
//          Teuchos::RCP<Cubature<double> > subcellCubature = cubFactory.create(subcellTopo, domainBasisCache->cubatureDegree());
          BasisCachePtr subcellCache = Teuchos::rcp( new BasisCache(subcellTopo, domainBasisCache->cubatureDegree(), false) );
          int numPoints = subcellCache->getRefCellPoints().dimension(0);
          refCellPoints.resize(numPoints,domainDim);
          cubatureWeightsSubcell = subcellCache->getCubatureWeights();
          
          if (d == domainDim) {
            refCellPoints = subcellCache->getRefCellPoints();
          } else {
            CamelliaCellTools::mapToReferenceSubcell(refCellPoints, subcellCache->getRefCellPoints(), d,
                                                     subcord, domainTopo);
          }
        }
        domainBasisCache->setRefCellPoints(refCellPoints, cubatureWeightsSubcell);
        IPPtr ipForProjection = (d==0) ? ip_l2 : ip; // just use values at vertices (ignore derivatives)
        set<int> dofsToSkip = allDofs;
        for (set<int>::iterator dofOrdinalIt=subcellDofOrdinals.begin(); dofOrdinalIt != subcellDofOrdinals.end(); dofOrdinalIt++) {
          dofsToSkip.erase(*dofOrdinalIt);
        }
        FieldContainer<double> newBasisCoefficients;
        projectFunctionOntoBasis(newBasisCoefficients, fxnToApproximate, basis, domainBasisCache, ipForProjection, v, dofsToSkip);
        for (int cellOrdinal=0; cellOrdinal<newBasisCoefficients.dimension(0); cellOrdinal++) {
          for (set<int>::iterator dofOrdinalIt=subcellDofOrdinals.begin(); dofOrdinalIt != subcellDofOrdinals.end(); dofOrdinalIt++) {
            basisCoefficients(cellOrdinal,*dofOrdinalIt) = newBasisCoefficients(cellOrdinal,*dofOrdinalIt);
          }
        }
      }
    }
  }
}
Пример #11
0
int main(int argc, char *argv[]) {

  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
  Kokkos::initialize();
  // This little trick lets us print to std::cout only if
  // a (dummy) command-line argument is provided.
  int iprint     = argc - 1;
  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing
  if (iprint > 0)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs, false);
  
  // Save the format state of the original std::cout.
  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);
  
  *outStream \
    << "===============================================================================\n" \
    << "|                                                                             |\n" \
    << "|                 Unit Test (Basis_HGRAD_QUAD_Cn_FEM)                         |\n" \
    << "|                                                                             |\n" \
    << "|     1) Conversion of Dof tags into Dof ordinals and back                    |\n" \
    << "|     2) Basis values for VALUE, GRAD, CURL, and Dk operators                 |\n" \
    << "|                                                                             |\n" \
    << "|  Questions? Contact  Pavel Bochev  ([email protected]),                    |\n" \
    << "|                      Robert Kirby  ([email protected]),                |\n" \
    << "|                      Denis Ridzal  ([email protected]),                    |\n" \
    << "|                      Kara Peterson ([email protected]).                    |\n" \
    << "|                                                                             |\n" \
    << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n" \
    << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
    << "|                                                                             |\n" \
    << "===============================================================================\n"\
    << "| TEST 1: Basis creation, exception testing                                   |\n"\
    << "===============================================================================\n";
  
  // Define basis and error flag
  // get points for basis
  const int deg=2;
  shards::CellTopology line(shards::getCellTopologyData< shards::Line<> >()); 
  FieldContainer<double> pts(PointTools::getLatticeSize(line,deg),1);
  PointTools::getLattice<double,FieldContainer<double> >(pts,line,deg);

  Basis_HGRAD_QUAD_Cn_FEM<double, FieldContainer<double> > quadBasis(deg,deg,pts,pts);
  int errorFlag = 0;

  // Initialize throw counter for exception testing
  int nException     = 0;
  int throwCounter   = 0;

  // Array with the 4 vertices, 4 edge midpoints, center of the reference QUAD and a random point.  
  FieldContainer<double> quadNodes(10, 2);
  quadNodes(0,0) = -1.0;  quadNodes(0,1) = -1.0;
  quadNodes(1,0) =  1.0;  quadNodes(1,1) = -1.0;
  quadNodes(2,0) =  1.0;  quadNodes(2,1) =  1.0;
  quadNodes(3,0) = -1.0;  quadNodes(3,1) =  1.0;
  // edge midpoints
  quadNodes(4,0) =  0.0;  quadNodes(4,1) = -1.0;
  quadNodes(5,0) =  1.0;  quadNodes(5,1) =  0.0;
  quadNodes(6,0) =  0.0;  quadNodes(6,1) =  1.0;
  quadNodes(7,0) = -1.0;  quadNodes(7,1) =  0.0;
  // center & random point
  quadNodes(8,0) =  0.0;  quadNodes(8,1) =  0.0;
  quadNodes(9,0) =1./3.;  quadNodes(9,1) =-3./5.;
  
  // Generic array for the output values; needs to be properly resized depending on the operator type
  FieldContainer<double> vals;

  try{
    // exception #1: DIV cannot be applied to scalar functions
    // resize vals to rank-2 container with dimensions (num. points, num. basis functions)
    vals.resize(quadBasis.getCardinality(), quadNodes.dimension(0));
    INTREPID_TEST_COMMAND( quadBasis.getValues(vals, quadNodes, OPERATOR_DIV), throwCounter, nException );
        
    // Exceptions 2-6: all bf tags/bf Ids below are wrong and should cause getDofOrdinal() and 
    // getDofTag() to access invalid array elements thereby causing bounds check exception
    // exception #2
     INTREPID_TEST_COMMAND( quadBasis.getDofOrdinal(3,0,0), throwCounter, nException );
     // exception #3
     INTREPID_TEST_COMMAND( quadBasis.getDofOrdinal(1,1,1), throwCounter, nException );
    // exception #4
    INTREPID_TEST_COMMAND( quadBasis.getDofOrdinal(0,4,0), throwCounter, nException );
    // exception #5
    INTREPID_TEST_COMMAND( quadBasis.getDofTag(10), throwCounter, nException );
    // exception #6
    INTREPID_TEST_COMMAND( quadBasis.getDofTag(-1), throwCounter, nException );
    
#ifdef HAVE_INTREPID_DEBUG
    // Exceptions 7- test exception handling with incorrectly dimensioned input/output arrays
    // exception #7: input points array must be of rank-2
    FieldContainer<double> badPoints1(4, 5, 3);
    INTREPID_TEST_COMMAND( quadBasis.getValues(vals, badPoints1, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #8 dimension 1 in the input point array must equal space dimension of the cell
    FieldContainer<double> badPoints2(4, quadBasis.getBaseCellTopology().getDimension() + 1);
    INTREPID_TEST_COMMAND( quadBasis.getValues(vals, badPoints2, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #9 output values must be of rank-2 for OPERATOR_VALUE
    FieldContainer<double> badVals1(4, 3, 1);
    INTREPID_TEST_COMMAND( quadBasis.getValues(badVals1, quadNodes, OPERATOR_VALUE), throwCounter, nException );

    // exception #10 output values must be of rank-3 for OPERATOR_GRAD
    FieldContainer<double> badVals2(4, 3);
    INTREPID_TEST_COMMAND( quadBasis.getValues(badVals2, quadNodes, OPERATOR_GRAD), throwCounter, nException );
    
    // exception #11 output values must be of rank-3 for OPERATOR_CURL
    INTREPID_TEST_COMMAND( quadBasis.getValues(badVals2, quadNodes, OPERATOR_CURL), throwCounter, nException );
    
    // exception #12 output values must be of rank-3 for OPERATOR_D2
    INTREPID_TEST_COMMAND( quadBasis.getValues(badVals2, quadNodes, OPERATOR_D2), throwCounter, nException );
    
    // exception #13 incorrect 0th dimension of output array (must equal number of basis functions)
    FieldContainer<double> badVals3(quadBasis.getCardinality() + 1, quadNodes.dimension(0));
    INTREPID_TEST_COMMAND( quadBasis.getValues(badVals3, quadNodes, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #14 incorrect 1st dimension of output array (must equal number of points in quadNodes)
    FieldContainer<double> badVals4(quadBasis.getCardinality(), quadNodes.dimension(0) + 1);
    INTREPID_TEST_COMMAND( quadBasis.getValues(badVals4, quadNodes, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #15: incorrect 2nd dimension of output array (must equal the space dimension)
    FieldContainer<double> badVals5(quadBasis.getCardinality(), quadNodes.dimension(0), quadBasis.getBaseCellTopology().getDimension() + 1);
    INTREPID_TEST_COMMAND( quadBasis.getValues(badVals5, quadNodes, OPERATOR_GRAD), throwCounter, nException );
    
    // exception #16: incorrect 2nd dimension of output array (must equal D2 cardinality in 2D)
    FieldContainer<double> badVals6(quadBasis.getCardinality(), quadNodes.dimension(0), 40);
    INTREPID_TEST_COMMAND( quadBasis.getValues(badVals6, quadNodes, OPERATOR_D2), throwCounter, nException );
    
    // exception #17: incorrect 2nd dimension of output array (must equal D3 cardinality in 2D)
    INTREPID_TEST_COMMAND( quadBasis.getValues(badVals6, quadNodes, OPERATOR_D3), throwCounter, nException );
#endif

  }
  catch (std::logic_error err) {
    *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
    *outStream << err.what() << '\n';
    *outStream << "-------------------------------------------------------------------------------" << "\n\n";
    errorFlag = -1000;
  };
  
  // Check if number of thrown exceptions matches the one we expect 
  if (throwCounter != nException) {
    errorFlag++;
    *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
  }
  
  *outStream \
    << "\n"
    << "===============================================================================\n"\
    << "| TEST 2: correctness of tag to enum and enum to tag lookups                  |\n"\
    << "===============================================================================\n";
  
  try{
    std::vector<std::vector<int> > allTags = quadBasis.getAllDofTags();
    
    // Loop over all tags, lookup the associated dof enumeration and then lookup the tag again
    for (unsigned i = 0; i < allTags.size(); i++) {
      int bfOrd  = quadBasis.getDofOrdinal(allTags[i][0], allTags[i][1], allTags[i][2]);
      
      std::vector<int> myTag = quadBasis.getDofTag(bfOrd);
       if( !( (myTag[0] == allTags[i][0]) &&
              (myTag[1] == allTags[i][1]) &&
              (myTag[2] == allTags[i][2]) &&
              (myTag[3] == allTags[i][3]) ) ) {
        errorFlag++;
        *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
        *outStream << " getDofOrdinal( {" 
          << allTags[i][0] << ", " 
          << allTags[i][1] << ", " 
          << allTags[i][2] << ", " 
          << allTags[i][3] << "}) = " << bfOrd <<" but \n";   
        *outStream << " getDofTag(" << bfOrd << ") = { "
          << myTag[0] << ", " 
          << myTag[1] << ", " 
          << myTag[2] << ", " 
          << myTag[3] << "}\n";        
      }
    }
    
    // Now do the same but loop over basis functions
    for( int bfOrd = 0; bfOrd < quadBasis.getCardinality(); bfOrd++) {
      std::vector<int> myTag  = quadBasis.getDofTag(bfOrd);
      int myBfOrd = quadBasis.getDofOrdinal(myTag[0], myTag[1], myTag[2]);
      if( bfOrd != myBfOrd) {
        errorFlag++;
        *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
        *outStream << " getDofTag(" << bfOrd << ") = { "
          << myTag[0] << ", " 
          << myTag[1] << ", " 
          << myTag[2] << ", " 
          << myTag[3] << "} but getDofOrdinal({" 
          << myTag[0] << ", " 
          << myTag[1] << ", " 
          << myTag[2] << ", " 
          << myTag[3] << "} ) = " << myBfOrd << "\n";
      }
    }
  }
  catch (std::logic_error err){
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  };
  
  *outStream \
    << "\n"
    << "===============================================================================\n"\
    << "| TEST 3: correctness of basis function values                                |\n"\
    << "===============================================================================\n";
  
  outStream -> precision(20);
  
  // VALUE: Correct basis values in (F,P) format:
  double basisValues[] = {
    1, 0, 0, 0, 0, 0, 0, 0, 0, -0.05333333333333334, \
    0, 0, 0, 0, 1, 0, 0, 0, 0, 0.4266666666666667, \
    0, 1, 0, 0, 0, 0, 0, 0, 0, 0.1066666666666667, \
    0, 0, 0, 0, 0, 0, 0, 1, 0, -0.07111111111111112 , \
    0, 0, 0, 0, 0, 0, 0, 0, 1, 0.5688888888888890, \
    0, 0, 0, 0, 0, 1, 0, 0, 0, 0.1422222222222222 ,\
    0, 0, 0, 1, 0, 0, 0, 0, 0, 0.01333333333333333, \
    0, 0, 0, 0, 0, 0, 1, 0, 0, -0.1066666666666667, \
    0, 0, 1, 0, 0, 0, 0, 0, 0, -0.02666666666666666 };

  // FIXME HERE: needs to be reordered.
  
  // GRAD and D1: Correct gradients and D1 in (F,P,D) format
  // 9 basis functions, each evaluated at 10 points, with two
  // components at each point.
  // that looks like 10 per to me.
  double basisGrads[] = {
    //
    -1.500000000000000, -1.500000000000000, 0.5000000000000000, 0, 0, 0, 0, 0.5000000000000000, -0.5000000000000000, 0, \
    0, 0, 0, 0, 0, -0.5000000000000000, 0, 0, -0.08000000000000002, 0.1222222222222222, \
    //
    2.000000000000000, 0, -2.000000000000000, 0, 0, 0, 0, 0, 0, -1.500000000000000, \
    0, 0, 0, 0.5000000000000000, 0, 0, 0, -0.5000000000000000,  -0.3199999999999999, -0.9777777777777779, \
    //
    -0.5000000000000000, 0, 1.500000000000000, -1.500000000000000, 0, 0.5000000000000000, 0, 0, 0.5000000000000000, 0, \
    0, -0.5000000000000000, 0, 0, 0, 0, 0, 0, 0.3999999999999999, -0.2444444444444444, \
    //
    0, 2.0, 0, 0, 0, 0, 0, -2.000000000000000, 0, 0, \
    0.5000000000000000, 0, 0, 0, -1.50, 0, -0.50, 0, -0.1066666666666667, -0.1333333333333333, \
    //
    0, 0, 0, 0, 0, 0, 0, 0, 0, 2.0,\
    -2.00, 0, 0, -2.0, 2.0, 0, 0, 0, -0.4266666666666667, 1.066666666666667 ,  \
    //
    0, 0, 0, 2.000000000000000, 0, -2.000000000000000, 0, 0, 0, 0, \
    1.5, 0, 0, 0, -0.5, 0, 0.5000000000000000, 0, 0.5333333333333334, 0.2666666666666666 ,  \
    //
    0, -0.5000000000000000, 0, 0, 0.5000000000000000, 0, -1.500000000000000, 1.500000000000000, 0, 0, \
    0, 0, -0.5000000000000000, 0, 0, 0.5000000000000000, 0, 0, 0.02000000000000000, 0.01111111111111112 , \
    //
    0, 0, 0, 0, -2.0, 0, 2.0, 0, 0, -0.50,				\
    0, 0, 0, 1.5, 0, 0, 0, 0.5000000000000000, 0.07999999999999997, -0.08888888888888888, \
    //
    0, 0, 0, -0.5000000000000000, 1.500000000000000, 1.500000000000000, -0.5000000000000000, 0, 0, 0, \
    0, 0.5000000000000000, 0.5000000000000000, 0, 0, 0, 0, 0, -0.09999999999999998, -0.02222222222222221 \
    //
  };
  
  // D2: Correct multiset of second order partials in (F,P,Dk) format. D2 cardinality = 3 for 2D 
  // 10 quad points and 3 values per point, so
  // each bf consists of 30 values.
  double basisD2[] = {
    1.0, 2.25, 1.0, 1.0, -0.75, 0, 0, 0.25, 0,  0, -0.75, 1.0, 1.0,  0.75, 0, 0, -0.25, 0, 0,  -0.25, 0, 0, 0.75, 1.0, 0,  0.25, 0, 0.48, 0.1833333333333334, -0.1111111111111111,
    //
    -2.0, -3.0, 0, -2.0, 3.0, 0, 0, -1.0, 0, \
    0, 1.0, 0, -2.0, 0, 1.0, 0, \
    1.0, 0, 0, 0, 1.0, 0, -1.0, \
    0, 0, 0, 1.0, -0.96, 0.7333333333333332, \
    0.8888888888888890, \
    //
    1.0, 0.75, 0, 1.0, -2.25, 1.0, 0, 0.75, 1.0, 0, -0.25, 0, \
    1.0, -0.75, 0, 0, -0.75, 1.0, 0, 0.25, 0, 0, 0.25, \
    0, 0, -0.25, 0, 0.48, -0.9166666666666666, 0.2222222222222222, 
    //
    0, -3.0, -2.0, 0, 1.0, 0, 0, -1.0, 0, 0, 3.0, \
    -2.0, 0, -1.0, 0, 1.0, 0, 0, 0, 1.0, 0, 1.0, 0, -2.0, \
    1.0, 0, 0, 0.6400000000000001, -0.2000000000000001,  0.2222222222222222, \
    //
    0, 4.0, 0, 0, -4.0,	0, 0, 4.0, 0, 0, -4.0, 0, 0, 0, \
    -2.0, -2.0, 0, 0, 0, 0, -2.0, -2.0, 0, 0, -2.0, 0, \
    -2.0, -1.280000000000000, -0.7999999999999998, -1.777777777777778 ,
    //
    0, -1.0, 0, 0, 3.0,	-2.0, 0, -3.0, -2.0, 0, \
    1.0, 0, 0, 1.0, 0, 1.0, 0, -2.0, 0, -1.0, 0, 1.0, 0, \
    0, 1.0, 0, 0, 0.6400000000000001, 1.0, -0.4444444444444444, \
    //
    0, 0.75, 1.0, 0, -0.25, 0, 1.0, 0.75, 0, 1.0, -2.25, 1.0, 0, \
    0.25, 0, 0, 0.25, 0, 1.0, -0.75, 0, 0, -0.75, 1.0, 0, \
    -0.25, 0, -0.12, 0.01666666666666666,  -0.1111111111111111, \
    //
    0, -1.0, 0, 0, 1.0,	0, -2.0, -3.0, 0, -2.0, 3.0, 0, 0, 0, 1.0, 0, -1.0, \
    0, -2.0, 0, 1.0, 0, 1.0, 0, \
    0, 0, 1.0, 0.24, 0.06666666666666665,  0.8888888888888890,	\
    //
    0, 0.25, 0, 0, -0.75, 1.0, 1.0, 2.25, 1.0, 1.0, \
    -0.75, 0, 0, -0.25, 0, 0, 0.75, 1.0, 1.0, \
    0.75, 0, 0, -0.25, 0, 0, 0.25, 0, -0.12, -0.08333333333333331, 0.2222222222222222 \
  };
  
  //D3: Correct multiset of second order partials in (F,P,Dk) format. D3 cardinality = 4 for 2D
  double basisD3[] = {
    0, -1.5, -1.5, 0, 0, -1.5, 0.5, 0, 0, 0.5, 
    0.5, 0, 0, 0.5, -1.5, 0, 0, -1.5, -0.5, 0, 
    0, -0.5, 0.5, 0, 0, 0.5, -0.5, 0, 0, -0.5, 
    -1.5, 0, 0, -0.5, -0.5, 0, 0, -1.1, -0.1666666666666667, 0, 
    //
    0, 3.0, 2.0, 0, 0, 3.0, -2.0, 0, 0, -1.0, 
    -2.0, 0, 0, -1.0, 2.0, 0, 0, 3.0, 0, 0, 
    0, 1.0, -2.0, 0, 0,	-1.0, 0, 0, 0, 1.0,
    2.0, 0, 0, 1.0, 0, 0, 0, 2.2, -0.6666666666666665, 0, 
    //
    0, -1.5, -0.5, 0, 0, -1.5, 1.5, 0, 0, 0.5, 
    1.5, 0, 0, 0.5, -0.5, 0, 0, -1.5, 0.5, 0, 
    0, -0.5, 1.5, 0, 0, 0.5, 0.5, 0, 0, -0.5, 
    -0.5, 0, 0, -0.5, 0.5, 0, 0, -1.1, 0.8333333333333333, 0,
    //
    0, 2.0, 3.0, 0, 0, 2.0, -1.0, 0, 0, -2.0,
    -1.0, 0, 0, -2.0, 3.0, 0, 0, 2.0,  1.0, 0, 
    0, 0, -1.0, 0, 0, -2.0, 1.0, 0, 0, 0, 
    3.0, 0, 0, 0, 1.0, 0, 0, 1.2, 0.3333333333333334, 0, 
    //
    0, -4.0, -4.0, 0, 0, -4.0, 4.0, 0, 0, 4.0, 
    4.0, 0, 0, 4.0, -4.0, 0, 0,	-4.0, 0, 0, 
    0, 0, 4.0, 0, 0, 4.0, 0, 0, 0, 0, 
    -4.0, 0, 0, 0, 0, 0, 0, -2.40, 1.333333333333333, 0,
    //
    0, 2.0, 1.0, 0, 0, 2.0, -3.0, 0, 0, -2.0, 
    -3.0, 0, 0, -2.0, 1.0, 0, 0, 2.0, -1.0, 0, 
    0, 0, -3.0, 0, 0, -2.0, -1.0, 0, 0, 0, 
    1.0, 0, 0, 0, -1.0, 0, 0, 1.2, -1.666666666666667, 0 ,
    //
    0, -0.5, -1.5, 0, 0, -0.5, 0.5, 0, 0, 1.5, 
    0.5, 0, 0, 1.5, -1.5, 0, 0, -0.5, -0.5, 0, 
    0, 0.5, 0.5, 0, 0, 1.5, -0.5, 0, 0, 0.5,
    -1.5, 0, 0, 0.5, -0.5, 0,  0, -0.09999999999999998, -0.1666666666666667, 0, 
    //
    0, 1.0, 2.0, 0, 0, 1.0, -2.0, 0, 0,	-3.0, 
    -2.0, 0, 0, -3.0, 2.0, 0, 0, 1.0, 0, 0, 
    0, -1.0, -2.0, 0, 0, -3.0, 0,  0, 0, -1.0, 
    2.0, 0, 0, -1.0, 0, 0, 0, 0.2, -0.6666666666666665, 0,
    //
    0, -0.5, -0.5, 0, 0, -0.5, 1.5, 0, 0, 1.5, 
    1.5, 0, 0, 1.5, -0.5, 0, 0, -0.5, 0.5, 0, 
    0, 0.5, 1.5, 0, 0, 1.5, 0.5, 0, 0, 0.5, 
    -0.5, 0, 0, 0.5, 0.5, 0, 0, -0.09999999999999998, 0.8333333333333333, 0
  };
  //D4: Correct multiset of second order partials in (F,P,Dk) format. D4 cardinality = 5 for 2D
  double basisD4[] = {
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0,
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 
    //
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0, 
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0, 
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0, 
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0, 
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0,
    //
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 
    //
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0, 
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0, 
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0, 
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0, 
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0,
    //
    0, 0, 4.0, 0, 0, 0, 0, 4.0, 0, 0, 
    0, 0, 4.0, 0, 0, 0, 0, 4.0, 0, 0, 
    0, 0, 4.0, 0, 0, 0, 0, 4.0, 0, 0, 
    0, 0, 4.0, 0, 0, 0, 0, 4.0, 0, 0, 
    0, 0, 4.0, 0, 0, 0, 0, 4.0, 0, 0,
    //
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0, 
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0, 
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0, 
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0,
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0,
    //
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0,
    //
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0, 
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0, 
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0, 
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0, 
    0, 0, -2.0, 0, 0, 0, 0, -2.0, 0, 0,
    //
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 
    0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0
};
  
  try{
        
    // Dimensions for the output arrays:
    int numFields = quadBasis.getCardinality();
    int numPoints = quadNodes.dimension(0);
    int spaceDim  = quadBasis.getBaseCellTopology().getDimension();
    
    // Generic array for values, grads, curls, etc. that will be properly sized before each call
    FieldContainer<double> vals;
    
    // Check VALUE of basis functions: resize vals to rank-2 container:
    vals.resize(numFields, numPoints);
    quadBasis.getValues(vals, quadNodes, OPERATOR_VALUE);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        
        // Compute offset for (F,P) container
	int l =  j + i * numPoints;
	if (std::abs(vals(i,j) - basisValues[l]) > INTREPID_TOL) {
	  errorFlag++;
	  *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
	  
	  // Output the multi-index of the value where the error is:
	  *outStream << " At multi-index { ";
	  *outStream << i << " ";*outStream << j << " ";
	  *outStream << "}  computed value: " << vals(i,j)
		     << " but reference value: " << basisValues[l] << "\n";
	}
      }
    }

    // Check GRAD of basis function: resize vals to rank-3 container
    vals.resize(numFields, numPoints, spaceDim);
    quadBasis.getValues(vals, quadNodes, OPERATOR_GRAD);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < spaceDim; k++) {
          
          // basisGrads is (F,P,D), compute offset:
          int l = k + j * spaceDim + i * spaceDim * numPoints;
           if (std::abs(vals(i,j,k) - basisGrads[l]) > INTREPID_TOL) {
             errorFlag++;
             *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

             // Output the multi-index of the value where the error is:
             *outStream << " At multi-index { ";
             *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
             *outStream << "}  computed grad component: " << vals(i,j,k)
               << " but reference grad component: " << basisGrads[l] << "\n";
            }
         }
      }
    }

    
    // Check D1 of basis function (do not resize vals because it has the correct size: D1 = GRAD)
    quadBasis.getValues(vals, quadNodes, OPERATOR_D1);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < spaceDim; k++) {
          
          // basisGrads is (F,P,D), compute offset:
          int l = k + j * spaceDim + i * spaceDim * numPoints;
           if (std::abs(vals(i,j,k) - basisGrads[l]) > INTREPID_TOL) {
             errorFlag++;
             *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

             // Output the multi-index of the value where the error is:
             *outStream << " At multi-index { ";
             *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
             *outStream << "}  computed D1 component: " << vals(i,j,k)
               << " but reference D1 component: " << basisGrads[l] << "\n";
            }
         }
      }
    }


    // Check CURL of basis function: resize vals just for illustration! 
    vals.resize(numFields, numPoints, spaceDim);
    quadBasis.getValues(vals, quadNodes, OPERATOR_CURL);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        // We will use "rotated" basisGrads to check CURL: get offsets to extract (u_y, -u_x)
        int curl_0 = 1 + j * spaceDim + i * spaceDim * numPoints;               // position of y-derivative
        int curl_1 = 0 + j * spaceDim + i * spaceDim * numPoints;               // position of x-derivative
        
        double curl_value_0 = basisGrads[curl_0];
        double curl_value_1 =-basisGrads[curl_1];
        if (std::abs(vals(i,j,0) - curl_value_0) > INTREPID_TOL) {
          errorFlag++;
          *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
          // Output the multi-index of the value where the error is:
          *outStream << " At multi-index { ";
          *outStream << i << " ";*outStream << j << " ";*outStream << 0 << " ";
          *outStream << "}  computed curl component: " << vals(i,j,0)
            << " but reference curl component: " << curl_value_0 << "\n";
        }
        if (std::abs(vals(i,j,1) - curl_value_1) > INTREPID_TOL) {
          errorFlag++;
          *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
          // Output the multi-index of the value where the error is:
          *outStream << " At multi-index { ";
          *outStream << i << " ";*outStream << j << " ";*outStream << 1 << " ";
          *outStream << "}  computed curl component: " << vals(i,j,1)
            << " but reference curl component: " << curl_value_1 << "\n";
        }
      }
    }
    
    // Check D2 of basis function
    int D2cardinality = Intrepid2::getDkCardinality(OPERATOR_D2, spaceDim);
    vals.resize(numFields, numPoints, D2cardinality);    
    quadBasis.getValues(vals, quadNodes, OPERATOR_D2);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < D2cardinality; k++) {
          
          // basisD2 is (F,P,Dk), compute offset:
          int l = k + j * D2cardinality + i * D2cardinality * numPoints;
           if (std::abs(vals(i,j,k) - basisD2[l]) > INTREPID_TOL) {
             errorFlag++;
             *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

             // Output the multi-index of the value where the error is:
             *outStream << " At multi-index { ";
             *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
             *outStream << "}  computed D2 component: " << vals(i,j,k)
               << " but reference D2 component: " << basisD2[l] << "\n";
            }
         }
      }
    }

    
    // Check D3 of basis function
    int D3cardinality = Intrepid2::getDkCardinality(OPERATOR_D3, spaceDim);
    vals.resize(numFields, numPoints, D3cardinality);    
    quadBasis.getValues(vals, quadNodes, OPERATOR_D3);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < D3cardinality; k++) {
          
          // basisD3 is (F,P,Dk), compute offset:
          int l = k + j * D3cardinality + i * D3cardinality * numPoints;
          if (std::abs(vals(i,j,k) - basisD3[l]) > INTREPID_TOL) {
            errorFlag++;
            *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
            
            // Output the multi-index of the value where the error is:
            *outStream << " At multi-index { ";
            *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
            *outStream << "}  computed D3 component: " << vals(i,j,k)
              << " but reference D3 component: " << basisD2[l] << "\n";
          }
        }
      }
    }
    
    // Check D4 of basis function
    int D4cardinality = Intrepid2::getDkCardinality(OPERATOR_D4, spaceDim);
    vals.resize(numFields, numPoints, D4cardinality);    
    quadBasis.getValues(vals, quadNodes, OPERATOR_D4);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < D4cardinality; k++) {
          
          // basisD4 is (F,P,Dk), compute offset:
          int l = k + j * D4cardinality + i * D4cardinality * numPoints;
          if (std::abs(vals(i,j,k) - basisD4[l]) > INTREPID_TOL) {
            errorFlag++;
            *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
            
            // Output the multi-index of the value where the error is:
            *outStream << " At multi-index { ";
            *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
            *outStream << "}  computed D4 component: " << vals(i,j,k)
              << " but reference D4 component: " << basisD4[l] << "\n";
          }
        }
      }
    }
    

    // Check all higher derivatives - must be zero. 
    for(EOperator op = OPERATOR_D5; op <= OPERATOR_D6; op++) {
      
      // The last dimension is the number of kth derivatives and needs to be resized for every Dk
      int DkCardin  = Intrepid2::getDkCardinality(op, spaceDim);
      vals.resize(numFields, numPoints, DkCardin);    

      quadBasis.getValues(vals, quadNodes, op);
      for (int i = 0; i < vals.size(); i++) {
        if (std::abs(vals[i]) > INTREPID_TOL) {
          errorFlag++;
          *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
          
          // Get the multi-index of the value where the error is and the operator order
          std::vector<int> myIndex;
          vals.getMultiIndex(myIndex,i);
          int ord = Intrepid2::getOperatorOrder(op);
          *outStream << " At multi-index { ";
          for(int j = 0; j < vals.rank(); j++) {
            *outStream << myIndex[j] << " ";
          }
          *outStream << "}  computed D"<< ord <<" component: " << vals[i] 
            << " but reference D" << ord << " component:  0 \n";
        }
      }
}
  }
  
  // Catch unexpected errors
  catch (std::logic_error err) {
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  };
  
  if (errorFlag != 0)
    std::cout << "End Result: TEST FAILED\n";
  else
    std::cout << "End Result: TEST PASSED\n";
  
  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);
  Kokkos::finalize();
  return errorFlag;
}
Пример #12
0
void Projector::projectFunctionOntoBasis(FieldContainer<double> &basisCoefficients, Teuchos::RCP<AbstractFunction> fxn, BasisPtr basis,
                                         const FieldContainer<double> &physicalCellNodes) {

  CellTopoPtr cellTopo = basis->domainTopology();
  DofOrderingPtr dofOrderPtr = Teuchos::rcp(new DofOrdering());

  int basisRank = BasisFactory::basisFactory()->getBasisRank(basis);
  int ID = 0; // only one entry for this fake dofOrderPtr
  dofOrderPtr->addEntry(ID,basis,basisRank);
  int maxTrialDegree = dofOrderPtr->maxBasisDegree();

  // do not build side caches - no projections for sides supported at the moment
  if (cellTopo->getTensorialDegree() != 0) {
    cout << "Projector::projectFunctionOntoBasis() does not yet support tensorial degree > 0.\n";
    TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "Projector::projectFunctionOntoBasis() does not yet support tensorial degree > 0.");
  }
  shards::CellTopology shardsTopo = cellTopo->getShardsTopology();
  BasisCache basisCache(physicalCellNodes, shardsTopo, *(dofOrderPtr), maxTrialDegree, false);
  // assume only L2 projections
  IntrepidExtendedTypes::EOperatorExtended op =  IntrepidExtendedTypes::OP_VALUE;

  // have information, build inner product matrix
  int numDofs = basis->getCardinality();
  FieldContainer<double> cubPoints = basisCache.getPhysicalCubaturePoints();    

  FieldContainer<double> basisValues = *(basisCache.getTransformedValues(basis, op));
  FieldContainer<double> testBasisValues = *(basisCache.getTransformedWeightedValues(basis, op));

  int numCells = physicalCellNodes.dimension(0);
  int numPts = cubPoints.dimension(1);
  FieldContainer<double> functionValues;
  fxn->getValues(functionValues, cubPoints);  

  FieldContainer<double> gramMatrix(numCells,numDofs,numDofs);
  FieldContainer<double> ipVector(numCells,numDofs);
  FunctionSpaceTools::integrate<double>(gramMatrix,basisValues,testBasisValues,COMP_BLAS);
  FunctionSpaceTools::integrate<double>(ipVector,functionValues,testBasisValues,COMP_BLAS); 
  
  basisCoefficients.resize(numCells,numDofs);
  for (int cellIndex=0; cellIndex<numCells; cellIndex++){

    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));
    
    /*
    cout << "matrix A = " << endl;
    for (int i=0;i<gramMatrix.dimension(2);i++){
      for (int j=0;j<gramMatrix.dimension(1);j++){
	cout << A(i,j) << " ";
      }
      cout << endl;
    }
    cout << endl;

    cout << "vector B = " << endl;
    for (int i=0;i<functionValues.dimension(1);i++){
      cout << b(i) << endl;
    }
    */

    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;
      }
    }

    for (int i=0;i<numDofs;i++){
      basisCoefficients(cellIndex,i) = x(i);
    }   
    
  } 
}
Пример #13
0
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);
        }
      }
    }
    
  }
}
Пример #14
0
void ParametricSurface::basisWeightsForProjectedInterpolant(FieldContainer<double> &basisCoefficients, VectorBasisPtr basis,
    MeshPtr mesh, int cellID)
{
  vector< ParametricCurvePtr > curves = mesh->parametricEdgesForCell(cellID);
  Teuchos::RCP<TransfiniteInterpolatingSurface> exactSurface = Teuchos::rcp( new TransfiniteInterpolatingSurface(curves) );
  exactSurface->setNeglectVertices(false);

  FieldContainer<double> edgeInterpolationCoefficients(basis->getCardinality());
  basisWeightsForEdgeInterpolant(edgeInterpolationCoefficients, basis, mesh, cellID);

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

  TFunctionPtr<double> edgeInterpolant = Teuchos::rcp( new BasisSumFunction(basis, edgeInterpolationCoefficients) );

  IPPtr L2 = Teuchos::rcp( new IP );
  // we assume that basis is a vector HGRAD basis
  VarFactoryPtr vf = VarFactory::varFactory();
  VarPtr v = vf->testVar("v", VECTOR_HGRAD);
  L2->addTerm(v);

  IPPtr H1 = Teuchos::rcp( new IP );
//  H1->addTerm(v); // experiment: seminorm is a norm when the edge dofs are excluded--and this is what LD does
  H1->addTerm(v->grad());

  int maxTestDegree = mesh->getElementType(cellID)->testOrderPtr->maxBasisDegree();
  TEUCHOS_TEST_FOR_EXCEPTION(maxTestDegree < 1, std::invalid_argument, "Constant test spaces unsupported.");

  int cubatureDegree = std::max(maxTestDegree*2,15); // chosen to match that used in edge projection.
  
  FieldContainer<double> physicalCellNodes;
  CellTopoPtr cellTopo = mesh->getElementType(cellID)->cellTopoPtr;
  if (cellTopo->getDimension() == 2)
  {
    physicalCellNodes = mesh->physicalCellNodesForCell(cellID);
  }
  if ((cellTopo->getDimension() == 3) && (cellTopo->getTensorialDegree() > 0))
  {
    // then we interpret this as space-time, and we just treat the first temporal side:
    unsigned temporalSideOrdinal = cellTopo->getTemporalSideOrdinal(0);
    FieldContainer<double> spaceTimePhysicalNodes = mesh->physicalCellNodesForCell(cellID);
    int sideDim = cellTopo->getDimension() - 1;
    int nodeCount = cellTopo->getNodeCount(sideDim, temporalSideOrdinal);
    physicalCellNodes.resize(1,nodeCount,sideDim);
    for (int node=0; node<nodeCount; node++)
    {
      int spaceTimeNode = cellTopo->getNodeMap(sideDim, temporalSideOrdinal, node);
      for (int d=0; d<sideDim; d++)
      {
        physicalCellNodes(0,node,d) = spaceTimePhysicalNodes(0,spaceTimeNode,d);
      }
    }
    // replace space-time cell topology with the purely spatial one:
    cellTopo = cellTopo->getSide(temporalSideOrdinal);
  }
  
  BasisCachePtr basisCache = BasisCache::basisCacheForCellTopology(cellTopo, cubatureDegree, physicalCellNodes);

  // project, skipping edgeNodeFieldIndices:
  Projector<double>::projectFunctionOntoBasis(basisCoefficients, TFunctionPtr<double>(exactSurface)-edgeInterpolant, basis, basisCache, H1, v, edgeFieldIndices);

  basisCoefficients.resize(basis->getCardinality()); // get rid of dummy numCells dimension
  // add the two sets of basis coefficients together
  for (int i=0; i<edgeInterpolationCoefficients.size(); i++)
  {
    basisCoefficients[i] += edgeInterpolationCoefficients[i];
  }
}
Пример #15
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";
    }
  }*/
}
Пример #16
0
int main(int argc, char *argv[]) {

  Teuchos::GlobalMPISession mpiSession(&argc, &argv);

  // This little trick lets us print to std::cout only if
  // a (dummy) command-line argument is provided.
  int iprint     = argc - 1;
  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing
  if (iprint > 0)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs, false);

  // Save the format state of the original std::cout.
  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);

  *outStream \
    << "===============================================================================\n" \
    << "|                                                                             |\n" \
    << "|               Unit Test (Basis_HGRAD_LINE_Cn_FEM_JACOBI)                    |\n" \
    << "|                                                                             |\n" \
    << "|     1) Conversion of Dof tags into Dof ordinals and back                    |\n" \
    << "|     2) Basis values for VALUE, GRAD, CURL, and Dk operators                 |\n" \
    << "|                                                                             |\n" \
    << "|  Questions? Contact  Pavel Bochev  ([email protected]),                    |\n" \
    << "|                      Denis Ridzal  ([email protected]),                    |\n" \
    << "|                      Kara Peterson ([email protected]).                    |\n" \
    << "|                                                                             |\n" \
    << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n" \
    << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
    << "|                                                                             |\n" \
    << "===============================================================================\n"\
    << "| TEST 1: Basis creation, exception testing                                   |\n"\
    << "===============================================================================\n";

  
  // Define basis and error flag
  double alpha = 0.0, beta = 0.0;
  Basis_HGRAD_LINE_Cn_FEM_JACOBI<double, FieldContainer<double> > lineBasis(5, alpha, beta);
  int errorFlag = 0;

  // Initialize throw counter for exception testing
  int nException     = 0;
  int throwCounter   = 0;
  
  // Define array containing vertices of the reference Line and a few other points   
  int numIntervals = 100;
  FieldContainer<double> lineNodes(numIntervals+1, 1);
  for (int i=0; i<numIntervals+1; i++) {
    lineNodes(i,0) = -1.0+(2.0*(double)i)/(double)numIntervals;
  }

  // Generic array for the output values; needs to be properly resized depending on the operator type
  FieldContainer<double> vals;

  try{
    // Exceptions 1-5: all bf tags/bf Ids below are wrong and should cause getDofOrdinal() and
    // getDofTag() to access invalid array elements thereby causing bounds check exception
    // exception #1
    INTREPID_TEST_COMMAND( lineBasis.getDofOrdinal(2,0,0), throwCounter, nException );
    // exception #2
    INTREPID_TEST_COMMAND( lineBasis.getDofOrdinal(1,1,1), throwCounter, nException );
    // exception #3
    INTREPID_TEST_COMMAND( lineBasis.getDofOrdinal(1,0,7), throwCounter, nException );
    // not an exception
    INTREPID_TEST_COMMAND( lineBasis.getDofOrdinal(1,0,5), throwCounter, nException ); --nException;
    // exception #4
    INTREPID_TEST_COMMAND( lineBasis.getDofTag(6), throwCounter, nException );
    // exception #5
    INTREPID_TEST_COMMAND( lineBasis.getDofTag(-1), throwCounter, nException );
    // not an exception
    INTREPID_TEST_COMMAND( lineBasis.getDofTag(5), throwCounter, nException ); --nException;
#ifdef HAVE_INTREPID_DEBUG
    // Exceptions 6-16 test exception handling with incorrectly dimensioned input/output arrays
    // exception #6: input points array must be of rank-2
    FieldContainer<double> badPoints1(4, 5, 3);
    INTREPID_TEST_COMMAND( lineBasis.getValues(vals, badPoints1, OPERATOR_VALUE), throwCounter, nException );

    // exception #7: dimension 1 in the input point array must equal space dimension of the cell
    FieldContainer<double> badPoints2(4, 3);
    INTREPID_TEST_COMMAND( lineBasis.getValues(vals, badPoints2, OPERATOR_VALUE), throwCounter, nException );

    // exception #8: output values must be of rank-2 for OPERATOR_VALUE
    FieldContainer<double> badVals1(4, 3, 1);
    INTREPID_TEST_COMMAND( lineBasis.getValues(badVals1, lineNodes, OPERATOR_VALUE), throwCounter, nException );

    // exception #9: output values must be of rank-3 for OPERATOR_GRAD
    FieldContainer<double> badVals2(4, 3);
    INTREPID_TEST_COMMAND( lineBasis.getValues(badVals2, lineNodes, OPERATOR_GRAD), throwCounter, nException );

    // exception #10: output values must be of rank-3 for OPERATOR_CURL
    INTREPID_TEST_COMMAND( lineBasis.getValues(badVals2, lineNodes, OPERATOR_CURL), throwCounter, nException );

    // exception #11: output values must be of rank-2 for OPERATOR_DIV
    INTREPID_TEST_COMMAND( lineBasis.getValues(badVals2, lineNodes, OPERATOR_DIV), throwCounter, nException );

    // exception #12: output values must be of rank-2 for OPERATOR_D1
    INTREPID_TEST_COMMAND( lineBasis.getValues(badVals2, lineNodes, OPERATOR_D1), throwCounter, nException );

    // exception #13: incorrect 0th dimension of output array (must equal number of basis functions)
    FieldContainer<double> badVals3(lineBasis.getCardinality() + 1, lineNodes.dimension(0));
    INTREPID_TEST_COMMAND( lineBasis.getValues(badVals3, lineNodes, OPERATOR_VALUE), throwCounter, nException );

    // exception #14: incorrect 1st dimension of output array (must equal number of points)
    FieldContainer<double> badVals4(lineBasis.getCardinality(), lineNodes.dimension(0) + 1);
    INTREPID_TEST_COMMAND( lineBasis.getValues(badVals4, lineNodes, OPERATOR_VALUE), throwCounter, nException );

    // exception #15: incorrect 2nd dimension of output array (must equal spatial dimension)
    FieldContainer<double> badVals5(lineBasis.getCardinality(), lineNodes.dimension(0), 2);
    INTREPID_TEST_COMMAND( lineBasis.getValues(badVals5, lineNodes, OPERATOR_GRAD), throwCounter, nException );

    // not an exception
    FieldContainer<double> goodVals2(lineBasis.getCardinality(), lineNodes.dimension(0));
    INTREPID_TEST_COMMAND( lineBasis.getValues(goodVals2, lineNodes, OPERATOR_VALUE), throwCounter, nException ); --nException;
#endif

  }
  catch (std::logic_error err) {
    *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
    *outStream << err.what() << '\n';
    *outStream << "-------------------------------------------------------------------------------" << "\n\n";
    errorFlag = -1000;
  };

  // Check if number of thrown exceptions matches the one we expect
  if (throwCounter != nException) {
    errorFlag++;
    *outStream << std::setw(70) << "FAILURE! Incorrect number of exceptions." << "\n";
  }


  *outStream \
    << "\n"
    << "===============================================================================\n"\
    << "| TEST 3: orthogonality of basis functions                                    |\n"\
    << "===============================================================================\n";

  outStream -> precision(20);

  try {

    // Check orthogonality property for Legendre polynomials.
    int maxorder = 10;

    DefaultCubatureFactory<double>  cubFactory;                                   // create factory
    shards::CellTopology line(shards::getCellTopologyData< shards::Line<> >());   // create cell topology
    for (int ordi=0; ordi < maxorder; ordi++) {
      //create left basis
      Teuchos::RCP<Basis<double,FieldContainer<double> > > lineBasisLeft =
        Teuchos::rcp(new Basis_HGRAD_LINE_Cn_FEM_JACOBI<double,FieldContainer<double> >(ordi) );

      for (int ordj=0; ordj < maxorder; ordj++) {

        //create right basis
        Teuchos::RCP<Basis<double,FieldContainer<double> > > lineBasisRight =
          Teuchos::rcp(new Basis_HGRAD_LINE_Cn_FEM_JACOBI<double,FieldContainer<double> >(ordj) );

        // get cubature points and weights
        Teuchos::RCP<Cubature<double> > lineCub = cubFactory.create(line, ordi+ordj);
        int numPoints = lineCub->getNumPoints();
        FieldContainer<double> cubPoints (numPoints, lineCub->getDimension());
        FieldContainer<double> cubWeights(numPoints);
        FieldContainer<double> cubWeightsC(1, numPoints);
        lineCub->getCubature(cubPoints, cubWeights);
        // "reshape" weights
        for (int i=0; i<numPoints; i++) { cubWeightsC(0,i) = cubWeights(i); }
        

        // get basis values
        int numFieldsLeft  = lineBasisLeft ->getCardinality();
        int numFieldsRight = lineBasisRight->getCardinality();
        FieldContainer<double> valsLeft(numFieldsLeft,numPoints),
                               valsRight(numFieldsRight,numPoints);
        lineBasisLeft ->getValues(valsLeft,  cubPoints, OPERATOR_VALUE);
        lineBasisRight->getValues(valsRight, cubPoints, OPERATOR_VALUE);

        // reshape by cloning and integrate
        FieldContainer<double> valsLeftC(1, numFieldsLeft,numPoints),
                               valsRightC(1, numFieldsRight,numPoints),
                               massMatrix(1, numFieldsLeft, numFieldsRight);
        ArrayTools::cloneFields<double>(valsLeftC, valsLeft);
        ArrayTools::cloneFields<double>(valsRightC, valsRight);
        ArrayTools::scalarMultiplyDataField<double>(valsRightC, cubWeightsC, valsRightC);
        FunctionSpaceTools::integrate<double>(massMatrix, valsLeftC, valsRightC, COMP_CPP);

        // check orthogonality property
        for (int i=0; i<numFieldsLeft; i++) {
          for (int j=0; j<numFieldsRight; j++) {

            if (i==j) {
              if ( std::abs(massMatrix(0,i,j)-(double)(2.0/(2.0*j+1.0))) > INTREPID_TOL ) {
                *outStream << "Incorrect ii (\"diagonal\") value for i=" << i << ", j=" << j << ": "
                           << massMatrix(0,i,j) << " != " << "2/(2*" << j << "+1)\n\n";
                errorFlag++;
              }
            }
            else {
              if ( std::abs(massMatrix(0,i,j)) > INTREPID_TOL ) {
                *outStream << "Incorrect ij (\"off-diagonal\") value for i=" << i << ", j=" << j << ": "
                           << massMatrix(0,i,j) << " != " << "0\n\n";
                errorFlag++;
              }
            }
          }
        }

      }
    }

  }
  // Catch unexpected errors
  catch (std::logic_error err) {
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  };

  *outStream \
    << "\n"
    << "===============================================================================\n"\
    << "| TEST 4: correctness of basis function derivatives                           |\n"\
    << "===============================================================================\n";

  outStream -> precision(20);

  // function values stored by bf, then pt
  double basisValues[] = {
    1.000000000000000, 1.000000000000000, 1.000000000000000,	\
    1.000000000000000, -1.000000000000000, -0.3333333333333333, \
    0.3333333333333333, 1.000000000000000, 1.000000000000000,	\
    -0.3333333333333333, -0.3333333333333333, 1.000000000000000,	\
    -1.000000000000000, 0.4074074074074074, -0.4074074074074074,	\
    1.000000000000000};

  double basisD1Values[] = 
    {0, 0, 0, 0, 1.000000000000000, 1.000000000000000, 1.000000000000000, \
     1.000000000000000, -3.000000000000000, -1.000000000000000,		\
     1.000000000000000, 3.000000000000000, 6.000000000000000,		\
     -0.6666666666666667, -0.6666666666666667, 6.000000000000000};

  double basisD2Values[] = 
    {0, 0, 0, 0, 0, 0, 0, 0, 3.000000000000000, 3.000000000000000,	\
     3.000000000000000, 3.000000000000000, -15.00000000000000,		\
     -5.000000000000000, 5.000000000000000, 15.00000000000000};

  double basisD3Values[] = 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15.00000000000000,		\
     15.00000000000000, 15.00000000000000, 15.00000000000000};
  


  try {
    Basis_HGRAD_LINE_Cn_FEM_JACOBI<double, FieldContainer<double> > lineBasis3(3, alpha, beta);
    int numIntervals = 3;
    FieldContainer<double> lineNodes3(numIntervals+1, 1);
    FieldContainer<double> vals;
    for (int i=0; i<numIntervals+1; i++) {
      lineNodes3(i,0) = -1.0+(2.0*(double)i)/(double)numIntervals;
    }
    int numFields = lineBasis3.getCardinality();
    int numPoints = lineNodes3.dimension(0);

    // test basis values
    vals.resize(numFields, numPoints);
    lineBasis3.getValues(vals,lineNodes3,OPERATOR_VALUE);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        
        // Compute offset for (F,P) container
        int l =  j + i * numPoints;
	if (std::abs(vals(i,j) - basisValues[l]) > INTREPID_TOL) {
	  errorFlag++;
	  *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
	  
	  // Output the multi-index of the value where the error is:
	  *outStream << " At multi-index { ";
	  *outStream << i << " ";*outStream << j << " ";
	  *outStream << "}  computed value: " << vals(i,j)
		     << " but reference value: " << basisValues[l] << "\n";
	}
      }
    }

    // test basis derivatives
    vals.resize(numFields, numPoints,1);
    lineBasis3.getValues(vals,lineNodes3,OPERATOR_D1);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        
        // Compute offset for (F,P) container
        int l =  j + i * numPoints;
	if (std::abs(vals(i,j,0) - basisD1Values[l]) > INTREPID_TOL) {
	  errorFlag++;
	  *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
	  
	  // Output the multi-index of the value where the error is:
	  *outStream << " At multi-index { ";
	  *outStream << i << " ";*outStream << j << " ";
	  *outStream << "}  computed value: " << vals(i,j,0)
		     << " but reference value: " << basisD1Values[l] << "\n";
	}
      }
    }

    vals.resize(numFields, numPoints,1);
    lineBasis3.getValues(vals,lineNodes3,OPERATOR_D2);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        
        // Compute offset for (F,P) container
        int l =  j + i * numPoints;
	if (std::abs(vals(i,j,0) - basisD2Values[l]) > INTREPID_TOL) {
	  errorFlag++;
	  *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
	  
	  // Output the multi-index of the value where the error is:
	  *outStream << " At multi-index { ";
	  *outStream << i << " ";*outStream << j << " ";
	  *outStream << "}  computed value: " << vals(i,j,0)
		     << " but reference value: " << basisD2Values[l] << "\n";
	}
      }
    }

    vals.resize(numFields, numPoints,1);
    lineBasis3.getValues(vals,lineNodes3,OPERATOR_D3);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        
        // Compute offset for (F,P) container
        int l =  j + i * numPoints;
	if (std::abs(vals(i,j,0) - basisD3Values[l]) > INTREPID_TOL) {
	  errorFlag++;
	  *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
	  
	  // Output the multi-index of the value where the error is:
	  *outStream << " At multi-index { ";
	  *outStream << i << " ";*outStream << j << " ";
	  *outStream << "}  computed value: " << vals(i,j,0)
		     << " but reference value: " << basisD3Values[l] << "\n";
	}
      }
    }
  }
  // Catch unexpected errors
  catch (std::logic_error err) {
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  };


  if (errorFlag != 0)
    std::cout << "End Result: TEST FAILED\n";
  else
    std::cout << "End Result: TEST PASSED\n";

  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);

  return errorFlag;
}
Пример #17
0
int main(int argc, char *argv[]) {

  Teuchos::GlobalMPISession mpiSession(&argc, &argv);

  // This little trick lets us print to std::cout only if
  // a (dummy) command-line argument is provided.
  int iprint     = argc - 1;
  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing
  if (iprint > 0)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs, false);
  
  // Save the format state of the original std::cout.
  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);
  
  *outStream \
    << "===============================================================================\n" \
    << "|                                                                             |\n" \
    << "|                 Unit Test (Basis_HCURL_HEX_In_FEM)                          |\n" \
    << "|                                                                             |\n" \
    << "|     1) Conversion of Dof tags into Dof ordinals and back                    |\n" \
    << "|     2) Basis values for VALUE and CURL operators                            |\n" \
    << "|                                                                             |\n" \
    << "|  Questions? Contact  Pavel Bochev  ([email protected]),                    |\n" \
    << "|                      Denis Ridzal  ([email protected]),                    |\n" \
    << "|                      Kara Peterson ([email protected]).                    |\n" \
    << "|                                                                             |\n" \
    << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n" \
    << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
    << "|                                                                             |\n" \
    << "===============================================================================\n"\
    << "| TEST 1: Basis creation, exception testing                                   |\n"\
    << "===============================================================================\n";
  
  // Define basis and error flag
  const int deg = 1;
  shards::CellTopology line(shards::getCellTopologyData< shards::Line<> >()); 
  FieldContainer<double> closedPts(PointTools::getLatticeSize(line,deg),1);
  FieldContainer<double> openPts(PointTools::getLatticeSize(line,deg+1,1),1);
  PointTools::getLattice<double,FieldContainer<double> >(closedPts,line,deg);
  PointTools::getLattice<double,FieldContainer<double> >(openPts,line,deg+1,1);

  Basis_HCURL_HEX_In_FEM<double, FieldContainer<double> > hexBasis(deg,closedPts,openPts);
  int errorFlag = 0;

  // Initialize throw counter for exception testing
  int nException     = 0;
  int throwCounter   = 0;

  // Define array containing the 8 vertices of the reference HEX, its center and 6 face centers
  FieldContainer<double> hexNodes(8, 3);
  hexNodes(0,0) = -1.0; hexNodes(0,1) = -1.0; hexNodes(0,2) = -1.0;
  hexNodes(1,0) = 1.0; hexNodes(1,1) = -1.0; hexNodes(1,2) = -1.0;
  hexNodes(2,0) = -1.0; hexNodes(2,1) = 1.0; hexNodes(2,2) = -1.0;
  hexNodes(3,0) = 1.0; hexNodes(3,1) = 1.0; hexNodes(3,2) = -1.0;
  hexNodes(4,0) = -1.0; hexNodes(4,1) = -1.0; hexNodes(4,2) = 1.0;
  hexNodes(5,0) = 1.0; hexNodes(5,1) = -1.0; hexNodes(5,2) = 1.0;
  hexNodes(6,0) = -1.0; hexNodes(6,1) = 1.0; hexNodes(6,2) = 1.0;
  hexNodes(7,0) = 1.0; hexNodes(7,1) = 1.0; hexNodes(7,2) = 1.0;


  
  // Generic array for the output values; needs to be properly resized depending on the operator type
  FieldContainer<double> vals;

  try{
    // exception #1: GRAD cannot be applied to HCURL functions 
    // resize vals to rank-3 container with dimensions (num. basis functions, num. points, arbitrary)
    vals.resize(hexBasis.getCardinality(), hexNodes.dimension(0), 4 );
    INTREPID_TEST_COMMAND( hexBasis.getValues(vals, hexNodes, OPERATOR_GRAD), throwCounter, nException );

    // exception #2: DIV cannot be applied to HCURL functions
    // resize vals to rank-2 container with dimensions (num. points, num. basis functions)
    vals.resize(hexBasis.getCardinality(), hexNodes.dimension(0) );
    INTREPID_TEST_COMMAND( hexBasis.getValues(vals, hexNodes, OPERATOR_DIV), throwCounter, nException );
        
    // Exceptions 3-7: all bf tags/bf Ids below are wrong and should cause getDofOrdinal() and 
    // getDofTag() to access invalid array elements thereby causing bounds check exception
    // exception #3
    INTREPID_TEST_COMMAND( hexBasis.getDofOrdinal(3,0,0), throwCounter, nException );
    // exception #4
    INTREPID_TEST_COMMAND( hexBasis.getDofOrdinal(1,1,1), throwCounter, nException );
    // exception #5
    INTREPID_TEST_COMMAND( hexBasis.getDofOrdinal(0,4,1), throwCounter, nException );
    // exception #6
    INTREPID_TEST_COMMAND( hexBasis.getDofTag(12), throwCounter, nException );
    // exception #7
    INTREPID_TEST_COMMAND( hexBasis.getDofTag(-1), throwCounter, nException );
    
#ifdef HAVE_INTREPID_DEBUG
    // Exceptions 8-15 test exception handling with incorrectly dimensioned input/output arrays
    // exception #8: input points array must be of rank-2
    FieldContainer<double> badPoints1(4, 5, 3);
    INTREPID_TEST_COMMAND( hexBasis.getValues(vals, badPoints1, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #9 dimension 1 in the input point array must equal space dimension of the cell
    FieldContainer<double> badPoints2(4, 2);
    INTREPID_TEST_COMMAND( hexBasis.getValues(vals, badPoints2, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #10 output values must be of rank-3 for OPERATOR_VALUE
    FieldContainer<double> badVals1(4, 3);
    INTREPID_TEST_COMMAND( hexBasis.getValues(badVals1, hexNodes, OPERATOR_VALUE), throwCounter, nException );
 
    // exception #11 output values must be of rank-3 for OPERATOR_CURL
    INTREPID_TEST_COMMAND( hexBasis.getValues(badVals1, hexNodes, OPERATOR_CURL), throwCounter, nException );
    
    // exception #12 incorrect 0th dimension of output array (must equal number of basis functions)
    FieldContainer<double> badVals2(hexBasis.getCardinality() + 1, hexNodes.dimension(0), 3);
    INTREPID_TEST_COMMAND( hexBasis.getValues(badVals2, hexNodes, OPERATOR_VALUE), throwCounter, nException ) ;
    
    // exception #13 incorrect 1st  dimension of output array (must equal number of points)
    FieldContainer<double> badVals3(hexBasis.getCardinality(), hexNodes.dimension(0) + 1, 3);
    INTREPID_TEST_COMMAND( hexBasis.getValues(badVals3, hexNodes, OPERATOR_VALUE), throwCounter, nException ) ;

    // exception #14: incorrect 2nd dimension of output array (must equal the space dimension)
    FieldContainer<double> badVals4(hexBasis.getCardinality(), hexNodes.dimension(0), 4);
    INTREPID_TEST_COMMAND( hexBasis.getValues(badVals4, hexNodes, OPERATOR_VALUE), throwCounter, nException ) ;
    
    // exception #15: incorrect 2nd dimension of output array (must equal the space dimension)
    INTREPID_TEST_COMMAND( hexBasis.getValues(badVals4, hexNodes, OPERATOR_CURL), throwCounter, nException ) ;
    
    // exception #16: D2 cannot be applied to HCURL functions 
    // resize vals to rank-3 container with dimensions (num. basis functions, num. points, arbitrary)
    vals.resize(hexBasis.getCardinality(), 
                hexNodes.dimension(0),  
                Intrepid2::getDkCardinality(OPERATOR_D2, hexBasis.getBaseCellTopology().getDimension()));
    INTREPID_TEST_COMMAND( hexBasis.getValues(vals, hexNodes, OPERATOR_D2), throwCounter, nException );
    
#endif
    
  }
  catch (std::logic_error err) {
    *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
    *outStream << err.what() << '\n';
    *outStream << "-------------------------------------------------------------------------------" << "\n\n";
    errorFlag = -1000;
  };
  
  // Check if number of thrown exceptions matches the one we expect 
  // Note Teuchos throw number will not pick up exceptions 3-7 and therefore will not match.
  if (throwCounter != nException) {
    errorFlag++;
    *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
  }
//#endif
  
  *outStream \
    << "\n"
    << "===============================================================================\n"\
    << "| TEST 2: correctness of tag to enum and enum to tag lookups                  |\n"\
    << "===============================================================================\n";
  
  try{
    std::vector<std::vector<int> > allTags = hexBasis.getAllDofTags();
    
    // Loop over all tags, lookup the associated dof enumeration and then lookup the tag again
    for (unsigned i = 0; i < allTags.size(); i++) {
      int bfOrd  = hexBasis.getDofOrdinal(allTags[i][0], allTags[i][1], allTags[i][2]);

//       for (unsigned j=0;j<4;j++) std::cout << allTags[i][j] << " "; std::cout << std::endl;
      
      std::vector<int> myTag = hexBasis.getDofTag(bfOrd);
       if( !( (myTag[0] == allTags[i][0]) &&
              (myTag[1] == allTags[i][1]) &&
              (myTag[2] == allTags[i][2]) &&
              (myTag[3] == allTags[i][3]) ) ) {
        errorFlag++;
        *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
        *outStream << " getDofOrdinal( {" 
          << allTags[i][0] << ", " 
          << allTags[i][1] << ", " 
          << allTags[i][2] << ", " 
          << allTags[i][3] << "}) = " << bfOrd <<" but \n";   
        *outStream << " getDofTag(" << bfOrd << ") = { "
          << myTag[0] << ", " 
          << myTag[1] << ", " 
          << myTag[2] << ", " 
          << myTag[3] << "}\n";        
      }
    }
    
    // Now do the same but loop over basis functions
    for( int bfOrd = 0; bfOrd < hexBasis.getCardinality(); bfOrd++) {
      std::vector<int> myTag  = hexBasis.getDofTag(bfOrd);
      int myBfOrd = hexBasis.getDofOrdinal(myTag[0], myTag[1], myTag[2]);
      if( bfOrd != myBfOrd) {
        errorFlag++;
        *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
        *outStream << " getDofTag(" << bfOrd << ") = { "
          << myTag[0] << ", " 
          << myTag[1] << ", " 
          << myTag[2] << ", " 
          << myTag[3] << "} but getDofOrdinal({" 
          << myTag[0] << ", " 
          << myTag[1] << ", " 
          << myTag[2] << ", " 
          << myTag[3] << "} ) = " << myBfOrd << "\n";
      }
    }
  }
  catch (std::logic_error err){
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  };
  
  *outStream \
    << "\n"
    << "===============================================================================\n"\
    << "| TEST 3: correctness of basis function values                                |\n"\
    << "===============================================================================\n";
  
  outStream -> precision(20);
  
  // VALUE: Each row pair gives the 12x3 correct basis set values at an evaluation point: (P,F,D) layout
  double basisValues[] = {
    1,0,0, 1,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0,
    0,0,0, 0,0,0, 1,0,0, 1,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0,
    0,0,0, 0,0,0, 0,0,0, 0,0,0, 1,0,0, 1,0,0, 0,0,0, 0,0,0,
    0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 1,0,0, 1,0,0,
    0,1,0, 0,0,0, 0,1,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0,
    0,0,0, 0,1,0, 0,0,0, 0,1,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0,
    0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,1,0, 0,0,0, 0,1,0, 0,0,0,
    0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,1,0, 0,0,0, 0,1,0,
    0,0,1, 0,0,0, 0,0,0, 0,0,0, 0,0,1, 0,0,0, 0,0,0, 0,0,0,
    0,0,0, 0,0,1, 0,0,0, 0,0,0, 0,0,0, 0,0,1, 0,0,0, 0,0,0,
    0,0,0, 0,0,0, 0,0,1, 0,0,0, 0,0,0, 0,0,0, 0,0,1, 0,0,0,
    0,0,0, 0,0,0, 0,0,0, 0,0,1, 0,0,0, 0,0,0, 0,0,0, 0,0,1
  };
  
  // CURL
  
  double basisCurls[] = {   
    0,-0.5,0.5, 0,-0.5,0.5, 0,0,0.5, 0,0,0.5, 0,-0.5,0, 0,-0.5,0, 0,0,0, 0,0,0,
    0,0,-0.5, 0,0,-0.5, 0,-0.5,-0.5, 0,-0.5,-0.5, 0,0,0, 0,0,0, 0,-0.5,0, 0,-0.5,0,
    0,0.5,0, 0,0.5,0, 0,0,0, 0,0,0, 0,0.5,0.5, 0,0.5,0.5, 0,0,0.5, 0,0,0.5,
    0,0,0, 0,0,0, 0,0.5,0, 0,0.5,0, 0,0,-0.5, 0,0,-0.5, 0,0.5,-0.5, 0,0.5,-0.5,
    // y-component basis functions
    // first y-component bf is (0,1/4(1-x)(1-z),0)
    // curl is (1/4(1-x),0,-1/4(1-z))
    0.5,0,-0.5, 0,0,-0.5, 0.5,0,-0.5, 0,0,-0.5, 0.5,0,0, 0,0,0, 0.5,0,0, 0,0,0,
    // second y-component bf is (0,1/4(1+x)(1-z),0)
    // curl is (1/4(1+x),0,1/4(1-z))
    0,0,0.5, 0.5,0,0.5, 0,0,0.5, 0.5,0,0.5, 0,0,0, 0.5,0,0, 0,0,0, 0.5,0,0,
    // third y-component bf is (0,1/4(1-x)(1+z),0)
    // curl is (-1/4(1-x),0,-1/4(1+z))
    -0.5,0,0, 0,0,0, -0.5,0,0, 0,0,0, -0.5,0,-0.5, 0,0,-0.5, -0.5,0,-0.5, 0,0,-0.5,
    // fourth y-component bf is (0,1/4(1+x)(1+z),0)
    // curl is (-1/4(1+x),0,1/4(1+z))
    0.0,0,0, -0.5,0,0, 0.0,0,0, -0.5,0,0, 0.0,0,0.5, -0.5,0,0.5, 0.0,0,0.5, -0.5,0,0.5,
    // first z-component bf is (0,0,1/4(1-x)(1-y))
    // curl is (-1/4(1-x),1/4(1-y),0)
    -0.5,0.5,0, 0,0.5,0, -0.5,0,0, 0,0,0, -0.5,0.5,0, 0,0.5,0, -0.5,0,0, 0,0,0,
    // second z-component bf is (0,0,1/4(1+x)(1-y))
    // curl is (-1/4(1+x),1/4(1-y),0)
    0.0,-0.5,0, -0.5,-0.5,0, 0,0,0, -0.5,0,0, 0,-0.5,0, -0.5,-0.5,0, 0,0,0, -0.5,0,0, 
    // third z-component bf is (0,0,1/4(1-x)(1+y))
    // curl is (1/4(1-x),1/4(1+y),0)
    0.5,0,0, 0,0,0, 0.5,0.5,0, 0,0.5,0, 0.5,0,0, 0,0,0, 0.5,0.5,0, 0,0.5,0, 
    // fourth z-component bf is (0,0,1/4(1+x)(1+y))
    // curl is (1/4(1+x),-1/4(1+y),0)
    0,0,0, 0.5,0,0, 0,-0.5,0, 0.5,-0.5,0, 0,0,0, 0.5,0,0, 0,-0.5,0, 0.5,-0.5,0 
  };

  
  try{
        
    // Dimensions for the output arrays:
    int numFields = hexBasis.getCardinality();
    int numPoints = hexNodes.dimension(0);
    int spaceDim  = hexBasis.getBaseCellTopology().getDimension();
    
    // Generic array for values and curls that will be properly sized before each call
    FieldContainer<double> vals;
    
    // Check VALUE of basis functions: resize vals to rank-3 container:
    vals.resize(numFields, numPoints, spaceDim);
    hexBasis.getValues(vals, hexNodes, OPERATOR_VALUE);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < spaceDim; k++) {
          
          // compute offset for (P,F,D) data layout: indices are P->j, F->i, D->k
          int l = k + i * spaceDim * numPoints + j * spaceDim;
           if (std::abs(vals(i,j,k) - basisValues[l]) > INTREPID_TOL) {
             errorFlag++;
             *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
        
             // Output the multi-index of the value where the error is: 
             *outStream << " At multi-index { ";
             *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
             *outStream << "}  computed value: " << vals(i,j,k)
               << " but reference value: " << basisValues[l] << "\n";
            }
         }
      }
    }
    
    // Check CURL of basis function: resize vals to rank-3 container
    vals.resize(numFields, numPoints, spaceDim);
    hexBasis.getValues(vals, hexNodes, OPERATOR_CURL);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < spaceDim; k++) {
          // compute offset for (P,F,D) data layout: indices are P->j, F->i, D->k
           int l = k + i * spaceDim * numPoints + j * spaceDim;
           if (std::abs(vals(i,j,k) - basisCurls[l]) > INTREPID_TOL) {
             errorFlag++;
             *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
        
             // Output the multi-index of the value where the error is: 
             *outStream << " At multi-index { ";
             *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
             *outStream << "}  computed curl component: " << vals(i,j,k) 
               << " but reference curl component: " << basisCurls[l] << "\n";
            }
         }
      }
    }
    
   }    
  
  // Catch unexpected errors
  catch (std::logic_error err) {
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  };
  
  if (errorFlag != 0)
    std::cout << "End Result: TEST FAILED\n";
  else
    std::cout << "End Result: TEST PASSED\n";
  
  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);
  
  return errorFlag;
}
Пример #18
0
int main(int argc, char *argv[]) {
  
  Teuchos::GlobalMPISession mpiSession(&argc, &argv);

  // This little trick lets us print to std::cout only if
  // a (dummy) command-line argument is provided.
  int iprint     = argc - 1;
  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing
  if (iprint > 0)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs, false);
  
  // Save the format state of the original std::cout.
  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);
  
  *outStream \
    << "===============================================================================\n" \
    << "|                                                                             |\n" \
    << "|                 Unit Test (Basis_HGRAD_WEDGE_C2_FEM)                        |\n" \
    << "|                                                                             |\n" \
    << "|     1) Conversion of Dof tags into Dof ordinals and back                    |\n" \
    << "|     2) Basis values for VALUE, GRAD, and Dk operators                       |\n" \
    << "|                                                                             |\n" \
    << "|  Questions? Contact  Pavel Bochev  ([email protected]),                    |\n" \
    << "|                      Denis Ridzal  ([email protected]),                    |\n" \
    << "|                      Kara Peterson ([email protected]).                    |\n" \
    << "|                                                                             |\n" \
    << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n" \
    << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
    << "|                                                                             |\n" \
    << "===============================================================================\n"\
    << "| TEST 1: Basis creation, exception testing                                   |\n"\
    << "===============================================================================\n";
  
  // Define basis and error flag
  Basis_HGRAD_WEDGE_C2_FEM<double, FieldContainer<double> > wedgeBasis;
  int errorFlag = 0;

  // Initialize throw counter for exception testing
  int nException     = 0;
  int throwCounter   = 0;

  // Nodes of Wedde<18>: vertices, edge midpoints, Quadrilateral face centers 
  FieldContainer<double> wedgeNodes(18, 3);
  wedgeNodes(0,0) =  0.0;  wedgeNodes(0,1) =  0.0;  wedgeNodes(0,2) = -1.0;  
  wedgeNodes(1,0) =  1.0;  wedgeNodes(1,1) =  0.0;  wedgeNodes(1,2) = -1.0;  
  wedgeNodes(2,0) =  0.0;  wedgeNodes(2,1) =  1.0;  wedgeNodes(2,2) = -1.0;
  wedgeNodes(3,0) =  0.0;  wedgeNodes(3,1) =  0.0;  wedgeNodes(3,2) =  1.0;  
  wedgeNodes(4,0) =  1.0;  wedgeNodes(4,1) =  0.0;  wedgeNodes(4,2) =  1.0;  
  wedgeNodes(5,0) =  0.0;  wedgeNodes(5,1) =  1.0;  wedgeNodes(5,2) =  1.0;
    
  wedgeNodes(6,0) =  0.5;  wedgeNodes(6,1) =  0.0;  wedgeNodes(6,2) = -1.0;  
  wedgeNodes(7,0) =  0.5;  wedgeNodes(7,1) =  0.5;  wedgeNodes(7,2) = -1.0;  
  wedgeNodes(8,0) =  0.0;  wedgeNodes(8,1) =  0.5;  wedgeNodes(8,2) = -1.0;
  wedgeNodes(9,0) =  0.0;  wedgeNodes(9,1) =  0.0;  wedgeNodes(9,2) =  0.0;
  wedgeNodes(10,0)=  1.0;  wedgeNodes(10,1)=  0.0;  wedgeNodes(10,2)=  0.0;  
  wedgeNodes(11,0)=  0.0;  wedgeNodes(11,1)=  1.0;  wedgeNodes(11,2)=  0.0;  
 
  wedgeNodes(12,0)=  0.5;  wedgeNodes(12,1)=  0.0;  wedgeNodes(12,2)=  1.0;  
  wedgeNodes(13,0)=  0.5;  wedgeNodes(13,1)=  0.5;  wedgeNodes(13,2)=  1.0;  
  wedgeNodes(14,0)=  0.0;  wedgeNodes(14,1)=  0.5;  wedgeNodes(14,2)=  1.0;  
  wedgeNodes(15,0)=  0.5;  wedgeNodes(15,1)=  0.0;  wedgeNodes(15,2)=  0.0;  
  wedgeNodes(16,0)=  0.5;  wedgeNodes(16,1)=  0.5;  wedgeNodes(16,2)=  0.0;  
  wedgeNodes(17,0)=  0.0;  wedgeNodes(17,1)=  0.5;  wedgeNodes(17,2)=  0.0;  


  // Generic array for the output values; needs to be properly resized depending on the operator type
  FieldContainer<double> vals;

  try{
    // exception #1: CURL cannot be applied to scalar functions
    // resize vals to rank-3 container with dimensions (num. points, num. basis functions)
    vals.resize(wedgeBasis.getCardinality(), wedgeNodes.dimension(0), 3 );
    INTREPID_TEST_COMMAND( wedgeBasis.getValues(vals, wedgeNodes, OPERATOR_DIV), throwCounter, nException );

    // exception #2: DIV cannot be applied to scalar functions
    // resize vals to rank-2 container with dimensions (num. points, num. basis functions)
    vals.resize(wedgeBasis.getCardinality(), wedgeNodes.dimension(0) );
    INTREPID_TEST_COMMAND( wedgeBasis.getValues(vals, wedgeNodes, OPERATOR_DIV), throwCounter, nException );
        
    // Exceptions 3-7: all bf tags/bf Ids below are wrong and should cause getDofOrdinal() and 
    // getDofTag() to access invalid array elements thereby causing bounds check exception
    // exception #3
    INTREPID_TEST_COMMAND( wedgeBasis.getDofOrdinal(3,0,0), throwCounter, nException );
    // exception #4
    INTREPID_TEST_COMMAND( wedgeBasis.getDofOrdinal(1,1,1), throwCounter, nException );
    // exception #5
    INTREPID_TEST_COMMAND( wedgeBasis.getDofOrdinal(0,9,0), throwCounter, nException );
    // exception #6
    INTREPID_TEST_COMMAND( wedgeBasis.getDofTag(18), throwCounter, nException );
    // exception #7
    INTREPID_TEST_COMMAND( wedgeBasis.getDofTag(-1), throwCounter, nException );
    
#ifdef HAVE_INTREPID_DEBUG
    // Exceptions 8-18 test exception handling with incorrectly dimensioned input/output arrays
    // exception #8: input points array must be of rank-2
    FieldContainer<double> badPoints1(4, 5, 3);
    INTREPID_TEST_COMMAND( wedgeBasis.getValues(vals, badPoints1, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #9 dimension 1 in the input point array must equal space dimension of the cell
    FieldContainer<double> badPoints2(4, wedgeBasis.getBaseCellTopology().getDimension() + 1);
    INTREPID_TEST_COMMAND( wedgeBasis.getValues(vals, badPoints2, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #10 output values must be of rank-2 for OPERATOR_VALUE
    FieldContainer<double> badVals1(4, 3, 1);
    INTREPID_TEST_COMMAND( wedgeBasis.getValues(badVals1, wedgeNodes, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #11 output values must be of rank-3 for OPERATOR_GRAD
    FieldContainer<double> badVals2(4, 3);
    INTREPID_TEST_COMMAND( wedgeBasis.getValues(badVals2, wedgeNodes, OPERATOR_GRAD), throwCounter, nException );
    
    // exception #12 output values must be of rank-3 for OPERATOR_D1
    INTREPID_TEST_COMMAND( wedgeBasis.getValues(badVals2, wedgeNodes, OPERATOR_D1), throwCounter, nException );
    
    // exception #13 output values must be of rank-3 for OPERATOR_D2
    INTREPID_TEST_COMMAND( wedgeBasis.getValues(badVals2, wedgeNodes, OPERATOR_D2), throwCounter, nException );
    
    // exception #14 incorrect 0th dimension of output array (must equal number of basis functions)
    FieldContainer<double> badVals3(wedgeBasis.getCardinality() + 1, wedgeNodes.dimension(0));
    INTREPID_TEST_COMMAND( wedgeBasis.getValues(badVals3, wedgeNodes, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #15 incorrect 1st dimension of output array (must equal number of points)
    FieldContainer<double> badVals4(wedgeBasis.getCardinality(), wedgeNodes.dimension(0) + 1);
    INTREPID_TEST_COMMAND( wedgeBasis.getValues(badVals4, wedgeNodes, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #16: incorrect 2nd dimension of output array (must equal the space dimension)
    FieldContainer<double> badVals5(wedgeBasis.getCardinality(), wedgeNodes.dimension(0), wedgeBasis.getBaseCellTopology().getDimension() - 1);
    INTREPID_TEST_COMMAND( wedgeBasis.getValues(badVals5, wedgeNodes, OPERATOR_GRAD), throwCounter, nException );
    
    // exception #17: incorrect 2nd dimension of output array (must equal D2 cardinality in 3D)
    FieldContainer<double> badVals6(wedgeBasis.getCardinality(), wedgeNodes.dimension(0), 40);
    INTREPID_TEST_COMMAND( wedgeBasis.getValues(badVals6, wedgeNodes, OPERATOR_D2), throwCounter, nException );
    
    // exception #18: incorrect 2nd dimension of output array (must equal D3 cardinality in 3D)
    INTREPID_TEST_COMMAND( wedgeBasis.getValues(badVals6, wedgeNodes, OPERATOR_D3), throwCounter, nException );
#endif

  }
  catch (std::logic_error err) {
    *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
    *outStream << err.what() << '\n';
    *outStream << "-------------------------------------------------------------------------------" << "\n\n";
    errorFlag = -1000;
  };
  
  // Check if number of thrown exceptions matches the one we expect - 18
  if (throwCounter != nException) {
    errorFlag++;
    *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
  }
  
  *outStream \
    << "\n"
    << "===============================================================================\n"\
    << "| TEST 2: correctness of tag to enum and enum to tag lookups                  |\n"\
    << "===============================================================================\n";
  
  try{
    std::vector<std::vector<int> > allTags = wedgeBasis.getAllDofTags();
    
    // Loop over all tags, lookup the associated dof enumeration and then lookup the tag again
    for (unsigned i = 0; i < allTags.size(); i++) {
      int bfOrd  = wedgeBasis.getDofOrdinal(allTags[i][0], allTags[i][1], allTags[i][2]);
      
      std::vector<int> myTag = wedgeBasis.getDofTag(bfOrd);
       if( !( (myTag[0] == allTags[i][0]) &&
              (myTag[1] == allTags[i][1]) &&
              (myTag[2] == allTags[i][2]) &&
              (myTag[3] == allTags[i][3]) ) ) {
        errorFlag++;
        *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
        *outStream << " getDofOrdinal( {" 
          << allTags[i][0] << ", " 
          << allTags[i][1] << ", " 
          << allTags[i][2] << ", " 
          << allTags[i][3] << "}) = " << bfOrd <<" but \n";   
        *outStream << " getDofTag(" << bfOrd << ") = { "
          << myTag[0] << ", " 
          << myTag[1] << ", " 
          << myTag[2] << ", " 
          << myTag[3] << "}\n";        
      }
    }
    
    // Now do the same but loop over basis functions
    for( int bfOrd = 0; bfOrd < wedgeBasis.getCardinality(); bfOrd++) {
      std::vector<int> myTag  = wedgeBasis.getDofTag(bfOrd);
      int myBfOrd = wedgeBasis.getDofOrdinal(myTag[0], myTag[1], myTag[2]);
      if( bfOrd != myBfOrd) {
        errorFlag++;
        *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
        *outStream << " getDofTag(" << bfOrd << ") = { "
          << myTag[0] << ", " 
          << myTag[1] << ", " 
          << myTag[2] << ", " 
          << myTag[3] << "} but getDofOrdinal({" 
          << myTag[0] << ", " 
          << myTag[1] << ", " 
          << myTag[2] << ", " 
          << myTag[3] << "} ) = " << myBfOrd << "\n";
      }
    }
  }
  catch (std::logic_error err){
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  };
  
  *outStream \
    << "\n"
    << "===============================================================================\n"\
    << "| TEST 3: correctness of basis function values                                |\n"\
    << "===============================================================================\n";
  
  outStream -> precision(20);
  
  // VALUE: correct basis function values in (F,P) format
  double basisValues[] = {
    1.00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.00, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.00, 0, 0, 0, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.00, 0, 0, 0, 0, 0, 0, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 1.00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    0, 0, 0, 0, 0, 1.00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    0, 0, 1.00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    1.00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.00, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.00, 0, 0, 0, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.00, 0, 0, 0, 0, 0, 0, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 1.00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    0, 0, 0, 0, 0, 1.00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    0, 0, 1.00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    1.00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.00  };
  
  // GRAD, D1, D2, D3 and D4 test values are stored in files due to their large size
  std::string     fileName;
  std::ifstream   dataFile;
  
  // GRAD and D1 values are stored in (F,P,D) format in a data file. Read file and do the test
  std::vector<double> basisGrads;           // Flat array for the gradient values.
  
  fileName = "./testdata/WEDGE_C2_GradVals.dat";
  dataFile.open(fileName.c_str());
  TEST_FOR_EXCEPTION( !dataFile.good(), std::logic_error,
                      ">>> ERROR (HGRAD_WEDGE_C2/test01): could not open GRAD values data file, test aborted.");
  while (!dataFile.eof() ){
    double temp;
    string line;                            // string for one line of input file
    std::getline(dataFile, line);           // get next line from file
    stringstream data_line(line);           // convert to stringstream
    while(data_line >> temp){               // extract value from line
      basisGrads.push_back(temp);           // push into vector
    }
  }
  // It turns out that just closing and then opening the ifstream variable does not reset it
  // and subsequent open() command fails. One fix is to explicitely clear the ifstream, or
  // scope the variables.
  dataFile.close();
  dataFile.clear();
  
  
  //D2: flat array with the values of D2 applied to basis functions. Multi-index is (F,P,D2cardinality)
  std::vector<double> basisD2;
  
  fileName = "./testdata/WEDGE_C2_D2Vals.dat";
  dataFile.open(fileName.c_str());
  TEST_FOR_EXCEPTION( !dataFile.good(), std::logic_error,
                      ">>> ERROR (HGRAD_WEDGE_C2/test01): could not open D2 values data file, test aborted.");
  
  while (!dataFile.eof() ){
    double temp;
    string line;                            // string for one line of input file
    std::getline(dataFile, line);           // get next line from file
    stringstream data_line(line);           // convert to stringstream
    while(data_line >> temp){               // extract value from line
      basisD2.push_back(temp);              // push into vector
    }
  }
  dataFile.close();
  dataFile.clear();
  
  
  //D3: flat array with the values of D3 applied to basis functions. Multi-index is (F,P,D3cardinality)
  std::vector<double> basisD3;
  
  fileName = "./testdata/WEDGE_C2_D3Vals.dat";
  dataFile.open(fileName.c_str());
  TEST_FOR_EXCEPTION( !dataFile.good(), std::logic_error,
                      ">>> ERROR (HGRAD_WEDGE_C2/test01): could not open D3 values data file, test aborted.");
  
  while (!dataFile.eof() ){
    double temp;
    string line;                            // string for one line of input file
    std::getline(dataFile, line);           // get next line from file
    stringstream data_line(line);           // convert to stringstream
    while(data_line >> temp){               // extract value from line
      basisD3.push_back(temp);              // push into vector
    }
  }
  dataFile.close();
  dataFile.clear();
  
  
  //D4: flat array with the values of D3 applied to basis functions. Multi-index is (F,P,D4cardinality)
  std::vector<double> basisD4;
  
  fileName = "./testdata/WEDGE_C2_D4Vals.dat";
  dataFile.open(fileName.c_str());
  TEST_FOR_EXCEPTION( !dataFile.good(), std::logic_error,
                      ">>> ERROR (HGRAD_WEDGE_C2/test01): could not open D4 values data file, test aborted.");
  
  while (!dataFile.eof() ){
    double temp;
    string line;                            // string for one line of input file
    std::getline(dataFile, line);           // get next line from file
    stringstream data_line(line);           // convert to stringstream
    while(data_line >> temp){               // extract value from line
      basisD4.push_back(temp);              // push into vector
    }
  }
  dataFile.close();
  dataFile.clear();

  
  try{
        
    // Dimensions for the output arrays:
    int numFields = wedgeBasis.getCardinality();
    int numPoints = wedgeNodes.dimension(0);
    int spaceDim  = wedgeBasis.getBaseCellTopology().getDimension();
    
    // Generic array for values, grads, curls, etc. that will be properly sized before each call
    FieldContainer<double> vals;
    
    // Check VALUE of basis functions: resize vals to rank-2 container:
    vals.resize(numFields, numPoints);
    wedgeBasis.getValues(vals, wedgeNodes, OPERATOR_VALUE);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
          int l =  i + j * numFields;
           if (std::abs(vals(i,j) - basisValues[l]) > INTREPID_TOL) {
             errorFlag++;
             *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

             // Output the multi-index of the value where the error is:
             *outStream << " At multi-index { ";
             *outStream << i << " ";*outStream << j << " ";
             *outStream << "}  computed value: " << vals(i,j)
               << " but reference value: " << basisValues[l] << "\n";
         }
      }
    }

    
    
    // Check GRAD of basis function: resize vals to rank-3 container
    vals.resize(numFields, numPoints, spaceDim);
    wedgeBasis.getValues(vals, wedgeNodes, OPERATOR_GRAD);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < spaceDim; k++) {
          
          // basisGrads is (F,P,D), compute offset:
          int l = k + j * spaceDim + i * spaceDim * numPoints;
          if (std::abs(vals(i,j,k) - basisGrads[l]) > INTREPID_TOL) {
            errorFlag++;
            *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
            
            // Output the multi-index of the value where the error is:
            *outStream << " At multi-index { ";
            *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
            *outStream << "}  computed grad component: " << vals(i,j,k)
              << " but reference grad component: " << basisGrads[l] << "\n";
          }
        }
      }
    }
    
    // Check D1 of basis function (do not resize vals because it has the correct size: D1 = GRAD)
    wedgeBasis.getValues(vals, wedgeNodes, OPERATOR_D1);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < spaceDim; k++) {
          
          // basisGrads is (F,P,D), compute offset:
          int l = k + j * spaceDim + i * spaceDim * numPoints;
          if (std::abs(vals(i,j,k) - basisGrads[l]) > INTREPID_TOL) {
            errorFlag++;
            *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
            
            // Output the multi-index of the value where the error is:
            *outStream << " At multi-index { ";
            *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
            *outStream << "}  computed D1 component: " << vals(i,j,k)
              << " but reference D1 component: " << basisGrads[l] << "\n";
          }
        }
      }
    }
    
    
    // Check D2 of basis function
    int D2cardinality = Intrepid::getDkCardinality(OPERATOR_D2, spaceDim);
    vals.resize(numFields, numPoints, D2cardinality);    
    wedgeBasis.getValues(vals, wedgeNodes, OPERATOR_D2);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < D2cardinality; k++) {
          
          // basisD2 is (F,P,Dk), compute offset:
          int l = k + j * D2cardinality + i * D2cardinality * numPoints;
          if (std::abs(vals(i,j,k) - basisD2[l]) > INTREPID_TOL) {
            errorFlag++;
            *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
            
            // Output the multi-index of the value where the error is:
            *outStream << " At multi-index { ";
            *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
            *outStream << "}  computed D2 component: " << vals(i,j,k)
              << " but reference D2 component: " << basisD2[l] << "\n";
          }
        }
      }
    }
    
    
    // Check D3 of basis function
    int D3cardinality = Intrepid::getDkCardinality(OPERATOR_D3, spaceDim);
    vals.resize(numFields, numPoints, D3cardinality);    
    wedgeBasis.getValues(vals, wedgeNodes, OPERATOR_D3);
    
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < D3cardinality; k++) {
          
          // basisD3 is (F,P,Dk), compute offset:
          int l = k + j * D3cardinality + i * D3cardinality * numPoints;
          if (std::abs(vals(i,j,k) - basisD3[l]) > INTREPID_TOL) {
            errorFlag++;
            *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
            
            // Output the multi-index of the value where the error is:
            *outStream << " At multi-index { ";
            *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
            *outStream << "}  computed D3 component: " << vals(i,j,k)
              << " but reference D3 component: " << basisD3[l] << "\n";
          }
        }
      }
    }
    
    
    // Check D4 of basis function
    int D4cardinality = Intrepid::getDkCardinality(OPERATOR_D4, spaceDim);
    vals.resize(numFields, numPoints, D4cardinality);    
    wedgeBasis.getValues(vals, wedgeNodes, OPERATOR_D4);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < D4cardinality; k++) {
          
          // basisD4 is (F,P,Dk), compute offset:
          int l = k + j * D4cardinality + i * D4cardinality * numPoints;
          if (std::abs(vals(i,j,k) - basisD4[l]) > INTREPID_TOL) {
            errorFlag++;
            *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
            
            // Output the multi-index of the value where the error is:
            *outStream << " At multi-index { ";
            *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
            *outStream << "}  computed D4 component: " << vals(i,j,k)
              << " but reference D4 component: " << basisD2[l] << "\n";
          }
        }
      }
    }
    
        
    // Check all higher derivatives - must be zero. 
    for(EOperator op = OPERATOR_D5; op < OPERATOR_MAX; op++) {
      
      // The last dimension is the number of kth derivatives and needs to be resized for every Dk
      int DkCardin  = Intrepid::getDkCardinality(op, spaceDim);
      vals.resize(numFields, numPoints, DkCardin);    

      wedgeBasis.getValues(vals, wedgeNodes, op);
      for (int i = 0; i < vals.size(); i++) {
        if (std::abs(vals[i]) > INTREPID_TOL) {
          errorFlag++;
          *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
          
          // Get the multi-index of the value where the error is and the operator order
          std::vector<int> myIndex;
          vals.getMultiIndex(myIndex,i);
          int ord = Intrepid::getOperatorOrder(op);
          *outStream << " At multi-index { ";
          for(int j = 0; j < vals.rank(); j++) {
            *outStream << myIndex[j] << " ";
          }
          *outStream << "}  computed D"<< ord <<" component: " << vals[i] 
            << " but reference D" << ord << " component:  0 \n";
        }
      }
    }    
  }
  
  // Catch unexpected errors
  catch (std::logic_error err) {
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  };
  
  if (errorFlag != 0)
    std::cout << "End Result: TEST FAILED\n";
  else
    std::cout << "End Result: TEST PASSED\n";
  
  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);
  
  return errorFlag;
}
Пример #19
0
int main(int argc, char *argv[]) {

  Teuchos::GlobalMPISession mpiSession(&argc, &argv);

  typedef CellTools<double>       CellTools;
  typedef RealSpaceTools<double>  RealSpaceTools;
  typedef shards::CellTopology    CellTopology;

 std::cout \
  << "===============================================================================\n" \
  << "|                                                                             |\n" \
  << "|                   Example use of the CellTools class                        |\n" \
  << "|                                                                             |\n" \
  << "|  1) Computation of face flux, for a given vector field, on a face workset   |\n" \
  << "|  2) Computation of edge circulation, for a given vector field, on a face    |\n" \
  << "|     workset.                                                                |\n" \
  << "|                                                                             |\n" \
  << "|  Questions? Contact  Pavel Bochev ([email protected])                      |\n" \
  << "|                      Denis Ridzal ([email protected]), or                  |\n" \
  << "|                      Kara Peterson ([email protected])                     |\n" \
  << "|                                                                             |\n" \
  << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n" \
  << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
  << "|                                                                             |\n" \
  << "===============================================================================\n"\
  << "|  EXAMPLE 1: Computation of face flux on a face workset                      |\n"\
  << "===============================================================================\n";

  
  /**  Given a vector field u(x,y,z) and a face workset we want to compute the flux of u on every
    *  face in this workset. A face workset is a set of faces that are images of the same reference
    *  face. It is defined by the following items:
    *    1. cell topology of a parent cell
    *    2. a set of nodes in physical frame defining the parenct cells in the workset
    *    3. subcell dimension and ordinal, relative to the reference cell in 1)
    *
    *  Given a face workset, the key steps to accomplish the task, , are as follows:
    *    1. Obtain cubature points on workset faces, i.e., in physical frame;
    *    2. Obtain (non-normalized) face normals at cubature points on workset faces
    *    3. Evaluate the vector field u(x,y,z) at cubature points on workset faces
    *    4. Compute dot product of u(x,y,z) and the face normals, times the cubature weights
    */
  
  /*************************************************************************************************
    *
    *  Step 0. Face workset comprising of 1 face of a Hexahedron<8> cell
    *
    ************************************************************************************************/
  
  //   Step 0.a: Specify cell topology of the parent cell
  CellTopology hexahedron_8( shards::getCellTopologyData<shards::Hexahedron<8> >() );
  
  //   Step 0.b: Specify the vertices of the parent Hexahedron<8> cell
  int worksetSize    = 2;
  int pCellNodeCount = hexahedron_8.getVertexCount();
  int pCellDim       = hexahedron_8.getDimension();
  
  FieldContainer<double> hexNodes(worksetSize, pCellNodeCount, pCellDim);
  // cell 0 bottom face vertices:
  hexNodes(0, 0, 0) = 0.00;   hexNodes(0, 0, 1) = 0.00,   hexNodes(0, 0, 2) = 0.00;          
  hexNodes(0, 1, 0) = 1.00;   hexNodes(0, 1, 1) = 0.00,   hexNodes(0, 1, 2) = 0.00;
  hexNodes(0, 2, 0) = 1.00;   hexNodes(0, 2, 1) = 1.00,   hexNodes(0, 2, 2) = 0.00;
  hexNodes(0, 3, 0) = 0.00;   hexNodes(0, 3, 1) = 1.00,   hexNodes(0, 3, 2) = 0.00;
  // cell 0 top face vertices
  hexNodes(0, 4, 0) = 0.00;   hexNodes(0, 4, 1) = 0.00,   hexNodes(0, 4, 2) = 1.00;          
  hexNodes(0, 5, 0) = 1.00;   hexNodes(0, 5, 1) = 0.00,   hexNodes(0, 5, 2) = 1.00;
  hexNodes(0, 6, 0) = 1.00;   hexNodes(0, 6, 1) = 1.00,   hexNodes(0, 6, 2) = 1.00;
  hexNodes(0, 7, 0) = 0.00;   hexNodes(0, 7, 1) = 1.00,   hexNodes(0, 7, 2) = 1.00;
  
  // cell 1 bottom face vertices:
  hexNodes(1, 0, 0) = 0.00;   hexNodes(1, 0, 1) = 0.00,   hexNodes(1, 0, 2) = 0.00;          
  hexNodes(1, 1, 0) = 1.00;   hexNodes(1, 1, 1) = 0.00,   hexNodes(1, 1, 2) = 0.00;
  hexNodes(1, 2, 0) = 1.00;   hexNodes(1, 2, 1) = 1.00,   hexNodes(1, 2, 2) = 0.00;
  hexNodes(1, 3, 0) = 0.00;   hexNodes(1, 3, 1) = 1.00,   hexNodes(1, 3, 2) = 0.00;
  // cell 1 top face vertices
  hexNodes(1, 4, 0) = 0.00;   hexNodes(1, 4, 1) = 0.00,   hexNodes(1, 4, 2) = 1.00;          
  hexNodes(1, 5, 0) = 1.00;   hexNodes(1, 5, 1) = 0.00,   hexNodes(1, 5, 2) = 1.00;
  hexNodes(1, 6, 0) = 1.00;   hexNodes(1, 6, 1) = 1.00,   hexNodes(1, 6, 2) = 0.75;
  hexNodes(1, 7, 0) = 0.00;   hexNodes(1, 7, 1) = 1.00,   hexNodes(1, 7, 2) = 1.00;
  
  
  //   Step 0.c: Specify the face ordinal, relative to the reference cell, of the face workset
  int subcellDim = 2;
  int subcellOrd = 1;  
  
  
  
  /*************************************************************************************************
    *
    *  Step 1:    Obtain Gauss points on workset faces for Hexahedron<8> topology
    *       1.1   Define cubature factory, face parametrization domain and arrays for cubature points
    *       1.2   Select Gauss rule on D = [-1,1]x[-1,1] 
    *       1.3   Map Gauss points from D to reference face and workset faces
    *
    ************************************************************************************************/
  
  //   Step 1.1.a: Define CubatureFactory
  DefaultCubatureFactory<double>  cubFactory;   
  
  //   Step 1.1.b: Define topology of the face parametrization domain as [-1,1]x[-1,1]
  CellTopology paramQuadFace(shards::getCellTopologyData<shards::Quadrilateral<4> >() );
  
  //   Step 1.1.c: Define storage for cubature points and weights on [-1,1]x[-1,1]
  FieldContainer<double> paramGaussWeights;
  FieldContainer<double> paramGaussPoints;
  
  //   Step 1.1.d: Define storage for cubature points on a reference face
  FieldContainer<double> refGaussPoints;
  
  //   Step 1.1.f: Define storage for cubature points on workset faces
  FieldContainer<double> worksetGaussPoints;

  //----------------
  
  //   Step 1.2.a: selects Gauss rule of order 3 on [-1,1]x[-1,1]
  Teuchos::RCP<Cubature<double> > hexFaceCubature = cubFactory.create(paramQuadFace, 3); 
  
  //   Step 1.2.b allocate storage for cubature points on [-1,1]x[-1,1]
  int cubDim       = hexFaceCubature -> getDimension();
  int numCubPoints = hexFaceCubature -> getNumPoints();
  
  // Arrays must be properly sized for the specified set of Gauss points
  paramGaussPoints.resize(numCubPoints, cubDim);
  paramGaussWeights.resize(numCubPoints);
  hexFaceCubature -> getCubature(paramGaussPoints, paramGaussWeights);
  
  //----------------
  
  //   Step 1.3.a: Allocate storage for Gauss points on the reference face
  refGaussPoints.resize(numCubPoints, pCellDim);

  //   Step 1.3.b: Allocate storage for Gauss points on the face in the workset
  worksetGaussPoints.resize(worksetSize, numCubPoints, pCellDim);

  //   Step 1.3.c: Map Gauss points to reference face: paramGaussPoints -> refGaussPoints
  CellTools::mapToReferenceSubcell(refGaussPoints,
                                   paramGaussPoints,
                                   subcellDim,                      
                                   subcellOrd,
                                   hexahedron_8);

  //   Step 1.3.d: Map Gauss points from ref. face to face workset: refGaussPoints -> worksetGaussPoints
  CellTools::mapToPhysicalFrame(worksetGaussPoints,
                                refGaussPoints,
                                hexNodes,
                                hexahedron_8);
  
  
  
  /*************************************************************************************************
    *
    *  Step 2.   Obtain (non-normalized) face normals at cubature points on workset faces
    *       2.1  Compute parent cell Jacobians at Gauss points on workset faces
    *       2.2  Compute face tangents on workset faces and their vector product
    *
    ************************************************************************************************/
  
  //   Step 2.1.a: Define and allocate storage for workset Jacobians
  FieldContainer<double> worksetJacobians(worksetSize, numCubPoints, pCellDim, pCellDim);
  
  //   Step 2.1.b: Compute Jacobians at Gauss pts. on reference face for all parent cells:
  CellTools::setJacobian(worksetJacobians,
                         refGaussPoints,
                         hexNodes,
                         hexahedron_8);
  
  //----------------
  
  //   Step 2.2.a: Allocate storage for face tangents and face normals
  FieldContainer<double> worksetFaceTu(worksetSize, numCubPoints, pCellDim);
  FieldContainer<double> worksetFaceTv(worksetSize, numCubPoints, pCellDim);
  FieldContainer<double> worksetFaceN(worksetSize, numCubPoints, pCellDim);
  
  //   Step 2.2.b: Compute face tangents
  CellTools::getPhysicalFaceTangents(worksetFaceTu,
                                     worksetFaceTv,
                                     worksetJacobians,
                                     subcellOrd,
                                     hexahedron_8);
  
  //   Step 2.2.c: Face outer normals (relative to parent cell) are uTan x vTan:
  RealSpaceTools::vecprod(worksetFaceN, worksetFaceTu, worksetFaceTv);
  
  
  
  /*************************************************************************************************
    *
    *  Step 3.   Evaluate the vector field u(x,y,z) at cubature points on workset faces
    *
    ************************************************************************************************/
  
  //   Step 3.a:  Allocate storage for vector field values at Gauss points on workset faces
  FieldContainer<double> worksetVFieldVals(worksetSize, numCubPoints, pCellDim);
  
  //   Step 3.b:  Compute vector field at Gauss points: here we take u(x,y,z) = (x,y,z)
  for(int pCellOrd = 0; pCellOrd < worksetSize; pCellOrd++){
    for(int ptOrd = 0; ptOrd < numCubPoints; ptOrd++){
      
      double x = worksetGaussPoints(pCellOrd, ptOrd, 0);
      double y = worksetGaussPoints(pCellOrd, ptOrd, 1);
      double z = worksetGaussPoints(pCellOrd, ptOrd, 2);

      vField(worksetVFieldVals(pCellOrd, ptOrd, 0), 
             worksetVFieldVals(pCellOrd, ptOrd, 1), 
             worksetVFieldVals(pCellOrd, ptOrd, 2),  x, y, z);
      
    }// pt
  }//cell
  

  /*************************************************************************************************
    *
    *  Step 4.   Compute dot product of u(x,y,z) and the face normals, times the cubature weights
    *
    ************************************************************************************************/
  
  // Allocate storage for dot product of vector field and face normals at Gauss points
  FieldContainer<double> worksetFieldDotNormal(worksetSize, numCubPoints);
  
  // Compute the dot product
  RealSpaceTools::dot(worksetFieldDotNormal, worksetVFieldVals, worksetFaceN);
  
  // Allocate storage for face fluxes on the workset
  FieldContainer<double> worksetFluxes(worksetSize);
  
  //----------------
  
  // Integration loop (temporary)
  for(int pCellOrd = 0; pCellOrd < worksetSize; pCellOrd++){
    worksetFluxes(pCellOrd) = 0.0;
    for(int pt = 0; pt < numCubPoints; pt++ ){
      worksetFluxes(pCellOrd) += worksetFieldDotNormal(pCellOrd, pt)*paramGaussWeights(pt);
    }// pt
  }//cell
  
  std::cout << "Face fluxes on workset faces : \n\n";
  for(int pCellOrd = 0; pCellOrd < worksetSize; pCellOrd++){
    
    CellTools::printWorksetSubcell(hexNodes, hexahedron_8, pCellOrd, subcellDim, subcellOrd);
    std::cout << " Flux = " << worksetFluxes(pCellOrd) << "\n\n";
    
  }
  
  
  
  /*************************************************************************************************
    *
    *  Optional: print Gauss points and face normals at Gauss points
    *
    ************************************************************************************************/

  // Print Gauss points on [-1,1]x[-1,1] and their images on workset faces
  std::cout \
    << "===============================================================================\n" \
    << "|                        Gauss points on workset faces:                       |\n" \
    << "===============================================================================\n";
  for(int pCell = 0; pCell < worksetSize; pCell++){
    
    CellTools::printWorksetSubcell(hexNodes, hexahedron_8, pCell, subcellDim, subcellOrd);
    
    for(int pt = 0; pt < numCubPoints; pt++){
      std::cout << "\t 2D Gauss point (" 
      << std::setw(8) << std::right <<  paramGaussPoints(pt, 0) << ", "
      << std::setw(8) << std::right <<  paramGaussPoints(pt, 1) << ")  " 
      << std::setw(8) << " -->  " << "(" 
      << std::setw(8) << std::right << worksetGaussPoints(pCell, pt, 0) << ", " 
      << std::setw(8) << std::right << worksetGaussPoints(pCell, pt, 1) << ", " 
      << std::setw(8) << std::right << worksetGaussPoints(pCell, pt, 2) << ")\n";
    }    
    std::cout << "\n\n";      
  }//pCell
  
  
  // Print face normals at Gauss points on workset faces
  std::cout \
    << "===============================================================================\n" \
    << "|          Face normals (non-unit) at Gauss points on workset faces:          |\n" \
    << "===============================================================================\n";
  for(int pCell = 0; pCell < worksetSize; pCell++){
    
    CellTools::printWorksetSubcell(hexNodes, hexahedron_8, pCell, subcellDim, subcellOrd);
    
    for(int pt = 0; pt < numCubPoints; pt++){
      std::cout << "\t 3D Gauss point: (" 
      << std::setw(8) << std::right << worksetGaussPoints(pCell, pt, 0) << ", " 
      << std::setw(8) << std::right << worksetGaussPoints(pCell, pt, 1) << ", " 
      << std::setw(8) << std::right << worksetGaussPoints(pCell, pt, 2) << ")" 
      << std::setw(8) << " out. normal:  " << "(" 
      << std::setw(8) << std::right << worksetFaceN(pCell, pt, 0) << ", " 
      << std::setw(8) << std::right << worksetFaceN(pCell, pt, 1) << ", " 
      << std::setw(8) << std::right << worksetFaceN(pCell, pt, 2) << ")\n";
    }    
    std::cout << "\n";      
  }//pCell
  
  return 0;
}
Пример #20
0
bool MeshTestUtility::determineRefTestPointsForNeighbors(MeshTopologyViewPtr meshTopo, CellPtr fineCell, unsigned int sideOrdinal,
    FieldContainer<double> &fineSideRefPoints, FieldContainer<double> &fineCellRefPoints,
    FieldContainer<double> &coarseSideRefPoints, FieldContainer<double> &coarseCellRefPoints)
{
  unsigned spaceDim = meshTopo->getDimension();
  unsigned sideDim = spaceDim - 1;

  if (spaceDim == 1)
  {
    fineSideRefPoints.resize(0,0);
    coarseSideRefPoints.resize(0,0);
    fineCellRefPoints.resize(1,1);
    coarseCellRefPoints.resize(1,1);

    FieldContainer<double> lineRefNodes(2,1);
    CellTopoPtr line = CellTopology::line();

    CamelliaCellTools::refCellNodesForTopology(lineRefNodes, line);

    fineCellRefPoints[0] = lineRefNodes[sideOrdinal];
    unsigned neighborSideOrdinal = fineCell->getNeighborInfo(sideOrdinal, meshTopo).second;
    if (neighborSideOrdinal != -1)
    {
      coarseCellRefPoints[0] = lineRefNodes[neighborSideOrdinal];
      return true;
    }
    else
    {
      return false;
    }
  }
  pair<GlobalIndexType, unsigned> neighborInfo = fineCell->getNeighborInfo(sideOrdinal, meshTopo);
  if (neighborInfo.first == -1)
  {
    // boundary
    return false;
  }
  CellPtr neighborCell = meshTopo->getCell(neighborInfo.first);
  if (neighborCell->isParent(meshTopo))
  {
    return false; // fineCell isn't the finer of the two...
  }

  CellTopoPtr fineSideTopo = fineCell->topology()->getSubcell(sideDim, sideOrdinal);

  CubatureFactory cubFactory;
  int cubDegree = 4; // fairly arbitrary choice: enough to get a decent number of test points...
  Teuchos::RCP<Cubature<double> > fineSideTopoCub = cubFactory.create(fineSideTopo, cubDegree);

  int numCubPoints = fineSideTopoCub->getNumPoints();

  FieldContainer<double> cubPoints(numCubPoints, sideDim);
  FieldContainer<double> cubWeights(numCubPoints); // we neglect these...

  fineSideTopoCub->getCubature(cubPoints, cubWeights);

  FieldContainer<double> sideRefCellNodes(fineSideTopo->getNodeCount(),sideDim);
  CamelliaCellTools::refCellNodesForTopology(sideRefCellNodes, fineSideTopo);

  int numTestPoints = numCubPoints + fineSideTopo->getNodeCount();

  FieldContainer<double> testPoints(numTestPoints, sideDim);
  for (int ptOrdinal=0; ptOrdinal<testPoints.dimension(0); ptOrdinal++)
  {
    if (ptOrdinal<fineSideTopo->getNodeCount())
    {
      for (int d=0; d<sideDim; d++)
      {
        testPoints(ptOrdinal,d) = sideRefCellNodes(ptOrdinal,d);
      }
    }
    else
    {
      for (int d=0; d<sideDim; d++)
      {
        testPoints(ptOrdinal,d) = cubPoints(ptOrdinal-fineSideTopo->getNodeCount(),d);
      }
    }
  }

  fineSideRefPoints = testPoints;
  fineCellRefPoints.resize(numTestPoints, spaceDim);

  CamelliaCellTools::mapToReferenceSubcell(fineCellRefPoints, testPoints, sideDim, sideOrdinal, fineCell->topology());

  CellTopoPtr coarseSideTopo = neighborCell->topology()->getSubcell(sideDim, neighborInfo.second);

  unsigned fineSideAncestorPermutation = fineCell->ancestralPermutationForSubcell(sideDim, sideOrdinal, meshTopo);
  unsigned coarseSidePermutation = neighborCell->subcellPermutation(sideDim, neighborInfo.second);

  unsigned coarseSideAncestorPermutationInverse = CamelliaCellTools::permutationInverse(coarseSideTopo, coarseSidePermutation);

  unsigned composedPermutation = CamelliaCellTools::permutationComposition(coarseSideTopo, coarseSideAncestorPermutationInverse, fineSideAncestorPermutation); // goes from coarse ordering to fine.

  RefinementBranch fineRefBranch = fineCell->refinementBranchForSide(sideOrdinal, meshTopo);

  FieldContainer<double> fineSideNodes(fineSideTopo->getNodeCount(), sideDim);  // relative to the ancestral cell whose neighbor is compatible
  if (fineRefBranch.size() == 0)
  {
    CamelliaCellTools::refCellNodesForTopology(fineSideNodes, coarseSideTopo, composedPermutation);
  }
  else
  {
    FieldContainer<double> ancestralSideNodes(coarseSideTopo->getNodeCount(), sideDim);
    CamelliaCellTools::refCellNodesForTopology(ancestralSideNodes, coarseSideTopo, composedPermutation);

    RefinementBranch fineSideRefBranch = RefinementPattern::sideRefinementBranch(fineRefBranch, sideOrdinal);
    fineSideNodes = RefinementPattern::descendantNodes(fineSideRefBranch, ancestralSideNodes);
  }

  BasisCachePtr sideTopoCache = Teuchos::rcp( new BasisCache(fineSideTopo, 1, false) );
  sideTopoCache->setRefCellPoints(testPoints);

  // add cell dimension
  fineSideNodes.resize(1,fineSideNodes.dimension(0), fineSideNodes.dimension(1));
  sideTopoCache->setPhysicalCellNodes(fineSideNodes, vector<GlobalIndexType>(), false);
  coarseSideRefPoints = sideTopoCache->getPhysicalCubaturePoints();

  // strip off the cell dimension:
  coarseSideRefPoints.resize(coarseSideRefPoints.dimension(1),coarseSideRefPoints.dimension(2));

  coarseCellRefPoints.resize(numTestPoints,spaceDim);
  CamelliaCellTools::mapToReferenceSubcell(coarseCellRefPoints, coarseSideRefPoints, sideDim, neighborInfo.second, neighborCell->topology());

  return true; // containers filled....
}
Пример #21
0
void Boundary::bcsToImpose(FieldContainer<GlobalIndexType> &globalIndices,
                           FieldContainer<Scalar> &globalValues, TBC<Scalar> &bc,
                           DofInterpreter* dofInterpreter)
{
  set< GlobalIndexType > rankLocalCells = _mesh->cellIDsInPartition();
  map< GlobalIndexType, double> bcGlobalIndicesAndValues;

  for (GlobalIndexType cellID : rankLocalCells)
  {
    bcsToImpose(bcGlobalIndicesAndValues, bc, cellID, dofInterpreter);
  }
  singletonBCsToImpose(bcGlobalIndicesAndValues, bc, dofInterpreter);
  
  // ****** New, tag-based BC imposition follows ******
  map< GlobalIndexType, double> bcTagGlobalIndicesAndValues;
  
  map< int, vector<pair<VarPtr, TFunctionPtr<Scalar>>>> tagBCs = bc.getDirichletTagBCs(); // keys are tags
  
  MeshTopology* meshTopo = dynamic_cast<MeshTopology*>(_mesh->getTopology().get());
  
  TEUCHOS_TEST_FOR_EXCEPTION(!meshTopo, std::invalid_argument, "pure MeshTopologyViews are not yet supported by new tag-based BC imposition");
  
  for (auto tagBC : tagBCs)
  {
    int tagID = tagBC.first;
    
    vector<EntitySetPtr> entitySets = meshTopo->getEntitySetsForTagID(DIRICHLET_SET_TAG_NAME, tagID);
    for (EntitySetPtr entitySet : entitySets)
    {
      // get rank-local cells that match the entity set:
      set<IndexType> matchingCellIDs = entitySet->cellIDsThatMatch(_mesh->getTopology(), rankLocalCells);
      for (IndexType cellID : matchingCellIDs)
      {
        ElementTypePtr elemType = _mesh->getElementType(cellID);
        BasisCachePtr basisCache = BasisCache::basisCacheForCell(_mesh, cellID);
        
        for (auto varFunctionPair : tagBC.second)
        {
          VarPtr var = varFunctionPair.first;
          FunctionPtr f = varFunctionPair.second;
          
          vector<int> sideOrdinals = elemType->trialOrderPtr->getSidesForVarID(var->ID());
          
          for (int sideOrdinal : sideOrdinals)
          {
            BasisPtr basis = elemType->trialOrderPtr->getBasis(var->ID(), sideOrdinal);
            bool isVolume = basis->domainTopology()->getDimension() == _mesh->getDimension();
            for (int d=0; d<_mesh->getDimension(); d++)
            {
              vector<unsigned> matchingSubcells;
              if (isVolume)
                matchingSubcells = entitySet->subcellOrdinals(_mesh->getTopology(), cellID, d);
              else
              {
                CellTopoPtr cellTopo = elemType->cellTopoPtr;
                int sideDim = cellTopo->getDimension() - 1;
                vector<unsigned> matchingSubcellsOnSide = entitySet->subcellOrdinalsOnSide(_mesh->getTopology(), cellID, sideOrdinal, d);
                for (unsigned sideSubcellOrdinal : matchingSubcellsOnSide)
                {
                  unsigned cellSubcellOrdinal = CamelliaCellTools::subcellOrdinalMap(cellTopo, sideDim, sideOrdinal, d, sideSubcellOrdinal);
                  matchingSubcells.push_back(cellSubcellOrdinal);
                }
              }
              
              if (matchingSubcells.size() == 0) continue; // nothing to impose
              
              /*
               What follows - projecting the function onto the basis on the whole domain - is more expensive than necessary,
               in the general case: we can do the projection on just the matching subcells, and if we had a way of taking the
               restriction of a basis to a subcell of the domain, then we could avoid computing the whole basis as well.
               
               But for now, this should work, and it's simple to implement.
               */
              BasisCachePtr basisCacheForImposition = isVolume ? basisCache : basisCache->getSideBasisCache(sideOrdinal);
              int numCells = 1;
              FieldContainer<double> basisCoefficients(numCells,basis->getCardinality());
              Projector<double>::projectFunctionOntoBasisInterpolating(basisCoefficients, f, basis, basisCacheForImposition);
              basisCoefficients.resize(basis->getCardinality());
              
              set<GlobalIndexType> matchingGlobalIndices;
              for (unsigned matchingSubcell : matchingSubcells)
              {
                set<GlobalIndexType> subcellGlobalIndices = dofInterpreter->globalDofIndicesForVarOnSubcell(var->ID(),cellID,d,matchingSubcell);
                matchingGlobalIndices.insert(subcellGlobalIndices.begin(),subcellGlobalIndices.end());
              }
              
              FieldContainer<double> globalData;
              FieldContainer<GlobalIndexType> globalDofIndices;
//              dofInterpreter->interpretLocalBasisCoefficients(cellID, var->ID(), sideOrdinal, basisCoefficientsToImpose, globalData, globalDofIndices);
              dofInterpreter->interpretLocalBasisCoefficients(cellID, var->ID(), sideOrdinal, basisCoefficients, globalData, globalDofIndices);
              for (int globalDofOrdinal=0; globalDofOrdinal<globalDofIndices.size(); globalDofOrdinal++)
              {
                GlobalIndexType globalDofIndex = globalDofIndices(globalDofOrdinal);
                if (matchingGlobalIndices.find(globalDofIndex) != matchingGlobalIndices.end())
                  bcTagGlobalIndicesAndValues[globalDofIndex] = globalData(globalDofOrdinal);
              }
            }
          }
        }
      }
    }
  }
  
  // merge tag-based and legacy BC maps
  double tol = 1e-15;
  for (auto tagEntry : bcTagGlobalIndicesAndValues)
  {
    if (bcGlobalIndicesAndValues.find(tagEntry.first) != bcGlobalIndicesAndValues.end())
    {
      // then check that they match, within tolerance
      double diff = abs(bcGlobalIndicesAndValues[tagEntry.first] - tagEntry.second);
      TEUCHOS_TEST_FOR_EXCEPTION(diff > tol, std::invalid_argument, "Incompatible BC entries encountered");
    }
    else
    {
      bcGlobalIndicesAndValues[tagEntry.first] = tagEntry.second;
    }
  }
  
  globalIndices.resize(bcGlobalIndicesAndValues.size());
  globalValues.resize(bcGlobalIndicesAndValues.size());
  globalIndices.initialize(0);
  globalValues.initialize(0.0);
  int entryOrdinal = 0;
  for (auto bcEntry : bcGlobalIndicesAndValues)
  {
    globalIndices[entryOrdinal] = bcEntry.first;
    globalValues[entryOrdinal] = bcEntry.second;
    entryOrdinal++;
  }
}
Пример #22
0
bool MeshTestUtility::neighborBasesAgreeOnSides(Teuchos::RCP<Mesh> mesh, Epetra_MultiVector &globalSolutionCoefficients)
{
  bool success = true;
  MeshTopologyViewPtr meshTopo = mesh->getTopology();
  int spaceDim = meshTopo->getDimension();

  set<IndexType> activeCellIndices = meshTopo->getActiveCellIndices();
  for (set<IndexType>::iterator cellIt=activeCellIndices.begin(); cellIt != activeCellIndices.end(); cellIt++)
  {
    IndexType cellIndex = *cellIt;
    CellPtr cell = meshTopo->getCell(cellIndex);

    BasisCachePtr fineCellBasisCache = BasisCache::basisCacheForCell(mesh, cellIndex);
    ElementTypePtr fineElemType = mesh->getElementType(cellIndex);
    DofOrderingPtr fineElemTrialOrder = fineElemType->trialOrderPtr;

    FieldContainer<double> fineSolutionCoefficients(fineElemTrialOrder->totalDofs());
    mesh->globalDofAssignment()->interpretGlobalCoefficients(cellIndex, fineSolutionCoefficients, globalSolutionCoefficients);
//    if ((cellIndex==0) || (cellIndex==2)) {
//      cout << "MeshTestUtility: local coefficients for cell " << cellIndex << ":\n" << fineSolutionCoefficients;
//    }

    unsigned sideCount = cell->getSideCount();
    for (unsigned sideOrdinal=0; sideOrdinal<sideCount; sideOrdinal++)
    {
      FieldContainer<double> fineSideRefPoints, fineCellRefPoints, coarseSideRefPoints, coarseCellRefPoints;
      bool hasCoarserNeighbor = determineRefTestPointsForNeighbors(meshTopo, cell, sideOrdinal, fineSideRefPoints, fineCellRefPoints, coarseSideRefPoints, coarseCellRefPoints);
      if (!hasCoarserNeighbor) continue;

      pair<GlobalIndexType, unsigned> neighborInfo = cell->getNeighborInfo(sideOrdinal, meshTopo);

      CellPtr neighborCell = meshTopo->getCell(neighborInfo.first);

      unsigned numTestPoints = coarseCellRefPoints.dimension(0);

      //        cout << "testing neighbor agreement between cell " << cellIndex << " and " << neighborCell->cellIndex() << endl;

      // if we get here, the cell has a neighbor on this side, and is at least as fine as that neighbor.

      BasisCachePtr fineSideBasisCache = fineCellBasisCache->getSideBasisCache(sideOrdinal);

      fineCellBasisCache->setRefCellPoints(fineCellRefPoints);

      BasisCachePtr coarseCellBasisCache = BasisCache::basisCacheForCell(mesh, neighborInfo.first);
      BasisCachePtr coarseSideBasisCache = coarseCellBasisCache->getSideBasisCache(neighborInfo.second);

      coarseCellBasisCache->setRefCellPoints(coarseCellRefPoints);

      bool hasSidePoints = (fineSideRefPoints.size() > 0);
      if (hasSidePoints)
      {
        fineSideBasisCache->setRefCellPoints(fineSideRefPoints);
        coarseSideBasisCache->setRefCellPoints(coarseSideRefPoints);
      }

      // sanity check: do physical points match?

      FieldContainer<double> fineCellPhysicalCubaturePoints = fineCellBasisCache->getPhysicalCubaturePoints();
      FieldContainer<double> coarseCellPhysicalCubaturePoints = coarseCellBasisCache->getPhysicalCubaturePoints();

      double tol = 1e-14;
      double maxDiff = 0;
      if (! fcsAgree(coarseCellPhysicalCubaturePoints, fineCellPhysicalCubaturePoints, tol, maxDiff) )
      {
        cout << "ERROR: MeshTestUtility::neighborBasesAgreeOnSides internal error: fine and coarse cell cubature points do not agree.\n";
        success = false;
        continue;
      }

      if (hasSidePoints)
      {
        FieldContainer<double> fineSidePhysicalCubaturePoints = fineSideBasisCache->getPhysicalCubaturePoints();
        FieldContainer<double> coarseSidePhysicalCubaturePoints = coarseSideBasisCache->getPhysicalCubaturePoints();

        double tol = 1e-14;
        double maxDiff = 0;
        if (! fcsAgree(fineSidePhysicalCubaturePoints, fineCellPhysicalCubaturePoints, tol, maxDiff) )
        {
          cout << "ERROR: MeshTestUtility::neighborBasesAgreeOnSides internal error: fine side and cell cubature points do not agree.\n";
          success = false;
          continue;
        }
        if (! fcsAgree(coarseSidePhysicalCubaturePoints, coarseCellPhysicalCubaturePoints, tol, maxDiff) )
        {
          cout << "ERROR: MeshTestUtility::neighborBasesAgreeOnSides internal error: coarse side and cell cubature points do not agree.\n";
          success = false;
          continue;
        }
        if (! fcsAgree(coarseSidePhysicalCubaturePoints, fineSidePhysicalCubaturePoints, tol, maxDiff) )
        {
          cout << "ERROR: MeshTestUtility::neighborBasesAgreeOnSides internal error: fine and coarse side cubature points do not agree.\n";
          success = false;
          continue;
        }
      }

      ElementTypePtr coarseElementType = mesh->getElementType(neighborInfo.first);
      DofOrderingPtr coarseElemTrialOrder = coarseElementType->trialOrderPtr;

      FieldContainer<double> coarseSolutionCoefficients(coarseElemTrialOrder->totalDofs());
      mesh->globalDofAssignment()->interpretGlobalCoefficients(neighborInfo.first, coarseSolutionCoefficients, globalSolutionCoefficients);

      set<int> varIDs = fineElemTrialOrder->getVarIDs();
      for (set<int>::iterator varIt = varIDs.begin(); varIt != varIDs.end(); varIt++)
      {
        int varID = *varIt;
//        cout << "MeshTestUtility: varID " << varID << ":\n";
        bool isTraceVar = mesh->bilinearForm()->isFluxOrTrace(varID);
        BasisPtr fineBasis, coarseBasis;
        BasisCachePtr fineCache, coarseCache;
        if (isTraceVar)
        {
          if (! hasSidePoints) continue; // then nothing to do for traces
          fineBasis = fineElemTrialOrder->getBasis(varID, sideOrdinal);
          coarseBasis = coarseElemTrialOrder->getBasis(varID, neighborInfo.second);
          fineCache = fineSideBasisCache;
          coarseCache = coarseSideBasisCache;
        }
        else
        {
          fineBasis = fineElemTrialOrder->getBasis(varID);
          coarseBasis = coarseElemTrialOrder->getBasis(varID);
          fineCache = fineCellBasisCache;
          coarseCache = coarseCellBasisCache;

          Camellia::EFunctionSpace fs = fineBasis->functionSpace();
          if ((fs == Camellia::FUNCTION_SPACE_HVOL)
              || (fs == Camellia::FUNCTION_SPACE_VECTOR_HVOL)
              || (fs == Camellia::FUNCTION_SPACE_TENSOR_HVOL))
          {
            // volume L^2 basis: no continuities expected...
            continue;
          }
        }
        FieldContainer<double> localValuesFine = *fineCache->getTransformedValues(fineBasis, OP_VALUE);
        FieldContainer<double> localValuesCoarse = *coarseCache->getTransformedValues(coarseBasis, OP_VALUE);

        bool scalarValued = (localValuesFine.rank() == 3);

        // the following used if vector or tensor-valued:
        Teuchos::Array<int> valueDim;
        unsigned componentsPerValue = 1;
        FieldContainer<double> valueContainer; // just used for enumeration computation...
        if (!scalarValued)
        {
          localValuesFine.dimensions(valueDim);
          // clear first three:
          valueDim.erase(valueDim.begin());
          valueDim.erase(valueDim.begin());
          valueDim.erase(valueDim.begin());
          valueContainer.resize(valueDim);
          componentsPerValue = valueContainer.size();
        }

        //          if (localValuesFine.rank() != 3) {
        //            cout << "WARNING: MeshTestUtility::neighborBasesAgreeOnSides() only supports scalar-valued bases right now.  Skipping check for varID " << varID << endl;
        //            continue;
        //          }

        FieldContainer<double> localPointValuesFine(fineElemTrialOrder->totalDofs());
        FieldContainer<double> localPointValuesCoarse(coarseElemTrialOrder->totalDofs());

        for (int valueComponentOrdinal=0; valueComponentOrdinal<componentsPerValue; valueComponentOrdinal++)
        {
          Teuchos::Array<int> valueMultiIndex(valueContainer.rank());

          if (!scalarValued)
            valueContainer.getMultiIndex(valueMultiIndex, valueComponentOrdinal);

          Teuchos::Array<int> localValuesMultiIndex(localValuesFine.rank());

          for (int r=0; r<valueMultiIndex.size(); r++)
          {
            localValuesMultiIndex[r+3] = valueMultiIndex[r];
          }

          for (int ptOrdinal=0; ptOrdinal<numTestPoints; ptOrdinal++)
          {
            localPointValuesCoarse.initialize(0);
            localPointValuesFine.initialize(0);
            localValuesMultiIndex[2] = ptOrdinal;

            double fineSolutionValue = 0, coarseSolutionValue = 0;

            for (int basisOrdinal=0; basisOrdinal < fineBasis->getCardinality(); basisOrdinal++)
            {
              int fineDofIndex;
              if (isTraceVar)
                fineDofIndex = fineElemTrialOrder->getDofIndex(varID, basisOrdinal, sideOrdinal);
              else
                fineDofIndex = fineElemTrialOrder->getDofIndex(varID, basisOrdinal);
              if (scalarValued)
              {
                localPointValuesFine(fineDofIndex) = localValuesFine(0,basisOrdinal,ptOrdinal);
              }
              else
              {
                localValuesMultiIndex[1] = basisOrdinal;
                localPointValuesFine(fineDofIndex) = localValuesFine.getValue(localValuesMultiIndex);
              }

              fineSolutionValue += fineSolutionCoefficients(fineDofIndex) * localPointValuesFine(fineDofIndex);
            }
            for (int basisOrdinal=0; basisOrdinal < coarseBasis->getCardinality(); basisOrdinal++)
            {
              int coarseDofIndex;
              if (isTraceVar)
                coarseDofIndex = coarseElemTrialOrder->getDofIndex(varID, basisOrdinal, neighborInfo.second);
              else
                coarseDofIndex = coarseElemTrialOrder->getDofIndex(varID, basisOrdinal);
              if (scalarValued)
              {
                localPointValuesCoarse(coarseDofIndex) = localValuesCoarse(0,basisOrdinal,ptOrdinal);
              }
              else
              {
                localValuesMultiIndex[1] = basisOrdinal;
                localPointValuesCoarse(coarseDofIndex) = localValuesCoarse.getValue(localValuesMultiIndex);
              }
              coarseSolutionValue += coarseSolutionCoefficients(coarseDofIndex) * localPointValuesCoarse(coarseDofIndex);
            }

            if (abs(coarseSolutionValue - fineSolutionValue) > 1e-13)
            {
              success = false;
              cout << "coarseSolutionValue (" << coarseSolutionValue << ") and fineSolutionValue (" << fineSolutionValue << ") differ by " << abs(coarseSolutionValue - fineSolutionValue);
              cout << " at point " << ptOrdinal << " for varID " << varID << ".  ";
              cout << "This may be an indication that something is amiss with the global-to-local map.\n";
            }
            else
            {
//              // DEBUGGING:
//              cout << "solution value at point (";
//              for (int d=0; d<spaceDim-1; d++) {
//                cout << fineSidePhysicalCubaturePoints(0,ptOrdinal,d) << ", ";
//              }
//              cout << fineSidePhysicalCubaturePoints(0,ptOrdinal,spaceDim-1) << "): ";
//              cout << coarseSolutionValue << endl;
            }

            FieldContainer<double> globalValuesFromFine, globalValuesFromCoarse;
            FieldContainer<GlobalIndexType> globalDofIndicesFromFine, globalDofIndicesFromCoarse;

            mesh->globalDofAssignment()->interpretLocalData(cellIndex, localPointValuesFine, globalValuesFromFine, globalDofIndicesFromFine);
            mesh->globalDofAssignment()->interpretLocalData(neighborInfo.first, localPointValuesCoarse, globalValuesFromCoarse, globalDofIndicesFromCoarse);

            std::map<GlobalIndexType, double> fineValuesMap;
            std::map<GlobalIndexType, double> coarseValuesMap;

            for (int i=0; i<globalDofIndicesFromCoarse.size(); i++)
            {
              GlobalIndexType globalDofIndex = globalDofIndicesFromCoarse[i];
              coarseValuesMap[globalDofIndex] = globalValuesFromCoarse[i];
            }

            double maxDiff = 0;
            for (int i=0; i<globalDofIndicesFromFine.size(); i++)
            {
              GlobalIndexType globalDofIndex = globalDofIndicesFromFine[i];
              fineValuesMap[globalDofIndex] = globalValuesFromFine[i];

              double diff = abs( fineValuesMap[globalDofIndex] - coarseValuesMap[globalDofIndex]);
              maxDiff = std::max(diff, maxDiff);
              if (diff > tol)
              {
                success = false;
                cout << "interpreted fine and coarse disagree at point (";
                for (int d=0; d<spaceDim; d++)
                {
                  cout << fineCellPhysicalCubaturePoints(0,ptOrdinal,d);
                  if (d==spaceDim-1)
                    cout <<  ").\n";
                  else
                    cout << ", ";
                }
              }
            }
            if (maxDiff > tol)
            {
              cout << "maxDiff: " << maxDiff << endl;
              cout << "globalValuesFromFine:\n" << globalValuesFromFine;
              cout << "globalValuesFromCoarse:\n" << globalValuesFromCoarse;

              cout << "globalDofIndicesFromFine:\n" << globalDofIndicesFromFine;
              cout <<  "globalDofIndicesFromCoarse:\n" << globalDofIndicesFromCoarse;

              continue; // only worth testing further if we passed the above
            }
          }
        }
      }
    }
  }

//  cout << "Completed neighborBasesAgreeOnSides.\n";
  return success;
}
Пример #23
0
int main(int argc, char *argv[]) {

  Teuchos::GlobalMPISession mpiSession(&argc, &argv);

  // This little trick lets us print to std::cout only if
  // a (dummy) command-line argument is provided.
  int iprint     = argc - 1;
  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing
  if (iprint > 0)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs, false);

  // Save the format state of the original std::cout.
  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);

  *outStream \
    << "===============================================================================\n" \
    << "|                                                                             |\n" \
    << "|                 Unit Test (Basis_HGRAD_TRI_C1_FEM)                          |\n" \
    << "|                                                                             |\n" \
    << "|     1) Conversion of Dof tags into Dof ordinals and back                    |\n" \
    << "|     2) Basis values for VALUE, GRAD, CURL, and Dk operators                 |\n" \
    << "|                                                                             |\n" \
    << "|  Questions? Contact  Pavel Bochev  ([email protected]),                    |\n" \
    << "|                      Denis Ridzal  ([email protected]),                    |\n" \
    << "|                      Kara Peterson ([email protected]).                    |\n" \
    << "|                                                                             |\n" \
    << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n" \
    << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
    << "|                                                                             |\n" \
    << "===============================================================================\n"\
    << "| TEST 1: Basis creation, exception testing                                   |\n"\
    << "===============================================================================\n";

  
  // Define basis and error flag
  Basis_HGRAD_TRI_C1_FEM<double, FieldContainer<double> > triBasis;
  int errorFlag = 0;

  // Initialize throw counter for exception testing
  int nException     = 0;
  int throwCounter   = 0;
  
  // Define array containing the 3 vertices of the reference Triangle, its center and another point  
  FieldContainer<double> triNodes(5, 2);
  triNodes(0,0) =  0.0;  triNodes(0,1) =  0.0;
  triNodes(1,0) =  1.0;  triNodes(1,1) =  0.0;
  triNodes(2,0) =  0.0;  triNodes(2,1) =  1.0;
  triNodes(3,0) =  0.5;  triNodes(3,1) =  0.5;
  triNodes(4,0) =  0.0;  triNodes(4,1) =  0.75;
  
  // Generic array for the output values; needs to be properly resized depending on the operator type
  FieldContainer<double> vals;

  try{
    // exception #1: DIV cannot be applied to scalar functions
    // resize vals to rank-2 container with dimensions (num. points, num. basis functions)
    vals.resize(triBasis.getCardinality(), triNodes.dimension(0) );
    INTREPID_TEST_COMMAND( triBasis.getValues(vals, triNodes, OPERATOR_DIV), throwCounter, nException );
    
    // Exceptions 2-6: all bf tags/bf Ids below are wrong and should cause getDofOrdinal() and 
    // getDofTag() to access invalid array elements thereby causing bounds check exception
    // exception #2
    INTREPID_TEST_COMMAND( triBasis.getDofOrdinal(2,0,0), throwCounter, nException );
    // exception #3
    INTREPID_TEST_COMMAND( triBasis.getDofOrdinal(1,1,1), throwCounter, nException );
    // exception #4
    INTREPID_TEST_COMMAND( triBasis.getDofOrdinal(0,4,0), throwCounter, nException );
    // exception #5
    INTREPID_TEST_COMMAND( triBasis.getDofTag(5), throwCounter, nException );
    // exception #6
    INTREPID_TEST_COMMAND( triBasis.getDofTag(-1), throwCounter, nException );

#ifdef HAVE_INTREPID_DEBUG
    // Exceptions 7-17 test exception handling with incorrectly dimensioned input/output arrays
    // exception #7: input points array must be of rank-2
    FieldContainer<double> badPoints1(4, 5, 3);
    INTREPID_TEST_COMMAND( triBasis.getValues(vals, badPoints1, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #8 dimension 1 in the input point array must equal space dimension of the cell
    FieldContainer<double> badPoints2(4, 3);
    INTREPID_TEST_COMMAND( triBasis.getValues(vals, badPoints2, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #9 output values must be of rank-2 for OPERATOR_VALUE
    FieldContainer<double> badVals1(4, 3, 1);
    INTREPID_TEST_COMMAND( triBasis.getValues(badVals1, triNodes, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #10 output values must be of rank-3 for OPERATOR_GRAD
    FieldContainer<double> badVals2(4, 3);
    INTREPID_TEST_COMMAND( triBasis.getValues(badVals2, triNodes, OPERATOR_GRAD), throwCounter, nException );
    
    // exception #11 output values must be of rank-3 for OPERATOR_CURL
    INTREPID_TEST_COMMAND( triBasis.getValues(badVals2, triNodes, OPERATOR_CURL), throwCounter, nException );
    
    // exception #12 output values must be of rank-3 for OPERATOR_D2
    INTREPID_TEST_COMMAND( triBasis.getValues(badVals2, triNodes, OPERATOR_D2), throwCounter, nException );
    
    // exception #13 incorrect 1st dimension of output array (must equal number of basis functions)
    FieldContainer<double> badVals3(triBasis.getCardinality() + 1, triNodes.dimension(0));
    INTREPID_TEST_COMMAND( triBasis.getValues(badVals3, triNodes, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #14 incorrect 0th dimension of output array (must equal number of points)
    FieldContainer<double> badVals4(triBasis.getCardinality(), triNodes.dimension(0) + 1);
    INTREPID_TEST_COMMAND( triBasis.getValues(badVals4, triNodes, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #15: incorrect 2nd dimension of output array (must equal the space dimension)
    FieldContainer<double> badVals5(triBasis.getCardinality(), triNodes.dimension(0), 4);
    INTREPID_TEST_COMMAND( triBasis.getValues(badVals5, triNodes, OPERATOR_GRAD), throwCounter, nException );
    
    // exception #16: incorrect 2nd dimension of output array (must equal D2 cardinality in 2D)
    FieldContainer<double> badVals6(triBasis.getCardinality(), triNodes.dimension(0), 40);
    INTREPID_TEST_COMMAND( triBasis.getValues(badVals6, triNodes, OPERATOR_D2), throwCounter, nException );
    
    // exception #17: incorrect 2nd dimension of output array (must equal D3 cardinality in 2D)
    INTREPID_TEST_COMMAND( triBasis.getValues(badVals6, triNodes, OPERATOR_D3), throwCounter, nException );
#endif
    
  }
  catch (std::logic_error err) {
    *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
    *outStream << err.what() << '\n';
    *outStream << "-------------------------------------------------------------------------------" << "\n\n";
    errorFlag = -1000;
  };
  
  // Check if number of thrown exceptions matches the one we expect
  if (throwCounter != nException) {
    errorFlag++;
    *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
  }
  
  *outStream \
    << "\n"
    << "===============================================================================\n"\
    << "| TEST 2: correctness of tag to enum and enum to tag lookups                  |\n"\
    << "===============================================================================\n";

  try{
    std::vector<std::vector<int> > allTags = triBasis.getAllDofTags();
    
    // Loop over all tags, lookup the associated dof enumeration and then lookup the tag again
    for (unsigned i = 0; i < allTags.size(); i++) {
      int bfOrd  = triBasis.getDofOrdinal(allTags[i][0], allTags[i][1], allTags[i][2]);
      
      std::vector<int> myTag = triBasis.getDofTag(bfOrd);
      if( !( (myTag[0] == allTags[i][0]) &&
             (myTag[1] == allTags[i][1]) &&
             (myTag[2] == allTags[i][2]) &&
             (myTag[3] == allTags[i][3]) ) ) {
        errorFlag++;
        *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
        *outStream << " getDofOrdinal( {" 
          << allTags[i][0] << ", " 
          << allTags[i][1] << ", " 
          << allTags[i][2] << ", " 
          << allTags[i][3] << "}) = " << bfOrd <<" but \n";   
        *outStream << " getDofTag(" << bfOrd << ") = { "
          << myTag[0] << ", " 
          << myTag[1] << ", " 
          << myTag[2] << ", " 
          << myTag[3] << "}\n";        
      }
    }
    
    // Now do the same but loop over basis functions
    for( int bfOrd = 0; bfOrd < triBasis.getCardinality(); bfOrd++) {
      std::vector<int> myTag  = triBasis.getDofTag(bfOrd);
      int myBfOrd = triBasis.getDofOrdinal(myTag[0], myTag[1], myTag[2]);
      if( bfOrd != myBfOrd) {
        errorFlag++;
        *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
        *outStream << " getDofTag(" << bfOrd << ") = { "
          << myTag[0] << ", " 
          << myTag[1] << ", " 
          << myTag[2] << ", " 
          << myTag[3] << "} but getDofOrdinal({" 
          << myTag[0] << ", " 
          << myTag[1] << ", " 
          << myTag[2] << ", " 
          << myTag[3] << "} ) = " << myBfOrd << "\n";
      }
    }
  }
  catch (std::logic_error err){
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  };
  
  *outStream \
    << "\n"
    << "===============================================================================\n"\
    << "| TEST 3: correctness of basis function values                                |\n"\
    << "===============================================================================\n";

  outStream -> precision(20);

  // VALUE: Each row gives the 3 correct basis set values at an evaluation point
  double basisValues[] = {
    1.0, 0.0, 0.0,
    0.0, 1.0, 0.0,
    0.0, 0.0, 1.0,
    0.0, 0.5, 0.5,
    0.25,0.0, 0.75
  };

  // GRAD and D1: each row gives the 6 correct values of the gradients of the 3 basis functions
  double basisGrads[] = {
    -1.0, -1.0,    1.0,  0.0,    0.0,  1.0,
    -1.0, -1.0,    1.0,  0.0,    0.0,  1.0,
    -1.0, -1.0,    1.0,  0.0,    0.0,  1.0,
    -1.0, -1.0,    1.0,  0.0,    0.0,  1.0,
    -1.0, -1.0,    1.0,  0.0,    0.0,  1.0,
  };

  // CURL: each row gives the 6 correct values of the curls of the 3 basis functions
  double basisCurls[] = {
    -1.0,  1.0,    0.0, -1.0,    1.0,  0.0,
    -1.0,  1.0,    0.0, -1.0,    1.0,  0.0,
    -1.0,  1.0,    0.0, -1.0,    1.0,  0.0,
    -1.0,  1.0,    0.0, -1.0,    1.0,  0.0,
    -1.0,  1.0,    0.0, -1.0,    1.0,  0.0
  };

  try{
    
    // Dimensions for the output arrays:
    int numFields = triBasis.getCardinality();
    int numPoints = triNodes.dimension(0);
    int spaceDim  = triBasis.getBaseCellTopology().getDimension();
    
    // Generic array for values, grads, curls, etc. that will be properly sized before each call
    FieldContainer<double> vals;
    
    // Check VALUE of basis functions: resize vals to rank-2 container:
    vals.resize(numFields, numPoints);
    triBasis.getValues(vals, triNodes, OPERATOR_VALUE);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
          int l =  i + j * numFields;
           if (std::abs(vals(i,j) - basisValues[l]) > INTREPID_TOL) {
             errorFlag++;
             *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

             // Output the multi-index of the value where the error is:
             *outStream << " At multi-index { ";
             *outStream << i << " ";*outStream << j << " ";
             *outStream << "}  computed value: " << vals(i,j)
               << " but reference value: " << basisValues[l] << "\n";
         }
      }
    }
    
    // Check GRAD of basis function: resize vals to rank-3 container
    vals.resize(numFields, numPoints, spaceDim);
    triBasis.getValues(vals, triNodes, OPERATOR_GRAD);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < spaceDim; k++) {
           int l = k + i * spaceDim + j * spaceDim * numFields;
           if (std::abs(vals(i,j,k) - basisGrads[l]) > INTREPID_TOL) {
             errorFlag++;
             *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

             // Output the multi-index of the value where the error is:
             *outStream << " At multi-index { ";
             *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
             *outStream << "}  computed grad component: " << vals(i,j,k)
               << " but reference grad component: " << basisGrads[l] << "\n";
            }
         }
      }
    }

    // Check D1 of basis function (do not resize vals because it has the correct size: D1 = GRAD)
    triBasis.getValues(vals, triNodes, OPERATOR_D1);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < spaceDim; k++) {
           int l = k + i * spaceDim + j * spaceDim * numFields;
           if (std::abs(vals(i,j,k) - basisGrads[l]) > INTREPID_TOL) {
             errorFlag++;
             *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

             // Output the multi-index of the value where the error is:
             *outStream << " At multi-index { ";
             *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
             *outStream << "}  computed D1 component: " << vals(i,j,k)
               << " but reference D1 component: " << basisGrads[l] << "\n";
            }
         }
      }
    }

    
    // Check CURL of basis function: resize vals just for illustration! 
    vals.resize(numFields, numPoints, spaceDim);
    triBasis.getValues(vals, triNodes, OPERATOR_CURL);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < spaceDim; k++) {
           int l = k + i * spaceDim + j * spaceDim * numFields;
           if (std::abs(vals(i,j,k) - basisCurls[l]) > INTREPID_TOL) {
             errorFlag++;
             *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

             // Output the multi-index of the value where the error is:
             *outStream << " At multi-index { ";
             *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
             *outStream << "}  computed curl component: " << vals(i,j,k)
               << " but reference curl component: " << basisCurls[l] << "\n";
            }
         }
      }
    }

    // Check all higher derivatives - must be zero. 
    for(EOperator op = OPERATOR_D2; op < OPERATOR_MAX; op++) {
      
      // The last dimension is the number of kth derivatives and needs to be resized for every Dk
      int DkCardin  = Intrepid::getDkCardinality(op, spaceDim);
      vals.resize(numFields, numPoints, DkCardin);    
      
      triBasis.getValues(vals, triNodes, op);
      for (int i = 0; i < vals.size(); i++) {
        if (std::abs(vals[i]) > INTREPID_TOL) {
          errorFlag++;
          *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
          
          // Get the multi-index of the value where the error is and the operator order
          std::vector<int> myIndex;
          vals.getMultiIndex(myIndex,i);
          int ord = Intrepid::getOperatorOrder(op);
          *outStream << " At multi-index { ";
          for(int j = 0; j < vals.rank(); j++) {
            *outStream << myIndex[j] << " ";
          }
          *outStream << "}  computed D"<< ord <<" component: " << vals[i] 
            << " but reference D" << ord << " component:  0 \n";
        }
      }
    }    
  }

  // Catch unexpected errors
  catch (std::logic_error err) {
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  };

  *outStream \
    << "\n"
    << "===============================================================================\n"\
    << "| TEST 4: correctness of DoF locations                                        |\n"\
    << "===============================================================================\n";

  try{
    Teuchos::RCP<Basis<double, FieldContainer<double> > > basis =
      Teuchos::rcp(new Basis_HGRAD_TRI_C1_FEM<double, FieldContainer<double> >);
    Teuchos::RCP<DofCoordsInterface<FieldContainer<double> > > coord_iface =
      Teuchos::rcp_dynamic_cast<DofCoordsInterface<FieldContainer<double> > >(basis);

    FieldContainer<double> cvals;
    FieldContainer<double> bvals(basis->getCardinality(), basis->getCardinality());

    // Check exceptions.
#ifdef HAVE_INTREPID_DEBUG
    cvals.resize(1,2,3);
    INTREPID_TEST_COMMAND( coord_iface->getDofCoords(cvals), throwCounter, nException );
    cvals.resize(4,2);
    INTREPID_TEST_COMMAND( coord_iface->getDofCoords(cvals), throwCounter, nException );
    cvals.resize(4,3);
    INTREPID_TEST_COMMAND( coord_iface->getDofCoords(cvals), throwCounter, nException );
#endif
    cvals.resize(3,2);
    INTREPID_TEST_COMMAND( coord_iface->getDofCoords(cvals), throwCounter, nException ); nException--;
    // Check if number of thrown exceptions matches the one we expect
    if (throwCounter != nException) {
      errorFlag++;
      *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
    }

    // Check mathematical correctness.
    basis->getValues(bvals, cvals, OPERATOR_VALUE);
    char buffer[120];
    for (int i=0; i<bvals.dimension(0); i++) {
      for (int j=0; j<bvals.dimension(1); j++) {
        if ((i != j) && (std::abs(bvals(i,j) - 0.0) > INTREPID_TOL)) {
          errorFlag++;
          sprintf(buffer, "\nValue of basis function %d at (%6.4e, %6.4e) is %6.4e but should be %6.4e!\n", i, cvals(i,0), cvals(i,1), bvals(i,j), 0.0);
          *outStream << buffer;
        }
        else if ((i == j) && (std::abs(bvals(i,j) - 1.0) > INTREPID_TOL)) {
          errorFlag++;
          sprintf(buffer, "\nValue of basis function %d at (%6.4e, %6.4e) is %6.4e but should be %6.4e!\n", i, cvals(i,0), cvals(i,1), bvals(i,j), 1.0);
          *outStream << buffer;
        }
      }
    }

  }
  catch (std::logic_error err){
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  };

  if (errorFlag != 0)
    std::cout << "End Result: TEST FAILED\n";
  else
    std::cout << "End Result: TEST PASSED\n";

  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);

  return errorFlag;
}
Пример #24
0
/** This example whows how to get vertex IDs for all the elements
  */
int main( int argc, char **argv )
{  
  using Teuchos::RCP;

  Teuchos::oblackholestream blackhole;
  Teuchos::GlobalMPISession mpiSession(&argc,&argv,&blackhole);

  RCP<const Teuchos::Comm<int> > comm = Teuchos::DefaultComm<int>::getComm();

  RCP<Teuchos::ParameterList> pl = rcp(new Teuchos::ParameterList);
  pl->set("X Blocks",2);
  pl->set("Y Blocks",1);
  pl->set("X Elements",6);
  pl->set("Y Elements",4);

  panzer_stk::SquareQuadMeshFactory factory;
  factory.setParameterList(pl);
  RCP<panzer_stk::STK_Interface> mesh = factory.buildMesh(MPI_COMM_WORLD);
  if(mesh->isWritable())
     mesh->writeToExodus("blocked_mesh.exo");
  unsigned dim = mesh->getDimension();

  std::vector<std::string> sideSets; 
  std::vector<std::string> elementBlocks; 
  mesh->getSidesetNames(sideSets);
  mesh->getElementBlockNames(elementBlocks);

  // loop over all sidesets
  for(std::size_t blk=0;blk<elementBlocks.size();++blk) {
     std::string eBlockId = elementBlocks[blk];
     
     for(std::size_t side=0;side<sideSets.size();++side) {
        std::string sideName = sideSets[side];
   
        std::vector<stk::mesh::Entity*> sideEntities; 
        mesh->getMySides(sideName,eBlockId,sideEntities);
   
        // don't try to build worksets for sides that don't have
        // any entities
        if(sideEntities.size()==0) { 
        std::cout << "SIDE = " << sideName << "/" << eBlockId << " <empty>" << std::endl;
           continue;
        }
   
        std::vector<stk::mesh::Entity*> elements;
        std::vector<std::size_t> localSideIds;
        panzer_stk::workset_utils::getSideElements(*mesh,eBlockId,sideEntities,localSideIds,elements);
        TEUCHOS_ASSERT(localSideIds.size()==elements.size());
   
        FieldContainer vertices;
        vertices.resize(elements.size(),4,dim);  
   
        // loop over elements of this block
        std::vector<std::size_t> localIds;
        for(std::size_t elm=0;elm<elements.size();++elm) {
           std::vector<stk::mesh::EntityId> nodes;
           stk::mesh::Entity * element = elements[elm];
   
           localIds.push_back(mesh->elementLocalId(element));
           getNodeIds(mesh->getNodeRank(),element,nodes);
   
           TEUCHOS_ASSERT(nodes.size()==4);
   
           for(std::size_t v=0;v<nodes.size();++v) {
              const double * coord = mesh->getNodeCoordinates(nodes[v]);
              
              for(unsigned d=0;d<dim;++d) 
                 vertices(elm,v,d) = coord[d]; 
           }
        }
   
        // print an excessive amount of information
        std::cout << "SIDE = " << sideName << "/" << eBlockId << std::endl;
        for(std::size_t elm=0;elm<elements.size();++elm) {
           std::cout << "   LID = " << localIds[elm];
           std::cout << ", Side = " << localSideIds[elm];
           std::cout << ", V = ";
   
           for(std::size_t v=0;v<4;++v) {
              std::cout << "[ ";
              for(unsigned d=0;d<dim;++d) 
                 std::cout << vertices(elm,v,d) << " ";
              std::cout << "], ";
           }
           std::cout << std::endl;
        }
     }
  }

  return 0;
}
Пример #25
0
int main(int argc, char *argv[]) {

    Teuchos::GlobalMPISession mpiSession(&argc, &argv);

    // This little trick lets us print to std::cout only if
    // a (dummy) command-line argument is provided.
    int iprint     = argc - 1;
    Teuchos::RCP<std::ostream> outStream;
    Teuchos::oblackholestream bhs; // outputs nothing
    if (iprint > 0)
        outStream = Teuchos::rcp(&std::cout, false);
    else
        outStream = Teuchos::rcp(&bhs, false);

    // Save the format state of the original std::cout.
    Teuchos::oblackholestream oldFormatState;
    oldFormatState.copyfmt(std::cout);

    *outStream \
            << "===============================================================================\n" \
            << "|                                                                             |\n" \
            << "|                 Unit Test (Basis_HDIV_QUAD_I1_FEM)                           |\n" \
            << "|                                                                             |\n" \
            << "|     1) Conversion of Dof tags into Dof ordinals and back                    |\n" \
            << "|     2) Basis values for VALUE and DIV operators                             |\n" \
            << "|                                                                             |\n" \
            << "|  Questions? Contact  Pavel Bochev  ([email protected]),                    |\n" \
            << "|                      Denis Ridzal  ([email protected]),                    |\n" \
            << "|                      Kara Peterson ([email protected]).                    |\n" \
            << "|                                                                             |\n" \
            << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n" \
            << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
            << "|                                                                             |\n" \
            << "===============================================================================\n"\
            << "| TEST 1: Basis creation, exception testing                                   |\n"\
            << "===============================================================================\n";

    // Define basis and error flag
    Basis_HDIV_QUAD_I1_FEM<double, FieldContainer<double> > quadBasis;
    int errorFlag = 0;

    // Initialize throw counter for exception testing
    int nException     = 0;
    int throwCounter   = 0;

    // Array with the 4 vertices of the reference Quadrilateral, its center and 4 more points
    FieldContainer<double> quadNodes(9, 2);
    quadNodes(0,0) = -1.0;
    quadNodes(0,1) = -1.0;
    quadNodes(1,0) =  1.0;
    quadNodes(1,1) = -1.0;
    quadNodes(2,0) =  1.0;
    quadNodes(2,1) =  1.0;
    quadNodes(3,0) = -1.0;
    quadNodes(3,1) =  1.0;

    quadNodes(4,0) =  0.0;
    quadNodes(4,1) =  0.0;
    quadNodes(5,0) =  0.0;
    quadNodes(5,1) = -0.5;
    quadNodes(6,0) =  0.0;
    quadNodes(6,1) =  0.5;
    quadNodes(7,0) = -0.5;
    quadNodes(7,1) =  0.0;
    quadNodes(8,0) =  0.5;
    quadNodes(8,1) =  0.0;

    // Generic array for the output values; needs to be properly resized depending on the operator type
    FieldContainer<double> vals;

    try {

        int spaceDim  = quadBasis.getBaseCellTopology().getDimension();

        // exception #1: GRAD cannot be applied to HDIV functions
        // resize vals to rank-3 container with dimensions (num. basis functions, num. points, arbitrary)
        vals.resize(quadBasis.getCardinality(), quadNodes.dimension(0), spaceDim );
        INTREPID_TEST_COMMAND( quadBasis.getValues(vals, quadNodes, OPERATOR_GRAD), throwCounter, nException );

        // exception #2: CURL cannot be applied to HDIV functions
        INTREPID_TEST_COMMAND( quadBasis.getValues(vals, quadNodes, OPERATOR_CURL), throwCounter, nException );

        // Exceptions 3-7: all bf tags/bf Ids below are wrong and should cause getDofOrdinal() and
        // getDofTag() to access invalid array elements thereby causing bounds check exception
        // exception #3
        INTREPID_TEST_COMMAND( quadBasis.getDofOrdinal(3,0,0), throwCounter, nException );
        // exception #4
        INTREPID_TEST_COMMAND( quadBasis.getDofOrdinal(1,1,1), throwCounter, nException );
        // exception #5
        INTREPID_TEST_COMMAND( quadBasis.getDofOrdinal(0,4,1), throwCounter, nException );
        // exception #6
        INTREPID_TEST_COMMAND( quadBasis.getDofTag(12), throwCounter, nException );
        // exception #7
        INTREPID_TEST_COMMAND( quadBasis.getDofTag(-1), throwCounter, nException );

#ifdef HAVE_INTREPID_DEBUG
        // Exceptions 8- test exception handling with incorrectly dimensioned input/output arrays
        // exception #8: input points array must be of rank-2
        FieldContainer<double> badPoints1(4, 5, 3);
        INTREPID_TEST_COMMAND( quadBasis.getValues(vals, badPoints1, OPERATOR_VALUE), throwCounter, nException );

        // exception #9 dimension 1 in the input point array must equal space dimension of the cell
        FieldContainer<double> badPoints2(4, spaceDim + 1);
        INTREPID_TEST_COMMAND( quadBasis.getValues(vals, badPoints2, OPERATOR_VALUE), throwCounter, nException );

        // exception #10 output values must be of rank-3 for OPERATOR_VALUE
        FieldContainer<double> badVals1(4, 5);
        INTREPID_TEST_COMMAND( quadBasis.getValues(badVals1, quadNodes, OPERATOR_VALUE), throwCounter, nException );

        // exception #11 output values must be of rank-2 for OPERATOR_DIV
        FieldContainer<double> badVals2(4, 5, spaceDim);
        INTREPID_TEST_COMMAND( quadBasis.getValues(badVals2, quadNodes, OPERATOR_DIV), throwCounter, nException );

        // exception #12 incorrect 0th dimension of output array (must equal number of basis functions)
        FieldContainer<double> badVals3(quadBasis.getCardinality() + 1, quadNodes.dimension(0), spaceDim);
        INTREPID_TEST_COMMAND( quadBasis.getValues(badVals3, quadNodes, OPERATOR_VALUE), throwCounter, nException );

        // exception #13 incorrect 0th dimension of output array (must equal number of basis functions)
        FieldContainer<double> badVals4(quadBasis.getCardinality() + 1, quadNodes.dimension(0));
        INTREPID_TEST_COMMAND( quadBasis.getValues(badVals4, quadNodes, OPERATOR_DIV), throwCounter, nException );

        // exception #14 incorrect 1st dimension of output array (must equal number of points)
        FieldContainer<double> badVals5(quadBasis.getCardinality(), quadNodes.dimension(0) + 1, spaceDim);
        INTREPID_TEST_COMMAND( quadBasis.getValues(badVals5, quadNodes, OPERATOR_VALUE), throwCounter, nException );

        // exception #15 incorrect 1st dimension of output array (must equal number of points)
        FieldContainer<double> badVals6(quadBasis.getCardinality(), quadNodes.dimension(0) + 1);
        INTREPID_TEST_COMMAND( quadBasis.getValues(badVals6, quadNodes, OPERATOR_DIV), throwCounter, nException );

        // exception #16: incorrect 2nd dimension of output array (must equal the space dimension)
        FieldContainer<double> badVals7(quadBasis.getCardinality(), quadNodes.dimension(0), spaceDim + 1);
        INTREPID_TEST_COMMAND( quadBasis.getValues(badVals7, quadNodes, OPERATOR_VALUE), throwCounter, nException );
#endif

    }
    catch (std::logic_error err) {
        *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
        *outStream << err.what() << '\n';
        *outStream << "-------------------------------------------------------------------------------" << "\n\n";
        errorFlag = -1000;
    };

    // Check if number of thrown exceptions matches the one we expect
    if (throwCounter != nException) {
        errorFlag++;
        *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
    }

    *outStream \
            << "\n"
            << "===============================================================================\n"\
            << "| TEST 2: correctness of tag to enum and enum to tag lookups                  |\n"\
            << "===============================================================================\n";

    try {
        std::vector<std::vector<int> > allTags = quadBasis.getAllDofTags();

        // Loop over all tags, lookup the associated dof enumeration and then lookup the tag again
        for (unsigned i = 0; i < allTags.size(); i++) {
            int bfOrd  = quadBasis.getDofOrdinal(allTags[i][0], allTags[i][1], allTags[i][2]);

            std::vector<int> myTag = quadBasis.getDofTag(bfOrd);
            if( !( (myTag[0] == allTags[i][0]) &&
                    (myTag[1] == allTags[i][1]) &&
                    (myTag[2] == allTags[i][2]) &&
                    (myTag[3] == allTags[i][3]) ) ) {
                errorFlag++;
                *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
                *outStream << " getDofOrdinal( {"
                           << allTags[i][0] << ", "
                           << allTags[i][1] << ", "
                           << allTags[i][2] << ", "
                           << allTags[i][3] << "}) = " << bfOrd <<" but \n";
                *outStream << " getDofTag(" << bfOrd << ") = { "
                           << myTag[0] << ", "
                           << myTag[1] << ", "
                           << myTag[2] << ", "
                           << myTag[3] << "}\n";
            }
        }

        // Now do the same but loop over basis functions
        for( int bfOrd = 0; bfOrd < quadBasis.getCardinality(); bfOrd++) {
            std::vector<int> myTag  = quadBasis.getDofTag(bfOrd);
            int myBfOrd = quadBasis.getDofOrdinal(myTag[0], myTag[1], myTag[2]);
            if( bfOrd != myBfOrd) {
                errorFlag++;
                *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
                *outStream << " getDofTag(" << bfOrd << ") = { "
                           << myTag[0] << ", "
                           << myTag[1] << ", "
                           << myTag[2] << ", "
                           << myTag[3] << "} but getDofOrdinal({"
                           << myTag[0] << ", "
                           << myTag[1] << ", "
                           << myTag[2] << ", "
                           << myTag[3] << "} ) = " << myBfOrd << "\n";
            }
        }
    }
    catch (std::logic_error err) {
        *outStream << err.what() << "\n\n";
        errorFlag = -1000;
    };

    *outStream \
            << "\n"
            << "===============================================================================\n"\
            << "| TEST 3: correctness of basis function values                                |\n"\
            << "===============================================================================\n";

    outStream -> precision(20);

    // VALUE: Each row pair gives the 6x3 correct basis set values at an evaluation point: (P,F,D) layout
    double basisValues[] = {
        0, -0.500000, 0, 0, 0, 0, -0.500000, 0, 0, -0.500000, 0.500000, 0, 0, \
        0, 0, 0, 0, 0, 0.500000, 0, 0, 0.500000, 0, 0, 0, 0, 0, 0, 0, \
        0.500000, -0.500000, 0, 0, -0.250000, 0.250000, 0, 0, 0.250000, \
        -0.250000, 0, 0, -0.375000, 0.250000, 0, 0, 0.125000, -0.250000, 0, \
        0, -0.125000, 0.250000, 0, 0, 0.375000, -0.250000, 0, 0, -0.250000, \
        0.125000, 0, 0, 0.250000, -0.375000, 0, 0, -0.250000, 0.375000, 0, 0, \
        0.250000, -0.125000, 0
    };

    // DIV: each row gives the 6 correct values of the divergence of the 6 basis functions: (P,F) layout
    double basisDivs[] = {
        0.25, 0.25, 0.25, 0.25,
        0.25, 0.25, 0.25, 0.25,
        0.25, 0.25, 0.25, 0.25,
        0.25, 0.25, 0.25, 0.25,
        0.25, 0.25, 0.25, 0.25,
        0.25, 0.25, 0.25, 0.25,
        0.25, 0.25, 0.25, 0.25,
        0.25, 0.25, 0.25, 0.25,
        0.25, 0.25, 0.25, 0.25,
    };

    try {

        // Dimensions for the output arrays:
        int numPoints = quadNodes.dimension(0);
        int numFields = quadBasis.getCardinality();
        int spaceDim  = quadBasis.getBaseCellTopology().getDimension();

        // Generic array for values and curls that will be properly sized before each call
        FieldContainer<double> vals;

        // Check VALUE of basis functions: resize vals to rank-3 container:
        vals.resize(numFields, numPoints, spaceDim);
        quadBasis.getValues(vals, quadNodes, OPERATOR_VALUE);
        for (int i = 0; i < numFields; i++) {
            for (int j = 0; j < numPoints; j++) {
                for (int k = 0; k < spaceDim; k++) {

                    // compute offset for (P,F,D) data layout: indices are P->j, F->i, D->k
                    int l = k + i * spaceDim + j * spaceDim * numFields;
                    if (std::abs(vals(i,j,k) - basisValues[l]) > INTREPID_TOL) {
                        errorFlag++;
                        *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

                        // Output the multi-index of the value where the error is:
                        *outStream << " At multi-index { ";
                        *outStream << i << " ";
                        *outStream << j << " ";
                        *outStream << k << " ";
                        *outStream << "}  computed value: " << vals(i,j,k)
                                   << " but reference value: " << basisValues[l] << "\n";
                    }
                }
            }
        }

        // Check DIV of basis function: resize vals to rank-2 container
        vals.resize(numFields, numPoints);
        quadBasis.getValues(vals, quadNodes, OPERATOR_DIV);
        for (int i = 0; i < numFields; i++) {
            for (int j = 0; j < numPoints; j++) {
                int l =  i + j * numFields;
                if (std::abs(vals(i,j) - basisDivs[l]) > INTREPID_TOL) {
                    errorFlag++;
                    *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

                    // Output the multi-index of the value where the error is:
                    *outStream << " At multi-index { ";
                    *outStream << i << " ";
                    *outStream << j << " ";
                    *outStream << "}  computed divergence component: " << vals(i,j)
                               << " but reference divergence component: " << basisDivs[l] << "\n";
                }
            }
        }

    }

    // Catch unexpected errors
    catch (std::logic_error err) {
        *outStream << err.what() << "\n\n";
        errorFlag = -1000;
    };

    if (errorFlag != 0)
        std::cout << "End Result: TEST FAILED\n";
    else
        std::cout << "End Result: TEST PASSED\n";

    // reset format state of std::cout
    std::cout.copyfmt(oldFormatState);

    return errorFlag;
}
Пример #26
0
int main(int argc, char *argv[]) {

  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
 Kokkos::initialize();
  // This little trick lets us print to std::cout only if
  // a (dummy) command-line argument is provided.
  int iprint     = argc - 1;
  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing
  if (iprint > 0)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs, false);

  // Save the format state of the original std::cout.
  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);

  *outStream \
    << "===============================================================================\n" \
    << "|                                                                             |\n" \
    << "|               Unit Test (Basis_HGRAD_LINE_Cn_FEM)                           |\n" \
    << "|                                                                             |\n" \
    << "|     1) Conversion of Dof tags into Dof ordinals and back                    |\n" \
    << "|     2) Basis values for VALUE, GRAD, CURL, and Dk operators                 |\n" \
    << "|                                                                             |\n" \
    << "|  Questions? Contact  Pavel Bochev  ([email protected]),                    |\n" \
    << "|                      Denis Ridzal  ([email protected]),                    |\n" \
    << "|                      Kara Peterson ([email protected]).                    |\n" \
    << "|                                                                             |\n" \
    << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n" \
    << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
    << "|                                                                             |\n" \
    << "===============================================================================\n"\
    << "| TEST 1: Basis creation, exception testing                                   |\n"\
    << "===============================================================================\n";

  
  // Define basis and error flag
  shards::CellTopology line(shards::getCellTopologyData< shards::Line<> >());   // create cell topology
  const int deg = 5;

  // get the points for the basis
  FieldContainer<double> pts(PointTools::getLatticeSize(line,deg),1);
  PointTools::getLattice<double,FieldContainer<double> >(pts,line,deg);

  Basis_HGRAD_LINE_Cn_FEM<double, FieldContainer<double> > lineBasis(deg, pts);
  int errorFlag = 0;

  // Initialize throw counter for exception testing
  int nException     = 0;
  int throwCounter   = 0;
  
  // Define array containing vertices of the reference Line and a few other points   
  int numIntervals = 100;
  FieldContainer<double> lineNodes(numIntervals+1, 1);
  for (int i=0; i<numIntervals+1; i++) {
    lineNodes(i,0) = -1.0+(2.0*(double)i)/(double)numIntervals;
  }

  // Generic array for the output values; needs to be properly resized depending on the operator type
  FieldContainer<double> vals;

  try{
    // exception #1: DIV cannot be applied to scalar functions
    // resize vals to rank-2 container with dimensions (num. points, num. basis functions)
    vals.resize(lineBasis.getCardinality(), lineNodes.dimension(0) );
    //INTREPID_TEST_COMMAND( lineBasis.getValues(vals, lineNodes, OPERATOR_DIV), throwCounter, nException );

    // Exceptions 1-5: all bf tags/bf Ids below are wrong and should cause getDofOrdinal() and
    // getDofTag() to access invalid array elements thereby causing bounds check exception
    // exception #1
    INTREPID_TEST_COMMAND( lineBasis.getDofOrdinal(2,0,0), throwCounter, nException );
    // exception #2
    INTREPID_TEST_COMMAND( lineBasis.getDofOrdinal(1,1,1), throwCounter, nException );
     // exception #3
    INTREPID_TEST_COMMAND( lineBasis.getDofOrdinal(1,0,7), throwCounter, nException );
    // exception #4
    INTREPID_TEST_COMMAND( lineBasis.getDofTag(6), throwCounter, nException );
    // exception #5
    INTREPID_TEST_COMMAND( lineBasis.getDofTag(-1), throwCounter, nException );
    // not an exception
    INTREPID_TEST_COMMAND( lineBasis.getDofTag(5), throwCounter, nException ); --nException;

#ifdef HAVE_INTREPID2_DEBUG
    // Exceptions 6-14 test exception handling with incorrectly dimensioned input/output arrays
    // exception #6: input points array must be of rank-2
    FieldContainer<double> badPoints1(4, 5, 3);
    INTREPID_TEST_COMMAND( lineBasis.getValues(vals, badPoints1, OPERATOR_VALUE), throwCounter, nException );

    // exception #7: dimension 1 in the input point array must equal space dimension of the cell
    FieldContainer<double> badPoints2(4, 3);
    INTREPID_TEST_COMMAND( lineBasis.getValues(vals, badPoints2, OPERATOR_VALUE), throwCounter, nException );

    // exception #8: output values must be of rank-2 for OPERATOR_VALUE
    FieldContainer<double> badVals1(4, 3, 1);
    INTREPID_TEST_COMMAND( lineBasis.getValues(badVals1, lineNodes, OPERATOR_VALUE), throwCounter, nException );

    // exception #9: output values must be of rank-3 for OPERATOR_GRAD
    FieldContainer<double> badVals2(4, 3);
    INTREPID_TEST_COMMAND( lineBasis.getValues(badVals2, lineNodes, OPERATOR_GRAD), throwCounter, nException );

    // exception #10: output values must be of rank-2 for OPERATOR_D1
    INTREPID_TEST_COMMAND( lineBasis.getValues(badVals2, lineNodes, OPERATOR_D1), throwCounter, nException );

    // exception #11: incorrect 0th dimension of output array (must equal number of basis functions)
    FieldContainer<double> badVals3(lineBasis.getCardinality() + 1, lineNodes.dimension(0));
    INTREPID_TEST_COMMAND( lineBasis.getValues(badVals3, lineNodes, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #12: incorrect 1st dimension of output array (must equal number of points)
    FieldContainer<double> badVals4(lineBasis.getCardinality(), lineNodes.dimension(0) + 1);
    INTREPID_TEST_COMMAND( lineBasis.getValues(badVals4, lineNodes, OPERATOR_VALUE), throwCounter, nException );

    // exception #13: incorrect 2nd dimension of output array (must equal spatial dimension)
    FieldContainer<double> badVals5(lineBasis.getCardinality(), lineNodes.dimension(0), 2);
    INTREPID_TEST_COMMAND( lineBasis.getValues(badVals5, lineNodes, OPERATOR_GRAD), throwCounter, nException );

    
    // not an exception
    FieldContainer<double> goodVals2(lineBasis.getCardinality(), lineNodes.dimension(0));
    INTREPID_TEST_COMMAND( lineBasis.getValues(goodVals2, lineNodes, OPERATOR_VALUE), throwCounter, nException ); --nException;
#endif

  }
  catch (std::logic_error err) {
    *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
    *outStream << err.what() << '\n';
    *outStream << "-------------------------------------------------------------------------------" << "\n\n";
    errorFlag = -1000;
  };

  // Check if number of thrown exceptions matches the one we expect
  if (throwCounter != nException) {
    errorFlag++;
    *outStream << std::setw(70) << "FAILURE! Incorrect number of exceptions." << "\n";
  }

   *outStream \
     << "\n"
     << "===============================================================================\n" \
     << "| TEST 2: correctness of basis function values                                |\n" \
     << "===============================================================================\n";
   outStream -> precision(20);


   try {
     // Check Kronecker property for Lagrange polynomials.
     int maxorder = 4;

     for (int ordi=1; ordi <= maxorder; ordi++) {
       FieldContainer<double> pts(PointTools::getLatticeSize(line,ordi),1);
       PointTools::getLattice<double,FieldContainer<double> >(pts,line,ordi);
       Basis_HGRAD_LINE_Cn_FEM<double, FieldContainer<double> > lineBasis(ordi, pts);
       FieldContainer<double> vals(lineBasis.getCardinality(),pts.dimension(0));
       lineBasis.getValues(vals,pts,OPERATOR_VALUE);
       for (int i=0;i<lineBasis.getCardinality();i++) {
  	for (int j=0;j<pts.dimension(0);j++) {
  	  if ( i==j && std::abs( vals(i,j) - 1.0 ) > INTREPID_TOL ) {
  	    errorFlag++;
  	    *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
 	    *outStream << " Basis function " << i << " does not have unit value at its node\n";
 	  }
 	  if ( i!=j && std::abs( vals(i,j) ) > INTREPID_TOL ) {
 	    errorFlag++;
 	    *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
 	    *outStream << " Basis function " << i << " does not vanish at node " << j << "\n";
 	  }
 	}
       }
     }
   }
  // Catch unexpected errors
  catch (std::logic_error err) {
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  };

  if (errorFlag != 0)
    std::cout << "End Result: TEST FAILED\n";
  else
    std::cout << "End Result: TEST PASSED\n";

  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);
 Kokkos::finalize();
  return errorFlag;
}
Пример #27
0
FieldContainer<double> SubBasisDofMatrixMapper::mapData(bool transposeConstraint, FieldContainer<double> &localData, bool applyOnLeftOnly)
{
    // localData must be rank 2, and must have the same size as FilteredLocalDofOrdinals in its first dimension
    bool didReshape = false;
    if (localData.rank() == 1)
    {
        // reshape as a rank 2 container (column vector as a matrix):
        localData.resize(localData.dimension(0),1);
        didReshape = true;
    }
    if (localData.rank() != 2)
    {
        cout << "localData must have rank 1 or 2.\n";
        TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "localData must have rank 1 or 2");
    }
    int constraintRows = transposeConstraint ? _constraintMatrix.dimension(1) : _constraintMatrix.dimension(0);
    int constraintCols = transposeConstraint ? _constraintMatrix.dimension(0) : _constraintMatrix.dimension(1);
    int dataCols = localData.dimension(1);
    int dataRows = localData.dimension(0);

    if ((dataCols==0) || (dataRows==0) || (constraintRows==0) || (constraintCols==0))
    {
        cout << "degenerate matrix encountered.\n";
    }

    // given the multiplication we'll do, we need constraint columns = data rows
    if (constraintCols != dataRows)
    {
        cout << "Missized container in SubBasisDofMatrixMapper::mapData() for left-multiplication by constraint matrix.\n";
        TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "Missized container in SubBasisDofMatrixMapper::mapData().");
    }
    // (could also test that the dimensions match what we expect in terms of the size of the mapped global dof ordinals or basisDofOrdinal filter)

    FieldContainer<double> result1(constraintRows,dataCols);

    char constraintTransposeFlag = transposeConstraint ? 'T' : 'N';
    char dataTransposeFlag = 'N';

    SerialDenseWrapper::multiply(result1,_constraintMatrix,localData,constraintTransposeFlag,dataTransposeFlag);

    if (didReshape)   // change the shape of localData back, and return result
    {
        localData.resize(localData.dimension(0));
        result1.resize(result1.size());
        return result1;
    }

    if (applyOnLeftOnly) return result1;

    if (constraintCols != dataCols)
    {
        cout << "Missized container in SubBasisDofMatrixMapper::mapData() for right-multiplication by constraint matrix.\n";
        TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "Missized container in SubBasisDofMatrixMapper::mapData().");
    }

    constraintTransposeFlag = (!transposeConstraint) ? 'T' : 'N'; // opposite of the above choice, since now we multiply on the right
    char resultTransposeFlag = 'N';

    FieldContainer<double> result(constraintRows,constraintRows);
    SerialDenseWrapper::multiply(result,result1,_constraintMatrix,resultTransposeFlag,constraintTransposeFlag);

    return result;
}
Пример #28
0
bool testBasisClassifications(BasisPtr basis) {
  bool success = true;
  
  CellTopoPtr cellTopo = basis->domainTopology();
  
  int numVertices = cellTopo->getVertexCount();
  int numEdges = cellTopo->getEdgeCount();
  
  int degree = basis->getDegree();
  
  // TODO: finish this
  vector<int> vertexOrdinals;
  for (int vertexIndex=0; vertexIndex < numVertices; vertexIndex++) {
    set<int> dofOrdinals = basis->dofOrdinalsForVertex(vertexIndex);
    if (dofOrdinals.size() == 0) TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "No dofOrdinal for vertex...");
    if (dofOrdinals.size() > 1) TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "More than one dofOrdinal per vertex...");
    vertexOrdinals.push_back(*(dofOrdinals.begin()));
  }
//  
//  if (! checkVertexOrdinalsQuad(basis, vertexOrdinals) ) {
//    success = false;
//    cout << "vertex dof ordinals don't match expected\n";
//    cout << "ordinals: ";
//    for (int vertexIndex=0; vertexIndex < numVertices; vertexIndex++) {
//      cout << vertexOrdinals[vertexIndex] << " ";
//    }
//    cout << endl;
//  }
  
  // get the points in reference space for each vertex
  FieldContainer<double> points;
  if (numVertices == 2) { // line
    points.resize(2,1);
    points(0,0) = -1;
    points(1,0) = 1;
  } else if (numVertices == 3) { // triangle
    TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "triangles not yet supported");
  } else if (numVertices == 4) { // quad
    points.resize(4,2);
    points(0,0) = -1;
    points(0,1) = -1;
    points(1,0) =  1;
    points(1,1) = -1;
    points(2,0) =  1;
    points(2,1) =  1;
    points(3,0) = -1;
    points(3,1) =  1;
  } else {
    TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "unsupported topology");
  }
  
  FieldContainer<double> vertexValues;
  if (basis->rangeRank() > 0) {
    TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "rank > 0 bases not yet supported");
  } else {
    vertexValues.resize(basis->getCardinality(),numVertices);
  }
  
  basis->getValues(vertexValues, points, Intrepid::OPERATOR_VALUE);
  
  // test that the points are correctly classified
  for (int fieldIndex=0; fieldIndex<basis->getCardinality(); fieldIndex++) {
    for (int ptIndex=0; ptIndex<numVertices; ptIndex++) {
      int dofOrdinalForPoint = vertexOrdinals[ptIndex];
      bool expectZero = (dofOrdinalForPoint != fieldIndex);
      if (expectZero) {
        if (vertexValues(fieldIndex,ptIndex) != 0) {
          success = false;
          cout << "Expected 0 for fieldIndex " << fieldIndex << " and ptIndex " << ptIndex;
          cout << ", but got " << vertexValues(fieldIndex,ptIndex) << endl;
        }
      } else {
        if (vertexValues(fieldIndex,ptIndex) == 0) {
          cout << "Expected nonzero for fieldIndex " << fieldIndex << " and ptIndex " << ptIndex << endl;
          success = false;
        }
      }
    }
  }
  
  if (!success) {
    cout << "Failed testBasisClassifications; vertexValues:\n" << vertexValues;
  }
  
  return success;
}
Пример #29
0
int main(int argc, char *argv[]) {
  
  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
 Kokkos::initialize();
  // This little trick lets us print to std::cout only if
  // a (dummy) command-line argument is provided.
  int iprint     = argc - 1;
  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing
  if (iprint > 0)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs, false);
  
  // Save the format state of the original std::cout.
  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);
  
  *outStream \
    << "===============================================================================\n" \
    << "|                                                                             |\n" \
    << "|                 Unit Test (Basis_HGRAD_TET_C2_FEM)                          |\n" \
    << "|                                                                             |\n" \
    << "|     1) Conversion of Dof tags into Dof ordinals and back                    |\n" \
    << "|     2) Basis values for VALUE, GRAD, and Dk operators                       |\n" \
    << "|                                                                             |\n" \
    << "|  Questions? Contact  Pavel Bochev  ([email protected]),                    |\n" \
    << "|                      Denis Ridzal  ([email protected]),                    |\n" \
    << "|                      Kara Peterson ([email protected]).                    |\n" \
    << "|                                                                             |\n" \
    << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n" \
    << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
    << "|                                                                             |\n" \
    << "===============================================================================\n"\
    << "| TEST 1: Basis creation, exception testing                                   |\n"\
    << "===============================================================================\n";
  
  // Define basis and error flag
  Basis_HGRAD_TET_C2_FEM<double, FieldContainer<double> > tetBasis;
  int errorFlag = 0;

  // Initialize throw counter for exception testing
  int nException     = 0;
  int throwCounter   = 0;

  // Define array containing the 10 nodes of Tetrahedron<10>: 4 vertices + 6 edge midpoints  
  FieldContainer<double> tetNodes(10, 3);
  tetNodes(0,0) =  0.0;  tetNodes(0,1) =  0.0;  tetNodes(0,2) =  0.0;  
  tetNodes(1,0) =  1.0;  tetNodes(1,1) =  0.0;  tetNodes(1,2) =  0.0;  
  tetNodes(2,0) =  0.0;  tetNodes(2,1) =  1.0;  tetNodes(2,2) =  0.0;
  tetNodes(3,0) =  0.0;  tetNodes(3,1) =  0.0;  tetNodes(3,2) =  1.0;  
  
  tetNodes(4,0) =  0.5;  tetNodes(4,1) =  0.0;  tetNodes(4,2) =  0.0;
  tetNodes(5,0) =  0.5;  tetNodes(5,1) =  0.5;  tetNodes(5,2) =  0.0;  
  tetNodes(6,0) =  0.0;  tetNodes(6,1) =  0.5;  tetNodes(6,2) =  0.0;  
  tetNodes(7,0) =  0.0;  tetNodes(7,1) =  0.0;  tetNodes(7,2) =  0.5;  
  tetNodes(8,0) =  0.5;  tetNodes(8,1) =  0.0;  tetNodes(8,2) =  0.5;  
  tetNodes(9,0) =  0.0;  tetNodes(9,1) =  0.5;  tetNodes(9,2) =  0.5;  


  // Generic array for the output values; needs to be properly resized depending on the operator type
  FieldContainer<double> vals;

  try{
    // exception #1: CURL cannot be applied to scalar functions
    // resize vals to rank-3 container with dimensions (num. points, num. basis functions, arbitrary)
    vals.resize(tetBasis.getCardinality(), tetNodes.dimension(0), 4 );
    INTREPID_TEST_COMMAND( tetBasis.getValues(vals, tetNodes, OPERATOR_CURL), throwCounter, nException );

    // exception #2: DIV cannot be applied to scalar functions
    // resize vals to rank-2 container with dimensions (num. points, num. basis functions)
    vals.resize(tetBasis.getCardinality(), tetNodes.dimension(0) );
    INTREPID_TEST_COMMAND( tetBasis.getValues(vals, tetNodes, OPERATOR_DIV), throwCounter, nException );
        
    // Exceptions 3-7: all bf tags/bf Ids below are wrong and should cause getDofOrdinal() and 
    // getDofTag() to access invalid array elements thereby causing bounds check exception
    // exception #3
    INTREPID_TEST_COMMAND( tetBasis.getDofOrdinal(3,0,0), throwCounter, nException );
    // exception #4
    INTREPID_TEST_COMMAND( tetBasis.getDofOrdinal(1,1,1), throwCounter, nException );
    // exception #5
    INTREPID_TEST_COMMAND( tetBasis.getDofOrdinal(0,4,0), throwCounter, nException );
    // exception #6
    INTREPID_TEST_COMMAND( tetBasis.getDofTag(10), throwCounter, nException );
    // exception #7
    INTREPID_TEST_COMMAND( tetBasis.getDofTag(-1), throwCounter, nException );
    
#ifdef HAVE_INTREPID2_DEBUG 
    // Exceptions 8-18 test exception handling with incorrectly dimensioned input/output arrays
    // exception #8: input points array must be of rank-2
    FieldContainer<double> badPoints1(4, 5, 3);
    INTREPID_TEST_COMMAND( tetBasis.getValues(vals, badPoints1, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #9 dimension 1 in the input point array must equal space dimension of the cell
    FieldContainer<double> badPoints2(4, tetBasis.getBaseCellTopology().getDimension() - 1);
    INTREPID_TEST_COMMAND( tetBasis.getValues(vals, badPoints2, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #10 output values must be of rank-2 for OPERATOR_VALUE
    FieldContainer<double> badVals1(4, 3, 1);
    INTREPID_TEST_COMMAND( tetBasis.getValues(badVals1, tetNodes, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #11 output values must be of rank-3 for OPERATOR_GRAD
    FieldContainer<double> badVals2(4, 3);
    INTREPID_TEST_COMMAND( tetBasis.getValues(badVals2, tetNodes, OPERATOR_GRAD), throwCounter, nException );
    
    // exception #12 output values must be of rank-3 for OPERATOR_D1
    INTREPID_TEST_COMMAND( tetBasis.getValues(badVals2, tetNodes, OPERATOR_D1), throwCounter, nException );
    
    // exception #13 output values must be of rank-3 for OPERATOR_D2
    INTREPID_TEST_COMMAND( tetBasis.getValues(badVals2, tetNodes, OPERATOR_D2), throwCounter, nException );
    
    // exception #14 incorrect 0th dimension of output array (must equal number of basis functions)
    FieldContainer<double> badVals3(tetBasis.getCardinality() + 1, tetNodes.dimension(0));
    INTREPID_TEST_COMMAND( tetBasis.getValues(badVals3, tetNodes, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #15 incorrect 1st dimension of output array (must equal number of points)
    FieldContainer<double> badVals4(tetBasis.getCardinality(), tetNodes.dimension(0) + 1);
    INTREPID_TEST_COMMAND( tetBasis.getValues(badVals4, tetNodes, OPERATOR_VALUE), throwCounter, nException );
    
    // exception #16: incorrect 2nd dimension of output array (must equal the space dimension)
    FieldContainer<double> badVals5(tetBasis.getCardinality(), tetNodes.dimension(0), tetBasis.getBaseCellTopology().getDimension() + 1);
    INTREPID_TEST_COMMAND( tetBasis.getValues(badVals5, tetNodes, OPERATOR_GRAD), throwCounter, nException );
    
    // exception #17: incorrect 2nd dimension of output array (must equal D2 cardinality in 2D)
    FieldContainer<double> badVals6(tetBasis.getCardinality(), tetNodes.dimension(0), 40);
    INTREPID_TEST_COMMAND( tetBasis.getValues(badVals6, tetNodes, OPERATOR_D1), throwCounter, nException );
    
    // exception #18: incorrect 2nd dimension of output array (must equal D3 cardinality in 2D)
    INTREPID_TEST_COMMAND( tetBasis.getValues(badVals6, tetNodes, OPERATOR_D2), throwCounter, nException );
#endif
    
  }
  catch (std::logic_error err) {
    *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
    *outStream << err.what() << '\n';
    *outStream << "-------------------------------------------------------------------------------" << "\n\n";
    errorFlag = -1000;
  };
  
  // Check if number of thrown exceptions matches the one we expect 
  if (throwCounter != nException) {
    errorFlag++;
    *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
  }
  
  *outStream \
    << "\n"
    << "===============================================================================\n"\
    << "| TEST 2: correctness of tag to enum and enum to tag lookups                  |\n"\
    << "===============================================================================\n";
  
  try{
    std::vector<std::vector<int> > allTags = tetBasis.getAllDofTags();
    
    // Loop over all tags, lookup the associated dof enumeration and then lookup the tag again
    for (unsigned i = 0; i < allTags.size(); i++) {
      int bfOrd  = tetBasis.getDofOrdinal(allTags[i][0], allTags[i][1], allTags[i][2]);
      
      std::vector<int> myTag = tetBasis.getDofTag(bfOrd);
       if( !( (myTag[0] == allTags[i][0]) &&
              (myTag[1] == allTags[i][1]) &&
              (myTag[2] == allTags[i][2]) &&
              (myTag[3] == allTags[i][3]) ) ) {
        errorFlag++;
        *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
        *outStream << " getDofOrdinal( {" 
          << allTags[i][0] << ", " 
          << allTags[i][1] << ", " 
          << allTags[i][2] << ", " 
          << allTags[i][3] << "}) = " << bfOrd <<" but \n";   
        *outStream << " getDofTag(" << bfOrd << ") = { "
          << myTag[0] << ", " 
          << myTag[1] << ", " 
          << myTag[2] << ", " 
          << myTag[3] << "}\n";        
      }
    }
    
    // Now do the same but loop over basis functions
    for( int bfOrd = 0; bfOrd < tetBasis.getCardinality(); bfOrd++) {
      std::vector<int> myTag  = tetBasis.getDofTag(bfOrd);
      int myBfOrd = tetBasis.getDofOrdinal(myTag[0], myTag[1], myTag[2]);
      if( bfOrd != myBfOrd) {
        errorFlag++;
        *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
        *outStream << " getDofTag(" << bfOrd << ") = { "
          << myTag[0] << ", " 
          << myTag[1] << ", " 
          << myTag[2] << ", " 
          << myTag[3] << "} but getDofOrdinal({" 
          << myTag[0] << ", " 
          << myTag[1] << ", " 
          << myTag[2] << ", " 
          << myTag[3] << "} ) = " << myBfOrd << "\n";
      }
    }
  }
  catch (std::logic_error err){
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  };
  
  *outStream \
    << "\n"
    << "===============================================================================\n"\
    << "| TEST 3: correctness of basis function values                                |\n"\
    << "===============================================================================\n";
  
  outStream -> precision(20);
  
  // VALUE: in (F,P) format
  double basisValues[] = {
    1.00000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.00000, 0, 0, 0, 0, 0, 0, 0, \
    0, 0, 0, 1.00000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.00000, 0, 0, 0, 0, \
    0, 0, 0, 0, 0, 0, 1.00000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.00000, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 0, 1.00000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    1.00000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.00000, 0, 0, 0, 0, 0, 0, 0, \
    0, 0, 0, 1.00000 };
  
  // GRAD and D1: in (F,P,D) format
  double basisGrads[] = {
    -3.00000, -3.00000, -3.00000, 1.00000, 1.00000, 1.00000, 1.00000, \
    1.00000, 1.00000, 1.00000, 1.00000, 1.00000, -1.00000, -1.00000, \
    -1.00000, 1.00000, 1.00000, 1.00000, -1.00000, -1.00000, -1.00000, \
    -1.00000, -1.00000, -1.00000, 1.00000, 1.00000, 1.00000, 1.00000, \
    1.00000, 1.00000, -1.00000, 0, 0, 3.00000, 0, 0, -1.00000, 0, 0, \
    -1.00000, 0, 0, 1.00000, 0, 0, 1.00000, 0, 0, -1.00000, 0, 0, \
    -1.00000, 0, 0, 1.00000, 0, 0, -1.00000, 0, 0, 0, -1.00000, 0, 0, \
    -1.00000, 0, 0, 3.00000, 0, 0, -1.00000, 0, 0, -1.00000, 0, 0, \
    1.00000, 0, 0, 1.00000, 0, 0, -1.00000, 0, 0, -1.00000, 0, 0, \
    1.00000, 0, 0, 0, -1.00000, 0, 0, -1.00000, 0, 0, -1.00000, 0, 0, \
    3.00000, 0, 0, -1.00000, 0, 0, -1.00000, 0, 0, -1.00000, 0, 0, \
    1.00000, 0, 0, 1.00000, 0, 0, 1.00000, 4.00000, 0, 0, -4.00000, \
    -4.00000, -4.00000, 0, 0, 0, 0, 0, 0, 0, -2.00000, -2.00000, \
    -2.00000, -2.00000, -2.00000, 2.00000, 0, 0, 2.00000, 0, 0, -2.00000, \
    -2.00000, -2.00000, 0, 0, 0, 0, 0, 0, 0, 4.00000, 0, 4.00000, 0, 0, \
    0, 0, 0, 0, 2.00000, 0, 2.00000, 2.00000, 0, 2.00000, 0, 0, 0, 0, 0, \
    0, 2.00000, 0, 2.00000, 0, 0, 0, 4.00000, 0, 0, 0, 0, -4.00000, \
    -4.00000, -4.00000, 0, 0, 0, 0, 2.00000, 0, -2.00000, -2.00000, \
    -2.00000, -2.00000, 0, -2.00000, 0, 2.00000, 0, 0, 0, 0, -2.00000, \
    -2.00000, -2.00000, 0, 0, 4.00000, 0, 0, 0, 0, 0, 0, -4.00000, \
    -4.00000, -4.00000, 0, 0, 2.00000, 0, 0, 0, 0, 0, 2.00000, -2.00000, \
    -2.00000, 0, -2.00000, -2.00000, -2.00000, -2.00000, -2.00000, \
    -2.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 4.00000, 0, 0, 0, 0, \
    2.00000, 0, 0, 2.00000, 0, 0, 0, 2.00000, 0, 0, 2.00000, 0, 2.00000, \
    2.00000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.00000, 0, 4.00000, 0, 0, 0, \
    0, 0, 0, 2.00000, 0, 0, 2.00000, 0, 2.00000, 0, 0, 2.00000, 0, 0, \
    2.00000, 2.00000};
  
  // D2 values in (F,P, Dk) format
  double basisD2[]={
    4.00000, 4.00000, 4.00000, 4.00000, 4.00000, 4.00000, 4.00000, \
    4.00000, 4.00000, 4.00000, 4.00000, 4.00000, 4.00000, 4.00000, \
    4.00000, 4.00000, 4.00000, 4.00000, 4.00000, 4.00000, 4.00000, \
    4.00000, 4.00000, 4.00000, 4.00000, 4.00000, 4.00000, 4.00000, \
    4.00000, 4.00000, 4.00000, 4.00000, 4.00000, 4.00000, 4.00000, \
    4.00000, 4.00000, 4.00000, 4.00000, 4.00000, 4.00000, 4.00000, \
    4.00000, 4.00000, 4.00000, 4.00000, 4.00000, 4.00000, 4.00000, \
    4.00000, 4.00000, 4.00000, 4.00000, 4.00000, 4.00000, 4.00000, \
    4.00000, 4.00000, 4.00000, 4.00000, 4.00000, 0, 0, 0, 0, 0, 4.00000, \
    0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, \
    4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, \
    0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, \
    0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, \
    4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, \
    0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, \
    0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 0, 0, 4.00000, \
    0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, \
    4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, \
    0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, \
    0, 0, 4.00000, -8.00000, -4.00000, -4.00000, 0, 0, 0, -8.00000, \
    -4.00000, -4.00000, 0, 0, 0, -8.00000, -4.00000, -4.00000, 0, 0, 0, \
    -8.00000, -4.00000, -4.00000, 0, 0, 0, -8.00000, -4.00000, -4.00000, \
    0, 0, 0, -8.00000, -4.00000, -4.00000, 0, 0, 0, -8.00000, -4.00000, \
    -4.00000, 0, 0, 0, -8.00000, -4.00000, -4.00000, 0, 0, 0, -8.00000, \
    -4.00000, -4.00000, 0, 0, 0, -8.00000, -4.00000, -4.00000, 0, 0, 0, \
    0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, \
    0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, \
    0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, \
    0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, -4.00000, 0, -8.00000, -4.00000, \
    0, 0, -4.00000, 0, -8.00000, -4.00000, 0, 0, -4.00000, 0, -8.00000, \
    -4.00000, 0, 0, -4.00000, 0, -8.00000, -4.00000, 0, 0, -4.00000, 0, \
    -8.00000, -4.00000, 0, 0, -4.00000, 0, -8.00000, -4.00000, 0, 0, \
    -4.00000, 0, -8.00000, -4.00000, 0, 0, -4.00000, 0, -8.00000, \
    -4.00000, 0, 0, -4.00000, 0, -8.00000, -4.00000, 0, 0, -4.00000, 0, \
    -8.00000, -4.00000, 0, 0, 0, -4.00000, 0, -4.00000, -8.00000, 0, 0, \
    -4.00000, 0, -4.00000, -8.00000, 0, 0, -4.00000, 0, -4.00000, \
    -8.00000, 0, 0, -4.00000, 0, -4.00000, -8.00000, 0, 0, -4.00000, 0, \
    -4.00000, -8.00000, 0, 0, -4.00000, 0, -4.00000, -8.00000, 0, 0, \
    -4.00000, 0, -4.00000, -8.00000, 0, 0, -4.00000, 0, -4.00000, \
    -8.00000, 0, 0, -4.00000, 0, -4.00000, -8.00000, 0, 0, -4.00000, 0, \
    -4.00000, -8.00000, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, \
    0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, \
    0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, \
    0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 0, 0, \
    4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, \
    0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, \
    0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, 0, 0, 0, 4.00000, 0, 0, \
    0, 0, 0, 4.00000, 0
  };
  
  
  try{
        
    // Dimensions for the output arrays:
    int numFields = tetBasis.getCardinality();
    int numPoints = tetNodes.dimension(0);
    int spaceDim  = tetBasis.getBaseCellTopology().getDimension();
    
    // Generic array for values, grads, curls, etc. that will be properly sized before each call
    FieldContainer<double> vals;
    
    // Check VALUE of basis functions: resize vals to rank-2 container:
    vals.resize(numFields, numPoints);
    tetBasis.getValues(vals, tetNodes, OPERATOR_VALUE);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
          int l =  i + j * numFields;
           if (std::abs(vals(i,j) - basisValues[l]) > INTREPID_TOL) {
             errorFlag++;
             *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

             // Output the multi-index of the value where the error is:
             *outStream << " At multi-index { ";
             *outStream << i << " ";*outStream << j << " ";
             *outStream << "}  computed value: " << vals(i,j)
               << " but reference value: " << basisValues[l] << "\n";
         }
      }
    }

    // Check GRAD of basis function: resize vals to rank-3 container
    vals.resize(numFields, numPoints, spaceDim);
    tetBasis.getValues(vals, tetNodes, OPERATOR_GRAD);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < spaceDim; k++) {
 
          // basisGrads is (F,P,D), compute offset:
          int l = k + j * spaceDim + i * spaceDim * numPoints;
           if (std::abs(vals(i,j,k) - basisGrads[l]) > INTREPID_TOL) {
             errorFlag++;
             *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

             // Output the multi-index of the value where the error is:
             *outStream << " At multi-index { ";
             *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
             *outStream << "}  computed grad component: " << vals(i,j,k)
               << " but reference grad component: " << basisGrads[l] << "\n";
            }
         }
      }
    }

    // Check D1 of basis function (do not resize vals because it has the correct size: D1 = GRAD)
    tetBasis.getValues(vals, tetNodes, OPERATOR_D1);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < spaceDim; k++) {
          
          // basisGrads is (F,P,D), compute offset:
          int l = k + j * spaceDim + i * spaceDim * numPoints;
           if (std::abs(vals(i,j,k) - basisGrads[l]) > INTREPID_TOL) {
             errorFlag++;
             *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";

             // Output the multi-index of the value where the error is:
             *outStream << " At multi-index { ";
             *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
             *outStream << "}  computed D1 component: " << vals(i,j,k)
               << " but reference D1 component: " << basisGrads[l] << "\n";
            }
         }
      }
    }

    // Check D2 of basis function
    int D2cardinality = Intrepid2::getDkCardinality(OPERATOR_D2, spaceDim);
    vals.resize(numFields, numPoints, D2cardinality);    
    tetBasis.getValues(vals, tetNodes, OPERATOR_D2);
    for (int i = 0; i < numFields; i++) {
      for (int j = 0; j < numPoints; j++) {
        for (int k = 0; k < D2cardinality; k++) {
          
          // basisD2 is (F,P,Dk), compute offset:
          int l = k + j * D2cardinality + i * D2cardinality * numPoints;
          if (std::abs(vals(i,j,k) - basisD2[l]) > INTREPID_TOL) {
            errorFlag++;
            *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
            
            // Output the multi-index of the value where the error is:
            *outStream << " At multi-index { ";
            *outStream << i << " ";*outStream << j << " ";*outStream << k << " ";
            *outStream << "}  computed D2 component: " << vals(i,j,k)
              << " but reference D2 component: " << basisD2[l] << "\n";
          }
        }
      }
    }
    
    
    // Check all higher derivatives - must be zero. 
    for(EOperator op = OPERATOR_D3; op < OPERATOR_MAX; op++) {
      
      // The last dimension is the number of kth derivatives and needs to be resized for every Dk
      int DkCardin  = Intrepid2::getDkCardinality(op, spaceDim);
      vals.resize(numFields, numPoints, DkCardin);    

      tetBasis.getValues(vals, tetNodes, op);
      for (int i1 = 0; i1 < numFields; i1++) 
        for (int i2 = 0; i2 < numPoints; i2++) 
          for (int i3 = 0; i3 < DkCardin; i3++) {
            if (std::abs(vals(i1,i2,i3)) > INTREPID_TOL) {
              errorFlag++;
              *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
          
              // Get the multi-index of the value where the error is and the operator order
              int ord = Intrepid2::getOperatorOrder(op);
              *outStream << " At multi-index { "<<i1<<" "<<i2 <<" "<<i3;
              *outStream << "}  computed D"<< ord <<" component: " << vals(i1,i2,i3) 
                         << " but reference D" << ord << " component:  0 \n";
            }
          }
    }    
  }
  
  // Catch unexpected errors
  catch (std::logic_error err) {
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  };
  
  if (errorFlag != 0)
    std::cout << "End Result: TEST FAILED\n";
  else
    std::cout << "End Result: TEST PASSED\n";
  
  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);
   Kokkos::finalize();
  return errorFlag;
}
Пример #30
0
void ExactSolution::L2NormOfError(FieldContainer<double> &errorSquaredPerCell, Solution &solution, ElementTypePtr elemTypePtr, int trialID, int sideIndex, int cubDegree, double solutionLift) {
//  BasisCache(ElementTypePtr elemType, Teuchos::RCP<Mesh> mesh = Teuchos::rcp( (Mesh*) NULL ), bool testVsTest=false, int cubatureDegreeEnrichment = 0)

  DofOrdering dofOrdering = *(elemTypePtr->trialOrderPtr.get());
  BasisPtr basis = dofOrdering.getBasis(trialID,sideIndex);
  
  bool boundaryIntegral = solution.mesh()->bilinearForm()->isFluxOrTrace(trialID);
  
  BasisCachePtr basisCache;
  if (cubDegree <= 0) { // then take the default cub. degree
    basisCache = Teuchos::rcp( new BasisCache( elemTypePtr, solution.mesh() ) );
  } else {
    // we could eliminate the logic below if we just added BasisCache::setCubatureDegree()...
    // (the logic below is just to make the enriched cubature match the requested cubature degree...)
    int maxTrialDegree;
    if (!boundaryIntegral) {
      maxTrialDegree = elemTypePtr->trialOrderPtr->maxBasisDegreeForVolume();
    } else {
      maxTrialDegree = elemTypePtr->trialOrderPtr->maxBasisDegree(); // generally, this will be the trace degree
    }
    int maxTestDegree = elemTypePtr->testOrderPtr->maxBasisDegree();
    int cubDegreeEnrichment = max(cubDegree - (maxTrialDegree + maxTestDegree), 0);
    basisCache = Teuchos::rcp( new BasisCache( elemTypePtr, solution.mesh(), false, cubDegreeEnrichment) );
  }
  
  // much of this code is the same as what's in the volume integration in computeStiffness...
  FieldContainer<double> physicalCellNodes = solution.mesh()->physicalCellNodes(elemTypePtr);
  vector<GlobalIndexType> cellIDs = solution.mesh()->cellIDsOfType(elemTypePtr);
  basisCache->setPhysicalCellNodes(physicalCellNodes, cellIDs, true);
  
  if (boundaryIntegral) {
    basisCache = basisCache->getSideBasisCache(sideIndex);
  }
  
  FieldContainer<double> weightedMeasure = basisCache->getWeightedMeasures();
  FieldContainer<double> weightedErrorSquared;
  
  int numCells = basisCache->getPhysicalCubaturePoints().dimension(0);
  int numCubPoints = basisCache->getPhysicalCubaturePoints().dimension(1);
  int spaceDim = basisCache->getPhysicalCubaturePoints().dimension(2);
  
  Teuchos::Array<int> dimensions;
  dimensions.push_back(numCells);
  dimensions.push_back(numCubPoints);
  
  int basisRank = BasisFactory::basisFactory()->getBasisRank(basis);
  if (basisRank==1) {
    dimensions.push_back(spaceDim);
  }
  
  FieldContainer<double> computedValues(dimensions);
  FieldContainer<double> exactValues(dimensions);
  
  if (solutionLift != 0.0) {
    int size = computedValues.size();
    for (int i=0; i<size; i++) {
      computedValues[i] += solutionLift;
    }
  }
  
  solution.solutionValues(computedValues, trialID, basisCache);
  this->solutionValues(exactValues, trialID, basisCache);
  
//  cout << "ExactSolution: exact values:\n" << exactValues;
//  cout << "ExactSolution: computed values:\n" << computedValues;
  
  FieldContainer<double> errorSquared(numCells,numCubPoints);
  
  squaredDifference(errorSquared,computedValues,exactValues);
  
  weightedErrorSquared.resize(numCells,numCubPoints);
  for (int cellIndex=0; cellIndex<numCells; cellIndex++) {
    for (int ptIndex=0; ptIndex<numCubPoints; ptIndex++) {
      // following two lines for viewing in the debugger:
      double weight = weightedMeasure(cellIndex,ptIndex);
      double errorSquaredVal = errorSquared(cellIndex,ptIndex);
      weightedErrorSquared(cellIndex,ptIndex) = errorSquared(cellIndex,ptIndex) * weightedMeasure(cellIndex,ptIndex);
    }
  }
  
  // compute the integral
  errorSquaredPerCell.initialize(0.0);
  int numPoints = weightedErrorSquared.dimension(1);
  for (int cellIndex=0; cellIndex<numCells; cellIndex++) {
    for (int ptIndex=0; ptIndex<numPoints; ptIndex++) {
      errorSquaredPerCell(cellIndex) += weightedErrorSquared(cellIndex,ptIndex);
    }
  }
}