VertexCFD  0.0-dev
VertexCFD_Utils_ScalarToVector_impl.hpp
1 #ifndef VERTEXCFD_UTILS_SCALARTOVECTOR_IMPL_HPP
2 #define VERTEXCFD_UTILS_SCALARTOVECTOR_IMPL_HPP
3 
4 #include <Phalanx_DataLayout_MDALayout.hpp>
5 
6 #include <Kokkos_Core.hpp>
7 
8 #include <limits>
9 #include <utility>
10 
11 namespace VertexCFD
12 {
13 namespace Utils
14 {
15 
16 //---------------------------------------------------------------------------//
17 template<typename EvalType, typename NewTag>
18 ScalarToVector<EvalType, NewTag>::ScalarToVector(
19  const panzer::IntegrationRule& ir,
20  const std::string& vector_name,
21  const VecOpt<std::string>& scalar_names,
22  const bool time_deriv,
23  const bool grads)
24  : _vector_name{vector_name}
25  , _scalar_names{scalar_names}
26 {
27  addFields("", _vector_field, _scalar_fields, ir.dl_scalar);
28 
29  if (grads)
30  {
31  addFields(
32  "GRAD_", _vector_grad_field, _scalar_grad_fields, ir.dl_vector);
33  }
34 
35  if (time_deriv)
36  {
37  addFields(
38  "DXDT_", _vector_dxdt_field, _scalar_dxdt_fields, ir.dl_scalar);
39  }
40 
41  this->setName("ScalarToVector (" + vector_name + ")");
42 }
43 
44 //---------------------------------------------------------------------------//
45 template<typename EvalType, typename NewTag>
46 void ScalarToVector<EvalType, NewTag>::evaluateFields(
47  typename panzer::Traits::EvalData)
48 {
49  copyFields(_vector_field, _scalar_fields);
50  copyFields(_vector_grad_field, _scalar_grad_fields);
51  copyFields(_vector_dxdt_field, _scalar_dxdt_fields);
52 }
53 
54 //---------------------------------------------------------------------------//
55 namespace Impl
56 {
57 // Make a new Layout by, taking all but the last extent from an existing
58 // layout.
59 template<typename... Tags, std::size_t... Is>
60 auto makeLayout(const PHX::DataLayout& layout,
61  std::index_sequence<Is...>,
62  const int num_scalars)
63 {
64  static_assert(sizeof...(Is) + 1 == sizeof...(Tags));
65 
66  return Teuchos::rcp(
67  new PHX::MDALayout<Tags...>(layout.extent(Is)..., num_scalars));
68 }
69 } // namespace Impl
70 
71 // Add dependent and evaluated fields for scalars and vector, respectively.
72 template<typename EvalType, typename NewTag>
73 template<typename... ScalarTags>
74 void ScalarToVector<EvalType, NewTag>::addFields(
75  const char* prefix,
76  PHX::MDField<ScalarT, ScalarTags..., NewTag>& vector_field,
77  VecOpt<PHX::MDField<const ScalarT, ScalarTags...>>& scalar_fields,
78  const Teuchos::RCP<PHX::DataLayout>& scalar_layout)
79 {
80  const int num_scalars = _scalar_names.size();
81 
82  scalar_fields.reserve(num_scalars);
83  for (const auto& name : _scalar_names)
84  {
85  if (name)
86  scalar_fields.emplace_back(
87  std::in_place, prefix + *name, scalar_layout);
88  else
89  scalar_fields.emplace_back(std::nullopt);
90  }
91 
92  auto vector_layout = Impl::makeLayout<ScalarTags..., NewTag>(
93  *scalar_layout, std::index_sequence_for<ScalarTags...>{}, num_scalars);
94 
95  vector_field = PHX::MDField<ScalarT, ScalarTags..., NewTag>(
96  prefix + _vector_name, vector_layout);
97 
98  this->addEvaluatedField(vector_field);
99  for (const auto& field : scalar_fields)
100  {
101  if (field)
102  this->addDependentField(*field);
103  }
104 }
105 
106 //---------------------------------------------------------------------------//
107 namespace Impl
108 {
109 // Make a dependent ALL so that it can be duplicated through pack expansion.
110 template<typename>
111 constexpr auto ALL = Kokkos::ALL;
112 } // namespace Impl
113 
114 // Perform copies from scalars to vector.
115 template<typename EvalType, typename NewTag>
116 template<typename... ScalarTags>
117 void ScalarToVector<EvalType, NewTag>::copyFields(
118  PHX::MDField<ScalarT, ScalarTags..., NewTag>& vector_field,
119  VecOpt<PHX::MDField<const ScalarT, ScalarTags...>>& scalar_fields)
120 {
121  const int num_scalars = scalar_fields.size();
122 
123  for (int sc = 0; sc < num_scalars; ++sc)
124  {
125  auto vector_view = Kokkos::subview(
126  vector_field.get_view(), Impl::ALL<ScalarTags>..., sc);
127  if (scalar_fields[sc])
128  {
129  Kokkos::deep_copy(vector_view, scalar_fields[sc]->get_view());
130  }
131  else
132  {
133  Kokkos::deep_copy(vector_view,
134  std::numeric_limits<double>::signaling_NaN());
135  }
136  }
137 }
138 
139 //---------------------------------------------------------------------------//
140 template<typename EvalType, typename NewTag>
141 auto ScalarToVector<EvalType, NewTag>::createFromIndexed(
142  const panzer::IntegrationRule& ir,
143  const std::string& vector_name,
144  const int num_scalars,
145  const bool time_deriv,
146  const bool grads)
147 {
148  auto scalar_names = VecOpt<std::string>{};
149  scalar_names.reserve(num_scalars);
150  for (int n = 0; n < num_scalars; ++n)
151  {
152  const auto ns = std::to_string(n);
153  scalar_names.emplace_back(vector_name + "_" + ns);
154  }
155  return Teuchos::rcp(
156  new ScalarToVector(ir, vector_name, scalar_names, time_deriv, grads));
157 };
158 
159 //---------------------------------------------------------------------------//
160 template<typename EvalType, typename NewTag>
161 auto ScalarToVector<EvalType, NewTag>::createFromSuffixed(
162  const panzer::IntegrationRule& ir,
163  const std::string& vector_name,
164  const VecOpt<std::string>& scalar_suffixes,
165  const bool time_deriv,
166  const bool grads)
167 {
168  auto scalar_names = VecOpt<std::string>{};
169  scalar_names.reserve(scalar_suffixes.size());
170  for (const auto& suffix : scalar_suffixes)
171  {
172  std::optional<std::string> name;
173  if (suffix)
174  name = vector_name + "_" + *suffix;
175  scalar_names.emplace_back(std::move(name));
176  }
177  return Teuchos::rcp(
178  new ScalarToVector(ir, vector_name, scalar_names, time_deriv, grads));
179 };
180 
181 //---------------------------------------------------------------------------//
182 template<typename EvalType, typename NewTag>
183 auto ScalarToVector<EvalType, NewTag>::createFromList(
184  const panzer::IntegrationRule& ir,
185  const std::string& vector_name,
186  const std::vector<std::string>& scalar_list,
187  const bool time_deriv,
188  const bool grads)
189 {
190  auto scalar_names = VecOpt<std::string>{};
191  scalar_names.reserve(scalar_list.size());
192  for (const auto& name : scalar_list)
193  {
194  scalar_names.emplace_back(std::move(name));
195  }
196  return Teuchos::rcp(
197  new ScalarToVector(ir, vector_name, scalar_names, time_deriv, grads));
198 };
199 
200 //---------------------------------------------------------------------------//
201 
202 } // namespace Utils
203 } // namespace VertexCFD
204 
205 #endif // VERTEXCFD_UTILS_SCALARTOVECTOR_IMPL_HPP
VertexCFD
Definition: tstMethodManufacturedSolutionBC.cpp:23