int 
 Intrepid2FieldPattern::
 getSubcellCount(int dim) const
 {
   const shards::CellTopology ct = intrepidBasis_->getBaseCellTopology();
   return ct.getSubcellCount(dim);
 }
void Intrepid2FieldPattern::buildSubcellClosure(const shards::CellTopology & cellTopo,unsigned dim,unsigned subCell,
                                               std::set<std::pair<unsigned,unsigned> > & closure)
{
   switch(dim) {
   case 0:
      closure.insert(std::make_pair(0,subCell));
      break;
   case 1:
      closure.insert(std::make_pair(0,cellTopo.getNodeMap(dim,subCell,0)));
      closure.insert(std::make_pair(0,cellTopo.getNodeMap(dim,subCell,1)));
      closure.insert(std::make_pair(1,subCell));
      break;
   case 2:
      {
      unsigned cnt = (shards::CellTopology(cellTopo.getCellTopologyData(dim,subCell))).getSubcellCount(dim-1);
      for(unsigned i=0;i<cnt;i++) {
         int edge = mapCellFaceEdge(cellTopo.getCellTopologyData(),subCell,i);
         buildSubcellClosure(cellTopo,dim-1,edge,closure);
      }
      closure.insert(std::make_pair(2,subCell));
      }
      break;
   default:
      // beyond a two dimension surface this thing crashes!
      TEUCHOS_ASSERT(false);
   };
}
    inline
    void 
    OrientationTools::
    mapToModifiedReference(outPointViewType outPoints,
                           const refPointViewType refPoints,
                           const shards::CellTopology cellTopo,
                           const ordinal_type cellOrt) {
#ifdef HAVE_INTREPID2_DEBUG
      {
        const auto cellDim = cellTopo.getDimension();
        INTREPID2_TEST_FOR_EXCEPTION( !( (1 <= cellDim) && (cellDim <= 2 ) ), std::invalid_argument,
                                      ">>> ERROR (Intrepid::OrientationTools::mapToModifiedReference): " \
                                      "Method defined only for 1 and 2-dimensional subcells.");
        
        INTREPID2_TEST_FOR_EXCEPTION( !( outPoints.dimension(0) == refPoints.dimension(0) ), std::invalid_argument,
                                      ">>> ERROR (Intrepid::OrientationTools::mapToModifiedReference): " \
                                      "Size of input and output point arrays does not match each other.");
      }
#endif
      
      // Apply the parametrization map to every point in parameter domain
      const auto numPts = outPoints.dimension(0);
      const auto key = cellTopo.getBaseCellTopologyData()->key;
      switch (key) {
      case shards::Line<>::key : {
        for (auto pt=0;pt<numPts;++pt)
          getModifiedLinePoint(outPoints(pt, 0),
                               refPoints(pt, 0),
                               cellOrt);
        break;
      }
      case shards::Triangle<>::key : {
        for (auto pt=0;pt<numPts;++pt)
          getModifiedTrianglePoint(outPoints(pt, 0), outPoints(pt, 1),
                                   refPoints(pt, 0), refPoints(pt, 1),
                                   cellOrt);
        break;
      }
      case shards::Quadrilateral<>::key : {
        for (auto pt=0;pt<numPts;++pt)
          getModifiedQuadrilateralPoint(outPoints(pt, 0), outPoints(pt, 1),
                                        refPoints(pt, 0), refPoints(pt, 1),
                                        cellOrt);
        break;
      }
      default: {
        INTREPID2_TEST_FOR_EXCEPTION( true, std::invalid_argument,
                                      ">>> ERROR (Intrepid2::OrientationTools::mapToModifiedReference): " \
                                      "Invalid cell topology." );
        break;
      }
      }
    }
Ejemplo n.º 4
0
  inline
  ordinal_type
  PointTools::
  getLatticeSize( const shards::CellTopology cellType,
                  const ordinal_type order,
                  const ordinal_type offset ) {
#ifdef HAVE_INTREPID2_DEBUG    
    INTREPID2_TEST_FOR_EXCEPTION( order < 0 || offset < 0,
                                  std::invalid_argument ,
                                  ">>> ERROR (PointTools::getLatticeSize): order and offset must be positive values." );
#endif
    ordinal_type r_val = 0;
    switch (cellType.getBaseKey()) {
    case shards::Tetrahedron<>::key: {
      const auto effectiveOrder = order - 4 * offset;
      r_val = (effectiveOrder < 0 ? 0 :(effectiveOrder+1)*(effectiveOrder+2)*(effectiveOrder+3)/6);
      break;
    }
    case shards::Triangle<>::key: {
      const auto effectiveOrder = order - 3 * offset;
      r_val = (effectiveOrder < 0 ? 0 : (effectiveOrder+1)*(effectiveOrder+2)/2);
      break;
    }
    case shards::Line<>::key: {
      const auto effectiveOrder = order - 2 * offset;
      r_val = (effectiveOrder < 0 ? 0 : (effectiveOrder+1));
      break;
    }
    default: {
      INTREPID2_TEST_FOR_EXCEPTION( true , std::invalid_argument ,
                                    ">>> ERROR (Intrepid2::PointTools::getLatticeSize): the specified cell type is not supported." );
    }
    }
    return r_val;
  }
void Intrepid2FieldPattern::getSubcellNodes(const shards::CellTopology & cellTopo,unsigned dim,unsigned subCell,
                                           std::vector<unsigned> & nodes)
{
   if(dim==0) {
      nodes.push_back(subCell);
      return;
   }

   // get all nodes on requested sub cell
   unsigned subCellNodeCount = cellTopo.getNodeCount(dim,subCell);
   for(unsigned node=0;node<subCellNodeCount;++node)
      nodes.push_back(cellTopo.getNodeMap(dim,subCell,node));

   // sort them so they are ordered correctly for "includes" call
   std::sort(nodes.begin(),nodes.end());
}
void Intrepid2FieldPattern::findContainedSubcells(const shards::CellTopology & cellTopo,unsigned dim,
                                                 const std::vector<unsigned> & nodes,
                                                 std::set<std::pair<unsigned,unsigned> > & subCells)
{

   unsigned subCellCount = cellTopo.getSubcellCount(dim); 
   for(unsigned subCellOrd=0;subCellOrd<subCellCount;++subCellOrd) {
      // get all nodes in sub cell
      std::vector<unsigned> subCellNodes;
      getSubcellNodes(cellTopo,dim,subCellOrd,subCellNodes);

      // if subCellNodes \subset nodes => add (dim,subCellOrd) to subCells
      bool isSubset = std::includes(       nodes.begin(),        nodes.end(),
                                    subCellNodes.begin(), subCellNodes.end());
      if(isSubset)
         subCells.insert(std::make_pair(dim,subCellOrd));
       
   }

   // stop recursion base case
   if(dim==0) return;

   // find subcells in next sub dimension
   findContainedSubcells(cellTopo,dim-1,nodes,subCells);
}
IntrepidSideCell<MDArray>::IntrepidSideCell( 
    const shards::CellTopology& side_topology,
    const unsigned side_id,
    const shards::CellTopology& parent_topology,
    const unsigned degree )
    : Base( side_topology, degree )
    , d_side_id( side_id )
    , d_parent_topology( parent_topology )
{
    // Map the side cubature points to the cell frame.
    MDArray mapped_cub_points( this->d_cubature->getNumPoints(), 
			       parent_topology.getDimension() );
    Intrepid::CellTools<Scalar>::mapToReferenceSubcell(
	mapped_cub_points, this->d_cub_points, side_topology.getDimension(),
	d_side_id, d_parent_topology );
    this->d_cub_points = mapped_cub_points;
}
 Basis_HGRAD_POLY_C1_FEM<Scalar, ArrayScalar>::Basis_HGRAD_POLY_C1_FEM(const shards::CellTopology& cellTopology){
   this -> basisCardinality_  = cellTopology.getNodeCount();
   this -> basisDegree_       = 1;
   this -> basisCellTopology_ = cellTopology;
   this -> basisType_         = BASIS_FEM_DEFAULT;
   this -> basisCoordinates_  = COORDINATES_CARTESIAN;
   this -> basisTagsAreSet_   = false;
 }
Ejemplo n.º 9
0
   unsigned
   getLocalSubcellIndexFromGlobalNodeList(const ArrayCellGIDs& cellGIDs,
                                          const ArraySideGIDs& subcellGIDs,
                                          const shards::CellTopology& cell,unsigned subcell_dim)
 {
   unsigned local_subcell;
   bool found_local_subcell = false;
   unsigned subcell = 0;
   while ( (subcell < cell.getSubcellCount(subcell_dim)) && (!found_local_subcell) ) {
 
     unsigned num_subcell_nodes =
 	cell.getCellTopologyData()->subcell[subcell_dim][subcell].topology->node_count;
 
     std::list<unsigned> tmp_subcell_gid_list;
     for (unsigned node = 0; node < num_subcell_nodes; ++node)
       tmp_subcell_gid_list.push_back(cellGIDs[cell.getNodeMap(subcell_dim,
                                                            subcell, node)]);
 
     bool subcell_matches = true;
     unsigned node = 0;
     while ( subcell_matches && (node < num_subcell_nodes) ) {
 
       std::list<unsigned>::iterator search =
         std::find(tmp_subcell_gid_list.begin(), tmp_subcell_gid_list.end(),
                   subcellGIDs[node]);
 
       if (search == tmp_subcell_gid_list.end())
         subcell_matches = false;
 
       ++node;
     }
 
     if (subcell_matches) {
       found_local_subcell = true;
       local_subcell = subcell;
     }
 
     ++subcell;
   }
 
   TEUCHOS_TEST_FOR_EXCEPTION(!found_local_subcell, std::runtime_error,
                      "Failed to find subcell!");
 
   return local_subcell;
 }
Ejemplo n.º 10
0
 void getBoundaryFlags(int *boundary,
                       const shards::CellTopology cell,
                       const int *element) {
   int subcell_verts[4], nids;
   const int dim = cell.getDimension();
   const int nside = cell.getSideCount();
   for (int i=0;i<nside;++i) {
     Orientation::getElementNodeMap(subcell_verts, nids,
                                    cell, element,
                                    dim-1, i);
     
     if (!findBoundary(boundary[i], subcell_verts, nids)) {
       TEUCHOS_TEST_FOR_EXCEPTION( true, std::runtime_error,
                                   ">>> ERROR (Intrepid::HGRAD_TRI_Cn::Test 04): " \
                                   "Side node is not found");
     }
   }
 }
Ejemplo n.º 11
0
 void PointTools::
 getWarpBlendLattice( /**/  Kokkos::DynRankView<pointValueType,pointProperties...> points,
                      const shards::CellTopology cell,
                      const ordinal_type order,
                      const ordinal_type offset ) {
   switch (cell.getBaseKey()) {
   // case shards::Tetrahedron<>::key: getWarpBlendLatticeTetrahedron( points, order, offset );  break;
   // case shards::Triangle<>::key:     getWarpBlendLatticeTriangle   ( points, order, offset );  break;
   case shards::Line<>::key:         getWarpBlendLatticeLine       ( points, order, offset );  break;
   default: {
     INTREPID2_TEST_FOR_EXCEPTION( true , std::invalid_argument ,
                                   ">>> ERROR (Intrepid2::PointTools::getWarpBlendLattice): the specified cell type is not supported." );
   }
   }
 }
Ejemplo n.º 12
0
    unsigned 
    getLocalSideIndexFromGlobalNodeList(const ArrayCellGIDs& cellGIDs, 
					const ArraySideGIDs& sideGIDs,
					const shards::CellTopology& cell)
  {
    unsigned cell_dim = cell.getDimension();
    //TEUCHOS_TEST_FOR_EXCEPTION(!cell.getSubcellHomogeneity(cell_dim - 1),
    //	       std::runtime_error, "Sides are not homogeneous!");
    
    unsigned local_side;
    bool found_local_side = false;
    unsigned side = 0;  
    while ( (side < cell.getSideCount()) && (!found_local_side) ) {
      
      const shards::CellTopology 
	side_topo(cell.getCellTopologyData(cell.getDimension()-1, side));
      
      unsigned num_side_nodes = 
	cell.getCellTopologyData()->side[side].topology->node_count;
 

      std::list<unsigned> tmp_side_gid_list;
      for (unsigned node = 0; node < num_side_nodes; ++node)
	tmp_side_gid_list.push_back(cellGIDs[cell.getNodeMap(cell_dim - 1, 
							     side, node)]);
     
      bool side_matches = true;
      unsigned node = 0;
      while ( side_matches && (node < num_side_nodes) ) {

	std::list<unsigned>::iterator search = 
	  std::find(tmp_side_gid_list.begin(), tmp_side_gid_list.end(),
		    sideGIDs[node]);
	
	if (search == tmp_side_gid_list.end())
	  side_matches = false;
	  
	++node;
      }
      
      if (side_matches) {
	found_local_side = true;
	local_side = side;
      }
      
      ++side;
    }
    
    TEUCHOS_TEST_FOR_EXCEPTION(!found_local_side, std::runtime_error,
		       "Failed to find side!");
    
    return local_side;
  }
  Basis_Constant_FEM<SpT,OT,PT>::
  Basis_Constant_FEM(const shards::CellTopology cellTopo) {
    const ordinal_type spaceDim = cellTopo.getDimension();

    this->basisCardinality_  = 1;
    this->basisDegree_       = 0;
    this->basisCellTopology_ = cellTopo;
    this->basisType_         = Intrepid2::BASIS_FEM_DEFAULT;
    this->basisCoordinates_  = Intrepid2::COORDINATES_CARTESIAN;

    // initialize tags
    {
      // Basis-dependent intializations
      const ordinal_type tagSize  = 4;        // size of DoF tag, i.e., number of fields in the tag
      const ordinal_type posScDim = 0;        // position in the tag, counting from 0, of the subcell dim
      const ordinal_type posScOrd = 1;        // position in the tag, counting from 0, of the subcell ordinal
      const ordinal_type posDfOrd = 2;        // position in the tag, counting from 0, of DoF ordinal relative to the subcell

      // An array with local DoF tags assigned to the basis functions, in the order of their local enumeration
      ordinal_type tags[4] = { spaceDim, 0, 0, 1 };

      ordinal_type_array_1d_host tagView(&tags[0], 4);

      this->setOrdinalTagData(this->tagToOrdinal_,
                              this->ordinalToTag_,
                              tagView,
                              this->basisCardinality_,
                              tagSize,
                              posScDim,
                              posScOrd,
                              posDfOrd);
    }

    // dofCoords on host and create its mirror view to device
    Kokkos::DynRankView<typename scalarViewType::value_type,typename SpT::array_layout,Kokkos::HostSpace>
      dofCoords("dofCoordsHost", this->basisCardinality_, spaceDim), cellVerts("cellVerts", spaceDim);

    CellTools<SpT>::getReferenceCellCenter(Kokkos::subview(dofCoords, 0, Kokkos::ALL()),
                                           cellVerts,
                                           cellTopo);

    this->dofCoords_ = Kokkos::create_mirror_view(typename SpT::memory_space(), dofCoords);
    Kokkos::deep_copy(this->dofCoords_, dofCoords);
  }
void mapToPhysicalFrame(ArrayPhysPoint      &        physPoints,
                                           const ArrayRefPoint &        refPoints,
                                           const ArrayCell     &        cellWorkset,
                                           const shards::CellTopology & cellTopo,
                                           const int &                  whichCell)
{
  int spaceDim  = (int)cellTopo.getDimension();
  int numCells  = cellWorkset.dimension(0);
  //points can be rank-2 (P,D), or rank-3 (C,P,D)
  int numPoints = (refPoints.rank() == 2) ? refPoints.dimension(0) : refPoints.dimension(1);

  // Initialize physPoints
  for(int i = 0; i < physPoints.dimentions(0); i++)
    for(int j = 0; j < physPoints.dimentions(1); j++)  
      for(int k = 0; k < physPoints.dimentions(2); k++)
         physPoints(i,j,k) = 0.0;
  

}
Ejemplo n.º 15
0
  void 
  PointTools::
  getLattice( /**/  Kokkos::DynRankView<pointValueType,pointProperties...> points,
              const shards::CellTopology cell,
              const ordinal_type         order,
              const ordinal_type         offset,
              const EPointType           pointType ) {
#ifdef HAVE_INTREPID2_DEBUG
    INTREPID2_TEST_FOR_EXCEPTION( points.rank() != 2,
                                  std::invalid_argument ,
                                  ">>> ERROR (PointTools::getLattice): points rank must be 2." );
    INTREPID2_TEST_FOR_EXCEPTION( order < 0 || offset < 0,
                                  std::invalid_argument ,
                                  ">>> ERROR (PointTools::getLattice): order and offset must be positive values." );

    const size_type latticeSize = getLatticeSize( cell, order, offset );
    const size_type spaceDim = cell.getDimension();
    
    INTREPID2_TEST_FOR_EXCEPTION( points.dimension(0) != latticeSize ||
                                  points.dimension(1) != spaceDim,
                                  std::invalid_argument ,
                                  ">>> ERROR (PointTools::getLattice): dimension does not match to lattice size." );
#endif

    // const auto latticeSize = getLatticeSize( cell, order, offset );
    // const auto spaceDim = cell.getDimension();
    
    // // the interface assumes that the input array follows the cell definition
    // // so, let's match all dimensions according to the cell specification
    // typedef Kokkos::pair<ordinal_type,ordinal_type> range_type;
    // auto pts = Kokkos::subview( points, 
    //                                    range_type(0, latticeSize), 
    //                                    range_type(0, spaceDim) );   
    switch (pointType) {
    case POINTTYPE_EQUISPACED:  getEquispacedLattice( points, cell, order, offset ); break;
    case POINTTYPE_WARPBLEND:   getWarpBlendLattice ( points, cell, order, offset ); break;
    default: {
      INTREPID2_TEST_FOR_EXCEPTION( true ,
                                    std::invalid_argument ,
                                    ">>> ERROR (PointTools::getLattice): invalid EPointType." );
    }
    }
  }
  void
  CellTools<SpT>::
  mapToReferenceSubcell( /**/  Kokkos::DynRankView<refSubcellPointValueType,refSubcellPointProperties...> refSubcellPoints,
                         const Kokkos::DynRankView<paramPointValueType,paramPointProperties...>           paramPoints,
                         const ordinal_type subcellDim,
                         const ordinal_type subcellOrd,
                         const shards::CellTopology parentCell ) {
#ifdef HAVE_INTREPID2_DEBUG
    INTREPID2_TEST_FOR_EXCEPTION( !hasReferenceCell(parentCell), std::invalid_argument,
                                  ">>> ERROR (Intrepid2::CellTools::mapToReferenceSubcell): the specified cell topology does not have a reference cell.");

    INTREPID2_TEST_FOR_EXCEPTION( subcellDim != 1 &&
                                  subcellDim != 2, std::invalid_argument,
                                  ">>> ERROR (Intrepid2::CellTools::mapToReferenceSubcell): method defined only for 1 and 2-dimensional subcells.");

    INTREPID2_TEST_FOR_EXCEPTION( subcellOrd <  0 ||
                                  subcellOrd >= parentCell.getSubcellCount(subcellDim), std::invalid_argument,
                                  ">>> ERROR (Intrepid2::CellTools::mapToReferenceSubcell): subcell ordinal out of range.");

    // refSubcellPoints is rank-2 (P,D1), D1 = cell dimension
    INTREPID2_TEST_FOR_EXCEPTION( refSubcellPoints.rank() != 2, std::invalid_argument,
                                  ">>> ERROR (Intrepid2::CellTools::mapToReferenceSubcell): refSubcellPoints must have rank 2.");
    INTREPID2_TEST_FOR_EXCEPTION( refSubcellPoints.dimension(1) != parentCell.getDimension(), std::invalid_argument,
                                  ">>> ERROR (Intrepid2::CellTools::mapToReferenceSubcell): refSubcellPoints dimension (1) does not match to parent cell dimension.");

    // paramPoints is rank-2 (P,D2) with D2 = subcell dimension
    INTREPID2_TEST_FOR_EXCEPTION( paramPoints.rank() != 2, std::invalid_argument,
                                  ">>> ERROR (Intrepid2::CellTools::mapToReferenceSubcell): paramPoints must have rank 2.");
    INTREPID2_TEST_FOR_EXCEPTION( paramPoints.dimension(1) != subcellDim, std::invalid_argument,
                                  ">>> ERROR (Intrepid2::CellTools::mapToReferenceSubcell): paramPoints dimension (1) does not match to subcell dimension.");

    // cross check: refSubcellPoints and paramPoints: dimension 0 must match
    INTREPID2_TEST_FOR_EXCEPTION( refSubcellPoints.dimension(0) < paramPoints.dimension(0), std::invalid_argument,
                                  ">>> ERROR (Intrepid2::CellTools::mapToReferenceSubcell): refSubcellPoints dimension (0) does not match to paramPoints dimension(0).");
#endif


    const auto cellDim = parentCell.getDimension();
    const auto numPts  = paramPoints.dimension(0);

    // Get the subcell map, i.e., the coefficients of the parametrization function for the subcell

    // can i get this map from devices ?
    subcellParamViewType subcellMap;
    getSubcellParametrization( subcellMap,
                               subcellDim,
                               parentCell );

    // subcell parameterization should be small computation (numPts is small) and it should be decorated with
    // kokkos inline... let's not do this yet

    // Apply the parametrization map to every point in parameter domain
    switch (subcellDim) {
    case 2: {
      for (size_type pt=0;pt<numPts;++pt) {
        const auto u = paramPoints(pt, 0);
        const auto v = paramPoints(pt, 1);

        // map_dim(u,v) = c_0(dim) + c_1(dim)*u + c_2(dim)*v because both Quad and Tri ref faces are affine!
        for (size_type i=0;i<cellDim;++i)
          refSubcellPoints(pt, i) = subcellMap(subcellOrd, i, 0) + ( subcellMap(subcellOrd, i, 1)*u +
                                                                     subcellMap(subcellOrd, i, 2)*v );
      }
      break;
    }
    case 1: {
      for (size_type pt=0;pt<numPts;++pt) {
        const auto u = paramPoints(pt, 0);
        for (size_type i=0;i<cellDim;++i)
          refSubcellPoints(pt, i) = subcellMap(subcellOrd, i, 0) + ( subcellMap(subcellOrd, i, 1)*u );
      }
      break;
    }
    default: {
      INTREPID2_TEST_FOR_EXCEPTION( subcellDim != 1 &&
                                    subcellDim != 2, std::invalid_argument,
                                    ">>> ERROR (Intrepid2::CellTools::mapToReferenceSubcell): method defined only for 1 and 2-subcells");
    }
    }
  }
int Intrepid2FieldPattern::getDimension() const
{
   const shards::CellTopology ct = intrepidBasis_->getBaseCellTopology();
   return ct.getDimension();
}
Ejemplo n.º 18
0
void mapToPhysicalFrame(ArrayPhysPoint      &        physPoints,
                                           const ArrayRefPoint &        refPoints,
                                           const ArrayCell     &        cellWorkset,
                                           const shards::CellTopology & cellTopo,
                                           const int &                  whichCell)
{
  int spaceDim  = (int)cellTopo.getDimension();
  int numCells  = cellWorkset.dimension(0);
  //points can be rank-2 (P,D), or rank-3 (C,P,D)
  int numPoints = (refPoints.rank() == 2) ? refPoints.dimension(0) : refPoints.dimension(1);

/*  // Mapping is computed using an appropriate H(grad) basis function: define RCP to the base class
  Teuchos::RCP<Basis<Scalar, FieldContainer<Scalar> > > HGRAD_Basis;

  // Choose the H(grad) basis depending on the cell topology. \todo define maps for shells and beams
  switch( cellTopo.getKey() ){

    // Standard Base topologies (number of cellWorkset = number of vertices)
      case shards::Line<2>::key:
      HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_LINE_C1_FEM<Scalar, FieldContainer<Scalar> >() );
      break;

    case shards::Triangle<3>::key:
      HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_TRI_C1_FEM<Scalar, FieldContainer<Scalar> >() );
      break;

    case shards::Quadrilateral<4>::key:
      HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_QUAD_C1_FEM<Scalar, FieldContainer<Scalar> >() );
      break;

    case shards::Tetrahedron<4>::key:
      HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_TET_C1_FEM<Scalar, FieldContainer<Scalar> >() );
      break;

    case shards::Hexahedron<8>::key:
      HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_HEX_C1_FEM<Scalar, FieldContainer<Scalar> >() );
      break;

    case shards::Wedge<6>::key:
      HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_WEDGE_C1_FEM<Scalar, FieldContainer<Scalar> >() );
      break;

    case shards::Pyramid<5>::key:
          HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_PYR_C1_FEM<Scalar, FieldContainer<Scalar> >() );
          break;

    // Standard Extended topologies
    case shards::Triangle<6>::key:
      HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_TRI_C2_FEM<Scalar, FieldContainer<Scalar> >() );
      break;

    case shards::Quadrilateral<9>::key:
      HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_QUAD_C2_FEM<Scalar, FieldContainer<Scalar> >() );
      break;

    case shards::Tetrahedron<10>::key:
      HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_TET_C2_FEM<Scalar, FieldContainer<Scalar> >() );
      break;

    case shards::Tetrahedron<11>::key:
      HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_TET_COMP12_FEM<Scalar, FieldContainer<Scalar> >() );
      break;

    case shards::Hexahedron<27>::key:
      HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_HEX_C2_FEM<Scalar, FieldContainer<Scalar> >() );
      break;

    case shards::Wedge<18>::key:
      HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_WEDGE_C2_FEM<Scalar, FieldContainer<Scalar> >() );
      break;

    // These extended topologies are not used for mapping purposes
    case shards::Quadrilateral<8>::key:
    case shards::Hexahedron<20>::key:
    case shards::Wedge<15>::key:
      TEUCHOS_TEST_FOR_EXCEPTION( (true), std::invalid_argument,
                          ">>> ERROR (Intrepid::CellTools::mapToPhysicalFrame): Cell topology not supported. ");
      break;

    // Base and Extended Line, Beam and Shell topologies 
     case shards::Line<3>::key:
    case shards::Beam<2>::key:
    case shards::Beam<3>::key:
    case shards::ShellLine<2>::key:
    case shards::ShellLine<3>::key:
    case shards::ShellTriangle<3>::key:
    case shards::ShellTriangle<6>::key:
    case shards::ShellQuadrilateral<4>::key:
    case shards::ShellQuadrilateral<8>::key:
    case shards::ShellQuadrilateral<9>::key:
      TEUCHOS_TEST_FOR_EXCEPTION( (true), std::invalid_argument,
                          ">>> ERROR (Intrepid::CellTools::mapToPhysicalFrame): Cell topology not supported. ");
      break;
    default:
      TEUCHOS_TEST_FOR_EXCEPTION( (true), std::invalid_argument,
                          ">>> ERROR (Intrepid::CellTools::mapToPhysicalFrame): Cell topology not supported.");
  }// switch  

  // Temp (F,P) array for the values of nodal basis functions at the reference points
  int basisCardinality = HGRAD_Basis -> getCardinality();
  FieldContainer<Scalar> basisVals(basisCardinality, numPoints);
*/
  // Initialize physPoints
  for(int i = 0; i < physPoints.dimentions(0); i++)
    for(int j = 0; j < physPoints.dimentions(1); j++)  
      for(int k = 0; k < physPoints.dimentions(2); k++)
         physPoints(i,j,k) = 0.0;
  

}
Ejemplo n.º 19
0
void testSubcellParametrizations(int&                               errorFlag,
                                 const shards::CellTopology&        parentCell,
                                 const FieldContainer<double>&      subcParamVert_A,
                                 const FieldContainer<double>&      subcParamVert_B,
                                 const int                          subcDim,
                                 const Teuchos::RCP<std::ostream>&  outStream){
  
  // Get cell dimension and subcell count
  int cellDim      = parentCell.getDimension();
  int subcCount    = parentCell.getSubcellCount(subcDim);
  
  
  // Loop over subcells of the specified dimension
  for(int subcOrd = 0; subcOrd < subcCount; subcOrd++){
    int subcVertexCount = parentCell.getVertexCount(subcDim, subcOrd);
    
    
    // Storage for correct reference subcell vertices and for the images of the parametrization domain points
    FieldContainer<double> refSubcellVertices(subcVertexCount, cellDim);
    FieldContainer<double> mappedParamVertices(subcVertexCount, cellDim);
    
    
    // Retrieve correct reference subcell vertices
    CellTools<double>::getReferenceSubcellVertices(refSubcellVertices, subcDim, subcOrd, parentCell);
    
    
    // Map vertices of the parametrization domain to 1 or 2-subcell with ordinal subcOrd
    // For edges parametrization domain is always 1-cube passed as "subcParamVert_A"
    if(subcDim == 1) {
      CellTools<double>::mapToReferenceSubcell(mappedParamVertices,
                                               subcParamVert_A,
                                               subcDim,
                                               subcOrd,
                                               parentCell);
    }
    // For faces need to treat Triangle and Quadrilateral faces separately
    else if(subcDim == 2) {
      
      // domain "subcParamVert_A" is the standard 2-simplex  
      if(subcVertexCount == 3){
        CellTools<double>::mapToReferenceSubcell(mappedParamVertices,
                                                 subcParamVert_A,
                                                 subcDim,
                                                 subcOrd,
                                                 parentCell);
      }
      // Domain "subcParamVert_B" is the standard 2-cube
      else if(subcVertexCount == 4){
        CellTools<double>::mapToReferenceSubcell(mappedParamVertices,
                                                 subcParamVert_B,
                                                 subcDim,
                                                 subcOrd,
                                                 parentCell);
      }
    }
    
    // Compare the images of the parametrization domain vertices with the true vertices.
    for(int subcVertOrd = 0; subcVertOrd < subcVertexCount; subcVertOrd++){
      for(int dim = 0; dim <  cellDim; dim++){
        
        if(mappedParamVertices(subcVertOrd, dim) != refSubcellVertices(subcVertOrd, dim) ) {
          errorFlag++; 
          *outStream 
            << std::setw(70) << "^^^^----FAILURE!" << "\n"
            << " Cell Topology = " << parentCell.getName() << "\n"
            << " Parametrization of subcell " << subcOrd << " which is "
            << parentCell.getName(subcDim,subcOrd) << " failed for vertex " << subcVertOrd << ":\n"
            << " parametrization map fails to map correctly coordinate " << dim << " of that vertex\n\n";
          
        }//if
      }// for dim 
    }// for subcVertOrd      
  }// for subcOrd
  
}
  void
  OrientationTools<SpT>::
  modifyBasisByOrientation(/**/  Kokkos::DynRankView<outputValueType,outputProperties...> output,
                           const Kokkos::DynRankView<inputValueType, inputProperties...>  input,
                           const Kokkos::DynRankView<ortValueType,   ortProperties...>    orts,
                           const BasisPtrType basis ) {
#ifdef HAVE_INTREPID2_DEBUG
    {
      INTREPID2_TEST_FOR_EXCEPTION( input.rank() != output.rank(), std::invalid_argument,
                                    ">>> ERROR (OrientationTools::modifyBasisByOrientation): Input and output rank are not 3.");
      for (ordinal_type i=0;i<input.rank();++i)
        INTREPID2_TEST_FOR_EXCEPTION( input.dimension(i) != output.dimension(i), std::invalid_argument,
                                      ">>> ERROR (OrientationTools::modifyBasisByOrientation): Input and output dimension does not match.");

      INTREPID2_TEST_FOR_EXCEPTION( input.dimension(1) != basis->getCardinality(), std::invalid_argument,
                                    ">>> ERROR (OrientationTools::modifyBasisByOrientation): Field dimension of input/output does not match to basis cardinality.");
      INTREPID2_TEST_FOR_EXCEPTION( input.dimension(3) != basis->getBaseCellTopology().getDimension(), std::invalid_argument,
                                    ">>> ERROR (OrientationTools::modifyBasisByOrientation): Space dimension of input/output does not match to topology dimension.");
    }
#endif
    if (basis->requireOrientation()) {
      auto ordinalToTag = Kokkos::create_mirror_view(typename SpT::memory_space(), basis->getAllDofTags());
      auto tagToOrdinal = Kokkos::create_mirror_view(typename SpT::memory_space(), basis->getAllDofOrdinal());
      
      Kokkos::deep_copy(ordinalToTag, basis->getAllDofTags());
      Kokkos::deep_copy(tagToOrdinal, basis->getAllDofOrdinal());
      
      const ordinal_type 
        numCells  = output.dimension(0),
        //numBasis  = output.dimension(1),
        numPoints = output.dimension(2),
        dimBasis  = output.dimension(3);
      
      const CoeffMatrixDataViewType matData = createCoeffMatrix(basis);
      const shards::CellTopology cellTopo = basis->getBaseCellTopology();
      
      const ordinal_type 
        numVerts = cellTopo.getVertexCount(), 
        numEdges = cellTopo.getEdgeCount(),
        numFaces = cellTopo.getFaceCount();
      
      const ordinal_type intrDim = ( numEdges == 0 ? 1 : 
                                     numFaces == 0 ? 2 : 
                                     /**/            3 );
      
      for (auto cell=0;cell<numCells;++cell) {
        auto out = Kokkos::subview(output, cell, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
        auto in  = Kokkos::subview(input,  cell, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
        
        // vertex copy (no orientation)
        for (auto vertId=0;vertId<numVerts;++vertId) {
          const auto i = tagToOrdinal(0, vertId, 0);
          if (i != -1) // if dof does not exist i returns with -1
            for (auto j=0;j<numPoints;++j)
              for (auto k=0;k<dimBasis;++k)
                out(i, j, k) = in(i, j, k);
        }
        
        // interior copy
        {
          const auto ordIntr = tagToOrdinal(intrDim, 0, 0);
          if (ordIntr != -1) {
            const auto ndofIntr = ordinalToTag(ordIntr, 3);
            for (auto i=0;i<ndofIntr;++i) {
              const auto ii = tagToOrdinal(intrDim, 0, i);
              for (auto j=0;j<numPoints;++j)
                for (auto k=0;k<dimBasis;++k)
                  out(ii, j, k) = in(ii, j, k);
            }
          }
        }
        
        // edge transformation
        if (numEdges > 0) {
          ordinal_type ortEdges[12];
          orts(cell).getEdgeOrientation(ortEdges, numEdges);
          
          // apply coeff matrix
          for (auto edgeId=0;edgeId<numEdges;++edgeId) {
            const auto ordEdge = tagToOrdinal(1, edgeId, 0);
            
            if (ordEdge != -1) {
              const auto ndofEdge = ordinalToTag(ordEdge, 3);
              const auto mat = Kokkos::subview(matData, 
                                               edgeId, ortEdges[edgeId], 
                                               Kokkos::ALL(), Kokkos::ALL());
              
              for (auto j=0;j<numPoints;++j) 
                for (auto i=0;i<ndofEdge;++i) {
                  const auto ii = tagToOrdinal(1, edgeId, i);
                  
                  for (auto k=0;k<dimBasis;++k) {
                    double temp = 0.0;
                    for (auto l=0;l<ndofEdge;++l) {
                      const auto ll = tagToOrdinal(1, edgeId, l);
                      temp += mat(i,l)*in(ll, j, k);
                    }
                    out(ii, j, k) = temp;
                  }
                }
            }
          }
        }
        
        // face transformation
        if (numFaces > 0) {
          ordinal_type ortFaces[12];
          orts(cell).getFaceOrientation(ortFaces, numFaces);
          
          // apply coeff matrix
          for (auto faceId=0;faceId<numFaces;++faceId) {
            const auto ordFace = tagToOrdinal(2, faceId, 0);
            
            if (ordFace != -1) {
              const auto ndofFace = ordinalToTag(ordFace, 3);
              const auto mat = Kokkos::subview(matData, 
                                               numEdges+faceId, ortFaces[faceId], 
                                               Kokkos::ALL(), Kokkos::ALL());
              
              for (auto j=0;j<numPoints;++j) 
                for (auto i=0;i<ndofFace;++i) {
                  const auto ii = tagToOrdinal(2, faceId, i);
                  
                  for (auto k=0;k<dimBasis;++k) {
                    double temp = 0.0;
                    for (auto l=0;l<ndofFace;++l) {
                      const auto ll = tagToOrdinal(2, faceId, l);
                      temp += mat(i,l)*in(ll, j, k);
                    }
                    out(ii, j, k) = temp;
                  }
                }
            }
          }
        }
        
      }
    } else {
      Kokkos::deep_copy(output, input);      
    }
  }
Ejemplo n.º 21
0
void build_element_matrix_and_rhs(FieldContainer<value_type> & A,
                                  FieldContainer<value_type> & b,
                                  DefaultCubatureFactory<value_type> & cubature_factory,
                                  const BasisSet_HGRAD_TRI_Cn_FEM<value_type,FieldContainer<value_type> > &basis_set,
                                  const int *element,
                                  const int *boundary,
                                  const FieldContainer<value_type> & cell_nodes,
                                  const Orientation ort,
                                  const int nx,
                                  const int ny) {

  // Step 0: initilization
  const auto &cell_basis = basis_set.getCellBasis();
  const auto &side_basis = basis_set.getLineBasis();

  const shards::CellTopology cell_topo = cell_basis.getBaseCellTopology();
  const shards::CellTopology side_topo = side_basis.getBaseCellTopology();

  const int nbf_cell = cell_basis.getCardinality();
  //const int nbf_side = side_basis.getCardinality();

  const int ndim_cell = cell_topo.getDimension();
  const int ndim_side = side_topo.getDimension();

  //const int nside = cell_topo.getEdgeCount();

  const int p = cell_basis.getDegree();

  // Step 1: create cubature data for integration
  Teuchos::RCP<Cubature<value_type> > cell_cub = cubature_factory.create(cell_topo, 2*p);
  Teuchos::RCP<Cubature<value_type> > side_cub = cubature_factory.create(side_topo, 2*p);

  const int npts_cell_cub = cell_cub->getNumPoints();
  const int npts_side_cub = side_cub->getNumPoints();

  // - cell related containers
  FieldContainer<value_type> cub_points_cell(npts_cell_cub, ndim_cell);
  FieldContainer<value_type> cub_points_cell_physical(1, npts_cell_cub, ndim_cell);
  FieldContainer<value_type> cub_weights_cell(npts_cell_cub);

  FieldContainer<value_type> jacobian_cell(1, npts_cell_cub, ndim_cell, ndim_cell);
  FieldContainer<value_type> jacobian_inv_cell(1, npts_cell_cub, ndim_cell, ndim_cell);
  FieldContainer<value_type> jacobian_det_cell(1, npts_cell_cub);

  FieldContainer<value_type> weighted_measure_cell(1, npts_cell_cub);

  FieldContainer<value_type> value_of_basis_at_cub_points_cell(nbf_cell, npts_cell_cub);
  FieldContainer<value_type> value_of_reordered_basis_at_cub_points_cell(nbf_cell, npts_cell_cub);

  FieldContainer<value_type> transformed_value_of_basis_at_cub_points_cell(1, nbf_cell, npts_cell_cub);
  FieldContainer<value_type> weighted_transformed_value_of_basis_at_cub_points_cell(1, nbf_cell, npts_cell_cub);

  FieldContainer<value_type> grad_of_basis_at_cub_points_cell(nbf_cell, npts_cell_cub, ndim_cell);
  FieldContainer<value_type> grad_of_reordered_basis_at_cub_points_cell(nbf_cell, npts_cell_cub, ndim_cell);

  FieldContainer<value_type> transformed_grad_of_basis_at_cub_points_cell(1, nbf_cell, npts_cell_cub, ndim_cell);
  FieldContainer<value_type> weighted_transformed_grad_of_basis_at_cub_points_cell(1, nbf_cell, npts_cell_cub, ndim_cell);

  FieldContainer<value_type> rhs_at_cub_points_cell_physical(1, npts_cell_cub);
  FieldContainer<value_type> rhs_and_soln_vector(1, nbf_cell);

  // - subcell related containders
  FieldContainer<value_type> cub_points_side(npts_side_cub, ndim_side);
  FieldContainer<value_type> cub_weights_side(npts_side_cub);
  FieldContainer<value_type> cub_points_side_refcell(npts_side_cub, ndim_cell);
  FieldContainer<value_type> cub_points_side_physical(1, npts_side_cub, ndim_cell);

  FieldContainer<value_type> jacobian_side_refcell(1, npts_side_cub, ndim_cell, ndim_cell);
  FieldContainer<value_type> jacobian_det_side_refcell(1, npts_side_cub);

  FieldContainer<value_type> weighted_measure_side_refcell(1, npts_side_cub);

  FieldContainer<value_type> value_of_basis_at_cub_points_side_refcell(nbf_cell, npts_side_cub);
  FieldContainer<value_type> value_of_reordered_basis_at_cub_points_side_refcell(nbf_cell, npts_side_cub);

  FieldContainer<value_type> transformed_value_of_basis_at_cub_points_side_refcell(1, nbf_cell, npts_side_cub);
  FieldContainer<value_type> weighted_transformed_value_of_basis_at_cub_points_side_refcell(1, nbf_cell, npts_side_cub);

  FieldContainer<value_type> neumann_data_at_cub_points_side_physical(1, npts_side_cub);
  FieldContainer<value_type> neumann_fields_per_side(1, nbf_cell);

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

  CellTools<value_type>::setJacobian   (jacobian_cell, cub_points_cell, cell_nodes, cell_topo);
  CellTools<value_type>::setJacobianInv(jacobian_inv_cell, jacobian_cell);
  CellTools<value_type>::setJacobianDet(jacobian_det_cell, jacobian_cell);

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

  // Step 1: mass matrix: tabulate values of basis functions at cubature points
  cell_basis.getValues(value_of_basis_at_cub_points_cell, cub_points_cell, OPERATOR_VALUE);
  if (apply_orientation) {
    OrientationTools<value_type>::verbose = false;
    OrientationTools<value_type>::getBasisFunctionsByTopology(value_of_reordered_basis_at_cub_points_cell,
                                                              value_of_basis_at_cub_points_cell,
                                                              cell_basis);
    OrientationTools<value_type>::getModifiedBasisFunctions(value_of_basis_at_cub_points_cell,
                                                            value_of_reordered_basis_at_cub_points_cell,
                                                            basis_set,
                                                            ort);
    OrientationTools<value_type>::verbose = false;
  }

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

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

  // integrate
  FunctionSpaceTools::integrate<value_type>(A,
                                            transformed_value_of_basis_at_cub_points_cell,
                                            weighted_transformed_value_of_basis_at_cub_points_cell,
                                            COMP_BLAS);

  // Step 2: stiffness matrix: tabulate grad values of basis functions at cubature points
  cell_basis.getValues(grad_of_basis_at_cub_points_cell, cub_points_cell, OPERATOR_GRAD);
  if (apply_orientation) {
    OrientationTools<value_type>::getBasisFunctionsByTopology(grad_of_reordered_basis_at_cub_points_cell,
                                                              grad_of_basis_at_cub_points_cell,
                                                              cell_basis);
    OrientationTools<value_type>::getModifiedBasisFunctions(grad_of_basis_at_cub_points_cell,
                                                            grad_of_reordered_basis_at_cub_points_cell,
                                                            basis_set,
                                                            ort);
  }

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

  // multiply with weighted measure
  FunctionSpaceTools::multiplyMeasure<value_type>(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<value_type>(A,
                                            transformed_grad_of_basis_at_cub_points_cell,
                                            weighted_transformed_grad_of_basis_at_cub_points_cell,
                                            COMP_BLAS,
                                            true);

  // Step 3: compute rhs function
  CellTools<value_type>::mapToPhysicalFrame(cub_points_cell_physical, cub_points_cell, cell_nodes, cell_topo);

  // evaluate rhs function
  eval_rhs(rhs_at_cub_points_cell_physical,
           cub_points_cell_physical,
           nx, ny);

  // compute rhs
  FunctionSpaceTools::integrate<value_type>(b,
                                            rhs_at_cub_points_cell_physical,
                                            weighted_transformed_value_of_basis_at_cub_points_cell,
                                            COMP_BLAS);

  // Step 4: compute boundary condition
  side_cub->getCubature(cub_points_side, cub_weights_side);
  const int nside = cell_topo.getSideCount();
  for (int i=0;i<nside;++i) {
    if (boundary[i]) {
      // compute geometric cell information
      CellTools<value_type>::mapToReferenceSubcell(cub_points_side_refcell, cub_points_side, ndim_side, i, cell_topo);
      CellTools<value_type>::setJacobian   (jacobian_side_refcell, cub_points_side_refcell, cell_nodes, cell_topo);
      CellTools<value_type>::setJacobianDet(jacobian_det_side_refcell, jacobian_side_refcell);

      // compute weighted edge measure
      FunctionSpaceTools::computeEdgeMeasure<value_type>(weighted_measure_side_refcell,
                                                         jacobian_side_refcell,
                                                         cub_weights_side,
                                                         i,
                                                         cell_topo);

      // tabulate values of basis functions at side cubature points, in the reference parent cell domain
      cell_basis.getValues(value_of_basis_at_cub_points_side_refcell, cub_points_side_refcell, OPERATOR_VALUE);
      if (apply_orientation) {
        OrientationTools<value_type>::getBasisFunctionsByTopology(value_of_reordered_basis_at_cub_points_side_refcell,
                                                                  value_of_basis_at_cub_points_side_refcell,
                                                                  cell_basis);
        OrientationTools<value_type>::getModifiedBasisFunctions(value_of_basis_at_cub_points_side_refcell,
                                                                value_of_reordered_basis_at_cub_points_side_refcell,
                                                                basis_set,
                                                                ort);
      }

      // transform
      FunctionSpaceTools::HGRADtransformVALUE<value_type>(transformed_value_of_basis_at_cub_points_side_refcell,
                                                          value_of_basis_at_cub_points_side_refcell);

      // multiply with weighted measure
      FunctionSpaceTools::multiplyMeasure<value_type>(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 boundary

      // map side cubature points in reference parent cell domain to physical space
      CellTools<value_type>::mapToPhysicalFrame(cub_points_side_physical, cub_points_side_refcell, cell_nodes, cell_topo);

      // now compute data
      eval_neumann(neumann_data_at_cub_points_side_physical,
                   cub_points_side_physical,
                   jacobian_side_refcell,
                   cell_topo,
                   i,
                   nx, ny);

      FunctionSpaceTools::integrate<value_type>(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<value_type>::add(b, neumann_fields_per_side);;
    }
  }
}
Ejemplo n.º 22
0
void compute_element_error(magnitude_type & interpolation_error,
                           magnitude_type & solution_norm,
                           const int *element,
                           const FieldContainer<value_type> & cell_nodes,
                           const BasisSet_HGRAD_TRI_Cn_FEM<value_type,FieldContainer<value_type> > &basis_set,
                           const FieldContainer<value_type> &sol,
                           const Orientation ort,
                           const int nx,
                           const int ny) {
  // initialize return values
  interpolation_error = 0.0;
  solution_norm = 0.0;

  // general environment
  const auto &cell_basis = basis_set.getCellBasis();
  const shards::CellTopology cell_topo = cell_basis.getBaseCellTopology();

  const int nbf_cell = cell_basis.getCardinality();
  const int ndim_cell = cell_topo.getDimension();

  // create points to evaluate in the reference cell
  const int order = 10;
  const int npts = PointTools::getLatticeSize(cell_topo, order, 1);

  FieldContainer<value_type> ref_cell_pts(npts, ndim_cell);
  PointTools::getLattice<value_type>(ref_cell_pts,
                                     cell_topo,
                                     order, 1);

  // map the points to physical frame
  FieldContainer<value_type> phy_cell_pts(1, npts, ndim_cell);
  CellTools<value_type>::mapToPhysicalFrame(phy_cell_pts, ref_cell_pts, cell_nodes, cell_topo);
  phy_cell_pts.resize(npts, ndim_cell);

  // Step 1: compute L2 error

  // evaluate exact solution
  FieldContainer<double> exact_solution_val(1, npts);
  eval_exact(exact_solution_val,
             phy_cell_pts,
             nx, ny);

  // evaluate basis at interpolation points
  FieldContainer<value_type> value_of_basis_at_ref_cell_pts(nbf_cell, npts);
  FieldContainer<value_type> value_of_reordered_basis_at_ref_cell_pts(nbf_cell, npts);

  cell_basis.getValues(value_of_basis_at_ref_cell_pts, ref_cell_pts, OPERATOR_VALUE);
  if (apply_orientation) {
    OrientationTools<value_type>::getBasisFunctionsByTopology(value_of_reordered_basis_at_ref_cell_pts,
                                                              value_of_basis_at_ref_cell_pts,
                                                              cell_basis);
    OrientationTools<value_type>::getModifiedBasisFunctions(value_of_basis_at_ref_cell_pts,
                                                            value_of_reordered_basis_at_ref_cell_pts,
                                                            basis_set,
                                                            ort);
  }

  // transform values of basis functions
  FieldContainer<double> transformed_value_of_basis_at_ref_cell_pts(1, nbf_cell, npts);
  FunctionSpaceTools::HGRADtransformVALUE<value_type>(transformed_value_of_basis_at_ref_cell_pts,
                                                      value_of_basis_at_ref_cell_pts);

  FieldContainer<double> interpolant(1, npts);
  FunctionSpaceTools::evaluate<value_type>(interpolant,
                                           sol,
                                           transformed_value_of_basis_at_ref_cell_pts);

  // compute error and magnitude of solution
  RealSpaceTools<value_type>::subtract(interpolant, exact_solution_val);

  interpolation_error += RealSpaceTools<value_type>::vectorNorm(&interpolant[0],
                                                                interpolant.dimension(1),
                                                                NORM_TWO);

  solution_norm += RealSpaceTools<value_type>::vectorNorm(&exact_solution_val[0],
                                                          exact_solution_val.dimension(1),
                                                          NORM_TWO);

  // Step 2: compute H1 error
  // skip for now, not meaningful for this unit test
}
//---------------------------------------------------------------------------//
Teuchos::RCP<Intrepid::Basis<double,Intrepid::FieldContainer<double> > > 
IntrepidBasisFactory::create( const shards::CellTopology& cell_topo )
{

    Teuchos::RCP<Intrepid::Basis<double,Intrepid::FieldContainer<double> > > basis;
    
    switch( cell_topo.getKey() ){
      
	case shards::Line<2>::key:
	    basis = Teuchos::rcp( 
		new Intrepid::Basis_HGRAD_LINE_C1_FEM<
		double,Intrepid::FieldContainer<double> >() );
	    break;

	case shards::Triangle<3>::key:
	    basis = Teuchos::rcp( 
		new Intrepid::Basis_HGRAD_TRI_C1_FEM<
		double,Intrepid::FieldContainer<double> >() );
	    break;

	case shards::Triangle<6>::key:    
	    basis = Teuchos::rcp( 
		new Intrepid::Basis_HGRAD_TRI_C2_FEM<
		double,Intrepid::FieldContainer<double> >() );
	    break;
        
	case shards::Quadrilateral<4>::key:
	    basis = Teuchos::rcp( 
		new Intrepid::Basis_HGRAD_QUAD_C1_FEM<
		double,Intrepid::FieldContainer<double> >() );
	    break;
        
	case shards::Quadrilateral<9>::key:
	    basis = Teuchos::rcp( 
		new Intrepid::Basis_HGRAD_QUAD_C2_FEM<
		double,Intrepid::FieldContainer<double> >() );
	    break;
        
	case shards::Tetrahedron<4>::key:
	    basis = Teuchos::rcp( 
		new Intrepid::Basis_HGRAD_TET_C1_FEM<
		double,Intrepid::FieldContainer<double> >() );
	    break;
        
	case shards::Tetrahedron<10>::key:
	    basis = Teuchos::rcp( 
		new Intrepid::Basis_HGRAD_TET_C2_FEM<
		double,Intrepid::FieldContainer<double> >() );
	    break;
        
	case shards::Hexahedron<8>::key:
	    basis = Teuchos::rcp( 
		new Intrepid::Basis_HGRAD_HEX_C1_FEM<
		double,Intrepid::FieldContainer<double> >() );
	    break;

	case shards::Hexahedron<27>::key:
	    basis = Teuchos::rcp( 
		new Intrepid::Basis_HGRAD_HEX_C2_FEM<
		double,Intrepid::FieldContainer<double> >() );
	    break;
              
	case shards::Wedge<6>::key:
	    basis = Teuchos::rcp( 
		new Intrepid::Basis_HGRAD_WEDGE_C1_FEM<
		double,Intrepid::FieldContainer<double> >() );
	    break;
        
	case shards::Wedge<18>::key:
	    basis = Teuchos::rcp( 
		new Intrepid::Basis_HGRAD_WEDGE_C2_FEM<
		double,Intrepid::FieldContainer<double> >() );
	    break;

	case shards::Pyramid<5>::key:
	case shards::Pyramid<13>::key:
	case shards::Pyramid<14>::key:
	    basis = Teuchos::rcp( 
		new Intrepid::Basis_HGRAD_PYR_C1_FEM<
		double,Intrepid::FieldContainer<double> >() );
	    break;

	default:
	    bool topology_supported = false;
	    DTK_INSIST( topology_supported );
	    break;
    }

    return basis;
}
Ejemplo n.º 24
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;
}
Ejemplo n.º 25
0
void BilinearFormUtility::computeOptimalStiffnessMatrix(FieldContainer<double> &stiffness, 
                                                        FieldContainer<double> &optimalTestWeights,
                                                        BilinearFormPtr bilinearForm,
                                                        Teuchos::RCP<DofOrdering> trialOrdering, Teuchos::RCP<DofOrdering> testOrdering,
                                                        shards::CellTopology &cellTopo, FieldContainer<double> &physicalCellNodes,
                                                        FieldContainer<double> &cellSideParities) {
  // lots of code copied and pasted from the very similar computeStiffnessMatrix.  The difference here is that for each optimal test function,
  // we need to ask the bilinear form about each of its components (it's a vector whereas the other guy had just a single basis function
  // for each...), and then apply the appropriate weights....
  // physicalCellNodes: the nodal points for the element(s) with topology cellTopo
  //                 The dimensions are (numCells, numNodesPerElement, spaceDimension)
  // optimalTestWeights dimensions are: (numCells, numTrial, numTest) -- numTrial is the optTest index
  // stiffness dimensions are: (numCells, # trialOrdering Dofs, # trialOrdering Dofs)
  // (while (cell,trial,test) is more natural conceptually, I believe the above ordering makes
  //  more sense given the inversion that we must do to compute the optimal test functions...)
  
  // steps:
  // 0. Set up BasisCache
  // 3. For each (test, trial) combination:
  //   a. Apply the specified operators to the basis in the DofOrdering, at the cubature points
  //   b. Multiply the two bases together, weighted with Jacobian/Piola transform and cubature weights
  //   c. Pass the result to bilinearForm's applyBilinearFormData method
  //   d. Sum up (integrate) and place in stiffness matrix according to DofOrdering indices
  
  // 0. Set up Cubature
  
  unsigned numCells = physicalCellNodes.dimension(0);
  unsigned numNodesPerElem = physicalCellNodes.dimension(1);
  unsigned spaceDim = physicalCellNodes.dimension(2);
  
  // Check that cellTopo and physicalCellNodes agree
  TEUCHOS_TEST_FOR_EXCEPTION( ( numNodesPerElem != cellTopo.getNodeCount() ),
                     std::invalid_argument,
                     "Second dimension of physicalCellNodes and cellTopo.getNodeCount() do not match.");
  TEUCHOS_TEST_FOR_EXCEPTION( ( spaceDim != cellTopo.getDimension() ),
                     std::invalid_argument,
                     "Third dimension of physicalCellNodes and cellTopo.getDimension() do not match.");
  
  int numOptTestFunctions = optimalTestWeights.dimension(1); // should also == numTrialDofs
  
  TEUCHOS_TEST_FOR_EXCEPTION( ( optimalTestWeights.dimension(1) != stiffness.dimension(2) ),
                     std::invalid_argument,
                     "optimalTestWeights.dimension(1) (=" << optimalTestWeights.dimension(1) << ") and stiffness.dimension(2) (=" << stiffness.dimension(2) << ") do not match.");
  TEUCHOS_TEST_FOR_EXCEPTION( ( stiffness.dimension(1) != stiffness.dimension(2) ),
                     std::invalid_argument,
                     "stiffness.dimension(1) (=" << stiffness.dimension(1) << ") and stiffness.dimension(2) (=" << stiffness.dimension(2) << ") do not match.");
  
  // Set up BasisCache
  int cubDegreeTrial = trialOrdering->maxBasisDegree();
  int cubDegreeTest = testOrdering->maxBasisDegree();
  int cubDegree = cubDegreeTrial + cubDegreeTest;
  
  BasisCache basisCache(physicalCellNodes, cellTopo, *trialOrdering, cubDegreeTest, true); // DO create side caches, too
  
  unsigned numSides = CamelliaCellTools::getSideCount(cellTopo);

  vector<int> testIDs = bilinearForm->testIDs();
  vector<int>::iterator testIterator;
  
  vector<int> trialIDs = bilinearForm->trialIDs();
  vector<int>::iterator trialIterator;
  
  BasisPtr trialBasis,testBasis;
  
  stiffness.initialize(0.0);
  
  for (trialIterator = trialIDs.begin(); trialIterator != trialIDs.end(); trialIterator++) {
    int trialID = *trialIterator;
    
    for (int optTestIndex=0; optTestIndex < numOptTestFunctions; optTestIndex++) {
      FieldContainer<double> weights(numCells,testOrdering->totalDofs());
      for (unsigned i=0; i<numCells; i++) {
        for (int j=0; j<testOrdering->totalDofs(); j++) {
          weights(i,j) = optimalTestWeights(i,optTestIndex,j);
        }
      }
      for (testIterator = testIDs.begin(); testIterator != testIDs.end(); testIterator++) {
        int testID = *testIterator;
        
        vector<EOperatorExtended> trialOperators, testOperators;
        bilinearForm->trialTestOperators(trialID, testID, trialOperators, testOperators);
        vector<EOperatorExtended>::iterator trialOpIt, testOpIt;
        testOpIt = testOperators.begin();
        
        int operatorIndex = -1;
        for (trialOpIt = trialOperators.begin(); trialOpIt != trialOperators.end(); trialOpIt++) {
          IntrepidExtendedTypes::EOperatorExtended trialOperator = *trialOpIt;
          IntrepidExtendedTypes::EOperatorExtended testOperator = *testOpIt;
          operatorIndex++;
          
          if (testOperator==OP_TIMES_NORMAL) {
            TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument,"OP_TIMES_NORMAL not supported for tests.  Use for trial only");
          }
          
          Teuchos::RCP < const FieldContainer<double> > testValuesTransformed;
          Teuchos::RCP < const FieldContainer<double> > trialValuesTransformed;
          Teuchos::RCP < const FieldContainer<double> > testValuesTransformedWeighted;

          if (! bilinearForm->isFluxOrTrace(trialID)) {
            trialBasis = trialOrdering->getBasis(trialID);
            testBasis = testOrdering->getBasis(testID);
            FieldContainer<double> miniStiffness( numCells, testBasis->getCardinality(), trialBasis->getCardinality() );
            
            trialValuesTransformed = basisCache.getTransformedValues(trialBasis,trialOperator);
            testValuesTransformedWeighted = basisCache.getTransformedWeightedValues(testBasis,testOperator);
            
            FieldContainer<double> physicalCubaturePoints = basisCache.getPhysicalCubaturePoints();
            FieldContainer<double> materialDataAppliedToTrialValues = *trialValuesTransformed; // copy first
            FieldContainer<double> materialDataAppliedToTestValues = *testValuesTransformedWeighted; // copy first
            bilinearForm->applyBilinearFormData(materialDataAppliedToTrialValues,materialDataAppliedToTestValues, 
                                               trialID,testID,operatorIndex,physicalCubaturePoints);
              
            int testDofOffset = testOrdering->getDofIndex(testID,0);
            // note that weightCellBasisValues does depend on contiguous test basis dofs...
            // (this is the plan, since there shouldn't be any kind of identification between different test dofs,
            //  especially since test functions live only inside the cell)
            weightCellBasisValues(materialDataAppliedToTestValues, weights, testDofOffset);
              
            FunctionSpaceTools::integrate<double>(miniStiffness,materialDataAppliedToTestValues,materialDataAppliedToTrialValues,COMP_BLAS);
            // place in the appropriate spot in the element-stiffness matrix
            // copy goes from (cell,trial_basis_dof,test_basis_dof) to (cell,element_trial_dof,element_test_dof)
            
            // there may be a more efficient way to do this copying:
            // (one strategy would be to reimplement fst::integrate to support offsets, so that no copying needs to be done...)
            for (int i=0; i < testBasis->getCardinality(); i++) {
              for (int j=0; j < trialBasis->getCardinality(); j++) {
                int trialDofIndex = trialOrdering->getDofIndex(trialID,j);
                for (unsigned k=0; k < numCells; k++) {
                  stiffness(k,optTestIndex,trialDofIndex) += miniStiffness(k,i,j);
                }
              }
            }          
          } else {  // boundary integral
            int trialBasisRank = trialOrdering->getBasisRank(trialID);
            int testBasisRank = testOrdering->getBasisRank(testID);
            
            TEUCHOS_TEST_FOR_EXCEPTION( ( trialBasisRank != 0 ),
                               std::invalid_argument,
                               "Boundary trial variable (flux or trace) given with non-scalar basis.  Unsupported.");
            
            bool isFlux = false; // i.e. the normal is "folded into" the variable definition, so that we must take parity into account
            const set<int> normalOperators = BilinearForm::normalOperators();
            if (   (normalOperators.find(testOperator)  == normalOperators.end() ) 
                && (normalOperators.find(trialOperator) == normalOperators.end() ) ) {
              // normal not yet taken into account -- so it must be "hidden" in the trial variable
              isFlux = true;
            }
            
            for (unsigned sideOrdinal=0; sideOrdinal<numSides; sideOrdinal++) {
              trialBasis = trialOrdering->getBasis(trialID,sideOrdinal);
              testBasis = testOrdering->getBasis(testID);
              
              FieldContainer<double> miniStiffness( numCells, testBasis->getCardinality(), trialBasis->getCardinality() );
              
              // for trial: we never dot with normal, and the value lives on the side, so we don't use the volume coords either:
              trialValuesTransformed = basisCache.getTransformedValues(trialBasis,trialOperator,sideOrdinal,false);
              // for test: first, don't dot with normal, but do use the volume coords:
              //testValuesTransformed = basisCache.getTransformedValues(testBasis,testOperator,sideOrdinal,true);
              testValuesTransformedWeighted = basisCache.getTransformedWeightedValues(testBasis,testOperator,sideOrdinal,true);
              
              // copy before manipulating trialValues--these are the ones stored in the cache, so we're not allowed to change them!!
              FieldContainer<double> materialDataAppliedToTrialValues = *trialValuesTransformed;
              if (isFlux) {
                // this being a flux ==> take cell parity into account (because then there must be a normal folded into the flux definition)
                // we need to multiply the trialValues by the parity of the normal, since
                // the trial implicitly contains an outward normal, and we need to adjust for the fact
                // that the neighboring cells have opposite normal
                // trialValues should have dimensions (numCells,numFields,numCubPointsSide)
                int numFields = trialValuesTransformed->dimension(1);
                int numPoints = trialValuesTransformed->dimension(2);
                for (unsigned cellIndex=0; cellIndex<numCells; cellIndex++) {
                  double parity = cellSideParities(cellIndex,sideOrdinal);
                  if (parity != 1.0) {  // otherwise, we can just leave things be...
                    for (int fieldIndex=0; fieldIndex<numFields; fieldIndex++) {
                      for (int ptIndex=0; ptIndex<numPoints; ptIndex++) {
                        materialDataAppliedToTrialValues(cellIndex,fieldIndex,ptIndex) *= parity;
                      }
                    }
                  }
                }
              }
              
              FieldContainer<double> cubPointsSidePhysical = basisCache.getPhysicalCubaturePointsForSide(sideOrdinal);
              FieldContainer<double> materialDataAppliedToTestValues = *testValuesTransformedWeighted; // copy first
              bilinearForm->applyBilinearFormData(materialDataAppliedToTrialValues,materialDataAppliedToTestValues,
                                                 trialID,testID,operatorIndex,cubPointsSidePhysical);              
              
              int testDofOffset = testOrdering->getDofIndex(testID,0,0);
              weightCellBasisValues(materialDataAppliedToTestValues, weights, testDofOffset);
              
              //   d. Sum up (integrate) and place in stiffness matrix according to DofOrdering indices
              FunctionSpaceTools::integrate<double>(miniStiffness,materialDataAppliedToTestValues,materialDataAppliedToTrialValues,COMP_BLAS);
              // place in the appropriate spot in the element-stiffness matrix
              // copy goes from (cell,trial_basis_dof,test_basis_dof) to (cell,element_trial_dof,element_test_dof)
                            
              for (int i=0; i < testBasis->getCardinality(); i++) {
                for (int j=0; j < trialBasis->getCardinality(); j++) {
                  int trialDofIndex = trialOrdering->getDofIndex(trialID,j,sideOrdinal);
                  for (unsigned k=0; k < numCells; k++) {
                    stiffness(k,optTestIndex,trialDofIndex) += miniStiffness(k,i,j);
                  }
                }
              }
            }
          }
          testOpIt++;
        }
      }
    }
  }
}
  void
  CellTools<SpT>::
  getSubcellParametrization(       subcellParamViewType &subcellParam,  
                             const ordinal_type         subcellDim,
                             const shards::CellTopology parentCell ) {
#ifdef HAVE_INTREPID2_DEBUG
    INTREPID2_TEST_FOR_EXCEPTION( !hasReferenceCell(parentCell), std::invalid_argument, 
                                  ">>> ERROR (Intrepid2::CellTools::getSubcellParametrization): the specified cell topology does not have a reference cell.");
#endif

    if (!isSubcellParametrizationSet_)
      setSubcellParametrization();
    
    // Select subcell parametrization according to its parent cell type
    const auto pcd = parentCell.getDimension(); // parent cell dim
    INTREPID2_TEST_FOR_EXCEPTION( subcellDim < 1 || subcellDim > static_cast<ordinal_type>(pcd-1), std::invalid_argument, 
                                  ">>> ERROR (Intrepid2::CellTools::getSubcellParametrization): Parametrizations defined in a range between 1 and (dim-1)");
    
    switch (parentCell.getKey() ) {
    case shards::Tetrahedron<4>::key:
    case shards::Tetrahedron<8>::key:
    case shards::Tetrahedron<10>::key:
    case shards::Tetrahedron<11>::key:       subcellParam = ( subcellDim == 2 ? subcellParamData_.tetFaces : subcellParamData_.tetEdges ); break;
      
    case shards::Hexahedron<8>::key:
    case shards::Hexahedron<20>::key:
    case shards::Hexahedron<27>::key:        subcellParam = ( subcellDim == 2 ? subcellParamData_.hexFaces : subcellParamData_.hexEdges ); break;
      
    case shards::Pyramid<5>::key:
    case shards::Pyramid<13>::key:
    case shards::Pyramid<14>::key:           subcellParam = ( subcellDim == 2 ? subcellParamData_.pyrFaces : subcellParamData_.pyrEdges ); break;
      
    case shards::Wedge<6>::key:
    case shards::Wedge<15>::key:
    case shards::Wedge<18>::key:             subcellParam = ( subcellDim == 2 ? subcellParamData_.wedgeFaces : subcellParamData_.wedgeEdges ); break;

    case shards::Triangle<3>::key:
    case shards::Triangle<4>::key:
    case shards::Triangle<6>::key:           subcellParam = subcellParamData_.triEdges; break;
                  
    case shards::Quadrilateral<4>::key:
    case shards::Quadrilateral<8>::key:
    case shards::Quadrilateral<9>::key:      subcellParam = subcellParamData_.quadEdges; break;

    // case shards::ShellTriangle<3>::key:
    // case shards::ShellTriangle<6>::key:      subcellParam = ( subcellDim == 2 ? subcellParamData_.shellTriFaces : subcellParamData_.shellTriEdges ); break;

    // case shards::ShellQuadrilateral<4>::key:
    // case shards::ShellQuadrilateral<8>::key:
    // case shards::ShellQuadrilateral<9>::key: subcellParam = ( subcellDim == 2 ? subcellParamData_.shellQuadFaces : subcellParamData_.shellQuadEdges ); break;

    case shards::ShellLine<2>::key:
    case shards::ShellLine<3>::key:
    case shards::Beam<2>::key:
    case shards::Beam<3>::key:               subcellParam = subcellParamData_.lineEdges; break;
    default: {
      INTREPID2_TEST_FOR_EXCEPTION( true, std::invalid_argument, 
                                    ">>> ERROR (Intrepid2::CellTools::getSubcellParametrization): invalid cell topology.");
    }
    }
  }
Ejemplo n.º 27
0
int NodalFieldPattern::getDimension() const
{
   const shards::CellTopology ct = getCellTopology();
   return ct.getDimension();
}
  void
  CellTools<SpT>::
  setSubcellParametrization( subcellParamViewType      &subcellParam,
                             const ordinal_type         subcellDim,
                             const shards::CellTopology parentCell ) {
#ifdef HAVE_INTREPID2_DEBUG
    INTREPID2_TEST_FOR_EXCEPTION( !hasReferenceCell(parentCell), std::invalid_argument, 
                                  ">>> ERROR (Intrepid2::CellTools::setSubcellParametrization): the specified cell topology does not have a reference cell.");
#endif
    // subcellParametrization is rank-3 FieldContainer with dimensions (SC, PCD, COEF) where:
    //  - SC    is the subcell count of subcells with the specified dimension in the parent cell
    //  - PCD   is Parent Cell Dimension, which gives the number of coordinate functions in the map
    //          PCD = 2 for standard 2D cells and non-standard 2D cells: shell line and beam
    //          PCD = 3 for standard 3D cells and non-standard 3D cells: shell Tri and Quad
    //  - COEF  is number of coefficients needed to specify a coordinate function:
    //          COEFF = 2 for edge parametrizations
    //          COEFF = 3 for both Quad and Tri face parametrizations. Because all Quad reference faces
    //          are affine, the coefficient of the bilinear term u*v is zero and is not stored, i.e.,
    //          3 coefficients are sufficient to store Quad face parameterization maps.
    //  
    // Edge parametrization maps [-1,1] to edge defined by (v0, v1)
    // Face parametrization maps [-1,1]^2 to quadrilateral face (v0, v1, v2, v3), or
    // standard 2-simplex  {(0,0),(1,0),(0,1)} to traingle face (v0, v1, v2).
    // This defines orientation-preserving parametrizations with respect to reference edge and
    // face orientations induced by their vertex order. 

    // get subcellParametrization dimensions: (sc, pcd, coeff)
    const auto sc    = parentCell.getSubcellCount(subcellDim);
    const auto pcd   = parentCell.getDimension();   
    const auto coeff = (subcellDim == 1) ? 2 : 3;

    INTREPID2_TEST_FOR_EXCEPTION( subcellDim < 1 || subcellDim > static_cast<ordinal_type>(pcd-1), std::invalid_argument, 
                                  ">>> ERROR (Intrepid2::CellTools::setSubcellParametrization): Parametrizations defined in a range between 1 and (dim-1)");


    // create a view
    subcellParam = subcellParamViewType("CellTools::setSubcellParametrization",
                                        sc, pcd, coeff);

    referenceNodeDataViewType 
      v0("CellTools::setSubcellParametrization::v0", Parameters::MaxDimension), 
      v1("CellTools::setSubcellParametrization::v1", Parameters::MaxDimension),
      v2("CellTools::setSubcellParametrization::v1", Parameters::MaxDimension),
      v3("CellTools::setSubcellParametrization::v1", Parameters::MaxDimension);

    if (subcellDim == 1) {
      // Edge parametrizations of 2D and 3D cells (shell lines and beams are 2D cells with edges)
      for (size_type subcellOrd=0;subcellOrd<sc;++subcellOrd) {
        // vertexK[0] = x_k; vertexK[1] = y_k; vertexK[2] = z_k; z_k = 0 for 2D cells
        // Note that ShellLine and Beam are 2D cells!
        const auto v0ord = parentCell.getNodeMap(subcellDim, subcellOrd, 0);
        const auto v1ord = parentCell.getNodeMap(subcellDim, subcellOrd, 1);

        getReferenceVertex(v0, parentCell, v0ord);
        getReferenceVertex(v1, parentCell, v1ord);
        
        // x(t) = (x0 + x1)/2 + t*(x1 - x0)/2 
        subcellParam(subcellOrd, 0, 0) = (v0[0] + v1[0])/2.0;
        subcellParam(subcellOrd, 0, 1) = (v1[0] - v0[0])/2.0;
        
        // y(t) = (y0 + y1)/2 + t*(y1 - y0)/2 
        subcellParam(subcellOrd, 1, 0) = (v0[1] + v1[1])/2.0;
        subcellParam(subcellOrd, 1, 1) = (v1[1] - v0[1])/2.0;
        
        if( pcd == 3 ) {
          // z(t) = (z0 + z1)/2 + t*(z1 - z0)/2 
          subcellParam(subcellOrd, 2, 0) = (v0[2] + v1[2])/2.0;
          subcellParam(subcellOrd, 2, 1) = (v1[2] - v0[2])/2.0;
        }
      }
    }
    else if (subcellDim == 2) {
      // Face parametrizations of 3D cells: (shell Tri and Quad are 3D cells with faces)
      // A 3D cell can have both Tri and Quad faces, but because they are affine images of the
      // parametrization domain, 3 coefficients are enough to store them in both cases.
      for (size_type subcellOrd=0;subcellOrd<sc;++subcellOrd) {
        
        switch (parentCell.getKey(subcellDim,subcellOrd)) {
          
        case shards::Triangle<3>::key:
        case shards::Triangle<4>::key:
        case shards::Triangle<6>::key: {
          const auto v0ord = parentCell.getNodeMap(subcellDim, subcellOrd, 0);
          const auto v1ord = parentCell.getNodeMap(subcellDim, subcellOrd, 1);
          const auto v2ord = parentCell.getNodeMap(subcellDim, subcellOrd, 2);

          getReferenceVertex(v0, parentCell, v0ord);
          getReferenceVertex(v1, parentCell, v1ord);
          getReferenceVertex(v2, parentCell, v2ord);
          
          // x(u,v) = x0 + (x1 - x0)*u + (x2 - x0)*v
          subcellParam(subcellOrd, 0, 0) = v0[0];
          subcellParam(subcellOrd, 0, 1) = v1[0] - v0[0];
          subcellParam(subcellOrd, 0, 2) = v2[0] - v0[0];
          
          // y(u,v) = y0 + (y1 - y0)*u + (y2 - y0)*v
          subcellParam(subcellOrd, 1, 0) = v0[1];
          subcellParam(subcellOrd, 1, 1) = v1[1] - v0[1];
          subcellParam(subcellOrd, 1, 2) = v2[1] - v0[1];
          
          // z(u,v) = z0 + (z1 - z0)*u + (z2 - z0)*v
          subcellParam(subcellOrd, 2, 0) = v0[2];
          subcellParam(subcellOrd, 2, 1) = v1[2] - v0[2];
          subcellParam(subcellOrd, 2, 2) = v2[2] - v0[2];
          break;
        }
        case shards::Quadrilateral<4>::key:
        case shards::Quadrilateral<8>::key:
        case shards::Quadrilateral<9>::key: {
          const auto v0ord = parentCell.getNodeMap(subcellDim, subcellOrd, 0);
          const auto v1ord = parentCell.getNodeMap(subcellDim, subcellOrd, 1);
          const auto v2ord = parentCell.getNodeMap(subcellDim, subcellOrd, 2);
          const auto v3ord = parentCell.getNodeMap(subcellDim, subcellOrd, 3);

          getReferenceVertex(v0, parentCell, v0ord);
          getReferenceVertex(v1, parentCell, v1ord);
          getReferenceVertex(v2, parentCell, v2ord);
          getReferenceVertex(v3, parentCell, v3ord);
                
          // x(u,v) = (x0+x1+x2+x3)/4+u*(-x0+x1+x2-x3)/4+v*(-x0-x1+x2+x3)/4+uv*(0=x0-x1+x2-x3)/4 
          subcellParam(subcellOrd, 0, 0) = ( v0[0] + v1[0] + v2[0] + v3[0])/4.0;
          subcellParam(subcellOrd, 0, 1) = (-v0[0] + v1[0] + v2[0] - v3[0])/4.0;
          subcellParam(subcellOrd, 0, 2) = (-v0[0] - v1[0] + v2[0] + v3[0])/4.0;
          
          // y(u,v) = (y0+y1+y2+y3)/4+u*(-y0+y1+y2-y3)/4+v*(-y0-y1+y2+y3)/4+uv*(0=y0-y1+y2-y3)/4 
          subcellParam(subcellOrd, 1, 0) = ( v0[1] + v1[1] + v2[1] + v3[1])/4.0;
          subcellParam(subcellOrd, 1, 1) = (-v0[1] + v1[1] + v2[1] - v3[1])/4.0;
          subcellParam(subcellOrd, 1, 2) = (-v0[1] - v1[1] + v2[1] + v3[1])/4.0;
          
          // z(u,v) = (z0+z1+z2+z3)/4+u*(-z0+z1+z2-z3)/4+v*(-z0-z1+z2+z3)/4+uv*(0=z0-z1+z2-z3)/4 
          subcellParam(subcellOrd, 2, 0) = ( v0[2] + v1[2] + v2[2] + v3[2])/4.0;
          subcellParam(subcellOrd, 2, 1) = (-v0[2] + v1[2] + v2[2] - v3[2])/4.0;
          subcellParam(subcellOrd, 2, 2) = (-v0[2] - v1[2] + v2[2] + v3[2])/4.0;
          break;
        }
        default: {
          INTREPID2_TEST_FOR_EXCEPTION( true, std::invalid_argument, 
                                        ">>> ERROR (Intrepid2::CellTools::setSubcellParametrization): parametrization not defined for the specified face topology.");
        }
        }
      }
    }
  }
Ejemplo n.º 29
0
      void getLocalToGlobalMap(int (*local2global)[2],
                               int &off_global,
                               const Basis<Scalar,ArrayType> &basis,
                               const int *element) {
        const int local = 0, global = 1;
        const int nbf = basis.getCardinality();
        const shards::CellTopology cell = basis.getBaseCellTopology();
        const int dim = cell.getDimension();

        int cnt = 0, off_element = 0;
        int subcell_verts[4], nids;

        const int nvert = cell.getVertexCount();
        for (int i=0;i<nvert;++i) {
          const int ord_vert = (off_element < nbf ? basis.getDofOrdinal(0, i, 0) : 0);
          const int dof_vert = (off_element < nbf ? basis.getDofTag(ord_vert)[3] : 0);
      
          local2global[cnt][local] = off_element;
          off_element += dof_vert;
          Orientation::getElementNodeMap(subcell_verts, nids,
                                         cell, element,
                                         0, i);
      
          if (!findNode(local2global[cnt][global], subcell_verts, nids, true)) {
            addNode(subcell_verts, nids, off_global);
            local2global[cnt][global] = off_global;
            off_global += dof_vert;
          }
          ++cnt;
        }
        const int nedge = cell.getEdgeCount();
        for (int i=0;i<nedge;++i) {
          const int ord_edge = (off_element < nbf ? basis.getDofOrdinal(1, i, 0) : 0);
          const int dof_edge = (off_element < nbf ? basis.getDofTag(ord_edge)[3] : 0);
      
          local2global[cnt][local] = off_element;
          off_element += dof_edge;
          Orientation::getElementNodeMap(subcell_verts, nids,
                                         cell, element,
                                         1, i);
      
          if (!findNode(local2global[cnt][global], subcell_verts, nids, true)) {
            addNode(subcell_verts, nids, off_global);
            local2global[cnt][global] = off_global;
            off_global += dof_edge;
          }
          ++cnt;
        }
        const int nface = cell.getFaceCount();
        for (int i=0;i<nface;++i) {
          const int ord_face = (off_element < nbf ? basis.getDofOrdinal(2, i, 0) : 0);
          const int dof_face = (off_element < nbf ? basis.getDofTag(ord_face)[3] : 0);
      
          local2global[cnt][local] = off_element;
          off_element += dof_face;
          Orientation::getElementNodeMap(subcell_verts, nids,
                                         cell, element,
                                         2, i);
      
          if (!findNode(local2global[cnt][global], subcell_verts, nids, true)) {
            addNode(subcell_verts, nids, off_global);
            local2global[cnt][global] = off_global;
            off_global += dof_face;
          }
          ++cnt;
        }
        {
          const int i = 0;
          const int ord_intr = (off_element < nbf ? basis.getDofOrdinal(dim, i, 0) : 0);
          const int dof_intr = (off_element < nbf ? basis.getDofTag(ord_intr)[3]   : 0);
      
          local2global[cnt][local] = off_element;
          off_element += dof_intr;
          Orientation::getElementNodeMap(subcell_verts, nids,
                                         cell, element,
                                         dim, i);
      
          if (!findNode(local2global[cnt][global], subcell_verts, nids, true)) {
            addNode(subcell_verts, nids, off_global);
            local2global[cnt][global] = off_global;
            off_global += dof_intr;
          }
          ++cnt;
        }
    
        // add the last offset
        local2global[cnt][local] = off_element;
        local2global[cnt][global] = -1; // invalid values
      }
Ejemplo n.º 30
0
int NodalFieldPattern::getSubcellCount(int dim) const
{
   const shards::CellTopology ct = getCellTopology();
   return ct.getSubcellCount(dim);
}