def calc_detrainment_entrainment( zi: gtscript.Field[DTYPE_FLOAT], xlamue: gtscript.Field[DTYPE_FLOAT], xlamud: gtscript.Field[DTYPE_FLOAT], ecko2: gtscript.Field[DTYPE_FLOAT], ctro2: gtscript.Field[DTYPE_FLOAT], eta: gtscript.Field[DTYPE_FLOAT], xmbp: gtscript.Field[DTYPE_FLOAT], kb: gtscript.Field[int], ktcon: gtscript.Field[int], cnvflg: gtscript.Field[int], index_k: gtscript.Field[int], dellae2: gtscript.Field[DTYPE_FLOAT]): with computation(PARALLEL), interval(1, -1): if cnvflg and (index_k < ktcon): dz = zi[0, 0, 0] - zi[0, 0, -1] aup = 1.0 if index_k > kb else 0.0 dv1q = 0.5 * (ecko2[0, 0, 0] + ecko2[0, 0, -1]) dv2q = 0.5 * (ctro2[0, 0, 0] + ctro2[0, 0, -1]) tem = 0.5 * (xlamue[0, 0, 0] + xlamue[0, 0, -1]) tem1 = 0.5 * (xlamud[0, 0, 0] + xlamud[0, 0, 0]) dellae2 = dellae2 + ( aup * tem1 * eta[0, 0, -1] * dv1q # detrainment from updraft - aup * tem * eta[0, 0, -1] * dv2q # entrainment into up and downdraft ) * dz * xmbp if index_k == kb: dellae2 = dellae2 - eta * ctro2 * xmbp with computation(FORWARD), interval(0, 1): if cnvflg and (kb == 1): dellae2 = dellae2 - eta * ctro2 * xmbp
def set_work_arrays( qtr: gtscript.Field[DTYPE_FLOAT], xmb: gtscript.Field[DTYPE_FLOAT], delp: gtscript.Field[DTYPE_FLOAT], kmax: gtscript.Field[int], kb: gtscript.Field[int], cnvflg: gtscript.Field[int], index_k: gtscript.Field[int], qaero: gtscript.Field[DTYPE_FLOAT], xmbp: gtscript.Field[DTYPE_FLOAT], ctro2: gtscript.Field[DTYPE_FLOAT], ecko2: gtscript.Field[DTYPE_FLOAT]): with computation(PARALLEL), interval(...): qaero = set_qaero(qtr, kmax, index_k) xmbp = set_xmbp(xmb, delp) with computation(PARALLEL), interval(...): ctro2 = set_ctro2(qaero, kmax, index_k) ecko2 = set_ecko2(ctro2, cnvflg, kb, index_k)
def calc_ecko2_chem_c_dellae2( zi: gtscript.Field[DTYPE_FLOAT], xlamue: gtscript.Field[DTYPE_FLOAT], xlamud: gtscript.Field[DTYPE_FLOAT], ctro2: gtscript.Field[DTYPE_FLOAT], c0t: gtscript.Field[DTYPE_FLOAT], eta: gtscript.Field[DTYPE_FLOAT], xmbp: gtscript.Field[DTYPE_FLOAT], kb: gtscript.Field[int], ktcon: gtscript.Field[int], cnvflg: gtscript.Field[int], index_k: gtscript.Field[int], ecko2: gtscript.Field[DTYPE_FLOAT], chem_c: gtscript.Field[DTYPE_FLOAT], # chem_pw: gtscript.Field[DTYPE_FLOAT], dellae2: gtscript.Field[DTYPE_FLOAT], *, fscav: float): with computation(FORWARD), interval(1, -1): if cnvflg and (index_k > kb) and (index_k < ktcon): dz = zi[0, 0, 0] - zi[0, 0, -1] tem = 0.5 * (xlamue[0, 0, 0] + xlamue[0, 0, -1]) * dz tem1 = 0.25 * (xlamud[0, 0, 0] + xlamud[0, 0, 0]) * dz factor = 1.0 + tem - tem1 # if conserved (not scavenging) then ecko2 = ((1.0 - tem1) * ecko2[0, 0, -1] + 0.5 * tem * (ctro2[0, 0, 0] + ctro2[0, 0, -1])) / factor # how much will be scavenged # this choice was used in GF, and is also described in a # successful implementation into CESM in GRL (Yu et al. 2019), # it uses dimesnsionless scavenging coefficients (fscav), # but includes henry coeffs with gas phase chemistry # fraction fscav is going into liquid chem_c = escav * fscav * ecko2 # of that part is going into rain out (chem_pw) tem2 = chem_c / (1.0 + c0t * dz) # chem_pw = c0t * dz * tem2 * eta # etah ecko2 = tem2 + ecko2 - chem_c with computation(PARALLEL), interval(0, -1): if index_k >= ktcon: ecko2 = ctro2 if cnvflg and (index_k == ktcon): # for the subsidence term already is considered dellae2 = eta[0, 0, -1] * ecko2[0, 0, -1] * xmbp
def diffusion_defs(in_field: gtscript.Field[float], out_field: gtscript.Field[float], *, alpha: float): from __externals__ import laplacian from __gtscript__ import PARALLEL, computation, interval with computation(PARALLEL), interval(...): lap1 = laplacian(in_field) lap2 = laplacian(lap1) out_field = in_field - alpha * lap2
def calc_final(dellae2: gtscript.Field[DTYPE_FLOAT], kmax: gtscript.Field[int], ktcon: gtscript.Field[int], cnvflg: gtscript.Field[int], index_k: gtscript.Field[int], qaero: gtscript.Field[DTYPE_FLOAT], *, delt: float): # compute final aerosol concentrations with computation(PARALLEL), interval(...): if cnvflg and (index_k <= min(kmax, ktcon)): qaero = qaero + dellae2 * delt if qaero < 0.0: qaero = qamin
def diffusion_defs(in_field: gtscript.Field[float], out_field: gtscript.Field[float], *, alpha: float): from __gtscript__ import PARALLEL, computation, interval with computation(PARALLEL), interval(...): lap1 = (-4.0 * in_field[0, 0, 0] + in_field[-1, 0, 0] + in_field[1, 0, 0] + in_field[0, -1, 0] + in_field[0, 1, 0]) lap2 = (-4.0 * lap1[0, 0, 0] + lap1[-1, 0, 0] + lap1[1, 0, 0] + lap1[0, -1, 0] + lap1[0, 1, 0]) out_field = in_field - alpha * lap2
def calc_dtime_max_arr(delp: gtscript.Field[DTYPE_FLOAT], ktcon: gtscript.Field[int], index_k: gtscript.Field[int], dtime_max_arr: gtscript.Field[DTYPE_FLOAT], *, delt: float): with computation(FORWARD): with interval(0, 1): dtime_max_arr = delt with interval(1, -1): if index_k - 1 < ktcon: dtime_max_arr = min(dtime_max_arr[0, 0, -1], 0.5 * delp[0, 0, -1]) else: dtime_max_arr = dtime_max_arr[0, 0, -1]
def calc_mass_flux(eta: gtscript.Field[DTYPE_FLOAT], xmb: gtscript.Field[DTYPE_FLOAT], qaero: gtscript.Field[DTYPE_FLOAT], delp: gtscript.Field[DTYPE_FLOAT], kb: gtscript.Field[int], ktcon: gtscript.Field[int], cnvflg: gtscript.Field[int], index_k: gtscript.Field[int], flx_lo: gtscript.Field[DTYPE_FLOAT], totlout: gtscript.Field[DTYPE_FLOAT], clipout: gtscript.Field[DTYPE_FLOAT], dellae2: gtscript.Field[DTYPE_FLOAT], *, dtime_max: float): with computation(PARALLEL), interval(1, -1): if cnvflg and (index_k - 1 < ktcon): tem = 0.0 if index_k - 1 < kb else eta[0, 0, -1] # low-order flux, upstream qaero_val = qaero[0, 0, 0] if tem > 0.0 else qaero[0, 0, -1] flx_lo = -xmb * tem * qaero_val # make sure low-ord fluxes don't violate positive-definiteness with computation(PARALLEL), interval(0, -1): if cnvflg and (index_k <= ktcon): # time step / grid spacing dtovdz = g * dtime_max / abs(delp) # total flux out totlout = max(0.0, flx_lo[0, 0, 1]) - min(0.0, flx_lo[0, 0, 0]) clipout = min(1.0, qaero / max(epsil, totlout) / (1.0001 * dtovdz)) # recompute upstream mass fluxes with computation(PARALLEL), interval(1, -1): if cnvflg and index_k - 1 <= ktcon: tem = 0.0 if index_k - 1 < kb else eta[0, 0, -1] clipout_val = clipout[0, 0, 0] if tem > 0.0 else clipout[0, 0, -1] flx_lo = flx_lo * clipout_val # a positive-definite low-order (diffusive) solution for the subsidnce fluxes with computation(PARALLEL), interval(0, -1): if cnvflg and index_k <= ktcon: # time step / grid spacing dtovdz = g * dtime_max / abs(delp) dellae2 = dellae2 - (flx_lo[0, 0, 1] - flx_lo[0, 0, 0]) * dtovdz / dtime_max
def diffusion_defs( in_field: gtscript.Field[float], out_field: gtscript.Field[float], *, a1: float, a2: float, a8: float, a20: float, ): from __gtscript__ import PARALLEL, computation, interval with computation(PARALLEL), interval(...): out_field = (a1 * in_field[0, -2, 0] + a2 * in_field[-1, -1, 0] + a8 * in_field[0, -1, 0] + a2 * in_field[1, -1, 0] + a1 * in_field[-2, 0, 0] + a8 * in_field[-1, 0, 0] + a20 * in_field[0, 0, 0] + a8 * in_field[1, 0, 0] + a1 * in_field[2, 0, 0] + a2 * in_field[-1, 1, 0] + a8 * in_field[0, 1, 0] + a2 * in_field[1, 1, 0] + a1 * in_field[0, 2, 0])
def heat_gt4py_3D(u_now: gtscript.Field[np.float64], u_next: gtscript.Field[np.float64], *, alpha: np.float64, dt: np.float64, dx: np.float64, dy: np.float64, dz: np.float64): ''' Definiton for the stencil in gt4py u_now -- field at the time t, as gtscript Field u_next -- field at the time t+dt, as gtscript Field alpha -- thermal diffusivity dt -- time step dx, dy, dz -- spacing in each direction ''' from __externals__ import laplace_gt4py_3D from __gtscript__ import PARALLEL, computation, interval with computation(PARALLEL): with interval(1, -1): u_next = u_now + dt * alpha * laplace_gt4py_3D(u_now, dx, dy, dz)
def sfc_sice_defs(ps: DT_F, t1: DT_F, q1: DT_F, sfcemis: DT_F, dlwflx: DT_F, sfcnsw: DT_F, sfcdsw: DT_F, srflag: DT_F, cm: DT_F, ch: DT_F, prsl1: DT_F, prslki: DT_F, islimsk: DT_I, wind: DT_F, flag_iter: DT_I, hice: DT_F, fice: DT_F, tice: DT_F, weasd: DT_F, tskin: DT_F, tprcp: DT_F, stc0: DT_F, stc1: DT_F, ep: DT_F, snwdph: DT_F, qsurf: DT_F, cmm: DT_F, chh: DT_F, evap: DT_F, hflx: DT_F, gflux: DT_F, snowmt: DT_F, *, delt: float, cimin: float): """This file contains the GFS thermodynamics surface ice model. ===================================================================== description: usage: program history log: 2005 -- xingren wu created from original progtm and added two-layer ice model 200x -- sarah lu added flag_iter oct 2006 -- h. wei added cmm and chh to output 2007 -- x. wu modified for mom4 coupling (i.e. cpldice) (not used anymore) 2007 -- s. moorthi micellaneous changes may 2009 -- y.-t. hou modified to include surface emissivity effect on lw radiation. replaced the confusing slrad with sfc net sw sfcnsw (dn-up). reformatted the code and add program documentation block. sep 2009 -- s. moorthi removed rcl, changed pressure units and further optimized jan 2015 -- x. wu change "cimin = 0.15" for both uncoupled and coupled case jul 2020 -- ETH-students port to gt4py ==================== definition of variables ==================== inputs: size ps - real, surface pressure im t1 - real, surface layer mean temperature ( k ) im q1 - real, surface layer mean specific humidity im sfcemis - real, sfc lw emissivity ( fraction ) im dlwflx - real, total sky sfc downward lw flux ( w/m**2 ) im sfcnsw - real, total sky sfc netsw flx into ground(w/m**2) im sfcdsw - real, total sky sfc downward sw flux ( w/m**2 ) im srflag - real, snow/rain fraction for precipitation im cm - real, surface exchange coeff for momentum (m/s) im ch - real, surface exchange coeff heat & moisture(m/s) im prsl1 - real, surface layer mean pressure im prslki - real, im islimsk - integer, sea/land/ice mask (=0/1/2) im wind - real, im flag_iter- logical, im delt - real, time interval (second) 1 cimin - real, minimum ice fraction 1 input/outputs: hice - real, sea-ice thickness im fice - real, sea-ice concentration im tice - real, sea-ice surface temperature im weasd - real, water equivalent accumulated snow depth (mm)im tskin - real, ground surface skin temperature ( k ) im tprcp - real, total precipitation im stc0 - real, soil temp (k), 1. layer im stc1 - real, soil temp (k), 2nd layer im ep - real, potential evaporation im outputs: snwdph - real, water equivalent snow depth (mm) im qsurf - real, specific humidity at sfc im snowmt - real, snow melt (m) im gflux - real, soil heat flux (w/m**2) im cmm - real, surface exchange coeff for momentum(m/s) im chh - real, surface exchange coeff heat&moisture (m/s) im evap - real, evaperation from latent heat flux im hflx - real, sensible heat flux im ===================================================================== """ from __gtscript__ import PARALLEL, computation, interval with computation(PARALLEL), interval(...): FLOAT_EPS = 1.0e-8 # sfc_sice constants EPS = RD / RV EPSM1 = RD / RV - 1.0 RVRDM1 = RV / RD - 1.0 ELOCP = HVAP / CP HIMAX = 8.0 # maximum ice thickness allowed HIMIN = 0.1 # minimum ice thickness required HSMAX = 2.0 # maximum snow depth allowed TIMIN = 173.0 # minimum temperature allowed for snow/ice ALBFW = 0.06 # albedo for lead DSI = 1.0 / 0.33 # --- ... set flag for sea-ice flag = (islimsk == 2) and flag_iter if flag_iter and (islimsk < 2): hice = 0.0 fice = 0.0 if flag: if srflag > 0.0: ep = ep * (1.0 - srflag) weasd = weasd + 1.0e3 * tprcp * srflag tprcp = tprcp * (1.0 - srflag) # --- ... initialize variables. all units are supposedly m.k.s. unless specified # psurf is in pascals, wind is wind speed, theta1 is adiabatic surface # temp from level 1, rho is density, qs1 is sat. hum. at level1 and qss # is sat. hum. at surface # convert slrad to the civilized unit from langley minute-1 k-4 # dlwflx has been given a negative sign for downward longwave # sfcnsw is the net shortwave flux (direction: dn-up) q0 = max(q1, FLOAT_EPS) theta1 = t1 * prslki rho = prsl1 / (RD * t1 * (1.0 + RVRDM1 * q0)) qs1 = fpvs_fn(t1) qs1 = max(EPS * qs1 / (prsl1 + EPSM1 * qs1), FLOAT_EPS) q0 = min(qs1, q0) if fice < cimin: # print("warning: ice fraction is low:", fice) # fice = cimin tice = TGICE tskin = TGICE # print('fix ice fraction: reset it to:', fice) fice = max(fice, cimin) ffw = 1.0 - fice qssi = fpvs_fn(tice) qssw = fpvs_fn(TGICE) qssi = EPS * qssi / (ps + EPSM1 * qssi) qssw = EPS * qssw / (ps + EPSM1 * qssw) # --- ... snow depth in water equivalent is converted from mm to m unit snowd = weasd * 0.001 # --- ... when snow depth is less than 1 mm, a patchy snow is assumed and # soil is allowed to interact with the atmosphere. # we should eventually move to a linear combination of soil and # snow under the condition of patchy snow. # --- ... rcp = rho CP ch v cmm = cm * wind chh = rho * ch * wind rch = chh * CP # --- ... sensible and latent heat flux over open water & sea ice evapi = ELOCP * rch * (qssi - q0) evapw = ELOCP * rch * (qssw - q0) snetw = sfcdsw * (1.0 - ALBFW) snetw = min(3.0 * sfcnsw / (1.0 + 2.0 * ffw), snetw) sneti = (sfcnsw - ffw * snetw) / fice t12 = tice * tice t14 = t12 * t12 # --- ... hfi = net non-solar and upir heat flux @ ice surface hfi = -dlwflx + sfcemis * SBC * t14 + evapi + rch * (tice - theta1) hfd = (4.0 * sfcemis * SBC * tice * t12 + (1.0 + ELOCP * EPS * HVAP * qs1 / (RD * t12)) * rch) t12 = TGICE * TGICE t14 = t12 * t12 # --- ... hfw = net heat flux @ water surface (within ice) focn = 2.0 # heat flux from ocean - should be from ocn model snof = 0.0 # snowfall rate - snow accumulates in gbphys hice = max(min(hice, HIMAX), HIMIN) snowd = min(snowd, HSMAX) if snowd > 2.0 * hice: # print('warning: too much snow :', snowd[i]) snowd = hice + hice # print('fix: decrease snow depth to:', snowd[i]) # run the 3-layer ice model snowd, hice, stc0, stc1, tice, snof, snowmt, gflux = ice3lay( fice, hfi, hfd, sneti, focn, delt, snowd, hice, stc0, stc1, tice, snof, snowmt, gflux, ) if tice < TIMIN: # print('warning: snow/ice temperature is too low:', tice, ' i=', i) tice = TIMIN # print('fix snow/ice temperature: reset it to:', TIMIN) if stc0 < TIMIN: # print('warning: layer 1 ice temp is too low:', stsice[i, 0], ' i=', i) stc0 = TIMIN # print('fix layer 1 ice temp: reset it to:', TIMIN) if stc1 < TIMIN: # print('warning: layer 2 ice temp is too low:', stsice[i, 1], 'i=', i) stc1 = TIMIN # print('fix layer 2 ice temp: reset it to:', TIMIN) tskin = tice * fice + TGICE * ffw stc0 = min(stc0, T0C) stc1 = min(stc1, T0C) # --- ... calculate sensible heat flux (& evap over sea ice) hflxi = rch * (tice - theta1) hflxw = rch * (TGICE - theta1) hflx = fice * hflxi + ffw * hflxw evap = fice * evapi + ffw * evapw # --- ... the rest of the output qsurf = q1 + evap / (ELOCP * rch) # --- ... convert snow depth back to mm of water equivalent weasd = snowd * 1000.0 snwdph = weasd * DSI # snow depth in mm hflx = hflx / rho * 1.0 / CP evap = evap / rho * 1.0 / HVAP
def copy_defs(src: gtscript.Field["dtype"], dst: gtscript.Field["dtype"]): from __gtscript__ import PARALLEL, computation, interval with computation(PARALLEL), interval(...): dst = src
def sfc_sice_p2_defs( q1: DT_F, islimsk: DT_I, flag_iter: DT_I, fice: DT_F, tice: DT_F, tskin: DT_F, stc0: DT_F, stc1: DT_F, qsurf: DT_F, evap: DT_F, hflx: DT_F, # new variables: ffw: DT_F, theta1: DT_F, rch: DT_F, evapi: DT_F, evapw: DT_F, rho: DT_F, ): from __gtscript__ import PARALLEL, computation, interval with computation(PARALLEL), interval(...): hflxi = INIT_VALUE hflxw = INIT_VALUE # --- ... set flag for sea-ice flag = (islimsk == 2) and flag_iter if flag: if tice < TIMIN: # print('warning: snow/ice temperature is too low:', tice, ' i=', i) tice = TIMIN # print('fix snow/ice temperature: reset it to:', TIMIN) if stc0 < TIMIN: # print('warning: layer 1 ice temp is too low:', stsice[i, 0], ' i=', i) stc0 = TIMIN # print('fix layer 1 ice temp: reset it to:', TIMIN) if stc1 < TIMIN: # print('warning: layer 2 ice temp is too low:', stsice[i, 1], 'i=', i) stc1 = TIMIN # print('fix layer 2 ice temp: reset it to:', TIMIN) tskin = tice * fice + TGICE * ffw stc0 = T0C if T0C < stc0 else stc0 stc1 = T0C if T0C < stc1 else stc1 # --- ... calculate sensible heat flux (& evap over sea ice) hflxi = rch * (tice - theta1) hflxw = rch * (TGICE - theta1) hflx = fice * hflxi + ffw * hflxw evap = fice * evapi + ffw * evapw # --- ... the rest of the output qsurf = q1 + evap / (ELOCP * rch) hflx = hflx / rho * 1. / CP evap = evap / rho * 1. / HVAP
def sfc_sice_defs( ps: DT_F, t1: DT_F, q1: DT_F, sfcemis: DT_F, dlwflx: DT_F, sfcnsw: DT_F, sfcdsw: DT_F, srflag: DT_F, cm: DT_F, ch: DT_F, prsl1: DT_F, prslki: DT_F, islimsk: DT_I, wind: DT_F, flag_iter: DT_I, hice: DT_F, fice: DT_F, tice: DT_F, weasd: DT_F, tskin: DT_F, tprcp: DT_F, stc0: DT_F, stc1: DT_F, ep: DT_F, snwdph: DT_F, qsurf: DT_F, cmm: DT_F, chh: DT_F, evap: DT_F, hflx: DT_F, gflux: DT_F, snowmt: DT_F, # new variables hfi: DT_F, hfd: DT_F, sneti: DT_F, focn: DT_F, snof: DT_F, # new variables for second part ffw: DT_F, theta1: DT_F, rch: DT_F, evapi: DT_F, evapw: DT_F, rho: DT_F, *, delt: float, cimin: float): """This file contains the GFS thermodynamics surface ice model. ===================================================================== description: usage: program history log: 2005 -- xingren wu created from original progtm and added two-layer ice model 200x -- sarah lu added flag_iter oct 2006 -- h. wei added cmm and chh to output 2007 -- x. wu modified for mom4 coupling (i.e. cpldice) (not used anymore) 2007 -- s. moorthi micellaneous changes may 2009 -- y.-t. hou modified to include surface emissivity effect on lw radiation. replaced the confusing slrad with sfc net sw sfcnsw (dn-up). reformatted the code and add program documentation block. sep 2009 -- s. moorthi removed rcl, changed pressure units and further optimized jan 2015 -- x. wu change "cimin = 0.15" for both uncoupled and coupled case jul 2020 -- ETH-students port to gt4py ==================== definition of variables ==================== inputs: size ps - real, surface pressure im t1 - real, surface layer mean temperature ( k ) im q1 - real, surface layer mean specific humidity im sfcemis - real, sfc lw emissivity ( fraction ) im dlwflx - real, total sky sfc downward lw flux ( w/m**2 ) im sfcnsw - real, total sky sfc netsw flx into ground(w/m**2) im sfcdsw - real, total sky sfc downward sw flux ( w/m**2 ) im srflag - real, snow/rain fraction for precipitation im cm - real, surface exchange coeff for momentum (m/s) im ch - real, surface exchange coeff heat & moisture(m/s) im prsl1 - real, surface layer mean pressure im prslki - real, im islimsk - integer, sea/land/ice mask (=0/1/2) im wind - real, im flag_iter- logical, im delt - real, time interval (second) 1 cimin - real, minimum ice fraction 1 input/outputs: hice - real, sea-ice thickness im fice - real, sea-ice concentration im tice - real, sea-ice surface temperature im weasd - real, water equivalent accumulated snow depth (mm)im tskin - real, ground surface skin temperature ( k ) im tprcp - real, total precipitation im stc0 - real, soil temp (k), 1. layer im stc1 - real, soil temp (k), 2nd layer im ep - real, potential evaporation im outputs: snwdph - real, water equivalent snow depth (mm) im qsurf - real, specific humidity at sfc im snowmt - real, snow melt (m) im gflux - real, soil heat flux (w/m**2) im cmm - real, surface exchange coeff for momentum(m/s) im chh - real, surface exchange coeff heat&moisture (m/s) im evap - real, evaperation from latent heat flux im hflx - real, sensible heat flux im ===================================================================== """ from __gtscript__ import PARALLEL, computation, interval with computation(PARALLEL), interval(...): # arrays # TODO - only initialize the arrays which are defined in an if-statement q0 = INIT_VALUE # theta1 = INIT_VALUE # rho = INIT_VALUE # ffw = INIT_VALUE # snowd = INIT_VALUE # rch = INIT_VALUE # evapi = INIT_VALUE # evapw = INIT_VALUE # sneti = INIT_VALUE snetw = INIT_VALUE t12 = INIT_VALUE t14 = INIT_VALUE # hfi = INIT_VALUE # hfd = INIT_VALUE # focn = INIT_VALUE # snof = INIT_VALUE # hflxi = INIT_VALUE # hflxw = INIT_VALUE # --- ... set flag for sea-ice flag = (islimsk == 2) and flag_iter if flag_iter and (islimsk < 2): hice = 0. fice = 0. qs1 = fpvs_fn(t1) if flag: if srflag > 0.: ep = ep * (1. - srflag) weasd = weasd + 1.e3 * tprcp * srflag tprcp = tprcp * (1. - srflag) # --- ... initialize variables. all units are supposedly m.k.s. unless specified # psurf is in pascals, wind is wind speed, theta1 is adiabatic surface # temp from level 1, rho is density, qs1 is sat. hum. at level1 and qss # is sat. hum. at surface # convert slrad to the civilized unit from langley minute-1 k-4 # dlwflx has been given a negative sign for downward longwave # sfcnsw is the net shortwave flux (direction: dn-up) q0 = q1 if q1 > 1.0e-8 else 1.0e-8 theta1 = t1 * prslki rho = prsl1 / (RD * t1 * (1. + RVRDM1 * q0)) qs1 = EPS * qs1 / (prsl1 + EPSM1 * qs1) qs1 = qs1 if qs1 > 1.e-8 else 1.e-8 q0 = qs1 if qs1 < q0 else q0 if fice < cimin: # print("warning: ice fraction is low:", fice) #fice = cimin tice = TGICE tskin = TGICE # print('fix ice fraction: reset it to:', fice) fice = fice if fice > cimin else cimin qssi = fpvs_fn(tice) qssw = fpvs_fn(TGICE) if flag: ffw = 1. - fice qssi = EPS * qssi / (ps + EPSM1 * qssi) qssw = EPS * qssw / (ps + EPSM1 * qssw) # --- ... snow depth in water equivalent is converted from mm to m unit weasd = weasd * 0.001 # --- ... when snow depth is less than 1 mm, a patchy snow is assumed and # soil is allowed to interact with the atmosphere. # we should eventually move to a linear combination of soil and # snow under the condition of patchy snow. # --- ... rcp = rho CP ch v cmm = cm * wind chh = rho * ch * wind rch = chh * CP # --- ... sensible and latent heat flux over open water & sea ice evapi = ELOCP * rch * (qssi - q0) evapw = ELOCP * rch * (qssw - q0) snetw = sfcdsw * (1. - ALBFW) t12 = 3. * sfcnsw / (1. + 2. * ffw) snetw = t12 if t12 < snetw else snetw sneti = (sfcnsw - ffw * snetw) / fice t12 = tice * tice t14 = t12 * t12 # --- ... hfi = net non-solar and upir heat flux @ ice surface hfi = -dlwflx + sfcemis * SBC * t14 + evapi + \ rch * (tice - theta1) hfd = 4. * sfcemis * SBC * tice * t12 + \ (1. + ELOCP * EPS * HVAP * qs1 / (RD * t12)) * rch t12 = TGICE * TGICE t14 = t12 * t12 # --- ... hfw = net heat flux @ water surface (within ice) focn = 2. # heat flux from ocean - should be from ocn model snof = 0. # snowfall rate - snow accumulates in gbphys # hice = np.maximum(np.minimum(hice, HIMAX), HIMIN) hice = HIMAX if HIMAX < hice else hice hice = HIMIN if HIMIN > hice else hice weasd = HSMAX if HSMAX < weasd else weasd if weasd > 2. * hice: # print('warning: too much snow :', snowd[i]) weasd = hice + hice
def ice3lay_defs( #fice, flag, hfi, hfd, sneti, focn, delt, snowd, hice, #stc0, stc1, tice, snof, snowmt, gflux): islimsk: DT_I, flag_iter: DT_I, hice: DT_F, fice: DT_F, tice: DT_F, snowd: DT_F, stc0: DT_F, stc1: DT_F, gflux: DT_F, snowmt: DT_F, snwdph: DT_F, # new variables hfi: DT_F, hfd: DT_F, sneti: DT_F, focn: DT_F, snof: DT_F, *, delt: float, ): """three-layer sea ice vertical thermodynamics * based on: m. winton, "a reformulated three-layer sea ice model", * journal of atmospheric and oceanic technology, 2000 * * * -> +---------+ <- tice - diagnostic surface temperature ( <= 0c )* / | | * snowd | snow | <- 0-heat capacity snow layer * \ | | * => +---------+ * / | | * / | | <- t1 - upper 1/2 ice temperature; this layer has * / | | a variable (t/s dependent) heat capacity * hice |...ice...| * \ | | * \ | | <- t2 - lower 1/2 ice temp. (fixed heat capacity) * \ | | * -> +---------+ <- base of ice fixed at seawater freezing temp. * * ===================== definition of variables ===================== * * inputs: size * fice - real, sea-ice concentration im * flag - logical, ice mask flag 1 * hfi - real, net non-solar and heat flux @ surface(w/m^2) im * hfd - real, heat flux derivatice @ sfc (w/m^2/deg-c) im * sneti - real, net solar incoming at top (w/m^2) im * focn - real, heat flux from ocean (w/m^2) im * delt - real, timestep (sec) 1 * * input/outputs: * snowd - real, surface pressure im * hice - real, sea-ice thickness im * stc0 - real, temp @ midpt of ice levels (deg c), 1st layer im * stc1 - real, temp @ midpt of ice levels (deg c), 2nd layer im * tice - real, surface temperature (deg c) im * snof - real, snowfall rate (m/sec) im * * outputs: * snowmt - real, snow melt during delt (m) im * gflux - real, conductive heat flux (w/m^2) im * * locals: * hdi - real, ice-water interface (m) * hsni - real, snow-ice (m) * * ====================================================================== * """ from __gtscript__ import PARALLEL, computation, interval with computation(PARALLEL), interval(...): # TODO - only initialize the arrays which are defined in an if-statement hdi = INIT_VALUE ip = INIT_VALUE tsf = INIT_VALUE ai = INIT_VALUE k12 = INIT_VALUE wrk = INIT_VALUE a10 = INIT_VALUE b10 = INIT_VALUE a1 = INIT_VALUE b1 = INIT_VALUE c1 = INIT_VALUE tmelt = INIT_VALUE bmelt = INIT_VALUE h1 = INIT_VALUE h2 = INIT_VALUE dh = INIT_VALUE flag = (islimsk == 2) and flag_iter if flag: snowd = snowd * DWDS hdi = (DSDW * snowd + DIDW * hice) if hice < hdi: snowd = snowd + hice - hdi hice = hice + (hdi - hice) * DSDI snof = snof * DWDS tice = tice - T0C stc0 = stc0 - T0C if stc0 - T0C < TFI0 else TFI0 stc1 = TFI0 if TFI0 < stc1 - T0C else stc1 - T0C # degc ip = I0 * sneti # ip +v here (in winton ip=-I0*sneti) if snowd > 0.: tsf = 0. ip = 0. else: tsf = TFI tice = tsf if tsf < tice else tice # compute ice temperature ai = hfi - sneti + ip - tice * hfd # +v sol input here k12 = KI4 * KS / (KS * hice + KI4 * snowd) wrk = 1. / (6. * delt * 2. * KI / hice + DICI * hice) a10 = DICI * hice * (0.5 / delt) + \ 2. * KI / hice * (4. * delt * 2. * KI / hice + DICI * hice) * wrk b10 = -DI * hice * (CI * stc0 + LI * TFI / \ stc0) * (0.5 / delt) - ip - 2. * KI / hice * \ (4. * delt * 2. * KI / hice * TFW + DICI * hice * stc1) * wrk a1 = a10 + hfd * k12 / (k12 + hfd) b1 = b10 + ai * k12 / (k12 + hfd) c1 = DILI * TFI * (0.5 / delt) * hice stc0 = -((b1 * b1 - 4. * a1 * c1)**0.5 + b1) / (a1 + a1) tice = (k12 * stc0 - ai) / (k12 + hfd) if tice > tsf: a1 = a10 + k12 b1 = b10 - k12 * tsf stc0 = -((b1 * b1 - 4. * a1 * c1)**0.5 + b1) / (a1 + a1) tice = tsf tmelt = (k12 * (stc0 - tsf) - (ai + hfd * tsf)) * delt else: tmelt = 0. snowd = snowd + snof * delt stc1 = (2. * delt * 2. * KI / hice * (stc0 + TFW + TFW) + \ DICI * hice * stc1) * wrk bmelt = (focn + KI4 * (stc1 - TFW) / hice) * delt # --- ... resize the ice ... h1 = 0.5 * hice h2 = 0.5 * hice # --- ... top ... if tmelt <= snowd * DSLI: snowmt = tmelt / DSLI snowd = snowd - snowmt else: snowmt = snowd h1 = h1 - (tmelt - snowd * DSLI) / \ (DI * (CI - LI / stc0) * (TFI - stc0)) snowd = 0. # --- ... and bottom if bmelt < 0.: dh = -bmelt / (DILI + DICI * (TFI - TFW)) stc1 = (h2 * stc1 + dh * TFW) / (h2 + dh) h2 = h2 + dh else: h2 = h2 - bmelt / (DILI + DICI * (TFI - stc1)) # --- ... if ice remains, even up 2 layers, else, pass negative energy back in snow hice = h1 + h2 # begin if_hice_block if hice > 0.: if h1 > 0.5 * hice: stc1 = (1. - 2. * h2 / hice) * (stc0 + LI*TFI/ \ (CI*stc0)) + 2. * h2 / hice * stc1 if stc1 > TFI: hice = hice - h2 * CI * (stc1 - TFI) / (LI * delt) stc1 = TFI else: stc0 = 2.*h1/hice*(stc0 + LI*TFI/ \ (CI*stc0)) + (1. - 2.*h1/hice)*stc1 stc0 = (stc0 - (stc0 * stc0 - 4.0 * TFI * LI / CI)**0.5) * 0.5 gflux = KI4 * KS / (KS * hice + KI4 * snowd) * (stc0 - tice) else: snowd = snowd + (h1*(CI*(stc0 - TFI)\ - LI*(1. - TFI/stc0)) + h2*(CI*\ (stc1 - TFI) - LI)) / LI hice = snowd * DSDI if snowd * DSDI < 0. else 0. snowd = 0. stc0 = TFW stc1 = TFW gflux = 0. gflux = fice * gflux snowmt = snowmt * DSDW snowd = snowd * DSDW tice = tice + T0C stc0 = stc0 + T0C stc1 = stc1 + T0C # --- ... convert snow depth back to mm of water equivalent snowd = snowd * 1000. snwdph = snowd * DSI # snow depth in mm
def copy_stencil(in_field: gtscript.Field[float], out_field: gtscript.Field[float]): from __gtscript__ import computation, interval, PARALLEL with computation(PARALLEL), interval(...): out_field = in_field