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.
solsor.F90 in branches/2011/DEV_r2739_STFC_dCSE/NEMOGCM/NEMO/OPA_SRC/SOL – NEMO

source: branches/2011/DEV_r2739_STFC_dCSE/NEMOGCM/NEMO/OPA_SRC/SOL/solsor.F90 @ 4460

Last change on this file since 4460 was 3211, checked in by spickles2, 12 years ago

Stephen Pickles, 11 Dec 2011

Commit to bring the rest of the DCSE NEMO development branch
in line with the latest development version. This includes
array index re-ordering of all OPA_SRC/.

  • Property svn:keywords set to Id
File size: 8.0 KB
RevLine 
[3]1MODULE solsor
2   !!======================================================================
[86]3   !!                     ***  MODULE  solsor  ***
[3]4   !! Ocean solver :  Successive Over-Relaxation solver
5   !!=====================================================================
[1601]6   !! History :  OPA  ! 1990-10  (G. Madec)  Original code
7   !!            7.1  ! 1993-04  (G. Madec)  time filter
8   !!                 ! 1996-05  (G. Madec)  merge sor and pcg formulations
9   !!                 ! 1996-11  (A. Weaver)  correction to preconditioning
10   !!   NEMO     1.0  ! 2003-04  (C. Deltel, G. Madec)  Red-Black SOR in free form
11   !!            2.0  ! 2005-09  (R. Benshila, G. Madec)  MPI optimization
12   !!----------------------------------------------------------------------
[3]13
14   !!----------------------------------------------------------------------
[86]15   !!   sol_sor     : Red-Black Successive Over-Relaxation solver
[3]16   !!----------------------------------------------------------------------
17   USE oce             ! ocean dynamics and tracers variables
18   USE dom_oce         ! ocean space and time domain variables
19   USE zdf_oce         ! ocean vertical physics variables
20   USE sol_oce         ! solver variables
21   USE in_out_manager  ! I/O manager
22   USE lib_mpp         ! distributed memory computing
23   USE lbclnk          ! ocean lateral boundary conditions (or mpp link)
[2528]24   USE lib_fortran
[3]25
26   IMPLICIT NONE
27   PRIVATE
28
[1601]29   PUBLIC   sol_sor    !
[16]30
[3211]31   !! * Control permutation of array indices
32#  include "oce_ftrans.h90"
33#  include "dom_oce_ftrans.h90"
34#  include "zdf_oce_ftrans.h90"
35
[3]36   !!----------------------------------------------------------------------
[2528]37   !! NEMO/OPA 3.3 , NEMO Consortium (2010)
[1152]38   !! $Id$
[2715]39   !! Software governed by the CeCILL licence     (NEMOGCM/NEMO_CeCILL.txt)
[3]40   !!----------------------------------------------------------------------
41CONTAINS
42     
[16]43   SUBROUTINE sol_sor( kindic )
[3]44      !!----------------------------------------------------------------------
45      !!                  ***  ROUTINE sol_sor  ***
46      !!                 
[1528]47      !! ** Purpose :   Solve the ellipic equation for the transport
48      !!      divergence system  using a red-black successive-over-
[86]49      !!      relaxation method.
[784]50      !!       This routine provides a MPI optimization to the existing solsor
51      !!     by reducing the number of call to lbc.
52      !!
[3]53      !! ** Method  :   Successive-over-relaxation method using the red-black
54      !!      technique. The former technique used was not compatible with
55      !!      the north-fold boundary condition used in orca configurations.
[784]56      !!      Compared to the classical sol_sor, this routine provides a
57      !!      mpp optimization by reducing the number of calls to lnc_lnk
58      !!      The solution is computed on a larger area and the boudary
59      !!      conditions only when the inside domain is reached.
60      !!
[1601]61      !! References :   Madec et al. 1988, Ocean Modelling, issue 78, 1-6.
62      !!                Beare and Stevens 1997 Ann. Geophysicae 15, 1369-1377
63      !!----------------------------------------------------------------------
[2715]64      USE wrk_nemo, ONLY:   wrk_in_use, wrk_not_released
65      USE wrk_nemo, ONLY:   ztab => wrk_2d_1    ! 2D workspace
66      !!
[1601]67      INTEGER, INTENT(inout) ::   kindic   ! solver indicator, < 0 if the convergence is not reached:
68      !                                    ! the model is stopped in step (set to zero before the call of solsor)
[3]69      !!
[2715]70      INTEGER  ::   ji, jj, jn       ! dummy loop indices
71      INTEGER  ::   ishift, icount, ijmppodd, ijmppeven, ijpr2d   ! local integers
72      REAL(wp) ::   ztmp, zres, zres2                             ! local scalars
[3]73      !!----------------------------------------------------------------------
74     
[2715]75      IF( wrk_in_use(2, 1) )THEN
76         CALL ctl_stop('sol_sor: requested workspace array is unavailable')   ;   RETURN
77      ENDIF
78
[1601]79      ijmppeven = MOD( nimpp+njmpp+jpr2di+jpr2dj   , 2 )
80      ijmppodd  = MOD( nimpp+njmpp+jpr2di+jpr2dj+1 , 2 )
81      ijpr2d    = MAX( jpr2di , jpr2dj )
[784]82      icount = 0
[16]83      !                                                       ! ==============
[1601]84      DO jn = 1, nn_nmax                                      ! Iterative loop
[16]85         !                                                    ! ==============
[3]86
[1601]87         IF( MOD(icount,ijpr2d+1) == 0 )   CALL lbc_lnk_e( gcx, c_solver_pt, 1. )   ! lateral boundary conditions
[784]88       
[16]89         ! Residus
90         ! -------
[86]91
92         ! Guess black update
[784]93         DO jj = 2-jpr2dj, nlcj-1+jpr2dj
94            ishift = MOD( jj-ijmppodd-jpr2dj, 2 )
95            DO ji = 2-jpr2di+ishift, nlci-1+jpr2di, 2
[86]96               ztmp =                  gcb(ji  ,jj  )   &
97                  &   - gcp(ji,jj,1) * gcx(ji  ,jj-1)   &
98                  &   - gcp(ji,jj,2) * gcx(ji-1,jj  )   &
99                  &   - gcp(ji,jj,3) * gcx(ji+1,jj  )   &
100                  &   - gcp(ji,jj,4) * gcx(ji  ,jj+1)
101               ! Estimate of the residual
[111]102               zres = ztmp - gcx(ji,jj)
[86]103               gcr(ji,jj) = zres * gcdmat(ji,jj) * zres
104               ! Guess update
[1601]105               gcx(ji,jj) = rn_sor * ztmp + (1-rn_sor) * gcx(ji,jj)
[3]106            END DO
107         END DO
[784]108         icount = icount + 1 
109 
[1601]110         IF( MOD(icount,ijpr2d+1) == 0 )   CALL lbc_lnk_e( gcx, c_solver_pt, 1. )   ! lateral boundary conditions
[3]111
[86]112         ! Guess red update
[784]113         DO jj = 2-jpr2dj, nlcj-1+jpr2dj
114            ishift = MOD( jj-ijmppeven-jpr2dj, 2 )
115            DO ji = 2-jpr2di+ishift, nlci-1+jpr2di, 2
[86]116               ztmp =                  gcb(ji  ,jj  )   &
117                  &   - gcp(ji,jj,1) * gcx(ji  ,jj-1)   &
118                  &   - gcp(ji,jj,2) * gcx(ji-1,jj  )   &
119                  &   - gcp(ji,jj,3) * gcx(ji+1,jj  )   &
120                  &   - gcp(ji,jj,4) * gcx(ji  ,jj+1) 
121               ! Estimate of the residual
[111]122               zres = ztmp - gcx(ji,jj)
[86]123               gcr(ji,jj) = zres * gcdmat(ji,jj) * zres
124               ! Guess update
[1601]125               gcx(ji,jj) = rn_sor * ztmp + (1-rn_sor) * gcx(ji,jj)
[3]126            END DO
127         END DO
[784]128         icount = icount + 1
[86]129
[111]130         ! test of convergence
[1601]131         IF ( jn > nn_nmin .AND. MOD( jn-nn_nmin, nn_nmod ) == 0 ) THEN
[86]132
[1601]133            SELECT CASE ( nn_sol_arp )
[120]134            CASE ( 0 )                 ! absolute precision (maximum value of the residual)
[784]135               zres2 = MAXVAL( gcr(2:nlci-1,2:nlcj-1) )
[120]136               IF( lk_mpp )   CALL mpp_max( zres2 )   ! max over the global domain
137               ! test of convergence
[1601]138               IF( zres2 < rn_resmax .OR. jn == nn_nmax ) THEN
[120]139                  res = SQRT( zres2 )
140                  niter = jn
141                  ncut = 999
142               ENDIF
[111]143            CASE ( 1 )                 ! relative precision
[2528]144               ztab = 0.
145               ztab(:,:) = gcr(2:nlci-1,2:nlcj-1)
146               rnorme = glob_sum( ztab)    ! sum over the global domain
[111]147               ! test of convergence
[1601]148               IF( rnorme < epsr .OR. jn == nn_nmax ) THEN
[111]149                  res = SQRT( rnorme )
150                  niter = jn
151                  ncut = 999
152               ENDIF
[120]153            END SELECT
[3]154         
155         !****
156         !     IF(lwp)WRITE(numsol,9300) jn, res, sqrt( epsr ) / eps
1579300     FORMAT('          niter :',i4,' res :',e20.10,' b :',e20.10)
158         !****
159         
[111]160         ENDIF
[3]161         ! indicator of non-convergence or explosion
[1601]162         IF( jn == nn_nmax .OR. SQRT(epsr)/eps > 1.e+20 ) kindic = -2
[3]163         IF( ncut == 999 ) GOTO 999
164         
[16]165         !                                                 ! =====================
166      END DO                                               ! END of iterative loop
167      !                                                    ! =====================
[3]168     
169999   CONTINUE
170     
[16]171      !  Output in gcx
172      !  -------------
[784]173      CALL lbc_lnk_e( gcx, c_solver_pt, 1. )    ! boundary conditions
[2715]174      !
175      IF( wrk_not_released(2, 1) )   CALL ctl_stop('sol_sor: failed to release workspace array')
[1601]176      !
[3]177   END SUBROUTINE sol_sor
178
179   !!=====================================================================
180END MODULE solsor
Note: See TracBrowser for help on using the repository browser.