// File: /workspace/github_cpp_makefile_star2_O3/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 $0x148, %rsp            # imm = 0x148
movq %rcx, %rbx
movl %edx, 0x14(%rsp)
movapd %xmm3, 0x30(%rsp)
movsd %xmm2, 0x20(%rsp)
movsd %xmm1, 0x18(%rsp)
movsd %xmm0, 0x8(%rsp)
movl %esi, %ebp
movq %rdi, %r14
leaq 0xb8(%rsp), %rdi
movl $0x90, %edx
xorl %esi, %esi
callq 0x20a0
movapd 0x30(%rsp), %xmm6
movsd 0x8(%rsp), %xmm1
movl %ebp, %eax
movq %rax, 0x28(%rsp)
testl %ebp, %ebp
jle 0x3b1d
movapd %xmm6, %xmm0
mulsd %xmm6, %xmm0
movq 0x18(%r14), %rax
movq 0x48(%r14), %rdx
movq (%rbx), %rcx
movapd %xmm6, %xmm3
unpcklpd %xmm6, %xmm3            # xmm3 = xmm3[0],xmm6[0]
movapd %xmm0, 0x90(%rsp)
unpcklpd %xmm0, %xmm0            # xmm0 = xmm0[0,0]
movapd %xmm0, 0x80(%rsp)
movq 0x28(%rsp), %rsi
leaq (,%rsi,8), %rsi
leaq (%rsi,%rsi,2), %r13
xorl %r15d, %r15d
movapd 0x185b(%rip), %xmm4     # 0x5240
movsd 0x162b(%rip), %xmm5     # 0x5018
leaq 0x13(%rsp), %r12
movapd %xmm3, 0x70(%rsp)
movupd (%rax,%r15), %xmm0
movupd (%rdx,%r15), %xmm2
mulpd %xmm3, %xmm2
addpd %xmm0, %xmm2
movupd (%rcx,%r15), %xmm0
mulpd 0x80(%rsp), %xmm0
mulpd %xmm4, %xmm0
addpd %xmm2, %xmm0
movupd %xmm0, (%rax,%r15)
movsd 0x10(%rdx,%r15), %xmm3
mulsd %xmm6, %xmm3
addsd 0x10(%rax,%r15), %xmm3
movsd 0x10(%rcx,%r15), %xmm2
mulsd 0x90(%rsp), %xmm2
mulsd %xmm5, %xmm2
addsd %xmm3, %xmm2
movsd %xmm2, 0x10(%rax,%r15)
movq %r12, %rdi
callq 0x4c3e
movq 0x18(%r14), %rax
movsd %xmm0, (%rax,%r15)
movsd 0x8(%rax,%r15), %xmm0
movq %r12, %rdi
movsd 0x8(%rsp), %xmm1
callq 0x4c3e
movq 0x18(%r14), %rax
movsd %xmm0, 0x8(%rax,%r15)
movsd 0x10(%rax,%r15), %xmm0
movq %r12, %rdi
movsd 0x8(%rsp), %xmm1
callq 0x4c3e
movq 0x18(%r14), %rax
movsd %xmm0, 0x10(%rax,%r15)
movq 0x48(%r14), %rdx
movq (%rbx), %rcx
movupd (%rdx,%r15), %xmm0
movupd (%rcx,%r15), %xmm1
movapd 0x70(%rsp), %xmm3
mulpd %xmm3, %xmm1
movapd 0x176f(%rip), %xmm4     # 0x5240
mulpd %xmm4, %xmm1
addpd %xmm0, %xmm1
movupd %xmm1, (%rdx,%r15)
movsd 0x10(%rcx,%r15), %xmm0
movapd 0x30(%rsp), %xmm6
mulsd %xmm6, %xmm0
movsd 0x1520(%rip), %xmm5     # 0x5018
mulsd %xmm5, %xmm0
addsd 0x10(%rdx,%r15), %xmm0
movsd %xmm0, 0x10(%rdx,%r15)
addq $0x18, %r15
cmpq %r15, %r13
movsd 0x8(%rsp), %xmm1
jne 0x39f8
movl 0x14(%rsp), %eax
testl %eax, %eax
je 0x3b79
cmpl $0x1, %eax
jne 0x3bc7
leaq 0x18(%r14), %rsi
leaq 0x40(%rsp), %rdi
callq 0x3122
leaq 0xb8(%rsp), %rdi
leaq 0x40(%rsp), %rdx
movapd 0x30(%rsp), %xmm0
movl %ebp, %esi
movsd 0x8(%rsp), %xmm1
movsd 0x18(%rsp), %xmm2
movsd 0x20(%rsp), %xmm3
callq 0x42ec
movq 0x40(%rsp), %rdi
testq %rdi, %rdi
je 0x3bc7
leaq 0x50(%rsp), %rax
jmp 0x3bbc
leaq 0x18(%r14), %rsi
leaq 0x58(%rsp), %rdi
callq 0x3122
leaq 0xb8(%rsp), %rdi
leaq 0x58(%rsp), %rdx
movl %ebp, %esi
movsd 0x8(%rsp), %xmm0
movsd 0x18(%rsp), %xmm1
movsd 0x20(%rsp), %xmm2
callq 0x3f88
movq 0x58(%rsp), %rdi
testq %rdi, %rdi
je 0x3bc7
leaq 0x68(%rsp), %rax
movq (%rax), %rsi
subq %rdi, %rsi
callq 0x2150
leaq 0xa0(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x4a5c
testl %ebp, %ebp
jle 0x3c80
movq 0x48(%r14), %rax
movq (%rbx), %rcx
movapd 0x30(%rsp), %xmm6
movapd %xmm6, %xmm7
unpcklpd %xmm6, %xmm7            # xmm7 = xmm7[0],xmm6[0]
movq 0x28(%rsp), %rdx
shlq $0x3, %rdx
leaq (%rdx,%rdx,2), %rdx
xorpd %xmm3, %xmm3
xorl %esi, %esi
movapd 0x162c(%rip), %xmm1     # 0x5240
movsd 0x13fc(%rip), %xmm2     # 0x5018
movupd (%rax,%rsi), %xmm4
movupd (%rcx,%rsi), %xmm5
mulpd %xmm7, %xmm5
mulpd %xmm1, %xmm5
addpd %xmm4, %xmm5
movupd %xmm5, (%rax,%rsi)
movsd 0x10(%rcx,%rsi), %xmm0
mulsd %xmm6, %xmm0
mulsd %xmm2, %xmm0
addsd 0x10(%rax,%rsi), %xmm0
movsd %xmm0, 0x10(%rax,%rsi)
movapd %xmm5, %xmm4
mulsd %xmm5, %xmm4
addsd %xmm3, %xmm4
unpckhpd %xmm5, %xmm5            # xmm5 = xmm5[1,1]
mulsd %xmm5, %xmm5
addsd %xmm4, %xmm5
mulsd %xmm0, %xmm0
addsd %xmm5, %xmm0
addq $0x18, %rsi
movapd %xmm0, %xmm3
cmpq %rsi, %rdx
jne 0x3c1c
jmp 0x3c84
xorpd %xmm0, %xmm0
movq 0xa0(%rsp), %rdi
testq %rdi, %rdi
movsd %xmm0, 0x8(%rsp)
je 0x3cad
movq 0xb0(%rsp), %rsi
subq %rdi, %rsi
callq 0x2150
movsd 0x8(%rsp), %xmm0
movq 0x130(%rsp), %rdi
testq %rdi, %rdi
je 0x3cd0
movq 0x140(%rsp), %rsi
subq %rdi, %rsi
callq 0x2150
movsd 0x8(%rsp), %xmm0
movq 0x118(%rsp), %rdi
testq %rdi, %rdi
je 0x3cf3
movq 0x128(%rsp), %rsi
subq %rdi, %rsi
callq 0x2150
movsd 0x8(%rsp), %xmm0
movq 0x100(%rsp), %rdi
testq %rdi, %rdi
je 0x3d16
movq 0x110(%rsp), %rsi
subq %rdi, %rsi
callq 0x2150
movsd 0x8(%rsp), %xmm0
movq 0xe8(%rsp), %rdi
testq %rdi, %rdi
je 0x3d39
movq 0xf8(%rsp), %rsi
subq %rdi, %rsi
callq 0x2150
movsd 0x8(%rsp), %xmm0
movq 0xb8(%rsp), %rdi
testq %rdi, %rdi
je 0x3d5c
movq 0xc8(%rsp), %rsi
subq %rdi, %rsi
callq 0x2150
movsd 0x8(%rsp), %xmm0
addq $0x148, %rsp            # imm = 0x148
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
movq 0x58(%rsp), %rdi
testq %rdi, %rdi
je 0x3da5
movq 0x68(%rsp), %rsi
jmp 0x3d94
movq %rax, %rbx
movq 0x40(%rsp), %rdi
testq %rdi, %rdi
je 0x3da5
movq 0x50(%rsp), %rsi
subq %rdi, %rsi
callq 0x2150
jmp 0x3da5
jmp 0x3da2
jmp 0x3da2
movq %rax, %rbx
leaq 0xb8(%rsp), %rdi
callq 0x31b2
movq %rbx, %rdi
callq 0x2200