/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import java.awt.*;
import java.awt.event.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
import java.text.*;
import java.awt.Graphics2D;
import java.awt.geom.*;

/*
 * NewJApplet.java
 *
 * Created on 09.01.2009, 11:17:57
 */
/**
 *
 * @author poj
 */
public class NewJApplet extends javax.swing.JApplet implements ActionListener {

    Timer timer;
    DecimalFormat df;
    double [][] Rmat;
    double xx,xy,xz,yx,yy,yz,zx,zy,zz; // rotation matrix
    double[] xc, yc, zc, bondl, phi, theta, xc0,yc0,zc0;
    double[] xcc, ycc, zcc;
    double[] gradx, grady, gradz,grad0x,grad0y,grad0z;
    double[] sx, sy, sz, s0x, s0y, s0z;
    int[] nat;
    double[] amass, dvec, evec;
    int[][] bondats;
    int[][] phiats;
    int[][] thetaats;
    double[][] ffbond, ffang,ffthet;
    int ffbondats[][], ffangats[][],ffthetats[][];
    int natmax = 25;
    int nbondmax = 50;
    int nphimax = 100;
    int nthetamax = 100;
    int natoms, nbonds, nphi, ntheta;
    int indexb, indexa,indexc;
    int nffbond, nffang,nffthet;
    double linepos = 0;
    double rotx = 0;
    double roty = 0;
    double rotz = 0;
    double[][] rmat;
    Point oldp, newp;
    boolean isfirst = true;
    double gbet = 0;
    double gbetold = 0;
    int countsteps = 0;
    double[][] Hessian, zmat;
    boolean animation = false;
    boolean modes_available=false;
    int dirflag = 1;
    int plotmode=0;
    double modf=1;
    int phase=0;
    int xfrom=0;
    int yfrom=0;
    int xto=0;
    int yto=0;
    
    double fac=0.696/1.66E-27;
    double s2cm=5E-12;
    
    double h,gnorm,gnorm0,lasth,lastgrad,gnormd;
    
    int animation_mode=3;
    
    boolean dihedrals_on=true;


    /** Initializes the applet NewJApplet */
    public void init() {
        try {
            java.awt.EventQueue.invokeAndWait(new Runnable() {

                public void run() {
                    initComponents();
                    init_arrays();
                    set_ic();
                    set_ff();
                    prepare_minim();
                }
            });
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void init_arrays() {
        nat = new int[natmax];
        bondats = new int[nbondmax][2];
        phiats = new int[nphimax][3];
        thetaats = new int[nthetamax][4];

        xc = new double[natmax];
        yc = new double[natmax];
        zc = new double[natmax];
        xcc = new double[natmax];
        ycc = new double[natmax];
        zcc = new double[natmax];

        xc0 = new double[natmax];
        yc0 = new double[natmax];
        zc0 = new double[natmax];

        sx = new double[natmax];
        sy = new double[natmax];
        sz = new double[natmax];
        s0x = new double[natmax];
        s0y = new double[natmax];
        s0z = new double[natmax];
        dvec = new double[3 * natmax];
        evec = new double[3 * natmax];

        gradx = new double[natmax];
        grady = new double[natmax];
        gradz = new double[natmax];
        grad0x = new double[natmax];
        grad0y = new double[natmax];
        grad0z = new double[natmax];
        bondl = new double[nbondmax];
        phi = new double[nphimax];
        theta = new double[nthetamax];

        ffbond = new double[nbondmax][2];
        ffbondats = new int[nbondmax][2];
        ffang = new double[nbondmax][2];
        ffangats = new int[nbondmax][3];
        ffthet= new double[nbondmax][2];
        ffangats = new int[nbondmax][3];
        ffthetats = new int[nbondmax][4];

        Hessian = new double[3 * natmax][3 * natmax];
        zmat = new double[3 * natmax][3 * natmax];
        
        
        xx=yy=zz=1.0;
        xy=xz=yx=yz=zx=zy=0.0;

        amass = new double[natmax];

        timer = new Timer(100, this);
        timer.setInitialDelay(100);
        timer.start();

        jLabel2.setText(""+plotmode);
        
        
         df = new DecimalFormat("########0.0");


    }

    public void actionPerformed(ActionEvent e) {
        int i;
       
        
        

        
        if (animation) {

             
            if (animation_mode==0) animate_modes();
            
            if(animation_mode==1) verlet();
            
            if (animation_mode==2)  steepest(true);

            if (animation_mode==3)  steepest(false);
        }

        //test(1);
        jPanel1.repaint();
        timer.restart();

    }
    
    
    public void animate_modes() {
        int i;
        double fm, cp;
        cp = Math.cos(phase * Math.PI / 4);
        for (i = 0; i < natoms; i++) {
            fm = cp / Math.sqrt(amass[i]);
            xcc[i] = xc[i] + Hessian[i * 3][plotmode] * modf * fm;
            ycc[i] = yc[i] + Hessian[i * 3 + 1][plotmode] * modf * fm;
            zcc[i] = zc[i] + Hessian[i * 3 + 2][plotmode] * modf * fm;


        }
        phase++;
        if (phase == 8) {
            phase = 0;
        }

    }

    public void addbond(int i1, int i2, double b) {

        bondl[nbonds] = b;

        bondats[nbonds][0] = i1;
        bondats[nbonds][1] = i2;

        nbonds += 1;

    }

    public void addphi(int i1, int i2, int i3, double p) {

        phi[nphi] = p;
        phiats[nphi][0] = i1;
        phiats[nphi][1] = i2;
        phiats[nphi][2] = i3;

        nphi++;


    }

    public void addtheta(int i1, int i2, int i3, int i4, double t) {

        theta[ntheta] = t;
        thetaats[ntheta][0] = i1;
        thetaats[ntheta][1] = i2;
        thetaats[ntheta][2] = i3;
        thetaats[ntheta][3] = i4;

        ntheta++;

    }

    public void addatom(int na, int n1, int n2, int n3, double b, double p, double t) {


        double xb, yb, zb, x1, x2, x3, y1, y2, y3, z1, z2, z3, xn, yn, zn, s1, s2, c1, c2, sp;

        nat[natoms] = na;

        switch (na) {

            case 1:
                amass[natoms] = 1.0;
                break;
            case 6:
                amass[natoms] = 12.0;
                break;
            case 7:
                amass[natoms] = 14.0;
                break;
            case 8:
                amass[natoms] = 16.0;
                break;
            default:
                amass[natoms] = 1.0;
                break;
        }


        addbond(natoms, n1, b);
        addphi(natoms, n1, n2, p);
        addtheta(natoms, n1, n2, n3, t);


        // unit vector along  2 - 1

        x1 = xc[n1] - xc[n2];
        x2 = yc[n1] - yc[n2];
        x3 = zc[n1] - zc[n2];

        xb = x1 * x1 + x2 * x2 + x3 * x3;
        xb = Math.sqrt(xb);

        x1 /= xb;
        x2 /= xb;
        x3 /= xb;

        // perpendicular vector in plane 1-2-3


        y1 = xc[n2] - xc[n3];
        y2 = yc[n2] - yc[n3];
        y3 = zc[n2] - zc[n3];



        sp = x1 * y1 + x2 * y2 + x3 * y3;
        yb = y1 * y1 + y2 * y2 + y3 * y3;



        y1 = y1 - x1 * sp;
        y2 = y2 - x2 * sp;
        y3 = y3 - x3 * sp;

        yb = y1 * y1 + y2 * y2 + y3 * y3;
        yb = Math.sqrt(yb);

        y1 /= yb;
        y2 /= yb;
        y3 /= yb;

        // third basis vector

        z1 = x2 * y3 - x3 * y2;
        z2 = x3 * y1 - x1 * y3;
        z3 = x1 * y2 - x2 * y1;

        zb = z1 * z1 + z2 * z2 + z3 * z3;
        zb = Math.sqrt(zb);

        z1 /= zb;
        z2 /= zb;
        z3 /= zb;


        // new position



        c1 = Math.cos((180 - p) * Math.PI / 180);
        c2 = Math.cos((180 - t) * Math.PI / 180);
        s1 = Math.sin((180 - p) * Math.PI / 180);
        s2 = Math.sin((180 - t) * Math.PI / 180);


        xn = c1 * x1 + s1 * c2 * y1 + s1 * s2 * z1;
        yn = c1 * x2 + s1 * c2 * y2 + s1 * s2 * z2;
        zn = c1 * x3 + s1 * c2 * y3 + s1 * s2 * z3;


        //  jTextArea2.append("xax " + x1 + " " + x2 + " " + x3 + " \n");
        //  jTextArea2.append("yax " + y1 + " " + y2 + " " + y3 + " \n");
        //  jTextArea2.append("zax " + z1 + " " + z2 + " " + z3 + " \n");
        //  jTextArea2.append("neu " + xn + " " + yn + " " + zn + " "+(xn*xn+yn*yn+zn*zn)+" \n");


        xc[natoms] = xc[n1] + b * xn;
        yc[natoms] = yc[n1] + b * yn;
        zc[natoms] = zc[n1] + b * zn;



        natoms++;



    }

    public void set_ic() {

        double dx, dy, dz, xce,yce,zce;

        int i, j, k, l, m, n;

        double rcn = 1.44;
        double rcc = 1.45;
        double rco = 1.22;
        double rch = 1.089;
        double rnh = 1.008;
        double roh = 0.95;

        double phincc = 109.5;
        double phicco = 120;
 
        double phih = 109.5;

        double thetncco = -180;
        double thetccnc = 180;


        natoms = 0;
        nbonds = 0;
        nphi = 0;
        ntheta = 0;




        // first atom


        nat[0] = 7;
        xc[0] = yc[0] = zc[0] = 0.0;
        amass[0]=14.0;

        // second atom


        nat[1] = 6;
        amass[1]=12.0;
        xc[1] = yc[1] = 0;
        zc[1] = rcn;

        // connect 1-2

        addbond(0, 1, 1.43);


        // third atom

        nat[2] = 6;
        amass[2]=12.0;
        xc[2] = 0;

        zc[2] = zc[1] + rcc * Math.cos((180 - phincc) * Math.PI / 180);
        yc[2] = yc[1] + rcc * Math.sin((180 - phincc) * Math.PI / 180);


        // connect 1-2-3

        addbond(1, 2, rcc);
        addphi(0, 1, 2, phincc);


        natoms = 3;


        // rest of atoms

        //jTextArea2.append(" atom 2" + xc[1] + " " + yc[1] + " " + zc[1] + "\n");
        //jTextArea2.append(" atom 3" + xc[2] + " " + yc[2] + " " + zc[2] + "\n");


        addatom(7, 2, 1, 0, rcn, phincc, 180.0);
        addatom(6, 3, 2, 1, rcn, phincc, 180.0);
        addatom(6, 4, 3, 2, rcc, phincc, 180.0);

        addatom(8, 2, 1, 0, rco, phicco, -60.0);


        addatom(8, 5, 4, 3, rco, phicco, 180.0);
        addatom(8, 5, 4, 3, rco, phicco, -60.0);


        addatom(1, 0, 1, 2, rnh, phih, -60.0);
        addatom(1, 0, 1, 2, rnh, phih,  60.0);
      
        addatom(1, 1, 2, 3, rch, phih, -60.0);
        addatom(1, 1, 2, 3, rch, phih, 60.0);
        addatom(1, 3, 2, 1, rnh, phih, 0.0);
        addatom(1, 4, 3, 2, rch, phih, 0.0);
        addatom(1, 4, 3, 2, rch, phih, 120.0);

        addatom(1, 8, 5, 4, roh, phih,180.0);  

        xce=yce=zce=0.0;
        for(i=0;i<natoms;i++){
         xce+=xc[i];
         yce+=yc[i];
         zce+=zc[i];
    }
        xce=xce/natoms;
        yce=yce/natoms;
        zce=zce/natoms;
        
        for(i=0;i<natoms;i++){
        xc[i]=xc[i]-xce;
        yc[i]=yc[i]-yce;
        zc[i]=zc[i]-zce;
        }
        
        copycoo();

    }

    public void zmat() {

        jTextArea3.append("" + nat[0] + "\n");
        jTextArea3.append("" + nat[1] + " 0  " + getbondl(1, 0) + "\n");
        jTextArea3.append("" + nat[2] + "  1  0  " + getbondl(1, 2) + "  " + getphi(0, 1, 2) + "\n");

        listatom(3, 2, 1, 0);
        listatom(4, 3, 2, 1);
        listatom(5, 4, 3, 2);

        listatom(6, 2, 1, 0);


        listatom(7, 5, 4, 3);
        listatom(8, 5, 4, 3);


        listatom(9, 0, 1, 2);
        listatom(10, 0, 1, 2);
        
        listatom(11, 1, 2, 3);
        listatom(12, 1, 2, 3);
        listatom(13, 3, 2, 1);
        listatom(14, 4, 3, 2);
        listatom(15, 4, 3, 2);
        listatom(16, 8, 5, 4);




    }

    public void listatom(int n1, int n2, int n3, int n4) {
        jTextArea3.append("" + nat[n1] + "  " + n2 + " " + n3 + " " + n4 + " " + getbondl(n1, n2) + "  " + getphi(n1, n2, n3) + "  " + gettheta(n1, n2, n3, n4) + "\n");

    }

    public void add_ffbond(int i, int j, double r, double k) {
        ffbond[indexb][0] = r;
        ffbond[indexb][1] = k;
        ffbondats[indexb][0] = i;
        ffbondats[indexb][1] = j;

        indexb++;

    }

    public void add_ffang(int n1, int n2, int n3, double phi, double k) {
        double kdeg;

        kdeg = 180 / Math.PI;
        kdeg = kdeg * kdeg;


        ffang[indexa][0] = phi;
        ffang[indexa][1] = k / kdeg;
        ffangats[indexa][0] = n1;
        ffangats[indexa][1] = n2;
        ffangats[indexa][2] = n3;

        indexa++;

    }
     public void add_ffthet(int n1, int n2, int n3, int n4, double phi, double k) {
        double kdeg;

        kdeg = 180 / Math.PI;
        kdeg = kdeg * kdeg;


        ffthet[indexc][0] = phi;
        ffthet[indexc][1] = k / kdeg;
        ffthetats[indexc][0] = n1;
        ffthetats[indexc][1] = n2;
        ffthetats[indexc][2] = n3;
        ffthetats[indexc][3] = n4;
        indexc++;

    }
    
        public void set_ff() {


        int i;

        double rcn = 1.346;
        double rc1n=1.438;
        double rc1n2=1.452;
        
        double rc2c1 = 1.51;
        double rcc1=1.528;
        
        double rc2o2 = 1.211;
        double rco=1.229;
        double rc2o1=1.339;
        
        double rnh = 1.016;
        double rn2h3=1.020;
               
        double rc1h1 = 1.098;
        double ro1h2=0.974;

        double kcn = 1296.3;
        double kc1n=935.5;
        double kc1n2=887.7;
        
        double kc2c1 = 818.9;
        double kcc1=767.9;
        
        double kc2o2 = 2154.5;
        double kco=1945.7;
        double kc2o1=1162.1;
        
        double knh = 1132.4;
        double kn2h3=1104.5;
        
        double kc1h1 = 900.0;
        double ko1h2=1214.6;

        double phincc1 = 115;
        double kncc1 = 160.9;
        double phic1nc = 122.3;
        double kc1nc = 160.1;
        double phic1c2o1 = 111.5;
        double kc1c2o1 = 156.0;
        double phic1c2o2=124.4;
        double kc1c2o2=123.8;
        double phic1co=121.4;
        double kc1co=127.5;
        
        double phio2c2o1 = 124.1;
        double ko2c2o1 = 146.5;
        double phinco = 123.2;
        double knco = 132.7;
        double phicc1h1 = 110.1;
        double kcc1h1 = 74.6;
        double phic2c1h1=109.4;
        double kc2c1h1=69.6;
        
        
        double phicnh = 123.1;
        double kcnh = 72.0;
        double phic1nh=114.6;
        double kc1nh=68.3;
        double phic1n2h3=108.7;
        double kc1n2h3=71.7;
        
        
        double phih1c1h1 = 106.6;
        double kh1c1h1 = 48.3;

        double phih3n2h3=107.7;
        double kh3n2h3=45.2;
        
        double phicc1n=107.4;
        double kcc1n=145.4;
        double phicc1n2=109.0;
        double kcc1n2=139.8;
        double phic2c1n=108.6;
        double kc2c1n=129.0;
        
        double phic2o1h2=106.9;
        double kc2o1h2=72.0;
        
        double phinc1h1=111.1;
        double knc1h1=73.3;
        double phin2c1h1=112.6;
        double kn2c1h1=80.1;
        


        indexb = 0;

        add_ffbond(0, 1, rc1n2, kc1n2);
        add_ffbond(1, 2, rcc1, kcc1);
        add_ffbond(2, 3, rcn, kcn);
        add_ffbond(3, 4, rc1n, kc1n);
        add_ffbond(4, 5, rc2c1, kc2c1);
        add_ffbond(5, 7, rc2o2, kc2o2);
        add_ffbond(5, 8, rc2o1, kc2o1);
        add_ffbond(2, 6, rco, kco);
        add_ffbond(0, 9, rn2h3, kn2h3);
        add_ffbond(0, 10, rn2h3, kn2h3);
        //add_ffbond(0, 11, rnh, knh);
        add_ffbond(1, 11, rc1h1, kc1h1);
        add_ffbond(1, 12, rc1h1, kc1h1);
        add_ffbond(3, 13, rnh, knh);
        add_ffbond(4, 14, rc1h1, kc1h1);
        add_ffbond(4, 15, rc1h1, kc1h1);
        
        add_ffbond(8,16,ro1h2,ko1h2);

        nffbond = indexb;

        indexa = 0;
        add_ffang(0, 1, 2, phicc1n2, kcc1n2);   //
        add_ffang(1, 2, 3, phincc1, kncc1);    //
        add_ffang(2, 3, 4, phic1nc, kc1nc);   //
        add_ffang(3, 4, 5, phic2c1n, kc2c1n);   //
        add_ffang(4, 5, 7, phic1c2o2, kc1c2o2);  //
        add_ffang(4, 5, 8, phic1c2o1, kc1c2o1);  //
        add_ffang(7, 5, 8, phio2c2o1, ko2c2o1);    //
        add_ffang(1, 2, 6, phic1co, kc1co);        //
        add_ffang(3, 2, 6, phinco, knco);          //      
        add_ffang(9, 0, 1, phic1n2h3, kc1n2h3);     //
        add_ffang(10, 0, 1, phic1n2h3, kc1n2h3);   //
        
        
        add_ffang(9, 0, 10, phih3n2h3, kh3n2h3); //
        
        
        
        
        add_ffang(15, 4, 3, phinc1h1, knc1h1);  //
        add_ffang(14, 4, 3, phinc1h1, knc1h1);  //
        
        add_ffang(15, 4, 5, phic2c1h1, kc2c1h1); //
        add_ffang(14, 4, 5, phic2c1h1, kc2c1h1); //
        
        add_ffang(16, 8, 5, phic2o1h2, kc2o1h2); //
        
        add_ffang(13, 3, 2, phicnh, kcnh);  //
       
        
        
  
        add_ffang(12, 1, 0, phin2c1h1, kn2c1h1);//
        
       
        
        
        add_ffang(11, 1, 0, phin2c1h1, kn2c1h1);//
        
        add_ffang(11, 1, 2, phicc1h1, kcc1h1);  //
        add_ffang(12, 1, 2, phicc1h1, kcc1h1);  //
        
        add_ffang(12, 1, 11, phih1c1h1, kh1c1h1); //
        add_ffang(14, 4, 15, phih1c1h1, kh1c1h1); //
        
        add_ffang(4,3,13,phic1nh,kc1nh);  //
        
        nffang = indexa;
        
        
        
        indexc=0;
        
        
        add_ffthet(9,0,1,2,-67.6,1.0);
        add_ffthet(13,3,2,1,27.5,1.0);
        add_ffthet(16,8,5,4,-147.4,1.0);
        add_ffthet(3,2,1,0,160.74,1.0);
        add_ffthet(4,3,2,1,-152.3,1.0);
        add_ffthet(5,4,3,2,-153.1,1.0);
        add_ffthet(7,5,4,3,123.7,1.0);
        add_ffthet(8,5,4,3,-56.5,1.0);  
        add_ffthet(14,4,3,2,-32.5,1.0);
        add_ffthet(15,4,3,2,86.3,1.0);
    
        add_ffthet(6,2,1,0,-26.3,1.0);
        
        
         nffthet=indexc;


    }



    public void ic2cart() {
    }

    public void cart2ic() {
    }

    public double getbondl(int i, int j) {
        double dx, dy, dz, r;
        dx = xc[i] - xc[j];
        dy = yc[i] - yc[j];
        dz = zc[i] - zc[j];
        r = dx * dx + dy * dy + dz * dz;
        r = Math.sqrt(r);
        return r;



    }

    public double getphi(int i, int j, int k) {

        double x1, y1, z1, x2, y2, z2, b1, b2, cc;

        x1 = xc[i] - xc[j];
        y1 = yc[i] - yc[j];
        z1 = zc[i] - zc[j];

        x2 = xc[k] - xc[j];
        y2 = yc[k] - yc[j];
        z2 = zc[k] - zc[j];

        b1 = x1 * x1 + y1 * y1 + z1 * z1;
        b2 = x2 * x2 + y2 * y2 + z2 * z2;



        cc = (x1 * x2 + y1 * y2 + z1 * z2) / Math.sqrt(b1 * b2);
        
        if(cc>1.0)cc=1.0;
        if(cc<-1.0)cc=-1.0;
          
       // if(Math.abs(cc)>1.0)jTextArea2.append("getphi "+cc+"\n");
        cc = Math.acos(cc) * 180.0 / Math.PI;

        //jTextArea2.append(""+i+" "+j+" "+k+" "+cc+ "\n");



        return cc;
    }

    public double gettheta(int i, int j, int k, int l) {
        double x12, y12, z12, x23, y23, z23, x34, y34, z34;
        double b12, b23, b34, nx, ny, nz, mx, my, mz, sp, bn, bm,det;

        x12 = xc[i] - xc[j];
        y12 = yc[i] - yc[j];
        z12 = zc[i] - zc[j];

        x23 = xc[k] - xc[j];
        y23 = yc[k] - yc[j];
        z23 = zc[k] - zc[j];

        x34 = xc[k] - xc[l];
        y34 = yc[k] - yc[l];
        z34 = zc[k] - zc[l];

        b12 = x12 * x12 + y12 * y12 + z12 * z12;
        b12 = Math.sqrt(b12);
        b23 = x23 * x23 + y23 * y23 + z23 * z23;
        b23 = Math.sqrt(b23);
        b34 = x34 * x34 + y34 * y34 + z34 * z34;
        b34 = Math.sqrt(b34);

        x12 /= b12;
        y12 /= b12;
        z12 /= b12;
        x23 /= b23;
        y23 /= b23;
        z23 /= b23;
        x34 /= b34;
        y34 /= b34;
        z34 /= b34;

        nx = y12 * z23 - z12 * y23;
        ny = z12 * x23 - x12 * z23;
        nz = x12 * y23 - y12 * x23;

        mx = -y34 * z23 + z34 * y23;
        my = -z34 * x23 + x34 * z23;
        mz = -x34 * y23 + y34 * x23;

        bn = nx * nx + ny * ny + nz * nz;
        bm = mx * mx + my * my + mz * mz;


        sp = (nx * mx + ny * my + nz * mz) / Math.sqrt(bn * bm);
        
        
        if(sp>1.0)sp=1.0;
        if(sp<-1.0)sp=-1.0;
       // if(Math.abs(sp)>1.0)jTextArea2.append("gettheta "+sp+"\n");

        sp = Math.acos(sp) * 180.0 / Math.PI;
        
        det=x23*ny*mz+y23*nz*mx+z23*nx*my;
        det=det-x23*my*nz-y23*mz*nx-z23*mx*ny;
        
        sp=-sp*Math.signum(det);
        
        return sp;
    }
   
    
    public void mode_shift(double cp, int imode)
    { int i; double fm,e;
    
     for (i = 0; i < natoms; i++) {
                    fm=cp/Math.sqrt(amass[i]);
                    xc[i] = xc[i] + Hessian[i * 3][imode] * modf*fm;
                    yc[i] = yc[i] + Hessian[i * 3 + 1][imode] * modf*fm;
                    zc[i] = zc[i] + Hessian[i * 3 + 2][imode] * modf*fm;


                }
    }
    
    
    public double mode_energy(double cp, int imode)
    { int i; double fm,e;
    
     for (i = 0; i < natoms; i++) {
                    fm=cp/Math.sqrt(amass[i]);
                    xc[i] = xc[i] + Hessian[i * 3][imode] * modf*fm;
                    yc[i] = yc[i] + Hessian[i * 3 + 1][imode] * modf*fm;
                    zc[i] = zc[i] + Hessian[i * 3 + 2][imode] * modf*fm;


                }
     e=energy();
     for (i = 0; i < natoms; i++) {
                    fm=cp/Math.sqrt(amass[i]);
                    xc[i] = xc[i] - Hessian[i * 3][imode] * modf*fm;
                    yc[i] = yc[i] - Hessian[i * 3 + 1][imode] * modf*fm;
                    zc[i] = zc[i] - Hessian[i * 3 + 2][imode] * modf*fm;


                }
     return e;
    
    }
    
    
    public double line_energy( double xla) {
        double el;
        linestep(xla);
        el=energy();
        linestep(-xla);
   
        return el;
        
    }
    

    public double check_energy() {
        int i;
        double e1, e, k, b0, b;
        e = 0;


        for (i = 0; i < nffbond; i++) {
            b = getbondl(ffbondats[i][0], ffbondats[i][1]);
            b0 = ffbond[i][0];
            k = ffbond[i][1];

            e1 = (b - b0);
            e1 = e1 * e1 * k*0.5;

            //jTextArea2.append("bond " + i + " " + e1 + "\n");
            e += e1;


        }



        for (i = 0; i < nffang; i++) {
            b = getphi(ffangats[i][0], ffangats[i][1], ffangats[i][2]);
            b0 = ffang[i][0];
            k = ffang[i][1];

            e1 = (b - b0);
            e1 =  e1 * e1 * k;


            e += e1;



        //jTextArea2.append(" energy "+b+"  "+e1+" \n");
        }
        
        for(i=0;i<nffthet;i++){
        
          b = gettheta(ffthetats[i][0], ffthetats[i][1], ffthetats[i][2],ffthetats[i][3]);
            b0 = ffthet[i][0];
            k = ffthet[i][1];

            e1 = (b - b0);
            e1 =  k*(1.0-Math.cos(e1));


            e += e1;
            
            
        
        
        }
        return e;

        
    }
        public double energy() {
        int i;
        double e1, e, k, b0, b;
        e = 0;


        for (i = 0; i < nffbond; i++) {
            b = getbondl(ffbondats[i][0], ffbondats[i][1]);
            b0 = ffbond[i][0];
            k = ffbond[i][1];

            e1 = (b - b0);
            e1 = e1 * e1 * k*0.5;

            //jTextArea2.append("bond " + i + " " + e1 + "\n");
            e += e1;


        }



        for (i = 0; i < nffang; i++) {
            b = getphi(ffangats[i][0], ffangats[i][1], ffangats[i][2]);
            b0 = ffang[i][0];
            k = ffang[i][1];

            e1 = (b - b0);
            e1 =  e1 * e1 * k;


            e += e1;



        //jTextArea2.append(" energy "+b+"  "+e1+" \n");
        }
        
        if(dihedrals_on)
        {
        for(i=0;i<nffthet;i++){
        
          b = gettheta(ffthetats[i][0], ffthetats[i][1], ffthetats[i][2],ffthetats[i][3]);
            b0 = ffthet[i][0];
            k = ffthet[i][1];

            e1 = (b - b0);
            e1 =  k*(1.0-Math.cos(e1));


            e += e1;
            
            //jTextArea2.append(""+b+" "+b0+" "+k+" "+e1+"\n");
        
        
        }}
        

        return e;
    }
        
    public void gradients()
    {
    
    calc_grad();
    
    }

    public void ana_gradients() {
        int i, n1, n2, n3;
        double dx, dy, dz, b, b0, k, f, gx, gy, gz, dx2, dy2, dz2, b1, b2;
        double c, s, sp, gx2, gy2, gz2, f2, f0, e1, e2, dex, dey, dez;

        for (i = 0; i < natmax; i++) {
            gradx[i] = grady[i] = gradz[i] = 0;
        }


        for (i = 0; i < nffbond; i++) {
            n1 = ffbondats[i][0];
            n2 = ffbondats[i][1];
            b0 = ffbond[i][0];
            k = ffbond[i][1];

            dx = xc[n1] - xc[n2];
            dy = yc[n1] - yc[n2];
            dz = zc[n1] - zc[n2];

            b = getbondl(n1, n2);

            f = k * (1 - b0 / b);
            gx = f * dx;
            gy = f * dy;
            gz = f * dz;
            gradx[n1] += gx;
            grady[n1] += gy;
            gradz[n1] += gz;
            gradx[n2] -= gx;
            grady[n2] -= gy;
            gradz[n2] -= gz;





        }

        for (i = 0; i < nffang; i++) {
            n1 = ffangats[i][0];
            n2 = ffangats[i][1];
            n3 = ffangats[i][2];
            b0 = ffang[i][0];
            k = ffang[i][1];

            b = getphi(n1, n2, n3);

            dx = xc[n1] - xc[n2];
            dy = yc[n1] - yc[n2];
            dz = zc[n1] - zc[n2];
            dx2 = xc[n3] - xc[n2];
            dy2 = yc[n3] - yc[n2];
            dz2 = zc[n3] - zc[n2];

            b1 = Math.sqrt(dx * dx + dy * dy + dz * dz);
            b2 = Math.sqrt(dx2 * dx2 + dy2 * dy2 + dz2 * dz2);

            sp = dx * dx2 + dy * dy2 + dz * dz2;

            c = sp / (b1 * b2);
            s = Math.sqrt(1 - c * c);

            f = 1 / (b1 * b2);
            f2 = sp / (b1 * b1 * b1 * b2);

            gx = f * dx2 - f2 * dx;
            gy = f * dy2 - f2 * dy;
            gz = f * dz2 - f2 * dz;

            f2 = sp / (b2 * b2 * b2 * b1);

            gx2 = f * dx - f2 * dx2;
            gy2 = f * dy - f2 * dy2;
            gz2 = f * dz - f2 * dz2;

            f0 = -2*k * (b - b0) * (180.0 / Math.PI) / s;

            gradx[n1] += f0 * gx;
            grady[n1] += f0 * gy;
            gradz[n1] += f0 * gz;
            gradx[n3] += f0 * gx2;
            grady[n3] += f0 * gy2;
            gradz[n3] += f0 * gz2;

            gradx[n2] -= f0 * (gx + gx2);
            grady[n2] -= f0 * (gy + gy2);
            gradz[n2] -= f0 * (gz + gz2);

        /*
        if(n1==0){
        jTextArea2.append("gradphi " + n1 + " " + n2 + " " + n3 + "   " + (f0 * gx) + "   " + (f0 * gy) + "   " + (f0 * gz) + "\n");
        }
        if(n3==0){
        jTextArea2.append("gradphi " + n1 + " " + n2 + " " + n3 + "  " + (f0 * gx2) + " " + (f0 * gy2) + " " + (f0 * gz2) + "\n");
        }
        if(n2==0){

        jTextArea2.append("gradphi " + n1 + " " + n2 + " " + n3 + "  " + (-f0 * (gx+gx2)) + " " + (-f0 * (gy+gy2)) + " " + (-f0 * (gz+gz2)) + "\n");

        }
         */
        }
    /*
    n1=0;
    xc[n1] += 0.001;
    e1 = energy();
    xc[n1] -= 0.002;
    e2 = energy();
    dex = (e1 - e2) * 500.0;

    xc[n1] += 0.001;

    yc[n1] += 0.001;
    e1 = energy();
    yc[n1] -= 0.002;
    e2 = energy();
    dey = (e1 - e2) * 500.0;

    yc[n1] += 0.001;


    zc[n1] += 0.001;
    e1 = energy();
    zc[n1] -= 0.002;
    e2=energy();

    dez = (e1 - e2) * 500.0;


    zc[n1] += 0.001;
    jTextArea2.append("numerical " + dex + "  " + dey + "  " + dez + "\n");
    jTextArea2.append("analytical " + gradx[n1] + "  " + grady[n1] + "  " + gradz[n1] + "\n");

     */









    }
    
    
        public void prepare_minim()
        { int i ;
        
        h=energy();
//        calc_grad();
        gradients();
         for (i = 0; i < natoms; i++) {

                s0x[i] = sx[i] = -gradx[i];
                s0y[i] = sy[i] = -grady[i];
                s0z[i] = sz[i] = -gradz[i];
                
                
                grad0x[i]=gradx[i];
                grad0y[i]=grady[i];
                grad0z[i]=gradz[i];
                

            }
        
        gnorm = Math.sqrt(gradbet());
        gnorm0=gnorm;

        }
        
        
        public void steepest(boolean conjug) {
        int i, i200, ix, iy, ic, ixo, iyo, ah, aw,countl;
        double f0,f1,f2, xl, df0, df1, xl0, xl1, xo, yo,  gnorm2, beta;
        double xa,xb,xc,xd,fa,fb,fc,fd;
        int nmax=5;
       

      

        //prepare_minim();

        i200 = 1;
        while ((i200 < nmax-2) && (gnorm > 1.0E-14)) {
           

         
             for (i = 0; i < natoms; i++) {

                s0x[i] = sx[i] ;
                s0y[i] = sy[i] ;
                s0z[i] = sz[i] ;
             

            }

            //rosb(x, y);
            h=energy(); 
            
//            calc_grad();
           gradients();

          
            gnorm = Math.sqrt(gradbet());
            
            gnormd = gradbet2();
            if (conjug) {
                
                
                // Polak Ribiere Method 
                
                beta = gnormd / (gnorm0*gnorm0);
                


                //jTextArea2.append(" beta2=" + beta +" "+gnormd+"  "+gnorm0+"\n");
            for (i = 0; i < natoms; i++) {

                sx[i] =beta*s0x[i] -gradx[i];
                sy[i] =beta*s0y[i] -grady[i];
                sz[i] =beta*s0z[i] -gradz[i];

            }


            } else {
                
                
                 for (i = 0; i < natoms; i++) {

                sx[i] = -gradx[i];
                sy[i] = -grady[i];
                sz[i] = -gradz[i];

            }

            }

//     determine xlam
              gnorm2=gradbet();
           
         
            f0=h;
            
            {xl=(1.0E-15+1.0E-14*h)/gnorm2;}
            
            if(xl>0 && xl<1E-8) xl=1E-8;
              if(xl<0 && xl>-1E-8) xl=-1E-8;
            
            
            f1=line_energy(xl);
              //jTextArea2.append("*0* "+f0+"  "+f1+"  "+xl+"\n");
            f2=f1;
         
            if (f1 > f0) {  //step too large??
                    xa=xl;
                    countl = 0;
                    do {
                        
                        xl = 0.5 * xl;
                        f1 = line_energy(xl);
                       // jTextArea2.append("*1* "+countl+"  "+f1+"  "+xl+"\n");
                        countl++;
                    } while ((countl < 100) && (f1 > f0));
                    
                    if(f1>f0){
                      //  jTextArea2.append("*br* "+f1+"  "+xa+" "+xl+"\n");
                        break;
                    }
                    xb=xl;
                    if(xb<xa){
                    xb=xa;
                    xa=xl;
                    
                    } //jTextArea2.append("ts "+f0+"  "+f1+"  "+f2+"\n"  ); gnorm = Math.sqrt(gradbet());
                do {  //ternary search

                    xc = (2 * xa + xb) / 3.0;
                    xd = (xa + 2 * xb) / 3.0;
                    fc = line_energy(xc);
                    fd = line_energy(xd);
                    if (fc < fd) {
                        xb = xd;
                    } else {
                        xa = xc;
                    }

                } while ((Math.abs(xb - xa) > 1.0E-14)&& !(fc==fd));
                xl = (xa + xb) / 2.0;
            }
            else{
                f2 = f1;
                if (f1 < f0) {
                    countl = 0;
                    do {
                        f1 = f2;
                        xl = 2 * xl;
                        f2 = line_energy(xl);
                         //   jTextArea2.append("*2* "+countl+" "+f1+"  "+xl+"\n");
                        countl++;
                    } while ((countl < 100) && (f2 < f1));
                }

                if (xl < 0) {
                    xa = xl;
                    xb = xl*0.5;
                } else {
                    xa = xl*0.5;
                    xb = xl;
                }
              //  jTextArea2.append("ts "+f0+"  "+f1+"  "+f2+"\n"  );
                do {  //ternary search

                    xc = (2 * xa + xb) / 3.0;
                    xd = (xa + 2 * xb) / 3.0;
                    fc = line_energy(xc);
                    fd = line_energy(xd);
                    if (fc < fd) {
                        xb = xd;
                    } else {
                        xa = xc;
                    }

                } while ((Math.abs(xb - xa) > 1.0E-14)&& !(fc==fd));
                xl = (xa + xb) / 2.0;
            }
            
            
          
            linestep(xl);
                 
            for (i = 0; i < natoms; i++) {

                
                grad0x[i]=gradx[i];
                grad0y[i]=grady[i];
                grad0z[i]=gradz[i];
                

            }
              gnorm0 = gnorm;
              //jTextArea2.append(" grad norm was "+gnorm0+"\n");
         
            //rosb(x,y);
            h=energy();
            
 //           calc_grad();
            gradients();
            jLabel4.setText(" Energy:  "+energy());
            jLabel3.setText(" RMS grad: "+Math.sqrt(gradbet()));
            //jTextArea2.append(" "+i200+"  "+energy()+"  "+Math.sqrt(gradbet())+"\n");
      
            i200++;
            countsteps++;
                jLabel1.setText("steps " + countsteps);
        }

        ix = 0;
         //rosb(x,y);
         h=energy();
         gnorm = Math.sqrt(gradbet());
       

        lastgrad=gnorm;
        lasth=h;
        copycoo();

        
         

    }

    public void linestep(double step) {
        int i;
        for (i = 0; i < natoms; i++) {
            xc[i] += sx[i] * step;
            yc[i] += sy[i] * step;
            zc[i] += sz[i] * step;
        }
        linepos += step;
    }

    public void followgrad() {
        int i, ia, count;
        double stepsize0 = 1.0E-8;
        double stepsize;
        double step, left, right, fl, fr, fm;
        double en, en0, mg, de, deold;


        //();



        // look for a change of the gradients sign

        count = 0;
        stepsize = 1.0E-6;

        for (i = 0; i < natoms; i++) {

            sx[i] = -gradx[i];
            sy[i] = -grady[i];
            sz[i] = -gradz[i];

        }


        do {


            linestep(stepsize);

            fm = analytgrad();

            stepsize = stepsize * 2;

            count++;
            //jTextArea2.append("step=" + linepos + "  de= " + (en - en0) + "\n");

            if (fm > 0) {
               // jTextArea2.append("sign change " + count + "\n");
            }
        } while ((fm < 0) && (count < 20));

        right = linepos;
        left = linepos - stepsize * 0.5;

        fl = -1;
        fr = 1;

        linestep(-0.25 * stepsize);

        count = 0;
        do {
            fm = analytgrad() * 1.0E7;

            if (fm < 0) {
                step = 0.25 * (right - left);
                left = linepos;
                linestep(step);
            } else {
                step = -0.25 * (right - left);
                right = linepos;
                linestep(step);
            }
           // calc_grad();
            gradients();

           // jTextArea2.append("line search    " + (right - left) + "  energy= " + energy() + " max grad=" + maxgrad() + " " + analytgrad() + "\n");
            count++;

        } while ((count < 30) && (Math.abs(fm) > 0.00000001));
    }

    public void conjgrad() {
        int i, ia, count;
        double stepsize0 = 1.0E-8;
        double stepsize;
        double step, left, right, fl, fr, fm;
        double en, en0, mg, de, deold;
        ;

        double beta;




        // look for a change of the gradients sign

        count = 0;
        stepsize = 1.0E-6;




        if (isfirst) {
            gbetold = 0;
            isfirst = false;

           // calc_grad();
            gradients();
            gbetold = gbet = gradbet();

            for (i = 0; i < natoms; i++) {

                s0x[i] = sx[i] = -gradx[i];
                s0y[i] = sy[i] = -grady[i];
                s0z[i] = sz[i] = -gradz[i];

            }
        } else {



            beta = 0;
            for (i = 0; i < natoms; i++) {

                beta += (gradx[i] * (gradx[i] + s0x[i]) + grady[i] * (grady[i] + s0y[i]) + gradz[i] * (gradz[i] + s0z[i]));
            //beta += (gradx[i] * (s0x[i]) + grady[i] * (s0y[i]) + gradz[i] * (s0z[i]));

            }


            deold = beta;


            beta = beta / gbetold;


            for (i = 0; i < natoms; i++) {

                sx[i] = beta * sx[i] - gradx[i];
                sy[i] = beta * sy[i] - grady[i];
                sz[i] = beta * sz[i] - gradz[i];

            }
        }

        for (i = 0; i < natoms; i++) {
            s0x[i] = -gradx[i];
            s0y[i] = -grady[i];
            s0z[i] = -gradz[i];
        }


        gbetold = gbet;

        do {


            linestep(stepsize);

            fm = analytgrad();

            stepsize = stepsize * 2;

            count++;
            //jTextArea2.append("step=" + linepos + "  de= " + (en - en0) + "\n");

            if (fm > 0) {
               // jTextArea2.append("sign change " + count + "\n");
            }
        } while ((fm < 0) && (count < 20));

        right = linepos;
        left = linepos - stepsize * 0.5;

        fl = -1;
        fr = 1;

        linestep(-0.25 * stepsize);

        count = 0;
        do {
            fm = analytgrad() * 1.0E7;

            if (fm < 0) {
                step = 0.25 * (right - left);
                left = linepos;
                linestep(step);
            } else {
                step = -0.25 * (right - left);
                right = linepos;
                linestep(step);
            }


         //   calc_grad();
            gradients();
            gbet = gradbet();



           // jTextArea2.append("line search    " + (right - left) + "  energy= " + energy() + " max grad=" + maxgrad() + " " + analytgrad() + "\n");
            count++;

        } while ((count < 30) && (Math.abs(fm) > 0.00000001));
    }

    public double numgrad() {
        double e1, e2, ng, ag;
        double stepsize0 = 1.0E-8;

        linestep(-stepsize0);
        e1 = energy();
        linestep(2 * stepsize0);
        e2 = energy();

        ng = (e2 - e1);

        linestep(-stepsize0);

        ag = analytgrad() * 2.0 * stepsize0;
        jTextArea3.append(" " + ng + "  " + ag + "\n");

        return ng;

    }

    public double analytgrad() {
        int i;
        double s;
    //    calc_grad();
        gradients();

        s = 0;
        for (i = 0; i < natoms; i++) {
            s += gradx[i] * sx[i] + grady[i] * sy[i] + gradz[i] * sz[i];

        }

        return s;
    }

    public double gradbet() {
        int i;
        double s;
        s = 0;
        for (i = 0; i < natoms; i++) {
            s = s + gradx[i] * gradx[i] + grady[i] * grady[i] + gradz[i] * gradz[i];
        }

        return s;
    } 
    public double gradbet2() {
        int i;
        double s;
        s = 0;
        for (i = 0; i < natoms; i++) {
            s = s + gradx[i] * (gradx[i]-grad0x[i])
                  + grady[i] * (grady[i]-grad0y[i])
                  + gradz[i] * (gradz[i]-grad0z[i]);
        }

        return s;
    }

    public double maxgrad() {
        int i;
        double m;

        m = 0;
        for (i = 0; i < natoms; i++) {
            if (Math.abs(gradx[i]) > m) {
                m = Math.abs(gradx[i]);
            }
            if (Math.abs(grady[i]) > m) {
                m = Math.abs(grady[i]);
            }
            if (Math.abs(gradz[i]) > m) {
                m = Math.abs(gradz[i]);
            }

        }

        return m;
    }

    public double eshift(int n, int c, double dx) {
        double e;

        e = 0;

        switch (c) {
            case 0:
                 {
                    xc[n] += dx;
                    e = energy();
                    xc[n] -= dx;
                }
                break;
            case 1:
                 {
                    yc[n] += dx;
                    e = energy();
                    yc[n] -= dx;
                }
                break;
            case 2:
                 {
                    zc[n] += dx;
                    e =energy();
                    zc[n] -= dx;
                }
                break;

        }
        //jTextArea2.append(""+n+"  "+c+"  "+dx+"  "+e+"\n");

        return e;
    }

    public double eshift12(int n, int c, int n2, int c2, double dx,double dy) {
        double e;
        int sel = 0;

        e = 0;

        sel = c * 3 + c2;


        switch (sel) {
            case 0:  // x x
                 {
                    xc[n] += dx;
                    xc[n2] += dy;
                    e = energy();
                    xc[n] -= dx;
                    xc[n2] -= dy;
                }
                break;
            case 1: // x y
                 {
                    xc[n] += dx;
                    yc[n2] += dy;
                    e = energy();
                    xc[n] -= dx;
                    yc[n2] -= dy;
                }
                break;
            case 2: // x z
                 {
                    xc[n] += dx;
                    zc[n2] += dy;
                    e = energy();
                    xc[n] -= dx;
                    zc[n2] -= dy;
                }
                break;
            case 3:  // y x
                 {
                    yc[n] += dx;
                    xc[n2] += dy;
                    e = energy();
                    yc[n] -= dx;
                    xc[n2] -= dy;
                }
                break;
            case 4: // y y
                 {
                    yc[n] += dx;
                    yc[n2] += dy;
                    e = energy();
                    yc[n] -= dx;
                    yc[n2] -= dy;
                }
                break;
            case 5: // y z
                 {
                    yc[n] += dx;
                    zc[n2] += dy;
                    e = energy();
                    yc[n] -= dx;
                    zc[n2] -= dy;
                }
                break;

            case 6:  // z x
                 {
                    zc[n] += dx;
                    xc[n2] += dy;
                    e = energy();
                    zc[n] -= dx;
                    xc[n2] -= dy;
                }
                break;
            case 7: // z y
                 {
                    zc[n] += dx;
                    yc[n2] += dy;
                    e = energy();
                    zc[n] -= dx;
                    yc[n2] -= dy;
                }
                break;
            case 8: // z z
                 {
                    zc[n] += dx;
                    zc[n2] += dy;
                    e = energy();
                    zc[n] -= dx;
                    zc[n2] -= dy;
                }
                break;



        }

        return e;
    }

    public void calc_H() {
        int i, j, n1, n2, n3, ind1, ind2, c1, c2;
        double e1, e2, e3, e4, e0, de;
        double xstep = 0.000001;


        e0 = energy();

        for (i = 0; i < 3 * natoms; i++) {
            for (j = 0; j < 3 * natoms; j++) {
                Hessian[i][j] = 0;
            }
        }


        for (n1 = 0; n1 < natoms; n1++) {




            for (c1 = 0; c1 < 3; c1++) {
                for (c2 = 0; c2 < 3; c2++) {

                    ind1 = 3 * n1 + c1;
                    ind2 = 3 * n1 + c2;

                    if (ind1 == ind2) {


                        e1 = eshift(n1, c1, xstep);
                        e2 = eshift(n1, c1, -xstep);


                        de = (e1 - e0) + (e2 - e0);
                                    //jTextArea2.append(" "+(de/e0) +"\n");
                        
                        de = de / (xstep * xstep);

                    //jTextArea2.append(" " + n1 + " " + c1 + "  " + n1 + " " + c2 + "  " + de + "\n");
                    } else {
                        
                         e1 = eshift12(n1, c1, n1, c2, xstep,xstep);                        
                         e2 = eshift12(n1, c1, n1, c2, -xstep,-xstep); 
                         e3 = eshift12(n1, c1, n1, c2, xstep,-xstep);
                         e4 = eshift12(n1, c1, n1, c2, -xstep,xstep);
                         
                         de=e1+e2-e3-e4;
                         de=0.25*de/(xstep*xstep);
                        
                        /*

                        e1 = eshift12(n1, c1, n1, c2, xstep);
                        e2 = eshift(n1, c1, xstep);
                        e3 = eshift(n1, c2, xstep);

                        de = e1 + e0 - e2 - e3;
                        de = de / (xstep * xstep);
                        */
                    //jTextArea2.append(" " + n1 + " " + c1 + "  " + n1 + " " + c2 + "  " + de + "\n");

                    }
                    Hessian[ind1][ind2] = de;
                    
                    
                    
        

                }

            }
        }


        for (n1 = 0; n1 < natoms; n1++) {
            for (n2 = n1 + 1; n2 < natoms; n2++) {




                for (c1 = 0; c1 < 3; c1++) {
                    for (c2 = 0; c2 < 3; c2++) {

                        ind1 = 3 * n1 + c1;
                        ind2 = 3 * n2 + c2;
                        
                         
                         e1 = eshift12(n1, c1, n2, c2, xstep,xstep);                        
                         e2 = eshift12(n1, c1, n2, c2, -xstep,-xstep); 
                         e3 = eshift12(n1, c1, n2, c2, xstep,-xstep);
                         e4 = eshift12(n1, c1, n2, c2, -xstep,xstep);
                         
                         de=e1+e2-e3-e4;
                         de=0.25*de/(xstep*xstep);
                        
                       // e1 = eshift12(n1, c1, n2, c2, xstep);
                       // e2 = eshift(n1, c1, xstep);
                       // e3 = eshift(n2, c2, xstep);

                        //de = e1 + e0 - e2 - e3;
                        //de = de / (xstep * xstep);

                        /*if (Math.abs(de) > 0.01) {
                        jTextArea2.append(" " + n1 + " " + c1 + "  " + n2 + " " + c2 + "  " + de + "\n");
                        }*/

                        Hessian[ind1][ind2] = de;
                        Hessian[ind2][ind1] = de;

                    }

                }
            }
        }
    }
      public void calc_grad() {
        int i, j, n1, n2, n3, ind1, ind2, c1, c2;
        double e1, e2, e3, e4, e0, de;
        double xstep = 1E-6;


        e0 = energy();

        for (i = 0; i <  natoms; i++) {
          //  gradx[i]=0;
          //  grady[i]=0;
          //  gradz[i]=0;
        }


        for (n1 = 0; n1 < natoms; n1++) {




            for (c1 = 0; c1 < 3; c1++) {
                 {

                   
                 

                     {


                        e1 = eshift(n1, c1, xstep);
                        e2 = eshift(n1, c1, -xstep);


                        de = (e1 - e2) ;
                                    //jTextArea2.append(" "+(de/e0) +"\n");
                        
                        de = de / (xstep *2);

                   // if(c1==0)jTextArea2.append(" " + n1 + " " + c1 + "  " + de +" "+gradx[n1]+ "\n");
                   //       if(c1==1)jTextArea2.append(" " + n1 + " " + c1 + "  " + de +" "+grady[n1]+ "\n");
                   //             if(c1==2)jTextArea2.append(" " + n1 + " " + c1 + "  " + de +" "+gradz[n1]+ "\n");
                    } 
                    if(c1==0) gradx[n1]=de; 
                    if(c1==1) grady[n1]=de;
                    if(c1==2) gradz[n1]=de;
                    
                    
                    
        

                }

            }
        }


    }

    public void modes() {
        int i, j, c1, c2, ind1, ind2, ierr = 0;

      
        calc_H();
    
        for (i = 0; i < natoms; i++) {
            for (j = 0; j < natoms; j++) {
                for (c1 = 0; c1 < 3; c1++) {
                    for (c2 = 0; c2 < 3; c2++) {

                        ind1 = i * 3 + c1;
                        ind2 = j * 3 + c2;

                        Hessian[ind1][ind2] /= Math.sqrt(amass[i] * amass[j]);
                       //jTextArea2.append(" " + ind1 + "  " + ind2 + "  " + Hessian[ind1][ind2] + "\n");
                    // jTextArea2.append(" "+ind1+"  "+ind2+"  "+amass[i]+"  "+amass[j]+"\n");


                    }
                }
            }
        }

        i = 0;
        tred2(3 * natoms, Hessian, dvec, evec, zmat);

        i = 0;

        tql2(3 * natoms, dvec, evec, Hessian, ierr);

        for (i = 0; i < 3 * natoms; i++) {
            if(dvec[i]>0)
            jTextArea3.append("mode" + i + "    " + ierr + " " + (s2cm*Math.sqrt(fac*dvec[i]) ) + "\n");
            else
                 jTextArea3.append("mode" + i + " I  " + ierr + " " + (s2cm*Math.sqrt(-fac*dvec[i]) ) + "\n");



        }
        labelmode();
        modes_available=true;

    }
    private void labelmode()
    {
         if (dvec[plotmode] > 0) {
            jLabel2.setText("" + plotmode + " " + df.format(s2cm * Math.sqrt(fac * dvec[plotmode])));
        } else {
            jLabel2.setText("" + plotmode + " I " + df.format(s2cm * Math.sqrt(-fac * dvec[plotmode])));
        }
    }
    
      public void verlet() {
        int i;
        double xn, yn, zn;
        double tst2 = 1.0E-30 * 0.695 / 1.66E-27;



        gradients();

        for (i = 0; i < natoms; i++) {

            xn = 2 * xc[i] - xc0[i] - gradx[i] * tst2 / amass[i];
            yn = 2 * yc[i] - yc0[i] - grady[i] * tst2 / amass[i];
            zn = 2 * zc[i] - zc0[i] - gradz[i] * tst2 / amass[i];

            xc0[i] = xc[i];
            xc[i] = xn;

            yc0[i] = yc[i];
            yc[i] = yn;
            zc0[i] = zc[i];
            zc[i] = zn;
        }




    }

    public void copycoo() {
        int i;
        for (i = 0; i < natoms; i++) {
            xc0[i] = xc[i];
            yc0[i] = yc[i];
            zc0[i] = zc[i];


        }

    }

    public void stretch() {
        double x4, y4, z4, x15, y15, z15, dx, dy, dz;

        x4 = xc[0];
        y4 = yc[0];
        z4 = zc[0];
        x15 = xc[9];
        y15 = yc[9];
        z15 = zc[9];

        dx = (x15 - x4) * 0.5;
        dy = (y15 - y4) * 0.5;
        dz = (z15 - z4) * 0.5;

        xc[9] += dx;
        yc[9] += dy;
        zc[9] += dz;
        copycoo();




    }

    public void stretch2() {
        double x4, y4, z4, x15, y15, z15, dx, dy, dz;

        x4 = xc[2];
        y4 = yc[2];
        z4 = zc[2];
        x15 = xc[6];
        y15 = yc[6];
        z15 = zc[6];

        dx = (x15 - x4) * 0.3;
        dy = (y15 - y4) * 0.3;
        dz = (z15 - z4) * 0.3;

        xc[6] += dx;
        yc[6] += dy;
        zc[6] += dz;
        copycoo();




    }

    public void addnoise() {
        int i;
        for (i = 0; i < natoms; i++) {
            xc[i] += 0.2 * (Math.random() - 0.5);
            yc[i] += 0.2 * (Math.random() - 0.5);
            zc[i] += 0.2 * (Math.random() - 0.5);

        }
        copycoo();
    }
    

    /** This method is called from within the init() method to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jTextArea1 = new javax.swing.JTextArea();
        buttonGroup1 = new javax.swing.ButtonGroup();
        jPanel1 = new myPanel();
        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();
        jButton3 = new javax.swing.JButton();
        jButton4 = new javax.swing.JButton();
        jButton5 = new javax.swing.JButton();
        jToggleButton1 = new javax.swing.JToggleButton();
        jButton6 = new javax.swing.JButton();
        jButton7 = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();
        jSlider2 = new javax.swing.JSlider();
        jButton8 = new javax.swing.JButton();
        jButton9 = new javax.swing.JButton();
        jButton10 = new javax.swing.JButton();
        jButton11 = new javax.swing.JButton();
        jButton12 = new javax.swing.JButton();
        jButton13 = new javax.swing.JButton();
        jLabel5 = new javax.swing.JLabel();
        jScrollPane3 = new javax.swing.JScrollPane();
        jTextArea3 = new javax.swing.JTextArea();
        jLabel4 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel1 = new javax.swing.JLabel();

        jTextArea1.setColumns(20);
        jTextArea1.setRows(5);
        jScrollPane1.setViewportView(jTextArea1);

        jPanel1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jPanel1MouseClicked(evt);
            }
            public void mousePressed(java.awt.event.MouseEvent evt) {
                jPanel1MousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                jPanel1MouseReleased(evt);
            }
        });
        jPanel1.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                jPanel1MouseDragged(evt);
            }
        });

        jButton1.setText("SD");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jButton2.setText("print zmat");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });

        jButton3.setText("CG");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton3ActionPerformed(evt);
            }
        });

        jButton4.setText("Reset");
        jButton4.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton4ActionPerformed(evt);
            }
        });

        jButton5.setText("calc Hessian");
        jButton5.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton5ActionPerformed(evt);
            }
        });

        jToggleButton1.setSelected(true);
        jToggleButton1.setText("dihedrals on");
        jToggleButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jToggleButton1ActionPerformed(evt);
            }
        });

        jButton6.setText("dwn");
        jButton6.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton6ActionPerformed(evt);
            }
        });

        jButton7.setText("up");
        jButton7.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton7ActionPerformed(evt);
            }
        });

        jSlider2.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                jSlider2MouseDragged(evt);
            }
        });

        jButton8.setText("stretch");
        jButton8.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton8ActionPerformed(evt);
            }
        });

        jButton9.setText("animate modes");
        jButton9.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton9ActionPerformed(evt);
            }
        });

        jButton10.setText("Verlet");
        jButton10.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton10ActionPerformed(evt);
            }
        });

        jButton11.setText("STOP");
        jButton11.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton11ActionPerformed(evt);
            }
        });

        jButton12.setText("stretch");
        jButton12.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton12ActionPerformed(evt);
            }
        });

        jButton13.setText("rand");
        jButton13.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton13ActionPerformed(evt);
            }
        });

        jLabel5.setText("click to rotate");

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 305, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(jPanel1Layout.createSequentialGroup()
                                .addComponent(jButton7)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jButton6))
                            .addComponent(jButton9))
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(jPanel1Layout.createSequentialGroup()
                                .addGap(20, 20, 20)
                                .addComponent(jButton4)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jButton8)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jButton12))
                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jButton3)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jButton1)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jButton10)))))
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 37, Short.MAX_VALUE)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jButton2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jButton5, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jToggleButton1, javax.swing.GroupLayout.Alignment.TRAILING))
                        .addGap(6, 6, 6))
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jButton11)
                            .addComponent(jButton13, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jSlider2, javax.swing.GroupLayout.PREFERRED_SIZE, 131, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGap(206, 206, 206)
                        .addComponent(jLabel5)))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jButton2, jButton5, jToggleButton1});

        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addComponent(jLabel5)
                .addGap(317, 317, 317)
                .addComponent(jButton2)
                .addGap(18, 18, 18)
                .addComponent(jButton5)
                .addGap(18, 18, 18)
                .addComponent(jToggleButton1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSlider2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(8, 8, 8)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton7)
                    .addComponent(jButton6)
                    .addComponent(jButton4)
                    .addComponent(jButton8)
                    .addComponent(jButton12)
                    .addComponent(jButton13))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton9)
                    .addComponent(jButton3)
                    .addComponent(jButton1)
                    .addComponent(jButton10)
                    .addComponent(jButton11, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addGap(183, 183, 183))
        );

        jTextArea3.setColumns(20);
        jTextArea3.setRows(5);
        jScrollPane3.setViewportView(jTextArea3);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jLabel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 470, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(0, 0, Short.MAX_VALUE))
                    .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 358, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(19, 19, 19)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jScrollPane3)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 571, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jLabel1)))
                .addContainerGap(186, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        {
           
              animation_mode=3;
            animation=true;
            jButton1.setBackground(Color.red);
             jButton3.setBackground(Color.LIGHT_GRAY);
            jButton9.setBackground(Color.LIGHT_GRAY);
             jButton10.setBackground(Color.LIGHT_GRAY);
            
        }
    // TODO add your handling code here:
    }//GEN-LAST:event_jButton1ActionPerformed

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
        zmat();        // TODO add your handling code here:
    }//GEN-LAST:event_jButton2ActionPerformed

    private void jPanel1MouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jPanel1MouseDragged
       double c,s,a1,b1,a2,b2,a3,b3;
       int dx,dy;
       xfrom=xto;
       yfrom=yto;
       xto=evt.getX();
       yto=evt.getY();
       dx=xto-xfrom;
       dy=yto-yfrom;
       //jTextArea3.append(" m dragged by "+dx+" "+dy+"\n");
       //rotz=rotz+dx;
       //jSlider1.setValue((int)rotz);
       
       c=Math.cos(dx*Math.PI/180.0);
       s=Math.sin(dx*Math.PI/180.0);
       
       a1=c*xx+s*zx;
       b1=-s*xx+c*zx;

       a2=c*xz+s*zz;
       b2=-s*xz+c*zz;
       
       a3=c*xy+s*zy;
       b3=-s*xy+c*zy;
       
       xx=a1;
       xz=a2;
       zx=b1;
       zz=b2;
       xy=a3;
       zy=b3;
       
       c=Math.cos(dy*Math.PI/180.0);
       s=Math.sin(dy*Math.PI/180.0);
       
       a1=c*yy+s*zy;
       b1=-s*yy+c*zy;

       a2=c*yz+s*zz;
       b2=-s*yz+c*zz;
       
       a3=c*yx+s*zx;
       b3=-s*yx+c*zx;
       
       yy=a1;
       yz=a2;
       zy=b1;
       zz=b2;
       yx=a3;
       zx=b3;
      
       //jTextArea3.append("new matrix\n");
       //jTextArea3.append(" "+xx+" "+xy+" "+xz+"\n");
       //jTextArea3.append(" "+yx+" "+yy+" "+yz+"\n");
       //jTextArea3.append(" "+zx+" "+zy+" "+zz+"\n");     
       
       
        jPanel1.repaint();
       
        // TODO add your handling code here:
    }//GEN-LAST:event_jPanel1MouseDragged

    private void jPanel1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jPanel1MouseClicked
        int x,y;
       //x=evt.getX();
       //y=evt.getY();
       //jTextArea3.append(" m clicked "+x+" "+y+"\n");// TODO add your handling code here:
    }//GEN-LAST:event_jPanel1MouseClicked

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
         {
            animation_mode=2;
            animation=true;
            jButton1.setBackground(Color.LIGHT_GRAY);
             jButton3.setBackground(Color.red);
            jButton9.setBackground(Color.LIGHT_GRAY);
             jButton10.setBackground(Color.LIGHT_GRAY);
            
             // TODO add your handling code here:
    }//GEN-LAST:event_jButton3ActionPerformed
    }
    private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton4ActionPerformed
        if (!animation) {
            isfirst = true;
            countsteps = 0;
            set_ic();
            prepare_minim();
            jPanel1.repaint();
        }
    // TODO add your handling code here:
    }//GEN-LAST:event_jButton4ActionPerformed

    private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton5ActionPerformed
        if (!animation) {
            modes();
        }
    // TODO add your handling code here:
    }//GEN-LAST:event_jButton5ActionPerformed

    private void jToggleButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleButton1ActionPerformed
       dihedrals_on = jToggleButton1.isSelected();      // TODO add your handling code here:
    }//GEN-LAST:event_jToggleButton1ActionPerformed

    private void jButton7ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton7ActionPerformed
        if (plotmode < 3 * natoms - 1) {
            plotmode++;
            labelmode();
        }


       

    }//GEN-LAST:event_jButton7ActionPerformed

    private void jButton6ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton6ActionPerformed
        if (plotmode > 0) {
            plotmode--;
            labelmode();
        
       
        }



    }//GEN-LAST:event_jButton6ActionPerformed

    private void jSlider2MouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jSlider2MouseDragged
    modf=jSlider2.getValue()*0.01;
        // TODO add your handling code here:
    }//GEN-LAST:event_jSlider2MouseDragged

    private void jButton8ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton8ActionPerformed
    stretch();       // TODO add your handling code here:
    }//GEN-LAST:event_jButton8ActionPerformed

    private void jPanel1MouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jPanel1MouseReleased
        int x,y;
       x=evt.getX();
       y=evt.getY();
       //jTextArea3.append(" m released "+x+" "+y+"\n");
    }//GEN-LAST:event_jPanel1MouseReleased

    private void jPanel1MousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jPanel1MousePressed
        int x,y;
       xto=xfrom=evt.getX();
       yto=yfrom=evt.getY();
       //jTextArea3.append(" m pressed "+xto+" "+yto+"\n");// TODO add your handling code here:
    }//GEN-LAST:event_jPanel1MousePressed

    private void jButton9ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton9ActionPerformed
         animation_mode=0;
            animation=true;// TODO add your handling code here:
            jButton1.setBackground(Color.LIGHT_GRAY);
             jButton3.setBackground(Color.LIGHT_GRAY);
            jButton9.setBackground(Color.red);
             jButton10.setBackground(Color.LIGHT_GRAY);
    }//GEN-LAST:event_jButton9ActionPerformed

    private void jButton10ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton10ActionPerformed
             animation_mode=1;
            animation=true;// TODO add your handling code here:
            jButton1.setBackground(Color.LIGHT_GRAY);
             jButton3.setBackground(Color.LIGHT_GRAY);
            jButton10.setBackground(Color.red);
             jButton9.setBackground(Color.LIGHT_GRAY);// TODO add your handling code here:
    }//GEN-LAST:event_jButton10ActionPerformed

    private void jButton11ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton11ActionPerformed
     
        animation=false;
        // TODO add your handling code here:
            jButton1.setBackground(Color.LIGHT_GRAY);
             jButton3.setBackground(Color.LIGHT_GRAY);
            jButton9.setBackground(Color.LIGHT_GRAY);
             jButton10.setBackground(Color.LIGHT_GRAY);
        // TODO add your handling code here:
    }//GEN-LAST:event_jButton11ActionPerformed

    private void jButton12ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton12ActionPerformed
       stretch2(); // TODO add your handling code here:
    }//GEN-LAST:event_jButton12ActionPerformed

    private void jButton13ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton13ActionPerformed
        addnoise();// TODO add your handling code here:
    }//GEN-LAST:event_jButton13ActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton10;
    private javax.swing.JButton jButton11;
    private javax.swing.JButton jButton12;
    private javax.swing.JButton jButton13;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JButton jButton4;
    private javax.swing.JButton jButton5;
    private javax.swing.JButton jButton6;
    private javax.swing.JButton jButton7;
    private javax.swing.JButton jButton8;
    private javax.swing.JButton jButton9;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JSlider jSlider2;
    private javax.swing.JTextArea jTextArea1;
    private javax.swing.JTextArea jTextArea3;
    private javax.swing.JToggleButton jToggleButton1;
    // End of variables declaration//GEN-END:variables

    public class myPanel extends javax.swing.JPanel {

        int i, ia, ix1, ix2, iy1, iy2, n1, n2;
        double stepsize = 0.000001;
        double en, energy_0, mg, cz, sz;
        int ixor=230;
        int iyor=210;

        public void paintComponent(Graphics g) {

            super.paintComponent(g);

         //   energy_0 = energy();
  //        calc_grad();
//            gradients();
            mg = maxgrad();

            //jTextArea2.append(" energy " + energy_0 +" max grad="+mg +"\n");


            cz = Math.cos(rotz * Math.PI / 180);
            sz = Math.sin(rotz * Math.PI / 180);

            if(animation && (animation_mode==0))
            {
            for (i = 0; i < nbonds; i++) {
                n1 = bondats[i][0];
                n2 = bondats[i][1];
                ix1 = (int) (50 * (xx * xcc[n1] + xy*ycc[n1]+ xz * zcc[n1]));
                iy1 = (int) (50 * (yx * xcc[n1] + yy*ycc[n1]+ yz* zcc[n1]));
                ix2 = (int) (50 * (xx * xcc[n2] + xy*ycc[n2]+ xz * zcc[n2]));
                iy2 = (int) (50 * (yx * xcc[n2] + yy*ycc[n2]+ yz* zcc[n2]));
                g.drawLine(ix1 + ixor, iy1 + iyor, ix2 + ixor, iy2 + iyor);

            }

            for (i = 0; i < natoms; i++) {
                 ix1 = (int) (50 * (xx * xcc[i] + xy*ycc[i]+ xz * zcc[i]));
                iy1 = (int) (50 * (yx * xcc[i] + yy*ycc[i]+ yz* zcc[i]));
                if (nat[i] == 8) {
                    g.setColor(Color.red);
                }
                if (nat[i] == 7) {
                    g.setColor(Color.blue);
                }
                if (nat[i] == 6) {
                    g.setColor(Color.green);
                }
                if (nat[i] == 1) {
                    g.setColor(Color.black);
                }

                g.fillOval(ix1 + ixor-5, iy1 + iyor-5, 10, 10);
            }
            }

            else
                 {
            for (i = 0; i < nbonds; i++) {
                n1 = bondats[i][0];
                n2 = bondats[i][1];
                ix1 = (int) (50 * (xx * xc[n1] + xy*yc[n1]+ xz * zc[n1]));
                iy1 = (int) (50 * (yx * xc[n1] + yy*yc[n1]+ yz* zc[n1]));
                ix2 = (int) (50 * (xx * xc[n2] + xy*yc[n2]+ xz * zc[n2]));
                iy2 = (int) (50 * (yx * xc[n2] + yy*yc[n2]+ yz* zc[n2]));
                g.drawLine(ix1 + ixor, iy1 + iyor, ix2 + ixor, iy2 + iyor);

            }

            for (i = 0; i < natoms; i++) {
                
                ix1 = (int) (50 * (xx * xc[i] + xy*yc[i]+ xz * zc[i]));
                iy1 = (int) (50 * (yx * xc[i] + yy*yc[i]+ yz* zc[i]));
                if (nat[i] == 8) {
                    g.setColor(Color.red);
                }
                if (nat[i] == 7) {
                    g.setColor(Color.blue);
                }
                if (nat[i] == 6) {
                    g.setColor(Color.green);
                }
                if (nat[i] == 1) {
                    g.setColor(Color.black);
                }

                g.fillOval(ix1 + ixor-5, iy1 + iyor-5, 10, 10);
            }
            }


        




        }
    }

    public void tql2(int n, double d[], double e[], double a[][], int ierr) {
        int i, j, k, l, m, ii, l1, l2, nm, mml, count;
        /*
        c     this subroutine is a translation of the algol procedure tql2,
        c     num. math. 11, 293-306(1968) by bowdler, martin, reinsch, and
        c     wilkinson.
        c     handbook for auto. comp., vol.ii-linear algebra, 227-240(1971).
        c
        c     this subroutine finds the eigenvalues and eigenvectors
        c     of a symmetric tridiagonal matrix by the ql method.
        c     the eigenvectors of a full symmetric matrix can also
        c     be found if  tred2  has been used to reduce this
        c     full matrix to tridiagonal form.
        c
        c     on input
        c
        c
        c
        c        n is the order of the matrix.
        c
        c        d contains the diagonal elements of the input matrix.
        c
        c        e contains the subdiagonal elements of the input matrix
        c          in its last n-1 positions.  e(1) is arbitrary.
        c
        c        a contains the transformation matrix produced in the
        c          reduction by  tred2, if performed.  if the eigenvectors
        c          of the tridiagonal matrix are desired, a must contain
        c          the identity matrix.
        c
        c      on output
        c
        c        d contains the eigenvalues in ascending order.  if an
        c          error exit is made, the eigenvalues are correct but
        c          unordered for indices 1,2,...,ierr-1.
        c
        c        e has been destroyed.
        c
        c        a contains orthonormal eigenvectors of the symmetric
        c          tridiagonal (or full) matrix.  if an error exit is made,
        c          a contains the eigenvectors associated with the stored
        c          eigenvalues.
        c
        c        ierr is set to
        c          zero       for normal return,
        c          j          if the j-th eigenvalue has not been
        c                     determined after 30 iterations.
        c
        c     calls pythag for  sqrt(a*a + b*b) .
        c
        c     questions and comments should be directed to burton s. garbow,
        c     mathematics and computer science div, argonne national laboratory
        c
        c     this version dated august 1983.
        c
        c     ------------------------------------------------------------------
         */
        double c, c2, c3, dl1, el1, f, g, h, p, r, s, s2, tst1, tst2;
        boolean iterate;

        ierr = 0;
        if (n > 1) {

            for (i = 1; i < n; i++) {
                e[i - 1] = e[i];
            }

            f = 0.0;
            tst1 = 0.0;
            e[n - 1] = 0.0;

            for (l = 0; l < n; l++) {

                count = 0;
                h = Math.abs(d[l]) + Math.abs(e[l]);
                if (tst1 < h) {
                    tst1 = h;
                }




//.......... look for small sub-diagonal element ..........



                m = l;
                iterate = true;


                do {

                    tst2 = tst1 + Math.abs(e[m]);

                    if (tst2 == tst1) {
                        iterate = false;
                    }

                    if (m >= n - 1) {
                        iterate = false;
                    }
                    if (iterate && (m < n - 1)) {
                        m++;
                    }


                } while (iterate);



                if (m > l) {
                    count = 0;
                    iterate = true;
                    do {
                        count++;
                        //     .......... form shift ..........
                        g = d[l];
                        p = (d[l + 1] - g) / (2.0 * e[l]);
                        r = pythag(p, 1.0);

                        d[l] = e[l] / (p + Math.copySign(r, p));
                        d[l + 1] = e[l] * (p + Math.copySign(r, p));
                        dl1 = d[l + 1];
                        h = g - d[l];
                        for (i = l + 2; i < n; i++) {
                            d[i] -= h;
                        }
                        f = f + h;
                        //     .......... ql transformation ..........


                        p = d[m];
                        c = 1.0;
                        c2 = c;
                        c3 = c;
                        el1 = e[l + 1];
                        s = 0.0;
                        s2 = 0.0;

                        for (i = m - 1; i >= l; i--) {
                            c3 = c2;
                            c2 = c;
                            s2 = s;
                            g = c * e[i];
                            h = c * p;
                            r = pythag(p, e[i]);
                            e[i + 1] = s * r;
                            s = e[i] / r;
                            c = p / r;
                            p = c * d[i] - s * g;
                            d[i + 1] = h + s * (c * g + s * d[i]);

                            //.......... form vector ..........

                            for (k = 0; k < n; k++) {
                                h = a[k][i + 1];
                                a[k][i + 1] = s * a[k][i] + c * h;
                                a[k][i] = c * a[k][i] - s * h;
                            }
                        }

                        p = -s * s2 * c3 * el1 * e[l] / dl1;
                        e[l] = s * p;
                        d[l] = c * p;

                        tst2 = tst1 + Math.abs(e[l]);
                        if (tst2 <= tst1) {
                            iterate = false;
                        }
                        if (count >= 30) {
                            iterate = false;
                        }

                    } while (iterate);

                    if (count >= 30) {
                        ierr = l;
                        break;
                    }
                }


                d[l] = d[l] + f;
                e[l] = 0.0;
            }

            //    .......... order eigenvalues and eigenvectors ..........

            for (i = 0; i < n - 1; i++) {
                k = i;
                p = d[i];
                for (j = i + 1; j < n; j++) {
                    if (d[j] < p) {
                        k = j;
                        p = d[j];
                    }
                }

                if (k != i) {
                    d[k] = d[i];
                    d[i] = p;
                    for (j = 0; j < n; j++) {
                        p = a[j][i];
                        a[j][i] = a[j][k];
                        a[j][k] = p;
                    }
                }
            }
        }
    }

    private double pythag(double x, double y) {
        double r;
        r = Math.sqrt(x * x + y * y);
        return r;
    }

    public void tred2(int n, double a[][], double d[], double e[], double z[][]) {
        int i, j, k, l, jp1;
        double f, g, h, hh, scale;

        /*
        c     this subroutine is a translation of the algol procedure tred2,
        c     num. math. 11, 181-195(1968) by martin, reinsch, and wilkinson.
        c     handbook for auto. comp., vol.ii-linear algebra, 212-226(1971).
        c
        c     this subroutine reduces a real symmetric matrix to a
        c     symmetric tridiagonal matrix using and accumulating
        c     orthogonal similarity transformations.
        c
        c     on input
        c
        c        n is the order of the matrix.
        c
        c        a contains the real symmetric input matrix.
        c
        c     on output
        c
        c        d contains the diagonal elements of the tridiagonal matrix.
        c
        c        e contains the subdiagonal elements of the tridiagonal
        c          matrix in its last n-1 positions.  e[0] is set to zero.
        c
        c        z contains the orthogonal transformation matrix
        c          produced in the reduction.
         */
        for (i = 0; i < n; i++) {
            d[i] = a[n - 1][i];
        }

        if (n > 1) {
            for (i = n - 1; i > 0; i--) {
                h = 0.0;
                scale = 0.0;
//     .......... scale row (algol tol then not needed) ..........
                for (k = 0; k < i; k++) {
                    scale = scale + Math.abs(d[k]);
                }

                if (scale == 0.0) {
                    e[i] = d[i - 1];
                    for (j = 0; j < i; j++) {
                        d[j] = a[i - 1][j];
                        a[i][j] = 0.0;
                        a[j][i] = 0.0;
                    }
                } else {

                    for (k = 0; k < i; k++) {
                        d[k] = d[k] / scale;
                        h = h + d[k] * d[k];

                    }

                    f = d[i - 1];
                    g = Math.sqrt(h);
                    if (f > 0) {
                        g = -g;
                    }
                    e[i] = scale * g;
                    h = h - f * g;
                    d[i - 1] = f - g;

//     .......... form a*u ..........

                    for (j = 0; j < i; j++) {
                        e[j] = 0.0;
                    }


                    for (j = 0; j < i; j++) {
                        f = d[j];
                        a[j][i] = f;
                        g = e[j] + a[j][j] * f;


                        for (k = j + 1; k < i; k++) {
                            g = g + a[k][j] * d[k];
                            e[k] = e[k] + a[k][j] * f;

                        }




                        e[j] = g;
                    }


//     .......... form p ..........

                    f = 0.0;
                    for (j = 0; j < i; j++) {

                        e[j] = e[j] / h;
                        f = f + e[j] * d[j];

                    }
                    hh = f / (h + h);



//     .......... form q ..........



                    for (j = 0; j < i; j++) {
                        e[j] = e[j] - hh * d[j];
                    }



//     .......... form reduced a ..........



                    for (j = 0; j < i; j++) {
                        f = d[j];
                        g = e[j];
                        for (k = j; k < i; k++) {
                            a[k][j] = a[k][j] - f * e[k] - g * d[k];
                        }
                        d[j] = a[i - 1][j];
                        a[i][j] = 0.0;
                    }


                }
                d[i] = h;
            }

//.......... accumulation of transformation matrices ..........



            for (i = 0; i < n - 1; i++) {


                a[n - 1][i] = a[i][i];
                a[i][i] = 1.0;
                h = d[i + 1];
                if (h != 0.0) {
                    for (k = 0; k <= i; k++) {
                        d[k] = a[k][i + 1] / h;
                    }

                    for (j = 0; j <= i; j++) {
                        g = 0.0;
                        for (k = 0; k <= i; k++) {
                            g = g + a[k][i + 1] * a[k][j];
                        }

                        for (k = 0; k <= i; k++) {
                            a[k][j] = a[k][j] - g * d[k];
                        }
                    }

                }



                for (k = 0; k <= i; k++) {
                    a[k][i + 1] = 0.0;
                }

            }


        }


        for (i = 0; i < n; i++) {
            d[i] = a[n - 1][i];
            a[n - 1][i] = 0.0;
        }

        a[n - 1][n - 1] = 1.0;
        e[0] = 0.0;


    }
}
