Android

Android


APLICACIONES

Página 24 de 25

                expdat[i]=(datMax+datMin)/2.0;

                expdatError[i]=(datMax-datMin)/2.0;

                // tolerancia

                if(expdatError[i]<tolerancia)

                        expdatError[i]=tolerancia;

                nDatosExp++;

             }

          }

       }

    }

    void leerPreferencias(){

         // lee lambad00 en el fichero de preferencias

         misDatos=getSharedPreferences("preferencias",0);

         lambda[0][0]=misDatos.getFloat("lambda00",0);

         lambda[0][1]=misDatos.getFloat("lambda01",0);

         lambda[1][0]=misDatos.getFloat("lambda10",0);

         lambda[1][1]=misDatos.getFloat("lambda11",0);

         Rdelta[0][0]=misDatos.getFloat("R00",0);

         Rdelta[0][1]=misDatos.getFloat("R01",0);

         Rdelta[1][0]=misDatos.getFloat("R10",0);

         Rdelta[1][1]=misDatos.getFloat("R11",0);

         Emax=misDatos.getFloat("Emax",0);

         tolerancia=misDatos.getFloat("tolerancia",0);

         resolucion=misDatos.getFloat("resolucion",0);

         // variables iniciales para minimizar

        xvar[0]=lambda[spin][0];

        xvar[1]=lambda[spin][1];

         xvar[2]=Rdelta[spin][0];

         xvar[3]=Rdelta[spin][1];

    }

    double minimiza(double paso){

       int dimension= nparametros;

       double[] xmas=new double[dimension];

       double[] xmenos=new double[dimension];

       double[] x=new double[dimension];

       for (int i=0;i<dimension;i++)x[i]=xvar[i];

       double minimo=chiCuadro(x);

       double oldmin=minimo;

       boolean esMinimo=false;

       while (!esMinimo){

       for (int i=0;i<dimension;i++){

          // calcula  puntos desplazados direccion +-i

          for(int j=0;j<dimension;j++){

             double kroneker=0;

             if (i==j)kroneker=1;

             xmas[j]=x[j]+paso*kroneker;

             xmenos[j]=x[j]-paso*kroneker;

          }

          // si R1 < R0 no nos movemos

          if(xmas[3]<xmas[2]) xmas[2]=xmas[3];

          if(xmenos[3]<xmenos[2])xmenos[3]=xmenos[2];

          double valuemas=chiCuadro(xmas);

          if(valuemas<minimo){

             minimo=valuemas;

             for (int j=0;j<dimension;j++)xvar[j]=xmas[j];

          }

          double valuemenos=chiCuadro(xmenos);

          if(valuemenos<minimo){

             minimo=valuemenos;

             for (int j=0;j<dimension;j++)xvar[j]=xmenos[j];

          }

          texto1="Minimo="+minimo;

       }

       // si el punto no se ha desplazado ES EL MINIMO

       if(minimo==oldmin) esMinimo=true;

       else {

          oldmin=minimo;

          for(int i=0;i<dimension;i++){x[i]=xvar[i];}

       }

       }

       return minimo;

       }

    double chiCuadro(double[] parametros){

       double valor=0;

       for (int i=0;i<nDatosExp;i++){

          double Elab=energyExp[i];

          deltaDeg[i]= desfasaje(Elab,parametros);

          double sumando =

                (deltaDeg[i]-expdat[i] )/expdatError[i];

          valor=valor + sumando*sumando;

       }

       return valor/nDatosExp;

    }

    // Calcula el desfasaje en onda S. Potencial delta-shell

    double desfasaje(double Elab, double[] parametros){

       double delta=0;

       double Erel=Elab/2;

       double muc2=939.0/2.0;

       double hbarc=197.32;

       double hbarc2=hbarc*hbarc;

       double twoMuH2=2.0*muc2/hbarc2;

       double epsilon=twoMuH2*Erel;

       double k=Math.sqrt(epsilon);

       for (int i=0;i<ndeltas;i++){

          double kr=k*parametros[i+ndeltas];

          // lamda esta dividida por 2mu en

          double alfak=parametros[i]/k;

          double ctan=1.0/Math.tan(kr+delta);

          double denominator=ctan+alfak;

          double unotan=1.0/denominator;

          delta=Math.atan(unotan)-kr;

       }

          // check delta is between -pi,pi for J=0

          if(spin==0){

          if (delta<=-Math.PI/2){

             while(delta<-Math.PI/2)delta=delta+Math.PI;

          }

          if(delta>Math.PI/2){

             while(delta>Math.PI/2)delta=delta-Math.PI*2;

          }

          }

          // check delta is between 0,pi for J=1

          if(spin==1){

          if (delta<0){

             while(delta<0)delta=delta+Math.PI;

          }

          if(delta>Math.PI){

             while(delta>Math.PI)delta=delta-Math.PI*2;

          }

          }

       double deltaDeg=delta*180/Math.PI;

       return deltaDeg;

    }

     @Override

     protected void onPause(){

       super.onPause();

       // detenemos el hilo

       continuar=false;

       if(hilo.isAlive()) hilo.stop();

       // guardamos datos

       SharedPreferences.Editor miEditor=misDatos.edit();

       lambda[spin][0]=xvar[0];

       lambda[spin][1]=xvar[1];

       Rdelta[spin][0]=xvar[2];

       Rdelta[spin][1]=xvar[3];

       miEditor.putFloat("lambda00",

                 (float) format(lambda[0][0],6));

       miEditor.putFloat("lambda01",

                 (float) format(lambda[0][1],6));

       miEditor.putFloat("lambda10",

                 (float) format(lambda[1][0],6));

       miEditor.putFloat("lambda11",

                 (float) format(lambda[1][1],6));        

       miEditor.putFloat("R00",

                 (float) format(Rdelta[0][0],6));

       miEditor.putFloat("R01",

                 (float) format(Rdelta[0][1],6));

       miEditor.putFloat("R10",

                 (float) format(Rdelta[1][0],6));

       miEditor.putFloat("R11",

                 (float) format(Rdelta[1][1],6));

       miEditor.commit();

       Toast.makeText(this,"Datos guardados",1).show();

     }

     // formatear un numero con varias cifras

     float format(double x, int cifras){

       String cadena=""+x;

       if (cadena.length()<=cifras)

              return Float.parseFloat(cadena);

       if(x<0) cifras=cifras+1;

       float y=Float.parseFloat(cadena.substring(0,cifras));

       return y;

 }

Figura C.2. Ajuste del desfasaje

1

S

0

para espín igual a cero.

Figura C.3. Valores ajustados del desfasaje

1

S

0

.

La descripción de los distintos métodos es la siguiente:

•   Método onCreate(). Se almacena el valor del espin (cero o uno) en la variable spin pasada como parámetro extra por la actividad principal. Luego se lee el fichero de preferencias en el método leerPreferencias() y se leen los datos experimentales en el método leerDatos(). Se instancia el objeto plot de tipo View, donde se dibuja la gráfica que, a su vez,  implementa la interfaz Runnable. Finalmente, se inicia un hilo para realizar el ajuste por mínimos cuadrados.

•   Clase Plot. Se utiliza para dibujar la gráfica y para implementar la interfaz Runnable. En el método onSizeChanged() se calculan las dimensiones de la pantalla y las de la gráfica. El método onDraw() dibuja la gráfica y escribe los valores de los parámetros del potencial, los datos experimentales que se están ajustando, el valor del mínimo y el paso de búsqueda.

•   Método run(). Implementado en la clase Plot. Comienza con un paso de búsqueda y ejecuta el método minimiza(paso) para encontrar el mínimo con ese paso. Luego reduce el paso a la mitad y se repite el proceso hasta llegar al mínimo con la resolución deseada.

•   Método minimiza(paso). Dado un paso de búsqueda, busca todos los puntos adyacentes, sumando y restando el paso a los parámetros del potencial, y calcula la función chi cuadrado en todos ellos ejecutando el método chiCuadro().

•   Método chiCuadro(). Calcula la función chi cuadrado haciendo un loop sobre las energías experimentales y llamando al método para calcular los desfasajes.

•   Método desfasaje(). Calcula el desfasaje para una energía y parámetros del potencial dados. Se resta o suma pi, teniendo en cuenta que para el canal

1

S

0

el desfasaje debe estar entre (-π/2, π/2), mientras que, para el canal

3

S

1

, el desfasaje está entre (0, π).

Figura C.4. Ajuste del desfasaje

3

S

1

para espín igual a uno.

Después de ajustar el canal

1

S

0

se pulsa la tecla back para volver a la actividad anterior y se pulsa el botón B para calcular los parámetros en el canal

3

S

1

. El proceso y resultado de la minimización se muestra en la figura C.4. Encontrado el mínimo se vuelve a pulsar back, volviendo de nuevo a la actividad principal con todos los parámetros ajustados, figura C.5.

Figura C.5. Valores ajustados del desfasaje

3

S

1

.

C.3. Energía del Helio-4

Pulsando el botón C de la actividad principal se calcula la energía del núcleo de Helio-4 usando el potencial que se ha ajustado. El núcleo de helio consiste en cuatro partículas: dos protones y dos neutrones. Supondremos que la interacción entre cada pareja de partículas es la que hemos ajustado en la sección anterior, promediada entre los dos canales de espin. Para calcular la energía se utiliza el llamado método variacional. Suponemos que la función de onda total del helio es el producto de cuatro funciones de onda para cada una de las partículas. Cada función de onda individual supondremos que es una Gaussiana del tipo:

con un parámetro α que debemos encontrar minimizando la energía:

Donde el primer término es la energía cinética y el segundo la energía potencial. El mínimo de esta función, con respecto al parámetro α, nos proporciona la energía del núcleo de Helio. El parámetro b = 1/α es una estimación del radio del helio.

El siguiente programa He4.java  es la actividad que realiza este cálculo, que se ejecuta pulsando el botón c.

  package es.ugr.amaro.handroicphysics;

  import android.app.Activity;

  import android.content.Context;

  import android.content.SharedPreferences;

  import android.graphics.Canvas;

  import android.graphics.Color;

  import android.graphics.Paint;

  import android.graphics.Path;

  import android.os.Bundle;

  import android.view.View;

  public class He4 extends Activity{

    // parametros del potencial

    double lambda[][]=new double[2][2];

    // centros de las deltas

    double Rdelta[][]=new double[2][2];

    Thread hilo;

    double bmin,emin;

    double cinetica,potencial;

    @Override

    public void onCreate(Bundle savedInstanceState){

       super.onCreate(savedInstanceState);

       leerPreferencias();

       Grafico grafico=new Grafico(this);

       setContentView(grafico);

       hilo=new Thread(grafico);

       hilo.start();

    }

     @Override

     protected void onPause(){

       super.onPause();

       // detenemos el hilo

       if(hilo.isAlive()) hilo.stop();

     }

    class Grafico extends View implements Runnable{

       int width,height;

       Paint paint1,paint2,paint3,paint4,paint,paintRun;

       Path path1,path2,path3;

       int topMargin=40;

       int margin=40;

       int x0,x1,y0,y1,x,y;

       double b0,b1,e0,e1;

       String texto;

       String texto1="texto1";

       String texto2="texto2";

       String texto3="texto3";

       // matriz para dibujar la energia

       int intervalos=200;

       double [] bMatriz=new double[intervalos];

       double [] eMatriz=new double[intervalos];

       double [] potMatriz=new double[intervalos];

       double [] cinMatriz=new double[intervalos];

       public Grafico(Context context) {

          super(context);

          paint=new Paint();

          paint.setColor(Color.BLACK);

          paint.setTextSize(16);

          paintRun=new Paint();

          paintRun.setColor(Color.RED);

          paintRun.setTextSize(20);

          paint1=new Paint();

          paint1.setColor(Color.BLACK);

          paint1.setStyle(Paint.Style.STROKE);

          paint1.setStrokeWidth(1);

          paint2=new Paint();

          paint2.setColor(Color.RED);

          paint2.setStyle(Paint.Style.STROKE);

          paint2.setStrokeWidth(3);

          paint3=new Paint();

          paint3.setColor(Color.BLUE);

          paint3.setStyle(Paint.Style.STROKE);

          paint3.setStrokeWidth(3);

          paint4=new Paint();

          paint4.setColor(Color.GREEN);

          paint4.setStyle(Paint.Style.STROKE);

          paint4.setStrokeWidth(3);

          path1=new Path();

          path2=new Path();

          path3=new Path();

          b0=0;

          b1=5;

          e0=-150;

          e1=50;

          // llena una matriz para dibujar la energia

          double paso=(b1-b0)/intervalos;

          for(int i=1;i<intervalos;i++){

             bMatriz[i]=b0+paso*i;

             eMatriz[i]=energia(bMatriz[i]);

             potMatriz[i]=potencial;

             cinMatriz[i]=cinetica;

          }

       }

       @Override

       protected void onSizeChanged(

                 int w, int h, int oldw, int oldh){

          width=w;

          height=h;

          x0=margin;

          x1=width-margin;

          y0=height-margin;

          y1=topMargin;

       }

       @Override

       protected void onDraw (Canvas canvas){

          canvas.drawColor(Color.WHITE);

          texto="Energia del  Helio-4";

          canvas.drawText(texto,x1/2,20,paint);

          canvas.drawRect(x0,y0,x1,y1,paint1);

          texto1="bmin="+format(bmin,6);

          texto2="Emin="+format(emin,6);

          canvas.drawText(texto1,width/2,85,paint);

          canvas.drawText(texto2,width/2,105,paint);

          canvas.drawText(texto3,width/2,65, paintRun);

          // dibuja funcion energia

          x=coX(bMatriz[1]);

          y=coY(eMatriz[1]);

          path1.moveTo(x,y);

          for(int i=2;i<intervalos;i++){

             x=coX(bMatriz[i]);

             y=coY(eMatriz[i]);

             path1.lineTo(x,y);

          }

          canvas.drawPath(path1,paint2);

          // dibuja energia cinetica

          x=coX(bMatriz[1]);

          y=coY(cinMatriz[1]);

          path2.moveTo(x,y);

          for(int i=2;i<intervalos;i++){

             x=coX(bMatriz[i]);

             y=coY(cinMatriz[i]);

             path2.lineTo(x,y);

          }

          canvas.drawPath(path2,paint3);

          // dibuja energia potencial

          x=coX(bMatriz[1]);

          y=coY(potMatriz[1]);

          path3.moveTo(x,y);

          for(int i=2;i<intervalos;i++){

             x=coX(bMatriz[i]);

             y=coY(potMatriz[i]);

             path3.lineTo(x,y);

          }

          canvas.drawPath(path3,paint4);

          // dibuja punto minimo

          canvas.drawCircle(coX(bmin), coY(emin), 5, paint);

          // marcas eje x

          for (int i=1; i<6;i++){

             canvas.drawLine(coX(i),coY(e0),

                      coX(i),coY(e0)-5,paint1);

             canvas.drawText(""+i,

                      coX(i),y0+20, paint);

          }

          // marcas eje y

          for (int i=-15;i<5;i++){

             canvas.drawLine(coX(b0),coY(10*i),

                   coX(b0)+5,coY(10*i), paint1);

             canvas.drawText(""+10*i,0,coY(10*i), paint);

          }

          // dibuja linea del cero

          canvas.drawLine(coX(b0),coY(0),

                          coX(b1),coY(0),paint1);

          // escribe contenidos de sharedpreferences

          int ii=0;

          for (int i=0;i<2;i++){

             for (int j=0;j<2;j++){

                texto="R"+i+"="+Rdelta[i][j];

                canvas.drawText(texto,

                       x1/2, y0/2+20*(ii+1), paint);

                ii++;

                texto="La"+i+j+"="+lambda[i][j];

                canvas.drawText(texto,

                       x1/2, y0/2+20*(ii+1), paint);

                ii++;

             }

          }

       }

       int coX(double b){

          double xdouble=x0+(x1-x0)*(b-b0)/(b1-b0);

          return (int) xdouble;

       }

       int coY(double e){

          double ddouble=y0+(y1-y0)*(e-e0)/(e1-e0);

          return (int) ddouble;

       }

       @Override

       public void run() {

          // Comienza buscando el minimo con paso=1

          double paso=1;

          int dt=50;

          bmin=1;

          emin=energia(bmin);

          double resolucion=0.01;

          while(paso>resolucion){

             minimiza(paso);

             paso=paso/2.0;

             texto2="paso="+paso;

             postInvalidate();

             try{ Thread.sleep(dt);}

             catch(InterruptedException e){;}

          }

          texto3="MINIMO ENCONTRADO!";

          postInvalidate();

       }

    }

    void minimiza(double paso){

       boolean found=false;

       while(!found){

       double bmas=bmin+paso;

       double bmenos=bmin-paso;

       double emenos=energia(bmenos);

       double emas=energia(bmas);

       if(emenos<emin){

          bmin=bmenos;

          emin=emenos;

       }else if(emas<emin){

          bmin=bmas;

          emin=emas;

       }else

          found=true;

       }

    }

    double energia(double b){

       final double hbarc=197.3;

       final double mc2=939;

       double sq2pi=Math.sqrt(2./Math.PI);

       double hbc2mc2=hbarc*hbarc/mc2;

       double alfa=1/b;

       double alfa2=alfa*alfa;

       double alfa3=alfa2*alfa;

       double factor=sq2pi*6.*hbc2mc2*alfa3;

       cinetica =9.0/4.*hbc2mc2*alfa2;

       potencial=0.;

       double r,r2,exponente,exponencial,lambdaMedio;

       for (int i=0;i<2;i++){

       for (int j=0;j<2;j++){

          r=Rdelta[i][j];

          r2=r*r;

          exponente=-alfa2*r2/2.0;

          exponencial=Math.exp(exponente);

          lambdaMedio=lambda[i][j]/2.;

           potencial=

                potencial+factor*lambdaMedio*r2*exponencial;

       }}

       double energy=cinetica+potencial;

       return energy;

    }

    void leerPreferencias(){

         SharedPreferences misDatos

                  = getSharedPreferences("preferencias",0);

         lambda[0][0]=misDatos.getFloat("lambda00",0);

         lambda[0][1]=misDatos.getFloat("lambda01",0);

         lambda[1][0]=misDatos.getFloat("lambda10",0);

         lambda[1][1]=misDatos.getFloat("lambda11",0);

         Rdelta[0][0]=misDatos.getFloat("R00",0);

         Rdelta[0][1]=misDatos.getFloat("R01",0);

         Rdelta[1][0]=misDatos.getFloat("R10",0);

         Rdelta[1][1]=misDatos.getFloat("R11",0);

    }

     // formatear un numero con varias cifras

     String format(double x, int cifras){

       String cadena=""+x;

       if (cadena.length()<=cifras)return cadena;

       if(x<0) cifras=cifras+1;

       return cadena.substring(0,cifras);

    }

  }

Figura C.6. Cálculo de la energía del núcleo de Helio-4.

Esta actividad dibuja la energía cinética (curva superior, positiva), energía potencial (curva inferior, negativa) y energía total (curva intermedia) del helio en función del radio b (en fm). El mínimo se encuentra variando este parámetro en el método minimiza(paso) con un paso inicial, que se va reduciendo a la mitad en el método run() hasta que se alcanza la resolución buscada. El resultado se ve en la figura C.6. El valor del mínimo encontrado en el ejemplo de la figura es de:

E = -28.488 MeV

muy próximo al valor experimental.

La aplicación completa y el código fuente pueden descargarse de la página web:

   http://www.ugr.es/~amaro/android

El lector puede ejecutar esta aplicación  introduciendo distintos valores iniciales para los parámetros, especialmente la energía máxima, la tolerancia y la resolución, para ajustar distintos potenciales y con ellos recalcular la energía del helio.

Ir a la siguiente página

Report Page