// File: 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:
subq $0x178, %rsp            # imm = 0x178
movq %rdi, 0x170(%rsp)
movsd %xmm0, 0x168(%rsp)
movl %esi, 0x164(%rsp)
movsd %xmm1, 0x158(%rsp)
movsd %xmm2, 0x150(%rsp)
movq 0x170(%rsp), %rdi
movq %rdi, 0xc0(%rsp)
movl $0x0, 0x14c(%rsp)
addq $0x18, %rdi
movslq 0x164(%rsp), %rsi
callq 0x5ca0
movq 0xc0(%rsp), %rdi
addq $0x30, %rdi
movslq 0x164(%rsp), %rsi
callq 0x5ca0
movq 0xc0(%rsp), %rdi
addq $0x48, %rdi
movslq 0x164(%rsp), %rsi
callq 0x5ca0
movsd 0x168(%rsp), %xmm0
movsd %xmm0, 0xc8(%rsp)
movl 0x164(%rsp), %edi
movsd 0x50e8(%rip), %xmm0     # 0x9008
callq 0x5d40
movaps %xmm0, %xmm1
movsd 0xc8(%rsp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, 0x140(%rsp)
movl 0x164(%rsp), %edi
movsd 0x50bb(%rip), %xmm0     # 0x9008
callq 0x5d40
movsd %xmm0, 0x138(%rsp)
movl $0x0, 0x134(%rsp)
cvtsi2sdl 0x134(%rsp), %xmm1
movsd 0x138(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x40a2
movl $0x0, 0x130(%rsp)
cvtsi2sdl 0x130(%rsp), %xmm1
movsd 0x138(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x408a
movl $0x0, 0x12c(%rsp)
cvtsi2sdl 0x12c(%rsp), %xmm1
movsd 0x138(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x4072
movq 0xc0(%rsp), %rdi
cvtsi2sdl 0x134(%rsp), %xmm0
mulsd 0x140(%rsp), %xmm0
movsd %xmm0, (%rdi)
cvtsi2sdl 0x130(%rsp), %xmm0
mulsd 0x140(%rsp), %xmm0
movsd %xmm0, 0x8(%rdi)
cvtsi2sdl 0x12c(%rsp), %xmm0
mulsd 0x140(%rsp), %xmm0
movsd %xmm0, 0x10(%rdi)
addq $0x18, %rdi
movslq 0x14c(%rsp), %rsi
callq 0x3350
movq 0xc0(%rsp), %rcx
movq (%rcx), %rdx
movq %rdx, (%rax)
movq 0x8(%rcx), %rdx
movq %rdx, 0x8(%rax)
movq 0x10(%rcx), %rcx
movq %rcx, 0x10(%rax)
movl 0x14c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x14c(%rsp)
movl 0x12c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x12c(%rsp)
jmp 0x3fb4
jmp 0x4074
movl 0x130(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x130(%rsp)
jmp 0x3f8d
jmp 0x408c
movl 0x134(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x134(%rsp)
jmp 0x3f66
xorps %xmm0, %xmm0
movsd %xmm0, 0x120(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x118(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x110(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x108(%rsp)
movl $0x0, 0x104(%rsp)
movl 0x104(%rsp), %eax
cmpl 0x164(%rsp), %eax
jge 0x43ee
callq 0x2040
movq 0xc0(%rsp), %rdi
cvtsi2sd %eax, %xmm0
movsd 0x511e(%rip), %xmm1     # 0x9228
divsd %xmm1, %xmm0
movsd 0x4f02(%rip), %xmm1     # 0x9018
subsd %xmm1, %xmm0
movsd %xmm0, 0x60(%rsp)
addq $0x48, %rdi
movslq 0x104(%rsp), %rsi
callq 0x3350
movsd 0x60(%rsp), %xmm0
movsd %xmm0, (%rax)
callq 0x2040
movq 0xc0(%rsp), %rdi
cvtsi2sd %eax, %xmm0
movsd 0x50d4(%rip), %xmm1     # 0x9228
divsd %xmm1, %xmm0
movsd 0x4eb8(%rip), %xmm1     # 0x9018
subsd %xmm1, %xmm0
movsd %xmm0, 0x68(%rsp)
addq $0x48, %rdi
movslq 0x104(%rsp), %rsi
callq 0x3350
movsd 0x68(%rsp), %xmm0
movsd %xmm0, 0x8(%rax)
callq 0x2040
movq 0xc0(%rsp), %rdi
cvtsi2sd %eax, %xmm0
movsd 0x5089(%rip), %xmm1     # 0x9228
divsd %xmm1, %xmm0
movsd 0x4e6d(%rip), %xmm1     # 0x9018
subsd %xmm1, %xmm0
movsd %xmm0, 0x70(%rsp)
addq $0x48, %rdi
movslq 0x104(%rsp), %rsi
callq 0x3350
movsd 0x70(%rsp), %xmm0
movq 0xc0(%rsp), %rdi
movsd %xmm0, 0x10(%rax)
movsd 0x120(%rsp), %xmm0
movsd %xmm0, 0x78(%rsp)
addq $0x48, %rdi
movslq 0x104(%rsp), %rsi
callq 0x3350
movsd 0x78(%rsp), %xmm0
movq 0xc0(%rsp), %rdi
addsd (%rax), %xmm0
movsd %xmm0, 0x120(%rsp)
movsd 0x118(%rsp), %xmm0
movsd %xmm0, 0x80(%rsp)
addq $0x48, %rdi
movslq 0x104(%rsp), %rsi
callq 0x3350
movsd 0x80(%rsp), %xmm0
movq 0xc0(%rsp), %rdi
addsd 0x8(%rax), %xmm0
movsd %xmm0, 0x118(%rsp)
movsd 0x110(%rsp), %xmm0
movsd %xmm0, 0x88(%rsp)
addq $0x48, %rdi
movslq 0x104(%rsp), %rsi
callq 0x3350
movsd 0x88(%rsp), %xmm0
movq 0xc0(%rsp), %rdi
addsd 0x10(%rax), %xmm0
movsd %xmm0, 0x110(%rsp)
movsd 0x108(%rsp), %xmm0
movsd %xmm0, 0x98(%rsp)
addq $0x48, %rdi
movslq 0x104(%rsp), %rsi
callq 0x3350
movq 0xc0(%rsp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, 0x90(%rsp)
addq $0x48, %rdi
movslq 0x104(%rsp), %rsi
callq 0x3350
movsd 0x90(%rsp), %xmm0
movsd 0x98(%rsp), %xmm1
movq 0xc0(%rsp), %rdi
movsd (%rax), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xa8(%rsp)
addq $0x48, %rdi
movslq 0x104(%rsp), %rsi
callq 0x3350
movq 0xc0(%rsp), %rdi
movsd 0x8(%rax), %xmm0
movsd %xmm0, 0xa0(%rsp)
addq $0x48, %rdi
movslq 0x104(%rsp), %rsi
callq 0x3350
movsd 0xa0(%rsp), %xmm0
movsd 0xa8(%rsp), %xmm1
movq 0xc0(%rsp), %rdi
movsd 0x8(%rax), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xb8(%rsp)
addq $0x48, %rdi
movslq 0x104(%rsp), %rsi
callq 0x3350
movq 0xc0(%rsp), %rdi
movsd 0x10(%rax), %xmm0
movsd %xmm0, 0xb0(%rsp)
addq $0x48, %rdi
movslq 0x104(%rsp), %rsi
callq 0x3350
movsd 0xb0(%rsp), %xmm0
movsd 0xb8(%rsp), %xmm1
movsd 0x10(%rax), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x108(%rsp)
movl 0x104(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x104(%rsp)
jmp 0x40dd
movsd 0x120(%rsp), %xmm0
cvtsi2sdl 0x164(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0xf8(%rsp)
movsd 0x118(%rsp), %xmm0
cvtsi2sdl 0x164(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0xf0(%rsp)
movsd 0x110(%rsp), %xmm0
cvtsi2sdl 0x164(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0xe8(%rsp)
movsd 0x108(%rsp), %xmm0
cvtsi2sdl 0x164(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0xe0(%rsp)
movsd 0x4dae(%rip), %xmm0     # 0x9220
mulsd 0x158(%rsp), %xmm0
divsd 0xe0(%rsp), %xmm0
callq 0x20e0
movsd %xmm0, 0xd8(%rsp)
movl $0x0, 0xd0(%rsp)
movl 0xd0(%rsp), %eax
cmpl 0x164(%rsp), %eax
jge 0x48b4
movq 0xc0(%rsp), %rdi
addq $0x48, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movq 0xc0(%rsp), %rdi
movsd (%rax), %xmm0
subsd 0xf8(%rsp), %xmm0
mulsd 0xd8(%rsp), %xmm0
movsd %xmm0, (%rsp)
addq $0x48, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movsd (%rsp), %xmm0
movq 0xc0(%rsp), %rdi
movsd %xmm0, (%rax)
addq $0x48, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movq 0xc0(%rsp), %rdi
movsd 0x8(%rax), %xmm0
subsd 0xf0(%rsp), %xmm0
mulsd 0xd8(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
addq $0x48, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movsd 0x8(%rsp), %xmm0
movq 0xc0(%rsp), %rdi
movsd %xmm0, 0x8(%rax)
addq $0x48, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movq 0xc0(%rsp), %rdi
movsd 0x10(%rax), %xmm0
subsd 0xe8(%rsp), %xmm0
mulsd 0xd8(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
addq $0x48, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movsd 0x10(%rsp), %xmm0
movq 0xc0(%rsp), %rdi
movsd %xmm0, 0x10(%rax)
addq $0x18, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movq 0xc0(%rsp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, 0x18(%rsp)
addq $0x48, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movsd 0x18(%rsp), %xmm1
movq 0xc0(%rsp), %rdi
movsd (%rax), %xmm0
movsd 0x150(%rsp), %xmm2
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x20(%rsp)
addq $0x30, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movsd 0x20(%rsp), %xmm0
movq 0xc0(%rsp), %rdi
movsd %xmm0, (%rax)
addq $0x18, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movq 0xc0(%rsp), %rdi
movsd 0x8(%rax), %xmm0
movsd %xmm0, 0x28(%rsp)
addq $0x48, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movsd 0x28(%rsp), %xmm1
movq 0xc0(%rsp), %rdi
movsd 0x8(%rax), %xmm0
movsd 0x150(%rsp), %xmm2
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x30(%rsp)
addq $0x30, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movsd 0x30(%rsp), %xmm0
movq 0xc0(%rsp), %rdi
movsd %xmm0, 0x8(%rax)
addq $0x18, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movq 0xc0(%rsp), %rdi
movsd 0x10(%rax), %xmm0
movsd %xmm0, 0x38(%rsp)
addq $0x48, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movsd 0x38(%rsp), %xmm1
movq 0xc0(%rsp), %rdi
movsd 0x10(%rax), %xmm0
movsd 0x150(%rsp), %xmm2
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x40(%rsp)
addq $0x30, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movsd 0x40(%rsp), %xmm0
movq 0xc0(%rsp), %rdi
movsd %xmm0, 0x10(%rax)
addq $0x30, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movsd (%rax), %xmm0
movsd 0x168(%rsp), %xmm1
leaq 0xd7(%rsp), %rdi
callq 0x89a0
movq 0xc0(%rsp), %rdi
movsd %xmm0, 0x48(%rsp)
addq $0x30, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movsd 0x48(%rsp), %xmm0
movq 0xc0(%rsp), %rdi
movsd %xmm0, (%rax)
addq $0x30, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movsd 0x8(%rax), %xmm0
movsd 0x168(%rsp), %xmm1
leaq 0xd7(%rsp), %rdi
callq 0x89a0
movq 0xc0(%rsp), %rdi
movsd %xmm0, 0x50(%rsp)
addq $0x30, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movsd 0x50(%rsp), %xmm0
movq 0xc0(%rsp), %rdi
movsd %xmm0, 0x8(%rax)
addq $0x30, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movsd 0x10(%rax), %xmm0
movsd 0x168(%rsp), %xmm1
leaq 0xd7(%rsp), %rdi
callq 0x89a0
movq 0xc0(%rsp), %rdi
movsd %xmm0, 0x58(%rsp)
addq $0x30, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3350
movsd 0x58(%rsp), %xmm0
movsd %xmm0, 0x10(%rax)
movl 0xd0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xd0(%rsp)
jmp 0x449d
addq $0x178, %rsp            # imm = 0x178
retq
nopl (%rax)