// File: shuwenyue[P]MD_code_cell_list/particle.cpp
// Function: particle::velocityverlet(int, double, double, double, double, int, std::vector<vec3<double>, std::allocator<vec3<double>>>)
double particle::velocityverlet(int NParticles, double BoxLength, double cutoff, double density, double dt, int cellist, vector<double3> forceV)
{
	// define variable: total velocities in each direction, total velocity^2, new positions, particle velocities
    double totalVx = 0;
    double totalVy = 0;
    double totalVz = 0;
    double totalV2 = 0;
    double velocityx = 0;
    double velocityy = 0;
    double velocityz = 0;
    
	// define objects to use functions in other classes 
    force forceObj;
	box boxObj;

	double energy;

    // calculate new position coordinates 
    for (int a = 0; a < NParticles; a++)
    {
        positionVector[a].x = positionVector[a].x + dt*velocityVector[a].x + dt*dt*forceV[a].x/2;
        positionVector[a].y = positionVector[a].y + dt*velocityVector[a].y + dt*dt*forceV[a].y/2;
        positionVector[a].z = positionVector[a].z + dt*velocityVector[a].z + dt*dt*forceV[a].z/2;

		// periodic boundary conditions
		positionVector[a].x = boxObj.pbc(positionVector[a].x, BoxLength);
		positionVector[a].y = boxObj.pbc(positionVector[a].y, BoxLength);
		positionVector[a].z = boxObj.pbc(positionVector[a].z, BoxLength);
	
		// first half velocity calculation using velocity verlet algorithm 
		velocityVector[a].x = velocityVector[a].x + forceV[a].x*dt/2;
        velocityVector[a].y = velocityVector[a].y + forceV[a].y*dt/2;
        velocityVector[a].z = velocityVector[a].z + forceV[a].z*dt/2;
    }

	// get new force from new positions, using either a cellist or no cellist
	if (cellist == 0)
	{
		energy = forceObj.getForce(NParticles,BoxLength,cutoff,density,positionVector);
	}
	else if (cellist == 1)
	{
		energy = forceObj.getForcecellist(dt, NParticles,BoxLength,cutoff,density,positionVector);
	}

	// obtain new forces in force vector from force class
	vector<double3> newForce = forceObj.getforceVector();

	// calculate new second half velocity calculation from new force
	for (int a = 0; a < NParticles; a++)
	{
		// calculate new velocity from verlet algorithm
		velocityVector[a].x = velocityVector[a].x + forceV[a].x*dt/2;
		velocityVector[a].y = velocityVector[a].y + forceV[a].y*dt/2;
		velocityVector[a].z = velocityVector[a].z + forceV[a].z*dt/2;
        
		// velocity center of mass
		//totalVx = totalVx + velocityVector[a].x;
		//totalVy = totalVy + velocityVector[a].y;
		//totalVz = totalVz + velocityVector[a].z;
        
		// use velocity^2 to calculate total kinetic energy
		totalV2 = totalV2 + velocityVector[a].x*velocityVector[a].x + velocityVector[a].y*velocityVector[a].y + velocityVector[a].z*velocityVector[a].z;
    }
    // return total velocity^2
    return totalV2;
}

// Assembly:
subq $0x338, %rsp            # imm = 0x338
movq %rcx, 0x1a8(%rsp)
movq %rdi, 0x330(%rsp)
movl %esi, 0x32c(%rsp)
movsd %xmm0, 0x320(%rsp)
movsd %xmm1, 0x318(%rsp)
movsd %xmm2, 0x310(%rsp)
movsd %xmm3, 0x308(%rsp)
movl %edx, 0x304(%rsp)
movq %rcx, 0x2f8(%rsp)
movq 0x330(%rsp), %rax
movq %rax, 0x1b0(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x2f0(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x2e8(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x2e0(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x2d8(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x2d0(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x2c8(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x2c0(%rsp)
leaq 0x230(%rsp), %rdi
callq 0x3160
movl $0x0, 0x21c(%rsp)
movl 0x21c(%rsp), %eax
cmpl 0x32c(%rsp), %eax
jge 0x5725
movq 0x1b0(%rsp), %rdi
addq $0x18, %rdi
movq %rdi, 0x198(%rsp)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movq 0x1b0(%rsp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, 0x118(%rsp)
movsd 0x308(%rsp), %xmm0
movsd %xmm0, 0x110(%rsp)
addq $0x48, %rdi
movq %rdi, 0x160(%rsp)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0x110(%rsp), %xmm0
movsd 0x118(%rsp), %xmm1
movq 0x1a8(%rsp), %rdi
movsd (%rax), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x128(%rsp)
movsd 0x308(%rsp), %xmm0
mulsd %xmm0, %xmm0
movsd %xmm0, 0x120(%rsp)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0x120(%rsp), %xmm1
movsd 0x128(%rsp), %xmm0
movq 0x198(%rsp), %rdi
movsd (%rax), %xmm2
mulsd %xmm2, %xmm1
movsd 0x3e2a(%rip), %xmm2     # 0x9018
movsd %xmm2, 0x180(%rsp)
mulsd %xmm2, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, 0x130(%rsp)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0x130(%rsp), %xmm0
movq 0x198(%rsp), %rdi
movsd %xmm0, (%rax)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movq 0x160(%rsp), %rdi
movsd 0x8(%rax), %xmm0
movsd %xmm0, 0x140(%rsp)
movsd 0x308(%rsp), %xmm0
movsd %xmm0, 0x138(%rsp)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0x138(%rsp), %xmm0
movsd 0x140(%rsp), %xmm1
movq 0x1a8(%rsp), %rdi
movsd 0x8(%rax), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x150(%rsp)
movsd 0x308(%rsp), %xmm0
mulsd %xmm0, %xmm0
movsd %xmm0, 0x148(%rsp)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0x148(%rsp), %xmm1
movsd 0x150(%rsp), %xmm0
movsd 0x180(%rsp), %xmm2
movq 0x198(%rsp), %rdi
movsd 0x8(%rax), %xmm3
mulsd %xmm3, %xmm1
mulsd %xmm2, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, 0x158(%rsp)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0x158(%rsp), %xmm0
movq 0x198(%rsp), %rdi
movsd %xmm0, 0x8(%rax)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movq 0x160(%rsp), %rdi
movsd 0x10(%rax), %xmm0
movsd %xmm0, 0x170(%rsp)
movsd 0x308(%rsp), %xmm0
movsd %xmm0, 0x168(%rsp)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0x168(%rsp), %xmm0
movsd 0x170(%rsp), %xmm1
movq 0x1a8(%rsp), %rdi
movsd 0x10(%rax), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x188(%rsp)
movsd 0x308(%rsp), %xmm0
mulsd %xmm0, %xmm0
movsd %xmm0, 0x178(%rsp)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0x178(%rsp), %xmm1
movsd 0x180(%rsp), %xmm2
movsd 0x188(%rsp), %xmm0
movq 0x198(%rsp), %rdi
movsd 0x10(%rax), %xmm3
mulsd %xmm3, %xmm1
mulsd %xmm2, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, 0x190(%rsp)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0x190(%rsp), %xmm0
movq 0x198(%rsp), %rdi
movsd %xmm0, 0x10(%rax)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd (%rax), %xmm0
movsd 0x320(%rsp), %xmm1
leaq 0x22f(%rsp), %rdi
callq 0x89a0
movsd %xmm0, 0x1a0(%rsp)
jmp 0x5446
movq 0x1b0(%rsp), %rdi
addq $0x18, %rdi
movq %rdi, 0x100(%rsp)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0x1a0(%rsp), %xmm0
movq 0x100(%rsp), %rdi
movsd %xmm0, (%rax)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0x8(%rax), %xmm0
movsd 0x320(%rsp), %xmm1
leaq 0x22f(%rsp), %rdi
callq 0x89a0
movsd %xmm0, 0x108(%rsp)
jmp 0x54af
movq 0x1b0(%rsp), %rdi
addq $0x18, %rdi
movq %rdi, 0xf0(%rsp)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0x108(%rsp), %xmm0
movq 0xf0(%rsp), %rdi
movsd %xmm0, 0x8(%rax)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0x10(%rax), %xmm0
movsd 0x320(%rsp), %xmm1
leaq 0x22f(%rsp), %rdi
callq 0x89a0
movsd %xmm0, 0xf8(%rsp)
jmp 0x5519
movq 0x1b0(%rsp), %rdi
addq $0x18, %rdi
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0xf8(%rsp), %xmm0
movq 0x1b0(%rsp), %rdi
movsd %xmm0, 0x10(%rax)
addq $0x48, %rdi
movslq 0x21c(%rsp), %rsi
callq 0x3350
movq 0x1a8(%rsp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, 0xc0(%rsp)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0xc0(%rsp), %xmm0
movq 0x1b0(%rsp), %rdi
movsd (%rax), %xmm1
mulsd 0x308(%rsp), %xmm1
movsd 0x3c8f(%rip), %xmm2     # 0x9230
divsd %xmm2, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, 0xc8(%rsp)
addq $0x48, %rdi
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0xc8(%rsp), %xmm0
movq 0x1b0(%rsp), %rdi
movsd %xmm0, (%rax)
addq $0x48, %rdi
movslq 0x21c(%rsp), %rsi
callq 0x3350
movq 0x1a8(%rsp), %rdi
movsd 0x8(%rax), %xmm0
movsd %xmm0, 0xd0(%rsp)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0xd0(%rsp), %xmm0
movq 0x1b0(%rsp), %rdi
movsd 0x8(%rax), %xmm1
mulsd 0x308(%rsp), %xmm1
movsd 0x3bfd(%rip), %xmm2     # 0x9230
divsd %xmm2, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, 0xd8(%rsp)
addq $0x48, %rdi
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0xd8(%rsp), %xmm0
movq 0x1b0(%rsp), %rdi
movsd %xmm0, 0x8(%rax)
addq $0x48, %rdi
movslq 0x21c(%rsp), %rsi
callq 0x3350
movq 0x1a8(%rsp), %rdi
movsd 0x10(%rax), %xmm0
movsd %xmm0, 0xe0(%rsp)
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0xe0(%rsp), %xmm0
movq 0x1b0(%rsp), %rdi
movsd 0x10(%rax), %xmm1
mulsd 0x308(%rsp), %xmm1
movsd 0x3b6a(%rip), %xmm2     # 0x9230
divsd %xmm2, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, 0xe8(%rsp)
addq $0x48, %rdi
movslq 0x21c(%rsp), %rsi
callq 0x3350
movsd 0xe8(%rsp), %xmm0
movsd %xmm0, 0x10(%rax)
movl 0x21c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x21c(%rsp)
jmp 0x50fd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x210(%rsp)
movl %eax, 0x20c(%rsp)
jmp 0x5c56
cmpl $0x0, 0x304(%rsp)
jne 0x581e
movq 0x1b0(%rsp), %rsi
movl 0x32c(%rsp), %eax
movl %eax, 0xa4(%rsp)
movsd 0x320(%rsp), %xmm0
movsd %xmm0, 0xa8(%rsp)
movsd 0x318(%rsp), %xmm0
movsd %xmm0, 0xb0(%rsp)
movsd 0x310(%rsp), %xmm0
movsd %xmm0, 0xb8(%rsp)
addq $0x18, %rsi
leaq 0x1f0(%rsp), %rdi
callq 0x3250
jmp 0x5792
movsd 0xb8(%rsp), %xmm2
movsd 0xb0(%rsp), %xmm1
movsd 0xa8(%rsp), %xmm0
movl 0xa4(%rsp), %esi
leaq 0x230(%rsp), %rdi
leaq 0x1f0(%rsp), %rdx
callq 0x6600
movsd %xmm0, 0x98(%rsp)
jmp 0x57d4
movsd 0x98(%rsp), %xmm0
movsd %xmm0, 0x220(%rsp)
leaq 0x1f0(%rsp), %rdi
callq 0x31f0
jmp 0x591f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x210(%rsp)
movl %eax, 0x20c(%rsp)
leaq 0x1f0(%rsp), %rdi
callq 0x31f0
jmp 0x5c56
cmpl $0x1, 0x304(%rsp)
jne 0x591d
movq 0x1b0(%rsp), %rsi
movsd 0x308(%rsp), %xmm0
movsd %xmm0, 0x70(%rsp)
movl 0x32c(%rsp), %eax
movl %eax, 0x7c(%rsp)
movsd 0x320(%rsp), %xmm0
movsd %xmm0, 0x80(%rsp)
movsd 0x318(%rsp), %xmm0
movsd %xmm0, 0x88(%rsp)
movsd 0x310(%rsp), %xmm0
movsd %xmm0, 0x90(%rsp)
addq $0x18, %rsi
leaq 0x1d8(%rsp), %rdi
callq 0x3250
jmp 0x5897
movsd 0x90(%rsp), %xmm3
movsd 0x88(%rsp), %xmm2
movsd 0x80(%rsp), %xmm1
movl 0x7c(%rsp), %esi
movsd 0x70(%rsp), %xmm0
leaq 0x230(%rsp), %rdi
leaq 0x1d8(%rsp), %rdx
callq 0x6e10
movsd %xmm0, 0x68(%rsp)
jmp 0x58d9
movsd 0x68(%rsp), %xmm0
movsd %xmm0, 0x220(%rsp)
leaq 0x1d8(%rsp), %rdi
callq 0x31f0
jmp 0x591d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x210(%rsp)
movl %eax, 0x20c(%rsp)
leaq 0x1d8(%rsp), %rdi
callq 0x31f0
jmp 0x5c56
jmp 0x591f
leaq 0x1c0(%rsp), %rdi
leaq 0x230(%rsp), %rsi
callq 0x7ec0
jmp 0x5936
movl $0x0, 0x1bc(%rsp)
movl 0x1bc(%rsp), %eax
cmpl 0x32c(%rsp), %eax
jge 0x5c21
movq 0x1b0(%rsp), %rdi
addq $0x48, %rdi
movslq 0x1bc(%rsp), %rsi
callq 0x3350
movq 0x1a8(%rsp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, 0x8(%rsp)
movslq 0x1bc(%rsp), %rsi
callq 0x3350
movsd 0x8(%rsp), %xmm0
movq 0x1b0(%rsp), %rdi
movsd (%rax), %xmm1
mulsd 0x308(%rsp), %xmm1
movsd 0x3880(%rip), %xmm2     # 0x9230
divsd %xmm2, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, 0x10(%rsp)
addq $0x48, %rdi
movslq 0x1bc(%rsp), %rsi
callq 0x3350
movsd 0x10(%rsp), %xmm0
movq 0x1b0(%rsp), %rdi
movsd %xmm0, (%rax)
addq $0x48, %rdi
movslq 0x1bc(%rsp), %rsi
callq 0x3350
movq 0x1a8(%rsp), %rdi
movsd 0x8(%rax), %xmm0
movsd %xmm0, 0x18(%rsp)
movslq 0x1bc(%rsp), %rsi
callq 0x3350
movsd 0x18(%rsp), %xmm0
movq 0x1b0(%rsp), %rdi
movsd 0x8(%rax), %xmm1
mulsd 0x308(%rsp), %xmm1
movsd 0x37fa(%rip), %xmm2     # 0x9230
divsd %xmm2, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, 0x20(%rsp)
addq $0x48, %rdi
movslq 0x1bc(%rsp), %rsi
callq 0x3350
movsd 0x20(%rsp), %xmm0
movq 0x1b0(%rsp), %rdi
movsd %xmm0, 0x8(%rax)
addq $0x48, %rdi
movslq 0x1bc(%rsp), %rsi
callq 0x3350
movq 0x1a8(%rsp), %rdi
movsd 0x10(%rax), %xmm0
movsd %xmm0, 0x28(%rsp)
movslq 0x1bc(%rsp), %rsi
callq 0x3350
movsd 0x28(%rsp), %xmm0
movq 0x1b0(%rsp), %rdi
movsd 0x10(%rax), %xmm1
mulsd 0x308(%rsp), %xmm1
movsd 0x3773(%rip), %xmm2     # 0x9230
divsd %xmm2, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, 0x30(%rsp)
addq $0x48, %rdi
movslq 0x1bc(%rsp), %rsi
callq 0x3350
movsd 0x30(%rsp), %xmm0
movq 0x1b0(%rsp), %rdi
movsd %xmm0, 0x10(%rax)
movsd 0x2d8(%rsp), %xmm0
movsd %xmm0, 0x40(%rsp)
addq $0x48, %rdi
movslq 0x1bc(%rsp), %rsi
callq 0x3350
movq 0x1b0(%rsp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, 0x38(%rsp)
addq $0x48, %rdi
movslq 0x1bc(%rsp), %rsi
callq 0x3350
movsd 0x38(%rsp), %xmm0
movsd 0x40(%rsp), %xmm1
movq 0x1b0(%rsp), %rdi
movsd (%rax), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x50(%rsp)
addq $0x48, %rdi
movslq 0x1bc(%rsp), %rsi
callq 0x3350
movq 0x1b0(%rsp), %rdi
movsd 0x8(%rax), %xmm0
movsd %xmm0, 0x48(%rsp)
addq $0x48, %rdi
movslq 0x1bc(%rsp), %rsi
callq 0x3350
movsd 0x48(%rsp), %xmm0
movsd 0x50(%rsp), %xmm1
movq 0x1b0(%rsp), %rdi
movsd 0x8(%rax), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x60(%rsp)
addq $0x48, %rdi
movslq 0x1bc(%rsp), %rsi
callq 0x3350
movq 0x1b0(%rsp), %rdi
movsd 0x10(%rax), %xmm0
movsd %xmm0, 0x58(%rsp)
addq $0x48, %rdi
movslq 0x1bc(%rsp), %rsi
callq 0x3350
movsd 0x58(%rsp), %xmm0
movsd 0x60(%rsp), %xmm1
movsd 0x10(%rax), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x2d8(%rsp)
movl 0x1bc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1bc(%rsp)
jmp 0x5941
movsd 0x2d8(%rsp), %xmm0
movsd %xmm0, (%rsp)
leaq 0x1c0(%rsp), %rdi
callq 0x31f0
leaq 0x230(%rsp), %rdi
callq 0x3370
movsd (%rsp), %xmm0
addq $0x338, %rsp            # imm = 0x338
retq
leaq 0x230(%rsp), %rdi
callq 0x3370
movq 0x210(%rsp), %rdi
callq 0x21f0