1module increment_mod
2 ! MODULE increment_mod (prefix='inc' category='1. High-level functionality')
3 !
4 !:Purpose: To add a 4D increment to a given 4D background/reference state and
5 ! to output the results
6 !
7 use codePrecision_mod
8 use midasMpi_mod
9 use timeCoord_mod
10 use gridStateVector_mod
11 use gridStateVectorFileIO_mod
12 use interpolation_mod
13 use horizontalCoord_mod
14 use verticalCoord_mod
15 use humidityLimits_mod
16 use utilities_mod
17 use message_mod
18 use gridVariableTransforms_mod
19 use BMatrix_mod
20 use varNamelist_mod
21 implicit none
22 save
23 private
24
25 ! public procedures
26 public :: inc_computeHighResAnalysis, inc_writeIncAndAnalHighRes, inc_getIncrement, inc_writeIncrement
27 public :: inc_writeAnalysis, inc_analPostProcessing
28
29 ! namelist variables
30 integer :: writeNumBits ! number of bits to use when writing analysis and high-res increment
31 logical :: writeHiresIncrement ! choose to write the high-res increment to a file
32 logical :: imposeRttovHuLimits ! choose to impose "rttov" humidity limits to analysis
33 logical :: useAnalIncMask ! for LAM only, choose to apply scale factor from a mask file to the increment
34 character(len=12) :: etiket_anlm ! 'etiket' used when writing the analysis
35 character(len=12) :: etiket_rehm ! 'etiket' used when writing the high-res increment
36 character(len=12) :: etiket_rebm ! 'etiket' used when writing the low-res increment
37 character(len=12) :: hInterpolationDegree ! type of interpolation to use: 'LINEAR' or 'CUBIC'
38 logical :: applyLiebmann ! choose to apply Liebmann extrapolation to SST and/or sea ice
39 logical :: SSTSpread ! choose to apply spatial spreading of the SST increment onto land
40 integer :: SSTSpreadMaxBoxSize ! control the amount of SST increment spreading
41 character(len=10) :: SSTSubgrid ! select subgrid on which to apply spreading: 'Yin' or 'Yan'
42
43CONTAINS
44
45 !--------------------------------------------------------------------------
46 ! readNameList
47 !--------------------------------------------------------------------------
48 subroutine readNameList
49 !
50 !:Purpose: Reading NAMINC namelist by any subroutines in increment_mod module.
51 !
52 implicit none
53
54 ! Locals:
55 integer :: nulnam, ierr
56 integer, external :: fnom, fclos
57 logical, save :: nmlAlreadyRead = .false.
58
59 NAMELIST /NAMINC/ writeHiresIncrement, etiket_rehm, etiket_anlm, &
60 etiket_rebm, writeNumBits, imposeRttovHuLimits, hInterpolationDegree, &
61 useAnalIncMask, applyLiebmann, SSTSpread, SSTSpreadMaxBoxSize, SSTSubgrid
62
63 if ( .not. nmlAlreadyRead ) then
64 nmlAlreadyRead = .true.
65
66 !- Setting default values
67 writeHiresIncrement = .true.
68 imposeRttovHuLimits = .true.
69 useAnalIncMask = .false.
70 etiket_rehm = 'INCREMENT'
71 etiket_rebm = 'INCREMENT'
72 etiket_anlm = 'ANALYSIS'
73 writeNumBits = 16
74 hInterpolationDegree = 'LINEAR'
75 applyLiebmann = .false.
76 SSTSpread = .false.
77 SSTSpreadMaxBoxSize = 0
78 SSTsubgrid = ' '
79
80 if ( .not. utl_isNamelistPresent('NAMINC','./flnml') ) then
81 call msg('readNameList (inc)', &
82 'NAMINC is missing in the namelist. The default values will be taken.', &
83 mpiAll_opt=.false.)
84 else
85 ! Reading the namelist
86 nulnam = 0
87 ierr = fnom(nulnam, './flnml', 'FTN+SEQ+R/O', 0)
88 read(nulnam, nml=naminc, iostat=ierr)
89 if ( ierr /= 0) call utl_abort('readNameList: Error reading namelist')
90 ierr = fclos(nulnam)
91 end if
92 if ( mmpi_myid == 0 ) write(*,nml=naminc)
93 end if
94
95 end subroutine readNameList
96
97 !--------------------------------------------------------------------------
98 ! inc_computeHighResAnalysis
99 !--------------------------------------------------------------------------
100 subroutine inc_computeHighResAnalysis( statevectorIncLowRes, & ! IN
101 stateVectorUpdateHighRes, stateVectorPsfcHighRes) ! OUT
102 !
103 !:Purpose: Computing high-resolution analysis on the trial grid.
104 !
105 implicit none
106
107 ! Arguments:
108 type(struct_gsv), intent(in) :: statevectorIncLowRes
109 type(struct_gsv), intent(inout) :: stateVectorUpdateHighRes
110 type(struct_gsv), intent(out) :: stateVectorPsfcHighRes
111
112 ! Locals:
113 type(struct_gsv) :: statevectorRef, statevectorRefPsfc
114 type(struct_gsv) :: statevectorIncRefLowRes
115 type(struct_gsv) :: statevectorTrlRefVars
116 type(struct_gsv) :: statevectorTrlLowResTime
117 type(struct_gsv) :: statevectorTrlLowResVert
118 type(struct_gsv) :: statevector_mask
119 type(struct_gsv) :: stateVectorHighRes
120
121 type(struct_vco), pointer :: vco_trl, vco_inc
122 type(struct_hco), pointer :: hco_trl, hco_inc
123
124 real(pre_incrReal), pointer :: PsfcIncPrior(:,:,:,:), PsfcIncMasked(:,:,:,:)
125 real(pre_incrReal), pointer :: analIncMask(:,:,:)
126
127 integer :: stepIndex, numStep_inc, numStep_trl
128 integer, allocatable :: dateStampList(:)
129
130 character(len=4), allocatable :: varNamesRef(:), varNamesPsfc(:)
131 logical :: allocHeightSfc, refStateNeeded
132
133 call msg('inc_computeHighResAnalysis', 'START', verb_opt=2)
134 call msg_memUsage('inc_computeHighResAnalysis')
135
136 call utl_tmg_start(80,'--Increment')
137 call utl_tmg_start(81,'----ComputeHighResAnalysis')
138
139 ! Set/Read values for the namelist NAMINC
140 call readNameList
141
142 if ( gsv_isAllocated(stateVectorPsfcHighRes) ) then
143 call utl_abort('inc_computeHighResAnalysis: '&
144 //'stateVectorPsfcHighRes should not be allocated yet')
145 end if
146
147 ! If P0 present it is infered the statevector is a 3D atmospheric state
148 refStateNeeded = gsv_varExist(varName='P0')
149
150 ! Setup timeCoord module (date read from trial file)
151 numStep_inc = tim_nstepobsinc ! low-res time
152 numStep_trl = tim_nstepobs ! high-res time
153 allocate(dateStampList(numStep_inc))
154 call tim_getstamplist(dateStampList,numStep_inc,tim_getDatestamp())
155
156 hco_trl => gsv_getHco(stateVectorUpdateHighRes)
157 vco_trl => gsv_getVco(stateVectorUpdateHighRes)
158 hco_inc => gsv_getHco(statevectorIncLowRes)
159 vco_inc => gsv_getVco(statevectorIncLowRes)
160
161 if (vco_trl%Vcode == 0 .or. .not. gsv_varExist(varName='P0')) then
162 allocHeightSfc = .false.
163 else
164 allocHeightSfc = stateVectorUpdateHighRes%heightSfcPresent
165 end if
166
167 ! Read the analysis mask (in LAM mode only) - N.B. different from land/sea mask!!!
168 if (.not. hco_trl%global .and. useAnalIncMask) then
169 call gio_getMaskLAM(statevector_mask, hco_trl, vco_trl, hInterpolationDegree)
170 end if
171
172 ref_building: if ( refStateNeeded ) then
173 ! Build a reference variables
174 !
175 ! - Allocate the target reference statevector for vertical interpolation
176 ! that will be done in inc_interpolateAndAdd.
177 ! The reference needs to have the vertical structure of the input which is the
178 ! increment, but since horizontal interpolation is done first, it needs the
179 ! trial horizontal structure.
180 if (vco_trl%Vcode == 5100) then
181 allocate(varNamesRef(4))
182 varNamesRef = (/'P0', 'P0LS', 'TT', 'HU'/)
183 allocate(varNamesPsfc(2))
184 varNamesPsfc = (/'P0','P0LS'/)
185 else
186 allocate(varNamesRef(3))
187 varNamesRef = (/'P0', 'TT', 'HU'/)
188 allocate(varNamesPsfc(1))
189 varNamesPsfc = (/'P0'/)
190 end if
191 call gsv_allocate( statevectorRef, numStep_inc, hco_trl, vco_inc, &
192 dataKind_opt=pre_incrReal, &
193 dateStamp_opt=tim_getDateStamp(), mpi_local_opt=.true., &
194 varNames_opt=varNamesRef, allocHeightSfc_opt=allocHeightSfc, &
195 hInterpolateDegree_opt=hInterpolationDegree )
196
197 ! - Restriction of increment to only reference state variables
198 call gsv_allocate( statevectorIncRefLowRes, numStep_inc, hco_inc, vco_inc, &
199 dateStamp_opt=tim_getDateStamp(), mpi_local_opt=.true., &
200 dataKind_opt=pre_incrReal, varNames_opt=varNamesRef, &
201 allocHeightSfc_opt=allocHeightSfc)
202 call gsv_copy(statevectorIncLowRes, statevectorIncRefLowRes, &
203 allowVarMismatch_opt=.true.)
204
205 ! - Horizontal *only* interpolation of analysis increment (ref state variables)
206 ! using int_interp_gsv since it also does needed mpi transpositions
207 call msg('inc_computeHighResAnalysis', &
208 'horizontal interpolation of the Psfc increment', mpiAll_opt=.false.)
209 call int_interp_gsv(statevectorIncRefLowRes,statevectorRef)
210 call gsv_deallocate(statevectorIncRefLowRes)
211 !- Apply mask to increment in LAM
212 if (.not. hco_trl%global .and. useAnalIncMask) then
213 call gsv_getField(statevectorRef,PsfcIncPrior,'P0')
214 call gsv_getField(statevectorRef,PsfcIncMasked,'P0')
215 call gsv_getField(statevector_mask,analIncMask)
216 do stepIndex = 1, statevectorRef%numStep
217 PsfcIncMasked(:,:,1,stepIndex) = PsfcIncPrior(:,:,1,stepIndex) * analIncMask(:,:,1)
218 end do
219 if (gsv_varExist(statevectorRef,'P0LS')) then
220 call gsv_getField(statevectorRef,PsfcIncPrior,'P0LS')
221 call gsv_getField(statevectorRef,PsfcIncMasked,'P0LS')
222 do stepIndex = 1, statevectorRef%numStep
223 PsfcIncMasked(:,:,1,stepIndex) = PsfcIncPrior(:,:,1,stepIndex) * analIncMask(:,:,1)
224 end do
225 end if
226 end if
227
228 ! - Compute analysis of reference state variables to use for vertical interpolation
229 ! of increment
230 call msg('inc_computeHighResAnalysis', &
231 'Computing reference variables analysis to use for interpolation of increment', &
232 mpiAll_opt=.false.)
233
234 ! - build a restriction to reference state variables of trial
235 call gsv_allocate(statevectorTrlRefVars, numStep_trl, &
236 hco_trl, vco_trl, dateStamp_opt=tim_getDateStamp(), &
237 mpi_local_opt=.true., dataKind_opt=pre_incrReal, &
238 varNames_opt=varNamesRef, allocHeightSfc_opt=allocHeightSfc )
239 call gsv_copy(stateVectorUpdateHighRes, statevectorTrlRefVars,&
240 allowVarMismatch_opt=.true.)
241 ! - bring trial to low time res
242 call gsv_allocate(statevectorTrlLowResTime, numStep_inc, hco_trl, vco_trl, &
243 dateStamp_opt=tim_getDateStamp(), mpi_local_opt=.true., &
244 dataKind_opt=pre_incrReal, varNames_opt=varNamesRef, &
245 allocHeightSfc_opt=allocHeightSfc)
246 call gsv_copy(statevectorTrlRefVars, statevectorTrlLowResTime, &
247 allowTimeMismatch_opt=.true.)
248 ! - bring trial to low res (increment) vertical structure
249 ! (no vertical interpolation reference needed as it is a full state,
250 ! not a incremental state)
251 call gsv_allocate(statevectorTrlLowResVert, numStep_inc, hco_trl, vco_inc, &
252 dateStamp_opt=tim_getDateStamp(), mpi_local_opt=.true., &
253 dataKind_opt=pre_incrReal, varNames_opt=varNamesRef, &
254 allocHeightSfc_opt=allocHeightSfc)
255 call int_vInterp_gsv(statevectorTrlLowResTime, statevectorTrlLowResVert)
256 call gsv_deallocate(statevectorTrlLowResTime)
257 call gsv_deallocate(statevectorTrlRefVars)
258 ! - build the analysis reference state for the increment vertical interpolation.
259 ! At that stage, statevectorRef contains the increment on the trial
260 ! horizontal grid, but analysis vertical structure; consistent for addition.
261 call gsv_add(statevectorTrlLowResVert, statevectorRef)
262 call gsv_deallocate(statevectorTrlLowResVert)
263
264 ! - Time interpolation to get high-res Psfc analysis increment to output
265 call msg('inc_computeHighResAnalysis', &
266 'Time interpolation to get high-res Psfc analysis increment', &
267 mpiAll_opt=.false.)
268
269 ! - Restriction to P0 only + vco set on vco_trl for later consistency
270 call gsv_allocate(statevectorRefPsfc, numStep_inc, hco_trl, vco_trl, &
271 dataKind_opt=pre_incrReal, &
272 dateStamp_opt=tim_getDateStamp(), mpi_local_opt=.true., &
273 varNames_opt=varNamesPsfc, allocHeightSfc_opt=allocHeightSfc, &
274 hInterpolateDegree_opt=hInterpolationDegree )
275 call gsv_copy(statevectorRef, statevectorRefPsfc, allowVarMismatch_opt=.true., &
276 allowVcoMismatch_opt=.true.)
277 ! - high res time interpolation
278 call gsv_allocate(stateVectorPsfcHighRes, numStep_trl, hco_trl, vco_trl, &
279 dataKind_opt=pre_incrReal, &
280 dateStamp_opt=tim_getDateStamp(), mpi_local_opt=.true., &
281 varNames_opt=varNamesPsfc, allocHeightSfc_opt=allocHeightSfc, &
282 hInterpolateDegree_opt=hInterpolationDegree)
283 call int_tInterp_gsv(statevectorRefPsfc, stateVectorPsfcHighRes)
284 else ref_building
285 call msg('inc_computeHighResAnalysis','P0 not present, not computing reference', &
286 verb_opt=3)
287 end if ref_building
288
289 ! Compute the analysis
290 call msg('inc_computeHighResAnalysis', 'compute the analysis', mpiAll_opt=.false.)
291
292 ! Copy of trial to be passed to inc_interpolateAndAdd
293 call gsv_allocate( stateVectorHighRes, numStep_trl, hco_trl, vco_trl, &
294 dataKind_opt=stateVectorUpdateHighRes%dataKind, &
295 dateStamp_opt=tim_getDateStamp(), &
296 mpi_local_opt=stateVectorUpdateHighRes%mpi_local, &
297 allocHeightSfc_opt=stateVectorUpdateHighRes%heightSfcPresent, &
298 hInterpolateDegree_opt=hInterpolationDegree, &
299 allocHeight_opt=.false., allocPressure_opt=.false. )
300 call gsv_copy( stateVectorUpdateHighRes,stateVectorHighRes, &
301 allowVarMismatch_opt=.true.)
302
303 ! Interpolate low-res increments to high-res and add to the initial state
304 if (.not. hco_trl%global .and. useAnalIncMask) then
305 if ( refStateNeeded ) then
306 call inc_interpolateAndAdd(statevectorIncLowRes, stateVectorHighRes, &
307 statevectorRef_opt=statevectorRef, &
308 statevectorMaskLAM_opt=statevector_mask)
309 else
310 call inc_interpolateAndAdd(statevectorIncLowRes, stateVectorHighRes, &
311 statevectorMaskLAM_opt=statevector_mask)
312 end if
313 else
314 if ( refStateNeeded ) then
315 call inc_interpolateAndAdd(statevectorIncLowRes, stateVectorHighRes, &
316 statevectorRef_opt=statevectorRef)
317 else
318 call inc_interpolateAndAdd(statevectorIncLowRes, stateVectorHighRes)
319 end if
320 end if
321
322 call gsv_copy( stateVectorHighRes, stateVectorUpdateHighRes, &
323 allowVarMismatch_opt=.true.)
324 call gsv_deallocate(stateVectorHighRes)
325
326 if ( gsv_isAllocated(statevectorRef) ) call gsv_deallocate(statevectorRef)
327 if ( gsv_isAllocated(statevector_mask) ) call gsv_deallocate(statevector_mask)
328
329 call utl_tmg_stop(81)
330 call utl_tmg_stop(80)
331
332 call msg('inc_computeHighResAnalysis', 'END', verb_opt=2)
333
334 end subroutine inc_computeHighResAnalysis
335
336 !--------------------------------------------------------------------------
337 ! inc_analPostProcessing
338 !--------------------------------------------------------------------------
339 subroutine inc_analPostProcessing (stateVectorPsfcHighRes, stateVectorUpdateHighRes, & ! IN
340 stateVectorTrial, stateVectorPsfc, stateVectorAnal) ! OUT
341 !
342 !:Purpose: Post processing of the high resolution analysis including degrading
343 ! temporal resolution, variable transform, and humidity clipping.
344 !
345 implicit none
346
347 ! Arguments:
348 type(struct_gsv), intent(inout) :: stateVectorPsfcHighRes
349 type(struct_gsv), intent(in) :: stateVectorUpdateHighRes
350 type(struct_gsv), intent(out) :: stateVectorTrial
351 type(struct_gsv), intent(out) :: stateVectorPsfc
352 type(struct_gsv), intent(out) :: stateVectorAnal
353
354 ! Locals:
355 type(struct_vco), pointer :: vco_trl => null()
356 type(struct_hco), pointer :: hco_trl => null()
357 character(len=4), allocatable :: varNamesPsfc(:)
358
359 real(pre_incrReal), pointer :: oceanIce_ptr(:,:,:,:)
360
361 logical :: allocHeightSfc
362
363 call msg('inc_analPostProcessing', 'START', verb_opt=2)
364 call msg_memUsage('inc_analPostProcessing')
365
366 call utl_tmg_start(80,'--Increment')
367 call utl_tmg_start(82,'----AnalPostProcessing')
368
369 ! Re-read trials to make stateVectorTrial with degraded timesteps available
370 hco_trl => gsv_getHco(stateVectorUpdateHighRes)
371 vco_trl => gsv_getVco(stateVectorUpdateHighRes)
372 allocHeightSfc = ( vco_trl%Vcode /= 0 )
373
374 call gsv_allocate(stateVectorTrial, tim_nstepobsinc, hco_trl, vco_trl, &
375 dataKind_opt = pre_incrReal, &
376 dateStamp_opt = tim_getDateStamp(), mpi_local_opt = .true., &
377 allocHeightSfc_opt = allocHeightSfc, hInterpolateDegree_opt = 'LINEAR', &
378 allocHeight_opt = .false., allocPressure_opt = .false.)
379 call gsv_zero(stateVectorTrial)
380 call gio_readTrials(stateVectorTrial)
381 call msg_memUsage('inc_analPostProcessing')
382
383 if (vco_trl%Vcode == 0 .or. .not. gsv_varExist(varName='P0')) then
384 allocHeightSfc = .false.
385 else
386 allocHeightSfc = stateVectorTrial%heightSfcPresent
387 end if
388
389 if (vco_trl%Vcode == 5100) then
390 allocate(varNamesPsfc(2))
391 varNamesPsfc = (/'P0','P0LS'/)
392 else
393 allocate(varNamesPsfc(1))
394 varNamesPsfc = (/'P0'/)
395 end if
396
397 ! Degrade timesteps stateVector high-res Psfc, and high-res analysis
398 if (gsv_varExist(varName='P0')) then
399 call gsv_allocate(stateVectorPsfc, tim_nstepobsinc, hco_trl, vco_trl, &
400 dataKind_opt = pre_incrReal, &
401 dateStamp_opt = tim_getDateStamp(), mpi_local_opt = .true., &
402 varNames_opt = varNamesPsfc, allocHeightSfc_opt = allocHeightSfc, &
403 hInterpolateDegree_opt = hInterpolationDegree)
404 call gsv_copy(stateVectorPsfcHighRes, stateVectorPsfc, &
405 allowTimeMismatch_opt = .true., allowVarMismatch_opt=.true.)
406 call gsv_deallocate(stateVectorPsfcHighRes)
407 end if
408
409 call gsv_allocate(stateVectorAnal, tim_nstepobsinc, hco_trl, vco_trl, &
410 dataKind_opt = pre_incrReal, &
411 dateStamp_opt = tim_getDateStamp(), mpi_local_opt = .true., &
412 allocHeightSfc_opt = allocHeightSfc, hInterpolateDegree_opt = 'LINEAR', &
413 allocHeight_opt = .false., allocPressure_opt = .false.)
414 call gsv_copy(stateVectorUpdateHighRes, stateVectorAnal, &
415 allowVarMismatch_opt = .true., allowTimeMismatch_opt = .true.)
416
417 if (gsv_varExist(stateVectorAnal, 'GL')) then
418 ! Impose limits [0,1] on sea ice concentration analysis
419 call gsv_getField(stateVectorAnal, oceanIce_ptr, 'GL')
420 oceanIce_ptr(:,:,:,:) = min(oceanIce_ptr(:,:,:,:), 1.0d0)
421 oceanIce_ptr(:,:,:,:) = max(oceanIce_ptr(:,:,:,:), 0.0d0)
422 end if
423
424 if (applyLiebmann) then
425
426 ! Start the variable transformations
427 if (gsv_varExist(stateVectorAnal, 'GL')) then
428 if (gsv_varExist(stateVectorAnal, 'LG')) then
429 ! Compute the continuous sea ice concentration field (LG)
430 call gvt_transform(stateVectorAnal, 'oceanIceContinuous', stateVectorRef_opt = stateVectorTrial, varName_opt = 'LG')
431 end if
432 end if
433
434 ! Start the variable transformations
435 if(gsv_varExist(stateVectorAnal,'TM')) then
436 ! Compute the continuous SST field (TM)
437 call gvt_transform(stateVectorAnal, 'oceanIceContinuous', stateVectorRef_opt = stateVectorTrial, varName_opt = 'TM')
438 end if
439
440 end if
441
442 if (SSTSpread) then
443 if(gsv_varExist(stateVectorAnal,'TM')) then
444 ! Compute SST spreading (TM) on neigbouring land points
445 call gvt_transform(stateVectorAnal, 'SSTSpread', varName_opt = 'TM', maxBoxSize_opt = SSTSpreadMaxBoxSize, subgrid_opt = SSTSubgrid)
446 end if
447 end if
448
449 ! Convert all transformed variables into model variables (e.g. LVIS->VIS, LPR->PR) for analysis
450 call gvt_transform(stateVectorAnal, 'AllTransformedToModel', allowOverWrite_opt = .true.)
451
452 ! Impose limits on humidity analysis
453 call msg('inc_analPostProcessing', 'calling qlim_saturationLimit')
454 call qlim_saturationLimit(stateVectorAnal)
455 if (imposeRttovHuLimits) call qlim_rttovLimit(stateVectorAnal)
456
457 if (gsv_varKindExist('CH')) then
458 ! Apply boundaries to analysis of CH kind variables as needed.
459 call msg('inc_analPostProcessing', &
460 'applying minimum values to analysis for variables of CH kind')
461 call gvt_transform(stateVectorAnal, 'CH_bounds')
462 end if
463
464 call utl_tmg_stop(82)
465 call utl_tmg_stop(80)
466
467 call msg('inc_analPostProcessing', 'END', verb_opt=2)
468
469 end subroutine inc_analPostProcessing
470
471 !--------------------------------------------------------------------------
472 ! inc_writeIncAndAnalHighRes
473 !--------------------------------------------------------------------------
474 subroutine inc_writeIncAndAnalHighRes( stateVectorTrial, stateVectorPsfc, &
475 stateVectorAnal )
476 !
477 !:Purpose: Write the high-resolution analysis increments to the rehm file.
478 !
479 implicit none
480
481 ! Arguments:
482 type(struct_gsv), target, intent(inout) :: stateVectorTrial
483 type(struct_gsv), intent(inout) :: stateVectorPsfc
484 type(struct_gsv), intent(inout) :: stateVectorAnal
485
486 ! Locals:
487 type(struct_gsv) :: stateVectorIncHighRes
488 type(struct_gsv) :: stateVector_1step_r4, stateVectorPsfc_1step_r4
489 character(len=4), allocatable :: varNamesPsfc(:)
490
491 type(struct_vco), pointer :: vco_trl => null()
492 type(struct_hco), pointer :: hco_trl => null()
493
494 integer :: stepIndex, stepIndexBeg, stepIndexEnd, stepIndexToWrite, numStep
495 integer :: dateStamp, numBatch, batchIndex, procToWrite
496 integer, allocatable :: dateStampList(:)
497
498 character(len=256) :: incFileName, anlFileName
499 character(len=4) :: coffset
500 character(len=4), pointer :: varNames(:)
501
502 real(8) :: deltaHours
503 real(8), pointer :: HeightSfc_increment(:,:), HeightSfc_trial(:,:)
504
505 logical :: allocHeightSfc, writeHeightSfc
506
507 call msg('inc_writeIncAndAnalHighRes', 'START', verb_opt=2)
508 call msg_memUsage('inc_writeIncAndAnalHighRes')
509
510 call utl_tmg_start(80,'--Increment')
511 call utl_tmg_start(83,'----WriteIncAndAnalHighRes')
512
513 ! Setup timeCoord module (date read from trial file)
514 numStep = tim_nstepobsinc
515 allocate(dateStampList(numStep))
516 call tim_getstamplist(dateStampList,numStep,tim_getDatestamp())
517
518 hco_trl => gsv_getHco(stateVectorTrial)
519 vco_trl => gsv_getVco(stateVectorTrial)
520 if (vco_trl%Vcode == 0 .or. .not. gsv_varExist(varName='P0')) then
521 allocHeightSfc = .false.
522 else
523 allocHeightSfc = stateVectorTrial%heightSfcPresent
524 end if
525 writeHeightSfc = allocHeightSfc
526
527 if (vco_trl%Vcode == 5100) then
528 allocate(varNamesPsfc(2))
529 varNamesPsfc = (/'P0','P0LS'/)
530 else
531 allocate(varNamesPsfc(1))
532 varNamesPsfc = (/'P0'/)
533 end if
534
535 ! Convert all transformed variables into model variables (e.g. LVIS->VIS, LPR->PR) for original trial
536 call gvt_transform(stateVectorTrial, 'AllTransformedToModel',allowOverWrite_opt=.true.)
537
538 ! Copy the surface height from trial into stateVectorPsfc and stateVectorAnal
539 if ( allocHeightSfc ) then
540 HeightSfc_trial => gsv_getHeightSfc(stateVectorTrial)
541 HeightSfc_increment => gsv_getHeightSfc(stateVectorPsfc)
542 HeightSfc_increment(:,:) = HeightSfc_trial(:,:)
543
544 nullify(HeightSfc_increment)
545 HeightSfc_increment => gsv_getHeightSfc(stateVectorAnal)
546 HeightSfc_increment(:,:) = HeightSfc_trial(:,:)
547 end if
548
549 ! reAllocate incHighRes with the names of the model variables (e.g. VIS, PR)
550 nullify(varNames)
551 call gsv_varNamesList(varNames, stateVectorAnal)
552 call gsv_allocate(stateVectorIncHighRes, numStep, hco_trl, vco_trl, &
553 dataKind_opt=pre_incrReal, &
554 dateStamp_opt=tim_getDateStamp(), mpi_local_opt=.true., &
555 allocHeightSfc_opt=allocHeightSfc, hInterpolateDegree_opt=hInterpolationDegree, &
556 varNames_opt=varNames )
557
558 ! Recompute increments and write out the files in parallel with respect to time steps
559 call gsv_copy(stateVectorAnal, stateVectorIncHighRes)
560 call gsv_add(stateVectorTrial, stateVectorIncHighRes, -1.0d0)
561
562 ! figure out number of batches of time steps for writing
563 numBatch = ceiling(real(stateVectorAnal%numStep) / real(mmpi_nprocs))
564 call msg('inc_writeIncAndAnalHighRes', &
565 'writing will be done by number of batches = '//str(numBatch))
566
567 batch_loop: do batchIndex = 1, numBatch
568
569 stepIndexBeg = 1 + (batchIndex - 1) * mmpi_nprocs
570 stepIndexEnd = min(stateVectorAnal%numStep, stepIndexBeg + mmpi_nprocs - 1)
571 call msg('inc_writeIncAndAnalHighRes', 'batchIndex = '//str(batchIndex) &
572 //', stepIndexBeg = '//str(stepIndexBeg) &
573 //', stepIndexEnd = '//str(stepIndexEnd))
574
575 ! figure out which time step I will write, if any (-1 if none)
576 stepIndexToWrite = -1
577 do stepIndex = stepIndexBeg, stepIndexEnd
578 procToWrite = nint( real(stepIndex - stepIndexBeg) * real(mmpi_nprocs) / real(stepIndexEnd - stepIndexBeg + 1) )
579 if ( procToWrite == mmpi_myid ) stepIndexToWrite = stepIndex
580 call msg('inc_writeIncAndAnalHighRes', ' stepIndex = '//str(stepIndex) &
581 //', procToWrite = '//str(procToWrite), mpiAll_opt=.false.)
582 end do
583
584 ! determine date and allocate stateVector for storing just 1 time step, if I do writing
585 if ( stepIndexToWrite /= -1 ) then
586
587 dateStamp = stateVectorAnal%dateStampList(stepIndexToWrite)
588 call difdatr(dateStamp,tim_getDatestamp(),deltaHours)
589 if(nint(deltaHours*60.0d0).lt.0) then
590 write(coffset,'(I4.3)') nint(deltaHours*60.0d0)
591 else
592 write(coffset,'(I3.3)') nint(deltaHours*60.0d0)
593 endif
594
595 call gsv_allocate( stateVector_1step_r4, 1, stateVectorAnal%hco, stateVectorAnal%vco, &
596 dateStamp_opt=dateStamp, mpi_local_opt=.false., dataKind_opt=4, &
597 allocHeightSfc_opt=allocHeightSfc, &
598 varNames_opt=varNames )
599 call gsv_allocate( stateVectorPsfc_1step_r4, 1, stateVectorAnal%hco, stateVectorAnal%vco, &
600 dateStamp_opt=dateStamp, mpi_local_opt=.false., dataKind_opt=4, &
601 varNames_opt=varNamesPsfc, allocHeightSfc_opt=allocHeightSfc )
602 call gsv_zero(stateVectorPsfc_1step_r4)
603 end if
604
605 ! transpose ANALYSIS data from Tiles to Steps
606 call gsv_transposeTilesToStep(stateVector_1step_r4, stateVectorAnal, stepIndexBeg)
607
608 ! write the ANALYSIS file for one timestep on all tasks with data
609 if ( stepIndexToWrite /= -1 ) then
610 call msg_memUsage('inc_writeIncAndAnalHighRes')
611 anlFileName = './anlm_' // trim(coffset) // 'm'
612 call gio_writeToFile( stateVector_1step_r4, trim(anlFileName), etiket_anlm, &
613 typvar_opt='A', writeHeightSfc_opt=writeHeightSfc, &
614 numBits_opt=writeNumBits, containsFullField_opt=.true. )
615 end if
616
617 if (writeHiresIncrement) then
618
619 ! transpose INCREMENT data from Tiles to Steps
620 call gsv_transposeTilesToStep(stateVector_1step_r4, stateVectorIncHighRes, stepIndexBeg)
621
622 ! write the INCREMENT file for one timestep on all tasks with data
623 if ( stepIndexToWrite /= -1 ) then
624 call msg_memUsage('inc_writeIncAndAnalHighRes')
625 incFileName = './rehm_' // trim(coffset) // 'm'
626 call gio_writeToFile( stateVector_1step_r4, trim(incFileName), etiket_rehm, &
627 typvar_opt='R', &
628 numBits_opt=writeNumBits, containsFullField_opt=.false. )
629 end if
630
631 if (gsv_varExist(varName='P0')) then
632
633 ! transpose ANALYSIS PSFC AND height_SFC ONLY data from Tiles to Steps
634 call gsv_transposeTilesToStep(stateVectorPsfc_1step_r4, stateVectorPsfc, stepIndexBeg)
635
636 ! Also write analysis value of Psfc and surface height to increment file
637 if ( stepIndexToWrite /= -1 ) then
638 call msg_memUsage('inc_writeIncAndAnalHighRes')
639 incFileName = './rehm_' // trim(coffset) // 'm'
640 call gio_writeToFile( stateVectorPsfc_1step_r4, trim(incFileName), etiket_rehm, &
641 typvar_opt='A', writeHeightSfc_opt=writeHeightSfc, &
642 numBits_opt=writeNumBits, containsFullField_opt=.true. )
643 end if
644
645 end if
646
647 end if ! writeHiresIncrement
648
649 if ( stepIndexToWrite /= -1 ) then
650 call gsv_deallocate(stateVector_1step_r4)
651 call gsv_deallocate(stateVectorPsfc_1step_r4)
652 end if
653
654 end do batch_loop
655
656 call gsv_deallocate(stateVectorAnal)
657 if (gsv_varExist(varName='P0')) then
658 call gsv_deallocate(stateVectorPsfc)
659 end if
660 call gsv_deallocate(stateVectorIncHighRes)
661 call gsv_deallocate(stateVectorTrial)
662
663 call utl_tmg_stop(83)
664 call utl_tmg_stop(80)
665
666 call msg('inc_writeIncAndAnalHighRes', 'END', verb_opt=2)
667
668 end subroutine inc_writeIncAndAnalHighRes
669
670 !--------------------------------------------------------------------------
671 ! inc_getIncrement
672 !--------------------------------------------------------------------------
673 subroutine inc_getIncrement(incr_cv,statevector_incr,nvadim_mpilocal)
674 !
675 !:Purpose: Get true analysis increment from control vector.
676 !
677 implicit none
678
679 ! Arguments:
680 real(8), intent(in) :: incr_cv(:)
681 type(struct_gsv), intent(inout) :: statevector_incr
682 integer, intent(in) :: nvadim_mpilocal
683
684 call utl_tmg_start(80,'--Increment')
685 call utl_tmg_start(84,'----GetIncrement')
686
687 ! compute increment from control vector (multiply by B^1/2)
688 call bmat_sqrtB( incr_cv, nvadim_mpilocal, statevector_incr )
689
690 ! Compute new diagnotics based on NAMSTATE
691 if ( gsv_varExist(statevector_incr,'QR') .and. gsv_varExist(statevector_incr,'DD') ) then
692 call msg('inc_getIncrement', 'User is asking for Vort-Div analysis increment')
693 call gvt_transform( statevector_incr, & ! INOUT
694 'UVtoVortDiv' ) ! IN
695 if ( gsv_varExist(statevector_incr,'PP') .and. gsv_varExist(statevector_incr,'CC') ) then
696 call msg('inc_getIncrement', 'User is asking for Psi-Chi analysis increment')
697 call gvt_transform( statevector_incr, & ! INOUT
698 'VortDivToPsiChi') ! IN
699 end if
700 end if
701
702 call utl_tmg_stop(84)
703 call utl_tmg_stop(80)
704
705 end subroutine inc_getIncrement
706
707 !--------------------------------------------------------------------------
708 ! inc_writeIncrement
709 !--------------------------------------------------------------------------
710 subroutine inc_writeIncrement( stateVector_incr, &
711 ip3ForWriteToFile_opt )
712 !
713 !:Purpose: Write the low-resolution analysis increments to the rebm file.
714 !
715 implicit none
716
717 ! Arguments:
718 type(struct_gsv), intent(in) :: stateVector_incr
719 integer, optional, intent(in) :: ip3ForWriteToFile_opt
720
721 ! Locals:
722 integer :: stepIndex, dateStamp
723 real(8) :: deltaHours
724 character(len=4) :: coffset
725 character(len=30) :: fileName
726
727 call msg('inc_writeIncrement', 'START', verb_opt=2)
728
729 call utl_tmg_start(80,'--Increment')
730 call utl_tmg_start(85,'----WriteIncrement')
731
732 ! loop over times for which increment is computed
733 do stepIndex = 1, tim_nstepobsinc
734 if (gsv_isAllocated(statevector_incr)) then
735 dateStamp = gsv_getDateStamp(stateVector_incr,stepIndex)
736 call msg('inc_writeIncrement', 'writing increment for time step: ' &
737 //str(stepIndex)//', dateStamp = '//str(dateStamp), mpiAll_opt=.false.)
738
739 ! write the increment file for this time step
740 call difdatr(dateStamp,tim_getDatestamp(),deltaHours)
741 if(nint(deltaHours*60.0d0).lt.0) then
742 write(coffset,'(I4.3)') nint(deltaHours*60.0d0)
743 else
744 write(coffset,'(I3.3)') nint(deltaHours*60.0d0)
745 end if
746 fileName = './rebm_' // trim(coffset) // 'm'
747 call gio_writeToFile( stateVector_incr, fileName, etiket_rebm, scaleFactor_opt=1.0d0, &
748 ip3_opt=ip3ForWriteToFile_opt, stepIndex_opt=stepIndex, &
749 containsFullField_opt=.false. )
750 end if
751 end do
752
753 call utl_tmg_stop(85)
754 call utl_tmg_stop(80)
755
756 call msg('inc_writeIncrement', 'END', verb_opt=2)
757
758
759 end subroutine inc_writeIncrement
760
761 !--------------------------------------------------------------------------
762 ! inc_writeAnalysis
763 !--------------------------------------------------------------------------
764 subroutine inc_writeAnalysis(statevector_anal)
765 !:Purpose: To write to output standard file the analysid from statevector strucure (1Dvar case)
766 ! to output the results
767 !
768 implicit none
769
770 ! Arguments:
771 type(struct_gsv), intent(in) :: statevector_anal
772
773 ! Locals:
774 integer :: stepIndex, dateStamp
775 real(8) :: deltaHours
776 character(len=4) :: coffset
777 character(len=30) :: fileName
778
779 call msg('inc_writeAnalysis', 'START', verb_opt=2)
780
781 call utl_tmg_start(80,'--Increment')
782 call utl_tmg_start(86,'----WriteAnalysis')
783
784 !
785 !- Set/Read values for the namelist NAMINC
786 !
787 call readNameList()
788
789 ! loop over times for which increment is computed
790 do stepIndex = 1, tim_nstepobsinc
791 if (gsv_isAllocated(statevector_anal)) then
792 dateStamp = gsv_getDateStamp(statevector_anal,stepIndex)
793 call msg('inc_writeAnalysis', 'writing analysis for time step: ' &
794 //str(stepIndex)//', dateStamp = '//str(dateStamp), mpiAll_opt=.false.)
795
796 ! write the increment file for this time step
797 call difdatr(dateStamp,tim_getDatestamp(),deltaHours)
798 if(nint(deltaHours*60.0d0).lt.0) then
799 write(coffset,'(I4.3)') nint(deltaHours*60.0d0)
800 else
801 write(coffset,'(I3.3)') nint(deltaHours*60.0d0)
802 end if
803 fileName = './anlm_' // trim(coffset) // 'm'
804 call gio_writeToFile( statevector_anal, fileName, etiket_anlm, scaleFactor_opt = 1.0d0, &
805 ip3_opt = 0, stepIndex_opt = stepIndex, containsFullField_opt=.true. )
806 end if
807 end do
808
809 call utl_tmg_stop(86)
810 call utl_tmg_stop(80)
811
812 call msg('inc_writeAnalysis', 'END', verb_opt=2)
813 end subroutine inc_writeAnalysis
814
815 !--------------------------------------------------------------------------
816 ! inc_interpolateAndAdd
817 !--------------------------------------------------------------------------
818 subroutine inc_interpolateAndAdd(statevector_in,statevector_inout, &
819 statevectorRef_opt, statevectorMaskLAM_opt, &
820 scaleFactor_opt)
821 !
822 !:Purpose: Interpolate the low-resolution increments to trial grid and add to
823 ! get the high-resolution analysis.
824 !
825 implicit none
826
827 ! Arguments:
828 type(struct_gsv), target, intent(in) :: statevector_in
829 type(struct_gsv), intent(inout) :: statevector_inout
830 type(struct_gsv), optional, intent(in) :: statevectorRef_opt ! Reference statevector providing optional fields (P0, TT, HU)
831 type(struct_gsv), optional, intent(in) :: statevectorMaskLAM_opt
832 real(8), optional, intent(in) :: scaleFactor_opt
833
834 ! Locals:
835 type(struct_gsv) :: statevector_in_hvInterp
836 type(struct_gsv) :: statevector_in_hvtInterp
837 type(struct_gsv), target :: statevector_in_withP0LS
838 type(struct_gsv), pointer :: statevector_in_ptr
839
840 character(len=4), pointer :: varNamesToInterpolate(:), varNamesToInterpolate_withP0LS(:)
841
842 call msg('inc_interpolateAndAdd', 'START', verb_opt=2)
843
844 ! Error traps
845 if ( .not. gsv_isAllocated(statevector_in) ) then
846 call utl_abort('inc_interpolateAndAdd: gridStateVector_in not yet allocated! Aborting.')
847 end if
848 if ( .not. gsv_isAllocated(statevector_inout) ) then
849 call utl_abort('inc_interpolateAndAdd: gridStateVector_inout not yet allocated! Aborting.')
850 end if
851 if ( present(statevectorRef_opt) ) then
852 if ( statevector_in%numstep /= statevectorRef_opt%numstep) then
853 call utl_abort('inc_interpolateAndAdd: statevector_in and statevectorRef_opt numstep inconsistent')
854 end if
855 end if
856
857 nullify(varNamesToInterpolate)
858 call vnl_varNamesFromExistList(varNamesToInterpolate, statevector_in%varExistlist(:))
859
860 ! Check if P0LS needs to be added to the increment
861 if (statevector_inout%vco%vcode == 5100 .and. &
862 .not.gsv_varExist(statevector_in, 'P0LS')) then
863 varNamesToInterpolate_withP0LS => vnl_addToVarNames(varNamesToInterpolate,'P0LS')
864 call gsv_allocate(statevector_in_withP0LS, statevector_in%numstep, &
865 statevector_in%hco, statevector_in%vco, &
866 dateStamp_opt=tim_getDateStamp(), &
867 mpi_local_opt=statevector_in%mpi_local, mpi_distribution_opt='Tiles', &
868 dataKind_opt=statevector_in%dataKind, &
869 allocHeightSfc_opt=statevector_in%heightSfcPresent, &
870 varNames_opt=varNamesToInterpolate_withP0LS, &
871 hInterpolateDegree_opt=statevector_in%hInterpolateDegree)
872 call gsv_zero(statevector_in_withP0LS)
873 call gsv_copy(statevector_in, statevector_in_withP0LS, &
874 allowVarMismatch_opt=.true.)
875 statevector_in_ptr => statevector_in_withP0LS
876 deallocate(varNamesToInterpolate)
877 varNamesToInterpolate => varNamesToInterpolate_withP0LS
878 else
879 statevector_in_ptr => statevector_in
880 end if
881 ! Do the spatial interpolation of statevector_in onto the grid of statevector_inout
882 call gsv_allocate(statevector_in_hvInterp, statevector_in%numstep, &
883 statevector_inout%hco, statevector_inout%vco, &
884 dateStamp_opt=tim_getDateStamp(), &
885 mpi_local_opt=statevector_inout%mpi_local, mpi_distribution_opt='Tiles', &
886 dataKind_opt=statevector_inout%dataKind, &
887 allocHeightSfc_opt=statevector_inout%heightSfcPresent, &
888 varNames_opt=varNamesToInterpolate, &
889 hInterpolateDegree_opt=statevector_inout%hInterpolateDegree, &
890 hExtrapolateDegree_opt='VALUE' )
891
892 call int_interp_gsv(statevector_in, statevector_in_hvInterp, &
893 statevectorRef_opt=statevectorRef_opt)
894
895 ! Do the time interpolation
896 call gsv_allocate(statevector_in_hvtInterp, statevector_inout%numstep, &
897 statevector_inout%hco, statevector_inout%vco, &
898 dateStamp_opt=tim_getDateStamp(), &
899 mpi_local_opt=statevector_inout%mpi_local, mpi_distribution_opt='Tiles', &
900 dataKind_opt=statevector_inout%dataKind, &
901 allocHeightSfc_opt=statevector_inout%heightSfcPresent, &
902 varNames_opt=varNamesToInterpolate, &
903 hInterpolateDegree_opt=statevector_inout%hInterpolateDegree, &
904 hExtrapolateDegree_opt='VALUE' )
905 call int_tInterp_gsv(statevector_in_hvInterp, statevector_in_hvtInterp)
906 call gsv_deallocate(statevector_in_hvInterp)
907
908 ! Masking
909 if (present(statevectorMaskLAM_opt)) then
910 call gsv_applyMaskLAM(statevector_in_hvtInterp,statevectorMaskLAM_opt)
911 end if
912
913 ! Do the summation
914 call gsv_add(statevector_in_hvtInterp,statevector_inout,scaleFactor_opt=scaleFactor_opt)
915
916 call gsv_deallocate(statevector_in_hvtInterp)
917 deallocate(varNamesToInterpolate)
918
919 call msg('inc_interpolateAndAdd', 'END', verb_opt=2)
920
921 end subroutine inc_interpolateAndAdd
922
923END MODULE increment_mod