2020-12-27 17:38:04 +01:00
|
|
|
#+begin_src elisp tangle: no :results none :exports none
|
2020-12-27 17:23:47 +01:00
|
|
|
(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
|
|
|
|
|
|
|
|
* Coordinate
|
|
|
|
:PROPERTIES:
|
|
|
|
:header-args: :noweb yes :comments both
|
|
|
|
:END:
|
|
|
|
|
|
|
|
Coordinates in 3D space.
|
|
|
|
|
|
|
|
All operations on points are done in atomic units. Therefore,
|
|
|
|
all coordinates are given in bohr and manipulated with this
|
|
|
|
module.
|
|
|
|
|
|
|
|
** Type
|
|
|
|
|
2021-01-28 00:34:26 +01:00
|
|
|
<<<~Coordinate.t~>>>
|
2020-12-27 17:23:47 +01:00
|
|
|
#+NAME: types
|
|
|
|
#+begin_src ocaml :tangle (eval mli)
|
|
|
|
type bohr
|
|
|
|
type angstrom
|
|
|
|
|
|
|
|
type xyz = {
|
|
|
|
x : float ;
|
|
|
|
y : float ;
|
|
|
|
z : float ;
|
|
|
|
}
|
|
|
|
|
|
|
|
type 'a point = xyz
|
|
|
|
|
|
|
|
type t = bohr point
|
|
|
|
|
|
|
|
type axis = X | Y | Z
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
#+begin_src ocaml :tangle (eval ml) :exports none
|
2021-01-04 09:19:35 +01:00
|
|
|
type bohr
|
|
|
|
type angstrom
|
|
|
|
|
|
|
|
type xyz = {
|
|
|
|
x : float ;
|
|
|
|
y : float ;
|
|
|
|
z : float ;
|
|
|
|
}
|
|
|
|
|
|
|
|
type 'a point = xyz
|
|
|
|
|
|
|
|
type t = bohr point
|
|
|
|
|
|
|
|
type axis = X | Y | Z
|
2020-12-27 17:23:47 +01:00
|
|
|
#+end_src
|
|
|
|
|
2020-12-27 23:08:12 +01:00
|
|
|
** Creation
|
2020-12-27 17:23:47 +01:00
|
|
|
|
2020-12-27 23:08:12 +01:00
|
|
|
#+begin_src ocaml :tangle (eval mli)
|
|
|
|
val make : 'a point -> t
|
2020-12-27 17:23:47 +01:00
|
|
|
val make_angstrom : 'a point -> angstrom point
|
2021-01-28 00:34:26 +01:00
|
|
|
val zero : bohr point
|
2020-12-27 23:08:12 +01:00
|
|
|
#+end_src
|
2020-12-27 17:23:47 +01:00
|
|
|
|
2020-12-27 23:08:12 +01:00
|
|
|
| ~make~ | Creates a point in atomic units |
|
|
|
|
| ~make_angstrom~ | Creates a point in angstrom |
|
|
|
|
| ~zero~ | $(0., 0., 0.)$ |
|
2020-12-27 17:38:04 +01:00
|
|
|
|
2020-12-27 23:08:12 +01:00
|
|
|
#+begin_src ocaml :tangle (eval ml) :exports none
|
|
|
|
external make : 'a point -> t = "%identity"
|
2020-12-27 17:23:47 +01:00
|
|
|
external make_angstrom : 'a point -> angstrom point = "%identity"
|
|
|
|
|
2020-12-27 23:08:12 +01:00
|
|
|
let zero =
|
2021-01-04 09:19:35 +01:00
|
|
|
make { x = 0. ; y = 0. ; z = 0. }
|
2020-12-27 23:08:12 +01:00
|
|
|
#+end_src
|
|
|
|
|
|
|
|
** Conversion
|
2020-12-27 17:23:47 +01:00
|
|
|
|
2020-12-27 23:08:12 +01:00
|
|
|
#+begin_src ocaml :tangle (eval mli)
|
2020-12-27 17:23:47 +01:00
|
|
|
val bohr_to_angstrom : bohr point -> angstrom point
|
2020-12-27 23:08:12 +01:00
|
|
|
val angstrom_to_bohr : angstrom point -> bohr point
|
|
|
|
#+end_src
|
2020-12-27 17:38:04 +01:00
|
|
|
|
2020-12-27 23:08:12 +01:00
|
|
|
| ~bohr_to_angstrom~ | Converts a point in bohr to angstrom |
|
|
|
|
| ~angstrom_to_bohr~ | Converts a point in angstrom to bohr |
|
2020-12-27 17:23:47 +01:00
|
|
|
|
2020-12-27 23:08:12 +01:00
|
|
|
#+begin_src ocaml :tangle (eval ml) :exports none
|
|
|
|
let b_to_a b = Constants.a0 *. b
|
2020-12-27 17:23:47 +01:00
|
|
|
let bohr_to_angstrom { x ; y ; z } =
|
|
|
|
make { x = b_to_a x ;
|
|
|
|
y = b_to_a y ;
|
|
|
|
z = b_to_a z ; }
|
|
|
|
|
|
|
|
|
2020-12-27 23:08:12 +01:00
|
|
|
let a_to_b a = Constants.a0_inv *. a
|
2020-12-27 17:23:47 +01:00
|
|
|
let angstrom_to_bohr { x ; y ; z } =
|
|
|
|
make { x = a_to_b x ;
|
|
|
|
y = a_to_b y ;
|
|
|
|
z = a_to_b z ; }
|
2020-12-27 23:08:12 +01:00
|
|
|
#+end_src
|
2020-12-27 17:23:47 +01:00
|
|
|
|
2020-12-27 23:08:12 +01:00
|
|
|
** Vector operations
|
2020-12-27 17:23:47 +01:00
|
|
|
|
2020-12-27 23:08:12 +01:00
|
|
|
#+begin_src ocaml :tangle (eval mli)
|
|
|
|
val neg : t -> t
|
|
|
|
val get : axis -> bohr point -> float
|
|
|
|
val dot : t -> t -> float
|
|
|
|
val norm : t -> float
|
|
|
|
val ( |. ) : float -> t -> t
|
|
|
|
val ( |+ ) : t -> t -> t
|
|
|
|
val ( |- ) : t -> t -> t
|
|
|
|
#+end_src
|
2020-12-27 17:23:47 +01:00
|
|
|
|
2021-01-28 00:34:26 +01:00
|
|
|
| ~neg~ | Negative of a point |
|
|
|
|
| ~get~ | Extracts the projection of the coordinate on an axis |
|
|
|
|
| ~dot~ | Dot product |
|
|
|
|
| ~norm~ | $\ell{^2}$ norm of the vector |
|
|
|
|
| $\vert .$ | Scales the vector by a constant |
|
|
|
|
| $\vert +$ | Adds two vectors |
|
|
|
|
| $\vert -$ | Subtracts two vectors |
|
2020-12-27 17:38:04 +01:00
|
|
|
|
2021-01-28 00:34:26 +01:00
|
|
|
Example:
|
2020-12-27 23:08:12 +01:00
|
|
|
#+begin_example
|
|
|
|
Coordinate.neg { x=1. ; y=2. ; z=3. } ;;
|
2020-12-29 01:08:37 +01:00
|
|
|
- : Coordinate.t = -1.0000 -2.0000 -3.0000
|
2020-12-27 23:08:12 +01:00
|
|
|
|
|
|
|
Coordinate.(get Y { x=1. ; y=2. ; z=3. }) ;;
|
|
|
|
- : float = 2.
|
2020-12-27 17:23:47 +01:00
|
|
|
|
2020-12-27 23:08:12 +01:00
|
|
|
Coordinate.(
|
|
|
|
2. |. { x=1. ; y=2. ; z=3. }
|
|
|
|
) ;;
|
2020-12-29 01:08:37 +01:00
|
|
|
- : Coordinate.t = 2.0000 4.0000 6.0000
|
2020-12-27 17:23:47 +01:00
|
|
|
|
2020-12-27 23:08:12 +01:00
|
|
|
Coordinate.(
|
|
|
|
{ x=1. ; y=2. ; z=3. } |+ { x=2. ; y=3. ; z=1. }
|
|
|
|
);;
|
2020-12-29 01:08:37 +01:00
|
|
|
- : Coordinate.t = 3.0000 5.0000 4.0000
|
2020-12-27 17:38:04 +01:00
|
|
|
|
2020-12-27 23:08:12 +01:00
|
|
|
Coordinate.(
|
|
|
|
{ x=1. ; y=2. ; z=3. } |- { x=2. ; y=3. ; z=1. }
|
|
|
|
);;
|
2020-12-29 01:08:37 +01:00
|
|
|
- : Coordinate.t = -1.0000 -1.0000 2.0000
|
2020-12-27 23:08:12 +01:00
|
|
|
#+end_example
|
2020-12-27 17:23:47 +01:00
|
|
|
|
|
|
|
|
2020-12-27 23:08:12 +01:00
|
|
|
#+begin_src ocaml :tangle (eval ml) :exports none
|
2020-12-27 17:23:47 +01:00
|
|
|
let get axis { x ; y ; z } =
|
|
|
|
match axis with
|
|
|
|
| X -> x
|
|
|
|
| Y -> y
|
|
|
|
| Z -> z
|
|
|
|
|
|
|
|
|
|
|
|
let ( |. ) s { x ; y ; z } =
|
|
|
|
make { x = s *. x ;
|
|
|
|
y = s *. y ;
|
|
|
|
z = s *. z ; }
|
|
|
|
|
|
|
|
|
|
|
|
let ( |+ )
|
|
|
|
{ x = x1 ; y = y1 ; z = z1 }
|
|
|
|
{ x = x2 ; y = y2 ; z = z2 } =
|
|
|
|
make { x = x1 +. x2 ;
|
|
|
|
y = y1 +. y2 ;
|
|
|
|
z = z1 +. z2 ; }
|
|
|
|
|
|
|
|
|
|
|
|
let ( |- )
|
|
|
|
{ x = x1 ; y = y1 ; z = z1 }
|
|
|
|
{ x = x2 ; y = y2 ; z = z2 } =
|
|
|
|
make { x = x1 -. x2 ;
|
|
|
|
y = y1 -. y2 ;
|
|
|
|
z = z1 -. z2 ; }
|
|
|
|
|
|
|
|
|
|
|
|
let neg a = -1. |. a
|
|
|
|
|
|
|
|
|
|
|
|
let dot
|
|
|
|
{ x = x1 ; y = y1 ; z = z1 }
|
|
|
|
{ x = x2 ; y = y2 ; z = z2 } =
|
|
|
|
x1 *. x2 +.
|
|
|
|
y1 *. y2 +.
|
|
|
|
z1 *. z2
|
|
|
|
|
|
|
|
|
|
|
|
let norm u =
|
|
|
|
sqrt ( dot u u )
|
2020-12-27 23:08:12 +01:00
|
|
|
#+end_src
|
2020-12-27 17:23:47 +01:00
|
|
|
|
|
|
|
** Printers
|
|
|
|
|
|
|
|
#+begin_src ocaml :tangle (eval mli)
|
|
|
|
val pp : Format.formatter -> t -> unit
|
|
|
|
val pp_bohr: Format.formatter -> t -> unit
|
|
|
|
val pp_angstrom : Format.formatter -> t -> unit
|
|
|
|
#+end_src
|
|
|
|
|
2020-12-27 17:38:04 +01:00
|
|
|
Coordinates can be printed in bohr or angstrom.
|
|
|
|
|
2020-12-27 17:23:47 +01:00
|
|
|
#+begin_src ocaml :tangle (eval ml) :exports none
|
|
|
|
open Format
|
|
|
|
let pp ppf c =
|
|
|
|
fprintf ppf "@[@[%8.4f@] @[%8.4f@] @[%8.4f@]@]" c.x c.y c.z
|
|
|
|
|
|
|
|
let pp_bohr ppf c =
|
|
|
|
fprintf ppf "@[(@[%10f@], @[%10f@], @[%10f@] Bohr)@]" c.x c.y c.z
|
|
|
|
|
|
|
|
let pp_angstrom ppf c =
|
|
|
|
let c = bohr_to_angstrom c in
|
|
|
|
fprintf ppf "@[(@[%10f@], @[%10f@], @[%10f@] Angs)@]" c.x c.y c.z
|
|
|
|
#+end_src
|
|
|
|
|