source: CPL/oasis3-mct/branches/OASIS3-MCT_2.0_branch/lib/scrip/src/remap_bicubic.f @ 4775

Last change on this file since 4775 was 4775, checked in by aclsce, 4 years ago
  • Imported oasis3-mct from Cerfacs svn server (not suppotred anymore).

The version has been extracted from https://oasis3mct.cerfacs.fr/svn/branches/OASIS3-MCT_2.0_branch/oasis3-mct@1818

File size: 26.4 KB
Line 
1C****
2C               *****************************
3C               * OASIS MODULE  -  LEVEL ? *
4C               * -------------     ------- *
5C               *****************************
6C
7C**** remap_bilinear - calculate bilinear remapping
8C
9C     Purpose:
10C     -------
11C     Adaptation of SCRIP 1.4 remap_bicubic module to calculate 
12C     bicubic remapping.
13C
14C**   Interface:
15C     ---------
16C       *CALL*  *remap_bicub**
17C
18C     Input:
19C     -----
20C
21C     Output:
22C     ------
23C
24C     History:
25C     -------
26C       Version   Programmer     Date        Description
27C       -------   ----------     ----        ----------- 
28C       2.5       S. Valcke      2002/09     Treatment for masked point
29C
30C %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
31!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
32!
33!     this module contains necessary routines for performing an
34!     bicubic interpolation.
35!
36!-----------------------------------------------------------------------
37!
38!     CVS:$Id: remap_bicubic.f 2826 2010-12-10 11:14:21Z valcke $
39!
40!     Copyright (c) 1997, 1998 the Regents of the University of
41!       California.
42!
43!     This software and ancillary information (herein called software)
44!     called SCRIP is made available under the terms described here. 
45!     The software has been approved for release with associated
46!     LA-CC Number 98-45.
47!
48!     Unless otherwise indicated, this software has been authored
49!     by an employee or employees of the University of California,
50!     operator of the Los Alamos National Laboratory under Contract
51!     No. W-7405-ENG-36 with the U.S. Department of Energy.  The U.S.
52!     Government has rights to use, reproduce, and distribute this
53!     software.  The public may copy and use this software without
54!     charge, provided that this Notice and any statement of authorship
55!     are reproduced on all copies.  Neither the Government nor the
56!     University makes any warranty, express or implied, or assumes
57!     any liability or responsibility for the use of this software.
58!
59!     If software is modified to produce derivative works, such modified
60!     software should be clearly marked, so as not to confuse it with
61!     the version available from Los Alamos National Laboratory.
62!
63!***********************************************************************
64
65      module remap_bicubic
66
67!-----------------------------------------------------------------------
68
69      use kinds_mod     ! defines common data types
70      use constants     ! defines common constants
71      use grids         ! module containing grid info
72      use remap_vars    ! module containing remap info
73      USE mod_oasis_flush
74
75      implicit NONE
76
77!-----------------------------------------------------------------------
78
79      integer (kind=int_kind), parameter ::
80     &    max_iter = 100   ! max iteration count for i,j iteration
81
82      real (kind=dbl_kind), parameter ::
83     &     converge = 1.e-10_dbl_kind ! convergence criterion
84
85!***********************************************************************
86
87      contains
88
89!***********************************************************************
90
91      subroutine remap_bicub (lextrapdone)
92
93!-----------------------------------------------------------------------
94!
95!     this routine computes the weights for a bicubic interpolation.
96!
97!-----------------------------------------------------------------------
98
99      LOGICAL :: lextrapdone   ! logical, true if EXTRAP done on field
100      LOGICAL :: ll_nnei       ! true (default) if extra search is done
101
102!-----------------------------------------------------------------------
103!
104!     local variables
105!
106!-----------------------------------------------------------------------
107
108      integer (kind=int_kind) :: n,icount,i, 
109     &     dst_add,        ! destination address
110     &     iter,           ! iteration counter
111     &     nmap            ! index of current map being computed
112
113      integer (kind=int_kind), dimension(4) :: 
114     &     src_add         ! address for the four source points
115
116      real (kind=dbl_kind), dimension(4)  ::
117     &     src_lats,       ! latitudes  of four  corners
118     &     src_lons        ! longitudes of four  corners
119
120      real (kind=dbl_kind), dimension(4,4)  ::
121     &     wgts            ! bicubic weights for four corners
122
123      real (kind=dbl_kind) ::
124     &     plat, plon,       ! lat/lon coords of destination point
125     &     iguess, jguess,   ! current guess for bicubic coordinate
126     &     deli, delj,       ! corrections to i,j
127     &     dth1, dth2, dth3, ! some latitude  differences
128     &     dph1, dph2, dph3, ! some longitude differences
129     &     dthp, dphp,       ! difference between point and sw corner
130     &     mat1, mat2, mat3, mat4, ! matrix elements
131     &     determinant,      ! matrix determinant
132     &     sum_wgts         ! sum of weights for normalization
133
134      real (kind=dbl_kind) :: 
135     &      coslat_dst, sinlat_dst, coslon_dst, sinlon_dst,
136     &      dist_min, distance, ! for computing dist-weighted avg
137     &      src_latsnn, arg
138
139      integer (kind=int_kind) :: min_add, max_add, srch_add, src_addnn
140
141!-----------------------------------------------------------------------
142!
143!     compute mappings from grid1 to grid2
144!
145!-----------------------------------------------------------------------
146!
147      IF (nlogprt .GE. 2) THEN
148         WRITE (UNIT = nulou,FMT = *)' '
149         WRITE (UNIT = nulou,FMT = *)'Entering routine remap_bicub'
150         CALL OASIS_FLUSH_SCRIP(nulou)
151      ENDIF
152!
153      ll_nnei = .true.
154      nmap = 1
155      if (grid1_rank /= 2) then
156        stop 'Can not do bicubic interpolation when grid_rank /= 2'
157      endif
158
159      !***
160      !*** loop over destination grid
161      !***
162     
163      grid_loop1: do dst_add = 1, grid2_size
164
165        if (.not. grid2_mask(dst_add)) cycle grid_loop1
166
167        plat = grid2_center_lat(dst_add)
168        plon = grid2_center_lon(dst_add)
169
170        !***
171        !*** find nearest square of grid points on source grid
172        !***
173
174        call grid_search_bicub(src_add, src_lats, src_lons,
175     &                         min_add, max_add,
176     &                         plat, plon, grid1_dims,
177     &                         grid1_center_lat, grid1_center_lon,
178     &                         grid1_bound_box, bin_addr1, 
179     &                         lextrapdone)
180
181        if (src_add(1) > 0) then
182
183          !***
184          !*** if the 4 surrounding points have been found and are
185          !*** non-masked, do bicubic interpolation
186          !***
187
188          grid2_frac(dst_add) = one
189
190          dth1 = src_lats(2) - src_lats(1)
191          dth2 = src_lats(4) - src_lats(1)
192          dth3 = src_lats(3) - src_lats(2) - dth2
193
194          dph1 = src_lons(2) - src_lons(1)
195          dph2 = src_lons(4) - src_lons(1)
196          dph3 = src_lons(3) - src_lons(2)
197
198          if (dph1 >  three*pih) dph1 = dph1 - pi2
199          if (dph2 >  three*pih) dph2 = dph2 - pi2
200          if (dph3 >  three*pih) dph3 = dph3 - pi2
201          if (dph1 < -three*pih) dph1 = dph1 + pi2
202          if (dph2 < -three*pih) dph2 = dph2 + pi2
203          if (dph3 < -three*pih) dph3 = dph3 + pi2
204
205          dph3 = dph3 - dph2
206
207          iguess = half
208          jguess = half
209
210          iter_loop1: do iter=1,max_iter
211
212            dthp = plat - src_lats(1) - dth1*iguess -
213     &                    dth2*jguess - dth3*iguess*jguess
214            dphp = plon - src_lons(1)
215
216            if (dphp >  three*pih) dphp = dphp - pi2
217            if (dphp < -three*pih) dphp = dphp + pi2
218
219            dphp = dphp - dph1*iguess - dph2*jguess - 
220     &                    dph3*iguess*jguess
221
222            mat1 = dth1 + dth3*jguess
223            mat2 = dth2 + dth3*iguess
224            mat3 = dph1 + dph3*jguess
225            mat4 = dph2 + dph3*iguess
226
227            determinant = mat1*mat4 - mat2*mat3
228
229            deli = (dthp*mat4 - mat2*dphp)/determinant
230            delj = (mat1*dphp - dthp*mat3)/determinant
231
232            if (abs(deli) < converge .and. 
233     &          abs(delj) < converge) exit iter_loop1
234
235            iguess = iguess + deli
236            jguess = jguess + delj
237
238          end do iter_loop1
239
240          if (iter <= max_iter) then
241
242            !***
243            !*** successfully found i,j - compute weights
244            !***
245
246            wgts(1,1) = (one - jguess**2*(three-two*jguess))*
247     &                  (one - iguess**2*(three-two*iguess))
248            wgts(1,2) = (one - jguess**2*(three-two*jguess))*
249     &                         iguess**2*(three-two*iguess)
250            wgts(1,3) =        jguess**2*(three-two*jguess)*
251     &                         iguess**2*(three-two*iguess)
252            wgts(1,4) =        jguess**2*(three-two*jguess)*
253     &                  (one - iguess**2*(three-two*iguess))
254            wgts(2,1) = (one - jguess**2*(three-two*jguess))*
255     &                         iguess*(iguess-one)**2
256            wgts(2,2) = (one - jguess**2*(three-two*jguess))*
257     &                         iguess**2*(iguess-one)
258            wgts(2,3) =        jguess**2*(three-two*jguess)*
259     &                         iguess**2*(iguess-one)
260            wgts(2,4) =        jguess**2*(three-two*jguess)*
261     &                         iguess*(iguess-one)**2
262            wgts(3,1) =        jguess*(jguess-one)**2*
263     &                  (one - iguess**2*(three-two*iguess))
264            wgts(3,2) =        jguess*(jguess-one)**2*
265     &                         iguess**2*(three-two*iguess)
266            wgts(3,3) =        jguess**2*(jguess-one)*
267     &                         iguess**2*(three-two*iguess)
268            wgts(3,4) =        jguess**2*(jguess-one)*
269     &                  (one - iguess**2*(three-two*iguess))
270            wgts(4,1) =        iguess*(iguess-one)**2*
271     &                         jguess*(jguess-one)**2
272            wgts(4,2) =        iguess**2*(iguess-one)*
273     &                         jguess*(jguess-one)**2
274            wgts(4,3) =        iguess**2*(iguess-one)*
275     &                         jguess**2*(jguess-one)
276            wgts(4,4) =        iguess*(iguess-one)**2*
277     &                         jguess**2*(jguess-one)
278
279            call store_link_bicub(dst_add, src_add, wgts, nmap)
280
281          ELSE
282              WRITE (UNIT = nulou,FMT = *)
283     &            'Iteration for i,j exceed max iteration count'
284              STOP
285          endif
286
287        else if (src_add(1) < 0) THEN
288
289          !***
290          !*** Search for bicubic failed or at least one of the 4
291          !*** neighbours was masked. Do distance-weighted average using
292          !*** the non-masked points among the 4 closest ones.
293          !***
294
295
296          IF (nlogprt .eq. 2) then
297              WRITE(nulou,*) ' '
298              WRITE(nulou,*) 
299     &  'WARNING: Cannot make bicubic interpolation for target point'
300     &            ,dst_add
301              WRITE(nulou,*) 
302     &    'Using non-masked points among 4 nearest neighbors.'
303              WRITE(nulou,*) ' '
304          ENDIF
305
306          !***
307          !*** Find the 4 closest points
308          !***
309          coslat_dst = cos(plat)
310          sinlat_dst = sin(plat)
311          coslon_dst = cos(plon)
312          sinlon_dst = sin(plon)
313          src_add = 0
314          dist_min = bignum
315          src_lats = bignum
316          do srch_add = min_add,max_add
317            arg = coslat_dst*cos(grid1_center_lat(srch_add))*
318     &           (coslon_dst*cos(grid1_center_lon(srch_add)) +
319     &            sinlon_dst*sin(grid1_center_lon(srch_add)))+
320     &            sinlat_dst*sin(grid1_center_lat(srch_add))
321            IF (arg < -1.0d0) THEN
322                arg = -1.0d0
323            ELSE IF (arg > 1.0d0) THEN
324                arg = 1.0d0
325            END IF               
326            distance=acos(arg)
327            if (distance < dist_min) then
328                sort_loop: do n=1,4
329                if (distance < src_lats(n)) then
330                    do i=4,n+1,-1
331                      src_add (i) = src_add (i-1)
332                      src_lats(i) = src_lats(i-1)
333                    end do
334                    src_add (n) = srch_add
335                    src_lats(n) = distance
336                    dist_min = src_lats(4)
337                    exit sort_loop
338                endif
339                end do sort_loop
340            endif
341          end do
342
343          src_lons = one/(src_lats + tiny)
344          distance = sum(src_lons)
345          src_lats = src_lons/distance
346
347          !***
348          !*** Among 4 closest points, keep only the non-masked ones
349          !***
350
351          icount = 0
352          do n=1,4
353            if (grid1_mask(src_add(n)) .or.
354     &          (.not. grid1_mask(src_add(n)) .and. lextrapdone)) then
355                icount = icount + 1
356            else
357                src_lats(n) = zero
358            endif
359          end do
360
361          if (icount > 0) then
362              !*** renormalize weights
363              sum_wgts = sum(src_lats)
364              wgts(1,1) = src_lats(1)/sum_wgts
365              wgts(1,2) = src_lats(2)/sum_wgts
366              wgts(1,3) = src_lats(3)/sum_wgts
367              wgts(1,4) = src_lats(4)/sum_wgts
368              wgts(2,:) = 0.
369              wgts(3,:) = 0.
370              wgts(4,:) = 0.
371
372              grid2_frac(dst_add) = one
373              call store_link_bicub(dst_add, src_add, wgts, nmap)
374          ELSE
375              IF (ll_nnei .eqv. .true. ) then
376              IF (NLOGPRT .GE. 2) THEN
377                  WRITE(nulou,*) '  '
378                  WRITE(nulou,*)' Using the nearest non-masked neighbour
379     & as all 4 surrounding source points are masked for target point',
380     &                dst_add
381                  WRITE(nulou,*) 'with longitude and latitude', 
382     &                plon, plat
383              ENDIF
384              src_latsnn = bignum
385!cdir novector
386              do srch_add = min_add,max_add
387                if (grid1_mask(srch_add) .or.
388     &          (.not. grid1_mask(srch_add) .and. lextrapdone)) THEN
389                    arg = coslat_dst*cos(grid1_center_lat(srch_add))*
390     &                   (coslon_dst*cos(grid1_center_lon(srch_add)) +
391     &                    sinlon_dst*sin(grid1_center_lon(srch_add)))+
392     &                    sinlat_dst*sin(grid1_center_lat(srch_add))
393                    IF (arg < -1.0d0) THEN
394                        arg = -1.0d0
395                    ELSE IF (arg > 1.0d0) THEN
396                        arg = 1.0d0
397                    END IF                   
398                    distance=acos(arg)
399
400                    if (distance < src_latsnn) then
401                        src_addnn = srch_add
402                        src_latsnn = distance
403                    endif
404                endif
405              end DO
406              IF (NLOGPRT .GE. 2) THEN
407                  WRITE(nulou,*) '  '
408                  WRITE(nulou,*) 
409     &                'Nearest non masked neighbour is source point ',
410     &                src_addnn
411                  WRITE(nulou,*) 'with longitude and latitude',
412     &          grid1_center_lon(src_addnn), grid1_center_lat(src_addnn)
413              ENDIF
414!
415              wgts(1,1) = 1.
416              wgts(1,2:4) = 0.
417              wgts(2,:) = 0.
418              wgts(3,:) = 0.
419              wgts(4,:) = 0.
420              src_add(1) = src_addnn
421              src_add(2) = 0
422              src_add(3) = 0
423              src_add(4) = 0
424
425              grid2_frac(dst_add) = one
426              call store_link_bicub(dst_add, src_add, wgts, nmap)
427          endif
428       ENDIF
429      ENDIF
430      end do grid_loop1
431!
432      IF (nlogprt .GE. 2) THEN
433         WRITE (UNIT = nulou,FMT = *)' '
434         WRITE (UNIT = nulou,FMT = *)'Leaving routine remap_bicub'
435         CALL OASIS_FLUSH_SCRIP(nulou)
436      ENDIF
437!
438      end subroutine remap_bicub
439
440!***********************************************************************
441
442      subroutine grid_search_bicub(src_add, src_lats, src_lons, 
443     &                             min_add, max_add,
444     &                             plat, plon, src_grid_dims,
445     &                             src_center_lat, src_center_lon,
446     &                             src_bound_box,
447     &                             src_bin_add, lextrapdone)
448
449!-----------------------------------------------------------------------
450!
451!     this routine finds the location of the search point plat, plon
452!     in the source grid and returns the corners needed for a bicubic
453!     interpolation.
454!
455!-----------------------------------------------------------------------
456
457!-----------------------------------------------------------------------
458!
459!     output variables
460!
461!-----------------------------------------------------------------------
462
463      integer (kind=int_kind), dimension(4), intent(out) ::
464     &        src_add  ! address of each corner point enclosing P
465
466      real (kind=dbl_kind), dimension(4), intent(out) ::
467     &        src_lats, ! latitudes  of the four corner points
468     &        src_lons  ! longitudes of the four corner points
469
470      integer (kind=int_kind) :: min_add, max_add
471   
472!-----------------------------------------------------------------------
473!
474!     input variables
475!
476!-----------------------------------------------------------------------
477
478      real (kind=dbl_kind), intent(in) ::
479     &        plat,   ! latitude  of the search point
480     &        plon    ! longitude of the search point
481
482      integer (kind=int_kind), dimension(2), intent(in) ::
483     &        src_grid_dims  ! size of each src grid dimension
484
485      real (kind=dbl_kind), dimension(:), intent(in) ::
486     &        src_center_lat, ! latitude  of each src grid center
487     &        src_center_lon  ! longitude of each src grid center
488
489      real (kind=dbl_kind), dimension(:,:), intent(in) ::
490     &        src_bound_box   ! bounding box for src grid search
491
492      integer (kind=int_kind), dimension(:,:), intent(in) ::
493     &        src_bin_add    ! search bins for restricting
494
495      LOGICAL ::
496     &           lextrapdone   ! logical, true if EXTRAP done on field
497
498!-----------------------------------------------------------------------
499!
500!     local variables
501!
502!-----------------------------------------------------------------------
503
504      integer (kind=int_kind) :: n, next_n, srch_add, ni,  ! dummy indices
505     &    nx, ny, ntotmask,           ! dimensions of src grid
506     &    i, j, jp1, ip1, n_add, e_add, ne_add  ! addresses
507
508      real (kind=dbl_kind) ::  ! vectors for cross-product check
509     &      vec1_lat, vec1_lon,
510     &      vec2_lat, vec2_lon, cross_product, cross_product_last
511
512!-----------------------------------------------------------------------
513!
514!     restrict search first using search bins.
515!
516!-----------------------------------------------------------------------
517
518      src_add = 0
519
520      min_add = size(src_center_lat)
521      max_add = 1
522      do n=1,num_srch_bins
523        if (plat >= bin_lats(1,n) .and. plat <= bin_lats(2,n) .and.
524     &      plon >= bin_lons(1,n) .and. plon <= bin_lons(2,n)) then
525          min_add = min(min_add, src_bin_add(1,n))
526          max_add = max(max_add, src_bin_add(2,n))
527        endif
528      end do
529 
530!-----------------------------------------------------------------------
531!
532!     now perform a more detailed search
533!
534!-----------------------------------------------------------------------
535
536      nx = src_grid_dims(1)
537      ny = src_grid_dims(2)
538
539      srch_loop: do srch_add = min_add,max_add
540
541        !*** first check bounding box
542
543        if (plat <= src_bound_box(2,srch_add) .and. 
544     &    plat >= src_bound_box(1,srch_add) .and.
545     &    plon <= src_bound_box(4,srch_add) .and. 
546     &    plon >= src_bound_box(3,srch_add)) then
547
548          !***
549          !*** we are within bounding box so get really serious
550          !***
551
552          !*** find N,S and NE points to this grid point
553
554          j = (srch_add - 1)/nx +1
555          i = srch_add - (j-1)*nx
556         
557          !*** find ip1
558          !*** Note: I do not want to take into account the number
559          !*** of overlapping grid points, as the underlying cell
560          !*** will be found in all cases if the grid overlaps.
561
562          if (i < nx) then
563              ip1 = i + 1
564          else
565              ip1 = 1
566          endif
567
568          if (j < ny) then
569              jp1 = j+1
570          else
571              jp1 = 1
572          endif
573
574          n_add = (jp1 - 1)*nx + i
575          e_add = (j - 1)*nx + ip1
576          ne_add = (jp1 - 1)*nx + ip1
577
578          src_lats(1) = src_center_lat(srch_add)
579          src_lats(2) = src_center_lat(e_add)
580          src_lats(3) = src_center_lat(ne_add)
581          src_lats(4) = src_center_lat(n_add)
582
583          src_lons(1) = src_center_lon(srch_add)
584          src_lons(2) = src_center_lon(e_add)
585          src_lons(3) = src_center_lon(ne_add)
586          src_lons(4) = src_center_lon(n_add)
587
588          !***
589          !*** for consistency, we must make sure all lons are in
590          !*** same 2pi interval
591          !***
592
593          vec1_lon = src_lons(1) - plon
594          if (vec1_lon > pi) then
595              src_lons(1) = src_lons(1) - pi2
596          else if (vec1_lon < -pi) then
597              src_lons(1) = src_lons(1) + pi2
598          endif
599          do n=2,4
600            vec1_lon = src_lons(n) - src_lons(1)
601            if (vec1_lon > pi) then
602                src_lons(n) = src_lons(n) - pi2
603            else if (vec1_lon < -pi) then
604                src_lons(n) = src_lons(n) + pi2
605            endif
606          end do
607
608          corner_loop: do n=1,4
609            next_n = MOD(n,4) + 1
610
611            !***
612            !*** here we take the cross product of the vector making
613            !*** up each box side with the vector formed by the vertex
614            !*** and search point.  if all the cross products are
615            !*** same sign, the point is contained in the box.
616            !***
617
618            vec1_lat = src_lats(next_n) - src_lats(n)
619            vec1_lon = src_lons(next_n) - src_lons(n)
620            vec2_lat = plat - src_lats(n)
621            vec2_lon = plon - src_lons(n)
622
623            !***
624            !*** check for 0,2pi crossings
625            !***
626
627            if (vec1_lon >  three*pih) then
628                vec1_lon = vec1_lon - pi2
629            else if (vec1_lon < -three*pih) then
630                vec1_lon = vec1_lon + pi2
631            endif
632            if (vec2_lon >  three*pih) then
633                vec2_lon = vec2_lon - pi2
634            else if (vec2_lon < -three*pih) then
635                vec2_lon = vec2_lon + pi2
636            endif
637
638            cross_product = vec1_lon*vec2_lat - vec2_lon*vec1_lat
639
640            !***
641            !*** if cross product is less than zero, this cell
642            !*** doesn't work
643            !***
644
645            if (n == 1) cross_product_last = cross_product
646            if (cross_product*cross_product_last < zero) then
647                exit corner_loop
648            else
649                cross_product_last = cross_product
650            endif
651
652          end do corner_loop
653
654          !***
655          !*** if cross products all positive, we found the location
656          !***
657
658          if (n > 4) then
659              src_add(1) = srch_add
660              src_add(2) = e_add
661              src_add(3) = ne_add
662              src_add(4) = n_add
663             
664              ! Check if one point is masked; IF so, nearest-neighbour
665              ! interpolation will be used
666 
667              ntotmask = 0
668              do ni=1,4
669                if (.not. grid1_mask(src_add(ni)).and. 
670     &              .not. lextrapdone) 
671     &              ntotmask = ntotmask + 1 
672              end DO
673              IF (ntotmask .gt. 0) src_add(1) = -src_add(1) 
674     
675              return
676          endif
677
678          !***
679          !*** otherwise move on to next cell
680          !***
681
682      endif                     !bounding box check
683      end do srch_loop
684
685      !***
686      !*** if no cell found, point is likely either in a box that straddles
687      !*** either pole or is outside the grid. Put src_add = -1 so that
688      !*** distance-weighted average of the 4 non-masked closest points
689      !*** is done in calling routine.
690 
691      src_add = -1
692
693!-----------------------------------------------------------------------
694
695      end subroutine grid_search_bicub 
696
697!***********************************************************************
698
699      subroutine store_link_bicub(dst_add, src_add, weights, nmap)
700
701!-----------------------------------------------------------------------
702!
703!     this routine stores the address and weight for four links
704!     associated with one destination point in the appropriate address
705!     and weight arrays and resizes those arrays if necessary.
706!
707!-----------------------------------------------------------------------
708
709!-----------------------------------------------------------------------
710!
711!     input variables
712!
713!-----------------------------------------------------------------------
714
715      integer (kind=int_kind), intent(in) ::
716     &        dst_add,  ! address on destination grid
717     &        nmap      ! identifies which direction for mapping
718
719      integer (kind=int_kind), dimension(4), intent(in) ::
720     &        src_add   ! addresses on source grid
721
722      real (kind=dbl_kind), dimension(4,4), intent(in) ::
723     &        weights ! array of remapping weights for these links
724
725!-----------------------------------------------------------------------
726!
727!     local variables
728!
729!-----------------------------------------------------------------------
730
731      integer (kind=int_kind) :: n, ! dummy index
732     &       num_links_old          ! placeholder for old link number
733
734!-----------------------------------------------------------------------
735!
736!     increment number of links and check to see if remap arrays need
737!     to be increased to accomodate the new link.  then store the
738!     link.
739!
740!-----------------------------------------------------------------------
741
742      select case (nmap)
743      case(1)
744
745        num_links_old  = num_links_map1
746        num_links_map1 = num_links_old + 4
747
748        if (num_links_map1 > max_links_map1) 
749     &     call resize_remap_vars(1,resize_increment)
750
751        do n=1,4
752          grid1_add_map1(num_links_old+n) = src_add(n)
753          grid2_add_map1(num_links_old+n) = dst_add
754          wts_map1    (:,num_links_old+n) = weights(:,n)
755        end do
756
757      case(2)
758
759        num_links_old  = num_links_map2
760        num_links_map2 = num_links_old + 4
761
762        if (num_links_map2 > max_links_map2) 
763     &     call resize_remap_vars(2,resize_increment)
764
765        do n=1,4
766          grid1_add_map2(num_links_old+n) = dst_add
767          grid2_add_map2(num_links_old+n) = src_add(n)
768          wts_map2    (:,num_links_old+n) = weights(:,n)
769        end do
770
771      end select
772
773!-----------------------------------------------------------------------
774
775      end subroutine store_link_bicub
776
777!***********************************************************************
778
779      end module remap_bicubic
780
781!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Note: See TracBrowser for help on using the repository browser.