In [38]:
import numpy as np
from boxvectors import directions as directions
import Initial_Parameters as ip
from md import System
from md import md
from distribution import maxwellboltzmann
import matplotlib.pyplot as plt
from scipy.special import erf
from scipy.special import erfc
from scipy.constants import epsilon_0
%matplotlib inline

In [2]:
Symbols = ip.Symbols
Coefficients = ip.Coefficients
Charges = ip.Charges
N = ip.N*np.sum(Coefficients)
L = ip.L
T = ip.T
dt = ip.dt
p_rea = ip.p_rea
p = ip.p
std = ip.std
k_cut = ip.k_cut
k_max = ip.k_max_long_range
n_boxes_LJ = ip.n_boxes_LJ
n_boxes_coulomb = ip.n_boxes_short_range
Sys= System(Symbols, Coefficients, Charges, N/2)
Labels = Sys.get_Labels()
Sigma, Epsilon = Sys.get_LJ_parameter()

m = Labels[:,0]

In [3]:
switch_parameter = np.array([1,-1,0,0])
r_switch = 1.5

In [4]:
def get_random_starting_Positions(N,L):
    Positions = np.zeros((N,3))
    Positions[:,0] = np.linspace(0.1,L[0],N, endpoint = False)
    Positions[:,1] = np.linspace(0.1,L[1],N, endpoint = False)
    Positions[:,2] = np.linspace(0.1,L[2],N, endpoint = False)
    np.random.shuffle(Positions[:,0])
    np.random.shuffle(Positions[:,1])
    np.random.shuffle(Positions[:,2])
    return Positions
Positions = get_random_starting_Positions(N,L)
Velocities = maxwellboltzmann().sample_distribution(N,m,T)
Forces = np.zeros((N,3))
R = np.linalg.norm(Positions,axis=1)

In [5]:
MD = md(
    Positions, 
    R, 
    Labels, 
    Velocities,
    Forces, 
    L, 
    T, 
    std, 
    Sigma, 
    Epsilon, 
    switch_parameter,
    r_switch, 
    n_boxes_coulomb, 
    k_max, 
    dt, 
    p_rea,
    k_cut)

In [6]:
MD.forces = MD.get_forces()

In [7]:
Temperature = np.zeros(10)
for i in np.arange(10):
    Positions_New, Velocities_New, Forces_New = MD.propagte_system()
    MD.positions = Positions_New
    MD.velocities = Velocities_New
    MD.forces = Forces_New
    Temperature[i] = MD.get_Temperature()
plt.plot(Temperature)


Out[7]:
[<matplotlib.lines.Line2D at 0x8370d30>]

In [19]:
Temperature


Out[19]:
array([  3.96552949e+43,   1.74062368e+44,   3.71070368e+44,
         4.56206623e+44,   5.47893188e+44,   6.53399312e+44,
         7.47223570e+44,   8.94799804e+44,   1.05401374e+45,
         1.12968365e+45])

In [17]:
Velocities = maxwellboltzmann().sample_distribution(N,m,T)
Velocities
MD.velocities


Out[17]:
array([[ -8.24032712e+23,  -7.73709893e+23,  -2.88629681e+23],
       [ -3.06246862e+22,  -9.26078991e+23,  -7.01418820e+23],
       [  3.21530228e+23,   1.19993267e+24,   1.22785921e+24],
       [ -1.66893485e+23,   3.58161183e+23,   1.65191985e+23],
       [ -1.12941398e+23,   1.01393354e+23,  -3.41284558e+23],
       [ -1.08422353e+24,   6.66747542e+23,   4.82473640e+23],
       [  4.66414316e+23,  -3.34191086e+23,   8.77189129e+23],
       [  1.35478548e+24,   9.17481913e+22,  -1.42588841e+24],
       [  5.39460336e+23,   9.94064535e+23,  -4.90034434e+23],
       [ -3.96625825e+23,  -1.23179785e+24,   2.97660864e+23],
       [  4.53301847e+23,  -7.22418684e+23,   6.64770262e+22],
       [  3.47995242e+23,   1.34862248e+23,   5.47854628e+23],
       [ -4.45388470e+22,   7.94015356e+22,   2.86797372e+23],
       [  1.10943438e+23,   1.72179080e+23,  -7.72806375e+23],
       [  3.23222984e+23,  -3.62124999e+22,  -1.77424368e+23],
       [ -1.64403393e+23,   4.38557091e+23,   1.95712924e+23],
       [ -6.28402664e+23,  -5.62366623e+23,   6.93286089e+23],
       [  2.11223771e+23,   2.33188550e+23,  -6.27659899e+23],
       [ -7.68610560e+21,   1.61293227e+23,  -3.62675457e+23],
       [ -5.86001844e+23,   5.70718430e+22,   3.38577644e+23]])

In [20]:
from particle_interaction import lennard_jones

In [35]:
def __short_range_forces(self,Positions,R, Labels,L):
    ''' Calculate the Force resulting from the short range coulomb interaction between the Particles

    Parameters
    ---------------

    Positions: Nx3 Array
        Array with N rows and 3 Columns, each row i contains the x,y and z coordinates of particle i.

    R: Nx1 Array
        Array with N entries. Contains each Particles Distance to the coordinate origin.

    Labels: Nx? Array
        Array with N rows and ? Columns. The third Column should contain labels, that specify the chemical species of the Particles.
        Particle A should have the label 1 and Particle B should have the label 0.

    L:3x1 Array
        Array containg the Dimensions of the Simulation box


    Returns
    --------------

    Force_short_range: Nx3 Array
        Array with N rows and 3 Columns. Each Row i contains the short-range-Force acting upon Particle i componentwise. 

    '''
    K = self.LinComb(self.n_boxes_short_range)
    K[:,0] *=L[0]
    K[:,1] *=L[1]
    K[:,2] *=L[2]

    N = np.size(Positions[:,0])
    Force_short_range = np.zeros((N,3))
    k = np.size(K[:,0])
    charges_pre_delete = np.zeros((N,3))
    charges_pre_delete[:,0]=Labels[:,1]  
    charges_pre_delete[:,1]=Labels[:,1] 
    charges_pre_delete[:,2]=Labels[:,1] 
    for i in np.arange(N):

        dists_single_cell_pre_delete = Positions[i,:]-Positions
        dists_single_cell = np.delete(dists_single_cell_pre_delete,i,0)
        charges = np.delete(charges_pre_delete,i,0)
        #This Skript paralellizes the sum over j and executes the sum over vectors n within the loop
        for j in np.arange(k):
            dists = dists_single_cell+K[j]

            norm_dists = np.linalg.norm(dists)

            Force_short_range[i,:] += np.sum(charges*dists/norm_dists**2 
            *( erfc( dists/np.sqrt(2)/self.std )/norm_dists 
            + np.sqrt(2.0/np.pi)/self.std*np.exp(-norm_dists**2/(2*self.std**2) )) ,0)

    #Getting the Pre-factor right        
    Force_short_range = Force_short_range* charges_pre_delete /(8*np.pi*epsilon_0)
    return Force_short_range


def __long_range_forces(self,Positions,Labels,L):
    ''' Calculate the Force resulting from the long range Coulomb interaction between the Particles

    Parameters
    ---------------

    Positions: Nx3 Array
        Array with N rows and 3 Columns, each row i contains the x,y and z coordinates of particle i.

    Labels: Nx? Array
        Array with N rows and ? Columns. The third Column should contain labels, that specify the chemical species of the Particles.
        Particle A should have the label 1 and Particle B should have the label 0.

    L:3x1 Array
        Array containg the Dimensions of the Simulation box


    Returns
    --------------

    Force_long_range: Nx3 Array
        Array with N rows and 3 Columns. Each Row i contains the long-range-Force acting upon Particle i componentwise. 

    '''
    i = np.complex(0,1)

    # setup k-vector matrix
    k = self.LinComb(self.k_max_long_range)*(2*np.pi)/L[0]
    # two k-vectors i,j have property k_i = -k_j respectively, delete one of them and delete k = (0,0,0)
    k = np.delete(k, (np.arange((np.shape(k)[0]+1)/2)), axis=0)
    # delete all k-vectors that are longer than cutoff
    k = np.delete(k, (np.where(np.sqrt(sum(np.transpose(k**2))) > self.k_cut)[0]), axis=0)

    # setup data needed for calculation
    k_betqua = sum(np.transpose(k**2))          # |k|^2
    num_k = np.shape(k_betqua)[0]               # number of k-vectors
    num_Par = np.shape(Positions)[0]            # number of particles
    f_1 = np.zeros((num_k,3))                   # placeholder for Forces during summation over k outside of for second loop
    f_2 = np.zeros((num_k))                     # placeholder for Forces during summation over k in second for-loop
    Force_long_range = np.zeros((num_Par,3))    # placeholder for long ranged forces
    charges = np.zeros((num_Par,3))             # create num_Par x 3 matrix with charges
    charges[:,0]=Labels[:,1]                    # in each column L[:,1] repeated
    charges[:,1]=Labels[:,1] 
    charges[:,2]=Labels[:,1]

    for h in np.arange(num_Par):    # loop over all particles

        for j in np.arange(num_k):  # loop over all k-vectors

            # "structure factor" sum (right sum in equation)
            f_2[j] = sum(Labels[:,1]*np.sin(np.dot(k[j,:],(Positions[h,:]*np.ones((num_Par,3)) - Positions).transpose())))

        # complete sum over all k, (left part of equation)
        f_1 = (((np.exp(-self.std**2/2*k_betqua)/k_betqua)*f_2)*np.ones((3,num_k))).transpose()*k  

        # actually sum over all k
        Force_long_range[h,:] = sum(f_1)   

    # get prefactor right                                      
    Force_long_range *= charges/(L[0]**3*epsilon_0)*2      # multiply by 2 because of symmetry properties of sine
    return Force_long_range

In [47]:
print (__short_range_forces(MD.coulomb, Positions, R, Labels, L))
print (__long_range_forces(MD.coulomb, Positions, Labels, L))
print  np.average(__long_range_forces(MD.coulomb, Positions, Labels, L)+__short_range_forces(MD.coulomb, Positions, R, Labels, L))


[[ 81018343.62800054  27110691.18900659  18962062.21340424]
 [ 73220400.84721398  23095557.94823673  27914585.04807917]
 [ 56852453.64127816  22292279.11197296  28615699.53978898]
 [ 81109952.12194264  28630121.9085355   29881081.48315293]
 [ 76882265.50147213  21016496.6666749   15439546.24306967]
 [ 94692958.32901129  24804432.75349204   7725303.0119257 ]
 [ 63939464.068956    22845886.85568941  36347441.45746564]
 [ 77516613.38710138  38785988.88872149  23279219.7408941 ]
 [ 86899568.17006186  14047366.73417427  45517545.50065438]
 [ 87168249.16352139  10596730.16783401  32920180.9768502 ]
 [-69717487.90918618   9512690.72943456  17422202.95625907]
 [-21015849.21754062  -2299995.78915987   9023229.94366373]
 [-50910222.91807438 -10134792.28561539  -7368074.77566294]
 [-82111953.30256502  16982812.68940496  19059813.9036541 ]
 [-19465641.26939055  11750699.61395064   9323484.55221299]
 [-56009632.01297209   9860429.50244155  16013633.07631915]
 [-52502374.85215947  12169194.60967492   8692124.81384536]
 [-25732146.15529962  10938155.77268996  16241492.00538153]
 [-21616672.73897418   7778074.65659477   5670860.55145139]
 [-32311897.41559734  14801339.87654409  -3709476.43799308]]
[[ -6.43779069e+09   5.62426356e+09  -1.62276817e+10]
 [  1.18825114e+10  -4.51601452e+09   8.33657378e+09]
 [  4.67578600e+08   5.28369989e+09   1.17050372e+10]
 [ -4.43692244e+09  -8.80352292e+08   5.63917866e+08]
 [ -1.84260744e+10  -1.50046954e+09  -4.75556335e+08]
 [  4.30390242e+08   3.55334933e+08   4.12234467e+09]
 [  7.14485731e+09   3.63936970e+09   6.79141665e+08]
 [ -1.21635171e+09  -3.17594854e+09  -9.45406872e+09]
 [  3.98813414e+09   4.01765209e+09  -6.39871257e+09]
 [  3.84917022e+09  -7.41311052e+09   1.84911640e+09]
 [  1.21736964e+10  -3.76019037e+09   5.01392936e+09]
 [  1.43626709e+10  -1.17853994e+10   2.50406394e+09]
 [  9.03736269e+09  -1.78584456e+09  -1.11290772e+10]
 [ -6.65852710e+09  -1.58500661e+09   8.30111224e+08]
 [  2.53279451e+09   3.57447872e+09   6.66830447e+09]
 [ -1.35126236e+09   1.02048336e+09   9.48821647e+09]
 [ -7.06579254e+09  -4.78136221e+09   1.09650724e+10]
 [ -3.12216997e+09   7.22850198e+09  -4.98252730e+08]
 [ -4.80886833e+09  -4.01103500e+07  -4.84670907e+09]
 [ -1.23454069e+10   1.04800247e+10  -1.36957711e+10]]
16991041.8079

In [75]:
K = MD.coulomb.LinComb(MD.coulomb.n_boxes_short_range)
K[:,0] *=L[0]
K[:,1] *=L[1]
K[:,2] *=L[2]

N = np.size(Positions[:,0])
Force_short_range = np.zeros((N,3))
k = np.size(K[:,0])
charges_pre_delete = np.zeros((N,3))
charges_pre_delete[:,0]=Labels[:,1]  
charges_pre_delete[:,1]=Labels[:,1] 
charges_pre_delete[:,2]=Labels[:,1] 
for i in np.arange(N):

    dists_single_cell_pre_delete = Positions[i,:]-Positions
    dists_single_cell = np.delete(dists_single_cell_pre_delete,i,0)
    charges = np.delete(charges_pre_delete,i,0)
    #This Skript paralellizes the sum over j and executes the sum over vectors n within the loop
    for j in np.arange(k):
        dists = dists_single_cell+K[j]

        norm_dists = np.linalg.norm(dists)

        Force_short_range[i,:] += np.sum(charges*dists/norm_dists**2 
        *( erfc( dists/np.sqrt(2)/std )/norm_dists 
        + np.sqrt(2.0/np.pi)/std * np.exp(-norm_dists**2/(2*std**2) )) ,0)
        
#Getting the Pre-factor right        
Force_short_range = Force_short_range* charges_pre_delete /(8*np.pi*epsilon_0)

In [76]:
charges_pre_delete /(8*np.pi*epsilon_0)


Out[76]:
array([[  4.49377589e+09,   4.49377589e+09,   4.49377589e+09],
       [  4.49377589e+09,   4.49377589e+09,   4.49377589e+09],
       [  4.49377589e+09,   4.49377589e+09,   4.49377589e+09],
       [  4.49377589e+09,   4.49377589e+09,   4.49377589e+09],
       [  4.49377589e+09,   4.49377589e+09,   4.49377589e+09],
       [  4.49377589e+09,   4.49377589e+09,   4.49377589e+09],
       [  4.49377589e+09,   4.49377589e+09,   4.49377589e+09],
       [  4.49377589e+09,   4.49377589e+09,   4.49377589e+09],
       [  4.49377589e+09,   4.49377589e+09,   4.49377589e+09],
       [  4.49377589e+09,   4.49377589e+09,   4.49377589e+09],
       [ -4.49377589e+09,  -4.49377589e+09,  -4.49377589e+09],
       [ -4.49377589e+09,  -4.49377589e+09,  -4.49377589e+09],
       [ -4.49377589e+09,  -4.49377589e+09,  -4.49377589e+09],
       [ -4.49377589e+09,  -4.49377589e+09,  -4.49377589e+09],
       [ -4.49377589e+09,  -4.49377589e+09,  -4.49377589e+09],
       [ -4.49377589e+09,  -4.49377589e+09,  -4.49377589e+09],
       [ -4.49377589e+09,  -4.49377589e+09,  -4.49377589e+09],
       [ -4.49377589e+09,  -4.49377589e+09,  -4.49377589e+09],
       [ -4.49377589e+09,  -4.49377589e+09,  -4.49377589e+09],
       [ -4.49377589e+09,  -4.49377589e+09,  -4.49377589e+09]])