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