Applet que plotea la función de onda:
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
class DibujaNivel extends Canvas{
int puntos;
double[] zona;
double energiaNivel;
int[] pts;
double energiaPozo;
//la x en el dibujo ira desde -xMax hasta x Max(distribucion de la
pantalla:20-60-20)
double xMax;
double step;
int n;
public void establecerNivel(int nivel, double energin,double V0,double
anchuraPozo){
double kNivel;
n=nivel;
energiaNivel=energin;
//es negativa
kNivel=Math.sqrt(2*(energiaNivel+V0));
energiaPozo=V0;
// la tomo positiva
xMax=anchuraPozo*5.0/6.0;
step=xMax/250.0;
puntos = 501;
zona= new double [501];
double rho=Math.sqrt(-energiaNivel*2);
pts = new int [501];
double factor;
if (Math.pow(-1,n+1)==1){
factor=Math.exp(-anchuraPozo*rho/2.0)/Math.cos(-anchuraPozo*kNivel/2.0);
}
else{
factor=Math.exp(-anchuraPozo*rho/2.0)/Math.sin(anchuraPozo*kNivel/2.0);
}
// las funciones las hago un poco a lo bruto, pues las
voy a reescalar
//despues en función de la altura del applet.
// zona1: exponencial real con signo positivo
for (int i=0; i < 100; i++) {
double xreal=-xMax+i*step;
zona[i]=Math.pow(-1,n+1)*Math.exp(rho*xreal);
}
// zona2: coseno para pares(n impar) seno para impares
for (int i=100; i < 401; i++) {
double xreal=-xMax+i*step;
if (Math.pow(-1,n+1)==1){
zona[i]=factor*Math.cos(kNivel*xreal);
}
else{
zona[i]=factor*Math.sin(kNivel*xreal);
}
}
//zona3: exponencial real con signo negativo
for (int i=401; i < 501; i++) {
double xreal=-xMax+i*step;
zona[i]=Math.exp(-rho*xreal);
}
repaint();
}
public void paint(Graphics g){
Dimension d=size();
int anchuraMax = d.width;
int alturaMax = d.height;
//traslado el origen
g.translate((int)(anchuraMax*0.5),(int)(alturaMax*0.2));
//dibujo pozo en negro
g.setColor(Color.black);
//lineas horizontales(3)
g.drawLine(-(int)(anchuraMax*0.5),0,-(int)(anchuraMax*.3),0);
g.drawLine((int)(anchuraMax*.3),0,(int)(anchuraMax*0.5),0);
g.drawLine(-(int)(anchuraMax*0.3),(int)(0.6*alturaMax),(int)(anchuraMax*0.3),(int)(alturaMax*0.6));
//lineas verticales(2)
g.drawLine(-(int)(anchuraMax*0.3),0,-(int)(anchuraMax*0.3),(int)(0.6*alturaMax));
g.drawLine((int)(anchuraMax*0.3),0,(int)(anchuraMax*0.3),(int)(0.6*alturaMax));
if(n>0){
//Ahora dibujamos el nivel en Verde
g.setColor(Color.green);
// la altura del nivel es:
int altura= (int)((-1.0*energiaNivel/energiaPozo)*alturaMax*0.6);
// linea horizontal que cruza el applet
y que sevirá para dibujar sobre ella la función
//de onda:
g.drawLine(-(int)(anchuraMax*0.5),altura,(int)(anchuraMax*0.5),altura);
//dibujamos la función. para
que no se salga del applet vemos su maximo:
double alturaMaximaOnda=0.0;
for(int i=101; i < 401; i++){
alturaMaximaOnda=Math.max(alturaMaximaOnda,Math.abs(zona[i]));
}
//Para ver si el peligro esta para arriba
o por abajo minimizo las dos alturas;
int distancia;
if(n==1){
distancia=altura;//en el
primer nivel solo tendremos peligro por arriba
}
else{
distancia=Math.min(altura,(int)(alturaMax*0.6-altura));
}
//para dibujar tengo esta distancia y el 20%
de la pantalla que no es ocupado por el pozo
//ahora hacemos lo más importante pasar
de algo general a dibujar en la pantalla
//diciendole a cada punto del plano
energia-distancia donde se tiene que ir a la pantalla
for(int i = 0; i < puntos; i++){
pts[i] = (int)(-(zona[i]/alturaMaximaOnda)
* (alturaMax*0.2+distancia)*.9 + altura);
//cambio de signo pues el tonto que
hizo Java no se le ocurrio otra cosa
//que poner el eje Y hacia
abajo ¡que más da que el resto del planeta
//lo ponga para arriba?
}
g.setColor(Color.blue);
double paso=anchuraMax/500.0;
//una vez que hemos pasado de la funcion
real a pixel solo queda dibujar
for(int i=1; i <puntos;i++){
int x1 = (int)((i-1)*paso-anchuraMax/2.0);
int x2 = (int)(i*paso-anchuraMax/2.0);
int y1 = pts[i-1];
int y2 = pts[i];
g.drawLine(x1,y1,x2,y2);
}
}
}
}
// ahora viene el applet que es lo mas facil.
public class DibujaNivel2 extends Applet {
// construimos un canvas de estos para pintar;
DibujaNivel nivelDibujado= new DibujaNivel();
//añadimos etiquetas y campos de texto para tomar y mostrar datos
TextField V0Text = new TextField(5);
Label V0Label = new Label("V0");
TextField a = new TextField(5);
Label aLabel = new Label ("eV. Ancho del pozo");
TextField niveles = new TextField(5);
Label nivelesLabel = new Label ("A. Niveles");
Label nivelBuscar = new Label ("El nivel ");
TextField nivel = new TextField(5);
Label knivelLabel = new Label(" tiene una energia:");
Label unidad= new Label("eV");
TextField nivelBuscado = new TextField(15);
// definimos estas vaiables aqui pues van a ser necesarias en muchos de los
metodos
double k0,V0,anchuraPozo;
public void init(){
//para colocar todo en los lugares cardinales de la pantalla se da
la siguiente orden:
setLayout(new BorderLayout());
//ordenamos por paneles y lo colocamos todo bonico;
Panel datoPanel=new Panel();
Panel resultados = new Panel();
Button dibu= new Button("Dibuja");
add("Center",nivelDibujado);
datoPanel.add(V0Label);
datoPanel.add(V0Text);
datoPanel.add(aLabel);
datoPanel.add(a);
datoPanel.add(nivelesLabel);
datoPanel.add(niveles);
resultados.add(nivelBuscar);
resultados.add(nivel);
resultados.add(knivelLabel);
resultados.add(nivelBuscado);
resultados.add(unidad);
resultados.add(dibu);
add("North",datoPanel);
add("South",resultados);
// inicializamos con unos parametros para que el java no me de problemas
con excepciones
//el poder de Java se vuelve contra el ignorante
V0Text.setText("10");
a.setText("6");
niveles.setText("4");
nivel.setText("1");
//dibujamos el pozo solamente de principio, para ello nos llevamos
todo fuera de pantalla menos el pozo
nivelDibujado.establecerNivel(-1,-1000.0,100.0,1.0);
}
//ahora veamos el motor
public boolean action(Event e, Object o){
//el unico evento posible es que alguien pulse intro en
un campo de texto pero me da igual los parametros
//hago cosas y cuando me harto devuelvo true y el applet
se queda reposando;
//cojo V0 de su panel
// V0=Double.parseDouble(V0Text.getText());
int EnteroV0 = Integer.parseInt(V0Text.getText());
V0=EnteroV0/27.2;
//calculo k0 que falta me hace
k0=Math.sqrt(2*V0);
//hago lo mismo con la anchura:
// anchuraPozo=Double.parseDouble(a.getText());
int EnteroAnc = Integer.parseInt(a.getText());
anchuraPozo=EnteroAnc/.52917;
//calculamos el numero de niveles
int numeroNiveles = 1+ (int)(k0*anchuraPozo/Math.PI);
// se lo decimos al que esta jugando para que no de mucho
el follon;
niveles.setText(String.valueOf(numeroNiveles));
//tomamos el nivel a buscar
int n=Integer.parseInt(nivel.getText());
//vemos que es valido
if (n > 0 && n < (numeroNiveles+1)){
//nos aprovechamos que sabemos donde va a
estar mas o menos y por el metodo de la bisección
//todo funciona bien mas o menos
double kredNivel = buscanivel(1.0*(n-1),1.0*n);
double energiaNivelUa=Math.pow(kredNivel*Math.PI/anchuraPozo,2)/2-V0;
double energiaNivel=energiaNivelUa*27.2;
//esceribimos el resultado para calmar la
curiosidad del navegante
nivelBuscado.setText(String.valueOf(energiaNivel));
// y por fin aprovechamos la potencia de la
clase de arriba con el metodo establecerNivel
nivelDibujado.establecerNivel(n,energiaNivelUa,V0,anchuraPozo);
}
//para que haga lo que debe reconducimos al navegador
else{ nivelBuscado.setText("cabrito!!!");}
//ya nos casamos de hacer cosas y por tanto para que se
este quieto:
return true;
}
// parte sencilla como en culaquier otro lenguaje
public int factorial(int n){
if (n==1) return 1;
else return n*factorial(n-1);
}
//método que busca la energía del nivel por bisección:
public double buscanivel(double left, double right){
//tomo este error yo para no ser demasiado quisquilloso
if (Math.abs(right-left)<0.001){ return ((right+left)/2.0);}
//utilizo recursividad
if ((f(right)*f((right+left)/2.0))<0){
return buscanivel(((right+left)/2.0),right);}
else{
return buscanivel(left,((right+left)/2.0));}
}
//este metodo es la funcion de la que quiero calcular los ceros
public double f(double kred){
double a=anchuraPozo;
double kreal=Math.PI*kred/a;
if (Math.tan(kreal*a/2.0)>0){
return Math.abs(Math.cos(kreal*a/2.0))-kreal/k0;
}
else{
return Math.abs(Math.sin(kreal*a/2.0))-kreal/k0;
}
}
}
Alojado en Hosting :: LMI