10
1
mirror of https://gitlab.com/scemama/QCaml.git synced 2024-06-26 15:12:05 +02:00
QCaml/common/coordinate.org
2021-01-04 09:19:35 +01:00

217 lines
4.9 KiB
Org Mode

#+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
* 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
#+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
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
** Creation
#+begin_src ocaml :tangle (eval mli)
val make : 'a point -> t
val make_angstrom : 'a point -> angstrom point
val zero : bohr point
#+end_src
| ~make~ | Creates a point in atomic units |
| ~make_angstrom~ | Creates a point in angstrom |
| ~zero~ | $(0., 0., 0.)$ |
#+begin_src ocaml :tangle (eval ml) :exports none
external make : 'a point -> t = "%identity"
external make_angstrom : 'a point -> angstrom point = "%identity"
let zero =
make { x = 0. ; y = 0. ; z = 0. }
#+end_src
** Conversion
#+begin_src ocaml :tangle (eval mli)
val bohr_to_angstrom : bohr point -> angstrom point
val angstrom_to_bohr : angstrom point -> bohr point
#+end_src
| ~bohr_to_angstrom~ | Converts a point in bohr to angstrom |
| ~angstrom_to_bohr~ | Converts a point in angstrom to bohr |
#+begin_src ocaml :tangle (eval ml) :exports none
let b_to_a b = Constants.a0 *. b
let bohr_to_angstrom { x ; y ; z } =
make { x = b_to_a x ;
y = b_to_a y ;
z = b_to_a z ; }
let a_to_b a = Constants.a0_inv *. a
let angstrom_to_bohr { x ; y ; z } =
make { x = a_to_b x ;
y = a_to_b y ;
z = a_to_b z ; }
#+end_src
** Vector operations
#+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
| ~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 |
| ~¦.~ | Scales the vector by a constant |
| ~¦+~ | Adds two vectors |
| ~¦-~ | Subtracts two vectors |
#+begin_example
Coordinate.neg { x=1. ; y=2. ; z=3. } ;;
- : Coordinate.t = -1.0000 -2.0000 -3.0000
Coordinate.(get Y { x=1. ; y=2. ; z=3. }) ;;
- : float = 2.
Coordinate.(
2. |. { x=1. ; y=2. ; z=3. }
) ;;
- : Coordinate.t = 2.0000 4.0000 6.0000
Coordinate.(
{ x=1. ; y=2. ; z=3. } |+ { x=2. ; y=3. ; z=1. }
);;
- : Coordinate.t = 3.0000 5.0000 4.0000
Coordinate.(
{ x=1. ; y=2. ; z=3. } |- { x=2. ; y=3. ; z=1. }
);;
- : Coordinate.t = -1.0000 -1.0000 2.0000
#+end_example
#+begin_src ocaml :tangle (eval ml) :exports none
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 )
#+end_src
** 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
Coordinates can be printed in bohr or angstrom.
#+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