// File: /workspace/github_cpp_makefile_star2_O2/shuwenyue[P]MD_code_cell_list/particle.cpp
// Function: particle::verlet(double, double, double, std::vector<vec3<double>, std::allocator<vec3<double>>>)
double particle::verlet(double dt, double NParticles, double BoxLength, 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 newX = 0;
    double newY = 0;
    double newZ = 0;
    double velocityx = 0;
    double velocityy = 0;
    double velocityz = 0;
    
    // define objects to use functions in other classes 
    force forceObj;
	box boxObj;

	// loop through all particles to determine new positions
    for (int a = 0; a < NParticles; a++)
    {
		// calculate new position coordinates from verlet algorithm
        newX = 2 * positionVector[a].x - positionPrevVector[a].x + dt*dt * forceV[a].x;
        newY = 2 * positionVector[a].y - positionPrevVector[a].y + dt*dt * forceV[a].y;
        newZ = 2 * positionVector[a].z - positionPrevVector[a].z + dt*dt * forceV[a].z;

		// periodic boundary conditions
		newX = boxObj.pbc(newX,BoxLength);
		newY = boxObj.pbc(newY,BoxLength);
		newZ = boxObj.pbc(newZ,BoxLength);

        // calculate new velocity from verlet algorithm
        velocityx = (boxObj.boundaries(newX - positionPrevVector[a].x,BoxLength))/(2*dt);
        velocityy = (boxObj.boundaries(newY - positionPrevVector[a].y,BoxLength))/(2*dt);
        velocityz = (boxObj.boundaries(newZ - positionPrevVector[a].z,BoxLength))/(2*dt);

        // velocity center of mass
        //totalVx = totalVx + velocityx;
        //totalVy = totalVy + velocityy;
        //totalVz = totalVz + velocityz;
        
        // use velocity^2 to calculate total kinetic energy
        totalV2 = totalV2 + velocityx*velocityx + velocityy*velocityy + velocityz*velocityz;

		// define new positions as current positions, current positions as previous positions
        positionPrevVector[a].x = positionVector[a].x;
        positionPrevVector[a].y = positionVector[a].y;
        positionPrevVector[a].z = positionVector[a].z;
        positionVector[a].x = boxObj.pbc(newX,BoxLength);
        positionVector[a].y = boxObj.pbc(newY,BoxLength);
        positionVector[a].z = boxObj.pbc(newZ,BoxLength);
    }
    
	// return total velocity^2
    return totalV2;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xf0, %rsp
movq %rsi, %rbx
movsd %xmm2, (%rsp)
movsd %xmm1, 0x58(%rsp)
movsd %xmm0, 0x20(%rsp)
movq %rdi, %r14
leaq 0x60(%rsp), %rdi
xorl %r12d, %r12d
movl $0x90, %edx
xorl %esi, %esi
callq 0x20b0
movsd 0x20(%rsp), %xmm1
movapd %xmm1, %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, 0x48(%rsp)
addsd %xmm1, %xmm1
movsd %xmm1, 0x20(%rsp)
xorpd %xmm0, %xmm0
movsd %xmm0, 0x40(%rsp)
leaq 0xf(%rsp), %r15
xorl %r13d, %r13d
cvtsi2sd %r12d, %xmm0
movsd 0x58(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x330e
movq 0x18(%r14), %rax
movq 0x30(%r14), %rcx
movsd (%rax,%r13), %xmm1
movsd 0x8(%rax,%r13), %xmm0
movsd %xmm0, 0x18(%rsp)
addsd %xmm1, %xmm1
subsd (%rcx,%r13), %xmm1
movq (%rbx), %rdx
movsd (%rdx,%r13), %xmm0
movsd 0x48(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd 0x8(%rcx,%r13), %xmm1
movsd %xmm1, 0x38(%rsp)
movsd 0x8(%rdx,%r13), %xmm1
movsd %xmm1, 0x10(%rsp)
movsd 0x10(%rax,%r13), %xmm1
addsd %xmm1, %xmm1
subsd 0x10(%rcx,%r13), %xmm1
movsd %xmm1, 0x30(%rsp)
movsd 0x10(%rdx,%r13), %xmm1
mulsd %xmm2, %xmm1
movsd %xmm1, 0x28(%rsp)
movq %r15, %rdi
movsd (%rsp), %xmm1
callq 0x455e
movsd %xmm0, 0x50(%rsp)
movsd 0x18(%rsp), %xmm1
addsd %xmm1, %xmm1
subsd 0x38(%rsp), %xmm1
movsd 0x10(%rsp), %xmm0
mulsd 0x48(%rsp), %xmm0
addsd %xmm1, %xmm0
movq %r15, %rdi
movsd (%rsp), %xmm1
callq 0x455e
movsd %xmm0, 0x18(%rsp)
movsd 0x28(%rsp), %xmm0
addsd 0x30(%rsp), %xmm0
movq %r15, %rdi
movsd (%rsp), %xmm1
callq 0x455e
movsd %xmm0, 0x10(%rsp)
movq 0x30(%r14), %rax
movsd 0x50(%rsp), %xmm0
subsd (%rax,%r13), %xmm0
movq %r15, %rdi
movsd (%rsp), %xmm1
callq 0x452c
movsd %xmm0, 0x38(%rsp)
movq 0x30(%r14), %rax
movsd 0x18(%rsp), %xmm0
subsd 0x8(%rax,%r13), %xmm0
movq %r15, %rdi
movsd (%rsp), %xmm1
callq 0x452c
movsd %xmm0, 0x30(%rsp)
movq 0x30(%r14), %rax
movsd 0x10(%rsp), %xmm0
subsd 0x10(%rax,%r13), %xmm0
movq %r15, %rdi
movsd (%rsp), %xmm1
callq 0x452c
movsd %xmm0, 0x28(%rsp)
movq 0x18(%r14), %rax
movq 0x30(%r14), %rcx
movups (%rax,%r13), %xmm0
movups %xmm0, (%rcx,%r13)
movsd 0x10(%rax,%r13), %xmm0
movsd %xmm0, 0x10(%rcx,%r13)
movq %r15, %rdi
movsd 0x50(%rsp), %xmm0
movsd (%rsp), %xmm1
callq 0x455e
movq 0x18(%r14), %rax
movsd %xmm0, (%rax,%r13)
movq %r15, %rdi
movsd 0x18(%rsp), %xmm0
movsd (%rsp), %xmm1
callq 0x455e
movq 0x18(%r14), %rax
movsd %xmm0, 0x8(%rax,%r13)
movq %r15, %rdi
movsd 0x10(%rsp), %xmm0
movsd (%rsp), %xmm1
callq 0x455e
movsd 0x20(%rsp), %xmm1
movsd 0x38(%rsp), %xmm2
divsd %xmm1, %xmm2
movsd 0x30(%rsp), %xmm3
divsd %xmm1, %xmm3
movsd 0x28(%rsp), %xmm4
divsd %xmm1, %xmm4
mulsd %xmm2, %xmm2
addsd 0x40(%rsp), %xmm2
mulsd %xmm3, %xmm3
addsd %xmm2, %xmm3
mulsd %xmm4, %xmm4
addsd %xmm3, %xmm4
movq 0x18(%r14), %rax
movsd %xmm0, 0x10(%rax,%r13)
addq $0x18, %r13
incl %r12d
movsd %xmm4, 0x40(%rsp)
jmp 0x30e1
leaq 0x60(%rsp), %rdi
callq 0x2bd2
movsd 0x40(%rsp), %xmm0
addq $0xf0, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq
movq %rax, %rbx
leaq 0x60(%rsp), %rdi
callq 0x2bd2
movq %rbx, %rdi
callq 0x2210