type t = { elec_num : int; mo_basis : MOBasis.t; mo_class : MOClass.t; spindets : Spindeterminant.t array; } let fci_of_mo_basis ?(frozen_core=true) mo_basis elec_num = let mo_num = MOBasis.size mo_basis in let ncore = (Nuclei.small_core @@ Simulation.nuclei @@ MOBasis.simulation mo_basis) / 2 in let mo_class = MOClass.of_list @@ if frozen_core then List.concat [ Util.list_range 1 ncore |> List.map (fun i -> MOClass.Core i) ; Util.list_range (ncore+1) mo_num |> List.map (fun i -> MOClass.Active i) ] else Util.list_range 1 mo_num |> List.map (fun i -> MOClass.Active i) in let m l = List.fold_left (fun accu i -> let j = i-1 in Z.(logor accu (shift_left one j)) ) Z.zero l in let occ_mask = m (MOClass.core_mos mo_class) and active_mask = m (MOClass.active_mos mo_class) in let neg_active_mask = Z.neg active_mask in Format.printf "%a\n" Util.pp_bitstring occ_mask; Format.printf "%a\n" Util.pp_bitstring active_mask; Format.printf "%a\n" Util.pp_bitstring neg_active_mask; let spindets = Util.bit_permtutations elec_num mo_num |> List.filter (fun b -> Z.logand neg_active_mask b = occ_mask) |> List.map (fun b -> Spindeterminant.of_bitstring b) |> Array.of_list in { elec_num ; mo_basis ; mo_class ; spindets } let pp_spindet_space ppf t = Format.fprintf ppf "@[["; Array.iteri (fun i d -> Format.fprintf ppf "@[@[%d@]@;@[%a@]@]@," i Spindeterminant.pp_spindet d) t.spindets; Format.fprintf ppf "]@]"