Gewöhnliche Differentialgleichungen mit Mathematica

Eine kleiner Einblick

Version 0.89  © 2005 Roland Steinbauer <roland . steinbauer@univie . ac . at>
(\(unter\ teilweiser\ Verwendung\ eines\ Notebooks\ von\ \ Evelina\ Erlacher\)
 <evelina . erlacher@univie . ac . at> zur Analysis2 im Sommersemester 2004)

Der Befehl DSolve

Die Grundsyntax

Mathematica ist in der Lage, eine Reihe verschiedener Klassen von gewöhnlichen Differentialgleichungen zu lösen. Der zugehörige Befehl heißt DSolve und funktioniert analog dem Solve-Befehl.
DSolve verlangt (in der Grundfunktion) drei Argumente: die Gleichung, die abhängige und die unabhängige Variable, also

DSolve[x'[t] == f[x[t], t], x[t], t].

Hier als Referenz

({{DSolve[gleichung,x[t],t], versucht die Differentialgleichung  gleichung  nach x[t] zu lösen wobei  t  die 
unabhängige Variable ist}})

Ein einfaches Beispiel

Wir machen uns nun mit DSolve anhand eines einfachen Beispiels (vgl. VO §1.1) vertraut.

DSolve[x'[t] == a*x[t], x[t], t]

Die Integrationskonstante wird als C[1] angezeigt.
Die Lösung wird als eine (Menge von) Ersetzungsregeln (sog. rules) ausgegeben. Um die Lösungsfunktion (etwa zur weiteren Bearbeitung) explizit darzustellen kann wie folgt vorgegangen werden.

x[t] /. %[[1]]

Die Notation [[1]] ist notwendig, um das erste Element aus der Liste der Ersetzungsregeln zu verwenden. Bei Weglassen der Klammern ergibt sich nämlich nur.

x[t] /. %%

Für eine detailliertere Diskussion der Ausgabeformen von DSolve siehe die Online Hilfe zu "pure functions in differential equations".

Der Umgang mit DSolve kann natürlich auch ein bißchen eleganter gestaltet werden, etwa so

ode[t_, x_] := (x'[t] == a*x[t])
lsg = DSolve[ode[t, x], x[t], t]

x1[t_] = x[t] /. lsg[[1]]

So kann die Lösung überprüft werden.

ode[t, x1]

Clear[ode, lsg, x1]

Anfangswertprobleme

Anfangswertprobleme können wir lösen, indem wir die Anfangsbedingung als zusätzliche Gleichung an den Befehl DSolve übergeben.

({{DSolve[{gleichung,anfangsbedingung},x[t],t],    \(versucht\ das\ Anfangswertproblem\ zu\ lösen\)}})

Als Beispiel bearbeiten wir weiter obige Gleichung.

DSolve[{x'[t] == a*x[t], x[0] == x0}, x[t], 
      t]

Oder etwas eleganter.

ode[t_, 
        x_] := (x'[t] == a*x[t])
ab[x0_] := (x[0] == x0)

sol = DSolve[{ode[t, x], ab[x0]}, x[t], t]

x1[t_, x0_] = x[t] /. sol[[1]]

Clear[ode, ab, sol]

Visualisierung der Lösung(en)

Die Grundsyntax

Die Lösungskurve einer ODE ist eine Funktion von ℝ nach ℝ und kann also mit dem Plot-Befehl gezeichnet werden; dieser verwendet folgende Syntax:

?Plot

Außerdem müssen wir mittels des Befehls Evaluate sicherstellen, dass zuerst die Funktion ausgewertet wird (sie ist ja mittels Ersetzungsregel definiert) und dann erst geplottet.

?Evaluate

Ein einfaches Beispiel, die Zweite

Zur Visualisierung der Lösung obiger Gleichung müssen wir noch den Parameter fixieren.

Plot[Evaluate[x1[t, 1] /. a -> 1], {t, -2, 5}]

Um eine Schar von Lösungen für verschiedene Anfangswerte zu plotten verwenden wir den Befehl Table.

?Table

lsgk[t_] = Table[x1[t, x0] /. a -> 1, {x0, -4, 4}]
Plot[Evaluate[lsgk[t]], {t, -1, 4}]

Das qualitative Verhalten der Lösungen (vgl. Vorlesung 1.5) können wir visulaisieren indem wir den Parameter variieren.

lsgka[t_] = 
      Table[x1[t, x0], {x0, -4, 4}]
Plot[
      Evaluate[lsgka[t] /. a -> -1], {t, -4, 
        1}]
Plot[Evaluate[lsgka[t] /. a -> 0], {t, -3, 3}]
Plot[Evaluate[lsgka[t] /. a -> 1], {t, -1, 4}]

Selbstverständlich können wir auch alle Kurven in einer Grafik darstellen; die Frage ist allerdings ob das in diesem Fall übersichtlicher ist...

Plot[
      Evaluate[{lsgka[t] /. a -> -1, lsgka[t] /. a -> 0, 
          lsgka[t] /. a -> 1}], {t, -2, 2}]

Clear[x1, lsgk, lsgka]

Richtungsfelder

Basissyntax

Um mit Mathematica Richtungsfelder von ODEs (1. Ordnung) darzustellen können wir den Befehl PlotVectorField verwenden; dieser ist im Paket Graphics enthalten.

Needs["Graphics`PlotField`"]

Die Syntax von PlotVectorField ist.

({{"PlotVectorField["{(Subscript["f", "x"])," "(Subscript["f", "y"])}," "
     {"x"," ""xmin"," ""xmax"}," "{"y"," ""ymin"," ""ymax"}"]"" ", "plot the vector field corresponding to the vector \nfunction "f=(fx, fy)}})

Dabei wird im Punkt (x, 
          y) ein Vektor (symbolisiert als kleiner Pfeil)
in Richtung ((Subscript[f, x]), (Subscript[f, y])) eingezeichnet .  
          Beim Zeichnen des Richtungsfeld einer ODE 
x' = f (t, x) ist die Richtung durch x' = f,  
      also ((Subscript[f, x]), (Subscript[f, y])) = (1, f (t, x)) gegeben.

Ein Beispiel

Wir diskutieren das logistische Populationsmodell (vgl. VO §1.2) x'(t)=ax(t)(1-x(t))=:f_a(x).

f[a_, x_] := a*x (1 - x)

bild1 = 
      PlotVectorField[{1, f[1, x]}, {t, -2, 2}, {x, -1, 2}, 
        PlotPoints -> 10, Axes -> True]

Die Gleichgewichtspunkte bei x=0 und x=a=1 finden wir explizit natürlich mittels.

Solve[f[1, x] == 0, x]

Dsolve scheitert allerdings beim Finden dieser Lösungen.

DSolve[{x'[t] == x[t]*(1 - x[t]), x[0] == 0}, x[t], 
      t]
DSolve[{x'[t] == x[t]*(1 - x[t]), x[0] == 1}, x[t], 
      t]

Nun wollen wir auch die Lösungen darstellen, um zu sehen, dass diese wirklich tangential zum Richtungsfeld sind. Wir beginnen mit dem "interessanten" Bereich 0<x0<1.

lsgk := 
      Table[x[t] /. 
          DSolve[{x'[t] == x[t]*(1 - x[t]), x[0] == x0}, x[t], 
            t], {x0, 1/10, 9/10, 1/20}]
bild2 = 
      Plot[Evaluate[lsgk], {t, -2, 2}, 
        PlotRange -> {0, 1}]

Mit dem Befehl Show können wir nun beide Graphiken gemeinsam ausgeben lassen. Genauer ermöglicht der Befehl Show, verschiedene Plots in einer einzigen Zeichnung vereinigt zu zeigen. Show akzeptiert als Argument ein Graphics-Object oder eine Liste von Graphics-Objekten. Viele der für Plot möglichen Optionen sind auch in Show möglich.

?Show

Show[bild1, bild2, PlotRange -> {-1, 2}, 
      Axes -> True]

Wir können auch Lösungen außerhalb der im Modell interessanten Region ansehen um die Quellen und Senkeneigenschaften der Gleichgewichtspunkte zu illustrieren.

lsgku := 
      Table[x[t] /. 
          DSolve[{x'[t] == x[t]*(1 - x[t]), x[0] == x0}, x[t], 
            t], {x0, -5/10, -1/10, 1/20}]
bild3 = 
      Plot[Evaluate[lsgku], {t, -2, 2}, 
        PlotRange -> {-2, 0}]

lsgko := 
      Table[x[t] /. 
          DSolve[{x'[t] == x[t]*(1 - x[t]), x[0] == x0}, x[t], 
            t], {x0, 11/10, 15/10, 1/20}]
bild4 = 
      Plot[Evaluate[lsgko], {t, -2, 2}, 
        PlotRange -> {1, 3}]

Um ein vollständiges Bild aufbauen zu können, fehlen uns nurmehr die Gleichgewichtslösungen.

bild5 := Plot[{0, 1}, {t, -2, 2}]
Show[bild1, bild2, bild3, bild4, bild5, 
      PlotRange -> {-1, 2}]

Clear[bild1, bild2, bild3, bild4, bild5, lsgk, lsgko, lsgku, 
      f]

Systeme von gewöhnlichen Differentialgleichungen

DSolve, die Zweite.

Der Befehl DSolve kann auch dazu verwendet werden Syteme von ODEs (und auch Systeme von Anfangswertproblemen) zu lösen .  Die Syntax lautet.

({{DSolve[{(Subscript[gl, 1]),...,(Subscript[gl, n])},
              {(Subscript[x, 1])[t],...,(Subscript[x, m])[t]},t],    versucht das Differentialgleichungssystem  (Subscript[gl, 1]),...,(Subscript[gl, n])  nach den 
    Funktionen (Subscript[x, 1]),...,(Subscript[x, m])  (mit unabhängiger Variablen  t ) zu lösen.}})

Ein Beispiel

odes := {x'[t] == 
          y[t], y'[t] == -x[t]}
lsg = DSolve[odes, {x[t], y[t]}, t]

x1[t_] = x[t] /. lsg[[1]]
y1[t_] = y[t] /. lsg[[1]]

Darstellung der Lösung

\(Wollen\ wir\ die\ Lösung\ des\ obigen\ Systems\ graphisch\ darstellen\), \(so\ müssen\ wir\ sie\ als\ Funktion\ t -> \((x \((t)\), y \((t)\))\)\), also als Funktion von ℝ->(ℝ^2) mittels des Befels ParametricPlot darstellen.

?ParametricPlot

Außerdem spezifizieren wir wieder Anfangsbedingungen.

lsg1 = 
      DSolve[{Flatten[odes], x[0] == 1, y[0] == 0}, {x[t], y[t]}, 
        t]
lsgk = {x[t], y[t]} /. lsg1[[1]]
ParametricPlot[lsgk, {t, 0, 2*Pi}, AspectRatio -> 1]

Clear[odes, lsg, x1, y1, lsg1, lsgk]

Einige weitere Beispiele --- Möglichkeiten und Grenzen

Lineare Gleichungen erster Ordnung

Wir können nun einige der in der Vorlesung erwähnten Beispiele ganz "billig" mittels Mathematica lösen.
Wir beginnen mit linearen, nichtautonomen Gleichungen 1. Ordnung.

DSolve[x'[t] + x[t] == t^2, x[t], t]

DSolve[x'[t] == Sin[t] + Cos[t]*x[t], x[t], t]

Die allgemeinelineare ODE 1. Ordnungläßt sich ebenfalls knacken.

DSolve[x'[t] == a[t]*x[t] + b[t], x[t], t]

Auch das Anfangswertproblem mit x(0)=0 macht keine Probleme.

DSolve[{x'[t] == a[t]*x[t] + b[t], x[0] == 0}, x[t], 
      t]

Das allgemeine AWP allerdings schon...

DSolve[{x'[t] == a[t]*x[t] + b[t], x[t0] == x0}, x[t], 
      t]

Nichtlineare Gleichungen erster Ordnung

Wir bearbeiten die homogene ODE aus 2.26 in der VO. Schon eine direkte Attacke auf das AWP führ ans Ziel
(Wir müssen die ODE nicht explizit auf homogene Form bringen).

ode = (t x'[t] == 
          x[t] - t - t*Exp[-x[t]/t])
ab = (x[1] == 0)
DSolve[{ode, ab}, x[t], t]

Clear[ode, ode1, ab]

Oft kann es passieren, dass die Lösung nur in Termen sog. spezieller Funktionen dargestellt werden kann; so z.B. bei der folgenden Gleichung vom Riccati-Typ.

ode = (x'[t] == 
          c (t^m) + b x[t]^2)
sol = DSolve[ode, x[t], t]

Der hier auftretende Befehl BesselJ implementiert die sog. Besselfunktionen der ersten Art in Mathematica.
Mehr Auskunft gibt

?BesselJ

oder eine graphische Ausgabe. Dazu fixieren die Parameter und varieren die Konstante in einem eingeschränkten Bereich.

b := 1
m := 2
c := 1
lsgk := 
      Table[Evaluate[x[t] /. sol[[1]] /. C[1] -> C], {C, 1, 
          10}]
Plot[Evaluate[lsgk], {t, 1, 2}]

Clear[ode, sol, b, m, c, lsgk, x]

Gleichungen 2. Ordnung.

DSolve[x''[t] == k*x[t], x[t], t]

DSolve[y''[t] == a*y'[t] + k*y[t], y[t], t]

Nun nichtlinear.

DSolve[x''[t] == Sin[x[t]], x[t], t]

Hier scheitert Mathematica beim Brerechnen der Lösung; ebenso, falls die Gleichung als System erster Ordnung eingegeben wird---allerdings mit einem anderen Output.

DSolve[{x1'[t] == 
          x2[t], x2'[t] == Sin[x1[t]]}, {x1[t], x2[t]}, 
      t]

Bei der folgenden Gleichungen gibt sich Mathematica gleich geschlagen...

DSolve[x''[t] == x[t]^2 - t - Sin[x[t]], x[t], t]

DSolve versucht die Lösungsfunktion(en) in geschlossener Form anzugeben.Oft ist das aber nicht möglich und der DSolve-Befehl versagt daher. (Das kann auch (schon) bei Gleichungen 1. Ordnung passieren.)

In so einem Fall können wir versuchen, eine numerische Approximation an die Lösung zu finden. Das ist der Inhalt des nächsten Abschnitts.

Der Befehl NDSolve

Dieser Befehl dient dazu eine numerische Approximation an die Lösungsfunktion einer ODE zu finden. Im Unterschied zum DSolve-Befehl muss ein Intervall für die unabhängige Variable angegeben werden muss. Weiters hat das Gleichungssystem genügend Anfangs- (oder Rand)bedingungen zu enthalten — denn offensichtlich haben unbekannte Konstanten C[1], C[2] etc. nichts in einer numerischen Lösung verloren. Die Lösung ist nicht ein geschlossener Ausdruck, sondern eine die Lösungsfunktion numerisch approximierende sogenannte InterpolatingFunction,  die auf dem im Befehl angegebenen Intervall definiert ist.

({{NDSolve[gleichung,x,{t,tmin,tmax}],    versucht die Differentialgleichung  gleichung  nach der Funktion  
   x  (mit unabhängiger Variablen t aus dem Intervall  [tmin, tmax] ) 
   zu lösen, wobei  die Lösung als InterpolatingFunction 
   \(angegeben\ \(\(wird\)\(.\)\(
\)\)\)}, {NDSolve[{(Subscript[gl, 1]),...,(Subscript[gl, n])},
{(Subscript[y, 1]),...,(Subscript[y, m])},{t,tmin,tmax}],    versucht das Differentialgleichungssystem  (Subscript[gl, 1]),...,(Subscript[gl, n])  nach 
 den Funktionen   (Subscript[y, 1]),...,(Subscript[y, m])  
 (mit unabhängiger Variablen t aus dem Intervall  [tmin, tmax] ) 
 zu lösen, wobei  die Lösungen als 
 InterpolatingFunctions angegeben werden}})

\(\(Eine\ ODE\ numerisch\ zu\ lösen\ bedeutet\ grob\ gesprochen, \ eine\ Folge\ von\ Punkten\ \((t\_n, x\_n)\)\ zu\ berechnen, \ 
      die\ hoffentlich\ in\ der\ Nähe\ des\ Graphen\ der\ tatsächlichen\ Lösung\ liegen . \ 
          Statt\ einer\ Liste\ solcher\ \((Folgen\ von)\)\)\(\ \)\)
\(Punkten\ gibt\ Mathematica\ einen\ Interpolationsfunktion\ an, \ die\ zwischen\ diesen\ Punkten\ \(\(interpoliert\)\(.\)\)\)

Wir versuchen nun, die Gleichung zu knacken, an der wir oben gescheitert sind.

lsg = 
      NDSolve[{x''[t] == Sin[x[t]], 
          x[0] == 1, x'[0] == 0}, 
        x, {t, -3, 3}]

Um die Funktionswerte der Interpolationsfunktion auszugeben gehen wir analog zu früher vor.

x[-3] /. lsg[[1]]

Verlassen wir den Breich, den wir ursprünglich dem NDSolve-Befehl übergeben haben, berechnet Mathematica einen Wert, gibt aber auch eine Warnung aus---und das zu recht, da diese Werte sehr schnell sehr falsch werden können.

x[-5] /. lsg[[1]]

Schließlich können wir die Interpolationsfunktion auch zeichnen.

Plot[Evaluate[x[t] /. lsg[[1]]], {t, -3, 3}]

Clear[lsg, x]

Ein Fortgeschrittenes Beispiel

Wir betrachten das folgende nichtlineare System von zwei ODEs erster Ordnung 
x'[t]==f[x[t],y[t]]
y'[t]==g[x[t],y[t]]
mit den Funktionen

f[x_, y_] := (4 - y^2) x - 3 y
g[x_, y_] := (4 - x^2) y + 3 x

Wir verwenden den Befehl NDSolve, daher müssen wir zwei Anfangs- oder Randbedingungen angeben. Die Lösung ist eine Funktion von ℝ in den (ℝ^2) mit den Komponenten x und y.

loesungskurve = 
      NDSolve[{x'[t] == f[x[t], y[t]], y'[t] == 
            g[x[t], y[t]], x[0] == 1, y[0] == 0}, {x, y}, {t, 0, 
          1.5}]

Die Lösungskurve hat als Funktion von ℝ in den (ℝ^2) die Komponenten x und y.
Wir stellen diese zunächst einzeln als Funktionen von t dar.

Plot[
      Evaluate[x[t] /. loesungskurve[[1, 1]]], {t, 0, 1.5}]

Plot[
      Evaluate[y[t] /. loesungskurve[[1, 2]]], {t, 0, 1.5}]

Mit ParametricPlot zeichnen wir nun die Lösungskurve.

ParametricPlot[
      Evaluate[{x[t], y[t]} /. loesungskurve], {t, 0,  .5}]

Der nächste Befehl erzeugt eine Liste von NDSolve-Lösungen mit verschiedenen Anfangsbedingungen. Wir erhalten Ersetzungsregeln für insgesamt 13⋆13=169 verschiedene Lösungskurven. (Der Befehl Flatten bewirkt, dass alle bis auf die äußersten geschwungenen Klammern in der Ausgabe von Table weggelassen werden.)

loesungskurven1 = 
        Table[NDSolve[{x'[t] == f[x[t], y[t]], y'[t] == 
                  g[x[t], y[t]], x[0] == m, y[0] == n}, {x, 
                y}, {t, 0, 1.5}], {m, -6, 6}, {n, -6, 6}] // 
          Flatten;

Je zwei aufeinanderfolgende Ersetzungsregeln (eine für x, eine für y) sind die Komponenten einer bestimmten Lösungskurve. Das Ergebnis des nächsten Befehls ist eine Liste der Funktionsterme der Lösungskurven — d. h. die Ersetzungsregeln werden durch Substitution zu Funktionstermen (von InterpolatingFunctions) und die zusammengehörenden Komponenten werden in geschwungenen Klammern zusammengefasst.

kurven1 = 
        Table[{x[t] /. loesungskurven1[[i]], 
            y[t] /. loesungskurven1[[i + 1]]}, {i, 1, 337, 
            2}];

Nun können wir alle 169 Lösungskurven in einem Plot zeichnen. (Die Ausgabe von ParametricPlot — ein Graphics-Objekt — wird in die Variable bild1 geschrieben.)

bild1 = 
      ParametricPlot[Evaluate[kurven1], {t, 0, 1}, 
        AspectRatio -> Automatic, 
        PlotRange -> {{-6, 6}, {-6, 6}}]

Änhlich wie für ODEs erster Ordnung, kann für Systeme von zwei ODEs erster Ordnung ein Richtungsfeld definiert werden: Betrachtet man einen fixen Punkt (x[t], y[t]) ∈ (ℝ^2) einer bestimmten Lösungskurve,  so liefert (x'[t], y'[t]) = (f[x[t],y[t]], g[x[t],y[t]]) einen Tangentialvektor in (x[t], y[t]) an die Lösungskurve und gibt damit die ungefähre Richtung an, in die die Kurve weiter verläuft. Die Länge des Vektors korrespondiert dabei zur "Geschwindigkeit", mit der die Kurve an dieser Stelle durchlaufen wird.
Legt man über einen bestimmten Ausschnitt des (ℝ^2) ein Gitter, berechnet in jedem Gitterpunkt den zugehörigen Tangentialvektor und zeichnet anschließend alle Vektoren als Pfeile (mit dem Schaft im zugehörigen Gitterpunkt) ein, so erhält man ein "Vektorfeld". Die Lösungskurven verlaufen mit den durch die Pfeile dargestellten "Strömungen".

Auch in dieser Situation können wir den Befehl PlotVectorField verwenden.

bild2 = 
      PlotVectorField[{f[x, y], g[x, y]}, {x, -6, 6}, {y, -6, 
          6}]

Show zeigt nun beide Zeichnungen in einem Bild.

Show[{bild1, bild2}, Ticks -> None, 
      PlotRange -> {{-6, 6}, {-6, 6}}]

Clear[f, g, loesungskurve, loesungskurven1, loesungskurven2, kurve, 
      kurven1, kurven2, bild1, bild2]

Warnungen

Lokale Existenz

Mathematica spezifiziert kein Existenzintervall für Lösungen einer ODE/eines AWP. Hier muss der Benutzer selbst mitdenken und sehr genau aufpassen. Wir beginnen mit dem Erzbeispiel für Blow up.

ode := (x'[t] == x[t]^2)
ab := (x[0] == 1)
sol = DSolve[{ode, ab}, x[t], t]

Plot[Evaluate[x[t] /. sol], {t, -2, 2}]

Die Lösung des AWP ist maximal auf (-∞,1) definiert. Mathematica schweigt sich zu diesem Thema allerdings aus. (Auf (1,∞) löst x[t] zwar die ODE, nicht aber das AWP.)

NDSolve allerdings warnt uns in so einem Fall...

sol1 = NDSolve[{ode, ab}, x[t], {t, -2, 2}]

...produziert aber "gefährlichen" Output

Plot[Evaluate[x[t] /. sol], {t, -2, 1.1}]

Clear[ode, ab, sol, x]

Betrachten wir ein weiteres Beispiel.

sol = DSolve[{x'[t] == Sqrt[x[t]], x[0] == 1}, x[t], t]

Mathematica gibt hier zwei Lösungen aus; eine für die negative, eine für die positive Wurzel.

Plot[Evaluate[x[t] /. sol], {t, -3, 3}]

Es ist allerdings größte Vorsicht angebracht, denn die zweite Lösung

x2[t_] = Simplify[x[t] /. sol[[2]]]

löst auf (-2,∞) die ODE mit der postiven Wurzel auf der rechten Seite. Für t<-2 wird x2' allerdings negativ und die Funktion löst die andere ODE---nämlich die mit der negative Wurzel. Mathematica schweigt sich zu diesem Thema vollständig aus.

Noch problematischer wird die Situation, wenn die ODE nicht so überschaubar ist wie in diesen einfachen Beispielen. Um dies zu illustrieren, kehren wir zur Riccatischen Gleichung von oben zurück und plotten die Lösungen auf einem etwas anderen Bereich.

ode = (x'[t] == 
          c (t^m) + b x[t]^2)
b := 1
m := 2
c := 1
sol = DSolve[ode, x[t], t]
lsgk := 
      Table[Evaluate[x[t] /. sol[[1]] /. C[1] -> C], {C, 1, 
          10}]
Plot[Evaluate[lsgk], {t, -1, 1}]

Die Funktionen sind also bei t=0 unstetig und dort daher sicher nicht Lösungen irgendeiner Differentialgleichung!
Insbesondere bei der Suche nach Lösungen komplizierten Gleichungen ist also größte Vorischt angebracht und ein blindes Verlassen auf Mathematica führt schnell zu falschen Schlüssen und Ergebnissen!

Nicht-Eindeutigkeit

Bei Nicht-Eindeuigkeit von Lösungen wird der Benutzer ebenfalls nicht automatisch gewarnt; auch hier heisst es gut aufpassen!
Wir betrachten das Erzbeispiel eines nicht eindeutig lösbaren AWP.

ode := (x'[t] == Sqrt[x[t]])
ab := (x[0] == 0)
sol = DSolve[{ode, ab}, x[t], t]

Die konstante Lösung y0(t)=0 fällt hier ebenso unter den Tisch wie die "gestückelten Lösungen" (vgl. VO 2.20).

z[t_, C_] := 0  /;  t ≤ C
z[t_, C_] := (t - C)^2/4  /;  t > C
Plot[Evaluate[Table[z[t, C], {C, 0, 5}]], {t, 0, 6}]