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

Ability to make a copy of Simulation object #864

Open
RemDelaporteMathurin opened this issue Aug 2, 2024 · 2 comments
Open

Ability to make a copy of Simulation object #864

RemDelaporteMathurin opened this issue Aug 2, 2024 · 2 comments
Labels

Comments

@RemDelaporteMathurin
Copy link
Collaborator

RemDelaporteMathurin commented Aug 2, 2024

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:

  1. 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
  1. 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:

  1. deepcopy the 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

  1. Our own copy method
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.

@KulaginVladimir
Copy link
Collaborator

Could you please show the cases where copying is needed?

@RemDelaporteMathurin
Copy link
Collaborator Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants