1module gridVariableTransforms_mod
2 ! MODULE gridVariableTransforms_mod (prefix='gvt' category='4. Data Object transformations')
3 !
4 !:Purpose: To store various functions for variable transforms using inputs
5 ! from gridStateVector(s). Outputs are also placed in a
6 ! gridStateVector.
7 !
8 use midasMpi_mod
9 use codePrecision_mod
10 use mathPhysConstants_mod
11 use earthConstants_mod
12 use timeCoord_mod
13 use gridStateVector_mod
14 use gridStateVectorFileIO_mod
15 use interpolation_mod
16 use ensembleStateVector_mod
17 use lamSpectralTransform_mod
18 use globalSpectralTransform_mod
19 use lamAnalysisGridTransforms_mod
20 use horizontalCoord_mod
21 use verticalCoord_mod
22 use utilities_mod
23 use varNameList_mod
24 use calcHeightAndPressure_mod
25 use utilities_mod
26 use humiditylimits_mod
27 use getGridPosition_mod
28
29 implicit none
30 save
31 private
32
33 ! public procedures
34 public :: gvt_setup, gvt_transform, gvt_getStateVectorTrial
35 public :: gvt_setupRefFromTrialFiles, gvt_setupRefFromStateVector
36
37 logical :: varKindCHTrialsInitialized(vnl_numVarMax) = .false.
38
39 type(struct_hco), pointer :: hco_anl => null()
40 type(struct_vco), pointer :: vco_anl => null()
41 type(struct_hco), pointer :: hco_trl => null()
42 type(struct_vco), pointer :: vco_trl => null()
43
44 type(struct_gsv), target :: stateVectorRefHU
45 type(struct_gsv), target :: stateVectorTrialvarKindCH(vnl_numVarMax)
46 type(struct_gsv), target :: stateVectorRefHeight
47
48 ! module interfaces
49 interface gvt_transform
50 module procedure gvt_transform_gsv
51 module procedure gvt_transform_ens
52 end interface gvt_transform
53
54CONTAINS
55
56 !--------------------------------------------------------------------------
57 ! gvt_setup
58 !--------------------------------------------------------------------------
59 subroutine gvt_setup(hco_in,hco_core,vco_in)
60 !
61 !:Purpose: To set up a variable transformation object
62 !
63 implicit none
64
65 ! Arguments:
66 type(struct_hco), pointer, intent(inout) :: hco_in
67 type(struct_hco), pointer, intent(inout) :: hco_core
68 type(struct_vco), pointer, intent(inout) :: vco_in
69
70 if ( gsv_containsNonZeroValues(stateVectorRefHU) ) return
71 if ( gsv_containsNonZeroValues(stateVectorRefHeight) ) return
72 if ( any(varKindCHTrialsInitialized(:)) ) return
73
74 write(*,*) 'gvt_setup: starting'
75
76 hco_anl => hco_in
77 vco_anl => vco_in
78
79 call lgt_setupFromHco(hco_anl,hco_core)
80
81 write(*,*) 'gvt_setup: done'
82
83 end subroutine gvt_setup
84
85 !--------------------------------------------------------------------------
86 ! gvt_setupRefFromTrialFiles
87 !--------------------------------------------------------------------------
88 subroutine gvt_setupRefFromTrialFiles(varName, varKind_opt)
89 !
90 !:Purpose: Initialise reference statevector from file
91 !
92 !:Arguments:
93 ! :varKind_opt: optional variable "kind" argument presently used to
94 ! initialise the reference state in a chemical assimilation
95 ! context.
96 !
97 implicit none
98
99 ! Arguments:
100 character(len=*), intent(in) :: varName ! reference variable/type used
101 character(len=*), optional, intent(in) :: varKind_opt ! additional variable/type information mandatory for some initialization
102
103 ! Locals:
104 type(struct_gsv) :: statevector_noZnoP
105 integer :: varIndex
106
107 select case ( trim(varName) )
108 case ('HU')
109 ! initialize stateVectorRefHU on analysis grid
110 call gsv_allocate(stateVectorRefHU, tim_nstepobsinc, hco_anl, vco_anl, &
111 dateStamp_opt=tim_getDateStamp(), &
112 mpi_local_opt=.true., allocHeightSfc_opt=.true., &
113 hInterpolateDegree_opt='LINEAR', &
114 varNames_opt=(/'HU','P0'/) )
115
116 ! read trial files using default horizontal interpolation degree
117 call gio_readTrials( stateVectorRefHU ) ! IN/OUT
118
119 case ('height')
120 if ( .not. gsv_isAllocated(stateVectorRefHeight) ) then
121 ! initialize stateVectorRefHeight on analysis grid
122 call gsv_allocate(stateVectorRefHeight, tim_nstepobsinc, hco_anl, &
123 vco_anl, dateStamp_opt=tim_getDateStamp(), &
124 mpi_local_opt=.true., allocHeightSfc_opt=.true., &
125 hInterpolateDegree_opt='LINEAR', &
126 varNames_opt=&
127 (/'Z_T','Z_M','P_T','P_M','TT','HU','P0'/) )
128 call gsv_zero(stateVectorRefHeight)
129 end if
130
131 ! initialize statevector_noZnoP on analysis grid
132 call gsv_allocate(statevector_noZnoP, tim_nstepobsinc, hco_anl, vco_anl, &
133 dateStamp_opt=tim_getDateStamp(), &
134 mpi_local_opt=.true., allocHeightSfc_opt=.true., &
135 hInterpolateDegree_opt='LINEAR', &
136 varNames_opt=(/'TT','HU','P0'/))
137 write(*,*) 'gvt_setupRefFromTrialFiles: statevector_noZnoP allocated'
138
139 ! read trial files using default horizontal interpolation degree
140 call gio_readTrials( statevector_noZnoP ) ! IN/OUT
141
142 ! copy the statevectors
143 call gsv_copy(statevector_noZnoP, stateVectorRefHeight, &
144 allowVarMismatch_opt=.true. )
145
146 call gsv_deallocate(statevector_noZnoP)
147
148 ! do height/P calculation of the grid
149 call czp_calcZandP_nl( stateVectorRefHeight )
150
151 case default
152 if ( present(varKind_opt) ) then
153 if (varKind_opt == 'CH' .and. &
154 vnl_varKindFromVarname(varName) == varKind_opt ) then
155
156 varIndex = vnl_varListIndex(varName)
157
158 ! initialize stateVectorTrialvarKindCH(varIndex) on analysis grid
159
160 call gsv_allocate(stateVectorTrialvarKindCH(varIndex), &
161 tim_nstepobsinc, hco_anl, vco_anl, &
162 dateStamp_opt=tim_getDateStamp(), &
163 mpi_local_opt=.true., allocHeightSfc_opt=.true., &
164 hInterpolateDegree_opt='LINEAR', &
165 varNames_opt=(/trim(varName),'P0'/) )
166
167 ! read trial files using default horizontal interpolation degree
168 call gio_readTrials( stateVectorTrialvarKindCH(varIndex) ) ! IN/OUT
169
170 varKindCHTrialsInitialized(varIndex) = .true.
171
172 else
173 call utl_abort('gvt_setupRefFromTrialFiles: unknown variable ='//trim(varName))
174 end if
175 else
176 call utl_abort('gvt_setupRefFromTrialFiles: unknown variable ='//trim(varName))
177 end if
178 end select
179
180 end subroutine gvt_setupRefFromTrialFiles
181
182 !--------------------------------------------------------------------------
183 ! gvt_transform_gsv
184 !--------------------------------------------------------------------------
185 subroutine gvt_transform_gsv(statevector, transform, statevectorOut_opt, &
186 stateVectorRef_opt, varName_opt, &
187 allowOverWrite_opt, maxBoxSize_opt, subgrid_opt )
188 !
189 !:Purpose: Top-level switch routine for transformations on the grid.
190 !
191 implicit none
192
193 ! Arguments:
194 type(struct_gsv), intent(inout) :: statevector ! statevector operand of the transformation
195 character(len=*), intent(in) :: transform ! string identifying the requested transformation
196 type(struct_gsv), optional, intent(inout) :: statevectorOut_opt
197 type(struct_gsv), optional, intent(in) :: statevectorRef_opt ! reference statevector necessary for some transformation
198 logical, optional, intent(in) :: allowOverWrite_opt
199 character(len=*), optional, intent(in) :: varName_opt ! additional variable/type info mandatory for some transformation
200 integer, optional, intent(in) :: maxBoxSize_opt ! additional info required by SSTSpread
201 character(len=*), optional, intent(in) :: subgrid_opt ! additional info required by SSTSpread to spread SST values
202
203 ! check stateVector and statevectorOut_opt are on the same grid
204 if ( present(stateVectorRef_opt) ) then
205 if ( .not. hco_equal(stateVectorRef_opt%hco, stateVector%hco) .or. &
206 .not. vco_equal(stateVectorRef_opt%vco, stateVector%vco) ) then
207 call utl_abort('gvt_transform: stateVectorRef_opt not on same grid as stateVector')
208 end if
209 end if
210
211 select case(trim(transform))
212
213 case ('AllTransformedToModel') ! Do all transformed variables: LPRtoPR, LVIStoVIS
214 if ( gsv_varExist(statevector,'LPR') ) then
215 write(*,*) 'gvt_transform: calling LPRtoPR stateVector transformation'
216 call LPRtoPR_gsv(statevector, statevectorOut_opt=statevectorOut_opt, &
217 allowOverWrite_opt=allowOverWrite_opt)
218 end if
219 if ( gsv_varExist(statevector,'LVIS') ) then
220 write(*,*) 'gvt_transform: calling LVIStoVIS stateVector transformation'
221 call LVIStoVIS(statevector, statevectorOut_opt=statevectorOut_opt, &
222 allowOverWrite_opt=allowOverWrite_opt)
223 end if
224
225 case ('UVtoVortDiv')
226 if (present(statevectorOut_opt)) then
227 call utl_abort('gvt_transform: for UVtoVortDiv, the option statevectorOut_opt is not yet available')
228 end if
229 call UVtoVortDiv_gsv(statevector)
230
231 case ('VortDivToPsiChi')
232 if (.not. gsv_varExist(statevector,'QR') .or. &
233 .not. gsv_varExist(statevector,'DD') ) then
234 call utl_abort('gvt_transform: for VortDivToPsiChi, variables QR and DD must be allocated in gridstatevector')
235 end if
236 if (present(statevectorOut_opt)) then
237 call utl_abort('gvt_transform: for VortDivToPsiChi, the option statevectorOut_opt is not yet available')
238 end if
239 call VortDivToPsiChi_gsv(statevector)
240
241 case ('UVtoPsiChi')
242 if (.not. gsv_varExist(statevector,'PP') .or. &
243 .not. gsv_varExist(statevector,'CC') ) then
244 call utl_abort('gvt_transform: for UVToPsiChi, variables PP and CC must be allocated in gridstatevector')
245 end if
246 if (present(statevectorOut_opt)) then
247 call utl_abort('gvt_transform: for UVToPsiChi, the option statevectorOut_opt is not yet available')
248 end if
249 call UVtoPsiChi_gsv(statevector)
250
251 case ('LQtoHU')
252 if ( .not. gsv_varExist(statevector,'HU') ) then
253 call utl_abort('gvt_transform: for LQtoHU, variable HU must be allocated in gridstatevector')
254 end if
255 if (present(statevectorOut_opt)) then
256 call utl_abort('gvt_transform: for LQtoHU, the option statevectorOut_opt is not yet available')
257 end if
258 call LQtoHU(statevector)
259
260 case ('HUtoLQ')
261 if ( .not. gsv_varExist(statevector,'HU') ) then
262 call utl_abort('gvt_transform: for HUtoLQ, variable HU must be allocated in gridstatevector')
263 end if
264 if (present(statevectorOut_opt)) then
265 call utl_abort('gvt_transform: for HUtoLQ, the option statevectorOut_opt is not yet available')
266 end if
267 call HUtoLQ_gsv(statevector)
268
269 case ('LQtoHU_tlm')
270 if ( .not. gsv_varExist(statevector,'HU') .and. &
271 .not. gsv_varExist(statevector,'LQ') ) then
272 call utl_abort('gvt_transform: for LQtoHU_tlm, variable HU or LQ must be allocated in gridstatevector')
273 end if
274 if ( gsv_varExist(statevector,'HU') .and. &
275 gsv_varExist(statevector,'LQ') ) then
276 call utl_abort('gvt_transform: for LQtoHU_tlm, only one of HU and LQ must be allocated in gridstatevector')
277 end if
278 if (present(statevectorOut_opt)) then
279 call utl_abort('gvt_transform: for LQtoHU_tlm, the option statevectorOut_opt is not yet available')
280 end if
281 call LQtoHU_tlm(statevector, stateVectorRef_opt)
282
283 case ('HUtoLQ_tlm')
284 if ( .not. gsv_varExist(statevector,'HU') ) then
285 call utl_abort('gvt_transform: for HUtoLQ_tlm, variable HU must be allocated in gridstatevector')
286 end if
287 if (present(statevectorOut_opt)) then
288 call utl_abort('gvt_transform: for HUtoLQ_tlm, the option statevectorOut_opt is not yet available')
289 end if
290 call HUtoLQ_tlm(statevector, stateVectorRef_opt)
291
292 case ('LQtoHU_ad')
293 if ( .not. gsv_varExist(statevector,'HU') ) then
294 call utl_abort('gvt_transform: for LQtoHU_ad, variable HU must be allocated in gridstatevector')
295 end if
296 if (present(statevectorOut_opt)) then
297 call utl_abort('gvt_transform: for LQtoHU_ad, the option statevectorOut_opt is not yet available')
298 end if
299 call LQtoHU_tlm(statevector, stateVectorRef_opt) ! self-adjoint
300
301 case ('HUtoLQ_ad')
302 if ( .not. gsv_varExist(statevector,'HU') ) then
303 call utl_abort('gvt_transform: for HUtoLQ_ad, variable HU must be allocated in gridstatevector')
304 end if
305 if (present(statevectorOut_opt)) then
306 call utl_abort('gvt_transform: for HUtoLQ_ad, the option statevectorOut_opt is not yet available')
307 end if
308 call HUtoLQ_tlm(statevector, stateVectorRef_opt) ! self-adjoint
309
310 case ('LPRoPR')
311 if ( .not. gsv_varExist(statevector,'PR') ) then
312 call utl_abort('gvt_transform: for LPRtoPR, variable PR must be allocated in gridstatevector')
313 end if
314 call LPRtoPR_gsv(statevector, statevectorOut_opt, &
315 allowOverWrite_opt=allowOverWrite_opt)
316
317 case ('PRtoLPR')
318 if ( .not. gsv_varExist(statevector,'PR') ) then
319 call utl_abort('gvt_transform: for PRtoLPR, variable PR must be allocated in gridstatevector')
320 end if
321 call PRtoLPR_gsv(statevector, statevectorOut_opt)
322
323 case ('LVIStoVIS')
324 if (present(statevectorOut_opt)) then
325 if ( .not. gsv_varExist(statevector,'LVIS')) then
326 call utl_abort('gvt_transform: for LVIStoVIS, variable LVIS must be allocated in gridstatevector IN')
327 end if
328 if ( .not. gsv_varExist(statevectorOut_opt,'VIS')) then
329 call utl_abort('gvt_transform: for LVIStoVIS, variable VIS must be allocated in gridstatevector OUT')
330 end if
331 call LVIStoVIS(statevector, statevectorOut_opt=statevectorOut_opt)
332 else
333 if (.not. gsv_varExist(statevector,'VIS') .or. &
334 .not. gsv_varExist(statevector,'LVIS') ) then
335 call utl_abort('gvt_transform: for LVIStoVIS, variables LVIS and VIS must be allocated in gridstatevector')
336 end if
337 call LVIStoVIS(statevector)
338 end if
339
340 case ('ZandP_nl')
341 if ( present(statevectorOut_opt) ) then
342 call utl_abort('gvt_transform: for ZandP_nl, the option statevectorOut_opt is not yet available')
343 end if
344 call czp_calcZandP_nl(stateVector)
345
346 case ('ZandP_tl')
347 if ( present(statevectorOut_opt) ) then
348 call utl_abort('gvt_transform: for ZandP_tl, the option statevectorOut_opt is not yet available')
349 end if
350 call ZandP_tl(stateVector)
351
352 case ('ZandP_ad')
353 if ( present(statevectorOut_opt) ) then
354 call utl_abort('gvt_transform: for ZandP_ad, the option statevectorOut_opt is not yet available')
355 end if
356 call ZandP_ad(stateVector)
357
358 case ('expCH_tlm')
359 if ( .not. gsv_varKindExist('CH') ) then
360 call utl_abort('gvt_transform: for expCH_tlm, variables of CH kind must be allocated in gridstatevector')
361 else if ( .not.present(varName_opt) ) then
362 call utl_abort('gvt_transform: for expCH_tlm, missing variable name')
363 else if ( .not. gsv_varExist(statevector,trim(varName_opt)) ) then
364 call utl_abort('gvt_transform: for expCH_tlm, variable '//trim(varName_opt)//' must be allocated in gridstatevector')
365 else if ( vnl_varKindFromVarname(trim(varName_opt)) /= 'CH' ) then
366 call utl_abort('gvt_transform: Invalid kind of varName for expCH_tlm')
367 else if ( .not. present(statevectorRef_opt)) then
368 call utl_abort('gvt_transform: for expCH_tlm, the option statevectorRef_opt must be present')
369 else if (present(statevectorOut_opt)) then
370 call utl_abort('gvt_transform: for expCH_tlm, the option statevectorOut_opt is not yet available')
371 end if
372 call expCH_tlm(statevector, varName_opt, stateVectorRef_opt)
373
374 case ('expCH_ad')
375 if ( .not. gsv_varKindExist('CH') ) then
376 call utl_abort('gvt_transform: for expCH_ad, variables of CH kind must be allocated in gridstatevector')
377 else if ( .not.present(varName_opt) ) then
378 call utl_abort('gvt_transform: for expCH_ad missing variable name')
379 else if ( .not. gsv_varExist(statevector,trim(varName_opt)) ) then
380 call utl_abort('gvt_transform: for expCH_ad, variable '//trim(varName_opt)//' must be allocated in gridstatevector')
381 else if ( vnl_varKindFromVarname(trim(varName_opt)) /= 'CH' ) then
382 call utl_abort('gvt_transform: Invalid kind of varName for expCH_ad')
383 else if ( .not. present(statevectorRef_opt)) then
384 call utl_abort('gvt_transform: for expCH_ad, the option statevectorRef_opt must be present')
385 else if (present(statevectorOut_opt)) then
386 call utl_abort('gvt_transform: for expCH_ad, the option statevectorOut_opt is not yet available')
387 end if
388 call expCH_tlm(statevector, varName_opt, stateVectorRef_opt) ! self-adjoint
389
390 case ('CH_bounds')
391 if ( .not. gsv_varKindExist('CH') ) then
392 call utl_abort('gvt_transform: for CH_bounds, variables of CH kind must be allocated in gridstatevector')
393 end if
394 call CH_bounds(statevector)
395
396 case ('oceanIceContinuous')
397 if (.not. present(statevectorRef_opt)) then
398 call utl_abort('gvt_transform: for gvt_oceanIceContinuous, the option statevectorRef_opt must be present')
399 end if
400 if (.not.present(varName_opt)) then
401 call utl_abort('gvt_transform: for gvt_oceanIceContinuous, missing variable name')
402 end if
403 call gvt_oceanIceContinuous(statevector, stateVectorRef_opt, varName_opt)
404
405 case ('SSTSpread')
406 if (.not.present(varName_opt)) then
407 call utl_abort('gvt_transform: for gvt_SSTSpread, missing variable name')
408 end if
409 if (.not.present(maxBoxSize_opt)) then
410 call utl_abort('gvt_transform: for gvt_SSTSpread, missing max box size')
411 end if
412 if (.not.present(subgrid_opt)) then
413 call utl_abort('gvt_transform: for gvt_SSTSpread, missing subgrid')
414 end if
415 call gvt_SSTSpread(statevector, varName_opt, maxBoxSize_opt, subgrid_opt)
416
417 case default
418 write(*,*)
419 write(*,*) 'Unsupported function : ', trim(transform)
420 call utl_abort('gvt_transform')
421 end select
422
423 end subroutine gvt_transform_gsv
424
425 !--------------------------------------------------------------------------
426 ! gvt_transform_ens
427 !--------------------------------------------------------------------------
428 subroutine gvt_transform_ens( ens,transform, allowOverWrite_opt, &
429 varName_opt, huMinValue_opt)
430 !
431 !:Purpose: Top-level switch routine for ensemble transformations on the
432 ! grid
433 !
434 implicit none
435
436 ! Arguments:
437 type(struct_ens), intent(inout) :: ens ! operand (ensemble of statevector)
438 character(len=*), intent(in) :: transform ! string identifying the requested transformation
439 logical, optional, intent(in) :: allowOverWrite_opt
440 character(len=*), optional, intent(in) :: varName_opt ! additional variable/type information mandatory for some transformation
441 real(8), optional, intent(in) :: huMinValue_opt ! HU min value for 'HUtoLQ' transformation
442
443 select case(trim(transform))
444 case ('AllTransformedToModel') ! Do all transformed variables: LPRtoPR
445 if ( ens_varExist(ens,'LPR') ) then
446 write(*,*) 'gvt_transform: calling LPRtoPR ensemble transformation'
447 call LPRtoPR_ens(ens, allowOverWrite_opt=allowOverWrite_opt)
448 end if
449 case ('HUtoLQ')
450 call HUtoLQ_ens(ens, huMinValue_opt=huMinValue_opt)
451 case ('LPRtoPR')
452 call LPRtoPR_ens(ens, allowOverWrite_opt=allowOverWrite_opt)
453 case ('UVtoPsiChi')
454 call UVtoPsiChi_ens(ens)
455 case ('UVtoVortDiv')
456 call UVtoVortDiv_ens(ens)
457 case ('logCH')
458 if ( .not.present(varName_opt) ) then
459 call utl_abort('gvt_transform: for logCH missing variable name')
460 else if ( vnl_varKindFromVarname(trim(varName_opt)) /= 'CH' ) then
461 call utl_abort('gvt_transform: Invalid kind of varName for logCH')
462 end if
463 call logCH_ens(ens,varName_opt)
464 case default
465 call utl_abort('gvt_transform_ens: Unsupported function '//trim(transform))
466 end select
467
468 end subroutine gvt_transform_ens
469
470 !--------------------------------------------------------------------------
471 ! gvt_getStateVectorTrial
472 !--------------------------------------------------------------------------
473 function gvt_getStateVectorTrial(varName) result(statevector_ptr)
474 !
475 !:Purpose: Returns a pointer to requested reference statevector
476 !
477 implicit none
478
479 ! Arguments:
480 character(len=*), intent(in) :: varName ! reference variable/type requested
481 ! Result:
482 type(struct_gsv), pointer :: statevector_ptr
483
484 select case ( trim(varName) )
485 case ('HU')
486 if ( .not. gsv_containsNonZeroValues(stateVectorRefHU) ) then
487 call utl_abort('gvt_getStateVectorTrial: do trials to stateVectorRefHU transform at higher level')
488 end if
489 statevector_ptr => stateVectorRefHU
490
491 case ('height')
492 if ( .not. gsv_containsNonZeroValues(stateVectorRefHeight) ) then
493 call utl_abort('gvt_getStateVectorTrial: do trials to stateVectorRefHeight transform at higher level')
494 end if
495 statevector_ptr => stateVectorRefHeight
496
497 case default
498 call utl_abort('gvt_getStateVectorTrial: unknown variable ='//trim(varName))
499 end select
500
501 end function gvt_getStateVectorTrial
502
503 !--------------------------------------------------------------------------
504 ! gvt_setupRefFromStateVector
505 !--------------------------------------------------------------------------
506 subroutine gvt_setupRefFromStateVector( stateVectorOnTrlGrid, varName, &
507 applyLimitOnHU_opt )
508 !
509 !:Purpose: computing the reference stateVector on the analysis grid at each
510 ! outer-loop iteration. The calculation is skipped if stateVectorRef* is
511 ! initialized (gsv_containsNonZeroValue(stateVectorRef*)=.true.).
512 ! The input stateVector is the high spatial/temporal resolution
513 ! statevector used for reading the trials and should contain
514 ! TT/HU/P0 if stateVectorRefHeight is asked for.
515 !
516 implicit none
517
518 ! Arguments:
519 type(struct_gsv), intent(in) :: stateVectorOnTrlGrid ! high spatial/temporal resolution statevector
520 character(len=*), intent(in) :: varName ! reference variable/type used
521 logical, optional, intent(in) :: applyLimitOnHU_opt
522
523 ! Locals:
524 type(struct_gsv) :: stateVectorLowResTime
525 type(struct_gsv) :: stateVectorLowResTimeSpace
526 type(struct_gsv), target :: stateVectorRefHUTT
527 logical :: allocHeightSfc
528 character(len=4), pointer :: varNames(:)
529
530 if ( mmpi_myid == 0 ) write(*,*) 'gvt_setupRefFromStateVector: START ', trim(varName)
531
532 if ( .not. associated(hco_trl) ) hco_trl => gsv_getHco(stateVectorOnTrlGrid)
533 if ( .not. associated(vco_trl) ) vco_trl => gsv_getVco(stateVectorOnTrlGrid)
534
535 select case ( trim(varName) )
536 case ('HU')
537 if ( .not. present(applyLimitOnHU_opt) ) then
538 call utl_abort('gvt_setupRefFromStateVector: applyLimitOnHU_opt for RefHU missing')
539 end if
540
541 if ( .not. gsv_isAllocated(stateVectorRefHU) ) then
542 call gsv_allocate(stateVectorRefHU, tim_nstepobsinc, hco_anl, vco_anl,&
543 dateStamp_opt=tim_getDateStamp(), &
544 mpi_local_opt=.true., allocHeightSfc_opt=.true., &
545 hInterpolateDegree_opt='LINEAR', &
546 varNames_opt=(/'HU','P0'/) )
547 else
548 call gsv_zero( stateVectorRefHU )
549 end if
550
551 allocHeightSfc = ( vco_trl%Vcode /= 0 )
552
553 call gsv_allocate(stateVectorRefHUTT, tim_nstepobsinc, hco_anl, vco_anl,&
554 dateStamp_opt=tim_getDateStamp(),&
555 mpi_local_opt=.true., allocHeightSfc_opt=.true., &
556 hInterpolateDegree_opt='LINEAR', &
557 varNames_opt=(/'HU','TT','P0'/) )
558
559 ! First, degrade the time steps
560 call gsv_allocate(stateVectorLowResTime, tim_nstepobsinc, hco_trl, &
561 vco_trl, dataKind_opt=pre_incrReal, &
562 dateStamp_opt=tim_getDateStamp(), mpi_local_opt=.true.,&
563 allocHeightSfc_opt=allocHeightSfc, &
564 hInterpolateDegree_opt='LINEAR', &
565 allocHeight_opt=.false., allocPressure_opt=.false. )
566 call gsv_copy( stateVectorOnTrlGrid, stateVectorLowResTime, &
567 allowTimeMismatch_opt=.true., allowVarMismatch_opt=.true. )
568
569 ! Second, interpolate to the low-resolution spatial grid.
570 nullify(varNames)
571 call gsv_varNamesList(varNames, stateVectorLowResTime)
572 call gsv_allocate(stateVectorLowResTimeSpace, tim_nstepobsinc, hco_anl, &
573 vco_anl, dataKind_opt=pre_incrReal, &
574 dateStamp_opt=tim_getDateStamp(), mpi_local_opt=.true.,&
575 allocHeightSfc_opt=.true., &
576 hInterpolateDegree_opt='LINEAR', varNames_opt=varNames)
577 call int_interp_gsv(stateVectorLowResTime, stateVectorLowResTimeSpace)
578
579 ! Now copy only P0, HU, and TT to create reference stateVector.
580 call gsv_copy(stateVectorLowResTimeSpace, stateVectorRefHUTT, &
581 allowTimeMismatch_opt=.false., allowVarMismatch_opt=.true.)
582 call gsv_deallocate(stateVectorLowResTimeSpace)
583 call gsv_deallocate(stateVectorLowResTime)
584
585 ! Impose humidity limits on stateVectorRefHUTT
586 if ( applyLimitOnHU_opt ) then
587 write(*,*) 'var: impose limits on stateVectorRefHUTT'
588 call qlim_saturationLimit(stateVectorRefHUTT)
589 call qlim_rttovLimit(stateVectorRefHUTT)
590 end if
591
592 call gsv_copy(stateVectorRefHUTT, stateVectorRefHU, &
593 allowTimeMismatch_opt=.false., allowVarMismatch_opt=.true.)
594 call gsv_deallocate(stateVectorRefHUTT)
595
596 case ('height')
597 if ( .not. gsv_isAllocated(stateVectorRefHeight) ) then
598 call gsv_allocate( stateVectorRefHeight, tim_nstepobsinc, hco_anl, &
599 vco_anl, dateStamp_opt=tim_getDateStamp(), &
600 mpi_local_opt=.true., allocHeightSfc_opt=.true., &
601 hInterpolateDegree_opt='LINEAR', &
602 varNames_opt=&
603 (/'Z_T','Z_M','P_T','P_M','TT','HU','P0','P0LS'/) )
604 else
605 call gsv_zero( stateVectorRefHeight )
606 end if
607
608 ! First, degrade the time steps
609 nullify(varNames)
610 call gsv_varNamesList(varNames, stateVectorRefHeight)
611 call gsv_allocate(stateVectorLowResTime, tim_nstepobsinc, hco_trl, &
612 vco_trl, dateStamp_opt=tim_getDateStamp(), &
613 mpi_local_opt=.true., allocHeightSfc_opt=.true., &
614 hInterpolateDegree_opt='LINEAR', &
615 varNames_opt=varNames )
616 call gsv_copy(stateVectorOnTrlGrid, stateVectorLowResTime, &
617 allowTimeMismatch_opt=.true., allowVarMismatch_opt=.true.)
618
619 ! Second, interpolate to the low-resolution spatial grid.
620 nullify(varNames)
621 call gsv_varNamesList(varNames, stateVectorLowResTime)
622 call gsv_allocate(stateVectorLowResTimeSpace, tim_nstepobsinc, hco_anl,&
623 vco_anl, dateStamp_opt=tim_getDateStamp(), &
624 mpi_local_opt=.true., allocHeightSfc_opt=.true., &
625 hInterpolateDegree_opt='LINEAR', varNames_opt=varNames)
626 call int_interp_gsv(stateVectorLowResTime, stateVectorLowResTimeSpace)
627
628 ! Now copy to create final stateVector height.
629 call gsv_copy(stateVectorLowResTimeSpace, stateVectorRefHeight, &
630 allowTimeMismatch_opt=.false., allowVarMismatch_opt=.true.)
631 call gsv_deallocate(stateVectorLowResTimeSpace)
632 call gsv_deallocate(stateVectorLowResTime)
633
634 ! do height/P calculation of the grid
635 call czp_calcZandP_nl(stateVectorRefHeight)
636
637 end select
638
639 if ( mmpi_myid == 0 ) write(*,*) 'gvt_setupRefFromStateVector: END'
640
641 end subroutine gvt_setupRefFromStateVector
642
643 !--------------------------------------------------------------------------
644 ! LQtoHU
645 !--------------------------------------------------------------------------
646 subroutine LQtoHU(statevector)
647 !
648 !:Purpose: Specific humidity logarithm exponentiation.
649 !
650 implicit none
651
652 ! Arguments:
653 type(struct_gsv), intent(inout) :: statevector
654
655 ! Locals:
656 integer :: lonIndex,latIndex,levIndex,stepIndex
657 real(8), pointer :: hu_ptr(:,:,:,:), lq_ptr(:,:,:,:)
658
659 call gsv_getField(statevector,hu_ptr,'HU')
660 call gsv_getField(statevector,lq_ptr,'HU')
661
662 do stepIndex = 1, statevector%numStep
663 !$OMP PARALLEL DO PRIVATE(lonIndex,latIndex,levIndex)
664 do levIndex = 1, gsv_getNumLev(statevector,vnl_varLevelFromVarname('HU'))
665 do latIndex = statevector%myLatBeg, statevector%myLatEnd
666 do lonIndex = statevector%myLonBeg, statevector%myLonEnd
667 hu_ptr(lonIndex,latIndex,levIndex,stepIndex) = &
668 exp(lq_ptr(lonIndex,latIndex,levIndex,stepIndex))
669 end do
670 end do
671 end do
672 !$OMP END PARALLEL DO
673 end do
674
675 end subroutine LQtoHU
676
677 !--------------------------------------------------------------------------
678 ! HUtoLQ_gsv
679 !--------------------------------------------------------------------------
680 subroutine HUtoLQ_gsv(statevector)
681 !
682 !:Purpose: Logarithmic transformation of specific humidity
683 !
684 implicit none
685
686 ! Arguments:
687 type(struct_gsv), intent(inout) :: statevector
688
689 ! Locals:
690 integer :: lonIndex,latIndex,levIndex,stepIndex
691 real(4), pointer :: hu_ptr_r4(:,:,:,:), lq_ptr_r4(:,:,:,:)
692 real(8), pointer :: hu_ptr_r8(:,:,:,:), lq_ptr_r8(:,:,:,:)
693
694 if ( gsv_getDataKind(statevector) == 8 ) then
695
696 call gsv_getField(statevector,hu_ptr_r8,'HU')
697 call gsv_getField(statevector,lq_ptr_r8,'HU')
698
699 do stepIndex = 1, statevector%numStep
700 !$OMP PARALLEL DO PRIVATE(lonIndex,latIndex,levIndex)
701 do levIndex = 1, gsv_getNumLev(statevector,vnl_varLevelFromVarname('HU'))
702 do latIndex = statevector%myLatBeg, statevector%myLatEnd
703 do lonIndex = statevector%myLonBeg, statevector%myLonEnd
704 lq_ptr_r8(lonIndex,latIndex,levIndex,stepIndex) = &
705 log(max(hu_ptr_r8(lonIndex,latIndex,levIndex,stepIndex),&
706 gsv_rhumin) )
707 end do
708 end do
709 end do
710 !$OMP END PARALLEL DO
711 end do
712
713 else
714
715 call gsv_getField(statevector,hu_ptr_r4,'HU')
716 call gsv_getField(statevector,lq_ptr_r4,'HU')
717
718 do stepIndex = 1, statevector%numStep
719 !$OMP PARALLEL DO PRIVATE(lonIndex,latIndex,levIndex)
720 do levIndex = 1, gsv_getNumLev(statevector,vnl_varLevelFromVarname('HU'))
721 do latIndex = statevector%myLatBeg, statevector%myLatEnd
722 do lonIndex = statevector%myLonBeg, statevector%myLonEnd
723 lq_ptr_r4(lonIndex,latIndex,levIndex,stepIndex) = &
724 log(max(hu_ptr_r4(lonIndex,latIndex,levIndex,stepIndex),&
725 real(gsv_rhumin,4)) )
726 end do
727 end do
728 end do
729 !$OMP END PARALLEL DO
730 end do
731
732 end if
733
734 end subroutine HUtoLQ_gsv
735
736 !--------------------------------------------------------------------------
737 ! HUtoLQ_ens
738 !--------------------------------------------------------------------------
739 subroutine HUtoLQ_ens(ens, huMinValue_opt)
740 !
741 !:Purpose: Specific humidity logarithm exponentiation (ensemble processing)
742 !
743 implicit none
744
745 ! Arguments:
746 type(struct_ens), intent(inout) :: ens
747 real(8), optional, intent(in) :: huMinValue_opt
748
749 ! Locals:
750 integer :: lonIndex, latIndex, levIndex, stepIndex, memberIndex
751 integer :: myLatBeg, myLatEnd, myLonBeg, myLonEnd
752 character(len=4) :: varName
753 real(4), pointer :: ptr4d_r4(:,:,:,:)
754 real(4) :: huMinValue
755
756 if (present(huMinValue_opt)) then
757 huMinValue = huMinValue_opt
758 else
759 huMinValue = MPC_MINIMUM_HU_R4
760 end if
761
762 call ens_getLatLonBounds(ens, myLonBeg, myLonEnd, myLatBeg, myLatEnd)
763
764 do levIndex = 1, ens_getNumK(ens)
765
766 varName = ens_getVarNameFromK(ens,levIndex)
767 if (varName /= 'HU') cycle
768
769 ptr4d_r4 => ens_getOneLev_r4(ens,levIndex)
770
771 do latIndex = myLatBeg, myLatEnd
772 do lonIndex = myLonBeg, myLonEnd
773 do stepIndex = 1, ens_getNumStep(ens)
774 do memberIndex = 1, ens_getNumMembers(ens)
775 ptr4d_r4(memberIndex,stepIndex,lonIndex,latIndex) = &
776 log(max( ptr4d_r4(memberIndex,stepIndex,lonIndex,latIndex),&
777 huMinValue) )
778 end do
779 end do
780 end do
781 end do
782
783 end do
784
785 end subroutine HUtoLQ_ens
786
787 !--------------------------------------------------------------------------
788 ! LQtoHU_tlm
789 !--------------------------------------------------------------------------
790 subroutine LQtoHU_tlm(statevector, stateVectorRef_opt)
791 !
792 !:Purpose: Tangent linear of exponentiation transformation of specific
793 ! humidity in logarithmic representation
794 !
795 implicit none
796
797 ! Arguments:
798 type(struct_gsv), intent(inout) :: statevector
799 type(struct_gsv), optional, intent(in) :: statevectorRef_opt
800
801 ! Locals:
802 integer :: lonIndex,latIndex,levIndex,stepIndex
803 real(8), pointer :: hu_ptr_r8(:,:,:,:), lq_ptr_r8(:,:,:,:)
804 real(8), pointer :: hu_trial(:,:,:,:)
805 real(4), pointer :: hu_ptr_r4(:,:,:,:), lq_ptr_r4(:,:,:,:)
806 character(len=4) :: varName
807
808 if ( gsv_varExist(statevector,'HU') ) then
809 varName = 'HU'
810 else if ( gsv_varExist(statevector,'LQ') ) then
811 varName = 'LQ'
812 else
813 call utl_abort('LQtoHU_tlm: either HU or LQ must be part of stateVector')
814 end if
815
816 if ( present(statevectorRef_opt) ) then
817 call gsv_getField(stateVectorRef_opt,hu_trial,'HU')
818 else
819 if ( .not. gsv_containsNonZeroValues(stateVectorRefHU) ) then
820 call utl_abort('LQtoHU_tlm: do trials to stateVectorRefHU transform at higher level')
821 end if
822 call gsv_getField(stateVectorRefHU,hu_trial,'HU')
823 end if
824
825 if ( gsv_getDataKind(statevector) == 4 ) then
826 call gsv_getField(statevector,hu_ptr_r4,varName)
827 call gsv_getField(statevector,lq_ptr_r4,varName)
828
829 do stepIndex = 1, statevector%numStep
830 !$OMP PARALLEL DO PRIVATE(lonIndex,latIndex,levIndex)
831 do levIndex = 1, gsv_getNumLev(statevector,vnl_varLevelFromVarname('HU'))
832 do latIndex = statevector%myLatBeg, statevector%myLatEnd
833 do lonIndex = statevector%myLonBeg, statevector%myLonEnd
834 hu_ptr_r4(lonIndex,latIndex,levIndex,stepIndex) = &
835 lq_ptr_r4(lonIndex,latIndex,levIndex,stepIndex)* &
836 max( hu_trial(lonIndex,latIndex,levIndex,stepIndex),&
837 MPC_MINIMUM_HU_R4)
838 end do
839 end do
840 end do
841 !$OMP END PARALLEL DO
842 end do
843 else
844 call gsv_getField(statevector,hu_ptr_r8,varName)
845 call gsv_getField(statevector,lq_ptr_r8,varName)
846
847 do stepIndex = 1, statevector%numStep
848 !$OMP PARALLEL DO PRIVATE(lonIndex,latIndex,levIndex)
849 do levIndex = 1, gsv_getNumLev(statevector,vnl_varLevelFromVarname('HU'))
850 do latIndex = statevector%myLatBeg, statevector%myLatEnd
851 do lonIndex = statevector%myLonBeg, statevector%myLonEnd
852 hu_ptr_r8(lonIndex,latIndex,levIndex,stepIndex) = &
853 lq_ptr_r8(lonIndex,latIndex,levIndex,stepIndex)* &
854 max( hu_trial(lonIndex,latIndex,levIndex,stepIndex),&
855 MPC_MINIMUM_HU_R8)
856 end do
857 end do
858 end do
859 !$OMP END PARALLEL DO
860 end do
861 end if
862
863 end subroutine LQtoHU_tlm
864
865 !--------------------------------------------------------------------------
866 ! HUtoLQ_tlm
867 !--------------------------------------------------------------------------
868 subroutine HUtoLQ_tlm(statevector, stateVectorRef_opt)
869 !
870 !:Purpose: Tangent linear of logarithmic transformation of specific
871 ! humidity
872 !
873 implicit none
874
875 ! Arguments:
876 type(struct_gsv), intent(inout) :: statevector
877 type(struct_gsv), optional, intent(in) :: statevectorRef_opt
878
879 ! Locals:
880 integer :: lonIndex,latIndex,levIndex,stepIndex
881 real(8), pointer :: hu_ptr_r8(:,:,:,:), lq_ptr_r8(:,:,:,:)
882 real(8), pointer :: hu_trial(:,:,:,:)
883 real(4), pointer :: hu_ptr_r4(:,:,:,:), lq_ptr_r4(:,:,:,:)
884
885 if ( present(statevectorRef_opt) ) then
886 call gsv_getField(stateVectorRef_opt,hu_trial,'HU')
887 else
888 if ( .not. gsv_containsNonZeroValues(stateVectorRefHU) ) then
889 call utl_abort('HUtoLQ_tlm: do trials to stateVectorRefHU transform at higher level')
890 end if
891 call gsv_getField(stateVectorRefHU,hu_trial,'HU')
892 end if
893
894 if ( gsv_getDataKind(statevector) == 4 ) then
895 call gsv_getField(statevector,hu_ptr_r4,'HU')
896 call gsv_getField(statevector,lq_ptr_r4,'HU')
897
898 do stepIndex = 1, statevector%numStep
899 !$OMP PARALLEL DO PRIVATE(lonIndex,latIndex,levIndex)
900 do levIndex = 1,gsv_getNumLev(statevector,vnl_varLevelFromVarname('HU'))
901 do latIndex = statevector%myLatBeg, statevector%myLatEnd
902 do lonIndex = statevector%myLonBeg, statevector%myLonEnd
903 lq_ptr_r4(lonIndex,latIndex,levIndex,stepIndex) = &
904 hu_ptr_r4(lonIndex,latIndex,levIndex,stepIndex) / &
905 max( hu_trial(lonIndex,latIndex,levIndex,stepIndex),&
906 MPC_MINIMUM_HU_R8)
907 end do
908 end do
909 end do
910 !$OMP END PARALLEL DO
911 end do
912 else
913 call gsv_getField(statevector,hu_ptr_r8,'HU')
914 call gsv_getField(statevector,lq_ptr_r8,'HU')
915
916 do stepIndex = 1, statevector%numStep
917 !$OMP PARALLEL DO PRIVATE(lonIndex,latIndex,levIndex)
918 do levIndex = 1,gsv_getNumLev(statevector,vnl_varLevelFromVarname('HU'))
919 do latIndex = statevector%myLatBeg, statevector%myLatEnd
920 do lonIndex = statevector%myLonBeg, statevector%myLonEnd
921 lq_ptr_r8(lonIndex,latIndex,levIndex,stepIndex) = &
922 hu_ptr_r8(lonIndex,latIndex,levIndex,stepIndex) / &
923 max( hu_trial(lonIndex,latIndex,levIndex,stepIndex),&
924 MPC_MINIMUM_HU_R8)
925 end do
926 end do
927 end do
928 !$OMP END PARALLEL DO
929 end do
930 end if
931
932 end subroutine HUtoLQ_tlm
933
934 !--------------------------------------------------------------------------
935 ! LPRtoPR_gsv
936 !--------------------------------------------------------------------------
937 subroutine LPRtoPR_gsv(stateVector, statevectorOut_opt, allowOverWrite_opt)
938 !
939 !:Purpose: Quantity of precipitation logarithm exponentiation
940 !
941 implicit none
942
943 ! Arguments:
944 type(struct_gsv), intent(inout) :: stateVector
945 type(struct_gsv), optional, intent(inout) :: statevectorOut_opt
946 logical, optional, intent(in) :: allowOverWrite_opt
947
948 ! Locals:
949 integer :: lonIndex,latIndex,levIndex,stepIndex
950 logical :: overWriteNeeded
951 real(4), pointer :: pr_ptr_r4(:,:,:,:), lpr_ptr_r4(:,:,:,:)
952 real(8), pointer :: pr_ptr_r8(:,:,:,:), lpr_ptr_r8(:,:,:,:)
953
954 ! Check if overWrite of PR is needed, but not allowed
955 overWriteNeeded = .false.
956 if (present(statevectorOut_opt)) then
957 if (.not. gsv_varExist(stateVectorOut_opt,'PR')) then
958 overWriteNeeded = .true.
959 end if
960 else
961 if (.not. gsv_varExist(stateVector,'PR')) then
962 overWriteNeeded = .true.
963 end if
964 end if
965 if (overWriteNeeded) then
966 if(present(allowOverWrite_opt)) then
967 if (.not.allowOverWrite_opt) then
968 call utl_abort('LPRtoPR_gsv: allowOverWrite_opt is false, but PR not present in stateVector')
969 end if
970 else
971 call utl_abort('LPRtoPR_gsv: allowOverWrite_opt not specified, but PR not present in stateVector')
972 end if
973 end if
974
975 if ( gsv_getDataKind(stateVector) == 8 ) then
976
977 if (present(statevectorOut_opt)) then
978 if (gsv_varExist(stateVectorOut_opt,'PR')) then
979 call gsv_getField(statevectorOut_opt,pr_ptr_r8,'PR')
980 else
981 call gsv_getField(statevectorOut_opt,pr_ptr_r8,'LPR')
982 end if
983 else
984 if (gsv_varExist(stateVector,'PR')) then
985 call gsv_getField(stateVector,pr_ptr_r8,'PR')
986 else
987 call gsv_getField(stateVector,pr_ptr_r8,'LPR')
988 end if
989 end if
990 call gsv_getField(stateVector,lpr_ptr_r8,'LPR')
991
992 do stepIndex = 1, stateVector%numStep
993 !$OMP PARALLEL DO PRIVATE(lonIndex,latIndex,levIndex)
994 do levIndex = 1, gsv_getNumLev(stateVector,vnl_varLevelFromVarname('LPR'))
995 do latIndex = stateVector%myLatBeg, stateVector%myLatEnd
996 do lonIndex = stateVector%myLonBeg, stateVector%myLonEnd
997 if (lpr_ptr_r8(lonIndex,latIndex,levIndex,stepIndex) > &
998 0.99D0*MPC_missingValue_R8) then
999
1000 pr_ptr_r8(lonIndex,latIndex,levIndex,stepIndex) = &
1001 max( 0.0D0, exp( lpr_ptr_r8(lonIndex,latIndex,levIndex,&
1002 stepIndex)) - &
1003 MPC_MINIMUM_PR_R8)
1004 else
1005 pr_ptr_r8(lonIndex,latIndex,levIndex,stepIndex) = &
1006 MPC_missingValue_R8
1007 end if
1008 end do
1009 end do
1010 end do
1011 !$OMP END PARALLEL DO
1012 end do
1013
1014 else
1015
1016 if (present(statevectorOut_opt)) then
1017 if (gsv_varExist(stateVectorOut_opt,'PR')) then
1018 call gsv_getField(statevectorOut_opt,pr_ptr_r4,'PR')
1019 else
1020 call gsv_getField(statevectorOut_opt,pr_ptr_r4,'LPR')
1021 end if
1022 else
1023 if (gsv_varExist(stateVector,'PR')) then
1024 call gsv_getField(stateVector,pr_ptr_r4,'PR')
1025 else
1026 call gsv_getField(stateVector,pr_ptr_r4,'LPR')
1027 end if
1028 end if
1029 call gsv_getField(stateVector,lpr_ptr_r4,'LPR')
1030
1031 do stepIndex = 1, stateVector%numStep
1032 !$OMP PARALLEL DO PRIVATE(lonIndex,latIndex,levIndex)
1033 do levIndex = 1,gsv_getNumLev(stateVector,vnl_varLevelFromVarname('LPR'))
1034 do latIndex = stateVector%myLatBeg, stateVector%myLatEnd
1035 do lonIndex = stateVector%myLonBeg, stateVector%myLonEnd
1036 if (lpr_ptr_r4(lonIndex,latIndex,levIndex,stepIndex) > &
1037 0.99*MPC_missingValue_R4) then
1038
1039 pr_ptr_r4(lonIndex,latIndex,levIndex,stepIndex) = &
1040 max( 0.0, exp( lpr_ptr_r4(lonIndex,latIndex,levIndex,&
1041 stepIndex)) - &
1042 MPC_MINIMUM_PR_R4)
1043 else
1044 pr_ptr_r4(lonIndex,latIndex,levIndex,stepIndex) = &
1045 MPC_missingValue_R4
1046 end if
1047 end do
1048 end do
1049 end do
1050 !$OMP END PARALLEL DO
1051 end do
1052
1053 end if
1054
1055 ! Change the variable name from LPR to PR if PR does not exist
1056 if (present(statevectorOut_opt)) then
1057 if (.not. gsv_varExist(stateVectorOut_opt,'PR')) then
1058 call gsv_modifyVarName(stateVectorOut_opt,'LPR','PR')
1059 end if
1060 else
1061 if (.not. gsv_varExist(stateVector,'PR')) then
1062 call gsv_modifyVarName(stateVector,'LPR','PR')
1063 end if
1064 end if
1065
1066 end subroutine LPRtoPR_gsv
1067
1068 !--------------------------------------------------------------------------
1069 ! LPRtoPR_ens
1070 !--------------------------------------------------------------------------
1071 subroutine LPRtoPR_ens(ens, allowOverWrite_opt)
1072 !
1073 !:Purpose: Quantity of precipitation logarithm exponentiation
1074 ! (ensemble processing)
1075 !
1076 implicit none
1077
1078 ! Arguments:
1079 type(struct_ens), intent(inout) :: ens
1080 logical, optional, intent(in) :: allowOverWrite_opt
1081
1082 ! Locals:
1083 integer :: lonIndex, latIndex, levIndex, stepIndex, memberIndex
1084 integer :: myLatBeg, myLatEnd, myLonBeg, myLonEnd, kIndexLPR, kIndexPR
1085 logical :: overWriteNeeded
1086 real(4), pointer :: PR_ptr_r4(:,:,:,:), LPR_ptr_r4(:,:,:,:)
1087
1088 ! Check if overWrite of PR is needed, but not allowed
1089 overWriteNeeded = .false.
1090 if (.not. ens_varExist(ens,'PR')) then
1091 overWriteNeeded = .true.
1092 end if
1093 if (overWriteNeeded) then
1094 if(present(allowOverWrite_opt)) then
1095 if (.not.allowOverWrite_opt) then
1096 call utl_abort('LPRtoPR_ens: allowOverWrite_opt is false, but PR not present in ensemble')
1097 end if
1098 else
1099 call utl_abort('LPRtoPR_ens: allowOverWrite_opt not specified, but PR not present in ensemble')
1100 end if
1101 end if
1102
1103 call ens_getLatLonBounds(ens, myLonBeg, myLonEnd, myLatBeg, myLatEnd)
1104
1105 levIndex = 1
1106 kIndexLPR = ens_getKFromLevVarName(ens, levIndex, 'LPR')
1107 if (ens_varExist(ens,'PR')) then
1108 kIndexPR = ens_getKFromLevVarName(ens, levIndex, 'PR')
1109 else
1110 kIndexPR = ens_getKFromLevVarName(ens, levIndex, 'LPR')
1111 end if
1112
1113 LPR_ptr_r4 => ens_getOneLev_r4(ens,kIndexLPR)
1114 PR_ptr_r4 => ens_getOneLev_r4(ens,kIndexPR)
1115
1116 do latIndex = myLatBeg, myLatEnd
1117 do lonIndex = myLonBeg, myLonEnd
1118 do stepIndex = 1, ens_getNumStep(ens)
1119 do memberIndex = 1, ens_getNumMembers(ens)
1120 PR_ptr_r4(memberIndex,stepIndex,lonIndex,latIndex) = &
1121 max( 0.0, exp( LPR_ptr_r4(memberIndex,stepIndex,lonIndex,&
1122 latIndex)) - &
1123 MPC_MINIMUM_PR_R4)
1124 ! maybe also impose minimum value of LPR
1125 !LPR_ptr_r4(memberIndex,stepIndex,lonIndex,latIndex) = &
1126 ! max(log(MPC_MINIMUM_PR_R4), LPR_ptr_r4(memberIndex,stepIndex,lonIndex,latIndex))
1127 end do
1128 end do
1129 end do
1130 end do
1131
1132 ! Change the variable name from LPR to PR if PR does not exist
1133 if (.not. ens_varExist(ens,'PR')) then
1134 call ens_modifyVarName(ens,'LPR','PR')
1135 end if
1136
1137 end subroutine LPRtoPR_ens
1138
1139 !--------------------------------------------------------------------------
1140 ! PRtoLPR_gsv
1141 !--------------------------------------------------------------------------
1142 subroutine PRtoLPR_gsv(stateVector, statevectorOut_opt)
1143 !
1144 !:Purpose: Logarithmic transformation of quantity of precipitation
1145 !
1146 implicit none
1147
1148 ! Arguments:
1149 type(struct_gsv), intent(inout) :: stateVector
1150 type(struct_gsv), optional, intent(inout) :: statevectorOut_opt
1151
1152 ! Locals:
1153 integer :: lonIndex,latIndex,levIndex,stepIndex
1154 real(4), pointer :: pr_ptr_r4(:,:,:,:), lpr_ptr_r4(:,:,:,:)
1155 real(8), pointer :: pr_ptr_r8(:,:,:,:), lpr_ptr_r8(:,:,:,:)
1156
1157 if ( gsv_getDataKind(stateVector) == 8 ) then
1158
1159 if (present(statevectorOut_opt)) then
1160 call gsv_getField(statevectorOut_opt,lpr_ptr_r8,'LPR')
1161 else
1162 call gsv_getField(stateVector,lpr_ptr_r8,'LPR')
1163 end if
1164 call gsv_getField(stateVector,pr_ptr_r8,'PR')
1165
1166 do stepIndex = 1, stateVector%numStep
1167 !$OMP PARALLEL DO PRIVATE(lonIndex,latIndex,levIndex)
1168 do levIndex = 1, gsv_getNumLev(stateVector,vnl_varLevelFromVarname('PR'))
1169 do latIndex = stateVector%myLatBeg, stateVector%myLatEnd
1170 do lonIndex = stateVector%myLonBeg, stateVector%myLonEnd
1171 if (pr_ptr_r8(lonIndex,latIndex,levIndex,stepIndex) > -1.0D0) then
1172 lpr_ptr_r8(lonIndex,latIndex,levIndex,stepIndex) = &
1173 log( MPC_MINIMUM_PR_R8 + &
1174 max(0.0d0,pr_ptr_r8(lonIndex,latIndex,levIndex,&
1175 stepIndex)))
1176 else
1177 lpr_ptr_r8(lonIndex,latIndex,levIndex,stepIndex) = &
1178 MPC_missingValue_R8
1179 end if
1180 end do
1181 end do
1182 end do
1183 !$OMP END PARALLEL DO
1184 end do
1185
1186 else
1187
1188 if (present(statevectorOut_opt)) then
1189 call gsv_getField(statevectorOut_opt,lpr_ptr_r4,'LPR')
1190 else
1191 call gsv_getField(stateVector,lpr_ptr_r4,'LPR')
1192 end if
1193 call gsv_getField(stateVector,pr_ptr_r4,'PR')
1194
1195 do stepIndex = 1, stateVector%numStep
1196 !$OMP PARALLEL DO PRIVATE(lonIndex,latIndex,levIndex)
1197 do levIndex = 1,gsv_getNumLev(stateVector,vnl_varLevelFromVarname('PR'))
1198 do latIndex = stateVector%myLatBeg, stateVector%myLatEnd
1199 do lonIndex = stateVector%myLonBeg, stateVector%myLonEnd
1200 if (pr_ptr_r4(lonIndex,latIndex,levIndex,stepIndex) > -1.0) then
1201 lpr_ptr_r4(lonIndex,latIndex,levIndex,stepIndex) = &
1202 log( MPC_MINIMUM_PR_R4 + &
1203 max(0.0,pr_ptr_r4(lonIndex,latIndex,levIndex,&
1204 stepIndex)))
1205 else
1206 lpr_ptr_r4(lonIndex,latIndex,levIndex,stepIndex) = &
1207 MPC_missingValue_R4
1208 end if
1209 end do
1210 end do
1211 end do
1212 !$OMP END PARALLEL DO
1213 end do
1214
1215 end if
1216
1217 end subroutine PRtoLPR_gsv
1218
1219 !--------------------------------------------------------------------------
1220 ! LVIStoVIS
1221 !--------------------------------------------------------------------------
1222 subroutine LVIStoVIS(stateVector, statevectorOut_opt, allowOverWrite_opt)
1223 !
1224 !:Purpose: Visibility logarithm exponentiation
1225 !
1226 implicit none
1227
1228 ! Arguments:
1229 type(struct_gsv), intent(inout) :: stateVector
1230 type(struct_gsv), optional, intent(inout) :: statevectorOut_opt
1231 logical, optional, intent(in) :: allowOverWrite_opt
1232
1233 ! Locals:
1234 integer :: lonIndex,latIndex,levIndex,stepIndex
1235 logical :: overWriteNeeded
1236 real(4), pointer :: vis_ptr_r4(:,:,:,:), lvis_ptr_r4(:,:,:,:)
1237 real(8), pointer :: vis_ptr_r8(:,:,:,:), lvis_ptr_r8(:,:,:,:)
1238
1239 ! Check if overWrite of PR is needed, but not allowed
1240 overWriteNeeded = .false.
1241 if (present(statevectorOut_opt)) then
1242 if (.not. gsv_varExist(stateVectorOut_opt,'PR')) then
1243 overWriteNeeded = .true.
1244 end if
1245 else
1246 if (.not. gsv_varExist(stateVector,'PR')) then
1247 overWriteNeeded = .true.
1248 end if
1249 end if
1250 if (overWriteNeeded) then
1251 if(present(allowOverWrite_opt)) then
1252 if (.not.allowOverWrite_opt) then
1253 call utl_abort('LVIStoVIS_gsv: allowOverWrite_opt is false, but PR not present in stateVector')
1254 end if
1255 else
1256 call utl_abort('LVIStoVIS_gsv: allowOverWrite_opt not specified, but PR not present in stateVector')
1257 end if
1258 end if
1259
1260 if ( gsv_getDataKind(stateVector) == 8 ) then
1261
1262 if (present(statevectorOut_opt)) then
1263 if (gsv_varExist(stateVectorOut_opt,'VIS')) then
1264 call gsv_getField(statevectorOut_opt,vis_ptr_r8,'VIS')
1265 else
1266 call gsv_getField(statevectorOut_opt,vis_ptr_r8,'LVIS')
1267 end if
1268 else
1269 if (gsv_varExist(stateVector,'VIS')) then
1270 call gsv_getField(stateVector,vis_ptr_r8,'VIS')
1271 else
1272 call gsv_getField(stateVector,vis_ptr_r8,'LVIS')
1273 end if
1274 end if
1275 call gsv_getField(stateVector,lvis_ptr_r8,'LVIS')
1276
1277 do stepIndex = 1, stateVector%numStep
1278 !$OMP PARALLEL DO PRIVATE(lonIndex,latIndex,levIndex)
1279 do levIndex = 1, gsv_getNumLev( stateVector,&
1280 vnl_varLevelFromVarname('LVIS'))
1281 do latIndex = stateVector%myLatBeg, stateVector%myLatEnd
1282 do lonIndex = stateVector%myLonBeg, stateVector%myLonEnd
1283 vis_ptr_r8(lonIndex,latIndex,levIndex,stepIndex) = &
1284 exp(lvis_ptr_r8(lonIndex,latIndex,levIndex,stepIndex))
1285 end do
1286 end do
1287 end do
1288 !$OMP END PARALLEL DO
1289 end do
1290
1291 else
1292
1293 if (present(statevectorOut_opt)) then
1294 if (gsv_varExist(stateVectorOut_opt,'VIS')) then
1295 call gsv_getField(statevectorOut_opt,vis_ptr_r4,'VIS')
1296 else
1297 call gsv_getField(statevectorOut_opt,vis_ptr_r4,'LVIS')
1298 end if
1299 else
1300 if (gsv_varExist(stateVector,'VIS')) then
1301 call gsv_getField(stateVector,vis_ptr_r4,'VIS')
1302 else
1303 call gsv_getField(stateVector,vis_ptr_r4,'LVIS')
1304 end if
1305 end if
1306 call gsv_getField(stateVector,lvis_ptr_r4,'LVIS')
1307
1308 do stepIndex = 1, stateVector%numStep
1309 !$OMP PARALLEL DO PRIVATE(lonIndex,latIndex,levIndex)
1310 do levIndex = 1, gsv_getNumLev( stateVector,&
1311 vnl_varLevelFromVarname('LVIS'))
1312 do latIndex = stateVector%myLatBeg, stateVector%myLatEnd
1313 do lonIndex = stateVector%myLonBeg, stateVector%myLonEnd
1314 vis_ptr_r4(lonIndex,latIndex,levIndex,stepIndex) = &
1315 exp(lvis_ptr_r4(lonIndex,latIndex,levIndex,stepIndex))
1316 end do
1317 end do
1318 end do
1319 !$OMP END PARALLEL DO
1320 end do
1321
1322 end if
1323
1324 ! Change the variable name from LVIS to VIS if VIS does not exist
1325 if (present(statevectorOut_opt)) then
1326 if (.not. gsv_varExist(stateVectorOut_opt,'VIS')) then
1327 call gsv_modifyVarName(stateVectorOut_opt,'LVIS','VIS')
1328 end if
1329 else
1330 if (.not. gsv_varExist(stateVector,'VIS')) then
1331 call gsv_modifyVarName(stateVector,'LVIS','VIS')
1332 end if
1333 end if
1334
1335 end subroutine LVIStoVIS
1336
1337
1338 !--------------------------------------------------------------------------
1339 ! ZandP_tl
1340 !--------------------------------------------------------------------------
1341 subroutine ZandP_tl(stateVector)
1342 !
1343 !:Purpose: Tangeant linear of height and pressure computation.
1344 ! The computation order depends on the native model
1345 ! representation (height or pressure based).
1346 !
1347 implicit none
1348
1349 ! Arguments:
1350 type(struct_gsv), intent(inout) :: stateVector
1351
1352 call czp_calcZandP_tl(statevector, stateVectorRefHeight)
1353
1354 end subroutine ZandP_tl
1355
1356 !--------------------------------------------------------------------------
1357 ! ZandP_ad
1358 !--------------------------------------------------------------------------
1359 subroutine ZandP_ad(stateVector)
1360 !
1361 !:Purpose: Adjoint of the tangeant linear computation of both height and
1362 ! pressure. The computation order depends on the native model
1363 ! representation (height or pressure based).
1364 !
1365 implicit none
1366
1367 ! Arguments:
1368 type(struct_gsv), intent(inout) :: stateVector
1369
1370 call czp_calcZandP_ad(statevector, stateVectorRefHeight)
1371
1372 end subroutine ZandP_ad
1373
1374 !--------------------------------------------------------------------------
1375 ! UVtoVortDiv_gsv
1376 !--------------------------------------------------------------------------
1377 subroutine UVtoVortDiv_gsv(statevector)
1378 !
1379 !:Purpose: Wind components to relative vorticity and divergence transformation.
1380 !
1381 implicit none
1382
1383 ! Arguments:
1384 type(struct_gsv), intent(inout) :: statevector
1385
1386 ! Locals:
1387 real(8), pointer :: uu_ptr(:,:,:,:), vv_ptr(:,:,:,:)
1388 real(8), pointer :: qr_ptr(:,:,:,:), dd_ptr(:,:,:,:)
1389 integer :: stepIndex
1390 integer :: nlev_M
1391
1392 call gsv_getField(statevector,uu_ptr,'UU')
1393 call gsv_getField(statevector,vv_ptr,'VV')
1394 if (gsv_varExist(statevector,'QR') .and. &
1395 gsv_varExist(statevector,'DD')) then
1396 call gsv_getField(statevector,qr_ptr,'QR')
1397 call gsv_getField(statevector,dd_ptr,'DD')
1398 else
1399 call gsv_getField(statevector,qr_ptr,'UU')
1400 call gsv_getField(statevector,dd_ptr,'VV')
1401 end if
1402
1403 nlev_M = gsv_getNumLev (statevector,'MM')
1404
1405 if ( statevector%hco%global ) then
1406 call utl_abort('UVtoVortDiv_gsv: global mode not available')
1407 else
1408 do stepIndex = 1, statevector%numStep
1409 call lgt_UVToVortDiv(qr_ptr(:,:,:,stepIndex), dd_ptr(:,:,:,stepIndex), & ! OUT
1410 uu_ptr(:,:,:,stepIndex), vv_ptr(:,:,:,stepIndex), & ! IN
1411 nlev_M ) ! IN
1412 end do
1413 end if
1414
1415 end subroutine UVtoVortDiv_gsv
1416
1417 !--------------------------------------------------------------------------
1418 ! vortDivtoPsiChi_gsv
1419 !--------------------------------------------------------------------------
1420 subroutine vortDivToPsiChi_gsv(statevector)
1421 !
1422 !:Purpose: Relative vorticity and divergence to stream function and
1423 ! velocity potential transformation.
1424 !
1425 implicit none
1426
1427 ! Arguments:
1428 type(struct_gsv), intent(inout) :: statevector
1429
1430 ! Locals:
1431 integer :: stepIndex
1432 logical, save :: firstTime = .true.
1433 real(8), pointer :: qr_ptr(:,:,:,:), dd_ptr(:,:,:,:)
1434 real(8), pointer :: pp_ptr(:,:,:,:), cc_ptr(:,:,:,:)
1435 type(struct_lst), save :: lst_lapl ! Spectral transform Parameters for Vort/Div -> Psi/Chi
1436 integer :: nlev_M
1437 integer :: nTrunc
1438
1439 nTrunc = max(statevector%hco%ni,statevector%hco%nj)/4 + 1
1440
1441 if (gsv_varExist(statevector,'QR') .and. &
1442 gsv_varExist(statevector,'DD')) then
1443 call gsv_getField(statevector,qr_ptr,'QR')
1444 call gsv_getField(statevector,dd_ptr,'DD')
1445 else
1446 call gsv_getField(statevector,qr_ptr,'UU')
1447 call gsv_getField(statevector,dd_ptr,'VV')
1448 end if
1449
1450 if (gsv_varExist(statevector,'PP') .and. &
1451 gsv_varExist(statevector,'CC')) then
1452 call gsv_getField(statevector,pp_ptr,'PP')
1453 call gsv_getField(statevector,cc_ptr,'CC')
1454 else
1455 call gsv_getField(statevector,pp_ptr,'UU')
1456 call gsv_getField(statevector,cc_ptr,'VV')
1457 end if
1458
1459 nlev_M = gsv_getNumLev (statevector,'MM')
1460
1461 if ( statevector%hco%global ) then
1462 call utl_abort('vortDivToPsiChi_gsv: global mode not available')
1463 else
1464 if (firstTime) then
1465 call lst_Setup(lst_lapl, & ! OUT
1466 statevector%hco%ni, statevector%hco%nj, & ! IN
1467 statevector%hco%dlon, nTrunc, & ! IN
1468 'LatLonMN', nlev_M ) ! IN
1469 firstTime = .false.
1470 end if
1471
1472 do stepIndex = 1, statevector%numStep
1473
1474 pp_ptr(:,:,:,stepIndex) = qr_ptr(:,:,:,stepIndex)
1475 cc_ptr(:,:,:,stepIndex) = dd_ptr(:,:,:,stepIndex)
1476
1477 ! Vort -> Psi
1478 call lst_Laplacian(lst_lapl, & ! IN
1479 pp_ptr(:,:,:,stepIndex), & ! INOUT
1480 'Inverse', nlev_M ) ! IN
1481
1482 ! Div -> Chi
1483 call lst_Laplacian(lst_lapl, & ! IN
1484 cc_ptr(:,:,:,stepIndex), & ! INOUT
1485 'Inverse', nlev_M ) ! IN
1486
1487 end do
1488
1489 end if
1490
1491 end subroutine VortDivToPsiChi_gsv
1492
1493 !--------------------------------------------------------------------------
1494 ! UVtoPsiChi_gsv
1495 !--------------------------------------------------------------------------
1496 subroutine UVtoPsiChi_gsv(statevector)
1497 !
1498 !:Purpose: Wind components to stream function and velocity potential
1499 ! transformation.
1500 !
1501 implicit none
1502
1503 ! Arguments:
1504 type(struct_gsv), intent(inout) :: statevector
1505
1506 ! Locals:
1507 integer :: stepIndex
1508 real(8), pointer :: uu_ptr(:,:,:,:), vv_ptr(:,:,:,:)
1509 real(8), pointer :: psi_ptr(:,:,:,:), chi_ptr(:,:,:,:)
1510 real(8), allocatable :: gridState(:,:,:), spectralState(:,:,:)
1511 real(8) :: dla2
1512 integer :: nlev_M, levIndex
1513 integer :: ila_mpiglobal, ila_mpilocal
1514 ! spectral transform configuration (saved)
1515 integer, save :: gstID = -1
1516 integer, save :: nla_mpilocal, maxMyNla, ntrunc
1517 integer, save :: mymBeg,mymEnd,mymSkip,mymCount
1518 integer, save :: mynBeg,mynEnd,mynSkip,mynCount
1519 integer, save, pointer :: ilaList_mpiglobal(:), ilaList_mpilocal(:)
1520
1521 write(*,*) 'UVtoPsiChi_gsv: starting'
1522 call flush(6)
1523
1524 if ( .not. statevector%hco%global ) then
1525
1526 call UVtoVortDiv_gsv (statevector)
1527 call vortDivToPsiChi_gsv(statevector)
1528
1529 else
1530
1531 call gsv_getField(statevector,uu_ptr,'UU')
1532 call gsv_getField(statevector,vv_ptr,'VV')
1533 if (gsv_varExist(statevector,'PP') .and. &
1534 gsv_varExist(statevector,'CC')) then
1535 call gsv_getField(statevector,psi_ptr,'PP')
1536 call gsv_getField(statevector,chi_ptr,'CC')
1537 else
1538 call gsv_getField(statevector,psi_ptr,'UU')
1539 call gsv_getField(statevector,chi_ptr,'VV')
1540 end if
1541 nlev_M = gsv_getNumLev(statevector,'MM')
1542
1543 if ( gstID < 0 ) then
1544 !ntrunc = statevector%nj
1545 ntrunc = 180
1546 gstID = gst_setup(statevector%ni,statevector%nj,ntrunc,2*nlev_M)
1547 call mmpi_setup_m(ntrunc,mymBeg,mymEnd,mymSkip,mymCount)
1548 call mmpi_setup_n(ntrunc,mynBeg,mynEnd,mynSkip,mynCount)
1549 call gst_ilaList_mpiglobal( ilaList_mpiglobal,nla_mpilocal,maxMyNla,&
1550 gstID,mymBeg,mymEnd,mymSkip,mynBeg,mynEnd,&
1551 mynSkip)
1552 call gst_ilaList_mpilocal(ilaList_mpilocal,gstID,mymBeg,mymEnd,mymSkip,&
1553 mynBeg,mynEnd,mynSkip)
1554 end if
1555
1556 dla2 = ec_ra * ec_ra
1557 allocate(gridState(statevector%lonPerPE,statevector%latPerPE,2*nlev_M))
1558 allocate(spectralState(nla_mpilocal,2,2*nlev_M))
1559
1560 do stepIndex = 1, statevector%numStep
1561
1562 gridState(:,:,1:nlev_M) = uu_ptr(:,:,:,stepIndex)
1563 gridState(:,:,(nlev_M+1):2*nlev_M) = vv_ptr(:,:,:,stepIndex)
1564
1565 call gst_setID(gstID)
1566 call gst_gdsp(spectralState,gridState,nlev_M)
1567
1568 do levIndex = 1, 2*nlev_M
1569 do ila_mpilocal = 1, nla_mpilocal
1570 ila_mpiglobal = ilaList_mpiglobal(ila_mpilocal)
1571 spectralState(ila_mpilocal,:,levIndex) = &
1572 spectralState(ila_mpilocal,:,levIndex) * &
1573 dla2*gst_getR1snp1(ila_mpiglobal)
1574 enddo
1575 enddo
1576
1577 call gst_speree(spectralState,gridState)
1578
1579 psi_ptr(:,:,:,stepIndex) = gridState(:,:,1:nlev_M)
1580 chi_ptr(:,:,:,stepIndex) = gridState(:,:,(nlev_M+1):2*nlev_M)
1581
1582 end do
1583
1584 write(*,*) 'deallocate'; call flush(6)
1585 deallocate(gridState)
1586 deallocate(spectralState)
1587
1588 end if
1589
1590 write(*,*) 'UVtoPsiChi_gsv: finished'
1591 call flush(6)
1592
1593 end subroutine UVtoPsiChi_gsv
1594
1595 !--------------------------------------------------------------------------
1596 ! UVtoPsiChi_ens
1597 !--------------------------------------------------------------------------
1598 subroutine UVtoPsiChi_ens(ens)
1599 !
1600 !:Purpose: Wind components to stream function and velocity potential
1601 ! transformation (ensemble processing).
1602 !
1603 implicit none
1604
1605 ! Arguments:
1606 type(struct_ens), intent(inout) :: ens
1607
1608 ! Locals:
1609 type(struct_hco), pointer :: hco_ens => null()
1610 type(struct_gsv) :: gridStateVector_oneMember
1611 integer :: memberIndex
1612
1613 write(*,*)
1614 write(*,*) 'gvt_UVtoPsiChi_ens: starting'
1615
1616 hco_ens => ens_getHco(ens)
1617
1618 !
1619 !- 1. Create a working stateVector
1620 !
1621 call gsv_allocate(gridStateVector_oneMember, 1, hco_ens, ens_getVco(ens), &
1622 varNames_opt=(/'UU','VV'/), &
1623 datestamp_opt=tim_getDatestamp(), &
1624 mpi_local_opt=.true., dataKind_opt=8)
1625
1626 !
1627 !- 2. Loop on members
1628 !
1629 do memberIndex = 1, ens_getNumMembers(ens)
1630
1631 !- 2.1 Copy to a stateVector
1632 call ens_copyMember(ens, gridStateVector_oneMember, memberIndex)
1633
1634 !- 2.2 Do the transform
1635 call UVtoPsiChi_gsv(gridStateVector_oneMember)
1636
1637 !- 2.3 Put the result back in the input ensembleStateVector
1638 call ens_insertMember(ens, gridStateVector_oneMember, memberIndex)
1639 end do
1640
1641 !
1642 !- 3. Cleaning
1643 !
1644 call gsv_deallocate(gridStateVector_oneMember)
1645
1646 write(*,*) 'gvt_UVtoPsiChi_ens: finished'
1647
1648 end subroutine UVtoPsiChi_ens
1649
1650 !--------------------------------------------------------------------------
1651 ! UVtoVorDiv_ens
1652 !--------------------------------------------------------------------------
1653 subroutine UVtoVortDiv_ens(ens)
1654 !
1655 !:Purpose: Wind components to relative vorticity and divergence transformation
1656 ! (ensemble processing)
1657 !
1658 implicit none
1659
1660 ! Arguments:
1661 type(struct_ens), intent(inout) :: ens
1662
1663 ! Locals:
1664 type(struct_hco), pointer :: hco_ens => null()
1665 type(struct_gsv) :: gridStateVector_oneMember
1666 integer :: memberIndex
1667
1668 write(*,*)
1669 write(*,*) 'gvt_UVtoVortDiv_ens: starting'
1670
1671 hco_ens => ens_getHco(ens)
1672
1673 if (hco_ens%global ) then
1674 call utl_abort('gvt_UVtoVortDiv_ens: global mode not yet available')
1675 end if
1676
1677 !
1678 !- 1. Create a working stateVector
1679 !
1680 call gsv_allocate(gridStateVector_oneMember, 1, hco_ens, ens_getVco(ens), &
1681 varNames_opt=(/'UU','VV'/), &
1682 datestamp_opt=tim_getDatestamp(), &
1683 mpi_local_opt=.true., dataKind_opt=8)
1684
1685 !
1686 !- 2. Loop on members
1687 !
1688 do memberIndex = 1, ens_getNumMembers(ens)
1689
1690 !- 2.1 Copy to a stateVector
1691 call ens_copyMember(ens, gridStateVector_oneMember, memberIndex)
1692
1693 !- 2.2 Do the transform
1694 call UVtoVortDiv_gsv(gridStateVector_oneMember)
1695
1696 !- 2.3 Put the result back in the input ensembleStateVector
1697 call ens_insertMember(ens, gridStateVector_oneMember, memberIndex)
1698 end do
1699
1700 !
1701 !- 3. Cleaning
1702 !
1703 call gsv_deallocate(gridStateVector_oneMember)
1704
1705 write(*,*) 'gvt_UVtoVortDiv_ens: finished'
1706
1707 end subroutine UVtoVortDiv_ens
1708
1709 !--------------------------------------------------------------------------
1710 ! logCH_ens
1711 !--------------------------------------------------------------------------
1712 subroutine logCH_ens(ens,varName)
1713 !
1714 !:Purpose: Logarithmic transformation of a chemical species concentration
1715 ! (ensemble processing)
1716 !
1717 implicit none
1718
1719 ! Arguments:
1720 type(struct_ens), intent(inout) :: ens
1721 character(len=4), intent(in) :: varName
1722
1723 ! Locals:
1724 integer :: lonIndex, latIndex, levIndex, stepIndex, memberIndex
1725 integer :: myLatBeg, myLatEnd, myLonBeg, myLonEnd
1726 character(len=4) :: varName_ens
1727 real(4) :: minVal
1728 real(4), pointer :: ptr4d_r4(:,:,:,:)
1729
1730 call ens_getLatLonBounds(ens, myLonBeg, myLonEnd, myLatBeg, myLatEnd)
1731
1732 do levIndex = 1, ens_getNumK(ens)
1733
1734 varName_ens = ens_getVarNameFromK(ens,levIndex)
1735 if ( trim(varName_ens) /= trim(varName) ) cycle
1736
1737 ptr4d_r4 => ens_getOneLev_r4(ens,levIndex)
1738 minVal=real(gsv_minValVarKindCH(vnl_varListIndex(varName)),4)
1739
1740 do latIndex = myLatBeg, myLatEnd
1741 do lonIndex = myLonBeg, myLonEnd
1742 do stepIndex = 1, ens_getNumStep(ens)
1743 do memberIndex = 1, ens_getNumMembers(ens)
1744 ptr4d_r4(memberIndex,stepIndex,lonIndex,latIndex) = &
1745 log(max(ptr4d_r4(memberIndex,stepIndex,lonIndex,latIndex),&
1746 minVal))
1747 end do
1748 end do
1749 end do
1750 end do
1751
1752 end do
1753
1754 end subroutine logCH_ens
1755
1756 !--------------------------------------------------------------------------
1757 ! expCH_tlm
1758 !--------------------------------------------------------------------------
1759 subroutine expCH_tlm(statevector, varName, stateVectorRef_opt)
1760 !
1761 !:Purpose: Tangent linear of exponentiation of chemical species
1762 ! concentration.
1763 ! Transform d[log(x)] to dx where x = 'stateVectorRef_opt',
1764 ! the input 'statevector' component is d[log(x)] and
1765 ! the output 'statevector' component is dx.
1766 !
1767 implicit none
1768
1769 ! Arguments:
1770 type(struct_gsv), intent(inout) :: statevector
1771 character(len=*), intent(in) :: varName
1772 type(struct_gsv), optional, intent(in) :: statevectorRef_opt
1773
1774 ! Locals:
1775 integer :: lonIndex,latIndex,levIndex,stepIndex,varIndex
1776 real(8), pointer :: var_ptr(:,:,:,:), logVar_ptr(:,:,:,:)
1777 real(8), pointer :: var_trial(:,:,:,:)
1778 real(8) :: minVal
1779
1780 if ( present(statevectorRef_opt) ) then
1781 call gsv_getField(stateVectorRef_opt,var_trial,trim(varName))
1782 else
1783 varIndex = vnl_varListIndex(varName)
1784 if ( .not. varKindCHTrialsInitialized(varIndex) ) then
1785 call utl_abort('expCH_tlm: do trials to stateVectorRefChem transform at higher level')
1786 end if
1787 call gsv_getField(stateVectorTrialvarKindCH(varIndex),var_trial,&
1788 trim(varName))
1789 end if
1790
1791 call gsv_getField(statevector,var_ptr,trim(varName))
1792 call gsv_getField(statevector,logVar_ptr,trim(varName))
1793
1794 minVal=gsv_minValVarKindCH(vnl_varListIndex(varName))
1795
1796 do stepIndex = 1, statevector%numStep
1797 !$OMP PARALLEL DO PRIVATE(lonIndex,latIndex,levIndex)
1798 do levIndex = 1, gsv_getNumLev( statevector,&
1799 vnl_varLevelFromVarname(trim(varName)))
1800 do latIndex = statevector%myLatBeg, statevector%myLatEnd
1801 do lonIndex = statevector%myLonBeg, statevector%myLonEnd
1802 var_ptr(lonIndex,latIndex,levIndex,stepIndex) = &
1803 logVar_ptr(lonIndex,latIndex,levIndex,stepIndex) &
1804 * max(var_trial(lonIndex,latIndex,levIndex,stepIndex),minVal)
1805 end do
1806 end do
1807 end do
1808 !$OMP END PARALLEL DO
1809 end do
1810
1811 end subroutine expCH_tlm
1812
1813 !--------------------------------------------------------------------------
1814 ! CH_bounds
1815 !--------------------------------------------------------------------------
1816 subroutine CH_bounds(statevector)
1817 !
1818 !:Purpose: Impose boundary values to variables of CH kind.
1819 !
1820 implicit none
1821
1822 ! Arguments:
1823 type(struct_gsv), intent(inout) :: statevector
1824
1825 ! Locals:
1826 integer :: varIndex,lonIndex,latIndex,levIndex,stepIndex
1827 real(8), pointer :: var_ptr(:,:,:,:)
1828 real(8) :: minVal
1829 character(len=4) :: varName
1830
1831 do varIndex = 1, vnl_numvarmax
1832 varName = vnl_varNameList(varIndex)
1833 if ( .not.gsv_varExist(varName=trim(varName)) ) cycle
1834 if ( vnl_varKindFromVarname(trim(varName)) /= 'CH' ) cycle
1835
1836 call gsv_getField(statevector,var_ptr,trim(varName))
1837
1838 minVal=gsv_minValVarKindCH(vnl_varListIndex(varName))
1839
1840 do stepIndex = 1, statevector%numStep
1841 !$OMP PARALLEL DO PRIVATE(lonIndex,latIndex,levIndex)
1842 do levIndex = 1, gsv_getNumLev( statevector,&
1843 vnl_varLevelFromVarname(trim(varName)))
1844 do latIndex = statevector%myLatBeg, statevector%myLatEnd
1845 do lonIndex = statevector%myLonBeg, statevector%myLonEnd
1846 var_ptr(lonIndex,latIndex,levIndex,stepIndex) = &
1847 max(var_ptr(lonIndex,latIndex,levIndex,stepIndex),minVal)
1848 end do
1849 end do
1850 end do
1851 !$OMP END PARALLEL DO
1852 end do
1853
1854 end do
1855
1856 end subroutine CH_bounds
1857
1858 !--------------------------------------------------------------------------
1859 ! gvt_oceanIceContinuous
1860 !--------------------------------------------------------------------------
1861 subroutine gvt_oceanIceContinuous(stateVector, stateVectorRef, outputVarName)
1862 !
1863 !:Purpose: Solve laplaces equation at a subset of gridpoints
1864 ! subject to the boundary conditions imposed by the
1865 ! surrounding points. Uses the method of sequential
1866 ! relaxation or Liebmann relaxation, which converges
1867 ! more rapidly than the simultaneous relaxation (see
1868 ! numerical weather analysis and prediction by P. D.
1869 ! Thompson, 1961, pp92-98). NOTE: this subroutine
1870 ! currently uses the oceanMask only for the first level.
1871 ! Therefore, if it is applied to 3D masked fields that
1872 ! have level-dependent masks, the code will abort so
1873 ! that the user can make the necessary adjustments to
1874 ! ensure the correct behaviour.
1875 !
1876 implicit none
1877
1878 ! Arguments:
1879 type(struct_gsv), intent(inout) :: statevector
1880 type(struct_gsv), intent(in) :: stateVectorRef
1881 character(len=*), intent(in) :: outputVarName
1882
1883 ! Locals:
1884 type(struct_gsv) :: statevector_analysis_1step_r8
1885 type(struct_gsv) :: statevector_trial_1step_r8
1886 real(8), pointer :: analysis_ptr(:,:,:,:), trial_ptr(:,:,:,:)
1887 real(8), pointer :: input_ptr(:,:,:,:)
1888 real(8) :: alpha, factor, correc, rms, maxAbsCorr, basic
1889 integer :: lonIndex, latIndex, levIndex, stepIndex
1890 integer :: ipass, numPass, numCorrect
1891 logical :: orca12
1892 character(len=2) :: inputVarName
1893
1894 ! abort if 3D mask is present, since we may not handle this situation correctly
1895 if (stateVector%oceanMask%nLev > 1) then
1896 call utl_abort('gvt_oceanIceContinuous: 3D mask present - this case not properly handled')
1897 end if
1898
1899 ! allocate statevector for single time steps
1900 if (mmpi_myid < stateVector%numStep) then
1901 if (outputVarName == 'LG') then
1902 call gsv_allocate(stateVector_analysis_1step_r8, 1, stateVector%hco, &
1903 stateVector%vco, mpi_local_opt = .false., &
1904 dataKind_opt = 8, varNames_opt = (/'GL','LG'/))
1905 call gsv_allocate(stateVector_trial_1step_r8, 1, stateVectorRef%hco, &
1906 stateVectorRef%vco, mpi_local_opt=.false., &
1907 dataKind_opt=8, varNames_opt = (/'GL','LG'/))
1908 else if(outputVarName == 'TM') then
1909 call gsv_allocate(stateVector_analysis_1step_r8, 1, stateVector%hco, &
1910 stateVector%vco, mpi_local_opt = .false., &
1911 dataKind_opt = 8, varNames_opt = (/outputVarName/))
1912 call gsv_allocate(stateVector_trial_1step_r8, 1, stateVectorRef%hco, &
1913 stateVectorRef%vco, mpi_local_opt = .false., &
1914 dataKind_opt = 8, varNames_opt = (/outputVarName/))
1915 else
1916 call utl_abort('gvt_oceanIceContinuous: unrecognized variable name: '//trim(outputVarName))
1917 end if
1918 end if
1919
1920 call gsv_transposeTilesToStep(stateVector_analysis_1step_r8, stateVector, 1)
1921 call gsv_transposeTilesToStep(stateVector_trial_1step_r8, stateVectorRef, 1)
1922
1923 if (gsv_isAllocated(stateVector_analysis_1step_r8)) then
1924
1925 if (outputVarName == 'LG') then
1926 inputVarName = 'GL'
1927 else
1928 inputVarName = outputVarName
1929 end if
1930 call gsv_getField(stateVector_analysis_1step_r8, input_ptr, inputVarName)
1931 call gsv_getField(stateVector_analysis_1step_r8, analysis_ptr, outputVarName)
1932 call gsv_getField(stateVector_trial_1step_r8, trial_ptr, outputVarName)
1933
1934 alpha = 1.975d0
1935 if( gpos_gridIsOrca(stateVector%ni, stateVector%nj, real(stateVector%hco%lat2d_4,8), real(stateVector%hco%lon2d_4,8)) ) then
1936 orca12 = .true.
1937 numPass = 1000
1938 factor = alpha*0.88d0
1939 else
1940 orca12 = .false.
1941 numPass = 500
1942 factor = alpha
1943 end if
1944
1945 write(*,*) 'gvt_oceanIceContinuous: Liebmann relaxation'
1946 write(*,*) 'gvt_oceanIceContinuous: Number of free points: ', count(.not. stateVector%oceanMask%mask)
1947 write(*,*) 'gvt_oceanIceContinuous: Number of fixed points: ', count( stateVector%oceanMask%mask)
1948 write(*,*) 'gvt_oceanIceContinuous: Total number of grid points: ', stateVector%ni*stateVector%nj
1949 write(*,*) 'gvt_oceanIceContinuous: Total number of iterations: ', numPass
1950
1951 do stepIndex = 1, statevector%numStep
1952 write(*,*) 'gvt_oceanIceContinuous: stepIndex = ', stepIndex
1953 do levIndex = 1, gsv_getNumLev(statevector,vnl_varLevelFromVarname(outputVarName))
1954
1955 write(*,*) 'gvt_oceanIceContinuous: levIndex = ',levIndex
1956
1957 ! Initialisation
1958 do latIndex = 1, stateVector%nj
1959 do lonIndex = 1, stateVector%ni
1960 if (stateVector%oceanMask%mask(lonIndex, latIndex, 1)) then
1961 analysis_ptr(lonIndex, latIndex, levIndex, stepIndex) = input_ptr(lonIndex, latIndex, levIndex, stepIndex)
1962 else
1963 analysis_ptr(lonIndex, latIndex, levIndex, stepIndex) = trial_ptr(lonIndex, latIndex, levIndex, stepIndex)
1964 end if
1965 end do
1966 end do
1967
1968 do ipass = 1, numPass
1969
1970 rms = 0.0d0
1971 numCorrect = 0
1972 maxAbsCorr = 0.0d0
1973
1974 if(stateVector%hco%grtyp == 'U') then
1975
1976 do latIndex = 2, stateVector%nj/2-1
1977 do lonIndex = 2, stateVector%ni-1
1978 if (.not. stateVector%oceanMask%mask(lonIndex, latIndex, 1)) then
1979 basic = (analysis_ptr(lonIndex + 1, latIndex , levIndex, stepIndex) + &
1980 analysis_ptr(lonIndex - 1, latIndex , levIndex, stepIndex) + &
1981 analysis_ptr(lonIndex , latIndex + 1, levIndex, stepIndex) + &
1982 analysis_ptr(lonIndex , latIndex - 1, levIndex, stepIndex)) / 4.0d0
1983 correc = factor * (basic - analysis_ptr(lonIndex, latIndex, levIndex, stepIndex))
1984 analysis_ptr(lonIndex, latIndex, levIndex, stepIndex) = analysis_ptr(lonIndex, latIndex, levIndex, stepIndex) + correc
1985 rms = rms + correc * correc
1986 numCorrect = numCorrect + 1
1987 if(abs(correc) > maxAbsCorr) maxAbsCorr = abs(correc)
1988 end if
1989 end do
1990 end do
1991
1992 do latIndex = stateVector%nj/2 + 2, stateVector%nj-1
1993 do lonIndex = 2, stateVector%ni-1
1994 if (.not. stateVector%oceanMask%mask(lonIndex, latIndex, 1)) then
1995 basic = (analysis_ptr(lonIndex + 1, latIndex , levIndex, stepIndex) + &
1996 analysis_ptr(lonIndex - 1, latIndex , levIndex, stepIndex) + &
1997 analysis_ptr(lonIndex , latIndex + 1, levIndex, stepIndex) + &
1998 analysis_ptr(lonIndex , latIndex - 1, levIndex, stepIndex)) / 4.0d0
1999 correc = factor * (basic - analysis_ptr(lonIndex, latIndex, levIndex, stepIndex))
2000 analysis_ptr(lonIndex, latIndex, levIndex, stepIndex) = analysis_ptr(lonIndex, latIndex, levIndex, stepIndex) + correc
2001 rms = rms + correc * correc
2002 numCorrect = numCorrect + 1
2003 if(abs(correc) > maxAbsCorr) maxAbsCorr = abs(correc)
2004 end if
2005 end do
2006 end do
2007
2008 else
2009
2010 do latIndex = 2, stateVector%nj-1
2011 do lonIndex = 2, stateVector%ni-1
2012 if (.not. stateVector%oceanMask%mask(lonIndex, latIndex, 1)) then
2013 basic = (analysis_ptr(lonIndex + 1, latIndex , levIndex, stepIndex) + &
2014 analysis_ptr(lonIndex - 1, latIndex , levIndex, stepIndex) + &
2015 analysis_ptr(lonIndex , latIndex + 1, levIndex, stepIndex) + &
2016 analysis_ptr(lonIndex , latIndex - 1, levIndex, stepIndex)) / 4.0d0
2017 correc = factor * (basic - analysis_ptr(lonIndex, latIndex, levIndex, stepIndex))
2018 analysis_ptr(lonIndex, latIndex, levIndex, stepIndex) = analysis_ptr(lonIndex, latIndex, levIndex, stepIndex) + correc
2019 rms = rms + correc * correc
2020 numCorrect = numCorrect + 1
2021 if(abs(correc) > maxAbsCorr) maxAbsCorr = abs(correc)
2022 end if
2023 end do
2024 end do
2025
2026 end if
2027
2028 if( orca12 ) then
2029 ! Periodicity in the X direction
2030 lonIndex = 1
2031 do latIndex = 2, stateVector%nj-1
2032 if (.not. stateVector%oceanMask%mask(lonIndex, latIndex, 1)) then
2033 basic = (analysis_ptr(lonIndex + 1, latIndex, levIndex, stepIndex) + &
2034 analysis_ptr(stateVector%ni-2, latIndex, levIndex, stepIndex) + &
2035 analysis_ptr(lonIndex, latIndex + 1, levIndex, stepIndex) + &
2036 analysis_ptr(lonIndex, latIndex - 1, levIndex, stepIndex)) / 4.0d0
2037 correc = factor * (basic - analysis_ptr(lonIndex, latIndex, levIndex, stepIndex))
2038 analysis_ptr(lonIndex, latIndex, levIndex, stepIndex) = analysis_ptr(lonIndex, latIndex, levIndex, stepIndex) + correc
2039 rms = rms + correc * correc
2040 numCorrect = numCorrect + 1
2041 if(abs(correc) > maxAbsCorr ) maxAbsCorr = abs(correc)
2042 end if
2043 end do
2044 lonIndex = stateVector%ni
2045 do latIndex = 2, stateVector%nj-1
2046 if (.not. stateVector%oceanMask%mask(lonIndex, latIndex, 1)) then
2047 basic = (analysis_ptr(3, latIndex, levIndex, stepIndex) + &
2048 analysis_ptr(lonIndex - 1, latIndex, levIndex, stepIndex) + &
2049 analysis_ptr(lonIndex, latIndex + 1, levIndex, stepIndex) + &
2050 analysis_ptr(lonIndex, latIndex - 1, levIndex, stepIndex)) / 4.0d0
2051 correc = factor * (basic - analysis_ptr(lonIndex, latIndex, levIndex, stepIndex))
2052 analysis_ptr(lonIndex, latIndex, levIndex, stepIndex) = analysis_ptr(lonIndex, latIndex, levIndex, stepIndex) + correc
2053 rms = rms + correc * correc
2054 numCorrect = numCorrect + 1
2055 if( abs(correc) > maxAbsCorr ) maxAbsCorr = abs(correc)
2056 end if
2057 end do
2058 ! North fold
2059 latIndex = stateVector%nj
2060 do lonIndex = 2, stateVector%ni-1
2061 if (.not. stateVector%oceanMask%mask(lonIndex, latIndex, 1)) then
2062 basic = (analysis_ptr(lonIndex + 1, latIndex, levIndex, stepIndex)+&
2063 analysis_ptr(lonIndex - 1, latIndex, levIndex, stepIndex)+&
2064 analysis_ptr(stateVector%ni + 2 - lonIndex, latIndex - 2, levIndex, stepIndex) + &
2065 analysis_ptr(stateVector%ni + 2 - lonIndex, latIndex - 1, levIndex, stepIndex) ) / 4.0d0
2066 correc = factor*(basic - analysis_ptr(lonIndex, latIndex, levIndex, stepIndex))
2067 analysis_ptr(lonIndex, latIndex, levIndex, stepIndex) = analysis_ptr(lonIndex, latIndex, levIndex, stepIndex) + correc
2068 rms = rms + correc * correc
2069 numCorrect = numCorrect + 1
2070 if(abs(correc) > maxAbsCorr) maxAbsCorr = abs(correc)
2071 end if
2072 end do
2073 end if
2074
2075 end do
2076
2077 if(numCorrect > 0) rms = sqrt(rms / real(numCorrect))
2078
2079 write(*,*) 'gvt_oceanIceContinuous: number of points corrected = ', numCorrect
2080 write(*,*) 'gvt_oceanIceContinuous: RMS correction during last iteration: ', rms
2081 write(*,*) 'gvt_oceanIceContinuous: MAX absolute correction during last iteration: ', maxAbsCorr
2082 write(*,*) 'gvt_oceanIceContinuous: Field min value = ', minval(analysis_ptr(:,:,levIndex,stepIndex))
2083 write(*,*) 'gvt_oceanIceContinuous: Field max value = ', maxval(analysis_ptr(:,:,levIndex,stepIndex))
2084
2085 if(maxAbsCorr > 1.0) then
2086 call utl_abort('gvt_oceanIceContinuous: Unstable algorithm !')
2087 end if
2088
2089 end do
2090 end do
2091
2092 if (outputVarName == 'LG') then
2093 !- Impose limits [0,1] on sea ice concentration analysis
2094 analysis_ptr(:,:,:,:) = min(analysis_ptr(:,:,:,:), 1.0d0)
2095 analysis_ptr(:,:,:,:) = max(analysis_ptr(:,:,:,:), 0.0d0)
2096 end if
2097
2098 end if
2099
2100 call gsv_transposeStepToTiles(stateVector_analysis_1step_r8, stateVector, 1)
2101
2102 if (mmpi_myid < stateVector%numStep) then
2103 call gsv_deallocate(stateVector_analysis_1step_r8)
2104 call gsv_deallocate(stateVector_trial_1step_r8)
2105 end if
2106
2107 end subroutine gvt_oceanIceContinuous
2108
2109 !--------------------------------------------------------------------------
2110 ! gvt_SSTSpread
2111 !--------------------------------------------------------------------------
2112 subroutine gvt_SSTSpread(stateVector, variableName, maxBoxSize, subgrid)
2113 !
2114 !:Purpose: Spread SST values on neigbouring land surface points
2115 !
2116 implicit none
2117
2118 ! Arguments:
2119 type(struct_gsv), intent(inout) :: stateVector ! state vector of SST analysis
2120 character(len=*), intent(in) :: variableName ! variable name
2121 integer , intent(in) :: maxBoxSize ! maximum box size of SST values spreading
2122 character(len=*), intent(in) :: subgrid ! spread SST values on neighbouring land points of "Yin" or "Yan" subgrid
2123
2124 ! Locals:
2125 logical, allocatable :: isWaterValue(:,:) ! .True. for water points, .False. for land points
2126 logical, allocatable :: updatedIsWaterValue(:,:) ! If the current value is already updated, set it to .True.
2127 real(4), allocatable :: updatedField(:,:) ! updated surface temperature on land
2128 real(4) :: updatedValueSum
2129 integer :: top, bottom, left, right, np
2130 integer :: boxSize, k, l, m
2131 integer :: in(100), jn(100), ngp
2132 integer :: lonIndex, latIndex
2133 integer :: latIndexBeg, latIndexEnd
2134 type(struct_gsv) :: stateVector_1step
2135 real(8), pointer :: field_ptr(:,:,:,:)
2136
2137 write(*,'(a,i2,a)') 'gvt_SSTSpread: spread SST values on ', maxBoxSize,' neighbouring land points on '//trim(subgrid)//' subgrid...'
2138 if (trim(subgrid) == 'Yin') then
2139 latIndexBeg = 1
2140 latIndexEnd = stateVector%hco%nj / 2
2141 else if(trim(subgrid) == 'Yan') then
2142 latIndexBeg = stateVector%hco%nj / 2 + 1
2143 latIndexEnd = stateVector%hco%nj
2144 else
2145 call utl_abort('gvt_SSTSpread: unknown subgrid: '//trim(subgrid))
2146 end if
2147
2148 ! abort if 3D mask is present, since we may not handle this situation correctly
2149 if (stateVector%oceanMask%nLev > 1) then
2150 call utl_abort('gvt_SSTSpread: 3D mask present - this case not properly handled')
2151 end if
2152
2153 ! abort if 3D variable is present
2154 if( gsv_getNumLev(stateVector, vnl_varLevelFromVarname(variableName)) > 1) then
2155 call utl_abort('gvt_SSTSpread: 3D variable present - this case not properly handled')
2156 end if
2157
2158 ! allocate statevector
2159 if (mmpi_myid < stateVector%numStep) then
2160 if(variableName == 'TM') then
2161 call gsv_allocate(stateVector_1step, 1, stateVector%hco, &
2162 stateVector%vco, mpi_local_opt = .false., &
2163 dataKind_opt = 8, varNames_opt = (/variableName/))
2164 else
2165 call utl_abort('gvt_SSTSpread: unrecognized variable name: '//trim(variableName))
2166 end if
2167 end if
2168
2169 allocate(isWaterValue(1:stateVector%hco%ni, latIndexBeg:latIndexEnd))
2170 allocate(updatedIsWaterValue(1:stateVector%hco%ni, latIndexBeg:latIndexEnd))
2171 allocate(updatedField(1:stateVector%hco%ni, latIndexBeg:latIndexEnd))
2172
2173 call gsv_transposeTilesToStep(stateVector_1step, stateVector, 1)
2174
2175 if (gsv_isAllocated(stateVector_1step)) then
2176
2177 call gsv_getField(stateVector_1step, field_ptr, variableName)
2178
2179 ! Initialisation
2180 do latIndex = latIndexBeg, latIndexEnd
2181 do lonIndex = 1, stateVector%hco%ni
2182 if (stateVector%oceanMask%mask(lonIndex, latIndex, 1)) then
2183 isWaterValue(lonIndex, latIndex) = .True.
2184 else
2185 isWaterValue(lonIndex, latIndex) = .False.
2186 end if
2187 updatedField(lonIndex,latIndex) = field_ptr(lonIndex, latIndex, 1, 1)
2188 end do
2189 end do
2190 updatedIsWaterValue(:,:) = isWaterValue(:,:)
2191
2192 boxSizeLoop: do boxSize = 1, maxBoxSize
2193
2194 do latIndex = latIndexBeg, latIndexEnd
2195 do lonIndex = 1, stateVector%hco%ni
2196
2197 if (isWaterValue(lonIndex,latIndex)) cycle
2198
2199 top = latIndex + boxSize
2200 bottom = latIndex - boxSize
2201 left = lonIndex - boxSize
2202 right = lonIndex + boxSize
2203
2204 np = 0
2205 l = bottom
2206 do k = left, right
2207 np = np + 1
2208 in(np) = k
2209 jn(np) = l
2210 end do
2211 k = right
2212 do l = bottom + 1, top
2213 np = np + 1
2214 in(np) = k
2215 jn(np) = l
2216 end do
2217 l = top
2218 do k = right - 1, left, -1
2219 np = np + 1
2220 in(np) = k
2221 jn(np) = l
2222 end do
2223 k = left
2224 do l = top - 1, bottom + 1, -1
2225 np = np + 1
2226 in(np) = k
2227 jn(np) = l
2228 end do
2229
2230 ngp = 0
2231 updatedValueSum = 0.0
2232 do m = 1, np
2233 if (in(m) >= 1 .and. in(m) <= stateVector%hco%ni .and. &
2234 jn(m) >= latIndexBeg .and. jn(m) <= latIndexEnd ) then
2235 if (isWaterValue(in(m), jn(m))) then
2236 updatedValueSum = updatedValueSum + field_ptr(in(m), jn(m), 1, 1)
2237 ngp = ngp + 1
2238 end if
2239 end if
2240 end do
2241
2242 ! mark the grid point as being filled by interpolation on the grid
2243 if (ngp /= 0) then
2244 updatedIsWaterValue(lonIndex, latIndex) = .True.
2245 updatedField(lonIndex, latIndex) = updatedValueSum / real(ngp)
2246 end if
2247
2248 end do
2249 end do
2250
2251 isWaterValue(:,:) = updatedIsWaterValue(:,:)
2252 field_ptr(:, latIndexBeg:latIndexEnd, 1, 1) = updatedField(:,:)
2253
2254 end do boxSizeLoop
2255
2256 write(*,*) 'gvt_SSTSpread: Field min value = ', minval(field_ptr(:, latIndexBeg:latIndexEnd, 1, 1))
2257 write(*,*) 'gvt_SSTSpread: Field max value = ', maxval(field_ptr(:, latIndexBeg:latIndexEnd, 1, 1))
2258
2259 end if
2260
2261 call gsv_transposeStepToTiles(stateVector_1step, stateVector, 1)
2262
2263 ! deallocate local arrays
2264 if (mmpi_myid < stateVector%numStep) then
2265 call gsv_deallocate(stateVector_1step)
2266 end if
2267 deallocate(isWaterValue)
2268 deallocate(updatedIsWaterValue)
2269 deallocate(updatedField)
2270
2271 end subroutine gvt_SSTSpread
2272
2273end module gridVariableTransforms_mod