Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@
## 2025-11-01 - [Avoid Temporary Array Allocations in Reductions]
**Learning:** In loops over parameters like temperature (`thermal_scan`), doing `np.sum(arr1 * arr2)` where array sizes match the system Hilbert space creates huge temporary arrays per loop iteration. Memory allocation dominates execution time.
**Action:** Use `np.dot(arr1, arr2)` instead of `np.sum(arr1 * arr2)` for 1D arrays to evaluate reductions in C-level BLAS/NumPy functions, bypassing Python/NumPy array allocations and boosting performance significantly with less peak memory.

## 2025-11-01 - [O(N^3) Matrix Multiplication Avoidance in Susceptibility]
**Learning:** In computing `np.sum(rho * np.real(np.diag(A @ A)))` for static susceptibilities where `A` is Hermitian, performing the full matrix multiplication `A @ A` costs $O(N^3)$ and dominates execution time for large N.
**Action:** Since `A` is Hermitian, `diag(A@A)_i = sum_j |A_ij|^2`. This allows replacing the $O(N^3)$ matrix multiplication with an $O(N^2)$ operation: `np.sum(np.abs(A)**2, axis=1)`. Combining this with `np.dot` instead of `np.sum(rho * arr)` avoids temporary allocations and massive speedups for large matrices.
7 changes: 4 additions & 3 deletions physics/response/susceptibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,12 @@ def static_susceptibility(
rho /= Z

# <A> = \sum _n rho _n <n|A|n>
A_avg = np.sum(rho * np.real(np.diag(A_q_eigen)))
A_avg = np.dot(rho, np.real(np.diag(A_q_eigen)))

# <A^2> = \sum _n rho _n <n|A^2|n>
A2_eigen = A_q_eigen @ A_q_eigen
A2_avg = np.sum(rho * np.real(np.diag(A2_eigen)))
# Optimized: A is Hermitian, so diag(A@A)_i = sum_j |A_ij|^2. Replaces O(N^3) with O(N^2).
A2_diag = np.sum(np.abs(A_q_eigen)**2, axis=1)
A2_avg = np.dot(rho, A2_diag)

# chi = \beta (<A^2> - <A>^2)
chi_static = beta * (A2_avg - A_avg**2)
Expand Down