From a8ead8bbd295ad6cae9a75e0f013e5e473bb626c Mon Sep 17 00:00:00 2001 From: tomsail Date: Fri, 13 Sep 2024 12:00:28 +0200 Subject: [PATCH] feat: add telemac3D support --- locks/requirements-ci-telemac.txt | 130 ++++++++++---------- poetry.lock | 5 +- pyposeidon/misc/telemac3d.cas | 194 ++++++++++++++++++++---------- pyposeidon/misc/telemac3d.json | 149 ++++++++++++++--------- pyposeidon/telemac.py | 72 ++++++----- pyposeidon/utils/cfl.py | 4 +- pyposeidon/utils/cpoint.py | 4 +- pyposeidon/utils/data.py | 40 +++--- pyposeidon/utils/norm.py | 3 +- pyposeidon/utils/obs.py | 20 ++- pyposeidon/utils/pplot.py | 1 + tests/test_telemac.py | 29 ++++- tests/utils/test_cpoint.py | 24 ++-- tests/utils/test_obs.py | 24 ++-- 14 files changed, 419 insertions(+), 280 deletions(-) diff --git a/locks/requirements-ci-telemac.txt b/locks/requirements-ci-telemac.txt index dea048b1..6d204919 100644 --- a/locks/requirements-ci-telemac.txt +++ b/locks/requirements-ci-telemac.txt @@ -1,17 +1,18 @@ affine==2.4.0 ; python_version >= "3.9" and python_version < "4" -annotated-types==0.6.0 ; python_version >= "3.9" and python_version < "4.0" -anyio==4.3.0 ; python_version >= "3.9" and python_version < "4.0" +annotated-types==0.7.0 ; python_version >= "3.9" and python_version < "4.0" +anyio==4.4.0 ; python_version >= "3.9" and python_version < "4.0" asciitree==0.3.3 ; python_version >= "3.9" and python_version < "4" -attrs==23.2.0 ; python_version >= "3.9" and python_version < "4" +attrs==24.2.0 ; python_version >= "3.9" and python_version < "4" beautifulsoup4==4.12.3 ; python_version >= "3.9" and python_version < "4" -black==24.3.0 ; python_version >= "3.9" and python_version < "4" +black==24.8.0 ; python_version >= "3.9" and python_version < "4" +bottleneck==1.4.0 ; python_version >= "3.9" and python_version < "4" bump2version==1.0.1 ; python_version >= "3.9" and python_version < "4" -cartopy==0.22.0 ; python_version >= "3.9" and python_version < "4" +cartopy==0.23.0 ; python_version >= "3.9" and python_version < "4" catalogue==2.0.10 ; python_version >= "3.9" and python_version < "4" -certifi==2024.2.2 ; python_version >= "3.9" and python_version < "4" -cffi==1.16.0 ; python_version >= "3.9" and python_version < "4" -cfgrib==0.9.11.0 ; python_version >= "3.9" and python_version < "4" -cftime==1.6.3 ; python_version >= "3.9" and python_version < "4" +certifi==2024.7.4 ; python_version >= "3.9" and python_version < "4" +cffi==1.17.0 ; python_version >= "3.9" and python_version < "4" +cfgrib==0.9.14.0 ; python_version >= "3.9" and python_version < "4" +cftime==1.6.4 ; python_version >= "3.9" and python_version < "4" charset-normalizer==3.3.2 ; python_version >= "3.9" and python_version < "4" click-plugins==1.1.1 ; python_version >= "3.9" and python_version < "4" click==8.1.7 ; python_version >= "3.9" and python_version < "4" @@ -21,93 +22,98 @@ colorama==0.4.6 ; python_version >= "3.9" and python_version < "4" and (sys_plat colorlog==6.8.2 ; python_version >= "3.9" and python_version < "4" configobj==5.0.8 ; python_version >= "3.9" and python_version < "4" contourpy==1.2.1 ; python_version >= "3.9" and python_version < "4" -coverage[toml]==7.4.4 ; python_version >= "3.9" and python_version < "4" +coverage[toml]==7.6.1 ; python_version >= "3.9" and python_version < "4" cycler==0.12.1 ; python_version >= "3.9" and python_version < "4" -dask==2024.4.1 ; python_version >= "3.9" and python_version < "4" -dataretrieval==1.0.6 ; python_version >= "3.9" and python_version < "4.0" +dask==2024.8.0 ; python_version >= "3.9" and python_version < "4" +dataretrieval==1.0.10 ; python_version >= "3.9" and python_version < "4.0" deprecated==1.2.14 ; python_version >= "3.9" and python_version < "4.0" -docopt==0.6.2 ; python_version >= "3.9" and python_version < "4" -donfig==0.8.1.post0 ; python_version >= "3.9" and python_version < "4" -eccodes==1.7.0 ; python_version >= "3.9" and python_version < "4" +docopt-ng==0.9.0 ; python_version >= "3.9" and python_version < "4" +donfig==0.8.1.post1 ; python_version >= "3.9" and python_version < "4" +eccodes==1.7.1 ; python_version >= "3.9" and python_version < "4" erddapy==2.2.0 ; python_version >= "3.9" and python_version < "4.0" -exceptiongroup==1.2.0 ; python_version >= "3.9" and python_version < "3.11" +exceptiongroup==1.2.2 ; python_version >= "3.9" and python_version < "3.11" execnet==2.1.1 ; python_version >= "3.9" and python_version < "4" f90nml==1.4.4 ; python_version >= "3.9" and python_version < "4" fasteners==0.19 ; python_version >= "3.9" and python_version < "4" and sys_platform != "emscripten" findlibs==0.0.5 ; python_version >= "3.9" and python_version < "4" -fiona==1.9.6 ; python_version >= "3.9" and python_version < "4" -fonttools==4.51.0 ; python_version >= "3.9" and python_version < "4" -fsspec==2024.3.1 ; python_version >= "3.9" and python_version < "4" -geopandas==0.14.3 ; python_version >= "3.9" and python_version < "4" -gmsh==4.12.2 ; python_version >= "3.9" and python_version < "4" +fonttools==4.53.1 ; python_version >= "3.9" and python_version < "4" +fsspec==2024.6.1 ; python_version >= "3.9" and python_version < "4" +geopandas==1.0.1 ; python_version >= "3.9" and python_version < "4" +gmsh==4.13.1 ; python_version >= "3.9" and python_version < "4" h11==0.14.0 ; python_version >= "3.9" and python_version < "4.0" html5lib==1.1 ; python_version >= "3.9" and python_version < "4.0" httpcore==1.0.5 ; python_version >= "3.9" and python_version < "4.0" httpx==0.27.0 ; python_version >= "3.9" and python_version < "4.0" -idna==3.6 ; python_version >= "3.9" and python_version < "4" -importlib-metadata==7.1.0 ; python_version >= "3.9" and python_version < "3.12" -importlib-resources==6.4.0 ; python_version >= "3.9" and python_version < "4.0" +idna==3.7 ; python_version >= "3.9" and python_version < "4" +importlib-metadata==8.4.0 ; python_version >= "3.9" and python_version < "4" +importlib-resources==6.4.4 ; python_version >= "3.9" and python_version < "4" iniconfig==2.0.0 ; python_version >= "3.9" and python_version < "4" -jinja2==3.1.3 ; python_version >= "3.9" and python_version < "4" -joblib==1.4.0 ; python_version >= "3.9" and python_version < "4" +jinja2==3.1.4 ; python_version >= "3.9" and python_version < "4" +joblib==1.4.2 ; python_version >= "3.9" and python_version < "4" kiwisolver==1.4.5 ; python_version >= "3.9" and python_version < "4" -limits==3.10.1 ; python_version >= "3.9" and python_version < "4.0" -llvmlite==0.42.0 ; python_version >= "3.9" and python_version < "4" +limits==3.13.0 ; python_version >= "3.9" and python_version < "4.0" +llvmlite==0.43.0 ; python_version >= "3.9" and python_version < "4" locket==1.0.0 ; python_version >= "3.9" and python_version < "4" -lxml==5.2.1 ; python_version >= "3.9" and python_version < "4.0" +lxml-html-clean==0.2.0 ; python_version >= "3.9" and python_version < "4.0" +lxml==5.3.0 ; python_version >= "3.9" and python_version < "4" +lxml[html-clean]==5.3.0 ; python_version >= "3.9" and python_version < "4.0" markupsafe==2.1.5 ; python_version >= "3.9" and python_version < "4" -matplotlib==3.8.4 ; python_version >= "3.9" and python_version < "4" +matplotlib==3.9.2 ; python_version >= "3.9" and python_version < "4" mpi4py==3.1.5 ; python_version >= "3.9" and python_version < "4" mypy-extensions==1.0.0 ; python_version >= "3.9" and python_version < "4" -netcdf4==1.6.5 ; python_version >= "3.9" and python_version < "4" +netcdf4==1.7.1.post2 ; python_version >= "3.9" and python_version < "4" numcodecs==0.12.1 ; python_version >= "3.9" and python_version < "4" -numpy==1.26.4 ; python_version >= "3.9" and python_version < "4" -packaging==24.0 ; python_version >= "3.9" and python_version < "4" -pandas==2.2.1 ; python_version >= "3.9" and python_version < "4" -partd==1.4.1 ; python_version >= "3.9" and python_version < "4" +numpy==2.0.1 ; python_version >= "3.9" and python_version < "4" +packaging==24.1 ; python_version >= "3.9" and python_version < "4" +pandas==2.2.2 ; python_version >= "3.9" and python_version < "4" +partd==1.4.2 ; python_version >= "3.9" and python_version < "4" pathspec==0.12.1 ; python_version >= "3.9" and python_version < "4" -pillow==10.3.0 ; python_version >= "3.9" and python_version < "4" -platformdirs==4.2.0 ; python_version >= "3.9" and python_version < "4" -pluggy==1.4.0 ; python_version >= "3.9" and python_version < "4" -psutil==5.9.8 ; python_version >= "3.9" and python_version < "4" +pillow==10.4.0 ; python_version >= "3.9" and python_version < "4" +platformdirs==4.2.2 ; python_version >= "3.9" and python_version < "4" +pluggy==1.5.0 ; python_version >= "3.9" and python_version < "4" +psutil==6.0.0 ; python_version >= "3.9" and python_version < "4" +pyarrow==17.0.0 ; python_version >= "3.9" and python_version < "4" pycparser==2.22 ; python_version >= "3.9" and python_version < "4" -pydantic-core==2.16.3 ; python_version >= "3.9" and python_version < "4.0" -pydantic==2.6.4 ; python_version >= "3.9" and python_version < "4.0" -pydap==3.4.1 ; python_version >= "3.9" and python_version < "4" -pykdtree==1.3.11 ; python_version >= "3.9" and python_version < "4" -pyogrio==0.7.2 ; python_version >= "3.9" and python_version < "4" +pydantic-core==2.20.1 ; python_version >= "3.9" and python_version < "4.0" +pydantic==2.8.2 ; python_version >= "3.9" and python_version < "4.0" +pydap==3.5 ; python_version >= "3.9" and python_version < "4" +pykdtree==1.3.12 ; python_version >= "3.9" and python_version < "4" +pymap3d==3.1.0 ; python_version >= "3.9" and python_version < "4" +pyogrio==0.9.0 ; python_version >= "3.9" and python_version < "4" pyparsing==3.1.2 ; python_version >= "3.9" and python_version < "4" pyproj==3.6.1 ; python_version >= "3.9" and python_version < "4" -pyresample==1.28.2 ; python_version >= "3.9" and python_version < "4" +pyresample==1.29.0 ; python_version >= "3.9" and python_version < "4" pyshp==2.3.1 ; python_version >= "3.9" and python_version < "4" pytest-cov==5.0.0 ; python_version >= "3.9" and python_version < "4" -pytest-xdist==3.5.0 ; python_version >= "3.9" and python_version < "4" -pytest==8.1.1 ; python_version >= "3.9" and python_version < "4" +pytest-xdist==3.6.1 ; python_version >= "3.9" and python_version < "4" +pytest==8.3.2 ; python_version >= "3.9" and python_version < "4" python-dateutil==2.9.0.post0 ; python_version >= "3.9" and python_version < "4" pytz==2024.1 ; python_version >= "3.9" and python_version < "4" -pyyaml==6.0.1 ; python_version >= "3.9" and python_version < "4" -rasterio==1.3.9 ; python_version >= "3.9" and python_version < "4" -requests==2.31.0 ; python_version >= "3.9" and python_version < "4" +pyyaml==6.0.2 ; python_version >= "3.9" and python_version < "4" +rasterio==1.3.10 ; python_version >= "3.9" and python_version < "4" +requests==2.32.3 ; python_version >= "3.9" and python_version < "4" rioxarray==0.15.0 ; python_version >= "3.9" and python_version < "4" -scipy==1.13.0 ; python_version >= "3.9" and python_version < "4" -searvey==0.3.11 ; python_version >= "3.9" and python_version < "4.0" -setuptools==69.2.0 ; python_version >= "3.9" and python_version < "4" -shapely==2.0.3 ; python_version >= "3.9" and python_version < "4" +scikit-learn==1.5.1 ; python_version >= "3.9" and python_version < "4" +scipy==1.13.1 ; python_version >= "3.9" and python_version < "4" +searvey==0.3.13 ; python_version >= "3.9" and python_version < "4.0" +setuptools==73.0.1 ; python_version >= "3.9" and python_version < "4" +shapely==2.0.6 ; python_version >= "3.9" and python_version < "4" six==1.16.0 ; python_version >= "3.9" and python_version < "4" sniffio==1.3.1 ; python_version >= "3.9" and python_version < "4.0" snuggs==1.4.7 ; python_version >= "3.9" and python_version < "4" -soupsieve==2.5 ; python_version >= "3.9" and python_version < "4" +soupsieve==2.6 ; python_version >= "3.9" and python_version < "4" srsly==2.4.8 ; python_version >= "3.9" and python_version < "4" +threadpoolctl==3.5.0 ; python_version >= "3.9" and python_version < "4" tomli==2.0.1 ; python_version >= "3.9" and python_full_version <= "3.11.0a6" toolz==0.12.1 ; python_version >= "3.9" and python_version < "4" -tqdm==4.66.2 ; python_version >= "3.9" and python_version < "4" -typing-extensions==4.11.0 ; python_version >= "3.9" and python_version < "4.0" +tqdm==4.66.5 ; python_version >= "3.9" and python_version < "4" +typing-extensions==4.12.2 ; python_version >= "3.9" and python_version < "4.0" tzdata==2024.1 ; python_version >= "3.9" and python_version < "4" -urllib3==2.2.1 ; python_version >= "3.9" and python_version < "4" +urllib3==2.2.2 ; python_version >= "3.9" and python_version < "4" webencodings==0.5.1 ; python_version >= "3.9" and python_version < "4.0" -webob==1.8.7 ; python_version >= "3.9" and python_version < "4" +webob==1.8.8 ; python_version >= "3.9" and python_version < "4" wrapt==1.16.0 ; python_version >= "3.9" and python_version < "4.0" xarray-selafin==0.1.4 ; python_version >= "3.9" and python_version < "4" -xarray==2024.3.0 ; python_version >= "3.9" and python_version < "4" -zarr==2.17.2 ; python_version >= "3.9" and python_version < "4" -zipp==3.18.1 ; python_version >= "3.9" and python_version < "3.12" +xarray==2024.7.0 ; python_version >= "3.9" and python_version < "4" +zarr==2.18.2 ; python_version >= "3.9" and python_version < "4" +zipp==3.20.0 ; python_version >= "3.9" and python_version < "4" diff --git a/poetry.lock b/poetry.lock index 0f3b6073..3204085a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "affine" @@ -3373,7 +3373,6 @@ files = [ {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0cace394b6ea70c01ca1595f839cf193df35d1575986e484ad35c4aeae7266c1"}, {file = "pandas-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24"}, {file = "pandas-2.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9dfde2a0ddef507a631dc9dc4af6a9489d5e2e740e226ad426a05cabfbd7c8ef"}, - {file = "pandas-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e9b79011ff7a0f4b1d6da6a61aa1aa604fb312d6647de5bad20013682d1429ce"}, {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cb51fe389360f3b5a4d57dbd2848a5f033350336ca3b340d1c53a1fad33bcad"}, {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eee3a87076c0756de40b05c5e9a6069c035ba43e8dd71c379e68cab2c20f16ad"}, {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3e374f59e440d4ab45ca2fffde54b81ac3834cf5ae2cdfa69c90bc03bde04d76"}, @@ -6040,4 +6039,4 @@ viz = ["geoviews", "holoviews", "hvplot", "ipykernel", "itkwidgets", "matplotlib [metadata] lock-version = "2.0" python-versions = ">=3.9, <4" -content-hash = "3b82313d68e68c02a7b42b03ee5678adaec056d90fb8bfc773ecc1858c069f9e" +content-hash = "555f3bffe150c808a765573e19c7920da7aa392d7acdaa31e5c802596cd5a378" diff --git a/pyposeidon/misc/telemac3d.cas b/pyposeidon/misc/telemac3d.cas index fd9777b7..980fd33b 100755 --- a/pyposeidon/misc/telemac3d.cas +++ b/pyposeidon/misc/telemac3d.cas @@ -1,14 +1,23 @@ +/-------------------------------------------------------------------/ +/ TELEMAC-3D - VALIDATION TEST CASE NUMBER 17 - 02/2000 / +/ M2 TIDE COMPONENT / +/-------------------------------------------------------------------/ +/ /---------------------------------------------- / COMPUTER INFORMATIONS /---------------------------------------------- / -FORTRAN FILE = '{{ fortran_file }}' -GEOMETRY FILE = '{{ geo_file }}' -BOUNDARY CONDITIONS FILE = '{{ cli_file }}' -3D RESULT FILE = '{{ out_3D_file }}' -2D RESULT FILE = '{{ out_2D_file }}' -FORMATTED DATA FILE 1 = '{{ formatted_data_file_1 }}' -DEBUGGER={{ debugger }} +GEOMETRY FILE = '{{geo_file}}' +BOUNDARY CONDITIONS FILE = '{{cli_file}}' +BINARY ATMOSPHERIC DATA FILE = +'{{inp_wind_file}}' +3D RESULT FILE = '{{out_3D_file}}' +2D RESULT FILE = '{{out_2D_file}}' +{% if monitor %}2D TIME SERIES FILE = '{{out_1D_file_2D}}' +3D TIME SERIES FILE = '{{out_1D_file_3D}}' +TIME SERIES COORDINATES FILE = '{{station_coords}}'{% endif %} +/CHECKING THE MESH = YES +/PARALLEL PROCESSORS = {{ ncsize }} {% if fortran %}FORTRAN FILE = 'user_fortran' {% endif %} / @@ -17,83 +26,136 @@ DEBUGGER={{ debugger }} /---------------------------------------------- / TITLE = '{{ title }}' -VARIABLES FOR 3D GRAPHIC PRINTOUTS : '{{ variables_3d_graphics }}' -VARIABLES FOR 2D GRAPHIC PRINTOUTS : '{{ variables_2d_graphics }}' -GRAPHIC PRINTOUT PERIOD = {{ graphic_printout_period }} -LISTING PRINTOUT PERIOD = {{ listing_printout_period }} -TIME STEP = {{ time_step }} -NUMBER OF TIME STEPS = {{ number_of_time_steps }} -CHECKING THE MESH = {{ checking_mesh }} -{% if nonlinearities %}NUMBER OF SUB ITERATIONS FOR NON LINEARITIES : {{no_subiter}} {% endif %} +VARIABLES FOR 3D GRAPHIC PRINTOUTS : 'Z,U,V,W' +VARIABLES FOR 2D GRAPHIC PRINTOUTS : 'U,V,S' +GRAPHIC PRINTOUT PERIOD = {{tstep_graph}} +LISTING PRINTOUT PERIOD = {{tstep_list}} +TIME STEP = {{tstep}} +DURATION = {{duration}} +ORIGINAL DATE OF TIME = {{datestart}} +ORIGINAL HOUR OF TIME = {{timestart}} +/NUMBER OF SUB ITERATIONS FOR NON LINEARITIES = 20 / /----------------------------------------------------------------------/ / INITIAL CONDITIONS /----------------------------------------------------------------------/ -ORIGINAL DATE OF TIME = {{ original_date_of_time }} -ORIGINAL HOUR OF TIME = {{ original_hour_of_time }} -/NUMBER OF DROGUES = {{ number_of_drogues }} -/PRINTOUT PERIOD FOR DROGUES = {{ printout_period_drogues }} -/DROGUES FILE = '{{ drogues_file }}' -MASS-BALANCE = {{ mass_balance }} + +{% if computation_continued %}PREVIOUS COMPUTATION FILE = {{ previous_computation_file }} +PREVIOUS COMPUTATION FILE FORMAT = 'SERAFIND' +{% else %} +INITIAL CONDITIONS = '{{initial_conditions}}' /ZERO ELEVATION, +/ /CONSTANT ELEVATION, +/ /INITIAL ELEVATION, +/ /ZERO DEPTH, +/ /CONSTANT DEPTH (together with INITIAL DEPTH), +/ /SPECIAL, +/ /TPXO SATELLITE ALTIMETRY{% endif %} / + +/--------------------------------------------------------------------- +/ CREATE RESTART CONDITIONS +/--------------------------------------------------------------------- +{% if hotstart %} +RESTART FILE = {{ restart_file }} +/RECORD NUMBER IN RESTART FILE = {{ restart_tstep }} +RESTART FILE FORMAT = 'SERAFIND' {% endif %} /---------------------------------------------- / PHYSICAL PARAMETERS /---------------------------------------------- / -LAW OF BOTTOM FRICTION = {{ law_of_bottom_friction }} -FRICTION COEFFICIENT FOR THE BOTTOM = {{ friction_coefficient_bottom }} -/TIDE GENERATING FORCE = {{ tide_generating_force }} -/FRICTION COEFFICIENT FOR THE BOTTOM = {{ friction_coefficient_bottom_2 }} -CORIOLIS = {{ coriolis }} -INITIAL CONDITIONS = '{{ initial_conditions }}' +LAW OF BOTTOM FRICTION = {{ friction_law }} +FRICTION COEFFICIENT FOR THE BOTTOM = {{ friction_coef }} +TIDE GENERATING FORCE = {{ tide_generating_force }} +MESH TRANSFORMATION = {{ mesh_transformation }} /sigma transformation default=1 +NUMBER OF HORIZONTAL LEVELS = {{ horizontal_levels }} +CORIOLIS = {{ coriolis }} +WIND = YES / /--------------------------------------------------------------------- / SPATIAL CONDITIONS - COORDINATE SYSTEM /--------------------------------------------------------------------- -SPHERICAL COORDINATES = {{ spherical_coordinates }} -SPATIAL PROJECTION TYPE = {{ spatial_projection_type }} -GEOGRAPHIC SYSTEM = {{ geographic_system }} -RESULT FILE IN LONGITUDE-LATITUDE = {{ result_file_in_longitude_latitude }} +SPHERICAL COORDINATES = YES +SPATIAL PROJECTION TYPE = 3 +/ '1="CARTESIAN, NOT GEOREFERENCED"'; '2="MERCATOR"'; '3="LATITUDE LONGITUDE"' +/ 'Option 2 or 3 mandatory for spherical coordinates / Option 3: latitude and longitude in degrees!' +GEOGRAPHIC SYSTEM = 5 /0="DEFINED BY USER" +/ /1="WGS84 LONGITUDE/LATITUDE IN REAL DEGREES" +/ /2="WGS84 NORTHERN UTM" +/ /3="WGS84 SOUTHERN UTM" +/ /4="LAMBERT" +/ /5="MERCATOR FOR TELEMAC" +/ +RESULT FILE IN LONGITUDE-LATITUDE = YES /------------------------------------------------------ / NUMERICAL PARAMETERS /---------------------------------------------- +{% if tidal_flats %} +TIDAL FLATS : YES / tidal flat correction +OPTION FOR THE TREATMENT OF TIDAL FLATS : 1 / equations solved everywhere with correction on tidal flats +TREATMENT ON TIDAL FLATS FOR TRACERS : 1 +TREATMENT OF NEGATIVE DEPTHS : 2 +MASS-LUMPING FOR DEPTH : 1 +{% endif %} / -SCHEME FOR ADVECTION OF DEPTH = {{ scheme_for_advection_of_depth }} -/SCHEME FOR ADVECTION OF VELOCITIES = {{ scheme_for_advection_of_velocities }} -ACCURACY FOR PROPAGATION = {{ accuracy_for_propagation }} -ACCURACY FOR DIFFUSION OF VELOCITIES = {{ accuracy_for_diffusion_of_velocities }} -ACCURACY FOR PPE = {{ accuracy_for_ppe }} -/ -MAXIMUM NUMBER OF ITERATIONS FOR ADVECTION SCHEMES = {{ max_iterations_advection_schemes }} -MAXIMUM NUMBER OF ITERATIONS FOR PROPAGATION = {{ max_iterations_propagation }} -MAXIMUM NUMBER OF ITERATIONS FOR DIFFUSION OF VELOCITIES = {{ max_iterations_diffusion_velocities }} -MAXIMUM NUMBER OF ITERATIONS FOR PPE = {{ max_iterations_ppe }} -MAXIMUM NUMBER OF ITERATIONS FOR DIFFUSION OF K-EPSILON = {{ max_iterations_diffusion_k_epsilon }} -/ -SOLVER FOR PPE = {{ solver_for_ppe }} -SOLVER FOR PROPAGATION = {{ solver_for_propagation }} -OPTION OF SOLVER FOR PROPAGATION = {{ option_solver_for_propagation }} -IMPLICITATION FOR DEPTH = {{ implicitation_for_depth }} -IMPLICITATION FOR VELOCITIES = {{ implicitation_for_velocities }} -COEFFICIENT FOR HORIZONTAL DIFFUSION OF VELOCITIES = {{ coefficient_horizontal_diffusion_velocities }} -COEFFICIENT FOR VERTICAL DIFFUSION OF VELOCITIES = {{ coefficient_vertical_diffusion_velocities }} -FREE SURFACE GRADIENT COMPATIBILITY = {{ free_surface_gradient_compatibility }} +/----------------------------------------------------------------------/ +/ ADVECTION / +/----------------------------------------------------------------------/ / -/---------------------------------------------------------------------- -/ VERTICAL DESCRIPTION (LAYERS, MESH, ETC...) -/---------------------------------------------------------------------- +/ PSI scheme +{% if tidal_flats %} +SCHEME FOR ADVECTION OF VELOCITIES= 13 +SCHEME FOR ADVECTION OF K-EPSILON = 13 +SCHEME FOR ADVECTION OF TRACERS = 13 +{% else %} +SCHEME FOR ADVECTION OF VELOCITIES= 5 +SCHEME FOR ADVECTION OF K-EPSILON = 5 +SCHEME FOR ADVECTION OF TRACERS = 5 +{% endif %} +/- without tidal flats, use the predictor-corrector without tidal flats treatment to gain some time +/ Predictor-corrector without tidal flats treatment +/SCHEME OPTION FOR ADVECTION OF VELOCITIES = 2 +/SCHEME OPTION FOR ADVECTION OF K-EPSILON = 2 +/SCHEME OPTION FOR ADVECTION OF TRACERS = 2 +MAXIMUM NUMBER OF ITERATIONS FOR ADVECTION SCHEMES = 200 +/NUMBER OF CORRECTIONS OF DISTRIBUTIVE SCHEMES = 2 / -MESH TRANSFORMATION = {{ mesh_transformation }} -NUMBER OF HORIZONTAL LEVELS = {{ number_of_horizontal_levels }} -NUMBER OF BOTTOM SMOOTHINGS = {{ number_of_bottom_smoothings }} +/----------------------------------------------------------------------/ +/ DIFFUSION / +/----------------------------------------------------------------------/ / -/---------------------------------------------- -/ DRY-WET ELEMENTS -/---------------------------------------------- +SCHEME FOR DIFFUSION OF VELOCITIES = 1 /default implicit (0 value cancels diffusion) +/SCHEME FOR DIFFUSION OF TRACERS = 1 +SCHEME FOR DIFFUSION OF K-EPSILON = 1 +IMPLICITATION FOR DIFFUSION = 1 /default +/MAXIMUM NUMBER OF ITERATIONS FOR DIFFUSION OF VELOCITIES = 200 +/DIFFUSION STEP +/---------------------------------------------------------------------/ +/ PROPAGATION / +/---------------------------------------------------------------------/ / -/TIDAL FLATS = {{ tidal_flats }} -/MINIMAL VALUE FOR DEPTH = {{ minimal_value_for_depth }} -/TREATMENT OF NEGATIVE DEPTHS = {{ treatment_of_negative_depths }} -/TREATMENT ON TIDAL FLATS FOR VELOCITIES = {{ treatment_on_tidal_flats_for_velocities }} -/OPTION FOR THE TREATMENT OF TIDAL FLATS = {{ option_for_treatment_of_tidal_flats }} -/ \ No newline at end of file +FREE SURFACE GRADIENT COMPATIBILITY = {{ surface_gradient_compatibility }} /only used with wave equation +IMPLICITATION FOR DEPTH = {{ implicitation_depth }} /default +IMPLICITATION FOR VELOCITIES = {{ implicitation_velocity }} /default (value < 0.5 makes unstable) +INITIAL GUESS FOR DEPTH = {{ initial_guess_h }} /default (choice 0,1 or 2) speeds up computation +/MAXIMUM NUMBER OF ITERATIONS FOR PROPAGATION = 500 +DYNAMIC PRESSURE IN WAVE EQUATION = YES +/----------------------------------------------------------------------/ +/ LINEAR SOLVERS / +/----------------------------------------------------------------------/ +SOLVER FOR PROPAGATION = {{ solver }} /keuze uit 1-8 +SOLVER FOR PPE = {{ solver_ppe }} +OPTION OF SOLVER FOR PROPAGATION = {{ solver_option }} +/SOLVER FOR DIFFUSION OF TRACERS =1;1 /mudei de 3 para 7 +SOLVER FOR DIFFUSION OF VELOCITIES = {{ solver }} /default choice from 1-8 +SOLVER FOR DIFFUSION OF K-EPSILON = 1 +OPTION OF SOLVER FOR DIFFUSION OF VELOCITIES = 10 +OPTION OF SOLVER FOR DIFFUSION OF TRACERS = 10 +/----------------------------------------------------------------------/ +/ ACCURACY / +/----------------------------------------------------------------------/ +/ACCURACY FOR PROPAGATION = 1.E-3 /default E-6 +/ACCURACY FOR PPE = 1.E-3 /default E-6 +/ACCURACY FOR DIFFUSION OF VELOCITIES = 1.E-3 /default E-6 +/ACCURACY FOR DIFFUSION OF K-EPSILON = 1.E-8 +/ACCURACY FOR DIFFUSION OF TRACERS = 1.E-8 +/ACCURACY FOR DIFFUSION OF SEDIMENT = 1.E-8 \ No newline at end of file diff --git a/pyposeidon/misc/telemac3d.json b/pyposeidon/misc/telemac3d.json index b919fc23..3b51e0c7 100644 --- a/pyposeidon/misc/telemac3d.json +++ b/pyposeidon/misc/telemac3d.json @@ -1,63 +1,92 @@ -{ - "fortran_file": "user_fortran", - "geo_file": "Global_10km_100km.slf", - "cli_file": "Global_10km_100km_t.cli", - "out_3D_file": "res.3d.slf", - "out_2D_file": "res.2d.slf", - "formatted_data_file_1": "tsunamis.txt", +{"params": + { + "geo_file": "geo.slf", + "cli_file": "geo.cli", + "out_3D_file": "results_3D.slf", + "out_2D_file": "results_2D.slf", + "out_1D_file_2D": "results_1D_2D.slf", + "out_1D_file_3D": "results_1D_3D.slf", + "station_coords": "station.in", + "monitor": false, + "inp_wind_file": "input_wind.slf", + "hotstart": true, + "restart_file": "restart_2D.slf", + "restart_tstep": -1, "fortran": false, - "debugger": 0, - "title": "TELEMAC 3D MODEL", - "variables_3d_graphics": "Z,U,V,W", - "variables_2d_graphics": "U,V,H,S", - "graphic_printout_period": 10, - "listing_printout_period": 10, - "time_step": 60, - "number_of_time_steps": 2000, - "checking_mesh": false, - "nonlinearities": false, - "no_subiter": 20, - "original_date_of_time": "2011;3;11", - "original_hour_of_time": "05;46;0", - "number_of_drogues": 2, - "printout_period_drogues": 60, - "drogues_file": "drogues.dat", + "title": "TELEMAC 2D Model", + "ncsize": 1, + "tstep_graph": 12, + "tstep_list": 6, + "tstep": 300, + "duration": "None", + "datestart": "None", + "timestart": "None", "mass_balance": true, - "law_of_bottom_friction": 5, - "friction_coefficient_bottom": 0.01, - "tide_generating_force": true, - "law_of_bottom_friction_2": 3, - "friction_coefficient_bottom_2": 60.0, - "mesh_transformation": 1, + "no_tracers": 1, + "computation_continued": false, + "previous_computation_file": "placeholder.slf", + "initial_conditions": "ZERO ELEVATION", + "spherical_coords": true, + "spatial_proj": 3, + "result_ll": true, + "lon_orig": 0, + "lat_orig": 0, + "geo_sys": 5, + "zone_no": 33, + "friction_law": 5, + "friction_coef": 0.03, + "friction_law_boundaries": 0, + "friction_coef_boundaries": 40, + "tide_generating_force": false, + "mesh_transformation":1, + "horizontal_levels": 5, "coriolis": true, - "initial_conditions": "SPECIAL", - "spherical_coordinates": true, - "spatial_projection_type": 3, - "geographic_system": 1, - "result_file_in_longitude_latitude": true, - "scheme_for_advection_of_depth": 5, - "scheme_for_advection_of_velocities": 14, - "accuracy_for_propagation": 1.0E-3, - "accuracy_for_diffusion_of_velocities": 1.0E-3, - "accuracy_for_ppe": 1.0E-3, - "max_iterations_advection_schemes": 200, - "max_iterations_propagation": 300, - "max_iterations_diffusion_velocities": 200, - "max_iterations_ppe": 200, - "max_iterations_diffusion_k_epsilon": 200, - "solver_for_ppe": 6, - "solver_for_propagation": 7, - "option_solver_for_propagation": 4, - "implicitation_for_depth": 0.6, - "implicitation_for_velocities": 0.6, - "coefficient_horizontal_diffusion_velocities": 1.0, - "coefficient_vertical_diffusion_velocities": 1.0, - "free_surface_gradient_compatibility": 0.5, - "number_of_horizontal_levels": 2, - "number_of_bottom_smoothings": 1, - "tidal_flats": true, - "minimal_value_for_depth": -10.0, - "treatment_of_negative_depths": 2, - "treatment_on_tidal_flats_for_velocities": 0, - "option_for_treatment_of_tidal_flats": 1 -} + "water_density": 1025, + "turb_model": 1, + "velocity_diffusivity": 1.0, + "no_smoothings": 0, + "wind": true, + "pressure": true, + "wind_type": 3, + "wind_coef": 3.4E-6, + "depth_threshold_wind": 1, + "tsunami": false, + "tsunami_fault": "100.;210000.;75000.;13.6;13.;36.;13.;0.;0.;3.", + "adv_u_v": true, + "diff_velocity": true, + "preconditioning": 2, + "matrix_storage": 3, + "info_solver": true, + "solver": 7, + "solver_ppe": 6, + "solver_option": 4, + "type_advection": "13;13", + "supg_option": "0;0", + "propagation": true, + "solver_accuracy": "1.E-5", + "matrix_vector_product": 1, + "mass_lumping": 1, + "discretizations_space": "11;11", + "surface_gradient_compatibility": 0.05, + "implicitation_depth": 0.95, + "implicitation_velocity": 0.95, + "initial_guess_u": 2, + "initial_guess_h": 2, + "tidal_boundary_conditions": 1, + "liquid_boundaries": 2, + "tidal_database": 2, + "db1_tide": "TPXO/h_LOCAL", + "db2_tide": "TPXO/uv_LOCAL", + "minor_constituents_inference": true, + "tidal_flats": false, + "tidal_flats_option": 1, + "negative_depths_treatment": 2, + "diffusion_velocities_option": 1, + "continuity_correction": true, + "tracer": false, + "source_x": -266565, + "source_y": 232753, + "source_flow": 1, + "tracer_values": 1000000 + } +} \ No newline at end of file diff --git a/pyposeidon/telemac.py b/pyposeidon/telemac.py index 1cd86a2a..4858724a 100644 --- a/pyposeidon/telemac.py +++ b/pyposeidon/telemac.py @@ -34,7 +34,7 @@ from pyposeidon.paths import DATA_PATH from pyposeidon.utils.get_value import get_value from pyposeidon.utils.converter import myconverter -from pyposeidon.utils.cpoint import closest_n_points +from pyposeidon.utils.cpoint import find_nearest_nodes from pyposeidon.utils import data from pyposeidon.utils.norm import normalize_column_names from pyposeidon.utils.norm import normalize_varnames @@ -194,14 +194,24 @@ def write_netcdf(ds, outpath): def extract_t_elev_2D( - ds: xr.Dataset, x: float, y: float, var: str = "elev", xstr: str = "longitude", ystr: str = "latitude" + ds: xr.Dataset, + x: float, + y: float, + var: str = "elev", + xstr: str = "longitude", + ystr: str = "latitude", + max_dist: float = 1000, ): lons, lats = ds[xstr].values, ds[ystr].values - indx, _ = closest_n_points(np.array([x, y]).T, 1, np.array([lons, lats]).T) - ds_ = ds.isel(node=indx[0]) - elev_ = ds_[var].values + mesh = pd.DataFrame(np.vstack([x, y]).T, columns=["lon", "lat"]) + points = pd.DataFrame(np.vstack([lons, lats]).T, columns=["lon", "lat"]) + df = find_nearest_nodes(mesh, points, 1) + df = df[df.distance < max_dist] + indx = df["mesh_index"] + ds_ = ds.isel(node=indx.values[0]) + out_ = ds_[var].values t_ = [pd.Timestamp(ti) for ti in ds_.time.values] - return pd.Series(elev_, index=t_), float(ds_[xstr]), float(ds_[ystr]) + return pd.Series(out_, index=t_), float(ds_[xstr]), float(ds_[ystr]) # Function to subset ERA data based on the mesh extent @@ -1098,7 +1108,7 @@ def run(self, api=True, **kwargs): return if self.fortran: - user_fortran = 'user_fortran' + user_fortran = "user_fortran" else: user_fortran = None @@ -1374,7 +1384,6 @@ def results(self, **kwargs): if self.monitor: logger.info("export observations file\n") - # idx = stations["gindex"] # not need for now res_1D = os.path.join(path, "results_1D.slf") xc = self.slf_to_xarray(res_1D, res_type="1D") @@ -1426,50 +1435,39 @@ def set_obs(self, **kwargs): logger.warning("no mesh available skipping \n") return - gpoints = np.array( - list( - zip( - self.mesh.Dataset.SCHISM_hgrid_node_x.values, - self.mesh.Dataset.SCHISM_hgrid_node_y.values, - ) - ) + mesh = pd.DataFrame( + np.array([self.mesh.Dataset.SCHISM_hgrid_node_x.values, self.mesh.Dataset.SCHISM_hgrid_node_y.values]).T, + columns=["lon", "lat"], ) + points = pd.DataFrame(np.array([tgn.longitude.values, tgn.latitude.values]).T, columns=["lon", "lat"]) + df = find_nearest_nodes(mesh, points, 1) + df = df[df.distance < max_dist] - coords = np.array([tgn.longitude.values, tgn.latitude.values]).T - cp, mask = closest_n_points(coords, 1, gpoints, max_dist) - mesh_index = cp - stations = gpoints[cp] - - if len(stations) == 0: + if len(df) == 0: logger.warning("no observations available\n") - stations = pd.DataFrame(stations, columns=["lon", "lat"]) - stations["z"] = 0 - stations.index += 1 - stations["gindex"] = mesh_index - stations["unique_id"] = stations.index - stations[id_str] = tgn[id_str].values[mask] - stations["longitude"] = stations.lon.values[mask] - stations["latitude"] = stations.lat.values[mask] + df["z"] = 0 + df.index += 1 + df["unique_id"] = df.index + df[id_str] = tgn[id_str].values + # convert to MERCATOR coordinates # dirty fix (this needs to be fixed in TELEMAC directly) - x, y = longlat2spherical(stations["longitude"], stations["latitude"],0,0) - stations["x"] = x - stations["y"] = y - - self.stations_mesh_id = stations + x, y = longlat2spherical(df["lon"], df["lat"], 0, 0) + df["x"] = x + df["y"] = y logger.info("write out stations.csv file \n") - tgn[mask].to_csv(os.path.join(path, "stations.csv"), index=False) + tgn.to_csv(os.path.join(path, "stations.csv"), index=False) logger.info("write out stations.in file \n") # output to file with open(os.path.join(path, "station.in"), "w") as f: - f.write(f"1 {stations.shape[0]}\n") # 1st line: number of periods and number of points + f.write(f"1 {df.shape[0]}\n") # 1st line: number of periods and number of points f.write( f"{0 + offset} {int(self.params['duration']) + offset} {self.params['tstep']}\n" ) # 2nd line: period 1: start time, end time and interval (in seconds) - stations.loc[:, ["x", "y", "unique_id", id_str]].to_csv( + df.loc[:, ["x", "y", "unique_id", id_str]].to_csv( f, header=None, sep=" ", index=False ) # 3rd-10th line: output points; x coordinate, y coordinate, station number, and station name diff --git a/pyposeidon/utils/cfl.py b/pyposeidon/utils/cfl.py index e769844c..7100d2b3 100644 --- a/pyposeidon/utils/cfl.py +++ b/pyposeidon/utils/cfl.py @@ -103,9 +103,7 @@ def parse_hgrid(path: os.PathLike[str] | str) -> dict[str, T.Any]: no_closed_boundaries = int(fd.readline().split(b"=")[0].strip()) total_closed_boundary_nodes = int(fd.readline().split(b"=")[0].strip()) for i in range(no_closed_boundaries): - no_nodes_in_boundary, boundary_type = map( - int, (fd.readline().split(b"=")[0].strip().split(b" ")) - ) + no_nodes_in_boundary, boundary_type = map(int, (fd.readline().split(b"=")[0].strip().split(b" "))) boundary_nodes = np.fromiter( fd, count=no_nodes_in_boundary, diff --git a/pyposeidon/utils/cpoint.py b/pyposeidon/utils/cpoint.py index 754fac74..8ef4cf47 100644 --- a/pyposeidon/utils/cpoint.py +++ b/pyposeidon/utils/cpoint.py @@ -101,6 +101,4 @@ def find_nearest_nodes( .assign(distance=(distances.flatten() * earth_radius)) .reset_index(names=["mesh_index"]) ) - return pd.concat( - (points.loc[points.index.repeat(k)].reset_index(drop=True), closest_nodes), axis="columns" - ) + return pd.concat((points.loc[points.index.repeat(k)].reset_index(drop=True), closest_nodes), axis="columns") diff --git a/pyposeidon/utils/data.py b/pyposeidon/utils/data.py index 25423231..eb1424a0 100644 --- a/pyposeidon/utils/data.py +++ b/pyposeidon/utils/data.py @@ -15,7 +15,6 @@ from pyposeidon.mesh import r2d import pyposeidon.model as pm from pyposeidon.tools import flat_list -from pyposeidon.utils.cpoint import closest_n_points import xarray as xr import glob import logging @@ -39,17 +38,6 @@ def get_output(solver_name: str, **kwargs): return instance -def extract_t_elev_2D( - ds: xr.Dataset, x: float, y: float, var: str = "elev", xstr: str = "longitude", ystr: str = "latitude" -): - lons, lats = ds[xstr].values, ds[ystr].values - indx, _ = closest_n_points(np.array([x, y]).T, 1, np.array([lons, lats]).T) - ds_ = ds.isel(node=indx[0]) - elev_ = ds_[var].values - t_ = [pd.Timestamp(ti) for ti in ds_.time.values] - return pd.Series(elev_, index=t_), float(ds_[xstr]), float(ds_[ystr]) - - class D3DResults: def __init__(self, **kwargs): rpath = kwargs.get("rpath", "./d3d/") @@ -226,11 +214,13 @@ def __init__(self, **kwargs): 1. there are 1D AND 2D results, they need to be addressed separately 2. selafin are readable directly in xarray, so we can skip the conversion step """ + from pyposeidon.telemac import extract_t_elev_2D rpath = kwargs.get("rpath", "./telemac/") res_type = kwargs.get("result_type", "2D") convert = kwargs.get("convert_results", True) extract_TS = kwargs.get("extract_TS", False) station_id_str = kwargs.get("id_str", "ioc_code") + max_dist = kwargs.get("max_dist", 1000) if res_type not in ["1D", "2D"]: raise ValueError("results_type needs to be '1D' or '2D'!") @@ -248,14 +238,14 @@ def __init__(self, **kwargs): datai = [] - tag = kwargs.get("tag", "telemac2d") + module = kwargs.get("module", "telemac2d") misc = kwargs.get("misc", {}) for folder in self.folders: logger.info(" Combining output for folder {}\n".format(folder)) - with open(folder + "/" + tag + "_model.json", "r") as f: + with open(folder + "/" + module + "_model.json", "r") as f: data = json.load(f) data = pd.json_normalize(data, max_level=0) info = data.to_dict(orient="records")[0] @@ -266,7 +256,15 @@ def __init__(self, **kwargs): # read from output file if convert: xdat = glob.glob(folder + "/outputs/" + out_default) - var, model_xstr, model_ystr = "elev", "longitude", "latitude" + model_xstr, model_ystr = "longitude", "latitude" + if module == "telemac2d": + var = "elev" + elif module == "telemac3d": + var = "elev" + elif module == "tomawac": + var = "hm0" + else: + raise ValueError(f"module {module} not supported!") if len(xdat) > 0: datai.append(xdat) # append to list @@ -284,7 +282,15 @@ def __init__(self, **kwargs): else: # read from selafin file xdat = glob.glob(folder + f"/results_{res_type}.slf") datai.append(xdat) # append to list - var, model_xstr, model_ystr = "S", "x", "y" + model_xstr, model_ystr = "x", "y" + if module == "telemac2d": + var = "S" + elif module == "telemac3d": + var = "Z" + elif module == "tomawac": + var = "WH" + else: + raise ValueError(f"module {module} not supported!") if not any(datai): logger.warning("no output files found") @@ -319,6 +325,6 @@ def __init__(self, **kwargs): for i_s, id_ in enumerate(stations[station_id_str]): s = stations[stations[station_id_str] == id_] mod, mlon, mlat = extract_t_elev_2D( - self.Dataset, s.longitude.values[0], s.latitude.values[0], var, model_xstr, model_ystr + self.Dataset, s.longitude.values[0], s.latitude.values[0], var, model_xstr, model_ystr, max_dist=max_dist ) mod.to_frame().to_parquet(f"{rpath}{id_}.parquet") diff --git a/pyposeidon/utils/norm.py b/pyposeidon/utils/norm.py index 5f84daab..163f3057 100644 --- a/pyposeidon/utils/norm.py +++ b/pyposeidon/utils/norm.py @@ -45,7 +45,8 @@ "U": "u", "V": "v", "S": "elev", - "HM0": "hm0", + "Z": "elev", + "WH": "hm0", "DIRM": "dir", "TM01": "tm01", "TM02": "tm02", diff --git a/pyposeidon/utils/obs.py b/pyposeidon/utils/obs.py index b9ef34cc..ece45fd1 100644 --- a/pyposeidon/utils/obs.py +++ b/pyposeidon/utils/obs.py @@ -1,4 +1,5 @@ """ Observational Data retrieval """ + from __future__ import annotations import itertools @@ -152,14 +153,27 @@ def serialize_stations( msg = f"stations must have these columns too: {mandatory_cols.difference(df_cols)}" raise ValueError(msg) # - basic_cols = ["mesh_lon", "mesh_lat", "z", "separator", "unique_id", "mesh_index", "lon", "lat", "depth", "distance"] + basic_cols = [ + "mesh_lon", + "mesh_lat", + "z", + "separator", + "unique_id", + "mesh_index", + "lon", + "lat", + "depth", + "distance", + ] station_in = stations.assign( z=0, separator="\t!\t", ) - station_in = station_in.set_index(station_in.index +1) + station_in = station_in.set_index(station_in.index + 1) station_in = station_in[basic_cols] with open(f"{path}", "w") as fd: - fd.write(f"{schism_station_flag.strip()}\t ! https://schism-dev.github.io/schism/master/input-output/optional-inputs.html#stationin-bp-format\n") + fd.write( + f"{schism_station_flag.strip()}\t ! https://schism-dev.github.io/schism/master/input-output/optional-inputs.html#stationin-bp-format\n" + ) fd.write(f"{len(station_in)}\t ! number of stations\n") station_in.to_csv(fd, header=None, sep=" ", float_format="%.10f") diff --git a/pyposeidon/utils/pplot.py b/pyposeidon/utils/pplot.py index 8f7af645..de87d4fe 100644 --- a/pyposeidon/utils/pplot.py +++ b/pyposeidon/utils/pplot.py @@ -23,6 +23,7 @@ import sys import os + # from pyposeidon.tools import to_geodataframe ffmpeg = sys.exec_prefix + "/bin/ffmpeg" diff --git a/tests/test_telemac.py b/tests/test_telemac.py index 54e2bf7f..63f45053 100644 --- a/tests/test_telemac.py +++ b/tests/test_telemac.py @@ -7,6 +7,7 @@ import pathlib import pyposeidon +from pyposeidon.utils import data import pytest from . import DATA_DIR @@ -78,6 +79,21 @@ }, } +case4 = { # test does not work with telemac3d: mesh quality is too bad + "solver_name": "telemac", + "mesh_file": MESH_FILE, + "module": "telemac3d", + "start_date": "2011-1-1 0:0:0", + "time_frame": "12H", + "meteo_source": [(DATA_DIR / "era5.grib").as_posix()], # meteo file + "dem_source": DEM_FILE, + "update": ["all"], # update only meteo, keep dem + "parameters": { + "dt": 50, + "horizontal_levels": 5, + }, +} + @pytest.mark.telemac @pytest.mark.parametrize("case", [case0, case1, case2, case3]) @@ -90,21 +106,26 @@ def test_telemac(tmpdir, case): b.create() b.mesh.Dataset.type[:] = "closed" b.output() + b.set_obs() b.save() b.run() - b.results() + case["result_type"] = "2D" + case["convert_results"] = True + case["max_dist"] = 5000 + res = data.get_output(**case) zarr_tar = b.rpath + "/outputs/out_2D.zarr.tar" assert os.path.exists(zarr_tar) a = pyposeidon.model.read(rpath + b.module + "_model.json") # read model a.create() a.mesh.Dataset.type[:] = "closed" a.output() + a.set_obs() a.save() a.run() - a.results() - zarr_tar = a.rpath + "/outputs/out_2D.zarr.tar" + case["result_type"] = "2D" + case["extract_TS"] = True + res = data.get_output(**case) res = a.rpath + "/results_2D.slf" - assert os.path.exists(zarr_tar) ds = xr.open_dataset(res, engine="selafin") if "WH" in ds.variables: max_WH = ds.WH.max().values diff --git a/tests/utils/test_cpoint.py b/tests/utils/test_cpoint.py index e0942650..c26b969b 100644 --- a/tests/utils/test_cpoint.py +++ b/tests/utils/test_cpoint.py @@ -11,19 +11,23 @@ @pytest.fixture(scope="session") def mesh_nodes(): - return pd.DataFrame({ - "lon": [0, 10, 20], - "lat": [0, 5, 0], - }) + return pd.DataFrame( + { + "lon": [0, 10, 20], + "lat": [0, 5, 0], + } + ) @pytest.fixture(scope="session") def points(): - return pd.DataFrame({ - "lon": [1, 11, 21, 2], - "lat": [1, 4, 1, 2], - "id": ["a", "b", "c", "d"], - }) + return pd.DataFrame( + { + "lon": [1, 11, 21, 2], + "lat": [1, 4, 1, 2], + "id": ["a", "b", "c", "d"], + } + ) @pytest.fixture(scope="session") @@ -41,7 +45,7 @@ def test_find_nearest_nodes(mesh_nodes, points): assert nearest_nodes.distance.max() < 320_000 -@pytest.mark.parametrize("k", [pytest.param(2, id='2 points'), pytest.param(3, id='3 points')]) +@pytest.mark.parametrize("k", [pytest.param(2, id="2 points"), pytest.param(3, id="3 points")]) def test_find_nearest_nodes_multiple_points_and_pass_tree_as_argument(mesh_nodes, points, k, ball_tree): nearest_nodes = find_nearest_nodes(mesh_nodes, points, k=k, tree=ball_tree) assert isinstance(nearest_nodes, pd.DataFrame) diff --git a/tests/utils/test_obs.py b/tests/utils/test_obs.py index 47339538..d1b8718b 100644 --- a/tests/utils/test_obs.py +++ b/tests/utils/test_obs.py @@ -17,17 +17,19 @@ def test_serialize_stations(tmp_path): 3 20.0000000000 0.0000000000 0 ! c 2 21.0000000000 1.0000000000 1 157249.3812719441 """ ) - stations = pd.DataFrame({ - 'lon': [1., 11., 21.], - 'lat': [1., 4., 1.], - 'unique_id': ["a", "b", "c"], - 'extra_col': ["AA", "BB", "CC"], - 'mesh_index': [0, 1, 2], - 'mesh_lon': [0., 10., 20.], - 'mesh_lat': [0., 5., 0.], - 'distance': [157249.38127194397, 157010.16264060183, 157249.38127194406], - 'depth': [3, 5, 1], - }) + stations = pd.DataFrame( + { + "lon": [1.0, 11.0, 21.0], + "lat": [1.0, 4.0, 1.0], + "unique_id": ["a", "b", "c"], + "extra_col": ["AA", "BB", "CC"], + "mesh_index": [0, 1, 2], + "mesh_lon": [0.0, 10.0, 20.0], + "mesh_lat": [0.0, 5.0, 0.0], + "distance": [157249.38127194397, 157010.16264060183, 157249.38127194406], + "depth": [3, 5, 1], + } + ) path = tmp_path / "station.in" serialize_stations(stations, path) contents = path.read_text()