From 1a5b76157bde47f0973fd8b9297b74bcdb741463 Mon Sep 17 00:00:00 2001 From: Anthony Scemama Date: Thu, 24 Feb 2022 19:06:19 +0100 Subject: [PATCH 01/11] Updated documentation --- org/qmckl_ao.org | 22 ++--- org/qmckl_blas.org | 193 ++++++++++++++++++++++++++++++++---------- org/qmckl_context.org | 70 ++++++++------- org/qmckl_error.org | 61 +++++++------ 4 files changed, 234 insertions(+), 112 deletions(-) diff --git a/org/qmckl_ao.org b/org/qmckl_ao.org index 55057bd..28aab78 100644 --- a/org/qmckl_ao.org +++ b/org/qmckl_ao.org @@ -5428,17 +5428,17 @@ qmckl_compute_ao_vgl_hpc_gaussian ( const int32_t n = lstart[l+1]-lstart[l]; const int64_t k = ao_index[ishell]; - double* const ao_vgl_1 = &(ao_vgl[ipoint*5*ao_num+k]); - double* const ao_vgl_2 = &(ao_vgl_1[ ao_num]); - double* const ao_vgl_3 = &(ao_vgl_1[2*ao_num]); - double* const ao_vgl_4 = &(ao_vgl_1[3*ao_num]); - double* const ao_vgl_5 = &(ao_vgl_1[4*ao_num]); + double* __restrict__ const ao_vgl_1 = &(ao_vgl[ipoint*5*ao_num+k]); + double* __restrict__ const ao_vgl_2 = &(ao_vgl_1[ ao_num]); + double* __restrict__ const ao_vgl_3 = &(ao_vgl_1[2*ao_num]); + double* __restrict__ const ao_vgl_4 = &(ao_vgl_1[3*ao_num]); + double* __restrict__ const ao_vgl_5 = &(ao_vgl_1[4*ao_num]); - double* poly_vgl_1; - double* poly_vgl_2; - double* poly_vgl_3; - double* poly_vgl_4; - double* poly_vgl_5; + double* __restrict__ poly_vgl_1; + double* __restrict__ poly_vgl_2; + double* __restrict__ poly_vgl_3; + double* __restrict__ poly_vgl_4; + double* __restrict__ poly_vgl_5; if (nidx > 0) { const double* f = &(ao_factor[k]); const int64_t idx = lstart[l]; @@ -5473,6 +5473,7 @@ qmckl_compute_ao_vgl_hpc_gaussian ( poly_vgl_3 = &(poly_vgl_l2[2][idx]); poly_vgl_4 = &(poly_vgl_l2[3][idx]); poly_vgl_5 = &(poly_vgl_l2[4][idx]); + for (int64_t il=0 ; il + for (int i=0 ; i<15 ; ++i) { + printf("%f %f\n", cnew[i], c[i]); + assert (c[i] == cnew[i]); + } +} + #+end_src ** ~qmckl_adjugate~ Given a matrix $\mathbf{A}$, the adjugate matrix @@ -1208,7 +1313,7 @@ qmckl_matmul (const qmckl_context context, for performance motivations. For larger sizes, we rely on the LAPACK library. - #+begin_src f90 :tangle (eval f) + #+begin_src f90 :tangle (eval f) :exports none integer function qmckl_adjugate_f(context, na, A, LDA, B, ldb, det_l) & result(info) use qmckl @@ -1263,7 +1368,7 @@ integer function qmckl_adjugate_f(context, na, A, LDA, B, ldb, det_l) & end function qmckl_adjugate_f #+end_src - + #+begin_src f90 :tangle (eval f) :exports none subroutine adjugate2(A,LDA,B,LDB,na,det_l) implicit none @@ -2047,11 +2152,11 @@ assert(QMCKL_SUCCESS == test_qmckl_adjugate(context)); Transposes a matrix: $A^\dagger_{ji} = A_{ij}$. - | Variable | Type | In/Out | Description | - |----------+---------------+--------+-------------------| - | context | qmckl_context | in | Global state | - | A | qmckl_matrix | in | Input matrix | - | At | qmckl_matrix | out | Transposed matrix | + | Variable | Type | In/Out | Description | + |-----------+-----------------+--------+-------------------| + | ~context~ | ~qmckl_context~ | in | Global state | + | ~A~ | ~qmckl_matrix~ | in | Input matrix | + | ~At~ | ~qmckl_matrix~ | out | Transposed matrix | #+begin_src c :tangle (eval h_private_func) :comments org qmckl_exit_code @@ -2061,7 +2166,7 @@ qmckl_transpose (qmckl_context context, #+end_src - #+begin_src c :tangle (eval c) :comments org + #+begin_src c :tangle (eval c) :comments org :exports none qmckl_exit_code qmckl_transpose (qmckl_context context, const qmckl_matrix A, @@ -2100,7 +2205,7 @@ qmckl_transpose (qmckl_context context, } #+end_src -*** Test +*** Test :noexport: #+begin_src c :comments link :tangle (eval c_test) { diff --git a/org/qmckl_context.org b/org/qmckl_context.org index 624681b..792a2cf 100644 --- a/org/qmckl_context.org +++ b/org/qmckl_context.org @@ -146,7 +146,7 @@ typedef struct qmckl_context_struct { the pointer associated with a context is non-null, we can still verify that it points to the expected data structure. - #+begin_src c :comments org :tangle (eval h_private_type) :noweb yes + #+begin_src c :comments org :tangle (eval h_private_type) :noweb yes :exports none #define VALID_TAG 0xBEEFFACE #define INVALID_TAG 0xDEADBEEF #+end_src @@ -156,10 +156,11 @@ typedef struct qmckl_context_struct { if the context is valid, ~QMCKL_NULL_CONTEXT~ otherwise. #+begin_src c :comments org :tangle (eval h_func) :noexport -qmckl_context qmckl_context_check(const qmckl_context context) ; +qmckl_context +qmckl_context_check (const qmckl_context context) ; #+end_src - #+begin_src c :tangle (eval c) + #+begin_src c :tangle (eval c) :exports none qmckl_context qmckl_context_check(const qmckl_context context) { if (context == QMCKL_NULL_CONTEXT) @@ -176,19 +177,27 @@ qmckl_context qmckl_context_check(const qmckl_context context) { } #+end_src - The context keeps a ``date'' that allows to check which data needs + The context keeps a /date/ that allows to check which data needs to be recomputed. The date is incremented when the context is touched. When a new element is added to the context, the functions - [[Creation][qmckl_context_create]], [[Destroy][qmckl_context_destroy]] and [[Copy][qmckl_context_copy]] + [[Creation][=qmckl_context_create=]] [[Destroy][=qmckl_context_destroy=]] and [[Copy][=qmckl_context_copy=]] should be updated in order to make deep copies. - #+begin_src c :comments org :tangle (eval h_func) :noexport -qmckl_exit_code qmckl_context_touch(const qmckl_context context) ; + When the electron coordinates have changed, the context is touched + using the following function. + + #+begin_src c :comments org :tangle (eval h_func) +qmckl_exit_code +qmckl_context_touch (const qmckl_context context); #+end_src - #+begin_src c :tangle (eval c) -qmckl_exit_code qmckl_context_touch(const qmckl_context context) { + This has the effect to increment the date of the context. + + #+begin_src c :tangle (eval c) :exports none +qmckl_exit_code +qmckl_context_touch(const qmckl_context context) +{ if (qmckl_context_check(context) == QMCKL_NULL_CONTEXT) { return qmckl_failwith( context, @@ -213,12 +222,12 @@ qmckl_exit_code qmckl_context_touch(const qmckl_context context) { - A new context always has all its members initialized with a NULL value # Header - #+begin_src c :comments org :tangle (eval h_func) :exports none + #+begin_src c :comments org :tangle (eval h_func) qmckl_context qmckl_context_create(); #+end_src # Source - #+begin_src c :tangle (eval c) + #+begin_src c :tangle (eval c) :exports none qmckl_context qmckl_context_create() { qmckl_context_struct* const ctx = @@ -326,13 +335,13 @@ assert( qmckl_context_check(context) == context ); ~lock_count~ attribute. # Header - #+begin_src c :comments org :tangle (eval h_func) :exports none + #+begin_src c :comments org :tangle (eval h_func) void qmckl_lock (qmckl_context context); void qmckl_unlock(qmckl_context context); #+end_src # Source - #+begin_src c :tangle (eval c) + #+begin_src c :tangle (eval c) :exports none void qmckl_lock(qmckl_context context) { if (context == QMCKL_NULL_CONTEXT) return ; @@ -345,9 +354,6 @@ void qmckl_lock(qmckl_context context) { } assert (rc == 0); ctx->lock_count += 1; -/* - printf(" lock : %d\n", ctx->lock_count); -,*/ } void qmckl_unlock(const qmckl_context context) { @@ -359,9 +365,6 @@ void qmckl_unlock(const qmckl_context context) { } assert (rc == 0); ctx->lock_count -= 1; -/* - printf("unlock : %d\n", ctx->lock_count); -,*/ } #+end_src @@ -372,12 +375,14 @@ void qmckl_unlock(const qmckl_context context) { # Header #+begin_src c :comments org :tangle (eval h_func) :exports none +/* qmckl_context qmckl_context_copy(const qmckl_context context); +*/ #+end_src # Source - #+begin_src c :tangle (eval c) + #+begin_src c :tangle (eval c) :exports none qmckl_context qmckl_context_copy(const qmckl_context context) { const qmckl_context checked_context = qmckl_context_check(context); @@ -418,13 +423,13 @@ qmckl_context qmckl_context_copy(const qmckl_context context) { # Fortran interface #+begin_src f90 :tangle (eval fh_func) :exports none - interface - integer (qmckl_context) function qmckl_context_copy(context) bind(C) - use, intrinsic :: iso_c_binding - import - integer (qmckl_context), intent(in), value :: context - end function qmckl_context_copy - end interface +! interface +! integer (qmckl_context) function qmckl_context_copy(context) bind(C) +! use, intrinsic :: iso_c_binding +! import +! integer (qmckl_context), intent(in), value :: context +! end function qmckl_context_copy +! end interface #+end_src # Test @@ -443,13 +448,16 @@ munit_assert_int64(qmckl_context_check(new_context), ==, new_context); It frees the context, and returns the previous context. # Header - #+begin_src c :comments org :tangle (eval h_func) :exports none -qmckl_exit_code qmckl_context_destroy(const qmckl_context context); + #+begin_src c :comments org :tangle (eval h_func) +qmckl_exit_code +qmckl_context_destroy (const qmckl_context context); #+end_src # Source - #+begin_src c :tangle (eval c) -qmckl_exit_code qmckl_context_destroy(const qmckl_context context) { + #+begin_src c :tangle (eval c) :exports none +qmckl_exit_code +qmckl_context_destroy (const qmckl_context context) +{ const qmckl_context checked_context = qmckl_context_check(context); if (checked_context == QMCKL_NULL_CONTEXT) return QMCKL_INVALID_CONTEXT; diff --git a/org/qmckl_error.org b/org/qmckl_error.org index cecd42d..97cc7cc 100644 --- a/org/qmckl_error.org +++ b/org/qmckl_error.org @@ -46,7 +46,7 @@ int main() { #+end_src -* +* - :PROPERTIES: :UNNUMBERED: t :END: @@ -204,18 +204,25 @@ return '\n'.join(result) string is assumed to be large enough to contain the error message (typically 128 characters). +* hidden :noexport: + + #+NAME: MAX_STRING_LENGTH + : 128 + * Decoding errors To decode the error messages, ~qmckl_string_of_error~ converts an error code into a string. - #+NAME: MAX_STRING_LENGTH - : 128 + #+begin_src c :comments org :tangle (eval h_func) :noweb yes +const char* +qmckl_string_of_error (const qmckl_exit_code error); + #+end_src - #+begin_src c :comments org :tangle (eval h_func) :exports none :noweb yes -const char* qmckl_string_of_error(const qmckl_exit_code error); -void qmckl_string_of_error_f(const qmckl_exit_code error, - char result[<>]); + #+begin_src c :comments org :tangle (eval h_private_func) :exports none :noweb yes +void +qmckl_string_of_error_f(const qmckl_exit_code error, + char result[<>]); #+end_src The text strings are extracted from the previous table. @@ -326,7 +333,7 @@ return '\n'.join(result) #+end_example # Source - #+begin_src c :comments org :tangle (eval c) :noweb yes + #+begin_src c :comments org :tangle (eval c) :noweb yes :exports none const char* qmckl_string_of_error(const qmckl_exit_code error) { switch (error) { <> @@ -340,7 +347,7 @@ void qmckl_string_of_error_f(const qmckl_exit_code error, char result[< 0); assert (exit_code < QMCKL_INVALID_EXIT_CODE); assert (function != NULL); @@ -544,8 +553,6 @@ if (x < 0) { #endif #+end_src - -** Test #+begin_src c :comments link :tangle (eval c_test) /* Initialize the variables */ char function_name[QMCKL_MAX_FUN_LEN]=""; From ff526a18cb0c6f315917bde12194aa777708f58d Mon Sep 17 00:00:00 2001 From: Anthony Scemama Date: Fri, 25 Feb 2022 13:57:13 +0100 Subject: [PATCH 02/11] Fix Clang build --- org/qmckl_ao.org | 4 ++-- org/qmckl_blas.org | 4 ++-- org/qmckl_context.org | 31 ++++++++++++++++++------------- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/org/qmckl_ao.org b/org/qmckl_ao.org index 28aab78..da9cbf1 100644 --- a/org/qmckl_ao.org +++ b/org/qmckl_ao.org @@ -5062,8 +5062,8 @@ for (int32_t ldl=3 ; ldl<=5 ; ++ldl) { for (int32_t k=0 ; k<5 ; ++k) { for (int32_t l=0 ; l +#include #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -1256,7 +1257,6 @@ print(C.T) rc = qmckl_double_of_matrix(context, C, cnew, 15); assert(rc == QMCKL_SUCCESS); - #include for (int i=0 ; i<15 ; ++i) { printf("%f %f\n", cnew[i], c[i]); assert (c[i] == cnew[i]); diff --git a/org/qmckl_context.org b/org/qmckl_context.org index 792a2cf..6a35789 100644 --- a/org/qmckl_context.org +++ b/org/qmckl_context.org @@ -62,6 +62,7 @@ int main() { #include #include #include +#include #include "qmckl.h" #include "qmckl_context_private_type.h" @@ -69,6 +70,8 @@ int main() { #+end_src + + * Context handling The context variable is a handle for the state of the library, @@ -185,9 +188,9 @@ qmckl_context qmckl_context_check(const qmckl_context context) { should be updated in order to make deep copies. When the electron coordinates have changed, the context is touched - using the following function. + using the following function. - #+begin_src c :comments org :tangle (eval h_func) + #+begin_src c :comments org :tangle (eval h_func) qmckl_exit_code qmckl_context_touch (const qmckl_context context); #+end_src @@ -222,7 +225,7 @@ qmckl_context_touch(const qmckl_context context) - A new context always has all its members initialized with a NULL value # Header - #+begin_src c :comments org :tangle (eval h_func) + #+begin_src c :comments org :tangle (eval h_func) qmckl_context qmckl_context_create(); #+end_src @@ -250,7 +253,9 @@ qmckl_context qmckl_context_create() { rc = pthread_mutexattr_init(&attr); assert (rc == 0); +#ifdef PTHREAD_MUTEX_RECURSIVE (void) pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); +#endif rc = pthread_mutex_init ( &(ctx->mutex), &attr); assert (rc == 0); @@ -261,30 +266,30 @@ qmckl_context qmckl_context_create() { /* Initialize data */ { ctx->tag = VALID_TAG; - + const qmckl_context context = (const qmckl_context) ctx; assert ( qmckl_context_check(context) != QMCKL_NULL_CONTEXT ); - + qmckl_exit_code rc; - + ctx->numprec.precision = QMCKL_DEFAULT_PRECISION; ctx->numprec.range = QMCKL_DEFAULT_RANGE; rc = qmckl_init_point(context); assert (rc == QMCKL_SUCCESS); - + rc = qmckl_init_electron(context); assert (rc == QMCKL_SUCCESS); - + rc = qmckl_init_nucleus(context); assert (rc == QMCKL_SUCCESS); - + rc = qmckl_init_ao_basis(context); assert (rc == QMCKL_SUCCESS); - + rc = qmckl_init_mo_basis(context); assert (rc == QMCKL_SUCCESS); - + rc = qmckl_init_determinant(context); assert (rc == QMCKL_SUCCESS); } @@ -335,7 +340,7 @@ assert( qmckl_context_check(context) == context ); ~lock_count~ attribute. # Header - #+begin_src c :comments org :tangle (eval h_func) + #+begin_src c :comments org :tangle (eval h_func) void qmckl_lock (qmckl_context context); void qmckl_unlock(qmckl_context context); #+end_src @@ -448,7 +453,7 @@ munit_assert_int64(qmckl_context_check(new_context), ==, new_context); It frees the context, and returns the previous context. # Header - #+begin_src c :comments org :tangle (eval h_func) + #+begin_src c :comments org :tangle (eval h_func) qmckl_exit_code qmckl_context_destroy (const qmckl_context context); #+end_src From b6a31b8c583f98172a94e6b70866794be289c3cb Mon Sep 17 00:00:00 2001 From: Anthony Scemama Date: Fri, 25 Feb 2022 16:30:16 +0100 Subject: [PATCH 03/11] Optimize AOs --- org/qmckl_ao.org | 157 +++++++++++++++++++++++++++-------------------- 1 file changed, 92 insertions(+), 65 deletions(-) diff --git a/org/qmckl_ao.org b/org/qmckl_ao.org index da9cbf1..5872c5b 100644 --- a/org/qmckl_ao.org +++ b/org/qmckl_ao.org @@ -3040,11 +3040,11 @@ integer(c_int32_t) function test_qmckl_ao_gaussian_vgl(context) bind(C) integer(c_int64_t), intent(in), value :: context integer*8 :: n, ldv, j, i - double precision :: X(3), R(3), Y(3), r2 + double precision :: X(3), R(3), Y(3), r2, z double precision, allocatable :: VGL(:,:), A(:) double precision :: epsilon - epsilon = qmckl_get_numprec_epsilon(context) + epsilon = 3.d0 * qmckl_get_numprec_epsilon(context) X = (/ 1.1 , 2.2 , 3.3 /) R = (/ 0.1 , 1.2 , -2.3 /) @@ -3068,29 +3068,43 @@ integer(c_int32_t) function test_qmckl_ao_gaussian_vgl(context) bind(C) do i=1,n test_qmckl_ao_gaussian_vgl = -11 - if (dabs(1.d0 - VGL(i,1) / (& - dexp(-A(i) * r2) & - )) > epsilon ) return + z = dabs(1.d0 - VGL(i,1) / (dexp(-A(i) * r2)) ) + if ( z > epsilon ) then + print *, z, epsilon + return + end if test_qmckl_ao_gaussian_vgl = -12 - if (dabs(1.d0 - VGL(i,2) / (& - -2.d0 * A(i) * Y(1) * dexp(-A(i) * r2) & - )) > epsilon ) return + z = dabs(1.d0 - VGL(i,2) / (& + -2.d0 * A(i) * Y(1) * dexp(-A(i) * r2) )) + if ( z > epsilon ) then + print *, z, epsilon + return + end if test_qmckl_ao_gaussian_vgl = -13 - if (dabs(1.d0 - VGL(i,3) / (& - -2.d0 * A(i) * Y(2) * dexp(-A(i) * r2) & - )) > epsilon ) return + z = dabs(1.d0 - VGL(i,3) / (& + -2.d0 * A(i) * Y(2) * dexp(-A(i) * r2) )) + if ( z > epsilon ) then + print *, z, epsilon + return + end if test_qmckl_ao_gaussian_vgl = -14 - if (dabs(1.d0 - VGL(i,4) / (& - -2.d0 * A(i) * Y(3) * dexp(-A(i) * r2) & - )) > epsilon ) return + z = dabs(1.d0 - VGL(i,4) / (& + -2.d0 * A(i) * Y(3) * dexp(-A(i) * r2) )) + if ( z > epsilon ) then + print *, z, epsilon + return + end if test_qmckl_ao_gaussian_vgl = -15 - if (dabs(1.d0 - VGL(i,5) / (& - A(i) * (4.d0*r2*A(i) - 6.d0) * dexp(-A(i) * r2) & - )) > epsilon ) return + z = dabs(1.d0 - VGL(i,5) / (& + A(i) * (4.d0*r2*A(i) - 6.d0) * dexp(-A(i) * r2) )) + if ( z > epsilon ) then + print *, z, epsilon + return + end if end do test_qmckl_ao_gaussian_vgl = 0 @@ -5423,16 +5437,16 @@ qmckl_compute_ao_vgl_hpc_gaussian ( const double s4 = s6_*z; const double s5 = s5_; + const int64_t k = ao_index[ishell]; + double* __restrict__ const ao_vgl_1 = ao_vgl + ipoint*5*ao_num + k; const int32_t l = shell_ang_mom[ishell]; const int32_t n = lstart[l+1]-lstart[l]; - const int64_t k = ao_index[ishell]; - double* __restrict__ const ao_vgl_1 = &(ao_vgl[ipoint*5*ao_num+k]); - double* __restrict__ const ao_vgl_2 = &(ao_vgl_1[ ao_num]); - double* __restrict__ const ao_vgl_3 = &(ao_vgl_1[2*ao_num]); - double* __restrict__ const ao_vgl_4 = &(ao_vgl_1[3*ao_num]); - double* __restrict__ const ao_vgl_5 = &(ao_vgl_1[4*ao_num]); + double* __restrict__ const ao_vgl_2 = ao_vgl_1 + ao_num; + double* __restrict__ const ao_vgl_3 = ao_vgl_1 + (ao_num<<1); + double* __restrict__ const ao_vgl_4 = ao_vgl_1 + (ao_num<<1) + ao_num; + double* __restrict__ const ao_vgl_5 = ao_vgl_1 + (ao_num<<2); double* __restrict__ poly_vgl_1; double* __restrict__ poly_vgl_2; @@ -5440,71 +5454,84 @@ qmckl_compute_ao_vgl_hpc_gaussian ( double* __restrict__ poly_vgl_4; double* __restrict__ poly_vgl_5; if (nidx > 0) { - const double* f = &(ao_factor[k]); + const double* __restrict__ f = ao_factor + k; const int64_t idx = lstart[l]; switch (nucleus_max_ang_mom[inucl]) { case 0: - ao_vgl_1[0] = s1 * f[0]; - ao_vgl_2[0] = s2 * f[0]; - ao_vgl_3[0] = s3 * f[0]; - ao_vgl_4[0] = s4 * f[0]; - ao_vgl_5[0] = s5; break; case 1: poly_vgl_1 = &(poly_vgl_l1[0][idx]); poly_vgl_2 = &(poly_vgl_l1[1][idx]); poly_vgl_3 = &(poly_vgl_l1[2][idx]); poly_vgl_4 = &(poly_vgl_l1[3][idx]); - for (int64_t il=0 ; il Date: Fri, 25 Feb 2022 16:39:44 +0100 Subject: [PATCH 04/11] Compiling options with gcc --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index fcc1dc5..968fbf8 100644 --- a/configure.ac +++ b/configure.ac @@ -49,12 +49,12 @@ AS_IF([test -d ${srcdir}/.git], AC_ARG_WITH(ifort, [AS_HELP_STRING([--with-ifort],[Use Intel Fortran compiler])], with_ifort=$withval, with_ifort=no) AS_IF([test "$with_ifort" == "yes"], [ FC=ifort - FCFLAGS="-xHost -ip -O2 -ftz -finline -g -mkl=sequential" ]) + FCFLAGS="-xHost -ip -Ofast -ftz -finline -g -mkl=sequential" ]) AC_ARG_WITH(icc, [AS_HELP_STRING([--with-icc],[Use Intel C compiler])], with_icc=$withval, with_icc=no) AS_IF([test "$with_icc" == "yes"], [ CC=icc - CFLAGS="-xHost -ip -O2 -ftz -finline -g -mkl=sequential" ]) + CFLAGS="-xHost -ip -Ofast -ftz -finline -g -mkl=sequential" ]) AS_IF([test "$with_icc"."$with_ifort" == "yes.yes"], [ ax_blas_ok="yes" From ad86cb7d670fbad691a22fe156cde6a010c51532 Mon Sep 17 00:00:00 2001 From: Anthony Scemama Date: Fri, 25 Feb 2022 20:39:20 +0100 Subject: [PATCH 05/11] Working on HPC version of AOs --- org/qmckl_ao.org | 135 +++++++++++++++++++++++++++++++++++++++------ org/qmckl_blas.org | 66 ++++++++++++++++++++-- 2 files changed, 179 insertions(+), 22 deletions(-) diff --git a/org/qmckl_ao.org b/org/qmckl_ao.org index 5872c5b..0262c53 100644 --- a/org/qmckl_ao.org +++ b/org/qmckl_ao.org @@ -268,7 +268,7 @@ end interface *** Data structure :noexport: - #+begin_src c :comments org :tangle (eval h_private_type) + #+begin_src c :comments org :tangle (eval h_private_type) :noweb yes typedef struct qmckl_ao_basis_struct { int64_t shell_num; int64_t prim_num; @@ -299,6 +299,9 @@ typedef struct qmckl_ao_basis_struct { bool provided; bool ao_cartesian; char type; +#ifdef HAVE_HPC + <> +#endif } qmckl_ao_basis_struct; #+end_src @@ -770,14 +773,14 @@ qmckl_set_ao_basis_shell_prim_num (qmckl_context context, } #+end_src - + #+begin_src c :comments org :tangle (eval h_func) qmckl_exit_code qmckl_set_ao_basis_shell_prim_index (qmckl_context context, const int64_t* shell_prim_index, const int64_t size_max); #+end_src - + #+begin_src c :comments org :tangle (eval c) :noweb yes :exports none qmckl_exit_code qmckl_set_ao_basis_shell_prim_index (qmckl_context context, @@ -831,15 +834,15 @@ qmckl_set_ao_basis_shell_prim_index (qmckl_context context, <> } #+end_src - - + + #+begin_src c :comments org :tangle (eval h_func) qmckl_exit_code qmckl_set_ao_basis_shell_factor (qmckl_context context, const double* shell_factor, const int64_t size_max); #+end_src - + #+begin_src c :comments org :tangle (eval c) :noweb yes :exports none qmckl_exit_code qmckl_set_ao_basis_shell_factor (qmckl_context context, @@ -893,15 +896,15 @@ qmckl_set_ao_basis_shell_factor (qmckl_context context, <> } #+end_src - - + + #+begin_src c :comments org :tangle (eval h_func) qmckl_exit_code qmckl_set_ao_basis_exponent (qmckl_context context, const double* exponent, const int64_t size_max); #+end_src - + #+begin_src c :comments org :tangle (eval c) :noweb yes :exports none qmckl_exit_code qmckl_set_ao_basis_exponent (qmckl_context context, @@ -2485,7 +2488,6 @@ free(ao_factor_test); | ~ao_vgl~ | ~double[point_num][5][ao_num]~ | Value, gradients, Laplacian of the primitives at current positions | | ~ao_vgl_date~ | ~uint64_t~ | Last modification date of Value, gradients, Laplacian of the AOs at current positions | - *** After initialization When the basis set is completely entered, extra data structures may be @@ -2625,11 +2627,109 @@ qmckl_exit_code qmckl_finalize_basis(qmckl_context context) { } } } - /* TODO : sort the basis set here */ - return QMCKL_SUCCESS; + + rc = QMCKL_SUCCESS; +#ifdef HAVE_HPC + rc = qmckl_finalize_basis_hpc(context); +#endif + + return rc; } #+end_src +*** HPC-specific data structures + + For faster access, we provide 3D tensors for the shell information + as: + - $C_{psa}$ = =coef_per_nucleus (iprim, ishell, inucl)= + - $\gamma_{pa}$ =expo_per_nucleus (iprim, inucl)= + + such that the computation of the radial parts can be vectorized. + Exponents are sorted in increasing order to exit loops quickly, + and only unique exponents are kept. + + The computation of the radial part is made as + \[ + R_{sa} = \sum_p C_{psa} \gamma_{pa} + \] + which is a matrix-vector product. + + #+NAME:HPC_struct + #+begin_src c :comments org :tangle (eval h_private_type) :exports none + /* HPC specific data structures */ + qmckl_tensor coef_per_nucleus; + qmckl_matrix expo_per_nucleus; + #+end_src + + #+begin_src c :comments org :tangle (eval h_private_func) :exports none +qmckl_exit_code qmckl_finalize_basis_hpc (qmckl_context context); + #+end_src + + #+begin_src c :comments org :tangle (eval c) :exports none +qmckl_exit_code qmckl_finalize_basis_hpc (qmckl_context context) +{ + qmckl_context_struct* const ctx = (qmckl_context_struct* const) context; + + int64_t shell_max = 0; + int64_t prim_max = 0; + int64_t nucl_num = ctx->nucleus.num; + for (int inucl=0 ; inucl < nucl_num ; ++inucl) { + shell_max = ctx->ao_basis.nucleus_shell_num[inucl] > shell_max ? + ctx->ao_basis.nucleus_shell_num[inucl] : shell_max; + + int64_t prim_num = 0; + const int64_t ishell_start = ctx->ao_basis.nucleus_index[inucl]; + const int64_t ishell_end = ctx->ao_basis.nucleus_index[inucl] + ctx->ao_basis.nucleus_shell_num[inucl]; + for (int64_t ishell = ishell_start ; ishell < ishell_end ; ++ishell) { + prim_num += ctx->ao_basis.shell_prim_num[ishell]; + } + prim_max = prim_num > prim_max ? + prim_num : prim_max; + } + + int64_t size[3] = { prim_max, shell_max, nucl_num }; + ctx->ao_basis.coef_per_nucleus = qmckl_tensor_alloc( context, 3, size ); + ctx->ao_basis.coef_per_nucleus = qmckl_tensor_set(ctx->ao_basis.coef_per_nucleus, 0.); + + ctx->ao_basis.expo_per_nucleus = qmckl_matrix_alloc( context, prim_max, nucl_num ); + ctx->ao_basis.expo_per_nucleus = qmckl_matrix_set(ctx->ao_basis.expo_per_nucleus, 0.); + + double expo[prim_max]; + double coef[shell_max][prim_max]; + for (int inucl=0 ; inucl < nucl_num ; ++inucl) { + memset(expo, 0, sizeof(expo)); + memset(coef, 0, sizeof(expo)); + + int64_t idx = 0; + const int64_t ishell_start = ctx->ao_basis.nucleus_index[inucl]; + const int64_t ishell_end = ctx->ao_basis.nucleus_index[inucl] + ctx->ao_basis.nucleus_shell_num[inucl]; + for (int64_t ishell = ishell_start ; ishell < ishell_end ; ++ishell) { + + const int64_t iprim_start = ctx->ao_basis.shell_prim_index[ishell]; + const int64_t iprim_end = ctx->ao_basis.shell_prim_index[ishell] + ctx->ao_basis.shell_prim_num[ishell]; + for (int64_t iprim = iprim_start ; iprim < iprim_end ; ++iprim) { + expo[idx] = ctx->ao_basis.coefficient_normalized[iprim]; + coef[ishell - ishell_start][idx] = ctx->ao_basis.coefficient_normalized[iprim]; + idx += 1; + } + } + + for (int64_t i=0 ; iao_basis.expo_per_nucleus, i, inucl ) = expo[i]; + } + + for (int64_t j=0 ; jao_basis.coef_per_nucleus, i, j, inucl ) = coef[j][i]; + } + } + + } + return QMCKL_SUCCESS; +} + + #+end_src + *** Access functions #+begin_src c :comments org :tangle (eval h_func) :noweb yes @@ -5477,6 +5577,7 @@ qmckl_compute_ao_vgl_hpc_gaussian ( poly_vgl_2 = &(poly_vgl[1][idx]); poly_vgl_3 = &(poly_vgl[2][idx]); poly_vgl_4 = &(poly_vgl[3][idx]); + poly_vgl_5 = &(poly_vgl[4][idx]); } switch (n) { case(1): @@ -5497,8 +5598,8 @@ qmckl_compute_ao_vgl_hpc_gaussian ( ao_vgl_4[il] = (poly_vgl_4[il] * s1 + poly_vgl_1[il] * s4) * f[il]; ao_vgl_5[il] = (poly_vgl_1[il] * s5 + 2.0*(poly_vgl_2[il] * s2 + - poly_vgl_3[il] * s3 + - poly_vgl_4[il] * s4 )) * f[il]; + poly_vgl_3[il] * s3 + + poly_vgl_4[il] * s4 )) * f[il]; } break; case(5): @@ -5512,8 +5613,8 @@ qmckl_compute_ao_vgl_hpc_gaussian ( ao_vgl_4[il] = (poly_vgl_4[il] * s1 + poly_vgl_1[il] * s4) * f[il]; ao_vgl_5[il] = (poly_vgl_1[il] * s5 + 2.0*(poly_vgl_2[il] * s2 + - poly_vgl_3[il] * s3 + - poly_vgl_4[il] * s4 )) * f[il]; + poly_vgl_3[il] * s3 + + poly_vgl_4[il] * s4 )) * f[il]; } break; default: @@ -5525,7 +5626,7 @@ qmckl_compute_ao_vgl_hpc_gaussian ( ao_vgl_2[il] = (poly_vgl_2[il] * s1 + poly_vgl_1[il] * s2) * f[il]; ao_vgl_3[il] = (poly_vgl_3[il] * s1 + poly_vgl_1[il] * s3) * f[il]; ao_vgl_4[il] = (poly_vgl_4[il] * s1 + poly_vgl_1[il] * s4) * f[il]; - ao_vgl_5[il] = (poly_vgl_1[il] * s5 + + ao_vgl_5[il] = (poly_vgl_5[il] * s1 + poly_vgl_1[il] * s5 + 2.0*(poly_vgl_2[il] * s2 + poly_vgl_3[il] * s3 + poly_vgl_4[il] * s4 )) * f[il]; diff --git a/org/qmckl_blas.org b/org/qmckl_blas.org index ecf8746..73f9e46 100644 --- a/org/qmckl_blas.org +++ b/org/qmckl_blas.org @@ -523,13 +523,71 @@ double qmckl_ten5(qmckl_tensor t, int64_t i, int64_t j, int64_t k, int64_t l, in #define qmckl_vec(v, i) v.data[i] #define qmckl_mat(m, i, j) m.data[(i) + (j)*m.size[0]] -#define qmckl_ten3(t, i, j, k) t.data[(i) + m.size[0]*((j) + size[1]*(k))] -#define qmckl_ten4(t, i, j, k, l) t.data[(i) + m.size[0]*((j) + size[1]*((k) + size[2]*(l)))] -#define qmckl_ten5(t, i, j, k, l, m) t.data[(i) + m.size[0]*((j) + size[1]*((k) + size[2]*((l) + size[3]*(m))))] +#define qmckl_ten3(t, i, j, k) t.data[(i) + t.size[0]*((j) + t.size[1]*(k))] +#define qmckl_ten4(t, i, j, k, l) t.data[(i) + t.size[0]*((j) + t.size[1]*((k) + t.size[2]*(l)))] +#define qmckl_ten5(t, i, j, k, l, m) t.data[(i) + t.size[0]*((j) + t.size[1]*((k) + t.size[2]*((l) + t.size[3]*(m))))] #+end_src For example: +** Set all elements + +*** Vector + + #+begin_src c :comments org :tangle (eval h_private_func) +qmckl_vector +qmckl_vector_set(qmckl_vector vector, double value); + #+end_src + + #+begin_src c :comments org :tangle (eval c) :exports none +qmckl_vector +qmckl_vector_set(qmckl_vector vector, double value) +{ + for (int64_t i=0 ; i Date: Sun, 27 Feb 2022 11:18:26 +0100 Subject: [PATCH 06/11] Fortran interface --- org/qmckl_ao.org | 10 ++++--- org/qmckl_nucleus.org | 62 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/org/qmckl_ao.org b/org/qmckl_ao.org index 0262c53..c821c67 100644 --- a/org/qmckl_ao.org +++ b/org/qmckl_ao.org @@ -1,3 +1,4 @@ +B #+TITLE: Atomic Orbitals #+SETUPFILE: ../tools/theme.setup #+INCLUDE: ../tools/lib.org @@ -2639,14 +2640,15 @@ qmckl_exit_code qmckl_finalize_basis(qmckl_context context) { *** HPC-specific data structures - For faster access, we provide 3D tensors for the shell information - as: + For faster access, we provide extra arrays for the shell information as: - $C_{psa}$ = =coef_per_nucleus (iprim, ishell, inucl)= - $\gamma_{pa}$ =expo_per_nucleus (iprim, inucl)= such that the computation of the radial parts can be vectorized. + Exponents are sorted in increasing order to exit loops quickly, - and only unique exponents are kept. + and only unique exponents are kept. This also allows to pack the + exponents to enable vectorization of exponentials. The computation of the radial part is made as \[ @@ -2655,7 +2657,7 @@ qmckl_exit_code qmckl_finalize_basis(qmckl_context context) { which is a matrix-vector product. #+NAME:HPC_struct - #+begin_src c :comments org :tangle (eval h_private_type) :exports none + #+begin_src c :comments org :exports none /* HPC specific data structures */ qmckl_tensor coef_per_nucleus; qmckl_matrix expo_per_nucleus; diff --git a/org/qmckl_nucleus.org b/org/qmckl_nucleus.org index 0191afe..319d5d1 100644 --- a/org/qmckl_nucleus.org +++ b/org/qmckl_nucleus.org @@ -187,6 +187,19 @@ qmckl_get_nucleus_num (const qmckl_context context, int64_t* const num) { } #+end_src + #+begin_src f90 :tangle (eval fh_func) :comments org :exports none +interface + integer(c_int32_t) function qmckl_get_nucleus_num(context, num) & + bind(C) + use, intrinsic :: iso_c_binding + import + implicit none + integer (c_int64_t) , intent(in) , value :: context + integer (c_int64_t) , intent(out) :: num + end function qmckl_get_nucleus_num +end interface + #+end_src + #+begin_src c :comments org :tangle (eval h_func) :exports none qmckl_exit_code @@ -242,6 +255,20 @@ qmckl_get_nucleus_charge (const qmckl_context context, #+end_src + #+begin_src f90 :tangle (eval fh_func) :comments org :exports none +interface + integer(c_int32_t) function qmckl_get_nucleus_charge(context, charge, size_max) & + bind(C) + use, intrinsic :: iso_c_binding + import + implicit none + integer (c_int64_t) , intent(in) , value :: context + real (c_double) , intent(out) :: charge(*) + integer (c_int64_t) , intent(in) , value :: size_max + end function qmckl_get_nucleus_charge +end interface + #+end_src + #+begin_src c :comments org :tangle (eval h_func) :exports none qmckl_exit_code @@ -277,6 +304,18 @@ qmckl_get_nucleus_rescale_factor (const qmckl_context context, } #+end_src + #+begin_src f90 :tangle (eval fh_func) :comments org :exports none +interface + integer(c_int32_t) function qmckl_get_nucleus_rescale_factor(context, kappa) & + bind(C) + use, intrinsic :: iso_c_binding + import + implicit none + integer (c_int64_t) , intent(in) , value :: context + real (c_double) , intent(out) :: kappa + end function qmckl_get_nucleus_rescale_factor +end interface + #+end_src #+begin_src c :comments org :tangle (eval h_func) :exports none qmckl_exit_code @@ -342,6 +381,21 @@ qmckl_get_nucleus_coord (const qmckl_context context, } #+end_src + #+begin_src f90 :tangle (eval fh_func) :comments org :exports none +interface + integer(c_int32_t) function qmckl_get_nucleus_coord(context, transp, coord, size_max) & + bind(C) + use, intrinsic :: iso_c_binding + import + implicit none + integer (c_int64_t) , intent(in) , value :: context + character(c_char) , intent(in) , value :: transp + real (c_double) , intent(out) :: coord(*) + integer (c_int64_t) , intent(in) , value :: size_max + end function qmckl_get_nucleus_coord +end interface + #+end_src + When all the data relative to nuclei have been set, the following function returns ~true~. @@ -424,7 +478,7 @@ interface implicit none integer (c_int64_t) , intent(in) , value :: context integer (c_int64_t) , intent(in) , value :: num - end function + end function qmckl_set_nucleus_num end interface #+end_src @@ -570,7 +624,7 @@ interface character(c_char) , intent(in) , value :: transp real (c_double) , intent(in) :: coord(*) integer (c_int64_t) , intent(in) , value :: size_max - end function + end function qmckl_set_nucleus_coord end interface #+end_src @@ -604,14 +658,14 @@ qmckl_set_nucleus_rescale_factor(qmckl_context context, #+begin_src f90 :tangle (eval fh_func) :comments org :exports none interface - integer(c_int32_t) function qmckl_set_rescale_factor(context, kappa) & + integer(c_int32_t) function qmckl_set_nucleus_rescale_factor(context, kappa) & bind(C) use, intrinsic :: iso_c_binding import implicit none integer (c_int64_t) , intent(in) , value :: context real (c_double) , intent(in) , value :: kappa - end function + end function qmckl_set_nucleus_rescale_factor end interface #+end_src From 8b7b56b57b380e5bbbe72766f72202143d46ffc0 Mon Sep 17 00:00:00 2001 From: q-posev Date: Mon, 28 Feb 2022 22:28:11 +0100 Subject: [PATCH 07/11] Fix broken build Recent HPC-related additions break the current build (make) process. This is because the HPC-related functions are not wrapped in the preprocessor ifdef statement. --- org/qmckl_ao.org | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/org/qmckl_ao.org b/org/qmckl_ao.org index c821c67..a79549a 100644 --- a/org/qmckl_ao.org +++ b/org/qmckl_ao.org @@ -2664,10 +2664,13 @@ qmckl_exit_code qmckl_finalize_basis(qmckl_context context) { #+end_src #+begin_src c :comments org :tangle (eval h_private_func) :exports none +#ifdef HAVE_HPC qmckl_exit_code qmckl_finalize_basis_hpc (qmckl_context context); +#endif #+end_src #+begin_src c :comments org :tangle (eval c) :exports none +#ifdef HAVE_HPC qmckl_exit_code qmckl_finalize_basis_hpc (qmckl_context context) { qmckl_context_struct* const ctx = (qmckl_context_struct* const) context; @@ -2729,6 +2732,7 @@ qmckl_exit_code qmckl_finalize_basis_hpc (qmckl_context context) } return QMCKL_SUCCESS; } +#endif #+end_src From 5b6f5302554509cc7dba97f565f28e1c82f4c8e5 Mon Sep 17 00:00:00 2001 From: q-posev Date: Tue, 1 Mar 2022 14:17:38 +0100 Subject: [PATCH 08/11] Fix debug build Added missing preprocessor wrapper --- org/qmckl_ao.org | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/org/qmckl_ao.org b/org/qmckl_ao.org index a79549a..7cc7eef 100644 --- a/org/qmckl_ao.org +++ b/org/qmckl_ao.org @@ -5376,6 +5376,7 @@ end function qmckl_compute_ao_vgl_doc_f | ~ao_vgl~ | ~double[point_num][5][ao_num]~ | out | Value, gradients and Laplacian of the AOs | #+begin_src c :comments org :tangle (eval c) :noweb yes :exports none +#ifdef HAVE_HPC qmckl_exit_code qmckl_compute_ao_vgl_hpc_gaussian ( const qmckl_context context, @@ -5655,6 +5656,7 @@ qmckl_compute_ao_vgl_hpc_gaussian ( } return QMCKL_SUCCESS; } +#endif #+end_src ** Interfaces @@ -5681,6 +5683,7 @@ qmckl_compute_ao_vgl_hpc_gaussian ( double* const ao_vgl ); #+end_src #+begin_src c :tangle (eval h_private_func) :comments org +#ifdef HAVE_HPC qmckl_exit_code qmckl_compute_ao_vgl_hpc_gaussian ( const qmckl_context context, const int64_t ao_num, @@ -5701,6 +5704,7 @@ qmckl_compute_ao_vgl_hpc_gaussian ( const double* expo, const double* coef_normalized, double* const ao_vgl ); +#endif #+end_src #+CALL: generate_c_interface(table=qmckl_ao_vgl_args_doc,rettyp=get_value("CRetType"),fname="qmckl_compute_ao_vgl_doc")) From 370a12803a1e116a3ebeeca5dba8e4cda0d5f9a6 Mon Sep 17 00:00:00 2001 From: Evgeny Posenitskiy <45995097+q-posev@users.noreply.github.com> Date: Wed, 2 Mar 2022 09:13:50 +0100 Subject: [PATCH 09/11] Fix test-build GitHub Action (#67) * Fix bugs in the .yml file * Fix test step in the GitHub CI When using out of source build all `make` rules should be executed in the corresponding directory (e.g. `_build`) * Add CI step to test TREXIO on MacOS * Explicitly provide gcc-10 and gfortran-10 to configure --- .github/workflows/test-build.yml | 44 ++++++++++---------------------- 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index 41b59e0..c7af73f 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -47,6 +47,7 @@ jobs: - name: Run test run: make -j 4 check + working-directory: _build - name: Archive test log file if: failure() @@ -57,13 +58,7 @@ jobs: - name: Dist test run: make distcheck - - - name: Archive test log file - if: failure() - uses: actions/upload-artifact@v2 - with: - name: dist-report-ubuntu - path: test-suite.log + working-directory: _build x86_macos: @@ -91,37 +86,26 @@ jobs: git clone https://github.com/TREX-CoE/trexio.git cd trexio ./autogen.sh - mkdir _build - cd _build - ../configure --enable-silent-rules - make -j 4 - - - name: Run test - run: make -j 4 check - - - name: Archive test log file - if: failure() - uses: actions/upload-artifact@v2 - with: - name: test-report-ubuntu - path: test-suite.log - - - name: Dist test - run: make distcheck - - - name: Archive test log file - if: failure() - uses: actions/upload-artifact@v2 - with: ./configure --prefix=${PWD}/_install --enable-silent-rules make -j 4 make install + - name: Test TREXIO + run: make -j 4 check + working-directory: trexio + + - name: Archive TREXIO test log file + if: failure() + uses: actions/upload-artifact@v2 + with: + name: test-report-trexio-macos + path: trexio/test-suite.log + - name: Build QMCkl run: | export PKG_CONFIG_PATH=${PWD}/trexio/_install/lib/pkgconfig:$PKG_CONFIG_PATH ./autogen.sh - ./configure --enable-silent-rules --enable-debug + ./configure CC=gcc-10 FC=gfortran-10 --enable-silent-rules --enable-debug make -j 4 - name: Run test From 11cb1de4a5a39b7dbcb034c83fc88fd780208787 Mon Sep 17 00:00:00 2001 From: q-posev Date: Fri, 4 Mar 2022 11:27:59 +0100 Subject: [PATCH 10/11] Create FindQMCKL module --- cmake/FindQMCKL.cmake | 77 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 cmake/FindQMCKL.cmake diff --git a/cmake/FindQMCKL.cmake b/cmake/FindQMCKL.cmake new file mode 100644 index 0000000..89b0b11 --- /dev/null +++ b/cmake/FindQMCKL.cmake @@ -0,0 +1,77 @@ +#=========================================== + +# Try to find the QMCkl library; +# If found, it will define the following variables (note the plural form): +# QMCKL_FOUND - System has libqmckl; +# QMCKL_INCLUDE_DIRS - The QMCKL include directories; +# QMCKL_LIBRARIES - The libraries needed to use QMCKL; + +# If QMCKL has been installed in a non-standard location, one can set an +# environment variable $QMCKL_DIR in the current shell: +# $ export QMCKL_DIR= +# to indicate the prefix used during the QMCKL installation +# (typically `./configure prefix= ..` or `cmake -DCMAKE_INSTALL_DIR= ..`) + +# This file should be located WITHIN your project source tree. +# (e.g. in cmake/FindQMCKL.cmake) +# How to use it in your project CMakeLists.txt: + +# This is needed to locate FindQMCKL.cmake file, modify it according to your source tree. +# list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/") + +# find_package(QMCKL) +# if (QMCKL_FOUND) +# include_directories(${QMCKL_INCLUDE_DIRS}) +# target_link_libraries(your_target ${QMCKL_LIBRARIES}) +# endif() + +#=========================================== + +# This file is distirbuted under the BSD 3-Clause License. +# Copyright (c) 2021, TREX Center of Excellence + +#=========================================== + +message("") + +set(QMCKL_SEARCH_PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt +) + +find_path(QMCKL_INCLUDE_DIR + NAMES qmckl.h + HINTS $ENV{QMCKL_DIR} + PATH_SUFFIXES include/qmckl include + PATHS ${QMCKL_SEARCH_PATHS} + ) + + +# No need to specify platform-specific prefix (e.g. libqmckl on Unix) or +# suffix (e.g. .so on Unix or .dylib on MacOS) in NAMES. CMake takes care of that. +find_library(QMCKL_LIBRARY + NAMES qmckl + HINTS $ENV{QMCKL_DIR} + PATH_SUFFIXES lib64 lib + PATHS ${QMCKL_SEARCH_PATHS} + ) + +message("") + +# Handle the QUIETLY and REQUIRED arguments and set QMCKL_FOUND to TRUE if +# all listed variables are TRUE. +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(QMCKL DEFAULT_MSG QMCKL_LIBRARY QMCKL_INCLUDE_DIR ) +MARK_AS_ADVANCED(QMCKL_INCLUDE_DIR QMCKL_LIBRARY) + +# Mot setting _INCLUDE_DIR and _LIBRARIES is considered a bug, +# see https://gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/How-To-Find-Libraries +set(QMCKL_LIBRARIES ${QMCKL_LIBRARY}) +set(QMCKL_INCLUDE_DIRS ${QMCKL_INCLUDE_DIR}) + From f85c52f3f8e4eb44f2c850bd5dc6aff27cbc56ee Mon Sep 17 00:00:00 2001 From: q-posev Date: Fri, 4 Mar 2022 11:29:56 +0100 Subject: [PATCH 11/11] Add linking instructions to README --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 4ab5bae..703bfee 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,24 @@ sudo make install sudo make installcheck ``` + +## Linking to your program + +The `make install` command takes care of installing the QMCkl shared library on the user machine. +Once installed, add `-lqmckl` to the list of compiler options. + +In some cases (e.g. when using custom `prefix` during configuration), the QMCkl library might end up installed in a directory, which is absent in the default `$LIBRARY_PATH`. +In order to link the program against QMCkl, the search paths can be modified as follows: + +`export LIBRARY_PATH=$LIBRARY_PATH:/lib` + +(same holds for `$LD_LIBRARY_PATH`). The `` has to be replaced with the prefix used during the installation. + +If your project relies on the CMake build system, feel free to use the +[FindQMCKL.cmake](https://github.com/TREX-CoE/qmckl/blob/master/cmake/FindQMCKL.cmake) +module to find and link the QMCkl library automatically. + + ## Verificarlo CI Since Verificarlo should not be a dependency of QMCkl, all Verificarlo