43 #ifndef PANZER_PROJECT_TO_FACES_IMPL_HPP
44 #define PANZER_PROJECT_TO_FACES_IMPL_HPP
46 #include "Teuchos_Assert.hpp"
47 #include "Phalanx_DataLayout.hpp"
49 #include "Intrepid2_Cubature.hpp"
50 #include "Intrepid2_DefaultCubatureFactory.hpp"
51 #include "Intrepid2_FunctionSpaceTools.hpp"
52 #include "Intrepid2_Kernels.hpp"
53 #include "Intrepid2_CellTools.hpp"
54 #include "Intrepid2_OrientationTools.hpp"
59 #include "Kokkos_ViewFactory.hpp"
61 #include "Teuchos_FancyOStream.hpp"
65 template<
typename EvalT,
typename Traits>
69 use_fast_method_on_rectangular_hex_mesh(false)
78 if(p.
isType<
int>(
"Quadrature Order"))
81 if(p.
isType<
bool>(
"Use Fast Method for Rectangular Hex Mesh"))
91 this->addEvaluatedField(result);
93 normals = PHX::MDField<const ScalarT,Cell,BASIS,Dim>(dof_name+
"_Normals",vector_layout);
94 this->addDependentField(
normals);
97 const shards::CellTopology & parentCell = *
basis->getCellTopology();
98 Intrepid2::DefaultCubatureFactory quadFactory;
100 = quadFactory.create<PHX::exec_space,double,
double>(parentCell.getCellTopologyData(2,0),
quad_degree);
101 int numQPoints = quadRule->getNumPoints();
104 for (
int qp(0); qp < numQPoints; ++qp)
106 vector_values[qp] = PHX::MDField<const ScalarT,Cell,BASIS,Dim>(dof_name+
"_Vector"+
"_qp_"+std::to_string(qp),vector_layout);
115 TEUCHOS_ASSERT(std::strstr(
basis->getCellTopology()->getBaseName(),
"Hexahedron") !=
nullptr);
118 vector_values[0] = PHX::MDField<const ScalarT,Cell,BASIS,Dim>(dof_name+
"_Vector",vector_layout);
122 if (use_fast_method_on_rectangular_hex_mesh)
123 this->setName(
"Project To Faces (Fast Rectangular Hex)");
125 this->setName(
"Project To Faces");
129 template<
typename EvalT,
typename Traits>
136 num_pts =
result.extent(1);
137 num_dim = vector_values[0].extent(2);
147 if (use_fast_method_on_rectangular_hex_mesh) {
152 const shards::CellTopology & parentCell = *basis->getCellTopology();
153 const int cellDim = parentCell.getDimension();
154 using HostDRVType = Kokkos::DynRankView<ScalarT,ProjectionSpace>;
155 refEdges = Kokkos::createDynRankViewWithType<HostDRVType>(
result.get_static_view(),
"ref_edges", 2, cellDim);
156 phyEdges = Kokkos::createDynRankViewWithType<HostDRVType>(
result.get_static_view(),
"phy_edges", 2, cellDim);
158 PHX::MDField<double,Cell,panzer::NODE,Dim> vertex_coords = (*d.
worksets_)[0].cell_vertex_coordinates;
159 physicalNodes = Kokkos::DynRankView<double,ProjectionSpace>(
"physicalNodes",1,vertex_coords.extent(1),num_dim);
161 const int subcell_dim = 2;
162 Intrepid2::DefaultCubatureFactory quadFactory;
163 int maxNumFaceQP = 0;
164 faceQuads.resize(num_pts);
165 for (
int p = 0; p < num_pts; ++p){
166 const shards::CellTopology & subcell = parentCell.getCellTopologyData(subcell_dim,p);
167 faceQuads[p] = quadFactory.create<ProjectionSpace::execution_space,double,
double>(subcell, quad_degree);
168 TEUCHOS_ASSERT(faceQuads[p]->getNumPoints() == static_cast<int>(vector_values.size()));
169 maxNumFaceQP = std::max(maxNumFaceQP,faceQuads[p]->getNumPoints());
171 quadWts = Kokkos::DynRankView<double,ProjectionSpace>(
"quadWts",maxNumFaceQP);
172 quadPts = Kokkos::DynRankView<double,ProjectionSpace>(
"quadPts",maxNumFaceQP,subcell_dim);
173 refQuadPts = Kokkos::DynRankView<double,ProjectionSpace>(
"refQuadPts",maxNumFaceQP,num_dim);
174 jacobianSide = Kokkos::DynRankView<double,ProjectionSpace>(
"jacobianSide",1,maxNumFaceQP,num_dim,num_dim);
175 weighted_measure = Kokkos::DynRankView<double,ProjectionSpace>(
"weighted_measure",1,maxNumFaceQP);
176 scratch_space = Kokkos::DynRankView<double,ProjectionSpace>(
"scratch_space",jacobianSide.span());
181 template<
typename EvalT,
typename Traits>
192 const shards::CellTopology & parentCell = *basis->getCellTopology();
193 Intrepid2::DefaultCubatureFactory quadFactory;
199 if (use_fast_method_on_rectangular_hex_mesh){
203 const unsigned num_faces = parentCell.getFaceCount();
204 std::vector<double> refFaceWt(num_faces, 0.0);
205 for (
unsigned f=0; f<num_faces; f++) {
206 faceQuad = quadFactory.create<PHX::exec_space,double,
double>(parentCell.getCellTopologyData(2,f), 1);
207 const int numQPoints = faceQuad->getNumPoints();
208 Kokkos::DynRankView<double,PHX::Device> quadWtsFast(
"quadWts",numQPoints);
209 Kokkos::DynRankView<double,PHX::Device> quadPtsFast(
"quadPts",numQPoints,num_dim);
210 faceQuad->getCubature(quadPtsFast,quadWtsFast);
211 for (
int q=0; q<numQPoints; q++)
212 refFaceWt[f] += quadWtsFast(q);
216 for (index_t cell = 0; cell < workset.
num_cells; ++cell) {
217 for (
int p = 0; p < num_pts; ++p) {
219 for (
int dim = 0; dim < num_dim; ++dim)
220 result(cell,p) += vector_values[0](cell,p,dim) * normals(cell,p,dim);
221 result(cell,p) *= refFaceWt[p];
227 const int subcell_dim = 2;
228 const int numFaces = Teuchos::as<int>(parentCell.getFaceCount());
232 for (index_t cell = 0; cell < workset.
num_cells; ++cell) {
235 for (
int point(0); point < vertex_coords.extent_int(1); ++point)
237 for (
int ict(0); ict < num_dim; ict++)
238 physicalNodes(0,point,ict) = vertex_coords(cell,point,ict);
241 int faceOrts[6] = {};
242 orientations->at(details.cell_local_ids[cell]).getFaceOrientation(faceOrts, numFaces);
245 for (
int p = 0; p < num_pts; ++p){
248 auto ortEdgeTan_U = Kokkos::subview(refEdges, 0, Kokkos::ALL());
249 auto ortEdgeTan_V = Kokkos::subview(refEdges, 1, Kokkos::ALL());
252 Intrepid2::Orientation::getReferenceFaceTangents(ortEdgeTan_U,
259 const shards::CellTopology & subcell = parentCell.getCellTopologyData(subcell_dim,p);
260 const auto& faceQuad = faceQuads[p];
261 faceQuad->getCubature(quadPts,quadWts);
264 Intrepid2::CellTools<ProjectionSpace::execution_space>::mapToReferenceSubcell(refQuadPts, quadPts, subcell_dim, p, parentCell);
267 Intrepid2::CellTools<ProjectionSpace::execution_space>::setJacobian(jacobianSide, refQuadPts, physicalNodes, parentCell);
270 Intrepid2::FunctionSpaceTools<ProjectionSpace::execution_space>::computeFaceMeasure(weighted_measure, jacobianSide, quadWts, p, parentCell, scratch_space);
273 for (
int qp = 0; qp < faceQuad->getNumPoints(); ++qp) {
275 auto phyEdgeTan_U = Kokkos::subview(phyEdges, 0, Kokkos::ALL());
276 auto phyEdgeTan_V = Kokkos::subview(phyEdges, 1, Kokkos::ALL());
277 auto J = Kokkos::subview(jacobianSide, 0, qp, Kokkos::ALL(), Kokkos::ALL());
279 Intrepid2::Kernels::Serial::matvec_product(phyEdgeTan_U, J, ortEdgeTan_U);
280 Intrepid2::Kernels::Serial::matvec_product(phyEdgeTan_V, J, ortEdgeTan_V);
284 normal[0] = (phyEdgeTan_U(1)*phyEdgeTan_V(2) - phyEdgeTan_U(2)*phyEdgeTan_V(1));
285 normal[1] = (phyEdgeTan_U(2)*phyEdgeTan_V(0) - phyEdgeTan_U(0)*phyEdgeTan_V(2));
286 normal[2] = (phyEdgeTan_U(0)*phyEdgeTan_V(1) - phyEdgeTan_U(1)*phyEdgeTan_V(0));
290 for(
int dim = 0; dim < num_dim; ++dim){
291 nnorm += normal[dim]*normal[dim];
293 nnorm = std::sqrt(nnorm);
297 for (
int dim = 0; dim < num_dim; ++dim)
298 result(cell,p) += weighted_measure(0,qp) * vector_values[qp](cell,p,dim) * normal[dim] / nnorm;
Teuchos::RCP< const std::vector< Intrepid2::Orientation > > orientations_
PHX::MDField< ScalarT, Cell, NODE, Dim > gatherFieldNormals
bool use_fast_method_on_rectangular_hex_mesh
If true, a fast algorithm can be used, but this requires a rectangular/square structured hex mesh...
PHX::MDField< const ScalarT, Cell, BASIS, Dim > normals
void evaluateFields(typename Traits::EvalData d)
T & get(const std::string &name, T def_value)
void postRegistrationSetup(typename Traits::SetupData d, PHX::FieldManager< Traits > &vm)
CellCoordArray cell_vertex_coordinates
PHX::MDField< ScalarT, Cell, BASIS > result
PHX::MDField< ScalarT, panzer::Cell, panzer::IP > result
A field that will be used to build up the result of the integral we're performing.
Teuchos::RCP< const PureBasis > basis
bool isType(const std::string &name) const
#define TEUCHOS_ASSERT(assertion_test)
std::vector< PHX::MDField< const ScalarT, Cell, BASIS, Dim > > vector_values
Teuchos::RCP< const std::vector< panzer::Workset > > worksets_