Programme pour tableau avancement chimie terminale

Bonjour,
Nous voyons en ce moment les avancements finaux en chimie et nous devons compléter un code python permettant de calculer l’avancement final selon différentes variables.
Voilà mon code:

import numpy as np
import matplotlib.pyplot as plt

La reaction consideree est A + B → C + D

Coefficients stoechiometriques

a, b, c, d = 1, 1, 1, 1

Quantites de matiere initiales et volume initial

n_iA, n_iB, n_iC, n_iD = 0.1, 0.1, 0, 0
V = 100.0e-3

Constante d’equilibre

K = 1e-1

Calcul de l’avancement final et generation des valeurs de x entre 0 mol et xmax

xmax = min(n_iA/a, n_iB/b)
x = np.arange(0, xmax, xmax/10000.0)
tau = x/xmax

Calcul des quantites de matiere et du quotient de reaction a chaque avancement x

n_A = n_iA-ax
n_B = n_iB-b
x
n_C = n_iC+cx
n_D = n_iD+d
x
Q_r = ((n_C/V)*c(n_D/V)**d)/((n_A/V)*a(n_B/V)**b)

Determination de l’avancement final x_f

for i in range(len(x)) :
if Q_r<K:
x_f = x[i]
i = i+1
else :
continue
plt.subplot(2,1,1)
plt.ylabel(‘Quantites de matiere \n de A, B, C et D (mol/L)’, fontsize=8)
plt.title(‘Evolutions des concentrations’, fontsize=8)
plt.grid()
plt.axis(xmin=0, xmax=1)
plt.axvline(x = x_f/xmax, label = ‘$\tau_f$’)
plt.plot(tau, n_A, color = ‘red’, label=’$n_A$’)
plt.plot(tau, n_B, color = ‘blue’, label=’$n_B$’)
plt.plot(tau, n_C, color = ‘green’, label=’$n_C$’)
plt.plot(tau, n_D, color = ‘orange’, label=’$n_D$’)
plt.legend()
plt.show()
plt.subplot(2,1,2)
plt.xlabel(‘Taux d’avancement $\tau$’, fontsize=8)
plt.ylabel(‘Constante de reaction $Q_r$ \n et constante d’equilibre $K$’, fontsize=8)
plt.title(‘Evolution du quotient de reaction \n en fonction de l’avancement’, fontsize=8)
plt.axvline(x = x_f/xmax, label = ‘$\tau_f$’)
plt.axis(xmin=0, xmax=1)
plt.plot(tau, K*np.ones(len(x)), color = ‘blue’, label=’$K$’)
plt.plot(tau, Q_r, color = ‘red’, label=’$Q_r$’)
plt.yscale(‘log’)
plt.legend()
plt.show()
print('L’avancement final correspond a x_f = ’ + str(x_f) + ’ mol, soit un taux d’avancement final tau_f = ’ + str(x_f/xmax) + ‘.’)

Mais en l’exécutant, je reçois le message d’erreur suivant:
ValueError Traceback (most recent call last)
in ()
21 # Determination de l’avancement final x_f
22 for i in range(len(x)) :
—> 23 if Q_r<K:
24 x_f = x[i]
25 i = i+0,1

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Je suis bloquée :frowning:
Merci d’avance pour votre aide!

My French is very poor, so I will not try to respond in French. Comments
inline below.

Nous voyons en ce moment les avancements finaux en chimie et nous
devons compléter un code python permettant de calculer l’avancement
final selon différentes variables.
Voilà mon code:

Your cut/paste has lost all the indenting, which is important in Python.
Next time, enclose the code (and error messages) in triple backticks to
preserve leading spaces, eg:

your code
goes here

In the leading up code you have:

import numpy as np
[...]
# La reaction consideree est A + B -> C + D
# Coefficients stoechiometriques
a, b, c, d = 1, 1, 1, 1
# Quantites de matiere initiales et volume initial
n_iA, n_iB, n_iC, n_iD = 0.1, 0.1, 0, 0
V = 100.0e-3
# Constante d'equilibre
K = 1e-1
# Calcul de l'avancement final et generation des valeurs de x entre 0 mol et xmax
xmax = min(n_iA/a, n_iB/b)
x = np.arange(0, xmax, xmax/10000.0)
tau = x/xmax
# Calcul des quantites de matiere et du quotient de reaction a chaque avancement x
n_A = n_iA-a*x
n_B = n_iB-b*x
n_C = n_iC+c*x
n_D = n_iD+d*x
Q_r = ((n_C/V)**c*(n_D/V)**d)/((n_A/V)**a*(n_B/V)**b)

Just offering my guess at the correct indenting here:

# Determination de l'avancement final x_f
for i in range(len(x)) :
    if Q_r<K:
        x_f = x[i]
        i = i+1
    else :
        continue

So, let us look at your error message:

ValueError Traceback (most recent call last)
<ipython-input-13-8b9e8f373c4f> in <module>()
21 # Determination de l'avancement final x_f
22 for i in range(len(x)) :
---> 23 if Q_r<K:
24 x_f = x[i]
25 i = i+0,1
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Since K is 0.1, this implies that Q_r is not a scalar but probably a
numpy array. If I run your code interactively I get:

>>> Q_r = ((n_C/V)**c*(n_D/V)**d)/((n_A/V)**a*(n_B/V)**b)
>>> Q_r
array([0.00000000e+00, 1.00020003e-08, 4.00160048e-08, ...,
       1.11044454e+07, 2.49900010e+07, 9.99800010e+07])

So it is an array. That is not comparable to a float such as K (0.1).

I am guessing that what you are doing is looking for values in Q_r which
are less than K, and setting x_f in accordance with that. If that is so,
you want to compare each element of Q_r, like this:

# Determination de l'avancement final x_f
for i in range(len(x)) :
    if Q_r[i]<K:
        x_f = x[i]
        i = i+1
    else :
        continue

I notice also that you have:

i = i+1

inside the loop. This will be ineffective, because the for-loop will
advance i. Usually you do not want to fiddle with a loop variable (“i”)
inside the loop. However, because the for-loop is advancing i you can
omit this line.

Note that there is a better way to write this for-loop, using the
builtin enumerate() function. Knowing that Q_r and x are the same
length, you can go:

# Determination de l'avancement final x_f
for i, Q_r_i in enumerate(Q_r):
    if Q_r_i<K:
        x_f = x[i]
    else :
        continue

The enumerate() function returns an (index,value) pair for the thing it
is iterating, so you get (0,Q_r[0]), (1,Q_r[1]) and so on. This lets you
use the value from Q_r directly as Q_r_i in the test.

Another thing you can do, ifyou do not care about “i” at the end (you
only seem to want x_f), is use the zip() function:

# Determination de l'avancement final x_f
for Q_r_i, x_i in zip(Q_r, x):
    if Q_r_i<K:
        x_f = x_i
    else :
        continue

The zip() function pairs up elements from 2 (or more) arrays, yielding
(Q_r[0],x[0]), (Q_r[1],x[1]) and so on. This gets you Q_r_i and x_i as
each pair of values from the 2 arrays, without bothering with “i” at
all.

Finally, regarding the for-loop logic. Your if-statement goes like this:

    if Q_r_i<K:
        x_f = x_i
    else :
        continue

The “else:continue” is redundant - the loop will continue anyway. You
can get rid of it:

    if Q_r_i<K:
        x_f = x_i

and if you only care about the first x_f value you find, you can exit
the loop early using “break”.

    if Q_r_i<K:
        x_f = x_i
        break

Finally, I recommend putting print() statements in your code to see
values before failures if the code is unclear. Example from your
original loop:

print("K =", K)
for i in range(len(x)) :
    print("i =", i)
    print("Q_r =", Q_r)
    if Q_r<K:
        x_f = x[i]
        i = i+1
    else :
        continue

This would at least make it clear that Q_r was an array and not the
value from the array, which may have helped understand the error
message.

Salut,
Cameron Simpson cs@cskk.id.au