From 5550c537b85a5bd9d7888912bad213757d7f9bd7 Mon Sep 17 00:00:00 2001 From: Joel Oskarsson Date: Mon, 14 Oct 2024 08:23:40 +0200 Subject: [PATCH] Fix wrong number of mesh levels when grid is multiple of refinement factor (#26) * Add small epsilon to level calculation before rounding to int * Add changelog entry * Change rounding to flooring --- CHANGELOG.md | 4 ++++ src/weather_model_graphs/create/mesh/mesh.py | 14 ++++++++------ tests/test_graph_creation.py | 20 ++++++++++++++++++++ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 710cea3..7677c1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Fix wrong number of mesh levels when grid is multiple of refinement factor + [\#26](https://github.com/mllam/weather-model-graphs/pull/26) + @joeloskarsson + - Create different number of mesh nodes in x- and y-direction. [\#21](https://github.com/mllam/weather-model-graphs/pull/21) @joeloskarsson diff --git a/src/weather_model_graphs/create/mesh/mesh.py b/src/weather_model_graphs/create/mesh/mesh.py index 4d2eedd..79b4b24 100644 --- a/src/weather_model_graphs/create/mesh/mesh.py +++ b/src/weather_model_graphs/create/mesh/mesh.py @@ -113,12 +113,14 @@ def create_multirange_2d_mesh_graphs( # Find the number of mesh levels possible in x- and y-direction, # and the number of leaf nodes that would correspond to # max_coord/(grid_refinement_factor*level_refinement_factor^mesh_levels) = 1 - max_mesh_levels = ( - (np.log(coord_extent) - np.log(grid_refinement_factor)) - / np.log(level_refinement_factor) - ).astype( - int - ) # (2,) + max_mesh_levels_float = ( + np.log(coord_extent) - np.log(grid_refinement_factor) + ) / np.log(level_refinement_factor) + + # Need to add a small epsilon before flooring to int, due to numerical + # issues with the computation above + eps = 1e-8 + max_mesh_levels = (max_mesh_levels_float + eps).astype(int) # (2,) nleaf = grid_refinement_factor * ( level_refinement_factor**max_mesh_levels ) # leaves at the bottom in each direction, if using max_mesh_levels diff --git a/tests/test_graph_creation.py b/tests/test_graph_creation.py index 67c6d3e..f35b35f 100644 --- a/tests/test_graph_creation.py +++ b/tests/test_graph_creation.py @@ -120,3 +120,23 @@ def test_create_rectangular_graph(kind): fn_name = f"create_{kind}_graph" fn = getattr(wmg.create.archetype, fn_name) fn(xy_grid=xy, grid_refinement_factor=2) + + +@pytest.mark.parametrize("grid_refinement_factor", (2, 3)) +@pytest.mark.parametrize("level_refinement_factor", (2, 3, 5)) +def test_create_exact_refinement(grid_refinement_factor, level_refinement_factor): + """ + This test is to check that it is possible to create graph hierarchies when + the refinement factors are an exact multiple of the number of nodes. In these + situations it should be possible to create multi-level graphs, but it was not + earlier due to numerical issues. + """ + N = grid_refinement_factor * (level_refinement_factor**2) + xy = _create_rectangular_fake_xy(Nx=N, Ny=N) + + # Build hierarchical graph, should have 2 levels and not give error + wmg.create.archetype.create_oskarsson_hierarchical_graph( + xy, + grid_refinement_factor=grid_refinement_factor, + level_refinement_factor=level_refinement_factor, + )