Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_ResponseScatterEvaluator_Probe_impl.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Panzer: A partial differential equation assembly
4 // engine for strongly coupled complex multiphysics systems
5 //
6 // Copyright 2011 NTESS and the Panzer contributors.
7 // SPDX-License-Identifier: BSD-3-Clause
8 // *****************************************************************************
9 // @HEADER
10 
11 #ifndef PANZER_RESPONSE_SCATTER_EVALUATOR_EXTREMEVALUE_IMPL_HPP
12 #define PANZER_RESPONSE_SCATTER_EVALUATOR_EXTREMEVALUE_IMPL_HPP
13 
14 #include <iostream>
15 #include <string>
16 
17 #include "PanzerDiscFE_config.hpp"
18 
19 #include "Phalanx_Evaluator_Macros.hpp"
20 #include "Phalanx_MDField.hpp"
21 #include "Phalanx_DataLayout_MDALayout.hpp"
22 
23 #include "Panzer_CellData.hpp"
24 #include "Panzer_PointRule.hpp"
26 #include "Panzer_ResponseBase.hpp"
27 #include "Panzer_Dimension.hpp"
29 
30 #include "Intrepid2_FunctionSpaceTools.hpp"
31 
32 #include "Thyra_SpmdVectorBase.hpp"
33 #include "Teuchos_ArrayRCP.hpp"
34 
35 #include "Kokkos_ViewFactory.hpp"
36 
37 namespace panzer {
38 
39 template<typename EvalT, typename Traits, typename LO, typename GO>
42  const std::string & responseName,
43  const std::string & fieldName,
44  const int fieldComponent,
45  const Teuchos::Array<double>& point,
46  const IntegrationRule & ir,
47  const Teuchos::RCP<const PureBasis>& basis,
49  const Teuchos::RCP<ProbeScatterBase> & probeScatter)
50  : responseName_(responseName)
51  , fieldName_(fieldName)
52  , fieldComponent_(fieldComponent)
53  , point_(point)
54  , basis_(basis)
55  , topology_(ir.topology)
56  , globalIndexer_(indexer)
57  , scatterObj_(probeScatter)
58  , haveProbe_(false)
59  , cellIndex_(-1)
60  , workset_id_(0)
61 {
62  using Teuchos::RCP;
63  using Teuchos::rcp;
64 
65  // the field manager will allocate all of these fields
67  this->addDependentField(field_);
68 
69  num_basis = basis->cardinality();
70  num_dim = basis->dimension();
71  TEUCHOS_ASSERT(num_dim == static_cast<size_t>(point_.size()));
72 
73  basis_values_ = Kokkos::DynRankView<double,PHX::Device>(
74  "basis_values", 1, num_basis, 1); // Cell, Basis, Point
75 
76  // build dummy target tag
77  std::string dummyName =
78  ResponseBase::buildLookupName(responseName) + " dummy target";
80  scatterHolder_ = rcp(new PHX::Tag<ScalarT>(dummyName,dl_dummy));
81  this->addEvaluatedField(*scatterHolder_);
82 
83  std::string n = "Probe Response Scatter: " + responseName;
84  this->setName(n);
85 }
86 
87 template<typename EvalT, typename Traits, typename LO, typename GO>
91 {
92  for (const auto& workset : *sd.worksets_) {
93  this->findCellAndComputeBasisValues(workset);
94  if (haveProbe_)
95  break;
96  }
97 }
98 
99 template<typename EvalT, typename Traits, typename LO, typename GO>
102 {
103  // extract linear object container
104  responseObj_ =
105  Teuchos::rcp_dynamic_cast<Response_Probe<EvalT> >(
106  d.gedc->getDataObject(ResponseBase::buildLookupName(responseName_)),
107  true);
108 }
109 
110 template<typename EvalT, typename Traits, typename LO, typename GO>
113 {
114  // This evaluator needs to run on host until checkPointwiseInclusion
115  // is moved to device.
116  using HostSpace = Kokkos::DefaultHostExecutionSpace;
117  using CTD = Intrepid2::CellTools<HostSpace>;
118  using FST = Intrepid2::FunctionSpaceTools<HostSpace>;
119 
120  // Find which cell contains our point
121  const int num_points = 1;
122  Kokkos::DynRankView<int,HostSpace> inCell("inCell", this->wda(d).cell_node_coordinates.extent_int(0), num_points);
123  Kokkos::DynRankView<double,HostSpace> physical_points_cell("physical_points_cell", this->wda(d).cell_node_coordinates.extent_int(0), num_points, num_dim);
124  auto tmp_point = point_;
125  {
126  Kokkos::MDRangePolicy<HostSpace,Kokkos::Rank<2>> policy({0,0},{d.num_cells,static_cast<decltype(d.num_cells)>(num_dim)});
127  Kokkos::parallel_for("copy node coords",policy,[&](const int cell, const int dim){
128  physical_points_cell(cell,0,dim) = tmp_point[dim];
129  });
130  HostSpace().fence();
131 
132  auto cell_coords = this->wda(d).cell_node_coordinates.get_view();
133  auto cell_coords_host = Kokkos::create_mirror_view(cell_coords);
134  Kokkos::deep_copy(cell_coords_host, cell_coords);
135 
136  const double tol = 1.0e-12;
137  CTD::checkPointwiseInclusion(inCell,
138  physical_points_cell,
139  cell_coords_host,
140  *topology_,
141  tol);
142  }
143 
144  for (index_t cell=0; cell<static_cast<int>(d.num_cells); ++cell) {
145  if (inCell(cell,0) == 1) {
146  cellIndex_ = cell;
147  workset_id_ = d.getIdentifier();
148  haveProbe_ = true;
149  break;
150  }
151  }
152 
153  // If no cell does, we're done
154  if (!haveProbe_) {
155  return false;
156  }
157 
158  // Map point to reference frame
159  const size_t num_nodes = this->wda(d).cell_node_coordinates.extent(1);
160  Kokkos::DynRankView<double,HostSpace> cell_coords("cell_coords", 1, int(num_nodes), int(num_dim)); // <C,B,D>
161  auto cnc_host = Kokkos::create_mirror_view(this->wda(d).cell_node_coordinates.get_view());
162  Kokkos::deep_copy(cnc_host,this->wda(d).cell_node_coordinates.get_view());
163  for (size_t i=0; i<num_nodes; ++i) {
164  for (size_t j=0; j<num_dim; ++j) {
165  cell_coords(0,i,j) = cnc_host(cellIndex_,i,j);
166  }
167  }
168  Kokkos::DynRankView<double,HostSpace> physical_points("physical_points", 1, 1, num_dim); // <C,P,D>
169  for (size_t i=0; i<num_dim; ++i)
170  physical_points(0,0,i) = physical_points_cell(0,0,i);
171 
172  Kokkos::DynRankView<double,HostSpace> reference_points("reference_points", 1, 1, num_dim); // <C,P,D>
173  CTD::mapToReferenceFrame(reference_points, physical_points, cell_coords, *topology_);
174 
175  Kokkos::DynRankView<double,HostSpace> reference_points_cell("reference_points_cell", 1, num_dim); // <P,D>
176  for (size_t i=0; i<num_dim; ++i)
177  reference_points_cell(0,i) = reference_points(0,0,i);
178 
179  // Compute basis functions at point
180  if (basis_->getElementSpace() == PureBasis::CONST ||
181  basis_->getElementSpace() == PureBasis::HGRAD) {
182 
183  // Evaluate basis at reference values
184  Kokkos::DynRankView<double,HostSpace> ref_basis_values("ref_basis_values", num_basis, 1); // <B,P>
185  basis_->getIntrepid2Basis<HostSpace,double,double>()->getValues(ref_basis_values,
186  reference_points_cell,
187  Intrepid2::OPERATOR_VALUE);
188 
189  // Apply transformation to physical frame
190  auto basis_values_host = Kokkos::create_mirror_view(basis_values_);
191  FST::HGRADtransformVALUE<double>(basis_values_host, ref_basis_values);
192  Kokkos::deep_copy(basis_values_,basis_values_host);
193  }
194  else if (basis_->getElementSpace() == PureBasis::HCURL ||
195  basis_->getElementSpace() == PureBasis::HDIV) {
196 
197  // Evaluate basis at reference values
198  Kokkos::DynRankView<double,HostSpace> ref_basis_values("ref_basis_values", num_basis, 1, num_dim); // <B,P,D>
199  basis_->getIntrepid2Basis<HostSpace,double,double>()->getValues(ref_basis_values,
200  reference_points_cell,
201  Intrepid2::OPERATOR_VALUE);
202 
203  // Apply transformation to physical frame
204  Kokkos::DynRankView<double,HostSpace> jac("jac", 1, 1, num_dim, num_dim); // <C,P,D,D>
205  CTD::setJacobian(jac, reference_points, cell_coords, *topology_);
206  Kokkos::DynRankView<double,HostSpace> basis_values_vec("basis_values_vec", 1, num_basis, 1, num_dim); // <C,B,P,D>
207  if (basis_->getElementSpace() == PureBasis::HCURL) {
208  Kokkos::DynRankView<double,HostSpace> jac_inv("jac_inv", 1, 1, num_dim, num_dim); // <C,P,D,D>
209  CTD::setJacobianInv(jac_inv, jac);
210  FST::HCURLtransformVALUE<double>(basis_values_vec, jac_inv,
211  ref_basis_values);
212  }
213  else {
214  Kokkos::DynRankView<double,HostSpace> jac_det("jac_det", 1, 1); // <C,P>
215  CTD::setJacobianDet(jac_det, jac);
216  FST::HDIVtransformVALUE<double>(basis_values_vec, jac, jac_det,
217  ref_basis_values);
218  }
219 
220  // Compute element orientations
221  std::vector<double> orientation;
222  globalIndexer_->getElementOrientation(cellIndex_, orientation);
223  std::string blockId = this->wda(d).block_id;
224  int fieldNum = globalIndexer_->getFieldNum(fieldName_);
225  const std::vector<int> & elmtOffset = globalIndexer_->getGIDFieldOffsets(blockId,fieldNum);
226 
227  // Extract component of basis
228  for (size_t i=0; i<num_basis; ++i) {
229  int offset = elmtOffset[i];
230  basis_values_(0,i,0) = orientation[offset] * basis_values_vec(0,i,0,fieldComponent_);
231  }
232 
233  }
234 
235  return true;
236 }
237 
238 template<typename EvalT, typename Traits, typename LO, typename GO>
241 {
242  using HostSpace = Kokkos::DefaultHostExecutionSpace;
243 
244  if ( !haveProbe_ ||
245  (haveProbe_ && d.getIdentifier() != workset_id_) )
246  return;
247 
248  auto field_coeffs_host = Kokkos::create_mirror_view(field_.get_view());
249  Kokkos::deep_copy(field_coeffs_host,field_.get_view());
250 
251  auto field_coeffs_host_subview = Kokkos::subview(field_coeffs_host,std::pair<int,int>(cellIndex_,cellIndex_+1),Kokkos::ALL);
252 
253  auto field_val = Kokkos::createDynRankViewWithType<Kokkos::DynRankView<ScalarT,HostSpace>>(field_coeffs_host, "field_val_at_point", 1, 1); // <C,P>
254 
255  auto basis_values_host = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),basis_values_);
256 
257  Intrepid2::FunctionSpaceTools<HostSpace>::evaluate(field_val, field_coeffs_host_subview, basis_values_host);
258  responseObj_->value = field_val(0,0);
259  responseObj_->have_probe = true;
260 }
261 
262 template <typename LO, typename GO>
265 {
266  using Teuchos::RCP;
267  using Teuchos::rcp_dynamic_cast;
268  using Thyra::SpmdVectorBase;
269 
270  TEUCHOS_ASSERT(this->scatterObj_!=Teuchos::null);
271 
273 
274  // grab local data for inputing
275  Teuchos::ArrayRCP<double> local_dgdx;
277  rcp_dynamic_cast<SpmdVectorBase<double> >(this->responseObj_->getGhostedVector());
278  dgdx->getNonconstLocalData(ptrFromRef(local_dgdx));
279  TEUCHOS_ASSERT(!local_dgdx.is_null());
280 
281  this->scatterObj_->scatterDerivative(this->responseObj_->value,
282  this->cellIndex_,
283  this->responseObj_->have_probe,
284  d,this->wda,
285  local_dgdx);
286 }
287 
288 }
289 
290 #endif
Teuchos::RCP< GlobalEvaluationDataContainer > gedc
int num_cells
DEPRECATED - use: numCells()
std::size_t getIdentifier() const
Get the unique identifier for this workset, this is not an index!
static std::string buildLookupName(const std::string &responseName)
void postRegistrationSetup(typename Traits::SetupData, PHX::FieldManager< Traits > &)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Kokkos::DynRankView< double, PHX::Device > basis_values_
size_type size() const
ResponseScatterEvaluator_ProbeBase(const std::string &responseName, const std::string &fieldName, const int fieldComponent, const Teuchos::Array< double > &point, const IntegrationRule &ir, const Teuchos::RCP< const PureBasis > &basis, const Teuchos::RCP< const panzer::GlobalIndexer > &indexer, const Teuchos::RCP< ProbeScatterBase > &probeScatter)
A constructor with concrete arguments instead of a parameter list.
#define TEUCHOS_ASSERT(assertion_test)
Teuchos::RCP< PHX::DataLayout > functional
&lt;Cell,Basis&gt; or &lt;Cell,Basis&gt;
bool is_null() const
Teuchos::RCP< const std::vector< panzer::Workset > > worksets_