18 fix dissipator coupling bug - #19
Conversation
|
Re: "Coupling and General operators have an attribute "hermitian_couplings" which will return the unique couplings," why wouldn't we just fix the Couplings to store all off-diagonal elements? Isn't it confusing to have two separate attributes? |
|
Re: "Added some parsing to State to return both the times vector and the states list from "propagate_using_master_equation()" when using 'zvode' since 'zvode' uses an adaptive time stepper and alters the list of times actually used in the simulation. i.e. If a user specifies a "times" vector, the state list from 'zvode' does not match the user's times list, so 'zvode' should give the user the correct times vector determined during numerical integration," I believe that propagate_using_master_equation already did return both the time array and the density matrices on that time grid.-- i.e., (times, rhos) -- and these times are not the ones used for numerical integration. The time grid specified, "time-evals" is meant to be the time grid on which the results are returned, independent of the integration time grid. Was this not the functionality of the zvode integration method? |
The Coupling Operators and General Operators do store all off-diagonal elements as a property "couplings", which returns a list of coupling elements. Having a separate attribute called "hermitian_couplings" helped give the Hamiltonian class easy access to the unique couplings it uses to generate the "Hint" contributions in the current implementation, but this can be done without needing "hermitian_couplings" to be its own property attribute. I'll remove the "hermitian_couplings" attribute since it's essentially a wrapper anyway and doesn't get used anywhere else besides the Hamiltonian; this should be reflected in the latest commit. |

Fixed a bug where coupling operators would only store an upper half or lower half of the matrix because of assumed usage in a Hamiltonian class. This led to Lindblad operators being created incorrectly if the Lindblad operator had content in both the upper and lower portions of its matrix.
Changes:
Coupling operators parse and store all couplings.
Coupling and General operators have an attribute "hermitian_couplings" which will return the unique couplings. For a General Operator with no couplings, None is returned.
The Hamiltonian class manages coupling operators by working from the hermitian couplings and all previous logic executes as before. i.e. a Coupling operator's Hamiltonian contribution is built via its static matrix * rate + the hermitian conjugate.
Note: During testing of different Lindblad operator choices, if the user specifies a \sigma_X type Lindblad operator in the lab frame that is highly off-resonant with the qubit, then required robust numerical integration methods are required since the transformed Lindblad operator is highly-oscillatory in the interaction picture. Therefore, there are several changes I made to use the 'zvode' integration method:
Custom math "zvode" method required some syntax fixes for attributes.
Made "atol" and "rtol" zvode class attributes so they could set by the user upstream as keyword arguments. The default atol and rtol values are too aggressive (near machine precision!) and lead to excessively slow integration behavior for problems that don't need such tight tolerances.
Added some parsing to State to return both the times vector and the states list from "propagate_using_master_equation()" when using 'zvode' since 'zvode' uses an adaptive time stepper and alters the list of times actually used in the simulation. i.e. If a user specifies a "times" vector, the state list from 'zvode' does not match the user's times list, so 'zvode' should give the user the correct times vector determined during numerical integration. EDIT 07/27/2026, instead of this approach, we have fixed 'zvode' to always return the solution at the exact time points as requested by the user. This is better than having heterogeneous output from the "propagate_using...()" method in state.
Added a test to test_dissipators.py to test the specific example of a qubit with an interaction-frame Lindblad operator L = \sqrt{gamma} \sigma_X. It tests both integration and agreement of the final |0> population with a reference.