10
1
mirror of https://gitlab.com/scemama/QCaml.git synced 2024-11-14 10:03:39 +01:00
QCaml/linear_algebra/lib/diis.ml

68 lines
1.2 KiB
OCaml
Raw Normal View History

2020-10-02 14:43:58 +02:00
type 'a t =
2018-05-31 16:46:45 +02:00
{
2020-10-02 14:43:58 +02:00
p : 'a Vector.t list;
e : 'a Vector.t list;
2018-05-31 16:46:45 +02:00
m : int;
mmax : int;
}
let make ?mmax:(mmax=15) () =
assert (mmax > 1);
{
p = [];
e = [];
m = 0 ;
mmax;
}
let append ~p ~e diis =
let update v l =
if diis.m < diis.mmax then
v :: l
else
match List.rev l with
| [] -> assert false
| _ :: rest -> v :: List.rev rest
in
{ diis with
p = update p diis.p;
e = update e diis.e;
m = min diis.mmax (diis.m+1);
}
2020-10-02 18:55:19 +02:00
type nvec
type one
2018-05-31 16:46:45 +02:00
let next diis =
2020-09-26 12:02:53 +02:00
let e = Matrix.of_col_vecs_list diis.e
and p = Matrix.of_col_vecs_list diis.p
2018-05-31 16:46:45 +02:00
in
let a =
let rec aux m =
2020-09-26 12:02:53 +02:00
let a = Matrix.make (m+1) (m+1) 1. in
let ax = Matrix.to_bigarray_inplace a in
ax.{m+1,m+1} <- 0.;
2020-10-02 18:55:19 +02:00
Matrix.gemm_tn_inplace ~c:a ~m ~n:m e e;
2020-09-26 12:02:53 +02:00
if m > 1 && Matrix.sycon a > 1.e-14 then
2019-09-10 18:39:14 +02:00
(aux [@tailcall]) (m-1)
2018-05-31 18:50:34 +02:00
else a
2018-05-31 16:46:45 +02:00
in
aux diis.m
in
2020-09-26 12:02:53 +02:00
let m = Matrix.dim1 a - 1 in
2020-10-02 18:55:19 +02:00
let c : (nvec,one) Matrix.t = Matrix.make0 (m+1) 1 in
2020-09-26 12:02:53 +02:00
let cx = Matrix.to_bigarray_inplace c in
cx.{m+1,1} <- 1.;
2020-10-02 18:55:19 +02:00
Matrix.sysv_inplace a ~b:c ;
Matrix.gemm_nn ~k:m p c
2020-09-26 12:02:53 +02:00
|> Matrix.as_vec_inplace
2020-10-02 18:55:19 +02:00
|> Vector.relabel
2018-05-31 16:46:45 +02:00
2020-10-02 18:55:19 +02:00
(*
|> Vector.relabel
*)
2018-05-31 16:46:45 +02:00