import java.io.*;
import java.lang.Math;

public class alphaQuartz2jmol {
  public static void main( String[] args ) {
    int i,j,k, icoord, iatom;

    int nXcell = 2, nYcell = 2, nZcell = 2;
    double aa = 4.9134, cc = 5.4052;

    double x,y,z, x_cart, y_cart, z_cart;
    double [][] base, silicon, oxygene, Si_cart, Ox_cart; 
    double []   vector, tempo;
                FileOutputStream out; // declare a file output object
                FileOutputStream parsec_out; // declare a file output object
                PrintStream p; // declare a print stream object

    System.out.println("This program generates the structure of alpha-Quartz");
    System.out.println("Taking the parameters from the Navy");
    System.out.println("Written by carrier@cs.umn.edu");
    System.out.println("Group #154; P6(_3)/mmc");

    int num_atoms_Si = 3;
    int num_atoms_Ox = 6;

    silicon = new double [num_atoms_Si][3];
    oxygene = new double [num_atoms_Ox][3];

    Si_cart = new double [num_atoms_Si][3];
    Ox_cart = new double [num_atoms_Ox][3];

    base    = new double [3][3];
    vector  = new double [3];
    tempo   = new double [3];

// The basis
   base[0][0] = 0.5; 
   base[0][1] = -Math.sqrt(3.0)/2.0; 
   base[0][2] = 0.000;

   base[1][0] = 0.5; 
   base[1][1] =  Math.sqrt(3.0)/2.0; 
   base[1][2] = 0.000;

   base[2][0] = 0.0; 
   base[2][1] = 0.0; 
   base[2][2] = cc/aa;
    

// print the basis
    System.out.println("The lattice basis");
    System.out.printf( "%2.12f %2.12f %2.12f\n",base[0][0], base[0][1], base[0][2] );
    System.out.printf( "%2.12f %2.12f %2.12f\n",base[1][0], base[1][1], base[1][2] );
    System.out.printf( "%2.12f %2.12f %2.12f\n",base[2][0], base[2][1], base[2][2] );

// prints to file out
    try
    {
      // Create a new file output stream
      out = new FileOutputStream("alphaQuartz.xyz");

      // Connect print stream to the output stream
      p = new PrintStream( out );

      p.println (num_atoms_Si + num_atoms_Ox);
      p.println();

      System.out.println( "6c ; O" );
//    Data from the Amer. Mineralogy society: Type in mineral "quartz" at http://rruff.geo.arizona.edu/AMS/amcsd.php
//    x = 0.4135;
//    y = 0.2669;
//    z = 0.1191; // That one makes no sense as it is. According to the Navy, it is 0.7854 which is + 2/3 
                  // the value given by Levien-Prewitt

//    Data from the Navy  http://cst-www.nrl.navy.mil/lattice/struk/sio2a.html
      x = 0.4141;
      y = 0.2681;
      z = 0.1187 + 0.6666; 

//    Int. Tables for Cryst. #154, 6c
      oxygene[ 0][0] = (    x        ); oxygene[ 0][1] = (      y      ); oxygene[ 0][2] = (    z       );
      oxygene[ 1][0] = (     -y      ); oxygene[ 1][1] = (    x-y      ); oxygene[ 1][2] = (    z+2./3. );
      oxygene[ 2][0] = (   -x+y      ); oxygene[ 2][1] = (   -x        ); oxygene[ 2][2] = (    z+1./3. );
      oxygene[ 3][0] = (      y      ); oxygene[ 3][1] = (    x        ); oxygene[ 3][2] = (   -z       );
      oxygene[ 4][0] = (   -x        ); oxygene[ 4][1] = (   -x+y      ); oxygene[ 4][2] = (   -z+2./3. );
      oxygene[ 5][0] = (    x-y      ); oxygene[ 5][1] = (     -y      ); oxygene[ 5][2] = (   -z+1./3. );

//    Check for the elements outside the unit cell
      for( i = 0; i < num_atoms_Ox; i++ ) {
         for( icoord=0; icoord <=2; icoord++) {
            if (oxygene[i][icoord] >=  1.0) oxygene[i][icoord] -= 1.0;
            if (oxygene[i][icoord] <= -1.0) oxygene[i][icoord] += 1.0;
         }
      }
//    Transform in cartesian coordinates
      for( i = 0; i < num_atoms_Ox; i++ ) {
         Ox_cart[i][0] = aa*(oxygene[i][0]*base[0][0] + oxygene[i][1]*base[1][0] + oxygene[i][2]*base[2][0]);
         Ox_cart[i][1] = aa*(oxygene[i][0]*base[0][1] + oxygene[i][1]*base[1][1] + oxygene[i][2]*base[2][1]);
         Ox_cart[i][2] = aa*(oxygene[i][0]*base[0][2] + oxygene[i][1]*base[1][2] + oxygene[i][2]*base[2][2]);
      }

      for( i = 0; i < num_atoms_Ox; i++ ) {
         p.printf ("O   %2.8f  %2.8f  %2.8f       %2.8f  %2.8f  %2.8f\n",
                    oxygene[i][0], oxygene[i][1], oxygene[i][2],
                    Ox_cart[i][0], Ox_cart[i][1], Ox_cart[i][2]);
      }

      System.out.println( "3 a ; Si" );
      x = 0.4699 ;

//    Int. Tables for Cryst. #154, 3a:
      silicon[0][0] = (    x        ); silicon[0][1] = (    0        ); silicon[0][2] = (    2./3.    );
      silicon[1][0] = (    0        ); silicon[1][1] = (    x        ); silicon[1][2] = (    1./3.    );
      silicon[2][0] = (   -x        ); silicon[2][1] = (   -x        ); silicon[2][2] = (    0.       );

//    Check for the elements outside the unit cell
      for( i = 0; i < num_atoms_Si; i++ ) {
         for( icoord=0; icoord <=2; icoord++) {
            if (silicon[i][icoord] >=  1.0) silicon[i][icoord] -= 1.0;
            if (silicon[i][icoord] <= -1.0) silicon[i][icoord] += 1.0;
         }
      }
//    Transform in cartesian coordinates
      for( i = 0; i < num_atoms_Si; i++ ) {
         Si_cart[i][0] = aa*(silicon[i][0]*base[0][0] + silicon[i][1]*base[1][0] + silicon[i][2]*base[2][0]);
         Si_cart[i][1] = aa*(silicon[i][0]*base[0][1] + silicon[i][1]*base[1][1] + silicon[i][2]*base[2][1]);
         Si_cart[i][2] = aa*(silicon[i][0]*base[0][2] + silicon[i][1]*base[1][2] + silicon[i][2]*base[2][2]);
      }

      for( i = 0; i< num_atoms_Si; i++ ) {
         p.printf ("Si   %2.8f  %2.8f  %2.8f       %2.8f  %2.8f  %2.8f\n",
                    silicon[i][0], silicon[i][1], silicon[i][2],
                    Si_cart[i][0], Si_cart[i][1], Si_cart[i][2]);
      }

      p.close();
    }
    catch (Exception e)
    {
      System.err.println ("Error writing to file alphaQuartz.xyz");
    }

// supercell generation next
    try
    { 
      // Create a new file output stream
      out = new FileOutputStream("supercell.xyz");
      
      // Connect print stream to the output stream
      p = new PrintStream( out );
      
      p.println ( (num_atoms_Si + num_atoms_Ox)*(nXcell+1)*(nYcell+1)*(nZcell+1) );    
      p.println();
// oxygen
      for(iatom=0 ; iatom < num_atoms_Ox; iatom++ ) {
        for( i=0 ; i<=nXcell; i++ ) {
          for( j=0 ; j<=nYcell; j++ ) {
            for( k=0 ; k<=nZcell; k++ ) {
//            Transform in cartesian coordinates
              for( icoord=0; icoord <=2; icoord++) {
                 tempo[icoord] = (oxygene[iatom][0] + i)*base[0][icoord] 
                               + (oxygene[iatom][1] + j)*base[1][icoord]
                               + (oxygene[iatom][2] + k)*base[2][icoord];
              }
              p.printf ("O    %2.8f  %2.8f  %2.8f\n",tempo[0]*aa, tempo[1]*aa, tempo[2]*aa);
            }
          }
        }
      }
// silicon
      for(iatom=0 ; iatom < num_atoms_Si; iatom++ ) {
        for( i=0 ; i<=nXcell; i++ ) {
          for( j=0 ; j<=nYcell; j++ ) {
            for( k=0 ; k<=nZcell; k++ ) {
//            Transform in cartesian coordinates
              for( icoord=0; icoord <=2; icoord++) {
                 tempo[icoord] = (silicon[iatom][0] + i)*base[0][icoord] 
                               + (silicon[iatom][1] + j)*base[1][icoord]
                               + (silicon[iatom][2] + k)*base[2][icoord];
              }
              p.printf ("Si   %2.8f  %2.8f  %2.8f\n",tempo[0]*aa, tempo[1]*aa, tempo[2]*aa);
            }
          }
        }
      }
      p.close();
    }
    catch (Exception e)
    {
      System.err.println ("Error writing to file");
    }

  }
}
