type mo_class = | Core of int (* Always doubly occupied *) | Inactive of int (* With 0,1 or 2 holes *) | Active of int (* With 0,1 or 2 holes or particles *) | Virtual of int (* With 0,1 or 2 particles *) | Deleted of int (* Always unoccupied *) | Auxiliary of int (* Auxiliary basis function *) type t = mo_class list let pp_mo_class ppf = function | Core i -> Format.fprintf ppf "@[Core %d@]" i | Inactive i -> Format.fprintf ppf "@[Inactive %d@]" i | Active i -> Format.fprintf ppf "@[Active %d@]" i | Virtual i -> Format.fprintf ppf "@[Virtual %d@]" i | Deleted i -> Format.fprintf ppf "@[Deleted %d@]" i | Auxiliary i -> Format.fprintf ppf "@[Auxiliary %d@]" i let pp ppf t = Format.fprintf ppf "@[[@,"; let rec aux = function | [] -> Format.fprintf ppf "]@]" | x :: [] -> Format.fprintf ppf "%a@,]@]" pp_mo_class x | x :: rest -> ( Format.fprintf ppf "%a@,;@," pp_mo_class x; aux rest ) in aux t let of_list t = t let to_list t = t let core_mos t = List.filter_map (fun x -> match x with | Core i -> Some i | _ -> None) t let inactive_mos t = List.filter_map (fun x -> match x with | Inactive i -> Some i | _ -> None ) t let active_mos t = List.filter_map (fun x -> match x with | Active i -> Some i | _ -> None ) t let virtual_mos t = List.filter_map (fun x -> match x with | Virtual i -> Some i | _ -> None ) t let deleted_mos t = List.filter_map (fun x -> match x with | Deleted i -> Some i | _ -> None ) t let auxiliary_mos t = List.filter_map (fun x -> match x with | Auxiliary i -> Some i | _ -> None ) t let mo_class_array t = let sze = List.length t + 1 in let result = Array.make sze (Deleted 0) in List.iter (fun c -> match c with | Core i -> result.(i) <- Core i | Inactive i -> result.(i) <- Inactive i | Active i -> result.(i) <- Active i | Virtual i -> result.(i) <- Virtual i | Deleted i -> result.(i) <- Deleted i | Auxiliary i -> result.(i) <- Auxiliary i ) t; result let fci ~frozen_core mo_basis = let mo_num = MOBasis.size mo_basis in let ncore = (Nuclei.small_core @@ Simulation.nuclei @@ MOBasis.simulation mo_basis) / 2 in of_list ( if frozen_core then List.concat [ Util.list_range 1 ncore |> List.map (fun i -> Core i) ; Util.list_range (ncore+1) mo_num |> List.map (fun i -> Active i) ] else Util.list_range 1 mo_num |> List.map (fun i -> Active i) ) let cas_sd mo_basis ~frozen_core n m = let mo_num = MOBasis.size mo_basis in let n_alfa = MOBasis.simulation mo_basis |> Simulation.electrons |> Electrons.n_alfa in let n_beta = MOBasis.simulation mo_basis |> Simulation.electrons |> Electrons.n_beta in let n_unpaired = n_alfa - n_beta in let n_alfa_in_cas = (n - n_unpaired)/2 + n_unpaired in let last_inactive = n_alfa - n_alfa_in_cas in let last_active = last_inactive + m in let ncore = if frozen_core then (Nuclei.small_core @@ Simulation.nuclei @@ MOBasis.simulation mo_basis) / 2 |> min last_inactive else 0 in of_list ( List.concat [ if ncore > 0 then Util.list_range 1 ncore |> List.map (fun i -> Core i) else [] ; Util.list_range (ncore+1) last_inactive |> List.map (fun i -> Inactive i) ; Util.list_range (last_inactive+1) last_active |> List.map (fun i -> Active i) ; Util.list_range (last_active+1) mo_num |> List.map (fun i -> Virtual i) ] )