/home/runner/work/amr-wind/amr-wind/amr-wind/wind_energy/actuator/turbine/ActSrcDiskOp_Turbine.H Source File

AMR-Wind API: /home/runner/work/amr-wind/amr-wind/amr-wind/wind_energy/actuator/turbine/ActSrcDiskOp_Turbine.H Source File
AMR-Wind API v0.1.0
CFD solver for wind plant simulations
Loading...
Searching...
No Matches
ActSrcDiskOp_Turbine.H
Go to the documentation of this file.
1#ifndef ACTSRCDISKOP_TURBINE_H
2#define ACTSRCDISKOP_TURBINE_H
3
4#include <numbers>
5#include "AMReX_REAL.H"
10
11using namespace amrex::literals;
12
14
15template <typename ActTrait>
17 ActTrait,
19 std::enable_if_t<std::is_base_of_v<TurbineType, ActTrait>>>
20{
21private:
22 typename ActTrait::DataType& m_data;
24
28
29 void copy_to_device();
30
31public:
32 explicit ActSrcOp(typename ActTrait::DataType& data)
33 : m_data(data)
34 , m_act_src(m_data.sim().repo().get_field("actuator_src_term"))
35 {}
36
37 void initialize();
38
40
41 void
42 operator()(int lev, const amrex::MFIter& mfi, const amrex::Geometry& geom);
43};
44
45template <typename ActTrait>
46void ActSrcOp<
47 ActTrait,
49 std::enable_if_t<std::is_base_of_v<TurbineType, ActTrait>>>::initialize()
50{
51 const auto& meta = m_data.meta();
52 m_blades.resize(meta.num_blades);
53 m_tower.resize(1);
54 m_hub.resize(1);
55}
56
57template <typename ActTrait>
58void ActSrcOp<
59 ActTrait,
61 std::enable_if_t<std::is_base_of_v<TurbineType, ActTrait>>>::
62 copy_to_device()
63{
64 const auto& meta = m_data.meta();
65 std::vector<ComponentView> tower_vec(1, meta.tower);
66 std::vector<ComponentView> hub_vec(1, meta.hub);
67
68 amrex::Gpu::copy(
69 amrex::Gpu::hostToDevice, meta.blades.begin(), meta.blades.end(),
70 m_blades.begin());
71 amrex::Gpu::copy(
72 amrex::Gpu::hostToDevice, tower_vec.begin(), tower_vec.end(),
73 m_tower.begin());
74 amrex::Gpu::copy(
75 amrex::Gpu::hostToDevice, hub_vec.begin(), hub_vec.end(),
76 m_hub.begin());
77}
78
79template <typename ActTrait>
80void ActSrcOp<
81 ActTrait,
83 std::enable_if_t<std::is_base_of_v<TurbineType, ActTrait>>>::
84operator()(const int lev, const amrex::MFIter& mfi, const amrex::Geometry& geom)
85{
86 BL_PROFILE(
87 "amr-wind::ActSrcOp<" + ActTrait::identifier() +
89
90 const auto& bx = mfi.tilebox();
91
92 const auto bxa =
93 amr_wind::utils::realbox_to_box(m_data.info().bound_box, geom);
94 const auto& bxi = bx & bxa;
95 if (bxi.isEmpty()) {
96 return;
97 }
98
99 const auto& sarr = m_act_src(lev).array(mfi);
100 const auto& problo = geom.ProbLoArray();
101 const auto& dx = geom.CellSizeArray();
102
103 auto& tdata = m_data.meta();
104 const int nBlades = tdata.num_blades;
105 const int nPB = tdata.num_pts_blade;
106 const int nPT = tdata.num_pts_tower;
107 const auto* blades = m_blades.data();
108 const auto* tower = m_tower.data();
109 const auto* hub = m_hub.data();
110 // assume constant dr same for all blades
111 const auto* host_pos = tdata.blades[0].pos.data();
112 const amrex::Real dR = vs::mag_sqr(host_pos[0] - host_pos[1]);
113 const amrex::Real dT =
114 2.0_rt * std::numbers::pi_v<amrex::Real> / tdata.num_blades;
115 // assume these will be copied to device by the lambda capture...
116 const vs::Vector m_normal(tdata.rotor_frame.x());
117 const vs::Vector m_origin(tdata.rot_center);
118
119 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) {
120 const vs::Vector cc{
121 problo[0] + ((i + 0.5_rt) * dx[0]),
122 problo[1] + ((j + 0.5_rt) * dx[1]),
123 problo[2] + ((k + 0.5_rt) * dx[2]),
124 };
125
126 amrex::RealArray src_force = {0.0_rt};
127 for (int ib = 0; ib < nBlades; ++ib) {
128 // blade/disk contribution
129 {
130 const auto* pos = blades[ib].pos.data();
131 const auto* force = blades[ib].force.data();
132 const auto* eps = blades[ib].epsilon.data();
133
134 for (int ip = 0; ip < nPB; ++ip) {
135 const auto R = utils::delta_pnts_cyl(
136 m_origin, m_normal, m_origin, pos[ip])
137 .x();
138 const auto dist_on_disk =
139 utils::delta_pnts_cyl(m_origin, m_normal, cc, pos[ip]);
140 const auto& pforce = force[ip];
141
142 const amrex::Real weight_R =
143 utils::linear_basis_1d(dist_on_disk.x(), dR);
144 const amrex::Real weight_T =
145 utils::linear_basis_1d(R * dist_on_disk.y(), dT * R);
146 const amrex::Real weight_N =
147 utils::gaussian1d(dist_on_disk.z(), eps[ip].x());
148 const auto projection_weight =
149 weight_R * weight_T * weight_N;
150
151 src_force[0] += projection_weight * pforce.x();
152 src_force[1] += projection_weight * pforce.y();
153 src_force[2] += projection_weight * pforce.z();
154 }
155 }
156 // tower contribution
157 {
158 const auto* pos = tower[0].pos.data();
159 const auto* force = tower[0].force.data();
160 const auto* eps = tower[0].epsilon.data();
161 const auto* tmat = tower[0].orientation.data();
162 for (int ip = 0; ip < nPT; ++ip) {
163 const auto dist = cc - pos[ip];
164 const auto dist_local = tmat[ip] & dist;
165 const auto gauss_fac =
166 utils::gaussian3d(dist_local, eps[ip]);
167 const auto& pforce = force[ip];
168
169 src_force[0] += gauss_fac * pforce.x();
170 src_force[1] += gauss_fac * pforce.y();
171 src_force[2] += gauss_fac * pforce.z();
172 }
173 }
174 // hub
175 {
176 const auto* pos = hub[0].pos.data();
177 const auto* force = hub[0].force.data();
178 const auto* eps = hub[0].epsilon.data();
179 const auto* tmat = hub[0].orientation.data();
180 const auto dist = cc - pos[0];
181 const auto dist_local = tmat[0] & dist;
182 const auto gauss_fac = utils::gaussian3d(dist_local, eps[0]);
183 const auto& pforce = force[0];
184 src_force[0] += gauss_fac * pforce.x();
185 src_force[1] += gauss_fac * pforce.y();
186 src_force[2] += gauss_fac * pforce.z();
187 }
188 }
189
190 sarr(i, j, k, 0) += src_force[0];
191 sarr(i, j, k, 1) += src_force[1];
192 sarr(i, j, k, 2) += src_force[2];
193 });
194}
195} // namespace amr_wind::actuator::ops
196
197#endif /* ACTSRCDISKOP_TURBINE_H */
Definition Field.H:112
Definition actuator_ops.H:68
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:89
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real gaussian1d(const amrex::Real &dist, const amrex::Real &eps)
Definition actuator_utils.H:71
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:129
amrex::Gpu::DeviceVector< ComponentView > DeviceVecComponent
Definition turbine_types.H:29
Definition bluff_body_ops.cpp:18
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 T mag_sqr(const TensorT< T > &t)
Definition tensorI.H:175
VectorT< amrex::Real > Vector
Definition vector.H:145
Definition actuator_types.H:56
static std::string identifier()
Definition actuator_types.H:57
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE T & x() &
Definition vector.H:97