Definition.ml

(* Copyright INRIA and Microsoft Corporation, 2008-2013. *)
(* DDMF is distributed under CeCILL-B license. *)

INCLUDE "preamble.ml"

(* Gives differential equation and initial conditions at a point. *)
(* Initial conditions are computed only for analytic functions. *)
(* Input: *)
(*   sf: special function object as defined in SF.ml *)
(*   point: where the initial conditions should be given *)
(* Output: *)
(*   {de, ic1, ic2, ...} where *)
(*   de: differential equation (without "= 0") *)
(*   ic1, ic2, ...: initial conditions; void if the function is not analytic *)
(* This is mostly used for point equal to << 0 >>. *)
let definition sf y point =
  let var = SF.var_of_t sf
  and eqn = sf.SF.lode
  and ic = SF.get_initial_conditions sf point in
  let feqn = << gfun:-formatdiffeq([$(eqn), $(y)($(var))]) >> in
  let ics =
    if ic.SF.analytic then begin
      (* Analytic function. *)
      (* Determine the list of power series coefficients that constitute *)
      (* the initial conditions. *)
      (* FIXME: If there is a single element in the list in the analytic case *)
      (* the data structure has to reflect it better. *)
      let m_list = (List.hd ic.SF.expansions).SF.monomials in
      let size = min <:int< nops($(feqn)) >> (List.length m_list) in
      let m_list = CommonTools.prefix_of_list size m_list in
      let ic_list =
        List.map
          (fun m ->
            let e = m.SF.x_expon and c = m.SF.coeff in
            << (D @@ $(e))($(y))($(point)) = $(e)! * $(c) >>)
          m_list in
      CommonTools.symb_of_symb_list ic_list
    end else << {} >> in
  << {$(eqn), op($(ics))} >>


(* Computes the same as above, but returns also a section for displaying *)
(* the definition. *)
let doc_and_def sf notation y point values =
  let eqn = sf.SF.lode
  and def = definition sf y point in
  let ics = << subsop(1 = NULL, $(def)) >> in

  (* Nicer display of the initial values. *)
  let ics =
    <<
      map(a -> `if`(op(0, op(2, a)) = `*`, op(1, a) =
          DDMF:-dynamow_times_to_frac(__DynaMoW_times([op(op(2, a))]), []), a),
        $(ics))
    >> in

  (* Display the differential equation and the initial conditions. *)
  let content =
    if <:bool< $(ics) = {} >> then
      <:par<<:dmath< $(symb:eqn) = 0. >>>>
    else
      let s = Wording.ending_of_seq ics in
      <:par<<:dmath< $(symb:eqn) = 0 >> with initial value$(str:s) >> @:@
      (Wording.enumeration_of_maplelist << [op($(ics))] >>) @:@ <:par<.>> in

  (* For displaying the mathematical representation of the function, *)
  (* we test whether the particular choice of the parameters allows  *)
  (* a simplification; in this (rare) case the output is of the form *)
  (* J_{1/2}(x) = sqrt(2/Pi/x)*sin(x). *)
  let rep_string = <:latex< $(sf.SF.rep) >> in
  let func_text =
    if String.compare notation rep_string = 0
    then <:par<<:imath< $(str: notation) >>>>
    else <:par<<:imath< $(str: notation) = $(str: rep_string) >>>> in

  (* Create a link to the corresponding ODE page. *)
  let ode_id = sf.SF.ode_id in
  let ode_link =
    DC.link_service
      (match List.length values with
      | 0 -> OrdinaryDiffEqn.Param0.descr ode_id None
      | 1 -> OrdinaryDiffEqn.Param1.descr ode_id (Some (List.hd values))
      | 2 ->
          OrdinaryDiffEqn.Param2.descr ode_id
            (Some (List.hd values, List.nth values 1))
      | 3 ->
          OrdinaryDiffEqn.Param3.descr
            ode_id (Some (List.hd values, List.nth values 1, List.nth values 2))
      | _ -> OrdinaryDiffEqn.Paramn.descr ode_id None)
      <:text<differential equation>> in

  let body =
    <:par<The function >> @:@ func_text @:@
(* These links have to be hidden for a relase, as most of them break *)
(* for the moment. *)
(*    <:par< satisfies the $(ode_link)>> @:@ content in *)
    (ignore ode_link ;
     <:par< satisfies the differential equation>>) @:@ content in

  DC.section <:text<Differential Equation>> body, def

Generated by GNU Enscript 1.6.5.90.