REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_bulk_flux.cpp
Go to the documentation of this file.
1#include <REMORA.H>
2
3using namespace amrex;
4
5/**
6 * @param[in ] lev level to operate on
7 * @param[in ] mf_cons scalar data: temperature, salinity, passsive scalar, etc
8 * @param[in ] mf_uwind u-direction wind dvelocity
9 * @param[in ] mf_vwind v-direction wind dvelocity
10 * @param[in ] mf_Tair air temperature [°C]
11 * @param[in ] mf_qair specific humidity [kg/kg]
12 * @param[in ] mf_Pair air pressure [mb]
13 * @param[in ] mf_srflx shortwave radiation flux [W/m²]
14 * @param[in ] mf_longwave_down external longwave radiation flux [W/m²]
15 * @param[inout] mf_evap evaporation rate
16 * @param[ out] mf_sustr u-direction surface momentum stress
17 * @param[ out] mf_svstr v-direction surface momentum stress
18 * @param[ out] mf_stflux surface scalar flux (temperature, salinity)
19 * @param[ out] mf_lrflx longwave radiation flux
20 * @param[inout] mf_lhflx latent heat flux
21 * @param[inout] mf_shflx sensible heat flux
22 * @param[in ] N number of vertical levels
23 */
24void
25REMORA::bulk_fluxes (int lev, MultiFab* mf_cons, MultiFab* mf_uwind, MultiFab* mf_vwind,
26 MultiFab* mf_Tair, MultiFab* mf_qair, MultiFab* mf_Pair,
27 MultiFab* mf_srflx,
28 MultiFab* mf_longwave_down,
29 MultiFab* mf_evap, MultiFab* mf_sustr, MultiFab* mf_svstr,
30 MultiFab* mf_stflux, MultiFab* mf_lrflx, MultiFab* mf_lhflx,
31 MultiFab* mf_shflx,
32 const int N)
33{
34 BL_PROFILE("REMORA::bulk_fluxes()");
35 const int IterMax = 3;
36 // The COARE version of the Charnock parameter and the scalar roughness lengths, the
37 // only choices myROMS's bulk_flux.F leaves to COARE_30
39 const BoxArray& ba = mf_cons->boxArray();
40 const DistributionMapping& dm = mf_cons->DistributionMap();
41 MultiFab mf_Taux(ba, dm, 1, IntVect(NGROW,NGROW,0));
42 MultiFab mf_Tauy(ba, dm, 1, IntVect(NGROW,NGROW,0));
43
44 // temps: Taux, Tauy,
45 for ( MFIter mfi(*mf_cons, TilingIfNotGPU()); mfi.isValid(); ++mfi) {
46 Array4<Real const> const& uwind = mf_uwind->const_array(mfi);
47 Array4<Real const> const& vwind = mf_vwind->const_array(mfi);
48 Array4<Real const> const& Tair_arr = mf_Tair->const_array(mfi);
49 Array4<Real const> const& qair_arr = mf_qair->const_array(mfi);
50 Array4<Real const> const& Pair_arr = mf_Pair->const_array(mfi);
51 Array4<Real const> const& srflx_arr = mf_srflx->const_array(mfi);
53 if (mf_longwave_down != nullptr) {
55 }
56 Array4<Real const> const& cons = mf_cons->const_array(mfi);
57 Array4<Real> const& sustr = mf_sustr->array(mfi);
58 Array4<Real> const& svstr = mf_svstr->array(mfi);
59 Array4<Real> const& stflux = mf_stflux->array(mfi);
60 Array4<Real> const& lrflx = mf_lrflx->array(mfi);
61 Array4<Real> const& lhflx = mf_lhflx->array(mfi);
62 Array4<Real> const& shflx = mf_shflx->array(mfi);
63 Array4<Real> const& evap = mf_evap->array(mfi);
64 Array4<Real> const& Taux = mf_Taux.array(mfi);
65 Array4<Real> const& Tauy = mf_Tauy.array(mfi);
66
67 Array4<const Real> const& mskr = vec_mskr[lev]->const_array(mfi);
68 Array4<const Real> const& msku = vec_msku[lev]->const_array(mfi);
69 Array4<const Real> const& mskv = vec_mskv[lev]->const_array(mfi);
70 Array4<const Real> const& rain = vec_rain[lev]->const_array(mfi);
71 Array4<const Real> const& EminusP = vec_EminusP[lev]->const_array(mfi);
72 Array4<const Real> const& cloud_arr = vec_cloud[lev]->const_array(mfi);
73
74 Real Hscale = solverChoice.rho0 * Cp;
75 Real Hscale2 = one / (solverChoice.rho0 * Cp);
76 Real blk_ZQ = solverChoice.blk_ZQ;
77 Real blk_ZT = solverChoice.blk_ZT;
78 Real blk_ZW = solverChoice.blk_ZW;
79 Real l_g = solverChoice.g;
80
82 bool longwave_is_net = solverChoice.longwave_is_net;
83 bool have_external_longwave = (mf_longwave_down != nullptr);
86
87 Real eps = Real(1e-20);
88
89 Box bx = mfi.tilebox();
90 Box ubx = mfi.grownnodaltilebox(0,IntVect(NGROW-1,NGROW-1,0));
91 Box vbx = mfi.grownnodaltilebox(1,IntVect(NGROW-1,NGROW-1,0));
92 Box gbx1 = bx; gbx1.grow(IntVect(NGROW,NGROW,0));
93
94 ParallelFor(makeSlab(gbx1,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int ) {
95 // Get spatially-varying atmospheric forcing from input arrays
96 Real PairM = Pair_arr(i,j,0); // Air pressure [mb]
97 Real TairC = Tair_arr(i,j,0); // Air temperature [°C]
98 Real TairK = TairC + Real(273.16); // Air temperature [K]
99 Real Hair = qair_arr(i,j,0); // Specific humidity [kg/kg] or RH [fraction]
100 Real RH = Hair;
101 Real srflux = srflx_arr(i,j,0); // Shortwave radiation flux [W/m²]
102 Real cloud = cloud_arr(i,j,0); // Cloud cover fraction [0-1]
103
104 // Input bulk parametrization fields
105 Real wind_mag = std::sqrt(uwind(i,j,0)*uwind(i,j,0) + vwind(i,j,0) * vwind(i,j,0));
106 Real TseaK = cons(i,j,N,Temp_comp) + Real(273.16);
107
108 // Initialize
109 Real delTc = zero;
110 Real delQc = zero;
111 Real cff = zero;
112
113 Real LHeat = lhflx(i,j,0) * Hscale;
114 Real SHeat = shflx(i,j,0) * Hscale;
115 Real Taur = zero;
116 Taux(i,j,0) = zero;
117 Tauy(i,j,0) = zero;
118 Real LRad;
119
120 /*-----------------------------------------------------------------------
121 Compute outward or net longwave radiation (W/m2), LRad.
122 -----------------------------------------------------------------------
123 If external longwave radiation is net, use it directly. If it is
124 downward, compute net longwave radiation as Ldown - Lemit, where
125 Lemit is computed from the model SST and an emissivity. Otherwise,
126 use Berliand (1952) formula to calculate net longwave radiation.
127 The equation for saturation vapor pressure is from Gill (Atmosphere-
128 Ocean Dynamics, pp 606). Here the coefficient in the cloud term
129 is assumed constant, but it is a function of latitude varying from
130 1.0 at poles to 0.5 at the Equator).
131
132 */
133 if (have_external_longwave && longwave_is_net) {
134 // External forcing provides net longwave directly (W/m2).
137 Real Ldown = longwave_down_arr(i,j,0);
138 Real Lemit = emmiss * StefBo * std::pow(TseaK,4);
139 LRad = Ldown - Lemit;
140 } else {
141 // Original Berliand parameterization
142 cff=(Real(0.7859)+Real(0.03477)*TairC)/(one+Real(0.00412)*TairC);
143 Real e_sat=std::pow(Real(10.0),cff);
144 Real vap_p=e_sat*RH;
145 Real cff2=TairK*TairK*TairK;
146 Real cff1=cff2*TairK;
147
149 (cff1*(Real(0.39)-Real(0.05)*std::sqrt(vap_p))*
150 (one-Real(0.6823)*cloud*cloud)+
151 cff2*Real(4.0)*(TseaK-TairK));
152 }
153 LRad *= mskr(i,j,0);
154 /*
155 -----------------------------------------------------------------------
156 Compute specific humidities (kg/kg).
157
158 note that Qair is the saturation specific humidity at Tair
159 Q is the actual specific humidity
160 Qsea is the saturation specific humidity at Tsea
161
162 Saturation vapor pressure in mb is first computed and then
163 converted to specific humidity in kg/kg
164
165 The saturation vapor pressure is computed from Teten formula
166 using the approach of Buck (1981):
167
168 Esat(mb) = (Real(1.0007)+3.46E-Real(6)*PairM(mb))*Real(6.1121)*
169 EXP(Real(17.502)*TairC(C)/(Real(240.97)+TairC(C)))
170
171 The ambient vapor is found from the definition of the
172 Relative humidity:
173
174 RH = W/Ws*100 ~ E/Esat*100 E = RH/100*Esat if RH is in %
175 E = RH*Esat if RH fractional
176
177 The specific humidity is then found using the relationship:
178
179 Q = 0.622 E/(P + (0.622-1)e)
180
181 Q(kg/kg) = Real(0.62197)*(E(mb)/(PairM(mb)Real(-0.378)*E(mb)))
182
183 -----------------------------------------------------------------------
184 */
185
186 // Compute air saturation vapor pressure (mb), using Teten formula.
187
188 Real cff_saturation_air=(Real(1.0007)+Real(3.46e-6)*PairM)*Real(6.1121)*
189 std::exp(Real(17.502)*TairC/(Real(240.97)+TairC));
190
191 // Compute specific humidity at Saturation, Qair (kg/kg).
192
193 Real Qair = Real(0.62197)*(cff_saturation_air/(PairM-Real(0.378)*cff_saturation_air+eps));
194
195 // Compute specific humidity, Q (kg/kg).
196 Real Q;
197 if (RH < 2.0) {
198 Real cff_Q = cff_saturation_air*RH; //Vapor pressure (mb)
199 Q=Real(0.62197)*(cff_Q/(PairM-Real(0.378)*cff_Q+eps)); //Spec hum (kg/kg)
200 } else { // RH input was actually specific humidity in g/kg
201 Q=RH/Real(1000.0); //!Spec Hum (kg/kg)
202 }
203
204 // Compute water saturation vapor pressure (mb), using Teten formula.
205
206 Real cff_saturation_water=(Real(1.0007)+Real(3.46e-6)*PairM)*Real(6.1121)*
207 std::exp(Real(17.502)*cons(i,j,N,Temp_comp)/(Real(240.97)+cons(i,j,N,Temp_comp)));
208
209 // Compute water saturation vapor pressure (mb), using Teten formula.
210 // Vapor Pressure reduced for salinity (Kraus and Businger, 1994, pp42).
211 Real cff_vp=cff_saturation_water*Real(0.98);
212
213 // Compute Qsea (kg/kg) from vapor pressure. As in ROMS, with no small-value
214 // guard here, unlike Q and Qair
215
216 Real Qsea=Real(0.62197)*(cff_vp/(PairM-Real(0.378)*cff_vp));
217 //
218 // -----------------------------------------------------------------------
219 // Compute Monin-Obukhov similarity parameters for wind (Wstar),
220 // heat (Tstar), and moisture (Qstar), Liu et al. (1979).
221 // -----------------------------------------------------------------------
222 //
223 // Moist air density (kg/m3).
224
225 Real rhoAir=PairM*Real(100.0)/(blk_Rgas*TairK*(one+Real(0.61)*Q));
226
227 // Kinematic viscosity of dry air (m2/s), Andreas (1989).
228
229 Real VisAir=Real(1.326e-5)*(one+TairC*(Real(6.542e-3)+TairC*
230 (Real(8.301e-6)-Real(4.84e-9)*TairC)));
231
232
233 // Compute latent heat of vaporization (J/kg) at sea surface, Hlv.
234
235 Real Hlv = (Real(2.501)-Real(0.00237)*cons(i,j,N,Temp_comp))*Real(1.0e6);
236
237 // Assume that wind is measured relative to sea surface and include
238 // gustiness.
239
240 Real Wgus=Real(0.5);
241 Real delW=std::sqrt(wind_mag*wind_mag+Wgus*Wgus);
242 Real delQ=Qsea-Q;
243 Real delT=cons(i,j,N,Temp_comp)-TairC;
244
245 // Neutral coefficients.
246 Real ZoW=Real(0.0001);
247 Real u10=delW*std::log(Real(10.0)/ZoW)/std::log(blk_ZW/ZoW);
248 Real Wstar=Real(0.035) * u10;
249 Real Zo10=Real(0.011)*Wstar*Wstar/l_g+Real(0.11)*VisAir/Wstar;
250 Real Cd10 =(vonKar/std::log(Real(10.0)/Zo10));
251 Cd10 = Cd10 * Cd10;
252 Real Ch10 =Real(0.00115);
253 Real Ct10 = Ch10/std::sqrt(Cd10);
254 Real ZoT10=Real(10.0)/std::exp(vonKar/Ct10);
255 Real Cd=(vonKar/std::log(blk_ZW/Zo10));
256 Cd = Cd * Cd;
257
258 // Compute Richardson number.
259 Real Ct=vonKar/std::log(blk_ZT/ZoT10); // T transfer coefficient
260 Real CC=vonKar*Ct/Cd;
261
262 Real Ribcu = -blk_ZW/(blk_Zabl*Real(0.004)*blk_beta*blk_beta*blk_beta);
263 Real Ri = -l_g*blk_ZW*((delT-delTc)+Real(0.61)*TairK*delQ)/
264 (TairK*delW*delW+eps);
265 Real Zetu;
266 if (Ri < zero) {
267 Zetu=CC*Ri/(one+Ri/Ribcu); // Unstable
268 } else {
269 Zetu=CC*Ri/(one+Real(3.0)*Ri/CC); // Stable
270 }
271 Real L10 = blk_ZW/Zetu;
272
273 // First guesses for Monon-Obukhov similarity scales.
274 Wstar=delW*vonKar/(std::log(blk_ZW/Zo10)-
275 bulk_psiu(blk_ZW/L10));
276 Real Tstar=-(delT-delTc)*vonKar/(std::log(blk_ZT/ZoT10)-
277 bulk_psit(blk_ZT/L10));
278 Real Qstar=-(delQ-delQc)*vonKar/(std::log(blk_ZQ/ZoT10)-
279 bulk_psit(blk_ZQ/L10));
280
281 // Modify Charnock for high wind speeds. The 0.125 factor below is for
282 // 1.0/(18.0-10.0).
283
284 Real charn;
285 if (coare30) {
286 // Momentum roughness length based on COARE 3.0 (Fairall et al. 2003, JPO)
287 if (delW > Real(18.0)) {
288 charn=Real(0.018);
289 } else if ((Real(10.0) < delW) and (delW <= Real(18.0))) {
290 charn=Real(0.011)+Real(0.125)*(Real(0.018)-Real(0.011))*(delW-Real(10.0));
291 } else {
292 charn=Real(0.011);
293 }
294 } else {
295 // Momentum roughness length based on COARE 3.5 (Edson et al. 2013, JPO)
296 charn=std::min(Real(0.028),Real(-0.005)+Real(0.0017)*delW);
297 }
298
299 // Iterate until convergence. It usually converges within 3 iterations.
300 for (int it=0; it<IterMax; it++) {
301 ZoW=charn*Wstar*Wstar/l_g+Real(0.11)*VisAir/(Wstar+eps);
302 Real Rr=ZoW*Wstar/VisAir;
303 // Compute Monin-Obukhov stability parameter, Z/L.
304 // Moisture and thermal roughness lengths: COARE 3.0, or COARE 3.5 adjusted
305 // to reflect COARE 3.0 fluxes (J. Edson, pers. comm., 11/2023)
306 Real ZoQ = coare30 ? std::min(Real(1.15e-4),Real(5.5e-5)/std::pow(Rr,Real(0.6)))
307 : std::min(Real(1.6e-4),Real(5.8e-5)/std::pow(Rr,Real(0.72)));
308 Real ZoT=ZoQ;
309 Real ZoL=vonKar*l_g*blk_ZW*(Tstar*(one+Real(0.61)*Q)+
310 Real(0.61)*TairK*Qstar)/
311 (TairK*Wstar*Wstar*(one+Real(0.61)*Q)+eps);
312 Real L=blk_ZW/(ZoL+eps);
313
314 // Evaluate stability functions at Z/L.
315 Real Wpsi=bulk_psiu(ZoL);
316 Real Tpsi=bulk_psit(blk_ZT/L);
317 Real Qpsi=bulk_psit(blk_ZQ/L);
318
319 // Compute wind scaling parameters, Wstar.
320 Wstar=std::max(eps,delW*vonKar/(std::log(blk_ZW/ZoW)-Wpsi));
321 Tstar=-(delT-delTc)*vonKar/(std::log(blk_ZT/ZoT)-Tpsi);
322 Qstar=-(delQ-delQc)*vonKar/(std::log(blk_ZQ/ZoQ)-Qpsi);
323
324 // Compute gustiness in wind speed.
325 Real Bf = -l_g/(TairK+Real(0.61)*Qstar)*Wstar*(Tstar+Real(0.61)*TairK*Qstar);
326 if (Bf>zero) {
327 Wgus=blk_beta*std::pow(Bf*blk_Zabl,one/Real(3.0));
328 } else {
329 Wgus=Real(0.2);
330 }
331 delW=std::sqrt(wind_mag*wind_mag+Wgus*Wgus);
332 }
333
334 // Compute turbulent sensible heat flux (W/m2), Hs.
336
337 // Compute sensible heat flux (W/m2) due to rainfall (kg/m2/s), Hsr.
338 Real diffw=Real(2.11e-5)*std::pow(TairK/Real(273.16),Real(1.94));
339 Real diffh=Real(0.02411)*(one+TairC*
340 (Real(3.309e-3)-Real(1.44e-6)*TairC))/
342 cff=Qair*Hlv/(blk_Rgas*TairK*TairK);
343 Real wet_bulb=one/(one+Real(0.622)*(cff*Hlv*diffw)/
344 (blk_Cpa*diffh));
345 // Negative rain is snow, so the rain terms take its magnitude
346 const Real rain_mag = std::abs(rain(i,j,0));
348 ((cons(i,j,N,Temp_comp)-TairC)+(Qsea-Q)*Hlv/blk_Cpa);
349 SHeat=(Hs+Hsr) * mskr(i,j,0);
350
351 // Compute turbulent latent heat flux (W/m2), Hl.
352
353 Real Hl=-Hlv*rhoAir*Wstar*Qstar;
354
355 // Compute Webb correction (Webb effect) to latent heat flux, Hlw.
356 Real upvel=Real(-1.61)*Wstar*Qstar-
357 (one+Real(1.61)*Q)*Wstar*Tstar/TairK;
358 Real Hlw=rhoAir*Hlv*upvel*Q;
359 LHeat=(Hl+Hlw) * mskr(i,j,0);
360
361 // Compute momentum flux (N/m2) due to rainfall (kg/m2/s).
362 Taur=Real(0.85)*rain_mag*wind_mag;
363
364 // Sum of stresses expressed as friction velocities, normalized by the wind
365 // speed without gustiness (Wilkin and Pareja-Roman, 02/2024). ROMS writes
366 // rhoAir*(Wstar^2+Taur/rhoAir); this form does not divide by rhoAir, which
367 // is 0 where the air pressure is (land fill values)
369 Taux(i,j,0)=cff*uwind(i,j,0) * mskr(i,j,0);
370 Tauy(i,j,0)=cff*vwind(i,j,0) * mskr(i,j,0);
371
372 //=======================================================================
373 // Compute surface net heat flux and surface wind stress.
374 //=======================================================================
375 //
376 // Compute kinematic, surface, net heat flux (degC m/s). Notice that
377 // the signs of latent and sensible fluxes are reversed because fluxes
378 // calculated from the bulk formulations above are positive out of the
379 // ocean.
380 //
381 // For EMINUSP option, EVAP = LHeat (W/m2) / Hlv (J/kg) = kg/m2/s
382 // PREC = rain = kg/m2/s
383 //
384 // To convert these rates to m/s divide by freshwater density, rhow.
385 //
386 // Note that when the air is undersaturated in water vapor (Q < Qsea)
387 // the model will evaporate and LHeat > 0:
388 //
389 // LHeat positive out of the ocean
390 // evap positive out of the ocean
391 //
392 // Note that if evaporating, the salt flux is positive
393 // and if raining, the salt flux is negative
394 //
395 // Note that stflux(:,:,isalt) is the E-P flux. The fresh water flux
396 // is positive out of the ocean and the salt flux is positive into the
397 // ocean. It is multiplied by surface salinity when computing state
398 // variable stflx(:,:,isalt) in "set_vbc.F".
399
400// Real one_over_rhow=one/rhow;
401 lrflx(i,j,0) = LRad*Hscale2;
402 lhflx(i,j,0) = -LHeat*Hscale2;
403 shflx(i,j,0) = -SHeat*Hscale2;
404 // Note: srflx from NetCDF is in W/m^2, convert to degC m/s by multiplying by Hscale2
405 stflux(i,j,0,Temp_comp)=(srflux*Hscale2 + lrflx(i,j,0) + lhflx(i,j,0) + shflx(i,j,0)) * mskr(i,j,0);
406 evap(i,j,0) = LHeat/(Hlv+eps) * mskr(i,j,0);
408 // Use prescribed E-P directly
409 stflux(i,j,0,Salt_comp) = mskr(i,j,0) * EminusP(i,j,0);
410 } else {
411 stflux(i,j,0,Salt_comp) = (one/rhow)*(evap(i,j,0)-rain(i,j,0)) * mskr(i,j,0);
412 }
413 });
414
415 Real cff_rho = Real(0.5) / solverChoice.rho0;
416 ParallelFor(makeSlab(ubx,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int ) {
417 sustr(i,j,0) = cff_rho*(Taux(i-1,j,0) + Taux(i,j,0)) * msku(i,j,0);
418 });
419 ParallelFor(makeSlab(vbx,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int ) {
420 svstr(i,j,0) = cff_rho*(Tauy(i,j-1,0) + Tauy(i,j,0)) * mskv(i,j,0);
421 });
422 }
423
424}
constexpr amrex::Real one
constexpr amrex::Real zero
constexpr amrex::Real blk_Zabl
constexpr amrex::Real vonKar
constexpr amrex::Real rhow
constexpr amrex::Real blk_Rgas
constexpr amrex::Real blk_beta
constexpr amrex::Real emmiss
constexpr amrex::Real Cp
constexpr amrex::Real StefBo
constexpr amrex::Real blk_Cpa
constexpr amrex::Real blk_Cpw
#define NGROW
#define Temp_comp
#define Salt_comp
mf_h setVal(geomdata.ProbHi(2))
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_EminusP
evaporation minus precipitation [kg/m^2/s], defined at rho-points
Definition REMORA.H:521
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskr
land/sea mask at cell centers (2D)
Definition REMORA.H:584
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_rain
precipitation rate [kg/m^2/s]
Definition REMORA.H:515
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_msku
land/sea mask at x-faces (2D)
Definition REMORA.H:586
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskv
land/sea mask at y-faces (2D)
Definition REMORA.H:588
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real bulk_psiu(amrex::Real ZoL)
Evaluate stability function psi for wind speed.
Definition REMORA.H:2232
static SolverChoice solverChoice
Container for algorithmic choices.
Definition REMORA.H:2017
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_cloud
cloud cover fraction [0-1], defined at rho-points
Definition REMORA.H:519
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real bulk_psit(amrex::Real ZoL)
Evaluate stability function psi for moisture and heat.
Definition REMORA.H:2264
void bulk_fluxes(int lev, amrex::MultiFab *mf_cons, amrex::MultiFab *mf_uwind, amrex::MultiFab *mf_vwind, amrex::MultiFab *mf_Tair, amrex::MultiFab *mf_qair, amrex::MultiFab *mf_Pair, amrex::MultiFab *mf_srflx, amrex::MultiFab *mf_longwave_down, amrex::MultiFab *mf_evap, amrex::MultiFab *mf_sustr, amrex::MultiFab *mf_svstr, amrex::MultiFab *mf_stflux, amrex::MultiFab *mf_lrflx, amrex::MultiFab *mf_lhflx, amrex::MultiFab *mf_shflx, const int N)
Calculate bulk temperature, salinity, wind fluxes.
@ EminusP
evaporation minus precipitation [m/s]
BulkFluxScheme bulk_flux_scheme
std::array< BulkForcingType, BulkFlux::NumTypes > bulk_flux_type