type t = { p : Vector.t list; e : Vector.t list; 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); } let next diis = let e = Matrix.of_col_vecs_list diis.e and p = Matrix.of_col_vecs_list diis.p in let a = let rec aux m = let a = Matrix.make (m+1) (m+1) 1. in let ax = Matrix.to_bigarray_inplace a in ax.{m+1,m+1} <- 0.; Matrix.gemm_inplace ~c:a ~transa:`T ~m ~n:m e e; if m > 1 && Matrix.sycon a > 1.e-14 then (aux [@tailcall]) (m-1) else a in aux diis.m in let m = Matrix.dim1 a - 1 in let c = Matrix.make0 (m+1) 1 in let cx = Matrix.to_bigarray_inplace c in cx.{m+1,1} <- 1.; Matrix.sysv_inplace ~b:c a; Matrix.gemm p c ~k:m |> Matrix.as_vec_inplace