// File: /workspace/github_cpp_makefile_star2_O2/Luthaf[P]zeopp/grid.cc
// Function: generateBOVGrid(ATOM_NETWORK*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>)
void generateBOVGrid(ATOM_NETWORK *atmnet, string name_f_dist, string name_g_dist, string name_h_dist, string name_f_bov, string name_g_bov, string name_h_bov) {

//-----declare large 3D array as a 3D pointer (i.e., ***) - we have to declare it as pointers otherwise we cannot declare an arbitrarily large grid - but if the grid is too large, you may not have enough RAM to store it, so watch the system monitor!
  double ***grid_distance;

//-----set the extent of the grid. If we know coordinate H (i.e. the coordinate in the abc plane that has all non-0 coordinates) we will know the maximum extent. 
//For my purposes, I defined a cube in terms of corners. A, B, and C correspond to defined unit cell vectors.
//D is the bottom corner between the B and C axes. E is the top corner between the A and C axes.
//F is the top corner between the B and C axes. G is the outermost corner. The innermost corner is simply (0, 0, 0).

  double origin_x = 0; 
  double origin_y = 0; 
  double origin_z = 0; 
  double Ax  = atmnet->v_a.x;
  double Bx = atmnet->v_b.x;
  double By  = atmnet->v_b.y;
  double Cx = atmnet->v_c.x;
  double Cy = atmnet->v_c.y;
  double Cz  = atmnet->v_c.z;

  double Dx = Ax + Bx; double Dy = By; double Dz = 0;
  double Ex = Ax + Cx; double Ey = Cy; double Ez = Cz;
  double Fx = Bx + Cx; double Fy = Cy; double Fz = Cz;
  double Gx = Ax + Bx + Cx; double Gy = By + Cy; double Gz = Cz;

  vector <double> xCoords;
  xCoords.push_back(origin_x); xCoords.push_back(Ax); xCoords.push_back(Bx); xCoords.push_back(Cx); xCoords.push_back(Dx); xCoords.push_back(Ex); xCoords.push_back(Fx); xCoords.push_back(Gx);
  vector <double> yCoords;
  yCoords.push_back(origin_y);yCoords.push_back(By); yCoords.push_back(Cy); yCoords.push_back(Gy);
	vector <double> zCoords;
	zCoords.push_back(origin_y); zCoords.push_back(Cz);

  double xMin = 1000; double xMax = 0;
  for (int a=0; a<xCoords.size(); a++){
    xMin = min(xMin, xCoords.at(a));
    xMax = max(xMax, xCoords.at(a));
  }

  double yMin = 1000; double yMax = 0;
  for (int b=0; b<yCoords.size(); b++){
    yMin = min(yMin, yCoords.at(b));
    yMax = max(yMax, yCoords.at(b));
  }
  double zMin = 1000; double zMax = 0;
  for (int c=0; c<zCoords.size(); c++){
    zMin = min(zMin, zCoords.at(c));
    zMax = max(zMax, zCoords.at(c));
  }

  double XGridDist = xMax - xMin; double YGridDist = yMax - yMin; double ZGridDist = zMax - zMin;


//-----set size that grid will take, i.e. the number of grid points in each dimension
  
  double tempXgrid = XGridDist/GRIDRES; double tempYgrid = YGridDist/GRIDRES; double tempZgrid = ZGridDist/GRIDRES;

  int x_grid_steps = ceil(tempXgrid);
  int y_grid_steps = ceil(tempYgrid); 
  int z_grid_steps = ceil(tempZgrid);

  double shiftInX = x_grid_steps - tempXgrid;
  double shiftInY = y_grid_steps - tempYgrid;
  double shiftInZ = z_grid_steps - tempZgrid;

  double xGridRes = XGridDist/x_grid_steps; double yGridRes = YGridDist/y_grid_steps; double zGridRes = ZGridDist/z_grid_steps;

  x_grid_steps++;
  y_grid_steps++;
  z_grid_steps++;

//-----create large 3D array
  printf("Declaring 3D array.\n\n");
	grid_distance = new double**[x_grid_steps];
	for(int i=0; i<x_grid_steps; i++) {
		grid_distance[i] = new double*[y_grid_steps];
		for(int j=0; j<y_grid_steps; j++) {
			grid_distance[i][j] = new double[z_grid_steps];
		}
	}

//-----fill it with values for the F function
  printf("Filling 3D array F with values.\n\n");
	for(int i=0; i<x_grid_steps; i++) {
		for(int j=0; j<y_grid_steps; j++) {
			for(int k=0; k<z_grid_steps; k++) {
				grid_distance[i][j][k] = calculate_distance_function(atmnet, i,j,k, xMin, yMin, 0, xGridRes, yGridRes, zGridRes, x_grid_steps, y_grid_steps, z_grid_steps, 'f'); 
			}
		}
	}

//-----Print structure_f.distances and structure_f.bov
  printf("Printing F grid.\n\n");
  FILE *file_distances_f, *file_bov_f; 
  char* distance_filename_f = new char [100];
  strcpy(distance_filename_f, name_f_dist.c_str()); 
  file_distances_f = fopen(distance_filename_f,"w");
  write_distances(file_distances_f, grid_distance, x_grid_steps, y_grid_steps, z_grid_steps);
  fclose(file_distances_f); 
  char* bov_filename_f = new char [100];
  strcpy(bov_filename_f, name_f_bov.c_str()); 
  file_bov_f = fopen(bov_filename_f,"w");
  write_bov(file_bov_f, distance_filename_f, x_grid_steps, y_grid_steps, z_grid_steps, xMin, yMin, zMin, XGridDist, YGridDist, ZGridDist);
  fclose(file_bov_f);

//-----fill it with values for the G function
/*
  printf("Filling 3D array G with values.\n\n");
	for(int i=0; i<x_grid_steps; i++) {
		for(int j=0; j<y_grid_steps; j++) {
			for(int k=0; k<z_grid_steps; k++) {
				grid_distance[i][j][k] = calculate_distance_function(atmnet, i,j,k, xMin, yMin, 0, xGridRes, yGridRes, zGridRes, x_grid_steps, y_grid_steps, z_grid_steps, 'g'); 
			}
		}
	}

//-----Print structure_g.distances and structure_g.bov
  printf("Printing G grid.\n\n");
  FILE *file_distances_g, *file_bov_g; 
  char* distance_filename_g = new char [100];
  strcpy(distance_filename_g, name_g_dist.c_str()); 
  file_distances_g = fopen(distance_filename_g,"w");
  write_distances(file_distances_g, grid_distance, x_grid_steps, y_grid_steps, z_grid_steps);
  fclose(file_distances_g); 
  char* bov_filename_g = new char [100];
  strcpy(bov_filename_g, name_g_bov.c_str()); 
  file_bov_g = fopen(bov_filename_g,"w");
  write_bov(file_bov_g, distance_filename_g, x_grid_steps, y_grid_steps, z_grid_steps, xMin, yMin, zMin, XGridDist, YGridDist, ZGridDist);
  fclose(file_bov_g);
*/


//-----fill it with values for the H function
/*
  printf("Filling 3D array H with values.\n\n");
	for(int i=0; i<x_grid_steps; i++) {
		for(int j=0; j<y_grid_steps; j++) {
			for(int k=0; k<z_grid_steps; k++) {
				grid_distance[i][j][k] = calculate_distance_function(atmnet, i,j,k, xMin, yMin, 0, xGridRes, yGridRes, zGridRes, x_grid_steps, y_grid_steps, z_grid_steps, 'h'); 
			}
		}
	}


//-----Print structure_h.distances and structure_h.bov

  printf("Printing H grid.\n\n");
  FILE *file_distances_h, *file_bov_h; 
  char* distance_filename_h = new char [100];
  strcpy(distance_filename_h, name_h_dist.c_str()); 
  file_distances_h = fopen(distance_filename_h,"w");
  write_distances(file_distances_h, grid_distance, x_grid_steps, y_grid_steps, z_grid_steps);
  fclose(file_distances_h); 
  char* bov_filename_h = new char [100];
  strcpy(bov_filename_h, name_h_bov.c_str()); 
  file_bov_h = fopen(bov_filename_h,"w");
  write_bov(file_bov_h, distance_filename_h, x_grid_steps, y_grid_steps, z_grid_steps, xMin, yMin, zMin, XGridDist, YGridDist, ZGridDist);
  fclose(file_bov_h);
*/


//-----free memory!
  printf("Freeing memory.\n\n");
	for(int i=0; i<x_grid_steps; i++) {
		for(int j=0; j<y_grid_steps; j++) {
			delete[] grid_distance[i][j];
		}
    delete[] grid_distance[i];
	}
  delete[] grid_distance; //important to have one "delete[]" per "new"
  delete[] distance_filename_f;
  //delete[] distance_filename_g;
  //delete[] distance_filename_h;
  delete[] bov_filename_f;
  //delete[] bov_filename_g;
  //delete[] bov_filename_h;

//---end successfully
  printf("Program complete.\n\n");


}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x198, %rsp            # imm = 0x198
movq %r8, %r12
movq %rsi, %r13
movq %rdi, %r15
leaq 0x190(%rsp), %rsi
andq $0x0, (%rsi)
andq $0x0, 0xc8(%rsp)
movsd 0x38(%rdi), %xmm0
movsd %xmm0, 0x178(%rsp)
movsd 0x50(%rdi), %xmm1
movsd %xmm1, 0x170(%rsp)
movsd 0x58(%rdi), %xmm2
movsd %xmm2, 0x168(%rsp)
movsd 0x68(%rdi), %xmm3
movsd %xmm3, 0x160(%rsp)
movsd 0x70(%rdi), %xmm4
movsd %xmm4, 0x158(%rsp)
movsd 0x78(%rdi), %xmm5
movsd %xmm5, 0x150(%rsp)
movapd %xmm0, %xmm5
addsd %xmm1, %xmm5
movsd %xmm5, 0x148(%rsp)
addsd %xmm3, %xmm0
movsd %xmm0, 0x140(%rsp)
addsd %xmm3, %xmm1
movsd %xmm1, 0x138(%rsp)
addsd %xmm3, %xmm5
movsd %xmm5, 0x130(%rsp)
addsd %xmm4, %xmm2
movsd %xmm2, 0x128(%rsp)
xorpd %xmm0, %xmm0
leaq 0x50(%rsp), %rdi
movapd %xmm0, (%rdi)
andq $0x0, 0x10(%rdi)
callq 0xac88
leaq 0x50(%rsp), %rdi
leaq 0x178(%rsp), %rsi
callq 0xac88
leaq 0x50(%rsp), %rdi
leaq 0x170(%rsp), %rsi
callq 0xac88
leaq 0x50(%rsp), %rdi
leaq 0x160(%rsp), %rsi
callq 0xac88
leaq 0x50(%rsp), %rdi
leaq 0x148(%rsp), %rsi
callq 0xac88
leaq 0x50(%rsp), %rdi
leaq 0x140(%rsp), %rsi
callq 0xac88
leaq 0x50(%rsp), %rdi
leaq 0x138(%rsp), %rsi
callq 0xac88
leaq 0x50(%rsp), %rdi
leaq 0x130(%rsp), %rsi
callq 0xac88
xorpd %xmm0, %xmm0
leaq 0xb0(%rsp), %rdi
movapd %xmm0, (%rdi)
andq $0x0, 0x10(%rdi)
leaq 0xc8(%rsp), %rsi
callq 0xac88
leaq 0xb0(%rsp), %rdi
leaq 0x168(%rsp), %rsi
callq 0xac88
leaq 0xb0(%rsp), %rdi
leaq 0x158(%rsp), %rsi
callq 0xac88
leaq 0xb0(%rsp), %rdi
leaq 0x128(%rsp), %rsi
callq 0xac88
xorpd %xmm0, %xmm0
leaq 0xe0(%rsp), %rdi
movapd %xmm0, (%rdi)
andq $0x0, 0x10(%rdi)
leaq 0xc8(%rsp), %rsi
callq 0xac88
leaq 0xe0(%rsp), %rdi
leaq 0x150(%rsp), %rsi
callq 0xac88
xorpd %xmm0, %xmm0
movsd %xmm0, 0x18(%rsp)
movsd 0x9b229(%rip), %xmm0    # 0x101710
movsd %xmm0, 0x30(%rsp)
xorl %ebx, %ebx
leaq 0x50(%rsp), %r14
movq 0x58(%rsp), %rax
subq 0x50(%rsp), %rax
sarq $0x3, %rax
cmpq %rbx, %rax
jbe 0x6654e
movq %r14, %rdi
movq %rbx, %rsi
callq 0xaa50
movsd (%rax), %xmm0
movsd %xmm0, 0x20(%rsp)
movq %r14, %rdi
movq %rbx, %rsi
callq 0xaa50
movsd 0x20(%rsp), %xmm1
minsd 0x30(%rsp), %xmm1
movsd (%rax), %xmm0
maxsd 0x18(%rsp), %xmm0
incq %rbx
movsd %xmm1, 0x30(%rsp)
movsd %xmm0, 0x18(%rsp)
jmp 0x664f4
xorpd %xmm0, %xmm0
movapd %xmm0, 0x40(%rsp)
movsd 0x9b1b0(%rip), %xmm0    # 0x101710
movapd %xmm0, 0xa0(%rsp)
xorl %ebx, %ebx
leaq 0xb0(%rsp), %r14
movq 0xb8(%rsp), %rax
subq 0xb0(%rsp), %rax
sarq $0x3, %rax
cmpq %rbx, %rax
jbe 0x665d9
movq %r14, %rdi
movq %rbx, %rsi
callq 0xaa50
movsd (%rax), %xmm0
movsd %xmm0, 0x20(%rsp)
movq %r14, %rdi
movq %rbx, %rsi
callq 0xaa50
movsd 0x20(%rsp), %xmm1
minsd 0xa0(%rsp), %xmm1
movsd (%rax), %xmm0
maxsd 0x40(%rsp), %xmm0
incq %rbx
movapd %xmm1, 0xa0(%rsp)
movapd %xmm0, 0x40(%rsp)
jmp 0x66573
xorpd %xmm0, %xmm0
movapd %xmm0, 0x20(%rsp)
movsd 0x9b125(%rip), %xmm0    # 0x101710
movapd %xmm0, 0xd0(%rsp)
xorl %ebx, %ebx
leaq 0xe0(%rsp), %r14
movq 0xe8(%rsp), %rax
subq 0xe0(%rsp), %rax
sarq $0x3, %rax
cmpq %rbx, %rax
jbe 0x6666a
movq %r14, %rdi
movq %rbx, %rsi
callq 0xaa50
movsd (%rax), %xmm0
movsd %xmm0, 0x90(%rsp)
movq %r14, %rdi
movq %rbx, %rsi
callq 0xaa50
movsd 0x90(%rsp), %xmm1
minsd 0xd0(%rsp), %xmm1
movsd (%rax), %xmm0
maxsd 0x20(%rsp), %xmm0
incq %rbx
movapd %xmm1, 0xd0(%rsp)
movapd %xmm0, 0x20(%rsp)
jmp 0x665fe
movq %r13, 0x110(%rsp)
movq %r12, 0x108(%rsp)
movsd 0x18(%rsp), %xmm1
subsd 0x30(%rsp), %xmm1
movapd 0x20(%rsp), %xmm2
unpcklpd 0x40(%rsp), %xmm2       # xmm2 = xmm2[0],mem[0]
movapd 0xd0(%rsp), %xmm0
unpcklpd 0xa0(%rsp), %xmm0       # xmm0 = xmm0[0],mem[0]
subpd %xmm0, %xmm2
movapd %xmm2, 0x20(%rsp)
movsd %xmm1, 0x18(%rsp)
movapd %xmm1, %xmm0
divsd 0x9e050(%rip), %xmm0    # 0x104710
callq 0x40c0
movapd %xmm0, 0x90(%rsp)
cvttsd2si %xmm0, %ebp
movapd 0x20(%rsp), %xmm0
divpd 0x9e060(%rip), %xmm0    # 0x104740
movapd %xmm0, 0x40(%rsp)
callq 0x40c0
movapd %xmm0, 0x80(%rsp)
movapd 0x40(%rsp), %xmm0
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
callq 0x40c0
movapd %xmm0, 0x40(%rsp)
leaq 0x9e244(%rip), %rdi     # 0x104954
callq 0x4670
movslq %ebp, %rax
cmpl $-0x1, %ebp
movq %rax, 0x70(%rsp)
leaq 0x8(,%rax,8), %rdi
pushq $-0x1
popq %rbx
cmovlq %rbx, %rdi
callq 0x4030
movq %rax, %r12
movapd 0x80(%rsp), %xmm0
unpcklpd 0x40(%rsp), %xmm0       # xmm0 = xmm0[0],mem[0]
cvttpd2dq %xmm0, %xmm0
movd %xmm0, %edx
pshufd $0x55, %xmm0, %xmm1     # xmm1 = xmm0[1,1,1,1]
movd %xmm1, %eax
cvttpd2dq 0x90(%rsp), %xmm1
cvtdq2pd %xmm1, %xmm1
cvtsi2sd %eax, %xmm2
cvtsi2sd %edx, %xmm3
movsd 0x18(%rsp), %xmm4
divsd %xmm1, %xmm4
movsd %xmm4, 0x40(%rsp)
movapd 0x20(%rsp), %xmm4
movapd %xmm4, %xmm1
unpckhpd %xmm4, %xmm1            # xmm1 = xmm1[1],xmm4[1]
movapd %xmm1, 0x180(%rsp)
divsd %xmm2, %xmm1
movapd %xmm1, 0x90(%rsp)
movsd %xmm4, 0x100(%rsp)
divsd %xmm3, %xmm4
movapd %xmm4, 0x20(%rsp)
incl %ebp
movl %ebp, 0x7c(%rsp)
leal 0x1(%rax), %ecx
movl %ecx, 0x3c(%rsp)
movslq %ecx, %rsi
pshufd $0x50, %xmm0, %xmm0     # xmm0 = xmm0[0,0,1,1]
pcmpeqd %xmm1, %xmm1
pcmpgtd %xmm0, %xmm1
movmskpd %xmm1, %ecx
shlq $0x3, %rsi
testb $0x2, %cl
cmovneq %rbx, %rsi
movq %rsi, 0x120(%rsp)
movq %rdx, 0x118(%rsp)
incl %edx
movl %edx, 0x38(%rsp)
movslq %edx, %r13
shlq $0x3, %r13
testb $0x1, %cl
cmovneq %rbx, %r13
cltq
movq %rax, 0x80(%rsp)
xorl %ebp, %ebp
cmpq 0x70(%rsp), %rbp
jg 0x6684d
movq 0x120(%rsp), %rdi
callq 0x4030
movq %rax, %rbx
movq %rax, (%r12,%rbp,8)
xorl %r14d, %r14d
cmpq 0x80(%rsp), %r14
jg 0x66848
movq %r13, %rdi
callq 0x4030
movq %rax, (%rbx,%r14,8)
incq %r14
jmp 0x6682d
incq %rbp
jmp 0x6680f
leaq 0x9e115(%rip), %rdi     # 0x104969
callq 0x4670
movslq 0x118(%rsp), %rbp
xorl %r14d, %r14d
cmpq 0x70(%rsp), %r14
jg 0x668db
xorl %r13d, %r13d
cmpq 0x80(%rsp), %r13
jg 0x668d6
xorl %ebx, %ebx
cmpq %rbp, %rbx
jg 0x668d1
movl $0x66, 0x8(%rsp)
xorpd %xmm2, %xmm2
movq %r15, %rdi
movl %r14d, %esi
movl %r13d, %edx
movl %ebx, %ecx
movsd 0x30(%rsp), %xmm0
movapd 0xa0(%rsp), %xmm1
movsd 0x40(%rsp), %xmm3
movapd 0x90(%rsp), %xmm4
movapd 0x20(%rsp), %xmm5
callq 0x66aa4
movq (%r12,%r14,8), %rax
movq (%rax,%r13,8), %rax
movsd %xmm0, (%rax,%rbx,8)
incq %rbx
jmp 0x6687a
incq %r13
jmp 0x6686e
incq %r14
jmp 0x66864
leaq 0x9e0a8(%rip), %rdi     # 0x10498a
callq 0x4670
pushq $0x64
popq %rdi
callq 0x4030
movl 0x7c(%rsp), %ebp
movq %rax, %r15
movq 0x110(%rsp), %rax
movq (%rax), %rsi
movq %r15, %rdi
callq 0x4430
leaq 0x9a2a4(%rip), %rsi     # 0x100bb4
movq %r15, %rdi
callq 0x4530
movq %rax, %rbx
movq %rax, %rdi
movq %r12, %rsi
movl %ebp, %edx
movl 0x3c(%rsp), %ecx
movl 0x38(%rsp), %r8d
callq 0x66c75
movq %rbx, %rdi
callq 0x4490
pushq $0x64
popq %rdi
callq 0x4030
movq %rax, %r14
movq 0x108(%rsp), %rax
movq (%rax), %rsi
movq %r14, %rdi
callq 0x4430
leaq 0x9a256(%rip), %rsi     # 0x100bb4
movq %r14, %rdi
callq 0x4530
movq %rax, %rbx
movq %rax, %rdi
movq %r15, %rsi
movl %ebp, %edx
movl 0x3c(%rsp), %ecx
movl 0x38(%rsp), %r8d
movsd 0x30(%rsp), %xmm0
movapd 0xa0(%rsp), %xmm1
movapd 0xd0(%rsp), %xmm2
movsd 0x18(%rsp), %xmm3
movapd 0x180(%rsp), %xmm4
movsd 0x100(%rsp), %xmm5
callq 0x66d75
movq %rbx, %rdi
callq 0x4490
leaq 0x9dfde(%rip), %rdi     # 0x10499c
callq 0x4670
xorl %ebx, %ebx
cmpq 0x70(%rsp), %rbx
jg 0x669ff
xorl %r13d, %r13d
movq (%r12,%rbx,8), %rdi
cmpq 0x80(%rsp), %r13
jg 0x669f0
movq (%rdi,%r13,8), %rdi
testq %rdi, %rdi
je 0x669eb
callq 0x4590
incq %r13
jmp 0x669cf
testq %rdi, %rdi
je 0x669fa
callq 0x4590
incq %rbx
jmp 0x669c5
movq %r12, %rdi
callq 0x4590
movq %r15, %rdi
callq 0x4590
movq %r14, %rdi
callq 0x4590
leaq 0x9df8f(%rip), %rdi     # 0x1049ad
callq 0x4670
leaq 0xe0(%rsp), %rdi
callq 0xb25c
leaq 0xb0(%rsp), %rdi
callq 0xb25c
leaq 0x50(%rsp), %rdi
callq 0xb25c
addq $0x198, %rsp            # imm = 0x198
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x66a75
jmp 0x66a75
jmp 0x66a75
jmp 0x66a75
movq %rax, %rbx
jmp 0x66a85
movq %rax, %rbx
jmp 0x66a92
jmp 0x66a75
jmp 0x66a75
jmp 0x66a75
jmp 0x66a75
jmp 0x66a75
movq %rax, %rbx
leaq 0xe0(%rsp), %rdi
callq 0xb25c
leaq 0xb0(%rsp), %rdi
callq 0xb25c
leaq 0x50(%rsp), %rdi
callq 0xb25c
movq %rbx, %rdi
callq 0x4780