ordinal_type compareToAnalytic( std::ifstream &inputFile,
                                  const Kokkos::DynRankView<ValueType,testMatProperties...> testMat,
                                  const ValueType reltol,
                                  const ordinal_type iprint,
                                  const TypeOfExactData analyticDataType ) {
    INTREPID2_TEST_FOR_EXCEPTION( testMat.rank() != 2, std::invalid_argument,
                                  ">>> ERROR (compareToAnalytic): testMat must have rank 2");

    Teuchos::RCP<std::ostream> outStream;
    Teuchos::oblackholestream  outNothing;
    if (iprint > 0)
      outStream = Teuchos::rcp(&std::cout, false);
    else
      outStream = Teuchos::rcp(&outNothing, false);

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

    std::string line;
    ValueType testentry;
    ValueType abstol;
    ValueType absdiff;
    ordinal_type i = 0, j = 0;
    ordinal_type err = 0;

    while (! inputFile.eof() && i < static_cast<ordinal_type>(testMat.dimension(0)) ) {
      std::getline(inputFile,line);
      std::istringstream linestream(line);
      std::string chunk;
      j = 0;
      while( linestream >> chunk ) {
        ordinal_type num1;
        ordinal_type num2;
        std::string::size_type loc = chunk.find( "/", 0);
        if( loc != std::string::npos ) {
          chunk.replace( loc, 1, " ");
          std::istringstream chunkstream(chunk);
          chunkstream >> num1;
          chunkstream >> num2;
          testentry = (ValueType)(num1)/(ValueType)(num2);
          abstol = ( std::fabs(testentry) < reltol ? reltol : std::fabs(reltol*testentry) );
          absdiff = std::fabs(testentry - testMat(i, j));
          if (absdiff > abstol) {
            ++err;
            *outStream << "FAILURE --> ";
          }
          *outStream << "entry[" << i << "," << j << "]:" << "   "
                     << testMat(i, j) << "   " << num1 << "/" << num2 << "   "
                     << absdiff << "   " << "<?" << "   " << abstol << "\n";
        }
        else {
          std::istringstream chunkstream(chunk);
          if (analyticDataType == INTREPID2_UTILS_FRACTION) {
            chunkstream >> num1;
            testentry = (ValueType)(num1);
          }
          else if (analyticDataType == INTREPID2_UTILS_SCALAR)
Example #2
0
int main(int argc, char *argv[]) {
//  feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);

  typedef ROL::Vector<RealT>          V;
  typedef ROL::Objective<RealT>       OBJ;
  typedef ROL::BoundConstraint<RealT> CON; 
  using Teuchos::RCP;

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

  RealT zero(0);

  RCP<V>   x0;
  RCP<V>   x;
  RCP<V>   g;
  RCP<OBJ> obj;
  RCP<CON> con;
  RCP<OBJ> model;  

  ROL::ZOO::getHS2(obj,con,x0,x);

  g = x->dual().clone();

  // Need to evaluate the gradient to construct the model
  obj->gradient(*g,*x,zero);

  model = Teuchos::rcp(new ROL::ColemanLiModel<RealT>(*obj,*con,*x,*g));

  RCP<V> s = x->clone();
  RCP<V> v = x->clone();
  RCP<V> u = x->clone();

  ROL::RandomizeVector(*s,-1.0,1.0);
  ROL::RandomizeVector(*u,-1.0,1.0);
  ROL::RandomizeVector(*v,-1.0,1.0);

  model->checkGradient(*s,*v);
  model->checkHessVec(*s,*v);
  model->checkHessSym(*s,*u,*v);

  return 0;
}
std::vector<Real> Objective<Real>::checkHessSym( const Vector<Real> &x,
                                                 const Vector<Real> &hv,
                                                 const Vector<Real> &v,
                                                 const Vector<Real> &w,
                                                 const bool printToStream,
                                                 std::ostream & outStream ) {

  Real tol = std::sqrt(ROL_EPSILON);
  
  // Compute (Hessian at x) times (vector v).
  Teuchos::RCP<Vector<Real> > h = hv.clone();
  this->hessVec(*h, v, x, tol);
  Real wHv = w.dot(h->dual());

  this->hessVec(*h, w, x, tol);
  Real vHw = v.dot(h->dual());

  std::vector<Real> hsymCheck(3, 0);

  hsymCheck[0] = wHv;
  hsymCheck[1] = vHw;
  hsymCheck[2] = std::abs(vHw-wHv);

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

  if (printToStream) {
    outStream << std::right
              << std::setw(20) << "<w, H(x)v>"
              << std::setw(20) << "<v, H(x)w>"
              << std::setw(20) << "abs error"
              << "\n";
    outStream << std::scientific << std::setprecision(11) << std::right
              << std::setw(20) << hsymCheck[0]
              << std::setw(20) << hsymCheck[1]
              << std::setw(20) << hsymCheck[2]
              << "\n";
  }

  // Reset format state of outStream.
  outStream.copyfmt(oldFormatState);

  return hsymCheck;

} // checkHessSym
Example #4
0
    int HDIV_WEDGE_I1_FEM_Test01(const bool verbose) {

      Teuchos::RCP<std::ostream> outStream;
      Teuchos::oblackholestream bhs; // outputs nothing

      if (1)// (verbose)
        outStream = Teuchos::rcp(&std::cout, false);
      else
        outStream = Teuchos::rcp(&bhs,       false);

      Teuchos::oblackholestream oldFormatState;
      oldFormatState.copyfmt(std::cout);

      typedef typename
        Kokkos::Impl::is_space<DeviceSpaceType>::host_mirror_space::execution_space HostSpaceType ;

      *outStream << "DeviceSpace::  "; DeviceSpaceType::print_configuration(*outStream, false);
      *outStream << "HostSpace::    ";   HostSpaceType::print_configuration(*outStream, false);
      
      *outStream  
        << "===============================================================================\n"
        << "|                                                                             |\n"
        << "|                 Unit Test (Basis_HDIV_WEDGE_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";

      typedef Kokkos::DynRankView<ValueType,DeviceSpaceType> DynRankView;
      typedef Kokkos::DynRankView<ValueType,HostSpaceType> DynRankViewHost;
#define ConstructWithLabel(obj, ...) obj(#obj, __VA_ARGS__)

      const ValueType tol = tolerence();
      int errorFlag = 0;

      // for virtual function, value and point types are declared in the class
      typedef ValueType outputValueType;
      typedef ValueType pointValueType;
      Basis_HDIV_WEDGE_I1_FEM<DeviceSpaceType,outputValueType,pointValueType> wedgeBasis;

      *outStream
        << "\n"
        << "===============================================================================\n"
        << "| TEST 1: constructors and exceptions                                         |\n"
        << "===============================================================================\n";

      try {
        ordinal_type nthrow = 0, ncatch = 0;
#ifdef HAVE_INTREPID2_DEBUG
  // Define array containing the 6 vertices of the reference WEDGE and 6 other points.
  DynRankView ConstructWithLabel(wedgeNodes, 12, 3);

        // Generic array for the output values; needs to be properly resized depending on the operator type
        const auto numFields = wedgeBasis.getCardinality();
        const auto numPoints = wedgeNodes.dimension(0);
        const auto spaceDim  = wedgeBasis.getBaseCellTopology().getDimension();
        
    // exception #1: GRAD cannot be applied to HDIV functions 
    DynRankView ConstructWithLabel(vals, numFields, numPoints, spaceDim );
    INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(vals, wedgeNodes, OPERATOR_GRAD));

    // exception #2: CURL cannot be applied to HDIV functions
    INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(vals, wedgeNodes, OPERATOR_CURL));
        
    // 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
    INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getDofOrdinal(3,0,0));
    // exception #4
    INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getDofOrdinal(1,1,1));
    // exception #5
    INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getDofOrdinal(0,4,1));
    // exception #6
    INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getDofTag(11));
    // exception #7
    INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getDofTag(-1));

    // Exceptions 8-15 test exception handling with incorrectly dimensioned input/output arrays
    // exception #8: input points array must be of rank-2
    DynRankView ConstructWithLabel(badPoints1, 4, 5, 3);
    INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(vals, badPoints1, OPERATOR_VALUE));

    // exception #9 dimension 1 in the input point array must equal space dimension of the cell
    DynRankView ConstructWithLabel(badPoints2, 4, 2);
    INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(vals, badPoints2, OPERATOR_VALUE));
    
    // exception #10 output values must be of rank-3 for OPERATOR_VALUE
    DynRankView ConstructWithLabel(badVals1, 4, 3);
    INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(badVals1, wedgeNodes, OPERATOR_VALUE));
 
    // exception #11 output values must be of rank-2 for OPERATOR_DIV
    DynRankView ConstructWithLabel(badVals2, 4, 3, 1);
    INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(badVals2, wedgeNodes, OPERATOR_DIV));
    
    // exception #12 incorrect 0th dimension of output array (must equal number of basis functions)
    DynRankView ConstructWithLabel(badVals3, wedgeBasis.getCardinality() + 1, wedgeNodes.dimension(0), 3);
    INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(badVals3, wedgeNodes, OPERATOR_VALUE));

    // exception #13 incorrect 0th dimension of output array (must equal number of basis functions)
    DynRankView ConstructWithLabel(badVals4, wedgeBasis.getCardinality() + 1, wedgeNodes.dimension(0));
    INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(badVals4, wedgeNodes, OPERATOR_DIV));

    // exception #14 incorrect 1st dimension of output array (must equal number of points)
    DynRankView ConstructWithLabel(badVals5, wedgeBasis.getCardinality(), wedgeNodes.dimension(0) + 1, 3);
    INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(badVals5, wedgeNodes, OPERATOR_VALUE));

    // exception #15 incorrect 1st dimension of output array (must equal number of points)
    DynRankView ConstructWithLabel(badVals6, wedgeBasis.getCardinality(), wedgeNodes.dimension(0) + 1);
    INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(badVals6, wedgeNodes, OPERATOR_DIV));

    // exception #16: incorrect 2nd dimension of output array (must equal the space dimension)
    DynRankView ConstructWithLabel(badVals7, wedgeBasis.getCardinality(), wedgeNodes.dimension(0), 4);
    INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(badVals7, wedgeNodes, OPERATOR_VALUE));
#endif
    
      } catch (std::logic_error err) {
        *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
        *outStream << err.what() << '\n';
        *outStream << "-------------------------------------------------------------------------------" << "\n\n";
        errorFlag = -1000;
      }
  
      *outStream
        << "\n"
        << "===============================================================================\n"
        << "| TEST 2: correctness of tag to enum and enum to tag lookups                  |\n"
        << "===============================================================================\n";
  
      try{
        const auto numFields = wedgeBasis.getCardinality();
        const auto allTags = wedgeBasis.getAllDofTags();

        // Loop over all tags, lookup the associated dof enumeration and then lookup the tag again
        const auto dofTagSize = allTags.dimension(0);
    
    // Loop over all tags, lookup the associated dof enumeration and then lookup the tag again
    for (size_type i = 0; i < dofTagSize; i++) {
      const auto bfOrd  = wedgeBasis.getDofOrdinal(allTags(i, 0), allTags(i, 1), allTags(i, 2));
      
      const auto 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 <numFields; bfOrd++) {
      const auto myTag  = wedgeBasis.getDofTag(bfOrd);
      const auto 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: Each row pair gives the 5x3 correct basis set values at an evaluation point
  double basisValues[] = {
    0, -0.500000, 0, 0, 0, 0, -0.500000, 0, 0, 0, 0, -2.00000, 0, 0, 0, \
    0.500000, -0.500000, 0, 0.500000, 0, 0, 0, 0, 0, 0, 0, -2.00000, 0, \
    0, 0, 0, 0, 0, 0, 0.500000, 0, -0.500000, 0.500000, 0, 0, 0, \
    -2.00000, 0, 0, 0, 0, -0.500000, 0, 0, 0, 0, -0.500000, 0, 0, 0, 0, \
    0, 0, 0, 2.00000, 0.500000, -0.500000, 0, 0.500000, 0, 0, 0, 0, 0, 0, \
    0, 0, 0, 0, 2.00000, 0, 0, 0, 0, 0.500000, 0, -0.500000, 0.500000, 0, \
    0, 0, 0, 0, 0, 2.00000, 0.125000, -0.250000, 0, 0.125000, 0.250000, \
    0, -0.375000, 0.250000, 0, 0, 0, -2.00000, 0, 0, 0, 0.250000, \
    -0.375000, 0, 0.250000, 0.125000, 0, -0.250000, 0.125000, 0, 0, 0, \
    -1.00000, 0, 0, 1.00000, 0.125000, -0.375000, 0, 0.125000, 0.125000, \
    0, -0.375000, 0.125000, 0, 0, 0, 0, 0, 0, 2.00000, 0.125000, \
    -0.500000, 0, 0.125000, 0, 0, -0.375000, 0, 0, 0, 0, -0.250000, 0, 0, \
    1.75000, 0, -0.250000, 0, 0, 0.250000, 0, -0.500000, 0.250000, 0, 0, \
    0, -1.25000, 0, 0, 0.750000, 0.250000, -0.250000, 0, 0.250000, \
    0.250000, 0, -0.250000, 0.250000, 0, 0, 0, -1.00000, 0, 0, 1.00000};
  
  // DIV: each row pair gives the 5 correct values of the divergence of the 5 basis functions
  double basisDivs[] = {   
    // 6 vertices
    1.0, 1.0, 1.0, 1.0, 1.0,
    1.0, 1.0, 1.0, 1.0, 1.0,
    1.0, 1.0, 1.0, 1.0, 1.0,
    1.0, 1.0, 1.0, 1.0, 1.0,
    1.0, 1.0, 1.0, 1.0, 1.0,
    1.0, 1.0, 1.0, 1.0, 1.0,
    // 6 other points
    1.0, 1.0, 1.0, 1.0, 1.0,
    1.0, 1.0, 1.0, 1.0, 1.0,
    1.0, 1.0, 1.0, 1.0, 1.0,
    1.0, 1.0, 1.0, 1.0, 1.0,
    1.0, 1.0, 1.0, 1.0, 1.0,
    1.0, 1.0, 1.0, 1.0, 1.0
  };
  
  try{

    DynRankViewHost ConstructWithLabel(wedgeNodesHost, 12, 3);
    wedgeNodesHost(0,0) =  0.0;  wedgeNodesHost(0,1) =  0.0;  wedgeNodesHost(0,2) = -1.0;
    wedgeNodesHost(1,0) =  1.0;  wedgeNodesHost(1,1) =  0.0;  wedgeNodesHost(1,2) = -1.0;
    wedgeNodesHost(2,0) =  0.0;  wedgeNodesHost(2,1) =  1.0;  wedgeNodesHost(2,2) = -1.0;
    wedgeNodesHost(3,0) =  0.0;  wedgeNodesHost(3,1) =  0.0;  wedgeNodesHost(3,2) =  1.0;
    wedgeNodesHost(4,0) =  1.0;  wedgeNodesHost(4,1) =  0.0;  wedgeNodesHost(4,2) =  1.0;
    wedgeNodesHost(5,0) =  0.0;  wedgeNodesHost(5,1) =  1.0;  wedgeNodesHost(5,2) =  1.0;

    wedgeNodesHost(6,0) =  0.25; wedgeNodesHost(6,1) =  0.5;  wedgeNodesHost(6,2) = -1.0;
    wedgeNodesHost(7,0) =  0.5;  wedgeNodesHost(7,1) =  0.25; wedgeNodesHost(7,2) =  0.0;
    wedgeNodesHost(8,0) =  0.25; wedgeNodesHost(8,1) =  0.25; wedgeNodesHost(8,2) =  1.0;
    wedgeNodesHost(9,0) =  0.25; wedgeNodesHost(9,1) =  0.0;  wedgeNodesHost(9,2) =  0.75;
    wedgeNodesHost(10,0)=  0.0;  wedgeNodesHost(10,1)=  0.5;  wedgeNodesHost(10,2)= -0.25;
    wedgeNodesHost(11,0)=  0.5;  wedgeNodesHost(11,1)=  0.5;  wedgeNodesHost(11,2)=  0.0;
        
        const auto wedgeNodes = Kokkos::create_mirror_view(typename DeviceSpaceType::memory_space(), wedgeNodesHost);
        Kokkos::deep_copy(wedgeNodes, wedgeNodesHost);

        // Dimensions for the output arrays:
        const auto numFields = wedgeBasis.getCardinality();
        const auto numPoints = wedgeNodes.dimension(0);
        const auto spaceDim  = wedgeBasis.getBaseCellTopology().getDimension();

    
    // Check VALUE of basis functions: resize vals to rank-3 container:
    {
    DynRankView ConstructWithLabel(vals, numFields, numPoints, spaceDim);
    wedgeBasis.getValues(vals, wedgeNodes, OPERATOR_VALUE);
    const auto vals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), vals);
    Kokkos::deep_copy(vals_host, vals);
    for (int i = 0; i < numFields; i++) {
      for (size_type j = 0; j < numPoints; j++) {
        for (size_type k = 0; k < spaceDim; k++) {
           int l = k + i * spaceDim + j * spaceDim * numFields;
           if (std::abs(vals_host(i,j,k) - basisValues[l]) > 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_host(i,j,k)
               << " but reference value: " << basisValues[l] << "\n";
            }
         }
      }
    }
    }

    
    // Check DIV of basis function: resize vals to rank-2 container
    {
    DynRankView ConstructWithLabel(vals, numFields, numPoints);
    wedgeBasis.getValues(vals, wedgeNodes, OPERATOR_DIV);
    const auto vals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), vals);
    Kokkos::deep_copy(vals_host, vals);
    for (int i = 0; i < numFields; i++) {
      for (size_type j = 0; j < numPoints; j++) {
          int l =  i + j * numFields;
           if (std::abs(vals_host(i,j) - basisDivs[l]) > 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_host(i,j)
               << " but reference divergence component: " << basisDivs[l] << "\n";
         }
      }
    }
    }
          } catch (std::logic_error err) {
        *outStream << err.what() << "\n\n";
        errorFlag = -1000;
      }

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

      try {
        const auto numFields = wedgeBasis.getCardinality();
        const auto spaceDim  = wedgeBasis.getBaseCellTopology().getDimension();

        // Check exceptions.
        ordinal_type nthrow = 0, ncatch = 0;
#ifdef HAVE_INTREPID2_DEBUG
        {
          DynRankView ConstructWithLabel(badVals, 1,2,3);
          INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getDofCoords(badVals) );
        }
        {
          DynRankView ConstructWithLabel(badVals, 4,3);
          INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getDofCoords(badVals) );
        }
        {
          DynRankView ConstructWithLabel(badVals, 5,2);
          INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getDofCoords(badVals) );
        }
#endif
        if (nthrow != ncatch) {
          errorFlag++;
          *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
          *outStream << "# of catch ("<< ncatch << ") is different from # of throw (" << ncatch << ")\n";
        }
       
        DynRankView ConstructWithLabel(bvals, numFields, numFields, spaceDim);
        DynRankView ConstructWithLabel(cvals, numFields, spaceDim);
       
        // Check mathematical correctness.
        wedgeBasis.getDofCoords(cvals);
        wedgeBasis.getValues(bvals, cvals, OPERATOR_VALUE);

        // Check mathematical correctness
        DynRankViewHost ConstructWithLabel(normals, numFields,spaceDim); // normals at each point basis point
        normals(0,0)  =  0.0; normals(0,1)  = -2.0; normals(0,2)  =  0.0;
        normals(1,0)  =  2.0; normals(1,1)  =  2.0; normals(1,2)  =  0.0;
        normals(2,0)  = -2.0; normals(2,1)  =  0.0; normals(2,2)  =  0.0;
        normals(3,0)  =  0.0; normals(3,1)  =  0.0; normals(3,2)  = -0.5;
        normals(4,0)  =  0.0; normals(4,1)  =  0.0; normals(4,2)  =  0.5;
    
        auto cvals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), cvals);
        Kokkos::deep_copy(cvals_host, cvals);

        auto bvals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), bvals);
        Kokkos::deep_copy(bvals_host, bvals);
    
        for (ordinal_type i=0;i<numFields;++i) {
          for (ordinal_type j=0;j<numFields;++j) {

            ValueType normal = 0.0;
            for(size_type d=0;d<spaceDim;++d) {
               normal += bvals_host(i,j,d)*normals(j,d);
            }

            const ValueType expected_normal = (i == j);
            if (std::abs(normal - expected_normal) > tol || isnan(normal)) {
              errorFlag++;
              std::stringstream ss;
              ss << "\nNormal component of basis function " << i << " at (" << cvals_host(j,0) << ", " << cvals_host(j,1)<< ", " << cvals_host(j,2) << ") is " << normal << " but should be " << expected_normal << "\n";
              *outStream << ss.str();
            }
          }
        }
      } 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;
    }
Example #5
0
  int HCURL_WEDGE_I1_FEM_Test01(const bool verbose) {
      
    Teuchos::RCP<std::ostream> outStream;
    Teuchos::oblackholestream bhs; // outputs nothing

    if (verbose)
      outStream = Teuchos::rcp(&std::cout, false);
    else
      outStream = Teuchos::rcp(&bhs, false);
      
    Teuchos::oblackholestream oldFormatState;
    oldFormatState.copyfmt(std::cout);
      
    typedef typename
      Kokkos::Impl::is_space<DeviceSpaceType>::host_mirror_space::execution_space HostSpaceType ;
      
    *outStream << "DeviceSpace::  "; DeviceSpaceType::print_configuration(*outStream, false);
    *outStream << "HostSpace::    ";   HostSpaceType::print_configuration(*outStream, false);

  *outStream 
    << "\n"
    << "===============================================================================\n" 
    << "|                                                                             |\n" 
    << "|                 Unit Test (Basis_HCURL_WEDGE_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]),                    |\n" 
    << "|                      Denis Ridzal  ([email protected]),                    |\n" 
    << "|                      Kara Peterson ([email protected]).                    |\n" 
    << "|                      Kyungjoo Kim  ([email protected]).                     |\n"
    << "|                                                                             |\n" 
    << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n" 
    << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" 
    << "|                                                                             |\n" 
    << "===============================================================================\n";

      typedef Kokkos::DynRankView<ValueType,DeviceSpaceType> DynRankView;
      typedef Kokkos::DynRankView<ValueType,HostSpaceType> DynRankViewHost;
#define ConstructWithLabel(obj, ...) obj(#obj, __VA_ARGS__)
      const ValueType tol = tolerence();

      int errorFlag = 0;

      // for virtual function, value and point types are declared in the class
      typedef ValueType outputValueType;
      typedef ValueType pointValueType;
      Basis_HCURL_WEDGE_I1_FEM<DeviceSpaceType,outputValueType,pointValueType> wedgeBasis;

  *outStream 
    << "\n"
    << "===============================================================================\n"
    << "| TEST 1: Basis creation, exception testing                                   |\n"
    << "===============================================================================\n";

  try{
    ordinal_type nthrow = 0, ncatch = 0;
#ifdef HAVE_INTREPID2_DEBUG
    // Define array containing the 4 vertices of the reference WEDGE and its center.
    DynRankView ConstructWithLabel(wedgeNodes, 12, 3);

    // Generic array for the output values; needs to be properly resized depending on the operator type
    const ordinal_type numFields = wedgeBasis.getCardinality();
    const ordinal_type numPoints = wedgeNodes.dimension(0);
    const ordinal_type spaceDim  = wedgeBasis.getBaseCellTopology().getDimension();

    DynRankView vals ("vals", numFields, numPoints);
    DynRankView vals_vec ("vals", numFields, numPoints, spaceDim);

    {
    // exception #1: GRAD cannot be applied to HCURL functions 
    // resize vals to rank-3 container with dimensions (num. basis functions, num. points, arbitrary)
      INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(vals_vec, wedgeNodes, OPERATOR_GRAD) );

    // exception #2: DIV cannot be applied to HCURL functions
    // resize vals to rank-2 container with dimensions (num. basis functions, num. points)
      INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(vals, wedgeNodes, OPERATOR_DIV) );
    }   
    // 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
      INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getDofOrdinal(3,0,0) );
    // exception #4
      INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getDofOrdinal(1,1,1) );
    // exception #5
      INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getDofOrdinal(0,4,1) );
    // exception #6
      INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getDofTag(numFields) );
    // exception #7
      INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getDofTag(-1) );
    }

    // Exceptions 8- test exception handling with incorrectly dimensioned input/output arrays
    {
    // exception #8: input points array must be of rank-2
      DynRankView ConstructWithLabel(badPoints1, 4, 5, 3);
      INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(vals, badPoints1, OPERATOR_VALUE) );
    } 
    {
    // exception #9 dimension 1 in the input point array must equal space dimension of the cell
      DynRankView ConstructWithLabel(badPoints2, 4, 2);
      INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(vals, badPoints2, OPERATOR_VALUE) );
    }
    {
    // exception #10 output values must be of rank-3 for OPERATOR_VALUE
      DynRankView ConstructWithLabel(badVals1, 4, 3);
      INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(badVals1, wedgeNodes, OPERATOR_VALUE) );
    // exception #11 output values must be of rank-3 for OPERATOR_CURL
      INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(badVals1, wedgeNodes, OPERATOR_CURL) );
    }
    { 
    // exception #12 incorrect 0th dimension of output array (must equal number of basis functions)
      DynRankView ConstructWithLabel(badVals2, numFields + 1, numPoints, 3);
      INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(badVals2, wedgeNodes, OPERATOR_VALUE) );
    }
    {
    // exception #13 incorrect 1st dimension of output array (must equal number of points)
      DynRankView ConstructWithLabel(badVals3, numFields, numPoints + 1, 3);
      INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(badVals3, wedgeNodes, OPERATOR_VALUE) );
    }
    {
    // exception #14: incorrect 2nd dimension of output array (must equal the space dimension)
      DynRankView ConstructWithLabel(badVals4, numFields, numPoints, 4);
      INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(badVals4, wedgeNodes, OPERATOR_VALUE) );
    
    // exception #15: incorrect 2nd dimension of output array (must equal the space dimension)
      INTREPID2_TEST_ERROR_EXPECTED( wedgeBasis.getValues(badVals4, wedgeNodes, OPERATOR_CURL) );
    }
#endif
  // Check if number of thrown exceptions matches the one we expect 
    if (nthrow != ncatch) {
      errorFlag++;
      *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
      *outStream << "# of catch ("<< ncatch << ") is different from # of throw (" << nthrow << ")\n";
    }
  } catch (std::logic_error err) {
    *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
    *outStream << err.what() << '\n';
    *outStream << "-------------------------------------------------------------------------------" << "\n\n";
    errorFlag = -1000;
  };

  *outStream 
    << "\n"
    << "===============================================================================\n"
    << "| TEST 2: correctness of tag to enum and enum to tag lookups                  |\n"
    << "===============================================================================\n";
  
  try{
    const ordinal_type numFields = wedgeBasis.getCardinality();
    const auto allTags = wedgeBasis.getAllDofTags();

    // Loop over all tags, lookup the associated dof enumeration and then lookup the tag again
    const ordinal_type dofTagSize = allTags.dimension(0);
    for (ordinal_type i = 0; i < dofTagSize; ++i) {
      auto bfOrd  = wedgeBasis.getDofOrdinal(allTags(i,0), allTags(i,1), allTags(i,2));
      
      const auto 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( ordinal_type bfOrd = 0; bfOrd < numFields; ++bfOrd) {
      const auto  myTag  = wedgeBasis.getDofTag(bfOrd);
      const auto 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: Each row pair gives the 9x3 correct basis set values at an evaluation point: (P,F,D) layout
  const ValueType basisValues[] = {
    1.00000, 0, 0, 0, 0, 0, 0, -1.00000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    0, 0.500000, 0, 0, 0, 0, 0, 0, 1.00000, 1.00000, 0, 0, 1.00000, 0, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.500000, 0, 0, 0, 0, \
    0, 0, -1.00000, 0, 0, -1.00000, -1.00000, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0.500000, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    1.00000, 0, 0, 0, 0, 0, 0, -1.00000, 0, 0, 0, 0.500000, 0, 0, 0, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.00000, 1.00000, 0, 0, 1.00000, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 0.500000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    0, 0, 0, -1.00000, 0, 0, -1.00000, -1.00000, 0, 0, 0, 0, 0, 0, 0, 0, \
    0, 0.500000, 0.500000, 0.250000, 0, -0.500000, 0.250000, 0, \
    -0.500000, -0.750000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.125000, \
    0, 0, 0.125000, 0, 0, 0.250000, 0.375000, 0.250000, 0, -0.125000, \
    0.250000, 0, -0.125000, -0.250000, 0, 0.375000, 0.250000, 0, \
    -0.125000, 0.250000, 0, -0.125000, -0.250000, 0, 0, 0, 0.125000, 0, \
    0, 0.250000, 0, 0, 0.125000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.750000, \
    0.250000, 0, -0.250000, 0.250000, 0, -0.250000, -0.750000, 0, 0, 0, \
    0.250000, 0, 0, 0.125000, 0, 0, 0.125000, 0.125000, 0.0312500, 0, 0, \
    0.0312500, 0, 0, -0.0937500, 0, 0.875000, 0.218750, 0, 0, 0.218750, \
    0, 0, -0.656250, 0, 0, 0, 0.375000, 0, 0, 0.125000, 0, 0, 0, \
    0.312500, 0, 0, -0.312500, 0, 0, -0.312500, -0.625000, 0, 0.187500, \
    0, 0, -0.187500, 0, 0, -0.187500, -0.375000, 0, 0, 0, 0.250000, 0, 0, \
    0, 0, 0, 0.250000, 0.250000, 0.250000, 0, -0.250000, 0.250000, 0, \
    -0.250000, -0.250000, 0, 0.250000, 0.250000, 0, -0.250000, 0.250000, \
    0, -0.250000, -0.250000, 0, 0, 0, 0, 0, 0, 0.250000, 0, 0, 0.250000    
  };
  
  // CURL: each row pair gives the 9x3 correct values of the curls of the 9 basis functions: (P,F,D) layout
  const ValueType basisCurls[] = {  
    0, -0.500000, 2.00000, 0, 0, 2.00000, -0.500000, 0, 2.00000, 0, \
    0.500000, 0, 0, 0, 0, 0.500000, 0, 0, -0.500000, 0.500000, 0, 0, \
    -0.500000, 0, 0.500000, 0, 0, 0.500000, -0.500000, 2.00000, 0.500000, \
    0, 2.00000, 0, 0, 2.00000, -0.500000, 0.500000, 0, -0.500000, 0, 0, \
    0, 0, 0, -0.500000, 0.500000, 0, 0, -0.500000, 0, 0.500000, 0, 0, 0, \
    0, 2.00000, 0, 0.500000, 2.00000, -0.500000, 0.500000, 2.00000, 0, 0, \
    0, 0, -0.500000, 0, 0.500000, -0.500000, 0, -0.500000, 0.500000, 0, \
    0, -0.500000, 0, 0.500000, 0, 0, 0, -0.500000, 0, 0, 0, 0, -0.500000, \
    0, 0, 0, 0.500000, 2.00000, 0, 0, 2.00000, 0.500000, 0, 2.00000, \
    -0.500000, 0.500000, 0, 0, -0.500000, 0, 0.500000, 0, 0, 0.500000, \
    -0.500000, 0, 0.500000, 0, 0, 0, 0, 0, -0.500000, 0.500000, 2.00000, \
    -0.500000, 0, 2.00000, 0, 0, 2.00000, -0.500000, 0.500000, 0, 0, \
    -0.500000, 0, 0.500000, 0, 0, 0, 0, 0, 0, 0.500000, 0, -0.500000, \
    0.500000, 0, 0, 0, 2.00000, 0, -0.500000, 2.00000, 0.500000, \
    -0.500000, 2.00000, -0.500000, 0.500000, 0, 0, -0.500000, 0, \
    0.500000, 0, 0, 0.125000, -0.250000, 2.00000, 0.125000, 0.250000, \
    2.00000, -0.375000, 0.250000, 2.00000, -0.125000, 0.250000, 0, \
    -0.125000, -0.250000, 0, 0.375000, -0.250000, 0, -0.500000, 0.500000, \
    0, 0, -0.500000, 0, 0.500000, 0, 0, 0.250000, -0.375000, 1.00000, \
    0.250000, 0.125000, 1.00000, -0.250000, 0.125000, 1.00000, -0.250000, \
    0.375000, 1.00000, -0.250000, -0.125000, 1.00000, 0.250000, \
    -0.125000, 1.00000, -0.500000, 0.500000, 0, 0, -0.500000, 0, \
    0.500000, 0, 0, 0.125000, -0.375000, 0, 0.125000, 0.125000, 0, \
    -0.375000, 0.125000, 0, -0.125000, 0.375000, 2.00000, -0.125000, \
    -0.125000, 2.00000, 0.375000, -0.125000, 2.00000, -0.500000, \
    0.500000, 0, 0, -0.500000, 0, 0.500000, 0, 0, 0.125000, -0.500000, \
    0.250000, 0.125000, 0, 0.250000, -0.375000, 0, 0.250000, -0.125000, \
    0.500000, 1.75000, -0.125000, 0, 1.75000, 0.375000, 0, 1.75000, \
    -0.500000, 0.500000, 0, 0, -0.500000, 0, 0.500000, 0, 0, 0, \
    -0.250000, 1.25000, 0, 0.250000, 1.25000, -0.500000, 0.250000, \
    1.25000, 0, 0.250000, 0.750000, 0, -0.250000, 0.750000, 0.500000, \
    -0.250000, 0.750000, -0.500000, 0.500000, 0, 0, -0.500000, 0, \
    0.500000, 0, 0, 0.250000, -0.250000, 1.00000, 0.250000, 0.250000, \
    1.00000, -0.250000, 0.250000, 1.00000, -0.250000, 0.250000, 1.00000, \
    -0.250000, -0.250000, 1.00000, 0.250000, -0.250000, 1.00000, \
    -0.500000, 0.500000, 0, 0, -0.500000, 0, 0.500000, 0, 0
  };
  
  try{
    
    DynRankViewHost ConstructWithLabel(wedgeNodesHost, 12, 3);
    wedgeNodesHost(0,0) =  0.0;  wedgeNodesHost(0,1) =  0.0;  wedgeNodesHost(0,2) = -1.0;
    wedgeNodesHost(1,0) =  1.0;  wedgeNodesHost(1,1) =  0.0;  wedgeNodesHost(1,2) = -1.0;
    wedgeNodesHost(2,0) =  0.0;  wedgeNodesHost(2,1) =  1.0;  wedgeNodesHost(2,2) = -1.0;
    wedgeNodesHost(3,0) =  0.0;  wedgeNodesHost(3,1) =  0.0;  wedgeNodesHost(3,2) =  1.0;
    wedgeNodesHost(4,0) =  1.0;  wedgeNodesHost(4,1) =  0.0;  wedgeNodesHost(4,2) =  1.0;
    wedgeNodesHost(5,0) =  0.0;  wedgeNodesHost(5,1) =  1.0;  wedgeNodesHost(5,2) =  1.0;
  
    wedgeNodesHost(6,0) =  0.25; wedgeNodesHost(6,1) =  0.5;  wedgeNodesHost(6,2) = -1.0;
    wedgeNodesHost(7,0) =  0.5;  wedgeNodesHost(7,1) =  0.25; wedgeNodesHost(7,2) =  0.0;
    wedgeNodesHost(8,0) =  0.25; wedgeNodesHost(8,1) =  0.25; wedgeNodesHost(8,2) =  1.0;
    wedgeNodesHost(9,0) =  0.25; wedgeNodesHost(9,1) =  0.0;  wedgeNodesHost(9,2) =  0.75;
    wedgeNodesHost(10,0)=  0.0;  wedgeNodesHost(10,1)=  0.5;  wedgeNodesHost(10,2)= -0.25;
    wedgeNodesHost(11,0)=  0.5;  wedgeNodesHost(11,1)=  0.5;  wedgeNodesHost(11,2)=  0.0;

    const auto wedgeNodes = Kokkos::create_mirror_view(typename DeviceSpaceType::memory_space(), wedgeNodesHost);
    Kokkos::deep_copy(wedgeNodes, wedgeNodesHost);
        
    // Dimensions for the output arrays:
    const ordinal_type numFields = wedgeBasis.getCardinality();
    const ordinal_type numPoints = wedgeNodes.dimension(0);
    const ordinal_type spaceDim  = wedgeBasis.getBaseCellTopology().getDimension();
    
    {
    // Check VALUE of basis functions: resize vals to rank-3 container:
    DynRankView ConstructWithLabel(vals, numFields, numPoints, spaceDim);
    wedgeBasis.getValues(vals, wedgeNodes, OPERATOR_VALUE);
    auto vals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), vals);
    Kokkos::deep_copy(vals_host, vals);
    for (ordinal_type i = 0; i < numFields; ++i) {
      for (ordinal_type j = 0; j < numPoints; ++j) {
        for (ordinal_type k = 0; k < spaceDim; ++k) {
          
          // compute offset for (P,F,D) data layout: indices are P->j, F->i, D->k
           const ordinal_type l = k + i * spaceDim + j * spaceDim * numFields;
           if (std::abs(vals_host(i,j,k) - basisValues[l]) > 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_host(i,j,k)
               << " but reference value: " << basisValues[l] << "\n";
            }
         }
      }
    }
    }

    {
    // Check CURL of basis function: resize vals to rank-3 container
    DynRankView ConstructWithLabel(vals, numFields, numPoints, spaceDim);
    wedgeBasis.getValues(vals, wedgeNodes, OPERATOR_CURL);
    auto vals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), vals);
    Kokkos::deep_copy(vals_host, vals);
    for (ordinal_type i = 0; i < numFields; ++i) {
      for (ordinal_type j = 0; j < numPoints; ++j) {
        for (ordinal_type k = 0; k < spaceDim; ++k) {
          
          // compute offset for (P,F,D) data layout: indices are P->j, F->i, D->k
           const ordinal_type l = k + i * spaceDim + j * spaceDim * numFields;
           if (std::abs(vals_host(i,j,k) - basisCurls[l]) > 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_host(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;
}
Example #6
0
    int Orientation_Test05(const bool verbose) {

      Teuchos::RCP<std::ostream> outStream;
      Teuchos::oblackholestream bhs; // outputs nothing

      if (verbose)
        outStream = Teuchos::rcp(&std::cout, false);
      else
        outStream = Teuchos::rcp(&bhs,       false);

      Teuchos::oblackholestream oldFormatState;
      oldFormatState.copyfmt(std::cout);

      typedef typename
        Kokkos::Impl::is_space<DeviceSpaceType>::host_mirror_space::execution_space HostSpaceType ;

      *outStream << "DeviceSpace::  "; DeviceSpaceType::print_configuration(*outStream, false);
      *outStream << "HostSpace::    ";   HostSpaceType::print_configuration(*outStream, false);
      *outStream << "\n";

      
      *outStream
        << "===============================================================================\n"
        << "|                                                                             |\n"
        << "|                 Unit Test (OrientationTools, getModifiedHcurl_I1_Basis)     |\n"
        << "|                                                                             |\n"
        << "===============================================================================\n";

      int errorFlag = 0;
      const double tol = tolerence();

      typedef OrientationTools<DeviceSpaceType> ots;
      try {

        {
          *outStream << "\n -- Testing Quadrilateral \n\n";

          Basis_HCURL_QUAD_I1_FEM<DeviceSpaceType> cellBasis;
          const auto cellTopo = cellBasis.getBaseCellTopology();
          const ordinal_type ndofBasis = cellBasis.getCardinality();
          
          // 
          // 9 12 13 16
          // 4  3 11 15
          // 5  2  8 14
          // 1  6  7 10
          ordinal_type refMesh[9][4] = { { 1, 6, 2, 5 },
                                         { 6, 7, 8, 2 },
                                         { 7,10,14, 8 },
                                         { 5, 2, 3, 4 },
                                         { 2, 8,11, 3 },
                                         { 8,14,15,11 },
                                         { 4, 3,12, 9 },
                                         { 3,11,13,12 },
                                         {11,15,16,13 } };
          const ordinal_type numCells = 9, numVerts = 4, numEdges = 4;

          // view to import refMesh from host          
          Kokkos::DynRankView<ordinal_type,Kokkos::LayoutRight,HostSpaceType> 
            elemNodesHost(&refMesh[0][0], numCells, numVerts);
          auto elemNodes = Kokkos::create_mirror_view(typename DeviceSpaceType::memory_space(), elemNodesHost);
          Kokkos::deep_copy(elemNodes, elemNodesHost);
          
          // compute orientations for cells (one time computation)
          Kokkos::DynRankView<Orientation,DeviceSpaceType> elemOrts("elemOrts", numCells);
          ots::getOrientation(elemOrts, elemNodes, cellTopo);

          auto elemOrtsHost = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), elemOrts);
          Kokkos::deep_copy(elemOrtsHost, elemOrts);
          
          // cell specific modified basis 
          Kokkos::DynRankView<double,DeviceSpaceType> outValues("outValues", numCells, ndofBasis);
          Kokkos::DynRankView<double,DeviceSpaceType> refValues("refValues", numCells, ndofBasis);
          
          auto refValuesHost = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), refValues);
          for (auto cell=0;cell<numCells;++cell)           
            for (auto bf=0;bf<ndofBasis;++bf) 
              refValuesHost(cell, bf) = bf;
          Kokkos::deep_copy(refValues, refValuesHost);

          // modify refValues accounting for orientations
          ots::modifyBasisByOrientation(outValues,
                                        refValues,
                                        elemOrts,
                                        &cellBasis);

          auto outValuesHost = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), outValues);
          Kokkos::deep_copy(outValuesHost, outValues);

          for (auto cell=0;cell<numCells;++cell) {
            int flag = 0 ;
            std::stringstream s1, s2;
            
            ordinal_type orts[numEdges];
            elemOrtsHost(cell).getEdgeOrientation(orts, numEdges);
            
            const double ortVal[2] = { 1.0 , - 1.0 };

            s1 << " :: edge(0000) = " ;
            s2 << " :: edge(" << orts[0] << orts[1] << orts[2] << orts[3] << ") = ";
            for (auto edgeId=0;edgeId<numEdges;++edgeId) {
              const auto ndof = cellBasis.getDofTag(cellBasis.getDofOrdinal(1, edgeId, 0))(3);
              for (auto i=0;i<ndof;++i) {
                const auto refOrd = cellBasis.getDofOrdinal(1, edgeId, i);
                const auto outOrd = cellBasis.getDofOrdinal(1, edgeId, i);
                s1 << std::setw(4) << refValuesHost(cell, outOrd);              
                s2 << std::setw(4) << outValuesHost(cell, outOrd);              

                flag += (std::abs(ortVal[orts[edgeId]]*outValuesHost(cell, outOrd) - refValuesHost(cell, refOrd)) > tol);
              }

              s1 << " // ";
              s2 << " // ";
            }

            *outStream << "\n cell = " << cell << "\n"
                       << " - refValues = " << s1.str() << "\n"
                       << " - outValues = " << s2.str() << "\n";
            if (flag) {
              *outStream << "                      ^^^^^^^^^^^^ FAILURE\n";
              errorFlag += flag;
            }
          }
          ots::clearCoeffMatrix();
        }

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

      if (errorFlag != 0)
        std::cout << "End Result: TEST FAILED = " << errorFlag << "\n";
      else
        std::cout << "End Result: TEST PASSED\n";
      
      // reset format state of std::cout
      std::cout.copyfmt(oldFormatState);
      
      return errorFlag;
    }
Example #7
0
  int HGRAD_TET_C2_FEM_Test01(const bool verbose) {

    Teuchos::RCP<std::ostream> outStream;
    Teuchos::oblackholestream bhs; // outputs nothing

    if (verbose)
      outStream = Teuchos::rcp(&std::cout, false);
    else
      outStream = Teuchos::rcp(&bhs,       false);

    Teuchos::oblackholestream oldFormatState;
    oldFormatState.copyfmt(std::cout);

    typedef typename
      Kokkos::Impl::is_space<DeviceSpaceType>::host_mirror_space::execution_space HostSpaceType ;

    *outStream << "DeviceSpace::  "; DeviceSpaceType::print_configuration(*outStream, false);
    *outStream << "HostSpace::    ";   HostSpaceType::print_configuration(*outStream, false);
  
  *outStream
    << "\n"
    << "===============================================================================\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"
    << "|                      Kyungjoo Kim  ([email protected]).                     |\n"
    << "|                                                                             |\n"
    << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n"
    << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n"
    << "|                                                                             |\n"
    << "===============================================================================\n";

    typedef Kokkos::DynRankView<ValueType,DeviceSpaceType> DynRankView;
    typedef Kokkos::DynRankView<ValueType,HostSpaceType>   DynRankViewHost;
#define ConstructWithLabel(obj, ...) obj(#obj, __VA_ARGS__)

    const ValueType tol = tolerence();
    int errorFlag = 0;
      
    // for virtual function, value and point types are declared in the class
    typedef ValueType outputValueType;
    typedef ValueType pointValueType;
    Basis_HGRAD_TET_C2_FEM<DeviceSpaceType,outputValueType,pointValueType> tetBasis;

  *outStream
    << "\n"
    << "===============================================================================\n"
    << "| TEST 1: Basis creation, exception testing                                   |\n"
    << "===============================================================================\n";
  
  try{
    ordinal_type nthrow = 0, ncatch = 0;
#ifdef HAVE_INTREPID2_DEBUG 

    DynRankView ConstructWithLabel(tetNodes, 10, 3);

    const auto numFields = tetBasis.getCardinality();
    const auto numPoints = tetNodes.dimension(0);
    const auto spaceDim  = tetBasis.getBaseCellTopology().getDimension();

    DynRankView ConstructWithLabel(vals, numFields, numPoints);
    DynRankView ConstructWithLabel(vals_vec, numFields, numPoints, 4);
    {
    // exception #1: CURL cannot be applied to scalar functions
    // resize vals to rank-3 container with dimensions (num. points, num. basis functions, arbitrary)
      INTREPID2_TEST_ERROR_EXPECTED( tetBasis.getValues(vals_vec, tetNodes, OPERATOR_CURL) );
    }
    {
    // exception #2: DIV cannot be applied to scalar functions
    // resize vals to rank-2 container with dimensions (num. points, num. basis functions)
      INTREPID2_TEST_ERROR_EXPECTED( tetBasis.getValues(vals, tetNodes, OPERATOR_DIV) );
    }
        
    // 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
      INTREPID2_TEST_ERROR_EXPECTED( tetBasis.getDofOrdinal(3,0,0) );
    // exception #4
      INTREPID2_TEST_ERROR_EXPECTED( tetBasis.getDofOrdinal(1,1,1) );
    // exception #5
      INTREPID2_TEST_ERROR_EXPECTED( tetBasis.getDofOrdinal(0,4,0) );
    // exception #6
      INTREPID2_TEST_ERROR_EXPECTED( tetBasis.getDofTag(10) );
    // exception #7
      INTREPID2_TEST_ERROR_EXPECTED( tetBasis.getDofTag(-1) );
    }
    
    // Exceptions 8-18 test exception handling with incorrectly dimensioned input/output arrays
    {
    // exception #8: input points array must be of rank-2
      DynRankView ConstructWithLabel(badPoints1, 4, 5, 3);
      INTREPID2_TEST_ERROR_EXPECTED( tetBasis.getValues(vals, badPoints1, OPERATOR_VALUE) );
    }
    { 
    // exception #9 dimension 1 in the input point array must equal space dimension of the cell
      DynRankView ConstructWithLabel(badPoints2, 4, spaceDim - 1);
      INTREPID2_TEST_ERROR_EXPECTED( tetBasis.getValues(vals, badPoints2, OPERATOR_VALUE) );
    }
    { 
    // exception #10 output values must be of rank-2 for OPERATOR_VALUE
      DynRankView ConstructWithLabel(badVals1, 4, 3, 1);
      INTREPID2_TEST_ERROR_EXPECTED( tetBasis.getValues(badVals1, tetNodes, OPERATOR_VALUE) );
    }
    { 
    // exception #11 output values must be of rank-3 for OPERATOR_GRAD
      DynRankView ConstructWithLabel(badVals2, 4, 3);
      INTREPID2_TEST_ERROR_EXPECTED( tetBasis.getValues(badVals2, tetNodes, OPERATOR_GRAD) );
    // exception #12 output values must be of rank-3 for OPERATOR_D1
      INTREPID2_TEST_ERROR_EXPECTED( tetBasis.getValues(badVals2, tetNodes, OPERATOR_D1) );
    // exception #13 output values must be of rank-3 for OPERATOR_D2
      INTREPID2_TEST_ERROR_EXPECTED( tetBasis.getValues(badVals2, tetNodes, OPERATOR_D2) );
    }
    {
    // exception #14 incorrect 0th dimension of output array (must equal number of basis functions)
      DynRankView ConstructWithLabel(badVals3, numFields + 1, numPoints);
      INTREPID2_TEST_ERROR_EXPECTED( tetBasis.getValues(badVals3, tetNodes, OPERATOR_VALUE) );
    }
    { 
    // exception #15 incorrect 1st dimension of output array (must equal number of points)
      DynRankView ConstructWithLabel(badVals4, numFields, numPoints + 1);
      INTREPID2_TEST_ERROR_EXPECTED( tetBasis.getValues(badVals4, tetNodes, OPERATOR_VALUE) );
    }
    { 
    // exception #16: incorrect 2nd dimension of output array (must equal the space dimension)
      DynRankView ConstructWithLabel(badVals5, numFields, numPoints, spaceDim + 1);
      INTREPID2_TEST_ERROR_EXPECTED( tetBasis.getValues(badVals5, tetNodes, OPERATOR_GRAD) );
    }
    { 
    // exception #17: incorrect 2nd dimension of output array (must equal D2 cardinality in 2D)
      DynRankView ConstructWithLabel(badVals6, numFields, numPoints, 40);
      INTREPID2_TEST_ERROR_EXPECTED( tetBasis.getValues(badVals6, tetNodes, OPERATOR_D1) );
    // exception #18: incorrect 2nd dimension of output array (must equal D3 cardinality in 2D)
      INTREPID2_TEST_ERROR_EXPECTED( tetBasis.getValues(badVals6, tetNodes, OPERATOR_D2) );
    }
#endif
    // Check if number of thrown exceptions matches the one we expect 
    if (nthrow != ncatch) {
      errorFlag++;
      *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
      *outStream << "# of catch ("<< ncatch << ") is different from # of throw (" << nthrow << ")\n";
    }
  } catch (std::logic_error err) {
    *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
    *outStream << err.what() << '\n';
    *outStream << "-------------------------------------------------------------------------------" << "\n\n";
    errorFlag = -1000;
  };
  
  *outStream
    << "\n"
    << "===============================================================================\n"
    << "| TEST 2: correctness of tag to enum and enum to tag lookups                  |\n"
    << "===============================================================================\n";
  
  try{
    const auto numFields = tetBasis.getCardinality();
    const auto allTags = tetBasis.getAllDofTags();
    
    // Loop over all tags, lookup the associated dof enumeration and then lookup the tag again
    const auto dofTagSize = allTags.dimension(0);
    for (auto i = 0; i < dofTagSize; ++i) {
      const auto bfOrd  = tetBasis.getDofOrdinal(allTags(i,0), allTags(i,1), allTags(i,2));
      
      const auto 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( auto bfOrd = 0; bfOrd < numFields; bfOrd++) {
      const auto myTag  = tetBasis.getDofTag(bfOrd);
      const auto 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
  const ValueType 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
  const ValueType 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
  const ValueType 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{
    ordinal_type nthrow = 0, ncatch = 0;

    DynRankViewHost ConstructWithLabel(tetNodesHost, 10, 3);
    tetNodesHost(0,0) =  0.0;  tetNodesHost(0,1) =  0.0;  tetNodesHost(0,2) =  0.0;  
    tetNodesHost(1,0) =  1.0;  tetNodesHost(1,1) =  0.0;  tetNodesHost(1,2) =  0.0;  
    tetNodesHost(2,0) =  0.0;  tetNodesHost(2,1) =  1.0;  tetNodesHost(2,2) =  0.0;
    tetNodesHost(3,0) =  0.0;  tetNodesHost(3,1) =  0.0;  tetNodesHost(3,2) =  1.0;  
    
    tetNodesHost(4,0) =  0.5;  tetNodesHost(4,1) =  0.0;  tetNodesHost(4,2) =  0.0;
    tetNodesHost(5,0) =  0.5;  tetNodesHost(5,1) =  0.5;  tetNodesHost(5,2) =  0.0;  
    tetNodesHost(6,0) =  0.0;  tetNodesHost(6,1) =  0.5;  tetNodesHost(6,2) =  0.0;  
    tetNodesHost(7,0) =  0.0;  tetNodesHost(7,1) =  0.0;  tetNodesHost(7,2) =  0.5;  
    tetNodesHost(8,0) =  0.5;  tetNodesHost(8,1) =  0.0;  tetNodesHost(8,2) =  0.5;  
    tetNodesHost(9,0) =  0.0;  tetNodesHost(9,1) =  0.5;  tetNodesHost(9,2) =  0.5;  

    auto tetNodes = Kokkos::create_mirror_view(typename DeviceSpaceType::memory_space(), tetNodesHost);
    Kokkos::deep_copy(tetNodes, tetNodesHost);
        
    // Dimensions for the output arrays:
    const auto numFields = tetBasis.getCardinality();
    const auto numPoints = tetNodes.dimension(0);
    const auto spaceDim  = tetBasis.getBaseCellTopology().getDimension();
    const auto D2cardinality = getDkCardinality(OPERATOR_D2, spaceDim);
    
    {
    // Check VALUE of basis functions: resize vals to rank-2 container:
    DynRankView ConstructWithLabel(vals, numFields, numPoints);
    tetBasis.getValues(vals, tetNodes, OPERATOR_VALUE);
    auto vals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), vals);
    Kokkos::deep_copy(vals_host, vals);
    for (auto i = 0; i < numFields; ++i) {
      for (auto j = 0; j < numPoints; ++j) {
          const auto l =  i + j * numFields;
           if (std::abs(vals_host(i,j) - basisValues[l]) > 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_host(i,j)
               << " but reference value: " << basisValues[l] << "\n";
         }
      }
    }
    }

    {
    // Check GRAD of basis function: resize vals to rank-3 container
    DynRankView ConstructWithLabel(vals, numFields, numPoints, spaceDim);
    tetBasis.getValues(vals, tetNodes, OPERATOR_GRAD);
    auto vals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), vals);
    Kokkos::deep_copy(vals_host, vals);
    for (auto i = 0; i < numFields; ++i) {
      for (auto j = 0; j < numPoints; ++j) {
        for (auto k = 0; k < spaceDim; ++k) {
 
          // basisGrads is (F,P,D), compute offset:
          const auto l = k + j * spaceDim + i * spaceDim * numPoints;
           if (std::abs(vals_host(i,j,k) - basisGrads[l]) > 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_host(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);
    Kokkos::deep_copy(vals_host, vals);
    for (auto i = 0; i < numFields; ++i) {
      for (auto j = 0; j < numPoints; ++j) {
        for (auto k = 0; k < spaceDim; ++k) {
          
          // basisGrads is (F,P,D), compute offset:
          const auto l = k + j * spaceDim + i * spaceDim * numPoints;
           if (std::abs(vals_host(i,j,k) - basisGrads[l]) > 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_host(i,j,k)
               << " but reference D1 component: " << basisGrads[l] << "\n";
            }
         }
      }
    }
    }

    {
    // Check D2 of basis function
    DynRankView ConstructWithLabel(vals, numFields, numPoints, D2cardinality);
    tetBasis.getValues(vals, tetNodes, OPERATOR_D2);
    auto vals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), vals);
    Kokkos::deep_copy(vals_host, vals);
    for (auto i = 0; i < numFields; ++i) {
      for (auto j = 0; j < numPoints; ++j) {
        for (auto k = 0; k < D2cardinality; ++k) {
          
          // basisD2 is (F,P,Dk), compute offset:
          const auto l = k + j * D2cardinality + i * D2cardinality * numPoints;
          if (std::abs(vals_host(i,j,k) - basisD2[l]) > 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_host(i,j,k)
              << " but reference D2 component: " << basisD2[l] << "\n";
          }
        }
      }
    }
    }
    
    {
    // Check all higher derivatives - must be zero. 

      const EOperator ops[] = { OPERATOR_D3,
                                OPERATOR_D4,
                                OPERATOR_D5,
                                OPERATOR_D6,
                                OPERATOR_D7,
                                OPERATOR_D8,
                                OPERATOR_D9,
                                OPERATOR_D10,
                                OPERATOR_MAX };
      for (auto h=0;ops[h]!=OPERATOR_MAX;++h) {
        const auto op = ops[h];
      // The last dimension is the number of kth derivatives and needs to be resized for every Dk
        const auto DkCardin  = getDkCardinality(op, spaceDim);
        DynRankView vals("vals", numFields, numPoints, DkCardin);

        tetBasis.getValues(vals, tetNodes, op);
        auto vals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), vals);
        Kokkos::deep_copy(vals_host, vals);

        for (auto i1 = 0; i1 < numFields; ++i1) 
          for (auto i2 = 0; i2 < numPoints; ++i2) 
            for (auto i3 = 0; i3 < DkCardin; ++i3) {
              if (std::abs(vals_host(i1,i2,i3)) > 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_host(i1,i2,i3) 
                           << " but reference D" << ord << " component:  0 \n";
              }
            }
      }    
    }    
  } 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;
}
Example #8
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_Cn_FEM)                       |\n" \
    << "|                                                                             |\n" \
    << "|     1) Patch test involving mass and stiffness matrices,                    |\n" \
    << "|        for the Neumann problem on a tetrahedral patch                       |\n" \
    << "|        Omega with boundary Gamma.                                           |\n" \
    << "|                                                                             |\n" \
    << "|        - div (grad u) + u = f  in Omega,  (grad u) . n = g  on Gamma        |\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: Patch test                                                          |\n"\
    << "===============================================================================\n";

  
  int errorFlag = 0;

  outStream -> precision(16);


  try {

    int max_order = 5;                                                                  // max total order of polynomial solution
    DefaultCubatureFactory<double>  cubFactory;                                         // create factory
    shards::CellTopology cell(shards::getCellTopologyData< shards::Tetrahedron<> >());  // create parent cell topology
    shards::CellTopology side(shards::getCellTopologyData< shards::Triangle<> >());     // create relevant subcell (side) topology
    int cellDim = cell.getDimension();
    int sideDim = side.getDimension();

    // Define array containing points at which the solution is evaluated, on the reference tet.
    int numIntervals = 10;
    int numInterpPoints = ((numIntervals + 1)*(numIntervals + 2)*(numIntervals + 3))/6;
    FieldContainer<double> interp_points_ref(numInterpPoints, 3);
    int counter = 0;
    for (int k=0; k<=numIntervals; k++) {
      for (int j=0; j<=numIntervals; j++) {
        for (int i=0; i<=numIntervals; i++) {
          if (i+j+k <= numIntervals) {
            interp_points_ref(counter,0) = i*(1.0/numIntervals);
            interp_points_ref(counter,1) = j*(1.0/numIntervals);
            interp_points_ref(counter,2) = k*(1.0/numIntervals);
            counter++;
          }
        }
      }
    }

    /* Definition of parent cell. */
    FieldContainer<double> cell_nodes(1, 4, cellDim);
    // funky tet
    cell_nodes(0, 0, 0) = -1.0;
    cell_nodes(0, 0, 1) = -2.0;
    cell_nodes(0, 0, 2) = 0.0;
    cell_nodes(0, 1, 0) = 6.0;
    cell_nodes(0, 1, 1) = 2.0;
    cell_nodes(0, 1, 2) = 0.0;
    cell_nodes(0, 2, 0) = -5.0;
    cell_nodes(0, 2, 1) = 1.0;
    cell_nodes(0, 2, 2) = 0.0;
    cell_nodes(0, 3, 0) = -4.0;
    cell_nodes(0, 3, 1) = -1.0;
    cell_nodes(0, 3, 2) = 3.0;
    // perturbed reference tet
    /*cell_nodes(0, 0, 0) = 0.1;
    cell_nodes(0, 0, 1) = -0.1;
    cell_nodes(0, 0, 2) = 0.2;
    cell_nodes(0, 1, 0) = 1.2;
    cell_nodes(0, 1, 1) = -0.1;
    cell_nodes(0, 1, 2) = 0.05;
    cell_nodes(0, 2, 0) = 0.0;
    cell_nodes(0, 2, 1) = 0.9;
    cell_nodes(0, 2, 2) = 0.1;
    cell_nodes(0, 3, 0) = 0.1;
    cell_nodes(0, 3, 1) = -0.1;
    cell_nodes(0, 3, 2) = 1.1;*/
    // reference tet
    /*cell_nodes(0, 0, 0) = 0.0;
    cell_nodes(0, 0, 1) = 0.0;
    cell_nodes(0, 0, 2) = 0.0;
    cell_nodes(0, 1, 0) = 1.0;
    cell_nodes(0, 1, 1) = 0.0;
    cell_nodes(0, 1, 2) = 0.0;
    cell_nodes(0, 2, 0) = 0.0;
    cell_nodes(0, 2, 1) = 1.0;
    cell_nodes(0, 2, 2) = 0.0;
    cell_nodes(0, 3, 0) = 0.0;
    cell_nodes(0, 3, 1) = 0.0;
    cell_nodes(0, 3, 2) = 1.0;*/

    FieldContainer<double> interp_points(1, numInterpPoints, cellDim);
    CellTools<double>::mapToPhysicalFrame(interp_points, interp_points_ref, cell_nodes, cell);
    interp_points.resize(numInterpPoints, cellDim);

    // we test two types of bases
    EPointType pointtype[] = {POINTTYPE_EQUISPACED, POINTTYPE_WARPBLEND};
    for (int ptype=0; ptype < 2; ptype++) {

      *outStream << "\nTesting bases with " << EPointTypeToString(pointtype[ptype]) << ":\n";

      for (int x_order=0; x_order <= max_order; x_order++) {
        for (int y_order=0; y_order <= max_order-x_order; y_order++) {
          for (int z_order=0; z_order <= max_order-x_order-y_order; z_order++) {

            // evaluate exact solution
            FieldContainer<double> exact_solution(1, numInterpPoints);
            u_exact(exact_solution, interp_points, x_order, y_order, z_order);

            int total_order = std::max(x_order + y_order + z_order, 1);

            for (int basis_order=total_order; basis_order <= max_order; basis_order++) {

              // set test tolerance;
              double zero = basis_order*basis_order*basis_order*100*INTREPID_TOL;

              //create basis
              Teuchos::RCP<Basis<double,FieldContainer<double> > > basis =
                Teuchos::rcp(new Basis_HGRAD_TET_Cn_FEM<double,FieldContainer<double> >(basis_order, pointtype[ptype]) );
              int numFields = basis->getCardinality();

              // create cubatures
              Teuchos::RCP<Cubature<double> > cellCub = cubFactory.create(cell, 2*basis_order);
              Teuchos::RCP<Cubature<double> > sideCub = cubFactory.create(side, 2*basis_order);
              int numCubPointsCell = cellCub->getNumPoints();
              int numCubPointsSide = sideCub->getNumPoints();

              /* Computational arrays. */
              /* Section 1: Related to parent cell integration. */
              FieldContainer<double> cub_points_cell(numCubPointsCell, cellDim);
              FieldContainer<double> cub_points_cell_physical(1, numCubPointsCell, cellDim);
              FieldContainer<double> cub_weights_cell(numCubPointsCell);
              FieldContainer<double> jacobian_cell(1, numCubPointsCell, cellDim, cellDim);
              FieldContainer<double> jacobian_inv_cell(1, numCubPointsCell, cellDim, cellDim);
              FieldContainer<double> jacobian_det_cell(1, numCubPointsCell);
              FieldContainer<double> weighted_measure_cell(1, numCubPointsCell);

              FieldContainer<double> value_of_basis_at_cub_points_cell(numFields, numCubPointsCell);
              FieldContainer<double> transformed_value_of_basis_at_cub_points_cell(1, numFields, numCubPointsCell);
              FieldContainer<double> weighted_transformed_value_of_basis_at_cub_points_cell(1, numFields, numCubPointsCell);
              FieldContainer<double> grad_of_basis_at_cub_points_cell(numFields, numCubPointsCell, cellDim);
              FieldContainer<double> transformed_grad_of_basis_at_cub_points_cell(1, numFields, numCubPointsCell, cellDim);
              FieldContainer<double> weighted_transformed_grad_of_basis_at_cub_points_cell(1, numFields, numCubPointsCell, cellDim);
              FieldContainer<double> fe_matrix(1, numFields, numFields);

              FieldContainer<double> rhs_at_cub_points_cell_physical(1, numCubPointsCell);
              FieldContainer<double> rhs_and_soln_vector(1, numFields);

              /* Section 2: Related to subcell (side) integration. */
              unsigned numSides = 4;
              FieldContainer<double> cub_points_side(numCubPointsSide, sideDim);
              FieldContainer<double> cub_weights_side(numCubPointsSide);
              FieldContainer<double> cub_points_side_refcell(numCubPointsSide, cellDim);
              FieldContainer<double> cub_points_side_physical(1, numCubPointsSide, cellDim);
              FieldContainer<double> jacobian_side_refcell(1, numCubPointsSide, cellDim, cellDim);
              FieldContainer<double> jacobian_det_side_refcell(1, numCubPointsSide);
              FieldContainer<double> weighted_measure_side_refcell(1, numCubPointsSide);

              FieldContainer<double> value_of_basis_at_cub_points_side_refcell(numFields, numCubPointsSide);
              FieldContainer<double> transformed_value_of_basis_at_cub_points_side_refcell(1, numFields, numCubPointsSide);
              FieldContainer<double> weighted_transformed_value_of_basis_at_cub_points_side_refcell(1, numFields, numCubPointsSide);
              FieldContainer<double> neumann_data_at_cub_points_side_physical(1, numCubPointsSide);
              FieldContainer<double> neumann_fields_per_side(1, numFields);

              /* Section 3: Related to global interpolant. */
              FieldContainer<double> value_of_basis_at_interp_points_ref(numFields, numInterpPoints);
              FieldContainer<double> transformed_value_of_basis_at_interp_points_ref(1, numFields, numInterpPoints);
              FieldContainer<double> interpolant(1, numInterpPoints);

              FieldContainer<int> ipiv(numFields);



              /******************* START COMPUTATION ***********************/

              // get cubature points and weights
              cellCub->getCubature(cub_points_cell, cub_weights_cell);

              // compute geometric cell information
              CellTools<double>::setJacobian(jacobian_cell, cub_points_cell, cell_nodes, cell);
              CellTools<double>::setJacobianInv(jacobian_inv_cell, jacobian_cell);
              CellTools<double>::setJacobianDet(jacobian_det_cell, jacobian_cell);

              // compute weighted measure
              FunctionSpaceTools::computeCellMeasure<double>(weighted_measure_cell, jacobian_det_cell, cub_weights_cell);

              ///////////////////////////
              // Computing mass matrices:
              // tabulate values of basis functions at (reference) cubature points
              basis->getValues(value_of_basis_at_cub_points_cell, cub_points_cell, OPERATOR_VALUE);

              // transform values of basis functions 
              FunctionSpaceTools::HGRADtransformVALUE<double>(transformed_value_of_basis_at_cub_points_cell,
                                                              value_of_basis_at_cub_points_cell);

              // multiply with weighted measure
              FunctionSpaceTools::multiplyMeasure<double>(weighted_transformed_value_of_basis_at_cub_points_cell,
                                                          weighted_measure_cell,
                                                          transformed_value_of_basis_at_cub_points_cell);

              // compute mass matrices
              FunctionSpaceTools::integrate<double>(fe_matrix,
                                                    transformed_value_of_basis_at_cub_points_cell,
                                                    weighted_transformed_value_of_basis_at_cub_points_cell,
                                                    COMP_BLAS);
              ///////////////////////////

              ////////////////////////////////
              // Computing stiffness matrices:
              // tabulate gradients of basis functions at (reference) cubature points
              basis->getValues(grad_of_basis_at_cub_points_cell, cub_points_cell, OPERATOR_GRAD);

              // transform gradients of basis functions 
              FunctionSpaceTools::HGRADtransformGRAD<double>(transformed_grad_of_basis_at_cub_points_cell,
                                                             jacobian_inv_cell,
                                                             grad_of_basis_at_cub_points_cell);

              // multiply with weighted measure
              FunctionSpaceTools::multiplyMeasure<double>(weighted_transformed_grad_of_basis_at_cub_points_cell,
                                                          weighted_measure_cell,
                                                          transformed_grad_of_basis_at_cub_points_cell);

              // compute stiffness matrices and sum into fe_matrix
              FunctionSpaceTools::integrate<double>(fe_matrix,
                                                    transformed_grad_of_basis_at_cub_points_cell,
                                                    weighted_transformed_grad_of_basis_at_cub_points_cell,
                                                    COMP_BLAS,
                                                    true);
              ////////////////////////////////

              ///////////////////////////////
              // Computing RHS contributions:
              // map cell (reference) cubature points to physical space
              CellTools<double>::mapToPhysicalFrame(cub_points_cell_physical, cub_points_cell, cell_nodes, cell);

              // evaluate rhs function
              rhsFunc(rhs_at_cub_points_cell_physical, cub_points_cell_physical, x_order, y_order, z_order);

              // compute rhs
              FunctionSpaceTools::integrate<double>(rhs_and_soln_vector,
                                                    rhs_at_cub_points_cell_physical,
                                                    weighted_transformed_value_of_basis_at_cub_points_cell,
                                                    COMP_BLAS);

              // compute neumann b.c. contributions and adjust rhs
              sideCub->getCubature(cub_points_side, cub_weights_side);
              for (unsigned i=0; i<numSides; i++) {
                // compute geometric cell information
                CellTools<double>::mapToReferenceSubcell(cub_points_side_refcell, cub_points_side, sideDim, (int)i, cell);
                CellTools<double>::setJacobian(jacobian_side_refcell, cub_points_side_refcell, cell_nodes, cell);
                CellTools<double>::setJacobianDet(jacobian_det_side_refcell, jacobian_side_refcell);

                // compute weighted face measure
                FunctionSpaceTools::computeFaceMeasure<double>(weighted_measure_side_refcell,
                                                               jacobian_side_refcell,
                                                               cub_weights_side,
                                                               i,
                                                               cell);

                // tabulate values of basis functions at side cubature points, in the reference parent cell domain
                basis->getValues(value_of_basis_at_cub_points_side_refcell, cub_points_side_refcell, OPERATOR_VALUE);
                // transform 
                FunctionSpaceTools::HGRADtransformVALUE<double>(transformed_value_of_basis_at_cub_points_side_refcell,
                                                                value_of_basis_at_cub_points_side_refcell);

                // multiply with weighted measure
                FunctionSpaceTools::multiplyMeasure<double>(weighted_transformed_value_of_basis_at_cub_points_side_refcell,
                                                            weighted_measure_side_refcell,
                                                            transformed_value_of_basis_at_cub_points_side_refcell);

                // compute Neumann data
                // map side cubature points in reference parent cell domain to physical space
                CellTools<double>::mapToPhysicalFrame(cub_points_side_physical, cub_points_side_refcell, cell_nodes, cell);
                // now compute data
                neumann(neumann_data_at_cub_points_side_physical, cub_points_side_physical, jacobian_side_refcell,
                        cell, (int)i, x_order, y_order, z_order);

                FunctionSpaceTools::integrate<double>(neumann_fields_per_side,
                                                      neumann_data_at_cub_points_side_physical,
                                                      weighted_transformed_value_of_basis_at_cub_points_side_refcell,
                                                      COMP_BLAS);

                // adjust RHS
                RealSpaceTools<double>::add(rhs_and_soln_vector, neumann_fields_per_side);;
              }
              ///////////////////////////////

              /////////////////////////////
              // Solution of linear system:
              int info = 0;
              Teuchos::LAPACK<int, double> solver;
              solver.GESV(numFields, 1, &fe_matrix[0], numFields, &ipiv(0), &rhs_and_soln_vector[0], numFields, &info);
              /////////////////////////////

              ////////////////////////
              // Building interpolant:
              // evaluate basis at interpolation points
              basis->getValues(value_of_basis_at_interp_points_ref, interp_points_ref, OPERATOR_VALUE);
              // transform values of basis functions 
              FunctionSpaceTools::HGRADtransformVALUE<double>(transformed_value_of_basis_at_interp_points_ref,
                                                              value_of_basis_at_interp_points_ref);
              FunctionSpaceTools::evaluate<double>(interpolant, rhs_and_soln_vector, transformed_value_of_basis_at_interp_points_ref);
              ////////////////////////

              /******************* END COMPUTATION ***********************/
          
              RealSpaceTools<double>::subtract(interpolant, exact_solution);

              *outStream << "\nRelative norm-2 error between exact solution polynomial of order ("
                         << x_order << ", " << y_order << ", " << z_order
                         << ") and finite element interpolant of order " << basis_order << ": "
                         << RealSpaceTools<double>::vectorNorm(&interpolant[0], interpolant.dimension(1), NORM_TWO) /
                            RealSpaceTools<double>::vectorNorm(&exact_solution[0], exact_solution.dimension(1), NORM_TWO) << "\n";

              if (RealSpaceTools<double>::vectorNorm(&interpolant[0], interpolant.dimension(1), NORM_TWO) /
                  RealSpaceTools<double>::vectorNorm(&exact_solution[0], exact_solution.dimension(1), NORM_TWO) > zero) {
                *outStream << "\n\nPatch test failed for solution polynomial order ("
                           << x_order << ", " << y_order << ", " << z_order << ") and basis order " << basis_order << "\n\n";
                errorFlag++;
              }
            } // end for basis_order
          } // end for z_order
        } // end for y_order
      } // end for x_order
    } // end for ptype

  }
  // 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;
}
Example #9
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;
}
Example #10
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;
}
Example #11
0
int main(int argc, char *argv[]) {
 
  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
Kokkos::initialize();
  typedef CellTools<double>       CellTools;
  typedef shards::CellTopology    CellTopology;
  
  // 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 CellTools                            |\n" \
    << "|                                                                             |\n" \
    << "|     1) Edge parametrizations                                                |\n" \
    << "|     2) Face parametrizations                                                |\n" \
    << "|     3) Edge tangents                                                        |\n" \
    << "|     4) Face tangents and normals                                            |\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";
  
  int errorFlag  = 0;

    
  // Vertices of the parametrization domain for 1-subcells: standard 1-cube [-1,1]
  FieldContainer<double> cube_1(2, 1);
  cube_1(0,0) = -1.0; 
  cube_1(1,0) = 1.0;

  
  // Vertices of the parametrization domain for triangular faces: the standard 2-simplex
  FieldContainer<double> simplex_2(3, 2);
  simplex_2(0, 0) = 0.0;   simplex_2(0, 1) = 0.0;
  simplex_2(1, 0) = 1.0;   simplex_2(1, 1) = 0.0;
  simplex_2(2, 0) = 0.0;   simplex_2(2, 1) = 1.0;
  
  
  // Vertices of the parametrization domain for quadrilateral faces: the standard 2-cube
  FieldContainer<double> cube_2(4, 2);
  cube_2(0, 0) =  -1.0;    cube_2(0, 1) =  -1.0;
  cube_2(1, 0) =   1.0;    cube_2(1, 1) =  -1.0;
  cube_2(2, 0) =   1.0;    cube_2(2, 1) =   1.0;
  cube_2(3, 0) =  -1.0;    cube_2(3, 1) =   1.0;

  
  // Pull all available topologies from Shards
  std::vector<shards::CellTopology> allTopologies;
  shards::getTopologies(allTopologies);
  
  
  // Set to 1 for edge and 2 for face tests
  int subcDim;

  try{
    
    *outStream \
    << "\n"
    << "===============================================================================\n"\
    << "| Test 1: edge parametrizations:                                              |\n"\
    << "===============================================================================\n\n";
    
    subcDim      = 1;
        
    // Loop over the cell topologies
    for(int topoOrd = 0; topoOrd < (int)allTopologies.size(); topoOrd++){
            
      // Test only 2D and 3D topologies that have reference cells, e.g., exclude Line, Pentagon, etc.
      if(allTopologies[topoOrd].getDimension() > 1 && CellTools::hasReferenceCell(allTopologies[topoOrd]) ){
        *outStream << " Testing edge parametrization for " <<  allTopologies[topoOrd].getName() <<"\n";
        testSubcellParametrizations(errorFlag,
                                    allTopologies[topoOrd],
                                    cube_1,
                                    cube_1,
                                    subcDim,
                                    outStream);
      }
    }

    
    *outStream \
      << "\n"
      << "===============================================================================\n"\
      << "| Test 2: face parametrizations:                                              |\n"\
      << "===============================================================================\n\n";
    
    subcDim      = 2;
    
    // Loop over the cell topologies
    for(int topoOrd = 0; topoOrd < (int)allTopologies.size(); topoOrd++){
      
      // Test only 3D topologies that have reference cells
      if(allTopologies[topoOrd].getDimension() > 2 && CellTools::hasReferenceCell(allTopologies[topoOrd]) ){
        *outStream << " Testing face parametrization for cell topology " <<  allTopologies[topoOrd].getName() <<"\n";
        testSubcellParametrizations(errorFlag,
                                    allTopologies[topoOrd],
                                    simplex_2,
                                    cube_2,
                                    subcDim,
                                    outStream);
      }
    }
    
    
    /***********************************************************************************************
      *
      * Common for test 3 and 4: edge tangents and face normals for standard cells with base topo
      *
      **********************************************************************************************/
    
    // Allocate storage and extract all standard cells with base topologies
    std::vector<shards::CellTopology> standardBaseTopologies;    
    shards::getTopologies(standardBaseTopologies, 4, shards::STANDARD_CELL, shards::BASE_TOPOLOGY);

    // Define topologies for the edge and face parametrization domains. (faces are Tri or Quad)
    CellTopology paramEdge    (shards::getCellTopologyData<shards::Line<2> >() );
    CellTopology paramTriFace (shards::getCellTopologyData<shards::Triangle<3> >() );
    CellTopology paramQuadFace(shards::getCellTopologyData<shards::Quadrilateral<4> >() );
    
    // Define CubatureFactory:
    DefaultCubatureFactory<double>  cubFactory;   
    
    *outStream \
      << "\n"
      << "===============================================================================\n"\
      << "| Test 3: edge tangents/normals for stand. cells with base topologies:        |\n"\
      << "===============================================================================\n\n";
    // This test loops over standard cells with base topologies, creates a set of nodes and tests tangents/normals 
    std::vector<shards::CellTopology>::iterator cti;
    
    // Define cubature on the edge parametrization domain:
    Teuchos::RCP<Cubature<double> > edgeCubature = cubFactory.create(paramEdge, 6); 
    int cubDim       = edgeCubature -> getDimension();
    int numCubPoints = edgeCubature -> getNumPoints();

    // Allocate storage for cubature points and weights on edge parameter domain and fill with points:
    FieldContainer<double> paramEdgePoints(numCubPoints, cubDim);
    FieldContainer<double> paramEdgeWeights(numCubPoints);
    edgeCubature -> getCubature(paramEdgePoints, paramEdgeWeights);
    

    // Loop over admissible topologies 
    for(cti = standardBaseTopologies.begin(); cti !=standardBaseTopologies.end(); ++cti){
      
      // Exclude 0D (node), 1D (Line) and Pyramid<5> cells
      if( ( (*cti).getDimension() >= 2) && ( (*cti).getKey() != shards::Pyramid<5>::key) ){ 
        
        int cellDim = (*cti).getDimension();
        int vCount  = (*cti).getVertexCount();
        FieldContainer<double> refCellVertices(vCount, cellDim);
        CellTools::getReferenceSubcellVertices(refCellVertices, cellDim, 0, (*cti) );
        
        *outStream << " Testing edge tangents";
          if(cellDim == 2) { *outStream << " and normals"; }          
        *outStream <<" for cell topology " <<  (*cti).getName() <<"\n";
        
        
        // Array for physical cell vertices ( must have rank 3 for setJacobians)
        FieldContainer<double> physCellVertices(1, vCount, cellDim);

        // Randomize reference cell vertices by moving them up to +/- (1/8) units along their
        // coordinate axis. Guaranteed to be non-degenerate for standard cells with base topology 
        for(int v = 0; v < vCount; v++){
          for(int d = 0; d < cellDim; d++){
            double delta = Teuchos::ScalarTraits<double>::random()/8.0;
            physCellVertices(0, v, d) = refCellVertices(v, d) + delta;
          } //for d
        }// for v     
        
        // Allocate storage for cub. points on a ref. edge; Jacobians, phys. edge tangents/normals
        FieldContainer<double> refEdgePoints(numCubPoints, cellDim);        
        FieldContainer<double> edgePointsJacobians(1, numCubPoints, cellDim, cellDim);
        FieldContainer<double> edgePointTangents(1, numCubPoints, cellDim);
        FieldContainer<double> edgePointNormals(1, numCubPoints, cellDim);        

        // Loop over edges:
        for(int edgeOrd = 0; edgeOrd < (int)(*cti).getEdgeCount(); edgeOrd++){
          /* 
           * Compute tangents on the specified physical edge using CellTools:
           *    1. Map points from edge parametrization domain to ref. edge with specified ordinal
           *    2. Compute parent cell Jacobians at ref. edge points
           *    3. Compute physical edge tangents
           */
          CellTools::mapToReferenceSubcell(refEdgePoints, paramEdgePoints, 1, edgeOrd, (*cti) );
          CellTools::setJacobian(edgePointsJacobians, refEdgePoints, physCellVertices, (*cti) );
          CellTools::getPhysicalEdgeTangents(edgePointTangents, edgePointsJacobians, edgeOrd, (*cti)); 
          /*
           * Compute tangents directly using parametrization of phys. edge and compare with CellTools tangents.
           *    1. Get edge vertices
           *    2. For affine edges tangent coordinates are given by F'(t) = (V1-V0)/2
           *       (for now we only test affine edges, but later we will test edges for cells 
           *        with extended topologies.)
           */
          int v0ord = (*cti).getNodeMap(1, edgeOrd, 0);
          int v1ord = (*cti).getNodeMap(1, edgeOrd, 1);
          
          for(int pt = 0; pt < numCubPoints; pt++){

            // Temp storage for directly computed edge tangents
            FieldContainer<double> edgeBenchmarkTangents(3);
            
            for(int d = 0; d < cellDim; d++){
              edgeBenchmarkTangents(d) = (physCellVertices(0, v1ord, d) - physCellVertices(0, v0ord, d))/2.0;
              
              // Compare with d-component of edge tangent by CellTools
              if( abs(edgeBenchmarkTangents(d) - edgePointTangents(0, pt, d)) > INTREPID2_THRESHOLD ){
                errorFlag++;
                *outStream
                  << std::setw(70) << "^^^^----FAILURE!" << "\n"
                  << " Edge tangent computation by CellTools failed for: \n"
                  << "       Cell Topology = " << (*cti).getName() << "\n"
                  << "        Edge ordinal = " << edgeOrd << "\n"
                  << "   Edge point number = " << pt << "\n"
                  << "  Tangent coordinate = " << d << "\n"
                  << "     CellTools value = " <<  edgePointTangents(0, pt, d) << "\n"
                  << "     Benchmark value = " <<  edgeBenchmarkTangents(d) << "\n\n";
              }
            } // for d
            
            // Test side normals for 2D cells only: edge normal has coordinates (t1, -t0)
            if(cellDim == 2) {
              CellTools::getPhysicalSideNormals(edgePointNormals, edgePointsJacobians, edgeOrd, (*cti));
              if( abs(edgeBenchmarkTangents(1) - edgePointNormals(0, pt, 0)) > INTREPID2_THRESHOLD ){
                errorFlag++;
                *outStream
                  << std::setw(70) << "^^^^----FAILURE!" << "\n"
                  << " Edge Normal computation by CellTools failed for: \n"
                  << "       Cell Topology = " << (*cti).getName() << "\n"
                  << "        Edge ordinal = " << edgeOrd << "\n"
                  << "   Edge point number = " << pt << "\n"
                  << "   Normal coordinate = " << 0 << "\n"
                  << "     CellTools value = " <<  edgePointNormals(0, pt, 0) << "\n"
                  << "     Benchmark value = " <<  edgeBenchmarkTangents(1) << "\n\n";
              }
              if( abs(edgeBenchmarkTangents(0) + edgePointNormals(0, pt, 1)) > INTREPID2_THRESHOLD ){
                errorFlag++;
                *outStream
                  << std::setw(70) << "^^^^----FAILURE!" << "\n"
                  << " Edge Normal computation by CellTools failed for: \n"
                  << "       Cell Topology = " << (*cti).getName() << "\n"
                  << "        Edge ordinal = " << edgeOrd << "\n"
                  << "   Edge point number = " << pt << "\n"
                  << "   Normal coordinate = " << 1  << "\n"
                  << "     CellTools value = " <<  edgePointNormals(0, pt, 1) << "\n"
                  << "     Benchmark value = " << -edgeBenchmarkTangents(0) << "\n\n";
              }
            } // edge normals            
          } // for pt
        }// for edgeOrd
      }// if admissible cell
    }// for cti
    
    
    
    *outStream \
      << "\n"
      << "===============================================================================\n"\
      << "| Test 4: face/side normals for stand. 3D cells with base topologies:         |                                                      |\n"\
      << "===============================================================================\n\n";
    // This test loops over standard 3D cells with base topologies, creates a set of nodes and tests normals 

    // Define cubature on the edge parametrization domain:
    Teuchos::RCP<Cubature<double> > triFaceCubature  = cubFactory.create(paramTriFace, 6); 
    Teuchos::RCP<Cubature<double> > quadFaceCubature = cubFactory.create(paramQuadFace, 6); 
    
    int faceCubDim           = triFaceCubature -> getDimension();
    int numTriFaceCubPoints  = triFaceCubature -> getNumPoints();
    int numQuadFaceCubPoints = quadFaceCubature -> getNumPoints();    
        
    // Allocate storage for cubature points and weights on face parameter domain and fill with points:
    FieldContainer<double> paramTriFacePoints(numTriFaceCubPoints, faceCubDim);
    FieldContainer<double> paramTriFaceWeights(numTriFaceCubPoints);
    FieldContainer<double> paramQuadFacePoints(numQuadFaceCubPoints, faceCubDim);
    FieldContainer<double> paramQuadFaceWeights(numQuadFaceCubPoints);
    
    triFaceCubature -> getCubature(paramTriFacePoints, paramTriFaceWeights);
    quadFaceCubature -> getCubature(paramQuadFacePoints, paramQuadFaceWeights);
    
    
    // Loop over admissible topologies 
    for(cti = standardBaseTopologies.begin(); cti !=standardBaseTopologies.end(); ++cti){
      
      // Exclude 2D and Pyramid<5> cells
      if( ( (*cti).getDimension() == 3) && ( (*cti).getKey() != shards::Pyramid<5>::key) ){ 
        
        int cellDim = (*cti).getDimension();
        int vCount  = (*cti).getVertexCount();
        FieldContainer<double> refCellVertices(vCount, cellDim);
        CellTools::getReferenceSubcellVertices(refCellVertices, cellDim, 0, (*cti) );
        
        *outStream << " Testing face/side normals for cell topology " <<  (*cti).getName() <<"\n";
        
        // Array for physical cell vertices ( must have rank 3 for setJacobians)
        FieldContainer<double> physCellVertices(1, vCount, cellDim);
        
        // Randomize reference cell vertices by moving them up to +/- (1/8) units along their
        // coordinate axis. Guaranteed to be non-degenerate for standard cells with base topology 
        for(int v = 0; v < vCount; v++){
          for(int d = 0; d < cellDim; d++){
            double delta = Teuchos::ScalarTraits<double>::random()/8.0;
            physCellVertices(0, v, d) = refCellVertices(v, d) + delta;
          } //for d
        }// for v     
        
        // Allocate storage for cub. points on a ref. face; Jacobians, phys. face normals and 
        // benchmark normals.
        FieldContainer<double> refTriFacePoints(numTriFaceCubPoints, cellDim);        
        FieldContainer<double> refQuadFacePoints(numQuadFaceCubPoints, cellDim);        
        FieldContainer<double> triFacePointsJacobians(1, numTriFaceCubPoints, cellDim, cellDim);
        FieldContainer<double> quadFacePointsJacobians(1, numQuadFaceCubPoints, cellDim, cellDim);
        FieldContainer<double> triFacePointNormals(1, numTriFaceCubPoints, cellDim);
        FieldContainer<double> triSidePointNormals(1, numTriFaceCubPoints, cellDim);
        FieldContainer<double> quadFacePointNormals(1, numQuadFaceCubPoints, cellDim);
        FieldContainer<double> quadSidePointNormals(1, numQuadFaceCubPoints, cellDim);
        
        
        // Loop over faces:
        for(int faceOrd = 0; faceOrd < (int)(*cti).getSideCount(); faceOrd++){
          
          // This test presently includes only Triangle<3> and Quadrilateral<4> faces. Once we support
          // cells with extended topologies we will add their faces as well.
          switch( (*cti).getCellTopologyData(2, faceOrd) -> key ) {
            
            case shards::Triangle<3>::key: 
              {
                // Compute face normals using CellTools
                CellTools::mapToReferenceSubcell(refTriFacePoints, paramTriFacePoints, 2, faceOrd, (*cti) );
                CellTools::setJacobian(triFacePointsJacobians, refTriFacePoints, physCellVertices, (*cti) );
                CellTools::getPhysicalFaceNormals(triFacePointNormals, triFacePointsJacobians, faceOrd, (*cti));               
                CellTools::getPhysicalSideNormals(triSidePointNormals, triFacePointsJacobians, faceOrd, (*cti));               
                /* 
                 * Compute face normals using direct linear parametrization of the face: the map from
                 * standard 2-simplex to physical Triangle<3> face in 3D is 
                 * F(x,y) = V0 + (V1-V0)x + (V2-V0)*y 
                 * Face normal is vector product Tx X Ty where Tx = (V1-V0); Ty = (V2-V0)
                 */
                int v0ord = (*cti).getNodeMap(2, faceOrd, 0);
                int v1ord = (*cti).getNodeMap(2, faceOrd, 1);
                int v2ord = (*cti).getNodeMap(2, faceOrd, 2);
                
                // Loop over face points: redundant for affine faces, but CellTools gives one vector 
                // per point so need to check all points anyways.
                for(int pt = 0; pt < numTriFaceCubPoints; pt++){
                  FieldContainer<double> tanX(3), tanY(3), faceNormal(3);
                  for(int d = 0; d < cellDim; d++){
                    tanX(d) = (physCellVertices(0, v1ord, d) - physCellVertices(0, v0ord, d));
                    tanY(d) = (physCellVertices(0, v2ord, d) - physCellVertices(0, v0ord, d));
                  }// for d
                  
                  RealSpaceTools<double>::vecprod(faceNormal, tanX, tanY); 
                  
                  // Compare direct normal with d-component of the face/side normal by CellTools
                  for(int d = 0; d < cellDim; d++){
                    
                    // face normal method
                    if( abs(faceNormal(d) - triFacePointNormals(0, pt, d)) > INTREPID2_THRESHOLD ){
                      errorFlag++;
                      *outStream
                        << std::setw(70) << "^^^^----FAILURE!" << "\n"
                        << " Face normal computation by CellTools failed for: \n"
                        << "       Cell Topology = " << (*cti).getName() << "\n"
                        << "       Face Topology = " << (*cti).getCellTopologyData(2, faceOrd) -> name << "\n"
                        << "        Face ordinal = " << faceOrd << "\n"
                        << "   Face point number = " << pt << "\n"
                        << "   Normal coordinate = " << d  << "\n"
                        << "     CellTools value = " <<  triFacePointNormals(0, pt, d)
                        << "     Benchmark value = " <<  faceNormal(d) << "\n\n";
                    }
                    //side normal method
                    if( abs(faceNormal(d) - triSidePointNormals(0, pt, d)) > INTREPID2_THRESHOLD ){
                      errorFlag++;
                      *outStream
                        << std::setw(70) << "^^^^----FAILURE!" << "\n"
                        << " Side normal computation by CellTools failed for: \n"
                        << "       Cell Topology = " << (*cti).getName() << "\n"
                        << "       Side Topology = " << (*cti).getCellTopologyData(2, faceOrd) -> name << "\n"
                        << "        Side ordinal = " << faceOrd << "\n"
                        << "   Side point number = " << pt << "\n"
                        << "   Normal coordinate = " << d  << "\n"
                        << "     CellTools value = " <<  triSidePointNormals(0, pt, d)
                        << "     Benchmark value = " <<  faceNormal(d) << "\n\n";
                    }
                  } // for d
                } // for pt
              }
              break;
              
            case shards::Quadrilateral<4>::key:
              {
                // Compute face normals using CellTools
                CellTools::mapToReferenceSubcell(refQuadFacePoints, paramQuadFacePoints, 2, faceOrd, (*cti) );
                CellTools::setJacobian(quadFacePointsJacobians, refQuadFacePoints, physCellVertices, (*cti) );
                CellTools::getPhysicalFaceNormals(quadFacePointNormals, quadFacePointsJacobians, faceOrd, (*cti));               
                CellTools::getPhysicalSideNormals(quadSidePointNormals, quadFacePointsJacobians, faceOrd, (*cti)); 
                /*
                 * Compute face normals using direct bilinear parametrization of the face: the map from
                 * [-1,1]^2 to physical Quadrilateral<4> face in 3D is 
                 * F(x,y) = ((V0+V1+V2+V3) + (-V0+V1+V2-V3)*X + (-V0-V1+V2+V3)*Y + (V0-V1+V2-V3)*X*Y)/4 
                 * Face normal is vector product Tx X Ty where
                 *          Tx = ((-V0+V1+V2-V3) + (V0-V1+V2-V3)*Y)/4
                 *          Ty = ((-V0-V1+V2+V3) + (V0-V1+V2-V3)*X)/4
                 */
                int v0ord = (*cti).getNodeMap(2, faceOrd, 0);
                int v1ord = (*cti).getNodeMap(2, faceOrd, 1);
                int v2ord = (*cti).getNodeMap(2, faceOrd, 2);
                int v3ord = (*cti).getNodeMap(2, faceOrd, 3);
                
                // Loop over face points (redundant for affine faces, but needed for later when we handle non-affine ones)
                for(int pt = 0; pt < numTriFaceCubPoints; pt++){
                  FieldContainer<double> tanX(3), tanY(3), faceNormal(3);
                  for(int d = 0; d < cellDim; d++){
                    tanX(d) = (physCellVertices(0, v0ord, d)*(-1.0 + paramQuadFacePoints(pt,1) )  +
                               physCellVertices(0, v1ord, d)*( 1.0 - paramQuadFacePoints(pt,1) ) + 
                               physCellVertices(0, v2ord, d)*( 1.0 + paramQuadFacePoints(pt,1) ) + 
                               physCellVertices(0, v3ord, d)*(-1.0 - paramQuadFacePoints(pt,1) ) )/4.0;
                    
                    tanY(d) = (physCellVertices(0, v0ord, d)*(-1.0 + paramQuadFacePoints(pt,0) ) +
                               physCellVertices(0, v1ord, d)*(-1.0 - paramQuadFacePoints(pt,0) ) + 
                               physCellVertices(0, v2ord, d)*( 1.0 + paramQuadFacePoints(pt,0) ) + 
                               physCellVertices(0, v3ord, d)*( 1.0 - paramQuadFacePoints(pt,0) ) )/4.0;
                  }// for d
                  
                  RealSpaceTools<double>::vecprod(faceNormal, tanX, tanY); 
                  // Compare direct normal with d-component of the face/side normal by CellTools
                  for(int d = 0; d < cellDim; d++){
                    
                    // face normal method
                    if( abs(faceNormal(d) - quadFacePointNormals(0, pt, d)) > INTREPID2_THRESHOLD ){
                      errorFlag++;
                      *outStream
                        << std::setw(70) << "^^^^----FAILURE!" << "\n"
                        << " Face normal computation by CellTools failed for: \n"
                        << "       Cell Topology = " << (*cti).getName() << "\n"
                        << "       Face Topology = " << (*cti).getCellTopologyData(2, faceOrd) -> name << "\n"
                        << "        Face ordinal = " << faceOrd << "\n"
                        << "   Face point number = " << pt << "\n"
                        << "   Normal coordinate = " << d  << "\n"
                        << "     CellTools value = " <<  quadFacePointNormals(0, pt, d)
                        << "     Benchmark value = " <<  faceNormal(d) << "\n\n";
                    }
                    //side normal method
                    if( abs(faceNormal(d) - quadSidePointNormals(0, pt, d)) > INTREPID2_THRESHOLD ){
                      errorFlag++;
                      *outStream
                        << std::setw(70) << "^^^^----FAILURE!" << "\n"
                        << " Side normal computation by CellTools failed for: \n"
                        << "       Cell Topology = " << (*cti).getName() << "\n"
                        << "       Side Topology = " << (*cti).getCellTopologyData(2, faceOrd) -> name << "\n"
                        << "        Side ordinal = " << faceOrd << "\n"
                        << "   Side point number = " << pt << "\n"
                        << "   Normal coordinate = " << d  << "\n"
                        << "     CellTools value = " <<  quadSidePointNormals(0, pt, d)
                        << "     Benchmark value = " <<  faceNormal(d) << "\n\n";
                    }
                  } // for d
                }// for pt
              }// case Quad
              break;
            default:
              errorFlag++;
              *outStream << " Face normals test failure: face topology not supported \n\n";
          } // switch 
        }// for faceOrd
      }// if admissible
      }// for cti
  }// try
  
  //============================================================================================//
  // Wrap up test: check if the test broke down unexpectedly due to an exception                //
  //============================================================================================//
  catch (std::logic_error err) {
    *outStream << err.what() << "\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;
}
Example #12
0
    int Orientation_Test01(const bool verbose) {

      Teuchos::RCP<std::ostream> outStream;
      Teuchos::oblackholestream bhs; // outputs nothing

      if (verbose)
        outStream = Teuchos::rcp(&std::cout, false);
      else
        outStream = Teuchos::rcp(&bhs,       false);

      Teuchos::oblackholestream oldFormatState;
      oldFormatState.copyfmt(std::cout);

      typedef typename
        Kokkos::Impl::is_space<DeviceSpaceType>::host_mirror_space::execution_space HostSpaceType ;

      *outStream << "DeviceSpace::  "; DeviceSpaceType::print_configuration(*outStream, false);
      *outStream << "HostSpace::    ";   HostSpaceType::print_configuration(*outStream, false);
      *outStream << "\n";

      
      *outStream
        << "===============================================================================\n"
        << "|                                                                             |\n"
        << "|                 Unit Test (Orientation)                                     |\n"
        << "|                                                                             |\n"
        << "===============================================================================\n";

      int errorFlag = 0;

      try {
        ordinal_type nthrow = 0, ncatch = 0;
        {
          Orientation ort;
          INTREPID2_TEST_ERROR_EXPECTED( if (ort.isAlignedToReference()) \
                                           throw std::logic_error("Default Orientation is not zero"); );
        }

        if (nthrow != ncatch) {
          errorFlag++;
          *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n";
          *outStream << "# of catch ("<< ncatch << ") is different from # of throw (" << nthrow << ")\n";
        }

        {
          *outStream << "\n -- Testing Triangle \n\n";

          const auto cellTopo = shards::CellTopology(shards::getCellTopologyData<shards::Triangle<3> >() );
          const ordinal_type elemNodes[6][3] = { { 1, 2, 3 },
                                                 { 1, 3, 2 },
                                                 { 2, 1, 3 },
                                                 { 2, 3, 1 },
                                                 { 3, 1, 2 },
                                                 { 3, 2, 1 } };

          const ordinal_type refEdgeOrts[6][3] = { { 0, 0, 1 },
                                                   { 0, 1, 1 },
                                                   { 1, 0, 1 },
                                                   { 0, 1, 0 },
                                                   { 1, 0, 0 },
                                                   { 1, 1, 0 } };
          
          for (auto i=0;i<6;++i) {
            // find orientation
            const auto nodes = Kokkos::View<const ordinal_type[3],HostSpaceType>(elemNodes[i]);
            const auto ort = Orientation::getOrientation(cellTopo, nodes);
            
            // decode orientation
            ordinal_type edgeOrt[3] = {};
            for (auto edgeId=0;edgeId<3;++edgeId) 
              ort.getEdgeOrientation(edgeOrt, 3);
            
            *outStream << " elemNodes = " 
                       << elemNodes[i][0] << " " 
                       << elemNodes[i][1] << " " 
                       << elemNodes[i][2] << " :: "
                       << " computed edgeOrts = " 
                       << edgeOrt[0] << " "
                       << edgeOrt[1] << " "
                       << edgeOrt[2] << " :: "
                       << " reference edgeOrts = " 
                       << refEdgeOrts[i][0] << " "
                       << refEdgeOrts[i][1] << " "
                       << refEdgeOrts[i][2] << " ::\n";
            
            if (edgeOrt[0] != refEdgeOrts[i][0] || 
                edgeOrt[1] != refEdgeOrts[i][1] || 
                edgeOrt[2] != refEdgeOrts[i][2])  {
              *outStream << "        ^^^^^^^^^^^^^^^^ FAILURE\n";
              ++errorFlag;
            }
          }
        }

        {
          *outStream << "\n -- Testing Quadrilateral \n\n";
          
          const auto cellTopo = shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >() );
          const ordinal_type elemNodes[24][4] = { { 1 ,  2 ,  3 ,  4 },
                                                  { 2 ,  1 ,  3 ,  4 },
                                                  { 1 ,  3 ,  2 ,  4 },
                                                  { 2 ,  3 ,  1 ,  4 },
                                                  { 3 ,  1 ,  2 ,  4 },
                                                  { 3 ,  2 ,  1 ,  4 },
                                                  { 1 ,  2 ,  4 ,  3 },
                                                  { 2 ,  1 ,  4 ,  3 },
                                                  { 1 ,  3 ,  4 ,  2 },
                                                  { 2 ,  3 ,  4 ,  1 },
                                                  { 3 ,  1 ,  4 ,  2 },
                                                  { 3 ,  2 ,  4 ,  1 },
                                                  { 1 ,  4 ,  2 ,  3 },
                                                  { 2 ,  4 ,  1 ,  3 },
                                                  { 1 ,  4 ,  3 ,  2 },
                                                  { 2 ,  4 ,  3 ,  1 },
                                                  { 3 ,  4 ,  1 ,  2 },
                                                  { 3 ,  4 ,  2 ,  1 },
                                                  { 4 ,  1 ,  2 ,  3 },
                                                  { 4 ,  2 ,  1 ,  3 },
                                                  { 4 ,  1 ,  3 ,  2 },
                                                  { 4 ,  2 ,  3 ,  1 },
                                                  { 4 ,  3 ,  1 ,  2 },
                                                  { 4 ,  3 ,  2 ,  1 } };
          
          const ordinal_type refEdgeOrts[24][4] = { { 0, 0, 0, 1 },
                                                    { 1, 0, 0, 1 },
                                                    { 0, 1, 0, 1 },
                                                    { 0, 1, 0, 1 },
                                                    { 1, 0, 0, 1 },
                                                    { 1, 1, 0, 1 },
                                                    { 0, 0, 1, 1 },
                                                    { 1, 0, 1, 1 },
                                                    { 0, 0, 1, 1 },
                                                    { 0, 0, 1, 0 },
                                                    { 1, 0, 1, 0 },
                                                    { 1, 0, 1, 0 },
                                                    { 0, 1, 0, 1 },
                                                    { 0, 1, 0, 1 },
                                                    { 0, 1, 1, 1 },
                                                    { 0, 1, 1, 0 },
                                                    { 0, 1, 0, 0 },
                                                    { 0, 1, 1, 0 },
                                                    { 1, 0, 0, 0 },
                                                    { 1, 1, 0, 0 },
                                                    { 1, 0, 1, 0 },
                                                    { 1, 0, 1, 0 },
                                                    { 1, 1, 0, 0 },
                                                    { 1, 1, 1, 0 } };

          for (auto i=0;i<24;++i) {
            // find orientation
            const auto nodes = Kokkos::View<const ordinal_type[4],HostSpaceType>(elemNodes[i]);
            const auto ort = Orientation::getOrientation(cellTopo, nodes);
            
            // decode orientation
            ordinal_type edgeOrt[4] = {};
            for (auto edgeId=0;edgeId<4;++edgeId) 
              ort.getEdgeOrientation(edgeOrt, 4);
            
            *outStream << " elemNodes = " 
                       << elemNodes[i][0] << " " 
                       << elemNodes[i][1] << " " 
                       << elemNodes[i][2] << " " 
                       << elemNodes[i][3] << " :: "
                       << " computed edgeOrts = " 
                       << edgeOrt[0] << " "
                       << edgeOrt[1] << " "
                       << edgeOrt[2] << " "
                       << edgeOrt[3] << " :: "
                       << " reference edgeOrts = " 
                       << refEdgeOrts[i][0] << " "
                       << refEdgeOrts[i][1] << " "
                       << refEdgeOrts[i][2] << " "
                       << refEdgeOrts[i][3] << " ::\n";
            
            if (edgeOrt[0] != refEdgeOrts[i][0] || 
                edgeOrt[1] != refEdgeOrts[i][1] || 
                edgeOrt[2] != refEdgeOrts[i][2] ||
                edgeOrt[3] != refEdgeOrts[i][3])  {
              *outStream << "        ^^^^^^^^^^^^^^^^ FAILURE\n";
              ++errorFlag;
            }
          }
        }

      } catch (std::exception err) {
Example #13
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 (FunctionSpaceTools)                         |\n" \
  << "|                                                                             |\n" \
  << "|     1) basic operator transformations and integration in HGRAD              |\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";


  int errorFlag = 0;
#ifdef HAVE_INTREPID_DEBUG
  int beginThrowNumber = Teuchos::TestForException_getThrowNumber();
  int endThrowNumber = beginThrowNumber + 28;
#endif

  typedef FunctionSpaceTools fst; 

  *outStream \
  << "\n"
  << "===============================================================================\n"\
  << "| TEST 1: exceptions                                                          |\n"\
  << "===============================================================================\n";

  try{
#ifdef HAVE_INTREPID_DEBUG
    FieldContainer<double,  1> a_2(2);
    FieldContainer<double,  2> a_2_2(2, 2);
    FieldContainer<double,  3> a_2_3(2, 3);
    FieldContainer<double,  4> a_3_2(3, 2);
    FieldContainer<double,  5> a_2_2_3(2, 2, 3);
    FieldContainer<double,  6> a_2_2_3_3(2, 2, 3, 3);
    FieldContainer<double,  7> a_2_2_2(2, 2, 2);
    FieldContainer<double,  8> a_2_2_2_3_3(2, 2, 2, 3, 3);
    FieldContainer<double,  9> a_2_2_2_2_2(2, 2, 2, 2, 2);
    FieldContainer<double, 10> a_2_2_2_2(2, 2, 2, 2);
    FieldContainer<double, 11> a_3_2_2_2(3, 2, 2, 2);
    FieldContainer<double, 12> a_2_3_2_2(2, 3, 2, 2);
    FieldContainer<double, 13> a_2_2_3_2(2, 2, 3, 2);
    FieldContainer<double, 14> a_2_2_2_3(2, 2, 2, 3);

    *outStream << "\n >>>>> TESTING computeCellMeasure:\n";
    INTREPID_TEST_COMMAND( fst::computeCellMeasure<double>(a_2_2, a_2, a_2) );
    INTREPID_TEST_COMMAND( fst::computeCellMeasure<double>(a_2_2, a_2_2, a_2) );

    *outStream << "\n >>>>> TESTING computeFaceMeasure:\n";
    INTREPID_TEST_COMMAND( fst::computeFaceMeasure<double>(a_2_2, a_2, a_2, 0, shards::getCellTopologyData< shards::Tetrahedron<> >()) );
    INTREPID_TEST_COMMAND( fst::computeFaceMeasure<double>(a_2_2, a_2_2_3_3, a_2, 0, shards::getCellTopologyData< shards::Tetrahedron<> >()) );

    *outStream << "\n >>>>> TESTING computeEdgeMeasure:\n";
    INTREPID_TEST_COMMAND( fst::computeEdgeMeasure<double>(a_2_2, a_2, a_2, 0, shards::getCellTopologyData< shards::Triangle<> >()) );
    INTREPID_TEST_COMMAND( fst::computeEdgeMeasure<double>(a_2_2, a_2_2_2_2, a_2, 0, shards::getCellTopologyData< shards::Triangle<> >()) );

    *outStream << "\n >>>>> TESTING integrate:\n";
    INTREPID_TEST_COMMAND( fst::integrate<double>(a_2_2_2_2, a_2_2_2, a_2_2_2, COMP_CPP) );
    INTREPID_TEST_COMMAND( fst::integrate<double>(a_2, a_2_2, a_2_2, COMP_CPP) );
    INTREPID_TEST_COMMAND( fst::integrate<double>(a_2, a_2_2_3, a_2_2_3, COMP_CPP) );
    INTREPID_TEST_COMMAND( fst::integrate<double>(a_2, a_2_2_3_3, a_2_2_3_3, COMP_CPP) );
    INTREPID_TEST_COMMAND( fst::integrate<double>(a_2_2, a_2_2, a_2_2_2, COMP_CPP) );
    INTREPID_TEST_COMMAND( fst::integrate<double>(a_2_2, a_2_2_3, a_2_2_2_3, COMP_CPP) );
    INTREPID_TEST_COMMAND( fst::integrate<double>(a_2_2, a_2_2_3_3, a_2_2_2_3_3, COMP_CPP) );
    INTREPID_TEST_COMMAND( fst::integrate<double>(a_2_2_2, a_2_2_2, a_2_2_2, COMP_CPP) );
    INTREPID_TEST_COMMAND( fst::integrate<double>(a_2_2_2, a_2_2_2_3, a_2_2_2_3, COMP_CPP) );
    INTREPID_TEST_COMMAND( fst::integrate<double>(a_2_2_2, a_2_2_2_3_3, a_2_2_2_3_3, COMP_CPP) );

    *outStream << "\n >>>>> TESTING operatorIntegral:\n";
    INTREPID_TEST_COMMAND( fst::operatorIntegral<double>(a_2_2_2, a_2_2, a_2_2_2, COMP_CPP) );
    INTREPID_TEST_COMMAND( fst::operatorIntegral<double>(a_2_2_2, a_2_2_2, a_2_2_2, COMP_CPP) );
    INTREPID_TEST_COMMAND( fst::operatorIntegral<double>(a_2_2_2, a_2_2_2_3, a_2_2_2_3, COMP_CPP) );
    INTREPID_TEST_COMMAND( fst::operatorIntegral<double>(a_2_2_2, a_2_2_2_3_3, a_2_2_2_3_3, COMP_CPP) );

    *outStream << "\n >>>>> TESTING functionalIntegral:\n";
    INTREPID_TEST_COMMAND( fst::functionalIntegral<double>(a_2_2, a_2_2_2_3_3, a_2_2_2, COMP_CPP) );
    INTREPID_TEST_COMMAND( fst::functionalIntegral<double>(a_2_2, a_2_2, a_2_2_2, COMP_CPP) );
    INTREPID_TEST_COMMAND( fst::functionalIntegral<double>(a_2_2, a_2_2_3, a_2_2_2_3, COMP_CPP) );
    INTREPID_TEST_COMMAND( fst::functionalIntegral<double>(a_2_2, a_2_2_3_3, a_2_2_2_3_3, COMP_CPP) );

    *outStream << "\n >>>>> TESTING dataIntegral:\n";
    INTREPID_TEST_COMMAND( fst::dataIntegral<double>(a_2, a_2, a_2_2_2, COMP_CPP) );
    INTREPID_TEST_COMMAND( fst::dataIntegral<double>(a_2, a_2_2, a_2_2, COMP_CPP) );
    INTREPID_TEST_COMMAND( fst::dataIntegral<double>(a_2, a_2_2_3, a_2_2_3, COMP_CPP) );
    INTREPID_TEST_COMMAND( fst::dataIntegral<double>(a_2, a_2_2_3_3, a_2_2_3_3, COMP_CPP) );

    *outStream << "\n >>>>> TESTING applyLeftFieldSigns:\n";
    INTREPID_TEST_COMMAND( fst::applyLeftFieldSigns<double>(a_2, a_2) );
    INTREPID_TEST_COMMAND( fst::applyLeftFieldSigns<double>(a_2_2_2, a_2) );
    INTREPID_TEST_COMMAND( fst::applyLeftFieldSigns<double>(a_2_2_2, a_3_2) );
    INTREPID_TEST_COMMAND( fst::applyLeftFieldSigns<double>(a_2_2_2, a_2_3) );
    INTREPID_TEST_COMMAND( fst::applyLeftFieldSigns<double>(a_2_2_2, a_2_2) );

    *outStream << "\n >>>>> TESTING applyRightFieldSigns:\n";
    INTREPID_TEST_COMMAND( fst::applyRightFieldSigns<double>(a_2, a_2) );
    INTREPID_TEST_COMMAND( fst::applyRightFieldSigns<double>(a_2_2_2, a_2) );
    INTREPID_TEST_COMMAND( fst::applyRightFieldSigns<double>(a_2_2_2, a_3_2) );
    INTREPID_TEST_COMMAND( fst::applyRightFieldSigns<double>(a_2_2_2, a_2_3) );
    INTREPID_TEST_COMMAND( fst::applyRightFieldSigns<double>(a_2_2_2, a_2_2) );

    *outStream << "\n >>>>> TESTING applyFieldSigns:\n";
    INTREPID_TEST_COMMAND( fst::applyFieldSigns<double>(a_2, a_2) );
    INTREPID_TEST_COMMAND( fst::applyFieldSigns<double>(a_2_2, a_2) );
    INTREPID_TEST_COMMAND( fst::applyFieldSigns<double>(a_2_2, a_3_2) );
    INTREPID_TEST_COMMAND( fst::applyFieldSigns<double>(a_2_2, a_2_3) );
    INTREPID_TEST_COMMAND( fst::applyFieldSigns<double>(a_2_2_2_3_3, a_2_2) );

    *outStream << "\n >>>>> TESTING evaluate:\n";
    INTREPID_TEST_COMMAND( fst::evaluate<double>(a_2, a_2, a_2_2) );
    INTREPID_TEST_COMMAND( fst::evaluate<double>(a_2, a_2, a_2_2_2_3_3) );
    INTREPID_TEST_COMMAND( fst::evaluate<double>(a_2, a_2_2, a_2_2_2_3_3) );
    INTREPID_TEST_COMMAND( fst::evaluate<double>(a_2_2_3_3, a_3_2, a_2_2_2_3_3) );
    INTREPID_TEST_COMMAND( fst::evaluate<double>(a_2_2_3_3, a_2_3, a_2_2_2_3_3) );
    INTREPID_TEST_COMMAND( fst::evaluate<double>(a_3_2_2_2, a_2_2, a_2_2_2_2_2) );
    INTREPID_TEST_COMMAND( fst::evaluate<double>(a_2_3_2_2, a_2_2, a_2_2_2_2_2) );
    INTREPID_TEST_COMMAND( fst::evaluate<double>(a_2_2_3_2, a_2_2, a_2_2_2_2_2) );
    INTREPID_TEST_COMMAND( fst::evaluate<double>(a_2_2_2_3, a_2_2, a_2_2_2_2_2) );
    INTREPID_TEST_COMMAND( fst::evaluate<double>(a_2_2_2_2, a_2_2, a_2_2_2_2_2) );
#endif
  }
  catch (std::logic_error err) {
    *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
    *outStream << err.what() << '\n';
    *outStream << "-------------------------------------------------------------------------------" << "\n\n";
    errorFlag = -1000;
  };

#ifdef HAVE_INTREPID_DEBUG
  if (Teuchos::TestForException_getThrowNumber() != endThrowNumber)
    errorFlag++;
#endif

  *outStream \
  << "\n"
  << "===============================================================================\n"\
  << "| TEST 2: correctness of math operations                                      |\n"\
  << "===============================================================================\n";

  outStream->precision(20);

  try {
      // cell type: tet
      shards::CellTopology cellType = shards::getCellTopologyData< shards::Tetrahedron<> >();

      /* Related to cubature. */
      // create cubature factory
      DefaultCubatureFactory<double, FieldContainer<double, 1>, FieldContainer<double, 2> > cubFactory;
      // cubature degree
      int cubDegree = 2;
      // create default cubature
      Teuchos::RCP<Cubature<double, FieldContainer<double, 1>, FieldContainer<double, 2> > > myCub = cubFactory.create(cellType, cubDegree);
      // get spatial dimension 
      int spaceDim = myCub->getDimension();
      // get number of cubature points
      int numCubPoints = myCub->getNumPoints();

      /* Related to basis. */
      // create tet basis
      Basis_HGRAD_TET_C1_FEM<double, FieldContainer<double, 1> > tetBasis;
      // get basis cardinality
      int numFields = tetBasis.getCardinality();
 
      /* Cell geometries. */
      int numCells    = 4;
      int numNodes    = 4;
      int numCellData = numCells*numNodes*spaceDim;
      double tetnodes[] = {
        // tet 0
        0.0, 0.0, 0.0,
        1.0, 0.0, 0.0,
        0.0, 1.0, 0.0,
        0.0, 0.0, 1.0,
        // tet 1
        4.0, 5.0, 1.0,
       -6.0, 2.0, 0.0,
        4.0, -3.0, -1.0,
        0.0, 2.0, 5.0,
        // tet 2
        -6.0, -3.0, 1.0,
        9.0, 2.0, 1.0,
        8.9, 2.1, 0.9,
        8.9, 2.1, 1.1,
        // tet 3
        -6.0, -3.0, 1.0,
        12.0, 3.0, 1.0,
        2.9, 0.1, 0.9,
        2.9, 0.1, 1.1
      };

      /* Computational arrays. */
      FieldContainer<double,  1> cub_points(numCubPoints, spaceDim);
      FieldContainer<double,  2> cub_weights(numCubPoints);
      FieldContainer<double,  3> cell_nodes(numCells, numNodes, spaceDim);
      FieldContainer<double,  4> jacobian(numCells, numCubPoints, spaceDim, spaceDim);
      FieldContainer<double,  5> jacobian_inv(numCells, numCubPoints, spaceDim, spaceDim);
      FieldContainer<double,  6> jacobian_det(numCells, numCubPoints);
      FieldContainer<double,  7> weighted_measure(numCells, numCubPoints);

      FieldContainer<double,  1> grad_of_basis_at_cub_points(numFields, numCubPoints, spaceDim);
      FieldContainer<double,  9> transformed_grad_of_basis_at_cub_points(numCells, numFields, numCubPoints, spaceDim);
      FieldContainer<double, 10> weighted_transformed_grad_of_basis_at_cub_points(numCells, numFields, numCubPoints, spaceDim);
      FieldContainer<double, 11> stiffness_matrices(numCells, numFields, numFields);

      FieldContainer<double,  1> value_of_basis_at_cub_points(numFields, numCubPoints);
      FieldContainer<double, 13> transformed_value_of_basis_at_cub_points(numCells, numFields, numCubPoints);
      FieldContainer<double, 14> weighted_transformed_value_of_basis_at_cub_points(numCells, numFields, numCubPoints);
      FieldContainer<double, 15> mass_matrices(numCells, numFields, numFields);

      /******************* START COMPUTATION ***********************/

      // get cubature points and weights
      myCub->getCubature(cub_points, cub_weights);

      // fill cell vertex array
      cell_nodes.setValues(tetnodes, numCellData);

      // compute geometric cell information
      CellTools<double>::setJacobian(jacobian, cub_points, cell_nodes, cellType);
      CellTools<double>::setJacobianInv(jacobian_inv, jacobian);
      CellTools<double>::setJacobianDet(jacobian_det, jacobian);

      // compute weighted measure
      fst::computeCellMeasure<double>(weighted_measure, jacobian_det, cub_weights);

      // Computing stiffness matrices:
      // tabulate gradients of basis functions at (reference) cubature points
      tetBasis.getValues(grad_of_basis_at_cub_points, cub_points, OPERATOR_GRAD);

      // transform gradients of basis functions
      fst::HGRADtransformGRAD<double>(transformed_grad_of_basis_at_cub_points,
                                      jacobian_inv,
                                      grad_of_basis_at_cub_points);

      // multiply with weighted measure
      fst::multiplyMeasure<double>(weighted_transformed_grad_of_basis_at_cub_points,
                                   weighted_measure,
                                   transformed_grad_of_basis_at_cub_points);

      // compute stiffness matrices
      fst::integrate<double>(stiffness_matrices,
                             transformed_grad_of_basis_at_cub_points,
                             weighted_transformed_grad_of_basis_at_cub_points,
                             COMP_CPP);


      // Computing mass matrices:
      // tabulate values of basis functions at (reference) cubature points
      tetBasis.getValues(value_of_basis_at_cub_points, cub_points, OPERATOR_VALUE);

      // transform values of basis functions
      fst::HGRADtransformVALUE<double>(transformed_value_of_basis_at_cub_points,
                                       value_of_basis_at_cub_points);

      // multiply with weighted measure
      fst::multiplyMeasure<double>(weighted_transformed_value_of_basis_at_cub_points,
                                   weighted_measure,
                                   transformed_value_of_basis_at_cub_points);

      // compute mass matrices
      fst::integrate<double>(mass_matrices,
                             transformed_value_of_basis_at_cub_points,
                             weighted_transformed_value_of_basis_at_cub_points,
                             COMP_CPP);

      /*******************  STOP COMPUTATION ***********************/


      /******************* START COMPARISON ***********************/
      string basedir = "./testdata";
      for (int cell_id = 0; cell_id < numCells; cell_id++) {

        stringstream namestream;
        string filename;
        namestream <<  basedir << "/mass_TET_FEM_P1" << "_" << "0" << cell_id+1 << ".dat";
        namestream >> filename;

        ifstream massfile(&filename[0]);
        if (massfile.is_open()) {
          if (compareToAnalytic<double>(&mass_matrices(cell_id, 0, 0), massfile, 1e-10, 0) > 0)
            errorFlag++;
          massfile.close();
        }
        else {
          errorFlag = -1;
          std::cout << "End Result: TEST FAILED\n";
          return errorFlag;
        }

        namestream.clear();
        namestream << basedir << "/stiff_TET_FEM_P1" << "_" << "0" << cell_id+1 << ".dat";
        namestream >> filename;

        ifstream stifffile(&filename[0]);
        if (stifffile.is_open())
        {
          if (compareToAnalytic<double>(&stiffness_matrices(cell_id, 0, 0), stifffile, 1e-10, 0) > 0)
            errorFlag++;
          stifffile.close();
        }
        else {
          errorFlag = -1;
          std::cout << "End Result: TEST FAILED\n";
          return errorFlag;
        }

      }

      /******************* STOP COMPARISON ***********************/

      *outStream << "\n";
  }
  catch (std::logic_error err) {
    *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
    *outStream << err.what() << '\n';
    *outStream << "-------------------------------------------------------------------------------" << "\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;
}
Example #14
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;
}
Example #15
0
/** \brief outdated tests for orthogonal bases
    \param argc [in] - number of command-line arguments
    \param argv [in] - command-line arguments
 */
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 OrthogonalBases                         |\n" \
    << "|                                                                             |\n" \
    << "|     1) Tests orthogonality of tetrahedral orthogonal basis                  |\n" \
    << "|                                                                             |\n" \
    << "|  Questions? Contact  Pavel Bochev ([email protected]) or                   |\n" \
    << "|                      Denis Ridzal ([email protected]) or                   |\n" \
    << "|                      Robert Kirby ([email protected])                  |\n" \
    << "|                                                                             |\n" \
    << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n" \
    << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
    << "|                                                                             |\n" \
    << "===============================================================================\n";
  
  int errorFlag  = 0;
  
  // First, get a reference quadrature rule

  CubatureDirectTetDefault<double,FieldContainer<double> > myCub(20);
  FieldContainer<double> cubPts( myCub.getNumPoints() , 3 );
  FieldContainer<double> cubWts( myCub.getNumPoints() );

  myCub.getCubature( cubPts , cubWts );
  
  // Tabulate the basis functions at the cubature points
  const int deg = 10;
  const int polydim = (deg+1)*(deg+2)*(deg+3)/6;
  FieldContainer<double> basisAtCubPts( polydim , myCub.getNumPoints() );
  OrthogonalBases::tabulateTetrahedron<double,FieldContainer<double>,FieldContainer<double> >( cubPts , deg , basisAtCubPts );

  // Now let's compute the mass matrix
  for (int i=0;i<polydim;i++) {
    for (int j=0;j<polydim;j++) {
      double cur = 0;
      for (int k=0;k<myCub.getNumPoints();k++) {
        cur += cubWts(k) * basisAtCubPts( i , k ) * basisAtCubPts( j , k );
      }
      if (i != j && fabs( cur ) > 20.0 * INTREPID_TOL) {
        std::cout << INTREPID_TOL << std::endl;
        std::cout << i << " " << j << " " << cur << std::endl;
        errorFlag++;
      }
      else if (i == j && fabs( cur ) < 20.0 * INTREPID_TOL ) {
        std::cout << i << " " << j << " " << cur << std::endl;
        errorFlag++;
      }

    }
  }

  
  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;
}
Example #16
0
int main(int argc, char *argv[]) {

  //Check number of arguments
  if (argc < 4) {
    std::cout <<"\n>>> ERROR: Invalid number of arguments.\n\n";
    std::cout <<"Usage:\n\n";
    std::cout <<"  ./Intrepid_example_Drivers_Example_10.exe deg NX NY NZ verbose\n\n";
    std::cout <<" where \n";
    std::cout <<"   int deg             - polynomial degree to be used (assumed >= 1) \n";
    std::cout <<"   int NX              - num intervals in x direction (assumed box domain, 0,1) \n";
    std::cout <<"   int NY              - num intervals in y direction (assumed box domain, 0,1) \n";
    std::cout <<"   int NZ              - num intervals in y direction (assumed box domain, 0,1) \n";
    std::cout <<"   verbose (optional)  - any character, indicates verbose output \n\n";
    exit(1);
  }
  
  // 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 > 2)
    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" \
    << "|  Example: Build Stiffness Matrix for                                        |\n" \
    << "|                   Poisson Equation on Hexahedral Mesh                       |\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";

  
  // ************************************ GET INPUTS **************************************
  
  int deg          = atoi(argv[1]);  // polynomial degree to use
  int NX           = atoi(argv[2]);  // num intervals in x direction (assumed box domain, 0,1)
  int NY           = atoi(argv[3]);  // num intervals in y direction (assumed box domain, 0,1)
  int NZ           = atoi(argv[4]);  // num intervals in y direction (assumed box domain, 0,1)
  

  // *********************************** CELL TOPOLOGY **********************************
  
  // Get cell topology for base hexahedron
  typedef shards::CellTopology    CellTopology;
  CellTopology hex_8(shards::getCellTopologyData<shards::Hexahedron<8> >() );
  
  // Get dimensions 
  int numNodesPerElem = hex_8.getNodeCount();
  int spaceDim = hex_8.getDimension();
  
  // *********************************** GENERATE MESH ************************************
  
  *outStream << "Generating mesh ... \n\n";
  
  *outStream << "   NX" << "   NY" << "   NZ\n";
  *outStream << std::setw(5) << NX <<
    std::setw(5) << NY << std::setw(5) << NZ << "\n\n";
  
  // Print mesh information
  int numElems = NX*NY*NZ;
  int numNodes = (NX+1)*(NY+1)*(NZ+1);
  *outStream << " Number of Elements: " << numElems << " \n";
  *outStream << "    Number of Nodes: " << numNodes << " \n\n";
  
  // Cube
  double leftX = 0.0, rightX = 1.0;
  double leftY = 0.0, rightY = 1.0;
  double leftZ = 0.0, rightZ = 1.0;

  // Mesh spacing
  double hx = (rightX-leftX)/((double)NX);
  double hy = (rightY-leftY)/((double)NY);
  double hz = (rightZ-leftZ)/((double)NZ);

  // Get nodal coordinates
  FieldContainer<double> nodeCoord(numNodes, spaceDim);
  FieldContainer<int> nodeOnBoundary(numNodes);
  int inode = 0;
  for (int k=0; k<NZ+1; k++) 
    {
      for (int j=0; j<NY+1; j++) 
	{
	  for (int i=0; i<NX+1; i++) 
	    {
	      nodeCoord(inode,0) = leftX + (double)i*hx;
	      nodeCoord(inode,1) = leftY + (double)j*hy;
	      nodeCoord(inode,2) = leftZ + (double)k*hz;
	      if (k==0 || k==NZ || j==0 || i==0 || j==NY || i==NX)
		{
		  nodeOnBoundary(inode)=1;
		}
	      else 
		{
		  nodeOnBoundary(inode)=0;
		}
	      inode++;
	    }
	}
    }
#define DUMP_DATA
#ifdef DUMP_DATA
  // Print nodal coords
  ofstream fcoordout("coords.dat");
  for (int i=0; i<numNodes; i++) {
    fcoordout << nodeCoord(i,0) <<" ";
    fcoordout << nodeCoord(i,1) <<" ";
    fcoordout << nodeCoord(i,2) <<"\n";
  }
  fcoordout.close();
#endif
  
  
  // Element to Node map
  // We'll keep it around, but this is only the DOFMap if you are in the lowest order case.
  FieldContainer<int> elemToNode(numElems, numNodesPerElem);
  int ielem = 0;
  for (int k=0; k<NZ; k++) 
    {
      for (int j=0; j<NY; j++) 
	{
	  for (int i=0; i<NX; i++) 
	    {
 	      elemToNode(ielem,0) = k * ( NX + 1 ) * ( NY + 1 ) + j * ( NX + 1 ) + i;
 	      elemToNode(ielem,1) = k * ( NX + 1 ) * ( NY + 1 ) + j * ( NX + 1 ) + i + 1;
 	      elemToNode(ielem,2) = k * ( NX + 1 ) * ( NY + 1 ) + ( j + 1 ) * ( NX + 1 ) + i + 1;
 	      elemToNode(ielem,3) = k * ( NX + 1 ) * ( NY + 1 ) + ( j + 1 ) * ( NX + 1 ) + i;
 	      elemToNode(ielem,4) = ( k + 1 ) * ( NX + 1 ) * ( NY + 1 ) + j * ( NX + 1 ) + i;
 	      elemToNode(ielem,5) = ( k + 1 ) * ( NX + 1 ) * ( NY + 1 ) + j * ( NX + 1 ) + i + 1;
 	      elemToNode(ielem,6) = ( k + 1 ) * ( NX + 1 ) * ( NY + 1 ) + ( j + 1 ) * ( NX + 1 ) + i + 1;
 	      elemToNode(ielem,7) = ( k + 1 ) * ( NX + 1 ) * ( NY + 1 ) + ( j + 1 ) * ( NX + 1 ) + i;
	      ielem++;
	    }
	}
    }
#ifdef DUMP_DATA
  // Output connectivity
  ofstream fe2nout("elem2node.dat");
  for (int k=0;k<NZ;k++)
    {
      for (int j=0; j<NY; j++) 
	{
	  for (int i=0; i<NX; i++) 
	    {
	      int ielem = i + j * NX + k * NY * NY;
	      for (int m=0; m<numNodesPerElem; m++)
		{
		  fe2nout << elemToNode(ielem,m) <<"  ";
		}
	      fe2nout <<"\n";
	    }
	}
    }
  fe2nout.close();
#endif
  
  // ************************************ CUBATURE ************************************** 
  *outStream << "Getting cubature ... \n\n";
  
  // Get numerical integration points and weights
  DefaultCubatureFactory<double>  cubFactory;                                   
  int cubDegree = 2*deg;
  Teuchos::RCP<Cubature<double> > quadCub = cubFactory.create(hex_8, cubDegree); 
  
  int cubDim       = quadCub->getDimension();
  int numCubPoints = quadCub->getNumPoints();
  
  FieldContainer<double> cubPoints(numCubPoints, cubDim);
  FieldContainer<double> cubWeights(numCubPoints);
  
  quadCub->getCubature(cubPoints, cubWeights);
  

  // ************************************** BASIS ***************************************
  
  *outStream << "Getting basis ... \n\n";
  
  // Define basis 
  Basis_HGRAD_HEX_Cn_FEM<double, FieldContainer<double> > quadHGradBasis(deg,POINTTYPE_SPECTRAL);
  int numFieldsG = quadHGradBasis.getCardinality();
  FieldContainer<double> quadGVals(numFieldsG, numCubPoints); 
  FieldContainer<double> quadGrads(numFieldsG, numCubPoints, spaceDim); 
  
  // Evaluate basis values and gradients at cubature points
  quadHGradBasis.getValues(quadGVals, cubPoints, OPERATOR_VALUE);
  quadHGradBasis.getValues(quadGrads, cubPoints, OPERATOR_GRAD);

  // create the local-global mapping
  FieldContainer<int> ltgMapping(numElems,numFieldsG);
  const int numDOF = (NX*deg+1)*(NY*deg+1)*(NZ*deg+1);
  ielem=0;
  for (int k=0;k<NZ;k++) 
    {
      for (int j=0;j<NY;j++) 
	{
	  for (int i=0;i<NX;i++) 
	    {
	      const int start = k * ( NY * deg + 1 ) * ( NX * deg + 1 ) + j * ( NX * deg + 1 ) + i * deg;
	      // loop over local dof on this cell
	      int local_dof_cur=0;
	      for (int kloc=0;kloc<=deg;kloc++) 
		{
		  for (int jloc=0;jloc<=deg;jloc++) 
		    {
		      for (int iloc=0;iloc<=deg;iloc++)
			{
			  ltgMapping(ielem,local_dof_cur) = start 
			    + kloc * ( NX * deg + 1 ) * ( NY * deg + 1 )
			    + jloc * ( NX * deg + 1 )
			    + iloc;
			  local_dof_cur++;
			}
		    }
		}
	      ielem++;
	    }
	}
    }
#ifdef DUMP_DATA
  // Output ltg mapping 
  ielem = 0;
  ofstream ltgout("ltg.dat");
  for (int k=0;k<NZ;k++)  
    {
      for (int j=0; j<NY; j++) 
	{
	  for (int i=0; i<NX; i++) 
	    {
	      int ielem = i + j * NX + k * NX * NY;
	      for (int m=0; m<numFieldsG; m++)
		{
		  ltgout << ltgMapping(ielem,m) <<"  ";
		}
	      ltgout <<"\n";
	    }
	}
    }
  ltgout.close();
#endif

  // ********** DECLARE GLOBAL OBJECTS *************
  Epetra_SerialComm Comm;
  Epetra_Map globalMapG(numDOF, 0, Comm);
  Epetra_FEVector u(globalMapG);  u.Random();
  Epetra_FEVector Ku(globalMapG);

  // time the instantiation 
  Epetra_Time instantiateTimer(Comm);
  Epetra_FECrsMatrix StiffMatrix(Copy,globalMapG,8*numFieldsG); 
  const double instantiateTime = instantiateTimer.ElapsedTime();


  // ********** CONSTRUCT AND INSERT LOCAL STIFFNESS MATRICES ***********
  *outStream << "Building local stiffness matrices...\n\n";
  typedef CellTools<double>  CellTools;
  typedef FunctionSpaceTools fst;
  int numCells = numElems; 

  // vertices
  FieldContainer<double> cellVertices(numCells,numNodesPerElem,spaceDim);

  // jacobian information
  FieldContainer<double> cellJacobian(numCells,numCubPoints,spaceDim,spaceDim);
  FieldContainer<double> cellJacobInv(numCells,numCubPoints,spaceDim,spaceDim);
  FieldContainer<double> cellJacobDet(numCells,numCubPoints);

  // element stiffness matrices and supporting storage space
  FieldContainer<double> localStiffMatrices(numCells, numFieldsG, numFieldsG);
  FieldContainer<double> transformedBasisGradients(numCells,numFieldsG,numCubPoints,spaceDim);
  FieldContainer<double> weightedTransformedBasisGradients(numCells,numFieldsG,numCubPoints,spaceDim);
  FieldContainer<double> weightedMeasure(numCells, numCubPoints);


  // get vertices of cells (for computing Jacobians)
  for (int i=0;i<numElems;i++)
    {
      for (int j=0;j<numNodesPerElem;j++)
	{
	  const int nodeCur = elemToNode(i,j);
	  for (int k=0;k<spaceDim;k++) 
	    {
	      cellVertices(i,j,k) = nodeCoord(nodeCur,k);
	    }
	}
    }
   
  Epetra_Time localConstructTimer( Comm );

  // jacobian evaluation 
  CellTools::setJacobian(cellJacobian,cubPoints,cellVertices,hex_8);
  CellTools::setJacobianInv(cellJacobInv, cellJacobian );
  CellTools::setJacobianDet(cellJacobDet, cellJacobian );

  // transform reference element gradients to each cell
  fst::HGRADtransformGRAD<double>(transformedBasisGradients, cellJacobInv, quadGrads);
      
  // compute weighted measure
  fst::computeCellMeasure<double>(weightedMeasure, cellJacobDet, cubWeights);

  // multiply values with weighted measure
  fst::multiplyMeasure<double>(weightedTransformedBasisGradients,
                               weightedMeasure, transformedBasisGradients);

  // integrate to compute element stiffness matrix
  fst::integrate<double>(localStiffMatrices,
                         transformedBasisGradients, weightedTransformedBasisGradients , COMP_BLAS);

  const double localConstructTime = localConstructTimer.ElapsedTime();


  Epetra_Time insertionTimer(Comm);

  // *** Element loop ***
  for (int k=0; k<numElems; k++) 
    {
      // assemble into global matrix
      StiffMatrix.InsertGlobalValues(numFieldsG,&ltgMapping(k,0),numFieldsG,&ltgMapping(k,0),&localStiffMatrices(k,0,0));
      
    }
  StiffMatrix.GlobalAssemble(); StiffMatrix.FillComplete();
  const double insertionTime = insertionTimer.ElapsedTime( );
  
  *outStream << "Time to instantiate global stiffness matrix: " << instantiateTime << "\n";
  *outStream << "Time to build local matrices (including Jacobian computation): "<< localConstructTime << "\n";
  *outStream << "Time to assemble global matrix from local matrices: " << insertionTime << "\n";
  *outStream << "Total construction time: " << instantiateTime + localConstructTime + insertionTime << "\n";

  Epetra_Time applyTimer(Comm);
  StiffMatrix.Apply(u,Ku);
  const double multTime = applyTimer.ElapsedTime();
  *outStream << "Time to multiply onto a vector: " << multTime << "\n";

  *outStream << "End Result: TEST PASSED\n";
  
  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);
  
  return 0;
}
Example #17
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 (CubatureGenSparse)                          |\n" \
  << "|                                                                             |\n" \
  << "|     1) Computing integrals of monomials on reference cells in 3D            |\n" \
  << "|                         - using Level 2 BLAS -                              |\n" \
  << "|                                                                             |\n" \
  << "|  Questions? Contact  Pavel Bochev ([email protected]),                     |\n" \
  << "|                      Denis Ridzal ([email protected]) or                   |\n" \
  << "|                      Matthew Keegan ([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: integrals of monomials in 3D (Level 2 BLAS version) using           |\n"\
  << "|           Generalized Sparse Grid Construction                              |\n"\
  << "===============================================================================\n";

  // internal variables:
  int                                      errorFlag = 0;
  int                                      polyCt = 0;
  int                                      offset = 0;
  Teuchos::Array< Teuchos::Array<double> > testInt;
  Teuchos::Array< Teuchos::Array<double> > analyticInt;
  Teuchos::Array<double>                   tmparray(1);
  double                                   reltol = 1.0e+04 * INTREPID_TOL;
  int maxDeg                             = 20; // can be as large as INTREPID2_CUBATURE_SPARSE3D_GAUSS_MAX, but runtime is excessive
  int maxOffset                          = INTREPID2_CUBATURE_LINE_GAUSS_MAX;
  int numPoly                            = (maxDeg+1)*(maxDeg+2)*(maxDeg+3)/6;
  int numAnalytic                        = (maxOffset+1)*(maxOffset+2)*(maxOffset+3)/6;
  testInt.assign(numPoly, tmparray);
  analyticInt.assign(numAnalytic, tmparray);

  // get names of files with analytic values
  std::string basedir = "./data";
  std::stringstream namestream;
  std::string filename;
  namestream << basedir << "/HEX_integrals" << ".dat";
  namestream >> filename;

  // format of data files with analytic values
  TypeOfExactData dataFormat = INTREPID_UTILS_FRACTION;

  // compute and compare integrals
  try {
      *outStream << "\nIntegrals of monomials:\n";
      std::ifstream filecompare(&filename[0]);
      // compute integrals
      for (int cubDeg=0; cubDeg <= maxDeg; cubDeg++) {
        int numMonomials = (cubDeg+1)*(cubDeg+2)*(cubDeg+3)/6; 
        testInt[cubDeg].resize(numMonomials);
        computeIntegral(testInt[cubDeg], cubDeg);
      }
      // get analytic values
      if (filecompare.is_open()) {
        getAnalytic(analyticInt, filecompare, dataFormat);
        // close file
        filecompare.close();
      }
      // perform comparison
      for (int cubDeg=0; cubDeg <= maxDeg; cubDeg++) {
        polyCt = 0;
        offset = 0;
        int oldErrorFlag = errorFlag;
        for (int xDeg=0; xDeg <= cubDeg; xDeg++) {
          for (int yDeg=0; yDeg <= cubDeg-xDeg; yDeg++) {
            for (int zDeg=0; zDeg <= cubDeg-xDeg-yDeg; zDeg++) {
              double abstol = ( analyticInt[polyCt+offset][0] == 0.0 ? reltol : std::fabs(reltol*analyticInt[polyCt+offset][0]) );
              double absdiff = std::fabs(analyticInt[polyCt+offset][0] - testInt[cubDeg][polyCt]);
              if (absdiff > abstol) {
                *outStream << "Cubature order " << std::setw(2) << std::left << cubDeg << " integrating "
                           << "x^" << std::setw(2) << std::left << xDeg << " * y^" << std::setw(2) << yDeg
                           << " * z^" << std::setw(2) << zDeg << ":" << "   "
                           << std::scientific << std::setprecision(16)
                           << testInt[cubDeg][polyCt] << "   " << analyticInt[polyCt+offset][0] << "   "
                           << std::setprecision(4) << absdiff << "   " << "<?" << "   " << abstol << "\n";
                errorFlag++;
                *outStream << std::right << std::setw(118) << "^^^^---FAILURE!\n";
              }
              polyCt++;
            }
            offset = offset + maxOffset - cubDeg;
          }
          offset = offset + (maxOffset - cubDeg)*(maxOffset - cubDeg + 1)/2;
        }
        *outStream << "Cubature order " << std::setw(2) << std::left << cubDeg;
        if (errorFlag == oldErrorFlag)
         *outStream << " passed.\n";
        else
         *outStream << " failed.\n";
      }
      *outStream << "\n";
  }
  catch (std::logic_error err) {
    *outStream << err.what() << "\n";
    errorFlag = -1;
  };


  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;
}
Example #18
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 (AdaptiveSparseGrid)                      |\n" \
  << "|                                                                             |\n" \
  << "|     1) Integrate a sum of Gaussians in 2D (Gerstner and Griebel).           |\n" \
  << "|                                                                             |\n" \
  << "|  Questions? Contact  Drew Kouri ([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 20: Integrate an anisotropic sum of Gaussians in 2D                    |\n"\
  << "===============================================================================\n";


  // internal variables:
  int         errorFlag    = 0;
  long double TOL          = INTREPID_TOL;
  int         dimension    = 2;
  int         maxLevel     = 25;
  bool        isNormalized = true;                  

  std::vector<EIntrepidBurkardt> rule1D(dimension,BURK_CLENSHAWCURTIS);
  std::vector<EIntrepidGrowth>   growth1D(dimension,GROWTH_FULLEXP);
 
  ASGdata<long double,StdVector<long double> > problem_data(
    dimension,rule1D,growth1D,maxLevel,isNormalized);  
  Teuchos::RCP<std::vector<long double> > integralValue = 
    Teuchos::rcp(new std::vector<long double>(1,0.0));
  StdVector<long double> sol(integralValue); sol.Set(0.0);
  problem_data.init(sol);

  long double eta = adaptSG(sol,problem_data,TOL); 

  long double analyticInt = (1.0+10.0)*std::sqrt(M_PI)/2.0*erff(1.0);
  long double abstol      = 1.0e1*std::sqrt(INTREPID_TOL);
  long double absdiff     = fabs(analyticInt-sol[0]);
  try { 
    *outStream << "Adaptive Sparse Grid exited with global error " 
	       << std::scientific << std::setprecision(16) << eta << "\n"
	       << "Approx = " << std::scientific << std::setprecision(16) << sol[0] 
	       << ",  Exact = " << std::scientific << std::setprecision(16) << analyticInt << "\n"
	       << "Error = " << std::scientific << std::setprecision(16) << absdiff << "   " 
	       << "<?" << "   " << abstol << "\n"; 
    if (absdiff > abstol) {
      errorFlag++;
      *outStream << std::right << std::setw(104) << "^^^^---FAILURE!\n";
    }
  }
  catch (std::logic_error err) {    
    *outStream << err.what() << "\n";
    errorFlag = -1;
  };  

  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;
}
Example #19
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_C1_FEM)                           |\n" \
    << "|                                                                             |\n" \
    << "|     1) Patch test involving mass and stiffness matrices,                    |\n" \
    << "|        for the Neumann problem on a REFERENCE line:                         |\n" \
    << "|                                                                             |\n" \
    << "|            - u'' + u = f  in (-1,1),  u' = g at -1,1                        |\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: Patch test                                                          |\n"\
    << "===============================================================================\n";

  
  int errorFlag = 0;
  double zero = 100*INTREPID_TOL;
  outStream -> precision(20);


  try {

    int max_order = 1;  // max total order of polynomial solution

    // Define array containing points at which the solution is evaluated
    int numIntervals = 100;
    int numInterpPoints = numIntervals + 1;
    FieldContainer<double> interp_points(numInterpPoints, 1);
    for (int i=0; i<numInterpPoints; i++) {
      interp_points(i,0) = -1.0+(2.0*(double)i)/(double)numIntervals;
    }
    
    DefaultCubatureFactory<double>  cubFactory;                                   // create factory
    shards::CellTopology line(shards::getCellTopologyData< shards::Line<> >());   // create cell topology

    //create basis
    Teuchos::RCP<Basis<double,FieldContainer<double> > > lineBasis =
      Teuchos::rcp(new Basis_HGRAD_LINE_C1_FEM<double,FieldContainer<double> >() );
    int numFields = lineBasis->getCardinality();
    int basis_order = lineBasis->getDegree();

    // create cubature
    Teuchos::RCP<Cubature<double> > lineCub = cubFactory.create(line, 2);
    int numCubPoints = lineCub->getNumPoints();
    int spaceDim = lineCub->getDimension();

    for (int soln_order=0; soln_order <= max_order; soln_order++) {

      // evaluate exact solution
      FieldContainer<double> exact_solution(1, numInterpPoints);
      u_exact(exact_solution, interp_points, soln_order);

      /* Computational arrays. */
      FieldContainer<double> cub_points(numCubPoints, spaceDim);
      FieldContainer<double> cub_points_physical(1, numCubPoints, spaceDim);
      FieldContainer<double> cub_weights(numCubPoints);
      FieldContainer<double> cell_nodes(1, 2, spaceDim);
      FieldContainer<double> jacobian(1, numCubPoints, spaceDim, spaceDim);
      FieldContainer<double> jacobian_inv(1, numCubPoints, spaceDim, spaceDim);
      FieldContainer<double> jacobian_det(1, numCubPoints);
      FieldContainer<double> weighted_measure(1, numCubPoints);

      FieldContainer<double> value_of_basis_at_cub_points(numFields, numCubPoints);
      FieldContainer<double> transformed_value_of_basis_at_cub_points(1, numFields, numCubPoints);
      FieldContainer<double> weighted_transformed_value_of_basis_at_cub_points(1, numFields, numCubPoints);
      FieldContainer<double> grad_of_basis_at_cub_points(numFields, numCubPoints, spaceDim);
      FieldContainer<double> transformed_grad_of_basis_at_cub_points(1, numFields, numCubPoints, spaceDim);
      FieldContainer<double> weighted_transformed_grad_of_basis_at_cub_points(1, numFields, numCubPoints, spaceDim);
      FieldContainer<double> fe_matrix(1, numFields, numFields);

      FieldContainer<double> rhs_at_cub_points_physical(1, numCubPoints);
      FieldContainer<double> rhs_and_soln_vector(1, numFields);

      FieldContainer<double> one_point(1, 1);
      FieldContainer<double> value_of_basis_at_one(numFields, 1);
      FieldContainer<double> value_of_basis_at_minusone(numFields, 1);
      FieldContainer<double> bc_neumann(2, numFields);

      FieldContainer<double> value_of_basis_at_interp_points(numFields, numInterpPoints);
      FieldContainer<double> transformed_value_of_basis_at_interp_points(1, numFields, numInterpPoints);
      FieldContainer<double> interpolant(1, numInterpPoints);

      FieldContainer<int> ipiv(numFields);

      /******************* START COMPUTATION ***********************/

      // get cubature points and weights
      lineCub->getCubature(cub_points, cub_weights);

      // fill cell vertex array
      cell_nodes(0, 0, 0) = -1.0;
      cell_nodes(0, 1, 0) = 1.0;

      // compute geometric cell information
      CellTools<double>::setJacobian(jacobian, cub_points, cell_nodes, line);
      CellTools<double>::setJacobianInv(jacobian_inv, jacobian);
      CellTools<double>::setJacobianDet(jacobian_det, jacobian);

      // compute weighted measure
      FunctionSpaceTools::computeCellMeasure<double>(weighted_measure, jacobian_det, cub_weights);

      ///////////////////////////
      // Computing mass matrices:
      // tabulate values of basis functions at (reference) cubature points
      lineBasis->getValues(value_of_basis_at_cub_points, cub_points, OPERATOR_VALUE);

      // transform values of basis functions
      FunctionSpaceTools::HGRADtransformVALUE<double>(transformed_value_of_basis_at_cub_points,
                                                      value_of_basis_at_cub_points);

      // multiply with weighted measure
      FunctionSpaceTools::multiplyMeasure<double>(weighted_transformed_value_of_basis_at_cub_points,
                                                  weighted_measure,
                                                  transformed_value_of_basis_at_cub_points);

      // compute mass matrices
      FunctionSpaceTools::integrate<double>(fe_matrix,
                                            transformed_value_of_basis_at_cub_points,
                                            weighted_transformed_value_of_basis_at_cub_points,
                                            COMP_CPP);
      ///////////////////////////

      ////////////////////////////////
      // Computing stiffness matrices:
      // tabulate gradients of basis functions at (reference) cubature points
      lineBasis->getValues(grad_of_basis_at_cub_points, cub_points, OPERATOR_GRAD);

      // transform gradients of basis functions
      FunctionSpaceTools::HGRADtransformGRAD<double>(transformed_grad_of_basis_at_cub_points,
                                                     jacobian_inv,
                                                     grad_of_basis_at_cub_points);

      // multiply with weighted measure
      FunctionSpaceTools::multiplyMeasure<double>(weighted_transformed_grad_of_basis_at_cub_points,
                                                  weighted_measure,
                                                  transformed_grad_of_basis_at_cub_points);

      // compute stiffness matrices and sum into fe_matrix
      FunctionSpaceTools::integrate<double>(fe_matrix,
                                            transformed_grad_of_basis_at_cub_points,
                                            weighted_transformed_grad_of_basis_at_cub_points,
                                            COMP_CPP,
                                            true);
      ////////////////////////////////

      ///////////////////////////////
      // Computing RHS contributions:
      // map (reference) cubature points to physical space
      CellTools<double>::mapToPhysicalFrame(cub_points_physical, cub_points, cell_nodes, line);

      // evaluate rhs function
      rhsFunc(rhs_at_cub_points_physical, cub_points_physical, soln_order);

      // compute rhs
      FunctionSpaceTools::integrate<double>(rhs_and_soln_vector,
                                            rhs_at_cub_points_physical,
                                            weighted_transformed_value_of_basis_at_cub_points,
                                            COMP_CPP);

      // compute neumann b.c. contributions and adjust rhs
      one_point(0,0) = 1.0;   lineBasis->getValues(value_of_basis_at_one, one_point, OPERATOR_VALUE);
      one_point(0,0) = -1.0;  lineBasis->getValues(value_of_basis_at_minusone, one_point, OPERATOR_VALUE);
      neumann(bc_neumann, value_of_basis_at_minusone, value_of_basis_at_one, soln_order);
      for (int i=0; i<numFields; i++) {
        rhs_and_soln_vector(0, i) -= bc_neumann(0, i);
        rhs_and_soln_vector(0, i) += bc_neumann(1, i);
      }
      ///////////////////////////////

      /////////////////////////////
      // Solution of linear system:
      int info = 0;
      Teuchos::LAPACK<int, double> solver;
      //solver.GESV(numRows, 1, &fe_mat(0,0), numRows, &ipiv(0), &fe_vec(0), numRows, &info);
      solver.GESV(numFields, 1, &fe_matrix[0], numFields, &ipiv(0), &rhs_and_soln_vector[0], numFields, &info);
      /////////////////////////////

      ////////////////////////
      // Building interpolant:
      // evaluate basis at interpolation points
      lineBasis->getValues(value_of_basis_at_interp_points, interp_points, OPERATOR_VALUE);
      // transform values of basis functions
      FunctionSpaceTools::HGRADtransformVALUE<double>(transformed_value_of_basis_at_interp_points,
                                                      value_of_basis_at_interp_points);
      FunctionSpaceTools::evaluate<double>(interpolant, rhs_and_soln_vector, transformed_value_of_basis_at_interp_points);
      ////////////////////////

      /******************* END COMPUTATION ***********************/
    
      RealSpaceTools<double>::subtract(interpolant, exact_solution);

      *outStream << "\nNorm-2 difference between exact solution polynomial of order "
                 << soln_order << " and finite element interpolant of order " << basis_order << ": "
                 << RealSpaceTools<double>::vectorNorm(&interpolant[0], interpolant.dimension(1), NORM_TWO) << "\n";

      if (RealSpaceTools<double>::vectorNorm(&interpolant[0], interpolant.dimension(1), NORM_TWO) > zero) {
        *outStream << "\n\nPatch test failed for solution polynomial order "
                   << soln_order << " and basis order " << basis_order << "\n\n";
        errorFlag++;
      }

    } // end for soln_order

  }
  // 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;
}
Example #20
0
int main(int argc, char *argv[]) {
Kokkos::initialize();
  //Check number of arguments
   if (argc < 4) {
      std::cout <<"\n>>> ERROR: Invalid number of arguments.\n\n";
      std::cout <<"Usage:\n\n";
      std::cout <<"  ./Intrepid_example_Drivers_Example_03.exe NX NY NZ verbose\n\n";
      std::cout <<" where \n";
      std::cout <<"   int NX              - num intervals in x direction (assumed box domain, 0,1) \n";
      std::cout <<"   int NY              - num intervals in y direction (assumed box domain, 0,1) \n";
      std::cout <<"   int NZ              - num intervals in z direction (assumed box domain, 0,1) \n";
      std::cout <<"   verbose (optional)  - any character, indicates verbose output \n\n";
      exit(1);
   }
  
  // 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 > 3)
    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" \
    << "|  Example: Generate Stiffness Matrix and Right Hand Side Vector for          |\n" \
    << "|                   Poisson Equation on Hexahedral Mesh                       |\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";


// ************************************ GET INPUTS **************************************

    int NX            = atoi(argv[1]);  // num intervals in x direction (assumed box domain, 0,1)
    int NY            = atoi(argv[2]);  // num intervals in y direction (assumed box domain, 0,1)
    int NZ            = atoi(argv[3]);  // num intervals in z direction (assumed box domain, 0,1)

// *********************************** CELL TOPOLOGY **********************************

   // Get cell topology for base hexahedron
    typedef shards::CellTopology    CellTopology;
    CellTopology hex_8(shards::getCellTopologyData<shards::Hexahedron<8> >() );

   // Get dimensions 
    int numNodesPerElem = hex_8.getNodeCount();
    int spaceDim = hex_8.getDimension();

// *********************************** GENERATE MESH ************************************

    *outStream << "Generating mesh ... \n\n";

    *outStream << "   NX" << "   NY" << "   NZ\n";
    *outStream << std::setw(5) << NX <<
                 std::setw(5) << NY <<
                 std::setw(5) << NZ << "\n\n";

   // Print mesh information
    int numElems = NX*NY*NZ;
    int numNodes = (NX+1)*(NY+1)*(NZ+1);
    *outStream << " Number of Elements: " << numElems << " \n";
    *outStream << "    Number of Nodes: " << numNodes << " \n\n";

   // Cube
    double leftX = 0.0, rightX = 1.0;
    double leftY = 0.0, rightY = 1.0;
    double leftZ = 0.0, rightZ = 1.0;

   // Mesh spacing
    double hx = (rightX-leftX)/((double)NX);
    double hy = (rightY-leftY)/((double)NY);
    double hz = (rightZ-leftZ)/((double)NZ);

   // Get nodal coordinates
    FieldContainer<double> nodeCoord(numNodes, spaceDim);
    FieldContainer<int> nodeOnBoundary(numNodes);
    int inode = 0;
    for (int k=0; k<NZ+1; k++) {
      for (int j=0; j<NY+1; j++) {
        for (int i=0; i<NX+1; i++) {
          nodeCoord(inode,0) = leftX + (double)i*hx;
          nodeCoord(inode,1) = leftY + (double)j*hy;
          nodeCoord(inode,2) = leftZ + (double)k*hz;
          if (k==0 || j==0 || i==0 || k==NZ || j==NY || i==NX){
             nodeOnBoundary(inode)=1;
          }
          else {
             nodeOnBoundary(inode)=0;
          }
          inode++;
        }
      }
    }
#define DUMP_DATA
#ifdef DUMP_DATA
   // Print nodal coords
    ofstream fcoordout("coords.dat");
    for (int i=0; i<numNodes; i++) {
       fcoordout << nodeCoord(i,0) <<" ";
       fcoordout << nodeCoord(i,1) <<" ";
       fcoordout << nodeCoord(i,2) <<"\n";
    }
    fcoordout.close();
#endif


  // Element to Node map
    FieldContainer<int> elemToNode(numElems, numNodesPerElem);
    int ielem = 0;
    for (int k=0; k<NZ; k++) {
      for (int j=0; j<NY; j++) {
        for (int i=0; i<NX; i++) {
          elemToNode(ielem,0) = (NY + 1)*(NX + 1)*k + (NX + 1)*j + i;
          elemToNode(ielem,1) = (NY + 1)*(NX + 1)*k + (NX + 1)*j + i + 1;
          elemToNode(ielem,2) = (NY + 1)*(NX + 1)*k + (NX + 1)*(j + 1) + i + 1;
          elemToNode(ielem,3) = (NY + 1)*(NX + 1)*k + (NX + 1)*(j + 1) + i;
          elemToNode(ielem,4) = (NY + 1)*(NX + 1)*(k + 1) + (NX + 1)*j + i;
          elemToNode(ielem,5) = (NY + 1)*(NX + 1)*(k + 1) + (NX + 1)*j + i + 1;
          elemToNode(ielem,6) = (NY + 1)*(NX + 1)*(k + 1) + (NX + 1)*(j + 1) + i + 1;
          elemToNode(ielem,7) = (NY + 1)*(NX + 1)*(k + 1) + (NX + 1)*(j + 1) + i;
          ielem++;
        }
      }
    }
#ifdef DUMP_DATA
   // Output connectivity
    ofstream fe2nout("elem2node.dat");
    for (int k=0; k<NZ; k++) {
      for (int j=0; j<NY; j++) {
        for (int i=0; i<NX; i++) {
          int ielem = i + j * NX + k * NX * NY;
          for (int m=0; m<numNodesPerElem; m++){
              fe2nout << elemToNode(ielem,m) <<"  ";
           }
          fe2nout <<"\n";
        }
      }
    }
    fe2nout.close();
#endif


// ************************************ CUBATURE **************************************

    *outStream << "Getting cubature ... \n\n";

   // Get numerical integration points and weights
    DefaultCubatureFactory<double>  cubFactory;                                   
    int cubDegree = 2;
    Teuchos::RCP<Cubature<double> > hexCub = cubFactory.create(hex_8, cubDegree); 

    int cubDim       = hexCub->getDimension();
    int numCubPoints = hexCub->getNumPoints();

    FieldContainer<double> cubPoints(numCubPoints, cubDim);
    FieldContainer<double> cubWeights(numCubPoints);

    hexCub->getCubature(cubPoints, cubWeights);


// ************************************** BASIS ***************************************

     *outStream << "Getting basis ... \n\n";

   // Define basis 
     Basis_HGRAD_HEX_C1_FEM<double, FieldContainer<double> > hexHGradBasis;
     int numFieldsG = hexHGradBasis.getCardinality();
     FieldContainer<double> hexGVals(numFieldsG, numCubPoints); 
     FieldContainer<double> hexGrads(numFieldsG, numCubPoints, spaceDim); 

  // Evaluate basis values and gradients at cubature points
     hexHGradBasis.getValues(hexGVals, cubPoints, OPERATOR_VALUE);
     hexHGradBasis.getValues(hexGrads, cubPoints, OPERATOR_GRAD);


// ******** LOOP OVER ELEMENTS TO CREATE LOCAL STIFFNESS MATRIX *************

    *outStream << "Building stiffness matrix and right hand side ... \n\n";

 // Settings and data structures for mass and stiffness matrices
    typedef CellTools<double>  CellTools;
    typedef FunctionSpaceTools fst;
    int numCells = 1; 

   // Container for nodes
    FieldContainer<double> hexNodes(numCells, numNodesPerElem, spaceDim);
   // Containers for Jacobian
    FieldContainer<double> hexJacobian(numCells, numCubPoints, spaceDim, spaceDim);
    FieldContainer<double> hexJacobInv(numCells, numCubPoints, spaceDim, spaceDim);
    FieldContainer<double> hexJacobDet(numCells, numCubPoints);
   // Containers for element HGRAD stiffness matrix
    FieldContainer<double> localStiffMatrix(numCells, numFieldsG, numFieldsG);
    FieldContainer<double> weightedMeasure(numCells, numCubPoints);
    FieldContainer<double> hexGradsTransformed(numCells, numFieldsG, numCubPoints, spaceDim);
    FieldContainer<double> hexGradsTransformedWeighted(numCells, numFieldsG, numCubPoints, spaceDim);
   // Containers for right hand side vectors
    FieldContainer<double> rhsData(numCells, numCubPoints);
    FieldContainer<double> localRHS(numCells, numFieldsG);
    FieldContainer<double> hexGValsTransformed(numCells, numFieldsG, numCubPoints);
    FieldContainer<double> hexGValsTransformedWeighted(numCells, numFieldsG, numCubPoints);
   // Container for cubature points in physical space
    FieldContainer<double> physCubPoints(numCells, numCubPoints, cubDim);

   // Global arrays in Epetra format 
    Epetra_SerialComm Comm;
    Epetra_Map globalMapG(numNodes, 0, Comm);
    Epetra_FECrsMatrix StiffMatrix(Copy, globalMapG, numFieldsG);
    Epetra_FEVector rhs(globalMapG);

 // *** Element loop ***
    for (int k=0; k<numElems; k++) {

     // Physical cell coordinates
      for (int i=0; i<numNodesPerElem; i++) {
         hexNodes(0,i,0) = nodeCoord(elemToNode(k,i),0);
         hexNodes(0,i,1) = nodeCoord(elemToNode(k,i),1);
         hexNodes(0,i,2) = nodeCoord(elemToNode(k,i),2);
      }

    // Compute cell Jacobians, their inverses and their determinants
       CellTools::setJacobian(hexJacobian, cubPoints, hexNodes, hex_8);
       CellTools::setJacobianInv(hexJacobInv, hexJacobian );
       CellTools::setJacobianDet(hexJacobDet, hexJacobian );

// ************************** Compute element HGrad stiffness matrices *******************************
  
     // transform to physical coordinates 
      fst::HGRADtransformGRAD<double>(hexGradsTransformed, hexJacobInv, hexGrads);
      
     // compute weighted measure
      fst::computeCellMeasure<double>(weightedMeasure, hexJacobDet, cubWeights);

     // multiply values with weighted measure
      fst::multiplyMeasure<double>(hexGradsTransformedWeighted,
                                   weightedMeasure, hexGradsTransformed);

     // integrate to compute element stiffness matrix
      fst::integrate<double>(localStiffMatrix,
                             hexGradsTransformed, hexGradsTransformedWeighted, COMP_BLAS);

      // assemble into global matrix
      for (int row = 0; row < numFieldsG; row++){
        for (int col = 0; col < numFieldsG; col++){
            int rowIndex = elemToNode(k,row);
            int colIndex = elemToNode(k,col);
            double val = localStiffMatrix(0,row,col);
            StiffMatrix.InsertGlobalValues(1, &rowIndex, 1, &colIndex, &val);
         }
      }

// ******************************* Build right hand side ************************************

      // transform integration points to physical points
       CellTools::mapToPhysicalFrame(physCubPoints, cubPoints, hexNodes, hex_8);

      // evaluate right hand side function at physical points
       for (int nPt = 0; nPt < numCubPoints; nPt++){

          double x = physCubPoints(0,nPt,0);
          double y = physCubPoints(0,nPt,1);
          double z = physCubPoints(0,nPt,2);

          rhsData(0,nPt) = evalDivGradu(x, y, z);
       }

     // transform basis values to physical coordinates 
      fst::HGRADtransformVALUE<double>(hexGValsTransformed, hexGVals);

     // multiply values with weighted measure
      fst::multiplyMeasure<double>(hexGValsTransformedWeighted,
                                   weightedMeasure, hexGValsTransformed);

     // integrate rhs term
      fst::integrate<double>(localRHS, rhsData, hexGValsTransformedWeighted, 
                             COMP_BLAS);

    // assemble into global vector
     for (int row = 0; row < numFieldsG; row++){
           int rowIndex = elemToNode(k,row);
           double val = -localRHS(0,row);
           rhs.SumIntoGlobalValues(1, &rowIndex, &val);
      }
     
 } // *** end element loop ***


  // Assemble global matrices
   StiffMatrix.GlobalAssemble(); StiffMatrix.FillComplete();
   rhs.GlobalAssemble();

 
  // Adjust stiffness matrix and rhs based on boundary conditions
   for (int row = 0; row<numNodes; row++){
       if (nodeOnBoundary(row)) {
          int rowindex = row;
          for (int col=0; col<numNodes; col++){
              double val = 0.0;
              int colindex = col;
              StiffMatrix.ReplaceGlobalValues(1, &rowindex, 1, &colindex, &val);
          }
          double val = 1.0;
          StiffMatrix.ReplaceGlobalValues(1, &rowindex, 1, &rowindex, &val);
          val = 0.0;
          rhs.ReplaceGlobalValues(1, &rowindex, &val);
       }
    }

#ifdef DUMP_DATA
   // Dump matrices to disk
     EpetraExt::RowMatrixToMatlabFile("stiff_matrix.dat",StiffMatrix);
     EpetraExt::MultiVectorToMatrixMarketFile("rhs_vector.dat",rhs,0,0,false);
#endif

   std::cout << "End Result: TEST PASSED\n";
   
   // reset format state of std::cout
   std::cout.copyfmt(oldFormatState);
   Kokkos::finalize();
   return 0;
}
Example #21
0
/** \brief Tests for Lagrange basis on triangles.  Tests Kronecker property of basis and basic execution
          of differentiation and dof-tab lookup
    \param argc [in] - number of command-line arguments
    \param argv [in] - command-line arguments
*/
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 HGRAD_TRI_Cn_FEM                        |\n" \
    << "|                                                                             |\n" \
    << "|     1) Tests triangular Lagrange basis                                      |\n" \
    << "|                                                                             |\n" \
    << "|  Questions? Contact  Pavel Bochev ([email protected]) or                   |\n" \
    << "|                      Denis Ridzal ([email protected]) or                   |\n" \
    << "|                      Robert Kirby ([email protected])                  |\n" \
    << "|                                                                             |\n" \
    << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n" \
    << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
    << "|                                                                             |\n" \
    << "===============================================================================\n";
  
  int errorFlag  = 0;

  // Let's instantiate a basis
  try {
    const int deg = 10;
    Basis_HGRAD_TRI_Cn_FEM<double,FieldContainer<double> >  myBasis( deg , POINTTYPE_WARPBLEND );

    // Get a lattice
    const int np_lattice = PointTools::getLatticeSize( myBasis.getBaseCellTopology() , deg , 0 );
    const int nbf = myBasis.getCardinality();
    FieldContainer<double> lattice( np_lattice , 2 );
    PointTools::getLattice<double,FieldContainer<double> >( lattice , 
                                                            myBasis.getBaseCellTopology() , 
                                                            deg , 
                                                            0 , 
                                                            POINTTYPE_WARPBLEND );         
    FieldContainer<double> vals( nbf , np_lattice );

    myBasis.getValues( vals , lattice , OPERATOR_VALUE );

    // test for Kronecker property
    for (int i=0;i<nbf;i++) {
      for (int j=0;j<np_lattice;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 (std::exception err) {
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  }

  try {
    const int deg = 3;
    Basis_HGRAD_TRI_Cn_FEM<double,FieldContainer<double> >  myBasis( deg , POINTTYPE_WARPBLEND );
    const std::vector<std::vector<std::vector<int> > >& dofdata = myBasis.getDofOrdinalData();
    for (unsigned d=0;d<dofdata.size();d++) {
      std::cout << "Dimension " << d << "\n";
      for (unsigned f=0;f<dofdata[d].size();f++) {
        std::cout << "\tFacet number " << f << "\n";
        std::cout << "\t\tDOFS:\n";
        for (unsigned n=0;n<dofdata[d][f].size();n++) {
          std::cout << "\t\t\t" << dofdata[d][f][n] << "\n";
        }
      }
    }
  }
  catch (std::exception err) {
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  }

  try {
    const int deg = 1;
    Basis_HGRAD_TRI_Cn_FEM<double,FieldContainer<double> >  myBasis( deg , POINTTYPE_WARPBLEND );
    
    // Get a lattice
    const int np_lattice = PointTools::getLatticeSize( myBasis.getBaseCellTopology() , deg , 0 );
    const int nbf = myBasis.getCardinality();
    FieldContainer<double> lattice( np_lattice , 2 );
    PointTools::getLattice<double,FieldContainer<double> >( lattice , 
                                                            myBasis.getBaseCellTopology() , 
                                                            deg , 
                                                            0 , 
                                                            POINTTYPE_WARPBLEND );         
    FieldContainer<double> vals( nbf , np_lattice , 2 );

    myBasis.getValues( vals , lattice , OPERATOR_CURL );

    std::cout << vals << std::endl;
  }
  catch (std::exception 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;
}
Example #22
0
    int FunctionSpaceTools_Test03(const bool verbose) {

      Teuchos::RCP<std::ostream> outStream;
      Teuchos::oblackholestream bhs; // outputs nothing

      if (verbose)
        outStream = Teuchos::rcp(&std::cout, false);
      else
        outStream = Teuchos::rcp(&bhs, false);

      Teuchos::oblackholestream oldFormatState;
      oldFormatState.copyfmt(std::cout);

      typedef typename
        Kokkos::Impl::is_space<DeviceSpaceType>::host_mirror_space::execution_space HostSpaceType ;

      *outStream << "DeviceSpace::  "; DeviceSpaceType::print_configuration(*outStream, false);
      *outStream << "HostSpace::    ";   HostSpaceType::print_configuration(*outStream, false);
      
      *outStream
        << "===============================================================================\n"
        << "|                                                                             |\n"
        << "|                      Unit Test (FunctionSpaceTools)                         |\n"
        << "|                                                                             |\n"
        << "|     1) Basic operator transformations and integration in HDIV:              |\n"
        << "|                                                                             |\n"
        << "|  Questions? Contact  Pavel Bochev ([email protected]) or                   |\n"
        << "|                      Denis Ridzal ([email protected]) or                   |\n"
        << "|                      Kyungjoo Kim ([email protected]).                      |\n"
        << "|                                                                             |\n"
        << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n"
        << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n"
        << "|                                                                             |\n"
        << "===============================================================================\n";

      typedef CellTools<DeviceSpaceType> ct;      
      typedef FunctionSpaceTools<DeviceSpaceType> fst;      
      typedef Kokkos::DynRankView<ValueType,DeviceSpaceType> DynRankView;

      int errorFlag = 0;

      *outStream
        << "\n"
        << "===============================================================================\n"
        << "| TEST 1: correctness of math operations                                      |\n"
        << "===============================================================================\n";
      
      outStream->precision(20);
      
      try {
        DefaultCubatureFactory cub_factory;                            

        shards::CellTopology cell_topo = shards::getCellTopologyData< shards::Hexahedron<8> >();    

        const auto cub_degree = 20;                                                               
        auto cub = cub_factory.create<DeviceSpaceType,ValueType,ValueType>(cell_topo, cub_degree); 

        const auto space_dim = cub->getDimension();                                              
        const auto num_cub_points = cub->getNumPoints();                                          

        Basis_HDIV_HEX_I1_FEM<DeviceSpaceType> basis;                        
        const auto num_fields = basis.getCardinality();                                       
        
        /* Cell geometries and orientations. */
        const auto num_cells = 4;
        const auto num_nodes = 8;
        
        const ValueType hexnodes[] = {
          // hex 0  -- affine
          -1.0, -1.0, -1.0,
          1.0, -1.0, -1.0,
          1.0, 1.0, -1.0,
          -1.0, 1.0, -1.0,
          -1.0, -1.0, 1.0,
          1.0, -1.0, 1.0,
          1.0, 1.0, 1.0,
          -1.0, 1.0, 1.0,
          // hex 1  -- affine
          -3.0, -3.0, 1.0,
          6.0, 3.0, 1.0,
          7.0, 8.0, 0.0,
          -2.0, 2.0, 0.0,
          -3.0, -3.0, 4.0,
          6.0, 3.0, 4.0,
          7.0, 8.0, 3.0,
          -2.0, 2.0, 3.0,
          // hex 2  -- affine
          -3.0, -3.0, 0.0,
          9.0, 3.0, 0.0,
          15.0, 6.1, 0.0,
          3.0, 0.1, 0.0,
          9.0, 3.0, 0.1,
          21.0, 9.0, 0.1,
          27.0, 12.1, 0.1,
          15.0, 6.1, 0.1,
          // hex 3  -- nonaffine
          -2.0, -2.0, 0.0,
          2.0, -1.0, 0.0,
          1.0, 6.0, 0.0,
          -1.0, 1.0, 0.0,
          0.0, 0.0, 1.0,
          1.0, 0.0, 1.0,
          1.0, 1.0, 1.0,
          0.0, 1.0, 1.0
        };
        
        const ValueType facesigns[] = {
          1, 1, 1, 1, 1, 1,
          1, -1, 1, -1, 1, -1,
          -1, -1, 1, 1, -1, 1,
          -1, -1, 1, 1, -1, -1
        };
        
        /* Computational arrays. */
        DynRankView ConstructWithLabel( cub_points,  num_cub_points, space_dim);
        DynRankView ConstructWithLabel( cub_weights, num_cub_points);

        DynRankView ConstructWithLabel( cell_nodes,       num_cells, num_nodes, space_dim);
        DynRankView ConstructWithLabel( field_signs,      num_cells, num_fields);

        DynRankView ConstructWithLabel( jacobian,         num_cells, num_cub_points, space_dim, space_dim);
        DynRankView ConstructWithLabel( jacobian_det,     num_cells, num_cub_points);
        DynRankView ConstructWithLabel( weighted_measure, num_cells, num_cub_points);
        
        DynRankView ConstructWithLabel( div_of_basis_at_cub_points,                                 num_fields, num_cub_points);
        DynRankView ConstructWithLabel( transformed_div_of_basis_at_cub_points,          num_cells, num_fields, num_cub_points);
        DynRankView ConstructWithLabel( weighted_transformed_div_of_basis_at_cub_points, num_cells, num_fields, num_cub_points);
        DynRankView ConstructWithLabel( stiffness_matrices,                              num_cells, num_fields, num_fields);
        
        DynRankView ConstructWithLabel( value_of_basis_at_cub_points,                                 num_fields, num_cub_points, space_dim);
        DynRankView ConstructWithLabel( transformed_value_of_basis_at_cub_points,          num_cells, num_fields, num_cub_points, space_dim);
        DynRankView ConstructWithLabel( weighted_transformed_value_of_basis_at_cub_points, num_cells, num_fields, num_cub_points, space_dim);
        DynRankView ConstructWithLabel( mass_matrices,                                     num_cells, num_fields, num_fields);

        /******************* START COMPUTATION ***********************/

        // get cubature points and weights
        cub->getCubature(cub_points, cub_weights);

        const Kokkos::DynRankView<const ValueType,Kokkos::LayoutRight,Kokkos::HostSpace> cell_nodes_host (&hexnodes[0],  num_cells, num_nodes, space_dim); 
        const Kokkos::DynRankView<const ValueType,Kokkos::LayoutRight,Kokkos::HostSpace> field_signs_host(&facesigns[0], num_cells, num_fields); 
        
        Kokkos::deep_copy( cell_nodes,  cell_nodes_host  );
        Kokkos::deep_copy( field_signs, field_signs_host );
        
        // compute geometric cell information
        ct::setJacobian(jacobian, cub_points, cell_nodes, cell_topo);
        ct::setJacobianDet(jacobian_det, jacobian);

        // compute weighted measure
        fst::computeCellMeasure(weighted_measure, jacobian_det, cub_weights);

        // **Computing stiffness matrices:
        basis.getValues(div_of_basis_at_cub_points, cub_points, OPERATOR_DIV);
        
        // transform divergences of basis functions
        fst::HDIVtransformDIV(transformed_div_of_basis_at_cub_points,
                              jacobian_det,
                              div_of_basis_at_cub_points);
        
        // multiply with weighted measure
        fst::multiplyMeasure(weighted_transformed_div_of_basis_at_cub_points,
                             weighted_measure,
                             transformed_div_of_basis_at_cub_points);
        
        // we can apply the field signs to the basis function arrays, or after the fact, see below
        fst::applyFieldSigns(transformed_div_of_basis_at_cub_points, field_signs);
        fst::applyFieldSigns(weighted_transformed_div_of_basis_at_cub_points, field_signs);
        
        // compute stiffness matrices
        fst::integrate(stiffness_matrices,
                       transformed_div_of_basis_at_cub_points,
                       weighted_transformed_div_of_basis_at_cub_points);
        

        // **Computing mass matrices:
        basis.getValues(value_of_basis_at_cub_points, cub_points, OPERATOR_VALUE);

            
        
        // transform values of basis functions
        fst::HDIVtransformVALUE(transformed_value_of_basis_at_cub_points,
                                jacobian,
                                jacobian_det,
                                value_of_basis_at_cub_points);

        // multiply with weighted measure
        fst::multiplyMeasure(weighted_transformed_value_of_basis_at_cub_points,
                             weighted_measure,
                             transformed_value_of_basis_at_cub_points);
        
        // compute mass matrices
        fst::integrate(mass_matrices,
                       transformed_value_of_basis_at_cub_points,
                       weighted_transformed_value_of_basis_at_cub_points);
        
        // apply field signs
        fst::applyLeftFieldSigns(mass_matrices, field_signs);
        fst::applyRightFieldSigns(mass_matrices, field_signs);
        
        /*******************  STOP COMPUTATION ***********************/
        
        
        /******************* START COMPARISON ***********************/
        std::string basedir = "../testdata";
        for (auto cid=0;cid<num_cells-1;++cid) {
          std::stringstream namestream;
          std::string filename;
          namestream <<  basedir << "/mass_HDIV_HEX_I1_FEM" << "_" << "0" << cid+1 << ".dat";
          namestream >> filename;

          *outStream << "\nCell ID : " << cid << "  mass matrix comparing with " << filename << "\n\n";
          
          std::ifstream massfile(&filename[0]);
          if (massfile.is_open()) {
            const auto mass_matrix_cell = Kokkos::subdynrankview(mass_matrices, cid, Kokkos::ALL(), Kokkos::ALL());
            errorFlag += compareToAnalytic(massfile, 
                                           mass_matrix_cell, 
                                           1e-10,
                                           verbose);
            massfile.close();
          } else {
            errorFlag = -1;
            INTREPID2_TEST_FOR_EXCEPTION( true, std::runtime_error,
                                          "Failed to open a file" );
          }
          
          namestream.clear();
          namestream << basedir << "/stiff_HDIV_HEX_I1_FEM" << "_" << "0" << cid+1 << ".dat";
          namestream >> filename;

          *outStream << "\nCell ID : " << cid << "  stiffness matrix comparing with " << filename << "\n\n";
          
          std::ifstream stifffile(&filename[0]);
          if (stifffile.is_open()) {
            const auto stiffness_matrix_cell = Kokkos::subdynrankview(stiffness_matrices, cid, Kokkos::ALL(), Kokkos::ALL());
            errorFlag += compareToAnalytic(stifffile,
                                           stiffness_matrix_cell,
                                           1e-10,
                                           verbose);
            stifffile.close();
          } else {
            errorFlag = -1;
            INTREPID2_TEST_FOR_EXCEPTION( true, std::runtime_error,
                                          "Failed to open a file" );
          }
        }

        for (auto cid=3;cid<num_cells;++cid) {
          std::stringstream namestream;
          std::string filename;
          namestream <<  basedir << "/mass_fp_HDIV_HEX_I1_FEM" << "_" << "0" << cid+1 << ".dat";
          namestream >> filename;

          *outStream << "\nCell ID : " << cid << "  mass matrix comparing with " << filename << "\n\n";
          
          std::ifstream massfile(&filename[0]);
          if (massfile.is_open()) {
            const auto mass_matrix_cell = Kokkos::subdynrankview(mass_matrices, cid, Kokkos::ALL(), Kokkos::ALL());
            errorFlag += compareToAnalytic(massfile, 
                                           mass_matrix_cell, 
                                           1e-4, 
                                           verbose,
                                           INTREPID2_UTILS_SCALAR);
            massfile.close();
          } else {
            errorFlag = -1;
            INTREPID2_TEST_FOR_EXCEPTION( true, std::runtime_error,
                                          "Failed to open a file" );
          }
          
          namestream.clear();
          namestream << basedir << "/stiff_fp_HDIV_HEX_I1_FEM" << "_" << "0" << cid+1 << ".dat";
          namestream >> filename;
          
          *outStream << "\nCell ID : " << cid << "  stiffness matrix comparing with " << filename << "\n\n";

          std::ifstream stifffile(&filename[0]);
          if (stifffile.is_open()) {
            const auto stiffness_matrix_cell = Kokkos::subdynrankview(stiffness_matrices, cid, Kokkos::ALL(), Kokkos::ALL());
            errorFlag += compareToAnalytic(stifffile,
                                           stiffness_matrix_cell,
                                           1e-4, 
                                           verbose,
                                           INTREPID2_UTILS_SCALAR);
            stifffile.close();
          } else {
            errorFlag = -1;
            INTREPID2_TEST_FOR_EXCEPTION( true, std::runtime_error,
                                          "Failed to open a file" );
          }
        }
        /******************* STOP COMPARISON ***********************/

        *outStream << "\n";
      } catch (std::logic_error err) {
        *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
        *outStream << err.what() << '\n';
        *outStream << "-------------------------------------------------------------------------------" << "\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;
    }
Example #23
0
/* -------------------------------------------------------------------
   This is a routine to test the integration, differentiation and
   interpolation routines in the polylib.c.

   First, it performs the integral

      /1      alpha   beta  alpha,beta
     |   (1-x)   (1+x)     P (x)       dx  = 0
     /-1                    n

   for all   -0.5 <= alpha <= 5   (increments of 0.5)
             -0.5 <= beta  <= 5   (increments of 0.5)

   using np points where
          NPLOWER <= np <= NPUPPER
                2     <= n  <= 2*np - delta

   delta = 1 (gauss), 2(radau), 3(lobatto).
   The integral is evaluated and if it is larger that EPS then the
   value of alpha,beta,np,n and the integral is printed to the screen.

   After every alpha value the statement
       "finished checking all beta values for alpha = #"
   is printed

   The routine then evaluates the derivate of

          d   n      n-1
      -- x  = n x
      dx

   for all   -0.5 <= alpha <= 5   (increments of 0.5)
             -0.5 <= beta  <= 5   (increments of 0.5)

   using np points where
          NPLOWER <= np <= NPUPPER
                2     <= n  <= np - 1

   The error is check in a pointwise sense and if it is larger than
   EPS then the value of alpha,beta,np,n and the error is printed to
   the screen. After every alpha value the statement
       "finished checking all beta values for alpha = #"
   is printed

   Finally the routine  evaluates the interpolation of

             n      n
        z  to  x

   where z are the quadrature zeros and x are the equispaced points

                  2*i
        x    =   -----   - 1.0    (0 <= i <= np-1)
     i       (np-1)


   for all   -0.5 <= alpha <= 5   (increments of 0.5)
             -0.5 <= beta  <= 5   (increments of 0.5)

   using np points where
          NPLOWER <= np <= NPUPPER
                2     <= n  <= np - 1

   The error is check in a pointwise sense and if it is larger than
   EPS then the value of alpha,beta,np,n and the error is printed to
   the screen. After every alpha value the statement
      "finished checking all beta values for alpha = #"
   is printed

   The above checks are performed for all the Gauss, Gauss-Radau and
   Gauss-Lobatto points. If you want to disable any routine then set
      GAUSS_INT, GAUSS_RADAU_INT, GAUSS_LOBATTO_INT = 0
   for the integration rouintes
      GAUSS_DIFF,GAUSS_RADAU_DIFF, GAUSS_LOBATTO_DIFF = 0
   for the differentiation routines
      GAUSS_INTERP,GAUSS_RADAU_INTERP, GAUSS_LOBATTO_INTERP = 0
   for the interpolation routines.
------------------------------------------------------------------*/
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 (IntrepidPolylib)                           |\n" \
  << "|                                                                             |\n" \
  << "|     1) the original Polylib tests                                           |\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";


  int errorFlag = 0;
  int beginThrowNumber = TestForException_getThrowNumber();
  int endThrowNumber = beginThrowNumber + 1;

  typedef IntrepidPolylib ipl; 
  IntrepidPolylib iplib;

  *outStream \
  << "\n"
  << "===============================================================================\n"\
  << "| TEST 1: exceptions                                                          |\n"\
  << "===============================================================================\n";

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

  if (TestForException_getThrowNumber() != endThrowNumber)
    errorFlag = -1000;

  *outStream \
  << "\n"
  << "===============================================================================\n"\
  << "| TEST 2: correctness of math operations                                      |\n"\
  << "===============================================================================\n";

  outStream->precision(20);

  try {
      { // start scope
      int np,n,i;
      double *z,*w,*p,sum=0,alpha,beta,*d;

      z  = dvector<double>(0,NPUPPER-1);
      w  = dvector<double>(0,NPUPPER-1);
      p  = dvector<double>(0,NPUPPER-1);

      d  = dvector<double>(0,NPUPPER*NPUPPER-1);

#if GAUSS_INT
      /* Gauss Integration */
      *outStream << "Begin checking Gauss integration\n";
      alpha = -0.5;
      while(alpha <= 5.0){
        beta = -0.5;
        while(beta <= 5.0){

          for(np = NPLOWER; np <= NPUPPER; ++np){
            ipl::zwgj(z,w,np,alpha,beta);
            for(n = 2; n < 2*np-1; ++n){
              ipl::jacobfd(np,z,p,(double*)0,n,alpha,beta);
              sum = ddot(np,w,1,p,1);
              if(std::abs(sum)>TEST_EPS) {
                errorFlag = -1000;
                *outStream << "ERROR:  alpha = " << alpha << ", beta = " << beta <<
                              ", np = " << np << ", n = " << n << "  integral was " << sum << "\n";
              }
            }
          }

          beta += 0.5;
        }
        *outStream << "finished checking all beta values for alpha = " << alpha << "\n";
        alpha += 0.5;
      }
      *outStream << "Finished checking Gauss Integration\n";
#endif

#if GAUSS_RADAUM_INT
      /* Gauss Radau (z = -1) Integration */
      *outStream << "Begin checking Gauss-Radau (z = -1) integration\n";
      alpha = -0.5;
      while(alpha <= 5.0){
        beta = -0.5;
        while(beta <= 5.0){

          for(np = NPLOWER; np <= NPUPPER; ++np){
            ipl::zwgrjm(z,w,np,alpha,beta);
            for(n = 2; n < 2*np-2; ++n){
              ipl::jacobfd(np,z,p,(double*)0,n,alpha,beta);
              sum = ddot(np,w,1,p,1);
              if(std::abs(sum)>TEST_EPS) {
                errorFlag = -1000;
                *outStream << "ERROR:  alpha = " << alpha << ", beta = " << beta <<
                              ", np = " << np << ", n = " << n << "  integral was " << sum << "\n";
              }
            }
          }

          beta += 0.5;
        }
        *outStream << "finished checking all beta values for alpha = " << alpha << "\n";
        alpha += 0.5;
      }
      *outStream << "Finished checking Gauss-Radau (z = -1) Integration\n";
#endif

#if GAUSS_RADAUP_INT
      /* Gauss Radau (z = +1) Integration */
      *outStream << "Begin checking Gauss-Radau (z = +1) integration\n";
      alpha = -0.5;
      while(alpha <= 5.0){
        beta = -0.5;
        while(beta <= 5.0){

          for(np = NPLOWER; np <= NPUPPER; ++np){
            ipl::zwgrjp(z,w,np,alpha,beta);
            for(n = 2; n < 2*np-2; ++n){
              ipl::jacobfd(np,z,p,(double*)0,n,alpha,beta);
              sum = ddot(np,w,1,p,1);
              if(std::abs(sum)>TEST_EPS) {
                errorFlag = -1000;
                *outStream << "ERROR:  alpha = " << alpha << ", beta = " << beta <<
                              ", np = " << np << ", n = " << n << "  integral was " << sum << "\n";
              }
            }
          }

          beta += 0.5;
        }
        *outStream << "finished checking all beta values for alpha = " << alpha << "\n";
        alpha += 0.5;
      }
      *outStream << "Finished checking Gauss-Radau (z = +1) Integration\n";
#endif

#if GAUSS_LOBATTO_INT
      /* Gauss Lobatto Integration */
      *outStream << "Begin checking Gauss-Lobatto integration\n";
      alpha = -0.5;
      while(alpha <= 5.0){
        beta = -0.5;
        while(beta <= 5.0){

          for(np = NPLOWER; np <= NPUPPER; ++np){
            ipl::zwglj(z,w,np,alpha,beta);
            for(n = 2; n < 2*np-3; ++n){
              ipl::jacobfd(np,z,p,(double*)0,n,alpha,beta);
              sum = ddot(np,w,1,p,1);
              if(std::abs(sum)>TEST_EPS) {
                errorFlag = -1000;
                *outStream << "ERROR:  alpha = " << alpha << ", beta = " << beta <<
                              ", np = " << np << ", n = " << n << "  integral was " << sum << "\n";
              }
            }
          }

          beta += 0.5;
        }
        *outStream << "finished checking all beta values for alpha = " << alpha << "\n";
        alpha += 0.5;
      }
      *outStream << "Finished checking Gauss-Lobatto Integration\n";
#endif

#if GAUSS_DIFF
      *outStream << "Begin checking differentiation through Gauss points\n";
      alpha = -0.5;
      while(alpha <= 5.0){
        beta = -0.5;
        while(beta <= 5.0){

          for(np = NPLOWER; np <= NPUPPER; ++np){
            ipl::zwgj(z,w,np,alpha,beta);
            for(n = 2; n < np-1; ++n){
              ipl::Dgj(d,z,np,alpha,beta);

              for(i = 0; i < np; ++i) p[i] = std::pow(z[i],n);
              sum = 0;
              for(i = 0; i < np; ++i)
                sum += std::abs(ddot(np,d+i*np,1,p,1) - n*std::pow(z[i],n-1));
              sum /= np;
              if(std::abs(sum)>TEST_EPS) {
                errorFlag = -1000;
                *outStream << "ERROR:  alpha = " << alpha << ", beta = " << beta <<
                              ", np = " << np << ", n = " << n << "  difference " << sum << "\n";
              }
            }
          }
          beta += 0.5;
        }
        *outStream << "finished checking all beta values for alpha = " << alpha << "\n";
        alpha += 0.5;
      }
      *outStream << "Finished checking Gauss Jacobi differentiation\n";
#endif

#if GAUSS_RADAUM_DIFF
      *outStream << "Begin checking differentiation through Gauss-Radau (z=-1) points\n";
      alpha = -0.5;
      while(alpha <= 5.0){
        beta = -0.5;
        while(beta <= 5.0){

          for(np = NPLOWER; np <= NPUPPER; ++np){
            ipl::zwgrjm(z,w,np,alpha,beta);
            for(n = 2; n < np-1; ++n){
              ipl::Dgrjm(d,z,np,alpha,beta);

              for(i = 0; i < np; ++i) p[i] = std::pow(z[i],n);
              sum = 0;
              for(i = 0; i < np; ++i)
                sum += std::abs(ddot(np,d+i*np,1,p,1) - n*std::pow(z[i],n-1));
              sum /= np;
              if(std::abs(sum)>TEST_EPS) {
                errorFlag = -1000;
                *outStream << "ERROR:  alpha = " << alpha << ", beta = " << beta <<
                              ", np = " << np << ", n = " << n << "  difference " << sum << "\n";
              }
            }
          }
          beta += 0.5;
        }
        *outStream << "finished checking all beta values for alpha = " << alpha << "\n";
        alpha += 0.5;
      }
      *outStream << "Finished checking Gauss-Radau (z=-1) differentiation\n";
#endif

#if GAUSS_RADAUP_DIFF
      *outStream << "Begin checking differentiation through Gauss-Radau (z=+1) points\n";
      alpha = -0.5;
      while(alpha <= 5.0){
        beta = -0.5;
        while(beta <= 5.0){

          for(np = NPLOWER; np <= NPUPPER; ++np){
            ipl::zwgrjp(z,w,np,alpha,beta);
            for(n = 2; n < np-1; ++n){
              ipl::Dgrjp(d,z,np,alpha,beta);

              for(i = 0; i < np; ++i) p[i] = std::pow(z[i],n);
              sum = 0;
              for(i = 0; i < np; ++i)
                sum += std::abs(ddot(np,d+i*np,1,p,1) - n*std::pow(z[i],n-1));
              sum /= np;
              if(std::abs(sum)>TEST_EPS) {
                errorFlag = -1000;
                *outStream << "ERROR:  alpha = " << alpha << ", beta = " << beta <<
                              ", np = " << np << ", n = " << n << "  difference " << sum << "\n";
              }
            }
          }
          beta += 0.5;
        }
        *outStream << "finished checking all beta values for alpha = " << alpha << "\n";
        alpha += 0.5;
      }
      *outStream << "Finished checking Gauss-Radau (z=+1) differentiation\n";
#endif

#if GAUSS_RADAUP_DIFF
      *outStream << "Begin checking differentiation through Gauss-Lobatto (z=+1) points\n";
      alpha = -0.5;
      while(alpha <= 5.0){
        beta = -0.5;
        while(beta <= 5.0){

          for(np = NPLOWER; np <= NPUPPER; ++np){
            ipl::zwglj(z,w,np,alpha,beta);
            for(n = 2; n < np-1; ++n){
              ipl::Dglj(d,z,np,alpha,beta);

              for(i = 0; i < np; ++i) p[i] = std::pow(z[i],n);
              sum = 0;
              for(i = 0; i < np; ++i)
                sum += std::abs(ddot(np,d+i*np,1,p,1) - n*std::pow(z[i],n-1));
              sum /= np;
              if(std::abs(sum)>TEST_EPS) {
                errorFlag = -1000;
                *outStream << "ERROR:  alpha = " << alpha << ", beta = " << beta <<
                              ", np = " << np << ", n = " << n << "  difference " << sum << "\n";
              }
            }
          }
          beta += 0.5;
        }
        *outStream << "finished checking all beta values for alpha = " << alpha << "\n";
        alpha += 0.5;
      }
      *outStream << "Finished checking Gauss-Lobatto differentiation\n";
#endif

#if GAUSS_INTERP
      *outStream << "Begin checking interpolation through Gauss points\n";
      alpha = -0.5;
      while(alpha <= 5.0){
        beta = -0.5;
        while(beta <= 5.0){

          for(np = NPLOWER; np <= NPUPPER; ++np){
            ipl::zwgj(z,w,np,alpha,beta);
            for(n = 2; n < np-1; ++n){
              for(i = 0; i < np; ++i) {
                w[i] = 2.0*i/(double)(np-1)-1.0;
                p[i] = std::pow(z[i],n);
              }
              ipl::Imgj(d,z,w,np,np,alpha,beta);
              sum = 0;
              for(i = 0; i < np; ++i)
                sum += std::abs(ddot(np,d+i*np,1,p,1) - std::pow(w[i],n));
              sum /= np;
              if(std::abs(sum)>TEST_EPS) {
                errorFlag = -1000;
                *outStream << "ERROR:  alpha = " << alpha << ", beta = " << beta <<
                              ", np = " << np << ", n = " << n << "  difference " << sum << "\n";
              }
            }
          }
          beta += 0.5;
        }
        *outStream << "finished checking all beta values for alpha = " << alpha << "\n";
        alpha += 0.5;
      }
      *outStream << "Finished checking Gauss Jacobi interpolation\n";
#endif

#if GAUSS_RADAUM_INTERP
      *outStream << "Begin checking interpolation through Gauss-Radau (z=-1) points\n";
      alpha = -0.5;
      while(alpha <= 5.0){
        beta = -0.5;
        while(beta <= 5.0){

          for(np = NPLOWER; np <= NPUPPER; ++np){
            ipl::zwgrjm(z,w,np,alpha,beta);
            for(n = 2; n < np-1; ++n){
              for(i = 0; i < np; ++i) {
                w[i] = 2.0*i/(double)(np-1)-1.0;
                p[i] = std::pow(z[i],n);
              }
              ipl::Imgrjm(d,z,w,np,np,alpha,beta);
              sum = 0;
              for(i = 0; i < np; ++i)
                sum += std::abs(ddot(np,d+i*np,1,p,1) - std::pow(w[i],n));
              sum /= np;
              if(std::abs(sum)>TEST_EPS) {
                errorFlag = -1000;
                *outStream << "ERROR:  alpha = " << alpha << ", beta = " << beta <<
                              ", np = " << np << ", n = " << n << "  difference " << sum << "\n";
              }
            }
          }
          beta += 0.5;
        }
        *outStream << "finished checking all beta values for alpha = " << alpha << "\n";
        alpha += 0.5;
      }
      *outStream << "Finished checking Gauss-Radau (z=-1) interpolation\n";
#endif

#if GAUSS_RADAUP_INTERP
      *outStream << "Begin checking interpolation through Gauss-Radau (z=+1) points\n";
      alpha = -0.5;
      while(alpha <= 5.0){
        beta = -0.5;
        while(beta <= 5.0){

          for(np = NPLOWER; np <= NPUPPER; ++np){
            ipl::zwgrjp(z,w,np,alpha,beta);
            for(n = 2; n < np-1; ++n){
              for(i = 0; i < np; ++i) {
                w[i] = 2.0*i/(double)(np-1)-1.0;
                p[i] = std::pow(z[i],n);
              }
              ipl::Imgrjp(d,z,w,np,np,alpha,beta);
              sum = 0;
              for(i = 0; i < np; ++i)
                sum += std::abs(ddot(np,d+i*np,1,p,1) - std::pow(w[i],n));
              sum /= np;
              if(std::abs(sum)>TEST_EPS) {
                errorFlag = -1000;
                *outStream << "ERROR:  alpha = " << alpha << ", beta = " << beta <<
                              ", np = " << np << ", n = " << n << "  difference " << sum << "\n";
              }
            }
          }
          beta += 0.5;
        }
        *outStream << "finished checking all beta values for alpha = " << alpha << "\n";
        alpha += 0.5;
      }
      *outStream << "Finished checking Gauss-Radau (z=+1) interpolation\n";
#endif

#if GAUSS_LOBATTO_INTERP
      *outStream << "Begin checking interpolation through Gauss-Lobatto points\n";
      alpha = -0.5;
      while(alpha <= 5.0){
        beta = -0.5;
        while(beta <= 5.0){

          for(np = NPLOWER; np <= NPUPPER; ++np){
            ipl::zwglj(z,w,np,alpha,beta);
            for(n = 2; n < np-1; ++n){
              for(i = 0; i < np; ++i) {
                w[i] = 2.0*i/(double)(np-1)-1.0;
                p[i] = std::pow(z[i],n);
              }
              ipl::Imglj(d,z,w,np,np,alpha,beta);
              sum = 0;
              for(i = 0; i < np; ++i)
                sum += std::abs(ddot(np,d+i*np,1,p,1) - std::pow(w[i],n));
              sum /= np;
              if(std::abs(sum)>TEST_EPS) {
                errorFlag = -1000;
                *outStream << "ERROR:  alpha = " << alpha << ", beta = " << beta <<
                              ", np = " << np << ", n = " << n << "  difference " << sum << "\n";
              }
            }
          }
          beta += 0.5;
        }
        *outStream << "finished checking all beta values for alpha = " << alpha << "\n";
        alpha += 0.5;
      }
      *outStream << "Finished checking Gauss-Lobatto interpolation\n";
#endif

      free(z); free(w); free(p); free(d);

      } // end scope

      /******************************************/
      *outStream << "\n";
  }
  catch (std::logic_error err) {
    *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n";
    *outStream << err.what() << '\n';
    *outStream << "-------------------------------------------------------------------------------" << "\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;
}
Example #24
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;
}
Example #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;
}
Example #26
0
/** \brief Performs a code-code comparison to FIAT for Raviart-Thomas bases on triangles (values and divs)
    \param argc [in] - number of command-line arguments
    \param argv [in] - command-line arguments
*/
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 HDIV_TRI_In_FEM                         |\n" \
    << "|                                                                             |\n" \
    << "|     1) Tests triangular Raviart-Thomas basis                                |\n" \
    << "|                                                                             |\n" \
    << "|  Questions? Contact  Pavel Bochev ([email protected]) or                   |\n" \
    << "|                      Denis Ridzal ([email protected]) or                   |\n" \
    << "|                      Robert Kirby ([email protected])                  |\n" \
    << "|                                                                             |\n" \
    << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n" \
    << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
    << "|                                                                             |\n" \
    << "===============================================================================\n";
  
  int errorFlag  = 0;

  // test for basis values, compare against fiat
  try {
    const int deg = 2;
    Basis_HDIV_TRI_In_FEM<double,FieldContainer<double> >  myBasis( deg , POINTTYPE_EQUISPACED );

    // Get a lattice
    const int np_lattice = PointTools::getLatticeSize( myBasis.getBaseCellTopology() , deg , 0 );
    FieldContainer<double> lattice( np_lattice , 2 );
    FieldContainer<double> myBasisValues( myBasis.getCardinality() , np_lattice , 2 );
    PointTools::getLattice<double,FieldContainer<double> >( lattice , 
                                                            myBasis.getBaseCellTopology() , 
                                                            deg , 
                                                            0 , 
                                                            POINTTYPE_EQUISPACED );    

    myBasis.getValues( myBasisValues , lattice , OPERATOR_VALUE );

    const double fiat_vals[] = {
      0.000000000000000e+00, -2.000000000000000e+00,
      2.500000000000000e-01, -5.000000000000000e-01,
      -1.000000000000000e+00, 1.000000000000000e+00,
      0.000000000000000e+00, -2.500000000000000e-01,
      -5.000000000000000e-01, 5.000000000000000e-01,
      0.000000000000000e+00, 0.000000000000000e+00,
      0.000000000000000e+00, 1.000000000000000e+00,
      2.500000000000000e-01, -5.000000000000000e-01,
      2.000000000000000e+00, -2.000000000000000e+00,
      0.000000000000000e+00, 5.000000000000000e-01,
      2.500000000000000e-01, -2.500000000000000e-01,
      0.000000000000000e+00, 0.000000000000000e+00,
      0.000000000000000e+00, 0.000000000000000e+00,
      2.500000000000000e-01, 0.000000000000000e+00,
      2.000000000000000e+00, 0.000000000000000e+00,
      0.000000000000000e+00, -5.000000000000000e-01,
      2.500000000000000e-01, 2.500000000000000e-01,
      0.000000000000000e+00, -1.000000000000000e+00,
      0.000000000000000e+00, 0.000000000000000e+00,
      -5.000000000000000e-01, 0.000000000000000e+00,
      -1.000000000000000e+00, 0.000000000000000e+00,
      0.000000000000000e+00, 2.500000000000000e-01,
      2.500000000000000e-01, 2.500000000000000e-01,
      0.000000000000000e+00, 2.000000000000000e+00,
      1.000000000000000e+00, 0.000000000000000e+00,
      5.000000000000000e-01, 0.000000000000000e+00,
      0.000000000000000e+00, 0.000000000000000e+00,
      -5.000000000000000e-01, 2.500000000000000e-01,
      -2.500000000000000e-01, 2.500000000000000e-01,
      -2.000000000000000e+00, 2.000000000000000e+00,
      -2.000000000000000e+00, 0.000000000000000e+00,
      -2.500000000000000e-01, 0.000000000000000e+00,
      0.000000000000000e+00, 0.000000000000000e+00,
      -5.000000000000000e-01, 2.500000000000000e-01,
      5.000000000000000e-01, -5.000000000000000e-01,
      1.000000000000000e+00, -1.000000000000000e+00,
      0.000000000000000e+00, 0.000000000000000e+00,
      1.500000000000000e+00, 0.000000000000000e+00,
      0.000000000000000e+00, 0.000000000000000e+00,
      0.000000000000000e+00, 7.500000000000000e-01,
      7.500000000000000e-01, -7.500000000000000e-01,
      0.000000000000000e+00, 0.000000000000000e+00,
      0.000000000000000e+00, 0.000000000000000e+00,
      7.500000000000000e-01, 0.000000000000000e+00,
      0.000000000000000e+00, 0.000000000000000e+00,
      0.000000000000000e+00, 1.500000000000000e+00,
      -7.500000000000000e-01, 7.500000000000000e-01,
      0.000000000000000e+00, 0.000000000000000e+00
    };

    int cur=0;
    for (int i=0;i<myBasisValues.dimension(0);i++) {
      for (int j=0;j<myBasisValues.dimension(1);j++) {
        for (int k=0;k<myBasisValues.dimension(2);k++) {
          if (std::abs( myBasisValues(i,j,k) - fiat_vals[cur] ) > 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 << " " << j << " " << k;
            *outStream << "}  computed value: " << myBasisValues(i,j,k)
                      << " but correct value: " << fiat_vals[cur] << "\n";
            *outStream << "Difference: " << std::abs( myBasisValues(i,j,k) - fiat_vals[cur] ) << "\n";
          }
          cur++;
        }
      }
    }
  }
  catch (std::exception err) {
    *outStream << err.what() << "\n\n";
    errorFlag = -1000;
  }
  try {
    const int deg = 2;
    Basis_HDIV_TRI_In_FEM<double,FieldContainer<double> >  myBasis( deg , POINTTYPE_EQUISPACED );

    // Get a lattice
    const int np_lattice = PointTools::getLatticeSize( myBasis.getBaseCellTopology() , deg , 0 );
    FieldContainer<double> lattice( np_lattice , 2 );
    FieldContainer<double> myBasisDivs( myBasis.getCardinality() , np_lattice );
    PointTools::getLattice<double,FieldContainer<double> >( lattice , 
                                                            myBasis.getBaseCellTopology() , 
                                                            deg , 
                                                            0 , 
                                                            POINTTYPE_EQUISPACED );    

    myBasis.getValues( myBasisDivs , lattice , OPERATOR_DIV );


    const double fiat_divs[] = {
      7.000000000000000e+00,
      2.500000000000000e+00,
      -2.000000000000000e+00,
      2.500000000000000e+00,
      -2.000000000000000e+00,
      -2.000000000000000e+00,
      -2.000000000000000e+00,
      2.500000000000000e+00,
      7.000000000000000e+00,
      -2.000000000000000e+00,
      2.500000000000000e+00,
      -2.000000000000000e+00,
      -2.000000000000000e+00,
      2.500000000000000e+00,
      7.000000000000000e+00,
      -2.000000000000000e+00,
      2.500000000000000e+00,
      -2.000000000000000e+00,
      -2.000000000000000e+00,
      -2.000000000000000e+00,
      -2.000000000000000e+00,
      2.500000000000000e+00,
      2.500000000000000e+00,
      7.000000000000000e+00,
      -2.000000000000000e+00,
      -2.000000000000000e+00,
      -2.000000000000000e+00,
      2.500000000000000e+00,
      2.500000000000000e+00,
      7.000000000000000e+00,
      7.000000000000000e+00,
      2.500000000000000e+00,
      -2.000000000000000e+00,
      2.500000000000000e+00,
      -2.000000000000000e+00,
      -2.000000000000000e+00,
      9.000000000000000e+00,
      0.000000000000000e+00,
      -9.000000000000000e+00,
      4.500000000000000e+00,
      -4.500000000000000e+00,
      0.000000000000000e+00,
      9.000000000000000e+00,
      4.500000000000000e+00,
      0.000000000000000e+00,
      0.000000000000000e+00,
      -4.500000000000000e+00,
      -9.000000000000000e+00
    };

    int cur=0;
    for (int i=0;i<myBasisDivs.dimension(0);i++) {
      for (int j=0;j<myBasisDivs.dimension(1);j++) {
        if (std::abs( myBasisDivs(i,j) - fiat_divs[cur] ) > 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 << " " << j;
          *outStream << "}  computed value: " << myBasisDivs(i,j)
                    << " but correct value: " << fiat_divs[cur] << "\n";
          *outStream << "Difference: " << std::abs( myBasisDivs(i,j) - fiat_divs[cur] ) << "\n";
        }
        cur++;
      }
    }
  }
  catch (std::exception 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;
}
Example #27
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 (CubatureDirect,CubatureTensor,DefaultCubatureFactory)       |\n" \
  << "|                                                                             |\n" \
  << "|     1) Computing integrals of monomials on reference cells in 3D            |\n" \
  << "|                         - using Level 2 BLAS -                              |\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: integrals of monomials in 3D (Level 2 BLAS version)                 |\n"\
  << "===============================================================================\n";

  // internal variables:
  int                                      errorFlag = 0;
  int                                      polyCt = 0;
  int                                      offset = 0;
  Teuchos::Array< Teuchos::Array<double> > testInt;
  Teuchos::Array< Teuchos::Array<double> > analyticInt;
  Teuchos::Array<double>                   tmparray(1);
  double                                   reltol = 1.0e+04 * INTREPID_TOL;
  int                                      maxDeg[4];
  int                                      maxOffset[4];
  int                                      numPoly[4];
  int                                      numAnalytic[4];
  // max polynomial degree tested, per cell type:
  maxDeg[0]                              = INTREPID2_CUBATURE_TET_DEFAULT_MAX;
  maxDeg[1]                              = 20; // can be as large as INTREPID2_CUBATURE_LINE_GAUSS_MAX, but runtime is excessive
  maxDeg[2]                              = std::min(INTREPID2_CUBATURE_LINE_GAUSS_MAX, INTREPID2_CUBATURE_TRI_DEFAULT_MAX);
  maxDeg[3]                              = std::min(INTREPID2_CUBATURE_LINE_GAUSS_MAX, INTREPID2_CUBATURE_LINE_GAUSSJACOBI20_MAX);
  // max polynomial degree recorded in analytic comparison files, per cell type:
  maxOffset[0]                           = INTREPID2_CUBATURE_TET_DEFAULT_MAX;
  maxOffset[1]                           = INTREPID2_CUBATURE_LINE_GAUSS_MAX;
  maxOffset[2]                           = std::min(INTREPID2_CUBATURE_LINE_GAUSS_MAX, INTREPID2_CUBATURE_TRI_DEFAULT_MAX);
  maxOffset[3]                           = std::min(INTREPID2_CUBATURE_LINE_GAUSS_MAX, INTREPID2_CUBATURE_LINE_GAUSSJACOBI20_MAX);
  for (int i=0; i<4; i++) {
    numPoly[i] = (maxDeg[i]+1)*(maxDeg[i]+2)*(maxDeg[i]+3)/6;
  }
  for (int i=0; i<4; i++) {
    numAnalytic[i] = (maxOffset[i]+1)*(maxOffset[i]+2)*(maxOffset[i]+3)/6;
  }


  // get names of files with analytic values
  std::string basedir = "./data";
  std::stringstream namestream[4];
  std::string filename[4];
  namestream[0] << basedir << "/TET_integrals" << ".dat";
  namestream[0] >> filename[0];
  namestream[1] << basedir << "/HEX_integrals" << ".dat";
  namestream[1] >> filename[1];
  namestream[2] << basedir << "/TRIPRISM_integrals" << ".dat";
  namestream[2] >> filename[2];
  namestream[3] << basedir << "/PYR_integrals" << ".dat";
  namestream[3] >> filename[3];

  // reference cells tested
  shards::CellTopology cellType[] = {shards::getCellTopologyData< shards::Tetrahedron<> >(),
                                     shards::getCellTopologyData< shards::Hexahedron<> >(),
                                     shards::getCellTopologyData< shards::Wedge<> >(),
                                     shards::getCellTopologyData< shards::Pyramid<> >() };
  // format of data files with analytic values
  TypeOfExactData dataFormat[] = {INTREPID2_UTILS_SCALAR, INTREPID_UTILS_FRACTION, INTREPID_UTILS_FRACTION, INTREPID_UTILS_FRACTION};

  // compute and compare integrals
  try {
    for (int cellCt=0; cellCt < 4; cellCt++) {
      testInt.assign(numPoly[cellCt], tmparray);
      analyticInt.assign(numAnalytic[cellCt], tmparray);

      *outStream << "\nIntegrals of monomials on a reference " << cellType[cellCt].getBaseCellTopologyData()->name << ":\n";
      std::ifstream filecompare(&filename[cellCt][0]);
      // compute integrals
      for (int cubDeg=0; cubDeg <= maxDeg[cellCt]; cubDeg++) {
        int numMonomials = (cubDeg+1)*(cubDeg+2)*(cubDeg+3)/6; 
        testInt[cubDeg].resize(numMonomials);
        computeIntegral(testInt[cubDeg], cellType[cellCt], cubDeg);
      }
      // get analytic values
      if (filecompare.is_open()) {
        getAnalytic(analyticInt, filecompare, dataFormat[cellCt]);
        // close file
        filecompare.close();
      }
      // perform comparison
      for (int cubDeg=0; cubDeg <= maxDeg[cellCt]; cubDeg++) {
        polyCt = 0;
        offset = 0;
        int oldErrorFlag = errorFlag;
        for (int xDeg=0; xDeg <= cubDeg; xDeg++) {
          for (int yDeg=0; yDeg <= cubDeg-xDeg; yDeg++) {
            for (int zDeg=0; zDeg <= cubDeg-xDeg-yDeg; zDeg++) {
              double abstol = ( analyticInt[polyCt+offset][0] == 0.0 ? reltol : std::fabs(reltol*analyticInt[polyCt+offset][0]) );
              double absdiff = std::fabs(analyticInt[polyCt+offset][0] - testInt[cubDeg][polyCt]);
              if (absdiff > abstol) {
                *outStream << "Cubature order " << std::setw(2) << std::left << cubDeg << " integrating "
                           << "x^" << std::setw(2) << std::left << xDeg << " * y^" << std::setw(2) << yDeg
                           << " * z^" << std::setw(2) << zDeg << ":" << "   "
                           << std::scientific << std::setprecision(16)
                           << testInt[cubDeg][polyCt] << "   " << analyticInt[polyCt+offset][0] << "   "
                           << std::setprecision(4) << absdiff << "   " << "<?" << "   " << abstol << "\n";
                errorFlag++;
                *outStream << std::right << std::setw(118) << "^^^^---FAILURE!\n";
              }
              polyCt++;
            }
            offset = offset + maxOffset[cellCt] - cubDeg;
          }
          offset = offset + (maxOffset[cellCt] - cubDeg)*(maxOffset[cellCt] - cubDeg + 1)/2;
        }
        *outStream << "Cubature order " << std::setw(2) << std::left << cubDeg;
        if (errorFlag == oldErrorFlag)
         *outStream << " passed.\n";
        else
         *outStream << " failed.\n";
      }
      *outStream << "\n";
    }  // end for cellCt
  }
  catch (std::logic_error err) {
    *outStream << err.what() << "\n";
    errorFlag = -1;
  };


  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;
}
Example #28
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_HEX_In_FEM)                         |\n" \
    << "|                                                                             |\n" \
    << "| 1) Patch test involving H(div) matrices                                     |\n" \
    << "|    for the Dirichlet problem on a hexahedron                                |\n" \
    << "|    Omega with boundary Gamma.                                               |\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: Patch test                                                          |\n" \
    << "===============================================================================\n";
  
  
  int errorFlag = 0;
  
  outStream -> precision(16);
  
  try {
    DefaultCubatureFactory<double> cubFactory;                                           // create cubature factory
    shards::CellTopology cell(shards::getCellTopologyData< shards::Hexahedron<> >());    // create parent cell topology
    shards::CellTopology side(shards::getCellTopologyData< shards::Quadrilateral<> >()); // create relevant subcell (side) topology
    shards::CellTopology line(shards::getCellTopologyData< shards::Line<> >() );         // for getting points to construct the basis
    
    int cellDim = cell.getDimension();
    int sideDim = side.getDimension();
    
    int min_order = 0;
    int max_order = 3;
    
    int numIntervals = 2;
    int numInterpPoints = (numIntervals + 1)*(numIntervals + 1)*(numIntervals+1);
    FieldContainer<double> interp_points_ref(numInterpPoints, cellDim);
    int counter = 0;
    for (int k=0;k<numIntervals;k++) {
      for (int j=0; j<=numIntervals; j++) {
	for (int i=0; i<=numIntervals; i++) {
          interp_points_ref(counter,0) = i*(1.0/numIntervals);
          interp_points_ref(counter,1) = j*(1.0/numIntervals);
          interp_points_ref(counter,2) = k*(1.0/numIntervals);
          counter++;
        }
      }
    }
    
    for (int basis_order=min_order;basis_order<=max_order;basis_order++) {
      // create bases
      // get the points for the vector basis
      Teuchos::RCP<Basis<double,FieldContainer<double> > > vectorBasis =
        Teuchos::rcp(new Basis_HDIV_HEX_In_FEM<double,FieldContainer<double> >(basis_order+1,POINTTYPE_SPECTRAL) );

      Teuchos::RCP<Basis<double,FieldContainer<double> > > scalarBasis =
	Teuchos::rcp(new Basis_HGRAD_HEX_Cn_FEM<double,FieldContainer<double> >(basis_order,POINTTYPE_SPECTRAL) );
      
      int numVectorFields = vectorBasis->getCardinality();
      int numScalarFields = scalarBasis->getCardinality();
      int numTotalFields = numVectorFields + numScalarFields;
      
      // create cubatures
      Teuchos::RCP<Cubature<double> > cellCub = cubFactory.create(cell, 2*(basis_order+1));
      Teuchos::RCP<Cubature<double> > sideCub = cubFactory.create(side, 2*(basis_order+1));
      
      int numCubPointsCell = cellCub->getNumPoints();
      int numCubPointsSide = sideCub->getNumPoints();
      
      // hold cubature information
      FieldContainer<double> cub_points_cell(numCubPointsCell, cellDim);
      FieldContainer<double> cub_weights_cell(numCubPointsCell);
      FieldContainer<double> cub_points_side( numCubPointsSide, sideDim );
      FieldContainer<double> cub_weights_side( numCubPointsSide );
      FieldContainer<double> cub_points_side_refcell( numCubPointsSide , cellDim );
      
      // hold basis function information on refcell
      FieldContainer<double> value_of_v_basis_at_cub_points_cell(numVectorFields, numCubPointsCell, cellDim );
      FieldContainer<double> w_value_of_v_basis_at_cub_points_cell(1, numVectorFields, numCubPointsCell, cellDim);
      FieldContainer<double> div_of_v_basis_at_cub_points_cell( numVectorFields, numCubPointsCell );
      FieldContainer<double> w_div_of_v_basis_at_cub_points_cell( 1, numVectorFields , numCubPointsCell );
      FieldContainer<double> value_of_s_basis_at_cub_points_cell(numScalarFields,numCubPointsCell);
      FieldContainer<double> w_value_of_s_basis_at_cub_points_cell(1,numScalarFields,numCubPointsCell);
      
      // containers for side integration:
      // I just need the normal component of the vector basis
      // and the exact solution at the cub points
      FieldContainer<double> value_of_v_basis_at_cub_points_side(numVectorFields,numCubPointsSide,cellDim);
      FieldContainer<double> n_of_v_basis_at_cub_points_side(numVectorFields,numCubPointsSide);
      FieldContainer<double> w_n_of_v_basis_at_cub_points_side(1,numVectorFields,numCubPointsSide);
      FieldContainer<double> diri_data_at_cub_points_side(1,numCubPointsSide);
      FieldContainer<double> side_normal(cellDim);
      
      // holds rhs data
      FieldContainer<double> rhs_at_cub_points_cell(1,numCubPointsCell);
      
      // FEM matrices and vectors
      FieldContainer<double> fe_matrix_M(1,numVectorFields,numVectorFields);
      FieldContainer<double> fe_matrix_B(1,numVectorFields,numScalarFields);
      FieldContainer<double> fe_matrix(1,numTotalFields,numTotalFields);
      
      FieldContainer<double> rhs_vector_vec(1,numVectorFields);
      FieldContainer<double> rhs_vector_scal(1,numScalarFields);
      FieldContainer<double> rhs_and_soln_vec(1,numTotalFields);
      
      FieldContainer<int> ipiv(numTotalFields);
      FieldContainer<double> value_of_s_basis_at_interp_points( numScalarFields , numInterpPoints);
      FieldContainer<double> interpolant( 1 , numInterpPoints );
      
      // set test tolerance
      double zero = (basis_order+1)*(basis_order+1)*1000.0*INTREPID_TOL;
      
      // build matrices outside the loop, and then just do the rhs
      // for each iteration
      
      cellCub->getCubature(cub_points_cell, cub_weights_cell);
      sideCub->getCubature(cub_points_side, cub_weights_side);
      
      // need the vector basis & its divergences
      vectorBasis->getValues(value_of_v_basis_at_cub_points_cell,
                             cub_points_cell,
                             OPERATOR_VALUE);
      vectorBasis->getValues(div_of_v_basis_at_cub_points_cell,
                             cub_points_cell,
                             OPERATOR_DIV);
      
      // need the scalar basis as well
      scalarBasis->getValues(value_of_s_basis_at_cub_points_cell,
                             cub_points_cell,
                             OPERATOR_VALUE);
      
      // construct mass matrix
      cub_weights_cell.resize(1,numCubPointsCell);
      FunctionSpaceTools::multiplyMeasure<double>(w_value_of_v_basis_at_cub_points_cell ,
                                                  cub_weights_cell ,
                                                  value_of_v_basis_at_cub_points_cell ); 
      cub_weights_cell.resize(numCubPointsCell);
      
      
      value_of_v_basis_at_cub_points_cell.resize( 1 , numVectorFields , numCubPointsCell , cellDim );
      FunctionSpaceTools::integrate<double>(fe_matrix_M,
                                            w_value_of_v_basis_at_cub_points_cell ,
                                            value_of_v_basis_at_cub_points_cell ,
                                            COMP_BLAS );
      value_of_v_basis_at_cub_points_cell.resize( numVectorFields , numCubPointsCell , cellDim );
      
      // div matrix
      cub_weights_cell.resize(1,numCubPointsCell);
      FunctionSpaceTools::multiplyMeasure<double>(w_div_of_v_basis_at_cub_points_cell,
                                                  cub_weights_cell,
                                                  div_of_v_basis_at_cub_points_cell);
      cub_weights_cell.resize(numCubPointsCell);
      
      value_of_s_basis_at_cub_points_cell.resize(1,numScalarFields,numCubPointsCell);
      FunctionSpaceTools::integrate<double>(fe_matrix_B,
                                            w_div_of_v_basis_at_cub_points_cell ,
                                            value_of_s_basis_at_cub_points_cell ,
                                            COMP_BLAS );
      value_of_s_basis_at_cub_points_cell.resize(numScalarFields,numCubPointsCell);
      
      for (int x_order=0;x_order<=basis_order;x_order++) {
        for (int y_order=0;y_order<=basis_order;y_order++) {
          for (int z_order=0;z_order<=basis_order;z_order++) {
            
            
            // reset global matrix since I destroyed it in LU factorization.
            fe_matrix.initialize();
            // insert mass matrix into global matrix
            for (int i=0;i<numVectorFields;i++) {
              for (int j=0;j<numVectorFields;j++) {
                fe_matrix(0,i,j) = fe_matrix_M(0,i,j);
              }
            }
            
            // insert div matrix into global matrix
            for (int i=0;i<numVectorFields;i++) {
              for (int j=0;j<numScalarFields;j++) {
                fe_matrix(0,i,numVectorFields+j)=-fe_matrix_B(0,i,j);
                fe_matrix(0,j+numVectorFields,i)=fe_matrix_B(0,i,j);
              }
            }
            
            // clear old vector data
            rhs_vector_vec.initialize();
            rhs_vector_scal.initialize();
            rhs_and_soln_vec.initialize();
            
            // now get rhs vector
            // rhs_vector_scal is just (rhs,w) for w in the scalar basis
            // I already have the scalar basis tabulated.
            cub_points_cell.resize(1,numCubPointsCell,cellDim);
            rhsFunc(rhs_at_cub_points_cell,
                    cub_points_cell,
                    x_order,
                    y_order,
                    z_order);
            
            cub_points_cell.resize(numCubPointsCell,cellDim);
            
            cub_weights_cell.resize(1,numCubPointsCell);
            FunctionSpaceTools::multiplyMeasure<double>(w_value_of_s_basis_at_cub_points_cell,
                                                        cub_weights_cell,
                                                        value_of_s_basis_at_cub_points_cell);
            cub_weights_cell.resize(numCubPointsCell);
            FunctionSpaceTools::integrate<double>(rhs_vector_scal,
                                                  rhs_at_cub_points_cell,
                                                  w_value_of_s_basis_at_cub_points_cell,
                                                  COMP_BLAS);

            for (int i=0;i<numScalarFields;i++) {
              rhs_and_soln_vec(0,numVectorFields+i) = rhs_vector_scal(0,i);
            }
            
            
            // now get <u,v.n> on boundary
            for (unsigned side_cur=0;side_cur<6;side_cur++) {
              // map side cubature to current side
              CellTools<double>::mapToReferenceSubcell( cub_points_side_refcell ,
                                                        cub_points_side ,
                                                        sideDim ,
                                                        (int)side_cur ,
                                                        cell );
              // Evaluate dirichlet data
              cub_points_side_refcell.resize(1,numCubPointsSide,cellDim);
              u_exact(diri_data_at_cub_points_side,
                      cub_points_side_refcell,x_order,y_order,z_order);

              cub_points_side_refcell.resize(numCubPointsSide,cellDim);
              
              // get normal direction, this has the edge weight factored into it already
              CellTools<double>::getReferenceSideNormal(side_normal , 
                                                        (int)side_cur,cell );

              // v.n at cub points on side
              vectorBasis->getValues(value_of_v_basis_at_cub_points_side ,
                                    cub_points_side_refcell ,
                                    OPERATOR_VALUE );

              for (int i=0;i<numVectorFields;i++) {
                for (int j=0;j<numCubPointsSide;j++) {
                  n_of_v_basis_at_cub_points_side(i,j) = 0.0;
                  for (int k=0;k<cellDim;k++) {
                    n_of_v_basis_at_cub_points_side(i,j) += side_normal(k) * 
                      value_of_v_basis_at_cub_points_side(i,j,k);
                  }
                } 
              }
              
              cub_weights_side.resize(1,numCubPointsSide);
              FunctionSpaceTools::multiplyMeasure<double>(w_n_of_v_basis_at_cub_points_side,
                                                          cub_weights_side,
                                                          n_of_v_basis_at_cub_points_side);
              cub_weights_side.resize(numCubPointsSide);
              
              FunctionSpaceTools::integrate<double>(rhs_vector_vec,
                                                    diri_data_at_cub_points_side,
                                                    w_n_of_v_basis_at_cub_points_side,
                                                    COMP_BLAS,
                                                    false);

              for (int i=0;i<numVectorFields;i++) {
                rhs_and_soln_vec(0,i) -= rhs_vector_vec(0,i);
              }
              
            }
            
            // solve linear system
            int info = 0;
            Teuchos::LAPACK<int, double> solver;
            solver.GESV(numTotalFields, 1, &fe_matrix(0,0,0), numTotalFields, &ipiv(0), &rhs_and_soln_vec(0,0), 
                        numTotalFields, &info);
            
            // compute interpolant; the scalar entries are last
            scalarBasis->getValues(value_of_s_basis_at_interp_points,
                                  interp_points_ref,
                                  OPERATOR_VALUE);
            for (int pt=0;pt<numInterpPoints;pt++) {
              interpolant(0,pt)=0.0;
              for (int i=0;i<numScalarFields;i++) {
                interpolant(0,pt) += rhs_and_soln_vec(0,numVectorFields+i)
                  * value_of_s_basis_at_interp_points(i,pt);
              }
            }
            
            interp_points_ref.resize(1,numInterpPoints,cellDim);
            // get exact solution for comparison
            FieldContainer<double> exact_solution(1,numInterpPoints);
            u_exact( exact_solution , interp_points_ref , x_order, y_order, z_order);
            interp_points_ref.resize(numInterpPoints,cellDim);

            RealSpaceTools<double>::add(interpolant,exact_solution);
            
            double nrm= RealSpaceTools<double>::vectorNorm(&interpolant(0,0),interpolant.dimension(1), NORM_TWO);

            *outStream << "\nNorm-2 error between scalar components of exact solution of order ("
                       << x_order << ", " << y_order << ", " << z_order
                       << ") and finite element interpolant of order " << basis_order << ": "
                       << nrm << "\n";

            if (nrm > zero) {
              *outStream << "\n\nPatch test failed for solution polynomial order ("
                         << x_order << ", " << y_order << ", " << z_order << ") and basis order (scalar, vector)  ("
                         << basis_order << ", " << basis_order+1 << ")\n\n";
              errorFlag++;
            }
            
          }
        }
      }
    }
    
  }
  
  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;
}
Example #29
0
    int Integration_Test10(const bool verbose) {

      Teuchos::RCP<std::ostream> outStream;
      Teuchos::oblackholestream bhs; // outputs nothing

      if (verbose)
        outStream = Teuchos::rcp(&std::cout, false);
      else
        outStream = Teuchos::rcp(&bhs, false);

      Teuchos::oblackholestream oldFormatState;
      oldFormatState.copyfmt(std::cout);

      typedef typename
        Kokkos::Impl::is_space<DeviceSpaceType>::host_mirror_space::execution_space HostSpaceType ;

      *outStream << "DeviceSpace::  "; DeviceSpaceType::print_configuration(*outStream, false);
      *outStream << "HostSpace::    ";   HostSpaceType::print_configuration(*outStream, false);
 
      *outStream
        << "===============================================================================\n"
        << "|                                                                             |\n"
        << "|                 Unit Test (CubaturePolylib)                                 |\n"
        << "|                                                                             |\n"
        << "|     1) Computing integrals of monomials on reference cells in 1D            |\n"
        << "|                                                                             |\n"
        << "|  Questions? Contact  Pavel Bochev ([email protected]) or                   |\n"
        << "|                      Denis Ridzal ([email protected]) or                   |\n"
        << "|                      Kyungjoo Kim ([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: integrals of monomials in 1D                                        |\n"
        << "===============================================================================\n";

      typedef Kokkos::DynRankView<ValueType,DeviceSpaceType> DynRankView;
#define ConstructWithLabel(obj, ...) obj(#obj, __VA_ARGS__)

      typedef ValueType pointValueType;
      typedef ValueType weightValueType;
      typedef CubaturePolylib<DeviceSpaceType,pointValueType,weightValueType> CubatureLineType;

      const auto tol = 10.0 * tolerence();

      int errorFlag = 0;

      // open file with analytic values
      std::string basedir = "../data";
      std::stringstream namestream;
      std::string filename;
      namestream <<  basedir << "/EDGE_integrals" << ".dat";
      namestream >> filename;
      *outStream << "filename = "  << filename << std::endl;
      std::ifstream filecompare(filename);

      *outStream << "\n-> Integrals of monomials on a reference line (edge):\n";

      // compute and compare integrals
      try {
        const auto maxDeg   = Parameters::MaxCubatureDegreeEdge;
        const auto polySize = maxDeg + 1;

        // test inegral values
        DynRankView ConstructWithLabel(testInt, maxDeg+1, polySize);
        
        // analytic integral values
        DynRankView ConstructWithLabel(analyticInt, maxDeg+1, polySize);

        // get analytic values
        if (filecompare.is_open()) {
          getAnalytic(analyticInt, filecompare);
          filecompare.close();
        } else {
          INTREPID2_TEST_FOR_EXCEPTION( true, std::runtime_error,
                                        ">>> ERROR (Integration::Test02): Cannot open analytic solution file" );
        }
        
        // storage for cubatrue points and weights
        DynRankView ConstructWithLabel(cubPoints, 
                                       Parameters::MaxIntegrationPoints, 
                                       Parameters::MaxDimension);

        DynRankView ConstructWithLabel(cubWeights, 
                                       Parameters::MaxIntegrationPoints);
        
        // compute integrals
        EPolyType polyType[4] = { POLYTYPE_GAUSS,
                                  POLYTYPE_GAUSS_RADAU_LEFT,
                                  POLYTYPE_GAUSS_RADAU_RIGHT,
                                  POLYTYPE_GAUSS_LOBATTO };
        for (size_type pid=0;pid<4;++pid) {
          const auto ptype = polyType[pid];
          *outStream << "\n  -> Testing poly type " << EPolyTypeToString(ptype) << "\n";

          for (size_type cubDeg=0;cubDeg<=maxDeg;++cubDeg) {
            CubatureLineType lineCub(cubDeg, ptype);
            for (auto polyDeg=0;polyDeg<=cubDeg;++polyDeg) 
              testInt(cubDeg, polyDeg) = computeIntegralOfMonomial<ValueType>(lineCub,
                                                                              cubPoints,
                                                                              cubWeights,
                                                                              polyDeg);
          }
                    
          // perform comparison
          for (size_type cubDeg=0;cubDeg<=maxDeg;++cubDeg) {
            for (auto polyDeg=0;polyDeg<=cubDeg;++polyDeg) {
              const auto abstol  = ( analyticInt(polyDeg,0) == 0 ? tol : std::fabs(tol*analyticInt(polyDeg,0)) );
              const auto absdiff = std::fabs(analyticInt(polyDeg,0) - testInt(cubDeg,polyDeg));
              *outStream << "Cubature order " << std::setw(2) << std::left << cubDeg << " integrating "
                         << "x^" << std::setw(2) << std::left << polyDeg <<  ":" << "   "
                         << std::scientific << std::setprecision(16) << testInt(cubDeg,polyDeg) << "   " << analyticInt(polyDeg,0) << "   "
                         << std::setprecision(4) << absdiff << "   " << "<?" << "   " << abstol << "\n";
              if (absdiff > abstol) {
                errorFlag++;
                *outStream << std::right << std::setw(104) << "^^^^---FAILURE!\n";
              }
            }
            *outStream << "\n";
          }
        } 
      } catch (std::logic_error err) {
        *outStream << err.what() << "\n";
        errorFlag = -1;
      }
      
      
      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;
    }
Example #30
0
int main(int argc, char *argv[]) {
Kokkos::initialize();
  //Check number of arguments
   if (argc < 4) {
      std::cout <<"\n>>> ERROR: Invalid number of arguments.\n\n";
      std::cout <<"Usage:\n\n";
      std::cout <<"  ./Intrepid_example_Drivers_Example_06.exe deg NX NY verbose\n\n";
      std::cout <<" where \n";
      std::cout <<"   int deg             - polynomial degree to be used (assumed > 1) \n";
      std::cout <<"   int NX              - num intervals in x direction (assumed box domain, 0,1) \n";
      std::cout <<"   int NY              - num intervals in y direction (assumed box domain, 0,1) \n";
      std::cout <<"   verbose (optional)  - any character, indicates verbose output \n\n";
      exit(1);
   }
  
  // 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 > 2)
    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" \
    << "|  Example: Apply Stiffness Matrix for                                        |\n" \
    << "|                   Poisson Equation on Quadrilateral Mesh                    |\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";

  
  // ************************************ GET INPUTS **************************************
  
  int deg          = atoi(argv[1]);  // polynomial degree to use
  int NX            = atoi(argv[2]);  // num intervals in x direction (assumed box domain, 0,1)
  int NY            = atoi(argv[3]);  // num intervals in y direction (assumed box domain, 0,1)
  

  // *********************************** CELL TOPOLOGY **********************************
  
  // Get cell topology for base hexahedron
  typedef shards::CellTopology    CellTopology;
  CellTopology quad_4(shards::getCellTopologyData<shards::Quadrilateral<4> >() );
  
  // Get dimensions 
  int numNodesPerElem = quad_4.getNodeCount();
  int spaceDim = quad_4.getDimension();
  
  // *********************************** GENERATE MESH ************************************
  
  *outStream << "Generating mesh ... \n\n";
  
  *outStream << "   NX" << "   NY\n";
  *outStream << std::setw(5) << NX <<
    std::setw(5) << NY << "\n\n";
  
  // Print mesh information
  int numElems = NX*NY;
  int numNodes = (NX+1)*(NY+1);
  *outStream << " Number of Elements: " << numElems << " \n";
  *outStream << "    Number of Nodes: " << numNodes << " \n\n";
  
  // Square
  double leftX = 0.0, rightX = 1.0;
  double leftY = 0.0, rightY = 1.0;

  // Mesh spacing
  double hx = (rightX-leftX)/((double)NX);
  double hy = (rightY-leftY)/((double)NY);

  // Get nodal coordinates
  FieldContainer<double> nodeCoord(numNodes, spaceDim);
  FieldContainer<int> nodeOnBoundary(numNodes);
  int inode = 0;
  for (int j=0; j<NY+1; j++) {
    for (int i=0; i<NX+1; i++) {
      nodeCoord(inode,0) = leftX + (double)i*hx;
      nodeCoord(inode,1) = leftY + (double)j*hy;
      if (j==0 || i==0 || j==NY || i==NX){
	nodeOnBoundary(inode)=1;
      }
      else {
	nodeOnBoundary(inode)=0;
      }
      inode++;
    }
  }
#define DUMP_DATA
#ifdef DUMP_DATA
  // Print nodal coords
  ofstream fcoordout("coords.dat");
  for (int i=0; i<numNodes; i++) {
    fcoordout << nodeCoord(i,0) <<" ";
    fcoordout << nodeCoord(i,1) <<"\n";
  }
  fcoordout.close();
#endif
  
  
  // Element to Node map
  // We'll keep it around, but this is only the DOFMap if you are in the lowest order case.
  FieldContainer<int> elemToNode(numElems, numNodesPerElem);
  int ielem = 0;
  for (int j=0; j<NY; j++) {
    for (int i=0; i<NX; i++) {
      elemToNode(ielem,0) = (NX + 1)*j + i;
      elemToNode(ielem,1) = (NX + 1)*j + i + 1;
      elemToNode(ielem,2) = (NX + 1)*(j + 1) + i + 1;
      elemToNode(ielem,3) = (NX + 1)*(j + 1) + i;
      ielem++;
    }
  }
#ifdef DUMP_DATA
  // Output connectivity
  ofstream fe2nout("elem2node.dat");
  for (int j=0; j<NY; j++) {
    for (int i=0; i<NX; i++) {
      int ielem = i + j * NX;
      for (int m=0; m<numNodesPerElem; m++){
	fe2nout << elemToNode(ielem,m) <<"  ";
      }
      fe2nout <<"\n";
    }
  }
  fe2nout.close();
#endif
  
  // ************************************ CUBATURE ************************************** 
  *outStream << "Getting cubature ... \n\n";
  
  // Get numerical integration points and weights
  DefaultCubatureFactory<double>  cubFactory;                                   
  int cubDegree = 2*deg;
  Teuchos::RCP<Cubature<double> > quadCub = cubFactory.create(quad_4, cubDegree); 
  
  int cubDim       = quadCub->getDimension();
  int numCubPoints = quadCub->getNumPoints();
  
  FieldContainer<double> cubPoints(numCubPoints, cubDim);
  FieldContainer<double> cubWeights(numCubPoints);
  
  quadCub->getCubature(cubPoints, cubWeights);
  

  // ************************************** BASIS ***************************************
  
  *outStream << "Getting basis ... \n\n";
  
  // Define basis 
  Basis_HGRAD_QUAD_Cn_FEM<double, FieldContainer<double> > quadHGradBasis(deg,POINTTYPE_SPECTRAL);
  int numFieldsG = quadHGradBasis.getCardinality();
  FieldContainer<double> quadGVals(numFieldsG, numCubPoints); 
  FieldContainer<double> quadGrads(numFieldsG, numCubPoints, spaceDim); 
  
  // Evaluate basis values and gradients at cubature points
  quadHGradBasis.getValues(quadGVals, cubPoints, OPERATOR_VALUE);
  quadHGradBasis.getValues(quadGrads, cubPoints, OPERATOR_GRAD);

  // create the local-global mapping for higher order elements
  FieldContainer<int> ltgMapping(numElems,numFieldsG);
  const int numDOF = (NX*deg+1)*(NY*deg+1);
  ielem=0;
  for (int j=0;j<NY;j++) {
    for (int i=0;i<NX;i++) {
      const int start = deg * j * ( NX * deg + 1 ) + i * deg;
      // loop over local dof on this cell
      int local_dof_cur=0;
      for (int vertical=0;vertical<=deg;vertical++) {
	for (int horizontal=0;horizontal<=deg;horizontal++) {
	  ltgMapping(ielem,local_dof_cur) = start + vertical*(NX*deg+1)+horizontal;
	  local_dof_cur++;
	}
      }
      ielem++;
    }
  }
#ifdef DUMP_DATA
  // Output ltg mapping
//   ofstream ltgout("ltg.dat");
//   for (int j=0; j<NY; j++) {
//     for (int i=0; i<NX; i++) {
//       int ielem = i + j * NX;
//       for (int m=0; m<numFieldsG; m++){
// 	ltgout << ltgMapping(ielem,m) <<"  ";
//       }
//       ltgout <<"\n";
//     }
//   }
//   ltgout.close();
#endif
  
  // ******** CREATE A SINGLE STIFFNESS MATRIX, WHICH IS REPLICATED ON ALL ELEMENTS *********
  *outStream << "Applying stiffness matrix and right hand side ... \n\n";

  // Settings and data structures for mass and stiffness matrices
  typedef CellTools<double>  CellTools;
  typedef FunctionSpaceTools fst;
  int numCells = 1; 

  // Container for nodes
  FieldContainer<double> refQuadNodes(numCells, numNodesPerElem, spaceDim);
  // Containers for Jacobian
  FieldContainer<double> refQuadJacobian(numCells, numCubPoints, spaceDim, spaceDim);
  FieldContainer<double> refQuadJacobInv(numCells, numCubPoints, spaceDim, spaceDim);
  FieldContainer<double> refQuadJacobDet(numCells, numCubPoints);
  // Containers for element HGRAD stiffness matrix
  FieldContainer<double> localStiffMatrix(numCells, numFieldsG, numFieldsG);
  FieldContainer<double> weightedMeasure(numCells, numCubPoints);
  FieldContainer<double> quadGradsTransformed(numCells, numFieldsG, numCubPoints, spaceDim);
  FieldContainer<double> quadGradsTransformedWeighted(numCells, numFieldsG, numCubPoints, spaceDim);
  // Containers for right hand side vectors
  FieldContainer<double> rhsData(numCells, numCubPoints);
  FieldContainer<double> localRHS(numCells, numFieldsG);
  FieldContainer<double> quadGValsTransformed(numCells, numFieldsG, numCubPoints);
  FieldContainer<double> quadGValsTransformedWeighted(numCells, numFieldsG, numCubPoints);
  // Container for cubature points in physical space
  FieldContainer<double> physCubPoints(numCells, numCubPoints, cubDim);
  
  // Global arrays in Epetra format 
  Epetra_SerialComm Comm;
  Epetra_Map globalMapG(numDOF, 0, Comm);
  Epetra_FEVector u(globalMapG);
  Epetra_FEVector Ku(globalMapG);
  u.Random();

  std::cout << "About to start ref element matrix\n";

  // ************************** Compute element HGrad stiffness matrices *******************************  
  refQuadNodes(0,0,0) = 0.0;
  refQuadNodes(0,0,1) = 0.0;
  refQuadNodes(0,1,0) = hx;
  refQuadNodes(0,1,1) = 0.0;
  refQuadNodes(0,2,0) = hx;
  refQuadNodes(0,2,1) = hy;
  refQuadNodes(0,3,0) = 0.0;
  refQuadNodes(0,3,1) = hy;

  // Compute cell Jacobians, their inverses and their determinants
  CellTools::setJacobian(refQuadJacobian, cubPoints, refQuadNodes, quad_4);
  CellTools::setJacobianInv(refQuadJacobInv, refQuadJacobian );
  CellTools::setJacobianDet(refQuadJacobDet, refQuadJacobian );
  
  // transform from [-1,1]^2 to [0,hx]x[0,hy]
  fst::HGRADtransformGRAD<double>(quadGradsTransformed, refQuadJacobInv, quadGrads);
      
  // compute weighted measure
  fst::computeCellMeasure<double>(weightedMeasure, refQuadJacobDet, cubWeights);

  // multiply values with weighted measure
  fst::multiplyMeasure<double>(quadGradsTransformedWeighted,
			       weightedMeasure, quadGradsTransformed);

  // integrate to compute element stiffness matrix
  fst::integrate<double>(localStiffMatrix,
			 quadGradsTransformed, quadGradsTransformedWeighted, COMP_BLAS);

  std::cout << "Finished with reference element matrix\n";

  
  // now we will scatter global degrees of freedom, apply the local stiffness matrix 
  // with BLAS, and then gather the results
  FieldContainer<double> uScattered(numElems,numFieldsG);
  FieldContainer<double> KuScattered(numElems,numFieldsG);

  // to extract info from u

  u.GlobalAssemble();

  Epetra_Time multTimer(Comm);

  Ku.PutScalar(0.0);
  Ku.GlobalAssemble();

  double *uVals = u[0];
  double *KuVals = Ku[0];

  Teuchos::BLAS<int,double> blas;
  Epetra_Time scatterTime(Comm);
  std::cout << "Scattering\n";
  // Scatter
  for (int k=0; k<numElems; k++) 
    {
      for (int i=0;i<numFieldsG;i++) 
	{
	  uScattered(k,i) = uVals[ltgMapping(k,i)];
	}
    }
  const double scatTime = scatterTime.ElapsedTime();
  std::cout << "Scattered in time " << scatTime << "\n";

  Epetra_Time blasTimer(Comm);
  blas.GEMM(Teuchos::NO_TRANS , Teuchos::NO_TRANS , 
	    numFieldsG , numElems, numFieldsG  , 
	    1.0 , 
	    &localStiffMatrix(0,0,0) , 
	    numFieldsG ,
	    &uScattered(0,0) , 
	    numFieldsG , 
	    0.0 , 
	     &KuScattered(0,0) , 
	    numFieldsG );
  const double blasTime = blasTimer.ElapsedTime();
  std::cout << "Element matrices applied in " << blasTime << "\n";

  Epetra_Time gatherTimer(Comm);
  // Gather
  for (int k=0;k<numElems;k++)
    {
      for (int i=0;i<numFieldsG;i++)
	{
	  KuVals[ltgMapping(k,i)] += KuScattered(k,i);
	}
    }

  const double gatherTime = gatherTimer.ElapsedTime();
  std::cout << "Gathered in " << gatherTime << "\n";
  

  const double applyTime = gatherTime + blasTime + scatTime;
  std::cout << "Time to do matrix-free product: " << applyTime << std::endl;
  
  
  std::cout << "End Result: TEST PASSED\n";
  
  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);
 Kokkos::finalize(); 
  return 0;
}