Anterior

Procedimiento numérico

Código del procedimiento numérico que calcula los niveles de energía, y proporciona los coeficientes de las funciones de onda en cada intervalo normalizados.

public class Complejo extends Object{
     double real;
     double imag;
     static final Complejo i=new Complejo(0.0, 1.0);

  public Complejo() {
     real=0.0;
     imag=0.0;
  }
  public Complejo(double real, double imag){
     this.real=real;
     this.imag=imag;
  }
  public Complejo opuesto(){
     return new Complejo(-real, -imag);
  }
  public Complejo conjugado(){
     return new Complejo(real, -imag);
  }
  public double modulo(){
     return (real*real+imag*imag);
  }
  public double argumento(){
     if(real==0.0 && imag==0.0){
          return 0.0;
     }else{
          return Math.atan(imag/real);
     }
  }
   public static Complejo suma(Complejo c1, Complejo c2){
     double x=c1.real+c2.real;
     double y=c1.imag+c2.imag;
     return new Complejo(x, y);
  }
   public static Complejo diferencia(Complejo c1, Complejo c2){
     double x=c1.real-c2.real;
     double y=c1.imag-c2.imag;
     return new Complejo(x, y);
  }

 public static Complejo producto(Complejo c1, Complejo c2){
     double x=c1.real*c2.real-c1.imag*c2.imag;
     double y=c1.real*c2.imag+c1.imag*c2.real;
     return new Complejo(x, y);
  }
  public static Complejo cociente(Complejo c1, Complejo c2){
     double aux=c2.real*c2.real+c2.imag*c2.imag;
     double x=(c1.real*c2.real+c1.imag*c2.imag)/aux;
     double y=(c1.imag*c2.real-c1.real*c2.imag)/aux;
     return new Complejo(x, y);
  }
  public static Complejo cociente(Complejo c, double d){
     double x=c.real/d;
     double y=c.imag/d;
     return new Complejo(x, y);
  }
  public static Complejo producto(Complejo c, double d){
     double x=c.real*d;
     double y=c.imag*d;
     return new Complejo(x, y);
 }
  public static Complejo exponencial(Complejo c){
     double x=Math.cos(c.imag)*Math.exp(c.real);
     double y=Math.sin(c.imag)*Math.exp(c.real);
     return new Complejo(x, y);
  }
  public static Complejo csqrt(double d){
     if(d>=0) return new Complejo(Math.sqrt(d), 0);
     return new Complejo(0, Math.sqrt(-d));
  }

  public String imprime(){
     return new String(real+" "+imag+"*i\n");
  }

  }

public class CAux4x4 {
     Complejo s[][]=new Complejo[2][4];

  public CAux4x4() {
     for(int i=0; i<2; i++){
          for(int j=0; j<4; j++){
               s[i][j]=new Complejo();
          }
     }
  }
  void auxiliar(Complejo q0, Complejo q1, double x){
     s[0][0]=Complejo.exponencial
(Complejo.producto(Complejo.producto(Complejo.i, q0), x));
     s[0][1]=Complejo.exponencial
(Complejo.producto(Complejo.producto(Complejo.i, q0), -x)); s[0][2]=Complejo.exponencial
(Complejo.producto(Complejo.producto(Complejo.i, q1), x)).opuesto(); s[0][3]=Complejo.exponencial
(Complejo.producto(Complejo.producto(Complejo.i, q1), -x)).opuesto(); s[1][0]=Complejo.producto(q0, s[0][0]); s[1][1]=Complejo.producto(q0, s[0][1]).opuesto(); s[1][2]=Complejo.producto(q1, s[0][2]); s[1][3]=Complejo.producto(q1, s[0][3]).opuesto(); } } public class CMatriz2x2 { Complejo a11; Complejo a12; Complejo a21; Complejo a22; public CMatriz2x2() { a11=new Complejo(); a12=new Complejo(); a21=new Complejo(); a22=new Complejo(); } public CMatriz2x2(Complejo a11, Complejo a12, Complejo a21, Complejo a22){ this.a11=a11; this.a12=a12; this.a21=a21; this.a22=a22; } public static CMatriz2x2 producto(CMatriz2x2 m1, CMatriz2x2 m2){ CMatriz2x2 temp=new CMatriz2x2(); temp.a11=Complejo.suma(Complejo.producto(m1.a11, m2.a11),
Complejo.producto(m1.a12,m2.a21)); temp.a12=Complejo.suma(Complejo.producto(m1.a11, m2.a12),
Complejo.producto(m1.a12,m2.a22)); temp.a21=Complejo.suma(Complejo.producto(m1.a21, m2.a11),
Complejo.producto(m1.a22,m2.a21)); temp.a22=Complejo.suma(Complejo.producto(m1.a21, m2.a12),
Complejo.producto(m1.a22,m2.a22)); return temp; } public static CVector2 producto(CMatriz2x2 m, CVector2 v){ CVector2 temp=new CVector2(); temp.a=Complejo.suma(Complejo.producto(m.a11, v.a),
Complejo.producto(m.a12,v.b)); temp.b=Complejo.suma(Complejo.producto(m.a21, v.a),
Complejo.producto(m.a22,v.b)); return temp; } public void matriz(Complejo k, double x){ a11=Complejo.exponencial
(Complejo.producto(Complejo.producto(Complejo.i, k), x)); a12=Complejo.exponencial
(Complejo.producto(Complejo.producto(Complejo.i, k), -x)); a21=Complejo.producto(k, a11); a22=Complejo.producto(k.opuesto(), a12); } public void inversa(Complejo k, double x){ a11=Complejo.cociente(Complejo.exponencial(Complejo.producto
(Complejo.producto(Complejo.i, k), -x)), 2); a21=Complejo.cociente(Complejo.exponencial(Complejo.producto
(Complejo.producto(Complejo.i, k), x)), 2); a12=Complejo.cociente(a11, k); a22=Complejo.cociente(a21, k.opuesto()); } } public class CVector2 { Complejo a; Complejo b; public CVector2(Complejo a, Complejo b) { this.a=a; this.b=b; } public CVector2(){ a=new Complejo(); b=new Complejo(); } public static CVector2 cociente(CVector2 v, double d){ return new CVector2(Complejo.cociente(v.a, d),
Complejo.cociente(v.b, d)); } } public class Matriz { int filas; int columnas; Complejo a[][]; public Matriz(int filas, int columnas) { this.filas=filas; this.columnas=columnas; a=new Complejo[filas][columnas]; for(int i=0; i<filas; i++){ for(int j=0; j<columnas; j++){ a[i][j]=new Complejo(); } } } Complejo determinante(){ Complejo det=new Complejo(1.0, 0); for(int k=0; k<filas-1; k++){ for(int i=k+1; i<filas; i++){ for(int j=k+1; j<filas; j++){ a[i][j]=Complejo.diferencia(a[i][j], Complejo.producto(a[i][k],
Complejo.cociente(a[k][j], a[k][k]))); } } det=Complejo.producto(det, a[k][k]); } det=Complejo.producto(det, a[filas-1][columnas-1]); return det; } } public abstract class Raices { static final double E1=1.0e-15; //cota de errores static final double E2=0.0001; static final int MAXITERACCION=100; static final int MAXNIVELES=30; static final double pasos[]={0.2, 0.2, 0.2,
0.1, 0.1, 0.06, 0.05, 0.04, 0.03, 0.01}; int N; //número de barreras double a; //anchura double b; //separación static final double H=5.0; //profundidad del pozo; //resultados double Ceros[]=new double[MAXNIVELES]; // ceros de la función int nCeros=0; // número de ceros de la función double DE; //paso de exploración en la búsqueda de ceros abstract double f(double E, int paridad); public Raices(int N, double a, double b) { this.a=a; this.b=b; this.N=N; DE=pasos[N]; } //procedimiento del punto medio double punto_medio(double inf, double sup, int paridad, Boolean bError){ double med, inter, ini; int j=0; //cuenta el número de iteraciones ini=f(inf, paridad); do{ med=(inf+sup)/2; inter=f(med, paridad); if(Math.abs(inter)<E1) return med; if(Math.abs((sup-inf)/med)<E2) return med; if(inter*ini<0) sup=med; else{ inf=med; ini=inter; } j++; }while(!(j==MAXITERACCION)); bError=new Boolean(true); return med; } //calcula en un intervalo entre dos discontinuidades void calcular(double E_inf, double E_sup, int paridad){ if((E_inf>E_sup)||(Math.abs(E_sup-E_inf)<=DE)) return; double inf, sup; double ini, fin; double raiz; Boolean Error=new Boolean(false); inf=E_inf+DE; ini=f(inf, paridad); sup=inf+DE; while(sup<E_sup-DE){ fin=f(sup, paridad); if(ini*fin>0){ ini=fin; inf=sup; sup=inf+DE; continue; } raiz=punto_medio(inf, sup, paridad, Error); if (!Error.booleanValue()){ Ceros[nCeros]=raiz; nCeros++; } Error=new Boolean(false); ini=fin; inf=sup; sup=inf+DE; } } } public class Niveles { int paridad; double energia; public Niveles() { paridad=0; energia=0.0; } } public class Solido extends Raices { double x[]; //puntos de discontinuidad de la función potencial double V[]; //función potencial Complejo q[]; CVector2 Coef[]; //coeficientes para la función de onda Matriz M; //matriz para el cálculo del determinante int nNivel; //número de niveles totales Niveles nivel[]; public Solido(int N, double a, double b) { super(N, a, b); V=new double[N+2]; M=new Matriz(2*N+2, 2*N+2); //para la función de onda q=new Complejo[N+2]; for(int j=0; j<N+2; j++){ q[j]=new Complejo(); } Coef=new CVector2[N+2]; for(int j=0; j<N+2; j++){ Coef[j]=new CVector2(); } //niveles de energía nNivel=0; nivel=new Niveles[MAXNIVELES]; for(int j=0; j<MAXNIVELES; j++){ nivel[j]=new Niveles(); } //sólido regular x=new double[N+3]; x[0]=0; //número de barreras impar, número de átomos par if(N%2==1){ x[1]=b/2; for(int j=2;j<N+2; j+=2){ x[j]=x[j-1]+a; if(j==N+1) break; x[j+1]=x[j]+b; } for(int j=0; j<N+1; j+=2){ V[j]=H; V[j+1]=0; } }else{ //número de barreras par, número de átomos impar x[1]=a/2; for(int j=2;j<N+2; j+=2){ x[j]=x[j-1]+b; x[j+1]=x[j]+a; } for(int j=0; j<N+1; j+=2){ V[j]=0; if(j==N) break; V[j+1]=H; } } V[N+1]=H; //el 2 se puede cambiar significa hasta que la función
// de onda tiende a cero al hacerse x grande x[N+2]=x[N+1]+2; } void inicializar(double E, int paridad){ CAux4x4 M4=new CAux4x4(); for(int j=0; j<N+2; j++){ q[j]=Complejo.csqrt(E-V[j]); } Complejo t1=new Complejo(); Complejo t2=new Complejo(); t1=Complejo.exponencial(Complejo.producto
(Complejo.producto(Complejo.i, q[0]), x[1])); t2=Complejo.exponencial(Complejo.producto
(Complejo.producto(Complejo.i, q[0]), -x[1])); M.a[0][0]=Complejo.suma(t1, Complejo.producto(t2, paridad)); M.a[1][0]=Complejo.producto(q[0],
Complejo.diferencia(t1, Complejo.producto(t2, paridad))); t1=Complejo.exponencial(Complejo.producto
(Complejo.producto(Complejo.i, q[1]), x[1])); M.a[0][1]=t1.opuesto(); M.a[1][1]=Complejo.producto(q[1].opuesto(), t1); //si el número de barreras es mayor que cero if(N>0){ t1=Complejo.exponencial(Complejo.producto
(Complejo.producto(Complejo.i, q[1]), -x[1])); M.a[0][2]=t1.opuesto(); M.a[1][2]=Complejo.producto(q[1], t1); t1=Complejo.exponencial(Complejo.producto
(Complejo.producto(Complejo.i, q[N]), x[N+1])); M.a[2*N][2*N-1]=t1; M.a[2*N+1][2*N-1]=Complejo.producto(q[N], t1); t1=Complejo.exponencial(Complejo.producto
(Complejo.producto(Complejo.i, q[N]), -x[N+1])); M.a[2*N][2*N]=t1; M.a[2*N+1][2*N]=Complejo.producto(q[N].opuesto(), t1); t1=Complejo.exponencial(Complejo.producto
(Complejo.producto(Complejo.i, q[N+1]), x[N+1])).opuesto(); M.a[2*N][2*N+1]=t1; M.a[2*N+1][2*N+1]=Complejo.producto(q[N+1], t1); } for(int i=2; i<2*N; i+=2){ M4.auxiliar(q[i/2], q[i/2+1], x[i/2+1]); for(int j=i; j<i+2; j++){ for(int k=i; k<i+4; k++){ M.a[j][k-1]=M4.s[j-i][k-i]; } } } } //define la función abstracta double f(double E, int paridad){ Complejo res=new Complejo(); inicializar(E, paridad); res=M.determinante(); //la parte imaginaria es pequeña return (res.real+res.imag); } //método de la burbuja //ordena según el valor de la energía void ordenar(){ double d; int j; for(int izq=1; izq<nNivel; ++izq){ for(int der=nNivel-1; der>=izq; --der){ if(nivel[der-1].energia>nivel[der].energia){ d=nivel[der-1].energia; j=nivel[der-1].paridad; nivel[der-1].energia=nivel[der].energia; nivel[der-1].paridad=nivel[der].paridad; nivel[der].energia=d; nivel[der].paridad=j; } } } } //halla todos los niveles de energía void hallarNiveles(){ nNivel=0; for(int par=-1; par<=1; par+=2){ nCeros=0; calcular(0.0, H, par); for(int i=0; i<nCeros; i++){ nivel[nNivel+i].energia=Ceros[i]; nivel[nNivel+i].paridad=par; } nNivel+=nCeros; } ordenar(); } boolean normalizar(double E, int paridad){ CVector2 X=new CVector2(new Complejo(1.0,0), new Complejo(paridad, 0)); CVector2 Y=new CVector2(new Complejo(1.0,0), new Complejo()); Coef[0]=X; Coef[N+1]=Y; CMatriz2x2 R=new CMatriz2x2(); CMatriz2x2 I=new CMatriz2x2(); for(int j=0; j<N+2; j++){ q[j]=Complejo.csqrt(E-V[j]); //no se puede normalizar la función de onda if(q[j].modulo()<1.0e-20) return false; } for(int j=1; j<N+2; j++){ I.inversa(q[j], x[j]); R.matriz(q[j-1], x[j]); X=CMatriz2x2.producto(I, CMatriz2x2.producto(R, X)); Coef[j]=X; } Complejo norma=new Complejo(); Complejo temp1=new Complejo(); Complejo temp2=new Complejo(); for(int j=0; j<N+1; j++){ if(E<V[j]){ //a y b son números reales y q[j] imaginario norma=Complejo.suma(norma, Complejo.producto
(Complejo.producto(Coef[j].a, Coef[j].b), 2*(x[j+1]-x[j]))); temp1=Complejo.cociente(Complejo.producto
(Coef[j].a, Coef[j].a.conjugado()), Complejo.producto
(Complejo.producto(Complejo.i, q[j]), 2)); temp2=Complejo.diferencia(Complejo.exponencial
(Complejo.producto(Complejo.producto(Complejo.i, q[j]), 2*x[j+1])), Complejo.exponencial(Complejo.producto
(Complejo.producto(Complejo.i, q[j]), 2*x[j]))); norma=Complejo.suma(norma, Complejo.producto(temp1, temp2)); temp1=Complejo.cociente(Complejo.producto
(Coef[j].b, Coef[j].b.conjugado()), Complejo.producto
(Complejo.producto(Complejo.i, q[j]), 2)); temp2=Complejo.diferencia(Complejo.exponencial
(Complejo.producto(Complejo.producto(Complejo.i, q[j]), -2*x[j+1])), Complejo.exponencial(Complejo.producto
(Complejo.producto(Complejo.i, q[j]), -2*x[j]))); norma=Complejo.diferencia(norma, Complejo.producto(temp1, temp2)); }else{ //a y b son complejos conjugados y q[j] es real temp1=Complejo.suma(Complejo.producto(Coef[j].a,
Coef[j].a.conjugado()), Complejo.producto(Coef[j].b, Coef[j].b.conjugado())); norma=Complejo.suma(norma, Complejo.producto(temp1, 2*(x[j+1]-x[j]))); temp1=Complejo.cociente(Complejo.producto(Coef[j].a,
Coef[j].b.conjugado()), Complejo.producto(Complejo.producto(Complejo.i, q[j]), 2)); temp2=Complejo.diferencia(Complejo.exponencial
(Complejo.producto(Complejo.producto(Complejo.i, q[j]), 2*x[j+1])), Complejo.exponencial(Complejo.producto
(Complejo.producto(Complejo.i, q[j]), 2*x[j]))); norma=Complejo.suma(norma, Complejo.producto(temp1, temp2)); temp1=Complejo.cociente(Complejo.producto(Coef[j].b,
Coef[j].a.conjugado()), Complejo.producto(Complejo.producto(Complejo.i, q[j]), 2)); temp2=Complejo.diferencia(Complejo.exponencial
(Complejo.producto(Complejo.producto(Complejo.i, q[j]), -2*x[j+1])), Complejo.exponencial(Complejo.producto
(Complejo.producto(Complejo.i, q[j]), -2*x[j]))); norma=Complejo.diferencia(norma, Complejo.producto(temp1, temp2)); } } temp1=Complejo.cociente(Complejo.producto(Coef[N+1].a,
Coef[N+1].a.conjugado()), Complejo.producto(Complejo.producto(Complejo.i, q[N+1]), -2)); temp2=Complejo.exponencial(Complejo.producto
(Complejo.producto(Complejo.i, q[N+1]), 2*x[N+1])); norma=Complejo.suma(norma, Complejo.producto(temp1, temp2)); for(int j=0; j<N+2; j++){ Coef[j]=CVector2.cociente(Coef[j], Math.sqrt(norma.real)); } return true; } }
Anterior