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

_set_timestep and get_timesteps for in CheckpointFile #3310

Merged
merged 28 commits into from
Jan 31, 2024

Conversation

sghelichkhani
Copy link
Contributor

Background

Previously, with DumbCheckpoint, we had set_timestep and get_timesteps functions which we were using for checkpointing states over time, allowing the user to retrieve all the stored indices and timesteps from a checkpoint.

Issue and proposed change

The transition to CheckpointFile, we don't have set_timestep and get_timesteps, primarily because of the way we are handling indexing using PETSc's ViewerHDF5 SetTimestep and IncrementTimestep. This PR introduces _set_timestep and get_timesteps to CheckpointFile. The implementation tries to be consistent with PETSc's SetTimestep and IncrementTimestep. Specifically, _set_timestep in CheckpointFile is invoked only when a timetag is given to save_function.

@sghelichkhani sghelichkhani marked this pull request as draft January 8, 2024 23:36
@sghelichkhani sghelichkhani marked this pull request as ready for review January 8, 2024 23:37
@dham dham requested a review from ksagiyam January 9, 2024 09:24
Copy link
Member

@dham dham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this addition.

I'll let @ksagiyam look at this in detail, but I would point out that it does need a test. I would suggest writing some trivial time steps to a file. Re-opening that file and then using this API.

Copy link
Contributor

@connorjward connorjward left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution!

firedrake/checkpointing.py Outdated Show resolved Hide resolved
firedrake/checkpointing.py Outdated Show resolved Hide resolved
firedrake/checkpointing.py Outdated Show resolved Hide resolved
firedrake/checkpointing.py Outdated Show resolved Hide resolved
Copy link
Contributor

@ksagiyam ksagiyam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As David suggested, could you please add tests?

firedrake/checkpointing.py Outdated Show resolved Hide resolved
firedrake/checkpointing.py Outdated Show resolved Hide resolved
firedrake/checkpointing.py Outdated Show resolved Hide resolved
@sghelichkhani
Copy link
Contributor Author

As David suggested, could you please add tests?

Thanks for this addition.

I'll let @ksagiyam look at this in detail, but I would point out that it does need a test. I would suggest writing some trivial time steps to a file. Re-opening that file and then using this API.

Added a simple checkpointing case of a mixed function, and then loading one of its subfunctions and making sure all work as expected. As @ksagiyam suggested, making it work for mixed functions required a bit of change.

Copy link
Contributor

@connorjward connorjward left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this looks OK but @ksagiyam should probably be the person to pass judgement.

@ksagiyam (not for this PR) would it be possible to generalise this to work for arbitrary attributes? Something like save_function(f, **kwargs) where kwargs is somehow unpacked and serialised.

Copy link
Contributor

@ksagiyam ksagiyam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started feeling that designing timestepping IO is worth a bit more thoughts.

Could you first look at the suggested changes?

firedrake/checkpointing.py Outdated Show resolved Hide resolved
firedrake/checkpointing.py Outdated Show resolved Hide resolved
firedrake/checkpointing.py Outdated Show resolved Hide resolved
tests/output/test_io_timestepping.py Outdated Show resolved Hide resolved
tests/output/test_io_timestepping.py Outdated Show resolved Hide resolved
tests/output/test_io_timestepping.py Outdated Show resolved Hide resolved
tests/output/test_io_timestepping.py Outdated Show resolved Hide resolved
tests/output/test_io_timestepping.py Outdated Show resolved Hide resolved
@ksagiyam
Copy link
Contributor

@connorjward Yes, I think so. Technically, users have access to h5pyfile and methods to construct paths, so they can save whatever they want, but it might be worth making a higher level interface available.

firedrake/checkpointing.py Outdated Show resolved Hide resolved
@connorjward
Copy link
Contributor

@connorjward Yes, I think so. Technically, users have access to h5pyfile and methods to construct paths, so they can save whatever they want, but it might be worth making a higher level interface available.

@ksagiyam should I create an issue (labelled "enhancement") for this or do you want to tackle this in this PR? You said:

I started feeling that designing timestepping IO is worth a bit more thoughts.

@ksagiyam
Copy link
Contributor

@connorjward I think that can be done in a separate PR. Please go ahead and open an issue about it.

I would like to think a bit further about the design/file-structure. For instance, I think timestepping_indices should be regarded as a topological property while timestepping_ts (or whatever we call it) should be a "geometric" one (these are coordinates in the temporal direction). I think I need to summarise my thoughts first.

Copy link
Contributor Author

@sghelichkhani sghelichkhani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should actually only allow users to save with t=None all the time or t=some_real_value all the time. This will let us avoid defining DEFAULT_REAL and avoid storing redundant values in the file. (Same for timestep). indices should always be stored, I think.

If we are to extend the interface as suggested by @connorjward in the future (#3328), what we do here must be consistent. Will the interface look like:

save_function(f, idx=..., timestepping_info={"time": ...,
                                             "timestep": ...})

? If so, I think, the corresponding attribute names should be PREFIX_TIMESTEPPING + "_history" + "_time"/PREFIX_TIMESTEPPING + "_history" + "_timestep" (or something) instead of PREFIX_TIMESTEPPING + "times"/PREFIX_TIMESTEPPING + "timesteps" as putting s for plural is not always correct? We then enforce the keys of timestepping_info dictionary to be the same throughout timestepping as in the above.

Thanks @ksagiyam. So to be consistent with the idea in #3328 I changed the timestepping_info to a dictionary as suggested. Then depending on whatever arbitrary key timestepping info is stored, the user can retrieve the same information within a dictionary. For the default case in timestepping mode, only {'indices':[list of indices]} are returned by get_timestepping_history. The same can be actually used for whatever float the user needs to store along a function.

Copy link
Contributor

@ksagiyam ksagiyam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it looks great. Suggested are some final touch ups.

firedrake/checkpointing.py Show resolved Hide resolved
firedrake/checkpointing.py Show resolved Hide resolved
firedrake/checkpointing.py Outdated Show resolved Hide resolved
firedrake/checkpointing.py Outdated Show resolved Hide resolved
firedrake/checkpointing.py Outdated Show resolved Hide resolved
firedrake/checkpointing.py Outdated Show resolved Hide resolved
tests/output/test_io_timestepping.py Show resolved Hide resolved
tests/output/test_io_timestepping.py Outdated Show resolved Hide resolved
tests/output/test_io_timestepping.py Outdated Show resolved Hide resolved
tests/output/test_io_timestepping.py Outdated Show resolved Hide resolved
@ksagiyam
Copy link
Contributor

@sghelichkhani We should probably push all timestepping attributes to self._path_to_vec_timestepping/self._path_to_function_timestepping folders just as we do for extrusion, but this should be simple. Let me do that after you review my current suggestions.

sghelichkhani and others added 2 commits January 27, 2024 07:09
Co-authored-by: ksagiyam <46749170+ksagiyam@users.noreply.github.com>
Copy link
Contributor Author

@sghelichkhani sghelichkhani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ksagiyam. Looks good to me. Once you do the final change I am happy for this to go.

Copy link
Contributor

@ksagiyam ksagiyam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please put:

    def _path_to_vec_timestepping(self, tmesh_name, dm_name, tf_name):
        return os.path.join(self._path_to_vec(tmesh_name, dm_name, tf_name), PREFIX_TIMESTEPPING)

after def _path_to_vec(...) and:

    def _path_to_function_timestepping(self, tmesh_name, mesh_name, V_name, function_name):
        return os.path.join(self._path_to_function(tmesh_name, mesh_name, V_name, function_name), PREFIX_TIMESTEPPING)

after def _path_to_function(...).

Please replace l.958:

            path = self._path_to_vec(tmesh.name, dm.name, tf.name())

with:

            dm_name = dm.name
            path = self._path_to_vec(tmesh.name, dm_name, tf.name())

Please also make your branch up-to-date.

firedrake/checkpointing.py Outdated Show resolved Hide resolved
firedrake/checkpointing.py Show resolved Hide resolved
firedrake/checkpointing.py Outdated Show resolved Hide resolved
firedrake/checkpointing.py Outdated Show resolved Hide resolved
firedrake/checkpointing.py Outdated Show resolved Hide resolved
Copy link
Contributor Author

@sghelichkhani sghelichkhani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! Let me know if I should do a squash on my end.

Copy link
Contributor

@ksagiyam ksagiyam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I will start CI.

firedrake/checkpointing.py Outdated Show resolved Hide resolved
firedrake/checkpointing.py Outdated Show resolved Hide resolved
ksagiyam
ksagiyam previously approved these changes Jan 31, 2024
firedrake/checkpointing.py Outdated Show resolved Hide resolved
ksagiyam
ksagiyam previously approved these changes Jan 31, 2024
firedrake/checkpointing.py Outdated Show resolved Hide resolved
@dham dham enabled auto-merge (squash) January 31, 2024 16:36
@dham dham merged commit d8bf62c into firedrakeproject:master Jan 31, 2024
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants