type bohr type angstrom type xyz = { x : float ; y : float ; z : float ; } type 'a point = xyz type t = bohr point external make : 'a point -> t = "%identity" external make_angstrom : 'a point -> angstrom point = "%identity" type axis = X | Y | Z let a_to_b a = Constants.a0_inv *. a 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 angstrom_to_bohr { x ; y ; z } = make { x = a_to_b x ; y = a_to_b y ; z = a_to_b z ; } let zero = make { x = 0. ; y = 0. ; z = 0. } (** Linear algebra *) 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 ) let get axis { x ; y ; z } = match axis with | X -> x | Y -> y | Z -> z 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