This code takes one ode, using same input as given to Mathematica’s DSolve and verifies it is valid. I use this in my ode solver. This is the very first function called to verify the input is valid.
symbolQ[_Symbol] = True; symbolQ[_] = False; has[e_,h_] := Not[FreeQ[e,h]] (*This function thanks to Carl Woll,see https://mathematica.stackexchange.com/questions/151850/using-cases-and-when-to-make-input-a-list-or-not*) getPatterns[expr_,pat_]:=Last@Reap[expr/. a:pat:>Sow[a],_,Sequence@@#2&]; (*Version Dec 2, 2024 by Nasser M. Abbasi*) (*Takes ode and IC, using same syntax as Mathematica's DSolve, and verifies it is valid*) (*Returns list of ode,IC,ode order if valid, else it generates Abort message*) parseOneOde[odeAndIc_,y_Symbol[x_Symbol],x_Symbol]:=Module[{ode,ic,constX,alg,LHS,z,n,indeps,deps,der,odeOrder}, If[Not[symbolQ[y]], Print["Invalid dependent variable given ",y]; Abort[] ]; If[Not[symbolQ[x]], Print["Invalid independent variable given ",x]; Abort[] ]; If[Head[odeAndIc]===List, {constX,ic,alg,ode}=Internal`ProcessEquations`SeparateEquations[Flatten[odeAndIc],{x},{y}] , {constX,ic,alg,ode}=Internal`ProcessEquations`SeparateEquations[{odeAndIc},{x},{y}] ]; If[Length[Flatten[constX]]!=0, Print["Does not support constraints on independent variable ",constX]; Abort[] ]; If[Length[Flatten[alg]]!=0, Print["Does not support algebratic equations ",alg]; Abort[] ]; If[Length[ode]>1, Print["Does not support more than one ode at this time",ode]; Abort[] ]; If[Length[ode]==0, Print["No ode in ",y[x]," found"]; Abort[] ]; (*extract the ode from the list now we know there is only one*) ode=First[Flatten@ode]; (*this makes it easier to parse*) LHS=First@ode-Last@ode; If[FreeQ[LHS,y], Print["Error: ode ",ode," has no ",y]; Abort[] ]; If[FreeQ[LHS,x], Print["Error. ode ",ode," has no ",x]; Abort[] ]; deps=getPatterns[LHS,y[]]; If[deps=!={}, Print["makeODE:: Can not have ",y[]," in ",ode]; Abort[] ]; deps=getPatterns[LHS,y[z_.]]; (*this checks there is no y on its own*) If[Length[Cases[Variables[LHS],Verbatim[y]]]!=0, Print["makeODE:: Can not have ",y," with no argument ",x," in ode ",ode]; Abort[] ]; (*this code checks all the independent variable in y[x] are x*) If[deps=!={}, deps=Union[Cases[deps,y[z_]:>z]];(*this extracts all the independent variables*) If[Length[deps]>1, Print["makeODE:: independent variable must be ",x," in ",ode]; Abort[] ]; If[First[deps]=!=x, Print["makeODE:: independent variable must be ",x," in ",ode]; Abort[] ] ]; der = getPatterns[LHS,Derivative[n_][y][x]]; If[der==={}, Print["makeODE::No differential equation found in ",ode]; Abort[] ]; der = getPatterns[LHS,Derivative[n_][y][_]]; indeps = Union@Cases[der,Derivative[n_][y][z_]:>z]; If[Or[Length@indeps>1,First@indeps=!=x], Print["Found wrong independent variable in derivative in ",ode]; Abort[] ]; ic = Union@ic; odeOrder = First@Flatten@Internal`ProcessEquations`DifferentialOrder[ode,{x},{y}]; If[Length@ic>0, If[Not[AllTrue[ic,Head[#]===Equal&]], Print["Invalid initial conditions found in ",ic]; Abort[] ]; If[Length@ic>odeOrder, Print["Too many initial conditions given for the order of the ode ",ic]; Abort[] ] ]; Print["Successful Parsing"]; Print["ode=",ode]; Print["y=",y]; Print["x=",x]; Print["ode order=",odeOrder]; Print["IC=",ic]; {ode,ic,odeOrder} ]
These are examples using the above function
parseOneOde[{y''[x] == y[x]*Sin[x], y[0] == 0, y'[0] == 1}, y[x], x] {y''[x] == Sin[x] y[x], {y[0] == 0, y''[0] == 1}, 2}
parseOneOde[{y''[x] == y[x]*Sin[x], y[x] == 0, y'[0] == 1}, y[x], x] "Does not support algebratic equations ", {y[x] == 0} $Aborted
parseOneOde[{y''[x] == y[]*Sin[x], y[Pi] == 0, y'[0] == 1}, y[x], x] makeODE:: Can not have y[] in y''[x]==Sin[x] y[] $Aborted
parseOneOde[{Sin[x] y''[x] + Derivative[y[x], {x, 7}] == y[x]*Sin[x] - y[x], y[Pi] == 0, y'[0] == 1}, y[x], x] {Derivative[y[x],{x,7}]+Sin[x] y''[x]==-y[x]+Sin[x] y[x],{y[Pi]==0,y'[0]==1},2}
parseOneOde[{Sin[x] y''[x] == y[z]*Sin[x] - y[x], y'[0] == 1}, y[x], x] makeODE:: independent variable must be , x, in , Sin[x] Derivative[2][y][x] == -y[x] + Sin[x] y[z]] $Aborted
Given a single ode, how to find the dependent variable?
Internal`ProcessEquations`FindDependentVariables[y''[x] + y[x]*y'[x] == x, x] {y}
Internal`ProcessEquations`FindDependentVariables[x'[t] == 0, t] {x}
Notice the second argument must be the independent variable.
There is no builtin function I could find in Mathematica to do this. But one way is the
following. We will have a function that returns the coefficients of the ode and the RHS. i.e.
given an ode
So for a first order ode, the result of calling this function, which we will get getODEcoeff
is
always a list. The Length of the list is 2 more than the order of the ode. If a coefficient is
missing, zero is placed in that slot. For example, for 3 y''[x] + x y[x]==Sin[x]
then
getODEcoeff[ode,y[x],x]
will return {3,0,x,Sin[x]
and for x y''''[x] + x y[x]==Sin[x]
it will return {x,0,0,0,x,Sin[x]}
and for first order ode y'[x]+f[x]*y[x]==9
it will
return {1,f[x],9}
.
Now we simply check that all element of this list have no
(to do)
Where did I get this from?
"Mathematica can handle partial differential equations via the DSolveIntegrals package. These arise in chemical contexts in the 1D wave equation, 3D wave equation, 3D diffusion equation, Time-dependent and Time independent Schrödinger equation. Hermite showed that the quintic equation could be solved by elliptic functions"
one way
Clear[y, x] DSolve[{y'[x]^2 == 1 - y[x]^2, y[0] == 0}, y[x], x] {{y[x] -> -Sin[x]}, {y[x] -> Sin[x]}}
And now
\verb|y[x] /. %| {-Sin[x],Sin[x]}
For an ode, that has just ordinary point at
with intitial conditions
findSeriesSolution[t_, nTerms_] := Module[{pt = 0, u, ode, s0, s1, ic, eq, sol}, ic = {u[0] -> 1, u'[0] -> 1}; ode = u''[t] + 4 u[t] + 1/10 u[t]^3 u'[t]^2; s0 = Series[ode, {t, pt, nTerms}]; s0 = s0 /. ic; roots = Solve@LogicalExpand[s0 == 0]; s1 = Series[u[t], {t, pt, nTerms + 2}]; sol = Normal[s1] /. ic /. roots[[1]] ]
and now call it with
seriesSol = findSeriesSolution[t, 6]
It returns
Update: As of recent versions, we can just do this
ode = u''[t] + 4 u[t] + 1/10 u[t]^3*u'[t]^2 == 0; ic = {u[0] == 1, u'[0] == 1}; AsymptoticDSolveValue[{ode, ic}, u[t], {t, 0, 6}]
Suppose we have
ode = Derivative[2][u][t] + Derivative[1][u][t] + u[t] == 3*Cos[2*t]; ode /. u -> (c1*Cos[#1] + c2*Sin[#1] & ) Out[2]= c2*Cos[t] - c1*Sin[t] == 3*Cos[2*t]
Given an ode, such as
We write it as
This small function I wrote for a HW will do this. Pass it
checkForSingularity[p_, q_, at_List, x_] := Module[{p0, q0, t, r, r0}, r = First@Last@Reap@Do[ If[at[[n]] === Infinity, p0 = p /. x -> (1/t); p0 = (2 t - p0)/t^2; q0 = (q /. x -> (1/t))/t^4; r0 = checkForSingularity[p0, q0, {0}, t]; Sow[Flatten[{Infinity, Rest[Flatten@r0]}]]; , r0 = {at[[n]], Limit[(x - at[[n]]) p, x -> at[[n]]], Limit[(x - at[[n]])^2 q, x -> at[[n]]]}; Sow@r0 ] , {n, 1, Length@at} ]; r ]
To use it on the above example
ClearAll[c, a, b, x]; m = checkForSingularity[(c - (a + b + 1) x)/(x (1 - x)), (-a b)/(x (1 - x)), {0, 1, Infinity}, x]; Grid[Join[{{"point", "limit x p(x)", "limit x^2 q(x)"}}, m], Frame -> All]
Gives
{{"point", "limit x p(x)", "limit x^2 q(x)"}, {0, c, 0}, {1, 1 + a + b - c, 0}, {\[Infinity], 1 - a - b, a b} }
Since all points have finite limits, then all
I did not test this function too much, but it works for the HW I did :)
Given ode
ClearAll[y,x,s] eq = y'''[x] == x y[x] eq = eq /. y -> Function[{x}, Exp[s[x]]] Simplify@Thread[eq/Exp[s[x]], Equal]
Gives
Given y'[x]+3 Sin[x]-3-Cos[x]-2 y[x]==0
how to rewrite it to be
y'[x]==3+Cos[x]-3 Sin[x]+2 y[x]
i.e. put y'[x]
on one side, and the rest on the other
side?
ClearAll[f,x,y] expr=y'[x]+3 Sin[x]-3-Cos[x]-2 y[x]==0; lhs=expr/.lhs_==rhs_:>lhs; rhs=expr/.lhs_==rhs_:>rhs; rhs=-(lhs/.(y'[x]+any_.):>any)+rhs; expr=y'[x]==rhs
This makes it easier to make it in form
Use this
Block[{DSolve`print=Print}, DSolve[{ode,ic},y[t],t] ]
see https://mathematica.stackexchange.com/questions/120364/why-cant-dsolve-find-a-solution-for-this-ode/120650#120650 by Michael E2.
ClearAll[withTimedIntegrate]; SetAttributes[withTimedIntegrate, HoldFirst]; withTimedIntegrate[code_, tc_] := Module[{$in}, Internal`InheritedBlock[{Integrate}, Unprotect[Integrate]; i : Integrate[___] /; ! TrueQ[$in] := Block[{$in = True}, TimeConstrained[i, tc, Inactivate[i, Integrate]] ]; Protect[Integrate]; code ] ]; withTimedIntegrate[{dsol} = DSolve[ode == 0, y, x], 1]; // AbsoluteTiming dsol
Use
Clear["Global`*"]; ode=y''[x]+3*y'[x]+3==0; Internal`ProcessEquations`DifferentialOrder[ode,{x},{y}] (* {{2}} *)
So it is order 2. Notice the input must be lists [ode,{x},{y}]
, it will hang if you use
[ode,x,y]
Degree of an ode is the degree of the highest derivative in the oder. This needs a helper function
(*This function thanks to Carl Woll, see https://mathematica.stackexchange.com/questions/151850/using-cases-and-when-to-make-input-a-list-or-not*) Clear["Global`*"]; getPatterns[expr_, pat_] := Last@Reap[expr /. a : pat :> Sow[a], _, Sequence @@ #2 &];
And now do
getDegreeOfOde[ode_,y_,x_]:=Module[{maxDer,p,d,der}, der = getPatterns[ode,Power[Derivative[_.][y][x],_.]] ; p = Flatten[Internal`ProcessEquations`DifferentialOrder[#,{x},{y}]&/@der]; maxDer = Extract[der,Position[p,Max[p]]]; Abs[First[maxDer/.(Derivative[_.][y][x])^(d_.):>d]] ]
Examples of usage
ode=y'''[x]+y''[x]^4+3*y'[x]^8+3*y[x]^8==0; getDegreeOfOde[ode,y,x] (*1*) ode=y''[x]^4+3*y'[x]^8+3*y[x]^8==0; getDegreeOfOde[ode,y,x] (*4*) ode=y''[x]+3*y'[x]^8+3*y[x]^8==0; getDegreeOfOde[ode,y,x] (*1*)
Given an ode (or any equation), and we want to move all terms with
moveAllYToOneSide[ode_Equal,y_Symbol,x_Symbol]:=Module[{expr=ode,termsWithNoY,termsWithY}, expr=expr[[1]]-expr[[2]]; termsWithNoY=Select[expr,FreeQ[#,y]&]; termsWithY=Select[expr,Not[FreeQ[#,y]]&]; expr=termsWithY==-termsWithNoY ]
Call it as
ode=y[x]*y'[x]+Sin[x]+3-1/y[x]==Sin[y[x]]+Pi*x*y[x]; moveAllYToOneSide[ode ,y,x]
Gives
-Sin[y[x]]-1/y[x]-Pi x y[x]+y[x] y'[x]==-3-Sin[x]