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

Last change on this file since 644 was 644, checked in by dubos, 7 years ago

devel/unstructured : unroll loops over stencils

File size: 9.5 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 {% call sequence() %}
24#define SEQUENCE_EXT {% call sequence() %}
25#define PROLOGUE(level) {% call at_level(level) %}
26#define EPILOGUE(level) {% call at_level(level) %}
27#define BODY(range) {% call(cell_up,cell_down) body(range) %}
28
29#define CST_IF(condition, action) {{ cst_if(#condition, #action) }}
30#define CST_IFTHEN(condition) {{flat}}if condition
31#define CST_ELSEIF(condition) {{flat}}elif condition
32#define CST_ELSE {{flat}}else
33#define CST_ENDIF {{flat}}endif
34
35#endif
36
37#ifdef PASS_JINJA
38
39{#  -------------------------- Design notes ------------------------------
40
41The syntax
42{% call(ARGNAMES) macro(ARGS) %}
43...
44{% endcall %}
45passes ARGS to macro ; this macro "calls" the body using the syntax 'caller(arg1,...)' ; these arguments
46are available in the body under the names ARGNAMES, as if it were a macro caller(ARGNAMES).
47
48Using its optional argument 'options', forall_cells() sets variable 'flags'
49and passes it on to on_mesh() / on_edges()
50
51Similarly variable 'lrange' is passed from forall_cells to on_mesh() / on_egdes() 
52
53-------------------------------------------------------------------------- #}
54
55
56{# ----------------------- SEQUENCE, FORALL ----------------------- #}
57
58{% macro sequence() -%}
59 
60!$OMP DO SCHEDULE(STATIC)                                                                           
61  DO ij=1,primal_num
62    {{ caller() }}
63  END DO
64!$OMP END DO
65
66{%- endmacro %}
67
68{% macro body(range) -%}
69  {{ define('CELL','l,ij') }}
70    DO l = {{ range }}
71      {{ caller() }}
72    END DO
73  {{ undef('CELL') }}
74{%- endmacro %}
75
76{% macro at_level(lev) -%}
77  {{ define('CELL','l,ij') }}
78  l={{ lev }}
79  {{ caller() }}
80  {{ undef('CELL') }}
81{%- endmacro %}
82
83{% macro forall_cells(start='1', end='llm', options=[]) -%}
84  {% set flags=[options] if options is string else options %}
85  {{ caller((start,end),flags) }}
86{%- endmacro %}
87
88{# ------------------------------ MESHES --------------------------- #}
89
90{# argument 'code' is the body enclosed by ON_XXX ... END_BLOCK ; it takes arguments : mesh,degree=0 #}
91
92{% macro vloop_unroll(mesh, lrange, flags, code) %}
93
94{% set thecode, has_primal, has_dual, has_trisk, has_none = code(mesh), False, False, False, True %}
95
96{% if 'primal_deg' in thecode %}
97! this VLOOP iterates over primal cell edges
98{% set has_primal, has_none = True,False %}
99{% endif %}
100{% if 'dual_deg' in thecode %}
101! this VLOOP iterates over dual cell edges
102{% set has_dual,has_none = True,False %}
103{% endif %}
104{% if 'trisk_deg' in thecode %}
105! this VLOOP iterates over the TRISK stencil
106{% set has_trisk,has_none = True,False %}
107{% endif %}
108
109{% if has_none %}
110{{ vloop(mesh, lrange, flags, code) }}
111{% endif %}
112
113{% if has_primal %}
114SELECT CASE(primal_deg(ij))
115CASE(4)
116{{ vloop(mesh, lrange, flags, code, 4) }}
117CASE(5)
118{{ vloop(mesh, lrange, flags, code, 5) }}
119CASE(6)
120{{ vloop(mesh, lrange, flags, code, 6) }}
121CASE DEFAULT
122{{ vloop(mesh, lrange, flags, code) }}
123END SELECT
124{% endif %}
125
126{% if has_dual %}
127SELECT CASE(dual_deg(ij))
128CASE(3)
129{{ vloop(mesh, lrange, flags, code, 3) }}
130CASE(4)
131{{ vloop(mesh, lrange, flags, code, 4) }}
132CASE DEFAULT
133{{ vloop(mesh, lrange, flags, code) }}
134END SELECT
135{% endif %}
136
137{% if has_trisk %}
138SELECT CASE(trisk_deg(edge))
139CASE(10)
140{{ vloop(mesh, lrange, flags, code, 10) }}
141CASE(4)
142{{ vloop(mesh, lrange, flags, code, 4) }}
143CASE DEFAULT
144{{ vloop(mesh, lrange, flags, code) }}
145END SELECT
146{% endif %}
147
148{%- endmacro %}
149
150{% macro vloop(mesh, lrange, flags, code, degree=0) %}
151
152{% set start,end = lrange %}
153{% set thecode, is_top_layer, is_top_inter = code(mesh,degree), False, False %}
154
155{{ define('IS_TOP_LAYER', '_FALSE_') }}
156{{ define('IS_TOP_INTERFACE', '_FALSE_') }}
157
158{% if 'IS_BOTTOM_LEVEL' in thecode or 'KDOWN' in thecode%}
159{# the code in the loop checks whether l==1, for the sake of performance
160we shall write special code for l=1 and start the loop at l=2 #}
161{{ define('IS_BOTTOM_LEVEL', '_TRUE_') }}
162{{ 'kdown = 1' if 'KDOWN' in thecode }}
163{{ 'kup   = 1' if 'KUP'   in thecode }}
164l=1
165{{ thecode }}
166{% set start='2' %}
167{% endif %}
168
169{% if 'IS_TOP_LAYER' in thecode %}
170{{ 'ERROR : using IS_TOP_LAYER in a loop ending at l=llm+1' if end=='llm+1' }}
171{# the code checks whether l==llm, write special code for l=llm and end the loop at l=llm-1 #}
172{% set end, is_top_layer = 'llm-1', True %}
173{% endif %}
174
175{% if 'IS_TOP_INTERFACE' in thecode or 'KUP' in thecode %}
176{# the code checks whether l==llm+1, write special code for l=llm+1 and end the loop at l=llm #}
177{{ 'ERROR : using IS_TOP_INTERFACE in a loop ending at l=llm' if end=='llm' }}
178{% set end, is_top_inter ='llm', True %}
179{% endif %}
180
181{{ define('IS_BOTTOM_LEVEL', '_FALSE_') }}
182  DO l = {{start}}, {{end}}
183    {{ 'kdown = l-1' if 'KDOWN' in thecode }}
184    {{ 'kup   = l' if 'KUP'   in thecode }}
185    {{ thecode }}
186  END DO
187
188{% if is_top_layer %}
189{{ define('IS_TOP_LAYER', '_TRUE_') }}
190{{ 'kdown = llm-1' if 'KDOWN' in thecode }}
191{{ 'kup   = llm' if 'KUP'   in thecode }}
192l=llm
193{{ thecode }}
194{% endif %}
195
196{% if is_top_inter %}
197{{ define('IS_TOP_INTERFACE', '_TRUE_') }}
198{{ 'kdown = llm' if 'KDOWN' in thecode }}
199{{ 'kup   = llm' if 'KUP'   in thecode }}
200l=llm+1
201{{ thecode }}
202{% endif %}
203
204{% endmacro %}
205
206{% macro on_mesh(mesh,lrange,flags) -%}
207{{ define('CELL','l,ij') if mesh=='primal' }}
208{{ define('DUAL_CELL', 'l,ij') if mesh=='dual'}}
209!$OMP DO SCHEDULE(STATIC)                                                                           
210DO ij = 1, {{ mesh }}_num
211{{ vloop_unroll(mesh, lrange, flags, caller) }}
212END DO
213!$OMP END DO
214{{ undef('CELL') }}
215{{ undef('DUAL_CELL') }}
216{%- endmacro %}
217
218{# ------------------------------ STENCILS --------------------------- #}
219
220{% macro on_edges(mesh,lrange,flags) -%}
221{% set thecode = caller(mesh) %}
222{{ define('EDGE', 'l,edge') }}
223{{ define('LE_DE', 'le_de(edge)') }}
224{{ define('SIGN', '1.') }}
225{{ define('CELL1', 'l,ij_left') }}
226{{ define('CELL2',  'l,ij_right') }}
227{{ define('VERTEX1', 'l,ij_down') }}
228{{ define('VERTEX2', 'l,ij_up') }}
229!$OMP DO SCHEDULE(STATIC)
230DO edge = 1, edge_num
231{{ 'ij_left = left(edge)'   if 'CELL1'    in thecode }}
232{{ 'ij_right = right(edge)' if 'CELL2'   in thecode }}
233{{ 'ij_up = up(edge)'       if 'VERTEX1' in thecode }}
234{{ 'ij_down = down(edge)'   if 'VERTEX2' in thecode }}
235{{ vloop_unroll(mesh, lrange, flags, caller) }}
236END DO
237!$OMP END DO
238{{ undef('EDGE') }}
239{{ undef('LE_DE') }}
240{{ undef('SIGN') }}
241{{ undef('CELL1') }}
242{{ undef('CELL2') }}
243{{ undef('VERTEX1') }}
244{{ undef('VERTEX2') }}
245{%- endmacro %}
246
247{% macro forall_edges(mesh,degree) -%}
248{% set thecode = caller() %}
249{{ define('EDGE', 'l,edge') }}
250{{ define('VERTEX1', 'l,ij_down') }}
251{{ define('VERTEX2', 'l,ij_up') }}
252{{ define('SIGN', mesh + '_ne(iedge,ij)') }}
253{{ define('LE_DE', 'le_de(edge)') }}
254
255{% if degree>1 %}
256{% for iedge in range(1,degree+1) %}
257  iedge = {{ iedge }}
258  edge = {{ mesh }}_edge({{ iedge }},ij)
259  {{ 'ij_up = up(edge)'       if 'VERTEX1' in thecode }}
260  {{ 'ij_down = down(edge)'   if 'VERTEX2' in thecode }}
261  {{ thecode }}
262{% endfor %}
263{% else %}
264DO iedge = 1, {{ mesh }}_deg(ij)
265  edge = {{ mesh }}_edge(iedge,ij)
266  {{ 'ij_up = up(edge)'       if 'VERTEX1' in thecode }}
267  {{ 'ij_down = down(edge)'   if 'VERTEX2' in thecode }}
268  {{ thecode }}
269END DO
270{% endif %}
271
272{{ undef('EDGE') }}
273{{ undef('SIGN') }}
274{{ undef('LE_DE') }}
275{%- endmacro %}
276
277{% macro forall_trisk(degree) -%}
278{% set thecode = caller() %}
279{{ define('EDGE_TRISK', 'l,edge_trisk') }}
280{% if degree>1 %}
281{% for itrisk in range(1,degree+1) %}
282  edge_trisk = trisk({{ itrisk }},edge)
283  {{ thecode }}
284{% endfor %}
285{% else %}
286DO itrisk = 1, trisk_deg(edge)
287  edge_trisk = trisk(itrisk,edge)
288  {{ thecode }}
289END DO
290{% endif %}
291{{ undef('EDGE_TRISK') }}
292{%- endmacro %}
293
294{% macro forall_vertices(mesh,degree) -%}
295{% set thecode = caller() %}
296{{ define('VERTEX', 'l,vertex') }}
297{% if degree>1 %}
298{% for ivertex in range(1,degree+1) %}
299  ivertex = {{ ivertex }}
300  vertex = {{ mesh }}_vertex({{ ivertex }},ij)
301  {{ thecode }}
302{% endfor %}
303{% else %}
304DO ivertex = 1, {{ mesh }}_deg(ij)
305  vertex = {{ mesh }}_vertex(ivertex,ij)
306  {{ thecode }}
307END DO
308{% endif %}
309{{ undef('VERTEX') }}
310{%- endmacro %}
311
312{# --------------------------------------------------------- #}
313
314{% set llm='llm' %}
315
316{{ undef('SIGN') }}
317{{ undef('CELL') }}
318{{ undef('CELL1') }}
319{{ undef('CELL2') }}
320{{ undef('VERTEX1') }}
321{{ undef('VERTEX2') }}
322{{ undef('EDGE_TRISK') }}
323
324{# --------------------- END JINJA ------------------------- #}
325
326#endif
327
328#ifdef PASS_POST1
329
330#define _TRUE_ (0==0)
331#define _FALSE_ (0==1)
332
333#define RIV2 Riv2(ivertex,ij)
334#define AI Ai(ij)
335#define AV Av(ij)
336#define FV fv(ij)
337#define WEE wee(itrisk,edge)
338#define edge_ne(iedge,ij) 1.
339#endif
340
341#ifdef PASS_POST2
342#define KUP(l,ij) kup,ij
343#define KDOWN(l,ij) kdown,ij
344#define DOWN(l,ij) l-1,ij
345#define UP(l,ij) l+1,ij
346#define HIDX(l,ij) ij
347#define VIDX(l,ij) l
348#endif
Note: See TracBrowser for help on using the repository browser.