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