From f873b36213140b8173bee1cc89406e82143dc1e5 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Mon, 19 Jul 2021 09:55:58 +0200 Subject: [PATCH 01/50] First stage of QMCkl integration of Sherman-Morrison-Woodbury kernels. --- org/qmckl_sherman_morrison_woodbury.cpp | 535 ++++++++++++++++++++++++ 1 file changed, 535 insertions(+) create mode 100644 org/qmckl_sherman_morrison_woodbury.cpp diff --git a/org/qmckl_sherman_morrison_woodbury.cpp b/org/qmckl_sherman_morrison_woodbury.cpp new file mode 100644 index 0000000..5903905 --- /dev/null +++ b/org/qmckl_sherman_morrison_woodbury.cpp @@ -0,0 +1,535 @@ +#include + +// Sherman-Morrison-Woodbury break-down threshold +#ifndef THRESHOLD +#define THRESHOLD 1e-3 +#endif +double threshold(); + +// Naïve Sherman Morrison +void sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N_updates, + double *Updates, unsigned int *Updates_index); + +// Woodbury 2x2 kernel +bool woodbury_2(double *Slater_inv, const unsigned int Dim, double *Updates, + const unsigned int *Updates_index); + +// Woodbury 3x3 kernel +bool woodbury_3(double *Slater_inv, const unsigned int Dim, double *Updates, + const unsigned int *Updates_index); + +// Sherman Morrison, with J. Slagel splitting (caller function) +void sherman_morrison_splitting_caller(double *Slater_inv, unsigned int Dim, unsigned int N_updates, + double *Updates, unsigned int *Updates_index); + +// Sherman Morrison, with J. Slagel splitting +// http://hdl.handle.net/10919/52966 +void sherman_morrison_splitting(double *Slater_inv, unsigned int Dim, unsigned int N_updates, + double *Updates, unsigned int *Updates_index, + double *later_updates, unsigned int *later_index, + unsigned int *later); + +// Mixed Sherman-Morrison-Woodbury kernel using +// Woodbury 2x2 and Sherman-Morrison with update-splitting +void sherman_morrison_woodbury_2(double *Slater_inv, const unsigned int Dim, + const unsigned int N_updates, double *Updates, + unsigned int *Updates_index); + +// Mixed Sherman-Morrison-Woodbury kernel using +// Woodbury 3x3, Woodbury 2x2 and Sherman-Morrison with update-splitting +void sherman_morrison_woodbury_3(double *Slater_inv, const unsigned int Dim, + const unsigned int N_updates, double *Updates, + unsigned int *Updates_index); + + + +// Sherman-Morrison-Woodbury break-down threshold +double threshold() { + const double threshold = THRESHOLD; +#ifdef DEBUG2 + std::cerr << "Break-down threshold set to: " << threshold << std::endl; +#endif + return threshold; +} + +// Naïve Sherman Morrison +void sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N_updates, + double *Updates, unsigned int *Updates_index) { +#ifdef DEBUG1 + std::cerr << "Called sherman_morrison with " << N_updates << " updates" << std::endl; +#endif + + double C[Dim]; + double D[Dim]; + + unsigned int l = 0; + // For each update + while (l < N_updates) { + // C = A^{-1} x U_l + for (unsigned int i = 0; i < Dim; i++) { + C[i] = 0; + for (unsigned int j = 0; j < Dim; j++) { + C[i] += Slater_inv[i * Dim + j] * Updates[l * Dim + j]; + } + } + + // Denominator + double den = 1 + C[Updates_index[l] - 1]; + if (std::fabs(den) < threshold()) { +#ifdef DEBUG1 + std::cerr << "Breakdown condition triggered at " << Updates_index[l] + << std::endl; +#endif + } + double iden = 1 / den; + + // D = v^T x A^{-1} + for (unsigned int j = 0; j < Dim; j++) { + D[j] = Slater_inv[(Updates_index[l] - 1) * Dim + j]; + } + + // A^{-1} = A^{-1} - C x D / den + for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + double update = C[i] * D[j] * iden; + Slater_inv[i * Dim + j] -= update; + } + } + + l += 1; + } +} + +// Woodbury 2x2 kernel +bool woodbury_2(double *Slater_inv, const unsigned int Dim, double *Updates, + const unsigned int *Updates_index) { +/* + C := S^{-1} * U, dim x 2 + B := 1 + V * C, 2 x 2 + D := V * S^{-1}, 2 x dim +*/ +#ifdef DEBUG1 + std::cerr << "Called Woodbury 2x2 kernel" << std::endl; +#endif + + const unsigned int row1 = (Updates_index[0] - 1); + const unsigned int row2 = (Updates_index[1] - 1); + + // Compute C = S_inv * U !! NON-STANDARD MATRIX MULTIPLICATION BECAUSE + // OF LAYOUT OF 'Updates' !! + double C[2 * Dim]; + for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < 2; j++) { + C[i * 2 + j] = 0; + for (unsigned int k = 0; k < Dim; k++) { + C[i * 2 + j] += Slater_inv[i * Dim + k] * Updates[Dim * j + k]; + } + } + } + + // Compute B = 1 + V * C + const double B0 = C[row1 * 2] + 1; + const double B1 = C[row1 * 2 + 1]; + const double B2 = C[row2 * 2]; + const double B3 = C[row2 * 2 + 1] + 1; + + // Check if determinant of inverted matrix is not zero + double det = B0 * B3 - B1 * B2; + if (std::fabs(det) < threshold()) { +#ifdef DEBUG1 + std::cerr << "Determinant too close to zero! No inverse found." + << std::endl; + std::cerr << "Determinant = " << det << std::endl; +#endif + return false; + } + + // Compute B^{-1} with explicit formula for 2x2 inversion + double Binv[4], idet = 1.0 / det; + Binv[0] = idet * B3; + Binv[1] = -1.0 * idet * B1; + Binv[2] = -1.0 * idet * B2; + Binv[3] = idet * B0; + + // Compute tmp = B^{-1} x (V.S^{-1}) + double tmp[2 * Dim]; + for (unsigned int i = 0; i < 2; i++) { + for (unsigned int j = 0; j < Dim; j++) { + tmp[i * Dim + j] = Binv[i * 2] * Slater_inv[row1 * Dim + j]; + tmp[i * Dim + j] += Binv[i * 2 + 1] * Slater_inv[row2 * Dim + j]; + } + } + + // Compute (S + U V)^{-1} = S^{-1} - C x tmp + for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + Slater_inv[i * Dim + j] -= C[i * 2] * tmp[j]; + Slater_inv[i * Dim + j] -= C[i * 2 + 1] * tmp[Dim + j]; + } + } + + return true; +} + +// Woodbury 3x3 kernel +bool woodbury_3(double *Slater_inv, const unsigned int Dim, double *Updates, + const unsigned int *Updates_index) { +/* + C := S^{-1} * U, dim x 3 + B := 1 + V * C, 3 x 3 + D := V * S^{-1}, 3 x dim +*/ +#ifdef DEBUG1 + std::cerr << "Called Woodbury 3x3 kernel" << std::endl; +#endif + + const unsigned int row1 = (Updates_index[0] - 1); + const unsigned int row2 = (Updates_index[1] - 1); + const unsigned int row3 = (Updates_index[2] - 1); + + // Compute C = S_inv * U !! NON-STANDARD MATRIX MULTIPLICATION BECAUSE + // OF LAYOUT OF 'Updates' !! + double C[3 * Dim]; + for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < 3; j++) { + C[i * 3 + j] = 0; + for (unsigned int k = 0; k < Dim; k++) { + C[i * 3 + j] += Slater_inv[i * Dim + k] * Updates[Dim * j + k]; + } + } + } + +#ifdef DEBUG2 + showMatrix2(C, Dim, 3, "C = S_inv * U"); + showMatrix2(D, 3, Dim, "D = V * S_inv"); +#endif + + // Compute B = 1 + V.C + const double B0 = C[row1 * 3] + 1; + const double B1 = C[row1 * 3 + 1]; + const double B2 = C[row1 * 3 + 2]; + const double B3 = C[row2 * 3]; + const double B4 = C[row2 * 3 + 1] + 1; + const double B5 = C[row2 * 3 + 2]; + const double B6 = C[row3 * 3]; + const double B7 = C[row3 * 3 + 1]; + const double B8 = C[row3 * 3 + 2] + 1; + +#ifdef DEBUG2 + showMatrix2(B, 3, 3, "B = 1 + V * C"); +#endif + + // Check if determinant of B is not too close to zero + double det; + det = B0 * (B4 * B8 - B5 * B7) - B1 * (B3 * B8 - B5 * B6) + + B2 * (B3 * B7 - B4 * B6); +#ifdef DEBUG2 + std::cerr << "Determinant of B = " << det << std::endl; +#endif + if (std::fabs(det) < threshold()) { +#ifdef DEBUG1 + std::cerr << "Determinant too close to zero! No inverse found." + << std::endl; + std::cerr << "Determinant = " << det << std::endl; +#endif + return false; + } + + // Compute B^{-1} with explicit formula for 3x3 inversion + double Binv[9], idet = 1.0 / det; + Binv[0] = (B4 * B8 - B7 * B5) * idet; + Binv[1] = -(B1 * B8 - B7 * B2) * idet; + Binv[2] = (B1 * B5 - B4 * B2) * idet; + Binv[3] = -(B3 * B8 - B6 * B5) * idet; + Binv[4] = (B0 * B8 - B6 * B2) * idet; + Binv[5] = -(B0 * B5 - B3 * B2) * idet; + Binv[6] = (B3 * B7 - B6 * B4) * idet; + Binv[7] = -(B0 * B7 - B6 * B1) * idet; + Binv[8] = (B0 * B4 - B3 * B1) * idet; + +#ifdef DEBUG2 + std::cerr << "Conditioning number of B = " << condition1(B, Binv, 3) + << std::endl; + showMatrix2(Binv, 3, 3, "Binv"); +#endif + + // Compute tmp = B^{-1} x (V.S^{-1}) + double tmp[3 * Dim]; + for (unsigned int i = 0; i < 3; i++) { + for (unsigned int j = 0; j < Dim; j++) { + tmp[i * Dim + j] = Binv[i * 3] * Slater_inv[row1 * Dim + j]; + tmp[i * Dim + j] += Binv[i * 3 + 1] * Slater_inv[row2 * Dim + j]; + tmp[i * Dim + j] += Binv[i * 3 + 2] * Slater_inv[row3 * Dim + j]; + } + } + +#ifdef DEBUG2 + showMatrix2(tmp, 3, Dim, "tmp = Binv * D"); +#endif + + // Compute (S + U V)^{-1} = S^{-1} - C x tmp + for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + Slater_inv[i * Dim + j] -= C[i * 3] * tmp[j]; + Slater_inv[i * Dim + j] -= C[i * 3 + 1] * tmp[Dim + j]; + Slater_inv[i * Dim + j] -= C[i * 3 + 2] * tmp[2 * Dim + j]; + } + } + +#ifdef DEBUG2 + showMatrix2(Slater_inv, Dim, Dim, "Slater_inv AFTER update"); +#endif + return true; +} + +// Sherman Morrison, with J. Slagel splitting (caller function) +// http://hdl.handle.net/10919/52966 +void sherman_morrison_splitting_caller(double *Slater_inv, unsigned int Dim, unsigned int N_updates, + double *Updates, unsigned int *Updates_index) { +#ifdef DEBUG1 + std::cerr << "Called sherman_morrison_splitting with " << N_updates << " updates" << std::endl; +#endif + + double later_updates[Dim * N_updates]; + unsigned int later_index[N_updates]; + unsigned int later = 0; + + sherman_morrison_splitting(Slater_inv, Dim, N_updates, Updates, Updates_index, later_updates, + later_index, &later); + + if (later > 0) { + sherman_morrison_splitting_caller(Slater_inv, Dim, later, later_updates, later_index); + } +} + +// Sherman Morrison, with J. Slagel splitting +// http://hdl.handle.net/10919/52966 +void sherman_morrison_splitting(double *Slater_inv, unsigned int Dim, unsigned int N_updates, + double *Updates, unsigned int *Updates_index, + double *later_updates, unsigned int *later_index, + unsigned int *later) { +#ifdef DEBUG1 + std::cerr << "Called sherman_morrison_splitting* with " << N_updates << " updates" << std::endl; +#endif + + double C[Dim]; + double D[Dim]; + + unsigned int l = 0; + // For each update + while (l < N_updates) { + // C = S^{-1} x U_l + for (unsigned int i = 0; i < Dim; i++) { + C[i] = 0; + for (unsigned int j = 0; j < Dim; j++) { + C[i] += Slater_inv[i * Dim + j] * Updates[l * Dim + j]; + } + } + + // Denominator + double den = 1 + C[Updates_index[l] - 1]; + if (std::fabs(den) < threshold()) { +#ifdef DEBUG1 + std::cerr << "Breakdown condition triggered at " << Updates_index[l] + << std::endl; + std::cerr << "Denominator = " << den << std::endl; +#endif + + // U_l = U_l / 2 (do the split) + for (unsigned int i = 0; i < Dim; i++) { + later_updates[*later * Dim + i] = Updates[l * Dim + i] / 2.0; + C[i] /= 2.0; + } + later_index[*later] = Updates_index[l]; + (*later)++; + + den = 1 + C[Updates_index[l] - 1]; + } + double iden = 1 / den; + + // D = v^T x S^{-1} + for (unsigned int j = 0; j < Dim; j++) { + D[j] = Slater_inv[(Updates_index[l] - 1) * Dim + j]; + } + + // S^{-1} = S^{-1} - C x D / den + for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + double update = C[i] * D[j] * iden; + Slater_inv[i * Dim + j] -= update; + } + } + l += 1; + } +} + +// Sherman-Morrison-Woodbury kernel 2 +// woodbury_2, sherman_morrison_splitting mixing scheme +void sherman_morrison_woodbury_2(double *Slater_inv, const unsigned int Dim, + const unsigned int N_updates, double *Updates, + unsigned int *Updates_index) { +#ifdef DEBUG2 + std::cerr << "Called Sherman-Morrison-Woodbury kernel 1 with " << N_updates + << " updates" << std::endl; + showMatrix2(Updates_index, 1, N_updates, "Updates_index"); + showMatrix2(Updates, N_updates, Dim, "Updates"); +#endif + + unsigned int n_of_2blocks = N_updates / 2; + unsigned int remainder = N_updates % 2; + unsigned int length_2block = 2 * Dim; + unsigned int length_1block = 1 * Dim; + + // Apply first 2*n_of_2blocks updates in n_of_2blocks blocks of 2 updates with + // Woodbury 2x2 kernel + double later_updates[Dim * N_updates]; + unsigned int later_index[N_updates]; + unsigned int later = 0; + if (n_of_2blocks > 0) { + for (unsigned int i = 0; i < n_of_2blocks; i++) { + double *Updates_2block = &Updates[i * length_2block]; + unsigned int *Updates_index_2block = &Updates_index[i * 2]; + bool ok; + ok = woodbury_2(Slater_inv, Dim, Updates_2block, Updates_index_2block); + if (!ok) { // Send the entire block to sherman_morrison_splitting +#ifdef DEBUG1 + std::cerr << "Woodbury 2x2 kernel failed! Sending block to sherman_morrison_splitting" + << std::endl; +#endif +#ifdef DEBUG2 + showMatrix2(Updates_2block, 2, Dim, "Updates_2block"); + showMatrix2(Updates_index_2block, 1, 2, "Updates_index_2block"); +#endif + unsigned int l = 0; + sherman_morrison_splitting(Slater_inv, Dim, 2, Updates_2block, Updates_index_2block, + later_updates + (Dim * later), later_index + later, &l); + later = later + l; + } + } + } + + if (remainder == 1) { // Apply last remaining update with sherman_morrison_splitting + double *Updates_1block = &Updates[n_of_2blocks * length_2block]; + unsigned int *Updates_index_1block = &Updates_index[2 * n_of_2blocks]; + unsigned int l = 0; + sherman_morrison_splitting(Slater_inv, Dim, 1, Updates_1block, Updates_index_1block, + later_updates + (Dim * later), later_index + later, &l); + later = later + l; + } + + if (later > 0) { + sherman_morrison_splitting_caller(Slater_inv, Dim, later, later_updates, later_index); + } +} + +// Sherman-Morrison-Woodbury kernel 3 +// woodbury_2, woodbury_3, sherman_morrison_splitting mixing scheme +void sherman_morrison_woodbury_3(double *Slater_inv, const unsigned int Dim, + const unsigned int N_updates, double *Updates, + unsigned int *Updates_index) { +#ifdef DEBUG2 + std::cerr << "Called Sherman-Morrison-Woodbury kernel 1 with " << N_updates + << " updates" << std::endl; + showMatrix2(Updates_index, 1, N_updates, "Updates_index"); + showMatrix2(Updates, N_updates, Dim, "Updates"); +#endif + + unsigned int n_of_3blocks = N_updates / 3; + unsigned int remainder = N_updates % 3; + unsigned int length_3block = 3 * Dim; + unsigned int length_2block = 2 * Dim; + unsigned int length_1block = 1 * Dim; + + // Apply first 3*n_of_3blocks updates in n_of_3blocks blocks of 3 updates with + // Woodbury 3x3 kernel + double later_updates[Dim * N_updates]; + unsigned int later_index[N_updates]; + unsigned int later = 0; + if (n_of_3blocks > 0) { + for (unsigned int i = 0; i < n_of_3blocks; i++) { + double *Updates_3block = &Updates[i * length_3block]; + unsigned int *Updates_index_3block = &Updates_index[i * 3]; + bool ok; + ok = woodbury_3(Slater_inv, Dim, Updates_3block, Updates_index_3block); + if (!ok) { // Send the entire block to sherman_morrison_splitting +#ifdef DEBUG2 + std::cerr << "Woodbury 3x3 kernel failed! Sending block to sherman_morrison_splitting" + << std::endl; + showMatrix2(Updates_3block, 3, Dim, "Updates_3block"); + showMatrix2(Updates_index_3block, 1, 3, "Updates_index_3block"); +#endif + unsigned int l = 0; + sherman_morrison_splitting(Slater_inv, Dim, 3, Updates_3block, Updates_index_3block, + later_updates + (Dim * later), later_index + later, &l); + later = later + l; + } + } + } + + if (remainder == 2) { // Apply last remaining block of 2 updates with Woodbury 2x2 kernel + double *Updates_2block = &Updates[n_of_3blocks * length_3block]; + unsigned int *Updates_index_2block = &Updates_index[3 * n_of_3blocks]; + bool ok; + ok = woodbury_2(Slater_inv, Dim, Updates_2block, Updates_index_2block); + if (!ok) { // Send the entire block to sherman_morrison_splitting +#ifdef DEBUG2 + std::cerr << "Woodbury 2x2 kernel failed! Sending block to sherman_morrison_splitting" + << std::endl; +#endif + unsigned int l = 0; + sherman_morrison_splitting(Slater_inv, Dim, 2, Updates_2block, Updates_index_2block, + later_updates + (Dim * later), later_index + later, &l); + later = later + l; + } + } + else if (remainder == 1) { // Apply last remaining update with sherman_morrison_splitting + double *Updates_1block = &Updates[n_of_3blocks * length_3block]; + unsigned int *Updates_index_1block = &Updates_index[3 * n_of_3blocks]; + unsigned int l = 0; + sherman_morrison_splitting(Slater_inv, Dim, 1, Updates_1block, Updates_index_1block, + later_updates + (Dim * later), later_index + later, &l); + later = later + l; + } + + if (later > 0) { + sherman_morrison_splitting_caller(Slater_inv, Dim, later, later_updates, later_index); + } +} + + + +extern "C" { + void sherman_morrison_f(double **linSlater_inv, unsigned int *Dim, unsigned int *N_updates, + double **linUpdates, unsigned int **Updates_index) { + sherman_morrison(*linSlater_inv, *Dim, *N_updates, *linUpdates, *Updates_index); + } + + bool woodbury_2_f(double **linSlater_inv, unsigned int *Dim, double **linUpdates, + unsigned int **Updates_index) { + bool ok; + ok = woodbury_2(*linSlater_inv, *Dim, *linUpdates, *Updates_index); + return ok; + } + + bool woodbury_3_f(double **linSlater_inv, unsigned int *Dim, double **linUpdates, + unsigned int **Updates_index) { + bool ok; + ok = woodbury_3(*linSlater_inv, *Dim, *linUpdates, *Updates_index); + return ok; + } + + void sherman_morrison_splitting_caller_f(double **linSlater_inv, unsigned int *Dim, unsigned int *N_updates, + double **linUpdates, unsigned int **Updates_index) { + sherman_morrison_splitting_caller(*linSlater_inv, *Dim, *N_updates, *linUpdates, *Updates_index); + } + + void sherman_morrison_woodbury_3_f(double **linSlater_inv, unsigned int *Dim, unsigned int *N_updates, + double **linUpdates, unsigned int **Updates_index) { + sherman_morrison_woodbury_3(*linSlater_inv, *Dim, *N_updates, *linUpdates, *Updates_index); + } + + void sherman_morrison_woodbury_2_f(double **linSlater_inv, unsigned int *Dim, unsigned int *N_updates, + double **linUpdates, unsigned int **Updates_index) { + sherman_morrison_woodbury_2(*linSlater_inv, *Dim, *N_updates, *linUpdates, *Updates_index); + } +} From 269f8d33d26ec9600a7aaf085f872a47bd9a4ab4 Mon Sep 17 00:00:00 2001 From: vijay gopal chilkuri Date: Mon, 19 Jul 2021 15:29:32 +0530 Subject: [PATCH 02/50] Added template org file for Francois. #25 --- org/table_of_contents | 1 + 1 file changed, 1 insertion(+) diff --git a/org/table_of_contents b/org/table_of_contents index 50a6159..dfc6f52 100644 --- a/org/table_of_contents +++ b/org/table_of_contents @@ -7,6 +7,7 @@ qmckl_nucleus.org qmckl_electron.org qmckl_ao.org qmckl_jastrow.org +qmckl_sherman_morrison_woodbury.org qmckl_distance.org qmckl_utils.org qmckl_tests.org From b0fd86db408a58be38eb18bb6f1b2403f1f509c2 Mon Sep 17 00:00:00 2001 From: vijay gopal chilkuri Date: Mon, 19 Jul 2021 15:31:07 +0530 Subject: [PATCH 03/50] Added missing org file. #25 --- org/qmckl_sherman_morrison_woodbury.org | 59 +++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 org/qmckl_sherman_morrison_woodbury.org diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org new file mode 100644 index 0000000..7436031 --- /dev/null +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -0,0 +1,59 @@ +#+TITLE: Sherman-Morrison-Woodbury +#+SETUPFILE: ../tools/theme.setup +#+INCLUDE: ../tools/lib.org + +[TODO: FMJC] Please add some intro. + +* Headers + #+begin_src elisp :noexport :results none +(org-babel-lob-ingest "../tools/lib.org") +#+end_src + + #+begin_src c :comments link :tangle (eval c_test) :noweb yes +#include "qmckl.h" +#include "assert.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +int main() { + qmckl_context context; + context = qmckl_context_create(); + + #+end_src + +* Sherman Morrison + +[TODO: FMJC] Add general doc for Naive SM. + +** ~qmckl_sherman_morrison~ + :PROPERTIES: + :Name: qmckl_sherman_morrison + :CRetType: qmckl_exit_code + :FRetType: qmckl_exit_code + :END: + +[TODO: FMJC] Add some detailed description. Including formulae etc. + + #+NAME: qmckl_sherman_morrison_args + | qmckl_context | context | in | Global state | + +*** Requirements + +[TODO: FMJC] Add description of the input variables. (see for e.g. qmckl_distance.org) + +*** C header +*** Source +*** Performance + +* End of files + + #+begin_src c :comments link :tangle (eval c_test) + assert (qmckl_context_destroy(context) == QMCKL_SUCCESS); + return 0; +} + + #+end_src + + +# -*- mode: org -*- +# vim: syntax=c From 36e414aacde4a9e97870dbf4427d74ba49386ba1 Mon Sep 17 00:00:00 2001 From: vijay gopal chilkuri Date: Mon, 19 Jul 2021 17:30:10 +0530 Subject: [PATCH 04/50] Added call to generate_c_header to template. #25 --- org/qmckl_sherman_morrison_woodbury.org | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 7436031..61c4a45 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -20,7 +20,7 @@ int main() { context = qmckl_context_create(); #+end_src - + * Sherman Morrison [TODO: FMJC] Add general doc for Naive SM. @@ -35,13 +35,16 @@ int main() { [TODO: FMJC] Add some detailed description. Including formulae etc. #+NAME: qmckl_sherman_morrison_args - | qmckl_context | context | in | Global state | + | qmckl_context | context | in | Global state | *** Requirements [TODO: FMJC] Add description of the input variables. (see for e.g. qmckl_distance.org) *** C header + + #+CALL: generate_c_header(table=qmckl_distance_sq_args,rettyp=get_value("CRetType"),fname=get_value("Name")) + *** Source *** Performance From 6c2866967d1f5a5cc68f1fdd33229cc0ccf311d7 Mon Sep 17 00:00:00 2001 From: vijay gopal chilkuri Date: Mon, 19 Jul 2021 17:31:11 +0530 Subject: [PATCH 05/50] Added call to generate_c_interface in template. #25 --- org/qmckl_sherman_morrison_woodbury.org | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 61c4a45..56f7309 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -48,6 +48,10 @@ int main() { *** Source *** Performance +** C interface + + #+CALL: generate_c_interface(table=qmckl_distance_sq_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + * End of files #+begin_src c :comments link :tangle (eval c_test) From 897eb3f34e33949f20915e483a2084b429e9e90a Mon Sep 17 00:00:00 2001 From: vijay gopal chilkuri Date: Mon, 19 Jul 2021 17:31:34 +0530 Subject: [PATCH 06/50] Added call to generate_f_interface in template. #25 --- org/qmckl_sherman_morrison_woodbury.org | 2 ++ 1 file changed, 2 insertions(+) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 56f7309..2a1dc49 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -52,6 +52,8 @@ int main() { #+CALL: generate_c_interface(table=qmckl_distance_sq_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+CALL: generate_f_interface(table=qmckl_distance_sq_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + * End of files #+begin_src c :comments link :tangle (eval c_test) From 4e31dc4ac4f96cb43352860122778c31c65a903f Mon Sep 17 00:00:00 2001 From: vijay gopal chilkuri Date: Mon, 19 Jul 2021 17:34:47 +0530 Subject: [PATCH 07/50] Added Tests block and set the noexport tags. #25 --- org/qmckl_sherman_morrison_woodbury.org | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 2a1dc49..fba8faa 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -43,16 +43,20 @@ int main() { *** C header - #+CALL: generate_c_header(table=qmckl_distance_sq_args,rettyp=get_value("CRetType"),fname=get_value("Name")) + #+CALL: generate_c_header(table=qmckl_sherman_morrison_args,rettyp=get_value("CRetType"),fname=get_value("Name")) *** Source *** Performance -** C interface +** C interface :noexport: - #+CALL: generate_c_interface(table=qmckl_distance_sq_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+CALL: generate_c_interface(table=qmckl_sherman_morrison_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - #+CALL: generate_f_interface(table=qmckl_distance_sq_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+CALL: generate_f_interface(table=qmckl_sherman_morrison_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + +*** Test :noexport: + +[TODO: FMJC] Write tests for the Sherman-Morrison part. * End of files From 81f56969507e40d722fa4eb44fb7be3b79aa5370 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Mon, 19 Jul 2021 16:15:28 +0200 Subject: [PATCH 08/50] Changed internal functions to static functions. Changed function names to conform with QMCkl naming conventions. Removed irrelevant debug output. qmckl_sherman_morrison() now returns false if the denominator is too close to 0 and true if it is ok. #25 --- org/qmckl_sherman_morrison_woodbury.cpp | 207 ++++++------------------ 1 file changed, 53 insertions(+), 154 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.cpp b/org/qmckl_sherman_morrison_woodbury.cpp index 5903905..10a7dde 100644 --- a/org/qmckl_sherman_morrison_woodbury.cpp +++ b/org/qmckl_sherman_morrison_woodbury.cpp @@ -4,59 +4,59 @@ #ifndef THRESHOLD #define THRESHOLD 1e-3 #endif -double threshold(); +static double threshold(); // Naïve Sherman Morrison -void sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N_updates, +bool qmckl_sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N_updates, double *Updates, unsigned int *Updates_index); // Woodbury 2x2 kernel -bool woodbury_2(double *Slater_inv, const unsigned int Dim, double *Updates, +bool qmckl_woodbury_2(double *Slater_inv, const unsigned int Dim, double *Updates, const unsigned int *Updates_index); // Woodbury 3x3 kernel -bool woodbury_3(double *Slater_inv, const unsigned int Dim, double *Updates, +bool qmckl_woodbury_3(double *Slater_inv, const unsigned int Dim, double *Updates, const unsigned int *Updates_index); // Sherman Morrison, with J. Slagel splitting (caller function) -void sherman_morrison_splitting_caller(double *Slater_inv, unsigned int Dim, unsigned int N_updates, +void qmckl_sherman_morrison_splitting(double *Slater_inv, unsigned int Dim, unsigned int N_updates, double *Updates, unsigned int *Updates_index); // Sherman Morrison, with J. Slagel splitting // http://hdl.handle.net/10919/52966 -void sherman_morrison_splitting(double *Slater_inv, unsigned int Dim, unsigned int N_updates, +static void slagel_splitting(double *Slater_inv, unsigned int Dim, unsigned int N_updates, double *Updates, unsigned int *Updates_index, double *later_updates, unsigned int *later_index, unsigned int *later); // Mixed Sherman-Morrison-Woodbury kernel using // Woodbury 2x2 and Sherman-Morrison with update-splitting -void sherman_morrison_woodbury_2(double *Slater_inv, const unsigned int Dim, +void qmckl_sherman_morrison_woodbury_2(double *Slater_inv, const unsigned int Dim, const unsigned int N_updates, double *Updates, unsigned int *Updates_index); // Mixed Sherman-Morrison-Woodbury kernel using // Woodbury 3x3, Woodbury 2x2 and Sherman-Morrison with update-splitting -void sherman_morrison_woodbury_3(double *Slater_inv, const unsigned int Dim, +void qmckl_sherman_morrison_woodbury_3(double *Slater_inv, const unsigned int Dim, const unsigned int N_updates, double *Updates, unsigned int *Updates_index); // Sherman-Morrison-Woodbury break-down threshold -double threshold() { +static double threshold() { const double threshold = THRESHOLD; -#ifdef DEBUG2 +#ifdef DEBUG std::cerr << "Break-down threshold set to: " << threshold << std::endl; #endif return threshold; } // Naïve Sherman Morrison -void sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N_updates, +bool qmckl_sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N_updates, double *Updates, unsigned int *Updates_index) { -#ifdef DEBUG1 - std::cerr << "Called sherman_morrison with " << N_updates << " updates" << std::endl; +#ifdef DEBUG + std::cerr << "Called qmckl_sherman_morrison with " << N_updates << " updates" << std::endl; #endif double C[Dim]; @@ -76,10 +76,7 @@ void sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N_updat // Denominator double den = 1 + C[Updates_index[l] - 1]; if (std::fabs(den) < threshold()) { -#ifdef DEBUG1 - std::cerr << "Breakdown condition triggered at " << Updates_index[l] - << std::endl; -#endif + return false; } double iden = 1 / den; @@ -98,17 +95,18 @@ void sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N_updat l += 1; } + return true; } // Woodbury 2x2 kernel -bool woodbury_2(double *Slater_inv, const unsigned int Dim, double *Updates, +bool qmckl_woodbury_2(double *Slater_inv, const unsigned int Dim, double *Updates, const unsigned int *Updates_index) { /* C := S^{-1} * U, dim x 2 B := 1 + V * C, 2 x 2 D := V * S^{-1}, 2 x dim */ -#ifdef DEBUG1 +#ifdef DEBUG std::cerr << "Called Woodbury 2x2 kernel" << std::endl; #endif @@ -136,11 +134,6 @@ bool woodbury_2(double *Slater_inv, const unsigned int Dim, double *Updates, // Check if determinant of inverted matrix is not zero double det = B0 * B3 - B1 * B2; if (std::fabs(det) < threshold()) { -#ifdef DEBUG1 - std::cerr << "Determinant too close to zero! No inverse found." - << std::endl; - std::cerr << "Determinant = " << det << std::endl; -#endif return false; } @@ -172,14 +165,14 @@ bool woodbury_2(double *Slater_inv, const unsigned int Dim, double *Updates, } // Woodbury 3x3 kernel -bool woodbury_3(double *Slater_inv, const unsigned int Dim, double *Updates, +bool qmckl_woodbury_3(double *Slater_inv, const unsigned int Dim, double *Updates, const unsigned int *Updates_index) { /* C := S^{-1} * U, dim x 3 B := 1 + V * C, 3 x 3 D := V * S^{-1}, 3 x dim */ -#ifdef DEBUG1 +#ifdef DEBUG std::cerr << "Called Woodbury 3x3 kernel" << std::endl; #endif @@ -199,11 +192,6 @@ bool woodbury_3(double *Slater_inv, const unsigned int Dim, double *Updates, } } -#ifdef DEBUG2 - showMatrix2(C, Dim, 3, "C = S_inv * U"); - showMatrix2(D, 3, Dim, "D = V * S_inv"); -#endif - // Compute B = 1 + V.C const double B0 = C[row1 * 3] + 1; const double B1 = C[row1 * 3 + 1]; @@ -215,23 +203,12 @@ bool woodbury_3(double *Slater_inv, const unsigned int Dim, double *Updates, const double B7 = C[row3 * 3 + 1]; const double B8 = C[row3 * 3 + 2] + 1; -#ifdef DEBUG2 - showMatrix2(B, 3, 3, "B = 1 + V * C"); -#endif - // Check if determinant of B is not too close to zero double det; det = B0 * (B4 * B8 - B5 * B7) - B1 * (B3 * B8 - B5 * B6) + B2 * (B3 * B7 - B4 * B6); -#ifdef DEBUG2 - std::cerr << "Determinant of B = " << det << std::endl; -#endif + if (std::fabs(det) < threshold()) { -#ifdef DEBUG1 - std::cerr << "Determinant too close to zero! No inverse found." - << std::endl; - std::cerr << "Determinant = " << det << std::endl; -#endif return false; } @@ -247,12 +224,6 @@ bool woodbury_3(double *Slater_inv, const unsigned int Dim, double *Updates, Binv[7] = -(B0 * B7 - B6 * B1) * idet; Binv[8] = (B0 * B4 - B3 * B1) * idet; -#ifdef DEBUG2 - std::cerr << "Conditioning number of B = " << condition1(B, Binv, 3) - << std::endl; - showMatrix2(Binv, 3, 3, "Binv"); -#endif - // Compute tmp = B^{-1} x (V.S^{-1}) double tmp[3 * Dim]; for (unsigned int i = 0; i < 3; i++) { @@ -263,10 +234,6 @@ bool woodbury_3(double *Slater_inv, const unsigned int Dim, double *Updates, } } -#ifdef DEBUG2 - showMatrix2(tmp, 3, Dim, "tmp = Binv * D"); -#endif - // Compute (S + U V)^{-1} = S^{-1} - C x tmp for (unsigned int i = 0; i < Dim; i++) { for (unsigned int j = 0; j < Dim; j++) { @@ -276,40 +243,37 @@ bool woodbury_3(double *Slater_inv, const unsigned int Dim, double *Updates, } } -#ifdef DEBUG2 - showMatrix2(Slater_inv, Dim, Dim, "Slater_inv AFTER update"); -#endif return true; } // Sherman Morrison, with J. Slagel splitting (caller function) // http://hdl.handle.net/10919/52966 -void sherman_morrison_splitting_caller(double *Slater_inv, unsigned int Dim, unsigned int N_updates, +void qmckl_sherman_morrison_splitting(double *Slater_inv, unsigned int Dim, unsigned int N_updates, double *Updates, unsigned int *Updates_index) { -#ifdef DEBUG1 - std::cerr << "Called sherman_morrison_splitting with " << N_updates << " updates" << std::endl; +#ifdef DEBUG + std::cerr << "Called qmckl_sherman_morrison_splitting with " << N_updates << " updates" << std::endl; #endif double later_updates[Dim * N_updates]; unsigned int later_index[N_updates]; unsigned int later = 0; - sherman_morrison_splitting(Slater_inv, Dim, N_updates, Updates, Updates_index, later_updates, + slagel_splitting(Slater_inv, Dim, N_updates, Updates, Updates_index, later_updates, later_index, &later); if (later > 0) { - sherman_morrison_splitting_caller(Slater_inv, Dim, later, later_updates, later_index); + qmckl_sherman_morrison_splitting(Slater_inv, Dim, later, later_updates, later_index); } } // Sherman Morrison, with J. Slagel splitting // http://hdl.handle.net/10919/52966 -void sherman_morrison_splitting(double *Slater_inv, unsigned int Dim, unsigned int N_updates, +static void slagel_splitting(double *Slater_inv, unsigned int Dim, unsigned int N_updates, double *Updates, unsigned int *Updates_index, double *later_updates, unsigned int *later_index, unsigned int *later) { -#ifdef DEBUG1 - std::cerr << "Called sherman_morrison_splitting* with " << N_updates << " updates" << std::endl; +#ifdef DEBUG + std::cerr << "Called slagel_splitting with " << N_updates << " updates" << std::endl; #endif double C[Dim]; @@ -329,11 +293,6 @@ void sherman_morrison_splitting(double *Slater_inv, unsigned int Dim, unsigned i // Denominator double den = 1 + C[Updates_index[l] - 1]; if (std::fabs(den) < threshold()) { -#ifdef DEBUG1 - std::cerr << "Breakdown condition triggered at " << Updates_index[l] - << std::endl; - std::cerr << "Denominator = " << den << std::endl; -#endif // U_l = U_l / 2 (do the split) for (unsigned int i = 0; i < Dim; i++) { @@ -363,16 +322,14 @@ void sherman_morrison_splitting(double *Slater_inv, unsigned int Dim, unsigned i } } -// Sherman-Morrison-Woodbury kernel 2 -// woodbury_2, sherman_morrison_splitting mixing scheme -void sherman_morrison_woodbury_2(double *Slater_inv, const unsigned int Dim, +// Sherman-Morrison-Woodbury 2x2 kernel +// qmckl_woodbury_2, slagel_splitting mixing scheme +void qmckl_sherman_morrison_woodbury_2(double *Slater_inv, const unsigned int Dim, const unsigned int N_updates, double *Updates, unsigned int *Updates_index) { -#ifdef DEBUG2 - std::cerr << "Called Sherman-Morrison-Woodbury kernel 1 with " << N_updates +#ifdef DEBUG + std::cerr << "Called qmckl_sherman_morrison_woodbury_2 with " << N_updates << " updates" << std::endl; - showMatrix2(Updates_index, 1, N_updates, "Updates_index"); - showMatrix2(Updates, N_updates, Dim, "Updates"); #endif unsigned int n_of_2blocks = N_updates / 2; @@ -390,48 +347,38 @@ void sherman_morrison_woodbury_2(double *Slater_inv, const unsigned int Dim, double *Updates_2block = &Updates[i * length_2block]; unsigned int *Updates_index_2block = &Updates_index[i * 2]; bool ok; - ok = woodbury_2(Slater_inv, Dim, Updates_2block, Updates_index_2block); - if (!ok) { // Send the entire block to sherman_morrison_splitting -#ifdef DEBUG1 - std::cerr << "Woodbury 2x2 kernel failed! Sending block to sherman_morrison_splitting" - << std::endl; -#endif -#ifdef DEBUG2 - showMatrix2(Updates_2block, 2, Dim, "Updates_2block"); - showMatrix2(Updates_index_2block, 1, 2, "Updates_index_2block"); -#endif + ok = qmckl_woodbury_2(Slater_inv, Dim, Updates_2block, Updates_index_2block); + if (!ok) { // Send the entire block to slagel_splitting unsigned int l = 0; - sherman_morrison_splitting(Slater_inv, Dim, 2, Updates_2block, Updates_index_2block, + slagel_splitting(Slater_inv, Dim, 2, Updates_2block, Updates_index_2block, later_updates + (Dim * later), later_index + later, &l); later = later + l; } } } - if (remainder == 1) { // Apply last remaining update with sherman_morrison_splitting + if (remainder == 1) { // Apply last remaining update with slagel_splitting double *Updates_1block = &Updates[n_of_2blocks * length_2block]; unsigned int *Updates_index_1block = &Updates_index[2 * n_of_2blocks]; unsigned int l = 0; - sherman_morrison_splitting(Slater_inv, Dim, 1, Updates_1block, Updates_index_1block, + slagel_splitting(Slater_inv, Dim, 1, Updates_1block, Updates_index_1block, later_updates + (Dim * later), later_index + later, &l); later = later + l; } if (later > 0) { - sherman_morrison_splitting_caller(Slater_inv, Dim, later, later_updates, later_index); + qmckl_sherman_morrison_splitting(Slater_inv, Dim, later, later_updates, later_index); } } -// Sherman-Morrison-Woodbury kernel 3 -// woodbury_2, woodbury_3, sherman_morrison_splitting mixing scheme -void sherman_morrison_woodbury_3(double *Slater_inv, const unsigned int Dim, +// Sherman-Morrison-Woodbury 3x3 kernel +// qmckl_woodbury_2, qmckl_woodbury_3, slagel_splitting mixing scheme +void qmckl_sherman_morrison_woodbury_3(double *Slater_inv, const unsigned int Dim, const unsigned int N_updates, double *Updates, unsigned int *Updates_index) { -#ifdef DEBUG2 - std::cerr << "Called Sherman-Morrison-Woodbury kernel 1 with " << N_updates +#ifdef DEBUG + std::cerr << "Called qmckl_sherman_morrison_woodbury_3 with " << N_updates << " updates" << std::endl; - showMatrix2(Updates_index, 1, N_updates, "Updates_index"); - showMatrix2(Updates, N_updates, Dim, "Updates"); #endif unsigned int n_of_3blocks = N_updates / 3; @@ -450,16 +397,10 @@ void sherman_morrison_woodbury_3(double *Slater_inv, const unsigned int Dim, double *Updates_3block = &Updates[i * length_3block]; unsigned int *Updates_index_3block = &Updates_index[i * 3]; bool ok; - ok = woodbury_3(Slater_inv, Dim, Updates_3block, Updates_index_3block); - if (!ok) { // Send the entire block to sherman_morrison_splitting -#ifdef DEBUG2 - std::cerr << "Woodbury 3x3 kernel failed! Sending block to sherman_morrison_splitting" - << std::endl; - showMatrix2(Updates_3block, 3, Dim, "Updates_3block"); - showMatrix2(Updates_index_3block, 1, 3, "Updates_index_3block"); -#endif + ok = qmckl_woodbury_3(Slater_inv, Dim, Updates_3block, Updates_index_3block); + if (!ok) { // Send the entire block to slagel_splitting unsigned int l = 0; - sherman_morrison_splitting(Slater_inv, Dim, 3, Updates_3block, Updates_index_3block, + slagel_splitting(Slater_inv, Dim, 3, Updates_3block, Updates_index_3block, later_updates + (Dim * later), later_index + later, &l); later = later + l; } @@ -470,66 +411,24 @@ void sherman_morrison_woodbury_3(double *Slater_inv, const unsigned int Dim, double *Updates_2block = &Updates[n_of_3blocks * length_3block]; unsigned int *Updates_index_2block = &Updates_index[3 * n_of_3blocks]; bool ok; - ok = woodbury_2(Slater_inv, Dim, Updates_2block, Updates_index_2block); - if (!ok) { // Send the entire block to sherman_morrison_splitting -#ifdef DEBUG2 - std::cerr << "Woodbury 2x2 kernel failed! Sending block to sherman_morrison_splitting" - << std::endl; -#endif + ok = qmckl_woodbury_2(Slater_inv, Dim, Updates_2block, Updates_index_2block); + if (!ok) { // Send the entire block to slagel_splitting unsigned int l = 0; - sherman_morrison_splitting(Slater_inv, Dim, 2, Updates_2block, Updates_index_2block, + slagel_splitting(Slater_inv, Dim, 2, Updates_2block, Updates_index_2block, later_updates + (Dim * later), later_index + later, &l); later = later + l; } } - else if (remainder == 1) { // Apply last remaining update with sherman_morrison_splitting + else if (remainder == 1) { // Apply last remaining update with slagel_splitting double *Updates_1block = &Updates[n_of_3blocks * length_3block]; unsigned int *Updates_index_1block = &Updates_index[3 * n_of_3blocks]; unsigned int l = 0; - sherman_morrison_splitting(Slater_inv, Dim, 1, Updates_1block, Updates_index_1block, + slagel_splitting(Slater_inv, Dim, 1, Updates_1block, Updates_index_1block, later_updates + (Dim * later), later_index + later, &l); later = later + l; } if (later > 0) { - sherman_morrison_splitting_caller(Slater_inv, Dim, later, later_updates, later_index); - } -} - - - -extern "C" { - void sherman_morrison_f(double **linSlater_inv, unsigned int *Dim, unsigned int *N_updates, - double **linUpdates, unsigned int **Updates_index) { - sherman_morrison(*linSlater_inv, *Dim, *N_updates, *linUpdates, *Updates_index); - } - - bool woodbury_2_f(double **linSlater_inv, unsigned int *Dim, double **linUpdates, - unsigned int **Updates_index) { - bool ok; - ok = woodbury_2(*linSlater_inv, *Dim, *linUpdates, *Updates_index); - return ok; - } - - bool woodbury_3_f(double **linSlater_inv, unsigned int *Dim, double **linUpdates, - unsigned int **Updates_index) { - bool ok; - ok = woodbury_3(*linSlater_inv, *Dim, *linUpdates, *Updates_index); - return ok; - } - - void sherman_morrison_splitting_caller_f(double **linSlater_inv, unsigned int *Dim, unsigned int *N_updates, - double **linUpdates, unsigned int **Updates_index) { - sherman_morrison_splitting_caller(*linSlater_inv, *Dim, *N_updates, *linUpdates, *Updates_index); - } - - void sherman_morrison_woodbury_3_f(double **linSlater_inv, unsigned int *Dim, unsigned int *N_updates, - double **linUpdates, unsigned int **Updates_index) { - sherman_morrison_woodbury_3(*linSlater_inv, *Dim, *N_updates, *linUpdates, *Updates_index); - } - - void sherman_morrison_woodbury_2_f(double **linSlater_inv, unsigned int *Dim, unsigned int *N_updates, - double **linUpdates, unsigned int **Updates_index) { - sherman_morrison_woodbury_2(*linSlater_inv, *Dim, *N_updates, *linUpdates, *Updates_index); + qmckl_sherman_morrison_splitting(Slater_inv, Dim, later, later_updates, later_index); } } From 7849f510f43999b35b0a3e1fa24d22557ffbd137 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Mon, 19 Jul 2021 17:38:53 +0200 Subject: [PATCH 09/50] Started integration of naive Sherman-Morrison in the org-mode file. #25 --- org/qmckl_sherman_morrison_woodbury.org | 88 +++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 6 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index fba8faa..17ca931 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -2,7 +2,8 @@ #+SETUPFILE: ../tools/theme.setup #+INCLUDE: ../tools/lib.org -[TODO: FMJC] Please add some intro. +Low- and high-level functions that use the Sherman-Morrison and Woodbury matrix inversion formulas to update the + inverse of a non-singualr matrix * Headers #+begin_src elisp :noexport :results none @@ -15,15 +16,18 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif +#include +#ifndef THRESHOLD +#define THRESHOLD 1e-3 +#endif + int main() { qmckl_context context; context = qmckl_context_create(); #+end_src -* Sherman Morrison - -[TODO: FMJC] Add general doc for Naive SM. +* Naïve Sherman-Morrison ** ~qmckl_sherman_morrison~ :PROPERTIES: @@ -32,20 +36,92 @@ int main() { :FRetType: qmckl_exit_code :END: -[TODO: FMJC] Add some detailed description. Including formulae etc. + The Sherman-Morrison formula + \begin{align} + S_k^{-1} &= (S_l + U_k)^-1 \\ + &= S_l^{-1} - \frac{S_l^{-1}U_kS_l}{1+\underline{v}_k^tS_l^{-1}\underline{u}_k} + \end{align} + #+NAME: qmckl_sherman_morrison_args | qmckl_context | context | in | Global state | + | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | + | uint | Dim | in | Leading dimension of Slater_inv | + | uint | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | + | double | Updates[N_updates*Dim] | in | Array containing the updates | + | double | Updates_index | in | Array containing the rank-1 updates | *** Requirements -[TODO: FMJC] Add description of the input variables. (see for e.g. qmckl_distance.org) + Add description of the input variables. (see for e.g. qmckl_distance.org) *** C header #+CALL: generate_c_header(table=qmckl_sherman_morrison_args,rettyp=get_value("CRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src c :tangle (eval h_func) :comments org + qmckl_exit_code qmckl_sherman_morrison ( + const qmckl_context context, + double *Slater_inv, + unsigned int Dim, + unsigned int N_updates, + double *Updates, + unsigned int *Updates_index ); + #+end_src + *** Source + + #+begin_src c :tangle (eval c_func) :comments org +bool qmckl_sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N_updates, + double *Updates, unsigned int *Updates_index) { +#ifdef DEBUG + std::cerr << "Called qmckl_sherman_morrison with " << N_updates << " updates" << std::endl; +#endif + + double C[Dim]; + double D[Dim]; + + unsigned int l = 0; + // For each update + while (l < N_updates) { + // C = A^{-1} x U_l + for (unsigned int i = 0; i < Dim; i++) { + C[i] = 0; + for (unsigned int j = 0; j < Dim; j++) { + C[i] += Slater_inv[i * Dim + j] * Updates[l * Dim + j]; + } + } + + // Denominator + double den = 1 + C[Updates_index[l] - 1]; + if (std::fabs(den) < threshold()) { + return false; + } + double iden = 1 / den; + + // D = v^T x A^{-1} + for (unsigned int j = 0; j < Dim; j++) { + D[j] = Slater_inv[(Updates_index[l] - 1) * Dim + j]; + } + + // A^{-1} = A^{-1} - C x D / den + for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + double update = C[i] * D[j] * iden; + Slater_inv[i * Dim + j] -= update; + } + } + + l += 1; + } + return true; +} + + #+end_src + + + *** Performance ** C interface :noexport: From dce8cad154d64a32ba39c82bf803b33c3eb5dd8a Mon Sep 17 00:00:00 2001 From: vijay gopal chilkuri Date: Mon, 19 Jul 2021 18:24:19 +0200 Subject: [PATCH 10/50] Modified autogen functions to incorporate unsigned. #25 --- tools/lib.org | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/lib.org b/tools/lib.org index d8e642a..5cb1802 100644 --- a/tools/lib.org +++ b/tools/lib.org @@ -42,6 +42,8 @@ f_of_c_d = { '' : '' , 'qmckl_exit_code' : 'integer (c_int32_t)' , 'int32_t' : 'integer (c_int32_t)' , 'int64_t' : 'integer (c_int64_t)' + , 'uint32_t' : 'integer (c_int32_t)' + , 'uint64_t' : 'integer (c_int64_t)' , 'float' : 'real (c_float )' , 'double' : 'real (c_double )' , 'char' : 'character' @@ -55,6 +57,8 @@ ctypeid_d = { '' : '' , 'qmckl_exit_code' : 'integer(c_int32_t)' , 'integer' : 'integer(c_int32_t)' , 'integer*8' : 'integer(c_int64_t)' + , 'integer' : 'integer(c_uint32_t)' + , 'integer*8' : 'integer(c_uint64_t)' , 'real' : 'real(c_float)' , 'real*8' : 'real(c_double)' , 'character' : 'character(c_char)' From 6e047046f4f15f4e66e285440abc5a7adad2c0ea Mon Sep 17 00:00:00 2001 From: vijay gopal chilkuri Date: Mon, 19 Jul 2021 18:25:10 +0200 Subject: [PATCH 11/50] Get the sherman morrison to compile. Tests still dont compile. #25 --- org/qmckl_sherman_morrison_woodbury.org | 126 ++++++++++++++++++++---- 1 file changed, 106 insertions(+), 20 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 17ca931..255c0f4 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -21,6 +21,8 @@ Low- and high-level functions that use the Sherman-Morrison and Woodbury matrix #define THRESHOLD 1e-3 #endif +#include "qmckl.h" + int main() { qmckl_context context; context = qmckl_context_create(); @@ -28,7 +30,7 @@ int main() { #+end_src * Naïve Sherman-Morrison - + ** ~qmckl_sherman_morrison~ :PROPERTIES: :Name: qmckl_sherman_morrison @@ -37,6 +39,7 @@ int main() { :END: The Sherman-Morrison formula + \begin{align} S_k^{-1} &= (S_l + U_k)^-1 \\ &= S_l^{-1} - \frac{S_l^{-1}U_kS_l}{1+\underline{v}_k^tS_l^{-1}\underline{u}_k} @@ -44,12 +47,12 @@ int main() { #+NAME: qmckl_sherman_morrison_args - | qmckl_context | context | in | Global state | - | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | - | uint | Dim | in | Leading dimension of Slater_inv | - | uint | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | - | double | Updates[N_updates*Dim] | in | Array containing the updates | - | double | Updates_index | in | Array containing the rank-1 updates | + | qmckl_context | context | in | Global state | + | uint64_t | Dim | in | Leading dimension of Slater_inv | + | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | + | double | Updates[N_updates*Dim] | in | Array containing the updates | + | uint64_t | Updates_index[N_updates] | in | Array containing the rank-1 updates | + | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | *** Requirements @@ -61,20 +64,59 @@ int main() { #+RESULTS: #+begin_src c :tangle (eval h_func) :comments org - qmckl_exit_code qmckl_sherman_morrison ( - const qmckl_context context, - double *Slater_inv, - unsigned int Dim, - unsigned int N_updates, - double *Updates, - unsigned int *Updates_index ); +// Sherman-Morrison-Woodbury break-down threshold +#ifndef THRESHOLD +#define THRESHOLD 1e-3 +#endif +static double threshold(); + + qmckl_exit_code qmckl_sherman_morrison_c ( + const qmckl_context context, + const uint64_t Dim, + const uint64_t N_updates, + const double* Updates, + const uint64_t* Updates_index, + double* Slater_inv ); #+end_src -*** Source +*** Source Fortran - #+begin_src c :tangle (eval c_func) :comments org -bool qmckl_sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N_updates, - double *Updates, unsigned int *Updates_index) { + #+begin_src f90 :tangle (eval f) +integer function qmckl_sherman_morrison_f(context, Slater_inv, Dim, N_updates, & + Updates, Updates_index) result(info) + use qmckl + implicit none + integer(qmckl_context) , intent(in) :: context + integer*8 , intent(in) :: Dim, N_updates + integer*8 , intent(in) :: Updates_index(N_updates) + real*8 , intent(in) :: Updates(N_updates*Dim) + real*8 , intent(inout) :: Slater_inv(Dim*Dim) + !logical, external :: qmckl_sherman_morrison_f + info = qmckl_sherman_morrison(context, Dim, N_updates, Updates, Updates_index, Slater_inv) +end function qmckl_sherman_morrison_f + #+end_src + +*** Source C + + #+begin_src c :tangle (eval c) :comments org +#include +#include "qmckl.h" + +// Sherman-Morrison-Woodbury break-down threshold +static double threshold() { + const double threshold = THRESHOLD; +#ifdef DEBUG + std::cerr << "Break-down threshold set to: " << threshold << std::endl; +#endif + return threshold; +} + +qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, + const uint64_t Dim, + const uint64_t N_updates, + const double* Updates, + const uint64_t* Updates_index, + double * Slater_inv) { #ifdef DEBUG std::cerr << "Called qmckl_sherman_morrison with " << N_updates << " updates" << std::endl; #endif @@ -95,7 +137,7 @@ bool qmckl_sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N // Denominator double den = 1 + C[Updates_index[l] - 1]; - if (std::fabs(den) < threshold()) { + if (fabs(den) < threshold()) { return false; } double iden = 1 / den; @@ -115,7 +157,7 @@ bool qmckl_sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N l += 1; } - return true; + return QMCKL_SUCCESS; } #+end_src @@ -128,8 +170,52 @@ bool qmckl_sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N #+CALL: generate_c_interface(table=qmckl_sherman_morrison_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src f90 :tangle (eval f) :comments org :exports none + integer(c_int32_t) function qmckl_sherman_morrison & + (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & + bind(C) result(info) + + use, intrinsic :: iso_c_binding + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) , value :: Dim + integer (c_int64_t) , intent(in) , value :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + integer(c_int32_t), external :: qmckl_sherman_morrison_c + info = qmckl_sherman_morrison_c & + (context, Dim, N_updates, Updates, Updates_index, Slater_inv) + + end function qmckl_sherman_morrison + #+end_src + #+CALL: generate_f_interface(table=qmckl_sherman_morrison_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src f90 :tangle (eval fh_func) :comments org :exports none + interface + integer(c_int32_t) function qmckl_sherman_morrison & + (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & + bind(C) + use, intrinsic :: iso_c_binding + import + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) , value :: Dim + integer (c_int64_t) , intent(in) , value :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + end function qmckl_sherman_morrison + end interface + #+end_src + *** Test :noexport: [TODO: FMJC] Write tests for the Sherman-Morrison part. From dcb4816941d494df9e55345b662315521d8a73e0 Mon Sep 17 00:00:00 2001 From: vijay gopal chilkuri Date: Tue, 20 Jul 2021 10:51:21 +0200 Subject: [PATCH 12/50] Added threshold function. Tests still dont compile. #25 --- org/qmckl_sherman_morrison_woodbury.org | 134 +++++++++++++++++++++--- 1 file changed, 118 insertions(+), 16 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 255c0f4..a78002f 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -28,6 +28,120 @@ int main() { context = qmckl_context_create(); #+end_src + +* Sherman-Morrison Helper Functions + +[TODO: FMJC] Add doc + +** ~qmckl_sherman_morrison_threshold~ + :PROPERTIES: + :Name: qmckl_sherman_morrison_threshold + :CRetType: double + :FRetType: double precision + :END: + +[TODO: FMJC] Add doc + + #+NAME: qmckl_sherman_morrison_threshold_args + | double | thresh | out | Threshold | + +*** Requirements + + Add description of the input variables. (see for e.g. qmckl_distance.org) + +*** C header + + #+CALL: generate_c_header(table=qmckl_sherman_morrison_threshold_args,rettyp=get_value("CRetType"),fname=get_value("Name")) + + #+RESULTS: + #+begin_src c :tangle (eval h_func) :comments org +// Sherman-Morrison-Woodbury break-down threshold +#ifndef THRESHOLD +#define THRESHOLD 1e-3 +#endif + + qmckl_exit_code qmckl_sherman_morrison_threshold ( + double* const thresh ); + #+end_src + + +*** Source Fortran + + #+begin_src f90 :tangle (eval f) +integer function qmckl_sherman_morrison_threshold_f(thresh) result(info) + use qmckl + implicit none + real*8 , intent(inout) :: thresh + !logical, external :: qmckl_sherman_morrison_f + info = qmckl_sherman_morrison_threshold(thresh) +end function qmckl_sherman_morrison_threshold_f + #+end_src + +*** Source C + + #+begin_src c :tangle (eval c) :comments org +#include +#include +#include "qmckl.h" + +// Sherman-Morrison-Woodbury break-down threshold +static double qmckl_shreman_morrison_threshold(double* const threshold) { + *threshold = THRESHOLD; +#ifdef DEBUG + std::cerr << "Break-down threshold set to: " << threshold << std::endl; +#endif +} + #+end_src + + +*** Performance + +** C interface :noexport: + + #+CALL: generate_c_interface(table=qmckl_sherman_morrison_threshold_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + + #+RESULTS: + #+begin_src f90 :tangle (eval f) :comments org :exports none + integer(c_int32_t) function qmckl_sherman_morrison_threshold & + (thresh) & + bind(C) result(info) + + use, intrinsic :: iso_c_binding + implicit none + + real (c_double ) , intent(out) :: thresh + + integer(c_int32_t), external :: qmckl_sherman_morrison_threshold_f + info = qmckl_sherman_morrison_threshold_f & + (thresh) + + end function qmckl_sherman_morrison_threshold + #+end_src + + #+CALL: generate_f_interface(table=qmckl_sherman_morrison_threshold_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + + #+RESULTS: + #+begin_src f90 :tangle (eval fh_func) :comments org :exports none + interface + integer(c_int32_t) function qmckl_sherman_morrison_threshold & + (thresh) & + bind(C) + use, intrinsic :: iso_c_binding + import + implicit none + + real (c_double ) , intent(out) :: thresh + + end function qmckl_sherman_morrison_threshold + end interface + #+end_src + +*** Test :noexport: + +[TODO: FMJC] Write tests for the Sherman-Morrison part. + + + * Naïve Sherman-Morrison @@ -64,12 +178,6 @@ int main() { #+RESULTS: #+begin_src c :tangle (eval h_func) :comments org -// Sherman-Morrison-Woodbury break-down threshold -#ifndef THRESHOLD -#define THRESHOLD 1e-3 -#endif -static double threshold(); - qmckl_exit_code qmckl_sherman_morrison_c ( const qmckl_context context, const uint64_t Dim, @@ -102,15 +210,6 @@ end function qmckl_sherman_morrison_f #include #include "qmckl.h" -// Sherman-Morrison-Woodbury break-down threshold -static double threshold() { - const double threshold = THRESHOLD; -#ifdef DEBUG - std::cerr << "Break-down threshold set to: " << threshold << std::endl; -#endif - return threshold; -} - qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, const uint64_t Dim, const uint64_t N_updates, @@ -124,6 +223,9 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, double C[Dim]; double D[Dim]; + double threshold = 0.0; + qmckl_sherman_morrison_threshold(&threshold); + unsigned int l = 0; // For each update while (l < N_updates) { @@ -137,7 +239,7 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, // Denominator double den = 1 + C[Updates_index[l] - 1]; - if (fabs(den) < threshold()) { + if (fabs(den) < threshold) { return false; } double iden = 1 / den; From 80c9a2291cf08ce9c506bf71d46ca03159f119e2 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Tue, 20 Jul 2021 11:15:33 +0200 Subject: [PATCH 13/50] Replaced with and std::fabs() with fabs() to be C-complient. #25 --- org/qmckl_sherman_morrison_woodbury.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index a78002f..ef21226 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -16,7 +16,7 @@ Low- and high-level functions that use the Sherman-Morrison and Woodbury matrix #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include +#include #ifndef THRESHOLD #define THRESHOLD 1e-3 #endif From f325f4feda9074675729fd1b7b82186ef34116c8 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Tue, 20 Jul 2021 11:40:19 +0200 Subject: [PATCH 14/50] - Replaced with and std::fabs() with fabs(). - Changed return values 'true' and 'false' to `QMCKL_SUCCESS` and `QMCKL_FAILURE`. - Commented out the '#ifdef DEBUG ... #endif' blocks because debug messages are not implemented yet. #25 --- org/qmckl_sherman_morrison_woodbury.cpp | 74 ++++++++++++------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.cpp b/org/qmckl_sherman_morrison_woodbury.cpp index 10a7dde..263dc84 100644 --- a/org/qmckl_sherman_morrison_woodbury.cpp +++ b/org/qmckl_sherman_morrison_woodbury.cpp @@ -1,4 +1,4 @@ -#include +#include // Sherman-Morrison-Woodbury break-down threshold #ifndef THRESHOLD @@ -46,18 +46,18 @@ void qmckl_sherman_morrison_woodbury_3(double *Slater_inv, const unsigned int Di // Sherman-Morrison-Woodbury break-down threshold static double threshold() { const double threshold = THRESHOLD; -#ifdef DEBUG - std::cerr << "Break-down threshold set to: " << threshold << std::endl; -#endif +// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. +// std::cerr << "Break-down threshold set to: " << threshold << std::endl; +// #endif return threshold; } // Naïve Sherman Morrison bool qmckl_sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N_updates, double *Updates, unsigned int *Updates_index) { -#ifdef DEBUG - std::cerr << "Called qmckl_sherman_morrison with " << N_updates << " updates" << std::endl; -#endif +// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. +// std::cerr << "Called qmckl_sherman_morrison with " << N_updates << " updates" << std::endl; +// #endif double C[Dim]; double D[Dim]; @@ -75,8 +75,8 @@ bool qmckl_sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N // Denominator double den = 1 + C[Updates_index[l] - 1]; - if (std::fabs(den) < threshold()) { - return false; + if (fabs(den) < threshold()) { + return QMCKL_FAILURE; } double iden = 1 / den; @@ -95,7 +95,7 @@ bool qmckl_sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N l += 1; } - return true; + return QMCKL_SUCCESS; } // Woodbury 2x2 kernel @@ -106,9 +106,9 @@ bool qmckl_woodbury_2(double *Slater_inv, const unsigned int Dim, double *Update B := 1 + V * C, 2 x 2 D := V * S^{-1}, 2 x dim */ -#ifdef DEBUG - std::cerr << "Called Woodbury 2x2 kernel" << std::endl; -#endif +// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. +// std::cerr << "Called Woodbury 2x2 kernel" << std::endl; +// #endif const unsigned int row1 = (Updates_index[0] - 1); const unsigned int row2 = (Updates_index[1] - 1); @@ -133,8 +133,8 @@ bool qmckl_woodbury_2(double *Slater_inv, const unsigned int Dim, double *Update // Check if determinant of inverted matrix is not zero double det = B0 * B3 - B1 * B2; - if (std::fabs(det) < threshold()) { - return false; + if (fabs(det) < threshold()) { + return QMCKL_FAILURE; } // Compute B^{-1} with explicit formula for 2x2 inversion @@ -161,7 +161,7 @@ bool qmckl_woodbury_2(double *Slater_inv, const unsigned int Dim, double *Update } } - return true; + return QMCKL_SUCCESS; } // Woodbury 3x3 kernel @@ -172,9 +172,9 @@ bool qmckl_woodbury_3(double *Slater_inv, const unsigned int Dim, double *Update B := 1 + V * C, 3 x 3 D := V * S^{-1}, 3 x dim */ -#ifdef DEBUG - std::cerr << "Called Woodbury 3x3 kernel" << std::endl; -#endif +// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. +// std::cerr << "Called Woodbury 3x3 kernel" << std::endl; +// #endif const unsigned int row1 = (Updates_index[0] - 1); const unsigned int row2 = (Updates_index[1] - 1); @@ -208,8 +208,8 @@ bool qmckl_woodbury_3(double *Slater_inv, const unsigned int Dim, double *Update det = B0 * (B4 * B8 - B5 * B7) - B1 * (B3 * B8 - B5 * B6) + B2 * (B3 * B7 - B4 * B6); - if (std::fabs(det) < threshold()) { - return false; + if (fabs(det) < threshold()) { + return QMCKL_FAILURE; } // Compute B^{-1} with explicit formula for 3x3 inversion @@ -243,16 +243,16 @@ bool qmckl_woodbury_3(double *Slater_inv, const unsigned int Dim, double *Update } } - return true; + return QMCKL_SUCCESS; } // Sherman Morrison, with J. Slagel splitting (caller function) // http://hdl.handle.net/10919/52966 void qmckl_sherman_morrison_splitting(double *Slater_inv, unsigned int Dim, unsigned int N_updates, double *Updates, unsigned int *Updates_index) { -#ifdef DEBUG - std::cerr << "Called qmckl_sherman_morrison_splitting with " << N_updates << " updates" << std::endl; -#endif +// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. +// std::cerr << "Called qmckl_sherman_morrison_splitting with " << N_updates << " updates" << std::endl; +// #endif double later_updates[Dim * N_updates]; unsigned int later_index[N_updates]; @@ -272,9 +272,9 @@ static void slagel_splitting(double *Slater_inv, unsigned int Dim, unsigned int double *Updates, unsigned int *Updates_index, double *later_updates, unsigned int *later_index, unsigned int *later) { -#ifdef DEBUG - std::cerr << "Called slagel_splitting with " << N_updates << " updates" << std::endl; -#endif +// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. +// std::cerr << "Called slagel_splitting with " << N_updates << " updates" << std::endl; +// #endif double C[Dim]; double D[Dim]; @@ -292,7 +292,7 @@ static void slagel_splitting(double *Slater_inv, unsigned int Dim, unsigned int // Denominator double den = 1 + C[Updates_index[l] - 1]; - if (std::fabs(den) < threshold()) { + if (fabs(den) < threshold()) { // U_l = U_l / 2 (do the split) for (unsigned int i = 0; i < Dim; i++) { @@ -327,10 +327,10 @@ static void slagel_splitting(double *Slater_inv, unsigned int Dim, unsigned int void qmckl_sherman_morrison_woodbury_2(double *Slater_inv, const unsigned int Dim, const unsigned int N_updates, double *Updates, unsigned int *Updates_index) { -#ifdef DEBUG - std::cerr << "Called qmckl_sherman_morrison_woodbury_2 with " << N_updates - << " updates" << std::endl; -#endif +// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. +// std::cerr << "Called qmckl_sherman_morrison_woodbury_2 with " << N_updates +// << " updates" << std::endl; +// #endif unsigned int n_of_2blocks = N_updates / 2; unsigned int remainder = N_updates % 2; @@ -376,10 +376,10 @@ void qmckl_sherman_morrison_woodbury_2(double *Slater_inv, const unsigned int Di void qmckl_sherman_morrison_woodbury_3(double *Slater_inv, const unsigned int Dim, const unsigned int N_updates, double *Updates, unsigned int *Updates_index) { -#ifdef DEBUG - std::cerr << "Called qmckl_sherman_morrison_woodbury_3 with " << N_updates - << " updates" << std::endl; -#endif +// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. +// std::cerr << "Called qmckl_sherman_morrison_woodbury_3 with " << N_updates +// << " updates" << std::endl; +// #endif unsigned int n_of_3blocks = N_updates / 3; unsigned int remainder = N_updates % 3; From 7b2a8caeabadb7724b9d7c8b0498e7ea71b7b992 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Tue, 20 Jul 2021 12:09:43 +0200 Subject: [PATCH 15/50] - Added documentation to helper functions - Removed redundant #include qmckl.h - Commented out the #ifdef DEBUG ... #endif blocks - Changed Sherman-Morrison break-down check to use qmckl_exit_code qmckl_sherman_morrison_threshold double* const thresh ). #25 --- org/qmckl_sherman_morrison_woodbury.org | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index ef21226..bebfc70 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -21,8 +21,6 @@ Low- and high-level functions that use the Sherman-Morrison and Woodbury matrix #define THRESHOLD 1e-3 #endif -#include "qmckl.h" - int main() { qmckl_context context; context = qmckl_context_create(); @@ -31,7 +29,7 @@ int main() { * Sherman-Morrison Helper Functions -[TODO: FMJC] Add doc +Helper functions that are used by the Sherman-Morrison-Woodbury kernels. These functions should only be used in the context of these kernels. ** ~qmckl_sherman_morrison_threshold~ :PROPERTIES: @@ -40,7 +38,7 @@ int main() { :FRetType: double precision :END: -[TODO: FMJC] Add doc +This function is used to set the threshold value that is used in the kernels to determine if a matrix is invertable or not. In the Sherman-Morrison kernels this is determined by comparing the denominator in the Sherman-Morrison formula to the value set in threshold. If the value is smaller than the threshold value it means the matrix is not invertable. In the Woodbury kernels the threshold value is compared with the value of the determinant of the update matrix. #+NAME: qmckl_sherman_morrison_threshold_args | double | thresh | out | Threshold | @@ -87,9 +85,9 @@ end function qmckl_sherman_morrison_threshold_f // Sherman-Morrison-Woodbury break-down threshold static double qmckl_shreman_morrison_threshold(double* const threshold) { *threshold = THRESHOLD; -#ifdef DEBUG - std::cerr << "Break-down threshold set to: " << threshold << std::endl; -#endif +// #ifdef DEBUG +// std::cerr << "Break-down threshold set to: " << threshold << std::endl; +// #endif } #+end_src @@ -216,9 +214,9 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, const double* Updates, const uint64_t* Updates_index, double * Slater_inv) { -#ifdef DEBUG - std::cerr << "Called qmckl_sherman_morrison with " << N_updates << " updates" << std::endl; -#endif +// #ifdef DEBUG +// std::cerr << "Called qmckl_sherman_morrison with " << N_updates << " updates" << std::endl; +// #endif double C[Dim]; double D[Dim]; @@ -239,8 +237,10 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, // Denominator double den = 1 + C[Updates_index[l] - 1]; - if (fabs(den) < threshold) { - return false; + double const thresh; + qmckl_sherman_morrison_threshold(&thresh); + if (fabs(den) < thresh) { + return QMCKL_FAILURE; } double iden = 1 / den; From 6b847d6dd3242f7ac6bc4d4edd8a6abdd686e696 Mon Sep 17 00:00:00 2001 From: vijay gopal chilkuri Date: Tue, 20 Jul 2021 16:58:38 +0200 Subject: [PATCH 16/50] Everything comipiles smoothly. Fixed link issue. #25 --- Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.am b/Makefile.am index ca045b9..7ec6322 100644 --- a/Makefile.am +++ b/Makefile.am @@ -58,6 +58,7 @@ fortrandir = $(datadir)/$(PACKAGE_NAME)/fortran/ dist_fortran_DATA = $(qmckl_f) AM_CPPFLAGS = -I$(srcdir)/src -I$(srcdir)/include +AM_FCFLAGS = -fno-underscoring lib_LTLIBRARIES = src/libqmckl.la src_libqmckl_la_SOURCES = $(qmckl_h) $(src_qmckl_f) $(C_FILES) $(F_FILES) $(H_PRIVATE_FUNC_FILES) $(H_PRIVATE_TYPE_FILES) $(header_tests) From 04d2ec2d7098f2ac3f8e1539ab139aa35dfabe45 Mon Sep 17 00:00:00 2001 From: vijay gopal chilkuri Date: Tue, 20 Jul 2021 19:34:51 +0200 Subject: [PATCH 17/50] Added an example usage of qmckl_sherman_morrison function as a test. #25 --- org/qmckl_sherman_morrison_woodbury.org | 30 ++++++++++++++++++------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index bebfc70..e5c221b 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -25,6 +25,7 @@ int main() { qmckl_context context; context = qmckl_context_create(); + qmckl_exit_code rc; #+end_src * Sherman-Morrison Helper Functions @@ -58,7 +59,7 @@ This function is used to set the threshold value that is used in the kernels to #define THRESHOLD 1e-3 #endif - qmckl_exit_code qmckl_sherman_morrison_threshold ( + qmckl_exit_code qmckl_sherman_morrison_threshold_c ( double* const thresh ); #+end_src @@ -83,11 +84,12 @@ end function qmckl_sherman_morrison_threshold_f #include "qmckl.h" // Sherman-Morrison-Woodbury break-down threshold -static double qmckl_shreman_morrison_threshold(double* const threshold) { +qmckl_exit_code qmckl_sherman_morrison_threshold_c(double* const threshold) { *threshold = THRESHOLD; // #ifdef DEBUG // std::cerr << "Break-down threshold set to: " << threshold << std::endl; // #endif +return QMCKL_SUCCESS; } #+end_src @@ -109,8 +111,8 @@ static double qmckl_shreman_morrison_threshold(double* const threshold) { real (c_double ) , intent(out) :: thresh - integer(c_int32_t), external :: qmckl_sherman_morrison_threshold_f - info = qmckl_sherman_morrison_threshold_f & + integer(c_int32_t), external :: qmckl_sherman_morrison_threshold_c + info = qmckl_sherman_morrison_threshold_c & (thresh) end function qmckl_sherman_morrison_threshold @@ -193,7 +195,7 @@ integer function qmckl_sherman_morrison_f(context, Slater_inv, Dim, N_updates, use qmckl implicit none integer(qmckl_context) , intent(in) :: context - integer*8 , intent(in) :: Dim, N_updates + integer*8 , intent(in), value :: Dim, N_updates integer*8 , intent(in) :: Updates_index(N_updates) real*8 , intent(in) :: Updates(N_updates*Dim) real*8 , intent(inout) :: Slater_inv(Dim*Dim) @@ -222,7 +224,7 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, double D[Dim]; double threshold = 0.0; - qmckl_sherman_morrison_threshold(&threshold); + qmckl_exit_code rc = qmckl_sherman_morrison_threshold_c(&threshold); unsigned int l = 0; // For each update @@ -237,8 +239,8 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, // Denominator double den = 1 + C[Updates_index[l] - 1]; - double const thresh; - qmckl_sherman_morrison_threshold(&thresh); + double thresh = 0.0; + qmckl_exit_code rc = qmckl_sherman_morrison_threshold_c(&thresh); if (fabs(den) < thresh) { return QMCKL_FAILURE; } @@ -322,6 +324,18 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, [TODO: FMJC] Write tests for the Sherman-Morrison part. + + #+begin_src c :tangle (eval c_test) +const uint64_t Dim = 2; +const uint64_t N_updates = 2; +const uint64_t Updates_index[2] = {0, 0}; +const double Updates[4] = {0.0, 0.0, 0.0, 0.0}; +double Slater_inv[4] = {0.0, 0.0, 0.0, 0.0}; + +rc = qmckl_sherman_morrison_c(context, Dim, N_updates, Updates, Updates_index, Slater_inv); +assert(rc == QMCKL_SUCCESS); + #+end_src + * End of files #+begin_src c :comments link :tangle (eval c_test) From 11eee81f847c07047629332fd0012d55ae2945e2 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Wed, 21 Jul 2021 17:30:12 +0200 Subject: [PATCH 18/50] - Added Woodbury 2x2 to org-mode file. QMCkl compiles but the testsuite fails with a segementation fault. #25 --- org/qmckl_sherman_morrison_woodbury.org | 211 +++++++++++++++++++++++- 1 file changed, 203 insertions(+), 8 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index e5c221b..f6efc80 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -143,7 +143,7 @@ return QMCKL_SUCCESS; -* Naïve Sherman-Morrison +* Naïve Sherman-Morrison ** ~qmckl_sherman_morrison~ :PROPERTIES: @@ -152,13 +152,7 @@ return QMCKL_SUCCESS; :FRetType: qmckl_exit_code :END: - The Sherman-Morrison formula - - \begin{align} - S_k^{-1} &= (S_l + U_k)^-1 \\ - &= S_l^{-1} - \frac{S_l^{-1}U_kS_l}{1+\underline{v}_k^tS_l^{-1}\underline{u}_k} - \end{align} - + This is the simplest of the available Sherman-Morrison-Woodbury kernels in QMCkl. It applies rank-1 updates one by one in the order that is given. It only checks if the denominator in the Sherman-Morrison formula is not too close to zero (and exit with an error if it does) during the application of an update. #+NAME: qmckl_sherman_morrison_args | qmckl_context | context | in | Global state | @@ -336,6 +330,207 @@ rc = qmckl_sherman_morrison_c(context, Dim, N_updates, Updates, Updates_index, S assert(rc == QMCKL_SUCCESS); #+end_src + +* Woodbury 2x2 + +** ~qmckl_woodbury_2~ + :PROPERTIES: + :Name: qmckl_woodbury_2 + :CRetType: qmckl_exit_code + :FRetType: qmckl_exit_code + :END: + + This is the simplest of the available Sherman-Morrison-Woodbury kernels in QMCkl. It applies rank-1 updates one by one in the order that is given. It only checks if the denominator in the Sherman-Morrison formula is not too close to zero (and exit with an error if it does) during the application of an update. + + #+NAME: qmckl_woodbury_2_args + | qmckl_context | context | in | Global state | + | uint64_t | Dim | in | Leading dimension of Slater_inv | + | double | Updates[2*Dim] | in | Array containing the updates | + | uint64_t | Updates_index[2] | in | Array containing the rank-1 updates | + | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | + +*** Requirements + + Add description of the input variables. (see for e.g. qmckl_distance.org) + +*** C header + + #+CALL: generate_c_header(table=qmckl_woodbury_2_args,rettyp=get_value("CRetType"),fname=get_value("Name")) + + #+RESULTS: + #+begin_src c :tangle (eval h_func) :comments org + qmckl_exit_code qmckl_woodbury_2_c ( + const qmckl_context context, + const uint64_t Dim, + const double* Updates, + const uint64_t* Updates_index, + double* Slater_inv ); + #+end_src + +*** Source Fortran + + #+begin_src f90 :tangle (eval f) +integer function qmckl_woodbury_2_f(context, Slater_inv, Dim, & + Updates, Updates_index) result(info) + use qmckl + implicit none + integer(qmckl_context) , intent(in) :: context + integer*8 , intent(in), value :: Dim + integer*8 , intent(in) :: Updates_index(2) + real*8 , intent(in) :: Updates(2*Dim) + real*8 , intent(inout) :: Slater_inv(Dim*Dim) + !logical, external :: qmckl_woodbury_2_f + info = qmckl_woodbury_2(context, Dim, Updates, Updates_index, Slater_inv) +end function qmckl_woodbury_2_f + #+end_src + +*** Source C + + #+begin_src c :tangle (eval c) :comments org +#include +#include "qmckl.h" + +qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, + const uint64_t Dim, + const double* Updates, + const uint64_t* Updates_index, + double * Slater_inv) { +/* + C := S^{-1} * U, dim x 2 + B := 1 + V * C, 2 x 2 + D := V * S^{-1}, 2 x dim +*/ +// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. +// std::cerr << "Called Woodbury 2x2 kernel" << std::endl; +// #endif + + const unsigned int row1 = (Updates_index[0] - 1); + const unsigned int row2 = (Updates_index[1] - 1); + + // Compute C = S_inv * U !! NON-STANDARD MATRIX MULTIPLICATION BECAUSE + // OF LAYOUT OF 'Updates' !! + double C[2 * Dim]; + for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < 2; j++) { + C[i * 2 + j] = 0; + for (unsigned int k = 0; k < Dim; k++) { + C[i * 2 + j] += Slater_inv[i * Dim + k] * Updates[Dim * j + k]; + } + } + } + + // Compute B = 1 + V * C + const double B0 = C[row1 * 2] + 1; + const double B1 = C[row1 * 2 + 1]; + const double B2 = C[row2 * 2]; + const double B3 = C[row2 * 2 + 1] + 1; + + // Check if determinant of inverted matrix is not zero + double det = B0 * B3 - B1 * B2; + double thresh = 0.0; + qmckl_exit_code rc = qmckl_sherman_morrison_threshold_c(&thresh); + if (fabs(det) < thresh) { + return QMCKL_FAILURE; + } + + // Compute B^{-1} with explicit formula for 2x2 inversion + double Binv[4], idet = 1.0 / det; + Binv[0] = idet * B3; + Binv[1] = -1.0 * idet * B1; + Binv[2] = -1.0 * idet * B2; + Binv[3] = idet * B0; + + // Compute tmp = B^{-1} x (V.S^{-1}) + double tmp[2 * Dim]; + for (unsigned int i = 0; i < 2; i++) { + for (unsigned int j = 0; j < Dim; j++) { + tmp[i * Dim + j] = Binv[i * 2] * Slater_inv[row1 * Dim + j]; + tmp[i * Dim + j] += Binv[i * 2 + 1] * Slater_inv[row2 * Dim + j]; + } + } + + // Compute (S + U V)^{-1} = S^{-1} - C x tmp + for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + Slater_inv[i * Dim + j] -= C[i * 2] * tmp[j]; + Slater_inv[i * Dim + j] -= C[i * 2 + 1] * tmp[Dim + j]; + } + } + + return QMCKL_SUCCESS; +} + + #+end_src + + + +*** Performance + +** C interface :noexport: + + #+CALL: generate_c_interface(table=qmckl_woodbury_2_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + + #+RESULTS: + #+begin_src f90 :tangle (eval f) :comments org :exports none + integer(c_int32_t) function qmckl_woodbury_2 & + (context, Dim, Updates, Updates_index, Slater_inv) & + bind(C) result(info) + + use, intrinsic :: iso_c_binding + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) , value :: Dim + real (c_double ) , intent(in) :: Updates(2*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(2) + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + integer(c_int32_t), external :: qmckl_woodbury_2_c + info = qmckl_woodbury_2_c & + (context, Dim, Updates, Updates_index, Slater_inv) + + end function qmckl_woodbury_2 + #+end_src + + #+CALL: generate_f_interface(table=qmckl_woodbury_2_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + + #+RESULTS: + #+begin_src f90 :tangle (eval fh_func) :comments org :exports none + interface + integer(c_int32_t) function qmckl_woodbury_2 & + (context, Dim, Updates, Updates_index, Slater_inv) & + bind(C) + use, intrinsic :: iso_c_binding + import + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) , value :: Dim + real (c_double ) , intent(in) :: Updates(2*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(2) + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + end function qmckl_woodbury_2 + end interface + #+end_src + +*** Test :noexport: + +[TODO: FMJC] Write tests for the Sherman-Morrison part. + + + #+begin_src c :tangle (eval c_test) +const uint64_t Dim2 = 2; +const uint64_t Updates_index2[2] = {0, 0}; +const double Updates2[4] = {0.0, 0.0, 0.0, 0.0}; +double Slater_inv2[4] = {0.0, 0.0, 0.0, 0.0}; + +rc = qmckl_woodbury_2_c(context, Dim, Updates, Updates_index, Slater_inv); +assert(rc == QMCKL_SUCCESS); + #+end_src + + + * End of files #+begin_src c :comments link :tangle (eval c_test) From 081e27dd92575c4254a2843f6e57349fce2c603e Mon Sep 17 00:00:00 2001 From: vijay gopal chilkuri Date: Wed, 21 Jul 2021 17:42:48 +0200 Subject: [PATCH 19/50] Bug fix in tests. #25 --- org/qmckl_sherman_morrison_woodbury.org | 34 ++++++++++++++++--------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index f6efc80..565789b 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -326,12 +326,16 @@ const uint64_t Updates_index[2] = {0, 0}; const double Updates[4] = {0.0, 0.0, 0.0, 0.0}; double Slater_inv[4] = {0.0, 0.0, 0.0, 0.0}; +// [TODO : FMJC ] add realistic tests + rc = qmckl_sherman_morrison_c(context, Dim, N_updates, Updates, Updates_index, Slater_inv); assert(rc == QMCKL_SUCCESS); #+end_src * Woodbury 2x2 + +[TODO: FMJC] Add main body intro. ** ~qmckl_woodbury_2~ :PROPERTIES: @@ -340,14 +344,18 @@ assert(rc == QMCKL_SUCCESS); :FRetType: qmckl_exit_code :END: - This is the simplest of the available Sherman-Morrison-Woodbury kernels in QMCkl. It applies rank-1 updates one by one in the order that is given. It only checks if the denominator in the Sherman-Morrison formula is not too close to zero (and exit with an error if it does) during the application of an update. + This is the simplest of the available Sherman-Morrison-Woodbury + kernels in QMCkl. It applies rank-1 updates one by one in the order + that is given. It only checks if the denominator in the + Sherman-Morrison formula is not too close to zero (and exit with an + error if it does) during the application of an update. #+NAME: qmckl_woodbury_2_args - | qmckl_context | context | in | Global state | - | uint64_t | Dim | in | Leading dimension of Slater_inv | - | double | Updates[2*Dim] | in | Array containing the updates | - | uint64_t | Updates_index[2] | in | Array containing the rank-1 updates | - | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | + | qmckl_context | context | in | Global state | + | uint64_t | Dim | in | Leading dimension of Slater_inv | + | double | Updates[2*Dim] | in | Array containing the updates | + | uint64_t | Updates_index[2] | in | Array containing the rank-1 updates | + | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | *** Requirements @@ -463,7 +471,7 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, #+end_src - + *** Performance ** C interface :noexport: @@ -520,12 +528,14 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, #+begin_src c :tangle (eval c_test) -const uint64_t Dim2 = 2; -const uint64_t Updates_index2[2] = {0, 0}; -const double Updates2[4] = {0.0, 0.0, 0.0, 0.0}; -double Slater_inv2[4] = {0.0, 0.0, 0.0, 0.0}; +const uint64_t woodbury_Dim = 2; +const uint64_t woodbury_Updates_index[2] = {1, 1}; +const double woodbury_Updates[4] = {1.0, 1.0, 1.0, 1.0}; +double woodbury_Slater_inv[4] = {1.0, 1.0, 1.0, 1.0}; -rc = qmckl_woodbury_2_c(context, Dim, Updates, Updates_index, Slater_inv); +// [TODO : FMJC ] add realistic tests + +rc = qmckl_woodbury_2_c(context, woodbury_Dim, woodbury_Updates, woodbury_Updates_index, woodbury_Slater_inv); assert(rc == QMCKL_SUCCESS); #+end_src From 83dbab7f6bce8f5f4cccb41a2f5b020ed8c14f71 Mon Sep 17 00:00:00 2001 From: vijay gopal chilkuri Date: Wed, 21 Jul 2021 17:56:04 +0200 Subject: [PATCH 20/50] Try not to export org-mode lisp stuff. #25 --- org/qmckl_sherman_morrison_woodbury.org | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 565789b..000f06a 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -2,11 +2,12 @@ #+SETUPFILE: ../tools/theme.setup #+INCLUDE: ../tools/lib.org -Low- and high-level functions that use the Sherman-Morrison and Woodbury matrix inversion formulas to update the - inverse of a non-singualr matrix +Low- and high-level functions that use the Sherman-Morrison and + Woodbury matrix inversion formulas to update the inverse of a + non-singualr matrix * Headers - #+begin_src elisp :noexport :results none + #+begin_src elisp :noexport :results none :exports none (org-babel-lob-ingest "../tools/lib.org") #+end_src @@ -30,7 +31,9 @@ int main() { * Sherman-Morrison Helper Functions -Helper functions that are used by the Sherman-Morrison-Woodbury kernels. These functions should only be used in the context of these kernels. +Helper functions that are used by the Sherman-Morrison-Woodbury +kernels. These functions should only be used in the context of these +kernels. ** ~qmckl_sherman_morrison_threshold~ :PROPERTIES: From fdb8f5d50a47537b85fda5f64cc35fcd10683bd9 Mon Sep 17 00:00:00 2001 From: vijay gopal chilkuri Date: Thu, 22 Jul 2021 09:59:02 +0200 Subject: [PATCH 21/50] changed unsigned int to uint64_t for consistency. #25 --- org/qmckl_sherman_morrison_woodbury.org | 30 ++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 000f06a..d562897 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -223,13 +223,13 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, double threshold = 0.0; qmckl_exit_code rc = qmckl_sherman_morrison_threshold_c(&threshold); - unsigned int l = 0; + uint64_t l = 0; // For each update while (l < N_updates) { // C = A^{-1} x U_l - for (unsigned int i = 0; i < Dim; i++) { + for (uint64_t i = 0; i < Dim; i++) { C[i] = 0; - for (unsigned int j = 0; j < Dim; j++) { + for (uint64_t j = 0; j < Dim; j++) { C[i] += Slater_inv[i * Dim + j] * Updates[l * Dim + j]; } } @@ -244,13 +244,13 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, double iden = 1 / den; // D = v^T x A^{-1} - for (unsigned int j = 0; j < Dim; j++) { + for (uint64_t j = 0; j < Dim; j++) { D[j] = Slater_inv[(Updates_index[l] - 1) * Dim + j]; } // A^{-1} = A^{-1} - C x D / den - for (unsigned int i = 0; i < Dim; i++) { - for (unsigned int j = 0; j < Dim; j++) { + for (uint64_t i = 0; i < Dim; i++) { + for (uint64_t j = 0; j < Dim; j++) { double update = C[i] * D[j] * iden; Slater_inv[i * Dim + j] -= update; } @@ -415,16 +415,16 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, // std::cerr << "Called Woodbury 2x2 kernel" << std::endl; // #endif - const unsigned int row1 = (Updates_index[0] - 1); - const unsigned int row2 = (Updates_index[1] - 1); + const uint64_t row1 = (Updates_index[0] - 1); + const uint64_t row2 = (Updates_index[1] - 1); // Compute C = S_inv * U !! NON-STANDARD MATRIX MULTIPLICATION BECAUSE // OF LAYOUT OF 'Updates' !! double C[2 * Dim]; - for (unsigned int i = 0; i < Dim; i++) { - for (unsigned int j = 0; j < 2; j++) { + for (uint64_t i = 0; i < Dim; i++) { + for (uint64_t j = 0; j < 2; j++) { C[i * 2 + j] = 0; - for (unsigned int k = 0; k < Dim; k++) { + for (uint64_t k = 0; k < Dim; k++) { C[i * 2 + j] += Slater_inv[i * Dim + k] * Updates[Dim * j + k]; } } @@ -453,16 +453,16 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, // Compute tmp = B^{-1} x (V.S^{-1}) double tmp[2 * Dim]; - for (unsigned int i = 0; i < 2; i++) { - for (unsigned int j = 0; j < Dim; j++) { + for (uint64_t i = 0; i < 2; i++) { + for (uint64_t j = 0; j < Dim; j++) { tmp[i * Dim + j] = Binv[i * 2] * Slater_inv[row1 * Dim + j]; tmp[i * Dim + j] += Binv[i * 2 + 1] * Slater_inv[row2 * Dim + j]; } } // Compute (S + U V)^{-1} = S^{-1} - C x tmp - for (unsigned int i = 0; i < Dim; i++) { - for (unsigned int j = 0; j < Dim; j++) { + for (uint64_t i = 0; i < Dim; i++) { + for (uint64_t j = 0; j < Dim; j++) { Slater_inv[i * Dim + j] -= C[i * 2] * tmp[j]; Slater_inv[i * Dim + j] -= C[i * 2 + 1] * tmp[Dim + j]; } From c6d00d5c5b6d55a3a4c19c40ea56e146d488c911 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Thu, 22 Jul 2021 11:38:50 +0200 Subject: [PATCH 22/50] Added and tested Woodbury 3x3 kernel to QMCkl. Residual = wb3 14 9.92936e-07 1.90518e-11 ok -- cycle 14 Residual = qmckl_wb3 14 9.92936e-07 1.90518e-11 ok -- cycle 14. #25 --- org/qmckl_sherman_morrison_woodbury.cpp | 190 +++++++++---------- org/qmckl_sherman_morrison_woodbury.org | 237 +++++++++++++++++++++++- 2 files changed, 323 insertions(+), 104 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.cpp b/org/qmckl_sherman_morrison_woodbury.cpp index 263dc84..53080ee 100644 --- a/org/qmckl_sherman_morrison_woodbury.cpp +++ b/org/qmckl_sherman_morrison_woodbury.cpp @@ -7,39 +7,39 @@ static double threshold(); // Naïve Sherman Morrison -bool qmckl_sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N_updates, - double *Updates, unsigned int *Updates_index); +bool qmckl_sherman_morrison(double *Slater_inv, uint64_t Dim, uint64_t N_updates, + double *Updates, uint64_t *Updates_index); // Woodbury 2x2 kernel -bool qmckl_woodbury_2(double *Slater_inv, const unsigned int Dim, double *Updates, - const unsigned int *Updates_index); +bool qmckl_woodbury_2(double *Slater_inv, const uint64_t Dim, double *Updates, + const uint64_t *Updates_index); // Woodbury 3x3 kernel -bool qmckl_woodbury_3(double *Slater_inv, const unsigned int Dim, double *Updates, - const unsigned int *Updates_index); +bool qmckl_woodbury_3(double *Slater_inv, const uint64_t Dim, double *Updates, + const uint64_t *Updates_index); // Sherman Morrison, with J. Slagel splitting (caller function) -void qmckl_sherman_morrison_splitting(double *Slater_inv, unsigned int Dim, unsigned int N_updates, - double *Updates, unsigned int *Updates_index); +void qmckl_sherman_morrison_splitting(double *Slater_inv, uint64_t Dim, uint64_t N_updates, + double *Updates, uint64_t *Updates_index); // Sherman Morrison, with J. Slagel splitting // http://hdl.handle.net/10919/52966 -static void slagel_splitting(double *Slater_inv, unsigned int Dim, unsigned int N_updates, - double *Updates, unsigned int *Updates_index, - double *later_updates, unsigned int *later_index, - unsigned int *later); +static void slagel_splitting(double *Slater_inv, uint64_t Dim, uint64_t N_updates, + double *Updates, uint64_t *Updates_index, + double *later_updates, uint64_t *later_index, + uint64_t *later); // Mixed Sherman-Morrison-Woodbury kernel using // Woodbury 2x2 and Sherman-Morrison with update-splitting -void qmckl_sherman_morrison_woodbury_2(double *Slater_inv, const unsigned int Dim, - const unsigned int N_updates, double *Updates, - unsigned int *Updates_index); +void qmckl_sherman_morrison_woodbury_2(double *Slater_inv, const uint64_t Dim, + const uint64_t N_updates, double *Updates, + uint64_t *Updates_index); // Mixed Sherman-Morrison-Woodbury kernel using // Woodbury 3x3, Woodbury 2x2 and Sherman-Morrison with update-splitting -void qmckl_sherman_morrison_woodbury_3(double *Slater_inv, const unsigned int Dim, - const unsigned int N_updates, double *Updates, - unsigned int *Updates_index); +void qmckl_sherman_morrison_woodbury_3(double *Slater_inv, const uint64_t Dim, + const uint64_t N_updates, double *Updates, + uint64_t *Updates_index); @@ -53,8 +53,8 @@ static double threshold() { } // Naïve Sherman Morrison -bool qmckl_sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N_updates, - double *Updates, unsigned int *Updates_index) { +bool qmckl_sherman_morrison(double *Slater_inv, uint64_t Dim, uint64_t N_updates, + double *Updates, uint64_t *Updates_index) { // #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. // std::cerr << "Called qmckl_sherman_morrison with " << N_updates << " updates" << std::endl; // #endif @@ -62,13 +62,13 @@ bool qmckl_sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N double C[Dim]; double D[Dim]; - unsigned int l = 0; + uint64_t l = 0; // For each update while (l < N_updates) { // C = A^{-1} x U_l - for (unsigned int i = 0; i < Dim; i++) { + for (uint64_t i = 0; i < Dim; i++) { C[i] = 0; - for (unsigned int j = 0; j < Dim; j++) { + for (uint64_t j = 0; j < Dim; j++) { C[i] += Slater_inv[i * Dim + j] * Updates[l * Dim + j]; } } @@ -81,13 +81,13 @@ bool qmckl_sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N double iden = 1 / den; // D = v^T x A^{-1} - for (unsigned int j = 0; j < Dim; j++) { + for (uint64_t j = 0; j < Dim; j++) { D[j] = Slater_inv[(Updates_index[l] - 1) * Dim + j]; } // A^{-1} = A^{-1} - C x D / den - for (unsigned int i = 0; i < Dim; i++) { - for (unsigned int j = 0; j < Dim; j++) { + for (uint64_t i = 0; i < Dim; i++) { + for (uint64_t j = 0; j < Dim; j++) { double update = C[i] * D[j] * iden; Slater_inv[i * Dim + j] -= update; } @@ -99,8 +99,8 @@ bool qmckl_sherman_morrison(double *Slater_inv, unsigned int Dim, unsigned int N } // Woodbury 2x2 kernel -bool qmckl_woodbury_2(double *Slater_inv, const unsigned int Dim, double *Updates, - const unsigned int *Updates_index) { +bool qmckl_woodbury_2(double *Slater_inv, const uint64_t Dim, double *Updates, + const uint64_t *Updates_index) { /* C := S^{-1} * U, dim x 2 B := 1 + V * C, 2 x 2 @@ -110,16 +110,16 @@ bool qmckl_woodbury_2(double *Slater_inv, const unsigned int Dim, double *Update // std::cerr << "Called Woodbury 2x2 kernel" << std::endl; // #endif - const unsigned int row1 = (Updates_index[0] - 1); - const unsigned int row2 = (Updates_index[1] - 1); + const uint64_t row1 = (Updates_index[0] - 1); + const uint64_t row2 = (Updates_index[1] - 1); // Compute C = S_inv * U !! NON-STANDARD MATRIX MULTIPLICATION BECAUSE // OF LAYOUT OF 'Updates' !! double C[2 * Dim]; - for (unsigned int i = 0; i < Dim; i++) { - for (unsigned int j = 0; j < 2; j++) { + for (uint64_t i = 0; i < Dim; i++) { + for (uint64_t j = 0; j < 2; j++) { C[i * 2 + j] = 0; - for (unsigned int k = 0; k < Dim; k++) { + for (uint64_t k = 0; k < Dim; k++) { C[i * 2 + j] += Slater_inv[i * Dim + k] * Updates[Dim * j + k]; } } @@ -146,16 +146,16 @@ bool qmckl_woodbury_2(double *Slater_inv, const unsigned int Dim, double *Update // Compute tmp = B^{-1} x (V.S^{-1}) double tmp[2 * Dim]; - for (unsigned int i = 0; i < 2; i++) { - for (unsigned int j = 0; j < Dim; j++) { + for (uint64_t i = 0; i < 2; i++) { + for (uint64_t j = 0; j < Dim; j++) { tmp[i * Dim + j] = Binv[i * 2] * Slater_inv[row1 * Dim + j]; tmp[i * Dim + j] += Binv[i * 2 + 1] * Slater_inv[row2 * Dim + j]; } } // Compute (S + U V)^{-1} = S^{-1} - C x tmp - for (unsigned int i = 0; i < Dim; i++) { - for (unsigned int j = 0; j < Dim; j++) { + for (uint64_t i = 0; i < Dim; i++) { + for (uint64_t j = 0; j < Dim; j++) { Slater_inv[i * Dim + j] -= C[i * 2] * tmp[j]; Slater_inv[i * Dim + j] -= C[i * 2 + 1] * tmp[Dim + j]; } @@ -165,8 +165,8 @@ bool qmckl_woodbury_2(double *Slater_inv, const unsigned int Dim, double *Update } // Woodbury 3x3 kernel -bool qmckl_woodbury_3(double *Slater_inv, const unsigned int Dim, double *Updates, - const unsigned int *Updates_index) { +bool qmckl_woodbury_3(double *Slater_inv, const uint64_t Dim, double *Updates, + const uint64_t *Updates_index) { /* C := S^{-1} * U, dim x 3 B := 1 + V * C, 3 x 3 @@ -176,17 +176,17 @@ bool qmckl_woodbury_3(double *Slater_inv, const unsigned int Dim, double *Update // std::cerr << "Called Woodbury 3x3 kernel" << std::endl; // #endif - const unsigned int row1 = (Updates_index[0] - 1); - const unsigned int row2 = (Updates_index[1] - 1); - const unsigned int row3 = (Updates_index[2] - 1); + const uint64_t row1 = (Updates_index[0] - 1); + const uint64_t row2 = (Updates_index[1] - 1); + const uint64_t row3 = (Updates_index[2] - 1); // Compute C = S_inv * U !! NON-STANDARD MATRIX MULTIPLICATION BECAUSE // OF LAYOUT OF 'Updates' !! double C[3 * Dim]; - for (unsigned int i = 0; i < Dim; i++) { - for (unsigned int j = 0; j < 3; j++) { + for (uint64_t i = 0; i < Dim; i++) { + for (uint64_t j = 0; j < 3; j++) { C[i * 3 + j] = 0; - for (unsigned int k = 0; k < Dim; k++) { + for (uint64_t k = 0; k < Dim; k++) { C[i * 3 + j] += Slater_inv[i * Dim + k] * Updates[Dim * j + k]; } } @@ -226,8 +226,8 @@ bool qmckl_woodbury_3(double *Slater_inv, const unsigned int Dim, double *Update // Compute tmp = B^{-1} x (V.S^{-1}) double tmp[3 * Dim]; - for (unsigned int i = 0; i < 3; i++) { - for (unsigned int j = 0; j < Dim; j++) { + for (uint64_t i = 0; i < 3; i++) { + for (uint64_t j = 0; j < Dim; j++) { tmp[i * Dim + j] = Binv[i * 3] * Slater_inv[row1 * Dim + j]; tmp[i * Dim + j] += Binv[i * 3 + 1] * Slater_inv[row2 * Dim + j]; tmp[i * Dim + j] += Binv[i * 3 + 2] * Slater_inv[row3 * Dim + j]; @@ -235,8 +235,8 @@ bool qmckl_woodbury_3(double *Slater_inv, const unsigned int Dim, double *Update } // Compute (S + U V)^{-1} = S^{-1} - C x tmp - for (unsigned int i = 0; i < Dim; i++) { - for (unsigned int j = 0; j < Dim; j++) { + for (uint64_t i = 0; i < Dim; i++) { + for (uint64_t j = 0; j < Dim; j++) { Slater_inv[i * Dim + j] -= C[i * 3] * tmp[j]; Slater_inv[i * Dim + j] -= C[i * 3 + 1] * tmp[Dim + j]; Slater_inv[i * Dim + j] -= C[i * 3 + 2] * tmp[2 * Dim + j]; @@ -248,15 +248,15 @@ bool qmckl_woodbury_3(double *Slater_inv, const unsigned int Dim, double *Update // Sherman Morrison, with J. Slagel splitting (caller function) // http://hdl.handle.net/10919/52966 -void qmckl_sherman_morrison_splitting(double *Slater_inv, unsigned int Dim, unsigned int N_updates, - double *Updates, unsigned int *Updates_index) { +void qmckl_sherman_morrison_splitting(double *Slater_inv, uint64_t Dim, uint64_t N_updates, + double *Updates, uint64_t *Updates_index) { // #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. // std::cerr << "Called qmckl_sherman_morrison_splitting with " << N_updates << " updates" << std::endl; // #endif double later_updates[Dim * N_updates]; - unsigned int later_index[N_updates]; - unsigned int later = 0; + uint64_t later_index[N_updates]; + uint64_t later = 0; slagel_splitting(Slater_inv, Dim, N_updates, Updates, Updates_index, later_updates, later_index, &later); @@ -268,10 +268,10 @@ void qmckl_sherman_morrison_splitting(double *Slater_inv, unsigned int Dim, unsi // Sherman Morrison, with J. Slagel splitting // http://hdl.handle.net/10919/52966 -static void slagel_splitting(double *Slater_inv, unsigned int Dim, unsigned int N_updates, - double *Updates, unsigned int *Updates_index, - double *later_updates, unsigned int *later_index, - unsigned int *later) { +static void slagel_splitting(double *Slater_inv, uint64_t Dim, uint64_t N_updates, + double *Updates, uint64_t *Updates_index, + double *later_updates, uint64_t *later_index, + uint64_t *later) { // #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. // std::cerr << "Called slagel_splitting with " << N_updates << " updates" << std::endl; // #endif @@ -279,13 +279,13 @@ static void slagel_splitting(double *Slater_inv, unsigned int Dim, unsigned int double C[Dim]; double D[Dim]; - unsigned int l = 0; + uint64_t l = 0; // For each update while (l < N_updates) { // C = S^{-1} x U_l - for (unsigned int i = 0; i < Dim; i++) { + for (uint64_t i = 0; i < Dim; i++) { C[i] = 0; - for (unsigned int j = 0; j < Dim; j++) { + for (uint64_t j = 0; j < Dim; j++) { C[i] += Slater_inv[i * Dim + j] * Updates[l * Dim + j]; } } @@ -295,7 +295,7 @@ static void slagel_splitting(double *Slater_inv, unsigned int Dim, unsigned int if (fabs(den) < threshold()) { // U_l = U_l / 2 (do the split) - for (unsigned int i = 0; i < Dim; i++) { + for (uint64_t i = 0; i < Dim; i++) { later_updates[*later * Dim + i] = Updates[l * Dim + i] / 2.0; C[i] /= 2.0; } @@ -307,13 +307,13 @@ static void slagel_splitting(double *Slater_inv, unsigned int Dim, unsigned int double iden = 1 / den; // D = v^T x S^{-1} - for (unsigned int j = 0; j < Dim; j++) { + for (uint64_t j = 0; j < Dim; j++) { D[j] = Slater_inv[(Updates_index[l] - 1) * Dim + j]; } // S^{-1} = S^{-1} - C x D / den - for (unsigned int i = 0; i < Dim; i++) { - for (unsigned int j = 0; j < Dim; j++) { + for (uint64_t i = 0; i < Dim; i++) { + for (uint64_t j = 0; j < Dim; j++) { double update = C[i] * D[j] * iden; Slater_inv[i * Dim + j] -= update; } @@ -324,32 +324,32 @@ static void slagel_splitting(double *Slater_inv, unsigned int Dim, unsigned int // Sherman-Morrison-Woodbury 2x2 kernel // qmckl_woodbury_2, slagel_splitting mixing scheme -void qmckl_sherman_morrison_woodbury_2(double *Slater_inv, const unsigned int Dim, - const unsigned int N_updates, double *Updates, - unsigned int *Updates_index) { +void qmckl_sherman_morrison_woodbury_2(double *Slater_inv, const uint64_t Dim, + const uint64_t N_updates, double *Updates, + uint64_t *Updates_index) { // #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. // std::cerr << "Called qmckl_sherman_morrison_woodbury_2 with " << N_updates // << " updates" << std::endl; // #endif - unsigned int n_of_2blocks = N_updates / 2; - unsigned int remainder = N_updates % 2; - unsigned int length_2block = 2 * Dim; - unsigned int length_1block = 1 * Dim; + uint64_t n_of_2blocks = N_updates / 2; + uint64_t remainder = N_updates % 2; + uint64_t length_2block = 2 * Dim; + uint64_t length_1block = 1 * Dim; // Apply first 2*n_of_2blocks updates in n_of_2blocks blocks of 2 updates with // Woodbury 2x2 kernel double later_updates[Dim * N_updates]; - unsigned int later_index[N_updates]; - unsigned int later = 0; + uint64_t later_index[N_updates]; + uint64_t later = 0; if (n_of_2blocks > 0) { - for (unsigned int i = 0; i < n_of_2blocks; i++) { + for (uint64_t i = 0; i < n_of_2blocks; i++) { double *Updates_2block = &Updates[i * length_2block]; - unsigned int *Updates_index_2block = &Updates_index[i * 2]; + uint64_t *Updates_index_2block = &Updates_index[i * 2]; bool ok; ok = qmckl_woodbury_2(Slater_inv, Dim, Updates_2block, Updates_index_2block); if (!ok) { // Send the entire block to slagel_splitting - unsigned int l = 0; + uint64_t l = 0; slagel_splitting(Slater_inv, Dim, 2, Updates_2block, Updates_index_2block, later_updates + (Dim * later), later_index + later, &l); later = later + l; @@ -359,8 +359,8 @@ void qmckl_sherman_morrison_woodbury_2(double *Slater_inv, const unsigned int Di if (remainder == 1) { // Apply last remaining update with slagel_splitting double *Updates_1block = &Updates[n_of_2blocks * length_2block]; - unsigned int *Updates_index_1block = &Updates_index[2 * n_of_2blocks]; - unsigned int l = 0; + uint64_t *Updates_index_1block = &Updates_index[2 * n_of_2blocks]; + uint64_t l = 0; slagel_splitting(Slater_inv, Dim, 1, Updates_1block, Updates_index_1block, later_updates + (Dim * later), later_index + later, &l); later = later + l; @@ -373,33 +373,33 @@ void qmckl_sherman_morrison_woodbury_2(double *Slater_inv, const unsigned int Di // Sherman-Morrison-Woodbury 3x3 kernel // qmckl_woodbury_2, qmckl_woodbury_3, slagel_splitting mixing scheme -void qmckl_sherman_morrison_woodbury_3(double *Slater_inv, const unsigned int Dim, - const unsigned int N_updates, double *Updates, - unsigned int *Updates_index) { +void qmckl_sherman_morrison_woodbury_3(double *Slater_inv, const uint64_t Dim, + const uint64_t N_updates, double *Updates, + uint64_t *Updates_index) { // #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. // std::cerr << "Called qmckl_sherman_morrison_woodbury_3 with " << N_updates // << " updates" << std::endl; // #endif - unsigned int n_of_3blocks = N_updates / 3; - unsigned int remainder = N_updates % 3; - unsigned int length_3block = 3 * Dim; - unsigned int length_2block = 2 * Dim; - unsigned int length_1block = 1 * Dim; + uint64_t n_of_3blocks = N_updates / 3; + uint64_t remainder = N_updates % 3; + uint64_t length_3block = 3 * Dim; + uint64_t length_2block = 2 * Dim; + uint64_t length_1block = 1 * Dim; // Apply first 3*n_of_3blocks updates in n_of_3blocks blocks of 3 updates with // Woodbury 3x3 kernel double later_updates[Dim * N_updates]; - unsigned int later_index[N_updates]; - unsigned int later = 0; + uint64_t later_index[N_updates]; + uint64_t later = 0; if (n_of_3blocks > 0) { - for (unsigned int i = 0; i < n_of_3blocks; i++) { + for (uint64_t i = 0; i < n_of_3blocks; i++) { double *Updates_3block = &Updates[i * length_3block]; - unsigned int *Updates_index_3block = &Updates_index[i * 3]; + uint64_t *Updates_index_3block = &Updates_index[i * 3]; bool ok; ok = qmckl_woodbury_3(Slater_inv, Dim, Updates_3block, Updates_index_3block); if (!ok) { // Send the entire block to slagel_splitting - unsigned int l = 0; + uint64_t l = 0; slagel_splitting(Slater_inv, Dim, 3, Updates_3block, Updates_index_3block, later_updates + (Dim * later), later_index + later, &l); later = later + l; @@ -409,11 +409,11 @@ void qmckl_sherman_morrison_woodbury_3(double *Slater_inv, const unsigned int Di if (remainder == 2) { // Apply last remaining block of 2 updates with Woodbury 2x2 kernel double *Updates_2block = &Updates[n_of_3blocks * length_3block]; - unsigned int *Updates_index_2block = &Updates_index[3 * n_of_3blocks]; + uint64_t *Updates_index_2block = &Updates_index[3 * n_of_3blocks]; bool ok; ok = qmckl_woodbury_2(Slater_inv, Dim, Updates_2block, Updates_index_2block); if (!ok) { // Send the entire block to slagel_splitting - unsigned int l = 0; + uint64_t l = 0; slagel_splitting(Slater_inv, Dim, 2, Updates_2block, Updates_index_2block, later_updates + (Dim * later), later_index + later, &l); later = later + l; @@ -421,8 +421,8 @@ void qmckl_sherman_morrison_woodbury_3(double *Slater_inv, const unsigned int Di } else if (remainder == 1) { // Apply last remaining update with slagel_splitting double *Updates_1block = &Updates[n_of_3blocks * length_3block]; - unsigned int *Updates_index_1block = &Updates_index[3 * n_of_3blocks]; - unsigned int l = 0; + uint64_t *Updates_index_1block = &Updates_index[3 * n_of_3blocks]; + uint64_t l = 0; slagel_splitting(Slater_inv, Dim, 1, Updates_1block, Updates_index_1block, later_updates + (Dim * later), later_index + later, &l); later = later + l; diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index d562897..199e34f 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -29,6 +29,7 @@ int main() { qmckl_exit_code rc; #+end_src + * Sherman-Morrison Helper Functions Helper functions that are used by the Sherman-Morrison-Woodbury @@ -42,8 +43,8 @@ kernels. :FRetType: double precision :END: -This function is used to set the threshold value that is used in the kernels to determine if a matrix is invertable or not. In the Sherman-Morrison kernels this is determined by comparing the denominator in the Sherman-Morrison formula to the value set in threshold. If the value is smaller than the threshold value it means the matrix is not invertable. In the Woodbury kernels the threshold value is compared with the value of the determinant of the update matrix. - + This function is used to set the threshold value that is used in the kernels to determine if a matrix is invertable or not. In the Sherman-Morrison kernels this is determined by comparing the denominator in the Sherman-Morrison formula to the value set in threshold. If the value is smaller than the threshold value it means the matrix is not invertable. In the Woodbury kernels the threshold value is compared with the value of the determinant of the update matrix. + #+NAME: qmckl_sherman_morrison_threshold_args | double | thresh | out | Threshold | @@ -66,7 +67,6 @@ This function is used to set the threshold value that is used in the kernels to double* const thresh ); #+end_src - *** Source Fortran #+begin_src f90 :tangle (eval f) @@ -95,14 +95,13 @@ qmckl_exit_code qmckl_sherman_morrison_threshold_c(double* const threshold) { return QMCKL_SUCCESS; } #+end_src - - + *** Performance ** C interface :noexport: #+CALL: generate_c_interface(table=qmckl_sherman_morrison_threshold_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - + #+RESULTS: #+begin_src f90 :tangle (eval f) :comments org :exports none integer(c_int32_t) function qmckl_sherman_morrison_threshold & @@ -122,7 +121,7 @@ return QMCKL_SUCCESS; #+end_src #+CALL: generate_f_interface(table=qmckl_sherman_morrison_threshold_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - + #+RESULTS: #+begin_src f90 :tangle (eval fh_func) :comments org :exports none interface @@ -145,7 +144,7 @@ return QMCKL_SUCCESS; - + * Naïve Sherman-Morrison ** ~qmckl_sherman_morrison~ @@ -338,7 +337,7 @@ assert(rc == QMCKL_SUCCESS); * Woodbury 2x2 -[TODO: FMJC] Add main body intro. +This is the Woodbury 3x3 kernel. ** ~qmckl_woodbury_2~ :PROPERTIES: @@ -543,6 +542,225 @@ assert(rc == QMCKL_SUCCESS); #+end_src +* Woodbury 3x3 + +This is the Woodbury 3x3 kernel. + +** ~qmckl_woodbury_3~ + :PROPERTIES: + :Name: qmckl_woodbury_3 + :CRetType: qmckl_exit_code + :FRetType: qmckl_exit_code + :END: + + This is the simplest of the available Sherman-Morrison-Woodbury + kernels in QMCkl. It applies rank-1 updates one by one in the order + that is given. It only checks if the denominator in the + Sherman-Morrison formula is not too close to zero (and exit with an + error if it does) during the application of an update. + + #+NAME: qmckl_woodbury_3_args + | qmckl_context | context | in | Global state | + | uint64_t | Dim | in | Leading dimension of Slater_inv | + | double | Updates[3*Dim] | in | Array containing the updates | + | uint64_t | Updates_index[3] | in | Array containing the rank-1 updates | + | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | + +*** Requirements + + Add description of the input variables. (see for e.g. qmckl_distance.org) + +*** C header + + #+CALL: generate_c_header(table=qmckl_woodbury_3_args,rettyp=get_value("CRetType"),fname=get_value("Name")) + + #+RESULTS: + #+begin_src c :tangle (eval h_func) :comments org + qmckl_exit_code qmckl_woodbury_3_c ( + const qmckl_context context, + const uint64_t Dim, + const double* Updates, + const uint64_t* Updates_index, + double* Slater_inv ); + #+end_src + +*** Source Fortran + + #+begin_src f90 :tangle (eval f) +integer function qmckl_woodbury_3_f(context, Slater_inv, Dim, & + Updates, Updates_index) result(info) + use qmckl + implicit none + integer(qmckl_context) , intent(in) :: context + integer*8 , intent(in), value :: Dim + integer*8 , intent(in) :: Updates_index(3) + real*8 , intent(in) :: Updates(3*Dim) + real*8 , intent(inout) :: Slater_inv(Dim*Dim) + !logical, external :: qmckl_woodbury_3_f + info = qmckl_woodbury_2(context, Dim, Updates, Updates_index, Slater_inv) +end function qmckl_woodbury_3_f + #+end_src + +*** Source C + + #+begin_src c :tangle (eval c) :comments org +#include +#include "qmckl.h" + +qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, + const uint64_t Dim, + const double* Updates, + const uint64_t* Updates_index, + double * Slater_inv) { +/* + C := S^{-1} * U, dim x 3 + B := 1 + V * C, 3 x 3 + D := V * S^{-1}, 3 x dim +,*/ +// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. +// std::cerr << "Called Woodbury 3x3 kernel" << std::endl; +// #endif + + const uint64_t row1 = (Updates_index[0] - 1); + const uint64_t row2 = (Updates_index[1] - 1); + const uint64_t row3 = (Updates_index[2] - 1); + + // Compute C = S_inv * U !! NON-STANDARD MATRIX MULTIPLICATION BECAUSE + // OF LAYOUT OF 'Updates' !! + double C[3 * Dim]; + for (uint64_t i = 0; i < Dim; i++) { + for (uint64_t j = 0; j < 3; j++) { + C[i * 3 + j] = 0; + for (uint64_t k = 0; k < Dim; k++) { + C[i * 3 + j] += Slater_inv[i * Dim + k] * Updates[Dim * j + k]; + } + } + } + + // Compute B = 1 + V.C + const double B0 = C[row1 * 3] + 1; + const double B1 = C[row1 * 3 + 1]; + const double B2 = C[row1 * 3 + 2]; + const double B3 = C[row2 * 3]; + const double B4 = C[row2 * 3 + 1] + 1; + const double B5 = C[row2 * 3 + 2]; + const double B6 = C[row3 * 3]; + const double B7 = C[row3 * 3 + 1]; + const double B8 = C[row3 * 3 + 2] + 1; + + // Check if determinant of B is not too close to zero + double det; + det = B0 * (B4 * B8 - B5 * B7) - B1 * (B3 * B8 - B5 * B6) + + B2 * (B3 * B7 - B4 * B6); + double thresh = 0.0; + qmckl_exit_code rc = qmckl_sherman_morrison_threshold_c(&thresh); + if (fabs(det) < thresh) { + return QMCKL_FAILURE; + } + + // Compute B^{-1} with explicit formula for 3x3 inversion + double Binv[9], idet = 1.0 / det; + Binv[0] = (B4 * B8 - B7 * B5) * idet; + Binv[1] = -(B1 * B8 - B7 * B2) * idet; + Binv[2] = (B1 * B5 - B4 * B2) * idet; + Binv[3] = -(B3 * B8 - B6 * B5) * idet; + Binv[4] = (B0 * B8 - B6 * B2) * idet; + Binv[5] = -(B0 * B5 - B3 * B2) * idet; + Binv[6] = (B3 * B7 - B6 * B4) * idet; + Binv[7] = -(B0 * B7 - B6 * B1) * idet; + Binv[8] = (B0 * B4 - B3 * B1) * idet; + + // Compute tmp = B^{-1} x (V.S^{-1}) + double tmp[3 * Dim]; + for (uint64_t i = 0; i < 3; i++) { + for (uint64_t j = 0; j < Dim; j++) { + tmp[i * Dim + j] = Binv[i * 3] * Slater_inv[row1 * Dim + j]; + tmp[i * Dim + j] += Binv[i * 3 + 1] * Slater_inv[row2 * Dim + j]; + tmp[i * Dim + j] += Binv[i * 3 + 2] * Slater_inv[row3 * Dim + j]; + } + } + + // Compute (S + U V)^{-1} = S^{-1} - C x tmp + for (uint64_t i = 0; i < Dim; i++) { + for (uint64_t j = 0; j < Dim; j++) { + Slater_inv[i * Dim + j] -= C[i * 3] * tmp[j]; + Slater_inv[i * Dim + j] -= C[i * 3 + 1] * tmp[Dim + j]; + Slater_inv[i * Dim + j] -= C[i * 3 + 2] * tmp[2 * Dim + j]; + } + } + + return QMCKL_SUCCESS; +} + + #+end_src + +*** Performance... + +** C interface :noexport: + + #+CALL: generate_c_interface(table=qmckl_woodbury_3_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + + #+RESULTS: + #+begin_src f90 :tangle (eval f) :comments org :exports none + integer(c_int32_t) function qmckl_woodbury_3 & + (context, Dim, Updates, Updates_index, Slater_inv) & + bind(C) result(info) + + use, intrinsic :: iso_c_binding + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) , value :: Dim + real (c_double ) , intent(in) :: Updates(3*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(3) + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + integer(c_int32_t), external :: qmckl_woodbury_3_c + info = qmckl_woodbury_3_c & + (context, Dim, Updates, Updates_index, Slater_inv) + + end function qmckl_woodbury_3 + #+end_src + + #+CALL: generate_f_interface(table=qmckl_woodbury_3_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + + #+RESULTS: + #+begin_src f90 :tangle (eval fh_func) :comments org :exports none + interface + integer(c_int32_t) function qmckl_woodbury_3 & + (context, Dim, Updates, Updates_index, Slater_inv) & + bind(C) + use, intrinsic :: iso_c_binding + import + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) , value :: Dim + real (c_double ) , intent(in) :: Updates(3*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(3) + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + end function qmckl_woodbury_3 + end interface + #+end_src + +*** Test :noexport: + +[TODO: FMJC] Write tests for the Sherman-Morrison part. + + + #+begin_src c :tangle (eval c_test) +const uint64_t woodbury3_Dim = 3; +const uint64_t woodbury3_Updates_index[3] = {1, 1, 1}; +const double woodbury3_Updates[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; +double woodbury3_Slater_inv[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; + +// [TODO : FMJC ] add realistic tests + +rc = qmckl_woodbury_3_c(context, woodbury3_Dim, woodbury3_Updates, woodbury3_Updates_index, woodbury3_Slater_inv); +assert(rc == QMCKL_SUCCESS); + #+end_src + * End of files @@ -556,3 +774,4 @@ assert(rc == QMCKL_SUCCESS); # -*- mode: org -*- # vim: syntax=c + From e1b325ab1846c755cee24940461fc205918c6fc6 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Thu, 22 Jul 2021 18:05:39 +0200 Subject: [PATCH 23/50] Added Sherman-Morrison with update splitting. For now the headers for qmckl_slagel_splitting_c and qmckl_sherman_morrison_splitting_c are not generated. #25 --- org/qmckl_sherman_morrison_woodbury.org | 278 +++++++++++++++++++----- 1 file changed, 218 insertions(+), 60 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 199e34f..93dd8bd 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -36,17 +36,17 @@ Helper functions that are used by the Sherman-Morrison-Woodbury kernels. These functions should only be used in the context of these kernels. -** ~qmckl_sherman_morrison_threshold~ +** ~qmckl_threshold~ :PROPERTIES: - :Name: qmckl_sherman_morrison_threshold + :Name: qmckl_threshold :CRetType: double :FRetType: double precision :END: This function is used to set the threshold value that is used in the kernels to determine if a matrix is invertable or not. In the Sherman-Morrison kernels this is determined by comparing the denominator in the Sherman-Morrison formula to the value set in threshold. If the value is smaller than the threshold value it means the matrix is not invertable. In the Woodbury kernels the threshold value is compared with the value of the determinant of the update matrix. - #+NAME: qmckl_sherman_morrison_threshold_args - | double | thresh | out | Threshold | + #+NAME: qmckl_threshold_args + | double | thresh | inout | Threshold | *** Requirements @@ -54,7 +54,7 @@ kernels. *** C header - #+CALL: generate_c_header(table=qmckl_sherman_morrison_threshold_args,rettyp=get_value("CRetType"),fname=get_value("Name")) + #+CALL: generate_c_header(table=qmckl_threshold_args,rettyp=get_value("CRetType"),fname=get_value("Name")) #+RESULTS: #+begin_src c :tangle (eval h_func) :comments org @@ -63,31 +63,20 @@ kernels. #define THRESHOLD 1e-3 #endif - qmckl_exit_code qmckl_sherman_morrison_threshold_c ( + qmckl_exit_code qmckl_threshold_c ( double* const thresh ); #+end_src *** Source Fortran - #+begin_src f90 :tangle (eval f) -integer function qmckl_sherman_morrison_threshold_f(thresh) result(info) - use qmckl - implicit none - real*8 , intent(inout) :: thresh - !logical, external :: qmckl_sherman_morrison_f - info = qmckl_sherman_morrison_threshold(thresh) -end function qmckl_sherman_morrison_threshold_f - #+end_src - *** Source C #+begin_src c :tangle (eval c) :comments org #include -#include #include "qmckl.h" // Sherman-Morrison-Woodbury break-down threshold -qmckl_exit_code qmckl_sherman_morrison_threshold_c(double* const threshold) { +qmckl_exit_code qmckl_threshold_c(double* const threshold) { *threshold = THRESHOLD; // #ifdef DEBUG // std::cerr << "Break-down threshold set to: " << threshold << std::endl; @@ -98,45 +87,115 @@ return QMCKL_SUCCESS; *** Performance +** ~qmckl_slagel_splitting~ + :PROPERTIES: + :Name: qmckl_slagel_splitting + :CRetType: double + :FRetType: double precision + :END: + + This function is used to set the threshold value that is used in the kernels to determine if a matrix is invertable or not. In the Sherman-Morrison kernels this is determined by comparing the denominator in the Sherman-Morrison formula to the value set in threshold. If the value is smaller than the threshold value it means the matrix is not invertable. In the Woodbury kernels the threshold value is compared with the value of the determinant of the update matrix. + + #+NAME: qmckl_slagel_splitting_args + | uint64_t | Dim | in | Leading dimension of Slater_inv | + | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | + | double | Updates[N_updates*Dim] | in | Array containing the rank-1 updates | + | uint64_t | Updates_index[N_updates] | in | Array containing positions of the rank-1 updates | + | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse Slater-matrix | + | double | later_updates[Dim * N_updates] | inout | Array containing the split updates for later | + | uint64_t | later_index[N_updates] | inout | Array containing the positions of the split updates for later | + | uint64_t | later | inout | Number of split updates for later | + + +*** Requirements + + Add description of the input variables. (see for e.g. qmckl_distance.org) + +*** C header + + #+CALL: generate_c_header(table=qmckl_slagel_splitting_args,rettyp=get_value("CRetType"),fname=get_value("Name")) + +*** Source Fortran + +*** Source C + + #+begin_src c :tangle (eval c) :comments org +#include +#include +#include "qmckl.h" + +qmckl_exit_code qmckl_slagel_splitting_c(uint64_t Dim, + uint64_t N_updates, + double *Updates, + uint64_t *Updates_index, + double *Slater_inv, + double *later_updates, + uint64_t *later_index, + uint64_t *later) { +// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. +// std::cerr << "Called slagel_splitting with " << N_updates << " updates" << std::endl; +// #endif + + double C[Dim]; + double D[Dim]; + + uint64_t l = 0; + // For each update + while (l < N_updates) { + // C = S^{-1} x U_l + for (uint64_t i = 0; i < Dim; i++) { + C[i] = 0; + for (uint64_t j = 0; j < Dim; j++) { + C[i] += Slater_inv[i * Dim + j] * Updates[l * Dim + j]; + } + } + + // Denominator + double den = 1 + C[Updates_index[l] - 1]; + double thresh = 0.0; + qmckl_exit_code rc = qmckl_threshold_c(&thresh); + if (fabs(den) < thresh) { + + // U_l = U_l / 2 (do the split) + for (uint64_t i = 0; i < Dim; i++) { + later_updates[*later * Dim + i] = Updates[l * Dim + i] / 2.0; + C[i] /= 2.0; + } + later_index[*later] = Updates_index[l]; + (*later)++; + + den = 1 + C[Updates_index[l] - 1]; + } + double iden = 1 / den; + + // D = v^T x S^{-1} + for (uint64_t j = 0; j < Dim; j++) { + D[j] = Slater_inv[(Updates_index[l] - 1) * Dim + j]; + } + + // S^{-1} = S^{-1} - C x D / den + for (uint64_t i = 0; i < Dim; i++) { + for (uint64_t j = 0; j < Dim; j++) { + double update = C[i] * D[j] * iden; + Slater_inv[i * Dim + j] -= update; + } + } + l += 1; + } + + return QMCKL_SUCCESS; +} + + #+end_src + +*** Performance + + ** C interface :noexport: - - #+CALL: generate_c_interface(table=qmckl_sherman_morrison_threshold_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - #+RESULTS: - #+begin_src f90 :tangle (eval f) :comments org :exports none - integer(c_int32_t) function qmckl_sherman_morrison_threshold & - (thresh) & - bind(C) result(info) + #+CALL: generate_f_interface(table=qmckl_threshold_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - use, intrinsic :: iso_c_binding - implicit none - - real (c_double ) , intent(out) :: thresh - - integer(c_int32_t), external :: qmckl_sherman_morrison_threshold_c - info = qmckl_sherman_morrison_threshold_c & - (thresh) - - end function qmckl_sherman_morrison_threshold - #+end_src - - #+CALL: generate_f_interface(table=qmckl_sherman_morrison_threshold_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - - #+RESULTS: - #+begin_src f90 :tangle (eval fh_func) :comments org :exports none - interface - integer(c_int32_t) function qmckl_sherman_morrison_threshold & - (thresh) & - bind(C) - use, intrinsic :: iso_c_binding - import - implicit none - - real (c_double ) , intent(out) :: thresh - - end function qmckl_sherman_morrison_threshold - end interface - #+end_src + #+CALL: generate_c_interface(table=qmckl_slagel_splitting_args,rettyp=get_value("FRetType"),fname=get_value("Name")) *** Test :noexport: @@ -219,9 +278,6 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, double C[Dim]; double D[Dim]; - double threshold = 0.0; - qmckl_exit_code rc = qmckl_sherman_morrison_threshold_c(&threshold); - uint64_t l = 0; // For each update while (l < N_updates) { @@ -236,7 +292,7 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, // Denominator double den = 1 + C[Updates_index[l] - 1]; double thresh = 0.0; - qmckl_exit_code rc = qmckl_sherman_morrison_threshold_c(&thresh); + qmckl_exit_code rc = qmckl_threshold_c(&thresh); if (fabs(den) < thresh) { return QMCKL_FAILURE; } @@ -438,7 +494,7 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, // Check if determinant of inverted matrix is not zero double det = B0 * B3 - B1 * B2; double thresh = 0.0; - qmckl_exit_code rc = qmckl_sherman_morrison_threshold_c(&thresh); + qmckl_exit_code rc = qmckl_threshold_c(&thresh); if (fabs(det) < thresh) { return QMCKL_FAILURE; } @@ -653,7 +709,7 @@ qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, det = B0 * (B4 * B8 - B5 * B7) - B1 * (B3 * B8 - B5 * B6) + B2 * (B3 * B7 - B4 * B6); double thresh = 0.0; - qmckl_exit_code rc = qmckl_sherman_morrison_threshold_c(&thresh); + qmckl_exit_code rc = qmckl_threshold_c(&thresh); if (fabs(det) < thresh) { return QMCKL_FAILURE; } @@ -762,6 +818,108 @@ assert(rc == QMCKL_SUCCESS); #+end_src +* Sherman-Morrison with update splitting + +This is like naïve Sherman-Morrising, but whenever a denominator is found that is too close to zero the update +is split in half. Then one half is applied immediately and the other have is ket for later. When all the updates +have been processed, the list of split updates that have been kept for later are processed. If again applying an +update results in a denominator that is too close to zero, it is split in half again. One half is applied immediately +and one half is kept for later. The algorithm is done when no more updates have been kept for later. This recursion +will always end in a finite number of steps, unless the last original update causes a singular Slater-matrix. + +** ~qmckl_sherman_morrison_splitting~ + :PROPERTIES: + :Name: qmckl_sherman_morrison_splitting + :CRetType: qmckl_exit_code + :FRetType: qmckl_exit_code + :END: + + This is the simplest of the available Sherman-Morrison-Woodbury + kernels in QMCkl. It applies rank-1 updates one by one in the order + that is given. It only checks if the denominator in the + Sherman-Morrison formula is not too close to zero (and exit with an + error if it does) during the application of an update. + + #+NAME: qmckl_sherman_morrison_splitting_args + | qmckl_context | context | in | Global state | + | uint64_t | Dim | in | Leading dimension of Slater_inv | + | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | + | double | Updates[N_updates*Dim] | in | Array containing the updates | + | uint64_t | Updates_index[N_updates] | in | Array containing the rank-1 updates | + | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | + +*** Requirements + + Add description of the input variables. (see for e.g. qmckl_distance.org) + +*** C header + + #+CALL: generate_c_header(table=qmckl_sherman_morrison_splitting_args,rettyp=get_value("CRetType"),fname=get_value("Name")) + +*** Source Fortran + +*** Source C + + #+begin_src c :tangle (eval c) :comments org +#include +#include "qmckl.h" + +qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, + const uint64_t Dim, + const uint64_t N_updates, + const double* Updates, + const uint64_t* Updates_index, + double * Slater_inv) { +// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. +// std::cerr << "Called qmckl_sherman_morrison_splitting with " << N_updates << " updates" << std::endl; +// #endif + + double later_updates[Dim * N_updates]; + uint64_t later_index[N_updates]; + uint64_t later = 0; + + qmckl_exit_code smss = qmckl_slagel_splitting_c(Dim, N_updates, Updates, Updates_index, + Slater_inv, later_updates, later_index, &later); + + if (later > 0) { + qmckl_context context = qmckl_context_create(); + qmckl_exit_code sms = qmckl_sherman_morrison_splitting_c(context, Dim, later, + later_updates, later_index, Slater_inv); + } + + return QMCKL_SUCCESS; +} + + #+end_src + +*** Performance... + +** C interface :noexport: + + #+CALL: generate_c_interface(table=qmckl_sherman_morrison_splitting_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + + #+CALL: generate_f_interface(table=qmckl_sherman_morrison_splitting_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + + +*** Test :noexport: + +[TODO: FMJC] Write tests for the Sherman-Morrison part. + + + #+begin_src c :tangle (eval c_test) +const uint64_t splitting_Dim = 3; +const uint64_t splitting_Updates_index[3] = {1, 1, 1}; +const double splitting_Updates[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; +double splitting_Slater_inv[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; + +// [TODO : FMJC ] add realistic tests + +rc = qmckl_sherman_morrison_splitting_c(context, splitting_Dim, splitting_Updates, splitting_Updates_index, splitting_Slater_inv); +assert(rc == QMCKL_SUCCESS); + #+end_src + + + * End of files #+begin_src c :comments link :tangle (eval c_test) From 90b6333560c5552f96843981b554322032795433 Mon Sep 17 00:00:00 2001 From: vijay gopal chilkuri Date: Thu, 22 Jul 2021 18:20:20 +0200 Subject: [PATCH 24/50] Splitting tests bug fix. #25 --- org/qmckl_sherman_morrison_woodbury.org | 129 +++++++++++++++++++----- 1 file changed, 104 insertions(+), 25 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 93dd8bd..b53c1ab 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -31,7 +31,7 @@ int main() { * Sherman-Morrison Helper Functions - + Helper functions that are used by the Sherman-Morrison-Woodbury kernels. These functions should only be used in the context of these kernels. @@ -97,14 +97,14 @@ return QMCKL_SUCCESS; This function is used to set the threshold value that is used in the kernels to determine if a matrix is invertable or not. In the Sherman-Morrison kernels this is determined by comparing the denominator in the Sherman-Morrison formula to the value set in threshold. If the value is smaller than the threshold value it means the matrix is not invertable. In the Woodbury kernels the threshold value is compared with the value of the determinant of the update matrix. #+NAME: qmckl_slagel_splitting_args - | uint64_t | Dim | in | Leading dimension of Slater_inv | - | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | - | double | Updates[N_updates*Dim] | in | Array containing the rank-1 updates | - | uint64_t | Updates_index[N_updates] | in | Array containing positions of the rank-1 updates | - | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse Slater-matrix | - | double | later_updates[Dim * N_updates] | inout | Array containing the split updates for later | - | uint64_t | later_index[N_updates] | inout | Array containing the positions of the split updates for later | - | uint64_t | later | inout | Number of split updates for later | + | uint64_t | Dim | in | Leading dimension of Slater_inv | + | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | + | double | Updates[N_updates*Dim] | in | Array containing the rank-1 updates | + | uint64_t | Updates_index[N_updates] | in | Array containing positions of the rank-1 updates | + | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse Slater-matrix | + | double | later_updates[Dim * N_updates] | inout | Array containing the split updates for later | + | uint64_t | later_index[N_updates] | inout | Array containing the positions of the split updates for later | + | uint64_t | later | inout | Number of split updates for later | *** Requirements @@ -126,8 +126,8 @@ return QMCKL_SUCCESS; qmckl_exit_code qmckl_slagel_splitting_c(uint64_t Dim, uint64_t N_updates, - double *Updates, - uint64_t *Updates_index, + const double *Updates, + const uint64_t *Updates_index, double *Slater_inv, double *later_updates, uint64_t *later_index, @@ -213,7 +213,11 @@ qmckl_exit_code qmckl_slagel_splitting_c(uint64_t Dim, :FRetType: qmckl_exit_code :END: - This is the simplest of the available Sherman-Morrison-Woodbury kernels in QMCkl. It applies rank-1 updates one by one in the order that is given. It only checks if the denominator in the Sherman-Morrison formula is not too close to zero (and exit with an error if it does) during the application of an update. + This is the simplest of the available Sherman-Morrison-Woodbury + kernels in QMCkl. It applies rank-1 updates one by one in the order + that is given. It only checks if the denominator in the + Sherman-Morrison formula is not too close to zero (and exit with an + error if it does) during the application of an update. #+NAME: qmckl_sherman_morrison_args | qmckl_context | context | in | Global state | @@ -820,12 +824,16 @@ assert(rc == QMCKL_SUCCESS); * Sherman-Morrison with update splitting -This is like naïve Sherman-Morrising, but whenever a denominator is found that is too close to zero the update -is split in half. Then one half is applied immediately and the other have is ket for later. When all the updates -have been processed, the list of split updates that have been kept for later are processed. If again applying an -update results in a denominator that is too close to zero, it is split in half again. One half is applied immediately -and one half is kept for later. The algorithm is done when no more updates have been kept for later. This recursion -will always end in a finite number of steps, unless the last original update causes a singular Slater-matrix. +This is like naïve Sherman-Morrising, but whenever a denominator is +found that is too close to zero the update is split in half. Then one +half is applied immediately and the other have is ket for later. When +all the updates have been processed, the list of split updates that +have been kept for later are processed. If again applying an update +results in a denominator that is too close to zero, it is split in +half again. One half is applied immediately and one half is kept for +later. The algorithm is done when no more updates have been kept for +later. This recursion will always end in a finite number of steps, +unless the last original update causes a singular Slater-matrix. ** ~qmckl_sherman_morrison_splitting~ :PROPERTIES: @@ -841,12 +849,12 @@ will always end in a finite number of steps, unless the last original update cau error if it does) during the application of an update. #+NAME: qmckl_sherman_morrison_splitting_args - | qmckl_context | context | in | Global state | - | uint64_t | Dim | in | Leading dimension of Slater_inv | - | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | - | double | Updates[N_updates*Dim] | in | Array containing the updates | - | uint64_t | Updates_index[N_updates] | in | Array containing the rank-1 updates | - | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | + | qmckl_context | context | in | Global state | + | uint64_t | Dim | in | Leading dimension of Slater_inv | + | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | + | double | Updates[N_updates*Dim] | in | Array containing the updates | + | uint64_t | Updates_index[N_updates] | in | Array containing the rank-1 updates | + | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | *** Requirements @@ -856,8 +864,34 @@ will always end in a finite number of steps, unless the last original update cau #+CALL: generate_c_header(table=qmckl_sherman_morrison_splitting_args,rettyp=get_value("CRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src c :tangle (eval h_func) :comments org + qmckl_exit_code qmckl_sherman_morrison_splitting_c ( + const qmckl_context context, + const uint64_t Dim, + const uint64_t N_updates, + const double* Updates, + const uint64_t* Updates_index, + double* Slater_inv ); + #+end_src + *** Source Fortran + #+begin_src f90 :tangle (eval f) +integer function qmckl_sherman_morrison_splitting_f(context, Slater_inv, Dim, N_updates, & + Updates, Updates_index) result(info) + use qmckl + implicit none + integer(qmckl_context) , intent(in) :: context + integer*8 , intent(in), value :: Dim, N_updates + integer*8 , intent(in) :: Updates_index(N_updates) + real*8 , intent(in) :: Updates(N_updates*Dim) + real*8 , intent(inout) :: Slater_inv(Dim*Dim) + info = qmckl_sherman_morrison_splitting(context, Dim, N_updates, Updates, Updates_index, Slater_inv) +end function qmckl_sherman_morrison_splitting_f + #+end_src + + *** Source C #+begin_src c :tangle (eval c) :comments org @@ -898,8 +932,52 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, #+CALL: generate_c_interface(table=qmckl_sherman_morrison_splitting_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src f90 :tangle (eval f) :comments org :exports none + integer(c_int32_t) function qmckl_sherman_morrison_splitting & + (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & + bind(C) result(info) + + use, intrinsic :: iso_c_binding + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) , value :: Dim + integer (c_int64_t) , intent(in) , value :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + integer(c_int32_t), external :: qmckl_sherman_morrison_splitting_c + info = qmckl_sherman_morrison_splitting_c & + (context, Dim, N_updates, Updates, Updates_index, Slater_inv) + + end function qmckl_sherman_morrison_splitting + #+end_src + #+CALL: generate_f_interface(table=qmckl_sherman_morrison_splitting_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src f90 :tangle (eval fh_func) :comments org :exports none + interface + integer(c_int32_t) function qmckl_sherman_morrison_splitting & + (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & + bind(C) + use, intrinsic :: iso_c_binding + import + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) , value :: Dim + integer (c_int64_t) , intent(in) , value :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + end function qmckl_sherman_morrison_splitting + end interface + #+end_src + *** Test :noexport: @@ -908,13 +986,14 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, #+begin_src c :tangle (eval c_test) const uint64_t splitting_Dim = 3; +const uint64_t splitting_N_updates = 3; const uint64_t splitting_Updates_index[3] = {1, 1, 1}; const double splitting_Updates[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; double splitting_Slater_inv[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; // [TODO : FMJC ] add realistic tests -rc = qmckl_sherman_morrison_splitting_c(context, splitting_Dim, splitting_Updates, splitting_Updates_index, splitting_Slater_inv); +rc = qmckl_sherman_morrison_splitting_c(context, splitting_Dim, splitting_N_updates, splitting_Updates, splitting_Updates_index, splitting_Slater_inv); assert(rc == QMCKL_SUCCESS); #+end_src From 159fb149a47e3e8401be80ffc989f33493b16c42 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Fri, 23 Jul 2021 16:50:51 +0200 Subject: [PATCH 25/50] Added Woobury 3x3, 2x2 and Sherman-Morrison-Splitting mixed kernels. Compiles fine but test still fail. #25 --- org/qmckl_sherman_morrison_woodbury.org | 289 +++++++++++++++++++++++- 1 file changed, 286 insertions(+), 3 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index b53c1ab..e2e93d9 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -908,16 +908,19 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, // std::cerr << "Called qmckl_sherman_morrison_splitting with " << N_updates << " updates" << std::endl; // #endif + qmckl_context local_context; + local_context = qmckl_context_create(); + qmckl_exit_code rc; + double later_updates[Dim * N_updates]; uint64_t later_index[N_updates]; uint64_t later = 0; - qmckl_exit_code smss = qmckl_slagel_splitting_c(Dim, N_updates, Updates, Updates_index, + rc = qmckl_slagel_splitting_c(Dim, N_updates, Updates, Updates_index, Slater_inv, later_updates, later_index, &later); if (later > 0) { - qmckl_context context = qmckl_context_create(); - qmckl_exit_code sms = qmckl_sherman_morrison_splitting_c(context, Dim, later, + rc = qmckl_sherman_morrison_splitting_c(local_context, Dim, later, later_updates, later_index, Slater_inv); } @@ -997,6 +1000,286 @@ rc = qmckl_sherman_morrison_splitting_c(context, splitting_Dim, splitting_N_upda assert(rc == QMCKL_SUCCESS); #+end_src +* Sherman-Morrison with Woodbury 2x2 and update splitting + +This is like naïve Sherman-Morrising, but whenever a denominator is +found that is too close to zero the update is split in half. Then one +half is applied immediately and the other have is ket for later. When +all the updates have been processed, the list of split updates that +have been kept for later are processed. If again applying an update +results in a denominator that is too close to zero, it is split in +half again. One half is applied immediately and one half is kept for +later. The algorithm is done when no more updates have been kept for +later. This recursion will always end in a finite number of steps, +unless the last original update causes a singular Slater-matrix. + +** ~qmckl_sherman_morrison_smw2s~ + :PROPERTIES: + :Name: qmckl_sherman_morrison_smw2s + :CRetType: qmckl_exit_code + :FRetType: qmckl_exit_code + :END: + + This is the simplest of the available Sherman-Morrison-Woodbury + kernels in QMCkl. It applies rank-1 updates one by one in the order + that is given. It only checks if the denominator in the + Sherman-Morrison formula is not too close to zero (and exit with an + error if it does) during the application of an update. + + #+NAME: qmckl_sherman_morrison_smw2s_args + | qmckl_context | context | in | Global state | + | uint64_t | Dim | in | Leading dimension of Slater_inv | + | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | + | double | Updates[N_updates*Dim] | in | Array containing the updates | + | uint64_t | Updates_index[N_updates] | in | Array containing the rank-1 updates | + | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | + +*** Requirements + + Add description of the input variables. (see for e.g. qmckl_distance.org) + +*** C header + + #+CALL: generate_c_header(table=qmckl_sherman_morrison_smw2s_args,rettyp=get_value("CRetType"),fname=get_value("Name")) + + +*** Source Fortran + + +*** Source C + + #+begin_src c :tangle (eval c) :comments org +#include +#include "qmckl.h" + +qmckl_exit_code qmckl_sherman_morrison_smw2s_c(const qmckl_context context, + const uint64_t Dim, + const uint64_t N_updates, + const double* Updates, + const uint64_t* Updates_index, + double * Slater_inv) { +// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. +// std::cerr << "Called qmckl_sherman_morrison_woodbury_2 with " << N_updates +// << " updates" << std::endl; +// #endif + + qmckl_context local_context; + local_context = qmckl_context_create(); + qmckl_exit_code rc; + + uint64_t n_of_2blocks = N_updates / 2; + uint64_t remainder = N_updates % 2; + uint64_t length_2block = 2 * Dim; + uint64_t length_1block = 1 * Dim; + + // Apply first 2*n_of_2blocks updates in n_of_2blocks blocks of 2 updates with + // Woodbury 2x2 kernel + double later_updates[Dim * N_updates]; + uint64_t later_index[N_updates]; + uint64_t later = 0; + if (n_of_2blocks > 0) { + for (uint64_t i = 0; i < n_of_2blocks; i++) { + double *Updates_2block = &Updates[i * length_2block]; + uint64_t *Updates_index_2block = &Updates_index[i * 2]; + rc = qmckl_woodbury_2_c(local_context, Dim, Updates_2block, Updates_index_2block, Slater_inv); + if (rc != 0) { // Send the entire block to slagel_splitting + uint64_t l = 0; + rc = qmckl_slagel_splitting_c(Dim, 2, Updates_2block, Updates_index_2block, + Slater_inv, later_updates + (Dim * later), later_index + later, &l); + later = later + l; + } + } + } + + if (remainder == 1) { // Apply last remaining update with slagel_splitting + double *Updates_1block = &Updates[n_of_2blocks * length_2block]; + uint64_t *Updates_index_1block = &Updates_index[2 * n_of_2blocks]; + uint64_t l = 0; + rc = qmckl_slagel_splitting_c(Dim, 1, Updates_1block, Updates_index_1block, + Slater_inv, later_updates + (Dim * later), later_index + later, &l); + later = later + l; + } + + if (later > 0) { + rc = qmckl_sherman_morrison_splitting_c(local_context, Dim, later, later_updates, later_index, Slater_inv); + } +} + + #+end_src + +*** Performance... + +** C interface :noexport: + + #+CALL: generate_c_interface(table=qmckl_sherman_morrison_smw2s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + + #+CALL: generate_f_interface(table=qmckl_sherman_morrison_smw2s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + +*** Test :noexport: + +[TODO: FMJC] Write tests for the Sherman-Morrison part. + + + #+begin_src c :tangle (eval c_test) +const uint64_t smw2s_Dim = 3; +const uint64_t smw2s_N_updates = 3; +const uint64_t smw2s_Updates_index[3] = {1, 1, 1}; +const double smw2s_Updates[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; +double smw2s_Slater_inv[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; + +// [TODO : FMJC ] add realistic tests + +rc = qmckl_sherman_morrison_smw2s_c(context, smw2s_Dim, smw2s_N_updates, + smw2s_Updates, smw2s_Updates_index, smw2s_Slater_inv); +assert(rc == QMCKL_SUCCESS); + #+end_src + +* Sherman-Morrison with Woodbury 3x3, 2x2 and update splitting + +This is like naïve Sherman-Morrising, but whenever a denominator is +found that is too close to zero the update is split in half. Then one +half is applied immediately and the other have is ket for later. When +all the updates have been processed, the list of split updates that +have been kept for later are processed. If again applying an update +results in a denominator that is too close to zero, it is split in +half again. One half is applied immediately and one half is kept for +later. The algorithm is done when no more updates have been kept for +later. This recursion will always end in a finite number of steps, +unless the last original update causes a singular Slater-matrix. + +** ~qmckl_sherman_morrison_smw32s~ + :PROPERTIES: + :Name: qmckl_sherman_morrison_smw32s + :CRetType: qmckl_exit_code + :FRetType: qmckl_exit_code + :END: + + This is the simplest of the available Sherman-Morrison-Woodbury + kernels in QMCkl. It applies rank-1 updates one by one in the order + that is given. It only checks if the denominator in the + Sherman-Morrison formula is not too close to zero (and exit with an + error if it does) during the application of an update. + + #+NAME: qmckl_sherman_morrison_smw32s_args + | qmckl_context | context | in | Global state | + | uint64_t | Dim | in | Leading dimension of Slater_inv | + | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | + | double | Updates[N_updates*Dim] | in | Array containing the updates | + | uint64_t | Updates_index[N_updates] | in | Array containing the rank-1 updates | + | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | + +*** Requirements + + Add description of the input variables. (see for e.g. qmckl_distance.org) + +*** C header + + #+CALL: generate_c_header(table=qmckl_sherman_morrison_smw32s_args,rettyp=get_value("CRetType"),fname=get_value("Name")) + + +*** Source Fortran + + +*** Source C + + #+begin_src c :tangle (eval c) :comments org +#include +#include "qmckl.h" + +qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, + const uint64_t Dim, + const uint64_t N_updates, + const double* Updates, + const uint64_t* Updates_index, + double * Slater_inv) { +// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. +// std::cerr << "Called qmckl_sherman_morrison_woodbury_3 with " << N_updates +// << " updates" << std::endl; +// #endif + + qmckl_context local_context; + local_context = qmckl_context_create(); + qmckl_exit_code rc; + + uint64_t n_of_3blocks = N_updates / 3; + uint64_t remainder = N_updates % 3; + uint64_t length_3block = 3 * Dim; + uint64_t length_2block = 2 * Dim; + uint64_t length_1block = 1 * Dim; + + // Apply first 3*n_of_3blocks updates in n_of_3blocks blocks of 3 updates with + // Woodbury 3x3 kernel + double later_updates[Dim * N_updates]; + uint64_t later_index[N_updates]; + uint64_t later = 0; + if (n_of_3blocks > 0) { + for (uint64_t i = 0; i < n_of_3blocks; i++) { + double *Updates_3block = &Updates[i * length_3block]; + uint64_t *Updates_index_3block = &Updates_index[i * 3]; + rc = qmckl_woodbury_3_c(local_context, Dim, Updates_3block, Updates_index_3block, Slater_inv); + if (rc != 0) { // Send the entire block to slagel_splitting + uint64_t l = 0; + rc = qmckl_slagel_splitting_c(Dim, 3, Updates_3block, Updates_index_3block, + Slater_inv, later_updates + (Dim * later), later_index + later, &l); + later = later + l; + } + } + } + + if (remainder == 2) { // Apply last remaining block of 2 updates with Woodbury 2x2 kernel + double *Updates_2block = &Updates[n_of_3blocks * length_3block]; + uint64_t *Updates_index_2block = &Updates_index[3 * n_of_3blocks]; + rc = qmckl_woodbury_2_c(local_context, Dim, Updates_2block, Updates_index_2block, Slater_inv); + if (rc != 0) { // Send the entire block to slagel_splitting + uint64_t l = 0; + rc = qmckl_slagel_splitting_c(Dim, 2, Updates_2block, Updates_index_2block, + Slater_inv, later_updates + (Dim * later), later_index + later, &l); + later = later + l; + } + } + else if (remainder == 1) { // Apply last remaining update with slagel_splitting + double *Updates_1block = &Updates[n_of_3blocks * length_3block]; + uint64_t *Updates_index_1block = &Updates_index[3 * n_of_3blocks]; + uint64_t l = 0; + rc = qmckl_slagel_splitting_c(Dim, 1, Updates_1block, Updates_index_1block, + Slater_inv, later_updates + (Dim * later), later_index + later, &l); + later = later + l; + } + + if (later > 0) { + rc = qmckl_sherman_morrison_splitting_c(local_context, Dim, later, later_updates, later_index, Slater_inv); + } +} + + #+end_src + +*** Performance... + +** C interface :noexport: + + #+CALL: generate_c_interface(table=qmckl_sherman_morrison_smw32s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + + #+CALL: generate_f_interface(table=qmckl_sherman_morrison_smw32s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + +*** Test :noexport: + +[TODO: FMJC] Write tests for the Sherman-Morrison part. + + + #+begin_src c :tangle (eval c_test) +const uint64_t smw32s_Dim = 3; +const uint64_t smw32s_N_updates = 3; +const uint64_t smw32s_Updates_index[3] = {1, 1, 1}; +const double smw32s_Updates[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; +double smw32s_Slater_inv[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; + +// [TODO : FMJC ] add realistic tests + +rc = qmckl_sherman_morrison_smw32s_c(context, smw32s_Dim, smw32s_N_updates, + smw32s_Updates, smw32s_Updates_index, smw32s_Slater_inv); +assert(rc == QMCKL_SUCCESS); + #+end_src + * End of files From d2eb9f5a5d9e8d05175b1b0569e198fe1d4cf565 Mon Sep 17 00:00:00 2001 From: vijay gopal chilkuri Date: Fri, 23 Jul 2021 19:58:24 +0200 Subject: [PATCH 26/50] Added interfaces and fortran versions and fixed return for smw2s. #25 --- org/qmckl_sherman_morrison_woodbury.org | 140 ++++++++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index e2e93d9..254a780 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -1042,9 +1042,34 @@ unless the last original update causes a singular Slater-matrix. #+CALL: generate_c_header(table=qmckl_sherman_morrison_smw2s_args,rettyp=get_value("CRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src c :tangle (eval h_func) :comments org + qmckl_exit_code qmckl_sherman_morrison_smw2s_c ( + const qmckl_context context, + const uint64_t Dim, + const uint64_t N_updates, + const double* Updates, + const uint64_t* Updates_index, + double* Slater_inv ); + #+end_src + *** Source Fortran + #+begin_src f90 :tangle (eval f) +integer function qmckl_sherman_morrison_smw2s_f(context, Slater_inv, Dim, N_updates, & + Updates, Updates_index) result(info) + use qmckl + implicit none + integer(qmckl_context) , intent(in) :: context + integer*8 , intent(in), value :: Dim, N_updates + integer*8 , intent(in) :: Updates_index(N_updates) + real*8 , intent(in) :: Updates(N_updates*Dim) + real*8 , intent(inout) :: Slater_inv(Dim*Dim) + info = qmckl_sherman_morrison_smw2s (context, Dim, N_updates, Updates, Updates_index, Slater_inv) +end function qmckl_sherman_morrison_smw2s_f + #+end_src + *** Source C @@ -1103,6 +1128,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw2s_c(const qmckl_context context, if (later > 0) { rc = qmckl_sherman_morrison_splitting_c(local_context, Dim, later, later_updates, later_index, Slater_inv); } + return QMCKL_SUCCESS; } #+end_src @@ -1113,8 +1139,52 @@ qmckl_exit_code qmckl_sherman_morrison_smw2s_c(const qmckl_context context, #+CALL: generate_c_interface(table=qmckl_sherman_morrison_smw2s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src f90 :tangle (eval f) :comments org :exports none + integer(c_int32_t) function qmckl_sherman_morrison_smw2s & + (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & + bind(C) result(info) + + use, intrinsic :: iso_c_binding + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) , value :: Dim + integer (c_int64_t) , intent(in) , value :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + integer(c_int32_t), external :: qmckl_sherman_morrison_smw2s_c + info = qmckl_sherman_morrison_smw2s_c & + (context, Dim, N_updates, Updates, Updates_index, Slater_inv) + + end function qmckl_sherman_morrison_smw2s + #+end_src + #+CALL: generate_f_interface(table=qmckl_sherman_morrison_smw2s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src f90 :tangle (eval fh_func) :comments org :exports none + interface + integer(c_int32_t) function qmckl_sherman_morrison_smw2s & + (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & + bind(C) + use, intrinsic :: iso_c_binding + import + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) , value :: Dim + integer (c_int64_t) , intent(in) , value :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + end function qmckl_sherman_morrison_smw2s + end interface + #+end_src + *** Test :noexport: [TODO: FMJC] Write tests for the Sherman-Morrison part. @@ -1176,9 +1246,35 @@ unless the last original update causes a singular Slater-matrix. #+CALL: generate_c_header(table=qmckl_sherman_morrison_smw32s_args,rettyp=get_value("CRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src c :tangle (eval h_func) :comments org + qmckl_exit_code qmckl_sherman_morrison_smw32s_c ( + const qmckl_context context, + const uint64_t Dim, + const uint64_t N_updates, + const double* Updates, + const uint64_t* Updates_index, + double* Slater_inv ); + #+end_src + *** Source Fortran + #+begin_src f90 :tangle (eval f) +integer function qmckl_sherman_morrison_smw32s_f(context, Slater_inv, Dim, N_updates, & + Updates, Updates_index) result(info) + use qmckl + implicit none + integer(qmckl_context) , intent(in) :: context + integer*8 , intent(in), value :: Dim, N_updates + integer*8 , intent(in) :: Updates_index(N_updates) + real*8 , intent(in) :: Updates(N_updates*Dim) + real*8 , intent(inout) :: Slater_inv(Dim*Dim) + !logical, external :: qmckl_sherman_morrison_f + info = qmckl_sherman_morrison_smw32s(context, Dim, N_updates, Updates, Updates_index, Slater_inv) +end function qmckl_sherman_morrison_smw32s_f + #+end_src + *** Source C @@ -1259,8 +1355,52 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, #+CALL: generate_c_interface(table=qmckl_sherman_morrison_smw32s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src f90 :tangle (eval f) :comments org :exports none + integer(c_int32_t) function qmckl_sherman_morrison_smw32s & + (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & + bind(C) result(info) + + use, intrinsic :: iso_c_binding + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) , value :: Dim + integer (c_int64_t) , intent(in) , value :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + integer(c_int32_t), external :: qmckl_sherman_morrison_smw32s_c + info = qmckl_sherman_morrison_smw32s_c & + (context, Dim, N_updates, Updates, Updates_index, Slater_inv) + + end function qmckl_sherman_morrison_smw32s + #+end_src + #+CALL: generate_f_interface(table=qmckl_sherman_morrison_smw32s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src f90 :tangle (eval fh_func) :comments org :exports none + interface + integer(c_int32_t) function qmckl_sherman_morrison_smw32s & + (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & + bind(C) + use, intrinsic :: iso_c_binding + import + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) , value :: Dim + integer (c_int64_t) , intent(in) , value :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + end function qmckl_sherman_morrison_smw32s + end interface + #+end_src + *** Test :noexport: [TODO: FMJC] Write tests for the Sherman-Morrison part. From decd977fffe07a34336903c105d0d18f939e964c Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Mon, 26 Jul 2021 12:19:29 +0200 Subject: [PATCH 27/50] Added mixed kernel with Woodbury 3x3 and update splitting. #25 --- org/qmckl_sherman_morrison_woodbury.org | 214 +++++++++++++++++++++++- 1 file changed, 211 insertions(+), 3 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 254a780..79d491b 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -30,6 +30,7 @@ int main() { #+end_src + * Sherman-Morrison Helper Functions Helper functions that are used by the Sherman-Morrison-Woodbury @@ -1000,6 +1001,7 @@ rc = qmckl_sherman_morrison_splitting_c(context, splitting_Dim, splitting_N_upda assert(rc == QMCKL_SUCCESS); #+end_src + * Sherman-Morrison with Woodbury 2x2 and update splitting This is like naïve Sherman-Morrising, but whenever a denominator is @@ -1095,7 +1097,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw2s_c(const qmckl_context context, uint64_t n_of_2blocks = N_updates / 2; uint64_t remainder = N_updates % 2; uint64_t length_2block = 2 * Dim; - uint64_t length_1block = 1 * Dim; + // uint64_t length_1block = 1 * Dim; // Apply first 2*n_of_2blocks updates in n_of_2blocks blocks of 2 updates with // Woodbury 2x2 kernel @@ -1204,6 +1206,211 @@ rc = qmckl_sherman_morrison_smw2s_c(context, smw2s_Dim, smw2s_N_updates, assert(rc == QMCKL_SUCCESS); #+end_src + +* Sherman-Morrison with Woodbury 3x3 and update splitting + +This is like naïve Sherman-Morrising, but whenever a denominator is +found that is too close to zero the update is split in half. Then one +half is applied immediately and the other have is ket for later. When +all the updates have been processed, the list of split updates that +have been kept for later are processed. If again applying an update +results in a denominator that is too close to zero, it is split in +half again. One half is applied immediately and one half is kept for +later. The algorithm is done when no more updates have been kept for +later. This recursion will always end in a finite number of steps, +unless the last original update causes a singular Slater-matrix. + +** ~qmckl_sherman_morrison_smw3s~ + :PROPERTIES: + :Name: qmckl_sherman_morrison_smw3s + :CRetType: qmckl_exit_code + :FRetType: qmckl_exit_code + :END: + + This is the simplest of the available Sherman-Morrison-Woodbury + kernels in QMCkl. It applies rank-1 updates one by one in the order + that is given. It only checks if the denominator in the + Sherman-Morrison formula is not too close to zero (and exit with an + error if it does) during the application of an update. + + #+NAME: qmckl_sherman_morrison_smw3s_args + | qmckl_context | context | in | Global state | + | uint64_t | Dim | in | Leading dimension of Slater_inv | + | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | + | double | Updates[N_updates*Dim] | in | Array containing the updates | + | uint64_t | Updates_index[N_updates] | in | Array containing the rank-1 updates | + | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | + +*** Requirements + + Add description of the input variables. (see for e.g. qmckl_distance.org) + +*** C header + + #+CALL: generate_c_header(table=qmckl_sherman_morrison_smw3s_args,rettyp=get_value("CRetType"),fname=get_value("Name")) + + #+RESULTS: + #+begin_src c :tangle (eval h_func) :comments org + qmckl_exit_code qmckl_sherman_morrison_smw3s_c ( + const qmckl_context context, + const uint64_t Dim, + const uint64_t N_updates, + const double* Updates, + const uint64_t* Updates_index, + double* Slater_inv ); + #+end_src + + +*** Source Fortran + + #+begin_src f90 :tangle (eval f) +integer function qmckl_sherman_morrison_smw3s_f(context, Slater_inv, Dim, N_updates, & + Updates, Updates_index) result(info) + use qmckl + implicit none + integer(qmckl_context) , intent(in) :: context + integer*8 , intent(in), value :: Dim, N_updates + integer*8 , intent(in) :: Updates_index(N_updates) + real*8 , intent(in) :: Updates(N_updates*Dim) + real*8 , intent(inout) :: Slater_inv(Dim*Dim) + !logical, external :: qmckl_sherman_morrison_f + info = qmckl_sherman_morrison_smw3s(context, Dim, N_updates, Updates, Updates_index, Slater_inv) +end function qmckl_sherman_morrison_smw3s_f + #+end_src + + +*** Source C + + #+begin_src c :tangle (eval c) :comments org +#include +#include "qmckl.h" + +qmckl_exit_code qmckl_sherman_morrison_smw3s_c(const qmckl_context context, + const uint64_t Dim, + const uint64_t N_updates, + const double* Updates, + const uint64_t* Updates_index, + double * Slater_inv) { +// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. +// std::cerr << "Called qmckl_sherman_morrison_woodbury_3 with " << N_updates +// << " updates" << std::endl; +// #endif + + qmckl_context local_context; + local_context = qmckl_context_create(); + qmckl_exit_code rc; + + uint64_t n_of_3blocks = N_updates / 3; + uint64_t remainder = N_updates % 3; + uint64_t length_3block = 3 * Dim; + + // Apply first 3*n_of_3blocks updates in n_of_3blocks blocks of 3 updates with + // Woodbury 3x3 kernel + double later_updates[Dim * N_updates]; + uint64_t later_index[N_updates]; + uint64_t later = 0; + if (n_of_3blocks > 0) { + for (uint64_t i = 0; i < n_of_3blocks; i++) { + double *Updates_3block = &Updates[i * length_3block]; + uint64_t *Updates_index_3block = &Updates_index[i * 3]; + rc = qmckl_woodbury_3_c(local_context, Dim, Updates_3block, Updates_index_3block, Slater_inv); + if (rc != 0) { // Send the entire block to slagel_splitting + uint64_t l = 0; + rc = qmckl_slagel_splitting_c(Dim, 3, Updates_3block, Updates_index_3block, + Slater_inv, later_updates + (Dim * later), later_index + later, &l); + later = later + l; + } + } + } + + if (remainder != 0) { // Apply last remaining block of 2 updates with Woodbury 2x2 kernel + double *Updates_remainder_block = &Updates[n_of_3blocks * length_3block]; + uint64_t *Updates_index_remainder_block = &Updates_index[3 * n_of_3blocks]; + uint64_t l = 0; + rc = qmckl_slagel_splitting_c(Dim, remainder, Updates_remainder_block, Updates_index_remainder_block, + Slater_inv, later_updates + (Dim * later), later_index + later, &l); + later = later + l; + } + + if (later > 0) { + rc = qmckl_sherman_morrison_splitting_c(local_context, Dim, later, later_updates, later_index, Slater_inv); + } +} + + #+end_src + +*** Performance... + +** C interface :noexport: + + #+CALL: generate_c_interface(table=qmckl_sherman_morrison_smw3s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + + #+RESULTS: + #+begin_src f90 :tangle (eval f) :comments org :exports none + integer(c_int32_t) function qmckl_sherman_morrison_smw3s & + (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & + bind(C) result(info) + + use, intrinsic :: iso_c_binding + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) , value :: Dim + integer (c_int64_t) , intent(in) , value :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + integer(c_int32_t), external :: qmckl_sherman_morrison_smw3s_c + info = qmckl_sherman_morrison_smw3s_c & + (context, Dim, N_updates, Updates, Updates_index, Slater_inv) + + end function qmckl_sherman_morrison_smw3s + #+end_src + + #+CALL: generate_f_interface(table=qmckl_sherman_morrison_smw3s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + + #+RESULTS: + #+begin_src f90 :tangle (eval fh_func) :comments org :exports none + interface + integer(c_int32_t) function qmckl_sherman_morrison_smw3s & + (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & + bind(C) + use, intrinsic :: iso_c_binding + import + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) , value :: Dim + integer (c_int64_t) , intent(in) , value :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + end function qmckl_sherman_morrison_smw3s + end interface + #+end_src + +*** Test :noexport: + +[TODO: FMJC] Write tests for the Sherman-Morrison part. + + + #+begin_src c :tangle (eval c_test) +const uint64_t smw32s_Dim = 3; +const uint64_t smw32s_N_updates = 3; +const uint64_t smw32s_Updates_index[3] = {1, 1, 1}; +const double smw32s_Updates[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; +double smw32s_Slater_inv[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; + +// [TODO : FMJC ] add realistic tests + +rc = qmckl_sherman_morrison_smw3s_c(context, smw32s_Dim, smw32s_N_updates, + smw32s_Updates, smw32s_Updates_index, smw32s_Slater_inv); +assert(rc == QMCKL_SUCCESS); + #+end_src + + * Sherman-Morrison with Woodbury 3x3, 2x2 and update splitting This is like naïve Sherman-Morrising, but whenever a denominator is @@ -1300,8 +1507,8 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, uint64_t n_of_3blocks = N_updates / 3; uint64_t remainder = N_updates % 3; uint64_t length_3block = 3 * Dim; - uint64_t length_2block = 2 * Dim; - uint64_t length_1block = 1 * Dim; + // uint64_t length_2block = 2 * Dim; + // uint64_t length_1block = 1 * Dim; // Apply first 3*n_of_3blocks updates in n_of_3blocks blocks of 3 updates with // Woodbury 3x3 kernel @@ -1422,6 +1629,7 @@ assert(rc == QMCKL_SUCCESS); + * End of files #+begin_src c :comments link :tangle (eval c_test) From 41be86fe594f561247986cd75dc4557e0bc5e6de Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Mon, 26 Jul 2021 17:41:21 +0200 Subject: [PATCH 28/50] Removed dependency on qmckl_threshhold() and the accompanying preprocessor definition. The break-down threshold now has to be passed explicitly as a function argument. #25 --- org/qmckl_sherman_morrison_woodbury.org | 278 +++++++++++++----------- 1 file changed, 146 insertions(+), 132 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 79d491b..453fa8f 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -18,9 +18,6 @@ Low- and high-level functions that use the Sherman-Morrison and #include "config.h" #endif #include -#ifndef THRESHOLD -#define THRESHOLD 1e-3 -#endif int main() { qmckl_context context; @@ -31,63 +28,12 @@ int main() { -* Sherman-Morrison Helper Functions +* Helper Functions Helper functions that are used by the Sherman-Morrison-Woodbury kernels. These functions should only be used in the context of these kernels. -** ~qmckl_threshold~ - :PROPERTIES: - :Name: qmckl_threshold - :CRetType: double - :FRetType: double precision - :END: - - This function is used to set the threshold value that is used in the kernels to determine if a matrix is invertable or not. In the Sherman-Morrison kernels this is determined by comparing the denominator in the Sherman-Morrison formula to the value set in threshold. If the value is smaller than the threshold value it means the matrix is not invertable. In the Woodbury kernels the threshold value is compared with the value of the determinant of the update matrix. - - #+NAME: qmckl_threshold_args - | double | thresh | inout | Threshold | - -*** Requirements - - Add description of the input variables. (see for e.g. qmckl_distance.org) - -*** C header - - #+CALL: generate_c_header(table=qmckl_threshold_args,rettyp=get_value("CRetType"),fname=get_value("Name")) - - #+RESULTS: - #+begin_src c :tangle (eval h_func) :comments org -// Sherman-Morrison-Woodbury break-down threshold -#ifndef THRESHOLD -#define THRESHOLD 1e-3 -#endif - - qmckl_exit_code qmckl_threshold_c ( - double* const thresh ); - #+end_src - -*** Source Fortran - -*** Source C - - #+begin_src c :tangle (eval c) :comments org -#include -#include "qmckl.h" - -// Sherman-Morrison-Woodbury break-down threshold -qmckl_exit_code qmckl_threshold_c(double* const threshold) { - *threshold = THRESHOLD; -// #ifdef DEBUG -// std::cerr << "Break-down threshold set to: " << threshold << std::endl; -// #endif -return QMCKL_SUCCESS; -} - #+end_src - -*** Performance - ** ~qmckl_slagel_splitting~ :PROPERTIES: :Name: qmckl_slagel_splitting @@ -102,6 +48,7 @@ return QMCKL_SUCCESS; | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | | double | Updates[N_updates*Dim] | in | Array containing the rank-1 updates | | uint64_t | Updates_index[N_updates] | in | Array containing positions of the rank-1 updates | + | double | breakdown | in | Break-down parameter on which to fail or not | | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse Slater-matrix | | double | later_updates[Dim * N_updates] | inout | Array containing the split updates for later | | uint64_t | later_index[N_updates] | inout | Array containing the positions of the split updates for later | @@ -116,6 +63,20 @@ return QMCKL_SUCCESS; #+CALL: generate_c_header(table=qmckl_slagel_splitting_args,rettyp=get_value("CRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src c :tangle (eval h_func) :comments org + qmckl_exit_code qmckl_slagel_splitting_c ( + const uint64_t Dim, + const uint64_t N_updates, + const double* Updates, + const uint64_t* Updates_index, + const double breakdown, + double* Slater_inv, + double* later_updates, + uint64_t* later_index, + uint64_t* later ); + #+end_src + *** Source Fortran *** Source C @@ -129,6 +90,7 @@ qmckl_exit_code qmckl_slagel_splitting_c(uint64_t Dim, uint64_t N_updates, const double *Updates, const uint64_t *Updates_index, + const double breakdown, double *Slater_inv, double *later_updates, uint64_t *later_index, @@ -153,9 +115,7 @@ qmckl_exit_code qmckl_slagel_splitting_c(uint64_t Dim, // Denominator double den = 1 + C[Updates_index[l] - 1]; - double thresh = 0.0; - qmckl_exit_code rc = qmckl_threshold_c(&thresh); - if (fabs(den) < thresh) { + if (fabs(den) < breakdown) { // U_l = U_l / 2 (do the split) for (uint64_t i = 0; i < Dim; i++) { @@ -194,17 +154,40 @@ qmckl_exit_code qmckl_slagel_splitting_c(uint64_t Dim, ** C interface :noexport: - #+CALL: generate_f_interface(table=qmckl_threshold_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - #+CALL: generate_c_interface(table=qmckl_slagel_splitting_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src f90 :tangle (eval f) :comments org :exports none + integer(c_int32_t) function qmckl_slagel_splitting & + (Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv, later_updates, later_index, later) & + bind(C) result(info) + + use, intrinsic :: iso_c_binding + implicit none + + integer (c_int64_t) , intent(in) , value :: Dim + integer (c_int64_t) , intent(in) , value :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(in) , value :: breakdown + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + real (c_double ) , intent(inout) :: later_updates(Dim * N_updates) + integer (c_int64_t) , intent(inout) :: later_index(N_updates) + integer (c_int64_t) , intent(inout) :: later + + integer(c_int32_t), external :: qmckl_slagel_splitting_c + info = qmckl_slagel_splitting_c & + (Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv, later_updates, later_index, later) + + end function qmckl_slagel_splitting + #+end_src + *** Test :noexport: [TODO: FMJC] Write tests for the Sherman-Morrison part. - * Naïve Sherman-Morrison ** ~qmckl_sherman_morrison~ @@ -226,6 +209,7 @@ qmckl_exit_code qmckl_slagel_splitting_c(uint64_t Dim, | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | | double | Updates[N_updates*Dim] | in | Array containing the updates | | uint64_t | Updates_index[N_updates] | in | Array containing the rank-1 updates | + | double | breakdown | in | Break-down parameter on which to fail or not | | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | *** Requirements @@ -244,23 +228,25 @@ qmckl_exit_code qmckl_slagel_splitting_c(uint64_t Dim, const uint64_t N_updates, const double* Updates, const uint64_t* Updates_index, + const double breakdown, double* Slater_inv ); #+end_src *** Source Fortran #+begin_src f90 :tangle (eval f) -integer function qmckl_sherman_morrison_f(context, Slater_inv, Dim, N_updates, & - Updates, Updates_index) result(info) +integer function qmckl_sherman_morrison_f(context, Dim, N_updates, & + Updates, Updates_index, breakdown, Slater_inv) result(info) use qmckl implicit none integer(qmckl_context) , intent(in) :: context integer*8 , intent(in), value :: Dim, N_updates integer*8 , intent(in) :: Updates_index(N_updates) real*8 , intent(in) :: Updates(N_updates*Dim) + real*8 , intent(in) :: breakdown real*8 , intent(inout) :: Slater_inv(Dim*Dim) !logical, external :: qmckl_sherman_morrison_f - info = qmckl_sherman_morrison(context, Dim, N_updates, Updates, Updates_index, Slater_inv) + info = qmckl_sherman_morrison(context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) end function qmckl_sherman_morrison_f #+end_src @@ -275,6 +261,7 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, const uint64_t N_updates, const double* Updates, const uint64_t* Updates_index, + const double breakdown, double * Slater_inv) { // #ifdef DEBUG // std::cerr << "Called qmckl_sherman_morrison with " << N_updates << " updates" << std::endl; @@ -296,9 +283,7 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, // Denominator double den = 1 + C[Updates_index[l] - 1]; - double thresh = 0.0; - qmckl_exit_code rc = qmckl_threshold_c(&thresh); - if (fabs(den) < thresh) { + if (fabs(den) < breakdown) { return QMCKL_FAILURE; } double iden = 1 / den; @@ -334,7 +319,7 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, #+RESULTS: #+begin_src f90 :tangle (eval f) :comments org :exports none integer(c_int32_t) function qmckl_sherman_morrison & - (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & + (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) & bind(C) result(info) use, intrinsic :: iso_c_binding @@ -345,11 +330,12 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, integer (c_int64_t) , intent(in) , value :: N_updates real (c_double ) , intent(in) :: Updates(N_updates*Dim) integer (c_int64_t) , intent(in) :: Updates_index(N_updates) - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + real (c_double ) , intent(in) :: breakdown + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) integer(c_int32_t), external :: qmckl_sherman_morrison_c info = qmckl_sherman_morrison_c & - (context, Dim, N_updates, Updates, Updates_index, Slater_inv) + (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) end function qmckl_sherman_morrison #+end_src @@ -360,7 +346,7 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, #+begin_src f90 :tangle (eval fh_func) :comments org :exports none interface integer(c_int32_t) function qmckl_sherman_morrison & - (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & + (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) & bind(C) use, intrinsic :: iso_c_binding import @@ -371,6 +357,7 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, integer (c_int64_t) , intent(in) , value :: N_updates real (c_double ) , intent(in) :: Updates(N_updates*Dim) integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(in) :: breakdown real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) end function qmckl_sherman_morrison @@ -387,11 +374,12 @@ const uint64_t Dim = 2; const uint64_t N_updates = 2; const uint64_t Updates_index[2] = {0, 0}; const double Updates[4] = {0.0, 0.0, 0.0, 0.0}; +const double breakdown = 1e-3; double Slater_inv[4] = {0.0, 0.0, 0.0, 0.0}; // [TODO : FMJC ] add realistic tests -rc = qmckl_sherman_morrison_c(context, Dim, N_updates, Updates, Updates_index, Slater_inv); +rc = qmckl_sherman_morrison_c(context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv); assert(rc == QMCKL_SUCCESS); #+end_src @@ -418,6 +406,7 @@ This is the Woodbury 3x3 kernel. | uint64_t | Dim | in | Leading dimension of Slater_inv | | double | Updates[2*Dim] | in | Array containing the updates | | uint64_t | Updates_index[2] | in | Array containing the rank-1 updates | + | double | breakdown | in | Break-down parameter on which to fail or not | | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | *** Requirements @@ -435,23 +424,25 @@ This is the Woodbury 3x3 kernel. const uint64_t Dim, const double* Updates, const uint64_t* Updates_index, + const double breakdown, double* Slater_inv ); #+end_src *** Source Fortran #+begin_src f90 :tangle (eval f) -integer function qmckl_woodbury_2_f(context, Slater_inv, Dim, & - Updates, Updates_index) result(info) +integer function qmckl_woodbury_2_f(context, Dim, & + Updates, Updates_index, breakdown, Slater_inv) result(info) use qmckl implicit none integer(qmckl_context) , intent(in) :: context integer*8 , intent(in), value :: Dim integer*8 , intent(in) :: Updates_index(2) real*8 , intent(in) :: Updates(2*Dim) + real*8 , intent(in) :: breakdown real*8 , intent(inout) :: Slater_inv(Dim*Dim) !logical, external :: qmckl_woodbury_2_f - info = qmckl_woodbury_2(context, Dim, Updates, Updates_index, Slater_inv) + info = qmckl_woodbury_2(context, Dim, Updates, Updates_index, breakdown, Slater_inv) end function qmckl_woodbury_2_f #+end_src @@ -465,6 +456,7 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, const uint64_t Dim, const double* Updates, const uint64_t* Updates_index, + const double breakdown, double * Slater_inv) { /* C := S^{-1} * U, dim x 2 @@ -498,9 +490,7 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, // Check if determinant of inverted matrix is not zero double det = B0 * B3 - B1 * B2; - double thresh = 0.0; - qmckl_exit_code rc = qmckl_threshold_c(&thresh); - if (fabs(det) < thresh) { + if (fabs(det) < breakdown) { return QMCKL_FAILURE; } @@ -544,7 +534,7 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, #+RESULTS: #+begin_src f90 :tangle (eval f) :comments org :exports none integer(c_int32_t) function qmckl_woodbury_2 & - (context, Dim, Updates, Updates_index, Slater_inv) & + (context, Dim, Updates, Updates_index, breakdown, Slater_inv) & bind(C) result(info) use, intrinsic :: iso_c_binding @@ -554,11 +544,12 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, integer (c_int64_t) , intent(in) , value :: Dim real (c_double ) , intent(in) :: Updates(2*Dim) integer (c_int64_t) , intent(in) :: Updates_index(2) + real (c_double ) , intent(in) :: breakdown real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) integer(c_int32_t), external :: qmckl_woodbury_2_c info = qmckl_woodbury_2_c & - (context, Dim, Updates, Updates_index, Slater_inv) + (context, Dim, Updates, Updates_index, breakdown, Slater_inv) end function qmckl_woodbury_2 #+end_src @@ -569,7 +560,7 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, #+begin_src f90 :tangle (eval fh_func) :comments org :exports none interface integer(c_int32_t) function qmckl_woodbury_2 & - (context, Dim, Updates, Updates_index, Slater_inv) & + (context, Dim, Updates, Updates_index, breakdown, Slater_inv) & bind(C) use, intrinsic :: iso_c_binding import @@ -579,6 +570,7 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, integer (c_int64_t) , intent(in) , value :: Dim real (c_double ) , intent(in) :: Updates(2*Dim) integer (c_int64_t) , intent(in) :: Updates_index(2) + real (c_double ) , intent(in) :: breakdown real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) end function qmckl_woodbury_2 @@ -594,11 +586,12 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, const uint64_t woodbury_Dim = 2; const uint64_t woodbury_Updates_index[2] = {1, 1}; const double woodbury_Updates[4] = {1.0, 1.0, 1.0, 1.0}; +const double woodbury_breakdown = 1e-3; double woodbury_Slater_inv[4] = {1.0, 1.0, 1.0, 1.0}; // [TODO : FMJC ] add realistic tests -rc = qmckl_woodbury_2_c(context, woodbury_Dim, woodbury_Updates, woodbury_Updates_index, woodbury_Slater_inv); +rc = qmckl_woodbury_2_c(context, woodbury_Dim, woodbury_Updates, woodbury_Updates_index, woodbury_breakdown, woodbury_Slater_inv); assert(rc == QMCKL_SUCCESS); #+end_src @@ -625,6 +618,7 @@ This is the Woodbury 3x3 kernel. | uint64_t | Dim | in | Leading dimension of Slater_inv | | double | Updates[3*Dim] | in | Array containing the updates | | uint64_t | Updates_index[3] | in | Array containing the rank-1 updates | + | double | breakdown | in | Break-down parameter on which to fail or not | | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | *** Requirements @@ -642,26 +636,28 @@ This is the Woodbury 3x3 kernel. const uint64_t Dim, const double* Updates, const uint64_t* Updates_index, + const double breakdown, double* Slater_inv ); #+end_src *** Source Fortran #+begin_src f90 :tangle (eval f) -integer function qmckl_woodbury_3_f(context, Slater_inv, Dim, & - Updates, Updates_index) result(info) +integer function qmckl_woodbury_3_f(context, Dim, & + Updates, Updates_index, breakdown, Slater_inv) result(info) use qmckl implicit none integer(qmckl_context) , intent(in) :: context integer*8 , intent(in), value :: Dim integer*8 , intent(in) :: Updates_index(3) real*8 , intent(in) :: Updates(3*Dim) + real*8 , intent(in) :: breakdown real*8 , intent(inout) :: Slater_inv(Dim*Dim) !logical, external :: qmckl_woodbury_3_f - info = qmckl_woodbury_2(context, Dim, Updates, Updates_index, Slater_inv) + info = qmckl_woodbury_3(context, Dim, Updates, Updates_index, breakdown, Slater_inv) end function qmckl_woodbury_3_f #+end_src - + *** Source C #+begin_src c :tangle (eval c) :comments org @@ -672,6 +668,7 @@ qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, const uint64_t Dim, const double* Updates, const uint64_t* Updates_index, + const double breakdown, double * Slater_inv) { /* C := S^{-1} * U, dim x 3 @@ -713,9 +710,7 @@ qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, double det; det = B0 * (B4 * B8 - B5 * B7) - B1 * (B3 * B8 - B5 * B6) + B2 * (B3 * B7 - B4 * B6); - double thresh = 0.0; - qmckl_exit_code rc = qmckl_threshold_c(&thresh); - if (fabs(det) < thresh) { + if (fabs(det) < breakdown) { return QMCKL_FAILURE; } @@ -764,7 +759,7 @@ qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, #+RESULTS: #+begin_src f90 :tangle (eval f) :comments org :exports none integer(c_int32_t) function qmckl_woodbury_3 & - (context, Dim, Updates, Updates_index, Slater_inv) & + (context, Dim, Updates, Updates_index, breakdown, Slater_inv) & bind(C) result(info) use, intrinsic :: iso_c_binding @@ -774,11 +769,12 @@ qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, integer (c_int64_t) , intent(in) , value :: Dim real (c_double ) , intent(in) :: Updates(3*Dim) integer (c_int64_t) , intent(in) :: Updates_index(3) + real (c_double ) , intent(in) , value :: breakdown real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) integer(c_int32_t), external :: qmckl_woodbury_3_c info = qmckl_woodbury_3_c & - (context, Dim, Updates, Updates_index, Slater_inv) + (context, Dim, Updates, Updates_index, breakdown, Slater_inv) end function qmckl_woodbury_3 #+end_src @@ -789,7 +785,7 @@ qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, #+begin_src f90 :tangle (eval fh_func) :comments org :exports none interface integer(c_int32_t) function qmckl_woodbury_3 & - (context, Dim, Updates, Updates_index, Slater_inv) & + (context, Dim, Updates, Updates_index, breakdown, Slater_inv) & bind(C) use, intrinsic :: iso_c_binding import @@ -799,6 +795,7 @@ qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, integer (c_int64_t) , intent(in) , value :: Dim real (c_double ) , intent(in) :: Updates(3*Dim) integer (c_int64_t) , intent(in) :: Updates_index(3) + real (c_double ) , intent(in) , value :: breakdown real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) end function qmckl_woodbury_3 @@ -814,17 +811,18 @@ qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, const uint64_t woodbury3_Dim = 3; const uint64_t woodbury3_Updates_index[3] = {1, 1, 1}; const double woodbury3_Updates[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; +const double woodbury3_breakdown = 1e-3; double woodbury3_Slater_inv[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; // [TODO : FMJC ] add realistic tests -rc = qmckl_woodbury_3_c(context, woodbury3_Dim, woodbury3_Updates, woodbury3_Updates_index, woodbury3_Slater_inv); +rc = qmckl_woodbury_3_c(context, woodbury3_Dim, woodbury3_Updates, woodbury3_Updates_index, woodbury3_breakdown, woodbury3_Slater_inv); assert(rc == QMCKL_SUCCESS); #+end_src * Sherman-Morrison with update splitting - + This is like naïve Sherman-Morrising, but whenever a denominator is found that is too close to zero the update is split in half. Then one half is applied immediately and the other have is ket for later. When @@ -855,6 +853,7 @@ unless the last original update causes a singular Slater-matrix. | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | | double | Updates[N_updates*Dim] | in | Array containing the updates | | uint64_t | Updates_index[N_updates] | in | Array containing the rank-1 updates | + | double | breakdown | in | Break-down parameter on which to fail or not | | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | *** Requirements @@ -873,22 +872,24 @@ unless the last original update causes a singular Slater-matrix. const uint64_t N_updates, const double* Updates, const uint64_t* Updates_index, + const double breakdown, double* Slater_inv ); #+end_src *** Source Fortran #+begin_src f90 :tangle (eval f) -integer function qmckl_sherman_morrison_splitting_f(context, Slater_inv, Dim, N_updates, & - Updates, Updates_index) result(info) +integer function qmckl_sherman_morrison_splitting_f(context, Dim, N_updates, & + Updates, Updates_index, breakdown, Slater_inv) result(info) use qmckl implicit none integer(qmckl_context) , intent(in) :: context integer*8 , intent(in), value :: Dim, N_updates integer*8 , intent(in) :: Updates_index(N_updates) real*8 , intent(in) :: Updates(N_updates*Dim) + real*8 , intent(in) :: breakdown real*8 , intent(inout) :: Slater_inv(Dim*Dim) - info = qmckl_sherman_morrison_splitting(context, Dim, N_updates, Updates, Updates_index, Slater_inv) + info = qmckl_sherman_morrison_splitting(context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) end function qmckl_sherman_morrison_splitting_f #+end_src @@ -904,6 +905,7 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, const uint64_t N_updates, const double* Updates, const uint64_t* Updates_index, + const double breakdown, double * Slater_inv) { // #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. // std::cerr << "Called qmckl_sherman_morrison_splitting with " << N_updates << " updates" << std::endl; @@ -918,11 +920,11 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, uint64_t later = 0; rc = qmckl_slagel_splitting_c(Dim, N_updates, Updates, Updates_index, - Slater_inv, later_updates, later_index, &later); + breakdown, Slater_inv, later_updates, later_index, &later); if (later > 0) { rc = qmckl_sherman_morrison_splitting_c(local_context, Dim, later, - later_updates, later_index, Slater_inv); + later_updates, later_index, breakdown, Slater_inv); } return QMCKL_SUCCESS; @@ -939,7 +941,7 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, #+RESULTS: #+begin_src f90 :tangle (eval f) :comments org :exports none integer(c_int32_t) function qmckl_sherman_morrison_splitting & - (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & + (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) & bind(C) result(info) use, intrinsic :: iso_c_binding @@ -950,11 +952,12 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, integer (c_int64_t) , intent(in) , value :: N_updates real (c_double ) , intent(in) :: Updates(N_updates*Dim) integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(in) , value :: breakdown real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) integer(c_int32_t), external :: qmckl_sherman_morrison_splitting_c info = qmckl_sherman_morrison_splitting_c & - (context, Dim, N_updates, Updates, Updates_index, Slater_inv) + (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) end function qmckl_sherman_morrison_splitting #+end_src @@ -965,7 +968,7 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, #+begin_src f90 :tangle (eval fh_func) :comments org :exports none interface integer(c_int32_t) function qmckl_sherman_morrison_splitting & - (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & + (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) & bind(C) use, intrinsic :: iso_c_binding import @@ -976,6 +979,7 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, integer (c_int64_t) , intent(in) , value :: N_updates real (c_double ) , intent(in) :: Updates(N_updates*Dim) integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(in) , value :: breakdown real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) end function qmckl_sherman_morrison_splitting @@ -993,16 +997,17 @@ const uint64_t splitting_Dim = 3; const uint64_t splitting_N_updates = 3; const uint64_t splitting_Updates_index[3] = {1, 1, 1}; const double splitting_Updates[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; +const double splitting_breakdown = 1e-3; double splitting_Slater_inv[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; // [TODO : FMJC ] add realistic tests -rc = qmckl_sherman_morrison_splitting_c(context, splitting_Dim, splitting_N_updates, splitting_Updates, splitting_Updates_index, splitting_Slater_inv); +rc = qmckl_sherman_morrison_splitting_c(context, splitting_Dim, splitting_N_updates, splitting_Updates, splitting_Updates_index, splitting_breakdown, splitting_Slater_inv); assert(rc == QMCKL_SUCCESS); #+end_src -* Sherman-Morrison with Woodbury 2x2 and update splitting +* Woodbury 2x2 with Sherman-Morrison and update splitting This is like naïve Sherman-Morrising, but whenever a denominator is found that is too close to zero the update is split in half. Then one @@ -1034,6 +1039,7 @@ unless the last original update causes a singular Slater-matrix. | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | | double | Updates[N_updates*Dim] | in | Array containing the updates | | uint64_t | Updates_index[N_updates] | in | Array containing the rank-1 updates | + | double | breakdown | in | Break-down parameter on which to fail or not | | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | *** Requirements @@ -1052,6 +1058,7 @@ unless the last original update causes a singular Slater-matrix. const uint64_t N_updates, const double* Updates, const uint64_t* Updates_index, + const double breakdown, double* Slater_inv ); #+end_src @@ -1084,6 +1091,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw2s_c(const qmckl_context context, const uint64_t N_updates, const double* Updates, const uint64_t* Updates_index, + const double breakdown, double * Slater_inv) { // #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. // std::cerr << "Called qmckl_sherman_morrison_woodbury_2 with " << N_updates @@ -1097,7 +1105,6 @@ qmckl_exit_code qmckl_sherman_morrison_smw2s_c(const qmckl_context context, uint64_t n_of_2blocks = N_updates / 2; uint64_t remainder = N_updates % 2; uint64_t length_2block = 2 * Dim; - // uint64_t length_1block = 1 * Dim; // Apply first 2*n_of_2blocks updates in n_of_2blocks blocks of 2 updates with // Woodbury 2x2 kernel @@ -1108,11 +1115,11 @@ qmckl_exit_code qmckl_sherman_morrison_smw2s_c(const qmckl_context context, for (uint64_t i = 0; i < n_of_2blocks; i++) { double *Updates_2block = &Updates[i * length_2block]; uint64_t *Updates_index_2block = &Updates_index[i * 2]; - rc = qmckl_woodbury_2_c(local_context, Dim, Updates_2block, Updates_index_2block, Slater_inv); + rc = qmckl_woodbury_2_c(local_context, Dim, Updates_2block, Updates_index_2block, breakdown, Slater_inv); if (rc != 0) { // Send the entire block to slagel_splitting uint64_t l = 0; rc = qmckl_slagel_splitting_c(Dim, 2, Updates_2block, Updates_index_2block, - Slater_inv, later_updates + (Dim * later), later_index + later, &l); + breakdown, Slater_inv, later_updates + (Dim * later), later_index + later, &l); later = later + l; } } @@ -1123,12 +1130,12 @@ qmckl_exit_code qmckl_sherman_morrison_smw2s_c(const qmckl_context context, uint64_t *Updates_index_1block = &Updates_index[2 * n_of_2blocks]; uint64_t l = 0; rc = qmckl_slagel_splitting_c(Dim, 1, Updates_1block, Updates_index_1block, - Slater_inv, later_updates + (Dim * later), later_index + later, &l); + breakdown, Slater_inv, later_updates + (Dim * later), later_index + later, &l); later = later + l; } if (later > 0) { - rc = qmckl_sherman_morrison_splitting_c(local_context, Dim, later, later_updates, later_index, Slater_inv); + rc = qmckl_sherman_morrison_splitting_c(local_context, Dim, later, later_updates, later_index, breakdown, Slater_inv); } return QMCKL_SUCCESS; } @@ -1197,17 +1204,18 @@ const uint64_t smw2s_Dim = 3; const uint64_t smw2s_N_updates = 3; const uint64_t smw2s_Updates_index[3] = {1, 1, 1}; const double smw2s_Updates[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; +const double smw2s_breakdown = 1e-3; double smw2s_Slater_inv[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; // [TODO : FMJC ] add realistic tests rc = qmckl_sherman_morrison_smw2s_c(context, smw2s_Dim, smw2s_N_updates, - smw2s_Updates, smw2s_Updates_index, smw2s_Slater_inv); + smw2s_Updates, smw2s_Updates_index, smw2s_breakdown, smw2s_Slater_inv); assert(rc == QMCKL_SUCCESS); #+end_src -* Sherman-Morrison with Woodbury 3x3 and update splitting +* Woodbury 3x3 with Sherman-Morrison and update splitting This is like naïve Sherman-Morrising, but whenever a denominator is found that is too close to zero the update is split in half. Then one @@ -1239,6 +1247,7 @@ unless the last original update causes a singular Slater-matrix. | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | | double | Updates[N_updates*Dim] | in | Array containing the updates | | uint64_t | Updates_index[N_updates] | in | Array containing the rank-1 updates | + | double | breakdown | in | Break-down parameter on which to fail or not | | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | *** Requirements @@ -1257,6 +1266,7 @@ unless the last original update causes a singular Slater-matrix. const uint64_t N_updates, const double* Updates, const uint64_t* Updates_index, + const double breakdown, double* Slater_inv ); #+end_src @@ -1290,6 +1300,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw3s_c(const qmckl_context context, const uint64_t N_updates, const double* Updates, const uint64_t* Updates_index, + const double breakdown, double * Slater_inv) { // #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. // std::cerr << "Called qmckl_sherman_morrison_woodbury_3 with " << N_updates @@ -1313,11 +1324,11 @@ qmckl_exit_code qmckl_sherman_morrison_smw3s_c(const qmckl_context context, for (uint64_t i = 0; i < n_of_3blocks; i++) { double *Updates_3block = &Updates[i * length_3block]; uint64_t *Updates_index_3block = &Updates_index[i * 3]; - rc = qmckl_woodbury_3_c(local_context, Dim, Updates_3block, Updates_index_3block, Slater_inv); + rc = qmckl_woodbury_3_c(local_context, Dim, Updates_3block, Updates_index_3block, breakdown, Slater_inv); if (rc != 0) { // Send the entire block to slagel_splitting uint64_t l = 0; rc = qmckl_slagel_splitting_c(Dim, 3, Updates_3block, Updates_index_3block, - Slater_inv, later_updates + (Dim * later), later_index + later, &l); + breakdown, Slater_inv, later_updates + (Dim * later), later_index + later, &l); later = later + l; } } @@ -1328,12 +1339,12 @@ qmckl_exit_code qmckl_sherman_morrison_smw3s_c(const qmckl_context context, uint64_t *Updates_index_remainder_block = &Updates_index[3 * n_of_3blocks]; uint64_t l = 0; rc = qmckl_slagel_splitting_c(Dim, remainder, Updates_remainder_block, Updates_index_remainder_block, - Slater_inv, later_updates + (Dim * later), later_index + later, &l); + breakdown, Slater_inv, later_updates + (Dim * later), later_index + later, &l); later = later + l; } if (later > 0) { - rc = qmckl_sherman_morrison_splitting_c(local_context, Dim, later, later_updates, later_index, Slater_inv); + rc = qmckl_sherman_morrison_splitting_c(local_context, Dim, later, later_updates, later_index, breakdown, Slater_inv); } } @@ -1397,21 +1408,22 @@ qmckl_exit_code qmckl_sherman_morrison_smw3s_c(const qmckl_context context, #+begin_src c :tangle (eval c_test) -const uint64_t smw32s_Dim = 3; -const uint64_t smw32s_N_updates = 3; -const uint64_t smw32s_Updates_index[3] = {1, 1, 1}; -const double smw32s_Updates[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; -double smw32s_Slater_inv[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; +const uint64_t smw3s__Dim = 3; +const uint64_t smw3s__N_updates = 3; +const uint64_t smw3s__Updates_index[3] = {1, 1, 1}; +const double smw3s_Updates[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; +const double smw3s_breakdown = 1e-3; +double smw3s_Slater_inv[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; // [TODO : FMJC ] add realistic tests -rc = qmckl_sherman_morrison_smw3s_c(context, smw32s_Dim, smw32s_N_updates, - smw32s_Updates, smw32s_Updates_index, smw32s_Slater_inv); +rc = qmckl_sherman_morrison_smw3s_c(context, smw3s_Dim, smw3s_N_updates, + smw3s_Updates, smw3s_Updates_index, smw3s_breakdown, smw3s_Slater_inv); assert(rc == QMCKL_SUCCESS); #+end_src -* Sherman-Morrison with Woodbury 3x3, 2x2 and update splitting +* Woodbury 3x3 and 2x2 with Sherman-Morrison and update splitting This is like naïve Sherman-Morrising, but whenever a denominator is found that is too close to zero the update is split in half. Then one @@ -1443,6 +1455,7 @@ unless the last original update causes a singular Slater-matrix. | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | | double | Updates[N_updates*Dim] | in | Array containing the updates | | uint64_t | Updates_index[N_updates] | in | Array containing the rank-1 updates | + | double | breakdown | in | Break-down parameter on which to fail or not | | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | *** Requirements @@ -1461,6 +1474,7 @@ unless the last original update causes a singular Slater-matrix. const uint64_t N_updates, const double* Updates, const uint64_t* Updates_index, + const double breakdown, double* Slater_inv ); #+end_src @@ -1494,6 +1508,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, const uint64_t N_updates, const double* Updates, const uint64_t* Updates_index, + const double breakdown, double * Slater_inv) { // #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. // std::cerr << "Called qmckl_sherman_morrison_woodbury_3 with " << N_updates @@ -1507,8 +1522,6 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, uint64_t n_of_3blocks = N_updates / 3; uint64_t remainder = N_updates % 3; uint64_t length_3block = 3 * Dim; - // uint64_t length_2block = 2 * Dim; - // uint64_t length_1block = 1 * Dim; // Apply first 3*n_of_3blocks updates in n_of_3blocks blocks of 3 updates with // Woodbury 3x3 kernel @@ -1519,11 +1532,11 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, for (uint64_t i = 0; i < n_of_3blocks; i++) { double *Updates_3block = &Updates[i * length_3block]; uint64_t *Updates_index_3block = &Updates_index[i * 3]; - rc = qmckl_woodbury_3_c(local_context, Dim, Updates_3block, Updates_index_3block, Slater_inv); + rc = qmckl_woodbury_3_c(local_context, Dim, Updates_3block, Updates_index_3block, breakdown, Slater_inv); if (rc != 0) { // Send the entire block to slagel_splitting uint64_t l = 0; rc = qmckl_slagel_splitting_c(Dim, 3, Updates_3block, Updates_index_3block, - Slater_inv, later_updates + (Dim * later), later_index + later, &l); + breakdown, Slater_inv, later_updates + (Dim * later), later_index + later, &l); later = later + l; } } @@ -1532,11 +1545,11 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, if (remainder == 2) { // Apply last remaining block of 2 updates with Woodbury 2x2 kernel double *Updates_2block = &Updates[n_of_3blocks * length_3block]; uint64_t *Updates_index_2block = &Updates_index[3 * n_of_3blocks]; - rc = qmckl_woodbury_2_c(local_context, Dim, Updates_2block, Updates_index_2block, Slater_inv); + rc = qmckl_woodbury_2_c(local_context, Dim, Updates_2block, Updates_index_2block, breakdown, Slater_inv); if (rc != 0) { // Send the entire block to slagel_splitting uint64_t l = 0; rc = qmckl_slagel_splitting_c(Dim, 2, Updates_2block, Updates_index_2block, - Slater_inv, later_updates + (Dim * later), later_index + later, &l); + breakdown, Slater_inv, later_updates + (Dim * later), later_index + later, &l); later = later + l; } } @@ -1545,12 +1558,12 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, uint64_t *Updates_index_1block = &Updates_index[3 * n_of_3blocks]; uint64_t l = 0; rc = qmckl_slagel_splitting_c(Dim, 1, Updates_1block, Updates_index_1block, - Slater_inv, later_updates + (Dim * later), later_index + later, &l); + breakdown, Slater_inv, later_updates + (Dim * later), later_index + later, &l); later = later + l; } if (later > 0) { - rc = qmckl_sherman_morrison_splitting_c(local_context, Dim, later, later_updates, later_index, Slater_inv); + rc = qmckl_sherman_morrison_splitting_c(local_context, Dim, later, later_updates, later_index, breakdown, Slater_inv); } } @@ -1618,12 +1631,13 @@ const uint64_t smw32s_Dim = 3; const uint64_t smw32s_N_updates = 3; const uint64_t smw32s_Updates_index[3] = {1, 1, 1}; const double smw32s_Updates[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; +const double smw32s_breakdown = 1e-3; double smw32s_Slater_inv[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; // [TODO : FMJC ] add realistic tests rc = qmckl_sherman_morrison_smw32s_c(context, smw32s_Dim, smw32s_N_updates, - smw32s_Updates, smw32s_Updates_index, smw32s_Slater_inv); + smw32s_Updates, smw32s_Updates_index, smw32s_breakdown, smw32s_Slater_inv); assert(rc == QMCKL_SUCCESS); #+end_src From 0e4ea1f81b406b329279f4a7eedb8a585799dbeb Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Tue, 27 Jul 2021 06:59:44 +0200 Subject: [PATCH 29/50] Fixed tests. Everything compiles successfully and passes all tests. #25 --- org/qmckl_sherman_morrison_woodbury.cpp | 434 ------------------------ org/qmckl_sherman_morrison_woodbury.org | 8 +- 2 files changed, 5 insertions(+), 437 deletions(-) delete mode 100644 org/qmckl_sherman_morrison_woodbury.cpp diff --git a/org/qmckl_sherman_morrison_woodbury.cpp b/org/qmckl_sherman_morrison_woodbury.cpp deleted file mode 100644 index 53080ee..0000000 --- a/org/qmckl_sherman_morrison_woodbury.cpp +++ /dev/null @@ -1,434 +0,0 @@ -#include - -// Sherman-Morrison-Woodbury break-down threshold -#ifndef THRESHOLD -#define THRESHOLD 1e-3 -#endif -static double threshold(); - -// Naïve Sherman Morrison -bool qmckl_sherman_morrison(double *Slater_inv, uint64_t Dim, uint64_t N_updates, - double *Updates, uint64_t *Updates_index); - -// Woodbury 2x2 kernel -bool qmckl_woodbury_2(double *Slater_inv, const uint64_t Dim, double *Updates, - const uint64_t *Updates_index); - -// Woodbury 3x3 kernel -bool qmckl_woodbury_3(double *Slater_inv, const uint64_t Dim, double *Updates, - const uint64_t *Updates_index); - -// Sherman Morrison, with J. Slagel splitting (caller function) -void qmckl_sherman_morrison_splitting(double *Slater_inv, uint64_t Dim, uint64_t N_updates, - double *Updates, uint64_t *Updates_index); - -// Sherman Morrison, with J. Slagel splitting -// http://hdl.handle.net/10919/52966 -static void slagel_splitting(double *Slater_inv, uint64_t Dim, uint64_t N_updates, - double *Updates, uint64_t *Updates_index, - double *later_updates, uint64_t *later_index, - uint64_t *later); - -// Mixed Sherman-Morrison-Woodbury kernel using -// Woodbury 2x2 and Sherman-Morrison with update-splitting -void qmckl_sherman_morrison_woodbury_2(double *Slater_inv, const uint64_t Dim, - const uint64_t N_updates, double *Updates, - uint64_t *Updates_index); - -// Mixed Sherman-Morrison-Woodbury kernel using -// Woodbury 3x3, Woodbury 2x2 and Sherman-Morrison with update-splitting -void qmckl_sherman_morrison_woodbury_3(double *Slater_inv, const uint64_t Dim, - const uint64_t N_updates, double *Updates, - uint64_t *Updates_index); - - - -// Sherman-Morrison-Woodbury break-down threshold -static double threshold() { - const double threshold = THRESHOLD; -// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. -// std::cerr << "Break-down threshold set to: " << threshold << std::endl; -// #endif - return threshold; -} - -// Naïve Sherman Morrison -bool qmckl_sherman_morrison(double *Slater_inv, uint64_t Dim, uint64_t N_updates, - double *Updates, uint64_t *Updates_index) { -// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. -// std::cerr << "Called qmckl_sherman_morrison with " << N_updates << " updates" << std::endl; -// #endif - - double C[Dim]; - double D[Dim]; - - uint64_t l = 0; - // For each update - while (l < N_updates) { - // C = A^{-1} x U_l - for (uint64_t i = 0; i < Dim; i++) { - C[i] = 0; - for (uint64_t j = 0; j < Dim; j++) { - C[i] += Slater_inv[i * Dim + j] * Updates[l * Dim + j]; - } - } - - // Denominator - double den = 1 + C[Updates_index[l] - 1]; - if (fabs(den) < threshold()) { - return QMCKL_FAILURE; - } - double iden = 1 / den; - - // D = v^T x A^{-1} - for (uint64_t j = 0; j < Dim; j++) { - D[j] = Slater_inv[(Updates_index[l] - 1) * Dim + j]; - } - - // A^{-1} = A^{-1} - C x D / den - for (uint64_t i = 0; i < Dim; i++) { - for (uint64_t j = 0; j < Dim; j++) { - double update = C[i] * D[j] * iden; - Slater_inv[i * Dim + j] -= update; - } - } - - l += 1; - } - return QMCKL_SUCCESS; -} - -// Woodbury 2x2 kernel -bool qmckl_woodbury_2(double *Slater_inv, const uint64_t Dim, double *Updates, - const uint64_t *Updates_index) { -/* - C := S^{-1} * U, dim x 2 - B := 1 + V * C, 2 x 2 - D := V * S^{-1}, 2 x dim -*/ -// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. -// std::cerr << "Called Woodbury 2x2 kernel" << std::endl; -// #endif - - const uint64_t row1 = (Updates_index[0] - 1); - const uint64_t row2 = (Updates_index[1] - 1); - - // Compute C = S_inv * U !! NON-STANDARD MATRIX MULTIPLICATION BECAUSE - // OF LAYOUT OF 'Updates' !! - double C[2 * Dim]; - for (uint64_t i = 0; i < Dim; i++) { - for (uint64_t j = 0; j < 2; j++) { - C[i * 2 + j] = 0; - for (uint64_t k = 0; k < Dim; k++) { - C[i * 2 + j] += Slater_inv[i * Dim + k] * Updates[Dim * j + k]; - } - } - } - - // Compute B = 1 + V * C - const double B0 = C[row1 * 2] + 1; - const double B1 = C[row1 * 2 + 1]; - const double B2 = C[row2 * 2]; - const double B3 = C[row2 * 2 + 1] + 1; - - // Check if determinant of inverted matrix is not zero - double det = B0 * B3 - B1 * B2; - if (fabs(det) < threshold()) { - return QMCKL_FAILURE; - } - - // Compute B^{-1} with explicit formula for 2x2 inversion - double Binv[4], idet = 1.0 / det; - Binv[0] = idet * B3; - Binv[1] = -1.0 * idet * B1; - Binv[2] = -1.0 * idet * B2; - Binv[3] = idet * B0; - - // Compute tmp = B^{-1} x (V.S^{-1}) - double tmp[2 * Dim]; - for (uint64_t i = 0; i < 2; i++) { - for (uint64_t j = 0; j < Dim; j++) { - tmp[i * Dim + j] = Binv[i * 2] * Slater_inv[row1 * Dim + j]; - tmp[i * Dim + j] += Binv[i * 2 + 1] * Slater_inv[row2 * Dim + j]; - } - } - - // Compute (S + U V)^{-1} = S^{-1} - C x tmp - for (uint64_t i = 0; i < Dim; i++) { - for (uint64_t j = 0; j < Dim; j++) { - Slater_inv[i * Dim + j] -= C[i * 2] * tmp[j]; - Slater_inv[i * Dim + j] -= C[i * 2 + 1] * tmp[Dim + j]; - } - } - - return QMCKL_SUCCESS; -} - -// Woodbury 3x3 kernel -bool qmckl_woodbury_3(double *Slater_inv, const uint64_t Dim, double *Updates, - const uint64_t *Updates_index) { -/* - C := S^{-1} * U, dim x 3 - B := 1 + V * C, 3 x 3 - D := V * S^{-1}, 3 x dim -*/ -// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. -// std::cerr << "Called Woodbury 3x3 kernel" << std::endl; -// #endif - - const uint64_t row1 = (Updates_index[0] - 1); - const uint64_t row2 = (Updates_index[1] - 1); - const uint64_t row3 = (Updates_index[2] - 1); - - // Compute C = S_inv * U !! NON-STANDARD MATRIX MULTIPLICATION BECAUSE - // OF LAYOUT OF 'Updates' !! - double C[3 * Dim]; - for (uint64_t i = 0; i < Dim; i++) { - for (uint64_t j = 0; j < 3; j++) { - C[i * 3 + j] = 0; - for (uint64_t k = 0; k < Dim; k++) { - C[i * 3 + j] += Slater_inv[i * Dim + k] * Updates[Dim * j + k]; - } - } - } - - // Compute B = 1 + V.C - const double B0 = C[row1 * 3] + 1; - const double B1 = C[row1 * 3 + 1]; - const double B2 = C[row1 * 3 + 2]; - const double B3 = C[row2 * 3]; - const double B4 = C[row2 * 3 + 1] + 1; - const double B5 = C[row2 * 3 + 2]; - const double B6 = C[row3 * 3]; - const double B7 = C[row3 * 3 + 1]; - const double B8 = C[row3 * 3 + 2] + 1; - - // Check if determinant of B is not too close to zero - double det; - det = B0 * (B4 * B8 - B5 * B7) - B1 * (B3 * B8 - B5 * B6) + - B2 * (B3 * B7 - B4 * B6); - - if (fabs(det) < threshold()) { - return QMCKL_FAILURE; - } - - // Compute B^{-1} with explicit formula for 3x3 inversion - double Binv[9], idet = 1.0 / det; - Binv[0] = (B4 * B8 - B7 * B5) * idet; - Binv[1] = -(B1 * B8 - B7 * B2) * idet; - Binv[2] = (B1 * B5 - B4 * B2) * idet; - Binv[3] = -(B3 * B8 - B6 * B5) * idet; - Binv[4] = (B0 * B8 - B6 * B2) * idet; - Binv[5] = -(B0 * B5 - B3 * B2) * idet; - Binv[6] = (B3 * B7 - B6 * B4) * idet; - Binv[7] = -(B0 * B7 - B6 * B1) * idet; - Binv[8] = (B0 * B4 - B3 * B1) * idet; - - // Compute tmp = B^{-1} x (V.S^{-1}) - double tmp[3 * Dim]; - for (uint64_t i = 0; i < 3; i++) { - for (uint64_t j = 0; j < Dim; j++) { - tmp[i * Dim + j] = Binv[i * 3] * Slater_inv[row1 * Dim + j]; - tmp[i * Dim + j] += Binv[i * 3 + 1] * Slater_inv[row2 * Dim + j]; - tmp[i * Dim + j] += Binv[i * 3 + 2] * Slater_inv[row3 * Dim + j]; - } - } - - // Compute (S + U V)^{-1} = S^{-1} - C x tmp - for (uint64_t i = 0; i < Dim; i++) { - for (uint64_t j = 0; j < Dim; j++) { - Slater_inv[i * Dim + j] -= C[i * 3] * tmp[j]; - Slater_inv[i * Dim + j] -= C[i * 3 + 1] * tmp[Dim + j]; - Slater_inv[i * Dim + j] -= C[i * 3 + 2] * tmp[2 * Dim + j]; - } - } - - return QMCKL_SUCCESS; -} - -// Sherman Morrison, with J. Slagel splitting (caller function) -// http://hdl.handle.net/10919/52966 -void qmckl_sherman_morrison_splitting(double *Slater_inv, uint64_t Dim, uint64_t N_updates, - double *Updates, uint64_t *Updates_index) { -// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. -// std::cerr << "Called qmckl_sherman_morrison_splitting with " << N_updates << " updates" << std::endl; -// #endif - - double later_updates[Dim * N_updates]; - uint64_t later_index[N_updates]; - uint64_t later = 0; - - slagel_splitting(Slater_inv, Dim, N_updates, Updates, Updates_index, later_updates, - later_index, &later); - - if (later > 0) { - qmckl_sherman_morrison_splitting(Slater_inv, Dim, later, later_updates, later_index); - } -} - -// Sherman Morrison, with J. Slagel splitting -// http://hdl.handle.net/10919/52966 -static void slagel_splitting(double *Slater_inv, uint64_t Dim, uint64_t N_updates, - double *Updates, uint64_t *Updates_index, - double *later_updates, uint64_t *later_index, - uint64_t *later) { -// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. -// std::cerr << "Called slagel_splitting with " << N_updates << " updates" << std::endl; -// #endif - - double C[Dim]; - double D[Dim]; - - uint64_t l = 0; - // For each update - while (l < N_updates) { - // C = S^{-1} x U_l - for (uint64_t i = 0; i < Dim; i++) { - C[i] = 0; - for (uint64_t j = 0; j < Dim; j++) { - C[i] += Slater_inv[i * Dim + j] * Updates[l * Dim + j]; - } - } - - // Denominator - double den = 1 + C[Updates_index[l] - 1]; - if (fabs(den) < threshold()) { - - // U_l = U_l / 2 (do the split) - for (uint64_t i = 0; i < Dim; i++) { - later_updates[*later * Dim + i] = Updates[l * Dim + i] / 2.0; - C[i] /= 2.0; - } - later_index[*later] = Updates_index[l]; - (*later)++; - - den = 1 + C[Updates_index[l] - 1]; - } - double iden = 1 / den; - - // D = v^T x S^{-1} - for (uint64_t j = 0; j < Dim; j++) { - D[j] = Slater_inv[(Updates_index[l] - 1) * Dim + j]; - } - - // S^{-1} = S^{-1} - C x D / den - for (uint64_t i = 0; i < Dim; i++) { - for (uint64_t j = 0; j < Dim; j++) { - double update = C[i] * D[j] * iden; - Slater_inv[i * Dim + j] -= update; - } - } - l += 1; - } -} - -// Sherman-Morrison-Woodbury 2x2 kernel -// qmckl_woodbury_2, slagel_splitting mixing scheme -void qmckl_sherman_morrison_woodbury_2(double *Slater_inv, const uint64_t Dim, - const uint64_t N_updates, double *Updates, - uint64_t *Updates_index) { -// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. -// std::cerr << "Called qmckl_sherman_morrison_woodbury_2 with " << N_updates -// << " updates" << std::endl; -// #endif - - uint64_t n_of_2blocks = N_updates / 2; - uint64_t remainder = N_updates % 2; - uint64_t length_2block = 2 * Dim; - uint64_t length_1block = 1 * Dim; - - // Apply first 2*n_of_2blocks updates in n_of_2blocks blocks of 2 updates with - // Woodbury 2x2 kernel - double later_updates[Dim * N_updates]; - uint64_t later_index[N_updates]; - uint64_t later = 0; - if (n_of_2blocks > 0) { - for (uint64_t i = 0; i < n_of_2blocks; i++) { - double *Updates_2block = &Updates[i * length_2block]; - uint64_t *Updates_index_2block = &Updates_index[i * 2]; - bool ok; - ok = qmckl_woodbury_2(Slater_inv, Dim, Updates_2block, Updates_index_2block); - if (!ok) { // Send the entire block to slagel_splitting - uint64_t l = 0; - slagel_splitting(Slater_inv, Dim, 2, Updates_2block, Updates_index_2block, - later_updates + (Dim * later), later_index + later, &l); - later = later + l; - } - } - } - - if (remainder == 1) { // Apply last remaining update with slagel_splitting - double *Updates_1block = &Updates[n_of_2blocks * length_2block]; - uint64_t *Updates_index_1block = &Updates_index[2 * n_of_2blocks]; - uint64_t l = 0; - slagel_splitting(Slater_inv, Dim, 1, Updates_1block, Updates_index_1block, - later_updates + (Dim * later), later_index + later, &l); - later = later + l; - } - - if (later > 0) { - qmckl_sherman_morrison_splitting(Slater_inv, Dim, later, later_updates, later_index); - } -} - -// Sherman-Morrison-Woodbury 3x3 kernel -// qmckl_woodbury_2, qmckl_woodbury_3, slagel_splitting mixing scheme -void qmckl_sherman_morrison_woodbury_3(double *Slater_inv, const uint64_t Dim, - const uint64_t N_updates, double *Updates, - uint64_t *Updates_index) { -// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. -// std::cerr << "Called qmckl_sherman_morrison_woodbury_3 with " << N_updates -// << " updates" << std::endl; -// #endif - - uint64_t n_of_3blocks = N_updates / 3; - uint64_t remainder = N_updates % 3; - uint64_t length_3block = 3 * Dim; - uint64_t length_2block = 2 * Dim; - uint64_t length_1block = 1 * Dim; - - // Apply first 3*n_of_3blocks updates in n_of_3blocks blocks of 3 updates with - // Woodbury 3x3 kernel - double later_updates[Dim * N_updates]; - uint64_t later_index[N_updates]; - uint64_t later = 0; - if (n_of_3blocks > 0) { - for (uint64_t i = 0; i < n_of_3blocks; i++) { - double *Updates_3block = &Updates[i * length_3block]; - uint64_t *Updates_index_3block = &Updates_index[i * 3]; - bool ok; - ok = qmckl_woodbury_3(Slater_inv, Dim, Updates_3block, Updates_index_3block); - if (!ok) { // Send the entire block to slagel_splitting - uint64_t l = 0; - slagel_splitting(Slater_inv, Dim, 3, Updates_3block, Updates_index_3block, - later_updates + (Dim * later), later_index + later, &l); - later = later + l; - } - } - } - - if (remainder == 2) { // Apply last remaining block of 2 updates with Woodbury 2x2 kernel - double *Updates_2block = &Updates[n_of_3blocks * length_3block]; - uint64_t *Updates_index_2block = &Updates_index[3 * n_of_3blocks]; - bool ok; - ok = qmckl_woodbury_2(Slater_inv, Dim, Updates_2block, Updates_index_2block); - if (!ok) { // Send the entire block to slagel_splitting - uint64_t l = 0; - slagel_splitting(Slater_inv, Dim, 2, Updates_2block, Updates_index_2block, - later_updates + (Dim * later), later_index + later, &l); - later = later + l; - } - } - else if (remainder == 1) { // Apply last remaining update with slagel_splitting - double *Updates_1block = &Updates[n_of_3blocks * length_3block]; - uint64_t *Updates_index_1block = &Updates_index[3 * n_of_3blocks]; - uint64_t l = 0; - slagel_splitting(Slater_inv, Dim, 1, Updates_1block, Updates_index_1block, - later_updates + (Dim * later), later_index + later, &l); - later = later + l; - } - - if (later > 0) { - qmckl_sherman_morrison_splitting(Slater_inv, Dim, later, later_updates, later_index); - } -} diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 453fa8f..a831219 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -1346,6 +1346,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw3s_c(const qmckl_context context, if (later > 0) { rc = qmckl_sherman_morrison_splitting_c(local_context, Dim, later, later_updates, later_index, breakdown, Slater_inv); } + return QMCKL_SUCCESS; } #+end_src @@ -1408,9 +1409,9 @@ qmckl_exit_code qmckl_sherman_morrison_smw3s_c(const qmckl_context context, #+begin_src c :tangle (eval c_test) -const uint64_t smw3s__Dim = 3; -const uint64_t smw3s__N_updates = 3; -const uint64_t smw3s__Updates_index[3] = {1, 1, 1}; +const uint64_t smw3s_Dim = 3; +const uint64_t smw3s_N_updates = 3; +const uint64_t smw3s_Updates_index[3] = {1, 1, 1}; const double smw3s_Updates[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; const double smw3s_breakdown = 1e-3; double smw3s_Slater_inv[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; @@ -1565,6 +1566,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, if (later > 0) { rc = qmckl_sherman_morrison_splitting_c(local_context, Dim, later, later_updates, later_index, breakdown, Slater_inv); } + return QMCKL_SUCCESS; } #+end_src From afc6e115d3fee8db883e8f7506c5bf12c3768004 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Tue, 27 Jul 2021 08:48:28 +0200 Subject: [PATCH 30/50] Resolved compiler warnings about initialising 'objects' with 'const objects'. #25 --- org/qmckl_sherman_morrison_woodbury.org | 28 ++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index a831219..ab7db81 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -1113,8 +1113,8 @@ qmckl_exit_code qmckl_sherman_morrison_smw2s_c(const qmckl_context context, uint64_t later = 0; if (n_of_2blocks > 0) { for (uint64_t i = 0; i < n_of_2blocks; i++) { - double *Updates_2block = &Updates[i * length_2block]; - uint64_t *Updates_index_2block = &Updates_index[i * 2]; + const double *Updates_2block = &Updates[i * length_2block]; + const uint64_t *Updates_index_2block = &Updates_index[i * 2]; rc = qmckl_woodbury_2_c(local_context, Dim, Updates_2block, Updates_index_2block, breakdown, Slater_inv); if (rc != 0) { // Send the entire block to slagel_splitting uint64_t l = 0; @@ -1126,8 +1126,8 @@ qmckl_exit_code qmckl_sherman_morrison_smw2s_c(const qmckl_context context, } if (remainder == 1) { // Apply last remaining update with slagel_splitting - double *Updates_1block = &Updates[n_of_2blocks * length_2block]; - uint64_t *Updates_index_1block = &Updates_index[2 * n_of_2blocks]; + const double *Updates_1block = &Updates[n_of_2blocks * length_2block]; + const uint64_t *Updates_index_1block = &Updates_index[2 * n_of_2blocks]; uint64_t l = 0; rc = qmckl_slagel_splitting_c(Dim, 1, Updates_1block, Updates_index_1block, breakdown, Slater_inv, later_updates + (Dim * later), later_index + later, &l); @@ -1322,8 +1322,8 @@ qmckl_exit_code qmckl_sherman_morrison_smw3s_c(const qmckl_context context, uint64_t later = 0; if (n_of_3blocks > 0) { for (uint64_t i = 0; i < n_of_3blocks; i++) { - double *Updates_3block = &Updates[i * length_3block]; - uint64_t *Updates_index_3block = &Updates_index[i * 3]; + const double *Updates_3block = &Updates[i * length_3block]; + const uint64_t *Updates_index_3block = &Updates_index[i * 3]; rc = qmckl_woodbury_3_c(local_context, Dim, Updates_3block, Updates_index_3block, breakdown, Slater_inv); if (rc != 0) { // Send the entire block to slagel_splitting uint64_t l = 0; @@ -1335,8 +1335,8 @@ qmckl_exit_code qmckl_sherman_morrison_smw3s_c(const qmckl_context context, } if (remainder != 0) { // Apply last remaining block of 2 updates with Woodbury 2x2 kernel - double *Updates_remainder_block = &Updates[n_of_3blocks * length_3block]; - uint64_t *Updates_index_remainder_block = &Updates_index[3 * n_of_3blocks]; + const double *Updates_remainder_block = &Updates[n_of_3blocks * length_3block]; + const uint64_t *Updates_index_remainder_block = &Updates_index[3 * n_of_3blocks]; uint64_t l = 0; rc = qmckl_slagel_splitting_c(Dim, remainder, Updates_remainder_block, Updates_index_remainder_block, breakdown, Slater_inv, later_updates + (Dim * later), later_index + later, &l); @@ -1531,8 +1531,8 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, uint64_t later = 0; if (n_of_3blocks > 0) { for (uint64_t i = 0; i < n_of_3blocks; i++) { - double *Updates_3block = &Updates[i * length_3block]; - uint64_t *Updates_index_3block = &Updates_index[i * 3]; + const double *Updates_3block = &Updates[i * length_3block]; + const uint64_t *Updates_index_3block = &Updates_index[i * 3]; rc = qmckl_woodbury_3_c(local_context, Dim, Updates_3block, Updates_index_3block, breakdown, Slater_inv); if (rc != 0) { // Send the entire block to slagel_splitting uint64_t l = 0; @@ -1544,8 +1544,8 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, } if (remainder == 2) { // Apply last remaining block of 2 updates with Woodbury 2x2 kernel - double *Updates_2block = &Updates[n_of_3blocks * length_3block]; - uint64_t *Updates_index_2block = &Updates_index[3 * n_of_3blocks]; + const double *Updates_2block = &Updates[n_of_3blocks * length_3block]; + const uint64_t *Updates_index_2block = &Updates_index[3 * n_of_3blocks]; rc = qmckl_woodbury_2_c(local_context, Dim, Updates_2block, Updates_index_2block, breakdown, Slater_inv); if (rc != 0) { // Send the entire block to slagel_splitting uint64_t l = 0; @@ -1555,8 +1555,8 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, } } else if (remainder == 1) { // Apply last remaining update with slagel_splitting - double *Updates_1block = &Updates[n_of_3blocks * length_3block]; - uint64_t *Updates_index_1block = &Updates_index[3 * n_of_3blocks]; + const double *Updates_1block = &Updates[n_of_3blocks * length_3block]; + const uint64_t *Updates_index_1block = &Updates_index[3 * n_of_3blocks]; uint64_t l = 0; rc = qmckl_slagel_splitting_c(Dim, 1, Updates_1block, Updates_index_1block, breakdown, Slater_inv, later_updates + (Dim * later), later_index + later, &l); From a5e58c80d70978c12d24ff47b2362c9145af325c Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Thu, 29 Jul 2021 11:48:38 +0200 Subject: [PATCH 31/50] Passing argument context instead of creating and passing a locally created context. #25 --- org/qmckl_sherman_morrison_woodbury.org | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index ab7db81..047846c 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -5,7 +5,7 @@ Low- and high-level functions that use the Sherman-Morrison and Woodbury matrix inversion formulas to update the inverse of a non-singualr matrix - + * Headers #+begin_src elisp :noexport :results none :exports none (org-babel-lob-ingest "../tools/lib.org") @@ -255,6 +255,7 @@ end function qmckl_sherman_morrison_f #+begin_src c :tangle (eval c) :comments org #include #include "qmckl.h" +#include qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, const uint64_t Dim, @@ -303,6 +304,7 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, l += 1; } + return QMCKL_SUCCESS; } @@ -911,8 +913,6 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, // std::cerr << "Called qmckl_sherman_morrison_splitting with " << N_updates << " updates" << std::endl; // #endif - qmckl_context local_context; - local_context = qmckl_context_create(); qmckl_exit_code rc; double later_updates[Dim * N_updates]; @@ -923,7 +923,7 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, breakdown, Slater_inv, later_updates, later_index, &later); if (later > 0) { - rc = qmckl_sherman_morrison_splitting_c(local_context, Dim, later, + rc = qmckl_sherman_morrison_splitting_c(context, Dim, later, later_updates, later_index, breakdown, Slater_inv); } From 978e20ac428e2232384c5024f123bc93605da485 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Fri, 30 Jul 2021 11:48:08 +0200 Subject: [PATCH 32/50] Removed local context var declarations from kernels and pass along context from passed arguments. #25 --- org/qmckl_sherman_morrison_woodbury.org | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 047846c..4f6259f 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -255,7 +255,6 @@ end function qmckl_sherman_morrison_f #+begin_src c :tangle (eval c) :comments org #include #include "qmckl.h" -#include qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, const uint64_t Dim, @@ -1098,8 +1097,6 @@ qmckl_exit_code qmckl_sherman_morrison_smw2s_c(const qmckl_context context, // << " updates" << std::endl; // #endif - qmckl_context local_context; - local_context = qmckl_context_create(); qmckl_exit_code rc; uint64_t n_of_2blocks = N_updates / 2; @@ -1115,7 +1112,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw2s_c(const qmckl_context context, for (uint64_t i = 0; i < n_of_2blocks; i++) { const double *Updates_2block = &Updates[i * length_2block]; const uint64_t *Updates_index_2block = &Updates_index[i * 2]; - rc = qmckl_woodbury_2_c(local_context, Dim, Updates_2block, Updates_index_2block, breakdown, Slater_inv); + rc = qmckl_woodbury_2_c(context, Dim, Updates_2block, Updates_index_2block, breakdown, Slater_inv); if (rc != 0) { // Send the entire block to slagel_splitting uint64_t l = 0; rc = qmckl_slagel_splitting_c(Dim, 2, Updates_2block, Updates_index_2block, @@ -1135,7 +1132,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw2s_c(const qmckl_context context, } if (later > 0) { - rc = qmckl_sherman_morrison_splitting_c(local_context, Dim, later, later_updates, later_index, breakdown, Slater_inv); + rc = qmckl_sherman_morrison_splitting_c(context, Dim, later, later_updates, later_index, breakdown, Slater_inv); } return QMCKL_SUCCESS; } @@ -1307,8 +1304,6 @@ qmckl_exit_code qmckl_sherman_morrison_smw3s_c(const qmckl_context context, // << " updates" << std::endl; // #endif - qmckl_context local_context; - local_context = qmckl_context_create(); qmckl_exit_code rc; uint64_t n_of_3blocks = N_updates / 3; @@ -1324,7 +1319,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw3s_c(const qmckl_context context, for (uint64_t i = 0; i < n_of_3blocks; i++) { const double *Updates_3block = &Updates[i * length_3block]; const uint64_t *Updates_index_3block = &Updates_index[i * 3]; - rc = qmckl_woodbury_3_c(local_context, Dim, Updates_3block, Updates_index_3block, breakdown, Slater_inv); + rc = qmckl_woodbury_3_c(context, Dim, Updates_3block, Updates_index_3block, breakdown, Slater_inv); if (rc != 0) { // Send the entire block to slagel_splitting uint64_t l = 0; rc = qmckl_slagel_splitting_c(Dim, 3, Updates_3block, Updates_index_3block, @@ -1344,7 +1339,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw3s_c(const qmckl_context context, } if (later > 0) { - rc = qmckl_sherman_morrison_splitting_c(local_context, Dim, later, later_updates, later_index, breakdown, Slater_inv); + rc = qmckl_sherman_morrison_splitting_c(context, Dim, later, later_updates, later_index, breakdown, Slater_inv); } return QMCKL_SUCCESS; } @@ -1516,8 +1511,6 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, // << " updates" << std::endl; // #endif - qmckl_context local_context; - local_context = qmckl_context_create(); qmckl_exit_code rc; uint64_t n_of_3blocks = N_updates / 3; @@ -1533,7 +1526,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, for (uint64_t i = 0; i < n_of_3blocks; i++) { const double *Updates_3block = &Updates[i * length_3block]; const uint64_t *Updates_index_3block = &Updates_index[i * 3]; - rc = qmckl_woodbury_3_c(local_context, Dim, Updates_3block, Updates_index_3block, breakdown, Slater_inv); + rc = qmckl_woodbury_3_c(context, Dim, Updates_3block, Updates_index_3block, breakdown, Slater_inv); if (rc != 0) { // Send the entire block to slagel_splitting uint64_t l = 0; rc = qmckl_slagel_splitting_c(Dim, 3, Updates_3block, Updates_index_3block, @@ -1546,7 +1539,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, if (remainder == 2) { // Apply last remaining block of 2 updates with Woodbury 2x2 kernel const double *Updates_2block = &Updates[n_of_3blocks * length_3block]; const uint64_t *Updates_index_2block = &Updates_index[3 * n_of_3blocks]; - rc = qmckl_woodbury_2_c(local_context, Dim, Updates_2block, Updates_index_2block, breakdown, Slater_inv); + rc = qmckl_woodbury_2_c(context, Dim, Updates_2block, Updates_index_2block, breakdown, Slater_inv); if (rc != 0) { // Send the entire block to slagel_splitting uint64_t l = 0; rc = qmckl_slagel_splitting_c(Dim, 2, Updates_2block, Updates_index_2block, @@ -1564,7 +1557,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, } if (later > 0) { - rc = qmckl_sherman_morrison_splitting_c(local_context, Dim, later, later_updates, later_index, breakdown, Slater_inv); + rc = qmckl_sherman_morrison_splitting_c(context, Dim, later, later_updates, later_index, breakdown, Slater_inv); } return QMCKL_SUCCESS; } From 9e58ab4bb93237fb0d259710a60a53fc9a8f647b Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Wed, 1 Sep 2021 15:29:14 +0200 Subject: [PATCH 33/50] Started adding anf polishing documentation. --- org/qmckl_sherman_morrison_woodbury.org | 59 +++++++++++++++++++------ 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 4f6259f..c9526f0 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -27,12 +27,10 @@ int main() { #+end_src - * Helper Functions -Helper functions that are used by the Sherman-Morrison-Woodbury -kernels. These functions should only be used in the context of these -kernels. +Helper functions that are used by the Sherman-Morrison-Woodbury kernels. +These functions can only be used internally by higher level functions. ** ~qmckl_slagel_splitting~ :PROPERTIES: @@ -41,7 +39,12 @@ kernels. :FRetType: double precision :END: - This function is used to set the threshold value that is used in the kernels to determine if a matrix is invertable or not. In the Sherman-Morrison kernels this is determined by comparing the denominator in the Sherman-Morrison formula to the value set in threshold. If the value is smaller than the threshold value it means the matrix is not invertable. In the Woodbury kernels the threshold value is compared with the value of the determinant of the update matrix. + ~qmckl_slagel_splitting~ is used internally to perform a J.~Slagel style split of rank-1 updates. + + For a given $u_j$ we define a threshold $\epsilon_j$, which is the minimum value of + $1+v_j^TS^{-1}u_j$ for the matrix to be considered nonsingular. If $1+v_j^TS^{-1}u_j \geq \epsilon_j$, + the update is applied as usual. Otherwise, $u_j$ will be redefined as $\frac{u_j}{2}$, and the other half + (to be applied at the end) will be defined using vectors $\frac{u_{j'}}{2}$ and $v_{j'}^T=v_{j'}^T$. #+NAME: qmckl_slagel_splitting_args | uint64_t | Dim | in | Leading dimension of Slater_inv | @@ -57,7 +60,15 @@ kernels. *** Requirements - Add description of the input variables. (see for e.g. qmckl_distance.org) + - ~Dim >= 2~ + - ~N_updates >= 1~ + - ~Updates~ is allocated with at least $1 \times 2 \times 8$ bytes + - ~Updates_index~ is allocated with at least $1 \times 8$ bytes + - ~breakdown~ is a small number such that $0 < breakdown << 1$ + - ~Slater_inv~ is allocated with at least $Dim \times Dim \times 8$ bytes + - ~later_updates~ is allocated with at least $1 \times 2 \times 8$ bytes + - ~later_index~ is allocated with at least $1 \times 8$ bytes + - ~later >= 0~ *** C header @@ -151,6 +162,8 @@ qmckl_exit_code qmckl_slagel_splitting_c(uint64_t Dim, *** Performance +This function performce better for cycles with 1 rank-1 update and with a high fail-rate. + ** C interface :noexport: @@ -184,8 +197,7 @@ qmckl_exit_code qmckl_slagel_splitting_c(uint64_t Dim, *** Test :noexport: -[TODO: FMJC] Write tests for the Sherman-Morrison part. - + This function does not have an explicit test as it is only used internally by higher level Sherman-Morrison-Woodbury functions. * Naïve Sherman-Morrison @@ -198,10 +210,20 @@ qmckl_exit_code qmckl_slagel_splitting_c(uint64_t Dim, :END: This is the simplest of the available Sherman-Morrison-Woodbury - kernels in QMCkl. It applies rank-1 updates one by one in the order + kernels. It applies rank-1 updates one by one in the order that is given. It only checks if the denominator in the - Sherman-Morrison formula is not too close to zero (and exit with an - error if it does) during the application of an update. + Sherman-Morrison formula is not too close to zero when an update is evaluated. + It will exit with an error code of the denominator is too close to zero. + + The formula that is applied is + \begin{equation} + (S + uv^T)^{-1} = S^{-1} - \frac{S^{-1} uv^T S^{-1}}{1 + v^T S^{-1} u} + \end{equation} + + where + $S$ is the Slater-matrix, + $u$ and $v^T$ are the column and row vectors containing the updates, + $S^{-1}$ is the inverse of the Slater-matrix. #+NAME: qmckl_sherman_morrison_args | qmckl_context | context | in | Global state | @@ -213,9 +235,15 @@ qmckl_exit_code qmckl_slagel_splitting_c(uint64_t Dim, | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | *** Requirements - - Add description of the input variables. (see for e.g. qmckl_distance.org) - + + - ~context~ is not ~QMCKL_NULL_CONTEXT~ + - ~Dim >= 2~ + - ~N_updates >= 1~ + - ~Updates~ is allocated with at least $1 \times 2 \times 8$ bytes + - ~Updates_index~ is allocated with at least $1 \times 8$ bytes + - ~breakdown~ is a small number such that $0 < breakdown << 1$ + - ~Slater_inv~ is allocated with at least $Dim \times Dim \times 8$ bytes + *** C header #+CALL: generate_c_header(table=qmckl_sherman_morrison_args,rettyp=get_value("CRetType"),fname=get_value("Name")) @@ -313,6 +341,9 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, *** Performance + This function performs better when there is only 1 rank-1 update in the update cycle and the fail-rate of rank-1 updates is high. + + ** C interface :noexport: #+CALL: generate_c_interface(table=qmckl_sherman_morrison_args,rettyp=get_value("FRetType"),fname=get_value("Name")) From bbd20ce87a8e5f9bd21d5e3c72a00588d13544fc Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Wed, 1 Sep 2021 16:06:51 +0200 Subject: [PATCH 34/50] More documentation added. --- org/qmckl_sherman_morrison_woodbury.org | 57 ++++++++++++++++--------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index c9526f0..8b3c56c 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -216,9 +216,9 @@ This function performce better for cycles with 1 rank-1 update and with a high f It will exit with an error code of the denominator is too close to zero. The formula that is applied is - \begin{equation} + \[ (S + uv^T)^{-1} = S^{-1} - \frac{S^{-1} uv^T S^{-1}}{1 + v^T S^{-1} u} - \end{equation} + \] where $S$ is the Slater-matrix, @@ -415,11 +415,9 @@ rc = qmckl_sherman_morrison_c(context, Dim, N_updates, Updates, Updates_index, b assert(rc == QMCKL_SUCCESS); #+end_src - + * Woodbury 2x2 -This is the Woodbury 3x3 kernel. - ** ~qmckl_woodbury_2~ :PROPERTIES: :Name: qmckl_woodbury_2 @@ -427,11 +425,19 @@ This is the Woodbury 3x3 kernel. :FRetType: qmckl_exit_code :END: - This is the simplest of the available Sherman-Morrison-Woodbury - kernels in QMCkl. It applies rank-1 updates one by one in the order - that is given. It only checks if the denominator in the - Sherman-Morrison formula is not too close to zero (and exit with an - error if it does) during the application of an update. + The simplest version of the generalised Sherman-Morrison-Woodbury kernels. It is used to apply two + rank-1 updates at once. The formula used in this algorithm is called the Woodbury Matrix Identity + \[ + (S + U V)^{-1} = S^{-1} - C B^{-1} D + \] + where + $S$ is the Slater-matrix + $U$ and $V$ are the matrices containing the updates and the canonical basis matrix + $S^{-1}$ is the inverse of the Slater-matrix + $C:= S^{-1}U$, a Dim $\times 2$ matrix + $B := 1 + VC$, the $2 \times 2$ matrix that is going to be inverted + $D := VS^{-1}$, a $2 \times Dim$ matrix + #+NAME: qmckl_woodbury_2_args | qmckl_context | context | in | Global state | @@ -443,7 +449,12 @@ This is the Woodbury 3x3 kernel. *** Requirements - Add description of the input variables. (see for e.g. qmckl_distance.org) + - ~context~ is not ~qmckl_null_context~ + - ~dim >= 2~ + - ~updates~ is allocated with at least $2 \times 2 \times 8$ bytes + - ~updates_index~ is allocated with $2 \times 8$ bytes + - ~breakdown~ is a small number such that $0 < breakdown << 1$ + - ~slater_inv~ is allocated with at least $dim \times dim \times 8$ bytes *** C header @@ -559,6 +570,8 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, *** Performance + This function is most efficient when used in cases where there are only 2 rank-1 updates + ** C interface :noexport: #+CALL: generate_c_interface(table=qmckl_woodbury_2_args,rettyp=get_value("FRetType"),fname=get_value("Name")) @@ -629,8 +642,6 @@ assert(rc == QMCKL_SUCCESS); * Woodbury 3x3 - -This is the Woodbury 3x3 kernel. ** ~qmckl_woodbury_3~ :PROPERTIES: @@ -639,11 +650,12 @@ This is the Woodbury 3x3 kernel. :FRetType: qmckl_exit_code :END: - This is the simplest of the available Sherman-Morrison-Woodbury - kernels in QMCkl. It applies rank-1 updates one by one in the order - that is given. It only checks if the denominator in the - Sherman-Morrison formula is not too close to zero (and exit with an - error if it does) during the application of an update. + The 3x3 version of the Woodbury 2x2 kernel. It is used to apply three + rank-1 updates at once. The formula used in this kernel is the same as for Woodbury 2x2, with the exception of + + $C:= S^{-1}U$, a Dim $\times 3$ matrix + $B := 1 + VC$, the $3 \times 3$ matrix that is going to be inverted + $D := VS^{-1}$, a $3 \times Dim$ matrix #+NAME: qmckl_woodbury_3_args | qmckl_context | context | in | Global state | @@ -655,7 +667,6 @@ This is the Woodbury 3x3 kernel. *** Requirements - Add description of the input variables. (see for e.g. qmckl_distance.org) *** C header @@ -784,6 +795,14 @@ qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, *** Performance... + - ~context~ is not ~qmckl_null_context~ + - ~dim >= 2~ + - ~updates~ is allocated with at least $3 \times 2 \times 8$ bytes + - ~updates_index~ is allocated with $3 \times 8$ bytes + - ~breakdown~ is a small number such that $0 < breakdown << 1$ + - ~slater_inv~ is allocated with at least $dim \times dim \times 8$ bytes + + ** C interface :noexport: #+CALL: generate_c_interface(table=qmckl_woodbury_3_args,rettyp=get_value("FRetType"),fname=get_value("Name")) From abb34618935d981a9d56a32acacae972ca5928a7 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Wed, 1 Sep 2021 16:10:59 +0200 Subject: [PATCH 35/50] Put info in the wrong place. --- org/qmckl_sherman_morrison_woodbury.org | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 8b3c56c..c929022 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -570,7 +570,7 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, *** Performance - This function is most efficient when used in cases where there are only 2 rank-1 updates + This function is most efficient when used in cases where there are only 2 rank-1 updates. ** C interface :noexport: @@ -667,6 +667,12 @@ assert(rc == QMCKL_SUCCESS); *** Requirements + - ~context~ is not ~qmckl_null_context~ + - ~dim >= 2~ + - ~updates~ is allocated with at least $3 \times 2 \times 8$ bytes + - ~updates_index~ is allocated with $3 \times 8$ bytes + - ~breakdown~ is a small number such that $0 < breakdown << 1$ + - ~slater_inv~ is allocated with at least $dim \times dim \times 8$ bytes *** C header @@ -794,13 +800,8 @@ qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, #+end_src *** Performance... - - - ~context~ is not ~qmckl_null_context~ - - ~dim >= 2~ - - ~updates~ is allocated with at least $3 \times 2 \times 8$ bytes - - ~updates_index~ is allocated with $3 \times 8$ bytes - - ~breakdown~ is a small number such that $0 < breakdown << 1$ - - ~slater_inv~ is allocated with at least $dim \times dim \times 8$ bytes + + This function is most efficient when used in cases where there are only 3 rank-1 updates. ** C interface :noexport: From 435628a5d0658584c53d4dd97fa7e705d9e1308b Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Thu, 2 Sep 2021 17:56:42 +0200 Subject: [PATCH 36/50] Finished first draft of the documentation --- org/qmckl_sherman_morrison_woodbury.org | 161 +++++++++++------------- 1 file changed, 75 insertions(+), 86 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index c929022..741336d 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -26,7 +26,7 @@ int main() { qmckl_exit_code rc; #+end_src - + * Helper Functions Helper functions that are used by the Sherman-Morrison-Woodbury kernels. @@ -39,10 +39,11 @@ These functions can only be used internally by higher level functions. :FRetType: double precision :END: - ~qmckl_slagel_splitting~ is used internally to perform a J.~Slagel style split of rank-1 updates. + ~qmckl_slagel_splitting~ is used internally to apply a list of rank-1 updates while splitting an update if necessary. + In case of a split it applies the first half of the update while putting the second half in waiting queue to be applied at the end. - For a given $u_j$ we define a threshold $\epsilon_j$, which is the minimum value of - $1+v_j^TS^{-1}u_j$ for the matrix to be considered nonsingular. If $1+v_j^TS^{-1}u_j \geq \epsilon_j$, + For a given update $u_j$ we define a threshold value $\epsilon_j$, which is the minimum value of + $1+v_j^TS^{-1}u_j$ for a non-singular matrix $S$. If $1+v_j^TS^{-1}u_j \geq \epsilon_j$, the update is applied as usual. Otherwise, $u_j$ will be redefined as $\frac{u_j}{2}$, and the other half (to be applied at the end) will be defined using vectors $\frac{u_{j'}}{2}$ and $v_{j'}^T=v_{j'}^T$. @@ -69,7 +70,7 @@ These functions can only be used internally by higher level functions. - ~later_updates~ is allocated with at least $1 \times 2 \times 8$ bytes - ~later_index~ is allocated with at least $1 \times 8$ bytes - ~later >= 0~ - + *** C header #+CALL: generate_c_header(table=qmckl_slagel_splitting_args,rettyp=get_value("CRetType"),fname=get_value("Name")) @@ -337,8 +338,6 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, #+end_src - - *** Performance This function performs better when there is only 1 rank-1 update in the update cycle and the fail-rate of rank-1 updates is high. @@ -567,7 +566,6 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, #+end_src - *** Performance This function is most efficient when used in cases where there are only 2 rank-1 updates. @@ -640,7 +638,7 @@ rc = qmckl_woodbury_2_c(context, woodbury_Dim, woodbury_Updates, woodbury_Update assert(rc == QMCKL_SUCCESS); #+end_src - + * Woodbury 3x3 ** ~qmckl_woodbury_3~ @@ -651,7 +649,8 @@ assert(rc == QMCKL_SUCCESS); :END: The 3x3 version of the Woodbury 2x2 kernel. It is used to apply three - rank-1 updates at once. The formula used in this kernel is the same as for Woodbury 2x2, with the exception of + rank-1 updates at once. The formula used in this kernel is the same as for Woodbury 2x2, + except for the sizes of the following matrices: $C:= S^{-1}U$, a Dim $\times 3$ matrix $B := 1 + VC$, the $3 \times 3$ matrix that is going to be inverted @@ -875,17 +874,6 @@ assert(rc == QMCKL_SUCCESS); * Sherman-Morrison with update splitting -This is like naïve Sherman-Morrising, but whenever a denominator is -found that is too close to zero the update is split in half. Then one -half is applied immediately and the other have is ket for later. When -all the updates have been processed, the list of split updates that -have been kept for later are processed. If again applying an update -results in a denominator that is too close to zero, it is split in -half again. One half is applied immediately and one half is kept for -later. The algorithm is done when no more updates have been kept for -later. This recursion will always end in a finite number of steps, -unless the last original update causes a singular Slater-matrix. - ** ~qmckl_sherman_morrison_splitting~ :PROPERTIES: :Name: qmckl_sherman_morrison_splitting @@ -893,11 +881,14 @@ unless the last original update causes a singular Slater-matrix. :FRetType: qmckl_exit_code :END: - This is the simplest of the available Sherman-Morrison-Woodbury - kernels in QMCkl. It applies rank-1 updates one by one in the order - that is given. It only checks if the denominator in the - Sherman-Morrison formula is not too close to zero (and exit with an - error if it does) during the application of an update. + This is a variation on the 'Naive' Sherman-Morrison kernel. Whenever the denominator $1+v_j^T S^{-1} u_j$ in + the Sherman-Morrison formula is deemed to be too close to zero, the update $u_j$ is split in half: + $u_j \rightarrow \frac{1}{1} u_j$. One half is applied immediately --necessarily increasing the value of the + denominator because of the split-- while the other halve is put in a queue that will be applied when all the + remaining updates have been treated. The kernel is executed recursively until the queue is eiter empty and all + updates are applied successfully, or the size of the queue equals the number of initial updates. In the last + case the Slater-matrix that would have resulted from applying the updates is un-invertable and therefore the + kernel exits with an exit code. #+NAME: qmckl_sherman_morrison_splitting_args | qmckl_context | context | in | Global state | @@ -910,8 +901,14 @@ unless the last original update causes a singular Slater-matrix. *** Requirements - Add description of the input variables. (see for e.g. qmckl_distance.org) - + - ~context~ is not ~QMCKL_NULL_CONTEXT~ + - ~Dim >= 2~ + - ~N_updates >= 1~ + - ~Updates~ is allocated with at least $1 \times 2 \times 8$ bytes + - ~Updates_index~ is allocated with at least $1 \times 8$ bytes + - ~breakdown~ is a small number such that $0 < breakdown << 1$ + - ~Slater_inv~ is allocated with at least $Dim \times Dim \times 8$ bytes + *** C header #+CALL: generate_c_header(table=qmckl_sherman_morrison_splitting_args,rettyp=get_value("CRetType"),fname=get_value("Name")) @@ -945,7 +942,6 @@ integer function qmckl_sherman_morrison_splitting_f(context, Dim, N_updates, end function qmckl_sherman_morrison_splitting_f #+end_src - *** Source C #+begin_src c :tangle (eval c) :comments org @@ -984,6 +980,8 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, *** Performance... + This kernel performs best when there are only 1 rank-1 update cycles and/or when the fail-rate is high. + ** C interface :noexport: #+CALL: generate_c_interface(table=qmckl_sherman_morrison_splitting_args,rettyp=get_value("FRetType"),fname=get_value("Name")) @@ -1059,17 +1057,6 @@ assert(rc == QMCKL_SUCCESS); * Woodbury 2x2 with Sherman-Morrison and update splitting -This is like naïve Sherman-Morrising, but whenever a denominator is -found that is too close to zero the update is split in half. Then one -half is applied immediately and the other have is ket for later. When -all the updates have been processed, the list of split updates that -have been kept for later are processed. If again applying an update -results in a denominator that is too close to zero, it is split in -half again. One half is applied immediately and one half is kept for -later. The algorithm is done when no more updates have been kept for -later. This recursion will always end in a finite number of steps, -unless the last original update causes a singular Slater-matrix. - ** ~qmckl_sherman_morrison_smw2s~ :PROPERTIES: :Name: qmckl_sherman_morrison_smw2s @@ -1077,11 +1064,17 @@ unless the last original update causes a singular Slater-matrix. :FRetType: qmckl_exit_code :END: - This is the simplest of the available Sherman-Morrison-Woodbury - kernels in QMCkl. It applies rank-1 updates one by one in the order - that is given. It only checks if the denominator in the - Sherman-Morrison formula is not too close to zero (and exit with an - error if it does) during the application of an update. + The Woodbury 2x2 kernel with Sherman-Morrison and update splitting combines the low-level Woodbury 2x2 kernel + and Sherman-Morrison with update splitting. For a given number of updates $N$ it splits the number of updates + in blocks of two updates. The blocks of two updates are then applied one by one using Woodbury 2x2. If a block + of updates fails, both updates in the block are applied with Sherman-Morrison instead, split if necessary and + with their second half put in a queue. After all blocks are processed the remaining one update --in case there + was an odd number of updates to begin with-- is also aplpied with Sherman-Morrison and split if necessary. + The queue containing the collected second halves of all the processed updates is processed at the very end to + avoid having many intermediate queues containing only a few updates that risks an increased probability + of artificially created non-singular intermediate matrices, resulting from division up the total number of + updates in blocks of three. + #+NAME: qmckl_sherman_morrison_smw2s_args | qmckl_context | context | in | Global state | @@ -1094,7 +1087,13 @@ unless the last original update causes a singular Slater-matrix. *** Requirements - Add description of the input variables. (see for e.g. qmckl_distance.org) + - ~context~ is not ~QMCKL_NULL_CONTEXT~ + - ~Dim >= 2~ + - ~N_updates >= 1~ + - ~Updates~ is allocated with at least $1 \times 2 \times 8$ bytes + - ~Updates_index~ is allocated with at least $1 \times 8$ bytes + - ~breakdown~ is a small number such that $0 < breakdown << 1$ + - ~Slater_inv~ is allocated with at least $Dim \times Dim \times 8$ bytes *** C header @@ -1112,7 +1111,6 @@ unless the last original update causes a singular Slater-matrix. double* Slater_inv ); #+end_src - *** Source Fortran #+begin_src f90 :tangle (eval f) @@ -1129,7 +1127,6 @@ integer function qmckl_sherman_morrison_smw2s_f(context, Slater_inv, Dim, N_upda end function qmckl_sherman_morrison_smw2s_f #+end_src - *** Source C #+begin_src c :tangle (eval c) :comments org @@ -1192,6 +1189,8 @@ qmckl_exit_code qmckl_sherman_morrison_smw2s_c(const qmckl_context context, *** Performance... + This kernel performs best for the case of two rank-1 update and a low fail-rate. + ** C interface :noexport: #+CALL: generate_c_interface(table=qmckl_sherman_morrison_smw2s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) @@ -1265,17 +1264,6 @@ assert(rc == QMCKL_SUCCESS); * Woodbury 3x3 with Sherman-Morrison and update splitting -This is like naïve Sherman-Morrising, but whenever a denominator is -found that is too close to zero the update is split in half. Then one -half is applied immediately and the other have is ket for later. When -all the updates have been processed, the list of split updates that -have been kept for later are processed. If again applying an update -results in a denominator that is too close to zero, it is split in -half again. One half is applied immediately and one half is kept for -later. The algorithm is done when no more updates have been kept for -later. This recursion will always end in a finite number of steps, -unless the last original update causes a singular Slater-matrix. - ** ~qmckl_sherman_morrison_smw3s~ :PROPERTIES: :Name: qmckl_sherman_morrison_smw3s @@ -1283,11 +1271,10 @@ unless the last original update causes a singular Slater-matrix. :FRetType: qmckl_exit_code :END: - This is the simplest of the available Sherman-Morrison-Woodbury - kernels in QMCkl. It applies rank-1 updates one by one in the order - that is given. It only checks if the denominator in the - Sherman-Morrison formula is not too close to zero (and exit with an - error if it does) during the application of an update. + The Woodbury 3x3 kernel with Sherman-Morrison and update splitting combines the low-level Woodbury 3x3 kernel + and Sherman-Morrison with update splitting. It works the same as Woodbury 2x2 with Sherman-Morrison and update + splitting, except that the updates are divided in blocks of three rank-1 updates instead of blocks of two + rank-1 updates. #+NAME: qmckl_sherman_morrison_smw3s_args | qmckl_context | context | in | Global state | @@ -1300,7 +1287,13 @@ unless the last original update causes a singular Slater-matrix. *** Requirements - Add description of the input variables. (see for e.g. qmckl_distance.org) + - ~context~ is not ~QMCKL_NULL_CONTEXT~ + - ~Dim >= 2~ + - ~N_updates >= 1~ + - ~Updates~ is allocated with at least $1 \times 2 \times 8$ bytes + - ~Updates_index~ is allocated with at least $1 \times 8$ bytes + - ~breakdown~ is a small number such that $0 < breakdown << 1$ + - ~Slater_inv~ is allocated with at least $Dim \times Dim \times 8$ bytes *** C header @@ -1318,7 +1311,6 @@ unless the last original update causes a singular Slater-matrix. double* Slater_inv ); #+end_src - *** Source Fortran #+begin_src f90 :tangle (eval f) @@ -1336,7 +1328,6 @@ integer function qmckl_sherman_morrison_smw3s_f(context, Slater_inv, Dim, N_upda end function qmckl_sherman_morrison_smw3s_f #+end_src - *** Source C #+begin_src c :tangle (eval c) :comments org @@ -1399,6 +1390,9 @@ qmckl_exit_code qmckl_sherman_morrison_smw3s_c(const qmckl_context context, *** Performance... + This kernel performs best for the case of three rank-1 update and a low fail-rate. + + ** C interface :noexport: #+CALL: generate_c_interface(table=qmckl_sherman_morrison_smw3s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) @@ -1471,17 +1465,6 @@ assert(rc == QMCKL_SUCCESS); * Woodbury 3x3 and 2x2 with Sherman-Morrison and update splitting - -This is like naïve Sherman-Morrising, but whenever a denominator is -found that is too close to zero the update is split in half. Then one -half is applied immediately and the other have is ket for later. When -all the updates have been processed, the list of split updates that -have been kept for later are processed. If again applying an update -results in a denominator that is too close to zero, it is split in -half again. One half is applied immediately and one half is kept for -later. The algorithm is done when no more updates have been kept for -later. This recursion will always end in a finite number of steps, -unless the last original update causes a singular Slater-matrix. ** ~qmckl_sherman_morrison_smw32s~ :PROPERTIES: @@ -1490,11 +1473,11 @@ unless the last original update causes a singular Slater-matrix. :FRetType: qmckl_exit_code :END: - This is the simplest of the available Sherman-Morrison-Woodbury - kernels in QMCkl. It applies rank-1 updates one by one in the order - that is given. It only checks if the denominator in the - Sherman-Morrison formula is not too close to zero (and exit with an - error if it does) during the application of an update. + The Woodbury 3x3 and 2x2 kernel with Sherman-Morrison and update splitting combines the low-level Woodbury 3x3 kernel, + the Woobury 2x2 kernel and Sherman-Morrison with update splitting. It works the almost the same as Woodbury 3x3 with + Sherman-Morrison and update splitting, except that when there is a remainder of two rank-1 updates, it is first tried + with Woodbury 2x2 instead of sending them all to Sherman-Morrison with update splitting. For example, in the case of + 5 updates the updates are applied in 1 block of 3 updates end 1 block of 2 updates. #+NAME: qmckl_sherman_morrison_smw32s_args | qmckl_context | context | in | Global state | @@ -1507,7 +1490,13 @@ unless the last original update causes a singular Slater-matrix. *** Requirements - Add description of the input variables. (see for e.g. qmckl_distance.org) + - ~context~ is not ~QMCKL_NULL_CONTEXT~ + - ~Dim >= 2~ + - ~N_updates >= 1~ + - ~Updates~ is allocated with at least $1 \times 2 \times 8$ bytes + - ~Updates_index~ is allocated with at least $1 \times 8$ bytes + - ~breakdown~ is a small number such that $0 < breakdown << 1$ + - ~Slater_inv~ is allocated with at least $Dim \times Dim \times 8$ bytes *** C header @@ -1525,7 +1514,6 @@ unless the last original update causes a singular Slater-matrix. double* Slater_inv ); #+end_src - *** Source Fortran #+begin_src f90 :tangle (eval f) @@ -1543,7 +1531,6 @@ integer function qmckl_sherman_morrison_smw32s_f(context, Slater_inv, Dim, N_upd end function qmckl_sherman_morrison_smw32s_f #+end_src - *** Source C #+begin_src c :tangle (eval c) :comments org @@ -1617,6 +1604,8 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, *** Performance... + This kernel performs best when the number of rank-1 updates is larger than 3 and fail-rates are low. + ** C interface :noexport: #+CALL: generate_c_interface(table=qmckl_sherman_morrison_smw32s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) From ef04e3df9bc372aea4928fdcd274559dcb949148 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Sun, 5 Sep 2021 11:22:41 +0200 Subject: [PATCH 37/50] Added realistic tests to all kernels. Everything compiles fine. --- org/qmckl_sherman_morrison_woodbury.org | 273 +++++++++++++++--------- 1 file changed, 177 insertions(+), 96 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 741336d..863573f 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -198,8 +198,7 @@ This function performce better for cycles with 1 rank-1 update and with a high f *** Test :noexport: - This function does not have an explicit test as it is only used internally by higher level Sherman-Morrison-Woodbury functions. - + This kernel does not have an explicit test because it is only used internally by higher-level Sherman-Morrison-Woodbury kernels. * Naïve Sherman-Morrison @@ -344,7 +343,7 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, ** C interface :noexport: - + #+CALL: generate_c_interface(table=qmckl_sherman_morrison_args,rettyp=get_value("FRetType"),fname=get_value("Name")) #+RESULTS: @@ -397,20 +396,66 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, *** Test :noexport: -[TODO: FMJC] Write tests for the Sherman-Morrison part. - +The tests for the kernels are executed on datasets that are extracted from a run of QMC=Chem on Benzene (21 spin-up/21 spin down electrons) using 329 unique alpha determinants. The tests are run such that the kernels reject the computed inverse whenever the computed intermediate determinants or denominators are smaller than 1e-3. This is the default value in QMC=Chem. The tests will return QMCKL_SUCCESS whenever all the elements of the final matrix $R=S.S^-1 - 1$ are smaller than the given tolerance value of 1e-3, and will return QMCKL_FAILURE if the values are larger than this tolerance value. #+begin_src c :tangle (eval c_test) -const uint64_t Dim = 2; -const uint64_t N_updates = 2; -const uint64_t Updates_index[2] = {0, 0}; -const double Updates[4] = {0.0, 0.0, 0.0, 0.0}; +const uint64_t Dim = 21; const double breakdown = 1e-3; -double Slater_inv[4] = {0.0, 0.0, 0.0, 0.0}; +const double tolerance = 1e-3; +double res[441]; -// [TODO : FMJC ] add realistic tests +const uint64_t N_updates1 = 1; +const uint64_t Updates_index1[1] = {21}; +const double Updates1[21] = {-0.0068946573883295389, -0.024496730417013196, -0.2336846236139537, -0.011720726499334019, 0.094674163497984229, 0.049728685989975902, 0.025834936182945929, 0.0586009658873081, -0.06664357893168929, -0.060625394340604558, 0.1100576994940636, -0.077925791963934898, -0.07255193404853344, 0.04257450252771329, -0.079073280096053591, 0.053145386278629192, 0.014488439075648779, -0.070511359721422195, -0.13172587938606731, -0.01733743725344538, 0.26186770945787408}; +const double Slater1[441] = {-2.8945870399475102, 3.5455725193023699, 2.0470812320709202, -3.5464441776275599, -2.0474903583526598, -2.89596366882324, -0.61329728364944502, 0.70991641283035301, 0.45664468407630898, 0.59523195028305098, 0.26079276204109197, -0.027727147564291999, -0.35093706846237199, -0.095610238611698206, -0.130077064037323, 0.10946778208017301, 0.021800471469759899, 0.048480678349733401, -0.092234551906585693, -0.0160505045205355, 0.0065372241660952603, -0.78021097183227495, -0.95558542013168302, -0.55174458026885997, -0.95579683780670199, -0.55179446935653698, 0.78044348955154397, -0.115299895405769, -0.11754634231329, -0.0318448171019554, -0.00082233443390577999, 0.064001239836216001, 0.12740932404995001, -0.049412809312343597, -0.074464745819568606, 0.19851659238338501, -0.088878795504569993, 0.135610401630402, -0.13736967742443101, -0.101879440248013, 0.102390937507153, 0.061368178576231003, -0.00527230883017182, 0.00029381641070358499, 0.0072919740341603799, -0.00026352208806201799, 0.0068838247098028703, 0.0047294595278799499, 0.11728889495134399, -0.062190085649490398, -0.15969239175319699, -0.10645916312933, 0.112943567335606, -0.0015487050404772199, -0.045737843960523598, 0.13196058571338701, 0.038660705089569099, -0.050266433507204097, -0.13745591044426, -0.037740666419267703, 0.11781705915927899, 0.19417031109332999, -0.0186148826032877, -0.30874741077423101, -0.37815779447555498, 0.218254208564758, 0.378139227628708, -0.21839827299118, -0.30879178643226601, 0.025539221242070202, 0.112043909728527, 0.037676706910133403, 0.025347150862216901, -0.19991625845432301, 0.14163509011268599, 0.13326919078826899, 0.213842943310738, 0.131471157073975, 0.14626120030879999, -0.0118067460134625, 0.093547157943248693, 0.22439678013324699, 0.0082425400614738499, -0.00068585784174501896, -1.52881526947021, -1.9163775505148799e-05, -2.1623263359069802, -1.5540548702119799e-05, 2.16284847259521, -1.52953028678894, -0.26402890682220498, 0.024944067001342801, -0.37140902876853898, -0.044071510434150703, -0.29843890666961698, -0.043834518641233403, -0.177285701036453, -0.058585006743669503, -0.0183692276477814, -0.026075478643178902, -0.15623773634433699, -0.011319605633616401, 0.054057534784078598, -0.23151709139347099, 0.10071966797113401, -0.067333526909351293, 0.00043256155913695698, 0.095035225152969402, -0.00043632232700474598, 0.094624765217304202, 0.066768139600753798, 0.14448715746402699, -0.12090456485748299, -0.203432962298393, -0.21472349762916601, 0.154288679361343, 0.017385326325893399, -0.071518480777740506, 0.27918133139610302, 0.080454014241695404, -0.0361245274543762, 0.0566458702087402, -0.030157707631588, 0.25150132179260298, -0.082445412874221802, -0.017144737765192999, -2.2779068946838401, -2.3393469746224599e-05, -3.2218937873840301, -1.7939200915861899e-05, 3.22278833389282, -2.2791447639465301, -0.47945570945739702, 0.045197278261184699, -0.64478874206543002, -0.080234304070472703, -0.47389149665832497, 0.024908870458602898, -0.23455648124218001, -0.10695217549800901, -0.033054649829864502, -0.195749551057816, -0.040076982229948002, 0.094596333801746396, 0.098401188850402804, -0.059563819319009802, 0.028169330209493599, -0.0025739683769643298, -0.0020174346864223502, -0.0024467820767313199, -0.00204527890309691, 0.00013988610589876801, 0.00073755031917244196, 0.17339251935482, 0.099962860345840496, 0.14622049033641801, -0.088966980576515198, 0.040044382214546197, -0.14437201619148299, -1.5416861060657501e-05, -0.081159926950931494, -0.11909016221761699, 0.170753449201584, 0.031124599277973199, -0.052109345793724102, 0.121445283293724, 0.0289684906601906, 0.0189813487231731, -0.0043673445470631097, -0.00014539182302542001, 0.0061219600029289696, 0.000189467871678062, 0.0060523007996380303, 0.00425094133242965, 0.0905451029539108, 0.058540407568216303, -0.15191346406936601, 0.11511342227459, 0.15016922354698201, 0.10024280846118901, -0.11066282540559801, -0.15089659392833699, -0.021995550021529201, 0.10021472722291901, 0.019932290539145501, 0.070281185209751101, -0.120184391736984, -0.030551897361874601, -0.023023990914225599, -0.0097634727135300602, 0.0119331693276763, -0.0068263513967394803, 0.011701960116624799, -0.0068089049309492103, 0.0095072658732533507, 0.133816182613373, -0.15090283751487699, 0.070243604481220204, 0.077758952975273105, -0.071993313729763003, -0.0526336021721363, -0.033549431711435297, -0.029018172994255999, 0.10475520789623299, 0.047332767397165298, 0.17077720165252699, 0.057527918368577999, -0.043988067656755399, 0.11077278107404701, -0.0581490993499756, -0.71565270423889205, 2.80283820757177e-05, 1.0121610164642301, -2.41986454057042e-05, 1.0123220682144201, 0.71586799621581998, -0.045286595821380601, -0.0269623268395662, 0.0683262273669243, -0.047560662031173699, -0.062597043812274905, -0.0278066452592611, 0.045772761106491103, 0.063010454177856404, 0.0197743345052004, -0.025724532082676901, -0.20542661845684099, -0.0248414911329746, 0.058127623051405002, 0.30385830998420699, 0.12407322973012901, -0.00073456991231069001, 0.000104061764432117, -0.0010063005611300501, 0.00014142321015242501, 0.00095045292982831597, -0.00064003589795902404, 0.056538689881563201, -0.038196403533220298, 0.095246985554695102, 0.077704243361949907, 0.089713566005229894, 0.071932643651962294, 0.058404259383678402, 0.097089007496833801, -1.8242251826450202e-05, -0.070699930191039997, 0.0231548044830561, 0.036239527165889698, -0.064700096845626803, 0.035663921386003501, -0.0192963760346174, -0.0285779368132353, 2.2119384368579599e-07, -0.0404084548354149, 4.62594880445977e-06, 0.040473498404025997, -0.028664523735642398, 0.0818745791912079, -0.0072916029021143896, 0.171691119670868, 0.0142411412671208, 0.227563425898552, 0.20764905214309701, 0.23875248432159399, 0.019401129335165, 0.0041248365305364097, -0.273390233516693, 0.031942136585712398, 0.24207504093647, -0.016599044203758202, 0.0499182641506195, -0.067969180643558502, -0.083720728754997295, -0.102523192763329, -0.059237916022539097, -0.10253403335809699, -0.0591498985886574, 0.083691440522670704, 0.093738317489623996, 0.118414394557476, 0.119053602218628, -0.19025875627994501, -0.017257452011108398, 0.111288614571095, -0.14737996459007299, -0.106449924409389, 0.119639433920383, -0.0358475148677826, 0.16083629429340399, -0.135845571756363, -0.045223556458950001, 0.129632458090782, 0.134273305535316, -0.0016409500967711199, 0.0020083498675376199, 0.0011536112288013101, -0.0019761291332542901, -0.0011378186754882301, -0.0015965295024216199, 0.062009602785110501, -0.085591755807399694, -0.073869466781616197, -0.129948750138283, -0.025633471086621298, 0.092304252088069902, 0.11476875841617599, 0.0570255033671856, -0.098354063928127303, 0.048130486160516697, -0.075562968850135803, -0.087558984756469699, -0.061446368694305399, 0.073952160775661496, -0.16332066059112499, -0.086937576532363905, -5.2227896958356703e-05, -0.12295132130384399, -5.67086790397298e-05, 0.122932203114033, -0.086922481656074496, 0.092386581003665896, 0.0563923679292202, 0.16267444193363201, -0.103307262063026, 0.177027583122253, 0.119934171438217, 0.15235325694084201, -0.13730293512344399, -0.036718469113111503, -0.13380806148052199, -0.14056211709976199, 0.11525499820709199, 0.122316166758537, -0.211628392338753, 0.13097538053989399, -0.71328485012054399, -0.87364697456359897, -0.50431287288665805, -0.87368428707122803, -0.50450080633163497, 0.71341556310653698, -0.0728774294257164, -0.0137394573539495, -0.131415024399757, 0.120499663054943, -0.15048809349536901, 0.067258194088935894, -0.016238121315836899, 0.25341770052909901, 0.061544414609670597, -0.124150305986404, -0.023104058578610399, 0.161576017737389, -0.18417926132678999, -0.016373874619603199, -0.0025253379717469198, -0.00358590018004179, -3.1569013572152501e-06, 0.00505110481753945, -1.33700987134944e-05, 0.0050756097771227403, 0.0036168387159705201, 0.076649472117423997, -0.0148532707244158, -0.15424914658069599, -0.031277053058147403, 0.20174449682235701, 0.17827098071575201, -0.21435502171516399, 0.043405968695879003, 0.0060502337291836704, 0.23922684788703899, 0.022777535021305102, 0.22072769701480899, 0.035028267651796299, -0.037091828882694203, -0.088090680539608002, -0.0137155568227172, -0.00072690693195909305, 0.019026592373848, 0.00073597067967057196, 0.018235495314001999, 0.012611641548574, 0.14907942712307001, 0.10721461474895499, -0.205590710043907, 0.18899101018905601, 0.14405034482479101, 0.0080890702083706908, -0.049517802894115399, -0.23817741870880099, -0.062822751700878102, -0.056222390383482, 0.079762905836105305, -0.057780988514423398, -0.208331778645515, -0.11229432374239, 0.015691248700022701, -0.13207408785819999, -0.00012266315752640399, -0.18668732047080999, -0.000116608949610963, 0.18647037446498901, -0.13181127607822399, 0.17992316186428101, 0.0310163982212543, 0.194987177848816, -0.051282022148370701, 0.079243704676628099, -0.16229276359081299, -0.029616238549351699, -0.065854735672473894, -0.025143278762698201, 0.277732163667679, -0.117880158126354, -0.184251189231873, 0.0632317289710045, -0.16761179268360099, 0.0069939070381224199, -0.0068073021247982996, -0.0083365431055426598, 0.0048150913789868398, 0.0083073899149894697, -0.0047997133806347804, -0.0067770029418170504, 0.077614806592464405, 0.12953585386276201, -0.063416801393032102, 0.138088583946228, -0.10224375873804099, 0.130568191409111, 0.164952263236046, 0.026345754042267799, 0.13718618452549, 0.084768116474151597, 0.096043966710567502, -0.054612904787063599, 0.138456135988235, -0.071488708257675199, 0.070078171789646093}; +double Slater_inv1[441] = {-0.0525082963130096, -192.960477122746, -167.343357271998, 1.69063377058866, -1378.4882402189, 239.360652372684, 874.40192183061697, -513.31846478968203, 807.35483045933495, -19.026422090297299, -17.824591748935202, 165.6645926386, -332.909289060628, -18.6107453916377, -11.6439930601979, 317.18559450822198, 214.12532640356201, -430.80943299473, -344.65005510575799, 740.81014093255203, -84.923325284754696, 0.064335245989650805, 234.71397330210399, 205.1186636226, -3.4153770027768502, 1680.13890084581, -293.40065007215702, -1065.8419078679401, 624.86259814866003, -989.76729197131897, 23.298249286417001, 21.573213707404399, -202.41174445438401, 405.86421806904502, 22.922945938042901, 14.236362125535999, -386.65825218682801, -261.06337565261498, 528.20337075570103, 421.94063881187702, -902.75507799084596, 105.03985525163, 0.044200668381308601, -138.85152101714399, -121.27002019292, 2.0061662585667599, -992.69022926063894, 173.24384564131401, 629.63518796071799, -369.68832373377103, 582.99742710801104, -13.474468953452901, -12.4187314531643, 119.002229516372, -239.76386110607999, -13.4968690647037, -8.1499663302329708, 228.499936475189, 154.09732894897101, -311.21651724011002, -248.26815844269399, 533.37480106787098, -61.991136485706697, -0.0765497914729725, 240.772681546397, 209.115172008988, -2.12401058528051, 1722.15420882834, -299.07379390801702, -1092.4670851015201, 641.09661184520598, -1007.44097957056, 23.333413806919001, 21.9897514440317, -206.53257016044699, 415.81861108697302, 23.3743606050752, 14.107639254523001, -396.52477956346598, -267.77854087146301, 537.68662188870303, 429.83533323670702, -925.65731644586003, 106.070284414301, -0.037109975520249097, -136.738457148886, -118.917063549582, 1.19704609156923, -977.22998951029899, 169.63000196416201, 620.01253859081601, -364.02043006288699, 570.85982682561803, -13.451266756380299, -12.146454471873501, 117.435790064483, -235.687342903548, -13.183975346097, -8.2288378293500593, 224.66974233421601, 151.73703725446899, -304.613662218336, -243.40661913323399, 525.55077671846004, -60.142862384234697, -0.062476778936209301, 195.74640208908301, 170.54051550313201, -2.8328765312753998, 1399.12576024585, -244.28628529648901, -887.63077081451104, 520.884480704167, -823.92607500410702, 19.0479002693959, 18.195743596123101, -168.030291787452, 337.586201042798, 18.991146825575299, 11.5224539224244, -321.78784999564101, -217.23371709456501, 439.82292557372398, 351.28300986264401, -752.091241883468, 87.457548717202599, 4.3572379528639997e-05, -23.790404094575401, -19.504220922406098, 0.26595531593048999, -161.34910319146201, 30.163156787264001, 102.337776116854, -58.672051676794297, 103.227708063905, -0.22802366652163999, -2.2306129106953398, 21.778747237132102, -40.783330246607299, -1.38732280869919, -0.75357165711863805, 39.269880423319599, 26.312297182321299, -55.061514171221297, -43.569942636118199, 85.973367077774896, -10.016061028885201, 4.0427159001010801e-05, 28.392374743152502, 26.373254860492299, -0.36980926031100297, 209.22398819265001, -37.9473984838014, -132.76472733653301, 77.720615205630693, -127.924723556082, 0.29745864731730998, 2.7793514223195599, -29.019189334306802, 53.826499495808498, 4.2582570650914597, 0.51526747227423098, -50.914050124737102, -31.724328055085401, 68.0683646567051, 55.266627392249198, -110.63482872154501, 14.1152956761065, 0.00055720168222872903, -2.6345228739497299, -3.4087974363069198, 0.048641237778327802, -18.3623844122964, 3.8195276251277801, 11.6411523542838, -5.8812824661877396, 15.735088038012799, -0.058858662594294599, -0.23845780430312999, 6.5124119812799099, -6.1494099868393697, 0.340564236694477, -0.880332042883611, 5.7252222161672197, 2.8545094725865199, -8.3447036743893506, -8.0497901808946395, 9.3503553819376606, -1.76541796469797, 0.00098753020434672305, -4.6360828892267198, -4.7638931470942598, 0.052453544062221497, -34.4916331053766, 7.7511206271403301, 21.997597399118899, -10.6934789694381, 32.345600850876203, -0.10706305963427901, -0.54284354835464799, 12.037079682564, -12.6961140374279, -1.7388931639227301, -1.8407110220006899, 10.3197626100112, 5.2986332905796001, -16.735105713526099, -14.146077371772099, 15.8344011098352, -1.6714914906603899, -4.8622590537520702e-05, 21.991930004831101, 18.4929481874854, -0.23309077760739899, 151.30678790823001, -25.711826077506299, -96.044580982176896, 55.801793853982701, -88.373121372798394, 0.202838254384864, 1.86718437434255, -20.278044655055201, 40.151563308198597, 1.3977678891012399, 0.324629892441265, -37.6766500842932, -24.340233848932201, 47.6840523743628, 38.2032083073968, -79.164159949210401, 8.7548536140586801, -0.00061993571816668601, -0.395895385274183, -1.4644468265008701, -0.0046318612148825598, -4.9913109472233304, 1.48540197873744, 3.26672618350988, -0.95752411931703396, 8.9569370743490193, -0.062041348029879102, -0.080157437015122804, 8.0102582504767295, -5.9688675669055504, 0.67530938859376199, 1.27437097858607, 5.0084164430027203, 0.35632315612076498, -3.3504197552733501, -4.6662276852701501, -0.607157596121083, 0.48644342530280699, -0.00097211385626449695, 4.8383102174293198, 5.4067550135312503, -0.10295717451613901, 29.4184191533957, -9.4450875338250793, -18.800441303291901, 8.5840933132932609, -37.118301659976296, 0.106267952523929, 0.66461896188866798, -11.4398182377096, 13.0631130369628, -0.68992479801260798, 1.9745973431694701, -10.3210596342876, -5.2304303953711804, 18.385374172705902, 17.020178998151501, -12.315621520081001, 3.7778248703987298, -0.00031338187670125201, 12.870239622711001, 12.0022872209785, -0.16605346741786001, 96.046941246958397, -16.9389614709639, -60.935799758442698, 35.1352737141356, -61.591085318216102, 0.111297136966112, 1.23095348877198, -10.067914675180299, 24.0397569908422, 1.55026659084186, 0.71351574089035996, -23.902604464805101, -14.335678342218401, 32.573495764200203, 25.978026199263301, -50.506323253986302, 6.2999821545807402, 0.00078010309855064104, -5.4500389454791298, -2.8881970061941198, 0.034137151949219097, -36.693158530832299, 5.3229408635849698, 23.065511761726999, -18.654750377009499, 16.655427409154399, 0.0120347437456702, -0.40190064848770302, -4.3952667136196499, -3.2283315530947299, 0.535114819933451, -1.6695636399303999, 4.8387109899640901, 5.9387464984757097, -9.2525260067921593, -7.0534068376986703, 24.6079478080533, -1.24249543569277, -0.00048592251459139902, 2.8352295963632699, 2.97576788056818, -0.061903426111554402, 15.662499828725799, -6.3594611155842697, -10.0297611955082, 4.4512302388898801, -22.9014624835775, 0.0522795583755256, 0.46237084970893699, -5.9599628993498204, 6.3134697655201197, -0.35523986461548501, 1.1938822885348901, -6.1222818696018599, -3.0697099757554498, 13.1385066502153, 10.0165667609847, -5.6534055293581504, 2.2982459946613698, 5.71641932114923e-05, -1.95937881355126, -3.1686710464991501, 0.0078900256254279908, -20.7802266137845, 1.9052049215289899, 13.243728372567, -7.2010122960325198, -1.78569599703996, -0.0023099999984344298, -0.181452511231602, 1.49235850994062, -3.4781928086271598, -0.25097197027097001, 0.034267435208927201, 2.9589361689912899, 2.1880246525605398, 0.40946783452396801, 1.85119165819145, 10.9769363093921, -0.49737197226351498, 0.00057014015696656801, -11.992703942957201, -9.1707599397024797, 0.13131957021746299, -80.913738884742898, 12.2802670275716, 51.275110674413497, -30.8846663544597, 40.768216707846101, -0.056350552707040001, -0.906909874969271, 4.5662724440002496, -16.493313057723601, -1.3954832548549501, -1.1309540462973, 17.671878079289101, 13.348292143643, -21.057182826114602, -17.2839203520208, 44.417018731905799, -5.1700529859646398, 0.00070585484241785499, -3.84393110623766, -3.8217546887026601, 0.042692631956155899, -33.103657623136797, 7.29987823117549, 21.1351246026951, -8.9046379168685696, 25.840620537279499, -0.077726091155589205, -0.51813471867742, 9.6014602253082906, -12.721891663249099, -1.51539376366047, -1.54216689848713, 11.448584843886, 4.4017938077693604, -13.490798207962101, -12.3088359993453, 13.904387711973399, -1.27899798343336, -4.8529590100271397e-05, 1.5144453784960501, 2.3396824932439499, -0.0087660084169081508, 9.4873136503254205, -1.65331055509645, -5.9367044032646401, 5.0146643904078898, -0.269092370588084, 0.0089905796176170498, 0.14805840549764701, -0.89101366694270501, 3.0317998491567302, 0.22142707740346401, 0.0064304970181167601, -3.4235077646052301, -1.69328028781498, 0.48844632252065601, -0.57157344288643996, -5.8659323559885497, 0.45402791645044299, 3.1177001030445297e-05, -2.4386266852651501, -0.31040563209251798, 0.0039504037521311498, -21.849203607580201, -0.45787097219896, 13.8161508224212, -9.4311122174081508, -5.4786114733527702, -0.0069717560537701602, 0.0049075772339915403, 1.65968311111433, -4.9313027452898597, -0.39825841496395797, 0.056303363068839998, 4.9803632483141103, 2.7343202713150898, 2.3452757571679799, 3.3498732374241098, 12.4790131924658, -0.41615992378439798}; -rc = qmckl_sherman_morrison_c(context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv); +const uint64_t N_updates2 = 2; +const uint64_t Updates_index2[2] = {20, 21}; +const double Updates2[42] = {-0.012056605890393198, 0.072118259966373, -0.14986032247543299, -0.023892195895314251, 0.2306191368843431, 0.070976656861603302, 0.059228850266663378, -0.0081594046205282003, 0.03775668889284136, -0.32248186320066397, -0.30175055470317586, -0.048578753136098399, -0.050512738234829151, 0.074964269995690003, 0.022375471889972701, 0.20063611492514641, -0.013817949220538101, 0.034675425849854905, 0.14269321411848099, 0.16303040878847203, 0.20520395040512121, 0.027209745720028898, -0.019752152264117806, 0.24686626344919221, 0.021544795483350802, 0.0053255971870385145, -0.074287162162363515, 0.0020896954229101539, -0.0015901625156403004, 0.045653678011149175, -0.095019596163183437, 0.015724316006526361, 0.057632524985820083, 0.0043175870669074383, -0.075611688196659296, -0.2787729352712634, 0.071667610667645931, -0.0016040895134210986, -0.018613442778587338, 0.16365851461887351, 0.018654582090675831, -0.43227782845497098}; +const double Slater2[441] = {-2.8945870399475102, 3.5455725193023699, 2.0470812320709202, -3.5464441776275599, -2.0474903583526598, -2.89596366882324, -0.61329728364944502, 0.70991641283035301, 0.45664468407630898, 0.59523195028305098, 0.26079276204109197, -0.027727147564291999, -0.35093706846237199, -0.095610238611698206, -0.130077064037323, 0.10946778208017301, 0.021800471469759899, 0.048480678349733401, -0.092234551906585693, -0.028107110410928698, 0.013431881554424799, -0.78021097183227495, -0.95558542013168302, -0.55174458026885997, -0.95579683780670199, -0.55179446935653698, 0.78044348955154397, -0.115299895405769, -0.11754634231329, -0.0318448171019554, -0.00082233443390577999, 0.064001239836216001, 0.12740932404995001, -0.049412809312343597, -0.074464745819568606, 0.19851659238338501, -0.088878795504569993, 0.135610401630402, -0.13736967742443101, -0.101879440248013, 0.174509197473526, 0.085864908993244199, -0.00527230883017182, 0.00029381641070358499, 0.0072919740341603799, -0.00026352208806201799, 0.0068838247098028703, 0.0047294595278799499, 0.11728889495134399, -0.062190085649490398, -0.15969239175319699, -0.10645916312933, 0.112943567335606, -0.0015487050404772199, -0.045737843960523598, 0.13196058571338701, 0.038660705089569099, -0.050266433507204097, -0.13745591044426, -0.037740666419267703, 0.11781705915927899, 0.044309988617896999, 0.215069741010666, -0.30874741077423101, -0.37815779447555498, 0.218254208564758, 0.378139227628708, -0.21839827299118, -0.30879178643226601, 0.025539221242070202, 0.112043909728527, 0.037676706910133403, 0.025347150862216901, -0.19991625845432301, 0.14163509011268599, 0.13326919078826899, 0.213842943310738, 0.131471157073975, 0.14626120030879999, -0.0118067460134625, 0.093547157943248693, 0.22439678013324699, -0.015649655833840401, 0.011034868657589, -1.52881526947021, -1.9163775505148799e-05, -2.1623263359069802, -1.5540548702119799e-05, 2.16284847259521, -1.52953028678894, -0.26402890682220498, 0.024944067001342801, -0.37140902876853898, -0.044071510434150703, -0.29843890666961698, -0.043834518641233403, -0.177285701036453, -0.058585006743669503, -0.0183692276477814, -0.026075478643178902, -0.15623773634433699, -0.011319605633616401, 0.054057534784078598, -0.00089795450912788499, 0.0060455044731497799, -0.067333526909351293, 0.00043256155913695698, 0.095035225152969402, -0.00043632232700474598, 0.094624765217304202, 0.066768139600753798, 0.14448715746402699, -0.12090456485748299, -0.203432962298393, -0.21472349762916601, 0.154288679361343, 0.017385326325893399, -0.071518480777740506, 0.27918133139610302, 0.080454014241695404, -0.0361245274543762, 0.0566458702087402, -0.030157707631588, 0.25150132179260298, -0.0114687560126185, -0.066873423755168901, -2.2779068946838401, -2.3393469746224599e-05, -3.2218937873840301, -1.7939200915861899e-05, 3.22278833389282, -2.2791447639465301, -0.47945570945739702, 0.045197278261184699, -0.64478874206543002, -0.080234304070472703, -0.47389149665832497, 0.024908870458602898, -0.23455648124218001, -0.10695217549800901, -0.033054649829864502, -0.195749551057816, -0.040076982229948002, 0.094596333801746396, 0.098401188850402804, -0.000334969052346423, 0.0023343940265476699, -0.0025739683769643298, -0.0020174346864223502, -0.0024467820767313199, -0.00204527890309691, 0.00013988610589876801, 0.00073755031917244196, 0.17339251935482, 0.099962860345840496, 0.14622049033641801, -0.088966980576515198, 0.040044382214546197, -0.14437201619148299, -1.5416861060657501e-05, -0.081159926950931494, -0.11909016221761699, 0.170753449201584, 0.031124599277973199, -0.052109345793724102, 0.121445283293724, 0.020809086039662399, -0.039619617164135, -0.0043673445470631097, -0.00014539182302542001, 0.0061219600029289696, 0.000189467871678062, 0.0060523007996380303, 0.00425094133242965, 0.0905451029539108, 0.058540407568216303, -0.15191346406936601, 0.11511342227459, 0.15016922354698201, 0.10024280846118901, -0.11066282540559801, -0.15089659392833699, -0.021995550021529201, 0.10021472722291901, 0.019932290539145501, 0.070281185209751101, -0.120184391736984, 0.0072047915309667596, 0.043619588017463698, -0.0097634727135300602, 0.0119331693276763, -0.0068263513967394803, 0.011701960116624799, -0.0068089049309492103, 0.0095072658732533507, 0.133816182613373, -0.15090283751487699, 0.070243604481220204, 0.077758952975273105, -0.071993313729763003, -0.0526336021721363, -0.033549431711435297, -0.029018172994255999, 0.10475520789623299, 0.047332767397165298, 0.17077720165252699, 0.057527918368577999, -0.043988067656755399, -0.21170908212661699, 0.0024762949906289599, -0.71565270423889205, 2.80283820757177e-05, 1.0121610164642301, -2.41986454057042e-05, 1.0123220682144201, 0.71586799621581998, -0.045286595821380601, -0.0269623268395662, 0.0683262273669243, -0.047560662031173699, -0.062597043812274905, -0.0278066452592611, 0.045772761106491103, 0.063010454177856404, 0.0197743345052004, -0.025724532082676901, -0.20542661845684099, -0.0248414911329746, 0.058127623051405002, 0.00210775528103113, 0.0140155302360654, -0.00073456991231069001, 0.000104061764432117, -0.0010063005611300501, 0.00014142321015242501, 0.00095045292982831597, -0.00064003589795902404, 0.056538689881563201, -0.038196403533220298, 0.095246985554695102, 0.077704243361949907, 0.089713566005229894, 0.071932643651962294, 0.058404259383678402, 0.097089007496833801, -1.8242251826450202e-05, -0.070699930191039997, 0.0231548044830561, 0.036239527165889698, -0.064700096845626803, -0.012914831750094899, 0.058629415929317502, -0.0285779368132353, 2.2119384368579599e-07, -0.0404084548354149, 4.62594880445977e-06, 0.040473498404025997, -0.028664523735642398, 0.0818745791912079, -0.0072916029021143896, 0.171691119670868, 0.0142411412671208, 0.227563425898552, 0.20764905214309701, 0.23875248432159399, 0.019401129335165, 0.0041248365305364097, -0.273390233516693, 0.031942136585712398, 0.24207504093647, -0.016599044203758202, -0.00059447408420965097, 0.00458275340497494, -0.083720728754997295, -0.102523192763329, -0.059237916022539097, -0.10253403335809699, -0.0591498985886574, 0.083691440522670704, 0.093738317489623996, 0.118414394557476, 0.119053602218628, -0.19025875627994501, -0.017257452011108398, 0.111288614571095, -0.14737996459007299, -0.106449924409389, 0.119639433920383, -0.0358475148677826, 0.16083629429340399, -0.135845571756363, -0.045223556458950001, 0.204596728086472, 0.091698803007602706, -0.0016409500967711199, 0.0020083498675376199, 0.0011536112288013101, -0.0019761291332542901, -0.0011378186754882301, -0.0015965295024216199, 0.062009602785110501, -0.085591755807399694, -0.073869466781616197, -0.129948750138283, -0.025633471086621298, 0.092304252088069902, 0.11476875841617599, 0.0570255033671856, -0.098354063928127303, 0.048130486160516697, -0.075562968850135803, -0.087558984756469699, -0.061446368694305399, 0.096327632665634197, -0.084247380495071397, -0.086937576532363905, -5.2227896958356703e-05, -0.12295132130384399, -5.67086790397298e-05, 0.122932203114033, -0.086922481656074496, 0.092386581003665896, 0.0563923679292202, 0.16267444193363201, -0.103307262063026, 0.177027583122253, 0.119934171438217, 0.15235325694084201, -0.13730293512344399, -0.036718469113111503, -0.13380806148052199, -0.14056211709976199, 0.11525499820709199, 0.122316166758537, -0.0109922774136066, 0.077829994261264801, -0.71328485012054399, -0.87364697456359897, -0.50431287288665805, -0.87368428707122803, -0.50450080633163497, 0.71341556310653698, -0.0728774294257164, -0.0137394573539495, -0.131415024399757, 0.120499663054943, -0.15048809349536901, 0.067258194088935894, -0.016238121315836899, 0.25341770052909901, 0.061544414609670597, -0.124150305986404, -0.023104058578610399, 0.161576017737389, -0.18417926132678999, -0.0301918238401413, -0.017013777047395699, -0.00358590018004179, -3.1569013572152501e-06, 0.00505110481753945, -1.33700987134944e-05, 0.0050756097771227403, 0.0036168387159705201, 0.076649472117423997, -0.0148532707244158, -0.15424914658069599, -0.031277053058147403, 0.20174449682235701, 0.17827098071575201, -0.21435502171516399, 0.043405968695879003, 0.0060502337291836704, 0.23922684788703899, 0.022777535021305102, 0.22072769701480899, 0.035028267651796299, -0.0024164030328393, -0.017579320818185799, -0.0137155568227172, -0.00072690693195909305, 0.019026592373848, 0.00073597067967057196, 0.018235495314001999, 0.012611641548574, 0.14907942712307001, 0.10721461474895499, -0.205590710043907, 0.18899101018905601, 0.14405034482479101, 0.0080890702083706908, -0.049517802894115399, -0.23817741870880099, -0.062822751700878102, -0.056222390383482, 0.079762905836105305, -0.057780988514423398, -0.208331778645515, 0.030398890376091, 0.14741712808609, -0.13207408785819999, -0.00012266315752640399, -0.18668732047080999, -0.000116608949610963, 0.18647037446498901, -0.13181127607822399, 0.17992316186428101, 0.0310163982212543, 0.194987177848816, -0.051282022148370701, 0.079243704676628099, -0.16229276359081299, -0.029616238549351699, -0.065854735672473894, -0.025143278762698201, 0.277732163667679, -0.117880158126354, -0.184251189231873, 0.0632317289710045, -0.0045813838951289697, 0.024331344291567799, -0.0068073021247982996, -0.0083365431055426598, 0.0048150913789868398, 0.0083073899149894697, -0.0047997133806347804, -0.0067770029418170504, 0.077614806592464405, 0.12953585386276201, -0.063416801393032102, 0.138088583946228, -0.10224375873804099, 0.130568191409111, 0.164952263236046, 0.026345754042267799, 0.13718618452549, 0.084768116474151597, 0.096043966710567502, -0.054612904787063599, 0.138456135988235, 0.13371524214744601, -0.19178953766822801}; +double Slater_inv2[441] = {-0.064091478343647895, 713.06177859755496, -52.018444001735702, 0.22294142549212401, 6739.1399551272798, 409.47332011602299, -4258.7085329747897, 2990.6198857571399, 2842.82174111627, -16.4362076124787, -19.6479024764561, -450.95698589104001, 1499.21617070053, 129.354086480939, -32.5623649949015, -1533.16729952379, -801.75588044433505, -1302.1490458327801, -1589.22747455529, -3895.5139631694801, 69.692448899038894, 0.078717515330272506, -890.24945003874404, 61.925371835460197, -1.59301536151858, -8399.1221177311709, -504.62121099099301, 5307.6897279898503, -3725.8058949477299, -3517.1067799943698, 20.0821069369808, 23.8371292623433, 563.21704392130198, -1868.99615781019, -160.79773282728499, 40.209679175758602, 1910.8342353503599, 1000.30652221449, 1610.10305651065, 1967.2714135880001, 4853.9412977750599, -86.938972564264105, 0.035772543187836597, 520.38606836760005, -37.3576026553948, 0.93824771966655895, 4913.8375731575898, 297.02078853525001, -3105.3054726097698, 2179.8383098375198, 2064.03863882426, -11.5897837400758, -13.7454041271756, -329.662381563542, 1093.32256576446, 94.164922311323394, -23.370538453071202, -1117.8490893585799, -585.07554862150903, -945.21841098621996, -1153.8443875258399, -2840.0954494666398, 50.509996472385303, -0.062171023850398299, -883.91684171449401, 65.956744158981707, -0.30209264289181997, -8354.6527651622891, -510.24292797392201, 5279.5127573481996, -3708.5126037463401, -3534.1651244869099, 20.118054506627601, 24.253115792914802, 558.90980701110504, -1858.4878939499599, -160.30158683160701, 40.074632460370502, 1900.40832678587, 993.28424539653497, 1619.3228924922901, 1974.7898591375399, 4829.6374496633298, -85.861801422967005, -0.045296585245108302, 503.608089249118, -37.409231418514402, 0.15972971393766999, 4760.0409737735199, 289.86000580815897, -3007.9000554557201, 2112.4472365954498, 2009.46047743586, -11.620588884143499, -13.435110153350299, -318.37193513541001, 1059.1982996055399, 91.392671066014998, -23.013250839168599, -1083.0984474979, -566.25418012298701, -920.44766441625598, -1123.03275109381, -2751.24966532286, 49.134449946833101, -0.050574070850706303, -735.268788752521, 52.034324888924203, -1.3246973887217, -6942.4299970826296, -419.091569409214, 4387.0782989889804, -3079.7112127626101, -2915.54203952635, 16.3862338355292, 20.069350976326799, 465.60100478088498, -1545.0790688177201, -133.05534575663401, 33.017866331913801, 1579.60766417078, 826.67092177544703, 1335.1987409164999, 1630.19252491066, 4012.1274550981102, -71.423354704319806, -0.00110547248442243, 66.086472294581398, -8.0640571635796796, 0.120361096092389, 643.91485283159295, 47.038233657028698, -406.863770451839, 288.91657765213398, 305.14483180816802, 0.028924090527909001, -2.4114842655012301, -39.3897517070086, 140.96244082771301, 13.290701732299899, -2.82866188450281, -144.284041440354, -74.462522726873601, -141.49789272768501, -167.03129270601499, -373.94726486427999, 5.3217330886365399, 0.00169058806401361, -100.681182204012, 9.9438606966790992, -0.16071917417936801, -947.22789644116904, -62.1819544991477, 598.507402482923, -421.456732120239, -417.90099350750501, -0.071547956877298299, 3.03910354158063, 58.825827638175099, -207.18138234350499, -16.8210784946065, 3.4953362885853601, 212.690544720802, 112.99993227712, 192.20097004017899, 232.57136070342199, 549.86422579734096, -7.9115450643297303, 0.00031167490112610501, 16.5702800434129, -0.96427444933400797, 0.017530807484877599, 153.70562899881901, 7.4253775224466096, -97.164535381519997, 68.391115404813903, 58.880541272935403, -0.00395431753418613, -0.27710621824447701, -6.5580129619132999, 32.685848366303901, 3.4769501442949502, -1.3237352902339601, -33.496400026660503, -18.678955342199799, -26.814344384641199, -34.430890540207301, -88.9250347843996, 1.51194685980572, 0.00045214452900354401, 37.241126324245002, 0.56653388165982099, -0.0153845901652373, 340.71285233348101, 15.613889705904301, -215.25964333041301, 151.26187968817001, 126.42681477968, 0.012659113756634199, -0.62711870198964903, -16.4637553538752, 71.986464894089806, 5.1001819045344803, -2.8075780414188398, -75.205305646206597, -41.656360989756003, -57.009250230864701, -71.671627817787495, -198.46090263475699, 5.47499644859007, 0.00085034576532286798, -48.324269416315303, 9.5426055788579802, -0.11918347900064399, -478.70065330731398, -38.914234951661598, 302.33505716911202, -216.13813506153201, -246.345286296176, 0.0018122457897085001, 2.0086911418790101, 27.577828210674401, -102.039313769876, -10.0857520350279, 1.94810040129421, 105.928854388454, 54.502095992205597, 115.30853907215899, 134.79460379303401, 280.65999252254602, -3.2448445639062502, -0.00017551641849241999, -35.157826546458601, -5.8891909991296698, 0.051680022896045397, -316.44550618039898, -5.0414187570711899, 200.212034255265, -135.39535162931199, -69.139114300097802, -0.16142175154882901, -0.0102013166269541, 31.668569875843001, -76.263188383823703, -5.0017512656630601, 2.0769594366589001, 76.002080804042095, 39.333282449810902, 30.0808204248134, 43.085264407243301, 177.27763312527699, -5.4457981556032404, -0.000306806291909659, -47.201229402180303, -1.2172052207398101, -0.0186567796198484, -436.83683166616999, -19.215912540534301, 276.031946309869, -192.67292600019499, -154.03017691774701, -0.042507166509503203, 0.76934514300024204, 23.977306301563999, -92.169363151535805, -9.1886362611435199, 3.1760937062011898, 95.958352522850603, 53.119118943843198, 68.432833843960694, 88.505438350444805, 253.98266241440601, -5.1028992571309599, 0.00043306496689241199, -45.515914649852498, 4.5704850382447297, -0.071472003061512898, -427.071656721686, -27.901412337784699, 269.85362292975498, -190.66655819995299, -192.761246218769, -0.0556222307934695, 1.3484518181471401, 29.668595531405, -94.026613967410796, -7.9849268838018501, 2.0615436543321501, 95.338384205774105, 51.130038963438999, 88.724620902414898, 106.181452502913, 248.269046435468, -3.6638133123307002, 0.00067386198047795695, 2.86001067576094, -1.83043518435104, 0.020675455904269301, 37.761848158240802, 6.8832167853114203, -24.015453768006701, 13.4834243521102, 35.324760224278002, 0.035792229507666501, -0.41862408163183901, -10.0509290141389, 13.5759504464113, 1.8922504612450599, -1.8614272588155001, -12.132753308102799, -3.3789310584400698, -17.244465911049499, -18.4686894621614, -17.916485915275999, 0.17564274753793899, -4.5499005275636101e-05, -31.614155756215101, -1.4091932535724401, -0.0060978442331452703, -292.99139921717801, -12.827598964788001, 185.144804328112, -128.77786179229901, -100.295349372036, -0.046207312260184701, 0.53169799203163903, 17.4856359712815, -63.3488322133691, -5.98125785658572, 1.9892546441005501, 64.233075829740997, 35.5568060355128, 46.269165313517597, 57.338723422189801, 170.63201646028199, -3.5806585828097099, 8.4039919523263399e-05, -4.0615650791823299, -3.4362521652092002, 0.011295419555382699, -39.6150470544694, 1.5105032334831401, 25.1537606371501, -15.330979335618601, -6.5084614221869197, -0.0083199111964546105, -0.17722199841012101, 2.9230666468463902, -7.7291578970740504, -0.59428543237974696, 0.082803013560185101, 7.2521932229389696, 4.54510970987024, 2.43118215251519, 4.7389061057811901, 21.734306554021401, -0.85611719611089199, -0.00025843236821193301, 52.817220161181702, -0.92129495231099501, 0.0263320504370466, 499.75948842769702, 24.448830234480202, -315.90847327586999, 219.760367065808, 186.369999846479, 0.12893364165019799, -1.03733562237538, -39.542133782410801, 114.562973083925, 9.1887926425616406, -2.6272948799917999, -114.688259732943, -59.320103692053301, -83.386175100226296, -106.311499516864, -287.23025749328701, 5.8899806135276798, 0.00029561730769906699, 28.2443444301325, 0.262667708054178, -0.0092881180472059802, 254.39556062397901, 13.3246994983259, -160.662465459228, 115.19312959924299, 97.930045120340793, 0.0140106353296333, -0.58271028141190895, -12.237212046379099, 52.1658593813167, 3.7250252932039301, -2.2830256115872798, -54.084720909199703, -31.577318042678201, -44.3507306279147, -56.3876021769941, -150.29869271905301, 4.1969751871532797, -3.5190977196700897e-05, 0.47111547837818402, 2.2068800929897598, -0.0070758873430103201, 0.13945915693743799, -1.8492037922933, -0.025671220257021801, 0.97970429288930505, -2.6130342276240199, 0.0060078182170399397, 0.15015803890865601, -0.18094310755408499, 0.92201583351316796, 0.051038179907958503, 0.030519047562509002, -1.2927339475995701, -0.52344231597663404, 1.4918374263167999, 0.861619645390301, -0.52697347953005502, 0.27598012654535198, -0.00073600321123188305, 57.569266190747499, 7.3278228968032701, -0.093258163105288297, 515.79957938656798, 10.8090738278263, -326.16130596512397, 222.642609875217, 129.33494256044199, 0.16458397773696601, -0.115854395362115, -39.1805516577625, 116.41448940344399, 9.4017853746533593, -1.32916748411286, -117.572672890536, -64.549778160481395, -55.365507632190301, -79.081290004649304, -294.59516563799099, 9.8243907421444003}; + +const uint64_t N_updates3 = 3; +const uint64_t Updates_index3[3] = {12, 13, 21}; +const double Updates3[63] = {-0.32320992089807998, -0.1768221333622936, -0.044189138920046375, -0.0083658993244170032, -0.13345118239521958, -0.088903807103633908, -0.25946535170078289, 0.14435659933042233, -0.21090563386678701, 0.019084170460701003, 0.073579406365752206, -0.013528384268283893, 0.031103432178496981, -0.25866857916116798, 0.022464506328106093, 0.032419085502625011, -0.083496315404772786, -0.392626002430916, -0.057606873102486092, 0.1326765250414613, 0.034384071826935009, 0.25532682985067379, -0.025051936507225009, 0.17769842967391061, 0.080573752522469011, 0.11870069429278349, 0.35069981217384349, 0.127604305744171, -0.081144510089870836, -0.04023376852273898, 0.0045312587171792984, 0.017237693071365301, 0.0386847481131554, -0.21935135498642899, 0.040930040180683996, -0.057743255048990395, -0.289656192064286, 0.26965582184493592, 0.257760990411043, -0.1886596158146856, -0.036238497123122194, -0.1386065091937782, 0.0015524076297879202, -0.1212832294404507, 0.028310360386967659, -0.005844349274411801, 0.0046449899673459971, 0.044258039444684996, 0.0025386139750480999, 0.0354412645101548, 0.064816890284419101, 0.1017611473798752, -0.25162110477685901, -0.0285851191729307, -0.024413086473941803, -0.22420015186071351, 0.059393912553786996, 0.04153373837471, 0.01215143408626318, 0.203658737242222, -0.0020150262862444011, -0.037645858246833121, 0.0714646056294439}; +const double Slater3[441] = {-2.8945870399475102, 3.5455725193023699, 2.0470812320709202, -3.5464441776275599, -2.0474903583526598, -2.89596366882324, -0.61329728364944502, 0.70991641283035301, 0.45664468407630898, 0.59523195028305098, 0.26079276204109197, -0.35093706846237199, -0.095610238611698206, -0.130077064037323, 0.10946778208017301, 0.021800471469759899, 0.048480678349733401, -0.092234551906585693, -0.0160505045205355, -0.028107110410928698, 0.0080896317958831804, -0.78021097183227495, -0.95558542013168302, -0.55174458026885997, -0.95579683780670199, -0.55179446935653698, 0.78044348955154397, -0.115299895405769, -0.11754634231329, -0.0318448171019554, -0.00082233443390577999, 0.064001239836216001, -0.049412809312343597, -0.074464745819568606, 0.19851659238338501, -0.088878795504569993, 0.135610401630402, -0.13736967742443101, -0.101879440248013, 0.102390937507153, 0.174509197473526, -0.0599150508642197, -0.00527230883017182, 0.00029381641070358499, 0.0072919740341603799, -0.00026352208806201799, 0.0068838247098028703, 0.0047294595278799499, 0.11728889495134399, -0.062190085649490398, -0.15969239175319699, -0.10645916312933, 0.112943567335606, -0.045737843960523598, 0.13196058571338701, 0.038660705089569099, -0.050266433507204097, -0.13745591044426, -0.037740666419267703, 0.11781705915927899, 0.19417031109332999, 0.044309988617896999, 0.0096954777836799604, -0.30874741077423101, -0.37815779447555498, 0.218254208564758, 0.378139227628708, -0.21839827299118, -0.30879178643226601, 0.025539221242070202, 0.112043909728527, 0.037676706910133403, 0.025347150862216901, -0.19991625845432301, 0.13326919078826899, 0.213842943310738, 0.131471157073975, 0.14626120030879999, -0.0118067460134625, 0.093547157943248693, 0.22439678013324699, 0.0082425400614738499, -0.015649655833840401, -0.00653020711615682, -1.52881526947021, -1.9163775505148799e-05, -2.1623263359069802, -1.5540548702119799e-05, 2.16284847259521, -1.52953028678894, -0.26402890682220498, 0.024944067001342801, -0.37140902876853898, -0.044071510434150703, -0.29843890666961698, -0.177285701036453, -0.058585006743669503, -0.0183692276477814, -0.026075478643178902, -0.15623773634433699, -0.011319605633616401, 0.054057534784078598, -0.23151709139347099, -0.00089795450912788499, 0.10536465793848, -0.067333526909351293, 0.00043256155913695698, 0.095035225152969402, -0.00043632232700474598, 0.094624765217304202, 0.066768139600753798, 0.14448715746402699, -0.12090456485748299, -0.203432962298393, -0.21472349762916601, 0.154288679361343, -0.071518480777740506, 0.27918133139610302, 0.080454014241695404, -0.0361245274543762, 0.0566458702087402, -0.030157707631588, 0.25150132179260298, -0.082445412874221802, -0.0114687560126185, 0.027113301679492, -2.2779068946838401, -2.3393469746224599e-05, -3.2218937873840301, -1.7939200915861899e-05, 3.22278833389282, -2.2791447639465301, -0.47945570945739702, 0.045197278261184699, -0.64478874206543002, -0.080234304070472703, -0.47389149665832497, -0.23455648124218001, -0.10695217549800901, -0.033054649829864502, -0.195749551057816, -0.040076982229948002, 0.094596333801746396, 0.098401188850402804, -0.059563819319009802, -0.000334969052346423, 0.030707944184541699, -0.0025739683769643298, -0.0020174346864223502, -0.0024467820767313199, -0.00204527890309691, 0.00013988610589876801, 0.00073755031917244196, 0.17339251935482, 0.099962860345840496, 0.14622049033641801, -0.088966980576515198, 0.040044382214546197, -1.5416861060657501e-05, -0.081159926950931494, -0.11909016221761699, 0.170753449201584, 0.031124599277973199, -0.052109345793724102, 0.121445283293724, 0.0289684906601906, 0.020809086039662399, 0.0544226132333279, -0.0043673445470631097, -0.00014539182302542001, 0.0061219600029289696, 0.000189467871678062, 0.0060523007996380303, 0.00425094133242965, 0.0905451029539108, 0.058540407568216303, -0.15191346406936601, 0.11511342227459, 0.15016922354698201, -0.11066282540559801, -0.15089659392833699, -0.021995550021529201, 0.10021472722291901, 0.019932290539145501, 0.070281185209751101, -0.120184391736984, -0.030551897361874601, 0.0072047915309667596, 0.041792899370193502, -0.0097634727135300602, 0.0119331693276763, -0.0068263513967394803, 0.011701960116624799, -0.0068089049309492103, 0.0095072658732533507, 0.133816182613373, -0.15090283751487699, 0.070243604481220204, 0.077758952975273105, -0.071993313729763003, -0.033549431711435297, -0.029018172994255999, 0.10475520789623299, 0.047332767397165298, 0.17077720165252699, 0.057527918368577999, -0.043988067656755399, 0.11077278107404701, -0.21170908212661699, 0.043612048029899597, -0.71565270423889205, 2.80283820757177e-05, 1.0121610164642301, -2.41986454057042e-05, 1.0123220682144201, 0.71586799621581998, -0.045286595821380601, -0.0269623268395662, 0.0683262273669243, -0.047560662031173699, -0.062597043812274905, 0.045772761106491103, 0.063010454177856404, 0.0197743345052004, -0.025724532082676901, -0.20542661845684099, -0.0248414911329746, 0.058127623051405002, 0.30385830998420699, 0.00210775528103113, -0.12754787504673001, -0.00073456991231069001, 0.000104061764432117, -0.0010063005611300501, 0.00014142321015242501, 0.00095045292982831597, -0.00064003589795902404, 0.056538689881563201, -0.038196403533220298, 0.095246985554695102, 0.077704243361949907, 0.089713566005229894, 0.058404259383678402, 0.097089007496833801, -1.8242251826450202e-05, -0.070699930191039997, 0.0231548044830561, 0.036239527165889698, -0.064700096845626803, 0.035663921386003501, -0.012914831750094899, -0.0478814952075481, -0.0285779368132353, 2.2119384368579599e-07, -0.0404084548354149, 4.62594880445977e-06, 0.040473498404025997, -0.028664523735642398, 0.0818745791912079, -0.0072916029021143896, 0.171691119670868, 0.0142411412671208, 0.227563425898552, 0.23875248432159399, 0.019401129335165, 0.0041248365305364097, -0.273390233516693, 0.031942136585712398, 0.24207504093647, -0.016599044203758202, 0.0499182641506195, -0.00059447408420965097, -0.092382267117500305, -0.083720728754997295, -0.102523192763329, -0.059237916022539097, -0.10253403335809699, -0.0591498985886574, 0.083691440522670704, 0.093738317489623996, 0.118414394557476, 0.119053602218628, -0.19025875627994501, -0.017257452011108398, -0.14737996459007299, -0.106449924409389, 0.119639433920383, -0.0358475148677826, 0.16083629429340399, -0.135845571756363, -0.045223556458950001, 0.129632458090782, 0.204596728086472, -0.089926846325397505, -0.0016409500967711199, 0.0020083498675376199, 0.0011536112288013101, -0.0019761291332542901, -0.0011378186754882301, -0.0015965295024216199, 0.062009602785110501, -0.085591755807399694, -0.073869466781616197, -0.129948750138283, -0.025633471086621298, 0.11476875841617599, 0.0570255033671856, -0.098354063928127303, 0.048130486160516697, -0.075562968850135803, -0.087558984756469699, -0.061446368694305399, 0.073952160775661496, 0.096327632665634197, -0.10392674803733799, -0.086937576532363905, -5.2227896958356703e-05, -0.12295132130384399, -5.67086790397298e-05, 0.122932203114033, -0.086922481656074496, 0.092386581003665896, 0.0563923679292202, 0.16267444193363201, -0.103307262063026, 0.177027583122253, 0.15235325694084201, -0.13730293512344399, -0.036718469113111503, -0.13380806148052199, -0.14056211709976199, 0.11525499820709199, 0.122316166758537, -0.211628392338753, -0.0109922774136066, 0.17250911891460399, -0.71328485012054399, -0.87364697456359897, -0.50431287288665805, -0.87368428707122803, -0.50450080633163497, 0.71341556310653698, -0.0728774294257164, -0.0137394573539495, -0.131415024399757, 0.120499663054943, -0.15048809349536901, -0.016238121315836899, 0.25341770052909901, 0.061544414609670597, -0.124150305986404, -0.023104058578610399, 0.161576017737389, -0.18417926132678999, -0.016373874619603199, -0.0301918238401413, 0.00962609611451626, -0.00358590018004179, -3.1569013572152501e-06, 0.00505110481753945, -1.33700987134944e-05, 0.0050756097771227403, 0.0036168387159705201, 0.076649472117423997, -0.0148532707244158, -0.15424914658069599, -0.031277053058147403, 0.20174449682235701, -0.21435502171516399, 0.043405968695879003, 0.0060502337291836704, 0.23922684788703899, 0.022777535021305102, 0.22072769701480899, 0.035028267651796299, -0.037091828882694203, -0.0024164030328393, 0.115568056702614, -0.0137155568227172, -0.00072690693195909305, 0.019026592373848, 0.00073597067967057196, 0.018235495314001999, 0.012611641548574, 0.14907942712307001, 0.10721461474895499, -0.205590710043907, 0.18899101018905601, 0.14405034482479101, -0.049517802894115399, -0.23817741870880099, -0.062822751700878102, -0.056222390383482, 0.079762905836105305, -0.057780988514423398, -0.208331778645515, -0.11229432374239, 0.030398890376091, 0.0136762224137783, -0.13207408785819999, -0.00012266315752640399, -0.18668732047080999, -0.000116608949610963, 0.18647037446498901, -0.13181127607822399, 0.17992316186428101, 0.0310163982212543, 0.194987177848816, -0.051282022148370701, 0.079243704676628099, -0.029616238549351699, -0.065854735672473894, -0.025143278762698201, 0.277732163667679, -0.117880158126354, -0.184251189231873, 0.0632317289710045, -0.16761179268360099, -0.0045813838951289697, -0.030651951208710702, -0.0068073021247982996, -0.0083365431055426598, 0.0048150913789868398, 0.0083073899149894697, -0.0047997133806347804, -0.0067770029418170504, 0.077614806592464405, 0.12953585386276201, -0.063416801393032102, 0.138088583946228, -0.10224375873804099, 0.164952263236046, 0.026345754042267799, 0.13718618452549, 0.084768116474151597, 0.096043966710567502, -0.054612904787063599, 0.138456135988235, -0.071488708257675199, 0.13371524214744601, 0.14154277741908999}; +// WB3 +double Slater_inv3_1[441] = {-0.056658742514349103, -9.5006825962797503, -18.307026635935799, -0.36744251865365501, 31.610841135834299, 39.084671241308698, -19.703711132730799, 18.666497646833299, 121.964198363159, -17.598444551917201, -2.9520245875548698, 24.935160344122199, 13.992695020707, 4.6612706754314903, -3.6234738869455199, -28.604054847833801, 9.5739197944338503, -62.128443913882499, -67.232459151277695, -11.803301377693099, -3.8508731471217099, 0.069411805979426894, 10.8007994955779, 22.458394727678201, -0.89282708659453403, -39.476164388726097, -47.5420201141931, 24.536662733275399, -23.351558477080602, -146.60044409871099, 21.549928185153298, 3.32891560872004, -30.5549979706051, -17.384760133954, -5.4401084934617003, 4.3730845094487396, 35.2040348414587, -11.414817838980399, 74.926509290741393, 80.145978783950099, 14.6842509146363, 5.7893824160342398, 0.041199702875412497, -6.4779318938824302, -13.2989719358296, 0.51508213587065199, 23.9434304832055, 27.923633944040301, -14.994539048994801, 13.545190256632999, 84.658750799602501, -12.440996315879, -1.6347815496642299, 17.4053340515119, 10.4563880132908, 3.2716511123291698, -2.32038524814726, -20.901080430435499, 6.5092932119827198, -43.310144838525801, -46.266317618221201, -9.0209731319320596, -3.3217327746699499, -0.071364036152653701, 11.529909516191401, 22.9175425489932, 0.44722818276140403, -39.897585842875301, -48.876557451246697, 24.801523764393401, -23.690956189203401, -151.28132599138999, 21.549304148995901, 3.4094704881876998, -30.687597458642099, -17.659848105023201, -5.7069215817131997, 4.0886157921745996, 35.564950307785701, -12.1803912964186, 77.135406641174299, 83.318689013925706, 14.819424258558801, 4.7782939163062803, -0.040051226770134098, -6.7134150132482402, -13.312257348225099, -0.26126985985289403, 22.204441530888801, 27.729627986407898, -13.7012421876807, 13.0503428483308, 85.297842345116607, -12.439369240025201, -1.60848061970372, 17.698309764178902, 10.1798985121263, 3.3110252774145601, -2.5466287558690199, -20.410023365852201, 6.7633439222022202, -43.4149505982517, -46.886928763683102, -7.88950712988734, -2.6927901019362199, -0.058248999176268398, 9.0508747193022892, 18.587941141225699, -0.73447131422595202, -35.308936282117699, -39.940782969048001, 21.9119312895712, -20.076960036338601, -123.935102576568, 17.592669318251101, 3.0259816420954402, -24.782453059479, -15.379073099754899, -4.67601503080067, 3.33242427220405, 30.0344780145867, -9.0772191462285008, 63.391820359557002, 67.760837774760006, 13.3701295015636, 4.8413052345891403, -0.00048534604109837199, -1.8238859168577699, 0.56645976558050504, -0.011652978445607001, 3.3511865791586, 2.0262681174419299, -2.14462816857628, 1.8811114733258301, 1.72516289469276, -0.0410444803602956, -0.17992011162600399, 4.6474809764852196, 0.32638302042170703, 1.28068103014527, 0.42381953652975901, -1.62158383882094, 1.84081037263479, -1.2636267813034701, -0.97726719185308597, -0.84319863660797401, 0.57245121780013697, 0.00072965273109526496, -0.74868100456805098, 0.61375144696985096, -0.013670796650539699, -10.880212250529199, -2.2389072194253701, 6.8446360871752603, -3.8338819099152301, -0.83708262317409499, 0.055638693619984997, 0.16395892268443801, -6.4020540512225601, -0.87619791103918299, 0.67273193621704896, -0.96217527481654197, 3.5322304037025498, 0.74780382069687101, 0.457651060635482, 2.4127372990709501, 5.8207812126355103, 0.41153697505715597, 0.00047300381075295099, -0.24273841428794099, 0.62931133864105804, -0.0075433586410305498, -3.8733549821913198, -2.7042122832831499, 2.4066006453807001, -1.90501007795962, -11.4961539239149, -0.025181201641384401, 0.20951155742128399, 4.41315756942062, -2.02827911285326, 0.53245648205106699, -0.57146100385840204, 1.6986603412216601, 0.20698230514139301, 5.5487259477006203, 4.3923373342920504, 2.6422104099671002, 0.12108516249854701, 0.00082691786224778699, 0.113024111733347, 2.7966391201096901, -0.052696331353419397, -4.8718908471754601, -4.3479524721016301, 3.1326652654405498, -2.1520186098021998, -17.7293360378548, -0.043482158450766098, 0.29115918226676102, 7.9265874331542596, -4.4255647905147004, -1.3335239860704799, -1.2720331573702599, 2.2195046250833101, 0.037526349197067099, 8.8672908187991606, 8.6317273115312592, 1.83700699526623, 1.8931859854467199, 0.000439374179950941, 1.8174276372186899, -0.095470042913778502, 0.0240432915091328, 0.33095163979973902, 0.419313643627721, -0.26508090252151401, 0.40758512406775099, 6.2032604963961004, 0.0299978360553445, -0.0350221248964512, -4.5247535085126103, 2.4252753636201798, -1.0443273705703999, -0.77183418222125399, -0.15673357470618601, -1.86654030909075, -2.3976989367798298, -1.56808861204302, 0.340202658594777, -1.0312623606052, -0.00063346566713256398, -0.661487272350328, -0.31969668820761499, -0.0207136433303984, -9.5617277834137209, -0.76548087353469296, 6.1338905273463604, -3.6493438141085299, -1.93160595722129, -0.054328540468196101, 0.063300925950509901, 8.0421985164502203, -6.7317743058458301, 0.56920882928816896, 1.39543139815216, 5.8217064803946901, 0.664937044390989, 2.0166407848672301, 0.66314768899536403, 2.4978865189964501, 0.90776612934725198, -0.00080526074137288, 0.866074714994297, -3.1810443538305599, 0.016712052067642799, 8.8525588583729107, 4.9029982933499703, -5.6387712154483003, 4.6377500718450797, 24.5361964752293, 0.036812637615073897, -0.307516025692601, -7.7158500239832, 6.5793196290456004, -0.90848412347546603, 1.2781649114678699, -4.0662241638244598, -0.85073071123983601, -12.848505169556301, -11.568586481641701, -3.9619743954566902, -0.100174674295188, 0.00069201116604256595, -0.421899716446686, -0.59032673715943695, 0.00276476648616889, 5.2753594946225197, 3.1708842333983198, -3.5051204501630502, -1.5506563388697101, 13.474253171986501, 0.038327175723695497, -0.21097106418518499, -8.0266607832375794, 6.6217101288174902, 1.26803738570163, -1.6239859547120901, -5.0491300215678701, 0.316141906166655, -6.8977435746728997, -6.9768951380000299, 1.3337978430772699, 0.27199695684951902, -0.00038359474997356102, 0.72100151176486804, -2.5365266414467098, 0.014980427848668199, 6.4663011480631196, 3.0354904137032901, -4.11275562441097, 3.6805173953314201, 18.1353313216757, 0.0085443837305102504, -0.16921638348780199, -3.85900106683119, 3.0428583654892001, -0.42146305418508101, 0.73140085261157395, -3.0095115595924198, -0.74724977432843798, -7.5689235578938199, -9.1654977643928905, -2.6018219553374502, -0.138580489522561, 3.1034344981670402e-05, 0.57346844296584099, -3.2816001969233399, 0.0098861018626169896, 2.7223870822496599, 3.19376385336182, -1.6094836478010499, 3.2093742171519399, 7.7061355268378202, 0.00180174673425388, -0.239342015844032, -0.17647999921287399, 1.7270571869450699, 0.18584316968323999, -0.066662651903874603, -2.3139065344532099, -0.65593666316055899, -3.9145254849983999, -3.4618799405385898, -2.6291335069492199, -0.23750024714478199, 0.00031371845096864198, -0.27014711720045598, -0.259122675110673, 0.0083797376871939597, 10.324015180961201, 0.62494833390683702, -6.5624316442850503, 3.9711776808922599, 2.31246521547006, 0.030498354639596902, -0.030734962225840101, -4.3487398562952402, 5.7898821592163596, 0.12407032656822101, -0.67808345005445703, -4.5636059941770499, 0.27242993392548098, -0.151105792955298, -2.1330095124199899, -4.5785158627476203, -0.23182086620430201, 0.00056545552199213298, 0.069522397061161395, 2.96885317382849, -0.051806865055980901, -9.7375846906152006, -3.7168685914889101, 6.2375373511235503, -2.6577205028209501, -20.3171172054412, -0.021304232202155899, 0.23708001500731801, 6.1434851687025596, -6.0140190081509104, -1.2111808932828501, -1.0189029621818799, 4.9024564940572102, 0.071576063751164501, 10.0372849796479, 8.8217235588703602, 3.2002119174291299, 1.88033862253058, -9.2381558436834005e-06, 0.209953576303675, 0.59897227695759403, 0.015408836716403701, 0.72667814261222297, 1.04253074219921, -0.36639952244782897, 2.1938545786385899, 10.5511658202853, -0.0060583673747924196, -0.040276481247202303, 0.19563265784432399, 0.695642528811383, 0.092195243295609006, -0.11700648378234201, -1.12128461392435, -0.24506719194217999, -5.08663676195245, -5.4127332500372898, -1.5233052074208899, -0.39207349407666497, -6.8044267141740398e-05, 1.4457806883519999, 3.6350558224209202, -0.050692260884422198, 6.5385777171092396, -6.1735157165659498, -4.2016623917464404, 0.71692866600594696, -26.888355558432, 0.028941180562419198, 0.41559738160577497, -1.41973334424801, 2.2623160579408399, 0.052440836591797699, 0.30315007284467799, -2.1595166526410599, -1.58941085218909, 13.577357339870201, 12.5510397413387, -2.28593652323275, 1.6131542987429599, 2.4964374967303e-05, 0.93824074473311303, -2.4541545673520901, 0.034536963170488502, 13.190305707504599, 4.9824580626416397, -8.2907707221262701, 7.2636404959165102, 24.581904470708601, -0.0158179845091273, -0.31398696530982101, -0.31358040502335599, 2.3904278510213701, 0.29019959630452602, -0.27262779401736098, -2.5076564852846102, -1.07562902654376, -12.0644593562773, -12.129759160663401, -8.6137752723124397, -0.85889008520979604}; +// SM+spl +double Slater_inv3_2[441] = {-0.056658742514349103, -9.5006825962797503, -18.307026635935799, -0.36744251865365501, 31.610841135834299, 39.084671241308698, -19.703711132730799, 18.666497646833299, 121.964198363159, -17.598444551917201, -2.9520245875548698, 24.935160344122199, 13.992695020707, 4.6612706754314903, -3.6234738869455199, -28.604054847833801, 9.5739197944338503, -62.128443913882499, -67.232459151277695, -11.803301377693099, -3.8508731471217099, 0.069411805979426894, 10.8007994955779, 22.458394727678201, -0.89282708659453403, -39.476164388726097, -47.5420201141931, 24.536662733275399, -23.351558477080602, -146.60044409871099, 21.549928185153298, 3.32891560872004, -30.5549979706051, -17.384760133954, -5.4401084934617003, 4.3730845094487396, 35.2040348414587, -11.414817838980399, 74.926509290741393, 80.145978783950099, 14.6842509146363, 5.7893824160342398, 0.041199702875412497, -6.4779318938824302, -13.2989719358296, 0.51508213587065199, 23.9434304832055, 27.923633944040301, -14.994539048994801, 13.545190256632999, 84.658750799602501, -12.440996315879, -1.6347815496642299, 17.4053340515119, 10.4563880132908, 3.2716511123291698, -2.32038524814726, -20.901080430435499, 6.5092932119827198, -43.310144838525801, -46.266317618221201, -9.0209731319320596, -3.3217327746699499, -0.071364036152653701, 11.529909516191401, 22.9175425489932, 0.44722818276140403, -39.897585842875301, -48.876557451246697, 24.801523764393401, -23.690956189203401, -151.28132599138999, 21.549304148995901, 3.4094704881876998, -30.687597458642099, -17.659848105023201, -5.7069215817131997, 4.0886157921745996, 35.564950307785701, -12.1803912964186, 77.135406641174299, 83.318689013925706, 14.819424258558801, 4.7782939163062803, -0.040051226770134098, -6.7134150132482402, -13.312257348225099, -0.26126985985289403, 22.204441530888801, 27.729627986407898, -13.7012421876807, 13.0503428483308, 85.297842345116607, -12.439369240025201, -1.60848061970372, 17.698309764178902, 10.1798985121263, 3.3110252774145601, -2.5466287558690199, -20.410023365852201, 6.7633439222022202, -43.4149505982517, -46.886928763683102, -7.88950712988734, -2.6927901019362199, -0.058248999176268398, 9.0508747193022892, 18.587941141225699, -0.73447131422595202, -35.308936282117699, -39.940782969048001, 21.9119312895712, -20.076960036338601, -123.935102576568, 17.592669318251101, 3.0259816420954402, -24.782453059479, -15.379073099754899, -4.67601503080067, 3.33242427220405, 30.0344780145867, -9.0772191462285008, 63.391820359557002, 67.760837774760006, 13.3701295015636, 4.8413052345891403, -0.00048534604109837199, -1.8238859168577699, 0.56645976558050504, -0.011652978445607001, 3.3511865791586, 2.0262681174419299, -2.14462816857628, 1.8811114733258301, 1.72516289469276, -0.0410444803602956, -0.17992011162600399, 4.6474809764852196, 0.32638302042170703, 1.28068103014527, 0.42381953652975901, -1.62158383882094, 1.84081037263479, -1.2636267813034701, -0.97726719185308597, -0.84319863660797401, 0.57245121780013697, 0.00072965273109526496, -0.74868100456805098, 0.61375144696985096, -0.013670796650539699, -10.880212250529199, -2.2389072194253701, 6.8446360871752603, -3.8338819099152301, -0.83708262317409499, 0.055638693619984997, 0.16395892268443801, -6.4020540512225601, -0.87619791103918299, 0.67273193621704896, -0.96217527481654197, 3.5322304037025498, 0.74780382069687101, 0.457651060635482, 2.4127372990709501, 5.8207812126355103, 0.41153697505715597, 0.00047300381075295099, -0.24273841428794099, 0.62931133864105804, -0.0075433586410305498, -3.8733549821913198, -2.7042122832831499, 2.4066006453807001, -1.90501007795962, -11.4961539239149, -0.025181201641384401, 0.20951155742128399, 4.41315756942062, -2.02827911285326, 0.53245648205106699, -0.57146100385840204, 1.6986603412216601, 0.20698230514139301, 5.5487259477006203, 4.3923373342920504, 2.6422104099671002, 0.12108516249854701, 0.00082691786224778699, 0.113024111733347, 2.7966391201096901, -0.052696331353419397, -4.8718908471754601, -4.3479524721016301, 3.1326652654405498, -2.1520186098021998, -17.7293360378548, -0.043482158450766098, 0.29115918226676102, 7.9265874331542596, -4.4255647905147004, -1.3335239860704799, -1.2720331573702599, 2.2195046250833101, 0.037526349197067099, 8.8672908187991606, 8.6317273115312592, 1.83700699526623, 1.8931859854467199, 0.000439374179950941, 1.8174276372186899, -0.095470042913778502, 0.0240432915091328, 0.33095163979973902, 0.419313643627721, -0.26508090252151401, 0.40758512406775099, 6.2032604963961004, 0.0299978360553445, -0.0350221248964512, -4.5247535085126103, 2.4252753636201798, -1.0443273705703999, -0.77183418222125399, -0.15673357470618601, -1.86654030909075, -2.3976989367798298, -1.56808861204302, 0.340202658594777, -1.0312623606052, -0.00063346566713256398, -0.661487272350328, -0.31969668820761499, -0.0207136433303984, -9.5617277834137209, -0.76548087353469296, 6.1338905273463604, -3.6493438141085299, -1.93160595722129, -0.054328540468196101, 0.063300925950509901, 8.0421985164502203, -6.7317743058458301, 0.56920882928816896, 1.39543139815216, 5.8217064803946901, 0.664937044390989, 2.0166407848672301, 0.66314768899536403, 2.4978865189964501, 0.90776612934725198, -0.00080526074137288, 0.866074714994297, -3.1810443538305599, 0.016712052067642799, 8.8525588583729107, 4.9029982933499703, -5.6387712154483003, 4.6377500718450797, 24.5361964752293, 0.036812637615073897, -0.307516025692601, -7.7158500239832, 6.5793196290456004, -0.90848412347546603, 1.2781649114678699, -4.0662241638244598, -0.85073071123983601, -12.848505169556301, -11.568586481641701, -3.9619743954566902, -0.100174674295188, 0.00069201116604256595, -0.421899716446686, -0.59032673715943695, 0.00276476648616889, 5.2753594946225197, 3.1708842333983198, -3.5051204501630502, -1.5506563388697101, 13.474253171986501, 0.038327175723695497, -0.21097106418518499, -8.0266607832375794, 6.6217101288174902, 1.26803738570163, -1.6239859547120901, -5.0491300215678701, 0.316141906166655, -6.8977435746728997, -6.9768951380000299, 1.3337978430772699, 0.27199695684951902, -0.00038359474997356102, 0.72100151176486804, -2.5365266414467098, 0.014980427848668199, 6.4663011480631196, 3.0354904137032901, -4.11275562441097, 3.6805173953314201, 18.1353313216757, 0.0085443837305102504, -0.16921638348780199, -3.85900106683119, 3.0428583654892001, -0.42146305418508101, 0.73140085261157395, -3.0095115595924198, -0.74724977432843798, -7.5689235578938199, -9.1654977643928905, -2.6018219553374502, -0.138580489522561, 3.1034344981670402e-05, 0.57346844296584099, -3.2816001969233399, 0.0098861018626169896, 2.7223870822496599, 3.19376385336182, -1.6094836478010499, 3.2093742171519399, 7.7061355268378202, 0.00180174673425388, -0.239342015844032, -0.17647999921287399, 1.7270571869450699, 0.18584316968323999, -0.066662651903874603, -2.3139065344532099, -0.65593666316055899, -3.9145254849983999, -3.4618799405385898, -2.6291335069492199, -0.23750024714478199, 0.00031371845096864198, -0.27014711720045598, -0.259122675110673, 0.0083797376871939597, 10.324015180961201, 0.62494833390683702, -6.5624316442850503, 3.9711776808922599, 2.31246521547006, 0.030498354639596902, -0.030734962225840101, -4.3487398562952402, 5.7898821592163596, 0.12407032656822101, -0.67808345005445703, -4.5636059941770499, 0.27242993392548098, -0.151105792955298, -2.1330095124199899, -4.5785158627476203, -0.23182086620430201, 0.00056545552199213298, 0.069522397061161395, 2.96885317382849, -0.051806865055980901, -9.7375846906152006, -3.7168685914889101, 6.2375373511235503, -2.6577205028209501, -20.3171172054412, -0.021304232202155899, 0.23708001500731801, 6.1434851687025596, -6.0140190081509104, -1.2111808932828501, -1.0189029621818799, 4.9024564940572102, 0.071576063751164501, 10.0372849796479, 8.8217235588703602, 3.2002119174291299, 1.88033862253058, -9.2381558436834005e-06, 0.209953576303675, 0.59897227695759403, 0.015408836716403701, 0.72667814261222297, 1.04253074219921, -0.36639952244782897, 2.1938545786385899, 10.5511658202853, -0.0060583673747924196, -0.040276481247202303, 0.19563265784432399, 0.695642528811383, 0.092195243295609006, -0.11700648378234201, -1.12128461392435, -0.24506719194217999, -5.08663676195245, -5.4127332500372898, -1.5233052074208899, -0.39207349407666497, -6.8044267141740398e-05, 1.4457806883519999, 3.6350558224209202, -0.050692260884422198, 6.5385777171092396, -6.1735157165659498, -4.2016623917464404, 0.71692866600594696, -26.888355558432, 0.028941180562419198, 0.41559738160577497, -1.41973334424801, 2.2623160579408399, 0.052440836591797699, 0.30315007284467799, -2.1595166526410599, -1.58941085218909, 13.577357339870201, 12.5510397413387, -2.28593652323275, 1.6131542987429599, 2.4964374967303e-05, 0.93824074473311303, -2.4541545673520901, 0.034536963170488502, 13.190305707504599, 4.9824580626416397, -8.2907707221262701, 7.2636404959165102, 24.581904470708601, -0.0158179845091273, -0.31398696530982101, -0.31358040502335599, 2.3904278510213701, 0.29019959630452602, -0.27262779401736098, -2.5076564852846102, -1.07562902654376, -12.0644593562773, -12.129759160663401, -8.6137752723124397, -0.85889008520979604}; + +const uint64_t N_updates5 = 5; +const uint64_t Updates_index5[5] = {17, 18, 19, 20, 21}; +const double Updates5[105] = {-0.026680206879973502, 0.27298007905483301, -0.099715244024992294, -0.1053539039567112, -0.1449181307107206, 0.086803577840328203, -0.13467331603169441, 0.083233945071697304, -0.050348894670605604, 0.113249283283949, -0.18058512732386639, -0.013084722682833599, -0.2101329043507576, 0.29668186604976698, 0.011996015906333896, -0.25581711530685397, -0.18468007631599939, -0.19795016199350388, 0.13754389435052872, 0.066371031105519007, 0.1506568714976311, 0.1407152302563191, -0.035490237176418013, -0.15555772557854669, -0.13084962218999829, -0.065377140417695004, -0.28165902942419097, -0.0038048550486564081, -0.17355462908744812, 0.1904655769467351, 0.1015159860253334, -0.082969114184379605, 0.1009396240115165, 0.25867408514022822, -0.090622015297412997, -0.0261126160621643, -0.0070611685514450073, 0.34575527906417902, 0.1856994293630127, 0.1505507901310916, -0.24748291820287749, -0.1930690407752986, -0.10824421048164369, -0.2003080397844319, -0.050228431820869016, 0.2341227037832137, -0.1714876033365724, 0.32784904539585158, 0.040038149803876807, 0.12709141941741103, -0.088602993637323102, -0.1617441214621064, -0.237361330538988, -0.029239896684885004, 0.039443209767341697, -0.15546871721744498, -0.0127334967255592, -0.093294814229011994, -0.16617536172270789, 0.081297293305397006, -0.11561803519725759, -0.088157065212726496, 0.043941155076026403, -0.043334499001503005, -0.072291933000086989, 0.25947313755750623, -0.00654759816825385, -0.23022028384730242, -0.0992842186242342, -0.059074921417050084, 0.009816635400056898, -0.018885548226535299, 0.28729220479726802, 0.30690228054299934, 0.058271216228604303, 0.050839929841458791, -0.091462507843971003, 0.21059621125459649, -0.19497598148882408, 0.012118805199861502, -0.040971436537802185, -0.0676504261791709, -0.16150601254776081, 0.076545581221580811, -0.44388696737587502, 0.026131823658942982, -0.11532356310635784, 0.038358195684850299, 0.16635001881513747, 0.035624274984002099, 0.039094586856663179, 0.12423532153479717, 0.13070272840559499, 0.027002811431885002, -0.22131750034168385, 0.1172939799726007, -0.034513717517256695, 0.19796614628285178, 0.087915631011128009, 0.1338309701532128, -0.086308442056179102, -0.014136113226413699, 0.06877816375345, 0.11613245680928279, -0.16100704949349121}; +const double Slater5[441] = {-2.8945870399475102, 3.5455725193023699, 2.0470812320709202, -3.5464441776275599, -2.0474903583526598, -2.89596366882324, -0.61329728364944502, 0.70991641283035301, 0.45664468407630898, 0.59523195028305098, 0.26079276204109197, -0.027727147564291999, -0.35093706846237199, -0.095610238611698206, -0.130077064037323, 0.10946778208017301, 0.021800471469759899, 0.048480678349733401, -0.092234551906585693, -0.0160505045205355, -0.42026260495185902, -0.78021097183227495, -0.95558542013168302, -0.55174458026885997, -0.95579683780670199, -0.55179446935653698, 0.78044348955154397, -0.115299895405769, -0.11754634231329, -0.0318448171019554, -0.00082233443390577999, 0.064001239836216001, 0.12740932404995001, -0.049412809312343597, -0.074464745819568606, 0.19851659238338501, -0.088878795504569993, 0.135610401630402, -0.13736967742443101, -0.101879440248013, 0.102390937507153, -0.12476679682731601, -0.00527230883017182, 0.00029381641070358499, 0.0072919740341603799, -0.00026352208806201799, 0.0068838247098028703, 0.0047294595278799499, 0.11728889495134399, -0.062190085649490398, -0.15969239175319699, -0.10645916312933, 0.112943567335606, -0.0015487050404772199, -0.045737843960523598, 0.13196058571338701, 0.038660705089569099, -0.050266433507204097, -0.13745591044426, -0.037740666419267703, 0.11781705915927899, 0.19417031109332999, -0.0079971449449658394, -0.30874741077423101, -0.37815779447555498, 0.218254208564758, 0.378139227628708, -0.21839827299118, -0.30879178643226601, 0.025539221242070202, 0.112043909728527, 0.037676706910133403, 0.025347150862216901, -0.19991625845432301, 0.14163509011268599, 0.13326919078826899, 0.213842943310738, 0.131471157073975, 0.14626120030879999, -0.0118067460134625, 0.093547157943248693, 0.22439678013324699, 0.0082425400614738499, 0.0250354297459126, -1.52881526947021, -1.9163775505148799e-05, -2.1623263359069802, -1.5540548702119799e-05, 2.16284847259521, -1.52953028678894, -0.26402890682220498, 0.024944067001342801, -0.37140902876853898, -0.044071510434150703, -0.29843890666961698, -0.043834518641233403, -0.177285701036453, -0.058585006743669503, -0.0183692276477814, -0.026075478643178902, -0.15623773634433699, -0.011319605633616401, 0.054057534784078598, -0.23151709139347099, -0.0016308756312355399, -0.067333526909351293, 0.00043256155913695698, 0.095035225152969402, -0.00043632232700474598, 0.094624765217304202, 0.066768139600753798, 0.14448715746402699, -0.12090456485748299, -0.203432962298393, -0.21472349762916601, 0.154288679361343, 0.017385326325893399, -0.071518480777740506, 0.27918133139610302, 0.080454014241695404, -0.0361245274543762, 0.0566458702087402, -0.030157707631588, 0.25150132179260298, -0.082445412874221802, -0.017600754275918, -2.2779068946838401, -2.3393469746224599e-05, -3.2218937873840301, -1.7939200915861899e-05, 3.22278833389282, -2.2791447639465301, -0.47945570945739702, 0.045197278261184699, -0.64478874206543002, -0.080234304070472703, -0.47389149665832497, 0.024908870458602898, -0.23455648124218001, -0.10695217549800901, -0.033054649829864502, -0.195749551057816, -0.040076982229948002, 0.094596333801746396, 0.098401188850402804, -0.059563819319009802, -0.0045592403039336196, -0.0025739683769643298, -0.0020174346864223502, -0.0024467820767313199, -0.00204527890309691, 0.00013988610589876801, 0.00073755031917244196, 0.17339251935482, 0.099962860345840496, 0.14622049033641801, -0.088966980576515198, 0.040044382214546197, -0.14437201619148299, -1.5416861060657501e-05, -0.081159926950931494, -0.11909016221761699, 0.170753449201584, 0.031124599277973199, -0.052109345793724102, 0.121445283293724, 0.0289684906601906, 0.120766848325729, -0.0043673445470631097, -0.00014539182302542001, 0.0061219600029289696, 0.000189467871678062, 0.0060523007996380303, 0.00425094133242965, 0.0905451029539108, 0.058540407568216303, -0.15191346406936601, 0.11511342227459, 0.15016922354698201, 0.10024280846118901, -0.11066282540559801, -0.15089659392833699, -0.021995550021529201, 0.10021472722291901, 0.019932290539145501, 0.070281185209751101, -0.120184391736984, -0.030551897361874601, 0.10763206332922, -0.0097634727135300602, 0.0119331693276763, -0.0068263513967394803, 0.011701960116624799, -0.0068089049309492103, 0.0095072658732533507, 0.133816182613373, -0.15090283751487699, 0.070243604481220204, 0.077758952975273105, -0.071993313729763003, -0.0526336021721363, -0.033549431711435297, -0.029018172994255999, 0.10475520789623299, 0.047332767397165298, 0.17077720165252699, 0.057527918368577999, -0.043988067656755399, 0.11077278107404701, -0.11803108453750601, -0.71565270423889205, 2.80283820757177e-05, 1.0121610164642301, -2.41986454057042e-05, 1.0123220682144201, 0.71586799621581998, -0.045286595821380601, -0.0269623268395662, 0.0683262273669243, -0.047560662031173699, -0.062597043812274905, -0.0278066452592611, 0.045772761106491103, 0.063010454177856404, 0.0197743345052004, -0.025724532082676901, -0.20542661845684099, -0.0248414911329746, 0.058127623051405002, 0.30385830998420699, -0.0018243347294628601, -0.00073456991231069001, 0.000104061764432117, -0.0010063005611300501, 0.00014142321015242501, 0.00095045292982831597, -0.00064003589795902404, 0.056538689881563201, -0.038196403533220298, 0.095246985554695102, 0.077704243361949907, 0.089713566005229894, 0.071932643651962294, 0.058404259383678402, 0.097089007496833801, -1.8242251826450202e-05, -0.070699930191039997, 0.0231548044830561, 0.036239527165889698, -0.064700096845626803, 0.035663921386003501, 0.140344902873039, -0.0285779368132353, 2.2119384368579599e-07, -0.0404084548354149, 4.62594880445977e-06, 0.040473498404025997, -0.028664523735642398, 0.0818745791912079, -0.0072916029021143896, 0.171691119670868, 0.0142411412671208, 0.227563425898552, 0.20764905214309701, 0.23875248432159399, 0.019401129335165, 0.0041248365305364097, -0.273390233516693, 0.031942136585712398, 0.24207504093647, -0.016599044203758202, 0.0499182641506195, 0.011294623836875, -0.083720728754997295, -0.102523192763329, -0.059237916022539097, -0.10253403335809699, -0.0591498985886574, 0.083691440522670704, 0.093738317489623996, 0.118414394557476, 0.119053602218628, -0.19025875627994501, -0.017257452011108398, 0.111288614571095, -0.14737996459007299, -0.106449924409389, 0.119639433920383, -0.0358475148677826, 0.16083629429340399, -0.135845571756363, -0.045223556458950001, 0.129632458090782, 0.0101170120760798, -0.0016409500967711199, 0.0020083498675376199, 0.0011536112288013101, -0.0019761291332542901, -0.0011378186754882301, -0.0015965295024216199, 0.062009602785110501, -0.085591755807399694, -0.073869466781616197, -0.129948750138283, -0.025633471086621298, 0.092304252088069902, 0.11476875841617599, 0.0570255033671856, -0.098354063928127303, 0.048130486160516697, -0.075562968850135803, -0.087558984756469699, -0.061446368694305399, 0.073952160775661496, -0.030968701466917999, -0.086937576532363905, -5.2227896958356703e-05, -0.12295132130384399, -5.67086790397298e-05, 0.122932203114033, -0.086922481656074496, 0.092386581003665896, 0.0563923679292202, 0.16267444193363201, -0.103307262063026, 0.177027583122253, 0.119934171438217, 0.15235325694084201, -0.13730293512344399, -0.036718469113111503, -0.13380806148052199, -0.14056211709976199, 0.11525499820709199, 0.122316166758537, -0.211628392338753, -0.030221903696656199, -0.71328485012054399, -0.87364697456359897, -0.50431287288665805, -0.87368428707122803, -0.50450080633163497, 0.71341556310653698, -0.0728774294257164, -0.0137394573539495, -0.131415024399757, 0.120499663054943, -0.15048809349536901, 0.067258194088935894, -0.016238121315836899, 0.25341770052909901, 0.061544414609670597, -0.124150305986404, -0.023104058578610399, 0.161576017737389, -0.18417926132678999, -0.016373874619603199, -0.061180751770734801, -0.00358590018004179, -3.1569013572152501e-06, 0.00505110481753945, -1.33700987134944e-05, 0.0050756097771227403, 0.0036168387159705201, 0.076649472117423997, -0.0148532707244158, -0.15424914658069599, -0.031277053058147403, 0.20174449682235701, 0.17827098071575201, -0.21435502171516399, 0.043405968695879003, 0.0060502337291836704, 0.23922684788703899, 0.022777535021305102, 0.22072769701480899, 0.035028267651796299, -0.037091828882694203, -0.054775215685367598, -0.0137155568227172, -0.00072690693195909305, 0.019026592373848, 0.00073597067967057196, 0.018235495314001999, 0.012611641548574, 0.14907942712307001, 0.10721461474895499, -0.205590710043907, 0.18899101018905601, 0.14405034482479101, 0.0080890702083706908, -0.049517802894115399, -0.23817741870880099, -0.062822751700878102, -0.056222390383482, 0.079762905836105305, -0.057780988514423398, -0.208331778645515, -0.11229432374239, 0.0132825700566173, -0.13207408785819999, -0.00012266315752640399, -0.18668732047080999, -0.000116608949610963, 0.18647037446498901, -0.13181127607822399, 0.17992316186428101, 0.0310163982212543, 0.194987177848816, -0.051282022148370701, 0.079243704676628099, -0.16229276359081299, -0.029616238549351699, -0.065854735672473894, -0.025143278762698201, 0.277732163667679, -0.117880158126354, -0.184251189231873, 0.0632317289710045, -0.16761179268360099, 0.0096404440701007808, -0.0068073021247982996, -0.0083365431055426598, 0.0048150913789868398, 0.0083073899149894697, -0.0047997133806347804, -0.0067770029418170504, 0.077614806592464405, 0.12953585386276201, -0.063416801393032102, 0.138088583946228, -0.10224375873804099, 0.130568191409111, 0.164952263236046, 0.026345754042267799, 0.13718618452549, 0.084768116474151597, 0.096043966710567502, -0.054612904787063599, 0.138456135988235, -0.071488708257675199, -0.0153317032381892}; +// WB2+spl: 2,2,1 +double Slater_inv5_1[441] = {-0.054189244668834902, -105.426713929607, -88.458496476283003, 1.5333775291907901, -306.17152423250297, 211.834723659242, 189.348181800731, -164.85602878397, 1001.02895803198, -19.086531171244101, -14.1862411100869, 93.929906236367501, -177.880045125896, -6.7382862272631598, -14.511503830974201, 198.86948709278099, 116.24375034946701, -509.187787693936, -474.82187536023201, 185.49468275501101, -68.704359475869197, 0.066396729468773799, 128.61396390514599, 107.279152808508, -3.2214077352586501, 377.39638500462598, -258.32727230254102, -233.50899542599601, 202.73053181330999, -1222.6711957145401, 23.374193247961198, 17.0231928902612, -115.31992914359, 218.34781344598201, 8.5868800406738099, 17.706454078785399, -244.13052330624399, -142.42769283244499, 622.15335091370196, 579.15535219316803, -228.72024346964599, 85.262861528059901, 0.042977214694503003, -75.818887039648899, -63.4429496117761, 1.89037149893251, -221.440571714557, 152.54192851849001, 136.92110635753301, -119.073716594494, 720.98982202338402, -13.516656591400601, -9.7291496308540406, 67.372278162472895, -128.19425354399101, -4.9638472213270699, -10.200417492010599, 143.31769471617801, 83.615852083439094, -366.86654819753397, -341.426964056759, 133.98241248588599, -50.230799667840699, -0.074440153582489205, 131.003888225851, 110.340015781723, -1.92534262087524, 381.482058581253, -264.51148724341499, -236.035513173862, 204.43864191351099, -1249.3967405711001, 23.404380739562701, 17.427737318703301, -116.737852869633, 221.189913802663, 8.4677080090305399, 17.684126766935599, -247.44394443997601, -145.031902348194, 635.53348480709997, 592.58164589603302, -230.87850923206801, 85.694308069456397, -0.038299262589364599, -74.702005824131604, -63.171412849899497, 1.0859859506457199, -217.148397050222, 150.25957665606299, 134.431598757773, -117.013550651343, 708.34335491195498, -13.4940069422526, -9.5788103819957797, 66.593490547156307, -125.80391712960601, -4.7671091217963504, -10.2632044954116, 140.809682960885, 82.366527572926103, -360.28206877713399, -335.74815599116999, 131.925760239261, -48.660685665615503, -0.060749768867194, 106.92546569584999, 88.790343162838894, -2.6692288353747702, 312.16097467403699, -214.903931604847, -193.215823966269, 167.781122174079, -1018.10641886182, 19.107519450141002, 14.388719322765001, -95.267373183568594, 180.40857560667001, 6.9728512293157801, 14.4102075774752, -201.83015329787199, -117.917199027973, 518.09179195913805, 482.46342773412402, -189.25708821193001, 70.869624357767506, -0.000187411047696029, -11.9846117540694, -9.5726690972884096, 0.23970985157893901, -31.525734707294099, 26.424001662617101, 19.629541977294, -12.8111861333484, 126.186955595279, -0.21994779537689901, -1.75278408990554, 12.699562562401301, -19.050321348645301, 0.28466729039388, -1.07057307471916, 20.675591706275501, 13.1048598424623, -64.121267975873096, -59.394985304548896, 16.918592992744401, -7.70362909966763, 0.00036065684724530402, 12.9068309168011, 12.002712393435401, -0.33194601220397202, 40.326484701927001, -31.878253347415502, -25.170560077575001, 17.9905011861023, -156.05779622500401, 0.28522581276215098, 2.06069522309385, -17.151275363286, 25.397351917205899, 2.08581286823873, 0.91118057859336898, -26.515090998756101, -14.4035822159035, 78.890023885294596, 75.240667711773398, -20.769502289340899, 10.973365712218101, 0.00054214253230406803, -2.29504518628212, -2.1312244512866698, 0.047562978801466302, -10.6318457557031, 3.0591772010668401, 6.6375862982055702, -4.4363733110097296, 16.291945106274301, -0.062929125223047597, -0.16835581689436099, 6.0820271877694996, -5.8351950377758204, 0.35401259185447298, -0.90070453596893996, 6.0382685793059503, 2.4785619931575602, -8.4908203096171402, -8.6197966065449307, 5.8804527059182696, -1.67757738078734, 0.00096800508899916803, -2.4934502646428101, -4.5195305250493698, 0.052900907147883501, -6.5403147654399101, 8.5375829900159896, 4.1350660479474399, -1.63386715634978, 39.5635438458416, -0.11054656518749099, -0.56905231469759199, 10.2311793759502, -8.8014973731182806, -1.42214511908425, -1.9356586876592501, 7.4277556761303396, 2.8985267278915199, -19.981167223464801, -18.310196540769098, 1.3631485584979499, -1.4104996470922699, 0.000167515045034934, 10.6237721447983, 9.6125946891096099, -0.20829092726741699, 28.481388931713699, -22.584157610136199, -17.8392407006579, 11.6781776869203, -110.705963174229, 0.192721307745398, 1.4471736958685699, -11.629464509211299, 19.0388155304672, -0.23390314175395899, 0.62505732559282601, -19.284349111137399, -11.6199046959709, 56.562315732201498, 53.440734762614099, -13.464260193464, 6.5494922727750904, -0.00064712664753083498, 0.51012013976619996, -0.40601608060218902, -0.010304898323864499, -1.9162384482042301, 0.67040773560745603, 1.4195140953666501, 1.89175006728124, 8.4997123797302105, -0.053837688493721801, -0.0081694468687663092, 7.5841687069424202, -3.9864241641726901, 0.82441242748559596, 1.28841942280286, 2.4602644684099202, -0.65833650503714802, -2.93422340475106, -4.7994849299481297, -3.1153746742144999, 0.76509679552570997, -0.00094253467883977896, 4.5884404541075803, 2.5577714145483599, -0.100362327319965, 18.711173319888399, -7.5191542625802104, -11.814804467633101, 7.51205003788884, -36.605280961279099, 0.11460812693040601, 0.498461399643222, -10.903564320961401, 13.2948947844546, -0.64349351510306596, 1.9974412451213299, -11.727821769419799, -4.9603602940684901, 17.916362650168399, 17.291804112001799, -7.9761250950845, 3.6407278735208699, -0.000183321670183587, 6.4691421816769399, 6.0512576241625498, -0.15162968127745899, 23.395366108183801, -14.5381852262701, -14.606223833564799, 10.199271998597199, -73.975176230999594, 0.109352036334604, 0.939662287060122, -5.0493506777824901, 12.432450504307001, 0.66340082972807302, 0.89171490853171798, -14.301193838340501, -7.1767924210601599, 37.417730343433, 34.621199008384998, -12.2257905481279, 5.0337643040644098, 0.00077853683475417402, -4.0437466042030499, -3.2232682351578399, 0.038202731665628202, -12.153196028398099, 6.5027616010011799, 7.2973627140258399, -12.054113026894999, 23.6623418919025, 0.0029087480524890102, -0.465988240269751, -5.8215678299339997, -0.92982871489462304, 0.72875377435640498, -1.76856112702097, 3.9100682853776498, 4.3638012685037904, -12.532035664209801, -10.8596693966264, 12.5729914998231, -1.17795314966104, -0.00047116201805309901, 2.7712702890005598, 1.4259517039641101, -0.060855532638316702, 9.8783846948200704, -5.3156162802238898, -6.24217543532784, 4.0955113938692902, -22.6133771249789, 0.0576846298115802, 0.37261538596098298, -5.69311024324454, 6.6165547759347501, -0.31572322723037299, 1.2076815066994999, -7.13883450856141, -3.0036796657518701, 12.888731168100399, 10.144844547714699, -3.4202567509716602, 2.2424073656324301, 0.00046719815518450402, -6.1786048720593501, -4.9366254575058903, 0.121293000821164, -13.5354546658637, 11.122151465656, 8.2996176249675795, -7.8492497139147304, 53.792699096533298, -0.056207389907105297, -0.72284563910330601, -0.034988476570927102, -5.8914910450597402, -0.57259031868870103, -1.3110690999933601, 8.9888650972260002, 6.8430482968640902, -26.406527264610599, -25.8419474444987, 8.95444342115516, -4.1168180484580699, 0.00068908057573134802, -2.0076563509740999, -3.65231424825159, 0.042894239647239998, -9.7520285174303201, 7.9819862061298199, 6.2214414143151, -1.1841920217922099, 31.911005041941699, -0.080053013664620296, -0.54185675163812796, 8.0781654837979193, -9.3493294125201594, -1.24083642122091, -1.6208022544009499, 8.8607449463367196, 2.3445831189331501, -16.218420387174199, -15.8119148955707, 1.7389982134136399, -1.0509978817476, -3.48584361237575e-05, 0.61330220442703598, 2.33052219623813, -0.0057796507046079101, 5.3801162861110896, -1.7460100802854299, -3.4260231079769401, 1.85323155008146, -1.34565392401789, 0.0020702237459098, 0.147768044797361, -0.43649104760725999, 0.997972495465969, 0.056933085588242997, 0.0077486424610570597, -0.89070134502194598, -0.68148789029708001, 0.89518325797891696, 0.16523545732706499, -2.8298454160600501, 0.26096748561569599, -3.9951230141139501e-05, 2.6625953366596802, 0.159171360187916, -0.0080654609832386693, 14.485659114429501, 0.26188806209423798, -8.9564367313419204, 9.5170929366304993, 3.6594343436186199, 0.017879567938259198, 0.0042052494877241001, -1.4377710841437801, 5.8763150360799203, 0.47441391996743998, -0.014783250610591801, -7.06163381200634, -2.9885184999935599, -1.42889911045556, -2.4433038426403901, -9.8958894810457991, 0.55194555716779503, -5.7250805560848302e-05, 0.98372766353792995, 3.2392588139392098, -0.0119630481344816, 0.14153713576169, -2.73924503033615, 0.060309030316031902, 2.34167965625057, -3.8604817562043001, 0.012593073725828199, 0.22349082635471901, -0.35749918018293803, 2.0835157939561699, 0.13368765195851301, 0.0515445449292352, -2.95655438325227, -1.09680637412728, 2.2418386652533302, 1.2169977713442901, -1.20005576483735, 0.48385142427875799}; +// WB3+splL 3,1,1 +double Slater_inv5_2[441] = {-0.054189244668834902, -105.426713929607, -88.458496476283003, 1.5333775291907901, -306.17152423250297, 211.834723659242, 189.348181800731, -164.85602878397, 1001.02895803198, -19.086531171244101, -14.1862411100869, 93.929906236367501, -177.880045125896, -6.7382862272631598, -14.511503830974201, 198.86948709278099, 116.24375034946701, -509.187787693936, -474.82187536023201, 185.49468275501101, -68.704359475869197, 0.066396729468773799, 128.61396390514599, 107.279152808508, -3.2214077352586501, 377.39638500462598, -258.32727230254102, -233.50899542599601, 202.73053181330999, -1222.6711957145401, 23.374193247961198, 17.0231928902612, -115.31992914359, 218.34781344598201, 8.5868800406738099, 17.706454078785399, -244.13052330624399, -142.42769283244499, 622.15335091370196, 579.15535219316803, -228.72024346964599, 85.262861528059901, 0.042977214694503003, -75.818887039648899, -63.4429496117761, 1.89037149893251, -221.440571714557, 152.54192851849001, 136.92110635753301, -119.073716594494, 720.98982202338402, -13.516656591400601, -9.7291496308540406, 67.372278162472895, -128.19425354399101, -4.9638472213270699, -10.200417492010599, 143.31769471617801, 83.615852083439094, -366.86654819753397, -341.426964056759, 133.98241248588599, -50.230799667840699, -0.074440153582489205, 131.003888225851, 110.340015781723, -1.92534262087524, 381.482058581253, -264.51148724341499, -236.035513173862, 204.43864191351099, -1249.3967405711001, 23.404380739562701, 17.427737318703301, -116.737852869633, 221.189913802663, 8.4677080090305399, 17.684126766935599, -247.44394443997601, -145.031902348194, 635.53348480709997, 592.58164589603302, -230.87850923206801, 85.694308069456397, -0.038299262589364599, -74.702005824131604, -63.171412849899497, 1.0859859506457199, -217.148397050222, 150.25957665606299, 134.431598757773, -117.013550651343, 708.34335491195498, -13.4940069422526, -9.5788103819957797, 66.593490547156307, -125.80391712960601, -4.7671091217963504, -10.2632044954116, 140.809682960885, 82.366527572926103, -360.28206877713399, -335.74815599116999, 131.925760239261, -48.660685665615503, -0.060749768867194, 106.92546569584999, 88.790343162838894, -2.6692288353747702, 312.16097467403699, -214.903931604847, -193.215823966269, 167.781122174079, -1018.10641886182, 19.107519450141002, 14.388719322765001, -95.267373183568594, 180.40857560667001, 6.9728512293157801, 14.4102075774752, -201.83015329787199, -117.917199027973, 518.09179195913805, 482.46342773412402, -189.25708821193001, 70.869624357767506, -0.000187411047696029, -11.9846117540694, -9.5726690972884096, 0.23970985157893901, -31.525734707294099, 26.424001662617101, 19.629541977294, -12.8111861333484, 126.186955595279, -0.21994779537689901, -1.75278408990554, 12.699562562401301, -19.050321348645301, 0.28466729039388, -1.07057307471916, 20.675591706275501, 13.1048598424623, -64.121267975873096, -59.394985304548896, 16.918592992744401, -7.70362909966763, 0.00036065684724530402, 12.9068309168011, 12.002712393435401, -0.33194601220397202, 40.326484701927001, -31.878253347415502, -25.170560077575001, 17.9905011861023, -156.05779622500401, 0.28522581276215098, 2.06069522309385, -17.151275363286, 25.397351917205899, 2.08581286823873, 0.91118057859336898, -26.515090998756101, -14.4035822159035, 78.890023885294596, 75.240667711773398, -20.769502289340899, 10.973365712218101, 0.00054214253230406803, -2.29504518628212, -2.1312244512866698, 0.047562978801466302, -10.6318457557031, 3.0591772010668401, 6.6375862982055702, -4.4363733110097296, 16.291945106274301, -0.062929125223047597, -0.16835581689436099, 6.0820271877694996, -5.8351950377758204, 0.35401259185447298, -0.90070453596893996, 6.0382685793059503, 2.4785619931575602, -8.4908203096171402, -8.6197966065449307, 5.8804527059182696, -1.67757738078734, 0.00096800508899916803, -2.4934502646428101, -4.5195305250493698, 0.052900907147883501, -6.5403147654399101, 8.5375829900159896, 4.1350660479474399, -1.63386715634978, 39.5635438458416, -0.11054656518749099, -0.56905231469759199, 10.2311793759502, -8.8014973731182806, -1.42214511908425, -1.9356586876592501, 7.4277556761303396, 2.8985267278915199, -19.981167223464801, -18.310196540769098, 1.3631485584979499, -1.4104996470922699, 0.000167515045034934, 10.6237721447983, 9.6125946891096099, -0.20829092726741699, 28.481388931713699, -22.584157610136199, -17.8392407006579, 11.6781776869203, -110.705963174229, 0.192721307745398, 1.4471736958685699, -11.629464509211299, 19.0388155304672, -0.23390314175395899, 0.62505732559282601, -19.284349111137399, -11.6199046959709, 56.562315732201498, 53.440734762614099, -13.464260193464, 6.5494922727750904, -0.00064712664753083498, 0.51012013976619996, -0.40601608060218902, -0.010304898323864499, -1.9162384482042301, 0.67040773560745603, 1.4195140953666501, 1.89175006728124, 8.4997123797302105, -0.053837688493721801, -0.0081694468687663092, 7.5841687069424202, -3.9864241641726901, 0.82441242748559596, 1.28841942280286, 2.4602644684099202, -0.65833650503714802, -2.93422340475106, -4.7994849299481297, -3.1153746742144999, 0.76509679552570997, -0.00094253467883977896, 4.5884404541075803, 2.5577714145483599, -0.100362327319965, 18.711173319888399, -7.5191542625802104, -11.814804467633101, 7.51205003788884, -36.605280961279099, 0.11460812693040601, 0.498461399643222, -10.903564320961401, 13.2948947844546, -0.64349351510306596, 1.9974412451213299, -11.727821769419799, -4.9603602940684901, 17.916362650168399, 17.291804112001799, -7.9761250950845, 3.6407278735208699, -0.000183321670183587, 6.4691421816769399, 6.0512576241625498, -0.15162968127745899, 23.395366108183801, -14.5381852262701, -14.606223833564799, 10.199271998597199, -73.975176230999594, 0.109352036334604, 0.939662287060122, -5.0493506777824901, 12.432450504307001, 0.66340082972807302, 0.89171490853171798, -14.301193838340501, -7.1767924210601599, 37.417730343433, 34.621199008384998, -12.2257905481279, 5.0337643040644098, 0.00077853683475417402, -4.0437466042030499, -3.2232682351578399, 0.038202731665628202, -12.153196028398099, 6.5027616010011799, 7.2973627140258399, -12.054113026894999, 23.6623418919025, 0.0029087480524890102, -0.465988240269751, -5.8215678299339997, -0.92982871489462304, 0.72875377435640498, -1.76856112702097, 3.9100682853776498, 4.3638012685037904, -12.532035664209801, -10.8596693966264, 12.5729914998231, -1.17795314966104, -0.00047116201805309901, 2.7712702890005598, 1.4259517039641101, -0.060855532638316702, 9.8783846948200704, -5.3156162802238898, -6.24217543532784, 4.0955113938692902, -22.6133771249789, 0.0576846298115802, 0.37261538596098298, -5.69311024324454, 6.6165547759347501, -0.31572322723037299, 1.2076815066994999, -7.13883450856141, -3.0036796657518701, 12.888731168100399, 10.144844547714699, -3.4202567509716602, 2.2424073656324301, 0.00046719815518450402, -6.1786048720593501, -4.9366254575058903, 0.121293000821164, -13.5354546658637, 11.122151465656, 8.2996176249675795, -7.8492497139147304, 53.792699096533298, -0.056207389907105297, -0.72284563910330601, -0.034988476570927102, -5.8914910450597402, -0.57259031868870103, -1.3110690999933601, 8.9888650972260002, 6.8430482968640902, -26.406527264610599, -25.8419474444987, 8.95444342115516, -4.1168180484580699, 0.00068908057573134802, -2.0076563509740999, -3.65231424825159, 0.042894239647239998, -9.7520285174303201, 7.9819862061298199, 6.2214414143151, -1.1841920217922099, 31.911005041941699, -0.080053013664620296, -0.54185675163812796, 8.0781654837979193, -9.3493294125201594, -1.24083642122091, -1.6208022544009499, 8.8607449463367196, 2.3445831189331501, -16.218420387174199, -15.8119148955707, 1.7389982134136399, -1.0509978817476, -3.48584361237575e-05, 0.61330220442703598, 2.33052219623813, -0.0057796507046079101, 5.3801162861110896, -1.7460100802854299, -3.4260231079769401, 1.85323155008146, -1.34565392401789, 0.0020702237459098, 0.147768044797361, -0.43649104760725999, 0.997972495465969, 0.056933085588242997, 0.0077486424610570597, -0.89070134502194598, -0.68148789029708001, 0.89518325797891696, 0.16523545732706499, -2.8298454160600501, 0.26096748561569599, -3.9951230141139501e-05, 2.6625953366596802, 0.159171360187916, -0.0080654609832386693, 14.485659114429501, 0.26188806209423798, -8.9564367313419204, 9.5170929366304993, 3.6594343436186199, 0.017879567938259198, 0.0042052494877241001, -1.4377710841437801, 5.8763150360799203, 0.47441391996743998, -0.014783250610591801, -7.06163381200634, -2.9885184999935599, -1.42889911045556, -2.4433038426403901, -9.8958894810457991, 0.55194555716779503, -5.7250805560848302e-05, 0.98372766353792995, 3.2392588139392098, -0.0119630481344816, 0.14153713576169, -2.73924503033615, 0.060309030316031902, 2.34167965625057, -3.8604817562043001, 0.012593073725828199, 0.22349082635471901, -0.35749918018293803, 2.0835157939561699, 0.13368765195851301, 0.0515445449292352, -2.95655438325227, -1.09680637412728, 2.2418386652533302, 1.2169977713442901, -1.20005576483735, 0.48385142427875799}; +// WB3,2+spl: 3,2 +double Slater_inv5_3[441] = {-0.054189244668834902, -105.426713929607, -88.458496476283003, 1.5333775291907901, -306.17152423250297, 211.834723659242, 189.348181800731, -164.85602878397, 1001.02895803198, -19.086531171244101, -14.1862411100869, 93.929906236367501, -177.880045125896, -6.7382862272631598, -14.511503830974201, 198.86948709278099, 116.24375034946701, -509.187787693936, -474.82187536023201, 185.49468275501101, -68.704359475869197, 0.066396729468773799, 128.61396390514599, 107.279152808508, -3.2214077352586501, 377.39638500462598, -258.32727230254102, -233.50899542599601, 202.73053181330999, -1222.6711957145401, 23.374193247961198, 17.0231928902612, -115.31992914359, 218.34781344598201, 8.5868800406738099, 17.706454078785399, -244.13052330624399, -142.42769283244499, 622.15335091370196, 579.15535219316803, -228.72024346964599, 85.262861528059901, 0.042977214694503003, -75.818887039648899, -63.4429496117761, 1.89037149893251, -221.440571714557, 152.54192851849001, 136.92110635753301, -119.073716594494, 720.98982202338402, -13.516656591400601, -9.7291496308540406, 67.372278162472895, -128.19425354399101, -4.9638472213270699, -10.200417492010599, 143.31769471617801, 83.615852083439094, -366.86654819753397, -341.426964056759, 133.98241248588599, -50.230799667840699, -0.074440153582489205, 131.003888225851, 110.340015781723, -1.92534262087524, 381.482058581253, -264.51148724341499, -236.035513173862, 204.43864191351099, -1249.3967405711001, 23.404380739562701, 17.427737318703301, -116.737852869633, 221.189913802663, 8.4677080090305399, 17.684126766935599, -247.44394443997601, -145.031902348194, 635.53348480709997, 592.58164589603302, -230.87850923206801, 85.694308069456397, -0.038299262589364599, -74.702005824131604, -63.171412849899497, 1.0859859506457199, -217.148397050222, 150.25957665606299, 134.431598757773, -117.013550651343, 708.34335491195498, -13.4940069422526, -9.5788103819957797, 66.593490547156307, -125.80391712960601, -4.7671091217963504, -10.2632044954116, 140.809682960885, 82.366527572926103, -360.28206877713399, -335.74815599116999, 131.925760239261, -48.660685665615503, -0.060749768867194, 106.92546569584999, 88.790343162838894, -2.6692288353747702, 312.16097467403699, -214.903931604847, -193.215823966269, 167.781122174079, -1018.10641886182, 19.107519450141002, 14.388719322765001, -95.267373183568594, 180.40857560667001, 6.9728512293157801, 14.4102075774752, -201.83015329787199, -117.917199027973, 518.09179195913805, 482.46342773412402, -189.25708821193001, 70.869624357767506, -0.000187411047696029, -11.9846117540694, -9.5726690972884096, 0.23970985157893901, -31.525734707294099, 26.424001662617101, 19.629541977294, -12.8111861333484, 126.186955595279, -0.21994779537689901, -1.75278408990554, 12.699562562401301, -19.050321348645301, 0.28466729039388, -1.07057307471916, 20.675591706275501, 13.1048598424623, -64.121267975873096, -59.394985304548896, 16.918592992744401, -7.70362909966763, 0.00036065684724530402, 12.9068309168011, 12.002712393435401, -0.33194601220397202, 40.326484701927001, -31.878253347415502, -25.170560077575001, 17.9905011861023, -156.05779622500401, 0.28522581276215098, 2.06069522309385, -17.151275363286, 25.397351917205899, 2.08581286823873, 0.91118057859336898, -26.515090998756101, -14.4035822159035, 78.890023885294596, 75.240667711773398, -20.769502289340899, 10.973365712218101, 0.00054214253230406803, -2.29504518628212, -2.1312244512866698, 0.047562978801466302, -10.6318457557031, 3.0591772010668401, 6.6375862982055702, -4.4363733110097296, 16.291945106274301, -0.062929125223047597, -0.16835581689436099, 6.0820271877694996, -5.8351950377758204, 0.35401259185447298, -0.90070453596893996, 6.0382685793059503, 2.4785619931575602, -8.4908203096171402, -8.6197966065449307, 5.8804527059182696, -1.67757738078734, 0.00096800508899916803, -2.4934502646428101, -4.5195305250493698, 0.052900907147883501, -6.5403147654399101, 8.5375829900159896, 4.1350660479474399, -1.63386715634978, 39.5635438458416, -0.11054656518749099, -0.56905231469759199, 10.2311793759502, -8.8014973731182806, -1.42214511908425, -1.9356586876592501, 7.4277556761303396, 2.8985267278915199, -19.981167223464801, -18.310196540769098, 1.3631485584979499, -1.4104996470922699, 0.000167515045034934, 10.6237721447983, 9.6125946891096099, -0.20829092726741699, 28.481388931713699, -22.584157610136199, -17.8392407006579, 11.6781776869203, -110.705963174229, 0.192721307745398, 1.4471736958685699, -11.629464509211299, 19.0388155304672, -0.23390314175395899, 0.62505732559282601, -19.284349111137399, -11.6199046959709, 56.562315732201498, 53.440734762614099, -13.464260193464, 6.5494922727750904, -0.00064712664753083498, 0.51012013976619996, -0.40601608060218902, -0.010304898323864499, -1.9162384482042301, 0.67040773560745603, 1.4195140953666501, 1.89175006728124, 8.4997123797302105, -0.053837688493721801, -0.0081694468687663092, 7.5841687069424202, -3.9864241641726901, 0.82441242748559596, 1.28841942280286, 2.4602644684099202, -0.65833650503714802, -2.93422340475106, -4.7994849299481297, -3.1153746742144999, 0.76509679552570997, -0.00094253467883977896, 4.5884404541075803, 2.5577714145483599, -0.100362327319965, 18.711173319888399, -7.5191542625802104, -11.814804467633101, 7.51205003788884, -36.605280961279099, 0.11460812693040601, 0.498461399643222, -10.903564320961401, 13.2948947844546, -0.64349351510306596, 1.9974412451213299, -11.727821769419799, -4.9603602940684901, 17.916362650168399, 17.291804112001799, -7.9761250950845, 3.6407278735208699, -0.000183321670183587, 6.4691421816769399, 6.0512576241625498, -0.15162968127745899, 23.395366108183801, -14.5381852262701, -14.606223833564799, 10.199271998597199, -73.975176230999594, 0.109352036334604, 0.939662287060122, -5.0493506777824901, 12.432450504307001, 0.66340082972807302, 0.89171490853171798, -14.301193838340501, -7.1767924210601599, 37.417730343433, 34.621199008384998, -12.2257905481279, 5.0337643040644098, 0.00077853683475417402, -4.0437466042030499, -3.2232682351578399, 0.038202731665628202, -12.153196028398099, 6.5027616010011799, 7.2973627140258399, -12.054113026894999, 23.6623418919025, 0.0029087480524890102, -0.465988240269751, -5.8215678299339997, -0.92982871489462304, 0.72875377435640498, -1.76856112702097, 3.9100682853776498, 4.3638012685037904, -12.532035664209801, -10.8596693966264, 12.5729914998231, -1.17795314966104, -0.00047116201805309901, 2.7712702890005598, 1.4259517039641101, -0.060855532638316702, 9.8783846948200704, -5.3156162802238898, -6.24217543532784, 4.0955113938692902, -22.6133771249789, 0.0576846298115802, 0.37261538596098298, -5.69311024324454, 6.6165547759347501, -0.31572322723037299, 1.2076815066994999, -7.13883450856141, -3.0036796657518701, 12.888731168100399, 10.144844547714699, -3.4202567509716602, 2.2424073656324301, 0.00046719815518450402, -6.1786048720593501, -4.9366254575058903, 0.121293000821164, -13.5354546658637, 11.122151465656, 8.2996176249675795, -7.8492497139147304, 53.792699096533298, -0.056207389907105297, -0.72284563910330601, -0.034988476570927102, -5.8914910450597402, -0.57259031868870103, -1.3110690999933601, 8.9888650972260002, 6.8430482968640902, -26.406527264610599, -25.8419474444987, 8.95444342115516, -4.1168180484580699, 0.00068908057573134802, -2.0076563509740999, -3.65231424825159, 0.042894239647239998, -9.7520285174303201, 7.9819862061298199, 6.2214414143151, -1.1841920217922099, 31.911005041941699, -0.080053013664620296, -0.54185675163812796, 8.0781654837979193, -9.3493294125201594, -1.24083642122091, -1.6208022544009499, 8.8607449463367196, 2.3445831189331501, -16.218420387174199, -15.8119148955707, 1.7389982134136399, -1.0509978817476, -3.48584361237575e-05, 0.61330220442703598, 2.33052219623813, -0.0057796507046079101, 5.3801162861110896, -1.7460100802854299, -3.4260231079769401, 1.85323155008146, -1.34565392401789, 0.0020702237459098, 0.147768044797361, -0.43649104760725999, 0.997972495465969, 0.056933085588242997, 0.0077486424610570597, -0.89070134502194598, -0.68148789029708001, 0.89518325797891696, 0.16523545732706499, -2.8298454160600501, 0.26096748561569599, -3.9951230141139501e-05, 2.6625953366596802, 0.159171360187916, -0.0080654609832386693, 14.485659114429501, 0.26188806209423798, -8.9564367313419204, 9.5170929366304993, 3.6594343436186199, 0.017879567938259198, 0.0042052494877241001, -1.4377710841437801, 5.8763150360799203, 0.47441391996743998, -0.014783250610591801, -7.06163381200634, -2.9885184999935599, -1.42889911045556, -2.4433038426403901, -9.8958894810457991, 0.55194555716779503, -5.7250805560848302e-05, 0.98372766353792995, 3.2392588139392098, -0.0119630481344816, 0.14153713576169, -2.73924503033615, 0.060309030316031902, 2.34167965625057, -3.8604817562043001, 0.012593073725828199, 0.22349082635471901, -0.35749918018293803, 2.0835157939561699, 0.13368765195851301, 0.0515445449292352, -2.95655438325227, -1.09680637412728, 2.2418386652533302, 1.2169977713442901, -1.20005576483735, 0.48385142427875799}; + +rc = qmckl_sherman_morrison_c(context, Dim, N_updates1, Updates1, Updates_index1, breakdown, Slater_inv1); +for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + res[i * Dim + j] = 0; + for (unsigned int k = 0; k < Dim; k++) { + res[i * Dim + j] += Slater1[i * Dim + k] * Slater_inv1[k * Dim + j]; + } + } +} +rc = QMCKL_SUCCESS; +for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + if (i == j && fabs(res[i * Dim + j] - 1) > tolerance) { + rc = QMCKL_FAILURE; + } + if (i != j && fabs(res[i * Dim + j]) > tolerance) { + rc = QMCKL_FAILURE; + } + } +} assert(rc == QMCKL_SUCCESS); #+end_src @@ -622,23 +667,30 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, *** Test :noexport: -[TODO: FMJC] Write tests for the Sherman-Morrison part. - - #+begin_src c :tangle (eval c_test) -const uint64_t woodbury_Dim = 2; -const uint64_t woodbury_Updates_index[2] = {1, 1}; -const double woodbury_Updates[4] = {1.0, 1.0, 1.0, 1.0}; -const double woodbury_breakdown = 1e-3; -double woodbury_Slater_inv[4] = {1.0, 1.0, 1.0, 1.0}; - -// [TODO : FMJC ] add realistic tests - -rc = qmckl_woodbury_2_c(context, woodbury_Dim, woodbury_Updates, woodbury_Updates_index, woodbury_breakdown, woodbury_Slater_inv); +rc = qmckl_woodbury_2_c(context, Dim, Updates2, Updates_index2, breakdown, Slater_inv2); +for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + res[i * Dim + j] = 0; + for (unsigned int k = 0; k < Dim; k++) { + res[i * Dim + j] += Slater2[i * Dim + k] * Slater_inv2[k * Dim + j]; + } + } +} +rc = QMCKL_SUCCESS; +for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + if (i == j && fabs(res[i * Dim + j] - 1) > tolerance) { + rc = QMCKL_FAILURE; + } + if (i != j && fabs(res[i * Dim + j]) > tolerance) { + rc = QMCKL_FAILURE; + } + } +} assert(rc == QMCKL_SUCCESS); #+end_src - * Woodbury 3x3 ** ~qmckl_woodbury_3~ @@ -855,19 +907,27 @@ qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, *** Test :noexport: -[TODO: FMJC] Write tests for the Sherman-Morrison part. - - #+begin_src c :tangle (eval c_test) -const uint64_t woodbury3_Dim = 3; -const uint64_t woodbury3_Updates_index[3] = {1, 1, 1}; -const double woodbury3_Updates[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; -const double woodbury3_breakdown = 1e-3; -double woodbury3_Slater_inv[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; - -// [TODO : FMJC ] add realistic tests - -rc = qmckl_woodbury_3_c(context, woodbury3_Dim, woodbury3_Updates, woodbury3_Updates_index, woodbury3_breakdown, woodbury3_Slater_inv); +rc = qmckl_woodbury_3_c(context, Dim, Updates3, Updates_index3, breakdown, Slater_inv3_1); +for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + res[i * Dim + j] = 0; + for (unsigned int k = 0; k < Dim; k++) { + res[i * Dim + j] += Slater3[i * Dim + k] * Slater_inv3_1[k * Dim + j]; + } + } +} +rc = QMCKL_SUCCESS; +for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + if (i == j && fabs(res[i * Dim + j] - 1) > tolerance) { + rc = QMCKL_FAILURE; + } + if (i != j && fabs(res[i * Dim + j]) > tolerance) { + rc = QMCKL_FAILURE; + } + } +} assert(rc == QMCKL_SUCCESS); #+end_src @@ -1037,20 +1097,27 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, *** Test :noexport: -[TODO: FMJC] Write tests for the Sherman-Morrison part. - - #+begin_src c :tangle (eval c_test) -const uint64_t splitting_Dim = 3; -const uint64_t splitting_N_updates = 3; -const uint64_t splitting_Updates_index[3] = {1, 1, 1}; -const double splitting_Updates[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; -const double splitting_breakdown = 1e-3; -double splitting_Slater_inv[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; - -// [TODO : FMJC ] add realistic tests - -rc = qmckl_sherman_morrison_splitting_c(context, splitting_Dim, splitting_N_updates, splitting_Updates, splitting_Updates_index, splitting_breakdown, splitting_Slater_inv); +rc = qmckl_sherman_morrison_splitting_c(context, Dim, N_updates3, Updates3, Updates_index3, breakdown, Slater_inv3_2); +for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + res[i * Dim + j] = 0; + for (unsigned int k = 0; k < Dim; k++) { + res[i * Dim + j] += Slater3[i * Dim + k] * Slater_inv3_2[k * Dim + j]; + } + } +} +rc = QMCKL_SUCCESS; +for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + if (i == j && fabs(res[i * Dim + j] - 1) > tolerance) { + rc = QMCKL_FAILURE; + } + if (i != j && fabs(res[i * Dim + j]) > tolerance) { + rc = QMCKL_FAILURE; + } + } +} assert(rc == QMCKL_SUCCESS); #+end_src @@ -1243,21 +1310,27 @@ qmckl_exit_code qmckl_sherman_morrison_smw2s_c(const qmckl_context context, *** Test :noexport: -[TODO: FMJC] Write tests for the Sherman-Morrison part. - - #+begin_src c :tangle (eval c_test) -const uint64_t smw2s_Dim = 3; -const uint64_t smw2s_N_updates = 3; -const uint64_t smw2s_Updates_index[3] = {1, 1, 1}; -const double smw2s_Updates[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; -const double smw2s_breakdown = 1e-3; -double smw2s_Slater_inv[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; - -// [TODO : FMJC ] add realistic tests - -rc = qmckl_sherman_morrison_smw2s_c(context, smw2s_Dim, smw2s_N_updates, - smw2s_Updates, smw2s_Updates_index, smw2s_breakdown, smw2s_Slater_inv); +rc = qmckl_sherman_morrison_smw2s_c(context, Dim, N_updates5, Updates5, Updates_index5, breakdown, Slater_inv5_1); +for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + res[i * Dim + j] = 0; + for (unsigned int k = 0; k < Dim; k++) { + res[i * Dim + j] += Slater5[i * Dim + k] * Slater_inv5_1[k * Dim + j]; + } + } +} +rc = QMCKL_SUCCESS; +for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + if (i == j && fabs(res[i * Dim + j] - 1) > tolerance) { + rc = QMCKL_FAILURE; + } + if (i != j && fabs(res[i * Dim + j]) > tolerance) { + rc = QMCKL_FAILURE; + } + } +} assert(rc == QMCKL_SUCCESS); #+end_src @@ -1445,21 +1518,27 @@ qmckl_exit_code qmckl_sherman_morrison_smw3s_c(const qmckl_context context, *** Test :noexport: -[TODO: FMJC] Write tests for the Sherman-Morrison part. - - #+begin_src c :tangle (eval c_test) -const uint64_t smw3s_Dim = 3; -const uint64_t smw3s_N_updates = 3; -const uint64_t smw3s_Updates_index[3] = {1, 1, 1}; -const double smw3s_Updates[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; -const double smw3s_breakdown = 1e-3; -double smw3s_Slater_inv[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; - -// [TODO : FMJC ] add realistic tests - -rc = qmckl_sherman_morrison_smw3s_c(context, smw3s_Dim, smw3s_N_updates, - smw3s_Updates, smw3s_Updates_index, smw3s_breakdown, smw3s_Slater_inv); +rc = qmckl_sherman_morrison_smw3s_c(context, Dim, N_updates5, Updates5, Updates_index5, breakdown, Slater_inv5_2); +for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + res[i * Dim + j] = 0; + for (unsigned int k = 0; k < Dim; k++) { + res[i * Dim + j] += Slater5[i * Dim + k] * Slater_inv5_2[k * Dim + j]; + } + } +} +rc = QMCKL_SUCCESS; +for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + if (i == j && fabs(res[i * Dim + j] - 1) > tolerance) { + rc = QMCKL_FAILURE; + } + if (i != j && fabs(res[i * Dim + j]) > tolerance) { + rc = QMCKL_FAILURE; + } + } +} assert(rc == QMCKL_SUCCESS); #+end_src @@ -1658,27 +1737,30 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, *** Test :noexport: -[TODO: FMJC] Write tests for the Sherman-Morrison part. - - #+begin_src c :tangle (eval c_test) -const uint64_t smw32s_Dim = 3; -const uint64_t smw32s_N_updates = 3; -const uint64_t smw32s_Updates_index[3] = {1, 1, 1}; -const double smw32s_Updates[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; -const double smw32s_breakdown = 1e-3; -double smw32s_Slater_inv[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; - -// [TODO : FMJC ] add realistic tests - -rc = qmckl_sherman_morrison_smw32s_c(context, smw32s_Dim, smw32s_N_updates, - smw32s_Updates, smw32s_Updates_index, smw32s_breakdown, smw32s_Slater_inv); +rc = qmckl_sherman_morrison_smw32s_c(context, Dim, N_updates5, Updates5, Updates_index5, breakdown, Slater_inv5_3); +for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + res[i * Dim + j] = 0; + for (unsigned int k = 0; k < Dim; k++) { + res[i * Dim + j] += Slater5[i * Dim + k] * Slater_inv5_3[k * Dim + j]; + } + } +} +rc = QMCKL_SUCCESS; +for (unsigned int i = 0; i < Dim; i++) { + for (unsigned int j = 0; j < Dim; j++) { + if (i == j && fabs(res[i * Dim + j] - 1) > tolerance) { + rc = QMCKL_FAILURE; + } + if (i != j && fabs(res[i * Dim + j]) > tolerance) { + rc = QMCKL_FAILURE; + } + } +} assert(rc == QMCKL_SUCCESS); #+end_src - - - * End of files #+begin_src c :comments link :tangle (eval c_test) @@ -1691,4 +1773,3 @@ assert(rc == QMCKL_SUCCESS); # -*- mode: org -*- # vim: syntax=c - From dcd6428c505742126e566c240b3f6551df69d58d Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Tue, 7 Sep 2021 09:27:22 +0200 Subject: [PATCH 38/50] * Moved Helper functions to the end * Typo fixed --- org/qmckl_sherman_morrison_woodbury.org | 350 ++++++++++++------------ 1 file changed, 177 insertions(+), 173 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 863573f..ed3d06a 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -4,7 +4,7 @@ Low- and high-level functions that use the Sherman-Morrison and Woodbury matrix inversion formulas to update the inverse of a - non-singualr matrix + non-singular matrix * Headers #+begin_src elisp :noexport :results none :exports none @@ -27,178 +27,6 @@ int main() { #+end_src -* Helper Functions - -Helper functions that are used by the Sherman-Morrison-Woodbury kernels. -These functions can only be used internally by higher level functions. - -** ~qmckl_slagel_splitting~ - :PROPERTIES: - :Name: qmckl_slagel_splitting - :CRetType: double - :FRetType: double precision - :END: - - ~qmckl_slagel_splitting~ is used internally to apply a list of rank-1 updates while splitting an update if necessary. - In case of a split it applies the first half of the update while putting the second half in waiting queue to be applied at the end. - - For a given update $u_j$ we define a threshold value $\epsilon_j$, which is the minimum value of - $1+v_j^TS^{-1}u_j$ for a non-singular matrix $S$. If $1+v_j^TS^{-1}u_j \geq \epsilon_j$, - the update is applied as usual. Otherwise, $u_j$ will be redefined as $\frac{u_j}{2}$, and the other half - (to be applied at the end) will be defined using vectors $\frac{u_{j'}}{2}$ and $v_{j'}^T=v_{j'}^T$. - - #+NAME: qmckl_slagel_splitting_args - | uint64_t | Dim | in | Leading dimension of Slater_inv | - | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | - | double | Updates[N_updates*Dim] | in | Array containing the rank-1 updates | - | uint64_t | Updates_index[N_updates] | in | Array containing positions of the rank-1 updates | - | double | breakdown | in | Break-down parameter on which to fail or not | - | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse Slater-matrix | - | double | later_updates[Dim * N_updates] | inout | Array containing the split updates for later | - | uint64_t | later_index[N_updates] | inout | Array containing the positions of the split updates for later | - | uint64_t | later | inout | Number of split updates for later | - - -*** Requirements - - - ~Dim >= 2~ - - ~N_updates >= 1~ - - ~Updates~ is allocated with at least $1 \times 2 \times 8$ bytes - - ~Updates_index~ is allocated with at least $1 \times 8$ bytes - - ~breakdown~ is a small number such that $0 < breakdown << 1$ - - ~Slater_inv~ is allocated with at least $Dim \times Dim \times 8$ bytes - - ~later_updates~ is allocated with at least $1 \times 2 \times 8$ bytes - - ~later_index~ is allocated with at least $1 \times 8$ bytes - - ~later >= 0~ - -*** C header - - #+CALL: generate_c_header(table=qmckl_slagel_splitting_args,rettyp=get_value("CRetType"),fname=get_value("Name")) - - #+RESULTS: - #+begin_src c :tangle (eval h_func) :comments org - qmckl_exit_code qmckl_slagel_splitting_c ( - const uint64_t Dim, - const uint64_t N_updates, - const double* Updates, - const uint64_t* Updates_index, - const double breakdown, - double* Slater_inv, - double* later_updates, - uint64_t* later_index, - uint64_t* later ); - #+end_src - -*** Source Fortran - -*** Source C - - #+begin_src c :tangle (eval c) :comments org -#include -#include -#include "qmckl.h" - -qmckl_exit_code qmckl_slagel_splitting_c(uint64_t Dim, - uint64_t N_updates, - const double *Updates, - const uint64_t *Updates_index, - const double breakdown, - double *Slater_inv, - double *later_updates, - uint64_t *later_index, - uint64_t *later) { -// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. -// std::cerr << "Called slagel_splitting with " << N_updates << " updates" << std::endl; -// #endif - - double C[Dim]; - double D[Dim]; - - uint64_t l = 0; - // For each update - while (l < N_updates) { - // C = S^{-1} x U_l - for (uint64_t i = 0; i < Dim; i++) { - C[i] = 0; - for (uint64_t j = 0; j < Dim; j++) { - C[i] += Slater_inv[i * Dim + j] * Updates[l * Dim + j]; - } - } - - // Denominator - double den = 1 + C[Updates_index[l] - 1]; - if (fabs(den) < breakdown) { - - // U_l = U_l / 2 (do the split) - for (uint64_t i = 0; i < Dim; i++) { - later_updates[*later * Dim + i] = Updates[l * Dim + i] / 2.0; - C[i] /= 2.0; - } - later_index[*later] = Updates_index[l]; - (*later)++; - - den = 1 + C[Updates_index[l] - 1]; - } - double iden = 1 / den; - - // D = v^T x S^{-1} - for (uint64_t j = 0; j < Dim; j++) { - D[j] = Slater_inv[(Updates_index[l] - 1) * Dim + j]; - } - - // S^{-1} = S^{-1} - C x D / den - for (uint64_t i = 0; i < Dim; i++) { - for (uint64_t j = 0; j < Dim; j++) { - double update = C[i] * D[j] * iden; - Slater_inv[i * Dim + j] -= update; - } - } - l += 1; - } - - return QMCKL_SUCCESS; -} - - #+end_src - -*** Performance - -This function performce better for cycles with 1 rank-1 update and with a high fail-rate. - - -** C interface :noexport: - - #+CALL: generate_c_interface(table=qmckl_slagel_splitting_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - - #+RESULTS: - #+begin_src f90 :tangle (eval f) :comments org :exports none - integer(c_int32_t) function qmckl_slagel_splitting & - (Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv, later_updates, later_index, later) & - bind(C) result(info) - - use, intrinsic :: iso_c_binding - implicit none - - integer (c_int64_t) , intent(in) , value :: Dim - integer (c_int64_t) , intent(in) , value :: N_updates - real (c_double ) , intent(in) :: Updates(N_updates*Dim) - integer (c_int64_t) , intent(in) :: Updates_index(N_updates) - real (c_double ) , intent(in) , value :: breakdown - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) - real (c_double ) , intent(inout) :: later_updates(Dim * N_updates) - integer (c_int64_t) , intent(inout) :: later_index(N_updates) - integer (c_int64_t) , intent(inout) :: later - - integer(c_int32_t), external :: qmckl_slagel_splitting_c - info = qmckl_slagel_splitting_c & - (Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv, later_updates, later_index, later) - - end function qmckl_slagel_splitting - #+end_src - -*** Test :noexport: - - This kernel does not have an explicit test because it is only used internally by higher-level Sherman-Morrison-Woodbury kernels. * Naïve Sherman-Morrison @@ -691,6 +519,7 @@ for (unsigned int i = 0; i < Dim; i++) { assert(rc == QMCKL_SUCCESS); #+end_src + * Woodbury 3x3 ** ~qmckl_woodbury_3~ @@ -1761,6 +1590,181 @@ for (unsigned int i = 0; i < Dim; i++) { assert(rc == QMCKL_SUCCESS); #+end_src + +* Helper Functions + +Helper functions that are used by the Sherman-Morrison-Woodbury kernels. +These functions can only be used internally by higher level functions. + +** ~qmckl_slagel_splitting~ + :PROPERTIES: + :Name: qmckl_slagel_splitting + :CRetType: double + :FRetType: double precision + :END: + + ~qmckl_slagel_splitting~ is used internally to apply a list of rank-1 updates while splitting an update if necessary. + In case of a split it applies the first half of the update while putting the second half in waiting queue to be applied at the end. + + For a given update $u_j$ we define a threshold value $\epsilon_j$, which is the minimum value of + $1+v_j^TS^{-1}u_j$ for a non-singular matrix $S$. If $1+v_j^TS^{-1}u_j \geq \epsilon_j$, + the update is applied as usual. Otherwise, $u_j$ will be redefined as $\frac{u_j}{2}$, and the other half + (to be applied at the end) will be defined using vectors $\frac{u_{j'}}{2}$ and $v_{j'}^T=v_{j'}^T$. + + #+NAME: qmckl_slagel_splitting_args + | uint64_t | Dim | in | Leading dimension of Slater_inv | + | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | + | double | Updates[N_updates*Dim] | in | Array containing the rank-1 updates | + | uint64_t | Updates_index[N_updates] | in | Array containing positions of the rank-1 updates | + | double | breakdown | in | Break-down parameter on which to fail or not | + | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse Slater-matrix | + | double | later_updates[Dim * N_updates] | inout | Array containing the split updates for later | + | uint64_t | later_index[N_updates] | inout | Array containing the positions of the split updates for later | + | uint64_t | later | inout | Number of split updates for later | + + +*** Requirements + + - ~Dim >= 2~ + - ~N_updates >= 1~ + - ~Updates~ is allocated with at least $1 \times 2 \times 8$ bytes + - ~Updates_index~ is allocated with at least $1 \times 8$ bytes + - ~breakdown~ is a small number such that $0 < breakdown << 1$ + - ~Slater_inv~ is allocated with at least $Dim \times Dim \times 8$ bytes + - ~later_updates~ is allocated with at least $1 \times 2 \times 8$ bytes + - ~later_index~ is allocated with at least $1 \times 8$ bytes + - ~later >= 0~ + +*** C header + + #+CALL: generate_c_header(table=qmckl_slagel_splitting_args,rettyp=get_value("CRetType"),fname=get_value("Name")) + + #+RESULTS: + #+begin_src c :tangle (eval h_func) :comments org + qmckl_exit_code qmckl_slagel_splitting_c ( + const uint64_t Dim, + const uint64_t N_updates, + const double* Updates, + const uint64_t* Updates_index, + const double breakdown, + double* Slater_inv, + double* later_updates, + uint64_t* later_index, + uint64_t* later ); + #+end_src + +*** Source Fortran + +*** Source C + + #+begin_src c :tangle (eval c) :comments org +#include +#include +#include "qmckl.h" + +qmckl_exit_code qmckl_slagel_splitting_c(uint64_t Dim, + uint64_t N_updates, + const double *Updates, + const uint64_t *Updates_index, + const double breakdown, + double *Slater_inv, + double *later_updates, + uint64_t *later_index, + uint64_t *later) { +// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. +// std::cerr << "Called slagel_splitting with " << N_updates << " updates" << std::endl; +// #endif + + double C[Dim]; + double D[Dim]; + + uint64_t l = 0; + // For each update + while (l < N_updates) { + // C = S^{-1} x U_l + for (uint64_t i = 0; i < Dim; i++) { + C[i] = 0; + for (uint64_t j = 0; j < Dim; j++) { + C[i] += Slater_inv[i * Dim + j] * Updates[l * Dim + j]; + } + } + + // Denominator + double den = 1 + C[Updates_index[l] - 1]; + if (fabs(den) < breakdown) { + + // U_l = U_l / 2 (do the split) + for (uint64_t i = 0; i < Dim; i++) { + later_updates[*later * Dim + i] = Updates[l * Dim + i] / 2.0; + C[i] /= 2.0; + } + later_index[*later] = Updates_index[l]; + (*later)++; + + den = 1 + C[Updates_index[l] - 1]; + } + double iden = 1 / den; + + // D = v^T x S^{-1} + for (uint64_t j = 0; j < Dim; j++) { + D[j] = Slater_inv[(Updates_index[l] - 1) * Dim + j]; + } + + // S^{-1} = S^{-1} - C x D / den + for (uint64_t i = 0; i < Dim; i++) { + for (uint64_t j = 0; j < Dim; j++) { + double update = C[i] * D[j] * iden; + Slater_inv[i * Dim + j] -= update; + } + } + l += 1; + } + + return QMCKL_SUCCESS; +} + + #+end_src + +*** Performance + +This function performce better for cycles with 1 rank-1 update and with a high fail-rate. + + +** C interface :noexport: + + #+CALL: generate_c_interface(table=qmckl_slagel_splitting_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + + #+RESULTS: + #+begin_src f90 :tangle (eval f) :comments org :exports none + integer(c_int32_t) function qmckl_slagel_splitting & + (Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv, later_updates, later_index, later) & + bind(C) result(info) + + use, intrinsic :: iso_c_binding + implicit none + + integer (c_int64_t) , intent(in) , value :: Dim + integer (c_int64_t) , intent(in) , value :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(in) , value :: breakdown + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + real (c_double ) , intent(inout) :: later_updates(Dim * N_updates) + integer (c_int64_t) , intent(inout) :: later_index(N_updates) + integer (c_int64_t) , intent(inout) :: later + + integer(c_int32_t), external :: qmckl_slagel_splitting_c + info = qmckl_slagel_splitting_c & + (Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv, later_updates, later_index, later) + + end function qmckl_slagel_splitting + #+end_src + +*** Test :noexport: + + This kernel does not have an explicit test because it is only used internally by higher-level Sherman-Morrison-Woodbury kernels. + + * End of files #+begin_src c :comments link :tangle (eval c_test) From 78c574af49a20e3e6d907e3d1b75caea6e0ad134 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Tue, 7 Sep 2021 11:22:54 +0200 Subject: [PATCH 39/50] Improved documentation and Requirements sections. --- org/qmckl_sherman_morrison_woodbury.org | 536 +++--------------------- 1 file changed, 62 insertions(+), 474 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index ed3d06a..6bd083b 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -5,7 +5,7 @@ Low- and high-level functions that use the Sherman-Morrison and Woodbury matrix inversion formulas to update the inverse of a non-singular matrix - + * Headers #+begin_src elisp :noexport :results none :exports none (org-babel-lob-ingest "../tools/lib.org") @@ -26,7 +26,6 @@ int main() { qmckl_exit_code rc; #+end_src - * Naïve Sherman-Morrison @@ -37,13 +36,12 @@ int main() { :FRetType: qmckl_exit_code :END: - This is the simplest of the available Sherman-Morrison-Woodbury - kernels. It applies rank-1 updates one by one in the order - that is given. It only checks if the denominator in the - Sherman-Morrison formula is not too close to zero when an update is evaluated. - It will exit with an error code of the denominator is too close to zero. - The formula that is applied is + This is the simplest of the available Sherman-Morrison-Woodbury kernels. It applies rank-1 updates one by one in + the order that is given. It only checks if the denominator in the Sherman-Morrison formula is not too close to + zero when an update is evaluated. It will exit with an error code of the denominator is too close to zero. + + The formula for any update $u_j$ (index $j$ is suppresed for clarity) that is applied is \[ (S + uv^T)^{-1} = S^{-1} - \frac{S^{-1} uv^T S^{-1}}{1 + v^T S^{-1} u} \] @@ -53,6 +51,17 @@ int main() { $u$ and $v^T$ are the column and row vectors containing the updates, $S^{-1}$ is the inverse of the Slater-matrix. + Even though the Slater-matrix $S$ with all updates applied at once is invertable, during the course of applying + updates to the inverse Slater-matrix $S^{-1}$ one-by-one it can happen that one of the intermediate inverse + matrices $S^{-1}$ becomes singular. Therefore a global threshold value $\epsilon$ is defined that is used to + evaluate each individual update $u_j$ when it is applied. + + This value sets the lower bound for which the + denominator $1+v_j^TS^{-1}u_j$ is considered to be too small and will most probably result in a singular matrix + $S$, or at least in an inverse of $S$ of very poor numerical quality. Therefore, when $1+v_j^TS^{-1}u_j \geq \epsilon$, + the update is applied as usual. If $1+v_j^TS^{-1}u_j \leq \epsilon$ the update is rejected and the kernel exits with + return code \texttt{QMCKL_FAILURE}. + #+NAME: qmckl_sherman_morrison_args | qmckl_context | context | in | Global state | | uint64_t | Dim | in | Leading dimension of Slater_inv | @@ -64,13 +73,13 @@ int main() { *** Requirements - - ~context~ is not ~QMCKL_NULL_CONTEXT~ - - ~Dim >= 2~ - - ~N_updates >= 1~ - - ~Updates~ is allocated with at least $1 \times 2 \times 8$ bytes - - ~Updates_index~ is allocated with at least $1 \times 8$ bytes - - ~breakdown~ is a small number such that $0 < breakdown << 1$ - - ~Slater_inv~ is allocated with at least $Dim \times Dim \times 8$ bytes + * ~context~ is not ~QMCKL_NULL_CONTEXT~ + * ~Dim >= 2~ + * ~N_updates >= 1~ + * ~Updates~ is allocated with $N_updates \times Dim$ elements + * ~Updates_index~ is allocated with $N_updates$ elements + * ~breakdown~ is a small number such that $0 < breakdown << 1$ + * ~Slater_inv~ is allocated with $Dim \times Dim$ elements *** C header @@ -297,8 +306,8 @@ assert(rc == QMCKL_SUCCESS); :FRetType: qmckl_exit_code :END: - The simplest version of the generalised Sherman-Morrison-Woodbury kernels. It is used to apply two - rank-1 updates at once. The formula used in this algorithm is called the Woodbury Matrix Identity + The Woodbury 2x2 kernel. It is used to apply two rank-1 updates at once. The formula used in + this algorithm is called the Woodbury Matrix Identity \[ (S + U V)^{-1} = S^{-1} - C B^{-1} D \] @@ -322,11 +331,11 @@ assert(rc == QMCKL_SUCCESS); *** Requirements - ~context~ is not ~qmckl_null_context~ - - ~dim >= 2~ - - ~updates~ is allocated with at least $2 \times 2 \times 8$ bytes - - ~updates_index~ is allocated with $2 \times 8$ bytes + - ~Dim >= 2~ + - ~Updates~ is allocated with $2 \times Dim$ elements + - ~Updates_index~ is allocated with $2$ elements - ~breakdown~ is a small number such that $0 < breakdown << 1$ - - ~slater_inv~ is allocated with at least $dim \times dim \times 8$ bytes + - ~Slater_inv~ is allocated with $Dim \times Dim$ elements *** C header @@ -438,7 +447,6 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, #+end_src - *** Performance This function is most efficient when used in cases where there are only 2 rank-1 updates. @@ -548,11 +556,11 @@ assert(rc == QMCKL_SUCCESS); *** Requirements - ~context~ is not ~qmckl_null_context~ - - ~dim >= 2~ - - ~updates~ is allocated with at least $3 \times 2 \times 8$ bytes - - ~updates_index~ is allocated with $3 \times 8$ bytes + - ~Dim >= 2~ + - ~Updates~ is allocated with $3 \times Dim$ elements + - ~Updates_index~ is allocated with $3$ elements - ~breakdown~ is a small number such that $0 < breakdown << 1$ - - ~slater_inv~ is allocated with at least $dim \times dim \times 8$ bytes + - ~Slater_inv~ is allocated with $Dim \times Dim$ elements *** C header @@ -790,13 +798,13 @@ assert(rc == QMCKL_SUCCESS); *** Requirements - - ~context~ is not ~QMCKL_NULL_CONTEXT~ - - ~Dim >= 2~ - - ~N_updates >= 1~ - - ~Updates~ is allocated with at least $1 \times 2 \times 8$ bytes - - ~Updates_index~ is allocated with at least $1 \times 8$ bytes - - ~breakdown~ is a small number such that $0 < breakdown << 1$ - - ~Slater_inv~ is allocated with at least $Dim \times Dim \times 8$ bytes + * ~context~ is not ~QMCKL_NULL_CONTEXT~ + * ~Dim >= 2~ + * ~N_updates >= 1~ + * ~Updates~ is allocated with $N_updates \times Dim$ elements + * ~Updates_index~ is allocated with $N_updates$ elements + * ~breakdown~ is a small number such that $0 < breakdown << 1$ + * ~Slater_inv~ is allocated with $Dim \times Dim$ elements *** C header @@ -951,427 +959,6 @@ assert(rc == QMCKL_SUCCESS); #+end_src -* Woodbury 2x2 with Sherman-Morrison and update splitting - -** ~qmckl_sherman_morrison_smw2s~ - :PROPERTIES: - :Name: qmckl_sherman_morrison_smw2s - :CRetType: qmckl_exit_code - :FRetType: qmckl_exit_code - :END: - - The Woodbury 2x2 kernel with Sherman-Morrison and update splitting combines the low-level Woodbury 2x2 kernel - and Sherman-Morrison with update splitting. For a given number of updates $N$ it splits the number of updates - in blocks of two updates. The blocks of two updates are then applied one by one using Woodbury 2x2. If a block - of updates fails, both updates in the block are applied with Sherman-Morrison instead, split if necessary and - with their second half put in a queue. After all blocks are processed the remaining one update --in case there - was an odd number of updates to begin with-- is also aplpied with Sherman-Morrison and split if necessary. - The queue containing the collected second halves of all the processed updates is processed at the very end to - avoid having many intermediate queues containing only a few updates that risks an increased probability - of artificially created non-singular intermediate matrices, resulting from division up the total number of - updates in blocks of three. - - - #+NAME: qmckl_sherman_morrison_smw2s_args - | qmckl_context | context | in | Global state | - | uint64_t | Dim | in | Leading dimension of Slater_inv | - | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | - | double | Updates[N_updates*Dim] | in | Array containing the updates | - | uint64_t | Updates_index[N_updates] | in | Array containing the rank-1 updates | - | double | breakdown | in | Break-down parameter on which to fail or not | - | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | - -*** Requirements - - - ~context~ is not ~QMCKL_NULL_CONTEXT~ - - ~Dim >= 2~ - - ~N_updates >= 1~ - - ~Updates~ is allocated with at least $1 \times 2 \times 8$ bytes - - ~Updates_index~ is allocated with at least $1 \times 8$ bytes - - ~breakdown~ is a small number such that $0 < breakdown << 1$ - - ~Slater_inv~ is allocated with at least $Dim \times Dim \times 8$ bytes - -*** C header - - #+CALL: generate_c_header(table=qmckl_sherman_morrison_smw2s_args,rettyp=get_value("CRetType"),fname=get_value("Name")) - - #+RESULTS: - #+begin_src c :tangle (eval h_func) :comments org - qmckl_exit_code qmckl_sherman_morrison_smw2s_c ( - const qmckl_context context, - const uint64_t Dim, - const uint64_t N_updates, - const double* Updates, - const uint64_t* Updates_index, - const double breakdown, - double* Slater_inv ); - #+end_src - -*** Source Fortran - - #+begin_src f90 :tangle (eval f) -integer function qmckl_sherman_morrison_smw2s_f(context, Slater_inv, Dim, N_updates, & - Updates, Updates_index) result(info) - use qmckl - implicit none - integer(qmckl_context) , intent(in) :: context - integer*8 , intent(in), value :: Dim, N_updates - integer*8 , intent(in) :: Updates_index(N_updates) - real*8 , intent(in) :: Updates(N_updates*Dim) - real*8 , intent(inout) :: Slater_inv(Dim*Dim) - info = qmckl_sherman_morrison_smw2s (context, Dim, N_updates, Updates, Updates_index, Slater_inv) -end function qmckl_sherman_morrison_smw2s_f - #+end_src - -*** Source C - - #+begin_src c :tangle (eval c) :comments org -#include -#include "qmckl.h" - -qmckl_exit_code qmckl_sherman_morrison_smw2s_c(const qmckl_context context, - const uint64_t Dim, - const uint64_t N_updates, - const double* Updates, - const uint64_t* Updates_index, - const double breakdown, - double * Slater_inv) { -// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. -// std::cerr << "Called qmckl_sherman_morrison_woodbury_2 with " << N_updates -// << " updates" << std::endl; -// #endif - - qmckl_exit_code rc; - - uint64_t n_of_2blocks = N_updates / 2; - uint64_t remainder = N_updates % 2; - uint64_t length_2block = 2 * Dim; - - // Apply first 2*n_of_2blocks updates in n_of_2blocks blocks of 2 updates with - // Woodbury 2x2 kernel - double later_updates[Dim * N_updates]; - uint64_t later_index[N_updates]; - uint64_t later = 0; - if (n_of_2blocks > 0) { - for (uint64_t i = 0; i < n_of_2blocks; i++) { - const double *Updates_2block = &Updates[i * length_2block]; - const uint64_t *Updates_index_2block = &Updates_index[i * 2]; - rc = qmckl_woodbury_2_c(context, Dim, Updates_2block, Updates_index_2block, breakdown, Slater_inv); - if (rc != 0) { // Send the entire block to slagel_splitting - uint64_t l = 0; - rc = qmckl_slagel_splitting_c(Dim, 2, Updates_2block, Updates_index_2block, - breakdown, Slater_inv, later_updates + (Dim * later), later_index + later, &l); - later = later + l; - } - } - } - - if (remainder == 1) { // Apply last remaining update with slagel_splitting - const double *Updates_1block = &Updates[n_of_2blocks * length_2block]; - const uint64_t *Updates_index_1block = &Updates_index[2 * n_of_2blocks]; - uint64_t l = 0; - rc = qmckl_slagel_splitting_c(Dim, 1, Updates_1block, Updates_index_1block, - breakdown, Slater_inv, later_updates + (Dim * later), later_index + later, &l); - later = later + l; - } - - if (later > 0) { - rc = qmckl_sherman_morrison_splitting_c(context, Dim, later, later_updates, later_index, breakdown, Slater_inv); - } - return QMCKL_SUCCESS; -} - - #+end_src - -*** Performance... - - This kernel performs best for the case of two rank-1 update and a low fail-rate. - -** C interface :noexport: - - #+CALL: generate_c_interface(table=qmckl_sherman_morrison_smw2s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - - #+RESULTS: - #+begin_src f90 :tangle (eval f) :comments org :exports none - integer(c_int32_t) function qmckl_sherman_morrison_smw2s & - (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & - bind(C) result(info) - - use, intrinsic :: iso_c_binding - implicit none - - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) , value :: Dim - integer (c_int64_t) , intent(in) , value :: N_updates - real (c_double ) , intent(in) :: Updates(N_updates*Dim) - integer (c_int64_t) , intent(in) :: Updates_index(N_updates) - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) - - integer(c_int32_t), external :: qmckl_sherman_morrison_smw2s_c - info = qmckl_sherman_morrison_smw2s_c & - (context, Dim, N_updates, Updates, Updates_index, Slater_inv) - - end function qmckl_sherman_morrison_smw2s - #+end_src - - #+CALL: generate_f_interface(table=qmckl_sherman_morrison_smw2s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - - #+RESULTS: - #+begin_src f90 :tangle (eval fh_func) :comments org :exports none - interface - integer(c_int32_t) function qmckl_sherman_morrison_smw2s & - (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & - bind(C) - use, intrinsic :: iso_c_binding - import - implicit none - - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) , value :: Dim - integer (c_int64_t) , intent(in) , value :: N_updates - real (c_double ) , intent(in) :: Updates(N_updates*Dim) - integer (c_int64_t) , intent(in) :: Updates_index(N_updates) - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) - - end function qmckl_sherman_morrison_smw2s - end interface - #+end_src - -*** Test :noexport: - - #+begin_src c :tangle (eval c_test) -rc = qmckl_sherman_morrison_smw2s_c(context, Dim, N_updates5, Updates5, Updates_index5, breakdown, Slater_inv5_1); -for (unsigned int i = 0; i < Dim; i++) { - for (unsigned int j = 0; j < Dim; j++) { - res[i * Dim + j] = 0; - for (unsigned int k = 0; k < Dim; k++) { - res[i * Dim + j] += Slater5[i * Dim + k] * Slater_inv5_1[k * Dim + j]; - } - } -} -rc = QMCKL_SUCCESS; -for (unsigned int i = 0; i < Dim; i++) { - for (unsigned int j = 0; j < Dim; j++) { - if (i == j && fabs(res[i * Dim + j] - 1) > tolerance) { - rc = QMCKL_FAILURE; - } - if (i != j && fabs(res[i * Dim + j]) > tolerance) { - rc = QMCKL_FAILURE; - } - } -} -assert(rc == QMCKL_SUCCESS); - #+end_src - - -* Woodbury 3x3 with Sherman-Morrison and update splitting - -** ~qmckl_sherman_morrison_smw3s~ - :PROPERTIES: - :Name: qmckl_sherman_morrison_smw3s - :CRetType: qmckl_exit_code - :FRetType: qmckl_exit_code - :END: - - The Woodbury 3x3 kernel with Sherman-Morrison and update splitting combines the low-level Woodbury 3x3 kernel - and Sherman-Morrison with update splitting. It works the same as Woodbury 2x2 with Sherman-Morrison and update - splitting, except that the updates are divided in blocks of three rank-1 updates instead of blocks of two - rank-1 updates. - - #+NAME: qmckl_sherman_morrison_smw3s_args - | qmckl_context | context | in | Global state | - | uint64_t | Dim | in | Leading dimension of Slater_inv | - | uint64_t | N_updates | in | Number of rank-1 updates to be applied to Slater_inv | - | double | Updates[N_updates*Dim] | in | Array containing the updates | - | uint64_t | Updates_index[N_updates] | in | Array containing the rank-1 updates | - | double | breakdown | in | Break-down parameter on which to fail or not | - | double | Slater_inv[Dim*Dim] | inout | Array containing the inverse of a Slater-matrix | - -*** Requirements - - - ~context~ is not ~QMCKL_NULL_CONTEXT~ - - ~Dim >= 2~ - - ~N_updates >= 1~ - - ~Updates~ is allocated with at least $1 \times 2 \times 8$ bytes - - ~Updates_index~ is allocated with at least $1 \times 8$ bytes - - ~breakdown~ is a small number such that $0 < breakdown << 1$ - - ~Slater_inv~ is allocated with at least $Dim \times Dim \times 8$ bytes - -*** C header - - #+CALL: generate_c_header(table=qmckl_sherman_morrison_smw3s_args,rettyp=get_value("CRetType"),fname=get_value("Name")) - - #+RESULTS: - #+begin_src c :tangle (eval h_func) :comments org - qmckl_exit_code qmckl_sherman_morrison_smw3s_c ( - const qmckl_context context, - const uint64_t Dim, - const uint64_t N_updates, - const double* Updates, - const uint64_t* Updates_index, - const double breakdown, - double* Slater_inv ); - #+end_src - -*** Source Fortran - - #+begin_src f90 :tangle (eval f) -integer function qmckl_sherman_morrison_smw3s_f(context, Slater_inv, Dim, N_updates, & - Updates, Updates_index) result(info) - use qmckl - implicit none - integer(qmckl_context) , intent(in) :: context - integer*8 , intent(in), value :: Dim, N_updates - integer*8 , intent(in) :: Updates_index(N_updates) - real*8 , intent(in) :: Updates(N_updates*Dim) - real*8 , intent(inout) :: Slater_inv(Dim*Dim) - !logical, external :: qmckl_sherman_morrison_f - info = qmckl_sherman_morrison_smw3s(context, Dim, N_updates, Updates, Updates_index, Slater_inv) -end function qmckl_sherman_morrison_smw3s_f - #+end_src - -*** Source C - - #+begin_src c :tangle (eval c) :comments org -#include -#include "qmckl.h" - -qmckl_exit_code qmckl_sherman_morrison_smw3s_c(const qmckl_context context, - const uint64_t Dim, - const uint64_t N_updates, - const double* Updates, - const uint64_t* Updates_index, - const double breakdown, - double * Slater_inv) { -// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. -// std::cerr << "Called qmckl_sherman_morrison_woodbury_3 with " << N_updates -// << " updates" << std::endl; -// #endif - - qmckl_exit_code rc; - - uint64_t n_of_3blocks = N_updates / 3; - uint64_t remainder = N_updates % 3; - uint64_t length_3block = 3 * Dim; - - // Apply first 3*n_of_3blocks updates in n_of_3blocks blocks of 3 updates with - // Woodbury 3x3 kernel - double later_updates[Dim * N_updates]; - uint64_t later_index[N_updates]; - uint64_t later = 0; - if (n_of_3blocks > 0) { - for (uint64_t i = 0; i < n_of_3blocks; i++) { - const double *Updates_3block = &Updates[i * length_3block]; - const uint64_t *Updates_index_3block = &Updates_index[i * 3]; - rc = qmckl_woodbury_3_c(context, Dim, Updates_3block, Updates_index_3block, breakdown, Slater_inv); - if (rc != 0) { // Send the entire block to slagel_splitting - uint64_t l = 0; - rc = qmckl_slagel_splitting_c(Dim, 3, Updates_3block, Updates_index_3block, - breakdown, Slater_inv, later_updates + (Dim * later), later_index + later, &l); - later = later + l; - } - } - } - - if (remainder != 0) { // Apply last remaining block of 2 updates with Woodbury 2x2 kernel - const double *Updates_remainder_block = &Updates[n_of_3blocks * length_3block]; - const uint64_t *Updates_index_remainder_block = &Updates_index[3 * n_of_3blocks]; - uint64_t l = 0; - rc = qmckl_slagel_splitting_c(Dim, remainder, Updates_remainder_block, Updates_index_remainder_block, - breakdown, Slater_inv, later_updates + (Dim * later), later_index + later, &l); - later = later + l; - } - - if (later > 0) { - rc = qmckl_sherman_morrison_splitting_c(context, Dim, later, later_updates, later_index, breakdown, Slater_inv); - } - return QMCKL_SUCCESS; -} - - #+end_src - -*** Performance... - - This kernel performs best for the case of three rank-1 update and a low fail-rate. - - -** C interface :noexport: - - #+CALL: generate_c_interface(table=qmckl_sherman_morrison_smw3s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - - #+RESULTS: - #+begin_src f90 :tangle (eval f) :comments org :exports none - integer(c_int32_t) function qmckl_sherman_morrison_smw3s & - (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & - bind(C) result(info) - - use, intrinsic :: iso_c_binding - implicit none - - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) , value :: Dim - integer (c_int64_t) , intent(in) , value :: N_updates - real (c_double ) , intent(in) :: Updates(N_updates*Dim) - integer (c_int64_t) , intent(in) :: Updates_index(N_updates) - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) - - integer(c_int32_t), external :: qmckl_sherman_morrison_smw3s_c - info = qmckl_sherman_morrison_smw3s_c & - (context, Dim, N_updates, Updates, Updates_index, Slater_inv) - - end function qmckl_sherman_morrison_smw3s - #+end_src - - #+CALL: generate_f_interface(table=qmckl_sherman_morrison_smw3s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - - #+RESULTS: - #+begin_src f90 :tangle (eval fh_func) :comments org :exports none - interface - integer(c_int32_t) function qmckl_sherman_morrison_smw3s & - (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & - bind(C) - use, intrinsic :: iso_c_binding - import - implicit none - - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) , value :: Dim - integer (c_int64_t) , intent(in) , value :: N_updates - real (c_double ) , intent(in) :: Updates(N_updates*Dim) - integer (c_int64_t) , intent(in) :: Updates_index(N_updates) - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) - - end function qmckl_sherman_morrison_smw3s - end interface - #+end_src - -*** Test :noexport: - - #+begin_src c :tangle (eval c_test) -rc = qmckl_sherman_morrison_smw3s_c(context, Dim, N_updates5, Updates5, Updates_index5, breakdown, Slater_inv5_2); -for (unsigned int i = 0; i < Dim; i++) { - for (unsigned int j = 0; j < Dim; j++) { - res[i * Dim + j] = 0; - for (unsigned int k = 0; k < Dim; k++) { - res[i * Dim + j] += Slater5[i * Dim + k] * Slater_inv5_2[k * Dim + j]; - } - } -} -rc = QMCKL_SUCCESS; -for (unsigned int i = 0; i < Dim; i++) { - for (unsigned int j = 0; j < Dim; j++) { - if (i == j && fabs(res[i * Dim + j] - 1) > tolerance) { - rc = QMCKL_FAILURE; - } - if (i != j && fabs(res[i * Dim + j]) > tolerance) { - rc = QMCKL_FAILURE; - } - } -} -assert(rc == QMCKL_SUCCESS); - #+end_src - - * Woodbury 3x3 and 2x2 with Sherman-Morrison and update splitting ** ~qmckl_sherman_morrison_smw32s~ @@ -1398,13 +985,13 @@ assert(rc == QMCKL_SUCCESS); *** Requirements - - ~context~ is not ~QMCKL_NULL_CONTEXT~ - - ~Dim >= 2~ - - ~N_updates >= 1~ - - ~Updates~ is allocated with at least $1 \times 2 \times 8$ bytes - - ~Updates_index~ is allocated with at least $1 \times 8$ bytes - - ~breakdown~ is a small number such that $0 < breakdown << 1$ - - ~Slater_inv~ is allocated with at least $Dim \times Dim \times 8$ bytes + * ~context~ is not ~QMCKL_NULL_CONTEXT~ + * ~Dim >= 2~ + * ~N_updates >= 1~ + * ~Updates~ is allocated with $N_updates \times Dim$ elements + * ~Updates_index~ is allocated with $N_updates$ elements + * ~breakdown~ is a small number such that $0 < breakdown << 1$ + * ~Slater_inv~ is allocated with $Dim \times Dim$ elements *** C header @@ -1593,8 +1180,8 @@ assert(rc == QMCKL_SUCCESS); * Helper Functions -Helper functions that are used by the Sherman-Morrison-Woodbury kernels. -These functions can only be used internally by higher level functions. +Private helper-functions that are used by the Sherman-Morrison-Woodbury kernels. +These functions can only be used internally by the kernels in this module. ** ~qmckl_slagel_splitting~ :PROPERTIES: @@ -1603,13 +1190,14 @@ These functions can only be used internally by higher level functions. :FRetType: double precision :END: - ~qmckl_slagel_splitting~ is used internally to apply a list of rank-1 updates while splitting an update if necessary. - In case of a split it applies the first half of the update while putting the second half in waiting queue to be applied at the end. + ~qmckl_slagel_splitting~ is the non-recursive, inner part of the 'Sherman-Morrison with update splitting'-kernel. + It is used internally to apply a collection of $N$ of rank-1 updates to the inverse Slater-matrix $S^{-1}$ and + splitting an update in two equal pieces if necessary. In case of a split, it applies the first half of the update, + while putting the second half in a waiting queue to be applied at the end. - For a given update $u_j$ we define a threshold value $\epsilon_j$, which is the minimum value of - $1+v_j^TS^{-1}u_j$ for a non-singular matrix $S$. If $1+v_j^TS^{-1}u_j \geq \epsilon_j$, - the update is applied as usual. Otherwise, $u_j$ will be redefined as $\frac{u_j}{2}$, and the other half - (to be applied at the end) will be defined using vectors $\frac{u_{j'}}{2}$ and $v_{j'}^T=v_{j'}^T$. + Therefore, when $1+v_j^TS^{-1}u_j \geq \epsilon$, the update is applied as usual. Otherwise, $u_j$ will be redefined + as $\frac{1}{2}u_j$. One half is applied immediately, the other half will be applied at the end of the algorithm, using vectors + $u_{j'}=\frac{1}{2}u_j$ and $v_{j'}^T=v_{j}^T$, which are stored in the array \texttt{later_updates}. #+NAME: qmckl_slagel_splitting_args | uint64_t | Dim | in | Leading dimension of Slater_inv | @@ -1627,12 +1215,12 @@ These functions can only be used internally by higher level functions. - ~Dim >= 2~ - ~N_updates >= 1~ - - ~Updates~ is allocated with at least $1 \times 2 \times 8$ bytes - - ~Updates_index~ is allocated with at least $1 \times 8$ bytes + - ~Updates~ is allocated with $N_updates \times Dim$ elements + - ~Updates_index~ is allocated with $N_updates$ elements - ~breakdown~ is a small number such that $0 < breakdown << 1$ - - ~Slater_inv~ is allocated with at least $Dim \times Dim \times 8$ bytes - - ~later_updates~ is allocated with at least $1 \times 2 \times 8$ bytes - - ~later_index~ is allocated with at least $1 \times 8$ bytes + - ~Slater_inv~ is allocated with $Dim \times Dim$ elements + - ~later_updates~ is allocated with $later \times Dim$ elements + - ~later_index~ is allocated with $N_updates$ elements - ~later >= 0~ *** C header From 37d5ff61ff7e50ffa052f4f19bbc48b437ea3ca7 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Tue, 7 Sep 2021 12:22:39 +0200 Subject: [PATCH 40/50] - Updated Perfomance recommendations, did some rewriting of parts of the text and removed more typos. --- org/qmckl_sherman_morrison_woodbury.org | 43 ++++++++++++++----------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 6bd083b..8ce4822 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -2,7 +2,7 @@ #+SETUPFILE: ../tools/theme.setup #+INCLUDE: ../tools/lib.org -Low- and high-level functions that use the Sherman-Morrison and + Low- and high-level functions that use the Sherman-Morrison and Woodbury matrix inversion formulas to update the inverse of a non-singular matrix @@ -59,8 +59,8 @@ int main() { This value sets the lower bound for which the denominator $1+v_j^TS^{-1}u_j$ is considered to be too small and will most probably result in a singular matrix $S$, or at least in an inverse of $S$ of very poor numerical quality. Therefore, when $1+v_j^TS^{-1}u_j \geq \epsilon$, - the update is applied as usual. If $1+v_j^TS^{-1}u_j \leq \epsilon$ the update is rejected and the kernel exits with - return code \texttt{QMCKL_FAILURE}. + the update is applied as usual and the kernel exits with return code \texttt{QMCKL_SUCCESS}. + If $1+v_j^TS^{-1}u_j \leq \epsilon$ the update is rejected and the kernel exits with return code \texttt{QMCKL_FAILURE}. #+NAME: qmckl_sherman_morrison_args | qmckl_context | context | in | Global state | @@ -176,8 +176,9 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, *** Performance - This function performs better when there is only 1 rank-1 update in the update cycle and the fail-rate of rank-1 updates is high. - + This function performs best when there is only 1 rank-1 update in the update cycle. It is not useful to + use Sherman-Morrison with update splitting for these cycles since splitting can never resolve a situation + where applying the update causes singular behaviour. ** C interface :noexport: @@ -449,7 +450,8 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, *** Performance - This function is most efficient when used in cases where there are only 2 rank-1 updates. + This function is most efficient when used in cases where there are only 2 rank-1 updates and + it is sure they will not result in a singular matrix. ** C interface :noexport: @@ -689,8 +691,8 @@ qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, *** Performance... - This function is most efficient when used in cases where there are only 3 rank-1 updates. - + This function is most efficient when used in cases where there are only 3 rank-1 updates and + it is sure they will not result in a singular matrix. ** C interface :noexport: @@ -780,11 +782,13 @@ assert(rc == QMCKL_SUCCESS); This is a variation on the 'Naive' Sherman-Morrison kernel. Whenever the denominator $1+v_j^T S^{-1} u_j$ in the Sherman-Morrison formula is deemed to be too close to zero, the update $u_j$ is split in half: - $u_j \rightarrow \frac{1}{1} u_j$. One half is applied immediately --necessarily increasing the value of the + $u_j \rightarrow \frac{1}{2} u_j$. One half is applied immediately --necessarily increasing the value of the denominator because of the split-- while the other halve is put in a queue that will be applied when all the - remaining updates have been treated. The kernel is executed recursively until the queue is eiter empty and all + remaining updates have been treated. + + The kernel is executed recursively until the queue is eiter empty and all updates are applied successfully, or the size of the queue equals the number of initial updates. In the last - case the Slater-matrix that would have resulted from applying the updates is un-invertable and therefore the + case the Slater-matrix that would have resulted from applying the updates is singular and therefore the kernel exits with an exit code. #+NAME: qmckl_sherman_morrison_splitting_args @@ -877,7 +881,7 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, *** Performance... - This kernel performs best when there are only 1 rank-1 update cycles and/or when the fail-rate is high. + This kernel performs best when there are 2 or more rank-1 update cycles and fail-rate is high. ** C interface :noexport: @@ -1099,7 +1103,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, *** Performance... - This kernel performs best when the number of rank-1 updates is larger than 3 and fail-rates are low. + This kernel performs best for update cycles with 2 or more rank-1 updates and the fail-rate is low. ** C interface :noexport: @@ -1176,7 +1180,7 @@ for (unsigned int i = 0; i < Dim; i++) { } assert(rc == QMCKL_SUCCESS); #+end_src - + * Helper Functions @@ -1191,7 +1195,7 @@ These functions can only be used internally by the kernels in this module. :END: ~qmckl_slagel_splitting~ is the non-recursive, inner part of the 'Sherman-Morrison with update splitting'-kernel. - It is used internally to apply a collection of $N$ of rank-1 updates to the inverse Slater-matrix $S^{-1}$ and + It is used internally to apply a collection of $N$ rank-1 updates to the inverse Slater-matrix $S^{-1}$ and splitting an update in two equal pieces if necessary. In case of a split, it applies the first half of the update, while putting the second half in a waiting queue to be applied at the end. @@ -1279,9 +1283,9 @@ qmckl_exit_code qmckl_slagel_splitting_c(uint64_t Dim, // Denominator double den = 1 + C[Updates_index[l] - 1]; - if (fabs(den) < breakdown) { + if (fabs(den) < breakdown) { // Here is decided to split the update, or not. - // U_l = U_l / 2 (do the split) + // U_l = U_l / 2: split the update in 2 equal halves and save the second halve in later_updates for (uint64_t i = 0; i < Dim; i++) { later_updates[*later * Dim + i] = Updates[l * Dim + i] / 2.0; C[i] /= 2.0; @@ -1290,7 +1294,7 @@ qmckl_exit_code qmckl_slagel_splitting_c(uint64_t Dim, (*later)++; den = 1 + C[Updates_index[l] - 1]; - } + } // From here onwards we continue with applying the first havel of the update to Slater_inv double iden = 1 / den; // D = v^T x S^{-1} @@ -1315,7 +1319,8 @@ qmckl_exit_code qmckl_slagel_splitting_c(uint64_t Dim, *** Performance -This function performce better for cycles with 1 rank-1 update and with a high fail-rate. +This function cannot be used by itself and is used in Sherman-Morrison with update splitting and Woodbury 3x3 and 2x2 +with Sherman-Morrison and update splitting. Please look at the performance reccomendations for those two kernels. ** C interface :noexport: From 6cc5b1abee226751cb7a5a95b77787fa32f30bfb Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Wed, 8 Sep 2021 16:46:01 +0200 Subject: [PATCH 41/50] Commented out compiler option that is most probably not needed. --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 7ec6322..e71a78e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -58,7 +58,7 @@ fortrandir = $(datadir)/$(PACKAGE_NAME)/fortran/ dist_fortran_DATA = $(qmckl_f) AM_CPPFLAGS = -I$(srcdir)/src -I$(srcdir)/include -AM_FCFLAGS = -fno-underscoring +# AM_FCFLAGS = -fno-underscoring lib_LTLIBRARIES = src/libqmckl.la src_libqmckl_la_SOURCES = $(qmckl_h) $(src_qmckl_f) $(C_FILES) $(F_FILES) $(H_PRIVATE_FUNC_FILES) $(H_PRIVATE_TYPE_FILES) $(header_tests) From 36f930b8f7016fbc2328c247ae9b912d9b45e8bb Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Fri, 10 Sep 2021 17:25:56 +0200 Subject: [PATCH 42/50] - Removed AM_FCFLAGS = -fno-underscoring from Makefile.am again. - Removed all Fortran code from the org/qmckl_sherman_morrison_woodbury.org file to prevent the appearance of *_ symbol names in libqmckl.so due to the use of Fortran compiler. - Removed all compiler warings due to imlpicit call to fabs() by including math.h - Removed all the cppcheck warnings of unsused variables by casting return-value function calls to void when the return value is not used. #25 --- Makefile.am | 1 - org/qmckl_sherman_morrison_woodbury.org | 388 ++---------------------- 2 files changed, 18 insertions(+), 371 deletions(-) diff --git a/Makefile.am b/Makefile.am index e71a78e..ca045b9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -58,7 +58,6 @@ fortrandir = $(datadir)/$(PACKAGE_NAME)/fortran/ dist_fortran_DATA = $(qmckl_f) AM_CPPFLAGS = -I$(srcdir)/src -I$(srcdir)/include -# AM_FCFLAGS = -fno-underscoring lib_LTLIBRARIES = src/libqmckl.la src_libqmckl_la_SOURCES = $(qmckl_h) $(src_qmckl_f) $(C_FILES) $(F_FILES) $(H_PRIVATE_FUNC_FILES) $(H_PRIVATE_TYPE_FILES) $(header_tests) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 8ce4822..dc573fd 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -25,8 +25,7 @@ int main() { qmckl_exit_code rc; #+end_src - - + * Naïve Sherman-Morrison ** ~qmckl_sherman_morrison~ @@ -36,7 +35,6 @@ int main() { :FRetType: qmckl_exit_code :END: - This is the simplest of the available Sherman-Morrison-Woodbury kernels. It applies rank-1 updates one by one in the order that is given. It only checks if the denominator in the Sherman-Morrison formula is not too close to zero when an update is evaluated. It will exit with an error code of the denominator is too close to zero. @@ -97,28 +95,11 @@ int main() { double* Slater_inv ); #+end_src -*** Source Fortran - - #+begin_src f90 :tangle (eval f) -integer function qmckl_sherman_morrison_f(context, Dim, N_updates, & - Updates, Updates_index, breakdown, Slater_inv) result(info) - use qmckl - implicit none - integer(qmckl_context) , intent(in) :: context - integer*8 , intent(in), value :: Dim, N_updates - integer*8 , intent(in) :: Updates_index(N_updates) - real*8 , intent(in) :: Updates(N_updates*Dim) - real*8 , intent(in) :: breakdown - real*8 , intent(inout) :: Slater_inv(Dim*Dim) - !logical, external :: qmckl_sherman_morrison_f - info = qmckl_sherman_morrison(context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) -end function qmckl_sherman_morrison_f - #+end_src - -*** Source C +*** Source #+begin_src c :tangle (eval c) :comments org #include +#include #include "qmckl.h" qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, @@ -171,7 +152,6 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, return QMCKL_SUCCESS; } - #+end_src *** Performance @@ -184,54 +164,8 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, #+CALL: generate_c_interface(table=qmckl_sherman_morrison_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - #+RESULTS: - #+begin_src f90 :tangle (eval f) :comments org :exports none - integer(c_int32_t) function qmckl_sherman_morrison & - (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) & - bind(C) result(info) - - use, intrinsic :: iso_c_binding - implicit none - - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) , value :: Dim - integer (c_int64_t) , intent(in) , value :: N_updates - real (c_double ) , intent(in) :: Updates(N_updates*Dim) - integer (c_int64_t) , intent(in) :: Updates_index(N_updates) - real (c_double ) , intent(in) :: breakdown - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) - - integer(c_int32_t), external :: qmckl_sherman_morrison_c - info = qmckl_sherman_morrison_c & - (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) - - end function qmckl_sherman_morrison - #+end_src - #+CALL: generate_f_interface(table=qmckl_sherman_morrison_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - #+RESULTS: - #+begin_src f90 :tangle (eval fh_func) :comments org :exports none - interface - integer(c_int32_t) function qmckl_sherman_morrison & - (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) & - bind(C) - use, intrinsic :: iso_c_binding - import - implicit none - - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) , value :: Dim - integer (c_int64_t) , intent(in) , value :: N_updates - real (c_double ) , intent(in) :: Updates(N_updates*Dim) - integer (c_int64_t) , intent(in) :: Updates_index(N_updates) - real (c_double ) , intent(in) :: breakdown - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) - - end function qmckl_sherman_morrison - end interface - #+end_src - *** Test :noexport: The tests for the kernels are executed on datasets that are extracted from a run of QMC=Chem on Benzene (21 spin-up/21 spin down electrons) using 329 unique alpha determinants. The tests are run such that the kernels reject the computed inverse whenever the computed intermediate determinants or denominators are smaller than 1e-3. This is the default value in QMC=Chem. The tests will return QMCKL_SUCCESS whenever all the elements of the final matrix $R=S.S^-1 - 1$ are smaller than the given tolerance value of 1e-3, and will return QMCKL_FAILURE if the values are larger than this tolerance value. @@ -297,7 +231,6 @@ for (unsigned int i = 0; i < Dim; i++) { assert(rc == QMCKL_SUCCESS); #+end_src - * Woodbury 2x2 ** ~qmckl_woodbury_2~ @@ -353,28 +286,11 @@ assert(rc == QMCKL_SUCCESS); double* Slater_inv ); #+end_src -*** Source Fortran - - #+begin_src f90 :tangle (eval f) -integer function qmckl_woodbury_2_f(context, Dim, & - Updates, Updates_index, breakdown, Slater_inv) result(info) - use qmckl - implicit none - integer(qmckl_context) , intent(in) :: context - integer*8 , intent(in), value :: Dim - integer*8 , intent(in) :: Updates_index(2) - real*8 , intent(in) :: Updates(2*Dim) - real*8 , intent(in) :: breakdown - real*8 , intent(inout) :: Slater_inv(Dim*Dim) - !logical, external :: qmckl_woodbury_2_f - info = qmckl_woodbury_2(context, Dim, Updates, Updates_index, breakdown, Slater_inv) -end function qmckl_woodbury_2_f - #+end_src - -*** Source C +*** Source #+begin_src c :tangle (eval c) :comments org #include +#include #include "qmckl.h" qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, @@ -387,7 +303,7 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, C := S^{-1} * U, dim x 2 B := 1 + V * C, 2 x 2 D := V * S^{-1}, 2 x dim -*/ +,*/ // #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. // std::cerr << "Called Woodbury 2x2 kernel" << std::endl; // #endif @@ -445,64 +361,19 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, return QMCKL_SUCCESS; } - #+end_src *** Performance This function is most efficient when used in cases where there are only 2 rank-1 updates and it is sure they will not result in a singular matrix. - + ** C interface :noexport: #+CALL: generate_c_interface(table=qmckl_woodbury_2_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - #+RESULTS: - #+begin_src f90 :tangle (eval f) :comments org :exports none - integer(c_int32_t) function qmckl_woodbury_2 & - (context, Dim, Updates, Updates_index, breakdown, Slater_inv) & - bind(C) result(info) - - use, intrinsic :: iso_c_binding - implicit none - - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) , value :: Dim - real (c_double ) , intent(in) :: Updates(2*Dim) - integer (c_int64_t) , intent(in) :: Updates_index(2) - real (c_double ) , intent(in) :: breakdown - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) - - integer(c_int32_t), external :: qmckl_woodbury_2_c - info = qmckl_woodbury_2_c & - (context, Dim, Updates, Updates_index, breakdown, Slater_inv) - - end function qmckl_woodbury_2 - #+end_src - #+CALL: generate_f_interface(table=qmckl_woodbury_2_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - #+RESULTS: - #+begin_src f90 :tangle (eval fh_func) :comments org :exports none - interface - integer(c_int32_t) function qmckl_woodbury_2 & - (context, Dim, Updates, Updates_index, breakdown, Slater_inv) & - bind(C) - use, intrinsic :: iso_c_binding - import - implicit none - - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) , value :: Dim - real (c_double ) , intent(in) :: Updates(2*Dim) - integer (c_int64_t) , intent(in) :: Updates_index(2) - real (c_double ) , intent(in) :: breakdown - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) - - end function qmckl_woodbury_2 - end interface - #+end_src - *** Test :noexport: #+begin_src c :tangle (eval c_test) @@ -529,7 +400,6 @@ for (unsigned int i = 0; i < Dim; i++) { assert(rc == QMCKL_SUCCESS); #+end_src - * Woodbury 3x3 ** ~qmckl_woodbury_3~ @@ -579,28 +449,11 @@ assert(rc == QMCKL_SUCCESS); double* Slater_inv ); #+end_src -*** Source Fortran - - #+begin_src f90 :tangle (eval f) -integer function qmckl_woodbury_3_f(context, Dim, & - Updates, Updates_index, breakdown, Slater_inv) result(info) - use qmckl - implicit none - integer(qmckl_context) , intent(in) :: context - integer*8 , intent(in), value :: Dim - integer*8 , intent(in) :: Updates_index(3) - real*8 , intent(in) :: Updates(3*Dim) - real*8 , intent(in) :: breakdown - real*8 , intent(inout) :: Slater_inv(Dim*Dim) - !logical, external :: qmckl_woodbury_3_f - info = qmckl_woodbury_3(context, Dim, Updates, Updates_index, breakdown, Slater_inv) -end function qmckl_woodbury_3_f - #+end_src - -*** Source C +*** Source #+begin_src c :tangle (eval c) :comments org #include +#include #include "qmckl.h" qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, @@ -698,52 +551,8 @@ qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, #+CALL: generate_c_interface(table=qmckl_woodbury_3_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - #+RESULTS: - #+begin_src f90 :tangle (eval f) :comments org :exports none - integer(c_int32_t) function qmckl_woodbury_3 & - (context, Dim, Updates, Updates_index, breakdown, Slater_inv) & - bind(C) result(info) - - use, intrinsic :: iso_c_binding - implicit none - - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) , value :: Dim - real (c_double ) , intent(in) :: Updates(3*Dim) - integer (c_int64_t) , intent(in) :: Updates_index(3) - real (c_double ) , intent(in) , value :: breakdown - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) - - integer(c_int32_t), external :: qmckl_woodbury_3_c - info = qmckl_woodbury_3_c & - (context, Dim, Updates, Updates_index, breakdown, Slater_inv) - - end function qmckl_woodbury_3 - #+end_src - #+CALL: generate_f_interface(table=qmckl_woodbury_3_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - #+RESULTS: - #+begin_src f90 :tangle (eval fh_func) :comments org :exports none - interface - integer(c_int32_t) function qmckl_woodbury_3 & - (context, Dim, Updates, Updates_index, breakdown, Slater_inv) & - bind(C) - use, intrinsic :: iso_c_binding - import - implicit none - - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) , value :: Dim - real (c_double ) , intent(in) :: Updates(3*Dim) - integer (c_int64_t) , intent(in) :: Updates_index(3) - real (c_double ) , intent(in) , value :: breakdown - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) - - end function qmckl_woodbury_3 - end interface - #+end_src - *** Test :noexport: #+begin_src c :tangle (eval c_test) @@ -770,7 +579,6 @@ for (unsigned int i = 0; i < Dim; i++) { assert(rc == QMCKL_SUCCESS); #+end_src - * Sherman-Morrison with update splitting ** ~qmckl_sherman_morrison_splitting~ @@ -826,24 +634,7 @@ assert(rc == QMCKL_SUCCESS); double* Slater_inv ); #+end_src -*** Source Fortran - - #+begin_src f90 :tangle (eval f) -integer function qmckl_sherman_morrison_splitting_f(context, Dim, N_updates, & - Updates, Updates_index, breakdown, Slater_inv) result(info) - use qmckl - implicit none - integer(qmckl_context) , intent(in) :: context - integer*8 , intent(in), value :: Dim, N_updates - integer*8 , intent(in) :: Updates_index(N_updates) - real*8 , intent(in) :: Updates(N_updates*Dim) - real*8 , intent(in) :: breakdown - real*8 , intent(inout) :: Slater_inv(Dim*Dim) - info = qmckl_sherman_morrison_splitting(context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) -end function qmckl_sherman_morrison_splitting_f - #+end_src - -*** Source C +*** Source #+begin_src c :tangle (eval c) :comments org #include @@ -860,17 +651,15 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, // std::cerr << "Called qmckl_sherman_morrison_splitting with " << N_updates << " updates" << std::endl; // #endif - qmckl_exit_code rc; - double later_updates[Dim * N_updates]; uint64_t later_index[N_updates]; uint64_t later = 0; - rc = qmckl_slagel_splitting_c(Dim, N_updates, Updates, Updates_index, + (void) qmckl_slagel_splitting_c(Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv, later_updates, later_index, &later); if (later > 0) { - rc = qmckl_sherman_morrison_splitting_c(context, Dim, later, + (void) qmckl_sherman_morrison_splitting_c(context, Dim, later, later_updates, later_index, breakdown, Slater_inv); } @@ -887,55 +676,8 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, #+CALL: generate_c_interface(table=qmckl_sherman_morrison_splitting_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - #+RESULTS: - #+begin_src f90 :tangle (eval f) :comments org :exports none - integer(c_int32_t) function qmckl_sherman_morrison_splitting & - (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) & - bind(C) result(info) - - use, intrinsic :: iso_c_binding - implicit none - - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) , value :: Dim - integer (c_int64_t) , intent(in) , value :: N_updates - real (c_double ) , intent(in) :: Updates(N_updates*Dim) - integer (c_int64_t) , intent(in) :: Updates_index(N_updates) - real (c_double ) , intent(in) , value :: breakdown - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) - - integer(c_int32_t), external :: qmckl_sherman_morrison_splitting_c - info = qmckl_sherman_morrison_splitting_c & - (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) - - end function qmckl_sherman_morrison_splitting - #+end_src - #+CALL: generate_f_interface(table=qmckl_sherman_morrison_splitting_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - #+RESULTS: - #+begin_src f90 :tangle (eval fh_func) :comments org :exports none - interface - integer(c_int32_t) function qmckl_sherman_morrison_splitting & - (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) & - bind(C) - use, intrinsic :: iso_c_binding - import - implicit none - - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) , value :: Dim - integer (c_int64_t) , intent(in) , value :: N_updates - real (c_double ) , intent(in) :: Updates(N_updates*Dim) - integer (c_int64_t) , intent(in) :: Updates_index(N_updates) - real (c_double ) , intent(in) , value :: breakdown - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) - - end function qmckl_sherman_morrison_splitting - end interface - #+end_src - - *** Test :noexport: #+begin_src c :tangle (eval c_test) @@ -962,7 +704,6 @@ for (unsigned int i = 0; i < Dim; i++) { assert(rc == QMCKL_SUCCESS); #+end_src - * Woodbury 3x3 and 2x2 with Sherman-Morrison and update splitting ** ~qmckl_sherman_morrison_smw32s~ @@ -1013,24 +754,7 @@ assert(rc == QMCKL_SUCCESS); double* Slater_inv ); #+end_src -*** Source Fortran - - #+begin_src f90 :tangle (eval f) -integer function qmckl_sherman_morrison_smw32s_f(context, Slater_inv, Dim, N_updates, & - Updates, Updates_index) result(info) - use qmckl - implicit none - integer(qmckl_context) , intent(in) :: context - integer*8 , intent(in), value :: Dim, N_updates - integer*8 , intent(in) :: Updates_index(N_updates) - real*8 , intent(in) :: Updates(N_updates*Dim) - real*8 , intent(inout) :: Slater_inv(Dim*Dim) - !logical, external :: qmckl_sherman_morrison_f - info = qmckl_sherman_morrison_smw32s(context, Dim, N_updates, Updates, Updates_index, Slater_inv) -end function qmckl_sherman_morrison_smw32s_f - #+end_src - -*** Source C +*** Source #+begin_src c :tangle (eval c) :comments org #include @@ -1079,7 +803,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, rc = qmckl_woodbury_2_c(context, Dim, Updates_2block, Updates_index_2block, breakdown, Slater_inv); if (rc != 0) { // Send the entire block to slagel_splitting uint64_t l = 0; - rc = qmckl_slagel_splitting_c(Dim, 2, Updates_2block, Updates_index_2block, + (void) qmckl_slagel_splitting_c(Dim, 2, Updates_2block, Updates_index_2block, breakdown, Slater_inv, later_updates + (Dim * later), later_index + later, &l); later = later + l; } @@ -1088,13 +812,13 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, const double *Updates_1block = &Updates[n_of_3blocks * length_3block]; const uint64_t *Updates_index_1block = &Updates_index[3 * n_of_3blocks]; uint64_t l = 0; - rc = qmckl_slagel_splitting_c(Dim, 1, Updates_1block, Updates_index_1block, + (void) qmckl_slagel_splitting_c(Dim, 1, Updates_1block, Updates_index_1block, breakdown, Slater_inv, later_updates + (Dim * later), later_index + later, &l); later = later + l; } if (later > 0) { - rc = qmckl_sherman_morrison_splitting_c(context, Dim, later, later_updates, later_index, breakdown, Slater_inv); + (void) qmckl_sherman_morrison_splitting_c(context, Dim, later, later_updates, later_index, breakdown, Slater_inv); } return QMCKL_SUCCESS; } @@ -1109,52 +833,8 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, #+CALL: generate_c_interface(table=qmckl_sherman_morrison_smw32s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - #+RESULTS: - #+begin_src f90 :tangle (eval f) :comments org :exports none - integer(c_int32_t) function qmckl_sherman_morrison_smw32s & - (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & - bind(C) result(info) - - use, intrinsic :: iso_c_binding - implicit none - - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) , value :: Dim - integer (c_int64_t) , intent(in) , value :: N_updates - real (c_double ) , intent(in) :: Updates(N_updates*Dim) - integer (c_int64_t) , intent(in) :: Updates_index(N_updates) - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) - - integer(c_int32_t), external :: qmckl_sherman_morrison_smw32s_c - info = qmckl_sherman_morrison_smw32s_c & - (context, Dim, N_updates, Updates, Updates_index, Slater_inv) - - end function qmckl_sherman_morrison_smw32s - #+end_src - #+CALL: generate_f_interface(table=qmckl_sherman_morrison_smw32s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - #+RESULTS: - #+begin_src f90 :tangle (eval fh_func) :comments org :exports none - interface - integer(c_int32_t) function qmckl_sherman_morrison_smw32s & - (context, Dim, N_updates, Updates, Updates_index, Slater_inv) & - bind(C) - use, intrinsic :: iso_c_binding - import - implicit none - - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) , value :: Dim - integer (c_int64_t) , intent(in) , value :: N_updates - real (c_double ) , intent(in) :: Updates(N_updates*Dim) - integer (c_int64_t) , intent(in) :: Updates_index(N_updates) - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) - - end function qmckl_sherman_morrison_smw32s - end interface - #+end_src - *** Test :noexport: #+begin_src c :tangle (eval c_test) @@ -1181,7 +861,6 @@ for (unsigned int i = 0; i < Dim; i++) { assert(rc == QMCKL_SUCCESS); #+end_src - * Helper Functions Private helper-functions that are used by the Sherman-Morrison-Woodbury kernels. @@ -1245,9 +924,7 @@ These functions can only be used internally by the kernels in this module. uint64_t* later ); #+end_src -*** Source Fortran - -*** Source C +*** Source #+begin_src c :tangle (eval c) :comments org #include @@ -1322,42 +999,14 @@ qmckl_exit_code qmckl_slagel_splitting_c(uint64_t Dim, This function cannot be used by itself and is used in Sherman-Morrison with update splitting and Woodbury 3x3 and 2x2 with Sherman-Morrison and update splitting. Please look at the performance reccomendations for those two kernels. - ** C interface :noexport: #+CALL: generate_c_interface(table=qmckl_slagel_splitting_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - - #+RESULTS: - #+begin_src f90 :tangle (eval f) :comments org :exports none - integer(c_int32_t) function qmckl_slagel_splitting & - (Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv, later_updates, later_index, later) & - bind(C) result(info) - - use, intrinsic :: iso_c_binding - implicit none - - integer (c_int64_t) , intent(in) , value :: Dim - integer (c_int64_t) , intent(in) , value :: N_updates - real (c_double ) , intent(in) :: Updates(N_updates*Dim) - integer (c_int64_t) , intent(in) :: Updates_index(N_updates) - real (c_double ) , intent(in) , value :: breakdown - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) - real (c_double ) , intent(inout) :: later_updates(Dim * N_updates) - integer (c_int64_t) , intent(inout) :: later_index(N_updates) - integer (c_int64_t) , intent(inout) :: later - - integer(c_int32_t), external :: qmckl_slagel_splitting_c - info = qmckl_slagel_splitting_c & - (Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv, later_updates, later_index, later) - - end function qmckl_slagel_splitting - #+end_src - + *** Test :noexport: This kernel does not have an explicit test because it is only used internally by higher-level Sherman-Morrison-Woodbury kernels. - * End of files #+begin_src c :comments link :tangle (eval c_test) @@ -1367,6 +1016,5 @@ with Sherman-Morrison and update splitting. Please look at the performance recco #+end_src - # -*- mode: org -*- # vim: syntax=c From ec9d5d23a29a907957513f08d2716734729a1555 Mon Sep 17 00:00:00 2001 From: v1j4y Date: Tue, 14 Sep 2021 09:56:31 +0200 Subject: [PATCH 43/50] Bug fix for get_value lisp function. --- tools/lib.org | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/lib.org b/tools/lib.org index 5cb1802..b7c6fc5 100644 --- a/tools/lib.org +++ b/tools/lib.org @@ -11,8 +11,8 @@ ** Function to get the value of a property. #+NAME: get_value #+begin_src elisp :var key="Type" -(setq x (org-property-values key)) -(pop x) +(org-with-point-at org-babel-current-src-block-location + (org-entry-get nil key t)) #+end_src #+RESULTS: get_value From eeaee39acd177b2810840f6390f2f9198fefec9b Mon Sep 17 00:00:00 2001 From: v1j4y Date: Tue, 14 Sep 2021 12:05:10 +0200 Subject: [PATCH 44/50] Removed RETURN blocks from lib to avoid dead code. --- tools/lib.org | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/tools/lib.org b/tools/lib.org index b7c6fc5..3ec8505 100644 --- a/tools/lib.org +++ b/tools/lib.org @@ -15,7 +15,6 @@ (org-entry-get nil key t)) #+end_src - #+RESULTS: get_value ** Table of function arguments @@ -188,23 +187,6 @@ results='\n'.join(results) return results #+END_SRC - #+RESULTS: generate_c_interface - #+begin_src f90 :tangle (eval f) :comments org :exports none - integer(c_int32_t) function [] & - () & - bind(C) result(info) - - use, intrinsic :: iso_c_binding - implicit none - - - integer(c_int32_t), external :: []_f - info = []_f & - () - - end function [] - #+end_src - *** Generates a Fortran interface to the C function #+NAME: generate_f_interface @@ -256,8 +238,5 @@ results='\n'.join(results) return results #+END_SRC - #+RESULTS: generate_f_interface - #+begin_src f90 :tangle (eval fh_func) :comments org :exports none - #+end_src From 65a9b79b7cfae7bc238fe2e3a46e3edf103ea150 Mon Sep 17 00:00:00 2001 From: v1j4y Date: Tue, 14 Sep 2021 12:13:17 +0200 Subject: [PATCH 45/50] Added Properties for interface auto generation. --- org/qmckl_sherman_morrison_woodbury.org | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index dc573fd..b982d50 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -161,6 +161,11 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, where applying the update causes singular behaviour. ** C interface :noexport: + :PROPERTIES: + :Name: qmckl_sherman_morrison + :CRetType: qmckl_exit_code + :FRetType: qmckl_exit_code + :END: #+CALL: generate_c_interface(table=qmckl_sherman_morrison_args,rettyp=get_value("FRetType"),fname=get_value("Name")) @@ -369,6 +374,11 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, it is sure they will not result in a singular matrix. ** C interface :noexport: + :PROPERTIES: + :Name: qmckl_woodbury_2 + :CRetType: qmckl_exit_code + :FRetType: qmckl_exit_code + :END: #+CALL: generate_c_interface(table=qmckl_woodbury_2_args,rettyp=get_value("FRetType"),fname=get_value("Name")) @@ -548,6 +558,11 @@ qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, it is sure they will not result in a singular matrix. ** C interface :noexport: + :PROPERTIES: + :Name: qmckl_woodbury_3 + :CRetType: qmckl_exit_code + :FRetType: qmckl_exit_code + :END: #+CALL: generate_c_interface(table=qmckl_woodbury_3_args,rettyp=get_value("FRetType"),fname=get_value("Name")) @@ -673,6 +688,11 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, This kernel performs best when there are 2 or more rank-1 update cycles and fail-rate is high. ** C interface :noexport: + :PROPERTIES: + :Name: qmckl_sherman_morrison_splitting + :CRetType: qmckl_exit_code + :FRetType: qmckl_exit_code + :END: #+CALL: generate_c_interface(table=qmckl_sherman_morrison_splitting_args,rettyp=get_value("FRetType"),fname=get_value("Name")) @@ -830,6 +850,11 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, This kernel performs best for update cycles with 2 or more rank-1 updates and the fail-rate is low. ** C interface :noexport: + :PROPERTIES: + :Name: qmckl_sherman_morrison_smw32s + :CRetType: qmckl_exit_code + :FRetType: qmckl_exit_code + :END: #+CALL: generate_c_interface(table=qmckl_sherman_morrison_smw32s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) @@ -1000,6 +1025,11 @@ This function cannot be used by itself and is used in Sherman-Morrison with upda with Sherman-Morrison and update splitting. Please look at the performance reccomendations for those two kernels. ** C interface :noexport: + :PROPERTIES: + :Name: qmckl_slagel_splitting + :CRetType: double + :FRetType: double precision + :END: #+CALL: generate_c_interface(table=qmckl_slagel_splitting_args,rettyp=get_value("FRetType"),fname=get_value("Name")) From 37a408c9dd065a6dd3c189b42b4355b69e026481 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Tue, 14 Sep 2021 09:55:55 +0200 Subject: [PATCH 46/50] Add fortran interface --- org/qmckl_sherman_morrison_woodbury.org | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index b982d50..11369e1 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -1,6 +1,7 @@ #+TITLE: Sherman-Morrison-Woodbury #+SETUPFILE: ../tools/theme.setup #+INCLUDE: ../tools/lib.org +#+STARTUP: content Low- and high-level functions that use the Sherman-Morrison and Woodbury matrix inversion formulas to update the inverse of a @@ -95,7 +96,26 @@ int main() { double* Slater_inv ); #+end_src -*** Source +*** Fortran source + + #+begin_src c :tangle (eval c) :comments org +integer function qmckl_sherman_morrison_f(context, Dim, N_updates, Updates, & + Updates_index, breakdown, Slater_inv) result(info) + use qmckl + implicit none + integer(qmckl_context) , intent(in) :: context + integer*8 , intent(in) :: Dim, N_updates + integer*8 , intent(in) :: Updates_index(N_updates) + real*8 , intent(in) :: breakdown + real*8 , intent(in) :: Updates(N_updates*Dim) + real*8 , intent(inout) :: Slater_inv(Dim*Dim) + info = qmckl_sherman_morrison(context, Dim, N_updates, Updates, & + Updates_index, breakdown, Slater_inv) + ) +end function qmckl_sherman_morrison_f + #+end_src + +*** C source #+begin_src c :tangle (eval c) :comments org #include @@ -168,6 +188,8 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, :END: #+CALL: generate_c_interface(table=qmckl_sherman_morrison_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + + #+RESULTS: #+CALL: generate_f_interface(table=qmckl_sherman_morrison_args,rettyp=get_value("FRetType"),fname=get_value("Name")) From 51bddd08641b93dee1e68d17848f8dc2fa7daf26 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Wed, 15 Sep 2021 10:52:00 +0200 Subject: [PATCH 47/50] - Added Fortran- and C-interface blocks in Naive Sherman Morrison section. - Changed the name qmckl_sherman_morrison_c to qmckl_sherman_morrison_c_ to compensate for added '_' by Fortran compiler. --- org/qmckl_sherman_morrison_woodbury.org | 76 +++++++++++++++++-------- 1 file changed, 51 insertions(+), 25 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 11369e1..3c8544e 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -86,35 +86,16 @@ int main() { #+RESULTS: #+begin_src c :tangle (eval h_func) :comments org - qmckl_exit_code qmckl_sherman_morrison_c ( + qmckl_exit_code qmckl_sherman_morrison ( const qmckl_context context, const uint64_t Dim, const uint64_t N_updates, const double* Updates, const uint64_t* Updates_index, - const double breakdown, + const double breakdown, double* Slater_inv ); #+end_src -*** Fortran source - - #+begin_src c :tangle (eval c) :comments org -integer function qmckl_sherman_morrison_f(context, Dim, N_updates, Updates, & - Updates_index, breakdown, Slater_inv) result(info) - use qmckl - implicit none - integer(qmckl_context) , intent(in) :: context - integer*8 , intent(in) :: Dim, N_updates - integer*8 , intent(in) :: Updates_index(N_updates) - real*8 , intent(in) :: breakdown - real*8 , intent(in) :: Updates(N_updates*Dim) - real*8 , intent(inout) :: Slater_inv(Dim*Dim) - info = qmckl_sherman_morrison(context, Dim, N_updates, Updates, & - Updates_index, breakdown, Slater_inv) - ) -end function qmckl_sherman_morrison_f - #+end_src - *** C source #+begin_src c :tangle (eval c) :comments org @@ -122,7 +103,7 @@ end function qmckl_sherman_morrison_f #include #include "qmckl.h" -qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, +qmckl_exit_code qmckl_sherman_morrison_c_(const qmckl_context context, const uint64_t Dim, const uint64_t N_updates, const double* Updates, @@ -188,11 +169,56 @@ qmckl_exit_code qmckl_sherman_morrison_c(const qmckl_context context, :END: #+CALL: generate_c_interface(table=qmckl_sherman_morrison_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - - #+RESULTS: + #+RESULTS: + #+begin_src f90 :tangle (eval f) :comments org :exports none + integer(c_int32_t) function qmckl_sherman_morrison & + (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) & + bind(C) result(info) + + use, intrinsic :: iso_c_binding + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) , value :: Dim + integer (c_int64_t) , intent(in) , value :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(in) , value :: breakdown + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + integer(c_int32_t), external :: qmckl_sherman_morrison_c + info = qmckl_sherman_morrison_c & + (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) + + end function qmckl_sherman_morrison + #+end_src + #+CALL: generate_f_interface(table=qmckl_sherman_morrison_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src f90 :tangle (eval fh_func) :comments org :exports none + interface + integer(c_int32_t) function qmckl_sherman_morrison & + (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) & + bind(C) + + use, intrinsic :: iso_c_binding + import + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) , value :: Dim + integer (c_int64_t) , intent(in) , value :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(in) , value :: breakdown + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + end function qmckl_sherman_morrison + end interface + #+end_src + *** Test :noexport: The tests for the kernels are executed on datasets that are extracted from a run of QMC=Chem on Benzene (21 spin-up/21 spin down electrons) using 329 unique alpha determinants. The tests are run such that the kernels reject the computed inverse whenever the computed intermediate determinants or denominators are smaller than 1e-3. This is the default value in QMC=Chem. The tests will return QMCKL_SUCCESS whenever all the elements of the final matrix $R=S.S^-1 - 1$ are smaller than the given tolerance value of 1e-3, and will return QMCKL_FAILURE if the values are larger than this tolerance value. @@ -235,7 +261,7 @@ double Slater_inv5_2[441] = {-0.054189244668834902, -105.426713929607, -88.45849 // WB3,2+spl: 3,2 double Slater_inv5_3[441] = {-0.054189244668834902, -105.426713929607, -88.458496476283003, 1.5333775291907901, -306.17152423250297, 211.834723659242, 189.348181800731, -164.85602878397, 1001.02895803198, -19.086531171244101, -14.1862411100869, 93.929906236367501, -177.880045125896, -6.7382862272631598, -14.511503830974201, 198.86948709278099, 116.24375034946701, -509.187787693936, -474.82187536023201, 185.49468275501101, -68.704359475869197, 0.066396729468773799, 128.61396390514599, 107.279152808508, -3.2214077352586501, 377.39638500462598, -258.32727230254102, -233.50899542599601, 202.73053181330999, -1222.6711957145401, 23.374193247961198, 17.0231928902612, -115.31992914359, 218.34781344598201, 8.5868800406738099, 17.706454078785399, -244.13052330624399, -142.42769283244499, 622.15335091370196, 579.15535219316803, -228.72024346964599, 85.262861528059901, 0.042977214694503003, -75.818887039648899, -63.4429496117761, 1.89037149893251, -221.440571714557, 152.54192851849001, 136.92110635753301, -119.073716594494, 720.98982202338402, -13.516656591400601, -9.7291496308540406, 67.372278162472895, -128.19425354399101, -4.9638472213270699, -10.200417492010599, 143.31769471617801, 83.615852083439094, -366.86654819753397, -341.426964056759, 133.98241248588599, -50.230799667840699, -0.074440153582489205, 131.003888225851, 110.340015781723, -1.92534262087524, 381.482058581253, -264.51148724341499, -236.035513173862, 204.43864191351099, -1249.3967405711001, 23.404380739562701, 17.427737318703301, -116.737852869633, 221.189913802663, 8.4677080090305399, 17.684126766935599, -247.44394443997601, -145.031902348194, 635.53348480709997, 592.58164589603302, -230.87850923206801, 85.694308069456397, -0.038299262589364599, -74.702005824131604, -63.171412849899497, 1.0859859506457199, -217.148397050222, 150.25957665606299, 134.431598757773, -117.013550651343, 708.34335491195498, -13.4940069422526, -9.5788103819957797, 66.593490547156307, -125.80391712960601, -4.7671091217963504, -10.2632044954116, 140.809682960885, 82.366527572926103, -360.28206877713399, -335.74815599116999, 131.925760239261, -48.660685665615503, -0.060749768867194, 106.92546569584999, 88.790343162838894, -2.6692288353747702, 312.16097467403699, -214.903931604847, -193.215823966269, 167.781122174079, -1018.10641886182, 19.107519450141002, 14.388719322765001, -95.267373183568594, 180.40857560667001, 6.9728512293157801, 14.4102075774752, -201.83015329787199, -117.917199027973, 518.09179195913805, 482.46342773412402, -189.25708821193001, 70.869624357767506, -0.000187411047696029, -11.9846117540694, -9.5726690972884096, 0.23970985157893901, -31.525734707294099, 26.424001662617101, 19.629541977294, -12.8111861333484, 126.186955595279, -0.21994779537689901, -1.75278408990554, 12.699562562401301, -19.050321348645301, 0.28466729039388, -1.07057307471916, 20.675591706275501, 13.1048598424623, -64.121267975873096, -59.394985304548896, 16.918592992744401, -7.70362909966763, 0.00036065684724530402, 12.9068309168011, 12.002712393435401, -0.33194601220397202, 40.326484701927001, -31.878253347415502, -25.170560077575001, 17.9905011861023, -156.05779622500401, 0.28522581276215098, 2.06069522309385, -17.151275363286, 25.397351917205899, 2.08581286823873, 0.91118057859336898, -26.515090998756101, -14.4035822159035, 78.890023885294596, 75.240667711773398, -20.769502289340899, 10.973365712218101, 0.00054214253230406803, -2.29504518628212, -2.1312244512866698, 0.047562978801466302, -10.6318457557031, 3.0591772010668401, 6.6375862982055702, -4.4363733110097296, 16.291945106274301, -0.062929125223047597, -0.16835581689436099, 6.0820271877694996, -5.8351950377758204, 0.35401259185447298, -0.90070453596893996, 6.0382685793059503, 2.4785619931575602, -8.4908203096171402, -8.6197966065449307, 5.8804527059182696, -1.67757738078734, 0.00096800508899916803, -2.4934502646428101, -4.5195305250493698, 0.052900907147883501, -6.5403147654399101, 8.5375829900159896, 4.1350660479474399, -1.63386715634978, 39.5635438458416, -0.11054656518749099, -0.56905231469759199, 10.2311793759502, -8.8014973731182806, -1.42214511908425, -1.9356586876592501, 7.4277556761303396, 2.8985267278915199, -19.981167223464801, -18.310196540769098, 1.3631485584979499, -1.4104996470922699, 0.000167515045034934, 10.6237721447983, 9.6125946891096099, -0.20829092726741699, 28.481388931713699, -22.584157610136199, -17.8392407006579, 11.6781776869203, -110.705963174229, 0.192721307745398, 1.4471736958685699, -11.629464509211299, 19.0388155304672, -0.23390314175395899, 0.62505732559282601, -19.284349111137399, -11.6199046959709, 56.562315732201498, 53.440734762614099, -13.464260193464, 6.5494922727750904, -0.00064712664753083498, 0.51012013976619996, -0.40601608060218902, -0.010304898323864499, -1.9162384482042301, 0.67040773560745603, 1.4195140953666501, 1.89175006728124, 8.4997123797302105, -0.053837688493721801, -0.0081694468687663092, 7.5841687069424202, -3.9864241641726901, 0.82441242748559596, 1.28841942280286, 2.4602644684099202, -0.65833650503714802, -2.93422340475106, -4.7994849299481297, -3.1153746742144999, 0.76509679552570997, -0.00094253467883977896, 4.5884404541075803, 2.5577714145483599, -0.100362327319965, 18.711173319888399, -7.5191542625802104, -11.814804467633101, 7.51205003788884, -36.605280961279099, 0.11460812693040601, 0.498461399643222, -10.903564320961401, 13.2948947844546, -0.64349351510306596, 1.9974412451213299, -11.727821769419799, -4.9603602940684901, 17.916362650168399, 17.291804112001799, -7.9761250950845, 3.6407278735208699, -0.000183321670183587, 6.4691421816769399, 6.0512576241625498, -0.15162968127745899, 23.395366108183801, -14.5381852262701, -14.606223833564799, 10.199271998597199, -73.975176230999594, 0.109352036334604, 0.939662287060122, -5.0493506777824901, 12.432450504307001, 0.66340082972807302, 0.89171490853171798, -14.301193838340501, -7.1767924210601599, 37.417730343433, 34.621199008384998, -12.2257905481279, 5.0337643040644098, 0.00077853683475417402, -4.0437466042030499, -3.2232682351578399, 0.038202731665628202, -12.153196028398099, 6.5027616010011799, 7.2973627140258399, -12.054113026894999, 23.6623418919025, 0.0029087480524890102, -0.465988240269751, -5.8215678299339997, -0.92982871489462304, 0.72875377435640498, -1.76856112702097, 3.9100682853776498, 4.3638012685037904, -12.532035664209801, -10.8596693966264, 12.5729914998231, -1.17795314966104, -0.00047116201805309901, 2.7712702890005598, 1.4259517039641101, -0.060855532638316702, 9.8783846948200704, -5.3156162802238898, -6.24217543532784, 4.0955113938692902, -22.6133771249789, 0.0576846298115802, 0.37261538596098298, -5.69311024324454, 6.6165547759347501, -0.31572322723037299, 1.2076815066994999, -7.13883450856141, -3.0036796657518701, 12.888731168100399, 10.144844547714699, -3.4202567509716602, 2.2424073656324301, 0.00046719815518450402, -6.1786048720593501, -4.9366254575058903, 0.121293000821164, -13.5354546658637, 11.122151465656, 8.2996176249675795, -7.8492497139147304, 53.792699096533298, -0.056207389907105297, -0.72284563910330601, -0.034988476570927102, -5.8914910450597402, -0.57259031868870103, -1.3110690999933601, 8.9888650972260002, 6.8430482968640902, -26.406527264610599, -25.8419474444987, 8.95444342115516, -4.1168180484580699, 0.00068908057573134802, -2.0076563509740999, -3.65231424825159, 0.042894239647239998, -9.7520285174303201, 7.9819862061298199, 6.2214414143151, -1.1841920217922099, 31.911005041941699, -0.080053013664620296, -0.54185675163812796, 8.0781654837979193, -9.3493294125201594, -1.24083642122091, -1.6208022544009499, 8.8607449463367196, 2.3445831189331501, -16.218420387174199, -15.8119148955707, 1.7389982134136399, -1.0509978817476, -3.48584361237575e-05, 0.61330220442703598, 2.33052219623813, -0.0057796507046079101, 5.3801162861110896, -1.7460100802854299, -3.4260231079769401, 1.85323155008146, -1.34565392401789, 0.0020702237459098, 0.147768044797361, -0.43649104760725999, 0.997972495465969, 0.056933085588242997, 0.0077486424610570597, -0.89070134502194598, -0.68148789029708001, 0.89518325797891696, 0.16523545732706499, -2.8298454160600501, 0.26096748561569599, -3.9951230141139501e-05, 2.6625953366596802, 0.159171360187916, -0.0080654609832386693, 14.485659114429501, 0.26188806209423798, -8.9564367313419204, 9.5170929366304993, 3.6594343436186199, 0.017879567938259198, 0.0042052494877241001, -1.4377710841437801, 5.8763150360799203, 0.47441391996743998, -0.014783250610591801, -7.06163381200634, -2.9885184999935599, -1.42889911045556, -2.4433038426403901, -9.8958894810457991, 0.55194555716779503, -5.7250805560848302e-05, 0.98372766353792995, 3.2392588139392098, -0.0119630481344816, 0.14153713576169, -2.73924503033615, 0.060309030316031902, 2.34167965625057, -3.8604817562043001, 0.012593073725828199, 0.22349082635471901, -0.35749918018293803, 2.0835157939561699, 0.13368765195851301, 0.0515445449292352, -2.95655438325227, -1.09680637412728, 2.2418386652533302, 1.2169977713442901, -1.20005576483735, 0.48385142427875799}; -rc = qmckl_sherman_morrison_c(context, Dim, N_updates1, Updates1, Updates_index1, breakdown, Slater_inv1); +rc = qmckl_sherman_morrison(context, Dim, N_updates1, Updates1, Updates_index1, breakdown, Slater_inv1); for (unsigned int i = 0; i < Dim; i++) { for (unsigned int j = 0; j < Dim; j++) { res[i * Dim + j] = 0; From c9e6bcdab16ccec9b120005432d5928a9fa2bd80 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Thu, 16 Sep 2021 13:44:12 +0200 Subject: [PATCH 48/50] Almost done with fixing interfaces. --- org/qmckl_mykernel.org | 130 ++++++++++++++ org/qmckl_sherman_morrison_woodbury.org | 217 +++++++++++++++++------- org/table_of_contents | 1 + 3 files changed, 282 insertions(+), 66 deletions(-) create mode 100644 org/qmckl_mykernel.org diff --git a/org/qmckl_mykernel.org b/org/qmckl_mykernel.org new file mode 100644 index 0000000..9c807f0 --- /dev/null +++ b/org/qmckl_mykernel.org @@ -0,0 +1,130 @@ +#+TITLE: My Kernel +#+SETUPFILE: ../tools/theme.setup +#+INCLUDE: ../tools/lib.org +#+STARTUP: content + +* Headers + #+begin_src elisp :noexport :results none :exports none +(org-babel-lob-ingest "../tools/lib.org") +#+end_src + + #+begin_src c :comments link :tangle (eval c_test) :noweb yes +#include "qmckl.h" +#include "assert.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include + +int main() { + qmckl_context context; + context = qmckl_context_create(); + qmckl_exit_code rc; + #+end_src + +* My Kernel + +** ~qmckl_mykernel~ + :PROPERTIES: + :Name: qmckl_mykernel + :CRetType: qmckl_exit_code + :FRetType: qmckl_exit_code + :END: + + #+NAME: qmckl_mykernel_args + | qmckl_context | context | in | Global state | + | int64_t | myarg1 | in | The only input argument | + +*** Requirements + + * ~context~ is not ~QMCKL_NULL_CONTEXT~ + +*** C header + + #+CALL: generate_c_header(table=qmckl_mykernel_args,rettyp=get_value("CRetType"),fname=get_value("Name")) + + #+RESULTS: + #+begin_src c :tangle (eval h_func) :comments org + qmckl_exit_code qmckl_mykernel(const qmckl_context context, + const int64_t* myarg1); + #+end_src + +*** C source + + #+begin_src c :tangle (eval c) :comments org + #include + #include + #include "qmckl.h" + + qmckl_exit_code qmckl_mykernel_c_(const qmckl_context context, + const int64_t* myarg1) { + + printf("Hello from qmckl_mykernel_c_\n"); + printf("Value of argument 'myarg1' from within 'qmckl_mykernel_c_' is: %i\n", *myarg1); + return QMCKL_SUCCESS; +} + #+end_src + +** C interface :noexport: + :PROPERTIES: + :Name: qmckl_mykernel + :CRetType: qmckl_exit_code + :FRetType: qmckl_exit_code + :END: + + #+CALL: generate_c_interface(table=qmckl_mykernel_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + + #+RESULTS: + #+begin_src f90 :tangle (eval f) :comments org :exports none + integer(c_int32_t) function qmckl_mykernel(context, myarg1) bind(C) result(info) + + use, intrinsic :: iso_c_binding + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) :: myarg1 + integer(c_int32_t) , external :: qmckl_mykernel_c + + write(*,*) "Hello from Fortran wrapper-function 'qmckl_mykernel'" + write(*,*) "Value of argument 'myarg1' from within 'qmckl_mykernel' before call to C-function 'qmckl_mykernel_c' is: ", myarg1 + info = qmckl_mykernel_c(context, myarg1) + write(*,*) "Value of argument 'myarg1' from within 'qmckl_mykernel' after call to C-function 'qmckl_mykernel_c' is: ", myarg1 + + end function qmckl_mykernel + #+end_src + + #+CALL: generate_f_interface(table=qmckl_mykernel_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + + #+RESULTS: + #+begin_src f90 :tangle (eval fh_func) :comments org :exports none + interface + integer(c_int32_t) function qmckl_mykernel(context, myarg1) bind(C) + use, intrinsic :: iso_c_binding + import + implicit none + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) :: myarg1 + end function qmckl_mykernel + end interface + #+end_src + +*** Test :noexport: + + #+begin_src c :tangle (eval c_test) + const int64_t arg1 = 10; + const int64_t* arg1p = &arg1; + printf("Value of arg1 before passing to 'qmckl_mykernel': %i\n", arg1); + rc = qmckl_mykernel(context, arg1p); + assert(rc == QMCKL_SUCCESS); + #+end_src + +* End of files + + #+begin_src c :comments link :tangle (eval c_test) + assert (qmckl_context_destroy(context) == QMCKL_SUCCESS); + return 0; + } + #+end_src + +# -*- mode: org -*- +# vim: syntax=c diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 3c8544e..256affd 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -86,14 +86,14 @@ int main() { #+RESULTS: #+begin_src c :tangle (eval h_func) :comments org - qmckl_exit_code qmckl_sherman_morrison ( + qmckl_exit_code qmckl_sherman_morrison( const qmckl_context context, - const uint64_t Dim, - const uint64_t N_updates, + const uint64_t* Dim_p, + const uint64_t* N_updates_p, const double* Updates, const uint64_t* Updates_index, - const double breakdown, - double* Slater_inv ); + const double* breakdown_p, + double* Slater_inv); #+end_src *** C source @@ -104,15 +104,15 @@ int main() { #include "qmckl.h" qmckl_exit_code qmckl_sherman_morrison_c_(const qmckl_context context, - const uint64_t Dim, - const uint64_t N_updates, + const uint64_t* Dim_p, + const uint64_t* N_updates_p, const double* Updates, const uint64_t* Updates_index, - const double breakdown, - double * Slater_inv) { -// #ifdef DEBUG -// std::cerr << "Called qmckl_sherman_morrison with " << N_updates << " updates" << std::endl; -// #endif + const double* breakdown_p, + double* Slater_inv) { + const uint64_t Dim = *Dim_p; + const uint64_t N_updates = *N_updates_p; + const double breakdown = *breakdown_p; double C[Dim]; double D[Dim]; @@ -180,11 +180,11 @@ qmckl_exit_code qmckl_sherman_morrison_c_(const qmckl_context context, implicit none integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) , value :: Dim - integer (c_int64_t) , intent(in) , value :: N_updates + integer (c_int64_t) , intent(in) :: Dim + integer (c_int64_t) , intent(in) :: N_updates real (c_double ) , intent(in) :: Updates(N_updates*Dim) integer (c_int64_t) , intent(in) :: Updates_index(N_updates) - real (c_double ) , intent(in) , value :: breakdown + real (c_double ) , intent(in) :: breakdown real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) integer(c_int32_t), external :: qmckl_sherman_morrison_c @@ -208,11 +208,11 @@ qmckl_exit_code qmckl_sherman_morrison_c_(const qmckl_context context, implicit none integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) , value :: Dim - integer (c_int64_t) , intent(in) , value :: N_updates + integer (c_int64_t) , intent(in) :: Dim + integer (c_int64_t) , intent(in) :: N_updates real (c_double ) , intent(in) :: Updates(N_updates*Dim) integer (c_int64_t) , intent(in) :: Updates_index(N_updates) - real (c_double ) , intent(in) , value :: breakdown + real (c_double ) , intent(in) :: breakdown real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) end function qmckl_sherman_morrison @@ -225,7 +225,10 @@ The tests for the kernels are executed on datasets that are extracted from a run #+begin_src c :tangle (eval c_test) const uint64_t Dim = 21; +const uint64_t* Dim_p = &Dim; +const uint64_t* N_updates_p = NULL; const double breakdown = 1e-3; +const double* breakdown_p = &breakdown; const double tolerance = 1e-3; double res[441]; @@ -261,7 +264,8 @@ double Slater_inv5_2[441] = {-0.054189244668834902, -105.426713929607, -88.45849 // WB3,2+spl: 3,2 double Slater_inv5_3[441] = {-0.054189244668834902, -105.426713929607, -88.458496476283003, 1.5333775291907901, -306.17152423250297, 211.834723659242, 189.348181800731, -164.85602878397, 1001.02895803198, -19.086531171244101, -14.1862411100869, 93.929906236367501, -177.880045125896, -6.7382862272631598, -14.511503830974201, 198.86948709278099, 116.24375034946701, -509.187787693936, -474.82187536023201, 185.49468275501101, -68.704359475869197, 0.066396729468773799, 128.61396390514599, 107.279152808508, -3.2214077352586501, 377.39638500462598, -258.32727230254102, -233.50899542599601, 202.73053181330999, -1222.6711957145401, 23.374193247961198, 17.0231928902612, -115.31992914359, 218.34781344598201, 8.5868800406738099, 17.706454078785399, -244.13052330624399, -142.42769283244499, 622.15335091370196, 579.15535219316803, -228.72024346964599, 85.262861528059901, 0.042977214694503003, -75.818887039648899, -63.4429496117761, 1.89037149893251, -221.440571714557, 152.54192851849001, 136.92110635753301, -119.073716594494, 720.98982202338402, -13.516656591400601, -9.7291496308540406, 67.372278162472895, -128.19425354399101, -4.9638472213270699, -10.200417492010599, 143.31769471617801, 83.615852083439094, -366.86654819753397, -341.426964056759, 133.98241248588599, -50.230799667840699, -0.074440153582489205, 131.003888225851, 110.340015781723, -1.92534262087524, 381.482058581253, -264.51148724341499, -236.035513173862, 204.43864191351099, -1249.3967405711001, 23.404380739562701, 17.427737318703301, -116.737852869633, 221.189913802663, 8.4677080090305399, 17.684126766935599, -247.44394443997601, -145.031902348194, 635.53348480709997, 592.58164589603302, -230.87850923206801, 85.694308069456397, -0.038299262589364599, -74.702005824131604, -63.171412849899497, 1.0859859506457199, -217.148397050222, 150.25957665606299, 134.431598757773, -117.013550651343, 708.34335491195498, -13.4940069422526, -9.5788103819957797, 66.593490547156307, -125.80391712960601, -4.7671091217963504, -10.2632044954116, 140.809682960885, 82.366527572926103, -360.28206877713399, -335.74815599116999, 131.925760239261, -48.660685665615503, -0.060749768867194, 106.92546569584999, 88.790343162838894, -2.6692288353747702, 312.16097467403699, -214.903931604847, -193.215823966269, 167.781122174079, -1018.10641886182, 19.107519450141002, 14.388719322765001, -95.267373183568594, 180.40857560667001, 6.9728512293157801, 14.4102075774752, -201.83015329787199, -117.917199027973, 518.09179195913805, 482.46342773412402, -189.25708821193001, 70.869624357767506, -0.000187411047696029, -11.9846117540694, -9.5726690972884096, 0.23970985157893901, -31.525734707294099, 26.424001662617101, 19.629541977294, -12.8111861333484, 126.186955595279, -0.21994779537689901, -1.75278408990554, 12.699562562401301, -19.050321348645301, 0.28466729039388, -1.07057307471916, 20.675591706275501, 13.1048598424623, -64.121267975873096, -59.394985304548896, 16.918592992744401, -7.70362909966763, 0.00036065684724530402, 12.9068309168011, 12.002712393435401, -0.33194601220397202, 40.326484701927001, -31.878253347415502, -25.170560077575001, 17.9905011861023, -156.05779622500401, 0.28522581276215098, 2.06069522309385, -17.151275363286, 25.397351917205899, 2.08581286823873, 0.91118057859336898, -26.515090998756101, -14.4035822159035, 78.890023885294596, 75.240667711773398, -20.769502289340899, 10.973365712218101, 0.00054214253230406803, -2.29504518628212, -2.1312244512866698, 0.047562978801466302, -10.6318457557031, 3.0591772010668401, 6.6375862982055702, -4.4363733110097296, 16.291945106274301, -0.062929125223047597, -0.16835581689436099, 6.0820271877694996, -5.8351950377758204, 0.35401259185447298, -0.90070453596893996, 6.0382685793059503, 2.4785619931575602, -8.4908203096171402, -8.6197966065449307, 5.8804527059182696, -1.67757738078734, 0.00096800508899916803, -2.4934502646428101, -4.5195305250493698, 0.052900907147883501, -6.5403147654399101, 8.5375829900159896, 4.1350660479474399, -1.63386715634978, 39.5635438458416, -0.11054656518749099, -0.56905231469759199, 10.2311793759502, -8.8014973731182806, -1.42214511908425, -1.9356586876592501, 7.4277556761303396, 2.8985267278915199, -19.981167223464801, -18.310196540769098, 1.3631485584979499, -1.4104996470922699, 0.000167515045034934, 10.6237721447983, 9.6125946891096099, -0.20829092726741699, 28.481388931713699, -22.584157610136199, -17.8392407006579, 11.6781776869203, -110.705963174229, 0.192721307745398, 1.4471736958685699, -11.629464509211299, 19.0388155304672, -0.23390314175395899, 0.62505732559282601, -19.284349111137399, -11.6199046959709, 56.562315732201498, 53.440734762614099, -13.464260193464, 6.5494922727750904, -0.00064712664753083498, 0.51012013976619996, -0.40601608060218902, -0.010304898323864499, -1.9162384482042301, 0.67040773560745603, 1.4195140953666501, 1.89175006728124, 8.4997123797302105, -0.053837688493721801, -0.0081694468687663092, 7.5841687069424202, -3.9864241641726901, 0.82441242748559596, 1.28841942280286, 2.4602644684099202, -0.65833650503714802, -2.93422340475106, -4.7994849299481297, -3.1153746742144999, 0.76509679552570997, -0.00094253467883977896, 4.5884404541075803, 2.5577714145483599, -0.100362327319965, 18.711173319888399, -7.5191542625802104, -11.814804467633101, 7.51205003788884, -36.605280961279099, 0.11460812693040601, 0.498461399643222, -10.903564320961401, 13.2948947844546, -0.64349351510306596, 1.9974412451213299, -11.727821769419799, -4.9603602940684901, 17.916362650168399, 17.291804112001799, -7.9761250950845, 3.6407278735208699, -0.000183321670183587, 6.4691421816769399, 6.0512576241625498, -0.15162968127745899, 23.395366108183801, -14.5381852262701, -14.606223833564799, 10.199271998597199, -73.975176230999594, 0.109352036334604, 0.939662287060122, -5.0493506777824901, 12.432450504307001, 0.66340082972807302, 0.89171490853171798, -14.301193838340501, -7.1767924210601599, 37.417730343433, 34.621199008384998, -12.2257905481279, 5.0337643040644098, 0.00077853683475417402, -4.0437466042030499, -3.2232682351578399, 0.038202731665628202, -12.153196028398099, 6.5027616010011799, 7.2973627140258399, -12.054113026894999, 23.6623418919025, 0.0029087480524890102, -0.465988240269751, -5.8215678299339997, -0.92982871489462304, 0.72875377435640498, -1.76856112702097, 3.9100682853776498, 4.3638012685037904, -12.532035664209801, -10.8596693966264, 12.5729914998231, -1.17795314966104, -0.00047116201805309901, 2.7712702890005598, 1.4259517039641101, -0.060855532638316702, 9.8783846948200704, -5.3156162802238898, -6.24217543532784, 4.0955113938692902, -22.6133771249789, 0.0576846298115802, 0.37261538596098298, -5.69311024324454, 6.6165547759347501, -0.31572322723037299, 1.2076815066994999, -7.13883450856141, -3.0036796657518701, 12.888731168100399, 10.144844547714699, -3.4202567509716602, 2.2424073656324301, 0.00046719815518450402, -6.1786048720593501, -4.9366254575058903, 0.121293000821164, -13.5354546658637, 11.122151465656, 8.2996176249675795, -7.8492497139147304, 53.792699096533298, -0.056207389907105297, -0.72284563910330601, -0.034988476570927102, -5.8914910450597402, -0.57259031868870103, -1.3110690999933601, 8.9888650972260002, 6.8430482968640902, -26.406527264610599, -25.8419474444987, 8.95444342115516, -4.1168180484580699, 0.00068908057573134802, -2.0076563509740999, -3.65231424825159, 0.042894239647239998, -9.7520285174303201, 7.9819862061298199, 6.2214414143151, -1.1841920217922099, 31.911005041941699, -0.080053013664620296, -0.54185675163812796, 8.0781654837979193, -9.3493294125201594, -1.24083642122091, -1.6208022544009499, 8.8607449463367196, 2.3445831189331501, -16.218420387174199, -15.8119148955707, 1.7389982134136399, -1.0509978817476, -3.48584361237575e-05, 0.61330220442703598, 2.33052219623813, -0.0057796507046079101, 5.3801162861110896, -1.7460100802854299, -3.4260231079769401, 1.85323155008146, -1.34565392401789, 0.0020702237459098, 0.147768044797361, -0.43649104760725999, 0.997972495465969, 0.056933085588242997, 0.0077486424610570597, -0.89070134502194598, -0.68148789029708001, 0.89518325797891696, 0.16523545732706499, -2.8298454160600501, 0.26096748561569599, -3.9951230141139501e-05, 2.6625953366596802, 0.159171360187916, -0.0080654609832386693, 14.485659114429501, 0.26188806209423798, -8.9564367313419204, 9.5170929366304993, 3.6594343436186199, 0.017879567938259198, 0.0042052494877241001, -1.4377710841437801, 5.8763150360799203, 0.47441391996743998, -0.014783250610591801, -7.06163381200634, -2.9885184999935599, -1.42889911045556, -2.4433038426403901, -9.8958894810457991, 0.55194555716779503, -5.7250805560848302e-05, 0.98372766353792995, 3.2392588139392098, -0.0119630481344816, 0.14153713576169, -2.73924503033615, 0.060309030316031902, 2.34167965625057, -3.8604817562043001, 0.012593073725828199, 0.22349082635471901, -0.35749918018293803, 2.0835157939561699, 0.13368765195851301, 0.0515445449292352, -2.95655438325227, -1.09680637412728, 2.2418386652533302, 1.2169977713442901, -1.20005576483735, 0.48385142427875799}; -rc = qmckl_sherman_morrison(context, Dim, N_updates1, Updates1, Updates_index1, breakdown, Slater_inv1); +N_updates_p = &N_updates1; +rc = qmckl_sherman_morrison(context, Dim_p, N_updates_p, Updates1, Updates_index1, breakdown_p, Slater_inv1); for (unsigned int i = 0; i < Dim; i++) { for (unsigned int j = 0; j < Dim; j++) { res[i * Dim + j] = 0; @@ -330,13 +334,13 @@ assert(rc == QMCKL_SUCCESS); #+RESULTS: #+begin_src c :tangle (eval h_func) :comments org - qmckl_exit_code qmckl_woodbury_2_c ( + qmckl_exit_code qmckl_woodbury_2( const qmckl_context context, - const uint64_t Dim, + const uint64_t* Dim_p, const double* Updates, const uint64_t* Updates_index, - const double breakdown, - double* Slater_inv ); + const double* breakdown_p, + double* Slater_inv); #+end_src *** Source @@ -346,20 +350,20 @@ assert(rc == QMCKL_SUCCESS); #include #include "qmckl.h" -qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, - const uint64_t Dim, +qmckl_exit_code qmckl_woodbury_2_c_(const qmckl_context context, + const uint64_t* Dim_p, const double* Updates, const uint64_t* Updates_index, - const double breakdown, + const double* breakdown_p, double * Slater_inv) { /* C := S^{-1} * U, dim x 2 B := 1 + V * C, 2 x 2 D := V * S^{-1}, 2 x dim ,*/ -// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. -// std::cerr << "Called Woodbury 2x2 kernel" << std::endl; -// #endif + + const uint64_t Dim = *Dim_p; + const double breakdown = *breakdown_p; const uint64_t row1 = (Updates_index[0] - 1); const uint64_t row2 = (Updates_index[1] - 1); @@ -430,12 +434,57 @@ qmckl_exit_code qmckl_woodbury_2_c(const qmckl_context context, #+CALL: generate_c_interface(table=qmckl_woodbury_2_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src f90 :tangle (eval f) :comments org :exports none + integer(c_int32_t) function qmckl_woodbury_2 & + (context, Dim, Updates, Updates_index, breakdown, Slater_inv) & + bind(C) result(info) + + use, intrinsic :: iso_c_binding + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) :: Dim + real (c_double ) , intent(in) :: Updates(2*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(2) + real (c_double ) , intent(in) :: breakdown + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + integer(c_int32_t), external :: qmckl_woodbury_2_c + info = qmckl_woodbury_2_c & + (context, Dim, Updates, Updates_index, breakdown, Slater_inv) + + end function qmckl_woodbury_2 + #+end_src + #+CALL: generate_f_interface(table=qmckl_woodbury_2_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src f90 :tangle (eval fh_func) :comments org :exports none + interface + integer(c_int32_t) function qmckl_woodbury_2 & + (context, Dim, Updates, Updates_index, breakdown, Slater_inv) & + bind(C) + use, intrinsic :: iso_c_binding + import + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) :: Dim + real (c_double ) , intent(in) :: Updates(2*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(2) + real (c_double ) , intent(in) :: breakdown + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + end function qmckl_woodbury_2 + end interface + #+end_src + *** Test :noexport: #+begin_src c :tangle (eval c_test) -rc = qmckl_woodbury_2_c(context, Dim, Updates2, Updates_index2, breakdown, Slater_inv2); + +rc = qmckl_woodbury_2(context, Dim_p, Updates2, Updates_index2, breakdown_p, Slater_inv2); for (unsigned int i = 0; i < Dim; i++) { for (unsigned int j = 0; j < Dim; j++) { res[i * Dim + j] = 0; @@ -498,13 +547,13 @@ assert(rc == QMCKL_SUCCESS); #+RESULTS: #+begin_src c :tangle (eval h_func) :comments org - qmckl_exit_code qmckl_woodbury_3_c ( + qmckl_exit_code qmckl_woodbury_3( const qmckl_context context, - const uint64_t Dim, + const uint64_t* Dim_p, const double* Updates, const uint64_t* Updates_index, - const double breakdown, - double* Slater_inv ); + const double* breakdown_p, + double* Slater_inv); #+end_src *** Source @@ -514,20 +563,20 @@ assert(rc == QMCKL_SUCCESS); #include #include "qmckl.h" -qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, - const uint64_t Dim, +qmckl_exit_code qmckl_woodbury_3_c_(const qmckl_context context, + const uint64_t* Dim_p, const double* Updates, const uint64_t* Updates_index, - const double breakdown, + const double* breakdown_p, double * Slater_inv) { /* C := S^{-1} * U, dim x 3 B := 1 + V * C, 3 x 3 D := V * S^{-1}, 3 x dim ,*/ -// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. -// std::cerr << "Called Woodbury 3x3 kernel" << std::endl; -// #endif + + const uint64_t Dim = *Dim_p; + const double breakdown = *breakdown_p; const uint64_t row1 = (Updates_index[0] - 1); const uint64_t row2 = (Updates_index[1] - 1); @@ -597,7 +646,6 @@ qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, return QMCKL_SUCCESS; } - #+end_src *** Performance... @@ -614,12 +662,56 @@ qmckl_exit_code qmckl_woodbury_3_c(const qmckl_context context, #+CALL: generate_c_interface(table=qmckl_woodbury_3_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src f90 :tangle (eval f) :comments org :exports none + integer(c_int32_t) function qmckl_woodbury_3 & + (context, Dim, Updates, Updates_index, breakdown, Slater_inv) & + bind(C) result(info) + + use, intrinsic :: iso_c_binding + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) :: Dim + real (c_double ) , intent(in) :: Updates(3*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(3) + real (c_double ) , intent(in) :: breakdown + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + integer(c_int32_t), external :: qmckl_woodbury_3_c + info = qmckl_woodbury_3_c & + (context, Dim, Updates, Updates_index, breakdown, Slater_inv) + + end function qmckl_woodbury_3 + #+end_src + #+CALL: generate_f_interface(table=qmckl_woodbury_3_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src f90 :tangle (eval fh_func) :comments org :exports none + interface + integer(c_int32_t) function qmckl_woodbury_3 & + (context, Dim, Updates, Updates_index, breakdown, Slater_inv) & + bind(C) + use, intrinsic :: iso_c_binding + import + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) :: Dim + real (c_double ) , intent(in) :: Updates(3*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(3) + real (c_double ) , intent(in) :: breakdown + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + end function qmckl_woodbury_3 + end interface + #+end_src + *** Test :noexport: #+begin_src c :tangle (eval c_test) -rc = qmckl_woodbury_3_c(context, Dim, Updates3, Updates_index3, breakdown, Slater_inv3_1); +rc = qmckl_woodbury_3(context, Dim_p, Updates3, Updates_index3, breakdown_p, Slater_inv3_1); for (unsigned int i = 0; i < Dim; i++) { for (unsigned int j = 0; j < Dim; j++) { res[i * Dim + j] = 0; @@ -687,14 +779,14 @@ assert(rc == QMCKL_SUCCESS); #+RESULTS: #+begin_src c :tangle (eval h_func) :comments org - qmckl_exit_code qmckl_sherman_morrison_splitting_c ( + qmckl_exit_code qmckl_sherman_morrison_splitting( const qmckl_context context, - const uint64_t Dim, - const uint64_t N_updates, + const uint64_t* Dim, + const uint64_t* N_updates, const double* Updates, const uint64_t* Updates_index, - const double breakdown, - double* Slater_inv ); + const double* breakdown, + double* Slater_inv); #+end_src *** Source @@ -703,26 +795,23 @@ assert(rc == QMCKL_SUCCESS); #include #include "qmckl.h" -qmckl_exit_code qmckl_sherman_morrison_splitting_c(const qmckl_context context, - const uint64_t Dim, - const uint64_t N_updates, +qmckl_exit_code qmckl_sherman_morrison_splitting_c_(const qmckl_context context, + const uint64_t* Dim, + const uint64_t* N_updates, const double* Updates, const uint64_t* Updates_index, - const double breakdown, + const double* breakdown, double * Slater_inv) { -// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. -// std::cerr << "Called qmckl_sherman_morrison_splitting with " << N_updates << " updates" << std::endl; -// #endif - - double later_updates[Dim * N_updates]; - uint64_t later_index[N_updates]; + + double later_updates[*Dim * *N_updates]; + uint64_t later_index[*N_updates]; uint64_t later = 0; - (void) qmckl_slagel_splitting_c(Dim, N_updates, Updates, Updates_index, - breakdown, Slater_inv, later_updates, later_index, &later); + (void) qmckl_slagel_splitting_c(*Dim, *N_updates, Updates, Updates_index, + *breakdown, Slater_inv, later_updates, later_index, &later); if (later > 0) { - (void) qmckl_sherman_morrison_splitting_c(context, Dim, later, + (void) qmckl_sherman_morrison_splitting_c_(context, Dim, later, later_updates, later_index, breakdown, Slater_inv); } @@ -835,10 +924,6 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, const uint64_t* Updates_index, const double breakdown, double * Slater_inv) { -// #ifdef DEBUG // Leave commented out since debugging information is not yet implemented in QMCkl. -// std::cerr << "Called qmckl_sherman_morrison_woodbury_3 with " << N_updates -// << " updates" << std::endl; -// #endif qmckl_exit_code rc; @@ -855,7 +940,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, for (uint64_t i = 0; i < n_of_3blocks; i++) { const double *Updates_3block = &Updates[i * length_3block]; const uint64_t *Updates_index_3block = &Updates_index[i * 3]; - rc = qmckl_woodbury_3_c(context, Dim, Updates_3block, Updates_index_3block, breakdown, Slater_inv); + rc = qmckl_woodbury_3_c_(context, &Dim, Updates_3block, Updates_index_3block, &breakdown, Slater_inv); if (rc != 0) { // Send the entire block to slagel_splitting uint64_t l = 0; rc = qmckl_slagel_splitting_c(Dim, 3, Updates_3block, Updates_index_3block, @@ -868,7 +953,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, if (remainder == 2) { // Apply last remaining block of 2 updates with Woodbury 2x2 kernel const double *Updates_2block = &Updates[n_of_3blocks * length_3block]; const uint64_t *Updates_index_2block = &Updates_index[3 * n_of_3blocks]; - rc = qmckl_woodbury_2_c(context, Dim, Updates_2block, Updates_index_2block, breakdown, Slater_inv); + rc = qmckl_woodbury_2_c_(context, &Dim, Updates_2block, Updates_index_2block, &breakdown, Slater_inv); if (rc != 0) { // Send the entire block to slagel_splitting uint64_t l = 0; (void) qmckl_slagel_splitting_c(Dim, 2, Updates_2block, Updates_index_2block, diff --git a/org/table_of_contents b/org/table_of_contents index dfc6f52..7aa7dc6 100644 --- a/org/table_of_contents +++ b/org/table_of_contents @@ -7,6 +7,7 @@ qmckl_nucleus.org qmckl_electron.org qmckl_ao.org qmckl_jastrow.org +qmckl_mykernel.org qmckl_sherman_morrison_woodbury.org qmckl_distance.org qmckl_utils.org From 908e52b855a0a94c6e793ea4ddf7ae3abac1565a Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Thu, 16 Sep 2021 17:24:19 +0200 Subject: [PATCH 49/50] All Fortran interfaces to C/C++ added and tested. Library and tests compile smoothly. --- org/qmckl_mykernel.org | 130 ------------------------ org/qmckl_sherman_morrison_woodbury.org | 130 +++++++++++++++++++++--- org/table_of_contents | 1 - 3 files changed, 115 insertions(+), 146 deletions(-) delete mode 100644 org/qmckl_mykernel.org diff --git a/org/qmckl_mykernel.org b/org/qmckl_mykernel.org deleted file mode 100644 index 9c807f0..0000000 --- a/org/qmckl_mykernel.org +++ /dev/null @@ -1,130 +0,0 @@ -#+TITLE: My Kernel -#+SETUPFILE: ../tools/theme.setup -#+INCLUDE: ../tools/lib.org -#+STARTUP: content - -* Headers - #+begin_src elisp :noexport :results none :exports none -(org-babel-lob-ingest "../tools/lib.org") -#+end_src - - #+begin_src c :comments link :tangle (eval c_test) :noweb yes -#include "qmckl.h" -#include "assert.h" -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include - -int main() { - qmckl_context context; - context = qmckl_context_create(); - qmckl_exit_code rc; - #+end_src - -* My Kernel - -** ~qmckl_mykernel~ - :PROPERTIES: - :Name: qmckl_mykernel - :CRetType: qmckl_exit_code - :FRetType: qmckl_exit_code - :END: - - #+NAME: qmckl_mykernel_args - | qmckl_context | context | in | Global state | - | int64_t | myarg1 | in | The only input argument | - -*** Requirements - - * ~context~ is not ~QMCKL_NULL_CONTEXT~ - -*** C header - - #+CALL: generate_c_header(table=qmckl_mykernel_args,rettyp=get_value("CRetType"),fname=get_value("Name")) - - #+RESULTS: - #+begin_src c :tangle (eval h_func) :comments org - qmckl_exit_code qmckl_mykernel(const qmckl_context context, - const int64_t* myarg1); - #+end_src - -*** C source - - #+begin_src c :tangle (eval c) :comments org - #include - #include - #include "qmckl.h" - - qmckl_exit_code qmckl_mykernel_c_(const qmckl_context context, - const int64_t* myarg1) { - - printf("Hello from qmckl_mykernel_c_\n"); - printf("Value of argument 'myarg1' from within 'qmckl_mykernel_c_' is: %i\n", *myarg1); - return QMCKL_SUCCESS; -} - #+end_src - -** C interface :noexport: - :PROPERTIES: - :Name: qmckl_mykernel - :CRetType: qmckl_exit_code - :FRetType: qmckl_exit_code - :END: - - #+CALL: generate_c_interface(table=qmckl_mykernel_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - - #+RESULTS: - #+begin_src f90 :tangle (eval f) :comments org :exports none - integer(c_int32_t) function qmckl_mykernel(context, myarg1) bind(C) result(info) - - use, intrinsic :: iso_c_binding - implicit none - - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) :: myarg1 - integer(c_int32_t) , external :: qmckl_mykernel_c - - write(*,*) "Hello from Fortran wrapper-function 'qmckl_mykernel'" - write(*,*) "Value of argument 'myarg1' from within 'qmckl_mykernel' before call to C-function 'qmckl_mykernel_c' is: ", myarg1 - info = qmckl_mykernel_c(context, myarg1) - write(*,*) "Value of argument 'myarg1' from within 'qmckl_mykernel' after call to C-function 'qmckl_mykernel_c' is: ", myarg1 - - end function qmckl_mykernel - #+end_src - - #+CALL: generate_f_interface(table=qmckl_mykernel_args,rettyp=get_value("FRetType"),fname=get_value("Name")) - - #+RESULTS: - #+begin_src f90 :tangle (eval fh_func) :comments org :exports none - interface - integer(c_int32_t) function qmckl_mykernel(context, myarg1) bind(C) - use, intrinsic :: iso_c_binding - import - implicit none - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) :: myarg1 - end function qmckl_mykernel - end interface - #+end_src - -*** Test :noexport: - - #+begin_src c :tangle (eval c_test) - const int64_t arg1 = 10; - const int64_t* arg1p = &arg1; - printf("Value of arg1 before passing to 'qmckl_mykernel': %i\n", arg1); - rc = qmckl_mykernel(context, arg1p); - assert(rc == QMCKL_SUCCESS); - #+end_src - -* End of files - - #+begin_src c :comments link :tangle (eval c_test) - assert (qmckl_context_destroy(context) == QMCKL_SUCCESS); - return 0; - } - #+end_src - -# -*- mode: org -*- -# vim: syntax=c diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index 256affd..ad34d60 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -811,7 +811,7 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c_(const qmckl_context context, *breakdown, Slater_inv, later_updates, later_index, &later); if (later > 0) { - (void) qmckl_sherman_morrison_splitting_c_(context, Dim, later, + (void) qmckl_sherman_morrison_splitting_c_(context, Dim, &later, later_updates, later_index, breakdown, Slater_inv); } @@ -833,12 +833,59 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c_(const qmckl_context context, #+CALL: generate_c_interface(table=qmckl_sherman_morrison_splitting_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src f90 :tangle (eval f) :comments org :exports none + integer(c_int32_t) function qmckl_sherman_morrison_splitting & + (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) & + bind(C) result(info) + + use, intrinsic :: iso_c_binding + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) :: Dim + integer (c_int64_t) , intent(in) :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(in) :: breakdown + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + integer(c_int32_t), external :: qmckl_sherman_morrison_splitting_c + info = qmckl_sherman_morrison_splitting_c & + (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) + + end function qmckl_sherman_morrison_splitting + #+end_src + #+CALL: generate_f_interface(table=qmckl_sherman_morrison_splitting_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src f90 :tangle (eval fh_func) :comments org :exports none + interface + integer(c_int32_t) function qmckl_sherman_morrison_splitting & + (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) & + bind(C) + use, intrinsic :: iso_c_binding + import + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) :: Dim + integer (c_int64_t) , intent(in) :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(in) :: breakdown + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + end function qmckl_sherman_morrison_splitting + end interface + #+end_src + *** Test :noexport: #+begin_src c :tangle (eval c_test) -rc = qmckl_sherman_morrison_splitting_c(context, Dim, N_updates3, Updates3, Updates_index3, breakdown, Slater_inv3_2); +N_updates_p = &N_updates3; +rc = qmckl_sherman_morrison_splitting(context, Dim_p, N_updates_p, Updates3, Updates_index3, breakdown_p, Slater_inv3_2); for (unsigned int i = 0; i < Dim; i++) { for (unsigned int j = 0; j < Dim; j++) { res[i * Dim + j] = 0; @@ -901,14 +948,14 @@ assert(rc == QMCKL_SUCCESS); #+RESULTS: #+begin_src c :tangle (eval h_func) :comments org - qmckl_exit_code qmckl_sherman_morrison_smw32s_c ( + qmckl_exit_code qmckl_sherman_morrison_smw32s( const qmckl_context context, - const uint64_t Dim, - const uint64_t N_updates, + const uint64_t* Dim_p, + const uint64_t* N_updates_p, const double* Updates, const uint64_t* Updates_index, - const double breakdown, - double* Slater_inv ); + const double* breakdown_p, + double* Slater_inv); #+end_src *** Source @@ -917,14 +964,18 @@ assert(rc == QMCKL_SUCCESS); #include #include "qmckl.h" -qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, - const uint64_t Dim, - const uint64_t N_updates, +qmckl_exit_code qmckl_sherman_morrison_smw32s_c_(const qmckl_context context, + const uint64_t* Dim_p, + const uint64_t* N_updates_p, const double* Updates, const uint64_t* Updates_index, - const double breakdown, + const double* breakdown_p, double * Slater_inv) { + const uint64_t Dim = *Dim_p; + const uint64_t N_updates = *N_updates_p; + const double breakdown = *breakdown_p; + qmckl_exit_code rc; uint64_t n_of_3blocks = N_updates / 3; @@ -950,7 +1001,8 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, } } - if (remainder == 2) { // Apply last remaining block of 2 updates with Woodbury 2x2 kernel + // Apply last remaining block of 2 updates with Woodbury 2x2 kernel + if (remainder == 2) { const double *Updates_2block = &Updates[n_of_3blocks * length_3block]; const uint64_t *Updates_index_2block = &Updates_index[3 * n_of_3blocks]; rc = qmckl_woodbury_2_c_(context, &Dim, Updates_2block, Updates_index_2block, &breakdown, Slater_inv); @@ -961,7 +1013,8 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, later = later + l; } } - else if (remainder == 1) { // Apply last remaining update with slagel_splitting + // Apply last remaining update with slagel_splitting + else if (remainder == 1) { const double *Updates_1block = &Updates[n_of_3blocks * length_3block]; const uint64_t *Updates_index_1block = &Updates_index[3 * n_of_3blocks]; uint64_t l = 0; @@ -971,7 +1024,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, } if (later > 0) { - (void) qmckl_sherman_morrison_splitting_c(context, Dim, later, later_updates, later_index, breakdown, Slater_inv); + (void) qmckl_sherman_morrison_splitting_c_(context, &Dim, &later, later_updates, later_index, &breakdown, Slater_inv); } return QMCKL_SUCCESS; } @@ -991,12 +1044,59 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c(const qmckl_context context, #+CALL: generate_c_interface(table=qmckl_sherman_morrison_smw32s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src f90 :tangle (eval f) :comments org :exports none + integer(c_int32_t) function qmckl_sherman_morrison_smw32s & + (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) & + bind(C) result(info) + + use, intrinsic :: iso_c_binding + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) :: Dim + integer (c_int64_t) , intent(in) :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(in) :: breakdown + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + integer(c_int32_t), external :: qmckl_sherman_morrison_smw32s_c + info = qmckl_sherman_morrison_smw32s_c & + (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) + + end function qmckl_sherman_morrison_smw32s + #+end_src + #+CALL: generate_f_interface(table=qmckl_sherman_morrison_smw32s_args,rettyp=get_value("FRetType"),fname=get_value("Name")) + #+RESULTS: + #+begin_src f90 :tangle (eval fh_func) :comments org :exports none + interface + integer(c_int32_t) function qmckl_sherman_morrison_smw32s & + (context, Dim, N_updates, Updates, Updates_index, breakdown, Slater_inv) & + bind(C) + use, intrinsic :: iso_c_binding + import + implicit none + + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) :: Dim + integer (c_int64_t) , intent(in) :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(in) :: breakdown + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + + end function qmckl_sherman_morrison_smw32s + end interface + #+end_src + *** Test :noexport: #+begin_src c :tangle (eval c_test) -rc = qmckl_sherman_morrison_smw32s_c(context, Dim, N_updates5, Updates5, Updates_index5, breakdown, Slater_inv5_3); +N_updates_p = &N_updates5; +rc = qmckl_sherman_morrison_smw32s(context, Dim_p, N_updates_p, Updates5, Updates_index5, breakdown_p, Slater_inv5_3); for (unsigned int i = 0; i < Dim; i++) { for (unsigned int j = 0; j < Dim; j++) { res[i * Dim + j] = 0; diff --git a/org/table_of_contents b/org/table_of_contents index 7aa7dc6..dfc6f52 100644 --- a/org/table_of_contents +++ b/org/table_of_contents @@ -7,7 +7,6 @@ qmckl_nucleus.org qmckl_electron.org qmckl_ao.org qmckl_jastrow.org -qmckl_mykernel.org qmckl_sherman_morrison_woodbury.org qmckl_distance.org qmckl_utils.org From 0a179be8f35032c96ae2aa3b7bbb49d7c81a1441 Mon Sep 17 00:00:00 2001 From: Francois Coppens Date: Sat, 18 Sep 2021 18:07:05 +0200 Subject: [PATCH 50/50] - Regularised function declarations argument syntax. - Added asserts in test to check for NULL pointers. --- org/qmckl_sherman_morrison_woodbury.org | 81 ++++++++++++++++--------- 1 file changed, 52 insertions(+), 29 deletions(-) diff --git a/org/qmckl_sherman_morrison_woodbury.org b/org/qmckl_sherman_morrison_woodbury.org index ad34d60..cf8f15f 100644 --- a/org/qmckl_sherman_morrison_woodbury.org +++ b/org/qmckl_sherman_morrison_woodbury.org @@ -96,7 +96,7 @@ int main() { double* Slater_inv); #+end_src -*** C source +*** Source #+begin_src c :tangle (eval c) :comments org #include @@ -110,6 +110,7 @@ qmckl_exit_code qmckl_sherman_morrison_c_(const qmckl_context context, const uint64_t* Updates_index, const double* breakdown_p, double* Slater_inv) { + const uint64_t Dim = *Dim_p; const uint64_t N_updates = *N_updates_p; const double breakdown = *breakdown_p; @@ -179,13 +180,13 @@ qmckl_exit_code qmckl_sherman_morrison_c_(const qmckl_context context, use, intrinsic :: iso_c_binding implicit none - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) :: Dim - integer (c_int64_t) , intent(in) :: N_updates - real (c_double ) , intent(in) :: Updates(N_updates*Dim) - integer (c_int64_t) , intent(in) :: Updates_index(N_updates) - real (c_double ) , intent(in) :: breakdown - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) :: Dim + integer (c_int64_t) , intent(in) :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(in) :: breakdown + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) integer(c_int32_t), external :: qmckl_sherman_morrison_c info = qmckl_sherman_morrison_c & @@ -207,13 +208,13 @@ qmckl_exit_code qmckl_sherman_morrison_c_(const qmckl_context context, import implicit none - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) :: Dim - integer (c_int64_t) , intent(in) :: N_updates - real (c_double ) , intent(in) :: Updates(N_updates*Dim) - integer (c_int64_t) , intent(in) :: Updates_index(N_updates) - real (c_double ) , intent(in) :: breakdown - real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(in) :: Dim + integer (c_int64_t) , intent(in) :: N_updates + real (c_double ) , intent(in) :: Updates(N_updates*Dim) + integer (c_int64_t) , intent(in) :: Updates_index(N_updates) + real (c_double ) , intent(in) :: breakdown + real (c_double ) , intent(inout) :: Slater_inv(Dim*Dim) end function qmckl_sherman_morrison end interface @@ -257,14 +258,15 @@ const uint64_t N_updates5 = 5; const uint64_t Updates_index5[5] = {17, 18, 19, 20, 21}; const double Updates5[105] = {-0.026680206879973502, 0.27298007905483301, -0.099715244024992294, -0.1053539039567112, -0.1449181307107206, 0.086803577840328203, -0.13467331603169441, 0.083233945071697304, -0.050348894670605604, 0.113249283283949, -0.18058512732386639, -0.013084722682833599, -0.2101329043507576, 0.29668186604976698, 0.011996015906333896, -0.25581711530685397, -0.18468007631599939, -0.19795016199350388, 0.13754389435052872, 0.066371031105519007, 0.1506568714976311, 0.1407152302563191, -0.035490237176418013, -0.15555772557854669, -0.13084962218999829, -0.065377140417695004, -0.28165902942419097, -0.0038048550486564081, -0.17355462908744812, 0.1904655769467351, 0.1015159860253334, -0.082969114184379605, 0.1009396240115165, 0.25867408514022822, -0.090622015297412997, -0.0261126160621643, -0.0070611685514450073, 0.34575527906417902, 0.1856994293630127, 0.1505507901310916, -0.24748291820287749, -0.1930690407752986, -0.10824421048164369, -0.2003080397844319, -0.050228431820869016, 0.2341227037832137, -0.1714876033365724, 0.32784904539585158, 0.040038149803876807, 0.12709141941741103, -0.088602993637323102, -0.1617441214621064, -0.237361330538988, -0.029239896684885004, 0.039443209767341697, -0.15546871721744498, -0.0127334967255592, -0.093294814229011994, -0.16617536172270789, 0.081297293305397006, -0.11561803519725759, -0.088157065212726496, 0.043941155076026403, -0.043334499001503005, -0.072291933000086989, 0.25947313755750623, -0.00654759816825385, -0.23022028384730242, -0.0992842186242342, -0.059074921417050084, 0.009816635400056898, -0.018885548226535299, 0.28729220479726802, 0.30690228054299934, 0.058271216228604303, 0.050839929841458791, -0.091462507843971003, 0.21059621125459649, -0.19497598148882408, 0.012118805199861502, -0.040971436537802185, -0.0676504261791709, -0.16150601254776081, 0.076545581221580811, -0.44388696737587502, 0.026131823658942982, -0.11532356310635784, 0.038358195684850299, 0.16635001881513747, 0.035624274984002099, 0.039094586856663179, 0.12423532153479717, 0.13070272840559499, 0.027002811431885002, -0.22131750034168385, 0.1172939799726007, -0.034513717517256695, 0.19796614628285178, 0.087915631011128009, 0.1338309701532128, -0.086308442056179102, -0.014136113226413699, 0.06877816375345, 0.11613245680928279, -0.16100704949349121}; const double Slater5[441] = {-2.8945870399475102, 3.5455725193023699, 2.0470812320709202, -3.5464441776275599, -2.0474903583526598, -2.89596366882324, -0.61329728364944502, 0.70991641283035301, 0.45664468407630898, 0.59523195028305098, 0.26079276204109197, -0.027727147564291999, -0.35093706846237199, -0.095610238611698206, -0.130077064037323, 0.10946778208017301, 0.021800471469759899, 0.048480678349733401, -0.092234551906585693, -0.0160505045205355, -0.42026260495185902, -0.78021097183227495, -0.95558542013168302, -0.55174458026885997, -0.95579683780670199, -0.55179446935653698, 0.78044348955154397, -0.115299895405769, -0.11754634231329, -0.0318448171019554, -0.00082233443390577999, 0.064001239836216001, 0.12740932404995001, -0.049412809312343597, -0.074464745819568606, 0.19851659238338501, -0.088878795504569993, 0.135610401630402, -0.13736967742443101, -0.101879440248013, 0.102390937507153, -0.12476679682731601, -0.00527230883017182, 0.00029381641070358499, 0.0072919740341603799, -0.00026352208806201799, 0.0068838247098028703, 0.0047294595278799499, 0.11728889495134399, -0.062190085649490398, -0.15969239175319699, -0.10645916312933, 0.112943567335606, -0.0015487050404772199, -0.045737843960523598, 0.13196058571338701, 0.038660705089569099, -0.050266433507204097, -0.13745591044426, -0.037740666419267703, 0.11781705915927899, 0.19417031109332999, -0.0079971449449658394, -0.30874741077423101, -0.37815779447555498, 0.218254208564758, 0.378139227628708, -0.21839827299118, -0.30879178643226601, 0.025539221242070202, 0.112043909728527, 0.037676706910133403, 0.025347150862216901, -0.19991625845432301, 0.14163509011268599, 0.13326919078826899, 0.213842943310738, 0.131471157073975, 0.14626120030879999, -0.0118067460134625, 0.093547157943248693, 0.22439678013324699, 0.0082425400614738499, 0.0250354297459126, -1.52881526947021, -1.9163775505148799e-05, -2.1623263359069802, -1.5540548702119799e-05, 2.16284847259521, -1.52953028678894, -0.26402890682220498, 0.024944067001342801, -0.37140902876853898, -0.044071510434150703, -0.29843890666961698, -0.043834518641233403, -0.177285701036453, -0.058585006743669503, -0.0183692276477814, -0.026075478643178902, -0.15623773634433699, -0.011319605633616401, 0.054057534784078598, -0.23151709139347099, -0.0016308756312355399, -0.067333526909351293, 0.00043256155913695698, 0.095035225152969402, -0.00043632232700474598, 0.094624765217304202, 0.066768139600753798, 0.14448715746402699, -0.12090456485748299, -0.203432962298393, -0.21472349762916601, 0.154288679361343, 0.017385326325893399, -0.071518480777740506, 0.27918133139610302, 0.080454014241695404, -0.0361245274543762, 0.0566458702087402, -0.030157707631588, 0.25150132179260298, -0.082445412874221802, -0.017600754275918, -2.2779068946838401, -2.3393469746224599e-05, -3.2218937873840301, -1.7939200915861899e-05, 3.22278833389282, -2.2791447639465301, -0.47945570945739702, 0.045197278261184699, -0.64478874206543002, -0.080234304070472703, -0.47389149665832497, 0.024908870458602898, -0.23455648124218001, -0.10695217549800901, -0.033054649829864502, -0.195749551057816, -0.040076982229948002, 0.094596333801746396, 0.098401188850402804, -0.059563819319009802, -0.0045592403039336196, -0.0025739683769643298, -0.0020174346864223502, -0.0024467820767313199, -0.00204527890309691, 0.00013988610589876801, 0.00073755031917244196, 0.17339251935482, 0.099962860345840496, 0.14622049033641801, -0.088966980576515198, 0.040044382214546197, -0.14437201619148299, -1.5416861060657501e-05, -0.081159926950931494, -0.11909016221761699, 0.170753449201584, 0.031124599277973199, -0.052109345793724102, 0.121445283293724, 0.0289684906601906, 0.120766848325729, -0.0043673445470631097, -0.00014539182302542001, 0.0061219600029289696, 0.000189467871678062, 0.0060523007996380303, 0.00425094133242965, 0.0905451029539108, 0.058540407568216303, -0.15191346406936601, 0.11511342227459, 0.15016922354698201, 0.10024280846118901, -0.11066282540559801, -0.15089659392833699, -0.021995550021529201, 0.10021472722291901, 0.019932290539145501, 0.070281185209751101, -0.120184391736984, -0.030551897361874601, 0.10763206332922, -0.0097634727135300602, 0.0119331693276763, -0.0068263513967394803, 0.011701960116624799, -0.0068089049309492103, 0.0095072658732533507, 0.133816182613373, -0.15090283751487699, 0.070243604481220204, 0.077758952975273105, -0.071993313729763003, -0.0526336021721363, -0.033549431711435297, -0.029018172994255999, 0.10475520789623299, 0.047332767397165298, 0.17077720165252699, 0.057527918368577999, -0.043988067656755399, 0.11077278107404701, -0.11803108453750601, -0.71565270423889205, 2.80283820757177e-05, 1.0121610164642301, -2.41986454057042e-05, 1.0123220682144201, 0.71586799621581998, -0.045286595821380601, -0.0269623268395662, 0.0683262273669243, -0.047560662031173699, -0.062597043812274905, -0.0278066452592611, 0.045772761106491103, 0.063010454177856404, 0.0197743345052004, -0.025724532082676901, -0.20542661845684099, -0.0248414911329746, 0.058127623051405002, 0.30385830998420699, -0.0018243347294628601, -0.00073456991231069001, 0.000104061764432117, -0.0010063005611300501, 0.00014142321015242501, 0.00095045292982831597, -0.00064003589795902404, 0.056538689881563201, -0.038196403533220298, 0.095246985554695102, 0.077704243361949907, 0.089713566005229894, 0.071932643651962294, 0.058404259383678402, 0.097089007496833801, -1.8242251826450202e-05, -0.070699930191039997, 0.0231548044830561, 0.036239527165889698, -0.064700096845626803, 0.035663921386003501, 0.140344902873039, -0.0285779368132353, 2.2119384368579599e-07, -0.0404084548354149, 4.62594880445977e-06, 0.040473498404025997, -0.028664523735642398, 0.0818745791912079, -0.0072916029021143896, 0.171691119670868, 0.0142411412671208, 0.227563425898552, 0.20764905214309701, 0.23875248432159399, 0.019401129335165, 0.0041248365305364097, -0.273390233516693, 0.031942136585712398, 0.24207504093647, -0.016599044203758202, 0.0499182641506195, 0.011294623836875, -0.083720728754997295, -0.102523192763329, -0.059237916022539097, -0.10253403335809699, -0.0591498985886574, 0.083691440522670704, 0.093738317489623996, 0.118414394557476, 0.119053602218628, -0.19025875627994501, -0.017257452011108398, 0.111288614571095, -0.14737996459007299, -0.106449924409389, 0.119639433920383, -0.0358475148677826, 0.16083629429340399, -0.135845571756363, -0.045223556458950001, 0.129632458090782, 0.0101170120760798, -0.0016409500967711199, 0.0020083498675376199, 0.0011536112288013101, -0.0019761291332542901, -0.0011378186754882301, -0.0015965295024216199, 0.062009602785110501, -0.085591755807399694, -0.073869466781616197, -0.129948750138283, -0.025633471086621298, 0.092304252088069902, 0.11476875841617599, 0.0570255033671856, -0.098354063928127303, 0.048130486160516697, -0.075562968850135803, -0.087558984756469699, -0.061446368694305399, 0.073952160775661496, -0.030968701466917999, -0.086937576532363905, -5.2227896958356703e-05, -0.12295132130384399, -5.67086790397298e-05, 0.122932203114033, -0.086922481656074496, 0.092386581003665896, 0.0563923679292202, 0.16267444193363201, -0.103307262063026, 0.177027583122253, 0.119934171438217, 0.15235325694084201, -0.13730293512344399, -0.036718469113111503, -0.13380806148052199, -0.14056211709976199, 0.11525499820709199, 0.122316166758537, -0.211628392338753, -0.030221903696656199, -0.71328485012054399, -0.87364697456359897, -0.50431287288665805, -0.87368428707122803, -0.50450080633163497, 0.71341556310653698, -0.0728774294257164, -0.0137394573539495, -0.131415024399757, 0.120499663054943, -0.15048809349536901, 0.067258194088935894, -0.016238121315836899, 0.25341770052909901, 0.061544414609670597, -0.124150305986404, -0.023104058578610399, 0.161576017737389, -0.18417926132678999, -0.016373874619603199, -0.061180751770734801, -0.00358590018004179, -3.1569013572152501e-06, 0.00505110481753945, -1.33700987134944e-05, 0.0050756097771227403, 0.0036168387159705201, 0.076649472117423997, -0.0148532707244158, -0.15424914658069599, -0.031277053058147403, 0.20174449682235701, 0.17827098071575201, -0.21435502171516399, 0.043405968695879003, 0.0060502337291836704, 0.23922684788703899, 0.022777535021305102, 0.22072769701480899, 0.035028267651796299, -0.037091828882694203, -0.054775215685367598, -0.0137155568227172, -0.00072690693195909305, 0.019026592373848, 0.00073597067967057196, 0.018235495314001999, 0.012611641548574, 0.14907942712307001, 0.10721461474895499, -0.205590710043907, 0.18899101018905601, 0.14405034482479101, 0.0080890702083706908, -0.049517802894115399, -0.23817741870880099, -0.062822751700878102, -0.056222390383482, 0.079762905836105305, -0.057780988514423398, -0.208331778645515, -0.11229432374239, 0.0132825700566173, -0.13207408785819999, -0.00012266315752640399, -0.18668732047080999, -0.000116608949610963, 0.18647037446498901, -0.13181127607822399, 0.17992316186428101, 0.0310163982212543, 0.194987177848816, -0.051282022148370701, 0.079243704676628099, -0.16229276359081299, -0.029616238549351699, -0.065854735672473894, -0.025143278762698201, 0.277732163667679, -0.117880158126354, -0.184251189231873, 0.0632317289710045, -0.16761179268360099, 0.0096404440701007808, -0.0068073021247982996, -0.0083365431055426598, 0.0048150913789868398, 0.0083073899149894697, -0.0047997133806347804, -0.0067770029418170504, 0.077614806592464405, 0.12953585386276201, -0.063416801393032102, 0.138088583946228, -0.10224375873804099, 0.130568191409111, 0.164952263236046, 0.026345754042267799, 0.13718618452549, 0.084768116474151597, 0.096043966710567502, -0.054612904787063599, 0.138456135988235, -0.071488708257675199, -0.0153317032381892}; -// WB2+spl: 2,2,1 -double Slater_inv5_1[441] = {-0.054189244668834902, -105.426713929607, -88.458496476283003, 1.5333775291907901, -306.17152423250297, 211.834723659242, 189.348181800731, -164.85602878397, 1001.02895803198, -19.086531171244101, -14.1862411100869, 93.929906236367501, -177.880045125896, -6.7382862272631598, -14.511503830974201, 198.86948709278099, 116.24375034946701, -509.187787693936, -474.82187536023201, 185.49468275501101, -68.704359475869197, 0.066396729468773799, 128.61396390514599, 107.279152808508, -3.2214077352586501, 377.39638500462598, -258.32727230254102, -233.50899542599601, 202.73053181330999, -1222.6711957145401, 23.374193247961198, 17.0231928902612, -115.31992914359, 218.34781344598201, 8.5868800406738099, 17.706454078785399, -244.13052330624399, -142.42769283244499, 622.15335091370196, 579.15535219316803, -228.72024346964599, 85.262861528059901, 0.042977214694503003, -75.818887039648899, -63.4429496117761, 1.89037149893251, -221.440571714557, 152.54192851849001, 136.92110635753301, -119.073716594494, 720.98982202338402, -13.516656591400601, -9.7291496308540406, 67.372278162472895, -128.19425354399101, -4.9638472213270699, -10.200417492010599, 143.31769471617801, 83.615852083439094, -366.86654819753397, -341.426964056759, 133.98241248588599, -50.230799667840699, -0.074440153582489205, 131.003888225851, 110.340015781723, -1.92534262087524, 381.482058581253, -264.51148724341499, -236.035513173862, 204.43864191351099, -1249.3967405711001, 23.404380739562701, 17.427737318703301, -116.737852869633, 221.189913802663, 8.4677080090305399, 17.684126766935599, -247.44394443997601, -145.031902348194, 635.53348480709997, 592.58164589603302, -230.87850923206801, 85.694308069456397, -0.038299262589364599, -74.702005824131604, -63.171412849899497, 1.0859859506457199, -217.148397050222, 150.25957665606299, 134.431598757773, -117.013550651343, 708.34335491195498, -13.4940069422526, -9.5788103819957797, 66.593490547156307, -125.80391712960601, -4.7671091217963504, -10.2632044954116, 140.809682960885, 82.366527572926103, -360.28206877713399, -335.74815599116999, 131.925760239261, -48.660685665615503, -0.060749768867194, 106.92546569584999, 88.790343162838894, -2.6692288353747702, 312.16097467403699, -214.903931604847, -193.215823966269, 167.781122174079, -1018.10641886182, 19.107519450141002, 14.388719322765001, -95.267373183568594, 180.40857560667001, 6.9728512293157801, 14.4102075774752, -201.83015329787199, -117.917199027973, 518.09179195913805, 482.46342773412402, -189.25708821193001, 70.869624357767506, -0.000187411047696029, -11.9846117540694, -9.5726690972884096, 0.23970985157893901, -31.525734707294099, 26.424001662617101, 19.629541977294, -12.8111861333484, 126.186955595279, -0.21994779537689901, -1.75278408990554, 12.699562562401301, -19.050321348645301, 0.28466729039388, -1.07057307471916, 20.675591706275501, 13.1048598424623, -64.121267975873096, -59.394985304548896, 16.918592992744401, -7.70362909966763, 0.00036065684724530402, 12.9068309168011, 12.002712393435401, -0.33194601220397202, 40.326484701927001, -31.878253347415502, -25.170560077575001, 17.9905011861023, -156.05779622500401, 0.28522581276215098, 2.06069522309385, -17.151275363286, 25.397351917205899, 2.08581286823873, 0.91118057859336898, -26.515090998756101, -14.4035822159035, 78.890023885294596, 75.240667711773398, -20.769502289340899, 10.973365712218101, 0.00054214253230406803, -2.29504518628212, -2.1312244512866698, 0.047562978801466302, -10.6318457557031, 3.0591772010668401, 6.6375862982055702, -4.4363733110097296, 16.291945106274301, -0.062929125223047597, -0.16835581689436099, 6.0820271877694996, -5.8351950377758204, 0.35401259185447298, -0.90070453596893996, 6.0382685793059503, 2.4785619931575602, -8.4908203096171402, -8.6197966065449307, 5.8804527059182696, -1.67757738078734, 0.00096800508899916803, -2.4934502646428101, -4.5195305250493698, 0.052900907147883501, -6.5403147654399101, 8.5375829900159896, 4.1350660479474399, -1.63386715634978, 39.5635438458416, -0.11054656518749099, -0.56905231469759199, 10.2311793759502, -8.8014973731182806, -1.42214511908425, -1.9356586876592501, 7.4277556761303396, 2.8985267278915199, -19.981167223464801, -18.310196540769098, 1.3631485584979499, -1.4104996470922699, 0.000167515045034934, 10.6237721447983, 9.6125946891096099, -0.20829092726741699, 28.481388931713699, -22.584157610136199, -17.8392407006579, 11.6781776869203, -110.705963174229, 0.192721307745398, 1.4471736958685699, -11.629464509211299, 19.0388155304672, -0.23390314175395899, 0.62505732559282601, -19.284349111137399, -11.6199046959709, 56.562315732201498, 53.440734762614099, -13.464260193464, 6.5494922727750904, -0.00064712664753083498, 0.51012013976619996, -0.40601608060218902, -0.010304898323864499, -1.9162384482042301, 0.67040773560745603, 1.4195140953666501, 1.89175006728124, 8.4997123797302105, -0.053837688493721801, -0.0081694468687663092, 7.5841687069424202, -3.9864241641726901, 0.82441242748559596, 1.28841942280286, 2.4602644684099202, -0.65833650503714802, -2.93422340475106, -4.7994849299481297, -3.1153746742144999, 0.76509679552570997, -0.00094253467883977896, 4.5884404541075803, 2.5577714145483599, -0.100362327319965, 18.711173319888399, -7.5191542625802104, -11.814804467633101, 7.51205003788884, -36.605280961279099, 0.11460812693040601, 0.498461399643222, -10.903564320961401, 13.2948947844546, -0.64349351510306596, 1.9974412451213299, -11.727821769419799, -4.9603602940684901, 17.916362650168399, 17.291804112001799, -7.9761250950845, 3.6407278735208699, -0.000183321670183587, 6.4691421816769399, 6.0512576241625498, -0.15162968127745899, 23.395366108183801, -14.5381852262701, -14.606223833564799, 10.199271998597199, -73.975176230999594, 0.109352036334604, 0.939662287060122, -5.0493506777824901, 12.432450504307001, 0.66340082972807302, 0.89171490853171798, -14.301193838340501, -7.1767924210601599, 37.417730343433, 34.621199008384998, -12.2257905481279, 5.0337643040644098, 0.00077853683475417402, -4.0437466042030499, -3.2232682351578399, 0.038202731665628202, -12.153196028398099, 6.5027616010011799, 7.2973627140258399, -12.054113026894999, 23.6623418919025, 0.0029087480524890102, -0.465988240269751, -5.8215678299339997, -0.92982871489462304, 0.72875377435640498, -1.76856112702097, 3.9100682853776498, 4.3638012685037904, -12.532035664209801, -10.8596693966264, 12.5729914998231, -1.17795314966104, -0.00047116201805309901, 2.7712702890005598, 1.4259517039641101, -0.060855532638316702, 9.8783846948200704, -5.3156162802238898, -6.24217543532784, 4.0955113938692902, -22.6133771249789, 0.0576846298115802, 0.37261538596098298, -5.69311024324454, 6.6165547759347501, -0.31572322723037299, 1.2076815066994999, -7.13883450856141, -3.0036796657518701, 12.888731168100399, 10.144844547714699, -3.4202567509716602, 2.2424073656324301, 0.00046719815518450402, -6.1786048720593501, -4.9366254575058903, 0.121293000821164, -13.5354546658637, 11.122151465656, 8.2996176249675795, -7.8492497139147304, 53.792699096533298, -0.056207389907105297, -0.72284563910330601, -0.034988476570927102, -5.8914910450597402, -0.57259031868870103, -1.3110690999933601, 8.9888650972260002, 6.8430482968640902, -26.406527264610599, -25.8419474444987, 8.95444342115516, -4.1168180484580699, 0.00068908057573134802, -2.0076563509740999, -3.65231424825159, 0.042894239647239998, -9.7520285174303201, 7.9819862061298199, 6.2214414143151, -1.1841920217922099, 31.911005041941699, -0.080053013664620296, -0.54185675163812796, 8.0781654837979193, -9.3493294125201594, -1.24083642122091, -1.6208022544009499, 8.8607449463367196, 2.3445831189331501, -16.218420387174199, -15.8119148955707, 1.7389982134136399, -1.0509978817476, -3.48584361237575e-05, 0.61330220442703598, 2.33052219623813, -0.0057796507046079101, 5.3801162861110896, -1.7460100802854299, -3.4260231079769401, 1.85323155008146, -1.34565392401789, 0.0020702237459098, 0.147768044797361, -0.43649104760725999, 0.997972495465969, 0.056933085588242997, 0.0077486424610570597, -0.89070134502194598, -0.68148789029708001, 0.89518325797891696, 0.16523545732706499, -2.8298454160600501, 0.26096748561569599, -3.9951230141139501e-05, 2.6625953366596802, 0.159171360187916, -0.0080654609832386693, 14.485659114429501, 0.26188806209423798, -8.9564367313419204, 9.5170929366304993, 3.6594343436186199, 0.017879567938259198, 0.0042052494877241001, -1.4377710841437801, 5.8763150360799203, 0.47441391996743998, -0.014783250610591801, -7.06163381200634, -2.9885184999935599, -1.42889911045556, -2.4433038426403901, -9.8958894810457991, 0.55194555716779503, -5.7250805560848302e-05, 0.98372766353792995, 3.2392588139392098, -0.0119630481344816, 0.14153713576169, -2.73924503033615, 0.060309030316031902, 2.34167965625057, -3.8604817562043001, 0.012593073725828199, 0.22349082635471901, -0.35749918018293803, 2.0835157939561699, 0.13368765195851301, 0.0515445449292352, -2.95655438325227, -1.09680637412728, 2.2418386652533302, 1.2169977713442901, -1.20005576483735, 0.48385142427875799}; -// WB3+splL 3,1,1 -double Slater_inv5_2[441] = {-0.054189244668834902, -105.426713929607, -88.458496476283003, 1.5333775291907901, -306.17152423250297, 211.834723659242, 189.348181800731, -164.85602878397, 1001.02895803198, -19.086531171244101, -14.1862411100869, 93.929906236367501, -177.880045125896, -6.7382862272631598, -14.511503830974201, 198.86948709278099, 116.24375034946701, -509.187787693936, -474.82187536023201, 185.49468275501101, -68.704359475869197, 0.066396729468773799, 128.61396390514599, 107.279152808508, -3.2214077352586501, 377.39638500462598, -258.32727230254102, -233.50899542599601, 202.73053181330999, -1222.6711957145401, 23.374193247961198, 17.0231928902612, -115.31992914359, 218.34781344598201, 8.5868800406738099, 17.706454078785399, -244.13052330624399, -142.42769283244499, 622.15335091370196, 579.15535219316803, -228.72024346964599, 85.262861528059901, 0.042977214694503003, -75.818887039648899, -63.4429496117761, 1.89037149893251, -221.440571714557, 152.54192851849001, 136.92110635753301, -119.073716594494, 720.98982202338402, -13.516656591400601, -9.7291496308540406, 67.372278162472895, -128.19425354399101, -4.9638472213270699, -10.200417492010599, 143.31769471617801, 83.615852083439094, -366.86654819753397, -341.426964056759, 133.98241248588599, -50.230799667840699, -0.074440153582489205, 131.003888225851, 110.340015781723, -1.92534262087524, 381.482058581253, -264.51148724341499, -236.035513173862, 204.43864191351099, -1249.3967405711001, 23.404380739562701, 17.427737318703301, -116.737852869633, 221.189913802663, 8.4677080090305399, 17.684126766935599, -247.44394443997601, -145.031902348194, 635.53348480709997, 592.58164589603302, -230.87850923206801, 85.694308069456397, -0.038299262589364599, -74.702005824131604, -63.171412849899497, 1.0859859506457199, -217.148397050222, 150.25957665606299, 134.431598757773, -117.013550651343, 708.34335491195498, -13.4940069422526, -9.5788103819957797, 66.593490547156307, -125.80391712960601, -4.7671091217963504, -10.2632044954116, 140.809682960885, 82.366527572926103, -360.28206877713399, -335.74815599116999, 131.925760239261, -48.660685665615503, -0.060749768867194, 106.92546569584999, 88.790343162838894, -2.6692288353747702, 312.16097467403699, -214.903931604847, -193.215823966269, 167.781122174079, -1018.10641886182, 19.107519450141002, 14.388719322765001, -95.267373183568594, 180.40857560667001, 6.9728512293157801, 14.4102075774752, -201.83015329787199, -117.917199027973, 518.09179195913805, 482.46342773412402, -189.25708821193001, 70.869624357767506, -0.000187411047696029, -11.9846117540694, -9.5726690972884096, 0.23970985157893901, -31.525734707294099, 26.424001662617101, 19.629541977294, -12.8111861333484, 126.186955595279, -0.21994779537689901, -1.75278408990554, 12.699562562401301, -19.050321348645301, 0.28466729039388, -1.07057307471916, 20.675591706275501, 13.1048598424623, -64.121267975873096, -59.394985304548896, 16.918592992744401, -7.70362909966763, 0.00036065684724530402, 12.9068309168011, 12.002712393435401, -0.33194601220397202, 40.326484701927001, -31.878253347415502, -25.170560077575001, 17.9905011861023, -156.05779622500401, 0.28522581276215098, 2.06069522309385, -17.151275363286, 25.397351917205899, 2.08581286823873, 0.91118057859336898, -26.515090998756101, -14.4035822159035, 78.890023885294596, 75.240667711773398, -20.769502289340899, 10.973365712218101, 0.00054214253230406803, -2.29504518628212, -2.1312244512866698, 0.047562978801466302, -10.6318457557031, 3.0591772010668401, 6.6375862982055702, -4.4363733110097296, 16.291945106274301, -0.062929125223047597, -0.16835581689436099, 6.0820271877694996, -5.8351950377758204, 0.35401259185447298, -0.90070453596893996, 6.0382685793059503, 2.4785619931575602, -8.4908203096171402, -8.6197966065449307, 5.8804527059182696, -1.67757738078734, 0.00096800508899916803, -2.4934502646428101, -4.5195305250493698, 0.052900907147883501, -6.5403147654399101, 8.5375829900159896, 4.1350660479474399, -1.63386715634978, 39.5635438458416, -0.11054656518749099, -0.56905231469759199, 10.2311793759502, -8.8014973731182806, -1.42214511908425, -1.9356586876592501, 7.4277556761303396, 2.8985267278915199, -19.981167223464801, -18.310196540769098, 1.3631485584979499, -1.4104996470922699, 0.000167515045034934, 10.6237721447983, 9.6125946891096099, -0.20829092726741699, 28.481388931713699, -22.584157610136199, -17.8392407006579, 11.6781776869203, -110.705963174229, 0.192721307745398, 1.4471736958685699, -11.629464509211299, 19.0388155304672, -0.23390314175395899, 0.62505732559282601, -19.284349111137399, -11.6199046959709, 56.562315732201498, 53.440734762614099, -13.464260193464, 6.5494922727750904, -0.00064712664753083498, 0.51012013976619996, -0.40601608060218902, -0.010304898323864499, -1.9162384482042301, 0.67040773560745603, 1.4195140953666501, 1.89175006728124, 8.4997123797302105, -0.053837688493721801, -0.0081694468687663092, 7.5841687069424202, -3.9864241641726901, 0.82441242748559596, 1.28841942280286, 2.4602644684099202, -0.65833650503714802, -2.93422340475106, -4.7994849299481297, -3.1153746742144999, 0.76509679552570997, -0.00094253467883977896, 4.5884404541075803, 2.5577714145483599, -0.100362327319965, 18.711173319888399, -7.5191542625802104, -11.814804467633101, 7.51205003788884, -36.605280961279099, 0.11460812693040601, 0.498461399643222, -10.903564320961401, 13.2948947844546, -0.64349351510306596, 1.9974412451213299, -11.727821769419799, -4.9603602940684901, 17.916362650168399, 17.291804112001799, -7.9761250950845, 3.6407278735208699, -0.000183321670183587, 6.4691421816769399, 6.0512576241625498, -0.15162968127745899, 23.395366108183801, -14.5381852262701, -14.606223833564799, 10.199271998597199, -73.975176230999594, 0.109352036334604, 0.939662287060122, -5.0493506777824901, 12.432450504307001, 0.66340082972807302, 0.89171490853171798, -14.301193838340501, -7.1767924210601599, 37.417730343433, 34.621199008384998, -12.2257905481279, 5.0337643040644098, 0.00077853683475417402, -4.0437466042030499, -3.2232682351578399, 0.038202731665628202, -12.153196028398099, 6.5027616010011799, 7.2973627140258399, -12.054113026894999, 23.6623418919025, 0.0029087480524890102, -0.465988240269751, -5.8215678299339997, -0.92982871489462304, 0.72875377435640498, -1.76856112702097, 3.9100682853776498, 4.3638012685037904, -12.532035664209801, -10.8596693966264, 12.5729914998231, -1.17795314966104, -0.00047116201805309901, 2.7712702890005598, 1.4259517039641101, -0.060855532638316702, 9.8783846948200704, -5.3156162802238898, -6.24217543532784, 4.0955113938692902, -22.6133771249789, 0.0576846298115802, 0.37261538596098298, -5.69311024324454, 6.6165547759347501, -0.31572322723037299, 1.2076815066994999, -7.13883450856141, -3.0036796657518701, 12.888731168100399, 10.144844547714699, -3.4202567509716602, 2.2424073656324301, 0.00046719815518450402, -6.1786048720593501, -4.9366254575058903, 0.121293000821164, -13.5354546658637, 11.122151465656, 8.2996176249675795, -7.8492497139147304, 53.792699096533298, -0.056207389907105297, -0.72284563910330601, -0.034988476570927102, -5.8914910450597402, -0.57259031868870103, -1.3110690999933601, 8.9888650972260002, 6.8430482968640902, -26.406527264610599, -25.8419474444987, 8.95444342115516, -4.1168180484580699, 0.00068908057573134802, -2.0076563509740999, -3.65231424825159, 0.042894239647239998, -9.7520285174303201, 7.9819862061298199, 6.2214414143151, -1.1841920217922099, 31.911005041941699, -0.080053013664620296, -0.54185675163812796, 8.0781654837979193, -9.3493294125201594, -1.24083642122091, -1.6208022544009499, 8.8607449463367196, 2.3445831189331501, -16.218420387174199, -15.8119148955707, 1.7389982134136399, -1.0509978817476, -3.48584361237575e-05, 0.61330220442703598, 2.33052219623813, -0.0057796507046079101, 5.3801162861110896, -1.7460100802854299, -3.4260231079769401, 1.85323155008146, -1.34565392401789, 0.0020702237459098, 0.147768044797361, -0.43649104760725999, 0.997972495465969, 0.056933085588242997, 0.0077486424610570597, -0.89070134502194598, -0.68148789029708001, 0.89518325797891696, 0.16523545732706499, -2.8298454160600501, 0.26096748561569599, -3.9951230141139501e-05, 2.6625953366596802, 0.159171360187916, -0.0080654609832386693, 14.485659114429501, 0.26188806209423798, -8.9564367313419204, 9.5170929366304993, 3.6594343436186199, 0.017879567938259198, 0.0042052494877241001, -1.4377710841437801, 5.8763150360799203, 0.47441391996743998, -0.014783250610591801, -7.06163381200634, -2.9885184999935599, -1.42889911045556, -2.4433038426403901, -9.8958894810457991, 0.55194555716779503, -5.7250805560848302e-05, 0.98372766353792995, 3.2392588139392098, -0.0119630481344816, 0.14153713576169, -2.73924503033615, 0.060309030316031902, 2.34167965625057, -3.8604817562043001, 0.012593073725828199, 0.22349082635471901, -0.35749918018293803, 2.0835157939561699, 0.13368765195851301, 0.0515445449292352, -2.95655438325227, -1.09680637412728, 2.2418386652533302, 1.2169977713442901, -1.20005576483735, 0.48385142427875799}; -// WB3,2+spl: 3,2 -double Slater_inv5_3[441] = {-0.054189244668834902, -105.426713929607, -88.458496476283003, 1.5333775291907901, -306.17152423250297, 211.834723659242, 189.348181800731, -164.85602878397, 1001.02895803198, -19.086531171244101, -14.1862411100869, 93.929906236367501, -177.880045125896, -6.7382862272631598, -14.511503830974201, 198.86948709278099, 116.24375034946701, -509.187787693936, -474.82187536023201, 185.49468275501101, -68.704359475869197, 0.066396729468773799, 128.61396390514599, 107.279152808508, -3.2214077352586501, 377.39638500462598, -258.32727230254102, -233.50899542599601, 202.73053181330999, -1222.6711957145401, 23.374193247961198, 17.0231928902612, -115.31992914359, 218.34781344598201, 8.5868800406738099, 17.706454078785399, -244.13052330624399, -142.42769283244499, 622.15335091370196, 579.15535219316803, -228.72024346964599, 85.262861528059901, 0.042977214694503003, -75.818887039648899, -63.4429496117761, 1.89037149893251, -221.440571714557, 152.54192851849001, 136.92110635753301, -119.073716594494, 720.98982202338402, -13.516656591400601, -9.7291496308540406, 67.372278162472895, -128.19425354399101, -4.9638472213270699, -10.200417492010599, 143.31769471617801, 83.615852083439094, -366.86654819753397, -341.426964056759, 133.98241248588599, -50.230799667840699, -0.074440153582489205, 131.003888225851, 110.340015781723, -1.92534262087524, 381.482058581253, -264.51148724341499, -236.035513173862, 204.43864191351099, -1249.3967405711001, 23.404380739562701, 17.427737318703301, -116.737852869633, 221.189913802663, 8.4677080090305399, 17.684126766935599, -247.44394443997601, -145.031902348194, 635.53348480709997, 592.58164589603302, -230.87850923206801, 85.694308069456397, -0.038299262589364599, -74.702005824131604, -63.171412849899497, 1.0859859506457199, -217.148397050222, 150.25957665606299, 134.431598757773, -117.013550651343, 708.34335491195498, -13.4940069422526, -9.5788103819957797, 66.593490547156307, -125.80391712960601, -4.7671091217963504, -10.2632044954116, 140.809682960885, 82.366527572926103, -360.28206877713399, -335.74815599116999, 131.925760239261, -48.660685665615503, -0.060749768867194, 106.92546569584999, 88.790343162838894, -2.6692288353747702, 312.16097467403699, -214.903931604847, -193.215823966269, 167.781122174079, -1018.10641886182, 19.107519450141002, 14.388719322765001, -95.267373183568594, 180.40857560667001, 6.9728512293157801, 14.4102075774752, -201.83015329787199, -117.917199027973, 518.09179195913805, 482.46342773412402, -189.25708821193001, 70.869624357767506, -0.000187411047696029, -11.9846117540694, -9.5726690972884096, 0.23970985157893901, -31.525734707294099, 26.424001662617101, 19.629541977294, -12.8111861333484, 126.186955595279, -0.21994779537689901, -1.75278408990554, 12.699562562401301, -19.050321348645301, 0.28466729039388, -1.07057307471916, 20.675591706275501, 13.1048598424623, -64.121267975873096, -59.394985304548896, 16.918592992744401, -7.70362909966763, 0.00036065684724530402, 12.9068309168011, 12.002712393435401, -0.33194601220397202, 40.326484701927001, -31.878253347415502, -25.170560077575001, 17.9905011861023, -156.05779622500401, 0.28522581276215098, 2.06069522309385, -17.151275363286, 25.397351917205899, 2.08581286823873, 0.91118057859336898, -26.515090998756101, -14.4035822159035, 78.890023885294596, 75.240667711773398, -20.769502289340899, 10.973365712218101, 0.00054214253230406803, -2.29504518628212, -2.1312244512866698, 0.047562978801466302, -10.6318457557031, 3.0591772010668401, 6.6375862982055702, -4.4363733110097296, 16.291945106274301, -0.062929125223047597, -0.16835581689436099, 6.0820271877694996, -5.8351950377758204, 0.35401259185447298, -0.90070453596893996, 6.0382685793059503, 2.4785619931575602, -8.4908203096171402, -8.6197966065449307, 5.8804527059182696, -1.67757738078734, 0.00096800508899916803, -2.4934502646428101, -4.5195305250493698, 0.052900907147883501, -6.5403147654399101, 8.5375829900159896, 4.1350660479474399, -1.63386715634978, 39.5635438458416, -0.11054656518749099, -0.56905231469759199, 10.2311793759502, -8.8014973731182806, -1.42214511908425, -1.9356586876592501, 7.4277556761303396, 2.8985267278915199, -19.981167223464801, -18.310196540769098, 1.3631485584979499, -1.4104996470922699, 0.000167515045034934, 10.6237721447983, 9.6125946891096099, -0.20829092726741699, 28.481388931713699, -22.584157610136199, -17.8392407006579, 11.6781776869203, -110.705963174229, 0.192721307745398, 1.4471736958685699, -11.629464509211299, 19.0388155304672, -0.23390314175395899, 0.62505732559282601, -19.284349111137399, -11.6199046959709, 56.562315732201498, 53.440734762614099, -13.464260193464, 6.5494922727750904, -0.00064712664753083498, 0.51012013976619996, -0.40601608060218902, -0.010304898323864499, -1.9162384482042301, 0.67040773560745603, 1.4195140953666501, 1.89175006728124, 8.4997123797302105, -0.053837688493721801, -0.0081694468687663092, 7.5841687069424202, -3.9864241641726901, 0.82441242748559596, 1.28841942280286, 2.4602644684099202, -0.65833650503714802, -2.93422340475106, -4.7994849299481297, -3.1153746742144999, 0.76509679552570997, -0.00094253467883977896, 4.5884404541075803, 2.5577714145483599, -0.100362327319965, 18.711173319888399, -7.5191542625802104, -11.814804467633101, 7.51205003788884, -36.605280961279099, 0.11460812693040601, 0.498461399643222, -10.903564320961401, 13.2948947844546, -0.64349351510306596, 1.9974412451213299, -11.727821769419799, -4.9603602940684901, 17.916362650168399, 17.291804112001799, -7.9761250950845, 3.6407278735208699, -0.000183321670183587, 6.4691421816769399, 6.0512576241625498, -0.15162968127745899, 23.395366108183801, -14.5381852262701, -14.606223833564799, 10.199271998597199, -73.975176230999594, 0.109352036334604, 0.939662287060122, -5.0493506777824901, 12.432450504307001, 0.66340082972807302, 0.89171490853171798, -14.301193838340501, -7.1767924210601599, 37.417730343433, 34.621199008384998, -12.2257905481279, 5.0337643040644098, 0.00077853683475417402, -4.0437466042030499, -3.2232682351578399, 0.038202731665628202, -12.153196028398099, 6.5027616010011799, 7.2973627140258399, -12.054113026894999, 23.6623418919025, 0.0029087480524890102, -0.465988240269751, -5.8215678299339997, -0.92982871489462304, 0.72875377435640498, -1.76856112702097, 3.9100682853776498, 4.3638012685037904, -12.532035664209801, -10.8596693966264, 12.5729914998231, -1.17795314966104, -0.00047116201805309901, 2.7712702890005598, 1.4259517039641101, -0.060855532638316702, 9.8783846948200704, -5.3156162802238898, -6.24217543532784, 4.0955113938692902, -22.6133771249789, 0.0576846298115802, 0.37261538596098298, -5.69311024324454, 6.6165547759347501, -0.31572322723037299, 1.2076815066994999, -7.13883450856141, -3.0036796657518701, 12.888731168100399, 10.144844547714699, -3.4202567509716602, 2.2424073656324301, 0.00046719815518450402, -6.1786048720593501, -4.9366254575058903, 0.121293000821164, -13.5354546658637, 11.122151465656, 8.2996176249675795, -7.8492497139147304, 53.792699096533298, -0.056207389907105297, -0.72284563910330601, -0.034988476570927102, -5.8914910450597402, -0.57259031868870103, -1.3110690999933601, 8.9888650972260002, 6.8430482968640902, -26.406527264610599, -25.8419474444987, 8.95444342115516, -4.1168180484580699, 0.00068908057573134802, -2.0076563509740999, -3.65231424825159, 0.042894239647239998, -9.7520285174303201, 7.9819862061298199, 6.2214414143151, -1.1841920217922099, 31.911005041941699, -0.080053013664620296, -0.54185675163812796, 8.0781654837979193, -9.3493294125201594, -1.24083642122091, -1.6208022544009499, 8.8607449463367196, 2.3445831189331501, -16.218420387174199, -15.8119148955707, 1.7389982134136399, -1.0509978817476, -3.48584361237575e-05, 0.61330220442703598, 2.33052219623813, -0.0057796507046079101, 5.3801162861110896, -1.7460100802854299, -3.4260231079769401, 1.85323155008146, -1.34565392401789, 0.0020702237459098, 0.147768044797361, -0.43649104760725999, 0.997972495465969, 0.056933085588242997, 0.0077486424610570597, -0.89070134502194598, -0.68148789029708001, 0.89518325797891696, 0.16523545732706499, -2.8298454160600501, 0.26096748561569599, -3.9951230141139501e-05, 2.6625953366596802, 0.159171360187916, -0.0080654609832386693, 14.485659114429501, 0.26188806209423798, -8.9564367313419204, 9.5170929366304993, 3.6594343436186199, 0.017879567938259198, 0.0042052494877241001, -1.4377710841437801, 5.8763150360799203, 0.47441391996743998, -0.014783250610591801, -7.06163381200634, -2.9885184999935599, -1.42889911045556, -2.4433038426403901, -9.8958894810457991, 0.55194555716779503, -5.7250805560848302e-05, 0.98372766353792995, 3.2392588139392098, -0.0119630481344816, 0.14153713576169, -2.73924503033615, 0.060309030316031902, 2.34167965625057, -3.8604817562043001, 0.012593073725828199, 0.22349082635471901, -0.35749918018293803, 2.0835157939561699, 0.13368765195851301, 0.0515445449292352, -2.95655438325227, -1.09680637412728, 2.2418386652533302, 1.2169977713442901, -1.20005576483735, 0.48385142427875799}; +double Slater_inv5[441] = {-0.054189244668834902, -105.426713929607, -88.458496476283003, 1.5333775291907901, -306.17152423250297, 211.834723659242, 189.348181800731, -164.85602878397, 1001.02895803198, -19.086531171244101, -14.1862411100869, 93.929906236367501, -177.880045125896, -6.7382862272631598, -14.511503830974201, 198.86948709278099, 116.24375034946701, -509.187787693936, -474.82187536023201, 185.49468275501101, -68.704359475869197, 0.066396729468773799, 128.61396390514599, 107.279152808508, -3.2214077352586501, 377.39638500462598, -258.32727230254102, -233.50899542599601, 202.73053181330999, -1222.6711957145401, 23.374193247961198, 17.0231928902612, -115.31992914359, 218.34781344598201, 8.5868800406738099, 17.706454078785399, -244.13052330624399, -142.42769283244499, 622.15335091370196, 579.15535219316803, -228.72024346964599, 85.262861528059901, 0.042977214694503003, -75.818887039648899, -63.4429496117761, 1.89037149893251, -221.440571714557, 152.54192851849001, 136.92110635753301, -119.073716594494, 720.98982202338402, -13.516656591400601, -9.7291496308540406, 67.372278162472895, -128.19425354399101, -4.9638472213270699, -10.200417492010599, 143.31769471617801, 83.615852083439094, -366.86654819753397, -341.426964056759, 133.98241248588599, -50.230799667840699, -0.074440153582489205, 131.003888225851, 110.340015781723, -1.92534262087524, 381.482058581253, -264.51148724341499, -236.035513173862, 204.43864191351099, -1249.3967405711001, 23.404380739562701, 17.427737318703301, -116.737852869633, 221.189913802663, 8.4677080090305399, 17.684126766935599, -247.44394443997601, -145.031902348194, 635.53348480709997, 592.58164589603302, -230.87850923206801, 85.694308069456397, -0.038299262589364599, -74.702005824131604, -63.171412849899497, 1.0859859506457199, -217.148397050222, 150.25957665606299, 134.431598757773, -117.013550651343, 708.34335491195498, -13.4940069422526, -9.5788103819957797, 66.593490547156307, -125.80391712960601, -4.7671091217963504, -10.2632044954116, 140.809682960885, 82.366527572926103, -360.28206877713399, -335.74815599116999, 131.925760239261, -48.660685665615503, -0.060749768867194, 106.92546569584999, 88.790343162838894, -2.6692288353747702, 312.16097467403699, -214.903931604847, -193.215823966269, 167.781122174079, -1018.10641886182, 19.107519450141002, 14.388719322765001, -95.267373183568594, 180.40857560667001, 6.9728512293157801, 14.4102075774752, -201.83015329787199, -117.917199027973, 518.09179195913805, 482.46342773412402, -189.25708821193001, 70.869624357767506, -0.000187411047696029, -11.9846117540694, -9.5726690972884096, 0.23970985157893901, -31.525734707294099, 26.424001662617101, 19.629541977294, -12.8111861333484, 126.186955595279, -0.21994779537689901, -1.75278408990554, 12.699562562401301, -19.050321348645301, 0.28466729039388, -1.07057307471916, 20.675591706275501, 13.1048598424623, -64.121267975873096, -59.394985304548896, 16.918592992744401, -7.70362909966763, 0.00036065684724530402, 12.9068309168011, 12.002712393435401, -0.33194601220397202, 40.326484701927001, -31.878253347415502, -25.170560077575001, 17.9905011861023, -156.05779622500401, 0.28522581276215098, 2.06069522309385, -17.151275363286, 25.397351917205899, 2.08581286823873, 0.91118057859336898, -26.515090998756101, -14.4035822159035, 78.890023885294596, 75.240667711773398, -20.769502289340899, 10.973365712218101, 0.00054214253230406803, -2.29504518628212, -2.1312244512866698, 0.047562978801466302, -10.6318457557031, 3.0591772010668401, 6.6375862982055702, -4.4363733110097296, 16.291945106274301, -0.062929125223047597, -0.16835581689436099, 6.0820271877694996, -5.8351950377758204, 0.35401259185447298, -0.90070453596893996, 6.0382685793059503, 2.4785619931575602, -8.4908203096171402, -8.6197966065449307, 5.8804527059182696, -1.67757738078734, 0.00096800508899916803, -2.4934502646428101, -4.5195305250493698, 0.052900907147883501, -6.5403147654399101, 8.5375829900159896, 4.1350660479474399, -1.63386715634978, 39.5635438458416, -0.11054656518749099, -0.56905231469759199, 10.2311793759502, -8.8014973731182806, -1.42214511908425, -1.9356586876592501, 7.4277556761303396, 2.8985267278915199, -19.981167223464801, -18.310196540769098, 1.3631485584979499, -1.4104996470922699, 0.000167515045034934, 10.6237721447983, 9.6125946891096099, -0.20829092726741699, 28.481388931713699, -22.584157610136199, -17.8392407006579, 11.6781776869203, -110.705963174229, 0.192721307745398, 1.4471736958685699, -11.629464509211299, 19.0388155304672, -0.23390314175395899, 0.62505732559282601, -19.284349111137399, -11.6199046959709, 56.562315732201498, 53.440734762614099, -13.464260193464, 6.5494922727750904, -0.00064712664753083498, 0.51012013976619996, -0.40601608060218902, -0.010304898323864499, -1.9162384482042301, 0.67040773560745603, 1.4195140953666501, 1.89175006728124, 8.4997123797302105, -0.053837688493721801, -0.0081694468687663092, 7.5841687069424202, -3.9864241641726901, 0.82441242748559596, 1.28841942280286, 2.4602644684099202, -0.65833650503714802, -2.93422340475106, -4.7994849299481297, -3.1153746742144999, 0.76509679552570997, -0.00094253467883977896, 4.5884404541075803, 2.5577714145483599, -0.100362327319965, 18.711173319888399, -7.5191542625802104, -11.814804467633101, 7.51205003788884, -36.605280961279099, 0.11460812693040601, 0.498461399643222, -10.903564320961401, 13.2948947844546, -0.64349351510306596, 1.9974412451213299, -11.727821769419799, -4.9603602940684901, 17.916362650168399, 17.291804112001799, -7.9761250950845, 3.6407278735208699, -0.000183321670183587, 6.4691421816769399, 6.0512576241625498, -0.15162968127745899, 23.395366108183801, -14.5381852262701, -14.606223833564799, 10.199271998597199, -73.975176230999594, 0.109352036334604, 0.939662287060122, -5.0493506777824901, 12.432450504307001, 0.66340082972807302, 0.89171490853171798, -14.301193838340501, -7.1767924210601599, 37.417730343433, 34.621199008384998, -12.2257905481279, 5.0337643040644098, 0.00077853683475417402, -4.0437466042030499, -3.2232682351578399, 0.038202731665628202, -12.153196028398099, 6.5027616010011799, 7.2973627140258399, -12.054113026894999, 23.6623418919025, 0.0029087480524890102, -0.465988240269751, -5.8215678299339997, -0.92982871489462304, 0.72875377435640498, -1.76856112702097, 3.9100682853776498, 4.3638012685037904, -12.532035664209801, -10.8596693966264, 12.5729914998231, -1.17795314966104, -0.00047116201805309901, 2.7712702890005598, 1.4259517039641101, -0.060855532638316702, 9.8783846948200704, -5.3156162802238898, -6.24217543532784, 4.0955113938692902, -22.6133771249789, 0.0576846298115802, 0.37261538596098298, -5.69311024324454, 6.6165547759347501, -0.31572322723037299, 1.2076815066994999, -7.13883450856141, -3.0036796657518701, 12.888731168100399, 10.144844547714699, -3.4202567509716602, 2.2424073656324301, 0.00046719815518450402, -6.1786048720593501, -4.9366254575058903, 0.121293000821164, -13.5354546658637, 11.122151465656, 8.2996176249675795, -7.8492497139147304, 53.792699096533298, -0.056207389907105297, -0.72284563910330601, -0.034988476570927102, -5.8914910450597402, -0.57259031868870103, -1.3110690999933601, 8.9888650972260002, 6.8430482968640902, -26.406527264610599, -25.8419474444987, 8.95444342115516, -4.1168180484580699, 0.00068908057573134802, -2.0076563509740999, -3.65231424825159, 0.042894239647239998, -9.7520285174303201, 7.9819862061298199, 6.2214414143151, -1.1841920217922099, 31.911005041941699, -0.080053013664620296, -0.54185675163812796, 8.0781654837979193, -9.3493294125201594, -1.24083642122091, -1.6208022544009499, 8.8607449463367196, 2.3445831189331501, -16.218420387174199, -15.8119148955707, 1.7389982134136399, -1.0509978817476, -3.48584361237575e-05, 0.61330220442703598, 2.33052219623813, -0.0057796507046079101, 5.3801162861110896, -1.7460100802854299, -3.4260231079769401, 1.85323155008146, -1.34565392401789, 0.0020702237459098, 0.147768044797361, -0.43649104760725999, 0.997972495465969, 0.056933085588242997, 0.0077486424610570597, -0.89070134502194598, -0.68148789029708001, 0.89518325797891696, 0.16523545732706499, -2.8298454160600501, 0.26096748561569599, -3.9951230141139501e-05, 2.6625953366596802, 0.159171360187916, -0.0080654609832386693, 14.485659114429501, 0.26188806209423798, -8.9564367313419204, 9.5170929366304993, 3.6594343436186199, 0.017879567938259198, 0.0042052494877241001, -1.4377710841437801, 5.8763150360799203, 0.47441391996743998, -0.014783250610591801, -7.06163381200634, -2.9885184999935599, -1.42889911045556, -2.4433038426403901, -9.8958894810457991, 0.55194555716779503, -5.7250805560848302e-05, 0.98372766353792995, 3.2392588139392098, -0.0119630481344816, 0.14153713576169, -2.73924503033615, 0.060309030316031902, 2.34167965625057, -3.8604817562043001, 0.012593073725828199, 0.22349082635471901, -0.35749918018293803, 2.0835157939561699, 0.13368765195851301, 0.0515445449292352, -2.95655438325227, -1.09680637412728, 2.2418386652533302, 1.2169977713442901, -1.20005576483735, 0.48385142427875799}; N_updates_p = &N_updates1; +assert(Dim_p != NULL); +assert(N_updates_p != NULL); +assert(Updates1 != NULL); +assert(Updates_index1 != NULL); +assert(breakdown_p != NULL); +assert(Slater_inv1 != NULL); rc = qmckl_sherman_morrison(context, Dim_p, N_updates_p, Updates1, Updates_index1, breakdown_p, Slater_inv1); for (unsigned int i = 0; i < Dim; i++) { for (unsigned int j = 0; j < Dim; j++) { @@ -355,7 +357,7 @@ qmckl_exit_code qmckl_woodbury_2_c_(const qmckl_context context, const double* Updates, const uint64_t* Updates_index, const double* breakdown_p, - double * Slater_inv) { + double* Slater_inv) { /* C := S^{-1} * U, dim x 2 B := 1 + V * C, 2 x 2 @@ -483,7 +485,11 @@ qmckl_exit_code qmckl_woodbury_2_c_(const qmckl_context context, *** Test :noexport: #+begin_src c :tangle (eval c_test) - +assert(Dim_p != NULL); +assert(Updates2 != NULL); +assert(Updates_index2 != NULL); +assert(breakdown_p != NULL); +assert(Slater_inv2 != NULL); rc = qmckl_woodbury_2(context, Dim_p, Updates2, Updates_index2, breakdown_p, Slater_inv2); for (unsigned int i = 0; i < Dim; i++) { for (unsigned int j = 0; j < Dim; j++) { @@ -568,7 +574,7 @@ qmckl_exit_code qmckl_woodbury_3_c_(const qmckl_context context, const double* Updates, const uint64_t* Updates_index, const double* breakdown_p, - double * Slater_inv) { + double* Slater_inv) { /* C := S^{-1} * U, dim x 3 B := 1 + V * C, 3 x 3 @@ -711,6 +717,11 @@ qmckl_exit_code qmckl_woodbury_3_c_(const qmckl_context context, *** Test :noexport: #+begin_src c :tangle (eval c_test) +assert(Dim_p != NULL); +assert(Updates3 != NULL); +assert(Updates_index3 != NULL); +assert(breakdown_p != NULL); +assert(Slater_inv3_1 != NULL); rc = qmckl_woodbury_3(context, Dim_p, Updates3, Updates_index3, breakdown_p, Slater_inv3_1); for (unsigned int i = 0; i < Dim; i++) { for (unsigned int j = 0; j < Dim; j++) { @@ -801,7 +812,7 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c_(const qmckl_context context, const double* Updates, const uint64_t* Updates_index, const double* breakdown, - double * Slater_inv) { + double* Slater_inv) { double later_updates[*Dim * *N_updates]; uint64_t later_index[*N_updates]; @@ -885,6 +896,12 @@ qmckl_exit_code qmckl_sherman_morrison_splitting_c_(const qmckl_context context, #+begin_src c :tangle (eval c_test) N_updates_p = &N_updates3; +assert(Dim_p != NULL); +assert(N_updates_p != NULL); +assert(Updates3 != NULL); +assert(Updates_index3 != NULL); +assert(breakdown_p != NULL); +assert(Slater_inv3_2 != NULL); rc = qmckl_sherman_morrison_splitting(context, Dim_p, N_updates_p, Updates3, Updates_index3, breakdown_p, Slater_inv3_2); for (unsigned int i = 0; i < Dim; i++) { for (unsigned int j = 0; j < Dim; j++) { @@ -970,7 +987,7 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c_(const qmckl_context context, const double* Updates, const uint64_t* Updates_index, const double* breakdown_p, - double * Slater_inv) { + double* Slater_inv) { const uint64_t Dim = *Dim_p; const uint64_t N_updates = *N_updates_p; @@ -1096,12 +1113,18 @@ qmckl_exit_code qmckl_sherman_morrison_smw32s_c_(const qmckl_context context, #+begin_src c :tangle (eval c_test) N_updates_p = &N_updates5; -rc = qmckl_sherman_morrison_smw32s(context, Dim_p, N_updates_p, Updates5, Updates_index5, breakdown_p, Slater_inv5_3); +assert(Dim_p != NULL); +assert(N_updates_p != NULL); +assert(Updates5 != NULL); +assert(Updates_index5 != NULL); +assert(breakdown_p != NULL); +assert(Slater_inv5 != NULL); +rc = qmckl_sherman_morrison_smw32s(context, Dim_p, N_updates_p, Updates5, Updates_index5, breakdown_p, Slater_inv5); for (unsigned int i = 0; i < Dim; i++) { for (unsigned int j = 0; j < Dim; j++) { res[i * Dim + j] = 0; for (unsigned int k = 0; k < Dim; k++) { - res[i * Dim + j] += Slater5[i * Dim + k] * Slater_inv5_3[k * Dim + j]; + res[i * Dim + j] += Slater5[i * Dim + k] * Slater_inv5[k * Dim + j]; } } } @@ -1275,8 +1298,8 @@ with Sherman-Morrison and update splitting. Please look at the performance recco #+begin_src c :comments link :tangle (eval c_test) assert (qmckl_context_destroy(context) == QMCKL_SUCCESS); return 0; + } - #+end_src # -*- mode: org -*-