3.1 How to parse an ODE?

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