/
Inicio :: Foros

 F.A.Q.F.A.Q.                  Conéctese para revisar sus mensajesConéctese para revisar sus mensajes   

Pregunta acerca de un algoritmo

 
      Índice del Foro elrincondelc.com -> Algoritmos
Ver tema anterior :: Ver siguiente tema  
AutorMensaje
mar5



Registrado: 18 Ene 2011
Mensajes: 21

MensajePublicado: 21/03/2011 2:24 am
Título: Pregunta acerca de un algoritmo

Hola!
Queria hacer una pregunta acerca de un algoritmo que estoy haciendo.Tengo que calcular la suma de los valores aceleracionx[i][0], es decir que me haga la suma de aceleracionx[1][0] por un lado,la de aceleracionx[2][0] por otro y aceleracionx[3][0]por otro,no la suma total de todas las componentes y segun lo tengo puesto no me hace la suma.
a,b y l son constantes cuyo valor no es relevante.
Muchas gracias.
Un saludo!


Código:

 for(i=0;i<part;i++){               
         for(j=0;j<part;j++){
             if(i!=j){           
                rij=sqrt(pow(p[i][0]-p[j][0],2)+pow(p[i][1]-p[j][1],2)+pow(p[i][2]-p[j][2],2));
       
                 printf(" resultado %4.2f\n",rij);
         
         termino1=(((2*a)/l)*exp(-(pow(rij,2)/l)));
         termino2=((b/l)*exp((-pow(rij,2)/(2*l))));
       
         s= termino1+termino2;
       
          aceleracionx[i][0]+=((p[i][0]-p[j][0])*(s));

         printf("valor  aceleracion%dx %e\n",i,aceleracionx[i][0]);
}
}
}

Volver arriba
Pantalàimon_



Registrado: 17 Jul 2007
Mensajes: 961

MensajePublicado: 21/03/2011 3:24 am
Título:

Me pierdo con tu código. Quieres calcular el vector aceleración. ¿Pero de que movimiento en particular? Parece que calcules la aceleración en función de la posición y otros parámetros. Pero al no saber la fórmula que debes usar, no tengo ni idea de si lo haces bien. Si no das más información yo lo único que puedo saber es que el vector aceleración es la segunda derivada respecto el tiempo del vector posición. Así que necesito saber con que movimiento estás tratando.

Por otra parte, estaria bien recordar que x^n equivale a multiplicar n veces por x. En particular pow(x,2) == x*x. Así que para un cuadrado mejor no usar la función pow().

Además, si quieres hacer una suma de terminos 0 , 1 i 2. Mejor hazlo con un for y una variable inicializada a 0 para ir sumando los terminos. Por ejemplo:

Código:
double rij[3];
double r, sum;
/* código */

sum = 0;
for( i = 0; i < 3; i++ )
{
   sum += rij[i]*rij[i]; /* sumar el termino rij[i]^2 */
}
/* Y luego si se desea calcular la raiz */
r = sqrt( sum );


Más que nada lo digo para cuando tengas que tratar con un movimiento en 26 dimensiones solo tengas que cambiar el 3 por un 26 y no poner una fórmula tan larga Wink. Lo dejo para que te sirva de referencia. Tu usa los nombres de variables que más te apetezcan.

Un saludo!
Volver arriba
mar5



Registrado: 18 Ene 2011
Mensajes: 21

MensajePublicado: 21/03/2011 3:43 am
Título:

Perdon por la explicacion,es que es un poco complicado de explicar.
Lo que hago es calcular la distancia que hay entre dos particulas haciendo uso de
rij=sqrt(pow(p[i][0]-p[j][0],2)+pow(p[i][1]-p[j][1],2)+pow(p[i][2]-p[j][2],2));

donde p[i][0]-p[j][0] es la distancia entre dos particulas,siendo i distinto de j(para que no calcule la distancia de una particula con si misma)y siendo 0,1,2 la componente x,y,z.
La aceleracion depende entonces de las posiciones de las particulas y del termino s que simplemente es la suma de los terminos 1y 2 que a su vez dependen de rij.
En teoria,si tengo 3 particulas me saldran 6 valores para la aceleracion (porque la particula 1 interaccion con la 2 y la 3,la particula 2 lo hace con la 1 y la 3 y la particula 3 lo hace con 1 y 2)y lo que quiero es la suma de,para la particula 1, la aceleracion que sale de la interaccion de la particula1 con la 2 y la aceleracion de la particula 1 con la 3 y lo mismo para la particula2 y la 3.
Espero habertelo aclarado un poco
Muchas gracias
Volver arriba
Pantalàimon_



Registrado: 17 Jul 2007
Mensajes: 961

MensajePublicado: 21/03/2011 6:52 am
Título:

Así de primeras no encuentro el error. Pero si que puedo darte unas correcciones. Hacer sqrt para luego elevar el número al cuadrado es una operación inútil. Podrías evitar muchos parentesis en algunas expresiones aritméticas sabiendo la prioridad de los operadores. Por otra parte, como te comenté, podrías calcular la distancia con un for y así evitar una expresión tan larga como "pow(p[i][0]-p[j][0],2)+pow(p[i][1]-p[j][1],2)+pow(p[i][2]-p[j][2],2)"

Aquí el código retocado:

Código:
for( i = 0; i < part; i++ )
{               
   for( j = 0; j < part; j++)
   {
      if(i!=j)
      {
         rij2 = 0 /* rij2 es la distancia al cuadrado */
         for( k = 0; k < 3; k++ )
         {
             int d = p[i][k] - p[j][k];   
             rij2 += d*d;
         }
       
         printf(" resultado %4.2f\n",sqrt(rij2));
         
         termino1 =  2*a/l * exp( -rij2 / l );
         termino2 =  b/l * exp( -rij2 / (2*l) );
       
         s = termino1 + termino2;
       
         aceleracionx[i][0] += (p[i][0] - p[j][0]) * s;

         printf("valor  aceleracion%dx %e\n",i,aceleracionx[i][0]);
      }
   }
}


Una posibilidad puede ser que no interpretes bien la salida del programa. Otra puede ser que no le des valor 0 a aceleracionx[i][0] para los valores de i que corresponda. Si quieres expresar un sumatorio en una variable, primero ha de estar a 0 para que el valor tenga algun sentido.

Un saludo!
Volver arriba
mar5



Registrado: 18 Ene 2011
Mensajes: 21

MensajePublicado: 21/03/2011 7:17 am
Título:

Gracias por las correcciones,seguire mirando porque puede que sea que interpreto mal la salida porque tengo las variables inicializadas a 0
gracias
un saludo
Volver arriba
Pantalàimon_



Registrado: 17 Jul 2007
Mensajes: 961

MensajePublicado: 22/03/2011 4:03 am
Título:

Buenas. He modificado el código poquisimo para calcular la aceleración de cada partícula. He asignado valores a a, b y l para que:

termino1 == e^(2rij^2)
termino2 == e^(rij^2)

También he elegido unas posiciones para las partículas sencilla para comprobar de manera fácil que los resultados son correctos y parece ser que lo son.

Código:
#include<math.h>
#include<stdio.h>

#define N_DIM  3
#define N_PART 3

int main(void)
{
   int i,j,k;

   double p[N_PART][N_DIM] = {{ 0., 0., 0. },
                              { 1., 0., 0. },
                              { 0., 1., 0. }};

   double aceleracionx[N_PART][N_DIM];

   double l = -0.50;
   double a = -0.25;
   double b = -0.50;

   for( i = 0; i < N_PART; i++ )
      for( k = 0; k < N_DIM; k++ )
         aceleracionx[i][k] = 0.;
   

   for( i = 0; i < N_PART; i++ )
   {               
      for( j = 0; j < N_PART; j++)
      {
         if(i!=j)
         {
            double ep,s;
            double rij2 = 0.0; /* rij2 es la distancia al cuadrado */
            for( k = 0; k < N_DIM; k++ )
            {
               double d = p[i][k] - p[j][k];   
               rij2 += d*d;
            }

            ep = exp( -rij2 / (2*l) );

            s = ( 2*a*ep + b ) * ep / l;

            for( k = 0; k < N_DIM; k++ )
            {
               aceleracionx[i][k] += (p[i][k] - p[j][k]) * s;
            }

           
         }
      }
   }

   for( i = 0; i < N_PART; i++ )
   {
      printf("aceleracion de la particula %d: ( %11.3e", i, aceleracionx[i][0] );
      for( k = 1; k < N_DIM; k++ )
         printf(", %11.3e", aceleracionx[i][k] );
      printf(" )\n");
   }

   return 0;
}



Como observación podrás ver que he quitado la forma de calcular s y la he substituido por una más eficiente:

Código:
     termino1 =  2*a/l * exp( -rij2 / l );
     termino2 =  b/l * exp( -rij2 / (2*l) );
       
     s = termino1 + termino2;


Se puede reducir a:

Código:
     ep = exp( -rij2 / (2*l) );

     s = ( 2*a*ep + b ) * ep / l;


Evitando hacer muchas operaciones repetidas.


Un saludo!
Volver arriba
mar5



Registrado: 18 Ene 2011
Mensajes: 21

MensajePublicado: 23/03/2011 1:26 am
Título:

Muchas gracias!
un saludo
Volver arriba
      Índice del Foro elrincondelc.com -> Algoritmos
Página 1 de 1Todas las horas están en GMT - 8 Horas

 
No puede crear mensajes
No puede responder temas
No puede editar sus mensajes
No puede borrar sus mensajes
No puede votar en encuestas

(c) ElRincondelC.com

Un proyecto de UrlanHeat.com