1 | MODULE diaobs |
---|
2 | !!====================================================================== |
---|
3 | !! *** MODULE diaobs *** |
---|
4 | !! Observation diagnostics: Computation of the misfit between data and |
---|
5 | !! their model equivalent |
---|
6 | !!====================================================================== |
---|
7 | !! History : 1.0 ! 2006-03 (K. Mogensen) Original code |
---|
8 | !! - ! 2006-05 (K. Mogensen, A. Weaver) Reformatted |
---|
9 | !! - ! 2006-10 (A. Weaver) Cleaning and add controls |
---|
10 | !! - ! 2007-03 (K. Mogensen) General handling of profiles |
---|
11 | !! - ! 2007-04 (G. Smith) Generalized surface operators |
---|
12 | !! 2.0 ! 2008-10 (M. Valdivieso) obs operator for velocity profiles |
---|
13 | !! 3.4 ! 2014-08 (J. While) observation operator for profiles in all vertical coordinates |
---|
14 | !! - ! Incorporated SST bias correction |
---|
15 | !! 3.6 ! 2015-02 (M. Martin) Simplification of namelist and code |
---|
16 | !! - ! 2015-08 (M. Martin) Combined surface/profile routines. |
---|
17 | !! 4.0 ! 2017-11 (G. Madec) style only |
---|
18 | !!---------------------------------------------------------------------- |
---|
19 | |
---|
20 | !!---------------------------------------------------------------------- |
---|
21 | !! dia_obs_init : Reading and prepare observations |
---|
22 | !! dia_obs : Compute model equivalent to observations |
---|
23 | !! dia_obs_wri : Write observational diagnostics |
---|
24 | !! calc_date : Compute the date of timestep in YYYYMMDD.HHMMSS format |
---|
25 | !! ini_date : Compute the initial date YYYYMMDD.HHMMSS |
---|
26 | !! fin_date : Compute the final date YYYYMMDD.HHMMSS |
---|
27 | !!---------------------------------------------------------------------- |
---|
28 | USE par_kind ! Precision variables |
---|
29 | USE in_out_manager ! I/O manager |
---|
30 | USE timing ! Timing |
---|
31 | USE par_oce ! ocean parameter |
---|
32 | USE dom_oce ! Ocean space and time domain variables |
---|
33 | USE sbc_oce ! Sea-ice fraction |
---|
34 | ! |
---|
35 | USE obs_read_prof ! Reading and allocation of profile obs |
---|
36 | USE obs_read_surf ! Reading and allocation of surface obs |
---|
37 | USE obs_bias ! Bias correction routine |
---|
38 | USE obs_readmdt ! Reading and allocation of MDT for SLA. |
---|
39 | USE obs_prep ! Preparation of obs. (grid search etc). |
---|
40 | USE obs_oper ! Observation operators |
---|
41 | USE obs_write ! Writing of observation related diagnostics |
---|
42 | USE obs_grid ! Grid searching |
---|
43 | USE obs_read_altbias ! Bias treatment for altimeter |
---|
44 | USE obs_profiles_def ! Profile data definitions |
---|
45 | USE obs_surf_def ! Surface data definitions |
---|
46 | USE obs_types ! Definitions for observation types |
---|
47 | USE obs_field ! Definitions for observation types |
---|
48 | ! |
---|
49 | USE mpp_map ! MPP mapping |
---|
50 | USE lib_mpp ! For ctl_warn/stop |
---|
51 | |
---|
52 | IMPLICIT NONE |
---|
53 | PRIVATE |
---|
54 | |
---|
55 | PUBLIC dia_obs_init ! Initialize and read observations |
---|
56 | PUBLIC dia_obs ! Compute model equivalent to observations |
---|
57 | PUBLIC dia_obs_wri ! Write model equivalent to observations |
---|
58 | PUBLIC calc_date ! Compute the date of a timestep |
---|
59 | |
---|
60 | LOGICAL, PUBLIC :: ln_diaobs !: Logical switch for the obs operator |
---|
61 | |
---|
62 | INTEGER :: nn_obsgroups |
---|
63 | |
---|
64 | TYPE(obs_group), DIMENSION(:), ALLOCATABLE :: sobsgroups ! Obs groups |
---|
65 | |
---|
66 | !!---------------------------------------------------------------------- |
---|
67 | !! NEMO/OCE 4.0 , NEMO Consortium (2018) |
---|
68 | !! $Id$ |
---|
69 | !! Software governed by the CeCILL license (see ./LICENSE) |
---|
70 | !!---------------------------------------------------------------------- |
---|
71 | CONTAINS |
---|
72 | |
---|
73 | SUBROUTINE dia_obs_init |
---|
74 | !!---------------------------------------------------------------------- |
---|
75 | !! *** ROUTINE dia_obs_init *** |
---|
76 | !! |
---|
77 | !! ** Purpose : Initialize and read observations |
---|
78 | !! |
---|
79 | !! ** Method : Read the namelist and call reading routines |
---|
80 | !! |
---|
81 | !! ** Action : Read the namelist and call reading routines |
---|
82 | !! |
---|
83 | !!---------------------------------------------------------------------- |
---|
84 | INTEGER, PARAMETER :: jpmaxngroups = 1000 ! Maximum number of obs groups |
---|
85 | INTEGER :: ios ! Local integer output status for namelist read |
---|
86 | INTEGER :: jtype ! Counter for obs types |
---|
87 | INTEGER :: jvar ! Counter for variables |
---|
88 | INTEGER :: jfile ! Counter for files |
---|
89 | INTEGER :: jenabled |
---|
90 | INTEGER :: jgroup |
---|
91 | ! |
---|
92 | LOGICAL, DIMENSION(:), ALLOCATABLE :: llvar |
---|
93 | ! |
---|
94 | REAL(dp) :: rn_dobsini ! Obs window start date YYYYMMDD.HHMMSS |
---|
95 | REAL(dp) :: rn_dobsend ! Obs window end date YYYYMMDD.HHMMSS |
---|
96 | !! |
---|
97 | NAMELIST/namobs/ln_diaobs, nn_obsgroups, & |
---|
98 | & ln_grid_global, ln_grid_search_lookup, & |
---|
99 | & cn_gridsearchfile, rn_gridsearchres, & |
---|
100 | & rn_dobsini, rn_dobsend |
---|
101 | !----------------------------------------------------------------------- |
---|
102 | |
---|
103 | !----------------------------------------------------------------------- |
---|
104 | ! Read namelist parameters |
---|
105 | !----------------------------------------------------------------------- |
---|
106 | ! Initialise time window |
---|
107 | CALL ini_date( rn_dobsini ) |
---|
108 | CALL fin_date( rn_dobsend ) |
---|
109 | |
---|
110 | ! Read namelist namobs : control observation diagnostics |
---|
111 | REWIND( numnam_ref ) ! Namelist namobs in reference namelist |
---|
112 | READ ( numnam_ref, namobs, IOSTAT = ios, ERR = 901) |
---|
113 | 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namobs in reference namelist' ) |
---|
114 | REWIND( numnam_cfg ) ! Namelist namobs in configuration namelist |
---|
115 | READ ( numnam_cfg, namobs, IOSTAT = ios, ERR = 902 ) |
---|
116 | 902 IF( ios > 0 ) CALL ctl_nam ( ios , 'namobs in configuration namelist' ) |
---|
117 | IF(lwm) WRITE ( numond, namobs ) |
---|
118 | |
---|
119 | IF( .NOT.ln_diaobs ) THEN |
---|
120 | IF(lwp) WRITE(numout,*) |
---|
121 | IF(lwp) WRITE(numout,*) 'dia_obs_init : NO Observation diagnostic used' |
---|
122 | IF(lwp) WRITE(numout,*) '~~~~~~~~~~~~' |
---|
123 | RETURN |
---|
124 | ENDIF |
---|
125 | |
---|
126 | IF(lwp) THEN |
---|
127 | WRITE(numout,*) |
---|
128 | WRITE(numout,*) 'dia_obs_init : Observation diagnostic initialization' |
---|
129 | WRITE(numout,*) '~~~~~~~~~~~~' |
---|
130 | WRITE(numout,*) ' Namelist namobs : set observation diagnostic parameters' |
---|
131 | WRITE(numout,*) ' Number of namobs_dta namelists to read nn_obsgroups = ', nn_obsgroups |
---|
132 | WRITE(numout,*) ' Global distribution of observations ln_grid_global = ', ln_grid_global |
---|
133 | WRITE(numout,*) ' Logical switch for obs grid search lookup ln_grid_search_lookup = ', ln_grid_search_lookup |
---|
134 | IF (ln_grid_search_lookup) THEN |
---|
135 | WRITE(numout,*) ' Grid search lookup file header cn_gridsearchfile = ', cn_gridsearchfile |
---|
136 | WRITE(numout,*) ' Grid search resolution rn_gridsearchres = ', rn_gridsearchres |
---|
137 | ENDIF |
---|
138 | ENDIF |
---|
139 | |
---|
140 | IF( ln_grid_global ) THEN |
---|
141 | CALL ctl_warn( 'dia_obs_init: ln_grid_global=T may cause memory issues when used with a large number of processors' ) |
---|
142 | ENDIF |
---|
143 | |
---|
144 | !----------------------------------------------------------------------- |
---|
145 | ! Read namobs_dta namelists and set up observation groups |
---|
146 | !----------------------------------------------------------------------- |
---|
147 | |
---|
148 | IF( nn_obsgroups == 0 ) THEN |
---|
149 | CALL ctl_warn( 'dia_obs_init: ln_diaobs is set to true, but nn_obsgroups == 0', & |
---|
150 | & ' so turning off calls to dia_obs' ) |
---|
151 | ln_diaobs = .FALSE. |
---|
152 | RETURN |
---|
153 | ENDIF |
---|
154 | |
---|
155 | ALLOCATE( sobsgroups(nn_obsgroups) ) |
---|
156 | |
---|
157 | jenabled = 0 |
---|
158 | DO jgroup = 1, nn_obsgroups |
---|
159 | CALL obs_group_read ( sobsgroups(jgroup) ) |
---|
160 | CALL obs_group_check( sobsgroups(jgroup), jgroup ) |
---|
161 | IF (sobsgroups(jgroup)%lenabled) THEN |
---|
162 | jenabled = jenabled + 1 |
---|
163 | IF( sobsgroups(jgroup)%lvel .AND. .NOT.ln_grid_global ) THEN |
---|
164 | CALL ctl_stop( 'Velocity data only works with ln_grid_global=.true.' ) |
---|
165 | ENDIF |
---|
166 | ENDIF |
---|
167 | END DO |
---|
168 | |
---|
169 | IF( jenabled == 0 ) THEN |
---|
170 | CALL ctl_warn( 'dia_obs_init: ln_diaobs is set to true, and nn_obsgroups > 0', & |
---|
171 | & ' but no groups are enabled so turning off calls to dia_obs' ) |
---|
172 | ln_diaobs = .FALSE. |
---|
173 | RETURN |
---|
174 | ENDIF |
---|
175 | |
---|
176 | |
---|
177 | !----------------------------------------------------------------------- |
---|
178 | ! Obs operator parameter checking and initialisations |
---|
179 | !----------------------------------------------------------------------- |
---|
180 | ! |
---|
181 | CALL obs_typ_init |
---|
182 | IF( ln_grid_global ) CALL mppmap_init |
---|
183 | ! |
---|
184 | CALL obs_grid_setup( ) |
---|
185 | |
---|
186 | !----------------------------------------------------------------------- |
---|
187 | ! Depending on switches read the various observation types |
---|
188 | !----------------------------------------------------------------------- |
---|
189 | ! |
---|
190 | DO jgroup = 1, nn_obsgroups |
---|
191 | IF (sobsgroups(jgroup)%lenabled) THEN |
---|
192 | IF (sobsgroups(jgroup)%lprof) THEN |
---|
193 | ! |
---|
194 | ! Read in profile or profile obs types |
---|
195 | ! |
---|
196 | ALLOCATE( llvar(sobsgroups(jgroup)%nobstypes) ) |
---|
197 | llvar(:) = .TRUE. |
---|
198 | ! |
---|
199 | CALL obs_rea_prof( sobsgroups(jgroup)%sprofdata, & |
---|
200 | & sobsgroups(jgroup)%nobsfiles, & |
---|
201 | & sobsgroups(jgroup)%cobsfiles, & |
---|
202 | & sobsgroups(jgroup)%nobstypes, & |
---|
203 | & sobsgroups(jgroup)%naddvars, & |
---|
204 | & sobsgroups(jgroup)%nextvars, & |
---|
205 | & nitend-nit000+2, & |
---|
206 | & rn_dobsini, & |
---|
207 | & rn_dobsend, & |
---|
208 | & llvar, & |
---|
209 | & sobsgroups(jgroup)%lignmis, & |
---|
210 | & sobsgroups(jgroup)%lall_at_all, & |
---|
211 | & .FALSE., & |
---|
212 | & sobsgroups(jgroup)%cobstypes, & |
---|
213 | & kdailyavtypes = sobsgroups(jgroup)%nprofdavtypes ) |
---|
214 | ! |
---|
215 | DO jvar = 1, sobsgroups(jgroup)%nobstypes |
---|
216 | CALL obs_prof_staend( sobsgroups(jgroup)%sprofdata, jvar ) |
---|
217 | END DO |
---|
218 | ! |
---|
219 | IF ( sobsgroups(jgroup)%sprofdata%next > 0 ) THEN |
---|
220 | CALL obs_prof_staend_ext( sobsgroups(jgroup)%sprofdata ) |
---|
221 | ENDIF |
---|
222 | ! |
---|
223 | CALL obs_pre_prof( sobsgroups(jgroup)%sprofdata, & |
---|
224 | & sobsgroups(jgroup)%sprofdataqc, & |
---|
225 | & llvar, & |
---|
226 | & jpi, jpj, jpk, & |
---|
227 | & sobsgroups(jgroup)%rmask, & |
---|
228 | & sobsgroups(jgroup)%rglam, & |
---|
229 | & sobsgroups(jgroup)%rgphi, & |
---|
230 | & sobsgroups(jgroup)%lnea, & |
---|
231 | & sobsgroups(jgroup)%lbound_reject, & |
---|
232 | & kdailyavtypes = sobsgroups(jgroup)%nprofdavtypes ) |
---|
233 | ! |
---|
234 | DEALLOCATE( llvar ) |
---|
235 | ! |
---|
236 | ELSEIF (sobsgroups(jgroup)%lsurf) THEN |
---|
237 | ! |
---|
238 | ! Read in surface obs types |
---|
239 | ! |
---|
240 | CALL obs_rea_surf( sobsgroups(jgroup)%ssurfdata, & |
---|
241 | & sobsgroups(jgroup)%nobsfiles, & |
---|
242 | & sobsgroups(jgroup)%cobsfiles, & |
---|
243 | & sobsgroups(jgroup)%nobstypes, & |
---|
244 | & sobsgroups(jgroup)%naddvars, & |
---|
245 | & sobsgroups(jgroup)%nextvars, & |
---|
246 | & nitend-nit000+2, & |
---|
247 | & rn_dobsini, & |
---|
248 | & rn_dobsend, & |
---|
249 | & sobsgroups(jgroup)%lignmis, & |
---|
250 | & .FALSE., & |
---|
251 | & sobsgroups(jgroup)%lnight, & |
---|
252 | & sobsgroups(jgroup)%cobstypes ) |
---|
253 | ! |
---|
254 | IF( sobsgroups(jgroup)%lsla ) THEN |
---|
255 | sobsgroups(jgroup)%ssurfdata%cextvars(sobsgroups(jgroup)%next_mdt) = 'MDT' |
---|
256 | sobsgroups(jgroup)%ssurfdata%cextlong(sobsgroups(jgroup)%next_mdt) = 'Mean dynamic topography' |
---|
257 | sobsgroups(jgroup)%ssurfdata%cextunit(sobsgroups(jgroup)%next_mdt) = 'Metres' |
---|
258 | sobsgroups(jgroup)%ssurfdata%caddvars(sobsgroups(jgroup)%nadd_ssh) = 'SSH' |
---|
259 | DO jvar = 1, sobsgroups(jgroup)%nobstypes |
---|
260 | sobsgroups(jgroup)%ssurfdata%caddlong(sobsgroups(jgroup)%nadd_ssh,jvar) = 'Model Sea surface height' |
---|
261 | sobsgroups(jgroup)%ssurfdata%caddunit(sobsgroups(jgroup)%nadd_ssh,jvar) = 'Metres' |
---|
262 | END DO |
---|
263 | ENDIF |
---|
264 | ! |
---|
265 | CALL obs_pre_surf( sobsgroups(jgroup)%ssurfdata, & |
---|
266 | & sobsgroups(jgroup)%ssurfdataqc, & |
---|
267 | & jpi, jpj, & |
---|
268 | & sobsgroups(jgroup)%rmask(:,:,1,:), & |
---|
269 | & sobsgroups(jgroup)%rglam, & |
---|
270 | & sobsgroups(jgroup)%rgphi, & |
---|
271 | & sobsgroups(jgroup)%lnea, & |
---|
272 | & sobsgroups(jgroup)%lbound_reject ) |
---|
273 | ! |
---|
274 | IF( sobsgroups(jgroup)%lsla ) THEN |
---|
275 | CALL obs_rea_mdt( sobsgroups(jgroup)%ssurfdataqc, & |
---|
276 | & sobsgroups(jgroup)%n2dint, & |
---|
277 | & sobsgroups(jgroup)%next_mdt ) |
---|
278 | IF( sobsgroups(jgroup)%laltbias ) THEN |
---|
279 | !CALL obs_rea_altbias( sobsgroups(jgroup)%ssurfdataqc, & |
---|
280 | ! & sobsgroups(jgroup)%n2dint, & |
---|
281 | ! & sobsgroups(jgroup)%caltbiasfile ) |
---|
282 | CALL obs_app_bias( sobsgroups(jgroup)%ssurfdataqc, & |
---|
283 | & sobsgroups(jgroup)%next_mdt, & |
---|
284 | & sobsgroups(jgroup)%n2dint, & |
---|
285 | & 1, & |
---|
286 | & sobsgroups(jgroup)%caltbiasfile, & |
---|
287 | & 'altbias', & |
---|
288 | & ld_extvar=.TRUE. ) |
---|
289 | ENDIF |
---|
290 | ENDIF |
---|
291 | ! |
---|
292 | IF( sobsgroups(jgroup)%lobsbias ) THEN |
---|
293 | CALL obs_app_bias( sobsgroups(jgroup)%ssurfdataqc, & |
---|
294 | & sobsgroups(jgroup)%nbiasvar, & |
---|
295 | & sobsgroups(jgroup)%n2dint, & |
---|
296 | & sobsgroups(jgroup)%nobsbiasfiles, & |
---|
297 | & sobsgroups(jgroup)%cobsbiasfiles, & |
---|
298 | & sobsgroups(jgroup)%cbiasvarname ) |
---|
299 | ENDIF |
---|
300 | ! |
---|
301 | ENDIF |
---|
302 | ENDIF |
---|
303 | END DO |
---|
304 | ! |
---|
305 | END SUBROUTINE dia_obs_init |
---|
306 | |
---|
307 | |
---|
308 | SUBROUTINE dia_obs( kstp ) |
---|
309 | !!---------------------------------------------------------------------- |
---|
310 | !! *** ROUTINE dia_obs *** |
---|
311 | !! |
---|
312 | !! ** Purpose : Call the observation operators on each time step |
---|
313 | !! |
---|
314 | !! ** Method : Call the observation operators on each time step to |
---|
315 | !! compute the model equivalent of the following data: |
---|
316 | !! - Profile data, currently T/S or U/V |
---|
317 | !! - Surface data, currently SST, SLA or sea-ice concentration. |
---|
318 | !! |
---|
319 | !! ** Action : |
---|
320 | !!---------------------------------------------------------------------- |
---|
321 | USE dom_oce, ONLY : gdept_n, gdept_1d ! Ocean space and time domain variables |
---|
322 | USE phycst , ONLY : rday ! Physical constants |
---|
323 | USE oce , ONLY : tsn, un, vn, sshn ! Ocean dynamics and tracers variables |
---|
324 | USE phycst , ONLY : rday ! Physical constants |
---|
325 | #if defined key_si3 |
---|
326 | USE ice , ONLY : at_i ! SI3 Ice model variables |
---|
327 | #endif |
---|
328 | #if defined key_cice |
---|
329 | USE sbc_oce, ONLY : fr_i ! ice fraction |
---|
330 | #endif |
---|
331 | |
---|
332 | IMPLICIT NONE |
---|
333 | |
---|
334 | !! * Arguments |
---|
335 | INTEGER, INTENT(IN) :: kstp ! Current timestep |
---|
336 | !! * Local declarations |
---|
337 | INTEGER :: idaystp ! Number of timesteps per day |
---|
338 | INTEGER :: jtype ! Data loop variable |
---|
339 | INTEGER :: jvar ! Variable number |
---|
340 | INTEGER :: jgroup |
---|
341 | INTEGER :: ji, jj ! Loop counters |
---|
342 | REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: & |
---|
343 | & zprofvar ! Model values for variables in a prof ob |
---|
344 | REAL(wp), DIMENSION(:,:), ALLOCATABLE :: & |
---|
345 | & zsurfvar ! Model values for variables in a surf ob |
---|
346 | |
---|
347 | !----------------------------------------------------------------------- |
---|
348 | |
---|
349 | IF( ln_timing ) CALL timing_start('dia_obs') |
---|
350 | |
---|
351 | IF(lwp) THEN |
---|
352 | WRITE(numout,*) |
---|
353 | WRITE(numout,*) 'dia_obs : Call the observation operators', kstp |
---|
354 | WRITE(numout,*) '~~~~~~~' |
---|
355 | ENDIF |
---|
356 | |
---|
357 | idaystp = NINT( rday / rdt ) |
---|
358 | |
---|
359 | !----------------------------------------------------------------------- |
---|
360 | ! Call the profile and surface observation operators |
---|
361 | !----------------------------------------------------------------------- |
---|
362 | |
---|
363 | DO jgroup = 1, nn_obsgroups |
---|
364 | IF (sobsgroups(jgroup)%lenabled) THEN |
---|
365 | |
---|
366 | IF (sobsgroups(jgroup)%lprof) THEN |
---|
367 | |
---|
368 | ALLOCATE( zprofvar(jpi,jpj,jpk) ) |
---|
369 | |
---|
370 | DO jvar = 1, sobsgroups(jgroup)%nobstypes |
---|
371 | |
---|
372 | SELECT CASE ( TRIM(sobsgroups(jgroup)%cobstypes(jvar)) ) |
---|
373 | CASE('POTM') |
---|
374 | zprofvar(:,:,:) = tsn(:,:,:,jp_tem) |
---|
375 | CASE('PSAL') |
---|
376 | zprofvar(:,:,:) = tsn(:,:,:,jp_sal) |
---|
377 | CASE('UVEL') |
---|
378 | zprofvar(:,:,:) = un(:,:,:) |
---|
379 | CASE('VVEL') |
---|
380 | zprofvar(:,:,:) = vn(:,:,:) |
---|
381 | CASE DEFAULT |
---|
382 | CALL ctl_stop( 'Unknown profile observation type '//TRIM(sobsgroups(jgroup)%cobstypes(jvar))//' in dia_obs' ) |
---|
383 | END SELECT |
---|
384 | |
---|
385 | CALL obs_prof_opt( sobsgroups(jgroup)%sprofdataqc, & |
---|
386 | & kstp, jpi, jpj, jpk, & |
---|
387 | & nit000, idaystp, jvar, & |
---|
388 | & zprofvar, & |
---|
389 | & gdept_n, & |
---|
390 | & gdepw_n, & |
---|
391 | & sobsgroups(jgroup)%rmask(:,:,:,jvar), & |
---|
392 | & sobsgroups(jgroup)%rglam(:,:,jvar), & |
---|
393 | & sobsgroups(jgroup)%rgphi(:,:,jvar), & |
---|
394 | & sobsgroups(jgroup)%n1dint, & |
---|
395 | & sobsgroups(jgroup)%n2dint, & |
---|
396 | & kdailyavtypes = sobsgroups(jgroup)%nprofdavtypes ) |
---|
397 | |
---|
398 | END DO |
---|
399 | |
---|
400 | DEALLOCATE( zprofvar ) |
---|
401 | |
---|
402 | ELSEIF (sobsgroups(jgroup)%lsurf) THEN |
---|
403 | |
---|
404 | ALLOCATE( zsurfvar(jpi,jpj) ) |
---|
405 | |
---|
406 | DO jvar = 1, sobsgroups(jgroup)%nobstypes |
---|
407 | |
---|
408 | SELECT CASE ( TRIM(sobsgroups(jgroup)%cobstypes(jvar)) ) |
---|
409 | CASE('SST') |
---|
410 | zsurfvar(:,:) = tsn(:,:,1,jp_tem) |
---|
411 | CASE('SLA') |
---|
412 | zsurfvar(:,:) = sshn(:,:) |
---|
413 | CASE('SSS') |
---|
414 | zsurfvar(:,:) = tsn(:,:,1,jp_sal) |
---|
415 | CASE('UVEL') |
---|
416 | zsurfvar(:,:) = un(:,:,1) |
---|
417 | CASE('VVEL') |
---|
418 | zsurfvar(:,:) = vn(:,:,1) |
---|
419 | CASE('ICECONC') |
---|
420 | IF ( kstp == 0 ) THEN |
---|
421 | IF ( lwp .AND. sobsgroups(jgroup)%ssurfdataqc%nsstpmpp(1) > 0 ) THEN |
---|
422 | CALL ctl_warn( 'Sea-ice not initialised on zeroth '// & |
---|
423 | & 'time-step but some obs are valid then.' ) |
---|
424 | WRITE(numout,*)sobsgroups(jgroup)%ssurfdataqc%nsstpmpp(1), & |
---|
425 | & ' sea-ice obs will be missed' |
---|
426 | ENDIF |
---|
427 | !!! IS THIS ROBUST TO MULTIPLE TYPES IN A GROUP??? |
---|
428 | sobsgroups(jgroup)%ssurfdataqc%nsurfup = sobsgroups(jgroup)%ssurfdataqc%nsurfup + & |
---|
429 | & sobsgroups(jgroup)%ssurfdataqc%nsstp(1) |
---|
430 | CYCLE |
---|
431 | ELSE |
---|
432 | #if defined key_cice || defined key_si3 |
---|
433 | zsurfvar(:,:) = fr_i(:,:) |
---|
434 | #else |
---|
435 | CALL ctl_stop( ' Trying to run sea-ice observation operator', & |
---|
436 | & ' but no sea-ice model appears to have been defined' ) |
---|
437 | #endif |
---|
438 | ENDIF |
---|
439 | END SELECT |
---|
440 | |
---|
441 | CALL obs_surf_opt( sobsgroups(jgroup)%ssurfdataqc, & |
---|
442 | & kstp, jpi, jpj, & |
---|
443 | & nit000, idaystp, & |
---|
444 | & jvar, zsurfvar, & |
---|
445 | & sobsgroups(jgroup)%rmask(:,:,1,jvar), & |
---|
446 | & sobsgroups(jgroup)%n2dint, & |
---|
447 | & sobsgroups(jgroup)%lnight, & |
---|
448 | & sobsgroups(jgroup)%ravglamscl, & |
---|
449 | & sobsgroups(jgroup)%ravgphiscl, & |
---|
450 | & sobsgroups(jgroup)%lfp_indegs, & |
---|
451 | & kssh=sobsgroups(jgroup)%nadd_ssh, & |
---|
452 | & kmdt=sobsgroups(jgroup)%next_mdt ) |
---|
453 | |
---|
454 | END DO |
---|
455 | |
---|
456 | DEALLOCATE( zsurfvar ) |
---|
457 | |
---|
458 | ENDIF |
---|
459 | |
---|
460 | ENDIF |
---|
461 | END DO |
---|
462 | |
---|
463 | IF( ln_timing ) CALL timing_stop('dia_obs') |
---|
464 | |
---|
465 | END SUBROUTINE dia_obs |
---|
466 | |
---|
467 | SUBROUTINE dia_obs_wri |
---|
468 | !!---------------------------------------------------------------------- |
---|
469 | !! *** ROUTINE dia_obs_wri *** |
---|
470 | !! |
---|
471 | !! ** Purpose : Call observation diagnostic output routines |
---|
472 | !! |
---|
473 | !! ** Method : Call observation diagnostic output routines |
---|
474 | !! |
---|
475 | !! ** Action : |
---|
476 | !! |
---|
477 | !! History : |
---|
478 | !! ! 06-03 (K. Mogensen) Original code |
---|
479 | !! ! 06-05 (K. Mogensen) Reformatted |
---|
480 | !! ! 06-10 (A. Weaver) Cleaning |
---|
481 | !! ! 07-03 (K. Mogensen) General handling of profiles |
---|
482 | !! ! 08-09 (M. Valdivieso) Velocity component (U,V) profiles |
---|
483 | !! ! 15-08 (M. Martin) Combined writing for prof and surf types |
---|
484 | !!---------------------------------------------------------------------- |
---|
485 | !! * Modules used |
---|
486 | USE obs_rot_vel ! Rotation of velocities |
---|
487 | |
---|
488 | IMPLICIT NONE |
---|
489 | |
---|
490 | !! * Local declarations |
---|
491 | INTEGER :: jgroup ! Data set loop variable |
---|
492 | INTEGER :: jo, jvar, jk, jadd, jext, jadd2, jext2 |
---|
493 | INTEGER :: iuvar, ivvar |
---|
494 | REAL(wp), DIMENSION(:), ALLOCATABLE :: & |
---|
495 | & zu, & |
---|
496 | & zv |
---|
497 | LOGICAL, DIMENSION(:), ALLOCATABLE :: ll_write |
---|
498 | TYPE(obswriinfo) :: sladd, slext |
---|
499 | |
---|
500 | IF( ln_timing ) CALL timing_start('dia_obs_wri') |
---|
501 | |
---|
502 | !----------------------------------------------------------------------- |
---|
503 | ! Depending on switches call various observation output routines |
---|
504 | !----------------------------------------------------------------------- |
---|
505 | |
---|
506 | DO jgroup = 1, nn_obsgroups |
---|
507 | IF (sobsgroups(jgroup)%lenabled) THEN |
---|
508 | |
---|
509 | IF (sobsgroups(jgroup)%lprof) THEN |
---|
510 | |
---|
511 | IF (sobsgroups(jgroup)%lvel) THEN |
---|
512 | iuvar = 0 |
---|
513 | ivvar = 0 |
---|
514 | DO jvar = 1, sobsgroups(jgroup)%nobstypes |
---|
515 | IF ( TRIM(sobsgroups(jgroup)%cobstypes(jvar)) == cobsname_uvel ) THEN |
---|
516 | iuvar = jvar |
---|
517 | ELSEIF ( TRIM(sobsgroups(jgroup)%cobstypes(jvar)) == cobsname_vvel ) THEN |
---|
518 | ivvar = jvar |
---|
519 | ENDIF |
---|
520 | END DO |
---|
521 | IF ( (iuvar > 0) .AND. (ivvar > 0) ) THEN |
---|
522 | |
---|
523 | ! For velocity data, rotate the model velocities to N/S, E/W |
---|
524 | ! using the compressed data structure. |
---|
525 | ALLOCATE( & |
---|
526 | & zu(sobsgroups(jgroup)%sprofdataqc%nvprot(iuvar)), & |
---|
527 | & zv(sobsgroups(jgroup)%sprofdataqc%nvprot(ivvar)) & |
---|
528 | & ) |
---|
529 | |
---|
530 | CALL obs_rotvel_pro( sobsgroups(jgroup)%sprofdataqc, sobsgroups(jgroup)%n2dint, & |
---|
531 | & iuvar, ivvar, zu, zv ) |
---|
532 | |
---|
533 | DO jo = 1, sobsgroups(jgroup)%sprofdataqc%nprof |
---|
534 | DO jk = sobsgroups(jgroup)%sprofdataqc%npvsta(jo,iuvar), sobsgroups(jgroup)%sprofdataqc%npvend(jo,iuvar) |
---|
535 | sobsgroups(jgroup)%sprofdataqc%var(iuvar)%vmod(jk) = zu(jk) |
---|
536 | END DO |
---|
537 | DO jk = sobsgroups(jgroup)%sprofdataqc%npvsta(jo,ivvar), sobsgroups(jgroup)%sprofdataqc%npvend(jo,ivvar) |
---|
538 | sobsgroups(jgroup)%sprofdataqc%var(ivvar)%vmod(jk) = zv(jk) |
---|
539 | END DO |
---|
540 | END DO |
---|
541 | |
---|
542 | DEALLOCATE( zu ) |
---|
543 | DEALLOCATE( zv ) |
---|
544 | |
---|
545 | ELSE |
---|
546 | CALL ctl_stop( 'Could not identify velocity observation variables to rotate' ) |
---|
547 | END IF |
---|
548 | END IF |
---|
549 | |
---|
550 | CALL obs_prof_decompress( sobsgroups(jgroup)%sprofdataqc, & |
---|
551 | & sobsgroups(jgroup)%sprofdata, .TRUE., numout ) |
---|
552 | |
---|
553 | ! Put additional and extra variable information into obswriinfo structure |
---|
554 | ! used by obs_write. |
---|
555 | ! add/ext variables generated by the OBS code (1...sobsgroups(jgroup)%naddvars) |
---|
556 | ! may duplicate ones read in (%naddvars+1...sobsgroups(jgroup)%sprofdata%nadd) |
---|
557 | ! Check for this, and if so only write out the version generated by the OBS code |
---|
558 | sladd%inum = sobsgroups(jgroup)%sprofdata%nadd |
---|
559 | ALLOCATE( ll_write(sobsgroups(jgroup)%sprofdata%nadd) ) |
---|
560 | ll_write(:) = .TRUE. |
---|
561 | IF ( (sobsgroups(jgroup)%naddvars > 0) .AND. & |
---|
562 | & (sobsgroups(jgroup)%sprofdata%nadd > sobsgroups(jgroup)%naddvars) ) THEN |
---|
563 | DO jadd = sobsgroups(jgroup)%naddvars + 1, sobsgroups(jgroup)%sprofdata%nadd |
---|
564 | DO jadd2 = 1, sobsgroups(jgroup)%naddvars |
---|
565 | IF ( TRIM(sobsgroups(jgroup)%sprofdata%caddvars(jadd )) == & |
---|
566 | & TRIM(sobsgroups(jgroup)%sprofdata%caddvars(jadd2)) ) THEN |
---|
567 | sladd%inum = sladd%inum - 1 |
---|
568 | ll_write(jadd) = .FALSE. |
---|
569 | ENDIF |
---|
570 | END DO |
---|
571 | END DO |
---|
572 | ENDIF |
---|
573 | IF ( sladd%inum > 0 ) THEN |
---|
574 | ALLOCATE( sladd%ipoint(sladd%inum), & |
---|
575 | & sladd%cdname(sladd%inum), & |
---|
576 | & sladd%cdlong(sladd%inum,sobsgroups(jgroup)%sprofdata%nvar), & |
---|
577 | & sladd%cdunit(sladd%inum,sobsgroups(jgroup)%sprofdata%nvar) ) |
---|
578 | jadd2 = 0 |
---|
579 | DO jadd = 1, sobsgroups(jgroup)%sprofdata%nadd |
---|
580 | IF ( ll_write(jadd) ) THEN |
---|
581 | jadd2 = jadd2 + 1 |
---|
582 | sladd%ipoint(jadd2) = jadd |
---|
583 | sladd%cdname(jadd2) = sobsgroups(jgroup)%sprofdata%caddvars(jadd) |
---|
584 | DO jvar = 1, sobsgroups(jgroup)%sprofdata%nvar |
---|
585 | sladd%cdlong(jadd2,jvar) = sobsgroups(jgroup)%sprofdata%caddlong(jadd,jvar) |
---|
586 | sladd%cdunit(jadd2,jvar) = sobsgroups(jgroup)%sprofdata%caddunit(jadd,jvar) |
---|
587 | END DO |
---|
588 | ENDIF |
---|
589 | END DO |
---|
590 | ENDIF |
---|
591 | DEALLOCATE( ll_write ) |
---|
592 | |
---|
593 | slext%inum = sobsgroups(jgroup)%sprofdata%next |
---|
594 | ALLOCATE( ll_write(sobsgroups(jgroup)%sprofdata%next) ) |
---|
595 | ll_write(:) = .TRUE. |
---|
596 | IF ( (sobsgroups(jgroup)%nextvars > 0) .AND. & |
---|
597 | & (sobsgroups(jgroup)%sprofdata%next > sobsgroups(jgroup)%nextvars) ) THEN |
---|
598 | DO jext = sobsgroups(jgroup)%nextvars + 1, sobsgroups(jgroup)%sprofdata%next |
---|
599 | DO jext2 = 1, sobsgroups(jgroup)%nextvars |
---|
600 | IF ( TRIM(sobsgroups(jgroup)%sprofdata%cextvars(jext )) == & |
---|
601 | & TRIM(sobsgroups(jgroup)%sprofdata%cextvars(jext2)) ) THEN |
---|
602 | slext%inum = slext%inum - 1 |
---|
603 | ll_write(jext) = .FALSE. |
---|
604 | ENDIF |
---|
605 | END DO |
---|
606 | END DO |
---|
607 | ENDIF |
---|
608 | IF ( slext%inum > 0 ) THEN |
---|
609 | ALLOCATE( slext%ipoint(slext%inum), & |
---|
610 | & slext%cdname(slext%inum), & |
---|
611 | & slext%cdlong(slext%inum,1), & |
---|
612 | & slext%cdunit(slext%inum,1) ) |
---|
613 | jext2 = 0 |
---|
614 | DO jext = 1, sobsgroups(jgroup)%sprofdata%next |
---|
615 | IF ( ll_write(jext) ) THEN |
---|
616 | jext2 = jext2 + 1 |
---|
617 | slext%ipoint(jext2) = jext |
---|
618 | slext%cdname(jext2) = sobsgroups(jgroup)%sprofdata%cextvars(jext) |
---|
619 | slext%cdlong(jext2,1) = sobsgroups(jgroup)%sprofdata%cextlong(jext) |
---|
620 | slext%cdunit(jext2,1) = sobsgroups(jgroup)%sprofdata%cextunit(jext) |
---|
621 | ENDIF |
---|
622 | END DO |
---|
623 | ENDIF |
---|
624 | DEALLOCATE( ll_write ) |
---|
625 | |
---|
626 | CALL obs_wri_prof( sobsgroups(jgroup)%sprofdata, sobsgroups(jgroup)%cgroupname, sladd, slext ) |
---|
627 | |
---|
628 | IF ( sladd%inum > 0 ) THEN |
---|
629 | DEALLOCATE( sladd%ipoint, sladd%cdname, sladd%cdlong, sladd%cdunit ) |
---|
630 | ENDIF |
---|
631 | IF ( slext%inum > 0 ) THEN |
---|
632 | DEALLOCATE( slext%ipoint, slext%cdname, slext%cdlong, slext%cdunit ) |
---|
633 | ENDIF |
---|
634 | |
---|
635 | ELSEIF (sobsgroups(jgroup)%lsurf) THEN |
---|
636 | |
---|
637 | IF (sobsgroups(jgroup)%lvel) THEN |
---|
638 | iuvar = 0 |
---|
639 | ivvar = 0 |
---|
640 | DO jvar = 1, sobsgroups(jgroup)%nobstypes |
---|
641 | IF ( TRIM(sobsgroups(jgroup)%cobstypes(jvar)) == cobsname_uvel ) THEN |
---|
642 | iuvar = jvar |
---|
643 | ELSEIF ( TRIM(sobsgroups(jgroup)%cobstypes(jvar)) == cobsname_vvel ) THEN |
---|
644 | ivvar = jvar |
---|
645 | ENDIF |
---|
646 | END DO |
---|
647 | IF ( (iuvar > 0) .AND. (ivvar > 0) ) THEN |
---|
648 | |
---|
649 | ! For velocity data, rotate the model velocities to N/S, E/W |
---|
650 | ! using the compressed data structure. |
---|
651 | ALLOCATE( & |
---|
652 | & zu(sobsgroups(jgroup)%ssurfdataqc%nsurf), & |
---|
653 | & zv(sobsgroups(jgroup)%ssurfdataqc%nsurf) & |
---|
654 | & ) |
---|
655 | |
---|
656 | CALL obs_rotvel_surf( sobsgroups(jgroup)%ssurfdataqc, sobsgroups(jgroup)%n2dint, & |
---|
657 | & iuvar, ivvar, zu, zv ) |
---|
658 | |
---|
659 | DO jo = 1, sobsgroups(jgroup)%ssurfdataqc%nsurf |
---|
660 | sobsgroups(jgroup)%ssurfdataqc%rmod(jo,iuvar) = zu(jo) |
---|
661 | sobsgroups(jgroup)%ssurfdataqc%rmod(jo,ivvar) = zv(jo) |
---|
662 | END DO |
---|
663 | |
---|
664 | DEALLOCATE( zu ) |
---|
665 | DEALLOCATE( zv ) |
---|
666 | |
---|
667 | ELSE |
---|
668 | CALL ctl_stop( 'Could not identify velocity observation variables to rotate' ) |
---|
669 | END IF |
---|
670 | END IF |
---|
671 | |
---|
672 | CALL obs_surf_decompress( sobsgroups(jgroup)%ssurfdataqc, & |
---|
673 | & sobsgroups(jgroup)%ssurfdata, .TRUE., numout ) |
---|
674 | |
---|
675 | ! Put additional and extra variable information into obswriinfo structure |
---|
676 | ! used by obs_write. |
---|
677 | ! add/ext variables generated by the OBS code (1...sobsgroups(jgroup)%naddvars) |
---|
678 | ! may duplicate ones read in (%naddvars+1...sobsgroups(jgroup)%ssurfdata%nadd) |
---|
679 | ! Check for this, and if so only write out the version generated by the OBS code |
---|
680 | sladd%inum = sobsgroups(jgroup)%ssurfdata%nadd |
---|
681 | ALLOCATE( ll_write(sobsgroups(jgroup)%ssurfdata%nadd) ) |
---|
682 | ll_write(:) = .TRUE. |
---|
683 | IF ( (sobsgroups(jgroup)%naddvars > 0) .AND. & |
---|
684 | & (sobsgroups(jgroup)%ssurfdata%nadd > sobsgroups(jgroup)%naddvars) ) THEN |
---|
685 | DO jadd = sobsgroups(jgroup)%naddvars + 1, sobsgroups(jgroup)%ssurfdata%nadd |
---|
686 | DO jadd2 = 1, sobsgroups(jgroup)%naddvars |
---|
687 | IF ( TRIM(sobsgroups(jgroup)%ssurfdata%caddvars(jadd )) == & |
---|
688 | & TRIM(sobsgroups(jgroup)%ssurfdata%caddvars(jadd2)) ) THEN |
---|
689 | sladd%inum = sladd%inum - 1 |
---|
690 | ll_write(jadd) = .FALSE. |
---|
691 | ENDIF |
---|
692 | END DO |
---|
693 | END DO |
---|
694 | ENDIF |
---|
695 | IF ( sladd%inum > 0 ) THEN |
---|
696 | ALLOCATE( sladd%ipoint(sladd%inum), & |
---|
697 | & sladd%cdname(sladd%inum), & |
---|
698 | & sladd%cdlong(sladd%inum,sobsgroups(jgroup)%ssurfdata%nvar), & |
---|
699 | & sladd%cdunit(sladd%inum,sobsgroups(jgroup)%ssurfdata%nvar) ) |
---|
700 | jadd2 = 0 |
---|
701 | DO jadd = 1, sobsgroups(jgroup)%ssurfdata%nadd |
---|
702 | IF ( ll_write(jadd) ) THEN |
---|
703 | jadd2 = jadd2 + 1 |
---|
704 | sladd%ipoint(jadd2) = jadd |
---|
705 | sladd%cdname(jadd2) = sobsgroups(jgroup)%ssurfdata%caddvars(jadd) |
---|
706 | DO jvar = 1, sobsgroups(jgroup)%ssurfdata%nvar |
---|
707 | sladd%cdlong(jadd2,jvar) = sobsgroups(jgroup)%ssurfdata%caddlong(jadd,jvar) |
---|
708 | sladd%cdunit(jadd2,jvar) = sobsgroups(jgroup)%ssurfdata%caddunit(jadd,jvar) |
---|
709 | END DO |
---|
710 | ENDIF |
---|
711 | END DO |
---|
712 | ENDIF |
---|
713 | DEALLOCATE( ll_write ) |
---|
714 | |
---|
715 | slext%inum = sobsgroups(jgroup)%ssurfdata%nextra |
---|
716 | ALLOCATE( ll_write(sobsgroups(jgroup)%ssurfdata%nextra) ) |
---|
717 | ll_write(:) = .TRUE. |
---|
718 | IF ( (sobsgroups(jgroup)%nextvars > 0) .AND. & |
---|
719 | & (sobsgroups(jgroup)%ssurfdata%nextra > sobsgroups(jgroup)%nextvars) ) THEN |
---|
720 | DO jext = sobsgroups(jgroup)%nextvars + 1, sobsgroups(jgroup)%ssurfdata%nextra |
---|
721 | DO jext2 = 1, sobsgroups(jgroup)%nextvars |
---|
722 | IF ( TRIM(sobsgroups(jgroup)%ssurfdata%cextvars(jext )) == & |
---|
723 | & TRIM(sobsgroups(jgroup)%ssurfdata%cextvars(jext2)) ) THEN |
---|
724 | slext%inum = slext%inum - 1 |
---|
725 | ll_write(jext) = .FALSE. |
---|
726 | ENDIF |
---|
727 | END DO |
---|
728 | END DO |
---|
729 | ENDIF |
---|
730 | IF ( slext%inum > 0 ) THEN |
---|
731 | ALLOCATE( slext%ipoint(slext%inum), & |
---|
732 | & slext%cdname(slext%inum), & |
---|
733 | & slext%cdlong(slext%inum,1), & |
---|
734 | & slext%cdunit(slext%inum,1) ) |
---|
735 | jext2 = 0 |
---|
736 | DO jext = 1, sobsgroups(jgroup)%ssurfdata%nextra |
---|
737 | IF ( ll_write(jext) ) THEN |
---|
738 | jext2 = jext2 + 1 |
---|
739 | slext%ipoint(jext2) = jext |
---|
740 | slext%cdname(jext2) = sobsgroups(jgroup)%ssurfdata%cextvars(jext) |
---|
741 | slext%cdlong(jext2,1) = sobsgroups(jgroup)%ssurfdata%cextlong(jext) |
---|
742 | slext%cdunit(jext2,1) = sobsgroups(jgroup)%ssurfdata%cextunit(jext) |
---|
743 | ENDIF |
---|
744 | END DO |
---|
745 | ENDIF |
---|
746 | DEALLOCATE( ll_write ) |
---|
747 | |
---|
748 | CALL obs_wri_surf( sobsgroups(jgroup)%ssurfdata, sobsgroups(jgroup)%cgroupname, sladd, slext ) |
---|
749 | |
---|
750 | IF ( sladd%inum > 0 ) THEN |
---|
751 | DEALLOCATE( sladd%ipoint, sladd%cdname, sladd%cdlong, sladd%cdunit ) |
---|
752 | ENDIF |
---|
753 | IF ( slext%inum > 0 ) THEN |
---|
754 | DEALLOCATE( slext%ipoint, slext%cdname, slext%cdlong, slext%cdunit ) |
---|
755 | ENDIF |
---|
756 | |
---|
757 | ENDIF |
---|
758 | |
---|
759 | ENDIF |
---|
760 | |
---|
761 | END DO |
---|
762 | |
---|
763 | IF( ln_timing ) CALL timing_stop('dia_obs_wri') |
---|
764 | |
---|
765 | END SUBROUTINE dia_obs_wri |
---|
766 | |
---|
767 | SUBROUTINE calc_date( kstp, ddobs ) |
---|
768 | !!---------------------------------------------------------------------- |
---|
769 | !! *** ROUTINE calc_date *** |
---|
770 | !! |
---|
771 | !! ** Purpose : Get date in double precision YYYYMMDD.HHMMSS format |
---|
772 | !! |
---|
773 | !! ** Method : Get date in double precision YYYYMMDD.HHMMSS format |
---|
774 | !! |
---|
775 | !! ** Action : Get date in double precision YYYYMMDD.HHMMSS format |
---|
776 | !! |
---|
777 | !! ** Action : Get initial date in double precision YYYYMMDD.HHMMSS format |
---|
778 | !! |
---|
779 | !! History : |
---|
780 | !! ! 06-03 (K. Mogensen) Original code |
---|
781 | !! ! 06-05 (K. Mogensen) Reformatted |
---|
782 | !! ! 06-10 (A. Weaver) Cleaning |
---|
783 | !! ! 06-10 (G. Smith) Calculates initial date the same as method for final date |
---|
784 | !! ! 10-05 (D. Lea) Update to month length calculation for NEMO vn3.2 |
---|
785 | !! ! 2014-09 (D. Lea) New generic routine now deals with arbitrary initial time of day |
---|
786 | !!---------------------------------------------------------------------- |
---|
787 | USE phycst, ONLY : & ! Physical constants |
---|
788 | & rday |
---|
789 | USE dom_oce, ONLY : & ! Ocean space and time domain variables |
---|
790 | & rdt |
---|
791 | |
---|
792 | IMPLICIT NONE |
---|
793 | |
---|
794 | !! * Arguments |
---|
795 | REAL(KIND=dp), INTENT(OUT) :: ddobs ! Date in YYYYMMDD.HHMMSS |
---|
796 | INTEGER :: kstp |
---|
797 | |
---|
798 | !! * Local declarations |
---|
799 | INTEGER :: iyea ! date - (year, month, day, hour, minute) |
---|
800 | INTEGER :: imon |
---|
801 | INTEGER :: iday |
---|
802 | INTEGER :: ihou |
---|
803 | INTEGER :: imin |
---|
804 | INTEGER :: imday ! Number of days in month. |
---|
805 | REAL(wp) :: zdayfrc ! Fraction of day |
---|
806 | |
---|
807 | INTEGER, DIMENSION(12) :: imonth_len !: length in days of the months of the current year |
---|
808 | |
---|
809 | !!---------------------------------------------------------------------- |
---|
810 | !! Initial date initialization (year, month, day, hour, minute) |
---|
811 | !!---------------------------------------------------------------------- |
---|
812 | iyea = ndate0 / 10000 |
---|
813 | imon = ( ndate0 - iyea * 10000 ) / 100 |
---|
814 | iday = ndate0 - iyea * 10000 - imon * 100 |
---|
815 | ihou = nn_time0 / 100 |
---|
816 | imin = ( nn_time0 - ihou * 100 ) |
---|
817 | |
---|
818 | !!---------------------------------------------------------------------- |
---|
819 | !! Compute number of days + number of hours + min since initial time |
---|
820 | !!---------------------------------------------------------------------- |
---|
821 | zdayfrc = kstp * rdt / rday |
---|
822 | zdayfrc = zdayfrc - aint(zdayfrc) |
---|
823 | imin = imin + int( zdayfrc * 24 * 60 ) |
---|
824 | DO WHILE (imin >= 60) |
---|
825 | imin=imin-60 |
---|
826 | ihou=ihou+1 |
---|
827 | END DO |
---|
828 | DO WHILE (ihou >= 24) |
---|
829 | ihou=ihou-24 |
---|
830 | iday=iday+1 |
---|
831 | END DO |
---|
832 | iday = iday + kstp * rdt / rday |
---|
833 | |
---|
834 | !----------------------------------------------------------------------- |
---|
835 | ! Convert number of days (iday) into a real date |
---|
836 | !---------------------------------------------------------------------- |
---|
837 | |
---|
838 | CALL calc_month_len( iyea, imonth_len ) |
---|
839 | |
---|
840 | DO WHILE ( iday > imonth_len(imon) ) |
---|
841 | iday = iday - imonth_len(imon) |
---|
842 | imon = imon + 1 |
---|
843 | IF ( imon > 12 ) THEN |
---|
844 | imon = 1 |
---|
845 | iyea = iyea + 1 |
---|
846 | CALL calc_month_len( iyea, imonth_len ) ! update month lengths |
---|
847 | ENDIF |
---|
848 | END DO |
---|
849 | |
---|
850 | !---------------------------------------------------------------------- |
---|
851 | ! Convert it into YYYYMMDD.HHMMSS format. |
---|
852 | !---------------------------------------------------------------------- |
---|
853 | ddobs = iyea * 10000_dp + imon * 100_dp + & |
---|
854 | & iday + ihou * 0.01_dp + imin * 0.0001_dp |
---|
855 | |
---|
856 | END SUBROUTINE calc_date |
---|
857 | |
---|
858 | SUBROUTINE ini_date( ddobsini ) |
---|
859 | !!---------------------------------------------------------------------- |
---|
860 | !! *** ROUTINE ini_date *** |
---|
861 | !! |
---|
862 | !! ** Purpose : Get initial date in double precision YYYYMMDD.HHMMSS format |
---|
863 | !! |
---|
864 | !! ** Method : |
---|
865 | !! |
---|
866 | !! ** Action : |
---|
867 | !! |
---|
868 | !! History : |
---|
869 | !! ! 06-03 (K. Mogensen) Original code |
---|
870 | !! ! 06-05 (K. Mogensen) Reformatted |
---|
871 | !! ! 06-10 (A. Weaver) Cleaning |
---|
872 | !! ! 10-05 (D. Lea) Update to month length calculation for NEMO vn3.2 |
---|
873 | !! ! 2014-09 (D. Lea) Change to call generic routine calc_date |
---|
874 | !!---------------------------------------------------------------------- |
---|
875 | |
---|
876 | IMPLICIT NONE |
---|
877 | |
---|
878 | !! * Arguments |
---|
879 | REAL(KIND=dp), INTENT(OUT) :: ddobsini ! Initial date in YYYYMMDD.HHMMSS |
---|
880 | |
---|
881 | CALL calc_date( nit000 - 1, ddobsini ) |
---|
882 | |
---|
883 | END SUBROUTINE ini_date |
---|
884 | |
---|
885 | SUBROUTINE fin_date( ddobsfin ) |
---|
886 | !!---------------------------------------------------------------------- |
---|
887 | !! *** ROUTINE fin_date *** |
---|
888 | !! |
---|
889 | !! ** Purpose : Get final date in double precision YYYYMMDD.HHMMSS format |
---|
890 | !! |
---|
891 | !! ** Method : |
---|
892 | !! |
---|
893 | !! ** Action : |
---|
894 | !! |
---|
895 | !! History : |
---|
896 | !! ! 06-03 (K. Mogensen) Original code |
---|
897 | !! ! 06-05 (K. Mogensen) Reformatted |
---|
898 | !! ! 06-10 (A. Weaver) Cleaning |
---|
899 | !! ! 10-05 (D. Lea) Update to month length calculation for NEMO vn3.2 |
---|
900 | !! ! 2014-09 (D. Lea) Change to call generic routine calc_date |
---|
901 | !!---------------------------------------------------------------------- |
---|
902 | |
---|
903 | IMPLICIT NONE |
---|
904 | |
---|
905 | !! * Arguments |
---|
906 | REAL(dp), INTENT(OUT) :: ddobsfin ! Final date in YYYYMMDD.HHMMSS |
---|
907 | |
---|
908 | CALL calc_date( nitend, ddobsfin ) |
---|
909 | |
---|
910 | END SUBROUTINE fin_date |
---|
911 | |
---|
912 | END MODULE diaobs |
---|