FESTIM
FESTIM copied to clipboard
Ability to make a copy of `Simulation` object
I can see a few use cases where being able to make a copy of a simulation could be useful.
At the moment, these are the options:
- New simulation + transfer parameters
import festim as F
model1 = F.Simulation()
model1.materials = F.Material(D_0=1, E_D=1, id=1)
model1.boundary_conditions = [F.DirichletBC(surfaces=[1], value=0, field="solute")]
model1.sources = [F.Source(volume=1, value=1, field="solute")]
model1.mesh = F.MeshFromVertices([1, 2, 3, 4])
model1.traps = [F.Trap(k_0=1, E_k=1, p_0=1, E_p=1, density=1, materials=model1.materials[0])]
model1.settings = F.Settings(transient=True, final_time=1, absolute_tolerance=1e-10, relative_tolerance=1e-10)
model1.T = 200
model1.dt = F.Stepsize(0.1)
model1.initialise()
model1.run()
model2 = F.Simulation()
model2.materials = model1.materials
model2.boundary_conditions = model1.boundary_conditions
model2.sources = model1.sources
model2.mesh = model1.mesh
model2.traps = model1.traps
model2.settings = model1.settings
model2.T = 500 # CHANGE THIS PARAMETER ONLY
model2.dt = model1.dt
- Changing the original model
import festim as F
model1 = F.Simulation()
model1.materials = F.Material(D_0=1, E_D=1, id=1)
model1.boundary_conditions = [F.DirichletBC(surfaces=[1], value=0, field="solute")]
model1.sources = [F.Source(volume=1, value=1, field="solute")]
model1.mesh = F.MeshFromVertices([1, 2, 3, 4])
model1.traps = [F.Trap(k_0=1, E_k=1, p_0=1, E_p=1, density=1, materials=model1.materials[0])]
model1.settings = F.Settings(transient=True, final_time=1, absolute_tolerance=1e-10, relative_tolerance=1e-10)
model1.T = 200
model1.dt = F.Stepsize(0.1)
model1.initialise()
model1.run()
model1.T = 500 # CHANGE THIS PARAMETER ONLY
model1.initialise()
model1.run()
Ideally we would want:
deepcopythe simulation
import festim as F
model1 = F.Simulation()
model1.materials = F.Material(D_0=1, E_D=1, id=1)
model1.boundary_conditions = [F.DirichletBC(surfaces=[1], value=0, field="solute")]
model1.sources = [F.Source(volume=1, value=1, field="solute")]
model1.mesh = F.MeshFromVertices([1, 2, 3, 4])
model1.traps = [F.Trap(k_0=1, E_k=1, p_0=1, E_p=1, density=1, materials=model1.materials[0])]
model1.settings = F.Settings(transient=True, final_time=1, absolute_tolerance=1e-10, relative_tolerance=1e-10)
model1.T = 200
model1.dt = F.Stepsize(0.1)
model1.initialise()
model1.run()
from copy import deepcopy
model2 = deepcopy(model1)
model2 .T = 500 # CHANGE THIS PARAMETER ONLY
model2 .initialise()
model2 .run()
However this is not possible because tries to copy some parameters that are not copiable (eg. fenics.Constant).
TypeError: cannot pickle 'dolfin.cpp.function.Constant' object
We could make our own copy method
- Our own
copymethod
import festim as F
from copy import deepcopy
model1 = F.Simulation()
model1.materials = F.Material(D_0=1, E_D=1, id=1)
model1.boundary_conditions = [F.DirichletBC(surfaces=[1], value=0, field="solute")]
model1.sources = [F.Source(volume=1, value=1, field="solute")]
model1.mesh = F.MeshFromVertices([1, 2, 3, 4])
model1.traps = [F.Trap(k_0=1, E_k=1, p_0=1, E_p=1, density=1, materials=model1.materials[0])]
model1.settings = F.Settings(transient=True, final_time=1, absolute_tolerance=1e-10, relative_tolerance=1e-10)
model1.T = 200
model1.dt = F.Stepsize(0.1)
model1.initialise()
model1.run()
def copy(model):
new_model = F.Simulation()
new_model.materials = [deepcopy(mat) for mat in model.materials]
new_model.boundary_conditions = [deepcopy(bc) for bc in model.boundary_conditions]
new_model.sources = [deepcopy(src) for src in model.sources]
new_model.mesh = deepcopy(model.mesh)
new_model.traps = [deepcopy(trap) for trap in model.traps]
new_model.settings = deepcopy(model.settings)
new_model.T = deepcopy(model.T)
new_model.dt = deepcopy(model.dt)
return new_model
model2 = copy(model1)
However some of these objects are also not copiable. like the BCs.
So we would have to create copy methods for these two.
It could end up requiring a lot of effort to maintain these copy methods over time.
I don't know what others think.
Could you please show the cases where copying is needed?
Here's an example that I can think of. Say you want to make a parametric study and decouple the plotting and simulation.
import festim as F
model = F.Simulation()
model.materials = F.Material(D_0=1, E_D=1, id=1)
model.boundary_conditions = [F.DirichletBC(surfaces=[1], value=0, field="solute")]
model.sources = [F.Source(volume=1, value=1, field="solute")]
model.mesh = F.MeshFromVertices([1, 2, 3, 4])
model.traps = [
F.Trap(k_0=1, E_k=1, p_0=1, E_p=1, density=1, materials=model.materials[0])
]
model.settings = F.Settings(
transient=True, final_time=1, absolute_tolerance=1e-10, relative_tolerance=1e-10
)
model.T = 200
model.dt = F.Stepsize(0.1)
# parametric study
for source_val in [1, 2, 3]:
model.sources[0].value = source_val
model.initialise()
model.run()
# plot the results
# plt.plot(..., label=f"source_val={source_val}")
# later
# make another plot with first value source_val
This would be facilitated if you could do:
# parametric study
models = []
for source_val in [1, 2, 3]:
new_model = model.copy()
new_model.sources[0].value = source_val
new_model.run()
models.append(new_model)
# later
for model in models:
# plot something