qutip/core/cy/openmp/bench_openmp.py
import numpy as np
from qutip.settings import settings as qset
from timeit import default_timer as timer
def _min_timer(function, *args, **kwargs):
min_time = 1e6
for kk in range(10000):
t0 = timer()
function(*args, **kwargs)
t1 = timer()
min_time = min(min_time, t1-t0)
return min_time
def system_bench(func, dims):
from qutip.random_objects import rand_ket
ratio = 0
ratio_old = 0
nnz_old = 0
for N in dims:
L = func(N).data
vec = rand_ket(L.shape[0], 0.25).full().ravel()
nnz = L.nnz
out = np.zeros_like(vec)
ser = _min_timer(_spmvpy, L.data, L.indices, L.indptr, vec, 1, out)
out = np.zeros_like(vec)
par = _min_timer(_spmvpy_openmp, L.data, L.indices, L.indptr, vec, 1, out, 2)
ratio = ser/par
if ratio > 1:
break
nnz_old = nnz
ratio_old = ratio
if ratio > 1:
rate = (ratio-ratio_old)/(nnz-nnz_old)
return int((1.0-ratio_old)/rate+nnz_old)
else:
return -1
def calculate_openmp_thresh():
# if qset.num_cpus == 1:
# return qset.openmp_thresh
jc_dims = np.unique(np.logspace(0.45, 1.78, 20, dtype=int))
jc_result = system_bench(_jc_liouvillian, jc_dims)
opto_dims = np.unique(np.logspace(0.4, 1.33, 12, dtype=int))
opto_result = system_bench(_opto_liouvillian, opto_dims)
spin_dims = np.unique(np.logspace(0.45, 1.17, 10, dtype=int))
spin_result = system_bench(_spin_hamiltonian, spin_dims)
# Double result to be conservative
thresh = 2*int(max([jc_result, opto_result, spin_result]))
if thresh < 0:
thresh = np.iinfo(np.int32).max
return thresh
def _jc_liouvillian(N):
from qutip.core import tensor, destroy, qeye, liouvillian
wc = 2*np.pi * 1.0 # cavity frequency
wa = 2*np.pi * 1.0 # atom frequency
g = 2*np.pi * 0.05 # coupling strength
kappa = 0.005 # cavity dissipation rate
gamma = 0.05 # atom dissipation rate
n_th_a = 1 # temperature in frequency units
use_rwa = 0
# operators
a = tensor(destroy(N), qeye(2))
sm = tensor(qeye(N), destroy(2))
# Hamiltonian
H = wc*a.dag()*a + wa*sm.dag()*sm + g*(a.dag()*sm + a*sm.dag())
c_op_list = []
rate = kappa * (1 + n_th_a)
if rate > 0.0:
c_op_list.append(np.sqrt(rate) * a)
rate = kappa * n_th_a
if rate > 0.0:
c_op_list.append(np.sqrt(rate) * a.dag())
rate = gamma
if rate > 0.0:
c_op_list.append(np.sqrt(rate) * sm)
return liouvillian(H, c_op_list)
def _opto_liouvillian(N):
from qutip.core import tensor, destroy, qeye, liouvillian
Nc = 5 # Number of cavity states
Nm = N # Number of mech states
kappa = 0.3 # Cavity damping rate
E = 0.1 # Driving Amplitude
g0 = 2.4*kappa # Coupling strength
Qm = 1e4 # Mech quality factor
gamma = 1/Qm # Mech damping rate
n_th = 1 # Mech bath temperature
delta = -0.43 # Detuning
a = tensor(destroy(Nc), qeye(Nm))
b = tensor(qeye(Nc), destroy(Nm))
num_b = b.dag()*b
num_a = a.dag()*a
H = -delta*(num_a)+num_b+g0*(b.dag()+b)*num_a+E*(a.dag()+a)
cc = np.sqrt(kappa)*a
cm = np.sqrt(gamma*(1.0 + n_th))*b
cp = np.sqrt(gamma*n_th)*b.dag()
c_ops = [cc, cm, cp]
return liouvillian(H, c_ops)
def _spin_hamiltonian(N):
from qutip.core import tensor, qeye, sigmax, sigmay, sigmaz
# array of spin energy splittings and coupling strengths. here we use
# uniform parameters, but in general we don't have too
h = 2*np.pi * 1.0 * np.ones(N)
Jz = 2*np.pi * 0.1 * np.ones(N)
Jx = 2*np.pi * 0.1 * np.ones(N)
Jy = 2*np.pi * 0.1 * np.ones(N)
# dephasing rate
si = qeye(2)
sx = sigmax()
sy = sigmay()
sz = sigmaz()
sx_list = []
sy_list = []
sz_list = []
for n in range(N):
op_list = [si] * N
op_list[n] = sx
sx_list.append(tensor(op_list))
op_list[n] = sy
sy_list.append(tensor(op_list))
op_list[n] = sz
sz_list.append(tensor(op_list))
# construct the hamiltonian
H = 0
# energy splitting terms
for n in range(N):
H += - 0.5 * h[n] * sz_list[n]
# interaction terms
for n in range(N-1):
H += - 0.5 * Jx[n] * sx_list[n] * sx_list[n+1]
H += - 0.5 * Jy[n] * sy_list[n] * sy_list[n+1]
H += - 0.5 * Jz[n] * sz_list[n] * sz_list[n+1]
return H