Skip to content
Snippets Groups Projects
inst_eddies.f90 6.40 KiB
program inst_eddies

  ! The current directory at run-time should contain directory SHPC.

  use, intrinsic:: ieee_arithmetic, only: IEEE_SUPPORT_DATATYPE, &
       ieee_support_nan
  use, intrinsic:: ISO_FORTRAN_ENV

  ! Libraries:
  use jumble, only: assert, new_unit, pi, argwhere, twopi
  use numer_rec_95, only: indexx

  use config_m, only: config, min_radius
  use derived_types, only: snapshot, shpc_slice_handler
  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
  use shpc_close_m, only: shpc_close
  use shpc_create_m, only: shpc_create
  use shpc_open_m, only: shpc_open
  use write_snapshot_m, only: write_snapshot

  implicit none

  type(snapshot) s
  TYPE(shpc_slice_handler) hshpc_cyclo, hshpc_anti
  integer iostat, i, l, nlon, nlat
  character(len = 200) iomsg
  integer unit

  real corner(2)
  ! longitude and latitude of the corner of the whole grid, in rad

  real step(2) ! longitude and latitude steps, in rad
  logical periodic ! grid is periodic in longitude

  real, allocatable:: ssh(:, :)
  ! (1 - max_radius(1):nlon + max_radius(1), nlat) if the grid is periodic
  ! in longitude, else (nlon, nlat). Sea-surface height, in m.

  real, allocatable:: u(:, :), v(:, :)
  ! (1 - max_radius(1):nlon + max_radius(1), nlat) if periodic, else
  ! (nlon, nlat) wind, in m s-1

  logical exist
  real t0, t1 ! CPU times, in s
  character(len = 30) timings_fname ! file name
  integer:: date = 0, slice = 0
  namelist /dates_nml/ date, slice

  integer, allocatable:: sorted_extr(:) ! (s%number_extr)
  ! Sorted identifying number of extrema: first, minima sorted in
  ! order of decreasing SSH, and second, maxima sorted in order of
  ! increasing SSH.

  real min_area ! minimum area of an outermost contour, in m2

  integer, allocatable:: selection(:)
  ! identifying numbers of a selection of extrema

  integer n_cycl ! number of cyclones
  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


  !--------------------------------------------------------------

  call assert(IEEE_SUPPORT_DATATYPE(0.), ieee_support_nan(0.), &
       "inst_eddies: not enough IEEE support")
  call cpu_time(t0)
  print *, "inst_eddies: Enter dates_nml:"
  read(unit = *, nml = dates_nml)
  write(timings_fname, fmt = '("SHPC/Slice_", i0, "/timings.txt")') slice
  inquire(file = timings_fname, exist = exist)
  call new_unit(unit)

  if (exist) then
     open(unit, file = timings_fname, STATUS = "old", ACTION = "WRITE", &
          position = "append")
  else
     OPEN(unit, file = timings_fname, STATUS = "new", ACTION = "WRITE", &
          iostat = iostat, iomsg = iomsg)

     if (iostat /= 0) then
        write(ERROR_UNIT, fmt = "(a, i0, a)") "Is the directory SHPC/Slice_", &
             slice, " created?"
        write(ERROR_UNIT, fmt = *) trim(iomsg)
        stop 1
     end if
  end if

  call config
  call input_ssh(corner, step, periodic, ssh, u, v)

  ! Open or create now so we test the existence of directories:
  call shpc_open(hshpc_cyclo, shpc_dir = "SHPC", cyclone = .true., &
       slice = slice, pszaccess = "rb+", iostat = iostat)

  if (iostat == 0) then
     call shpc_open(hshpc_anti, shpc_dir = "SHPC", cyclone = .false., &
          slice = slice, pszaccess = "rb+")
  else
     print *, "inst_eddies: Opening failed so we will create a slice..."
     call shpc_create(hshpc_cyclo, shpc_dir = "SHPC", cyclone = .true., &
          slice = slice, grid_lon_lat = .true.)
     call shpc_create(hshpc_anti, shpc_dir = "SHPC", cyclone = .false., &
          slice = slice, grid_lon_lat = .true.)
  end if

  call cpu_time(t1)
  write(unit, fmt = *) "CPU time for preamble, before computation:", t1 - t0, &
       "s"
  t0 = t1
  call set_all_extr(s, step, periodic, ssh, corner)

  allocate(sorted_extr(s%number_extr))
  min_area = pi * (min_radius * 1e3)**2

  forall (i = 1:s%number_extr)
     s%list(i)%out_cont%closed = .true.
     ! must be intialized to true because it is used in nearby_extr
  end forall

  ! Double sort of extrema on cyclonicity and SSH value:

  selection = argwhere(s%list%cyclone)
  n_cycl = size(selection)
  selection = selection(indexx(s%list(selection)%extr%ssh))
  sorted_extr(:n_cycl) = selection(n_cycl:1:- 1) ! descending order of ssh

  selection = argwhere(.not. s%list%cyclone)
  selection = selection(indexx(s%list(selection)%extr%ssh))
  sorted_extr(n_cycl + 1:) = selection

  ! Done sorting

  if (.not. periodic) nlon = size(ssh, 1)
  nlat = size(ssh, 2)

  loop_extr: do l = 1, s%number_extr
     i = sorted_extr(l)

     associate (e => s%list(i))
       ! Define the geographical window around each eddy extremum:

       llc = e%extr%coord_proj - max_radius
       urc = e%extr%coord_proj + max_radius

       llc(2) = max(llc(2), 1)
       urc(2) = min(urc(2), nlat)

       if (.not. periodic) then
          llc(1) = max(llc(1), 1)
          urc(1) = min(urc(1), nlon)
       end if

       corner_window = corner + (llc - 1) * step
     end associate

     outside_points = 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:
     if (periodic) outside_points(1, :) = outside_points(1, :) &
          + ceiling((corner_window(1) - outside_points(1, :)) / twopi) &
          * twopi

     call set_contours(s, 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)), &
          corner_window, min_area, i, outside_points)
  end do loop_extr

  call cpu_time(t1)
  write(unit, fmt = *) "CPU time for computation, before output:", t1 - t0, "s"
  t0 = t1
  print *, "inst_eddies: s%number_extr = ", s%number_extr
  call write_snapshot(s, hshpc_cyclo, hshpc_anti, date)
  CALL shpc_close(hshpc_cyclo)
  CALL shpc_close(hshpc_anti)

  if (iostat == 0) then
     print *, 'inst_eddies: Appended to shapefiles in one slice of SHPC.'
  else
     print *, 'inst_eddies: Created shapefiles in one slice of SHPC.'
  end if

  call cpu_time(t1)
  write(unit, fmt = *) "CPU time for output:", t1 - t0, "s"
  close(unit)

end program inst_eddies