My Project
mod_obcs.f90
Go to the documentation of this file.
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 !/===========================================================================/
13 ! Copyright (c) 2007, The University of Massachusetts Dartmouth
14 ! Produced at the School of Marine Science & Technology
15 ! Marine Ecosystem Dynamics Modeling group
16 ! All rights reserved.
17 !
18 ! FVCOM has been developed by the joint UMASSD-WHOI research team. For
19 ! details of authorship and attribution of credit please see the FVCOM
20 ! technical manual or contact the MEDM group.
21 !
22 !
23 ! This file is part of FVCOM. For details, see http://fvcom.smast.umassd.edu
24 ! The full copyright notice is contained in the file COPYRIGHT located in the
25 ! root directory of the FVCOM code. This original header must be maintained
26 ! in all distributed versions.
27 !
28 ! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 ! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
30 ! THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 ! PURPOSE ARE DISCLAIMED.
32 !
33 !/---------------------------------------------------------------------------/
34 ! CVS VERSION INFORMATION
35 ! $Id$
36 ! $Name$
37 ! $Revision$
38 !/===========================================================================/
39 
40 !==============================================================================!
41 ! TYPE_OBC = 1: Surface Elevation Specified (Tidal Forcing) (ASL) !
42 ! TYPE_OBC = 2: AS TYPE_OBC=1 AND NON-LINEAR FLUX FOR CURRENT AT OPEN BOUNDARY !
43 ! TYPE_OBC = 3: Zero Surface Elevation Boundary Condition (ASL_CLP) !
44 ! TYPE_OBC = 4: AS TYPE_OBC=3 AND NON-LINEAR FLUX FOR CURRENT AT OPEN BOUNDARY !
45 ! TYPE_OBC = 5: GRAVITY-WAVE RADIATION IMPLICIT OPEN BOUNDARY CONDITION (GWI) !
46 ! TYPE_OBC = 6: AS TYPE_OBC=5 AND NON-LINEAR FLUX FOR CURRENT AT OPEN BOUNDARY !
47 ! TYPE_OBC = 7: BLUMBERG AND KHANTA IMPLICIT OPEN BOUNDARY CONDITION (BKI) !
48 ! TYPE_OBC = 8: AS TYPE_OBC=7 AND NON-LINEAR FLUX FOR CURRENT AT OPEN BOUNDARY !
49 ! TYPE_OBC = 9: ORLANSKI RADIATION EXPLICIT OPEN BOUNDARY CONDITION (ORE) !
50 ! TYPE_OBC =10: AS TYPE_OBC=9 AND NON-LINEAR FLUX FOR CURRENT AT OPEN BOUNDARY !
51 ! !
52 ! TYPE_TSOBC = 1: THE PERTURBATION OF TEMPERATURE AND SALINITY AT OPEN BOUNDARY!
53 ! ARE EQUAL TO THAT AT NEXT_OBC !
54 ! TYPE_TSOBC = 2: GRAVITY-WAVE RADIATION IMPLICIT OPEN BOUNDARY CONDITION FOR !
55 ! THE PERTURBATION OF TEMPERATURE AND SALINITY !
56 ! TYPE_TSOBC = 3: BLUMBERG AND KHANTA IMPLICIT OPEN BOUNDARY CONDITION FOR !
57 ! THE PERTURBATION OF TEMPERATURE AND SALINITY !
58 ! TYPE_TSOBC = 4: ORLANSKI RADIATION EXPLICIT OPEN BOUNDARY CONDITION FOR !
59 ! THE PERTURBATION OF TEMPERATURE AND SALINITY !
60 !==============================================================================!
61 
62 MODULE mod_obcs
63  USE mod_prec
64  USE mod_utils
65  USE control, type_tsobc => obc_ts_type
66  USE mod_time
67  USE mod_force
68  USE bcs
69  IMPLICIT NONE
70  SAVE
71 
72  !--Open Boundary Types, Lists, Pointers
73 
74  ! INTEGER :: IOBCN_GL !!GLOBAL NUMBER OF OPEN BOUNDARY NODES
75  ! INTEGER :: IOBCN !!LOCAL NUMBER OF OPEN BOUNDARY NODES
76  ! INTEGER, ALLOCATABLE :: I_OBC_GL(:) !!GLOBAL ID OF OPEN BOUNDARY NODES
77  ! INTEGER, ALLOCATABLE :: I_OBC_N(:) !!OPEN BOUNDARY NODE LIST
78  INTEGER, ALLOCATABLE :: next_obc(:) !!INTERIOR NEIGHBOR OF OPEN BOUNDARY NODE
79  INTEGER, ALLOCATABLE :: next_obc2(:) !!INTERIOR NEIGHBOR OF NEXT_OBC
80  ! INTEGER, ALLOCATABLE :: TYPE_OBC(:) !!OUTER BOUNDARY NODE TYPE (FOR SURFACE ELEVATION)
81  ! INTEGER, ALLOCATABLE :: TYPE_OBC_GL(:) !!OUTER BOUNDARY NODE TYPE (FOR SURFACE ELEVATION)
82  INTEGER :: ibcn(5) !!NUMBER OF EACH TYPE OF OBN IN LOCAL DOM
83  INTEGER :: ibcn_gl(5) !!NUMBER OF EACH TYPE OF OBN IN GLOBAL DOM
84  INTEGER, ALLOCATABLE :: obc_lst(:,:) !!MAPPING OF OPEN BOUNDARY ARRAYS TO EACH TYPE
85  INTEGER, ALLOCATABLE :: nadjn_obc(:) !!NUMBER OF ADJACENT OPEN BOUNDARY NODES TO OBN
86  INTEGER, ALLOCATABLE :: adjn_obc(:,:) !!ADJACENT OBN's of OBN
87  INTEGER, ALLOCATABLE :: nadjc_obc(:) !!NUMBER OF ADJACENT OPEN BOUNDARY CELLS TO OBN
88  INTEGER, ALLOCATABLE :: adjc_obc(:,:) !!ADJACENT OPEN BOUNDARY CELLS
89 
90  !-- Open Boundary TEMPERATURE AND SALINITY FOR NUDGING
91  REAL(sp), ALLOCATABLE :: temp_obc(:,:) !!OPEN BOUNDARY TEMPERATURE (see mod_force.F)
92  REAL(sp), ALLOCATABLE :: salt_obc(:,:) !!OPEN BOUNDARY SALT (see mod_force.F)
93  !--Open Boundary Metrics
94  INTEGER, ALLOCATABLE :: nfluxf_obc(:) !!NUMBER OF FLUX SEGMENTS TO OBN
95  REAL(sp), ALLOCATABLE :: fluxf_obc(:,:) !!FLUX FRACTION ON EACH SIDE OF OBN
96  REAL(sp), ALLOCATABLE :: nxobc(:) !!INWARD POINTING X-NORMAL OF OBN
97  REAL(sp), ALLOCATABLE :: nyobc(:) !!INWARD POINTING Y-NORMAL OF OBN
98  REAL(sp), ALLOCATABLE :: dltn_obc(:) !!DISTANCE BETWEEN NEXT_OBC AND OBN NORMAL TO BOUNDARY
99 
100  !--Previous Time Level Free Surface Fields
101  REAL(sp), ALLOCATABLE :: elm1(:) !!SURFACE ELEV FROM PREVIOUS TIME LEVEL (ORLANSKI COND)
102  REAL(sp), ALLOCATABLE :: elm2(:) !!SURFACE ELEV FROM PREVIOUS TIME LEVEL (ORLANSKI COND)
103  REAL(sp), ALLOCATABLE :: t1m1(:,:) !!TEMPERATURE FROM PREVIOUS TIME LEVEL (ORLANSKI COND)
104  REAL(sp), ALLOCATABLE :: t1m2(:,:) !!TEMPERATURE FROM PREVIOUS TIME LEVEL (ORLANSKI COND)
105  REAL(sp), ALLOCATABLE :: s1m1(:,:) !!SALINITY FROM PREVIOUS TIME LEVEL (ORLANSKI COND)
106  REAL(sp), ALLOCATABLE :: s1m2(:,:) !!SALINITY FROM PREVIOUS TIME LEVEL (ORLANSKI COND)
107 
108  !--Nonlinear Velocity Open Boundary Condition Arrays
109  REAL(sp), ALLOCATABLE :: fluxobn(:)
110  REAL(sp), ALLOCATABLE :: iucp(:)
111  REAL(sp), ALLOCATABLE :: xflux_obcn(:)
112  REAL(sp), ALLOCATABLE :: uard_obcn(:)
113  REAL(sp), ALLOCATABLE :: xflux_obc(:,:)
114 
115 
116 CONTAINS
117  !==========================================================================|
118  SUBROUTINE alloc_obc_data
120  !--------------------------------------------------------------------------|
121  ! ALLOCATE AND INITIALIZE SURFACE ELEVATION ARRAYS FOR |
122  ! TIME STEPS N-1 AND N-2 |
123  !--------------------------------------------------------------------------|
124 
125  USE all_vars
126  IMPLICIT NONE
127 
128  ALLOCATE(elm1(0:mt)) ;elm1 = zero
129  ALLOCATE(elm2(0:mt)) ;elm2 = zero
130  ALLOCATE(next_obc(iobcn)) ;next_obc = 0
131  ALLOCATE(next_obc2(iobcn)) ;next_obc2 = 0
132  ALLOCATE(fluxobn(1:nt)) ;fluxobn = zero
133  ALLOCATE(iucp(0:nt)) ;iucp = 1
134  ALLOCATE(xflux_obcn(iobcn+1)) ;xflux_obcn = zero
135  ALLOCATE(uard_obcn(iobcn+1)) ;uard_obcn = zero
136  ALLOCATE(xflux_obc(iobcn+1,kbm1));xflux_obc = zero
137 
138  ALLOCATE(temp_obc(iobcn,kbm1)) ;temp_obc = zero
139  ALLOCATE(salt_obc(iobcn,kbm1)) ;salt_obc = zero
140 
141  IF(type_tsobc == 4)THEN
142  ALLOCATE(t1m1(0:mt,kbm1)) ;t1m1 = zero
143  ALLOCATE(t1m2(0:mt,kbm1)) ;t1m2 = zero
144  ALLOCATE(s1m1(0:mt,kbm1)) ;s1m1 = zero
145  ALLOCATE(s1m2(0:mt,kbm1)) ;s1m2 = zero
146  END IF
147  RETURN
148  END SUBROUTINE alloc_obc_data
149  !==========================================================================|
150 
151  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
152  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
153 
154  !==========================================================================|
155  SUBROUTINE assign_elm1_to_elm2
157  !--------------------------------------------------------------------------|
158  ! Assign ELM1 to ELM2 and EL to ELM1 |
159  !--------------------------------------------------------------------------|
160 
161  USE all_vars
162  IMPLICIT NONE
163 
164  elm2 = elm1
165  elm1 = el
166 
167  IF(type_tsobc == 4)THEN
168  t1m2 = t1m1
169  t1m1 = t1
170 
171  s1m2 = s1m1
172  s1m1 = s1
173  END IF
174 
175  RETURN
176  END SUBROUTINE assign_elm1_to_elm2
177  !==========================================================================|
178 
179  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
180  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
181 
182 
183  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
184  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
185 
186  !==========================================================================|
187  SUBROUTINE elevation_atmo ! ONLY USED if defined (ATMO_TIDE)
188  !--------------------------------------------------------------------------|
189  ! Surface Elevation of ATMOSPHERIC TIDE |
190  !--------------------------------------------------------------------------|
191  USE all_vars
192  IMPLICIT NONE
193 
194  REAL(SP),PARAMETER :: APT_ATMO = 0.0113_sp
195  REAL(DP),PARAMETER :: ALFA_ATMO = 112.0_sp*pi2/360.0_sp
196  REAL(SP),PARAMETER :: S2PERIOD = 43200.0_sp
197 
198  INTEGER :: I,J
199  TYPE(time):: TIME_ELAPSED
200  REAL(DP):: TIME_FLT,PHAI_IJ
201  REAL(SP):: FORCE
202 
203  IF(.not.use_proj) CALL fatal_error &
204  & ("ELEVATION_ATMO: ILLEGAL ATTEMPT TO USE ATMOSPHERIC TIDE IN CARTESIAN MODE",&
205  & "YOU MUST BE USING PROJ4 TO DO THIS",&
206  & "THE POLICE HAVE BEEN NOTIFIED AND WILL BE THERE SHORTLY")
207 
208 
209 
210 
211  ! THIS CODE IS CALLED DURING EACH RK STAGE
212  ! DECIDE WHICH TIME YOU WANT TO USE!
213  time_elapsed = rktime - spectime
214 
215 !! IN MY JUDGEMENT, A TIMESERIES FORCING DOES NOT MAKE SENSE FOR ATMO/EQUITIDE
216 
217 ! SELECT CASE(TIDE_FORCING_TYPE)
218 ! CASE(TIDE_FORCING_TIMESERIES)
219  !
220  !-Julian: Set Elevation Based on Linear Interpolation Between Two Data Times-|
221  !
222 ! CALL FATAL_ERROR("ELEVATION_EQUI: Not set up for Julian Timeseries forcing yet?")
223 
224 ! CASE(TIDE_FORCING_SPECTRAL)
225  !
226  !-Non-Julian: Set Elevation of Equilibrium Tide -----------------------------|
227  !
228 
229  time_flt = seconds(time_elapsed * pi2/s2period)
230 
231  DO i = 1, mt
232  phai_ij = lon(i)*pi2/360.0_sp
233  force = apt_atmo*dcos(time_flt+2.0_dp*phai_ij-alfa_atmo)
234  elf_atmo(i) = force * ramp
235  END DO
236 
237 ! CASE DEFAULT
238 ! CALL FATAL_ERROR("ELEVATION_ATMO: INVALID TIDE FORCING TYPE ?")
239 ! END SELECT
240 
241 
242 
243  RETURN
244  END SUBROUTINE elevation_atmo
245  !==========================================================================|
246 
247 !==============================================================================|
248 ! SET BOUNDARY CONDITIONS FOR CALCULATING atmospher pressure external model|
249 ! |
250 !==============================================================================|
251 
252  SUBROUTINE bcond_pa_air
253  END SUBROUTINE bcond_pa_air
254 
255 
256 !==============================================================================|
257  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
258  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
259 
260  !==========================================================================|
261  SUBROUTINE bcond_asl
263  !--------------------------------------------------------------------------|
264  ! Surface Elevation Boundary Condition (Tidal Forcing) |
265  !--------------------------------------------------------------------------|
266 
267  USE all_vars, only : elf
268  IMPLICIT NONE
269 
270  INTEGER :: I,II,J,JN
271  TYPE(time):: TIME_ELAPSED
272  REAL(DP):: TIME_FLT,PHAI_IJ
273  REAL(SP):: FORCE
274  REAL(SP), ALLOCATABLE :: BND_ELV(:)
275 
276 
277  ALLOCATE(bnd_elv(iobcn))
278  !
279  !-Julian: Set Elevation Based on Linear Interpolation Between Two Data Times-|
280  !
281  SELECT CASE(tide_forcing_type)
283 
284 
285  ! THIS CODE IS CALLED DURING EACH RK STAGE
286  ! DECIDE WHICH TIME YOU WANT TO USE!
287  CALL update_tide(rktime,bnd_elv)
288  ! CALL UPDATE_TIDE(ExtTime,BND_ELV)
289 
290 
291  DO j = 1, ibcn(1)
292  jn = obc_lst(1,j)
293  ii = i_obc_n(jn)
294 
295  elf(ii) = bnd_elv(j)*ramp
296  END DO
297 
298  !
299  !-Non-Julian: Set Elevation Based on Input Amplitude and Phase of Tidal Comps-|
300  !
301 
303 
304 
305 
306 
307  ! THIS CODE IS CALLED DURING EACH RK STAGE
308  ! DECIDE WHICH TIME YOU WANT TO USE!
309  time_elapsed = rktime - spectime
310  ! TIME_ELAPSED = ExtTime - SpecTime
311 
312  ! write(ipt,*) "-----------------------------------------"
313  DO i = 1, ibcn(1)
314  jn = obc_lst(1,i)
315  ii = i_obc_n(jn)
316  force = 0.0_sp
317  DO j = 1,ntidecomps
318  phai_ij = phai(i,j)*pi2/360.0_sp
319  time_flt = seconds(time_elapsed * pi2/period(j))
320  ! Take cosine of a double precision number to preserve accuracy!
321  force = apt(i,j)*dcos(time_flt -phai_ij) + force
322  END DO
323  force = force + emean(i)
324  elf(ii) = force * ramp
325  ! write(ipt,*) "ELF=",ELF(II)
326 
327  END DO
328 
329  CASE DEFAULT
330  CALL fatal_error("BCOND_ASL: INVALID TIDE FORCING TYPE ?")
331  END SELECT
332 
333  DEALLOCATE(bnd_elv)
334 
335  RETURN
336  END SUBROUTINE bcond_asl
337 !!$!==========================================================================|
338 
339  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
340  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
341 
342  !==========================================================================|
343  SUBROUTINE bcond_asl_clp
345  !--------------------------------------------------------------------------|
346  ! Zero Surface Elevation Boundary Condition |
347  !--------------------------------------------------------------------------|
348 
349  USE all_vars
350  IMPLICIT NONE
351 
352  INTEGER :: I,II,JN
353 
354  DO i = 1, ibcn(2)
355  jn = obc_lst(2,i)
356  ii = i_obc_n(jn)
357  elf(ii) = 0.0_sp
358  END DO
359 
360  RETURN
361  END SUBROUTINE bcond_asl_clp
362  !==========================================================================|
363 
364  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
365  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
366 
367  !==========================================================================|
368  SUBROUTINE bcond_gwi(K_RK)
370  !--------------------------------------------------------------------------|
371  ! GRAVITY-WAVE RADIATION IMPLICIT OPEN BOUNDARY CONDITION (GWI) |
372  !--------------------------------------------------------------------------|
373 
374  USE all_vars
375  IMPLICIT NONE
376 
377  INTEGER :: I1,I2,J,JN,K_RK
378  REAL(SP):: CC,CP,ALPHA_RK_TMP
379 
380  IF(k_rk == 0)THEN
381  alpha_rk_tmp = 1.0
382  ELSE
383  alpha_rk_tmp = alpha_rk(k_rk)
384  END IF
385 
386  DO j = 1,ibcn(3)
387  jn = obc_lst(3,j)
388  i1 = i_obc_n(jn)
389  i2 = next_obc(jn)
390  cc = sqrt(grav_n(i1)*h(i1))*dte/dltn_obc(jn)*alpha_rk_tmp
391  cp = cc + 1.0_sp
392  elf(i1) = (cc*elf(i2) + elrk(i1))/cp
393  END DO
394 
395  RETURN
396  END SUBROUTINE bcond_gwi
397  !==========================================================================|
398 
399  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
400  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
401 
402  !==========================================================================|
403  SUBROUTINE bcond_bki(K_RK)
405  !--------------------------------------------------------------------------|
406  ! BLUMBERG AND KHANTA IMPLICIT OPEN BOUNDARY CONDITION |
407  !--------------------------------------------------------------------------|
408 
409  USE all_vars
410  IMPLICIT NONE
411 
412  INTEGER :: I1,I2,J,JN,K_RK
413  REAL(SP):: CC,CP,ALPHA_RK_TMP
414 
415  IF(k_rk == 0)THEN
416  alpha_rk_tmp = 1.0
417  ELSE
418  alpha_rk_tmp = alpha_rk(k_rk)
419  END IF
420 
421  DO j = 1,ibcn(4)
422  jn = obc_lst(4,j)
423  i1 = i_obc_n(jn)
424  i2 = next_obc(jn)
425  cc = sqrt(grav_n(i1)*h(i1))*dte/dltn_obc(jn)*alpha_rk_tmp
426  cp = cc + 1.0_sp
427  elf(i1) = (cc*elf(i2) + elrk(i1)*(1.0_sp-dte/10800.0_sp))/cp
428  END DO
429 
430  RETURN
431  END SUBROUTINE bcond_bki
432  !==============================================================================|
433 
434  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
435  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
436 
437  !==============================================================================|
438  SUBROUTINE bcond_ore
440  !------------------------------------------------------------------------------|
441  ! ORLANSKI RADIATION EXPLICIT OPEN BOUNDARY CONDITION (ORE) |
442  !------------------------------------------------------------------------------|
443 
444  USE all_vars
445  IMPLICIT NONE
446 
447  INTEGER :: I1,I2,I3,J,JN
448  REAL(SP) :: CL, MU
449 
450  DO j = 1, ibcn(5)
451  jn = obc_lst(5,j)
452  i1 = i_obc_n(jn)
453  i2 = next_obc(jn)
454  i3 = next_obc2(jn)
455 
456  cl = (elm2(i2)-el(i2))/(el(i2)+elm2(i2)-2.0*elm1(i3))
457  IF(cl >= 1.0)THEN
458  mu = 1.0
459  ELSE IF(cl > 0.0 .AND. cl < 1.0)THEN
460  mu = cl
461  ELSE
462  mu = 0.0
463  END IF
464 
465  elf(i1)=(elm1(i1)*(1.0-mu)+2.0*mu*el(i2))/(1.0+mu)
466  END DO
467 
468  RETURN
469  END SUBROUTINE bcond_ore
470  !==============================================================================|
471 
472  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
473  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
474 
475  !========================================================================
476 
477  SUBROUTINE setup_obctypes
478  USE lims
479  IMPLICIT NONE
480 
481  INTEGER :: I,I1,I2,NCNT,IERR,J
482  INTEGER, ALLOCATABLE :: TEMP1(:),TEMP2(:),TEMP3(:),TEMP4(:),TEMP5(:),TEMP6(:),TEMP7(:),ITEMP(:)
483 
484  ! CREATE THE BC TYPE INTEGERS USED IN THE MODEL
485  CALL separate_obc ! (MOD_OBCS.F)
486 
487  !==============================================================================|
488  ! REPORT AND CHECK OBC RESULTS |
489  !==============================================================================|
490  ALLOCATE(temp1(nprocs),temp2(nprocs),temp3(nprocs),temp4(nprocs))
491  ALLOCATE(temp5(nprocs),temp6(nprocs),temp7(nprocs))
492  temp1(1) = iobcn
493  temp2(1) = ibcn(1)
494  temp3(1) = ibcn(2)
495  temp4(1) = ibcn(3)
496  temp5(1) = ibcn(4)
497  temp6(1) = ibcn(5)
498  ! TEMP7(1) = NOBCGEO
499 
500 
501 
502  IF(dbg_set(dbg_log)) THEN
503  WRITE(ipt,*) '! BCOND TYPE : TOTAL BC NODES; BC NODES IN EACH DOMAIN'
504  WRITE(ipt,100)'! IOBCN :',iobcn_gl, (temp1(i),i=1,nprocs)
505  WRITE(ipt,100)'! IBCN(1) :',ibcn_gl(1), (temp2(i),i=1,nprocs)
506  WRITE(ipt,100)'! IBCN(2) :',ibcn_gl(2), (temp3(i),i=1,nprocs)
507  WRITE(ipt,100)'! IBCN(3) :',ibcn_gl(3), (temp4(i),i=1,nprocs)
508  WRITE(ipt,100)'! IBCN(4) :',ibcn_gl(4), (temp5(i),i=1,nprocs)
509  WRITE(ipt,100)'! IBCN(5) :',ibcn_gl(5), (temp6(i),i=1,nprocs)
510  ! IF(MSR)WRITE(IPT,100)'! NOBCGEO :'
511  !,NOBCGEO_GL, (TEMP7(I),I=1,NPROCS)
512  END IF
513 
514  DEALLOCATE(temp1,temp2,temp3,temp4,temp5,temp6,temp7)
515 
516  RETURN
517 100 FORMAT(1x,a26,i6," =>",2x,4(i5,1h,))
518 
519  END SUBROUTINE setup_obctypes
520  !==============================================================================|
521 
522  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
523  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
524 
525  !==============================================================================|
526  SUBROUTINE separate_obc
528  !------------------------------------------------------------------------------|
529  ! Accumulate separately the amounts of nodes for 11 types of open boundaries |
530  !------------------------------------------------------------------------------|
531  USE all_vars
532  IMPLICIT NONE
533 
534  INTEGER :: I,I1,I2,I3,I4,I5,II,J
535 
536  ibcn = 0
537  ibcn_gl = 0
538 
539  DO i = 1, iobcn_gl
540  IF(type_obc_gl(i) == 1 .OR. type_obc_gl(i) == 2) ibcn_gl(1) = ibcn_gl(1) + 1
541  IF(type_obc_gl(i) == 3 .OR. type_obc_gl(i) == 4) ibcn_gl(2) = ibcn_gl(2) + 1
542  IF(type_obc_gl(i) == 5 .OR. type_obc_gl(i) == 6) ibcn_gl(3) = ibcn_gl(3) + 1
543  IF(type_obc_gl(i) == 7 .OR. type_obc_gl(i) == 8) ibcn_gl(4) = ibcn_gl(4) + 1
544  IF(type_obc_gl(i) == 9 .OR. type_obc_gl(i) == 10) ibcn_gl(5) = ibcn_gl(5) + 1
545  END DO
546 
547  DO i = 1, iobcn
548  IF(type_obc(i) == 1 .OR. type_obc(i) == 2) ibcn(1) = ibcn(1) + 1
549  IF(type_obc(i) == 3 .OR. type_obc(i) == 4) ibcn(2) = ibcn(2) + 1
550  IF(type_obc(i) == 5 .OR. type_obc(i) == 6) ibcn(3) = ibcn(3) + 1
551  IF(type_obc(i) == 7 .OR. type_obc(i) == 8) ibcn(4) = ibcn(4) + 1
552  IF(type_obc(i) == 9 .OR. type_obc(i) == 10) ibcn(5) = ibcn(5) + 1
553  END DO
554 
555  i1 = 0
556  i2 = 0
557  i3 = 0
558  i4 = 0
559  i5 = 0
560 
561 
562  ALLOCATE(obc_lst(5,maxval(ibcn))) ; obc_lst = 0
563 
564  DO i=1,iobcn
565  IF(type_obc(i) == 1 .OR. type_obc(i) == 2)THEN
566  i1 = i1 + 1
567  obc_lst(1,i1) = i
568  ELSE IF(type_obc(i) == 3 .OR. type_obc(i) == 4)THEN
569  i2 = i2 + 1
570  obc_lst(2,i2) = i
571  ELSE IF(type_obc(i) == 5 .OR. type_obc(i) == 6)THEN
572  i3 = i3 + 1
573  obc_lst(3,i3) = i
574  ELSE IF(type_obc(i) == 7 .OR. type_obc(i) == 8)THEN
575  i4 = i4 + 1
576  obc_lst(4,i4) = i
577  ELSE IF(type_obc(i) == 9 .OR. type_obc(i) == 10)THEN
578  i5 = i5 + 1
579  obc_lst(5,i5) = i
580  END IF
581  END DO
582 
583  RETURN
584  END SUBROUTINE separate_obc
585  !==============================================================================|
586 
587  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
588  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
589 
590  !==============================================================================|
591  SUBROUTINE setup_obc
593  !------------------------------------------------------------------------------!
594  USE all_vars
595  IMPLICIT NONE
596 
597  REAL(SP) :: DXC,DYC,DXN,DYN,CROSS,E1,E2,DOTMAX,DOT,DX,DY,DXN_TMP,DYN_TMP
598  INTEGER :: I,J,JJ,INODE,JNODE,I1,I2,IC,N1,N2,N3
599  LOGICAL :: DEBUG
600 
601  REAL(SP), ALLOCATABLE :: NXOBC_TMP(:),NYOBC_TMP(:)
602 
603  !------------------------------------------------------------------------------!
604 
605 
606  IF(dbg_set(dbg_log))WRITE(ipt,*) "!"
607  IF(dbg_set(dbg_log))WRITE(ipt,*) "! SETTING UP OPEN BOUNDARY CONDITIONS"
608  IF(dbg_set(dbg_log))WRITE(ipt,*) "!"
609 
610  !--Determine Adjacent Open Boundary Points-------------------------------------!
611 
612  ALLOCATE(nadjn_obc(iobcn)) ; nadjn_obc = 0
613  ALLOCATE(adjn_obc(iobcn,2)) ; adjn_obc = 0
614 
615  DO i=1,iobcn
616  inode = i_obc_n(i)
617  DO j=1,ntsn(inode)-1
618  jnode = nbsn(inode,j)
619  IF(isonb(jnode) == 2 .AND. inode /= jnode)THEN
620  nadjn_obc(i) = nadjn_obc(i) + 1
621  adjn_obc(i,nadjn_obc(i)) = jnode
622  END IF
623  END DO
624  END DO
625 
626  DO i=1,iobcn
627  IF(nadjn_obc(i) == 0)THEN
628  WRITE(*,*)'NO ADJACENT NODE FOUND FOR BOUNDARY NODE',i
629  WRITE(*,*)'IN PROCESSOR',myid
630  CALL pstop
631  END IF
632  END DO
633 
634  !--Determine Adjacent Cells-(Nonlinear Only)-----------------------------------!
635  !--Simultaneously Determine INWARD Pointing Normal NXOBC,NYOBC !
636 
637  ALLOCATE(nadjc_obc(iobcn)) ; nadjc_obc = 0
638  ALLOCATE(adjc_obc(iobcn,2)) ; adjc_obc = 0
639  ALLOCATE(nxobc(iobcn)) ; nxobc = 0
640  ALLOCATE(nyobc(iobcn)) ; nyobc = 0
641  ALLOCATE(nxobc_tmp(iobcn)) ; nxobc_tmp = 0
642  ALLOCATE(nyobc_tmp(iobcn)) ; nyobc_tmp = 0
643 
644  DO i=1,iobcn
645  i1 = i_obc_n(i)
646 
647  !!Mark First Cell on Boundary Edge Adjacent to Node I
648  i2 = adjn_obc(i,1)
649  DO j = 1, ntve(i1)
650  ic = nbve(i1,j)
651  n1 = nv(ic,1) ; n2 = nv(ic,2) ; n3 = nv(ic,3)
652  IF( n1-i2 == 0 .OR. n2-i2 == 0 .OR. n3-i2 == 0)THEN
653  dxn = vx(i2)-vx(i1) ; dyn = vy(i2)-vy(i1)
654  dxc = xc(ic)-vx(i1) ; dyc = yc(ic)-vy(i1)
655  cross = sign(1.0_sp,dxc*dyn - dyc*dxn)
656  nxobc_tmp(i) = cross*dyn/sqrt(dxn**2 +dyn**2)
657  nyobc_tmp(i) = -cross*dxn/sqrt(dxn**2 +dyn**2)
658  nxobc(i) = nxobc_tmp(i)
659  nyobc(i) = nyobc_tmp(i)
660  nadjc_obc(i) = nadjc_obc(i) + 1
661  adjc_obc(i,nadjc_obc(i)) = ic
662  IF(mod(type_obc(i),2) == 1)THEN
663  !!Node is Linear, Mark Cell as Linear for Flux Update
664  iucp(ic) = 0
665  END IF
666  END IF
667  END DO
668 
669  IF(nadjn_obc(i) > 1)THEN
670  i2 = adjn_obc(i,2)
671  DO j = 1, ntve(i1)
672  ic = nbve(i1,j)
673  n1 = nv(ic,1) ; n2 = nv(ic,2) ; n3 = nv(ic,3)
674  IF( n1-i2 == 0 .OR. n2-i2 == 0 .OR. n3-i2 == 0)THEN
675  dxn = vx(i2)-vx(i1) ; dyn = vy(i2)-vy(i1)
676  dxc = xc(ic)-vx(i1) ; dyc = yc(ic)-vy(i1)
677  cross = sign(1.0_sp,dxc*dyn - dyc*dxn)
678  nxobc_tmp(i) = nxobc_tmp(i) + cross*dyn/sqrt(dxn**2 +dyn**2)
679  nyobc_tmp(i) = nyobc_tmp(i) - cross*dxn/sqrt(dxn**2 +dyn**2)
680  nxobc(i) = nxobc_tmp(i)/sqrt(nxobc_tmp(i)**2 + nyobc_tmp(i)**2)
681  nyobc(i) = nyobc_tmp(i)/sqrt(nxobc_tmp(i)**2 + nyobc_tmp(i)**2)
682 
683  nadjc_obc(i) = nadjc_obc(i) + 1
684  adjc_obc(i,nadjc_obc(i)) = ic
685  IF(mod(type_obc(i),2) == 1)THEN
686  !!Node is Linear, Mark Cell as Linear for Flux Update
687  iucp(ic) = 0
688  END IF
689  END IF
690  END DO
691  END IF
692  END DO
693 
694  DEALLOCATE(nxobc_tmp,nyobc_tmp)
695 
696  !--Determine Adjacent FluxFractions--------------------------------------------!
697 
698  ALLOCATE(nfluxf_obc(iobcn)) ; nfluxf_obc = 0
699  ALLOCATE(fluxf_obc(iobcn,2)) ; fluxf_obc = 0
700  DO i=1,iobcn
701  IF(nadjn_obc(i) == 1)THEN
702  nfluxf_obc(i) = 1
703  fluxf_obc(i,1) = 1.
704  fluxf_obc(i,2) = 0.
705  ELSE
706  nfluxf_obc(i) = 2
707  n1 = i_obc_n(i)
708  n2 = adjn_obc(i,1)
709  n3 = adjn_obc(i,2)
710  e1 = sqrt( (vx(n1)-vx(n2))**2 + (vy(n1)-vy(n2))**2)
711  e2 = sqrt( (vx(n1)-vx(n3))**2 + (vy(n1)-vy(n3))**2)
712  fluxf_obc(i,1) = e1/(e1+e2)
713  fluxf_obc(i,2) = e2/(e1+e2)
714  END IF
715  END DO
716  !--Determine 1st Layer Neighbor for Open Boundary Points-----------------------!
717  !--Node Chosen is Node That is Connected to OBC Node and is Oriented !
718  !--Most Normal to the Boundary. It is not Necessarily the Closest Node !
719  !--Determine also DLTN_OBC, the normal component of the distance between !
720  !--Next_obc and the open boundary node !
721 
722  DO i=1,iobcn
723  dotmax = -1.0
724  inode = i_obc_n(i)
725  DO j=1,ntsn(inode)-1
726  jnode = nbsn(inode,j)
727  IF(isonb(jnode) /= 2 .AND. inode /= jnode)THEN
728  dxn_tmp = vx(jnode)-vx(inode)
729  dyn_tmp = vy(jnode)-vy(inode)
730  dxn = dxn_tmp/sqrt(dxn_tmp**2 + dyn_tmp**2)
731  dyn = dyn_tmp/sqrt(dxn_tmp**2 + dyn_tmp**2)
732  dot = dxn*nxobc(i) + dyn*nyobc(i)
733  IF(dot > dotmax)THEN
734  dotmax = dot
735  next_obc(i) = jnode
736  END IF
737  END IF
738  END DO
739  END DO
740 
741  !--Determine 2nd Layer Neighbor for Open Boundary Points-----------------------!
742 
743  DO i=1,iobcn
744  dotmax = -1.0
745  inode = next_obc(i)
746  IF(inode > m) cycle
747  DO j=1,ntsn(inode)-1
748  jnode = nbsn(inode,j)
749  IF(isonb(jnode) /= 2)THEN
750  dxn_tmp = vx(jnode)-vx(inode)
751  dyn_tmp = vy(jnode)-vy(inode)
752  dxn = dxn_tmp/(sqrt(dxn_tmp**2 + dyn_tmp**2) + 1.0e-9_sp)
753  dyn = dyn_tmp/(sqrt(dxn_tmp**2 + dyn_tmp**2) + 1.0e-9_sp)
754  dot = dxn*nxobc(i) + dyn*nyobc(i)
755  IF(dot > dotmax)THEN
756  dotmax = dot
757  next_obc2(i) = jnode
758  END IF
759  END IF
760  END DO
761  END DO
762 
763  !--Determine DLTN_OBC----------------------------------------------------------!
764  ALLOCATE(dltn_obc(iobcn))
765  DO i=1,iobcn
766  i1 = i_obc_n(i)
767  i2 = next_obc(i)
768 
769  dx = vx(i2)-vx(i1)
770  dy = vy(i2)-vy(i1)
771  dltn_obc(i) = abs(dx*nxobc(i) + dy*nyobc(i))
772  END DO
773 
774 !!$ RETURN
775 !!$!--Dump Information to Matlab Files for Checking-------------------------------!
776 !!$
777 !!$ OPEN(UNIT=81,FILE='mesh.scatter',FORM='formatted')
778 !!$ DO I=1,M
779 !!$ WRITE(81,*)vx(i),vy(i)
780 !!$ END DO
781 !!$ CLOSE(81)
782 !!$ OPEN(UNIT=81,FILE='nextobc.scatter',FORM='formatted')
783 !!$ DO I=1,IOBCN
784 !!$ I1 = NEXT_OBC(I)
785 !!$ WRITE(81,*)VX(I1),VY(I1)
786 !!$ END DO
787 !!$ CLOSE(81)
788 !!$ OPEN(UNIT=81,FILE='nextobc2.scatter',FORM='formatted')
789 !!$ DO I=1,IOBCN
790 !!$ I1 = NEXT_OBC2(I)
791 !!$ WRITE(81,*)VX(I1),VY(I1)
792 !!$ END DO
793 !!$ CLOSE(81)
794 !!$ OPEN(UNIT=81,FILE='iobcn.scatter',FORM='formatted')
795 !!$ DO I=1,IOBCN
796 !!$ I1 = I_OBC_N(I)
797 !!$ WRITE(81,*)VX(I1),VY(I1)
798 !!$ END DO
799 !!$ CLOSE(81)
800 !!$ OPEN(UNIT=81,FILE='obcnorm.scatter',FORM='formatted')
801 !!$ DO I=1,IOBCN
802 !!$ I1 = I_OBC_N(I)
803 !!$ WRITE(81,*)NXOBC(I1),NYOBC(I1)
804 !!$ END DO
805 !!$ CLOSE(81)
806 !!$ OPEN(UNIT=81,FILE='nonlinear.scatter',FORM='formatted')
807 !!$ DO I=1,IOBCN
808 !!$ IF(NADJC_OBC(I) > 0) WRITE(81,*)XC(ADJC_OBC(I,1)),YC(ADJC_OBC(I,1))
809 !!$ IF(NADJC_OBC(I) > 1) WRITE(81,*)XC(ADJC_OBC(I,2)),YC(ADJC_OBC(I,2))
810 !!$ END DO
811 !!$ CLOSE(81)
812 !!$ OPEN(UNIT=81,FILE='linear.scatter',FORM='formatted')
813 !!$ DO I=1,N
814 !!$ IF(IUCP(I)==0)THEN
815 !!$ WRITE(81,*)XC(I),YC(I)
816 !!$ END IF
817 !!$ END DO
818 !!$ CLOSE(81)
819 
820  RETURN
821  END SUBROUTINE setup_obc
822  !==============================================================================|
823 
824  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
825  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
826 
827  !==============================================================================|
828  SUBROUTINE flux_obn(K)
830  USE all_vars
831  IMPLICIT NONE
832 
833  INTEGER, INTENT(IN) :: K
834  INTEGER :: I,J,C1,C2
835  REAL(SP) :: FF,FLUX
836 
837  fluxobn = 0.0_sp
838 
839  DO i = 1, iobcn
840 
841  j = i_obc_n(i)
842  !Compute Boundary Flux From Continuity Flux Defect
843  flux = -(elf(j)-elrk(j))*art1(j)/(alpha_rk(k)*dte)-xflux_obcn(i)
844 
845  !Set Flux In Adjacent Nonlinear BC Element 1 (If Exists)
846  IF(nadjc_obc(i) > 0) THEN
847  c1 = adjc_obc(i,1)
848  ff = fluxf_obc(i,1)
849  fluxobn(c1) = fluxobn(c1) + ff*flux
850  END IF
851 
852  !Set Flux In Adjacent Nonlinear BC Element 2 (If Exists)
853  IF(nadjc_obc(i) > 1) THEN
854  c2 = adjc_obc(i,2)
855  ff = fluxf_obc(i,2)
856  fluxobn(c2) = fluxobn(c2) + ff*flux
857  END IF
858 
859  END DO
860 
861  RETURN
862  END SUBROUTINE flux_obn
863  !========================================================================
864 
865  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
866  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
867 
868  !==============================================================================|
869  SUBROUTINE bcond_t_perturbation(T2D_NEXT,T2D,TTMP,I,J,J1)
870  !==============================================================================|
871  ! Calculate the OBC for temperature perturbation |
872  !==============================================================================|
873  USE all_vars
874  IMPLICIT NONE
875 
876  ! INTEGER :: I1,I2,J,JN
877  INTEGER :: I,J,J1,J2,K
878  REAL(SP):: CC,CP,MU,CL
879  REAL(SP):: PERT_NEXT,PERT,T2D_NEXT,T2D
880  REAL(SP):: T2D_NEXT1,TM12D_NEXT2,TM12D_NEXT1,TM22D_NEXT1
881  REAL(SP):: TTMP(IOBCN,KBM1)
882 
883  SELECT CASE(type_tsobc)
884 
885  CASE(1)
886  DO k=1,kbm1
887  ttmp(i,k) = tf1(j1,k) - t2d_next
888  END DO
889  CASE(2)
890  cc = sqrt(grav_n(j)*h(j))*dti/dltn_obc(i)
891  cp = cc + 1.0_sp
892  DO k=1,kbm1
893  pert_next = tf1(j1,k) - t2d_next
894  pert = t1(j,k) - t2d
895  ttmp(i,k) = (cc*pert_next + pert)/cp
896  END DO
897  CASE(3)
898  cc = sqrt(grav_n(j)*h(j))*dti/dltn_obc(i)
899  cp = cc + 1.0_sp
900  DO k=1,kbm1
901  pert_next = tf1(j1,k) - t2d_next
902  pert = t1(j,k) - t2d
903  ttmp(i,k) = (cc*pert_next + pert*(1.0_sp - dti/10800.0_sp))/cp
904  END DO
905  CASE(4)
906  j2 = next_obc2(i)
907  t2d_next1 =0.0_sp
908  tm12d_next2=0.0_sp
909  tm12d_next1=0.0_sp
910  tm22d_next1=0.0_sp
911  DO k=1,kbm1
912  t2d_next1 =t2d_next1 +t1(j1,k)*dz(j1,k)
913  tm12d_next2=tm12d_next2+t1m1(j2,k)*dz(j2,k)
914  tm12d_next1=tm12d_next1+t1m1(j,k)*dz(j,k)
915  tm22d_next1=tm22d_next1+t1m2(j1,k)*dz(j1,k)
916  END DO
917 
918  DO k=1,kbm1
919  cl = ((t1m2(j1,k)-tm22d_next1)-(t1(j1,k)-t2d_next1))/ &
920  ((t1(j1,k)-t2d_next1)+(t1m2(j1,k)-tm22d_next1) &
921  -2.0*(t1m1(j2,k)-tm12d_next2))
922  IF(cl >= 1.0)THEN
923  mu = 1.0
924  ELSE IF(cl > 0.0 .AND. cl < 1.0)THEN
925  mu = cl
926  ELSE
927  mu = 0.0
928  END IF
929 
930  ttmp(i,k)=((t1m1(j,k)-tm12d_next1)*(1.0-mu) &
931  +2.0*mu*(t1(j1,k)-t2d_next1))/(1.0+mu)
932  END DO
933 
934  CASE DEFAULT
935  CALL fatal_error("INVALID OBC_TS_TYPE IN NML_OPEN_BOUNDARY_CONTROL"&
936  &, "See mod_obcs.F")
937 
938  END SELECT
939 
940  RETURN
941  END SUBROUTINE bcond_t_perturbation
942  !========================================================================
943 
944  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
945  !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
946 
947  !==============================================================================|
948  SUBROUTINE bcond_s_perturbation(S2D_NEXT,S2D,STMP,I,J,J1)
949  !==============================================================================|
950  ! Calculate the OBC for salinity perturbation |
951  !==============================================================================|
952  USE all_vars
953  IMPLICIT NONE
954 
955  INTEGER :: I,J,J1,J2,K
956  REAL(SP):: CC,CP,MU,CL
957  REAL(SP):: PERT_NEXT,PERT,S2D_NEXT,S2D
958  REAL(SP):: S2D_NEXT1,SM12D_NEXT2,SM12D_NEXT1,SM22D_NEXT1
959  REAL(SP):: STMP(IOBCN,KBM1)
960 
961  SELECT CASE(type_tsobc)
962 
963  CASE(1)
964  DO k=1,kbm1
965  stmp(i,k) = sf1(j1,k) - s2d_next
966  END DO
967  CASE(2)
968  cc = sqrt(grav_n(j)*h(j))*dti/dltn_obc(i)
969  cp = cc + 1.0_sp
970  DO k=1,kbm1
971  pert_next = sf1(j1,k) - s2d_next
972  pert = s1(j,k) - s2d
973  stmp(i,k) = (cc*pert_next + pert)/cp
974  END DO
975  CASE(3)
976  cc = sqrt(grav_n(j)*h(j))*dti/dltn_obc(i)
977  cp = cc + 1.0_sp
978  DO k=1,kbm1
979  pert_next = sf1(j1,k) - s2d_next
980  pert = s1(j,k) - s2d
981  stmp(i,k) = (cc*pert_next + pert*(1.0_sp - dti/10800.0_sp))/cp
982  END DO
983  CASE(4)
984  j2 = next_obc2(i)
985  s2d_next1 =0.0_sp
986  sm12d_next2=0.0_sp
987  sm12d_next1=0.0_sp
988  sm22d_next1=0.0_sp
989  DO k=1,kbm1
990  s2d_next1 =s2d_next1 +s1(j1,k)*dz(j1,k)
991  sm12d_next2=sm12d_next2+s1m1(j2,k)*dz(j2,k)
992  sm12d_next1=sm12d_next1+s1m1(j,k)*dz(j,k)
993  sm22d_next1=sm22d_next1+s1m2(j1,k)*dz(j1,k)
994  END DO
995 
996  DO k=1,kbm1
997  cl = ((s1m2(j1,k)-sm22d_next1)-(s1(j1,k)-s2d_next1))/ &
998  ((s1(j1,k)-s2d_next1)+(s1m2(j1,k)-sm22d_next1) &
999  -2.0*(s1m1(j2,k)-sm12d_next2))
1000  IF(cl >= 1.0)THEN
1001  mu = 1.0
1002  ELSE IF(cl > 0.0 .AND. cl < 1.0)THEN
1003  mu = cl
1004  ELSE
1005  mu = 0.0
1006  END IF
1007 
1008  stmp(i,k)=((s1m1(j,k)-sm12d_next1)*(1.0-mu) &
1009  +2.0*mu*(s1(j1,k)-s2d_next1))/(1.0+mu)
1010  END DO
1011 
1012  CASE DEFAULT
1013  CALL fatal_error("INVALID OBC_TS_TYPE IN NML_OPEN_BOUNDARY_CONTROL"&
1014  &, "See mod_obcs.F")
1015 
1016  END SELECT
1017 
1018  RETURN
1019  END SUBROUTINE bcond_s_perturbation
1020  !========================================================================
1021 
1022  SUBROUTINE gday1(IDD,IMM,IYY,ICC,KD)
1024 ! given day,month,year and century(each 2 digits), gday returns
1025 ! the day#, kd based on the gregorian calendar.
1026 ! the gregorian calendar, currently 'universally' in use was
1027 ! initiated in europe in the sixteenth century. note that gday
1028 ! is valid only for gregorian calendar dates.
1029 !
1030 ! kd=1 corresponds to january 1, 0000
1031 !
1032 ! note that the gregorian reform of the julian calendar
1033 ! omitted 10 days in 1582 in order to restore the date
1034 ! of the vernal equinox to march 21 (the day after
1035 ! oct 4, 1582 became oct 15, 1582), and revised the leap
1036 ! year rule so that centurial years not divisible by 400
1037 ! were not leap years.
1038 !
1039 ! this routine was written by eugene neufeld, at ios, in june 1990.
1040 !
1041  integer idd, imm, iyy, icc, kd
1042  integer ndp(13)
1043  integer ndm(12)
1044  data ndp/0,31,59,90,120,151,181,212,243,273,304,334,365/
1045  data ndm/31,28,31,30,31,30,31,31,30,31,30,31/
1046 !
1047 ! test for invalid input:
1048  if(icc.lt.0)then
1049 ! write(11,5000)icc
1050  call pstop
1051  endif
1052  if(iyy.lt.0.or.iyy.gt.99)then
1053 ! write(11,5010)iyy
1054  call pstop
1055  endif
1056  if(imm.le.0.or.imm.gt.12)then
1057 ! write(11,5020)imm
1058  call pstop
1059  endif
1060  if(idd.le.0)then
1061 ! write(11,5030)idd
1062  call pstop
1063  endif
1064  if(imm.ne.2.and.idd.gt.ndm(imm))then
1065 ! write(11,5030)idd
1066  call pstop
1067  endif
1068  if(imm.eq.2.and.idd.gt.29)then
1069 ! write(11,5030)idd
1070  call pstop
1071  endif
1072  if(imm.eq.2.and.idd.gt.28.and.((iyy/4)*4-iyy.ne.0.or.(iyy.eq.0.and.(icc/4)*4-icc.ne.0)))then
1073 ! write(11,5030)idd
1074  call pstop
1075  endif
1076 5000 format(' input error. icc = ',i7)
1077 5010 format(' input error. iyy = ',i7)
1078 5020 format(' input error. imm = ',i7)
1079 5030 format(' input error. idd = ',i7)
1080 !
1081 ! calculate day# of last day of last century:
1082  kd = icc*36524 + (icc+3)/4
1083 !
1084 ! calculate day# of last day of last year:
1085  kd = kd + iyy*365 + (iyy+3)/4
1086 !
1087 ! adjust for century rule:
1088 ! (viz. no leap-years on centurys except when the 2-digit
1089 ! century is divisible by 4.)
1090  if(iyy.gt.0.and.(icc-(icc/4)*4).ne.0) kd=kd-1
1091 ! kd now truly represents the day# of the last day of last year.
1092 !
1093 ! calculate day# of last day of last month:
1094  kd = kd + ndp(imm)
1095 !
1096 ! adjust for leap years:
1097  if(imm.gt.2.and.((iyy/4)*4-iyy).eq.0.and.((iyy.ne.0).or.(((icc/4)*4-icc).eq.0))) kd=kd+1
1098 ! kd now truly represents the day# of the last day of the last
1099 ! month.
1100 !
1101 ! calculate the current day#:
1102  kd = kd + idd
1103 
1104  RETURN
1105  END SUBROUTINE gday1
1106 
1107  subroutine astro(d1,h,pp,s,p,np,dh,dpp,ds,dp,dnp)
1108 ! this subroutine calculates the following five ephermides
1109 ! of the sun and moon
1110 ! h = mean longitude of the sum
1111 ! pp = mean longitude of the solar perigee
1112 ! s = mean longitude of the moon
1113 ! p = mean longitude of the lunar perigee
1114 ! np = negative of the longitude of the mean ascending node
1115 ! and their rates of change.
1116 ! units for the ephermides are cycles and for their derivatives
1117 ! are cycles/365 days
1118 ! the formulae for calculating this ephermides were taken from
1119 ! pages 98 and 107 of the explanatory supplement to the
1120 ! astronomical ephermeris and the american ephermis and
1121 ! nautical almanac (1961)
1122 !
1123  implicit real*8(a-h,o-z)
1124  real*8 np
1125  d2=d1*1.d-4
1126  f=360.d0
1127  f2=f/365.d0
1128  h=279.696678d0+.9856473354d0*d1+.00002267d0*d2*d2
1129  pp=281.220833d0+.0000470684d0*d1+.0000339d0*d2*d2+.00000007d0*d2**3
1130  s=270.434164d0+13.1763965268d0*d1-.000085d0*d2*d2+.000000039d0*d2**3
1131  p=334.329556d0+.1114040803d0*d1-.0007739d0*d2*d2-.00000026d0*d2**3
1132  np=-259.183275d0+.0529539222d0*d1-.0001557d0*d2*d2-.00000005d0*d2**3
1133  h=h/f
1134  pp=pp/f
1135  s=s/f
1136  p=p/f
1137  np=np/f
1138  h=h-dint(h)
1139  pp=pp-dint(pp)
1140  s=s-dint(s)
1141  p=p-dint(p)
1142  np=np-dint(np)
1143  dh=.9856473354d0+2.d-8*.00002267d0*d1
1144  dpp=.0000470684d0+2.d-8*.0000339d0*d1+3.d-12*.00000007d0*d1**2
1145  ds=13.1763965268d0-2.d-8*.000085d0*d1+3.d-12*.000000039d0*d1**2
1146  dp=.1114040803d0-2.d-8*.0007739d0*d1-3.d-12*.00000026d0*d1**2
1147  dnp=+.0529539222d0-2.d-8*.0001557d0*d1-3.d-12*.00000005d0*d1**2
1148  dh=dh/f2
1149  dpp=dpp/f2
1150  ds=ds/f2
1151  dp=dp/f2
1152  dnp=dnp/f2
1153  return
1154  end subroutine astro
1155 
1156 !!$
1157 
1158 END MODULE mod_obcs
integer, dimension(:), allocatable, target ntsn
Definition: mod_main.f90:1023
subroutine astro(d1, h, pp, s, p, np, dh, dpp, ds, dp, dnp)
Definition: mod_obcs.f90:1108
logical use_proj
Definition: mod_main.f90:633
integer, dimension(:), allocatable nadjc_obc
Definition: mod_obcs.f90:87
real(sp), dimension(:,:), allocatable fluxf_obc
Definition: mod_obcs.f90:95
subroutine flux_obn(K)
Definition: mod_obcs.f90:829
subroutine bcond_t_perturbation(T2D_NEXT, T2D, TTMP, I, J, J1)
Definition: mod_obcs.f90:870
real(dp), dimension(4), parameter alpha_rk
Definition: mod_main.f90:875
real(sp), dimension(:), allocatable dltn_obc
Definition: mod_obcs.f90:98
real(sp), dimension(:), allocatable, target elrk
Definition: mod_main.f90:1138
real(sp), dimension(:), allocatable, target h
Definition: mod_main.f90:1131
real(sp), dimension(:), allocatable emean
Definition: mod_main.f90:1798
subroutine bcond_asl
Definition: mod_obcs.f90:262
subroutine bcond_pa_air
Definition: mod_obcs.f90:253
real(sp), dimension(:), allocatable, target el
Definition: mod_main.f90:1134
integer, dimension(:), allocatable nfluxf_obc
Definition: mod_obcs.f90:94
integer, dimension(:), allocatable type_obc
Definition: mod_main.f90:1783
real(sp), dimension(:,:), allocatable s1m1
Definition: mod_obcs.f90:105
logical function dbg_set(vrb)
Definition: mod_utils.f90:182
integer obc_ts_type
Definition: mod_main.f90:589
integer, dimension(:,:), allocatable adjn_obc
Definition: mod_obcs.f90:86
integer, dimension(:), allocatable nadjn_obc
Definition: mod_obcs.f90:85
real(sp) dte
Definition: mod_main.f90:843
subroutine separate_obc
Definition: mod_obcs.f90:527
real(sp), dimension(:), allocatable, target art1
Definition: mod_main.f90:1010
real(sp), dimension(:), allocatable, target yc
Definition: mod_main.f90:1004
integer, public tide_forcing_type
Definition: mod_force.f90:78
real(sp), dimension(:,:), allocatable, target t1
Definition: mod_main.f90:1307
real(sp), dimension(:), allocatable elm2
Definition: mod_obcs.f90:102
integer, dimension(:,:), allocatable obc_lst
Definition: mod_obcs.f90:84
real(sp) dti
Definition: mod_main.f90:844
real(sp), dimension(:), allocatable iucp
Definition: mod_obcs.f90:110
integer, target nprocs
Definition: mod_main.f90:72
subroutine elevation_atmo
Definition: mod_obcs.f90:188
real(sp), dimension(:), allocatable nyobc
Definition: mod_obcs.f90:97
subroutine setup_obc
Definition: mod_obcs.f90:592
real(sp), dimension(:,:), allocatable xflux_obc
Definition: mod_obcs.f90:113
integer, parameter, public tide_forcing_timeseries
Definition: mod_force.f90:80
integer, dimension(:), allocatable next_obc2
Definition: mod_obcs.f90:79
real(sp), dimension(:,:), allocatable s1m2
Definition: mod_obcs.f90:106
real(sp), dimension(:,:), allocatable apt
Definition: mod_main.f90:1796
real(sp), dimension(:,:), allocatable, target s1
Definition: mod_main.f90:1308
integer, parameter, public tide_forcing_spectral
Definition: mod_force.f90:79
real(sp), dimension(:,:), allocatable temp_obc
Definition: mod_obcs.f90:91
integer, dimension(:), allocatable next_obc
Definition: mod_obcs.f90:78
real(sp), dimension(:), allocatable period
Definition: mod_main.f90:1795
real(sp), dimension(:), allocatable, target vx
Definition: mod_main.f90:1001
real(sp), dimension(:), allocatable nxobc
Definition: mod_obcs.f90:96
integer iobcn
Definition: mod_main.f90:1777
integer ntidecomps
Definition: mod_main.f90:1794
real(sp), dimension(:,:), allocatable, target tf1
Definition: mod_main.f90:1310
real(sp), dimension(:), allocatable uard_obcn
Definition: mod_obcs.f90:112
subroutine pstop
Definition: mod_utils.f90:273
integer, parameter sp
Definition: mod_prec.f90:48
subroutine gday1(IDD, IMM, IYY, ICC, KD)
Definition: mod_obcs.f90:1023
real(sp), dimension(:), allocatable, target vy
Definition: mod_main.f90:1002
integer, dimension(:), allocatable, target ntve
Definition: mod_main.f90:1022
subroutine, public update_tide(NOW, BND_ELV)
Definition: mod_force.f90:6979
integer, dimension(:), allocatable i_obc_n
Definition: mod_main.f90:1779
real(sp), dimension(:), allocatable elm1
Definition: mod_obcs.f90:101
real(sp), dimension(:,:), allocatable, target sf1
Definition: mod_main.f90:1311
real(sp), dimension(:), allocatable, target elf
Definition: mod_main.f90:1140
real(sp), dimension(:), allocatable xflux_obcn
Definition: mod_obcs.f90:111
type(time) spectime
Definition: mod_main.f90:841
subroutine bcond_ore
Definition: mod_obcs.f90:439
integer, dimension(:,:), allocatable, target nv
Definition: mod_main.f90:1018
integer, dimension(5) ibcn
Definition: mod_obcs.f90:82
integer, dimension(5) ibcn_gl
Definition: mod_obcs.f90:83
real(sp), dimension(:,:), allocatable t1m2
Definition: mod_obcs.f90:104
real(dp), parameter zero
Definition: mod_main.f90:882
real(dp), parameter pi2
Definition: mod_main.f90:881
integer, dimension(:,:), allocatable adjc_obc
Definition: mod_obcs.f90:88
real(sp), dimension(:,:), allocatable, target dz
Definition: mod_main.f90:1092
subroutine assign_elm1_to_elm2
Definition: mod_obcs.f90:156
real(sp), dimension(:), allocatable, target elf_atmo
Definition: mod_main.f90:1150
real(dp) function seconds(MJD)
Definition: mod_time.f90:742
integer, dimension(:), allocatable type_obc_gl
Definition: mod_main.f90:1782
subroutine bcond_bki(K_RK)
Definition: mod_obcs.f90:404
real(sp), dimension(:), allocatable fluxobn
Definition: mod_obcs.f90:109
integer, dimension(:,:), allocatable, target nbve
Definition: mod_main.f90:1034
integer, parameter dp
Definition: mod_prec.f90:52
subroutine fatal_error(ER1, ER2, ER3, ER4)
Definition: mod_utils.f90:230
real(sp), dimension(:), allocatable, target lon
Definition: mod_main.f90:995
real(sp), dimension(:), allocatable, target xc
Definition: mod_main.f90:1003
real(sp), dimension(:,:), allocatable phai
Definition: mod_main.f90:1797
subroutine bcond_gwi(K_RK)
Definition: mod_obcs.f90:369
real(sp), dimension(:), allocatable, target grav_n
Definition: mod_main.f90:1013
integer iobcn_gl
Definition: mod_main.f90:1775
subroutine bcond_asl_clp
Definition: mod_obcs.f90:344
real(sp) ramp
Definition: mod_main.f90:845
integer, dimension(:,:), allocatable, target nbsn
Definition: mod_main.f90:1030
subroutine setup_obctypes
Definition: mod_obcs.f90:478
integer ipt
Definition: mod_main.f90:922
integer, dimension(:), allocatable, target isonb
Definition: mod_main.f90:1024
real(sp), dimension(:,:), allocatable t1m1
Definition: mod_obcs.f90:103
subroutine bcond_s_perturbation(S2D_NEXT, S2D, STMP, I, J, J1)
Definition: mod_obcs.f90:949
real(sp), dimension(:,:), allocatable salt_obc
Definition: mod_obcs.f90:92
subroutine alloc_obc_data
Definition: mod_obcs.f90:119
integer, parameter dbg_log
Definition: mod_utils.f90:65
type(time) rktime
Definition: mod_main.f90:829