예제 #1
0
MxDimMatrix<T, DIM> MxDimMatrix<T, DIM>::inv() const {

  MxDimMatrix<T, DIM> thisT = this->transpose(); 
  MxDimMatrix<T, DIM> solnT(MxDimVector<T, DIM>(1));

  int info;
  int ipiv[DIM];
  Teuchos::LAPACK<int, T> lapack;
  lapack.GESV(DIM, DIM, &thisT(0, 0), DIM, ipiv, &solnT(0, 0), DIM, &info);
  
  if (info != 0)
    std::cout << "MxDimMatrix::inv(): error in lapack routine. Return code: " << info << ".\n";

  return solnT.transpose();
}
예제 #2
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;
}
예제 #3
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;
}
예제 #4
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;
}
예제 #5
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_QUAD_C2_FEM)                      |\n" \
    << "|                                                                             |\n" \
    << "|     1) Patch test involving mass and stiffness matrices,                    |\n" \
    << "|        for the Neumann problem on a physical parallelogram                  |\n" \
    << "|        AND a reference quad Omega with boundary Gamma.                      |\n" \
    << "|                                                                             |\n" \
    << "|        - div (grad u) + u = f  in Omega,  (grad u) . n = g  on Gamma        |\n" \
    << "|                                                                             |\n" \
    << "|        For a generic parallelogram, the basis recovers a complete           |\n" \
    << "|        polynomial space of order 2. On a (scaled and/or translated)         |\n" \
    << "|        reference quad, the basis recovers a complete tensor product         |\n" \
    << "|        space of order 2 (i.e. incl. the x^2*y, x*y^2, x^2*y^2 terms).       |\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 = 2;                                                                    // max total order of polynomial solution
    DefaultCubatureFactory<double>  cubFactory;                                           // create cubature factory
    shards::CellTopology cell(shards::getCellTopologyData< shards::Quadrilateral<> >());  // create parent cell topology
    shards::CellTopology side(shards::getCellTopologyData< shards::Line<> >());           // create relevant subcell (side) topology
    int cellDim = cell.getDimension();
    int sideDim = side.getDimension();

    // Define array containing points at which the solution is evaluated, in reference cell.
    int numIntervals = 10;
    int numInterpPoints = (numIntervals + 1)*(numIntervals + 1);
    FieldContainer<double> interp_points_ref(numInterpPoints, 2);
    int counter = 0;
    for (int j=0; j<=numIntervals; j++) {
      for (int i=0; i<=numIntervals; i++) {
        interp_points_ref(counter,0) = i*(2.0/numIntervals)-1.0;
        interp_points_ref(counter,1) = j*(2.0/numIntervals)-1.0;
        counter++;
      }
    }

    /* Parent cell definition. */
    FieldContainer<double> cell_nodes[2];
    cell_nodes[0].resize(1, 4, cellDim);
    cell_nodes[1].resize(1, 4, cellDim);

    // Generic parallelogram.
    cell_nodes[0](0, 0, 0) = -5.0;
    cell_nodes[0](0, 0, 1) = -1.0;
    cell_nodes[0](0, 1, 0) = 4.0;
    cell_nodes[0](0, 1, 1) = 1.0;
    cell_nodes[0](0, 2, 0) = 8.0;
    cell_nodes[0](0, 2, 1) = 3.0;
    cell_nodes[0](0, 3, 0) = -1.0;
    cell_nodes[0](0, 3, 1) = 1.0;
    // Reference quad. 
    cell_nodes[1](0, 0, 0) = -1.0;
    cell_nodes[1](0, 0, 1) = -1.0;
    cell_nodes[1](0, 1, 0) = 1.0;
    cell_nodes[1](0, 1, 1) = -1.0;
    cell_nodes[1](0, 2, 0) = 1.0;
    cell_nodes[1](0, 2, 1) = 1.0;
    cell_nodes[1](0, 3, 0) = -1.0;
    cell_nodes[1](0, 3, 1) = 1.0;

    std::stringstream mystream[2];
    mystream[0].str("\n>> Now testing basis on a generic parallelogram ...\n");
    mystream[1].str("\n>> Now testing basis on the reference quad ...\n");

    for (int pcell = 0; pcell < 2; pcell++) {
      *outStream << mystream[pcell].str();
      FieldContainer<double> interp_points(1, numInterpPoints, cellDim);
      CellTools<double>::mapToPhysicalFrame(interp_points, interp_points_ref, cell_nodes[pcell], cell);
      interp_points.resize(numInterpPoints, cellDim);

      for (int x_order=0; x_order <= max_order; x_order++) {
        int max_y_order = max_order;
        if (pcell == 0) {
          max_y_order -= x_order;
        }
        for (int y_order=0; y_order <= max_y_order; y_order++) {

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

          int basis_order = 2;

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

          //create basis
          Teuchos::RCP<Basis<double,FieldContainer<double> > > basis =
            Teuchos::rcp(new Basis_HGRAD_QUAD_C2_FEM<double,FieldContainer<double> >() );
          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(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
          cellCub->getCubature(cub_points_cell, cub_weights_cell);

          // compute geometric cell information
          CellTools<double>::setJacobian(jacobian_cell, cub_points_cell, cell_nodes[pcell], 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[pcell], cell);

          // evaluate rhs function
          rhsFunc(rhs_at_cub_points_cell_physical, cub_points_cell_physical, x_order, y_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[pcell], cell);
            CellTools<double>::setJacobianDet(jacobian_det_side_refcell, jacobian_side_refcell);

            // compute weighted edge measure
            FunctionSpaceTools::computeEdgeMeasure<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[pcell], 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);

            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, interp_points_ref, 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 << "\nRelative norm-2 error between exact solution polynomial of order ("
                     << x_order << ", " << y_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 << ") and basis order " << basis_order << "\n\n";
            errorFlag++;
          }
        } // end for y_order
      } // end for x_order
    } // end for pcell

  }
  // 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;
}
예제 #6
0
// ----------------------------------------------------------------------
// Main
//
//
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;

  for (int i=0;i<argc;++i) {
    if ((strcmp(argv[i],"--nelement")          == 0)) { nelement = atoi(argv[++i]); continue;}
    if ((strcmp(argv[i],"--apply-orientation") == 0)) { apply_orientation  = atoi(argv[++i]); continue;}
    if ((strcmp(argv[i],"--verbose")           == 0)) { verbose  = atoi(argv[++i]); continue;}
    if ((strcmp(argv[i],"--maxp")              == 0)) { maxp     = atoi(argv[++i]); continue;}
  }

  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 << std::scientific;
  *outStream \
    << "===============================================================================\n" \
    << "|                                                                             |\n" \
    << "|                    Unit Test (Basis_HGRAD_TRI_Cn_FEM)                       |\n" \
    << "|                                                                             |\n" \
    << "|     1) Patch test involving mass and stiffness matrices,                    |\n" \
    << "|        for the Neumann problem on a triangular 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" \
    << "|                      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 4: Patch test for high order assembly                                  |\n" \
    << "===============================================================================\n";

  int r_val = 0;

  // precision control
  outStream->precision(3);

#if defined( INTREPID_USING_EXPERIMENTAL_HIGH_ORDER )

  try {
    // test setup
    const int ndim = 2;
    FieldContainer<value_type> base_nodes(1, 4, ndim);
    base_nodes(0, 0, 0) = 0.0;
    base_nodes(0, 0, 1) = 0.0;

    base_nodes(0, 1, 0) = 1.0;
    base_nodes(0, 1, 1) = 0.0;

    base_nodes(0, 2, 0) = 0.0;
    base_nodes(0, 2, 1) = 1.0;

    base_nodes(0, 3, 0) = 1.0;
    base_nodes(0, 3, 1) = 1.0;

    // element 0 has globally permuted edge node
    const int elt_0[2][3] = { { 0, 1, 2 },
                              { 0, 2, 1 } };
    
    // element 1 is locally permuted
    int elt_1[3] = { 1, 2, 3 };

    DefaultCubatureFactory<value_type> cubature_factory;

    // for all test orders
    for (int nx=0;nx<=maxp;++nx) {
      for (int ny=0;ny<=maxp-nx;++ny) {
        // polynomial order of approximation
        const int minp = std::max(nx+ny, 1);

        // test for all basis above order p
        const EPointType pointtype[] = { POINTTYPE_EQUISPACED, POINTTYPE_WARPBLEND };
        for (int ptype=0;ptype<2;++ptype) {
          for (int p=minp;p<=maxp;++p) {
            *outStream << "\n"                                              \
                       << "===============================================================================\n" \
                       << "  Order (nx,ny,p) = " << nx << ", " << ny << ", " << p << " , PointType = " << EPointTypeToString(pointtype[ptype]) << "\n" \
                       << "===============================================================================\n";

            BasisSet_HGRAD_TRI_Cn_FEM<value_type,FieldContainer<value_type> > basis_set(p, pointtype[ptype]);
            const auto& basis = basis_set.getCellBasis();
            const shards::CellTopology cell = basis.getBaseCellTopology();

            const int nbf = basis.getCardinality();

            const int nvert = cell.getVertexCount();
            const int nedge = cell.getEdgeCount();

            FieldContainer<value_type> nodes(1, 4, ndim);
            FieldContainer<value_type> cell_nodes(1, nvert, ndim);

            // ignore the subdimension; the matrix is always considered as 1D array
            FieldContainer<value_type> A(1, nbf, nbf), b(1, nbf);

            // ***** Test for different orientations *****
            for (int conf0=0;conf0<2;++conf0) {
              for (int ino=0;ino<3;++ino) {
                nodes(0, elt_0[conf0][ino], 0) = base_nodes(0, ino, 0);
                nodes(0, elt_0[conf0][ino], 1) = base_nodes(0, ino, 1);
              }
              nodes(0, 3, 0) = base_nodes(0, 3, 0);
              nodes(0, 3, 1) = base_nodes(0, 3, 1);

              // reset element connectivity
              elt_1[0] = 1;
              elt_1[1] = 2;
              elt_1[2] = 3;

              // for all permuations of element 1
              for (int conf1=0;conf1<6;++conf1) {
                // filter out left handed element
                fill_cell_nodes(cell_nodes, 
                                nodes, 
                                elt_1,
                                nvert, ndim);
                if (OrientationTools<value_type>::isLeftHandedCell(cell_nodes)) {
                  // skip left handed
                } else {
                  const int *element[2] = { elt_0[conf0], elt_1 };
                  *outStream << "\n"                                \
                             << "  Element 0 is configured " << conf0 << " "
                             << "(" << element[0][0] << ","<< element[0][1] << "," << element[0][2] << ")"
                             << "  Element 1 is configured " << conf1 << " "
                             << "(" << element[1][0] << ","<< element[1][1] << "," << element[1][2] << ")"
                             << "\n";

                  if (verbose) {
                    *outStream << " - Element nodal connectivity - \n";
                    for (int iel=0;iel<nelement;++iel)
                      *outStream << " iel = " << std::setw(4) << iel
                                 << ", nodes = "
                                 << std::setw(4) << element[iel][0]
                                 << std::setw(4) << element[iel][1]
                                 << std::setw(4) << element[iel][2]
                                 << "\n";
                  }

                  // Step 0: count one-to-one mapping between high order nodes and dofs
                  Example::ToyMesh mesh;
                  int local2global[2][8][2], boundary[2][3], off_global = 0;

                  const int nnodes_per_element
                    = cell.getVertexCount()
                    + cell.getEdgeCount()
                    + 1;

                  for (int iel=0;iel<nelement;++iel)
                    mesh.getLocalToGlobalMap(local2global[iel], off_global, basis, element[iel]);

                  for (int iel=0;iel<nelement;++iel)
                    mesh.getBoundaryFlags(boundary[iel], cell, element[iel]);

                  if (verbose) {
                    *outStream << " - Element one-to-one local2global map -\n";
                    for (int iel=0;iel<nelement;++iel) {
                      *outStream << " iel = " << std::setw(4) << iel << "\n";
                      for (int i=0;i<(nnodes_per_element+1);++i) {
                        *outStream << "   local = " << std::setw(4) << local2global[iel][i][0]
                                   << "   global = " << std::setw(4) << local2global[iel][i][1]
                                   << "\n";
                      }
                    }
                    *outStream << " - Element boundary flags -\n";
                    const int nside = cell.getSideCount();
                    for (int iel=0;iel<nelement;++iel) {
                      *outStream << " iel = " << std::setw(4) << iel << "\n";
                      for (int i=0;i<nside;++i) {
                        *outStream << "   side = " << std::setw(4) << i
                                   << "   boundary = " << std::setw(4) << boundary[iel][i]
                                   << "\n";
                      }
                    }
                  }

                  // Step 1: assembly
                  const int ndofs = off_global;
                  FieldContainer<value_type> A_asm(1, ndofs, ndofs), b_asm(1, ndofs);

                  for (int iel=0;iel<nelement;++iel) {
                    // Step 1.1: create element matrices
                    Orientation ort = Orientation::getOrientation(cell, element[iel]);

                    // set element nodal coordinates
                    fill_cell_nodes(cell_nodes, 
                                    nodes, 
                                    element[iel], 
                                    nvert, ndim);

                    build_element_matrix_and_rhs(A, b,
                                                 cubature_factory,
                                                 basis_set,
                                                 element[iel],
                                                 boundary[iel],
                                                 cell_nodes,
                                                 ort,
                                                 nx, ny);
                    // if p is bigger than 4, not worth to look at the matrix
                    if (verbose && p < 5) {
                      *outStream << " - Element matrix and rhs, iel = " << iel << "\n";
                      *outStream << std::showpos;
                      for (int i=0;i<nbf;++i) {
                        for (int j=0;j<nbf;++j)
                          *outStream << MatVal(A, i, j) << " ";
                        *outStream << ":: " << MatVal(b, i, 0) << "\n";
                      }
                      *outStream << std::noshowpos;
                    }

                    // Step 1.2: assemble high order elements
                    assemble_element_matrix_and_rhs(A_asm, b_asm,
                                                    A, b,
                                                    local2global[iel],
                                                    nnodes_per_element);
                  }

                  if (verbose && p < 5) {
                    *outStream << " - Assembled element matrix and rhs -\n";
                    *outStream << std::showpos;
                    for (int i=0;i<ndofs;++i) {
                      for (int j=0;j<ndofs;++j)
                        *outStream << MatVal(A_asm, i, j) << " ";
                      *outStream << ":: " << MatVal(b_asm, i, 0) << "\n";
                    }
                    *outStream << std::noshowpos;
                  }

                  // Step 2: solve the system of equations
                  int info = 0;
                  Teuchos::LAPACK<int,value_type> lapack;
                  FieldContainer<int> ipiv(ndofs);
                  lapack.GESV(ndofs, 1, &A_asm(0,0,0), ndofs, &ipiv(0,0), &b_asm(0,0), ndofs, &info);
                  TEUCHOS_TEST_FOR_EXCEPTION( info != 0, std::runtime_error,
                                              ">>> ERROR (Intrepid::HGRAD_TRI_Cn::Test 04): " \
                                              "LAPACK solve fails");

                  // Step 3: construct interpolant and check solutions
                  magnitude_type interpolation_error = 0, solution_norm =0;
                  for (int iel=0;iel<nelement;++iel) {
                    retrieve_element_solution(b,
                                              b_asm,
                                              local2global[iel],
                                              nnodes_per_element);

                    if (verbose && p < 5) {
                      *outStream << " - Element solution, iel = " << iel << "\n";
                      *outStream << std::showpos;
                      for (int i=0;i<nbf;++i) {
                        *outStream << MatVal(b, i, 0) << "\n";
                      }
                      *outStream << std::noshowpos;
                    }

                    magnitude_type
                      element_interpolation_error = 0,
                      element_solution_norm = 0;

                    Orientation ort = Orientation::getOrientation(cell, element[iel]);

                    // set element nodal coordinates
                    fill_cell_nodes(cell_nodes, 
                                    nodes, 
                                    element[iel], 
                                    nvert, ndim);

                    compute_element_error(element_interpolation_error,
                                          element_solution_norm,
                                          element[iel],
                                          cell_nodes,
                                          basis_set,
                                          b,
                                          ort,
                                          nx, ny);

                    interpolation_error += element_interpolation_error;
                    solution_norm       += element_solution_norm;

                    {
                      int edge_orts[3];
                      ort.getEdgeOrientation(edge_orts, nedge);
                      *outStream << "   iel = " << std::setw(4) << iel
                                 << ", orientation = "
                                 << edge_orts[0]
                                 << edge_orts[1]
                                 << edge_orts[2]
                                 << " , error = " << element_interpolation_error
                                 << " , solution norm = " << element_solution_norm
                                 << " , relative error = " << (element_interpolation_error/element_solution_norm)
                                 << "\n";
                    }
                    const magnitude_type relative_error = interpolation_error/solution_norm;
                    const magnitude_type tol = p*p*100*INTREPID_TOL;

                    if (relative_error > tol) {
                      ++r_val;
                      *outStream << "\n\nPatch test failed: \n"
                                 << "    exact polynomial (nx, ny) = " << std::setw(4) << nx << ", " << std::setw(4) << ny << "\n"
                                 << "    basis order               = " << std::setw(4) << p << "\n"
                                 << "    orientation configuration = " << std::setw(4) << conf0 << std::setw(4) << conf1 << "\n"
                                 << "    relative error            = " << std::setw(4) << relative_error << "\n"
                                 << "    tolerance                 = " << std::setw(4) << tol << "\n";
                    }
                  }
                } 

                // for next iteration
                std::next_permutation(elt_1, elt_1+3);
              } // end of conf1
            } // end of conf0
          } // end of p
        } // end of point type
      } // end of ny
    } // end of nx
  }
  catch (std::logic_error err) {
    *outStream << err.what() << "\n\n";
    r_val = -1000;
  };
#else
  *outStream << "\t This test is for high order element assembly. \n"
             << "\t Use -D INTREPID_USING_EXPERIMENTAL_HIGH_ORDER in CMAKE_CXX_FLAGS \n";
#endif

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

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

  Kokkos::finalize();

  return r_val;
}
// Solves turning point equations via classic Salinger bordering
// The first m columns of input_x and input_null store the RHS while
// the last column stores df/dp, d(Jn)/dp respectively.  Note however
// input_param has only m columns (not m+1).  result_x, result_null,
// are result_param have the same dimensions as their input counterparts
NOX::Abstract::Group::ReturnType 
LOCA::TurningPoint::MooreSpence::PhippsBordering::solveTransposeContiguous(
		  Teuchos::ParameterList& params,
		  const NOX::Abstract::MultiVector& input_x,
		  const NOX::Abstract::MultiVector& input_null,
	          const NOX::Abstract::MultiVector::DenseMatrix& input_param,
		  NOX::Abstract::MultiVector& result_x,
		  NOX::Abstract::MultiVector& result_null,
	          NOX::Abstract::MultiVector::DenseMatrix& result_param) const
{
  std::string callingFunction = 
    "LOCA::TurningPoint::MooreSpence::PhippsBordering::solveTransposeContiguous()";
  NOX::Abstract::Group::ReturnType finalStatus = NOX::Abstract::Group::Ok;
  NOX::Abstract::Group::ReturnType status;

  int m = input_x.numVectors()-2;
  std::vector<int> index_input(m);
  std::vector<int> index_input_dp(m+1);
  std::vector<int> index_null(1);
  std::vector<int> index_dp(1);
  for (int i=0; i<m; i++) {
    index_input[i] = i;
    index_input_dp[i] = i;
  }
  index_input_dp[m] = m;
  index_dp[0] = m;
  index_null[0] = m+1;

  NOX::Abstract::MultiVector::DenseMatrix tmp_mat_1(1, m+1);
  NOX::Abstract::MultiVector::DenseMatrix tmp_mat_2(1, m+2);

  // Create view of first m+1 columns of input_null, result_null
  Teuchos::RCP<NOX::Abstract::MultiVector> input_null_view = 
      input_null.subView(index_input_dp);
  Teuchos::RCP<NOX::Abstract::MultiVector> result_null_view = 
      result_null.subView(index_input_dp);

  // verify underlying Jacobian is valid
  if (!group->isJacobian()) {
    status = group->computeJacobian();
    finalStatus = 
      globalData->locaErrorCheck->combineAndCheckReturnTypes(status, 
							     finalStatus,
							     callingFunction);
  }

  // Solve  |J^T v||A B| = |G -phi|
  //        |u^T 0||a b|   |0   0 |
  status =
    transposeBorderedSolver->applyInverseTranspose(params, 
						   input_null_view.get(), 
						   NULL, 
						   *result_null_view, 
						   tmp_mat_1);
  finalStatus = 
    globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus,
							   callingFunction);
  Teuchos::RCP<NOX::Abstract::MultiVector> A = 
    result_null.subView(index_input);
  Teuchos::RCP<NOX::Abstract::MultiVector> B = 
    result_null.subView(index_dp);
  double b = tmp_mat_1(0,m);

  // compute (Jv)_x^T[A B u]
  result_null[m+1] = *uVector;
  Teuchos::RCP<NOX::Abstract::MultiVector> tmp = 
    result_null.clone(NOX::ShapeCopy);
  status = group->computeDwtJnDxMulti(result_null, *nullVector, *tmp);
  finalStatus = 
    globalData->locaErrorCheck->combineAndCheckReturnTypes(status, 
							   finalStatus,
							   callingFunction);

  // compute [F 0 0] - (Jv)_x^T[A B u]
  tmp->update(1.0, input_x, -1.0);

  // verify underlying Jacobian is valid
  if (!group->isJacobian()) {
    status = group->computeJacobian();
    finalStatus = 
      globalData->locaErrorCheck->combineAndCheckReturnTypes(status, 
							     finalStatus,
							     callingFunction);
  }

  // Solve  |J^T v||C D E| = |F - (Jv)_x^T A  -(Jv)_x^T B  -(Jv)_x^T u|
  //        |u^T 0||c d e|   |         0             0            0   |
  status = 
    transposeBorderedSolver->applyInverseTranspose(params, 
						   tmp.get(), 
						   NULL, 
						   result_x,
						   tmp_mat_2);
  finalStatus = 
    globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus,
							   callingFunction);
  Teuchos::RCP<NOX::Abstract::MultiVector> C = 
    result_x.subView(index_input);
  Teuchos::RCP<NOX::Abstract::MultiVector> D = 
    result_x.subView(index_dp);
  Teuchos::RCP<NOX::Abstract::MultiVector> E = 
    result_x.subView(index_null);
  double d = tmp_mat_2(0, m);
  double e = tmp_mat_2(0, m+1);

  // compute (Jv)_p^T*[A B u]
  NOX::Abstract::MultiVector::DenseMatrix t1(1,m+2);
  result_null.multiply(1.0, *dJndp, t1);

  // compute f_p^T*[C D E]
  NOX::Abstract::MultiVector::DenseMatrix t2(1,m+2);
  result_x.multiply(1.0, *dfdp, t2);

  // compute f_p^T*u
  double fptu = uVector->innerProduct((*dfdp)[0]);

  // Fill coefficient arrays
  double M[9];
  M[0] = st;   M[1] =  -e;   M[2] = t1(0,m+1) + t2(0,m+1);
  M[3] = 0.0;  M[4] =   st;  M[5] = fptu;
  M[6] = -b;   M[7] =  -d;   M[8] = t1(0,m) + t2(0,m);

  // Compute RHS
  double *R = new double[3*m];
  for (int i=0; i<m; i++) {
    R[3*i]   = tmp_mat_1(0,i);
    R[3*i+1] = tmp_mat_2(0,i);
    R[3*i+2] = result_param(0,i) - t1(0,i) - t2(0,i);
  }

  // Solve M*P = R
  int three = 3;
  int piv[3];
  int info;
  Teuchos::LAPACK<int,double> L;
  L.GESV(three, m, M, three, piv, R, three, &info);
  if (info != 0) {
    globalData->locaErrorCheck->throwError(
				    callingFunction,
				    "Solve of 3x3 coefficient matrix failed!");
    return NOX::Abstract::Group::Failed;
  }

  NOX::Abstract::MultiVector::DenseMatrix alpha(1,m);
  NOX::Abstract::MultiVector::DenseMatrix beta(1,m);
  for (int i=0; i<m; i++) {
    alpha(0,i)        = R[3*i];
    beta(0,i)         = R[3*i+1];
    result_param(0,i) = R[3*i+2];
  }

  // compute A = A + B*z + alpha*u (remember A is a sub-view of result_null)
  A->update(Teuchos::NO_TRANS, 1.0, *B, result_param, 1.0);
  A->update(Teuchos::NO_TRANS, 1.0, *uMultiVector, alpha, 1.0);

  // compute C = C + D*z + alpha*E + beta*u 
  // (remember C is a sub-view of result_x)
  C->update(Teuchos::NO_TRANS, 1.0, *D, result_param, 1.0);
  C->update(Teuchos::NO_TRANS, 1.0, *E, alpha, 1.0);
  C->update(Teuchos::NO_TRANS, 1.0, *uMultiVector, beta, 1.0);

  delete [] R;

  return finalStatus;
}
// Solves turning point equations via Phipps modified bordering
// The first m columns of input_x and input_null store the RHS while
// the last column stores df/dp, d(Jn)/dp respectively.  Note however
// input_param has only m columns (not m+1).  result_x, result_null,
// are result_param have the same dimensions as their input counterparts
NOX::Abstract::Group::ReturnType 
LOCA::TurningPoint::MooreSpence::PhippsBordering::solveContiguous(
		  Teuchos::ParameterList& params,
		  const NOX::Abstract::MultiVector& input_x,
		  const NOX::Abstract::MultiVector& input_null,
	          const NOX::Abstract::MultiVector::DenseMatrix& input_param,
		  NOX::Abstract::MultiVector& result_x,
		  NOX::Abstract::MultiVector& result_null,
	          NOX::Abstract::MultiVector::DenseMatrix& result_param) const
{
  std::string callingFunction = 
    "LOCA::TurningPoint::MooreSpence::PhippsBordering::solveContiguous()";
  NOX::Abstract::Group::ReturnType finalStatus = NOX::Abstract::Group::Ok;
  NOX::Abstract::Group::ReturnType status;

  int m = input_x.numVectors()-2;
  std::vector<int> index_input(m);
  std::vector<int> index_input_dp(m+1);
  std::vector<int> index_null(1);
  std::vector<int> index_dp(1);
  for (int i=0; i<m; i++) {
    index_input[i] = i;
    index_input_dp[i] = i;
  }
  index_input_dp[m] = m;
  index_dp[0] = m;
  index_null[0] = m+1;

  NOX::Abstract::MultiVector::DenseMatrix tmp_mat_1(1, m+1);
  NOX::Abstract::MultiVector::DenseMatrix tmp_mat_2(1, m+2);

  // Create view of first m+1 columns of input_x, result_x
  Teuchos::RCP<NOX::Abstract::MultiVector> input_x_view = 
      input_x.subView(index_input_dp);
  Teuchos::RCP<NOX::Abstract::MultiVector> result_x_view = 
      result_x.subView(index_input_dp);

  // verify underlying Jacobian is valid
  if (!group->isJacobian()) {
    status = group->computeJacobian();
    finalStatus = 
      globalData->locaErrorCheck->combineAndCheckReturnTypes(status, 
							     finalStatus,
							     callingFunction);
  }
  
  // Solve  |J   u||A B| = |F df/dp|
  //        |v^T 0||a b|   |0   0  |
  status = borderedSolver->applyInverse(params, input_x_view.get(), NULL, 
					*result_x_view, tmp_mat_1);
  finalStatus = 
    globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus,
							   callingFunction);
  Teuchos::RCP<NOX::Abstract::MultiVector> A = 
    result_x.subView(index_input);
  Teuchos::RCP<NOX::Abstract::MultiVector> B = 
    result_x.subView(index_dp);
  double b = tmp_mat_1(0,m);

  // compute (Jv)_x[A B v]
  result_x[m+1] = *nullVector;
  Teuchos::RCP<NOX::Abstract::MultiVector> tmp = 
    result_x.clone(NOX::ShapeCopy);
  status = group->computeDJnDxaMulti(*nullVector, *JnVector, result_x,
				     *tmp);
  finalStatus = 
    globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus,
							   callingFunction);

  // compute (Jv)_x[A B v] - [G d(Jn)/dp 0]
  tmp->update(-1.0, input_null, 1.0);

  // verify underlying Jacobian is valid
  if (!group->isJacobian()) {
    status = group->computeJacobian();
    finalStatus = 
      globalData->locaErrorCheck->combineAndCheckReturnTypes(status, 
							     finalStatus,
							     callingFunction);
  }

  // Solve  |J   u||C D E| = |(Jv)_x A - G  (Jv)_x B - d(Jv)/dp  (Jv)_x v|
  //        |v^T 0||c d e|   |         0             0               0   |
  status = borderedSolver->applyInverse(params, tmp.get(), NULL, result_null,
					tmp_mat_2);
  finalStatus = 
    globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus,
							   callingFunction);
  Teuchos::RCP<NOX::Abstract::MultiVector> C = 
    result_null.subView(index_input);
  Teuchos::RCP<NOX::Abstract::MultiVector> D = 
    result_null.subView(index_dp);
  Teuchos::RCP<NOX::Abstract::MultiVector> E = 
    result_null.subView(index_null);
  double d = tmp_mat_2(0, m);
  double e = tmp_mat_2(0, m+1);

  // Fill coefficient arrays
  double M[9];
  M[0] = s;   M[1] =  e;  M[2] = -tpGroup->lTransNorm((*E)[0]);
  M[3] = 0.0; M[4] =  s;  M[5] =  tpGroup->lTransNorm(*nullVector);
  M[6] = b;   M[7] = -d;  M[8] =  tpGroup->lTransNorm((*D)[0]);

  // compute h + phi^T C
  tpGroup->lTransNorm(*C, result_param);
  result_param += input_param;

  double *R = new double[3*m];
  for (int i=0; i<m; i++) {
    R[3*i]   =  tmp_mat_1(0,i);
    R[3*i+1] = -tmp_mat_2(0,i);
    R[3*i+2] =  result_param(0,i);
  }

  // Solve M*P = R
  int three = 3;
  int piv[3];
  int info;
  Teuchos::LAPACK<int,double> L;
  L.GESV(three, m, M, three, piv, R, three, &info);
  if (info != 0) {
    globalData->locaErrorCheck->throwError(
				    callingFunction,
				    "Solve of 3x3 coefficient matrix failed!");
    return NOX::Abstract::Group::Failed;
  }

  NOX::Abstract::MultiVector::DenseMatrix alpha(1,m);
  NOX::Abstract::MultiVector::DenseMatrix beta(1,m);
  for (int i=0; i<m; i++) {
    alpha(0,i)        = R[3*i];
    beta(0,i)         = R[3*i+1];
    result_param(0,i) = R[3*i+2];
  }

  // compute A = A - B*z + v*alpha (remember A is a sub-view of result_x)
  A->update(Teuchos::NO_TRANS, -1.0, *B, result_param, 1.0);
  A->update(Teuchos::NO_TRANS, 1.0, *nullMultiVector, alpha, 1.0);

  // compute C = -C + d*z - E*alpha + v*beta 
  // (remember C is a sub-view of result_null)
  C->update(Teuchos::NO_TRANS, 1.0, *D, result_param, -1.0);
  C->update(Teuchos::NO_TRANS, -1.0, *E, alpha, 1.0);
  C->update(Teuchos::NO_TRANS, 1.0, *nullMultiVector, beta, 1.0);

  delete [] R;

  return finalStatus;
}
예제 #9
0
int main(int argc, char *argv[]) {
  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
  Kokkos::initialize();
  // This little trick lets us print to std::cout only if
  // a (dummy) command-line argument is provided.
  int iprint = argc - 1;
  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing
  if (iprint > 0)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs, false);
  
  // Save the format state of the original std::cout.
  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);
  
  *outStream \
    << "===============================================================================\n" \
    << "|                                                                             |\n" \
    << "|                  Unit Test (Basis_HCURL_HEX_In_FEM)                         |\n" \
    << "|                                                                             |\n" \
    << "| 1) Patch test involving H(curl) matrices                                    |\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 2: Patch test for mass matrices                                        |\n" \
    << "===============================================================================\n";
  
  
  int errorFlag = 0;
  
  outStream -> precision(16);
  
  try {
    shards::CellTopology cell(shards::getCellTopologyData< shards::Hexahedron<8> >());  // create parent cell topology
    
    int cellDim = cell.getDimension();
    
    int min_order = 1;
    int max_order = 3;
    
    int numIntervals = max_order;
    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 basis
      Teuchos::RCP<Basis<double,FieldContainer<double> > > basis =
        Teuchos::rcp(new Basis_HCURL_HEX_In_FEM<double,FieldContainer<double> >(basis_order,POINTTYPE_SPECTRAL) );
      int numFields = basis->getCardinality();
      
      // create cubatures
      DefaultCubatureFactory<double> cubFactory;
      Teuchos::RCP<Cubature<double> > cellCub = cubFactory.create( cell , 2* basis_order );


      int numCubPointsCell = cellCub->getNumPoints();
      
      // hold cubature information
      FieldContainer<double> cub_points_cell(numCubPointsCell, cellDim);
      FieldContainer<double> cub_weights_cell(numCubPointsCell);
      
      // hold basis function information on refcell
      FieldContainer<double> value_of_basis_at_cub_points_cell(numFields, numCubPointsCell, cellDim );
      FieldContainer<double> w_value_of_basis_at_cub_points_cell(1, numFields, numCubPointsCell, cellDim);


      // holds rhs data
      FieldContainer<double> rhs_at_cub_points_cell(1,numCubPointsCell,cellDim);
      
      // FEM mass matrix
      FieldContainer<double> fe_matrix_bak(1,numFields,numFields);
      FieldContainer<double> fe_matrix(1,numFields,numFields);
      FieldContainer<double> rhs_and_soln_vec(1,numFields);
      
      FieldContainer<int> ipiv(numFields);
      FieldContainer<double> value_of_basis_at_interp_points( numFields , numInterpPoints , cellDim);
      FieldContainer<double> interpolant( 1, numInterpPoints , cellDim );

      int info = 0;
      Teuchos::LAPACK<int, double> solver;
      
      // set test tolerance
      double zero = (basis_order+1)*(basis_order+1)*1000*INTREPID_TOL;
      
      // build matrices outside the loop, and then just do the rhs
      // for each iteration
      cellCub->getCubature(cub_points_cell, cub_weights_cell);
      
      // need the vector basis
      basis->getValues(value_of_basis_at_cub_points_cell,
		       cub_points_cell,
		       OPERATOR_VALUE);
      basis->getValues( value_of_basis_at_interp_points ,
			interp_points_ref ,
			OPERATOR_VALUE );


      // construct mass matrix
      cub_weights_cell.resize(1,numCubPointsCell);
      FunctionSpaceTools::multiplyMeasure<double>(w_value_of_basis_at_cub_points_cell ,
                                                  cub_weights_cell ,
                                                  value_of_basis_at_cub_points_cell ); 
      cub_weights_cell.resize(numCubPointsCell);
      
      
      value_of_basis_at_cub_points_cell.resize( 1 , numFields , numCubPointsCell , cellDim );
      FunctionSpaceTools::integrate<double>(fe_matrix_bak,
                                            w_value_of_basis_at_cub_points_cell ,
                                            value_of_basis_at_cub_points_cell ,
                                            COMP_BLAS );
      value_of_basis_at_cub_points_cell.resize( numFields , numCubPointsCell , cellDim );
      
      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++) {
	    for (int comp=0;comp<cellDim;comp++) {
	      fe_matrix.initialize();
	      // copy mass matrix 
	      for (int i=0;i<numFields;i++) {
		for (int j=0;j<numFields;j++) {
		  fe_matrix(0,i,j) = fe_matrix_bak(0,i,j);
		}
	      }
	      
	      // clear old vector data
	      rhs_and_soln_vec.initialize();
	      
	      // now get rhs vector
	      
	      cub_points_cell.resize(1,numCubPointsCell,cellDim);
	     
	      rhs_at_cub_points_cell.initialize();
	      rhsFunc(rhs_at_cub_points_cell,
		      cub_points_cell,
		      comp, 
		      x_order,
		      y_order,
		      z_order);

	      cub_points_cell.resize(numCubPointsCell,cellDim);
	      cub_weights_cell.resize(numCubPointsCell);

	      FunctionSpaceTools::integrate<double>(rhs_and_soln_vec,
						    rhs_at_cub_points_cell,
						    w_value_of_basis_at_cub_points_cell,
						    COMP_BLAS);
	      
	      // solve linear system

 	      solver.GESV(numFields, 1, &fe_matrix(0,0,0), numFields, &ipiv(0), &rhs_and_soln_vec(0,0), 
 			  numFields, &info);
// 	      solver.POTRF('L',numFields,&fe_matrix(0,0,0),numFields,&info);
// 	      solver.POTRS('L',numFields,1,&fe_matrix(0,0,0),numFields,&rhs_and_soln_vec(0,0),numFields,&info);
	      
	      interp_points_ref.resize(1,numInterpPoints,cellDim);
	      // get exact solution for comparison
	      FieldContainer<double> exact_solution(1,numInterpPoints,cellDim);
	      exact_solution.initialize();
	      u_exact( exact_solution , interp_points_ref , comp , x_order, y_order, z_order);
	      interp_points_ref.resize(numInterpPoints,cellDim);

	      // compute interpolant
	      // first evaluate basis at interpolation points
	      value_of_basis_at_interp_points.resize(1,numFields,numInterpPoints,cellDim);
	      FunctionSpaceTools::evaluate<double>( interpolant , 
						    rhs_and_soln_vec ,
						    value_of_basis_at_interp_points );
	      value_of_basis_at_interp_points.resize(numFields,numInterpPoints,cellDim);

	      RealSpaceTools<double>::subtract(interpolant,exact_solution);

	      // let's compute the L2 norm
	      interpolant.resize(1,numInterpPoints,cellDim);
	      FieldContainer<double> l2norm(1);
	      FunctionSpaceTools::dataIntegral<double>( l2norm ,
							interpolant ,
							interpolant ,
							COMP_BLAS );
	      
	      const double nrm = sqrtl(l2norm(0));
	      
	      *outStream << "\nFunction space L^2 Norm-2 error between scalar components of exact solution of order ("
			 << x_order << ", " << y_order << ", " << z_order
			 << ") in component " << comp 
			 << " 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;
}
예제 #10
0
// Solves pitchfork equations via Phipps modified bordering
// The first m columns of input_x and input_null store the RHS,
// column m+1 stores df/dp, d(Jn)/dp, column m+2 stores psi and 0,
// and the last column provides space for solving (Jv_x) v.  Note however
// input_param has only m columns.  result_x, result_null,
// are result_param have the same dimensions as their input counterparts
NOX::Abstract::Group::ReturnType 
LOCA::Pitchfork::MooreSpence::PhippsBordering::solveContiguous(
		  Teuchos::ParameterList& params,
		  const NOX::Abstract::MultiVector& input_x,
		  const NOX::Abstract::MultiVector& input_null,
		  const NOX::Abstract::MultiVector::DenseMatrix& input_slack,
	          const NOX::Abstract::MultiVector::DenseMatrix& input_param,
		  NOX::Abstract::MultiVector& result_x,
		  NOX::Abstract::MultiVector& result_null,
		  NOX::Abstract::MultiVector::DenseMatrix& result_slack,
	          NOX::Abstract::MultiVector::DenseMatrix& result_param) const
{
  string callingFunction = 
    "LOCA::Pitchfork::MooreSpence::PhippsBordering::solveContiguous()";
  NOX::Abstract::Group::ReturnType finalStatus = NOX::Abstract::Group::Ok;
  NOX::Abstract::Group::ReturnType status;

  int m = input_x.numVectors()-3;
  vector<int> index_input(m);
  vector<int> index_input_dp(m+2);
  vector<int> index_null(1);
  vector<int> index_dp(1);
  vector<int> index_s(1);
  for (int i=0; i<m; i++) {
    index_input[i] = i;
    index_input_dp[i] = i;
  }
  index_input_dp[m] = m;
  index_input_dp[m+1] = m+1;
  index_dp[0] = m;
  index_s[0] = m+1;
  index_null[0] = m+2;

  NOX::Abstract::MultiVector::DenseMatrix tmp_mat_1(1, m+2);
  NOX::Abstract::MultiVector::DenseMatrix tmp_mat_2(1, m+3);

  // Create view of first m+2 columns of input_x, result_x
  Teuchos::RCP<NOX::Abstract::MultiVector> input_x_view = 
      input_x.subView(index_input_dp);
  Teuchos::RCP<NOX::Abstract::MultiVector> result_x_view = 
      result_x.subView(index_input_dp);

  // verify underlying Jacobian is valid
  if (!group->isJacobian()) {
    status = group->computeJacobian();
    finalStatus = 
      globalData->locaErrorCheck->combineAndCheckReturnTypes(status, 
							     finalStatus,
							     callingFunction);
  }
  
  // Solve  |J   u||A B C| = |F df/dp psi|
  //        |v^T 0||a b c|   |0   0    0 |
  status = borderedSolver->applyInverse(params, input_x_view.get(), NULL, 
					*result_x_view, tmp_mat_1);
  finalStatus = 
    globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus,
							   callingFunction);
  Teuchos::RCP<NOX::Abstract::MultiVector> A = 
    result_x.subView(index_input);
  Teuchos::RCP<NOX::Abstract::MultiVector> B = 
    result_x.subView(index_dp);
  Teuchos::RCP<NOX::Abstract::MultiVector> C = 
    result_x.subView(index_s);
  double b = tmp_mat_1(0,m);
  double c = tmp_mat_1(0,m+1);

  // compute (Jv)_x[A B C v]
  result_x[m+2] = *nullVector;
  Teuchos::RCP<NOX::Abstract::MultiVector> tmp = 
    result_x.clone(NOX::ShapeCopy);
  status = group->computeDJnDxaMulti(*nullVector, *JnVector, result_x,
				     *tmp);
  finalStatus = 
    globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus,
							   callingFunction);

  // compute [G d(Jn)/dp 0 0] - (Jv)_x[A B C v]
  tmp->update(1.0, input_null, -1.0);

  // verify underlying Jacobian is valid
  if (!group->isJacobian()) {
    status = group->computeJacobian();
    finalStatus = 
      globalData->locaErrorCheck->combineAndCheckReturnTypes(status, 
							     finalStatus,
							     callingFunction);
  }

  // Solve  |J   u||D E K L| = |G-(Jv)_xA  d(Jv)/dp-(Jv)_xB  -(Jv)_xC -(Jv)_xv|
  //        |v^T 0||d e k l|   |    0             0              0        0   |
  status = borderedSolver->applyInverse(params, tmp.get(), NULL, result_null,
					tmp_mat_2);
  finalStatus = 
    globalData->locaErrorCheck->combineAndCheckReturnTypes(status, finalStatus,
							   callingFunction);
  Teuchos::RCP<NOX::Abstract::MultiVector> D = 
    result_null.subView(index_input);
  Teuchos::RCP<NOX::Abstract::MultiVector> E = 
    result_null.subView(index_dp);
  Teuchos::RCP<NOX::Abstract::MultiVector> K = 
    result_null.subView(index_s);
  Teuchos::RCP<NOX::Abstract::MultiVector> L = 
    result_null.subView(index_null);
  double e = tmp_mat_2(0, m);
  double k = tmp_mat_2(0, m+1);
  double l = tmp_mat_2(0, m+2);

  double ltE = pfGroup->lTransNorm((*E)[0]);
  double ltK = pfGroup->lTransNorm((*K)[0]);
  double ltL = pfGroup->lTransNorm((*L)[0]);
  double ltv = pfGroup->lTransNorm(*nullVector);
  double ipv = group->innerProduct(*nullVector, *asymVector);
  double ipB = group->innerProduct((*B)[0], *asymVector);
  double ipC = group->innerProduct((*C)[0], *asymVector);

  // Fill coefficient arrays
  double M[16];
  M[0]  = sigma; M[1]  = -l;     M[2]  =  ipv; M[3]  =  ltL;
  M[4]  = 0.0;   M[5]  =  sigma; M[6]  =  0.0; M[7]  =  ltv;
  M[8]  = b;     M[9]  =  e;     M[10] = -ipB; M[11] = -ltE;
  M[12] = c;     M[13] =  k;     M[14] = -ipC; M[15] = -ltK;

  // compute s - <A,psi>
  NOX::Abstract::MultiVector::DenseMatrix tmp_mat_3(1, m);
  group->innerProduct(*asymMultiVector, *A, tmp_mat_3);
  tmp_mat_3 -= input_slack;
  tmp_mat_3.scale(-1.0);

  // compute h - phi^T D
  NOX::Abstract::MultiVector::DenseMatrix tmp_mat_4(1, m);
  pfGroup->lTransNorm(*D, tmp_mat_4);
  tmp_mat_4 -= input_param;
  tmp_mat_4.scale(-1.0);

  double *R = new double[4*m];
  for (int i=0; i<m; i++) {
    R[4*i]   = tmp_mat_1(0,i);
    R[4*i+1] = tmp_mat_2(0,i);
    R[4*i+2] = tmp_mat_3(0,i);
    R[4*i+3] = tmp_mat_4(0,i);
  }

  // Solve M*P = R
  int piv[4];
  int info;
  Teuchos::LAPACK<int,double> dlapack;
  dlapack.GESV(4, m, M, 4, piv, R, 4, &info);
  if (info != 0) {
    globalData->locaErrorCheck->throwError(
				    callingFunction,
				    "Solve of 4x4 coefficient matrix failed!");
    return NOX::Abstract::Group::Failed;
  }

  NOX::Abstract::MultiVector::DenseMatrix alpha(1,m);
  NOX::Abstract::MultiVector::DenseMatrix beta(1,m);
  for (int i=0; i<m; i++) {
    alpha(0,i)        = R[4*i];
    beta(0,i)         = R[4*i+1];
    result_param(0,i) = R[4*i+2];
    result_slack(0,i) = R[4*i+3];
  }

  // compute A = A - B*z -C*w + v*alpha (remember A is a sub-view of result_x)
  A->update(Teuchos::NO_TRANS, -1.0, *B, result_param, 1.0);
  A->update(Teuchos::NO_TRANS, -1.0, *C, result_slack, 1.0);
  A->update(Teuchos::NO_TRANS, 1.0, *nullMultiVector, alpha, 1.0);

  // compute D = D - E*z - K*w + L*alpha + v*beta 
  // (remember D is a sub-view of result_null)
  D->update(Teuchos::NO_TRANS, -1.0, *E, result_param, 1.0);
  D->update(Teuchos::NO_TRANS, -1.0, *K, result_slack, 1.0);
  D->update(Teuchos::NO_TRANS, 1.0, *L, alpha, 1.0);
  D->update(Teuchos::NO_TRANS, 1.0, *nullMultiVector, beta, 1.0);

  delete [] R;

  return finalStatus;
}