#+begin_src elisp tangle: no :results none :exports none
(setq pwd (file-name-directory buffer-file-name))
(setq name (file-name-nondirectory (substring buffer-file-name 0 -4)))
(setq lib (concat pwd "lib/"))
(setq testdir (concat pwd "test/"))
(setq mli (concat lib name ".mli"))
(setq ml  (concat lib name ".ml"))
(setq test-ml  (concat testdir name ".ml"))
(org-babel-tangle)
#+end_src 

* Frozen core
  :PROPERTIES:
  :header-args: :noweb yes :comments both
  :END:

  Defines how the core electrons are frozen, for each atom.

** Type

   #+NAME: types
   #+begin_src ocaml :tangle (eval mli)
type kind =
  | All_electron
  | Small
  | Large
   #+end_src

   #+begin_src ocaml :tangle (eval mli)
type t
   #+end_src

   #+begin_src ocaml :tangle (eval ml) :exports none
<<types>>
type t = int array
   #+end_src

** Creation

   #+begin_src ocaml :tangle (eval mli)
val make : kind -> Particles.Nuclei.t -> t

val of_int_list  : int list  -> t
val of_int_array : int array -> t
   #+end_src

   | ~make~         | Creates a ~Frozen_core.t~ with the same kind for all atoms               |
   | ~of_int_array~ | Creates a ~Frozen_core.t~ giving the number of frozen electrons per atom |
   | ~of_int_list~  | Creates a ~Frozen_core.t~ giving the number of frozen electrons per atom |

   #+begin_example
let f = Frozen_core.(make Small nuclei) ;;
val f : Frozen_core.t = [|0; 2; 2; 0|]

let f = Frozen_core.(of_int_list [0; 2; 2; 0])
val f : Frozen_core.t = [|0; 2; 2; 0|]
   #+end_example

   #+begin_src ocaml :tangle (eval ml) :exports none
let make_ae nuclei =
  Array.map (fun _ -> 0) nuclei

let make_small nuclei =
  Array.map (fun (e,_) -> Particles.Element.small_core e) nuclei

let make_large nuclei =
  Array.map (fun (e,_) -> Particles.Element.large_core e) nuclei

let make = function
  | All_electron -> make_ae 
  | Small        -> make_small 
  | Large        -> make_large


external of_int_array : int array -> t = "%identity"

let of_int_list = Array.of_list 
   #+end_src

** Access

   #+begin_src ocaml :tangle (eval mli)
val num_elec : t -> int
val num_mos  : t -> int
   #+end_src

   | ~num_elec~ | Number of frozen electrons          |
   | ~num_mos~  | Number of frozen molecular orbitals |

   #+begin_example
Frozen_core.num_elec f ;;
- : int = 4

Frozen_core.num_mos f ;;
- : int = 2
   #+end_example

   #+begin_src ocaml :tangle (eval ml) :exports none
let num_elec t =
  Array.fold_left ( + ) 0 t

let num_mos t =
  (num_elec t) / 2
   #+end_src

** Printers

   #+begin_src ocaml :tangle (eval mli)
val pp : Format.formatter -> t -> unit
   #+end_src

   #+begin_src ocaml :tangle (eval ml) :exports none
let pp ppf t =
  Format.fprintf ppf "@[[|";
  Array.iter (fun x -> Format.fprintf ppf "@,@[%d@]" x) t;
  Format.fprintf ppf "|]@]";
   #+end_src

