Scilab : un logiciel libre pour le calcul scientifique  · Web view2007-01-07 · Scilab est un...

36
Scilab un logiciel libre pour le calcul scientifique LPA et MPA - 1 -

Transcript of Scilab : un logiciel libre pour le calcul scientifique  · Web view2007-01-07 · Scilab est un...

Scilabun logiciel libre pour le calcul scientifique

LPA et MPA

- 1 -

Chapitre 1 : Présentation de Scilab1   Calcul scientifique, symbolique ou numérique ?

On trouve sur le marché deux types de logiciels de calcul scientifique, les logiciels de calcul symbolique qui, en gros, ``font des maths'' et les logiciels de calcul numérique, qui sont faits plutôt pour les applications des maths. Dans la première catégorie on trouve entre autres Maple, Mathematica et MuPad. Ce dernier offre des licences gratuites aux étudiants et aux chercheurs. Ces logiciels sont utilisés depuis quelques années dans les classes prépas scientifiques. Dans la deuxième catégorie, où le marché est plus large, on trouve essentiellement les logiciels commerciaux (et très chers !) Matlab et Xmath et maintenant Scilab qui est un logiciel libre (et tout aussi puissant que ses concurrents), distribué avec son code source. Scilab a été développé par des chercheurs de l'INRIA et de l'ENPC pour des applications industrielles et comme outil de recherche (développement et tests d'algorithmes). Alors que les logiciels de calcul symbolique font des calculs exacts avec des gros nombres entiers (des ``bignums'' selon la terminologie anglosaxonne), les logiciels numériques font eux leurs calculs avec des nombres flottants et la vitesse de calcul est essentielle. Par exemple, pour inverser une matrice de polynômes de taille 10 x 10 contenant des nombres flottants, Maple va vite jeter l'éponge alors que Scilab va donner le résultat immédiatement. Au contraire Scilab est incapable de trouver la dérivée symbolique de la fonction sinus ! A chacun son domaine...Vous pouvez télécharger Scilab depuis: http://www.istia.univ-angers.fr/~jaulin/scilab.html.

2   Qu'est-ce que Scilab ?

Scilab est un puissant environnement de programmation interactif pour le calcul numérique. C'est un gros logiciel : environ 13 000 fichiers, plus de 400 000 lignes de code source (en C et Fortran), 70 000 lignes de code Scilab (librairies spécialisées), 80 000 lignes de ``man'' (help en ligne et doc). Scilab comporte un langage de programmation et un interpréteur qui travaille sur des objets de type numériques mais pouvant être structurés selon les besoins de l'utilisateur. C'est un système complètement ouvert, puisque c'est l'utilisateur qui définit ses propres fonctions à partir des puissantes primitives de calcul qui sont fournies.

3   Comment démarrer ?

Au démarrage, on obtient l’écran représenté ci-dessous

Figure 1: La fenêtre principale Scilab

A l'invite (le ``prompt'') notée -->, on passe une commande, Scilab donne le résultat puis redonne -->. Après avoir passé quelques commandes, les premiers pas se font en cliquant sur le bouton ``démos''. En observant les démos, on commence à voir les capacités du logiciel. On comprend vite que les objets manipulés sont surtout des vecteurs et des matrices numériques, ce qui donne un code très compact avec des notations matricielles naturelles. En fait, la syntaxe de Scilab est identique à la syntaxe de Matlab pour tout ce qui concerne les manipulations sur les vecteurs et les matrices. Le gain par rapport à un codage en C (ou Fortran) est énorme : pas de déclaration de types, pas de compilation, ni d'allocation de mémoire, tout est automatique. Le prix à payer est bien sûr celui de l'interprétation qui peut devenir très cher pour certaines

- 2 -

applications. Un help en ligne est disponible; il donne la syntaxe d'appel des différentes fonctions (il y en a plus de mille...). La plupart des fonctions sont illustrées par un exemple qu'on peut faire tourner par un simple copier-coller à la souris depuis la fenêtre de help vers la fenêtre Scilab. Les démos donnent des exemples de graphiques, de traitement du signal, de commande, et de simulation de systèmes dont la célèbre démo du vélo, qui montre la simulation d'un vélo à partir des équations mathématiques d'un vélo idéal se déplaçant sans frottement sur une surface plane. Les équations du vélo ont été obtenues à l'aide de Maple qui génère aussi le programme numérique exploité directement par Scilab.

4   Un système ouvert

Scilab se veut avant tout un système ouvert. Pour tirer profit au mieux du logiciel, l' utilisateur doit apprendre à utiliser le langage Scilab pour développer ses applications. En général, un programme Scilab se compose de quelques lignes car les primitives de calcul et de manipulation d'objets fournies sont nombreuses et puissantes. Ces programmes sont définis dans des fichiers que l'utilisateur construit à l'aide de son éditeur préféré, puis chargés dans Scilab. Cela se fait à la souris (Menu File opérations) ou directement par la commande getf. Un fichier peut bien sûr contenir un nombre arbitraire de fonctions Scilab. L'utilisateur standard de Scilab passe souvent l'essentiel de son temps à définir et mettre au point ses fonctions en faisant de nombreux allers-retours entre son éditeur et Scilab.En plus des vecteurs et des matrices (qui peuvent contenir des nombres réels ou complexes, des chaînes de caractères, des polynômes, ...), on peut définir des objets plus complexes à partir de listes typées ou non. Ces objets peuvent être manipulés à leur tour par des opérateurs définis par l'utilisateur. Enfin l'utilisateur peut rajouter à Scilab des fonctions écrites en langage C (ou Fortran). Il peut alors linker dynamiquement son application à Scilab. Un répertoire examples donne (comme son nom l'indique) de nombreux exemples de fonctions linkées dynamiquement à Scilab. Les utilisateurs habitués à Matlab y trouveront même des fonctions émulant les fonctions d'interfaçage Matlab.

5   Le graphique

Figure 2: Un plot3d

Le graphique sous Scilab est assez déroutant pour le débutant et un investissement important est nécessaire pour appréhender l'ensemble des primitives graphiques dont l'usage ``brut'' semble peu convivial. La meilleure façon de démarrer est encore de faire tourner les démos graphiques, de repérer celle qui ressemble le plus à ce que l'on veut faire, puis de modifier le script proposé dans la démo pour l'adapter à ses besoins dans une nouvelle fonction. On peut faire des graphiques 2D et 3D, des tracés de contours, des tracés paramétriques, des animations, etc. Les graphiques peuvent être exportés au format Xfig, Postscript, Gif et Postscript-Latex. La figure 2 est tirée d'une des démo graphique est obtenue en quelques lignes de code par la commande primitive graphique plot3d2.L'application Scicos, qui est une boite à outils dont l'éditeur graphique est entièrement écrit en Scilab illustre bien les puissantes capacités du graphique. Cette application est une interface bloc-diagramme pour la simulation de systèmes dynamiques interconnectés. C'est l'analogue du logiciel Simulink de Matlab (mais Simulink n'est pas fourni en standard dans la distribution de Matlab : il faut payer une licence supplémentaire spécifique). Cet outil est très utilisé en milieu industriel (par exemple à EDF) pour simuler des systèmes complexes. La figure 3 montre un très simple diagramme Scicos. La première préoccupation de l'utilisateur est de définir un modèle de simulation pour le système qu'il étudie (ce qui peut être aussi bien un moteur de voiture qu'une centrale électrique) et de regarder si les simulations faites avec son modèle correspondent bien à la réalité...

- 3 -

6   Les boites à outils

Figure 3: Un schéma Scicos

En plus de Scicos, Scilab fournit des boites à outils dans la plupart des domaines de l'ingénierie : traitement du signal, commande, optimisation, graphes, analyse fractale, calcul parallèle, statistique, etc... Ces boites à outils sont bien sûr fournies avec la version distribuée de Scilab. À ces boites à outils s'ajoutent des contributions extérieures : l' objectif de Scilab est bien de fournir une structure d'accueil gratuite pour toutes sortes d'applications scientifiques. Les bonnes volontés sont donc mises à contribution. C'est le principe du logiciel libre : qualité et mise en commun des efforts.

- 4 -

Chapitre 2 : Premiers pas sous Scilab1. Mode calculatrice

Dans Scilab, la plupart du temps on manipule des vecteurs et des matrices. Les opérateurs et les fonctions élémentaires sont conçus pour favoriser ce type de manipulation et de manière plus générale, de permettre la vectorisation des programmes. Certes le langage Scilab contient des opérations conditionnelles (if-then-else-elseif), des boucles (while, for) et la programmation récursive, mais la vectorisation permet de limiter le recours à ces fonctionnalités qui ne sont jamais très efficaces dans le cas d'un langage interprété. Par exemple, pour tracer la fonction cos(2x2) entre 0 et 5, on peut définir sans boucle le vecteur contenant les points à afficher, de la manière suivante :

-->x=[0:999]*5/1000;On peut, par la suite, utiliser ce vecteur pour évaluer la fonction et tracer la courbe (Fig. 1) :

-->y=cos(2*x^2); -->plot2d(x,y)

Figure 1: Exemple d'un plot2d

L'opérateur <<:>> dans [0:999] permet de définir un vecteur d'entiers allant de 0 à 999. On peut trouver, sans aucune boucle, les points où la fonction cos(2x2) est extrémale en utilisant le fait que la dérivée aux points extrêmes change de signe. On calcule d'abord le vecteur dy dont les composantes sont yi+1-yi, puis le vecteur p contenant (yi+1-yi)(yi+2-yi+1) et enfin on cherche les composantes négatives de p :

-->dy=y(2:$)-y(1:$-1);-->p=dy(1:$-1).*dy(2:$); -->x_ext=x(find(p<=0)) x_ext = column 1 to 8 ! 1.25 1.765 2.165 2.5 2.795 3.065 3.31 3.54 !

column 9 to 15 ! 3.755 3.96 4.15 4.335 4.515 4.685 4.85 !L'opérateur <<$>> désigne l'indice du dernier élément (1000 dans le cas de y et 999 dans le cas de dy) et l'opérateur <<.*>> désigne le produit élément par élément. Le résultat de p<=0 est un vecteur de booléens dont les indices correspondant aux éléments ayant la valeur vraie (%t en Scilab) sont déterminés par la fonction find .L'absence de <<;>> à la fin de la dernière instruction actionne l'affichage du résultat. Les graphiques 3D sont aussi souvent réalisés en utilisant des opérations matricielles. Par exemple pour tracer la surface f(x,y)=10sin(x)cos(y), 0 x < , 0 y < 2, on peut faire:

-->x=[0:99]*%pi/100;y=[0:99]*2*%pi/100;-->M=10*sin(x)'*cos(y);plot3d(x,y,M)

- 5 -

Figure 2: plot3d de la fonction 10sin(x)cos(y)

L'opérateur <<'>> correspond à la transposition donc sin(x)'*cos(y) est le produit d'un vecteur colonne de taille 100 par un vecteur ligne de taille 100, ce qui est une matrices à 10000 éléments. Par des opérations de souris et en utilisant les menus de la fenêtre graphique, on peut faire tourner le plot 3D (Fig. 2) dans l'espace pour obtenir un point de vue optimal et sauver le résultat en divers formats (Postscript, xfig, gif, ...).

2. La programmation

Un programme Scilab correspond à l'enchaînement d'une suite d'instructions. Ces instructions peuvent être placées dans un fichier (qu'on appelle un script) à l'aide d'un éditeur de texte. Si on nomme par exemple le fichier toto.sce , on peut alors exécuter le script avec l'instruction :

-->exec toto.sce // vous pouvez aussi procéder avec le menu de scilab (file/exec)Il faut auparavant mettre Scilab sous le répertoire où vous avez sauver votre fichier (menu file/change directory)Scilab permet aussi de définir de nouvelles fonctions. Le mot-clé function est utilisé pour déclarer le début d'une fonction dans un fichier texte.

function v=mafonc(v,op)// cette fonction recoit un vecteur v et une chaine de caracteres indiquant// l'operation a effectuer sur vif v==[ ] then return;endselect opcase "aleatoire" then vrand=rand(v); // rand est un generateur de nombre aleatoire [junk,ind]=sort(vrand); v=v(ind);case "decroissant" then v=sort(v);case "croissant" then v=-sort(-v);end

Noter l'utilisation de <<//>> pour indiquer les commentaires. La fonction mafonc, définie dans le fichier mafonc.sci peut alors être <<chargée>> et utilisée dans Scilab comme suit :

-->getf mafonc.sci // vous pouvez aussi procéder avec le menu de scilab (file/getf)-->y=mafonc([2,5,4],"aleatoire")

y = ! 5. 2. 4. !Il existe aussi la possibilité de définir des fonctions <<en-ligne>>. Par exemple l'instruction sort(x) trie les éléments de x dans l'ordre décroissant. On peut alors facilement définir en ligne la fonction trie qui trie dans l'ordre croissant:

-->deff("y=trie(x)","y=-sort(-x)")Une fonction est un objet dans Scilab au même titre qu'un vecteur ou une matrice de chaîne de caractères. Dans l'exemple suivant, on passe une fonction comme argument d'une autre fonction :

function x=bubble(x,fun)// cette fonction realise un trie à bulle ; x est un vecteur de nombres complexes// fun est une fonction définissant la relation d'ordre a utiliser n=size(x,"*"); // n est le produit des 2 dimensions de xfini=%f; //f comme falsewhile ~fini fini=%t for i=1:n-1 if fun(x(i),x(i+1)) then

- 6 -

tmp=x(i); x(i)=x(i+1); x(i+1)=tmp; fini=%f end endend

Pour utiliser cette fonction, il faut d'abord définir une fonction définissant la relation d'ordre choisie, par exemple la relation d'ordre correspondant à la norme :

function test=cmp_nrm(a,b)test=norm(a)>norm(b); // test est booleen

Alors pour trier un vecteur de nombres complexes suivant leurs normes, il suffit de charger les deux fonctions et de faire par exemple :

-->bubble([1+%i,2,4*%i],cmp_nrm) ans = ! 1.+ i 2. 4.i !

La fonction bubble a peu d'intérêt dans ce cas car le tri des vecteurs peut en général se faire de manière plus efficace par vectorisation. Mais si la structure à trier contient des éléments autres que des simples scalaires, elle peut être très utile. Mais pour cela il faut modifier bubble pour qu'il accepte des structures. Une façon de coder des structures dans Scilab est d'utiliser la commande list. Une structure peut contenir des objets hétérogènes : des matrices, des chaînes de caractères, des booléens, des polynômes, et même d'autres structures. Les éléments d'une structure peuvent être manipulés presque comme ceux d'un vecteur, donc les modifications à faire dans bubble sont minimes ; en particulier il suffit de remplacer size(x,"*") par size(x) car contrairement aux vecteurs, qui ne sont que des matrices particulières, les structures n'ont qu'une seule dimension. En utilisant la même fonction cmp_nrm, on peut maintenant (ayant fait la modification dans bubble), trier des matrices selon leur norme comme suit :

-->ll=list(rand(2,3),[1,2;5,4],eye(2,2));-->ln=bubble(ll,cmp_nrm) ln = ln(1) ! 1. 0. !

! 0. 1. !ln(2) ! 0.84974 0.87821 0.56084 !

! 0.68573 0.06837 0.66235 !ln(3) ! 1. 2. !

! 5. 4. !Scilab contient des centaines de fonctions préprogrammées pour résoudre des problèmes mathématiques spécifiques. Mais toutes les fonctions ne sont pas écrites en langage Scilab. Les fonctions très élémentaires et les fonctions pour lesquelles la vitesse d'exécution est un facteur crucial (par exemple l'inversion d'une matrice) sont codées en dur (en C ou fortran). On appelle ces fonctions des primitives. L'utilisateur peut aussi écrire ses programmes en dur et les interfacer avec Scilab. Cela peut se faire en utilisant les fonctions link ou addinter pour définir de nouvelles primitives.

3. L'interface utilisateur

Scilab permet de développer des applications interactives complètes. Pour cela, il propose des boîtes de dialogues programmables. Par exemple :

-->age=x_dialog(["Quel est votre age ?"],"18")

et d'autres fonctions de ce type comme x_message, x_choose, etc... On peut aussi, de manière dynamique, rajouter des boutons et des menus aussi bien à la fenêtre principale Scilab qu'aux fenêtres graphiques. Dans les fenêtres graphiques, on a accès aux événements souris (position de la souris, bouton pressé, etc...). Pour mieux comprendre l'étendue de ces fonctionnalités, il suffit de lancer la démo Scicos qui est un éditeur schéma-bloc et un simulateur de systèmes dynamiques dont l'éditeur est écrit entièrement en Scilab.

4. Comment obtenir de l'aide

- 7 -

Scilab contient un manuel en ligne. Pour obtenir de l'aide sur une fonction dont on connaît le nom, par exemple plot2d, il suffit de faire :

-->help plot2d La page du manuel correspondant à plot2d s'ouvre alors dans une fenêtre. Si on ne connaît pas le nom de la fonction, on peut faire une recherche par mots-clés, par exemple :

-->apropos plotOn obtient alors la liste des fonctions contenant plot comme mot-clé (les mots-clés sont bien-entendu en anglais). On peut aussi accéder à ces fonctionnalités en cliquant sur le bouton help de la fenêtre principale de Scilab. Dans ce cas, on obtient, en plus, une liste souvent très utile des fonctions classées par thème. Il existe aussi un ensemble de démos des applications types disponibles depuis les menus de la fenêtre principale. Il existe aussi des manuels (en anglais) disponibles par ftp anonyme qui décrivent différentes applications de Scilab.

- 8 -

Chapitre 3 : Debug en Scilab

Tout programmeur sait bien que l'écriture de code s'accompagne inévitablement de bugs qui commencent avec l'erreur de syntaxe pour aller à un résultat faux sans qu'il soit toujours évident de trier entre une erreur de programmation (le programme "ne fait pas ce que je crois") et une erreur d'algorithme (ce que j'ai écrit est correct, fais bien ce que je souhaitais mais ne résout pas le problème que je souhaitais résoudre). Enfin il y a parfois à comprendre plus précisément ce que fait une fonction de Scilab et même (sait-on jamais ?!) à découvrir un bug de Scilab. Il y a dans Scilab un certain nombre de fonctions qui permettent de suivre l'exécution de programmes et de localiser les erreurs. Prenons un exemple très simple de fonction :

function [y]=bisq(x,a,b,c)xx=x.*x;y=a*xx**2+b*xx+c;return--> a=1;b=2;c=-4; --> xres=fsolve(100,bisq)xres = 1.1117859

La première fonctionnalité consiste à interrompre l'exécution d'une fonction écrite en langage Scilab. Il y a pour cela 3 possibilités : une commande clavier et deux commandes programmées. La commande clavier est Ctrl-c et les commandes programmées sont setbpt et pause. La commande pause doit être insérée dans le code de la fonction (ce qui nécessite un nouveau chargement de la fonction) à l'endroit souhaité alors que la commande setbpt (place un point d'arrêt ou breakpoint) est une commande extérieure à la fonction qui ne modifie pas son code source.

a=1;b=2;c=-4;x=10;-->bisq(x,a,b,c) ans = 10196. -->setbpt('bisq',2)-->bisq(x,a,b,c)Stop after row 2 in function bisq :-1->

Le prompt -1-> signifie que nous sommes maintenant au niveau 1 d'interruption (on peut donc avoir plusieurs niveaux). A ce niveau on se trouve dans la situation de départ d'une nouvelle session de Scilab. On peut faire toutes les manipulations souhaitées sans affecter le niveau inférieur. Ce qui est essentiel c'est que l'on a accès ``en lecture'' à toutes les variables du niveau inférieur. La commande setbpt('bisq',2) a eu le même effet que l'insertion de la commande pause après la deuxième ligne de la fonction bisq. Les variables du niveau inférieur doivent être "remontées" au niveau d'interruption : la manière la plus simple consiste à taper leur nom suivi de ; pour éviter l'affichage :

-1->a;On redescend au niveau inférieur et on reprend l'exécution interrompue par la commande resume (ou return ) :

-1->resume ans = 10196.

Mais on peut modifier des variables du niveau inférieur à partir du niveau d'interruption par la commande resume en lui donnant comme paramètre les noms des variables modifiées; dans le cas précédent on peu faire :

-->y=bisq(x,a,b,c)Stop after row 2 in function bisq :-1->a=5;b=0.;-1->[a,b]=resume(a,b) y = 49996.

On peut revenir directement au niveau 0 par la commande abort. Les points d'arrêt sont listés par la commande dispbpt et libérés par la commande delbpt :

-->dispbpt() breakpoints of function :bisq 2-->delbpt('bisq',2)

Lorsqu'on utilise Ctrl-c pour interrompre l'exécution de longs programmes il est utile de localiser l'endroit où l'interruption s'est produite par la commande whereami :

- 9 -

-1->whereami() // En francais : Ou suis-je ?whereami called under pausepause called at line 3 of macro bisq

Si une fonction est une fonction des librairies Scilab on peut localiser cette fonction par :

-->whereis('median') ans = elemlib

On peut alors connaître le chemin d'accès à cette librairie ainsi que la liste de toutes les fonctions de la librairie en tapant simplement le nom de la librairie :

-->elemlib elemlib = Functions files location :SCI/macros/elem/ and atanm atanhm atanh asinhm asinh asinm asin acoshm acosh acosm acos cosm cothm coth cotg coshm cosh erfcx erfc erf fix GLoad intersect isnan isinf inttrap intsplin integrate intc intl interpln lex_sort logm log10 mean median modulo null or pertrans setdiff st_deviation spones sprand spzeros speye squarewave smooth sqrtm sinm signm sinhm sinh toeplitz tanhm tanh tanm tan union unique

Il y a, bien sûr, quelques commandes qui donnent des renseignements sur les variables utilisées :

-->whoyour variables are...

typeof whos y x xres c b a bisq startup ierr MODE_X scicos_pal %helps MSDOS home PWD TMPDIR percentlib fraclablib soundlib xdesslib utillib tdcslib siglib s2flib roblib optlib metalib elemlib commlib polylib autolib armalib alglib intlib mtlblib SCI %F %T %z %s %nan %inf old newstacksize $ %t %f %eps %io %i %e

using 6196 elements out of 1000000 and 54 variables out of 1071La commande who fournit la liste des variables et librairies utilisées ainsi que la place mémoire utilisée dans la pile (avec la taille de cette dernière qui peut être également obtenue par stacksize() ). La commande whos est plus précise : elle donne en plus le type des variables, fonctions et librairies utilisées avec leur taille et la place mémoire occupée.

-->whos()Name Type Size Bytes typeof compiled function 3088 whos compiled function 5736 y constant matrix 1 by 1 24 x constant matrix 1 by 1 24 xres constant matrix 1 by 1 24 .................................TMPDIR string 1 by 1 80 percentlib library 8920 fraclablib library 1504 soundlib library 272

Lors de l'écriture de programmes multiples il peut être intéressant de savoir si un nom de variable est déjà utilisé ou quel est le type d'une variable :

-->exists('x') ans = 1. -->type(x) ans = 1.-->typeof(x)

- 10 -

ans = constantOn peut également libérer la place mémoire occupée par un variable en la détruisant par la commande clear.Certaines erreurs dépendent de l'environnement, c'est à dire qu'elles ne se produisent que pour certaines valeurs des paramètres. Or, pour corriger une erreur il faut pouvoir la reproduire : pour cette opération il est commode d'utiliser les fonctions save et load. En utilisation courante ces fonctions permettent d'écrire et de recharger des résultats de manière efficace (en format binaire). L'appel le plus simple save('nom de fichier') permet de sauver toutes les variables utilisées pour recharger ensuite cet environnement et reproduire une erreur éventuelle.

- 11 -

Chapitre 4 : - Simulation de systèmes dynamiques

1   Systèmes dynamiques

L'évolution de son compte d'épargne logement, la gestion de ses actions ou la trajectoire de la fusée Ariane sont des exemples de systèmes dynamiques. Un tel système évolue avec le temps t. On part d'un instant t=t0 et on se demande comment le système va se comporter dans le futur : combien j'aurai d'argent sur mon compte, mes actions vont-elles monter ou baisser, la fusée va-t'elle poursuivre la trajectoire prévue et le virus va-t'il se développer ou disparaître ? Et tout cela en fonction d'un certain nombre de paramètres. C'est ce qu'on appelle la simulation du système dynamique.

Pour résoudre ces problèmes, on utilise un modèle mathématique qui va représenter au mieux le phénomène que l'on veut simuler. Les équations différentielles sont un des modèles les plus courants pour représenter les systèmes dynamiques. Nous sommes donc amenés à la résolution de celles-ci. Le premier réflexe est d'utiliser un système de calcul formel pour cela (ces systèmes, comme Maple ou MuPAD par exemple, permettent de réaliser des calculs mathématiques symboliques et exacts). On obtiendrait ainsi la fonction solution de l'équation et il n'y aurait plus qu'à l'utiliser pour trouver la solution. Par exemple, la masse y(t) d'une substance radioactive qui se décompose avec un taux par unité de masse est modélisée par l'équation différentielle linéaire :

y'(t)=  y(t) y(t0)=y0

où y0 représente la masse à l'instant t0. Ici et dans toute la suite y'(t) représentera la dérivée de y par rapport au temps t. On peut résoudre explicitement cette équation différentielle dont la solution est y(t)=y0exp((t-t0)). Il est alors facile de connaître l'évolution de la masse y(t) puisque l'on a son expression. Malheureusement, dans la majorité des cas, on n'aura pas cette chance et il sera impossible de trouver une fonction solution de l'équation différentielle. C'est le cas pour la simple équation différentielle suivante :

y'(t)=y2(t)-t y(t0)=y0

(1)

que nous étudierons plus loin. Dans ce cas, seule une résolution numérique (à opposer avec une résolution purement symbolique) est possible. Et il faut avoir une grande efficacité pour obtenir la solution en un temps le plus court possible pour traiter des problèmes de grande taille : en effet on aura la plupart du temps non pas une équation différentielle à résoudre, mais un système d'équations différentielles (c'est-à-dire plusieurs équations différentielles couplées, voir le paragraphe 2.2) sur un grand nombre de pas de temps. En général, cela est difficile voire impossible à réaliser dans un système de calcul formel. De plus, il faut pouvoir résoudre la plus grande classe de problèmes possibles : c'est là qu'un système comme Scilab avec ses solveurs est indispensable. De plus, après la résolution numérique, c'est généralement en traçant des courbes que l'on va réellement voir l'évolution avec le temps du résultat : Scilab est parfaitement équipé pour ça et c'est ce que nous allons voir dans les paragraphes suivants.

2   Le solveur ODE

La fonction ode est la fonction principale de résolution de systèmes d'équations différentielles. C'est en fait une interface à une famille de solveurs appelés ODEPACK. Nous allons voir deux exemples d'utilisation.

2.1   Un système dynamique en dimension 1

On ne peut pas trouver de solution d'un système tel que (1) à l'aide d'une formule explicite. On va donc calculer une solution numérique et tracer dans le plan (t,y) l'évolution des trajectoires y(t) passant par le point initial donné (t0,y0). Usuellement pour avoir une première idée de la forme des trajectoires on trace les lignes de champ : ce sont les tangentes aux trajectoires pour tous les points d'une grille. Pour cela, on n'a pas besoin de résoudre l'équation et on utilise la fonction champ . D'abord, on définit la fonction qui représente le système, soit f(t,y)=y2-t, en Scilab. Comme cette fonction est très simple, on utilise :

deff("yprim=f(t,y)","yprim=y^2-t")puis on définit le cadre en (t,y), c'est-à-dire les valeurs min et max de t et y, dans lequel on va tracer les lignes de champ :

tmin=-3; tmax=5; ymin=-3; ymax=3;t=tmin:tmax; y=ymin:ymax;

et enfin on trace les lignes de champ : nt=size(t,"*"); ny=size(y,"*");ft=ones(nt,ny);

- 12 -

fy=feval(t,y,f);xset("font",2,12) //fixe la taille des caractères sur la figurechamp(t,y,ft,fy)xtitle("","t","y")

Ici feval est utilisé pour évaluer la fonction f aux points de la grille. Cela donne la figure 1(a).

Figure 1: champs de vecteurs

On va ensuite résoudre le système sur un intervalle de temps de 0 à 5, c'est-à-dire en partant du point t=0,y(0)=0 jusqu'à t=5 par pas de temps de 0,1 (noter que ce pas de temps détermine les instants où la solution est calculée, mais qu'en fait le solveur calcule de façon interne un pas variable optimal). Cela se fait simplement par :

t0=0; y0=0; tfin=5; dt=0.1; T=t0:dt:tfin;sol=ode(y0,t0,T,f);

où f est la fonction définie plus haut et en retour sol est la valeur de y(t) pour toutes les valeurs de t entre 0 et 5 par pas de 0,1, soit un vecteur de 51 éléments. Tracer la trajectoire correspondante peut se faire avec :

xset("thickness",2); plot2d(T,sol,1,"000")où "000" sert à utiliser le cadre et les échelles graphiques précédentes (voir le help de plot2d). Mais il est plus amusant de cliquer sur un point du cadre et de voir se tracer la trajectoire passant par ce point. Cela peut se faire en utilisant xclick. Cette fonction retourne le numéro du bouton cliqué ainsi que les coordonnées du point cliqué. Il suffit alors de réaliser une boucle infinie jusqu'à ce que l'on clique par exemple sur le bouton de droite de la souris (dans ce cas c_i dans le programme ci-dessous est égal à 2 ). À partir de chaque point cliqué, on résout l'équation différentielle une fois dans le sens des t croissants jusqu'à tmax et une fois dans le sens des t décroissants jusqu'à tmin. Cela donne le code suivant :

while(%t) [c_i,t0,y0]=xclick(); if c_i==2 then break end; if t0>=tmin & t0<=tmax & y0>=ymin & y0<=ymax then T=t0:dt:tmax; sol=ode(y0,t0,T,f); plot2d(T(1:size(sol,"*")),sol,1,"000") T=t0:-dt:tmin; sol=ode(y0,t0,T,f); plot2d(T(1:size(sol,"*")),sol,1,"000") endend

où l'on a utilisé T(1:size(sol,"*")) car parfois la solution part à l'infini et donc le solveur s'arrête avant la fin. Cela donne la figure 1(b).

2.2   Des requins et des sardines ou la dure vie des prédateurs

Nous allons traiter ici le cas des systèmes de deux équations différentielles. On a un système dont les fonctions inconnues sont maintenant x(t) et y(t). L'exemple le plus classique, qui est d'ailleurs à l'origine des équations différentielles, est celui de la trajectoire des planètes autour du soleil. Maintenant pour voir les solutions, on va les placer dans ce que l'on appelle le plan de phase, c'est-à-dire le plan (x,y) et les solutions se promèneront, lorsque le temps t varie, le long de ces trajectoires : penser aux planètes. D'abord une petite histoire. À Trieste, pendant la première guerre mondiale, la pêche avait bien sûr diminué à cause des événements. La pêche consistait à lancer des filets et à récupérer tous les poissons. Le bureau des pêches avait constaté qu'alors la proportion de poissons du style requins, peu intéressants pour la consommation, avait considérablement

- 13 -

augmenté par rapport aux poissons intéressants du style sardines. Ils demandèrent l'aide de Volterra qui modélisa le système requins-sardines par le système des deux équations différentielles suivantes où x(t) représente le nombre de sardines et y(t) représente le nombre de requins : {

x'(t)=a x(t)-b x(t)y(t)      a,b > 0 y'(t)=c x(t)y(t)-d y(t)      c,d > 0 x(0)=x0,    y(0)=y0

Ce modèle approché, appelé aussi système de Lotka-Volterra, signifie qu'en l'absence de requins les sardines prolifèrent x'(t)=a x(t), qu'en l'absence de sardines les requins disparaissent y'(t)=-d y(t) et le terme en x(t)y(t), qui représente la rencontre des requins et des sardines, augmente le nombre de requins et diminue le nombre de sardines (car ces dernières sont mangées par les requins). À partir de ce modèle Volterra en déduit, sans pouvoir faire les calculs numériques à l'époque, que plus on pêche de poissons, plus la proportion de sardines, donc de poissons intéressants, est importante ! C'est ce que nous allons essayer de retrouver par le calcul. On prendra par exemple pour l'application numérique a=3, b=1, c=1 et d=2. On crée d'abord un fichier volterra.sci dans lequel on définit le système précédent sous la forme d'une fonction vectorielle f(t,Y) où Y représente le vecteur (x,y) (on rappelle que les fichiers lus par Scilab doivent toujours être terminés par un retour chariot) :

function Yprim=f(t,Y)x=Y(1); y=Y(2);xprim=a*x-b*x*y;yprim=c*x*y-d*y;Yprim=[xprim;yprim]

et que l'on charge par getf("volterra.sci"). On va d'abord tracer les lignes de champ dans le plan de phase, ce qui permet encore d'avoir une idée des trajectoires sans résoudre le système : cela revient à tracer le vecteur (x'(t),y'(t)) en chaque point d'une grille. On utilise ici la fonction fchamp faite exprès pour ça :

a=3; b=1; c=1; d=2; xmin=0; xmax=6; ymin=0; ymax=6;xr=xmin:0.5:xmax; yr=ymin:0.5:ymax;xset("font",2,12)fchamp(f,0,xr,yr)xtitle("","x","y")

où la fonction f est celle définie dans volterra.sci. On voit le champ de vecteurs sur la figure 2(a). On va faire comme au paragraphe précédant et tracer des trajectoires qui passent par le point cliqué. Cela se fait de la même façon par :

xset("thickness",2)t0=0; tmax=5; dt=0.05;T=t0:dt:tmax;while(%t) [c_i,x0,y0]=xclick(); if c_i==2 then break end; if x0>=xmin & x0<=xmax & y0>=ymin & y0<=ymax then sol=ode([x0;y0],t0,T,f); plot2d(sol(1,:),sol(2,:),1,"000") endend

La seule différence est qu'ici il faut donner un vecteur (x 0,y0) comme condition initiale et que le tableau sol en sortie de ode est maintenant une matrice à deux lignes correspondant à x(t) (nombre de sardines) et y(t) (nombre de requins). Les trajectoires tournent autour du point d'équilibre (x=d/c=2,y=a/b=3) et on peut en voir sur la figure 2(a).

- 14 -

Figure 2: champs de vecteurs et trajectoires du modèle de voltera

On peut vérifier que lorsqu'on augmente la fréquence de pêche, c'est-à-dire a a- et d d+, le point d'équilibre se déplace vers un lieu où il y a moins de requins et plus de sardines. C'est ce que l'on voit sur la figure 2(b) en prenant =2 et =2 et en refaisant les calculs dans Scilab. Le point d'équilibre passe du point (2,3) au point (4,1). On retrouve donc bien les résultats de Volterra.

- 15 -

Chapitre 5 : -Introduction à Scicos (simulink)

Il est toujours possible de construire et de simuler des modèles de systèmes dynamiques dans Scilab en utilisant les fonctions de base comme ode (solveur de systèmes d'équations différentielles). Mais cela nécessite en général beaucoup de programmation en langage Scilab ou C. Ces programmes, en particulier quand le système à simuler contient des composants discrets, sont complexes, difficiles à déboguer et trop particuliers pour conduire à du code ré-utilisable. L'éditeur graphique de la boîte à outils Scicos permet à l'utilisateur de décrire son système dynamique de façon complètement modulaire. Le modèle ainsi obtenu peut alors être compilé, et le résultat simulé, par le simulateur Scicos. Les systèmes modélisables et simulables par Scicos sont de nature très variée ; ils peuvent comporter des composants évoluant en temps continu, en temps discret, et même des composants événementiels. On les appelle des systèmes hybrides. Dans cet article, on présente l'utilisation de Scicos à travers plusieurs exemples ; pour cela on n'utilisera que des blocs prédéfinis, fournis avec la boîte à outils. Dans le prochain numéro, on abordera le problème de construction de nouveaux blocs.

1 Un exemple simple

Supposons qu'on veuille simuler le fonctionnement d'un simple intégrateur (un système dont la sortie est l'intégrale de son entrée). En plus de l'intégrateur, il faut une entrée et un affichage graphique pour visualiser la sortie. On commence par lancer l'éditeur Scicos (dans Scilab) avec la commande :

--> scicos();Cela ouvre la fenêtre principale de l'éditeur Scicos. La fenêtre et le schéma correspondant sont intitulés par défaut Untitled. Le schéma est bien évidemment vide pour le moment. Toutes les fonctionnalités de Scicos sont disponibles à travers des menus déroulants. On devine assez facilement la fonction de chaque bouton de chaque menu par son nom : Save pour enregistrer un schéma, Load pour le charger, Copy pour copier un bloc, Delete pour le supprimer, Color pour donner une couleur au bloc, etc...Il existe aussi un bouton Help qui se trouve dans le menu Misc qui permet de consulter l'aide en ligne sur chaque menu. Pour cela, il suffit de cliquer sur Help puis sur le bouton ad hoc. Le bouton help permet aussi d'accéder à l'aide sur les blocs ; il suffit de cliquer sur le bloc après avoir cliqué sur Help. On commence par chercher les blocs dont on a besoin dans les <<palettes>> Scicos. Une palette est un schéma contenant des blocs que l'on peut utiliser pour construire d'autres schémas. Pour ouvrir une palette, il faut cliquer sur le bouton palette du menu Edit. On voit alors une liste de palettes ; choisissons la palette Linear. On voit alors s'ouvrir la fenêtre graphique qu'on voit dans la figure 1.

Figure 1: La palette Linear.

L'icône du bloc intégrateur est 1/s. Pour copier ce bloc dans le schéma Untitled, il suffit de placer la souris sur ce bloc et cliquer sur le bouton gauche de la souris, puis placer la souris dans la fenêtre qui contient le schéma Untitled, à l'endroit où on veut placer le bloc, et recliquer. Une copie du bloc 1/s apparaît alors dans Untitled. Il faut maintenant définir une entrée pour l'intégrateur : par exemple un sinus. Pour cela, on va chercher dans la palette Inputs_Outputs le bloc

- 16 -

sinusoid_generator. Pour connecter la sortie de sinusoid_generator à l'entrée du bloc 1/s, on clique d'abord près du port de sortie de sinusoid_generator puis près du port d'entrée de 1/s (voir Figure 2).

Figure 2: Schéma Scicos simulable.

Le schéma ainsi obtenu est simulable mais pas intéressant à simuler car nous ne verrons rien, il faut rajouter de quoi afficher le résultat ! On place donc le bloc MScope (oscilloscope à entrées multiples) dans le schéma et on connecte la sortie de 1/s à sa première entrée et la sortie de sinusoid_generator sur sa deuxième entrée. Comme la sortie de sinusoid_generator est déjà branchée, il faut placer la souris quelque part sur le lien qui sort de sinusoid_generator et cliquer ; cela crée un branchement et débute un lien, puis cliquer sur l'entrée de MScope. Pour obtenir un schéma plus lisible, il est préférable de ne pas créer dans ce dernier cas un lien direct qui passerait par dessus le bloc 1/s, mais de le contourner. Pour cela, après avoir débuté le lien, on peut cliquer sur des points intermédiaires avant de cliquer sur l'entrée de MScope . Le bloc MScope est un bloc discret qui affiche les valeurs de ses entrées quand il est activé. Pour activer ce bloc, il faut envoyer un événement sur son port d'entrée événement placé en haut du bloc. Dans ce cas on veut envoyer une suite d'événements espacés de manière régulière dans le temps. Pour cela on utilise le bloc horloge d'événement (l'horloge rouge ayant une sortie en bas qui se trouve dans la palette Inputs_Outputs ). Une fois ce bloc placé et branché, le schéma complet doit ressembler a celui de la Figure 3.

- 17 -

Figure 3: Schéma complet.

Le schéma peut alors être simulé. Cliquer sur le bouton Run du menu Simulate. On observe alors l'ouverture d'une fenêtre graphique fonctionnant comme une oscilloscope. Pour arrêter la simulation il suffit de cliquer sur stop.

Figure 4: Résultat de la simulation affiché par l'oscilloscope.

On constate alors (voir Figure 4) que les paramètres par défaut de l'oscilloscope ne sont pas bien réglés ici; il faut faire en sorte que la première courbe reste dans la fenêtre graphique. Pour changer les paramètres d'un bloc, il suffit de cliquer sur le bloc, ce qui ouvre un dialogue (voir Figure 5).

Figure 5: Paramètres par défaut de l'oscilloscope.

On peut régler le problème ici en changeant les premières valeurs de Ymin_vector et Ymax_vector, par exemple on peut remplacer le premier (qui vaut -1) par 0 et le deuxième par 2.

2. Les requins et les sardines

- 18 -

On est maintenant en mesure de construire des modèles plus compliqués. Prenons par exemple le modèle de la population des requins et des sardines présenté dans l'article précédent :

x'(t) = a x(t)-b x(t)y(t)      a,b > 0 y'(t) = cx(t)y(t)-d y(t)      c,d > 0

où x(t) représente le nombre de sardines et y(t) représente le nombre de requins. Ce modèle approché, appelé aussi système de Lotka-Volterra, signifie qu'en l'absence de requins les sardines prolifèrent x'(t)=a x(t), qu'en l'absence de sardines les requins disparaissent y'(t)=-d y(t) et le terme en x(t)y(t), qui représente la rencontre des requins et des sardines, augmente le nombre de requins et diminue le nombre de sardines (car ces dernières sont mangées par les requins).

Le schéma Scicos représentant ce modèle est donné dans la Figure 6. On retrouve les états x et y comme les sorties des deux intégrateurs (un intégrateur pour chaque équation différentielle). Les entrées de ses intégrateurs sont alors x' et y' . Pour réaliser les équations définissant x' et y' dans le schéma, on a utilisé des blocs sommateurs, multiplicateurs et gains (multiplication par constante). On a pris a=2, b=1, c=.3 et d=1.

Figure 6: Le schéma Scicos correspondant au modèle de la population des requins et des sardines.

Le résultat de la simulation pour x(0)=2 et y(0)=1 est donné dans la Figure 7. On retrouve alors le comportement périodique attendu.

Figure 7: L'évolution de la population des requins (en haut) et des sardines (en bas).

- 19 -

On constate donc qu'il peut exister une forte variation de la population des sardines ; cela dépend des populations initiales des sardines et des requins (x(0) et y(0)). Si on commence près des populations d'équilibre, les variations sont moins fortes. Les populations d'équilibre xe et ye correspondent à une condition initiale pour laquelle l'état reste constant. Elles vérifient bien entendu le système : {

0=a xe-b xeye 0=c xeye-d ye

. ce qui (à part la solution évidente (0,0)) donne xe=d/c et ye=a/b.

La régulation par la pêche

On peut introduire l'influence de la pêche de sardines dans le modèle précédent en modifiant l'équation de x'(t) comme suit : x'(t)=a x(t)-b x(t)y(t)+f x(t)      a,b > 0,  f<0,

le coefficient f indique alors l'effort de pêche. Noter que cette modification ne modifie pas le point d'équilibre xe. Supposons maintenant que les autorités de pêche veuillent réguler la population des sardines. Pour cela ils autorisent la pêche ( f<0) si la population des sardines dépasse un certain seuil (x>xmax) et ils interdisent la pêche (f=0) quand cette population passe en dessous d'un autre seuil (x<xmin). Pour modéliser ce <<régulateur>>, on note qu'il faut générer deux événements : ces événements sont alors utilisés pour modifier la valeur de f (voir Figure 8).

Figure 8: Le modèle de l'évolution de la population des sardines et des requins régulé par la pêche.

Les blocs -to+ et +to- génèrent des événements quand leur entrées traversent zéro dans le sens négatif vers positif et positif vers négatif, respectivement. Le bloc Selector copie la valeur qui se trouve sur sa première entrée (ici 0) sur sa sortie quand il reçoit un événement sur son premier port d'entrée événement, et il copie la valeur sur sa deuxième entrée (ici 1) quand il reçoit un événement sur l'autre port. Donc quand x-3.4 dépasse 0, f devient -1 et quand x-3.2 passe en dessous de 0, f devient 0. Ces valeurs sont choisies pour pousser x vers sa valeur d'équilibre xe=d/c=3.33. Le bloc Mux permet de concaténer les deux entrées pour former un signal vectoriel. Ce signal est affiché par MScope en superposant les deux valeurs (voir Figure 9). La courbe de dessous indique les périodes d'ouverture et de fermeture de la pêche. On constate qu'après une période transitoire, le système se stabilise au point d'équilibre (xe,ye) où l'on autorise la pêche ; le régulateur n'est alors plus sollicité. Dans la pratique, à cause des phénomènes que nous n'avons pas pris en compte dans notre modèle simpliste, on s'écarte régulièrement du point d'équilibre et donc le régulateur doit rester en place.

- 20 -

Figure 9: L'évolution des populations dans le cas régulé. En haut, en noir, on a la population des sardines et, en vert, la population des requins. En bas, on trouve les périodes d'ouverture

de la pêche (f=-1).

Le système régulé peut, bien évidemment, être simulé directement dans Scilab en utilisant la fonction ode. Mais cela nécessiterait beaucoup de programmation dans le langage Scilab. De plus, le résultat serait difficile à ré-utiliser. Dans l'environnement Scicos, il serait facile de modifier la structure du régulateur, rajouter d'autres populations animales en interaction avec les sardines et les requins, etc... Ce type de modifications, impliqueraient, très souvent, une réécriture complète du programme Scilab.

Super Block

Le Schéma 8 est assez chargé, on aimerait bien utiliser une description hiérarchique pour le simplifier et le rendre plus lisible. Pour cela on peut utiliser un <<Super Block>>, qui ressemble à un bloc normal mais qui peut contenir tout un sous-schéma. Par exemple, pour mettre la partie régulateur dans un <<Super Block>>, on peut cliquer sur le bouton Region_to_SuperBlock du menu Diagram, puis sélectionner la région correspondant au régulateur. Cette région disparaît alors et elle est remplacée par un seul bloc de type <<Super Block>> (Fig. 10). Pour accéder au schéma qui se trouve à l'intérieur de ce bloc, il suffit de cliquer dessus, ce qui lance un nouvel éditeur Scicos.

Figure 10: Mise en Super Block du régulateur.

- 21 -

On peut manipuler un <<Super Block>> comme n'importe quel autre bloc, en particulier on peut le copier et l'utiliser plusieurs fois dans le même schéma. De manière générale, on peut utiliser un nombre illimité de <<Super Block>> par schéma et on peut même placer des <<Super Block>> dans d'autres <<Super Block>>.

Paramètres formels

Il est possible, et souvent souhaitable, de définir les paramètres des blocs Scicos de manière formelle. Par exemple, dans l'exemple précédent, au lieu de rentrer, dans les blocs, les valeurs numériques des paramètres a, b, c, etc..., on peut les définir dans le <<Context>> du schéma comme variables Scilab puis utiliser leur noms comme paramètres de blocs. Le <<Context>> peut être invoqué en cliquant sur le bouton Context du menu Edit (voir Figure 11). On peut mettre n'importe quelle instruction Scilab dans le <<Context>>, le contenu est exécuté comme un script.

Figure 11: Le Context du schéma Scicos.

Une fois ces variables définies, on peut les utiliser comme paramètres de blocs (voir Figure 12).

Figure 12: Le modèle régulé avec le Context défini dans la Figure 11 (à comparer à la Figure 8).

Le <<Context>> est sauvé automatiquement avec le schéma et il est évalué à chaque chargement.

- 22 -

Chapitre 6 : - L'interface utilisateur1   Les primitives graphiques

Scilab permet de tracer toutes sortes de graphiques. Bien qu'il existe des fonctions de haut niveau et très puissantes, nous ne verrons dans cet article que les primitives de base. Dans cette section, vous apprendrez à déterminer des zones de travail, dessiner un rectangle, des lignes, des flèches, des arcs et des ellipses. Rappelons que pour une aide sur une fonction, par exemple xclick, vous pouvez taper dans la fenêtre Scilab l'une des commandes suivantes :

-->apropos xclick-->help xclick

1.1   Fenêtre graphique et changement d'origine

Avant tout regardons comment obtenir les dimensions d'une fenêtre graphique donnée. Il suffit de taper : -->[wrect,frect]=xgetech()

frect = ! 0. 0. 1. 1. ! wrect =! 0. 0. 1. 1. !

qui renvoie dans wrect (Working RECTangle) un quadruplet [x,y,w,h] contenant les coordonnées (x,y) du coin supérieur gauche et les proportions (w,h) de la zone de travail (w est la largeur et h la hauteur). Ce sont les proportions relatives à la taille courante de la fenêtre. L'échelle de proportion dans cette zone de travail est donnée par frect (Frame RECTangle), un quadruplet [xmin, ymin, xmax, ymax]. Pour redéfinir la zone par défaut, nous utilisons l'instruction xsetech qui permet de redéfinir l'échelle de la fenêtre graphique, ainsi que son origine. Par exemple, pour définir l'échelle entre (-10 ; 10) pour l'axe des ordonnées et (-10 ; 10) pour les abscisses sur toute la fenêtre entrons la suite d'instructions :

--> wrect=[0,0,1,1]; // on sélectionne toute la fenêtre--> frect=[-10 -10 10 10]; // définition de l'\'échelle --> xsetech(wrect,frect) ;

1.2   Dessiner un rectangle

Nous pouvons alors dessiner un rectangle dans un repère orienté grâce à l'instruction xrect(x, y, w, h), par exemple le rectangle d'origine (0,0) et de dimension (7,7), après changement de l'échelle de la fenêtre courante :

-->wrect=[0 0 1 1];-->frect=[-10 -10 10 10];-->xsetech(wrect,frect); // definition de l'\'échelle-->xarrows([0 0],[-10 10],0.5); // dessine les axes sous forme de flèches-->xarrows([-10 10],[-0 0],0.5);-->xrect(0 ,0 ,7 ,7); // Pour un carré de coté 7

Affichons un rectangle de coins supérieur gauche (x0=0,y0=6) et inférieur droit (x1=5, y1=0) : -->green = 3;xset("foreground",green);xrect(0, 6, 5,6);//w=x1-x0 et h=y1-y0La variante xfrect dessine un rectangle plein (f comme filled) en utilisant la couleur définie par xset. xrects dessine un ensemble de n rectangles (s pour plusieurs rectangles), dont les quadruplets sont sous la forme d'une matrice 4 lignes et n colonnes (4xn). Devinez ce que fait xfrects !

-->xrects([[0 ;0 ;7 ;7], [0; 6; 5;6]], [-1 2])

- 23 -

Figure 1: Tracé de rectangle

Remarquez qu'un indice de couleur positif rempli le rectangle, un indice négatif dessine le contour.

1.3   Dessiner des lignes et flèches

La syntaxe générale de la fonction xarrows que nous avons utilisée dans l'exemple précédent est xarrows( nx, ny, [ size, style]). Les paramètres nx est une matrice 2xn contenant les abscisses des points de départ et d'arrivée, ny les ordonnées. Ainsi, l'affichage des deux axes s'effectue par une seule instruction.

-->xarrows([0 -10; 0 10], [-10 0; 10 0], 0.5, [3 4]);Pour dessiner une ligne brisée (un ensemble de segments reliés), Scilab propose l'instruction : xpoly(xv, yv, dtype, [closeflag]) où xv et yv sont respectivement les n-uplets des abscisses et des ordonnées, la chaîne de caractères dtype est soit ``lines'' soit ``marks'', et closeflag est un entier positionné à 1 pour obtenir une forme fermée, et différente de 1 pour une forme ouverte :

--> xpoly([1 4 8],[ 1 2 10],"lines",0); // polygone ouvert --> xpoly([-1 -4 -8],[ -1 -2 -10],"lines",1); // polygone ferme

Figure 2: Polyline.

1.4   Dessiner des Arcs et des Cercles

L'instruction xarc(x,y,w,h,angle_debut,angle_de_rotation) dessine un arc contenu dans le rectangle défini par (x,y,w,h). La fonction xarc utilise des angles exprimés en 64ième de degré. Les instructions suivantes dessinent un quart de cercle (un arc de 90o à partir de 90o) inscrit dans le rectangle :

-->xrect(0,0,5,5);-->xset("pattern",2) -->xfarc(-8,8,16,16,90*64,90*64);

- 24 -

Figure 3: Arc plein.

Il existe les mêmes variantes que pour xrect : xfarc, xarcs et xfarcs. Par exemple : -->arcs=[-8 0 0.5; // coin superieur gauche x--> 8 0.0 0.5; // coin supérieur gauche y--> 0.5 1.0 0.5; // largeur--> 0.5 0.5 1.0; // hauteur--> 0.0 0.0 0.0; // angle de départ--> 180*64 360*64 90*64];// angle de rotation-->xarcs(arcs,[1,2,3]);// trois arcs de trois couleurs différentes

2   Interfaces utilisateur

Pour permettre le développement d'outils graphiques interactif, Scilab propose quelques fonctions de base. Ces fonctions permettent à l'utilisateur de détecter des évènements, de définir des fenêtres de dialogue et de gérer des menus.

2.1   Détection des évènements souris et du clavier

Les trois fonctions xclick, xgetmouse et locate permettent de connaître la position de la souris dans une fenêtre graphique et de détecter les évènements de la souris et du clavier. Ce sont des fonctions bloquantes. C'est-à-dire que leur appel bloque l'interpréteur Scilab, jusqu'à ce qu'une action de la souris ait été réalisée. La fonction xclick attend un clic de la souris ou l'appui d'une touche du clavier. Sa syntaxe est [mouse_button, x_coordinate, y_coordinate, gwin_num, callback_string]=xclick([flag]) . Les variables renvoyées sont :

mouse_button : numéro du bouton de la souris qui a été cliqué, ou code ASCII de la touche qui a été appuyée. x_coordinate : abscisse de la position de souris. y_coordinate : ordonnée de la position de souris. gwin_num : numéro de fenêtre. callback_string : chaîne de caractères correspondant au code du callback associé au menu s'il s'agit d'un click

sur un menu, ou ``void'' sinon.

-->[button, x, y, gwin, str]=xclick(); //j'appuie sur le bouton gauche de la souris dans la fenetre graphique 0 str = void gwin = 0. y = - 1.4615385 x = - 12.138085 button = 0.--> [button, x, y, gwin, str] = xclick(); // j appuie sur a dans la fenetre graphique 0 str = void gwin = 0. y = - 12.923077 x = - 11.113586

- 25 -

button = 97.L'instruction rep=xgetmouse([flag]), renvoie la position de la souris dans la fenêtre courante. Si flag est présent les clics sont mémorisés dans la queue d'évènements et ne sont pas effacés lors de l'appel à xgetmouse. Cette fonction renvoie un vecteur rep=[x y bouton], dans lequel x et y représentent la position de la souris en coordonnées utilisateurs (cf. xsetech), et bouton est un entier égal à 0, 1 ou 2 selon le bouton de souris cliqué, -1 s'il s'agit d'un mouvement de souris. Contrairement à xclick, xgetmouse n'attend pas de clic de souris ou de touche clavier. Il permet ainsi de connaître à tout moment la position de la souris.

-->a=xgetmouse();//je place la souris sur la fenetre a = ! - 8.5746102 - 8.6923077 - 1. !-->a=xgetmouse();//je clic sur le bouton gauche a = ! - 1.8040089 1.3846154 0. !-->while(1)-->rep=xgetmouse() //renvoie dans la fenetre courante la position de la souris -->end;

L'instruction locate([n[,flag]]) renvoie la matrice des points sélectionnés par un clic. Si n est supérieur à 0, alors n points devront être impérativement sélectionnés. Si n est égal à -1, les points sont sélectionnés par le bouton droit ou milieu jusqu'à ce que le bouton gauche ait été cliqué. Si flagest égal à 1, alors une croix est placée à chaque coordonnée sélectionnée.

-->a=locate(3,1);//je clic 3 fois et dessine 3 croix a = ! - 5.2783964 - 1.3585746 - 5.6347439 !

! 10.615385 10.153846 6.7692308 !

2.2   Boîtes de dialogues

2.2.1   x_dialog

L'instruction result=x_dialog(labels,valueini) crée une boîte de dialogue utilisateur. Le paramètre labels est un vecteur de chaîne de caractères qui spécifie le titre de la fenêtre puis le titre de la saisie, et valueini initialise la valeur par défaut. La fonction renvoie la valeur saisie qui peut être un scalaire ou une chaîne de caractères, ou alors la matrice vide [] si le bouton Cancel est appuyé.

-->x_dialog(['Taille';'entrez la taille';'un autre commentaire'],'1') ans = 1

Figure 4: Boîte de dialogue.

2.2.2   x_mdialog

Les instructions result=x_mdialog(titre, labels, valeur_initiale) ou result = x_mdialog (titre, label_vertical, label_horizontal, matrice_valeur_initiale) permettent de saisir des matrices de chaînes de caractères. -->x_mdialog('matrice',['L 1'; 'L 2'],['C 1' ;'C 2'],['a','b';'c', 'd']) ans = !a b !

! !!c d !

Pour convertir les chaînes de caractères en valeurs numériques vous pouvez utiliser la fonction evstr sur les éléments de la matrice.

- 26 -

Figure 5: Boîte de dialogues multiples.

2.2.3   x_choose

L'instruction num=x_choose(labels, titre [,bouton]) permet de choisir un item parmi les labels. La fonction renvoie le numéro de l'item choisi, 0 si Cancel.

--> n=x_choose(['item1';'item2';'item3'],['ceci est un commentaire']) n = 2.

Figure 6: Boite de choix.

2.2.4   getvalue

La fonction de haut niveau getvalue encapsule x_dialog et permet de saisir des valeurs avec détection d'erreurs, évaluation de la réponse.... Sa syntaxe est [ok,x1,..,x14]=getvalue(titre, labels, type, init) où la chaîne de caractère titre contient le nom de la boîte , labels correspond aux noms des champs à saisir, type est une list Scilab qui définit le type et le nombre d'éléments de chaque champs par list(typ1,dim1,..,typn,dimn) où typn est l'une des ces chaînes de caractères :

'mat' : matrice 'col' : vecteur colonne 'row' : vecteur ligne 'vec' : vecteur 'str' : string 'lis' : list.

dim un scalaire supérieur à zéro, ou égal à -1 si la dimension est indéfinie. init est le vecteur de valeurs initiales. ok vaut %t (true) si le bouton Ok a été appuyé ou %f (false) si Cancel a été appuyé. xi contient la valeur de retour de chacun des champs.

--> labels=["magnitude";"frequence";"phase "];--> [ok,mag,freq,ph]=getvalue("definit le signal sinus",labels,...--> list("vec",1,"vec",1,"vec",1),["0.85";"10^2";"%pi/3"]) ph = 1.0471976 freq = 100. mag = 0.85 ok = T

- 27 -

Figure 7: Boite de dialogue évoluée.

2.3   La gestion des menus

Dans cette section nous allons construire des exemples de menus simples.

2.3.1   Ajouter un menu

Pour créer un menu nous utilisons l'instruction : addmenu(gwin,menu_name [,submenus] [,action]). Cette instruction permet d'ajouter un menu dans une fenêtre Scilab, désignée par son numéro gwin. Signalons que gwin=-1 désigne la fenêtre principale (comme le raccourci addmenu(menu_name [,submenus] [,action])). Le paramètre menu_name est une chaîne de caractères représentant le label du bouton. Par exemple :

--> menu_name = 'Dessin';submenus est un vecteur de chaîne de caractères désignant les labels des sous-menus. Par exemple :

--> submenus = ['Rectangle';'Ligne';'Cercle']action est une liste(cf. Linux Magazine numéro 14) de deux éléments : action=list(flag,proc_name), où flag est un entier. Lorsqu'il est mis à 0, sa valeur par défaut, action est une chaîne de caractère nommant soit une variable (qui contient une suite d'instructions Scilab) soit une fonction Scilab. Le cas flag=1 est réservé à l'appel d'une routine externe C ou FORTRAN. Par exemple :

--> action = list(0,'Dessin');proc_name est la chaîne de caractères désignant ``Dessin'' tel que les callbacks du menu Dessin soient des chaînes de caractères ordonnées dans un tableau proc_name_numero_de_fenêtre_graphique(numéro_de_sous-menu), pour un bouton dans la fenêtre de command la syntaxe est proc_name(numéro_de_sous-menu). Remarquez le _0 à la fin du nom de la procédure Dessin. Il s'agit du numéro de fenêtre graphique (gwin) à laquelle est associé le bouton. Si le bouton appartient à la fenêtre principale, il n'y a pas de postfixe à ajouter. :

-->Dessin_0(1) = 'xrects([-1; 1 ;3; 3])'; //premier sous-menu de la fenetre 0-->addmenu(0, menu_name, submenus, action);

Remarquez le _0 à la fin du nom de la procédure Dessin. Il s'agit du numéro de fenêtre graphique (gwin) à laquelle est associé le bouton.

2.3.2   Désactiver et réactiver un menu

Il est parfois nécessaire de bloquer l'utilisation d'un menu ou d'un sous-menu. Ces fonctionnalités sont accessibles par les instructions unsetmenu(gwin,menu_name,[nsub]) et setmenu(gwin,menu_name,[nsub]). Dans ces instructions, le paramètre nsub identifie le nième label du sous-menu qui doit être désactivé. Ainsi l'instruction

--> unsetmenu(0,'Dessin');désactive le menu Dessin, alors que

--> unsetmenu(0,'Dessin',1)ne désactive que le menu Dessin/Rectangle en laissant actifs Dessin/Ligne et Dessin/Cercle.

Figure 8: Désactivation de Dessin/Rectangle.

Bien sûr on peut les réactiver par la fonction setmenu. Les paramètres d'appel de cette fonction sont identiques à celle de unsetmenu. L'exemple suivant :

--> setmenu(0,menu_name);

- 28 -

active le menu Dessin, alors que --> setmenu(0,menu_name,1)

active de nouveau le menu Dessin/Rectangle.

2.3.3   Supprimer un menu

La suppression de n'importe quel menu, même ceux existant par défaut, se fait par l'instruction delmenu(menu_name) et delmenu(gwin,menu_name).

--> delmenu(menu_name);

- 29 -