-
Notifications
You must be signed in to change notification settings - Fork 61
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
Added second-order Magnus solver in the fixed-step exponential solvers #86
Added second-order Magnus solver in the fixed-step exponential solvers #86
Conversation
Awesome, thanks for submitting this! There are a few things to address to proceed with this PR:
We can discuss more about each individual point - I'm happy to help with any part of this, especially the parts involving more detailed knowledge of the repo itself (e.g. setting up the proper citation method or adding tests). Aside from this, I also have some direct comments on the code itself:
Here,
This will also be useful if the suggestion in #83 is implemented (so that a diagonalization-based method can optionally be used.)
|
… function, (ii) reducing # of operations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New commit is has nice improvements. Some comments:
- Move the
get_exponential_take_step
method to later in the file, to right beforefixed_step_solver_template
.- Also, add some documentation for this function.
- Add the
magnus_order
argument to the documentation forscipy_expm_solver
andjax_expm_solver
. State that only order1
and2
are supported. Note that this file is totally "internal" (i.e. users technically shouldn't see it), so the documentation here is for developers. - Add the
magnus_order
argument to the documentation for the exponential solvers in thesolve_lmde
function inqiskit_dynamics/solvers/solver_functions.py
. You can see howmax_dt
is described there and add a similar sentence. You should also add a reference here to the geometric methods book. You can do this by adding an entry to the bibtex filedocs/refs.bib
, then cite it in the documentation using thefootcite
command. (Seeqiskit_dynamics/perturbation/__init__.py
for an example usage offootcite
.) - Clean up the
if
/else
forget_exponential_take_step
, and raise an error ifmagnus_order > 2
. E.g. do:
if magnus_order == 1:
...
elif magnus_order == 2:
...
else:
raise QiskitError("Only magnus_order 1 or 2 are supported.")
For this last point you'll need to add from qiskit import QiskitError
to the imports at the top of the file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added some standalone comments, including direct code suggestions. Don't forget to add the magnus_order
kwarg to jax_expm_parallel_solver
as well.
For the solve_lmde
doc string, the description of the magnus_order
argument should be moved into the first bullet point describing the 'scipy_expm'
function. Currently it says:
- ``'scipy_expm'``: A fixed-step matrix-exponential solver using ``scipy.linalg.expm``.
Requires additional kwarg ``max_dt`` indicating the maximum step
size to take. This solver will break integration periods into even
sub-intervals no larger than ``max_dt``, and solve over each sub-interval via
matrix exponentiation of the generator sampled at the midpoint.
and it should now say something like (please review/edit this):
- ``'scipy_expm'``: A fixed-step matrix-exponential solver using ``scipy.linalg.expm``.
Requires additional kwarg ``max_dt`` indicating the maximum step
size to take. This solver will break integration periods into even
sub-intervals no larger than ``max_dt`` and solve over each sub-interval.
The optional kwarg ``magnus_order`` controls the integration rule: if
``magnus_order==1``, the generator is sampled at the interval midpoint
and exponentiated, and if ``magnus_order==2``, a second-order exponentiation
rule is adopted from :footcite:`hairer_geometric_2006`.
Also it seems like something strange has happened with your refs.bib
file - it says you're adding the whole thing, which may be because your branch was out of date. We can resolve this later.
After these changes, the next thing is to start adding tests. One thing that will make this easier is that you're adding functionality to already-existing functions, so you'll just need to add some additional tests to handle the case magnus_order=2
. There are a few places where tests need to be added. Each file tests different aspects/levels of the interfaces in Dynamics, and each one is mostly set up to make it easy to subject new solver methods to a suite of tests. All of the relevant testing files are in the test/dynamics/solvers
folder.
- The file
test_fixed_step_solvers.py
contains tests for directly testing the low level solver functions likescipy_expm_solver
. To add a test for thescipy_expm_solver
function withmagnus_order==2
, you can copy the classTestScipyExpmSolver
(giving it a new name, likeTestScipyExpmSolver_Magnus2
), and update thetake_step
method so that it implements the second order rule, and thesolve
method so that it callsscipy_expm_solver
withmagnus_order=2
. This same process can be repeated in this file for the tests forjax_expm_solver
andjax_expm_parallel_solver
. - A similar process needs to be done in the
test_solver_functions.py
file, which tests things at the level of thesolve_ode
andsolve_lmde
functions, which users will actually interact with. - Lastly, you'll need to add a test in
test_solver_functions_interface.py
, to validate that an error is raised if a user attempts to pass something other than the integers1
or2
to themagnus_order
argument.
The last thing I want to ask at this stage, is if there are orders higher than 2 that we can support. Are there higher order rules described in the geometric integration methods book? If we could also add order 3 and/or 4 that'd be pretty cool, and now would be the right time to do it.
magnus_order: the expansion order in the Magnus method. Only order 1 and 2 | ||
are supported |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may seem pedantic, but for comments, try to follow the general style in the repo. E.g. Capitalize/punctuate. Indent new lines.
magnus_order: the expansion order in the Magnus method. Only order 1 and 2 | |
are supported | |
magnus_order: The expansion order in the Magnus method. Only order 1 and 2 | |
are supported. |
|
||
else: | ||
raise QiskitError("Only magnus_order 1 or 2 are supported.") | ||
# end of if clause based on magnus order |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unnecessary comment
raise QiskitError("Only magnus_order 1 or 2 are supported.") | ||
# end of if clause based on magnus order | ||
|
||
# return the function |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for this comment
magnus_order: the expansion order in the Magnus method | ||
expm_func: method of matrix exponentian; can e.g. be expm, jexp. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
magnus_order: the expansion order in the Magnus method | |
expm_func: method of matrix exponentian; can e.g. be expm, jexp. | |
magnus_order: The expansion order in the Magnus method. | |
expm_func: Method of matrix exponentian. |
-``max_dt`` kwarg in the same manner as ``method='scipy_expm'``. This method is only | ||
recommended for use with GPU execution. | ||
-``magnus_order`` kwarg that determines the expansion order for fixed step exponential solvers. | ||
Only order 1 and 2 are supported. The second-order solver is adopted from | ||
:footcite:`hairer_geometric_2006` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Undo these changes - see main comment.
magnus_order: the expansion order in the Magnus method. Only order 1 and 2 | ||
are supported |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
magnus_order: the expansion order in the Magnus method. Only order 1 and 2 | |
are supported | |
magnus_order: The expansion order in the Magnus method. Only order 1 and 2 | |
are supported. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've double checked and verified that I believe the constants/integration rules are implemented correctly. Also had some other very minor comments. There are a couple of other stylistic things we'll need to address to make the automated style-checker pass before merging, but we can do that at the end after the tests are added.
elif magnus_order==2: | ||
|
||
# second-order step size constants | ||
c1=1/2-np.sqrt(3)/6 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is obviously very minor but change all 1/2
to 0.5
. Obviously a trivial operation but it still saves the construction of the ints and then the division.
# Magnus terms | ||
term1=a1+a3/12 | ||
term2=matrix_commutator(-20*a1-a3+com1,a2+com2)/240 | ||
terms=term1+term2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think any clarity is lost by making this a single line:
terms = a1 + a3/12 + matrix_commutator(-20*a1-a3+com1,a2+com2)/240
return expm_func(terms) @ y | ||
|
||
else: | ||
raise QiskitError("Only magnus_order 1, 2 and 3 are supported.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
raise QiskitError("Only magnus_order 1, 2 and 3 are supported.") | |
raise QiskitError("Only magnus_order 1, 2, and 3 are supported.") |
… moein_feature
…ents by Dan Puzzuoli
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like a great addition! Apologies for all the trivial comments, but it's the best way to maintain coding standards.
Note that I did not look at blanes_magnus_2009 and so cannot vouch for correctness.
I think I've changed everything you said. No need to apologize, I appreciate the thoroughness and commitment to consistent formatting. |
…t-community#86) Co-authored-by: Daniel Puzzuoli <dan.puzzuoli@gmail.com>
Summary
Second order Magnus solver is added to the following fixed-step exponential solvers:
scipy_expm_solver
jax_expm_solver
jax_expm_parallel_solver
Details and comments