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