Voici un petit pack de sources en rapport avec la simulation de pendules couples, je vous le laisse decouvrir par vous meme. Je vous conseille toutefois de pas trop faire attention a la fonciton 'jacobi', il est suffisant de savoir ce qu'elle fait et de savoir l'utiliser (elle diagonalise une matrice et nous permet d'avoir acces aux valeur propres et aux vecteurs propres si je me souvient bien).
J'espere rendre service a tout(e?)s les etudiant(e?)s interesser (ou pas) par ce genre de simulation.
Source / Exemple :
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define ROTATE(a,i,j,k,l) g=a[i][j];h=a[k][l]; a[i][j]=g-s*(h+g*tau);a[k][l]=h+s*(g-h*tau);
#define C 2 //si jamais on veux remplacer C dans le reste du prog il suffit decrire un autre chiffre que 2
#define W1 1 //idem
double *vecteur(int n);
void ecrire_vecteur(double *v,int n);
double **matrice(int m,int n);
void ecrire_matrice(double **A, int m, int n);
void jacobi(double **a,int n,double *d,double **v1, int *nrot);
void eigsrt(double *d, double **v, int n);
FILE *n_pendules_couples, *fopen(); //fopen est une fonction on doit donc la marquer
main()
{
double *v; // le vecteur
int i,j,k,n,m,nrot;
double **A,*d,**v1,n2;
n_pendules_couples=fopen("n_pendules_couples.dat","w");
//valeurs2=fopen("valeurs2.dat","w");
n=20;
A=matrice(n,n);
d=vecteur(n); //d est un vecteur avec les valeurs propres
v1=matrice(n,n);
for(k=1;k<=n;k++)
{
for(i=1;i<=n;i++)
//init de la matrice... a l'arrache mais ca marche ;-) ...
for(j=1;j<=n;j++)
{
if (i==j)
A[i][j]=-(W1*W1+C);
if (i==j && i==1 && j==1)
{
A[i][j]=-(W1*W1+C);
A[i][j+1]=C;
}
if (i==j && i==n && j==n)
{
A[i][j]=-(W1*W1+C);
A[i][j-1]=C;
}
if (i==j-1)
A[i][j]=C;
if (i==j+1)
A[i][j]=C;
}
//A[1][1]=-(W1*W1+C); // parce que jacobi va me changer la matrice, je reinitialise
//A[1][2]=A[2][1]=C;
//A[2][2]=-(n2*n2+C); // d apres la formule trouvee a part (calcul a la maison)
//ecrire_matrice(A,n,n);
jacobi(A,n,d,v1,&nrot);
eigsrt(d,v1,n);
//printf("valeurs propres: \n"); ecrire_vecteur(d,n);
//printf("vecteurs propres: \n"); ecrire_matrice(v1,n,n);
//printf("\n");
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
fprintf(n_pendules_couples,"%d \t %lg \t",i,v1[i][j]);
fprintf(n_pendules_couples,"\n");
}
}
fclose(n_pendules_couples);
}
// procedure qui permet d' reserver la place pour un vecteur
double *vecteur(int n)
{
double *v;
v=(double*)calloc(n,sizeof(double));
return (v--); // pour que l'indice commence a 1
}
void ecrire_vecteur(double *v,int n) //procedure qui permet d'ecrire un vecteur
{
int i;
for(i=1;i<=n;i++)
printf("%lg \n",v[i]);
}
double **matrice(int m,int n) //declaration de la matrice
{
double**A;
A--; //va changer les indices des lignes
register int i; //pour les utiliser plus rapidement
A=(double**)calloc(m,sizeof(double*)); //on pointe sur les lignes
for(i=1;i<=m;i++)
{
A[i]=(double*)calloc(n,sizeof(double));
A[i]--; //va changer les indices de chaque colonne
}
return A;
}
void ecrire_matrice(double **A, int m,int n) //afficher la matrice
{
int i,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
printf(" %5.3lg ", A[i][j]); // je vais ecrire mes double avec 5 caracteres et 3 chiffres apres la virgule
printf("\n");
}
}
void jacobi(double **a,int n,double *d,double **v, int *nrot) //la matrice va etre modifiee a la sortie, si on veut la garder il faut la sauver
/*Nb: Payes ta perche :D */
{
int j,iq,ip,i;
double tresh,theta,tau,t,sm,s,h,g,c,*b,*z;
b=vecteur(n);
z=vecteur(n);
for (ip=1;ip<=n;ip++){
for (iq=1;iq<=n;iq++) v[ip][iq]=0.0;
v[ip][ip]=1.0;
}
for (ip=1;ip<=n;ip++){ // initialise b et d a la diagonale de a
b[ip]=d[ip]=a[ip][ip]; //ce vecteur va accumuler les termes en tant qu'equations
z[ip]=0.0;
}
*nrot=0;
for (i=1;i<=50;i++) {
sm=0.0;
for (ip=1;ip<=n-1;ip++){ // somme des elements diagonaux
for (iq=ip+1;iq<=n;iq++)
sm += fabs(a[ip][iq]);
}
if (sm == 0.0){
z++;
free(z);
b++;
free(b);
return;
}
if (i < 4)
tresh=0.2*sm/(n*n);
else
tresh=0.0;
for (ip=1;ip<=n-1;ip++){
for (iq=ip+1;iq<=n;iq++){
g=100.0*fabs(a[ip][iq]);
if (i > 4 && (double)(fabs(d[ip])+g) == (double)fabs(d[ip]) && (double)(fabs(d[iq])+g) == (double)fabs(d[iq]))
a[ip][iq]=0.0;
else if (fabs(a[ip][iq]) > tresh) {
h=d[iq]-d[ip];
if ((double)(fabs(h)+g) == (double)fabs(h))
t=(a[ip][iq])/h;
else{
theta=0.5*h/(a[ip][iq]);
t=1.0/(fabs(theta)+sqrt(1.0+theta*theta));
if (theta < 0.0) t = -t;
}
c=1.0/sqrt(1+t*t);
s=t*c;
tau=s/(1.0+c);
h=t*a[ip][iq];
z[ip] -= h;
z[iq] += h;
d[ip] -= h;
d[iq] += h;
a[ip][iq]=0.0;
for (j=1;j<=ip-1;j++){
ROTATE(a,j,ip,j,iq)
}
for (j=ip+1;j<=iq-1;j++){
ROTATE(a,ip,j,j,iq)
}
for (j=iq+1;j<=n;j++){
ROTATE(a,ip,j,iq,j)
}
for (j=1;j<=n;j++){
ROTATE(v,j,ip,j,iq)
}
++(*nrot);
}
}
}
for (ip=1;ip<=n;ip++){
b[ip] += z[ip];
d[ip]=b[ip];
z[ip]=0.0;
}
}
printf("too many iterations in routine jacobi \n");
}
//EOD
void eigsrt(double *d, double **v, int n)
{
int k,j,i;
double p;
for (i=1;i<n;i++)
{
p=d[k=i];
for (j=i+1;j<=n;j++)
if (d[j] >= p) p=d[k=j];
if (k != i)
{
d[k]=d[i];
d[i]=p;
for (j=1;j<=n;j++)
{
p=v[j][i];
v[j][i]=v[j][k];
v[j][k]=p;
}
}
}
}
Conclusion :
Bon ne m'en veuillez pas trop si la presentation et les commentaires ne sont pas parfaits.
NB: Ce code a etait fait en colaboration avec 'le Grec'.
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.