From 7d99eff6bb3948039d8afa8b0f4e062f7ec2d5ce Mon Sep 17 00:00:00 2001 From: Lionel GUEZ <guez@lmd.ens.fr> Date: Fri, 15 Dec 2017 13:44:15 +0100 Subject: [PATCH] In procedure get_snapshot, encountered rounding error that led to out-of-range index so add min when calculating urc. Bug fix in procedure good_contour. polygon_contains_point should not be called if polyline is not closed. Procedure polygon_contains_point became unpure so remove pure for procedure inside_4 too. In program test_good_contour, read corner and step from namelist rather than from coordinates in NetCDF file. Makes it possible to use the same NetCDF file with different coordinates. Also read outside_points from a file rather than standard input so there is no need to specify in advance the number of outside points. Take into account the possibility that no outermost contour was found in program test_set_outermost_contour. Also, use fixed names for input files because it is not convenient to require a particular order of these two files on the command line. --- Sources/get_snapshot.f | 7 ++- Sources/good_contour.f | 29 +++++------ Sources/inside_4.f | 2 +- Tests/Stdin/good_contour_nml_1.txt | 1 + ...contour_in2.txt => good_contour_nml_2.txt} | 5 +- ...contour_in.txt => no_good_contour_nml.txt} | 3 -- ...od_contour_in.txt => outside_points_1.csv} | 2 - Tests/Stdin/outside_points_2.csv | 2 + Tests/test_good_contour.f | 38 ++++++++------- Tests/test_set_outermost_contour.f | 48 +++++++++---------- Tests/tests.json | 17 ++++--- 11 files changed, 78 insertions(+), 76 deletions(-) create mode 100644 Tests/Stdin/good_contour_nml_1.txt rename Tests/Stdin/{good_contour_in2.txt => good_contour_nml_2.txt} (51%) rename Tests/Stdin/{no_good_contour_in.txt => no_good_contour_nml.txt} (77%) rename Tests/Stdin/{good_contour_in.txt => outside_points_1.csv} (56%) create mode 100644 Tests/Stdin/outside_points_2.csv diff --git a/Sources/get_snapshot.f b/Sources/get_snapshot.f index 58af9c39..75e3b453 100644 --- a/Sources/get_snapshot.f +++ b/Sources/get_snapshot.f @@ -179,9 +179,12 @@ contains llc(:, i) = floor(convert_to_ind(minval( & s%list_vis(i)%outermost_contour%points, dim = 2), corner, & step)) - urc(:, i) = ceiling(convert_to_ind(maxval( & + + urc(:, i) = min(ceiling(convert_to_ind(maxval( & s%list_vis(i)%outermost_contour%points, dim = 2), corner, & - step)) + step)), [nlon, nlat]) + ! (min should have no effect except because of roundup error) + corner_window(:, i) = corner + (llc(:, i) - 1) * step ind_targ_extr(:, i) = s%ind_extr(:, i) - llc(:, i) + 1 diff --git a/Sources/good_contour.f b/Sources/good_contour.f index 13962e80..00bfc038 100644 --- a/Sources/good_contour.f +++ b/Sources/good_contour.f @@ -29,7 +29,7 @@ contains integer j ! index in outside_points integer n_cont ! number of contours integer n_out ! number of outside points - + !-------------------------------------------------------------- n_out = size(outside_points, 2) @@ -37,20 +37,21 @@ contains n_cont = size(contours) found_good_contour = .false. i = 1 - + do while (.not. found_good_contour .and. i <= n_cont) - if (contours(i)%closed .and. polygon_contains_point(contours(i)%points, & - inside_point)) then - found_good_contour = .true. ! maybe - ! Does contours(i) contain one of outside_points? - j = 1 + if (contours(i)%closed) then + if (polygon_contains_point(contours(i)%points, inside_point)) then + found_good_contour = .true. ! maybe + ! Does contours(i) contain one of outside_points? + j = 1 - do while (found_good_contour .and. j <= n_out) - found_good_contour & - = .not. polygon_contains_point(contours(i)%points, & - outside_points(:, j)) - j = j + 1 - end do + do while (found_good_contour .and. j <= n_out) + found_good_contour & + = .not. polygon_contains_point(contours(i)%points, & + outside_points(:, j)) + j = j + 1 + end do + end if end if i = i + 1 @@ -61,7 +62,7 @@ contains else good_contour = null_polyline() end if - + end function good_contour end module good_contour_m diff --git a/Sources/inside_4.f b/Sources/inside_4.f index a8a96a74..edf19835 100644 --- a/Sources/inside_4.f +++ b/Sources/inside_4.f @@ -4,7 +4,7 @@ module inside_4_m contains - pure logical function inside_4(distance, center, v) + logical function inside_4(distance, center, v) ! This procedure returns true if the four points center \pm ! (distance(1), 0) and center \pm (0, distance(2)) are inside diff --git a/Tests/Stdin/good_contour_nml_1.txt b/Tests/Stdin/good_contour_nml_1.txt new file mode 100644 index 00000000..0ebbd508 --- /dev/null +++ b/Tests/Stdin/good_contour_nml_1.txt @@ -0,0 +1 @@ +&MAIN_NML corner = -2., -2., step = 0.08, 0.08 / diff --git a/Tests/Stdin/good_contour_in2.txt b/Tests/Stdin/good_contour_nml_2.txt similarity index 51% rename from Tests/Stdin/good_contour_in2.txt rename to Tests/Stdin/good_contour_nml_2.txt index dafb4655..8e682e45 100644 --- a/Tests/Stdin/good_contour_in2.txt +++ b/Tests/Stdin/good_contour_nml_2.txt @@ -1,5 +1,2 @@ ! Case where one of the contours tested does not contain inside point. -&MAIN_NML INSIDE_POINT=0.3,0 / -2 --0.5,-1 --0.7,0 +&MAIN_NML INSIDE_POINT=0.3,0, corner = -2., -2., step = 0.08, 0.08/ diff --git a/Tests/Stdin/no_good_contour_in.txt b/Tests/Stdin/no_good_contour_nml.txt similarity index 77% rename from Tests/Stdin/no_good_contour_in.txt rename to Tests/Stdin/no_good_contour_nml.txt index b6e951b2..61f8cde0 100644 --- a/Tests/Stdin/no_good_contour_in.txt +++ b/Tests/Stdin/no_good_contour_nml.txt @@ -1,5 +1,2 @@ ! Case where there is no good contour &MAIN_NML INSIDE_POINT=0.,0. / -2 --0.5, -1. -0.3, 0. diff --git a/Tests/Stdin/good_contour_in.txt b/Tests/Stdin/outside_points_1.csv similarity index 56% rename from Tests/Stdin/good_contour_in.txt rename to Tests/Stdin/outside_points_1.csv index 017d4aa4..b6fb92e0 100644 --- a/Tests/Stdin/good_contour_in.txt +++ b/Tests/Stdin/outside_points_1.csv @@ -1,4 +1,2 @@ -&MAIN_NML / -2 -0.5, -1. 0.3, 0. diff --git a/Tests/Stdin/outside_points_2.csv b/Tests/Stdin/outside_points_2.csv new file mode 100644 index 00000000..3260f5c4 --- /dev/null +++ b/Tests/Stdin/outside_points_2.csv @@ -0,0 +1,2 @@ +-0.5, -1. +-0.7, 0. diff --git a/Tests/test_good_contour.f b/Tests/test_good_contour.f index edf48f7c..926e74f7 100644 --- a/Tests/test_good_contour.f +++ b/Tests/test_good_contour.f @@ -2,6 +2,7 @@ program test_good_contour use contour_531, only: polyline use good_contour_m, only: good_contour + use jumble, only: new_unit, count_lines use netcdf, only: nf90_nowrite use netcdf95, only: nf95_open, nf95_inq_dimid, nf95_inquire_dimension, & nf95_get_var, nf95_inq_varid, nf95_close @@ -13,18 +14,19 @@ program test_good_contour implicit none character(len = :), allocatable:: filename - integer nx, ny, n_out - real x(2), y(2) ! just the first two values to get the corner and step + integer nx, ny, n_out, i type(polyline) c real:: level = 5. real, allocatable:: Z(:, :) real:: inside_point(2) = [- 0.7, 0.] real, allocatable:: outside_points(:, :) ! (2, n_out) + real:: step(2) = [0.04363323129985824, 0.04363323129985824] ! in rad + real:: corner(2) = [0.002181662, - 0.72213] ! in rad TYPE(shpfileobject) shphandle integer field_number, shape_number - integer length, status, ncid, varid, dimid + integer length, status, ncid, varid, dimid, unit - namelist /main_nml/ inside_point, level + namelist /main_nml/ inside_point, level, step, corner !------------------------------------------------------------------- @@ -38,13 +40,9 @@ program test_good_contour call nf95_inq_dimid(ncid, "x", dimid) call nf95_inquire_dimension(ncid, dimid, nclen = nx) - call nf95_inq_varid(ncid, "x", varid) - call nf95_get_var(ncid, varid, x) call nf95_inq_dimid(ncid, "y", dimid) call nf95_inquire_dimension(ncid, dimid, nclen = ny) - call nf95_inq_varid(ncid, "y", varid) - call nf95_get_var(ncid, varid, y) allocate(z(nx, ny)) @@ -58,18 +56,22 @@ program test_good_contour read(unit = *, nml = main_nml) write(unit = *, nml = main_nml) - print *, "Number of outside points? " - read *, n_out + print *, 'Reading from "outside_points.csv"...' + call new_unit(unit) + open(unit, file = "outside_points.csv", status = "old", action = "read", & + position = "rewind") + call count_lines(unit, n_out) + rewind(unit) allocate(outside_points(2, n_out)) - if (n_out /= 0) then - print *, "Enter outside points." - read *, outside_points - end if - print *, "outside_points = ", outside_points + if (n_out /= 0) read (unit, fmt = *) outside_points + close(unit) + print *, "outside_points:" + + do i = 1, n_out + print *, outside_points(:, i) + end do - c = good_contour(corner = [x(1), y(1)], step = [x(2) - x(1), y(2) - y(1)], & - z = z, level = level, inside_point = inside_point, & - outside_points = outside_points) + c = good_contour(corner, step, z, level, inside_point, outside_points) if (c%n_points /= 0) then call shp_create_03("test_good_contour", shpt_polygon, shphandle) diff --git a/Tests/test_set_outermost_contour.f b/Tests/test_set_outermost_contour.f index 415e1e7d..9995a584 100644 --- a/Tests/test_set_outermost_contour.f +++ b/Tests/test_set_outermost_contour.f @@ -3,11 +3,10 @@ program test_set_outermost_contour use, intrinsic:: ISO_FORTRAN_ENV use derived_types, only: eddy - use jumble, only: get_command_arg_dyn use netcdf, only: nf90_nowrite use netcdf95, only: nf95_open, nf95_close, nf95_inq_varid, nf95_get_var, & nf95_gw_var - use nr_util, only: pi, assert + use nr_util, only: pi use set_outermost_contour_m, only: set_outermost_contour use shapelib, only: shpt_polygon, shpfileobject, ftdouble, shpclose use shapelib_03, only: shp_create_03, dbf_add_field_03, & @@ -15,7 +14,6 @@ program test_set_outermost_contour implicit none - character(len = :), allocatable:: filename integer ncid, varid real longitude(2) ! in rad real latitude(2) ! in rad @@ -37,28 +35,23 @@ program test_set_outermost_contour !---------------------------------------------------------------- - call assert(COMMAND_ARGUMENT_COUNT() == 2, & - "Required arguments: ADT-file extr_map-file") - write(unit = error_unit, nml = main_nml) write(unit = error_unit, fmt = *) "Enter namelist main_nml." read(unit = *, nml = main_nml) write(unit = *, nml = main_nml) - ! No problem of degenerate time coordinate with extr_map-file so + ! No problem of degenerate time coordinate with "extr_map.nc" so ! read it first: - call get_command_arg_dyn(2, filename) - print *, "Reading from ", filename, "..." - call nf95_open(filename, nf90_nowrite, ncid) + print *, 'Reading from "extr_map.nc"...' + call nf95_open("extr_map.nc", nf90_nowrite, ncid) call nf95_inq_varid(ncid, "extr_map", varid) call nf95_gw_var(ncid, varid, extr_map) call nf95_close(ncid) - call get_command_arg_dyn(1, filename) - print *, "Reading from ", filename, "..." - call nf95_open(filename, nf90_nowrite, ncid) + print *, 'Reading from "h.nc"...' + call nf95_open("h.nc", nf90_nowrite, ncid) call nf95_inq_varid(ncid, "lon", varid) call nf95_get_var(ncid, varid, longitude) @@ -83,18 +76,21 @@ program test_set_outermost_contour call set_outermost_contour(e, ind_targ_extr, innermost_level, extr_map, & ssh, corner = [longitude(1), latitude(1)], step = step) - print *, "e%outermost_contour%closed = ", e%outermost_contour%closed - print *, "Radius of disk of equal area: ", & - sqrt(e%outermost_contour%area / pi) / 1e3, "km" - - call shp_create_03("test_set_outermost_contour", shpt_polygon, shphandle) - call dbf_add_field_03(field_number, shphandle, 'level', ftdouble, & - nwidth = 13, ndecimals = 6) - call shp_append_simple_object_03(shape_number, shphandle, shpt_polygon, & - e%outermost_contour%points / pi * 180.) - call dbf_write_attribute_03(shphandle, shape_number, ifield = 0, & - fieldvalue = e%outermost_contour%ssh) - CALL shpclose(shphandle) - print *, 'Created shapefile "test_set_outermost_contour".' + if (e%outermost_contour%closed) then + print *, "Radius of disk of equal area: ", & + sqrt(e%outermost_contour%area / pi) / 1e3, "km" + + call shp_create_03("test_set_outermost_contour", shpt_polygon, shphandle) + call dbf_add_field_03(field_number, shphandle, 'level', ftdouble, & + nwidth = 13, ndecimals = 6) + call shp_append_simple_object_03(shape_number, shphandle, shpt_polygon, & + e%outermost_contour%points / pi * 180.) + call dbf_write_attribute_03(shphandle, shape_number, ifield = 0, & + fieldvalue = e%outermost_contour%ssh) + CALL shpclose(shphandle) + print *, 'Created shapefile "test_set_outermost_contour".' + else + print *, "Could not find an outermost contour." + end if end program test_set_outermost_contour diff --git a/Tests/tests.json b/Tests/tests.json index 98bf5e66..7fd07ffd 100644 --- a/Tests/tests.json +++ b/Tests/tests.json @@ -1,21 +1,26 @@ [ { - "stdin" : "$stdin_dir/good_contour_in.txt", + "stdin" : "$stdin_dir/good_contour_nml_1.txt", "args" : ["$compil_prod_dir/test_good_contour", "$input_dir/example.nc"], - "title" : "Good_contour" + "title" : "Good_contour", + "required": [["$stdin_dir/outside_points_1.csv", "outside_points.csv"]], + "description": "3 contours at that level. 2 contain the inside point, one of which contains the 2 outside points." }, { - "stdin" : "$stdin_dir/good_contour_in2.txt", + "stdin" : "$stdin_dir/good_contour_nml_2.txt", "args" : ["$compil_prod_dir/test_good_contour", "$input_dir/example.nc"], - "title" : "Good_contour_2" + "title" : "Good_contour_2", + "required": [["$stdin_dir/outside_points_2.csv", "outside_points.csv"]], + "description": "Select another good contour." }, { - "stdin" : "$stdin_dir/no_good_contour_in.txt", + "stdin" : "$stdin_dir/no_good_contour_nml.txt", "args" : ["$compil_prod_dir/test_good_contour", "$input_dir/example.nc"], - "title" : "No_good_contour" + "title" : "No_good_contour", + "required": [["$stdin_dir/outside_points_1.csv", "outside_points.csv"]] }, { "args" : ["$compil_prod_dir/test_local_extrema", -- GitLab