1 #ifndef ERF_IBSEB_SOLAR_H
2 #define ERF_IBSEB_SOLAR_H
4 #include <AMReX_REAL.H>
5 #include <AMReX_GpuQualifiers.H>
6 #include <AMReX_Algorithm.H>
7 #include <AMReX_Array4.H>
43 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
46 return 2.0 *
PI * (day_of_year - 1.0) / 365.0;
54 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
57 return day0 + std::floor(t_utc_s / 86400.0);
61 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
66 - 0.399912 * std::cos(
gamma) + 0.070257 * std::sin(
gamma)
67 - 0.006758 * std::cos(2.0 *
gamma) + 0.000907 * std::sin(2.0 *
gamma)
68 - 0.002697 * std::cos(3.0 *
gamma) + 0.00148 * std::sin(3.0 *
gamma);
72 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
76 return 229.18 * (0.000075 + 0.001868 * std::cos(
gamma) - 0.032077 * std::sin(
gamma)
77 - 0.014615 * std::cos(2.0 *
gamma) - 0.040849 * std::sin(2.0 *
gamma));
86 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
89 amrex::Real t_utc_h = std::fmod(time_utc_s / 3600.0, 24.0);
90 if (t_utc_h < 0.0) { t_utc_h += 24.0; }
92 return 15.0 * (t_solar_h - 12.0) *
PI / 180.0;
104 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
107 const double two_pi = 2.0 * double(
PI);
108 double h = two_pi * (calday - std::floor(calday)) +
double(longitude_rad) - double(
PI);
109 h = std::fmod(h +
double(
PI), two_pi);
110 if (h < 0.0) { h += two_pi; }
115 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
119 amrex::Real cz = std::sin(lat) * std::sin(decl) + std::cos(lat) * std::cos(decl) * std::cos(hour_angle);
120 if (cz < -1.0) { cz = -1.0; }
121 if (cz > 1.0) { cz = 1.0; }
122 return std::acos(cz);
130 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
137 if (sz < 1.0e-6) {
return 0.0; }
139 if (std::abs(cos_lat) < 1.0e-6) {
return 0.0; }
142 const amrex::Real sin_az = -std::sin(hour_angle) * std::cos(decl) / sz;
143 const amrex::Real cos_az = (std::sin(decl) - cz * std::sin(lat)) / (sz * cos_lat);
145 if (az < 0.0) { az += 2.0 *
PI; }
154 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
158 return 1.000110 + 0.034221 * std::cos(G) + 0.001280 * std::sin(G)
159 + 0.000719 * std::cos(2.0 * G) + 0.000077 * std::sin(2.0 * G);
163 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
168 sx = s * std::sin(azimuth);
169 sy = s * std::cos(azimuth);
170 sz = std::cos(zenith);
178 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
182 if (cos_zenith <= 1.0e-3)
return 0.0;
183 return S0 * distance_factor * std::pow(tau, 1.0 / cos_zenith);
191 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
195 if (cos_zenith <= 1.0e-3)
return 0.0;
196 const amrex::Real tr = std::pow(tau, 1.0 / cos_zenith);
197 return k_d * S0 * distance_factor * cos_zenith * (1.0 - tr);
220 amrex::Array4<const int>
top;
231 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
235 if (!
wrap_x) {
return false; }
238 if (cj <
top.begin[1] || cj >=
top.end[1]) {
239 if (!
wrap_y) {
return false; }
240 cj =
top.begin[1] + ((cj -
top.begin[1]) %
ny +
ny) %
ny;
246 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
249 const int kt =
top(
ci, cj,
top.begin[2]);
264 if (
height <= 0.0) {
return 1; }
266 if (sz_min <= 0.0 || cz <= 0.0) {
return std::numeric_limits<int>::max() / 4; }
268 if (reach >=
amrex::Real(std::numeric_limits<int>::max() / 8)) {
return std::numeric_limits<int>::max() / 4; }
269 return amrex::max(1,
static_cast<int>(std::ceil(reach)) + 1);
283 const amrex::Real u_min = 0.5 / n_el, u_max = (n_el - 0.5) / n_el;
285 const amrex::Real wall = std::sqrt(u_min) * std::sin(
PI / n_az);
286 return amrex::min(roof, wall);
308 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
312 if (sz <= 0.0)
return true;
313 if (
z0 >= m.
z_max)
return false;
318 int ci = m.
ilo +
static_cast<int>(std::floor((
x - m.
x_lo) /
dx));
319 int cj = m.
jlo +
static_cast<int>(std::floor((
y - m.
y_lo) /
dy));
320 const int stepx = (sx > 0.0) ? 1 : ((sx < 0.0) ? -1 : 0);
321 const int stepy = (sy > 0.0) ? 1 : ((sy < 0.0) ? -1 : 0);
323 const amrex::Real tdx = (stepx != 0) ?
dx / std::abs(sx) : big;
324 const amrex::Real tdy = (stepy != 0) ?
dy / std::abs(sy) : big;
327 if (stepx > 0) tmx = ((m.
x_lo + (
ci - m.
ilo + 1) *
dx) -
x) / sx;
328 else if (stepx < 0) tmx = ((m.
x_lo + (
ci - m.
ilo) *
dx) -
x) / sx;
329 if (stepy > 0) tmy = ((m.
y_lo + (cj - m.
jlo + 1) *
dy) -
y) / sy;
330 else if (stepy < 0) tmy = ((m.
y_lo + (cj - m.
jlo) *
dy) -
y) / sy;
335 const int max_iter =
static_cast<int>(amrex::min(
amrex::Real(1.0e9), steps)) + 8;
336 for (
int it = 0; it < max_iter; ++it) {
338 if (!m.
locate(
ci, cj))
return false;
342 if (tmx < tmy) {
t = tmx; tmx += tdx;
ci += stepx; }
343 else {
t = tmy; tmy += tdy; cj += stepy; }
344 z =
z0 +
t0 * sz +
t * sz;
345 if (
z >= m.
z_max)
return false;
370 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
379 int ci = m.
ilo +
static_cast<int>(std::floor((
x - m.
x_lo) /
dx));
380 int cj = m.
jlo +
static_cast<int>(std::floor((
y - m.
y_lo) /
dy));
381 const int stepx = (sx > 0.0) ? 1 : ((sx < 0.0) ? -1 : 0);
382 const int stepy = (sy > 0.0) ? 1 : ((sy < 0.0) ? -1 : 0);
384 const amrex::Real tdx = (stepx != 0) ?
dx / std::abs(sx) : big;
385 const amrex::Real tdy = (stepy != 0) ?
dy / std::abs(sy) : big;
387 if (stepx > 0) tmx = ((m.
x_lo + (
ci - m.
ilo + 1) *
dx) -
x) / sx;
388 else if (stepx < 0) tmx = ((m.
x_lo + (
ci - m.
ilo) *
dx) -
x) / sx;
389 if (stepy > 0) tmy = ((m.
y_lo + (cj - m.
jlo + 1) *
dy) -
y) / sy;
390 else if (stepy < 0) tmy = ((m.
y_lo + (cj - m.
jlo) *
dy) -
y) / sy;
391 if (stepx == 0 && stepy == 0) {
401 const bool level = (std::abs(sz) < 1.0e-9);
406 const int max_iter =
static_cast<int>(amrex::min(
amrex::Real(1.0e9), steps)) + 8;
407 for (
int it = 0; it < max_iter; ++it) {
410 const bool solid = (top > m.
z_ground + eps);
420 if (tmx < tmy) { tmx += tdx;
ci += stepx; }
421 else { tmy += tdy; cj += stepy; }
436 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
445 amrex::Real n[3] = {0.0, 0.0, 0.0}, t1[3] = {0.0, 0.0, 0.0}, t2[3] = {0.0, 0.0, 0.0};
447 if (dir == 0) { t1[1] = 1.0; t2[2] = 1.0; }
448 else if (dir == 1) { t1[0] = 1.0; t2[2] = 1.0; }
449 else { t1[0] = 1.0; t2[1] = 1.0; }
450 sx = cn * n[0] + ct * t1[0] + st * t2[0];
451 sy = cn * n[1] + ct * t1[1] + st * t2[1];
452 sz = cn * n[2] + ct * t1[2] + st * t2[2];
Real z0
Definition: ERF_InitCustomPertVels_ScalarAdvDiff.H:12
const Real dy
Definition: ERF_InitCustomPert_ABL.H:45
const Real dx
Definition: ERF_InitCustomPert_ABL.H:44
amrex::Real gamma
Definition: ERF_InitCustomPert_DataAssimilation_ISV.H:9
Real height
Definition: ERF_InitCustomPert_SquallLine.H:37
Dimensionless numeric literals and pure mathematical constants.
constexpr amrex::Real PI
Definition: ERF_NumericalConstants.H:46
amrex::Real Real
Definition: ERF_ShocInterface.H:19
@ theta
Definition: ERF_Kessler.H:26
@ t
Definition: ERF_WSM6.H:293
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real phi(amrex::Real d, amrex::Real z0, amrex::Real psi) noexcept
Definition: ERF_ImmersedWallCell.H:142
Definition: ERF_IBSEBBalance.H:51
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int ray_hit(amrex::Real x0, amrex::Real y0, amrex::Real z0, amrex::Real sx, amrex::Real sy, amrex::Real sz, const RayMap &m)
Definition: ERF_IBSEBSolar.H:371
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void hemisphere_direction(int dir, int nsign, int ia, int ie, int n_az, int n_el, amrex::Real &sx, amrex::Real &sy, amrex::Real &sz)
Definition: ERF_IBSEBSolar.H:437
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real solar_zenith(amrex::Real latitude_deg, amrex::Real decl, amrex::Real hour_angle)
Definition: ERF_IBSEBSolar.H:116
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real clear_sky_dni(amrex::Real cos_zenith, amrex::Real S0, amrex::Real tau, amrex::Real distance_factor)
Definition: ERF_IBSEBSolar.H:179
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real orbital_hour_angle(double calday, amrex::Real longitude_rad)
Definition: ERF_IBSEBSolar.H:105
amrex::Real hemisphere_min_sz(int n_az, int n_el)
Definition: ERF_IBSEBSolar.H:281
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real equation_of_time(amrex::Real day_of_year)
Definition: ERF_IBSEBSolar.H:73
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real earth_sun_distance_factor(amrex::Real day_of_year)
Definition: ERF_IBSEBSolar.H:155
RayHit
What a ray from a face ends on.
Definition: ERF_IBSEBSolar.H:351
@ RAY_GROUND
Definition: ERF_IBSEBSolar.H:351
@ RAY_SKY
Definition: ERF_IBSEBSolar.H:351
@ RAY_BUILDING
Definition: ERF_IBSEBSolar.H:351
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void sun_vector(amrex::Real zenith, amrex::Real azimuth, amrex::Real &sx, amrex::Real &sy, amrex::Real &sz)
Definition: ERF_IBSEBSolar.H:164
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool ray_blocked(amrex::Real x0, amrex::Real y0, amrex::Real z0, amrex::Real sx, amrex::Real sy, amrex::Real sz, const RayMap &m)
Definition: ERF_IBSEBSolar.H:309
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real solar_azimuth(amrex::Real latitude_deg, amrex::Real decl, amrex::Real hour_angle, amrex::Real zenith)
Definition: ERF_IBSEBSolar.H:131
int ray_halo_cells(amrex::Real height, amrex::Real dx, amrex::Real sz_min)
Definition: ERF_IBSEBSolar.H:262
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real day_of_year_at(amrex::Real day0, amrex::Real t_utc_s)
Definition: ERF_IBSEBSolar.H:55
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real solar_declination(amrex::Real day_of_year)
Definition: ERF_IBSEBSolar.H:62
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real spencer_day_angle(amrex::Real day_of_year)
Definition: ERF_IBSEBSolar.H:44
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real solar_hour_angle(amrex::Real time_utc_s, amrex::Real longitude_deg, amrex::Real day_of_year)
Definition: ERF_IBSEBSolar.H:87
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real clear_sky_diffuse_h(amrex::Real cos_zenith, amrex::Real S0, amrex::Real tau, amrex::Real distance_factor, amrex::Real k_d)
Definition: ERF_IBSEBSolar.H:192
real(c_double), parameter t0
Definition: ERF_module_model_constants.F90:39
real(c_double), private ci
Definition: ERF_module_mp_morr_two_moment.F90:203
Definition: ERF_IBSEBSolar.H:219
amrex::Real x_lo
Definition: ERF_IBSEBSolar.H:224
amrex::Array4< const int > top
Column tops over the patch (any k index; use top.begin[2])
Definition: ERF_IBSEBSolar.H:220
int ilo
Definition: ERF_IBSEBSolar.H:221
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real column_top(int ci, int cj) const noexcept
Definition: ERF_IBSEBSolar.H:247
amrex::Real y_lo
Physical position of the domain's low corner [m].
Definition: ERF_IBSEBSolar.H:224
amrex::Real z_max
Tallest column the map holds [m]; a ray above it meets nothing.
Definition: ERF_IBSEBSolar.H:227
bool wrap_x
Definition: ERF_IBSEBSolar.H:223
int ny
Columns of the domain in x and y.
Definition: ERF_IBSEBSolar.H:222
amrex::Real dx
Definition: ERF_IBSEBSolar.H:225
amrex::Real z_ground
Ground height [m].
Definition: ERF_IBSEBSolar.H:226
bool wrap_y
The patch spans the periodic domain in x / y.
Definition: ERF_IBSEBSolar.H:223
int max_steps
Columns a ray at the map's floor elevation crosses before it clears z_max (the halo's reach in x plus...
Definition: ERF_IBSEBSolar.H:228
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool locate(int &ci, int &cj) const noexcept
Definition: ERF_IBSEBSolar.H:232
amrex::Real dy
Definition: ERF_IBSEBSolar.H:225
amrex::Real dz
Cell sizes [m].
Definition: ERF_IBSEBSolar.H:225
int jlo
Low corner of the domain, in cells.
Definition: ERF_IBSEBSolar.H:221
int nx
Definition: ERF_IBSEBSolar.H:222