Operands could not be broadcast together with shapes

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Basilius Sapientia
User
Beiträge: 46
Registriert: Freitag 5. September 2014, 22:34

Ich habe folgenden Code:

Code: Alles auswählen

from __future__ import division
import numpy as np
import matplotlib.pyplot as plt

RT=8.3144621 #J/K/mol
pi=3.1415926535
Na=6.022e23 #1/mol
r=6*10**(-10) #m
D=np.array([2, 3])*10**(-9) #m2/s
kdd=np.array([1, 4])*10**(11) #1/s
Get=10e3 #J/mol
Gdd=np.arange(-100, 30+1, 1)

print Gdd

kq=(4*pi*Na*r)/((1/D)+(3/(kdd*r**2))*(np.exp((((Get/2)**2+(Gdd)**2)**(1/2)+Get/2)/(RT))+np.exp(Get/RT)))
Was kann ich tun? Was mache ich falsch? Error: operands could not be broadcast together with shapes (2,) (131,) . Am Ende hätte ich gerne ein plot (kq, Gdd) - mit zwei funktionen. Ich benutze oben ein array, weil der erste Graph D=2 und kdd=1 haben soll, die zweite Kurve im gleichen Graph soltle D=3 und kdd=4 haben (natürlich mit den richtigen Potenzen). Was mache ich also falsch?

PS! Plotten schaffe ich wahrscheinlich schon. Wäre da nur nicht der Error. Danke im Voraus!
BlackJack

@Basilius Sapientia: Du müsstest die Berechung von `kq` solange in Teilergebnisse runterbrechen bis zu weisst welcher Operator zu dieser Ausnahme führt und Dir dann die Operanden anschauen ob die so aussehen wie Du das erwartest.

Spoiler: Du versuchst diese beiden Arrays zu multiplizieren:

Code: Alles auswählen

array([  5.83333333e+08,   3.54166667e+08])

array([ inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,
        inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,
        inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,
        inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,
        inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,
        inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,
        inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,
        inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,
        inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,
        inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,
        inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,
        inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf,  inf])
Mal davon abgesehen das die Dimensionen dafür nicht passen sehen die `inf`-Werte auch verdächtig aus.
Basilius Sapientia
User
Beiträge: 46
Registriert: Freitag 5. September 2014, 22:34

Tut mir leid, ich verstehe nicht so richtig, was du meinst? Die Zahlen die du im array erwähnst habe ich doch in meinem Code nicht drinnen? Was ich am Ende gerne haben würde, wäre ein Graph. Der Graph sollte folgende Kurven haben: Gdd,kq1 und Gdd,kq2. Dafür brauche ich aber die Werte, sprich die y-Koordinatenpunkte, für die zwei kq's. Und dann ist das Problem aufgetaucht.

Es tut mir wirklich leid, aber ich verstehe nicht wirklich was du mir sagst (liegt an mir, nicht an dir). Das mit dem Herunterbrechen leuchtet ein. Allerdings finde ich den Fehler nicht.

Vielleicht sollte ich kein Array nutzen? Was ich mit den Arrays bezwecken wollte war, dass die Punkte für kq1 ausgerechnet wird mit der ersten Zahl in jedem Array, und dann die kq2 Werte mit der zweiten Zahl im Array. Vielleicht liegt da der Fehler?

Ich bräuchte etwas mehr Hilfe, ich bin nicht besonders gut was Programmieren angeht :-)
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Basilius Sapientia: Die Exponentialfunktion von großen Argumenten werden schnell so groß, dass sie nicht mehr mit Floats darstellbar sind, daher unendlich (inf). Wenn Du jede Klammer für sich ausrechnest wirst Du doch einfach feststellen, welcher dieser Klammerausdrücke ohne und welche mit Fehler durchlaufen.
Basilius Sapientia
User
Beiträge: 46
Registriert: Freitag 5. September 2014, 22:34

Wie ihr mir empfohlen habt, habe ich meinen Code aufgeteilt. Was ich als top und als left beschrieben habe ergibt Zahlen. rl und rr ergeben keine Zahlen, sondern nur inf. Allerdings ergibt rl und rr Zahlen, wenn man np.exp entfernt. Allerdings kann ich, logischerweise, np.exp nicht einfach weglassen, da die Formel dann falsch wäre.

Ich denke, das Problem liegt an np.exp? Bei rl und rr ergibt dies nämlich nur inf! Und ich weiß nicht, wie ich dies lösen soll.

Code: Alles auswählen

from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
import math

RT=8.3144621 #J/K/mol
pi=3.1415926535
Na=6.022e23 #1/mol
r=6*10**(-10) #m
D=np.array([2, 3])*10**(-9) #m2/s
kdd=np.array([1, 4])*10**(11) #1/s
Get=10e3 #J/mol
Gdd=np.arange(-100, 30+1, 1)

top=(4*pi*Na*r)
left=((1/D)+(3/(kdd*r**2)))
rl=(np.exp((((Get/2)**2+Gdd**2)**(1/2)+Get/2)/(RT)))
rr=(np.exp(Get/RT))

#kq=top/(left*(rl+rr))
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Basilius Sapientia: um es nochmal deutlich zu sagen, die Formeln passen weder von den Einheiten, der Größenordnung oder der Matrixdimensionen überein. Da ist definitiv was falsch. Woher hast Du die Formeln?
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Zum Codestil:
  • Du hast viel zu viele Klammern. Klammere nur da wo es notwendig ist, Du klammerst aber fast alles.
  • Statt 10**(-9) nimm 1.e-9
  • Statt (...)**(1/2) nimm np.sqrt(...).
  • Benutze Floats und verlass Dich nicht auf __future__
  • Wenn Du numpy benutzt, dann benutze nicht math.
  • pi ist in numpy definiert.
  • R und N_A sind in scipy.constants definiert
Zum Fehler
Wenn das Argument von exp größer als ca. 750 wird, dann kommt inf raus. D.h. entweder sind Deine Größenordnungen etwas durcheinander (z.B soll der Radius wirklich in der Größenordnung des Atomdurchmessers sein?) oder Du hast in der Formel irgendwo noch was vergessen. Wie lautet denn die physikalische Formel, die Du versuchst zu programmieren?
a fool with a tool is still a fool, www.magben.de, YouTube
Basilius Sapientia
User
Beiträge: 46
Registriert: Freitag 5. September 2014, 22:34

Danke für die viele Hilfe! Jetzt funktioniert jedes einzelne Bruchstück ohne inf zu zeigen. Leider bleibt das Hauptproblem. Ich habe allerdings nicht das mit "__divide__ nicht nutzen, sondern lieber Floats" verstanden.

Hier der Code:

Code: Alles auswählen

from __future__ import division
import numpy as np
import matplotlib.pyplot as plt

RT=8.3144621*298.15 #J/K/mol
Na=6.022*1e23 #1/mol
r=6*1e-9 #dm
D=2*np.array([2, 3])*1e-7 #dm2/s
kdd=np.array([1, 4])*1e11 #1/s
Get=10e3 #J/mol
Gdd=np.arange(-100, 30+1, 1)

top=4*np.pi*Na*r
left=1/D+3/(kdd*r**2)
rl=np.exp((np.sqrt((Gdd*1e3/2)**2+Get**2)+Gdd*1e3/2)/RT)
rr=np.exp(Gdd*1e3/RT)

#kq=top/(left*(rl+rr))
Jetzt muss "nur" noch kq Zahlen ergeben. Ich denke, der Fehler liegt an meine arrays?

Was ich mit den Arrays bezwecken wollte
kq soll keine Zahl ergeben, sondern eine Zahlenreihe. Beziehungsweise zwei Zahlenreihen. Nennen wir die eine Datenreihe kq1, also kq minimum, dann sollte python für mich mit D=2*1e-7 und kdd=1*1e11 rechnen. Dann sollte Python noch eine zweite Datentabelle, kq2, rausgeben - also die Maximumswerte: D=3*1e-7 und kdd=4*1e11.

Plot
Dann wollte ich Graph machen. Einen mit Gdd (kJ/mol) auf der x-Akse und kq auf der Y-Akse in M^-1*s^-1. Deshalb benutze ich auch dm -> denn zum Schluß erhalte ich dm3=L und zusammen mit anderen Einheiten ergibt dies eben 1/Molar * 1/Sekund. Auf diesem Graph sollte dann kq1 (also minimum) und kq2 (also maximum) abgebildet sein, als zwei Kurven.

Und dann noch einen zweiten Graph erstellen - einfach den oben genannten Graphen, nur halt logarithmisch.

Formel
Wir mussten die Quenchingrate, k_q, von der Stern-Volmer-Gleichung herleiten und berechnen. Es ist eine Formel in Spektrometrie. Wir sollten daraufhin den Graphen zeichnen, und als theoretische Grundlage für die Analyse von unseren gemessenen Ergebnissen nutzen. Leider kann man in diesem Forum kein LaTeX nuten, ansonsten hätte ich ja aufschreiben können, wie die Formel aussieht. Ich bin mir ziemlich sicher, dass die Formel die wir hergeleitet haben, richtig ist. Und ich habe jetzt alles vier mal kontrolliert.

Problem
Es ist immer noch das gleiche Problem. Ich denke, es liegt an den Arrays. Ich habe D und kdd mit einer Zahl anstatt einem Array ersetzt - und habe Zahlen herausbekommen - und zwar die richtigen, so weit ich sehen kann. Also müssen die Arrays ersetzt(?) oder verändert werden.

Was ich mir wünsche
Ich dachte man könnte es mit Arrays machen, aber offenbar nicht? Die kq-Formel ist die richtige - nur versteht Python offenbar nicht, dass es erst eine Datenreihe mit D1 (also die erste Zahl im Array) und kdd1 erstellen soll, und dann eine Datenreihe mit D2 (also die zweite Zahl im Array) und kdd2. Natürlich müsste ich die dann definieren können. Wenn ihr mir einen Trick verraten könntet, womit man zwei Datenreihen erhält, wo die erste Datenreihe (kq1) die erste Zahl im Array und die zweite Datenreihe mit den zweiten Zahlen in den Arrays erstellt werden, und dann noch wie man die zwei kq-Datenreihen als kq1 und kq2 definieren könnte, das wäre super. Plotten schaffe ich schon.

Vielen Dank im Voraus!
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Basilius Sapientia: Du kannst ohne Sorge Dich darauf verlassen, dass wenn Du division von __future__ importierst, Deine Divisionen nicht ganzzahlig sind. Und Informatiker benutzen gerne die "e"-Schreibweise, wenn Dir aber 10^x lieber ist, dann schreib das so. Deine Einheitenkommentare stimmen jetzt nicht mehr. Da es zur Prüfung der Richtigkeit der Formeln zwingen ist, solltest Du das schleunigst reparieren.
Dein Problem ist, dass Du verschiedene Dimensionen hast, Du aber nur 1-Dimensionale Vektoren benutzt. Die eine Dimension sind die x-Werte in Gdd, die andere Deine zwei Kurven. Das kann numpy natürlich nicht auf magische Art und Weise wissen, sondern Du must es explizit sagen, z.B. so:

Code: Alles auswählen

D = 2*np.array([[2, 3]])*1e-7 #dm2/s
kdd = np.array([[1, 4]])*1e11 #1/s
Gdd = np.arange(-100, 30+1, 1).reshape(-1, 1)
Basilius Sapientia
User
Beiträge: 46
Registriert: Freitag 5. September 2014, 22:34

Das hat mein Problem gelöst! Vielen Dank! Ich erhalte jetzt zwei Säulen mit den richtigen Zahlen!

Eine (hoffentlich) allerletzte Frage: wie definiere ich die eine Säule als kq1 und die andere als kq2?
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Basilius Sapientia: das ist hoffentlich gar nicht nötig. Durch Sequence-Unpacking:

Code: Alles auswählen

kq1, kq2 = kq.T
Basilius Sapientia
User
Beiträge: 46
Registriert: Freitag 5. September 2014, 22:34

Das Problem ist jetzt gelöst :-) ... Danke nochmal :-)
Antworten