Skip to content

Commit ad7437a

Browse files
committed
HEOM Performance fixes
1 parent a3b51ef commit ad7437a

File tree

4 files changed

+40
-16
lines changed

4 files changed

+40
-16
lines changed

qutip/core/cy/qobjevo.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class QobjEvo:
3939
def arguments(self, new_args: dict[str, Any]) -> None: ...
4040
@overload
4141
def arguments(self, **new_args) -> None: ...
42-
def compress(self) -> QobjEvo: ...
42+
def compress(self, *, _skip_coeff=False, _skip_qobj=False) -> QobjEvo: ...
4343
def tidyup(self, atol: Number) -> QobjEvo: ...
4444
def copy(self) -> QobjEvo: ...
4545
def conj(self) -> QobjEvo: ...

qutip/core/cy/qobjevo.pyx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,7 @@ cdef class QobjEvo:
850850
cleaned_elements.append(_EvoElement(qobj, coeff))
851851
return cleaned_elements
852852

853-
def compress(self):
853+
def compress(self, *, _skip_coeff=False, _skip_qobj=False):
854854
"""
855855
Look for redundance in the :obj:`.QobjEvo` components:
856856
@@ -878,8 +878,10 @@ cdef class QobjEvo:
878878
else:
879879
func_elements.append(element)
880880

881-
coeff_elements = self._compress_merge_coeff(coeff_elements)
882-
coeff_elements = self._compress_merge_qobj(coeff_elements)
881+
if not _skip_coeff:
882+
coeff_elements = self._compress_merge_coeff(coeff_elements)
883+
if not _skip_qobj:
884+
coeff_elements = self._compress_merge_qobj(coeff_elements)
883885

884886
cleaned_elements = coeff_elements + func_elements
885887

qutip/core/direct_sum.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
QobjLike = Union[Number, Qobj, QobjEvo]
2626

27+
ARRAY_ONE = np.full((1,), 1, dtype=_data.base.idxint_dtype)
28+
2729

2830
def _is_like_ket(qobj: Any) -> bool:
2931
return (
@@ -376,7 +378,7 @@ def _do_direct_sum(
376378
_skip_check=True
377379
)
378380
if qobjevos:
379-
result.compress()
381+
result.compress(_skip_coeff=True)
380382
return result
381383

382384

@@ -419,7 +421,7 @@ def direct_component(sum_qobj, *index):
419421
if isinstance(sum_qobj, QobjEvo):
420422
result = sum_qobj.linear_map(lambda x: direct_component(x, *index),
421423
_skip_check=True)
422-
result.compress()
424+
result.compress(_skip_coeff=True)
423425
return result(0) if result.isconstant else result
424426

425427
to_index, from_index = _check_component_index(sum_qobj._dims, index)
@@ -508,7 +510,7 @@ def set_direct_component(sum_qobj, component, *index):
508510
zeroed = sum_qobj.linear_map(
509511
lambda x: set_direct_component(x, None, *index),
510512
_skip_check=True)
511-
zeroed.compress()
513+
zeroed.compress(_skip_coeff=True)
512514
zeroed = zeroed(0) if zeroed.isconstant else zeroed
513515
else:
514516
zeroed = set_direct_component(sum_qobj, None, *index)
@@ -540,11 +542,21 @@ def _blow_up_qobj(x: Qobj, *, sum_dimensions, row, col, dtype):
540542
else:
541543
data_col = 0
542544

545+
xh, xw = x.shape
546+
sh, sw = sum_dimensions.shape
547+
543548
return Qobj(
544-
_data.block_overwrite(
545-
_data.zeros[dtype](*sum_dimensions.shape),
546-
x.data, data_row, data_col, dtype=dtype
547-
), dims=sum_dimensions, copy=False
549+
_data.block_build(
550+
ARRAY_ONE,
551+
ARRAY_ONE,
552+
np.full((1,), x.data, dtype=_data.Data),
553+
np.array([data_row, xh, sh - xh - data_row],
554+
dtype=_data.base.idxint_dtype),
555+
np.array([data_col, xw, sw - xw - data_col],
556+
dtype=_data.base.idxint_dtype),
557+
dtype=dtype
558+
),
559+
dims=sum_dimensions, copy=False
548560
)
549561

550562

qutip/solver/heom/bofin_solvers.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,7 @@ def __init__(self, H, bath, max_depth, *, odd_parity=False, options=None):
675675
else H # already a liouvillian
676676
)
677677
if isinstance(self.L_sys, QobjEvo):
678-
self.L_sys.compress()
678+
self.L_sys.compress(_skip_coeff=True)
679679

680680
# Dimensions that L_sys acts on
681681
self._sys_dims_ = self.L_sys._dims[0].oper
@@ -822,7 +822,7 @@ def _grad_prev(self, he_n, k):
822822
else:
823823
op = self._grad_prev_bosonic(he_n, k)
824824
if isinstance(op, QobjEvo):
825-
op.compress()
825+
op.compress(_skip_coeff=True)
826826
return op
827827

828828
def _grad_prev_bosonic(self, he_n, k):
@@ -892,7 +892,7 @@ def _grad_next(self, he_n, k):
892892
else:
893893
op = self._grad_next_bosonic(he_n, k)
894894
if isinstance(op, QobjEvo):
895-
op.compress()
895+
op.compress(_skip_coeff=True)
896896
return op
897897

898898
def _grad_next_bosonic(self, he_n, k):
@@ -928,7 +928,7 @@ def _calculate_rhs(self):
928928

929929
ops = {}
930930
for he_n in self.ados.labels:
931-
ops[(idx(he_n), idx(he_n))] = self._grad_n(he_n) + self.L_sys
931+
ops[(idx(he_n), idx(he_n))] = self._grad_n(he_n)
932932
for k in range(len(self.ados.dims)):
933933
next_he = self.ados.next(he_n, k)
934934
if next_he is not None:
@@ -937,7 +937,17 @@ def _calculate_rhs(self):
937937
if prev_he is not None:
938938
ops[(idx(he_n), idx(prev_he))] = self._grad_prev(he_n, k)
939939

940-
return direct_sum_sparse(ops, self._rhs_dims)
940+
if isinstance(self.L_sys, QobjEvo):
941+
liouvillian_part = self.L_sys.linear_map(self._liouvillian_part)
942+
else:
943+
liouvillian_part = self._liouvillian_part(self.L_sys)
944+
945+
return liouvillian_part + direct_sum_sparse(ops, self._rhs_dims)
946+
947+
def _liouvillian_part(self, L):
948+
return direct_sum_sparse(
949+
{(idx, idx): L for idx in range(self._n_ados)}, self._rhs_dims
950+
)
941951

942952
def steady_state(
943953
self,

0 commit comments

Comments
 (0)