/*
 * finitelapplet.java
 *
 * Created on 24. März 2008, 10:01
 */

import java.awt.*;
import java.awt.event.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
import java.awt.Graphics2D;
import java.awt.geom.*;
import java.text.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.awt.Color;

/**
 *
 * @author  poj
 */
public class finitelapplet extends javax.swing.JApplet
        implements ActionListener {

    DecimalFormat df, df1;
    Timer timer;
    Thread calculatorThread;
    Graphics2D gb;
    BufferedImage image;
    int iy0, iy1, ix0, ix1;
    double tscale;
    int NMAX = 1800; /* max number of elements */

    int points_phi = 12;
    int points_theta = 12;
    int points = 12;
    double radius = 1.0;  /* size in Angstrom */

    double DK = 20.0;
    double damp = 1.0;
    double distance = 0;
    int loop, i, j, k, l, indx, nelements;
    double rfex, ss, c1, c2, phi, theta, rf, dx, dy, dz, d2, d3, ww, x, y, z, grid, f_value;
    double[] xi, yi, zi, qi, area, xn, ynn, zn, B;
    double[][] W;
    int[] xpoints, ypoints;
    boolean equal_area = false;
    boolean horizontal=true;

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

                public void run() {
                    initComponents();
                }
            });
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        init_variables();
        reset();


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

    }

    public void actionPerformed(ActionEvent e) {

        if ((loop > 1000)) {
            return;
        }

        iterate();
        //draw();
        timer.setInitialDelay(10);
        timer.setDelay(10);
        timer.restart();

    }

    /** 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.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        buttonGroup1 = new javax.swing.ButtonGroup();
        jPanel1 = new myPanel();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jSlider1 = new javax.swing.JSlider();
        jSlider2 = new javax.swing.JSlider();
        jLabel3 = new javax.swing.JLabel();
        jSlider3 = new javax.swing.JSlider();
        jLabel4 = new javax.swing.JLabel();
        jSlider4 = new javax.swing.JSlider();
        jLabel5 = new javax.swing.JLabel();
        jButton1 = new javax.swing.JButton();
        jToggleButton1 = new javax.swing.JToggleButton();
        jLabel6 = new javax.swing.JLabel();
        jRadioButton1 = new javax.swing.JRadioButton();
        jRadioButton2 = new javax.swing.JRadioButton();

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 385, Short.MAX_VALUE)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 488, Short.MAX_VALUE)
        );

        jLabel1.setText("jLabel1");

        jLabel2.setText("jLabel2");

        jSlider1.setMaximum(900);
        jSlider1.setMinimum(100);
        jSlider1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                jSlider1MouseReleased(evt);
            }
        });
        jSlider1.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                jSlider1MouseDragged(evt);
            }
        });

        jSlider2.setMajorTickSpacing(6);
        jSlider2.setMaximum(42);
        jSlider2.setMinimum(6);
        jSlider2.setPaintLabels(true);
        jSlider2.setPaintTicks(true);
        jSlider2.setSnapToTicks(true);
        jSlider2.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                jSlider2MouseReleased(evt);
            }
        });
        jSlider2.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                jSlider2MouseDragged(evt);
            }
        });

        jLabel3.setText("jLabel2");

        jSlider3.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                jSlider3MouseReleased(evt);
            }
        });
        jSlider3.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                jSlider3MouseDragged(evt);
            }
        });

        jLabel4.setText("jLabel2");

        jSlider4.setMaximum(90);
        jSlider4.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                jSlider4MouseReleased(evt);
            }
        });
        jSlider4.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                jSlider4MouseDragged(evt);
            }
        });

        jLabel5.setText("jLabel2");

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

        jToggleButton1.setText("equal area");
        jToggleButton1.setHideActionText(true);
        jToggleButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jToggleButton1ActionPerformed(evt);
            }
        });

        jLabel6.setText("jLabel1");

        buttonGroup1.add(jRadioButton1);
        jRadioButton1.setSelected(true);
        jRadioButton1.setText("horizontal");
        jRadioButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jRadioButton1ActionPerformed(evt);
            }
        });

        buttonGroup1.add(jRadioButton2);
        jRadioButton2.setText("vertical");
        jRadioButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jRadioButton2ActionPerformed(evt);
            }
        });

        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()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel2)
                    .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, 156, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jButton1)
                        .addGap(18, 18, 18)
                        .addComponent(jToggleButton1))
                    .addComponent(jLabel1)
                    .addComponent(jLabel6)
                    .addComponent(jLabel4)
                    .addComponent(jSlider3, javax.swing.GroupLayout.PREFERRED_SIZE, 156, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel3)
                    .addComponent(jSlider2, javax.swing.GroupLayout.PREFERRED_SIZE, 156, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel5)
                    .addComponent(jSlider4, javax.swing.GroupLayout.PREFERRED_SIZE, 156, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jRadioButton1)
                        .addGap(18, 18, 18)
                        .addComponent(jRadioButton2)))
                .addContainerGap(172, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(23, 23, 23)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLabel1)
                        .addGap(18, 18, 18)
                        .addComponent(jLabel6)
                        .addGap(33, 33, 33)
                        .addComponent(jLabel2)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jLabel4)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jSlider3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(jLabel3)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jSlider2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(26, 26, 26)
                        .addComponent(jLabel5)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jSlider4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jRadioButton1)
                            .addComponent(jRadioButton2))
                        .addGap(28, 28, 28)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jButton1)
                            .addComponent(jToggleButton1))))
                .addContainerGap(54, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents
    private void jSlider1MouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jSlider1MouseDragged

        jLabel2.setText("DK=" + df.format(Math.pow(jSlider1.getValue() * 0.01, 2)));
    // TODO add your handling code here:
    }//GEN-LAST:event_jSlider1MouseDragged

    private void jSlider1MouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jSlider1MouseReleased

        DK = Math.pow(jSlider1.getValue() * 0.01, 2);
        reset();
        loop = 0;
    // TODO add your handling code here:
    }//GEN-LAST:event_jSlider1MouseReleased

    private void jSlider2MouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jSlider2MouseReleased
        points = jSlider2.getValue();
        points_phi = points;
        points_theta = points;
        reset();
        loop = 0;// TODO add your handling code here:
    }//GEN-LAST:event_jSlider2MouseReleased

    private void jSlider2MouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jSlider2MouseDragged
        points = jSlider2.getValue();

    // TODO add your handling code here:
    }//GEN-LAST:event_jSlider2MouseDragged

    private void jSlider3MouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jSlider3MouseReleased

        double damp1;
        damp1 = jSlider3.getValue() * 0.01;
        jLabel4.setText("damping=" + df.format(damp1));
        
        damp=1-damp1;
        reset();
        loop = 0;
    // TODO add your handling code here:
    }//GEN-LAST:event_jSlider3MouseReleased

    private void jSlider3MouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jSlider3MouseDragged
        jLabel4.setText("damping=" + df.format(jSlider3.getValue() * 0.01));


    // TODO add your handling code here:
    }//GEN-LAST:event_jSlider3MouseDragged

    private void jSlider4MouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jSlider4MouseReleased

        distance = jSlider4.getValue() * 0.01;
        jLabel5.setText("distance=" + df.format(distance));
        reset();
        loop = 0;
    // TODO add your handling code here:
    }//GEN-LAST:event_jSlider4MouseReleased

    private void jSlider4MouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jSlider4MouseDragged
        distance = jSlider4.getValue() * 0.01;
        jLabel5.setText("distance=" + df.format(distance));
    // TODO add your handling code here:
    }//GEN-LAST:event_jSlider4MouseDragged

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        reset();
        loop = 0;// TODO add your handling code here:
    }//GEN-LAST:event_jButton1ActionPerformed

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

    private void jRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButton1ActionPerformed
       horizontal=jRadioButton1.isSelected(); 
       reset();
       loop=0;// TODO add your handling code here:
    }//GEN-LAST:event_jRadioButton1ActionPerformed

    private void jRadioButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButton2ActionPerformed
       horizontal=!(jRadioButton2.isSelected()); 
       reset();
       loop=0;
       // TODO add your handling code here:
    }//GEN-LAST:event_jRadioButton2ActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.JButton jButton1;
    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.JLabel jLabel6;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JRadioButton jRadioButton1;
    private javax.swing.JRadioButton jRadioButton2;
    private javax.swing.JSlider jSlider1;
    private javax.swing.JSlider jSlider2;
    private javax.swing.JSlider jSlider3;
    private javax.swing.JSlider jSlider4;
    private javax.swing.JToggleButton jToggleButton1;
    // End of variables declaration//GEN-END:variables
    void init_variables() {
        xi = new double[NMAX];
        yi = new double[NMAX];
        zi = new double[NMAX];
        qi = new double[NMAX];
        area = new double[NMAX];
        xn = new double[NMAX];
        ynn = new double[NMAX];
        zn = new double[NMAX];
        B = new double[NMAX];
        W = new double[NMAX][NMAX];

        xpoints = new int[4];
        ypoints = new int[4];

        image =
                new BufferedImage(550, 650, BufferedImage.TYPE_INT_RGB);
        gb = (Graphics2D) image.createGraphics();
        gb.setBackground(Color.white);
        gb.clearRect(0, 0, 550, 650);
        df = new DecimalFormat("#0.00");
        df1 = new DecimalFormat("#0.000000000000");
        jSlider1.setValue((int) (10 * DK));
        jLabel2.setText("DK=" + df.format(DK));
        jSlider2.setValue(points);
        jSlider3.setValue((int) (damp * 100));
        jLabel4.setText("damping=" + df.format(damp));
        jSlider4.setValue((int) (distance * 100));
        jLabel5.setText("distance=" + df.format(distance));
    }

    double exact_value(double s) {
        int i;
        double sum, sn, s2;

        sum = 1 / DK;
        sn = s * s / (radius * radius);
        s2 = sn;

        for (i = 1; i < 30; i++) {

            sum = sum + sn * (i + 1) / (i + (i + 1) * DK);
            sn = sn * s2;


        }

        sum = sum * (1 - DK) * 7.2;
        return sum;



    }

    void draw_elements() {
        int i, j, ic, index;
        double phi1, phi2, theta1, theta2, x1, x2, y1, y2, z1, z2,
                x3, y3, z3, x4, y4, z4;
        Graphics g = jPanel1.getGraphics();
        Graphics2D g2 = (Graphics2D) g;
        Color col;
        index = 0;
        for (i = 0; i < points_phi; i++) {
            for (j = 0; j < points_theta; j++) {
                phi1 = i * 2.0 * Math.PI / points_phi;
                theta1 = j * Math.PI / points_theta;

                phi2 = (i + 1) * 2.0 * Math.PI / points_phi;
                theta2 = (j + 1) * Math.PI / points_theta;

              
                if(horizontal)
                {
                x1 = Math.sin(theta1) * Math.cos(phi1);
                y1 = Math.sin(theta1) * Math.sin(phi1);
                z1 = Math.cos(theta1);


                x2 = Math.sin(theta1) * Math.cos(phi2);
                y2 = Math.sin(theta1) * Math.sin(phi2);
                z2 = Math.cos(theta1);


                x3 = Math.sin(theta2) * Math.cos(phi2);
                y3 = Math.sin(theta2) * Math.sin(phi2);
                z3 = Math.cos(theta2);


                x4 = Math.sin(theta2) * Math.cos(phi1);
                y4 = Math.sin(theta2) * Math.sin(phi1);
                z4 = Math.cos(theta2);
                }
                else
                {
                x1 = Math.sin(theta1) * Math.cos(phi1);
                z1 = Math.sin(theta1) * Math.sin(phi1);
                y1 = Math.cos(theta1);


                x2 = Math.sin(theta1) * Math.cos(phi2);
                z2 = Math.sin(theta1) * Math.sin(phi2);
                y2 = Math.cos(theta1);


                x3 = Math.sin(theta2) * Math.cos(phi2);
                z3 = Math.sin(theta2) * Math.sin(phi2);
                y3 = Math.cos(theta2);


                x4 = Math.sin(theta2) * Math.cos(phi1);
                z4 = Math.sin(theta2) * Math.sin(phi1);
                y4 = Math.cos(theta2);
                
                
                
                }

                if ((y1 + y2 + y3 + y4) < 0) {
                    xpoints[0] = (int) (100 * x1)+150;
                    ypoints[0] = (int) (100 * z1)+350;
                    xpoints[1] = (int) (100 * x2)+150;
                    ypoints[1] = (int) (100 * z2)+350;
                    xpoints[2] = (int) (100 * x3)+150;
                    ypoints[2] = (int) (100 * z3)+350;
                    xpoints[3] = (int) (100 * x4)+150;
                    ypoints[3] = (int) (100 * z4)+350;

                    if (qi[index] < 0) {
                        ic = (int) (-qi[index] * 250);
                        if (ic > 255) {
                            ic = 255;
                        }
                        col = new Color(ic, 255 - ic, 255 - ic);
                    } else {
                        ic = (int) (qi[index] * 500);
                        if (ic > 255) {
                            ic = 255;
                        }
                        col = new Color(255 - ic, 255 - ic, ic);
                    }
                    gb.setColor(col);
                    gb.fillPolygon(xpoints, ypoints, 4);
                    gb.setColor(Color.black);
                    gb.drawPolygon(xpoints, ypoints, 4);
                }

                index++;
            }
        }



    }

    void draw_equal_elements() {
        int i, j, ic, index;
        double phi1, phi2, theta1, theta2, x1, x2, y1, y2, z1, z2,
                x3, y3, z3, x4, y4, z4, c1, c2, s1, s2;
        Graphics g = jPanel1.getGraphics();
        Graphics2D g2 = (Graphics2D) g;
        Color col;
        index = 0;
        for (i = 0; i < points_phi; i++) {
            for (j = 0; j < points_theta; j++) {
                phi1 = i * 2.0 * Math.PI / points_phi;
                c1 = 1.0 - j * 2.0 / points_theta;
                s1 = Math.sqrt(1 - c1 * c1);


                phi2 = (i + 1) * 2.0 * Math.PI / points_phi;
                c2 = 1.0 - (j + 1) * 2.0 / points_theta;
                s2 = Math.sqrt(1 - c2 * c2);

                if(horizontal)
                {
                x1 = s1 * Math.cos(phi1);
                y1 = s1 * Math.sin(phi1);
                z1 = c1;

                x2 = s1 * Math.cos(phi2);
                y2 = s1 * Math.sin(phi2);
                z2 = c1;

                x3 = s2 * Math.cos(phi2);
                y3 = s2 * Math.sin(phi2);
                z3 = c2;

                x4 = s2 * Math.cos(phi1);
                y4 = s2 * Math.sin(phi1);
                z4 = c2;
                }
                else{
                x1 = s1 * Math.cos(phi1);
                z1 = s1 * Math.sin(phi1);
                y1 = c1;

                x2 = s1 * Math.cos(phi2);
                z2 = s1 * Math.sin(phi2);
                y2 = c1;

                x3 = s2 * Math.cos(phi2);
                z3 = s2 * Math.sin(phi2);
                y3 = c2;

                x4 = s2 * Math.cos(phi1);
                z4 = s2 * Math.sin(phi1);
                y4 = c2;
                
                }
                

                if ((y1 + y2 + y3 + y4) < 0) {
                    xpoints[0] = (int) (100 * x1)+150;
                    ypoints[0] = (int) (100 * z1)+350;
                    xpoints[1] = (int) (100 * x2)+150;
                    ypoints[1] = (int) (100 * z2)+350;
                    xpoints[2] = (int) (100 * x3)+150;
                    ypoints[2] = (int) (100 * z3)+350;
                    xpoints[3] = (int) (100 * x4)+150;
                    ypoints[3] = (int) (100 * z4)+350;

                    if (qi[index] < 0) {
                        ic = (int) (-qi[index] * 250);
                        if (ic > 255) {
                            ic = 255;
                        }
                        col = new Color(ic, 255 - ic, 255 - ic);
                    } else {
                        ic = (int) (qi[index] * 500);
                        if (ic > 255) {
                            ic = 255;
                        }
                        col = new Color(255 - ic, 255 - ic, ic);
                    }
                    gb.setColor(col);
                    gb.fillPolygon(xpoints, ypoints, 4);
                    gb.setColor(Color.black);
                    gb.drawPolygon(xpoints, ypoints, 4);
                }

                index++;
            }
        }



    }

    void generate_elements() {

        indx = 0;
        rfex = -14.4 * (1.0 - 1.0 / DK) / radius;


        f_value = 2.0 * (1 - DK) / (1 + DK);
        f_value = f_value / (4.0 * Math.PI);

        ss = 0.0;



        for (i = 0; i < points_phi; i++) {
            for (j = 0; j < points_theta; j++) {
                phi = (i + 0.5) * 2.0 * Math.PI / points_phi;
                theta = (j + 0.5) * Math.PI / points_theta;

                xi[indx] = Math.sin(theta) * Math.cos(phi);
                yi[indx] = Math.sin(theta) * Math.sin(phi);
                zi[indx] = Math.cos(theta);

                xn[indx] = xi[indx];
                ynn[indx] = yi[indx];
                zn[indx] = zi[indx];

                xi[indx] = xi[indx] * radius;
                yi[indx] = yi[indx] * radius;
                zi[indx] = zi[indx] * radius;


                c1 = Math.cos(j * Math.PI / points_theta);
                c2 = Math.cos((j + 1) * Math.PI / points_theta);

                area[indx] = radius * radius * (c1 - c2) * 2.0 * Math.PI / points_phi;

                ss = ss + area[indx];


                indx++;
            }
        }




        nelements = indx;
        jLabel3.setText("elements=" + nelements);

    }

    void generate_equal_elements() {
        double c;

        indx = 0;
        rfex = -14.4 * (1.0 - 1.0 / DK) / radius;


        f_value = 2.0 * (1 - DK) / (1 + DK);
        f_value = f_value / (4.0 * Math.PI);

        ss = 0.0;



        for (i = 0; i < points_phi; i++) {
            for (j = 0; j < points_theta; j++) {
                phi = (i + 0.5) * 2.0 * Math.PI / points_phi;
                c = 1.0 - (j + 0.5) * 2.0 / points_theta;

                theta = (j + 0.5) * Math.PI / points_theta;

                xi[indx] = Math.sqrt(1 - c * c) * Math.cos(phi);
                yi[indx] = Math.sqrt(1 - c * c) * Math.sin(phi);
                zi[indx] = c;

                xn[indx] = xi[indx];
                ynn[indx] = yi[indx];
                zn[indx] = zi[indx];

                xi[indx] = xi[indx] * radius;
                yi[indx] = yi[indx] * radius;
                zi[indx] = zi[indx] * radius;


                c1 = 1 - (j * 2.0) / points_theta;
                c2 = 1 - (j + 1) * 2.0 / points_theta;

                area[indx] = radius * radius * (c1 - c2) * 2.0 * Math.PI / points_phi;

                ss = ss + area[indx];


                indx++;
            }
        }




        nelements = indx;
        jLabel3.setText("elements=" + nelements);

    }

    void reset() {
        int i;
        if (equal_area) {
            generate_equal_elements();
        } else {
            generate_elements();
        }

        loop = 0;
        for (i = 0; i < NMAX; i++) {
            qi[i] = 0;
        }
    }

    void iterate() { //calculate interactions
        Graphics g = jPanel1.getGraphics();
        Graphics2D g2 = (Graphics2D) g;
        double rf0;
        int index, ix, iy, iy0;

        if (loop == 0) {
            gb.setBackground(Color.white);
            gb.clearRect(0, 0, 550, 650);
            for (i = 0; i < nelements; i++) {
                dx = xi[i];
                dy = yi[i];
                dz = zi[i];
                
                if(horizontal) dy=dy+distance;
                else dz=dz+distance;

                d2 = dx * dx + dy * dy + dz * dz;
                d3 = Math.sqrt(d2) * d2;
                ww = xn[i] * dx + ynn[i] * dy + zn[i] * dz;
                B[i] = f_value * ww / d3;
            }
        }
        if (loop < 100) {
            for (i = 0; i < nelements; i++) {
                for (j = 0; j < nelements; j++) {
                    if (i == j) {
                        W[i][j] = 1.0;
                    } else {
                        dx = xi[i] - xi[j];
                        dy = yi[i] - yi[j];
                        dz = zi[i] - zi[j];

                        d2 = dx * dx + dy * dy + dz * dz;
                        d3 = Math.sqrt(d2) * d2;

                        ww = xn[i] * dx + ynn[i] * dy + zn[i] * dz;
                        W[i][j] = f_value * ww * area[j] * qi[j] / d3;



                    }
                }




            }


            for (i = 0; i < nelements; i++) {
                qi[i] = (1.0 - damp) * qi[i] + damp * B[i];
                for (j = 0; j < nelements; j++) {
                    if (i != j) {
                        qi[i] = qi[i] + damp * W[i][j];
                    }
                }
            }





            rf0 = rf;
            rf = 0.0;

            for (i = 0; i < nelements; i++) {
                
                if(horizontal)
                d2 = xi[i] * xi[i] + (yi[i] + distance) * (yi[i] + distance) + zi[i] * zi[i];
                else
                d2 = xi[i] * xi[i] + (zi[i] + distance) * (zi[i] + distance) + yi[i] * yi[i];
                
                rf = rf + qi[i] * area[i] / Math.sqrt(d2);
            }

            //printf(" %e  %e \n", rf * 14.4, rf * 14.4 - rfex);
            gb.setColor(Color.black);
            if (equal_area) {
                draw_equal_elements();
            } else {
                draw_elements();
            }

            gb.setColor(Color.red);
            if (loop > 0) {
                gb.drawLine(2 * (loop - 1), 50 - (int) (5 * 7.2 * rf0),
                        2 * loop, 50 - (int) (5 * 7.2 * rf));

          

            }


            gb.setColor(Color.blue);
            gb.drawLine(0, 50 - (int) (5 * exact_value(distance)), 300,
                    50 - (int) (5 * exact_value(distance)));
            gb.setColor(Color.black);
            gb.drawLine(0, 50 + (int) (5 * 5), 300, 50 + (int) (5 * 5));
            gb.drawLine(0, 50 + (int) (5 * 10), 300, 50 + (int) (5 * 10));
            gb.drawLine(0, 50 + (int) (5 * 15), 300, 50 + (int) (5 * 15));
            gb.drawLine(0, 50 + (int) (5 * 20), 300, 50 + (int) (5 * 20));
            gb.drawLine(0, 50 + (int) (5 * 25), 300, 50 + (int) (5 * 25));
            gb.drawLine(0, 50 + (int) (5 * 30), 300, 50 + (int) (5 * 30));
            gb.drawLine(0, 50 + (int) (5 * 35), 300, 50 + (int) (5 * 35));
            gb.drawString("-5eV", 310, 50 + 25);
            gb.drawString("-10eV", 310, 50 + 50);
            gb.drawString("-15eV", 310, 50 + 75);
            gb.drawString("-20eV", 310, 50 + 100);
            gb.drawString("-25eV", 310, 50 + 125);
            gb.drawString("-30eV", 310, 50 + 150);
            gb.drawString("-35eV", 310, 50 + 175);

            jLabel1.setText("red:solvation energy=" + df1.format(7.2 * rf) + " eV ");
            jLabel6.setText("blue:analytical value=" + df1.format(exact_value(distance))+" eV");



            g2.drawImage(image, 0, 0, null);
            loop++;



        }





    /*for(i=0;i<nelements;i++) printf(" %i  %e  %e \n",i,qi[i],area[i]);
     */
    }

    public class myPanel extends javax.swing.JPanel {

        public void paint(Graphics g) {
            int ix, iy, ir, ix5, ix10, ix15, ix20, ix25, k, i, j;
            double xp, yp;
            Graphics2D g2 = (Graphics2D) g;
            int size = 200;

            //if(count==0) {super.paintComponent(g);

            //}

            super.paintComponent(g);


            g2.drawImage(image, 0, 0, null);



        }
    }
}
