Seite 1 von 1

return funktion gibt nur eine Variable aus

Verfasst: Freitag 4. Januar 2019, 18:56
von Krackerer
Hallo,

in meinen Programm ignoriert Python einfach die zweite Variable die ausgegeben werden sollte. Die np.size ist bei u_gs und u_jacobi 100. Warum wird der Iterationszähler i nicht ausgegeben?

Code: Alles auswählen

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d

def jacobi(u,itmax):
    [Nx,Ny] = np.shape(u)
    u2      = np.zeros([Nx,Ny]);u2[:,0]=u[:,0];u2[:,Ny-1]=u[:,Ny-1];u2[0,:]=u[0,:];u2[Nx-1,:]=u[Nx-1,:]
    i=0
    while i<itmax:
        #calc u2=u(k+1)
        for j in range(1,Nx-1):
            for l in range(1,Ny-1):
                u2[j,l] = 0.25* (u[j+1,l]+u[j-1,l]+u[j,l-1]+u[j,l+1])
        #print(u2)
        if np.allclose(u,u2,atol=1e-2):
            return(u2)
        i+=1
        u=u2
    print("convergence criterion not met after %i iterations" %i)
    return u2

def gs(u,itmax):
    [Nx,Ny] = np.shape(u)
    u2      = np.zeros([Nx,Ny]);u2[:,0]=u[:,0];u2[:,Ny-1]=u[:,Ny-1];u2[0,:]=u[0,:];u2[Nx-1,:]=u[Nx-1,:]
    i=0
    while i<itmax:
        #calc u2=u(k+1)
        for j in range(1,Nx-1):
            for l in range(1,Ny-1):
                u2[j,l] = 0.25* (u[j+1,l]+u2[j-1,l]+u2[j,l-1]+u[j,l+1])
        #print(u2)
        if np.allclose(u,u2,atol=1e-2):
            return(u2)
        i+=1
        u=u2
    print("convergence criterion not met after %i iterations" %i)
    return i,u2

def 


#initialisation and boundary conditions
itmax = 1000
Nx=10
Ny=10
x=np.linspace(-1,1,num=Nx,endpoint=True)
y=np.linspace(-1,1,num=Ny,endpoint=True)
u=np.zeros([Nx,Ny]) ; u_exact = np.zeros([Nx,Ny])# ; u_jacobi=np.zeros([Nx,Ny])
u[:,0]=x**2-1 ; u[:,Ny-1]=x**2-1 ; u[0,:]=1-y**2 ; u[Nx-1,:]=1-y**2

#calc exact solution
for j in range(Nx):
    u_exact[j,:] = x[j]**2 - y**2

#calc numeric solutions
u_jacobi = jacobi(u,itmax)
u_gs     = gs(u,itmax)
print(np.size(gs(u,itmax)))

Re: return funktion gibt nur eine Variable aus

Verfasst: Freitag 4. Januar 2019, 19:21
von __blackjack__
@Krackerer: Das ist alles ein bisschen lang um das mal eben so zu verstehen und zu sehen wo Du denn etwas anderes erwartest was passiert und was genau Du wo erwartest und was da stattdessen passiert. Zumal das auch gar nicht lauffähig ist, weil da mitten drin ein ``def`` steht was syntaktisch falsch ist.

Was beim schnellen drüber schauen auffällt ist das `gs()` entweder nur `u2` zurück gibt, falls die ``if``-Bedingung in der Schleife zutrifft, oder ein Tupel aus `i` und `u2` falls die Bedingung der ``while``-Schleife zutrifft. Das ist eine komische API, denn der Aufrufer muss dann ja unterscheiden welchen Fall er da zurück bekommt. Solche Asymmetrien sollte man vermeiden.

``return`` ist übrigens keine Funktion und man sollte das deshalb auch nicht so schreiben als wäre es eine. Nach dem Schlüsselwort sollte ein Leerzeichen stehen und Klammern sollte man nur setzen wenn das die Lesbarkeit fördert. Also beispielsweise wenn es mehrere längere Ausdrücke sind die Elemente eines literalen Tupel bilden und man die Kommas leicht übersehen kann. Sicher nicht wenn da einfach nur ``return u2`` steht.

Re: return funktion gibt nur eine Variable aus

Verfasst: Freitag 4. Januar 2019, 22:07
von Sirius3
Zu dem was __blackjack__ schon geschrieben hat: ; sollte man nicht benutzen, sondern jede Anweisung in eine neue Zeile schreiben. `l` ist ein sehr schlechter Variablenname, weil man ihn sehr leicht mit 1 verwechseln kann, was mir beim Lesen öfter passiert ist. Statt der for-Schleifen würde man besser mit slices arbeiten. So ganz verstanden habe ich aber nicht, wie Dein gewünschtes Ergebnis vom aktuellen abweicht.

Re: return funktion gibt nur eine Variable aus

Verfasst: Samstag 5. Januar 2019, 09:29
von noisefloor
Hallo,

wenn eine Funktion mehr als einen Wert zurück gibt, du den Rückgabewert aber nur an eine Variable bindest, erhältst du automatisch ein Tupel:

Code: Alles auswählen

>>> def foo():
...     return 3, 'bar'
... 
>>> a = foo()
>>> a
(3, 'bar')
>>>
Auf die Elemente des Tupels kannst du per Index zugreifen.

Aber, wie von __blackjack__ schon gesagt: ein _oder_ zwei Werte zurück liefern ist schlecht, weil inkonsistent. Es sollten im gegebenen Fall dann immer zwei Werte sein. Der eine könnte ja auch `None` sein, damit kann man dann wenigsten arbeiten.

Gruß, noisefloor

Re: return funktion gibt nur eine Variable aus

Verfasst: Samstag 5. Januar 2019, 12:20
von __blackjack__
@noisefloor: In diesem Fall gibt es den Wert für das erste Element ja aber auch in dem Fall wo im Code kein Tupel zurückgegeben wird.

@Krackerer: Wobei mir gerade auffällt, dass die beteiligten ``while``-Schleifen eigentlich ``for``-Schleifen sein sollten. Und ``u=u2`` dürfte ein Fehler sein, denn dadurch kommt die Schleife nie über die zweite Iteration hinaus, weil danach beide Namen für das selbe Array stehen und die Abbruchbedingung in dem ``if`` damit natürlich immer wahr ist, denn die Werte in einem Array sind natürlich immer gleich wenn man es mit sich selbst vergleicht. ;-) An der Stelle möchtest Du vielleicht lieber eine Kopie erstellen und die dann an `u` binden.

Re: return funktion gibt nur eine Variable aus

Verfasst: Montag 7. Januar 2019, 17:22
von Krackerer
Vielen Dank für die ganzen Antworten!

Ich habe sehr lange nicht verstanden warum es nicht funktioniert aber wie @_blackjack_ angemerkt hat, liegt es daran, dass Bedingung immer erfüllt wird und ich ernsthaft immer übersehen habe, dass dort nur u2 steht. Habe diesen Fehler tagelang gesucht...

ja stimmt an der Bedingung muss ich noch feilen, die stimmt nicht. (das mit dem u=u2). Warum meine while schleife eine for schleife sein sollte verstehe ich allerdings nicht.

EDIT: aber warum ist die bedingung schon bei i=2 erfült? ich ändere u2 ja vor dem vergleich. und wenn die beiden Arrays ähnlich genug sind soll es ja abbrechen..
EDIT2: achso, wenn ich schreibe u=u2 dann sind diese variablen die selben? wie mach ich das wenn ich nur den wert hineinschreiben soll? mit u=np.array(u2)

Re: return funktion gibt nur eine Variable aus

Verfasst: Montag 7. Januar 2019, 17:37
von __blackjack__
@Krackerer: Weil man dafür ``for``-Schleifen nimmt. Das spart zwei Zeilen Code und man sieht auch gleich das `i` tatsächlich nur von der Schleife abhängt ohne den Code im Schleifenkörper zu kennen.

Re: return funktion gibt nur eine Variable aus

Verfasst: Montag 7. Januar 2019, 17:44
von Krackerer
__blackjack__ hat geschrieben: Montag 7. Januar 2019, 17:37 @Krackerer: Weil man dafür ``for``-Schleifen nimmt. Das spart zwei Zeilen Code und man sieht auch gleich das `i` tatsächlich nur von der Schleife abhängt ohne den Code im Schleifenkörper zu kennen.
Ich muss zugeben den unterschied der beiden Schleifen nicht wirklich zu kennen. Das muss ich mir wohl mal anschauen. Vielen Dank an alle, sieht so aus als würde es jetzt funktionieren!