def exp_x_time(rho_operator, time):
    x_operator_average = np.empty(len(time), dtype=float)
    p_operator_average = np.empty(len(time), dtype=float)
    for j in range(len(time)):
        rho = np.matrix(rho_operator[:, :, j])
        x_operator_average[j] = qfl.trace_matrix(rho * x_operator)
        p_operator_average[j] = qfl.trace_matrix(rho * p_operator)
    return x_operator_average, p_operator_average
def prob_and_proj_time(rho_operator, time):
    prob_in_time = np.empty((len(time), len(x_grid_midpoints[0])), dtype=float)
    proj_A_time = np.empty(len(time), dtype=float)
    for j in range(len(time)):
        rho = np.matrix(rho_operator[:, :, j])
        proj_A_time[j] = qfl.trace_matrix(rho * project_A)
        for k in range(len(x_grid_projectors)):
            prob_in_time[j, k] = qfl.trace_matrix(x_grid_projectors[k] * rho)
    return prob_in_time, proj_A_time
def eval_current_density_tran_rate(rho_operator, time):
    current_density_tran_rate = np.empty(len(time), dtype=float)
    for j in range(len(time)):
        rho = np.matrix(rho_operator[:, :, j])
        current_density_tran_rate[j] = qfl.trace_matrix(
            current_density_flux_at_x0 * project_B * rho) / 0.5
    return current_density_tran_rate
def init_prob_density_distr(init_rho, x_grid_projectors):
    init_prob_den_distr = np.zeros(len(x_grid_projectors), dtype=float)
    for k in range(len(x_grid_projectors)):
        init_prob_den_distr[k] = qfl.trace_matrix(x_grid_projectors[k] *
                                                  init_rho)
    return init_prob_den_distr
    xmax = matdata['x_limits'][0][1]
except Exception as e:
    raise ('Data has to be generated first')

### Defining constants and operators that will be adjusted in project
gamma = 0.1 / 2
T = 0.25
lindblad = np.sqrt(4 * mass * kb * T *
                   gamma) / hbar * x_operator + 1j * np.sqrt(gamma) / (np.sqrt(
                       4 * mass * kb * T)) * p_operator
hamiltonian = h_sys + gamma / 2 * (x_operator * p_operator +
                                   p_operator * x_operator)

### Start from rho_equilibrium state projected onto A
rho_equilibrium = qfl.exp_matrix(-h_sys / (kb * T))
rho_equilibrium = rho_equilibrium / qfl.trace_matrix(rho_equilibrium)
init_rho = project_A * rho_equilibrium
init_rho = init_rho / qfl.trace_matrix(init_rho)

### Define name to save figures automatically
init_state_str = 'eq_state_t' + str(T).replace(".", "") + '_'

### Plotting the initial state

### Creating quicker function to plot the initial probability density distribution.
### Have not timed it. Effectiveness is dubious. Should probably consider vectorising
### but that would probably involve re-writing trace_matrix to accomodate arrays
### or finding apply function. FIX ME.


@numba.jit
gamma = 0.01 / 2
lindblad = np.sqrt(4 * mass * kb * T *
                   gamma) / hbar * x_operator + 1j * np.sqrt(gamma) / (np.sqrt(
                       4 * mass * kb * T)) * p_operator
hamiltonian = h_sys + gamma / 2 * (x_operator * p_operator +
                                   p_operator * x_operator)

### Start from this wavefunction
p_init = 0.1
q_init = 1
init_state = qfl.init_coherent_state(dim, p_init, q_init, mass, omega, hbar)
init_state_str = 'coherent_state_' + 'q' + str(q_init).replace(
    ".", "") + 'p_init' + str(p_init).replace(".", "")

init_rho = init_state * init_state.getH()
init_rho = init_rho / qfl.trace_matrix(init_rho)

#### RESULTS START HERE

#### Getting the time evolution of rho and prob density

### For most of graphs
short_time_step = 0.001
short_no_steps = 5000

rho_operator_short_time = qfl.rho_lindblad_superoperator(
    init_rho, hamiltonian, lindblad, hbar, short_time_step, short_no_steps)

print("checkpoint5")

short_time = np.arange(0, short_no_steps * short_time_step, short_time_step)