source: codes/icosagcm/devel/src/unstructured/data_unstructured.F90 @ 744

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

devel : make_icosa option for mixed precision

File size: 9.5 KB
Line 
1MODULE data_unstructured_mod
2  USE ISO_C_BINDING
3  USE OMP_LIB
4  IMPLICIT NONE
5  SAVE
6
7#include "unstructured.h90"
8
9  INTEGER, PARAMETER :: eta_mass=1, eta_lag=2, &
10       thermo_theta=1, thermo_entropy=2, thermo_moist=3, thermo_boussinesq=4, &
11       caldyn_vert_cons=1, max_nb_stage=5
12  INDEX,  BIND(C) :: caldyn_thermo=thermo_theta, caldyn_eta=eta_lag, &
13       caldyn_vert_variant=caldyn_vert_cons, nb_threads=0, nb_stage=0
14  LOGICAL(C_BOOL), BIND(C) :: hydrostatic=.TRUE., debug_hevi_solver=.TRUE.
15
16#ifdef CPP_MIXED_PREC
17  LOGICAL(C_BOOL), BIND(C) :: mixed_precision=.TRUE.
18#else
19  LOGICAL(C_BOOL), BIND(C) :: mixed_precision=.FALSE.
20#endif
21
22  INDEX, BIND(C) :: llm, nqdyn, edge_num, primal_num, dual_num, &
23       max_primal_deg, max_dual_deg, max_trisk_deg
24  INDEX, ALLOCATABLE :: & ! deg(ij) = nb of vertices = nb of edges of primal/dual cell ij
25       primal_deg(:), primal_edge(:,:), primal_vertex(:,:), primal_ne(:,:), & 
26       dual_deg(:), dual_edge(:,:), dual_vertex(:,:), dual_ne(:,:), &
27       trisk_deg(:), trisk(:,:), &
28       left(:), right(:), up(:), down(:)
29  ! left and right are adjacent primal cells
30  ! flux is positive when going from left to right
31  ! up and down are adjacent dual cells
32  ! circulation is positive when going from down to up
33
34  TIME, PARAMETER :: print_trace_interval = 1.
35  TIME, BIND(C) :: elapsed
36  NUM, BIND(C) :: g, ptop, cpp, cppv, Rd, Rv, preff, Treff, pbot, Phi_bot, rho_bot
37  NUM :: kappa
38  NUM1(max_nb_stage), BIND(C)              :: tauj       ! diagonal of fast Butcher tableau
39  NUM2(max_nb_stage,max_nb_stage), BIND(C) :: cslj, cflj ! slow and fast modified Butcher tableaus
40  NUM1(:), ALLOCATABLE            :: le_de, fv, Av, Ai
41  NUM2(:,:), ALLOCATABLE          :: Riv2, wee, ap,bp, mass_bl, mass_dak, mass_dbk
42
43  INTEGER(C_INT), BIND(C) :: comm_icosa, dynamico_mpi_rank=0
44
45  INTEGER, PARAMETER :: id_dev1=1, id_dev2=2, &
46       id_pvort_only=3, id_slow_hydro=4, id_fast=5, id_coriolis=6, id_theta=7, id_geopot=8, id_vert=9, &
47       id_solver=10, id_slow_NH=11, id_NH_geopot=12, id_vert_NH=13, id_update=14, id_halo=15, nb_routines=15 
48  TIME, PRIVATE :: start_time, time_spent(nb_routines) ! time spent in each kernel
49  INTEGER, PRIVATE :: current_id, nb_calls(nb_routines)
50  INTEGER(KIND=8), PRIVATE :: bytes(nb_routines) ! bytes read or written by each kernel
51  CHARACTER(len = 10) :: id_name(nb_routines) = &
52       (/'dev1      ', 'dev2      ', &
53       'pvort_only', 'slow_hydro', 'fast      ', 'coriolis  ', 'theta     ', 'geopot    ', 'vert      ', &
54       'solver    ', 'slow_NH   ', 'NH_geopot ', 'vert_NH   ',  'update    ', 'halo_xchg ' /)
55
56  INTEGER, PARAMETER ::transfer_primal=1, transfer_edge=2, transfer_dual=3, transfer_max=3
57  TYPE Halo_transfer
58     INTEGER :: ranks ! size of arrays rank, len
59     INTEGER, ALLOCATABLE :: rank(:), & ! MPI ranks to communicate with
60          num(:), & ! number of cells to send to / receive from other MPI ranks
61          cells(:) ! local indices of cells to send/receive
62     NUM, ALLOCATABLE :: buf2(:,:)
63  END TYPE Halo_transfer
64  TYPE(Halo_transfer), TARGET :: send_info(transfer_max), recv_info(transfer_max)
65
66CONTAINS
67
68  !----------------------------      PROFILING      --------------------------
69 
70  SUBROUTINE init_trace()
71    !$OMP MASTER
72    time_spent(:)=0.
73    bytes(:)=0
74    nb_calls(:)=0
75    !$OMP END MASTER
76  END SUBROUTINE init_trace
77
78  SUBROUTINE print_trace_() BIND(C, name='dynamico_print_trace')
79    INTEGER :: id
80    TIME :: total_spent
81    total_spent=SUM(time_spent)
82    IF(dynamico_mpi_rank==0) THEN
83       PRINT *, '========================= Performance metrics ========================='
84       PRINT *, 'Total time spent in instrumented code (seconds) :', total_spent
85       PRINT *, 'Name, #calls, %time, microsec/call, MB/sec'   
86       DO id=1,nb_routines
87          IF(nb_calls(id)>0) PRINT *, id_name(id), nb_calls(id), INT(100.*time_spent(id)/total_spent), &
88               INT(1e6*time_spent(id)/nb_calls(id)), INT(1e-6*bytes(id)/time_spent(id))
89       END DO
90    END IF
91  END SUBROUTINE print_trace_
92
93  SUBROUTINE print_trace()
94    !$OMP MASTER
95       IF(SUM(time_spent)>print_trace_interval) THEN
96          CALL print_trace_
97          CALL init_trace()
98       END IF
99    !$OMP END MASTER
100  END SUBROUTINE print_trace
101
102  SUBROUTINE enter_trace(id, nbytes)
103    INTEGER :: id, nbytes
104    !$OMP MASTER
105    current_id = id
106    bytes(id) = bytes(id) + nbytes
107    nb_calls(id)=nb_calls(id)+1
108    start_time = OMP_GET_WTIME()
109    !$OMP END MASTER
110  END SUBROUTINE enter_trace
111
112  SUBROUTINE exit_trace()
113    TIME :: elapsed
114    !$OMP MASTER
115    elapsed = OMP_GET_WTIME()-start_time
116    IF(elapsed<0.) elapsed=0.
117    time_spent(current_id) = time_spent(current_id) + elapsed
118    !$OMP END MASTER
119  END SUBROUTINE exit_trace
120
121  !---------------------------- CONTEXT INITIALIZATION --------------------------
122
123#define ALLOC1(v,n1) IF(ALLOCATED(v)) DEALLOCATE(v) ; ALLOCATE(v(n1))
124#define ALLOC2(v,n1,n2) IF(ALLOCATED(v)) DEALLOCATE(v) ; ALLOCATE(v(n1,n2))
125
126  SUBROUTINE init_mesh( & 
127       primal_deg_, primal_edge_, primal_ne_, &
128       dual_deg_, dual_edge_, dual_ne_, dual_vertex_, &
129       left_, right_, up_, down_ ,&
130       trisk_deg_, trisk_) BINDC(init_mesh)
131    INDEX :: primal_deg_(primal_num), primal_edge_(max_primal_deg,primal_num), &
132         primal_ne_(max_primal_deg,primal_num), &
133         dual_deg_(dual_num), dual_edge_(max_dual_deg,dual_num), &
134         dual_ne_(max_dual_deg,dual_num), &
135         dual_vertex_(max_dual_deg,dual_num), &
136         trisk_deg_(edge_num), trisk_(max_trisk_deg, edge_num)
137    INDEX, DIMENSION(edge_num) :: left_, right_, down_, up_
138
139    PRINT *, 'init_mesh ...'
140    PRINT *, 'Primal mesh : ', primal_num, max_primal_deg
141    PRINT *, 'Dual mesh   : ', dual_num, max_dual_deg
142    PRINT *, 'Edge mesh   : ', edge_num, max_trisk_deg
143    PRINT *, 'Vertical levels :', llm
144    ALLOC1(primal_deg, primal_num)
145    ALLOC2(primal_edge, max_primal_deg,primal_num)
146    ALLOC2(primal_ne, max_primal_deg,primal_num)
147    ALLOC1(dual_deg,dual_num)
148    ALLOC2(dual_edge, max_dual_deg,dual_num)
149    ALLOC2(dual_ne, max_dual_deg,dual_num)
150    ALLOC2(dual_vertex, max_dual_deg,dual_num)
151    ALLOC1(trisk_deg, edge_num)
152    ALLOC2(trisk, max_trisk_deg, edge_num)
153    PRINT *, SHAPE(trisk), edge_num
154    ALLOC1(left, edge_num)
155    ALLOC1(right, edge_num)
156    ALLOC1(up, edge_num)
157    ALLOC1(down, edge_num)
158    primal_deg(:) = primal_deg_(:)
159    primal_edge(:,:) = primal_edge_(:,:)
160    primal_ne(:,:) = primal_ne_(:,:)
161    dual_deg(:) = dual_deg_(:)
162    dual_edge(:,:) = dual_edge_(:,:)
163    dual_ne(:,:) = dual_ne_(:,:)
164    dual_vertex(:,:) = dual_vertex_(:,:)
165    IF(MINVAL(dual_deg)<3) THEN
166       STOP 'At least one dual cell has less than 3 vertices'
167    END IF
168    IF(MINVAL(primal_deg)<3) THEN
169       STOP 'At least one primal cell has less than 3 vertices'
170    END IF
171    left(:)=left_(:)
172    right(:)=right_(:)
173    down(:)=down_(:)
174    up=up_(:)
175    trisk_deg(:)=trisk_deg_(:)
176    trisk(:,:)=trisk_(:,:)
177    PRINT *, MAXVAL(primal_edge), edge_num
178    PRINT *, MAXVAL(dual_edge), edge_num
179    PRINT *, MAXVAL(dual_vertex), dual_num
180    PRINT *, MAXVAL(trisk), edge_num
181    PRINT *, MAX(MAXVAL(left),MAXVAL(right)), primal_num
182    PRINT *, MAX(MAXVAL(up),MAXVAL(down)), dual_num
183    PRINT *, SHAPE(trisk), edge_num
184    PRINT *,' ... Done.'
185  END SUBROUTINE init_mesh
186
187  ! Input arrays to init_metric and init_hybrid are declared DBL
188  ! => always float64 on the Python side
189  ! They are copied to Fortran arrays of type NUM (float or double)
190
191  SUBROUTINE init_metric(Ai_, Av_, fv_, le_de_, Riv2_, wee_) BINDC(init_metric)
192    DBL :: Ai_(primal_num), Av_(dual_num), fv_(dual_num), le_de_(edge_num), &
193         Riv2_(max_dual_deg,dual_num), wee_(max_trisk_deg,edge_num)
194    PRINT *, 'init_metric ...'
195    ALLOC1(Ai,primal_num)
196    ALLOC1(Av,dual_num)
197    ALLOC1(fv,dual_num)
198    ALLOC1(le_de,edge_num)
199    ALLOC2(Riv2, max_dual_deg, dual_num)
200    ALLOC2(wee, max_trisk_deg, edge_num)
201    Ai(:) = Ai_(:)
202    Av(:) = Av_(:)
203    fv(:) = fv_(:)
204    le_de(:) = le_de_(:)
205    Riv2(:,:)=Riv2_(:,:)
206    wee(:,:) = wee_(:,:)
207    PRINT *, MAXVAL(ABS(Ai))
208    PRINT *, MAXVAL(ABS(Av))
209    PRINT *, MAXVAL(ABS(fv))
210    PRINT *, MAXVAL(ABS(le_de))
211    PRINT *, MAXVAL(ABS(Riv2))
212    PRINT *, MAXVAL(ABS(wee))
213    PRINT *, MINVAL(right), MAXVAL(right)
214    PRINT *, MINVAL(right), MAXVAL(left)
215    PRINT *,' ... Done.'
216    IF(nb_threads==0) nb_threads=OMP_GET_MAX_THREADS()
217    PRINT *,'OpenMP : max_threads, num_procs, nb_threads', OMP_GET_MAX_THREADS(), OMP_GET_NUM_PROCS(), nb_threads
218  END SUBROUTINE init_metric
219  !
220  SUBROUTINE show_openmp() BINDC(show_openmp)
221    PRINT *,'OpenMP : max_threads, num_procs', OMP_GET_MAX_THREADS(), OMP_GET_NUM_PROCS()
222  END SUBROUTINE show_openmp
223  !
224  SUBROUTINE init_params() BINDC(init_params)
225    PRINT *, 'Setting physical parameters ...'
226    IF(hydrostatic) THEN
227       PRINT *, 'Hydrostatic dynamics (HPE)'
228    ELSE
229       PRINT *, 'Non-hydrostatic dynamics (Euler)'
230    END IF
231    kappa = Rd/cpp
232    PRINT *, 'g = ',g
233    PRINT *, 'preff = ',preff
234    PRINT *, 'Treff = ',Treff
235    PRINT *, 'Rd = ',Rd
236    PRINT *, 'cpp = ',cpp
237    PRINT *, 'kappa = ',kappa
238    PRINT *, '... Done'
239    CALL init_trace
240  END SUBROUTINE init_params
241  !
242  SUBROUTINE init_hybrid(bl,dak,dbk) BINDC(init_hybrid)
243    DBL :: bl(llm+1, primal_num), &
244         dak(llm, primal_num), dbk(llm, primal_num)
245    PRINT *, 'Setting hybrid coefficients ...'
246    ALLOC2(mass_bl, llm+1, primal_num)
247    ALLOC2(mass_dak, llm, primal_num)
248    ALLOC2(mass_dbk, llm, primal_num)
249    mass_bl(:,:)  = bl(:,:)
250    mass_dak(:,:) = dak(:,:)
251    mass_dbk(:,:) = dbk(:,:)
252    PRINT *, '... Done, llm = ', llm
253  END SUBROUTINE Init_hybrid
254
255END MODULE data_unstructured_mod
Note: See TracBrowser for help on using the repository browser.