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"
33#include "Teuchos_ArrayRCP.hpp"
34
35#include "Kokkos_ViewFactory.hpp"
36
37namespace panzer {
38
39template<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,
48 const Teuchos::RCP<const panzer::GlobalIndexer> & indexer,
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
66 field_ = PHX::MDField<const ScalarT,Cell,BASIS>(fieldName,basis_->functional);
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";
79 RCP<PHX::DataLayout> dl_dummy = rcp(new PHX::MDALayout<panzer::Dummy>(0));
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}
87template<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
99template<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
110template<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
238template<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
262template <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
272 Base::evaluateFields(d);
273
274 // grab local data for inputing
275 Teuchos::ArrayRCP<double> local_dgdx;
276 RCP<SpmdVectorBase<double> > 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
static std::string buildLookupName(const std::string &responseName)
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!
Teuchos::RCP< GlobalEvaluationDataContainer > gedc
Teuchos::RCP< const std::vector< panzer::Workset > > worksets_