Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 6 additions & 3 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Add GLMakie/XFVB dependencies
run: sudo apt-get update && sudo apt-get install -y xorg-dev mesa-utils xvfb libgl1 freeglut3-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxext-dev libcairo2-dev libfreetype6-dev libffi-dev libjpeg-dev libpng-dev libz-dev
- name: Checkout
uses: actions/checkout@v4
- name: Set up Julia
uses: julia-actions/setup-julia@v1
with:
Expand All @@ -33,11 +36,11 @@ jobs:
conda activate test
pip install -e .

- name: Run tests with coverage
- name: Run tests with xvfb
shell: bash -l {0}
run: |
conda activate test
pytest --cov=battmo --cov-report=term-missing
xvfb-run -s "-screen 0 1024x768x24" pytest --cov=battmo --cov-report=term-missing

release:
name: Build and publish to PyPI
Expand Down
86 changes: 54 additions & 32 deletions battmo/api/plotting.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
import juliapkg
from ..julia_import import jl
import juliacall
import time
import asyncio


def activate_plotting():
try:
jl.seval("using WGLMakie; WGLMakie.activate!()")
jl.seval("using GLMakie; GLMakie.activate!()")

except:
print("Unable to load WGLMakie. Have you called install_plotting()?")

print("Unable to load GLMakie. Have you called install_plotting()?")

return False
return True


def install_plotting():
juliapkg.add("WGLMakie", "276b4fcb-3e11-5398-bf8b-a0c2d153d008")
juliapkg.add("GLMakie", "e9467ef8-e4e7-5192-8a1a-b1aee30e663a")
juliapkg.resolve()
activate_plotting()
return True


def uninstall_plotting():
juliapkg.rm("WGLMakie", "276b4fcb-3e11-5398-bf8b-a0c2d153d008")
juliapkg.rm("GLMakie", "e9467ef8-e4e7-5192-8a1a-b1aee30e663a")
juliapkg.resolve()
return True

Expand All @@ -30,43 +34,61 @@ def make_interactive():
juliacall.interactive()


def plot_dashboard(output, plot_type="simple"):
async def keep_plot_dashboard_alive(*arg, **kwargs):
fig = jl.plot_dashboard(*arg, **kwargs)
while True:
jl.seval("yield()")
await asyncio.sleep(0.1)


def plot_dashboard(*arg, **kwargs):

if activate_plotting():
fig = jl.plot_dashboard(output, plot_type=plot_type)

if plot_type == "line":
jl.seval(
"""
println("Press Ctrl+C to stop plotting interactivity")
while true
sleep(0.1)
end
"""
)
loop = asyncio.get_event_loop()

if loop.is_running():
# Notebook or already running loop
loop.create_task(keep_plot_dashboard_alive(*arg, **kwargs))
else:
# Script or no loop running - start a loop
asyncio.run(keep_plot_dashboard_alive(*arg, **kwargs))

make_interactive()

return fig
async def keep_plot_output_alive(*arg, **kwargs):
fig = jl.plot_output(*arg, **kwargs)
while True:
jl.seval("yield()")
await asyncio.sleep(0.1)


def plot_output(*arg, **kwargs):
if activate_plotting():
fig = jl.plot_output(*arg, **kwargs)
make_interactive()
jl.seval("display(current_figure())")
return fig
try:
loop = asyncio.get_event_loop()
# Notebook or already running loop
loop.create_task(keep_plot_output_alive(*arg, **kwargs))

except RuntimeError:
# Script: no loop running, so start one
asyncio.run(keep_plot_output_alive(*arg, **kwargs))


async def keep_plot_interactive_3d_alive(*arg, **kwargs):
fig = jl.plot_interactive_3d(*arg, **kwargs)
while True:
jl.seval("yield()")
await asyncio.sleep(0.1)


def plot_interactive_3d(*arg, **kwargs):
if activate_plotting():
fig = jl.plot_interactive_3d(*arg, **kwargs)
make_interactive()
jl.seval(
"""
println("Press Ctrl+C to stop plotting interactivity")
while true
sleep(0.1)
end
"""
)
return fig
try:
loop = asyncio.get_event_loop()
# Notebook or already running loop
loop.create_task(keep_plot_interactive_3d_alive(*arg, **kwargs))

except RuntimeError:

# Script: no loop running, so start one
asyncio.run(keep_plot_interactive_3d_alive(*arg, **kwargs))
9 changes: 2 additions & 7 deletions battmo/julia_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@
try:
jl.seval(
"""
using BattMo,
using Jutul:Jutul,get_1d_interpolator
using WGLMakie
using BattMo, Jutul
"""
)

Expand All @@ -53,12 +51,9 @@
import Pkg
Pkg.add("BattMo")
Pkg.add("Jutul")
Pkg.add("WGLMakie")
Pkg.instantiate()

using BattMo
using Jutul:Jutul,get_1d_interpolator
using WGLMakie
using BattMo, Jutul
"""
)

Expand Down
6 changes: 3 additions & 3 deletions battmo/juliapkg.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
"uuid": "2b460a1a-8a2b-45b2-b125-b5c536396eb9",
"version": "0.4.6"
},
"WGLMakie": {
"uuid": "276b4fcb-3e11-5398-bf8b-a0c2d153d008",
"version": "0.11.10"
"GLMakie": {
"uuid": "e9467ef8-e4e7-5192-8a1a-b1aee30e663a",
"version": "0.11.11"
},
"OpenSSL_jll": {
"uuid": "458c3c95-2e84-50aa-8efc-19380b2a3a95",
Expand Down
13 changes: 12 additions & 1 deletion examples/1d_simulation.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,41 @@
# Partial port of https://battmoteam.github.io/BattMo.jl/dev/tutorials/2_run_a_simulation
# %%
from battmo import *
import plotly.express as px
import pandas as pd
import numpy as np
import asyncio

# %%
# Load parameter sets
cell_parameters = load_cell_parameters(from_default_set="chen_2020")
cycling_protocol = load_cycling_protocol(from_default_set="cc_discharge")

# %%
# Have a quick look into what kind of cell we're dealing with
quick_cell_check(cell_parameters)

# %%
# Setup model and simulation
model = LithiumIonBattery()
sim = Simulation(model, cell_parameters, cycling_protocol)
output = solve(sim)

# %%
# Have a look into which output quantities are available
print_info(output)

# %%
# Plot voltage curve
time_series = output.time_series

df = to_pandas(time_series)
fig = px.line(df, x="Time", y="Voltage", title="Voltage curve")
fig.show()


# %%
# Plot a dashboard
plot_dashboard(output, plot_type="contour")


# %%
10 changes: 6 additions & 4 deletions examples/3d_simulation.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Partial port of https://battmoteam.github.io/BattMo.jl/dev/tutorials/2_run_a_simulation
# %%
from battmo import *
import plotly.express as px

# Load parameter sets
# %% Load parameter sets
cell_parameters = load_cell_parameters(from_default_set="chen_2020")
cycling_protocol = load_cycling_protocol(from_default_set="cc_discharge")
model_settings = load_model_settings(from_default_set="p4d_cylindrical")
Expand All @@ -13,10 +13,12 @@
cell_parameters["PositiveElectrode"]["CurrentCollector"]["TabWidth"] = 0.002
simulation_settings["AngularGridPoints"] = 8

# Setup model and simulation
# %% Setup model and simulation
model = LithiumIonBattery(model_settings=model_settings)
sim = Simulation(model, cell_parameters, cycling_protocol, simulation_settings=simulation_settings)
output = solve(sim)

# Plot interative 3D results
# %% Plot interative 3D results
plot_interactive_3d(output)

# %%
Loading