#+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 * Electrons :PROPERTIES: :header-args: :noweb yes :comments both :END: Data structure which contains the number of \alpha and \beta electrons. ** Type #+NAME: types #+begin_src ocaml :tangle (eval mli) type t #+end_src #+begin_src ocaml :tangle (eval ml) :exports none type t = { n_alfa : int ; n_beta : int ; } #+end_src #+begin_src ocaml :tangle (eval test-ml) :exports none open Common open Particles open Alcotest let test_all () = let nuclei = "3 Water O 0. 0. 0. H -0.756950272703377558 0. -0.585882234512562827 H 0.756950272703377558 0. -0.585882234512562827 " |> Nuclei.of_xyz_string in let e = Electrons.of_atoms nuclei in #+end_src ** Creation #+begin_src ocaml :tangle (eval mli) open Common val make : int -> int -> t val of_atoms : ?multiplicity:int -> ?charge:int -> Nuclei.t -> t (* @param multiplicity default is 1 @param charge default is 0 @raise Invalid_argument if the spin multiplicity is not compatible with the molecule and the total charge. *) #+end_src | ~make~ | ~make n_alfa n_beta~ | | ~of_atoms~ | Creates the data relative to electrons for a molecular system described by ~Nuclei.t~ for a given total charge and spin multiplicity. | #+begin_src ocaml :tangle (eval ml) :exports none open Common let make n_alfa n_beta = { n_alfa ; n_beta } let of_atoms ?multiplicity:(multiplicity=1) ?charge:(charge=0) nuclei = let positive_charges = Array.fold_left (fun accu (e, _) -> accu + Charge.to_int (Element.to_charge e) ) 0 nuclei in let negative_charges = charge - positive_charges in let n_elec = - negative_charges in let n_beta = ((n_elec - multiplicity)+1)/2 in let n_alfa = n_elec - n_beta in let result = { n_alfa ; n_beta } in if multiplicity <> (n_alfa - n_beta)+1 then invalid_arg (__FILE__^": make"); result #+end_src #+begin_src ocaml :tangle (eval test-ml) :exports none check int "of_atoms alfa" 5 (Electrons.n_alfa e); check int "of_atoms beta" 5 (Electrons.n_beta e); #+end_src ** Access #+begin_src ocaml :tangle (eval mli) val charge : t -> Charge.t val n_elec : t -> int val n_alfa : t -> int val n_beta : t -> int val multiplicity : t -> int #+end_src | ~charge~ | Sum of the charges of the electrons | | ~n_elec~ | Number of electrons | | ~n_alfa~ | Number of alpha electrons | | ~n_beta~ | Number of beta electrons | | ~multiplicity~ | Spin multiplicity: $2S+1$ | #+begin_src ocaml :tangle (eval ml) :exports none let charge e = - (e.n_alfa + e.n_beta) |> Charge.of_int let n_alfa t = t.n_alfa let n_beta t = t.n_beta let n_elec t = t.n_alfa + t.n_beta let multiplicity t = t.n_alfa - t.n_beta + 1 #+end_src #+begin_src ocaml :tangle (eval test-ml) :exports none check int "charge " (-10) (Charge.to_int @@ Electrons.charge e); check int "n_elec" 10 (Electrons.n_elec e); check int "multiplicity" 1 (Electrons.multiplicity e); check int "of_atoms alfa m3" 6 (Electrons.(of_atoms ~multiplicity:3 nuclei |> n_alfa)); check int "of_atoms beta m3" 4 (Electrons.(of_atoms ~multiplicity:3 nuclei |> n_beta)); check int "of_atoms n_elec m3" 10 (Electrons.(of_atoms ~multiplicity:3 nuclei |> n_elec)); check int "of_atoms alfa m2 c1" 5 (Electrons.(of_atoms ~multiplicity:2 ~charge:1 nuclei |> n_alfa)); check int "of_atoms beta m2 c1" 4 (Electrons.(of_atoms ~multiplicity:2 ~charge:1 nuclei |> n_beta)); check int "of_atoms beta m2 c1" 9 (Electrons.(of_atoms ~multiplicity:2 ~charge:1 nuclei |> n_elec)); check int "of_atoms mult m2 c1" 2 (Electrons.(of_atoms ~multiplicity:2 ~charge:1 nuclei |> multiplicity)); check bool "make" true (Electrons.make 6 4 = Electrons.(of_atoms ~multiplicity:3 nuclei)); #+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 "@[n_alfa=%d, n_beta=%d@]" t.n_alfa t.n_beta #+end_src ** Tests #+begin_src ocaml :tangle (eval test-ml) :exports none () let tests = [ "all", `Quick, test_all ] #+end_src