// File: /workspace/github_cpp_makefile_star2_O2/shuwenyue[P]MD_code_cell_list/main.cpp
// Function: main
int main () 
{
	// define parameters
	int NParticles; // number of particles in box
	double T; // temperature in reduced units
	double density; // density = Number of Particles / Volume of Box
	double cutoff; // maximum distance between any two particles where interaction energy is explicitly calculated
	double cellist; // algorithm that reduces calculation time from N2 to N
	double BoxLength;
	double tmax; // total run time
	double dt; // time step

	// set configuration parameters in reduced units 
	cout << "-------------------------------------------------------------------" << endl;
	cout << "Enter Parameters for 3D Lennard Jones Molecular Dynamics Simulation" << endl;
	cout << "(in reduced units)" << endl;
	cout << "-------------------------------------------------------------------" << endl;
	cout << "Number of Particles (only perfect cube numbers e.g. 512, 10648, 27000):";
	cin >> NParticles;
	cout << "Temperature (e.g. 1):";
	cin >> T;
	cout << "Density (e.g. 0.5):";
	cin >> density;
	cout << "Cutoff distance (e.g. 3):";
	cin >> cutoff;
	cout << "Run Time (e.g. 5 seconds):";
	cin >> tmax;
	cout << "Time Step (e.g. 0.005):";
	cin >> dt;
	cout << "Use cellist? (0 for NO, 1 for YES)";
	cin >> cellist;
	BoxLength = pow((NParticles/density), 1.0/3.0);
	cout << "BoxLength: " << BoxLength << endl;
	cout << "-------------------------------------------------------------------" << endl;

	// pre-assigned parameters
    /*T = 1.6; 
    NParticles = 512; 
	density = 0.7;
    cutoff = 3;
	BoxLength = pow((NParticles/density), 1.0/3.0);
	cellist = 1; // 0 for no cellist, 1 for cellist
	tmax = 1; // total run time
    dt = 0.005; // time step*/

	cout << "BoxLength: " << BoxLength << endl;
    
	double energy;
	double ETotal;
	double rtotal;

	// print to output file
    ofstream trajFile;
    trajFile.open("traj.xyz"); // trajectory file (position coordinates of every particle at every timestep, can view movie in VMD)
    ofstream logFile;
    logFile.open("test.log"); // output of temperature and energy at each timestep

	// clock (to calculate total run time of simulation)
	clock_t start, end;

	// define objects to use functions in other classes 
	particle particleObj;
	box boxObj;
	force forceObj;

	// initialize positions of particles on a lattice in a box and initialize velocities
    particleObj.initialize(BoxLength, NParticles, T, dt); 
	vector<double3> initial = particleObj.getpositionVector(); // save initial positions of particles

	// start clock
	start = clock();

	// print header for screen output
	cout << "-------------------------------------------------------------------" << endl;
	cout << endl;
	cout << "Timestep" << "          Temperature" << "         Energy" << endl;
	cout << endl;
	cout << "-------------------------------------------------------------------" << endl;

    for (double t = 0; t<tmax; t=t+dt)
    {

		// call getForce (no cellist) or getForcecellist (with cellist) to calculate forces on all particles (in matrix called forceVector) and return total energy from particle interactions
		if (cellist == 0)
		{
			energy = forceObj.getForce(NParticles, BoxLength, cutoff, density, particleObj.getpositionVector());
		}

		if (cellist == 1)
		{
			energy = forceObj.getForcecellist(t, NParticles, BoxLength, cutoff, density, particleObj.getpositionVector());
		}
    
        // access forceVector from force class and place in variable called forceV
		vector<double3> forceV = forceObj.getforceVector();

		// integrate forces using verlet algorithm and return total velocity^2 squared (to be used in Temperature and Energy calculation later)
		double totalV2 = particleObj.verlet(dt, NParticles, BoxLength, forceV);

		// velocity verlet algorithm
		//double totalV2 = particleObj.velocityverlet(NParticles, BoxLength, cutoff, density, dt, cellist, forceV);

		// temperature calculation using averaged velocity: velocity^2/NParticles
		T = totalV2 / (3*NParticles);

		// total energy calculating using total velocity^2 and energy using averaged velocity
		ETotal = (energy + 0.5*totalV2)/NParticles;

		// print to screen the (1) timestep, (2) temperature, (3) energy 
		cout << "Timestep: " << t << " ---  T: " << T << " ---  E: " << ETotal << endl;

		// print to output file the (1) timestep, (2) temperature, (3) energy 
		logFile << t << "  " << T << "  " << ETotal << endl;

		// print particle positions at every time step to trajectory xyz file 
		vector<double3> positionOutput = particleObj.getpositionVector();
		trajFile << NParticles << endl;
		trajFile << endl;
		for (int i = 0; i < NParticles; i++)
		{
			trajFile << "1 " << positionOutput[i].x << " " << positionOutput[i].y << " " << positionOutput[i].z << endl;
		}
    }

	end = clock();
	// print total CPU time from simulation
	cout << "CPU time: " << ((float)(end - start)/CLOCKS_PER_SEC) << endl;

	logFile.close();
	trajFile.close();

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x5e8, %rsp            # imm = 0x5E8
movq 0x4bfc(%rip), %rbx      # 0x6fd0
leaq 0x2c51(%rip), %r14      # 0x502c
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2130
movq %rax, %rdi
callq 0x2090
leaq 0x2c7b(%rip), %rsi      # 0x5070
movq %rbx, %rdi
callq 0x2130
movq %rax, %rdi
callq 0x2090
leaq 0x2ca8(%rip), %rsi      # 0x50b4
movq %rbx, %rdi
callq 0x2130
movq %rax, %rdi
callq 0x2090
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2130
movq %rax, %rdi
callq 0x2090
leaq 0x2c91(%rip), %rsi      # 0x50c7
movq %rbx, %rdi
callq 0x2130
movq 0x4b9b(%rip), %r12      # 0x6fe0
leaq 0x4(%rsp), %r15
movq %r12, %rdi
movq %r15, %rsi
callq 0x20c0
leaq 0x2cb3(%rip), %rsi      # 0x510f
movq %rbx, %rdi
callq 0x2130
leaq 0x28(%rsp), %rsi
movq %r12, %rdi
callq 0x20d0
leaq 0x2cad(%rip), %rsi      # 0x5125
movq %rbx, %rdi
callq 0x2130
leaq 0x48(%rsp), %r13
movq %r12, %rdi
movq %r13, %rsi
callq 0x20d0
leaq 0x2ca2(%rip), %rsi      # 0x5139
movq %rbx, %rdi
callq 0x2130
leaq 0x40(%rsp), %rsi
movq %r12, %rdi
callq 0x20d0
leaq 0x2ca0(%rip), %rsi      # 0x5153
movq %rbx, %rdi
callq 0x2130
leaq 0x70(%rsp), %rsi
movq %r12, %rdi
callq 0x20d0
leaq 0x2c9f(%rip), %rsi      # 0x516e
movq %rbx, %rdi
callq 0x2130
leaq 0x30(%rsp), %rsi
movq %r12, %rdi
callq 0x20d0
leaq 0x2c9b(%rip), %rsi      # 0x5186
movq %rbx, %rdi
callq 0x2130
leaq 0x38(%rsp), %rsi
movq %r12, %rdi
callq 0x20d0
cvtsi2sdl (%r15), %xmm0
divsd (%r13), %xmm0
movsd 0x2af5(%rip), %xmm1     # 0x5008
callq 0x2200
movsd %xmm0, 0x18(%rsp)
leaq 0x2c84(%rip), %r15      # 0x51a9
movq %rbx, %rdi
movq %r15, %rsi
callq 0x2130
movq %rax, %rdi
movsd 0x18(%rsp), %xmm0
callq 0x21a0
movq %rax, %rdi
callq 0x2090
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2130
movq %rax, %rdi
callq 0x2090
movq %rbx, %rdi
movq %r15, %rsi
callq 0x2130
movq %rax, %rdi
movsd 0x18(%rsp), %xmm0
callq 0x21a0
movq %rax, %rdi
callq 0x2090
leaq 0x3e8(%rsp), %rbx
movq %rbx, %rdi
callq 0x21e0
leaq 0x2c24(%rip), %rsi      # 0x51b5
pushq $0x10
popq %rdx
movq %rbx, %rdi
callq 0x2030
leaq 0x1e8(%rsp), %rdi
callq 0x21e0
leaq 0x2c0e(%rip), %rsi      # 0x51be
leaq 0x1e8(%rsp), %rdi
pushq $0x10
popq %rdx
callq 0x2030
xorpd %xmm0, %xmm0
leaq 0xf0(%rsp), %rbx
movapd %xmm0, 0x50(%rbx)
movapd %xmm0, 0x40(%rbx)
movapd %xmm0, 0x30(%rbx)
movapd %xmm0, 0x20(%rbx)
movapd %xmm0, 0x10(%rbx)
movapd %xmm0, (%rbx)
leaq 0x158(%rsp), %rdi
movl $0x90, %edx
xorl %esi, %esi
callq 0x20b0
movl 0x4(%rsp), %esi
movsd 0x28(%rsp), %xmm1
movsd 0x30(%rsp), %xmm2
movq %rbx, %rdi
movsd 0x18(%rsp), %xmm0
callq 0x2d14
leaq 0xd8(%rsp), %rdi
leaq 0xf0(%rsp), %rsi
callq 0x3692
callq 0x20e0
movq %rax, 0x50(%rsp)
movq 0x498f(%rip), %rdi      # 0x6fd0
leaq 0x29e4(%rip), %rsi      # 0x502c
callq 0x2130
movq %rax, %rdi
callq 0x2090
movq 0x4974(%rip), %rdi      # 0x6fd0
callq 0x2090
movq 0x4968(%rip), %rdi      # 0x6fd0
leaq 0x2b58(%rip), %rsi      # 0x51c7
callq 0x2130
leaq 0x2b55(%rip), %rsi      # 0x51d0
movq %rax, %rdi
callq 0x2130
leaq 0x2b5c(%rip), %rsi      # 0x51e6
movq %rax, %rdi
callq 0x2130
movq %rax, %rdi
callq 0x2090
movq 0x492f(%rip), %rdi      # 0x6fd0
callq 0x2090
movq 0x4923(%rip), %rdi      # 0x6fd0
leaq 0x2978(%rip), %rsi      # 0x502c
callq 0x2130
movq %rax, %rdi
callq 0x2090
leaq 0xf0(%rsp), %r15
leaq 0x3e8(%rsp), %r14
leaq 0x2b40(%rip), %r13      # 0x5218
xorpd %xmm1, %xmm1
leaq 0x2b33(%rip), %r12      # 0x5216
movsd 0x70(%rsp), %xmm0
movsd %xmm1, 0x20(%rsp)
ucomisd %xmm1, %xmm0
jbe 0x2a14
movsd 0x38(%rsp), %xmm0
ucomisd 0x2919(%rip), %xmm0     # 0x5020
jne 0x2777
jp 0x2777
movl 0x4(%rsp), %ebp
movsd 0x40(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x48(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
leaq 0xc0(%rsp), %rdi
movq %r15, %rsi
callq 0x3692
leaq 0x158(%rsp), %rdi
movl %ebp, %esi
movsd 0x18(%rsp), %xmm0
movsd 0x8(%rsp), %xmm1
movsd 0x10(%rsp), %xmm2
leaq 0xc0(%rsp), %rbx
movq %rbx, %rdx
callq 0x385c
movsd %xmm0, 0x10(%rsp)
movq %rbx, %rdi
callq 0x2c66
movsd 0x38(%rsp), %xmm0
ucomisd 0x2891(%rip), %xmm0     # 0x5010
jne 0x27ef
jp 0x27ef
movl 0x4(%rsp), %ebp
movsd 0x40(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x48(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
leaq 0xa8(%rsp), %rdi
movq %r15, %rsi
callq 0x3692
leaq 0x158(%rsp), %rdi
movsd 0x20(%rsp), %xmm0
movl %ebp, %esi
movsd 0x18(%rsp), %xmm1
movsd 0x8(%rsp), %xmm2
movsd 0x10(%rsp), %xmm3
leaq 0xa8(%rsp), %rbx
movq %rbx, %rdx
callq 0x3bba
movsd %xmm0, 0x10(%rsp)
movq %rbx, %rdi
callq 0x2c66
leaq 0x90(%rsp), %rbp
movq %rbp, %rdi
leaq 0x158(%rsp), %rsi
callq 0x4332
movsd 0x30(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
movl 0x4(%rsp), %ebx
leaq 0x78(%rsp), %rdi
movq %rbp, %rsi
callq 0x2b72
cvtsi2sd %ebx, %xmm1
movq %r15, %rdi
movsd 0x8(%rsp), %xmm0
movsd 0x18(%rsp), %xmm2
leaq 0x78(%rsp), %rbx
movq %rbx, %rsi
callq 0x3076
movsd %xmm0, 0x8(%rsp)
movq %rbx, %rdi
callq 0x2c66
movl 0x4(%rsp), %ebx
leal (%rbx,%rbx,2), %eax
cvtsi2sd %eax, %xmm0
movsd 0x8(%rsp), %xmm2
movapd %xmm2, %xmm1
divsd %xmm0, %xmm1
movsd %xmm1, 0x28(%rsp)
mulsd 0x279f(%rip), %xmm2     # 0x5018
movsd %xmm2, 0x8(%rsp)
movq 0x474a(%rip), %rdi      # 0x6fd0
leaq 0x2969(%rip), %rsi      # 0x51f6
callq 0x2130
movq %rax, %rdi
movsd 0x20(%rsp), %xmm0
callq 0x21a0
movq %rax, %rdi
leaq 0x2957(%rip), %rsi      # 0x5201
callq 0x2130
movsd 0x28(%rsp), %xmm0
movq %rax, %rdi
callq 0x21a0
movq %rax, %rdi
leaq 0x2944(%rip), %rsi      # 0x520b
callq 0x2130
movsd 0x8(%rsp), %xmm0
addsd 0x10(%rsp), %xmm0
cvtsi2sd %ebx, %xmm1
divsd %xmm1, %xmm0
movq %rax, %rdi
movsd %xmm0, 0x8(%rsp)
callq 0x21a0
movq %rax, %rdi
callq 0x2090
leaq 0x1e8(%rsp), %rdi
movsd 0x20(%rsp), %xmm0
callq 0x21a0
movq %rax, %rdi
leaq 0x2902(%rip), %rsi      # 0x5215
callq 0x2130
movsd 0x28(%rsp), %xmm0
movq %rax, %rdi
callq 0x21a0
movq %rax, %rdi
leaq 0x28e5(%rip), %rsi      # 0x5215
callq 0x2130
movq %rax, %rdi
movsd 0x8(%rsp), %xmm0
callq 0x21a0
movq %rax, %rdi
callq 0x2090
leaq 0x58(%rsp), %rdi
movq %r15, %rsi
callq 0x3692
movl 0x4(%rsp), %esi
movq %r14, %rdi
callq 0x21f0
movq %rax, %rdi
callq 0x2090
movq %r14, %rdi
callq 0x2090
xorl %ebp, %ebp
xorl %ebx, %ebx
movslq 0x4(%rsp), %rax
cmpq %rax, %rbx
jge 0x29ec
movq %r14, %rdi
movq %r13, %rsi
callq 0x2130
movq 0x58(%rsp), %rcx
movsd (%rcx,%rbp), %xmm0
movq %rax, %rdi
callq 0x21a0
movq %rax, %rdi
movq %r12, %rsi
callq 0x2130
movq 0x58(%rsp), %rcx
movsd 0x8(%rcx,%rbp), %xmm0
movq %rax, %rdi
callq 0x21a0
movq %rax, %rdi
movq %r12, %rsi
callq 0x2130
movq 0x58(%rsp), %rcx
movsd 0x10(%rcx,%rbp), %xmm0
movq %rax, %rdi
callq 0x21a0
movq %rax, %rdi
callq 0x2090
incq %rbx
addq $0x18, %rbp
jmp 0x2978
leaq 0x58(%rsp), %rdi
callq 0x2c66
leaq 0x90(%rsp), %rdi
callq 0x2c66
movsd 0x20(%rsp), %xmm1
addsd 0x30(%rsp), %xmm1
jmp 0x26e3
callq 0x20e0
movq %rax, %rbx
movq 0x45ad(%rip), %rdi      # 0x6fd0
leaq 0x27f1(%rip), %rsi      # 0x521b
callq 0x2130
subq 0x50(%rsp), %rbx
cvtsi2ss %rbx, %xmm0
divss 0x25e7(%rip), %xmm0     # 0x5028
movq %rax, %rdi
callq 0x20f0
movq %rax, %rdi
callq 0x2090
leaq 0x1e8(%rsp), %rdi
callq 0x2160
leaq 0x3e8(%rsp), %rdi
callq 0x2160
leaq 0xd8(%rsp), %rdi
callq 0x2c66
leaq 0x158(%rsp), %rdi
callq 0x2bd2
leaq 0xf0(%rsp), %rdi
callq 0x2c04
leaq 0x1e8(%rsp), %rdi
callq 0x2180
leaq 0x3e8(%rsp), %rdi
callq 0x2180
xorl %eax, %eax
addq $0x5e8, %rsp            # imm = 0x5E8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x2ac2
movq %rax, %rbx
jmp 0x2b36
movq %rax, %rbx
jmp 0x2b50
jmp 0x2ad1
movq %rax, %rbx
jmp 0x2b5d
jmp 0x2b03
movq %rax, %rbx
leaq 0xa8(%rsp), %rdi
jmp 0x2b24
movq %rax, %rbx
leaq 0xc0(%rsp), %rdi
jmp 0x2b24
jmp 0x2b0a
movq %rax, %rbx
leaq 0x78(%rsp), %rdi
jmp 0x2b17
jmp 0x2b03
movq %rax, %rbx
jmp 0x2b29
jmp 0x2b0f
movq %rax, %rbx
jmp 0x2b1c
movq %rax, %rbx
leaq 0x58(%rsp), %rdi
callq 0x2c66
leaq 0x90(%rsp), %rdi
callq 0x2c66
leaq 0xd8(%rsp), %rdi
callq 0x2c66
leaq 0x158(%rsp), %rdi
callq 0x2bd2
leaq 0xf0(%rsp), %rdi
callq 0x2c04
leaq 0x1e8(%rsp), %rdi
callq 0x2180
leaq 0x3e8(%rsp), %rdi
callq 0x2180
movq %rbx, %rdi
callq 0x2210