source: codes/icosagcm/devel/Python/src/unstructured/macros.jin @ 802

Last change on this file since 802 was 685, checked in by dubos, 6 years ago

devel/unstructured : towards vertical remapping

File size: 12.2 KB
Line 
1#ifdef PASS_PRE1
2#define _AND_ &&
3#define _OR_ ||
4#define _NOT_ !
5#define IS_INNER_LAYER (_NOT_ (IS_BOTTOM_LEVEL _OR_ IS_TOP_LAYER))
6#define IS_INNER_INTERFACE (_NOT_ (IS_BOTTOM_LEVEL _OR_ IS_TOP_INTERFACE))
7#endif
8
9#ifdef PASS_PRE2
10
11#define BARRIER !$OMP BARRIER
12#define IS_INNER_INTERFACE (.NOT. (IS_BOTTOM_LEVEL .OR. IS_TOP_INTERFACE))
13#define KERNEL(name) {% call() define_kernel(#name) %}
14#define FORALL_CELLS(...) {% call(lrange,flags) forall_cells(__VA_ARGS__) %}
15#define FORALL_CELLS_EXT(...) {% call(lrange,flags) forall_cells(__VA_ARGS__) %}
16#define ON_PRIMAL {% call(mesh, degree=0) on_mesh('primal',lrange,flags) %}
17#define ON_DUAL {% call(mesh, degree=0) on_mesh('dual',lrange,flags) %}
18#define ON_EDGES {% call(mesh, degree=0) on_edges('edge',lrange,flags) %}
19#define FORALL_EDGES {% call forall_edges(mesh,degree) %}
20#define FORALL_VERTICES {% call forall_vertices(mesh,degree) %}
21#define FORALL_TRISK {% call forall_trisk(degree) %}
22#define END_BLOCK {% endcall %}
23#define SEQUENCE_C0 {% call(body,at_level) sequence_primal() %}
24#define SEQUENCE_C1 {% call(body,at_level) sequence_primal() %}
25#define SEQUENCE_E0 {% call(body,at_level) sequence_edge() %}
26#define PROLOGUE(level) {% call at_level(level) %}
27#define EPILOGUE(level) {% call at_level(level) %}
28#define BODY(range) {% call body(range) %}
29
30#define CST_IF(condition, action) {{ cst_if(#condition, #action) }}
31#define CST_IFTHEN(condition) {{flat}}if condition
32#define CST_ELSEIF(condition) {{flat}}elif condition
33#define CST_ELSE {{flat}}else
34#define CST_ENDIF {{flat}}endif
35
36#endif
37
38#ifdef PASS_JINJA
39
40{#  -------------------------- Design notes ------------------------------
41
42The syntax
43{% call(ARGNAMES) macro(ARGS) %}
44...
45{% endcall %}
46passes ARGS to macro ; this macro "calls" the body using the syntax 'caller(arg1,...)' ; these arguments
47are available in the body under the names ARGNAMES, as if it were a macro caller(ARGNAMES).
48
49Using its optional argument 'options', forall_cells() sets variable 'flags'
50and passes it on to on_mesh() / on_edges()
51
52Similarly variable 'lrange' is passed from forall_cells to on_mesh() / on_egdes() 
53
54-------------------------------------------------------------------------- #}
55
56{# NB : degree = number of elements in stencil, for instance number of edges of primal cell #}
57{# define the degrees for which a special version of code is generated #}
58{% set degree_primal, degree_dual, degree_trisk = (4,5,6), (3,4), (4,10) %}
59
60{# ----------------------- SEQUENCE, FORALL ----------------------- #}
61
62{% macro sequence_primal() -%}
63!$OMP DO SCHEDULE(STATIC)                                                                           
64  DO ij=1,primal_num
65    {{ caller(body_primal, at_level_primal) }}
66  END DO
67!$OMP END DO
68{%- endmacro %}
69
70{% macro sequence_edge() -%}
71{% set thecode = caller(body_edge, at_level_edge) %}
72!$OMP DO SCHEDULE(STATIC)                                                                           
73  DO edge=1,edge_num
74{{ 'ij_left = left(edge)'   if 'CELL1'    in thecode }}
75{{ 'ij_right = right(edge)' if 'CELL2'   in thecode }}
76{{ 'ij_up = up(edge)'       if 'VERTEX1' in thecode }}
77{{ 'ij_down = down(edge)'   if 'VERTEX2' in thecode }}
78    {{ thecode }}
79  END DO
80!$OMP END DO
81{%- endmacro %}
82
83{% macro body_primal(range) -%}
84  {{ define('CELL','l,ij') }}
85    DO l = {{ range }}
86      {{ caller() }}
87    END DO
88  {{ undef('CELL') }}
89{%- endmacro %}
90
91{% macro body_edge(range) -%}
92{% set thecode = caller() %}
93{{ define('EDGE', 'l,edge') }}
94{{ cdef(thecode, 'LE_DE', 'le_de(edge)') }}
95{{ cdef(thecode, 'SIGN', '1.') }}
96{{ cdef(thecode, 'CELL1', 'l,ij_left') }}
97{{ cdef(thecode, 'CELL2',  'l,ij_right') }}
98{{ cdef(thecode, 'VERTEX1', 'l,ij_down') }}
99{{ cdef(thecode, 'VERTEX2', 'l,ij_up') }}
100    DO l = {{ range }}
101      {{ thecode }}
102    END DO
103{{ cundef(thecode, ('EDGE','LE_DE','SIGN','CELL1','CELL2','VERTEX1','VERTEX2') ) }}
104{%- endmacro %}
105
106{% macro at_level_primal(lev) -%}
107  {{ define('CELL','%s,ij'%lev) }}
108  {{ caller() }}
109  {{ undef('CELL') }}
110{%- endmacro %}
111
112{% macro at_level_edge(lev) -%}
113  {{ define('EDGE','%s,edge'%lev) }}
114  {{ caller() }}
115  {{ undef('EDGE') }}
116{%- endmacro %}
117
118{% macro forall_cells(start='1', end='llm', options=[]) -%}
119  {% set flags=[options] if options is string else options %}
120  {{ caller((start,end),flags) }}
121{%- endmacro %}
122
123{# ---------------------- PRELOAD STENCIL INDICES ---------------------- #}
124
125{% macro get_edges(thecode, mesh,degree) %}
126{% for iedge in range(1,degree+1) %}
127{{ 'edge%d = %s_edge(%d,ij)'%(iedge,mesh,iedge) if 'EDGE' in thecode }}
128{% endfor %}
129{% for iedge in range(1,degree+1) %}
130{{ 'le_de%d = le_de(edge%d)'%(iedge,iedge) if 'LE_DE' in thecode }}     
131{% endfor %}
132{% for iedge in range(1,degree+1) %}
133{{ 'sign%d = %s_ne(%d,ij)'%(iedge,mesh,iedge) if 'SIGN' in thecode }}   
134{% endfor %}
135{% for iedge in range(1,degree+1) %}
136{{ 'ij_up%d = up(edge%d)'%(iedge,iedge) if 'VERTEX1' in thecode }}
137{% endfor %}
138{% for iedge in range(1,degree+1) %}
139{{ 'ij_down%d = down(edge%d)'%(iedge,iedge) if 'VERTEX2' in thecode }}
140{% endfor %}
141{% endmacro %}
142
143{% macro get_vertices(thecode, mesh,degree) %}
144{% for ivertex in range(1,degree+1) %}
145{{ 'vertex%d = %s_vertex(%d,ij)'%(ivertex,mesh,ivertex) if 'VERTEX' in thecode }}
146{% endfor %}
147{% endmacro %}
148
149{# ------------------------------ MESHES --------------------------- #}
150
151{# argument 'code' is the body enclosed by ON_XXX ... END_BLOCK ; it takes arguments : mesh,degree=0 #}
152
153{% macro vloop_unroll(mesh, lrange, flags, code) %}
154
155{% set thecode, has_primal, has_dual, has_trisk, has_none = code(mesh), False, False, False, True %}
156
157{% if 'primal_deg' in thecode %}
158! this VLOOP iterates over primal cell edges
159{% set has_primal, has_none = True,False %}
160{% endif %}
161{% if 'dual_deg' in thecode %}
162! this VLOOP iterates over dual cell edges
163{% set has_dual,has_none = True,False %}
164{% endif %}
165{% if 'trisk_deg' in thecode %}
166! this VLOOP iterates over the TRISK stencil
167{% set has_trisk,has_none = True,False %}
168{% endif %}
169
170{% if has_none %}
171{{ vloop(mesh, lrange, flags, code) }}
172{% endif %}
173
174{% if has_primal %}
175SELECT CASE(primal_deg(ij))
176{% for degree in degree_primal %}
177CASE({{ degree }})
178{{ get_edges(thecode, mesh, degree) }}
179{{ vloop(mesh, lrange, flags, code, degree) }}
180{% endfor %}
181CASE DEFAULT
182{{ vloop(mesh, lrange, flags, code) }}
183END SELECT
184{% endif %}
185
186{% if has_dual %}
187SELECT CASE(dual_deg(ij))
188{% for degree in degree_dual %}
189CASE({{ degree }})
190{{ get_edges(thecode, mesh, degree) }}
191{{ get_vertices(thecode,mesh,degree) }}
192{{ vloop(mesh, lrange, flags, code, degree) }}
193{% endfor %}
194CASE DEFAULT
195{{ vloop(mesh, lrange, flags, code) }}
196END SELECT
197{% endif %}
198
199{% if has_trisk %}
200SELECT CASE(trisk_deg(edge))
201{% for degree in degree_trisk %}
202CASE({{ degree }})
203{{ vloop(mesh, lrange, flags, code, degree) }}
204{% endfor %}
205CASE DEFAULT
206{{ vloop(mesh, lrange, flags, code) }}
207END SELECT
208{% endif %}
209
210{%- endmacro %}
211
212{% macro vloop(mesh, lrange, flags, code, degree=0) %}
213
214{% set start,end = lrange %}
215{% set thecode, is_top_layer, is_top_inter = code(mesh,degree), False, False %}
216
217{{ define('IS_TOP_LAYER', '_FALSE_') }}
218{{ define('IS_TOP_INTERFACE', '_FALSE_') }}
219
220{% if 'IS_BOTTOM_LEVEL' in thecode or 'KDOWN' in thecode%}
221{# the code in the loop checks whether l==1, for the sake of performance
222we shall write special code for l=1 and start the loop at l=2 #}
223{{ define('IS_BOTTOM_LEVEL', '_TRUE_') }}
224{{ 'kdown = 1' if 'KDOWN' in thecode }}
225{{ 'kup   = 1' if 'KUP'   in thecode }}
226l=1
227{{ thecode }}
228{% set start='2' %}
229{% endif %}
230
231{% if 'IS_TOP_LAYER' in thecode %}
232{{ 'ERROR : using IS_TOP_LAYER in a loop ending at l=llm+1' if end=='llm+1' }}
233{# the code checks whether l==llm, write special code for l=llm and end the loop at l=llm-1 #}
234{% set end, is_top_layer = 'llm-1', True %}
235{% endif %}
236
237{% if 'IS_TOP_INTERFACE' in thecode or 'KUP' in thecode %}
238{# the code checks whether l==llm+1, write special code for l=llm+1 and end the loop at l=llm #}
239{{ 'ERROR : using IS_TOP_INTERFACE in a loop ending at l=llm' if end=='llm' }}
240{% set end, is_top_inter ='llm', True %}
241{% endif %}
242
243{{ define('IS_BOTTOM_LEVEL', '_FALSE_') }}
244!DIR$ SIMD
245  DO l = {{start}}, {{end}}
246    {{ 'kdown = l-1' if 'KDOWN' in thecode }}
247    {{ 'kup   = l' if 'KUP'   in thecode }}
248    {{ thecode }}
249  END DO
250
251{% if is_top_layer %}
252{{ define('IS_TOP_LAYER', '_TRUE_') }}
253{{ 'kdown = llm-1' if 'KDOWN' in thecode }}
254{{ 'kup   = llm' if 'KUP'   in thecode }}
255l=llm
256{{ thecode }}
257{% endif %}
258
259{% if is_top_inter %}
260{{ define('IS_TOP_INTERFACE', '_TRUE_') }}
261{{ 'kdown = llm' if 'KDOWN' in thecode }}
262{{ 'kup   = llm' if 'KUP'   in thecode }}
263l=llm+1
264{{ thecode }}
265{% endif %}
266
267{% endmacro %}
268
269{% macro on_mesh(mesh,lrange,flags) -%}
270{{ define('CELL','l,ij') if mesh=='primal' }}
271{{ define('DUAL_CELL', 'l,ij') if mesh=='dual'}}
272!$OMP DO SCHEDULE(STATIC)                                                                           
273DO ij = 1, {{ mesh }}_num
274{{ vloop_unroll(mesh, lrange, flags, caller) }}
275END DO
276!$OMP END DO
277{{ undef('CELL') }}
278{{ undef('DUAL_CELL') }}
279{%- endmacro %}
280
281{# ------------------------------ STENCILS --------------------------- #}
282
283{% macro on_edges(mesh,lrange,flags) -%}
284{% set thecode = caller(mesh) %}
285{{ define('EDGE', 'l,edge') }}
286{{ cdef(thecode, 'LE_DE', 'le_de(edge)') }}
287{{ cdef(thecode, 'SIGN', '1.') }}
288{{ cdef(thecode, 'CELL1', 'l,ij_left') }}
289{{ cdef(thecode, 'CELL2',  'l,ij_right') }}
290{{ cdef(thecode, 'VERTEX1', 'l,ij_down') }}
291{{ cdef(thecode, 'VERTEX2', 'l,ij_up') }}
292!$OMP DO SCHEDULE(STATIC)
293DO edge = 1, edge_num
294{{ 'ij_left = left(edge)'   if 'CELL1'    in thecode }}
295{{ 'ij_right = right(edge)' if 'CELL2'   in thecode }}
296{{ 'ij_up = up(edge)'       if 'VERTEX1' in thecode }}
297{{ 'ij_down = down(edge)'   if 'VERTEX2' in thecode }}
298{{ vloop_unroll(mesh, lrange, flags, caller) }}
299END DO
300!$OMP END DO
301{{ cundef(thecode, ('EDGE','LE_DE','SIGN','CELL1','CELL2','VERTEX1','VERTEX2') ) }}
302{%- endmacro %}
303
304{% macro forall_edges(mesh,degree) -%}
305{% set thecode = caller() %}
306
307{% if degree>1 %}
308{% for iedge in range(1,degree+1) %}
309{{ cdef(thecode, 'EDGE', 'l,edge%d'%iedge) }}
310{{ cdef(thecode, 'SIGN', 'sign%d'%iedge) }}
311{{ cdef(thecode, 'LE_DE', 'le_de%d'%iedge) }}
312{{ cdef(thecode, 'VERTEX1', 'l,ij_up%d'%iedge) }}
313{{ cdef(thecode, 'VERTEX2', 'l,ij_down%d'%iedge) }}
314  {{ thecode }}
315{% endfor %}
316{% else %}
317{{ cdef(thecode, 'EDGE', 'l,edge') }}
318{{ cdef(thecode, 'SIGN', mesh + '_ne(iedge,ij)') }}
319{{ cdef(thecode, 'LE_DE', 'le_de(edge)') }}
320{{ cdef(thecode, 'VERTEX1', 'l,ij_up') }}
321{{ cdef(thecode, 'VERTEX2', 'l,ij_down') }}
322DO iedge = 1, {{ mesh }}_deg(ij)
323  edge = {{ mesh }}_edge(iedge,ij)
324  {{ 'ij_up = up(edge)'       if 'VERTEX1' in thecode }}
325  {{ 'ij_down = down(edge)'   if 'VERTEX2' in thecode }}
326  {{ thecode }}
327END DO
328{% endif %}
329{{ cundef(thecode, ('EDGE', 'SIGN', 'LE_DE', 'VERTEX1', 'VERTEX2') ) }}
330{%- endmacro %}
331
332{% macro forall_trisk(degree) -%}
333{% set thecode = caller() %}
334{{ define('EDGE_TRISK', 'l,edge_trisk') }}
335{% if degree>1 %}
336{% for itrisk in range(1,degree+1) %}
337  itrisk = {{ itrisk }}
338  edge_trisk = trisk({{ itrisk }},edge)
339  {{ thecode }}
340{% endfor %}
341{% else %}
342DO itrisk = 1, trisk_deg(edge)
343  edge_trisk = trisk(itrisk,edge)
344  {{ thecode }}
345END DO
346{% endif %}
347{{ undef('EDGE_TRISK') }}
348{%- endmacro %}
349
350{% macro forall_vertices(mesh,degree) -%}
351{% set thecode = caller() %}
352{% if degree>1 %}
353{% for ivertex in range(1,degree+1) %}
354{{ define('RIV2', 'Riv2(%d,ij)'%ivertex ) }}
355{{ define('VERTEX', 'l,vertex%d'%ivertex ) }}
356  {{ thecode }}
357{% endfor %}
358{% else %}
359{{ define('RIV2', 'Riv2(ivertex,ij)') }}
360{{ define('VERTEX', 'l,vertex') }}
361DO ivertex = 1, {{ mesh }}_deg(ij)
362  vertex = {{ mesh }}_vertex(ivertex,ij)
363  {{ thecode }}
364END DO
365{% endif %}
366{{ undef('VERTEX') }}
367{{ undef('RIV2') }}
368{%- endmacro %}
369
370{# --------------------------------------------------------- #}
371
372{% set llm='llm' %}
373
374{{ undef('SIGN') }}
375{{ undef('CELL') }}
376{{ undef('CELL1') }}
377{{ undef('CELL2') }}
378{{ undef('VERTEX1') }}
379{{ undef('VERTEX2') }}
380{{ undef('EDGE_TRISK') }}
381
382{# --------------------- END JINJA ------------------------- #}
383
384#endif
385
386#ifdef PASS_POST1
387
388#define _TRUE_ (0==0)
389#define _FALSE_ (0==1)
390
391#define AI Ai(ij)
392#define AV Av(ij)
393#define FV fv(ij)
394#define WEE wee(itrisk,edge)
395#define edge_ne(iedge,ij) 1.
396#endif
397
398#ifdef PASS_POST2
399#define AT_LEVEL(l,ij,lev) lev,ij
400#define KUP(l,ij) kup,ij
401#define KDOWN(l,ij) kdown,ij
402#define DOWN(l,ij) l-1,ij
403#define UP(l,ij) l+1,ij
404#define HIDX(l,ij) ij
405#define VIDX(l,ij) l
406#endif
Note: See TracBrowser for help on using the repository browser.