@@ -1182,16 +1182,33 @@ end function Adcroft_reciprocal
1182
1182
! ! flow over any points which are shallower than Dmask and permit an
1183
1183
! ! appropriate treatment of the boundary conditions. mask2dCu and mask2dCv
1184
1184
! ! are 0.0 at any points adjacent to a land point. mask2dBu is 0.0 at
1185
- ! ! any land or boundary point. For points in the interior, mask2dCu,
1186
- ! ! mask2dCv, and mask2dBu are all 1.0.
1187
- subroutine initialize_masks (G , PF , US )
1185
+ ! ! any land or boundary point. For points in the ocean interior or at open boundary
1186
+ ! ! condition points, mask2dCu, mask2dCv, and mask2dBu are all 1.0.
1187
+ subroutine initialize_masks (G , PF , US , OBC_dir_u , OBC_dir_v , open_corner_OBCs )
1188
1188
type (dyn_horgrid_type), intent (inout ) :: G ! < The dynamic horizontal grid type
1189
1189
type (param_file_type), intent (in ) :: PF ! < Parameter file structure
1190
1190
type (unit_scale_type), intent (in ) :: US ! < A dimensional unit scaling type
1191
+ integer , dimension (G% IsdB:G% IedB,G% jsd:G% jed), &
1192
+ optional , intent (in ) :: OBC_dir_u ! < Trinary values that indicate whether there
1193
+ ! ! is an open boundary condition at zonal velocity
1194
+ ! ! faces and their orientation, with 0 for no OBC,
1195
+ ! ! a positive value for an Eastern OBC and
1196
+ ! ! a negative value for a Western OBC.
1197
+ integer , dimension (G% isd:G% ied,G% JsdB:G% JedB), &
1198
+ optional , intent (in ) :: OBC_dir_v ! < Trinary values that indicate whether there
1199
+ ! ! is an open boundary condition at zonal velocity
1200
+ ! ! faces and their orientation, with 0 for no OBC,
1201
+ ! ! a positive value for a Northern OBC and
1202
+ ! ! a negative value for a Southern OBC.
1203
+ logical , optional , intent (in ) :: open_corner_OBCs ! < If present and true, the bay-like corner
1204
+ ! ! between two orthogonal open boundary segments is open,
1205
+ ! ! otherwise it is closed.
1206
+
1191
1207
! Local variables
1192
1208
real :: Dmask ! The depth for masking in the same units as G%bathyT [Z ~> m].
1193
1209
real :: min_depth ! The minimum ocean depth in the same units as G%bathyT [Z ~> m].
1194
1210
real :: mask_depth ! The depth shallower than which to mask a point as land [Z ~> m].
1211
+ logical :: open_corners ! If true, the bay-like corner between two orthogonal open boundary segments is open
1195
1212
character (len= 40 ) :: mdl = " MOM_grid_init initialize_masks"
1196
1213
integer :: i, j
1197
1214
@@ -1212,6 +1229,8 @@ subroutine initialize_masks(G, PF, US)
1212
1229
Dmask = mask_depth
1213
1230
if (mask_depth == - 9999.0 * US% m_to_Z) Dmask = min_depth
1214
1231
1232
+ open_corners = .false. ; if (present (open_corner_OBCs)) open_corners = open_corner_OBCs
1233
+
1215
1234
G% mask2dCu(:,:) = 0.0 ; G% mask2dCv(:,:) = 0.0 ; G% mask2dBu(:,:) = 0.0
1216
1235
1217
1236
! Construct the h-point or T-point mask
@@ -1229,6 +1248,20 @@ subroutine initialize_masks(G, PF, US)
1229
1248
else
1230
1249
G% mask2dCu(I,j) = 1.0
1231
1250
endif
1251
+ enddo ; enddo
1252
+
1253
+ if (present (OBC_dir_u)) then
1254
+ do j= G% jsd,G% jed ; do I= G% isd,G% ied-1
1255
+ if (OBC_dir_u(I,j) > 0 ) then
1256
+ if (G% bathyT(i,j) > Dmask) G% mask2dCu(I,j) = 1.0
1257
+ endif
1258
+ if (OBC_dir_u(I,j) < 0 ) then
1259
+ if (G% bathyT(i+1 ,j) > Dmask) G% mask2dCu(I,j) = 1.0
1260
+ endif
1261
+ enddo ; enddo
1262
+ endif
1263
+
1264
+ do j= G% jsd,G% jed ; do I= G% isd,G% ied-1
1232
1265
! This mask may be revised later after the open boundary positions are specified.
1233
1266
G% OBCmaskCu(I,j) = G% mask2dCu(I,j)
1234
1267
enddo ; enddo
@@ -1239,19 +1272,60 @@ subroutine initialize_masks(G, PF, US)
1239
1272
else
1240
1273
G% mask2dCv(i,J) = 1.0
1241
1274
endif
1275
+ enddo ; enddo
1276
+
1277
+ if (present (OBC_dir_v)) then
1278
+ do J= G% jsd,G% jed-1 ; do i= G% isd,G% ied
1279
+ if (OBC_dir_v(i,J) > 0 ) then
1280
+ if (G% bathyT(i,j) > Dmask) G% mask2dCv(i,J) = 1.0
1281
+ endif
1282
+ if (OBC_dir_v(i,J) < 0 ) then
1283
+ if (G% bathyT(i,j+1 ) > Dmask) G% mask2dCv(i,J) = 1.0
1284
+ endif
1285
+ enddo ; enddo
1286
+ endif
1287
+
1288
+ do J= G% jsd,G% jed-1 ; do i= G% isd,G% ied
1242
1289
! This mask may be revised later after the open boundary positions are specified.
1243
1290
G% OBCmaskCv(i,J) = G% mask2dCv(i,J)
1244
1291
enddo ; enddo
1245
1292
1293
+ ! The mask at the vertex can be determined from the masks at the faces.
1294
+ ! This works at interior ocean points or at convex OBC points.
1246
1295
do J= G% jsd,G% jed-1 ; do I= G% isd,G% ied-1
1247
- if ((G% bathyT(i+1 ,j) <= Dmask) .or. (G% bathyT(i+1 ,j+1 ) <= Dmask) .or. &
1248
- (G% bathyT(i,j) <= Dmask) .or. (G% bathyT(i,j+1 ) <= Dmask)) then
1249
- G% mask2dBu(I,J) = 0.0
1250
- else
1251
- G% mask2dBu(I,J) = 1.0
1252
- endif
1296
+ G% mask2dBu(I,J) = (G% mask2dCu(I,j) * G% mask2dCu(I,j+1 )) * (G% mask2dCv(i,J) * G% mask2dCv(i+1 ,J))
1253
1297
enddo ; enddo
1254
1298
1299
+ ! This block resets masks at the vertices when there are OBCs. The right logic is that if there
1300
+ ! are 2 or more unmasked OBCs, this point should be open, but to recreate the previous answers,
1301
+ if (present (OBC_dir_u)) then
1302
+ do J= G% jsd,G% jed-1 ; do I= G% isd,G% ied-1
1303
+ ! These are conditions to set open vertex points on a straight north-south coastline
1304
+ if ((G% mask2dCu(I,j) * OBC_dir_u(I,j)) * (G% mask2dCu(I,j+1 ) * OBC_dir_u(I,j+1 )) > 0 .) &
1305
+ G% mask2dBu(I,J) = 1.0
1306
+ enddo ; enddo
1307
+ endif
1308
+ if (present (OBC_dir_v)) then
1309
+ do J= G% jsd,G% jed-1 ; do I= G% isd,G% ied-1
1310
+ ! These are conditions to set open vertex points on a straight east-west coastline
1311
+ if ((G% mask2dCv(i,J) * OBC_dir_v(i,J)) * (G% mask2dCv(i+1 ,J) * OBC_dir_v(i+1 ,J)) > 0 .) &
1312
+ G% mask2dBu(I,J) = 1.0
1313
+ enddo ; enddo
1314
+ endif
1315
+ if (open_corners .and. present (OBC_dir_u) .and. present (OBC_dir_v)) then
1316
+ do J= G% jsd,G% jed-1 ; do I= G% isd,G% ied-1
1317
+ ! These are the 4 conditions to set an open point in a concave (bay-like) corner
1318
+ if ((G% mask2dCu(I,j+1 ) * OBC_dir_u(I,j+1 ) < 0 .) .and. (G% mask2dCv(i+1 ,J) * OBC_dir_v(i+1 ,J) < 0 .)) &
1319
+ G% mask2dBu(I,J) = 1.0 ! Southwestern corner
1320
+ if ((G% mask2dCu(I,j+1 ) * OBC_dir_u(I,j+1 ) > 0 .) .and. (G% mask2dCv(i,J) * OBC_dir_v(i,J) < 0 .)) &
1321
+ G% mask2dBu(I,J) = 1.0 ! Southeastern corner
1322
+ if ((G% mask2dCu(I,j) * OBC_dir_u(I,j) < 0 .) .and. (G% mask2dCv(i+1 ,J) * OBC_dir_v(i+1 ,J) > 0 .)) &
1323
+ G% mask2dBu(I,J) = 1.0 ! Northwestern corner
1324
+ if ((G% mask2dCu(I,j) * OBC_dir_u(I,j) > 0 .) .and. (G% mask2dCv(i,J) * OBC_dir_v(i,J) > 0 .)) &
1325
+ G% mask2dBu(I,J) = 1.0 ! Northeastern corner
1326
+ enddo ; enddo
1327
+ endif
1328
+
1255
1329
call pass_var(G% mask2dBu, G% Domain, position= CORNER)
1256
1330
call pass_vector(G% mask2dCu, G% mask2dCv, G% Domain, To_All+ Scalar_Pair, CGRID_NE)
1257
1331
0 commit comments