From f79616fa61a4db348ddddfc8e9f1b36250c36f94 Mon Sep 17 00:00:00 2001
From: Lionel GUEZ <guez@lmd.ipsl.fr>
Date: Fri, 5 Jul 2024 17:32:19 +0200
Subject: [PATCH] Redefine `outside_points` in projection space

In main program units `inst_eddies`, `examine_eddy` and
`test_get_1_outerm`, redefine `outside_points` as coordinates in
projection space, avoiding a round trip to longitude and latitude. In
`examine_eddy`, we therefore store `coord_proj` instead of coord.
---
 .../Tests/Input/Region_1/outside_points.csv   | 13 ++--
 Inst_eddies/Tests/examine_eddy.f90            | 61 +++++++++----------
 Inst_eddies/Tests/test_get_1_outerm.f90       | 18 +++---
 Inst_eddies/inst_eddies.f90                   | 30 ++++-----
 Inst_eddies/set_contours.f90                  |  6 +-
 5 files changed, 57 insertions(+), 71 deletions(-)

diff --git a/Inst_eddies/Tests/Input/Region_1/outside_points.csv b/Inst_eddies/Tests/Input/Region_1/outside_points.csv
index 6b40dd18..752a7b9f 100644
--- a/Inst_eddies/Tests/Input/Region_1/outside_points.csv
+++ b/Inst_eddies/Tests/Input/Region_1/outside_points.csv
@@ -1,7 +1,6 @@
-"degrees east" "degrees north"
-"longitude" "latitude"
-8.375 -36.125
-6.125 -35.375
-8.125 -34.625
-10.875 -34.625
-5.875 -33.125
+ x y
+          13           8
+          24           8
+           4          14
+          14           2
+           5           5
diff --git a/Inst_eddies/Tests/examine_eddy.f90 b/Inst_eddies/Tests/examine_eddy.f90
index a1b56731..501f7049 100644
--- a/Inst_eddies/Tests/examine_eddy.f90
+++ b/Inst_eddies/Tests/examine_eddy.f90
@@ -20,15 +20,13 @@ program examine_eddy
   ! The main difficulty here was to get outside_points. We need in
   ! outside_points all the extrema of opposite sign (including those
   ! not associated to an eddy) plus the extrema of same sign
-  ! associated to an eddy. Note that coord and outside_points may not
-  ! be exactly equal to what they were in inst_eddies because there is
-  ! a multiplication of coord by rad_to_deg when writing the shapefile
-  ! and a multiplication by deg_to_rad when reading it.
+  ! associated to an eddy. Note that e%extr%coord may not be exactly
+  ! equal to what it was in inst_eddies because there is a
+  ! multiplication by rad_to_deg when writing the shapefile and a
+  ! multiplication by deg_to_rad when reading it.
 
   ! Libraries:
-  use contour_531, only: convert_to_ind
-  use jumble, only: get_command_arg_dyn, read_column, deg_to_rad, rad_to_deg, &
-       twopi, new_unit
+  use jumble, only: get_command_arg_dyn, read_column, deg_to_rad, new_unit
   use shapelib, only: shpfileobject, shpclose
   use shapelib_03, only: dbf_read_attribute_03, dbf_get_field_index_03, &
        shp_read_point, shp_open_03
@@ -47,7 +45,7 @@ program examine_eddy
   implicit none
 
   integer:: date = huge(0), eddy_i_target = huge(0)
-  integer ishape_first, d0, ishape, i, l, n1, n2, number_extr, unit
+  integer ishape_first, d0, ishape, i, l, n1, n2, number_extr, unit, nlon
   logical:: cyclone = .true. ! orientation of target eddy
   namelist /main_nml/ cyclone, date, eddy_i_target
   TYPE(shpfileobject) hshp
@@ -71,26 +69,24 @@ program examine_eddy
   ! (nlon, nlat). Wind, in m s-1.
 
   type(snapshot) s
+  real coord(2) ! longitude and latitude, in rad
 
-  real, allocatable:: coord(:, :)
-  ! (2, number_extr) longitude and latitude, in rad
+  integer, allocatable:: coord_proj(:, :)
+  ! (2, number_extr) coordinates in projection space
 
   integer, allocatable:: selection(:)
   ! identifying numbers of a selection of eddies
 
   logical, allocatable:: in_window(:)
 
-  real, allocatable:: outside_points(:, :) ! (2, :) longitude and
-  ! latitude, in rad, of all the significant extrema, except the
-  ! target extremum
+  integer, allocatable:: outside_points(:, :) ! (2, :)
+  ! coordinates in projection space of all the significant extrema,
+  ! except the target extremum
 
   TYPE(shpc_slice_handler) hshpc
   integer llc(2) ! indices in global grid of lower left corner
   integer urc(2) ! indices in global grid of upper right corner
 
-  real corner_window(2) ! longitude and latitude of the window around each
-  ! extremum, in rad
-
   !------------------------------------------------------------------------
 
   call config
@@ -122,15 +118,16 @@ program examine_eddy
   end if
 
   number_extr = ishape_last(date) - ishape_first + 1
-  allocate(coord(2, number_extr), in_window(number_extr))
+  allocate(coord_proj(2, number_extr), in_window(number_extr))
 
   do ishape = ishape_first, ishape_last(date)
-     call shp_read_point(coord(:, ishape - ishape_first + 1), hshp, ishape)
+     call shp_read_point(coord, hshp, ishape)
+     coord_proj(:, ishape - ishape_first + 1) = nint((coord * deg_to_rad &
+          - corner) / step + 1.)
   end do
 
-  coord = coord * deg_to_rad
-  e%extr%coord = coord(:, eddy_i_target)
-  e%extr%coord_proj = nint(convert_to_ind(e%extr%coord, corner, step))
+  e%extr%coord = (coord_proj(:, eddy_i_target) - 1) * step + corner
+  e%extr%coord_proj = coord_proj(:, eddy_i_target)
   call dbf_get_field_index_03(hshp, "ssh", ifield)
   call dbf_read_attribute_03(e%extr%ssh, hshp, ifield, &
        ishape = ishape_first + eddy_i_target - 1)
@@ -149,18 +146,18 @@ program examine_eddy
      urc(1) = min(urc(1), size(ssh, 1))
   end if
 
-  corner_window = corner + (llc - 1) * step
-
   ! Done defining geographical window
 
+  if (periodic) nlon = size(ssh, 1) - 2 * max_radius(1)
+
   do i = 1, number_extr
      if (i /= eddy_i_target) then
         ! Shift the longitude to a value close to the longitude of the
         ! target extremum:
-        if (periodic) coord(1, i) = coord(1, i) &
-             + ceiling((corner_window(1) - coord(1, i)) / twopi) * twopi
+        if (periodic) coord_proj(1, i) = coord_proj(1, i) &
+             + ceiling((llc(1) - coord_proj(1, i)) / real(nlon)) * nlon
 
-        in_window(i) = all(abs(nint((coord(:, i) - e%extr%coord) / step)) &
+        in_window(i) = all(abs(coord_proj(:, i) - e%extr%coord_proj) &
              < max_radius)
      else
         in_window(i) = .false.
@@ -174,12 +171,12 @@ program examine_eddy
   selection = pack(selection, s%list(selection)%cyclone .neqv. cyclone)
   n1 = size(selection)
   allocate(outside_points(2, n1 + n2))
-  forall (i = 1:n1) outside_points(:, i) = s%list(selection(i))%extr%coord
+  forall (i = 1:n1) outside_points(:, i) = s%list(selection(i))%extr%coord_proj
   l = n1 + 1
 
   do i = 1, number_extr
      if (in_window(i)) then
-        outside_points(:, l) = coord(:, i)
+        outside_points(:, l) = coord_proj(:, i)
         l = l + 1
      end if
   end do
@@ -190,7 +187,7 @@ program examine_eddy
   call set_contours(e%out_cont, e%speed_cont, e%max_speed, cyclone, e%extr, &
        e%innermost_level, step, ssh(llc(1):urc(1), llc(2):urc(2)), &
        u(llc(1):urc(1), llc(2):urc(2)), v(llc(1):urc(1), llc(2):urc(2)), llc, &
-       convert_to_ind(outside_points, corner, step))
+       outside_points)
   call close_cont_list
   call shpc_create(hshpc, shpc_dir = "SHPC", cyclone = cyclone, slice = 0, &
        grid_lon_lat = .true.)
@@ -199,7 +196,6 @@ program examine_eddy
   CALL shpc_close(hshpc)
   print *, "llc = ", llc
   print *, "urc = ", urc
-  print *, "corner_window (in degrees):", corner_window * rad_to_deg
   print *, "Number of extrema of opposite orientation which must be outside ", &
        "outermost contour:", n1
   print *, "Number of (valid) eddies of same orientation which must be ", &
@@ -207,11 +203,10 @@ program examine_eddy
 
   call new_unit(unit)
   open(unit, file = "outside_points.csv", status = "replace", action = "write")
-  write(unit, fmt = *) '"degrees east" "degrees north"'
-  write(unit, fmt = *) "longitude latitude"
+  write(unit, fmt = *) "x y"
 
   do i = 1, n1 + n2
-     write(unit, fmt = *) outside_points(:, i) * rad_to_deg
+     write(unit, fmt = *) outside_points(:, i)
   end do
 
   close(unit)
diff --git a/Inst_eddies/Tests/test_get_1_outerm.f90 b/Inst_eddies/Tests/test_get_1_outerm.f90
index 86b68a2c..201f50f6 100644
--- a/Inst_eddies/Tests/test_get_1_outerm.f90
+++ b/Inst_eddies/Tests/test_get_1_outerm.f90
@@ -6,8 +6,8 @@ program test_get_1_outerm
   ! cont_list and cont_list_proj.
 
   ! Libraries:
-  use contour_531, only: polyline, convert_to_ind
-  use jumble, only: csvread, deg_to_rad, rad_to_deg
+  use contour_531, only: polyline
+  use jumble, only: csvread, rad_to_deg
   use shapelib, only: shpfileobject, ftdouble, shpt_polygon, shpclose
   use shapelib_03, only: shp_create_03, dbf_add_field_03, &
        shp_append_object_03, dbf_write_attribute_03
@@ -47,9 +47,9 @@ program test_get_1_outerm
   TYPE(shpc_slice_handler) hshpc
   type(eddy) e
 
-  real, allocatable:: outside_points(:, :) ! (2, :) longitude and
-  ! latitude, in rad, of all the significant extrema, except the
-  ! target extremum
+  integer, allocatable:: outside_points(:, :) ! (2, :)
+  ! coordinates in projection space of all the significant extrema,
+  ! except the target extremum
 
   logical:: grid_lon_lat = .true.
   integer, parameter:: n_max_cont = 31
@@ -89,8 +89,8 @@ program test_get_1_outerm
   inquire(file = "outside_points.csv", exist = exist)
 
   if (exist) then
-     call csvread("outside_points.csv", outside_points, first_r = 3)
-     outside_points = transpose(outside_points) * deg_to_rad
+     call csvread("outside_points.csv", outside_points, first_r = 2)
+     outside_points = transpose(outside_points)
   else
      print *, '"outside_points.csv" not found. Assuming no outside points...'
      allocate(outside_points(2, 0))
@@ -99,8 +99,8 @@ program test_get_1_outerm
   e%extr%coord_proj = ind_targ_extr
   e%extr%coord = corner + (ind_targ_extr - 1) * step
   call get_1_outerm(e%out_cont, cont_list, cont_list_proj, n_cont, cyclone, &
-       real(ind_targ_extr), innermost_level, convert_to_ind(outside_points, &
-       corner, step), ssh, corner = [1., 1.], step = step)
+       real(ind_targ_extr), innermost_level, real(outside_points), ssh, &
+       corner = [1., 1.], step = step)
 
   if (e%out_cont%closed) then
      e%extr%ssh = ssh(ind_targ_extr(1), ind_targ_extr(2))
diff --git a/Inst_eddies/inst_eddies.f90 b/Inst_eddies/inst_eddies.f90
index cc173a18..cb146bee 100644
--- a/Inst_eddies/inst_eddies.f90
+++ b/Inst_eddies/inst_eddies.f90
@@ -7,13 +7,12 @@ program inst_eddies
   use, intrinsic:: ISO_FORTRAN_ENV, only: ERROR_UNIT
 
   ! Libraries:
-  use contour_531, only: convert_to_ind, convert_to_reg_coord
-  use jumble, only: assert, new_unit, argwhere, twopi
+  use jumble, only: assert, new_unit, argwhere
   use numer_rec_95, only: indexx
 
   use config_m, only: config
   use derived_types, only: snapshot, shpc_slice_handler
-  use input_ssh_m, only: input_ssh, max_radius, corner
+  use input_ssh_m, only: input_ssh, max_radius
   use nearby_extr_m, only: nearby_extr
   use set_all_extr_m, only: set_all_extr
   use set_contours_m, only: set_contours
@@ -59,12 +58,9 @@ program inst_eddies
   integer llc(2) ! indices in global grid of lower left corner
   integer urc(2) ! indices in global grid of upper right corner
 
-  real corner_window(2) ! longitude and latitude of the window around each
-  ! extremum, in rad
-
-  real, allocatable:: outside_points(:, :) ! (2, :) longitude and
-  ! latitude, in rad, of all the significant extrema, except the
-  ! target extremum
+  integer, allocatable:: outside_points(:, :) ! (2, :)
+  ! coordinates in projection space of all the significant extrema,
+  ! except the target extremum
 
   !--------------------------------------------------------------
 
@@ -137,7 +133,7 @@ program inst_eddies
 
   ! Done sorting
 
-  if (.not. periodic) nlon = size(ssh, 1)
+  nlon = size(ssh, 1) - 2 * merge(max_radius(1), 0, periodic)
   nlat = size(ssh, 2)
 
   do l = 1, s%number_extr
@@ -156,25 +152,21 @@ program inst_eddies
         urc(1) = min(urc(1), nlon)
      end if
 
-     corner_window = corner + (llc - 1) * step
-
      ! Done defining geographical window
 
      outside_points &
-          = convert_to_reg_coord(nearby_extr(s%extr_map(llc(1):urc(1), &
-          llc(2):urc(2)), s%list, i), corner, step)
+          = nearby_extr(s%extr_map(llc(1):urc(1), llc(2):urc(2)), s%list, i)
 
-     ! Shift the longitude of each point to a value close to the
-     ! longitude of the target extremum:
+     ! Shift the x coordinate of each point to a value close to the
+     ! coordinate of the target extremum:
      if (periodic) outside_points(1, :) = outside_points(1, :) &
-          + ceiling((corner_window(1) - outside_points(1, :)) / twopi) &
-          * twopi
+          + ceiling((llc(1) - outside_points(1, :)) / real(nlon)) * nlon
 
      call set_contours(s%list(i)%out_cont, s%list(i)%speed_cont, &
           s%list(i)%max_speed, s%list(i)%cyclone, s%list(i)%extr, &
           s%list(i)%innermost_level, step, ssh(llc(1):urc(1), llc(2):urc(2)), &
           u(llc(1):urc(1), llc(2):urc(2)), v(llc(1):urc(1), llc(2):urc(2)), &
-          llc, convert_to_ind(outside_points, corner, step))
+          llc, outside_points)
   end do
 
   call cpu_time(t1)
diff --git a/Inst_eddies/set_contours.f90 b/Inst_eddies/set_contours.f90
index 8b18750c..50b50746 100644
--- a/Inst_eddies/set_contours.f90
+++ b/Inst_eddies/set_contours.f90
@@ -46,7 +46,7 @@ contains
     ! corresponding to ssh(1, 1). A priori, this is not the corner of
     ! the grid of the NetCDF file.
 
-    real, intent(in):: outside_points_proj(:, :) ! (2, :)
+    integer, intent(in):: outside_points_proj(:, :) ! (2, :)
     ! coordinates in projection space of all the significant extrema,
     ! except the target extremum
 
@@ -94,8 +94,8 @@ contains
          innermost_level, abs(extr%ssh - innermost_level) < min_amp)
 
     call get_1_outerm(out_cont, cont_list, cont_list_proj, n_cont, cyclone, &
-         real(extr%coord_proj), innermost_level_2, outside_points_proj, ssh, &
-         real(corner), step)
+         real(extr%coord_proj), innermost_level_2, real(outside_points_proj), &
+         ssh, real(corner), step)
 
     ! Done with outermost contour, now let us take care of the
     ! max-speed contour.
-- 
GitLab