Simulation d'un circuit LC en quelques lignes de C++

Ces quelques lignes suffisent pour résoudre numériquement une équation différentielle du deuxième ordre.

1 Etude analytique

J'ai publié cette étude depuis bien longtemps, sur ce site, ICI (Oscillateur harmonique)

Il s'agissait donc d'établir l'équation différentielle s'appliquant à un circuit oscillant LC. Nous avions obtenu l'équation différentielle du deuxième ordre ci-contre :

La solution de cette équation différentielle est une combinaison linéaire de fonctions cosinus et sinus, donc dans le cas qui nous occupe on obtient un courant sinusoïdal et une tension également sinusoïdale, dont la phase et l'amplitude sont déterminés par les conditions initiales. La résolution de cette équation différentielle est exposée ICI (Equations différentielles d'ordre 2)

Mais me direz-vous la nature sait-elle ce qu'est une équation différentielle du second ordre et comment fait-elle pour la résoudre lorsqu'elle n'a pas de papier et de crayon sous la main ? Nous nous avions trouvé la solution par... intuition, ayant l'habitude de manier des fonctions simples (sin et cos) et connaissant par coeur leurs fonctions dérivées. Ce qui nous avait de suite mis sur la voie d'une fonction sinusoïdale. Mais il serait quand même satisfaisant de voir surgir un sinus de ce circuit oscillant SANS JAMAIS utiliser la fonction sinus, ni aucune fonction d'ailleurs, dans un programme informatique qui se contenterait de calculer point par point l'évolution du courant et de la tension à partir de l'instant où l'on connecte un condensateur préalablement chargé aux bornes de la self. Et il serait encore bien plus satisfaisant de voir que cela se produit avec quelques lignes de code (en C++) que nous écrivons nous même. (Bien sûr il existe des programmes de simulation numérique qui font ça très bien mais le faire soit même avec quatre ou cinq lignes de code, c'est quand même autre chose!!)

Eh bien C'EST CHOSE FAITE !
Je vous donne ci-dessous ces quelques lignes de code (c'est une boucle en fait, dans laquelle chaque passage représente le temps dt).

2 La boucle de calcul :

La boucle dont je parle c'est la boucle ;
for(n=0; n<600; n++) {...}

Le reste étant la déclaration et l'initialisation des variables. Et les deux dernières lignes de cette boucle ne servent qu'à afficher le résultat, elle ne participent pas au calcul. Donc la partie purement opérationnelle se résume à... 5 lignes.
Et que voit-on dans ce code ? des sinus ? que nenni ! des cosinus ? pas d'avantage !! Que des multiplications, des divisions et des additions. Et le résultat ? Le voici :

3 Courbes tracées par cette boucle :

Nous remarquons que la tension démarre bien de +V0, qu'elle décroit mais ne s’arrête pas à zéro, qu'elle dépasse le zéro et devient négative (le condensateur se recharge en sens inverse), que la tension et le courant sont en quadrature de phase (déphasage de pi/2)... Donc ces sinusoïdes "émergentes" confortent la théorie et sa solution analytique. Les seuls présupposés sont les propriétés de base du condensateur et de la self, qui les définissent, à savoir que Q = C x U et que u = -L x di/dt.

4 Le programme complet en Qt4 et C++

Bien sûr le programme complet est bien plus gros que ces 10 lignes, mais TOUT le reste ne sert qu'à déclarer (et initialiser) quelques constantes (les valeurs des composants C et L), les variables (u, i...), et surtout à afficher le résultat dans une fenêtre. Le voici :

CODE SOURCE en C++ Qt4
  1. /*
  2.   Programme écrit par Silicium628
  3.   ce logiciel est libre et open source
  4.  
  5.   */
  6. #include "mainwindow.h"
  7. #include "ui_mainwindow.h"
  8. #include "math.h"
  9.  
  10. QString version = "2.0";
  11.  
  12. QColor couleur_ecran = QColor::fromRgb(255, 255, 255, 255);
  13. QColor couleur_ligne = QColor::fromRgb(0, 0, 0, 255);
  14. QColor couleur_trace1 = QColor::fromRgb(255, 0, 0, 255);
  15. QColor couleur_trace2 = QColor::fromRgb(0, 255, 0, 255);
  16. QColor couleur_trace3 = QColor::fromRgb(0, 0, 255, 255);
  17. QColor couleur_texte = QColor::fromRgb(255, 255, 0, 255);
  18.  
  19. QPen pen_ligne(couleur_ligne, 1, Qt::SolidLine);
  20. QPen pen_trace1(couleur_trace1, 1, Qt::SolidLine);
  21. QPen pen_trace2(couleur_trace2, 1, Qt::SolidLine);
  22. QPen pen_trace3(couleur_trace3, 1, Qt::SolidLine);
  23. QPen pen_reticule(couleur_ligne, 1, Qt::SolidLine);
  24.  
  25.  
  26. MainWindow::MainWindow(QWidget *parent) :
  27. QMainWindow(parent)
  28. {
  29. setupUi(this);
  30. setWindowTitle("Equa_diff_2deg " + version);
  31.  
  32. scene = new QGraphicsScene(this);
  33. scene->setBackgroundBrush(couleur_ecran);
  34. graphicsView1->setScene(scene);
  35. graphicsView1->setGeometry(5,5,610,610); // POSITION et dimensions de l'écran
  36.  
  37. groupe_reticule = new QGraphicsItemGroup();
  38. scene->addItem(groupe_reticule);
  39. groupe_trace = new QGraphicsItemGroup();
  40. scene->addItem(groupe_trace);
  41. }
  42.  
  43.  
  44.  
  45. MainWindow::~MainWindow()
  46. {
  47.  
  48. }
  49.  
  50.  
  51.  
  52. void MainWindow::effacer_trace()
  53. {
  54. foreach( QGraphicsItem *item, scene->items( groupe_trace->boundingRect() ) )
  55. {
  56. if( item->group() == groupe_trace ) { delete item; }
  57. }
  58. }
  59.  
  60.  
  61. void MainWindow::tracer_cadre()
  62. {
  63.  
  64. rectangle = new QGraphicsRectItem(0, 0, 600, 600);
  65. rectangle->setPen(pen_reticule);
  66. groupe_trace->addToGroup(rectangle);
  67.  
  68. ligne1 = new QGraphicsLineItem(0,300,600,300);
  69. groupe_trace->addToGroup(ligne1);
  70. }
  71.  
  72.  
  73.  
  74. void MainWindow::tracer1(int x_aff, int y_aff )
  75. {
  76. if (y_aff<550)
  77. {
  78. rectangle = new QGraphicsRectItem(x_aff, 300-y_aff, 1, 1);
  79. rectangle->setPen(pen_trace1);
  80. groupe_trace->addToGroup(rectangle);
  81. }
  82. }
  83.  
  84.  
  85.  
  86. void MainWindow::tracer2(int x_aff, int y_aff )
  87. {
  88. if (y_aff<550)
  89. {
  90. rectangle = new QGraphicsRectItem(x_aff, 300-y_aff, 1, 1);
  91. rectangle->setPen(pen_trace2);
  92. groupe_trace->addToGroup(rectangle);
  93. }
  94. }
  95.  
  96.  
  97. void MainWindow::tracer3(int x_aff, int y_aff)
  98. {
  99. if (y_aff<550)
  100. {
  101. rectangle = new QGraphicsRectItem(x_aff, 300-y_aff, 1, 1);
  102. rectangle->setPen(pen_trace3);
  103. groupe_trace->addToGroup(rectangle);
  104. }
  105. }
  106.  
  107.  
  108. void MainWindow::boucle_de_calcul()
  109. {
  110. float q, u, i, t;
  111. float memo_u, memo_i, memo_q;
  112. float L, C;
  113. float q0, u0, i0;
  114. float dq, du, di, dt;
  115.  
  116. q0=0;
  117. u0=40;
  118. i0=0;
  119.  
  120. L=1e-6; // 1uH
  121. C=100.0*1e-12; // 100pF
  122. dt=0.5e-9; // 0.5ns
  123.  
  124. int x_aff, y_aff;
  125. int n, y;
  126.  
  127. u=u0;
  128. i=i0;
  129. for(n=0; n<600; n++)
  130. {
  131. di=u*dt/L; //le courant augmente dans la self
  132. i+=di; // il atteint cette valeur
  133. dq=i*dt; //ce qui correspond au passage de cette quantité d'électricité (charge)
  134. du=dq/C; //qui en entrant dans le condensateur fait varier sa tension
  135. u-=du; // cette tension prend alors cette nouvelle valeur
  136.  
  137. y = u;
  138. tracer1(n, 2*y);
  139. tracer2(n, 100*i);
  140. }
  141. }
  142.  
  143.  
  144.  
  145.  
  146.  
  147. void MainWindow::on_pushButton_2_clicked()
  148. {
  149. effacer_trace();
  150. tracer_cadre();
  151. boucle_de_calcul();
  152. }
  153.  
  154.  
  155.  
  156.  

5 DOCUMENTS

lien vers le code source complet pour Qt4 (ou Qt5):

6 -

A voir également...

Liens externes :




Me contacter à propos de cet article :

Question mathématique :

Click to reload image
=
cliquez sur l'image pour un faire autre calcul.




Réponses à certaines de vos questions...
le: 10-12-2016 à 12:45

Bonjour,

Pour des raisons pédagogiques, je pense que le point "2-La boucle de calcul" n'apporte rien car il n'y a pas de déclaration des valeurs appelées : L=1e-6; // 1uH C=100.0*1e-12; // 100pF
dt=0.5e-9; // 0.5ns
et elle est rédigée différemment. Peut-être pourriez-vous rédiger de point 2 avec les valeurs déclarées.
Merci pour le partage et félicitation pour votre maîtrise

->Effectivement la façon de présenter les choses n'était pas très claire, j'ai donc tenu compte de votre remarque en modifiant l'article. Je vous remercie.
le: 15-03-2017 à 15:56

Bonjour,

Merci pour cet exemple simple de résolution numérique d'équation différentielle.
Il est aussi possible de produire ces traces à l'aide d'Excel. Dans ce cas, chaque itération correspond à une ligne.

Meilleures salutations de Suisse romande.
686