File: /nfs/home/0/users/jenkins/mfix.git/model/output_manager.f

1     !----------------------------------------------------------------------!
2     !                                                                      !
3     !  Subroutine: OUTPUT_MANAGER                                          !
4     !  Author: J.Musser                                   Date:            !
5     !                                                                      !
6     !  Purpose: Relocate calls to write output files (RES, SPx, VTP). This !
7     !  was done to simplify the time_march code.                           !
8     !                                                                      !
9     !----------------------------------------------------------------------!
10           SUBROUTINE OUTPUT_MANAGER(BATCHQ_END, FINISHED)
11     
12     ! Global Variables:
13     !---------------------------------------------------------------------//
14     
15           use output, only: RES_TIME, RES_DT
16           use output, only: SPX_TIME, SPX_DT
17           use output, only: OUT_TIME, OUT_DT
18           use output, only: USR_TIME, USR_DT
19           use vtk, only:    VTK_TIME, VTK_DT
20     
21           use output, only: DISK, DISK_TOT
22     
23           use param1, only: N_SPX
24           use param, only: DIMENSION_USR
25           use vtk, only: DIMENSION_VTK
26     
27           use run, only: TIME, DT, TSTOP
28     
29           use time_cpu, only: CPU_IO
30     
31           use compar, only: myPE, PE_IO
32     
33           use discretelement, only: DISCRETE_ELEMENT
34     
35           use vtk, only: WRITE_VTK_FILES
36           use qmom_kinetic_equation, only: QMOMK
37     
38           use param1, only: UNDEFINED
39     
40           use vtp, only: write_vtp_file
41     
42     
43           IMPLICIT NONE
44     
45     
46     ! Dummy Arguments:
47     !---------------------------------------------------------------------//
48     ! Flag that the the user specified batch time (plus buffer) is met.
49           LOGICAL, INTENT(IN) :: BATCHQ_END
50     ! Flag that a steady state case is completed.
51           LOGICAL, INTENT(IN) :: FINISHED
52     
53     ! Local Variables:
54     !---------------------------------------------------------------------//
55     ! Loop counter and counter
56           INTEGER :: LC, IDX
57     ! Flag to write NetCDF output
58           LOGICAL :: bWRITE_NETCDF_FILES
59     ! Flag that the header (time) has not be written.
60           LOGICAL :: HDR_MSG
61     ! SPX file extensions.
62           CHARACTER(LEN=35) ::  EXT_END
63     ! Wall time at the start of IO operations.
64           DOUBLE PRECISION :: WALL_START
65     
66     ! External function:
67     !---------------------------------------------------------------------//
68     ! Returns the current wall time.
69           DOUBLE PRECISION :: WALL_TIME
70     !......................................................................!
71     
72     
73     ! Initialize the SPx file extension array.
74           EXT_END = '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
75     ! Initial the header flag.
76           HDR_MSG = .TRUE.
77     
78     ! Get the current time before any IO operations begin
79           WALL_START = WALL_TIME()
80     
81     ! Write restart file, if needed
82           IF(CHECK_TIME(RES_TIME) .OR. BATCHQ_END) THEN
83     
84              RES_TIME = NEXT_TIME(RES_DT)
85              CALL WRITE_RES1
86              CALL NOTIFY_USER('.RES;')
87     
88              IF(DISCRETE_ELEMENT) THEN
89                 CALL WRITE_RES0_DES
90                 CALL NOTIFY_USER('DES.RES;')
91              ENDIF
92     
93              IF(QMOMK) THEN
94                 CALL QMOMK_WRITE_RESTART
95                 CALL NOTIFY_USER('QMOMK.RES;')
96              ENDIF
97     
98           ENDIF
99     
100     ! Write SPx files, if needed
101           IDX = 0
102           bWRITE_NETCDF_FILES = .FALSE.
103     
104           DO LC=1, N_SPX
105              IF(CHECK_TIME(SPX_TIME(LC))) THEN
106                 SPX_TIME(LC) = NEXT_TIME(SPX_DT(LC))
107     
108                 CALL WRITE_SPX1(LC, 0)
109                 CALL NOTIFY_USER('SPx:',EXT_END(LC:LC))
110     
111                 DISK_TOT = DISK_TOT + DISK(LC)
112                 IDX = IDX + 1
113     
114                 bWRITE_NETCDF_FILES = .TRUE.
115              ENDIF
116           ENDDO
117           IF(IDX /=0) CALL FLUSH_LIST
118     
119     
120     ! Write standard output, if needed
121           IF(CHECK_TIME(OUT_TIME)) THEN
122              OUT_TIME = NEXT_TIME(OUT_DT)
123              CALL WRITE_OUT1
124              CALL NOTIFY_USER('.OUT;')
125           ENDIF
126     
127     ! Write special output, if needed
128           IDX = 0
129           DO LC = 1, DIMENSION_USR
130              IF(CHECK_TIME(USR_TIME(LC))) THEN
131                 USR_TIME(LC) = NEXT_TIME(USR_DT(LC))
132                 CALL WRITE_USR1 (LC)
133                 CALL NOTIFY_USER('.USR:',EXT_END(LC:LC))
134                 IDX = IDX + 1
135              ENDIF
136           ENDDO
137           IF(IDX /=0) CALL FLUSH_LIST
138     
139           CALL FLUSH_NOTIFY_USER
140     
141     ! Write vtk file, if needed
142           IF(WRITE_VTK_FILES) THEN
143              DO LC = 1, DIMENSION_VTK
144                 IF(CHECK_TIME(VTK_TIME(LC))) THEN
145                    VTK_TIME(LC) = NEXT_TIME(VTK_DT(LC))
146                    CALL WRITE_VTU_FILE(LC)
147                    IF(DISCRETE_ELEMENT) CALL WRITE_VTP_FILE(LC)
148                 ENDIF
149              ENDDO
150           ENDIF
151     
152     ! Write NetCDF files.
153           IF(bWRITE_NETCDF_FILES) CALL WRITE_NETCDF(0,0,TIME)
154     
155     ! Add the amount of time needed for all IO operations to total.
156           CPU_IO = CPU_IO + (WALL_TIME() - WALL_START)
157     
158           RETURN
159     
160           contains
161     
162     
163     !----------------------------------------------------------------------!
164     !                                                                      !
165     !----------------------------------------------------------------------!
166           LOGICAL FUNCTION CHECK_TIME(lTIME)
167     
168           DOUBLE PRECISION, INTENT(IN) :: lTIME
169     
170           CHECK_TIME = ((DT == UNDEFINED) .AND. FINISHED) .OR. &
171              (TIME + 0.1d0*DT>=lTIME) .OR. (TIME+0.1d0*DT>=TSTOP)
172     
173           RETURN
174           END FUNCTION CHECK_TIME
175     
176     
177     !----------------------------------------------------------------------!
178     !                                                                      !
179     !----------------------------------------------------------------------!
180           DOUBLE PRECISION FUNCTION NEXT_TIME(lWRITE_DT)
181     
182           DOUBLE PRECISION, INTENT(IN) :: lWRITE_DT
183     
184           IF (DT /= UNDEFINED) &
185              NEXT_TIME = (INT((TIME + 0.1d0*DT)/lWRITE_DT)+1)*lWRITE_DT
186     
187           RETURN
188           END FUNCTION NEXT_TIME
189     
190     
191     !----------------------------------------------------------------------!
192     !                                                                      !
193     !----------------------------------------------------------------------!
194           SUBROUTINE NOTIFY_USER(MSG, EXT)
195     
196           use output, only: FULL_LOG
197           use funits, only: DMP_LOG
198           use funits, only: UNIT_LOG
199     
200           CHARACTER(len=*), INTENT(IN) :: MSG
201           CHARACTER(len=*), INTENT(IN), OPTIONAL :: EXT
202     
203     
204           LOGICAL :: SCR_LOG
205     
206           SCR_LOG = (FULL_LOG .and. myPE.eq.PE_IO)
207     
208           IF(HDR_MSG) THEN
209              IF(DMP_LOG) WRITE(UNIT_LOG, 1000, ADVANCE='NO') TIME
210              IF(SCR_LOG) WRITE(*, 1000, ADVANCE='NO') TIME
211              HDR_MSG = .FALSE.
212           ENDIF
213     
214      1000 FORMAT(' ',/' t=',F12.6,' Wrote')
215     
216           IF(.NOT.present(EXT)) THEN
217              IF(DMP_LOG) WRITE(UNIT_LOG, 1100, ADVANCE='NO') MSG
218              IF(SCR_LOG) WRITE(*, 1100, ADVANCE='NO') MSG
219           ELSE
220              IF(IDX == 0) THEN
221                 IF(DMP_LOG) WRITE(UNIT_LOG, 1110, ADVANCE='NO') MSG, EXT
222                 IF(SCR_LOG) WRITE(*, 1110, ADVANCE='NO') MSG, EXT
223              ELSE
224                 IF(DMP_LOG) WRITE(UNIT_LOG, 1120, ADVANCE='NO') EXT
225                 IF(SCR_LOG) WRITE(*, 1120, ADVANCE='NO') EXT
226              ENDIF
227           ENDIF
228     
229      1100 FORMAT(1X,A)
230      1110 FORMAT(1X,A,1x,A)
231      1120 FORMAT(',',A)
232     
233           RETURN
234           END SUBROUTINE NOTIFY_USER
235     
236     !----------------------------------------------------------------------!
237     !                                                                      !
238     !----------------------------------------------------------------------!
239           SUBROUTINE FLUSH_LIST
240     
241           use output, only: FULL_LOG
242           use funits, only: DMP_LOG
243           use funits, only: UNIT_LOG
244     
245           LOGICAL :: SCR_LOG
246     
247           SCR_LOG = (FULL_LOG .and. myPE.eq.PE_IO)
248     
249           IF(DMP_LOG) WRITE(UNIT_LOG,1000, ADVANCE='NO')
250           IF(SCR_LOG) WRITE(*,1000, ADVANCE='NO')
251     
252      1000 FORMAT(';')
253     
254           RETURN
255           END SUBROUTINE FLUSH_LIST
256     
257     
258     !----------------------------------------------------------------------!
259     !                                                                      !
260     !----------------------------------------------------------------------!
261           SUBROUTINE FLUSH_NOTIFY_USER
262     
263           use output, only: FULL_LOG
264           use funits, only: DMP_LOG
265           use funits, only: UNIT_LOG
266     
267           use time_cpu, only: TIME_START
268           use time_cpu, only: WALL_START
269     
270           use output, only: NLOG
271     
272           use run, only: NSTEP
273     
274           use error_manager
275     
276     
277           DOUBLE PRECISION :: WALL_ELAP, WALL_LEFT, WALL_NOW
278           CHARACTER(LEN=9) :: CHAR_ELAP, CHAR_LEFT
279           CHARACTER(LEN=4) :: UNIT_ELAP, UNIT_LEFT
280     
281           LOGICAL :: SCR_LOG
282     
283           SCR_LOG = (FULL_LOG .and. myPE.eq.PE_IO)
284     
285           IF(.NOT.HDR_MSG) THEN
286              IF(DMP_LOG) WRITE(UNIT_LOG,1000)
287              IF(SCR_LOG) WRITE(*,1000)
288           ENDIF
289     
290      1000 FORMAT(' ',/' ')
291     
292     ! Write the elapsed time and estimated remaining time
293           IF(MOD(NSTEP,NLOG) == 0) THEN
294              WALL_NOW = WALL_TIME()
295     ! Calculate the elapsed wall time.
296              WALL_ELAP = WALL_NOW - WALL_START
297              CALL GET_TUNIT(WALL_ELAP, UNIT_ELAP)
298              CHAR_ELAP=''; WRITE(CHAR_ELAP,"(F9.2)") WALL_ELAP
299              CHAR_ELAP = trim(adjustl(CHAR_ELAP))
300     ! Estimate the remaining wall time.
301              WALL_LEFT = (WALL_NOW-WALL_START)*(TSTOP-TIME)/               &
302                 max(TIME-TIME_START,1.0d-6)
303              CALL GET_TUNIT(WALL_LEFT, UNIT_LEFT)
304              CHAR_LEFT=''; WRITE(CHAR_LEFT,"(F9.2)") WALL_LEFT
305              CHAR_LEFT = trim(adjustl(CHAR_LEFT))
306     ! Notify the user of usage/remaining wall times.
307              WRITE(ERR_MSG,2000)                                           &
308                 'Elapsed:', trim(CHAR_ELAP), trim(UNIT_ELAP),              &
309                 'Est. Remaining:',trim(CHAR_LEFT), trim(UNIT_LEFT)
310              CALL FLUSH_ERR_MSG(HEADER=.FALSE., FOOTER=.FALSE.)
311           ENDIF
312     
313      2000 FORMAT('Wall Time - ',2(A,1X,A,A,4X))
314     
315     
316     
317           RETURN
318           END SUBROUTINE FLUSH_NOTIFY_USER
319     
320           END SUBROUTINE OUTPUT_MANAGER
321     !----------------------------------------------------------------------!
322     !                                                                      !
323     !                                                                      !
324     !                                                                      !
325     !----------------------------------------------------------------------!
326           SUBROUTINE INIT_OUTPUT_VARS
327     
328           use output, only: RES_TIME, RES_DT
329           use output, only: SPX_TIME, SPX_DT
330           use output, only: OUT_TIME, OUT_DT
331           use output, only: USR_TIME, USR_DT
332           use vtk, only:    VTK_TIME, VTK_DT
333     
334           use output, only: DISK, DISK_TOT
335     
336           use param1, only: N_SPX
337           use param, only: DIMENSION_USR
338           use vtk, only: DIMENSION_VTK
339     
340     
341           use physprop, only: MMAX, NMAX
342           use run, only: RUN_TYPE
343           use run, only: K_EPSILON
344           use param1, only: ZERO
345           use geometry, only: IJKMAX2
346     
347           use vtk, only: DIMENSION_VTK
348           use vtk, only: WRITE_VTK_FILES
349           use vtk, only: VTK_TIME, VTK_DT
350     
351           use param1, only: UNDEFINED
352           use run, only: TIME, DT
353     
354           use time_cpu, only: CPU_IO
355           use time_cpu, only: TIME_START
356           use time_cpu, only: WALL_START
357           use rxns, only: nRR
358           use scalars, only: NScalar
359           use output, only: ONEMEG
360     
361           IMPLICIT NONE
362     
363     ! Disk space needed for one variable and each SPX file
364           DOUBLE PRECISION :: DISK_ONE
365     
366     ! External function for geting job wall time
367           DOUBLE PRECISION :: WALL_TIME
368     
369     ! Loop counter
370           INTEGER :: LC
371     
372     ! Initialize times for writing outputs
373           OUT_TIME = TIME
374     ! Initialize the amount of time spent on IO
375           CPU_IO = 0.0d0
376     
377     ! Initialize disk space calculations
378           DISK_TOT = ZERO
379           DISK_ONE = 4.0*IJKMAX2/ONEMEG
380     
381           DISK(1) = 1.0*DISK_ONE                           ! EPg
382           DISK(2) = 2.0*DISK_ONE                           ! Pg, Ps
383           DISK(3) = 3.0*DISK_ONE                           ! Ug, Vg, Wg
384           DISK(4) = 3.0*DISK_ONE*MMAX                      ! Us, Vs, Ws
385           DISK(5) = 1.0*DISK_ONE*MMAX                      ! ROPs
386           DISK(6) = 1.0*DISK_ONE*(MMAX+1)                  ! Tg, Ts
387           DISK(7) = 1.0*DISK_ONE*(sum(NMAX(0:MMAX)))       ! Xg, Xs
388           DISK(8) = 1.0*DISK_ONE*MMAX                      ! Theta
389           DISK(9) = 1.0*DISK_ONE*NScalar                   ! User Scalars
390           DISK(10) = nRR*DISK_ONE                          ! ReactionRates
391           DISK(11) = merge(2.0*DISK_ONE, ZERO, K_EPSILON)  ! K-Epsilon
392     
393     
394           IF (RUN_TYPE == 'NEW') THEN
395              RES_TIME = TIME
396              SPX_TIME(:N_SPX) = TIME
397           ELSE
398              IF (DT /= UNDEFINED) THEN
399                 RES_TIME = RES_DT *                                        &
400                    (INT((TIME + 0.1d0*DT)/RES_DT) + 1)
401                 SPX_TIME(:N_SPX) = SPX_DT(:N_SPX) *                        &
402                    (INT((TIME + 0.1d0*DT)/SPX_DT(:N_SPX)) + 1)
403              ENDIF
404           ENDIF
405     
406           DO LC = 1, DIMENSION_USR
407              USR_TIME(LC) = UNDEFINED
408              IF (USR_DT(LC) /= UNDEFINED) THEN
409                 IF (RUN_TYPE == 'NEW') THEN
410                    USR_TIME(LC) = TIME
411                 ELSE
412                    USR_TIME(LC) = USR_DT(LC) *                             &
413                       (INT((TIME+0.1d0*DT)/USR_DT(LC))+1)
414                 ENDIF
415              ENDIF
416           ENDDO
417     
418     ! Initialize VTK_TIME
419           IF(WRITE_VTK_FILES) THEN
420              DO LC = 1, DIMENSION_VTK
421                 VTK_TIME(LC) = UNDEFINED
422                 IF (VTK_DT(LC) /= UNDEFINED) THEN
423                    IF (RUN_TYPE == 'NEW'.OR.RUN_TYPE=='RESTART_2') THEN
424                       VTK_TIME(LC) = TIME
425                    ELSE
426                       VTK_TIME(LC) = VTK_DT(LC) *                          &
427                          (INT((TIME + 0.1d0*DT)/VTK_DT(LC))+1)
428                    ENDIF
429                 ENDIF
430              ENDDO
431           ENDIF
432     
433           WALL_START = WALL_TIME()
434           TIME_START = TIME
435     
436           RETURN
437           END SUBROUTINE INIT_OUTPUT_VARS
438     
439