diff --git a/components/mpas-framework/src/operators/mpas_vector_operations.F b/components/mpas-framework/src/operators/mpas_vector_operations.F index 64c848944183..108b28786e29 100644 --- a/components/mpas-framework/src/operators/mpas_vector_operations.F +++ b/components/mpas-framework/src/operators/mpas_vector_operations.F @@ -46,6 +46,8 @@ module mpas_vector_operations mpas_cross_product_in_r3, & mpas_tangential_velocity, & mpas_tangential_vector_1d, & + mpas_vector_cell_to_edge_anisotropic, & + mpas_vector_cell_to_edge_isotropic, & mpas_vector_R3Cell_to_2DEdge, & mpas_vector_R3Cell_to_normalVectorEdge, & mpas_vector_R3_to_LonLatR, & @@ -288,6 +290,187 @@ subroutine mpas_vector_R3Cell_to_normalVectorEdge(vectorR3Cell, & end subroutine mpas_vector_R3Cell_to_normalVectorEdge!}}} + + +!*********************************************************************** +! +! routine mpas_vector_cell_to_edge_anisotropic +! +!> \brief Interpolate a 2d vector field from cell centers to edges +!> \author Xylar Asay-Davis +!> \date May 2024 +!> \details +!> This subroutine interpolates a 2D vector field on the sphere to edges +!> using an anisotropic approach that only uses the 2 closest cell centers +! +!----------------------------------------------------------------------- + + subroutine mpas_vector_cell_to_edge_anisotropic(zonalCell, meridionalCell, & + nEdges, cellsOnEdge, zonalEdge, meridionalEdge)!{{{ + + !----------------------------------------------------------------- + ! + ! input variables + ! + !----------------------------------------------------------------- + + real (kind=RKIND), dimension(:), intent(in) :: & + zonalCell, & !< Input: zonal component of the vector at cell centers + meridionalCell !< Input: meridional component of the vector at cell centers + + integer, intent(in) :: & + nEdges !< Input: The number of edges (level of halo) to include in the computation + + integer, dimension(:,:), intent(in) :: & + cellsOnEdge !< Input: cells adjacent to each mesh edge + + !----------------------------------------------------------------- + ! + ! output variables + ! + !----------------------------------------------------------------- + + real (kind=RKIND), dimension(:), intent(out) :: & + zonalEdge, & !< Input: zonal component of the vector at cell centers + meridionalEdge !< Input: meridional component of the vector at cell centers + + !----------------------------------------------------------------- + ! + ! local variables + ! + !----------------------------------------------------------------- + + integer :: iEdge, cell1, cell2 + +#ifdef MPAS_OPENACC + !$acc parallel loop & + !$acc present(cellsOnEdge, zonalCell, meridionalCell, & + !$acc zonalEdge, meridionalEdge) & + !$acc private(cell1, cell2) +#else + !$omp parallel + !$omp do schedule(runtime) & + !$omp private(cell1, cell2) +#endif + do iEdge = 1, nEdges + cell1 = cellsOnEdge(1, iEdge) + cell2 = cellsOnEdge(2, iEdge) + + zonalEdge(iEdge) = 0.5_RKIND * (zonalCell(cell1) + & + zonalCell(cell2)) + meridionalEdge(iEdge) = 0.5_RKIND * (meridionalCell(cell1) + & + meridionalCell(cell2)) + end do +#ifndef MPAS_OPENACC + !$omp end do + !$omp end parallel +#endif + + end subroutine mpas_vector_cell_to_edge_anisotropic!}}} + + + +!*********************************************************************** +! +! routine mpas_vector_cell_to_edge_isotropic +! +!> \brief Interpolate a 2d vector field from cell centers to edges +!> \author Xylar Asay-Davis +!> \date May 2024 +!> \details +!> This subroutine interpolates a 2D vector field on the sphere to edges +!> using an isotropic approach that uses 4 adjacent cell centers +! +!----------------------------------------------------------------------- + + subroutine mpas_vector_cell_to_edge_isotropic(zonalCell, meridionalCell, & + nEdges, vertexDegree, verticesOnEdge, cellsOnVertex, kiteAreasOnVertex, & + zonalEdge, meridionalEdge)!{{{ + + !----------------------------------------------------------------- + ! + ! input variables + ! + !----------------------------------------------------------------- + + real (kind=RKIND), dimension(:), intent(in) :: & + zonalCell, & !< Input: zonal component of the vector at cell centers + meridionalCell !< Input: meridional component of the vector at cell centers + + integer, intent(in) :: & + nEdges, & !< Input: The number of edges (level of halo) to include in the computation + vertexDegree !< Input: The number of edges and cells adjacent to each vertex + + integer, dimension(:,:), intent(in) :: & + verticesOnEdge, & !< Input: vertices adjacent to each mesh edge + cellsOnVertex !< Input: cells adjacent to each mesh vertex + + real (kind=RKIND), dimension(:, :), intent(in) :: & + kiteAreasOnVertex !< Input: The area of elements bounded by a cell, a vertex and + !< the centers of the two edges they share + + !----------------------------------------------------------------- + ! + ! output variables + ! + !----------------------------------------------------------------- + + real (kind=RKIND), dimension(:), intent(out) :: & + zonalEdge, & !< Input: zonal component of the vector at cell centers + meridionalEdge !< Input: meridional component of the vector at cell centers + + !----------------------------------------------------------------- + ! + ! local variables + ! + !----------------------------------------------------------------- + + integer :: iEdge, iVert, iCell, v, c + + real (kind=RKIND) :: area, areaSum, zonal, meridional + +#ifdef MPAS_OPENACC + !$acc parallel loop gang vector & + !$acc present(verticesOnEdge, cellsOnVertex, kiteAreasOnVertex, & + !$acc zonalCell, meridionalCell, & + !$acc zonalEdge, meridionalEdge) & + !$acc private(areaSum, area, v, c, iVert, iCell) +#else + !$omp parallel + !$omp do schedule(runtime) & + !$omp private(areaSum, area, v, c, iVert, iCell) +#endif + do iEdge = 1, nEdges + zonalEdge(iEdge) = 0.0_RKIND + meridionalEdge(iEdge) = 0.0_RKIND + areaSum = 0.0_RKIND + do v = 1, 2 + iVert = verticesOnEdge(v, iEdge) + do c = 1, vertexDegree + iCell = cellsOnVertex(c, iVert) + ! kite areas are zero for invalid cells on vertex + area = kiteAreasOnVertex(c, iVert) + + zonalEdge(iEdge) = zonalEdge(iEdge) & + + zonalCell(iCell) * area + meridionalEdge(iEdge) = meridionalEdge(iEdge) & + + meridionalCell(iCell) * area + + areaSum = areaSum + area + end do + end do + zonalEdge(iEdge) = zonalEdge(iEdge) / areaSum + meridionalEdge(iEdge) = meridionalEdge(iEdge) / areaSum + end do +#ifndef MPAS_OPENACC + !$omp end do + !$omp end parallel +#endif + + end subroutine mpas_vector_cell_to_edge_isotropic!}}} + + + !*********************************************************************** ! ! routine mpas_tangential_velocity diff --git a/components/mpas-ocean/bld/build-namelist b/components/mpas-ocean/bld/build-namelist index 0b8d3c782fa7..54bc9d586d87 100755 --- a/components/mpas-ocean/bld/build-namelist +++ b/components/mpas-ocean/bld/build-namelist @@ -690,6 +690,7 @@ add_default($nl, 'config_gotm_constant_bottom_drag_coeff'); add_default($nl, 'config_use_variable_drag'); add_default($nl, 'config_use_bulk_wind_stress'); +add_default($nl, 'config_bulk_wind_stress_interp_isotropic'); add_default($nl, 'config_use_bulk_thickness_flux'); add_default($nl, 'config_flux_attenuation_coefficient'); add_default($nl, 'config_flux_attenuation_coefficient_runoff'); diff --git a/components/mpas-ocean/bld/build-namelist-section b/components/mpas-ocean/bld/build-namelist-section index 28030392442d..f2935c7c25c7 100644 --- a/components/mpas-ocean/bld/build-namelist-section +++ b/components/mpas-ocean/bld/build-namelist-section @@ -219,6 +219,7 @@ add_default($nl, 'config_gotm_constant_bottom_drag_coeff'); add_default($nl, 'config_use_variable_drag'); add_default($nl, 'config_use_bulk_wind_stress'); +add_default($nl, 'config_bulk_wind_stress_interp_isotropic'); add_default($nl, 'config_use_bulk_thickness_flux'); add_default($nl, 'config_flux_attenuation_coefficient'); add_default($nl, 'config_flux_attenuation_coefficient_runoff'); diff --git a/components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml b/components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml index 4069eb144cff..5596662aa469 100644 --- a/components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml +++ b/components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml @@ -284,6 +284,7 @@ .false. .true. +.false. .true. 0.001 10.0 diff --git a/components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml b/components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml index 01456cd6583a..f4147c7e281c 100644 --- a/components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml +++ b/components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml @@ -1148,6 +1148,14 @@ Valid values: .true. or .false. Default: Defined in namelist_defaults.xml + +Controls if windstress is interpolated to edges from 4 adjacent cells rather than just 2. + +Valid values: .true. or .false. +Default: Defined in namelist_defaults.xml + + Controls if a bulk thickness flux will be computed for surface forcing. @@ -1188,7 +1196,7 @@ Default: Defined in namelist_defaults.xml -Name of shortwave absorption type used in simulation. +Name of shortwave absorption type used in simulation. Valid values: 'jerlov' or 'ohlmann00' or 'none' Default: Defined in namelist_defaults.xml diff --git a/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/isotropic_wind_stress/README b/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/isotropic_wind_stress/README new file mode 100644 index 000000000000..a2889bc0afc2 --- /dev/null +++ b/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/isotropic_wind_stress/README @@ -0,0 +1,4 @@ +This testdef is used to test a stealth feature in mpaso introduced by +PR #XXXX. It simplies changes one mpaso namelist variable, + config_bulk_wind_stress_interp_isotropic +from its default value of false to true. diff --git a/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/isotropic_wind_stress/user_nl_mpaso b/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/isotropic_wind_stress/user_nl_mpaso new file mode 100644 index 000000000000..2780fe82a5a5 --- /dev/null +++ b/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/isotropic_wind_stress/user_nl_mpaso @@ -0,0 +1 @@ + config_bulk_wind_stress_interp_isotropic = .true. diff --git a/components/mpas-ocean/src/Registry.xml b/components/mpas-ocean/src/Registry.xml index f8b56c083d44..d198ea033bb0 100644 --- a/components/mpas-ocean/src/Registry.xml +++ b/components/mpas-ocean/src/Registry.xml @@ -679,6 +679,10 @@ description="Controls if zonal and meridional components of windstress are used to build surface wind stress." possible_values=".true. or .false." /> +