10
1
mirror of https://gitlab.com/scemama/QCaml.git synced 2024-11-07 06:33:39 +01:00

Huckel guess and DIIS OK

This commit is contained in:
Anthony Scemama 2018-05-31 17:48:54 +02:00
parent 3482e02695
commit e81a48dc73
2 changed files with 36 additions and 21 deletions

View File

@ -3,7 +3,7 @@ open Lacaml.D
open Simulation open Simulation
let make ?guess:(guess=`Huckel) ?max_scf:(max_scf=64) ?level_shift:(level_shift=0.1) let make ?guess:(guess=`Huckel) ?max_scf:(max_scf=64) ?level_shift:(level_shift=0.1)
?threshold_SCF:(threshold_SCF=1.e-6) simulation = ?threshold_SCF:(threshold_SCF=1.e-5) simulation =
(* Number of occupied MOs *) (* Number of occupied MOs *)
let nocc = let nocc =
@ -34,8 +34,8 @@ let make ?guess:(guess=`Huckel) ?max_scf:(max_scf=64) ?level_shift:(level_shift=
and m_V = Lazy.force simulation.eN_ints and m_V = Lazy.force simulation.eN_ints
in in
(* Level shift *) (* Level shift in MO basis *)
let m_LS = let m_LSmo =
Array.init (Mat.dim2 m_X) (fun i -> Array.init (Mat.dim2 m_X) (fun i ->
if i > nocc then level_shift else 0.) if i > nocc then level_shift else 0.)
|> Vec.of_array |> Vec.of_array
@ -43,7 +43,7 @@ let make ?guess:(guess=`Huckel) ?max_scf:(max_scf=64) ?level_shift:(level_shift=
in in
(* SCF iterations *) (* SCF iterations *)
let rec loop nSCF iterations m_C diis = let rec loop nSCF iterations energy_prev m_C diis =
(* Density matrix over nocc occupied MOs *) (* Density matrix over nocc occupied MOs *)
let m_P = let m_P =
@ -58,41 +58,50 @@ let make ?guess:(guess=`Huckel) ?max_scf:(max_scf=64) ?level_shift:(level_shift=
x.Fock.fock, x.Fock.core, x.Fock.coulomb, x.Fock.exchange x.Fock.fock, x.Fock.core, x.Fock.coulomb, x.Fock.exchange
in in
(* Add level shift in AO basis *)
let m_F =
let m_SC =
gemm m_S m_C
in
gemm m_SC (gemm m_LSmo m_SC ~transb:`T)
|> Mat.add m_F
in
(* Fock matrix in orthogonal basis *)
let m_F_ortho =
xt_o_x m_F m_X
in
let error_fock = let error_fock =
let fps = let fps =
gemm m_F (gemm m_P m_S) gemm m_F (gemm m_P m_S)
and spf = and spf =
gemm m_S (gemm m_P m_F) gemm m_S (gemm m_P m_F)
in in
Mat.sub fps spf xt_o_x (Mat.sub fps spf) m_X
in in
let diis = let diis =
DIIS.append ~p:(Mat.as_vec m_F) ~e:(Mat.as_vec error_fock) diis DIIS.append ~p:(Mat.as_vec m_F_ortho) ~e:(Mat.as_vec error_fock) diis
in in
let m_F_diis = let m_F_diis =
let x = let x =
Bigarray.genarray_of_array1 (DIIS.next diis) Bigarray.genarray_of_array1 (DIIS.next diis)
in in
Bigarray.reshape_2 x (Mat.dim1 m_F) (Mat.dim2 m_F) Bigarray.reshape_2 x (Mat.dim1 m_F_ortho) (Mat.dim2 m_F_ortho)
in in
(* Fock matrix in MO basis *) (* MOs in orthogonal MO basis *)
let m_Fmo =
xt_o_x m_F_diis m_C
|> Mat.add m_LS
in
(* MOs in old MO basis *)
let m_C', eigenvalues = let m_C', eigenvalues =
diagonalize_symm m_Fmo diagonalize_symm m_F_diis
in in
(* MOs in AO basis *) (* MOs in AO basis *)
let m_C = let m_C =
gemm m_C m_C' gemm m_X m_C'
in in
(* Hartree-Fock energy *) (* Hartree-Fock energy *)
@ -103,7 +112,7 @@ let make ?guess:(guess=`Huckel) ?max_scf:(max_scf=64) ?level_shift:(level_shift=
(* Convergence criterion *) (* Convergence criterion *)
let error = let error =
xt_o_x error_fock m_C error_fock
|> Mat.as_vec |> Mat.as_vec
|> amax |> amax
|> abs_float |> abs_float
@ -117,10 +126,16 @@ let make ?guess:(guess=`Huckel) ?max_scf:(max_scf=64) ?level_shift:(level_shift=
eigenvalues.{nocc+1} -. eigenvalues.{nocc}; eigenvalues.{nocc+1} -. eigenvalues.{nocc};
in in
Printf.printf "%d %16.10f %11.4e %10.4f\n%!" nSCF energy error gap; let () =
match energy_prev with
| Some energy_prev ->
Printf.eprintf "%3d %16.10f %16.10f %11.4e %10.4f\n%!" nSCF energy (energy -. energy_prev) error gap
| None ->
Printf.eprintf "%3d %16.10f %16s %11.4e %10.4f\n%!" nSCF energy "" error gap
in
if not converged then if not converged then
loop (nSCF+1) ( (energy, error, gap) :: iterations) m_C diis loop (nSCF+1) ( (energy, error, gap) :: iterations) (Some energy) m_C diis
else else
let iterations = let iterations =
List.rev ( (energy, error, gap) :: iterations ) List.rev ( (energy, error, gap) :: iterations )
@ -159,7 +174,7 @@ let make ?guess:(guess=`Huckel) ?max_scf:(max_scf=64) ?level_shift:(level_shift=
in in
let diis = DIIS.make () in let diis = DIIS.make () in
loop 1 [] m_C diis loop 1 [] None m_C diis

View File

@ -44,7 +44,7 @@ let next diis =
let a = Mat.make (m+1) (m+1) 1. in let a = Mat.make (m+1) (m+1) 1. in
a.{m+1,m+1} <- 0.; a.{m+1,m+1} <- 0.;
ignore @@ lacpy ~b:a (gemm ~transa:`T ~m ~n:m e e); ignore @@ lacpy ~b:a (gemm ~transa:`T ~m ~n:m e e);
if sycon (lacpy a) > 1.e-10 then a if sycon (lacpy a) > 1.e-14 then a
else aux (m-1) else aux (m-1)
in in
aux diis.m aux diis.m