source: codes/icosagcm/devel/Python/src/kernels_caldyn_hydro.jin @ 836

Last change on this file since 836 was 836, checked in by dubos, 5 years ago

devel : Cp(T) thermodynamics (TBC)

File size: 3.7 KB
Line 
1#define THECELL {{ thecell }}
2
3{# ---------------- macro to generate code computing pressure top-down ---------------
4   formula = formula to compute 'gravitational' mass
5   = rhodz (dry) rhodz*theta (boussinesq) rhodz*(1+qv) (moist)         #}
6
7#define BALANCE(formula) {% call(thecell) balance() %} formula {% endcall %}
8{% macro balance() %} {% set formula=caller %}
9SEQUENCE_C1
10  PROLOGUE(llm)
11    pk(CELL) = ptop + .5*g*{{ formula('CELL') }}
12  END_BLOCK
13  BODY('llm-1,1,-1')
14    pk(CELL) = pk(UP(CELL)) + (.5*g)*({{ formula('CELL') }}+{{ formula('UP(CELL)') }})
15  END_BLOCK
16  IF(caldyn_eta == eta_lag) THEN
17    EPILOGUE(1)
18      ps(HIDX(CELL)) = pk(CELL) + .5*g*{{ formula('CELL') }}
19    END_BLOCK
20  END IF
21END_BLOCK
22{%- endmacro %}
23
24{# ------------ macro to generate code computing geopotential bottom-up --------------
25   var = variable to be stored in pk(CELL)
26   caller() computes gv = g*v where v = specific volume
27   details depend on caldyn_thermo #}
28
29#define GEOPOT(var) {% call geopot(var) %}
30{% macro geopot(var) %} {% set formula=caller %}
31  SEQUENCE_C1
32    BODY('1,llm')
33      p_ik = pk(CELL)
34      {{ formula() }}
35      pk(CELL) = {{ var }}
36      geopot(UP(CELL)) = geopot(CELL) + gv*rhodz(CELL)
37    END_BLOCK
38  END_BLOCK
39{%- endmacro %}
40
41#define END_GEOPOT {% endcall %}
42
43KERNEL(compute_geopot)
44  SELECT CASE(caldyn_thermo)
45  CASE(thermo_boussinesq)
46    ! use hydrostatic balance with theta*rhodz to find pk (=Lagrange multiplier=pressure)
47    BALANCE( theta(THECELL,1)*rhodz(THECELL) )
48    ! now pk contains the Lagrange multiplier (pressure)
49    ! specific volume 1 = dphi/g/rhodz
50    SEQUENCE_C1
51      BODY('1,llm')
52        geopot(UP(CELL)) = geopot(CELL) + g*rhodz(CELL)
53      END_BLOCK
54    END_BLOCK
55  CASE(thermo_theta)
56    BALANCE( rhodz(THECELL) )
57    GEOPOT('exner_ik')
58      exner_ik = cpp * (p_ik/preff) ** kappa
59      gv = (g*kappa)*theta(CELL,1)*exner_ik/p_ik
60    END_GEOPOT
61  CASE(thermo_entropy)
62    BALANCE( rhodz(THECELL) )
63    GEOPOT('temp_ik')
64      temp_ik = Treff*exp((theta(CELL,1) + Rd*log(p_ik/preff))/cpp)
65      gv = (g*Rd)*temp_ik/p_ik   ! specific volume v = Rd*T/p
66    END_GEOPOT
67  CASE(thermo_variable_Cp)
68    ! thermodynamics with variable Cp
69    !      Cp.dT = dh = Tds + vdp
70    !              pv = RT
71    ! =>           ds = (dh+v.dp)/T = Cp.dT/T - R dp/p
72    !           Cp(T) = Cp0 * (T/T0)^nu
73    ! =>       s(p,T) = Cp(T)/nu - R log(p/preff)
74    !               h = Cp(T).T/(nu+1)
75    BALANCE( rhodz(THECELL) )
76    GEOPOT('temp_ik')
77      Cp_ik = nu*( theta(CELL,1) + Rd*log(p_ik/preff) )
78      temp_ik = Treff* (Cp_ik/cpp)**(1./nu)
79      gv = (g*Rd)*temp_ik/p_ik   ! specific volume v = Rd*T/p
80    END_GEOPOT
81  CASE(thermo_moist)
82    BALANCE( rhodz(THECELL)*(1.+theta(THECELL,2)) )
83    GEOPOT('temp_ik')
84      qv = theta(CELL,2) ! water vaper mixing ratio = mv/md
85      Rmix = Rd+qv*Rv
86      chi = ( theta(CELL,1) + Rmix*log(p_ik/preff) ) / (cpp + qv*cppv) ! log(T/Treff)
87      temp_ik = Treff*exp(chi)
88      ! specific volume v = R*T/p
89      ! R = (Rd + qv.Rv)/(1+qv)
90      gv = g*Rmix*temp_ik/(p_ik*(1+qv))
91    END_GEOPOT
92  END SELECT
93END_BLOCK
94
95KERNEL(caldyn_slow_hydro)
96  FORALL_CELLS_EXT()
97    ON_EDGES
98      uu = .5*(rhodz(CELL1)+rhodz(CELL2))*u(EDGE)
99      hflux(EDGE) = uu*LE_DE
100    END_BLOCK
101  END_BLOCK
102
103  FORALL_CELLS()
104    ON_PRIMAL
105      ke=0.d0
106      FORALL_EDGES
107        ke = ke + LE_DE*u(EDGE)**2
108      END_BLOCK
109      BERNI(CELL)=ke*(.25/AI)
110    END_BLOCK
111  END_BLOCK
112  IF(zero) THEN
113    FORALL_CELLS()
114      ON_EDGES
115        du(EDGE) = SIGN*(berni(CELL1)-berni(CELL2)) ! minus gradient
116      END_BLOCK
117    END_BLOCK
118  ELSE
119    FORALL_CELLS()
120      ON_EDGES
121        du(EDGE) = du(EDGE) + SIGN*(berni(CELL1)-berni(CELL2)) ! minus gradient
122      END_BLOCK
123    END_BLOCK
124  END IF
125
126END_BLOCK
Note: See TracBrowser for help on using the repository browser.