Panzer Version of the Day
Loading...
Searching...
No Matches
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"
27#include "Panzer_Dimension.hpp"
29
30#include "Intrepid2_FunctionSpaceTools.hpp"
31
32#include "Thyra_SpmdVectorBase.hpp"
34#include "Thyra_ProductVectorBase.hpp"
35#include "Teuchos_ArrayRCP.hpp"
36
37#include "Sacado_Fad_Kokkos_ViewFactory.hpp"
38
39namespace panzer {
40
41template<typename EvalT, typename Traits, typename LO, typename GO>
44 const std::string & responseName,
45 const std::string & fieldName,
46 const int fieldComponent,
47 const Teuchos::Array<double>& point,
48 const IntegrationRule & ir,
49 const Teuchos::RCP<const PureBasis>& basis,
50 const Teuchos::RCP<const panzer::GlobalIndexer> & indexer,
51 const Teuchos::RCP<ProbeScatterBase> & probeScatter)
52 : responseName_(responseName)
53 , fieldName_(fieldName)
54 , fieldComponent_(fieldComponent)
55 , point_(point)
56 , basis_(basis)
57 , topology_(ir.topology)
58 , globalIndexer_(indexer)
59 , scatterObj_(probeScatter)
60 , haveProbe_(false)
61 , cellIndex_(-1)
62 , workset_id_(0)
63{
64 using Teuchos::RCP;
65 using Teuchos::rcp;
66
67 // the field manager will allocate all of these fields
68 field_ = PHX::MDField<const ScalarT,Cell,BASIS>(fieldName,basis_->functional);
69 this->addDependentField(field_);
70
71 num_basis = basis->cardinality();
72 num_dim = basis->dimension();
73 TEUCHOS_ASSERT(num_dim == static_cast<size_t>(point_.size()));
74
75 basis_values_ = Kokkos::DynRankView<double,PHX::Device>(
76 "basis_values", 1, num_basis, 1); // Cell, Basis, Point
78 // build dummy target tag
79 std::string dummyName =
80 ResponseBase::buildLookupName(responseName) + " dummy target";
81 RCP<PHX::DataLayout> dl_dummy = rcp(new PHX::MDALayout<panzer::Dummy>(0));
82 scatterHolder_ = rcp(new PHX::Tag<ScalarT>(dummyName,dl_dummy));
83 this->addEvaluatedField(*scatterHolder_);
84
85 std::string n = "Probe Response Scatter: " + responseName;
86 this->setName(n);
88
89template<typename EvalT, typename Traits, typename LO, typename GO>
93{
94 for (const auto& workset : *sd.worksets_) {
96 if (haveProbe_)
97 break;
98 }
99}
100
101template<typename EvalT, typename Traits, typename LO, typename GO>
104{
105 auto blockedDOFManager =
106 Teuchos::rcp_dynamic_cast<const panzer::BlockedDOFManager>(globalIndexer_);
107
108 if (Teuchos::is_null(blockedDOFManager))
109 return 0;
110
111 const std::string field = (fieldName_=="" ? responseName_ : fieldName_);
112 const int fieldNum = blockedDOFManager->getFieldNum(field);
113 TEUCHOS_TEST_FOR_EXCEPTION(fieldNum < 0,std::logic_error,
114 "ResponseScatterEvaluator_Probe: field \"" << field << "\" was not found "
115 "in the blocked DOF manager.");
116
117 return blockedDOFManager->getFieldBlock(fieldNum);
118}
119
120template<typename EvalT, typename Traits, typename LO, typename GO>
122getDerivativeOffset(const std::string& blockId) const
123{
124 auto blockedDOFManager =
125 Teuchos::rcp_dynamic_cast<const panzer::BlockedDOFManager>(globalIndexer_);
126
127 if (Teuchos::is_null(blockedDOFManager))
128 return 0;
129
130 return blockedDOFManager->getBlockGIDOffset(blockId,getProductVectorBlockIndex());
131}
132
133template<typename EvalT, typename Traits, typename LO, typename GO>
136{
137 // extract linear object container
138 responseObj_ =
139 Teuchos::rcp_dynamic_cast<Response_Probe<EvalT> >(
140 d.gedc->getDataObject(ResponseBase::buildLookupName(responseName_)),
141 true);
142}
143
144template<typename EvalT, typename Traits, typename LO, typename GO>
147{
148 // This evaluator needs to run on host until checkPointwiseInclusion
149 // is moved to device.
150 using HostSpace = Kokkos::DefaultHostExecutionSpace;
151 using CTD = Intrepid2::CellTools<HostSpace>;
152 using FST = Intrepid2::FunctionSpaceTools<HostSpace>;
153
154 // Find which cell contains our point
155 const int num_points = 1;
156 Kokkos::DynRankView<int,HostSpace> inCell("inCell", this->wda(d).cell_node_coordinates.extent_int(0), num_points);
157 Kokkos::DynRankView<double,HostSpace> physical_points_cell("physical_points_cell", this->wda(d).cell_node_coordinates.extent_int(0), num_points, num_dim);
158 auto tmp_point = point_;
159 {
160 Kokkos::MDRangePolicy<HostSpace,Kokkos::Rank<2>> policy({0,0},{d.num_cells,static_cast<decltype(d.num_cells)>(num_dim)});
161 Kokkos::parallel_for("copy node coords",policy,[&](const int cell, const int dim){
162 physical_points_cell(cell,0,dim) = tmp_point[dim];
163 });
164 HostSpace().fence();
165
166 auto cell_coords = this->wda(d).cell_node_coordinates.get_view();
167 auto cell_coords_host = Kokkos::create_mirror_view(cell_coords);
168 Kokkos::deep_copy(cell_coords_host, cell_coords);
169
170 const double tol = 1.0e-12;
171 CTD::checkPointwiseInclusion(inCell,
172 physical_points_cell,
173 cell_coords_host,
174 *topology_,
175 tol);
176 }
177
178 for (index_t cell=0; cell<static_cast<int>(d.num_cells); ++cell) {
179 if (inCell(cell,0) == 1) {
180 cellIndex_ = cell;
181 workset_id_ = d.getIdentifier();
182 haveProbe_ = true;
183 break;
184 }
185 }
186
187 // If no cell does, we're done
188 if (!haveProbe_) {
189 return false;
190 }
191
192 // Map point to reference frame
193 const size_t num_nodes = this->wda(d).cell_node_coordinates.extent(1);
194 Kokkos::DynRankView<double,HostSpace> cell_coords("cell_coords", 1, int(num_nodes), int(num_dim)); // <C,B,D>
195 auto cnc_host = Kokkos::create_mirror_view(this->wda(d).cell_node_coordinates.get_view());
196 Kokkos::deep_copy(cnc_host,this->wda(d).cell_node_coordinates.get_view());
197 for (size_t i=0; i<num_nodes; ++i) {
198 for (size_t j=0; j<num_dim; ++j) {
199 cell_coords(0,i,j) = cnc_host(cellIndex_,i,j);
200 }
201 }
202 Kokkos::DynRankView<double,HostSpace> physical_points("physical_points", 1, 1, num_dim); // <C,P,D>
203 for (size_t i=0; i<num_dim; ++i)
204 physical_points(0,0,i) = physical_points_cell(0,0,i);
205
206 Kokkos::DynRankView<double,HostSpace> reference_points("reference_points", 1, 1, num_dim); // <C,P,D>
207 CTD::mapToReferenceFrame(reference_points, physical_points, cell_coords, *topology_);
208
209 Kokkos::DynRankView<double,HostSpace> reference_points_cell("reference_points_cell", 1, num_dim); // <P,D>
210 for (size_t i=0; i<num_dim; ++i)
211 reference_points_cell(0,i) = reference_points(0,0,i);
212
213 // Compute basis functions at point
214 if (basis_->getElementSpace() == PureBasis::CONST ||
215 basis_->getElementSpace() == PureBasis::HGRAD) {
216
217 // Evaluate basis at reference values
218 Kokkos::DynRankView<double,HostSpace> ref_basis_values("ref_basis_values", num_basis, 1); // <B,P>
219 basis_->getIntrepid2Basis<HostSpace,double,double>()->getValues(ref_basis_values,
220 reference_points_cell,
221 Intrepid2::OPERATOR_VALUE);
222
223 // Apply transformation to physical frame
224 auto basis_values_host = Kokkos::create_mirror_view(basis_values_);
225 FST::HGRADtransformVALUE<double>(basis_values_host, ref_basis_values);
226 Kokkos::deep_copy(basis_values_,basis_values_host);
227 }
228 else if (basis_->getElementSpace() == PureBasis::HCURL ||
229 basis_->getElementSpace() == PureBasis::HDIV) {
230
231 // Evaluate basis at reference values
232 Kokkos::DynRankView<double,HostSpace> ref_basis_values("ref_basis_values", num_basis, 1, num_dim); // <B,P,D>
233 basis_->getIntrepid2Basis<HostSpace,double,double>()->getValues(ref_basis_values,
234 reference_points_cell,
235 Intrepid2::OPERATOR_VALUE);
236
237 // Apply transformation to physical frame
238 Kokkos::DynRankView<double,HostSpace> jac("jac", 1, 1, num_dim, num_dim); // <C,P,D,D>
239 CTD::setJacobian(jac, reference_points, cell_coords, *topology_);
240 Kokkos::DynRankView<double,HostSpace> basis_values_vec("basis_values_vec", 1, num_basis, 1, num_dim); // <C,B,P,D>
241 if (basis_->getElementSpace() == PureBasis::HCURL) {
242 Kokkos::DynRankView<double,HostSpace> jac_inv("jac_inv", 1, 1, num_dim, num_dim); // <C,P,D,D>
243 CTD::setJacobianInv(jac_inv, jac);
244 FST::HCURLtransformVALUE<double>(basis_values_vec, jac_inv,
245 ref_basis_values);
246 }
247 else {
248 Kokkos::DynRankView<double,HostSpace> jac_det("jac_det", 1, 1); // <C,P>
249 CTD::setJacobianDet(jac_det, jac);
250 FST::HDIVtransformVALUE<double>(basis_values_vec, jac, jac_det,
251 ref_basis_values);
252 }
253
254 // Compute element orientations
255 std::vector<double> orientation;
256 globalIndexer_->getElementOrientation(cellIndex_, orientation);
257 std::string blockId = this->wda(d).block_id;
258 int fieldNum = globalIndexer_->getFieldNum(fieldName_);
259 const std::vector<int> & elmtOffset = globalIndexer_->getGIDFieldOffsets(blockId,fieldNum);
260
261 // Extract component of basis
262 for (size_t i=0; i<num_basis; ++i) {
263 int offset = elmtOffset[i];
264 basis_values_(0,i,0) = orientation[offset] * basis_values_vec(0,i,0,fieldComponent_);
265 }
266
267 }
268
269 return true;
270}
271
272template<typename EvalT, typename Traits, typename LO, typename GO>
275{
276 using HostSpace = Kokkos::DefaultHostExecutionSpace;
277
278 if ( !haveProbe_ ||
279 (haveProbe_ && d.getIdentifier() != workset_id_) )
280 return;
281
282 auto field_coeffs_host = Kokkos::create_mirror_view(field_.get_view());
283 Kokkos::deep_copy(field_coeffs_host,field_.get_view());
284
285 auto field_coeffs_host_subview = Kokkos::subview(field_coeffs_host,std::pair<int,int>(cellIndex_,cellIndex_+1),Kokkos::ALL);
286
287 auto field_val = Sacado::createDynRankViewWithType<Kokkos::DynRankView<ScalarT,HostSpace>>(field_coeffs_host, "field_val_at_point", 1, 1); // <C,P>
288
289 auto basis_values_host = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),basis_values_);
290
291 Intrepid2::FunctionSpaceTools<HostSpace>::evaluate(field_val, field_coeffs_host_subview, basis_values_host);
292 responseObj_->value = field_val(0,0);
293 responseObj_->have_probe = true;
294}
295
296template <typename LO, typename GO>
299{
300 using Teuchos::RCP;
301 using Teuchos::rcp_dynamic_cast;
302 using Thyra::SpmdVectorBase;
303
304 TEUCHOS_ASSERT(this->scatterObj_!=Teuchos::null);
305
306 Base::evaluateFields(d);
307
308 // grab local data for inputing
309 Teuchos::ArrayRCP<double> local_dgdx;
310 RCP<SpmdVectorBase<double> > dgdx =
311 rcp_dynamic_cast<SpmdVectorBase<double> >(this->responseObj_->getGhostedVector());
312 if (dgdx.is_null()) {
313 // Blocked system: scatter into the block that owns the probed field, which
314 // is the block the scatter object's indexer was taken from.
315 auto blocked = rcp_dynamic_cast<Thyra::ProductVectorBase<double> >(
316 this->responseObj_->getGhostedVector(),true);
317 dgdx = rcp_dynamic_cast<SpmdVectorBase<double> >(
318 blocked->getNonconstVectorBlock(this->getProductVectorBlockIndex()),true);
319 }
320 dgdx->getNonconstLocalData(ptrFromRef(local_dgdx));
321 TEUCHOS_ASSERT(!local_dgdx.is_null());
322
323 this->scatterObj_->scatterDerivative(this->responseObj_->value,
324 this->cellIndex_,
325 this->responseObj_->have_probe,
326 d,this->wda,
327 this->getDerivativeOffset(this->wda(d).block_id),
328 local_dgdx);
329}
330
331}
332
333#endif
PHX::MDField< ScalarT, panzer::Cell, panzer::BASIS > field
A field to which we'll contribute, or in which we'll store, the result of computing this integral.
static std::string buildLookupName(const std::string &responseName)
int getDerivativeOffset(const std::string &blockId) const
First Fad derivative component belonging to the probed field's product vector block,...
void postRegistrationSetup(typename Traits::SetupData, PHX::FieldManager< Traits > &)
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.
int num_cells
DEPRECATED - use: numCells()
std::size_t getIdentifier() const
Get the unique identifier for this workset, this is not an index!
User-defined data passed to PHX::Evaluator::preEvaluate(), called once before each residual/Jacobian ...
Teuchos::RCP< GlobalEvaluationDataContainer > gedc
Container of global (non-cell-local) data, e.g. distributed vectors needed by gather/scatter evaluato...
User-defined data passed to PHX::Evaluator::postRegistrationSetup() during the one-time setup phase.
Teuchos::RCP< const std::vector< panzer::Workset > > worksets_
All worksets that will be evaluated over the lifetime of this evaluator.