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