├── tests ├── data │ ├── EmptyFile.nc │ ├── written_files │ │ └── .gitkeep │ ├── 1D2D_net.nc │ ├── OneMesh2D.nc │ ├── ResultFile.nc │ └── AllUGridEntities.nc ├── utils │ ├── src │ │ └── Utils.cpp │ ├── include │ │ └── TestUtils │ │ │ ├── Definitions.hpp.in │ │ │ └── Utils.hpp │ └── CMakeLists.txt ├── CMakeLists.txt └── api │ └── CMakeLists.txt ├── .gitattributes ├── scripts ├── docker │ ├── requirements.txt │ ├── error.sh │ ├── main.sh │ ├── downlaod_sonar_tools.sh │ ├── Dockerfile │ ├── dnf_install.sh │ ├── utilities.sh │ ├── build_and_test.sh │ └── sonar_scanner.sh ├── append_target_framework_to_output_path_in_csproj.py ├── download_sonar_tools.py ├── get_package_ids_from_directory_packages_props.py └── doxygen_ci.py ├── libs ├── UGridNET │ ├── dll │ │ ├── src │ │ │ ├── AssemblyInfo.cs │ │ │ ├── ByteArrayExtensions.cs │ │ │ ├── UGridNETException.cs │ │ │ ├── ContactsExtensions.cs │ │ │ ├── Mesh1DExtensions.cs │ │ │ ├── IntPtrHelpers.cs │ │ │ ├── DisposableMesh1D.cs │ │ │ ├── Network1DExtensions.cs │ │ │ ├── Mesh2DExtensions.cs │ │ │ ├── DisposableNativeObject.cs │ │ │ ├── IntPtrExtensions.cs │ │ │ ├── StringExtensions.cs │ │ │ └── ProjectedCoordinateSystem.cs │ │ ├── Directory.Packages.props │ │ └── CMakeLists.txt │ ├── nuget │ │ ├── README.md │ │ ├── Deltares.UGridNET.nuspec.in │ │ ├── Deltares.UGridNET.targets │ │ └── CMakeLists.txt │ ├── CMakeLists.txt │ ├── test │ │ ├── Directory.Packages.props │ │ ├── src │ │ │ ├── TestUtilities.cs │ │ │ ├── TopologyExtensionsTests.cs │ │ │ ├── UGridNETExceptionTests.cs │ │ │ ├── ByteArrayExtensionsTests.cs │ │ │ ├── IntPtrExtensionsTests.cs │ │ │ ├── IntPtrHelpersTests.cs │ │ │ ├── SWIGTests.cs │ │ │ └── StringExtensionsTests.cs │ │ └── CMakeLists.txt │ ├── config │ │ ├── NuGet.config │ │ └── Directory.Build.props.in │ ├── projs │ │ ├── UnitTestConsumer_VS-17-2022 │ │ │ ├── Directory.Packages.props │ │ │ ├── NuGet.config │ │ │ ├── UnitTestConsumer │ │ │ │ └── UnitTestConsumer.csproj │ │ │ └── UnitTestConsumer.sln │ │ └── UnitTestConsumer_VS-16-2019 │ │ │ ├── Directory.Packages.props │ │ │ ├── NuGet.config │ │ │ ├── UnitTestConsumer │ │ │ └── UnitTestConsumer.csproj │ │ │ └── UnitTestConsumer.sln │ ├── SWIG │ │ ├── interface │ │ │ └── UGrid.i │ │ └── CMakeLists.txt │ └── tools │ │ └── CMakeLists.txt ├── CMakeLists.txt ├── UGridAPI │ ├── include │ │ └── UGridAPI │ │ │ ├── MeshLocations.hpp │ │ │ ├── UGridState.hpp │ │ │ ├── Contacts.hpp │ │ │ ├── Network1D.hpp │ │ │ ├── Mesh1D.hpp │ │ │ └── Mesh2D.hpp │ └── CMakeLists.txt └── UGrid │ ├── include │ └── UGrid │ │ ├── UGridVarAttributeStringBuilder.hpp │ │ ├── Mesh2D.hpp │ │ ├── Mesh1D.hpp │ │ ├── Constants.hpp │ │ ├── Network1D.hpp │ │ └── Contacts.hpp │ └── CMakeLists.txt ├── .editorconfig ├── docs ├── main_page.md ├── stylesheet.css └── CMakeLists.txt ├── .clang-format ├── .github └── workflows │ ├── spell-check.yml │ ├── doxy-check.yml │ ├── doxy-build.yml │ └── style-check.yml ├── cmake ├── git_helpers.cmake ├── user_config_options.cmake ├── cached_globals.cmake ├── fetch_contents.cmake ├── compiler_config.cmake ├── install_tools.cmake └── find_packages.cmake ├── package ├── nuget │ ├── Deltares.UGrid.Release.nuspec.in │ ├── Deltares.UGrid.Development.nuspec.in │ └── Deltares.UGrid.targets ├── CMakeLists.txt ├── Version │ ├── Version.hpp │ └── Version.hpp.in └── version.rc.in ├── CMakeLists.txt └── README.md /tests/data/EmptyFile.nc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/utils/src/Utils.cpp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/data/written_files/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | . !text !filter !merge !diff 2 | -------------------------------------------------------------------------------- /scripts/docker/requirements.txt: -------------------------------------------------------------------------------- 1 | requests==2.32.3 2 | -------------------------------------------------------------------------------- /tests/data/1D2D_net.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Deltares/UGrid/main/tests/data/1D2D_net.nc -------------------------------------------------------------------------------- /tests/data/OneMesh2D.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Deltares/UGrid/main/tests/data/OneMesh2D.nc -------------------------------------------------------------------------------- /tests/data/ResultFile.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Deltares/UGrid/main/tests/data/ResultFile.nc -------------------------------------------------------------------------------- /tests/data/AllUGridEntities.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Deltares/UGrid/main/tests/data/AllUGridEntities.nc -------------------------------------------------------------------------------- /scripts/docker/error.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | error() { 4 | local exit_code="$?" 5 | echo "$(basename "$0")": "$1" 6 | exit $exit_code 7 | } 8 | -------------------------------------------------------------------------------- /libs/UGridNET/dll/src/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleToAttribute("UGridNET.Tests")] 4 | [assembly: InternalsVisibleToAttribute("UnitTestConsumer")] -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Visual Studio generated .editorconfig file with C++ settings. 2 | 3 | [*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}] 4 | vc_generate_documentation_comments = doxygen_triple_slash 5 | -------------------------------------------------------------------------------- /tests/utils/include/TestUtils/Definitions.hpp.in: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #define TEST_FOLDER std::string("@TEST_FOLDER@/data") 4 | #define TEST_WRITE_FOLDER std::string("@TEST_FOLDER@/data/written_files") -------------------------------------------------------------------------------- /docs/main_page.md: -------------------------------------------------------------------------------- 1 | Main Page {#mainpage} 2 | ============ 3 | 4 | - [API documentation](@ref ugridapi) 5 | - [**Python wrapper**](https://deltares.github.io/ugridpy/) 6 | - [Internal documentation](@ref ugrid) 7 | -------------------------------------------------------------------------------- /libs/UGridNET/nuget/README.md: -------------------------------------------------------------------------------- 1 | # UGridNET 2 | 3 | UGridNet is a SWIG-generated .NET wrapper around the [UGrid library](https://github.com/Deltares/UGrid). The purpose of this library is to read and write files following the UGrid format. 4 | -------------------------------------------------------------------------------- /libs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Add UGrid static lib 2 | add_subdirectory(UGrid) 3 | 4 | # Add UGridAPI dynamic lib 5 | add_subdirectory(UGridAPI) 6 | 7 | # Add UGridNET 8 | if(BUILD_DOTNET_WRAPPER) 9 | add_subdirectory(UGridNET) 10 | endif() -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(TEST_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}") 2 | configure_file("${CMAKE_CURRENT_SOURCE_DIR}/utils/include/TestUtils/Definitions.hpp.in" "${CMAKE_CURRENT_SOURCE_DIR}/utils/include/TestUtils/Definitions.hpp") 3 | 4 | add_subdirectory(utils) 5 | 6 | add_subdirectory(api) 7 | -------------------------------------------------------------------------------- /libs/UGridNET/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Download necessary tools 2 | add_subdirectory(tools) 3 | 4 | # Add UGrid (SWIG-based) dynamic lib 5 | add_subdirectory(SWIG) 6 | 7 | # Add UGridNET dynamic lib 8 | add_subdirectory(dll) 9 | 10 | # Add the UGridNET tests 11 | add_subdirectory(test) 12 | 13 | # Add nuget config 14 | add_subdirectory(nuget) 15 | -------------------------------------------------------------------------------- /libs/UGridNET/dll/Directory.Packages.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: LLVM 3 | UseTab: Never 4 | IndentWidth: 4 5 | TabWidth: 4 6 | BreakBeforeBraces: Allman 7 | AllowShortIfStatementsOnASingleLine: false 8 | AllowShortLambdasOnASingleLine: Inline 9 | IndentCaseLabels: false 10 | ColumnLimit: 0 11 | AccessModifierOffset: -4 12 | NamespaceIndentation: All 13 | SortIncludes: true 14 | PointerAlignment: Left 15 | ... 16 | -------------------------------------------------------------------------------- /.github/workflows/spell-check.yml: -------------------------------------------------------------------------------- 1 | name: Spell check 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | 8 | jobs: 9 | check: 10 | name: Codespell 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | 17 | - uses: codespell-project/actions-codespell@v2 18 | with: 19 | check_filenames: true 20 | skip: "**/*.i" 21 | -------------------------------------------------------------------------------- /libs/UGridNET/test/Directory.Packages.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /scripts/docker/main.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | export netCDFCxx_DIR=${THIRD_PARTY_INSTALL_DIR}/netcdf_cxx4/lib64/cmake/netCDF/ 6 | export ZLIB_ROOT=${THIRD_PARTY_INSTALL_DIR}/zlib/ 7 | 8 | source /workspace/scripts/docker/error.sh 9 | source /workspace/scripts/docker/utilities.sh 10 | source /workspace/scripts/docker/build_and_test.sh 11 | if [[ "${RUN_SONAR_SCANNER}" = "true" ]]; then 12 | source /workspace/scripts/docker/sonar_scanner.sh 13 | fi 14 | -------------------------------------------------------------------------------- /libs/UGridNET/config/NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /scripts/docker/downlaod_sonar_tools.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | source /workspace/scripts/docker/utilities.sh 6 | 7 | print_text_box "Download sonar tools" 8 | python3 /workspace/scripts/download_sonar_tools.py --save_dir ${SONAR_SAVE_DIR} 9 | chmod +x ${SONAR_SAVE_DIR}/build-wrapper-linux-x86/build-wrapper-linux-x86-64 10 | chmod +x ${SONAR_SAVE_DIR}/sonar-scanner/bin/sonar-scanner 11 | chmod +x ${SONAR_SAVE_DIR}/sonar-scanner/jre/bin/java 12 | chmod +x ${SONAR_SAVE_DIR}/sonar-scanner/jre/lib/jspawnhelper 13 | -------------------------------------------------------------------------------- /libs/UGridNET/projs/UnitTestConsumer_VS-17-2022/Directory.Packages.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /libs/UGridNET/projs/UnitTestConsumer_VS-16-2019/Directory.Packages.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.github/workflows/doxy-check.yml: -------------------------------------------------------------------------------- 1 | name: Check documentation 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | 8 | jobs: 9 | check: 10 | name: DoxygenCheck 11 | 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | 16 | - name: Set up Python 17 | uses: actions/setup-python@v5 18 | with: 19 | python-version: 3.11 20 | 21 | - name: Install doxygen 22 | run: sudo apt-get install doxygen 23 | 24 | - name: Check doxygen 25 | run: | 26 | # Set error mode. Makes bash bail on first non-zero exit code 27 | set -e 28 | python3 scripts/doxygen_ci.py --fail-with-warnings 29 | -------------------------------------------------------------------------------- /cmake/git_helpers.cmake: -------------------------------------------------------------------------------- 1 | # Gets the current branch name 2 | function(get_current_branch_name branch_name) 3 | execute_process( 4 | COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD 5 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 6 | OUTPUT_VARIABLE GIT_BRANCH_NAME 7 | OUTPUT_STRIP_TRAILING_WHITESPACE 8 | COMMAND_ERROR_IS_FATAL LAST 9 | ) 10 | set(${branch_name} "${GIT_BRANCH_NAME}" PARENT_SCOPE) 11 | endfunction() 12 | 13 | # Checks if the branch name is "main" or starts with "release/" 14 | function(is_main_or_release_branch branch_name result) 15 | if("${branch_name}" STREQUAL "main" OR "${branch_name}" MATCHES "^release/") 16 | set(${result} true PARENT_SCOPE) 17 | else() 18 | set(${result} false PARENT_SCOPE) 19 | endif() 20 | endfunction() -------------------------------------------------------------------------------- /.github/workflows/doxy-build.yml: -------------------------------------------------------------------------------- 1 | name: Deploy documentation 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | 7 | jobs: 8 | check: 9 | name: DoxygenDeploy 10 | 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v4 15 | 16 | - name: Set up Python 17 | uses: actions/setup-python@v5 18 | with: 19 | python-version: 3.11 20 | 21 | - name: Install doxygen 22 | run: sudo apt-get install doxygen 23 | 24 | - name: Run doxygen 25 | run: python3 scripts/doxygen_ci.py 26 | 27 | - name: Deploy to github pages 28 | uses: peaceiris/actions-gh-pages@v3 29 | with: 30 | github_token: ${{ secrets.GITHUB_TOKEN }} 31 | publish_dir: ./build/docs/html 32 | -------------------------------------------------------------------------------- /libs/UGridNET/SWIG/interface/UGrid.i: -------------------------------------------------------------------------------- 1 | #define UGRID_API 2 | 3 | %include "windows.i" 4 | %include "std_string.i" 5 | %include "std_vector.i" 6 | %include "std_map.i" 7 | %include "std_unordered_map.i" 8 | %include "std_unique_ptr.i" 9 | %include "std_shared_ptr.i" 10 | 11 | %{ 12 | #include "UGridAPI/Mesh1D.hpp" 13 | #include "UGridAPI/Mesh2D.hpp" 14 | #include "UGridAPI/MeshLocations.hpp" 15 | #include "UGridAPI/Contacts.hpp" 16 | #include "UGridAPI/Network1D.hpp" 17 | #include "UGridAPI/UGrid.hpp" 18 | %} 19 | 20 | %include "UGridTypemaps.i" 21 | 22 | %include "UGridAPI/Mesh1D.hpp" 23 | %include "UGridAPI/Mesh2D.hpp" 24 | %include "UGridAPI/MeshLocations.hpp" 25 | %include "UGridAPI/Contacts.hpp" 26 | %include "UGridAPI/Network1D.hpp" 27 | %include "UGridAPI/UGrid.hpp" 28 | -------------------------------------------------------------------------------- /libs/UGridNET/nuget/Deltares.UGridNET.nuspec.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Deltares.UGridNET 5 | @VERSION@ 6 | Deltares.UGridNET 7 | Stichting Deltares 8 | Stichting Deltares 9 | false 10 | Deltares library for reading/writing UGrid files. 11 | Copyright © Stichting Deltares @COPYRIGHT_YEAR@ 12 | README.md 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /libs/UGridNET/config/Directory.Build.props.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | @PROJECT_NAME@ 4 | @PROJECT_DESCRIPTION@ 5 | Stichting Deltares 6 | Copyright © Stichting Deltares @GLOB_CURRENT_YEAR@ 7 | UGrid 8 | @PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.@PROJECT_VERSION_TWEAK@ 9 | @PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.@PROJECT_VERSION_TWEAK@ 10 | <@PROJECT_DOTNET_TARGET_FRAMEWORKS_TAG@>@PROJECT_DOTNET_TARGET_FRAMEWORKS@ 11 | true 12 | 13 | -------------------------------------------------------------------------------- /package/nuget/Deltares.UGrid.Release.nuspec.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Deltares.UGrid 5 | @PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.@PROJECT_VERSION_TWEAK@ 6 | Deltares 7 | Deltares 8 | Deltares back end for reading and writing UGrid meshes 9 | Copyright 2024 10 | signed 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /package/nuget/Deltares.UGrid.Development.nuspec.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Deltares.UGrid 5 | @PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.@PROJECT_VERSION_TWEAK@-dev 6 | Deltares 7 | Deltares 8 | Deltares back end for reading and writing UGrid meshes 9 | Copyright 2024 10 | development 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /cmake/user_config_options.cmake: -------------------------------------------------------------------------------- 1 | include(CMakeDependentOption) 2 | 3 | # unit testing option 4 | option( 5 | ENABLE_UNIT_TESTING 6 | "Enables building the unit test executables" 7 | ON 8 | ) 9 | 10 | # code coverage option 11 | if(LINUX AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 12 | option( 13 | ENABLE_CODE_COVERAGE 14 | "Generates code coverage statistics." 15 | OFF 16 | ) 17 | endif() 18 | 19 | # option for building .NET targets (only available under Windows) 20 | cmake_dependent_option( 21 | BUILD_DOTNET_WRAPPER 22 | "Configures and builds the C# targets that use code generated by SWIG" 23 | OFF 24 | "WIN32" 25 | OFF 26 | ) 27 | 28 | cmake_dependent_option( 29 | PACK_NUPKG_LOCALLY 30 | "Pack the NuGet package locally. Should be used only to validate the NUPKG locally." 31 | OFF 32 | "BUILD_DOTNET_WRAPPER" 33 | OFF 34 | ) 35 | -------------------------------------------------------------------------------- /libs/UGridNET/projs/UnitTestConsumer_VS-17-2022/NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /libs/UGridNET/tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_SOURCE_DIR}/cmake/install_tools.cmake) 2 | 3 | set(TOOLS_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/tools) 4 | 5 | #install swig 6 | set(SWIG_VERSION 4.2.1) 7 | set(SWIG_INSTALL_PREFIX ${TOOLS_INSTALL_DIR}/swig) 8 | install_swig( 9 | SWIG_VERSION ${SWIG_VERSION} 10 | SWIG_INSTALL_PREFIX ${SWIG_INSTALL_PREFIX} 11 | SWIG_CLEAN FALSE 12 | SWIG_DIR_OUT SWIG_DIR 13 | SWIG_EXECUTABLE_OUT SWIG_EXECUTABLE 14 | ) 15 | set(SWIG_DIR "${SWIG_DIR}" PARENT_SCOPE) 16 | set(SWIG_EXECUTABLE "${SWIG_EXECUTABLE}" PARENT_SCOPE) 17 | 18 | #install nuget 19 | set(NUGET_VERSION "latest") 20 | set(NUGET_INSTALL_PREFIX ${TOOLS_INSTALL_DIR}) 21 | install_nuget( 22 | NUGET_VERSION ${NUGET_VERSION} 23 | NUGET_INSTALL_PREFIX ${NUGET_INSTALL_PREFIX} 24 | NUGET_EXECUTABLE_OUT NUGET_EXECUTABLE 25 | ) 26 | set(NUGET_EXECUTABLE "${NUGET_EXECUTABLE}" PARENT_SCOPE) 27 | -------------------------------------------------------------------------------- /libs/UGridNET/projs/UnitTestConsumer_VS-16-2019/NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /package/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Configure DLL version 2 | configure_file( 3 | ${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in 4 | ${CMAKE_BINARY_DIR}/version.rc @ONLY 5 | ) 6 | 7 | # Configure the nuspec files 8 | configure_file( 9 | ${CMAKE_CURRENT_SOURCE_DIR}/nuget/Deltares.UGrid.Development.nuspec.in 10 | ${CMAKE_BINARY_DIR}/package/nuget/Deltares.UGrid.Development.nuspec @ONLY 11 | ) 12 | 13 | configure_file( 14 | ${CMAKE_CURRENT_SOURCE_DIR}/nuget/Deltares.UGrid.Release.nuspec.in 15 | ${CMAKE_BINARY_DIR}/package/nuget/Deltares.UGrid.Release.nuspec @ONLY 16 | ) 17 | 18 | configure_file( 19 | ${CMAKE_CURRENT_SOURCE_DIR}/nuget/Deltares.UGrid.targets 20 | ${CMAKE_BINARY_DIR}/package/nuget/Deltares.UGrid.targets COPYONLY 21 | ) 22 | 23 | # Configure the version header file 24 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Version/Version.hpp.in 25 | ${CMAKE_CURRENT_SOURCE_DIR}/Version/Version.hpp @ONLY) -------------------------------------------------------------------------------- /package/nuget/Deltares.UGrid.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <_FilesToCopyUGridLibs Include="$(MSBuildThisFileDirectory)..\..\runtimes\**\*"/> 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | <_OriginalFilesUGrid Include="$(MSBuildThisFileDirectory)..\..\runtimes\**\*"/> 14 | <_FilesToCleanUGrid Include="$(OutDir)\%(_OriginalFilesDimrLibs.RecursiveDir)%(_OriginalFilesDimrLibs.FileName)%(_OriginalFilesDimrLibs.Extension)"/> 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /libs/UGridNET/test/src/TestUtilities.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | 5 | 6 | namespace UGridNET.Tests 7 | { 8 | 9 | internal class TestUtilities 10 | { 11 | 12 | public static string GetTestDataPath() 13 | { 14 | string path = Environment.GetEnvironmentVariable("UGRID_TEST_DATA_DIR"); 15 | 16 | // Check if the environment variable is set 17 | if (string.IsNullOrEmpty(path)) 18 | { 19 | throw new InvalidOperationException("The UGRID_TEST_DATA_DIR environment variable is not set."); 20 | } 21 | 22 | // Check if the path is absolute and that it exists 23 | if (!(Path.IsPathRooted(path) && Directory.Exists(path))) 24 | { 25 | throw new InvalidOperationException( 26 | $"The specified UGRID_TEST_DATA_DIR path must be absolute and should exist. UGRID_TEST_DATA_DIR={path}"); 27 | } 28 | 29 | return path; 30 | } 31 | 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /scripts/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM quay.io/pypa/manylinux_2_28_x86_64:latest 2 | 3 | WORKDIR /workspace 4 | 5 | COPY . /workspace 6 | 7 | ENV CLEAN_BUILD="false" 8 | ENV BUILD_TYPE="Release" 9 | ENV VERBOSE_BUILD="false" 10 | 11 | ENV RUN_SONAR_SCANNER="false" 12 | ENV SONAR_TOKEN="" 13 | ENV BRANCH_NAME="" 14 | 15 | RUN chmod +x /workspace/scripts/docker/dnf_install.sh 16 | RUN /workspace/scripts/docker/dnf_install.sh 17 | 18 | ARG SONAR_SAVE_DIR=/sonar 19 | ENV SONAR_SAVE_DIR=${SONAR_SAVE_DIR} 20 | RUN chmod +x /workspace/scripts/docker/downlaod_sonar_tools.sh 21 | RUN /workspace/scripts/docker/downlaod_sonar_tools.sh 22 | 23 | ARG THIRD_PARTY_WORK_DIR=/third_party/work 24 | ARG THIRD_PARTY_INSTALL_DIR=/third_party/install 25 | ENV THIRD_PARTY_INSTALL_DIR=${THIRD_PARTY_INSTALL_DIR} 26 | RUN chmod +x /workspace/scripts/install_netcdf_cxx4.sh 27 | RUN /workspace/scripts/install_netcdf_cxx4.sh \ 28 | --work_dir ${THIRD_PARTY_WORK_DIR} \ 29 | --install_dir ${THIRD_PARTY_INSTALL_DIR} \ 30 | --clean 31 | 32 | ENTRYPOINT ["bash", "/workspace/scripts/docker/main.sh"] 33 | -------------------------------------------------------------------------------- /scripts/docker/dnf_install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | source /workspace/scripts/docker/error.sh 6 | source /workspace/scripts/docker/utilities.sh 7 | 8 | dnf install -y epel-release 9 | dnf config-manager --enable epel 10 | dnf install -y dnf-utils 11 | dnf config-manager --set-enabled powertools 12 | dnf update -y 13 | 14 | dev_toolset="gcc-toolset-12" 15 | 16 | packages=( 17 | "git" 18 | "cmake" 19 | "boost1.78-devel.x86_64" 20 | "m4" 21 | "perl" 22 | "openssl-devel" 23 | "libcurl-devel" 24 | ${dev_toolset} 25 | "doxygen" 26 | "python311" 27 | ) 28 | 29 | for package in "${packages[@]}"; do 30 | col_echo --blue "Installing ${package}..." 31 | dnf install -y "${package}" || error "[dnf] Failed to install ${package}" 32 | done 33 | 34 | dnf clean all 35 | 36 | # enable the gcc toolset 37 | scl enable "${dev_toolset}" bash || error "[scl] Failed to enable ${dev_toolset}" 38 | 39 | # make pip available and install requirements 40 | python3 -m ensurepip 41 | python3 -m pip install -r /workspace/scripts/docker/requirements.txt 42 | -------------------------------------------------------------------------------- /scripts/docker/utilities.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function col_echo() { 4 | local color=$1 5 | local text=$2 6 | if ! [[ ${color} =~ '^[0-9]$' ]]; then 7 | case $(echo ${color} | tr '[:upper:]' '[:lower:]') in 8 | --black | -k) 9 | color=0 10 | ;; 11 | --red | -r) 12 | color=1 13 | ;; 14 | --green | -g) 15 | color=2 16 | ;; 17 | --yellow | -y) 18 | color=3 19 | ;; 20 | --blue | -b) 21 | color=4 22 | ;; 23 | --magenta | -m) 24 | color=5 25 | ;; 26 | --cyan | -c) 27 | color=6 28 | ;; 29 | --white | -w) 30 | color=7 31 | ;; 32 | *) # default color 33 | color=9 34 | ;; 35 | esac 36 | fi 37 | tput -T xterm setaf ${color} 38 | echo ${text} 39 | tput -T xterm sgr0 40 | } 41 | 42 | function print_text_box() { 43 | local string="$1" 44 | local length=${#string} 45 | local border="+-$(printf "%${length}s" | tr ' ' '-')-+" 46 | 47 | col_echo --green "$border" 48 | col_echo --green "| $string |" 49 | col_echo --green "$border" 50 | } 51 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.23) 2 | 3 | # cached globals 4 | include(cmake/cached_globals.cmake) 5 | 6 | project( 7 | UGrid 8 | VERSION ${GLOB_UGRID_PROJECT_VERSION} 9 | DESCRIPTION "Library for reading and writing UGrid files." 10 | LANGUAGES CXX C 11 | ) 12 | 13 | # configuration options 14 | if (NOT WIN32) 15 | message(NOTICE "Build type: ${CMAKE_BUILD_TYPE}") 16 | endif() 17 | 18 | # configuration options 19 | include(cmake/user_config_options.cmake) 20 | 21 | # configure the compiler 22 | include(cmake/compiler_config.cmake) 23 | 24 | # fetch dependencies, must appear after options.cmake 25 | include(cmake/fetch_contents.cmake) 26 | 27 | # find required packages 28 | include(cmake/find_packages.cmake) 29 | 30 | # organize targets into folders, can be remove in version > 3.26 (ON by default) 31 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 32 | 33 | # Docs only available if this is the main app 34 | add_subdirectory(docs) 35 | 36 | # Run packaging scripts: requires semantic version 37 | add_subdirectory(package) 38 | 39 | # Libraries 40 | add_subdirectory(libs) 41 | 42 | # Add unit tests 43 | if(ENABLE_UNIT_TESTING) 44 | add_subdirectory(tests) 45 | endif() 46 | -------------------------------------------------------------------------------- /scripts/append_target_framework_to_output_path_in_csproj.py: -------------------------------------------------------------------------------- 1 | import xml.etree.ElementTree as ET 2 | import sys 3 | from pathlib import Path 4 | 5 | # CMake sets AppendTargetFrameworkToOutputPath to false if there a single target framework. 6 | # The dlls are therefore written to: 7 | # ${CMAKE_CURRENT_BINARY_DIR}/$/ome_app.dll 8 | # When multiple frameworks are targeted, this property is not set and therefore defaults to true. 9 | # ${CMAKE_CURRENT_BINARY_DIR}/$//ome_app.dll 10 | 11 | def append_target_framework_to_output_path(file_path: Path) -> None: 12 | # Parse the cs project 13 | tree = ET.parse(file_path) 14 | root = tree.getroot() 15 | 16 | # Find the AppendTargetFrameworkToOutputPath property and set iot to true 17 | for prop in root.findall(".//PropertyGroup/AppendTargetFrameworkToOutputPath"): 18 | prop.text = 'true' 19 | 20 | # Save changes back to the file, will likely mess up the original formatting 21 | tree.write(file_path, encoding="utf-8", method="xml", xml_declaration=False) 22 | 23 | if __name__ == "__main__": 24 | file_path = Path(sys.argv[1]) 25 | append_target_framework_to_output_path(file_path) 26 | -------------------------------------------------------------------------------- /cmake/cached_globals.cmake: -------------------------------------------------------------------------------- 1 | # version 2 | set(UGRID_PROJECT_VERSION_MAJOR 0) 3 | set(UGRID_PROJECT_VERSION_MINOR 0) 4 | set(UGRID_PROJECT_VERSION_PATCH 0) 5 | if(DEFINED ENV{UGRID_BUILD_NUMBER}) 6 | set(UGRID_PROJECT_VERSION_TWEAK $ENV{UGRID_BUILD_NUMBER}) 7 | else() 8 | set(UGRID_PROJECT_VERSION_TWEAK 0) 9 | endif() 10 | set( 11 | GLOB_UGRID_PROJECT_VERSION 12 | "${UGRID_PROJECT_VERSION_MAJOR}.${UGRID_PROJECT_VERSION_MINOR}.${UGRID_PROJECT_VERSION_PATCH}.${UGRID_PROJECT_VERSION_TWEAK}" 13 | CACHE STRING "Project version" 14 | ) 15 | 16 | # year 17 | string(TIMESTAMP GLOB_CURRENT_YEAR "%Y") 18 | set(GLOB_CURRENT_YEAR ${GLOB_CURRENT_YEAR} CACHE STRING "Current year") 19 | 20 | # .NET config 21 | if(BUILD_DOTNET_WRAPPER) 22 | # .NET SDK 23 | set(GLOB_DOTNET_SDK "Microsoft.NET.Sdk" CACHE STRING ".NET SDK") 24 | # List of .NET target frameworks (semicolon-delimited) 25 | set(GLOB_LIB_DOTNET_TARGET_FRAMEWORKS "netstandard2.0;" CACHE STRING "Library .NET target framework" FORCE) 26 | set(GLOB_TEST_DOTNET_TARGET_FRAMEWORKS "net481;" CACHE STRING "Test .NET target framework" FORCE) 27 | # .NET language version 28 | set(GLOB_CSHARP_LANGUAGE_VERSION "7.3" CACHE STRING "C# Compiler Options for language feature rules") 29 | endif() 30 | -------------------------------------------------------------------------------- /docs/stylesheet.css: -------------------------------------------------------------------------------- 1 | /* The standard CSS for doxygen 1.8.6 */ 2 | 3 | body, table, div, p, dl { 4 | font: 400 14px/22px Helvetica, 'Segoe UI', Arial, freesans, sans-serif; 5 | word-wrap: break-word; 6 | } 7 | 8 | code { 9 | font-size: 85%; 10 | font-family: "SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace; 11 | white-space: pre-wrap; 12 | padding: 1px 5px; 13 | background-color: rgb(223, 229, 241); 14 | vertical-align: baseline; 15 | } 16 | 17 | body { 18 | background-image: url(bodybg.png); 19 | margin: 0 auto; 20 | } 21 | 22 | div.fragment { 23 | padding: 3px; 24 | padding-bottom: 0px; 25 | } 26 | 27 | div.line { 28 | padding-bottom: 3px; 29 | font-family: "SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace; 30 | } 31 | 32 | div.contents { 33 | width: 980px; 34 | margin: 0 auto; 35 | padding: 15px 15px; 36 | border: 1px solid rgb(10, 80, 122); 37 | background-color: #fff; 38 | } 39 | 40 | span.arrow { 41 | height: 13px; 42 | } 43 | 44 | div.image img{ 45 | max-width: 900px; 46 | } 47 | 48 | #projectlogo 49 | { 50 | text-align: center; 51 | vertical-align: middle; 52 | border-collapse: separate; 53 | padding-left: 0.5em; 54 | } 55 | -------------------------------------------------------------------------------- /cmake/fetch_contents.cmake: -------------------------------------------------------------------------------- 1 | include(FetchContent) 2 | 3 | if(ENABLE_UNIT_TESTING) 4 | 5 | # Fetch googletest 6 | set(googletest_url "https://github.com/google/googletest.git") 7 | set(googletest_tag "v1.15.1") 8 | set(cmake_FetchContent_Populate_deprecation_version "3.30.0") 9 | 10 | if(CMAKE_VERSION VERSION_GREATER_EQUAL "${cmake_FetchContent_Populate_deprecation_version}") 11 | FetchContent_Declare( 12 | googletest 13 | GIT_REPOSITORY ${googletest_url} 14 | GIT_TAG ${googletest_tag} 15 | EXCLUDE_FROM_ALL # available from v3.28.0+ 16 | ) 17 | else() 18 | FetchContent_Declare( 19 | googletest 20 | GIT_REPOSITORY ${googletest_url} 21 | GIT_TAG ${googletest_tag} 22 | ) 23 | endif() 24 | 25 | if(WIN32) 26 | set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 27 | endif() 28 | 29 | if(CMAKE_VERSION VERSION_GREATER_EQUAL "${cmake_FetchContent_Populate_deprecation_version}") 30 | FetchContent_MakeAvailable(googletest) 31 | else() 32 | # deprecated 33 | FetchContent_GetProperties(googletest) 34 | if(NOT googletest_POPULATED) 35 | FetchContent_Populate(googletest) 36 | add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL) 37 | endif() 38 | endif() 39 | 40 | enable_testing() 41 | endif() 42 | -------------------------------------------------------------------------------- /package/Version/Version.hpp: -------------------------------------------------------------------------------- 1 | //---- GPL --------------------------------------------------------------------- 2 | // 3 | // Copyright (C) Stichting Deltares, 2011-2021. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation version 3. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | // 17 | // contact: delft3d.support@deltares.nl 18 | // Stichting Deltares 19 | // P.O. Box 177 20 | // 2600 MH Delft, The Netherlands 21 | // 22 | // All indications and logos of, and references to, "Delft3D" and "Deltares" 23 | // are registered trademarks of Stichting Deltares, and remain the property of 24 | // Stichting Deltares. All rights reserved. 25 | // 26 | //------------------------------------------------------------------------------ 27 | 28 | // Only modify `Version.hpp.in`, never `Version.hpp` 29 | static char versionString[64] = "0.0.0.0"; 30 | -------------------------------------------------------------------------------- /libs/UGridNET/nuget/Deltares.UGridNET.targets: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | <_FilesToCopyUGridNET Include="$(MSBuildThisFileDirectory)..\..\runtimes\win-x64\native\**\*"/> 7 | 8 | 9 | 10 | 11 | 12 | 13 | <_OriginalFilesUGridNET Include="$(MSBuildThisFileDirectory)..\..\runtimes\win-x64\native\**\*"/> 14 | 15 | <_FilesToCleanUGridNET Include="$(OutDir)\%(_OriginalFilesUGridNET.RecursiveDir)%(_OriginalFilesUGridNET.FileName)%(_OriginalFilesUGridNET.Extension)"/> 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tests/utils/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # project name 2 | project( 3 | TestUtils 4 | VERSION ${CMAKE_PROJECT_VERSION} 5 | DESCRIPTION "Test utilities" 6 | LANGUAGES CXX 7 | ) 8 | 9 | # target name 10 | set(TARGET_NAME ${PROJECT_NAME}) 11 | 12 | # static library 13 | add_library(${TARGET_NAME} STATIC) 14 | 15 | # source directory 16 | set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) 17 | 18 | # include directory 19 | set(INC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) 20 | set(DOMAIN_INC_DIR ${INC_DIR}/TestUtils) 21 | 22 | # list of target sources 23 | set(SRC_LIST 24 | ${SRC_DIR}/Utils.cpp 25 | ) 26 | 27 | set(INC_LIST 28 | ${DOMAIN_INC_DIR}/Utils.hpp 29 | ${DOMAIN_INC_DIR}/Definitions.hpp 30 | ) 31 | 32 | # add sources to target 33 | # add sources to target 34 | target_sources( 35 | ${TARGET_NAME} 36 | PRIVATE 37 | ${SRC_LIST} 38 | PUBLIC 39 | FILE_SET HEADERS 40 | BASE_DIRS 41 | ${INC_DIR} 42 | FILES 43 | ${INC_LIST} 44 | ) 45 | 46 | # Expose the interface of the shared lib 47 | target_include_directories(${TARGET_NAME} PUBLIC ${INC_DIR}) 48 | 49 | # Should be linked to the main library, as well as the google test library 50 | target_link_libraries(${TARGET_NAME} PRIVATE UGrid) 51 | 52 | # group the sources in IDE tree 53 | source_group("Source Files" FILES ${SRC_LIST}) 54 | 55 | # group the headers in IDE tree 56 | source_group("Header Files" FILES ${INC_LIST}) 57 | -------------------------------------------------------------------------------- /scripts/docker/build_and_test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | build_dir="/workspace/build" 6 | 7 | # ======================== 8 | # clean 9 | # ======================== 10 | if [[ "${CLEAN_BUILD}" = "true" && -d ${build_dir} ]]; then 11 | print_text_box "Clean build" 12 | rm -fr ${build_dir} 13 | echo "Removed ${build_dir}" 14 | fi 15 | 16 | # ======================== 17 | # configure 18 | # ======================== 19 | print_text_box "Configure build" 20 | cmake \ 21 | -S . \ 22 | -B ${build_dir} \ 23 | -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ 24 | -DCMAKE_PREFIX_PATH="${THIRD_PARTY_INSTALL_DIR}" || 25 | error "[cmake] Failed to configure project" 26 | 27 | # ======================== 28 | # build 29 | # ======================== 30 | verbose_switch="" 31 | if [ "${VERBOSE_BUILD}" = "true" ]; then 32 | verbose_switch="--verbose" 33 | fi 34 | print_text_box "Build" 35 | cmake \ 36 | --build ${build_dir} \ 37 | --config ${BUILD_TYPE} \ 38 | --parallel \ 39 | ${verbose_switch} || 40 | error "[cmake] Failed to build project" 41 | 42 | # ======================== 43 | # run tests 44 | # ======================== 45 | print_text_box "Test" 46 | ctest --output-on-failure --extra-verbose --test-dir ${build_dir} 47 | 48 | # ======================== 49 | # install 50 | # ======================== 51 | print_text_box "Install" 52 | cmake --install ${build_dir} --prefix ${build_dir}/install 53 | -------------------------------------------------------------------------------- /package/Version/Version.hpp.in: -------------------------------------------------------------------------------- 1 | //---- GPL --------------------------------------------------------------------- 2 | // 3 | // Copyright (C) Stichting Deltares, 2011-2021. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation version 3. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | // 17 | // contact: delft3d.support@deltares.nl 18 | // Stichting Deltares 19 | // P.O. Box 177 20 | // 2600 MH Delft, The Netherlands 21 | // 22 | // All indications and logos of, and references to, "Delft3D" and "Deltares" 23 | // are registered trademarks of Stichting Deltares, and remain the property of 24 | // Stichting Deltares. All rights reserved. 25 | // 26 | //------------------------------------------------------------------------------ 27 | 28 | // Only modify `Version.hpp.in`, never `Version.hpp` 29 | static char versionString[64] = "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.@PROJECT_VERSION_TWEAK@"; 30 | -------------------------------------------------------------------------------- /libs/UGridNET/projs/UnitTestConsumer_VS-16-2019/UnitTestConsumer/UnitTestConsumer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net481 4 | AnyCPU;x64 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /libs/UGridNET/projs/UnitTestConsumer_VS-17-2022/UnitTestConsumer/UnitTestConsumer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net481;net6.0;net8.0 4 | AnyCPU;x64 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /libs/UGridNET/projs/UnitTestConsumer_VS-16-2019/UnitTestConsumer.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.35130.168 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTestConsumer", "UnitTestConsumer\UnitTestConsumer.csproj", "{F322D9EA-5461-4472-A14C-E02EE84E3695}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|x64 = Debug|x64 12 | Release|Any CPU = Release|Any CPU 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {F322D9EA-5461-4472-A14C-E02EE84E3695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {F322D9EA-5461-4472-A14C-E02EE84E3695}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {F322D9EA-5461-4472-A14C-E02EE84E3695}.Debug|x64.ActiveCfg = Debug|x64 19 | {F322D9EA-5461-4472-A14C-E02EE84E3695}.Debug|x64.Build.0 = Debug|x64 20 | {F322D9EA-5461-4472-A14C-E02EE84E3695}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {F322D9EA-5461-4472-A14C-E02EE84E3695}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {F322D9EA-5461-4472-A14C-E02EE84E3695}.Release|x64.ActiveCfg = Release|x64 23 | {F322D9EA-5461-4472-A14C-E02EE84E3695}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {5B49EC0A-C1AA-45E2-9048-E83D46BAE9CA} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /.github/workflows/style-check.yml: -------------------------------------------------------------------------------- 1 | name: Code formatting 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | 8 | jobs: 9 | check: 10 | name: ClangFormat 11 | 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | 16 | - name: Install clang-format 17 | run: sudo apt install clang-format 18 | 19 | - name: Run clang-format and report result 20 | run: | 21 | declare -a directories=( 22 | "libs/UGrid/src" 23 | "libs/UGrid/include" 24 | "libs/UGridAPI/src" 25 | "libs/UGridAPI/include" 26 | "tests" 27 | ) 28 | # Parse full lines 29 | export IFS=$'\n' 30 | for directory in "${directories[@]}"; do 31 | ( 32 | cd "${directory}" 33 | # Format each file in the directory with name ending with ".hpp", ".h", ".cpp" 34 | for file in $(git ls-files | egrep "\\.hpp$|\\.h$|\\.cpp$"$); do 35 | echo Formatting "${file}" 36 | # format it in place, so git diff can pick it up. 37 | clang-format -style=file -i "${file}" 38 | done 39 | ) 40 | done 41 | # Just some visual separation 42 | echo -e "\\n\\n\\n\\tChecking diff...\\n\\n\\n" 43 | # Set error mode. Makes bash bail on first non-zero exit code 44 | set -e 45 | # Print diff, if any and report with exit code. 46 | git diff --exit-code 47 | # When no diff present, provide status. 48 | echo -e "\\tStyle is fine" 49 | -------------------------------------------------------------------------------- /cmake/compiler_config.cmake: -------------------------------------------------------------------------------- 1 | # Set the C++ standard 2 | set(CMAKE_CXX_STANDARD 20) 3 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 4 | 5 | # Disable compiler-specific extensions 6 | set(CMAKE_CXX_EXTENSIONS OFF) 7 | 8 | # Create position-independent executables and shared libraries 9 | set(CMAKE_POSITION_INDEPENDENT_CODE ON) 10 | 11 | # Add compiler-specific options and definitions per supported platform 12 | if (UNIX) 13 | if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 14 | add_compile_options("$<$:-fvisibility=hidden;-Werror;-Wall;-Wextra;-pedantic;-Wno-unused-function>") 15 | add_compile_options("$<$,$>:-O2>") 16 | add_compile_options("$<$,$>:-g>") 17 | else() 18 | message(FATAL_ERROR "Unsupported compiler. Only GNU is supported under Linux. Found ${CMAKE_CXX_COMPILER_ID}.") 19 | endif() 20 | elseif(WIN32) 21 | if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 22 | add_compile_options("$<$:/EHsc;/MP;/MD;/W3;/WX>") 23 | add_compile_options("$<$,$>:/O2>") 24 | add_compile_options("$<$,$>:/Od;/DEBUG>") 25 | add_compile_definitions("$<$:_USE_MATH_DEFINES>") 26 | add_compile_definitions("$<$:_CRT_SECURE_NO_WARNINGS>") 27 | else() 28 | message(FATAL_ERROR "Unsupported compiler. Only MSVC is supported under Windows. Found ${CMAKE_CXX_COMPILER_ID}.") 29 | endif() 30 | else() 31 | message(FATAL_ERROR "Unsupported platform. Only Linux and Windows are supported.") 32 | endif() 33 | -------------------------------------------------------------------------------- /libs/UGridNET/projs/UnitTestConsumer_VS-17-2022/UnitTestConsumer.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.12.35527.113 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTestConsumer", "UnitTestConsumer\UnitTestConsumer.csproj", "{F322D9EA-5461-4472-A14C-E02EE84E3695}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|x64 = Debug|x64 12 | Release|Any CPU = Release|Any CPU 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {F322D9EA-5461-4472-A14C-E02EE84E3695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {F322D9EA-5461-4472-A14C-E02EE84E3695}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {F322D9EA-5461-4472-A14C-E02EE84E3695}.Debug|x64.ActiveCfg = Debug|x64 19 | {F322D9EA-5461-4472-A14C-E02EE84E3695}.Debug|x64.Build.0 = Debug|x64 20 | {F322D9EA-5461-4472-A14C-E02EE84E3695}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {F322D9EA-5461-4472-A14C-E02EE84E3695}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {F322D9EA-5461-4472-A14C-E02EE84E3695}.Release|x64.ActiveCfg = Release|x64 23 | {F322D9EA-5461-4472-A14C-E02EE84E3695}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {5B49EC0A-C1AA-45E2-9048-E83D46BAE9CA} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UGrid 2 | 3 | Deltares library for reading/writing UGrid files. The UGrid entities available in this library are: Network1d, Mesh1d, Mesh2d and Contacts. 4 | 5 | The library also offers APIs for: 6 | - Getting simulation results defined on specific entity locations (data variables). 7 | - Getting the topological entities attributes names and values, to facilitate the use of UGrid with Python xarray. 8 | 9 | Network1d, Mesh1d, and Contacts concern Deltares extensions to UGrid, which will be submitted to the UGrid community. 10 | 11 | For more information about UGrid conventions: 12 | 13 | https://ugrid-conventions.github.io/ugrid-conventions/ 14 | 15 | ## Build 16 | 17 | The requirements are: 18 | - CMake 3.19 or higher 19 | - A C++17 compatible compiler 20 | - The Boost libraries 21 | - Git 22 | - Doxygen (optional) 23 | 24 | 25 | On windows precompiled boost binaries (with MSVC compiler) can be downloaded here: 26 | 27 | https://sourceforge.net/projects/boost/files/boost-binaries/ 28 | 29 | Once installed, modify boost environmental variables accordingly. For example: 30 | ```powershell 31 | BOOST_INCLUDEDIR=C:\Apps\boost_1_74_0 32 | BOOST_LIBRARYDIR=C:\Apps\boost_1_74_0\lib64-msvc-14.2 33 | ``` 34 | ### IDE 35 | To use an IDE, such as Visual Studio: 36 | 37 | ```powershell 38 | cmake -S . -B xbuild -G"Visual Studio 16 2019" 39 | cmake --open xbuild 40 | ``` 41 | ### Command line 42 | To configure: 43 | ```powershell 44 | cmake -S . -B build 45 | ``` 46 | 47 | To build: 48 | ```powershell 49 | cmake --build build 50 | ``` 51 | 52 | To build docs (requires Doxygen, output in `build/docs/html`): 53 | ```powershell 54 | cmake --build build --target docs 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /libs/UGridNET/test/src/TopologyExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System; 3 | using UGridNET.Extensions; 4 | 5 | namespace UGridNET.Tests 6 | { 7 | public class TopologyExtensionsTests 8 | { 9 | // Test case source for different classes 10 | private static readonly object[] TestCases = 11 | { 12 | new TestCaseData(new Mesh1D { num_nodes = 10, num_edges = 5 }), 13 | new TestCaseData(new Mesh2D { num_nodes = 10, num_edges = 5, num_faces = 6, num_face_nodes_max = 7 }), 14 | new TestCaseData(new Contacts { num_contacts = 5 }), 15 | new TestCaseData(new Network1D { num_nodes = 10, num_edges = 5, num_geometry_nodes = 20 }) 16 | }; 17 | 18 | [TestCaseSource(nameof(TestCases))] 19 | public void TopologyAllocateAndFreeExtensionsDoNotThrow(object instance) 20 | { 21 | Assert.DoesNotThrow(() => 22 | { 23 | switch (instance) 24 | { 25 | case Mesh1D mesh1D: 26 | mesh1D.Allocate(); 27 | mesh1D.Free(); 28 | break; 29 | case Mesh2D mesh2D: 30 | mesh2D.Allocate(); 31 | mesh2D.Free(); 32 | break; 33 | case Contacts contacts: 34 | contacts.Allocate(); 35 | contacts.Free(); 36 | break; 37 | case Network1D network1D: 38 | network1D.Allocate(); 39 | network1D.Free(); 40 | break; 41 | } 42 | }); 43 | } 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /libs/UGridAPI/include/UGridAPI/MeshLocations.hpp: -------------------------------------------------------------------------------- 1 | //---- GPL --------------------------------------------------------------------- 2 | // 3 | // Copyright (C) Stichting Deltares, 2011-2021. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation version 3. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | // 17 | // contact: delft3d.support@deltares.nl 18 | // Stichting Deltares 19 | // P.O. Box 177 20 | // 2600 MH Delft, The Netherlands 21 | // 22 | // All indications and logos of, and references to, "Delft3D" and "Deltares" 23 | // are registered trademarks of Stichting Deltares, and remain the property of 24 | // Stichting Deltares. All rights reserved. 25 | // 26 | //------------------------------------------------------------------------------ 27 | 28 | #pragma once 29 | 30 | #ifndef UGRID_API 31 | #ifdef _WIN32 32 | #define UGRID_API __declspec(dllexport) 33 | #else 34 | #define UGRID_API __attribute__((visibility("default"))) 35 | #endif 36 | #endif 37 | 38 | namespace ugridapi 39 | { 40 | 41 | /// @brief MeshLocations locations 42 | enum MeshLocations 43 | { 44 | Unknown = -1, ///< Unknown 45 | Faces = 0, ///< Faces 46 | Nodes = 1, ///< Nodes 47 | Edges = 2, ///< Edges 48 | }; 49 | 50 | } // namespace ugridapi 51 | -------------------------------------------------------------------------------- /docs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(Doxygen) 2 | if(NOT Doxygen_FOUND) 3 | message(STATUS "Doxygen not found, not building docs") 4 | return() 5 | endif() 6 | 7 | set(DOXYGEN_INPUT_LIST 8 | "${CMAKE_CURRENT_SOURCE_DIR}/main_page.md \ 9 | ${PROJECT_SOURCE_DIR}/libs/UGrid/include/UGrid \ 10 | ${PROJECT_SOURCE_DIR}/libs/UGridAPI/include/UGridAPI") 11 | set(DOXYGEN_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) 12 | set(DOXYGEN_INDEX_FILE ${DOXYGEN_OUTPUT_DIR}/html/index.html) 13 | set(DOXYFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in) 14 | set(DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) 15 | set(DOXYFILE_EXTRACT_PRIVATE "FALSE") 16 | 17 | # This is only used for the CI 18 | set(DOXYGEN_WARN_LOG_FILE "") 19 | 20 | # Replace variables inside @@ with the current values 21 | configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY) 22 | 23 | # Doxygen won't create this for us 24 | file(MAKE_DIRECTORY ${DOXYGEN_OUTPUT_DIR}) 25 | 26 | # UGrid headers 27 | file(GLOB UGrid_HEADER_LIST CONFIGURE_DEPENDS 28 | "${PROJECT_SOURCE_DIR}/libs/UGrid/include/UGrid/*.hpp") 29 | 30 | # UGridapi headers 31 | file(GLOB UGridAPI_HEADER_LIST CONFIGURE_DEPENDS 32 | "${PROJECT_SOURCE_DIR}/libs/UGridAPI/include/UGridAPI/*.hpp") 33 | 34 | # markdown file 35 | file(GLOB DOXYGEN_MARKDOWN_FILES CONFIGURE_DEPENDS 36 | "${CMAKE_CURRENT_SOURCE_DIR}/*.md") 37 | 38 | # Only regenerate Doxygen when the Doxyfile or public headers change 39 | add_custom_command( 40 | OUTPUT ${DOXYGEN_INDEX_FILE} 41 | DEPENDS ${UGrid_HEADER_LIST} ${UGridAPI_HEADER_LIST} 42 | ${DOXYGEN_MARKDOWN_FILES} 43 | COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT} 44 | WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/libs" 45 | MAIN_DEPENDENCY ${DOXYFILE_OUT} 46 | ${DOXYFILE_IN} 47 | COMMENT "Generating docs") 48 | 49 | add_custom_target(Doxygen ALL DEPENDS ${DOXYGEN_INDEX_FILE}) 50 | -------------------------------------------------------------------------------- /tests/api/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # project name 2 | project( 3 | UGridAPITests 4 | VERSION ${CMAKE_PROJECT_VERSION} 5 | DESCRIPTION "UGridAPI tests" 6 | LANGUAGES CXX C 7 | ) 8 | 9 | # target name 10 | set(TARGET_NAME ${PROJECT_NAME}) 11 | 12 | # Make a test executable 13 | add_executable(${TARGET_NAME}) 14 | 15 | # source directory 16 | set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) 17 | 18 | # include directory 19 | set(INC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) 20 | 21 | # list of target sources 22 | set(SRC_LIST 23 | ${SRC_DIR}/APITests.cpp 24 | ) 25 | 26 | set(INC_LIST) 27 | 28 | # add sources to target 29 | target_sources(${TARGET_NAME} PRIVATE ${SRC_LIST} ${INC_LIST}) 30 | 31 | # Expose the interface of the shared lib 32 | target_include_directories(${TARGET_NAME} PUBLIC ${INC_DIR}) 33 | 34 | # Should be linked to the main library, as well as the google test library 35 | target_link_libraries( 36 | ${TARGET_NAME} 37 | PRIVATE 38 | "$" 39 | TestUtils 40 | GTest::gmock 41 | GTest::gtest_main 42 | ) 43 | 44 | # If you register a test, then ctest and make test will run it. You can also run 45 | # examples and check the output, as well. Command can be a target. 46 | add_test( 47 | NAME ${TARGET_NAME} 48 | COMMAND ${TARGET_NAME} 49 | ) 50 | 51 | # group the sources in IDE tree 52 | source_group("Source Files" FILES ${SRC_LIST}) 53 | 54 | # group the headers in IDE tree 55 | source_group("Header Files" FILES ${INC_LIST}) 56 | 57 | # Copy dependencies 58 | add_custom_command( 59 | TARGET ${TARGET_NAME} 60 | POST_BUILD 61 | #COMMAND ${CMAKE_COMMAND} -E echo "Copying ${THIRD_PARTY_RUNTIME_DEPS} to $" 62 | COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ 63 | COMMAND ${CMAKE_COMMAND} -E copy -t $ ${THIRD_PARTY_RUNTIME_DEPS} 64 | COMMENT "Copying runtime dependencies..." 65 | ) 66 | -------------------------------------------------------------------------------- /libs/UGridNET/dll/src/ByteArrayExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace UGridNET 5 | { 6 | namespace Extensions 7 | { 8 | /// 9 | /// Provides extension methods for byte arrays. 10 | /// 11 | internal static class ByteArrayExtensions 12 | { 13 | /// Converts a null-terminated byte array to a string. 14 | /// The byte array to convert. 15 | /// Specifies whether to trim the end of the resulting string. 16 | /// The converted string. 17 | /// Thrown when the byte array is null. 18 | /// Thrown when the byte array is empty or not null-terminated. 19 | /// If the converted string is not trimmed, a space is appended to it to preserve the original length. 20 | public static string GetStringFromNullTerminatedArray(this byte[] bytes, bool doTrimEnd = false) 21 | { 22 | if (bytes == null) 23 | { 24 | throw new ArgumentNullException(nameof(bytes), "Byte array cannot be null."); 25 | } 26 | 27 | if (bytes.Length == 0) 28 | { 29 | throw new ArgumentException("Byte array cannot be empty.", nameof(bytes)); 30 | } 31 | 32 | if (bytes[bytes.Length - 1] != 0x00) 33 | { 34 | throw new ArgumentException("Byte array is not null-terminated.", nameof(bytes)); 35 | } 36 | 37 | string str = Encoding.UTF8.GetString(bytes, 0, bytes.Length - 1); 38 | return doTrimEnd ? str.TrimEnd() : str + ' '; 39 | } 40 | 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /libs/UGridNET/dll/src/UGridNETException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UGridNET 4 | { 5 | /// 6 | /// Custom exceptions for errors that occur within the UGridNET library. 7 | /// 8 | public sealed class UGridNETException : Exception 9 | { 10 | private static readonly string prefix = "UGridNET error"; 11 | 12 | /// 13 | /// Initializes a new instance of the class. 14 | /// 15 | public UGridNETException() 16 | { 17 | } 18 | 19 | /// 20 | /// Initializes a new instance of the class with a specified error message. 21 | /// 22 | /// The message that describes the error. 23 | public UGridNETException(string message) 24 | : base($"{prefix}: {message}") 25 | { 26 | } 27 | 28 | /// 29 | /// Initializes a new instance of the class with a 30 | /// specified formatted error message and format arguments. 31 | /// 32 | /// The error message format string. 33 | /// An array of objects to format. 34 | public UGridNETException(string format, params object[] args) 35 | : base(string.Format($"{prefix}: {format}", args)) 36 | { 37 | } 38 | 39 | /// 40 | /// Initializes a new instance of the class with a 41 | /// specified error message and a reference to the inner exception that is the cause of this exception. 42 | /// 43 | /// The message that describes the error. 44 | /// The exception that is the cause of the current exception. 45 | public UGridNETException(string message, Exception innerException) 46 | : base($"{prefix}: {message}", innerException) 47 | { 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /libs/UGridAPI/include/UGridAPI/UGridState.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace ugridapi 9 | { 10 | /// @brief The class holding the state of the UGridIO 11 | struct UGridState 12 | { 13 | UGridState() = default; 14 | 15 | /// @brief Constructor 16 | /// @param nc_file [in] A pointer to a NcFile handle 17 | explicit UGridState(const std::shared_ptr& nc_file) 18 | : m_ncFile(nc_file) 19 | { 20 | } 21 | 22 | std::shared_ptr m_ncFile; ///< A pointer to a NcFile handle 23 | std::vector m_mesh1d; ///< A vector containing all Mesh1D instances 24 | std::vector m_network1d; ///< A vector containing all Network1D instances 25 | std::vector m_mesh2d; ///< A vector containing all Mesh2D instances 26 | std::vector m_contacts; ///< A vector containing all Contacts instances 27 | 28 | /// @brief Set netcdf dimensions not related to topology 29 | /// @param dimension_name The dimension name 30 | /// @param dimension_value The dimension value 31 | void set_dimension(const std::string& dimension_name, const int dimension_value) 32 | { 33 | auto const it = m_dimensions.find(dimension_name); 34 | if (it != m_dimensions.end()) 35 | { 36 | return; 37 | } 38 | auto const nc_dimension = m_ncFile->addDim(dimension_name, dimension_value); 39 | m_dimensions.emplace(dimension_name, nc_dimension); 40 | } 41 | 42 | /// @brief Get the nectdf dimension from its name 43 | /// @param dimension_name The dimension name 44 | /// @return The netcdf dimension 45 | netCDF::NcDim get_dimension(const std::string& dimension_name) const 46 | { 47 | return m_dimensions.at(dimension_name); 48 | } 49 | 50 | private: 51 | std::map m_dimensions; ///< Dimensions not related to a topology 52 | }; 53 | } // namespace ugridapi 54 | -------------------------------------------------------------------------------- /libs/UGridAPI/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project( 2 | UGridAPI 3 | VERSION ${CMAKE_PROJECT_VERSION} 4 | DESCRIPTION "UGridAPI shared library" 5 | LANGUAGES CXX C 6 | ) 7 | 8 | # target name 9 | set(TARGET_NAME ${PROJECT_NAME}) 10 | 11 | # shared library 12 | add_library(${TARGET_NAME} SHARED ${CMAKE_BINARY_DIR}/version.rc) 13 | 14 | # source directory 15 | set(SRC_DIR ${PROJECT_SOURCE_DIR}/src) 16 | 17 | # include directory 18 | set(INC_DIR ${PROJECT_SOURCE_DIR}/include) 19 | set(DOMAIN_INC_DIR ${INC_DIR}/UGridAPI) 20 | set(VERSION_INC_DIR ${CMAKE_SOURCE_DIR}/package) 21 | 22 | # list of target sources 23 | set(SRC_LIST ${SRC_DIR}/UGrid.cpp) 24 | 25 | # list of target headers 26 | set( 27 | INC_LIST 28 | ${DOMAIN_INC_DIR}/Contacts.hpp 29 | ${DOMAIN_INC_DIR}/Mesh1D.hpp 30 | ${DOMAIN_INC_DIR}/Mesh2D.hpp 31 | ${DOMAIN_INC_DIR}/MeshLocations.hpp 32 | ${DOMAIN_INC_DIR}/Network1D.hpp 33 | ${DOMAIN_INC_DIR}/UGrid.hpp 34 | ${DOMAIN_INC_DIR}/UGridState.hpp 35 | ${VERSION_INC_DIR}/Version/Version.hpp 36 | ) 37 | 38 | # add sources to target 39 | target_sources( 40 | ${TARGET_NAME} 41 | PRIVATE 42 | ${SRC_LIST} 43 | PUBLIC 44 | FILE_SET HEADERS 45 | BASE_DIRS 46 | ${INC_DIR} ${VERSION_INC_DIR} 47 | FILES 48 | ${INC_LIST} 49 | ) 50 | 51 | # Expose the interface of the shared lib 52 | target_include_directories(${TARGET_NAME} PUBLIC ${INC_DIR}) 53 | 54 | # link required libraries 55 | target_link_libraries( 56 | ${TARGET_NAME} 57 | PUBLIC 58 | "$" 59 | ) 60 | 61 | # Make sure that coverage information is produced when using gcc 62 | if(ENABLE_CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 63 | target_compile_options( 64 | ${TARGET_NAME} 65 | PRIVATE 66 | --coverage # equivalent to -fprofile-arcs -ftest-coverage 67 | -static-libgcc 68 | -static-libstdc++ 69 | ) 70 | target_link_libraries(${TARGET_NAME} PRIVATE gcov) 71 | endif() 72 | 73 | # Add precompiled header to speed up compilation 74 | target_precompile_headers( 75 | ${TARGET_NAME} 76 | PRIVATE 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | ) 87 | 88 | install(TARGETS ${TARGET_NAME} FILE_SET HEADERS DESTINATION "include") 89 | 90 | # group the sources in IDE tree 91 | source_group("Source Files" FILES ${SRC_LIST}) 92 | 93 | # group the headers in IDE tree 94 | source_group("Header Files" FILES ${INC_LIST}) 95 | 96 | -------------------------------------------------------------------------------- /libs/UGridNET/test/src/UGridNETExceptionTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace UGridNET.Tests 6 | { 7 | 8 | [TestFixture] 9 | public class UGridNETExceptionTests 10 | { 11 | 12 | [Test] 13 | public void UGridNETExceptionWithoutParameters() 14 | { 15 | try 16 | { 17 | throw new UGridNETException(); 18 | } 19 | catch (UGridNETException exception) 20 | { 21 | Assert.That(exception, Is.Not.Null); 22 | Assert.That(exception.Message, Is.EqualTo("Exception of type 'UGridNET.UGridNETException' was thrown.")); 23 | } 24 | } 25 | 26 | [Test] 27 | public void UGridNETExceptionWithString() 28 | { 29 | try 30 | { 31 | throw new UGridNETException("Test exception"); 32 | } 33 | catch (UGridNETException exception) 34 | { 35 | Assert.That(exception, Is.Not.Null); 36 | Assert.That(exception.Message, Is.EqualTo("UGridNET error: Test exception")); 37 | } 38 | } 39 | 40 | [Test] 41 | public void UGridNETExceptionWithFormattedString() 42 | { 43 | try 44 | { 45 | throw new UGridNETException("Test exception {0} {1} {2} {3} {2} {1} {0}", 1, 2.5, 'c', "str"); 46 | } 47 | catch (UGridNETException exception) 48 | { 49 | Assert.That(exception, Is.Not.Null); 50 | Assert.That(exception.Message, Is.EqualTo("UGridNET error: Test exception 1 2,5 c str c 2,5 1")); 51 | } 52 | } 53 | 54 | [Test] 55 | public void UGridNETExceptionWithStringAndInnerException() 56 | { 57 | var exceptionMessage = "UGridNETException exception message."; 58 | var innerException = new InvalidOperationException("Inner exception of type InvalidOperationException."); 59 | 60 | try 61 | { 62 | throw new UGridNETException(exceptionMessage, innerException); 63 | } 64 | catch (UGridNETException exception) 65 | { 66 | Assert.That(exception, Is.Not.Null); 67 | Assert.That(exception.Message, Is.EqualTo("UGridNET error: " + exceptionMessage)); 68 | Assert.That(exception.InnerException, Is.EqualTo(innerException)); 69 | } 70 | } 71 | 72 | } 73 | } -------------------------------------------------------------------------------- /libs/UGridAPI/include/UGridAPI/Contacts.hpp: -------------------------------------------------------------------------------- 1 | //---- GPL --------------------------------------------------------------------- 2 | // 3 | // Copyright (C) Stichting Deltares, 2011-2021. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation version 3. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | // 17 | // contact: delft3d.support@deltares.nl 18 | // Stichting Deltares 19 | // P.O. Box 177 20 | // 2600 MH Delft, The Netherlands 21 | // 22 | // All indications and logos of, and references to, "Delft3D" and "Deltares" 23 | // are registered trademarks of Stichting Deltares, and remain the property of 24 | // Stichting Deltares. All rights reserved. 25 | // 26 | //------------------------------------------------------------------------------ 27 | 28 | #pragma once 29 | 30 | #include 31 | 32 | namespace ugridapi 33 | { 34 | /// @brief A struct used to describe UGrid contact in a C-compatible manner 35 | struct Contacts 36 | { 37 | /// @brief The name of the contact entity 38 | char* name = nullptr; 39 | 40 | /// @brief The actual contact, expressed as pair of indices from a mesh index to another mesh index 41 | int* edges = nullptr; 42 | 43 | /// @brief For each contact its type 44 | int* contact_type = nullptr; 45 | 46 | /// @brief The name of each contact 47 | char* contact_name_id = nullptr; 48 | 49 | /// @brief The long name of each contact 50 | char* contact_name_long = nullptr; 51 | 52 | /// @brief The name of the mesh where the contact start 53 | char* mesh_from_name = nullptr; 54 | 55 | /// @brief The name of the mesh where the contact ends 56 | char* mesh_to_name = nullptr; 57 | 58 | /// @brief The location type (node, edge or face) at the contact start 59 | MeshLocations mesh_from_location = MeshLocations::Unknown; 60 | 61 | /// @brief The location type (node, edge or face) at the contact end 62 | MeshLocations mesh_to_location = MeshLocations::Unknown; 63 | 64 | /// @brief The number of contact 65 | int num_contacts = 0; 66 | }; 67 | } // namespace ugridapi 68 | -------------------------------------------------------------------------------- /libs/UGridNET/test/src/ByteArrayExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using UGridNET.Extensions; 7 | 8 | namespace UGridNET.Tests 9 | { 10 | public class ByteArrayExtensionsTests 11 | { 12 | [Test] 13 | public void GetStringFromNullTerminatedArrayThrowsDueToNullBytesArray() 14 | { 15 | byte[] bytes = null; 16 | string str; 17 | Assert.Throws(() => str = bytes.GetStringFromNullTerminatedArray()); 18 | } 19 | 20 | [Test] 21 | public void GetStringFromNullTerminatedArrayThrowsDueToEmptyBytesArray() 22 | { 23 | var bytes = new byte[] { }; 24 | string str; 25 | Assert.Throws(() => str = bytes.GetStringFromNullTerminatedArray()); 26 | } 27 | 28 | [Test] 29 | public void GetStringFromNullTerminatedArrayThrowsDueToBytesArrayNotBeingNullTerminated() 30 | { 31 | byte[] bytes = { 32 | 0x42, 0x6c, 0x75, 0x65, 0x20, 33 | 0x73, 0x77, 0x69, 0x74, 0x63, 34 | 0x68, 0x65, 0x73, 0x20, 0x61, 35 | 0x72, 0x65, 0x20, 0x72, 0x61, 36 | 0x64 37 | }; 38 | string str; 39 | Assert.Throws(() => str = bytes.GetStringFromNullTerminatedArray()); 40 | } 41 | 42 | [Test] 43 | public void GetStringFromNullTerminatedArraySucceedsWhenTrimmingIsNotRequested() 44 | { 45 | byte[] bytes = { 46 | 0x42, 0x6c, 0x75, 0x65, 0x20, 47 | 0x73, 0x77, 0x69, 0x74, 0x63, 48 | 0x68, 0x65, 0x73, 0x20, 0x61, 49 | 0x72, 0x65, 0x20, 0x72, 0x61, 50 | 0x64, 0x20, 0x20, 0x20, 0x00 51 | }; 52 | string str = bytes.GetStringFromNullTerminatedArray(); 53 | string expectedStr = "Blue switches are rad "; 54 | Assert.That(str, Is.EqualTo(expectedStr)); 55 | } 56 | 57 | [Test] 58 | public void GetStringFromNullTerminatedArraySucceedsWhenTrimmingIsRequested() 59 | { 60 | byte[] bytes = { 61 | 0x42, 0x6c, 0x75, 0x65, 0x20, 62 | 0x73, 0x77, 0x69, 0x74, 0x63, 63 | 0x68, 0x65, 0x73, 0x20, 0x61, 64 | 0x72, 0x65, 0x20, 0x72, 0x61, 65 | 0x64, 0x20, 0x20, 0x20, 0x00 66 | }; 67 | string str = bytes.GetStringFromNullTerminatedArray(true); 68 | string expectedStr = "Blue switches are rad"; 69 | Assert.That(str, Is.EqualTo(expectedStr)); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /scripts/download_sonar_tools.py: -------------------------------------------------------------------------------- 1 | """ 2 | Script used to download sonar tools 3 | """ 4 | 5 | import requests 6 | import zipfile 7 | import shutil 8 | import platform 9 | import argparse 10 | 11 | from pathlib import Path 12 | 13 | SONAR_SCANNER_VERSION = "5.0.1.3006" 14 | 15 | 16 | def download_file(url: str, save_path: Path, chunk_size=128) -> None: 17 | r = requests.get(url, stream=True) 18 | with save_path.open("wb") as fd: 19 | for chunk in r.iter_content(chunk_size=chunk_size): 20 | fd.write(chunk) 21 | 22 | 23 | def unzip_file(zip_file_path: Path, unzip_directory: Path) -> None: 24 | with zipfile.ZipFile(str(zip_file_path), "r") as zip_ref: 25 | zip_ref.extractall(str(unzip_directory)) 26 | 27 | 28 | def get_build_wrapper(save_dir: Path) -> None: 29 | 30 | if platform.system() == "Windows": 31 | url = "https://sonarcloud.io/static/cpp/build-wrapper-win-x86.zip" 32 | elif platform.system() == "Linux": 33 | url = "https://sonarcloud.io/static/cpp/build-wrapper-linux-x86.zip" 34 | else: 35 | raise Exception("Unsupported OS used.") 36 | 37 | save_path = save_dir / Path("build-wrapper.zip") 38 | download_file(url, save_path) 39 | unzip_file(save_path, save_dir) 40 | 41 | 42 | def rename_sonar_scanner_folder(save_dir: Path) -> None: 43 | sonar_scanner_folder = next(save_dir.glob("sonar-scanner-*")) 44 | shutil.move( 45 | str(sonar_scanner_folder), str(sonar_scanner_folder.with_name("sonar-scanner")) 46 | ) 47 | 48 | 49 | def get_scanner(save_dir: Path, sonar_scanner_version: str) -> None: 50 | if platform.system() == "Windows": 51 | url = f"https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-{sonar_scanner_version}-windows.zip" 52 | elif platform.system() == "Linux": 53 | url = f"https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-{sonar_scanner_version}-linux.zip" 54 | else: 55 | raise Exception("Unsupported OS used.") 56 | 57 | save_path = save_dir / Path("download_sonar_scanner.zip") 58 | download_file(url, save_path) 59 | unzip_file(save_path, save_dir) 60 | rename_sonar_scanner_folder(save_dir) 61 | 62 | 63 | if __name__ == "__main__": 64 | parser = argparse.ArgumentParser() 65 | parser.add_argument( 66 | "-ssv", 67 | "--sonar_scanner_version", 68 | help="The sonar scanner version", 69 | default=f"{SONAR_SCANNER_VERSION}", 70 | ) 71 | parser.add_argument( 72 | "--save_dir", 73 | type=Path, 74 | required=True, 75 | help="The sonar scanner save directory", 76 | ) 77 | args = vars(parser.parse_args()) 78 | 79 | save_dir = args["save_dir"] 80 | save_dir.mkdir(exist_ok=True) 81 | get_build_wrapper(save_dir) 82 | get_scanner(save_dir, args["sonar_scanner_version"]) 83 | -------------------------------------------------------------------------------- /libs/UGrid/include/UGrid/UGridVarAttributeStringBuilder.hpp: -------------------------------------------------------------------------------- 1 | //---- GPL --------------------------------------------------------------------- 2 | // 3 | // Copyright (C) Stichting Deltares, 2011-2021. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation version 3. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | // 17 | // contact: delft3d.support@deltares.nl 18 | // Stichting Deltares 19 | // P.O. Box 177 20 | // 2600 MH Delft, The Netherlands 21 | // 22 | // All indications and logos of, and references to, "Delft3D" and "Deltares" 23 | // are registered trademarks of Stichting Deltares, and remain the property of 24 | // Stichting Deltares. All rights reserved. 25 | // 26 | //------------------------------------------------------------------------------ 27 | 28 | #pragma once 29 | 30 | /// \namespace ugrid 31 | /// @brief Contains the logic of the C++ static library 32 | namespace ugrid 33 | { 34 | /// @brief A class for building ugrid variable names, appending strings to the entity name 35 | class UGridVarAttributeStringBuilder 36 | { 37 | public: 38 | /// @brief Constructor setting the entity name 39 | /// @param name The entity name 40 | explicit UGridVarAttributeStringBuilder(std::string const& name) : m_name(name) 41 | { 42 | m_os << m_name; 43 | } 44 | 45 | /// @brief Clears the stream and adds the entity name 46 | void clear() 47 | { 48 | m_os.str(std::string()); 49 | m_os << m_name; 50 | } 51 | 52 | /// @brief Get the stream content 53 | /// @return The stream content 54 | [[nodiscard]] std::string str() const 55 | { 56 | return m_os.str(); 57 | } 58 | 59 | /// @brief Customized << operator for adding content into the internal stream 60 | /// @tparam T The content type 61 | /// @param val The content value 62 | /// @return The current UGridVarAttributeStringBuilder instance 63 | template 64 | UGridVarAttributeStringBuilder& operator<<(T val) 65 | { 66 | m_os << val; 67 | return *this; 68 | } 69 | 70 | private: 71 | std::stringstream m_os; ///< The string stream, used for concatenating strings 72 | std::string m_name; ///< The entity name 73 | }; 74 | 75 | } // namespace ugrid 76 | -------------------------------------------------------------------------------- /libs/UGridNET/dll/src/ContactsExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UGridNET 4 | { 5 | namespace Extensions 6 | { 7 | internal static class ContactsExtensions 8 | { 9 | /// Allocates unmanaged memory for all required properties of the instance. 10 | /// Instance of . 11 | /// Memory allocated by this method must be freed by 12 | public static void Allocate(this Contacts contacts) 13 | { 14 | try 15 | { 16 | contacts.name = IntPtrHelpers.AllocateZeroed(UGrid.name_long_length); 17 | contacts.contact_name_id = IntPtrHelpers.AllocateZeroed(UGrid.name_long_length * contacts.num_contacts); 18 | contacts.mesh_from_name = IntPtrHelpers.AllocateZeroed(UGrid.name_long_length); 19 | contacts.mesh_to_name = IntPtrHelpers.AllocateZeroed(UGrid.name_long_length); 20 | contacts.contact_name_long = IntPtrHelpers.AllocateZeroed(UGrid.name_long_length * contacts.num_contacts); 21 | contacts.edges = IntPtrHelpers.AllocateZeroed(contacts.num_contacts * 2); 22 | contacts.contact_type = IntPtrHelpers.AllocateZeroed(contacts.num_contacts); 23 | } 24 | catch 25 | { 26 | // AllocHGlobal may throw OutOfMemoryException exception, clean up and re-throw 27 | contacts.Free(); 28 | throw; 29 | } 30 | } 31 | 32 | /// 33 | /// Frees unmanaged memory allocated by for all required properties 34 | /// of the instance. 35 | /// 36 | /// Instance of . 37 | public static void Free(this Contacts contacts) 38 | { 39 | IntPtrHelpers.Free(() => contacts.name, value => contacts.name = value); 40 | IntPtrHelpers.Free(() => contacts.contact_name_id, value => contacts.contact_name_id = value); 41 | IntPtrHelpers.Free(() => contacts.mesh_from_name, value => contacts.mesh_from_name = value); 42 | IntPtrHelpers.Free(() => contacts.mesh_to_name, value => contacts.mesh_to_name = value); 43 | IntPtrHelpers.Free(() => contacts.contact_name_long, value => contacts.contact_name_long = value); 44 | IntPtrHelpers.Free(() => contacts.edges, value => contacts.edges = value); 45 | IntPtrHelpers.Free(() => contacts.contact_type, value => contacts.contact_type = value); 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /libs/UGridNET/test/src/IntPtrExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using NUnit.Framework; 4 | using UGridNET.Extensions; 5 | 6 | namespace UGridNET.Tests 7 | { 8 | 9 | [TestFixture] 10 | public class IntPtrExtensionsTests 11 | { 12 | private int[] array = null; 13 | 14 | private IntPtr ptr = IntPtr.Zero; 15 | private readonly int size = 10; 16 | //private readonly int sizeOfInt = Marshal.SizeOf(); 17 | 18 | [SetUp] 19 | public void SetUp() 20 | { 21 | array = new int[size]; 22 | for (int i = 0; i < size; i++) 23 | { 24 | array[i] = i; 25 | } 26 | 27 | ptr = Marshal.AllocHGlobal(size * Marshal.SizeOf()); 28 | } 29 | 30 | [TearDown] 31 | public void TearDown() 32 | { 33 | Marshal.FreeHGlobal(ptr); 34 | } 35 | 36 | [Test] 37 | public void CopyArrayToPtrThrowsDueToNullPointer() 38 | { 39 | var zeroIntPtr = IntPtr.Zero; 40 | Assert.Throws(() => zeroIntPtr.CopyFromArray(array)); 41 | } 42 | 43 | [Test] 44 | public void CopyArrayToPtrThrowsDueToNullArray() 45 | { 46 | int[] nullArray = null; 47 | Assert.Throws(() => ptr.CopyFromArray(nullArray)); 48 | } 49 | 50 | [Test] 51 | public void CopyArrayToPtrThrowsDueToEmptyArray() 52 | { 53 | int[] emptyArray = new int[] { }; 54 | Assert.Throws(() => ptr.CopyFromArray(emptyArray)); 55 | } 56 | 57 | [Test] 58 | public void CopyArrayToPtrSucceeds() 59 | { 60 | ptr.CopyFromArray(array); 61 | int[] result = new int[size]; 62 | for (int i = 0; i < size; i++) 63 | { 64 | result[i] = Marshal.ReadInt32(ptr, i * Marshal.SizeOf()); 65 | } 66 | Assert.That(result, Is.EqualTo(array)); 67 | } 68 | 69 | [Test] 70 | public void CopyPtrToArrayThrowsDueToNullPointer() 71 | { 72 | var zeroIntPtr = IntPtr.Zero; 73 | int[] result; 74 | Assert.Throws(() => result = zeroIntPtr.CopyToArray(size)); 75 | } 76 | 77 | [Test] 78 | public void CopyPtrToArrayThrowsDueInvalidArrayLength() 79 | { 80 | int[] emptyArray = new int[] { }; 81 | int[] result; 82 | Assert.Throws(() => result = ptr.CopyToArray(-1)); 83 | } 84 | 85 | [Test] 86 | public void CopyPtrToArraySucceeds() 87 | { 88 | for (int i = 0; i < size; i++) 89 | { 90 | Marshal.WriteInt32(ptr, i * Marshal.SizeOf(), i); 91 | } 92 | var result = ptr.CopyToArray(size); 93 | Assert.That(result, Is.EqualTo(array)); 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /scripts/get_package_ids_from_directory_packages_props.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import xml.etree.ElementTree as ET 3 | from pathlib import Path 4 | 5 | 6 | def parse_xml(file_path: Path) -> str: 7 | """ 8 | Finds all the PackageVersion elements and joins the underscore-suffixed Include values into a comma-separated string 9 | reason behind underscore is related to how set_target_properties sets the property VS_PACKAGE_REFERENCES 10 | see https://cmake.org/cmake/help/latest/prop_tgt/VS_PACKAGE_REFERENCES.html 11 | set_target_properties( PROPERTIES VS_PACKAGE_REFERENCES "package1_x.y.z;package2_x.y.z;...") 12 | sets the following in a csproj 13 | # 14 | 15 | 16 | 17 | 18 | 19 | # 20 | the underscore in between separates the package's name from its version. 21 | # 22 | The packages are defined in Directory.Packages.props as follows: 23 | # 24 | 25 | 26 | true 27 | 28 | 29 | 30 | 31 | . 32 | . 33 | . 34 | 35 | 36 | # 37 | but when central package management is used (ManagePackageVersionsCentrally set to true). 38 | it is not allowed to set the version in the csproj PackageReference anymore. So we leave out the version. 39 | This results in 40 | # 41 | 42 | 43 | 44 | 45 | 46 | # 47 | Visual Studio does not complain about the attribute "Version" having no value. 48 | 49 | Args: 50 | - file_path (Path): path to Directory.Packages.props file. 51 | 52 | Returns: 53 | - str: Underscore-suffixed semicolon-delimited package references. 54 | """ 55 | 56 | # Parse the XML file 57 | tree = ET.parse(file_path) 58 | root = tree.getroot() 59 | 60 | # Initialize a list to store Include attribute values 61 | include_values = [] 62 | 63 | for package in root.findall(".//PackageVersion"): 64 | include_attr = package.get("Include") 65 | if include_attr: 66 | include_values.append(include_attr + "_") 67 | 68 | return ";".join(include_values) 69 | 70 | 71 | if __name__ == "__main__": 72 | # The file path is passed as the first command line argument 73 | if len(sys.argv) != 2: 74 | print( 75 | "Usage: python get_package_ids_from_directory_packages_prop.py " 76 | ) 77 | sys.exit(1) 78 | 79 | file_path = sys.argv[1] 80 | result = parse_xml(file_path) 81 | print(result) 82 | -------------------------------------------------------------------------------- /scripts/docker/sonar_scanner.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | sonar_scanner_save_dir="/workspace/sonar" 6 | sonar_build_dir="/workspace/build_sonar" 7 | 8 | # ======================== 9 | # clean 10 | # ======================== 11 | if [[ "${CLEAN_BUILD}" = "true" && -d ${sonar_build_dir} ]]; then 12 | print_text_box "Clean build" 13 | rm -fr ${sonar_build_dir} 14 | echo "Removed ${sonar_build_dir}" 15 | fi 16 | 17 | # ======================== 18 | # configure 19 | # ======================== 20 | print_text_box "Configure Sonar build" 21 | cmake \ 22 | -S . \ 23 | -B ${sonar_build_dir} \ 24 | -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ 25 | -DCMAKE_PREFIX_PATH="${THIRD_PARTY_INSTALL_DIR}" \ 26 | -DENABLE_CODE_COVERAGE:BOOL=ON || 27 | error "[Sonar: cmake config] Failed to configure project" 28 | 29 | # ======================== 30 | # build 31 | # ======================== 32 | print_text_box "Sonar Build" 33 | verbose_switch="" 34 | if [ "${VERBOSE_BUILD}" = "true" ]; then 35 | verbose_switch="--verbose" 36 | fi 37 | sonar_out_dir="/workspace/sonar_analysis" 38 | ${SONAR_SAVE_DIR}/build-wrapper-linux-x86/build-wrapper-linux-x86-64 \ 39 | --out-dir ${sonar_out_dir} \ 40 | cmake \ 41 | --build ${sonar_build_dir} \ 42 | --config ${BUILD_TYPE} \ 43 | --parallel \ 44 | ${verbose_switch} || 45 | error "[Sonar: sonar build-wrapper-linux-x86-64 + cmake build] Failed to build project" 46 | 47 | # ======================== 48 | # run 49 | # ======================== 50 | print_text_box "Run" 51 | ${sonar_build_dir}/tests/api/UGridAPITests 52 | 53 | # ======================== 54 | # Generate coverage report 55 | # ======================== 56 | print_text_box "Generate and collect coverage report" 57 | gcov_reports_dir="/workspace/gcov_reports_dir" 58 | # run gcov on all .gcda files found 59 | find ${sonar_build_dir} -iname '*.gcda' -exec gcov -p {} ';' >/dev/null 60 | # make gcov_reports_dir directory to store all coverage results 61 | rm -rf ${gcov_reports_dir} 62 | mkdir ${gcov_reports_dir} 63 | # move the coverage results to gcov_reports_dir 64 | find . -maxdepth 1 -iname '*.gcov' -exec mv {} ${gcov_reports_dir} ';' 65 | echo "Reports saved to ${gcov_reports_dir}" 66 | 67 | # ======================== 68 | # Analyse 69 | # ======================== 70 | print_text_box "Analyse coverage reports" 71 | sonar_scanner_options=( 72 | "-Dsonar.token=${SONAR_TOKEN}" 73 | "-Dsonar.organization=deltares" 74 | "-Dsonar.projectKey=Deltares_UGrid" 75 | "-Dsonar.sources=libs" 76 | "-Dsonar.cfamily.build-wrapper-output=${sonar_out_dir}" 77 | "-Dsonar.host.url=https://sonarcloud.io" 78 | "-Dsonar.branch.name=${BRANCH_NAME}" 79 | "-Dsonar.cpp.std=c++20" 80 | "-Dsonar.cfamily.gcov.reportsPath=${gcov_reports_dir}" 81 | "-Dsonar.cpd.exclusions=libs/UGridNET/**/*" 82 | ) 83 | if [[ "${VERBOSE_BUILD}" = "true" ]]; then 84 | sonar_scanner_options+=("-Dsonar.verbose=true") 85 | fi 86 | if [[ "${BUILD_TYPE}" = "Debug" || "${BUILD_TYPE}" = "RelWithDebInfo" ]]; then 87 | sonar_scanner_options+=("--debug") 88 | fi 89 | 90 | ${SONAR_SAVE_DIR}/sonar-scanner/bin/sonar-scanner "${sonar_scanner_options[@]}" || 91 | error "[Sonar: sonar-scanner] Failed to analyse reports" 92 | -------------------------------------------------------------------------------- /libs/UGridAPI/include/UGridAPI/Network1D.hpp: -------------------------------------------------------------------------------- 1 | //---- GPL --------------------------------------------------------------------- 2 | // 3 | // Copyright (C) Stichting Deltares, 2011-2021. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation version 3. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | // 17 | // contact: delft3d.support@deltares.nl 18 | // Stichting Deltares 19 | // P.O. Box 177 20 | // 2600 MH Delft, The Netherlands 21 | // 22 | // All indications and logos of, and references to, "Delft3D" and "Deltares" 23 | // are registered trademarks of Stichting Deltares, and remain the property of 24 | // Stichting Deltares. All rights reserved. 25 | // 26 | //------------------------------------------------------------------------------ 27 | 28 | #pragma once 29 | 30 | namespace ugridapi 31 | { 32 | /// @brief A struct used to describe UGrid network1d in a C-compatible manner 33 | struct Network1D 34 | { 35 | /// @brief The name of the network 36 | char* name = nullptr; 37 | 38 | /// @brief The node x coordinates 39 | double* node_x = nullptr; 40 | 41 | /// @brief The node y coordinates 42 | double* node_y = nullptr; 43 | 44 | /// @brief The node name 45 | char* node_id = nullptr; 46 | 47 | /// @brief The node long name 48 | char* node_long_name = nullptr; 49 | 50 | /// @brief The node defining each edge 51 | int* edge_nodes = nullptr; 52 | 53 | /// @brief The edge lengths 54 | double* edge_length = nullptr; 55 | 56 | /// @brief The edge order 57 | int* edge_order = nullptr; 58 | 59 | /// @brief The name of the edge 60 | char* edge_id = nullptr; 61 | 62 | /// @brief The long name of the edge 63 | char* edge_long_name = nullptr; 64 | 65 | /// @brief The geometry node x coordinates 66 | double* geometry_nodes_x = nullptr; 67 | 68 | /// @brief The geometry node y coordinates 69 | double* geometry_nodes_y = nullptr; 70 | 71 | /// @brief The number of geometry node on each edge 72 | int* num_edge_geometry_nodes = nullptr; 73 | 74 | /// @brief The number of geometry node 75 | int num_geometry_nodes = 0; 76 | 77 | /// @brief The number of network1d node 78 | int num_nodes = 0; 79 | 80 | /// @brief The number of network1d branches 81 | int num_edges = 0; 82 | 83 | /// @brief 1 If the coordinates are in a spherical system, 0 otherwise 84 | int is_spherical = 0; 85 | 86 | /// @brief The start index used in arrays using indices, such as in the edge_node array 87 | int start_index = 0; 88 | }; 89 | } // namespace ugridapi 90 | -------------------------------------------------------------------------------- /libs/UGrid/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # project name 2 | project( 3 | UGrid 4 | VERSION ${CMAKE_PROJECT_VERSION} 5 | DESCRIPTION "UGrid static library" 6 | LANGUAGES CXX 7 | ) 8 | 9 | # target name 10 | set(TARGET_NAME ${PROJECT_NAME}) 11 | 12 | # static library 13 | add_library(${TARGET_NAME} STATIC) 14 | 15 | # source directories 16 | set(SRC_DIR ${PROJECT_SOURCE_DIR}/src) 17 | 18 | # include directories 19 | set(INC_DIR ${PROJECT_SOURCE_DIR}/include) 20 | set(DOMAIN_INC_DIR ${INC_DIR}/UGrid) 21 | 22 | # list of target sources 23 | set( 24 | SRC_LIST 25 | ${SRC_DIR}/Contacts.cpp 26 | ${SRC_DIR}/Mesh1D.cpp 27 | ${SRC_DIR}/Mesh2D.cpp 28 | ${SRC_DIR}/Network1D.cpp 29 | ${SRC_DIR}/UGridEntity.cpp 30 | ) 31 | 32 | # list of target headers 33 | set( 34 | INC_LIST 35 | ${DOMAIN_INC_DIR}/Constants.hpp 36 | ${DOMAIN_INC_DIR}/Contacts.hpp 37 | ${DOMAIN_INC_DIR}/Mesh1D.hpp 38 | ${DOMAIN_INC_DIR}/Mesh2D.hpp 39 | ${DOMAIN_INC_DIR}/Network1D.hpp 40 | ${DOMAIN_INC_DIR}/Operations.hpp 41 | ${DOMAIN_INC_DIR}/UGridEntity.hpp 42 | ${DOMAIN_INC_DIR}/UGridVarAttributeStringBuilder.hpp 43 | ) 44 | 45 | # add sources to target 46 | target_sources( 47 | ${TARGET_NAME} 48 | PRIVATE 49 | ${SRC_LIST} 50 | PUBLIC 51 | FILE_SET HEADERS 52 | BASE_DIRS 53 | ${INC_DIR} 54 | FILES 55 | ${INC_LIST} 56 | ) 57 | 58 | # Add precompiled header 59 | target_precompile_headers( 60 | ${TARGET_NAME} 61 | PRIVATE 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | ) 72 | 73 | # Expose the interface of the static lib 74 | target_include_directories(${TARGET_NAME} PUBLIC ${INC_DIR} ${PROJECT_SOURCE_DIR}/../UGridAPI/include) 75 | 76 | # Boost 77 | target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${Boost_INCLUDE_DIR}) 78 | 79 | # link required libraries 80 | target_link_libraries( 81 | ${TARGET_NAME} 82 | PUBLIC 83 | netCDF::netcdf 84 | netCDF::netcdf-cxx4 85 | ) 86 | 87 | # Make sure that coverage information is produced when using gcc 88 | if(ENABLE_CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 89 | target_compile_options( 90 | ${TARGET_NAME} 91 | PRIVATE 92 | --coverage # equivalent to -f profile-arcs -ftest-coverage 93 | -static-libgcc 94 | -static-libstdc++ 95 | ) 96 | target_link_libraries(${TARGET_NAME} PRIVATE gcov) 97 | endif() 98 | 99 | install(TARGETS ${TARGET_NAME} FILE_SET HEADERS DESTINATION "include") 100 | 101 | # group the sources in IDE tree 102 | source_group("Source Files" FILES ${SRC_LIST}) 103 | # group the headers in IDE tree 104 | source_group("Header Files" FILES ${INC_LIST}) 105 | 106 | # Add unit tests 107 | # if(ENABLE_UNIT_TESTING) 108 | # add_subdirectory(tests) 109 | # endif() 110 | 111 | # Copy dependencies 112 | add_custom_command( 113 | TARGET ${TARGET_NAME} 114 | POST_BUILD 115 | #COMMAND ${CMAKE_COMMAND} -E echo "Copying ${THIRD_PARTY_RUNTIME_DEPS} to $" 116 | COMMAND ${CMAKE_COMMAND} -E copy -t $ ${THIRD_PARTY_RUNTIME_DEPS} 117 | COMMENT "Copying runtime dependencies..." 118 | ) 119 | -------------------------------------------------------------------------------- /scripts/doxygen_ci.py: -------------------------------------------------------------------------------- 1 | """ 2 | Script which builds the docs of UGrid with doxygen 3 | 4 | It is used to 5 | - check for warnings 6 | - build and push it to Github pages 7 | """ 8 | 9 | import subprocess 10 | import sys 11 | from pathlib import Path 12 | import argparse 13 | 14 | 15 | def configure_doxyfile( 16 | doxyfile_in: Path, 17 | doxyfile_path: Path, 18 | doxygen_log_path: Path, 19 | doxygen_input_list: str, 20 | output_dir: Path, 21 | docs_dir: Path, 22 | fail_with_warnings: bool, 23 | ): 24 | with open(doxyfile_in, "r") as file: 25 | doxyfile_data = file.read() 26 | 27 | doxyfile_data = doxyfile_data.replace("@DOXYGEN_INPUT_LIST@", doxygen_input_list) 28 | doxyfile_data = doxyfile_data.replace( 29 | "@DOXYGEN_OUTPUT_DIR@", str(output_dir.resolve()) 30 | ) 31 | doxyfile_data = doxyfile_data.replace( 32 | "@CMAKE_CURRENT_SOURCE_DIR@", str(docs_dir.resolve()) 33 | ) 34 | doxyfile_data = doxyfile_data.replace( 35 | "@DOXYGEN_WARN_LOG_FILE@", str(doxygen_log_path) 36 | ) 37 | 38 | if fail_with_warnings: 39 | doxyfile_data = doxyfile_data.replace("@DOXYGEN_EXTRACT_PRIVATE@", "TRUE") 40 | else: 41 | doxyfile_data = doxyfile_data.replace("@DOXYGEN_EXTRACT_PRIVATE@", "FALSE") 42 | 43 | with open(doxyfile_path, "w") as file: 44 | file.write(doxyfile_data) 45 | 46 | 47 | def file_empty(file: Path): 48 | return file.stat().st_size == 0 49 | 50 | 51 | def print_file(file: Path): 52 | with open(file, "r") as f: 53 | print(f.read()) 54 | 55 | 56 | # Set dirs 57 | root_dir = Path(__file__).parent.parent 58 | UGrid_include_dir = root_dir / "libs" / "UGrid" / "include" / "UGrid" 59 | UGridapi_include_dir = root_dir / "libs" / "UGridAPI" / "include" / "UGridAPI" 60 | output_dir = root_dir / "build" / "docs" 61 | docs_dir = root_dir / "docs" 62 | 63 | # Set paths 64 | main_page_path = docs_dir / "main_page.md" 65 | doxyfile_in_path = docs_dir / "Doxyfile.in" 66 | doxyfile_path = output_dir / "Doxyfile" 67 | doxygen_log_path = output_dir / "Doxygen_log.txt" 68 | doxygen_input_list = f"{UGrid_include_dir.resolve()} \ 69 | {UGridapi_include_dir.resolve()} \ 70 | {main_page_path.resolve()}" 71 | 72 | # The dir tree is not created automatically 73 | output_dir.parent.mkdir(exist_ok=True) 74 | output_dir.mkdir(exist_ok=True) 75 | 76 | parser = argparse.ArgumentParser() 77 | parser.add_argument( 78 | "--fail-with-warnings", 79 | action="store_true", 80 | help="let the script exit with code 1 with doxygen warnings", 81 | ) 82 | args = parser.parse_args() 83 | 84 | configure_doxyfile( 85 | doxyfile_in_path, 86 | doxyfile_path, 87 | doxygen_log_path, 88 | doxygen_input_list, 89 | output_dir, 90 | docs_dir, 91 | args.fail_with_warnings, 92 | ) 93 | 94 | # Call doxygen 95 | subprocess.call(f"doxygen {doxyfile_path}", shell=True) 96 | 97 | 98 | if args.fail_with_warnings: 99 | # Check if file is empty 100 | # If it is not, there were warnings and we exit with 1 101 | if not file_empty(doxygen_log_path): 102 | print("There were warnings") 103 | print_file(doxygen_log_path) 104 | sys.exit(1) 105 | -------------------------------------------------------------------------------- /libs/UGridNET/nuget/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Configure the nuspec files 2 | project( 3 | UGridNET.NuGetPack 4 | VERSION ${CMAKE_PROJECT_VERSION} 5 | DESCRIPTION "Configures and conditionally generates the UGridNET NuGet package" 6 | LANGUAGES NONE 7 | ) 8 | 9 | set(TARGET_NAME ${PROJECT_NAME}) 10 | 11 | set(NUSPEC_IN ${CMAKE_CURRENT_SOURCE_DIR}/Deltares.UGridNET.nuspec.in) 12 | set(NUPKG_TARGETS ${CMAKE_CURRENT_SOURCE_DIR}/Deltares.UGridNET.targets) 13 | set(NUPKG_README ${CMAKE_CURRENT_SOURCE_DIR}/README.md) 14 | 15 | add_custom_target( 16 | ${TARGET_NAME} ALL 17 | DEPENDS 18 | $<$:$> 19 | $<$:$> 20 | SOURCES 21 | ${NUSPEC_IN} 22 | ${NUPKG_TARGETS} 23 | ${NUPKG_README} 24 | ) 25 | 26 | # generate version string 27 | include(${CMAKE_SOURCE_DIR}/cmake/git_helpers.cmake) 28 | set(VERSION_SUFFIX "") 29 | if(${GIT_FOUND}) 30 | get_current_branch_name(current_branch_name) 31 | is_main_or_release_branch("${current_branch_name}" on_main_or_release_branch) 32 | if(NOT ${on_main_or_release_branch}) 33 | set(VERSION_SUFFIX "-dev") 34 | endif() 35 | endif() 36 | string(JOIN "." NUPKG_VERSION 37 | ${PROJECT_VERSION_MAJOR} 38 | ${PROJECT_VERSION_MINOR} 39 | ${PROJECT_VERSION_PATCH} 40 | ${PROJECT_VERSION_TWEAK} 41 | ) 42 | string(APPEND NUPKG_VERSION ${VERSION_SUFFIX}) 43 | 44 | # Add dependencies and files to nuspec config template 45 | set(NUSPEC_PRECONFIG ${CMAKE_CURRENT_BINARY_DIR}/Deltares.UGridNET.nuspec.preconfig) 46 | set(NUSPEC_CONFIG ${CMAKE_CURRENT_BINARY_DIR}/Deltares.UGridNET.nuspec) 47 | add_custom_command( 48 | TARGET ${TARGET_NAME} 49 | POST_BUILD 50 | COMMAND ${Python_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/configure_nuspec.py 51 | --template ${NUSPEC_IN} 52 | --destination ${NUSPEC_PRECONFIG} 53 | --build_type $ 54 | --dotnet_target_frameworks ${GLOB_LIB_DOTNET_TARGET_FRAMEWORKS} 55 | --runtime_dependencies ${ALL_RUNTIME_DEPS} 56 | COMMAND_EXPAND_LISTS 57 | VERBATIM 58 | COMMENT "Generating nuspec pre-config file" 59 | ) 60 | 61 | # Then substitute the CMake variables 62 | set(CONFIGURE_NUSPEC_SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/configure_nuspec.cmake) 63 | file( 64 | GENERATE 65 | OUTPUT ${CONFIGURE_NUSPEC_SCRIPT} 66 | CONTENT "configure_file(${NUSPEC_PRECONFIG} ${NUSPEC_CONFIG} @ONLY)" 67 | ) 68 | add_custom_command( 69 | TARGET ${TARGET_NAME} 70 | POST_BUILD 71 | COMMAND ${CMAKE_COMMAND} 72 | -DVERSION=${NUPKG_VERSION} 73 | -DCOPYRIGHT_YEAR=${GLOB_CURRENT_YEAR} 74 | -DBUILD_DIR=${CMAKE_BINARY_DIR} 75 | -P ${CONFIGURE_NUSPEC_SCRIPT} 76 | COMMENT "Generating nuspec config file" 77 | ) 78 | 79 | # Copy the targets 80 | configure_file(${NUPKG_TARGETS} ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) 81 | 82 | # Copy the README 83 | configure_file(${NUPKG_README} ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) 84 | 85 | # pack the nuget 86 | if(PACK_NUPKG_LOCALLY) 87 | set(NUPKG_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/packed) 88 | set(NUPKG ${NUPKG_OUT_DIR}/Deltares.UGridNET.${NUPKG_VERSION}) 89 | add_custom_command( 90 | TARGET ${TARGET_NAME} 91 | POST_BUILD 92 | COMMAND ${NUGET_EXECUTABLE} pack ${NUSPEC_CONFIG} 93 | -OutputDirectory ${NUPKG_OUT_DIR} 94 | -Properties Configuration=Release 95 | -Verbosity detailed 96 | COMMENT "Execute NuGet pack" 97 | ) 98 | endif() 99 | -------------------------------------------------------------------------------- /libs/UGridAPI/include/UGridAPI/Mesh1D.hpp: -------------------------------------------------------------------------------- 1 | //---- GPL --------------------------------------------------------------------- 2 | // 3 | // Copyright (C) Stichting Deltares, 2011-2021. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation version 3. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | // 17 | // contact: delft3d.support@deltares.nl 18 | // Stichting Deltares 19 | // P.O. Box 177 20 | // 2600 MH Delft, The Netherlands 21 | // 22 | // All indications and logos of, and references to, "Delft3D" and "Deltares" 23 | // are registered trademarks of Stichting Deltares, and remain the property of 24 | // Stichting Deltares. All rights reserved. 25 | // 26 | //------------------------------------------------------------------------------ 27 | 28 | #pragma once 29 | 30 | #include 31 | 32 | namespace ugridapi 33 | { 34 | /// @brief A struct used to describe UGrid mesh1d in a C-compatible manner 35 | struct Mesh1D 36 | { 37 | /// @brief The mesh1d name 38 | char* name = nullptr; 39 | 40 | /// @brief The network name 41 | char* network_name = nullptr; 42 | 43 | /// @brief The node x coordinate 44 | double* node_x = nullptr; 45 | 46 | /// @brief The node y coordinate 47 | double* node_y = nullptr; 48 | 49 | /// @brief The edge node connectivity 50 | int* edge_nodes = nullptr; 51 | 52 | /// @brief The network edge id where every node lies 53 | int* node_edge_id = nullptr; 54 | 55 | /// @brief The offset of each node on the network branch 56 | double* node_edge_offset = nullptr; 57 | 58 | /// @brief The node name 59 | char* node_id = nullptr; 60 | 61 | /// @brief The node long name 62 | char* node_long_name = nullptr; 63 | 64 | /// @brief The network edge id where every edge lies 65 | int* edge_edge_id = nullptr; 66 | 67 | /// @brief The offset of each edge on the network branch 68 | double* edge_edge_offset = nullptr; 69 | 70 | /// @brief The edge x coordinate 71 | double* edge_x = nullptr; 72 | 73 | /// @brief The edge y coordinate 74 | double* edge_y = nullptr; 75 | 76 | /// @brief The number of node 77 | int num_nodes = 0; 78 | 79 | /// @brief The number of edge 80 | int num_edges = 0; 81 | 82 | /// @brief 1 If coordinates are in a spherical system, 0 otherwise 83 | int is_spherical = 0; 84 | 85 | /// @brief The start index used in arrays using indices, such as edge_node 86 | int start_index = 0; 87 | 88 | /// @brief The fill value for array of doubles 89 | double double_fill_value = ugrid::double_missing_value; 90 | 91 | /// @brief The fill value for array of integers 92 | int int_fill_value = ugrid::int_missing_value; 93 | }; 94 | } // namespace ugridapi 95 | -------------------------------------------------------------------------------- /libs/UGridNET/dll/src/Mesh1DExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UGridNET 4 | { 5 | namespace Extensions 6 | { 7 | internal static class Mesh1DExtensions 8 | { 9 | /// Allocates unmanaged memory for all required properties of the instance. 10 | /// Instance of . 11 | /// Memory allocated by this method must be freed by 12 | public static void Allocate(this Mesh1D mesh1D) 13 | { 14 | try 15 | { 16 | mesh1D.name = IntPtrHelpers.AllocateZeroed(UGrid.name_long_length); 17 | mesh1D.node_long_name = IntPtrHelpers.AllocateZeroed(UGrid.name_long_length * mesh1D.num_nodes); 18 | mesh1D.network_name = IntPtrHelpers.AllocateZeroed(UGrid.name_long_length); 19 | mesh1D.node_x = IntPtrHelpers.AllocateZeroed(mesh1D.num_nodes); 20 | mesh1D.node_y = IntPtrHelpers.AllocateZeroed(mesh1D.num_nodes); 21 | mesh1D.edge_x = IntPtrHelpers.AllocateZeroed(mesh1D.num_edges); 22 | mesh1D.edge_y = IntPtrHelpers.AllocateZeroed(mesh1D.num_edges); 23 | mesh1D.edge_nodes = IntPtrHelpers.AllocateZeroed(mesh1D.num_edges * 2); 24 | mesh1D.edge_edge_id = IntPtrHelpers.AllocateZeroed(mesh1D.num_edges); 25 | mesh1D.node_edge_id = IntPtrHelpers.AllocateZeroed(mesh1D.num_nodes); 26 | mesh1D.node_edge_offset = IntPtrHelpers.AllocateZeroed(mesh1D.num_nodes); 27 | } 28 | catch 29 | { 30 | // AllocHGlobal may throw OutOfMemoryException exception, clean up and re-throw 31 | mesh1D.Free(); 32 | throw; 33 | 34 | } 35 | } 36 | 37 | /// 38 | /// Frees unmanaged memory allocated by for all required properties 39 | /// of the instance. 40 | /// 41 | /// Instance of . 42 | public static void Free(this Mesh1D mesh1D) 43 | { 44 | IntPtrHelpers.Free(() => mesh1D.name, value => mesh1D.name = value); 45 | IntPtrHelpers.Free(() => mesh1D.node_long_name, value => mesh1D.node_long_name = value); 46 | IntPtrHelpers.Free(() => mesh1D.network_name, value => mesh1D.network_name = value); 47 | IntPtrHelpers.Free(() => mesh1D.node_x, value => mesh1D.node_x = value); 48 | IntPtrHelpers.Free(() => mesh1D.node_y, value => mesh1D.node_y = value); 49 | IntPtrHelpers.Free(() => mesh1D.edge_x, value => mesh1D.edge_x = value); 50 | IntPtrHelpers.Free(() => mesh1D.edge_y, value => mesh1D.edge_y = value); 51 | IntPtrHelpers.Free(() => mesh1D.edge_nodes, value => mesh1D.edge_nodes = value); 52 | IntPtrHelpers.Free(() => mesh1D.edge_edge_id, value => mesh1D.edge_edge_id = value); 53 | IntPtrHelpers.Free(() => mesh1D.node_edge_id, value => mesh1D.node_edge_id = value); 54 | IntPtrHelpers.Free(() => mesh1D.node_edge_offset, value => mesh1D.node_edge_offset = value); 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /libs/UGridNET/dll/src/IntPtrHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace UGridNET 5 | { 6 | internal static class IntPtrHelpers 7 | { 8 | /// Allocates unmanaged memory for an array of elements of the specified type. 9 | /// The type of elements for which memory is being allocated. 10 | /// The number of elements to allocate memory for. 11 | /// A pointer to the allocated unmanaged memory if is strictly positive, IntPtr.Zero otherwise . 12 | /// The caller is responsible for freeing the memory using . 13 | public static IntPtr Allocate(int count) where T : struct 14 | { 15 | return count > 0 ? Marshal.AllocHGlobal(count * Marshal.SizeOf()) : IntPtr.Zero; 16 | } 17 | 18 | /// Allocates unmanaged memory for an array of elements of the specified type and initializes it to zero. 19 | /// The type of elements for which memory is being allocated. 20 | /// The number of elements to allocate memory for. 21 | /// A pointer to the allocated and zero-initialized unmanaged memory if is strictly positive, IntPtr.Zero otherwise. 22 | /// The caller is responsible for freeing the memory using . 23 | public static IntPtr AllocateZeroed(int count) where T : struct 24 | { 25 | var ptr = Allocate(count); 26 | if (ptr == IntPtr.Zero) return ptr; 27 | var totalBytes = count * Marshal.SizeOf(); 28 | Marshal.Copy(new byte[totalBytes], 0, ptr, totalBytes); 29 | return ptr; 30 | } 31 | 32 | /// Frees unmanaged memory previously allocated with . 33 | /// A pointer to the unmanaged memory to free. 34 | public static void Free(ref IntPtr ptr) 35 | { 36 | if (ptr == IntPtr.Zero) return; 37 | Marshal.FreeHGlobal(ptr); 38 | ptr = IntPtr.Zero; 39 | } 40 | 41 | /// Frees unmanaged memory previously allocated with . 42 | /// A function that returns the pointer to the unmanaged memory block. 43 | /// An action that sets the pointer to after freeing the memory. 44 | /// 45 | /// This overload is necessary for freeing IntPtr properties which cannot be passed by reference. 46 | /// Such properties are encountered often in SWIG-generated code 47 | /// It first retrieves the pointer using the function. 48 | /// If the pointer is not , it frees the memory using 49 | /// and then sets the pointer to using the action. 50 | /// 51 | public static void Free(Func getPtr, Action setPtr) 52 | { 53 | var ptr = getPtr(); 54 | if (ptr == IntPtr.Zero) return; 55 | Marshal.FreeHGlobal(ptr); 56 | setPtr(IntPtr.Zero); 57 | } 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /libs/UGridNET/SWIG/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project( 2 | UGridCSharpWrapper 3 | VERSION ${CMAKE_PROJECT_VERSION} 4 | DESCRIPTION "C# wrapper around UGridAPI" 5 | LANGUAGES CXX C 6 | ) 7 | 8 | # target name 9 | set(TARGET_NAME ${PROJECT_NAME}) 10 | 11 | # Find SWIG 12 | find_package(SWIG REQUIRED COMPONENTS csharp) 13 | if (NOT SWIG_FOUND) 14 | message(FATAL_ERROR "Could not find SWIG") 15 | endif() 16 | 17 | # relevant directories 18 | set(UGridAPI_ROOT_DIR ${CMAKE_SOURCE_DIR}/libs/UGridAPI) 19 | set(UGridAPI_SRC_DIR ${UGridAPI_ROOT_DIR}/src) 20 | set(UGridAPI_INC_DIR ${UGridAPI_ROOT_DIR}/include) 21 | set(UGridAPI_DOMAIN_INC_DIR ${UGridAPI_INC_DIR}/UGridAPI) 22 | set(VERSION_INC_DIR ${CMAKE_SOURCE_DIR}/package) 23 | 24 | 25 | set(SWIG_INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/interface/UGrid.i) 26 | set(SWIG_OUTPUT_SRC_DIR ${CMAKE_CURRENT_BINARY_DIR}/src) 27 | set(SWIG_OUTPUT_DIR ${SWIG_OUTPUT_SRC_DIR}/csharp) 28 | set(SWIG_OUTFILE_DIR ${SWIG_OUTPUT_SRC_DIR}/cxx) 29 | set(SWIG_CPP_OUTFILE_NAME "${TARGET_NAME}.cxx") 30 | 31 | file(MAKE_DIRECTORY ${SWIG_OUTPUT_DIR}) 32 | file(MAKE_DIRECTORY ${SWIG_OUTFILE_DIR}) 33 | 34 | message(STATUS "Generating code...") 35 | execute_process( 36 | COMMAND ${SWIG_EXECUTABLE} 37 | -v # verbose 38 | -module UGrid # module name 39 | -dllimport ${TARGET_NAME} # override DllImport attribute name to target name 40 | -namespace UGridNET # generate wrappers into the specified C# namespace 41 | -csharp # target language 42 | -c++ # enable c++ processing 43 | -I${UGridAPI_INC_DIR} # look for SWIG files in the specified directory 44 | -outdir ${SWIG_OUTPUT_DIR} # language specific files output directory, C# src in tis case 45 | -o ${SWIG_OUTFILE_DIR}/${SWIG_CPP_OUTFILE_NAME} # name of C/C++ output file 46 | -O # enable optimization 47 | ${SWIG_INTERFACE} 48 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 49 | RESULT_VARIABLE SWIG_RESULT 50 | ERROR_VARIABLE SWIG_ERROR 51 | ECHO_OUTPUT_VARIABLE 52 | ECHO_ERROR_VARIABLE 53 | COMMAND_ERROR_IS_FATAL LAST 54 | ) 55 | 56 | # Get list of generated sources 57 | file(GLOB SWIG_GENERATED_CSHARP_SRCS CONFIGURE_DEPENDS "${SWIG_OUTPUT_DIR}/*.cs") 58 | set(SWIG_GENERATED_CSHARP_SRCS ${SWIG_GENERATED_CSHARP_SRCS} PARENT_SCOPE) 59 | 60 | add_library(${TARGET_NAME} SHARED ${CMAKE_BINARY_DIR}/version.rc) 61 | 62 | set( 63 | SRC_LIST 64 | ${UGridAPI_SRC_DIR}/UGrid.cpp 65 | ${SWIG_OUTFILE_DIR}/${SWIG_CPP_OUTFILE_NAME} 66 | ) 67 | 68 | set( 69 | INC_LIST 70 | ${UGridAPI_DOMAIN_INC_DIR}/Contacts.hpp 71 | ${UGridAPI_DOMAIN_INC_DIR}/Mesh1D.hpp 72 | ${UGridAPI_DOMAIN_INC_DIR}/Mesh2D.hpp 73 | ${UGridAPI_DOMAIN_INC_DIR}/Network1D.hpp 74 | ${UGridAPI_DOMAIN_INC_DIR}/UGrid.hpp 75 | ${UGridAPI_DOMAIN_INC_DIR}/UGridState.hpp 76 | ${VERSION_INC_DIR}/Version/Version.hpp 77 | ) 78 | 79 | target_sources( 80 | ${TARGET_NAME} 81 | PRIVATE 82 | ${SRC_LIST} 83 | PUBLIC 84 | FILE_SET HEADERS 85 | BASE_DIRS 86 | ${UGridAPI_INC_DIR} ${VERSION_INC_DIR} 87 | FILES 88 | ${INC_LIST} 89 | ) 90 | 91 | target_link_libraries( 92 | ${TARGET_NAME} 93 | PUBLIC 94 | "$" 95 | ) 96 | 97 | # group the sources in IDE tree 98 | source_group("Source Files" FILES ${SRC_LIST}) 99 | 100 | # group the headers in IDE tree 101 | source_group("Header Files" FILES ${INC_LIST}) 102 | 103 | -------------------------------------------------------------------------------- /package/version.rc.in: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // VERSIONINFO resource 4 | // 5 | // http://msdn.microsoft.com/en-us/library/windows/desktop/aa381058(v=vs.85).aspx 6 | 7 | // @MAJOR@,@MINOR@,@BUILD@,@PATCH@ 8 | #define VER_FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,@PROJECT_VERSION_TWEAK@ 9 | #define VER_FILEVERSION_STR "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.@PROJECT_VERSION_TWEAK@\0" 10 | 11 | #define VER_PRODUCTVERSION VER_FILEVERSION 12 | #define VER_PRODUCTVERSION_STR VER_FILEVERSION_STR 13 | 14 | 15 | // versionID 16 | // Version-information resource identifier. This value must be 1. 17 | 1 VERSIONINFO 18 | 19 | //// fixed-info 20 | // Binary version number for the file. 21 | FILEVERSION VER_FILEVERSION 22 | 23 | // Binary version number for the product with which the file is distributed. 24 | PRODUCTVERSION VER_PRODUCTVERSION 25 | 26 | // Bits in the FILEFLAGS statement are valid. 27 | FILEFLAGSMASK 0x17L 28 | 29 | // Attributes of the file. 30 | // VS_FF_DEBUG = 1 : File contains debugging information or is compiled with debugging features enabled. 31 | // VS_FF_PATCHED = 4 : File has been modified and is not identical to the original shipping file of the 32 | // same version number. 33 | // VS_FF_PRERELEASE = 2 : File is a development version, not a commercially released product. 34 | // VS_FF_PRIVATEBUILD = 8 : File was not built using standard release procedures. 35 | // VS_FF_SPECIALBUILD = 20 : File was built by the original company using standard release procedures but is a 36 | // : variation of the standard file of the same version number. 37 | #ifdef _DEBUG 38 | FILEFLAGS 0x1L 39 | #else 40 | FILEFLAGS 0x2L 41 | #endif 42 | 43 | // Operating system for which this file was designed. 44 | // VOS_DOS = 0x10000 : File was designed for MS-DOS. 45 | // VOS_NT = 0x40000 : File was designed for 32-bit Windows. 46 | // VOS_WINDOWS16 = 0x1 : File was designed for 16-bit Windows. 47 | // VOS_WINDOWS32 = 0x4 : File was designed for 32-bit Windows. 48 | // VOS_DOS_WINDOWS16 = 0x10001 : File was designed for 16-bit Windows running with MS-DOS. 49 | // VOS_DOS_WINDOWS32 = 0x10004 : File was designed for 32-bit Windows running with MS-DOS. 50 | // VOS_NT_WINDOWS32 = 0x40004 : File was designed for 32-bit Windows. 51 | // NB: appears obsolete, nothing for x64. 52 | FILEOS 0x4L 53 | 54 | // General type of file. 55 | // VFT_APP = 0x1 : File contains an application. 56 | // VFT_DLL = 0x2 : File contains a dynamic-link library (DLL). 57 | // VFT_DRV = 0x3 : File contains a device driver. 58 | // VFT_FONT = 0x4 : File contains a font. 59 | // VFT_VXD = 0x5 : File contains a virtual device. 60 | // VFT_STATIC_LIB = 0x7 : File contains a static-link library. 61 | FILETYPE 0x2L 62 | 63 | // Function of the file. 64 | FILESUBTYPE 0x0L 65 | 66 | BEGIN 67 | BLOCK "StringFileInfo" 68 | BEGIN 69 | BLOCK "080904b0" 70 | BEGIN 71 | VALUE "CompanyName", "Stichting Deltares" 72 | VALUE "FileDescription", "UGrid" 73 | VALUE "FileVersion", VER_FILEVERSION_STR 74 | VALUE "InternalName", "UGrid" 75 | VALUE "LegalCopyright", "Copyright (c) @GLOB_CURRENT_YEAR@ Stichting Deltares" 76 | VALUE "OriginalFilename", "UGrid.dll" 77 | VALUE "ProductName", "UGrid" 78 | VALUE "ProductVersion", VER_PRODUCTVERSION_STR 79 | END 80 | END 81 | 82 | BLOCK "VarFileInfo" 83 | BEGIN 84 | // langID, one of the following language codes. 85 | // 0x409 : U.S. English 86 | // 0x809 : U.K. English 87 | // charsetID, one of the following character-set identifiers. 88 | // 1200 : Unicode 89 | VALUE "Translation", 0x809, 1200 90 | END 91 | END 92 | 93 | // end of file. 94 | -------------------------------------------------------------------------------- /libs/UGrid/include/UGrid/Mesh2D.hpp: -------------------------------------------------------------------------------- 1 | //---- GPL --------------------------------------------------------------------- 2 | // 3 | // Copyright (C) Stichting Deltares, 2011-2021. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation version 3. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | // 17 | // contact: delft3d.support@deltares.nl 18 | // Stichting Deltares 19 | // P.O. Box 177 20 | // 2600 MH Delft, The Netherlands 21 | // 22 | // All indications and logos of, and references to, "Delft3D" and "Deltares" 23 | // are registered trademarks of Stichting Deltares, and remain the property of 24 | // Stichting Deltares. All rights reserved. 25 | // 26 | //------------------------------------------------------------------------------ 27 | 28 | #pragma once 29 | 30 | #include 31 | 32 | #include 33 | 34 | /// \namespace ugrid 35 | /// @brief Contains the logic of the C++ static library 36 | namespace ugrid 37 | { 38 | 39 | /// @brief A class implementing the methods for reading/writing a mesh2d in UGrid format 40 | struct Mesh2D : UGridEntity 41 | { 42 | /// @brief Constructor setting the NetCDF file 43 | /// @param nc_file The NetCDF file pointer 44 | explicit Mesh2D(std::shared_ptr nc_file); 45 | 46 | /// @brief Constructor setting nc_file and all internal state 47 | /// @param nc_file The nc file pointer 48 | /// @param topology_variable The mesh2d name 49 | /// @param entity_attributes The topological attributes (key value pair with key the topological attribute name and value the associated vector of variables) 50 | /// @param entity_attribute_names The topological attributes names (key value pair with key the topological attribute name and value the associated vector of variables names) 51 | /// @param entity_dimensions The dimensions associated with the mesh2d (key value pair with key the dimension enumeration and value the associated NetCDF dimension) 52 | Mesh2D( 53 | std::shared_ptr nc_file, 54 | netCDF::NcVar const& topology_variable, 55 | std::map> const& entity_attributes, 56 | std::map> const& entity_attribute_names, 57 | std::map const& entity_dimensions); 58 | 59 | /// @brief Defines the mesh2d header 60 | /// @param mesh2d The mesh2d api structure with the fields to write and all optional flags 61 | void define(ugridapi::Mesh2D const& mesh2d); 62 | 63 | /// @brief Writes a mesh2d to file 64 | /// @param mesh2d mesh2d The mesh2d api structure with the fields to write and all optional flags 65 | void put(ugridapi::Mesh2D const& mesh2d); 66 | 67 | /// @brief Inquires the mesh2d dimensions 68 | /// @param mesh2d The mesh2d api structure with the fields where to assign the dimensions 69 | void inquire(ugridapi::Mesh2D& mesh2d) const; 70 | 71 | /// @brief Inquires the mesh2d arrays 72 | /// @param mesh2d The mesh2d api structure with the fields where to assign the data 73 | void get(ugridapi::Mesh2D& mesh2d) const; 74 | 75 | /// @brief The dimensionality of a Mesh2D 76 | /// @return The dimensionality 77 | static int get_dimensionality() { return 2; } 78 | }; 79 | } // namespace ugrid 80 | -------------------------------------------------------------------------------- /libs/UGrid/include/UGrid/Mesh1D.hpp: -------------------------------------------------------------------------------- 1 | //---- GPL --------------------------------------------------------------------- 2 | // 3 | // Copyright (C) Stichting Deltares, 2011-2021. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation version 3. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | // 17 | // contact: delft3d.support@deltares.nl 18 | // Stichting Deltares 19 | // P.O. Box 177 20 | // 2600 MH Delft, The Netherlands 21 | // 22 | // All indications and logos of, and references to, "Delft3D" and "Deltares" 23 | // are registered trademarks of Stichting Deltares, and remain the property of 24 | // Stichting Deltares. All rights reserved. 25 | // 26 | //------------------------------------------------------------------------------ 27 | 28 | #pragma once 29 | 30 | #include 31 | 32 | #include 33 | 34 | /// \namespace ugrid 35 | /// @brief Contains the logic of the C++ static library 36 | namespace ugrid 37 | { 38 | 39 | /// @brief A class implementing the methods for reading/writing a mesh1d in UGrid format 40 | struct Mesh1D : UGridEntity 41 | { 42 | /// @brief Constructor setting the NetCDF file 43 | /// @param nc_file The NetCDF file pointer 44 | explicit Mesh1D(std::shared_ptr nc_file); 45 | 46 | /// @brief Constructor setting nc_file and all internal state 47 | /// @param nc_file The nc file pointer 48 | /// @param topology_variable The mesh1d name 49 | /// @param entity_attributes The topological attributes (key value pair with key the topological attribute name and value the associated vector of variables) 50 | /// @param entity_attribute_names The topological attributes names (key value pair with key the topological attribute name and value the associated vector of variables names) 51 | /// @param entity_dimensions The dimensions associated with the mesh1d (key value pair with key the dimension enumeration and value the associated NetCDF dimension) 52 | Mesh1D(std::shared_ptr nc_file, 53 | netCDF::NcVar const& topology_variable, 54 | std::map> const& entity_attributes, 55 | std::map> const& entity_attribute_names, 56 | std::map const& entity_dimensions); 57 | 58 | /// @brief Defines the mesh1d header (ug_write_mesh_arrays, ug_create_1d_mesh_v2, ug_def_mesh_ids) 59 | /// @param mesh1d The mesh1d api structure with the fields to write and all optional flags 60 | void define(ugridapi::Mesh1D const& mesh1d); 61 | 62 | /// @brief Writes a mesh1d to file 63 | /// @param mesh1d mesh1d The mesh1d api structure with the fields to write and all optional flags 64 | void put(ugridapi::Mesh1D const& mesh1d); 65 | 66 | /// @brief Inquires the mesh1d dimensions 67 | /// @param mesh1d The mesh1d api structure with the fields where to assign the dimensions 68 | void inquire(ugridapi::Mesh1D& mesh1d) const; 69 | 70 | /// @brief Inquires the mesh1d arrays 71 | /// @param mesh1d The mesh1d api structure with the fields where to assign the data 72 | void get(ugridapi::Mesh1D& mesh1d) const; 73 | 74 | /// @brief Get the dimensionality of a Mesh1d 75 | /// @return The dimensionality 76 | static int get_dimensionality() { return 1; } 77 | }; 78 | } // namespace ugrid -------------------------------------------------------------------------------- /libs/UGridNET/test/src/IntPtrHelpersTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace UGridNET.Tests 7 | { 8 | public class IntPtrHelpersBasicTests 9 | { 10 | [Test] 11 | public void AllocateValidTypeReturnsNonZeroPointerInt() 12 | { 13 | AllocateValidTypeReturnsNonZeroPointer(10); 14 | } 15 | 16 | [Test] 17 | public void AllocateValidTypeReturnsNonZeroPointerDouble() 18 | { 19 | AllocateValidTypeReturnsNonZeroPointer(10); 20 | } 21 | 22 | [Test] 23 | public void AllocateValidTypeReturnsNonZeroPointerByte() 24 | { 25 | AllocateValidTypeReturnsNonZeroPointer(10); 26 | } 27 | 28 | private void AllocateValidTypeReturnsNonZeroPointer(int count) where T : struct 29 | { 30 | var ptr = IntPtr.Zero; 31 | Assert.DoesNotThrow(() => ptr = IntPtrHelpers.Allocate(count)); 32 | Assert.That(ptr, Is.Not.EqualTo(IntPtr.Zero)); 33 | IntPtrHelpers.Free(ref ptr); 34 | } 35 | 36 | [Test] 37 | public void AllocateZeroedValidTypeReturnsNonZeroPointerInt() 38 | { 39 | AllocateZeroedValidTypeReturnsNonZeroPointer(10); 40 | } 41 | 42 | [Test] 43 | public void AllocateZeroedValidTypeReturnsNonZeroPointerDouble() 44 | { 45 | AllocateZeroedValidTypeReturnsNonZeroPointer(10); 46 | } 47 | 48 | [Test] 49 | public void AllocateZeroedValidTypeReturnsNonZeroPointerByte() 50 | { 51 | AllocateZeroedValidTypeReturnsNonZeroPointer(10); 52 | } 53 | 54 | private void AllocateZeroedValidTypeReturnsNonZeroPointer(int count) where T : struct 55 | { 56 | var ptr = IntPtr.Zero; 57 | Assert.DoesNotThrow(() => ptr = IntPtrHelpers.AllocateZeroed(count)); 58 | Assert.That(ptr, Is.Not.EqualTo(IntPtr.Zero)); 59 | IntPtrHelpers.Free(ref ptr); 60 | } 61 | 62 | [Test] 63 | public void AllocateZeroedInitializesMemoryToZeroInt() 64 | { 65 | AllocateZeroedInitializesMemoryToZero(5); 66 | } 67 | 68 | [Test] 69 | public void AllocateZeroedInitializesMemoryToZeroDouble() 70 | { 71 | AllocateZeroedInitializesMemoryToZero(5); 72 | } 73 | 74 | [Test] 75 | public void AllocateZeroedInitializesMemoryToZeroByte() 76 | { 77 | AllocateZeroedInitializesMemoryToZero(5); 78 | } 79 | 80 | private void AllocateZeroedInitializesMemoryToZero(int count) where T : struct 81 | { 82 | var ptr = IntPtrHelpers.AllocateZeroed(count); 83 | 84 | var totalBytes = count * Marshal.SizeOf(); 85 | var buffer = new byte[totalBytes]; 86 | Marshal.Copy(ptr, buffer, 0, totalBytes); 87 | 88 | Assert.That(buffer, Is.All.Zero); 89 | 90 | IntPtrHelpers.Free(ref ptr); 91 | } 92 | } 93 | 94 | public class IntPtrHelpersClassWithPropertyTests 95 | { 96 | 97 | private class ClassWithProperty 98 | { 99 | public IntPtr Pointer { set; get; } 100 | } 101 | 102 | [Test] 103 | public void AllocateAnFreeAClassProperty() 104 | { 105 | var classWithProperty = new ClassWithProperty(); 106 | const int count = 10; 107 | Assert.DoesNotThrow(() => classWithProperty.Pointer = IntPtrHelpers.Allocate(count)); 108 | Assert.That(classWithProperty.Pointer, Is.Not.EqualTo(IntPtr.Zero)); 109 | IntPtrHelpers.Free(() => classWithProperty.Pointer, value => classWithProperty.Pointer = value); 110 | Assert.That(classWithProperty.Pointer, Is.EqualTo(IntPtr.Zero)); 111 | } 112 | 113 | } 114 | } -------------------------------------------------------------------------------- /libs/UGridNET/dll/src/DisposableMesh1D.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace UGridNET 8 | { 9 | public sealed class DisposableMesh1D : DisposableNativeObject 10 | { 11 | private byte[] name; 12 | 13 | private byte[] networkName; 14 | 15 | private int numNodes; 16 | 17 | private int numEdges; 18 | 19 | private double[] nodeX; 20 | 21 | private double[] nodeY; 22 | 23 | private int[] nodeEdgeID; 24 | 25 | private double[] nodeEdgeOffset; 26 | 27 | private double[] edgeX; 28 | 29 | private double[] edgeY; 30 | 31 | private int[] edgeNodes; 32 | 33 | public DisposableMesh1D() {} 34 | 35 | public DisposableMesh1D(int nNodes, int nEdges) 36 | { 37 | NumNodes = nNodes; 38 | NumEdges = nEdges; 39 | 40 | Name = new byte[UGrid.name_long_length]; 41 | NetworkName = new byte[UGrid.name_long_length]; 42 | 43 | NodeX = new double[NumNodes]; 44 | NodeY = new double[NumNodes]; 45 | NodeEdgeID = new int[NumNodes]; 46 | NodeEdgeOffset = new double[NumNodes]; 47 | 48 | EdgeX = new double[NumEdges]; 49 | EdgeY = new double[NumEdges]; 50 | EdgeNodes = new int[NumEdges * 2]; 51 | } 52 | 53 | ~DisposableMesh1D() 54 | { 55 | Dispose(false); 56 | } 57 | 58 | public byte[] Name 59 | { 60 | get { return name; } 61 | set { name = value; } 62 | } 63 | 64 | public byte[] NetworkName 65 | { 66 | get { return networkName; } 67 | set { networkName = value; } 68 | } 69 | 70 | public int NumNodes 71 | { 72 | get { return numNodes; } 73 | set { numNodes = value; } 74 | } 75 | 76 | public int NumEdges 77 | { 78 | get { return numEdges; } 79 | set { numEdges = value; } 80 | } 81 | 82 | public double[] NodeX 83 | { 84 | get { return nodeX; } 85 | set { nodeX = value; } 86 | } 87 | 88 | public double[] NodeY 89 | { 90 | get { return nodeY; } 91 | set { nodeY = value; } 92 | } 93 | 94 | public int[] NodeEdgeID 95 | { 96 | get { return nodeEdgeID; } 97 | set { nodeEdgeID = value; } 98 | } 99 | 100 | public double[] NodeEdgeOffset 101 | { 102 | get { return nodeEdgeOffset; } 103 | set { nodeEdgeOffset = value; } 104 | } 105 | 106 | public double[] EdgeX 107 | { 108 | get { return edgeX; } 109 | set { edgeX = value; } 110 | } 111 | 112 | public double[] EdgeY 113 | { 114 | get { return edgeY; } 115 | set { edgeY = value; } 116 | } 117 | 118 | public int[] EdgeNodes 119 | { 120 | get { return edgeNodes; } 121 | set { edgeNodes = value; } 122 | } 123 | 124 | protected override void SetNativeObject(ref Mesh1D mesh2D) 125 | { 126 | mesh2D.name = GetPinnedObjectPointer(Name); 127 | mesh2D.network_name = GetPinnedObjectPointer(NetworkName); 128 | 129 | mesh2D.num_nodes = NumNodes; 130 | mesh2D.num_edges = NumEdges; 131 | 132 | mesh2D.node_x = GetPinnedObjectPointer(NodeX); 133 | mesh2D.node_y = GetPinnedObjectPointer(NodeY); 134 | mesh2D.node_edge_id = GetPinnedObjectPointer(NodeEdgeID); 135 | mesh2D.node_edge_offset = GetPinnedObjectPointer(NodeEdgeOffset); 136 | 137 | mesh2D.edge_x = GetPinnedObjectPointer(EdgeX); 138 | mesh2D.edge_y = GetPinnedObjectPointer(EdgeY); 139 | mesh2D.edge_nodes = GetPinnedObjectPointer(EdgeNodes); 140 | } 141 | } 142 | } -------------------------------------------------------------------------------- /libs/UGridNET/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project( 2 | UGridNET.Tests 3 | VERSION ${CMAKE_PROJECT_VERSION} 4 | DESCRIPTION "UGrid C# API tests" 5 | LANGUAGES CSharp 6 | ) 7 | 8 | # target name 9 | set(TARGET_NAME ${PROJECT_NAME}) 10 | 11 | set(NUGET_CONFIG ${CMAKE_CURRENT_BINARY_DIR}/NuGet.config) 12 | configure_file( 13 | ${CMAKE_CURRENT_SOURCE_DIR}/../config/NuGet.config 14 | ${NUGET_CONFIG} 15 | COPYONLY 16 | ) 17 | 18 | list(LENGTH GLOB_TEST_DOTNET_TARGET_FRAMEWORKS LIST_LENGTH) 19 | if(${LIST_LENGTH} EQUAL 1) 20 | set(PROJECT_DOTNET_TARGET_FRAMEWORKS_TAG "TargetFramework") 21 | else() 22 | set(PROJECT_DOTNET_TARGET_FRAMEWORKS_TAG "TargetFrameworks") 23 | endif() 24 | set(PROJECT_DOTNET_TARGET_FRAMEWORKS ${GLOB_TEST_DOTNET_TARGET_FRAMEWORKS}) 25 | set(DIRECTORY_BUILD_PROPS ${CMAKE_CURRENT_BINARY_DIR}/Directory.Build.props) 26 | configure_file( 27 | ${CMAKE_CURRENT_SOURCE_DIR}/../config/Directory.Build.props.in 28 | ${DIRECTORY_BUILD_PROPS} 29 | @ONLY 30 | ) 31 | 32 | set(DIRECTORY_PACKAGES_PROPS ${CMAKE_CURRENT_BINARY_DIR}/Directory.Packages.props) 33 | configure_file( 34 | ${CMAKE_CURRENT_SOURCE_DIR}/Directory.Packages.props 35 | ${DIRECTORY_PACKAGES_PROPS} 36 | COPYONLY 37 | ) 38 | 39 | execute_process( 40 | COMMAND ${Python_EXECUTABLE} 41 | ${CMAKE_SOURCE_DIR}/scripts/get_package_ids_from_directory_packages_props.py 42 | ${DIRECTORY_PACKAGES_PROPS} 43 | OUTPUT_VARIABLE PACKAGE_REFERENCES 44 | RESULT_VARIABLE RETURN_CODE 45 | OUTPUT_STRIP_TRAILING_WHITESPACE 46 | COMMAND_ERROR_IS_FATAL LAST 47 | ) 48 | 49 | add_library( 50 | ${TARGET_NAME} 51 | SHARED 52 | ${NUGET_CONFIG} 53 | ${DIRECTORY_PACKAGES_PROPS} 54 | ${DIRECTORY_BUILD_PROPS} 55 | src/ByteArrayExtensionsTests.cs 56 | src/IntPtrExtensionsTests.cs 57 | src/IntPtrHelpersTests.cs 58 | src/StringExtensionsTests.cs 59 | src/SWIGTests.cs 60 | src/TestUtilities.cs 61 | src/TopologyExtensionsTests.cs 62 | src/UGridNETExceptionTests.cs 63 | src/UGridReaderTests.cs 64 | src/UGridWriterTests.cs 65 | ) 66 | 67 | target_link_libraries(${TARGET_NAME} PRIVATE "$") 68 | 69 | set_target_properties( 70 | ${TARGET_NAME} 71 | PROPERTIES 72 | DOTNET_TARGET_FRAMEWORK "${GLOB_TEST_DOTNET_TARGET_FRAMEWORKS}" 73 | DOTNET_SDK ${GLOB_DOTNET_SDK} 74 | VS_PACKAGE_REFERENCES "${PACKAGE_REFERENCES}" 75 | VS_GLOBAL_PlatformTarget "AnyCPU" 76 | #VS_GLOBAL_AppendTargetFrameworkToOutputPath "true" 77 | VS_DOTNET_REFERENCEPROP_UGridNET_TAG_SetTargetFramework "TargetFramework=netstandard2.0" 78 | ) 79 | 80 | target_compile_options(${TARGET_NAME} PRIVATE "/platform:anycpu") 81 | 82 | # add_custom_command( 83 | # TARGET ${TARGET_NAME} 84 | # PRE_BUILD 85 | # COMMAND ${Python_EXECUTABLE} 86 | # ${CMAKE_SOURCE_DIR}/scripts/append_target_framework_to_output_path_in_csproj.py 87 | # ${CMAKE_CURRENT_BINARY_DIR}/UGridNET.Test.csproj 88 | # COMMENT "Configure CS projects to append the target framework to the output path" 89 | # ) 90 | 91 | # restore nuget packages 92 | add_custom_command( 93 | TARGET ${TARGET_NAME} 94 | PRE_BUILD 95 | COMMAND ${NUGET_EXECUTABLE} restore ${CMAKE_CURRENT_BINARY_DIR}/UGridNET.Tests.sln 96 | -Force 97 | -NoHttpCache 98 | -Verbosity detailed 99 | -ConfigFile ${CMAKE_CURRENT_BINARY_DIR}//NuGet.config 100 | COMMENT "Restore NuGet packages" 101 | ) 102 | 103 | # create empty list of the commands which must to be called in the custom target 104 | set(TARGET_COMMANDS) 105 | 106 | # For each test .NET target framework, UGridNET.Test needs the third party dependencies and the SWIG-generated dependencies 107 | foreach(FRAMEWORK ${GLOB_TEST_DOTNET_TARGET_FRAMEWORKS}) 108 | list( 109 | APPEND 110 | TARGET_COMMANDS 111 | COMMAND ${CMAKE_COMMAND} -E echo "Copying ${ALL_RUNTIME_DEPS} to $/${FRAMEWORK}" 112 | COMMAND ${CMAKE_COMMAND} -E copy -t $/${FRAMEWORK} ${ALL_RUNTIME_DEPS} 113 | ) 114 | endforeach() 115 | 116 | 117 | add_custom_command( 118 | TARGET ${TARGET_NAME} 119 | POST_BUILD 120 | ${TARGET_COMMANDS} 121 | COMMENT "Copying runtime dependencies..." 122 | ) -------------------------------------------------------------------------------- /libs/UGridNET/dll/src/Network1DExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UGridNET 4 | { 5 | namespace Extensions 6 | { 7 | internal static class Network1DExtensions 8 | { 9 | /// Allocates unmanaged memory for all required properties of the instance. 10 | /// Instance of . 11 | /// Memory allocated by this method must be freed by 12 | public static void Allocate(this Network1D network1D) 13 | { 14 | try 15 | { 16 | network1D.name = IntPtrHelpers.AllocateZeroed(UGrid.name_long_length); 17 | network1D.node_id = IntPtrHelpers.AllocateZeroed(UGrid.name_length * network1D.num_nodes); 18 | network1D.node_long_name = IntPtrHelpers.AllocateZeroed(UGrid.name_long_length * network1D.num_nodes); 19 | network1D.edge_id = IntPtrHelpers.AllocateZeroed(UGrid.name_length * network1D.num_edges); 20 | network1D.edge_long_name = IntPtrHelpers.AllocateZeroed(UGrid.name_long_length * network1D.num_edges); 21 | network1D.node_x = IntPtrHelpers.AllocateZeroed(network1D.num_nodes); 22 | network1D.node_y = IntPtrHelpers.AllocateZeroed(network1D.num_nodes); 23 | network1D.edge_nodes = IntPtrHelpers.AllocateZeroed(network1D.num_edges * 2); 24 | network1D.edge_length = IntPtrHelpers.AllocateZeroed(network1D.num_edges); 25 | network1D.edge_order = IntPtrHelpers.AllocateZeroed(network1D.num_edges); 26 | network1D.geometry_nodes_x = IntPtrHelpers.AllocateZeroed(network1D.num_geometry_nodes); 27 | network1D.geometry_nodes_y = IntPtrHelpers.AllocateZeroed(network1D.num_geometry_nodes); 28 | network1D.num_edge_geometry_nodes = IntPtrHelpers.AllocateZeroed(network1D.num_edges); 29 | } 30 | catch 31 | { 32 | // AllocHGlobal may throw OutOfMemoryException exception, clean up and re-throw 33 | network1D.Free(); 34 | throw; 35 | } 36 | } 37 | 38 | /// 39 | /// Frees unmanaged memory allocated by for all required properties 40 | /// of the instance. 41 | /// 42 | /// Instance of . 43 | public static void Free(this Network1D network1D) 44 | { 45 | IntPtrHelpers.Free(() => network1D.name, value => network1D.name = value); 46 | IntPtrHelpers.Free(() => network1D.node_id, value => network1D.node_id = value); 47 | IntPtrHelpers.Free(() => network1D.node_long_name, value => network1D.node_long_name = value); 48 | IntPtrHelpers.Free(() => network1D.edge_id, value => network1D.edge_id = value); 49 | IntPtrHelpers.Free(() => network1D.edge_long_name, value => network1D.edge_long_name = value); 50 | IntPtrHelpers.Free(() => network1D.node_x, value => network1D.node_x = value); 51 | IntPtrHelpers.Free(() => network1D.node_y, value => network1D.node_y = value); 52 | IntPtrHelpers.Free(() => network1D.edge_nodes, value => network1D.edge_nodes = value); 53 | IntPtrHelpers.Free(() => network1D.edge_length, value => network1D.edge_length = value); 54 | IntPtrHelpers.Free(() => network1D.edge_order, value => network1D.edge_order = value); 55 | IntPtrHelpers.Free(() => network1D.geometry_nodes_x, value => network1D.geometry_nodes_x = value); 56 | IntPtrHelpers.Free(() => network1D.geometry_nodes_y, value => network1D.geometry_nodes_y = value); 57 | IntPtrHelpers.Free(() => network1D.num_edge_geometry_nodes, value => network1D.num_edge_geometry_nodes = value); 58 | } 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /libs/UGridNET/dll/src/Mesh2DExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UGridNET 4 | { 5 | namespace Extensions 6 | { 7 | internal static class Mesh2DExtensions 8 | { 9 | /// Allocates unmanaged memory for all required properties of the instance. 10 | /// Instance of . 11 | /// Memory allocated by this method must be freed by 12 | public static void Allocate(this Mesh2D mesh2D) 13 | { 14 | try 15 | { 16 | mesh2D.name = IntPtrHelpers.AllocateZeroed(UGrid.name_long_length); 17 | mesh2D.node_x = IntPtrHelpers.AllocateZeroed(mesh2D.num_nodes); 18 | mesh2D.node_y = IntPtrHelpers.AllocateZeroed(mesh2D.num_nodes); 19 | mesh2D.node_z = IntPtrHelpers.AllocateZeroed(mesh2D.num_nodes); 20 | mesh2D.edge_x = IntPtrHelpers.AllocateZeroed(mesh2D.num_edges); 21 | mesh2D.edge_y = IntPtrHelpers.AllocateZeroed(mesh2D.num_edges); 22 | mesh2D.edge_z = IntPtrHelpers.AllocateZeroed(mesh2D.num_edges); 23 | mesh2D.face_x = IntPtrHelpers.AllocateZeroed(mesh2D.num_faces); 24 | mesh2D.face_y = IntPtrHelpers.AllocateZeroed(mesh2D.num_faces); 25 | mesh2D.face_z = IntPtrHelpers.AllocateZeroed(mesh2D.num_faces); 26 | mesh2D.edge_nodes = IntPtrHelpers.AllocateZeroed(mesh2D.num_edges * 2); 27 | mesh2D.edge_faces = IntPtrHelpers.AllocateZeroed(mesh2D.num_edges * 2); 28 | mesh2D.face_nodes = IntPtrHelpers.AllocateZeroed(mesh2D.num_faces * mesh2D.num_face_nodes_max); 29 | mesh2D.face_edges = IntPtrHelpers.AllocateZeroed(mesh2D.num_faces * mesh2D.num_face_nodes_max); 30 | mesh2D.face_faces = IntPtrHelpers.AllocateZeroed(mesh2D.num_faces * mesh2D.num_face_nodes_max); 31 | } 32 | catch 33 | { 34 | // AllocHGlobal may throw OutOfMemoryException exception, clean up and re-throw 35 | mesh2D.Free(); 36 | throw; 37 | } 38 | } 39 | 40 | /// 41 | /// Frees unmanaged memory allocated by for all required properties 42 | /// of the instance. 43 | /// 44 | /// Instance of . 45 | public static void Free(this Mesh2D mesh2D) 46 | { 47 | IntPtrHelpers.Free(() => mesh2D.name, value => mesh2D.name = value); 48 | IntPtrHelpers.Free(() => mesh2D.node_x, value => mesh2D.node_x = value); 49 | IntPtrHelpers.Free(() => mesh2D.node_y, value => mesh2D.node_y = value); 50 | IntPtrHelpers.Free(() => mesh2D.node_z, value => mesh2D.node_z = value); 51 | IntPtrHelpers.Free(() => mesh2D.edge_x, value => mesh2D.edge_x = value); 52 | IntPtrHelpers.Free(() => mesh2D.edge_y, value => mesh2D.edge_y = value); 53 | IntPtrHelpers.Free(() => mesh2D.edge_z, value => mesh2D.edge_z = value); 54 | IntPtrHelpers.Free(() => mesh2D.face_x, value => mesh2D.face_x = value); 55 | IntPtrHelpers.Free(() => mesh2D.face_y, value => mesh2D.face_y = value); 56 | IntPtrHelpers.Free(() => mesh2D.face_z, value => mesh2D.face_z = value); 57 | IntPtrHelpers.Free(() => mesh2D.edge_nodes, value => mesh2D.edge_nodes = value); 58 | IntPtrHelpers.Free(() => mesh2D.edge_faces, value => mesh2D.edge_faces = value); 59 | IntPtrHelpers.Free(() => mesh2D.face_nodes, value => mesh2D.face_nodes = value); 60 | IntPtrHelpers.Free(() => mesh2D.face_edges, value => mesh2D.face_edges = value); 61 | IntPtrHelpers.Free(() => mesh2D.face_faces, value => mesh2D.face_faces = value); 62 | } 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /libs/UGridAPI/include/UGridAPI/Mesh2D.hpp: -------------------------------------------------------------------------------- 1 | //---- GPL --------------------------------------------------------------------- 2 | // 3 | // Copyright (C) Stichting Deltares, 2011-2021. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation version 3. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | // 17 | // contact: delft3d.support@deltares.nl 18 | // Stichting Deltares 19 | // P.O. Box 177 20 | // 2600 MH Delft, The Netherlands 21 | // 22 | // All indications and logos of, and references to, "Delft3D" and "Deltares" 23 | // are registered trademarks of Stichting Deltares, and remain the property of 24 | // Stichting Deltares. All rights reserved. 25 | // 26 | //------------------------------------------------------------------------------ 27 | 28 | #pragma once 29 | 30 | #include 31 | 32 | namespace ugridapi 33 | { 34 | /// @brief A struct used to describe UGrid mesh2d in a C-compatible manner 35 | struct Mesh2D 36 | { 37 | /// @brief The mesh2d name 38 | char* name = nullptr; 39 | 40 | /// @brief The edge node connectivity 41 | int* edge_nodes = nullptr; 42 | 43 | /// @brief The node composing each face 44 | int* face_nodes = nullptr; 45 | 46 | /// @brief The node x coordinates 47 | double* node_x = nullptr; 48 | 49 | /// @brief The node y coordinates 50 | double* node_y = nullptr; 51 | 52 | /// @brief The edge x coordinate 53 | double* edge_x = nullptr; 54 | 55 | /// @brief The edge y coordinate 56 | double* edge_y = nullptr; 57 | 58 | /// @brief The face x coordinates 59 | double* face_x = nullptr; 60 | 61 | /// @brief The face y coordinates 62 | double* face_y = nullptr; 63 | 64 | /// @brief The edge composing each face 65 | int* edge_faces = nullptr; 66 | 67 | /// @brief For each face, the edge composing it 68 | int* face_edges = nullptr; 69 | 70 | /// @brief For each face, the neighboring face 71 | int* face_faces = nullptr; 72 | 73 | /// @brief The node z coordinates 74 | double* node_z = nullptr; 75 | 76 | /// @brief The edge z coordinates 77 | double* edge_z = nullptr; 78 | 79 | /// @brief The face z coordinates 80 | double* face_z = nullptr; 81 | 82 | /// @brief The z coordinates of a layer 83 | double* layer_zs = nullptr; 84 | 85 | /// @brief The z coordinates of a layer interface 86 | double* interface_zs = nullptr; 87 | 88 | /// @brief TODO to be detailed 89 | double* boundary_node_connectivity = nullptr; 90 | 91 | /// @brief TODO to be detailed 92 | double* volume_coordinates = nullptr; 93 | 94 | /// @brief The number of node 95 | int num_nodes = 0; 96 | 97 | /// @brief The number of edge 98 | int num_edges = 0; 99 | 100 | /// @brief The number of face 101 | int num_faces = 0; 102 | 103 | /// @brief The number of layers 104 | int num_layers = 0; 105 | 106 | /// @brief The start index used in arrays using indices, such as edge_node 107 | int start_index = 0; 108 | 109 | /// @brief The maximum number of face node 110 | int num_face_nodes_max = 4; 111 | 112 | /// @brief 1 if coordinates are in a spherical system, 0 otherwise 113 | int is_spherical = 0; 114 | 115 | /// @brief The fill value for array of doubles 116 | double double_fill_value = ugrid::double_missing_value; 117 | 118 | /// @brief The fill value for array of integers 119 | int int_fill_value = ugrid::int_missing_value; 120 | }; 121 | } // namespace ugridapi 122 | -------------------------------------------------------------------------------- /cmake/install_tools.cmake: -------------------------------------------------------------------------------- 1 | if(WIN32) 2 | 3 | function(check_arguments function_name args_prefix required_args) 4 | set(missing_required_args FALSE) 5 | set(missing_args_msg "") 6 | foreach(arg IN LISTS required_args) 7 | if (NOT DEFINED ${args_prefix}_${arg}) 8 | string(APPEND missing_args_msg " ${arg} argument is required but it was not provided.\n") 9 | set(missing_required_args TRUE) 10 | endif() 11 | endforeach() 12 | if(missing_required_args) 13 | message(FATAL_ERROR "Error in function ${function_name}: One or more required arguments are missing.\n${missing_args_msg}") 14 | endif() 15 | endfunction() 16 | 17 | # Downloads and installs SWIG 18 | function(install_swig) 19 | set(prefix ARGS) 20 | set(options SWIG_CLEAN) 21 | set(one_value_args SWIG_VERSION SWIG_INSTALL_PREFIX SWIG_DIR_OUT SWIG_EXECUTABLE_OUT) 22 | set(multi_value_args "") 23 | 24 | # Parse the arguments 25 | cmake_parse_arguments( 26 | "${prefix}" 27 | "${options}" 28 | "${one_value_args}" 29 | "${multi_value_args}" 30 | ${ARGN} 31 | ) 32 | 33 | # Check if all required arguments are provided 34 | set(required_args ${options} ${one_value_args} ${multi_value_args}) 35 | check_arguments("${CMAKE_CURRENT_FUNCTION}" "${prefix}" "${required_args}") 36 | 37 | message(STATUS "Installing SWIG ${ARGS_SWIG_VERSION}...") 38 | 39 | # Set the download URL and file paths 40 | set(SWIG_URL "http://prdownloads.sourceforge.net/swig/swigwin-${ARGS_SWIG_VERSION}.zip") 41 | set(DOWNLOAD_DIR "${ARGS_SWIG_INSTALL_PREFIX}/download") 42 | 43 | # Create the download and extraction directories 44 | file(MAKE_DIRECTORY ${ARGS_SWIG_INSTALL_PREFIX}) 45 | file(MAKE_DIRECTORY ${DOWNLOAD_DIR}) 46 | 47 | # Download the SWIG zip file 48 | set(SWIG_ZIP "${DOWNLOAD_DIR}/swigwin-${ARGS_SWIG_VERSION}.zip") 49 | if(NOT EXISTS ${SWIG_ZIP}) 50 | file(DOWNLOAD ${SWIG_URL} ${SWIG_ZIP}) 51 | endif() 52 | 53 | # Unzip the downloaded file 54 | set(INSTALL_DIR ${ARGS_SWIG_INSTALL_PREFIX}/swigwin-${ARGS_SWIG_VERSION}) 55 | if(NOT EXISTS ${INSTALL_DIR}) 56 | file(ARCHIVE_EXTRACT 57 | INPUT ${SWIG_ZIP} 58 | DESTINATION ${ARGS_SWIG_INSTALL_PREFIX}) 59 | endif() 60 | 61 | # Remove the zip file after extraction 62 | if(${ARGS_SWIG_CLEAN}) 63 | file(REMOVE_RECURSE ${DOWNLOAD_DIR}) 64 | endif() 65 | 66 | # Set the output 67 | set(LIBRARY_DIR ${INSTALL_DIR}/Lib) 68 | set(EXECUTABLE_DIR ${INSTALL_DIR}/swig.exe) 69 | set(${ARGS_SWIG_DIR_OUT} "${LIBRARY_DIR}" PARENT_SCOPE) 70 | set(${ARGS_SWIG_EXECUTABLE_OUT} "${EXECUTABLE_DIR}" PARENT_SCOPE) 71 | 72 | # Summary 73 | message(STATUS "SWIG ${ARGS_SWIG_VERSION} installed to ${INSTALL_DIR}") 74 | endfunction() 75 | 76 | # Dowanlod and install nuget 77 | function(install_nuget) 78 | 79 | set(prefix ARGS) 80 | set(options "") 81 | set(one_value_args NUGET_VERSION NUGET_INSTALL_PREFIX NUGET_EXECUTABLE_OUT) 82 | set(multi_value_args "") 83 | 84 | # Parse the arguments 85 | cmake_parse_arguments( 86 | "${prefix}" 87 | "${options}" 88 | "${one_value_args}" 89 | "${multi_value_args}" 90 | ${ARGN} 91 | ) 92 | 93 | # Check if all required arguments are provided 94 | set(required_args ${options} ${one_value_args} ${multi_value_args}) 95 | check_arguments("${CMAKE_CURRENT_FUNCTION}" "${prefix}" "${required_args}") 96 | 97 | message(STATUS "Installing NuGet ${ARGS_NUGET_VERSION}...") 98 | 99 | set(NUGET_DOWNLOAD_DIR ${ARGS_NUGET_INSTALL_PREFIX}/nuget) 100 | file(MAKE_DIRECTORY ${NUGET_DOWNLOAD_DIR}) 101 | set(NUGET_EXECUTABLE ${NUGET_DOWNLOAD_DIR}/nuget.exe) 102 | if(NOT EXISTS ${NUGET_EXE}) 103 | set(NUGET_URL "https://dist.nuget.org/win-x86-commandline/${ARGS_NUGET_VERSION}/nuget.exe") 104 | file(DOWNLOAD ${NUGET_URL} ${NUGET_EXECUTABLE}) 105 | endif() 106 | 107 | # Set the output 108 | set(${ARGS_NUGET_EXECUTABLE_OUT} "${NUGET_EXECUTABLE}" PARENT_SCOPE) 109 | 110 | # Summary 111 | message(STATUS "NuGet ${ARGS_NUGET_VERSION} installed to ${NUGET_DOWNLOAD_DIR}") 112 | endfunction() 113 | 114 | endif() 115 | -------------------------------------------------------------------------------- /libs/UGrid/include/UGrid/Constants.hpp: -------------------------------------------------------------------------------- 1 | //---- GPL --------------------------------------------------------------------- 2 | // 3 | // Copyright (C) Stichting Deltares, 2011-2021. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation version 3. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | // 17 | // contact: delft3d.support@deltares.nl 18 | // Stichting Deltares 19 | // P.O. Box 177 20 | // 2600 MH Delft, The Netherlands 21 | // 22 | // All indications and logos of, and references to, "Delft3D" and "Deltares" 23 | // are registered trademarks of Stichting Deltares, and remain the property of 24 | // Stichting Deltares. All rights reserved. 25 | // 26 | //------------------------------------------------------------------------------ 27 | 28 | #pragma once 29 | 30 | #include 31 | 32 | /// \namespace ugrid 33 | /// @brief Contains the logic of the C++ static library 34 | namespace ugrid 35 | { 36 | /// @brief The UGrid entity locations 37 | enum UGridEntityLocations 38 | { 39 | node = 0, 40 | edge = 1, 41 | face = 2, 42 | layer = 3, 43 | layer_interface = 4, 44 | vertical = 5, 45 | contact = 6, 46 | invalid_location = 7 47 | }; 48 | 49 | /// @brief The dimensions on a UGrid file 50 | enum class UGridFileDimensions 51 | { 52 | Two, 53 | node, 54 | node_geometry, 55 | edge, 56 | face, 57 | layer, 58 | layer_interface, 59 | max_face_node, 60 | contact, 61 | id, 62 | long_name 63 | }; 64 | 65 | /// @brief The UGrid Entity coordinates 66 | enum class UGridEntityCoordinates 67 | { 68 | x, 69 | y, 70 | lat, 71 | lon 72 | }; 73 | 74 | constexpr size_t name_length = 40; ///< length of the names 75 | constexpr size_t name_long_length = 80; ///< length of the long names 76 | constexpr int int_invalid_value = std::numeric_limits::max(); ///< integer invalid value 77 | constexpr double double_invalid_value = std::numeric_limits::max(); ///< double invalid value 78 | 79 | constexpr int int_missing_value = -999; ///< integer missing value 80 | constexpr double double_missing_value = -999.0; ///< double missing value 81 | constexpr int num_face_nodes_max = 6; ///< default maximum number of node per face 82 | const std::string two_string("Two"); ///< Name of variable dimension containing two 83 | const std::string name_length_dimension("name_length_dimension"); ///< Name of variable dimension containing two 84 | const std::string name_long_length_dimension("name_long_length_dimension"); ///< Name of variable dimension containing two 85 | 86 | // define topology variable aliases 87 | static const std::map> attribute_aliases{ 88 | // nodes 89 | {"node_id", {"node_id", "node_ids"}}, 90 | {"node_long_name", {"node_long_name", "node_long_names"}}, 91 | // edges 92 | {"edge_id", {"edge_id", "branch_id", "branch_ids"}}, 93 | {"edge_long_name", {"branch_long_name", "branch_long_names", "edge_long_name"}}, 94 | // contacts 95 | {"contact_id", {"contact_id", "contact_ids"}}, 96 | {"contact_long_name", {"contact_long_name", "contact_long_names"}}, 97 | // edge 98 | {"edge_length", {"edge_length", "branch_length", "branch_lengths"}}, 99 | {"node_edge_id", {"branch_id", "branch_ids", "edge_id", "node_edge_id"}}, 100 | }; 101 | 102 | } // namespace ugrid 103 | -------------------------------------------------------------------------------- /cmake/find_packages.cmake: -------------------------------------------------------------------------------- 1 | # Boost 2 | set(BOOST_MIN_VERSION "1.78.0") 3 | find_package(Boost ${BOOST_MIN_VERSION} REQUIRED) 4 | if (Boost_FOUND) 5 | message(STATUS "Found Boost ${Boost_VERSION}") 6 | else() 7 | message(FATAL_ERROR "Could not find Boost (minimum required version is ${BOOST_MIN_REQ_VERSION})") 8 | endif() 9 | 10 | # zlib 11 | if(WIN32) 12 | # Set the path to the shared library 13 | if(DEFINED ENV{ZLIB_ROOT}) 14 | message(VERBOSE "ZLIB_ROOT is an env var") 15 | set(ZLIB_LIBRARY_PATH "$ENV{ZLIB_ROOT}") 16 | elseif(DEFINED ZLIB_ROOT) 17 | message(VERBOSE "ZLIB_ROOT is a config option") 18 | set(ZLIB_LIBRARY_PATH "${ZLIB_ROOT}") 19 | else() 20 | message(FATAL_ERROR "ZLIB_ROOT is undefined") 21 | endif() 22 | set(ZLIB_LIBRARY "${ZLIB_LIBRARY_PATH}/bin/zlib.dll") 23 | endif() 24 | find_package(ZLIB REQUIRED) 25 | if (ZLIB_FOUND) 26 | message(STATUS "Found ZLIB ${ZLIB_VERSION}") 27 | else() 28 | message(FATAL_ERROR "Could not find ZLIB") 29 | endif() 30 | 31 | # hdf5 32 | find_package (HDF5 NAMES hdf5 COMPONENTS C HL shared) 33 | if (HDF5_FOUND) 34 | message(STATUS "Found HDF5 ${HDF5_VERSION}") 35 | else() 36 | message(FATAL_ERROR "Could not find HDF5") 37 | endif() 38 | 39 | # netCDF 40 | find_package(netCDF REQUIRED COMPONENTS C) 41 | if (netCDF_FOUND) 42 | message(STATUS "Found NetCDF ${netCDF_VERSION}") 43 | else() 44 | message(FATAL_ERROR "Could not find NetCDF") 45 | endif() 46 | 47 | # netCDFCxx 48 | find_package(netCDFCxx REQUIRED) 49 | if (netCDFCxx_FOUND) 50 | message(STATUS "Found NetCDFCxx ${netCDFCxx_VERSION}") 51 | else() 52 | message(FATAL_ERROR "Could not find NetCDFCxx") 53 | endif() 54 | 55 | # curl 56 | find_package(CURL REQUIRED) 57 | if (CURL_FOUND) 58 | message(STATUS "Found CURL ${CURL_VERSION_STRING}") 59 | else() 60 | message(FATAL_ERROR "Could not find CURL") 61 | endif() 62 | 63 | # python 64 | set(Python_FIND_VIRTUALENV FIRST) 65 | find_package(Python REQUIRED COMPONENTS Interpreter) 66 | if (Python_FOUND) 67 | message(STATUS "Found Python ${Python_VERSION}") 68 | else() 69 | message(FATAL_ERROR "Could not find Python") 70 | endif() 71 | 72 | # git 73 | find_package(Git) 74 | if (Git_FOUND) 75 | message(STATUS "Found Git ${GIT_VERSION_STRING}") 76 | endif() 77 | 78 | # check the dependencies that must be collected later 79 | function(check_runtime_dependency IMPORTED_TARGET_NAME REQUIRED_IMPORTED_TARGET_TYPE) 80 | get_target_property(TARGET_TYPE ${IMPORTED_TARGET_NAME} TYPE) 81 | if(NOT "${TARGET_TYPE}" STREQUAL "${REQUIRED_IMPORTED_TARGET_TYPE}") 82 | message(FATAL_ERROR "Dependency ${IMPORTED_TARGET_NAME}: ${REQUIRED_IMPORTED_TARGET_TYPE} was requested but ${TARGET_TYPE} was found") 83 | endif() 84 | get_target_property(IMPORTED_TARGET_LOCATION ${IMPORTED_TARGET_NAME} LOCATION) 85 | message(STATUS "Runtime dependency ${IMPORTED_TARGET_NAME} (${REQUIRED_IMPORTED_TARGET_TYPE}): ${IMPORTED_TARGET_LOCATION}") 86 | endfunction() 87 | 88 | check_runtime_dependency(netCDF::netcdf SHARED_LIBRARY) 89 | check_runtime_dependency(netCDF::netcdf-cxx4 SHARED_LIBRARY) 90 | check_runtime_dependency(hdf5-shared SHARED_LIBRARY) 91 | check_runtime_dependency(hdf5_hl-shared SHARED_LIBRARY) 92 | check_runtime_dependency(ZLIB::ZLIB UNKNOWN_LIBRARY) 93 | check_runtime_dependency(CURL::libcurl SHARED_LIBRARY) 94 | 95 | # cache the third-party runtime dependencies 96 | # It would be cool to use TARGET_RUNTIME_DLLS which is described here 97 | # https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#genex:TARGET_RUNTIME_DLLS 98 | # Unfortunately ZLIB, which is an HDF5 dependency, does not provide an IMPORTED_LOCATION (dll path), 99 | # so it does not make it to the list of run time dependencies. 100 | # Besides, UGrid is a static library and TARGET_RUNTIME_DLLS works with executables, modules and shared libraries. 101 | # The runtime dependencies are set manually here. 102 | set( 103 | THIRD_PARTY_RUNTIME_DEPS 104 | $ 105 | $ 106 | $ 107 | $ 108 | $ # not an element of TARGET_RUNTIME_DLLS, helaas speculaas 109 | $ 110 | CACHE STRING "Third-party runtime dependencies" FORCE 111 | ) 112 | 113 | # cache all runtime dependencies 114 | set( 115 | ALL_RUNTIME_DEPS 116 | ${THIRD_PARTY_RUNTIME_DEPS} 117 | $ 118 | CACHE STRING "All runtime dependencies" FORCE 119 | ) 120 | -------------------------------------------------------------------------------- /libs/UGridNET/dll/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project( 2 | UGridNET 3 | VERSION ${CMAKE_PROJECT_VERSION} 4 | DESCRIPTION "UGrid C# API" 5 | LANGUAGES CSharp 6 | ) 7 | 8 | #set(CMAKE_GENERATOR_PLATFORM win32) 9 | 10 | # target name 11 | set(TARGET_NAME ${PROJECT_NAME}) 12 | 13 | set(NUGET_CONFIG ${CMAKE_CURRENT_BINARY_DIR}/NuGet.config) 14 | configure_file( 15 | ${CMAKE_CURRENT_SOURCE_DIR}/../config/NuGet.config 16 | ${NUGET_CONFIG} 17 | COPYONLY 18 | ) 19 | 20 | list(LENGTH GLOB_LIB_DOTNET_TARGET_FRAMEWORKS LIST_LENGTH) 21 | if(${LIST_LENGTH} EQUAL 1) 22 | set(PROJECT_DOTNET_TARGET_FRAMEWORKS_TAG "TargetFramework") 23 | else() 24 | set(PROJECT_DOTNET_TARGET_FRAMEWORKS_TAG "TargetFrameworks") 25 | endif() 26 | set(PROJECT_DOTNET_TARGET_FRAMEWORKS ${GLOB_LIB_DOTNET_TARGET_FRAMEWORKS}) 27 | set(DIRECTORY_BUILD_PROPS ${CMAKE_CURRENT_BINARY_DIR}/Directory.Build.props) 28 | configure_file( 29 | ${CMAKE_CURRENT_SOURCE_DIR}/../config/Directory.Build.props.in 30 | ${DIRECTORY_BUILD_PROPS} 31 | @ONLY 32 | ) 33 | 34 | set(DIRECTORY_PACKAGES_PROPS ${CMAKE_CURRENT_BINARY_DIR}/Directory.Packages.props) 35 | configure_file( 36 | ${CMAKE_CURRENT_SOURCE_DIR}/Directory.Packages.props 37 | ${DIRECTORY_PACKAGES_PROPS} 38 | COPYONLY 39 | ) 40 | 41 | execute_process( 42 | COMMAND ${Python_EXECUTABLE} 43 | ${CMAKE_SOURCE_DIR}/scripts/get_package_ids_from_directory_packages_props.py 44 | ${DIRECTORY_PACKAGES_PROPS} 45 | OUTPUT_VARIABLE PACKAGE_REFERENCES 46 | RESULT_VARIABLE RETURN_CODE 47 | OUTPUT_STRIP_TRAILING_WHITESPACE 48 | COMMAND_ERROR_IS_FATAL LAST 49 | ) 50 | 51 | set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) 52 | set( 53 | SOURCES 54 | ${SWIG_GENERATED_CSHARP_SRCS} 55 | ${SOURCE_DIR}/AssemblyInfo.cs 56 | ${SOURCE_DIR}/ByteArrayExtensions.cs 57 | ${SOURCE_DIR}/ContactsExtensions.cs 58 | ${SOURCE_DIR}/DisposableMesh1D.cs 59 | ${SOURCE_DIR}/DisposableMesh2D.cs 60 | ${SOURCE_DIR}/DisposableNativeObject.cs 61 | ${SOURCE_DIR}/IntPtrExtensions.cs 62 | ${SOURCE_DIR}/IntPtrHelpers.cs 63 | ${SOURCE_DIR}/Mesh1DExtensions.cs 64 | ${SOURCE_DIR}/Mesh2DExtensions.cs 65 | ${SOURCE_DIR}/Network1DExtensions.cs 66 | ${SOURCE_DIR}/ProjectedCoordinateSystem.cs 67 | ${SOURCE_DIR}/StringExtensions.cs 68 | ${SOURCE_DIR}/UGridNETException.cs 69 | ${SOURCE_DIR}/UGridBase.cs 70 | ${SOURCE_DIR}/UGridReader.cs 71 | ${SOURCE_DIR}/UGridWriter.cs 72 | ) 73 | 74 | add_library( 75 | ${TARGET_NAME} 76 | SHARED 77 | ${NUGET_CONFIG} 78 | ${DIRECTORY_PACKAGES_PROPS} 79 | ${DIRECTORY_BUILD_PROPS} 80 | ${SOURCES} 81 | ) 82 | 83 | set_target_properties( 84 | ${TARGET_NAME} 85 | PROPERTIES 86 | DOTNET_TARGET_FRAMEWORK "${GLOB_LIB_DOTNET_TARGET_FRAMEWORKS}" 87 | DOTNET_SDK ${GLOB_DOTNET_SDK} 88 | VS_PACKAGE_REFERENCES "${PACKAGE_REFERENCES}" 89 | VS_GLOBAL_PlatformTarget "AnyCPU" 90 | #VS_GLOBAL_AppendTargetFrameworkToOutputPath "true" 91 | ) 92 | 93 | target_compile_options(${TARGET_NAME} PRIVATE "/unsafe") 94 | 95 | target_compile_options(${TARGET_NAME} PRIVATE "/platform:anycpu") 96 | 97 | # add_custom_command( 98 | # TARGET ${TARGET_NAME} 99 | # PRE_BUILD 100 | # COMMAND ${Python_EXECUTABLE} 101 | # ${CMAKE_SOURCE_DIR}/scripts/append_target_framework_to_output_path_in_csproj.py 102 | # ${CMAKE_CURRENT_BINARY_DIR}/UGridNET.csproj 103 | # COMMENT "Configure CS projects to append the target framework to the output path" 104 | # ) 105 | 106 | # restore nuget packages 107 | add_custom_command( 108 | TARGET ${TARGET_NAME} 109 | PRE_BUILD 110 | COMMAND ${NUGET_EXECUTABLE} restore ${CMAKE_CURRENT_BINARY_DIR}/UGridNET.sln 111 | -Force 112 | -NoHttpCache 113 | -Verbosity detailed 114 | -ConfigFile ${CMAKE_CURRENT_BINARY_DIR}//NuGet.config 115 | COMMENT "Restore NuGet packages" 116 | ) 117 | 118 | # create empty list of the commands which must to be called in the custom target 119 | set(TARGET_COMMANDS) 120 | 121 | # For each supported .NET target framework, UGridNET needs the third party dependencies and the SWIG-generated dependencies 122 | foreach(FRAMEWORK ${GLOB_LIB_DOTNET_TARGET_FRAMEWORKS}) 123 | list( 124 | APPEND 125 | TARGET_COMMANDS 126 | COMMAND ${CMAKE_COMMAND} -E echo "Copying ${ALL_RUNTIME_DEPS} to $/${FRAMEWORK}" 127 | COMMAND ${CMAKE_COMMAND} -E copy -t $/${FRAMEWORK} ${ALL_RUNTIME_DEPS} 128 | ) 129 | endforeach() 130 | 131 | 132 | add_custom_command( 133 | TARGET ${TARGET_NAME} 134 | POST_BUILD 135 | ${TARGET_COMMANDS} 136 | COMMENT "Copying runtime dependencies..." 137 | ) -------------------------------------------------------------------------------- /libs/UGridNET/dll/src/DisposableNativeObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace UGridNET 8 | { 9 | /// 10 | /// Base class for disposable mesh objects. Provides pinning of arrays in memory for exchange with native calls. 11 | /// 12 | public abstract class DisposableNativeObject : IDisposable where TNative : new() 13 | { 14 | private readonly Dictionary objectGarbageCollectHandles = new Dictionary(); 15 | private bool disposed; 16 | 17 | /// 18 | /// Disposes the unmanaged resources 19 | /// 20 | ~DisposableNativeObject() 21 | { 22 | Dispose(false); 23 | } 24 | 25 | /// 26 | /// Indicates if arrays are pinned in memory 27 | /// 28 | private bool IsMemoryPinned 29 | { 30 | get { return objectGarbageCollectHandles.Count > 0; } 31 | } 32 | 33 | /// 34 | public void Dispose() 35 | { 36 | Dispose(true); 37 | GC.SuppressFinalize(this); 38 | } 39 | 40 | /// 41 | /// Creates a native structure for this object 42 | /// 43 | /// 44 | public TNative CreateNativeObject() 45 | { 46 | if (!IsMemoryPinned) 47 | { 48 | PinMemory(); 49 | } 50 | 51 | var nativeObject = new TNative(); 52 | SetNativeObject(ref nativeObject); 53 | return nativeObject; 54 | } 55 | 56 | /// 57 | /// Maps the object with current state (used in ) 58 | /// 59 | /// Newly created native object 60 | protected abstract void SetNativeObject(ref TNative nativeObject); 61 | 62 | /// 63 | /// Get the pointer to the pinned object 64 | /// 65 | /// Object to get 66 | /// 67 | protected IntPtr GetPinnedObjectPointer(object objectToLookUp) 68 | { 69 | return (objectToLookUp != null) 70 | ? objectGarbageCollectHandles[objectToLookUp].AddrOfPinnedObject() 71 | : IntPtr.Zero; 72 | } 73 | 74 | /// 75 | /// Disposes resources 76 | /// 77 | /// 78 | /// Boolean indicating that the call is called from the dispose method 79 | /// not the destructor 80 | /// 81 | protected virtual void Dispose(bool disposing) 82 | { 83 | if (disposed) 84 | { 85 | return; 86 | } 87 | 88 | ReleaseUnmanagedResources(); 89 | 90 | disposed = true; 91 | } 92 | 93 | /// 94 | /// Pins the arrays in memory (no garbage collect until unpinned (done in dispose)) 95 | /// 96 | private void PinMemory() 97 | { 98 | IEnumerable arrayProperties = GetType().GetProperties().Where(f => f.PropertyType.IsArray); 99 | 100 | // force initialization 101 | foreach (PropertyInfo arrayProperty in arrayProperties) 102 | { 103 | Type elementType = arrayProperty.PropertyType.GetElementType(); 104 | object objectToPin = arrayProperty.GetValue(this); 105 | AddObjectToPin(objectToPin); 106 | } 107 | } 108 | 109 | private void UnPinMemory() 110 | { 111 | foreach (KeyValuePair valuePair in objectGarbageCollectHandles) 112 | { 113 | valuePair.Value.Free(); 114 | } 115 | 116 | objectGarbageCollectHandles.Clear(); 117 | } 118 | 119 | private void AddObjectToPin(object objectToPin) 120 | { 121 | if(objectToPin != null) 122 | { 123 | objectGarbageCollectHandles.Add(objectToPin, GCHandle.Alloc(objectToPin, GCHandleType.Pinned)); 124 | } 125 | } 126 | 127 | private void ReleaseUnmanagedResources() 128 | { 129 | UnPinMemory(); 130 | } 131 | } 132 | } -------------------------------------------------------------------------------- /libs/UGridNET/dll/src/IntPtrExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace UGridNET 5 | { 6 | namespace Extensions 7 | { 8 | /// 9 | /// Provides extension methods for working with . 10 | /// 11 | public static class IntPtrExtensions 12 | { 13 | /// 14 | /// Copies data from an unmanaged memory pointer to a managed array. 15 | /// 16 | /// The type of elements in the array. Must be a value type. 17 | /// The unmanaged memory pointer. 18 | /// The number of elements to copy. 19 | /// A managed array containing the copied data. 20 | /// Thrown when the pointer is null. 21 | /// Thrown when the length is less than or equal to zero. 22 | /// Thrown when the type of elements is not supported. 23 | public static T[] CopyToArray(this IntPtr pointer, int length) where T : struct 24 | { 25 | if (pointer == IntPtr.Zero) 26 | { 27 | throw new ArgumentNullException(nameof(pointer), "Pointer is null. Cannot copy a null pointer to a array."); 28 | } 29 | 30 | if (length <= 0) 31 | { 32 | throw new ArgumentException("Array length must be greater than zero.", nameof(length)); 33 | } 34 | 35 | var array = new T[length]; 36 | 37 | switch (array) 38 | { 39 | case int[] intArray: 40 | Marshal.Copy(pointer, intArray, 0, intArray.Length); 41 | break; 42 | case double[] doubleArray: 43 | Marshal.Copy(pointer, doubleArray, 0, doubleArray.Length); 44 | break; 45 | case byte[] byteArray: 46 | Marshal.Copy(pointer, byteArray, 0, byteArray.Length); 47 | break; 48 | default: 49 | throw new NotSupportedException("Currently only int, double and byte data types are supported."); 50 | } 51 | 52 | return array; 53 | } 54 | 55 | /// 56 | /// Copies data from a managed array to an unmanaged memory pointer. 57 | /// 58 | /// The type of elements in the array. Must be a value type. 59 | /// The unmanaged memory pointer. 60 | /// The managed array containing the data to copy. 61 | /// Thrown when the pointer or array is null. 62 | /// Thrown when the array is empty. 63 | /// Thrown when the type of elements is not supported. 64 | public static void CopyFromArray(this IntPtr pointer, T[] array) where T : struct 65 | { 66 | if (pointer == IntPtr.Zero) 67 | { 68 | throw new ArgumentNullException(nameof(pointer), "Pointer is null."); 69 | } 70 | 71 | if (array == null) 72 | { 73 | throw new ArgumentNullException(nameof(array), "Array is null."); 74 | } 75 | 76 | if (array.Length == 0) 77 | { 78 | throw new ArgumentException("Array is empty.", nameof(array)); 79 | } 80 | 81 | switch (array) 82 | { 83 | case int[] intArray: 84 | Marshal.Copy(intArray, 0, pointer, intArray.Length); 85 | break; 86 | case double[] doubleArray: 87 | Marshal.Copy(doubleArray, 0, pointer, doubleArray.Length); 88 | break; 89 | case byte[] byteArray: 90 | Marshal.Copy(byteArray, 0, pointer, byteArray.Length); 91 | break; 92 | default: 93 | throw new NotSupportedException("Currently only int, double and byte data types are supported."); 94 | } 95 | } 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /libs/UGrid/include/UGrid/Network1D.hpp: -------------------------------------------------------------------------------- 1 | //---- GPL --------------------------------------------------------------------- 2 | // 3 | // Copyright (C) Stichting Deltares, 2011-2021. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation version 3. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | // 17 | // contact: delft3d.support@deltares.nl 18 | // Stichting Deltares 19 | // P.O. Box 177 20 | // 2600 MH Delft, The Netherlands 21 | // 22 | // All indications and logos of, and references to, "Delft3D" and "Deltares" 23 | // are registered trademarks of Stichting Deltares, and remain the property of 24 | // Stichting Deltares. All rights reserved. 25 | // 26 | //------------------------------------------------------------------------------ 27 | 28 | #pragma once 29 | #include 30 | 31 | #include 32 | 33 | /// \namespace ugrid 34 | /// @brief Contains the logic of the C++ static library 35 | namespace ugrid 36 | { 37 | /// @brief A class implementing the methods for reading/writing a mesh2d in UGrid format 38 | struct Network1D : UGridEntity 39 | { 40 | /// @brief Constructor setting the NetCDF file 41 | /// @param nc_file The NetCDF file pointer 42 | explicit Network1D(std::shared_ptr nc_file); 43 | 44 | /// @brief Constructor setting nc_file and all internal state 45 | /// @param nc_file The nc file pointer 46 | /// @param topology_variable The network topology variable 47 | /// @param entity_attributes The topological attributes (key value pair with key the attribute name and value the associated vector of variables) 48 | /// @param entity_attribute_names The topological attributes names (key value pair with key the attribute name and value the associated vector of variables names) 49 | /// @param entity_dimensions The dimensions associated with the mesh2d (key value pair with key the dimension enumeration and value the associated NetCDF dimension) 50 | Network1D( 51 | std::shared_ptr nc_file, 52 | netCDF::NcVar const& topology_variable, 53 | std::map> const& entity_attributes, 54 | std::map> const& entity_attribute_names, 55 | std::map const& entity_dimensions); 56 | 57 | /// @brief Defines the network1d header (ug_create_1d_network_v1) 58 | /// @param mesh2d The network1d api structure with the fields to write and all optional flags 59 | void define(ugridapi::Network1D const& mesh2d); 60 | 61 | /// @brief Writes a network1d to file 62 | /// @param mesh2d network1d The mesh2d api structure with the fields to write and all optional flags 63 | void put(ugridapi::Network1D const& mesh2d); 64 | 65 | /// @brief Inquires the network1d dimensions 66 | /// @param mesh2d The network1d api structure with the fields where to assign the dimensions 67 | void inquire(ugridapi::Network1D& mesh2d) const; 68 | 69 | /// @brief Inquires the network1d arrays 70 | /// @param mesh2d The network1d api structure with the fields where to assign the data 71 | void get(ugridapi::Network1D& mesh2d) const; 72 | 73 | /// @brief A function to determine if a variable is a network variable 74 | /// @param attributes [in] The variable attributes 75 | /// @return True if the variable is a topology variable 76 | static bool is_topology_variable(std::map const& attributes); 77 | 78 | /// @brief Get the dimensionality of a Network1D 79 | /// @return The dimensionality 80 | static int get_dimensionality() { return 1; } 81 | 82 | private: 83 | netCDF::NcVar m_network_geometry_variable; ///< The network topology variable 84 | std::map> m_network_geometry_attribute_variables; ///< For each network attribute, the corresponding attributes 85 | std::map> m_network_geometry_attributes_names; ///< For each network attribute, the corresponding names 86 | std::map m_network_geometry_dimensions; ///< The network entity dimensions 87 | }; 88 | } // namespace ugrid -------------------------------------------------------------------------------- /libs/UGridNET/test/src/SWIGTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Runtime.InteropServices; 4 | using System.Text; 5 | using NUnit.Framework; 6 | using UGridNET.Extensions; 7 | 8 | namespace UGridNET.Tests 9 | { 10 | 11 | public class SWIGTests 12 | { 13 | private static readonly string TestDataPath = TestUtilities.GetTestDataPath(); 14 | 15 | [Test] 16 | public void GetDoubleDataByVariableName() 17 | { 18 | int result = -1; 19 | 20 | int fileMode = -1; 21 | result = UGrid.ug_file_read_mode(ref fileMode); 22 | Assert.That(result, Is.EqualTo(0)); 23 | 24 | int fileID = -1; 25 | var filePath = Path.Combine(TestDataPath, "ResultFile.nc"); 26 | result = UGrid.ug_file_open(System.Text.Encoding.Default.GetBytes(filePath), fileMode, ref fileID); 27 | Assert.That(result, Is.EqualTo(0)); 28 | 29 | int dimensionsCount = 0; 30 | string variableNameStr = "mesh1d_s0 "; 31 | byte[] variableName = System.Text.Encoding.Default.GetBytes(variableNameStr); 32 | result = UGrid.ug_variable_count_dimensions(fileID, variableName, ref dimensionsCount); 33 | Assert.That(result, Is.EqualTo(0)); 34 | 35 | var dimensionVec = new int[dimensionsCount]; 36 | UGrid.ug_variable_get_data_dimensions(fileID, variableName, dimensionVec); 37 | Assert.That(result, Is.EqualTo(0)); 38 | 39 | int totalDimension = 1; 40 | for (int i = 0; i < dimensionsCount; i++) 41 | { 42 | totalDimension *= dimensionVec[i]; 43 | } 44 | 45 | var data = new double[totalDimension]; 46 | UGrid.ug_variable_get_data_double(fileID, variableName, data); 47 | Assert.That(result, Is.EqualTo(0)); 48 | 49 | // compare 20 values between 86 and 106 50 | const int offset = 85; 51 | const int sampleSize = 20; 52 | double[] expectedData = new double[sampleSize] 53 | { 54 | -5.0, 55 | 0.27, 56 | 0.75, 57 | -0.36, 58 | 0.27, 59 | 0.56, 60 | 0.83, 61 | 0.79, 62 | 0.8, 63 | 0.81, 64 | 0.88, 65 | 0.63, 66 | 0.7, 67 | 1.02, 68 | 1.07, 69 | 0.97, 70 | 1.02, 71 | 1.14, 72 | 1.13, 73 | 0.9 74 | }; 75 | 76 | for (int i = 0; i < sampleSize; i++) 77 | { 78 | Assert.That(data[i + offset], Is.EqualTo(expectedData[i])); 79 | } 80 | 81 | result = UGrid.ug_file_close(fileID); 82 | Assert.That(result, Is.EqualTo(0)); 83 | } 84 | 85 | [Test] 86 | public void TestMesh1DReadAndInquire() 87 | { 88 | Mesh1D mesh1D = new Mesh1D(); 89 | try 90 | { 91 | int result = -1; 92 | 93 | int fileMode = -1; 94 | 95 | result = UGrid.ug_file_read_mode(ref fileMode); 96 | Assert.That(result, Is.EqualTo(0)); 97 | 98 | int fileID = -1; 99 | var filePath = Path.Combine(TestDataPath, "AllUGridEntities.nc"); 100 | result = UGrid.ug_file_open(System.Text.Encoding.Default.GetBytes(filePath), fileMode, ref fileID); 101 | Assert.That(result, Is.EqualTo(0)); 102 | 103 | //// get the number of topologies 104 | int numTopologies = 0; 105 | result = UGrid.ug_topology_get_count(fileID, TopologyType.Mesh1dTopology, ref numTopologies); 106 | Assert.That(numTopologies, Is.EqualTo(1)); 107 | Assert.That(result, Is.EqualTo(0)); 108 | 109 | // get the mesh 110 | const int topologyId = 0; 111 | result = UGrid.ug_mesh1d_inq(fileID, topologyId, mesh1D); 112 | Assert.That(result, Is.EqualTo(0)); 113 | Assert.That(mesh1D.num_nodes, Is.EqualTo(25)); 114 | Assert.That(mesh1D.num_edges, Is.EqualTo(24)); 115 | 116 | mesh1D.node_x = Marshal.AllocHGlobal(mesh1D.num_nodes * Marshal.SizeOf()); 117 | mesh1D.edge_nodes = Marshal.AllocHGlobal(mesh1D.num_edges * 2 * Marshal.SizeOf()); 118 | 119 | result = UGrid.ug_file_close(fileID); 120 | Assert.That(result, Is.EqualTo(0)); 121 | } 122 | finally 123 | { 124 | mesh1D?.Dispose(); 125 | } 126 | } 127 | } 128 | } -------------------------------------------------------------------------------- /libs/UGridNET/test/src/StringExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using UGridNET.Extensions; 7 | 8 | namespace UGridNET.Tests 9 | { 10 | public class StringExtensionsTests 11 | { 12 | [Test] 13 | public void GetBytesThrowsDueToNullString() 14 | { 15 | string str = null; 16 | var bytes = new byte[] { }; 17 | Assert.Throws(() => bytes = str.GetBytes()); 18 | } 19 | 20 | 21 | [Test] 22 | public void GetBytesSucceeds() 23 | { 24 | string str = "I am not a number, I am a free man!"; 25 | byte[] expectedBytes = { 26 | 0x49, 0x20, 0x61, 0x6d, 0x20, 27 | 0x6e, 0x6f, 0x74, 0x20, 0x61, 28 | 0x20, 0x6e, 0x75, 0x6d, 0x62, 29 | 0x65, 0x72, 0x2c, 0x20, 0x49, 30 | 0x20, 0x61, 0x6d, 0x20, 0x61, 31 | 0x20, 0x66, 0x72, 0x65, 0x65, 32 | 0x20, 0x6d, 0x61, 0x6e, 0x21 33 | }; 34 | byte[] bytes = str.GetBytes(); 35 | Assert.That(bytes, Is.EqualTo(expectedBytes)); 36 | } 37 | 38 | [Test] 39 | public void GetRightPaddedNullTerminatedBytesThrowsDueToNullStr() 40 | { 41 | string str = null; 42 | int totalLength = 40; 43 | var bytes = new byte[] { }; 44 | Assert.Throws(() => str.GetRightPaddedNullTerminatedBytes(totalLength)); 45 | } 46 | 47 | [Test] 48 | public void GetRightPaddedNullTerminatedBytesThrowsDueToNegativeTotalLength() 49 | { 50 | string str = "I am not a number, I am a free man!"; 51 | int totalLength = -40; 52 | var bytes = new byte[] { }; 53 | Assert.Throws(() => str.GetRightPaddedNullTerminatedBytes(totalLength)); 54 | } 55 | 56 | [Test] 57 | public void GetRightPaddedNullTerminatedBytesThrowsDueToStringLengthExceedingTotalLength() 58 | { 59 | string str = "I am not a number, I am a free man!"; // 35 characters 60 | int totalLength = 30; 61 | var bytes = new byte[] { }; 62 | Assert.Throws(() => str.GetRightPaddedNullTerminatedBytes(totalLength)); 63 | } 64 | 65 | [Test] 66 | public void GetRightPaddedNullTerminatedBytesSucceeds() 67 | { 68 | string str = "I am not a number, I am a free man!"; // 35 characters 69 | int totalLength = 40; 70 | var expectedBytes = new List { 71 | 0x49, 0x20, 0x61, 0x6d, 0x20, 72 | 0x6e, 0x6f, 0x74, 0x20, 0x61, 73 | 0x20, 0x6e, 0x75, 0x6d, 0x62, 74 | 0x65, 0x72, 0x2c, 0x20, 0x49, 75 | 0x20, 0x61, 0x6d, 0x20, 0x61, 76 | 0x20, 0x66, 0x72, 0x65, 0x65, 77 | 0x20, 0x6d, 0x61, 0x6e, 0x21 78 | }; 79 | // pad with spaces up to total length -1 80 | expectedBytes.AddRange(Enumerable.Repeat((byte)0x20, totalLength - expectedBytes.Count - 1)); 81 | // null terminate 82 | expectedBytes.Add(0x00); 83 | 84 | byte[] bytes = str.GetRightPaddedNullTerminatedBytes(totalLength); 85 | Assert.That(bytes, Is.EqualTo(expectedBytes.ToArray())); 86 | } 87 | 88 | [Test] 89 | public void GetTokenizeThrowsDueToNullStr() 90 | { 91 | int maxTokenLength = 40; 92 | string str = null; 93 | List tokens = null; 94 | Assert.Throws(() => tokens = str.Tokenize(maxTokenLength)); 95 | } 96 | 97 | [Test] 98 | public void GetTokenizeThrowsDueToEmptyStr() 99 | { 100 | int maxTokenLength = 40; 101 | var str = string.Empty; 102 | List tokens = null; 103 | Assert.Throws(() => tokens = str.Tokenize(maxTokenLength)); 104 | } 105 | 106 | [Test] 107 | public void GetTokenizeThrowsDueToNegativeMaximumTokenLength() 108 | { 109 | int maxTokenLength = -40; 110 | var str = "I am not a number, I am a free man!"; 111 | List tokens = null; 112 | Assert.Throws(() => tokens = str.Tokenize(maxTokenLength)); 113 | } 114 | 115 | 116 | [Test] 117 | public void GetTokenizeSucceeds() 118 | { 119 | int maxTokenLength = 40; 120 | string str = "I am not a number, I am a free man!"; 121 | var tokens = str.Split(' '); 122 | var stringBuilder = string.Empty; 123 | foreach (var token in tokens) 124 | { 125 | stringBuilder += token.PadRight(maxTokenLength); 126 | } 127 | Assert.That(stringBuilder.Tokenize(maxTokenLength), Is.EqualTo(tokens)); 128 | } 129 | } 130 | } -------------------------------------------------------------------------------- /libs/UGridNET/dll/src/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace UGridNET 6 | { 7 | namespace Extensions 8 | { 9 | 10 | /// 11 | /// Provides extension methods for the class. 12 | /// 13 | internal static class StringExtensions 14 | { 15 | /// 16 | /// Converts the specified string to a byte array using UTF-8 encoding. 17 | /// 18 | /// The string to convert. 19 | /// A byte array representing the UTF-8 encoded string. 20 | public static byte[] GetBytes(this string str) 21 | { 22 | return Encoding.UTF8.GetBytes(str); 23 | } 24 | 25 | /// 26 | /// Converts the specified string to a right-padded, null-terminated byte 27 | /// array of the specified length using UTF-8 encoding. 28 | /// 29 | /// The string to convert. 30 | /// The length of the resulting byte array. 31 | /// 32 | /// A byte array of the specified length, containing the UTF-8 encoded string, 33 | /// right-padded with spaces and null-terminated. 34 | /// 35 | /// Thrown when the string is null. 36 | /// Thrown when the length is negative. 37 | /// Thrown when the string length exceeds the allowed length minus one for the null terminator. 38 | public static byte[] GetRightPaddedNullTerminatedBytes(this string str, int length) 39 | { 40 | if (str == null) 41 | { 42 | throw new ArgumentNullException(nameof(str), "String cannot be null."); 43 | } 44 | 45 | if (length < 0) 46 | { 47 | throw new ArgumentOutOfRangeException(nameof(length), "Length cannot be negative."); 48 | } 49 | 50 | if (str.Length > length - 1) 51 | { 52 | throw new ArgumentException("String length exceeds the allowed length minus one for the null terminator.", nameof(str)); 53 | } 54 | 55 | // Trim then pad the string, reserve the last char for the null character 56 | var paddedString = str.Trim().PadRight(length - 1); 57 | 58 | // Convert the string to bytes 59 | var bytesFromPaddedString = Encoding.UTF8.GetBytes(paddedString); 60 | 61 | // Create a new array with an extra byte for the null terminator 62 | var bytes = new byte[length]; 63 | 64 | // Copy the bytes of the string to the newly created bytes array as the 65 | Array.Copy(bytesFromPaddedString, bytes, length - 1); 66 | 67 | // Explicitly Set last element to null even though this is not really necessary as 68 | // the declaration var bytes = new byte[length]; initializes all elements to null. 69 | bytes[length - 1] = 0x00; 70 | 71 | return bytes; 72 | } 73 | 74 | /// Splits the specified string into tokens of the specified maximum length. 75 | /// The string to tokenize. 76 | /// The maximum length of each token. 77 | /// A list of tokens. 78 | /// Thrown when the string is null. 79 | /// Thrown when the string is empty or the maximum token length is not positive. 80 | public static List Tokenize(this string str, int maxTokenLength) 81 | { 82 | if (str == null) 83 | { 84 | throw new ArgumentNullException(nameof(str), "String cannot be null."); 85 | } 86 | 87 | if (str.Length == 0) 88 | { 89 | throw new ArgumentException("String cannot be null.", nameof(str)); 90 | } 91 | 92 | if (maxTokenLength <= 0) 93 | { 94 | throw new ArgumentException("Maximum token length must be strictly positive.", nameof(maxTokenLength)); 95 | } 96 | 97 | var tokens = new List(); 98 | for (int i = 0; i < str.Length; i += maxTokenLength) 99 | { 100 | var token = str.Substring(i, maxTokenLength); 101 | tokens.Add(token.Trim()); 102 | } 103 | 104 | return tokens; 105 | } 106 | } 107 | } 108 | } -------------------------------------------------------------------------------- /tests/utils/include/TestUtils/Utils.hpp: -------------------------------------------------------------------------------- 1 | //---- GPL --------------------------------------------------------------------- 2 | // 3 | // Copyright (C) Stichting Deltares, 2011-2021. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation version 3. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | // 17 | // contact: delft3d.support@deltares.nl 18 | // Stichting Deltares 19 | // P.O. Box 177 20 | // 2600 MH Delft, The Netherlands 21 | // 22 | // All indications and logos of, and references to, "Delft3D" and "Deltares" 23 | // are registered trademarks of Stichting Deltares, and remain the property of 24 | // Stichting Deltares. All rights reserved. 25 | // 26 | //------------------------------------------------------------------------------ 27 | 28 | #pragma once 29 | 30 | /// @brief Performs right trim of single string 31 | /// @param str [in] The input string 32 | static void right_trim_string(std::string& str) 33 | { 34 | auto const is_graph = [](auto const& ch) 35 | { 36 | return std::isgraph(ch); 37 | }; 38 | 39 | str.erase(std::find_if(str.rbegin(), str.rend(), is_graph).base(), str.end()); 40 | } 41 | 42 | /// @brief Right trims all entries of a vector of strings 43 | /// @param str_vector [in] The input vector 44 | static void right_trim_string_vector(std::vector& str_vector) 45 | { 46 | for (auto& str : str_vector) 47 | { 48 | right_trim_string(str); 49 | } 50 | } 51 | 52 | /// @brief Performs left trim of single string 53 | /// @param str [in] The input string 54 | static void left_trim_string(std::string& str) 55 | { 56 | auto const is_graph = [](auto const& ch) 57 | { 58 | return std::isgraph(ch); 59 | }; 60 | 61 | str.erase(str.begin(), std::find_if(str.begin(), str.end(), is_graph)); 62 | } 63 | 64 | /// @brief Left trims all entries of a vector of strings 65 | /// @param str_vector [in] The input vector 66 | static void left_trim_string_vector(std::vector& str_vector) 67 | { 68 | for (auto& str : str_vector) 69 | { 70 | left_trim_string(str); 71 | } 72 | } 73 | 74 | static void trim_string_vector(std::vector& str_vector) 75 | { 76 | left_trim_string_vector(str_vector); 77 | right_trim_string_vector(str_vector); 78 | } 79 | 80 | /// @brief Splits a string in equal sized tokens 81 | /// @param string_value [in] The input string 82 | /// @param num_tokens [in] The number of tokens 83 | /// @param length_token [in] The length of the token 84 | /// @return The resulting vector containing each token 85 | static std::vector split_string(std::string string_value, size_t num_tokens, size_t length_token) 86 | { 87 | std::vector result; 88 | for (size_t i = 0; i < num_tokens; ++i) 89 | { 90 | auto attribute_name = string_value.substr(i * length_token, length_token); 91 | result.emplace_back(attribute_name); 92 | } 93 | return result; 94 | } 95 | 96 | /// @brief Puts the content of a string into a char array and adds null termination 97 | /// @param value [in] The input string 98 | /// @param len [in] The array length 99 | /// @param char_array [out] The output char array 100 | static void string_to_char_array(std::string const& value, size_t len, char* char_array) 101 | { 102 | if (value.empty()) 103 | { 104 | throw std::runtime_error("string_to_char_array: value string is empty."); 105 | } 106 | if (char_array == nullptr) 107 | { 108 | throw std::runtime_error("string_to_char_array: char_array is nullptr."); 109 | } 110 | for (size_t i = 0; i < value.size(); ++i) 111 | { 112 | char_array[i] = value[i]; 113 | } 114 | for (auto i = value.size(); i < len - 1; ++i) 115 | { 116 | char_array[i] = ' '; 117 | } 118 | // null terminate 119 | char_array[len - 1] = '\0'; 120 | } 121 | 122 | /// @brief Puts the content of a vector of strings into a char array and adds null termination 123 | /// @param value [in] The input string 124 | /// @param len [in] The length of each entry in char_array 125 | /// @param char_array [out] The output char array 126 | static void vector_of_strings_to_char_array(std::vector const& values, size_t len, char* char_array) 127 | { 128 | if (char_array == nullptr || values.empty()) 129 | { 130 | return; 131 | } 132 | 133 | size_t char_array_position = 0; 134 | for (size_t i = 0; i < values.size(); ++i) 135 | { 136 | for (size_t j = 0; j < values[i].size(); ++j) 137 | { 138 | char_array[char_array_position] = values[i][j]; 139 | char_array_position++; 140 | } 141 | for (size_t j = values[i].size(); j < len; ++j) 142 | { 143 | char_array[char_array_position] = ' '; 144 | char_array_position++; 145 | } 146 | } 147 | 148 | // null terminate 149 | char_array[char_array_position - 1] = '\0'; 150 | } 151 | -------------------------------------------------------------------------------- /libs/UGrid/include/UGrid/Contacts.hpp: -------------------------------------------------------------------------------- 1 | //---- GPL --------------------------------------------------------------------- 2 | // 3 | // Copyright (C) Stichting Deltares, 2011-2021. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation version 3. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | // 17 | // contact: delft3d.support@deltares.nl 18 | // Stichting Deltares 19 | // P.O. Box 177 20 | // 2600 MH Delft, The Netherlands 21 | // 22 | // All indications and logos of, and references to, "Delft3D" and "Deltares" 23 | // are registered trademarks of Stichting Deltares, and remain the property of 24 | // Stichting Deltares. All rights reserved. 25 | // 26 | //------------------------------------------------------------------------------ 27 | 28 | #pragma once 29 | 30 | #include 31 | #include 32 | 33 | /// \namespace ugrid 34 | /// @brief Contains the logic of the C++ static library 35 | namespace ugrid 36 | { 37 | /// @brief A class implementing the methods for reading/writing contact in UGrid format 38 | struct Contacts : UGridEntity 39 | { 40 | /// @brief Constructor setting the NetCDF file 41 | /// @param nc_file The NetCDF file pointer 42 | Contacts(std::shared_ptr nc_file) : UGridEntity(nc_file) 43 | { 44 | } 45 | 46 | /// @brief Constructor setting nc_file and all internal state 47 | /// @param nc_file The NcFile file pointer 48 | /// @param topology_variable The contact name 49 | /// @param entity_attributes The topological attributes (key value pair with key the topological attribute name and value the associated vector of variables) 50 | /// @param entity_attribute_names The topological attributes names (key value pair with key the topological attribute name and value the associated vector of variables names) 51 | /// @param entity_dimensions The dimensions associated with the contact (key value pair with key the dimension enumeration and value the associated NetCDF dimension) 52 | explicit Contacts( 53 | std::shared_ptr nc_file, 54 | netCDF::NcVar const& topology_variable, 55 | std::map> const& entity_attributes, 56 | std::map> const& entity_attribute_names, 57 | std::map const& entity_dimensions); 58 | 59 | /// @brief Defines the contact header (ug_write_mesh_arrays: ug_create_1d_mesh_v2, ug_def_mesh_ids) 60 | /// @param contacts [in] The contact api structure with the fields to write and all optional flags 61 | void define(ugridapi::Contacts const& contacts); 62 | 63 | /// @brief Writes a contact to file 64 | /// @param contacts [in] contact The contact api structure with the fields to write and all optional flags 65 | void put(ugridapi::Contacts const& contacts); 66 | 67 | /// @brief Inquires the contact dimensions 68 | /// @param contacts [out] The contact api structure with the fields where to assign the dimensions 69 | void inquire(ugridapi::Contacts& contacts) const; 70 | 71 | /// @brief Inquires the contact arrays 72 | /// @param contacts [out] The contact api structure with the fields where to assign the data 73 | void get(ugridapi::Contacts& contacts) const; 74 | 75 | /// @brief Function containing the criteria to determine if a variable is a mesh topology contact 76 | /// @param attributes The file attributes 77 | /// @return True if is a mesh topology contact, false otherwise 78 | static bool is_topology_variable(std::map const& attributes); 79 | 80 | /// @brief A function to determine if a topology variable has a matching dimensionality 81 | /// @param attributes [in] The variable attributes 82 | /// @param entity_dimensionality [in] The sought dimensionality 83 | /// @return If The topology variable has a matching functionality 84 | static bool has_matching_dimensionality([[maybe_unused]] std::map const& attributes, 85 | [[maybe_unused]] int entity_dimensionality) 86 | { 87 | return true; 88 | } 89 | 90 | /// @brief Get the dimensionality of a Network1D 91 | /// @return The dimensionality 92 | static int get_dimensionality() { return 1; } 93 | 94 | private: 95 | std::string m_entity_from_name = ""; ///< The name of entity where the contact starts 96 | std::string m_entity_to_name = ""; ///< The name of entity where the contact ends 97 | UGridEntityLocations m_mesh_from_location = invalid_location; ///< The location on the entity where the contact starts 98 | UGridEntityLocations m_mesh_to_location = invalid_location; ///< The location on the entity where the contact ends 99 | }; 100 | } // namespace ugrid 101 | -------------------------------------------------------------------------------- /libs/UGridNET/dll/src/ProjectedCoordinateSystem.cs: -------------------------------------------------------------------------------- 1 | namespace UGridNET 2 | { 3 | 4 | /// 5 | /// Represents a projected coordinate system. 6 | /// 7 | public sealed class ProjectedCoordinateSystem 8 | { 9 | // integers 10 | private int epsg; 11 | 12 | // doubles 13 | private double longitudeOfPrimeMeridian; 14 | private double semiMajorAxis; 15 | private double semiMinorAxis; 16 | private double inverseFlattening; 17 | 18 | // strings 19 | private string name = ""; 20 | private string gridMappingName = ""; 21 | private string proj4Params = ""; 22 | private string EPSG_code = ""; 23 | private string projectionName = ""; 24 | private string wkt = ""; 25 | 26 | /// 27 | /// Gets or sets the EPSG code. 28 | /// 29 | public int EPSG 30 | { 31 | get { return epsg; } 32 | set { epsg = value; } 33 | } 34 | 35 | /// 36 | /// Gets or sets the longitude of the prime meridian. 37 | /// 38 | public double LongitudeOfPrimeMeridian 39 | { 40 | get { return longitudeOfPrimeMeridian; } 41 | set { longitudeOfPrimeMeridian = value; } 42 | } 43 | 44 | /// 45 | /// Gets or sets the semi-major axis. 46 | /// 47 | public double SemiMajorAxis 48 | { 49 | get { return semiMajorAxis; } 50 | set { semiMajorAxis = value; } 51 | } 52 | 53 | /// 54 | /// Gets or sets the semi-minor axis. 55 | /// 56 | public double SemiMinorAxis 57 | { 58 | get { return semiMinorAxis; } 59 | set { semiMinorAxis = value; } 60 | } 61 | 62 | /// 63 | /// Gets or sets the inverse flattening. 64 | /// 65 | public double InverseFlattening 66 | { 67 | get { return inverseFlattening; } 68 | set { inverseFlattening = value; } 69 | } 70 | 71 | /// 72 | /// Gets or sets the name. 73 | /// 74 | public string Name 75 | { 76 | get { return name; } 77 | set { name = value; } 78 | } 79 | 80 | /// 81 | /// Gets or sets the grid mapping name. 82 | /// 83 | public string GridMappingName 84 | { 85 | get { return gridMappingName; } 86 | set { gridMappingName = value; } 87 | } 88 | 89 | /// 90 | /// Gets or sets the Proj4 parameters. 91 | /// 92 | public string Proj4Params 93 | { 94 | get { return proj4Params; } 95 | set { proj4Params = value; } 96 | } 97 | 98 | /// 99 | /// Gets or sets the EPSG code as a string. 100 | /// 101 | public string EPSGCode 102 | { 103 | get { return EPSG_code; } 104 | set { EPSG_code = value; } 105 | } 106 | 107 | /// 108 | /// Gets or sets the projection name. 109 | /// 110 | public string ProjectionName 111 | { 112 | get { return projectionName; } 113 | set { projectionName = value; } 114 | } 115 | 116 | /// 117 | /// Gets or sets the Well-Known Text (WKT) representation. 118 | /// 119 | public string WKT 120 | { 121 | get { return wkt; } 122 | set { wkt = value; } 123 | } 124 | 125 | public ProjectedCoordinateSystem() { } 126 | 127 | /// 128 | /// Initializes a new instance of the class. 129 | /// 130 | /// The EPSG code. 131 | /// The longitude of the prime meridian. 132 | /// The semi-major axis. 133 | /// The semi-minor axis. 134 | /// The inverse flattening. 135 | /// The name. 136 | /// The grid mapping name. 137 | /// The Proj4 parameters. 138 | /// The EPSG code as a string. 139 | /// The Well-Known Text (WKT) representation. 140 | public ProjectedCoordinateSystem( 141 | int epsg, 142 | double longitudeOfPrimeMeridian, 143 | double semiMajorAxis, 144 | double semiMinorAxis, 145 | double inverseFlattening, 146 | string name, 147 | string gridMappingName, 148 | string proj4Params, 149 | string epsgCode, 150 | string projectionName, 151 | string wkt 152 | ) 153 | { 154 | this.epsg = epsg; 155 | this.longitudeOfPrimeMeridian = longitudeOfPrimeMeridian; 156 | this.semiMajorAxis = semiMajorAxis; 157 | this.semiMinorAxis = semiMinorAxis; 158 | this.inverseFlattening = inverseFlattening; 159 | this.name = name; 160 | this.gridMappingName = gridMappingName; 161 | this.proj4Params = proj4Params; 162 | this.EPSG_code = epsgCode; 163 | this.projectionName = projectionName; 164 | this.wkt = wkt; 165 | } 166 | } 167 | } --------------------------------------------------------------------------------