/home/runner/work/amr-wind/amr-wind/amr-wind/wind_energy/actuator/disk/disk_spreading.H Source File

AMR-Wind API: /home/runner/work/amr-wind/amr-wind/amr-wind/wind_energy/actuator/disk/disk_spreading.H Source File
AMR-Wind API v0.1.0
CFD solver for wind plant simulations
Loading...
Searching...
No Matches
disk_spreading.H
Go to the documentation of this file.
1#ifndef DISK_SPREADING_H_
2#define DISK_SPREADING_H_
3
4#include "AMReX_REAL.H"
8
9using namespace amrex::literals;
10
12
21template <typename T>
23{
24public:
25 using OwnerType = T;
26
28 const T& actObj,
29 const int lev,
30 const amrex::MFIter& mfi,
31 const amrex::Geometry& geom)
32 {
33 (this->*m_function)(actObj, lev, mfi, geom);
34 }
35
37 void operator=(const SpreadingFunction&) = delete;
38
40 const T& actObj,
41 const int,
42 const amrex::MFIter&,
43 const amrex::Geometry&);
44
46 const T& actObj,
47 const int lev,
48 const amrex::MFIter& mfi,
49 const amrex::Geometry& geom)
50 {
51 const auto& bx = mfi.tilebox();
52
53 const auto bxa = amr_wind::utils::realbox_to_box(
54 actObj.m_data.info().bound_box, geom);
55 const auto& bxi = bx & bxa;
56 if (bxi.isEmpty()) {
57 return;
58 }
59
60 const auto& sarr = actObj.m_act_src(lev).array(mfi);
61 const auto& problo = geom.ProbLoArray();
62 const auto& dx = geom.CellSizeArray();
63
64 const auto& data = actObj.m_data.meta();
65
66 const vs::Vector epsilon = vs::Vector::one() * data.epsilon;
67 const vs::Vector m_normal(data.normal_vec);
68 const auto* pos = actObj.m_pos.data();
69 const auto* force = actObj.m_force.data();
70 const int npts = data.num_force_pts;
71 const int nForceTheta = data.num_force_theta_pts;
72 const auto dTheta = ::amr_wind::utils::two_pi() / nForceTheta;
73
74 amrex::ParallelFor(
75 bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
76 const vs::Vector cc{
77 problo[0] + (i + 0.5_rt) * dx[0],
78 problo[1] + (j + 0.5_rt) * dx[1],
79 problo[2] + (k + 0.5_rt) * dx[2],
80 };
81
82 amrex::RealArray src_force = {0.0_rt};
83 for (int ip = 0; ip < npts; ++ip) {
84 const auto& pforce = force[ip] / nForceTheta;
85 const auto pLoc = pos[ip];
86
87 for (int it = 0; it < nForceTheta; ++it) {
88 const amrex::Real angle =
89 ::amr_wind::utils::degrees(it * dTheta);
90 const auto rotMatrix = vs::quaternion(m_normal, angle);
91 const auto diskPoint = pLoc & rotMatrix;
92 const auto distance = diskPoint - cc;
93 const auto projection_weight =
94 utils::gaussian3d(distance, epsilon);
95
96 src_force[0] += projection_weight * pforce.x();
97 src_force[1] += projection_weight * pforce.y();
98 src_force[2] += projection_weight * pforce.z();
99 }
100 }
101
102 sarr(i, j, k, 0) += src_force[0];
103 sarr(i, j, k, 1) += src_force[1];
104 sarr(i, j, k, 2) += src_force[2];
105 });
106 }
107
109 const T& actObj,
110 const int lev,
111 const amrex::MFIter& mfi,
112 const amrex::Geometry& geom)
113 {
114 const auto& bx = mfi.tilebox();
115
116 const auto bxa = amr_wind::utils::realbox_to_box(
117 actObj.m_data.info().bound_box, geom);
118 const auto& bxi = bx & bxa;
119 if (bxi.isEmpty()) {
120 return;
121 }
122
123 const auto& sarr = actObj.m_act_src(lev).array(mfi);
124 const auto& problo = geom.ProbLoArray();
125 const auto& dx = geom.CellSizeArray();
126
127 const auto& data = actObj.m_data.meta();
128
129 const amrex::Real dR = data.dr;
130 const amrex::Real epsilon = data.epsilon;
131 const vs::Vector m_normal(data.normal_vec);
132 const vs::Vector m_origin(data.center);
133 const auto* pos = actObj.m_pos.data();
134 const auto* force = actObj.m_force.data();
135 const int npts = data.num_force_pts;
136
137 amrex::ParallelFor(
138 bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
139 const vs::Vector cc{
140 problo[0] + (i + 0.5_rt) * dx[0],
141 problo[1] + (j + 0.5_rt) * dx[1],
142 problo[2] + (k + 0.5_rt) * dx[2],
143 };
144
145 amrex::RealArray src_force = {0.0_rt};
146 for (int ip = 0; ip < npts; ++ip) {
147 const auto R = utils::delta_pnts_cyl(
148 m_origin, m_normal, m_origin, pos[ip])
149 .x();
150 const auto dist_on_disk =
151 utils::delta_pnts_cyl(m_origin, m_normal, cc, pos[ip]);
152 const auto& pforce = force[ip];
153
154 const amrex::Real weight_R =
155 utils::linear_basis_1d(dist_on_disk.x(), dR);
156 const amrex::Real weight_T =
157 1.0_rt / (::amr_wind::utils::two_pi() * R);
158 const amrex::Real weight_N =
159 utils::gaussian1d(dist_on_disk.z(), epsilon);
160 const auto projection_weight =
161 weight_R * weight_T * weight_N;
162
163 src_force[0] += projection_weight * pforce.x();
164 src_force[1] += projection_weight * pforce.y();
165 src_force[2] += projection_weight * pforce.z();
166 }
167
168 sarr(i, j, k, 0) += src_force[0];
169 sarr(i, j, k, 1) += src_force[1];
170 sarr(i, j, k, 2) += src_force[2];
171 });
172 }
174 const T& actObj,
175 const int lev,
176 const amrex::MFIter& mfi,
177 const amrex::Geometry& geom)
178 {
179 const auto& bx = mfi.tilebox();
180
181 const auto bxa = amr_wind::utils::realbox_to_box(
182 actObj.m_data.info().bound_box, geom);
183 const auto& bxi = bx & bxa;
184 if (bxi.isEmpty()) {
185 return;
186 }
187
188 const auto& sarr = actObj.m_act_src(lev).array(mfi);
189 const auto& problo = geom.ProbLoArray();
190 const auto& dx = geom.CellSizeArray();
191
192 const auto& data = actObj.m_data.meta();
193
194 const amrex::Real dR = data.dr;
195 const amrex::Real dTheta =
196 ::amr_wind::utils::two_pi() / data.num_vel_pts_t;
197 const amrex::Real epsilon = data.epsilon;
198 const vs::Vector m_normal(data.normal_vec);
199 const vs::Vector m_origin(data.center);
200 const auto* pos = actObj.m_pos.data();
201 const auto* force = actObj.m_force.data();
202 const int npts = data.num_force_pts;
203
204 amrex::ParallelFor(
205 bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
206 const vs::Vector cc{
207 problo[0] + (i + 0.5_rt) * dx[0],
208 problo[1] + (j + 0.5_rt) * dx[1],
209 problo[2] + (k + 0.5_rt) * dx[2],
210 };
211
212 amrex::RealArray src_force = {0.0_rt};
213 for (int ip = 0; ip < npts; ++ip) {
214 const auto radius =
216 m_origin, m_normal, m_origin, pos[ip])
217 .x();
218 const auto dArc = radius * dTheta;
219 const auto dist_on_disk =
220 utils::delta_pnts_cyl(m_origin, m_normal, cc, pos[ip]);
221 const amrex::Real arclength = dist_on_disk.y() * radius;
222 const auto& pforce = force[ip];
223
224 const amrex::Real weight_R =
225 utils::linear_basis_1d(dist_on_disk.x(), dR);
226 const amrex::Real weight_T =
227 utils::linear_basis_1d(arclength, dArc);
228 const amrex::Real weight_N =
229 utils::gaussian1d(dist_on_disk.z(), epsilon);
230 const auto projection_weight =
231 weight_R * weight_T * weight_N;
232
233 src_force[0] += projection_weight * pforce.x();
234 src_force[1] += projection_weight * pforce.y();
235 src_force[2] += projection_weight * pforce.z();
236 }
237
238 sarr(i, j, k, 0) += src_force[0];
239 sarr(i, j, k, 1) += src_force[1];
240 sarr(i, j, k, 2) += src_force[2];
241 });
242 }
243
246 void initialize(const std::string& key)
247 {
248 if (std::is_same<UniformCt, typename OwnerType::TraitType>::value) {
249 if (key == "UniformGaussian") {
251 } else if (key == "LinearBasis") {
253 } else {
254 amrex::Abort("Invalid spreading type");
255 }
256 } else {
258 }
259 }
260};
261} // namespace amr_wind::actuator::ops
262#endif /* DISK_SPREADING_H_ */
void linear_basis_spreading(const T &actObj, const int lev, const amrex::MFIter &mfi, const amrex::Geometry &geom)
Definition disk_spreading.H:108
SpreadingFunction()
Definition disk_spreading.H:244
void linear_basis_in_theta(const T &actObj, const int lev, const amrex::MFIter &mfi, const amrex::Geometry &geom)
Definition disk_spreading.H:173
void uniform_gaussian_spreading(const T &actObj, const int lev, const amrex::MFIter &mfi, const amrex::Geometry &geom)
Definition disk_spreading.H:45
MyType< ActTrait > OwnerType
Definition disk_spreading.H:25
void initialize(const std::string &key)
Definition disk_spreading.H:246
SpreadingFunction(const SpreadingFunction &)=delete
void operator()(const T &actObj, const int lev, const amrex::MFIter &mfi, const amrex::Geometry &geom)
Definition disk_spreading.H:27
void(SpreadingFunction::* m_function)(const MyType< ActTrait > &actObj, const int, const amrex::MFIter &, const amrex::Geometry &)
Definition disk_spreading.H:39
void operator=(const SpreadingFunction &)=delete
Definition ActSrcLineOp.H:12
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE vs::Vector delta_pnts_cyl(const vs::Vector &origin, const vs::Vector &normal, const vs::Vector &point1, const vs::Vector &point2)
Definition actuator_utils.H:88
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real gaussian1d(const amrex::Real &dist, const amrex::Real &eps)
Definition actuator_utils.H:70
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real gaussian3d(const vs::Vector &dist, const vs::Vector &eps)
Definition actuator_utils.H:45
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real linear_basis_1d(const amrex::Real distance, const amrex::Real dX)
Definition actuator_utils.H:128
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE constexpr amrex::Real two_pi()
Return .
Definition trig_ops.H:24
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real degrees(const amrex::Real rad_val)
Convert from radians to degrees.
Definition trig_ops.H:44
amrex::Box realbox_to_box(const amrex::RealBox &rbx, const amrex::Geometry &geom)
Definition index_operations.cpp:5
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Tensor quaternion(const Vector &axis, const amrex::Real angle)
Definition tensorI.H:218
VectorT< amrex::Real > Vector
Definition vector.H:148
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE constexpr VectorT< amrex::Real > one()
Definition vector.H:50
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE T & x() &noexcept
Definition vector.H:97