7 use mom_cpu_clock,
only : cpu_clock_id, cpu_clock_begin, cpu_clock_end, clock_routine
15 use mom_io,
only : east_face, north_face
16 use mom_io,
only : slasher, read_data, field_size, single_file
22 use time_interp_external_mod,
only : init_external_field, time_interp_external
23 use time_interp_external_mod,
only : time_interp_external_init
31 implicit none ;
private
33 #include <MOM_memory.h>
73 character(len=8) :: name
74 real,
pointer,
dimension(:,:,:) :: buffer_src=>null()
77 real,
dimension(:,:,:),
pointer :: dz_src=>null()
78 real,
dimension(:,:,:),
pointer :: buffer_dst=>null()
79 real,
dimension(:,:),
pointer :: bt_vel=>null()
85 real,
dimension(:,:,:),
pointer :: t => null()
86 real :: obc_inflow_conc = 0.0
87 character(len=32) :: name
89 real,
dimension(:,:,:),
pointer :: tres => null()
90 logical :: is_initialized
97 logical :: locked = .false.
107 logical :: radiation_tan
109 logical :: radiation_grad
112 logical :: oblique_tan
114 logical :: oblique_grad
117 logical :: nudged_tan
118 logical :: nudged_grad
120 logical :: specified_tan
123 logical :: values_needed
124 logical :: u_values_needed
125 logical :: v_values_needed
126 logical :: t_values_needed
127 logical :: s_values_needed
128 logical :: z_values_needed
129 logical :: g_values_needed
133 logical :: is_e_or_w_2
135 integer :: num_fields
136 character(len=32),
pointer,
dimension(:) :: field_names=>null()
141 real :: velocity_nudging_timescale_in
142 real :: velocity_nudging_timescale_out
144 logical :: temp_segment_data_exists
145 logical :: salt_segment_data_exists
146 real,
pointer,
dimension(:,:) :: cg=>null()
148 real,
pointer,
dimension(:,:) :: htot=>null()
149 real,
pointer,
dimension(:,:,:) :: h=>null()
150 real,
pointer,
dimension(:,:,:) :: normal_vel=>null()
152 real,
pointer,
dimension(:,:,:) :: tangential_vel=>null()
154 real,
pointer,
dimension(:,:,:) :: tangential_grad=>null()
156 real,
pointer,
dimension(:,:,:) :: normal_trans=>null()
158 real,
pointer,
dimension(:,:) :: normal_vel_bt=>null()
160 real,
pointer,
dimension(:,:) :: eta=>null()
161 real,
pointer,
dimension(:,:,:) :: grad_normal=>null()
163 real,
pointer,
dimension(:,:,:) :: grad_tan=>null()
165 real,
pointer,
dimension(:,:,:) :: grad_gradient=>null()
167 real,
pointer,
dimension(:,:,:) :: rx_norm_rad=>null()
169 real,
pointer,
dimension(:,:,:) :: ry_norm_rad=>null()
171 real,
pointer,
dimension(:,:,:) :: rx_norm_obl=>null()
173 real,
pointer,
dimension(:,:,:) :: ry_norm_obl=>null()
175 real,
pointer,
dimension(:,:,:) :: cff_normal=>null()
177 real,
pointer,
dimension(:,:,:) :: nudged_normal_vel=>null()
179 real,
pointer,
dimension(:,:,:) :: nudged_tangential_vel=>null()
181 real,
pointer,
dimension(:,:,:) :: nudged_tangential_grad=>null()
184 type(hor_index_type) :: hi
185 real :: tr_invlscale_out
189 real :: tr_invlscale_in
196 integer :: number_of_segments = 0
198 logical :: open_u_bcs_exist_globally = .false.
200 logical :: open_v_bcs_exist_globally = .false.
202 logical :: flather_u_bcs_exist_globally = .false.
204 logical :: flather_v_bcs_exist_globally = .false.
206 logical :: oblique_bcs_exist_globally = .false.
208 logical :: nudged_u_bcs_exist_globally = .false.
210 logical :: nudged_v_bcs_exist_globally = .false.
212 logical :: specified_u_bcs_exist_globally = .false.
214 logical :: specified_v_bcs_exist_globally = .false.
216 logical :: radiation_bcs_exist_globally = .false.
217 logical :: user_bcs_set_globally = .false.
219 logical :: update_obc = .false.
220 logical :: needs_io_for_data = .false.
221 logical :: zero_vorticity = .false.
222 logical :: freeslip_vorticity = .false.
224 logical :: computed_vorticity = .false.
226 logical :: specified_vorticity = .false.
228 logical :: zero_strain = .false.
229 logical :: freeslip_strain = .false.
231 logical :: computed_strain = .false.
233 logical :: specified_strain = .false.
235 logical :: zero_biharmonic = .false.
237 logical :: brushcutter_mode = .false.
239 logical,
pointer,
dimension(:) :: &
240 tracer_x_reservoirs_used => null()
242 logical,
pointer,
dimension(:) :: &
243 tracer_y_reservoirs_used => null()
250 integer,
pointer,
dimension(:,:) :: &
251 segnum_u => null(), &
265 real,
pointer,
dimension(:,:,:) :: &
266 rx_normal => null(), &
268 ry_normal => null(), &
270 rx_oblique => null(), &
271 ry_oblique => null(), &
273 real,
pointer,
dimension(:,:,:,:) :: &
285 real :: tide_flow = 3.0e6
290 character(len=32) :: name
297 logical :: locked = .false.
303 character(len=40) ::
mdl =
"MOM_open_boundary"
305 #include "version_variable.h"
323 logical :: debug_obc, debug, mask_outside, reentrant_x, reentrant_y
324 character(len=15) :: segment_param_str
325 character(len=100) :: segment_str
326 character(len=200) :: config1
327 real :: lscale_in, lscale_out
331 "Controls where open boundaries are located, what kind of boundary condition "//&
332 "to impose, and what data to apply, if any.")
333 call get_param(param_file,
mdl,
"OBC_NUMBER_OF_SEGMENTS", obc%number_of_segments, &
334 "The number of open boundary segments.", &
336 call get_param(param_file,
mdl,
"G_EARTH", obc%g_Earth, &
337 "The gravitational acceleration of the Earth.", &
338 units=
"m s-2", default = 9.80)
339 call get_param(param_file,
mdl,
"OBC_USER_CONFIG", config1, &
340 "A string that sets how the open boundary conditions are "//&
341 " configured: \n", default=
"none", do_not_log=.true.)
343 "The number of model layers", default=0, do_not_log=.true.)
345 if (config1 /=
"none" .and. config1 /=
"dyed_obcs") obc%user_BCs_set_globally = .true.
347 if (obc%number_of_segments > 0)
then
348 call get_param(param_file,
mdl,
"OBC_ZERO_VORTICITY", obc%zero_vorticity, &
349 "If true, sets relative vorticity to zero on open boundaries.", &
351 call get_param(param_file,
mdl,
"OBC_FREESLIP_VORTICITY", obc%freeslip_vorticity, &
352 "If true, sets the normal gradient of tangential velocity to "//&
353 "zero in the relative vorticity on open boundaries. This cannot "//&
354 "be true if another OBC_XXX_VORTICITY option is True.", default=.true.)
355 call get_param(param_file,
mdl,
"OBC_COMPUTED_VORTICITY", obc%computed_vorticity, &
356 "If true, uses the external values of tangential velocity "//&
357 "in the relative vorticity on open boundaries. This cannot "//&
358 "be true if another OBC_XXX_VORTICITY option is True.", default=.false.)
359 call get_param(param_file,
mdl,
"OBC_SPECIFIED_VORTICITY", obc%specified_vorticity, &
360 "If true, uses the external values of tangential velocity "//&
361 "in the relative vorticity on open boundaries. This cannot "//&
362 "be true if another OBC_XXX_VORTICITY option is True.", default=.false.)
363 if ((obc%zero_vorticity .and. obc%freeslip_vorticity) .or. &
364 (obc%zero_vorticity .and. obc%computed_vorticity) .or. &
365 (obc%zero_vorticity .and. obc%specified_vorticity) .or. &
366 (obc%freeslip_vorticity .and. obc%computed_vorticity) .or. &
367 (obc%freeslip_vorticity .and. obc%specified_vorticity) .or. &
368 (obc%computed_vorticity .and. obc%specified_vorticity)) &
369 call mom_error(fatal,
"MOM_open_boundary.F90, open_boundary_config:\n"//&
370 "Only one of OBC_ZERO_VORTICITY, OBC_FREESLIP_VORTICITY, OBC_COMPUTED_VORTICITY\n"//&
371 "and OBC_IMPORTED_VORTICITY can be True at once.")
372 call get_param(param_file,
mdl,
"OBC_ZERO_STRAIN", obc%zero_strain, &
373 "If true, sets the strain used in the stress tensor to zero on open boundaries.", &
375 call get_param(param_file,
mdl,
"OBC_FREESLIP_STRAIN", obc%freeslip_strain, &
376 "If true, sets the normal gradient of tangential velocity to "//&
377 "zero in the strain use in the stress tensor on open boundaries. This cannot "//&
378 "be true if another OBC_XXX_STRAIN option is True.", default=.true.)
379 call get_param(param_file,
mdl,
"OBC_COMPUTED_STRAIN", obc%computed_strain, &
380 "If true, sets the normal gradient of tangential velocity to "//&
381 "zero in the strain use in the stress tensor on open boundaries. This cannot "//&
382 "be true if another OBC_XXX_STRAIN option is True.", default=.false.)
383 call get_param(param_file,
mdl,
"OBC_SPECIFIED_STRAIN", obc%specified_strain, &
384 "If true, sets the normal gradient of tangential velocity to "//&
385 "zero in the strain use in the stress tensor on open boundaries. This cannot "//&
386 "be true if another OBC_XXX_STRAIN option is True.", default=.false.)
387 if ((obc%zero_strain .and. obc%freeslip_strain) .or. &
388 (obc%zero_strain .and. obc%computed_strain) .or. &
389 (obc%zero_strain .and. obc%specified_strain) .or. &
390 (obc%freeslip_strain .and. obc%computed_strain) .or. &
391 (obc%freeslip_strain .and. obc%specified_strain) .or. &
392 (obc%computed_strain .and. obc%specified_strain)) &
393 call mom_error(fatal,
"MOM_open_boundary.F90, open_boundary_config: \n"//&
394 "Only one of OBC_ZERO_STRAIN, OBC_FREESLIP_STRAIN, OBC_COMPUTED_STRAIN \n"//&
395 "and OBC_IMPORTED_STRAIN can be True at once.")
396 call get_param(param_file,
mdl,
"OBC_ZERO_BIHARMONIC", obc%zero_biharmonic, &
397 "If true, zeros the Laplacian of flow on open boundaries in the biharmonic "//&
398 "viscosity term.", default=.false.)
399 call get_param(param_file,
mdl,
"MASK_OUTSIDE_OBCS", mask_outside, &
400 "If true, set the areas outside open boundaries to be land.", &
402 call get_param(param_file,
mdl,
"DEBUG", debug, default=.false.)
403 call get_param(param_file,
mdl,
"DEBUG_OBC", debug_obc, default=.false.)
404 if (debug_obc .or. debug) &
405 call log_param(param_file,
mdl,
"DEBUG_OBC", debug_obc, &
406 "If true, do additional calls to help debug the performance "//&
407 "of the open boundary condition code.", default=.false., &
408 debuggingparam=.true.)
410 call get_param(param_file,
mdl,
"OBC_SILLY_THICK", obc%silly_h, &
411 "A silly value of thicknesses used outside of open boundary "//&
412 "conditions for debugging.", units=
"m", default=0.0, scale=us%m_to_Z, &
413 do_not_log=.not.debug_obc, debuggingparam=.true.)
414 call get_param(param_file,
mdl,
"OBC_SILLY_VEL", obc%silly_u, &
415 "A silly value of velocities used outside of open boundary "//&
416 "conditions for debugging.", units=
"m/s", default=0.0, scale=us%m_s_to_L_T, &
417 do_not_log=.not.debug_obc, debuggingparam=.true.)
418 reentrant_x = .false.
419 call get_param(param_file,
mdl,
"REENTRANT_X", reentrant_x, default=.true.)
420 reentrant_y = .false.
421 call get_param(param_file,
mdl,
"REENTRANT_Y", reentrant_y, default=.false.)
425 allocate(obc%segment(0:obc%number_of_segments))
426 do l=0,obc%number_of_segments
427 obc%segment(l)%Flather = .false.
428 obc%segment(l)%radiation = .false.
429 obc%segment(l)%radiation_tan = .false.
430 obc%segment(l)%radiation_grad = .false.
431 obc%segment(l)%oblique = .false.
432 obc%segment(l)%oblique_tan = .false.
433 obc%segment(l)%oblique_grad = .false.
434 obc%segment(l)%nudged = .false.
435 obc%segment(l)%nudged_tan = .false.
436 obc%segment(l)%nudged_grad = .false.
437 obc%segment(l)%specified = .false.
438 obc%segment(l)%specified_tan = .false.
439 obc%segment(l)%open = .false.
440 obc%segment(l)%gradient = .false.
441 obc%segment(l)%values_needed = .false.
442 obc%segment(l)%u_values_needed = .false.
443 obc%segment(l)%v_values_needed = .false.
444 obc%segment(l)%t_values_needed = .false.
445 obc%segment(l)%s_values_needed = .false.
446 obc%segment(l)%z_values_needed = .false.
447 obc%segment(l)%g_values_needed = .false.
449 obc%segment(l)%is_N_or_S = .false.
450 obc%segment(l)%is_E_or_W = .false.
451 obc%segment(l)%is_E_or_W_2 = .false.
452 obc%segment(l)%Velocity_nudging_timescale_in = 0.0
453 obc%segment(l)%Velocity_nudging_timescale_out = 0.0
454 obc%segment(l)%num_fields = 0
456 allocate(obc%segnum_u(g%IsdB:g%IedB,g%jsd:g%jed)) ; obc%segnum_u(:,:) =
obc_none
457 allocate(obc%segnum_v(g%isd:g%ied,g%JsdB:g%JedB)) ; obc%segnum_v(:,:) =
obc_none
459 do l = 1, obc%number_of_segments
460 write(segment_param_str(1:15),
"('OBC_SEGMENT_',i3.3)") l
461 call get_param(param_file,
mdl, segment_param_str, segment_str, &
462 "Documentation needs to be dynamic?????", &
463 fail_if_missing=.true.)
465 if (segment_str(1:2) ==
'I=')
then
467 elseif (segment_str(1:2) ==
'J=')
then
470 call mom_error(fatal,
"MOM_open_boundary.F90, open_boundary_config: "//&
471 "Unable to interpret "//segment_param_str//
" = "//trim(segment_str))
479 call get_param(param_file,
mdl,
"OBC_RADIATION_MAX", obc%rx_max, &
480 "The maximum magnitude of the baroclinic radiation "//&
481 "velocity (or speed of characteristics). This is only "//&
482 "used if one of the open boundary segments is using Orlanski.", &
483 units=
"m s-1", default=10.0)
484 call get_param(param_file,
mdl,
"OBC_RAD_VEL_WT", obc%gamma_uv, &
485 "The relative weighting for the baroclinic radiation "//&
486 "velocities (or speed of characteristics) at the new "//&
487 "time level (1) or the running mean (0) for velocities. "//&
488 "Valid values range from 0 to 1. This is only used if "//&
489 "one of the open boundary segments is using Orlanski.", &
490 units=
"nondim", default=0.3)
496 call get_param(param_file,
mdl,
"OBC_TRACER_RESERVOIR_LENGTH_SCALE_OUT ", lscale_out, &
497 "An effective length scale for restoring the tracer concentration "//&
498 "at the boundaries to externally imposed values when the flow "//&
499 "is exiting the domain.", units=
"m", default=0.0, scale=us%m_to_L)
501 call get_param(param_file,
mdl,
"OBC_TRACER_RESERVOIR_LENGTH_SCALE_IN ", lscale_in, &
502 "An effective length scale for restoring the tracer concentration "//&
503 "at the boundaries to values from the interior when the flow "//&
504 "is entering the domain.", units=
"m", default=0.0, scale=us%m_to_L)
512 do l = 1, obc%number_of_segments
513 obc%segment(l)%Tr_InvLscale_in = 0.0
514 if (lscale_in>0.) obc%segment(l)%Tr_InvLscale_in = 1.0/lscale_in
515 obc%segment(l)%Tr_InvLscale_out = 0.0
516 if (lscale_out>0.) obc%segment(l)%Tr_InvLscale_out = 1.0/lscale_out
522 if ((obc%open_u_BCs_exist_globally .or. obc%open_v_BCs_exist_globally) .and. &
523 .not.g%symmetric )
call mom_error(fatal, &
524 "MOM_open_boundary, open_boundary_config: "//&
525 "Symmetric memory must be used when using Flather OBCs.")
527 if (.not.(obc%specified_u_BCs_exist_globally .or. obc%specified_v_BCs_exist_globally .or. &
528 obc%open_u_BCs_exist_globally .or. obc%open_v_BCs_exist_globally))
then
533 call time_interp_external_init()
541 use mpp_mod,
only : mpp_pe, mpp_set_current_pelist, mpp_get_current_pelist,mpp_npes
547 integer :: n,m,num_fields
548 character(len=256) :: segstr, filename
549 character(len=20) :: segnam, suffix
550 character(len=32) :: varnam, fieldname
552 character(len=32),
dimension(MAX_OBC_FIELDS) :: fields
553 character(len=128) :: inputdir
555 character(len=32) :: remappingScheme
556 character(len=256) :: mesg
557 logical :: check_reconstruction, check_remapping, force_bounds_in_subcell
558 integer,
dimension(4) :: siz,siz2
559 integer :: is, ie, js, je
560 integer :: isd, ied, jsd, jed
561 integer :: IsdB, IedB, JsdB, JedB
562 integer,
dimension(:),
allocatable :: saved_pelist
563 integer :: current_pe
564 integer,
dimension(1) :: single_pelist
567 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
574 call get_param(pf,
mdl,
"INPUTDIR", inputdir, default=
".")
575 inputdir = slasher(inputdir)
577 call get_param(pf,
mdl,
"REMAPPING_SCHEME", remappingscheme, &
578 "This sets the reconstruction scheme used "//&
579 "for vertical remapping for all variables. "//&
580 "It can be one of the following schemes: \n"//&
581 trim(remappingschemesdoc), default=remappingdefaultscheme,do_not_log=.true.)
582 call get_param(pf,
mdl,
"FATAL_CHECK_RECONSTRUCTIONS", check_reconstruction, &
583 "If true, cell-by-cell reconstructions are checked for "//&
584 "consistency and if non-monotonicity or an inconsistency is "//&
585 "detected then a FATAL error is issued.", default=.false.,do_not_log=.true.)
586 call get_param(pf,
mdl,
"FATAL_CHECK_REMAPPING", check_remapping, &
587 "If true, the results of remapping are checked for "//&
588 "conservation and new extrema and if an inconsistency is "//&
589 "detected then a FATAL error is issued.", default=.false.,do_not_log=.true.)
590 call get_param(pf,
mdl,
"REMAP_BOUND_INTERMEDIATE_VALUES", force_bounds_in_subcell, &
591 "If true, the values on the intermediate grid used for remapping "//&
592 "are forced to be bounded, which might not be the case due to "//&
593 "round off.", default=.false.,do_not_log=.true.)
594 call get_param(pf,
mdl,
"BRUSHCUTTER_MODE", obc%brushcutter_mode, &
595 "If true, read external OBC data on the supergrid.", &
598 allocate(obc%remap_CS)
600 check_reconstruction=check_reconstruction, &
601 check_remapping=check_remapping, force_bounds_in_subcell=force_bounds_in_subcell)
603 if (obc%user_BCs_set_globally)
return
606 do n=1, obc%number_of_segments
607 segment => obc%segment(n)
608 write(segnam,
"('OBC_SEGMENT_',i3.3,'_DATA')") n
609 call get_param(pf,
mdl, segnam, segstr,
'OBC segment docs')
614 allocate(saved_pelist(0:mpp_npes()-1))
615 call mpp_get_current_pelist(saved_pelist)
616 current_pe = mpp_pe()
617 single_pelist(1) = current_pe
618 call mpp_set_current_pelist(single_pelist)
620 do n=1, obc%number_of_segments
621 segment => obc%segment(n)
622 if (.not. segment%values_needed) cycle
624 write(segnam,
"('OBC_SEGMENT_',i3.3,'_DATA')") n
625 write(suffix,
"('_segment_',i3.3)") n
632 if (segstr ==
'')
then
633 write(mesg,
'("No OBC_SEGMENT_XXX_DATA string for OBC segment ",I3)') n
638 if (num_fields == 0)
then
639 call mom_mesg(
'initialize_segment_data: num_fields = 0')
643 allocate(segment%field(num_fields))
644 segment%num_fields = num_fields
646 segment%temp_segment_data_exists=.false.
647 segment%salt_segment_data_exists=.false.
652 isd = segment%HI%isd ; ied = segment%HI%ied
653 jsd = segment%HI%jsd ; jed = segment%HI%jed
654 isdb = segment%HI%IsdB ; iedb = segment%HI%IedB
655 jsdb = segment%HI%JsdB ; jedb = segment%HI%JedB
658 call parse_segment_data_str(trim(segstr), var=trim(fields(m)),
value=
value, filenam=filename, fieldnam=fieldname)
659 if (trim(filename) /=
'none')
then
660 obc%update_OBC = .true.
661 obc%needs_IO_for_data = .true.
663 segment%field(m)%name = trim(fields(m))
664 if (segment%field(m)%name ==
'TEMP')
then
665 segment%temp_segment_data_exists=.true.
666 segment%t_values_needed = .false.
668 if (segment%field(m)%name ==
'SALT')
then
669 segment%salt_segment_data_exists=.true.
670 segment%s_values_needed = .false.
672 filename = trim(inputdir)//trim(filename)
673 fieldname = trim(fieldname)//trim(suffix)
674 call field_size(filename,fieldname,siz,no_domain=.true.)
676 if (segment%on_pe)
then
677 if (obc%brushcutter_mode .and. (modulo(siz(1),2) == 0 .or. modulo(siz(2),2) == 0))
then
678 call mom_error(fatal,
'segment data are not on the supergrid')
683 if (obc%brushcutter_mode)
then
691 if (obc%brushcutter_mode)
then
699 if (segment%is_E_or_W)
then
700 if (segment%field(m)%name ==
'V')
then
701 allocate(segment%field(m)%buffer_src(isdb:iedb,jsdb:jedb,siz2(3)))
702 segment%v_values_needed = .false.
703 else if (segment%field(m)%name ==
'DVDX')
then
704 allocate(segment%field(m)%buffer_src(isdb:iedb,jsdb:jedb,siz2(3)))
705 segment%g_values_needed = .false.
707 allocate(segment%field(m)%buffer_src(isdb:iedb,jsd:jed,siz2(3)))
708 if (segment%field(m)%name ==
'U')
then
709 segment%u_values_needed = .false.
710 else if (segment%field(m)%name ==
'SSH')
then
711 segment%z_values_needed = .false.
712 else if (segment%field(m)%name ==
'TEMP')
then
713 segment%t_values_needed = .false.
714 else if (segment%field(m)%name ==
'SALT')
then
715 segment%s_values_needed = .false.
719 if (segment%field(m)%name ==
'U')
then
720 allocate(segment%field(m)%buffer_src(isdb:iedb,jsdb:jedb,siz2(3)))
721 segment%u_values_needed = .false.
722 else if (segment%field(m)%name ==
'DUDY')
then
723 allocate(segment%field(m)%buffer_src(isdb:iedb,jsdb:jedb,siz2(3)))
724 segment%g_values_needed = .false.
726 allocate(segment%field(m)%buffer_src(isd:ied,jsdb:jedb,siz2(3)))
727 if (segment%field(m)%name ==
'V')
then
728 segment%v_values_needed = .false.
729 else if (segment%field(m)%name ==
'SSH')
then
730 segment%z_values_needed = .false.
731 else if (segment%field(m)%name ==
'TEMP')
then
732 segment%t_values_needed = .false.
733 else if (segment%field(m)%name ==
'SALT')
then
734 segment%s_values_needed = .false.
738 segment%field(m)%buffer_src(:,:,:)=0.0
739 segment%field(m)%fid = init_external_field(trim(filename),&
740 trim(fieldname),ignore_axis_atts=.true.,threading=single_file)
742 fieldname =
'dz_'//trim(fieldname)
743 call field_size(filename,fieldname,siz,no_domain=.true.)
744 if (segment%is_E_or_W)
then
745 if (segment%field(m)%name ==
'V' .or. segment%field(m)%name ==
'DVDX')
then
746 allocate(segment%field(m)%dz_src(isdb:iedb,jsdb:jedb,siz(3)))
748 allocate(segment%field(m)%dz_src(isdb:iedb,jsd:jed,siz(3)))
751 if (segment%field(m)%name ==
'U' .or. segment%field(m)%name ==
'DUDY')
then
752 allocate(segment%field(m)%dz_src(isdb:iedb,jsdb:jedb,siz(3)))
754 allocate(segment%field(m)%dz_src(isd:ied,jsdb:jedb,siz(3)))
757 segment%field(m)%dz_src(:,:,:)=0.0
758 segment%field(m)%nk_src=siz(3)
759 segment%field(m)%fid_dz = init_external_field(trim(filename),trim(fieldname),&
760 ignore_axis_atts=.true.,threading=single_file)
762 segment%field(m)%nk_src=1
766 segment%field(m)%fid = -1
767 segment%field(m)%value =
value
768 segment%field(m)%name = trim(fields(m))
769 if (segment%field(m)%name ==
'U')
then
770 segment%u_values_needed = .false.
771 elseif (segment%field(m)%name ==
'V')
then
772 segment%v_values_needed = .false.
773 elseif (segment%field(m)%name ==
'SSH')
then
774 segment%z_values_needed = .false.
775 elseif (segment%field(m)%name ==
'TEMP')
then
776 segment%t_values_needed = .false.
777 elseif (segment%field(m)%name ==
'SALT')
then
778 segment%s_values_needed = .false.
779 elseif (segment%field(m)%name ==
'DVDX' .or. segment%field(m)%name ==
'DUDY')
then
780 segment%g_values_needed = .false.
784 if (segment%u_values_needed .or. segment%v_values_needed .or. &
785 segment%t_values_needed .or. segment%s_values_needed .or. &
786 segment%z_values_needed .or. segment%g_values_needed)
then
787 write(mesg,
'("Values needed for OBC segment ",I3)') n
792 call mpp_set_current_pelist(saved_pelist)
801 integer,
intent(in) :: Is_obc
802 integer,
intent(in) :: Ie_obc
803 integer,
intent(in) :: Js_obc
804 integer,
intent(in) :: Je_obc
806 integer :: Isg,Ieg,Jsg,Jeg
809 if (ie_obc<is_obc)
then
810 isg=ie_obc;ieg=is_obc
812 isg=is_obc;ieg=ie_obc
814 if (je_obc<js_obc)
then
815 jsg=je_obc;jeg=js_obc
817 jsg=js_obc;jeg=je_obc
821 seg%HI%IsgB = isg ; seg%HI%IegB = ieg
822 seg%HI%isg = isg+1 ; seg%HI%ieg = ieg
823 seg%HI%JsgB = jsg ; seg%HI%JegB = jeg
824 seg%HI%jsg = jsg+1 ; seg%HI%Jeg = jeg
827 isg = isg - g%idg_offset
828 jsg = jsg - g%jdg_offset
829 ieg = ieg - g%idg_offset
830 jeg = jeg - g%jdg_offset
834 seg%HI%IsdB = min( max(isg, g%HI%IsdB), g%HI%IedB)
835 seg%HI%IedB = min( max(ieg, g%HI%IsdB), g%HI%IedB)
836 seg%HI%isd = min( max(isg+1, g%HI%isd), g%HI%ied)
837 seg%HI%ied = min( max(ieg, g%HI%isd), g%HI%ied)
838 seg%HI%IscB = min( max(isg, g%HI%IscB), g%HI%IecB)
839 seg%HI%IecB = min( max(ieg, g%HI%IscB), g%HI%IecB)
840 seg%HI%isc = min( max(isg+1, g%HI%isc), g%HI%iec)
841 seg%HI%iec = min( max(ieg, g%HI%isc), g%HI%iec)
845 seg%HI%JsdB = min( max(jsg, g%HI%JsdB), g%HI%JedB)
846 seg%HI%JedB = min( max(jeg, g%HI%JsdB), g%HI%JedB)
847 seg%HI%jsd = min( max(jsg+1, g%HI%jsd), g%HI%jed)
848 seg%HI%jed = min( max(jeg, g%HI%jsd), g%HI%jed)
849 seg%HI%JscB = min( max(jsg, g%HI%JscB), g%HI%JecB)
850 seg%HI%JecB = min( max(jeg, g%HI%JscB), g%HI%JecB)
851 seg%HI%jsc = min( max(jsg+1, g%HI%jsc), g%HI%jec)
852 seg%HI%jec = min( max(jeg, g%HI%jsc), g%HI%jec)
861 character(len=*),
intent(in) :: segment_str
862 integer,
intent(in) :: l_seg
864 logical,
intent(in) :: reentrant_y
866 integer :: I_obc, Js_obc, Je_obc
868 character(len=32) :: action_str(8)
869 character(len=128) :: segment_param_str
870 real,
allocatable,
dimension(:) :: tnudge
872 call parse_segment_str(g%ieg, g%jeg, segment_str, i_obc, js_obc, je_obc, action_str, reentrant_y)
876 i_obc = i_obc - g%idg_offset
877 js_obc = js_obc - g%jdg_offset
878 je_obc = je_obc - g%jdg_offset
880 if (je_obc>js_obc)
then
882 elseif (je_obc<js_obc)
then
884 j=js_obc;js_obc=je_obc;je_obc=j
887 obc%segment(l_seg)%on_pe = .false.
890 if (len_trim(action_str(a_loop)) == 0)
then
892 elseif (trim(action_str(a_loop)) ==
'FLATHER')
then
893 obc%segment(l_seg)%Flather = .true.
894 obc%segment(l_seg)%open = .true.
895 obc%Flather_u_BCs_exist_globally = .true.
896 obc%open_u_BCs_exist_globally = .true.
897 obc%segment%z_values_needed = .true.
898 obc%segment%u_values_needed = .true.
899 elseif (trim(action_str(a_loop)) ==
'ORLANSKI')
then
900 obc%segment(l_seg)%radiation = .true.
901 obc%segment(l_seg)%open = .true.
902 obc%open_u_BCs_exist_globally = .true.
903 obc%radiation_BCs_exist_globally = .true.
904 elseif (trim(action_str(a_loop)) ==
'ORLANSKI_TAN')
then
905 obc%segment(l_seg)%radiation = .true.
906 obc%segment(l_seg)%radiation_tan = .true.
907 obc%radiation_BCs_exist_globally = .true.
908 elseif (trim(action_str(a_loop)) ==
'ORLANSKI_GRAD')
then
909 obc%segment(l_seg)%radiation = .true.
910 obc%segment(l_seg)%radiation_grad = .true.
911 elseif (trim(action_str(a_loop)) ==
'OBLIQUE')
then
912 obc%segment(l_seg)%oblique = .true.
913 obc%segment(l_seg)%open = .true.
914 obc%oblique_BCs_exist_globally = .true.
915 obc%open_u_BCs_exist_globally = .true.
916 elseif (trim(action_str(a_loop)) ==
'OBLIQUE_TAN')
then
917 obc%segment(l_seg)%oblique = .true.
918 obc%segment(l_seg)%oblique_tan = .true.
919 obc%oblique_BCs_exist_globally = .true.
920 elseif (trim(action_str(a_loop)) ==
'OBLIQUE_GRAD')
then
921 obc%segment(l_seg)%oblique = .true.
922 obc%segment(l_seg)%oblique_grad = .true.
923 elseif (trim(action_str(a_loop)) ==
'NUDGED')
then
924 obc%segment(l_seg)%nudged = .true.
925 obc%nudged_u_BCs_exist_globally = .true.
926 obc%segment%u_values_needed = .true.
927 elseif (trim(action_str(a_loop)) ==
'NUDGED_TAN')
then
928 obc%segment(l_seg)%nudged_tan = .true.
929 obc%nudged_u_BCs_exist_globally = .true.
930 obc%segment%v_values_needed = .true.
931 elseif (trim(action_str(a_loop)) ==
'NUDGED_GRAD')
then
932 obc%segment(l_seg)%nudged_grad = .true.
933 obc%segment%g_values_needed = .true.
934 elseif (trim(action_str(a_loop)) ==
'GRADIENT')
then
935 obc%segment(l_seg)%gradient = .true.
936 obc%segment(l_seg)%open = .true.
937 obc%open_u_BCs_exist_globally = .true.
938 elseif (trim(action_str(a_loop)) ==
'SIMPLE')
then
939 obc%segment(l_seg)%specified = .true.
940 obc%specified_u_BCs_exist_globally = .true.
941 obc%segment%u_values_needed = .true.
942 elseif (trim(action_str(a_loop)) ==
'SIMPLE_TAN')
then
943 obc%segment(l_seg)%specified_tan = .true.
945 call mom_error(fatal,
"MOM_open_boundary.F90, setup_u_point_obc: "//&
946 "String '"//trim(action_str(a_loop))//
"' not understood.")
948 if (obc%segment(l_seg)%nudged .or. obc%segment(l_seg)%nudged_tan)
then
949 write(segment_param_str(1:43),
"('OBC_SEGMENT_',i3.3,'_VELOCITY_NUDGING_TIMESCALES')") l_seg
951 call get_param(pf,
mdl, segment_param_str(1:43), tnudge, &
952 "Timescales in days for nudging along a segment, "//&
953 "for inflow, then outflow. Setting both to zero should "//&
954 "behave like SIMPLE obcs for the baroclinic velocities.", &
955 fail_if_missing=.true., default=0., units=
"days", scale=86400.0*us%s_to_T)
956 obc%segment(l_seg)%Velocity_nudging_timescale_in = tnudge(1)
957 obc%segment(l_seg)%Velocity_nudging_timescale_out = tnudge(2)
963 obc%segment(l_seg)%is_E_or_W_2 = .true.
965 if (i_obc<=g%HI%IsdB+1 .or. i_obc>=g%HI%IedB-1)
return
966 if (je_obc<=g%HI%JsdB .or. js_obc>=g%HI%JedB)
return
968 obc%segment(l_seg)%on_pe = .true.
969 obc%segment(l_seg)%is_E_or_W = .true.
971 do j=g%HI%jsd, g%HI%jed
972 if (j>js_obc .and. j<=je_obc)
then
973 obc%segnum_u(i_obc,j) = l_seg
976 obc%segment(l_seg)%Is_obc = i_obc
977 obc%segment(l_seg)%Ie_obc = i_obc
978 obc%segment(l_seg)%Js_obc = js_obc
979 obc%segment(l_seg)%Je_obc = je_obc
982 if (obc%segment(l_seg)%oblique .and. obc%segment(l_seg)%radiation) &
983 call mom_error(fatal,
"MOM_open_boundary.F90, setup_u_point_obc: \n"//&
984 "Orlanski and Oblique OBC options cannot be used together on one segment.")
986 if (obc%segment(l_seg)%u_values_needed .or. obc%segment(l_seg)%v_values_needed .or. &
987 obc%segment(l_seg)%t_values_needed .or. obc%segment(l_seg)%s_values_needed .or. &
988 obc%segment(l_seg)%z_values_needed .or. obc%segment(l_seg)%g_values_needed) &
989 obc%segment(l_seg)%values_needed = .true.
997 character(len=*),
intent(in) :: segment_str
998 integer,
intent(in) :: l_seg
1000 logical,
intent(in) :: reentrant_x
1002 integer :: J_obc, Is_obc, Ie_obc
1003 integer :: i, a_loop
1004 character(len=32) :: action_str(8)
1005 character(len=128) :: segment_param_str
1006 real,
allocatable,
dimension(:) :: tnudge
1009 call parse_segment_str(g%ieg, g%jeg, segment_str, j_obc, is_obc, ie_obc, action_str, reentrant_x)
1013 j_obc = j_obc - g%jdg_offset
1014 is_obc = is_obc - g%idg_offset
1015 ie_obc = ie_obc - g%idg_offset
1017 if (ie_obc>is_obc)
then
1019 elseif (ie_obc<is_obc)
then
1021 i=is_obc;is_obc=ie_obc;ie_obc=i
1024 obc%segment(l_seg)%on_pe = .false.
1027 if (len_trim(action_str(a_loop)) == 0)
then
1029 elseif (trim(action_str(a_loop)) ==
'FLATHER')
then
1030 obc%segment(l_seg)%Flather = .true.
1031 obc%segment(l_seg)%open = .true.
1032 obc%Flather_v_BCs_exist_globally = .true.
1033 obc%open_v_BCs_exist_globally = .true.
1034 obc%segment%z_values_needed = .true.
1035 obc%segment%v_values_needed = .true.
1036 elseif (trim(action_str(a_loop)) ==
'ORLANSKI')
then
1037 obc%segment(l_seg)%radiation = .true.
1038 obc%segment(l_seg)%open = .true.
1039 obc%open_v_BCs_exist_globally = .true.
1040 obc%radiation_BCs_exist_globally = .true.
1041 elseif (trim(action_str(a_loop)) ==
'ORLANSKI_TAN')
then
1042 obc%segment(l_seg)%radiation = .true.
1043 obc%segment(l_seg)%radiation_tan = .true.
1044 obc%radiation_BCs_exist_globally = .true.
1045 elseif (trim(action_str(a_loop)) ==
'ORLANSKI_GRAD')
then
1046 obc%segment(l_seg)%radiation = .true.
1047 obc%segment(l_seg)%radiation_grad = .true.
1048 elseif (trim(action_str(a_loop)) ==
'OBLIQUE')
then
1049 obc%segment(l_seg)%oblique = .true.
1050 obc%segment(l_seg)%open = .true.
1051 obc%oblique_BCs_exist_globally = .true.
1052 obc%open_v_BCs_exist_globally = .true.
1053 elseif (trim(action_str(a_loop)) ==
'OBLIQUE_TAN')
then
1054 obc%segment(l_seg)%oblique = .true.
1055 obc%segment(l_seg)%oblique_tan = .true.
1056 obc%oblique_BCs_exist_globally = .true.
1057 elseif (trim(action_str(a_loop)) ==
'OBLIQUE_GRAD')
then
1058 obc%segment(l_seg)%oblique = .true.
1059 obc%segment(l_seg)%oblique_grad = .true.
1060 elseif (trim(action_str(a_loop)) ==
'NUDGED')
then
1061 obc%segment(l_seg)%nudged = .true.
1062 obc%nudged_v_BCs_exist_globally = .true.
1063 obc%segment%v_values_needed = .true.
1064 elseif (trim(action_str(a_loop)) ==
'NUDGED_TAN')
then
1065 obc%segment(l_seg)%nudged_tan = .true.
1066 obc%nudged_v_BCs_exist_globally = .true.
1067 obc%segment%u_values_needed = .true.
1068 elseif (trim(action_str(a_loop)) ==
'NUDGED_GRAD')
then
1069 obc%segment(l_seg)%nudged_grad = .true.
1070 obc%segment%g_values_needed = .true.
1071 elseif (trim(action_str(a_loop)) ==
'GRADIENT')
then
1072 obc%segment(l_seg)%gradient = .true.
1073 obc%segment(l_seg)%open = .true.
1074 obc%open_v_BCs_exist_globally = .true.
1075 elseif (trim(action_str(a_loop)) ==
'SIMPLE')
then
1076 obc%segment(l_seg)%specified = .true.
1077 obc%specified_v_BCs_exist_globally = .true.
1078 obc%segment%v_values_needed = .true.
1079 elseif (trim(action_str(a_loop)) ==
'SIMPLE_TAN')
then
1080 obc%segment(l_seg)%specified_tan = .true.
1082 call mom_error(fatal,
"MOM_open_boundary.F90, setup_v_point_obc: "//&
1083 "String '"//trim(action_str(a_loop))//
"' not understood.")
1085 if (obc%segment(l_seg)%nudged .or. obc%segment(l_seg)%nudged_tan)
then
1086 write(segment_param_str(1:43),
"('OBC_SEGMENT_',i3.3,'_VELOCITY_NUDGING_TIMESCALES')") l_seg
1088 call get_param(pf,
mdl, segment_param_str(1:43), tnudge, &
1089 "Timescales in days for nudging along a segment, "//&
1090 "for inflow, then outflow. Setting both to zero should "//&
1091 "behave like SIMPLE obcs for the baroclinic velocities.", &
1092 fail_if_missing=.true., default=0., units=
"days", scale=86400.0*us%s_to_T)
1093 obc%segment(l_seg)%Velocity_nudging_timescale_in = tnudge(1)
1094 obc%segment(l_seg)%Velocity_nudging_timescale_out = tnudge(2)
1100 if (j_obc<=g%HI%JsdB+1 .or. j_obc>=g%HI%JedB-1)
return
1101 if (ie_obc<=g%HI%IsdB .or. is_obc>=g%HI%IedB)
return
1103 obc%segment(l_seg)%on_pe = .true.
1104 obc%segment(l_seg)%is_N_or_S = .true.
1106 do i=g%HI%isd, g%HI%ied
1107 if (i>is_obc .and. i<=ie_obc)
then
1108 obc%segnum_v(i,j_obc) = l_seg
1111 obc%segment(l_seg)%Is_obc = is_obc
1112 obc%segment(l_seg)%Ie_obc = ie_obc
1113 obc%segment(l_seg)%Js_obc = j_obc
1114 obc%segment(l_seg)%Je_obc = j_obc
1117 if (obc%segment(l_seg)%oblique .and. obc%segment(l_seg)%radiation) &
1118 call mom_error(fatal,
"MOM_open_boundary.F90, setup_v_point_obc: \n"//&
1119 "Orlanski and Oblique OBC options cannot be used together on one segment.")
1121 if (obc%segment(l_seg)%u_values_needed .or. obc%segment(l_seg)%v_values_needed .or. &
1122 obc%segment(l_seg)%t_values_needed .or. obc%segment(l_seg)%s_values_needed .or. &
1123 obc%segment(l_seg)%z_values_needed .or. obc%segment(l_seg)%g_values_needed) &
1124 obc%segment(l_seg)%values_needed = .true.
1128 subroutine parse_segment_str(ni_global, nj_global, segment_str, l, m, n, action_str, reentrant)
1129 integer,
intent(in) :: ni_global
1130 integer,
intent(in) :: nj_global
1131 character(len=*),
intent(in) :: segment_str
1132 integer,
intent(out) :: l
1133 integer,
intent(out) :: m
1134 integer,
intent(out) :: n
1135 character(len=*),
intent(out) :: action_str(:)
1136 logical,
intent(in) :: reentrant
1138 character(len=24) :: word1, word2, m_word, n_word
1143 integer,
parameter :: halo = 10
1148 if (word1(1:2)==
'I=')
then
1151 if (.not. (word2(1:2)==
'J='))
call mom_error(fatal,
"MOM_open_boundary.F90, parse_segment_str: "//&
1152 "Second word of string '"//trim(segment_str)//
"' must start with 'J='.")
1153 elseif (word1(1:2)==
'J=')
then
1156 if (.not. (word2(1:2)==
'I='))
call mom_error(fatal,
"MOM_open_boundary.F90, parse_segment_str: "//&
1157 "Second word of string '"//trim(segment_str)//
"' must start with 'I='.")
1159 call mom_error(fatal,
"MOM_open_boundary.F90, parse_segment_str"//&
1160 "String '"//segment_str//
"' must start with 'I=' or 'J='.")
1165 if (l<0 .or. l>l_max)
then
1166 call mom_error(fatal,
"MOM_open_boundary.F90, parse_segment_str: "//&
1167 "First value from string '"//trim(segment_str)//
"' is outside of the physical domain.")
1174 if (m<-halo .or. m>mn_max+halo)
then
1175 call mom_error(fatal,
"MOM_open_boundary.F90, parse_segment_str: "//&
1176 "Beginning of range in string '"//trim(segment_str)//
"' is outside of the physical domain.")
1179 if (m<-1 .or. m>mn_max+1)
then
1180 call mom_error(fatal,
"MOM_open_boundary.F90, parse_segment_str: "//&
1181 "Beginning of range in string '"//trim(segment_str)//
"' is outside of the physical domain.")
1189 if (n<-halo .or. n>mn_max+halo)
then
1190 call mom_error(fatal,
"MOM_open_boundary.F90, parse_segment_str: "//&
1191 "End of range in string '"//trim(segment_str)//
"' is outside of the physical domain.")
1194 if (n<-1 .or. n>mn_max+1)
then
1195 call mom_error(fatal,
"MOM_open_boundary.F90, parse_segment_str: "//&
1196 "End of range in string '"//trim(segment_str)//
"' is outside of the physical domain.")
1200 if (abs(n-m)==0)
then
1201 call mom_error(fatal,
"MOM_open_boundary.F90, parse_segment_str: "//&
1202 "Range in string '"//trim(segment_str)//
"' must span one cell.")
1206 do j = 1,
size(action_str)
1214 character(len=*),
intent(in) :: string
1215 integer,
intent(in) :: imax
1219 slen = len_trim(string)
1220 if (slen==0)
call mom_error(fatal,
"MOM_open_boundary.F90, parse_segment_str"//&
1221 "Parsed string was empty!")
1222 if (len_trim(string)==1 .and. string(1:1)==
'N')
then
1224 elseif (string(1:1)==
'N')
then
1225 if (string(2:2)==
'+')
then
1228 elseif (string(2:2)==
'-')
then
1236 911
call mom_error(fatal,
"MOM_open_boundary.F90, parse_segment_str"//&
1237 "Problem reading value from string '"//trim(string)//
"'.")
1242 subroutine parse_segment_data_str(segment_str, var, value, filenam, fieldnam, fields, num_fields, debug )
1243 character(len=*),
intent(in) :: segment_str
1245 character(len=*),
optional,
intent(in) :: var
1246 character(len=*),
optional,
intent(out) :: filenam
1247 character(len=*),
optional,
intent(out) :: fieldnam
1249 real,
optional,
intent(out) ::
value
1250 character(len=*),
dimension(MAX_OBC_FIELDS), &
1251 optional,
intent(out) :: fields
1252 integer,
optional,
intent(out) :: num_fields
1253 logical,
optional,
intent(in) :: debug
1255 character(len=128) :: word1, word2, word3, method
1256 integer :: lword, nfields, n, m
1257 logical :: continue,dbg
1258 character(len=32),
dimension(MAX_OBC_FIELDS) :: flds
1263 if (
PRESENT(debug)) dbg=debug
1267 if (trim(word1) ==
'')
exit
1270 flds(nfields) = trim(word2)
1273 if (
PRESENT(fields))
then
1279 if (
PRESENT(num_fields))
then
1285 if (
PRESENT(var))
then
1287 if (trim(var)==trim(flds(n)))
then
1301 if (trim(word2) == trim(var))
then
1303 lword=len_trim(method)
1304 if (method(lword-3:lword) ==
'file')
then
1309 lword=len_trim(fieldnam)
1310 fieldnam = fieldnam(1:lword-1)
1312 elseif (method(lword-4:lword) ==
'value')
then
1316 lword=len_trim(word1)
1317 read(word1(1:lword),*,
end=986,err=987) value
1323 986
call mom_error(fatal,
'End of record while parsing segment data specification! '//trim(segment_str))
1324 987
call mom_error(fatal,
'Error while parsing segment data specification! '//trim(segment_str))
1333 type(param_file_type),
intent(in) :: PF
1334 logical,
intent(in) :: use_temperature
1337 integer :: n,m,num_fields
1338 character(len=256) :: segstr, filename
1339 character(len=20) :: segnam, suffix
1340 character(len=32) :: varnam, fieldname
1342 character(len=32),
dimension(MAX_OBC_FIELDS) :: fields
1344 character(len=256) :: mesg
1346 do n=1, obc%number_of_segments
1347 segment => obc%segment(n)
1348 write(segnam,
"('OBC_SEGMENT_',i3.3,'_DATA')") n
1349 write(suffix,
"('_segment_',i3.3)") n
1352 call get_param(pf,
mdl, segnam, segstr)
1353 if (segstr ==
'') cycle
1356 if (num_fields == 0) cycle
1360 call parse_segment_data_str(trim(segstr), var=trim(fields(m)),
value=
value, filenam=filename, fieldnam=fieldname)
1361 if (trim(filename) /=
'none')
then
1362 if (fields(m) ==
'TEMP')
then
1363 if (segment%is_E_or_W_2)
then
1364 obc%tracer_x_reservoirs_used(1) = .true.
1366 obc%tracer_y_reservoirs_used(1) = .true.
1369 if (fields(m) ==
'SALT')
then
1370 if (segment%is_E_or_W_2)
then
1371 obc%tracer_x_reservoirs_used(2) = .true.
1373 obc%tracer_y_reservoirs_used(2) = .true.
1379 if (use_temperature)
then
1380 if (segment%is_E_or_W_2)
then
1381 obc%tracer_x_reservoirs_used(1) = .true.
1382 obc%tracer_x_reservoirs_used(2) = .true.
1384 obc%tracer_y_reservoirs_used(1) = .true.
1385 obc%tracer_y_reservoirs_used(2) = .true.
1396 character(len=*),
intent(in) :: segment_str
1398 character(len=*),
intent(in) :: var
1399 real,
intent(out) :: param_value
1400 logical,
optional,
intent(in) :: debug
1402 character(len=128) :: word1, word2, word3, method
1403 integer :: lword, nfields, n, m
1404 logical :: continue,dbg
1405 character(len=32),
dimension(MAX_OBC_FIELDS) :: flds
1410 if (
PRESENT(debug)) dbg=debug
1413 word1 = extract_word(segment_str,
',',nfields+1)
1414 if (trim(word1) ==
'')
exit
1416 word2 = extract_word(word1,
'=',1)
1417 flds(nfields) = trim(word2)
1434 if (trim(var)==trim(flds(n)))
then
1444 word3 = extract_word(segment_str,
',',m)
1447 word2 = extract_word(word1,
'=',1)
1448 if (trim(word2) == trim(var))
then
1449 method=trim(extract_word(word1,
'=',2))
1450 lword=len_trim(method)
1451 read(method(1:lword),*,err=987) param_value
1471 986
call mom_error(fatal,
'End of record while parsing segment data specification! '//trim(segment_str))
1472 987
call mom_error(fatal,
'Error while parsing segment parameter specification! '//trim(segment_str))
1479 type(ocean_grid_type),
intent(in) :: g
1480 type(verticalgrid_type),
intent(in) :: gv
1481 type(unit_scale_type),
intent(in) :: us
1482 type(param_file_type),
intent(in) :: param_file
1484 type(mom_restart_cs),
pointer :: restart_csp
1487 real :: vel2_rescale
1489 integer :: i, j, k, isd, ied, jsd, jed, nz
1490 integer :: isdb, iedb, jsdb, jedb
1491 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed ; nz = gv%ke
1492 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
1494 if (.not.
associated(obc))
return
1496 id_clock_pass = cpu_clock_id(
'(Ocean OBC halo updates)', grain=clock_routine)
1517 if ( obc%oblique_BCs_exist_globally .and. (us%s_to_T_restart * us%m_to_L_restart /= 0.0) .and. &
1518 ((us%m_to_L * us%s_to_T_restart) /= (us%m_to_L_restart * us%s_to_T)) )
then
1519 vel2_rescale = (us%m_to_L * us%s_to_T_restart)**2 / (us%m_to_L_restart * us%s_to_T)**2
1520 if (query_initialized(obc%rx_oblique,
"rx_oblique", restart_csp))
then
1521 do k=1,nz ;
do j=jsd,jed ;
do i=isdb,iedb
1522 obc%rx_oblique(i,j,k) = vel2_rescale * obc%rx_oblique(i,j,k)
1523 enddo ;
enddo ;
enddo
1525 if (query_initialized(obc%ry_oblique,
"ry_oblique", restart_csp))
then
1526 do k=1,nz ;
do j=jsdb,jedb ;
do i=isd,ied
1527 obc%ry_oblique(i,j,k) = vel2_rescale * obc%ry_oblique(i,j,k)
1528 enddo ;
enddo ;
enddo
1530 if (query_initialized(obc%cff_normal,
"cff_normal", restart_csp))
then
1531 do k=1,nz ;
do j=jsdb,jedb ;
do i=isdb,iedb
1532 obc%cff_normal(i,j,k) = vel2_rescale * obc%cff_normal(i,j,k)
1533 enddo ;
enddo ;
enddo
1539 logical function open_boundary_query(OBC, apply_open_OBC, apply_specified_OBC, apply_Flather_OBC, &
1540 apply_nudged_OBC, needs_ext_seg_data)
1542 logical,
optional,
intent(in) :: apply_open_obc
1543 logical,
optional,
intent(in) :: apply_specified_obc
1544 logical,
optional,
intent(in) :: apply_flather_obc
1545 logical,
optional,
intent(in) :: apply_nudged_obc
1546 logical,
optional,
intent(in) :: needs_ext_seg_data
1548 if (.not.
associated(obc))
return
1550 obc%open_v_BCs_exist_globally
1551 if (
present(apply_specified_obc))
open_boundary_query = obc%specified_u_BCs_exist_globally .or. &
1552 obc%specified_v_BCs_exist_globally
1553 if (
present(apply_flather_obc))
open_boundary_query = obc%Flather_u_BCs_exist_globally .or. &
1554 obc%Flather_v_BCs_exist_globally
1555 if (
present(apply_nudged_obc))
open_boundary_query = obc%nudged_u_BCs_exist_globally .or. &
1556 obc%nudged_v_BCs_exist_globally
1567 if (.not.
associated(obc))
return
1569 do n=1, obc%number_of_segments
1570 segment => obc%segment(n)
1573 if (
associated(obc%segment))
deallocate(obc%segment)
1574 if (
associated(obc%segnum_u))
deallocate(obc%segnum_u)
1575 if (
associated(obc%segnum_v))
deallocate(obc%segnum_v)
1576 if (
associated(obc%rx_normal))
deallocate(obc%rx_normal)
1577 if (
associated(obc%ry_normal))
deallocate(obc%ry_normal)
1578 if (
associated(obc%rx_oblique))
deallocate(obc%rx_oblique)
1579 if (
associated(obc%ry_oblique))
deallocate(obc%ry_oblique)
1580 if (
associated(obc%cff_normal))
deallocate(obc%cff_normal)
1581 if (
associated(obc%tres_x))
deallocate(obc%tres_x)
1582 if (
associated(obc%tres_y))
deallocate(obc%tres_y)
1595 type(dyn_horgrid_type),
intent(in) :: g
1596 real,
dimension(SZI_(G),SZJ_(G)),
intent(inout) :: depth
1601 if (.not.
associated(obc))
return
1603 if (.not.(obc%specified_u_BCs_exist_globally .or. obc%specified_v_BCs_exist_globally .or. &
1604 obc%open_u_BCs_exist_globally .or. obc%open_v_BCs_exist_globally)) &
1607 do n=1,obc%number_of_segments
1608 segment=>obc%segment(n)
1609 if (.not. segment%on_pe) cycle
1612 do j=segment%HI%jsd,segment%HI%jed
1613 depth(i+1,j) = depth(i,j)
1617 do j=segment%HI%jsd,segment%HI%jed
1618 depth(i,j) = depth(i+1,j)
1622 do i=segment%HI%isd,segment%HI%ied
1623 depth(i,j+1) = depth(i,j)
1627 do i=segment%HI%isd,segment%HI%ied
1628 depth(i,j) = depth(i,j+1)
1640 type(dyn_horgrid_type),
intent(inout) :: g
1641 type(unit_scale_type),
intent(in) :: us
1642 real,
dimension(SZIB_(G),SZJ_(G)),
intent(inout) :: areacu
1643 real,
dimension(SZI_(G),SZJB_(G)),
intent(inout) :: areacv
1647 logical :: any_u, any_v
1649 if (.not.
associated(obc))
return
1651 do n=1,obc%number_of_segments
1652 segment=>obc%segment(n)
1653 if (.not. segment%on_pe) cycle
1654 if (segment%is_E_or_W)
then
1658 do j=segment%HI%jsd,segment%HI%jed
1659 if (g%mask2dCu(i,j) == 0) obc%segnum_u(i,j) =
obc_none
1663 g%mask2dT(i+1,j) = 0
1666 do j=segment%HI%JsdB+1,segment%HI%JedB-1
1670 g%mask2dCv(i+1,j) = 0
1676 do i=segment%HI%isd,segment%HI%ied
1677 if (g%mask2dCv(i,j) == 0) obc%segnum_v(i,j) =
obc_none
1681 g%mask2dT(i,j+1) = 0
1684 do i=segment%HI%IsdB+1,segment%HI%IedB-1
1688 g%mask2dCu(i,j+1) = 0
1694 do n=1,obc%number_of_segments
1695 segment=>obc%segment(n)
1696 if (.not. segment%on_pe .or. .not. segment%specified) cycle
1697 if (segment%is_E_or_W)
then
1700 do j=segment%HI%jsd,segment%HI%jed
1702 areacu(i,j) = g%areaT(i,j)
1704 areacu(i,j) = g%areaT(i+1,j)
1710 do i=segment%HI%isd,segment%HI%ied
1712 areacv(i,j) = g%areaT(i,j+1)
1714 areacu(i,j) = g%areaT(i,j)
1726 do n=1,obc%number_of_segments
1727 segment=>obc%segment(n)
1728 if (.not. segment%on_pe) cycle
1729 if (segment%is_E_or_W)
then
1731 do j=segment%HI%jsd,segment%HI%jed
1732 if (obc%segnum_u(i,j) /=
obc_none) any_u = .true.
1736 do i=segment%HI%isd,segment%HI%ied
1737 if (obc%segnum_v(i,j) /=
obc_none) any_v = .true.
1743 if (.not.(any_u .or. any_v)) obc%OBC_pe = .false.
1749 type(ocean_grid_type),
intent(inout) :: G
1753 integer :: i, j, k, m, n
1755 do n=1,obc%number_of_segments
1756 segment=>obc%segment(n)
1757 if (
associated(segment%tr_Reg))
then
1758 if (segment%is_E_or_W)
then
1761 if (
associated(segment%tr_Reg%Tr(m)%tres))
then
1763 do j=segment%HI%jsd,segment%HI%jed
1764 obc%tres_x(i,j,k,m) = segment%tr_Reg%Tr(m)%t(i,j,k)
1772 if (
associated(segment%tr_Reg%Tr(m)%tres))
then
1774 do i=segment%HI%isd,segment%HI%ied
1775 obc%tres_y(i,j,k,m) = segment%tr_Reg%Tr(m)%t(i,j,k)
1788 type(ocean_grid_type),
intent(inout) :: g
1790 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(inout) :: u_new
1793 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: u_old
1794 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(inout) :: v_new
1797 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: v_old
1798 type(unit_scale_type),
intent(in) :: us
1799 real,
intent(in) :: dt
1801 real :: dhdt, dhdx, dhdy
1802 real :: gamma_u, gamma_2
1804 real :: rx_max, ry_max
1805 real :: rx_new, rx_avg
1806 real :: ry_new, ry_avg
1807 real :: cff_new, cff_avg
1808 real,
allocatable,
dimension(:,:,:) :: &
1818 integer :: i, j, k, is, ie, js, je, m, nz, n
1819 integer :: is_obc, ie_obc, js_obc, je_obc
1821 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
1823 if (.not.
associated(obc))
return
1825 if (.not.(obc%open_u_BCs_exist_globally .or. obc%open_v_BCs_exist_globally)) &
1828 eps = 1.0e-20*us%m_s_to_L_T**2
1833 if (obc%gamma_uv < 1.0)
then
1834 do n=1,obc%number_of_segments
1835 segment=>obc%segment(n)
1836 if (.not. segment%on_pe) cycle
1837 if (segment%is_E_or_W .and. segment%radiation)
then
1840 do j=segment%HI%jsd,segment%HI%jed
1841 segment%rx_norm_rad(i,j,k) = obc%rx_normal(i,j,k)
1844 elseif (segment%is_N_or_S .and. segment%radiation)
then
1847 do i=segment%HI%isd,segment%HI%ied
1848 segment%ry_norm_rad(i,j,k) = obc%ry_normal(i,j,k)
1852 if (segment%is_E_or_W .and. segment%oblique)
then
1855 do j=segment%HI%jsd,segment%HI%jed
1856 segment%rx_norm_obl(i,j,k) = obc%rx_oblique(i,j,k)
1857 segment%ry_norm_obl(i,j,k) = obc%ry_oblique(i,j,k)
1858 segment%cff_normal(i,j,k) = obc%cff_normal(i,j,k)
1861 elseif (segment%is_N_or_S .and. segment%oblique)
then
1864 do i=segment%HI%isd,segment%HI%ied
1865 segment%rx_norm_obl(i,j,k) = obc%rx_oblique(i,j,k)
1866 segment%ry_norm_obl(i,j,k) = obc%ry_oblique(i,j,k)
1867 segment%cff_normal(i,j,k) = obc%cff_normal(i,j,k)
1875 do n=1,obc%number_of_segments
1876 segment=>obc%segment(n)
1877 if (
associated(segment%tr_Reg))
then
1878 if (segment%is_E_or_W)
then
1881 if (
associated(segment%tr_Reg%Tr(m)%tres))
then
1883 do j=segment%HI%jsd,segment%HI%jed
1884 segment%tr_Reg%Tr(m)%tres(i,j,k) = obc%tres_x(i,j,k,m)
1892 if (
associated(segment%tr_Reg%Tr(m)%tres))
then
1894 do i=segment%HI%isd,segment%HI%ied
1895 segment%tr_Reg%Tr(m)%tres(i,j,k) = obc%tres_y(i,j,k,m)
1904 gamma_u = obc%gamma_uv
1905 rx_max = obc%rx_max ; ry_max = obc%rx_max
1906 do n=1,obc%number_of_segments
1907 segment=>obc%segment(n)
1908 if (.not. segment%on_pe) cycle
1912 if (i<g%HI%IscB) cycle
1913 do k=1,nz ;
do j=segment%HI%jsd,segment%HI%jed
1914 if (segment%radiation)
then
1915 dhdt = (u_old(i-1,j,k) - u_new(i-1,j,k))
1916 dhdx = (u_new(i-1,j,k) - u_new(i-2,j,k))
1918 if (dhdt*dhdx > 0.0) rx_new = min( (dhdt/dhdx), rx_max)
1919 if (gamma_u < 1.0)
then
1920 rx_avg = (1.0-gamma_u)*segment%rx_norm_rad(i,j,k) + gamma_u*rx_new
1924 segment%rx_norm_rad(i,j,k) = rx_avg
1928 segment%normal_vel(i,j,k) = (u_new(i,j,k) + rx_avg*u_new(i-1,j,k)) / (1.0+rx_avg)
1931 if (gamma_u < 1.0)
then
1932 obc%rx_normal(i,j,k) = segment%rx_norm_rad(i,j,k)
1934 elseif (segment%oblique)
then
1935 dhdt = (u_old(i-1,j,k) - u_new(i-1,j,k))
1936 dhdx = (u_new(i-1,j,k) - u_new(i-2,j,k))
1937 if (dhdt*(segment%grad_normal(j,1,k) + segment%grad_normal(j-1,1,k)) > 0.0)
then
1938 dhdy = segment%grad_normal(j-1,1,k)
1939 elseif (dhdt*(segment%grad_normal(j,1,k) + segment%grad_normal(j-1,1,k)) == 0.0)
then
1942 dhdy = segment%grad_normal(j,1,k)
1944 if (dhdt*dhdx < 0.0) dhdt = 0.0
1946 cff_new = max(dhdx*dhdx + dhdy*dhdy, eps)
1947 ry_new = min(cff_new,max(dhdt*dhdy,-cff_new))
1948 if (gamma_u < 1.0)
then
1949 rx_avg = (1.0-gamma_u)*segment%rx_norm_obl(i,j,k) + gamma_u*rx_new
1950 ry_avg = (1.0-gamma_u)*segment%ry_norm_obl(i,j,k) + gamma_u*ry_new
1951 cff_avg = (1.0-gamma_u)*segment%cff_normal(i,j,k) + gamma_u*cff_new
1957 segment%rx_norm_obl(i,j,k) = rx_avg
1958 segment%ry_norm_obl(i,j,k) = ry_avg
1959 segment%cff_normal(i,j,k) = cff_avg
1960 segment%normal_vel(i,j,k) = ((cff_avg*u_new(i,j,k) + rx_avg*u_new(i-1,j,k)) - &
1961 (max(ry_avg,0.0)*segment%grad_normal(j-1,2,k) + &
1962 min(ry_avg,0.0)*segment%grad_normal(j,2,k))) / &
1964 if (gamma_u < 1.0)
then
1967 obc%rx_oblique(i,j,k) = segment%rx_norm_obl(i,j,k)
1968 obc%ry_oblique(i,j,k) = segment%ry_norm_obl(i,j,k)
1969 obc%cff_normal(i,j,k) = segment%cff_normal(i,j,k)
1971 elseif (segment%gradient)
then
1972 segment%normal_vel(i,j,k) = u_new(i-1,j,k)
1974 if ((segment%radiation .or. segment%oblique) .and. segment%nudged)
then
1976 if (dhdt*dhdx <= 0.0)
then
1977 tau = segment%Velocity_nudging_timescale_in
1979 tau = segment%Velocity_nudging_timescale_out
1981 gamma_2 = dt / (tau + dt)
1982 segment%normal_vel(i,j,k) = (1.0 - gamma_2) * segment%normal_vel(i,j,k) + &
1983 gamma_2 * segment%nudged_normal_vel(i,j,k)
1986 if (segment%radiation_tan .or. segment%radiation_grad)
then
1988 allocate(rx_tang_rad(segment%HI%IsdB:segment%HI%IedB,segment%HI%JsdB:segment%HI%JedB,nz))
1990 if (gamma_u < 1.0)
then
1991 rx_tang_rad(i,segment%HI%JsdB,k) = segment%rx_norm_rad(i,segment%HI%jsd,k)
1992 rx_tang_rad(i,segment%HI%JedB,k) = segment%rx_norm_rad(i,segment%HI%jed,k)
1993 do j=segment%HI%JsdB+1,segment%HI%JedB-1
1994 rx_tang_rad(i,j,k) = 0.5*(segment%rx_norm_rad(i,j,k) + segment%rx_norm_rad(i,j+1,k))
1997 do j=segment%HI%JsdB,segment%HI%JedB
1998 dhdt = v_old(i,j,k)-v_new(i,j,k)
1999 dhdx = v_new(i,j,k)-v_new(i-1,j,k)
2000 rx_tang_rad(i,j,k) = 0.0
2001 if (dhdt*dhdx > 0.0) rx_tang_rad(i,j,k) = min( (dhdt/dhdx), rx_max)
2005 if (segment%radiation_tan)
then
2006 do k=1,nz ;
do j=segment%HI%JsdB,segment%HI%JedB
2007 rx_avg = rx_tang_rad(i,j,k)
2008 segment%tangential_vel(i,j,k) = (v_new(i,j,k) + rx_avg*v_new(i-1,j,k)) / (1.0+rx_avg)
2011 if (segment%nudged_tan)
then
2012 do k=1,nz ;
do j=segment%HI%JsdB,segment%HI%JedB
2014 if (rx_tang_rad(i,j,k) <= 0.0)
then
2015 tau = segment%Velocity_nudging_timescale_in
2017 tau = segment%Velocity_nudging_timescale_out
2019 gamma_2 = dt / (tau + dt)
2020 segment%tangential_vel(i,j,k) = (1.0 - gamma_2) * segment%tangential_vel(i,j,k) + &
2021 gamma_2 * segment%nudged_tangential_vel(i,j,k)
2024 if (segment%radiation_grad)
then
2025 js_obc = max(segment%HI%JsdB,g%jsd+1)
2026 je_obc = min(segment%HI%JedB,g%jed-1)
2027 do k=1,nz ;
do j=js_obc,je_obc
2028 rx_avg = rx_tang_rad(i,j,k)
2038 segment%tangential_grad(i,j,k) = ((v_new(i,j,k) - v_new(i-1,j,k))*g%IdxBu(i-1,j) + &
2039 rx_avg*(v_new(i-1,j,k) - v_new(i-2,j,k))*g%IdxBu(i-2,j)) / (1.0+rx_avg)
2042 if (segment%nudged_grad)
then
2043 do k=1,nz ;
do j=segment%HI%JsdB,segment%HI%JedB
2045 if (rx_tang_rad(i,j,k) <= 0.0)
then
2046 tau = segment%Velocity_nudging_timescale_in
2048 tau = segment%Velocity_nudging_timescale_out
2050 gamma_2 = dt / (tau + dt)
2051 segment%tangential_grad(i,j,k) = (1.0 - gamma_2) * segment%tangential_grad(i,j,k) + &
2052 gamma_2 * segment%nudged_tangential_grad(i,j,k)
2055 deallocate(rx_tang_rad)
2057 if (segment%oblique_tan .or. segment%oblique_grad)
then
2059 allocate(rx_tang_obl(segment%HI%IsdB:segment%HI%IedB,segment%HI%JsdB:segment%HI%JedB,nz))
2060 allocate(ry_tang_obl(segment%HI%IsdB:segment%HI%IedB,segment%HI%JsdB:segment%HI%JedB,nz))
2061 allocate(cff_tangential(segment%HI%IsdB:segment%HI%IedB,segment%HI%JsdB:segment%HI%JedB,nz))
2063 if (gamma_u < 1.0)
then
2064 rx_tang_obl(i,segment%HI%JsdB,k) = segment%rx_norm_obl(i,segment%HI%jsd,k)
2065 rx_tang_obl(i,segment%HI%JedB,k) = segment%rx_norm_obl(i,segment%HI%jed,k)
2066 ry_tang_obl(i,segment%HI%JsdB,k) = segment%ry_norm_obl(i,segment%HI%jsd,k)
2067 ry_tang_obl(i,segment%HI%JedB,k) = segment%ry_norm_obl(i,segment%HI%jed,k)
2068 cff_tangential(i,segment%HI%JsdB,k) = segment%cff_normal(i,segment%HI%jsd,k)
2069 cff_tangential(i,segment%HI%JedB,k) = segment%cff_normal(i,segment%HI%jed,k)
2070 do j=segment%HI%JsdB+1,segment%HI%JedB-1
2071 rx_tang_obl(i,j,k) = 0.5*(segment%rx_norm_obl(i,j,k) + segment%rx_norm_obl(i,j+1,k))
2072 ry_tang_obl(i,j,k) = 0.5*(segment%ry_norm_obl(i,j,k) + segment%ry_norm_obl(i,j+1,k))
2073 cff_tangential(i,j,k) = 0.5*(segment%cff_normal(i,j,k) + segment%cff_normal(i,j+1,k))
2076 do j=segment%HI%JsdB,segment%HI%JedB
2077 dhdt = v_old(i,j,k)-v_new(i,j,k)
2078 dhdx = v_new(i,j,k)-v_new(i-1,j,k)
2079 if (dhdt*(segment%grad_tan(j,1,k) + segment%grad_tan(j+1,1,k)) > 0.0)
then
2080 dhdy = segment%grad_tan(j,1,k)
2081 elseif (dhdt*(segment%grad_tan(j,1,k) + segment%grad_tan(j+1,1,k)) == 0.0)
then
2084 dhdy = segment%grad_tan(j+1,1,k)
2086 if (dhdt*dhdx < 0.0) dhdt = 0.0
2088 cff_new = max(dhdx*dhdx + dhdy*dhdy, eps)
2089 ry_new = min(cff_new,max(dhdt*dhdy,-cff_new))
2090 rx_tang_obl(i,j,k) = rx_new
2091 ry_tang_obl(i,j,k) = ry_new
2092 cff_tangential(i,j,k) = cff_new
2096 if (segment%oblique_tan)
then
2097 do k=1,nz ;
do j=segment%HI%JsdB,segment%HI%JedB
2098 rx_avg = rx_tang_obl(i,j,k)
2099 ry_avg = ry_tang_obl(i,j,k)
2100 cff_avg = cff_tangential(i,j,k)
2101 segment%tangential_vel(i,j,k) = ((cff_avg*v_new(i,j,k) + rx_avg*v_new(i-1,j,k)) - &
2102 (max(ry_avg,0.0)*segment%grad_tan(j,2,k) + &
2103 min(ry_avg,0.0)*segment%grad_tan(j+1,2,k))) / &
2107 if (segment%nudged_tan)
then
2108 do k=1,nz ;
do j=segment%HI%JsdB,segment%HI%JedB
2110 if (rx_tang_obl(i,j,k) <= 0.0)
then
2111 tau = segment%Velocity_nudging_timescale_in
2113 tau = segment%Velocity_nudging_timescale_out
2115 gamma_2 = dt / (tau + dt)
2116 segment%tangential_vel(i,j,k) = (1.0 - gamma_2) * segment%tangential_vel(i,j,k) + &
2117 gamma_2 * segment%nudged_tangential_vel(i,j,k)
2120 if (segment%oblique_grad)
then
2121 js_obc = max(segment%HI%JsdB,g%jsd+1)
2122 je_obc = min(segment%HI%JedB,g%jed-1)
2123 do k=1,nz ;
do j=segment%HI%JsdB+1,segment%HI%JedB-1
2124 rx_avg = rx_tang_obl(i,j,k)
2125 ry_avg = ry_tang_obl(i,j,k)
2126 cff_avg = cff_tangential(i,j,k)
2127 segment%tangential_grad(i,j,k) = &
2128 ((cff_avg*(v_new(i,j,k) - v_new(i-1,j,k))*g%IdxBu(i-1,j) + &
2129 rx_avg*(v_new(i-1,j,k) - v_new(i-2,j,k))*g%IdxBu(i-2,j)) - &
2130 (max(ry_avg,0.0)*segment%grad_gradient(j,2,k) + &
2131 min(ry_avg,0.0)*segment%grad_gradient(j+1,2,k)) ) / &
2135 if (segment%nudged_grad)
then
2136 do k=1,nz ;
do j=segment%HI%JsdB,segment%HI%JedB
2138 if (rx_tang_obl(i,j,k) <= 0.0)
then
2139 tau = segment%Velocity_nudging_timescale_in
2141 tau = segment%Velocity_nudging_timescale_out
2143 gamma_2 = dt / (tau + dt)
2144 segment%tangential_grad(i,j,k) = (1.0 - gamma_2) * segment%tangential_grad(i,j,k) + &
2145 gamma_2 * segment%nudged_tangential_grad(i,j,k)
2148 deallocate(rx_tang_obl)
2149 deallocate(ry_tang_obl)
2150 deallocate(cff_tangential)
2156 if (i>g%HI%IecB) cycle
2157 do k=1,nz ;
do j=segment%HI%jsd,segment%HI%jed
2158 if (segment%radiation)
then
2159 dhdt = (u_old(i+1,j,k) - u_new(i+1,j,k))
2160 dhdx = (u_new(i+1,j,k) - u_new(i+2,j,k))
2162 if (dhdt*dhdx > 0.0) rx_new = min( (dhdt/dhdx), rx_max)
2163 if (gamma_u < 1.0)
then
2164 rx_avg = (1.0-gamma_u)*segment%rx_norm_rad(i,j,k) + gamma_u*rx_new
2168 segment%rx_norm_rad(i,j,k) = rx_avg
2172 segment%normal_vel(i,j,k) = (u_new(i,j,k) + rx_avg*u_new(i+1,j,k)) / (1.0+rx_avg)
2173 if (gamma_u < 1.0)
then
2176 obc%rx_normal(i,j,k) = segment%rx_norm_rad(i,j,k)
2178 elseif (segment%oblique)
then
2179 dhdt = (u_old(i+1,j,k) - u_new(i+1,j,k))
2180 dhdx = (u_new(i+1,j,k) - u_new(i+2,j,k))
2181 if (dhdt*(segment%grad_normal(j,1,k) + segment%grad_normal(j-1,1,k)) > 0.0)
then
2182 dhdy = segment%grad_normal(j-1,1,k)
2183 elseif (dhdt*(segment%grad_normal(j,1,k) + segment%grad_normal(j-1,1,k)) == 0.0)
then
2186 dhdy = segment%grad_normal(j,1,k)
2188 if (dhdt*dhdx < 0.0) dhdt = 0.0
2191 cff_new = max(dhdx*dhdx + dhdy*dhdy, eps)
2192 ry_new = min(cff_new,max(dhdt*dhdy,-cff_new))
2193 if (gamma_u < 1.0)
then
2194 rx_avg = (1.0-gamma_u)*segment%rx_norm_obl(i,j,k) + gamma_u*rx_new
2195 ry_avg = (1.0-gamma_u)*segment%ry_norm_obl(i,j,k) + gamma_u*ry_new
2196 cff_avg = (1.0-gamma_u)*segment%cff_normal(i,j,k) + gamma_u*cff_new
2202 segment%rx_norm_obl(i,j,k) = rx_avg
2203 segment%ry_norm_obl(i,j,k) = ry_avg
2204 segment%cff_normal(i,j,k) = cff_avg
2205 segment%normal_vel(i,j,k) = ((cff_avg*u_new(i,j,k) + rx_avg*u_new(i+1,j,k)) - &
2206 (max(ry_avg,0.0)*segment%grad_normal(j-1,2,k) + &
2207 min(ry_avg,0.0)*segment%grad_normal(j,2,k))) / &
2209 if (gamma_u < 1.0)
then
2212 obc%rx_oblique(i,j,k) = segment%rx_norm_obl(i,j,k)
2213 obc%ry_oblique(i,j,k) = segment%ry_norm_obl(i,j,k)
2214 obc%cff_normal(i,j,k) = segment%cff_normal(i,j,k)
2216 elseif (segment%gradient)
then
2217 segment%normal_vel(i,j,k) = u_new(i+1,j,k)
2219 if ((segment%radiation .or. segment%oblique) .and. segment%nudged)
then
2221 if (dhdt*dhdx <= 0.0)
then
2222 tau = segment%Velocity_nudging_timescale_in
2224 tau = segment%Velocity_nudging_timescale_out
2226 gamma_2 = dt / (tau + dt)
2227 segment%normal_vel(i,j,k) = (1.0 - gamma_2) * segment%normal_vel(i,j,k) + &
2228 gamma_2 * segment%nudged_normal_vel(i,j,k)
2231 if (segment%radiation_tan .or. segment%radiation_grad)
then
2233 allocate(rx_tang_rad(segment%HI%IsdB:segment%HI%IedB,segment%HI%JsdB:segment%HI%JedB,nz))
2235 if (gamma_u < 1.0)
then
2236 rx_tang_rad(i,segment%HI%JsdB,k) = segment%rx_norm_rad(i,segment%HI%jsd,k)
2237 rx_tang_rad(i,segment%HI%JedB,k) = segment%rx_norm_rad(i,segment%HI%jed,k)
2238 do j=segment%HI%JsdB+1,segment%HI%JedB-1
2239 rx_tang_rad(i,j,k) = 0.5*(segment%rx_norm_rad(i,j,k) + segment%rx_norm_rad(i,j+1,k))
2242 do j=segment%HI%JsdB,segment%HI%JedB
2243 dhdt = v_old(i+1,j,k)-v_new(i+1,j,k)
2244 dhdx = v_new(i+1,j,k)-v_new(i+2,j,k)
2245 rx_tang_rad(i,j,k) = 0.0
2246 if (dhdt*dhdx > 0.0) rx_tang_rad(i,j,k) = min( (dhdt/dhdx), rx_max)
2250 if (segment%radiation_tan)
then
2251 do k=1,nz ;
do j=segment%HI%JsdB,segment%HI%JedB
2252 rx_avg = rx_tang_rad(i,j,k)
2253 segment%tangential_vel(i,j,k) = (v_new(i+1,j,k) + rx_avg*v_new(i+2,j,k)) / (1.0+rx_avg)
2256 if (segment%nudged_tan)
then
2257 do k=1,nz ;
do j=segment%HI%JsdB,segment%HI%JedB
2259 if (rx_tang_rad(i,j,k) <= 0.0)
then
2260 tau = segment%Velocity_nudging_timescale_in
2262 tau = segment%Velocity_nudging_timescale_out
2264 gamma_2 = dt / (tau + dt)
2265 segment%tangential_vel(i,j,k) = (1.0 - gamma_2) * segment%tangential_vel(i,j,k) + &
2266 gamma_2 * segment%nudged_tangential_vel(i,j,k)
2269 if (segment%radiation_grad)
then
2270 js_obc = max(segment%HI%JsdB,g%jsd+1)
2271 je_obc = min(segment%HI%JedB,g%jed-1)
2272 do k=1,nz ;
do j=js_obc,je_obc
2273 rx_avg = rx_tang_rad(i,j,k)
2283 segment%tangential_grad(i,j,k) = ((v_new(i+2,j,k) - v_new(i+1,j,k))*g%IdxBu(i+1,j) + &
2284 rx_avg*(v_new(i+3,j,k) - v_new(i+2,j,k))*g%IdxBu(i+2,j)) / (1.0+rx_avg)
2287 if (segment%nudged_grad)
then
2288 do k=1,nz ;
do j=segment%HI%JsdB,segment%HI%JedB
2290 if (rx_tang_rad(i,j,k) <= 0.0)
then
2291 tau = segment%Velocity_nudging_timescale_in
2293 tau = segment%Velocity_nudging_timescale_out
2295 gamma_2 = dt / (tau + dt)
2296 segment%tangential_grad(i,j,k) = (1.0 - gamma_2) * segment%tangential_grad(i,j,k) + &
2297 gamma_2 * segment%nudged_tangential_grad(i,j,k)
2300 deallocate(rx_tang_rad)
2302 if (segment%oblique_tan .or. segment%oblique_grad)
then
2304 allocate(rx_tang_obl(segment%HI%IsdB:segment%HI%IedB,segment%HI%JsdB:segment%HI%JedB,nz))
2305 allocate(ry_tang_obl(segment%HI%IsdB:segment%HI%IedB,segment%HI%JsdB:segment%HI%JedB,nz))
2306 allocate(cff_tangential(segment%HI%IsdB:segment%HI%IedB,segment%HI%JsdB:segment%HI%JedB,nz))
2308 if (gamma_u < 1.0)
then
2309 rx_tang_obl(i,segment%HI%JsdB,k) = segment%rx_norm_obl(i,segment%HI%jsd,k)
2310 rx_tang_obl(i,segment%HI%JedB,k) = segment%rx_norm_obl(i,segment%HI%jed,k)
2311 ry_tang_obl(i,segment%HI%JsdB,k) = segment%ry_norm_obl(i,segment%HI%jsd,k)
2312 ry_tang_obl(i,segment%HI%JedB,k) = segment%ry_norm_obl(i,segment%HI%jed,k)
2313 cff_tangential(i,segment%HI%JsdB,k) = segment%cff_normal(i,segment%HI%jsd,k)
2314 cff_tangential(i,segment%HI%JedB,k) = segment%cff_normal(i,segment%HI%jed,k)
2315 do j=segment%HI%JsdB+1,segment%HI%JedB-1
2316 rx_tang_obl(i,j,k) = 0.5*(segment%rx_norm_obl(i,j,k) + segment%rx_norm_obl(i,j+1,k))
2317 ry_tang_obl(i,j,k) = 0.5*(segment%ry_norm_obl(i,j,k) + segment%ry_norm_obl(i,j+1,k))
2318 cff_tangential(i,j,k) = 0.5*(segment%cff_normal(i,j,k) + segment%cff_normal(i,j+1,k))
2321 do j=segment%HI%JsdB,segment%HI%JedB
2322 dhdt = v_old(i+1,j,k)-v_new(i+1,j,k)
2323 dhdx = v_new(i+1,j,k)-v_new(i+2,j,k)
2324 if (dhdt*(segment%grad_tan(j,1,k) + segment%grad_tan(j+1,1,k)) > 0.0)
then
2325 dhdy = segment%grad_tan(j,1,k)
2326 elseif (dhdt*(segment%grad_tan(j,1,k) + segment%grad_tan(j+1,1,k)) == 0.0)
then
2329 dhdy = segment%grad_tan(j+1,1,k)
2331 if (dhdt*dhdx < 0.0) dhdt = 0.0
2333 cff_new = max(dhdx*dhdx + dhdy*dhdy, eps)
2334 ry_new = min(cff_new,max(dhdt*dhdy,-cff_new))
2335 rx_tang_obl(i,j,k) = rx_new
2336 ry_tang_obl(i,j,k) = ry_new
2337 cff_tangential(i,j,k) = cff_new
2341 if (segment%oblique_tan)
then
2342 do k=1,nz ;
do j=segment%HI%JsdB,segment%HI%JedB
2343 rx_avg = rx_tang_obl(i,j,k)
2344 ry_avg = ry_tang_obl(i,j,k)
2345 cff_avg = cff_tangential(i,j,k)
2346 segment%tangential_vel(i,j,k) = ((cff_avg*v_new(i+1,j,k) + rx_avg*v_new(i+2,j,k)) - &
2347 (max(ry_avg,0.0)*segment%grad_tan(j,2,k) + &
2348 min(ry_avg,0.0)*segment%grad_tan(j+1,2,k))) / &
2352 if (segment%nudged_tan)
then
2353 do k=1,nz ;
do j=segment%HI%JsdB,segment%HI%JedB
2355 if (rx_tang_obl(i,j,k) <= 0.0)
then
2356 tau = segment%Velocity_nudging_timescale_in
2358 tau = segment%Velocity_nudging_timescale_out
2360 gamma_2 = dt / (tau + dt)
2361 segment%tangential_vel(i,j,k) = (1.0 - gamma_2) * segment%tangential_vel(i,j,k) + &
2362 gamma_2 * segment%nudged_tangential_vel(i,j,k)
2365 if (segment%oblique_grad)
then
2366 js_obc = max(segment%HI%JsdB,g%jsd+1)
2367 je_obc = min(segment%HI%JedB,g%jed-1)
2368 do k=1,nz ;
do j=segment%HI%JsdB+1,segment%HI%JedB-1
2369 rx_avg = rx_tang_obl(i,j,k)
2370 ry_avg = ry_tang_obl(i,j,k)
2371 cff_avg = cff_tangential(i,j,k)
2372 segment%tangential_grad(i,j,k) = &
2373 ((cff_avg*(v_new(i+2,j,k) - v_new(i+1,j,k))*g%IdxBu(i+1,j) + &
2374 rx_avg*(v_new(i+3,j,k) - v_new(i+2,j,k))*g%IdxBu(i+2,j)) - &
2375 (max(ry_avg,0.0)*segment%grad_gradient(j,2,k) + &
2376 min(ry_avg,0.0)*segment%grad_gradient(j+1,2,k))) / &
2380 if (segment%nudged_grad)
then
2381 do k=1,nz ;
do j=segment%HI%JsdB,segment%HI%JedB
2383 if (rx_tang_obl(i,j,k) <= 0.0)
then
2384 tau = segment%Velocity_nudging_timescale_in
2386 tau = segment%Velocity_nudging_timescale_out
2388 gamma_2 = dt / (tau + dt)
2389 segment%tangential_grad(i,j,k) = (1.0 - gamma_2) * segment%tangential_grad(i,j,k) + &
2390 gamma_2 * segment%nudged_tangential_grad(i,j,k)
2393 deallocate(rx_tang_obl)
2394 deallocate(ry_tang_obl)
2395 deallocate(cff_tangential)
2401 if (j<g%HI%JscB) cycle
2402 do k=1,nz ;
do i=segment%HI%isd,segment%HI%ied
2403 if (segment%radiation)
then
2404 dhdt = (v_old(i,j-1,k) - v_new(i,j-1,k))
2405 dhdy = (v_new(i,j-1,k) - v_new(i,j-2,k))
2407 if (dhdt*dhdy > 0.0) ry_new = min( (dhdt/dhdy), ry_max)
2408 if (gamma_u < 1.0)
then
2409 ry_avg = (1.0-gamma_u)*segment%ry_norm_rad(i,j,k) + gamma_u*ry_new
2413 segment%ry_norm_rad(i,j,k) = ry_avg
2417 segment%normal_vel(i,j,k) = (v_new(i,j,k) + ry_avg*v_new(i,j-1,k)) / (1.0+ry_avg)
2418 if (gamma_u < 1.0)
then
2421 obc%ry_normal(i,j,k) = segment%ry_norm_rad(i,j,k)
2423 elseif (segment%oblique)
then
2424 dhdt = (v_old(i,j-1,k) - v_new(i,j-1,k))
2425 dhdy = (v_new(i,j-1,k) - v_new(i,j-2,k))
2426 if (dhdt*(segment%grad_normal(i,1,k) + segment%grad_normal(i-1,1,k)) > 0.0)
then
2427 dhdx = segment%grad_normal(i-1,1,k)
2428 elseif (dhdt*(segment%grad_normal(i,1,k) + segment%grad_normal(i-1,1,k)) == 0.0)
then
2431 dhdx = segment%grad_normal(i,1,k)
2433 if (dhdt*dhdy < 0.0) dhdt = 0.0
2435 cff_new = max(dhdx*dhdx + dhdy*dhdy, eps)
2436 rx_new = min(cff_new,max(dhdt*dhdx,-cff_new))
2437 if (gamma_u < 1.0)
then
2438 rx_avg = (1.0-gamma_u)*segment%rx_norm_obl(i,j,k) + gamma_u*rx_new
2439 ry_avg = (1.0-gamma_u)*segment%ry_norm_obl(i,j,k) + gamma_u*ry_new
2440 cff_avg = (1.0-gamma_u)*segment%cff_normal(i,j,k) + gamma_u*cff_new
2446 segment%rx_norm_obl(i,j,k) = rx_avg
2447 segment%ry_norm_obl(i,j,k) = ry_avg
2448 segment%cff_normal(i,j,k) = cff_avg
2449 segment%normal_vel(i,j,k) = ((cff_avg*v_new(i,j,k) + ry_avg*v_new(i,j-1,k)) - &
2450 (max(rx_avg,0.0)*segment%grad_normal(i-1,2,k) +&
2451 min(rx_avg,0.0)*segment%grad_normal(i,2,k))) / &
2453 if (gamma_u < 1.0)
then
2456 obc%rx_oblique(i,j,k) = segment%rx_norm_obl(i,j,k)
2457 obc%ry_oblique(i,j,k) = segment%ry_norm_obl(i,j,k)
2458 obc%cff_normal(i,j,k) = segment%cff_normal(i,j,k)
2460 elseif (segment%gradient)
then
2461 segment%normal_vel(i,j,k) = v_new(i,j-1,k)
2463 if ((segment%radiation .or. segment%oblique) .and. segment%nudged)
then
2465 if (dhdt*dhdy <= 0.0)
then
2466 tau = segment%Velocity_nudging_timescale_in
2468 tau = segment%Velocity_nudging_timescale_out
2470 gamma_2 = dt / (tau + dt)
2471 segment%normal_vel(i,j,k) = (1.0 - gamma_2) * segment%normal_vel(i,j,k) + &
2472 gamma_2 * segment%nudged_normal_vel(i,j,k)
2475 if (segment%radiation_tan .or. segment%radiation_grad)
then
2477 allocate(ry_tang_rad(segment%HI%IsdB:segment%HI%IedB,segment%HI%JsdB:segment%HI%JedB,nz))
2479 if (gamma_u < 1.0)
then
2480 ry_tang_rad(segment%HI%IsdB,j,k) = segment%ry_norm_rad(segment%HI%isd,j,k)
2481 ry_tang_rad(segment%HI%IedB,j,k) = segment%ry_norm_rad(segment%HI%ied,j,k)
2482 do i=segment%HI%IsdB+1,segment%HI%IedB-1
2483 ry_tang_rad(i,j,k) = 0.5*(segment%ry_norm_rad(i,j,k) + segment%ry_norm_rad(i+1,j,k))
2486 do i=segment%HI%IsdB,segment%HI%IedB
2487 dhdt = u_old(i,j-1,k)-u_new(i,j-1,k)
2488 dhdy = u_new(i,j-1,k)-u_new(i,j-2,k)
2489 ry_tang_rad(i,j,k) = 0.0
2490 if (dhdt*dhdy > 0.0) ry_tang_rad(i,j,k) = min( (dhdt/dhdy), rx_max)
2494 if (segment%radiation_tan)
then
2495 do k=1,nz ;
do i=segment%HI%IsdB,segment%HI%IedB
2496 ry_avg = ry_tang_rad(i,j,k)
2497 segment%tangential_vel(i,j,k) = (u_new(i,j,k) + ry_avg*u_new(i,j-1,k)) / (1.0+ry_avg)
2500 if (segment%nudged_tan)
then
2501 do k=1,nz ;
do i=segment%HI%IsdB,segment%HI%IedB
2503 if (ry_tang_rad(i,j,k) <= 0.0)
then
2504 tau = segment%Velocity_nudging_timescale_in
2506 tau = segment%Velocity_nudging_timescale_out
2508 gamma_2 = dt / (tau + dt)
2509 segment%tangential_vel(i,j,k) = (1.0 - gamma_2) * segment%tangential_vel(i,j,k) + &
2510 gamma_2 * segment%nudged_tangential_vel(i,j,k)
2513 if (segment%radiation_grad)
then
2514 is_obc = max(segment%HI%IsdB,g%isd+1)
2515 ie_obc = min(segment%HI%IedB,g%ied-1)
2516 do k=1,nz ;
do i=is_obc,ie_obc
2517 ry_avg = ry_tang_rad(i,j,k)
2527 segment%tangential_grad(i,j,k) = ((u_new(i,j,k) - u_new(i,j-1,k))*g%IdyBu(i,j-1) + &
2528 ry_avg*(u_new(i,j-1,k) - u_new(i,j-2,k))*g%IdyBu(i,j-2)) / (1.0+ry_avg)
2531 if (segment%nudged_grad)
then
2532 do k=1,nz ;
do i=segment%HI%IsdB,segment%HI%IedB
2534 if (ry_tang_rad(i,j,k) <= 0.0)
then
2535 tau = segment%Velocity_nudging_timescale_in
2537 tau = segment%Velocity_nudging_timescale_out
2539 gamma_2 = dt / (tau + dt)
2540 segment%tangential_grad(i,j,k) = (1.0 - gamma_2) * segment%tangential_grad(i,j,k) + &
2541 gamma_2 * segment%nudged_tangential_grad(i,j,k)
2544 deallocate(ry_tang_rad)
2546 if (segment%oblique_tan .or. segment%oblique_grad)
then
2548 allocate(rx_tang_obl(segment%HI%IsdB:segment%HI%IedB,segment%HI%JsdB:segment%HI%JedB,nz))
2549 allocate(ry_tang_obl(segment%HI%IsdB:segment%HI%IedB,segment%HI%JsdB:segment%HI%JedB,nz))
2550 allocate(cff_tangential(segment%HI%IsdB:segment%HI%IedB,segment%HI%JsdB:segment%HI%JedB,nz))
2552 if (gamma_u < 1.0)
then
2553 rx_tang_obl(segment%HI%IsdB,j,k) = segment%rx_norm_obl(segment%HI%isd,j,k)
2554 rx_tang_obl(segment%HI%IedB,j,k) = segment%rx_norm_obl(segment%HI%ied,j,k)
2555 ry_tang_obl(segment%HI%IsdB,j,k) = segment%ry_norm_obl(segment%HI%isd,j,k)
2556 ry_tang_obl(segment%HI%IedB,j,k) = segment%ry_norm_obl(segment%HI%ied,j,k)
2557 cff_tangential(segment%HI%IsdB,j,k) = segment%cff_normal(segment%HI%isd,j,k)
2558 cff_tangential(segment%HI%IedB,j,k) = segment%cff_normal(segment%HI%ied,j,k)
2559 do i=segment%HI%IsdB+1,segment%HI%IedB-1
2560 rx_tang_obl(i,j,k) = 0.5*(segment%rx_norm_obl(i,j,k) + segment%rx_norm_obl(i+1,j,k))
2561 ry_tang_obl(i,j,k) = 0.5*(segment%ry_norm_obl(i,j,k) + segment%ry_norm_obl(i+1,j,k))
2562 cff_tangential(i,j,k) = 0.5*(segment%cff_normal(i,j,k) + segment%cff_normal(i+1,j,k))
2565 do i=segment%HI%IsdB,segment%HI%IedB
2566 dhdt = u_old(i,j,k)-u_new(i,j,k)
2567 dhdy = u_new(i,j,k)-u_new(i,j-1,k)
2568 if (dhdt*(segment%grad_tan(i,1,k) + segment%grad_tan(i+1,1,k)) > 0.0)
then
2569 dhdx = segment%grad_tan(i,1,k)
2570 elseif (dhdt*(segment%grad_tan(i,1,k) + segment%grad_tan(i+1,1,k)) == 0.0)
then
2573 dhdx = segment%grad_tan(i+1,1,k)
2575 if (dhdt*dhdy < 0.0) dhdt = 0.0
2577 cff_new = max(dhdx*dhdx + dhdy*dhdy, eps)
2578 rx_new = min(cff_new,max(dhdt*dhdx,-cff_new))
2579 rx_tang_obl(i,j,k) = rx_new
2580 ry_tang_obl(i,j,k) = ry_new
2581 cff_tangential(i,j,k) = cff_new
2585 if (segment%oblique_tan)
then
2586 do k=1,nz ;
do i=segment%HI%IsdB,segment%HI%IedB
2587 rx_avg = rx_tang_obl(i,j,k)
2588 ry_avg = ry_tang_obl(i,j,k)
2589 cff_avg = cff_tangential(i,j,k)
2590 segment%tangential_vel(i,j,k) = ((cff_avg*u_new(i,j,k) + ry_avg*u_new(i,j-1,k)) - &
2591 (max(rx_avg,0.0)*segment%grad_tan(i,2,k) + &
2592 min(rx_avg,0.0)*segment%grad_tan(i+1,2,k))) / &
2596 if (segment%nudged_tan)
then
2597 do k=1,nz ;
do i=segment%HI%IsdB,segment%HI%IedB
2599 if (ry_tang_obl(i,j,k) <= 0.0)
then
2600 tau = segment%Velocity_nudging_timescale_in
2602 tau = segment%Velocity_nudging_timescale_out
2604 gamma_2 = dt / (tau + dt)
2605 segment%tangential_vel(i,j,k) = (1.0 - gamma_2) * segment%tangential_vel(i,j,k) + &
2606 gamma_2 * segment%nudged_tangential_vel(i,j,k)
2609 if (segment%oblique_grad)
then
2610 is_obc = max(segment%HI%IsdB,g%isd+1)
2611 ie_obc = min(segment%HI%IedB,g%ied-1)
2612 do k=1,nz ;
do i=segment%HI%IsdB+1,segment%HI%IedB-1
2613 rx_avg = rx_tang_obl(i,j,k)
2614 ry_avg = ry_tang_obl(i,j,k)
2615 cff_avg = cff_tangential(i,j,k)
2616 segment%tangential_grad(i,j,k) = &
2617 ((cff_avg*(u_new(i,j,k) - u_new(i,j-1,k))*g%IdyBu(i,j-1) + &
2618 ry_avg*(u_new(i,j-1,k) - u_new(i,j-2,k))*g%IdyBu(i,j-2)) - &
2619 (max(rx_avg,0.0)*segment%grad_gradient(i,2,k) + &
2620 min(rx_avg,0.0)*segment%grad_gradient(i+1,2,k))) / &
2624 if (segment%nudged_grad)
then
2625 do k=1,nz ;
do i=segment%HI%IsdB,segment%HI%IedB
2627 if (ry_tang_obl(i,j,k) <= 0.0)
then
2628 tau = segment%Velocity_nudging_timescale_in
2630 tau = segment%Velocity_nudging_timescale_out
2632 gamma_2 = dt / (tau + dt)
2633 segment%tangential_grad(i,j,k) = (1.0 - gamma_2) * segment%tangential_grad(i,j,k) + &
2634 gamma_2 * segment%nudged_tangential_grad(i,j,k)
2637 deallocate(rx_tang_obl)
2638 deallocate(ry_tang_obl)
2639 deallocate(cff_tangential)
2645 if (j>g%HI%JecB) cycle
2646 do k=1,nz ;
do i=segment%HI%isd,segment%HI%ied
2647 if (segment%radiation)
then
2648 dhdt = (v_old(i,j+1,k) - v_new(i,j+1,k))
2649 dhdy = (v_new(i,j+1,k) - v_new(i,j+2,k))
2651 if (dhdt*dhdy > 0.0) ry_new = min( (dhdt/dhdy), ry_max)
2652 if (gamma_u < 1.0)
then
2653 ry_avg = (1.0-gamma_u)*segment%ry_norm_rad(i,j,k) + gamma_u*ry_new
2657 segment%ry_norm_rad(i,j,k) = ry_avg
2661 segment%normal_vel(i,j,k) = (v_new(i,j,k) + ry_avg*v_new(i,j+1,k)) / (1.0+ry_avg)
2662 if (gamma_u < 1.0)
then
2665 obc%ry_normal(i,j,k) = segment%ry_norm_rad(i,j,k)
2667 elseif (segment%oblique)
then
2668 dhdt = (v_old(i,j+1,k) - v_new(i,j+1,k))
2669 dhdy = (v_new(i,j+1,k) - v_new(i,j+2,k))
2670 if (dhdt*(segment%grad_normal(i,1,k) + segment%grad_normal(i-1,1,k)) > 0.0)
then
2671 dhdx = segment%grad_normal(i-1,1,k)
2672 elseif (dhdt*(segment%grad_normal(i,1,k) + segment%grad_normal(i-1,1,k)) == 0.0)
then
2675 dhdx = segment%grad_normal(i,1,k)
2677 if (dhdt*dhdy < 0.0) dhdt = 0.0
2680 cff_new = max(dhdx*dhdx + dhdy*dhdy, eps)
2681 rx_new = min(cff_new,max(dhdt*dhdx,-cff_new))
2682 if (gamma_u < 1.0)
then
2683 rx_avg = (1.0-gamma_u)*segment%rx_norm_obl(i,j,k) + gamma_u*rx_new
2684 ry_avg = (1.0-gamma_u)*segment%ry_norm_obl(i,j,k) + gamma_u*ry_new
2685 cff_avg = (1.0-gamma_u)*segment%cff_normal(i,j,k) + gamma_u*cff_new
2691 segment%rx_norm_obl(i,j,k) = rx_avg
2692 segment%ry_norm_obl(i,j,k) = ry_avg
2693 segment%cff_normal(i,j,k) = cff_avg
2694 segment%normal_vel(i,j,k) = ((cff_avg*v_new(i,j,k) + ry_avg*v_new(i,j+1,k)) - &
2695 (max(rx_avg,0.0)*segment%grad_normal(i-1,2,k) + &
2696 min(rx_avg,0.0)*segment%grad_normal(i,2,k))) / &
2698 if (gamma_u < 1.0)
then
2701 obc%rx_oblique(i,j,k) = segment%rx_norm_obl(i,j,k)
2702 obc%ry_oblique(i,j,k) = segment%ry_norm_obl(i,j,k)
2703 obc%cff_normal(i,j,k) = segment%cff_normal(i,j,k)
2705 elseif (segment%gradient)
then
2706 segment%normal_vel(i,j,k) = v_new(i,j+1,k)
2708 if ((segment%radiation .or. segment%oblique) .and. segment%nudged)
then
2710 if (dhdt*dhdy <= 0.0)
then
2711 tau = segment%Velocity_nudging_timescale_in
2713 tau = segment%Velocity_nudging_timescale_out
2715 gamma_2 = dt / (tau + dt)
2716 segment%normal_vel(i,j,k) = (1.0 - gamma_2) * segment%normal_vel(i,j,k) + &
2717 gamma_2 * segment%nudged_normal_vel(i,j,k)
2720 if (segment%radiation_tan .or. segment%radiation_grad)
then
2722 allocate(ry_tang_rad(segment%HI%IsdB:segment%HI%IedB,segment%HI%JsdB:segment%HI%JedB,nz))
2724 if (gamma_u < 1.0)
then
2725 ry_tang_rad(segment%HI%IsdB,j,k) = segment%ry_norm_rad(segment%HI%isd,j,k)
2726 ry_tang_rad(segment%HI%IedB,j,k) = segment%ry_norm_rad(segment%HI%ied,j,k)
2727 do i=segment%HI%IsdB+1,segment%HI%IedB-1
2728 ry_tang_rad(i,j,k) = 0.5*(segment%ry_norm_rad(i,j,k) + segment%ry_norm_rad(i+1,j,k))
2731 do i=segment%HI%IsdB,segment%HI%IedB
2732 dhdt = u_old(i,j+1,k)-u_new(i,j+1,k)
2733 dhdy = u_new(i,j+1,k)-u_new(i,j+2,k)
2734 ry_tang_rad(i,j,k) = 0.0
2735 if (dhdt*dhdy > 0.0) ry_tang_rad(i,j,k) = min( (dhdt/dhdy), rx_max)
2739 if (segment%radiation_tan)
then
2740 do k=1,nz ;
do i=segment%HI%IsdB,segment%HI%IedB
2741 ry_avg = ry_tang_rad(i,j,k)
2742 segment%tangential_vel(i,j,k) = (u_new(i,j+1,k) + ry_avg*u_new(i,j+2,k)) / (1.0+ry_avg)
2745 if (segment%nudged_tan)
then
2746 do k=1,nz ;
do i=segment%HI%IsdB,segment%HI%IedB
2748 if (ry_tang_rad(i,j,k) <= 0.0)
then
2749 tau = segment%Velocity_nudging_timescale_in
2751 tau = segment%Velocity_nudging_timescale_out
2753 gamma_2 = dt / (tau + dt)
2754 segment%tangential_vel(i,j,k) = (1.0 - gamma_2) * segment%tangential_vel(i,j,k) + &
2755 gamma_2 * segment%nudged_tangential_vel(i,j,k)
2758 if (segment%radiation_grad)
then
2759 is_obc = max(segment%HI%IsdB,g%isd+1)
2760 ie_obc = min(segment%HI%IedB,g%ied-1)
2761 do k=1,nz ;
do i=is_obc,ie_obc
2762 ry_avg = ry_tang_rad(i,j,k)
2772 segment%tangential_grad(i,j,k) = ((u_new(i,j+2,k) - u_new(i,j+1,k))*g%IdyBu(i,j+1) + &
2773 ry_avg*(u_new(i,j+3,k) - u_new(i,j+2,k))*g%IdyBu(i,j+2)) / (1.0+ry_avg)
2776 if (segment%nudged_grad)
then
2777 do k=1,nz ;
do j=segment%HI%JsdB,segment%HI%JedB
2779 if (ry_tang_rad(i,j,k) <= 0.0)
then
2780 tau = segment%Velocity_nudging_timescale_in
2782 tau = segment%Velocity_nudging_timescale_out
2784 gamma_2 = dt / (tau + dt)
2785 segment%tangential_grad(i,j,k) = (1.0 - gamma_2) * segment%tangential_grad(i,j,k) + &
2786 gamma_2 * segment%nudged_tangential_grad(i,j,k)
2789 deallocate(ry_tang_rad)
2791 if (segment%oblique_tan .or. segment%oblique_grad)
then
2793 allocate(rx_tang_obl(segment%HI%IsdB:segment%HI%IedB,segment%HI%JsdB:segment%HI%JedB,nz))
2794 allocate(ry_tang_obl(segment%HI%IsdB:segment%HI%IedB,segment%HI%JsdB:segment%HI%JedB,nz))
2795 allocate(cff_tangential(segment%HI%IsdB:segment%HI%IedB,segment%HI%JsdB:segment%HI%JedB,nz))
2797 if (gamma_u < 1.0)
then
2798 rx_tang_obl(segment%HI%IsdB,j,k) = segment%rx_norm_obl(segment%HI%isd,j,k)
2799 rx_tang_obl(segment%HI%IedB,j,k) = segment%rx_norm_obl(segment%HI%ied,j,k)
2800 ry_tang_obl(segment%HI%IsdB,j,k) = segment%ry_norm_obl(segment%HI%isd,j,k)
2801 ry_tang_obl(segment%HI%IedB,j,k) = segment%ry_norm_obl(segment%HI%ied,j,k)
2802 cff_tangential(segment%HI%IsdB,j,k) = segment%cff_normal(segment%HI%isd,j,k)
2803 cff_tangential(segment%HI%IedB,j,k) = segment%cff_normal(segment%HI%ied,j,k)
2804 do i=segment%HI%IsdB+1,segment%HI%IedB-1
2805 rx_tang_obl(i,j,k) = 0.5*(segment%rx_norm_obl(i,j,k) + segment%rx_norm_obl(i+1,j,k))
2806 ry_tang_obl(i,j,k) = 0.5*(segment%ry_norm_obl(i,j,k) + segment%ry_norm_obl(i+1,j,k))
2807 cff_tangential(i,j,k) = 0.5*(segment%cff_normal(i,j,k) + segment%cff_normal(i+1,j,k))
2810 do i=segment%HI%IsdB,segment%HI%IedB
2811 dhdt = u_old(i,j+1,k)-u_new(i,j+1,k)
2812 dhdy = u_new(i,j+1,k)-u_new(i,j+2,k)
2813 if (dhdt*(segment%grad_tan(i,1,k) + segment%grad_tan(i+1,1,k)) > 0.0)
then
2814 dhdx = segment%grad_tan(i,1,k)
2815 elseif (dhdt*(segment%grad_tan(i,1,k) + segment%grad_tan(i+1,1,k)) == 0.0)
then
2818 dhdx = segment%grad_tan(i+1,1,k)
2820 if (dhdt*dhdy < 0.0) dhdt = 0.0
2822 cff_new = max(dhdx*dhdx + dhdy*dhdy, eps)
2823 rx_new = min(cff_new,max(dhdt*dhdx,-cff_new))
2824 rx_tang_obl(i,j,k) = rx_new
2825 ry_tang_obl(i,j,k) = ry_new
2826 cff_tangential(i,j,k) = cff_new
2830 if (segment%oblique_tan)
then
2831 do k=1,nz ;
do i=segment%HI%IsdB,segment%HI%IedB
2832 rx_avg = rx_tang_obl(i,j,k)
2833 ry_avg = ry_tang_obl(i,j,k)
2834 cff_avg = cff_tangential(i,j,k)
2835 segment%tangential_vel(i,j,k) = ((cff_avg*u_new(i,j+1,k) + ry_avg*u_new(i,j+2,k)) - &
2836 (max(rx_avg,0.0)*segment%grad_tan(i,2,k) + &
2837 min(rx_avg,0.0)*segment%grad_tan(i+1,2,k)) ) / &
2841 if (segment%nudged_tan)
then
2842 do k=1,nz ;
do i=segment%HI%IsdB,segment%HI%IedB
2844 if (ry_tang_obl(i,j,k) <= 0.0)
then
2845 tau = segment%Velocity_nudging_timescale_in
2847 tau = segment%Velocity_nudging_timescale_out
2849 gamma_2 = dt / (tau + dt)
2850 segment%tangential_vel(i,j,k) = (1.0 - gamma_2) * segment%tangential_vel(i,j,k) + &
2851 gamma_2 * segment%nudged_tangential_vel(i,j,k)
2854 if (segment%oblique_grad)
then
2855 is_obc = max(segment%HI%IsdB,g%isd+1)
2856 ie_obc = min(segment%HI%IedB,g%ied-1)
2857 do k=1,nz ;
do i=segment%HI%IsdB+1,segment%HI%IedB-1
2858 rx_avg = rx_tang_obl(i,j,k)
2859 ry_avg = ry_tang_obl(i,j,k)
2860 cff_avg = cff_tangential(i,j,k)
2861 segment%tangential_grad(i,j,k) = &
2862 ((cff_avg*(u_new(i,j+2,k) - u_new(i,j+1,k))*g%IdyBu(i,j+1) + &
2863 ry_avg*(u_new(i,j+3,k) - u_new(i,j+2,k))*g%IdyBu(i,j+2)) - &
2864 (max(rx_avg,0.0)*segment%grad_gradient(i,2,k) + &
2865 min(rx_avg,0.0)*segment%grad_gradient(i+1,2,k))) / &
2869 if (segment%nudged_grad)
then
2870 do k=1,nz ;
do j=segment%HI%JsdB,segment%HI%JedB
2872 if (ry_tang_obl(i,j,k) <= 0.0)
then
2873 tau = segment%Velocity_nudging_timescale_in
2875 tau = segment%Velocity_nudging_timescale_out
2877 gamma_2 = dt / (tau + dt)
2878 segment%tangential_grad(i,j,k) = (1.0 - gamma_2) * segment%tangential_grad(i,j,k) + &
2879 gamma_2 * segment%nudged_tangential_grad(i,j,k)
2882 deallocate(rx_tang_obl)
2883 deallocate(ry_tang_obl)
2884 deallocate(cff_tangential)
2892 call pass_vector(u_new, v_new, g%Domain, clock=
id_clock_pass)
2900 type(ocean_grid_type),
intent(inout) :: g
2901 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(inout) :: u
2903 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(inout) :: v
2906 integer :: i, j, k, n
2909 if (.not.
associated(obc))
return
2911 do n=1,obc%number_of_segments
2912 segment => obc%segment(n)
2913 if (.not. segment%on_pe)
then
2915 elseif (segment%radiation .or. segment%oblique .or. segment%gradient)
then
2916 if (segment%is_E_or_W)
then
2918 do k=1,g%ke ;
do j=segment%HI%jsd,segment%HI%jed
2919 u(i,j,k) = segment%normal_vel(i,j,k)
2921 elseif (segment%is_N_or_S)
then
2923 do k=1,g%ke ;
do i=segment%HI%isd,segment%HI%ied
2924 v(i,j,k) = segment%normal_vel(i,j,k)
2936 type(ocean_grid_type),
intent(inout) :: g
2937 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(inout) :: u
2938 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(inout) :: v
2940 integer :: i, j, k, n
2943 if (.not.
associated(obc))
return
2945 do n=1,obc%number_of_segments
2946 segment => obc%segment(n)
2947 if (.not. segment%on_pe)
then
2949 elseif (segment%is_E_or_W)
then
2951 do k=1,g%ke ;
do j=segment%HI%jsd,segment%HI%jed
2954 elseif (segment%is_N_or_S)
then
2956 do k=1,g%ke ;
do i=segment%HI%isd,segment%HI%ied
2966 type(ocean_grid_type),
intent(in) :: G
2968 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: uvel
2969 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: vvel
2972 if (.not. segment%on_pe)
return
2974 if (segment%is_E_or_W)
then
2978 do j=max(segment%HI%JsdB, g%HI%JsdB+1),min(segment%HI%JedB, g%HI%JedB-1)
2979 segment%grad_normal(j,1,k) = (uvel(i-1,j+1,k)-uvel(i-1,j,k)) * g%mask2dBu(i-1,j)
2980 segment%grad_normal(j,2,k) = (uvel(i,j+1,k)-uvel(i,j,k)) * g%mask2dBu(i,j)
2983 if (segment%oblique_tan)
then
2985 do j=max(segment%HI%jsd-1, g%HI%jsd),min(segment%HI%jed+1, g%HI%jed)
2986 segment%grad_tan(j,1,k) = (vvel(i-1,j,k)-vvel(i-1,j-1,k)) * g%mask2dT(i-1,j)
2987 segment%grad_tan(j,2,k) = (vvel(i,j,k)-vvel(i,j-1,k)) * g%mask2dT(i,j)
2991 if (segment%oblique_grad)
then
2993 do j=max(segment%HI%jsd, g%HI%jsd+1),min(segment%HI%jed, g%HI%jed-1)
2994 segment%grad_gradient(j,1,k) = (((vvel(i-1,j,k) - vvel(i-2,j,k))*g%IdxBu(i-2,j)) - &
2995 (vvel(i-1,j-1,k) - vvel(i-2,j-1,k))*g%IdxBu(i-2,j-1)) * g%mask2dCu(i-2,j)
2996 segment%grad_gradient(j,2,k) = (((vvel(i,j,k) - vvel(i-1,j,k))*g%IdxBu(i-1,j)) - &
2997 (vvel(i,j-1,k) - vvel(i-1,j-1,k))*g%IdxBu(i-1,j-1)) * g%mask2dCu(i-1,j)
3004 do j=max(segment%HI%JsdB, g%HI%JsdB+1),min(segment%HI%JedB, g%HI%JedB-1)
3005 segment%grad_normal(j,1,k) = (uvel(i+1,j+1,k)-uvel(i+1,j,k)) * g%mask2dBu(i+1,j)
3006 segment%grad_normal(j,2,k) = (uvel(i,j+1,k)-uvel(i,j,k)) * g%mask2dBu(i,j)
3009 if (segment%oblique_tan)
then
3011 do j=max(segment%HI%jsd-1, g%HI%jsd),min(segment%HI%jed+1, g%HI%jed)
3012 segment%grad_tan(j,1,k) = (vvel(i+2,j,k)-vvel(i+2,j-1,k)) * g%mask2dT(i+2,j)
3013 segment%grad_tan(j,2,k) = (vvel(i+1,j,k)-vvel(i+1,j-1,k)) * g%mask2dT(i+1,j)
3017 if (segment%oblique_grad)
then
3019 do j=max(segment%HI%jsd, g%HI%jsd+1),min(segment%HI%jed, g%HI%jed-1)
3020 segment%grad_gradient(j,1,k) = (((vvel(i+3,j,k) - vvel(i+2,j,k))*g%IdxBu(i+2,j)) - &
3021 (vvel(i+3,j-1,k) - vvel(i+2,j-1,k))*g%IdxBu(i+2,j-1)) * g%mask2dCu(i+2,j)
3022 segment%grad_gradient(j,2,k) = (((vvel(i+2,j,k) - vvel(i+1,j,k))*g%IdxBu(i+1,j)) - &
3023 (vvel(i+2,j-1,k) - vvel(i+1,j-1,k))*g%IdxBu(i+1,j-1)) * g%mask2dCu(i+1,j)
3028 elseif (segment%is_N_or_S)
then
3032 do i=max(segment%HI%IsdB, g%HI%IsdB+1),min(segment%HI%IedB, g%HI%IedB-1)
3033 segment%grad_normal(i,1,k) = (vvel(i+1,j-1,k)-vvel(i,j-1,k)) * g%mask2dBu(i,j-1)
3034 segment%grad_normal(i,2,k) = (vvel(i+1,j,k)-vvel(i,j,k)) * g%mask2dBu(i,j)
3037 if (segment%oblique_tan)
then
3039 do i=max(segment%HI%isd-1, g%HI%isd),min(segment%HI%ied+1, g%HI%ied)
3040 segment%grad_tan(i,1,k) = (uvel(i,j-1,k)-uvel(i-1,j-1,k)) * g%mask2dT(i,j-1)
3041 segment%grad_tan(i,2,k) = (uvel(i,j,k)-uvel(i-1,j,k)) * g%mask2dT(i,j)
3045 if (segment%oblique_grad)
then
3047 do i=max(segment%HI%isd, g%HI%isd+1),min(segment%HI%ied, g%HI%ied-1)
3048 segment%grad_gradient(i,1,k) = (((uvel(i,j-1,k) - uvel(i,j-2,k))*g%IdyBu(i,j-2)) - &
3049 (uvel(i-1,j-1,k) - uvel(i-1,j-2,k))*g%IdyBu(i-1,j-2)) * g%mask2dCv(i,j-2)
3050 segment%grad_gradient(i,2,k) = (((uvel(i,j,k) - uvel(i,j-1,k))*g%IdyBu(i,j-1)) - &
3051 (uvel(i-1,j,k) - uvel(i-1,j-1,k))*g%IdyBu(i-1,j-1)) * g%mask2dCv(i,j-1)
3058 do i=max(segment%HI%IsdB, g%HI%IsdB+1),min(segment%HI%IedB, g%HI%IedB-1)
3059 segment%grad_normal(i,1,k) = (vvel(i+1,j+1,k)-vvel(i,j+1,k)) * g%mask2dBu(i,j+1)
3060 segment%grad_normal(i,2,k) = (vvel(i+1,j,k)-vvel(i,j,k)) * g%mask2dBu(i,j)
3063 if (segment%oblique_tan)
then
3065 do i=max(segment%HI%isd-1, g%HI%isd),min(segment%HI%ied+1, g%HI%ied)
3066 segment%grad_tan(i,1,k) = (uvel(i,j+2,k)-uvel(i-1,j+2,k)) * g%mask2dT(i,j+2)
3067 segment%grad_tan(i,2,k) = (uvel(i,j+1,k)-uvel(i-1,j+1,k)) * g%mask2dT(i,j+1)
3071 if (segment%oblique_grad)
then
3073 do i=max(segment%HI%isd, g%HI%isd+1),min(segment%HI%ied, g%HI%ied-1)
3074 segment%grad_gradient(i,1,k) = (((uvel(i,j+3,k) - uvel(i,j+2,k))*g%IdyBu(i,j+2)) - &
3075 (uvel(i-1,j+3,k) - uvel(i-1,j+2,k))*g%IdyBu(i-1,j+2)) * g%mask2dCv(i,j+2)
3076 segment%grad_gradient(i,2,k) = (((uvel(i,j+2,k) - uvel(i,j+1,k))*g%IdyBu(i,j+1)) - &
3077 (uvel(i-1,j+2,k) - uvel(i-1,j+1,k))*g%IdyBu(i-1,j+1)) * g%mask2dCv(i,j+1)
3090 type(ocean_grid_type),
intent(inout) :: g
3092 type(thermo_var_ptrs),
intent(inout) :: tv
3093 real,
dimension(SZI_(G),SZJ_(G), SZK_(G)),
intent(inout) :: h
3094 type(param_file_type),
intent(in) :: pf
3095 type(tracer_registry_type),
pointer :: tracer_reg
3097 integer :: i, j, k, itt, is, ie, js, je, isd, ied, jsd, jed, nz, n
3098 integer :: isd_off, jsd_off
3099 integer :: isdb, iedb, jsdb, jedb
3101 character(len=40) ::
mdl =
"set_tracer_data"
3102 character(len=200) :: filename, obc_file, inputdir
3104 real :: temp_u(g%domain%niglobal+1,g%domain%njglobal)
3105 real :: temp_v(g%domain%niglobal,g%domain%njglobal+1)
3107 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
3108 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
3109 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
3115 if (
associated(tv%T))
then
3117 call pass_var(tv%T, g%Domain)
3118 call pass_var(tv%S, g%Domain)
3120 do n=1,obc%number_of_segments
3121 segment => obc%segment(n)
3122 if (.not. segment%on_pe) cycle
3126 do k=1,g%ke ;
do j=segment%HI%jsd,segment%HI%jed
3127 tv%T(i+1,j,k) = tv%T(i,j,k) ; tv%S(i+1,j,k) = tv%S(i,j,k)
3131 do k=1,g%ke ;
do j=segment%HI%jsd,segment%HI%jed
3132 tv%T(i,j,k) = tv%T(i+1,j,k) ; tv%S(i,j,k) = tv%S(i+1,j,k)
3136 do k=1,g%ke ;
do i=segment%HI%isd,segment%HI%ied
3137 tv%T(i,j+1,k) = tv%T(i,j,k) ; tv%S(i,j+1,k) = tv%S(i,j,k)
3141 do k=1,g%ke ;
do i=segment%HI%isd,segment%HI%ied
3142 tv%T(i,j,k) = tv%T(i,j+1,k) ; tv%S(i,j,k) = tv%S(i,j+1,k)
3153 character(len=32),
intent(in) :: field
3159 do n=1,obc_seg%num_fields
3160 if (trim(field) == obc_seg%field(n)%name)
then
3174 integer :: isd, ied, jsd, jed
3175 integer :: IsdB, IedB, JsdB, JedB
3176 integer :: IscB, IecB, JscB, JecB
3177 character(len=40) :: mdl =
"allocate_OBC_segment_data"
3179 isd = segment%HI%isd ; ied = segment%HI%ied
3180 jsd = segment%HI%jsd ; jed = segment%HI%jed
3181 isdb = segment%HI%IsdB ; iedb = segment%HI%IedB
3182 jsdb = segment%HI%JsdB ; jedb = segment%HI%JedB
3183 iscb = segment%HI%IscB ; iecb = segment%HI%IecB
3184 jscb = segment%HI%JscB ; jecb = segment%HI%JecB
3186 if (.not. segment%on_pe)
return
3188 if (segment%is_E_or_W)
then
3190 allocate(segment%Cg(isdb:iedb,jsd:jed)); segment%Cg(:,:)=0.
3191 allocate(segment%Htot(isdb:iedb,jsd:jed)); segment%Htot(:,:)=0.0
3192 allocate(segment%h(isdb:iedb,jsd:jed,obc%ke)); segment%h(:,:,:)=0.0
3193 allocate(segment%eta(isdb:iedb,jsd:jed)); segment%eta(:,:)=0.0
3194 if (segment%radiation)
then
3195 allocate(segment%rx_norm_rad(isdb:iedb,jsd:jed,obc%ke)); segment%rx_norm_rad(:,:,:)=0.0
3197 allocate(segment%normal_vel(isdb:iedb,jsd:jed,obc%ke)); segment%normal_vel(:,:,:)=0.0
3198 allocate(segment%normal_vel_bt(isdb:iedb,jsd:jed)); segment%normal_vel_bt(:,:)=0.0
3199 allocate(segment%normal_trans(isdb:iedb,jsd:jed,obc%ke)); segment%normal_trans(:,:,:)=0.0
3200 if (segment%nudged)
then
3201 allocate(segment%nudged_normal_vel(isdb:iedb,jsd:jed,obc%ke)); segment%nudged_normal_vel(:,:,:)=0.0
3203 if (segment%radiation_tan .or. segment%nudged_tan .or. segment%specified_tan .or. &
3204 segment%oblique_tan .or. obc%computed_vorticity .or. obc%computed_strain)
then
3205 allocate(segment%tangential_vel(isdb:iedb,jsdb:jedb,obc%ke)); segment%tangential_vel(:,:,:)=0.0
3207 if (segment%nudged_tan)
then
3208 allocate(segment%nudged_tangential_vel(isdb:iedb,jsdb:jedb,obc%ke)); segment%nudged_tangential_vel(:,:,:)=0.0
3210 if (segment%nudged_grad)
then
3211 allocate(segment%nudged_tangential_grad(isdb:iedb,jsdb:jedb,obc%ke)); segment%nudged_tangential_grad(:,:,:)=0.0
3213 if (obc%specified_vorticity .or. obc%specified_strain .or. segment%radiation_grad .or. &
3214 segment%oblique_grad)
then
3215 allocate(segment%tangential_grad(isdb:iedb,jsdb:jedb,obc%ke)); segment%tangential_grad(:,:,:)=0.0
3217 if (segment%oblique)
then
3218 allocate(segment%grad_normal(jsdb:jedb,2,obc%ke)); segment%grad_normal(:,:,:) = 0.0
3219 allocate(segment%rx_norm_obl(isdb:iedb,jsd:jed,obc%ke)); segment%rx_norm_obl(:,:,:)=0.0
3220 allocate(segment%ry_norm_obl(isdb:iedb,jsd:jed,obc%ke)); segment%ry_norm_obl(:,:,:)=0.0
3221 allocate(segment%cff_normal(isdb:iedb,jsd:jed,obc%ke)); segment%cff_normal(:,:,:)=0.0
3223 if (segment%oblique_tan)
then
3224 allocate(segment%grad_tan(jsd-1:jed+1,2,obc%ke)); segment%grad_tan(:,:,:) = 0.0
3226 if (segment%oblique_grad)
then
3227 allocate(segment%grad_gradient(jsd:jed,2,obc%ke)); segment%grad_gradient(:,:,:) = 0.0
3231 if (segment%is_N_or_S)
then
3233 allocate(segment%Cg(isd:ied,jsdb:jedb)); segment%Cg(:,:)=0.
3234 allocate(segment%Htot(isd:ied,jsdb:jedb)); segment%Htot(:,:)=0.0
3235 allocate(segment%h(isd:ied,jsdb:jedb,obc%ke)); segment%h(:,:,:)=0.0
3236 allocate(segment%eta(isd:ied,jsdb:jedb)); segment%eta(:,:)=0.0
3237 if (segment%radiation)
then
3238 allocate(segment%ry_norm_rad(isd:ied,jsdb:jedb,obc%ke)); segment%ry_norm_rad(:,:,:)=0.0
3240 allocate(segment%normal_vel(isd:ied,jsdb:jedb,obc%ke)); segment%normal_vel(:,:,:)=0.0
3241 allocate(segment%normal_vel_bt(isd:ied,jsdb:jedb)); segment%normal_vel_bt(:,:)=0.0
3242 allocate(segment%normal_trans(isd:ied,jsdb:jedb,obc%ke)); segment%normal_trans(:,:,:)=0.0
3243 if (segment%nudged)
then
3244 allocate(segment%nudged_normal_vel(isd:ied,jsdb:jedb,obc%ke)); segment%nudged_normal_vel(:,:,:)=0.0
3246 if (segment%radiation_tan .or. segment%nudged_tan .or. segment%specified_tan .or. &
3247 segment%oblique_tan .or. obc%computed_vorticity .or. obc%computed_strain)
then
3248 allocate(segment%tangential_vel(isdb:iedb,jsdb:jedb,obc%ke)); segment%tangential_vel(:,:,:)=0.0
3250 if (segment%nudged_tan)
then
3251 allocate(segment%nudged_tangential_vel(isdb:iedb,jsdb:jedb,obc%ke)); segment%nudged_tangential_vel(:,:,:)=0.0
3253 if (segment%nudged_grad)
then
3254 allocate(segment%nudged_tangential_grad(isdb:iedb,jsdb:jedb,obc%ke)); segment%nudged_tangential_grad(:,:,:)=0.0
3256 if (obc%specified_vorticity .or. obc%specified_strain .or. segment%radiation_grad .or. &
3257 segment%oblique_grad)
then
3258 allocate(segment%tangential_grad(isdb:iedb,jsdb:jedb,obc%ke)); segment%tangential_grad(:,:,:)=0.0
3260 if (segment%oblique)
then
3261 allocate(segment%grad_normal(isdb:iedb,2,obc%ke)); segment%grad_normal(:,:,:) = 0.0
3262 allocate(segment%rx_norm_obl(isd:ied,jsdb:jedb,obc%ke)); segment%rx_norm_obl(:,:,:)=0.0
3263 allocate(segment%ry_norm_obl(isd:ied,jsdb:jedb,obc%ke)); segment%ry_norm_obl(:,:,:)=0.0
3264 allocate(segment%cff_normal(isd:ied,jsdb:jedb,obc%ke)); segment%cff_normal(:,:,:)=0.0
3266 if (segment%oblique_tan)
then
3267 allocate(segment%grad_tan(isd-1:ied+1,2,obc%ke)); segment%grad_tan(:,:,:) = 0.0
3269 if (segment%oblique_grad)
then
3270 allocate(segment%grad_gradient(isd:ied,2,obc%ke)); segment%grad_gradient(:,:,:) = 0.0
3281 character(len=40) :: mdl =
"deallocate_OBC_segment_data"
3283 if (.not. segment%on_pe)
return
3285 if (
associated (segment%Cg))
deallocate(segment%Cg)
3286 if (
associated (segment%Htot))
deallocate(segment%Htot)
3287 if (
associated (segment%h))
deallocate(segment%h)
3288 if (
associated (segment%eta))
deallocate(segment%eta)
3289 if (
associated (segment%rx_norm_rad))
deallocate(segment%rx_norm_rad)
3290 if (
associated (segment%ry_norm_rad))
deallocate(segment%ry_norm_rad)
3291 if (
associated (segment%rx_norm_obl))
deallocate(segment%rx_norm_obl)
3292 if (
associated (segment%ry_norm_obl))
deallocate(segment%ry_norm_obl)
3293 if (
associated (segment%cff_normal))
deallocate(segment%cff_normal)
3294 if (
associated (segment%grad_normal))
deallocate(segment%grad_normal)
3295 if (
associated (segment%grad_tan))
deallocate(segment%grad_tan)
3296 if (
associated (segment%grad_gradient))
deallocate(segment%grad_gradient)
3297 if (
associated (segment%normal_vel))
deallocate(segment%normal_vel)
3298 if (
associated (segment%normal_vel_bt))
deallocate(segment%normal_vel_bt)
3299 if (
associated (segment%normal_trans))
deallocate(segment%normal_trans)
3300 if (
associated (segment%nudged_normal_vel))
deallocate(segment%nudged_normal_vel)
3301 if (
associated (segment%tangential_vel))
deallocate(segment%tangential_vel)
3302 if (
associated (segment%nudged_tangential_vel))
deallocate(segment%nudged_tangential_vel)
3303 if (
associated (segment%nudged_tangential_grad))
deallocate(segment%nudged_tangential_grad)
3304 if (
associated (segment%tangential_grad))
deallocate(segment%tangential_grad)
3314 type(ocean_grid_type),
intent(in) :: g
3316 real,
dimension(SZIB_(G),SZJ_(G), SZK_(G)),
intent(inout) :: u
3317 real,
dimension(SZI_(G),SZJB_(G), SZK_(G)),
intent(inout) :: v
3319 integer :: i, j, k, n
3321 if (.not.
associated(obc))
return
3323 do n = 1, obc%number_of_segments
3325 if (obc%segment(n)%is_N_or_S)
then
3326 j = obc%segment(n)%HI%JsdB
3328 do i = obc%segment(n)%HI%IsdB, obc%segment(n)%HI%IedB
3329 u(i,j+1,k) = obc%silly_u
3332 do i = obc%segment(n)%HI%IsdB, obc%segment(n)%HI%IedB
3333 u(i,j,k) = obc%silly_u
3336 elseif (obc%segment(n)%is_E_or_W)
then
3337 i = obc%segment(n)%HI%IsdB
3339 do j = obc%segment(n)%HI%JsdB, obc%segment(n)%HI%JedB
3340 v(i+1,j,k) = obc%silly_u
3343 do j = obc%segment(n)%HI%JsdB, obc%segment(n)%HI%JedB
3344 v(i,j,k) = obc%silly_u
3357 type(ocean_grid_type),
intent(in) :: g
3358 type(verticalgrid_type),
intent(in) :: gv
3360 real,
dimension(SZI_(G),SZJ_(G), SZK_(GV)),
intent(inout) :: h
3363 integer :: i, j, k, n
3365 if (.not.
associated(obc))
return
3367 silly_h = gv%Z_to_H*obc%silly_h
3369 do n = 1, obc%number_of_segments
3371 if (obc%segment(n)%is_N_or_S)
then
3372 j = obc%segment(n)%HI%JsdB
3374 do i = obc%segment(n)%HI%isd, obc%segment(n)%HI%ied
3375 h(i,j+1,k) = silly_h
3378 do i = obc%segment(n)%HI%isd, obc%segment(n)%HI%ied
3382 elseif (obc%segment(n)%is_E_or_W)
then
3383 i = obc%segment(n)%HI%IsdB
3385 do j = obc%segment(n)%HI%jsd, obc%segment(n)%HI%jed
3386 h(i+1,j,k) = silly_h
3389 do j = obc%segment(n)%HI%jsd, obc%segment(n)%HI%jed
3401 type(ocean_grid_type),
intent(in) :: g
3402 type(verticalgrid_type),
intent(in) :: gv
3403 type(unit_scale_type),
intent(in) :: us
3405 type(thermo_var_ptrs),
intent(in) :: tv
3406 real,
dimension(SZI_(G),SZJ_(G), SZK_(G)),
intent(inout) :: h
3407 type(time_type),
intent(in) :: time
3409 integer :: i, j, k, is, ie, js, je, isd, ied, jsd, jed
3410 integer :: isdb, iedb, jsdb, jedb, n, m, nz
3411 character(len=40) ::
mdl =
"set_OBC_segment_data"
3412 character(len=200) :: filename, obc_file, inputdir
3414 integer,
dimension(4) :: siz,siz2
3416 integer :: ni_seg, nj_seg
3418 integer :: is_obc, ie_obc, js_obc, je_obc
3419 integer :: ishift, jshift
3420 real,
dimension(:,:),
pointer :: seg_vel => null()
3421 real,
dimension(:,:),
pointer :: seg_trans => null()
3422 real,
dimension(:,:,:),
allocatable :: tmp_buffer
3423 real,
dimension(:),
allocatable :: h_stack
3424 integer :: is_obc2, js_obc2
3425 real :: net_h_src, net_h_int, scl_fac
3426 real,
pointer,
dimension(:,:) :: normal_trans_bt=>null()
3428 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
3429 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
3430 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
3433 if (.not.
associated(obc))
return
3435 do n = 1, obc%number_of_segments
3436 segment => obc%segment(n)
3438 if (.not. segment%on_pe) cycle
3440 ni_seg = segment%ie_obc-segment%is_obc+1
3441 nj_seg = segment%je_obc-segment%js_obc+1
3442 is_obc = max(segment%is_obc,isd-1)
3443 ie_obc = min(segment%ie_obc,ied)
3444 js_obc = max(segment%js_obc,jsd-1)
3445 je_obc = min(segment%je_obc,jed)
3458 if (segment%is_E_or_W)
then
3459 allocate(normal_trans_bt(segment%HI%IsdB:segment%HI%IedB,segment%HI%jsd:segment%HI%jed))
3460 normal_trans_bt(:,:)=0.0
3463 do j=segment%HI%jsd,segment%HI%jed
3464 segment%Cg(i,j) = sqrt(gv%g_prime(1)*g%bathyT(i+ishift,j))
3465 segment%Htot(i,j)=0.0
3467 segment%h(i,j,k) = h(i+ishift,j,k)
3468 segment%Htot(i,j)=segment%Htot(i,j)+segment%h(i,j,k)
3472 allocate(normal_trans_bt(segment%HI%isd:segment%HI%ied,segment%HI%JsdB:segment%HI%JedB))
3473 normal_trans_bt(:,:)=0.0
3476 do i=segment%HI%isd,segment%HI%ied
3477 segment%Cg(i,j) = sqrt(gv%g_prime(1)*g%bathyT(i,j+jshift))
3478 segment%Htot(i,j)=0.0
3480 segment%h(i,j,k) = h(i,j+jshift,k)
3481 segment%Htot(i,j)=segment%Htot(i,j)+segment%h(i,j,k)
3486 allocate(h_stack(g%ke))
3488 do m = 1,segment%num_fields
3489 if (segment%field(m)%fid > 0)
then
3490 siz(1)=
size(segment%field(m)%buffer_src,1)
3491 siz(2)=
size(segment%field(m)%buffer_src,2)
3492 siz(3)=
size(segment%field(m)%buffer_src,3)
3493 if (.not.
associated(segment%field(m)%buffer_dst))
then
3494 if (siz(3) /= segment%field(m)%nk_src)
call mom_error(fatal,
'nk_src inconsistency')
3495 if (segment%field(m)%nk_src > 1)
then
3496 if (segment%is_E_or_W)
then
3497 if (segment%field(m)%name ==
'V' .or. segment%field(m)%name ==
'DVDX')
then
3498 allocate(segment%field(m)%buffer_dst(is_obc:ie_obc,js_obc:je_obc,g%ke))
3500 allocate(segment%field(m)%buffer_dst(is_obc:ie_obc,js_obc+1:je_obc,g%ke))
3502 if (segment%field(m)%name ==
'U')
then
3503 allocate(segment%field(m)%bt_vel(is_obc:ie_obc,js_obc+1:je_obc))
3504 segment%field(m)%bt_vel(:,:)=0.0
3507 if (segment%field(m)%name ==
'U' .or. segment%field(m)%name ==
'DUDY')
then
3508 allocate(segment%field(m)%buffer_dst(is_obc:ie_obc,js_obc:je_obc,g%ke))
3510 allocate(segment%field(m)%buffer_dst(is_obc+1:ie_obc,js_obc:je_obc,g%ke))
3512 if (segment%field(m)%name ==
'V')
then
3513 allocate(segment%field(m)%bt_vel(is_obc+1:ie_obc,js_obc:je_obc))
3514 segment%field(m)%bt_vel(:,:)=0.0
3518 if (segment%is_E_or_W)
then
3519 if (segment%field(m)%name ==
'V' .or. segment%field(m)%name ==
'DVDX')
then
3520 allocate(segment%field(m)%buffer_dst(is_obc:ie_obc,js_obc:je_obc,1))
3522 allocate(segment%field(m)%buffer_dst(is_obc:ie_obc,js_obc+1:je_obc,1))
3524 if (segment%field(m)%name ==
'U')
then
3525 allocate(segment%field(m)%bt_vel(is_obc:ie_obc,js_obc+1:je_obc))
3526 segment%field(m)%bt_vel(:,:)=0.0
3529 if (segment%field(m)%name ==
'U' .or. segment%field(m)%name ==
'DUDY')
then
3530 allocate(segment%field(m)%buffer_dst(is_obc:ie_obc,js_obc:je_obc,1))
3532 allocate(segment%field(m)%buffer_dst(is_obc+1:ie_obc,js_obc:je_obc,1))
3534 if (segment%field(m)%name ==
'V')
then
3535 allocate(segment%field(m)%bt_vel(is_obc+1:ie_obc,js_obc:je_obc))
3536 segment%field(m)%bt_vel(:,:)=0.0
3540 segment%field(m)%buffer_dst(:,:,:)=0.0
3544 if (obc%brushcutter_mode)
then
3545 allocate(tmp_buffer(1,nj_seg*2-1,segment%field(m)%nk_src))
3547 allocate(tmp_buffer(1,nj_seg,segment%field(m)%nk_src))
3550 if (obc%brushcutter_mode)
then
3551 allocate(tmp_buffer(ni_seg*2-1,1,segment%field(m)%nk_src))
3553 allocate(tmp_buffer(ni_seg,1,segment%field(m)%nk_src))
3557 call time_interp_external(segment%field(m)%fid,time, tmp_buffer)
3558 if (obc%brushcutter_mode)
then
3559 if (segment%is_E_or_W)
then
3560 if (segment%field(m)%name ==
'V' .or. segment%field(m)%name ==
'DVDX')
then
3561 segment%field(m)%buffer_src(is_obc,:,:) = &
3562 tmp_buffer(1,2*(js_obc+g%jdg_offset)+1:2*(je_obc+g%jdg_offset)+1:2,:)
3564 segment%field(m)%buffer_src(is_obc,:,:) = &
3565 tmp_buffer(1,2*(js_obc+g%jdg_offset)+1:2*(je_obc+g%jdg_offset):2,:)
3568 if (segment%field(m)%name ==
'U' .or. segment%field(m)%name ==
'DUDY')
then
3569 segment%field(m)%buffer_src(:,js_obc,:) = &
3570 tmp_buffer(2*(is_obc+g%idg_offset)+1:2*(ie_obc+g%idg_offset)+1:2,1,:)
3572 segment%field(m)%buffer_src(:,js_obc,:) = &
3573 tmp_buffer(2*(is_obc+g%idg_offset)+1:2*(ie_obc+g%idg_offset):2,1,:)
3577 if (segment%is_E_or_W)
then
3578 if (segment%field(m)%name ==
'V' .or. segment%field(m)%name ==
'DVDX')
then
3579 segment%field(m)%buffer_src(is_obc,:,:)=tmp_buffer(1,js_obc+g%jdg_offset+1:je_obc+g%jdg_offset+1,:)
3581 segment%field(m)%buffer_src(is_obc,:,:)=tmp_buffer(1,js_obc+g%jdg_offset+1:je_obc+g%jdg_offset,:)
3584 if (segment%field(m)%name ==
'U' .or. segment%field(m)%name ==
'DUDY')
then
3585 segment%field(m)%buffer_src(:,js_obc,:)=tmp_buffer(is_obc+g%idg_offset+1:ie_obc+g%idg_offset+1,1,:)
3587 segment%field(m)%buffer_src(:,js_obc,:)=tmp_buffer(is_obc+g%idg_offset+1:ie_obc+g%idg_offset,1,:)
3591 if (segment%field(m)%nk_src > 1)
then
3592 call time_interp_external(segment%field(m)%fid_dz,time, tmp_buffer)
3593 if (obc%brushcutter_mode)
then
3594 if (segment%is_E_or_W)
then
3595 if (segment%field(m)%name ==
'V' .or. segment%field(m)%name ==
'DVDX')
then
3596 segment%field(m)%dz_src(is_obc,:,:) = &
3597 tmp_buffer(1,2*(js_obc+g%jdg_offset)+1:2*(je_obc+g%jdg_offset)+1:2,:)
3599 segment%field(m)%dz_src(is_obc,:,:) = &
3600 tmp_buffer(1,2*(js_obc+g%jdg_offset)+1:2*(je_obc+g%jdg_offset):2,:)
3603 if (segment%field(m)%name ==
'U' .or. segment%field(m)%name ==
'DUDY')
then
3604 segment%field(m)%dz_src(:,js_obc,:) = &
3605 tmp_buffer(2*(is_obc+g%idg_offset)+1:2*(ie_obc+g%idg_offset)+1:2,1,:)
3607 segment%field(m)%dz_src(:,js_obc,:) = &
3608 tmp_buffer(2*(is_obc+g%idg_offset)+1:2*(ie_obc+g%idg_offset):2,1,:)
3612 if (segment%is_E_or_W)
then
3613 if (segment%field(m)%name ==
'V' .or. segment%field(m)%name ==
'DVDX')
then
3614 segment%field(m)%dz_src(is_obc,:,:)=tmp_buffer(1,js_obc+g%jdg_offset+1:je_obc+g%jdg_offset+1,:)
3616 segment%field(m)%dz_src(is_obc,:,:)=tmp_buffer(1,js_obc+g%jdg_offset+1:je_obc+g%jdg_offset,:)
3619 if (segment%field(m)%name ==
'U' .or. segment%field(m)%name ==
'DUDY')
then
3620 segment%field(m)%dz_src(:,js_obc,:)=tmp_buffer(is_obc+g%idg_offset+1:ie_obc+g%idg_offset+1,1,:)
3622 segment%field(m)%dz_src(:,js_obc,:)=tmp_buffer(is_obc+g%idg_offset+1:ie_obc+g%idg_offset,1,:)
3629 if (segment%is_E_or_W)
then
3633 if (segment%field(m)%name ==
'V' .or. segment%field(m)%name ==
'DVDX')
then
3635 do j=max(js_obc,jsd),min(je_obc,jed-1)
3638 segment%field(m)%buffer_dst(i,j,:)=0.0
3639 if (g%mask2dCu(i,j)>0. .and. g%mask2dCu(i,j+1)>0.)
then
3640 h_stack(:) = 0.5*(h(i+ishift,j,:) + h(i+ishift,j+1,:))
3641 call remapping_core_h(obc%remap_CS, &
3642 segment%field(m)%nk_src,segment%field(m)%dz_src(i,j,:), &
3643 segment%field(m)%buffer_src(i,j,:), &
3644 g%ke, h_stack, segment%field(m)%buffer_dst(i,j,:))
3645 elseif (g%mask2dCu(i,j)>0.)
then
3646 h_stack(:) = h(i+ishift,j,:)
3647 call remapping_core_h(obc%remap_CS, &
3648 segment%field(m)%nk_src,segment%field(m)%dz_src(i,j,:), &
3649 segment%field(m)%buffer_src(i,j,:), &
3650 g%ke, h_stack, segment%field(m)%buffer_dst(i,j,:))
3651 elseif (g%mask2dCu(i,j+1)>0.)
then
3652 h_stack(:) = h(i+ishift,j+1,:)
3653 call remapping_core_h(obc%remap_CS, &
3654 segment%field(m)%nk_src,segment%field(m)%dz_src(i,j,:), &
3655 segment%field(m)%buffer_src(i,j,:), &
3656 g%ke, h_stack, segment%field(m)%buffer_dst(i,j,:))
3660 do j=js_obc+1,je_obc
3663 segment%field(m)%buffer_dst(i,j,:)=0.0
3664 if (g%mask2dCu(i,j)>0.)
then
3665 net_h_src = sum( segment%field(m)%dz_src(i,j,:) )
3666 net_h_int = sum( h(i+ishift,j,:) )
3667 scl_fac = net_h_int / net_h_src
3668 call remapping_core_h(obc%remap_CS, &
3669 segment%field(m)%nk_src, scl_fac*segment%field(m)%dz_src(i,j,:), &
3670 segment%field(m)%buffer_src(i,j,:), &
3671 g%ke, h(i+ishift,j,:), segment%field(m)%buffer_dst(i,j,:))
3679 if (segment%field(m)%name ==
'U' .or. segment%field(m)%name ==
'DUDY')
then
3681 do i=max(is_obc,isd),min(ie_obc,ied-1)
3682 segment%field(m)%buffer_dst(i,j,:)=0.0
3683 if (g%mask2dCv(i,j)>0. .and. g%mask2dCv(i+1,j)>0.)
then
3686 h_stack(:) = 0.5*(h(i,j+jshift,:) + h(i+1,j+jshift,:))
3687 call remapping_core_h(obc%remap_CS, &
3688 segment%field(m)%nk_src,segment%field(m)%dz_src(i,j,:), &
3689 segment%field(m)%buffer_src(i,j,:), &
3690 g%ke, h_stack, segment%field(m)%buffer_dst(i,j,:))
3691 elseif (g%mask2dCv(i,j)>0.)
then
3692 h_stack(:) = h(i,j+jshift,:)
3693 call remapping_core_h(obc%remap_CS, &
3694 segment%field(m)%nk_src,segment%field(m)%dz_src(i,j,:), &
3695 segment%field(m)%buffer_src(i,j,:), &
3696 g%ke, h_stack, segment%field(m)%buffer_dst(i,j,:))
3697 elseif (g%mask2dCv(i+1,j)>0.)
then
3698 h_stack(:) = h(i+1,j+jshift,:)
3699 call remapping_core_h(obc%remap_CS, &
3700 segment%field(m)%nk_src,segment%field(m)%dz_src(i,j,:), &
3701 segment%field(m)%buffer_src(i,j,:), &
3702 g%ke, h_stack, segment%field(m)%buffer_dst(i,j,:))
3706 do i=is_obc+1,ie_obc
3709 segment%field(m)%buffer_dst(i,j,:)=0.0
3710 if (g%mask2dCv(i,j)>0.)
then
3711 net_h_src = sum( segment%field(m)%dz_src(i,j,:) )
3712 net_h_int = sum( h(i,j+jshift,:) )
3713 scl_fac = net_h_int / net_h_src
3714 call remapping_core_h(obc%remap_CS, &
3715 segment%field(m)%nk_src,segment%field(m)%dz_src(i,j,:), &
3716 segment%field(m)%buffer_src(i,j,:), &
3717 g%ke, h(i,j+jshift,:), segment%field(m)%buffer_dst(i,j,:))
3723 segment%field(m)%buffer_dst(:,:,1) = segment%field(m)%buffer_src(:,:,1)
3725 deallocate(tmp_buffer)
3727 if (.not.
associated(segment%field(m)%buffer_dst))
then
3728 if (segment%is_E_or_W)
then
3729 if (segment%field(m)%name ==
'V')
then
3730 allocate(segment%field(m)%buffer_dst(is_obc:ie_obc,js_obc:je_obc,g%ke))
3731 allocate(segment%field(m)%bt_vel(is_obc:ie_obc,js_obc:je_obc))
3732 elseif (segment%field(m)%name ==
'U')
then
3733 allocate(segment%field(m)%buffer_dst(is_obc:ie_obc,js_obc+1:je_obc,g%ke))
3734 allocate(segment%field(m)%bt_vel(is_obc:ie_obc,js_obc+1:je_obc))
3735 elseif (segment%field(m)%name ==
'DVDX')
then
3736 allocate(segment%field(m)%buffer_dst(is_obc:ie_obc,js_obc:je_obc,g%ke))
3737 elseif (segment%field(m)%name ==
'SSH')
then
3738 allocate(segment%field(m)%buffer_dst(is_obc:ie_obc,js_obc:je_obc,1))
3740 allocate(segment%field(m)%buffer_dst(is_obc:ie_obc,js_obc+1:je_obc,g%ke))
3743 if (segment%field(m)%name ==
'U')
then
3744 allocate(segment%field(m)%buffer_dst(is_obc:ie_obc,js_obc:je_obc,g%ke))
3745 allocate(segment%field(m)%bt_vel(is_obc:ie_obc,js_obc:je_obc))
3746 elseif (segment%field(m)%name ==
'V')
then
3747 allocate(segment%field(m)%buffer_dst(is_obc+1:ie_obc,js_obc:je_obc,g%ke))
3748 allocate(segment%field(m)%bt_vel(is_obc+1:ie_obc,js_obc:je_obc))
3749 elseif (segment%field(m)%name ==
'DUDY')
then
3750 allocate(segment%field(m)%buffer_dst(is_obc:ie_obc,js_obc:je_obc,g%ke))
3751 elseif (segment%field(m)%name ==
'SSH')
then
3752 allocate(segment%field(m)%buffer_dst(is_obc:ie_obc,js_obc:je_obc,1))
3754 allocate(segment%field(m)%buffer_dst(is_obc+1:ie_obc,js_obc:je_obc,g%ke))
3757 segment%field(m)%buffer_dst(:,:,:) = segment%field(m)%value
3758 if (trim(segment%field(m)%name) ==
'U' .or. trim(segment%field(m)%name) ==
'V')
then
3759 segment%field(m)%bt_vel(:,:) = segment%field(m)%value
3764 if (trim(segment%field(m)%name) ==
'U' .or. trim(segment%field(m)%name) ==
'V')
then
3765 if (segment%field(m)%fid>0)
then
3766 if (trim(segment%field(m)%name) ==
'U' .and. segment%is_E_or_W)
then
3768 do j=js_obc+1,je_obc
3769 normal_trans_bt(i,j) = 0.0
3771 segment%normal_vel(i,j,k) = us%m_s_to_L_T*segment%field(m)%buffer_dst(i,j,k)
3772 segment%normal_trans(i,j,k) = us%m_s_to_L_T*segment%field(m)%buffer_dst(i,j,k)*segment%h(i,j,k) * &
3774 normal_trans_bt(i,j) = normal_trans_bt(i,j) + segment%normal_trans(i,j,k)
3776 segment%normal_vel_bt(i,j) = normal_trans_bt(i,j) / (max(segment%Htot(i,j),1.e-12) * g%dyCu(i,j))
3777 if (
associated(segment%nudged_normal_vel)) segment%nudged_normal_vel(i,j,:) = segment%normal_vel(i,j,:)
3779 elseif (trim(segment%field(m)%name) ==
'V' .and. segment%is_N_or_S)
then
3781 do i=is_obc+1,ie_obc
3782 normal_trans_bt(i,j) = 0.0
3784 segment%normal_vel(i,j,k) = us%m_s_to_L_T*segment%field(m)%buffer_dst(i,j,k)
3785 segment%normal_trans(i,j,k) = us%m_s_to_L_T*segment%field(m)%buffer_dst(i,j,k)*segment%h(i,j,k) * &
3787 normal_trans_bt(i,j) = normal_trans_bt(i,j) + segment%normal_trans(i,j,k)
3789 segment%normal_vel_bt(i,j) = normal_trans_bt(i,j) / (max(segment%Htot(i,j),1.e-12) * g%dxCv(i,j))
3790 if (
associated(segment%nudged_normal_vel)) segment%nudged_normal_vel(i,j,:) = segment%normal_vel(i,j,:)
3792 elseif (trim(segment%field(m)%name) ==
'V' .and. segment%is_E_or_W .and. &
3793 associated(segment%tangential_vel))
then
3797 segment%tangential_vel(i,j,k) = us%m_s_to_L_T*segment%field(m)%buffer_dst(i,j,k)
3799 if (
associated(segment%nudged_tangential_vel)) &
3800 segment%nudged_tangential_vel(i,j,:) = segment%tangential_vel(i,j,:)
3802 elseif (trim(segment%field(m)%name) ==
'U' .and. segment%is_N_or_S .and. &
3803 associated(segment%tangential_vel))
then
3807 segment%tangential_vel(i,j,k) = us%m_s_to_L_T*segment%field(m)%buffer_dst(i,j,k)
3809 if (
associated(segment%nudged_tangential_vel)) &
3810 segment%nudged_tangential_vel(i,j,:) = segment%tangential_vel(i,j,:)
3812 elseif (trim(segment%field(m)%name) ==
'DVDX' .and. segment%is_E_or_W .and. &
3813 associated(segment%tangential_grad))
then
3817 segment%tangential_grad(i,j,k) = us%T_to_s*segment%field(m)%buffer_dst(i,j,k)
3820 elseif (trim(segment%field(m)%name) ==
'DUDY' .and. segment%is_N_or_S .and. &
3821 associated(segment%tangential_grad))
then
3825 segment%tangential_grad(i,j,k) = us%T_to_s*segment%field(m)%buffer_dst(i,j,k)
3834 if (segment%is_E_or_W)
then
3841 if (segment%is_N_or_S)
then
3849 if (trim(segment%field(m)%name) ==
'SSH')
then
3852 segment%eta(i,j) = segment%field(m)%buffer_dst(i,j,1)
3857 if (trim(segment%field(m)%name) ==
'TEMP')
then
3858 if (
associated(segment%field(m)%buffer_dst))
then
3859 do k=1,nz;
do j=js_obc2, je_obc;
do i=is_obc2,ie_obc
3860 segment%tr_Reg%Tr(1)%t(i,j,k) = segment%field(m)%buffer_dst(i,j,k)
3861 enddo ;
enddo ;
enddo
3862 if (.not. segment%tr_Reg%Tr(1)%is_initialized)
then
3864 do k=1,nz;
do j=js_obc2, je_obc;
do i=is_obc2,ie_obc
3865 segment%tr_Reg%Tr(1)%tres(i,j,k) = segment%tr_Reg%Tr(1)%t(i,j,k)
3866 enddo ;
enddo ;
enddo
3867 segment%tr_Reg%Tr(1)%is_initialized=.true.
3870 segment%tr_Reg%Tr(1)%OBC_inflow_conc = segment%field(m)%value
3872 elseif (trim(segment%field(m)%name) ==
'SALT')
then
3873 if (
associated(segment%field(m)%buffer_dst))
then
3874 do k=1,nz;
do j=js_obc2, je_obc;
do i=is_obc2,ie_obc
3875 segment%tr_Reg%Tr(2)%t(i,j,k) = segment%field(m)%buffer_dst(i,j,k)
3876 enddo ;
enddo ;
enddo
3877 if (.not. segment%tr_Reg%Tr(2)%is_initialized)
then
3879 do k=1,nz;
do j=js_obc2, je_obc;
do i=is_obc2,ie_obc
3880 segment%tr_Reg%Tr(2)%tres(i,j,k) = segment%tr_Reg%Tr(2)%t(i,j,k)
3881 enddo ;
enddo ;
enddo
3882 segment%tr_Reg%Tr(2)%is_initialized=.true.
3885 segment%tr_Reg%Tr(2)%OBC_inflow_conc = segment%field(m)%value
3891 deallocate(normal_trans_bt)
3899 character(len=32),
intent(in) :: name
3900 type(param_file_type),
intent(in) :: param_file
3903 character(len=256) :: mesg
3907 if (reg%nobc>=max_fields_)
then
3908 write(mesg,
'("Increase MAX_FIELDS_ in MOM_memory.h to at least ",I3," to allow for &
3909 &all the open boundaries being registered via register_OBC.")') reg%nobc+1
3910 call mom_error(fatal,
"MOM register_tracer: "//mesg)
3912 reg%nobc = reg%nobc + 1
3915 reg%OB(nobc)%name = name
3917 if (reg%locked)
call mom_error(fatal, &
3918 "MOM register_tracer was called for variable "//trim(reg%OB(nobc)%name)//&
3919 " with a locked tracer registry.")
3925 type(param_file_type),
intent(in) :: param_file
3928 integer,
save :: init_calls = 0
3930 #include "version_variable.h"
3931 character(len=40) ::
mdl =
"MOM_open_boundary"
3932 character(len=256) :: mesg
3934 if (.not.
associated(reg))
then ;
allocate(reg)
3935 else ;
return ;
endif
3940 init_calls = init_calls + 1
3941 if (init_calls > 1)
then
3942 write(mesg,
'("OBC_registry_init called ",I3, &
3943 &" times with different registry pointers.")') init_calls
3944 if (is_root_pe())
call mom_error(warning,
"MOM_open_boundary"//mesg)
3951 type(param_file_type),
intent(in) :: param_file
3955 character(len=32) :: casename =
"OBC file"
3957 if (
associated(cs))
then
3958 call mom_error(warning,
"register_file_OBC called with an "// &
3959 "associated control structure.")
3974 if (
associated(cs))
then
3981 type(param_file_type),
intent(in) :: param_file
3984 integer,
save :: init_calls = 0
3987 #include "version_variable.h"
3988 character(len=40) ::
mdl =
"segment_tracer_registry_init"
3989 character(len=256) :: mesg
3991 if (.not.
associated(segment%tr_Reg))
then
3992 allocate(segment%tr_Reg)
3997 init_calls = init_calls + 1
4000 if (init_calls == 1)
call log_version(param_file,
mdl, version,
"")
4012 OBC_scalar, OBC_array)
4013 type(verticalgrid_type),
intent(in) :: gv
4014 type(tracer_type),
target :: tr_ptr
4021 type(param_file_type),
intent(in) :: param_file
4023 real,
optional,
intent(in) :: obc_scalar
4025 logical,
optional,
intent(in) :: obc_array
4031 integer :: isd, ied, jsd, jed
4032 integer :: isdb, iedb, jsdb, jedb
4033 character(len=256) :: mesg
4037 if (segment%tr_Reg%ntseg>=max_fields_)
then
4038 write(mesg,
'("Increase MAX_FIELDS_ in MOM_memory.h to at least ",I3," to allow for &
4039 &all the tracers being registered via register_tracer.")') segment%tr_Reg%ntseg+1
4040 call mom_error(fatal,
"MOM register_tracer: "//mesg)
4042 segment%tr_Reg%ntseg = segment%tr_Reg%ntseg + 1
4043 ntseg = segment%tr_Reg%ntseg
4045 isd = segment%HI%isd ; ied = segment%HI%ied
4046 jsd = segment%HI%jsd ; jed = segment%HI%jed
4047 isdb = segment%HI%IsdB ; iedb = segment%HI%IedB
4048 jsdb = segment%HI%JsdB ; jedb = segment%HI%JedB
4050 segment%tr_Reg%Tr(ntseg)%Tr => tr_ptr
4051 segment%tr_Reg%Tr(ntseg)%name = tr_ptr%name
4053 if (segment%tr_Reg%locked)
call mom_error(fatal, &
4054 "MOM register_tracer was called for variable "//trim(segment%tr_Reg%Tr(ntseg)%name)//&
4055 " with a locked tracer registry.")
4057 if (
present(obc_scalar)) segment%tr_Reg%Tr(ntseg)%OBC_inflow_conc = obc_scalar
4058 if (
present(obc_array))
then
4059 if (segment%is_E_or_W)
then
4060 allocate(segment%tr_Reg%Tr(ntseg)%t(isdb:iedb,jsd:jed,1:gv%ke));segment%tr_Reg%Tr(ntseg)%t(:,:,:)=0.0
4061 allocate(segment%tr_Reg%Tr(ntseg)%tres(isdb:iedb,jsd:jed,1:gv%ke));segment%tr_Reg%Tr(ntseg)%tres(:,:,:)=0.0
4062 segment%tr_Reg%Tr(ntseg)%is_initialized=.false.
4063 elseif (segment%is_N_or_S)
then
4064 allocate(segment%tr_Reg%Tr(ntseg)%t(isd:ied,jsdb:jedb,1:gv%ke));segment%tr_Reg%Tr(ntseg)%t(:,:,:)=0.0
4065 allocate(segment%tr_Reg%Tr(ntseg)%tres(isd:ied,jsdb:jedb,1:gv%ke));segment%tr_Reg%Tr(ntseg)%tres(:,:,:)=0.0
4066 segment%tr_Reg%Tr(ntseg)%is_initialized=.false.
4079 if (
associated(reg))
then
4081 if (
associated(reg%Tr(n)%t))
deallocate(reg%Tr(n)%t)
4088 type(verticalgrid_type),
intent(in) :: gv
4090 type(tracer_registry_type),
pointer :: tr_reg
4091 type(param_file_type),
intent(in) :: param_file
4094 integer :: isd, ied, isdb, iedb, jsd, jed, jsdb, jedb, nz, nf
4095 integer :: i, j, k, n
4096 character(len=32) :: name
4098 type(tracer_type),
pointer :: tr_ptr => null()
4100 if (.not.
associated(obc))
return
4102 do n=1, obc%number_of_segments
4103 segment=>obc%segment(n)
4104 if (.not. segment%on_pe) cycle
4106 if (
associated(segment%tr_Reg)) &
4107 call mom_error(fatal,
"register_temp_salt_segments: tracer array was previously allocated")
4110 call tracer_name_lookup(tr_reg, tr_ptr, name)
4112 obc_array=segment%temp_segment_data_exists)
4114 call tracer_name_lookup(tr_reg, tr_ptr, name)
4116 obc_array=segment%salt_segment_data_exists)
4122 type(ocean_grid_type),
intent(inout) :: g
4124 type(thermo_var_ptrs),
intent(inout) :: tv
4127 integer :: isd, ied, isdb, iedb, jsd, jed, jsdb, jedb, n, nz
4131 if (.not.
associated(obc))
return
4132 if (.not.
associated(tv%T) .and.
associated(tv%S))
return
4135 call pass_var(tv%T, g%Domain)
4136 call pass_var(tv%S, g%Domain)
4140 do n=1, obc%number_of_segments
4141 segment => obc%segment(n)
4142 if (.not. segment%on_pe) cycle
4144 isd = segment%HI%isd ; ied = segment%HI%ied
4145 jsd = segment%HI%jsd ; jed = segment%HI%jed
4146 isdb = segment%HI%IsdB ; iedb = segment%HI%IedB
4147 jsdb = segment%HI%JsdB ; jedb = segment%HI%JedB
4150 if (segment%is_E_or_W)
then
4152 do k=1,nz ;
do j=segment%HI%jsd,segment%HI%jed
4154 segment%tr_Reg%Tr(1)%t(i,j,k) = tv%T(i+1,j,k)
4155 segment%tr_Reg%Tr(2)%t(i,j,k) = tv%S(i+1,j,k)
4157 segment%tr_Reg%Tr(1)%t(i,j,k) = tv%T(i,j,k)
4158 segment%tr_Reg%Tr(2)%t(i,j,k) = tv%S(i,j,k)
4163 do k=1,nz ;
do i=segment%HI%isd,segment%HI%ied
4165 segment%tr_Reg%Tr(1)%t(i,j,k) = tv%T(i,j+1,k)
4166 segment%tr_Reg%Tr(2)%t(i,j,k) = tv%S(i,j+1,k)
4168 segment%tr_Reg%Tr(1)%t(i,j,k) = tv%T(i,j,k)
4169 segment%tr_Reg%Tr(2)%t(i,j,k) = tv%S(i,j,k)
4173 segment%tr_Reg%Tr(1)%tres(:,:,:) = segment%tr_Reg%Tr(1)%t(:,:,:)
4174 segment%tr_Reg%Tr(2)%tres(:,:,:) = segment%tr_Reg%Tr(2)%t(:,:,:)
4183 type(dyn_horgrid_type),
intent(inout) :: G
4184 type(param_file_type),
intent(in) :: param_file
4186 type(unit_scale_type),
intent(in) :: US
4189 integer :: isd, ied, IsdB, IedB, jsd, jed, JsdB, JedB, n
4191 logical :: fatal_error = .false.
4193 integer,
parameter :: cin = 3, cout = 4, cland = -1, cedge = -2
4194 character(len=256) :: mesg
4196 real,
allocatable,
dimension(:,:) :: color, color2
4199 if (.not.
associated(obc))
return
4201 call get_param(param_file,
mdl,
"MINIMUM_DEPTH", min_depth, &
4202 units=
"m", default=0.0, scale=us%m_to_Z, do_not_log=.true.)
4204 allocate(color(g%isd:g%ied, g%jsd:g%jed)) ; color = 0
4205 allocate(color2(g%isd:g%ied, g%jsd:g%jed)) ; color2 = 0
4210 color(g%isd,j) = cedge
4211 color(g%ied,j) = cedge
4212 color2(g%isd,j) = cedge
4213 color2(g%ied,j) = cedge
4216 color(i,g%jsd) = cedge
4217 color(i,g%jed) = cedge
4218 color2(i,g%jsd) = cedge
4219 color2(i,g%jed) = cedge
4226 if (g%bathyT(i,j) <= min_depth) color(i,j) = cland
4227 if (g%bathyT(i,j) <= min_depth) color2(i,j) = cland
4231 do j=g%jsd,g%jed ;
do i=g%IsdB+1,g%IedB-1
4233 if (color(i,j) == 0.0) color(i,j) = cout
4234 if (color(i+1,j) == 0.0) color(i+1,j) = cin
4235 elseif (obc%segment(obc%segnum_u(i,j))%direction ==
obc_direction_e)
then
4236 if (color(i,j) == 0.0) color(i,j) = cin
4237 if (color(i+1,j) == 0.0) color(i+1,j) = cout
4240 do j=g%JsdB+1,g%JedB-1 ;
do i=g%isd,g%ied
4242 if (color(i,j) == 0.0) color(i,j) = cout
4243 if (color(i,j+1) == 0.0) color(i,j+1) = cin
4244 elseif (obc%segment(obc%segnum_v(i,j))%direction ==
obc_direction_n)
then
4245 if (color(i,j) == 0.0) color(i,j) = cin
4246 if (color(i,j+1) == 0.0) color(i,j+1) = cout
4250 do j=g%JsdB+1,g%JedB-1 ;
do i=g%isd,g%ied
4252 if (color2(i,j) == 0.0) color2(i,j) = cout
4253 if (color2(i,j+1) == 0.0) color2(i,j+1) = cin
4254 elseif (obc%segment(obc%segnum_v(i,j))%direction ==
obc_direction_n)
then
4255 if (color2(i,j) == 0.0) color2(i,j) = cin
4256 if (color2(i,j+1) == 0.0) color2(i,j+1) = cout
4259 do j=g%jsd,g%jed ;
do i=g%IsdB+1,g%IedB-1
4261 if (color2(i,j) == 0.0) color2(i,j) = cout
4262 if (color2(i+1,j) == 0.0) color2(i+1,j) = cin
4263 elseif (obc%segment(obc%segnum_u(i,j))%direction ==
obc_direction_e)
then
4264 if (color2(i,j) == 0.0) color2(i,j) = cin
4265 if (color2(i+1,j) == 0.0) color2(i+1,j) = cout
4274 do j=g%jsd,g%jed ;
do i=g%isd,g%ied
4275 if (color(i,j) /= color2(i,j))
then
4276 fatal_error = .true.
4277 write(mesg,
'("MOM_open_boundary: problem with OBC segments specification at ",I5,",",I5," during\n", &
4278 "the masking of the outside grid points.")') i, j
4279 call mom_error(warning,
"MOM register_tracer: "//mesg, all_print=.true.)
4281 if (color(i,j) == cout) g%bathyT(i,j) = min_depth
4283 if (fatal_error)
call mom_error(fatal, &
4284 "MOM_open_boundary: inconsistent OBC segments.")
4291 subroutine flood_fill(G, color, cin, cout, cland)
4292 type(dyn_horgrid_type),
intent(inout) :: G
4293 real,
dimension(:,:),
intent(inout) :: color
4294 integer,
intent(in) :: cin
4295 integer,
intent(in) :: cout
4296 integer,
intent(in) :: cland
4299 integer :: i, j, ncount
4302 do while (ncount > 0)
4304 do j=g%jsd+1,g%jed-1
4305 do i=g%isd+1,g%ied-1
4306 if (color(i,j) == 0.0 .and. color(i-1,j) > 0.0)
then
4307 color(i,j) = color(i-1,j)
4310 if (color(i,j) == 0.0 .and. color(i+1,j) > 0.0)
then
4311 color(i,j) = color(i+1,j)
4314 if (color(i,j) == 0.0 .and. color(i,j-1) > 0.0)
then
4315 color(i,j) = color(i,j-1)
4318 if (color(i,j) == 0.0 .and. color(i,j+1) > 0.0)
then
4319 color(i,j) = color(i,j+1)
4324 do j=g%jed-1,g%jsd+1,-1
4325 do i=g%ied-1,g%isd+1,-1
4326 if (color(i,j) == 0.0 .and. color(i-1,j) > 0.0)
then
4327 color(i,j) = color(i-1,j)
4330 if (color(i,j) == 0.0 .and. color(i+1,j) > 0.0)
then
4331 color(i,j) = color(i+1,j)
4334 if (color(i,j) == 0.0 .and. color(i,j-1) > 0.0)
then
4335 color(i,j) = color(i,j-1)
4338 if (color(i,j) == 0.0 .and. color(i,j+1) > 0.0)
then
4339 color(i,j) = color(i,j+1)
4344 call pass_var(color, g%Domain)
4345 call sum_across_pes(ncount)
4351 subroutine flood_fill2(G, color, cin, cout, cland)
4352 type(dyn_horgrid_type),
intent(inout) :: G
4353 real,
dimension(:,:),
intent(inout) :: color
4354 integer,
intent(in) :: cin
4355 integer,
intent(in) :: cout
4356 integer,
intent(in) :: cland
4359 integer :: i, j, ncount
4362 do while (ncount > 0)
4364 do i=g%isd+1,g%ied-1
4365 do j=g%jsd+1,g%jed-1
4366 if (color(i,j) == 0.0 .and. color(i-1,j) > 0.0)
then
4367 color(i,j) = color(i-1,j)
4370 if (color(i,j) == 0.0 .and. color(i+1,j) > 0.0)
then
4371 color(i,j) = color(i+1,j)
4374 if (color(i,j) == 0.0 .and. color(i,j-1) > 0.0)
then
4375 color(i,j) = color(i,j-1)
4378 if (color(i,j) == 0.0 .and. color(i,j+1) > 0.0)
then
4379 color(i,j) = color(i,j+1)
4384 do i=g%ied-1,g%isd+1,-1
4385 do j=g%jed-1,g%jsd+1,-1
4386 if (color(i,j) == 0.0 .and. color(i-1,j) > 0.0)
then
4387 color(i,j) = color(i-1,j)
4390 if (color(i,j) == 0.0 .and. color(i+1,j) > 0.0)
then
4391 color(i,j) = color(i+1,j)
4394 if (color(i,j) == 0.0 .and. color(i,j-1) > 0.0)
then
4395 color(i,j) = color(i,j-1)
4398 if (color(i,j) == 0.0 .and. color(i,j+1) > 0.0)
then
4399 color(i,j) = color(i,j+1)
4404 call pass_var(color, g%Domain)
4405 call sum_across_pes(ncount)
4413 type(hor_index_type),
intent(in) :: hi
4414 type(verticalgrid_type),
pointer :: gv
4416 type(tracer_registry_type),
pointer :: reg
4417 type(param_file_type),
intent(in) :: param_file
4418 type(mom_restart_cs),
pointer :: restart_csp
4419 logical,
intent(in) :: use_temperature
4423 character(len=100) :: mesg
4426 if (.not.
associated(obc)) &
4427 call mom_error(fatal,
"open_boundary_register_restarts: Called with "//&
4428 "uninitialized OBC control structure")
4430 if (
associated(obc%rx_normal) .or.
associated(obc%ry_normal) .or. &
4431 associated(obc%rx_oblique) .or.
associated(obc%ry_oblique) .or.
associated(obc%cff_normal)) &
4432 call mom_error(fatal,
"open_boundary_register_restarts: Restart "//&
4433 "arrays were previously allocated")
4435 if (
associated(obc%tres_x) .or.
associated(obc%tres_y)) &
4436 call mom_error(fatal,
"open_boundary_register_restarts: Restart "//&
4437 "arrays were previously allocated")
4443 if (obc%radiation_BCs_exist_globally)
then
4444 allocate(obc%rx_normal(hi%isdB:hi%iedB,hi%jsd:hi%jed,gv%ke))
4445 obc%rx_normal(:,:,:) = 0.0
4446 vd = var_desc(
"rx_normal",
"m s-1",
"Normal Phase Speed for EW radiation OBCs",
'u',
'L')
4447 call register_restart_field(obc%rx_normal, vd, .false., restart_csp)
4448 allocate(obc%ry_normal(hi%isd:hi%ied,hi%jsdB:hi%jedB,gv%ke))
4449 obc%ry_normal(:,:,:) = 0.0
4450 vd = var_desc(
"ry_normal",
"m s-1",
"Normal Phase Speed for NS radiation OBCs",
'v',
'L')
4451 call register_restart_field(obc%ry_normal, vd, .false., restart_csp)
4453 if (obc%oblique_BCs_exist_globally)
then
4454 allocate(obc%rx_oblique(hi%isdB:hi%iedB,hi%jsd:hi%jed,gv%ke))
4455 obc%rx_oblique(:,:,:) = 0.0
4456 vd = var_desc(
"rx_oblique",
"m2 s-2",
"Radiation Speed Squared for EW oblique OBCs",
'u',
'L')
4457 call register_restart_field(obc%rx_oblique, vd, .false., restart_csp)
4458 allocate(obc%ry_oblique(hi%isd:hi%ied,hi%jsdB:hi%jedB,gv%ke))
4459 obc%ry_oblique(:,:,:) = 0.0
4460 vd = var_desc(
"ry_oblique",
"m2 s-2",
"Radiation Speed Squared for NS oblique OBCs",
'v',
'L')
4461 call register_restart_field(obc%ry_oblique, vd, .false., restart_csp)
4462 allocate(obc%cff_normal(hi%IsdB:hi%IedB,hi%jsdB:hi%jedB,gv%ke))
4463 obc%cff_normal(:,:,:) = 0.0
4464 vd = var_desc(
"cff_normal",
"m2 s-2",
"denominator for oblique OBCs",
'q',
'L')
4465 call register_restart_field(obc%cff_normal, vd, .false., restart_csp)
4468 if (reg%ntr == 0)
return
4469 if (.not.
associated(obc%tracer_x_reservoirs_used))
then
4471 allocate(obc%tracer_x_reservoirs_used(reg%ntr))
4472 allocate(obc%tracer_y_reservoirs_used(reg%ntr))
4473 obc%tracer_x_reservoirs_used(:) = .false.
4474 obc%tracer_y_reservoirs_used(:) = .false.
4478 if (obc%ntr /= reg%ntr)
then
4480 write(mesg,
'("Inconsistent values for ntr ", I8," and ",I8,".")') obc%ntr, reg%ntr
4481 call mom_error(warning,
'open_boundary_register_restarts: '//mesg)
4486 if (any(obc%tracer_x_reservoirs_used))
then
4487 allocate(obc%tres_x(hi%isdB:hi%iedB,hi%jsd:hi%jed,gv%ke,obc%ntr))
4488 obc%tres_x(:,:,:,:) = 0.0
4490 if (obc%tracer_x_reservoirs_used(m))
then
4491 write(mesg,
'("tres_x_",I3.3)') m
4492 vd = var_desc(mesg,
"Conc",
"Tracer concentration for EW OBCs",
'u',
'L')
4493 call register_restart_field(obc%tres_x(:,:,:,m), vd, .false., restart_csp)
4497 if (any(obc%tracer_y_reservoirs_used))
then
4498 allocate(obc%tres_y(hi%isd:hi%ied,hi%jsdB:hi%jedB,gv%ke,obc%ntr))
4499 obc%tres_y(:,:,:,:) = 0.0
4501 if (obc%tracer_y_reservoirs_used(m))
then
4502 write(mesg,
'("tres_y_",I3.3)') m
4503 vd = var_desc(mesg,
"Conc",
"Tracer concentration for NS OBCs",
'v',
'L')
4504 call register_restart_field(obc%tres_y(:,:,:,m), vd, .false., restart_csp)
4513 type(ocean_grid_type),
intent(in) :: g
4514 type(verticalgrid_type),
intent(in) :: gv
4515 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: uhr
4517 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: vhr
4519 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
4522 real,
intent(in) :: dt
4523 type(tracer_registry_type),
pointer :: reg
4526 real :: u_l_in, u_l_out
4527 real :: v_l_in, v_l_out
4529 integer :: i, j, k, m, n, ntr, nz
4530 integer :: ishift, idir, jshift, jdir
4534 if (
associated(obc))
then ;
if (obc%OBC_pe)
then ;
do n=1,obc%number_of_segments
4535 segment=>obc%segment(n)
4536 if (.not.
associated(segment%tr_Reg)) cycle
4537 if (segment%is_E_or_W)
then
4538 do j=segment%HI%jsd,segment%HI%jed
4543 ishift = 1 ; idir = -1
4545 ishift = 0 ; idir = 1
4548 do m=1,ntr ;
if (
associated(segment%tr_Reg%Tr(m)%tres))
then ;
do k=1,nz
4549 u_l_out = max(0.0, (idir*uhr(i,j,k))*segment%Tr_InvLscale_out / (h(i+ishift,j,k)*g%dyCu(i,j)))
4550 u_l_in = min(0.0, (idir*uhr(i,j,k))*segment%Tr_InvLscale_in / (h(i+ishift,j,k)*g%dyCu(i,j)))
4551 fac1 = 1.0 + (u_l_out-u_l_in)
4552 segment%tr_Reg%Tr(m)%tres(i,j,k) = (1.0/fac1)*(segment%tr_Reg%Tr(m)%tres(i,j,k) + &
4553 (u_l_out*reg%Tr(m)%t(i+ishift,j,k) - &
4554 u_l_in*segment%tr_Reg%Tr(m)%t(i,j,k)))
4555 if (
associated(obc%tres_x)) obc%tres_x(i,j,k,m) = segment%tr_Reg%Tr(m)%tres(i,j,k)
4556 enddo ;
endif ;
enddo
4559 do i=segment%HI%isd,segment%HI%ied
4564 jshift = 1 ; jdir = -1
4566 jshift = 0 ; jdir = 1
4569 do m=1,ntr ;
if (
associated(segment%tr_Reg%Tr(m)%tres))
then ;
do k=1,nz
4570 v_l_out = max(0.0, (jdir*vhr(i,j,k))*segment%Tr_InvLscale_out / (h(i,j+jshift,k)*g%dxCv(i,j)))
4571 v_l_in = min(0.0, (jdir*vhr(i,j,k))*segment%Tr_InvLscale_in / (h(i,j+jshift,k)*g%dxCv(i,j)))
4572 fac1 = 1.0 + (v_l_out-v_l_in)
4573 segment%tr_Reg%Tr(m)%tres(i,j,k) = (1.0/fac1)*(segment%tr_Reg%Tr(m)%tres(i,j,k) + &
4574 (v_l_out*reg%Tr(m)%t(i,j+jshift,k) - &
4575 v_l_in*segment%tr_Reg%Tr(m)%t(i,j,k)))
4576 if (
associated(obc%tres_y)) obc%tres_y(i,j,k,m) = segment%tr_Reg%Tr(m)%tres(i,j,k)
4577 enddo ;
endif ;
enddo
4580 enddo ;
endif ;
endif
4593 type(ocean_grid_type),
intent(in) :: G
4594 type(verticalgrid_type),
intent(in) :: GV
4595 type(unit_scale_type),
intent(in) :: US
4597 integer,
intent(in) :: fld
4599 integer :: i, j, k, is, ie, js, je, nz, contractions, dilations
4601 real,
allocatable,
dimension(:,:,:) :: eta
4602 real :: hTolerance = 0.1
4603 real :: hTmp, eTmp, dilate
4604 character(len=100) :: mesg
4606 htolerance = 0.1*us%m_to_Z
4608 nz =
size(segment%field(fld)%dz_src,3)
4610 if (segment%is_E_or_W)
then
4612 is = segment%HI%isdB ; ie = segment%HI%iedB
4613 js = segment%HI%jsd ; je = segment%HI%jed
4615 is = segment%HI%isd ; ie = segment%HI%ied
4616 js = segment%HI%jsdB ; je = segment%HI%jedB
4618 allocate(eta(is:ie,js:je,nz+1))
4619 contractions=0; dilations=0
4620 do j=js,je ;
do i=is,ie
4628 eta(i,j,k)=eta(i,j,k-1)-segment%field(fld)%dz_src(i,j,k-1)
4633 if (-eta(i,j,k) > segment%Htot(i,j) + htolerance)
then
4634 eta(i,j,k) = -segment%Htot(i,j)
4635 contractions = contractions + 1
4642 if (eta(i,j,k) < (eta(i,j,k+1) + gv%Angstrom_Z))
then
4643 eta(i,j,k) = eta(i,j,k+1) + gv%Angstrom_Z
4644 segment%field(fld)%dz_src(i,j,k) = gv%Angstrom_Z
4646 segment%field(fld)%dz_src(i,j,k) = (eta(i,j,k) - eta(i,j,k+1))
4652 if (-eta(i,j,nz+1) < segment%Htot(i,j) - htolerance)
then
4653 dilations = dilations + 1
4655 eta(i,j,nz+1) = -segment%Htot(i,j)
4656 segment%field(fld)%dz_src(i,j,nz)= eta(i,j,nz)-eta(i,j,nz+1)
4667 segment%field(fld)%dz_src(i,j,k) = segment%field(fld)%dz_src(i,j,k)*gv%Z_to_H