From b4103be54764743e089bd041e9bc7c1c9bf8c95d Mon Sep 17 00:00:00 2001 From: Jacques Franc <49998870+jafranc@users.noreply.github.com> Date: Thu, 7 May 2026 11:21:50 +0200 Subject: [PATCH 01/10] fix: Revert patch b751c2/#246 (#252) * Revert "fix: testing possible bypass broken (#246)" This reverts commit b751c28955536be54933b2c3680b767e3ce05dd1. * post-revert fix --- .github/workflows/test_geos_integration.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test_geos_integration.yml b/.github/workflows/test_geos_integration.yml index 9671e519..872ed20a 100644 --- a/.github/workflows/test_geos_integration.yml +++ b/.github/workflows/test_geos_integration.yml @@ -100,7 +100,7 @@ jobs: -DENABLE_YAPF=OFF \ -DGEOS_ENABLE_TESTS=OFF \ -DGEOS_ENABLE_CONTACT=OFF \ - -DGEOS_ENABLE_FLUIDFLOW=ON \ + -DGEOS_ENABLE_FLUIDFLOW=OFF \ -DGEOS_ENABLE_INDUCEDSEISMICITY=OFF \ -DGEOS_ENABLE_MULTIPHYSICS=OFF \ -DGEOS_ENABLE_SIMPLEPDE=OFF \ @@ -252,6 +252,16 @@ jobs: # Ensure geosx_python_tools is built (provides format_xml) echo "Building geosx_python_tools dependency..." make geosx_python_tools -j8 + + # The geosx_format_all_xml_files target has a bug - it depends on 'geosx_xml_tools' which doesn't exist + # It should depend on 'geosx_python_tools'. Since we can't modify the CMakeLists.txt, + # we'll run the formatting command directly instead + # To solve the bug in cmake, we would have to change: + # add_custom_target( geosx_format_all_xml_files + # COMMAND bash ${CMAKE_SOURCE_DIR}/../scripts/formatXMLFiles.bash -g ${CMAKE_BINARY_DIR}/bin/format_xml ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/../examples + # WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + # DEPENDS geosx_python_tools # ← Change this! + # ) echo "Running XML formatting directly (bypassing broken make target)..." if [ -f "bin/format_xml" ] && [ -f "$GEOS_ROOT/scripts/formatXMLFiles.bash" ]; then From 184a75e7b522b906842ddbed40f8ba507f014193 Mon Sep 17 00:00:00 2001 From: Jacques Franc <49998870+jafranc@users.noreply.github.com> Date: Fri, 15 May 2026 16:37:27 +0200 Subject: [PATCH 02/10] Fix: Install setuptools and wheel before package installation for Python 3.12+ compatibility On Ubuntu 24.04 with Python 3.12+, the distutils module no longer exists in the standard library. This caused package builds to fail with "ModuleNotFoundError: No module named 'distutils'". The fix is to install setuptools, wheel, and pip upfront before attempting to build and install packages. This ensures the build dependencies are available for all subsequent package installations. Moved build dependency installation to the "Install build dependencies" step that runs before package installation. --- .github/workflows/python-package.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 54d08e11..e0298bde 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -104,12 +104,13 @@ jobs: libx11-dev \ libxext-dev + - name: Install build dependencies + run: | + python -m pip install --upgrade pip setuptools wheel + - name: Install package # working-directory: ./${{ matrix.package-name }} run: | - python -m pip install --upgrade pip - - DEPS="${{ matrix.dependencies || '' }}" if [ -n "$DEPS" ]; then @@ -121,8 +122,6 @@ jobs: echo "Installing main package..." python -m pip install ./${{ matrix.package-name }}/[test] - # LWS Install setuptools first to provide pkg_resources for older plugins - python -m pip install setuptools python -m pip install "pytest>=8.0.0" yapf toml "pytest-html>=4.0.0" - name: Lint with yapf From 1527ab264ae1d7f9f0caf5bff71b7f46eb1548ee Mon Sep 17 00:00:00 2001 From: Jacques Franc <49998870+jafranc@users.noreply.github.com> Date: Tue, 19 May 2026 08:55:25 +0200 Subject: [PATCH 03/10] feat: Adding launchpad for GEOS in trame (#162) * starting import launcher handling * ssh login * full PoC * change host * update versions f/ VFileUpload * start status * job status track * kill jobs enable * working w/o copyback * first attempt at copy back * update regex * alternate strat copy back * discard sim_status_view * spliting up big block * refactor cluster entries * completion bars * adjust install and pathing * sd works for external mesh * with internal mesh too * env and assets loading logique * fine-grained conf * rename transfer partition * fixing imporper eval of num unk * allow .vtk for wells meshes * add list of req files before run * yapf * Update .gitignore to include user-specs note * Update Docker image for integration tests * fix CI test-geos-integration with local env for U24 * few fixes --- .github/workflows/python-package.yml | 11 +- .github/workflows/test_geos_integration.yml | 51 ++- .github/workflows/typing-check.yml | 2 +- .gitignore | 5 +- geos-trame/README.rst | 16 +- geos-trame/configure.sh | 4 + geos-trame/pyproject.toml | 16 +- geos-trame/src/geos/trame/app/core.py | 42 +- geos-trame/src/geos/trame/app/io/hpc_tools.py | 99 +++++ .../trame/app/io/jinja_t/local_copyback.jinja | 15 + .../trame/app/io/jinja_t/local_slurm.jinja | 27 ++ .../trame/app/io/jinja_t/p4_copyback.jinja | 15 + .../geos/trame/app/io/jinja_t/p4_slurm.jinja | 27 ++ .../trame/app/io/jinja_t/pine_copyback.jinja | 15 + .../trame/app/io/jinja_t/pine_slurm.jinja | 28 ++ .../src/geos/trame/app/io/simulation.py | 311 +++++++++++++ geos-trame/src/geos/trame/app/io/ssh_tools.py | 307 +++++++++++++ geos-trame/src/geos/trame/app/main.py | 24 +- geos-trame/src/geos/trame/app/ui/plotting.py | 2 +- .../src/geos/trame/app/ui/simulation_view.py | 410 ++++++++++++++++++ .../src/geos/trame/app/ui/viewer/boxViewer.py | 3 +- .../src/geos/trame/app/ui/viewer/viewer.py | 4 +- .../trame/app/utils/async_file_watcher.py | 65 +++ geos-trame/src/geos/trame/assets/cluster.json | 68 +++ install_packages.sh | 12 +- 25 files changed, 1522 insertions(+), 57 deletions(-) create mode 100644 geos-trame/configure.sh create mode 100644 geos-trame/src/geos/trame/app/io/hpc_tools.py create mode 100644 geos-trame/src/geos/trame/app/io/jinja_t/local_copyback.jinja create mode 100644 geos-trame/src/geos/trame/app/io/jinja_t/local_slurm.jinja create mode 100644 geos-trame/src/geos/trame/app/io/jinja_t/p4_copyback.jinja create mode 100644 geos-trame/src/geos/trame/app/io/jinja_t/p4_slurm.jinja create mode 100644 geos-trame/src/geos/trame/app/io/jinja_t/pine_copyback.jinja create mode 100644 geos-trame/src/geos/trame/app/io/jinja_t/pine_slurm.jinja create mode 100644 geos-trame/src/geos/trame/app/io/simulation.py create mode 100644 geos-trame/src/geos/trame/app/io/ssh_tools.py create mode 100644 geos-trame/src/geos/trame/app/ui/simulation_view.py create mode 100644 geos-trame/src/geos/trame/app/utils/async_file_watcher.py create mode 100644 geos-trame/src/geos/trame/assets/cluster.json diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index e0298bde..f533a136 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -104,13 +104,12 @@ jobs: libx11-dev \ libxext-dev - - name: Install build dependencies - run: | - python -m pip install --upgrade pip setuptools wheel - - name: Install package # working-directory: ./${{ matrix.package-name }} run: | + python -m pip install --upgrade pip + + DEPS="${{ matrix.dependencies || '' }}" if [ -n "$DEPS" ]; then @@ -122,6 +121,8 @@ jobs: echo "Installing main package..." python -m pip install ./${{ matrix.package-name }}/[test] + # LWS Install setuptools first to provide pkg_resources for older plugins + python -m pip install setuptools python -m pip install "pytest>=8.0.0" yapf toml "pytest-html>=4.0.0" - name: Lint with yapf @@ -157,7 +158,7 @@ jobs: check_force_integration_label: runs-on: ubuntu-latest - needs: [build] + # needs: [build] outputs: has_geos_integration_force_label: ${{ steps.set-label.outputs.has_label }} steps: diff --git a/.github/workflows/test_geos_integration.yml b/.github/workflows/test_geos_integration.yml index 872ed20a..5edaafd8 100644 --- a/.github/workflows/test_geos_integration.yml +++ b/.github/workflows/test_geos_integration.yml @@ -25,7 +25,7 @@ jobs: container: # using this image to get access to python 3.10+ - image: geosx/ubuntu22.04-gcc12:${{ needs.setup.outputs.tag }} + image: geosx/ubuntu24.04-gcc13:${{ needs.setup.outputs.tag }} steps: - name: Checkout geosPythonPackages @@ -44,22 +44,25 @@ jobs: - name: Install Build Dependencies run: | apt-get update - apt-get install -y make python3-numpy python3-dev python3-venv python3-pip + apt-get install -y make python3-numpy python3-dev python3-venv python3-setuptools # Ensure pip installs scripts to /usr/local/bin export PATH="/usr/local/bin:$PATH" echo "PATH=/usr/local/bin:$PATH" >> $GITHUB_ENV + # For Ubuntu 24.04 with Python 3.12+, setuptools is required (distutils was removed) + # Upgrade setuptools to latest versions + python3 -m pip install --break-system-packages --upgrade setuptools + # Set environment variables to handle setuptools/distutils issues - echo "SETUPTOOLS_USE_DISTUTILS=stdlib" >> $GITHUB_ENV echo "PIP_DISABLE_PIP_VERSION_CHECK=1" >> $GITHUB_ENV echo "PYTHONDONTWRITEBYTECODE=1" >> $GITHUB_ENV - + - name: Setup test environment run: | echo "Setting up test environment..." GEOS_ROOT="$(pwd)/GEOS" - SETUP_PYTHON_ENVIRONMENT_SCRIPT="$GEOS_ROOT/scripts/setupPythonEnvironment.bash" + SETUP_PYTHON_ENVIRONMENT_SCRIPT="${GEOS_ROOT}/scripts/setupPythonEnvironment.bash" if [ -n "${{ github.head_ref }}" ]; then CURRENT_GEOSPYTHONPACKAGES_BRANCH_NAME="${{ github.head_ref }}" @@ -119,6 +122,11 @@ jobs: run: | echo "=== Test 1: Direct setupPythonEnvironment.bash execution ===" mkdir -p bin_direct + + # # encapsulate env + python3 -m venv geos-venv + . geos-venv/bin/activate + python -m pip install --upgrade pip setuptools wheel # The setup script searches specific paths but pip installs to /usr/local/bin # We need to patch the setup script to also search /usr/local/bin @@ -130,8 +138,22 @@ jobs: # Add /usr/local/bin to the MOD_SEARCH_PATH array right after the python bin directory # We insert /usr/local/bin as the second entry - sed -i '/^declare -a MOD_SEARCH_PATH=.*PYTHON_TARGET)"/a\ "/usr/local/bin"' "$TEMP_SETUP_SCRIPT" - + # sed -i '/^declare -a MOD_SEARCH_PATH=.*PYTHON_TARGET)"/a\ "/usr/local/bin"' "$TEMP_SETUP_SCRIPT" + # Only add --break-system-packages for Python >= 3.12 + # PYTHON_VERSION=$($(which python3) -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') + # if [[ "$PYTHON_VERSION" == "3.12" || "$PYTHON_VERSION" > "3.12" ]]; then + # sed -i 's/${PIP_CMD} install/${PIP_CMD} install --break-system-packages/g' "$TEMP_SETUP_SCRIPT" + # sed -i 's/$PYTHON_TARGET -m pip install --upgrade pip setuptools wheel/$PYTHON_TARGET -m pip install --upgrade setuptools/' "$TEMP_SETUP_SCRIPT" + # fi + cat "$TEMP_SETUP_SCRIPT" + export PIP_NO_BUILD_ISOLATION=1 + bash "$TEMP_SETUP_SCRIPT" \ + -p $(which python) \ + -b "$(pwd)/bin_direct" \ + --python-pkg-branch "$CURRENT_GEOSPYTHONPACKAGES_BRANCH_NAME" \ + --verbose + cat "$TEMP_SETUP_SCRIPT" + export PIP_NO_BUILD_ISOLATION=1 bash "$TEMP_SETUP_SCRIPT" \ -p $(which python3) \ -b "$(pwd)/bin_direct" \ @@ -210,6 +232,8 @@ jobs: echo "Creating symlink from PyGEOSX virtual environment..." ln -s "$(pwd)/lib/PYGEOSX/bin/test_geosx_xml_tools" python/geosx/bin/test_geosx_xml_tools else + # If the real test script is not found, create a placeholder so the test step can proceed. + # This ensures the workflow does not fail due to a missing test script, but signals that a real test should be provided. echo "Creating placeholder test script..." echo '#!/usr/bin/env python3' > python/geosx/bin/test_geosx_xml_tools echo 'import sys' >> python/geosx/bin/test_geosx_xml_tools @@ -284,7 +308,16 @@ jobs: run: | if [[ "${{ needs.test_geos_integration.result }}" == "success" ]]; then echo "All integration tests passed successfully!" >> $GITHUB_STEP_SUMMARY - else + elif [[ "${{ needs.test_geos_integration.result }}" == "failure" ]]; then echo "Integration tests failed. Please review the logs." >> $GITHUB_STEP_SUMMARY exit 1 - fi \ No newline at end of file + elif [[ "${{ needs.test_geos_integration.result }}" == "cancelled" ]]; then + echo "Integration tests were cancelled." >> $GITHUB_STEP_SUMMARY + exit 0 + elif [[ "${{ needs.test_geos_integration.result }}" == "skipped" ]]; then + echo "Integration tests were skipped." >> $GITHUB_STEP_SUMMARY + exit 0 + else + echo "Integration tests ended with unknown status: ${{ needs.test_geos_integration.result }}" >> $GITHUB_STEP_SUMMARY + exit 1 + fi diff --git a/.github/workflows/typing-check.yml b/.github/workflows/typing-check.yml index 940fb9fc..b8482468 100644 --- a/.github/workflows/typing-check.yml +++ b/.github/workflows/typing-check.yml @@ -30,7 +30,7 @@ jobs: # working-directory: ./${{ matrix.package-name }} run: | python -m pip install --upgrade pip - python -m pip install mypy ruff types-PyYAML types-pytz + python -m pip install mypy ruff types-PyYAML types-paramiko types-pytz - name: Typing check with mypy # working-directory: ./${{ matrix.package-name }} diff --git a/.gitignore b/.gitignore index 5f08477d..6275d935 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,9 @@ MANIFEST *.manifest *.spec +#env (do not port user-specs) +.env + # Installer logs pip-log.txt pip-delete-this-directory.txt @@ -165,4 +168,4 @@ cython_debug/ #.idea/ # VSCode -.vscode \ No newline at end of file +.vscode diff --git a/geos-trame/README.rst b/geos-trame/README.rst index a1c54deb..6e519cda 100644 --- a/geos-trame/README.rst +++ b/geos-trame/README.rst @@ -21,7 +21,21 @@ Build and install the Vue components cd vue-components npm i npm run build - cd - + cd .. + +then configure the .env + + sh configure.sh + +this will generate a `dotenv` environement file defining useful path to trame, + +.. code-block:: console + + cat .env + TEMPLATE_DIR=/path/to/geosPythonPackages/geos-trame/src/geos/trame/io/jinja_t + ASSETS_DIR=/path/to/geosPythonPackages/geos-trame/src/geos/trame/assets + +those will have lower precedence than local environement variables if defined Install the application diff --git a/geos-trame/configure.sh b/geos-trame/configure.sh new file mode 100644 index 00000000..f46d8ff9 --- /dev/null +++ b/geos-trame/configure.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +echo "TEMPLATE_DIR=${PWD}/src/geos/trame/app/io/jinja_t/" >> ${PWD}/src/geos/trame/assets/.env +echo "ASSETS_DIR=${PWD}/src/geos/trame/assets/" >> ${PWD}/src/geos/trame/assets/.env \ No newline at end of file diff --git a/geos-trame/pyproject.toml b/geos-trame/pyproject.toml index 73d7a028..e751b49b 100644 --- a/geos-trame/pyproject.toml +++ b/geos-trame/pyproject.toml @@ -31,18 +31,19 @@ keywords = [ dependencies = [ "setuptools", - "typing-extensions==4.12.2", "trame==3.6.5", - "trame-vuetify==2.7.1", + "trame-vuetify==3.1.0", "trame-code==1.0.1", "trame-server==3.2.3", - "trame-client==3.5.0", + "trame-client==3.11.2", "trame-simput==2.4.3", - "trame-vtk>=2.8.14", + "trame-vtk==2.10.0", "matplotlib==3.9.4", "trame-matplotlib==2.0.3", "trame-components==2.4.2", + "python-dotenv>=1.2.1", "mpld3<0.5.11", + "paramiko==4.0.0", "xsdata[cli]>=25.4", "xsdata-pydantic[lxml]==24.5", "pyvista==0.45.2", @@ -51,7 +52,7 @@ dependencies = [ "funcy==2.0", "pytz==2025.2", "typing_inspect==0.9.0", - "typing_extensions>=4.12", + "typing_extensions>=4.15.0", "PyYAML", ] @@ -73,7 +74,8 @@ test = [ "pixelmatch==0.3.0", "Pillow==11.0.0", "pytest-mypy==0.10.3", - "pytest-xprocess==1.0.2" + "pytest-xprocess==1.0.2", + "playwright==1.59.0" ] [project.readme] @@ -94,7 +96,7 @@ include-package-data = true # include = ['geos-trame*'] [tool.setuptools.package-data] -"*" = ["*.js", "*.css"] +"*" = ["*.js", "*.css","assets/*","*.jinja","*.json",".env"] [tool.pytest.ini_options] addopts = [ diff --git a/geos-trame/src/geos/trame/app/core.py b/geos-trame/src/geos/trame/app/core.py index 3baf7d38..7452782e 100644 --- a/geos-trame/src/geos/trame/app/core.py +++ b/geos-trame/src/geos/trame/app/core.py @@ -1,7 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. # SPDX-FileContributor: Lionel Untereiner, Jacques Franc - +# ignore context collapsing as it is clearer this way +# ruff: noqa: SIM117 from trame.ui.vuetify3 import VAppLayout from trame.decorators import TrameApp from trame.widgets import html, simput @@ -24,6 +25,9 @@ from geos.trame.app.ui.viewer.viewer import DeckViewer from geos.trame.app.components.alertHandler import AlertHandler +from geos.trame.app.io.simulation import Simulation +from geos.trame.app.ui.simulation_view import define_simulation_view + import sys @@ -38,10 +42,12 @@ def __init__( self, server: Server, file_name: str ) -> None: self.deckEditor: DeckEditor | None = None self.timelineEditor: TimelineEditor | None = None self.deckInspector: DeckInspector | None = None + self.simulationLauncher: Simulation | None = None self.server = server server.enable_module( module ) self.state.input_file = file_name + self.state.user_id = None # TODO handle hot_reload @@ -67,6 +73,9 @@ def __init__( self, server: Server, file_name: str ) -> None: self.region_viewer = RegionViewer() self.well_viewer = WellViewer( 5, 5 ) + ######## Simulation runner + self.simulation = Simulation( server=server ) + # Data loader self.data_loader = DataLoader( self.tree, self.region_viewer, self.well_viewer, trame_server=server ) @@ -177,24 +186,6 @@ def build_ui( self ) -> None: ): vuetify.VIcon( "mdi-content-save-outline" ) - with html.Div( - style= - "height: 100%; width: 300px; display: flex; align-items: center; justify-content: space-between;", - v_if=( "tab_idx == 1", ), - ): - vuetify.VBtn( - "Run", - style="z-index: 1;", - ) - vuetify.VBtn( - "Kill", - style="z-index: 1;", - ) - vuetify.VBtn( - "Clear", - style="z-index: 1;", - ) - # input file editor with vuetify.VCol( v_show=( "tab_idx == 0", ), classes="flex-grow-1 pa-0 ma-0" ): if self.tree.input_file is not None: @@ -208,3 +199,16 @@ def build_ui( self ) -> None: "The file " + self.state.input_file + " cannot be parsed.", file=sys.stderr, ) + + with vuetify.VCol( v_show=( "tab_idx == 1" ), classes="flex-grow-1 pa-0 ma-0" ): + if self.simulation is not None: + define_simulation_view( self.server ) + else: + self.ctrl.on_add_error( + "Error", + "The execution context " + self.state.exec_context + " is not consistent.", + ) + print( + "The execution context " + self.state.exec_context + " is not consistent.", + file=sys.stderr, + ) diff --git a/geos-trame/src/geos/trame/app/io/hpc_tools.py b/geos-trame/src/geos/trame/app/io/hpc_tools.py new file mode 100644 index 00000000..99ffec48 --- /dev/null +++ b/geos-trame/src/geos/trame/app/io/hpc_tools.py @@ -0,0 +1,99 @@ +from geos.trame.app.io.ssh_tools import SimulationConstant + + +class SuggestDecomposition: + + def __init__( self, selected_cluster: SimulationConstant, n_unknowns: int, job_type: str = 'cpu' ) -> None: + """Initialize the decomposition hinter for HPC.""" + self.selected_cluster: SimulationConstant = selected_cluster + self.n_unknowns: int = n_unknowns + self.job_type: str = job_type #TODO should be an enum + self.sd: list[ dict ] = [] + + @staticmethod + def compute( n_unknowns: int, + memory_per_unknown_bytes: int, + node_memory_gb: int, + cores_per_node: int, + min_unknowns_per_rank: int = 10000, + strong_scaling: bool = True ) -> list[ dict ]: + """Suggests node/rank distribution for a cluster computation. + + Parameters: + - n_unknowns: total number of unknowns + - memory_per_unknown_bytes: estimated memory per unknown + - node_memory_gb: available memory per node + - cores_per_node: cores available per node + - min_unknowns_per_rank: minimum for efficiency + - strong_scaling: True if problem size is fixed + + Note: + - 10,000-100,000 unknowns per rank is often a sweet spot for many PDE solvers + - Use power-of-2 decompositions when possible (helps with communication patterns) + - For 3D problems, try to maintain cubic subdomains (minimizes surface-to-volume ratio, reducing communication) + - Don't oversubscribe: avoid using more ranks than provide parallel efficiency + + """ + # Memory constraint + node_memory_bytes = node_memory_gb * 1e9 + max_unknowns_per_node = int( 0.8 * node_memory_bytes / memory_per_unknown_bytes ) + + # Compute minimum nodes needed + min_nodes = max( 1, ( n_unknowns + max_unknowns_per_node - 1 ) // max_unknowns_per_node ) + + # Determine ranks per node + unknowns_per_node = n_unknowns // min_nodes + unknowns_per_rank = max( min_unknowns_per_rank, unknowns_per_node // cores_per_node ) + + # Calculate total ranks needed + n_ranks = max( 1, n_unknowns // unknowns_per_rank ) + + # Distribute across nodes + ranks_per_node = min( cores_per_node, ( n_ranks + min_nodes - 1 ) // min_nodes ) + n_nodes = ( n_ranks + ranks_per_node - 1 ) // ranks_per_node + + return [ + { + 'id': 1, + 'nodes': n_nodes, + 'ranks_per_node': ranks_per_node, + 'total_ranks': n_nodes * ranks_per_node, + 'unknowns_per_rank': n_unknowns // ( n_nodes * ranks_per_node ) + }, + { + 'id': 2, + 'nodes': n_nodes * 2, + 'ranks_per_node': ranks_per_node // 2, + 'total_ranks': n_nodes * ranks_per_node, + 'unknowns_per_rank': n_unknowns // ( n_nodes * ranks_per_node ) + }, + ] + + def get_sd( self ) -> list[ dict ]: + """Get the suggested decomposition popoulated.""" + if self.job_type == 'cpu' and self.selected_cluster: #make it an enum + self.sd = SuggestDecomposition.compute( self.n_unknowns, 64, self.selected_cluster.mem_per_node, + self.selected_cluster.cores_per_node ) + self.sd = [ { + **item, 'label': f"{self.selected_cluster.name} : {item['nodes']} x {item['ranks_per_node']}" + } for item in self.sd ] + else: + self.sd = [ + { + 'id': -1, + 'label': 'No: 0x0', + 'nodes': 0, + 'ranks_per_node': 0, + 'total_ranks': 0, + 'unknowns_per_rank': 0 + }, + ] + # elif job_type == 'gpu': + # selected_cluster['n_nodes']*selected_cluster['gpu']['per_node'] + + return self.sd + + # def to_list( self ) -> list[ str ]: + # """Pretty printer to list of string for display in UI.""" + # sd = self.get_sd() + # return [ f"{self.selected_cluster.name} : {sd_item['nodes']} x {sd_item['ranks_per_node']}" for sd_item in sd ] diff --git a/geos-trame/src/geos/trame/app/io/jinja_t/local_copyback.jinja b/geos-trame/src/geos/trame/app/io/jinja_t/local_copyback.jinja new file mode 100644 index 00000000..fb360583 --- /dev/null +++ b/geos-trame/src/geos/trame/app/io/jinja_t/local_copyback.jinja @@ -0,0 +1,15 @@ +#!/bin/sh +#SBATCH --job-name="{{ job_name }}" +#SBATCH --ntasks={{ ntasks }} +#SBATCH --partition={{ partition }} +#SBATCH --comment={{ comment_gr }} +#SBATCH --account={{ account }} +#SBATCH --nodes={{ nodes }} +#SBATCH --time={{ time | default('00:10:00') }} +#SBATCH --mem={{ mem }} +#SBATCH --output=job_GEOS_%j.out +#SBATCH --error=job_GEOS_%j.err +#SBATCH --dependency=afterok:{{ dep_job_id }} + +srun tar cfz {{ dep_job_id }}.tgz Outputs_{{ dep_job_id }}/ log_{{ dep_job_id }}.out +srun mkdir -p {{ target_dl_path }} && mv -v {{ dep_job_id }}.tgz {{ target_dl_path }} \ No newline at end of file diff --git a/geos-trame/src/geos/trame/app/io/jinja_t/local_slurm.jinja b/geos-trame/src/geos/trame/app/io/jinja_t/local_slurm.jinja new file mode 100644 index 00000000..21f6ff6f --- /dev/null +++ b/geos-trame/src/geos/trame/app/io/jinja_t/local_slurm.jinja @@ -0,0 +1,27 @@ +#!/bin/sh +#SBATCH --job-name="{{ job_name }}" +#SBATCH --ntasks={{ ntasks }} +#SBATCH --partition={{ partition }} +#SBATCH --comment={{ comment_gr }} +#SBATCH --account={{ account }} +#SBATCH --nodes={{ nodes }} +#SBATCH --time={{ time | default('00:10:00') }} +#SBATCH --mem={{ mem }} +#SBATCH --output=job_GEOS_%j.out +#SBATCH --error=job_GEOS_%j.err + +ulimit -s unlimited +ulimit -c unlimited + +module purge +module use {{ geos_module }} +module load {{ geos_load_list }} + +export HDF5_USE_FILE_LOCKING=FALSE +export OMP_NUM_THREADS=1 +export EXEC={{ geos_path }} + +srun --hint=nomultithread \ + -n {{ ntasks }} ${EXEC} \ + -o Outputs_${SLURM_JOBID} \ + -i {{ input_file | default('geosDeck.xml') }} | tee Outputs_${SLURM_JOBID}/log_${SLURM_JOBID}.out \ No newline at end of file diff --git a/geos-trame/src/geos/trame/app/io/jinja_t/p4_copyback.jinja b/geos-trame/src/geos/trame/app/io/jinja_t/p4_copyback.jinja new file mode 100644 index 00000000..35cc2b79 --- /dev/null +++ b/geos-trame/src/geos/trame/app/io/jinja_t/p4_copyback.jinja @@ -0,0 +1,15 @@ +#!/bin/sh +#SBATCH --job-name="{{ job_name }}" +#SBATCH --ntasks={{ ntasks }} +#SBATCH --partition={{ partition }} +#SBATCH --comment={{ comment_gr }} +#SBATCH --account={{ account }} +#SBATCH --nodes={{ nodes }} +#SBATCH --time={{ time | default('00:10:00') }} +#SBATCH --mem={{ mem }} +#SBATCH --output=job_GEOS_%j.out +#SBATCH --err=job_GEOS_%j.err +#SBATCH --dependency=afterok:{{ dep_job_id }} + +srun tar cfz {{ dep_job_id }}.tgz Outputs_{{ dep_job_id }}/ log_{{ dep_job_id }}.out +srun mkdir -p {{ target_dl_path }} && mv -v {{ dep_job_id }}.tgz {{ target_dl_path }} diff --git a/geos-trame/src/geos/trame/app/io/jinja_t/p4_slurm.jinja b/geos-trame/src/geos/trame/app/io/jinja_t/p4_slurm.jinja new file mode 100644 index 00000000..bb331e45 --- /dev/null +++ b/geos-trame/src/geos/trame/app/io/jinja_t/p4_slurm.jinja @@ -0,0 +1,27 @@ +#!/bin/sh +#SBATCH --job-name="{{ job_name }}" +#SBATCH --ntasks={{ ntasks }} +#SBATCH --partition={{ partition }} +#SBATCH --comment={{ comment_gr }} +#SBATCH --account={{ account }} +#SBATCH --nodes={{ nodes }} +#SBATCH --time={{ time | default('00:10:00') }} +#SBATCH --mem={{ mem }} +#SBATCH --output=job_GEOS_%j.out +#SBATCH --error=job_GEOS_%j.err + +ulimit -s unlimited +ulimit -c unlimited + +module purge +module use {{ geos_module }} +module load {{ geos_load_list }} + +export HDF5_USE_FILE_LOCKING=FALSE +export OMP_NUM_THREADS=1 +export EXEC={{ geos_path }} + +srun --mpi=pmix_v3 --hint=nomultithread \ + -n {{ ntasks }} ${EXEC} \ + -o Outputs_${SLURM_JOBID} \ + -i {{ input_file | default('geosDeck.xml') }} | tee log_${SLURM_JOBID}.out diff --git a/geos-trame/src/geos/trame/app/io/jinja_t/pine_copyback.jinja b/geos-trame/src/geos/trame/app/io/jinja_t/pine_copyback.jinja new file mode 100644 index 00000000..e849c07d --- /dev/null +++ b/geos-trame/src/geos/trame/app/io/jinja_t/pine_copyback.jinja @@ -0,0 +1,15 @@ +#!/bin/sh +#SBATCH --job-name="{{ job_name }}" +#SBATCH --ntasks={{ ntasks }} +#SBATCH --partition={{ partition }} +#SBATCH --comment={{ comment_gr }} +#SBATCH --account={{ account }} +#SBATCH --nodes={{ nodes }} +#SBATCH --time={{ time | default('00:10:00') }} +#SBATCH --mem={{ mem }} +#SBATCH --output=job_GEOS_%j.out +#SBATCH --error=job_GEOS_%j.err +#SBATCH --dependency=afterok:{{ dep_job_id }} + +srun tar cfz {{ dep_job_id }}.tgz Outputs_{{ dep_job_id }}/ log_{{ dep_job_id }}.out +srun mkdir -p {{ target_dl_path }} && mv -v {{ dep_job_id }}.tgz {{ target_dl_path }} diff --git a/geos-trame/src/geos/trame/app/io/jinja_t/pine_slurm.jinja b/geos-trame/src/geos/trame/app/io/jinja_t/pine_slurm.jinja new file mode 100644 index 00000000..0c47ae29 --- /dev/null +++ b/geos-trame/src/geos/trame/app/io/jinja_t/pine_slurm.jinja @@ -0,0 +1,28 @@ +#!/bin/sh +#SBATCH --job-name="{{ job_name }}" +#SBATCH --ntasks={{ ntasks }} +#SBATCH --partition={{ partition }} +#SBATCH --comment={{ comment_gr }} +#SBATCH --account={{ account }} +#SBATCH --nodes={{ nodes }} +#SBATCH --time={{ time | default('00:10:00') }} +#SBATCH --mem={{ mem }} +#SBATCH --output=job_GEOS_%j.out +#SBATCH --error=job_GEOS_%j.err + +ulimit -s unlimited +ulimit -c unlimited + +module purge +module use {{ geos_module }} +module load {{ geos_load_list }} + +export HDF5_USE_FILE_LOCKING=FALSE +export OMP_NUM_THREADS=1 +export EXEC={{ geos_path }} + +mkdir -p Outputs_${SLURM_JOBID} && touch log_${SLURM_JOBID}.out +mpirun -mca coll_hcoll_enable 0 -x UCX_RNDV_THRESH=131072 \ + -n {{ ntasks }} ${EXEC} \ + -o Outputs_${SLURM_JOBID} \ + -i {{ input_file | default('geosDeck.xml') }} | tee Outputs_${SLURM_JOBID}/log_${SLURM_JOBID}.out diff --git a/geos-trame/src/geos/trame/app/io/simulation.py b/geos-trame/src/geos/trame/app/io/simulation.py new file mode 100644 index 00000000..e4afac10 --- /dev/null +++ b/geos-trame/src/geos/trame/app/io/simulation.py @@ -0,0 +1,311 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. +# SPDX-FileContributor: Jacques Franc + +from pathlib import Path +from enum import Enum, unique, auto +from typing import Optional, Any +from trame_server.core import Server + +from geos.trame.app.io.ssh_tools import Authentificator +from geos.trame.app.utils.async_file_watcher import AsyncPeriodicRunner + +from jinja2 import Environment, FileSystemLoader +import paramiko +import re +import os + + +@unique +class SimulationStatus( Enum ): + SCHEDULED = auto() + RUNNING = auto() + COMPLETING = auto() + COPY_BACK = auto() + DONE = auto() + NOT_RUN = auto() + UNKNOWN = auto() + + +@unique +class SlurmJobStatus( Enum ): + PENDING = "PEND" + RUNNING = "R" + COMPLETING = "CG" + COMPLETED = "CD" + SUSPENDED = "S" + UNKNOWN = "UNKNOWN" + + +class Simulation: + """Simulation component. + + Fills the UI with the screenshot as read from the simulation outputs folder and a graph with the time series + from the simulation. + Requires a simulation runner providing information on the output path of the simulation to monitor and ways to + trigger the simulation. + """ + + def __init__( self, server: Server, sim_info_dir: Optional[ Path ] = None ) -> None: + """Initialize the Simulation object with logging and sim triggers among other callbacks.""" + self._server = server + controller = server.controller + self._sim_info_dir = sim_info_dir + server.state.job_ids = [] + server.state.selected_cluster = None + server.state.nunknowns = 1 + + server.state.status_colors = { + "PENDING": "#4CAF50", #PD + "RUNNING": "#3F51B5", #R + "CANCELLED": "#FFC107", #CA + "COMPLETED": "#484B45", #CD + "FAILED": "#E53935", #F + } + self._job_status_watcher: Optional[ AsyncPeriodicRunner ] = None + self._job_status_watcher_period_ms = 2000 + + #define triggers + @controller.trigger( "run_try_login" ) + def run_try_login() -> None: + + # if server.state.key: + Authentificator.ssh_client = Authentificator._create_ssh_client( + Authentificator.get_cluster( server.state.selected_cluster_name ).host, #test + Authentificator.get_cluster( server.state.selected_cluster_name ).port, + server.state.login, + key=Authentificator.get_key( server.state.login, server.state.password, server.state.key_path, + server.state.selected_cluster_name ) ) + + if Authentificator.ssh_client: + server.state.access_granted = True + + @controller.trigger( "run_simulation" ) + def run_simulation() -> None: + + # if server.state.access_granted and server.state.sd and server.state.simulation_xml_filename: + if server.state.access_granted and server.state.simulation_xml_filename and server.state.decomposition: + if Authentificator.ssh_client: + # create remote path + try: + sftp = Authentificator.ssh_client.open_sftp() + sftp.stat( server.state.simulation_remote_path ) + except FileNotFoundError: + import posixpath + jpart = '/' + for part in server.state.simulation_remote_path.split( '/' )[ 1: ]: + try: + jpart = posixpath.join( jpart, part ) + sftp.stat( str( jpart ) ) # exists? + except FileNotFoundError: + sftp.mkdir( str( jpart ) ) + except PermissionError: + print( f"Permission error creating root folder at {jpart}" ) + raise + except: + print( f"Error creating root folder at {jpart}" ) + raise + + # create local path + os.makedirs( server.state.simulation_dl_path, exist_ok=True ) + + Authentificator._sftp_copy_tree( Authentificator.ssh_client, + Simulation.gen_tree( server.state.simulation_xml_filename ), + server.state.simulation_remote_path ) + + cluster_name = Authentificator.get_cluster( server.state.selected_cluster_name ).name + cluster_part = Authentificator.get_cluster( server.state.selected_cluster_name ).partition + cluster_trans_part = Authentificator.get_cluster( + server.state.selected_cluster_name ).partition_transfert + run_id: str = Simulation.render_and_run( + f'{cluster_name}_slurm.jinja', + 'job.slurm', + server, + job_name=server.state.simulation_job_name, + input_file=[ + item for item in server.state.simulation_xml_filename if item.get( 'type' ) == 'text/xml' + ][ 0 ].get( 'name' ), + nodes=server.state.decomposition[ 'nodes' ], + ntasks=server.state.decomposition[ 'nodes' ] * server.state.decomposition[ 'ranks_per_node' ], + geos_module=Authentificator.get_cluster( server.state.selected_cluster_name ).geos_module, + geos_load_list=" ".join( + Authentificator.get_cluster( server.state.selected_cluster_name ).geos_load_list ), + geos_path=Authentificator.get_cluster( server.state.selected_cluster_name ).geos_path, + mem="0", + comment_gr=server.state.slurm_comment, + partition=cluster_part, + account=server.state.slurm_comment ) + + Simulation.render_and_run( f'{cluster_name}_copyback.jinja', + 'copyback.slurm', + server, + job_name=server.state.simulation_job_name, + input_file=[ + item for item in server.state.simulation_xml_filename + if item.get( 'type' ) == 'text/xml' + ][ 0 ].get( 'name' ), + nodes=1, + ntasks=1, + mem="0", + dep_job_id=run_id, + target_dl_path=server.state.simulation_dl_path, + comment_gr=server.state.slurm_comment, + partition=cluster_trans_part, + account=server.state.slurm_comment ) + + self._start_result_streams() + + else: + raise paramiko.SSHException + + @controller.trigger( "kill_all_simulations" ) + def kill_all_simulations() -> None: + # exec scancel jobid + for jobs in server.state.job_ids: + Authentificator.kill_job( jobs[ 'job_id' ] ) + + def __del__( self ) -> None: + """Clean up running streams on destruction.""" + self._stop_result_streams() + + def set_status_watcher_period_ms( self, period_ms: int ) -> None: + """Set the watcher period in ms.""" + self._job_status_watcher_period_ms = period_ms + if self._job_status_watcher: + self._job_status_watcher.set_period_ms( period_ms ) + + def _stop_result_streams( self ) -> None: + if self._job_status_watcher is not None: + self._job_status_watcher.stop() + + def _start_result_streams( self ) -> None: + self._stop_result_streams() + self._job_status_watcher = AsyncPeriodicRunner( self.check_jobs, period_ms=self._job_status_watcher_period_ms ) + + def check_jobs( self ) -> None: + """Check on running jobs and update their names and progresses.""" + if Authentificator.ssh_client: + jid = self._server.state.job_ids + for index, job in enumerate( jid ): + job_id = job[ 'job_id' ] + _, sout, _ = Authentificator._execute_remote_command( + Authentificator.ssh_client, f'sacct -j {job_id} -o JobID,JobName,State --noheader' ) + job_line = sout.strip().split( "\n" )[ -1 ] + + jid[ index ][ 'status' ] = job_line.split()[ 2 ] + jid[ index ][ 'name' ] = job_line.split()[ 1 ] + + if ( jid[ index ][ 'status' ] == 'RUNNING' ): + _, sout, _ = Authentificator._execute_remote_command( + Authentificator.ssh_client, + f"sacct -j {job_id} -o ElapsedRaw,TimelimitRaw --noheader --parsable2 | head -n 1 " ) + progress_line = sout.strip().split( "|" ) + jid[ index ][ 'slprogress' ] = str( + float( progress_line[ 0 ] ) / float( progress_line[ 1 ] ) / 60 * 100 ) + + # getthe completed status + pattern = re.compile( r'\((\d+(?:\.\d+)?)%\s*completed\)' ) + _, sout, _ = Authentificator._execute_remote_command( + Authentificator.ssh_client, + f"grep \"completed\" {self._server.state.simulation_remote_path}/job_GEOS_{job_id}.out | tail -1" + ) + m = pattern.search( sout.strip() ) + if m: + jid[ index ][ 'simprogress' ] = str( m.group( 1 ) ) + + print( + f"{job_line}-{job_id}\n job id:{jid[index]['job_id']}\n status:{jid[index]['status']}\n name:{jid[index]['name']} \n --- \n" + ) + self._server.state.job_ids = jid + self._server.state.dirty( "job_ids" ) + self._server.state.flush() + + return None + + @staticmethod + def render_and_run( template_name: str, dest_name: str, server: Server, **kwargs: Any ) -> str: + """Render the slurm template and run it. Return it job_id.""" + if server.state.access_granted and server.state.simulation_xml_filename: + template = Environment( + loader=FileSystemLoader( f'{os.getenv("TEMPLATE_DIR")}' ) ).get_template( template_name ) + rendered = template.render( kwargs ) + + if Authentificator.ssh_client: + #write slurm directly on remote + try: + sftp = Authentificator.ssh_client.open_sftp() + remote_path = Path( server.state.simulation_remote_path ) / Path( dest_name ) + with sftp.file( str( remote_path ), 'w' ) as f: + f.write( rendered ) + + except PermissionError as e: + print( f"Permission error: {e}" ) + except IOError as e: + print( f"Error accessing remote file or path: {e}" ) + except Exception as e: + print( f"An error occurred during SFTP: {e}" ) + + _, sout, _ = Authentificator._execute_remote_command( + Authentificator.ssh_client, f'cd {server.state.simulation_remote_path} && sbatch {dest_name}' ) + job_lines = sout.strip() + job_id = re.search( r"Submitted batch job (\d+)", job_lines ) + if job_id: + server.state.job_ids.append( { 'job_id': job_id.group( 1 ) } ) + return job_id.group( 1 ) + else: + return "-1" + else: + return "-1" + else: + return "-1" + + @staticmethod + def gen_tree( xml_filename: Any ) -> dict: + """Generate file tree to be copied on remote from files uploaded.""" + import re + xml_pattern = re.compile( r"\.xml$", re.IGNORECASE ) + mesh_pattern = re.compile( r"\.(vtu|vtm|pvtu|pvtm)$", re.IGNORECASE ) + table_pattern = re.compile( r"\.(txt|dat|csv|geos)$", re.IGNORECASE ) + xml_matches = [] + mesh_matches = [] + table_matches = [] + + pattern_file = r"[\w\-.]+\.(?:vtu|pvtu|dat|txt|xml|geos)\b" # all files + pattern_xml_path = r"\"(.*/)*([\w\-.]+\.(?:xml))\b" + pattern_mesh_path = r"\"(.*/)*([\w\-.]+\.(?:vtu|pvtu|vtm|pvtm))\b" + pattern_table_curly_path = r"((?:[\w\-/]+/)+)*([\w\-.]+\.(?:geos|csv|dat|txt))" + + for file in xml_filename: + if xml_pattern.search( file.get( "name", "" ) ): + xml_matches.append( file ) + elif mesh_pattern.search( file.get( "name", "" ) ): + mesh_matches.append( file ) + elif table_pattern.search( file.get( "name", "" ) ): + table_matches.append( file ) + + #assume the first XML is the main xml + xml_expected_file_matches = re.findall( pattern_file, xml_matches[ 0 ][ 'content' ].decode( "utf-8" ) ) + + #TODO all the needed files + test_assert = { item.get( "name" ) for item in xml_filename }.intersection( set( xml_expected_file_matches ) ) + assert test_assert + + decoded = re.sub( pattern_xml_path, r'"\2', xml_matches[ 0 ][ 'content' ].decode( "utf-8" ) ) + decoded = re.sub( pattern_mesh_path, r'"mesh/\2', decoded ) + decoded = re.sub( pattern_table_curly_path, r"tables/\2", decoded ) + + xml_matches[ 0 ][ 'content' ] = decoded.encode( "utf-8" ) + + FILE_TREE = { + 'root': '.', + "structure": { + "files": xml_matches, + "subfolders": { + "mesh": mesh_matches, + "tables": table_matches + } + } + } + + print( f"Generated FILE_TREE: {FILE_TREE}" ) + return FILE_TREE diff --git a/geos-trame/src/geos/trame/app/io/ssh_tools.py b/geos-trame/src/geos/trame/app/io/ssh_tools.py new file mode 100644 index 00000000..ff5ef654 --- /dev/null +++ b/geos-trame/src/geos/trame/app/io/ssh_tools.py @@ -0,0 +1,307 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. +# SPDX-FileContributor: Jacques Franc + +from typing import Optional +from pathlib import Path +import paramiko +import os +import json +from dataclasses import dataclass + + +@dataclass +class SimulationConstant: + name: str + host: str + partition: str + partition_transfert: str + port: int + geos_path: str + geos_module: str + geos_load_list: list + remote_home_base: str # for ssh key + simulation_default_filename: str + simulation_remote_path: str + simulation_dl_default_path: str + simulation_information_default_path: str + n_nodes: int + cores_per_node: int + mem_per_node: int + + +#If proxyJump are needed +# +# proxy_cmd = "ssh -W {host}:{port} proxyuser@bastion.example.com".format( +# host=ssh_host, port=ssh_port +# ) +# from paramiko import ProxyCommand +# sock = ProxyCommand(proxy_cmd) + +# client = paramiko.SSHClient() +# client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) +# client.connect( +# hostname=ssh_host, +# port=ssh_port, +# username=username, +# key_filename=keyfile, +# sock=sock, # <— tunnel created by ProxyCommand +# ) + + +class Authentificator: + + ssh_client: Optional[ paramiko.SSHClient ] = None + + sim_constants: list = [] + + @staticmethod + def reload_simconstants() -> None: + """Reload the cluster configuration from cluster.json file.""" + Authentificator.sim_constants = [ + SimulationConstant( **item ) + for item in json.load( open( f'{os.getenv("ASSETS_DIR")}/cluster.json', 'r' ) ) # noqa: SIM115 + ] + + @staticmethod + def get_cluster( name: str ) -> Optional[ SimulationConstant ]: + """Return the structured meta for cluster selected.""" + match = next( ( item for item in Authentificator.sim_constants if item.name == name ), None ) + return match + + @staticmethod + def _sftp_copy_tree( ssh_client: paramiko.SSHClient, file_tree: dict, remote_root: str ) -> None: + """Copy the file tree at remote root using ssh_client.""" + # Connect to remote server + sftp = ssh_client.open_sftp() + + Authentificator.dfs_tree( file_tree[ "structure" ], file_tree[ "root" ], sftp=sftp, remote_root=remote_root ) + + sftp.close() + + @staticmethod + def dfs_tree( node: list | dict, path: str, sftp: paramiko.SFTPClient, remote_root: str ) -> None: + """Create the tree represented by node at local path in remote pointed by sftp client at remote_root.""" + if path is None or remote_root is None: + return # type:ignore[unreachable] + + lp = Path( path ) + rp = Path( remote_root ) / lp + + if isinstance( node, list ): + for file in node: + print( f"copying {lp/Path(file.get('name'))} to {rp/Path(file.get('name'))}" ) + try: + content = file.get( 'content' ) + mode = "wb" if isinstance( content, ( bytes, bytearray ) ) else "w" + with sftp.file( str( rp / Path( file.get( 'name' ) ) ), mode ) as f: + f.write( content ) + except Exception as e: + print( f"Error copying {lp/Path(file.get('name'))} to {rp/Path(file.get('name'))}: {e}" ) + raise + elif isinstance( node, dict ): + if "files" in node: + files = node[ 'files' ] + for file in files: + print( f"copying {lp/Path(file.get('name'))} to {rp/Path(file.get('name'))}" ) + try: + content = file.get( 'content' ) + mode = "wb" if isinstance( content, ( bytes, bytearray ) ) else "w" + with sftp.file( str( rp / Path( file.get( 'name' ) ) ), mode ) as f: + f.write( content ) + except Exception as e: + print( f"Error copying {lp/Path(file.get('name'))} to {rp/Path(file.get('name'))}: {e}" ) + raise + if "subfolders" in node: + for subfolder, content in node[ "subfolders" ].items(): + try: + sftp.stat( str( rp / Path( subfolder ) ) ) + except FileNotFoundError: + try: + print( f"creating {rp/Path(subfolder)}" ) + sftp.mkdir( str( rp / Path( subfolder ) ) ) + except: + print( f"Error creating {rp/Path(subfolder)} on remote." ) + raise + Authentificator.dfs_tree( content, str( lp / Path( subfolder ) ), sftp, remote_root ) + + for folder, content in node.items(): + if folder not in [ "files", "subfolders" ]: + try: + sftp.stat( str( rp / Path( folder ) ) ) + except FileNotFoundError: + print( f"creating {rp/Path(folder)}" ) + try: + sftp.mkdir( str( rp / Path( folder ) ) ) + except: + print( f"Error creating {rp/Path(subfolder)} on remote." ) + raise + Authentificator.dfs_tree( content, str( lp / Path( folder ) ), sftp, remote_root ) + + @staticmethod + def kill_job( id: int ) -> None: + """Cancel job identified by id in slurm schedulder.""" + if Authentificator.ssh_client: + Authentificator._execute_remote_command( Authentificator.ssh_client, f"scancel {id}" ) + return None + + @staticmethod + def get_key( id: str, pword: str, key_path: str, cluster_name: str ) -> paramiko.RSAKey: + """Return the ssh key if found or create and dispatch one.""" + try: + PRIVATE_KEY = paramiko.RSAKey.from_private_key_file( key_path ) + return PRIVATE_KEY + except paramiko.SSHException as e: + print( f"Error loading private key: {e}\n" ) + raise paramiko.SSHException( f"Error loading private key: {e}\n" ) from e + except FileNotFoundError as e: + print( f"Private key not found: {e}\n Generating key at ... {key_path}" ) + PRIVATE_KEY = Authentificator.gen_key( key_path ) + temp_client = paramiko.SSHClient() + temp_client.set_missing_host_key_policy( paramiko.AutoAddPolicy() ) + + clusterByName = Authentificator.get_cluster( cluster_name ) + if clusterByName is None: + raise ValueError( f"Cluster '{cluster_name}' not found in configuration." ) from e + + host = clusterByName.host + port = clusterByName.port + temp_client.connect( host, port, username=id, password=pword, timeout=10 ) + remote_base = clusterByName.remote_home_base + Authentificator._transfer_file_sftp( temp_client, f"{key_path.split('/')[-1]}.pub", + f"{remote_base}/{id}/.ssh/{key_path.split('/')[-1]}.pub" ) + Authentificator._execute_remote_command( + temp_client, + f" cat {remote_base}/.ssh/{key_path.split('/')[-1]}.pub | tee -a {clusterByName.remote_home_base}/.ssh/authorized_keys" + ) + + return PRIVATE_KEY + + @staticmethod + def gen_key( key_path: str ) -> paramiko.RSAKey: + """Generate RSAKey for SSH protocol.""" + # home = os.environ.get( "HOME" ) + # file_path = f"{home}/.ssh/id_trame" + key = paramiko.RSAKey.generate( bits=4096 ) + key.write_private_key_file( key_path ) + + # Get public key in OpenSSH format + public_key = f"{key.get_name()} {key.get_base64()}" + with open( key_path + ".pub", "w" ) as pub_file: + pub_file.write( public_key ) + + suffix = key_path.split( '/' )[ -1 ] + print( f"SSH key pair generated: {suffix} (private), {suffix}.pub (public)" ) + + return key + + @staticmethod + def _create_ssh_client( host: str, + port: int, + username: str, + password: str | None = None, + key: paramiko.RSAKey | None = None ) -> paramiko.SSHClient | None: + """Initializes and returns an SSH client connection. + + Uses context manager for automatic cleanup. + """ + client = paramiko.SSHClient() + # Automatically adds the hostname and new host keys to the host files (~/.ssh/known_hosts) + client.set_missing_host_key_policy( paramiko.AutoAddPolicy() ) + + try: + print( f"Connecting to {host} using key-based authentication..." ) + client.connect( host, port, username, pkey=key, timeout=10 ) + + return client + except paramiko.AuthenticationException: + print( "Authentication failed. Check your credentials or key." ) + return None + except paramiko.SSHException as e: + print( f"Could not establish SSH connection: {e}" ) + return None + except Exception as e: + print( f"An unexpected error occurred: {e}" ) + return None + + @staticmethod + def _execute_remote_command( client: paramiko.SSHClient, command: str ) -> tuple[ int, str, str ]: + """Executes a single command on the remote server and prints the output.""" + if not client: + return ( -1, "", "" ) + + print( f"\n--- Executing Command: '{command}' ---" ) + try: + # Executes the command. stdin, stdout, and stderr are file-like objects. + # Ensure command ends with a newline character for some shell environments. + stdin, stdout, stderr = client.exec_command( command ) + + # Wait for the command to finish and read the output + exit_status = stdout.channel.recv_exit_status() + + # Print standard output + stdout_data = stdout.read().decode().strip() + if stdout_data: + print( "STDOUT:" ) + print( stdout_data ) + + # Print standard error (if any) + stderr_data = stderr.read().decode().strip() + if stderr_data: + print( "STDERR:" ) + print( stderr_data ) + + print( f"Command exited with status: {exit_status}" ) + return ( exit_status, stdout_data, stderr_data ) + + except PermissionError as e: + print( f"Permission error: {e}" ) + return ( -1, "", "" ) + except IOError as e: + print( f"Error accessing remote file or path: {e}" ) + return ( -1, "", "" ) + except Exception as e: + print( f"An error occurred during SFTP: {e}" ) + return ( -1, "", "" ) + + @staticmethod + def _transfer_file_sftp( client: paramiko.SSHClient, + local_path: str, + remote_path: str, + direction: str = "put" ) -> Optional[ bool ]: + """Transfers a file using SFTP (Secure File Transfer Protocol). + + Direction can be 'put' (upload) or 'get' (download). + """ + if not client: + return None + + print( f"\n--- Starting SFTP Transfer ({direction.upper()}) ---" ) + + try: + # Establish an SFTP connection session + sftp = client.open_sftp() + + if direction == "put": + print( f"Uploading '{local_path}' to '{remote_path}'..." ) + sftp.put( local_path, remote_path ) + print( "Upload complete." ) + elif direction == "get": + print( f"Downloading '{remote_path}' to '{local_path}'..." ) + sftp.get( remote_path, local_path ) + print( "Download complete." ) + else: + print( "Invalid transfer direction. Use 'put' or 'get'." ) + + sftp.close() + return True + + except FileNotFoundError: + print( f"Error: Local file '{local_path}' not found." ) + return False + except IOError as e: + print( f"Error accessing remote file or path: {e}" ) + return False + except Exception as e: + print( f"An error occurred during SFTP: {e}" ) + return False diff --git a/geos-trame/src/geos/trame/app/main.py b/geos-trame/src/geos/trame/app/main.py index 2ad3b293..cada4bee 100644 --- a/geos-trame/src/geos/trame/app/main.py +++ b/geos-trame/src/geos/trame/app/main.py @@ -1,13 +1,17 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. -# SPDX-FileContributor: Lionel Untereiner +# SPDX-FileContributor: Lionel Untereiner, Jacques Franc from pathlib import Path from typing import Any +from dotenv import load_dotenv +import os from trame.app import get_server # type: ignore from trame_server import Server +#do not override if existing from geos.trame.app.core import GeosTrame +from geos.trame.app.io.ssh_tools import Authentificator def main( server: Server = None, **kwargs: Any ) -> None: @@ -24,13 +28,23 @@ def main( server: Server = None, **kwargs: Any ) -> None: # parse args parser = server.cli - parser.add_argument( "-I", "--input", help="Input file (.xml)" ) + parser.add_argument( "-I", "--input", help="Input file (.xml)", required=True ) + parser.add_argument( "-e", "--env", help="dot_env file", required=False ) ( args, _unknown ) = parser.parse_known_args() - if args.input is None: - print( "Usage: \n\tgeos-trame -I /path/to/input/file" ) - return + if args.env: + if not load_dotenv( dotenv_path=Path( args.env ) ): + raise SystemExit( f"Failed to load environment file: {args.env}" ) + else: + env_path = Path( __file__ ).parent.parent / "assets/.env" + if not load_dotenv( dotenv_path=env_path ): + raise SystemExit( f"Failed to load environment file: {env_path}" ) + + Authentificator.reload_simconstants() + + print( f"TEMPLATE_DIR .. {os.getenv('TEMPLATE_DIR')}" ) + print( f"ASSETS_DIR .. {os.getenv('ASSETS_DIR')}" ) file_name = str( Path( args.input ).absolute() ) diff --git a/geos-trame/src/geos/trame/app/ui/plotting.py b/geos-trame/src/geos/trame/app/ui/plotting.py index 1ca2bbb9..790203c2 100644 --- a/geos-trame/src/geos/trame/app/ui/plotting.py +++ b/geos-trame/src/geos/trame/app/ui/plotting.py @@ -57,7 +57,7 @@ def _figure_size( self ) -> dict: "dpi": dpi, } - def _permeability( self, **kwargs: Any ) -> Figure: + def _permeability( self, **kwargs: Any ) -> type[ Figure ]: # read data assert self.source.input_file is not None if self.source.input_file is None: diff --git a/geos-trame/src/geos/trame/app/ui/simulation_view.py b/geos-trame/src/geos/trame/app/ui/simulation_view.py new file mode 100644 index 00000000..627b4757 --- /dev/null +++ b/geos-trame/src/geos/trame/app/ui/simulation_view.py @@ -0,0 +1,410 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. +# SPDX-FileContributor: Jacques Franc +# ignore context collapsing as it is clearer this way +# ruff: noqa: SIM117 +from typing import Any + +from trame.widgets import html +from trame.widgets import vuetify3 as vuetify +from trame_server import Server + +from geos.trame.app.io.simulation import Authentificator +from geos.trame.app.io.hpc_tools import SuggestDecomposition + +#rough estimate of n unknowns would be better from GEOS's dry-run +# unknowns (oncell,onpoint) +# for now do not take into account wells as dep on the num of wells (neg vs matrix elmts) +# for now do not take into account frac as dep on the num of frac elmts (prob neg vs matrix elmts) +solvers_to_unknowns = { + "CompositionalMultiphaseFVM": ( 3, 0 ), + "CompositionalMultiphaseHybridFVM": ( 4, 0 ), + "CompositionalMultiphaseReservoirPoromechanics": ( 3, 3 ), + "CompositionalMultiphaseReservoirPoromechanicsConformingFractures": ( 3, 6 ), + "CompositionalMultiphaseWell": ( 3, 0 ), + "ElasticFirstOrderSEM": ( 0, 3 ), + "ElasticSEM": ( 0, 3 ), + "ImmiscibleMultiphaseFlow": ( 3, 0 ), + "LaplaceFEM": ( 0, 3 ), + "MultiphasePoromechanics": ( 3, 3 ), + "MultiphasePoromechanicsReservoir": ( 3, 3 ), #?? + "MultiphasePoromechanicsConformingFractures": ( 3, 6 ), + "SinglePhaseFVM": ( 2, 0 ), + "SinglePhaseHybridFVM": ( 3, 0 ), + "SinglePhasePoromechanics": ( 2, 3 ), + "SinglePhasePoromechanicsConformingFractures": ( 2, 3 ), + "SinglePhasePoromechanicsConformingFracturesALM": ( 2, 3 ), + "SinglePhaseWell": ( 2, 0 ), + "SolidMechanicsEmbeddedFractures": ( 0, 3 ), + "SolidMechanicsAugmentedLagrangianContact": ( 0, 3 ), + "SolidMechanicsLagrangeContact": ( 0, 3 ), + "SolidMechanicsLagrangeContactBubbleStab": ( 0, 3 ), + "SolidMechanicsLagrangianFEM": ( 0, 3 ) +} + + +# helpers +def _what_solver( bcontent: dict ) -> tuple[ int, int ]: + from xml.etree.ElementTree import Element, fromstring + sim_xml: Element = fromstring( bcontent[ 'content' ] ) + solver = sim_xml.find( 'Solvers' ) + nunk: list[ tuple[ int, int ] ] = [ solvers_to_unknowns.get( elt.tag, ( 1, 0 ) ) + for elt in solver ] if solver else [ ( 0, 0 ) ] + return max( nunk ) + + +def _how_many_cells( bcontent: dict ) -> tuple[ int, int ]: + import vtk + name = bcontent[ 'name' ] + if name.endswith( ".vtp" ): + reader = vtk.vtkXMLPolyDataReader() + elif name.endswith( ".vtu" ): + reader = vtk.vtkXMLUnstructuredGridReader() + elif name.endswith( ".vtm" ): + reader = vtk.vtkXMLMultiBlockDataReader() + else: + raise ValueError( "Unsupported kind (use 'vtp', 'vtu', or 'vtm')." ) + + reader.SetReadFromInputString( 1 ) + reader.SetInputString( bcontent[ 'content' ] ) + reader.Update() + output = reader.GetOutput() + return ( output.GetNumberOfCells(), output.GetNumberOfPoints() ) + + +def _has_internalMesh( bcontent: dict ) -> bool: + from xml.etree.ElementTree import Element, fromstring + sim_xml: Element = fromstring( bcontent[ 'content' ] ) + return bool( sim_xml.find( 'Mesh/InternalMesh' ) is not None ) + + +def _what_internalMesh( bcontent: dict ) -> tuple[ int, int ]: + from xml.etree.ElementTree import Element, fromstring + import re + sim_xml: Element = fromstring( bcontent[ 'content' ] ) + + mesh = sim_xml.find( 'Mesh/InternalMesh' ) + + def _parse_sum( value: str | None ) -> int: + if value is None: + return 0 + return sum( int( el ) for el in re.findall( r'-?\d+(?:\.\d+)?', value ) ) + + if mesh is None: + nx = ny = nz = 0 + else: + nx = _parse_sum( mesh.get( 'nx' ) ) + ny = _parse_sum( mesh.get( 'ny' ) ) + nz = _parse_sum( mesh.get( 'nz' ) ) + + return ( nx * ny * nz, ( nx + 1 ) * ( ny + 1 ) * ( nz + 1 ) ) + + +#TODO a class from it +def define_simulation_view( server: Server ) -> None: + """Functional definition of UI elements.""" + + @server.state.change( "other_widget_selected_file" ) + def on_other_widget_file_ready( other_widget_selected_file: dict, **_: Any ) -> None: + if not other_widget_selected_file: + return + + current = list( server.state.simulation_xml_filename ) + existing_names = { f.get( "name" ) for f in current } + + if other_widget_selected_file.get( "name" ) not in existing_names: + current.append( other_widget_selected_file ) + server.state.simulation_xml_filename = current + + @server.state.change( "selected_cluster_name" ) + def on_cluster_change( selected_cluster_name: str, **_: Any ) -> None: + print( f"selecting {selected_cluster_name}" ) + cluster = Authentificator.get_cluster( selected_cluster_name ) + if cluster is None: + print( f"Error: Cluster '{selected_cluster_name}' not found in configuration." ) + return + + server.state.decompositions = SuggestDecomposition( cluster, server.state.nunknowns ).get_sd() + + server.state.simulation_remote_path = cluster.simulation_remote_path + + server.state.simulation_dl_path = cluster.simulation_dl_default_path + + # @server.state.change( "decomposition" ) + # def on_decomposition_selected( decomposition: str, **_: Any ) -> None: + # = SuggestDecomposition( Authentificator.get_cluster( server.state.selected_cluster_name ), server.state.nunknowns ).get_sd() + # # if server.state.decomposition: + # except: + # server.state.sd = { 'nodes': 0, 'total_ranks': 0 } + + @server.state.change( "simulation_xml_temp" ) + def on_temp_change( simulation_xml_temp: list, **_: Any ) -> None: + current_list = server.state.simulation_xml_filename + new_list = current_list + simulation_xml_temp + + server.state.simulation_xml_filename = new_list + server.state.simulation_xml_temp = [] + + @server.state.change( "nunknowns" ) + def on_nunknowns_change( nunknowns: int, **_: Any ) -> None: + #re-gen list + if len( server.state.decompositions ) > 0: + server.state.decompositions = SuggestDecomposition( + Authentificator.get_cluster( server.state.selected_cluster_name ), nunknowns ).get_sd() + print( f'unknowns changed : {server.state.nunknowns} -> {nunknowns}' ) + server.state.nunknowns = nunknowns + + @server.state.change( "simulation_xml_filename" ) + def on_simfiles_change( simulation_xml_filename: list, **_: Any ) -> None: + import re + has_xml = [ file.get( "type", "" ) == 'text/xml' for file in simulation_xml_filename ] + + has_external_mesh = [ + bool( file.get( "name", "" ).endswith( ( ".vtu", ".vtm", ".vtp" ) ) ) for file in simulation_xml_filename + ] + + has_internal_mesh = False + for i, _ in enumerate( has_xml ): + if has_xml[ i ]: + has_internal_mesh = _has_internalMesh( simulation_xml_filename[ i ] ) + + if any( has_xml ): + uc = up = nc = np = 0 + # compute unknowns and cells only for xml files, if external mesh do not take into account internal mesh info even if present, if no external mesh try to take into account internal mesh info if present + # useful for decomposition suggestion + for i, _ in enumerate( has_xml ): + if has_external_mesh[ i ]: + nc, np = _how_many_cells( simulation_xml_filename[ i ] ) + elif has_xml[ i ]: + uc, up = _what_solver( simulation_xml_filename[ i ] ) + if has_internal_mesh: + nc, np = _what_internalMesh( simulation_xml_filename[ i ] ) + + if all( i is not None for i in ( uc, nc, up, np ) ): + server.state.nunknowns = uc * nc + up * np + + if any( has_xml ): + xml_pattern = re.compile( r"\.xml$", re.IGNORECASE ) + mesh_pattern = re.compile( r"\.(vtu|vtm|pvtu|pvtm)$", re.IGNORECASE ) + table_pattern = re.compile( r"\.(txt|dat|csv|geos)$", re.IGNORECASE ) + + xml_matches, mesh_matches, table_matches = [], [], [] + + pattern_file = r"[\w\-.]+\.(?:vtu|pvtu|dat|txt|xml|geos)\b" + + # Fix: use enumerate instead of .index() to handle duplicates safely + for i, file in enumerate( simulation_xml_filename ): + if not has_xml[ i ]: + continue + name = file.get( "name", "" ) + if xml_pattern.search( name ): + xml_matches.append( file ) + elif mesh_pattern.search( name ): + mesh_matches.append( file ) + elif table_pattern.search( name ): + table_matches.append( file ) + + if xml_matches: + already_have = { file.get( "name", "" ) for file in simulation_xml_filename } + required = set( re.findall( pattern_file, xml_matches[ 0 ][ 'content' ].decode( "utf-8" ) ) ) + required -= already_have + # Fix: store as list of dicts so the UI can use {{ file.name }} + server.state.simulation_xml_required = [ { "name": f } for f in sorted( required ) ] + else: + server.state.simulation_xml_required = [] + + server.state.is_valid_jobfiles = any( has_xml ) + server.state.all_req_files = any( has_xml ) and len( server.state.simulation_xml_required ) == 0 + + def kill_job( index_to_remove: int ) -> None: + # for now just check there is an xml + jid = list( server.state.job_ids ) + if 0 <= index_to_remove < len( jid ): + removed_id = jid[ index_to_remove ][ 'job_id' ] + Authentificator.kill_job( removed_id ) + del jid[ index_to_remove ] + + server.state.job_ids = jid + print( f"Job {removed_id} kill. Still running: {len(jid)}" ) + else: + print( f"Error: supress index does not exist ({index_to_remove})." ) + + def run_remove_jobfile( index_to_remove: int ) -> None: + current_files = list( server.state.simulation_xml_filename ) + if 0 <= index_to_remove < len( current_files ): + del current_files[ index_to_remove ] + + server.state.simulation_xml_filename = current_files + print( f"File at {index_to_remove} deleted. New files: {len(current_files)}" ) + else: + print( f"Erreur: Wrong deletion index ({index_to_remove})." ) + + with vuetify.VContainer(): + with vuetify.VRow(): + with vuetify.VCol( cols=4 ): + vuetify.VTextField( v_model=( + "login", + None, + ), + label="Login", + dense=True, + hide_details=True, + clearable=True, + prepend_icon="mdi-login" ) + with vuetify.VCol( cols=4 ): + vuetify.VTextField( v_model=( + "password", + None, + ), + label="Password", + type="password", + dense=True, + hide_details=True, + clearable=True, + prepend_icon="mdi-onepassword" ) + + # + server.state.access_granted = False + server.state.is_valid_jobfiles = False + server.state.simulation_xml_filename = [] + server.state.simulation_xml_required = [] + server.state.selected_cluster_names = [ cluster.name for cluster in Authentificator.sim_constants ] + # server.state.decompositions = [] + + # --------------------------- auth block -----------------------# + vuetify.VDivider( vertical=True, thickness=5, classes="mx-4" ) + with vuetify.VCol( cols=1 ): + vuetify.VSelect( label="Cluster", + items=( "selected_cluster_names", ), + v_model=( "selected_cluster_name", 'p4' ) ) + vuetify.VDivider( vertical=True, thickness=5, classes="mx-4" ) + with vuetify.VCol( cols=1 ): + vuetify.VSelect( label="Decomposition", + items=( "decompositions", [] ), + v_model=( "decomposition", None ), + item_title="label", + item_value="id", + return_object=True ) + + with vuetify.VRow(): + with vuetify.VCol( cols=8 ): + vuetify.VTextField( v_model=( + "key_path", + "/users/$USER/.ssh/id_trame", + ), + label="Path to ssh key", + dense=True, + hide_details=True, + clearable=True, + prepend_icon="mdi-key-chain-variant" ) + + # + vuetify.VDivider( vertical=True, thickness=5, classes="mx-4" ) + with vuetify.VCol( cols=1 ): + vuetify.VBtn( "Log in", click="trigger('run_try_login')", + disabled=( "access_granted", ) ) # type: ignore + # + vuetify.VDivider( vertical=True, thickness=5, classes="mx-4" ) + with vuetify.VCol( cols=1 ): + vuetify.VTextField( + v_model=( "slurm_comment", None ), + label="Comment to slurm", + dense=True, + hide_details=True, + clearable=True, + ) # type: ignore + + # --------------------------- simulation block -----------------------# + vuetify.VDivider( thickness=5, classes="my-4" ) + + with vuetify.VRow(): + with vuetify.VCol( cols=4 ): + vuetify.VFileUpload( + v_model=( "simulation_xml_temp", [] ), + title="Simulation file name", + density='comfortable', + hide_details=True, + # clearable=True, + multiple=True, + filter_by_type='.xml,.vtu,.vtm,.pvtu,.pvtm,.dat,.csv,.txt,.geos,.vtk', + # readonly=True, + disabled=( "!access_granted", ) ) + with vuetify.VCol( cols=4 ), vuetify.VList(): + with vuetify.VListItem( v_for=( "(file,i) in simulation_xml_filename" ), + key="i", + value="file", + prepend_icon="mdi-minus-circle-outline", + click=( run_remove_jobfile, "[i]" ) ): + vuetify.VListItemTitle( "{{ file.name }}" ) + vuetify.VListItemSubtitle( "{{ file.size ? (file.size / 1024).toFixed(1) + ' KB' : 'URL' }}" ) + vuetify.VDivider( thickness=2, classes="my-2" ) + + with vuetify.VListItem( + v_for=( "(file,i) in simulation_xml_required" ), + key="i", + value="file", + classes="bg-red-lighten-4 text-red-darken-4", + # base_color="red-lighten-4", + # style="background-color: rgb(var(--v-theme-error-lighten-4));", + prepend_icon="mdi-alert-circle-outline" ): + vuetify.VListItemTitle( "{{ file.name }} (required)" ) + + with vuetify.VRow(), vuetify.VCol(): + vuetify.VTextField( v_model=( "simulation_remote_path", None ), + label="Path where to write files and launch code", + prepend_icon="mdi-upload", + dense=True, + hide_details=True, + clearable=True, + disabled=( "!access_granted", ) + # TODO callback validation of path + ) + + with vuetify.VRow(), vuetify.VCol(): + vuetify.VTextField( v_model=( "simulation_dl_path", None ), + label="Simulation download path", + dense=True, + clearable=True, + prepend_icon="mdi-download", + disabled=( "!access_granted", ) + # TODO callback validation of path + ) + + with vuetify.VRow(): + with vuetify.VCol( cols=4 ): + vuetify.VTextField( v_model=( "simulation_job_name", "geosJob" ), + label="Job Name", + dense=True, + hide_details=True, + clearable=True, + disabled=( "!access_granted", ) ) + + vuetify.VSpacer() + with vuetify.VCol( cols=1 ): + vuetify.VBtn( "Run", + click="trigger('run_simulation')", + disabled=( "!is_valid_jobfiles || !all_req_files", ), + classes="ml-auto" ), # type: ignore + + # ------------------------------- Status block ----------------------------- # + vuetify.VDivider( thickness=5, classes="my-4" ) + + with vuetify.VRow(): + vuetify.VSpacer() + with vuetify.VCol( cols=1 ): + vuetify.VBtn( "Kill All", click="trigger('kill_all_simulations')" ), # type: ignore + + color_expression = "status_colors[job_ids[i].status] || '#607D8B'" + with vuetify.VRow(), vuetify.VCol( cols=4 ), vuetify.VList(): + with vuetify.VListItem( v_for=( "(jobs,i) in job_ids" ), + key="i", + value="jobs", + base_color=( color_expression, ), + prepend_icon="mdi-minus-circle-outline", + click=( kill_job, "[i]" ) ): + vuetify.VListItemTitle( "{{ jobs.status }} -- {{ jobs.name }} -- {{ jobs.job_id }}" ) + vuetify.VProgressLinear( v_model=( "jobs.simprogress", "0" ), ) + vuetify.VProgressLinear( v_model=( "jobs.slprogress", "0" ), ) + + with vuetify.VRow( v_if="simulation_error" ): + html.Div( "An error occurred while running simulation :
{{simulation_error}}", style="color:red;" ) diff --git a/geos-trame/src/geos/trame/app/ui/viewer/boxViewer.py b/geos-trame/src/geos/trame/app/ui/viewer/boxViewer.py index e51f5035..4b5310e1 100644 --- a/geos-trame/src/geos/trame/app/ui/viewer/boxViewer.py +++ b/geos-trame/src/geos/trame/app/ui/viewer/boxViewer.py @@ -4,6 +4,7 @@ import pyvista as pv from geos.trame.schema_generated.schema_mod import Box +from typing import Any import re @@ -102,7 +103,7 @@ def _compute_intersected_cell( self ) -> None: if len( saved_ids ) > 0: self._extracted_cells = self._mesh.extract_cells( saved_ids ) - def _check_cell_inside_box( self, cell: pv.Cell, box_bounds: list[ float ] ) -> bool: + def _check_cell_inside_box( self, cell: pv.Cell, box_bounds: Any ) -> bool: """Check if the cell is inside the box bounds. A cell is considered inside the box if his bounds are completely diff --git a/geos-trame/src/geos/trame/app/ui/viewer/viewer.py b/geos-trame/src/geos/trame/app/ui/viewer/viewer.py index 4ea3c705..46ceddb3 100644 --- a/geos-trame/src/geos/trame/app/ui/viewer/viewer.py +++ b/geos-trame/src/geos/trame/app/ui/viewer/viewer.py @@ -401,8 +401,8 @@ def _update_box( self, active_block: Box, show_obj: bool ) -> None: return if self.box_engine is not None and active_block.name in self.box_engine: - box_polydata_actor: pv.Actor = self.box_engine[ active_block.name ].get_box_polydata_actor() - extracted_cell_actor: pv.Actor = self.box_engine[ active_block.name ].get_extracted_cells_actor() + box_polydata_actor: pv.BasePlotter = self.box_engine[ active_block.name ].get_box_polydata_actor() + extracted_cell_actor: pv.BasePlotter = self.box_engine[ active_block.name ].get_extracted_cells_actor() self.plotter.remove_actor( box_polydata_actor ) self.plotter.remove_actor( extracted_cell_actor ) del self.box_engine[ active_block.name ] diff --git a/geos-trame/src/geos/trame/app/utils/async_file_watcher.py b/geos-trame/src/geos/trame/app/utils/async_file_watcher.py new file mode 100644 index 00000000..f8960e58 --- /dev/null +++ b/geos-trame/src/geos/trame/app/utils/async_file_watcher.py @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. +# SPDX-FileContributor: Jacques Franc + +import asyncio +from asyncio import CancelledError, ensure_future +from typing import Callable + +from trame_server.utils import asynchronous + + +class AsyncPeriodicRunner: + """While started, runs given callback at given period.""" + + def __init__( self, callback: Callable, period_ms: int = 100 ) -> None: + """Init the async watcher object.""" + self.last_m_time = None + self.callback = callback + self.period_ms = period_ms + self.task = None + self.start() + + def __del__( self ) -> None: + """Clean up async watch on destruction.""" + self.stop() + + def set_period_ms( self, period_ms: int ) -> None: + """Set the async watch period. + + :params:period_ms period in ms + """ + self.period_ms = period_ms + + def start( self ) -> None: + """Stop existing async watch and start a new stream.""" + self.stop() + self.task = asynchronous.create_task( self._runner() ) + + def stop( self ) -> None: + """Stop the async watch.""" + if not self.task: + return + + ensure_future( self._wait_for_cancel() ) # type:ignore[unreachable] + + async def _wait_for_cancel( self ) -> None: + """Cancel and await cancel error for the task. + + If cancel is done outside async, it may raise warnings as cancelled exception may be triggered outside async + loop. + """ + if not self.task or self.task.done() or self.task.cancelled(): # type:ignore[unreachable] + self.task = None + return + + try: # type:ignore[unreachable] + self.task.cancel() + await self.task + except CancelledError: + self.task = None + + async def _runner( self ) -> None: + while True: + self.callback() + await asyncio.sleep( self.period_ms / 1000.0 ) diff --git a/geos-trame/src/geos/trame/assets/cluster.json b/geos-trame/src/geos/trame/assets/cluster.json new file mode 100644 index 00000000..221dd11d --- /dev/null +++ b/geos-trame/src/geos/trame/assets/cluster.json @@ -0,0 +1,68 @@ +[ + { + "name": "p4", + "host": "p4log01", + "partition": "p4_general", + "partition_transfert": "p4_transfer", + "port": 22, + "geos_path": "/workrd/users/$USER/GEOS/build-spack-generated-debug/bin/geosx", + "geos_module": "/workrd/users/$USER/modulesRHEL88", + "geos_load_list": [ + "geos-daily-rhel88" + ], + "remote_home_base": "/users/$USER", + "simulation_default_filename": "geosDeck.xml", + "simulation_remote_path": "/workrd/users/$USER/Example", + "simulation_dl_default_path": "/users/$USER/Example", + "simulation_information_default_path": "/users/$USER/.trame-logs", + "n_nodes": 212, + "cores_per_node": 192, + "mem_per_node": 747 + }, + { + "name": "pine", + "host": "pine-1", + "partition": "pine", + "partition_transfert": "pine", + "port": 22, + "geos_path": "/shared/data1/Users/$USER/codes/GEOS-2025-11-03/build-pine-1.pine.cluster-linux-rocky9-zen4-gcc@11.4.1-release/bin/geosx", + "geos_module": "/apps/modules/modulefiles3", + "geos_load_list": [ + "genesis", + "common", + "proxy", + "slurm", + "gcc/11.4.1", + "openmpi-gcc/5.0.5", + "cmake/3.27.9" + ], + "remote_home_base": "/home/$USER", + "simulation_default_filename": "geosDeck.xml", + "simulation_remote_path": "/shared/data1/Users/$USER/Example", + "simulation_dl_default_path": "/shared/data1/Users/$USER/Example", + "simulation_information_default_path": "/home/$USER/.trame-logs", + "n_nodes": 48, + "cores_per_node": 64, + "mem_per_node": 768 + }, + { + "name": "local", + "host": "127.0.0.1", + "partition": "debug", + "partition_transfert": "debug", + "port": 22, + "geos_path": "/opt/GEOS/build-spack-generated-debug/bin/geosx", + "geos_module": "/workrd/users/$USER/geos-generated", + "geos_load_list": [ + "geos-toolchains" + ], + "remote_home_base": "/home/$USER", + "simulation_default_filename": "geosDeck.xml", + "simulation_remote_path": "/work/", + "simulation_dl_default_path": "/data/", + "simulation_information_default_path": "/home/.trame-logs", + "n_nodes": 1, + "cores_per_node": 8, + "mem_per_node": 32 + } +] \ No newline at end of file diff --git a/install_packages.sh b/install_packages.sh index 3ded0635..3f9a454a 100755 --- a/install_packages.sh +++ b/install_packages.sh @@ -11,8 +11,10 @@ python -m pip install --upgrade ./mesh-doctor python -m pip install --upgrade ./pygeos-tools python -m pip install --upgrade ./geos-pv #! trame install requires npm -# cd ./geos-trame/vue-components -# npm i -# npm run build -# cd ../../ -# python -m pip install ./geos-trame \ No newline at end of file +cd ./geos-trame/vue-components +npm i +npm run build +cd .. +sh configure.sh +cd .. +python -m pip install ./geos-trame From 44bc69a2c4534fc173090ac82be125ea4b2a2d2b Mon Sep 17 00:00:00 2001 From: Jacques Franc <49998870+jafranc@users.noreply.github.com> Date: Thu, 28 May 2026 17:11:34 +0200 Subject: [PATCH 04/10] feat: Adding optionable converter MD->SG (#253) * PR gen from script by copilot * scrap vtk full import * using writing and reading logic * adding some tests * adding component splitter * fix test w/ cc * yapf * copilot review --- .../geos/mesh_doctor/actions/convertMD2SG.py | 438 ++++++++++++++++++ .../src/geos/mesh_doctor/parsing/__init__.py | 1 + .../parsing/convertMD2SGParsing.py | 76 +++ mesh-doctor/src/geos/mesh_doctor/register.py | 2 +- mesh-doctor/tests/data/base_hexa_shift_2.vtu | Bin 0 -> 736501 bytes mesh-doctor/tests/data/base_tetra_shift.vtm | 7 + .../domain_fracture_2_ids.vtu | 55 +++ .../data/base_tetra_shift/domain_ids.vtu | 44 ++ mesh-doctor/tests/test_convertMD2SG.py | 65 +++ 9 files changed, 687 insertions(+), 1 deletion(-) create mode 100644 mesh-doctor/src/geos/mesh_doctor/actions/convertMD2SG.py create mode 100644 mesh-doctor/src/geos/mesh_doctor/parsing/convertMD2SGParsing.py create mode 100644 mesh-doctor/tests/data/base_hexa_shift_2.vtu create mode 100644 mesh-doctor/tests/data/base_tetra_shift.vtm create mode 100644 mesh-doctor/tests/data/base_tetra_shift/domain_fracture_2_ids.vtu create mode 100644 mesh-doctor/tests/data/base_tetra_shift/domain_ids.vtu create mode 100644 mesh-doctor/tests/test_convertMD2SG.py diff --git a/mesh-doctor/src/geos/mesh_doctor/actions/convertMD2SG.py b/mesh-doctor/src/geos/mesh_doctor/actions/convertMD2SG.py new file mode 100644 index 00000000..0e90fe10 --- /dev/null +++ b/mesh-doctor/src/geos/mesh_doctor/actions/convertMD2SG.py @@ -0,0 +1,438 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. +# SPDX-FileContributor: GitHub Copilot, Jacques Franc +from dataclasses import dataclass +from typing import Optional, Union + +from vtkmodules.vtkCommonDataModel import VTK_TRIANGLE, VTK_TRIANGLE_STRIP, VTK_QUAD, VTK_POLYGON, vtkPolyData, vtkKdTree, vtkCell +from vtkmodules.vtkCommonCore import vtkIdTypeArray, vtkPoints, reference, vtkUnsignedIntArray, vtkDataArray, vtkIdList +from vtkmodules.vtkCommonDataModel import vtkSelection, vtkSelectionNode, vtkUnstructuredGrid, vtkMultiBlockDataSet +from vtkmodules.vtkFiltersCore import vtkAppendPolyData, vtkCleanPolyData +from vtkmodules.vtkFiltersExtraction import vtkExtractSelection +from vtkmodules.vtkFiltersGeometry import vtkGeometryFilter + +from geos.mesh_doctor.parsing.cliParsing import setupLogger +from geos.mesh.io.vtkIO import readMesh, VtkOutput, writeMesh + + +@dataclass( frozen=True ) +class Options: + meshVtkOutput: VtkOutput + attrs: tuple[ int, ...] = () + skipCleanCollocated: bool = False + skipFilterVolumeCells: bool = False + + +@dataclass( frozen=True ) +class Result: + outputMesh: Optional[ vtkUnstructuredGrid ] + bounds: tuple[ float, float, float, float, float, float ] + numPoints: int + numCells: int + attrs: tuple[ int, ...] + skipCleanCollocated: bool + nCleanCollocated: int + skipFilterVolumeCells: bool + nFilterVolumeCells: int + nColors: int + + +TOLERANCE = 1e-6 + + +def is_surface_cell_type( t: int ) -> bool: + """Checks if the given VTK cell type is a surface cell type (2D).""" + surface_types = { + VTK_TRIANGLE, + VTK_QUAD, + VTK_POLYGON, + VTK_TRIANGLE_STRIP, + } + return t in surface_types + + +def __process_block( block: Union[ vtkMultiBlockDataSet, vtkUnstructuredGrid, vtkPolyData ], + append_filter: vtkAppendPolyData, attrs: list[ int ] ) -> None: + """Recursively processes a block of the multi-block dataset, extracting surface cells that match the given attributes and adding them to the append filter.""" + if isinstance( block, vtkMultiBlockDataSet ): + for i in range( block.GetNumberOfBlocks() ): + child: Union[ vtkMultiBlockDataSet, vtkUnstructuredGrid, + vtkPolyData ] = block.GetBlock( i ) # type: ignore[assignment] + if child is not None: + __process_block( child, append_filter, attrs ) + return + + if not hasattr( block, "GetNumberOfCells" ): + return + if block.GetNumberOfCells() == 0: + return + + cell_types = set() + for i in range( block.GetNumberOfCells() ): + cell_types.add( block.GetCellType( i ) ) + + if all( is_surface_cell_type( ct ) for ct in cell_types ): + cell_attributes = block.GetCellData().GetArray( "attribute" ) + if len( attrs ) == 0 or ( cell_attributes is not None and cell_attributes.GetTuple1( 0 ) in attrs ): + if isinstance( block, vtkPolyData ): + append_filter.AddInputData( block ) + else: + gf = vtkGeometryFilter() + gf.SetInputData( block ) + gf.Update() + append_filter.AddInputData( gf.GetOutput() ) + + +def __extract_first_vol( block: Union[ vtkMultiBlockDataSet, vtkUnstructuredGrid ] ) -> Optional[ vtkUnstructuredGrid ]: + """Recursively searches for the first volumetric block in the multi-block dataset.""" + if isinstance( block, vtkMultiBlockDataSet ): + for i in range( block.GetNumberOfBlocks() ): + child: Union[ vtkMultiBlockDataSet, vtkUnstructuredGrid ] = block.GetBlock( i ) # type: ignore[assignment] + if child is not None: + found = __extract_first_vol( child ) + if found is not None: + return found + return None + + if not hasattr( block, "GetNumberOfCells" ): + return None + if block.GetNumberOfCells() == 0: + return None + + is_vol = False + for i in range( block.GetNumberOfCells() ): + cell_type = block.GetCellType( i ) + is_vol = not is_surface_cell_type( cell_type ) + if is_vol: + break + return block if is_vol else None + + +def _filterVolumeCells( mesh: vtkUnstructuredGrid, + attrs: list[ int ] ) -> tuple[ vtkUnstructuredGrid, vtkUnstructuredGrid, int ]: + """Filters out volume cells from the input mesh, keeping only surface cells that match the given attributes. Returns the filtered volume mesh, the extracted surface mesh, and the number of cells removed.""" + volumeIds = vtkIdTypeArray() + surfaceIds = vtkIdTypeArray() + nVolume = nSurface = nOther = 0 + + cell_attributes = mesh.GetCellData().GetArray( "attribute" ) + assert cell_attributes is not None, "Input mesh must have a 'attribute' cell data array." + for i in range( mesh.GetNumberOfCells() ): + dim = mesh.GetCell( i ).GetCellDimension() + if dim == 3: + volumeIds.InsertNextValue( i ) + nVolume += 1 + elif dim == 2: + if cell_attributes.GetTuple1( i ) in attrs or len( attrs ) == 0: + surfaceIds.InsertNextValue( i ) + nSurface += 1 + else: + nOther += 1 + + if cell_attributes is not None: + setupLogger.info( + f"Mesh contains {nVolume} volume cells, {nSurface} surface cells matching attributes {attrs}, and {nOther} other cells." + ) + else: + setupLogger.info( + f"Mesh contains {nVolume} volume cells, {nSurface} surface cells, and {nOther} other cells (no 'attribute' array for filtering)." + ) + + if nSurface == 0 and nOther == 0: + setupLogger.info( "No filtering needed (all cells are 3D)" ) + return mesh, mesh.NewInstance(), nSurface + nOther + + sn = vtkSelectionNode() + sn.SetFieldType( vtkSelectionNode.CELL ) + sn.SetContentType( vtkSelectionNode.INDICES ) + sn.SetSelectionList( volumeIds ) + Esn = vtkSelectionNode() + Esn.SetFieldType( vtkSelectionNode.CELL ) + Esn.SetContentType( vtkSelectionNode.INDICES ) + Esn.SetSelectionList( surfaceIds ) + + sel = vtkSelection() + sel.AddNode( sn ) + Esel = vtkSelection() + Esel.AddNode( Esn ) + + ext = vtkExtractSelection() + ext.SetInputData( 0, mesh ) + ext.SetInputData( 1, sel ) + ext.Update() + Eext = vtkExtractSelection() + Eext.SetInputData( 0, mesh ) + Eext.SetInputData( 1, Esel ) + Eext.Update() + + setupLogger.info( f"Filtered → {nVolume} cells (removed {nSurface + nOther})" ) + + if nVolume > 0: + if nSurface > 0: + return ext.GetOutput(), Eext.GetOutput(), nSurface + nOther + return ext.GetOutput(), mesh.NewInstance(), nSurface + nOther + + return mesh.NewInstance(), mesh.NewInstance(), nSurface + nOther + + +def __clean_collocated( main: vtkUnstructuredGrid ) -> tuple[ vtkUnstructuredGrid, int ]: + """Cleans collocated points in the input mesh, returning a new mesh with unique points and updated cell connectivity, as well as the number of points cleaned.""" + clean_point_set: dict[ tuple[ float, float, float ], int ] = {} + reverse_map: dict[ int, int ] = {} + + for pid in range( main.GetNumberOfPoints() ): + pt = main.GetPoints().GetPoint( pid ) + reverse_map[ pid ] = clean_point_set.get( pt, pid ) + clean_point_set.setdefault( pt, pid ) + + old_to_new: dict[ int, int ] = {} + clean_points = vtkPoints() + for pt, ids in clean_point_set.items(): + old_to_new[ ids ] = clean_points.InsertNextPoint( pt ) + + rewrite_mesh = vtkUnstructuredGrid() + rewrite_mesh.SetPoints( clean_points ) + + for cell_id in range( main.GetNumberOfCells() ): + cell: vtkCell = main.GetCell( cell_id ) + new_ids: list[ int ] = [] + for i in range( cell.GetNumberOfPoints() ): + pid = cell.GetPointId( i ) + new_ids.append( old_to_new.get( reverse_map.get( pid, pid ), pid ) ) + rewrite_mesh.InsertNextCell( cell.GetCellType(), len( new_ids ), new_ids ) + + rewrite_mesh.GetCellData().ShallowCopy( main.GetCellData() ) + + for array_i in range( main.GetPointData().GetNumberOfArrays() ): + arr = main.GetPointData().GetArray( array_i ) + new_arr = vtkDataArray.CreateDataArray( arr.GetDataType() ) + new_arr.SetName( arr.GetName() ) + new_arr.SetNumberOfComponents( arr.GetNumberOfComponents() ) + new_arr.SetNumberOfTuples( clean_points.GetNumberOfPoints() ) + for old_id, new_id in old_to_new.items(): + new_arr.SetTuple( new_id, arr.GetTuple( old_id ) ) + rewrite_mesh.GetPointData().AddArray( new_arr ) + + nCleanCollocated = main.GetNumberOfPoints() - rewrite_mesh.GetNumberOfPoints() + return rewrite_mesh, nCleanCollocated + + +def __paintNodes( + main: vtkUnstructuredGrid, + frac_polys: list[ vtkUnstructuredGrid ] ) -> tuple[ vtkUnstructuredGrid, list[ vtkUnstructuredGrid ] ]: + """Paints the nodes of the main mesh that are close to the fracture polygons, returning the modified main mesh and the list of fracture polygons.""" + kd = vtkKdTree() + kd.BuildLocatorFromPoints( main ) + + narray = vtkUnsignedIntArray() + narray.SetNumberOfComponents( 1 ) + narray.SetNumberOfTuples( main.GetNumberOfPoints() ) + + for i in range( main.GetNumberOfPoints() ): + narray.SetTuple1( i, 0 ) + + count = 0 + setupLogger.info( f"Number of fracpolys: {len(frac_polys)}" ) + for poly in frac_polys: + setupLogger.info( + f"Processing fracpoly with {poly.GetNumberOfPoints()} points and {poly.GetNumberOfCells()} cells." ) + for i in range( poly.GetNumberOfPoints() ): + dist = reference( 0.0 ) + id_source = kd.FindClosestPoint( poly.GetPoint( i ), dist ) # type: ignore[call-overload] + if dist > TOLERANCE: # type: ignore[operator] + setupLogger.warning( + f"[too far point] main point ({id_source}) is too far from frac point ({i}) = ({dist} > {TOLERANCE})" + ) + narray.SetTuple1( id_source, 1 ) + count += 1 + + setupLogger.info( f"Painted {count}/{narray.GetNumberOfTuples()} nodes based on proximity to fracture polygons." ) + narray.SetName( "faultNodes" ) + main.GetPointData().AddArray( narray ) + return main, frac_polys + + +#TODO refactor with other coloring function to avoid code duplication +def __coloringNodes( main: vtkUnstructuredGrid ) -> tuple[ vtkUnstructuredGrid, int ]: + """Colors the nodes of the main mesh based on their point-connectivity, one array per connected component of faultNodes==1 points. Returns the modified mesh and the number of connected components found.""" + fault_array = main.GetPointData().GetArray( "faultNodes" ) + n_pts = main.GetNumberOfPoints() + + # Collect only the fault-node ids up front + fault_pids = { pid for pid in range( n_pts ) if fault_array.GetTuple1( pid ) == 1 } + setupLogger.info( f"Found {len(fault_pids)} fault nodes to color based on connectivity." ) + + visited: set[ int ] = set() + color = 0 + + for seed in fault_pids: + if seed in visited: + continue + + # One fresh, zero-filled array per connected component + color_array = vtkUnsignedIntArray() + color_array.SetNumberOfComponents( 1 ) + color_array.SetNumberOfTuples( n_pts ) + color_array.Fill( 0 ) + + # Iterative DFS — avoids Python recursion-depth limit + stack = [ seed ] + count = 0 + while stack: + pid = stack.pop() + if pid in visited: + continue + visited.add( pid ) + color_array.SetTuple1( pid, 1 ) # mark this point as belonging to component + count += 1 + + cells = vtkIdList() + main.GetPointCells( pid, cells ) + for ci in range( cells.GetNumberOfIds() ): + cell = main.GetCell( cells.GetId( ci ) ) + for vi in range( cell.GetNumberOfPoints() ): + nbr = cell.GetPointId( vi ) + if nbr not in visited and nbr in fault_pids: + stack.append( nbr ) + + color_array.SetName( f"faultNodes_{color}" ) + setupLogger.info( f"Connected component {color}: {count} points" ) + + main.GetPointData().AddArray( color_array ) + color += 1 + + return main, color + + +def polydata_to_ugrid( poly: vtkUnstructuredGrid ) -> vtkUnstructuredGrid: + """Converts a vtkPolyData to a vtkUnstructuredGrid by copying points, cells, and data.""" + ugrid = vtkUnstructuredGrid() + ugrid.SetPoints( poly.GetPoints() ) + for cid in range( poly.GetNumberOfCells() ): + cell = poly.GetCell( cid ) + ugrid.InsertNextCell( cell.GetCellType(), cell.GetPointIds() ) + ugrid.GetPointData().ShallowCopy( poly.GetPointData() ) + ugrid.GetCellData().ShallowCopy( poly.GetCellData() ) + return ugrid + + +def meshDoctor_to_surfaceGen( hierachical_mesh: vtkMultiBlockDataSet, attrs: tuple[ int, ...], + skip_clean_collocated: bool ) -> tuple[ vtkUnstructuredGrid, int, int ]: + """Converts a mesh-doctor multi-block dataset to a surface mesh compatible with SurfaceGen by extracting surface cells that match the given attributes, optionally cleaning collocated points, and returning the resulting unstructured grid along with the number of points cleaned. + + Args: + hierachical_mesh: The input multi-block dataset containing the mesh. + attrs: A tuple of attribute values to filter surface cells. If empty, all surface cells are included. + skip_clean_collocated: If True, skips the step of cleaning collocated points. If False, collocated points will be cleaned and the number of points cleaned will be returned. + + Returns: + A tuple containing the converted surface mesh as a vtkUnstructuredGrid and the number of points cleaned from collocated points (if skip_clean_collocated is False) or 0 (if skip + """ + append_filter = vtkAppendPolyData() + __process_block( hierachical_mesh, append_filter, list( attrs ) ) + + main = __extract_first_vol( hierachical_mesh ) + if main is None: + raise ValueError( "No volumetric block found in the multi-block mesh." ) + + nCleanCollocated, nColors = 0, 0 + if not skip_clean_collocated: + main, nCleanCollocated = __clean_collocated( main ) + + append_filter.Update() + clean = vtkCleanPolyData() + clean.SetInputConnection( append_filter.GetOutputPort() ) + clean.Update() + + painted_main, _ = __paintNodes( main, [ clean.GetOutput() ] ) + colored_main, nColors = __coloringNodes( painted_main ) + return polydata_to_ugrid( colored_main ), nCleanCollocated, nColors + + +def toSurfaceGen( hierachical_mesh: vtkUnstructuredGrid, attrs: tuple[ int, ...], skip_clean_collocated: bool, + skip_filter_volume_cells: bool ) -> tuple[ vtkUnstructuredGrid, int, int, int ]: + """Converts a single unstructured grid mesh to a surface mesh compatible with SurfaceGen by optionally filtering out volume cells, extracting surface cells that match the given attributes, optionally cleaning collocated points, and returning the resulting unstructured grid along with the number of points cleaned and cells filtered. + + Args: + hierachical_mesh: The input unstructured grid mesh. + attrs: A tuple of attribute values to filter surface cells. If empty, all surface cells are included. + skip_clean_collocated: If True, skips the step of cleaning collocated points. If False, collocated points will be cleaned and the number of points cleaned will be returned. + skip_filter_volume_cells: If True, skips the step of filtering out volume cells and extracting surface cells. If False, volume cells will be filtered out and surface cells matching the attributes will be extracted, and the number of cells filtered will be returned. + + Returns: + A tuple containing the converted surface mesh as a vtkUnstructuredGrid, the number of points cleaned from collocated points (if skip_clean_collocated is False) or 0 (if skip clean_collocated is True), and the number of cells filtered out as volume cells (if skip_filter_volume_cells is False) or 0 (if skip_filter_volume_cells is True). + """ + nCleanCollocated, nFilteredVolumeCells, nColors = 0, 0, 0 + if skip_filter_volume_cells: + main = hierachical_mesh + surfaces: list[ vtkUnstructuredGrid ] = [] + else: + main, surfs, nFilteredVolumeCells = _filterVolumeCells( hierachical_mesh, list( attrs ) ) + surfaces = [ surfs ] + + if not skip_clean_collocated: + main, nCleanCollocated = __clean_collocated( main ) + + painted_main, _ = __paintNodes( main, surfaces ) + setupLogger.info( f"Has Array faultNodes: {painted_main.GetPointData().HasArray('faultNodes')}" ) + setupLogger.info( + f"Range of faultNodes: {painted_main.GetPointData().GetArray('faultNodes').GetRange() if painted_main.GetPointData().HasArray('faultNodes') else 'N/A'}" + ) + colored_main, nColors = __coloringNodes( painted_main ) + return polydata_to_ugrid( colored_main ), nCleanCollocated, nFilteredVolumeCells, nColors + + +def meshAction( mesh: Union[ vtkMultiBlockDataSet, vtkUnstructuredGrid ], options: Options ) -> Result: + """Performs the conversion of the input mesh to a surface mesh compatible with SurfaceGen using the specified options, and returns the result containing the output file path, bounds, number of points and cells, and details about the cleaning and filtering steps. + + Args: + mesh: The input mesh to be converted, which can be either a vtkMultiBlockDataSet or a vtkUnstructuredGrid. + options: The options for the conversion, including attributes to filter, whether to skip cleaning collocated points, and whether to skip filtering volume cells. + + Returns: + A Result object containing the output file path, bounds, number of points and cells in the converted mesh, the attributes used for filtering, whether cleaning collocated points was skipped, whether filtering volume cells was skipped, and the number of points cleaned and cells filtered if those steps were performed. + + """ + if isinstance( mesh, vtkMultiBlockDataSet ): + converted, nCleanCollocated, nColors = meshDoctor_to_surfaceGen( mesh, options.attrs, + options.skipCleanCollocated ) + nFilteredVolumeCells = 0 + elif isinstance( mesh, vtkUnstructuredGrid ): + converted, nCleanCollocated, nFilteredVolumeCells, nColors = toSurfaceGen( mesh, options.attrs, + options.skipCleanCollocated, + options.skipFilterVolumeCells ) + else: + raise TypeError( f"Unsupported mesh type {type( mesh )}." ) + + return Result( outputMesh=converted, + bounds=converted.GetBounds(), + numPoints=converted.GetNumberOfPoints(), + numCells=converted.GetNumberOfCells(), + attrs=options.attrs, + skipCleanCollocated=options.skipCleanCollocated, + skipFilterVolumeCells=options.skipFilterVolumeCells, + nCleanCollocated=nCleanCollocated, + nFilterVolumeCells=nFilteredVolumeCells, + nColors=nColors ) + + +def action( vtuInputFile: str, options: Options ) -> Result: + """Reads a mesh from the input file, converts it to a surface mesh compatible with SurfaceGen using the specified options, and returns the result containing the output file path, bounds, number of points and cells, and details about the cleaning and filtering steps. + + Args: + vtuInputFile: The path to the input VTU file containing the mesh to be converted. + options: The options for the conversion, including attributes to filter, whether to skip cleaning collocated points, and whether to skip filtering volume cells. + + Returns: + A Result object containing the output file path, bounds, number of points and cells in the converted mesh, the attributes used for filtering, whether cleaning collocated points was skipped, whether filtering volume cells was skipped, and the number of points cleaned and cells filtered if those steps were performed. + """ + if vtuInputFile is None: + raise ValueError( "An input file must be provided." ) + + mesh = readMesh( vtuInputFile ) + result = meshAction( mesh, options ) + + setupLogger.info( f"Writing converted mesh to {options.meshVtkOutput.output}" ) + writeMesh( result.outputMesh, options.meshVtkOutput ) + + return result diff --git a/mesh-doctor/src/geos/mesh_doctor/parsing/__init__.py b/mesh-doctor/src/geos/mesh_doctor/parsing/__init__.py index ecdb80d9..f25f20ec 100644 --- a/mesh-doctor/src/geos/mesh_doctor/parsing/__init__.py +++ b/mesh-doctor/src/geos/mesh_doctor/parsing/__init__.py @@ -19,6 +19,7 @@ ORPHAN_2D = "orphan2d" CHECK_INTERNAL_TAGS = "checkInternalTags" EULER = "euler" +CONVERT_MD2SG = "convertMD2SG" @dataclass( frozen=True ) diff --git a/mesh-doctor/src/geos/mesh_doctor/parsing/convertMD2SGParsing.py b/mesh-doctor/src/geos/mesh_doctor/parsing/convertMD2SGParsing.py new file mode 100644 index 00000000..06447e7a --- /dev/null +++ b/mesh-doctor/src/geos/mesh_doctor/parsing/convertMD2SGParsing.py @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. +# SPDX-FileContributor: GitHub Copilot, Jacques Franc +from __future__ import annotations +from argparse import _SubParsersAction +from typing import Any + +from geos.mesh_doctor.actions.convertMD2SG import Options, Result +from geos.mesh_doctor.parsing import CONVERT_MD2SG +from geos.mesh_doctor.parsing._sharedChecksParsingLogic import getOptionsUsedMessage +from geos.mesh_doctor.parsing.cliParsing import setupLogger, addVtuInputFileArgument +from geos.mesh.io.vtkIO import VtkOutput + +__ATTRS = "attrs" +__OUTPUT_FILE = "outputFile" +__SKIP_CLEAN = "skipCleanCollocated" +__SKIP_FILTER = "skipFilterVolumeCells" + + +def convert( parsedOptions: dict[ str, Any ] ) -> Options: + """Convert parsed command-line options to Options object. + + Args: + parsedOptions: Dictionary of parsed command-line options. + + Returns: + Options: Converted options object. + """ + return Options( attrs=tuple( parsedOptions.get( __ATTRS, [] ) ), + skipCleanCollocated=parsedOptions.get( __SKIP_CLEAN, False ), + skipFilterVolumeCells=parsedOptions.get( __SKIP_FILTER, False ), + meshVtkOutput=VtkOutput( output=parsedOptions.get( __OUTPUT_FILE ), isDataModeBinary=True ) ) + + +def fillSubparser( subparsers: _SubParsersAction[ Any ] ) -> None: + """Fill the argument parser for the convertMD2SG action. + + Args: + subparsers: Subparsers from the main argument parser. + """ + p = subparsers.add_parser( CONVERT_MD2SG, + help="Convert a mesh-doctor dataset to a SurfaceGen-compatible VTU file." ) + addVtuInputFileArgument( p ) + p.add_argument( '-z', + '--' + __ATTRS, + type=int, + nargs='+', + default=[], + help="[int ...]: Attributes to include when filtering surface cells." ) + p.add_argument( '--' + __OUTPUT_FILE, + type=str, + default="converted.vtu", + help="[string]: Optional output VTU file path." ) + p.add_argument( '--' + __SKIP_CLEAN, action='store_true', help="Skip the collocated node cleanup step." ) + p.add_argument( '--' + __SKIP_FILTER, + action='store_true', + help="Skip the surface/volume extraction step when input is a single VTU file." ) + + +def displayResults( options: Options, result: Result ) -> None: + """Display the results of the convertMD2SG action. + + Args: + options: The options used for the conversion. + result: The results of the conversion. + """ + setupLogger.results( getOptionsUsedMessage( options ) ) + setupLogger.results( "Converted mesh saved to: {0}".format( options.meshVtkOutput.output ) ) + setupLogger.results( f" Points: {result.numPoints:,}" ) + setupLogger.results( f" Cells: {result.numCells:,}" ) + setupLogger.results( f" Bounds: {result.bounds}" ) + setupLogger.results( + f" Skip clean collocated(npoints cleaned): {result.skipCleanCollocated} ({result.nCleanCollocated})" ) + setupLogger.results( + f" Skip filter volume cells(ncells removed): {result.skipFilterVolumeCells} ({result.nFilterVolumeCells})" ) + setupLogger.results( f" Number of connected components for faultNodes: {result.nColors}" ) diff --git a/mesh-doctor/src/geos/mesh_doctor/register.py b/mesh-doctor/src/geos/mesh_doctor/register.py index 99675376..41d96a60 100644 --- a/mesh-doctor/src/geos/mesh_doctor/register.py +++ b/mesh-doctor/src/geos/mesh_doctor/register.py @@ -59,7 +59,7 @@ def registerParsingActions( parsing.FIX_ELEMENTS_ORDERINGS, parsing.GENERATE_CUBE, parsing.GENERATE_FRACTURES, parsing.GENERATE_GLOBAL_IDS, parsing.MAIN_CHECKS, parsing.NON_CONFORMAL, parsing.SELF_INTERSECTING_ELEMENTS, parsing.SUPPORTED_ELEMENTS, parsing.ORPHAN_2D, - parsing.CHECK_INTERNAL_TAGS, parsing.EULER ): + parsing.CHECK_INTERNAL_TAGS, parsing.EULER, parsing.CONVERT_MD2SG ): __HELPERS[ actionName ] = actionName __ACTIONS[ actionName ] = actionName diff --git a/mesh-doctor/tests/data/base_hexa_shift_2.vtu b/mesh-doctor/tests/data/base_hexa_shift_2.vtu new file mode 100644 index 0000000000000000000000000000000000000000..8b1febf6722508349cf12993c0241dfcd9693f19 GIT binary patch literal 736501 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
1f1N*k~qE`KrisCh7- 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 OxBsq>e(N`W?f(ZckpqYT literal 0 HcmV?d00001 diff --git a/mesh-doctor/tests/data/base_tetra_shift.vtm b/mesh-doctor/tests/data/base_tetra_shift.vtm new file mode 100644 index 00000000..72cfda3f --- /dev/null +++ b/mesh-doctor/tests/data/base_tetra_shift.vtm @@ -0,0 +1,7 @@ + + + + + + + diff --git a/mesh-doctor/tests/data/base_tetra_shift/domain_fracture_2_ids.vtu b/mesh-doctor/tests/data/base_tetra_shift/domain_fracture_2_ids.vtu new file mode 100644 index 00000000..bd71da8e --- /dev/null +++ b/mesh-doctor/tests/data/base_tetra_shift/domain_fracture_2_ids.vtu @@ -0,0 +1,55 @@ + + + + + + + AQAAAACAAABwEgAAMAMAAA==eJxd1Vd0CFYAh/GEBInYM0GqgpAYsXdpFVWqtLQ1g9iJPWMGbemw2mprFNUqNUqncU4nnUaH0dqxZ8QeidFz5MvLd1/+5/e93nvO7RwU8PA84HSRu8rd5O5yDzle7in3knvLCXIfua/cT+4vD5AHyoPkRDlJHiwPkYfKw+Th8gh5pDxKHi2PkcfK4+Rkebw8QZ4oT5Iny1PkFHmqPE2eLr8svyK/Ks+QZ8qvya/Lb8hvyrPk2fIcea48T35Lflt+R54vvyu/J78vL5AXyovkxfIH8hJ5qbxM/lBeLn8kfyyvkD+RV8qr5E/l1fIaea28Tv5MXi9vkD+Xv5C/lL+Sv5a/kTfKm+TN8hb5W/lwSJa/ox/B3+Mf2KP0VPZH+jH8Ez6Ot+ITeBs+iX/Gp/Av+DT+Ff/GnqGfZX+nn8N/4PN4O76Ad+CLeCdOw7vwJfwn/otNp19m/6Zfwf/gq3g3vob34Ot4L76B9+Gb+F/8H3uLfpvdT7+DD+AMfBBn4kP4Lj6M7+Ej+D4+ilOz3ws9IDRrjtED8XGcA5/AOfFJHIRP4WB8GufCZ/BZNjc9D3uOHoLP41B8AefFF3EYTsP58CWcH6fjy2wBekH2Cr0QvooL42u4CL6Oi+IbuBi+iYvjW/g2W4Jekr1DD8cZOAJn4lL4Li6N7+Ey+D6OxA9wQHDWPEIvywbSH8U5cDmcE0fhIFweB+MKOBeuiHPjPGw0vRIbQq+MQ3EMzotjcRiugvPhqjg/roYL4IJsdXocW4heAxfGNXERXAsXxbVxMVwHF8d1cQlckq1Hr8+G0xvgCNwQl8KNcGncGJfBTXBk9j2z2f9DOTlKLi9XkCvK0XIlubIcI8fKVeSqcjW5uhwn15BryrXk2nIdua5cT64vN5Abyo3kxnIT+TG5qdxMflx+Qm4uPym3kFvKreSn5Nby03Ibua38jNxOflZuL3eQn5OflzvKneQX5Bfll+TOche5q9xN7i73kOPlnnIvubecIPeR+8r95P7yAHmgPEhOlJPkwfIQeag8TB4uj5BHyqPk0fIYeaw8Tk6Wx8sT5InyJHmyPEVOkafK0+Tp8v+bFOsf + + + 1113.0004492 + + + 2930.1435118 + + + + + AQAAAACAAAA4CQAA/AEAAA==eJw11dViEAQAQFFiwMZGrmDEyAGC0g0iIAKSEtLSKN0tJaGoSEu3dHdIl9IonUp3t+QDx/tyPuHGivW+2IzDuAxgPMZnAgYyiAkZzBAmYmImYVImY3KGMozhjGAkUzAlo5iKqZmGaRnNdEzPDMzITMzMGGZhVmbjB8zOHPyQHzEnczE38zAv8zE/C7AgC7Ewi7Aoi7E4P2YJfsKSLMXS/JRl+BnLshzL83NWYEVWYmVWYVV+wWqszhqsyS9Zi7VZh3VZj/XZgF+xIRuxMZuwKZuxOVvwa37DlmzF1mzDtmzH9uzAjuzEzuzCruzG7uzBnuzF3vyWfdiX/difA/gdB3IQB3MIv+cPHMof+RN/5jD+wuEcwZEcxdEcw7H8leM4nhM4kZM4mVM4ldM4nTM4k7P4G2dzDudyHudzARdyERdzCZdyGZdzBVdyFVdzDddyHddzA3/nRm7iZm7hVm7jdu7gTu7ibv7BP7mHe7mP+3mAB3mIh/kX/+YRHuUxHucJnuQpnuYZnuU5nuc//JcXeJGXeJlXeJXXeJ03eJO3eJt3eJf3eJ8P+JCP+JhP+JTP+Jwv+B9f8hVf8w3f8v/xx2YcxmUA4zE+EzCQQUzIYIYwERMzCZMyGZMzlGEMZwQjmYIpGcVUTM00TMtopmN6ZmBGZmJmxvAdK1+CjQ== + + + + + AQAAAACAAAAwDAAAHwAAAA==eJztxaENAAAMArCF/4+ewHFDa5qr2LZt2/b8qo4DDQ== + + + AQAAAACAAAAwDAAAiQIAAA==eJw11dViEAQAQFEYMWB05+jO0bkRG6O7YXR3jhjdHUoqjQFKd2OQJiihdCihNCqNPHC4L+cTbqxY74rNAMZhXMZjfAYyARMyEYOYmEmYlMmYnCmYkqmYmmmYlumYnhmYkZmYmVkYzKzMxuzMwZzMxdzMw7zMx/wswIIsxMIswqIsxhAWZwmWZCmWZhmWZTmWZwVWZCWGMoyVWYVVWY3hjGB1RrIGa7IWa7MO67Ie67MBG7IRG7MJm7IZm7MFW7IVW7MNo9iW7dieHdiRndiZXdiV3didPdiTvdibfdiX/difAziQgziYQxjNoRzG4RzBGI7kKI7mGI7lOI7nBE7kJE7mFE7lNE7nDM7kLM7mHM7lPH7ADzmfC7iQi7iYS/gRP+ZSLuNyruBKruJqruEn/JSf8XOu5Tp+wS+5nhu4kZu4mVu4ldu4nTu4k7u4m3u4l/u4nwd4kIf4Fb/mN/yWh3mER3mMx3mC3/F7/sAf+RN/5kme4i/8lad5hmd5jr/xd57nBV7kJV7mFV7lNV7nDf7BP3mTt3ibd/gX/+Zd3uN9PuBDPuJjPuE//Jf/8Smf8Tlf8CVf8TXf8H++H39sBjAO4zIe4zOQCZiQiRjExEzCpEzG5EzBlEzF1EzDtEzH9MzAjMzEzMzCYGZlNmZnDuZkLuZmHuZlPuZnARZkIRZmERZlMYawOEuwJEuxNMuwLMuxPCuwIisxlGGszCqsymoMZwSrM5I1WJO1WJt1WJf1WJ8N2JCN2JhN2JTN2Jwt2JKt2JptGMW2bMf27MCO7MTO7MKu7Mbu7MGe7MXe7MO+7Mf+HMCBHMTBHMJoDuUwDucIxnAkR3E0x3Asx3E8J3AiJ/Eti52i1g== + + + + + AQAAAACAAACoGwAA2AMAAA==eJx1lj1MFVEQRq2pscUWa22VUlusqbXVFlupsaCBwgaaryExmiiJISIYxABRQZ8oKD+KKIgV1ro7vpiZj7PNhsPL3rtzzyZnYry5NDDR3scHbvdOX9kZHvv393/+uG/kcPDxPePx+ynj+e/6nGnjR4PNf+7D8x8a7+lM3rzU8wjWnTF+fmj02Un/E9jPrPGpv0/vTD6Ffc4Zv9Be87D/BePzJ/1/d/Qc3mvR+LV2oy/gfZeM7ww3C7+EOSwbv9W87s0VmM+q8TPt9Qrm5vxqu6HXME/nzS6HRt/AnNeMt2PrOI/5rxs/17xW31s4F+c3rjfXOzivjvFm1d5p53GO743/bpY9cR73DeOX24U/wLk7b1935CP4sGl8Zbm5nIcnW8bPti/8Cfxx3i479Bm82oa5OQ/fnMc8nYeHOzBn5+Gn85j/LnjrPJZ1Hj7vwXk5D92cxzl+Af+dx/k6j+/iK5y78/henIcP+/AdOQ9PnMf39Q38cR7fnfPw6gC8ch5eOQ+vnIdX38Er5+GV8/Dqh/G7rVfOwyvn4dUheOU8vHIeXh2BV87DK+fh1U/wynl45Ty8OgavnIdXzsOrX+CV8/Cqcv2bwx3gtaMEHSXoKL6f3lGCjhJ0lKCjuvfaUYKOEnSUoKMEHSXoKEFHCTpK0FGCjurea0cJOkrQUYKOEnSUoKMEHSXoKEFHCTpK0FGCjhJ0lKCjBB0l6ChBRwk6StBRgo7q3mtHCTpK0FGCjhJ0lKCjBB0l6ChBRwk6StBRgo4SdJSgowQd1b07P72jBB0l6ChBRwk6StBRgo4SdJSgowQdJegoQUcJOkrQUYKOEnSUoKMEHSXoKEFHCTpK0FGCjhJ0VPfu/PSOEnSUoKMEHSXoKEFHCTpK0FGCjhJ0lKCjBB0l6ChBRwk6StBRgo4SdJSsoy62831gHZX5mPHaUfn3U8brPvJzpo3XjsrPf2i8dlRed8Z47ai8n1njtaPyPueM147K+18wXjsqv9ei8dpR+X2XjNeOynNYNl47Ks9n1XjtqDw357Wj8jyd147Kc14zXjsqz3/deO2ofC7Oa0fl8+oYrx2Vz/G98dpR+Xw3jNeOyufuvHZU9mHTeO2o7MmW8dpR2R/ntaOyV9swN+e1o/I8ndeOynN2Xjsqz38XvHVeOyr7vAfn5bx2VD7HL8ZrR+XzdV47Kp+789pR2Yd947WjsifOa0dlf5zXjspeHYBXzmtHZa+c147KXjmvHZW9+mG8dlT2ynl4dQheOa8dlb06Aq+c147KXv0Er5zXjspeHYNXzmtHZa+8i7od9Qfhzwss + + + 0.059371710435 + + + 0.99252204006 + + + + + + + AQAAAACAAACQJAAAAgcAAA==eJxd2VXc3nUdh/F10bAmtrERdhEiIJMUE2UJSzdim4MhYJBTEAUlxQBRZzIEkxIMhh2YlEo4MUhbAQPhgM/7YJ+dXK/t/73ug//vup+9vr9n6YCn/wwKB4ZHhkPCweER9XfeUeHQ8o4Oh9XzZeHwer48HFHPV4Qj6/kbw1H1fGW4UT0/Jty4nh8bblLPV4Wb1vPvhEvCN4TfC72npeH3wyPr+Q/Co+r5D8Oj6/mPwmX1/JZweT3/cbiinr8tHBeODX8Seq+8n4Yr6/nPwmPq+c/DY+v5L8JV9fzW8Lh6fm94Snhy+L/w0vCS0Hno2B+fu1noPJfUnHN8U7h5ec7T5/OPD7cozzn7nvBPCLcsz/n39+3EcKvydOH7xn9zOLo8vfge8t8SjilPR76f/LeGuuHpy/eWf1I4PtSdvnyf+c55Qnm68z3n62NieXr0/eefGm5dnk79XOCfFm5Tnn79vOCfHm5bnq79HOGvDrcrT7d65b89nFSebvXKf0c4uTzd6pV/RjilPN3qlX9muH15utUr/53h1PJ0q1f+WeG08nSrV/67wh3K061e+e8OdyzPz0md888OdypP5/rmnxPuXJ7O9c1/T/iM8nSub/57w2eWp3N9888Nn1WezvXNPy98dnk61zf//PA55a0O9c2/IHxueTrXN//C8Hnl6Vzf/IvC55en88nlvy98QXk61zf/4vCF5elc3/z3hy8qT+f65n8g3KU8neub/8Fw1/J0rm/+h8LdytO5vvn+v929PJ3rm+//6ReXp3N98z8c7lGezvXNvyx8SXk61zf/I+Ge5elc3/yPhnuVp3N98z8W7l2ezvXNXxO+tDyd65v/8XCf8nSub/4nwunl6Vzf/E+GLytP5/rmfyrctzyd65v/6XC/8nSub/5nwv3L07m++ZeHB5Snc33z14YHlqdzffOvCA8qT+f65n82fHl5Otc3/8rw4PJ0rm/+VeErytO5vvl63rPmPhe+sj5Pzzrmfz58VXlrQh3zvxC+ujw965j/xfA15elZx/wvha8tT8/Ty/9yeEh5etYx/+rwdeXpWcf8a8LXl6dnHfOvDQ8tT8865l8XzihPzzrmXx/OLE/POubr9qCa+0o4qz5Pt3rl3xDOLk+3euXfGM4pT5+65H81nFuePnXJ/1p4WHn61CX/6+Hh5elTl/xvhPPK06cu+TeF88vTpy7568IF5elTl/ybw4Xl6VOX/G+Gi8rTpy753woXl6dPXfJ1OKPmdDWz5vQzq+Z0Mrvm9DCn5pz73JpzvofVnHM8vOac17yaWxfOrznvf0HNec8La877XFRz3w4X19x3Q/cL7iVuC+11x9W8OfdZt4f2Op57LZ/PvyO01/Hcd7m/4N8Z2ut47sHcX/B/GdrreO7H3F/wfxXa63juzdxf8H8d2ut47tPcX/DvCu11PPds7i/4d4f2Op57NvcX/HtCex3P/Zv7C/5vQnua/c69nPsL/vrQnsZzX+f+gv/b0J7Gc4/n/oJ/X7i6PPd77i/4vwvtaTzd6pX/+9CextOtXvl/CO1pPN3qlf/H0J7G061e+feH9jSebvXKfyC0p/F0q1f+g6E9jadbvfIfCu1pPN3qlf9waE/j6Vav/EdCexpPt3rl/ym0p/Hc6+qc/+fQnsbTub75fwntabz1ob75ej6t5v4a2t98np51zP9baH/j6Xl1+X8P7W88PeuY/4/Q/sbTs475/wztbzw965j/r9D+xtOzjvmPhvY3np51zH8stL/x9Kxj/uOh/Y2nZx3z/x3a33h61jH/P6H9jadnHfP/G9rfeHrWMf+J0D5mj9Ozjvn/D+1jPD3rmP9kaE/j6VavfL+gsKfxdKtX/sDM29N4utUrf1Dm1wzY0NOtXvmDM29P4+lWr/whmben8XSrV/7QzNvTeLrVK39Y5u1pPN3qlT888/Y0nm71yh+ReXsaT7d65Y/MvD2Np1u98kdl3p7G061e+Rtl3v7G83s0nfM3zrz9jadzffM3ybz9jadzffP1fFnNbZrPsdf5PD3rmL9Z/t1exxtY/fM3D+11vEHVP3+L0F7HG1z987cM7XW8IdU/f6vQXscbWv3zR4f2Ot6w6p8/JrTX8YZX//yxob2ON6L6548L7XU8PeuYPz607/H0rGO+btfW3ITQfujzdKtX/sTQ3sjTrV75W4f2SZ4+dcnfJrRn8vSpS/62of2Tp09d8rcL7aU8feqSPym0r/L0qUv+5NAey9OnLvlTQvstT5+65G8frhuwoadPXfKnhvZhnj51yZ8W2pN5+tQlf4fQ/szTpy75O4b2b54O9cfX2/U1pys9mdOPbszpRB/m9KADc87deZtzvs7VnHN0fuacl3OaUueybsCGc96/9z613rP3O63ep/do7infwyxp + + + AQAAAACAAAAwDAAAlwIAAA==eJwtxVlgCAQAAFDmmixX5Mo95FjkWLRF7vuKMEeGyNUc0WTO3OfGWDnKrZWQ3EOpue8ULbSaVkpuUpPiY+/9vGxZMuV0bgc5nwu6sIu6hEu5rINdyVUc4hqu5VDXc7gbuJGbuoVbu507urO7urt7OdL9PMCDPNTDPNKjPcYxnuDJnuoZnu15jnO8E7zEy73Cq73Oid7gTd7ibd7pJO/zfif7kI/6hE/7rM85xRed6jSn+4qv+rpv+a7vO8MP/cgBWTPP4UDncV4XcCEXcXGXdBmXd0VXdjVXd03XcV2Hub4buombu5XbuoM7uYsj3NO93df9PdBDHOURHuVoj/V4T/IUT/csz3WsF3qx3/cyf+hVXuuP/Ik3+jNv9Q7v9l5/6a990Ed83Kf8jb/z977gH/2zf/Fv/sPXfNN3/Jf/8b/+31kDMs/uXH7CTzq/n/LTLuZnXNrlXMHPuqqf8/Ou7Rf8ol/yy27sZm7pNm7vV/yqu7mHX3Mfv+43PNhverjf8tt+x+M80e96mmd6jud7gRf5PS/1B17pNV7vj/2pN/tzb/cu7/EX/soHfNjHfNJn/K3P+wdf8k++7F/9u//0Dd/2Pf/tB/7PWbLJOZ3bQc7ngi7soi7hUi7rYFdyFYe4hms51PUc7gZu5KZu4dZu547u7K7u7l6OdD8P8CAP9TCP9GiPcYwneLKneoZne57jHO8EL/Fyr/Bqr3OiN3iTt3ibdzrJ+7zfyT7koz7h0z7rc07xRac6zem+4qu+7lu+6/vO8EM/ckD2zHM40Hmc1wVcyEVc3CVdxuVd0ZVdzdVd03Vc12Gu74Zu4uZu5bbu4E7u4gj3dG/3dX8P9BBHeYRHOdpjPd6TPMXTPctzHeuFfgyLILtF + + + AQAAAACAAACGAQAADQAAAA==eJxjZx8FAw8AJtEKqw== + + + + + diff --git a/mesh-doctor/tests/data/base_tetra_shift/domain_ids.vtu b/mesh-doctor/tests/data/base_tetra_shift/domain_ids.vtu new file mode 100644 index 00000000..958a15a5 --- /dev/null +++ b/mesh-doctor/tests/data/base_tetra_shift/domain_ids.vtu @@ -0,0 +1,44 @@ + + + + + + + AQAAAACAAADwUQAAnA8AAA==eJw13MMWGIqSAMAX27Zt+8a2bdu2bdu2bdu2bXsWU+lNfUKf5v/+9/8RgAEZiIEZhEEZjMEZgiEZiqEZhmEZjuEZgREZiZEZhVEZjdEZgzEZi7EZh3EZj/GZgAmZiImZhEmZjMmZgimZiqmZhmmZjumZgRmZiZmZhVmZjdmZgzmZi7mZh/8xL/MxPwuwIAuxMIuwKIuxOEuwJEuxNMuwLMuxPCuwIiuxMquwKquxOmuwJmuxNuuwLuuxPhuwIRuxMZuwKZuxOVuwJVuxNduwLduxPTuwIzuxM7uwK7uxO3uwJ3uxN/uwL/uxPwdwIAdxMIdwKIdxOEdwJEdxNMdwLMdxPCdwIidxMqdwKqdxOmdwJmdxNudwLudxPhdwIRdxMZdwKZdxOVdwJVdxNddwLddxPTdwIzdxM7dwK7dxO3dwJ3dxN/dwL/dxPw/wIA/xMI/wKI/xOE/wJE/xNM/wLM/xPC/wIi/xMq/wKq/xOm/wJm/xNu/wLu/xPh/wIR/xMZ/wKZ/xOV/wJV/xNd/wLd/xPT/wIz/xM7/wK7/xO3/wJ3/xN//wL/8l/gAMyEAMzCAMymAMzhAMyVAMzTAMy3AMzwiMyEiMzCiMymiMzhiMyViMzTiMy3iMzwRMyERMzCRMymRMzhRMyVRMzTRMy3RMzwzMyEzMzCzMymzMzhzMyVzMzTz8j3mZj/lZgAVZiIVZhEVZjMVZgiVZiqVZhmVZjuVZgRVZiZVZhVVZjdVZgzVZi7VZh3VZj/XZgA3ZiI3ZhE3ZjM3Zgi3Ziq3Zhm3Zju3ZgR3ZiZ3ZhV3Zjd3Zgz3Zi73Zh33Zj/05gAM5iIM5hEM5jMM5giM5iqM5hmM5juM5gRM5iZM5hVM5jdM5gzM5i7M5h3M5j/O5gAu5iIu5hEu5jMu5giu5iqu5hmu5juu5gRu5iZu5hVu5jdu5gzu5i7u5h3u5j/t5gAd5iId5hEd5jMd5gid5iqd5hmd5jud5gRd5iZd5hVd5jdd5gzd5i7d5h3d5j/f5gA/5iI/5hE/5jM/5gi/5iq/5hm/5ju/5gR/5iZ/5hV/5jd/5gz/5i7/5h3/5r+APwIAMxMAMwqAMxuAMwZAMxdAMw7AMx/CMwIiMxMiMwqiMxuiMwZiMxdiMw7iMx/hMwIRMxMRMwqRMxuRMwZRMxdRMw7RMx/TMwIzMxMzMwqzMxuzMwZzMxdzMw/+Yl/mYnwVYkIVYmEVYlMVYnCVYkqVYmmVYluVYnhVYkZVYmVVYldVYnTVYk7VYm3VYl/VYnw3YkI3YmE3YlM3YnC3Ykq3Ymm3Ylu3Ynh3YkZ3YmV3Yld3YnT3Yk73Ym33Yl/3YnwM4kIM4mEM4lMM4nCM4kqM4mmM4luM4nhM4kZM4mVM4ldM4nTM4k7M4m3M4l/M4nwu4kIu4mEu4lMu4nCu4kqu4mmu4luu4nhu4kZu4mVu4ldu4nTu4k7u4m3u4l/u4nwd4kId4mEd4lMd4nCd4kqd4mmd4lud4nhd4kZd4mVd4ldd4nTd4k7d4m3d4l/d4nw/4kI/4mE/4lM/4nC/4kq/4mm/4lu/4nh/4kZ/4mV/4ld/4nT/4k7/4m3/4l/8a/QEYkIEYmEEYlMEYnCEYkqEYmmEYluEYnhEYkZEYmVEYldEYnTEYk7EYm3EYl/EYnwmYkImYmEmYlMmYnCmYkqmYmmmYlumYnhmYkZmYmVmYldmYnTmYk7mYm3n4H/MyH/OzAAuyEAuzCIuyGIuzBEuyFEuzDMuyHMuzAiuyEiuzCquyGquzBmuyFmuzDuuyHuuzARuyERuzCZuyGZuzBVuyFVuzDduyHduzAzuyEzuzC7uyG7uzB3uyF3uzD/uyH/tzAAdyEAdzCIdyGIdzBEdyFEdzDMdyHMdzAidyEidzCqdyGqdzBmdyFmdzDudyHudzARdyERdzCZdyGZdzBVdyFVdzDddyHddzAzdyEzdzC7dyG7dzB3dyF3dzD/dyH/fzAA/yEA/zCI/yGI/zBE/yFE/zDM/yHM/zAi/yEi/zCq/yGq/zBm/yFm/zDu/yHu/zAR/yER/zCZ/yGZ/zBV/yFV/zDd/yHd/zAz/yEz/zC7/yG7/zB3/yF3/zD//y34A/AAMyEAMzCIMyGIMzBEMyFEMzDMMyHMMzAiMyEiMzCqMyGqMzBmMyFmMzDuMyHuMzARMyERMzCZMyGZMzBVMyFVMzDdMyHdMzAzMyEzMzC7MyG7MzB3MyF3MzD/9jXuZjfhZgQRZiYRZhURZjcZZgSZZiaZZhWZZjeVZgRVZiZVZhVVZjddZgTdZibdZhXdZjfTZgQzZiYzZhUzZjc7ZgS7Zia7ZhW7Zje3ZgR3ZiZ3ZhV3Zjd/ZgT/Zib/ZhX/Zjfw7gQA7iYA7hUA7jcI7gSI7iaI7hWI7jeE7gRE7iZE7hVE7jdM7gTM7ibM7hXM7jfC7gQi7iYi7hUi7jcq7gSq7iaq7hWq7jem7gRm7iZm7hVm7jdu7gTu7ibu7hXu7jfh7gQR7iYR7hUR7jcZ7gSZ7iaZ7hWZ7jeV7gRV7iZV7hVV7jdd7gTd7ibd7hXd7jfT7gQz7iYz7hUz7jc77gS77ia77hW77je37gR37iZ37hV37jd/7gT/7ib/7hX/5b7AvAgAzEwAzCoAzG4AzBkAzF0AzDsAzH8IzAiIzEyIzCqIzG6IzBmIzF2IzDuIzH+EzAhEzExEzCpEzG5EzBlEzF1EzDtEzH9MzAjMzEzMzCrMzG7MzBnMzF3MzD/5iX+ZifBViQhViYRViUxVicJViSpViaZViW5VieFViRlViZVViV1VidNViTtVibdViX9VifDdiQjdiYTdiUzdicLdiSrdiabdiW7dieHdiRndiZXdiV3didPdiTvdibfdiX/difAziQgziYQziUwzicIziSoziaYziW4zieEziRkziZUziV0zidMziTszibcziX8zifC7iQi7iYS7iUy7icK7iSq7iaa7iW67ieG7iRm7iZW7iV27idO7iTu7ibe7iX+7ifB3iQh3iYR3iUx3icJ3iSp3iaZ3iW53ieF3iRl3iZV3iV13idN3iTt3ibd3iX93ifD/iQj/iYT/iUz/icL/iSr/iab/iW7/ieH/iRn/iZX/iV3/idP/iTv/ibf/iX/xb6AzAgAzEwgzAogzE4QzAkQzE0wzAswzE8IzAiIzEyozAqozE6YzAmYzE24zAu4zE+EzAhEzExkzApkzE5UzAlUzE10zAt0zE9MzAjMzEzszArszE7czAnczE38/A/5mU+5mcBFmQhFmYRFmUxFmcJlmQplmYZlmU5lmcFVmQlVmYVVmU1VmcN1mQt1mYd1mU91mcDNmQjNmYTNmUzNmcLtmQrtmYbtmU7tmcHdmQndmYXdmU3dmcP9mQv9mYf9mU/9ucADuQgDuYQDuUwDucIjuQojuYYjuU4jucETuQkTuYUTuU0TucMzuQszuYczuU8zucCLuQiLuYSLuUyLucKruQqruYaruU6rucGbuQmbuYWbuU2bucO7uQu7uYe7uU+7ucBHuQhHuYRHuUxHucJnuQpnuYZnuU5nucFXuQlXuYVXuU1XucN3uQt3uYd3uU93ucDPuQjPuYTPuUzPucLvuQrvuYbvuU7vucHfuQnfuYXfuU3fucP/uQv/uYf/uW/Q74ADMhADMwgDMpgDM4QDMlQDM0wDMtwDM8IjMhIjMwojMpojM4YjMlYjM04jMt4jM8ETMhETMwkTMpkTM4UTMlUTM00TMt0TM8MzMhMzMwszMpszM4czMlczM08/I95mY/5WYAFWYiFWYRFWYzFWYIlWYqlWYZlWY7lWYEVWYmVWYVVWY3VWYM1WYu1WYd1WY/12YAN2YiN2YRN2YzN2YIt2Yqt2YZt2Y7t2YEd2Ymd2YVd2Y3d2YM92Yu92Yd92Y/9OYADOYiDOYRDOYzDOYIjOYqjOYZjOY7jOYETOYmTOYVTOY3TOYMzOYuzOYdzOY/zuYALuYiLuYRLuYzLuYIruYqruYZruY7ruYEbuYmbuYVbuY3buYM7uYu7uYd7uY/7eYAHeYiHeYRHeYzHeYIneYqneYZneY7neYEXeYmXeYVXeY3XeYM3eYu3eYd3eY/3+YAP+YiP+YRP+YzP+YIv+Yqv+YZv+Y7v+YEf+Ymf+YVf+Y3f+YM/+Yu/+Yd/+e+APwADMhADMwiDMhiDMwRDMhRDMwzDMhzDMwIjMhIjMwqjMhqjMwZjMhZjMw7jMh7jMwETMhETMwmTMhmTMwVTMhVTMw3TMh3TMwMzMhMzMwuzMhuzMwdzMhdzMw//Y17mY34WYEEWYmEWYVEWY3GWYEmWYmmWYVmWY3lWYEVWYmVWYVVWY3XWYE3WYm3WYV3WY302YEM2YmM2YVM2Y3O2YEu2Ymu2YVu2Y3t2YEd2Ymd2YVd2Y3f2YE/2Ym/2YV/2Y38O4EAO4mAO4VAO43CO4EiO4miO4ViO43hO4ERO4mRO4VRO43TO4EzO4mzO4VzO43wu4EIu4mIu4VIu43Ku4Equ4mqu4Vqu43pu4EZu4mZu4VZu43bu4E7u4m7u4V7u434e4EEe4mEe4VEe43Ge4Eme4mme4Vme43le4EVe4mVe4VVe43Xe4E3e4m3e4V3e430+4EM+4mM+4VM+43O+4Eu+4mu+4Vu+43t+4Ed+4md+4Vd+43f+4E/+4m/+4V/+e9wTgAEZiIEZhEEZjMEZgiEZiqEZhmEZjuEZgREZiZEZhVEZjdEZgzEZi7EZh3EZj/GZgAmZiImZhEmZjMmZgimZiqmZhmmZjumZgRmZiZmZhVmZjdmZgzmZi7mZh/8xL/MxPwuwIAuxMIuwKIuxOEuwJEuxNMuwLMuxPCuwIiuxMquwKquxOmuwJmuxNuuwLuuxPhuwIRuxMZuwKZuxOVuwJVuxNduwLduxPTuwIzuxM7uwK7uxO3uwJ3uxN/uwL/uxPwdwIAdxMIdwKIdxOEdwJEdxNMdwLMdxPCdwIidxMqdwKqdxOmdwJmdxNudwLudxPhdwIRdxMZdwKZdxOVdwJVdxNddwLddxPTdwIzdxM7dwK7dxO3dwJ3dxN/dwL/dxPw/wIA/xMI/wKI/xOE/wJE/xNM/wLM/xPC/wIi/xMq/wKq/xOm/wJm/xNu/wLu/xPh/wIR/xMZ/wKZ/xOV/wJV/xNd/wLd/xPT/wIz/xM7/wK7/xO3/wJ3/xN//wL/897AvAgAzEwAzCoAzG4AzBkAzF0AzDsAzH8IzAiIzEyIzCqIzG6IzBmIzF2IzDuIzH+EzAhEzExEzCpEzG5EzBlEzF1EzDtEzH9MzAjMzEzMzCrMzG7MzBnMzF3MzD/wP9BjIb + + + + + AwAAAACAAAA4OAAASQAAAEkAAAAyAAAAeJztxTEBAAAMAqDZv/QOYwgPuYpt27Zt27Zt27Zt27Zt27Zt27Zt27Zt27Zt27Zt27Zt27Zt27Zt27Zt27Zt27Zt28M//AAQAXic7cUxAQAADAKg2b/0DmMID7mKbdu2bdu2bdu2bdu2bdu2bdu2bdu2bdu2bdu2bdu2bdu2bdu2bdu2bdu2bdu2bdvDP/wAEAF4nO3FoQEAAAgDIOf/Rxt8wGiAQmrFtm3btm3btm3btm3btm3b9tvbtm3bto8PUFkIkA== + + + AwAAAACAAAA4OAAATBgAAFEYAADHCgAAeJw13dMWIMqSBcDbtm3btm3btm3btm3btm3bdvc8TJx6iU+olVWZO//3v/8/ARiQgRiYQRiUwRicIRiSoRiaYRiW4RieERiRkRiZURiV0RidMRiTsRibcRiX8RifCZiQiZiYSZiUyZicKZiSqZiaaZiW6ZieGZiRmZiZWZiV2ZidOZiTuZibeZiX+ZifBViQhViYRViUxVicJViSpViaZViW5VieFViRlViZVViV1VidNViTtVibdViX9VifDdiQjdiYTdiUzdicLdiSrdiabdiW7dieHdiRndiZXdiV3didPdiTvdibfdiX/difAziQgziYQziUwzicIziSoziaYziW4zieEziRkziZUziV0zidMziTszibcziX8zifC7iQi7iYS7iUy7icK7iSq7iaa7iW67ieG7iRm7iZW7iV27idO7iTu7ibe7iX+7ifB3iQh3iYR3iUx3icJ3iSp3iaZ3iW53ieF3iRl3iZV3iV13idN3iTt3ibd3iX93ifD/iQj/iYT/iUz/icL/iSr/iab/iW7/ieH/iRn/iZX/iV3/idP/iTv/ibf/iX//jfxR+AARmIgRmEQRmMwRmCIRmKoRmGYRmO4RmBERmJkRmFURmN0RmDMRmLsRmHcRmP8ZmACZmIiZmESZmMyZmCKZmKqZmGaZmO6ZmBGZmJmZmFWZmN2ZmDOZmLuZmHeZmP+VmABVmIhVmERVmMxVmCJVmKpVmGZVmO5VmBFVmJlVmFVVmN1VmDNVmLtVmHdVmP9dmADdmIjdmETdmMzdmCLdmKrdmGbdmO7dmBHdmJndmFXdmN3dmDPdmLvdmHfdmP/TmAAzmIgzmEQzmMwzmCIzmKozmGYzmO4zmBEzmJkzmFUzmN0zmDMzmLszmHczmP87mAC7mIi7mES7mMy7mCK7mKq7mGa7mO67mBG7mJm7mFW7mN27mDO7mLu7mHe7mP+3mAB3mIh3mER3mMx3mCJ3mKp3mGZ3mO53mBF3mJl3mFV3mN13mDN3mLt3mHd3mP9/mAD/mIj/mET/mMz/mCL/mKr/mGb/mO7/mBH/mJn/mFX/mN3/mDP/mLv/mHf/mP/xX8ARiQgRiYQRiUwRicIRiSoRiaYRiW4RieERiRkRiZURiV0RidMRiTsRibcRiX8RifCZiQiZiYSZiUyZicKZiSqZiaaZiW6ZieGZiRmZiZWZiV2ZidOZiTuZibeZiX+ZifBViQhViYRViUxVicJViSpViaZViW5VieFViRlViZVViV1VidNViTtVibdViX9VifDdiQjdiYTdiUzdicLdiSrdiabdiW7dieHdiRndiZXdiV3didPdiTvdibfdiX/difAziQgziYQziUwzicIziSoziaYziW4zieEziRkziZUziV0zidMziTszibcziX8zifC7iQi7iYS7iUy7icK7iSq7iaa7iW67ieG7iRm7iZW7iV27idO7iTu7ibe7iX+7ifB3iQh3iYR3iUx3icJ3iSp3iaZ3iW53ieF3iRl3iZV3iV13idN3iTt3ibd3iX93ifD/iQj/iYT/iUz/icL/iSr/iab/iW7/ieH/iRn/iZX/iV3/idP/iTv/ibf/iX//jfQ38ABmQgBmYQBmUwBmcIhmQohmYYhmU4hmcERmQkRmYURmU0RmcMxmQsxmYcxmU8xmcCJmQiJmYSJmUyJmcKpmQqpmYapmU6pmcGZmQmZmYWZmU2ZmcO5mQu5mYe5mU+5mcBFmQhFmYRFmUxFmcJlmQplmYZlmU5lmcFVmQlVmYVVmU1VmcN1mQt1mYd1mU91mcDNmQjNmYTNmUzNmcLtmQrtmYbtmU7tmcHdmQndmYXdmU3dmcP9mQv9mYf9mU/9ucADuQgDuYQDuUwDucIjuQojuYYjuU4jucETuQkTuYUTuU0TucMzuQszuYczuU8zucCLuQiLuYSLuUyLucKruQqruYaruU6rucGbuQmbuYWbuU2bucO7uQu7uYe7uU+7ucBHuQhHuYRHuUxHucJnuQpnuYZnuU5nucFXuQlXuYVXuU1XucN3uQt3uYd3uU93ucDPuQjPuYTPuUzPucLvuQrvuYbvuU7vucHfuQnfuYXfuU3fucP/uQv/uYf/uU//vfBH4ABGYiBGYRBGYzBGYIhGYqhGYZhGY7hGYERGYmRGYVRGY3RGYMxGYuxGYdxGY/xmYAJmYiJmYRJmYzJmYIpmYqpmYZpmY7pmYEZmYmZmYVZmY3ZmYM5mYu5mYd5mY/5WYAFWYiFWYRFWYzFWYIlWYqlWYZlWY7lWYEVWYmVWYVVWY3VWYM1WYu1WYd1WY/12YAN2YiN2YRN2YzN2YIt2Yqt2YZt2Y7t2YEd2Ymd2YVd2Y3d2YM92Yu92Yd92Y/9OYADOYiDOYRDOYzDOYIjOYqjOYZjOY7jOYETOYmTOYVTOY3TOYMzOYuzOYdzOY/zuYALuYiLuYRLuYzLuYIruYqruYZruY7ruYEbuYmbuYVbuY3buYM7uYu7uYd7uY/7eYAHeYiHeYRHeYzHeYIneYqneYZneY7neYEXeYmXeYVXeY3XeYM3eYu3eYd3eY/3+YAP+YiP+YRP+YzP+YIv+Yqv+YZv+Y7v+YEf+Ymf+YVf+Y3f+YM/+Yu/+Yd/+Y//NfYFYEAGYmAGYVAGY3CGYEiGYmiGYViGY3hGYERGYmRGYVRGY3TGYEzGYmzGYVzGY3wmYEImYmImYVImY3KmYEqmYmqmYVqmY3pmYEZmYmZmYVZmY3bmYE7mYm7mYV7mY34WYEEWYmEWYVEWY3GWYEmWYmmWYVmWY3lWYEVWYmVWYVVWY3XWYE3WYm3WYV3WY302YEM2YmM2YVM2Y3O2YEu2Ymu2YVu2Y3t2YEd2Ymd2YVd2Y3f2YE/2Ym/2YV/2Y38O4EAO4mAO4VAO43CO4EiO4miO4ViO43hO4ERO4mRO4VRO43TO4EzO4mzO4VzO43wu4EIu4mIu4VIu43Ku4Equ4mqu4Vqu43pu4EZu4mZu4VZu43bu4E7u4m7u4V7u434e4EEe4mEe4VEe43Ge4Eme4mme4Vme43le4EVe4mVe4VVe43Xe4E3e4m3e4V3e430+4EM+4mM+4VM+43O+4Eu+4mu+4Vu+43t+4Ed+4md+4Vd+43f+4E/+4m/+4V/+438N/QEYkIEYmEEYlMEYnCEYkqEYmmEYluEYnhEYkZEYmVEYldEYnTEYk7EYm3EYl/EYnwmYkImYmEmYlMmYnCmYkqmYmmmYlumYnhmYkZmYmVmYldmYnTmYk7mYm3mYl/mYnwVYkIVYmEVYlMVYnCVYkqVYmmVYluVYnhVYkZVYmVVYldVYnTVYk7VYm3VYl/VYnw3YkI3YmE3YlM3YnC3Ykq3Ymm3Ylu3Ynh3YkZ3YmV3Yld3YnT3Yk73Ym33Yl/3YnwM4kIM4mEM4lMM4nCM4kqM4mmM4luM4nhM4kZM4mVM4ldM4nTM4k7M4m3M4l/M4nwu4kIu4mEu4lMu4nCu4kqu4mmu4luu4nhu4kZu4mVu4ldu4nTu4k7u4m3u4l/u4nwd4kId4mEd4lMd4nCd4kqd4mmd4lud4nhd4kZd4mVd4ldd4nTd4k7d4m3d4l/d4nw/4kI/4mE/4lM/4nC/4kq/4mm/4lu/4nh/4kZ/4mV/4ld/4nT/4k7/4m3/4l//43yBfAAZkIAZmEAZlMAZnCIZkKIZmGIZlOIZnBEZkJEZmFEZlNEZnDMZkLMZmHMZlPMZnAiZkIiZmEiZlMiZnCqZkKqZmGqZlOqZnBmZkJmZmFmZlNmZnDuZkLuZmHuZlPuZnARZkIRZmERZlMRZnCZZkKZZmGZZlOZZnBVZkJVZmFVZlNVZnDdZkLdZmHdZlPdZnAzZkIzZmEzZlMzZnC7ZkK7ZmG7ZlO7ZnB3ZkJ3ZmF3ZlN3ZnD/ZkL/ZmH/ZlP/bnAA7kIA7mEA7lMA7nCI7kKI7mGI7lOI7nBE7kJE7mFE7lNE7nDM7kLM7mHM7lPM7nAi7kIi7mEi7lMi7nCq7kKq7mGq7lOq7nBm7kJm7mFm7lNm7nDu7kLu7mHu7lPu7nAR7kIR7mER7lMR7nCZ7kKZ7mGZ7lOZ7nBV7kJV7mFV7lNV7nDd7kLd7mHd7lPd7nAz7kIz7mEz7lMz7nC77kK77mG77lO77nB37kJ37mF37lN37nD/7kL/7mH/7lP/43wB+AARmIgRmEQRmMwRmCIRmKoRmGYRmO4RmBERmJkRmFURmN0RmDMRmLsRmHcRmP8ZmACZmIiZmESZmMyZmCKZmKqZmGaZmO6ZmBGZmJmZmFWZmN2ZmDOZmLuZmHeZmP+VmABVmIhVmERVmMxVmCJVmKpVmGZVmO5VmBFVmJlVmFVVmN1VmDNVmLtVmHdVmP9dmADdmIjdmETdmMzdmCLdmKrdmGbdmO7dmBHdmJndmFXdmN3dmDPdmLvdmHfdmP/TmAAzmIgzmEQzmMwzmCIzmKozmGYzmO4zmBEzmJkzmFUzmN0zmDMzmLszmHczmP87mAC7mIi7mES7mMy7mCK7mKq7mGa7mO67mBG7mJm7mFW7mN27mDO7mLu7mHe7mP+3mAB3mIh3mER3mMx3mCJ3mKp3mGZ3mO53mBF3mJl3mFV3mN13mDN3mLt3mHd3mP9/mAD/mIj/mET/mMz/mCL/mKr/mGb/mO7/mBH/mJn/mFX/mN3/mDP/mLv/mHf/mP/wX3BGBABmJgBmFQBmNwhmBIhmJohmFYhmN4RmBERmJkRmFURmN0xmBMxmJsxmFcxmN8JmBCJmJiJmFSJmNypmBKpmJqpmFapmN6ZmBGZmJmZmFWZmN25mBO5mJu5mFe5mN+FmBBFmJhFmFRFmNxlmBJlmJplmFZlmN5VmBFVmJlVmFVVmN11mBN1mJt1mFd1mN9NmBDNmJjNmFTNmNztmBLtmJrtmFbtmN7dmBHdmJndmFXdmN39mBP9mJv9mFf9mN/DuBADuJgDuFQDuNwjuBIjuJojuFYjuN4TuBETuJkTuFUTuN0zuBMzuJszuFczuN8LuBCLuJiLuFSLuNyruBKruJqruFaruN6buBGbuJmbuFWbuN27uBO7uJu7uFe7uN+HuBBHuJhHuFRHuNxnuBJnuJpnuFZnuN5XuBFXuJlXuFVXuN13uBN3uJt3uFd3uN9PuBDPuJjPuFTPuNzvuBLvuJrvuFbvuN7fuBHfuJnfuFXfuN3/uBP/uJv/uFf/uN/gX0BGJCBGJhBGJTBGJwhGJKhGJphGJbhGJ4RGJGRGJlRGJXRGJ0xGJOxGJtxGJfxGJ8JmJCJmJhJmJTJmJwpmJKpmJppmJbpmJ4ZmJGZmJlZmJXZmJ05mJO5mJt5mJf5mJ8FWJCFWJhFWJTFWJwlWJKlWJplWJblWJ4VWJGVWJlVWJXVWJ01WJO1WJt1WJf1WJ8N2JCN2JhN2JTN2Jwt2JKt2Jpt2Jbt2J4d2JGd2Jld2JXd2J092JO92Jt92Jf92J8DOJCDOJhDOJTDOJwjOJKjOJpjOJbjOJ4TOJGTOJlTOJXTOJ0zOJOzOJtzOJfzOJ8LuJCLuJhLuJTLuJwruJKruJpruJbruJ4buJGbuJlbuJXbuJ07uJO7uJt7uJf7uJ8HeJCHeJhHeJTHeJwneJKneJpneJbneJ4XeJGXeJlXeJXXeJ03eJO3eJt3eJf3eJ8P+JCP+JhP+JTP+Jwv+JKv+Jpv+Jbv+J4f+JGf+Jlf+JXf+J0/+JO/+Jt/+Jf/+F9QbwAGZCAGZhAGZTAGZwiGZCiGZhiGZTiGZwRGZCRGZhRGZTRGZwzGZCzGZhzGZTzGZwImZCImZhImZTImZwqmZCqmZhqmZTqmZwZmZCZmZhZmZTZmZw7mZC7mZh7mZT7mZwEWZCEWZhEWZTEWZwmWZCmWZhmWZTmWZwVWZCVWZhVWZTVWZw3WZC3WZh3WZT3WZwM2ZCM2ZhM2ZTM2Zwu2ZCu2Zhu2ZTu2Zwd2ZCd2Zhd2ZTd2Zw/2ZC/2Zh/2ZT/25wAO5CAO5hAO5TAO5wiO5CiO5hiO5TiO5wRO5CRO5hRO5TRO5wzO5CzO5hzO5TzO5wIu5CIu5hIu5TIu5wqu5Cqu5hqu5Tqu5wZu5CZu5hZu5TZu5w7u5C7u5h7u5T7u5wEe5CEe5hEe5TEe5wme5Cme5hme5Tme5wVe5CVe5hVe5TVe5w3e5C3e5h3e5T3e5wM+5CM+5hM+5TM+5wu+5Cu+5hu+5Tu+5wd+5Cd+5hd+5Td+5w/+5C/+5h/+5T/+F9AfgAEZiIEZhEEZjMEZgiEZiqEZhmEZjuEZgREZiZEZhVEZjdEZgzEZi7EZh3EZj/GZgAmZiImZhEmZjMmZgimZiqmZhmmZjumZgRmZiZmZhVmZjdmZgzmZi7mZh3mZj/lZgAVZiIVZhEVZjMVZgiVZiqVZhmVZjuVZgRVZiZVZhVVZjdVZgzVZi7VZh3VZj/XZgA3ZiI3ZhE3ZjM3Zgi3Ziq3Zhm3Zju3ZgR3ZiZ3ZhV3Zjd3Zgz3Zi73Zh33Zj/05gAM5iIM5hEM5jMM5giM5iqM5hmM5juM5gRM5iZM5hVM5jdM5gzM5i7M5h3M5j/O5gAu5iIu5hEu5jMu5giu5iqu5hmu5juu5gRu5iZu5hVu5jdu5gzu5i7u5h3u5j/t5gAd5iId5hEd5jMd5gid5iqd5hmd5jud5gRd5iZd5hVd5jdd5gzd5i7d5h3d5j/f5gA/5iI/5hE/5jM/5gi/5iq/5hm/5ju/5gR/5iZ/5hV/5jd/5gz/5i7/5h3/5j/8t5gnAgAzEwAzCoAzG4AzBkAzF0AzDsAzH8IzAiIzEyIzCqIzG6IzBmIzF2IzDuIzH+EzAhEzExEzCpEzG5EzBlEzF1EzDtEzH9MzAjMzEzMzCrMzG7MzBnMzF3MzDvMzH/CzAgizEwizCoizG4izBkizF0izDsizH8qzAiqzEyqzCqqzG6qzBmqzF2qzDuqzH+mzAhmzExmzCpmzG5mzBlmzF1mzDtmzH9uzAjuzEzuzCruzG7uzBnuzF3uzDvuzH/hzAgRzEwRzCoRzG4RzBkRzF0RzDsRzH8ZzAiZzEyZzCqZzG6ZzBmZzF2ZzDuZzH+VzAhVzExVzCpVzG5VzBlVzF1VzDtVzH9dzAjdzEzdzCrdzG7dzBndzF3dzDvdzH/TzAgzzEwzzCozzG4zzBkzzF0zzDszzH87zAi7zEy7zCq7zG67zBm7zF27zDu7zH+3zAh3zEx3zCp3zG53zBl3zF13zDt3zH9/zAj/zEz/zCr/zG7/zBn/zF3/zDv/zH/xbyBWBABmJgBmFQBmNwhmBIhmJohmFYhmN4RmBERmJkRmFURmN0xmBMxmJsxmFcxmN8JmBCJmJiJmFSJmNypmBKpmJqpmFapmN6ZmBGZmJmZmFWZmN25mBO5mJu5mFe5mN+FmBBFmJhFmFRFmNxlmBJlmJplmFZlmN5VmBFVmJlVmFVVmN11mBN1mJt1mFd1mN9NmBDNmJjNmFTNmNztmBLtmJrtmFbtmN7dmBHdmJndmFXdmN39mBP9mJv9mFf9mN/DuBADuJgDuFQDuNwjuBIjuJojuFYjuN4TuBETuJkTuFUTuN0zuBMzuJszuFczuN8LuBCLuJiLuFSLuNyruBKruJqruFaruN6buBGbuJmbuFWbuN27uBO7uJu7uFe7uN+HuBBHuJhHuFRHuNxnuBJnuJpnuFZnuN5XuBFXuJlXuFVXuN13uBN3uJt3uFd3uN9PuBDPuJjPuFTPuNzvuBLvuJrvuFbvuN7fuBHfuJnfuFXfuN3/uBP/uJv/uFf/uN/i3gDMCADMTCDMCiDMThDMCRDMTTDMCzDMTwjMCIjMTKjMCqjMTpjMCZjMTbjMC7jMT4TMCETMTGTMCmTMTlTMCVTMTXTMC3TMT0zMCMzMTOzMCuzMTtzMCdzMTfzMC/zMT8LsCALsTCLsCiLsThLsCRLsTTLsCzLsTwrsCIrsTKrsCqrsTprsCZrsTbrsC7rsT4bsCEbsTGbsCmbsTlbsCVbsTXbsC3bsT07sCM7sTO7sCu7sTt7sCd7sTf7sC/7sT8HcCAHcTCHcCiHcThHcCRHcTTHcCzHcTwncCIncTKncCqncTpncCZncTbncC7ncT4XcCEXcTGXcCmXcTlXcCVXcTXXcC3XcT03cCM3cTO3cCu3cTt3cCd3cTf3cC/3cT8P8CAP8TCP8CiP8ThP8CRP8TTP8CzP8Twv8CIv8TKv8Cqv8Tpv8CZv8Tbv8C7v8T4f8CEf8TGf8Cmf8Tlf8CVf8TXf8C3f8T0/8CM/8TO/8Cu/8Tt/8Cd/8Tf/8C//8f8AkFtweXicLcVDEBgGAgDA2LZt27Zt27Zt23bSxrZt27atm7nufjZAhAD/F9CBHNhBHNTBHNwhHNKhHNphHNbhHN4RHNGRHNlRHNXRHN0xHNOxHNtxHNfxHN8JnNCJnNhJnNTJnNwpnNKpnNppnNbpnN4ZnNGZnNlZnNXZnN05nNO5nNt5nNf5nN8FXNCFXNhFXNTFXNwlXNKlXNplXNblXN4VXNGVXNlVXNXVXN01XNO1XNt1XNf1XN8N3NCN3NhN3NTN3Nwt3NKt3Npt3Nbt3N4d3NGd3Nld3NXd3N093NO93Nt93Nf93N8DPNCDPNhDPNTDPNwjPNKjPNpjPNbjPN4TPNGTPNlTPNXTPN0zPNOzPNtzPNfzPN8LvNCLvNhLvNTLvNwrvNKr/I//9Wqv8Vqv83pv8EZv8mZv8VZv83bv8E7v8m7v8V7v834f8EEf8mEf8VEf83Gf8Emf8mmf8Vmf83lf8EVf8mVf8VVf83Xf8E3f8m3f8V3f830/8EM/8mM/8VM/83O/8Eu/8mu/8Vu/83t/8Ed/8md/8Vd/83f/8E//8m//8V8HiPhfAR3IgR3EQR3MwR3CIR3KoR3GYR3O4R3BER3JkR3FUR3N0R3DMR3LsR3HcR3P8Z3ACZ3IiZ3ESZ3MyZ3CKZ3KqZ3GaZ3O6Z3BGZ3JmZ3FWZ3N2Z3DOZ3LuZ3HeZ3P+V3ABV3IhV3ERV3MxV3CJV3KpV3GZV3O5V3BFV3JlV3FVV3N1V3DNV3LtV3HdV3P9d3ADd3Ijd3ETd3Mzd3CLd3Krd3Gbd3O7d3BHd3Jnd3FXd3N3d3DPd3Lvd3Hfd3P/T3AAz3Igz3EQz3Mwz3CIz3Koz3GYz3O4z3BEz3Jkz3FUz3N0z3DMz3Lsz3Hcz3P873AC73Ii73ES73My73CK73K//hfr/Yar/U6r/cGb/Qmb/YWb/U2b/cO7/Qu7/Ye7/U+7/cBH/QhH/YRH/UxH/cJn/Qpn/YZn/U5n/cFX/QlX/YVX/U1X/cN3/Qt3/Yd3/U93/cDP/QjP/YTP/UzP/cLv/Qrv/Ybv/U7v/cHf/Qnf/YXf/U3f/cP//Qv//Yf/3WASP8V0IEc2EEc1MEc3CEc0qEc2mEc1uEc3hEc0ZEc2VEc1dEc3TEc07Ec23Ec1/Ec3wmc0Imc2Emc1Mmc3Cmc0qmc2mmc1umc3hmc0Zmc2Vmc1dmc3Tmc07mc23mc1/mc3wVc0IVc2EVc1MVc3CVc0qVc2mVc1uVc3hVc0ZVc2VVc1dVc3TVc07Vc23Vc1/Vc3w3c0I3c2E3c1M3c3C3c0q3c2m3c1u3c3h3c0Z3c2V3c1d3c3T3c073c233c1/3c3wM80IM82EM81MM83CM80qM82mM81uM83hM80ZM82VM81dM83TM807M823M81/M83wu80Iu82Eu81Mu83Cu80qv8j//1aq/xWq/zem/wRm/yZm/xVm/zdu/wTu/ybu/xXu/zfh/wQR/yYR/xUR/zcZ/wSZ/yaZ/xWZ/zeV/wRV/yZV/xVV/zdd/wTd/ybd/xXd/zfT/wQz/yYz/xUz/zc7/wS7/ya7/xW7/ze3/wR3/yZ3/xV3/zd//wT//yb//xXweI/F8BHciBHcRBHczBHcIhHcqhHcZhHc7hHcERHcmRHcVRHc3RHcMxHcuxHcdxHc/xncAJnciJncRJnczJncIpncqpncZpnc7pncEZncmZncVZnc3ZncM5ncu5ncd5nc/5XcAFXciFXcRFXczFXcIlXcqlXcZlXc7lXcEVXcmVXcVVXc3VXcM1Xcu1Xcd1Xc/13cAN3ciN3cRN3czN3cIt3cqt3cZt3c7t3cEd3cmd3cVd3c3d3cM93cu93cd93c/9PcADPciDPcRDPczDPcIjPcqjPcZjPc7jPcETPcmTPcVTPc3TPcMzPcuzPcdzPc/zvcALvciLvcRLvczLvcIrvcr/+F+v9hqv9Tqv9wZv9CZv9hZv9TZv9w7v9C7v9h7v9T7v9wEf9CEf9hEf9TEf9wmf9Cmf9hmf9Tmf9wVf9CVf9hVf9TVf9w3f9C3f9h3f9T3f9wM/9CM/9hM/9TM/9wu/9Cu/9hu/9Tu/9wd/9Cd/9hd/9Td/9w//9C//9h//dYAo/xXQgRzYQRzUwRzcIRzSoRzaYRzW4RzeERzRkRzZURzV0RzdMRzTsRzbcRzX8RzfCZzQiZzYSZzUyZzcKZzSqZzaaZzW6ZzeGZzRmZzZWZzV2ZzdOZzTuZzbeZzX+ZzfBVzQhVzYRVzUxVzcJVzSpVzaZVzW5VzeFVzRlVzZVVzV1VzdNVzTtVzbdVzX9VzfDdzQjdzYTdzUzdzcLdzSrdzabdzW7dzeHdzRndzZXdzV3dzdPdzTvdzbfdzX/dzfAzzQgzzYQzzUwzzcIzzSozzaYzzW4zzeEzzRkzzZUzzV0zzdMzzTszzbczzX8zzfC7zQi7zYS7zUy7zcK7zSq/yP//Vqr/Far/N6b/BGb/Jmb/FWb/N27/BO7/Ju7/Fe7/N+H/BBH/JhH/FRH/Nxn/BJn/Jpn/FZn/N5X/BFX/JlX/FVX/N13/BN3/Jt3/Fd3/N9P/BDP/JjP/FTP/Nzv/BLv/Jrv/Fbv/N7f/BHf/Jnf/FXf/N3//BP//Jv//FfB4j6XwEdyIEdxEEdzMEdwiEdyqEdxmEdzuEdwREdyZEdxVEdzdEdwzEdy7Edx3Edz/GdwAmdyImdxEmdzMmdwimdyqmdxmmdzumdwRmdyZmdxVmdzdmdwzmdy7mdx3mdz/ldwAVdyIVdxEVdzMVdwiVdyqVdxmVdzuVdwRVdyZVdxVVdzdVdwzVdy7Vdx3Vdz/XdwA3dyI3dxE3dzM3dwi3dyq3dxm3dzu3dwR3dyZ3dxV3dzd3dwz3dy73dx33dz/09wAM9yIM9xEM9zMM9wiM9yqM9xmM9zuM9wRM9yZM9xVM9zdM9wzM9y7M9x3M9z/O9wAu9yIu9xEu9zMu9wiu9yv/4X6/2Gq/1Oq/3Bm/0Jm/2Fm/1Nm/3Du/0Lu/2Hu/1Pu/3AR/0IR/2ER/1MR/3CZ/0KZ/2GZ/1OZ/3BV/0JV/2FV/1NV/3Dd/0Ld/2Hd/1Pd/3Az/0Iz/2Ez/1Mz/3C7/0K7/2G7/1O7/3B3/0J3/2F3/1N3/3D//0L//2H/91gGj/FdCBHNhBHNTBHNwhHNKhHNphHNbhHN4RHNGRHNlRHNXRHN0xHNOxHNtxHNfxHN8JnNCJnNhJnNTJnNwpnNKpnNppnNbpnN4ZnNGZnNlZnNXZnN05nNO5nNt5nNf5nN8FXNCFXNhFXNTFXNwlXNKlXNplXNblXN4VXNGVXNlVXNXVXN01XNO1XNt1XNf1XN8N3NCN3NhN3NTN3Nwt3NKt3Npt3Nbt3N4d3NGd3Nld3NXd3N093NO93Nt93Nf93N8DPNCDPNhDPNTDPNwjPNKjPNpjPNbjPN4TPNGTPNlTPNXTPN0zPNOzPNtzPNfzPN8LvNCLvNhLvNTLvNwrvNKr/I//9Wqv8Vqv83pv8EZv8mZv8VZv83bv8E7v8m7v8V7v834f8EEf8mEf8VEf83Gf8Emf8mmf8Vmf83lf8EVf8mVf8VVf83Xf8E3f8m3f8V3f830/8EM/8mM/8VM/83O/8Eu/8mu/8Vu/83t/8Ed/8md/8Vd/83f/8E//8m//8V8HiP5fAR3IgR3EQR3MwR3CIR3KoR3GYR3O4R3BER3JkR3FUR3N0R3DMR3LsR3HcR3P8Z3ACZ3IiZ3ESZ3MyZ3CKZ3KqZ3GaZ3O6Z3BGZ3JmZ3FWZ3N2Z3DOZ3LuZ3HeZ3P+V3ABV3IhV3ERV3MxV3CJV3KpV3GZV3O5V3BFV3JlV3FVV3N1V3DNV3LtV3HdV3P9d3ADd3Ijd3ETd3Mzd3CLd3Krd3Gbd3O7d3BHd3Jnd3FXd3N3d3DPd3Lvd3Hfd3P/T3AAz3Igz3EQz3Mwz3CIz3Koz3GYz3O4z3BEz3Jkz3FUz3N0z3DMz3Lsz3Hcz3P873AC73Ii73ES73My73CK73K//hfr/Yar/U6r/cGb/Qmb/YWb/U2b/cO7/Qu7/Ye7/U+7/cBH/QhH/YRH/UxH/cJn/Qpn/YZn/U5n/cFX/QlX/YVX/U1X/cN3/Qt3/Yd3/U93/cDP/QjP/YTP/UzP/cLv/Qrv/Ybv/U7v/cHf/Qnf/YXf/U3f/cP//Qv//Yf/3WAGP8V0IEc2EEc1MEc3CEc0qEc2mEc1uEc3hEc0ZEc2VEc1dEc3TEc07Ec23Ec1/Ec3wmc0Imc2Emc1Mmc3Cmc0qmc2mmc1umc3hmc0Zmc2Vmc1dmc3Tmc07mc23mc1/mc3wVc0IVc2EVc1MVc3CVc0qVc2mVc1uVc3hVc0ZVc2VVc1dVc3TVc07Vc23Vc1/Vc3w3c0I3c2E3c1M3c3C3c0q3c2m3c1u3c3h3c0Z3c2V3c1d3c3T3c073c233c1/3c3wM80IM82EM81MM83CM80qM82mM81uM83hM80ZM82VM81dM83TM807M823M81/M83wu80Iu82Eu81Mu83Cu80qv8j//1aq/xWq/zem/wRm/yZm/xVm/zdu/wTu/ybu/xXu/zfh/wQR/yYR/xUR/zcZ/wSZ/yaZ/xWZ/zeV/wRV/yZV/xVV/zdd/wTd/ybd/xXd/zfT/wQz/yYz/xUz/zc7/wS7/ya7/xW7/ze3/wR3/yZ3/xV3/zd//wT//yb//xXweI+V8BHciBHcRBHczBHcIhHcqhHcZhHc7hHcERHcmRHcVRHc3RHcMxHcuxHcdxHc/xncAJnciJncRJnczJncIpncqpncZpnc7pncEZncmZncVZnc3ZncM5ncu5ncd5nc/5XcAFXciFXcRFXczFXcIlXcqlXcZlXc7lXcEVXcmVXcVVXc3VXcM1Xcu1Xcd1Xc/13cAN3ciN3cRN3czN3cIt3cqt3cZt3c7t3cEd3cmd3cVd3c3d3cM93cu93cd93c/9PcADPciDPcRDPczDPcIjPcqjPcZjPc7jPcETPcmTPcVTPc3TPcMzPcuzPcdzPc/zvcALvciLvcRLvczLvcIrvcr/+F+v9hqv9Tqv9wZv9CZv9hZv9TZv9w7v9C7v9h7v9T7v9wEf9CEf9hEf9TEf9wmf9Cmf9hmf9Tmf9wVf9CVf9hVf9TVf9w3f9C3f9h3f9T3f9wM/9CM/9hM/9TM/9wu/9Cu/9hu/9Tu/9wd/9Cd/9hd/9Td/9w//9C//9h//dYBY/xXQgRzYQRzUwRzcIRzSoRzaYRzW4RzeERzRkRzZURzV0RzdMRzTsRzbcRzX8RzfCZzQiZzYSZzUyZzcKZzSqZzaaZzW6ZzeGZzRmZzZWZzV2ZzdOZzTuZzbeZzX+ZzfBVzQhVzYRVzUxVzcJVzSpVzaZVzW5VzeFVzRlVzZVVzV1VzdNVzTtVzbdVzX9VzfDdzQjdzYTdzUzdzcLdzSrdzabdzW7dzeHdzRndzZXdzV3dzdPdzTvdzbfdzX/dzfAzzQgzzYQzzUwzzcIzzSozzaYzzW4zzeEzzRkzzZUzzV0zzdMzzTszzbczzX8zzfC7zQi7zYS7zUy7zcK7zSq/yP//Vqr/Far/N6b/BGb/Jmb/FWb/N27/BO7/Ju7/Fe7/N+H/BBH/JhH/FRH/Nxn/BJn/Jpn/FZn/N5X/BFX/JlX/FVX/N13/BN3/Jt3/Fd3/N9P/BDP/JjP/FTP/Nzv/BLv/Jrv/Fbv/N7f/BHf/Jnf/FXf/N3//BP//Jv//FfB4j9XwEdyIEdxEEdzMEdwiEdyqEdxmEdzuEdwREdyZEdxVEdzdEdwzEdy7Edx3Edz/GdwAmdyImdxEmdzMmdwimdyqmdxmmdzumdwRmdyZmdxVmdzdmdwzmdy7mdx3mdz/ldwAVdyIVdxEVdzMVdwiVdyqVdxmVdzuVdwRVdyZVdxVVdzdVdwzVdy7Vdx3Vdz/XdwA3dyI3dxE3dzM3dwi3dyq3dxm3dzu3dwR3dyZ3dxV3dzd3dwz3dy73dx33dz/09wAM9yIM9xEM9zMM9wiM9yqM9xmM9zuM9wRM9yZM9xVM9zdM9wzM9y7M9x3M9z/O9wAu9yIu9xEu9zMu9wiu9yv/4X6/2Gq/1Oq/3Bm/0Jm/2Fm/1Nm/3Du/0Lu/2Hu/1Pu/3AR/0IR/2ER/1MR/3CZ/0KZ/2GZ/1OZ/3BV/0JV/2FV/1NV/3Dd/0Ld/2Hd/1Pd/3Az/0Iz/2Ez/1Mz/3C7/0K7/2G7/1O7/3B3/0J3/2F3/1N3/3D//0L//2H/91gDj/FdCBHNhBHNTBHNwhHNKhHNphHNbhHN4RHNGRHNlRHNXRHN0xHNOxHNtxHNfxHN8JnNCJnNhJnNTJnNwpnNKpnNppnNbpnN4ZnNGZnNlZnNXZnN05nNO5nNt5nNf5nN8FXNCFXNhFXNTFXNwlXNKlXNplXNblXN4VXNGVXNlVXNXVXN01XNO1XNt1XNf1XN8N3NCN3NhN3NTN3Nwt3NKt3Npt3Nbt3N4d3NGd3Nld3NXd3N093NO93Nt93Nf93N8DPNCDPNhDPNTDPNwjPNKjPNpjPNbjPN4TPNGTPNlTPNXTPN0zPNOzPNtzPNfzPN8LvNCLvNhLvNTLvNwrvNKr/I//9Wqv8Vqv83pv8EZv8mZv8VZv83bv8E7v8m7v8V7v834f8EEf8mEf8VEf83Gf8Emf8mmf8Vmf83lf8EVf8mVf8VVf83Xf8E3f8m3f8V3f830/8EM/8mM/8VM/83O/8Eu/8mu/8Vu/83t/8Ed/8md/8Vd/83f/8E//8m//8V8HiPtfAR3IgR3EQR3MwR3CIR3KoR3GYR3O4R3BER3JkR3FUR3N0R3DMR3LsR3HcR3P8Z3ACZ3IiZ3ESZ3MyZ3CKZ3KqZ3GaZ3O6Z3BGZ3JmZ3FWZ3N2Z3DOZ3LuZ3HeZ3P+V3ABV3IhV3ERV3MxV3CJV3KpV3GZV3O5V3BFV3JlV3FVV3N1V3DNV3LtV3HdV3P9d3ADd3Ijd3ETd3Mzd3CLd3Krd3Gbd3O7d3BHd3Jnd3FXd3N3d3DPd3Lvd3Hfd3P/T3AAz3Igz3EQz3Mwz3CIz3Koz3GYz3O4z3BEz3Jkz3FUz3N0z3DMz3Lsz3Hcz3P873AC73Ii73ES73My73CK73K//hfr/Yar/U6r/cGb/Qmb/YWb/U2b/cO7/Qu7/Ye7/U+7/cBH/QhH/YRH/UxH/cJn/Qpn/YZn/U5n/cFX/QlX/YVX/U1X/cN3/Qt3/Yd3/U93/cDP/QjP/YTP/UzP/cLv/Qrv/Ybv/U7v/cHf/Qnf/YXf/U3f/cP//Qv//Yf/3WAeP8V0IEc2EEc1MEc3CEc0qEc2mEc1uEc3hEc0ZEc2VEc1dEc3TEc07Ec23Ec1/Ec3wmc0Imc2Emc1Mmc3Cmc0qmc2mmc1umc3hmc0Zmc2Vmc1dmc3Tmc07mc23mc1/mc3wVc0IVc2EVc1MVc3CVc0qVc2mVc1uVc3hVc0ZVc2VVc1dVc3TVc07Vc23Vc1/Vc3w3c0I3c2E3c1M3c3C3c0q3c2m3c1u3c3h3c0Z3c2V3c1d3c3T3c073c233c1/3c3wM80IM82EM81MM83CM80qM82mM81uM83hM80ZM82VM81dM83TM807M823M81/M83wu80Iu82Eu81Mu83Cu80qv8j//1aq/xWq/zem/wRm/yZm/xVm/zdu/wTu/ybu/xXu/zfh/wQR/yYR/xUR/zcZ/wSZ/yaZ/xWZ/zeV/wRV/yZV/xVV/zdd/wTd/ybd/xXd/zfT/wQz/yYz/xUz/zc7/wS7/ya7/xW7/ze3/wR3/yZ3/xV3/zd//wT//yb//xXweI/18BHciBHcRBHczBHcIhHcqhHcZhHc7hHcERHcmRHcVRHc3RHcMxHcuxHcdxHc/xncAJnciJncRJnczJncIpncqpncZpnc7pncEZncmZncVZnc3ZncM5ncu5ncd5nc/5XcAFXciFXcRFXczFXcIlXcqlXcZlXc7lXcEVXcmVXcVVXc3VXcM1Xcu1Xcd1Xc/13cAN3ciN3cRN3czN3cIt3cqt3cZt3c7t3cEd3cmd3cVd3c3d3cM93cu93cd93c/9PcADPciDPcRDPczDPcIjPcqjPcZjPc7jPcETPcmTPcVTPc3TPcMzPcuzPcdzPc/zvcALvciLvcRLvczLvcIrvcr/+F+v9hqv9Tqv9wZv9CZv9hZv9TZv9w7v9C7v9h7v9T7v9wEf9CEf9hEf9TEf9wmf9Cmf9hmf9Tmf9wVf9CVf9hVf9TVf9w3f9C3f9h3f9T3f9wM/9CM/9hM/9TM/9wu/9Cu/9hu/9Tu/9wd/9Cd/9hd/9Td/9w//9C//9h//9f8AUMRwiHicLcVDEBgGAgDA2LZt27aTxrZt27atxrZt27Zt3sx197MBEgT4v4AO5MAO4qAO5uAO4ZAO5dAO47AO5/CO4IiO5MiO4qiO5uiO4ZiO5diO47iO5/hO4IRO5MRO4qRO5uRO4ZRO5dRO47RO5/TO4IzO5MzO4qzO5uzO4ZzO5dzO47zO5/wu4IIu5MIu4qIu5uIu4ZIu5dIu47Iu5/Ku4H9c0ZVc2VVc1dVc3TVc07Vc23Vc1/Vc3w3c0I3c2E3c1M3c3C3c0q3c2m3c1u3c3h3c0Z3c2V3c1d3c3T3c073c233c1/3c3wM80IM82EM81MM83CM80qM82mM81uM83hM80ZM82VM81dM83TM807M823M81/M83wu80Iu82P96iZd6mZd7hVd6lVd7jdd6ndd7gzd6kzd7i7d6m7d7h3d6l3d7j/d6n/f7gA/6kA/7iI/6mI/7hE/6lE/7jM/6nM/7gi/6ki/7iq/6mq/7hm/6lm/7ju/6nu/7gR/6kR/7iZ/6mZ/7hV/6lV/7jd/6nd/7gz/6kz/7i7/6m7/7h3/6l3/7j/86QML/CuhADuwgDupgDu4QDulQDu0wDutwDu8IjuhIjuwojupoju4YjulYju04jut4ju8ETuhETuwkTupkTu4UTulUTu00Tut0Tu8MzuhMzuwszupszu4czulczu08zut8zu8CLuhCLuwiLupiLu4SLulSLu0yLutyLu8K/scVXcmVXcVVXc3VXcM1Xcu1Xcd1Xc/13cAN3ciN3cRN3czN3cIt3cqt3cZt3c7t3cEd3cmd3cVd3c3d3cM93cu93cd93c/9PcADPciDPcRDPczDPcIjPcqjPcZjPc7jPcETPcmTPcVTPc3TPcMzPcuzPcdzPc/zvcALvciL/a+XeKmXeblXeKVXebXXeK3Xeb03eKM3ebO3eKu3ebt3eKd3ebf3eK/3eb8P+KAP+bCP+KiP+bhP+KRP+bTP+KzP+bwv+KIv+bKv+Kqv+bpv+KZv+bbv+K7v+b4f+KEf+bGf+Kmf+blf+KVf+bXf+K3f+b0/+KM/+bO/+Ku/+bt/+Kd/+bf/+K8DJPqvgA7kwA7ioA7m4A7hkA7l0A7jsA7n8I7giI7kyI7iqI7m6I7hmI7l2I7juI7n+E7ghE7kxE7ipE7m5E7hlE7l1E7jtE7n9M7gjM7kzM7irM7m7M7hnM7l3M7jvM7n/C7ggi7kwi7ioi7m4i7hki7l0i7jsi7n8q7gf1zRlVzZVVzV1VzdNVzTtVzbdVzX9VzfDdzQjdzYTdzUzdzcLdzSrdzabdzW7dzeHdzRndzZXdzV3dzdPdzTvdzbfdzX/dzfAzzQgzzYQzzUwzzcIzzSozzaYzzW4zzeEzzRkzzZUzzV0zzdMzzTszzbczzX8zzfC7zQi7zY/3qJl3qZl3uFV3qVV3uN13qd13uDN3qTN3uLt3qbt3uHd3qXd3uP93qf9/uAD/qQD/uIj/qYj/uET/qUT/uMz/qcz/uCL/qSL/uKr/qar/uGb/qWb/uO7/qe7/uBH/qRH/uJn/qZn/uFX/qVX/uN3/qd3/uDP/qTP/uLv/qbv/uHf/qXf/uP/zpA4v8K6EAO7CAO6mAO7hAO6VAO7TAO63AO7wiO6EiO7CiO6miO7hiO6ViO7TiO63iO7wRO6ERO7CRO6mRO7hRO6VRO7TRO63RO7wzO6EzO7CzO6mzO7hzO6VzO7TzO63zO7wIu6EIu7CIu6mIu7hIu6VIu7TIu63Iu7wr+xxVdyZVdxVVdzdVdwzVdy7Vdx3Vdz/XdwA3dyI3dxE3dzM3dwi3dyq3dxm3dzu3dwR3dyZ3dxV3dzd3dwz3dy73dx33dz/09wAM9yIM9xEM9zMM9wiM9yqM9xmM9zuM9wRM9yZM9xVM9zdM9wzM9y7M9x3M9z/O9wAu9yIv9r5d4qZd5uVd4pVd5tdd4rdd5vTd4ozd5s7d4q7d5u3d4p3d5t/d4r/d5vw/4oA/5sI/4qI/5uE/4pE/5tM/4rM/5vC/4oi/5sq/4qq/5um/4pm/5tu/4ru/5vh/4oR/5sZ/4qZ/5uV/4pV/5td/4rd/5vT/4oz/5s7/4q7/5u3/4p3/5t//4rwMk+a+ADuTADuKgDubgDuGQDuXQDuOwDufwjuCIjuTIjuKojubojuGYjuXYjuO4juf4TuCETuTETuKkTubkTuGUTuXUTuO0Tuf0zuCMzuTMzuKszubszuGczuXczuO8zuf8LuCCLuTCLuKiLubiLuGSLuXSLuOyLufyruB/XNGVXNlVXNXVXN01XNO1XNt1XNf1XN8N3NCN3NhN3NTN3Nwt3NKt3Npt3Nbt3N4d3NGd3Nld3NXd3N093NO93Nt93Nf93N8DPNCDPNhDPNTDPNwjPNKjPNpjPNbjPN4TPNGTPNlTPNXTPN0zPNOzPNtzPNfzPN8LvNCLvNj/eomXepmXe4VXepVXe43Xep3Xe4M3epM3e4u3epu3e4d3epd3e4/3ep/3+4AP+pAP+4iP+piP+4RP+pRP+4zP+pzP+4Iv+pIv+4qv+pqv+4Zv+pZv+47v+p7v+4Ef+pEf+4mf+pmf+4Vf+pVf+43f+p3f+4M/+pM/+4u/+pu/+4d/+pd/+4//OkDS/wroQA7sIA7qYA7uEA7pUA7tMA7rcA7vCI7oSI7sKI7qaI7uGI7pWI7tOI7reI7vBE7oRE7sJE7qZE7uFE7pVE7tNE7rdE7vDM7oTM7sLM7qbM7uHM7pXM7tPM7rfM7vAi7oQi7sIi7qYi7uEi7pUi7tMi7rci7vCv7HFV3JlV3FVV3N1V3DNV3LtV3HdV3P9d3ADd3Ijd3ETd3Mzd3CLd3Krd3Gbd3O7d3BHd3Jnd3FXd3N3d3DPd3Lvd3Hfd3P/T3AAz3Igz3EQz3Mwz3CIz3Koz3GYz3O4z3BEz3Jkz3FUz3N0z3DMz3Lsz3Hcz3P873AC73Ii/2vl3ipl3m5V3ilV3m113it13m9N3ijN3mzt3irt3m7d3ind3m393iv93m/D/igD/mwj/ioj/m4T/ikT/m0z/isz/m8L/iiL/myr/iqr/m6b/imb/m27/iu7/m+H/ihH/mxn/ipn/m5X/ilX/m13/it3/m9P/ijP/mzv/irv/m7f/inf/m3//ivAyT7r4AO5MAO4qAO5uAO4ZAO5dAO47AO5/CO4IiO5MiO4qiO5uiO4ZiO5diO47iO5/hO4IRO5MRO4qRO5uRO4ZRO5dRO47RO5/TO4IzO5MzO4qzO5uzO4ZzO5dzO47zO5/wu4IIu5MIu4qIu5uIu4ZIu5dIu47Iu5/Ku4H9c0ZVc2VVc1dVc3TVc07Vc23Vc1/Vc3w3c0I3c2E3c1M3c3C3c0q3c2m3c1u3c3h3c0Z3c2V3c1d3c3T3c073c233c1/3c3wM80IM82EM81MM83CM80qM82mM81uM83hM80ZM82VM81dM83TM807M823M81/M83wu80Iu82P96iZd6mZd7hVd6lVd7jdd6ndd7gzd6kzd7i7d6m7d7h3d6l3d7j/d6n/f7gA/6kA/7iI/6mI/7hE/6lE/7jM/6nM/7gi/6ki/7iq/6mq/7hm/6lm/7ju/6nu/7gR/6kR/7iZ/6mZ/7hV/6lV/7jd/6nd/7gz/6kz/7i7/6m7/7h3/6l3/7j/86QPL/CuhADuwgDupg/h9hF3Lj + + + + + AgAAAACAAADQdQAA5Q8AADAPAAA=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 + + + 0 + + + 1.0099504938 + + + + + + + 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YZc99vnDAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c3Pn4HOv/9LgEGGGGaEUcYY5zcTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz5/OOCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754dc/+CXAIEMMM8IoY4zzmwkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnz8ccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zw6//7JcAgQwwzwihjjPObCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfPxxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDPQH+AQYYYZoRRxhjnNxNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPn844JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvn5s8jxD38JMMgQw4wwyhjj/GaCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OcPBxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PpHvwQYZIhhRhhljHF+M8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvs84cDDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9+/eNfAgwyxDAjjDLGOL+ZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfb5wwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND/8s8gUYZIhhRhhljHF+M8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvs84cDDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnim58/C5z/5JcAgwwxzAijjDHObyaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPff5wwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDr3/6S4BBhhhmhFHGGOc3E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+fzjgkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eHXP/slwCBDDDPCKGOM85sJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58/HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88M8Cf4BBhhhmhFHGGOc3E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+fzjgkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eHXP/8lwCBDDDPCKGOM85sJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58/HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88Otf/BJgkCGGGWGUMcb5zQSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzx8OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3749S9/CTDIEMOMMMoY4/xmgkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjnDwcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/wT3BNgkCGGGWGUMcb5zQSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzx8OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3749a9+CTDIEMOMMMoY4/xmgkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjnDwcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/z6178EGGSIYUYYZYxxfjPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577POHAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffv2bXwIMMsQwI4wyxji/mWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32+cMBhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ//BPYFGGSIYUYYZYxxfjPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577POHAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffv3bXwIMMsQwI4wyxji/mWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32+cMBhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//t0vAQYZYpgRRhljnN9MMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvv84YBDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1///pcAgwwxzAijjDHObyaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPff5wwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDP0G9AQYZYpgRRhljnN9MMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvv84YBDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1//4ZcAgwwxzAijjDHObyaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPff5wwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDr//4S4BBhhhmhFHGGOc3E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+fzjgkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eHXf/olwCBDDDPCKGOM85sJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58/HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88E9Af4BBhhhmhFHGGOc3E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+fzjgkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eHX//9LgEGGGGaEUcYY5zcTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz5/OOCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754dd//iXAIEMMM8IoY4zzmwkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnz8ccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zw67/8EmCQIYYZYZQxxvnNBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPHw445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745ItvfvjnME+AQYYYZoRRxhjnNxNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPn844JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnh13/9JcAgQwwzwihjjPObCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfPxxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDrv/0SYJAhhhlhlDHG+c0Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8fDjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++PXffwkwyBDDjDDKGOP8ZoJJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY5w8HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/8c5AvwCBDDDPCKGOM85sJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58/HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88Ot//BJgkCGGGWGUMcb5zQSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzx8OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3749T9/CTDIEMOMMMoY4/xmgkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjnDwcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/z6X78EGGSIYUYYZYxxfjPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577POHAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psf/jnEG2CQIYYZYZQxxvnNBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPHw445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvj1v38JMMgQw4wwyhjj/GaCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OcPBxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//Po/vwQYZIhhRhhljHF+M8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvs84cDDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9+/d9fAgwyxDAjjDLGOL+ZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfb5wwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND79yv/w/dLzYyHicLcUhuAEAACBmQRAEQRAEQRAEQRAEd7OdbbbZZnd2ZzvbbLPNNtvczW7uThCEFwRBEARBEARBEARBEF4QBEEQBEEQhBf2ffP/5Q8WAv+/kMOOOOqY40446ZTTzjjrnPMuuOiSy6646prrbrjpltvuuOue+x546JF/PPbEU88898JLr7z2xlvvvPfBR5/867Mvvvrmux9++uW3P/5z4B98CzrksCOOOua4E0465bQzzjrnvAsuuuSyK6665robbrrltjvuuue+Bx565B+PPfHUM8+98NIrr73x1jvvffDRJ//67Iuvvvnuh59++e2P/xz4h9+CDjnsiKOOOe6Ek0457YyzzjnvgosuueyKq6657oabbrntjrvuue+Bhx75x2NPPPXMcy+89Mprb7z1znsffPTJvz774qtvvvvhp19+++M/B/6db0GHHHbEUcccd8JJp5x2xlnnnHfBRZdcdsVV11x3w0233HbHXffc98BDj/zjsSeeeua5F1565bU33nrnvQ8++uRfn33x1Tff/fDTL7/98Z8DxW9Bhxx2xFHHHHfCSaecdsZZ55x3wUWXXHbFVddcd8NNt9x2x1333PfAQ4/847EnnnrmuRdeeuW1N956570PPvrkX5998dU33/3w0y+//fGfA//ut6BDDjviqGOOO+GkU04746xzzrvgoksuu+Kqa6674aZbbrvjrnvue+ChR/7x2BNPPfPcCy+98tobb73z3gcfffKvz7746pvvfvjpl9/++M+Bf+9b0CGHHXHUMcedcNIpp51x1jnnXXDRJZddcdU1191w0y233XHXPfc98NAj/3jsiaeeee6Fl1557Y233nnvg48++ddnX3z1zXc//PTLb3/858A/+hZ0yGFHHHXMcSecdMppZ5x1znkXXHTJZVdcdc11N9x0y2133HXPfQ889Mg/HnviqWeee+GlV15746133vvgo0/+9dkXX33z3Q8//fLbH/85UPoWdMhhRxx1zHEnnHTKaWecdc55F1x0yWVXXHXNdTfcdMttd9x1z30PPPTIPx574qlnnnvhpVdee+Otd9774KNP/vXZF199890PP/3y2x//OfDvfws65LAjjjrmuBNOOuW0M84657wLLrrksiuuuua6G2665bY77rrnvgceeuQfjz3x1DPPvfDSK6+98dY7733w0Sf/+uyLr7757oeffvntj/8c+A++BR1y2BFHHXPcCSedctoZZ51z3gUXXXLZFVddc90NN91y2x133XPfAw898o/HnnjqmedeeOmV19546533Pvjok3999sVX33z3w0+//PbHfw78h9+CDjnsiKOOOe6Ek0457YyzzjnvgosuueyKq6657oabbrntjrvuue+Bhx75x2NPPPXMcy+89Mprb7z1znsffPTJvz774qtvvvvhp19+++M/B8rfgg457IijjjnuhJNOOe2Ms84574KLLrnsiquuue6Gm2657Y677rnvgYce+cdjTzz1zHMvvPTKa2+89c57H3z0yb8+++Krb7774adffvvjPwf+o29Bhxx2xFHHHHfCSaecdsZZ55x3wUWXXHbFVddcd8NNt9x2x1333PfAQ4/847EnnnrmuRdeeuW1N956570PPvrkX5998dU33/3w0y+//fGfA//xt6BDDjviqGOOO+GkU04746xzzrvgoksuu+Kqa6674aZbbrvjrnvue+ChR/7x2BNPPfPcCy+98tobb73z3gcfffKvz7746pvvfvjpl9/++M+B/+Rb0CGHHXHUMcedcNIpp51x1jnnXXDRJZddcdU1191w0y233XHXPfc98NAj/3jsiaeeee6Fl1557Y233nnvg48++ddnX3z1zXc//PTLb3/850DlW9Ahhx1x1DHHnXDSKaedcdY5511w0SWXXXHVNdfdcNMtt91x1z33PfDQI/947ImnnnnuhZdeee2Nt95574OPPvnXZ1989c13P/z0y29//OfAf/ot6JDDjjjqmONOOOmU084465zzLrjoksuuuOqa62646Zbb7rjrnvseeOiRfzz2xFPPPPfCS6+89sZb77z3wUef/OuzL7765rsffvrltz/+c+A/+xZ0yGFHHHXMcSecdMppZ5x1znkXXHTJZVdcdc11N9x0y2133HXPfQ889Mg/HnviqWeee+GlV15746133vvgo0/+9dkXX33z3Q8//fLbH/858J9/CzrksCOOOua4E0465bQzzjrnvAsuuuSyK6665robbrrltjvuuue+Bx565B+PPfHUM8+98NIrr73x1jvvffDRJ//67Iuvvvnuh59++e2P/xyofgs65LAjjjrmuBNOOuW0M84657wLLrrksiuuuua6G2665bY77rrnvgceeuQfjz3x1DPPvfDSK6+98dY7733w0Sf/+uyLr7757oeffvntj/8c+C++BR1y2BFHHXPcCSedctoZZ51z3gUXXXLZFVddc90NN91y2x133XPfAw898o/HnnjqmedeeOmV19546533Pvjok3999sVX33z3w0+//PbHfw78429Bhxx2xFHHHHfCSaecdsZZ55x3wUWXXHbFVddcd8NNt9x2x1333PfAQ4/847EnnnrmuRdeeuW1N956570PPvrkX5998dU33/3w0y+//fGfA//kW9Ahhx1x1DHHnXDSKaedcdY5511w0SWXXXHVNdfdcNMtt91x1z33PfDQI/947ImnnnnuhZdeee2Nt95574OPPvnXZ1989c13P/z0y29//OdA7VvQIYcdcdQxx51w0imnnXHWOeddcNEll11x1TXX3XDTLbfdcdc99z3w0CP/eOyJp5557oWXXnntjbfeee+Djz7512dffPXNdz/89Mtvf/znwH/5LeiQw4446pjjTjjplNPOOOuc8y646JLLrrjqmutuuOmW2+646577HnjokX889sRTzzz3wkuvvPbGW++898FHn/zrsy+++ua7H3765bc//nPgn34LOuSwI4465rgTTjrltDPOOue8Cy665LIrrrrmuhtuuuW2O+66574HHnrkH4898dQzz73w0iuvvfHWO+998NEn//rsi6+++e6Hn3757Y//HPhn34IOOeyIo4457oSTTjntjLPOOe+Ciy657Iqrrrnuhptuue2Ou+6574GHHvnHY0889cxzL7z0ymtvvPXOex989Mm/Pvviq2++++GnX3774z8H6t+CDjnsiKOOOe6Ek0457YyzzjnvgosuueyKq6657oabbrntjrvuue+Bhx75x2NPPPXMcy+89Mprb7z1znsffPTJvz774qtvvvvhp19+++M/B/6rb0GHHHbEUcccd8JJp5x2xlnnnHfBRZdcdsVV11x3w0233HbHXffc98BDj/zjsSeeeua5F1565bU33nrnvQ8++uRfn33x1Tff/fDTL7/98Z8D//W3oEMOO+KoY4474aRTTjvjrHPOu+CiSy674qprrrvhpltuu+Oue+574KFH/vHYE08989wLL73y2htvvfPeBx998q/Pvvjqm+9++OmX3/74z4F//i3okMOOOOqY40446ZTTzjjrnPMuuOiSy6646prrbrjpltvuuOue+x546JF/PPbEU88898JLr7z2xlvvvPfBR5/867Mvvvrmux9++uW3P/5zoPEt6JDDjjjqmONOOOmU084465zzLrjoksuuuOqa62646Zbb7rjrnvseeOiRfzz2xFPPPPfCS6+89sZb77z3wUef/OuzL7765rsffvrltz/+c+C/+RZ0yGFHHHXMcSecdMppZ5x1znkXXHTJZVdcdc11N9x0y2133HXPfQ889Mg/HnviqWeee+GlV15746133vvgo0/+9dkXX33z3Q8//fLbH/858N9+CzrksCOOOua4E0465bQzzjrnvAsuuuSyK6665robbrrltjvuuue+Bx565B+PPfHUM8+98NIrr73x1jvvffDRJ//67Iuvvvnuh59++e2P/xz4774FHXLYEUcdc9wJJ51y2hlnnXPeBRddctkVV11z3Q033XLbHXfdc98DDz3yj8eeeOqZ51546ZXX3njrnfc++OiTf332xVfffPfDT7/89sd/DjS/BR1y2BFHHXPcCSedctoZZ51z3gUXXXLZFVddc90NN91y2x133XPfAw898o/HnnjqmedeeOmV19546533Pvjok3999sVX33z3w0+//PbHfw7899+CDjnsiKOOOe6Ek0457YyzzjnvgosuueyKq6657oabbrntjrvuue+Bhx75x2NPPPXMcy+89Mprb7z1znsffPTJvz774qtvvvvhp19+++M/B/6Hb0GHHHbEUcccd8JJp5x2xlnnnHfBRZdcdsVV11x3w0233HbHXffc98BDj/zjsSeeeua5F1565bU33nrnvQ8++uRfn33x1Tff/fDTL7/98Z8D/+O3oEMOO+KoY4474aRTTjvjrHPOu+CiSy674qprrrvhpltuu+Oue+574KFH/vHYE08989wLL73y2htvvfPeBx998q/Pvvjqm+9++OmX3/74z4HWt6BDDjviqGOOO+GkU04746xzzrvgoksuu+Kqa6674aZbbrvjrnvue+ChR/7x2BNPPfPcCy+98tobb73z3gcfffKvz7746pvvfvjpl9/++M+B/+lb0CGHHXHUMcedcNIpp51x1jnnXXDRJZddcdU1191w0y233XHXPfc98NAj/3jsiaeeee6Fl1557Y233nnvg48++ddnX3z1zXc//PTLb3/858D//C3okMOOOOqY40446ZTTzjjrnPMuuOiSy6646prrbrjpltvuuOue+x546JF/PPbEU88898JLr7z2xlvvvPfBR5/867Mvvvrmux9++uW3P/5z4H/5FnTIYUccdcxxJ5x0ymlnnHXOeRdcdMllV1x1zXU33HTLbXfcdc99Dzz0yD8ee+KpZ5574aVXXnvjrXfe++CjT/712RdfffPdDz/98tsf/znQ/hZ0yGFHHHXMcSecdMppZ5x1znkXXHTJZVdcdc11N9x0y2133HXPfQ889Mg/HnviqWeee+GlV15746133vvgo0/+9dkXX33z3Q8//fLbH/858L9+CzrksCOOOua4E0465bQzzjrnvAsuuuSyK6665robbrrltjvuuue+Bx565B+PPfHUM8+98NIrr73x1jvvffDRJ//67Iuvvvnuh59++e2P/xz4374FHXLYEUcdc9wJJ51y2hlnnXPeBRddctkVV11z3Q033XLbHXfdc98DDz3yj8eeeOqZ51546ZXX3njrnfc++OiTf332xVfffPfDT7/89sd/Dvzv34IOOeyIo4457oSTTjntjLPOOe+Ciy657Iqrrrnuhptuue2Ou+6574GHHvnHY0889cxzL7z0ymtvvPXOex989Mm/Pvviq2++++GnX3774z8HOt+CDjnsiKOOOe6Ek0457YyzzjnvgosuueyKq6657oabbrntjrvuue+Bhx75x2NPPPXMcy+89Mprb7z1znsffPTJvz774qtvvvvhp19+++M/B/6Pb0GHHHbEUcccd8JJp5x2xlnnnHfBRZdcdsVV11x3w0233HbHXffc98BDj/zjsSeeeua5F1565bU33nrnvQ8++uRfn33x1Tff/fDTL7/98Z8D/+e3oEMOO+KoY4474aRTTjvjrHPOu+CiSy674qprrrvhpltuu+Oue+574KFH/vHYE08989wLL73y2htvvfPeBx998q/Pvvjqm+9++OmX3/74z4H/61vQIYcdcdQxx51w0imnnXHWOeddcNEll11x1TXX3XDTLbfdcdc99z3w0CP/eOyJp5557oWXXnntjbfeee+Djz7512dffPXNdz/89Mtvf/znQPdb0CGHHXHUMcedcNIpp51x1jnnXXDRJZddcdU1191w0y233XHXPfc98NAj/3jsiaeeee6Fl1557Y233nnvg48++ddnX3z1zXc//PTLb3/858C/+BZ0yGFHHHXMcSecdMppZ5x1znkXXHTJZVdcdc11N9x0y2133HXPfQ889Mg/HnviqWeee+GlV15746133vvgo0/+9dkXX33z3Q8//fLbH/858C+/BR1y2BFHHXPcCSedctoZZ51z3gUXXXLZFVddc90NN91y2x133XPfAw898o/HnnjqmedeeOmV19546533Pvjok3999sVX33z3w0+//PbHfw7839+CDjnsiKOOOe6Ek0457YyzzjnvgosuueyKq6657oabbrntjrvuue+Bhx75x2NPPPXMcy+89Mprb7z1znsffPTJvz774qtvvvvhp19+++M/B3rfgg457IijjjnuhJNOOe2Ms84574KLLrnsiquuue6Gm2657Y677rnvgYce+cdjTzz1zHMvvPTKa2+89c57H3z0yb8+++Krb7774adffvvjPwf+n29Bhxx2xFHHHHfCSaecdsZZ55x3wUWXXHbFVddcd8NNt9x2x1333PfAQ4/847EnnnrmuRdeeuW1N956570PPvrkX5998dU33/3w0y+//fGfA//qW9Ahhx1x1DHHnXDSKaedcdY5511w0SWXXXHVNdfdcNMtt91x1z33PfDQI/947ImnnnnuhZdeee2Nt95574OPPvnXZ1989c13P/z0y29//OfA//st6JDDjjjqmONOOOmU084465zzLrjoksuuuOqa62646Zbb7rjrnvseeOiRfzz2xFPPPPfCS6+89sZb77z3wUef/OuzL7765rsffvrltz/+c6D/LeiQw4446pjjTjjplNPOOOuc8y646JLLrrjqmutuuOmW2+646577HnjokX889sRTzzz3wkuvvPbGW++898FHn/zrsy+++ua7H3765bc//nPgX38LOuSwI4465rgTTjrltDPOOue8Cy665LIrrrrmuhtuuuW2O+66574HHnrkH4898dQzz73w0iuvvfHWO+998NEn//rsi6+++e6Hn3757Y//HPg334IOOeyIo4457oSTTjntjLPOOe+Ciy657Iqrrrnuhptuue2Ou+6574GHHvnHY0889cxzL7z0ymtvvPXOex989Mm/Pvviq2++++GnX3774z8H/u23oEMOO+KoY4474aRTTjvjrHPOu+CiSy674qprrrvhpltuu+Oue+574KFH/vHYE08989wLL73y2htvvfPeBx998q/Pvvjqm+9++OmX3/74z4HBt/8PdlHZBHicLcVxnAOKQADgo8niaLI4miyOJoujyeJosjiaLI4mi6PJYjRZHE3mvb1nz5tnGIZLp1YunVq5NLWyNLVy6dTKpVMrl6ZWlk6tXPj92vf98wVqa/8v6HWHHPaGI4560zHHveWEk952ymnvOOOsd51z3nsuuOiSy65431XXXHfDTbfcdscHPnTXRz52zyfue+ChRx771Gee+NwXnvrSM8+98JWXvvba61YFHPS6Qw57wxFHvemY495ywklvO+W0d5xx1rvOOe89F1x0yWVXvO+qa6674aZbbrvjAx+66yMfu+cT9z3w0COPfeozT3zuC0996ZnnXvjKS1977YZVAQe97pDD3nDEUW865ri3nHDS20457R1nnPWuc857zwUXXXLZFe+76prrbrjpltvu+MCH7vrIx+75xH0PPPTIY5/6zBOf+8JTX3rmuRe+8tLXXrtxVcBBrzvksDcccdSbjjnuLSec9LZTTnvHGWe965zz3nPBRZdcdsX7rrrmuhtuuuW2Oz7wobs+8rF7PnHfAw898tinPvPE577w1Jeeee6Fr7z0tdfqqwIOet0hh73hiKPedMxxbznhpLedcto7zjjrXeec954LLrrksived9U1191w0y233fGBD931kY/d84n7Hnjokcc+9ZknPveFp770zHMvfOWlr71206qAg153yGFvOOKoNx1z3FtOOOltp5z2jjPOetc5573ngosuueyK9111zXU33HTLbXd84EN3feRj93zivgceeuSxT33mic994akvPfPcC1956Wuv3bwq4KDXHXLYG4446k3HHPeWE0562ymnveOMs951znnvueCiSy674n1XXXPdDTfdctsdH/jQXR/52D2fuO+Bhx557FOfeeJzX3jqS88898JXXvraa69fFXDQ6w457A1HHPWmY457ywknve2U095xxlnvOue891xw0SWXXfG+q6657oabbrntjg986K6PfOyeT9z3wEOPPPapzzzxuS889aVnnnvhKy997bXGqoCDXnfIYW844qg3HXPcW0446W2nnPaOM8561znnveeCiy657Ir3XXXNdTfcdMttd3zgQ3d95GP3fOK+Bx565LFPfeaJz33hqS8989wLX3npa6/dsirgoNcdctgbjjjqTccc95YTTnrbKae944yz3nXOee+54KJLLrvifVddc90NN91y2x0f+NBdH/nYPZ+474GHHnnsU5954nNfeOpLzzz3wlde+tprb1gVcNDrDjnsDUcc9aZjjnvLCSe97ZTT3nHGWe8657z3XHDRJZdd8b6rrrnuhptuue2OD3zoro987J5P3PfAQ4889qnPPPG5Lzz1pWeee+ErL33ttVtXBRz0ukMOe8MRR73pmOPecsJJbzvltHeccda7zjnvPRdcdMllV7zvqmuuu+GmW2674wMfuusjH7vnE/c98NAjj33qM0987gtPfemZ5174yktfe625KuCg1x1y2BuOOOpNxxz3lhNOetspp73jjLPedc5577ngoksuu+J9V11z3Q033XLbHR/40F0f+dg9n7jvgYceeexTn3nic1946kvPPPfCV1762mtvXBVw0OsOOewNRxz1pmOOe8sJJ73tlNPeccZZ7zrnvPdccNEll13xvquuue6Gm2657Y4PfOiuj3zsnk/c98BDjzz2qc888bkvPPWlZ5574Ssvfe2121YFHPS6Qw57wxFHvemY495ywklvO+W0d5xx1rvOOe89F1x0yWVXvO+qa6674aZbbrvjAx+66yMfu+cT9z3w0COPfeozT3zuC0996ZnnXvjKS1977U2rAg563SGHveGIo950zHFvOeGkt51y2jvOOOtd55z3ngsuuuSyK9531TXX3XDTLbfd8YEP3fWRj93zifseeOiRxz71mSc+94WnvvTMcy985aWvvdZaFXDQ6w457A1HHPWmY457ywknve2U095xxlnvOue891xw0SWXXfG+q6657oabbrntjg986K6PfOyeT9z3wEOPPPapzzzxuS889aVnnnvhKy997bU3rwo46HWHHPaGI4560zHHveWEk952ymnvOOOsd51z3nsuuOiSy65431XXXHfDTbfcdscHPnTXRz52zyfue+ChRx771Gee+NwXnvrSM8+98JWXvvbaW1YFHPS6Qw57wxFHvemY495ywklvO+W0d5xx1rvOOe89F1x0yWVXvO+qa6674aZbbrvjAx+66yMfu+cT9z3w0COPfeozT3zuC0996ZnnXvjKS1977a2rAg563SGHveGIo950zHFvOeGkt51y2jvOOOtd55z3ngsuuuSyK9531TXX3XDTLbfd8YEP3fWRj93zifseeOiRxz71mSc+94WnvvTMcy985aWvvdZeFXDQ6w457A1HHPWmY457ywknve2U095xxlnvOue891xw0SWXXfG+q6657oabbrntjg986K6PfOyeT9z3wEOPPPapzzzxuS889aVnnnvhKy997bW3rQo46HWHHPaGI4560zHHveWEk952ymnvOOOsd51z3nsuuOiSy65431XXXHfDTbfcdscHPnTXRz52zyfue+ChRx771Gee+NwXnvrSM8+98JWXvvZXffu3r76Dg76z7+q7Oex7+t6+j6O+vx/oBznuh/rhfoSTfrQf68c57Sf6yX6Ks366n+lnOe/n+vl+gYt+sV/ql7niV/rVfo1rvtE3+xY3/Sa/xW9zx+/2e/xed/0+v98fcM8f9If8YQ/8EX/UH/PYH/cn/ElP/Cl/2p/x1J/15/x5z/0Ff9Ff8tJf9ld8u3esDviOvpPv4pDv7nv4Xo74vr6fH+CYH+yH+GFO+JF+lB/jlB/vJ/hJzvipfpqf4Zyf7ef4eS74hX6RX+KyX+5X+FWu+rW+wTe54Vt9m9/stt/hd/nnfOhf9C/7V3zsX/dv+rfc9+/69/0HHvmP/af+M5/5L/3X/htf+O/9j/4nz/yv/nf/h6/83/5f/5/XOqu+zl/vb/C6v9Hf5G/2hr/F3+pv86a/3d/h7/SWv8vf7e/xtr/X3+fv945/wD/oH/Kuf9g/4h/1nn/MP+6fcMk/6Z/yT3vfP+Of9etc9+v9Br/RLb/Vb/c7feCf9y/4l3zkX/Wv+Td84t/27/j3PPQf+o/8Jz71n/sv/Fc+99/67/wPvvQ/+1/8b174P/1f/h9f+6u+/TtX38FB39l39d0c9j19b9/HUd/fD/SDHPdD/XA/wkk/2o/145z2E/1kP8VZP93P9LOc93P9fL/ARb/YL/XLXPEr/Wq/xjXf6Jt9i5t+k9/it7njd/s9fq+7fp/f7w+45w/6Q/6wB/6IP+qPeeyP+xP+pCf+lD/tz3jqz/pz/rzn/oK/6C956S/7K77du1YHfEffyXdxyHf3PXwvR3xf388PcMwP9kP8MCf8SD/Kj3HKj/cT/CRn/FQ/zc9wzs/2c/w8F/xCv8gvcdkv9yv8Klf9Wt/gm9zwrb7Nb3bbXwMukFCt + + + AQAAAACAAAAHJwAAJQAAAA==eJztwaEBAAAMAqC04v8H7weTAUgAAAAAAAAAAAAoHBMecq9+rg== + + + + + diff --git a/mesh-doctor/tests/test_convertMD2SG.py b/mesh-doctor/tests/test_convertMD2SG.py new file mode 100644 index 00000000..3c3bfe4f --- /dev/null +++ b/mesh-doctor/tests/test_convertMD2SG.py @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. +# SPDX-FileContributor: GitHub Copilot, Jacques Franc +import argparse + +from geos.mesh_doctor.parsing.convertMD2SGParsing import convert, fillSubparser +from geos.mesh_doctor.actions.convertMD2SG import Result, action + + +def test_convert_md2sg_parser() -> None: + """Test the convertMD2SG parser and conversion function.""" + parser = argparse.ArgumentParser( description='Testing.' ) + subparsers = parser.add_subparsers() + fillSubparser( subparsers ) + + args = parser.parse_args( [ 'convertMD2SG', '-i', 'mesh-doctor/tests/data/base_tetra_shift.vtm', '-z', '2' ] ) + + options = convert( vars( args ) ) + assert options.attrs == ( 2, ) + assert options.skipCleanCollocated is False + assert options.skipFilterVolumeCells is False + assert options.meshVtkOutput.output == "converted.vtu" + + +def test_convertion() -> None: + """Test the convertMD2SG action.""" + parser = argparse.ArgumentParser( description='Testing.' ) + subparsers = parser.add_subparsers() + fillSubparser( subparsers ) + + args = parser.parse_args( [ + 'convertMD2SG', '-i', 'mesh-doctor/tests/data/base_tetra_shift.vtm', '-z', '2', '--outputFile', 'converted.vtu' + ] ) + + options = convert( vars( args ) ) + actionsResult = action( vars( args )[ 'vtuInputFile' ], options ) + assert isinstance( actionsResult, Result ) + assert actionsResult.outputMesh is not None + assert actionsResult.nCleanCollocated != 0 + assert actionsResult.outputMesh.GetNumberOfCells() > 0 + assert actionsResult.outputMesh.GetPointData().HasArray( "faultNodes_0" ) + assert actionsResult.outputMesh.GetPointData().GetArray( "faultNodes_0" ).GetRange() == ( 0.0, 1.0 ) + + +def test_convertion_cc() -> None: + """Test the convertMD2SG action from vtu file with multiple connected components.""" + parser = argparse.ArgumentParser( description='Testing.' ) + subparsers = parser.add_subparsers() + fillSubparser( subparsers ) + + args = parser.parse_args( [ + 'convertMD2SG', '-i', 'mesh-doctor/tests/data/base_hexa_shift_2.vtu', '-z', '2', '3', '--outputFile', + 'converted_cc.vtu', '--skipCleanCollocated' + ] ) + + options = convert( vars( args ) ) + actionsResult = action( vars( args )[ 'vtuInputFile' ], options ) + assert isinstance( actionsResult, Result ) + assert actionsResult.outputMesh is not None + assert actionsResult.nCleanCollocated == 0 + assert actionsResult.outputMesh.GetNumberOfCells() > 0 + assert actionsResult.outputMesh.GetPointData().HasArray( "faultNodes_0" ) + assert actionsResult.outputMesh.GetPointData().GetArray( "faultNodes_0" ).GetRange() == ( 0.0, 1.0 ) + assert actionsResult.outputMesh.GetPointData().HasArray( "faultNodes_1" ) + assert actionsResult.outputMesh.GetPointData().GetArray( "faultNodes_1" ).GetRange() == ( 0.0, 1.0 ) From f354581a18b6a61c714299d14ed8710741d8057f Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 29 May 2026 15:50:46 +0000 Subject: [PATCH 05/10] Apply jafranc review comments on PR#251 (euler surface) - Add SetRegionIdAssignmentMode(CELL_COUNT_DESCENDING) after SetExtractionModeToAllRegions() in __countConnectedComponents so regions are ordered largest-first (suggestion on line 154). - Add comment that GetConnectivityArray/GetOffsetsArray require VTK 9+ (comment on line 233). - Store non-manifold edge point-id pairs in SurfaceComponent and display them (up to 10) in the results output so users know exactly where non-manifold edges are located (question on line 249). https://claude.ai/code/session_01GwpNNFQRPhb26XMCFHJtts --- mesh-doctor/src/geos/mesh_doctor/actions/euler.py | 9 +++++++-- mesh-doctor/src/geos/mesh_doctor/parsing/eulerParsing.py | 7 +++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/mesh-doctor/src/geos/mesh_doctor/actions/euler.py b/mesh-doctor/src/geos/mesh_doctor/actions/euler.py index b72504ab..92d5a129 100644 --- a/mesh-doctor/src/geos/mesh_doctor/actions/euler.py +++ b/mesh-doctor/src/geos/mesh_doctor/actions/euler.py @@ -52,6 +52,7 @@ class SurfaceComponent: numBoundaryEdges: int numNonManifoldEdges: int interpretation: str + nonManifoldEdgeEndpoints: tuple[ tuple[ int, int ], ...] = field( default_factory=tuple ) @dataclass( frozen=True ) @@ -152,6 +153,7 @@ def __countConnectedComponents( mesh: vtk.vtkUnstructuredGrid ) -> int: cf = vtk.vtkConnectivityFilter() cf.SetInputData( mesh ) cf.SetExtractionModeToAllRegions() + cf.SetRegionIdAssignmentMode( vtk.vtkConnectivityFilter.CELL_COUNT_DESCENDING ) cf.ColorRegionsOn() cf.Update() return cf.GetNumberOfExtractedRegions() @@ -229,6 +231,7 @@ def __surfaceComponentsFromColored( colored: vtk.vtkUnstructuredGrid ) -> list[ """Compute (V, E, F, chi, boundary, non-manifold) per RegionId of a colored 2D mesh.""" rid = vtk_to_numpy( colored.GetCellData().GetArray( "RegionId" ) ).astype( np.int64 ) cells = colored.GetCells() + # GetConnectivityArray / GetOffsetsArray require VTK 9+ conn = vtk_to_numpy( cells.GetConnectivityArray() ).astype( np.int64, copy=False ) off = vtk_to_numpy( cells.GetOffsetsArray() ).astype( np.int64, copy=False ) @@ -251,7 +254,8 @@ def __surfaceComponentsFromColored( colored: vtk.vtkUnstructuredGrid ) -> list[ E = len( edgeCount ) F = int( len( sel ) ) bE = sum( 1 for c in edgeCount.values() if c == 1 ) - nm = sum( 1 for c in edgeCount.values() if c > 2 ) + nmEdges = tuple( ek for ek, c in edgeCount.items() if c > 2 ) + nm = len( nmEdges ) chi = V - E + F components.append( SurfaceComponent( componentId=int( regionId ), @@ -262,7 +266,8 @@ def __surfaceComponentsFromColored( colored: vtk.vtkUnstructuredGrid ) -> list[ eulerCharacteristic=chi, numBoundaryEdges=bE, numNonManifoldEdges=nm, - interpretation=__interpretSurface( chi, bE, nm ) ) ) + interpretation=__interpretSurface( chi, bE, nm ), + nonManifoldEdgeEndpoints=nmEdges ) ) return components diff --git a/mesh-doctor/src/geos/mesh_doctor/parsing/eulerParsing.py b/mesh-doctor/src/geos/mesh_doctor/parsing/eulerParsing.py index 1ad7dcfa..ba51d96e 100644 --- a/mesh-doctor/src/geos/mesh_doctor/parsing/eulerParsing.py +++ b/mesh-doctor/src/geos/mesh_doctor/parsing/eulerParsing.py @@ -131,6 +131,13 @@ def __displaySurfaceGroup( g: SurfaceGroup ) -> None: setupLogger.results( " " + f"{c.componentId:>5} {c.numCells:>9,} {c.numVertices:>8,} {c.numEdges:>8,} " f"{c.numFaces:>8,} {c.eulerCharacteristic:>5} {c.numBoundaryEdges:>6,} " f"{c.numNonManifoldEdges:>4,} {c.interpretation}" ) + if c.nonManifoldEdgeEndpoints: + _MAX_DISPLAY = 10 + shown = c.nonManifoldEdgeEndpoints[ :_MAX_DISPLAY ] + setupLogger.results( f" non-manifold edge endpoints (point id pairs): " + + ", ".join( f"({a},{b})" for a, b in shown ) + + ( f" … (+{len(c.nonManifoldEdgeEndpoints)-_MAX_DISPLAY} more)" + if len( c.nonManifoldEdgeEndpoints ) > _MAX_DISPLAY else "" ) ) if len( g.components ) > 1: setupLogger.results( f" WARNING: {len(g.components)} components — verify isolated cells" ) From 50386f52587c993da88f67288e1f8e084e2c3e61 Mon Sep 17 00:00:00 2001 From: Jacques Franc <49998870+jafranc@users.noreply.github.com> Date: Fri, 29 May 2026 19:13:01 +0200 Subject: [PATCH 06/10] Update eulerParsing.py --- mesh-doctor/src/geos/mesh_doctor/parsing/eulerParsing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesh-doctor/src/geos/mesh_doctor/parsing/eulerParsing.py b/mesh-doctor/src/geos/mesh_doctor/parsing/eulerParsing.py index ba51d96e..7af5061e 100644 --- a/mesh-doctor/src/geos/mesh_doctor/parsing/eulerParsing.py +++ b/mesh-doctor/src/geos/mesh_doctor/parsing/eulerParsing.py @@ -134,7 +134,7 @@ def __displaySurfaceGroup( g: SurfaceGroup ) -> None: if c.nonManifoldEdgeEndpoints: _MAX_DISPLAY = 10 shown = c.nonManifoldEdgeEndpoints[ :_MAX_DISPLAY ] - setupLogger.results( f" non-manifold edge endpoints (point id pairs): " + setupLogger.results( " non-manifold edge endpoints (point id pairs): " + ", ".join( f"({a},{b})" for a, b in shown ) + ( f" … (+{len(c.nonManifoldEdgeEndpoints)-_MAX_DISPLAY} more)" if len( c.nonManifoldEdgeEndpoints ) > _MAX_DISPLAY else "" ) ) From ad3e13ae46ff1fcbdf11ba2167a06cd5114bf0a7 Mon Sep 17 00:00:00 2001 From: jafranc Date: Mon, 1 Jun 2026 08:53:02 +0200 Subject: [PATCH 07/10] revert ascending order --- mesh-doctor/src/geos/mesh_doctor/actions/euler.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mesh-doctor/src/geos/mesh_doctor/actions/euler.py b/mesh-doctor/src/geos/mesh_doctor/actions/euler.py index 92d5a129..d69bee6c 100644 --- a/mesh-doctor/src/geos/mesh_doctor/actions/euler.py +++ b/mesh-doctor/src/geos/mesh_doctor/actions/euler.py @@ -153,7 +153,6 @@ def __countConnectedComponents( mesh: vtk.vtkUnstructuredGrid ) -> int: cf = vtk.vtkConnectivityFilter() cf.SetInputData( mesh ) cf.SetExtractionModeToAllRegions() - cf.SetRegionIdAssignmentMode( vtk.vtkConnectivityFilter.CELL_COUNT_DESCENDING ) cf.ColorRegionsOn() cf.Update() return cf.GetNumberOfExtractedRegions() From 77468f67dd3f6fb73bedf37f83f58c6211a7345d Mon Sep 17 00:00:00 2001 From: jafranc Date: Mon, 1 Jun 2026 09:31:55 +0200 Subject: [PATCH 08/10] adding a toGlobalEdgeId helper --- mesh-doctor/src/geos/mesh_doctor/actions/euler.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/mesh-doctor/src/geos/mesh_doctor/actions/euler.py b/mesh-doctor/src/geos/mesh_doctor/actions/euler.py index d69bee6c..ce998d2d 100644 --- a/mesh-doctor/src/geos/mesh_doctor/actions/euler.py +++ b/mesh-doctor/src/geos/mesh_doctor/actions/euler.py @@ -225,6 +225,16 @@ def __interpretSurface( chi: int, boundaryEdges: int, nonManifoldEdges: int ) -> return f"surface with multiple boundaries / holes (chi={chi})" return f"open (chi={chi}, unusual)" +def _toGlobalEdgeId( mesh: vtk.vtkUnstructuredGrid, edge: tuple[ int, int ] ) -> tuple[ int, int ]: + """Return a global edge ID for a pair of point IDs.""" + p0, p1 = edge + ids = mesh.GetPointData().GetGlobalIds() + if ids is not None: + ids = vtk_to_numpy( ids ).astype( np.int64, copy=False ) + return ( ids[p0], ids[p1] ) + else: + setupLogger.warning( f"No globalIds found. Falling back to local id for non-manifold edge detection.", stacklevel=2 ) + return edge def __surfaceComponentsFromColored( colored: vtk.vtkUnstructuredGrid ) -> list[ SurfaceComponent ]: """Compute (V, E, F, chi, boundary, non-manifold) per RegionId of a colored 2D mesh.""" @@ -253,7 +263,7 @@ def __surfaceComponentsFromColored( colored: vtk.vtkUnstructuredGrid ) -> list[ E = len( edgeCount ) F = int( len( sel ) ) bE = sum( 1 for c in edgeCount.values() if c == 1 ) - nmEdges = tuple( ek for ek, c in edgeCount.items() if c > 2 ) + nmEdges = tuple( _toGlobalEdgeId( colored, ek ) for ek, c in edgeCount.items() if c > 2 ) nm = len( nmEdges ) chi = V - E + F components.append( From 8440ff09c558e7352b7a89a576d88cf9cf429c0e Mon Sep 17 00:00:00 2001 From: Jacques Franc <49998870+jafranc@users.noreply.github.com> Date: Mon, 1 Jun 2026 16:18:53 +0200 Subject: [PATCH 09/10] Update euler.py --- mesh-doctor/src/geos/mesh_doctor/actions/euler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesh-doctor/src/geos/mesh_doctor/actions/euler.py b/mesh-doctor/src/geos/mesh_doctor/actions/euler.py index ce998d2d..808e828f 100644 --- a/mesh-doctor/src/geos/mesh_doctor/actions/euler.py +++ b/mesh-doctor/src/geos/mesh_doctor/actions/euler.py @@ -233,7 +233,7 @@ def _toGlobalEdgeId( mesh: vtk.vtkUnstructuredGrid, edge: tuple[ int, int ] ) -> ids = vtk_to_numpy( ids ).astype( np.int64, copy=False ) return ( ids[p0], ids[p1] ) else: - setupLogger.warning( f"No globalIds found. Falling back to local id for non-manifold edge detection.", stacklevel=2 ) + setupLogger.warning( "No globalIds found. Falling back to local id for non-manifold edge detection.", stacklevel=2 ) return edge def __surfaceComponentsFromColored( colored: vtk.vtkUnstructuredGrid ) -> list[ SurfaceComponent ]: From cb5f6ddd176ae4bd2d5eaeb390a85f998c84bf13 Mon Sep 17 00:00:00 2001 From: jacques franc Date: Tue, 2 Jun 2026 08:43:15 +0200 Subject: [PATCH 10/10] yapf --- mesh-doctor/src/geos/mesh_doctor/actions/euler.py | 7 +++++-- mesh-doctor/src/geos/mesh_doctor/parsing/eulerParsing.py | 8 ++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/mesh-doctor/src/geos/mesh_doctor/actions/euler.py b/mesh-doctor/src/geos/mesh_doctor/actions/euler.py index 808e828f..8da86e29 100644 --- a/mesh-doctor/src/geos/mesh_doctor/actions/euler.py +++ b/mesh-doctor/src/geos/mesh_doctor/actions/euler.py @@ -225,17 +225,20 @@ def __interpretSurface( chi: int, boundaryEdges: int, nonManifoldEdges: int ) -> return f"surface with multiple boundaries / holes (chi={chi})" return f"open (chi={chi}, unusual)" + def _toGlobalEdgeId( mesh: vtk.vtkUnstructuredGrid, edge: tuple[ int, int ] ) -> tuple[ int, int ]: """Return a global edge ID for a pair of point IDs.""" p0, p1 = edge ids = mesh.GetPointData().GetGlobalIds() if ids is not None: ids = vtk_to_numpy( ids ).astype( np.int64, copy=False ) - return ( ids[p0], ids[p1] ) + return ( ids[ p0 ], ids[ p1 ] ) else: - setupLogger.warning( "No globalIds found. Falling back to local id for non-manifold edge detection.", stacklevel=2 ) + setupLogger.warning( "No globalIds found. Falling back to local id for non-manifold edge detection.", + stacklevel=2 ) return edge + def __surfaceComponentsFromColored( colored: vtk.vtkUnstructuredGrid ) -> list[ SurfaceComponent ]: """Compute (V, E, F, chi, boundary, non-manifold) per RegionId of a colored 2D mesh.""" rid = vtk_to_numpy( colored.GetCellData().GetArray( "RegionId" ) ).astype( np.int64 ) diff --git a/mesh-doctor/src/geos/mesh_doctor/parsing/eulerParsing.py b/mesh-doctor/src/geos/mesh_doctor/parsing/eulerParsing.py index 7af5061e..d6bbbf2e 100644 --- a/mesh-doctor/src/geos/mesh_doctor/parsing/eulerParsing.py +++ b/mesh-doctor/src/geos/mesh_doctor/parsing/eulerParsing.py @@ -134,10 +134,10 @@ def __displaySurfaceGroup( g: SurfaceGroup ) -> None: if c.nonManifoldEdgeEndpoints: _MAX_DISPLAY = 10 shown = c.nonManifoldEdgeEndpoints[ :_MAX_DISPLAY ] - setupLogger.results( " non-manifold edge endpoints (point id pairs): " - + ", ".join( f"({a},{b})" for a, b in shown ) - + ( f" … (+{len(c.nonManifoldEdgeEndpoints)-_MAX_DISPLAY} more)" - if len( c.nonManifoldEdgeEndpoints ) > _MAX_DISPLAY else "" ) ) + setupLogger.results( " non-manifold edge endpoints (point id pairs): " + ", ".join( f"({a},{b})" + for a, b in shown ) + + ( f" … (+{len(c.nonManifoldEdgeEndpoints)-_MAX_DISPLAY} more)" + if len( c.nonManifoldEdgeEndpoints ) > _MAX_DISPLAY else "" ) ) if len( g.components ) > 1: setupLogger.results( f" WARNING: {len(g.components)} components — verify isolated cells" )