Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Oscillations like fortran #42

Merged
merged 35 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
02e6192
Introduce the typo to porosity diffusion coefficient and set Phis to 0.8
EmiliaJarochowska Jun 11, 2024
fac6d43
With these settings marlpde will integrate to about 54% of 250 ka, i.…
HannoSpreeuw Jul 4, 2024
d44c1fb
Need this to be able to plot. Implicit solvers work and should be mor…
HannoSpreeuw Jul 15, 2024
a9691a1
outt and outx are redundant. They are remnants from the original Pyth…
HannoSpreeuw Jul 15, 2024
e9274ec
Try to find oscillations without the typo.
HannoSpreeuw Jul 15, 2024
f5e57d3
Revert "There are no bottom boundary conditions for CA and CC in equa…
HannoSpreeuw Jul 15, 2024
c27524b
_apply_operator (with leading underscore) is deprecated.
HannoSpreeuw Jul 15, 2024
3503581
250_000 is perhaps easier to read.
HannoSpreeuw Jul 15, 2024
c1d98ae
The typo in the porososity diffusion coefficient is applied here and …
HannoSpreeuw Jul 16, 2024
73b91b4
In the py-pde documentation there is a mention of 'adjacent_value' as…
HannoSpreeuw Jul 17, 2024
2f422c6
Want to rerun with the 'curvature=0' 'seems reasonable' ad-hoc bottom…
HannoSpreeuw Jul 19, 2024
24cd1b5
Curious to see what we end up with in terms of oscillations if impose…
HannoSpreeuw Jul 19, 2024
7e73aa7
xcem and xcemf are probably remnants from the original Python datacla…
HannoSpreeuw Jul 19, 2024
05ae980
Checking if a large grid with a curvature=0 ad-hoc bottom boundary co…
HannoSpreeuw Jul 19, 2024
0bd4d02
See if we can find a configuration - i.e. a combination of initial co…
HannoSpreeuw Jul 20, 2024
fe26b5f
'git status' shows changes in launch.json from vscode. Anything relat…
HannoSpreeuw Jul 25, 2024
c9a34ff
This should be (one of) the last commit(s) before merging with main. …
HannoSpreeuw Jul 25, 2024
1a0a4a3
Merge branch 'main' into Oscillations_like_Fortran
HannoSpreeuw Jul 25, 2024
743838d
'TkAgg' caused CI build problems : ImportError: Cannot load backend '…
HannoSpreeuw Jul 25, 2024
c57a6e3
Merge branch 'Oscillations_like_Fortran' of github.com:astro-turing/I…
HannoSpreeuw Jul 25, 2024
bd58ea6
Typo
HannoSpreeuw Jul 25, 2024
9747fa5
Lines should not exceed 80 characters.
HannoSpreeuw Jul 25, 2024
2b6b82e
The integration time is really an arbitrary value and up to the user.…
HannoSpreeuw Jul 25, 2024
d366191
For the users it is helpful to know that this value should be entered…
HannoSpreeuw Jul 25, 2024
8b63469
This line is needed because the default values for Phi0 and PhiIni ha…
HannoSpreeuw Jul 25, 2024
b6b3df0
This should clarify the setting of some solver variables. Arguments l…
HannoSpreeuw Aug 2, 2024
cd364b7
The solver method applied in solve_ivp should be set in parameters.py…
HannoSpreeuw Aug 2, 2024
78c5c87
The 'method' keyword for eq.solve will break the call to 'solve' if a…
HannoSpreeuw Aug 2, 2024
4b4b9ea
The default settings don't reproduce fig. 3 anymore
EmiliaJarochowska Aug 5, 2024
be3e6af
Trying to fix '..../site-packages/jupyter_client/connect.py:22: Depre…
HannoSpreeuw Aug 5, 2024
725db90
This commit tries to fix problems emerging from incompatible user cho…
HannoSpreeuw Aug 5, 2024
f5c8023
This commit has everything to do with the previous commit: if e.g. th…
HannoSpreeuw Aug 5, 2024
6a7ca7b
Now that the call to integrate_equations has three dicts as arguments…
HannoSpreeuw Aug 5, 2024
43a27de
Not sure why this is needed, possibly because of commit 4b4b9ea243fce…
HannoSpreeuw Aug 5, 2024
1286b70
Implementation of a Jacobian sparsity matrix for the 'Radau' and 'BDF…
HannoSpreeuw Aug 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ __pycache__
*.npy
.*.swp
Results
.vscode
.vscode/*.json
*.lock
26 changes: 0 additions & 26 deletions .vscode/launch.json

This file was deleted.

20 changes: 0 additions & 20 deletions .vscode/settings.json

This file was deleted.

2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ python marlpde/Evolve_scenario.py
```
Results in the form of an .hdf5 file will be stored in a subdirectory of a `Results` directory, which will be in the root folder of the cloned repo.

After two minutes you should see plots similar to figure 3e from [L'Heureux (2018)](https://www.hindawi.com/journals/geofluids/2018/4968315/).

### Alternative: poetry
If you prefer [`poetry`](https://python-poetry.org/) over `pipenv`, you may install all the dependencies and activate the environment using the command `poetry install`. Next, either:

Expand Down
29 changes: 20 additions & 9 deletions marlpde/Evolve_scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def integrate_equations(**kwargs):
'''
This function retrieves the parameters of the Scenario to be simulated and
the solution parameters for the integration. It then integrates the five
partial differential equations form L'Heureux, stores and returns the
partial differential equations from L'Heureux, stores and returns the
solution, to be used for plotting.
'''

Expand Down Expand Up @@ -93,16 +93,27 @@ def integrate_equations(**kwargs):
else:
data_tracker = None

sol, info = eq.solve(state, t_range=End_time, dt=dt, \
solver=kwargs["solver"], scheme=kwargs["scheme"],\
tracker=["progress", \
storage.tracker(kwargs["progress_tracker_interval"]),\
live_plots, data_tracker], \
backend=kwargs["backend"], ret_info=kwargs["retinfo"],\
adaptive=kwargs["adaptive"])
if kwargs["solver"]=='scipy':
sol, info = eq.solve(state, t_range=End_time, dt=dt,
solver='scipy', method=kwargs["method"],
lband=kwargs["lband"], uband=kwargs["uband"],
tracker=["progress", storage.tracker(
kwargs["progress_tracker_interval"]),
live_plots, data_tracker],
backend=kwargs["backend"],
ret_info=kwargs["retinfo"])
else:
sol, info = eq.solve(state, t_range=End_time, dt=dt,
solver=kwargs["solver"], scheme=kwargs["scheme"],
tracker=["progress", storage.tracker(
kwargs["progress_tracker_interval"]),
live_plots, data_tracker],
backend=kwargs["backend"],
ret_info=kwargs["retinfo"],\
adaptive=kwargs["adaptive"])

print()
print(f"Meta-information about the solution : {info}")
print(f"Meta-information about the solution : {info}\n")

covered_time_span = Tstar * info["controller"]["t_final"]

Expand Down
42 changes: 22 additions & 20 deletions marlpde/LHeureux_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,8 @@ def __init__(self, AragoniteSurface, CalciteSurface, CaSurface,
self.CaSurface = CaSurface
self.CO3Surface = CO3Surface
self.PorSurface = PorSurface
# There are no bottom boundary conditions for CA and CC in equations
# 35 from L'Heureux, but py-pde demands left and right boundary
# conditions. This means that '"curvature" : 0' is a dummy boundary
# condition. We will make sure that it does not leak into our
# integration, by using only backward differencing for the spatial
# derivatives in the right-hand sides of the time derivative equations
# for CA and CC.
self.bc_CA = [{"value": CA0}, {"value" : 1e99}]
self.bc_CC = [{"value": CC0}, {"value": 1e99}]
self.bc_CA = [{"value": CA0}, {"curvature": 0}]
self.bc_CC = [{"value": CC0}, {"curvature": 0}]
self.bc_cCa = [{"value": cCa0}, {"derivative": 0}]
self.bc_cCO3 = [{"value": cCO30}, {"derivative": 0}]
self.bc_Phi = [{"value": Phi0}, {"derivative": 0}]
Expand Down Expand Up @@ -87,6 +80,7 @@ def __init__(self, AragoniteSurface, CalciteSurface, CaSurface,
self.F_fixed = 1 - np.exp(10 - 10 / self.PhiIni)
self.dPhi_fixed = self.auxcon * self.F_fixed *\
self.PhiIni ** 3 / (1 - self.PhiIni)


def get_state(self, AragoniteSurface, CalciteSurface, CaSurface, CO3Surface,
PorSurface):
Expand Down Expand Up @@ -167,13 +161,18 @@ def evolution_rate(self, state, t=0):
one_minus_Phi = 1 - Phi
U = self.presum + self.rhorat * Phi ** 3 * F /one_minus_Phi

# Enforce no bottom boundary condition for CA and CC by using
# backwards differencing only.
# Choose either forward or backward differencing for CA and CC
# depending on the sign of U

CA_grad_back = CA.apply_operator("grad_back", self.bc_CA)
CA_grad = CA_grad_back
CA_grad_forw = CA.apply_operator("grad_forw", self.bc_CA)
CA_grad = ScalarField(state.grid, np.where(U.data>0, CA_grad_back.data, \
CA_grad_forw.data))

CC_grad_back = CC.apply_operator("grad_back", self.bc_CC)
CC_grad = CC_grad_back
CC_grad_forw = CC.apply_operator("grad_forw", self.bc_CC)
CC_grad = ScalarField(state.grid, np.where(U.data>0, CC_grad_back.data, \
CC_grad_forw.data))

W = self.presum - self.rhorat * Phi ** 2 * F

Expand Down Expand Up @@ -269,11 +268,10 @@ def _make_pde_rhs_numba(self, state):
Peclet_min = self.Peclet_min
Peclet_max = self.Peclet_max
delta_x = state.grid._axes_coords[0][1] - state.grid._axes_coords[0][0]

# Enforce no bottom boundary condition for CA and CC by using
# backwards differencing only.
grad_back_CA = state.grid.make_operator("grad_back", bc = self.bc_CA)
grad_forw_CA = state.grid.make_operator("grad_forw", bc = self.bc_CA)
grad_back_CC = state.grid.make_operator("grad_back", bc = self.bc_CC)
grad_forw_CC = state.grid.make_operator("grad_forw", bc = self.bc_CC)
grad_back_cCa = state.grid.make_operator("grad_back", bc = self.bc_cCa)
grad_forw_cCa = state.grid.make_operator("grad_forw", bc = self.bc_cCa)
laplace_cCa = state.grid.make_operator("laplace", bc = self.bc_cCa)
Expand All @@ -292,9 +290,11 @@ def pde_rhs(state_data, t=0):
# either one of them, based on the sign of U.
CA = state_data[0]
CA_grad_back = grad_back_CA(CA)
CA_grad_forw = grad_forw_CA(CA)

CC = state_data[1]
CC_grad_back = grad_back_CC(CC)
CC_grad_forw = grad_forw_CC(CC)

cCa = state_data[2]
cCa_grad_back = grad_back_cCa(cCa)
Expand Down Expand Up @@ -348,10 +348,12 @@ def pde_rhs(state_data, t=0):

U[i] = presum + rhorat * Phi[i] ** 3 * F[i]/ (1 - Phi[i])

# Enforce no bottom boundary condition for CA and CC by using
# backwards differencing only.
CA_grad[i] = CA_grad_back[i]
CC_grad[i] = CC_grad_back[i]
if U[i] > 0:
CA_grad[i] = CA_grad_back[i]
CC_grad[i] = CC_grad_back[i]
else:
CA_grad[i] = CA_grad_forw[i]
CC_grad[i] = CC_grad_forw[i]

W[i] = presum - rhorat * Phi[i] ** 2 * F[i]

Expand Down
33 changes: 18 additions & 15 deletions marlpde/parameters.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# ~\~ language=Python filename=marlpde/marlpde.py
# ~\~ begin <<lit/python-interface.md|marlpde/marlpde.py>>[init]
# import numpy
import configparser
from pathlib import Path
from dataclasses import (dataclass, asdict, make_dataclass, fields)
Expand Down Expand Up @@ -39,17 +36,15 @@ class Scenario:
S: quantity = 0.1 * u.cm / u.a
# cAthy: quantity = 0.1 * u.dimensionless
phiinf: quantity = 0.01 * u.dimensionless
phi0: quantity = 0.6 * u.dimensionless
phi0: quantity = 0.8 * u.dimensionless
ca0: quantity = 0.326e-3 * u.M
co30: quantity = 0.326e-3 * u.M
ccal0: quantity = 0.3 * u.dimensionless
cara0: quantity = 0.6 * u.dimensionless
xdis: quantity = 50.0 * u.cm # x_d (start of dissolution zone)
xcem: quantity = -100.0 * u.cm
xcemf: quantity = 1000.0 * u.cm
length: quantity = 500.0 * u.cm
Th: quantity = 100.0 * u.cm # h_d (height of dissolution zone)
phi00: quantity = 0.5 * u.dimensionless
phi00: quantity = 0.8 * u.dimensionless
ca00: quantity = 0.326e-3 * u.M # sqrt(Kc) / 2
co300: quantity = 0.326e-3 * u.M # sqrt(Kc) / 2
ccal00: quantity = 0.3 * u.dimensionless
Expand Down Expand Up @@ -155,24 +150,32 @@ class Solver:
So parameters like time interval, time step and tolerance.
'''
dt: float = 1.e-6
# T* is more suitable as a default value
# than the original value (100_000 years).
tmax: float = Map_Scenario().Tstar
# timesteps in between writing.
# tmax is the integration time in years.
tmax: int = Map_Scenario().Tstar
N: int = 200
solver: str = "explicit"
scheme: str = "rk"
solver: str = "scipy"
# Beware that "scheme" and "adaptive" will only be propagated if you have
# chosen py-pde's native "explicit" solver above.
scheme: str = "euler"
adaptive: bool = True
# solve_ivp from scipy offers six methods. They can be set here.
method: str = "LSODA"
# Setting lband and uband for method="LSODA" leads to tremendous performance
# increase. See Scipy's solve_ivp documentation for background. Consider it
# equivalent to providing a sparsity matrix for the "Radau" and "BDF"
# implicit methods.
lband: int = 1
uband: int = 1
backend: str = "numba"
retinfo: bool = True
adaptive: bool = True

@dataclass
class Tracker:
'''
Initialises all the tracking parameters, such as tracker interval.
Also indicates the quantities to be tracked, as boolean values.
'''
progress_tracker_interval: float = 0.01
progress_tracker_interval: float = Solver().tmax/ 100 / Map_Scenario().Tstar
live_plotting: bool = False
plotting_interval: str = '0:05'
data_tracker_interval: float = 0.01
Expand Down
6 changes: 3 additions & 3 deletions tests/Regression_test/test_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ def test_integration_Scenario_A():
# dict containing the solver parameters (such as required tolerance).
# The ground truth data were generated with PhiNR=Phi0. In this codebase
# that was later changed to PhiNR=PhiIni, to comply with the L'Heureux
# paper, so we need to reapply the old condition PhiNR=Phi0 to arrive at the
# ground truth data.
# paper, so we need to reapply the old condition PhiNR=Phi0 to arrive at
# the ground truth data.
all_kwargs = asdict(Map_Scenario()) | asdict(Solver()) | \
asdict(Tracker()) | {"PhiNR": 0.6}
asdict(Tracker()) | {"Phi0": 0.6, "PhiIni": 0.5, "PhiNR": 0.6}
# integrate_equations returns four variables, we only need the first one.
solution, _, _, _, _ = \
integrate_equations(**all_kwargs)
Expand Down
Loading