import java.util.*;
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
import javax.swing.*;

public class HT_silindir
{
double x0,x1,x2;
int ix;

public HT_silindir()
{
ix=0;	
x1=0.0;
}

public  static double fx(double lambda,double Bi)
{return lambda*Mathd.J(1,lambda)/Mathd.J(0,lambda)-Bi;}

public  static double dfx(double x,double h,double Bi)
{ //Türev hesabı
  return (-fx((x+2.0*h),Bi)+8.0*fx((x+h),Bi)-8.0*fx((x-h),Bi)+fx((x-2.0*h),Bi))/(12.0*h);
}

public  double Cn(double lambda)
{
 double J1=Mathd.J(1,lambda);
 double J0=Mathd.J(0,lambda);	
 return 2.0/lambda*J1/(J0*J0+J1*J1);
}

public void genislet(double Bi)
{
	//kök olan bir bölge bulana kadar verilen sınırı genişletir
	x0=x1;
	x2=x1+0.00001;
	int NTRY=200;
	double a[]=new double[2];
	double FACTOR=1.01;
	int j;
	double f1,f2;
	if (x1 == x2) System.out.println("Giriş değerleri yanlış verildi");
	f1=fx(x1,Bi);
	f2=fx(x2,Bi);
	for (j=1;j<=NTRY;j++) {
		if (f1*f2 < 0.0) {ix++;break;}
		else 
		{f2=fx(x2 += FACTOR*(x2-x1),Bi);}
	}
}
//  x1 ve x2 nin yeni değerleri geldi


public double lambda(double Bi)
{
//lineer olmayan denklemin kökü : ikiyebölme-Newton Raphson metodu
genislet(Bi);         //kök sınırlarını saptar
double xacc=1.0e-10; //iterasyonlar arasındaki fark, bu rakamdan 
// küçük olduğunda çözüme ulaştığımızı kabul edeceğiz
double EPS=1.0e-10;
double h=0.0001; //türev step büyüklüğü
int MAXIT=100;  //Maksimum iterasyon sayısı
int j;
double dfr,dx,dxold,fr,fh,fl;
double temp,b,a,r;
fl=fx(x1,Bi);
fh=fx(x2,Bi);
//System.out.println("x1 ="+x1+"fl="+fl+"x2="+x2+"fh="+fh);
//Bölgemizde kök değeri varmı kontrol et
if ((fl > 0.0 && fh > 0.0) || (fl < 0.0 && fh < 0.0))
System.out.println("n = "+ix+"x1="+x0+"x2="+x2+"verilen sınırlar içinde kök değeri yok");
if (fl == 0.0) return x1;
if (fh == 0.0) return x2;
if (fl < 0.0)   { a=x1;b=x2;} 
else            { b=x1;a=x2;}
r=0.5*(x1+x2); //orta nokta değeri 
dxold=Math.abs(x2-x1); 
dx=dxold; 
fr=fx(r,Bi);   //fonksiyonun r noktasındaki değeri
dfr=dfx(r,h,Bi); //fonksiyonun türevinin r noktasındaki değeri
for (j=1;j<=MAXIT;j++) 
{ 
if ((((r-b)*dfr-fr)*((r-a)*dfr-fr) > 0.0) || (Math.abs(2.0*fr) > Math.abs(dxold*dfr))) 
    { //ikiye bölme 
	  dxold=dx;
      dx=0.5*(b-a);
      r=a+dx;
      if ( a == r && fr>EPS) {x1=r+0.001;return r;} //çözüm!!!!
    } 
else{ //Newton-Raphson
	  dxold=dx;
      dx=fr/dfr;
      temp=r;
      r -= dx;
      if ((temp == r) && fr<EPS) {x1=r+0.001;return r;}  //çözüm!!!!!
    }
if ((Math.abs(dx) < xacc)&& fr<EPS) {x1=r+0.001;return r;} //çözüm!!!!!
fr=fx(r,Bi);
dfr=dfx(r,h,Bi);
if (fr < 0.0) 
a=r;
else
b=r;
}
System.out.println("Maksimum iterasyon sayısı aşıldı");
return 0.0; //program buraya gelmemeli 
}

public  double teta(double Fo,double Bi,double x)
{double tt=0;double ln=0;
 for(int n=0;n<20;n++)
 {ln=lambda(Bi);
 double ffx=fx(ln,Bi);
 double cn;
  if(Math.abs(ffx)<1.0e-4)
  {
  cn=Cn(ln);
  System.out.println("ln ="+ln+"Cn = "+cn+"  ix="+ix+"  x1="+x0+"x2="+x2+"fx="+ffx);
  tt+=cn*Math.exp(-ln*ln*Fo)*Mathd.J(0,ln*x);
  }
 }
 return tt;	
}

     public static void main (String args[])  
     {  
       HT_silindir hts=new  HT_silindir();
       double Bi,Fo,x;
       Fo=Double.parseDouble(JOptionPane.showInputDialog(" Forier sayısı Fo : "));
       Bi=Double.parseDouble(JOptionPane.showInputDialog(" Biot sayısı   Bi : "));
       x=Double.parseDouble(JOptionPane.showInputDialog(" boyutsuz silindirik koordinat r* = r/r0 : "));
       JOptionPane.showMessageDialog(null," teta = "+hts.teta(Fo,Bi,x),
       "silindirde zamana bağlı ısı transferi  : ",JOptionPane.PLAIN_MESSAGE);
     } 
}