// File: /workspace/github_cpp_makefile_star2_O1/shuwenyue[P]MD_code_cell_list/particle.cpp
// Function: particle::initialize(double, int, double, double)
void particle::initialize(double BoxLength, int NParticles, double T, double dt)
{
	int particles = 0;

	// resize NParticles x 3 matrices to hold positions, previous positions, and velocities
	positionVector.resize(NParticles);
    positionPrevVector.resize(NParticles);
    velocityVector.resize(NParticles);

	// calculate length of lattice box, or alternatively the length a particle "takes up"
	double ParticleLength = BoxLength/pow(NParticles,1.0/3.0);

	// calculate number of lattice boxes on each side of big box, also the number of particles in 1 dimension of box
	double ParticlesPerSide = pow(NParticles, 1.0/3.0);	

	// initialize positions, looping over x, y, z directions of lattice to place particle at each point
	for (int x = 0; x < ParticlesPerSide; x++)
	{
		for (int y = 0; y < ParticlesPerSide; y++)
		{
			for (int z = 0; z < ParticlesPerSide; z++) 
			{
				// x,y,z coordinates for 1 single particle
				// position = cooridinate * lattice box length
				position.x = x * ParticleLength; 
				position.y = y * ParticleLength;
				position.z = z * ParticleLength;

				// put that position of 1 particle in positionVector corresponding to particle number
				positionVector[particles] = position;

				particles = particles + 1;

			}
		}
	}

	// initialize velocity variables to 0
    double totalVx = 0;
    double totalVy = 0;
    double totalVz = 0;
    double totalV2 = 0;

	// initialize velocities using random numbers
	for (int j = 0; j < NParticles; j++)
	{
		// draw random number from -0.5 and 0.5 for velocity of 1 particle
        velocityVector[j].x = (rand() / double(RAND_MAX)) - 0.5;
        velocityVector[j].y = (rand() / double(RAND_MAX)) - 0.5;
        velocityVector[j].z = (rand() / double(RAND_MAX)) - 0.5;
       
        // add random new velocity to total velocity 
        totalVx = totalVx + velocityVector[j].x;
        totalVy = totalVy + velocityVector[j].y;
        totalVz = totalVz + velocityVector[j].z;
       
		// total velocity^2 calculated from all 3 components 
        totalV2 = totalV2 + (velocityVector[j].x)*(velocityVector[j].x) + (velocityVector[j].y)*(velocityVector[j].y) + (velocityVector[j].z)*(velocityVector[j].z);

	}

	// average total velocities to each particle
	double averageVx;
	double averageVy;
	double averageVz;
	double averageV2;

	// average velocities over all particles
    averageVx = totalVx/NParticles;
    averageVy = totalVy/NParticles;
    averageVz = totalVz/NParticles;
    averageV2 = totalV2/NParticles;
    
    // scale factor for velocities
    double fScale = sqrt((3*T)/averageV2);
	box boxObj;
    
    for (int k = 0; k < NParticles; k++)
    {
		// subtracting by averageV gives center of mass = 0 so box does not shift
		// fscale assigns the correct velocity to produce the input temperature
        velocityVector[k].x = (velocityVector[k].x - averageVx) * fScale;
        velocityVector[k].y = (velocityVector[k].y - averageVy) * fScale;
        velocityVector[k].z = (velocityVector[k].z - averageVz) * fScale;
       
		// initialize matrix of 'previous' positions by moving 1 time step
        positionPrevVector[k].x = positionVector[k].x - (velocityVector[k].x)*dt;
        positionPrevVector[k].y = positionVector[k].y - (velocityVector[k].y)*dt;
        positionPrevVector[k].z = positionVector[k].z - (velocityVector[k].z)*dt;

		// periodic boundary conditions
		positionPrevVector[k].x = boxObj.pbc(positionPrevVector[k].x, BoxLength);
		positionPrevVector[k].y = boxObj.pbc(positionPrevVector[k].y, BoxLength);
		positionPrevVector[k].z = boxObj.pbc(positionPrevVector[k].z, BoxLength);
    }

}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movapd %xmm2, 0x50(%rsp)
movsd %xmm1, 0x70(%rsp)
movl %esi, %ebp
movsd %xmm0, 0x18(%rsp)
movq %rdi, %r12
leaq 0x18(%rdi), %rbx
movslq %esi, %r13
movq %rbx, %rdi
movq %r13, %rsi
callq 0x3e7c
leaq 0x30(%r12), %r14
movq %r14, %rdi
movq %r13, %rsi
callq 0x3e7c
leaq 0x48(%r12), %r15
movq %r15, %rdi
movq %r13, %rsi
callq 0x3e7c
xorps %xmm0, %xmm0
cvtsi2sd %r13d, %xmm0
movapd %xmm0, 0x20(%rsp)
movsd 0x1d0b(%rip), %xmm1     # 0x5008
callq 0x21f0
movsd %xmm0, 0x8(%rsp)
movapd 0x20(%rsp), %xmm0
movsd 0x1cf2(%rip), %xmm1     # 0x5008
callq 0x21f0
xorpd %xmm5, %xmm5
ucomisd %xmm5, %xmm0
jbe 0x33cb
movsd 0x18(%rsp), %xmm1
divsd 0x8(%rsp), %xmm1
xorl %eax, %eax
xorpd %xmm2, %xmm2
xorl %ecx, %ecx
mulsd %xmm1, %xmm2
xorpd %xmm3, %xmm3
xorl %edx, %edx
mulsd %xmm1, %xmm3
cltq
leaq (,%rax,8), %rsi
leaq (%rsi,%rsi,2), %rsi
xorpd %xmm4, %xmm4
movl $0x1, %edi
movsd %xmm2, (%r12)
movsd %xmm3, 0x8(%r12)
mulsd %xmm1, %xmm4
movsd %xmm4, 0x10(%r12)
movq 0x18(%r12), %r8
movups (%r12), %xmm4
movups %xmm4, (%r8,%rsi)
movq 0x10(%r12), %r9
movq %r9, 0x10(%r8,%rsi)
incq %rax
xorps %xmm4, %xmm4
cvtsi2sd %edi, %xmm4
addq $0x18, %rsi
incl %edi
ucomisd %xmm4, %xmm0
ja 0x3362
incl %edx
xorps %xmm3, %xmm3
cvtsi2sd %edx, %xmm3
ucomisd %xmm3, %xmm0
ja 0x3347
incl %ecx
xorps %xmm2, %xmm2
cvtsi2sd %ecx, %xmm2
ucomisd %xmm2, %xmm0
ja 0x333d
movl %ebp, %r12d
movl %ebp, 0x40(%rsp)
testl %ebp, %ebp
jle 0x34ca
leaq (,%r12,8), %rax
leaq (%rax,%rax,2), %r13
xorpd %xmm4, %xmm4
xorpd %xmm0, %xmm0
xorl %ebp, %ebp
xorpd %xmm5, %xmm5
movsd %xmm0, 0x60(%rsp)
movapd %xmm4, 0x30(%rsp)
movsd %xmm5, 0x8(%rsp)
callq 0x2050
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
movsd 0x1e0e(%rip), %xmm1     # 0x5228
divsd %xmm1, %xmm0
movsd 0x1e0a(%rip), %xmm1     # 0x5230
addsd %xmm1, %xmm0
movq (%r15), %rax
movsd %xmm0, (%rax,%rbp)
callq 0x2050
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
divsd 0x1de2(%rip), %xmm0     # 0x5228
addsd 0x1de2(%rip), %xmm0     # 0x5230
movq (%r15), %rax
movsd %xmm0, 0x8(%rax,%rbp)
callq 0x2050
movapd 0x30(%rsp), %xmm4
movsd 0x8(%rsp), %xmm5
xorps %xmm3, %xmm3
cvtsi2sd %eax, %xmm3
divsd 0x1db1(%rip), %xmm3     # 0x5228
addsd 0x1db1(%rip), %xmm3     # 0x5230
movq (%r15), %rax
movsd %xmm3, 0x10(%rax,%rbp)
movupd (%rax,%rbp), %xmm1
addpd %xmm1, %xmm4
addsd %xmm3, %xmm5
movapd %xmm1, %xmm2
mulsd %xmm1, %xmm2
addsd 0x60(%rsp), %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
mulsd %xmm1, %xmm1
addsd %xmm2, %xmm1
mulsd %xmm3, %xmm3
addsd %xmm1, %xmm3
addq $0x18, %rbp
movapd %xmm3, %xmm0
cmpq %rbp, %r13
jne 0x33f4
jmp 0x34d2
xorpd %xmm4, %xmm4
xorpd %xmm3, %xmm3
divsd 0x20(%rsp), %xmm3
movsd 0x70(%rsp), %xmm0
mulsd 0x1d52(%rip), %xmm0     # 0x5238
divsd %xmm3, %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x34fa
sqrtsd %xmm0, %xmm6
jmp 0x351b
movsd %xmm5, 0x8(%rsp)
movapd %xmm4, 0x30(%rsp)
callq 0x2100
movapd 0x30(%rsp), %xmm4
movsd 0x8(%rsp), %xmm5
movapd %xmm0, %xmm6
movapd 0x50(%rsp), %xmm3
movl 0x40(%rsp), %eax
testl %eax, %eax
movsd 0x18(%rsp), %xmm1
jle 0x3650
movapd 0x20(%rsp), %xmm0
divsd %xmm0, %xmm5
unpcklpd %xmm0, %xmm0            # xmm0 = xmm0[0,0]
divpd %xmm0, %xmm4
movapd %xmm6, %xmm0
unpcklpd %xmm6, %xmm0            # xmm0 = xmm0[0],xmm6[0]
movapd %xmm0, 0x20(%rsp)
movapd %xmm3, %xmm0
unpcklpd %xmm3, %xmm0            # xmm0 = xmm0[0],xmm3[0]
movapd %xmm0, 0x40(%rsp)
shlq $0x3, %r12
leaq (%r12,%r12,2), %r13
xorl %ebp, %ebp
leaq 0x17(%rsp), %r12
movsd %xmm5, 0x8(%rsp)
movapd %xmm4, 0x30(%rsp)
movapd %xmm6, 0x60(%rsp)
movq (%r15), %rax
movupd (%rax,%rbp), %xmm7
subpd %xmm4, %xmm7
mulpd 0x20(%rsp), %xmm7
movupd %xmm7, (%rax,%rbp)
movsd 0x10(%rax,%rbp), %xmm2
subsd %xmm5, %xmm2
mulsd %xmm6, %xmm2
movsd %xmm2, 0x10(%rax,%rbp)
movq (%rbx), %rax
movq (%r14), %rcx
movupd (%rax,%rbp), %xmm0
mulpd 0x40(%rsp), %xmm7
subpd %xmm7, %xmm0
movupd %xmm0, (%rcx,%rbp)
movsd 0x10(%rax,%rbp), %xmm4
mulsd %xmm3, %xmm2
subsd %xmm2, %xmm4
movsd %xmm4, 0x10(%rcx,%rbp)
movq %r12, %rdi
callq 0x4d26
movq (%r14), %rax
movsd %xmm0, (%rax,%rbp)
movsd 0x8(%rax,%rbp), %xmm0
movq %r12, %rdi
movsd 0x18(%rsp), %xmm1
callq 0x4d26
movq (%r14), %rax
movsd %xmm0, 0x8(%rax,%rbp)
movsd 0x10(%rax,%rbp), %xmm0
movq %r12, %rdi
movsd 0x18(%rsp), %xmm1
callq 0x4d26
movsd 0x18(%rsp), %xmm1
movapd 0x60(%rsp), %xmm6
movapd 0x30(%rsp), %xmm4
movsd 0x8(%rsp), %xmm5
movapd 0x50(%rsp), %xmm3
movq (%r14), %rax
movsd %xmm0, 0x10(%rax,%rbp)
addq $0x18, %rbp
cmpq %rbp, %r13
jne 0x3582
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop