Bonjour,

J'ai du mal à utiliser le module python odeint, dans le sens où, quand je l'utilise pour résoudre mon système d'équations différentielles couplées (partie #####RESOLUTION##### du programme), je n'obtiens pas de solution.
Mon objectif étant d'étudier les stratégies de courses en triathlon, je souhaite dans un premier temps faire l'étude d'une course avec des puissances constantes, or peu importe les valeurs de puissances que je donne à mes variables k, p_nage, p_vélo et p_pied, le programme ne converge pas.
J'ai du mal à saisir comment corriger le programme pour que le module fonctionne, je me suis assuré de ne jamais diviser par 0, j'ai modifié les tolérances rtol et atol du module sans réussite et les constantes que je fournis sont normalement cohérentes.
Si quelqu'un pouvait me fournir une piste pour avancer cela m'aiderait grandement.

Je vous remercie de l'attention que vous porterez à mon message.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
 
from scipy.integrate import odeint
from scipy.integrate import simpson
import numpy as np
import matplotlib.pyplot as plt
 
# Profil de la course
D_nage = 1.5 * 10**3
D_vélo = 40 * 10**3
D_pied = 10 * 10**3
T_transition_1 = 50
T_transition_2 = 25
 
##### MODELISATION MECANIQUE #####
 
# Paramètres généraux
M = 70  # kg
g = 9.81  # m/s²
 
# Paramètres natation
Ma_nage = 0.25 * M  # kg
F0_nage = 246  # N
v0_nage = 9.1  # m/s
ρ_eau = 1000  # kg/m³
S_front = 0.1  # m²
S_tot = 0.91  # m²
Cd = 0.35
Cs = 3 * 10**(-3)
Cw = 5 * 10**(-3)
 
v_eau = 7.1  # m/s
 
# Paramètres cyclisme
Ma_vélo = 10
F0_vélo = 1187  # N
v0_vélo = 21  # m/s
η = 0.98
l = 0
b = 0
R = 0.25  # m
ρ_air = 1.225  # kg/m³
Cx_x_S_cycliste = 0.4  # m²
fd = 0.01
 
v_vélo = 2.7
 
# Paramètres course à pied
Ma_pied = 0
f0 = 0
τ = 0
c = 0
 
# Modélisation natation
 
def Fp(v):
    return F0_nage * (1 - (v / v0_nage))
 
def Fr(v):
    return 0.5 * ρ_eau * (S_front * Cd + S_tot * Cs + ((M / ρ_eau)**2) * Cw) * (v**2)
 
# Modélisation cyclisme
 
def F_cyliste(v):
    return F0_vélo * (1 - (v / v0_vélo))
 
def F_prop(v):
    return ((η * l) / (b * R)) * F_cyliste(v)
 
def F_air(v):
    return 0.5 * ρ_air * Cx_x_S_cycliste * (v**2)
 
F_friction = fd * (M + Ma_vélo) * g
 
# Modélisation course à pied
 
def fp(v):
    v_sécu = max(v, 1)
    return (f0 / v_sécu) - (1 / τ)
 
def fr(v):
    return -c * (v**2)
 
# Modèle général mécanique
 
def dvdx(x, v, k, p_nage, p_vélo, p_pied):
    v_securité = max(v, 1)
    if x < D_nage:
        v_pour = v_securité * (1 - 0.1 * (1 - k))
        return (1 / (M + Ma_nage)) * ((p_nage / v_pour) * (1 - 0.3 * (1 - k)) - Fr(v_pour)) / v_pour
    elif x >= D_nage and x < D_vélo + D_nage:
        return (1 / (M + Ma_vélo)) * (M * (p_vélo / v_securité) - F_air(v) - F_friction) / v_securité
    elif x >= D_vélo + D_nage and x < D_pied + D_vélo + D_nage:
        return p_pied / v_securité - fr(v)
 
##### MODELISATION ENERGETIQUE #####
 
# Paramètres énergetiques
e0 = 1400  # J/kg
e_cr = 0.3
𝜎_max = 24.22  # m²/s³
𝜎_r = 6  # m²/s³
𝜎_f = 20.44  # m²/s³
ϕ = 0.5
c_η = 4  # s
𝜉 = 0.25
 
# Modèle énergetique
def 𝜎(e):
    if e < e0 * e_cr:
        return 𝜎_f * (1 - e / (e0 * e_cr)) + (𝜎_max * e) / (e0 * e_cr)
    elif e >= e0 * e_cr and e <= e0 * ϕ:
        return 𝜎_max
    elif e > e0 * ϕ:
        return 𝜎_r + ((𝜎_max - 𝜎_r) * (e0 - e) / (e0 * (1 - ϕ)))
    return 0
 
def f(x, v, k, p_nage, p_vélo, p_pied):
    if x < D_nage:
        return p_nage * 0.3 * k
    elif x >= D_nage and x < D_vélo + D_nage:
        return p_vélo
    elif x >= D_vélo + D_nage and x < D_pied + D_vélo + D_nage:
        return p_pied
    return 0
 
def dedx(x, e, v, k, p_nage, p_vélo, p_pied):
    v_safe = max(v, 1)
    return (𝜎(e) / v_safe) - (1 / 𝜉) * f(x, v, k, p_nage, p_vélo, p_pied) / v_safe
 
##### RESOLUTION DU SYSTEME #####
 
# Définir les intervalles de distance
x1 = np.linspace(0, D_nage, 100)
x2 = np.linspace(D_nage, D_nage + D_vélo, 100)
x3 = np.linspace(D_nage + D_vélo, D_nage + D_vélo + D_pied, 100)
 
# Système
def dSdx(S, x, k, p_nage, p_vélo, p_pied):
    v, e = S
    dv = dvdx(x, v, k, p_nage, p_vélo, p_pied)
    de = dedx(x, e, v, k, p_nage, p_vélo, p_pied)
    return [dv, de]
 
def résolution(p_nage, p_vélo, p_pied, k):
    # Condition initiale sur [0, D1]
    S0 = [v_eau, e0]
    sol1, infodict1 = odeint(dSdx, S0, x1, args=(k, p_nage, p_vélo, p_pied), rtol=1e-1, atol=1e-2, full_output=True)
 
    if infodict1['message'] != 'Integration successful.':
        print("Erreur d'intégration sur la phase de natation:", infodict1['message'])
        return [np.nan, None, None, None]
 
    # Condition imposée à D1
    S0_2 = [v_vélo, sol1[-1, 1]]
    sol2, infodict2 = odeint(dSdx, S0_2, x2, args=(k, p_nage, p_vélo, p_pied), rtol=1e-1, atol=1e-2, full_output=True)
 
    if infodict2['message'] != 'Integration successful.':
        print("Erreur d'intégration sur la phase de cyclisme:", infodict2['message'])
        return [np.nan, None, None, None]
 
    # Condition imposée à D2
    S0_3 = [1, sol2[-1, 1]]
    sol3, infodict3 = odeint(dSdx, S0_3, x3, args=(k, p_nage, p_vélo, p_pied), rtol=1e-1, atol=1e-2, full_output=True)
 
    if infodict3['message'] != 'Integration successful.':
        print("Erreur d'intégration sur la phase de course à pied:", infodict3['message'])
        return [np.nan, None, None, None]
 
    # Concaténer les solutions
    X = np.concatenate((x1, x2, x3))
    V = np.concatenate((sol1[:, 0], sol2[:, 0], sol3[:, 0]))
    E = np.concatenate((sol1[:, 1], sol2[:, 1], sol3[:, 1]))
 
    V_safe = np.where(V < 1e-2, 1e-2, V)
 
    # Calcul des intégrales sur chaque intervalle
    T1 = simpson(1 / V_safe[:len(x1)], x=x1)
    T2 = simpson(1 / V_safe[len(x1):len(x1) + len(x2)], x=x2)
    T3 = simpson(1 / V_safe[len(x1) + len(x2):], x=x3)
 
    return [T1 + T2 + T3 + T_transition_1 + T_transition_2, X, V, E]  # Temps total
 
# Demande des valeurs d'entrée
p_nage = float(input("Veuillez entrer la valeur de p_nage : "))
p_vélo = float(input("Veuillez entrer la valeur de p_vélo : "))
p_pied = float(input("Veuillez entrer la valeur de p_pied : "))
k = float(input("Veuillez entrer la valeur de k : "))
 
# Appel de la fonction résolution
temps_total, X, V, E = résolution(p_nage, p_vélo, p_pied, k)
 
# Affichage des résultats
print("\nTemps total calculé :", temps_total)
 
# Tracer les résultats
if X is not None and V is not None and E is not None:
    plt.plot(X, V, label='vitesse (V)')
    plt.plot(X, E, label='énergie (E)')
    plt.xlabel('Position x')
    plt.ylabel('V, E')
    plt.legend()
    plt.show()