#define THECELL {{ thecell }} {# ---------------- macro to generate code computing pressure top-down --------------- formula = formula to compute 'gravitational' mass = rhodz (dry) rhodz*theta (boussinesq) rhodz*(1+qv) (moist) #} #define BALANCE(formula) {% call(thecell) balance() %} formula {% endcall %} {% macro balance() %} {% set formula=caller %} SEQUENCE_EXT PROLOGUE(llm) pk(CELL) = ptop + .5*g*{{ formula('CELL') }} END_BLOCK BODY('llm-1,1,-1') pk(CELL) = pk(UP(CELL)) + (.5*g)*({{ formula('CELL') }}+{{ formula('UP(CELL)') }}) END_BLOCK IF(caldyn_eta == eta_lag) THEN EPILOGUE(1) ps(HIDX(CELL)) = pk(CELL) + .5*g*{{ formula('CELL') }} END_BLOCK END IF END_BLOCK {%- endmacro %} {# ------------ macro to generate code computing geopotential bottom-up -------------- var = variable to be stored in pk(CELL) caller() computes gv = g*v where v = specific volume details depend on caldyn_thermo #} #define GEOPOT(var) {% call geopot(var) %} {% macro geopot(var) %} {% set formula=caller %} SEQUENCE_EXT BODY('1,llm') p_ik = pk(CELL) {{ formula() }} pk(CELL) = {{ var }} geopot(UP(CELL)) = geopot(CELL) + gv*rhodz(CELL) END_BLOCK END_BLOCK {%- endmacro %} #define END_GEOPOT {% endcall %} KERNEL(compute_geopot) SELECT CASE(caldyn_thermo) CASE(thermo_boussinesq) ! use hydrostatic balance with theta*rhodz to find pk (=Lagrange multiplier=pressure) BALANCE( theta(THECELL,1)*rhodz(THECELL) ) ! now pk contains the Lagrange multiplier (pressure) ! specific volume 1 = dphi/g/rhodz SEQUENCE_EXT BODY('1,llm') geopot(UP(CELL)) = geopot(CELL) + g*rhodz(CELL) END_BLOCK END_BLOCK CASE(thermo_theta) BALANCE( rhodz(THECELL) ) GEOPOT('exner_ik') exner_ik = cpp * (p_ik/preff) ** kappa gv = (g*kappa)*theta(CELL,1)*exner_ik/p_ik END_GEOPOT CASE(thermo_entropy) BALANCE( rhodz(THECELL) ) GEOPOT('temp_ik') temp_ik = Treff*exp((theta(CELL,1) + Rd*log(p_ik/preff))/cpp) gv = (g*Rd)*temp_ik/p_ik ! specific volume v = Rd*T/p END_GEOPOT CASE(thermo_moist) BALANCE( rhodz(THECELL)*(1.+theta(THECELL,2)) ) GEOPOT('temp_ik') qv = theta(CELL,2) ! water vaper mixing ratio = mv/md Rmix = Rd+qv*Rv chi = ( theta(CELL,1) + Rmix*log(p_ik/preff) ) / (cpp + qv*cppv) ! log(T/Treff) temp_ik = Treff*exp(chi) ! specific volume v = R*T/p ! R = (Rd + qv.Rv)/(1+qv) gv = g*Rmix*temp_ik/(p_ik*(1+qv)) END_GEOPOT END SELECT END_BLOCK KERNEL(caldyn_slow_hydro) FORALL_CELLS_EXT() ON_EDGES uu = .5*(rhodz(CELL1)+rhodz(CELL2))*u(EDGE) hflux(EDGE) = uu*LE_DE END_BLOCK END_BLOCK FORALL_CELLS() ON_PRIMAL ke=0.d0 FORALL_EDGES ke = ke + LE_DE*u(EDGE)**2 END_BLOCK BERNI(CELL)=ke*(.25/AI) END_BLOCK END_BLOCK IF(zero) THEN FORALL_CELLS() ON_EDGES du(EDGE) = SIGN*(berni(CELL1)-berni(CELL2)) ! minus gradient END_BLOCK END_BLOCK ELSE FORALL_CELLS() ON_EDGES du(EDGE) = du(EDGE) + SIGN*(berni(CELL1)-berni(CELL2)) ! minus gradient END_BLOCK END_BLOCK END IF END_BLOCK