Lab 6 - fonction my_edo

Lab 6 - fonction my_edo

par Thomas Cosgrove,
Nombre de réponses : 7

Bonjour,

j'ai un problème avec la fonction my_edo.m à la question 1. J'essaie d'implémenter une boucle if afin de tenir compte de la fonction x''(t) par parties, mais la fonction ne va jamais au 'else' malgré que la condition x(t) > 150 soit rencontrée. Le résultat final est que mon sauteur ne se stabilise jamais car la même partie de x(t) est utilisée pour toute valeur de (t).

Merci!

En réponse à Thomas Cosgrove

Re: Lab 6 - fonction my_edo

par Daniel Lévesque,
Bonjour,

Il faudra faire deux choses:

1. S'assurer que l'information qui entre et qui sort de la fonction my_edo.m est bien en accord avec ce que la boucle essaie de faire (scalaires, vecteurs, matrices,... ?). Donc, quelques évaluations à la main de la fonction règle ce problème rapidement (un simple test bidon pour voir si tout fonctionne comme prévu);
2. Faire afficher le résultat de chaque étape de calcul. Donc pas de point-virgule (;) et c'est même une bonne idée d'inclure l'affichage de tous les paramètre utilisés pour savoir exactement où est rendu le code lors du calcul. Attention! il faut y aller avec peu d'itérations au début pour ne pas inonder le command window (imprimer le résultat dans un fichier de sortie est une excellente idée!). Ensuite, on passe à travers chaque élément affiché et y a fort à parier qu'on trouvera un affichage qui ne correspond pas à ce qu'on essai de faire. Il suffit ensuite de le corriger et de recommencer la procédure jusqu'à ce que ça fonctionne.

En bref, ça ne fonctionne pas parce que soit le code ne fait pas ce que vous voulez qu'il fasse ou soit parce que vous n'êtes pas certain de l'utilisation d'un élément du code (comme my_edo.m). Ça peut-être un mélange des deux aussi. La méthode de débugage que je propose fonctionne très bien pour régler ce genre de problème parce que ça vous force à bien comprendre chaque calcul que fait votre code. Donc vous allez travailler un peu plus, mais vous maîtriserez votre code sur le bout des doigts et surtout il fonctionnera comme prévu (deux choses qu'il faut avoir de toute façon).

Souvent pour le travail je dois me servir de codes que je n'ai pas écrit et que je n'ai pas le temps d'écrire, souvent dans un langage que je ne connais pas. Quand il y a un bug ou que je ne réussi pas à obtenir ce que je cherche du code rapidement, je dois trouver pourquoi. La méthode que je viens de décrire plus haut est la meilleure approche pour faire ça. Ça paraît long au début, mais c'est un peu comme le lièvre et la tortue; le lièvre fini toujours par trébucher sur les fleurs du tapis.

Après avoir essayé cette approche, vous aurez des questions plus précises si ça ne fonctionne toujours pas. Vous aurez aussi plus d'information particulières sur le problème. On sera alors en mesure de mieux vous aider avec ces informations en main.

Bon travail!
En réponse à Daniel Lévesque

Re: Lab 6 - fonction my_edo

par Thomas Cosgrove,
Bonjour,
J'utilise la fonction la fonction suivante pour poser mon système d'équations :
function [ f ] = my_edo_ex1( t , z )
m = 70;
g = 9.8;
k = 0.227;
%ici, Z1 = x(t) et Z2 = x'(t)
f(1) = z(2);
%La forme de Z2' change en fonction de la valeur de x(t) = Z1
if z(1) <= 150
f(2) = g - ((sign(z(2))*k*z(2)^2))/m;
else
f(2) = g - ((sign(z(2))*k*z(2)^2)-10*(z(1)-150)-(7*z(2)))/m;
end
end
z(1) atteint une valeur supérieure à 150 après 28 itérations de rk4.m, et entre effectivement dans le 'else'. Je ne comprend pas toutefois pas encore pourquoi les valeurs de positions et de vitesse de ne stabilisent pas.
Elle n'arrêtent jamais de croître.

Mon appel de rk4.m est le suivant :
[time_rk_ex1,x_rk_ex1] = rk4('my_edo_ex1',[0 100],[0 0],100);
la matrice x_rk_ex1 contient les valeurs de Z1 = x(t) et Z2 = x'(t) à chaque pas de temps. Je m'en suis donc servi pour calculer x''(t), mais celle-ci croît constamment aussi.

J'ai appelé et utilisé rk4 et my_edo de la même façon dans les exercices du labo et au #2 avec succès.

Merci!
En réponse à Thomas Cosgrove

Re: Lab 6 - fonction my_edo

par Daniel Lévesque,
Bonjour,

Donc, si ça fonctionnait pour le labo et le #2 il faut regarder ce qui a été modifié pour cette question. Comme vous n'avez pas à modifier la fonction rk4, il faudrait vérifier que my_edo.m fait bien ce qu'elle est supposée faire...

indice: z(1) atteint une valeur supérieure à 150 après 28 itérations de rk4.m, et entre effectivement dans le 'else'. Je ne comprend pas toutefois pas encore pourquoi les valeurs de positions et de vitesse de ne stabilisent pas.
Elle n'arrêtent jamais de croître.

C'est comme je disais dans mon message précédent: il faut vraiment aller voir chaque élément de calcul (entrée et sortie) pour comprendre quelle partie du code ne fait pas son travail. Donc c'est bien, on a déjà un indice sur le fait qu'un valeur ne cesse de croître, mais on ne sait pas encore vraiment d'où ça vient. Il faut continuer de fouiller chaque partie du code pour le trouver. Par exemple, ici l'indice c'est que my_edo.m est remise en cause. Il faut donc isoler cette composante du code et faire quelques évaluations à la main et comparer avec ce que la fonction donne dans Matlab.

Par exemple, on sait que my_edo.m représente la force exercée sur notre sauteur. On peut évaluer quelques valeurs de cette force à la main (des valeurs simples juste pour tester) et voir si my_edo.m donne le même résultat. Si on n'a pas le même résultat c'est génial parce qu'on vient de trouver le problème, il suffit de le corriger. Si tout est en accord avec les calculs à la main il faut passer au prochain élément du code.

autre indice: si la position ne cesse de croître, c'est qu'une force est appliquée pour permettre cette croissance. Donc soit que le modèle est faux (il est valide, je l'ai vérifié), soit y a une force de mal écrite... wink wink ...

Bon travail!
En réponse à Daniel Lévesque

Re: Lab 6 - fonction my_edo

par Julien Sabourin-Jean,
Salut,

J'ai eu le même problème que M. Thomas. J'avais exactement le même code, moi aussi mes valeurs ne convergeaient pas. Et tout d'un coup, entre 2 tests, ça a fonctionné sans que je ne modifie mon code.

Ce que j'ai fait :
-J'ai ajouté pour le fun une variable dans mon code de my_edo. Lorsqu'on est dans la condition : f(2) = g - ((sign(z(2))*k*z(2)^2)-10*(z(1)-150)-(7*z(2)))/m; j'ai rajouté *m au 7*z(2)
-J'obtiens alors f(2) = g - ((sign(z(2))*k*z(2)^2)-10*(z(1)-150)-(7*z(2)*m))/m;
-Puis, par hasard, j'ai fait la commande ''annuler'' (Ctrl+Z) une fois;
-Cela m'a ramené à mon code initial;

Et expliquez-moi pourquoi, mon code s'est mis a fonctionné et j'arrivais à une convergence. Donc, pour ma part, je crois que mon problème était matlab en tant que tel et non mon code. Je ne peux pas dire si cela est ton cas, mais moi ça a fonctionné. Honnêtement, c'est vraiment bizarre.

J'espère que ça t'aidera
En réponse à Daniel Lévesque

Re: Lab 6 - fonction my_edo

par Thomas Cosgrove,
J'ai trouvé une erreur dans une force qui fait qu'au lieu d'avoir des valeurs croissantes, elle oscillent, ce qui est un pas dans le bon sens. Il n'y a toutefois pas d'amortissement, dont l'expression devrait être celle de la friction visqueuse de la corde = -7*x'(t). Le seul moyen que je reussi à faire stabiliser le sauteur est en ajoutant un sign(z(2)) devant le R = -7*z(2)

Merci!
En réponse à Thomas Cosgrove

Re: Lab 6 - fonction my_edo

par Daniel Lévesque,
Bon travail messieurs, vous y êtes presque!

99% du temps le problème est beaucoup moins compliquer qu'on le pense. Croyez-moi, j'ai assez d'imagination pour croire que des forces mystérieuses sont à l'oeuvre dans mon code où bien qu'un phénomène étrange vient s'immiscer dans mon modèle. Quand on est rendu à ce stade (comme penser que c'est de la faute de l'ordinateur ou peut-être la façon qu'on appuie sur une touche du clavier, et je dis ça en m'incluant... sans blague) c'est qu'on se fait des idées et qu'il faut simplement revenir sur nos vérifications: on n'a pas trouvé l'erreur la première fois, il faut chercher l'erreur à nouveau. Je dis ça avec beaucoup d'humour bien sûr, je le vis assez souvent.

Par exemple, Julien a trouvé que quelque chose cloche avec le bout de code: f(2) = g - ((sign(z(2))*k*z(2)^2)-10*(z(1)-150)-(7*z(2)*m))/m;
Étrangement, Thomas voit aussi un problème avec ce bout de code. Une coïncidence? Non, vraiment pas! Puisque je me permet de faire un peu d'humour, je vais aussi être honnête. Quand j'ai pris le temps de me faire un bout de code rapide pour voir ce qui pourrait clocher avec votre démarche plus tôt aujourd'hui, je me suis retrouvé à inverser le signe de certains termes du système. J'ai donc aussi constaté une croissance de la variable position et ainsi, bye bye sauteur! J'ai vite réalisé (parce que je sais que je fais 10 erreurs par ligne de code...) qu'en écrivant f(2) j'ai modifié le terme de droite avec des parenthèses après l'avoir écrit pour inclure le facteur 1/m qui vient de la gauche de l'équation différentielle. Et donc les parenthèses que j'ai ajoutées pour n'écrire qu'une seule fois 1/m ont du même coup transformé les signes négatifs en signes positifs. C'est exactement ce que je voulais dire quand je parlais du lièvre qui trébuche sur les fleurs du tapis!

Donc, avez-vous comptabilisé vos parenthèses? Avez-vous essayé d'écrire au long l'expression DANS VOTRE CODE pour être certain de ne pas avoir fait l'erreur?

J'ai réussi à trouver le problème rapidement dans mon code parce que j'ai compris que la force n'était pas bonne (grandit au lieu de diminuer, interprétation physique qui vient de l'expérience) et aussi parce que j'ai abusé un peu trop des parenthèses pour sauver du temps. Si on comptabilise le temps que vous avez pris à tourner en rond avec ce problème, on comprend rapidement qu'il faut écrire ses programmes comme une tortue et clarifier tout au maximum parce que inévitablement on devra y revenir pour corriger un bug..

Bon travail!
En réponse à Daniel Lévesque

Re: Lab 6 - fonction my_edo

par Thomas Cosgrove,
J'ai fini par y arriver en subdivisant l'équation en 3 termes de forces différents et en calculant séparément chaque terme pour ne pas avoir 57 parenthèses.

Merci pour votre aide!