diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index 154d462..790ed16 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -1,8 +1,8 @@
-FROM mcr.microsoft.com/devcontainers/base:bullseye
+FROM dolfinx/dolfinx:v0.7.0
# FROM mcr.microsoft.com/devcontainers/base:jammy
-
ARG DEBIAN_FRONTEND=noninteractive
-ARG USER=vscode
+# RUN useradd -ms /bin/bash vscode
+# ARG USER=vscode
RUN DEBIAN_FRONTEND=noninteractive \
&& apt-get update \
@@ -28,9 +28,11 @@ RUN DEBIAN_FRONTEND=noninteractive \
# Python and poetry installation
USER $USER
ARG HOME="/home/$USER"
-ARG PYTHON_VERSION=3.11
-# ARG PYTHON_VERSION=3.10
+# Don't change. Dolfinx in the base image is only compiled with 3.10
+ARG PYTHON_VERSION=3.10
+
+# Use poetry pyenv
ENV PYENV_ROOT="${HOME}/.pyenv"
ENV PATH="${PYENV_ROOT}/shims:${PYENV_ROOT}/bin:${HOME}/.local/bin:$PATH"
@@ -42,4 +44,4 @@ RUN echo "done 0" \
&& pyenv global ${PYTHON_VERSION} \
&& echo "done 3" \
&& curl -sSL https://install.python-poetry.org | python3 - \
- && poetry config virtualenvs.in-project true
\ No newline at end of file
+ && poetry config virtualenvs.in-project true
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 6e4cfad..f4f842a 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -11,19 +11,24 @@
// "forwardPorts": [],
// ๐ Use 'postCreateCommand' to run commands after the container is created.
- "postCreateCommand": "poetry install --with dev --no-interaction",
+ "postCreateCommand": "bash .devcontainer/postCreate.sh",
// ๐ Configure tool-specific properties.
"customizations": {
"vscode": {
- "extensions":["ms-python.python", "njpwerner.autodocstring"]
+ "extensions":[
+ "ms-python.python",
+ "njpwerner.autodocstring",
+ "ms-python.autopep8",
+ "ms-toolsai.jupyter",
+ "ms-python.vscode-pylance",
+ "ms-azuretools.vscode-docker"
+ ]
}
},
"features": {
- "ghcr.io/devcontainers/features/git-lfs:1": {
- "autoPull": true,
- "version": "latest"
- }
+ "ghcr.io/devcontainers/features/git-lfs:1": {},
+ "ghcr.io/devcontainers/features/docker-in-docker:2": {}
}
// ๐ Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
diff --git a/.devcontainer/postCreate.sh b/.devcontainer/postCreate.sh
new file mode 100644
index 0000000..af415a5
--- /dev/null
+++ b/.devcontainer/postCreate.sh
@@ -0,0 +1,2 @@
+poetry install --with dev --no-interaction
+poetry run pip install petsc4py==3.20.0 mpi4py==3.1.5 https://github.com/FEniCS/ufl/archive/refs/tags/2023.2.0.zip https://github.com/FEniCS/ffcx/archive/v0.7.0.zip https://github.com/FEniCS/basix/archive/v0.7.0.zip
\ No newline at end of file
diff --git a/.gitattributes b/.gitattributes
index ea9598d..6b03da5 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,2 +1 @@
-*.gri filter=lfs diff=lfs merge=lfs -text
-*.png filter=lfs diff=lfs merge=lfs -text
+*.gri *.png filter=lfs diff=lfs merge=lfs -text
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index b51e845..aed70ee 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -5,6 +5,7 @@ name: docs
on:
workflow_dispatch:
+ workflow_call:
push:
branches: [ main ]
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
new file mode 100644
index 0000000..15666ba
--- /dev/null
+++ b/.github/workflows/publish.yml
@@ -0,0 +1,64 @@
+# This workflows will upload a Python Package using Twine when a release is created
+# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
+
+name: build
+
+on:
+ workflow_dispatch:
+
+jobs:
+ test3d:
+ uses: equinor/warmth/.github/workflows/python-test-3d.yml@main
+ with:
+ event_type: ${{ github.event_name}}
+ action_type: ${{ github.event.action}}
+ test1d:
+ uses: equinor/warmth/.github/workflows/python-test.yml@main
+ with:
+ event_type: ${{ github.event_name}}
+ action_type: ${{ github.event.action}}
+ snyk:
+ uses: equinor/warmth/.github/workflows/snyk.yml@main
+ docs:
+ uses: equinor/warmth/.github/workflows/docs.yml@main
+
+ deploy:
+ needs: [test3d, test1d, snyk, docs]
+ environment: deploy
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ ref: 'master'
+ fetch-depth: 0
+
+ - name: Set up Python
+ uses: actions/setup-python@v2
+ with:
+ python-version: '3.11'
+
+ - name: Azure key vault login
+ uses: Azure/login@v1
+ with:
+ client-id: ${{ secrets.AZURE_CLIENT_ID }}
+ tenant-id: ${{ secrets.AZURE_TENANT_ID }}
+ subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
+
+ - name: Fetch secrets
+ uses: azure/CLI@v1
+ with:
+ azcliversion: 2.42.0
+ inlineScript: |
+ echo PYPI_TOKEN=$(az keyvault secret show --vault-name PSSCloudDev --name PYPI-Token --query value -o tsv) >> $GITHUB_ENV
+
+ - name: Install dependencies
+ run: |
+ curl -sSL https://install.python-poetry.org | python3
+ poetry install --with dev --no-interaction
+
+ - name: Build and publish
+ run: |
+ poetry config pypi-token.pypi ${{ env.PYPI_TOKEN }}
+ poetry build
+ poetry publish
\ No newline at end of file
diff --git a/.github/workflows/python-test-3d.yml b/.github/workflows/python-test-3d.yml
new file mode 100644
index 0000000..dc02aae
--- /dev/null
+++ b/.github/workflows/python-test-3d.yml
@@ -0,0 +1,40 @@
+# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
+# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
+
+name: Tests3D
+
+on:
+ workflow_call:
+ inputs:
+ event_type:
+ required: true
+ type: string
+ action_type:
+ required: true
+ type: string
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Run
+ uses: tj-actions/docker-run@v2
+ with:
+ image: dolfinx/dolfinx:v0.7.0
+ name: dolfinx
+ options: -v ${{ github.workspace }}:/warmth
+ args: |
+ cd /warmth
+ pip install .
+ pip install pytest==7.4.2 pytest-cov==4.1.0
+ pytest --cov-report=term-missing --cov=warmth/3d tests/3d | tee pytest-coverage.txt
+
+
+ - name: Comment coverage
+ if: ${{ github.event_name == 'pull_request' && github.event.action == 'opened' }}
+ uses: coroo/pytest-coverage-commentator@v1.0.2
+ with:
+ pytest-coverage: pytest-coverage.txt
diff --git a/.github/workflows/python-test.yml b/.github/workflows/python-test.yml
index 0d50f8d..5168f78 100644
--- a/.github/workflows/python-test.yml
+++ b/.github/workflows/python-test.yml
@@ -2,47 +2,72 @@
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
name: Tests
-
+
on:
+ workflow_call:
+ inputs:
+ event_type:
+ required: true
+ type: string
+ action_type:
+ required: true
+ type: string
workflow_dispatch:
push:
- branches: [ main, dev ]
+ branches: [main, dev]
pull_request:
- branches: [ main , dev ]
+ branches: [main, dev]
jobs:
build:
-
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ['3.10','3.11']
+ python-version: ["3.10", "3.11"]
steps:
- - uses: actions/checkout@v2
- - name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v2
- with:
- python-version: ${{ matrix.python-version }}
-
- - name: Install dependencies
- run: |
- curl -sSL https://install.python-poetry.org | python3
- poetry install --with dev --no-interaction
-
- - name: Lint with flake8
- run: |
- # stop the build if there are Python syntax errors or undefined names
- poetry run flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics --exclude=docs
- # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
- poetry run flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --exclude=docs
-
- - name: Test with pytest
- run: |
- poetry run pytest --cov-report=term-missing --cov=warmth tests/ | tee pytest-coverage.txt
-
- - name: Comment coverage
- if: ${{ github.event_name == 'pull_request' && github.event.action == 'opened' }}
- uses: coroo/pytest-coverage-commentator@v1.0.2
- with:
- pytest-coverage: pytest-coverage.txt
+ - uses: actions/checkout@v2
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v2
+ with:
+ python-version: ${{ matrix.python-version }}
+
+ - name: Install dependencies
+ run: |
+ curl -sSL https://install.python-poetry.org | python3
+ poetry install --with dev --no-interaction
+
+ - name: Lint with flake8
+ run: |
+ # stop the build if there are Python syntax errors or undefined names
+ poetry run flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics --exclude=docs
+ # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
+ poetry run flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --exclude=docs
+
+ - name: Test with pytest
+ run: |
+ poetry run pytest --cov-report=term-missing --ignore=tests/3d --cov=warmth tests/ | tee pytest-coverage.txt
+
+ - name: Comment coverage
+ if: ${{ github.event_name == 'pull_request' && github.event.action == 'opened' }}
+ uses: coroo/pytest-coverage-commentator@v1.0.2
+ with:
+ pytest-coverage: pytest-coverage.txt
+
+ - name: check_3d_modified
+ uses: dorny/paths-filter@v2
+ id: filter3d
+ with:
+ filters: |
+ mesh3d:
+ - 'warmth/3d/**'
+ outputs:
+ filter3d: ${{ steps.filter3d.outputs.mesh3d }}
+
+ test3d:
+ needs: [build]
+ uses: equinor/warmth/.github/workflows/python-test-3d.yml@main
+ if: ${{ needs.build.outputs.filter3d }} == 'true'
+ with:
+ event_type: ${{ github.event_name}}
+ action_type: ${{ github.event.action}}
diff --git a/.github/workflows/snyk.yml b/.github/workflows/snyk.yml
new file mode 100644
index 0000000..59918e5
--- /dev/null
+++ b/.github/workflows/snyk.yml
@@ -0,0 +1,23 @@
+name: Snyk scan
+on:
+ push:
+ branches: [main, dev]
+ pull_request:
+ branches: [main, dev]
+ workflow_call:
+jobs:
+ security:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@master
+ - name: Run Snyk to check for vulnerabilities
+ uses: snyk/actions/python-3.10@master
+ continue-on-error: false
+ env:
+ SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
+ with:
+ args: --sarif-file-output=snyk.sarif --severity-threshold=high
+ - name: Upload result to GitHub Code Scanning
+ uses: github/codeql-action/upload-sarif@v2
+ with:
+ sarif_file: snyk.sarif
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 7877cef..188248e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -62,4 +62,8 @@ exec11/
exec12/
exec13/
-docs/_build
\ No newline at end of file
+docs/_build
+
+*.c
+*.o
+*.so
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 04b38ef..e80c786 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -89,7 +89,7 @@ Standard acronyms to start the commit message with are:
```
API: an (incompatible) API change (will be rare)
PERF: performance or bench-marking
- BLD: change related to building xtgeo
+ BLD: change related to building
BUG: bug fix
FIX: fixes wrt to technical issues, e.g. wrong requirements.txt
DEP: deprecate something, or remove a deprecated object
@@ -98,7 +98,7 @@ Standard acronyms to start the commit message with are:
CLN: code cleanup, maintenance commit (refactoring, typos, PEP, etc.)
REV: revert an earlier commit
TST: addition or modification of tests
- REL: related to releasing xtgeo
+ REL: related to release
```
## Type hints
diff --git a/docs/notebooks/3D_simulation.ipynb b/docs/notebooks/3D_simulation.ipynb
new file mode 100644
index 0000000..5d71c12
--- /dev/null
+++ b/docs/notebooks/3D_simulation.ipynb
@@ -0,0 +1,344 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import warmth\n",
+ "from pathlib import Path"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.03"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "1e-6*30e3"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.03"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "30e-3"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "maps_dir = Path(\"./data/\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model = warmth.Model()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "inputs = model.builder.input_horizons_template"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#Add surface grids to the table. You can use other method as well\n",
+ "inputs.loc[0]=[0,\"0.gri\",None,\"Onlap\"]\n",
+ "inputs.loc[1]=[66,\"66.gri\",None,\"Onlap\"]\n",
+ "inputs.loc[2]=[100,\"100.gri\",None,\"Onlap\"]\n",
+ "inputs.loc[3]=[163,\"163.gri\",None,\"Erosive\"]\n",
+ "inputs.loc[4]=[168,\"168.gri\",None,\"Erosive\"]\n",
+ "inputs.loc[5]=[170,\"170.gri\",None,\"Onlap\"]\n",
+ "inputs.loc[6]=[182,\"182.gri\",None,\"Erosive\"]\n",
+ "model.builder.input_horizons=inputs\n",
+ "inputs"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "inc = 2000\n",
+ "model.builder.define_geometry(maps_dir/\"0.gri\",xinc=inc,yinc=inc,fformat=\"irap_binary\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model.builder.grid.__dict__"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model.builder.extract_nodes(4,maps_dir)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model.parameters.time_start"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from warmth.data import haq87\n",
+ "model.builder.set_eustatic_sea_level(haq87)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for i in model.builder.iter_node():\n",
+ " i.rift=[[182,175]]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model.simulator.simulate_every = 1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model.builder.n_valid_node"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model.builder.node"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model.builder.iter_node()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "NameError",
+ "evalue": "name 'model' is not defined",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
+ "\u001b[1;32m/workspaces/warmth/docs/notebooks/3D_simulation.ipynb Cell 14\u001b[0m line \u001b[0;36m1\n\u001b[0;32m----> 1\u001b[0m \u001b[39mfor\u001b[39;00m i \u001b[39min\u001b[39;00m model\u001b[39m.\u001b[39mbuilder\u001b[39m.\u001b[39mnode:\n\u001b[1;32m 2\u001b[0m \u001b[39mprint\u001b[39m(i)\n",
+ "\u001b[0;31mNameError\u001b[0m: name 'model' is not defined"
+ ]
+ }
+ ],
+ "source": [
+ "for i in model.builder.node:\n",
+ " print(i)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%time\n",
+ "model.simulator.run(save=True,purge=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n",
+ "# interpolate and extrapolate the missing nodes\n",
+ "# find nearby nodes from the array indexer_full_sim, which is sorted by x-index\n",
+ "import itertools\n",
+ "from subsheat3D.fixed_mesh_model import interpolateNode\n",
+ "for ni in range(len(model.builder.nodes)):\n",
+ " for nj in range(len(model.builder.nodes[ni])):\n",
+ " if model.builder.nodes[ni][nj] is False:\n",
+ " closest_x_up = []\n",
+ " for j in range(ni,len(model.builder.nodes[nj])):\n",
+ " matching_x = [ i[0] for i in model.builder.indexer_full_sim if i[0]==j ]\n",
+ " closest_x_up = closest_x_up + list(set(matching_x))\n",
+ " if len(matching_x)>0:\n",
+ " break\n",
+ " closest_x_down = []\n",
+ " for j in range(ni-1,-1,-1):\n",
+ " matching_x = [ i[0] for i in model.builder.indexer_full_sim if i[0]==j ]\n",
+ " closest_x_down = closest_x_down + list(set(matching_x))\n",
+ " if len(matching_x)>0:\n",
+ " break\n",
+ " closest_y_up = []\n",
+ " for j in range(nj,len(model.builder.nodes[ni])):\n",
+ " matching_y = [ i[1] for i in model.builder.indexer_full_sim if (i[1]==j and ((i[0] in closest_x_up) or i[0] in closest_x_down)) ]\n",
+ " closest_y_up = closest_y_up + list(set(matching_y))\n",
+ " if len(matching_y)>0:\n",
+ " break\n",
+ " closest_y_down = []\n",
+ " for j in range(nj-1,-1,-1):\n",
+ " matching_y = [ i[1] for i in model.builder.indexer_full_sim if (i[1]==j and (i[0] in closest_x_up or i[0] in closest_x_down) ) ]\n",
+ " closest_y_down = closest_y_down + list(set(matching_y))\n",
+ " if len(matching_y)>0:\n",
+ " break\n",
+ "\n",
+ " interpolationNodes = [ model.builder.nodes[i[0]][i[1]] for i in itertools.product(closest_x_up+closest_x_down, closest_y_up+closest_y_down) ]\n",
+ " interpolationNodes = [nn for nn in interpolationNodes if nn is not False]\n",
+ " node = interpolateNode(interpolationNodes)\n",
+ " node.X, node.Y = model.builder.grid.location_grid[ni,nj,:]\n",
+ " model.builder.nodes[ni][nj] = node\n",
+ " else:\n",
+ " node = interpolateNode([model.builder.nodes[ni][nj]]) # \"interpolate\" the node from itself to make sure the same member variables exist at the end\n",
+ " model.builder.nodes[ni][nj] = node\n",
+ " # if (model.builder.nodes[ni][nj].Y>12000):\n",
+ " # model.builder.nodes[ni][nj].crustRHP = (2e-6) * 4\n",
+ " # model.builder.nodes[ni][nj].rhp = (2e-6) * 4\n",
+ " model.builder.nodes[ni][nj].crustRHP = (2e0) * 1\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Rebuild/reload mesh at tti= 182\n",
+ "Using 1D Node parameters NodeParameters1D(shf=0.03, hc=30000.0, hw=3600.0, hLith=130000.0, kLith=3.109, kCrust=2.5, kAsth=100, rhp=2, crustliquid=2500.0, crustsolid=2800.0, lithliquid=2700.0, lithsolid=3300.0, asthliquid=2700.0, asthsolid=3200.0, T0=5, Tm=1330.0, qbase=0.03)\n",
+ "builing\n",
+ "buildVertices\n"
+ ]
+ },
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mThe Kernel crashed while executing code in the the current cell or a previous cell. Please review the code in the cell(s) to identify a possible cause of the failure. Click here for more info. View Jupyter log for further details."
+ ]
+ }
+ ],
+ "source": [
+ "from warmth.mesh_model import run\n",
+ "import os\n",
+ "try:\n",
+ " os.mkdir('mesh')\n",
+ "except FileExistsError:\n",
+ " pass\n",
+ "try:\n",
+ " os.mkdir('temp')\n",
+ "except FileExistsError:\n",
+ " pass\n",
+ "run(model,start_time=model.parameters.time_start,end_time=0)\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": ".venv",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.13"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/notebooks/Build_within_Python.ipynb b/docs/notebooks/Build_within_Python.ipynb
index cd9ccf1..56fef24 100644
--- a/docs/notebooks/Build_within_Python.ipynb
+++ b/docs/notebooks/Build_within_Python.ipynb
@@ -9,7 +9,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 1,
"metadata": {
"scrolled": true
},
@@ -24,7 +24,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
@@ -33,7 +33,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
@@ -62,9 +62,177 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 4,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/workspaces/warmth/warmth/build.py:199: FutureWarning: In a future version, the Index constructor will not infer numeric dtypes when passed object-dtype sequences (matching Series behavior)\n",
+ " check_ascending = df.apply(lambda x: x.is_monotonic_increasing)\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " top | \n",
+ " topage | \n",
+ " k_cond | \n",
+ " rhp | \n",
+ " phi | \n",
+ " decay | \n",
+ " solidus | \n",
+ " liquidus | \n",
+ " base | \n",
+ " baseage | \n",
+ " thickness | \n",
+ " grain_thickness | \n",
+ " phi_mean | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 152.0 | \n",
+ " 0 | \n",
+ " 1.500000 | \n",
+ " 2.301755e-09 | \n",
+ " 0.620000 | \n",
+ " 0.500 | \n",
+ " 2720.0 | \n",
+ " 2448.0 | \n",
+ " 810.0 | \n",
+ " 20 | \n",
+ " 658.0 | \n",
+ " 0.310357 | \n",
+ " 0.528332 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 810.0 | \n",
+ " 20 | \n",
+ " 1.538462 | \n",
+ " 2.079433e-09 | \n",
+ " 0.599730 | \n",
+ " 0.490 | \n",
+ " 2708.0 | \n",
+ " 2437.2 | \n",
+ " 1608.0 | \n",
+ " 66 | \n",
+ " 798.0 | \n",
+ " 0.511062 | \n",
+ " 0.359571 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 1608.0 | \n",
+ " 66 | \n",
+ " 1.500000 | \n",
+ " 2.301755e-09 | \n",
+ " 0.200000 | \n",
+ " 0.500 | \n",
+ " 2720.0 | \n",
+ " 2448.0 | \n",
+ " 1973.0 | \n",
+ " 100 | \n",
+ " 365.0 | \n",
+ " 0.332780 | \n",
+ " 0.088275 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 1973.0 | \n",
+ " 100 | \n",
+ " 1.500000 | \n",
+ " 2.301755e-09 | \n",
+ " 0.620000 | \n",
+ " 0.500 | \n",
+ " 2720.0 | \n",
+ " 2448.0 | \n",
+ " 2262.0 | \n",
+ " 145 | \n",
+ " 289.0 | \n",
+ " 0.221878 | \n",
+ " 0.232256 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 2262.0 | \n",
+ " 145 | \n",
+ " 1.500000 | \n",
+ " 2.301755e-09 | \n",
+ " 0.620000 | \n",
+ " 0.500 | \n",
+ " 2720.0 | \n",
+ " 2448.0 | \n",
+ " 2362.0 | \n",
+ " 152 | \n",
+ " 100.0 | \n",
+ " 0.078943 | \n",
+ " 0.210571 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 2362.0 | \n",
+ " 152 | \n",
+ " 1.904762 | \n",
+ " 4.719506e-10 | \n",
+ " 0.447705 | \n",
+ " 0.415 | \n",
+ " 2618.0 | \n",
+ " 2356.2 | \n",
+ " 2427.0 | \n",
+ " 160 | \n",
+ " 65.0 | \n",
+ " 0.053525 | \n",
+ " 0.176536 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " top topage k_cond rhp phi decay solidus liquidus \\\n",
+ "0 152.0 0 1.500000 2.301755e-09 0.620000 0.500 2720.0 2448.0 \n",
+ "1 810.0 20 1.538462 2.079433e-09 0.599730 0.490 2708.0 2437.2 \n",
+ "2 1608.0 66 1.500000 2.301755e-09 0.200000 0.500 2720.0 2448.0 \n",
+ "3 1973.0 100 1.500000 2.301755e-09 0.620000 0.500 2720.0 2448.0 \n",
+ "4 2262.0 145 1.500000 2.301755e-09 0.620000 0.500 2720.0 2448.0 \n",
+ "5 2362.0 152 1.904762 4.719506e-10 0.447705 0.415 2618.0 2356.2 \n",
+ "\n",
+ " base baseage thickness grain_thickness phi_mean \n",
+ "0 810.0 20 658.0 0.310357 0.528332 \n",
+ "1 1608.0 66 798.0 0.511062 0.359571 \n",
+ "2 1973.0 100 365.0 0.332780 0.088275 \n",
+ "3 2262.0 145 289.0 0.221878 0.232256 \n",
+ "4 2362.0 152 100.0 0.078943 0.210571 \n",
+ "5 2427.0 160 65.0 0.053525 0.176536 "
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"node =warmth.single_node()\n",
"node.sediments_inputs = node_template\n",
@@ -73,7 +241,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
@@ -83,11 +251,11 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
- "node.shf = 60e-3\n",
+ "node.crustRHP = 2e-6 \n",
"node.qbase = 30e-3\n",
"node.rift = np.array([[160,145]])\n",
"#node.paleoWD=np.array([200]) # Only for mulit rift"
@@ -95,7 +263,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
@@ -104,7 +272,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
@@ -114,9 +282,18 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 9,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "CPU times: user 612 ms, sys: 0 ns, total: 612 ms\n",
+ "Wall time: 624 ms\n"
+ ]
+ }
+ ],
"source": [
"%%time\n",
"model.simulator.run(parallel=False)\n"
@@ -124,18 +301,48 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 10,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array([1.24])"
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"model.builder.nodes[0][0].beta"
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 11,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/workspaces/warmth/warmth/postprocessing.py:199: RuntimeWarning: invalid value encountered in divide\n",
+ " v=-1*initial_poro/initial_decay*phi1\n"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "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nOvk5ISqqirU1tbC3Nz8ttfMnz8fGzduREJCAs6cOdPsfGVlJSZOnIiJEyfim2++gbOzMzIyMjBx4kTU1tZqXVtSUgI/P7+7tJqIDImPloiow+rfvz8uX74MX19f+Pv7a72sra1v+z39+vUD0LDOy508/vjjuHjxIkJDQ7V6V5pcvXoVxcXFWLduHUaNGoWgoKBmA32bXLp0CREREa1vHBHpBYMMEXVYzz//PEpKSjBz5kycPXsWKSkp+OOPPzBv3jyoVKrbfo+zszP69++PY8eO3fG+Dg4OyM3NxYEDB2573tvbG+bm5vjoo4+QmpqKXbt24c0332x23fXr15GdnY3x48fr1kAiajMGGSLqsDw8PHD8+HGoVCpMmDABYWFhWLJkCezt7SEW3/nH19///nd88803d723vb39HXt1nJ2dsW3bNnz//fcIDg7GunXr8M477zS77rvvvsOECRPg4+PTuoYRkd6IBEEQjF0EEZE+VVdXo3fv3tixYweGDRtmkPeora1FQEAAvv32W4wYMcIg70FE98YeGSLqdKysrPDVV1/ddeG8tsrIyMD//d//McQQGRl7ZIiIiMhksUeGiIiITBaDDBEREZksBhkiIiIyWQwyREREZLIYZIiIiMhkMcgQERGRyWKQISIiIpPFIENEREQmi0GGiIiITNb/A/DDw1bnn5FcAAAAAElFTkSuQmCC",
+ "text/plain": [
+ "