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

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

devel : DySL for enstrophy-conserving scheme

File size: 12.3 KB
RevLine 
[615]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__) %}
[644]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) %}
[615]22#define END_BLOCK {% endcall %}
[685]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() %}
[615]26#define PROLOGUE(level) {% call at_level(level) %}
27#define EPILOGUE(level) {% call at_level(level) %}
[685]28#define BODY(range) {% call body(range) %}
[615]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
[644]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
[615]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
[653]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) %}
[644]59
[615]60{# ----------------------- SEQUENCE, FORALL ----------------------- #}
61
[685]62{% macro sequence_primal() -%}
[615]63!$OMP DO SCHEDULE(STATIC)                                                                           
64  DO ij=1,primal_num
[685]65    {{ caller(body_primal, at_level_primal) }}
[615]66  END DO
67!$OMP END DO
[685]68{%- endmacro %}
[615]69
[685]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
[615]81{%- endmacro %}
82
[685]83{% macro body_primal(range) -%}
[615]84  {{ define('CELL','l,ij') }}
85    DO l = {{ range }}
86      {{ caller() }}
87    END DO
88  {{ undef('CELL') }}
89{%- endmacro %}
90
[685]91{% macro body_edge(range) -%}
92{% set thecode = caller() %}
93{{ define('EDGE', 'l,edge') }}
94{{ cdef(thecode, 'LE_DE', 'le_de(edge)') }}
[919]95{{ cdef(thecode, 'LE', 'le(edge)') }}
96{{ cdef(thecode, 'DE', 'de(edge)') }}
[685]97{{ cdef(thecode, 'SIGN', '1.') }}
98{{ cdef(thecode, 'CELL1', 'l,ij_left') }}
99{{ cdef(thecode, 'CELL2',  'l,ij_right') }}
100{{ cdef(thecode, 'VERTEX1', 'l,ij_down') }}
101{{ cdef(thecode, 'VERTEX2', 'l,ij_up') }}
102    DO l = {{ range }}
103      {{ thecode }}
104    END DO
105{{ cundef(thecode, ('EDGE','LE_DE','SIGN','CELL1','CELL2','VERTEX1','VERTEX2') ) }}
106{%- endmacro %}
107
108{% macro at_level_primal(lev) -%}
109  {{ define('CELL','%s,ij'%lev) }}
[615]110  {{ caller() }}
111  {{ undef('CELL') }}
112{%- endmacro %}
113
[685]114{% macro at_level_edge(lev) -%}
115  {{ define('EDGE','%s,edge'%lev) }}
116  {{ caller() }}
117  {{ undef('EDGE') }}
118{%- endmacro %}
119
[615]120{% macro forall_cells(start='1', end='llm', options=[]) -%}
121  {% set flags=[options] if options is string else options %}
122  {{ caller((start,end),flags) }}
123{%- endmacro %}
124
[650]125{# ---------------------- PRELOAD STENCIL INDICES ---------------------- #}
[615]126
[647]127{% macro get_edges(thecode, mesh,degree) %}
128{% for iedge in range(1,degree+1) %}
[650]129{{ 'edge%d = %s_edge(%d,ij)'%(iedge,mesh,iedge) if 'EDGE' in thecode }}
[647]130{% endfor %}
131{% for iedge in range(1,degree+1) %}
[650]132{{ 'le_de%d = le_de(edge%d)'%(iedge,iedge) if 'LE_DE' in thecode }}     
[647]133{% endfor %}
134{% for iedge in range(1,degree+1) %}
[650]135{{ 'sign%d = %s_ne(%d,ij)'%(iedge,mesh,iedge) if 'SIGN' in thecode }}   
[647]136{% endfor %}
137{% for iedge in range(1,degree+1) %}
138{{ 'ij_up%d = up(edge%d)'%(iedge,iedge) if 'VERTEX1' in thecode }}
139{% endfor %}
140{% for iedge in range(1,degree+1) %}
141{{ 'ij_down%d = down(edge%d)'%(iedge,iedge) if 'VERTEX2' in thecode }}
142{% endfor %}
143{% endmacro %}
144
[650]145{% macro get_vertices(thecode, mesh,degree) %}
146{% for ivertex in range(1,degree+1) %}
147{{ 'vertex%d = %s_vertex(%d,ij)'%(ivertex,mesh,ivertex) if 'VERTEX' in thecode }}
148{% endfor %}
149{% endmacro %}
150
151{# ------------------------------ MESHES --------------------------- #}
152
[644]153{# argument 'code' is the body enclosed by ON_XXX ... END_BLOCK ; it takes arguments : mesh,degree=0 #}
154
155{% macro vloop_unroll(mesh, lrange, flags, code) %}
156
157{% set thecode, has_primal, has_dual, has_trisk, has_none = code(mesh), False, False, False, True %}
158
159{% if 'primal_deg' in thecode %}
160! this VLOOP iterates over primal cell edges
161{% set has_primal, has_none = True,False %}
162{% endif %}
163{% if 'dual_deg' in thecode %}
164! this VLOOP iterates over dual cell edges
165{% set has_dual,has_none = True,False %}
166{% endif %}
167{% if 'trisk_deg' in thecode %}
168! this VLOOP iterates over the TRISK stencil
169{% set has_trisk,has_none = True,False %}
170{% endif %}
171
172{% if has_none %}
173{{ vloop(mesh, lrange, flags, code) }}
174{% endif %}
175
176{% if has_primal %}
177SELECT CASE(primal_deg(ij))
[653]178{% for degree in degree_primal %}
179CASE({{ degree }})
180{{ get_edges(thecode, mesh, degree) }}
181{{ vloop(mesh, lrange, flags, code, degree) }}
182{% endfor %}
[644]183CASE DEFAULT
184{{ vloop(mesh, lrange, flags, code) }}
185END SELECT
186{% endif %}
187
188{% if has_dual %}
189SELECT CASE(dual_deg(ij))
[653]190{% for degree in degree_dual %}
191CASE({{ degree }})
192{{ get_edges(thecode, mesh, degree) }}
193{{ get_vertices(thecode,mesh,degree) }}
194{{ vloop(mesh, lrange, flags, code, degree) }}
195{% endfor %}
[644]196CASE DEFAULT
197{{ vloop(mesh, lrange, flags, code) }}
198END SELECT
199{% endif %}
200
201{% if has_trisk %}
202SELECT CASE(trisk_deg(edge))
[653]203{% for degree in degree_trisk %}
204CASE({{ degree }})
205{{ vloop(mesh, lrange, flags, code, degree) }}
206{% endfor %}
[644]207CASE DEFAULT
208{{ vloop(mesh, lrange, flags, code) }}
209END SELECT
210{% endif %}
211
212{%- endmacro %}
213
214{% macro vloop(mesh, lrange, flags, code, degree=0) %}
215
[615]216{% set start,end = lrange %}
[644]217{% set thecode, is_top_layer, is_top_inter = code(mesh,degree), False, False %}
[615]218
219{{ define('IS_TOP_LAYER', '_FALSE_') }}
220{{ define('IS_TOP_INTERFACE', '_FALSE_') }}
221
222{% if 'IS_BOTTOM_LEVEL' in thecode or 'KDOWN' in thecode%}
223{# the code in the loop checks whether l==1, for the sake of performance
224we shall write special code for l=1 and start the loop at l=2 #}
225{{ define('IS_BOTTOM_LEVEL', '_TRUE_') }}
226{{ 'kdown = 1' if 'KDOWN' in thecode }}
227{{ 'kup   = 1' if 'KUP'   in thecode }}
228l=1
229{{ thecode }}
230{% set start='2' %}
231{% endif %}
232
233{% if 'IS_TOP_LAYER' in thecode %}
234{{ 'ERROR : using IS_TOP_LAYER in a loop ending at l=llm+1' if end=='llm+1' }}
235{# the code checks whether l==llm, write special code for l=llm and end the loop at l=llm-1 #}
236{% set end, is_top_layer = 'llm-1', True %}
237{% endif %}
238
239{% if 'IS_TOP_INTERFACE' in thecode or 'KUP' in thecode %}
240{# the code checks whether l==llm+1, write special code for l=llm+1 and end the loop at l=llm #}
241{{ 'ERROR : using IS_TOP_INTERFACE in a loop ending at l=llm' if end=='llm' }}
242{% set end, is_top_inter ='llm', True %}
243{% endif %}
244
245{{ define('IS_BOTTOM_LEVEL', '_FALSE_') }}
[647]246!DIR$ SIMD
[615]247  DO l = {{start}}, {{end}}
248    {{ 'kdown = l-1' if 'KDOWN' in thecode }}
249    {{ 'kup   = l' if 'KUP'   in thecode }}
250    {{ thecode }}
251  END DO
252
253{% if is_top_layer %}
254{{ define('IS_TOP_LAYER', '_TRUE_') }}
255{{ 'kdown = llm-1' if 'KDOWN' in thecode }}
256{{ 'kup   = llm' if 'KUP'   in thecode }}
257l=llm
258{{ thecode }}
259{% endif %}
260
261{% if is_top_inter %}
262{{ define('IS_TOP_INTERFACE', '_TRUE_') }}
263{{ 'kdown = llm' if 'KDOWN' in thecode }}
264{{ 'kup   = llm' if 'KUP'   in thecode }}
265l=llm+1
266{{ thecode }}
267{% endif %}
268
269{% endmacro %}
270
271{% macro on_mesh(mesh,lrange,flags) -%}
272{{ define('CELL','l,ij') if mesh=='primal' }}
273{{ define('DUAL_CELL', 'l,ij') if mesh=='dual'}}
274!$OMP DO SCHEDULE(STATIC)                                                                           
275DO ij = 1, {{ mesh }}_num
[644]276{{ vloop_unroll(mesh, lrange, flags, caller) }}
[615]277END DO
278!$OMP END DO
279{{ undef('CELL') }}
280{{ undef('DUAL_CELL') }}
281{%- endmacro %}
282
283{# ------------------------------ STENCILS --------------------------- #}
284
285{% macro on_edges(mesh,lrange,flags) -%}
286{% set thecode = caller(mesh) %}
287{{ define('EDGE', 'l,edge') }}
[650]288{{ cdef(thecode, 'LE_DE', 'le_de(edge)') }}
[919]289{{ cdef(thecode, 'DE', 'de(edge)') }}
290{{ cdef(thecode, 'LE', 'le(edge)') }}
[650]291{{ cdef(thecode, 'SIGN', '1.') }}
292{{ cdef(thecode, 'CELL1', 'l,ij_left') }}
293{{ cdef(thecode, 'CELL2',  'l,ij_right') }}
294{{ cdef(thecode, 'VERTEX1', 'l,ij_down') }}
295{{ cdef(thecode, 'VERTEX2', 'l,ij_up') }}
[615]296!$OMP DO SCHEDULE(STATIC)
297DO edge = 1, edge_num
298{{ 'ij_left = left(edge)'   if 'CELL1'    in thecode }}
299{{ 'ij_right = right(edge)' if 'CELL2'   in thecode }}
300{{ 'ij_up = up(edge)'       if 'VERTEX1' in thecode }}
301{{ 'ij_down = down(edge)'   if 'VERTEX2' in thecode }}
[644]302{{ vloop_unroll(mesh, lrange, flags, caller) }}
[615]303END DO
304!$OMP END DO
[650]305{{ cundef(thecode, ('EDGE','LE_DE','SIGN','CELL1','CELL2','VERTEX1','VERTEX2') ) }}
[615]306{%- endmacro %}
307
[644]308{% macro forall_edges(mesh,degree) -%}
[615]309{% set thecode = caller() %}
[644]310
311{% if degree>1 %}
312{% for iedge in range(1,degree+1) %}
[650]313{{ cdef(thecode, 'EDGE', 'l,edge%d'%iedge) }}
314{{ cdef(thecode, 'SIGN', 'sign%d'%iedge) }}
315{{ cdef(thecode, 'LE_DE', 'le_de%d'%iedge) }}
316{{ cdef(thecode, 'VERTEX1', 'l,ij_up%d'%iedge) }}
317{{ cdef(thecode, 'VERTEX2', 'l,ij_down%d'%iedge) }}
[644]318  {{ thecode }}
319{% endfor %}
320{% else %}
[650]321{{ cdef(thecode, 'EDGE', 'l,edge') }}
322{{ cdef(thecode, 'SIGN', mesh + '_ne(iedge,ij)') }}
323{{ cdef(thecode, 'LE_DE', 'le_de(edge)') }}
324{{ cdef(thecode, 'VERTEX1', 'l,ij_up') }}
325{{ cdef(thecode, 'VERTEX2', 'l,ij_down') }}
[615]326DO iedge = 1, {{ mesh }}_deg(ij)
327  edge = {{ mesh }}_edge(iedge,ij)
[644]328  {{ 'ij_up = up(edge)'       if 'VERTEX1' in thecode }}
329  {{ 'ij_down = down(edge)'   if 'VERTEX2' in thecode }}
[615]330  {{ thecode }}
331END DO
[644]332{% endif %}
[650]333{{ cundef(thecode, ('EDGE', 'SIGN', 'LE_DE', 'VERTEX1', 'VERTEX2') ) }}
[615]334{%- endmacro %}
335
[644]336{% macro forall_trisk(degree) -%}
337{% set thecode = caller() %}
[615]338{{ define('EDGE_TRISK', 'l,edge_trisk') }}
[644]339{% if degree>1 %}
340{% for itrisk in range(1,degree+1) %}
[647]341  itrisk = {{ itrisk }}
[644]342  edge_trisk = trisk({{ itrisk }},edge)
343  {{ thecode }}
344{% endfor %}
345{% else %}
[615]346DO itrisk = 1, trisk_deg(edge)
347  edge_trisk = trisk(itrisk,edge)
[644]348  {{ thecode }}
[615]349END DO
[644]350{% endif %}
[615]351{{ undef('EDGE_TRISK') }}
352{%- endmacro %}
353
[644]354{% macro forall_vertices(mesh,degree) -%}
355{% set thecode = caller() %}
356{% if degree>1 %}
357{% for ivertex in range(1,degree+1) %}
[650]358{{ define('RIV2', 'Riv2(%d,ij)'%ivertex ) }}
359{{ define('VERTEX', 'l,vertex%d'%ivertex ) }}
[644]360  {{ thecode }}
361{% endfor %}
362{% else %}
[650]363{{ define('RIV2', 'Riv2(ivertex,ij)') }}
364{{ define('VERTEX', 'l,vertex') }}
[615]365DO ivertex = 1, {{ mesh }}_deg(ij)
366  vertex = {{ mesh }}_vertex(ivertex,ij)
[644]367  {{ thecode }}
[615]368END DO
[644]369{% endif %}
[615]370{{ undef('VERTEX') }}
[650]371{{ undef('RIV2') }}
[615]372{%- endmacro %}
373
374{# --------------------------------------------------------- #}
375
376{% set llm='llm' %}
377
378{{ undef('SIGN') }}
379{{ undef('CELL') }}
380{{ undef('CELL1') }}
381{{ undef('CELL2') }}
382{{ undef('VERTEX1') }}
383{{ undef('VERTEX2') }}
384{{ undef('EDGE_TRISK') }}
385
386{# --------------------- END JINJA ------------------------- #}
387
388#endif
389
390#ifdef PASS_POST1
391
392#define _TRUE_ (0==0)
393#define _FALSE_ (0==1)
394
395#define AI Ai(ij)
396#define AV Av(ij)
397#define FV fv(ij)
[940]398#define WEE wee(itrisk,edge,1)
[615]399#define edge_ne(iedge,ij) 1.
400#endif
401
402#ifdef PASS_POST2
[685]403#define AT_LEVEL(l,ij,lev) lev,ij
[615]404#define KUP(l,ij) kup,ij
405#define KDOWN(l,ij) kdown,ij
406#define DOWN(l,ij) l-1,ij
407#define UP(l,ij) l+1,ij
408#define HIDX(l,ij) ij
409#define VIDX(l,ij) l
410#endif
Note: See TracBrowser for help on using the repository browser.