VertexCFD  0.0-dev
VertexCFD_Utils_SmoothClamp.hpp
1 #ifndef VERTEXCFD_UTILS_SMOOTHCLAMP_HPP
2 #define VERTEXCFD_UTILS_SMOOTHCLAMP_HPP
3 
4 #include <Sacado.hpp>
5 #include <Sacado_Fad_Exp_Expression.hpp>
6 #include <Sacado_Fad_Exp_ExpressionTraits.hpp>
7 
8 #include <type_traits>
9 
10 namespace VertexCFD
11 {
12 namespace SmoothMath
13 {
14 //---------------------------------------------------------------------------//
15 // Implementation of smooth "clamp" using Sacado expressions
16 //---------------------------------------------------------------------------//
17 template<typename T, typename ExprSpec>
19 {
20 };
21 
22 template<typename T>
23 class SmoothClampOp<T, Sacado::Fad::Exp::ExprSpecDefault>
24  : public Sacado::Fad::Exp::Expr<
25  SmoothClampOp<T, Sacado::Fad::Exp::ExprSpecDefault>>
26 {
27  public:
28  using ExprT = typename std::remove_cv<T>::type;
29  using value_type = typename ExprT::value_type;
30  using scalar_type = typename ExprT::scalar_type;
31  using expr_spec_type = Sacado::Fad::Exp::ExprSpecDefault;
32 
33  SACADO_INLINE_FUNCTION explicit SmoothClampOp(const T& x,
34  double lo,
35  double hi,
36  double tol)
37  : x_(x)
38  , lo_(lo)
39  , hi_(hi)
40  , tol_(tol)
41  {
42  }
43 
44  SACADO_INLINE_FUNCTION int size() const { return x_.size(); }
45 
46  SACADO_INLINE_FUNCTION bool hasFastAccess() const
47  {
48  return x_.hasFastAccess();
49  }
50 
51  SACADO_INLINE_FUNCTION value_type val() const
52  {
53  // -inf < x < inf
54  if (x_ <= lo_ - tol_)
55  {
56  return lo_;
57  }
58 
59  // lo - tol < x < inf
60  else if (x_ >= hi_ + tol_)
61  {
62  return hi_;
63  }
64 
65  // lo - tol < x < hi + tol
66  else if (x_ < lo_ + tol_)
67  {
68  // lo - tol < x < lo + tol => -tol < (x-lo) < tol
69  return 0.5
70  * (x_.val() + lo_
71  + 0.5
72  * ((x_.val() - lo_) * (x_.val() - lo_) / tol_
73  + tol_));
74  }
75 
76  // lo + tol <= x < hi + tol
77  else if (x_ > hi_ - tol_)
78  {
79  // hi - tol < x < hi + tol => -tol < (x-hi) < tol
80  return 0.5
81  * (x_.val() + hi_
82  - 0.5
83  * ((x_.val() - hi_) * (x_.val() - hi_) / tol_
84  + tol_));
85  }
86 
87  // lo + tol <= x <= h - tol
88  else
89  {
90  return x_.val();
91  }
92  }
93 
94  SACADO_INLINE_FUNCTION value_type dx(int i) const
95  {
96  // -inf < x < inf
97  if (x_ <= lo_ - tol_)
98  {
99  return 0.0;
100  }
101  // lo - tol < x < inf
102  else if (x_ >= hi_ + tol_)
103  {
104  return 0.0;
105  }
106  // lo - tol < x < hi + tol
107  else if (x_ < lo_ + tol_)
108  {
109  // lo - tol < x < lo + tol => -tol < (x-lo) < tol
110  return 0.5 * (x_.dx(i) + (x_.val() - lo_) * x_.dx(i) / tol_);
111  }
112  // lo + tol <= x < hi + tol
113  else if (x_ > hi_ - tol_)
114  {
115  // hi - tol < x < hi + tol => -tol < (x-hi) < tol
116  return 0.5 * (x_.dx(i) + (x_.val() - hi_) * x_.dx(i) / tol_);
117  }
118  // lo + tol <= x <= h - tol
119  else
120  {
121  return x_.dx(i);
122  }
123  }
124 
125  SACADO_INLINE_FUNCTION value_type fastAccessDx(int i) const
126  {
127  // -inf < x < inf
128  if (x_ <= lo_ - tol_)
129  {
130  return 0.0;
131  }
132  // lo - tol < x < inf
133  else if (x_ >= hi_ + tol_)
134  {
135  return 0.0;
136  }
137  // lo - tol < x < hi + tol
138  else if (x_ < lo_ + tol_)
139  {
140  // lo - tol < x < lo + tol => -tol < (x-lo) < tol
141  return 0.5
142  * (x_.fastAccessDx(i)
143  + (x_.val() - lo_) * x_.fastAccessDx(i) / tol_);
144  }
145  // lo + tol <= x < hi + tol
146  else if (x_ > hi_ - tol_)
147  {
148  // hi - tol < x < hi + tol => -tol < (x-hi) < tol
149  return 0.5
150  * (x_.fastAccessDx(i)
151  + (x_.val() - hi_) * x_.fastAccessDx(i) / tol_);
152  }
153  // lo + tol <= x <= h - tol
154  else
155  {
156  return x_.fastAccessDx(i);
157  }
158  }
159 
160  private:
161  const T& x_;
162  double lo_;
163  double hi_;
164  double tol_;
165 };
166 
167 // Generic implementation for POD types
168 template<typename T>
169 SACADO_INLINE_FUNCTION
170  typename std::enable_if<std::is_trivial<T>::value, T>::type
171  clamp(const T x, const double lo, const double hi, const double tol)
172 {
173  // -inf < x < inf
174  if (x <= lo - tol)
175  {
176  return lo;
177  }
178 
179  // lo - tol < x < inf
180  else if (x >= hi + tol)
181  {
182  return hi;
183  }
184 
185  // lo - tol < x < hi + tol
186  else if (x < lo + tol)
187  {
188  // lo - tol < x < lo + tol => -tol < (x-lo) < tol
189  return 0.5 * (x + lo + 0.5 * ((x - lo) * (x - lo) / tol + tol));
190  }
191 
192  // lo + tol <= x < hi + tol
193  else if (x > hi - tol)
194  {
195  // hi - tol < x < hi + tol => -tol < (x-hi) < tol
196  return 0.5 * (x + hi - 0.5 * ((x - hi) * (x - hi) / tol + tol));
197  }
198 
199  // lo + tol <= x <= h - tol
200  else
201  {
202  return x;
203  }
204 }
205 
206 using Sacado::Fad::Exp::Expr;
207 
208 // Specialization for FAD types
209 template<typename T>
210 SACADO_INLINE_FUNCTION
211  SmoothClampOp<typename Expr<T>::derived_type, typename T::expr_spec_type>
212  clamp(const Expr<T>& x, double lo, double hi, double tol)
213 {
214  using expr_t = SmoothClampOp<typename Expr<T>::derived_type,
215  typename T::expr_spec_type>;
216  return expr_t(x.derived(), lo, hi, tol);
217 }
218 
219 } // end namespace SmoothMath
220 } // end namespace VertexCFD
221 
222 namespace Sacado
223 {
224 
226 
227 namespace Fad
228 {
229 namespace Exp
230 {
231 
232 //
233 // Specializations for Sacado traits
234 //
235 
236 template<typename T, typename E>
237 struct ExprLevel<SmoothClampOp<T, E>>
238 {
239  static const unsigned value = ExprLevel<T>::value;
240 };
241 
242 template<typename T, typename E>
243 struct IsFadExpr<SmoothClampOp<T, E>>
244 {
245  static const unsigned value = true;
246 };
247 
248 } // namespace Exp
249 } // namespace Fad
250 
251 template<typename T, typename E>
252 struct IsExpr<SmoothClampOp<T, E>>
253 {
254  static const unsigned value = true;
255 };
256 
257 template<typename T, typename E>
258 struct BaseExprType<SmoothClampOp<T, E>>
259 {
260  using type = typename BaseExprType<T>::type;
261 };
262 
263 template<typename T, typename E>
264 struct IsSimdType<SmoothClampOp<T, E>>
265 {
266  static const bool value
267  = IsSimdType<typename SmoothClampOp<T, E>::scalar_type>::value;
268 };
269 
270 template<typename T, typename E>
271 struct ValueType<SmoothClampOp<T, E>>
272 {
273  using type = typename SmoothClampOp<T, E>::value_type;
274 };
275 
276 template<typename T, typename E>
277 struct ScalarType<SmoothClampOp<T, E>>
278 {
279  using type = typename SmoothClampOp<T, E>::scalar_type;
280 };
281 
282 } // namespace Sacado
283 
284 #endif // end VERTEXCFD_UTILS_SMOOTHCLAMP_HPP
VertexCFD
Definition: tstMethodManufacturedSolutionBC.cpp:23
VertexCFD::SmoothMath::SmoothClampOp
Definition: VertexCFD_Utils_SmoothClamp.hpp:19