This gives high level view of my differential equations solver program which is in development for academic use. The program design is based on top-down modular design.
There are a number of public API’s. The main API is dsolve(). But there are other API’s such as for finding eigenvalues and eigenvectors.
This diagram shows the top level design
The following is the pseudo code of the dsolve() procedure. This is one of main calls into the main module for solving a single differential equation. It returns back all solutions found.
dsolve:=proc(ode,y(x),IC,hint::string) -- This CALL validates the ode itself. IC are validated by each separate -- module below this throws parse error if any fail ode_MGR:-parse_ode(ode); ode_order := ode_MGR:-:-get_ode_order(ode); -- parse and validate IC. This throws error if any fails IF ode_order =1 then first_order_ode:-parse_IC(ode,y(x),IC); ELIF ode_order=2 then second_order_ode:-parse_IC(ode,y(x),IC); ELSE higher_order_ode:-parse_IC(ode,y(x),IC); END IF -- the following factors ode if possible. For example for y''*y'=0 gives -- y''=0 and y'=0 factors. If not possible to factor, ode itself is only -- factor. in 99% of the times, ode do not factor and ode_factors list -- will just contain the original ode. But this makes it much easier -- to solve an ode if it can be factored. ode_factors := factor_ode(ode); -- This finds general and any singular solutions if any solutions_found := process_factors(ode,y(x),IC,hint,ode_factors) -- Update solutions for IC solutions_found := update_solutions_for_IC(solutions_found,y(x),IC) -- Finally, check solutions. Throw away ones that do not verify -- the ODE or IC solutions_found := verify_solutions_against_ode_and_IC(solutions_found,ode,y(x),IC) RETURN solutions_found
The following procedure is the main dispatcher.
It takes in the ode factors after being parsed with the initial conditions also parsed and verified and dispatches each to the correct solver depending on the ode order.
Its input is the original ode and all the factors found. Most of the time there are no factors and only the ode itself is its own factor. It returns back set of the solutions found.
process_factors:=proc(ode,y(x),IC,hint::string,ode_factors::list) solutions_found := {}; FOR current_factor in ode_factors DO -- must have at least one -- possible to have factor not ode. Example x*y'=0, only factor is y'=0 -- and x factor is ignored. IF current_factor has y THEN -- find ode order to know which module to call. ode_order := ode_MGR:-:-get_ode_order(current_factor); IF ode_order = 0 then -- algebraic factor -- handle case of factor has only y and no y'. For example y*y'=0 -- or cos(y)*y'=0, then factors are cos(y)=0 and y'=0 and so on. -- solutions to algebric factors have no consant of integration -- but must still satisfy original ode and initial conditions. solution := SOLVE(current_factor=0,y(x)) -- only keep if it satisfies original ode and IC if any IF solution does not satisfy ode or does not satisfy IC THEN solution:={}; END IF; ELIF ode_order = 1 then solution := first_order_ode:-dsolve(current_factor,y(x),IC,hint); ELIF ode_order = 2 then solution := second_order_ode:-dsolve(current_factor,y(x),IC,hint); ELSE solution := higher_order_ode:-dsolve(current_factor,y(x),IC,hint); FI; -- collect solutions and remove duplicates solutions_found := solutions_found UNION solution; END IF; END DO; RETURN solutions_found END proc;