// File: /workspace/github_cpp_makefile_star2_O2/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:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x158, %rsp            # imm = 0x158
movq %rcx, %rbx
movl %edx, 0x3c(%rsp)
movaps %xmm3, 0x20(%rsp)
movsd %xmm2, 0x48(%rsp)
movsd %xmm1, 0x40(%rsp)
movsd %xmm0, 0x10(%rsp)
movl %esi, %ebp
movq %rdi, %r14
leaq 0xc8(%rsp), %rdi
xorl %r15d, %r15d
movl $0x90, %edx
xorl %esi, %esi
callq 0x20b0
leaq 0x18(%r14), %r12
movapd 0x20(%rsp), %xmm0
movapd %xmm0, %xmm1
mulsd %xmm0, %xmm1
testl %ebp, %ebp
movl $0x0, %eax
movl %ebp, 0x1c(%rsp)
cmovgl %ebp, %eax
unpcklpd %xmm0, %xmm0            # xmm0 = xmm0[0,0]
movapd %xmm0, 0x50(%rsp)
movapd %xmm1, 0x70(%rsp)
unpcklpd %xmm1, %xmm1            # xmm1 = xmm1[0,0]
movapd %xmm1, 0x60(%rsp)
imulq $0x18, %rax, %rbp
leaq 0xf(%rsp), %r13
cmpq %r15, %rbp
je 0x34fd
movq 0x18(%r14), %rax
movq 0x48(%r14), %rcx
movq (%rbx), %rdx
movupd (%rax,%r15), %xmm0
movupd (%rcx,%r15), %xmm1
mulpd 0x50(%rsp), %xmm1
addpd %xmm0, %xmm1
movupd (%rdx,%r15), %xmm0
mulpd 0x60(%rsp), %xmm0
mulpd 0x1e30(%rip), %xmm0     # 0x5240
addpd %xmm1, %xmm0
movupd %xmm0, (%rax,%r15)
movsd 0x10(%rcx,%r15), %xmm1
mulsd 0x20(%rsp), %xmm1
addsd 0x10(%rax,%r15), %xmm1
movsd 0x10(%rdx,%r15), %xmm2
mulsd 0x70(%rsp), %xmm2
mulsd 0x1bd5(%rip), %xmm2     # 0x5018
addsd %xmm1, %xmm2
movsd %xmm2, 0x10(%rax,%r15)
movq %r13, %rdi
movsd 0x10(%rsp), %xmm1
callq 0x455e
movq (%r12), %rax
movsd %xmm0, (%rax,%r15)
movsd 0x8(%rax,%r15), %xmm0
movq %r13, %rdi
movsd 0x10(%rsp), %xmm1
callq 0x455e
movq (%r12), %rax
movsd %xmm0, 0x8(%rax,%r15)
movsd 0x10(%rax,%r15), %xmm0
movq %r13, %rdi
movsd 0x10(%rsp), %xmm1
callq 0x455e
movq 0x18(%r14), %rax
movsd %xmm0, 0x10(%rax,%r15)
movq 0x48(%r14), %rax
movq (%rbx), %rcx
movupd (%rax,%r15), %xmm0
movupd (%rcx,%r15), %xmm1
mulpd 0x50(%rsp), %xmm1
mulpd 0x1d79(%rip), %xmm1     # 0x5240
addpd %xmm0, %xmm1
movupd %xmm1, (%rax,%r15)
movsd 0x10(%rcx,%r15), %xmm0
mulsd 0x20(%rsp), %xmm0
mulsd 0x1b32(%rip), %xmm0     # 0x5018
addsd 0x10(%rax,%r15), %xmm0
movsd %xmm0, 0x10(%rax,%r15)
addq $0x18, %r15
jmp 0x33d2
movl 0x3c(%rsp), %eax
testl %eax, %eax
je 0x354f
cmpl $0x1, %eax
jne 0x3590
leaq 0x98(%rsp), %r15
movq %r15, %rdi
movq %r12, %rsi
callq 0x2b72
leaq 0xc8(%rsp), %rdi
movapd 0x20(%rsp), %xmm0
movl 0x1c(%rsp), %esi
movsd 0x10(%rsp), %xmm1
movsd 0x40(%rsp), %xmm2
movsd 0x48(%rsp), %xmm3
movq %r15, %rdx
callq 0x3bba
jmp 0x3588
leaq 0xb0(%rsp), %r15
movq %r15, %rdi
movq %r12, %rsi
callq 0x2b72
leaq 0xc8(%rsp), %rdi
movl 0x1c(%rsp), %esi
movsd 0x10(%rsp), %xmm0
movsd 0x40(%rsp), %xmm1
movsd 0x48(%rsp), %xmm2
movq %r15, %rdx
callq 0x385c
movq %r15, %rdi
callq 0x2c66
leaq 0x80(%rsp), %rdi
leaq 0xc8(%rsp), %rsi
callq 0x4332
movq 0x48(%r14), %rax
xorpd %xmm2, %xmm2
xorl %ecx, %ecx
cmpq %rcx, %rbp
je 0x361e
movq (%rbx), %rdx
movupd (%rax,%rcx), %xmm1
movupd (%rdx,%rcx), %xmm0
mulpd 0x50(%rsp), %xmm0
mulpd 0x1c71(%rip), %xmm0     # 0x5240
addpd %xmm1, %xmm0
movupd %xmm0, (%rax,%rcx)
movapd %xmm0, %xmm1
mulsd %xmm0, %xmm1
addsd %xmm2, %xmm1
movsd 0x10(%rdx,%rcx), %xmm2
mulsd 0x20(%rsp), %xmm2
mulsd 0x1a20(%rip), %xmm2     # 0x5018
addsd 0x10(%rax,%rcx), %xmm2
movsd %xmm2, 0x10(%rax,%rcx)
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
mulsd %xmm0, %xmm0
addsd %xmm1, %xmm0
mulsd %xmm2, %xmm2
addsd %xmm0, %xmm2
addq $0x18, %rcx
jmp 0x35af
leaq 0x80(%rsp), %rdi
movsd %xmm2, 0x20(%rsp)
callq 0x2c66
leaq 0xc8(%rsp), %rdi
callq 0x2bd2
movsd 0x20(%rsp), %xmm0
addq $0x158, %rsp            # imm = 0x158
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
leaq 0xb0(%rsp), %rdi
jmp 0x366e
movq %rax, %rbx
leaq 0x98(%rsp), %rdi
callq 0x2c66
jmp 0x367c
jmp 0x3679
jmp 0x3679
movq %rax, %rbx
leaq 0xc8(%rsp), %rdi
callq 0x2bd2
movq %rbx, %rdi
callq 0x2210
nop