Fichier de rejeu Close

Indication Close

A propos de... Close

Commentaire Close

Téléchargements

Aide

Résolusion d’un système d’équations différentielles

Objectif :

Cette page de l’ENIBOOK participe à la zone généraliste de deuxième année

L’objectif est de réutiliser ce que vous avez appris concernant la boucle de simulation pour simuler le comportement d’un système modélisé avec des équations différentielles, dans le cadre de la ZG2.

Ecrire dans un fichier CSV

Lors de l’objectif 5 du cours IPI, nous avons appris à programmer en utilisant une boucle de simulation et à mettre en oeuvre une résolution d’Euler explicite. Cette méthode de programmation s’applique au développement d’un jeu en IPI mais peut évidemment s’appliquer à d’autres projets en programmation. Nous profitons donc de la zone généraliste pour appliquer à nouveau cette méthode.

Ainsi, vous pouvez vous fabriquer un outil réutilisable qui encapsule tout ce qu’il faut pour modéliser un système d’équations différentielles. Nous vous proposons une trame pour réaliser un code, mais bien évidemment, n’hésitez pas à personnaliser votre outil.

Puisque que nous avons défini un type TimeSeries lors de l’activité précedente, nous pouvons commencer par concevoir que le résultat de la simulation sera un TimeSeries.

Type : TimeSeries = struct
    data : liste de liste de réels
    labels : liste de chaînes de caractères
A faire :

Compléter TimeSeries.py

Reprennez votre code de TimeSeries.py et ajoutez une fonction dump() qui crée un csv à partir d’un TimeSeries.

#####################
#                   #
#  TimeSeries.py    #
#  05/2022          #
#  ENIB/ZG2         #
#  G. desmeulles    #
#                   #
#####################

import csv
import matplotlib.pyplot as plt

#constructor
def create(filename=None,time_stamp_column_number=0):

    ts={'data':[],'labels':[]}

    if filename!=None:

        with open(filename, newline='') as csvfile:
            spamreader = csv.reader(csvfile, delimiter=',', quotechar='"')
            for row in spamreader:
                ts['data'].append(row)

        ts['labels']=ts['data'].pop(0)

        if time_stamp_column_number:
            swap_column(ts,0,time_stamp_column_number)

        ts['xlabel']=ts['labels'][0]

    return ts

#accessor/mutators
def get_data(ts):    return ts['data'][:]
def get_labels(ts):    return ts['labels'][:]
def set_data(ts,data):    ts['data']=data
def set_labels(ts,labels):    ts['labels']=labels

#operations
def swap_column(ts,n1,n2):
    for row in ts['data']:
        row.insert(n1,row.pop(n2))
    ts['labels'].insert(n1,ts['labels'].pop(n2))

def plot(ts,x_label=None,y_label="",title="",filename=None):

    if x_label==None:
        x_label=ts['labels'][0]

    nb_columns=len(ts['data'][0])
    columns=[[] for x in range(nb_columns)]

    for i in range(0,len(ts['data'])):
        for j in range(nb_columns) :
            columns[j].append(float(ts['data'][i][j]))

    fig, ax = plt.subplots()

    for i in range(nb_columns-1):
        ax.plot(columns[0], columns[i+1], label=ts['labels'][i+1])

    ax.set(xlabel=x_label, ylabel=y_label, title=title)
    ax.legend()
    plt.show()
    if filename:
        fig.savefig(filename)

#Nouvelle fonction
def dump(ts,filename):

    with open(filename, 'w', newline='') as csvfile:

        spamwriter = csv.writer(csvfile, delimiter=',',)
        spamwriter.writerow(ts['labels'])
        for line in ts['data']:
            output = []
            for val in line:
                output.append(str(val))
            spamwriter.writerow(output)


if __name__=='__main__':

    print('test TimeSeries.py')
    ts = create('HCSR04_data4_ressort_2022_03_10.csv',3)
    print(ts)
    plot(ts,y_label='distance(mm)',title='Courbe ZG2!!',filename='test.png')
    dump(ts,'test.csv')

Un exemple d’équations diférentielles du second ordre

Voici un sujet de d’électronique que vous passerez peut-être lors des semestres suivants TDmoteur_temporel_S4A.pdf

On modélise le système suivant :

_images/moteur.png

Voici l’équation différentielle :

_images/moteur_equadif.png

Le travail qui vous sera proposer dans ce TD d’électronique l’année prochaine, permettra de déterminer les différents paramètres de l’équation. Aujourd’hui, nous prendrons les valeurs suivantes pour la résolution numérique:

  • R = 0.5 Ohm
  • J = 0.0044 kgm2
  • L = 300 mH
  • K = 0.1 V.rad/s
  • u(t) = 10 V
A faire :

Implémenter un type pour représenter ce système

Type : Motor = struct
    R : réels
    J : réels
    L : réels
    K : réels
    U : réels
    omega0 : réels
    omega1 : réels
    omega2 : réels

Ce type abstrait fournit au moins deux opérations : * create() : un constructeur qui prend en paramètre les valeurs des paramètres * simulate(motor,sim_dt,log_dt,duration) : une fonction que condrons dans un second temps.

Résoudre

Il ne reste plus qu’a reprendre la méthode d’Euler explicite pour implémenter une fonction simulate(). La fonction simulate prend en paramètres :

  • le pas de simulation
  • le pas de trace
  • la durée de la simulation

Le pas de trace peut être inférieur au pas de simulation. En effet le pas de trace définit la précision à laquelle on mémorise les résultats

La fonction simulate() renvoie un TimeSeries qui contient les séries temporelles de la vitesse du moteur et de ses dérivées premières et secondes.

Performances & précision

Jouons avec le pas de simulation pour comprendre le compromis entre temps de simulation et erreur numérique...

A faire :

Erreur numérique

Augmentez le pas de simulation jusqu’a observer des résultats de simulations aberrants. Puis baissez le pas de simulation jusqu’à constater que cela n’améliore plus les résultats de manière significative

A faire :

Temps de calcul

Lorsque le pas de simulation devient petit, les temps de résolution deviennent importants. Il peut être intéressant de vérifier que votre code ne consomme pas inutilement du temps de calcul.

En utilisant Cprofile ou timeit(), essayez d’améliorer l’efficacité de la fonction simulate().

if __name__=="__main__":
    #profilage
    import cProfile
    import timeit

    m1=create()
    m2=create()
    m3=create()

    #c_profile
    cProfile.run('ts1=simulate_slow(m2,0.00001,0.001,7.0)')
    cProfile.run('ts=simulate(m1,0.00001,0.001,7.0)')
    cProfile.run('ts2=simulate_fast(m3,0.00001,0.001,7.0)')

    #en utilisant timeit
    print(timeit.timeit('m=Motor.create();ts1=Motor.simulate_slow(m,0.0001,0.001,7.0)',setup='import Motor',number=20))