New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
multi.f90 in branches/2015/nemo_v3_6_STABLE/NEMOGCM/TOOLS/SIREN/src – NEMO

source: branches/2015/nemo_v3_6_STABLE/NEMOGCM/TOOLS/SIREN/src/multi.f90 @ 5608

Last change on this file since 5608 was 5608, checked in by jpaul, 9 years ago

commit changes/bugfix/... for SIREN; see ticket #1580

File size: 16.5 KB
Line 
1!----------------------------------------------------------------------
2! NEMO system team, System and Interface for oceanic RElocable Nesting
3!----------------------------------------------------------------------
4!
5! MODULE: multi
6!
7! DESCRIPTION:
8!> This module manage multi file structure.
9!
10!> @details
11!>    define type TMULTI:<br/>
12!> @code
13!>    TYPE(TMULTI) :: tl_multi
14!> @endcode
15!>
16!>    to initialize a multi-file structure:<br/>
17!> @code
18!>    tl_multi=multi_init(cd_varfile(:))
19!> @endcode
20!>       - cd_varfile : array of variable with file path
21!>       ('var1:file1','var2:file2')<br/>
22!>          file path could be replaced by a matrix of value.<br/>
23!>          separators used to defined matrix are:
24!>             - ',' for line
25!>             - '/' for row
26!>             - '\' for level<br/>
27!>             Example:<br/>
28!>                - 'var1:3,2,3/1,4,5'
29!>                - 3,2,3/1,4,5  => 
30!>                      @f$ \left( \begin{array}{ccc}
31!>                           3 & 2 & 3 \\
32!>                           1 & 4 & 5 \end{array} \right) @f$<br/>
33!>
34!>    to get the number of mpp file in mutli file structure:<br/>
35!>    - tl_multi\%i_nmpp
36!>
37!>    to get the total number of variable in mutli file structure:<br/>
38!>    - tl_multi\%i_nvar
39!>
40!>    @note number of variable and number of file could differ cause several variable
41!>    could be in the same file.
42!>
43!>    to get array of mpp structure in mutli file structure:<br/>
44!>    - tl_multi\%t_mpp(:)
45!>
46!>    to print information about multi structure:<br/>
47!> @code
48!>    CALL multi_print(td_multi)
49!> @endcode
50!>
51!>    to clean multi file strucutre:<br/>
52!> @code
53!>    CALL multi_clean(td_multi)
54!> @endcode
55!>       - td_multi is multi file structure
56!>
57!> @author
58!>  J.Paul
59! REVISION HISTORY:
60!> @date November, 2013 - Initial Version
61!> @date October, 2014
62!> - use mpp file structure instead of file
63!> @date November, 2014 - Fix memory leaks bug
64!
65!> @note Software governed by the CeCILL licence     (NEMOGCM/NEMO_CeCILL.txt)
66!----------------------------------------------------------------------
67MODULE multi
68   USE kind                            ! F90 kind parameter
69   USE logger                          ! log file manager
70   USE fct                             ! basic useful function
71   USE dim                             ! dimension manager
72   USE var                             ! variable manager
73   USE file                            ! file manager
74   USE iom                             ! I/O manager
75   USE mpp                             ! MPP manager
76   USE iom_mpp                         ! MPP I/O manager
77
78   IMPLICIT NONE
79   ! NOTE_avoid_public_variables_if_possible
80
81   ! type and variable
82   PUBLIC :: TMULTI       !< multi file structure
83
84   ! function and subroutine
85   PUBLIC :: multi_copy        !< copy multi structure
86   PUBLIC :: multi_init        !< initialise multi structure
87   PUBLIC :: multi_clean       !< clean multi strcuture
88   PUBLIC :: multi_print       !< print information about milti structure
89
90   PUBLIC :: multi__add_mpp    !< add file strucutre to multi file structure
91   PRIVATE :: multi__copy_unit !< copy multi file structure
92
93   TYPE TMULTI !< multi file structure
94      ! general
95      INTEGER(i4)                         :: i_nmpp  = 0         !< number of mpp files
96      INTEGER(i4)                         :: i_nvar  = 0         !< total number of variables
97      TYPE(TMPP) , DIMENSION(:), POINTER  :: t_mpp => NULL()     !< mpp files composing multi
98   END TYPE
99
100   INTERFACE multi_copy
101      MODULE PROCEDURE multi__copy_unit   ! copy multi file structure
102   END INTERFACE   
103
104CONTAINS
105   !-------------------------------------------------------------------
106   !> @brief
107   !> This function copy multi mpp structure in another one
108   !> @details
109   !> file variable value are copied in a temporary array,
110   !> so input and output file structure value do not point on the same
111   !> "memory cell", and so on are independant.
112   !>
113   !> @warning do not use on the output of a function who create or read an
114   !> attribute (ex: tl_att=att_copy(att_init()) is forbidden).
115   !> This will create memory leaks.
116   !> @warning to avoid infinite loop, do not use any function inside
117   !> this subroutine
118   !>   
119   !> @author J.Paul
120   !> - November, 2013- Initial Version
121   !> @date November, 2014
122   !>    - use function instead of overload assignment operator (to avoid memory leak)
123   !>
124   !> @param[in] td_multi    mpp structure
125   !> @return copy of input multi structure
126   !-------------------------------------------------------------------
127   FUNCTION multi__copy_unit( td_multi )
128      IMPLICIT NONE
129      ! Argument
130      TYPE(TMULTI), INTENT(IN)  :: td_multi
131      ! function
132      TYPE(TMULTI) :: multi__copy_unit
133
134      ! local variable
135      TYPE(TMPP) :: tl_mpp
136
137      ! loop indices
138      INTEGER(i4) :: ji
139      !----------------------------------------------------------------
140
141      multi__copy_unit%i_nmpp = td_multi%i_nmpp
142      multi__copy_unit%i_nvar = td_multi%i_nvar
143
144      ! copy variable structure
145      IF( ASSOCIATED(multi__copy_unit%t_mpp) )THEN
146         CALL mpp_clean(multi__copy_unit%t_mpp(:))
147         DEALLOCATE(multi__copy_unit%t_mpp)
148      ENDIF
149      IF( ASSOCIATED(td_multi%t_mpp) .AND. multi__copy_unit%i_nmpp > 0 )THEN
150         ALLOCATE( multi__copy_unit%t_mpp(multi__copy_unit%i_nmpp) )
151         DO ji=1,multi__copy_unit%i_nmpp
152            tl_mpp = mpp_copy(td_multi%t_mpp(ji))
153            multi__copy_unit%t_mpp(ji) = mpp_copy(tl_mpp)
154         ENDDO
155         ! clean
156         CALL mpp_clean(tl_mpp)
157      ENDIF
158
159   END FUNCTION multi__copy_unit
160   !-------------------------------------------------------------------
161   !> @brief This subroutine initialize multi file structure.
162   !>
163   !> @details
164   !> if variable name is 'all', add all the variable of the file in mutli file
165   !> structure.
166   !> @note if first character of filename is numeric, assume matrix is given as
167   !> input.<br/>
168   !> create pseudo file named 'data-*', with matrix read as variable value.
169   !>
170   !> @author J.Paul
171   !> - November, 2013- Initial Version
172   !> @date July, 2015 - check if variable to be read is in file
173   !>
174   !> @param[in] cd_varfile   variable location information (from namelist)
175   !> @return multi file structure
176   !-------------------------------------------------------------------
177   FUNCTION multi_init(cd_varfile)
178      IMPLICIT NONE
179
180      ! Argument
181      CHARACTER(LEN=*), DIMENSION(:), INTENT(IN) :: cd_varfile
182
183      ! function
184      TYPE(TMULTI) :: multi_init
185
186      ! local variable
187      CHARACTER(LEN=lc) :: cl_name
188      CHARACTER(LEN=lc) :: cl_lower
189      CHARACTER(LEN=lc) :: cl_file
190      CHARACTER(LEN=lc) :: cl_matrix
191
192      INTEGER(i4)       :: il_nvar
193      INTEGER(i4)       :: il_varid
194
195      LOGICAL           :: ll_dim
196
197      TYPE(TVAR)        :: tl_var
198
199      TYPE(TMPP)        :: tl_mpp
200
201      ! loop indices
202      INTEGER(i4) :: ji
203      INTEGER(i4) :: jj
204      INTEGER(i4) :: jk
205      !----------------------------------------------------------------
206
207      ji=1
208      DO WHILE( TRIM(cd_varfile(ji)) /= '' )
209
210         il_nvar=0
211         cl_name=fct_split(cd_varfile(ji),1,':')
212         cl_lower=fct_lower(cl_name)
213         cl_file=fct_split(cd_varfile(ji),2,':')
214
215         IF( LEN(TRIM(cl_file)) == lc )THEN
216            CALL logger_fatal("MULTI INIT: file name too long (==256)."//&
217            &  " check namelist.")
218         ENDIF
219
220         IF( TRIM(cl_lower) /= '' )THEN
221            IF( TRIM(cl_file) /= '' )THEN
222               cl_matrix=''
223               IF( fct_is_num(cl_file(1:1)) )THEN
224                  cl_matrix=TRIM(cl_file)
225                  WRITE(cl_file,'(a,i2.2)')'data-',ji
226
227                  tl_var=var_init(TRIM(cl_name))
228                  CALL var_read_matrix(tl_var, cl_matrix)
229
230                  ! create mpp structure
231                  tl_mpp=mpp_init(TRIM(cl_file), tl_var)
232
233                  ! add variable
234                  CALL mpp_add_var(tl_mpp,tl_var)
235
236                  ! number of variable
237                  il_nvar=il_nvar+1
238
239               ELSE
240
241                  !
242                  tl_mpp=mpp_init( file_init(TRIM(cl_file)) )
243
244                  ! define variable
245                  IF( TRIM(fct_lower(cl_lower)) /= 'all' )THEN
246
247                     ! check if variable is in file
248                     il_varid=var_get_index(tl_mpp%t_proc(1)%t_var(:),cl_lower)
249                     IF( il_varid == 0 )THEN
250                        CALL logger_fatal("MULTI INIT: variable "//&
251                           & TRIM(cl_name)//" not in file "//&
252                           & TRIM(cl_file) )
253                     ENDIF
254
255                     ! clean var
256                     CALL mpp_del_var(tl_mpp)
257
258                     tl_var=var_init(TRIM(cl_lower))
259
260                     ! add variable
261                     CALL mpp_add_var(tl_mpp,tl_var)
262
263                     ! number of variable
264                     il_nvar=il_nvar+1
265
266                     ! clean structure
267                     CALL var_clean(tl_var)
268
269                  ELSE ! cl_lower == 'all'
270
271                     DO jk=tl_mpp%t_proc(1)%i_nvar,1,-1
272                       
273                        ! check if variable is dimension
274                        ll_dim=.FALSE.
275                        DO jj=1,ip_maxdim
276                           IF( TRIM(tl_mpp%t_proc(1)%t_dim(jj)%c_name) == &
277                           &   TRIM(tl_mpp%t_proc(1)%t_var(jk)%c_name) )THEN
278                              ll_dim=.TRUE.
279                              CALL logger_trace("MULTI INIT: "//&
280                              &  TRIM(tl_mpp%t_proc(1)%t_var(jk)%c_name)//&
281                              &  ' is var dimension')
282                              EXIT
283                           ENDIF
284                        ENDDO
285                        ! do not use variable dimension
286                        IF( ll_dim )THEN
287                           tl_var=var_init( &
288                           &  TRIM(tl_mpp%t_proc(1)%t_var(jk)%c_name) )
289                           ! delete variable
290                           CALL mpp_del_var(tl_mpp,tl_var)
291                           ! clean structure
292                           CALL var_clean(tl_var)
293                        ELSE
294                           ! number of variable
295                           il_nvar=il_nvar+1
296                        ENDIF
297
298                     ENDDO
299
300                  ENDIF
301
302               ENDIF
303
304               CALL multi__add_mpp(multi_init, tl_mpp) 
305
306               ! update total number of variable
307               multi_init%i_nvar=multi_init%i_nvar+il_nvar
308
309               ! clean
310               CALL mpp_clean(tl_mpp)
311
312            ELSE
313               CALL logger_error("MULTI INIT: file name matching variable "//&
314               &                 TRIM(cl_name)//" is empty. check namelist.")
315            ENDIF
316         ELSE
317            CALL logger_error("MULTI INIT: variable name "//&
318            &                 "is empty. check namelist.")
319         ENDIF
320
321         ji=ji+1
322      ENDDO
323
324   END FUNCTION multi_init
325   !-------------------------------------------------------------------
326   !> @brief This subroutine clean multi file strucutre.
327   !
328   !> @author J.Paul
329   !> - November, 2013- Initial Version
330   !
331   !> @param[in] td_multi  multi file structure
332   !-------------------------------------------------------------------
333   SUBROUTINE multi_clean(td_multi)
334      IMPLICIT NONE
335
336      ! Argument     
337      TYPE(TMULTI), INTENT(INOUT) :: td_multi
338
339      ! local variable
340      TYPE(TMULTI) :: tl_multi ! empty multi file structure
341
342      ! loop indices
343      !----------------------------------------------------------------
344
345      CALL logger_info( " CLEAN: reset multi file " )
346
347      IF( ASSOCIATED( td_multi%t_mpp ) )THEN
348         CALL mpp_clean(td_multi%t_mpp(:))
349         DEALLOCATE(td_multi%t_mpp)
350      ENDIF
351
352      ! replace by empty structure
353      td_multi=multi_copy(tl_multi)
354
355   END SUBROUTINE multi_clean
356   !-------------------------------------------------------------------
357   !> @brief This subroutine print some information about mpp strucutre.
358   !
359   !> @author J.Paul
360   !> - November, 2013- Initial Version
361   !
362   !> @param[in] td_multi multi file structure
363   !-------------------------------------------------------------------
364   SUBROUTINE multi_print(td_multi)
365      IMPLICIT NONE
366
367      ! Argument     
368      TYPE(TMULTI), INTENT(IN) :: td_multi
369
370      ! local variable
371
372      ! loop indices
373      INTEGER(i4) :: ji
374      INTEGER(i4) :: jj
375      !----------------------------------------------------------------
376
377      ! print file
378      IF( td_multi%i_nmpp /= 0 .AND. ASSOCIATED(td_multi%t_mpp) )THEN
379         WRITE(*,'(/a,i3)') 'MULTI: total number of mpp: ',&
380         &  td_multi%i_nmpp
381         WRITE(*,'(6x,a,i3)') ' total number of variable: ',&
382         &  td_multi%i_nvar
383         DO ji=1,td_multi%i_nmpp
384            WRITE(*,'(3x,3a)') 'MPP FILE ',TRIM(td_multi%t_mpp(ji)%c_name),&
385            & ' CONTAINS'
386            DO jj=1,td_multi%t_mpp(ji)%t_proc(1)%i_nvar
387               IF( ASSOCIATED(td_multi%t_mpp(ji)%t_proc(1)%t_var) )THEN
388                  WRITE(*,'(6x,a)') &
389                  &  TRIM(td_multi%t_mpp(ji)%t_proc(1)%t_var(jj)%c_name)
390               ENDIF
391            ENDDO
392         ENDDO
393      ENDIF
394
395   END SUBROUTINE multi_print
396   !-------------------------------------------------------------------
397   !> @brief
398   !>    This subroutine add file to multi file structure.
399   !>
400   !> @detail
401   !
402   !> @author J.Paul
403   !> - November, 2013- Initial Version
404   !> @date October, 2014
405   !> - use mpp file structure instead of file
406   !
407   !> @param[inout] td_multi  multi mpp file strcuture
408   !> @param[in]    td_mpp    mpp file strcuture
409   !> @return mpp file id in multi mpp file structure
410   !-------------------------------------------------------------------
411   SUBROUTINE multi__add_mpp( td_multi, td_mpp )
412      IMPLICIT NONE
413      ! Argument
414      TYPE(TMULTI), INTENT(INOUT) :: td_multi
415      TYPE(TMPP)  , INTENT(IN)    :: td_mpp
416
417      ! local variable
418      INTEGER(i4) :: il_status
419      INTEGER(i4) :: il_mppid
420     
421      TYPE(TMPP), DIMENSION(:), ALLOCATABLE :: tl_mpp
422
423      ! loop indices
424      INTEGER(i4) :: ji
425      !----------------------------------------------------------------
426
427      il_mppid=0
428      IF( ASSOCIATED(td_multi%t_mpp) )THEN
429         il_mppid=mpp_get_index(td_multi%t_mpp(:),TRIM(td_mpp%c_name))
430      ENDIF
431
432      IF( il_mppid /= 0 )THEN
433
434            CALL logger_debug( " MULTI ADD FILE: mpp file "//TRIM(td_mpp%c_name)//&
435            &               " already in multi mpp file structure")
436
437            ! add new variable
438            DO ji=1,td_mpp%t_proc(1)%i_nvar
439               CALL mpp_add_var(td_multi%t_mpp(il_mppid), td_mpp%t_proc(1)%t_var(ji))
440            ENDDO
441
442      ELSE
443 
444         CALL logger_trace("MULTI ADD MPP: add mpp "//&
445         &               TRIM(td_mpp%c_name)//" in multi mpp file structure")
446
447         IF( td_multi%i_nmpp > 0 )THEN
448            !
449            ! already other mpp file in multi file structure
450            ALLOCATE( tl_mpp(td_multi%i_nmpp), stat=il_status )
451            IF(il_status /= 0 )THEN
452
453               CALL logger_error( " MULTI ADD MPP FILE: not enough space to put &
454               &               mpp file in multi mpp file structure")
455
456            ELSE
457               ! save temporary multi file structure
458               tl_mpp(:)=mpp_copy(td_multi%t_mpp(:))
459
460               CALL mpp_clean(td_multi%t_mpp(:))
461               DEALLOCATE( td_multi%t_mpp )
462               ALLOCATE( td_multi%t_mpp(td_multi%i_nmpp+1), stat=il_status)
463               IF(il_status /= 0 )THEN
464
465                  CALL logger_error( " MULTI ADD MPP FILE: not enough space "//&
466                  &  "to put mpp file in multi mpp file structure ")
467
468               ENDIF
469
470               ! copy mpp file in multi mpp file before
471               td_multi%t_mpp(1:td_multi%i_nmpp) = mpp_copy(tl_mpp(:))
472
473               ! clean
474               CALL mpp_clean(tl_mpp(:))
475               DEALLOCATE(tl_mpp)
476            ENDIF
477
478         ELSE
479            ! no file in multi file structure
480            IF( ASSOCIATED(td_multi%t_mpp) )THEN
481               CALL mpp_clean(td_multi%t_mpp(:))
482               DEALLOCATE(td_multi%t_mpp)
483            ENDIF
484            ALLOCATE( td_multi%t_mpp(td_multi%i_nmpp+1), stat=il_status )
485            IF(il_status /= 0 )THEN
486
487               CALL logger_error( " MULTI ADD MPP FILE: not enough space "//&
488               &  "to put mpp file in multi mpp file structure " )
489
490            ENDIF
491         ENDIF
492
493         ! update number of mpp
494         td_multi%i_nmpp=td_multi%i_nmpp+1
495
496         ! add new mpp
497         td_multi%t_mpp(td_multi%i_nmpp)=mpp_copy(td_mpp)
498
499      ENDIF
500   END SUBROUTINE multi__add_mpp
501END MODULE multi
502
Note: See TracBrowser for help on using the repository browser.