New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
obs_grid_search_bruteforce.h90 in branches/dev_1784_OBS/NEMO/OPA_SRC/OBS – NEMO

source: branches/dev_1784_OBS/NEMO/OPA_SRC/OBS/obs_grid_search_bruteforce.h90 @ 2001

Last change on this file since 2001 was 2001, checked in by djlea, 14 years ago

Adding observation operator code

File size: 13.9 KB
Line 
1   SUBROUTINE obs_grid_search_bruteforce( kpi, kpj, kpiglo, kpjglo,       &
2      &                                   kldi, klei, kldj, klej,         &
3      &                                   kmyproc, ktotproc,              &
4      &                                   pglam, pgphi, pmask,            &
5      &                                   kobs, plam, pphi, kobsi, kobsj, &
6      &                                   kproc)
7      !!----------------------------------------------------------------------
8      !!                ***  ROUTINE obs_grid_search_bruteforce ***
9      !!
10      !! ** Purpose : Search gridpoints to find the grid box containing
11      !!              the observations
12      !!
13      !! ** Method  : Call to linquad
14      !!
15      !! ** Action  : Return kproc holding the observation and kiobsi,kobsj
16      !!              valid on kproc=kmyproc processor only.
17      !!   
18      !! History :
19      !!        !  2001-11  (N. Daget, A. Weaver)
20      !!        !  2006-03  (A. Weaver) NEMOVAR migration.
21      !!        !  2006-05  (K. Mogensen) Moved to to separate routine.
22      !!        !  2007-10  (A. Vidard) Bug fix in wrap around checks; cleanup
23      !!----------------------------------------------------------------------
24
25      !! * Arguments
26      INTEGER, INTENT(IN) :: &
27         & kpi,     &               ! Number of local longitudes
28         & kpj,     &               ! Number of local latitudes
29         & kpiglo,  &               ! Number of global longitudes
30         & kpjglo,  &               ! Number of global latitudes
31         & kldi,    &               ! Start of inner domain in i
32         & klei,    &               ! End of inner domain in i
33         & kldj,    &               ! Start of inner domain in j
34         & klej,    &               ! End of inner domain in j
35         & kmyproc, &               ! Processor number for MPP
36         & ktotproc                 ! Total number of processors
37      REAL(KIND=wp), DIMENSION(kpi,kpj), INTENT(IN) :: &
38         & pglam,   &               ! Grid point longitude
39         & pgphi,   &               ! Grid point latitude
40         & pmask                    ! Grid point mask
41      INTEGER,INTENT(IN) :: &
42         & kobs                     ! Size of the observation arrays
43      REAL(KIND=wp), DIMENSION(kobs), INTENT(IN) :: &
44         & plam, &                  ! Longitude of obsrvations
45         & pphi                     ! Latitude of observations
46      INTEGER, DIMENSION(kobs), INTENT(OUT) :: &
47         & kobsi, &                 ! I-index of observations
48         & kobsj, &                 ! J-index of observations
49         & kproc                    ! Processor number of observations
50 
51      !! * Local declarations
52      REAL(wp), DIMENSION(:), ALLOCATABLE :: &
53         & zplam, zpphi
54      REAL(wp) :: &
55         & zlammax, &
56         & zlam
57      INTEGER :: &
58         & ji,      &
59         & jj,      &
60         & jk,      &
61         & jo,      &
62         & jlon,    &
63         & jlat,    &
64         & joffset, &
65         & jostride
66      REAL(KIND=wp), DIMENSION(:,:), ALLOCATABLE :: &
67         & zlamg, &
68         & zphig, &
69         & zmskg, &
70         & zphitmax,&
71         & zphitmin,&
72         & zlamtmax,&
73         & zlamtmin
74      LOGICAL, DIMENSION(:,:), ALLOCATABLE :: &
75         & llinvalidcell
76      REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: &
77         & zlamtm,  &
78         & zphitm
79
80      !-----------------------------------------------------------------------
81      ! Define grid setup for grid search
82      !-----------------------------------------------------------------------
83      IF (ln_grid_global) THEN
84         jlon     = kpiglo
85         jlat     = kpjglo
86         joffset  = kmyproc
87         jostride = ktotproc
88      ELSE
89         jlon     = kpi
90         jlat     = kpj
91         joffset  = 0
92         jostride = 1
93      ENDIF
94      !-----------------------------------------------------------------------
95      ! Set up data for grid search
96      !-----------------------------------------------------------------------
97      ALLOCATE( &
98         & zlamg(jlon,jlat),             &
99         & zphig(jlon,jlat),             &
100         & zmskg(jlon,jlat),             &
101         & zphitmax(jlon-1,jlat-1),      &
102         & zphitmin(jlon-1,jlat-1),      &
103         & zlamtmax(jlon-1,jlat-1),      &
104         & zlamtmin(jlon-1,jlat-1),      &
105         & llinvalidcell(jlon-1,jlat-1), &
106         & zlamtm(4,jlon-1,jlat-1),      &
107         & zphitm(4,jlon-1,jlat-1)       &
108         & )
109      !-----------------------------------------------------------------------
110      ! Copy data to local arrays
111      !-----------------------------------------------------------------------
112      IF (ln_grid_global) THEN
113         zlamg(:,:) = -1.e+10
114         zphig(:,:) = -1.e+10
115         zmskg(:,:) = -1.e+10
116         DO jj = kldj, klej
117            DO ji = kldi, klei
118               zlamg(mig(ji),mjg(jj)) = pglam(ji,jj)
119               zphig(mig(ji),mjg(jj)) = pgphi(ji,jj)
120               zmskg(mig(ji),mjg(jj)) = pmask(ji,jj)
121            END DO
122         END DO
123         CALL mpp_global_max( zlamg )
124         CALL mpp_global_max( zphig )
125         CALL mpp_global_max( zmskg )
126      ELSE
127         DO jj = 1, jlat
128            DO ji = 1, jlon
129               zlamg(ji,jj) = pglam(ji,jj)
130               zphig(ji,jj) = pgphi(ji,jj)
131               zmskg(ji,jj) = pmask(ji,jj)
132            END DO
133         END DO
134      ENDIF
135      !-----------------------------------------------------------------------
136      ! Copy longitudes and latitudes
137      !-----------------------------------------------------------------------
138      ALLOCATE( &
139         & zplam(kobs), &
140         & zpphi(kobs)  &
141         & )
142      DO jo = 1, kobs
143         zplam(jo) = plam(jo)
144         zpphi(jo) = pphi(jo)
145      ENDDO
146      !-----------------------------------------------------------------------
147      ! Set default values for output
148      !-----------------------------------------------------------------------
149      kproc(:) = -1
150      kobsi(:) = -1
151      kobsj(:) = -1
152      !-----------------------------------------------------------------------
153      ! Copy grid positions to temporary arrays and renormalize to 0 to 360.
154      !-----------------------------------------------------------------------
155      DO jj = 1, jlat-1
156         DO ji = 1, jlon-1
157            zlamtm(1,ji,jj) = zlamg(ji  ,jj  )
158            zphitm(1,ji,jj) = zphig(ji  ,jj  )
159            zlamtm(2,ji,jj) = zlamg(ji+1,jj  )
160            zphitm(2,ji,jj) = zphig(ji+1,jj  )
161            zlamtm(3,ji,jj) = zlamg(ji+1,jj+1)
162            zphitm(3,ji,jj) = zphig(ji+1,jj+1)
163            zlamtm(4,ji,jj) = zlamg(ji  ,jj+1)
164            zphitm(4,ji,jj) = zphig(ji  ,jj+1)
165         END DO
166      END DO
167      WHERE ( zlamtm(:,:,:) < 0.0_wp )
168         zlamtm(:,:,:) = zlamtm(:,:,:) + 360.0_wp
169      END WHERE
170      WHERE ( zlamtm(:,:,:) > 360.0_wp )
171         zlamtm(:,:,:) = zlamtm(:,:,:) - 360.0_wp
172      END WHERE
173      !-----------------------------------------------------------------------
174      ! Handle case of the wraparound; beware, not working with orca180
175      !-----------------------------------------------------------------------
176      DO jj = 1, jlat-1
177         DO ji = 1, jlon-1
178            zlammax = MAXVAL( zlamtm(:,ji,jj) )
179            WHERE (zlammax - zlamtm(:, ji, jj) > 180 ) &
180               & zlamtm(:,ji,jj) = zlamtm(:,ji,jj) + 360._wp
181            zphitmax(ji,jj) = MAXVAL(zphitm(:,ji,jj))
182            zphitmin(ji,jj) = MINVAL(zphitm(:,ji,jj))
183            zlamtmax(ji,jj) = MAXVAL(zlamtm(:,ji,jj))
184            zlamtmin(ji,jj) = MINVAL(zlamtm(:,ji,jj))
185         END DO
186      END DO
187      !-----------------------------------------------------------------------
188      ! Search for boxes with only land points mark them invalid
189      !-----------------------------------------------------------------------
190      llinvalidcell(:,:) = .FALSE.
191      DO jj = 1, jlat-1
192         DO ji = 1, jlon-1
193            llinvalidcell(ji,jj) =               &
194               & zmskg(ji  ,jj  ) == 0.0_wp .AND. &
195               & zmskg(ji+1,jj  ) == 0.0_wp .AND. &
196               & zmskg(ji+1,jj+1) == 0.0_wp .AND. &
197               & zmskg(ji  ,jj+1) == 0.0_wp
198         END DO
199      END DO
200
201      !------------------------------------------------------------------------
202      ! Master loop for grid search
203      !------------------------------------------------------------------------
204
205      DO jo = 1+joffset, kobs, jostride
206
207         !---------------------------------------------------------------------
208         ! Ensure that all observation longtiudes are between 0 and 360
209         !---------------------------------------------------------------------
210
211         IF ( zplam(jo) <   0.0_wp ) zplam(jo) = zplam(jo) + 360.0_wp
212         IF ( zplam(jo) > 360.0_wp ) zplam(jo) = zplam(jo) - 360.0_wp
213
214         !---------------------------------------------------------------------
215         ! Find observations which are on within 1e-6 of a grid point
216         !---------------------------------------------------------------------
217
218         gridloop: DO jj = 1, jlat-1
219            DO ji = 1, jlon-1
220               IF ( ABS( zphig(ji,jj) - zpphi(jo) ) < 1e-6 )  THEN
221                  zlam = zlamg(ji,jj)
222                  IF ( zlam <   0.0_wp ) zlam = zlam + 360.0_wp
223                  IF ( zlam > 360.0_wp ) zlam = zlam - 360.0_wp
224                  IF ( ABS( zlam - zplam(jo) ) < 1e-6 ) THEN
225                     IF ( llinvalidcell(ji,jj) ) THEN
226                        kproc(jo) = kmyproc + 1000000
227                        kobsi(jo) = ji + 1
228                        kobsj(jo) = jj + 1
229                        CYCLE
230                     ELSE
231                        kproc(jo) = kmyproc
232                        kobsi(jo) = ji + 1
233                        kobsj(jo) = jj + 1
234                        EXIT gridloop
235                     END IF
236                  ENDIF
237               ENDIF
238            ENDDO
239         ENDDO gridloop
240         
241         !---------------------------------------------------------------------
242         ! Ensure that all observation longtiudes are between -180 and 180
243         !---------------------------------------------------------------------
244
245         IF ( zplam(jo) > 180 ) zplam(jo) = zplam(jo) - 360.0_wp
246
247         !---------------------------------------------------------------------
248         ! Do coordinate search using brute force.
249         ! - For land points kproc is set to number of the processor + 1000000
250         !   and we continue the search.
251         ! - For ocean points kproc is set to the number of the processor
252         !   and we stop the search.
253         !---------------------------------------------------------------------
254
255         IF ( kproc(jo) == -1 ) THEN
256
257            ! Normal case
258            gridpoints : DO jj = 1, jlat-1
259               DO ji = 1, jlon-1
260                 
261                  IF ( ( zplam(jo) > zlamtmax(ji,jj) ) .OR. &
262                     & ( zplam(jo) < zlamtmin(ji,jj) ) ) CYCLE
263                 
264                  IF ( ABS( zpphi(jo) ) < 85 ) THEN
265                     IF ( ( zpphi(jo) > zphitmax(ji,jj) ) .OR. &
266                        & ( zpphi(jo) < zphitmin(ji,jj) ) ) CYCLE
267                  ENDIF
268                 
269                  IF ( linquad( zplam(jo), zpphi(jo), &
270                     &          zlamtm(:,ji,jj), zphitm(:,ji,jj) ) ) THEN
271                     IF ( llinvalidcell(ji,jj) ) THEN
272                        kproc(jo) = kmyproc + 1000000
273                        kobsi(jo) = ji + 1
274                        kobsj(jo) = jj + 1
275                        CYCLE
276                     ELSE
277                        kproc(jo) = kmyproc
278                        kobsi(jo) = ji + 1
279                        kobsj(jo) = jj + 1
280                        EXIT gridpoints
281                     ENDIF
282                  ENDIF
283                 
284               END DO
285            END DO gridpoints
286
287         ENDIF
288
289         ! In case of failure retry for obs. longtiude + 360.
290         IF ( kproc(jo) == -1 ) THEN
291            gridpoints_greenwich : DO jj = 1, jlat-1
292               DO ji = 1, jlon-1
293
294                  IF ( ( zplam(jo)+360.0_wp > zlamtmax(ji,jj) ) .OR. &
295                     & ( zplam(jo)+360.0_wp < zlamtmin(ji,jj) ) ) CYCLE
296
297                  IF ( ABS( zpphi(jo) ) < 85 ) THEN
298                     IF ( ( zpphi(jo) > zphitmax(ji,jj) ) .OR. &
299                        & ( zpphi(jo) < zphitmin(ji,jj) ) ) CYCLE
300                  ENDIF
301
302                  IF ( linquad( zplam(jo)+360.0_wp, zpphi(jo), &
303                     &          zlamtm(:,ji,jj), zphitm(:,ji,jj) ) ) THEN
304                     IF ( llinvalidcell(ji,jj) ) THEN
305                        kproc(jo) = kmyproc + 1000000
306                        kobsi(jo) = ji + 1
307                        kobsj(jo) = jj + 1
308                        CYCLE
309                     ELSE
310                        kproc(jo) = kmyproc
311                        kobsi(jo) = ji + 1
312                        kobsj(jo) = jj + 1
313                        EXIT gridpoints_greenwich
314                     ENDIF
315                  ENDIF
316
317               END DO
318            END DO gridpoints_greenwich
319
320         ENDIF
321      END DO
322
323      !----------------------------------------------------------------------
324      ! Synchronize kproc on all processors
325      !----------------------------------------------------------------------
326      IF ( ln_grid_global ) THEN
327         CALL obs_mpp_max_integer( kproc, kobs )
328         CALL obs_mpp_max_integer( kobsi, kobs )
329         CALL obs_mpp_max_integer( kobsj, kobs )
330      ELSE
331         CALL obs_mpp_find_obs_proc( kproc, kobsi, kobsj, kobs )
332      ENDIF
333
334      WHERE( kproc(:) >= 1000000 )
335         kproc(:) = kproc(:) - 1000000
336      END WHERE
337
338      DEALLOCATE( &
339         & zlamg,         &
340         & zphig,         &
341         & zmskg,         &
342         & zphitmax,      &
343         & zphitmin,      &
344         & zlamtmax,      &
345         & zlamtmin,      &
346         & llinvalidcell, &
347         & zlamtm,        &
348         & zphitm,        &
349         & zplam,         &
350         & zpphi          &
351         & )
352
353   END SUBROUTINE obs_grid_search_bruteforce
Note: See TracBrowser for help on using the repository browser.