# OrdinaryDiffEqn.ml

```(* Copyright INRIA and Microsoft Corporation, 2008-2013. *)

INCLUDE "preamble.ml"

(* Create a page that displays information about a differential equation. *)
let ode_main_page ode parvals =

let var = FEqn.var_of_t ode
and params = FEqn.params_of_t ode in
let eqn = CommonTools.eval_expr ode.FEqn.eqn params parvals in

(* Determine names for coefficient sequences and summation variable. *)
let in_use =
CommonTools.symb_of_symb_list
((List.map (fun a -> << parse(\$(str: a)) >>) parvals) @
[ << \$(var) >> ]) in
let seq_var, sum_var = CommonTools.unused_names_for_sequence in_use in

(* (1) Particular Solutions *)
(* Display the ODE and its solutions, provided they are in the sf database. *)
let display_sf sf_id =
try
(* For displaying the mathematical representation of the function, *)
(* we test whether the particular choice of the parameters allows  *)
(* a simplification; in this case we write, e.g., J_{1/2}(x) = ... *)
let sf = DB.sf_of_id sf_id in
let func_rep1 = CommonTools.subs_expr sf.SF.rep params parvals
and func_rep2 =
<:latex< \$(CommonTools.eval_expr sf.SF.rep params parvals) >> in
let func_rep =
if String.compare func_rep1 func_rep2 = 0
then <:par<<:imath< \$(str: func_rep1) >>>>
else <:par<<:imath< \$(str: func_rep1) = \$(str: func_rep2) >>>>
in
[ <:par<the function >> @:@ func_rep ]
with
_ -> [] in
(* TODO: The word "function" should appear as a link to the corresponding *)
(* special function page. But since SpecialFunction.ml is compiled after  *)
(* OrdinaryDiffEqn.ml, this causes a linking problem during compilation.  *)
let sols = List.flatten (List.map display_sf ode.FEqn.sol_ids) in
let text_sols = Wording.enumeration_of_ents sols in
let text1, text2 = match List.length sols with
| 0 -> <:par<No particular solutions>>, <:par<are known to the database>>
| 1 -> <:par<A particular solution>>, <:par<is >>
| _ -> <:par<Some particular solutions>>, <:par<are >> in
let text_ode =
<:par< of the differential equation <:dmath< \$(symb: eqn) = 0 >>>> in
let particular_solutions =
DC.section
<:text<Particular Solutions>>
(text1 @:@ text_ode @:@ text2 @:@ text_sols @:@ <:par<.>>) in

(* (1a) Genericity conditions *)
let gen_conds =
CommonTools.symb_list_of_symb
<< DDMF:-genericity_conditions(\$(eqn), y, \$(var)) >> in
let genericity =
if gen_conds = [] then DC.ent_null else
<:par<All formulas on this page are valid under the condition that >> @:@
(Wording.enumeration_of_maples gen_conds) @:@
(if List.length gen_conds = 1
then <:par< is not an integer>>
else <:par< are not integers>>) @:@
<:par< (special values for parameters can be entered at the bottom).>> in

(* (2) Singular Points *)
(* Show the singular points of the differential equation. *)
let sings =
CommonTools.symb_list_of_symb
<< DDMF:-singular_points(\$(eqn), y, \$(var)) >> in
let inhom = <:bool< eval(\$(eqn), y(\$(var)) = 0) <> 0 >>
and nsing = List.length sings in
let text_sps = <:par<The differential equation has >> @:@
(match nsing with
| 0 -> <:par<no singular points.>>
| 1 -> <:par<one singular point:>>
| _ -> <:par<\$(int: nsing) singular points:>>) in
let text_type sp =
<:par<<:isymb< \$(sp) >> is >> @:@
(if <:bool< DDMF:-regular_singularity(\$(eqn), y, \$(var), \$(sp)) >>
then <:par<a regular >>
else <:par<an irregular >>) @:@
<:par<singular point.>> in
let singular_points =
DC.section
<:text<Singular Points>>
text_sps @@@ (DC.ordered_list (List.map text_type sings)) in

(* (3) Asymptotic Expansions at 0 and infinity *)
(* We always display the local expansions at 0 and infinity. *)
let warn =
if inhom then
DC.warning
<:par<
The given differential equation is not homogeneous. The expansions
below are solutions to the corresponding homogeneous equation.
>>
else
DC.ent_null
and sec_0 =
DC.inline_service
(BasisOfSolutions.descr (eqn, var, <<0>>, seq_var, sum_var) None)
and sec_inf =
DC.inline_service
(BasisOfSolutions.descr (eqn, var, <<infinity>>, seq_var, sum_var) None)
in
let exp_0inf =
DC.section
<:text<Asymptotic Expansions at <:isymb<0>> and <:isymb<infinity>>>>
(warn @@@ sec_0 @@@ sec_inf) in

(* (4) Asymptotic Expansions at other singular points *)
(* Display the local expansions at singularities other than 0 and infinity. *)
let sings =
List.filter (fun a -> <:bool< \$(a) <> 0 and \$(a) <> infinity >>) sings in
let one_sec s =
DC.inline_service
(BasisOfSolutions.descr (eqn, var, s, seq_var, sum_var) None) in
let secs = List.map one_sec sings in
let exp_sing =
if sings = [] then
DC.ent_null
else
DC.section
<:text<Asymptotic Expansions at other singular points>>
(List.fold_left (@@@) DC.ent_null secs) in

(* (5) Parameters *)
let enter_params =
if params = [] then DC.ent_null else
let nb_params = List.length params in
let s = Wording.ending_of_int nb_params in
let param_text =
<:par<The \$(str: ode.FEqn.eqn_name) depends on the parameter\$(str: s) >>
@:@
(Wording.enumeration_of_ents
(List.map (fun a -> <:par<<:isymb< \$(a) >>>>) params)) @:@
<:par<. The box>>  @:@
(if nb_params = 1 then <:par<>> else <:par<es>>) @:@
<:par< below can be used to rename or instantiate >> @:@
(if nb_params = 1 then <:par<this>> else <:par<these>>) @:@
<:par< parameter\$(str: s).>> in
DC.section <:text<Parameters>> (param_text @@@ <:par<>>) in

(* Final result of ode_main_page. *)
particular_solutions @@@ genericity @@@ singular_points @@@
exp_0inf @@@ exp_sing @@@ enter_params

(* This function checks whether the choice of parameters conflicts with *)
(* the function name, typically y(x), w.r.t. which the ODE is given. *)
let display_ode ode_id parvals =
let ode = DB.eqn_of_id ode_id in
let var = FEqn.var_of_t ode in
let parval_list =
CommonTools.symb_of_symb_list
(List.map (fun a -> << parse(\$(str: a)) >>) parvals) in
if <:bool< has(\$(parval_list), {\$(var), y}) >>
then
DC.warning
<:par<
Conflict between function <:isymb< y(\$(var)) >> and the parameters.
>>
else ode_main_page ode parvals

(* Define several services, corresponding to the number of parameters. *)
let title ode_id =
<:text<The \$(str: (DB.eqn_of_id ode_id).FEqn.eqn_name)>>

let_service Param0
(ode_id : string):
DC.sec_entities * unit with { title = title } =
DC.section (title _req_params) (display_ode ode_id [ ]), ()

let_service Param1
(ode_id : string)
(p1 : string = "a") :
DC.sec_entities * unit with { title = title } =
DC.section (title _req_params) (display_ode ode_id [ p1 ]), ()

let_service Param2
(ode_id : string)
(p1 : string = "a")
(p2 : string = "b") :
DC.sec_entities * unit with { title = title } =
DC.section (title _req_params) (display_ode ode_id [ p1 ; p2 ]), ()

let_service Param3
(ode_id : string)
(p1 : string = "a")
(p2 : string = "b")
(p3 : string = "c") :
DC.sec_entities * unit with { title = title } =
DC.section (title _req_params) (display_ode ode_id [ p1 ; p2 ; p3 ]), ()

let_service Paramn
(ode_id : string) :
DC.sec_entities * unit with { title = title } =
let eqn_text = <:par<<:dmath< \$(symb: (DB.eqn_of_id ode_id).FEqn.eqn) = 0 >>>>
and warn_text = <:par<This differential equation has too many parameters.>> in
DC.section (title _req_params) (DC.warning (eqn_text @:@ warn_text)), ()
```

Generated by GNU Enscript 1.6.5.90.