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

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

devel/unstructured : streamline loop unrolling

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