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
77
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);
87}
88
89template<typename EvalT, typename Traits, typename LO, typename GO>
93{
94 for (const auto& workset : *sd.worksets_) {
95 this->findCellAndComputeBasisValues(workset);
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
139 Teuchos::rcp_dynamic_cast<Response_Probe<EvalT> >(
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 // Intrepid2's first template parameter is a device, not an execution space.
152 using HostDevice = HostSpace::device_type;
153 using CTD = Intrepid2::CellTools<HostDevice>;
154 using FST = Intrepid2::FunctionSpaceTools<HostDevice>;
155
156 // Find which cell contains our point
157 const int num_points = 1;
158 Kokkos::DynRankView<int,HostSpace> inCell("inCell", this->wda(d).cell_node_coordinates.extent_int(0), num_points);
159 Kokkos::DynRankView<double,HostSpace> physical_points_cell("physical_points_cell", this->wda(d).cell_node_coordinates.extent_int(0), num_points, num_dim);
160 auto tmp_point = point_;
161 {
162 Kokkos::MDRangePolicy<HostSpace,Kokkos::Rank<2>> policy({0,0},{d.num_cells,static_cast<decltype(d.num_cells)>(num_dim)});
163 Kokkos::parallel_for("copy node coords",policy,[&](const int cell, const int dim){
164 physical_points_cell(cell,0,dim) = tmp_point[dim];
165 });
166 HostSpace().fence();
167
168 auto cell_coords = this->wda(d).cell_node_coordinates.get_view();
169 auto cell_coords_host = Kokkos::create_mirror_view(cell_coords);
170 Kokkos::deep_copy(cell_coords_host, cell_coords);
171
172 const double tol = 1.0e-12;
173 CTD::checkPointwiseInclusion(inCell,
174 physical_points_cell,
175 cell_coords_host,
176 *topology_,
177 tol);
178 }
179
180 for (index_t cell=0; cell<static_cast<int>(d.num_cells); ++cell) {
181 if (inCell(cell,0) == 1) {
182 cellIndex_ = cell;
184 haveProbe_ = true;
185 break;
186 }
187 }
188
189 // If no cell does, we're done
190 if (!haveProbe_) {
191 return false;
192 }
193
194 // Map point to reference frame
195 const size_t num_nodes = this->wda(d).cell_node_coordinates.extent(1);
196 Kokkos::DynRankView<double,HostSpace> cell_coords("cell_coords", 1, int(num_nodes), int(num_dim)); // <C,B,D>
197 auto cnc_host = Kokkos::create_mirror_view(this->wda(d).cell_node_coordinates.get_view());
198 Kokkos::deep_copy(cnc_host,this->wda(d).cell_node_coordinates.get_view());
199 for (size_t i=0; i<num_nodes; ++i) {
200 for (size_t j=0; j<num_dim; ++j) {
201 cell_coords(0,i,j) = cnc_host(cellIndex_,i,j);
202 }
203 }
204 Kokkos::DynRankView<double,HostSpace> physical_points("physical_points", 1, 1, num_dim); // <C,P,D>
205 for (size_t i=0; i<num_dim; ++i)
206 physical_points(0,0,i) = physical_points_cell(0,0,i);
207
208 Kokkos::DynRankView<double,HostSpace> reference_points("reference_points", 1, 1, num_dim); // <C,P,D>
209 CTD::mapToReferenceFrame(reference_points, physical_points, cell_coords, *topology_);
210
211 Kokkos::DynRankView<double,HostSpace> reference_points_cell("reference_points_cell", 1, num_dim); // <P,D>
212 for (size_t i=0; i<num_dim; ++i)
213 reference_points_cell(0,i) = reference_points(0,0,i);
214
215 // Compute basis functions at point
216 if (basis_->getElementSpace() == PureBasis::CONST ||
217 basis_->getElementSpace() == PureBasis::HGRAD) {
218
219 // Evaluate basis at reference values
220 Kokkos::DynRankView<double,HostSpace> ref_basis_values("ref_basis_values", num_basis, 1); // <B,P>
221 basis_->getIntrepid2Basis<HostDevice,double,double>()->getValues(ref_basis_values,
222 reference_points_cell,
223 Intrepid2::OPERATOR_VALUE);
224
225 // Apply transformation to physical frame
226 auto basis_values_host = Kokkos::create_mirror_view(basis_values_);
227 FST::HGRADtransformVALUE<double>(basis_values_host, ref_basis_values);
228 Kokkos::deep_copy(basis_values_,basis_values_host);
229 }
230 else if (basis_->getElementSpace() == PureBasis::HCURL ||
231 basis_->getElementSpace() == PureBasis::HDIV) {
232
233 // Evaluate basis at reference values
234 Kokkos::DynRankView<double,HostSpace> ref_basis_values("ref_basis_values", num_basis, 1, num_dim); // <B,P,D>
235 basis_->getIntrepid2Basis<HostDevice,double,double>()->getValues(ref_basis_values,
236 reference_points_cell,
237 Intrepid2::OPERATOR_VALUE);
238
239 // Apply transformation to physical frame
240 Kokkos::DynRankView<double,HostSpace> jac("jac", 1, 1, num_dim, num_dim); // <C,P,D,D>
241 CTD::setJacobian(jac, reference_points, cell_coords, *topology_);
242 Kokkos::DynRankView<double,HostSpace> basis_values_vec("basis_values_vec", 1, num_basis, 1, num_dim); // <C,B,P,D>
243 if (basis_->getElementSpace() == PureBasis::HCURL) {
244 Kokkos::DynRankView<double,HostSpace> jac_inv("jac_inv", 1, 1, num_dim, num_dim); // <C,P,D,D>
245 CTD::setJacobianInv(jac_inv, jac);
246 FST::HCURLtransformVALUE<double>(basis_values_vec, jac_inv,
247 ref_basis_values);
248 }
249 else {
250 Kokkos::DynRankView<double,HostSpace> jac_det("jac_det", 1, 1); // <C,P>
251 CTD::setJacobianDet(jac_det, jac);
252 FST::HDIVtransformVALUE<double>(basis_values_vec, jac, jac_det,
253 ref_basis_values);
254 }
255
256 // Compute element orientations
257 std::vector<double> orientation;
258 globalIndexer_->getElementOrientation(cellIndex_, orientation);
259 std::string blockId = this->wda(d).block_id;
260 int fieldNum = globalIndexer_->getFieldNum(fieldName_);
261 const std::vector<int> & elmtOffset = globalIndexer_->getGIDFieldOffsets(blockId,fieldNum);
262
263 // Extract component of basis
264 for (size_t i=0; i<num_basis; ++i) {
265 int offset = elmtOffset[i];
266 basis_values_(0,i,0) = orientation[offset] * basis_values_vec(0,i,0,fieldComponent_);
267 }
268
269 }
270
271 return true;
272}
273
274template<typename EvalT, typename Traits, typename LO, typename GO>
277{
278 using HostSpace = Kokkos::DefaultHostExecutionSpace;
279 // Intrepid2's first template parameter is a device, not an execution space.
280 using HostDevice = HostSpace::device_type;
281
282 if ( !haveProbe_ ||
284 return;
285
286 auto field_coeffs_host = Kokkos::create_mirror_view(field_.get_view());
287 Kokkos::deep_copy(field_coeffs_host,field_.get_view());
288
289 auto field_coeffs_host_subview = Kokkos::subview(field_coeffs_host,std::pair<int,int>(cellIndex_,cellIndex_+1),Kokkos::ALL);
290
291 auto field_val = Sacado::createDynRankViewWithType<Kokkos::DynRankView<ScalarT,HostSpace>>(field_coeffs_host, "field_val_at_point", 1, 1); // <C,P>
292
293 auto basis_values_host = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),basis_values_);
294
295 Intrepid2::FunctionSpaceTools<HostDevice>::evaluate(field_val, field_coeffs_host_subview, basis_values_host);
296 responseObj_->value = field_val(0,0);
297 responseObj_->have_probe = true;
298}
299
300template <typename LO, typename GO>
303{
304 using Teuchos::RCP;
305 using Teuchos::rcp_dynamic_cast;
306 using Thyra::SpmdVectorBase;
307
308 TEUCHOS_ASSERT(this->scatterObj_!=Teuchos::null);
309
311
312 // grab local data for inputing
313 Teuchos::ArrayRCP<double> local_dgdx;
314 RCP<SpmdVectorBase<double> > dgdx =
315 rcp_dynamic_cast<SpmdVectorBase<double> >(this->responseObj_->getGhostedVector());
316 if (dgdx.is_null()) {
317 // Blocked system: scatter into the block that owns the probed field, which
318 // is the block the scatter object's indexer was taken from.
319 auto blocked = rcp_dynamic_cast<Thyra::ProductVectorBase<double> >(
320 this->responseObj_->getGhostedVector(),true);
321 dgdx = rcp_dynamic_cast<SpmdVectorBase<double> >(
322 blocked->getNonconstVectorBlock(this->getProductVectorBlockIndex()),true);
323 }
324 dgdx->getNonconstLocalData(ptrFromRef(local_dgdx));
325 TEUCHOS_ASSERT(!local_dgdx.is_null());
326
327 this->scatterObj_->scatterDerivative(this->responseObj_->value,
328 this->cellIndex_,
329 this->responseObj_->have_probe,
330 d,this->wda,
331 this->getDerivativeOffset(this->wda(d).block_id),
332 local_dgdx);
333}
334
335}
336
337#endif
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.
Teuchos::RCP< const panzer::GlobalIndexer > globalIndexer_
int num_cells
DEPRECATED - use: numCells().
std::size_t getIdentifier() const
Get the unique identifier for this workset, this is not an index!
Teuchos::RCP< GlobalEvaluationDataContainer > gedc
Container of global (non-cell-local) data, e.g. distributed vectors needed by gather/scatter evaluato...
Teuchos::RCP< const std::vector< panzer::Workset > > worksets_
All worksets that will be evaluated over the lifetime of this evaluator.
const PED & PreEvalData
Data type passed to PHX::Evaluator::preEvaluate().
const panzer::Workset & EvalData
Data type passed to PHX::Evaluator::evaluateFields(): a single workset holding the cell data for one ...
const SD & SetupData
Data type passed to PHX::Evaluator::postRegistrationSetup().