From 0e1f9399238dc537bd6ac466e773414d77dc1108 Mon Sep 17 00:00:00 2001 From: Lionel GUEZ <guez@lmd.ens.fr> Date: Tue, 31 Jan 2023 21:56:30 +0100 Subject: [PATCH] Keep the good contours Keep the good contours found when looking for the outermost contour, subject to a maximum of `n_max_cont` contours. The idea is to use them later when looking for the maximum-speed contour. Inside function `get_1_outerm`, we temporarily store the good contours in a local explicit-shape array, `cont_list`. --- Inst_eddies/get_1_outerm.f90 | 74 ++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/Inst_eddies/get_1_outerm.f90 b/Inst_eddies/get_1_outerm.f90 index b2a79f38..bcd01fc2 100644 --- a/Inst_eddies/get_1_outerm.f90 +++ b/Inst_eddies/get_1_outerm.f90 @@ -9,10 +9,20 @@ contains ! This procedure gets one outermost contour, if it can find ! one. If the procedure cannot find an outermost contour, it - ! returns a null ssh_contour. An outermost contour is not found - ! if, and only if, there is no good contour at innermost level. If - ! a contour is found then its level is farther from the extremum - ! than innermost level. + ! returns a null ssh_contour. The procedure also finds some inner + ! contours. The number of contours stored, including the outermost + ! contour, is lower than or equal to n_max_cont. If we find more + ! than n_max_cont -1 good contours excluding the outermost + ! contour, then we store only the first n_max_cont -1 found, + ! because they provide a better sample of the ssh range. If the + ! procedure cannot find an outermost contour, it does not store + ! inner contours. An outermost contour is not found if, and only + ! if, there is no good contour at innermost level. If an outermost + ! contour is found then its level is farther from the extremum + ! than innermost level. In the array of stored contours, the + ! contours are in monotonic order of ssh: ascending if the + ! extremum is a minimum, descending if the extremum is a + ! maximum. The area is only computed for the outermost contour. ! Method: dichotomy on level of ssh. @@ -29,7 +39,7 @@ contains use jumble, only: assert use ccw_orient_m, only: ccw_orient - use derived_types, only: ssh_contour, missing_ssh + use derived_types, only: ssh_contour, null_ssh_contour use good_contour_m, only: good_contour use spher_polyline_area_m, only: spher_polyline_area @@ -55,60 +65,74 @@ contains ! Local: real level_try, level_good, level_bad ! in m - type(polyline) tentative_contour real, parameter:: precision = 5e-4 ! in m logical mask(size(ssh, 1), size(ssh, 2)) + integer, parameter:: n_max_cont = 31 + + type(ssh_contour) cont_list(n_max_cont + 1) + ! Contour list. The outermost contour is element n_cont. The + ! contours are in monotonic order of ssh. + + integer n_cont ! number of good contours found and stored !----------------------------------------------------------------- - get_1_outerm%polyline = good_contour(corner, step, ssh, innermost_level_2, & + n_cont = 0 + cont_list(1)%polyline = good_contour(corner, step, ssh, innermost_level_2, & coord_extr, outside_points) - if (get_1_outerm%n_points == 0) then - ! null ssh contour - get_1_outerm%ssh = missing_ssh - get_1_outerm%area = - 1e6 + if (cont_list(1)%n_points == 0) then + get_1_outerm = null_ssh_contour() else + n_cont = 1 + cont_list(1)%ssh = innermost_level_2 level_good = innermost_level_2 mask = ssh /= huge(0.) level_try = merge(maxval(ssh, mask), minval(ssh, mask), cyclone) call assert(merge(level_try > level_good, level_try < level_good, & cyclone), "get_1_outerm level_try") - tentative_contour = good_contour(corner, step, ssh, level_try, & + cont_list(2)%polyline = good_contour(corner, step, ssh, level_try, & coord_extr, outside_points) - if (tentative_contour%n_points /= 0) then + if (cont_list(2)%n_points /= 0) then ! This can only happen if there are degenerate extrema ! everywhere around the path of contour. So it should ! probably never happen. - get_1_outerm%polyline = tentative_contour - get_1_outerm%ssh = level_try + n_cont = 2 + cont_list(2)%ssh = level_try else ! Assertion: {no good contour at maxval or minval} level_bad = level_try do while (abs(level_bad - level_good) > precision) level_try = (level_good + level_bad) / 2. - tentative_contour = good_contour(corner, step, ssh, level_try, & - coord_extr, outside_points) + cont_list(n_cont + 1)%polyline = good_contour(corner, step, ssh, & + level_try, coord_extr, outside_points) + + if (cont_list(n_cont + 1)%n_points /= 0) then + cont_list(n_cont + 1)%ssh = level_try + + if (n_cont == n_max_cont) then + ! Replace the previous good contour found + cont_list(n_cont) = cont_list(n_cont + 1) + else + n_cont = n_cont + 1 + end if - if (tentative_contour%n_points /= 0) then level_good = level_try - get_1_outerm%polyline = tentative_contour else level_bad = level_try end if - ! Assertion: get_1_outerm%polyline == good_contour(. . ., - ! level_good) and get_1_outerm%%n_points /= 0 and + ! Assertion: cont_list(n_cont)%polyline == good_contour(. . ., + ! level_good) and cont_list(n_cont)%%n_points /= 0 and ! no good contour at level_bad end do - - get_1_outerm%ssh = level_good end if - get_1_outerm%area = spher_polyline_area(get_1_outerm%polyline) - call ccw_orient(get_1_outerm) + cont_list(n_cont)%area = spher_polyline_area(cont_list(n_cont)%polyline) + call ccw_orient(cont_list(n_cont)) + get_1_outerm = cont_list(n_cont) end if end function get_1_outerm -- GitLab