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

Simulation save/restart module #33

Open
skim0119 opened this issue Jan 6, 2022 · 10 comments
Open

Simulation save/restart module #33

skim0119 opened this issue Jan 6, 2022 · 10 comments
Assignees
Labels
enhancement New feature or request good first issue Good for newcomers prio:low Priority level: low

Comments

@skim0119
Copy link
Collaborator

skim0119 commented Jan 6, 2022

Issue by skim0119
Wednesday Dec 29, 2021 at 05:00 GMT
Originally opened as https://github.com/GazzolaLab/elastica-python/issues/111


Partially provide a way to save and load rod. We need more robust simulator-wise callback to save the module. (restart.py)

Things to keep in mind

  • Some data is serializable, which we can use pickle or json, but some other modules must be handled separately.
  • We should account for customized forces/connection/etc. If they have state variables (such as ramp-up rate, etc), we need to save them as well.
  • The interaction between finalize() is somewhat contradicting restart/reloading data in the middle of a simulation.
@skim0119 skim0119 added enhancement New feature or request good first issue Good for newcomers labels Jan 6, 2022
@skim0119
Copy link
Collaborator Author

skim0119 commented Jan 6, 2022

Comment by armantekinalp
Thursday Dec 30, 2021 at 05:29 GMT


In future implementation of restart I think we should add these functionalities:

  • Current implementation allows only loading systems after finalize call. Instead we should call restart functions before finalize.
  • Curren implementation only saves systems i.e. rods, rigid bodies. As @skim0119 mentioned above, restart should save a copy of simulator and user can just load & run. However, some users might need more customization and they might want to only save rods but not the simulation. For those cases we should have an option to save/load systems or simulation.
  • We could also allow users to save simulator/systems every some steps. This might be useful for debugging purposes.

@skim0119 skim0119 self-assigned this Mar 11, 2022
@skim0119 skim0119 added this to the Version 0.3 milestone Mar 11, 2022
@Anika-Roy
Copy link

is this issue open?
Im a beginner and I'd like to work on it

@skim0119
Copy link
Collaborator Author

@Anika-Roy Thank you for your interest. Yes, this issue is still open.
If you are interested in working, let me know, I can assign you.

@bhosale2 bhosale2 added the prio:low Priority level: low label Aug 1, 2022
@bhosale2 bhosale2 modified the milestones: Version 0.3, Version 0.3.1 Aug 2, 2022
@anshusinha26
Copy link

@skim0119 Hello! I'm a beginner looking to make my first contribution to PyElastica, and I'm interested in working on the Simulation save/restart module issue (#33) listed under the good first issue label. I understand that this may involve some challenges, such as handling non-serialisable data and accounting for customised forces/connections, but I'm eager to learn and contribute to the project.
Could you please provide me with some guidance on how to get started with this issue?
Thank you!

@anshusinha26
Copy link

Hi @skim0119 @bhosale2 , I'm interested in contributing to PyElastica and I noticed that issue #33 on simulation save/restart module is still open. Would it be possible to assign this issue to me? I would love to work on it as a beginner.
Thank you!

@anshusinha26
Copy link

I have made changes in "restart.py" and here is the updated code:
doc = """Generate or load restart file implementations."""
all = ["save_state", "load_state"]
import numpy as np
import os
from itertools import groupby

def all_equal(iterable):
"""
Checks if all elements of list are equal.
Parameters
----------
iterable : list
Iterable list
Returns
-------
Boolean
References
----------
https://stackoverflow.com/questions/3844801/check-if-all-elements-in-a-list-are-identical
"""
g = groupby(iterable)
return next(g, True) and not next(g, False)

def save_state(simulator, directory: str = "", time=0.0, verbose: bool = False):
"""
Save state parameters of each rod.
TODO : environment list variable is not uniform at the current stage of development.
It would be nice if we have set list (like env.system) that iterates all the rods.
Parameters
----------
simulator : object
Simulator object.
directory : str
Directory path name. The path must exist.
time : float
Simulation time.
verbose : boolean

"""
os.makedirs(directory, exist_ok=True)
for idx, rod in enumerate(simulator):
    path = os.path.join(directory, "system_{}.npz".format(idx))
    np.savez(path, time=time,
             vertices=rod.vertices,
             edges=rod.edges,
             state_variables=rod.state_variables,
             forces=rod.forces,
             connections=rod.connections,
              **rod.__dict__)

    """
    In the modified version of save_state,
    we are saving the following new pieces of data:

        1. vertices: An array of the rod's vertices.
        2. edges: An array of the rod's edges.
        3. state_variables: A dictionary containing the values of any state variables the rod has.
        4. forces: A dictionary containing information about any forces acting on the rod.
        5. connections: A dictionary containing information about any connections the rod has.
    """

if verbose:
    print("Save complete: {}".format(directory))

def load_state(simulator, directory: str = "", verbose: bool = False):
"""
Load the rod-state. Compatibale with 'save_state' method.
If the save-file does not exist, it returns error.
Call this function after finalize method.

Parameters
----------
simulator : object
    Simulator object.
directory : str
    Directory path name.
verbose : boolean

Returns
------
time : float
    Simulation time of systems when they are saved.
"""
time_list = []  # Simulation time of rods when they are saved.
for idx, rod in enumerate(simulator):
    path = os.path.join(directory, "system_{}.npz".format(idx))
    data = np.load(path, allow_pickle=True)
    for key, value in data.items():
        if key == "time":
            time_list.append(value.item())
            continue

        if key == "vertices":
            rod.vertices[:] = value
        elif key == "edges":
            rod.edges[:] = value
        elif key == "state_variables":
            rod.state_variables.update(value.tolist())
        elif key == "forces":
            rod.forces.update(value.tolist())
        elif key == "connections":
            rod.connections.update(value.tolist())
        elif value.shape != ():
            # Copy data into placeholders
            getattr(rod, key)[:] = value
        else:
            # For single-value data
            setattr(rod, key, value)

if not all_equal(time_list):
    raise ValueError(
        "Restart time of loaded rods are different, check your inputs!"
    )

# Apply boundary conditions, after loading the systems.
simulator.constrain_values(0.0)
simulator.constrain_rates(0.0)

if verbose:
    print("Load complete: {}".format(directory))

return time_list[0]

@anshusinha26
Copy link

@skim0119 @bhosale2 I'm facing some issues while committing the code:

Added the changes by "git add" and it worked perfectly fine.

Next step was to commit the changes, and I tried "git commit -m "Add a code for saving and loading simulation state",
but it showed and error:

Screenshot 2023-03-26 at 12 35 48 PM

Screenshot 2023-03-26 at 12 38 37 PM

Please help me with this!

@kumarabhi2005
Copy link

@skim0119
I want to work on this issue...

@skim0119
Copy link
Collaborator Author

@kumarabhi2005 Thank you for your interest in our project. You are welcome to try. Here, we want to serialize the entire simulator, and be able to save the simulator state comprehensively with all the features.

@rukundob451
Copy link

@skim0119 is this still available?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers prio:low Priority level: low
Projects
None yet
Development

No branches or pull requests

7 participants