import numpy as np
import multiprocessing as mp
import pyfftw
from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan
from numpy import heaviside as heav
from include import helper
import h5py


# ---------Spatial and potential parameters--------------
Mx = My = 64
Nx = Ny = 128  # Number of grid pts
dx = dy = 1 / 2  # Grid spacing
dkx = pi / (Mx * dx)
dky = pi / (My * dy)  # K-space spacing
len_x = Nx * dx     # Box length
len_y = Ny * dy
x = np.arange(-Mx, Mx) * dx
y = np.arange(-My, My) * dy
X, Y = np.meshgrid(x, y)  # Spatial meshgrid

data = h5py.File('../data/splitting_dipole_data.hdf5', 'a')
data.create_dataset('grid/x', x.shape, data=x)
data.create_dataset('grid/y', y.shape, data=y)

kx = np.fft.fftshift(np.arange(-Mx, Mx) * dkx)
ky = np.fft.fftshift(np.arange(-My, My) * dky)
Kx, Ky = np.meshgrid(kx, ky)  # K-space meshgrid

# Initialising FFTs
cpu_count = mp.cpu_count()
wfn_data = pyfftw.empty_aligned((Nx, Ny), dtype='complex128')
fft_forward = pyfftw.FFTW(wfn_data, wfn_data, axes=(0, 1), threads=cpu_count)
fft_backward = pyfftw.FFTW(wfn_data, wfn_data, direction='FFTW_BACKWARD', axes=(0, 1), threads=cpu_count)

# Framework for wavefunction data
psi_plus_k = pyfftw.empty_aligned((Nx, Ny), dtype='complex128')
psi_0_k = pyfftw.empty_aligned((Nx, Ny), dtype='complex128')
psi_minus_k = pyfftw.empty_aligned((Nx, Ny), dtype='complex128')

# Controlled variables
V = 0.  # Doubly periodic box
p = q = 0.
c0 = 2
c1 = 0.5  # Effective 3-component BEC
k = 0  # Array index

# ------------------------------ Generating SQV's -------------------------
# Euler angles
alpha = 0.
beta = pi / 4
gamma = 0.

N_vort = 2  # Number of vortices

pos = [-10, 0, 10, 0]
theta_k = np.empty((N_vort, Nx, Ny))
theta_tot = np.empty((Nx, Ny))

for k in range(N_vort // 2):
    # Scaling positional arguments
    Y_minus = 2 * pi * (Y - pos[k]) / len_y
    X_minus = 2 * pi * (X - pos[N_vort // 2 + k]) / len_x
    Y_plus = 2 * pi * (Y - pos[N_vort + k]) / len_y
    X_plus = 2 * pi * (X - pos[3 * N_vort // 2 + k]) / len_x
    x_plus = 2 * pi * pos[3 * N_vort // 2 + k] / len_x
    x_minus = 2 * pi * pos[N_vort // 2 + k] / len_x

    for nn in np.arange(-5, 5):
        theta_k[k, :, :] += arctan(
            tanh((Y_minus + 2 * pi * nn) / 2) * tan((X_minus - pi) / 2)) \
                            - arctan(tanh((Y_plus + 2 * pi * nn) / 2) * tan((X_plus - pi) / 2)) \
                            + pi * (heav(X_plus, 1.) - heav(X_minus, 1.))

    theta_k[k, :, :] -= (2 * pi * Y / len_y) * (x_plus - x_minus) / (2 * pi)
    theta_tot += theta_k[k, :, :]


# Initial wavefunction
Psi = np.empty((3, Nx, Ny), dtype='complex128')
Psi[0, :, :] = np.zeros((Nx, Ny)) + 0j
Psi[1, :, :] = np.ones((Nx, Ny), dtype='complex128') * exp(1j * theta_tot)
Psi[2, :, :] = np.zeros((Nx, Ny)) + 0j
psi_plus, psi_0, psi_minus = helper.rotation(Psi, Nx, Ny, alpha, beta, gamma)  # Performs rotation to wavefunction

# Aligning wavefunction to potentially speed up FFTs
pyfftw.byte_align(psi_plus)
pyfftw.byte_align(psi_0)
pyfftw.byte_align(psi_minus)
# ------------------------------------------------------------------------

# Normalisation constants
N_plus = dx * dy * np.linalg.norm(psi_plus) ** 2
N_0 = dx * dy * np.linalg.norm(psi_0) ** 2
N_minus = dx * dy * np.linalg.norm(psi_minus) ** 2

# Time steps, number and wavefunction save variables
Nt = 80000
Nframe = 200
dt = 5e-3
t = 0.

# Saving time variables:
data.create_dataset('time/Nt', data=Nt)
data.create_dataset('time/dt', data=dt)
data.create_dataset('time/Nframe', data=Nframe)

# Setting up variables to be sequentially saved:
psi_plus_save = data.create_dataset('wavefunction/psi_plus', (Nx, Ny, Nt/Nframe), dtype='complex128')
psi_0_save = data.create_dataset('wavefunction/psi_0', (Nx, Ny, Nt/Nframe), dtype='complex128')
psi_minus_save = data.create_dataset('wavefunction/psi_minus', (Nx, Ny, Nt/Nframe), dtype='complex128')

for i in range(Nt):
    # Spin vector terms:
    F_perp = sqrt(2.) * (conj(psi_plus) * psi_0 + conj(psi_0) * psi_minus)
    Fz = abs(psi_plus) ** 2 - abs(psi_minus) ** 2
    F = sqrt(abs(Fz) ** 2 + abs(F_perp) ** 2)  # Magnitude of spin vector

    # Total density
    n = abs(psi_minus) ** 2 + abs(psi_0) ** 2 + abs(psi_plus) ** 2

    # Sin and cosine terms for solution
    C = cos(c1 * F * (-1j * dt))
    if F.min() == 0:
        S = np.zeros((Nx, Ny), dtype='complex128')  # Ensures no division by zero
    else:
        S = 1j * sin(c1 * F * (-1j * dt)) / F

    # Forward FFTs
    fft_forward(psi_plus, psi_plus_k)
    fft_forward(psi_0, psi_0_k)
    fft_forward(psi_minus, psi_minus_k)

    # Computing kinetic energy + quadratic Zeeman
    psi_plus_k *= exp(-0.25 * dt * (Kx ** 2 + Ky ** 2 + 2 * q)) / (Nx * Ny)
    psi_0_k *= exp(-0.25 * dt * (Kx ** 2 + Ky ** 2)) / (Nx * Ny)
    psi_minus_k *= exp(-0.25 * dt * (Kx ** 2 + Ky ** 2 + 2 * q)) / (Nx * Ny)

    # Inverse FFTs
    fft_backward(psi_plus_k, psi_plus)
    fft_backward(psi_0_k, psi_0)
    fft_backward(psi_minus_k, psi_minus)

    # Rescaling
    psi_plus *= (Nx * Ny)
    psi_0 *= (Nx * Ny)
    psi_minus *= (Nx * Ny)

    # Trap, linear Zeeman & interaction flow
    psi_plus = ((C - S * Fz) * psi_plus - 1. / sqrt(2.) * S * conj(F_perp) * psi_0) * exp(-dt * (V - p + c0 * n))
    psi_0 = (-1. / sqrt(2.) * S * F_perp * psi_plus + C * psi_0 - 1. / sqrt(2.) * S * conj(F_perp) * psi_minus) \
            * exp(-dt * (V + c0 * n))
    psi_minus = (-1. / sqrt(2.) * S * F_perp * psi_0 + (C + S * Fz) * psi_minus) * exp(-dt * (V + p + c0 * n))

    # Forward FFTs
    fft_forward(psi_plus, psi_plus_k)
    fft_forward(psi_0, psi_0_k)
    fft_forward(psi_minus, psi_minus_k)

    # Computing kinetic energy + quadratic Zeeman
    psi_plus_k *= exp(-0.25 * dt * (Kx ** 2 + Ky ** 2 + 2 * q)) / (Nx * Ny)
    psi_0_k *= exp(-0.25 * dt * (Kx ** 2 + Ky ** 2)) / (Nx * Ny)
    psi_minus_k *= exp(-0.25 * dt * (Kx ** 2 + Ky ** 2 + 2 * q)) / (Nx * Ny)

    # Inverse FFTs
    fft_backward(psi_plus_k, psi_plus)
    fft_backward(psi_0_k, psi_0)
    fft_backward(psi_minus_k, psi_minus)

    # Rescaling
    psi_plus *= (Nx * Ny)
    psi_0 *= (Nx * Ny)
    psi_minus *= (Nx * Ny)

    # Renormalizing wavefunction
    psi_plus *= sqrt(N_plus) / sqrt(dx * dy * np.linalg.norm(psi_plus) ** 2)
    psi_0 *= sqrt(N_0) / sqrt(dx * dy * np.linalg.norm(psi_0) ** 2)
    psi_minus *= sqrt(N_minus) / sqrt(dx * dy * np.linalg.norm(psi_minus) ** 2)

    # Prints current time and saves data to an array
    if np.mod(i, Nframe) == 0:
        print('it = %1.4f' % t)

        psi_plus_save[:, :, k] = psi_plus[:, :]
        psi_0_save[:, :, k] = psi_0[:, :]
        psi_minus_save[:, :, k] = psi_minus[:, :]

        k += 1
    t += dt

data.close()

[((20, 7, 20, 24), 'numpy.meshgrid', 'np.meshgrid', ({(20, 19, 20, 20): 'x', (20, 22, 20, 23): 'y'}, {}), '(x, y)', True, 'import numpy as np\n'), ((22, 7, 22, 59), 'h5py.File', 'h5py.File', ({(22, 17, 22, 53): '"""../data/splitting_dipole_data.hdf5"""', (22, 55, 22, 58): '"""a"""'}, {}), "('../data/splitting_dipole_data.hdf5', 'a')", False, 'import h5py\n'), ((28, 9, 28, 28), 'numpy.meshgrid', 'np.meshgrid', ({(28, 21, 28, 23): 'kx', (28, 25, 28, 27): 'ky'}, {}), '(kx, ky)', True, 'import numpy as np\n'), ((31, 12, 31, 26), 'multiprocessing.cpu_count', 'mp.cpu_count', ({}, {}), '()', True, 'import multiprocessing as mp\n'), ((32, 11, 32, 61), 'pyfftw.empty_aligned', 'pyfftw.empty_aligned', (), '', False, 'import pyfftw\n'), ((33, 14, 33, 77), 'pyfftw.FFTW', 'pyfftw.FFTW', (), '', False, 'import pyfftw\n'), ((34, 15, 34, 105), 'pyfftw.FFTW', 'pyfftw.FFTW', (), '', False, 'import pyfftw\n'), ((37, 13, 37, 63), 'pyfftw.empty_aligned', 'pyfftw.empty_aligned', (), '', False, 'import pyfftw\n'), ((38, 10, 38, 60), 'pyfftw.empty_aligned', 'pyfftw.empty_aligned', (), '', False, 'import pyfftw\n'), ((39, 14, 39, 64), 'pyfftw.empty_aligned', 'pyfftw.empty_aligned', (), '', False, 'import pyfftw\n'), ((57, 10, 57, 36), 'numpy.empty', 'np.empty', ({(57, 19, 57, 35): '(N_vort, Nx, Ny)'}, {}), '((N_vort, Nx, Ny))', True, 'import numpy as np\n'), ((58, 12, 58, 30), 'numpy.empty', 'np.empty', ({(58, 21, 58, 29): '(Nx, Ny)'}, {}), '((Nx, Ny))', True, 'import numpy as np\n'), ((80, 6, 80, 47), 'numpy.empty', 'np.empty', (), '', True, 'import numpy as np\n'), ((84, 29, 84, 77), 'include.helper.rotation', 'helper.rotation', ({(84, 45, 84, 48): 'Psi', (84, 50, 84, 52): 'Nx', (84, 54, 84, 56): 'Ny', (84, 58, 84, 63): 'alpha', (84, 65, 84, 69): 'beta', (84, 71, 84, 76): 'gamma'}, {}), '(Psi, Nx, Ny, alpha, beta, gamma)', False, 'from include import helper\n'), ((87, 0, 87, 27), 'pyfftw.byte_align', 'pyfftw.byte_align', ({(87, 18, 87, 26): 'psi_plus'}, {}), '(psi_plus)', False, 'import pyfftw\n'), ((88, 0, 88, 24), 'pyfftw.byte_align', 'pyfftw.byte_align', ({(88, 18, 88, 23): 'psi_0'}, {}), '(psi_0)', False, 'import pyfftw\n'), ((89, 0, 89, 28), 'pyfftw.byte_align', 'pyfftw.byte_align', ({(89, 18, 89, 27): 'psi_minus'}, {}), '(psi_minus)', False, 'import pyfftw\n'), ((18, 4, 18, 22), 'numpy.arange', 'np.arange', ({(18, 14, 18, 17): '(-Mx)', (18, 19, 18, 21): 'Mx'}, {}), '(-Mx, Mx)', True, 'import numpy as np\n'), ((19, 4, 19, 22), 'numpy.arange', 'np.arange', ({(19, 14, 19, 17): '(-My)', (19, 19, 19, 21): 'My'}, {}), '(-My, My)', True, 'import numpy as np\n'), ((69, 14, 69, 30), 'numpy.arange', 'np.arange', ({(69, 24, 69, 26): '(-5)', (69, 28, 69, 29): '(5)'}, {}), '(-5, 5)', True, 'import numpy as np\n'), ((81, 15, 81, 33), 'numpy.zeros', 'np.zeros', ({(81, 24, 81, 32): '(Nx, Ny)'}, {}), '((Nx, Ny))', True, 'import numpy as np\n'), ((82, 15, 82, 52), 'numpy.ones', 'np.ones', (), '', True, 'import numpy as np\n'), ((82, 55, 82, 74), 'numpy.exp', 'exp', ({(82, 59, 82, 73): '(1.0j * theta_tot)'}, {}), '(1.0j * theta_tot)', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((83, 15, 83, 33), 'numpy.zeros', 'np.zeros', ({(83, 24, 83, 32): '(Nx, Ny)'}, {}), '((Nx, Ny))', True, 'import numpy as np\n'), ((123, 8, 123, 32), 'numpy.cos', 'cos', ({(123, 12, 123, 31): 'c1 * F * (-1.0j * dt)'}, {}), '(c1 * F * (-1.0j * dt))', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((26, 21, 26, 39), 'numpy.arange', 'np.arange', ({(26, 31, 26, 34): '-Mx', (26, 36, 26, 38): 'Mx'}, {}), '(-Mx, Mx)', True, 'import numpy as np\n'), ((27, 21, 27, 39), 'numpy.arange', 'np.arange', ({(27, 31, 27, 34): '-My', (27, 36, 27, 38): 'My'}, {}), '(-My, My)', True, 'import numpy as np\n'), ((93, 19, 93, 43), 'numpy.linalg.norm', 'np.linalg.norm', ({(93, 34, 93, 42): 'psi_plus'}, {}), '(psi_plus)', True, 'import numpy as np\n'), ((94, 16, 94, 37), 'numpy.linalg.norm', 'np.linalg.norm', ({(94, 31, 94, 36): 'psi_0'}, {}), '(psi_0)', True, 'import numpy as np\n'), ((95, 20, 95, 45), 'numpy.linalg.norm', 'np.linalg.norm', ({(95, 35, 95, 44): 'psi_minus'}, {}), '(psi_minus)', True, 'import numpy as np\n'), ((115, 13, 115, 21), 'numpy.sqrt', 'sqrt', ({(115, 18, 115, 20): '(2.0)'}, {}), '(2.0)', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((125, 12, 125, 50), 'numpy.zeros', 'np.zeros', (), '', True, 'import numpy as np\n'), ((135, 18, 135, 63), 'numpy.exp', 'exp', ({(135, 22, 135, 62): '(-0.25 * dt * (Kx ** 2 + Ky ** 2 + 2 * q))'}, {}), '(-0.25 * dt * (Kx ** 2 + Ky ** 2 + 2 * q))', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((136, 15, 136, 52), 'numpy.exp', 'exp', ({(136, 19, 136, 51): '(-0.25 * dt * (Kx ** 2 + Ky ** 2))'}, {}), '(-0.25 * dt * (Kx ** 2 + Ky ** 2))', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((137, 19, 137, 64), 'numpy.exp', 'exp', ({(137, 23, 137, 63): '(-0.25 * dt * (Kx ** 2 + Ky ** 2 + 2 * q))'}, {}), '(-0.25 * dt * (Kx ** 2 + Ky ** 2 + 2 * q))', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((150, 86, 150, 113), 'numpy.exp', 'exp', ({(150, 90, 150, 112): '(-dt * (V - p + c0 * n))'}, {}), '(-dt * (V - p + c0 * n))', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((152, 14, 152, 37), 'numpy.exp', 'exp', ({(152, 18, 152, 36): '(-dt * (V + c0 * n))'}, {}), '(-dt * (V + c0 * n))', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((153, 83, 153, 110), 'numpy.exp', 'exp', ({(153, 87, 153, 109): '(-dt * (V + p + c0 * n))'}, {}), '(-dt * (V + p + c0 * n))', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((161, 18, 161, 63), 'numpy.exp', 'exp', ({(161, 22, 161, 62): '(-0.25 * dt * (Kx ** 2 + Ky ** 2 + 2 * q))'}, {}), '(-0.25 * dt * (Kx ** 2 + Ky ** 2 + 2 * q))', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((162, 15, 162, 52), 'numpy.exp', 'exp', ({(162, 19, 162, 51): '(-0.25 * dt * (Kx ** 2 + Ky ** 2))'}, {}), '(-0.25 * dt * (Kx ** 2 + Ky ** 2))', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((163, 19, 163, 64), 'numpy.exp', 'exp', ({(163, 23, 163, 63): '(-0.25 * dt * (Kx ** 2 + Ky ** 2 + 2 * q))'}, {}), '(-0.25 * dt * (Kx ** 2 + Ky ** 2 + 2 * q))', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((176, 16, 176, 28), 'numpy.sqrt', 'sqrt', ({(176, 21, 176, 27): 'N_plus'}, {}), '(N_plus)', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((177, 13, 177, 22), 'numpy.sqrt', 'sqrt', ({(177, 18, 177, 21): 'N_0'}, {}), '(N_0)', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((178, 17, 178, 30), 'numpy.sqrt', 'sqrt', ({(178, 22, 178, 29): 'N_minus'}, {}), '(N_minus)', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((181, 7, 181, 24), 'numpy.mod', 'np.mod', ({(181, 14, 181, 15): 'i', (181, 17, 181, 23): 'Nframe'}, {}), '(i, Nframe)', True, 'import numpy as np\n'), ((115, 25, 115, 39), 'numpy.conj', 'conj', ({(115, 30, 115, 38): 'psi_plus'}, {}), '(psi_plus)', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((115, 50, 115, 61), 'numpy.conj', 'conj', ({(115, 55, 115, 60): 'psi_0'}, {}), '(psi_0)', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((127, 17, 127, 41), 'numpy.sin', 'sin', ({(127, 21, 127, 40): '(c1 * F * (-1.0j * dt))'}, {}), '(c1 * F * (-1.0j * dt))', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((73, 36, 73, 52), 'numpy.heaviside', 'heav', ({(73, 41, 73, 47): 'X_plus', (73, 49, 73, 51): '(1.0)'}, {}), '(X_plus, 1.0)', True, 'from numpy import heaviside as heav\n'), ((73, 55, 73, 72), 'numpy.heaviside', 'heav', ({(73, 60, 73, 67): 'X_minus', (73, 69, 73, 71): '(1.0)'}, {}), '(X_minus, 1.0)', True, 'from numpy import heaviside as heav\n'), ((150, 62, 150, 74), 'numpy.conj', 'conj', ({(150, 67, 150, 73): 'F_perp'}, {}), '(F_perp)', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((151, 86, 151, 98), 'numpy.conj', 'conj', ({(151, 91, 151, 97): 'F_perp'}, {}), '(F_perp)', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((176, 46, 176, 70), 'numpy.linalg.norm', 'np.linalg.norm', ({(176, 61, 176, 69): 'psi_plus'}, {}), '(psi_plus)', True, 'import numpy as np\n'), ((177, 40, 177, 61), 'numpy.linalg.norm', 'np.linalg.norm', ({(177, 55, 177, 60): 'psi_0'}, {}), '(psi_0)', True, 'import numpy as np\n'), ((178, 48, 178, 73), 'numpy.linalg.norm', 'np.linalg.norm', ({(178, 63, 178, 72): 'psi_minus'}, {}), '(psi_minus)', True, 'import numpy as np\n'), ((71, 12, 71, 45), 'numpy.tanh', 'tanh', ({(71, 17, 71, 44): '((Y_minus + 2 * pi * nn) / 2)'}, {}), '((Y_minus + 2 * pi * nn) / 2)', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((71, 48, 71, 71), 'numpy.tan', 'tan', ({(71, 52, 71, 70): '((X_minus - pi) / 2)'}, {}), '((X_minus - pi) / 2)', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((72, 37, 72, 69), 'numpy.tanh', 'tanh', ({(72, 42, 72, 68): '((Y_plus + 2 * pi * nn) / 2)'}, {}), '((Y_plus + 2 * pi * nn) / 2)', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((72, 72, 72, 94), 'numpy.tan', 'tan', ({(72, 76, 72, 93): '((X_plus - pi) / 2)'}, {}), '((X_plus - pi) / 2)', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((150, 47, 150, 55), 'numpy.sqrt', 'sqrt', ({(150, 52, 150, 54): '(2.0)'}, {}), '(2.0)', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((151, 71, 151, 79), 'numpy.sqrt', 'sqrt', ({(151, 76, 151, 78): '(2.0)'}, {}), '(2.0)', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((153, 23, 153, 31), 'numpy.sqrt', 'sqrt', ({(153, 28, 153, 30): '(2.0)'}, {}), '(2.0)', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n'), ((151, 19, 151, 27), 'numpy.sqrt', 'sqrt', ({(151, 24, 151, 26): '(2.0)'}, {}), '(2.0)', False, 'from numpy import pi, exp, sqrt, sin, cos, conj, arctan, tanh, tan\n')]