ROMS
Loading...
Searching...
No Matches
array_modes.F
Go to the documentation of this file.
1#include "cppdefs.h"
3#if defined WEAK_CONSTRAINT && (defined ARRAY_MODES || defined CLIPPING)
4!
5!git $Id$
6!================================================== Hernan G. Arango ===
7! Copyright (c) 2002-2025 The ROMS Group Andrew M. Moore !
8! Licensed under a MIT/X style license !
9! See License_ROMS.md !
10!=======================================================================
11! !
12! These routines are used to process the requested eigenvector(s) !
13! of the stabilized representer matrix when computing the array !
14! modes or clipped spectrum analysis. !
15! !
16! Reference: !
17! !
18! Bennett, A.F, 2002: Inverse Modeling of the Ocean and Atmosphere, !
19! Cambridge University Press, p 49-51. !
20! !
21!======================================================================!
22!
23 implicit none
24
25 PRIVATE
26# ifdef ARRAY_MODES
27 PUBLIC :: rep_check
28 PUBLIC :: rep_eigen
29# endif
30# ifdef CLIPPING
31 PUBLIC :: rep_clip
32# endif
33
34 CONTAINS
35
36# ifdef ARRAY_MODES
37 SUBROUTINE rep_check (ng, model, outLoop, NinnLoop)
38!
39!=======================================================================
40! !
41! This routine checks the dot-product of the array mode with the !
42! corresponding eigenvector of the stabilized representer matrix. !
43! !
44!=======================================================================
45!
46 USE mod_param
47 USE mod_parallel
48 USE mod_fourdvar
49 USE mod_iounits
50 USE mod_scalars
51
52# ifdef DISTRIBUTE
53!
54 USE distribute_mod, ONLY : mp_bcastf
55# endif
56!
57! Imported variable declarations
58!
59 integer, intent(in) :: ng, model, outloop, ninnloop
60!
61! Local variable declarations.
62!
63 integer :: iobs, innloop
64
65 real(r8) :: zsum
66# ifdef RPCG
67 real(r8) :: zfact
68 real(r8), dimension(NinnLoop) :: zdot
69# endif
70!
71!-----------------------------------------------------------------------
72! Check the dot-product of the array mode with the corresponding
73! eigenvector of the stabilized representer matrix.
74!-----------------------------------------------------------------------
75!
76 master_thread : IF (master) THEN
77
78# ifdef RPCG
79 DO innloop=1,ninnloop
80 zdot(innloop)=0.0_r8
81 IF (innloop.eq.1) THEN
82 zfact=1.0_r8/cg_gnorm_v(outloop)
83 ELSE
84 zfact=1.0_r8/cg_beta(innloop,outloop)
85 END IF
86 DO iobs=1,ndatum(ng)
87 IF (obserr(iobs).ne.0.0_r8) THEN
88 zdot(innloop)=zdot(innloop)+ &
89 & tlmodval(iobs)*zfact* &
90 & tlmodval_s(iobs,innloop,outloop)/ &
91 & obserr(iobs)
92 END IF
93 END DO
94 END DO
95!
96 zsum=0.0_r8
97 DO innloop=1,ninnloop
98 zsum=zsum+zdot(innloop)*cg_zv(innloop,nvct,outloop)
99 END DO
100# else
101 DO iobs=1,ndatum(ng)
102 admodval(iobs)=0.0_r8
103 END DO
104!
105! Multiply desired eigenvector of Lanczos tridiagonal matrix
106! by the Lanczos vectors to obtain the corresponding eigenvector
107! of the preconditioned stabilized representer matrix.
108!
109 DO iobs=1,ndatum(ng)
110 DO innloop=1,ninnloop
111 admodval(iobs)=admodval(iobs)+ &
112 & cg_zv(innloop,nvct,outloop)* &
113 & zcglwk(iobs,innloop,outloop)
114 END DO
115 END DO
116!
117! Now convert ADmodVal back to physical units.
118!
119 DO iobs=1,ndatum(ng)
120 IF (obserr(iobs).ne.0.0_r8) THEN
121 admodval(iobs)=admodval(iobs)/sqrt(obserr(iobs))
122 END IF
123 END DO
124!
125! Now compute the dot-product of the final solution with the initial
126! eigenvector.
127!
128 zsum=0.0_r8
129 DO iobs=1,ndatum(ng)
130 zsum=zsum+tlmodval(iobs)*admodval(iobs)
131 END DO
132# endif
133!
134! Compare the dot-product with (cg_Ritz-1).
135!
136 WRITE (stdout,10) zsum, cg_ritz(nvct,outloop)-1
137 10 FORMAT (/,' REP CHECK: zsum = ', 1p, e14.7,2x, &
138 & 'cg_Ritz-1 = ', 1p, e14.7)
139
140 END IF master_thread
141
142# ifdef DISTRIBUTE
143!
144!-----------------------------------------------------------------------
145! Broadcast new solution to other nodes.
146!-----------------------------------------------------------------------
147!
148 CALL mp_bcastf (ng, model, admodval)
149# endif
150
151 RETURN
152 END SUBROUTINE rep_check
153
154 SUBROUTINE rep_eigen (ng, model, outLoop, NinnLoop)
155!
156!=======================================================================
157! !
158! This routine computes the specified eigenvector, Nvct, of the !
159! stabilized representer matrix. !
160! !
161!=======================================================================
162!
163 USE mod_param
164 USE mod_parallel
165 USE mod_fourdvar
166 USE mod_iounits
167 USE mod_scalars
168
169# ifdef DISTRIBUTE
170!
171 USE distribute_mod, ONLY : mp_bcastf
172# endif
173!
174! Imported variable declarations
175!
176 integer, intent(in) :: ng, model, outloop, ninnloop
177!
178! Local variable declarations.
179!
180 integer :: iobs, innloop
181!
182!-----------------------------------------------------------------------
183! Compute specified eignevector of the stabilized representer matrix.
184!-----------------------------------------------------------------------
185!
186 master_thread : IF (master) THEN
187
188 DO iobs=1,ndatum(ng)
189 admodval(iobs)=0.0_r8
190 END DO
191!
192! Multiply desired eigenvector of Lanczos tridiagonal matrix
193! by the Lanczos vectors to obtain the corresponding eigenvector
194! of the preconditioned stabilized representer matrix.
195!
196 DO iobs=1,ndatum(ng)
197 DO innloop=1,ninnloop
198 admodval(iobs)=admodval(iobs)+ &
199 & cg_zv(innloop,nvct,outloop)* &
200 & zcglwk(iobs,innloop,outloop)
201 END DO
202 END DO
203
204# ifndef RPCG
205!
206! Now convert ADmodVal back to physical units.
207!
208 DO iobs=1,ndatum(ng)
209 IF (obserr(iobs).ne.0.0_r8) THEN
210 admodval(iobs)=admodval(iobs)/sqrt(obserr(iobs))
211 END IF
212 END DO
213# endif
214
215 END IF master_thread
216
217# ifdef DISTRIBUTE
218!
219!-----------------------------------------------------------------------
220! Broadcast new solution to other nodes.
221!-----------------------------------------------------------------------
222!
223 CALL mp_bcastf (ng, model, admodval)
224# endif
225
226 RETURN
227 END SUBROUTINE rep_eigen
228# endif
229
230# ifdef CLIPPING
231 SUBROUTINE rep_clip (ng, model, outLoop, NinnLoop)
232!
233!=======================================================================
234! !
235! This routine performs clipping of the analysis by disgarding !
236! potentially unphysical array modes. !
237! !
238!=======================================================================
239!
240 USE mod_param
241 USE mod_parallel
242 USE mod_fourdvar
243 USE mod_iounits
244 USE mod_scalars
245
246# ifdef DISTRIBUTE
247!
248 USE distribute_mod, ONLY : mp_bcastf
249# endif
250!
251! Imported variable declarations
252!
253 integer, intent(in) :: ng, model, outloop, ninnloop
254!
255! Local variable declarations.
256!
257 integer :: iobs, ivec, innloop
258
259 real(r8), dimension(NinnLoop) :: zu
260
261 real(r8), dimension(Ndatum(ng)) :: innov, rsvec
262!
263!-----------------------------------------------------------------------
264! Clipp the analysis by disgarding potentially unphysical array modes.
265!-----------------------------------------------------------------------
266!
267 master_thread : IF (master) THEN
268!
269! First compute the dot-product of innovation vector with each
270! selected eigenvector of the stabilized representer matrix.
271! All eigenvectors < Nvct are disgarded.
272!
273 DO iobs=1,ndatum(ng)
274 innov(iobs)=obsval(iobs)-nlmodval(iobs)
275 END DO
276 DO ivec=nvct,ninner
277 DO iobs=1,ndatum(ng)
278 rsvec(iobs)=0.0_r8
279 END DO
280 DO iobs=1,ndatum(ng)
281 DO innloop=1,ninnloop
282 rsvec(iobs)=rsvec(iobs)+ &
283 & cg_zv(innloop,ivec,outloop)* &
284 & zcglwk(iobs,innloop,outloop)
285 END DO
286 END DO
287!
288! Convert RSVEC back to physical units.
289!
290 DO iobs=1,ndatum(ng)
291 IF (obserr(iobs).ne.0.0_r8) THEN
292 rsvec(iobs)=rsvec(iobs)/sqrt(obserr(iobs))
293 END IF
294 END DO
295 zu(ivec)=0.0_r8
296 DO iobs=1,ndatum(ng)
297 zu(ivec)=zu(ivec)+innov(iobs)*rsvec(iobs)
298 END DO
299 END DO
300!
301! Second divide by the eigenvalues of the stabilized representer
302! matrix.
303!
304 DO ivec=nvct,ninner
305 zu(ivec)=zu(ivec)/cg_ritz(ivec,outloop)
306 END DO
307!
308! Finally form the weighted sum of the selected eigenvectors of the
309! stabilized representer matrix.
310!
311 DO iobs=1,ndatum(ng)
312 admodval(iobs)=0.0_r8
313 END DO
314!
315! Multiply desired eigenvector of Lanczos tridiagonal matrix
316! by the Lanczos vectors to obtain the corresponding eigenvector
317! of the preconditioned stabilized representer matrix.
318!
319 DO ivec=nvct,ninner
320 DO iobs=1,ndatum(ng)
321 DO innloop=1,ninnloop
322 admodval(iobs)=admodval(iobs)+ &
323 & cg_zv(innloop,ivec,outloop)* &
324 & zcglwk(iobs,innloop,outloop)* &
325 & zu(ivec)
326 END DO
327 END DO
328 END DO
329!
330! Now convert ADmodVal back to physical units.
331!
332 DO iobs=1,ndatum(ng)
333 IF (obserr(iobs).ne.0.0_r8) THEN
334 admodval(iobs)=admodval(iobs)/sqrt(obserr(iobs))
335 END IF
336 END DO
337
338 END IF master_thread
339
340# ifdef DISTRIBUTE
341!
342!-----------------------------------------------------------------------
343! Broadcast new solution to other nodes.
344!-----------------------------------------------------------------------
345!
346 CALL mp_bcastf (ng, model, admodval)
347# endif
348
349 RETURN
350 END SUBROUTINE rep_clip
351# endif
352#endif
353 END MODULE array_modes_mod
subroutine, public rep_check(ng, model, outloop, ninnloop)
Definition array_modes.F:38
subroutine, public rep_eigen(ng, model, outloop, ninnloop)
subroutine, public rep_clip(ng, model, outloop, ninnloop)
real(dp), dimension(:), allocatable cg_gnorm_v
real(dp), dimension(:,:), allocatable cg_beta
real(dp), dimension(:,:), allocatable cg_ritz
integer, dimension(:), allocatable ndatum
real(r8), dimension(:), allocatable obsval
real(r8), dimension(:), allocatable obserr
real(dp), dimension(:,:,:), allocatable cg_zv
real(r8), dimension(:), allocatable admodval
real(r8), dimension(:,:,:), allocatable zcglwk
real(r8), dimension(:), allocatable nlmodval
integer stdout
logical master
integer ninner