Changeset 3294 for trunk/NEMOGCM/NEMO/OPA_SRC/BDY
- Timestamp:
- 2012-01-28T17:44:18+01:00 (12 years ago)
- Location:
- trunk/NEMOGCM/NEMO/OPA_SRC/BDY
- Files:
-
- 1 deleted
- 8 edited
- 3 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/NEMOGCM/NEMO/OPA_SRC/BDY/bdy_oce.F90
r2715 r3294 7 7 !! 3.0 ! 2008-04 (NEMO team) add in the reference version 8 8 !! 3.3 ! 2010-09 (D. Storkey) add ice boundary conditions 9 !! 3.4 ! 2011 (D. Storkey) rewrite in preparation for OBC-BDY merge 9 10 !!---------------------------------------------------------------------- 10 11 #if defined key_bdy … … 19 20 PUBLIC 20 21 22 TYPE, PUBLIC :: OBC_INDEX !: Indices and weights which define the open boundary 23 INTEGER, DIMENSION(jpbgrd) :: nblen 24 INTEGER, DIMENSION(jpbgrd) :: nblenrim 25 INTEGER, POINTER, DIMENSION(:,:) :: nbi 26 INTEGER, POINTER, DIMENSION(:,:) :: nbj 27 INTEGER, POINTER, DIMENSION(:,:) :: nbr 28 INTEGER, POINTER, DIMENSION(:,:) :: nbmap 29 REAL , POINTER, DIMENSION(:,:) :: nbw 30 REAL , POINTER, DIMENSION(:) :: flagu 31 REAL , POINTER, DIMENSION(:) :: flagv 32 END TYPE OBC_INDEX 33 34 TYPE, PUBLIC :: OBC_DATA !: Storage for external data 35 REAL, POINTER, DIMENSION(:) :: ssh 36 REAL, POINTER, DIMENSION(:) :: u2d 37 REAL, POINTER, DIMENSION(:) :: v2d 38 REAL, POINTER, DIMENSION(:,:) :: u3d 39 REAL, POINTER, DIMENSION(:,:) :: v3d 40 REAL, POINTER, DIMENSION(:,:) :: tem 41 REAL, POINTER, DIMENSION(:,:) :: sal 42 #if defined key_lim2 43 REAL, POINTER, DIMENSION(:) :: frld 44 REAL, POINTER, DIMENSION(:) :: hicif 45 REAL, POINTER, DIMENSION(:) :: hsnif 46 #endif 47 END TYPE OBC_DATA 48 21 49 !!---------------------------------------------------------------------- 22 50 !! Namelist variables 23 51 !!---------------------------------------------------------------------- 24 CHARACTER(len=80) :: cn_mask !: Name of unstruct. bdy mask file 25 CHARACTER(len=80) :: cn_dta_frs_T !: Name of unstruct. bdy data file at T points for FRS conditions 26 CHARACTER(len=80) :: cn_dta_frs_U !: Name of unstruct. bdy data file at U points for FRS conditions 27 CHARACTER(len=80) :: cn_dta_frs_V !: Name of unstruct. bdy data file at V points for FRS conditions 28 CHARACTER(len=80) :: cn_dta_fla_T !: Name of unstruct. bdy data file at T points for Flather scheme 29 CHARACTER(len=80) :: cn_dta_fla_U !: Name of unstruct. bdy data file at U points for Flather scheme 30 CHARACTER(len=80) :: cn_dta_fla_V !: Name of unstruct. bdy data file at V points for Flather scheme 52 CHARACTER(len=80), DIMENSION(jp_bdy) :: cn_coords_file !: Name of bdy coordinates file 53 CHARACTER(len=80) :: cn_mask_file !: Name of bdy mask file 31 54 ! 32 LOGICAL :: ln_tides = .false. !: =T apply tidal harmonic forcing along open boundaries 33 LOGICAL :: ln_vol = .false. !: =T volume correction 34 LOGICAL :: ln_mask = .false. !: =T read bdymask from file 35 LOGICAL :: ln_clim = .false. !: =T bdy data files contain 1 time dump (-->bdy forcing will be constant) 36 ! ! or 12 months (-->bdy forcing will be cyclic) 37 LOGICAL :: ln_dyn_fla = .false. !: =T Flather boundary conditions on barotropic velocities 38 LOGICAL :: ln_dyn_frs = .false. !: =T FRS boundary conditions on velocities 39 LOGICAL :: ln_tra_frs = .false. !: =T FRS boundary conditions on tracers (T and S) 40 LOGICAL :: ln_ice_frs = .false. !: =T FRS boundary conditions on seaice (leads fraction, ice depth, snow depth) 55 LOGICAL, DIMENSION(jp_bdy) :: ln_coords_file !: =T read bdy coordinates from file; 56 ! !: =F read bdy coordinates from namelist 57 LOGICAL :: ln_mask_file !: =T read bdymask from file 58 LOGICAL :: ln_vol !: =T volume correction 41 59 ! 42 INTEGER :: nn_rimwidth = 7 !: boundary rim width 43 INTEGER :: nn_dtactl = 1 !: = 0 use the initial state as bdy dta ; = 1 read it in a NetCDF file 44 INTEGER :: nn_volctl = 1 !: = 0 the total volume will have the variability of the surface Flux E-P 45 ! ! = 1 the volume will be constant during all the integration. 46 60 INTEGER :: nb_bdy !: number of open boundary sets 61 INTEGER, DIMENSION(jp_bdy) :: nn_rimwidth !: boundary rim width for Flow Relaxation Scheme 62 INTEGER :: nn_volctl !: = 0 the total volume will have the variability of the surface Flux E-P 63 ! ! = 1 the volume will be constant during all the integration. 64 INTEGER, DIMENSION(jp_bdy) :: nn_dyn2d ! Choice of boundary condition for barotropic variables (U,V,SSH) 65 INTEGER, DIMENSION(jp_bdy) :: nn_dyn2d_dta !: = 0 use the initial state as bdy dta ; 66 !: = 1 read it in a NetCDF file 67 !: = 2 read tidal harmonic forcing from a NetCDF file 68 !: = 3 read external data AND tidal harmonic forcing from NetCDF files 69 INTEGER, DIMENSION(jp_bdy) :: nn_dyn3d ! Choice of boundary condition for baroclinic velocities 70 INTEGER, DIMENSION(jp_bdy) :: nn_dyn3d_dta !: = 0 use the initial state as bdy dta ; 71 !: = 1 read it in a NetCDF file 72 INTEGER, DIMENSION(jp_bdy) :: nn_tra ! Choice of boundary condition for active tracers (T and S) 73 INTEGER, DIMENSION(jp_bdy) :: nn_tra_dta !: = 0 use the initial state as bdy dta ; 74 !: = 1 read it in a NetCDF file 75 #if defined key_lim2 76 INTEGER, DIMENSION(jp_bdy) :: nn_ice_lim2 ! Choice of boundary condition for sea ice variables 77 INTEGER, DIMENSION(jp_bdy) :: nn_ice_lim2_dta !: = 0 use the initial state as bdy dta ; 78 !: = 1 read it in a NetCDF file 79 #endif 80 ! 81 47 82 !!---------------------------------------------------------------------- 48 83 !! Global variables … … 52 87 REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: bdyvmask !: Mask defining computational domain at V-points 53 88 89 REAL(wp) :: bdysurftot !: Lateral surface of unstructured open boundary 90 91 REAL(wp), POINTER, DIMENSION(:,:) :: pssh !: 92 REAL(wp), POINTER, DIMENSION(:,:) :: phur !: 93 REAL(wp), POINTER, DIMENSION(:,:) :: phvr !: Pointers for barotropic fields 94 REAL(wp), POINTER, DIMENSION(:,:) :: pu2d !: 95 REAL(wp), POINTER, DIMENSION(:,:) :: pv2d !: 96 54 97 !!---------------------------------------------------------------------- 55 !! Unstructuredopen boundary data variables98 !! open boundary data variables 56 99 !!---------------------------------------------------------------------- 57 INTEGER, DIMENSION(jpbgrd) :: nblen = 0 !: Size of bdy data on a proc for each grid type58 INTEGER, DIMENSION(jpbgrd) :: nblenrim = 0 !: Size of bdy data on a proc for first rim ind59 INTEGER, DIMENSION(jpbgrd) :: nblendta = 0 !: Size of bdy data in file60 100 61 INTEGER, DIMENSION(jpbdim,jpbgrd) :: nbi, nbj !: i and j indices of bdy dta 62 INTEGER, DIMENSION(jpbdim,jpbgrd) :: nbr !: Discrete distance from rim points 63 INTEGER, DIMENSION(jpbdim,jpbgrd) :: nbmap !: Indices of data in file for data in memory 64 65 REAL(wp) :: bdysurftot !: Lateral surface of unstructured open boundary 66 67 REAL(wp), DIMENSION(jpbdim) :: flagu, flagv !: Flag for normal velocity compnt for velocity components 68 REAL(wp), DIMENSION(jpbdim,jpbgrd) :: nbw !: Rim weights of bdy data 69 70 REAL(wp), DIMENSION(jpbdim) :: sshbdy !: Now clim of bdy sea surface height (Flather) 71 REAL(wp), DIMENSION(jpbdim) :: ubtbdy, vbtbdy !: Now clim of bdy barotropic velocity components 72 REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: tbdy , sbdy !: Now clim of bdy temperature and salinity 73 REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: ubdy , vbdy !: Now clim of bdy velocity components 74 REAL(wp), DIMENSION(jpbdim) :: sshtide !: Tidal boundary array : SSH 75 REAL(wp), DIMENSION(jpbdim) :: utide, vtide !: Tidal boundary array : U and V 76 #if defined key_lim2 77 REAL(wp), DIMENSION(jpbdim) :: frld_bdy !: now ice leads fraction climatology 78 REAL(wp), DIMENSION(jpbdim) :: hicif_bdy !: Now ice thickness climatology 79 REAL(wp), DIMENSION(jpbdim) :: hsnif_bdy !: now snow thickness 80 #endif 101 INTEGER, DIMENSION(jp_bdy) :: nn_dta !: =0 => *all* data is set to initial conditions 102 !: =1 => some data to be read in from data files 103 REAL(wp), ALLOCATABLE, DIMENSION(:,:,:), TARGET :: dta_global !: workspace for reading in global data arrays 104 TYPE(OBC_INDEX), DIMENSION(jp_bdy), TARGET :: idx_bdy !: bdy indices (local process) 105 TYPE(OBC_DATA) , DIMENSION(jp_bdy) :: dta_bdy !: bdy external data (local process) 81 106 82 107 !!---------------------------------------------------------------------- … … 94 119 !!---------------------------------------------------------------------- 95 120 ! 96 ALLOCATE( bdytmask(jpi,jpj) , tbdy(jpbdim,jpk) , sbdy(jpbdim,jpk) , & 97 & bdyumask(jpi,jpj) , ubdy(jpbdim,jpk) , & 98 & bdyvmask(jpi,jpj) , vbdy(jpbdim,jpk) , STAT=bdy_oce_alloc ) 121 ALLOCATE( bdytmask(jpi,jpj) , bdyumask(jpi,jpj), bdyvmask(jpi,jpj), & 122 & STAT=bdy_oce_alloc ) 99 123 ! 100 124 IF( lk_mpp ) CALL mpp_sum ( bdy_oce_alloc ) … … 112 136 !!====================================================================== 113 137 END MODULE bdy_oce 138 -
trunk/NEMOGCM/NEMO/OPA_SRC/BDY/bdy_par.F90
r2528 r3294 7 7 !! 3.0 ! 2008-04 (NEMO team) add in the reference version 8 8 !! 3.3 ! 2010-09 (D. Storkey and E. O'Dea) update for Shelf configurations 9 !! 3.4 ! 2011 (D. Storkey) rewrite in preparation for OBC-BDY merge 9 10 !!---------------------------------------------------------------------- 10 11 #if defined key_bdy … … 16 17 PUBLIC 17 18 19 # if ! defined key_agrif 18 20 LOGICAL, PUBLIC, PARAMETER :: lk_bdy = .TRUE. !: Unstructured Ocean Boundary Condition flag 19 INTEGER, PUBLIC, PARAMETER :: jpbdta = 20000 !: Max length of bdy field in file 20 INTEGER, PUBLIC, PARAMETER :: jpbdim = 20000 !: Max length of bdy field on a processor 21 # else 22 LOGICAL, PUBLIC :: lk_bdy = .TRUE. !: Unstructured Ocean Boundary Condition flag 23 # endif 24 INTEGER, PUBLIC, PARAMETER :: jp_bdy = 10 !: Maximum number of bdy sets 21 25 INTEGER, PUBLIC, PARAMETER :: jpbtime = 1000 !: Max number of time dumps per file 22 INTEGER, PUBLIC, PARAMETER :: jpbgrd = 6 !: Number of horizontal grid types used (T, u, v, f) 26 INTEGER, PUBLIC, PARAMETER :: jpbgrd = 3 !: Number of horizontal grid types used (T, U, V) 27 28 !! Flags for choice of schemes 29 INTEGER, PUBLIC, PARAMETER :: jp_none = 0 !: Flag for no open boundary condition 30 INTEGER, PUBLIC, PARAMETER :: jp_frs = 1 !: Flag for Flow Relaxation Scheme 31 INTEGER, PUBLIC, PARAMETER :: jp_flather = 2 !: Flag for Flather 23 32 #else 24 33 !!---------------------------------------------------------------------- 25 34 !! Default option : NO Unstructured open boundary condition 26 35 !!---------------------------------------------------------------------- 27 LOGICAL, PUBLIC, PARAMETER :: lk_bdy = .FALSE. !: Unstructured Ocean Boundary Condition flag 36 # if ! defined key_agrif 37 LOGICAL, PUBLIC, PARAMETER :: lk_bdy = .FALSE. !: Unstructured Ocean Boundary Condition flag 38 # else 39 LOGICAL, PUBLIC :: lk_bdy = .FALSE. !: Unstructured Ocean Boundary Condition flag 40 # endif 28 41 #endif 29 42 -
trunk/NEMOGCM/NEMO/OPA_SRC/BDY/bdydta.F90
r2715 r3294 10 10 !! 3.3 ! 2010-09 (E.O'Dea) modifications for Shelf configurations 11 11 !! 3.3 ! 2010-09 (D.Storkey) add ice boundary conditions 12 !! 3.4 ! 2011 (D. Storkey) rewrite in preparation for OBC-BDY merge 12 13 !!---------------------------------------------------------------------- 13 14 #if defined key_bdy 14 15 !!---------------------------------------------------------------------- 15 !! 'key_bdy' Unstructured Open Boundary Conditions 16 !!---------------------------------------------------------------------- 17 !! bdy_dta_frs : read u, v, t, s data along open boundaries 18 !! bdy_dta_fla : read depth-mean velocities and elevation along open boundaries 19 !!---------------------------------------------------------------------- 16 !! 'key_bdy' Open Boundary Conditions 17 !!---------------------------------------------------------------------- 18 !! bdy_dta : read external data along open boundaries from file 19 !! bdy_dta_init : initialise arrays etc for reading of external data 20 !!---------------------------------------------------------------------- 21 USE wrk_nemo ! Memory Allocation 22 USE timing ! Timing 20 23 USE oce ! ocean dynamics and tracers 21 24 USE dom_oce ! ocean space and time domain 22 25 USE phycst ! physical constants 23 USE bdy_oce ! ocean open boundary conditions 26 USE bdy_oce ! ocean open boundary conditions 24 27 USE bdytides ! tidal forcing at boundaries 25 USE iom26 USE io ipsl28 USE fldread ! read input fields 29 USE iom ! IOM library 27 30 USE in_out_manager ! I/O logical units 28 31 #if defined key_lim2 … … 33 36 PRIVATE 34 37 35 PUBLIC bdy_dta_frs ! routines called by step.F90 36 PUBLIC bdy_dta_fla 37 PUBLIC bdy_dta_alloc ! routine called by bdy_init.F90 38 39 INTEGER :: numbdyt, numbdyu, numbdyv ! logical units for T-, U-, & V-points data file, resp. 40 INTEGER :: ntimes_bdy ! exact number of time dumps in data files 41 INTEGER :: nbdy_b, nbdy_a ! record of bdy data file for before and after time step 42 INTEGER :: numbdyt_bt, numbdyu_bt, numbdyv_bt ! logical unit for T-, U- & V-points data file, resp. 43 INTEGER :: ntimes_bdy_bt ! exact number of time dumps in data files 44 INTEGER :: nbdy_b_bt, nbdy_a_bt ! record of bdy data file for before and after time step 45 46 INTEGER, DIMENSION (jpbtime) :: istep, istep_bt ! time array in seconds in each data file 47 48 REAL(wp) :: zoffset ! time offset between time origin in file & start time of model run 49 50 REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:) :: tbdydta, sbdydta ! time interpolated values of T and S bdy data 51 REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:) :: ubdydta, vbdydta ! time interpolated values of U and V bdy data 52 REAL(wp), DIMENSION(jpbdim,2) :: ubtbdydta, vbtbdydta ! Arrays used for time interpolation of bdy data 53 REAL(wp), DIMENSION(jpbdim,2) :: sshbdydta ! bdy data of ssh 54 55 #if defined key_lim2 56 REAL(wp), DIMENSION(jpbdim,2) :: frld_bdydta ! } 57 REAL(wp), DIMENSION(jpbdim,2) :: hicif_bdydta ! } Arrays used for time interp. of ice bdy data 58 REAL(wp), DIMENSION(jpbdim,2) :: hsnif_bdydta ! } 59 #endif 60 38 PUBLIC bdy_dta ! routine called by step.F90 and dynspg_ts.F90 39 PUBLIC bdy_dta_init ! routine called by nemogcm.F90 40 41 INTEGER, ALLOCATABLE, DIMENSION(:) :: nb_bdy_fld ! Number of fields to update for each boundary set. 42 INTEGER :: nb_bdy_fld_sum ! Total number of fields to update for all boundary sets. 43 44 LOGICAL, DIMENSION(jp_bdy) :: ln_full_vel_array ! =T => full velocities in 3D boundary conditions 45 ! =F => baroclinic velocities in 3D boundary conditions 46 47 TYPE(FLD), PUBLIC, ALLOCATABLE, DIMENSION(:), TARGET :: bf ! structure of input fields (file informations, fields read) 48 49 TYPE(MAP_POINTER), ALLOCATABLE, DIMENSION(:) :: nbmap_ptr ! array of pointers to nbmap 50 51 # include "domzgr_substitute.h90" 61 52 !!---------------------------------------------------------------------- 62 53 !! NEMO/OPA 3.3 , NEMO Consortium (2010) … … 66 57 CONTAINS 67 58 68 FUNCTION bdy_dta_alloc() 69 !!---------------------------------------------------------------------- 70 USE lib_mpp, ONLY: ctl_warn, mpp_sum 71 ! 72 INTEGER :: bdy_dta_alloc 73 !!---------------------------------------------------------------------- 74 ! 75 ALLOCATE(tbdydta(jpbdim,jpk,2), sbdydta(jpbdim,jpk,2), & 76 ubdydta(jpbdim,jpk,2), vbdydta(jpbdim,jpk,2), Stat=bdy_dta_alloc) 77 78 IF( lk_mpp ) CALL mpp_sum ( bdy_dta_alloc ) 79 IF(bdy_dta_alloc /= 0) CALL ctl_warn('bdy_dta_alloc: failed to allocate arrays') 80 81 END FUNCTION bdy_dta_alloc 82 83 84 SUBROUTINE bdy_dta_frs( kt ) 59 SUBROUTINE bdy_dta( kt, jit, time_offset ) 85 60 !!---------------------------------------------------------------------- 86 !! *** SUBROUTINE bdy_dta _frs***61 !! *** SUBROUTINE bdy_dta *** 87 62 !! 88 !! ** Purpose : Read unstructured boundary data for FRS condition. 89 !! 90 !! ** Method : At the first timestep, read in boundary data for two 91 !! times from the file and time-interpolate. At other 92 !! timesteps, check to see if we need another time from 93 !! the file. If so read it in. Time interpolate. 63 !! ** Purpose : Update external data for open boundary conditions 64 !! 65 !! ** Method : Use fldread.F90 66 !! 94 67 !!---------------------------------------------------------------------- 95 INTEGER, INTENT( in ) :: kt ! ocean time-step index (for timesplitting option, otherwise zero) 96 !! 97 CHARACTER(LEN=80), DIMENSION(3) :: clfile ! names of input files 98 CHARACTER(LEN=70 ) :: clunits ! units attribute of time coordinate 99 LOGICAL :: lect ! flag for reading 100 INTEGER :: it, ib, ik, igrd ! dummy loop indices 101 INTEGER :: igrd_start, igrd_end ! start and end of loops on igrd 102 INTEGER :: idvar ! netcdf var ID 103 INTEGER :: iman, i15, imois ! Time variables for monthly clim forcing 104 INTEGER :: ntimes_bdyt, ntimes_bdyu, ntimes_bdyv 105 INTEGER :: itimer, totime 106 INTEGER :: ii, ij ! array addresses 107 INTEGER :: ipi, ipj, ipk, inum ! local integers (NetCDF read) 108 INTEGER :: iyear0, imonth0, iday0 109 INTEGER :: ihours0, iminutes0, isec0 110 INTEGER :: iyear, imonth, iday, isecs 111 INTEGER, DIMENSION(jpbtime) :: istept, istepu, istepv ! time arrays from data files 112 REAL(wp) :: dayfrac, zxy, zoffsett 113 REAL(wp) :: zoffsetu, zoffsetv 114 REAL(wp) :: dayjul0, zdayjulini 115 REAL(wp), DIMENSION(jpbtime) :: zstepr ! REAL time array from data files 116 REAL(wp), DIMENSION(jpbdta,1,jpk) :: zdta ! temporary array for data fields 68 !! 69 INTEGER, INTENT( in ) :: kt ! ocean time-step index 70 INTEGER, INTENT( in ), OPTIONAL :: jit ! subcycle time-step index (for timesplitting option) 71 INTEGER, INTENT( in ), OPTIONAL :: time_offset ! time offset in units of timesteps. NB. if jit 72 ! is present then units = subcycle timesteps. 73 ! time_offset = 0 => get data at "now" time level 74 ! time_offset = -1 => get data at "before" time level 75 ! time_offset = +1 => get data at "after" time level 76 ! etc. 77 !! 78 INTEGER :: ib_bdy, jfld, jstart, jend, ib, ii, ij, ik, igrd ! local indices 79 INTEGER, DIMENSION(jpbgrd) :: ilen1 80 INTEGER, POINTER, DIMENSION(:) :: nblen, nblenrim ! short cuts 81 !! 117 82 !!--------------------------------------------------------------------------- 118 119 120 IF( ln_dyn_frs .OR. ln_tra_frs & 121 & .OR. ln_ice_frs ) THEN ! If these are both false then this routine does nothing 122 123 ! -------------------- ! 124 ! Initialization ! 125 ! -------------------- ! 126 127 lect = .false. ! If true, read a time record 128 129 ! Some time variables for monthly climatological forcing: 130 ! ******************************************************* 131 132 !!gm here use directely daymod calendar variables 133 134 iman = INT( raamo ) ! Number of months in a year 135 136 i15 = INT( 2*REAL( nday, wp ) / ( REAL( nmonth_len(nmonth), wp ) + 0.5 ) ) 137 ! i15=0 if the current day is in the first half of the month, else i15=1 138 139 imois = nmonth + i15 - 1 ! imois is the first month record 140 IF( imois == 0 ) imois = iman 141 142 ! Time variable for non-climatological forcing: 143 ! ********************************************* 144 itimer = (kt-nit000+1)*rdt ! current time in seconds for interpolation 145 146 147 ! !-------------------! 148 IF( kt == nit000 ) THEN ! First call only ! 149 ! !-------------------! 150 istep(:) = 0 151 nbdy_b = 0 152 nbdy_a = 0 153 154 ! Get time information from bdy data file 155 ! *************************************** 156 157 IF(lwp) WRITE(numout,*) 158 IF(lwp) WRITE(numout,*) 'bdy_dta_frs : Initialize unstructured boundary data' 159 IF(lwp) WRITE(numout,*) '~~~~~~~' 160 161 IF ( nn_dtactl == 0 ) THEN 162 ! 163 IF(lwp) WRITE(numout,*) ' Bdy data are taken from initial conditions' 164 ! 165 ELSEIF (nn_dtactl == 1) THEN 166 ! 167 IF(lwp) WRITE(numout,*) ' Bdy data are read in netcdf files' 168 ! 169 dayfrac = adatrj - REAL( itimer, wp ) / 86400. ! day fraction at time step kt-1 170 dayfrac = dayfrac - INT ( dayfrac ) ! 171 totime = ( nitend - nit000 + 1 ) * rdt ! Total time of the run to verify that all the 172 ! ! necessary time dumps in file are included 173 ! 174 clfile(1) = cn_dta_frs_T 175 clfile(2) = cn_dta_frs_U 176 clfile(3) = cn_dta_frs_V 177 ! 178 ! how many files are we to read in? 179 igrd_start = 1 180 igrd_end = 3 181 IF(.NOT. ln_tra_frs .AND. .NOT. ln_ice_frs) THEN ! No T-grid file. 182 igrd_start = 2 183 ELSEIF ( .NOT. ln_dyn_frs ) THEN ! No U-grid or V-grid file. 184 igrd_end = 1 185 ENDIF 186 187 DO igrd = igrd_start, igrd_end ! loop over T, U & V grid ! 188 ! !---------------------------! 189 CALL iom_open( clfile(igrd), inum ) 190 CALL iom_gettime( inum, zstepr, kntime=ntimes_bdy, cdunits=clunits ) 191 192 SELECT CASE( igrd ) 193 CASE (1) ; numbdyt = inum 194 CASE (2) ; numbdyu = inum 195 CASE (3) ; numbdyv = inum 196 END SELECT 197 198 ! Calculate time offset 199 READ(clunits,7000) iyear0, imonth0, iday0, ihours0, iminutes0, isec0 200 ! Convert time origin in file to julian days 201 isec0 = isec0 + ihours0*60.*60. + iminutes0*60. 202 CALL ymds2ju(iyear0, imonth0, iday0, REAL(isec0, wp), dayjul0) 203 ! Compute model initialization time 204 iyear = ndastp / 10000 205 imonth = ( ndastp - iyear * 10000 ) / 100 206 iday = ndastp - iyear * 10000 - imonth * 100 207 isecs = dayfrac * 86400 208 CALL ymds2ju(iyear, imonth, iday, REAL(isecs, wp) , zdayjulini) 209 ! offset from initialization date: 210 zoffset = (dayjul0-zdayjulini)*86400 211 ! 212 7000 FORMAT('seconds since ', I4.4,'-',I2.2,'-',I2.2,' ',I2.2,':',I2.2,':',I2.2) 213 214 !! TO BE DONE... Check consistency between calendar from file 215 !! (available optionally from iom_gettime) and calendar in model 216 !! when calendar in model available outside of IOIPSL. 217 218 IF(lwp) WRITE(numout,*) 'number of times: ',ntimes_bdy 219 IF(lwp) WRITE(numout,*) 'offset: ',zoffset 220 IF(lwp) WRITE(numout,*) 'totime: ',totime 221 IF(lwp) WRITE(numout,*) 'zstepr: ',zstepr(1:ntimes_bdy) 222 223 ! Check that there are not too many times in the file. 224 IF( ntimes_bdy > jpbtime ) THEN 225 WRITE(ctmp1,*) 'Check file: ', clfile(igrd), 'jpbtime= ', jpbtime, ' ntimes_bdy= ', ntimes_bdy 226 CALL ctl_stop( 'Number of time dumps in files exceed jpbtime parameter', ctmp1 ) 227 ENDIF 228 229 ! Check that time array increases: 230 it = 1 231 DO WHILE( zstepr(it+1) > zstepr(it) .AND. it /= ntimes_bdy - 1 ) 232 it = it + 1 233 END DO 234 ! 235 IF( it /= ntimes_bdy-1 .AND. ntimes_bdy > 1 ) THEN 236 WRITE(ctmp1,*) 'Check file: ', clfile(igrd) 237 CALL ctl_stop( 'Time array in unstructured boundary data files', & 238 & 'does not continuously increase.' , ctmp1 ) 239 ENDIF 240 ! 241 ! Check that times in file span model run time: 242 IF( zstepr(1) + zoffset > 0 ) THEN 243 WRITE(ctmp1,*) 'Check file: ', clfile(igrd) 244 CALL ctl_stop( 'First time dump in bdy file is after model initial time', ctmp1 ) 245 END IF 246 IF( zstepr(ntimes_bdy) + zoffset < totime ) THEN 247 WRITE(ctmp1,*) 'Check file: ', clfile(igrd) 248 CALL ctl_stop( 'Last time dump in bdy file is before model final time', ctmp1 ) 249 END IF 250 ! 251 SELECT CASE( igrd ) 252 CASE (1) 253 ntimes_bdyt = ntimes_bdy 254 zoffsett = zoffset 255 istept(:) = INT( zstepr(:) + zoffset ) 256 numbdyt = inum 257 CASE (2) 258 ntimes_bdyu = ntimes_bdy 259 zoffsetu = zoffset 260 istepu(:) = INT( zstepr(:) + zoffset ) 261 numbdyu = inum 262 CASE (3) 263 ntimes_bdyv = ntimes_bdy 264 zoffsetv = zoffset 265 istepv(:) = INT( zstepr(:) + zoffset ) 266 numbdyv = inum 267 END SELECT 268 ! 269 END DO ! end loop over T, U & V grid 270 271 IF (igrd_start == 1 .and. igrd_end == 3) THEN 272 ! Only test differences if we are reading in 3 files 273 ! Verify time consistency between files 274 IF( ntimes_bdyu /= ntimes_bdyt .OR. ntimes_bdyv /= ntimes_bdyt ) THEN 275 CALL ctl_stop( 'Bdy data files must have the same number of time dumps', & 276 & 'Multiple time frequencies not implemented yet' ) 277 ENDIF 278 ntimes_bdy = ntimes_bdyt 279 ! 280 IF( zoffsetu /= zoffsett .OR. zoffsetv /= zoffsett ) THEN 281 CALL ctl_stop( 'Bdy data files must have the same time origin', & 282 & 'Multiple time frequencies not implemented yet' ) 283 ENDIF 284 zoffset = zoffsett 285 ENDIF 286 287 IF( igrd_start == 1 ) THEN ; istep(:) = istept(:) 288 ELSE ; istep(:) = istepu(:) 289 ENDIF 290 291 ! Check number of time dumps: 292 IF( ntimes_bdy == 1 .AND. .NOT. ln_clim ) THEN 293 CALL ctl_stop( 'There is only one time dump in data files', & 294 & 'Choose ln_clim=.true. in namelist for constant bdy forcing.' ) 295 ENDIF 296 297 IF( ln_clim ) THEN 298 IF( ntimes_bdy /= 1 .AND. ntimes_bdy /= 12 ) THEN 299 CALL ctl_stop( 'For climatological boundary forcing (ln_clim=.true.),', & 300 & 'bdy data files must contain 1 or 12 time dumps.' ) 301 ELSEIF( ntimes_bdy == 1 ) THEN 302 IF(lwp) WRITE(numout,*) 303 IF(lwp) WRITE(numout,*) 'We assume constant boundary forcing from bdy data files' 304 ELSEIF( ntimes_bdy == 12 ) THEN 305 IF(lwp) WRITE(numout,*) 306 IF(lwp) WRITE(numout,*) 'We assume monthly (and cyclic) boundary forcing from bdy data files' 307 ENDIF 308 ENDIF 309 310 ! Find index of first record to read (before first model time). 311 it = 1 312 DO WHILE( istep(it+1) <= 0 .AND. it <= ntimes_bdy - 1 ) 313 it = it + 1 314 END DO 315 nbdy_b = it 316 ! 317 IF(lwp) WRITE(numout,*) 'Time offset is ',zoffset 318 IF(lwp) WRITE(numout,*) 'First record to read is ',nbdy_b 319 320 ENDIF ! endif (nn_dtactl == 1) 321 322 323 ! 1.2 Read first record in file if necessary (ie if nn_dtactl == 1) 324 ! ***************************************************************** 325 326 IF( nn_dtactl == 0 ) THEN ! boundary data arrays are filled with initial conditions 327 ! 328 IF (ln_tra_frs) THEN 329 igrd = 1 ! T-points data 330 DO ib = 1, nblen(igrd) 331 ii = nbi(ib,igrd) 332 ij = nbj(ib,igrd) 83 !! 84 IF( nn_timing == 1 ) CALL timing_start('bdy_dta') 85 86 ! Initialise data arrays once for all from initial conditions where required 87 !--------------------------------------------------------------------------- 88 IF( kt .eq. nit000 .and. .not. PRESENT(jit) ) THEN 89 90 ! Calculate depth-mean currents 91 !----------------------------- 92 CALL wrk_alloc(jpi,jpj,pu2d,pv2d) 93 94 pu2d(:,:) = 0.e0 95 pv2d(:,:) = 0.e0 96 97 DO ik = 1, jpkm1 !! Vertically integrated momentum trends 98 pu2d(:,:) = pu2d(:,:) + fse3u(:,:,ik) * umask(:,:,ik) * un(:,:,ik) 99 pv2d(:,:) = pv2d(:,:) + fse3v(:,:,ik) * vmask(:,:,ik) * vn(:,:,ik) 100 END DO 101 pu2d(:,:) = pu2d(:,:) * hur(:,:) 102 pv2d(:,:) = pv2d(:,:) * hvr(:,:) 103 104 DO ib_bdy = 1, nb_bdy 105 106 nblen => idx_bdy(ib_bdy)%nblen 107 nblenrim => idx_bdy(ib_bdy)%nblenrim 108 109 IF( nn_dyn2d(ib_bdy) .gt. 0 .and. nn_dyn2d_dta(ib_bdy) .eq. 0 ) THEN 110 IF( nn_dyn2d(ib_bdy) .eq. jp_frs ) THEN 111 ilen1(:) = nblen(:) 112 ELSE 113 ilen1(:) = nblenrim(:) 114 ENDIF 115 igrd = 1 116 DO ib = 1, ilen1(igrd) 117 ii = idx_bdy(ib_bdy)%nbi(ib,igrd) 118 ij = idx_bdy(ib_bdy)%nbj(ib,igrd) 119 dta_bdy(ib_bdy)%ssh(ib) = sshn(ii,ij) * tmask(ii,ij,1) 120 END DO 121 igrd = 2 122 DO ib = 1, ilen1(igrd) 123 ii = idx_bdy(ib_bdy)%nbi(ib,igrd) 124 ij = idx_bdy(ib_bdy)%nbj(ib,igrd) 125 dta_bdy(ib_bdy)%u2d(ib) = pu2d(ii,ij) * umask(ii,ij,1) 126 END DO 127 igrd = 3 128 DO ib = 1, ilen1(igrd) 129 ii = idx_bdy(ib_bdy)%nbi(ib,igrd) 130 ij = idx_bdy(ib_bdy)%nbj(ib,igrd) 131 dta_bdy(ib_bdy)%v2d(ib) = pv2d(ii,ij) * vmask(ii,ij,1) 132 END DO 133 ENDIF 134 135 IF( nn_dyn3d(ib_bdy) .gt. 0 .and. nn_dyn3d_dta(ib_bdy) .eq. 0 ) THEN 136 IF( nn_dyn3d(ib_bdy) .eq. jp_frs ) THEN 137 ilen1(:) = nblen(:) 138 ELSE 139 ilen1(:) = nblenrim(:) 140 ENDIF 141 igrd = 2 142 DO ib = 1, ilen1(igrd) 333 143 DO ik = 1, jpkm1 334 tbdy(ib,ik) = tn(ii,ij,ik) 335 sbdy(ib,ik) = sn(ii,ij,ik) 144 ii = idx_bdy(ib_bdy)%nbi(ib,igrd) 145 ij = idx_bdy(ib_bdy)%nbj(ib,igrd) 146 dta_bdy(ib_bdy)%u3d(ib,ik) = ( un(ii,ij,ik) - pu2d(ii,ij) ) * umask(ii,ij,ik) 147 END DO 148 END DO 149 igrd = 3 150 DO ib = 1, ilen1(igrd) 151 DO ik = 1, jpkm1 152 ii = idx_bdy(ib_bdy)%nbi(ib,igrd) 153 ij = idx_bdy(ib_bdy)%nbj(ib,igrd) 154 dta_bdy(ib_bdy)%v3d(ib,ik) = ( vn(ii,ij,ik) - pv2d(ii,ij) ) * vmask(ii,ij,ik) 155 END DO 156 END DO 157 ENDIF 158 159 IF( nn_tra(ib_bdy) .gt. 0 .and. nn_tra_dta(ib_bdy) .eq. 0 ) THEN 160 IF( nn_tra(ib_bdy) .eq. jp_frs ) THEN 161 ilen1(:) = nblen(:) 162 ELSE 163 ilen1(:) = nblenrim(:) 164 ENDIF 165 igrd = 1 ! Everything is at T-points here 166 DO ib = 1, ilen1(igrd) 167 DO ik = 1, jpkm1 168 ii = idx_bdy(ib_bdy)%nbi(ib,igrd) 169 ij = idx_bdy(ib_bdy)%nbj(ib,igrd) 170 dta_bdy(ib_bdy)%tem(ib,ik) = tsn(ii,ij,ik,jp_tem) * tmask(ii,ij,ik) 171 dta_bdy(ib_bdy)%sal(ib,ik) = tsn(ii,ij,ik,jp_sal) * tmask(ii,ij,ik) 172 END DO 173 END DO 174 ENDIF 175 176 #if defined key_lim2 177 IF( nn_ice_lim2(ib_bdy) .gt. 0 .and. nn_ice_lim2_dta(ib_bdy) .eq. 0 ) THEN 178 IF( nn_ice_lim2(ib_bdy) .eq. jp_frs ) THEN 179 ilen1(:) = nblen(:) 180 ELSE 181 ilen1(:) = nblenrim(:) 182 ENDIF 183 igrd = 1 ! Everything is at T-points here 184 DO ib = 1, ilen1(igrd) 185 ii = idx_bdy(ib_bdy)%nbi(ib,igrd) 186 ij = idx_bdy(ib_bdy)%nbj(ib,igrd) 187 dta_bdy(ib_bdy)%frld(ib) = frld(ii,ij) * tmask(ii,ij,1) 188 dta_bdy(ib_bdy)%hicif(ib) = hicif(ii,ij) * tmask(ii,ij,1) 189 dta_bdy(ib_bdy)%hsnif(ib) = hsnif(ii,ij) * tmask(ii,ij,1) 190 END DO 191 ENDIF 192 #endif 193 194 ENDDO ! ib_bdy 195 196 CALL wrk_dealloc(jpi,jpj,pu2d,pv2d) 197 198 ENDIF ! kt .eq. nit000 199 200 ! update external data from files 201 !-------------------------------- 202 203 jstart = 1 204 DO ib_bdy = 1, nb_bdy 205 IF( nn_dta(ib_bdy) .eq. 1 ) THEN ! skip this bit if no external data required 206 207 IF( PRESENT(jit) ) THEN 208 ! Update barotropic boundary conditions only 209 ! jit is optional argument for fld_read and tide_update 210 IF( nn_dyn2d(ib_bdy) .gt. 0 ) THEN 211 IF( nn_dyn2d_dta(ib_bdy) .eq. 2 ) THEN ! tidal harmonic forcing ONLY: initialise arrays 212 dta_bdy(ib_bdy)%ssh(:) = 0.0 213 dta_bdy(ib_bdy)%u2d(:) = 0.0 214 dta_bdy(ib_bdy)%v2d(:) = 0.0 215 ENDIF 216 IF( nn_dyn2d_dta(ib_bdy) .eq. 1 .or. nn_dyn2d_dta(ib_bdy) .eq. 3 ) THEN ! update external data 217 jend = jstart + 2 218 CALL fld_read( kt=kt, kn_fsbc=1, sd=bf(jstart:jend), map=nbmap_ptr(jstart:jend), & 219 & jit=jit, time_offset=time_offset ) 220 ENDIF 221 IF( nn_dyn2d_dta(ib_bdy) .ge. 2 ) THEN ! update tidal harmonic forcing 222 CALL tide_update( kt=kt, idx=idx_bdy(ib_bdy), dta=dta_bdy(ib_bdy), td=tides(ib_bdy), & 223 & jit=jit, time_offset=time_offset ) 224 ENDIF 225 ENDIF 226 ELSE 227 IF( nn_dyn2d(ib_bdy) .gt. 0 .and. nn_dyn2d_dta(ib_bdy) .eq. 2 ) THEN ! tidal harmonic forcing ONLY: initialise arrays 228 dta_bdy(ib_bdy)%ssh(:) = 0.0 229 dta_bdy(ib_bdy)%u2d(:) = 0.0 230 dta_bdy(ib_bdy)%v2d(:) = 0.0 231 ENDIF 232 IF( nb_bdy_fld(ib_bdy) .gt. 0 ) THEN ! update external data 233 jend = jstart + nb_bdy_fld(ib_bdy) - 1 234 CALL fld_read( kt=kt, kn_fsbc=1, sd=bf(jstart:jend), map=nbmap_ptr(jstart:jend), time_offset=time_offset ) 235 ENDIF 236 IF( nn_dyn2d(ib_bdy) .gt. 0 .and. nn_dyn2d_dta(ib_bdy) .ge. 2 ) THEN ! update tidal harmonic forcing 237 CALL tide_update( kt=kt, idx=idx_bdy(ib_bdy), dta=dta_bdy(ib_bdy), td=tides(ib_bdy), time_offset=time_offset ) 238 ENDIF 239 ENDIF 240 jstart = jend+1 241 242 ! If full velocities in boundary data then split into barotropic and baroclinic data 243 ! (Note that we have already made sure that you can't use ln_full_vel = .true. at the same 244 ! time as the dynspg_ts option). 245 246 IF( ln_full_vel_array(ib_bdy) .and. & 247 & ( nn_dyn2d_dta(ib_bdy) .eq. 1 .or. nn_dyn2d_dta(ib_bdy) .eq. 3 .or. nn_dyn3d_dta(ib_bdy) .eq. 1 ) ) THEN 248 249 igrd = 2 ! zonal velocity 250 dta_bdy(ib_bdy)%u2d(:) = 0.0 251 DO ib = 1, idx_bdy(ib_bdy)%nblen(igrd) 252 ii = idx_bdy(ib_bdy)%nbi(ib,igrd) 253 ij = idx_bdy(ib_bdy)%nbj(ib,igrd) 254 DO ik = 1, jpkm1 255 dta_bdy(ib_bdy)%u2d(ib) = dta_bdy(ib_bdy)%u2d(ib) & 256 & + fse3u(ii,ij,ik) * umask(ii,ij,ik) * dta_bdy(ib_bdy)%u3d(ib,ik) 257 END DO 258 dta_bdy(ib_bdy)%u2d(ib) = dta_bdy(ib_bdy)%u2d(ib) * hur(ii,ij) 259 DO ik = 1, jpkm1 260 dta_bdy(ib_bdy)%u3d(ib,ik) = dta_bdy(ib_bdy)%u3d(ib,ik) - dta_bdy(ib_bdy)%u2d(ib) 336 261 END DO 337 262 END DO 338 ENDIF 339 340 IF(ln_dyn_frs) THEN 341 igrd = 2 ! U-points data 342 DO ib = 1, nblen(igrd) 343 ii = nbi(ib,igrd) 344 ij = nbj(ib,igrd) 263 264 igrd = 3 ! meridional velocity 265 dta_bdy(ib_bdy)%v2d(:) = 0.0 266 DO ib = 1, idx_bdy(ib_bdy)%nblen(igrd) 267 ii = idx_bdy(ib_bdy)%nbi(ib,igrd) 268 ij = idx_bdy(ib_bdy)%nbj(ib,igrd) 345 269 DO ik = 1, jpkm1 346 ubdy(ib,ik) = un(ii, ij, ik) 270 dta_bdy(ib_bdy)%v2d(ib) = dta_bdy(ib_bdy)%v2d(ib) & 271 & + fse3v(ii,ij,ik) * vmask(ii,ij,ik) * dta_bdy(ib_bdy)%v3d(ib,ik) 272 END DO 273 dta_bdy(ib_bdy)%v2d(ib) = dta_bdy(ib_bdy)%v2d(ib) * hvr(ii,ij) 274 DO ik = 1, jpkm1 275 dta_bdy(ib_bdy)%v3d(ib,ik) = dta_bdy(ib_bdy)%v3d(ib,ik) - dta_bdy(ib_bdy)%v2d(ib) 347 276 END DO 348 277 END DO 349 ! 350 igrd = 3 ! V-points data 351 DO ib = 1, nblen(igrd) 352 ii = nbi(ib,igrd) 353 ij = nbj(ib,igrd) 354 DO ik = 1, jpkm1 355 vbdy(ib,ik) = vn(ii, ij, ik) 356 END DO 357 END DO 358 ENDIF 359 ! 360 #if defined key_lim2 361 IF( ln_ice_frs ) THEN 362 igrd = 1 ! T-points data 363 DO ib = 1, nblen(igrd) 364 frld_bdy (ib) = frld(nbi(ib,igrd), nbj(ib,igrd)) 365 hicif_bdy(ib) = hicif(nbi(ib,igrd), nbj(ib,igrd)) 366 hsnif_bdy(ib) = hsnif(nbi(ib,igrd), nbj(ib,igrd)) 367 END DO 368 ENDIF 369 #endif 370 ELSEIF( nn_dtactl == 1 ) THEN ! Set first record in the climatological case: 371 ! 372 IF( ln_clim .AND. ntimes_bdy == 1 ) THEN 373 nbdy_a = 1 374 ELSEIF( ln_clim .AND. ntimes_bdy == iman ) THEN 375 nbdy_b = 0 376 nbdy_a = imois 278 279 ENDIF 280 281 END IF ! nn_dta(ib_bdy) = 1 282 END DO ! ib_bdy 283 284 IF( nn_timing == 1 ) CALL timing_stop('bdy_dta') 285 286 END SUBROUTINE bdy_dta 287 288 289 SUBROUTINE bdy_dta_init 290 !!---------------------------------------------------------------------- 291 !! *** SUBROUTINE bdy_dta_init *** 292 !! 293 !! ** Purpose : Initialise arrays for reading of external data 294 !! for open boundary conditions 295 !! 296 !! ** Method : Use fldread.F90 297 !! 298 !!---------------------------------------------------------------------- 299 USE dynspg_oce, ONLY: lk_dynspg_ts 300 !! 301 INTEGER :: ib_bdy, jfld, jstart, jend, ierror ! local indices 302 !! 303 CHARACTER(len=100) :: cn_dir ! Root directory for location of data files 304 CHARACTER(len=100), DIMENSION(nb_bdy) :: cn_dir_array ! Root directory for location of data files 305 LOGICAL :: ln_full_vel ! =T => full velocities in 3D boundary data 306 ! =F => baroclinic velocities in 3D boundary data 307 INTEGER :: ilen_global ! Max length required for global bdy dta arrays 308 INTEGER, DIMENSION(jpbgrd) :: ilen0 ! size of local arrays 309 INTEGER, ALLOCATABLE, DIMENSION(:) :: ilen1, ilen3 ! size of 1st and 3rd dimensions of local arrays 310 INTEGER, ALLOCATABLE, DIMENSION(:) :: ibdy ! bdy set for a particular jfld 311 INTEGER, ALLOCATABLE, DIMENSION(:) :: igrid ! index for grid type (1,2,3 = T,U,V) 312 INTEGER, POINTER, DIMENSION(:) :: nblen, nblenrim ! short cuts 313 TYPE(FLD_N), ALLOCATABLE, DIMENSION(:) :: blf_i ! array of namelist information structures 314 TYPE(FLD_N) :: bn_tem, bn_sal, bn_u3d, bn_v3d ! 315 TYPE(FLD_N) :: bn_ssh, bn_u2d, bn_v2d ! informations about the fields to be read 316 #if defined key_lim2 317 TYPE(FLD_N) :: bn_frld, bn_hicif, bn_hsnif ! 318 #endif 319 NAMELIST/nambdy_dta/ cn_dir, bn_tem, bn_sal, bn_u3d, bn_v3d, bn_ssh, bn_u2d, bn_v2d 320 #if defined key_lim2 321 NAMELIST/nambdy_dta/ bn_frld, bn_hicif, bn_hsnif 322 #endif 323 NAMELIST/nambdy_dta/ ln_full_vel 324 !!--------------------------------------------------------------------------- 325 326 IF( nn_timing == 1 ) CALL timing_start('bdy_dta_init') 327 328 ! Set nn_dta 329 DO ib_bdy = 1, nb_bdy 330 nn_dta(ib_bdy) = MAX( nn_dyn2d_dta(ib_bdy) & 331 ,nn_dyn3d_dta(ib_bdy) & 332 ,nn_tra_dta(ib_bdy) & 333 #if defined key_lim2 334 ,nn_ice_lim2_dta(ib_bdy) & 335 #endif 336 ) 337 IF(nn_dta(ib_bdy) .gt. 1) nn_dta(ib_bdy) = 1 338 END DO 339 340 ! Work out upper bound of how many fields there are to read in and allocate arrays 341 ! --------------------------------------------------------------------------- 342 ALLOCATE( nb_bdy_fld(nb_bdy) ) 343 nb_bdy_fld(:) = 0 344 DO ib_bdy = 1, nb_bdy 345 IF( nn_dyn2d(ib_bdy) .gt. 0 .and. ( nn_dyn2d_dta(ib_bdy) .eq. 1 .or. nn_dyn2d_dta(ib_bdy) .eq. 3 ) ) THEN 346 nb_bdy_fld(ib_bdy) = nb_bdy_fld(ib_bdy) + 3 347 ENDIF 348 IF( nn_dyn3d(ib_bdy) .gt. 0 .and. nn_dyn3d_dta(ib_bdy) .eq. 1 ) THEN 349 nb_bdy_fld(ib_bdy) = nb_bdy_fld(ib_bdy) + 2 350 ENDIF 351 IF( nn_tra(ib_bdy) .gt. 0 .and. nn_tra_dta(ib_bdy) .eq. 1 ) THEN 352 nb_bdy_fld(ib_bdy) = nb_bdy_fld(ib_bdy) + 2 353 ENDIF 354 #if defined key_lim2 355 IF( nn_ice_lim2(ib_bdy) .gt. 0 .and. nn_ice_lim2_dta(ib_bdy) .eq. 1 ) THEN 356 nb_bdy_fld(ib_bdy) = nb_bdy_fld(ib_bdy) + 3 357 ENDIF 358 #endif 359 ENDDO 360 361 nb_bdy_fld_sum = SUM( nb_bdy_fld ) 362 363 ALLOCATE( bf(nb_bdy_fld_sum), STAT=ierror ) 364 IF( ierror > 0 ) THEN 365 CALL ctl_stop( 'bdy_dta: unable to allocate bf structure' ) ; RETURN 366 ENDIF 367 ALLOCATE( blf_i(nb_bdy_fld_sum), STAT=ierror ) 368 IF( ierror > 0 ) THEN 369 CALL ctl_stop( 'bdy_dta: unable to allocate blf_i structure' ) ; RETURN 370 ENDIF 371 ALLOCATE( nbmap_ptr(nb_bdy_fld_sum), STAT=ierror ) 372 IF( ierror > 0 ) THEN 373 CALL ctl_stop( 'bdy_dta: unable to allocate nbmap_ptr structure' ) ; RETURN 374 ENDIF 375 ALLOCATE( ilen1(nb_bdy_fld_sum), ilen3(nb_bdy_fld_sum) ) 376 ALLOCATE( ibdy(nb_bdy_fld_sum) ) 377 ALLOCATE( igrid(nb_bdy_fld_sum) ) 378 379 ! Read namelists 380 ! -------------- 381 REWIND(numnam) 382 jfld = 0 383 DO ib_bdy = 1, nb_bdy 384 IF( nn_dta(ib_bdy) .eq. 1 ) THEN 385 ! set file information 386 cn_dir = './' ! directory in which the model is executed 387 ln_full_vel = .false. 388 ! ... default values (NB: frequency positive => hours, negative => months) 389 ! ! file ! frequency ! variable ! time intep ! clim ! 'yearly' or ! weights ! rotation ! 390 ! ! name ! hours ! name ! (T/F) ! (T/F) ! 'monthly' ! filename ! pairs ! 391 bn_ssh = FLD_N( 'bdy_ssh' , 24 , 'sossheig' , .false. , .false. , 'yearly' , '' , '' ) 392 bn_u2d = FLD_N( 'bdy_vel2d_u' , 24 , 'vobtcrtx' , .false. , .false. , 'yearly' , '' , '' ) 393 bn_v2d = FLD_N( 'bdy_vel2d_v' , 24 , 'vobtcrty' , .false. , .false. , 'yearly' , '' , '' ) 394 bn_u3d = FLD_N( 'bdy_vel3d_u' , 24 , 'vozocrtx' , .false. , .false. , 'yearly' , '' , '' ) 395 bn_v3d = FLD_N( 'bdy_vel3d_v' , 24 , 'vomecrty' , .false. , .false. , 'yearly' , '' , '' ) 396 bn_tem = FLD_N( 'bdy_tem' , 24 , 'votemper' , .false. , .false. , 'yearly' , '' , '' ) 397 bn_sal = FLD_N( 'bdy_sal' , 24 , 'vosaline' , .false. , .false. , 'yearly' , '' , '' ) 398 #if defined key_lim2 399 bn_frld = FLD_N( 'bdy_frld' , 24 , 'ildsconc' , .false. , .false. , 'yearly' , '' , '' ) 400 bn_hicif = FLD_N( 'bdy_hicif' , 24 , 'iicethic' , .false. , .false. , 'yearly' , '' , '' ) 401 bn_hsnif = FLD_N( 'bdy_hsnif' , 24 , 'isnothic' , .false. , .false. , 'yearly' , '' , '' ) 402 #endif 403 404 ! Important NOT to rewind here. 405 READ( numnam, nambdy_dta ) 406 407 cn_dir_array(ib_bdy) = cn_dir 408 ln_full_vel_array(ib_bdy) = ln_full_vel 409 410 IF( ln_full_vel_array(ib_bdy) .and. lk_dynspg_ts ) THEN 411 CALL ctl_stop( 'bdy_dta_init: ERROR, cannot specify full velocities in boundary data',& 412 & 'with dynspg_ts option' ) ; RETURN 413 ENDIF 414 415 nblen => idx_bdy(ib_bdy)%nblen 416 nblenrim => idx_bdy(ib_bdy)%nblenrim 417 418 ! Only read in necessary fields for this set. 419 ! Important that barotropic variables come first. 420 IF( nn_dyn2d(ib_bdy) .gt. 0 .and. ( nn_dyn2d_dta(ib_bdy) .eq. 1 .or. nn_dyn2d_dta(ib_bdy) .eq. 3 ) ) THEN 421 422 IF( nn_dyn2d(ib_bdy) .ne. jp_frs ) THEN 423 jfld = jfld + 1 424 blf_i(jfld) = bn_ssh 425 ibdy(jfld) = ib_bdy 426 igrid(jfld) = 1 427 ilen1(jfld) = nblenrim(igrid(jfld)) 428 ilen3(jfld) = 1 429 ENDIF 430 431 IF( .not. ln_full_vel_array(ib_bdy) ) THEN 432 433 jfld = jfld + 1 434 blf_i(jfld) = bn_u2d 435 ibdy(jfld) = ib_bdy 436 igrid(jfld) = 2 437 IF( nn_dyn2d(ib_bdy) .eq. jp_frs ) THEN 438 ilen1(jfld) = nblen(igrid(jfld)) 439 ELSE 440 ilen1(jfld) = nblenrim(igrid(jfld)) 441 ENDIF 442 ilen3(jfld) = 1 443 444 jfld = jfld + 1 445 blf_i(jfld) = bn_v2d 446 ibdy(jfld) = ib_bdy 447 igrid(jfld) = 3 448 IF( nn_dyn2d(ib_bdy) .eq. jp_frs ) THEN 449 ilen1(jfld) = nblen(igrid(jfld)) 450 ELSE 451 ilen1(jfld) = nblenrim(igrid(jfld)) 452 ENDIF 453 ilen3(jfld) = 1 454 455 ENDIF 456 457 ENDIF 458 459 ! baroclinic velocities 460 IF( ( nn_dyn3d(ib_bdy) .gt. 0 .and. nn_dyn3d_dta(ib_bdy) .eq. 1 ) .or. & 461 & ( ln_full_vel_array(ib_bdy) .and. nn_dyn2d(ib_bdy) .gt. 0 .and. & 462 & ( nn_dyn2d_dta(ib_bdy) .eq. 1 .or. nn_dyn2d_dta(ib_bdy) .eq. 3 ) ) ) THEN 463 464 jfld = jfld + 1 465 blf_i(jfld) = bn_u3d 466 ibdy(jfld) = ib_bdy 467 igrid(jfld) = 2 468 IF( nn_dyn3d(ib_bdy) .eq. jp_frs ) THEN 469 ilen1(jfld) = nblen(igrid(jfld)) 470 ELSE 471 ilen1(jfld) = nblenrim(igrid(jfld)) 472 ENDIF 473 ilen3(jfld) = jpk 474 475 jfld = jfld + 1 476 blf_i(jfld) = bn_v3d 477 ibdy(jfld) = ib_bdy 478 igrid(jfld) = 3 479 IF( nn_dyn3d(ib_bdy) .eq. jp_frs ) THEN 480 ilen1(jfld) = nblen(igrid(jfld)) 481 ELSE 482 ilen1(jfld) = nblenrim(igrid(jfld)) 483 ENDIF 484 ilen3(jfld) = jpk 485 486 ENDIF 487 488 ! temperature and salinity 489 IF( nn_tra(ib_bdy) .gt. 0 .and. nn_tra_dta(ib_bdy) .eq. 1 ) THEN 490 491 jfld = jfld + 1 492 blf_i(jfld) = bn_tem 493 ibdy(jfld) = ib_bdy 494 igrid(jfld) = 1 495 IF( nn_tra(ib_bdy) .eq. jp_frs ) THEN 496 ilen1(jfld) = nblen(igrid(jfld)) 497 ELSE 498 ilen1(jfld) = nblenrim(igrid(jfld)) 499 ENDIF 500 ilen3(jfld) = jpk 501 502 jfld = jfld + 1 503 blf_i(jfld) = bn_sal 504 ibdy(jfld) = ib_bdy 505 igrid(jfld) = 1 506 IF( nn_tra(ib_bdy) .eq. jp_frs ) THEN 507 ilen1(jfld) = nblen(igrid(jfld)) 508 ELSE 509 ilen1(jfld) = nblenrim(igrid(jfld)) 510 ENDIF 511 ilen3(jfld) = jpk 512 513 ENDIF 514 515 #if defined key_lim2 516 ! sea ice 517 IF( nn_ice_lim2(ib_bdy) .gt. 0 .and. nn_ice_lim2_dta(ib_bdy) .eq. 1 ) THEN 518 519 jfld = jfld + 1 520 blf_i(jfld) = bn_frld 521 ibdy(jfld) = ib_bdy 522 igrid(jfld) = 1 523 IF( nn_ice_lim2(ib_bdy) .eq. jp_frs ) THEN 524 ilen1(jfld) = nblen(igrid(jfld)) 525 ELSE 526 ilen1(jfld) = nblenrim(igrid(jfld)) 527 ENDIF 528 ilen3(jfld) = 1 529 530 jfld = jfld + 1 531 blf_i(jfld) = bn_hicif 532 ibdy(jfld) = ib_bdy 533 igrid(jfld) = 1 534 IF( nn_ice_lim2(ib_bdy) .eq. jp_frs ) THEN 535 ilen1(jfld) = nblen(igrid(jfld)) 536 ELSE 537 ilen1(jfld) = nblenrim(igrid(jfld)) 538 ENDIF 539 ilen3(jfld) = 1 540 541 jfld = jfld + 1 542 blf_i(jfld) = bn_hsnif 543 ibdy(jfld) = ib_bdy 544 igrid(jfld) = 1 545 IF( nn_ice_lim2(ib_bdy) .eq. jp_frs ) THEN 546 ilen1(jfld) = nblen(igrid(jfld)) 547 ELSE 548 ilen1(jfld) = nblenrim(igrid(jfld)) 549 ENDIF 550 ilen3(jfld) = 1 551 552 ENDIF 553 #endif 554 ! Recalculate field counts 555 !------------------------- 556 nb_bdy_fld_sum = 0 557 IF( ib_bdy .eq. 1 ) THEN 558 nb_bdy_fld(ib_bdy) = jfld 559 nb_bdy_fld_sum = jfld 377 560 ELSE 378 nbdy_a = nbdy_b 379 ENDIF 380 381 ! Read first record: 382 ipj = 1 383 ipk = jpk 384 igrd = 1 385 ipi = nblendta(igrd) 386 387 IF(ln_tra_frs) THEN 388 ! 389 igrd = 1 ! Temperature 390 IF( nblendta(igrd) <= 0 ) THEN 391 idvar = iom_varid( numbdyt, 'votemper' ) 392 nblendta(igrd) = iom_file(numbdyt)%dimsz(1,idvar) 393 ENDIF 394 IF(lwp) WRITE(numout,*) 'Dim size for votemper is ', nblendta(igrd) 395 ipi = nblendta(igrd) 396 CALL iom_get ( numbdyt, jpdom_unknown, 'votemper', zdta(1:ipi,1:ipj,1:ipk), nbdy_a ) 397 ! 398 DO ib = 1, nblen(igrd) 399 DO ik = 1, jpkm1 400 tbdydta(ib,ik,2) = zdta(nbmap(ib,igrd),1,ik) 401 END DO 402 END DO 403 ! 404 igrd = 1 ! salinity 405 IF( nblendta(igrd) .le. 0 ) THEN 406 idvar = iom_varid( numbdyt, 'vosaline' ) 407 nblendta(igrd) = iom_file(numbdyt)%dimsz(1,idvar) 408 ENDIF 409 IF(lwp) WRITE(numout,*) 'Dim size for vosaline is ', nblendta(igrd) 410 ipi = nblendta(igrd) 411 CALL iom_get ( numbdyt, jpdom_unknown, 'vosaline', zdta(1:ipi,1:ipj,1:ipk), nbdy_a ) 412 ! 413 DO ib = 1, nblen(igrd) 414 DO ik = 1, jpkm1 415 sbdydta(ib,ik,2) = zdta(nbmap(ib,igrd),1,ik) 416 END DO 417 END DO 418 ENDIF ! ln_tra_frs 419 420 IF( ln_dyn_frs ) THEN 421 ! 422 igrd = 2 ! u-velocity 423 IF ( nblendta(igrd) .le. 0 ) THEN 424 idvar = iom_varid( numbdyu,'vozocrtx' ) 425 nblendta(igrd) = iom_file(numbdyu)%dimsz(1,idvar) 426 ENDIF 427 IF(lwp) WRITE(numout,*) 'Dim size for vozocrtx is ', nblendta(igrd) 428 ipi = nblendta(igrd) 429 CALL iom_get ( numbdyu, jpdom_unknown,'vozocrtx',zdta(1:ipi,1:ipj,1:ipk),nbdy_a ) 430 DO ib = 1, nblen(igrd) 431 DO ik = 1, jpkm1 432 ubdydta(ib,ik,2) = zdta(nbmap(ib,igrd),1,ik) 433 END DO 434 END DO 435 ! 436 igrd = 3 ! v-velocity 437 IF ( nblendta(igrd) .le. 0 ) THEN 438 idvar = iom_varid( numbdyv,'vomecrty' ) 439 nblendta(igrd) = iom_file(numbdyv)%dimsz(1,idvar) 440 ENDIF 441 IF(lwp) WRITE(numout,*) 'Dim size for vomecrty is ', nblendta(igrd) 442 ipi = nblendta(igrd) 443 CALL iom_get ( numbdyv, jpdom_unknown,'vomecrty',zdta(1:ipi,1:ipj,1:ipk),nbdy_a ) 444 DO ib = 1, nblen(igrd) 445 DO ik = 1, jpkm1 446 vbdydta(ib,ik,2) = zdta(nbmap(ib,igrd),1,ik) 447 END DO 448 END DO 449 ENDIF ! ln_dyn_frs 450 451 #if defined key_lim2 452 IF( ln_ice_frs ) THEN 453 ! 454 igrd=1 ! leads fraction 455 IF(lwp) WRITE(numout,*) 'Dim size for ildsconc is ',nblendta(igrd) 456 ipi=nblendta(igrd) 457 CALL iom_get ( numbdyt, jpdom_unknown,'ildsconc',zdta(1:ipi,:,1),nbdy_a ) 458 DO ib=1, nblen(igrd) 459 frld_bdydta(ib,2) = zdta(nbmap(ib,igrd),1,1) 460 END DO 461 ! 462 igrd=1 ! ice thickness 463 IF(lwp) WRITE(numout,*) 'Dim size for iicethic is ',nblendta(igrd) 464 ipi=nblendta(igrd) 465 CALL iom_get ( numbdyt, jpdom_unknown,'iicethic',zdta(1:ipi,:,1),nbdy_a ) 466 DO ib=1, nblen(igrd) 467 hicif_bdydta(ib,2) = zdta(nbmap(ib,igrd),1,1) 468 END DO 469 ! 470 igrd=1 ! snow thickness 471 IF(lwp) WRITE(numout,*) 'Dim size for isnowthi is ',nblendta(igrd) 472 ipi=nblendta(igrd) 473 CALL iom_get ( numbdyt, jpdom_unknown,'isnowthi',zdta(1:ipi,:,1),nbdy_a ) 474 DO ib=1, nblen(igrd) 475 hsnif_bdydta(ib,2) = zdta(nbmap(ib,igrd),1,1) 476 END DO 477 ENDIF ! just if ln_ice_frs is set 478 #endif 479 480 IF( .NOT.ln_clim .AND. istep(1) > 0 ) THEN ! First data time is after start of run 481 nbdy_b = nbdy_a ! Put first value in both time levels 482 IF( ln_tra_frs ) THEN 483 tbdydta(:,:,1) = tbdydta(:,:,2) 484 sbdydta(:,:,1) = sbdydta(:,:,2) 485 ENDIF 486 IF( ln_dyn_frs ) THEN 487 ubdydta(:,:,1) = ubdydta(:,:,2) 488 vbdydta(:,:,1) = vbdydta(:,:,2) 489 ENDIF 490 #if defined key_lim2 491 IF( ln_ice_frs ) THEN 492 frld_bdydta (:,1) = frld_bdydta(:,2) 493 hicif_bdydta(:,1) = hicif_bdydta(:,2) 494 hsnif_bdydta(:,1) = hsnif_bdydta(:,2) 495 ENDIF 496 #endif 497 END IF 498 ! 499 END IF ! nn_dtactl == 0/1 500 501 ! In the case of constant boundary forcing fill bdy arrays once for all 502 IF( ln_clim .AND. ntimes_bdy == 1 ) THEN 503 IF( ln_tra_frs ) THEN 504 tbdy (:,:) = tbdydta (:,:,2) 505 sbdy (:,:) = sbdydta (:,:,2) 506 ENDIF 507 IF( ln_dyn_frs) THEN 508 ubdy (:,:) = ubdydta (:,:,2) 509 vbdy (:,:) = vbdydta (:,:,2) 510 ENDIF 511 #if defined key_lim2 512 IF( ln_ice_frs ) THEN 513 frld_bdy (:) = frld_bdydta (:,2) 514 hicif_bdy(:) = hicif_bdydta(:,2) 515 hsnif_bdy(:) = hsnif_bdydta(:,2) 516 ENDIF 517 #endif 518 519 IF( ln_tra_frs .OR. ln_ice_frs) CALL iom_close( numbdyt ) 520 IF( ln_dyn_frs ) CALL iom_close( numbdyu ) 521 IF( ln_dyn_frs ) CALL iom_close( numbdyv ) 522 END IF 523 ! 524 ENDIF ! End if nit000 525 526 527 ! !---------------------! 528 IF( nn_dtactl == 1 .AND. ntimes_bdy > 1 ) THEN ! at each time step ! 529 ! !---------------------! 530 ! Read one more record if necessary 531 !********************************** 532 533 IF( ln_clim .AND. imois /= nbdy_b ) THEN ! remember that nbdy_b=0 for kt=nit000 534 nbdy_b = imois 535 nbdy_a = imois + 1 536 nbdy_b = MOD( nbdy_b, iman ) ; IF( nbdy_b == 0 ) nbdy_b = iman 537 nbdy_a = MOD( nbdy_a, iman ) ; IF( nbdy_a == 0 ) nbdy_a = iman 538 lect=.true. 539 ELSEIF( .NOT.ln_clim .AND. itimer >= istep(nbdy_a) ) THEN 540 541 IF( nbdy_a < ntimes_bdy ) THEN 542 nbdy_b = nbdy_a 543 nbdy_a = nbdy_a + 1 544 lect =.true. 561 nb_bdy_fld(ib_bdy) = jfld - nb_bdy_fld_sum 562 nb_bdy_fld_sum = nb_bdy_fld_sum + nb_bdy_fld(ib_bdy) 563 ENDIF 564 565 ENDIF ! nn_dta .eq. 1 566 ENDDO ! ib_bdy 567 568 569 DO jfld = 1, nb_bdy_fld_sum 570 ALLOCATE( bf(jfld)%fnow(ilen1(jfld),1,ilen3(jfld)) ) 571 IF( blf_i(jfld)%ln_tint ) ALLOCATE( bf(jfld)%fdta(ilen1(jfld),1,ilen3(jfld),2) ) 572 nbmap_ptr(jfld)%ptr => idx_bdy(ibdy(jfld))%nbmap(:,igrid(jfld)) 573 ENDDO 574 575 ! fill bf with blf_i and control print 576 !------------------------------------- 577 jstart = 1 578 DO ib_bdy = 1, nb_bdy 579 jend = jstart + nb_bdy_fld(ib_bdy) - 1 580 CALL fld_fill( bf(jstart:jend), blf_i(jstart:jend), cn_dir_array(ib_bdy), 'bdy_dta', & 581 & 'open boundary conditions', 'nambdy_dta' ) 582 jstart = jend + 1 583 ENDDO 584 585 ! Initialise local boundary data arrays 586 ! nn_xxx_dta=0 : allocate space - will be filled from initial conditions later 587 ! nn_xxx_dta=1 : point to "fnow" arrays 588 !------------------------------------- 589 590 jfld = 0 591 DO ib_bdy=1, nb_bdy 592 593 nblen => idx_bdy(ib_bdy)%nblen 594 nblenrim => idx_bdy(ib_bdy)%nblenrim 595 596 IF (nn_dyn2d(ib_bdy) .gt. 0) THEN 597 IF( nn_dyn2d_dta(ib_bdy) .eq. 0 .or. nn_dyn2d_dta(ib_bdy) .eq. 2 .or. ln_full_vel_array(ib_bdy) ) THEN 598 IF( nn_dyn2d(ib_bdy) .eq. jp_frs ) THEN 599 ilen0(1:3) = nblen(1:3) 600 ELSE 601 ilen0(1:3) = nblenrim(1:3) 602 ENDIF 603 ALLOCATE( dta_bdy(ib_bdy)%ssh(ilen0(1)) ) 604 ALLOCATE( dta_bdy(ib_bdy)%u2d(ilen0(2)) ) 605 ALLOCATE( dta_bdy(ib_bdy)%v2d(ilen0(3)) ) 545 606 ELSE 546 ! We have reached the end of the file 547 ! put the last data time into both time levels 548 nbdy_b = nbdy_a 549 IF(ln_tra_frs) THEN 550 tbdydta(:,:,1) = tbdydta(:,:,2) 551 sbdydta(:,:,1) = sbdydta(:,:,2) 552 ENDIF 553 IF(ln_dyn_frs) THEN 554 ubdydta(:,:,1) = ubdydta(:,:,2) 555 vbdydta(:,:,1) = vbdydta(:,:,2) 556 ENDIF 557 #if defined key_lim2 558 IF(ln_ice_frs) THEN 559 frld_bdydta (:,1) = frld_bdydta (:,2) 560 hicif_bdydta(:,1) = hicif_bdydta(:,2) 561 hsnif_bdydta(:,1) = hsnif_bdydta(:,2) 562 ENDIF 563 #endif 564 END IF ! nbdy_a < ntimes_bdy 565 ! 566 END IF 567 568 IF( lect ) THEN ! Swap arrays 569 IF( ln_tra_frs ) THEN 570 tbdydta(:,:,1) = tbdydta(:,:,2) 571 sbdydta(:,:,1) = sbdydta(:,:,2) 572 ENDIF 573 IF( ln_dyn_frs ) THEN 574 ubdydta(:,:,1) = ubdydta(:,:,2) 575 vbdydta(:,:,1) = vbdydta(:,:,2) 576 ENDIF 577 #if defined key_lim2 578 IF( ln_ice_frs ) THEN 579 frld_bdydta (:,1) = frld_bdydta (:,2) 580 hicif_bdydta(:,1) = hicif_bdydta(:,2) 581 hsnif_bdydta(:,1) = hsnif_bdydta(:,2) 582 ENDIF 583 #endif 584 ! read another set 585 ipj = 1 586 ipk = jpk 587 588 IF( ln_tra_frs ) THEN 589 ! 590 igrd = 1 ! temperature 591 ipi = nblendta(igrd) 592 CALL iom_get ( numbdyt, jpdom_unknown, 'votemper', zdta(1:ipi,1:ipj,1:ipk), nbdy_a ) 593 DO ib = 1, nblen(igrd) 594 DO ik = 1, jpkm1 595 tbdydta(ib,ik,2) = zdta(nbmap(ib,igrd),1,ik) 596 END DO 597 END DO 598 ! 599 igrd = 1 ! salinity 600 ipi = nblendta(igrd) 601 CALL iom_get ( numbdyt, jpdom_unknown, 'vosaline', zdta(1:ipi,1:ipj,1:ipk), nbdy_a ) 602 DO ib = 1, nblen(igrd) 603 DO ik = 1, jpkm1 604 sbdydta(ib,ik,2) = zdta(nbmap(ib,igrd),1,ik) 605 END DO 606 END DO 607 ENDIF ! ln_tra_frs 608 609 IF(ln_dyn_frs) THEN 610 ! 611 igrd = 2 ! u-velocity 612 ipi = nblendta(igrd) 613 CALL iom_get ( numbdyu, jpdom_unknown,'vozocrtx',zdta(1:ipi,1:ipj,1:ipk),nbdy_a ) 614 DO ib = 1, nblen(igrd) 615 DO ik = 1, jpkm1 616 ubdydta(ib,ik,2) = zdta(nbmap(ib,igrd),1,ik) 617 END DO 618 END DO 619 ! 620 igrd = 3 ! v-velocity 621 ipi = nblendta(igrd) 622 CALL iom_get ( numbdyv, jpdom_unknown,'vomecrty',zdta(1:ipi,1:ipj,1:ipk),nbdy_a ) 623 DO ib = 1, nblen(igrd) 624 DO ik = 1, jpkm1 625 vbdydta(ib,ik,2) = zdta(nbmap(ib,igrd),1,ik) 626 END DO 627 END DO 628 ENDIF ! ln_dyn_frs 629 ! 630 #if defined key_lim2 631 IF(ln_ice_frs) THEN 632 ! 633 igrd = 1 ! ice concentration 634 ipi=nblendta(igrd) 635 CALL iom_get ( numbdyt, jpdom_unknown,'ildsconc',zdta(1:ipi,:,1),nbdy_a ) 636 DO ib=1, nblen(igrd) 637 frld_bdydta(ib,2) = zdta( nbmap(ib,igrd), 1, 1 ) 638 END DO 639 ! 640 igrd=1 ! ice thickness 641 ipi=nblendta(igrd) 642 CALL iom_get ( numbdyt, jpdom_unknown,'iicethic',zdta(1:ipi,:,1),nbdy_a ) 643 DO ib=1, nblen(igrd) 644 hicif_bdydta(ib,2) = zdta( nbmap(ib,igrd), 1, 1 ) 645 END DO 646 ! 647 igrd=1 ! snow thickness 648 ipi=nblendta(igrd) 649 CALL iom_get ( numbdyt, jpdom_unknown,'isnowthi',zdta(1:ipi,:,1),nbdy_a ) 650 DO ib=1, nblen(igrd) 651 hsnif_bdydta(ib,2) = zdta( nbmap(ib,igrd), 1, 1 ) 652 END DO 653 ENDIF ! ln_ice_frs 654 #endif 655 ! 656 IF(lwp) WRITE(numout,*) 'bdy_dta_frs : first record file used nbdy_b ',nbdy_b 657 IF(lwp) WRITE(numout,*) '~~~~~~~~ last record file used nbdy_a ',nbdy_a 658 IF (.NOT.ln_clim) THEN 659 IF(lwp) WRITE(numout,*) 'first record time (s): ', istep(nbdy_b) 660 IF(lwp) WRITE(numout,*) 'model time (s) : ', itimer 661 IF(lwp) WRITE(numout,*) 'second record time (s): ', istep(nbdy_a) 662 ENDIF 663 ! 664 ENDIF ! end lect=.true. 665 666 667 ! Interpolate linearly 668 ! ******************** 669 ! 670 IF( ln_clim ) THEN ; zxy = REAL( nday ) / REAL( nmonth_len(nbdy_b) ) + 0.5 - i15 671 ELSEIF( istep(nbdy_b) == istep(nbdy_a) ) THEN 672 zxy = 0.0_wp 673 ELSE ; zxy = REAL( istep(nbdy_b) - itimer ) / REAL( istep(nbdy_b) - istep(nbdy_a) ) 674 END IF 675 676 IF(ln_tra_frs) THEN 677 igrd = 1 ! temperature & salinity 678 DO ib = 1, nblen(igrd) 679 DO ik = 1, jpkm1 680 tbdy(ib,ik) = zxy * tbdydta(ib,ik,2) + (1.-zxy) * tbdydta(ib,ik,1) 681 sbdy(ib,ik) = zxy * sbdydta(ib,ik,2) + (1.-zxy) * sbdydta(ib,ik,1) 682 END DO 683 END DO 684 ENDIF 685 686 IF(ln_dyn_frs) THEN 687 igrd = 2 ! u-velocity 688 DO ib = 1, nblen(igrd) 689 DO ik = 1, jpkm1 690 ubdy(ib,ik) = zxy * ubdydta(ib,ik,2) + (1.-zxy) * ubdydta(ib,ik,1) 691 END DO 692 END DO 693 ! 694 igrd = 3 ! v-velocity 695 DO ib = 1, nblen(igrd) 696 DO ik = 1, jpkm1 697 vbdy(ib,ik) = zxy * vbdydta(ib,ik,2) + (1.-zxy) * vbdydta(ib,ik,1) 698 END DO 699 END DO 700 ENDIF 701 702 #if defined key_lim2 703 IF(ln_ice_frs) THEN 704 igrd=1 705 DO ib=1, nblen(igrd) 706 frld_bdy(ib) = zxy * frld_bdydta(ib,2) + (1.-zxy) * frld_bdydta(ib,1) 707 hicif_bdy(ib) = zxy * hicif_bdydta(ib,2) + (1.-zxy) * hicif_bdydta(ib,1) 708 hsnif_bdy(ib) = zxy * hsnif_bdydta(ib,2) + (1.-zxy) * hsnif_bdydta(ib,1) 709 END DO 710 ENDIF ! just if ln_ice_frs is true 711 #endif 712 713 END IF !end if ((nn_dtactl==1).AND.(ntimes_bdy>1)) 714 715 716 ! !---------------------! 717 ! ! last call ! 718 ! !---------------------! 719 IF( kt == nitend ) THEN 720 IF(ln_tra_frs .or. ln_ice_frs) CALL iom_close( numbdyt ) ! Closing of the 3 files 721 IF(ln_dyn_frs) CALL iom_close( numbdyu ) 722 IF(ln_dyn_frs) CALL iom_close( numbdyv ) 723 ENDIF 724 ! 725 ENDIF ! ln_dyn_frs .OR. ln_tra_frs 726 ! 727 END SUBROUTINE bdy_dta_frs 728 729 730 SUBROUTINE bdy_dta_fla( kt, jit, icycl ) 731 !!--------------------------------------------------------------------------- 732 !! *** SUBROUTINE bdy_dta_fla *** 733 !! 734 !! ** Purpose : Read unstructured boundary data for Flather condition 735 !! 736 !! ** Method : At the first timestep, read in boundary data for two 737 !! times from the file and time-interpolate. At other 738 !! timesteps, check to see if we need another time from 739 !! the file. If so read it in. Time interpolate. 740 !!--------------------------------------------------------------------------- 741 !!gm DOCTOR names : argument integer : start with "k" 742 INTEGER, INTENT( in ) :: kt ! ocean time-step index 743 INTEGER, INTENT( in ) :: jit ! barotropic time step index 744 INTEGER, INTENT( in ) :: icycl ! number of cycles need for final file close 745 ! ! (for timesplitting option, otherwise zero) 746 !! 747 LOGICAL :: lect ! flag for reading 748 INTEGER :: it, ib, igrd ! dummy loop indices 749 INTEGER :: idvar ! netcdf var ID 750 INTEGER :: iman, i15, imois ! Time variables for monthly clim forcing 751 INTEGER :: ntimes_bdyt, ntimes_bdyu, ntimes_bdyv 752 INTEGER :: itimer, totime 753 INTEGER :: ipi, ipj, ipk, inum ! temporary integers (NetCDF read) 754 INTEGER :: iyear0, imonth0, iday0 755 INTEGER :: ihours0, iminutes0, isec0 756 INTEGER :: iyear, imonth, iday, isecs 757 INTEGER, DIMENSION(jpbtime) :: istept, istepu, istepv ! time arrays from data files 758 REAL(wp) :: dayfrac, zxy, zoffsett 759 REAL(wp) :: zoffsetu, zoffsetv 760 REAL(wp) :: dayjul0, zdayjulini 761 REAL(wp) :: zinterval_s, zinterval_e ! First and last interval in time axis 762 REAL(wp), DIMENSION(jpbtime) :: zstepr ! REAL time array from data files 763 REAL(wp), DIMENSION(jpbdta,1) :: zdta ! temporary array for data fields 764 CHARACTER(LEN=80), DIMENSION(6) :: clfile 765 CHARACTER(LEN=70 ) :: clunits ! units attribute of time coordinate 766 !!--------------------------------------------------------------------------- 767 768 !!gm add here the same style as in bdy_dta_frs 769 !!gm clearly bdy_dta_fla and bdy_dta_frs can be combined... 770 !!gm too many things duplicated in the read of data... simplification can be done 771 772 ! -------------------- ! 773 ! Initialization ! 774 ! -------------------- ! 775 776 lect = .false. ! If true, read a time record 777 778 ! Some time variables for monthly climatological forcing: 779 ! ******************************************************* 780 !!gm here use directely daymod variables 781 782 iman = INT( raamo ) ! Number of months in a year 783 784 i15 = INT( 2*REAL( nday, wp ) / ( REAL( nmonth_len(nmonth), wp ) + 0.5 ) ) 785 ! i15=0 if the current day is in the first half of the month, else i15=1 786 787 imois = nmonth + i15 - 1 ! imois is the first month record 788 IF( imois == 0 ) imois = iman 789 790 ! Time variable for non-climatological forcing: 791 ! ********************************************* 792 793 itimer = ((kt-1)-nit000+1)*rdt ! current time in seconds for interpolation 794 itimer = itimer + jit*rdt/REAL(nn_baro,wp) ! in non-climatological case 795 796 IF ( ln_tides ) THEN 797 798 ! -------------------------------------! 799 ! Update BDY fields with tidal forcing ! 800 ! -------------------------------------! 801 802 CALL tide_update( kt, jit ) 803 804 ENDIF 805 806 IF ( ln_dyn_fla ) THEN 807 808 ! -------------------------------------! 809 ! Update BDY fields with model data ! 810 ! -------------------------------------! 811 812 ! !-------------------! 813 IF( kt == nit000 .and. jit ==2 ) THEN ! First call only ! 814 ! !-------------------! 815 istep_bt(:) = 0 816 nbdy_b_bt = 0 817 nbdy_a_bt = 0 818 819 ! Get time information from bdy data file 820 ! *************************************** 821 822 IF(lwp) WRITE(numout,*) 823 IF(lwp) WRITE(numout,*) 'bdy_dta_fla :Initialize unstructured boundary data for barotropic variables.' 824 IF(lwp) WRITE(numout,*) '~~~~~~~' 825 826 IF( nn_dtactl == 0 ) THEN 827 IF(lwp) WRITE(numout,*) 'Bdy data are taken from initial conditions' 828 829 ELSEIF (nn_dtactl == 1) THEN 830 IF(lwp) WRITE(numout,*) 'Bdy data are read in netcdf files' 831 832 dayfrac = adatrj - REAL(itimer,wp)/86400. ! day fraction at time step kt-1 833 dayfrac = dayfrac - INT (dayfrac) ! 834 totime = (nitend-nit000+1)*rdt ! Total time of the run to verify that all the 835 ! necessary time dumps in file are included 836 837 clfile(4) = cn_dta_fla_T 838 clfile(5) = cn_dta_fla_U 839 clfile(6) = cn_dta_fla_V 840 841 DO igrd = 4,6 842 843 CALL iom_open( clfile(igrd), inum ) 844 CALL iom_gettime( inum, zstepr, kntime=ntimes_bdy_bt, cdunits=clunits ) 845 846 SELECT CASE( igrd ) 847 CASE (4) 848 numbdyt_bt = inum 849 CASE (5) 850 numbdyu_bt = inum 851 CASE (6) 852 numbdyv_bt = inum 853 END SELECT 854 855 ! Calculate time offset 856 READ(clunits,7000) iyear0, imonth0, iday0, ihours0, iminutes0, isec0 857 ! Convert time origin in file to julian days 858 isec0 = isec0 + ihours0*60.*60. + iminutes0*60. 859 CALL ymds2ju(iyear0, imonth0, iday0, REAL(isec0, wp), dayjul0) 860 ! Compute model initialization time 861 iyear = ndastp / 10000 862 imonth = ( ndastp - iyear * 10000 ) / 100 863 iday = ndastp - iyear * 10000 - imonth * 100 864 isecs = dayfrac * 86400 865 CALL ymds2ju(iyear, imonth, iday, REAL(isecs, wp) , zdayjulini) 866 ! zoffset from initialization date: 867 zoffset = (dayjul0-zdayjulini)*86400 868 ! 869 870 7000 FORMAT('seconds since ', I4.4,'-',I2.2,'-',I2.2,' ',I2.2,':',I2.2,':',I2.2) 871 872 !! TO BE DONE... Check consistency between calendar from file 873 !! (available optionally from iom_gettime) and calendar in model 874 !! when calendar in model available outside of IOIPSL. 875 876 ! Check that there are not too many times in the file. 877 IF (ntimes_bdy_bt > jpbtime) CALL ctl_stop( & 878 'Number of time dumps in bdy file exceed jpbtime parameter', & 879 'Check file:' // TRIM(clfile(igrd)) ) 880 881 ! Check that time array increases (or interp will fail): 882 DO it = 2, ntimes_bdy_bt 883 IF ( zstepr(it-1) >= zstepr(it) ) THEN 884 CALL ctl_stop('Time array in unstructured boundary data file', & 885 'does not continuously increase.', & 886 'Check file:' // TRIM(clfile(igrd)) ) 887 EXIT 888 END IF 889 END DO 890 891 IF ( .NOT. ln_clim ) THEN 892 ! Check that times in file span model run time: 893 894 ! Note: the fields may be time means, so we allow nit000 to be before 895 ! first time in the file, provided that it falls inside the meaning 896 ! period of the first field. Until we can get the meaning period 897 ! from the file, use the interval between fields as a proxy. 898 ! If nit000 is before the first time, use the value at first time 899 ! instead of extrapolating. This is done by putting time 1 into 900 ! both time levels. 901 ! The same applies to the last time level: see setting of lect below. 902 903 IF ( ntimes_bdy_bt == 1 ) CALL ctl_stop( & 904 'There is only one time dump in data files', & 905 'Set ln_clim=.true. in namelist for constant bdy forcing.' ) 906 907 zinterval_s = zstepr(2) - zstepr(1) 908 zinterval_e = zstepr(ntimes_bdy_bt) - zstepr(ntimes_bdy_bt-1) 909 910 IF( zstepr(1) + zoffset > 0 ) THEN 911 WRITE(ctmp1,*) 'Check file: ', clfile(igrd) 912 CALL ctl_stop( 'First time dump in bdy file is after model initial time', ctmp1 ) 913 END IF 914 IF( zstepr(ntimes_bdy_bt) + zoffset < totime ) THEN 915 WRITE(ctmp1,*) 'Check file: ', clfile(igrd) 916 CALL ctl_stop( 'Last time dump in bdy file is before model final time', ctmp1 ) 917 END IF 918 END IF ! .NOT. ln_clim 919 920 IF ( igrd .EQ. 4) THEN 921 ntimes_bdyt = ntimes_bdy_bt 922 zoffsett = zoffset 923 istept(:) = INT( zstepr(:) + zoffset ) 924 ELSE IF (igrd .EQ. 5) THEN 925 ntimes_bdyu = ntimes_bdy_bt 926 zoffsetu = zoffset 927 istepu(:) = INT( zstepr(:) + zoffset ) 928 ELSE IF (igrd .EQ. 6) THEN 929 ntimes_bdyv = ntimes_bdy_bt 930 zoffsetv = zoffset 931 istepv(:) = INT( zstepr(:) + zoffset ) 932 ENDIF 933 934 ENDDO 935 936 ! Verify time consistency between files 937 938 IF ( ntimes_bdyu /= ntimes_bdyt .OR. ntimes_bdyv /= ntimes_bdyt ) THEN 939 CALL ctl_stop( & 940 'Time axis lengths differ between bdy data files', & 941 'Multiple time frequencies not implemented yet' ) 942 ELSE 943 ntimes_bdy_bt = ntimes_bdyt 944 ENDIF 945 946 IF (zoffsetu.NE.zoffsett .OR. zoffsetv.NE.zoffsett) THEN 947 CALL ctl_stop( & 948 'Bdy data files must have the same time origin', & 949 'Multiple time frequencies not implemented yet' ) 950 ENDIF 951 zoffset = zoffsett 952 953 !! Check that times are the same in the three files... HERE. 954 istep_bt(:) = istept(:) 955 956 ! Check number of time dumps: 957 IF (ln_clim) THEN 958 SELECT CASE ( ntimes_bdy_bt ) 959 CASE( 1 ) 960 IF(lwp) WRITE(numout,*) 961 IF(lwp) WRITE(numout,*) 'We assume constant boundary forcing from bdy data files' 962 IF(lwp) WRITE(numout,*) 963 CASE( 12 ) 964 IF(lwp) WRITE(numout,*) 965 IF(lwp) WRITE(numout,*) 'We assume monthly (and cyclic) boundary forcing from bdy data files' 966 IF(lwp) WRITE(numout,*) 967 CASE DEFAULT 968 CALL ctl_stop( & 969 'For climatological boundary forcing (ln_clim=.true.),',& 970 'bdy data files must contain 1 or 12 time dumps.' ) 971 END SELECT 972 ENDIF 973 974 ! Find index of first record to read (before first model time). 975 976 it=1 977 DO WHILE ( ((istep_bt(it+1)) <= 0 ).AND.(it.LE.(ntimes_bdy_bt-1))) 978 it=it+1 979 END DO 980 nbdy_b_bt = it 981 982 IF(lwp) WRITE(numout,*) 'Time offset is ',zoffset 983 IF(lwp) WRITE(numout,*) 'First record to read is ',nbdy_b_bt 984 985 ENDIF ! endif (nn_dtactl == 1) 986 987 ! 1.2 Read first record in file if necessary (ie if nn_dtactl == 1) 988 ! ***************************************************************** 989 990 IF ( nn_dtactl == 0) THEN 991 ! boundary data arrays are filled with initial conditions 992 igrd = 5 ! U-points data 993 DO ib = 1, nblen(igrd) 994 ubtbdy(ib) = un(nbi(ib,igrd), nbj(ib,igrd), 1) 995 END DO 996 997 igrd = 6 ! V-points data 998 DO ib = 1, nblen(igrd) 999 vbtbdy(ib) = vn(nbi(ib,igrd), nbj(ib,igrd), 1) 1000 END DO 1001 1002 igrd = 4 ! T-points data 1003 DO ib = 1, nblen(igrd) 1004 sshbdy(ib) = sshn(nbi(ib,igrd), nbj(ib,igrd)) 1005 END DO 1006 1007 ELSEIF (nn_dtactl == 1) THEN 1008 1009 ! Set first record in the climatological case: 1010 IF ((ln_clim).AND.(ntimes_bdy_bt==1)) THEN 1011 nbdy_a_bt = 1 1012 ELSEIF ((ln_clim).AND.(ntimes_bdy_bt==iman)) THEN 1013 nbdy_b_bt = 0 1014 nbdy_a_bt = imois 1015 ELSE 1016 nbdy_a_bt = nbdy_b_bt 1017 END IF 1018 1019 ! Open Netcdf files: 1020 1021 CALL iom_open ( cn_dta_fla_T, numbdyt_bt ) 1022 CALL iom_open ( cn_dta_fla_U, numbdyu_bt ) 1023 CALL iom_open ( cn_dta_fla_V, numbdyv_bt ) 1024 1025 ! Read first record: 1026 ipj=1 1027 igrd=4 1028 ipi=nblendta(igrd) 1029 1030 ! ssh 1031 igrd=4 1032 IF ( nblendta(igrd) .le. 0 ) THEN 1033 idvar = iom_varid( numbdyt_bt,'sossheig' ) 1034 nblendta(igrd) = iom_file(numbdyt_bt)%dimsz(1,idvar) 1035 ENDIF 1036 WRITE(numout,*) 'Dim size for sossheig is ',nblendta(igrd) 1037 ipi=nblendta(igrd) 1038 1039 CALL iom_get ( numbdyt_bt, jpdom_unknown,'sossheig',zdta(1:ipi,1:ipj),nbdy_a_bt ) 1040 1041 DO ib=1, nblen(igrd) 1042 sshbdydta(ib,2) = zdta(nbmap(ib,igrd),1) 1043 END DO 1044 1045 ! u-velocity 1046 igrd=5 1047 IF ( nblendta(igrd) .le. 0 ) THEN 1048 idvar = iom_varid( numbdyu_bt,'vobtcrtx' ) 1049 nblendta(igrd) = iom_file(numbdyu_bt)%dimsz(1,idvar) 1050 ENDIF 1051 WRITE(numout,*) 'Dim size for vobtcrtx is ',nblendta(igrd) 1052 ipi=nblendta(igrd) 1053 1054 CALL iom_get ( numbdyu_bt, jpdom_unknown,'vobtcrtx',zdta(1:ipi,1:ipj),nbdy_a_bt ) 1055 1056 DO ib=1, nblen(igrd) 1057 ubtbdydta(ib,2) = zdta(nbmap(ib,igrd),1) 1058 END DO 1059 1060 ! v-velocity 1061 igrd=6 1062 IF ( nblendta(igrd) .le. 0 ) THEN 1063 idvar = iom_varid( numbdyv_bt,'vobtcrty' ) 1064 nblendta(igrd) = iom_file(numbdyv_bt)%dimsz(1,idvar) 1065 ENDIF 1066 WRITE(numout,*) 'Dim size for vobtcrty is ',nblendta(igrd) 1067 ipi=nblendta(igrd) 1068 1069 CALL iom_get ( numbdyv_bt, jpdom_unknown,'vobtcrty',zdta(1:ipi,1:ipj),nbdy_a_bt ) 1070 1071 DO ib=1, nblen(igrd) 1072 vbtbdydta(ib,2) = zdta(nbmap(ib,igrd),1) 1073 END DO 1074 1075 END IF 1076 1077 ! In the case of constant boundary forcing fill bdy arrays once for all 1078 IF ((ln_clim).AND.(ntimes_bdy_bt==1)) THEN 1079 1080 ubtbdy (:) = ubtbdydta (:,2) 1081 vbtbdy (:) = vbtbdydta (:,2) 1082 sshbdy (:) = sshbdydta (:,2) 1083 1084 CALL iom_close( numbdyt_bt ) 1085 CALL iom_close( numbdyu_bt ) 1086 CALL iom_close( numbdyv_bt ) 1087 1088 END IF 1089 1090 ENDIF ! End if nit000 1091 1092 ! -------------------- ! 1093 ! 2. At each time step ! 1094 ! -------------------- ! 1095 1096 IF ((nn_dtactl==1).AND.(ntimes_bdy_bt>1)) THEN 1097 1098 ! 2.1 Read one more record if necessary 1099 !************************************** 1100 1101 IF ( (ln_clim).AND.(imois/=nbdy_b_bt) ) THEN ! remember that nbdy_b_bt=0 for kt=nit000 1102 nbdy_b_bt = imois 1103 nbdy_a_bt = imois+1 1104 nbdy_b_bt = MOD( nbdy_b_bt, iman ) 1105 IF( nbdy_b_bt == 0 ) nbdy_b_bt = iman 1106 nbdy_a_bt = MOD( nbdy_a_bt, iman ) 1107 IF( nbdy_a_bt == 0 ) nbdy_a_bt = iman 1108 lect=.true. 1109 1110 ELSEIF ((.NOT.ln_clim).AND.(itimer >= istep_bt(nbdy_a_bt))) THEN 1111 nbdy_b_bt=nbdy_a_bt 1112 nbdy_a_bt=nbdy_a_bt+1 1113 lect=.true. 1114 END IF 1115 1116 IF (lect) THEN 1117 1118 ! Swap arrays 1119 sshbdydta(:,1) = sshbdydta(:,2) 1120 ubtbdydta(:,1) = ubtbdydta(:,2) 1121 vbtbdydta(:,1) = vbtbdydta(:,2) 1122 1123 ! read another set 1124 1125 ipj=1 1126 ipk=jpk 1127 igrd=4 1128 ipi=nblendta(igrd) 1129 1130 1131 ! ssh 1132 igrd=4 1133 ipi=nblendta(igrd) 1134 1135 CALL iom_get ( numbdyt_bt, jpdom_unknown,'sossheig',zdta(1:ipi,1:ipj),nbdy_a_bt ) 1136 1137 DO ib=1, nblen(igrd) 1138 sshbdydta(ib,2) = zdta(nbmap(ib,igrd),1) 1139 END DO 1140 1141 ! u-velocity 1142 igrd=5 1143 ipi=nblendta(igrd) 1144 1145 CALL iom_get ( numbdyu_bt, jpdom_unknown,'vobtcrtx',zdta(1:ipi,1:ipj),nbdy_a_bt ) 1146 1147 DO ib=1, nblen(igrd) 1148 ubtbdydta(ib,2) = zdta(nbmap(ib,igrd),1) 1149 END DO 1150 1151 ! v-velocity 1152 igrd=6 1153 ipi=nblendta(igrd) 1154 1155 CALL iom_get ( numbdyv_bt, jpdom_unknown,'vobtcrty',zdta(1:ipi,1:ipj),nbdy_a_bt ) 1156 1157 DO ib=1, nblen(igrd) 1158 vbtbdydta(ib,2) = zdta(nbmap(ib,igrd),1) 1159 END DO 1160 1161 1162 IF(lwp) WRITE(numout,*) 'bdy_dta_fla : first record file used nbdy_b_bt ',nbdy_b_bt 1163 IF(lwp) WRITE(numout,*) '~~~~~~~~ last record file used nbdy_a_bt ',nbdy_a_bt 1164 IF (.NOT.ln_clim) THEN 1165 IF(lwp) WRITE(numout,*) 'first record time (s): ', istep_bt(nbdy_b_bt) 1166 IF(lwp) WRITE(numout,*) 'model time (s) : ', itimer 1167 IF(lwp) WRITE(numout,*) 'second record time (s): ', istep_bt(nbdy_a_bt) 1168 ENDIF 1169 END IF ! end lect=.true. 1170 1171 1172 ! 2.2 Interpolate linearly: 1173 ! *************************** 1174 1175 IF (ln_clim) THEN 1176 zxy = REAL( nday, wp ) / REAL( nmonth_len(nbdy_b_bt), wp ) + 0.5 - i15 1177 ELSE 1178 zxy = REAL(istep_bt(nbdy_b_bt)-itimer, wp) / REAL(istep_bt(nbdy_b_bt)-istep_bt(nbdy_a_bt), wp) 1179 END IF 1180 1181 igrd=4 1182 DO ib=1, nblen(igrd) 1183 sshbdy(ib) = zxy * sshbdydta(ib,2) + & 1184 (1.-zxy) * sshbdydta(ib,1) 1185 END DO 1186 1187 igrd=5 1188 DO ib=1, nblen(igrd) 1189 ubtbdy(ib) = zxy * ubtbdydta(ib,2) + & 1190 (1.-zxy) * ubtbdydta(ib,1) 1191 END DO 1192 1193 igrd=6 1194 DO ib=1, nblen(igrd) 1195 vbtbdy(ib) = zxy * vbtbdydta(ib,2) + & 1196 (1.-zxy) * vbtbdydta(ib,1) 1197 END DO 1198 1199 1200 END IF !end if ((nn_dtactl==1).AND.(ntimes_bdy_bt>1)) 1201 1202 ! ------------------- ! 1203 ! Last call kt=nitend ! 1204 ! ------------------- ! 1205 1206 ! Closing of the 3 files 1207 IF( kt == nitend .and. jit == icycl ) THEN 1208 CALL iom_close( numbdyt_bt ) 1209 CALL iom_close( numbdyu_bt ) 1210 CALL iom_close( numbdyv_bt ) 1211 ENDIF 1212 1213 ENDIF ! ln_dyn_frs 1214 1215 END SUBROUTINE bdy_dta_fla 1216 607 IF( nn_dyn2d(ib_bdy) .ne. jp_frs ) THEN 608 jfld = jfld + 1 609 dta_bdy(ib_bdy)%ssh => bf(jfld)%fnow(:,1,1) 610 ENDIF 611 jfld = jfld + 1 612 dta_bdy(ib_bdy)%u2d => bf(jfld)%fnow(:,1,1) 613 jfld = jfld + 1 614 dta_bdy(ib_bdy)%v2d => bf(jfld)%fnow(:,1,1) 615 ENDIF 616 ENDIF 617 618 IF ( nn_dyn3d(ib_bdy) .gt. 0 .and. nn_dyn3d_dta(ib_bdy) .eq. 0 ) THEN 619 IF( nn_dyn3d(ib_bdy) .eq. jp_frs ) THEN 620 ilen0(1:3) = nblen(1:3) 621 ELSE 622 ilen0(1:3) = nblenrim(1:3) 623 ENDIF 624 ALLOCATE( dta_bdy(ib_bdy)%u3d(ilen0(2),jpk) ) 625 ALLOCATE( dta_bdy(ib_bdy)%v3d(ilen0(3),jpk) ) 626 ENDIF 627 IF ( ( nn_dyn3d(ib_bdy) .gt. 0 .and. nn_dyn3d_dta(ib_bdy) .eq. 1 ).or. & 628 & ( ln_full_vel_array(ib_bdy) .and. nn_dyn2d(ib_bdy) .gt. 0 .and. & 629 & ( nn_dyn2d_dta(ib_bdy) .eq. 1 .or. nn_dyn2d_dta(ib_bdy) .eq. 3 ) ) ) THEN 630 jfld = jfld + 1 631 dta_bdy(ib_bdy)%u3d => bf(jfld)%fnow(:,1,:) 632 jfld = jfld + 1 633 dta_bdy(ib_bdy)%v3d => bf(jfld)%fnow(:,1,:) 634 ENDIF 635 636 IF (nn_tra(ib_bdy) .gt. 0) THEN 637 IF( nn_tra_dta(ib_bdy) .eq. 0 ) THEN 638 IF( nn_tra(ib_bdy) .eq. jp_frs ) THEN 639 ilen0(1:3) = nblen(1:3) 640 ELSE 641 ilen0(1:3) = nblenrim(1:3) 642 ENDIF 643 ALLOCATE( dta_bdy(ib_bdy)%tem(ilen0(1),jpk) ) 644 ALLOCATE( dta_bdy(ib_bdy)%sal(ilen0(1),jpk) ) 645 ELSE 646 jfld = jfld + 1 647 dta_bdy(ib_bdy)%tem => bf(jfld)%fnow(:,1,:) 648 jfld = jfld + 1 649 dta_bdy(ib_bdy)%sal => bf(jfld)%fnow(:,1,:) 650 ENDIF 651 ENDIF 652 653 #if defined key_lim2 654 IF (nn_ice_lim2(ib_bdy) .gt. 0) THEN 655 IF( nn_ice_lim2_dta(ib_bdy) .eq. 0 ) THEN 656 IF( nn_ice_lim2(ib_bdy) .eq. jp_frs ) THEN 657 ilen0(1:3) = nblen(1:3) 658 ELSE 659 ilen0(1:3) = nblenrim(1:3) 660 ENDIF 661 ALLOCATE( dta_bdy(ib_bdy)%frld(ilen0(1)) ) 662 ALLOCATE( dta_bdy(ib_bdy)%hicif(ilen0(1)) ) 663 ALLOCATE( dta_bdy(ib_bdy)%hsnif(ilen0(1)) ) 664 ELSE 665 jfld = jfld + 1 666 dta_bdy(ib_bdy)%frld => bf(jfld)%fnow(:,1,1) 667 jfld = jfld + 1 668 dta_bdy(ib_bdy)%hicif => bf(jfld)%fnow(:,1,1) 669 jfld = jfld + 1 670 dta_bdy(ib_bdy)%hsnif => bf(jfld)%fnow(:,1,1) 671 ENDIF 672 ENDIF 673 #endif 674 675 ENDDO ! ib_bdy 676 677 IF( nn_timing == 1 ) CALL timing_stop('bdy_dta_init') 678 679 END SUBROUTINE bdy_dta_init 1217 680 1218 681 #else 1219 682 !!---------------------------------------------------------------------- 1220 !! Dummy module NO UnstructOpen Boundary Conditions683 !! Dummy module NO Open Boundary Conditions 1221 684 !!---------------------------------------------------------------------- 1222 685 CONTAINS 1223 SUBROUTINE bdy_dta_frs( kt ) ! Empty routine 1224 WRITE(*,*) 'bdy_dta_frs: You should not have seen this print! error?', kt 1225 END SUBROUTINE bdy_dta_frs 1226 SUBROUTINE bdy_dta_fla( kt, kit, icycle ) ! Empty routine 1227 WRITE(*,*) 'bdy_dta_frs: You should not have seen this print! error?', kt, kit 1228 END SUBROUTINE bdy_dta_fla 686 SUBROUTINE bdy_dta( kt, jit, time_offset ) ! Empty routine 687 INTEGER, INTENT( in ) :: kt 688 INTEGER, INTENT( in ), OPTIONAL :: jit 689 INTEGER, INTENT( in ), OPTIONAL :: time_offset 690 WRITE(*,*) 'bdy_dta: You should not have seen this print! error?', kt 691 END SUBROUTINE bdy_dta 692 SUBROUTINE bdy_dta_init() ! Empty routine 693 WRITE(*,*) 'bdy_dta_init: You should not have seen this print! error?' 694 END SUBROUTINE bdy_dta_init 1229 695 #endif 1230 696 -
trunk/NEMOGCM/NEMO/OPA_SRC/BDY/bdydyn.F90
r2528 r3294 2 2 !!====================================================================== 3 3 !! *** MODULE bdydyn *** 4 !! Unstructured Open Boundary Cond. : Flow relaxation scheme onvelocities4 !! Unstructured Open Boundary Cond. : Apply boundary conditions to velocities 5 5 !!====================================================================== 6 6 !! History : 1.0 ! 2005-02 (J. Chanut, A. Sellar) Original code … … 10 10 !! 3.3 ! 2010-09 (E.O'Dea) modifications for Shelf configurations 11 11 !! 3.3 ! 2010-09 (D.Storkey) add ice boundary conditions 12 !! 3.4 ! 2011 (D. Storkey) rewrite in preparation for OBC-BDY merge 12 13 !!---------------------------------------------------------------------- 13 14 #if defined key_bdy … … 15 16 !! 'key_bdy' : Unstructured Open Boundary Condition 16 17 !!---------------------------------------------------------------------- 17 !! bdy_dyn_frs : relaxation of velocities on unstructured open boundary 18 !! bdy_dyn_fla : Flather condition for barotropic solution 18 !! bdy_dyn : split velocities into barotropic and baroclinic parts 19 !! and call bdy_dyn2d and bdy_dyn3d to apply boundary 20 !! conditions 19 21 !!---------------------------------------------------------------------- 22 USE wrk_nemo ! Memory Allocation 23 USE timing ! Timing 20 24 USE oce ! ocean dynamics and tracers 21 25 USE dom_oce ! ocean space and time domain 26 USE dynspg_oce 22 27 USE bdy_oce ! ocean open boundary conditions 23 USE dynspg_oce ! for barotropic variables24 USE phycst ! physical constants28 USE bdydyn2d ! open boundary conditions for barotropic solution 29 USE bdydyn3d ! open boundary conditions for baroclinic velocities 25 30 USE lbclnk ! ocean lateral boundary conditions (or mpp link) 26 USE bdytides ! for tidal harmonic forcing at boundary27 31 USE in_out_manager ! 28 32 … … 30 34 PRIVATE 31 35 32 PUBLIC bdy_dyn_frs ! routine called in dynspg_flt (free surface case ONLY) 33 # if defined key_dynspg_exp || defined key_dynspg_ts 34 PUBLIC bdy_dyn_fla ! routine called in dynspg_flt (free surface case ONLY) 35 # endif 36 PUBLIC bdy_dyn ! routine called in dynspg_flt (if lk_dynspg_flt) or 37 ! dyn_nxt (if lk_dynspg_ts or lk_dynspg_exp) 36 38 39 # include "domzgr_substitute.h90" 37 40 !!---------------------------------------------------------------------- 38 41 !! NEMO/OPA 3.3 , NEMO Consortium (2010) … … 42 45 CONTAINS 43 46 44 SUBROUTINE bdy_dyn _frs( kt)47 SUBROUTINE bdy_dyn( kt, dyn3d_only ) 45 48 !!---------------------------------------------------------------------- 46 !! *** SUBROUTINE bdy_dyn _frs***49 !! *** SUBROUTINE bdy_dyn *** 47 50 !! 48 !! ** Purpose : - Apply the Flow Relaxation Scheme for dynamic in the 49 !! case of unstructured open boundaries. 51 !! ** Purpose : - Wrapper routine for bdy_dyn2d and bdy_dyn3d. 50 52 !! 51 !! References :- Engedahl H., 1995: Use of the flow relaxation scheme in52 !! a three-dimensional baroclinic ocean model with realistic53 !! topography. Tellus, 365-382.54 53 !!---------------------------------------------------------------------- 55 INTEGER, INTENT( in ) :: kt ! Main time step counter56 54 !! 57 INTEGER :: jb, jk ! dummy loop indices 58 INTEGER :: ii, ij, igrd ! local integers 59 REAL(wp) :: zwgt ! boundary weight 60 !!---------------------------------------------------------------------- 61 ! 62 IF(ln_dyn_frs) THEN ! If this is false, then this routine does nothing. 63 ! 64 IF( kt == nit000 ) THEN 65 IF(lwp) WRITE(numout,*) 66 IF(lwp) WRITE(numout,*) 'bdy_dyn_frs : Flow Relaxation Scheme on momentum' 67 IF(lwp) WRITE(numout,*) '~~~~~~~' 68 ENDIF 69 ! 70 igrd = 2 ! Relaxation of zonal velocity 71 DO jb = 1, nblen(igrd) 72 DO jk = 1, jpkm1 73 ii = nbi(jb,igrd) 74 ij = nbj(jb,igrd) 75 zwgt = nbw(jb,igrd) 76 ua(ii,ij,jk) = ( ua(ii,ij,jk) * ( 1.- zwgt ) + ubdy(jb,jk) * zwgt ) * umask(ii,ij,jk) 77 END DO 78 END DO 79 ! 80 igrd = 3 ! Relaxation of meridional velocity 81 DO jb = 1, nblen(igrd) 82 DO jk = 1, jpkm1 83 ii = nbi(jb,igrd) 84 ij = nbj(jb,igrd) 85 zwgt = nbw(jb,igrd) 86 va(ii,ij,jk) = ( va(ii,ij,jk) * ( 1.- zwgt ) + vbdy(jb,jk) * zwgt ) * vmask(ii,ij,jk) 87 END DO 88 END DO 89 CALL lbc_lnk( ua, 'U', -1. ) ; CALL lbc_lnk( va, 'V', -1. ) ! Boundary points should be updated 90 ! 91 ENDIF ! ln_dyn_frs 92 ! 93 END SUBROUTINE bdy_dyn_frs 55 INTEGER, INTENT( in ) :: kt ! Main time step counter 56 LOGICAL, INTENT( in ), OPTIONAL :: dyn3d_only ! T => only update baroclinic velocities 57 !! 58 INTEGER :: jk,ii,ij,ib,igrd ! Loop counter 59 LOGICAL :: ll_dyn2d, ll_dyn3d 60 !! 94 61 62 IF( nn_timing == 1 ) CALL timing_start('bdy_dyn') 95 63 96 # if defined key_dynspg_exp || defined key_dynspg_ts 97 !!---------------------------------------------------------------------- 98 !! 'key_dynspg_exp' OR explicit sea surface height 99 !! 'key_dynspg_ts ' split-explicit sea surface height 100 !!---------------------------------------------------------------------- 101 102 !! Option to use Flather with dynspg_flt not coded yet... 64 ll_dyn2d = .true. 65 ll_dyn3d = .true. 103 66 104 SUBROUTINE bdy_dyn_fla( pssh ) 105 !!---------------------------------------------------------------------- 106 !! *** SUBROUTINE bdy_dyn_fla *** 107 !! 108 !! - Apply Flather boundary conditions on normal barotropic velocities 109 !! (ln_dyn_fla=.true. or ln_tides=.true.) 110 !! 111 !! ** WARNINGS about FLATHER implementation: 112 !!1. According to Palma and Matano, 1998 "after ssh" is used. 113 !! In ROMS and POM implementations, it is "now ssh". In the current 114 !! implementation (tested only in the EEL-R5 conf.), both cases were unstable. 115 !! So I use "before ssh" in the following. 116 !! 117 !!2. We assume that the normal ssh gradient at the bdy is zero. As a matter of 118 !! fact, the model ssh just inside the dynamical boundary is used (the outside 119 !! ssh in the code is not updated). 120 !! 121 !! References: Flather, R. A., 1976: A tidal model of the northwest European 122 !! continental shelf. Mem. Soc. R. Sci. Liege, Ser. 6,10, 141-164. 123 !!---------------------------------------------------------------------- 124 REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pssh 67 IF( PRESENT(dyn3d_only) ) THEN 68 IF( dyn3d_only ) ll_dyn2d = .false. 69 ENDIF 125 70 126 INTEGER :: jb, igrd ! dummy loop indices 127 INTEGER :: ii, ij, iim1, iip1, ijm1, ijp1 ! 2D addresses 128 REAL(wp) :: zcorr ! Flather correction 129 REAL(wp) :: zforc ! temporary scalar 130 !!---------------------------------------------------------------------- 71 !------------------------------------------------------- 72 ! Set pointers 73 !------------------------------------------------------- 131 74 132 ! ---------------------------------! 133 ! Flather boundary conditions :! 134 ! ---------------------------------! 135 136 IF(ln_dyn_fla .OR. ln_tides) THEN ! If these are both false, then this routine does nothing. 75 pssh => sshn 76 phur => hur 77 phvr => hvr 78 CALL wrk_alloc(jpi,jpj,pu2d,pv2d) 137 79 138 ! Fill temporary array with ssh data (here spgu): 139 igrd = 4 140 spgu(:,:) = 0.0 141 DO jb = 1, nblenrim(igrd) 142 ii = nbi(jb,igrd) 143 ij = nbj(jb,igrd) 144 IF( ln_dyn_fla ) spgu(ii, ij) = sshbdy(jb) 145 IF( ln_tides ) spgu(ii, ij) = spgu(ii, ij) + sshtide(jb) 146 END DO 147 ! 148 igrd = 5 ! Flather bc on u-velocity; 149 ! ! remember that flagu=-1 if normal velocity direction is outward 150 ! ! I think we should rather use after ssh ? 151 DO jb = 1, nblenrim(igrd) 152 ii = nbi(jb,igrd) 153 ij = nbj(jb,igrd) 154 iim1 = ii + MAX( 0, INT( flagu(jb) ) ) ! T pts i-indice inside the boundary 155 iip1 = ii - MIN( 0, INT( flagu(jb) ) ) ! T pts i-indice outside the boundary 156 ! 157 zcorr = - flagu(jb) * SQRT( grav * hur_e(ii, ij) ) * ( pssh(iim1, ij) - spgu(iip1,ij) ) 158 zforc = ubtbdy(jb) + utide(jb) 159 ua_e(ii,ij) = zforc + zcorr * umask(ii,ij,1) 160 END DO 161 ! 162 igrd = 6 ! Flather bc on v-velocity 163 ! ! remember that flagv=-1 if normal velocity direction is outward 164 DO jb = 1, nblenrim(igrd) 165 ii = nbi(jb,igrd) 166 ij = nbj(jb,igrd) 167 ijm1 = ij + MAX( 0, INT( flagv(jb) ) ) ! T pts j-indice inside the boundary 168 ijp1 = ij - MIN( 0, INT( flagv(jb) ) ) ! T pts j-indice outside the boundary 169 ! 170 zcorr = - flagv(jb) * SQRT( grav * hvr_e(ii, ij) ) * ( pssh(ii, ijm1) - spgu(ii,ijp1) ) 171 zforc = vbtbdy(jb) + vtide(jb) 172 va_e(ii,ij) = zforc + zcorr * vmask(ii,ij,1) 173 END DO 174 CALL lbc_lnk( ua_e, 'U', -1. ) ! Boundary points should be updated 175 CALL lbc_lnk( va_e, 'V', -1. ) ! 176 ! 177 ENDIF ! ln_dyn_fla .or. ln_tides 178 ! 179 END SUBROUTINE bdy_dyn_fla 180 #endif 80 !------------------------------------------------------- 81 ! Split velocities into barotropic and baroclinic parts 82 !------------------------------------------------------- 83 84 pu2d(:,:) = 0.e0 85 pv2d(:,:) = 0.e0 86 DO jk = 1, jpkm1 !! Vertically integrated momentum trends 87 pu2d(:,:) = pu2d(:,:) + fse3u(:,:,jk) * umask(:,:,jk) * ua(:,:,jk) 88 pv2d(:,:) = pv2d(:,:) + fse3v(:,:,jk) * vmask(:,:,jk) * va(:,:,jk) 89 END DO 90 pu2d(:,:) = pu2d(:,:) * phur(:,:) 91 pv2d(:,:) = pv2d(:,:) * phvr(:,:) 92 DO jk = 1 , jpkm1 93 ua(:,:,jk) = ua(:,:,jk) - pu2d(:,:) 94 va(:,:,jk) = va(:,:,jk) - pv2d(:,:) 95 END DO 96 97 !------------------------------------------------------- 98 ! Apply boundary conditions to barotropic and baroclinic 99 ! parts separately 100 !------------------------------------------------------- 101 102 IF( ll_dyn2d ) CALL bdy_dyn2d( kt ) 103 104 IF( ll_dyn3d ) CALL bdy_dyn3d( kt ) 105 106 !------------------------------------------------------- 107 ! Recombine velocities 108 !------------------------------------------------------- 109 110 DO jk = 1 , jpkm1 111 ua(:,:,jk) = ( ua(:,:,jk) + pu2d(:,:) ) * umask(:,:,jk) 112 va(:,:,jk) = ( va(:,:,jk) + pv2d(:,:) ) * vmask(:,:,jk) 113 END DO 114 115 CALL wrk_dealloc(jpi,jpj,pu2d,pv2d) 116 117 IF( nn_timing == 1 ) CALL timing_stop('bdy_dyn') 118 119 END SUBROUTINE bdy_dyn 181 120 182 121 #else … … 185 124 !!---------------------------------------------------------------------- 186 125 CONTAINS 187 SUBROUTINE bdy_dyn_frs( kt ) ! Empty routine 188 WRITE(*,*) 'bdy_dyn_frs: You should not have seen this print! error?', kt 189 END SUBROUTINE bdy_dyn_frs 190 SUBROUTINE bdy_dyn_fla( pssh ) ! Empty routine 191 REAL :: pssh(:,:) 192 WRITE(*,*) 'bdy_dyn_fla: You should not have seen this print! error?', pssh(1,1) 193 END SUBROUTINE bdy_dyn_fla 126 SUBROUTINE bdy_dyn( kt ) ! Empty routine 127 WRITE(*,*) 'bdy_dyn: You should not have seen this print! error?', kt 128 END SUBROUTINE bdy_dyn 194 129 #endif 195 130 -
trunk/NEMOGCM/NEMO/OPA_SRC/BDY/bdyini.F90
r2715 r3294 10 10 !! 3.3 ! 2010-09 (E.O'Dea) updates for Shelf configurations 11 11 !! 3.3 ! 2010-09 (D.Storkey) add ice boundary conditions 12 !! 3.4 ! 2011 (D. Storkey) rewrite in preparation for OBC-BDY merge 12 13 !!---------------------------------------------------------------------- 13 14 #if defined key_bdy … … 17 18 !! bdy_init : Initialization of unstructured open boundaries 18 19 !!---------------------------------------------------------------------- 20 USE timing ! Timing 19 21 USE oce ! ocean dynamics and tracers variables 20 22 USE dom_oce ! ocean space and time domain 21 USE obc_par ! ocean open boundary conditions22 23 USE bdy_oce ! unstructured open boundary conditions 23 USE bdydta, ONLY: bdy_dta_alloc ! open boundary data24 USE bdytides ! tides at open boundaries initialization (tide_init routine)25 24 USE in_out_manager ! I/O units 26 25 USE lbclnk ! ocean lateral boundary conditions (or mpp link) … … 31 30 PRIVATE 32 31 33 PUBLIC bdy_init ! routine called by opa.F9032 PUBLIC bdy_init ! routine called in nemo_init 34 33 35 34 !!---------------------------------------------------------------------- … … 52 51 !! ** Input : bdy_init.nc, input file for unstructured open boundaries 53 52 !!---------------------------------------------------------------------- 54 INTEGER :: ii, ij, ik, igrd, ib, ir ! dummy loop indices 55 INTEGER :: icount, icountr, ib_len, ibr_max ! local integers 56 INTEGER :: iw, ie, is, in, inum, id_dummy ! - - 57 INTEGER :: igrd_start, igrd_end ! - - 58 REAL(wp) :: zefl, zwfl, znfl, zsfl ! local scalars 59 INTEGER, DIMENSION (2) :: kdimsz 60 INTEGER, DIMENSION(jpbdta, jpbgrd) :: nbidta, nbjdta ! Index arrays: i and j indices of bdy dta 61 INTEGER, DIMENSION(jpbdta, jpbgrd) :: nbrdta ! Discrete distance from rim points 62 REAL(wp), DIMENSION(jpidta,jpjdta) :: zmask ! global domain mask 63 REAL(wp), DIMENSION(jpbdta,1) :: zdta ! temporary array 64 CHARACTER(LEN=80),DIMENSION(6) :: clfile 53 ! namelist variables 54 !------------------- 55 INTEGER, PARAMETER :: jp_nseg = 100 56 INTEGER :: nbdysege, nbdysegw, nbdysegn, nbdysegs 57 INTEGER, DIMENSION(jp_nseg) :: jpieob, jpjedt, jpjeft 58 INTEGER, DIMENSION(jp_nseg) :: jpiwob, jpjwdt, jpjwft 59 INTEGER, DIMENSION(jp_nseg) :: jpjnob, jpindt, jpinft 60 INTEGER, DIMENSION(jp_nseg) :: jpjsob, jpisdt, jpisft 61 62 ! local variables 63 !------------------- 64 INTEGER :: ib_bdy, ii, ij, ik, igrd, ib, ir, iseg ! dummy loop indices 65 INTEGER :: icount, icountr, ibr_max, ilen1, ibm1 ! local integers 66 INTEGER :: iw, ie, is, in, inum, id_dummy ! - - 67 INTEGER :: igrd_start, igrd_end, jpbdta ! - - 68 INTEGER, POINTER :: nbi, nbj, nbr ! short cuts 69 REAL , POINTER :: flagu, flagv ! - - 70 REAL(wp) :: zefl, zwfl, znfl, zsfl ! local scalars 71 INTEGER, DIMENSION (2) :: kdimsz 72 INTEGER, DIMENSION(jpbgrd,jp_bdy) :: nblendta ! Length of index arrays 73 INTEGER, ALLOCATABLE, DIMENSION(:,:,:) :: nbidta, nbjdta ! Index arrays: i and j indices of bdy dta 74 INTEGER, ALLOCATABLE, DIMENSION(:,:,:) :: nbrdta ! Discrete distance from rim points 75 REAL(wp), DIMENSION(jpidta,jpjdta) :: zmask ! global domain mask 76 CHARACTER(LEN=80),DIMENSION(jpbgrd) :: clfile 77 CHARACTER(LEN=1),DIMENSION(jpbgrd) :: cgrid 65 78 !! 66 NAMELIST/nambdy/cn_mask, cn_dta_frs_T, cn_dta_frs_U, cn_dta_frs_V, & 67 & cn_dta_fla_T, cn_dta_fla_U, cn_dta_fla_V, & 68 & ln_tides, ln_clim, ln_vol, ln_mask, & 69 & ln_dyn_fla, ln_dyn_frs, ln_tra_frs,ln_ice_frs, & 70 & nn_dtactl, nn_rimwidth, nn_volctl 79 NAMELIST/nambdy/ nb_bdy, ln_coords_file, cn_coords_file, & 80 & ln_mask_file, cn_mask_file, nn_dyn2d, nn_dyn2d_dta, & 81 & nn_dyn3d, nn_dyn3d_dta, nn_tra, nn_tra_dta, & 82 #if defined key_lim2 83 & nn_ice_lim2, nn_ice_lim2_dta, & 84 #endif 85 & ln_vol, nn_volctl, nn_rimwidth 86 !! 87 NAMELIST/nambdy_index/ nbdysege, jpieob, jpjedt, jpjeft, & 88 nbdysegw, jpiwob, jpjwdt, jpjwft, & 89 nbdysegn, jpjnob, jpindt, jpinft, & 90 nbdysegs, jpjsob, jpisdt, jpisft 91 71 92 !!---------------------------------------------------------------------- 72 93 94 IF( nn_timing == 1 ) CALL timing_start('bdy_init') 95 96 IF( bdy_oce_alloc() /= 0 ) CALL ctl_stop( 'STOP', 'bdy_init : unable to allocate oce arrays' ) 97 73 98 IF(lwp) WRITE(numout,*) 74 IF(lwp) WRITE(numout,*) 'bdy_init : initialization of unstructuredopen boundaries'99 IF(lwp) WRITE(numout,*) 'bdy_init : initialization of open boundaries' 75 100 IF(lwp) WRITE(numout,*) '~~~~~~~~' 76 101 ! 77 ! ! allocate bdy_oce arrays78 IF( bdy_oce_alloc() /= 0 ) CALL ctl_stop( 'STOP', 'bdy_init : unable to allocate oce arrays' )79 IF( bdy_dta_alloc() /= 0 ) CALL ctl_stop( 'STOP', 'bdy_init : unable to allocate dta arrays' )80 102 81 103 IF( jperio /= 0 ) CALL ctl_stop( 'Cyclic or symmetric,', & 82 & ' and unstructured open boundary condition are not compatible' ) 83 84 IF( lk_obc ) CALL ctl_stop( 'Straight open boundaries,', & 85 & ' and unstructured open boundaries are not compatible' ) 86 87 ! --------------------------- 88 REWIND( numnam ) ! Read namelist parameters 104 & ' and general open boundary condition are not compatible' ) 105 106 cgrid= (/'t','u','v'/) 107 108 ! ----------------------------------------- 109 ! Initialise and read namelist parameters 110 ! ----------------------------------------- 111 112 nb_bdy = 0 113 ln_coords_file(:) = .false. 114 cn_coords_file(:) = '' 115 ln_mask_file = .false. 116 cn_mask_file(:) = '' 117 nn_dyn2d(:) = 0 118 nn_dyn2d_dta(:) = -1 ! uninitialised flag 119 nn_dyn3d(:) = 0 120 nn_dyn3d_dta(:) = -1 ! uninitialised flag 121 nn_tra(:) = 0 122 nn_tra_dta(:) = -1 ! uninitialised flag 123 #if defined key_lim2 124 nn_ice_lim2(:) = 0 125 nn_ice_lim2_dta(:)= -1 ! uninitialised flag 126 #endif 127 ln_vol = .false. 128 nn_volctl = -1 ! uninitialised flag 129 nn_rimwidth(:) = -1 ! uninitialised flag 130 131 REWIND( numnam ) 89 132 READ ( numnam, nambdy ) 133 134 ! ----------------------------------------- 135 ! Check and write out namelist parameters 136 ! ----------------------------------------- 90 137 91 138 ! ! control prints 92 139 IF(lwp) WRITE(numout,*) ' nambdy' 93 140 94 ! ! check type of data used (nn_dtactl value) 95 IF(lwp) WRITE(numout,*) 'nn_dtactl =', nn_dtactl 96 IF(lwp) WRITE(numout,*) 97 SELECT CASE( nn_dtactl ) ! 98 CASE( 0 ) ; IF(lwp) WRITE(numout,*) ' initial state used for bdy data' 99 CASE( 1 ) ; IF(lwp) WRITE(numout,*) ' boundary data taken from file' 100 CASE DEFAULT ; CALL ctl_stop( 'nn_dtactl must be 0 or 1' ) 101 END SELECT 102 103 IF(lwp) WRITE(numout,*) 104 IF(lwp) WRITE(numout,*) 'Boundary rim width for the FRS nn_rimwidth = ', nn_rimwidth 105 106 IF(lwp) WRITE(numout,*) 107 IF(lwp) WRITE(numout,*) ' nn_volctl = ', nn_volctl 108 109 IF( ln_vol ) THEN ! check volume conservation (nn_volctl value) 110 SELECT CASE ( nn_volctl ) 141 IF( nb_bdy .eq. 0 ) THEN 142 IF(lwp) WRITE(numout,*) 'nb_bdy = 0, NO OPEN BOUNDARIES APPLIED.' 143 ELSE 144 IF(lwp) WRITE(numout,*) 'Number of open boundary sets : ',nb_bdy 145 ENDIF 146 147 DO ib_bdy = 1,nb_bdy 148 IF(lwp) WRITE(numout,*) ' ' 149 IF(lwp) WRITE(numout,*) '------ Open boundary data set ',ib_bdy,'------' 150 151 IF( ln_coords_file(ib_bdy) ) THEN 152 IF(lwp) WRITE(numout,*) 'Boundary definition read from file '//TRIM(cn_coords_file(ib_bdy)) 153 ELSE 154 IF(lwp) WRITE(numout,*) 'Boundary defined in namelist.' 155 ENDIF 156 IF(lwp) WRITE(numout,*) 157 158 IF(lwp) WRITE(numout,*) 'Boundary conditions for barotropic solution: ' 159 SELECT CASE( nn_dyn2d(ib_bdy) ) 160 CASE( 0 ) ; IF(lwp) WRITE(numout,*) ' no open boundary condition' 161 CASE( 1 ) ; IF(lwp) WRITE(numout,*) ' Flow Relaxation Scheme' 162 CASE( 2 ) ; IF(lwp) WRITE(numout,*) ' Flather radiation condition' 163 CASE DEFAULT ; CALL ctl_stop( 'unrecognised value for nn_dyn2d' ) 164 END SELECT 165 IF( nn_dyn2d(ib_bdy) .gt. 0 ) THEN 166 SELECT CASE( nn_dyn2d_dta(ib_bdy) ) ! 167 CASE( 0 ) ; IF(lwp) WRITE(numout,*) ' initial state used for bdy data' 168 CASE( 1 ) ; IF(lwp) WRITE(numout,*) ' boundary data taken from file' 169 CASE( 2 ) ; IF(lwp) WRITE(numout,*) ' tidal harmonic forcing taken from file' 170 CASE( 3 ) ; IF(lwp) WRITE(numout,*) ' boundary data AND tidal harmonic forcing taken from files' 171 CASE DEFAULT ; CALL ctl_stop( 'nn_dyn2d_dta must be between 0 and 3' ) 172 END SELECT 173 ENDIF 174 IF(lwp) WRITE(numout,*) 175 176 IF(lwp) WRITE(numout,*) 'Boundary conditions for baroclinic velocities: ' 177 SELECT CASE( nn_dyn3d(ib_bdy) ) 178 CASE( 0 ) ; IF(lwp) WRITE(numout,*) ' no open boundary condition' 179 CASE( 1 ) ; IF(lwp) WRITE(numout,*) ' Flow Relaxation Scheme' 180 CASE DEFAULT ; CALL ctl_stop( 'unrecognised value for nn_dyn3d' ) 181 END SELECT 182 IF( nn_dyn3d(ib_bdy) .gt. 0 ) THEN 183 SELECT CASE( nn_dyn3d_dta(ib_bdy) ) ! 184 CASE( 0 ) ; IF(lwp) WRITE(numout,*) ' initial state used for bdy data' 185 CASE( 1 ) ; IF(lwp) WRITE(numout,*) ' boundary data taken from file' 186 CASE DEFAULT ; CALL ctl_stop( 'nn_dyn3d_dta must be 0 or 1' ) 187 END SELECT 188 ENDIF 189 IF(lwp) WRITE(numout,*) 190 191 IF(lwp) WRITE(numout,*) 'Boundary conditions for temperature and salinity: ' 192 SELECT CASE( nn_tra(ib_bdy) ) 193 CASE( 0 ) ; IF(lwp) WRITE(numout,*) ' no open boundary condition' 194 CASE( 1 ) ; IF(lwp) WRITE(numout,*) ' Flow Relaxation Scheme' 195 CASE DEFAULT ; CALL ctl_stop( 'unrecognised value for nn_tra' ) 196 END SELECT 197 IF( nn_tra(ib_bdy) .gt. 0 ) THEN 198 SELECT CASE( nn_tra_dta(ib_bdy) ) ! 199 CASE( 0 ) ; IF(lwp) WRITE(numout,*) ' initial state used for bdy data' 200 CASE( 1 ) ; IF(lwp) WRITE(numout,*) ' boundary data taken from file' 201 CASE DEFAULT ; CALL ctl_stop( 'nn_tra_dta must be 0 or 1' ) 202 END SELECT 203 ENDIF 204 IF(lwp) WRITE(numout,*) 205 206 #if defined key_lim2 207 IF(lwp) WRITE(numout,*) 'Boundary conditions for sea ice: ' 208 SELECT CASE( nn_ice_lim2(ib_bdy) ) 209 CASE( 0 ) ; IF(lwp) WRITE(numout,*) ' no open boundary condition' 210 CASE( 1 ) ; IF(lwp) WRITE(numout,*) ' Flow Relaxation Scheme' 211 CASE DEFAULT ; CALL ctl_stop( 'unrecognised value for nn_tra' ) 212 END SELECT 213 IF( nn_ice_lim2(ib_bdy) .gt. 0 ) THEN 214 SELECT CASE( nn_ice_lim2_dta(ib_bdy) ) ! 215 CASE( 0 ) ; IF(lwp) WRITE(numout,*) ' initial state used for bdy data' 216 CASE( 1 ) ; IF(lwp) WRITE(numout,*) ' boundary data taken from file' 217 CASE DEFAULT ; CALL ctl_stop( 'nn_ice_lim2_dta must be 0 or 1' ) 218 END SELECT 219 ENDIF 220 IF(lwp) WRITE(numout,*) 221 #endif 222 223 IF(lwp) WRITE(numout,*) 'Boundary rim width for the FRS scheme = ', nn_rimwidth(ib_bdy) 224 IF(lwp) WRITE(numout,*) 225 226 ENDDO 227 228 IF( ln_vol ) THEN ! check volume conservation (nn_volctl value) 229 IF(lwp) WRITE(numout,*) 'Volume correction applied at open boundaries' 230 IF(lwp) WRITE(numout,*) 231 SELECT CASE ( nn_volctl ) 111 232 CASE( 1 ) ; IF(lwp) WRITE(numout,*) ' The total volume will be constant' 112 233 CASE( 0 ) ; IF(lwp) WRITE(numout,*) ' The total volume will vary according to the surface E-P flux' 113 234 CASE DEFAULT ; CALL ctl_stop( 'nn_volctl must be 0 or 1' ) 114 END SELECT 115 IF(lwp) WRITE(numout,*) 116 ELSE 117 IF(lwp) WRITE(numout,*) 'No volume correction with unstructured open boundaries' 118 IF(lwp) WRITE(numout,*) 119 ENDIF 120 121 IF( ln_tides ) THEN 122 IF(lwp) WRITE(numout,*) 'Tidal harmonic forcing at unstructured open boundaries' 123 IF(lwp) WRITE(numout,*) 124 ENDIF 125 126 IF( ln_dyn_fla ) THEN 127 IF(lwp) WRITE(numout,*) 'Flather condition on U, V at unstructured open boundaries' 128 IF(lwp) WRITE(numout,*) 129 ENDIF 130 131 IF( ln_dyn_frs ) THEN 132 IF(lwp) WRITE(numout,*) 'FRS condition on U and V at unstructured open boundaries' 133 IF(lwp) WRITE(numout,*) 134 ENDIF 135 136 IF( ln_tra_frs ) THEN 137 IF(lwp) WRITE(numout,*) 'FRS condition on T & S fields at unstructured open boundaries' 138 IF(lwp) WRITE(numout,*) 139 ENDIF 140 141 IF( ln_ice_frs ) THEN 142 IF(lwp) WRITE(numout,*) 'FRS condition on ice fields at unstructured open boundaries' 143 IF(lwp) WRITE(numout,*) 144 ENDIF 145 146 IF( ln_tides ) CALL tide_init ! Read tides namelist 147 148 149 ! Read arrays defining unstructured open boundaries 235 END SELECT 236 IF(lwp) WRITE(numout,*) 237 ELSE 238 IF(lwp) WRITE(numout,*) 'No volume correction applied at open boundaries' 239 IF(lwp) WRITE(numout,*) 240 ENDIF 241 150 242 ! ------------------------------------------------- 243 ! Initialise indices arrays for open boundaries 244 ! ------------------------------------------------- 245 246 ! Work out global dimensions of boundary data 247 ! --------------------------------------------- 248 REWIND( numnam ) 249 DO ib_bdy = 1, nb_bdy 250 251 jpbdta = 1 252 IF( .NOT. ln_coords_file(ib_bdy) ) THEN ! Work out size of global arrays from namelist parameters 253 254 ! No REWIND here because may need to read more than one nambdy_index namelist. 255 READ ( numnam, nambdy_index ) 256 257 ! Automatic boundary definition: if nbdysegX = -1 258 ! set boundary to whole side of model domain. 259 IF( nbdysege == -1 ) THEN 260 nbdysege = 1 261 jpieob(1) = jpiglo - 1 262 jpjedt(1) = 2 263 jpjeft(1) = jpjglo - 1 264 ENDIF 265 IF( nbdysegw == -1 ) THEN 266 nbdysegw = 1 267 jpiwob(1) = 2 268 jpjwdt(1) = 2 269 jpjwft(1) = jpjglo - 1 270 ENDIF 271 IF( nbdysegn == -1 ) THEN 272 nbdysegn = 1 273 jpjnob(1) = jpjglo - 1 274 jpindt(1) = 2 275 jpinft(1) = jpiglo - 1 276 ENDIF 277 IF( nbdysegs == -1 ) THEN 278 nbdysegs = 1 279 jpjsob(1) = 2 280 jpisdt(1) = 2 281 jpisft(1) = jpiglo - 1 282 ENDIF 283 284 nblendta(:,ib_bdy) = 0 285 DO iseg = 1, nbdysege 286 igrd = 1 287 nblendta(igrd,ib_bdy) = nblendta(igrd,ib_bdy) + jpjeft(iseg) - jpjedt(iseg) + 1 288 igrd = 2 289 nblendta(igrd,ib_bdy) = nblendta(igrd,ib_bdy) + jpjeft(iseg) - jpjedt(iseg) + 1 290 igrd = 3 291 nblendta(igrd,ib_bdy) = nblendta(igrd,ib_bdy) + jpjeft(iseg) - jpjedt(iseg) 292 ENDDO 293 DO iseg = 1, nbdysegw 294 igrd = 1 295 nblendta(igrd,ib_bdy) = nblendta(igrd,ib_bdy) + jpjwft(iseg) - jpjwdt(iseg) + 1 296 igrd = 2 297 nblendta(igrd,ib_bdy) = nblendta(igrd,ib_bdy) + jpjwft(iseg) - jpjwdt(iseg) + 1 298 igrd = 3 299 nblendta(igrd,ib_bdy) = nblendta(igrd,ib_bdy) + jpjwft(iseg) - jpjwdt(iseg) 300 ENDDO 301 DO iseg = 1, nbdysegn 302 igrd = 1 303 nblendta(igrd,ib_bdy) = nblendta(igrd,ib_bdy) + jpinft(iseg) - jpindt(iseg) + 1 304 igrd = 2 305 nblendta(igrd,ib_bdy) = nblendta(igrd,ib_bdy) + jpinft(iseg) - jpindt(iseg) 306 igrd = 3 307 nblendta(igrd,ib_bdy) = nblendta(igrd,ib_bdy) + jpinft(iseg) - jpindt(iseg) + 1 308 ENDDO 309 DO iseg = 1, nbdysegs 310 igrd = 1 311 nblendta(igrd,ib_bdy) = nblendta(igrd,ib_bdy) + jpisft(iseg) - jpisdt(iseg) + 1 312 igrd = 2 313 nblendta(igrd,ib_bdy) = nblendta(igrd,ib_bdy) + jpisft(iseg) - jpisdt(iseg) 314 igrd = 3 315 nblendta(igrd,ib_bdy) = nblendta(igrd,ib_bdy) + jpisft(iseg) - jpisdt(iseg) + 1 316 ENDDO 317 318 nblendta(:,ib_bdy) = nblendta(:,ib_bdy) * nn_rimwidth(ib_bdy) 319 jpbdta = MAXVAL(nblendta(:,ib_bdy)) 320 321 322 ELSE ! Read size of arrays in boundary coordinates file. 323 324 325 CALL iom_open( cn_coords_file(ib_bdy), inum ) 326 jpbdta = 1 327 DO igrd = 1, jpbgrd 328 id_dummy = iom_varid( inum, 'nbi'//cgrid(igrd), kdimsz=kdimsz ) 329 nblendta(igrd,ib_bdy) = kdimsz(1) 330 jpbdta = MAX(jpbdta, kdimsz(1)) 331 ENDDO 332 333 ENDIF 334 335 ENDDO ! ib_bdy 336 337 ! Allocate arrays 338 !--------------- 339 ALLOCATE( nbidta(jpbdta, jpbgrd, nb_bdy), nbjdta(jpbdta, jpbgrd, nb_bdy), & 340 & nbrdta(jpbdta, jpbgrd, nb_bdy) ) 341 342 ALLOCATE( dta_global(jpbdta, 1, jpk) ) 343 344 ! Calculate global boundary index arrays or read in from file 345 !------------------------------------------------------------ 346 REWIND( numnam ) 347 DO ib_bdy = 1, nb_bdy 348 349 IF( .NOT. ln_coords_file(ib_bdy) ) THEN ! Calculate global index arrays from namelist parameters 350 351 ! No REWIND here because may need to read more than one nambdy_index namelist. 352 READ ( numnam, nambdy_index ) 353 354 ! Automatic boundary definition: if nbdysegX = -1 355 ! set boundary to whole side of model domain. 356 IF( nbdysege == -1 ) THEN 357 nbdysege = 1 358 jpieob(1) = jpiglo - 1 359 jpjedt(1) = 2 360 jpjeft(1) = jpjglo - 1 361 ENDIF 362 IF( nbdysegw == -1 ) THEN 363 nbdysegw = 1 364 jpiwob(1) = 2 365 jpjwdt(1) = 2 366 jpjwft(1) = jpjglo - 1 367 ENDIF 368 IF( nbdysegn == -1 ) THEN 369 nbdysegn = 1 370 jpjnob(1) = jpjglo - 1 371 jpindt(1) = 2 372 jpinft(1) = jpiglo - 1 373 ENDIF 374 IF( nbdysegs == -1 ) THEN 375 nbdysegs = 1 376 jpjsob(1) = 2 377 jpisdt(1) = 2 378 jpisft(1) = jpiglo - 1 379 ENDIF 380 381 ! ------------ T points ------------- 382 igrd = 1 383 icount = 0 384 DO ir = 1, nn_rimwidth(ib_bdy) 385 ! east 386 DO iseg = 1, nbdysege 387 DO ij = jpjedt(iseg), jpjeft(iseg) 388 icount = icount + 1 389 nbidta(icount, igrd, ib_bdy) = jpieob(iseg) - ir + 1 390 nbjdta(icount, igrd, ib_bdy) = ij 391 nbrdta(icount, igrd, ib_bdy) = ir 392 ENDDO 393 ENDDO 394 ! west 395 DO iseg = 1, nbdysegw 396 DO ij = jpjwdt(iseg), jpjwft(iseg) 397 icount = icount + 1 398 nbidta(icount, igrd, ib_bdy) = jpiwob(iseg) + ir - 1 399 nbjdta(icount, igrd, ib_bdy) = ij 400 nbrdta(icount, igrd, ib_bdy) = ir 401 ENDDO 402 ENDDO 403 ! north 404 DO iseg = 1, nbdysegn 405 DO ii = jpindt(iseg), jpinft(iseg) 406 icount = icount + 1 407 nbidta(icount, igrd, ib_bdy) = ii 408 nbjdta(icount, igrd, ib_bdy) = jpjnob(iseg) - ir + 1 409 nbrdta(icount, igrd, ib_bdy) = ir 410 ENDDO 411 ENDDO 412 ! south 413 DO iseg = 1, nbdysegs 414 DO ii = jpisdt(iseg), jpisft(iseg) 415 icount = icount + 1 416 nbidta(icount, igrd, ib_bdy) = ii 417 nbjdta(icount, igrd, ib_bdy) = jpjsob(iseg) + ir + 1 418 nbrdta(icount, igrd, ib_bdy) = ir 419 ENDDO 420 ENDDO 421 ENDDO 422 423 ! ------------ U points ------------- 424 igrd = 2 425 icount = 0 426 DO ir = 1, nn_rimwidth(ib_bdy) 427 ! east 428 DO iseg = 1, nbdysege 429 DO ij = jpjedt(iseg), jpjeft(iseg) 430 icount = icount + 1 431 nbidta(icount, igrd, ib_bdy) = jpieob(iseg) - ir 432 nbjdta(icount, igrd, ib_bdy) = ij 433 nbrdta(icount, igrd, ib_bdy) = ir 434 ENDDO 435 ENDDO 436 ! west 437 DO iseg = 1, nbdysegw 438 DO ij = jpjwdt(iseg), jpjwft(iseg) 439 icount = icount + 1 440 nbidta(icount, igrd, ib_bdy) = jpiwob(iseg) + ir - 1 441 nbjdta(icount, igrd, ib_bdy) = ij 442 nbrdta(icount, igrd, ib_bdy) = ir 443 ENDDO 444 ENDDO 445 ! north 446 DO iseg = 1, nbdysegn 447 DO ii = jpindt(iseg), jpinft(iseg) - 1 448 icount = icount + 1 449 nbidta(icount, igrd, ib_bdy) = ii 450 nbjdta(icount, igrd, ib_bdy) = jpjnob(iseg) - ir + 1 451 nbrdta(icount, igrd, ib_bdy) = ir 452 ENDDO 453 ENDDO 454 ! south 455 DO iseg = 1, nbdysegs 456 DO ii = jpisdt(iseg), jpisft(iseg) - 1 457 icount = icount + 1 458 nbidta(icount, igrd, ib_bdy) = ii 459 nbjdta(icount, igrd, ib_bdy) = jpjsob(iseg) + ir + 1 460 nbrdta(icount, igrd, ib_bdy) = ir 461 ENDDO 462 ENDDO 463 ENDDO 464 465 ! ------------ V points ------------- 466 igrd = 3 467 icount = 0 468 DO ir = 1, nn_rimwidth(ib_bdy) 469 ! east 470 DO iseg = 1, nbdysege 471 DO ij = jpjedt(iseg), jpjeft(iseg) - 1 472 icount = icount + 1 473 nbidta(icount, igrd, ib_bdy) = jpieob(iseg) - ir + 1 474 nbjdta(icount, igrd, ib_bdy) = ij 475 nbrdta(icount, igrd, ib_bdy) = ir 476 ENDDO 477 ENDDO 478 ! west 479 DO iseg = 1, nbdysegw 480 DO ij = jpjwdt(iseg), jpjwft(iseg) - 1 481 icount = icount + 1 482 nbidta(icount, igrd, ib_bdy) = jpiwob(iseg) + ir - 1 483 nbjdta(icount, igrd, ib_bdy) = ij 484 nbrdta(icount, igrd, ib_bdy) = ir 485 ENDDO 486 ENDDO 487 ! north 488 DO iseg = 1, nbdysegn 489 DO ii = jpindt(iseg), jpinft(iseg) 490 icount = icount + 1 491 nbidta(icount, igrd, ib_bdy) = ii 492 nbjdta(icount, igrd, ib_bdy) = jpjnob(iseg) - ir 493 nbrdta(icount, igrd, ib_bdy) = ir 494 ENDDO 495 ENDDO 496 ! south 497 DO iseg = 1, nbdysegs 498 DO ii = jpisdt(iseg), jpisft(iseg) 499 icount = icount + 1 500 nbidta(icount, igrd, ib_bdy) = ii 501 nbjdta(icount, igrd, ib_bdy) = jpjsob(iseg) + ir + 1 502 nbrdta(icount, igrd, ib_bdy) = ir 503 ENDDO 504 ENDDO 505 ENDDO 506 507 ELSE ! Read global index arrays from boundary coordinates file. 508 509 DO igrd = 1, jpbgrd 510 CALL iom_get( inum, jpdom_unknown, 'nbi'//cgrid(igrd), dta_global(1:nblendta(igrd,ib_bdy),:,1) ) 511 DO ii = 1,nblendta(igrd,ib_bdy) 512 nbidta(ii,igrd,ib_bdy) = INT( dta_global(ii,1,1) ) 513 END DO 514 CALL iom_get( inum, jpdom_unknown, 'nbj'//cgrid(igrd), dta_global(1:nblendta(igrd,ib_bdy),:,1) ) 515 DO ii = 1,nblendta(igrd,ib_bdy) 516 nbjdta(ii,igrd,ib_bdy) = INT( dta_global(ii,1,1) ) 517 END DO 518 CALL iom_get( inum, jpdom_unknown, 'nbr'//cgrid(igrd), dta_global(1:nblendta(igrd,ib_bdy),:,1) ) 519 DO ii = 1,nblendta(igrd,ib_bdy) 520 nbrdta(ii,igrd,ib_bdy) = INT( dta_global(ii,1,1) ) 521 END DO 522 523 ibr_max = MAXVAL( nbrdta(:,igrd,ib_bdy) ) 524 IF(lwp) WRITE(numout,*) 525 IF(lwp) WRITE(numout,*) ' Maximum rimwidth in file is ', ibr_max 526 IF(lwp) WRITE(numout,*) ' nn_rimwidth from namelist is ', nn_rimwidth(ib_bdy) 527 IF (ibr_max < nn_rimwidth(ib_bdy)) & 528 CALL ctl_stop( 'nn_rimwidth is larger than maximum rimwidth in file',cn_coords_file(ib_bdy) ) 529 530 END DO 531 CALL iom_close( inum ) 532 533 ENDIF 534 535 ENDDO 536 537 ! Work out dimensions of boundary data on each processor 538 ! ------------------------------------------------------ 539 540 iw = mig(1) + 1 ! if monotasking and no zoom, iw=2 541 ie = mig(1) + nlci-1 - 1 ! if monotasking and no zoom, ie=jpim1 542 is = mjg(1) + 1 ! if monotasking and no zoom, is=2 543 in = mjg(1) + nlcj-1 - 1 ! if monotasking and no zoom, in=jpjm1 544 545 DO ib_bdy = 1, nb_bdy 546 DO igrd = 1, jpbgrd 547 icount = 0 548 icountr = 0 549 idx_bdy(ib_bdy)%nblen(igrd) = 0 550 idx_bdy(ib_bdy)%nblenrim(igrd) = 0 551 DO ib = 1, nblendta(igrd,ib_bdy) 552 ! check that data is in correct order in file 553 ibm1 = MAX(1,ib-1) 554 IF(lwp) THEN ! Since all procs read global data only need to do this check on one proc... 555 IF( nbrdta(ib,igrd,ib_bdy) < nbrdta(ibm1,igrd,ib_bdy) ) THEN 556 CALL ctl_stop('bdy_init : ERROR : boundary data in file must be defined in order of distance from edge nbr.', & 557 'A utility for re-ordering boundary coordinates and data files exists in the TOOLS/OBC directory') 558 ENDIF 559 ENDIF 560 ! check if point is in local domain 561 IF( nbidta(ib,igrd,ib_bdy) >= iw .AND. nbidta(ib,igrd,ib_bdy) <= ie .AND. & 562 & nbjdta(ib,igrd,ib_bdy) >= is .AND. nbjdta(ib,igrd,ib_bdy) <= in ) THEN 563 ! 564 icount = icount + 1 565 ! 566 IF( nbrdta(ib,igrd,ib_bdy) == 1 ) icountr = icountr+1 567 ENDIF 568 ENDDO 569 idx_bdy(ib_bdy)%nblenrim(igrd) = icountr !: length of rim boundary data on each proc 570 idx_bdy(ib_bdy)%nblen (igrd) = icount !: length of boundary data on each proc 571 ENDDO ! igrd 572 573 ! Allocate index arrays for this boundary set 574 !-------------------------------------------- 575 ilen1 = MAXVAL(idx_bdy(ib_bdy)%nblen(:)) 576 ALLOCATE( idx_bdy(ib_bdy)%nbi(ilen1,jpbgrd) ) 577 ALLOCATE( idx_bdy(ib_bdy)%nbj(ilen1,jpbgrd) ) 578 ALLOCATE( idx_bdy(ib_bdy)%nbr(ilen1,jpbgrd) ) 579 ALLOCATE( idx_bdy(ib_bdy)%nbmap(ilen1,jpbgrd) ) 580 ALLOCATE( idx_bdy(ib_bdy)%nbw(ilen1,jpbgrd) ) 581 ALLOCATE( idx_bdy(ib_bdy)%flagu(ilen1) ) 582 ALLOCATE( idx_bdy(ib_bdy)%flagv(ilen1) ) 583 584 ! Dispatch mapping indices and discrete distances on each processor 585 ! ----------------------------------------------------------------- 586 587 DO igrd = 1, jpbgrd 588 icount = 0 589 ! Loop on rimwidth to ensure outermost points come first in the local arrays. 590 DO ir=1, nn_rimwidth(ib_bdy) 591 DO ib = 1, nblendta(igrd,ib_bdy) 592 ! check if point is in local domain and equals ir 593 IF( nbidta(ib,igrd,ib_bdy) >= iw .AND. nbidta(ib,igrd,ib_bdy) <= ie .AND. & 594 & nbjdta(ib,igrd,ib_bdy) >= is .AND. nbjdta(ib,igrd,ib_bdy) <= in .AND. & 595 & nbrdta(ib,igrd,ib_bdy) == ir ) THEN 596 ! 597 icount = icount + 1 598 idx_bdy(ib_bdy)%nbi(icount,igrd) = nbidta(ib,igrd,ib_bdy)- mig(1)+1 599 idx_bdy(ib_bdy)%nbj(icount,igrd) = nbjdta(ib,igrd,ib_bdy)- mjg(1)+1 600 idx_bdy(ib_bdy)%nbr(icount,igrd) = nbrdta(ib,igrd,ib_bdy) 601 idx_bdy(ib_bdy)%nbmap(icount,igrd) = ib 602 ENDIF 603 ENDDO 604 ENDDO 605 ENDDO 606 607 ! Compute rim weights for FRS scheme 608 ! ---------------------------------- 609 DO igrd = 1, jpbgrd 610 DO ib = 1, idx_bdy(ib_bdy)%nblen(igrd) 611 nbr => idx_bdy(ib_bdy)%nbr(ib,igrd) 612 idx_bdy(ib_bdy)%nbw(ib,igrd) = 1.- TANH( FLOAT( nbr - 1 ) *0.5 ) ! tanh formulation 613 ! idx_bdy(ib_bdy)%nbw(ib,igrd) = (FLOAT(nn_rimwidth+1-nbr)/FLOAT(nn_rimwidth))**2 ! quadratic 614 ! idx_bdy(ib_bdy)%nbw(ib,igrd) = FLOAT(nn_rimwidth+1-nbr)/FLOAT(nn_rimwidth) ! linear 615 END DO 616 END DO 617 618 ENDDO 619 620 ! ------------------------------------------------------ 621 ! Initialise masks and find normal/tangential directions 622 ! ------------------------------------------------------ 151 623 152 624 ! Read global 2D mask at T-points: bdytmask 153 ! *****************************************625 ! ----------------------------------------- 154 626 ! bdytmask = 1 on the computational domain AND on open boundaries 155 627 ! = 0 elsewhere … … 158 630 zmask( : ,:) = 0.e0 159 631 zmask(jpizoom+1:jpizoom+jpiglo-2,:) = 1.e0 160 ELSE IF( ln_mask ) THEN161 CALL iom_open( cn_mask , inum )632 ELSE IF( ln_mask_file ) THEN 633 CALL iom_open( cn_mask_file, inum ) 162 634 CALL iom_get ( inum, jpdom_data, 'bdy_msk', zmask(:,:) ) 163 635 CALL iom_close( inum ) … … 184 656 185 657 186 ! Read discrete distance and mapping indices187 ! ******************************************188 nbidta(:,:) = 0.e0189 nbjdta(:,:) = 0.e0190 nbrdta(:,:) = 0.e0191 192 IF( cp_cfg == "eel" .AND. jp_cfg == 5 ) THEN193 icount = 0194 DO ir = 1, nn_rimwidth ! Define west boundary (from ii=2 to ii=1+nn_rimwidth):195 DO ij = 3, jpjglo-2196 icount = icount + 1197 nbidta(icount,:) = ir + 1 + (jpizoom-1)198 nbjdta(icount,:) = ij + (jpjzoom-1)199 nbrdta(icount,:) = ir200 END DO201 END DO202 !203 DO ir = 1, nn_rimwidth ! Define east boundary (from ii=jpiglo-1 to ii=jpiglo-nn_rimwidth):204 DO ij=3,jpjglo-2205 icount = icount + 1206 nbidta(icount,:) = jpiglo-ir + (jpizoom-1)207 nbidta(icount,2) = jpiglo-ir-1 + (jpizoom-1) ! special case for u points208 nbjdta(icount,:) = ij + (jpjzoom-1)209 nbrdta(icount,:) = ir210 END DO211 END DO212 !213 ELSE ! Read indices and distances in unstructured boundary data files214 !215 IF( ln_tides ) THEN ! Read tides input files for preference in case there are no bdydata files216 clfile(4) = TRIM(filtide)//TRIM(tide_cpt(1))//'_grid_T.nc'217 clfile(5) = TRIM(filtide)//TRIM(tide_cpt(1))//'_grid_U.nc'218 clfile(6) = TRIM(filtide)//TRIM(tide_cpt(1))//'_grid_V.nc'219 ENDIF220 IF( ln_dyn_fla .AND. .NOT. ln_tides ) THEN221 clfile(4) = cn_dta_fla_T222 clfile(5) = cn_dta_fla_U223 clfile(6) = cn_dta_fla_V224 ENDIF225 226 IF( ln_tra_frs ) THEN227 clfile(1) = cn_dta_frs_T228 IF( .NOT. ln_dyn_frs ) THEN229 clfile(2) = cn_dta_frs_T ! Dummy read re read T file for sake of 6 files230 clfile(3) = cn_dta_frs_T !231 ENDIF232 ENDIF233 IF( ln_dyn_frs ) THEN234 IF( .NOT. ln_tra_frs ) clfile(1) = cn_dta_frs_U ! Dummy Read235 clfile(2) = cn_dta_frs_U236 clfile(3) = cn_dta_frs_V237 ENDIF238 239 ! ! how many files are we to read in?240 IF(ln_tides .OR. ln_dyn_fla) igrd_start = 4241 !242 IF(ln_tra_frs ) THEN ; igrd_start = 1243 ELSEIF(ln_dyn_frs) THEN ; igrd_start = 2244 ENDIF245 !246 IF( ln_tra_frs ) igrd_end = 1247 !248 IF(ln_dyn_fla .OR. ln_tides) THEN ; igrd_end = 6249 ELSEIF( ln_dyn_frs ) THEN ; igrd_end = 3250 ENDIF251 252 DO igrd = igrd_start, igrd_end253 CALL iom_open( clfile(igrd), inum )254 id_dummy = iom_varid( inum, 'nbidta', kdimsz=kdimsz )255 IF(lwp) WRITE(numout,*) 'kdimsz : ',kdimsz256 ib_len = kdimsz(1)257 IF( ib_len > jpbdta) CALL ctl_stop( 'Boundary data array in file too long.', &258 & 'File :', TRIM(clfile(igrd)),'increase parameter jpbdta.' )259 260 CALL iom_get( inum, jpdom_unknown, 'nbidta', zdta(1:ib_len,:) )261 DO ii = 1,ib_len262 nbidta(ii,igrd) = INT( zdta(ii,1) )263 END DO264 CALL iom_get( inum, jpdom_unknown, 'nbjdta', zdta(1:ib_len,:) )265 DO ii = 1,ib_len266 nbjdta(ii,igrd) = INT( zdta(ii,1) )267 END DO268 CALL iom_get( inum, jpdom_unknown, 'nbrdta', zdta(1:ib_len,:) )269 DO ii = 1,ib_len270 nbrdta(ii,igrd) = INT( zdta(ii,1) )271 END DO272 CALL iom_close( inum )273 274 IF( igrd < 4) THEN ! Check that rimwidth in file is big enough for Frs case(barotropic is one):275 ibr_max = MAXVAL( nbrdta(:,igrd) )276 IF(lwp) WRITE(numout,*)277 IF(lwp) WRITE(numout,*) ' Maximum rimwidth in file is ', ibr_max278 IF(lwp) WRITE(numout,*) ' nn_rimwidth from namelist is ', nn_rimwidth279 IF (ibr_max < nn_rimwidth) CALL ctl_stop( 'nn_rimwidth is larger than maximum rimwidth in file' )280 ENDIF !Check igrd < 4281 !282 END DO283 !284 ENDIF285 286 ! Dispatch mapping indices and discrete distances on each processor287 ! *****************************************************************288 289 iw = mig(1) + 1 ! if monotasking and no zoom, iw=2290 ie = mig(1) + nlci-1 - 1 ! if monotasking and no zoom, ie=jpim1291 is = mjg(1) + 1 ! if monotasking and no zoom, is=2292 in = mjg(1) + nlcj-1 - 1 ! if monotasking and no zoom, in=jpjm1293 294 DO igrd = igrd_start, igrd_end295 icount = 0296 icountr = 0297 nblen (igrd) = 0298 nblenrim(igrd) = 0299 nblendta(igrd) = 0300 DO ir=1, nn_rimwidth301 DO ib = 1, jpbdta302 ! check if point is in local domain and equals ir303 IF( nbidta(ib,igrd) >= iw .AND. nbidta(ib,igrd) <= ie .AND. &304 & nbjdta(ib,igrd) >= is .AND. nbjdta(ib,igrd) <= in .AND. &305 & nbrdta(ib,igrd) == ir ) THEN306 !307 icount = icount + 1308 !309 IF( ir == 1 ) icountr = icountr+1310 IF (icount > jpbdim) THEN311 IF(lwp) WRITE(numout,*) 'bdy_ini: jpbdim too small'312 nstop = nstop + 1313 ELSE314 nbi(icount, igrd) = nbidta(ib,igrd)- mig(1)+1315 nbj(icount, igrd) = nbjdta(ib,igrd)- mjg(1)+1316 nbr(icount, igrd) = nbrdta(ib,igrd)317 nbmap(icount,igrd) = ib318 ENDIF319 ENDIF320 END DO321 END DO322 nblenrim(igrd) = icountr !: length of rim boundary data on each proc323 nblen (igrd) = icount !: length of boundary data on each proc324 END DO325 326 ! Compute rim weights327 ! -------------------328 DO igrd = igrd_start, igrd_end329 DO ib = 1, nblen(igrd)330 nbw(ib,igrd) = 1.- TANH( FLOAT( nbr(ib,igrd) - 1 ) *0.5 ) ! tanh formulation331 ! nbw(ib,igrd) = (FLOAT(nn_rimwidth+1-nbr(ib,igrd))/FLOAT(nn_rimwidth))**2 ! quadratic332 ! nbw(ib,igrd) = FLOAT(nn_rimwidth+1-nbr(ib,igrd))/FLOAT(nn_rimwidth) ! linear333 END DO334 END DO335 336 658 ! Mask corrections 337 659 ! ---------------- … … 361 683 ! bdy masks and bmask are now set to zero on boundary points: 362 684 igrd = 1 ! In the free surface case, bmask is at T-points 363 DO ib = 1, nblenrim(igrd) 364 bmask(nbi(ib,igrd), nbj(ib,igrd)) = 0.e0 365 END DO 685 DO ib_bdy = 1, nb_bdy 686 DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd) 687 bmask(idx_bdy(ib_bdy)%nbi(ib,igrd), idx_bdy(ib_bdy)%nbj(ib,igrd)) = 0.e0 688 ENDDO 689 ENDDO 366 690 ! 367 691 igrd = 1 368 DO ib = 1, nblenrim(igrd) 369 bdytmask(nbi(ib,igrd), nbj(ib,igrd)) = 0.e0 370 END DO 692 DO ib_bdy = 1, nb_bdy 693 DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd) 694 bdytmask(idx_bdy(ib_bdy)%nbi(ib,igrd), idx_bdy(ib_bdy)%nbj(ib,igrd)) = 0.e0 695 ENDDO 696 ENDDO 371 697 ! 372 698 igrd = 2 373 DO ib = 1, nblenrim(igrd) 374 bdyumask(nbi(ib,igrd), nbj(ib,igrd)) = 0.e0 375 END DO 699 DO ib_bdy = 1, nb_bdy 700 DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd) 701 bdyumask(idx_bdy(ib_bdy)%nbi(ib,igrd), idx_bdy(ib_bdy)%nbj(ib,igrd)) = 0.e0 702 ENDDO 703 ENDDO 376 704 ! 377 705 igrd = 3 378 DO ib = 1, nblenrim(igrd) 379 bdyvmask(nbi(ib,igrd), nbj(ib,igrd)) = 0.e0 380 END DO 706 DO ib_bdy = 1, nb_bdy 707 DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd) 708 bdyvmask(idx_bdy(ib_bdy)%nbi(ib,igrd), idx_bdy(ib_bdy)%nbj(ib,igrd)) = 0.e0 709 ENDDO 710 ENDDO 381 711 382 712 ! Lateral boundary conditions … … 384 714 CALL lbc_lnk( bdyumask(:,:), 'U', 1. ) ; CALL lbc_lnk( bdyvmask(:,:), 'V', 1. ) 385 715 386 IF( ln_vol .OR. ln_dyn_fla ) THEN ! Indices and directions of rim velocity components 387 ! 716 DO ib_bdy = 1, nb_bdy ! Indices and directions of rim velocity components 717 718 idx_bdy(ib_bdy)%flagu(:) = 0.e0 719 idx_bdy(ib_bdy)%flagv(:) = 0.e0 720 icount = 0 721 388 722 !flagu = -1 : u component is normal to the dynamical boundary but its direction is outward 389 723 !flagu = 0 : u is tangential 390 724 !flagu = 1 : u is normal to the boundary and is direction is inward 391 icount = 0 392 flagu(:) = 0.e0 393 725 394 726 igrd = 2 ! u-component 395 DO ib = 1, nblenrim(igrd) 396 zefl=bdytmask(nbi(ib,igrd) , nbj(ib,igrd)) 397 zwfl=bdytmask(nbi(ib,igrd)+1, nbj(ib,igrd)) 398 IF( zefl + zwfl ==2 ) THEN 399 icount = icount +1 727 DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd) 728 nbi => idx_bdy(ib_bdy)%nbi(ib,igrd) 729 nbj => idx_bdy(ib_bdy)%nbj(ib,igrd) 730 zefl = bdytmask(nbi ,nbj) 731 zwfl = bdytmask(nbi+1,nbj) 732 IF( zefl + zwfl == 2 ) THEN 733 icount = icount + 1 400 734 ELSE 401 flagu(ib)=-zefl+zwfl735 idx_bdy(ib_bdy)%flagu(ib)=-zefl+zwfl 402 736 ENDIF 403 737 END DO … … 406 740 !flagv = 0 : u is tangential 407 741 !flagv = 1 : u is normal to the boundary and is direction is inward 408 flagv(:) = 0.e0409 742 410 743 igrd = 3 ! v-component 411 DO ib = 1, nblenrim(igrd) 412 znfl = bdytmask(nbi(ib,igrd), nbj(ib,igrd)) 413 zsfl = bdytmask(nbi(ib,igrd), nbj(ib,igrd)+1) 414 IF( znfl + zsfl ==2 ) THEN 744 DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd) 745 nbi => idx_bdy(ib_bdy)%nbi(ib,igrd) 746 nbj => idx_bdy(ib_bdy)%nbj(ib,igrd) 747 znfl = bdytmask(nbi,nbj ) 748 zsfl = bdytmask(nbi,nbj+1) 749 IF( znfl + zsfl == 2 ) THEN 415 750 icount = icount + 1 416 751 ELSE 417 flagv(ib) = -znfl + zsfl752 idx_bdy(ib_bdy)%flagv(ib) = -znfl + zsfl 418 753 END IF 419 754 END DO … … 422 757 IF(lwp) WRITE(numout,*) 423 758 IF(lwp) WRITE(numout,*) ' E R R O R : Some data velocity points,', & 424 ' are not boundary points. Check nbi, nbj, indices .'759 ' are not boundary points. Check nbi, nbj, indices for boundary set ',ib_bdy 425 760 IF(lwp) WRITE(numout,*) ' ========== ' 426 761 IF(lwp) WRITE(numout,*) … … 428 763 ENDIF 429 764 430 END IF765 ENDDO 431 766 432 767 ! Compute total lateral surface for volume correction: … … 435 770 IF( ln_vol ) THEN 436 771 igrd = 2 ! Lateral surface at U-points 437 DO ib = 1, nblenrim(igrd) 438 bdysurftot = bdysurftot + hu (nbi(ib,igrd) ,nbj(ib,igrd)) & 439 & * e2u (nbi(ib,igrd) ,nbj(ib,igrd)) * ABS( flagu(ib) ) & 440 & * tmask_i(nbi(ib,igrd) ,nbj(ib,igrd)) & 441 & * tmask_i(nbi(ib,igrd)+1,nbj(ib,igrd)) 442 END DO 772 DO ib_bdy = 1, nb_bdy 773 DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd) 774 nbi => idx_bdy(ib_bdy)%nbi(ib,igrd) 775 nbj => idx_bdy(ib_bdy)%nbi(ib,igrd) 776 flagu => idx_bdy(ib_bdy)%flagu(ib) 777 bdysurftot = bdysurftot + hu (nbi , nbj) & 778 & * e2u (nbi , nbj) * ABS( flagu ) & 779 & * tmask_i(nbi , nbj) & 780 & * tmask_i(nbi+1, nbj) 781 ENDDO 782 ENDDO 443 783 444 784 igrd=3 ! Add lateral surface at V-points 445 DO ib = 1, nblenrim(igrd) 446 bdysurftot = bdysurftot + hv (nbi(ib,igrd),nbj(ib,igrd) ) & 447 & * e1v (nbi(ib,igrd),nbj(ib,igrd) ) * ABS( flagv(ib) ) & 448 & * tmask_i(nbi(ib,igrd),nbj(ib,igrd) ) & 449 & * tmask_i(nbi(ib,igrd),nbj(ib,igrd)+1) 450 END DO 785 DO ib_bdy = 1, nb_bdy 786 DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd) 787 nbi => idx_bdy(ib_bdy)%nbi(ib,igrd) 788 nbj => idx_bdy(ib_bdy)%nbi(ib,igrd) 789 flagv => idx_bdy(ib_bdy)%flagv(ib) 790 bdysurftot = bdysurftot + hv (nbi, nbj ) & 791 & * e1v (nbi, nbj ) * ABS( flagv ) & 792 & * tmask_i(nbi, nbj ) & 793 & * tmask_i(nbi, nbj+1) 794 ENDDO 795 ENDDO 451 796 ! 452 797 IF( lk_mpp ) CALL mpp_sum( bdysurftot ) ! sum over the global domain 453 798 END IF 454 455 ! Initialise bdy data arrays456 ! --------------------------457 tbdy(:,:) = 0.e0458 sbdy(:,:) = 0.e0459 ubdy(:,:) = 0.e0460 vbdy(:,:) = 0.e0461 sshbdy(:) = 0.e0462 ubtbdy(:) = 0.e0463 vbtbdy(:) = 0.e0464 #if defined key_lim2465 frld_bdy(:) = 0.e0466 hicif_bdy(:) = 0.e0467 hsnif_bdy(:) = 0.e0468 #endif469 470 ! Read in tidal constituents and adjust for model start time471 ! ----------------------------------------------------------472 IF( ln_tides ) CALL tide_data473 799 ! 800 ! Tidy up 801 !-------- 802 DEALLOCATE(nbidta, nbjdta, nbrdta) 803 804 IF( nn_timing == 1 ) CALL timing_stop('bdy_init') 805 474 806 END SUBROUTINE bdy_init 475 807 476 808 #else 477 809 !!--------------------------------------------------------------------------------- 478 !! Dummy module NO unstructuredopen boundaries810 !! Dummy module NO open boundaries 479 811 !!--------------------------------------------------------------------------------- 480 812 CONTAINS -
trunk/NEMOGCM/NEMO/OPA_SRC/BDY/bdytides.F90
r2528 r3294 8 8 !! 3.0 ! 2008-04 (NEMO team) add in the reference version 9 9 !! 3.3 ! 2010-09 (D.Storkey and E.O'Dea) bug fixes 10 !! 3.4 ! 2011 (D. Storkey) rewrite in preparation for OBC-BDY merge 10 11 !!---------------------------------------------------------------------- 11 12 #if defined key_bdy 12 13 !!---------------------------------------------------------------------- 13 !! 'key_bdy' UnstructuredOpen Boundary Condition14 !! 'key_bdy' Open Boundary Condition 14 15 !!---------------------------------------------------------------------- 15 16 !! PUBLIC 16 !! tide_init : read of namelist 17 !! tide_data : read in and initialisation of tidal constituents at boundary 17 !! tide_init : read of namelist and initialisation of tidal harmonics data 18 18 !! tide_update : calculation of tidal forcing at each timestep 19 19 !! PRIVATE … … 24 24 !! vset :/ 25 25 !!---------------------------------------------------------------------- 26 USE timing ! Timing 26 27 USE oce ! ocean dynamics and tracers 27 28 USE dom_oce ! ocean space and time domain … … 33 34 USE bdy_oce ! ocean open boundary conditions 34 35 USE daymod ! calendar 36 USE fldread, ONLY: fld_map 35 37 36 38 IMPLICIT NONE 37 39 PRIVATE 38 40 39 PUBLIC tide_init ! routine called in bdyini 40 PUBLIC tide_data ! routine called in bdyini 41 PUBLIC tide_init ! routine called in nemo_init 41 42 PUBLIC tide_update ! routine called in bdydyn 42 43 43 LOGICAL, PUBLIC :: ln_tide_date !: =T correct tide phases and amplitude for model start date 44 INTEGER, PUBLIC, PARAMETER :: jptides_max = 15 !: Max number of tidal contituents 45 INTEGER, PUBLIC :: ntide !: Actual number of tidal constituents 46 47 CHARACTER(len=80), PUBLIC :: filtide !: Filename root for tidal input files 48 CHARACTER(len= 4), PUBLIC, DIMENSION(jptides_max) :: tide_cpt !: Names of tidal components used. 49 50 INTEGER , PUBLIC, DIMENSION(jptides_max) :: nindx !: ??? 51 REAL(wp), PUBLIC, DIMENSION(jptides_max) :: tide_speed !: Phase speed of tidal constituent (deg/hr) 52 53 REAL(wp), DIMENSION(jpbdim,jptides_max) :: ssh1, ssh2 ! Tidal constituents : SSH 54 REAL(wp), DIMENSION(jpbdim,jptides_max) :: u1 , u2 ! Tidal constituents : U 55 REAL(wp), DIMENSION(jpbdim,jptides_max) :: v1 , v2 ! Tidal constituents : V 44 TYPE, PUBLIC :: TIDES_DATA !: Storage for external tidal harmonics data 45 INTEGER :: ncpt !: Actual number of tidal components 46 REAL(wp), POINTER, DIMENSION(:) :: speed !: Phase speed of tidal constituent (deg/hr) 47 REAL(wp), POINTER, DIMENSION(:,:,:) :: ssh !: Tidal constituents : SSH 48 REAL(wp), POINTER, DIMENSION(:,:,:) :: u !: Tidal constituents : U 49 REAL(wp), POINTER, DIMENSION(:,:,:) :: v !: Tidal constituents : V 50 END TYPE TIDES_DATA 51 52 INTEGER, PUBLIC, PARAMETER :: jptides_max = 15 !: Max number of tidal contituents 53 54 TYPE(TIDES_DATA), PUBLIC, DIMENSION(jp_bdy), TARGET :: tides !: External tidal harmonics data 56 55 57 56 !!---------------------------------------------------------------------- … … 66 65 !! *** SUBROUTINE tide_init *** 67 66 !! 68 !! ** Purpose : - Read in namelist for tides 69 !! 70 !!---------------------------------------------------------------------- 71 INTEGER :: itide ! dummy loop index 67 !! ** Purpose : - Read in namelist for tides and initialise external 68 !! tidal harmonics data 69 !! 70 !!---------------------------------------------------------------------- 71 !! namelist variables 72 !!------------------- 73 LOGICAL :: ln_tide_date !: =T correct tide phases and amplitude for model start date 74 CHARACTER(len=80) :: filtide !: Filename root for tidal input files 75 CHARACTER(len= 4), DIMENSION(jptides_max) :: tide_cpt !: Names of tidal components used. 76 REAL(wp), DIMENSION(jptides_max) :: tide_speed !: Phase speed of tidal constituent (deg/hr) 77 !! 78 INTEGER, DIMENSION(jptides_max) :: nindx !: index of pre-set tidal components 79 INTEGER :: ib_bdy, itide, ib !: dummy loop indices 80 INTEGER :: inum, igrd 81 INTEGER, DIMENSION(3) :: ilen0 !: length of boundary data (from OBC arrays) 82 CHARACTER(len=80) :: clfile !: full file name for tidal input file 83 REAL(wp) :: z_arg, z_atde, z_btde, z1t, z2t 84 REAL(wp),DIMENSION(jptides_max) :: z_vplu, z_ftc 85 REAL(wp),ALLOCATABLE, DIMENSION(:,:,:) :: dta_read !: work space to read in tidal harmonics data 86 !! 87 TYPE(TIDES_DATA), POINTER :: td !: local short cut 72 88 !! 73 89 NAMELIST/nambdy_tide/ln_tide_date, filtide, tide_cpt, tide_speed 74 90 !!---------------------------------------------------------------------- 91 92 IF( nn_timing == 1 ) CALL timing_start('tide_init') 75 93 76 94 IF(lwp) WRITE(numout,*) … … 78 96 IF(lwp) WRITE(numout,*) '~~~~~~~~~' 79 97 80 ! Namelist nambdy_tide : tidal harmonic forcing at open boundaries 81 ln_tide_date = .false. 82 filtide(:) = '' 83 tide_speed(:) = 0.0 84 tide_cpt(:) = '' 85 REWIND( numnam ) ! Read namelist parameters 86 READ ( numnam, nambdy_tide ) 87 ! ! Count number of components specified 88 ntide = jptides_max 89 DO itide = 1, jptides_max 90 IF( tide_cpt(itide) == '' ) THEN 91 ntide = itide-1 92 exit 93 ENDIF 94 END DO 95 96 ! ! find constituents in standard list 97 DO itide = 1, ntide 98 nindx(itide) = 0 99 IF( TRIM( tide_cpt(itide) ) == 'Q1' ) nindx(itide) = 1 100 IF( TRIM( tide_cpt(itide) ) == 'O1' ) nindx(itide) = 2 101 IF( TRIM( tide_cpt(itide) ) == 'P1' ) nindx(itide) = 3 102 IF( TRIM( tide_cpt(itide) ) == 'S1' ) nindx(itide) = 4 103 IF( TRIM( tide_cpt(itide) ) == 'K1' ) nindx(itide) = 5 104 IF( TRIM( tide_cpt(itide) ) == '2N2' ) nindx(itide) = 6 105 IF( TRIM( tide_cpt(itide) ) == 'MU2' ) nindx(itide) = 7 106 IF( TRIM( tide_cpt(itide) ) == 'N2' ) nindx(itide) = 8 107 IF( TRIM( tide_cpt(itide) ) == 'NU2' ) nindx(itide) = 9 108 IF( TRIM( tide_cpt(itide) ) == 'M2' ) nindx(itide) = 10 109 IF( TRIM( tide_cpt(itide) ) == 'L2' ) nindx(itide) = 11 110 IF( TRIM( tide_cpt(itide) ) == 'T2' ) nindx(itide) = 12 111 IF( TRIM( tide_cpt(itide) ) == 'S2' ) nindx(itide) = 13 112 IF( TRIM( tide_cpt(itide) ) == 'K2' ) nindx(itide) = 14 113 IF( TRIM( tide_cpt(itide) ) == 'M4' ) nindx(itide) = 15 114 IF( nindx(itide) == 0 .AND. lwp ) THEN 115 WRITE(ctmp1,*) 'constitunent', itide,':', tide_cpt(itide), 'not in standard list' 116 CALL ctl_warn( ctmp1 ) 117 ENDIF 118 END DO 119 ! ! Parameter control and print 120 IF( ntide < 1 ) THEN 121 CALL ctl_stop( ' Did not find any tidal components in namelist nambdy_tide' ) 122 ELSE 123 IF(lwp) WRITE(numout,*) ' Namelist nambdy_tide : tidal harmonic forcing at open boundaries' 124 IF(lwp) WRITE(numout,*) ' tidal components specified ', ntide 125 IF(lwp) WRITE(numout,*) ' ', tide_cpt(1:ntide) 126 IF(lwp) WRITE(numout,*) ' associated phase speeds (deg/hr) : ' 127 IF(lwp) WRITE(numout,*) ' ', tide_speed(1:ntide) 128 ENDIF 129 130 ! Initialisation of tidal harmonics arrays 131 sshtide(:) = 0.e0 132 utide (:) = 0.e0 133 vtide (:) = 0.e0 134 ! 98 REWIND(numnam) 99 DO ib_bdy = 1, nb_bdy 100 IF( nn_dyn2d_dta(ib_bdy) .ge. 2 ) THEN 101 102 td => tides(ib_bdy) 103 104 ! Namelist nambdy_tide : tidal harmonic forcing at open boundaries 105 ln_tide_date = .false. 106 filtide(:) = '' 107 tide_speed(:) = 0.0 108 tide_cpt(:) = '' 109 110 ! Don't REWIND here - may need to read more than one of these namelists. 111 READ ( numnam, nambdy_tide ) 112 ! ! Count number of components specified 113 td%ncpt = 0 114 DO itide = 1, jptides_max 115 IF( tide_cpt(itide) /= '' ) THEN 116 td%ncpt = td%ncpt + 1 117 ENDIF 118 END DO 119 120 ! Fill in phase speeds from namelist 121 ALLOCATE( td%speed(td%ncpt) ) 122 td%speed = tide_speed(1:td%ncpt) 123 124 ! Find constituents in standard list 125 DO itide = 1, td%ncpt 126 nindx(itide) = 0 127 IF( TRIM( tide_cpt(itide) ) == 'Q1' ) nindx(itide) = 1 128 IF( TRIM( tide_cpt(itide) ) == 'O1' ) nindx(itide) = 2 129 IF( TRIM( tide_cpt(itide) ) == 'P1' ) nindx(itide) = 3 130 IF( TRIM( tide_cpt(itide) ) == 'S1' ) nindx(itide) = 4 131 IF( TRIM( tide_cpt(itide) ) == 'K1' ) nindx(itide) = 5 132 IF( TRIM( tide_cpt(itide) ) == '2N2' ) nindx(itide) = 6 133 IF( TRIM( tide_cpt(itide) ) == 'MU2' ) nindx(itide) = 7 134 IF( TRIM( tide_cpt(itide) ) == 'N2' ) nindx(itide) = 8 135 IF( TRIM( tide_cpt(itide) ) == 'NU2' ) nindx(itide) = 9 136 IF( TRIM( tide_cpt(itide) ) == 'M2' ) nindx(itide) = 10 137 IF( TRIM( tide_cpt(itide) ) == 'L2' ) nindx(itide) = 11 138 IF( TRIM( tide_cpt(itide) ) == 'T2' ) nindx(itide) = 12 139 IF( TRIM( tide_cpt(itide) ) == 'S2' ) nindx(itide) = 13 140 IF( TRIM( tide_cpt(itide) ) == 'K2' ) nindx(itide) = 14 141 IF( TRIM( tide_cpt(itide) ) == 'M4' ) nindx(itide) = 15 142 IF( nindx(itide) == 0 .AND. lwp ) THEN 143 WRITE(ctmp1,*) 'constitunent', itide,':', tide_cpt(itide), 'not in standard list' 144 CALL ctl_warn( ctmp1 ) 145 ENDIF 146 END DO 147 ! ! Parameter control and print 148 IF( td%ncpt < 1 ) THEN 149 CALL ctl_stop( ' Did not find any tidal components in namelist nambdy_tide' ) 150 ELSE 151 IF(lwp) WRITE(numout,*) ' Namelist nambdy_tide : tidal harmonic forcing at open boundaries' 152 IF(lwp) WRITE(numout,*) ' tidal components specified ', td%ncpt 153 IF(lwp) WRITE(numout,*) ' ', tide_cpt(1:td%ncpt) 154 IF(lwp) WRITE(numout,*) ' associated phase speeds (deg/hr) : ' 155 IF(lwp) WRITE(numout,*) ' ', tide_speed(1:td%ncpt) 156 ENDIF 157 158 159 ! Allocate space for tidal harmonics data - 160 ! get size from OBC data arrays 161 ! --------------------------------------- 162 163 ilen0(1) = SIZE( dta_bdy(ib_bdy)%ssh ) 164 ALLOCATE( td%ssh( ilen0(1), td%ncpt, 2 ) ) 165 166 ilen0(2) = SIZE( dta_bdy(ib_bdy)%u2d ) 167 ALLOCATE( td%u( ilen0(2), td%ncpt, 2 ) ) 168 169 ilen0(3) = SIZE( dta_bdy(ib_bdy)%v2d ) 170 ALLOCATE( td%v( ilen0(3), td%ncpt, 2 ) ) 171 172 ALLOCATE( dta_read( MAXVAL(ilen0), 1, 1 ) ) 173 174 175 ! Open files and read in tidal forcing data 176 ! ----------------------------------------- 177 178 DO itide = 1, td%ncpt 179 ! ! SSH fields 180 clfile = TRIM(filtide)//TRIM(tide_cpt(itide))//'_grid_T.nc' 181 IF(lwp) WRITE(numout,*) 'Reading data from file ', clfile 182 CALL iom_open( clfile, inum ) 183 CALL fld_map( inum, 'z1' , dta_read(1:ilen0(1),1:1,1:1) , 1, idx_bdy(ib_bdy)%nbmap(:,1) ) 184 td%ssh(:,itide,1) = dta_read(1:ilen0(1),1,1) 185 CALL fld_map( inum, 'z2' , dta_read(1:ilen0(1),1:1,1:1) , 1, idx_bdy(ib_bdy)%nbmap(:,1) ) 186 td%ssh(:,itide,2) = dta_read(1:ilen0(1),1,1) 187 CALL iom_close( inum ) 188 ! ! U fields 189 clfile = TRIM(filtide)//TRIM(tide_cpt(itide))//'_grid_U.nc' 190 IF(lwp) WRITE(numout,*) 'Reading data from file ', clfile 191 CALL iom_open( clfile, inum ) 192 CALL fld_map( inum, 'u1' , dta_read(1:ilen0(2),1:1,1:1) , 1, idx_bdy(ib_bdy)%nbmap(:,2) ) 193 td%u(:,itide,1) = dta_read(1:ilen0(2),1,1) 194 CALL fld_map( inum, 'u2' , dta_read(1:ilen0(2),1:1,1:1) , 1, idx_bdy(ib_bdy)%nbmap(:,2) ) 195 td%u(:,itide,2) = dta_read(1:ilen0(2),1,1) 196 CALL iom_close( inum ) 197 ! ! V fields 198 clfile = TRIM(filtide)//TRIM(tide_cpt(itide))//'_grid_V.nc' 199 IF(lwp) WRITE(numout,*) 'Reading data from file ', clfile 200 CALL iom_open( clfile, inum ) 201 CALL fld_map( inum, 'v1' , dta_read(1:ilen0(3),1:1,1:1) , 1, idx_bdy(ib_bdy)%nbmap(:,3) ) 202 td%v(:,itide,1) = dta_read(1:ilen0(3),1,1) 203 CALL fld_map( inum, 'v2' , dta_read(1:ilen0(3),1:1,1:1) , 1, idx_bdy(ib_bdy)%nbmap(:,3) ) 204 td%v(:,itide,2) = dta_read(1:ilen0(3),1,1) 205 CALL iom_close( inum ) 206 ! 207 END DO ! end loop on tidal components 208 209 IF( ln_tide_date ) THEN ! correct for date factors 210 211 !! used nmonth, nyear and nday from daymod.... 212 ! Calculate date corrects for 15 standard consituents 213 ! This is the initialisation step, so nday, nmonth, nyear are the 214 ! initial date/time of the integration. 215 print *, nday,nmonth,nyear 216 nyear = int(ndate0 / 10000 ) ! initial year 217 nmonth = int((ndate0 - nyear * 10000 ) / 100 ) ! initial month 218 nday = int(ndate0 - nyear * 10000 - nmonth * 100) 219 220 CALL uvset( 0, nday, nmonth, nyear, z_ftc, z_vplu ) 221 222 IF(lwp) WRITE(numout,*) 'Correcting tide for date:', nday, nmonth, nyear 223 224 DO itide = 1, td%ncpt ! loop on tidal components 225 ! 226 IF( nindx(itide) /= 0 ) THEN 227 !!gm use rpi and rad global variable 228 z_arg = 3.14159265d0 * z_vplu(nindx(itide)) / 180.0d0 229 z_atde=z_ftc(nindx(itide))*cos(z_arg) 230 z_btde=z_ftc(nindx(itide))*sin(z_arg) 231 IF(lwp) WRITE(numout,'(2i5,8f10.6)') itide, nindx(itide), td%speed(itide), & 232 & z_ftc(nindx(itide)), z_vplu(nindx(itide)) 233 ELSE 234 z_atde = 1.0_wp 235 z_btde = 0.0_wp 236 ENDIF 237 ! ! elevation 238 igrd = 1 239 DO ib = 1, ilen0(igrd) 240 z1t = z_atde * td%ssh(ib,itide,1) + z_btde * td%ssh(ib,itide,2) 241 z2t = z_atde * td%ssh(ib,itide,2) - z_btde * td%ssh(ib,itide,1) 242 td%ssh(ib,itide,1) = z1t 243 td%ssh(ib,itide,2) = z2t 244 END DO 245 ! ! u 246 igrd = 2 247 DO ib = 1, ilen0(igrd) 248 z1t = z_atde * td%u(ib,itide,1) + z_btde * td%u(ib,itide,2) 249 z2t = z_atde * td%u(ib,itide,2) - z_btde * td%u(ib,itide,1) 250 td%u(ib,itide,1) = z1t 251 td%u(ib,itide,2) = z2t 252 END DO 253 ! ! v 254 igrd = 3 255 DO ib = 1, ilen0(igrd) 256 z1t = z_atde * td%v(ib,itide,1) + z_btde * td%v(ib,itide,2) 257 z2t = z_atde * td%v(ib,itide,2) - z_btde * td%v(ib,itide,1) 258 td%v(ib,itide,1) = z1t 259 td%v(ib,itide,2) = z2t 260 END DO 261 ! 262 END DO ! end loop on tidal components 263 ! 264 ENDIF ! date correction 265 ! 266 ENDIF ! nn_dyn2d_dta(ib_bdy) .ge. 2 267 ! 268 END DO ! loop on ib_bdy 269 270 IF( nn_timing == 1 ) CALL timing_stop('tide_init') 271 135 272 END SUBROUTINE tide_init 136 273 137 274 138 SUBROUTINE tide_data 139 !!---------------------------------------------------------------------- 140 !! *** SUBROUTINE tide_data *** 141 !! 142 !! ** Purpose : - Read in tidal harmonics data and adjust for the start 143 !! time of the model run. 144 !! 145 !!---------------------------------------------------------------------- 146 INTEGER :: itide, igrd, ib ! dummy loop indices 147 CHARACTER(len=80) :: clfile ! full file name for tidal input file 148 INTEGER :: ipi, ipj, inum, idvar ! temporary integers (netcdf read) 149 INTEGER, DIMENSION(6) :: lendta=0 ! length of data in the file (note may be different from nblendta!) 150 REAL(wp) :: z_arg, z_atde, z_btde, z1t, z2t 151 REAL(wp), DIMENSION(jpbdta,1) :: zdta ! temporary array for data fields 152 REAL(wp), DIMENSION(jptides_max) :: z_vplu, z_ftc 153 !!------------------------------------------------------------------------------ 154 155 ! Open files and read in tidal forcing data 156 ! ----------------------------------------- 157 158 ipj = 1 159 160 DO itide = 1, ntide 161 ! ! SSH fields 162 clfile = TRIM(filtide)//TRIM(tide_cpt(itide))//'_grid_T.nc' 163 IF(lwp) WRITE(numout,*) 'Reading data from file ', clfile 164 CALL iom_open( clfile, inum ) 165 igrd = 4 166 IF( nblendta(igrd) <= 0 ) THEN 167 idvar = iom_varid( inum,'z1' ) 168 IF(lwp) WRITE(numout,*) 'iom_file(1)%ndims(idvar) : ',iom_file%ndims(idvar) 169 nblendta(igrd) = iom_file(inum)%dimsz(1,idvar) 170 WRITE(numout,*) 'Dim size for z1 is ', nblendta(igrd) 171 ENDIF 172 ipi = nblendta(igrd) 173 CALL iom_get( inum, jpdom_unknown, 'z1', zdta(1:ipi,1:ipj) ) 174 DO ib = 1, nblenrim(igrd) 175 ssh1(ib,itide) = zdta(nbmap(ib,igrd),1) 176 END DO 177 CALL iom_get( inum, jpdom_unknown, 'z2', zdta(1:ipi,1:ipj) ) 178 DO ib = 1, nblenrim(igrd) 179 ssh2(ib,itide) = zdta(nbmap(ib,igrd),1) 180 END DO 181 CALL iom_close( inum ) 182 ! 183 ! ! U fields 184 clfile = TRIM(filtide)//TRIM(tide_cpt(itide))//'_grid_U.nc' 185 IF(lwp) WRITE(numout,*) 'Reading data from file ', clfile 186 CALL iom_open( clfile, inum ) 187 igrd = 5 188 IF( lendta(igrd) <= 0 ) THEN 189 idvar = iom_varid( inum,'u1' ) 190 lendta(igrd) = iom_file(inum)%dimsz(1,idvar) 191 WRITE(numout,*) 'Dim size for u1 is ',lendta(igrd) 192 ENDIF 193 ipi = lendta(igrd) 194 CALL iom_get( inum, jpdom_unknown, 'u1', zdta(1:ipi,1:ipj) ) 195 DO ib = 1, nblenrim(igrd) 196 u1(ib,itide) = zdta(nbmap(ib,igrd),1) 197 END DO 198 CALL iom_get( inum, jpdom_unknown, 'u2', zdta(1:ipi,1:ipj) ) 199 DO ib = 1, nblenrim(igrd) 200 u2(ib,itide) = zdta(nbmap(ib,igrd),1) 201 END DO 202 CALL iom_close( inum ) 203 ! 204 ! ! V fields 205 clfile = TRIM(filtide)//TRIM(tide_cpt(itide))//'_grid_V.nc' 206 if(lwp) write(numout,*) 'Reading data from file ', clfile 207 CALL iom_open( clfile, inum ) 208 igrd = 6 209 IF( lendta(igrd) <= 0 ) THEN 210 idvar = iom_varid( inum,'v1' ) 211 lendta(igrd) = iom_file(inum)%dimsz(1,idvar) 212 WRITE(numout,*) 'Dim size for v1 is ', lendta(igrd) 213 ENDIF 214 ipi = lendta(igrd) 215 CALL iom_get( inum, jpdom_unknown, 'v1', zdta(1:ipi,1:ipj) ) 216 DO ib = 1, nblenrim(igrd) 217 v1(ib,itide) = zdta(nbmap(ib,igrd),1) 218 END DO 219 CALL iom_get( inum, jpdom_unknown, 'v2', zdta(1:ipi,1:ipj) ) 220 DO ib=1, nblenrim(igrd) 221 v2(ib,itide) = zdta(nbmap(ib,igrd),1) 222 END DO 223 CALL iom_close( inum ) 224 ! 225 END DO ! end loop on tidal components 226 227 IF( ln_tide_date ) THEN ! correct for date factors 228 229 !! used nmonth, nyear and nday from daymod.... 230 ! Calculate date corrects for 15 standard consituents 231 ! This is the initialisation step, so nday, nmonth, nyear are the 232 ! initial date/time of the integration. 233 print *, nday,nmonth,nyear 234 nyear = int(ndate0 / 10000 ) ! initial year 235 nmonth = int((ndate0 - nyear * 10000 ) / 100 ) ! initial month 236 nday = int(ndate0 - nyear * 10000 - nmonth * 100) 237 238 CALL uvset( 0, nday, nmonth, nyear, z_ftc, z_vplu ) 239 240 IF(lwp) WRITE(numout,*) 'Correcting tide for date:', nday, nmonth, nyear 241 242 DO itide = 1, ntide ! loop on tidal components 243 ! 244 IF( nindx(itide) /= 0 ) THEN 245 !!gm use rpi and rad global variable 246 z_arg = 3.14159265d0 * z_vplu(nindx(itide)) / 180.0d0 247 z_atde=z_ftc(nindx(itide))*cos(z_arg) 248 z_btde=z_ftc(nindx(itide))*sin(z_arg) 249 IF(lwp) WRITE(numout,'(2i5,8f10.6)') itide, nindx(itide), tide_speed(itide), & 250 & z_ftc(nindx(itide)), z_vplu(nindx(itide)) 251 ELSE 252 z_atde = 1.0_wp 253 z_btde = 0.0_wp 254 ENDIF 255 ! ! elevation 256 igrd = 4 257 DO ib = 1, nblenrim(igrd) 258 z1t = z_atde * ssh1(ib,itide) + z_btde * ssh2(ib,itide) 259 z2t = z_atde * ssh2(ib,itide) - z_btde * ssh1(ib,itide) 260 ssh1(ib,itide) = z1t 261 ssh2(ib,itide) = z2t 262 END DO 263 ! ! u 264 igrd = 5 265 DO ib = 1, nblenrim(igrd) 266 z1t = z_atde * u1(ib,itide) + z_btde * u2(ib,itide) 267 z2t = z_atde * u2(ib,itide) - z_btde * u1(ib,itide) 268 u1(ib,itide) = z1t 269 u2(ib,itide) = z2t 270 END DO 271 ! ! v 272 igrd = 6 273 DO ib = 1, nblenrim(igrd) 274 z1t = z_atde * v1(ib,itide) + z_btde * v2(ib,itide) 275 z2t = z_atde * v2(ib,itide) - z_btde * v1(ib,itide) 276 v1(ib,itide) = z1t 277 v2(ib,itide) = z2t 278 END DO 279 ! 280 END DO ! end loop on tidal components 281 ! 282 ENDIF ! date correction 283 ! 284 END SUBROUTINE tide_data 285 286 287 SUBROUTINE tide_update ( kt, jit ) 275 SUBROUTINE tide_update ( kt, idx, dta, td, jit, time_offset ) 288 276 !!---------------------------------------------------------------------- 289 277 !! *** SUBROUTINE tide_update *** 290 278 !! 291 !! ** Purpose : - Add tidal forcing to ssh bdy, ubtbdy and vbtbdyarrays.279 !! ** Purpose : - Add tidal forcing to ssh, u2d and v2d OBC data arrays. 292 280 !! 293 281 !!---------------------------------------------------------------------- 294 INTEGER, INTENT( in ) :: kt ! Main timestep counter282 INTEGER, INTENT( in ) :: kt ! Main timestep counter 295 283 !!gm doctor jit ==> kit 296 INTEGER, INTENT( in ) :: jit ! Barotropic timestep counter (for timesplitting option) 297 !! 298 INTEGER :: itide, igrd, ib ! dummy loop indices 299 REAL(wp) :: z_arg, z_sarg ! 284 TYPE(OBC_INDEX), INTENT( in ) :: idx ! OBC indices 285 TYPE(OBC_DATA), INTENT(inout) :: dta ! OBC external data 286 TYPE(TIDES_DATA),INTENT( in ) :: td ! tidal harmonics data 287 INTEGER,INTENT(in),OPTIONAL :: jit ! Barotropic timestep counter (for timesplitting option) 288 INTEGER,INTENT( in ), OPTIONAL :: time_offset ! time offset in units of timesteps. NB. if jit 289 ! is present then units = subcycle timesteps. 290 ! time_offset = 0 => get data at "now" time level 291 ! time_offset = -1 => get data at "before" time level 292 ! time_offset = +1 => get data at "after" time level 293 ! etc. 294 !! 295 INTEGER :: itide, igrd, ib ! dummy loop indices 296 INTEGER :: time_add ! time offset in units of timesteps 297 REAL(wp) :: z_arg, z_sarg 300 298 REAL(wp), DIMENSION(jptides_max) :: z_sist, z_cost 301 299 !!---------------------------------------------------------------------- 302 300 301 IF( nn_timing == 1 ) CALL timing_start('tide_update') 302 303 time_add = 0 304 IF( PRESENT(time_offset) ) THEN 305 time_add = time_offset 306 ENDIF 307 303 308 ! Note tide phase speeds are in deg/hour, so we need to convert the 304 309 ! elapsed time in seconds to hours by dividing by 3600.0 305 IF( jit == 0 ) THEN 306 z_arg = kt * rdt * rad / 3600.0 307 ELSE ! we are in a barotropic subcycle (for timesplitting option) 308 ! z_arg = ( (kt-1) * rdt + jit * rdt / REAL(nn_baro,lwp) ) * rad / 3600.0 309 z_arg = ( (kt-1) * rdt + jit * rdt / REAL(nn_baro,wp) ) * rad / 3600.0 310 IF( PRESENT(jit) ) THEN 311 z_arg = ( (kt-1) * rdt + (jit+time_add) * rdt / REAL(nn_baro,wp) ) * rad / 3600.0 312 ELSE 313 z_arg = (kt+time_add) * rdt * rad / 3600.0 310 314 ENDIF 311 315 312 DO itide = 1, ntide313 z_sarg = z_arg * t ide_speed(itide)316 DO itide = 1, td%ncpt 317 z_sarg = z_arg * td%speed(itide) 314 318 z_cost(itide) = COS( z_sarg ) 315 319 z_sist(itide) = SIN( z_sarg ) 316 320 END DO 317 321 318 ! summing of tidal constituents into BDY arrays 319 sshtide(:) = 0.0 320 utide (:) = 0.0 321 vtide (:) = 0.0 322 ! 323 DO itide = 1, ntide 324 igrd=4 ! SSH on tracer grid. 325 DO ib = 1, nblenrim(igrd) 326 sshtide(ib) =sshtide(ib)+ ssh1(ib,itide)*z_cost(itide) + ssh2(ib,itide)*z_sist(itide) 327 ! if(lwp) write(numout,*) 'z',ib,itide,sshtide(ib), ssh1(ib,itide),ssh2(ib,itide) 322 DO itide = 1, td%ncpt 323 igrd=1 ! SSH on tracer grid. 324 DO ib = 1, idx%nblenrim(igrd) 325 dta%ssh(ib) = dta%ssh(ib) + td%ssh(ib,itide,1)*z_cost(itide) + td%ssh(ib,itide,2)*z_sist(itide) 326 ! if(lwp) write(numout,*) 'z', ib, itide, dta%ssh(ib), td%ssh(ib,itide,1),td%ssh(ib,itide,2) 328 327 END DO 329 igrd= 5! U grid330 DO ib=1, nblenrim(igrd)331 utide(ib) = utide(ib)+ u1(ib,itide)*z_cost(itide) + u2(ib,itide)*z_sist(itide)332 ! if(lwp) write(numout,*) 'u',ib,itide,utide(ib), u1(ib,itide),u2(ib,itide)328 igrd=2 ! U grid 329 DO ib=1, idx%nblenrim(igrd) 330 dta%u2d(ib) = dta%u2d(ib) + td%u(ib,itide,1)*z_cost(itide) + td%u(ib,itide,2)*z_sist(itide) 331 ! if(lwp) write(numout,*) 'u',ib,itide,utide(ib), td%u(ib,itide,1),td%u(ib,itide,2) 333 332 END DO 334 igrd= 6! V grid335 DO ib=1, nblenrim(igrd)336 vtide(ib) = vtide(ib)+ v1(ib,itide)*z_cost(itide) + v2(ib,itide)*z_sist(itide)337 ! if(lwp) write(numout,*) 'v',ib,itide,vtide(ib), v1(ib,itide),v2(ib,itide)333 igrd=3 ! V grid 334 DO ib=1, idx%nblenrim(igrd) 335 dta%v2d(ib) = dta%v2d(ib) + td%v(ib,itide,1)*z_cost(itide) + td%v(ib,itide,2)*z_sist(itide) 336 ! if(lwp) write(numout,*) 'v',ib,itide,vtide(ib), td%v(ib,itide,1),td%v(ib,itide,2) 338 337 END DO 339 338 END DO 339 ! 340 IF( nn_timing == 1 ) CALL timing_stop('tide_update') 340 341 ! 341 342 END SUBROUTINE tide_update -
trunk/NEMOGCM/NEMO/OPA_SRC/BDY/bdytra.F90
r2528 r3294 2 2 !!====================================================================== 3 3 !! *** MODULE bdytra *** 4 !! Ocean tracers: Flow Relaxation Scheme of tracers on each open boundary4 !! Ocean tracers: Apply boundary conditions for tracers 5 5 !!====================================================================== 6 6 !! History : 1.0 ! 2005-01 (J. Chanut, A. Sellar) Original code 7 7 !! 3.0 ! 2008-04 (NEMO team) add in the reference version 8 !! 3.4 ! 2011 (D. Storkey) rewrite in preparation for OBC-BDY merge 8 9 !!---------------------------------------------------------------------- 9 10 #if defined key_bdy … … 11 12 !! 'key_bdy' Unstructured Open Boundary Conditions 12 13 !!---------------------------------------------------------------------- 13 !! bdy_tra_frs : Relaxation of tracers on unstructured open boundaries 14 !! bdy_tra : Apply open boundary conditions to T and S 15 !! bdy_tra_frs : Apply Flow Relaxation Scheme 14 16 !!---------------------------------------------------------------------- 17 USE timing ! Timing 15 18 USE oce ! ocean dynamics and tracers variables 16 19 USE dom_oce ! ocean space and time domain variables 17 20 USE bdy_oce ! ocean open boundary conditions 21 USE bdydta, ONLY: bf 18 22 USE lbclnk ! ocean lateral boundary conditions (or mpp link) 19 23 USE in_out_manager ! I/O manager … … 22 26 PRIVATE 23 27 24 PUBLIC bdy_tra _frs! routine called in tranxt.F9028 PUBLIC bdy_tra ! routine called in tranxt.F90 25 29 26 30 !!---------------------------------------------------------------------- … … 31 35 CONTAINS 32 36 33 SUBROUTINE bdy_tra_frs( kt ) 37 SUBROUTINE bdy_tra( kt ) 38 !!---------------------------------------------------------------------- 39 !! *** SUBROUTINE bdy_tra *** 40 !! 41 !! ** Purpose : - Apply open boundary conditions for temperature and salinity 42 !! 43 !!---------------------------------------------------------------------- 44 INTEGER, INTENT( in ) :: kt ! Main time step counter 45 !! 46 INTEGER :: ib_bdy ! Loop index 47 48 DO ib_bdy=1, nb_bdy 49 50 SELECT CASE( nn_tra(ib_bdy) ) 51 CASE(jp_none) 52 CYCLE 53 CASE(jp_frs) 54 CALL bdy_tra_frs( idx_bdy(ib_bdy), dta_bdy(ib_bdy), kt ) 55 CASE DEFAULT 56 CALL ctl_stop( 'bdy_tra : unrecognised option for open boundaries for T and S' ) 57 END SELECT 58 ENDDO 59 60 END SUBROUTINE bdy_tra 61 62 SUBROUTINE bdy_tra_frs( idx, dta, kt ) 34 63 !!---------------------------------------------------------------------- 35 64 !! *** SUBROUTINE bdy_tra_frs *** 36 65 !! 37 !! ** Purpose : Apply the Flow Relaxation Scheme for tracers in the 38 !! case of unstructured open boundaries. 66 !! ** Purpose : Apply the Flow Relaxation Scheme for tracers at open boundaries. 39 67 !! 40 68 !! Reference : Engedahl H., 1995, Tellus, 365-382. 41 69 !!---------------------------------------------------------------------- 42 INTEGER, INTENT( in ) :: kt 70 INTEGER, INTENT(in) :: kt 71 TYPE(OBC_INDEX), INTENT(in) :: idx ! OBC indices 72 TYPE(OBC_DATA), INTENT(in) :: dta ! OBC external data 43 73 !! 44 74 REAL(wp) :: zwgt ! boundary weight … … 47 77 !!---------------------------------------------------------------------- 48 78 ! 49 IF(ln_tra_frs) THEN ! If this is false, then this routine does nothing. 50 ! 51 IF( kt == nit000 ) THEN 52 IF(lwp) WRITE(numout,*) 53 IF(lwp) WRITE(numout,*) 'bdy_tra_frs : Flow Relaxation Scheme for tracers' 54 IF(lwp) WRITE(numout,*) '~~~~~~~' 55 ENDIF 56 ! 57 igrd = 1 ! Everything is at T-points here 58 DO ib = 1, nblen(igrd) 59 DO ik = 1, jpkm1 60 ii = nbi(ib,igrd) 61 ij = nbj(ib,igrd) 62 zwgt = nbw(ib,igrd) 63 ta(ii,ij,ik) = ( ta(ii,ij,ik) * (1.-zwgt) + tbdy(ib,ik) * zwgt ) * tmask(ii,ij,ik) 64 sa(ii,ij,ik) = ( sa(ii,ij,ik) * (1.-zwgt) + sbdy(ib,ik) * zwgt ) * tmask(ii,ij,ik) 65 END DO 66 END DO 67 ! 68 CALL lbc_lnk( ta, 'T', 1. ) ; CALL lbc_lnk( sa, 'T', 1. ) ! Boundary points should be updated 69 ! 70 ENDIF ! ln_tra_frs 79 IF( nn_timing == 1 ) CALL timing_start('bdy_tra_frs') 80 ! 81 igrd = 1 ! Everything is at T-points here 82 DO ib = 1, idx%nblen(igrd) 83 DO ik = 1, jpkm1 84 ii = idx%nbi(ib,igrd) 85 ij = idx%nbj(ib,igrd) 86 zwgt = idx%nbw(ib,igrd) 87 tsa(ii,ij,ik,jp_tem) = ( tsa(ii,ij,ik,jp_tem) + zwgt * ( dta%tem(ib,ik) - tsa(ii,ij,ik,jp_tem) ) ) * tmask(ii,ij,ik) 88 tsa(ii,ij,ik,jp_sal) = ( tsa(ii,ij,ik,jp_sal) + zwgt * ( dta%sal(ib,ik) - tsa(ii,ij,ik,jp_sal) ) ) * tmask(ii,ij,ik) 89 END DO 90 END DO 91 ! 92 CALL lbc_lnk( tsa(:,:,:,jp_tem), 'T', 1. ) ; CALL lbc_lnk( tsa(:,:,:,jp_sal), 'T', 1. ) ! Boundary points should be updated 93 ! 94 IF( kt .eq. nit000 ) CLOSE( unit = 102 ) 95 ! 96 IF( nn_timing == 1 ) CALL timing_stop('bdy_tra_frs') 71 97 ! 72 98 END SUBROUTINE bdy_tra_frs … … 77 103 !!---------------------------------------------------------------------- 78 104 CONTAINS 79 SUBROUTINE bdy_tra _frs(kt) ! Empty routine80 WRITE(*,*) 'bdy_tra _frs: You should not have seen this print! error?', kt81 END SUBROUTINE bdy_tra _frs105 SUBROUTINE bdy_tra(kt) ! Empty routine 106 WRITE(*,*) 'bdy_tra: You should not have seen this print! error?', kt 107 END SUBROUTINE bdy_tra 82 108 #endif 83 109 -
trunk/NEMOGCM/NEMO/OPA_SRC/BDY/bdyvol.F90
r2528 r3294 3 3 !! *** MODULE bdyvol *** 4 4 !! Ocean dynamic : Volume constraint when unstructured boundary 5 !! and Free surface are used5 !! and filtered free surface are used 6 6 !!====================================================================== 7 7 !! History : 1.0 ! 2005-01 (J. Chanut, A. Sellar) Original code 8 8 !! - ! 2006-01 (J. Chanut) Bug correction 9 9 !! 3.0 ! 2008-04 (NEMO team) add in the reference version 10 !! 3.4 ! 2011 (D. Storkey) rewrite in preparation for OBC-BDY merge 10 11 !!---------------------------------------------------------------------- 11 12 #if defined key_bdy && defined key_dynspg_flt … … 14 15 !! 'key_dynspg_flt' filtered free surface 15 16 !!---------------------------------------------------------------------- 17 USE timing ! Timing 16 18 USE oce ! ocean dynamics and tracers 17 19 USE dom_oce ! ocean space and time domain … … 71 73 !! 72 74 INTEGER :: ji, jj, jk, jb, jgrd 73 INTEGER :: i i, ij75 INTEGER :: ib_bdy, ii, ij 74 76 REAL(wp) :: zubtpecor, z_cflxemp, ztranst 77 TYPE(OBC_INDEX), POINTER :: idx 75 78 !!----------------------------------------------------------------------------- 79 80 IF( nn_timing == 1 ) CALL timing_start('bdy_vol') 76 81 77 82 IF( ln_vol ) THEN … … 91 96 ! ------------------------------------------------ 92 97 zubtpecor = 0.e0 93 jgrd = 2 ! cumulate u component contribution first 94 DO jb = 1, nblenrim(jgrd) 95 DO jk = 1, jpkm1 96 ii = nbi(jb,jgrd) 97 ij = nbj(jb,jgrd) 98 zubtpecor = zubtpecor + flagu(jb) * ua(ii,ij, jk) * e2u(ii,ij) * fse3u(ii,ij,jk) 98 DO ib_bdy = 1, nb_bdy 99 idx => idx_bdy(ib_bdy) 100 101 jgrd = 2 ! cumulate u component contribution first 102 DO jb = 1, idx%nblenrim(jgrd) 103 DO jk = 1, jpkm1 104 ii = idx%nbi(jb,jgrd) 105 ij = idx%nbj(jb,jgrd) 106 zubtpecor = zubtpecor + idx%flagu(jb) * ua(ii,ij, jk) * e2u(ii,ij) * fse3u(ii,ij,jk) 107 END DO 99 108 END DO 100 END DO101 jgrd = 3 ! then add v component contribution102 DO jb = 1, nblenrim(jgrd)103 DO jk = 1, jpkm1104 ii = nbi(jb,jgrd)105 ij = nbj(jb,jgrd)106 zubtpecor = zubtpecor + flagv(jb) * va(ii,ij, jk) * e1v(ii,ij) * fse3v(ii,ij,jk)109 jgrd = 3 ! then add v component contribution 110 DO jb = 1, idx%nblenrim(jgrd) 111 DO jk = 1, jpkm1 112 ii = idx%nbi(jb,jgrd) 113 ij = idx%nbj(jb,jgrd) 114 zubtpecor = zubtpecor + idx%flagv(jb) * va(ii,ij, jk) * e1v(ii,ij) * fse3v(ii,ij,jk) 115 END DO 107 116 END DO 117 108 118 END DO 109 119 IF( lk_mpp ) CALL mpp_sum( zubtpecor ) ! sum over the global domain … … 118 128 ! ------------------------------------------------------------- 119 129 ztranst = 0.e0 120 jgrd = 2 ! correct u component 121 DO jb = 1, nblenrim(jgrd) 122 DO jk = 1, jpkm1 123 ii = nbi(jb,jgrd) 124 ij = nbj(jb,jgrd) 125 ua(ii,ij,jk) = ua(ii,ij,jk) - flagu(jb) * zubtpecor * umask(ii,ij,jk) 126 ztranst = ztranst + flagu(jb) * ua(ii,ij,jk) * e2u(ii,ij) * fse3u(ii,ij,jk) 130 DO ib_bdy = 1, nb_bdy 131 idx => idx_bdy(ib_bdy) 132 133 jgrd = 2 ! correct u component 134 DO jb = 1, idx%nblenrim(jgrd) 135 DO jk = 1, jpkm1 136 ii = idx%nbi(jb,jgrd) 137 ij = idx%nbj(jb,jgrd) 138 ua(ii,ij,jk) = ua(ii,ij,jk) - idx%flagu(jb) * zubtpecor * umask(ii,ij,jk) 139 ztranst = ztranst + idx%flagu(jb) * ua(ii,ij,jk) * e2u(ii,ij) * fse3u(ii,ij,jk) 140 END DO 127 141 END DO 128 END DO129 jgrd = 3 ! correct v component130 DO jb = 1, nblenrim(jgrd)131 DO jk = 1, jpkm1132 ii = nbi(jb,jgrd)133 ij = nbj(jb,jgrd)134 va(ii,ij,jk) = va(ii,ij,jk) -flagv(jb) * zubtpecor * vmask(ii,ij,jk)135 ztranst = ztranst + flagv(jb) * va(ii,ij,jk) * e1v(ii,ij) * fse3v(ii,ij,jk)142 jgrd = 3 ! correct v component 143 DO jb = 1, idx%nblenrim(jgrd) 144 DO jk = 1, jpkm1 145 ii = idx%nbi(jb,jgrd) 146 ij = idx%nbj(jb,jgrd) 147 va(ii,ij,jk) = va(ii,ij,jk) -idx%flagv(jb) * zubtpecor * vmask(ii,ij,jk) 148 ztranst = ztranst + idx%flagv(jb) * va(ii,ij,jk) * e1v(ii,ij) * fse3v(ii,ij,jk) 149 END DO 136 150 END DO 151 137 152 END DO 138 153 IF( lk_mpp ) CALL mpp_sum( ztranst ) ! sum over the global domain … … 149 164 IF(lwp) WRITE(numout,*)' cumulated transport ztranst =', ztranst , '(m3/s)' 150 165 END IF 166 ! 167 IF( nn_timing == 1 ) CALL timing_stop('bdy_vol') 151 168 ! 152 169 END IF ! ln_vol
Note: See TracChangeset
for help on using the changeset viewer.