diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml deleted file mode 100644 index a5b0c8c..0000000 --- a/.github/workflows/test-build.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: test-build - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: install dependencies - run: sudo apt-get install emacs - - name: make - run: make -C src/ - - name: build docs - run: make -C src/ doc - - name: deploy docs - uses: ./ - with: - username: scemama - password: 7da28e533792db220a4811fc4e487b8ba817862f - remote_url: https://github.com/appleboy/gh-pages-action.git - - test: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: install dependencies - run: sudo apt-get install emacs - - name: Checkout submodules using a PAT - run: | - git config --file .gitmodules --get-regexp url | while read url; do - git config --file=.gitmodules $(echo "$url" | sed -E "s/git@github.com:|https:\/\/github.com\//https:\/\/${{ secrets.CI_PAT }}:${{ secrets.CI_PAT }}@github.com\//") - done - git submodule sync - git submodule update --init --recursive - - name: make - run: make -C src/ test diff --git a/docs/.gitignore b/.gitignore similarity index 100% rename from docs/.gitignore rename to .gitignore diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 8ad4907..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "munit"] - path = munit - url = https://github.com/nemequ/munit/ diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 2ad479f..0000000 --- a/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2020, TREX Center of Excellence -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.html b/README.html new file mode 100644 index 0000000..ac0f09b --- /dev/null +++ b/README.html @@ -0,0 +1,548 @@ + + + + +QMCkl source code documentation + + + + + + + + + + + + + + + +
+

QMCkl source code documentation

+
+

Table of Contents

+ +
+ +
+

1 Introduction

+
+

+The ultimate goal of QMCkl is to provide a high-performance +implementation of the main kernels of QMC. In this particular +repository, we focus on the definition of the API and the tests, +and on a pedagogical presentation of the algorithms. We expect the +HPC experts to use this repository as a reference for re-writing +optimized libraries. +

+ +

+Literate programming is particularly adapted in this context. +Source files are written in org-mode format, to provide useful +comments and LaTex formulas close to the code. There exists multiple +possibilities to convert org-mode files into different formats such as +HTML or pdf. +For a tutorial on literate programming with org-mode, follow +this link. +

+ +

+The code is extracted from the org files using Emacs as a command-line +tool in the Makefile, and then the produced files are compiled. +

+
+ +
+

1.1 Language used

+
+

+Fortran is one of the most common languages used by the community, +and is simple enough to make the algorithms readable. Hence we +propose in this pedagogical implementation of QMCkl to use Fortran +to express the algorithms. For specific internal functions where +the C language is more natural, C is used. +

+ +

+As Fortran modules generate compiler-dependent files, the use of +modules is restricted to the internal use of the library, otherwise +the compliance with C is violated. +

+ +

+The external dependencies should be kept as small as possible, so +external libraries should be used only if their used is strongly +justified. +

+
+
+ +
+

1.2 Source code editing

+
+

+Any text editor can be used to edit org-mode files. For a better +user experience Emacs is recommended. +For users hating Emacs, it is good to know that Emacs can behave +like Vim when switched into ``Evil'' mode. There also exists +Spacemacs which helps the transition for Vim users. +

+ +

+For users with a preference for Jupyter notebooks, the following +script can convert jupyter notebooks to org-mode files: +

+ +
+ +
"nb_to_org.sh"body
+
+
+ +

+And pandoc can convert multiple markdown formats into org-mode. +

+
+
+ +
+

1.3 Writing in Fortran

+
+

+The Fortran source files should provide a C interface using +iso_c_binding. The name of the Fortran source files should end +with _f.f90 to be properly handled by the Makefile. +The names of the functions defined in fortran should be the same as +those exposed in the API suffixed by _f. +Fortran interface files should also be written in a file with a +.fh extension. +

+
+
+ +
+

1.4 Coding style

+
+

+To improve readability, we maintain a consistent coding style in the library. +

+ +
    +
  • For C source files, we will use (decide on a coding style) +
  • +
  • For Fortran source files, we will use (decide on a coding style) +
  • +
+ +

+Coding style can be automatically checked with clang-format. +

+
+
+
+ +
+

2 Design of the library

+
+

+The proposed API should allow the library to: +

+
    +
  • deal with memory transfers between CPU and accelerators +
  • +
  • use different levels of floating-point precision +
  • +
+ +

+We chose a multi-layered design with low-level and high-level +functions (see below). +

+
+ +
+

2.1 Naming conventions

+
+

+Use qmckl_ as a prefix for all exported functions and variables. +All exported header files should have a filename with the prefix +qmckl_. +

+ +

+If the name of the org-mode file is xxx.org, the name of the +produced C files should be xxx.c and xxx.h and the name of the +produced Fortran files should be xxx.f90 +

+ +

+Arrays are in uppercase and scalars are in lowercase. +

+
+
+ +
+

2.2 Application programming interface

+
+

+The application programming interface (API) is designed to be +compatible with the C programming language (not C++), to ensure +that the library will be easily usable in any language. +This implies that only the following data types are allowed in the API: +

+ +
    +
  • 32-bit and 64-bit floats and arrays (real and double) +
  • +
  • 32-bit and 64-bit integers and arrays (int32_t and int64_t) +
  • +
  • Pointers should be represented as 64-bit integers (even on +32-bit architectures) +
  • +
  • ASCII strings are represented as a pointers to a character arrays +and terminated by a zero character (C convention). +
  • +
+ +

+To facilitate the use in other languages than C, we provide some +bindings in other languages in other repositories. +

+
+
+ +
+

2.3 Global state

+
+

+Global variables should be avoided in the library, because it is +possible that one single program needs to use multiple instances of +the library. To solve this problem we propose to use a pointer to a +context variable, built by the library with the +qmckl_context_create function. The context contains the global +state of the library, and is used as the first argument of many +QMCkl functions. +

+ +

+Modifying the state is done by setters and getters, prefixed +by qmckl_context_set_ an qmckl_context_get_. +When a context variable is modified by a setter, a copy of the old +data structure is made and updated, and the pointer to the new data +structure is returned, such that the old contexts can still be +accessed. +It is also possible to modify the state in an impure fashion, using +the qmckl_context_update_ functions. +The context and its old versions can be destroyed with +qmckl_context_destroy. +

+
+
+ +
+

2.4 Low-level functions

+
+

+Low-level functions are very simple functions which are leaves of the +function call tree (they don't call any other QMCkl function). +

+ +

+This functions are pure, and unaware of the QMCkl context. They are +not allowed to allocate/deallocate memory, and if they need +temporary memory it should be provided in input. +

+
+
+ +
+

2.5 High-level functions

+
+

+High-level functions are at the top of the function call tree. +They are able to choose which lower-level function to call +depending on the required precision, and do the corresponding type +conversions. +These functions are also responsible for allocating temporary +storage, to simplify the use of accelerators. +

+ +

+The high-level functions should be pure, unless the introduction of +non-purity is justified. All the side effects should be made in the +context variable. +

+
+
+ +
+

2.6 Numerical precision

+
+

+The number of bits of precision required for a function should be +given as an input of low-level computational functions. This input will +be used to define the values of the different thresholds that might +be used to avoid computing unnecessary noise. +High-level functions will use the precision specified in the +context variable. +

+
+
+
+ +
+

3 Algorithms

+
+

+Reducing the scaling of an algorithm usually implies also reducing +its arithmetic complexity (number of flops per byte). Therefore, +for small sizes \(\mathcal{O}(N^3)\) and \(\mathcal{O}(N^2)\) algorithms +are better adapted than linear scaling algorithms. +As QMCkl is a general purpose library, multiple algorithms should +be implemented adapted to different problem sizes. +

+
+
+ +
+

4 Rules for the API

+
+
    +
  • stdint should be used for integers (int32_t, int64_t) +
  • +
  • integers used for counting should always be int64_t +
  • +
  • floats should be by default double, unless explicitly mentioned +
  • +
  • pointers are converted to int64_t to increase portability +
  • +
+
+
+ +
+

5 Documentation

+ +
+ +
+

6 Acknowledgments

+
+

+euflag.jpg +TREX: Targeting Real Chemical Accuracy at the Exascale project has received funding from the European Union’s Horizon 2020 - Research and Innovation program - under grant agreement no. 952165. The content of this document does not represent the opinion of the European Union, and the European Union is not responsible for any use that might be made of such content. +

+
+
+
+
+

Created: 2020-10-28 Wed 23:57

+

Emacs 25.2.2 (Org mode 8.2.10)

+

Validate

+
+ + diff --git a/README.md b/README.md deleted file mode 100644 index e64cfb3..0000000 --- a/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# QMCkl: Quantum Monte Carlo Kernel Library - -![Build Status](https://github.com/TREX-CoE/qmckl/workflows/test-build/badge.svg?branch=main) - -The domain of quantum chemistry needs a library in which the main -kernels of Quantum Monte Carlo (QMC) methods are implemented. In the -library proposed in this project, we expose the main algorithms in a -simple language and provide a standard API and tests to enable the -development of high-performance QMCkl implementations taking -advantage of modern hardware. - -See the [source code](https://github.com/TREX-CoE/qmckl/tree/main/src) -to read the documentation. - - -To clone the repository, use: -``` -git clone --recursive https://github.com/TREX-CoE/qmckl.git -``` -to dowload also the [munit](https://github.com/nemequ/munit) unit testing -framework. - - ------------------------------- - -![European flag](https://trex-coe.eu/sites/default/files/inline-images/euflag.jpg) -[TREX: Targeting Real Chemical Accuracy at the Exascale](https://trex-coe.eu) project has received funding from the European Union’s Horizon 2020 - Research and Innovation program - under grant agreement no. 952165. The content of this document does not represent the opinion of the European Union, and the European Union is not responsible for any use that might be made of such content. - diff --git a/TODO.org b/TODO.org deleted file mode 100644 index 1fad144..0000000 --- a/TODO.org +++ /dev/null @@ -1,18 +0,0 @@ -* Set up CI on Travis -* Write tests - -* malloc/free : Parameters for accelerators? -We should define qmckl_malloc and qmckl_free just to give the -possibility of the HPC implementations to define how they allocate the -memory (on CPU or GPU, using alternatives to malloc/free, etc). -A possibility could be to pass the id of a NUMA domain as a parameter of -qmckl_malloc, where the domain id is something obtained from the -context. - - -* TRANSA, TRANSB -* Performance info -* Benchmark interpolation of basis functions -* Complex numbers -* Adjustable number for derivatives (1,2,3) - diff --git a/munit b/munit deleted file mode 160000 index fbbdf14..0000000 --- a/munit +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fbbdf1467eb0d04a6ee465def2e529e4c87f2118 diff --git a/qmckl.html b/qmckl.html new file mode 100644 index 0000000..f11be9f --- /dev/null +++ b/qmckl.html @@ -0,0 +1,255 @@ + + + + +QMCkl C header + + + + + + + + + + + + + +
+

QMCkl C header

+
+

Table of Contents

+ +
+

+This file produces the qmckl.h header file, which is included in all +other C header files. It is the main entry point to the library. +

+ +
+ +
#ifndef QMCKL_H
+#define QMCKL_H
+#include <stdlib.h>
+#include <stdint.h>
+
+
+ +
+

1 Constants

+
+
+

1.1 Success/failure

+
+

+These are the codes returned by the functions to indicate success +or failure. All such functions should have as a return type qmckl_exit_code. +

+ +
+ +
#define QMCKL_SUCCESS 0
+#define QMCKL_FAILURE 1
+
+typedef int32_t qmckl_exit_code;
+typedef int64_t qmckl_context ;
+
+
+
+
+ + +
+

1.2 Precision-related constants

+
+

+Controlling numerical precision enables optimizations. Here, the +default parameters determining the target numerical precision and +range are defined. +

+ +
+ +
#define QMCKL_DEFAULT_PRECISION 53
+#define QMCKL_DEFAULT_RANGE     11
+
+
+
+
+
+ +
+

2 Header files

+
+

+All the functions expoed in the API are defined in the following +header files. +

+ +
+ +
#include "qmckl_memory.h"
+#include "qmckl_context.h"
+
+#include "qmckl_distance.h"
+#include "qmckl_ao.h"
+
+
+
+
+ +
+

3 End of header

+
+
+ +
#endif
+
+
+
+
+
+
+

Created: 2020-10-28 Wed 23:57

+

Emacs 25.2.2 (Org mode 8.2.10)

+

Validate

+
+ + diff --git a/qmckl_ao.html b/qmckl_ao.html new file mode 100644 index 0000000..be42f61 --- /dev/null +++ b/qmckl_ao.html @@ -0,0 +1,652 @@ + + + + +Atomic Orbitals + + + + + + + + + + + + + + + +
+

Atomic Orbitals

+
+

Table of Contents

+ +
+

+This files contains all the routines for the computation of the +values, gradients and Laplacian of the atomic basis functions. +

+ +

+4 files are produced: +

+ + +
+

1 Polynomials

+
+

+\[ + P_l(\mathbf{r},\mathbf{R}_i) = (x-X_i)^a (y-Y_i)^b (z-Z_i)^c + \] +

+\begin{eqnarray*} +\frac{\partial }{\partial x} P_l\left(\mathbf{r},\mathbf{R}_i \right) & = & a (x-X_i)^{a-1} (y-Y_i)^b (z-Z_i)^c \\ +\frac{\partial }{\partial y} P_l\left(\mathbf{r},\mathbf{R}_i \right) & = & b (x-X_i)^a (y-Y_i)^{b-1} (z-Z_i)^c \\ +\frac{\partial }{\partial z} P_l\left(\mathbf{r},\mathbf{R}_i \right) & = & c (x-X_i)^a (y-Y_i)^b (z-Z_i)^{c-1} \\ +\end{eqnarray*} +\begin{eqnarray*} +\left( \frac{\partial }{\partial x^2} + + \frac{\partial }{\partial y^2} + + \frac{\partial }{\partial z^2} \right) P_l + \left(\mathbf{r},\mathbf{R}_i \right) & = & + a(a-1) (x-X_i)^{a-2} (y-Y_i)^b (z-Z_i)^c + \\ + && b(b-1) (x-X_i)^a (y-Y_i)^{b-1} (z-Z_i)^c + \\ + && c(c-1) (x-X_i)^a (y-Y_i)^b (z-Z_i)^{c-1} +\end{eqnarray*} +
+ +
+

1.1 qmckl_ao_powers

+
+

+Computes all the powers of the n input data up to the given +maximum value given in input for each of the \(n\) points: +

+ +

+\[ P_{ij} = X_j^i \] +

+
+ +
+

1.1.1 Arguments

+
+ + + +++ ++ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
contextinputGlobal state
ninputNumber of values
X(n)inputArray containing the input values
LMAX(n)inputArray containing the maximum power for each value
P(LDP,n)outputArray containing all the powers of X
LDPinputLeading dimension of array P
+
+
+ +
+

1.1.2 Requirements

+
+
    +
  • context is not 0 +
  • +
  • n > 0 +
  • +
  • X is allocated with at least \(n \times 8\) bytes +
  • +
  • LMAX is allocated with at least \(n \times 4\) bytes +
  • +
  • P is allocated with at least \(n \times \max_i \text{LMAX}_i \times 8\) bytes +
  • +
  • LDP >= \(\max_i\) LMAX[i] +
  • +
+
+
+ +
+

1.1.3 Header

+
+
+ +
qmckl_exit_code qmckl_ao_powers(qmckl_context context,
+		int64_t n, 
+		double *X, int32_t *LMAX,
+		double *P, int64_t LDP);
+
+
+
+
+ +
+

1.1.4 Source

+
+
+ +
integer function qmckl_ao_powers_f(context, n, X, LMAX, P, ldp) result(info)
+  implicit none
+  integer*8 , intent(in)  :: context
+  integer*8 , intent(in)  :: n
+  real*8    , intent(in)  :: X(n)
+  integer   , intent(in)  :: LMAX(n)
+  real*8    , intent(out) :: P(ldp,n)
+  integer*8 , intent(in)  :: ldp
+
+  integer*8  :: i,j
+
+  info = 0
+
+  if (context == 0_8) then
+     info = -1
+     return
+  endif
+
+  if (LDP < MAXVAL(LMAX)) then
+     info = -2
+     return
+  endif
+
+  do j=1,n
+    P(1,j) = X(j)
+    do i=2,LMAX(j)
+       P(i,j) = P(i-1,j) * X(j) 
+    end do
+  end do
+
+end function qmckl_ao_powers_f
+
+
+
+
+
+ +
+

1.2 qmckl_ao_polynomial_vgl

+
+

+Computes the values, gradients and Laplacians at a given point of +all polynomials with an angular momentum up to lmax. +

+
+ +
+

1.2.1 Arguments

+
+ + + +++ ++ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
contextinputGlobal state
X(3)inputArray containing the coordinates of the points
R(3)inputArray containing the x,y,z coordinates of the center
lmaxinputMaximum angular momentum
noutputNumber of computed polynomials
L(ldl,n)outputContains a,b,c for all n results
ldlinputLeading dimension of L
VGL(ldv,n)outputValue, gradients and Laplacian of the polynomials
ldvinputLeading dimension of array VGL
+
+
+ +
+

1.2.2 Requirements

+
+
    +
  • context is not 0 +
  • +
  • n > 0 +
  • +
  • X is allocated with at least \(3 \times 8\) bytes +
  • +
  • R is allocated with at least \(3 \times 8\) bytes +
  • +
  • lmax >= 0 +
  • +
  • On output, n should be equal to (=lmax=+1)(=lmax=+2)(=lmax=+3)/6 +
  • +
  • L is allocated with at least \(3 \times n \times 4\) bytes +
  • +
  • ldl >= 3 +
  • +
  • VGL is allocated with at least \(5 \times n \times 8\) bytes +
  • +
  • ldv >= 5 +
  • +
+
+
+ +
+

1.2.3 Header

+
+
+ +
qmckl_exit_code qmckl_ao_polynomial_vgl(qmckl_context context,
+		double *X, double *R,
+		int32_t lmax, int64_t *n,
+		int32_t *L,   int64_t ldl,
+		double *VGL,  int64_t ldv);
+
+
+
+
+ +
+

1.2.4 Source

+
+
+ +
integer function qmckl_ao_polynomial_vgl_f(context, X, R, lmax, n, L, ldl, VGL, ldv) result(info)
+  implicit none
+  integer*8 , intent(in)  :: context
+  real*8    , intent(in)  :: X(3), R(3)
+  integer   , intent(in)  :: lmax
+  integer*8 , intent(out) :: n
+  integer   , intent(out) :: L(ldl,(lmax+1)*(lmax+2)*(lmax+3)/6)
+  integer*8 , intent(in)  :: ldl
+  real*8    , intent(out) :: VGL(ldv,(lmax+1)*(lmax+2)*(lmax+3)/6)
+  integer*8 , intent(in)  :: ldv
+
+  integer*8         :: i,j
+  integer           :: a,b,c,d
+  real*8            :: Y(3)
+  integer           :: lmax_array(3)
+  real*8            :: pows(-2:lmax,3)
+  integer, external :: qmckl_ao_powers_f
+  double precision  :: xy, yz, xz
+  double precision  :: da, db, dc, dd
+
+  info = 0
+
+  if (context == 0_8) then
+     info = -1
+     return
+  endif
+
+  n = (lmax+1)*(lmax+2)*(lmax+3)/6
+
+  if (ldl < 3) then
+     info = -2
+     return
+  endif
+
+  if (ldv < 5) then
+     info = -3
+     return
+  endif
+
+
+  do i=1,3
+     Y(i) = X(i) - R(i)
+  end do
+  pows(-2:-1,1:3) = 0.d0
+  pows(0,1:3) = 1.d0
+  lmax_array(1:3) = lmax
+  info = qmckl_ao_powers_f(context, 1_8, Y(1), (/lmax/), pows(1,1), size(pows,1,kind=8)) 
+  if (info /= 0) return
+  info = qmckl_ao_powers_f(context, 1_8, Y(2), (/lmax/), pows(1,2), size(pows,1,kind=8)) 
+  if (info /= 0) return
+  info = qmckl_ao_powers_f(context, 1_8, Y(3), (/lmax/), pows(1,3), size(pows,1,kind=8)) 
+  if (info /= 0) return
+
+
+  n=1
+  vgl(1:5,1:n) = 0.d0
+  l(1:3,n) = 0
+  vgl(1,n) = 1.d0
+  dd = 1.d0
+  do d=1,lmax
+     da = 0.d0
+     do a=0,d
+	db = 0.d0
+	do b=0,d-a
+	   c  = d  - a  - b
+	   dc = dd - da - db
+	   n = n+1
+	   l(1,n) = a
+	   l(2,n) = b
+	   l(3,n) = c
+
+	   xy = pows(a,1) * pows(b,2)
+	   yz = pows(b,2) * pows(c,3)
+	   xz = pows(a,1) * pows(c,3)
+
+	   vgl(1,n) = xy * pows(c,3)
+
+	   xy = dc * xy
+	   xz = db * xz
+	   yz = da * yz
+
+	   vgl(2,n) = pows(a-1,1) * yz
+	   vgl(3,n) = pows(b-1,2) * xz
+	   vgl(4,n) = pows(c-1,3) * xy
+
+	   vgl(5,n) = &
+		(da-1.d0) * pows(a-2,1) * yz + &
+		(db-1.d0) * pows(b-2,2) * xz + &
+		(dc-1.d0) * pows(c-2,3) * xy
+
+	   db = db + 1.d0
+	end do
+	da = da + 1.d0
+     end do
+     dd = dd + 1.d0
+  end do
+
+end function qmckl_ao_polynomial_vgl_f
+
+
+
+
+
+
+ + +
+

2 TODO Gaussian basis functions

+
+ +
+

3 TODO Slater basis functions

+
+
+
+

Created: 2020-10-28 Wed 23:57

+

Emacs 25.2.2 (Org mode 8.2.10)

+

Validate

+
+ + diff --git a/qmckl_context.html b/qmckl_context.html new file mode 100644 index 0000000..a9e3312 --- /dev/null +++ b/qmckl_context.html @@ -0,0 +1,739 @@ + + + + +Context + + + + + + + + + + + + + +
+

Context

+
+

Table of Contents

+ +
+

+This file is written in C because it is more natural to express the context in +C than in Fortran. +

+ +

+3 files are produced: +

+ + +
+

1 Context

+
+

+The context variable is a handle for the state of the library, and +is stored in the following data structure, which can't be seen +outside of the library. To simplify compatibility with other +languages, the pointer to the internal data structure is converted +into a 64-bit signed integer, defined in the qmckl_context type. +A value of 0 for the context is equivalent to a NULL pointer. +

+
+ +
+

1.0.1 Source

+
+
+ +
typedef struct qmckl_context_struct {
+  struct qmckl_context_struct * prev;
+  uint32_t tag;
+  int32_t precision;
+  int32_t range;
+} qmckl_context_struct;
+
+#define VALID_TAG   0xBEEFFACE
+#define INVALID_TAG 0xDEADBEEF
+
+
+ +

+The tag is used internally to check if the memory domain pointed by +a pointer is a valid context. +

+
+
+ +
+

1.1 qmckl_context_check

+
+

+Checks if the domain pointed by the pointer is a valid context. +Returns the input qmckl_context if the context is valid, 0 otherwise. +

+
+ +
+

1.1.1 Header

+
+
+ +
qmckl_context qmckl_context_check(const qmckl_context context) ;
+
+
+
+
+ +
+

1.1.2 Source

+
+
+ +
qmckl_context qmckl_context_check(const qmckl_context context) {
+  qmckl_context_struct * ctx;
+
+  if (context == (qmckl_context) 0) return (qmckl_context) 0;
+
+  ctx = (qmckl_context_struct*) context;
+  if (ctx->tag != VALID_TAG) return (qmckl_context) 0;
+
+  return context;
+}
+
+
+
+
+
+ +
+

1.2 qmckl_context_create

+
+

+To create a new context, use qmckl_context_create(). +

+
    +
  • On success, returns a pointer to a context using the qmckl_context type +
  • +
  • Returns 0 upon failure to allocate the internal data structure +
  • +
+
+ +
+

1.2.1 Header

+
+
+ +
qmckl_context qmckl_context_create();
+
+
+
+
+ +
+

1.2.2 Source

+
+
+ +
qmckl_context qmckl_context_create() {
+
+  qmckl_context_struct*  context;
+
+  context = (qmckl_context_struct*) qmckl_malloc ((qmckl_context) 0, sizeof(qmckl_context_struct));
+  if (context == NULL) {
+    return (qmckl_context) 0;
+  }
+
+  context->prev      = NULL;
+  context->precision = QMCKL_DEFAULT_PRECISION;
+  context->range     = QMCKL_DEFAULT_RANGE;
+  context->tag       = VALID_TAG;
+
+  return (qmckl_context) context;
+}
+
+
+
+
+
+ +
+

1.3 qmckl_context_copy

+
+

+This function makes a shallow copy of the current context. +

+
    +
  • Copying the 0-valued context returns 0 +
  • +
  • On success, returns a pointer to the new context using the qmckl_context type +
  • +
  • Returns 0 upon failure to allocate the internal data structure +for the new context +
  • +
+
+ +
+

1.3.1 Header

+
+
+ +
qmckl_context qmckl_context_copy(const qmckl_context context);
+
+
+
+
+ +
+

1.3.2 Source

+
+
+ +
qmckl_context qmckl_context_copy(const qmckl_context context) {
+
+  qmckl_context_struct* old_context;
+  qmckl_context_struct* new_context;
+  qmckl_context checked_context;
+
+  checked_context = qmckl_context_check(context);
+
+  if (checked_context == (qmckl_context) 0) {
+    return (qmckl_context) 0;
+  }
+
+  new_context = (qmckl_context_struct*) qmckl_malloc (context, sizeof(qmckl_context_struct));
+  if (new_context == NULL) {
+    return (qmckl_context) 0;
+  }
+
+  old_context = (qmckl_context_struct*) checked_context;
+
+  new_context->prev      = old_context;
+  new_context->precision = old_context->precision;
+  new_context->range     = old_context->range;
+  new_context->tag       = VALID_TAG;
+
+  return (qmckl_context) new_context;
+}
+
+
+
+
+
+ +
+

1.4 qmckl_context_previous

+
+

+Returns the previous context +

+
    +
  • On success, returns the ancestor of the current context +
  • +
  • Returns 0 for the initial context +
  • +
  • Returns 0 for the 0-valued context +
  • +
+
+ +
+

1.4.1 Header

+
+
+ +
qmckl_context qmckl_context_previous(const qmckl_context context);
+
+
+
+
+ +
+

1.4.2 Source

+
+
+ +
qmckl_context qmckl_context_previous(const qmckl_context context) {
+
+  qmckl_context checked_context;
+  qmckl_context_struct* ctx;
+
+  checked_context = qmckl_context_check(context);
+  if (checked_context == (qmckl_context) 0) {
+    return (qmckl_context) 0;
+  }
+
+  ctx = (qmckl_context_struct*) checked_context;
+  return qmckl_context_check((qmckl_context) ctx->prev);
+}
+
+
+
+
+
+ +
+

1.5 qmckl_context_destroy

+
+

+Destroys the current context, leaving the ancestors untouched. +

+
    +
  • Succeeds if the current context is properly destroyed +
  • +
  • Fails otherwise +
  • +
  • Fails if the 0-valued context is given in argument +
  • +
  • Fails if the the pointer is not a valid context +
  • +
+
+ +
+

1.5.1 Header

+
+
+ +
qmckl_exit_code qmckl_context_destroy(qmckl_context context);
+
+
+
+
+ +
+

1.5.2 Source

+
+
+ +
qmckl_exit_code qmckl_context_destroy(qmckl_context context) {
+
+  qmckl_context_struct* ctx;
+  qmckl_context checked_context;
+
+  checked_context = qmckl_context_check(context);
+  if (checked_context == (qmckl_context) 0) return QMCKL_FAILURE;
+
+  ctx = (qmckl_context_struct*) context;
+  if (ctx == NULL) return QMCKL_FAILURE;
+
+  ctx->tag = INVALID_TAG;
+  qmckl_free(ctx);
+  return QMCKL_SUCCESS;
+}
+
+
+
+
+
+
+ + +
+

2 Precision

+
+

+The following functions set and get the expected required precision +and range. precision should be an integer between 2 and 53, and +range should be an integer between 2 and 11. +

+ +

+The setter functions functions return a new context as a 64-bit integer. +The getter functions return the value, as a 32-bit integer. +The update functions return QMCKL_SUCCESS or QMCKL_FAILURE. +

+
+ +
+

2.1 qmckl_context_update_precision

+
+
+

2.1.1 Source

+
+
+ +
qmckl_exit_code qmckl_context_update_precision(const qmckl_context context, const int precision);
+
+
+ +
+ +
qmckl_exit_code qmckl_context_update_precision(const qmckl_context context, const int precision) {
+  qmckl_context_struct* ctx;
+
+  if (precision <  2) return QMCKL_FAILURE;
+  if (precision > 53) return QMCKL_FAILURE;
+
+  ctx = (qmckl_context_struct*) context;
+  if (ctx == NULL) return QMCKL_FAILURE;
+
+  ctx->precision = precision;
+  return QMCKL_SUCCESS;
+}
+
+
+
+
+
+
+

2.2 qmckl_context_update_range

+
+
+

2.2.1 Source

+
+
+ +
qmckl_exit_code qmckl_context_update_range(const qmckl_context context, const int range);
+
+
+ +
+ +
qmckl_exit_code qmckl_context_update_range(const qmckl_context context, const int range) {
+  qmckl_context_struct* ctx;
+
+  if (range <  2) return QMCKL_FAILURE;
+  if (range > 11) return QMCKL_FAILURE;
+
+  ctx = (qmckl_context_struct*) context;
+  if (ctx == NULL) return QMCKL_FAILURE;
+
+  ctx->range = range;
+  return QMCKL_SUCCESS;
+}
+
+
+
+
+
+
+

2.3 qmckl_context_set_precision

+
+
+

2.3.1 Source

+
+
+ +
qmckl_context qmckl_context_set_precision(const qmckl_context context, const int precision);
+
+
+ +
+ +
qmckl_context qmckl_context_set_precision(const qmckl_context context, const int precision) {
+  qmckl_context new_context;
+
+  new_context = qmckl_context_copy(context);
+  if (new_context == 0) return 0;
+
+  if (qmckl_context_update_precision(context, precision) == QMCKL_FAILURE) return 0;
+
+  return new_context;
+}
+
+
+
+
+
+
+

2.4 qmckl_context_set_range

+
+
+

2.4.1 Source

+
+
+ +
qmckl_context qmckl_context_set_range(const qmckl_context context, const int range);
+
+
+ +
+ +
qmckl_context qmckl_context_set_range(const qmckl_context context, const int range) {
+  qmckl_context new_context;
+
+  new_context = qmckl_context_copy(context);
+  if (new_context == 0) return 0;
+
+  if (qmckl_context_update_range(context, range) == QMCKL_FAILURE) return 0;
+
+  return new_context;
+}
+
+
+
+
+
+ +
+

2.5 qmckl_context_get_precision

+
+
+

2.5.1 Source

+
+
+ +
int qmckl_context_get_precision(const qmckl_context context);
+
+
+ +
+ +
int qmckl_context_get_precision(const qmckl_context context) {
+  qmckl_context_struct* ctx;
+  ctx = (qmckl_context_struct*) context;
+  return ctx->precision;
+}
+
+
+
+
+
+
+

2.6 qmckl_context_get_range

+
+
+

2.6.1 Source

+
+
+ +
int qmckl_context_get_range(const qmckl_context context);
+
+
+ +
+ +
int qmckl_context_get_range(const qmckl_context context) {
+  qmckl_context_struct* ctx;
+  ctx = (qmckl_context_struct*) context;
+  return ctx->range;
+}
+
+
+
+
+
+
+
+
+

Created: 2020-10-28 Wed 23:57

+

Emacs 25.2.2 (Org mode 8.2.10)

+

Validate

+
+ + diff --git a/qmckl_distance.html b/qmckl_distance.html new file mode 100644 index 0000000..c379a8b --- /dev/null +++ b/qmckl_distance.html @@ -0,0 +1,523 @@ + + + + +Computation of distances + + + + + + + + + + + + + + + +
+

Computation of distances

+
+

Table of Contents

+ +
+

+Function for the computation of distances between particles. +

+ +

+3 files are produced: +

+ + +
+

1 Squared distance

+
+
+

1.1 qmckl_distance_sq

+
+

+Computes the matrix of the squared distances between all pairs of +points in two sets, one point within each set: +\[ + C_{ij} = \sum_{k=1}^3 (A_{k,i}-B_{k,j})^2 + \] +

+
+ +
+

1.1.1 Arguments

+
+ + + +++ ++ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
contextinputGlobal state
transainputArray A is N: Normal, T: Transposed
transbinputArray B is N: Normal, T: Transposed
minputNumber of points in the first set
ninputNumber of points in the second set
A(lda,3)inputArray containing the \(m \times 3\) matrix \(A\)
ldainputLeading dimension of array A
B(ldb,3)inputArray containing the \(n \times 3\) matrix \(B\)
ldbinputLeading dimension of array B
C(ldc,n)outputArray containing the \(m \times n\) matrix \(C\)
ldcinputLeading dimension of array C
+
+
+ +
+

1.1.2 Requirements

+
+
    +
  • context is not 0 +
  • +
  • m > 0 +
  • +
  • n > 0 +
  • +
  • lda >= 3 if transa is N +
  • +
  • lda >= m if transa is T +
  • +
  • ldb >= 3 if transb is N +
  • +
  • ldb >= n if transb is T +
  • +
  • ldc >= m if transa is = +
  • +
  • A is allocated with at least \(3 \times m \times 8\) bytes +
  • +
  • B is allocated with at least \(3 \times n \times 8\) bytes +
  • +
  • C is allocated with at least \(m \times n \times 8\) bytes +
  • +
+
+
+ +
+

1.1.3 Performance

+
+

+This function might be more efficient when A and B are +transposed. +

+
+
+ +
+

1.1.4 Header

+
+
+ +
qmckl_exit_code qmckl_distance_sq(qmckl_context context,
+				  char transa, char transb,
+				  int64_t m, int64_t n,
+				  double *A, int64_t lda,
+				  double *B, int64_t ldb,
+				  double *C, int64_t ldc);
+
+
+
+
+ +
+

1.1.5 Source

+
+
+ +
integer function qmckl_distance_sq_f(context, transa, transb, m, n, A, LDA, B, LDB, C, LDC) result(info)
+  implicit none
+  integer*8  , intent(in)  :: context
+  character  , intent(in)  :: transa, transb
+  integer*8  , intent(in)  :: m, n
+  integer*8  , intent(in)  :: lda
+  real*8     , intent(in)  :: A(lda,*)
+  integer*8  , intent(in)  :: ldb
+  real*8     , intent(in)  :: B(ldb,*)
+  integer*8  , intent(in)  :: ldc
+  real*8     , intent(out) :: C(ldc,*)
+
+  integer*8 :: i,j
+  real*8    :: x, y, z
+  integer   :: transab
+
+  info = 0
+
+  if (context == 0_8) then
+     info = -1
+     return
+  endif
+
+  if (m <= 0_8) then
+     info = -2
+     return
+  endif
+
+  if (n <= 0_8) then
+     info = -3
+     return
+  endif
+
+  if (transa == 'N' .or. transa == 'n') then
+     transab = 0
+  else if (transa == 'T' .or. transa == 't') then
+     transab = 1
+  else
+     transab = -100
+  endif
+
+  if (transb == 'N' .or. transb == 'n') then
+     continue
+  else if (transa == 'T' .or. transa == 't') then
+     transab = transab + 2
+  else
+     transab = -100
+  endif
+
+  if (transab < 0) then
+     info = -4
+     return 
+  endif
+
+  if (iand(transab,1) == 0 .and. LDA < 3) then
+     info = -5
+     return
+  endif
+
+  if (iand(transab,1) == 1 .and. LDA < m) then
+     info = -6
+     return
+  endif
+
+  if (iand(transab,2) == 0 .and. LDA < 3) then
+     info = -6
+     return
+  endif
+
+  if (iand(transab,2) == 2 .and. LDA < m) then
+     info = -7
+     return
+  endif
+
+
+  select case (transab)
+
+  case(0)
+
+     do j=1,n
+	do i=1,m
+	   x = A(1,i) - B(1,j)
+	   y = A(2,i) - B(2,j)
+	   z = A(3,i) - B(3,j)
+	   C(i,j) = x*x + y*y + z*z
+	end do
+     end do
+
+  case(1)
+
+     do j=1,n
+	do i=1,m
+	   x = A(i,1) - B(1,j)
+	   y = A(i,2) - B(2,j)
+	   z = A(i,3) - B(3,j)
+	   C(i,j) = x*x + y*y + z*z
+	end do
+     end do
+
+  case(2)
+
+     do j=1,n
+	do i=1,m
+	   x = A(1,i) - B(j,1)
+	   y = A(2,i) - B(j,2)
+	   z = A(3,i) - B(j,3)
+	   C(i,j) = x*x + y*y + z*z
+	end do
+     end do
+
+  case(3)
+
+     do j=1,n
+	do i=1,m
+	   x = A(i,1) - B(j,1)
+	   y = A(i,2) - B(j,2)
+	   z = A(i,3) - B(j,3)
+	   C(i,j) = x*x + y*y + z*z
+	end do
+     end do
+
+  end select
+
+end function qmckl_distance_sq_f
+
+
+
+
+
+
+
+
+

Created: 2020-10-28 Wed 23:57

+

Emacs 25.2.2 (Org mode 8.2.10)

+

Validate

+
+ + diff --git a/qmckl_memory.html b/qmckl_memory.html new file mode 100644 index 0000000..a4ebe10 --- /dev/null +++ b/qmckl_memory.html @@ -0,0 +1,252 @@ + + + + +Memory management + + + + + + + + + + + + + +
+

Memory management

+
+

Table of Contents

+ +
+

+We override the allocation functions to enable the possibility of +optimized libraries to fine-tune the memory allocation. +

+ +

+3 files are produced: +

+ + +
+

1 qmckl_malloc

+
+

+Analogous of malloc, but passing a context and a signed 64-bit integers as argument. +

+
+
+

1.1 Header

+
+
+ +
void* qmckl_malloc(const qmckl_context ctx, const size_t size);
+
+
+
+
+ +
+

1.2 Source

+
+
+ +
void* qmckl_malloc(const qmckl_context ctx, const size_t size) {
+  if (ctx == (qmckl_context) 0) {
+    /* Avoids unused parameter error */
+    return malloc( (size_t) size );
+  }
+  return malloc( (size_t) size );
+}
+
+
+
+
+
+ +
+

2 qmckl_free

+
+
+

2.1 Header

+
+
+ +
void qmckl_free(void *ptr);
+
+
+
+
+ +
+

2.2 Source

+
+
+ +
void qmckl_free(void *ptr) {
+  free(ptr);
+}
+
+
+
+
+
+
+
+

Created: 2020-10-28 Wed 23:57

+

Emacs 25.2.2 (Org mode 8.2.10)

+

Validate

+
+ + diff --git a/src/.gitignore b/src/.gitignore deleted file mode 100644 index 90eb50e..0000000 --- a/src/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -*.o -*.c -*.f90 -*.h -*.html -*~ -*.so -Makefile.generated -test_qmckl diff --git a/src/Makefile b/src/Makefile deleted file mode 100644 index 6cf6be8..0000000 --- a/src/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -CC=gcc -CFLAGS=-fPIC -fexceptions -Wall -Werror -Wpedantic -Wextra -g - -FC=gfortran -FFLAGS=-fPIC -g -fcheck=all -Waliasing -Wampersand -Wconversion -Wsurprising -Wintrinsics-std -Wno-tabs -Wintrinsic-shadow -Wline-truncation -Wreal-q-constant -Wuninitialized -fbacktrace -ffpe-trap=zero,overflow,underflow -finit-real=nan - -LIBS=-lgfortran -lm - -#CC=icc -#CFLAGS=-fPIC -g -# -#FC=ifort -#FFLAGS=-fPIC -g -# -#LIBS=-lm -lifcore -lirc - - -export CC CFLAGS FC FFLAGS LIBS - -ORG_SOURCE_FILES=$(wildcard qmckl*.org) test_qmckl.org -OBJECT_FILES=$(filter-out $(EXCLUDED_OBJECTS), $(patsubst %.org,%.o,$(ORG_SOURCE_FILES))) - -.PHONY: clean -.SECONDARY: # Needed to keep the produced C and Fortran files - -libqmckl.so: Makefile.generated - $(MAKE) -f Makefile.generated - -test: Makefile.generated - $(MAKE) -f Makefile.generated test - -doc:$(ORG_SOURCE_FILES) - ./create_doc.sh README.org $(ORG_SOURCE_FILES) - -clean: - rm -f qmckl.h test_qmckl_* test_qmckl.c qmckl_*.f90 qmckl_*.c qmckl_*.o qmckl_*.h Makefile.generated libqmckl.so *.html *.fh - -Makefile.generated: $(ORG_SOURCE_FILES) Makefile create_makefile.sh - ./create_makefile.sh $(ORG_SOURCE_FILES) - diff --git a/src/README.org b/src/README.org deleted file mode 100644 index a895586..0000000 --- a/src/README.org +++ /dev/null @@ -1,213 +0,0 @@ -#+TITLE: QMCkl source code documentation -#+EXPORT_FILE_NAME: index.html - -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: - -* Introduction - - The ultimate goal of QMCkl is to provide a high-performance - implementation of the main kernels of QMC. In this particular - repository, we focus on the definition of the API and the tests, - and on a /pedagogical/ presentation of the algorithms. We expect the - HPC experts to use this repository as a reference for re-writing - optimized libraries. - - Literate programming is particularly adapted in this context. - Source files are written in [[https://karl-voit.at/2017/09/23/orgmode-as-markup-only/][org-mode]] format, to provide useful - comments and LaTex formulas close to the code. There exists multiple - possibilities to convert org-mode files into different formats such as - HTML or pdf. - For a tutorial on literate programming with org-mode, follow - [[http://www.howardism.org/Technical/Emacs/literate-programming-tutorial.html][this link]]. - - The code is extracted from the org files using Emacs as a command-line - tool in the =Makefile=, and then the produced files are compiled. - -** Language used - - Fortran is one of the most common languages used by the community, - and is simple enough to make the algorithms readable. Hence we - propose in this pedagogical implementation of QMCkl to use Fortran - to express the algorithms. For specific internal functions where - the C language is more natural, C is used. - - As Fortran modules generate compiler-dependent files, the use of - modules is restricted to the internal use of the library, otherwise - the compliance with C is violated. - - The external dependencies should be kept as small as possible, so - external libraries should be used /only/ if their used is strongly - justified. - -** Source code editing - - Any text editor can be used to edit org-mode files. For a better - user experience Emacs is recommended. - For users hating Emacs, it is good to know that Emacs can behave - like Vim when switched into ``Evil'' mode. There also exists - [[https://www.spacemacs.org][Spacemacs]] which helps the transition for Vim users. - - For users with a preference for Jupyter notebooks, the following - script can convert jupyter notebooks to org-mode files: - - #+BEGIN_SRC sh tangle: nb_to_org.sh -#!/bin/bash -# $ nb_to_org.sh notebook.ipynb -# produces the org-mode file notebook.org - -set -e - -nb=$(basename $1 .ipynb) -jupyter nbconvert --to markdown ${nb}.ipynb --output ${nb}.md -pandoc ${nb}.md -o ${nb}.org -rm ${nb}.md - #+END_SRC - - And pandoc can convert multiple markdown formats into org-mode. - -** Writing in Fortran - - The Fortran source files should provide a C interface using - =iso_c_binding=. The name of the Fortran source files should end - with =_f.f90= to be properly handled by the Makefile. - The names of the functions defined in fortran should be the same as - those exposed in the API suffixed by =_f=. - Fortran interface files should also be written in a file with a - =.fh= extension. - -** Coding style - # TODO: decide on a coding style - - To improve readability, we maintain a consistent coding style in the library. - - - For C source files, we will use __(decide on a coding style)__ - - For Fortran source files, we will use __(decide on a coding style)__ - - Coding style can be automatically checked with [[https://clang.llvm.org/docs/ClangFormat.html][clang-format]]. - -* Design of the library - - The proposed API should allow the library to: - - deal with memory transfers between CPU and accelerators - - use different levels of floating-point precision - - We chose a multi-layered design with low-level and high-level - functions (see below). - -** Naming conventions - - Use =qmckl_= as a prefix for all exported functions and variables. - All exported header files should have a filename with the prefix - =qmckl_=. - - If the name of the org-mode file is =xxx.org=, the name of the - produced C files should be =xxx.c= and =xxx.h= and the name of the - produced Fortran files should be =xxx.f90= - - Arrays are in uppercase and scalars are in lowercase. - -** Application programming interface - - The application programming interface (API) is designed to be - compatible with the C programming language (not C++), to ensure - that the library will be easily usable in any language. - This implies that only the following data types are allowed in the API: - - - 32-bit and 64-bit floats and arrays (=real= and =double=) - - 32-bit and 64-bit integers and arrays (=int32_t= and =int64_t=) - - Pointers should be represented as 64-bit integers (even on - 32-bit architectures) - - ASCII strings are represented as a pointers to a character arrays - and terminated by a zero character (C convention). - - # TODO : Link to repositories for bindings - To facilitate the use in other languages than C, we provide some - bindings in other languages in other repositories. - -** Global state - - Global variables should be avoided in the library, because it is - possible that one single program needs to use multiple instances of - the library. To solve this problem we propose to use a pointer to a - =context= variable, built by the library with the - =qmckl_context_create= function. The =context= contains the global - state of the library, and is used as the first argument of many - QMCkl functions. - - Modifying the state is done by setters and getters, prefixed - by =qmckl_context_set_= an =qmckl_context_get_=. - When a context variable is modified by a setter, a copy of the old - data structure is made and updated, and the pointer to the new data - structure is returned, such that the old contexts can still be - accessed. - It is also possible to modify the state in an impure fashion, using - the =qmckl_context_update_= functions. - The context and its old versions can be destroyed with - =qmckl_context_destroy=. - -** Low-level functions - - Low-level functions are very simple functions which are leaves of the - function call tree (they don't call any other QMCkl function). - - This functions are /pure/, and unaware of the QMCkl =context=. They are - not allowed to allocate/deallocate memory, and if they need - temporary memory it should be provided in input. - -** High-level functions - - High-level functions are at the top of the function call tree. - They are able to choose which lower-level function to call - depending on the required precision, and do the corresponding type - conversions. - These functions are also responsible for allocating temporary - storage, to simplify the use of accelerators. - - The high-level functions should be pure, unless the introduction of - non-purity is justified. All the side effects should be made in the - =context= variable. - - # TODO : We need an identifier for impure functions - -** Numerical precision - - The number of bits of precision required for a function should be - given as an input of low-level computational functions. This input will - be used to define the values of the different thresholds that might - be used to avoid computing unnecessary noise. - High-level functions will use the precision specified in the - =context= variable. - -* Algorithms - - Reducing the scaling of an algorithm usually implies also reducing - its arithmetic complexity (number of flops per byte). Therefore, - for small sizes \(\mathcal{O}(N^3)\) and \(\mathcal{O}(N^2)\) algorithms - are better adapted than linear scaling algorithms. - As QMCkl is a general purpose library, multiple algorithms should - be implemented adapted to different problem sizes. - -* Rules for the API - - - =stdint= should be used for integers (=int32_t=, =int64_t=) - - integers used for counting should always be =int64_t= - - floats should be by default =double=, unless explicitly mentioned - - pointers are converted to =int64_t= to increase portability - -* Documentation - - - [[./qmckl.org][Main QMCkl header file]] - - [[./qmckl_memory.org][Memory management]] - - [[./qmckl_context.org][Context]] - - [[./qmckl_distance.org][Distance]] - - [[./qmckl_ao.org][Atomic orbitals]] - -* Acknowledgments - - [[https://trex-coe.eu/sites/default/files/inline-images/euflag.jpg]] - [[https://trex-coe.eu][TREX: Targeting Real Chemical Accuracy at the Exascale]] project has received funding from the European Union’s Horizon 2020 - Research and Innovation program - under grant agreement no. 952165. The content of this document does not represent the opinion of the European Union, and the European Union is not responsible for any use that might be made of such content. diff --git a/src/config.el b/src/config.el deleted file mode 100755 index 9395d1d..0000000 --- a/src/config.el +++ /dev/null @@ -1,87 +0,0 @@ -(require 'org) -(require 'font-lock) - -(require 'subr-x) ;; for `when-let' - -(unless (boundp 'maximal-integer) - (defconst maximal-integer (lsh -1 -1) - "Maximal integer value representable natively in emacs lisp.")) - -(defun face-spec-default (spec) - "Get list containing at most the default entry of face SPEC. -Return nil if SPEC has no default entry." - (let* ((first (car-safe spec)) - (display (car-safe first))) - (when (eq display 'default) - (list (car-safe spec))))) - -(defun face-spec-min-color (display-atts) - "Get min-color entry of DISPLAY-ATTS pair from face spec." - (let* ((display (car-safe display-atts))) - (or (car-safe (cdr (assoc 'min-colors display))) - maximal-integer))) - -(defun face-spec-highest-color (spec) - "Search face SPEC for highest color. -That means the DISPLAY entry of SPEC -with class 'color and highest min-color value." - (let ((color-list (cl-remove-if-not - (lambda (display-atts) - (when-let ((display (car-safe display-atts)) - (class (and (listp display) - (assoc 'class display))) - (background (assoc 'background display))) - (and (member 'light (cdr background)) - (member 'color (cdr class))))) - spec))) - (cl-reduce (lambda (display-atts1 display-atts2) - (if (> (face-spec-min-color display-atts1) - (face-spec-min-color display-atts2)) - display-atts1 - display-atts2)) - (cdr color-list) - :initial-value (car color-list)))) - -(defun face-spec-t (spec) - "Search face SPEC for fall back." - (cl-find-if (lambda (display-atts) - (eq (car-safe display-atts) t)) - spec)) - -(defun my-face-attribute (face attribute &optional frame inherit) - "Get FACE ATTRIBUTE from `face-user-default-spec' and not from `face-attribute'." - (let* ((face-spec (face-user-default-spec face)) - (display-attr (or (face-spec-highest-color face-spec) - (face-spec-t face-spec))) - (attr (cdr display-attr)) - (val (or (plist-get attr attribute) (car-safe (cdr (assoc attribute attr)))))) - ;; (message "attribute: %S" attribute) ;; for debugging - (when (and (null (eq attribute :inherit)) - (null val)) - (let ((inherited-face (my-face-attribute face :inherit))) - (when (and inherited-face - (null (eq inherited-face 'unspecified))) - (setq val (my-face-attribute inherited-face attribute))))) - ;; (message "face: %S attribute: %S display-attr: %S, val: %S" face attribute display-attr val) ;; for debugging - (or val 'unspecified))) - -(advice-add 'face-attribute :override #'my-face-attribute) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Debugging: -(defmacro print-args-and-ret (fun) - "Prepare FUN for printing args and return value." - `(advice-add (quote ,fun) :around - (lambda (oldfun &rest args) - (let ((ret (apply oldfun args))) - (message ,(concat "Calling " (symbol-name fun) " with args %S returns %S.") args ret) - ret)) - '((name "print-args-and-ret")))) - -; (print-args-and-ret htmlize-faces-in-buffer) -; (print-args-and-ret htmlize-get-override-fstruct) -; (print-args-and-ret htmlize-face-to-fstruct) -; (print-args-and-ret htmlize-attrlist-to-fstruct) -; (print-args-and-ret face-foreground) -; (print-args-and-ret face-background) -; (print-args-and-ret face-attribute) diff --git a/src/create_doc.sh b/src/create_doc.sh deleted file mode 100755 index e85ff5b..0000000 --- a/src/create_doc.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -# Tangle org files - -emacsclient -a "" \ - --socket-name=org_to_code \ - --eval "(load-file \"config.el\")" - -for INPUT in $@ ; do - echo $INPUT - emacsclient \ - --no-wait \ - --socket-name=org_to_code \ - --eval "(find-file \"$INPUT\")" \ - --eval "(org-html-export-to-html)" -done -mv *.html ../docs - -emacsclient \ - --no-wait \ - --socket-name=org_to_code \ - --eval '(kill-emacs)' - diff --git a/src/create_makefile.sh b/src/create_makefile.sh deleted file mode 100755 index 3ff14b9..0000000 --- a/src/create_makefile.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/bin/bash - -OUTPUT=Makefile.generated - -# Tangle org files - -emacsclient -a "" \ - --socket-name=org_to_code \ - --eval "(require 'org)" - -for INPUT in $@ ; do - emacsclient \ - --no-wait \ - --socket-name=org_to_code \ - --eval "(org-babel-tangle-file \"$INPUT\")" -done - -emacsclient \ - --no-wait \ - --socket-name=org_to_code \ - --eval '(kill-emacs)' - - - -# Create the list of *.o files to be created - -OBJECTS="" -for i in $(ls qmckl_*.c) ; do - FILE=${i%.c} - OBJECTS="${OBJECTS} ${FILE}.o" -done >> $OUTPUT - -for i in $(ls qmckl_*.f90) ; do - FILE=${i%.f90} - OBJECTS="${OBJECTS} ${FILE}.o" -done >> $OUTPUT - -TESTS="" -for i in $(ls test_qmckl_*.c) ; do - FILE=${i%.c}.o - TESTS="${TESTS} ${FILE}" -done >> $OUTPUT - -TESTS_F="" -for i in $(ls test_qmckl_*.f90) ; do - FILE=${i%.f90}.o - TESTS_F="${TESTS_F} ${FILE}" -done >> $OUTPUT - - -# Write the Makefile - -cat << EOF > $OUTPUT -CC=$CC -CFLAGS=$CFLAGS -I../munit/ - -FC=$FC -FFLAGS=$FFLAGS -OBJECT_FILES=$OBJECTS -TESTS=$TESTS -TESTS_F=$TESTS_F - -LIBS=$LIBS - -libqmckl.so: \$(OBJECT_FILES) - \$(CC) -shared \$(OBJECT_FILES) -o libqmckl.so - -%.o: %.c - \$(CC) \$(CFLAGS) -c \$*.c -o \$*.o - -%.o: %.f90 - \$(FC) \$(FFLAGS) -c \$*.f90 -o \$*.o - -test_qmckl: test_qmckl.c libqmckl.so \$(TESTS) \$(TESTS_F) - \$(CC) \$(CFLAGS) -Wl,-rpath,$PWD -L. \ - ../munit/munit.c \$(TESTS) \$(TESTS_F) -lqmckl \$(LIBS) test_qmckl.c -o test_qmckl - -test: test_qmckl - ./test_qmckl - -.PHONY: test -EOF - -for i in $(ls qmckl_*.c) ; do - FILE=${i%.c} - echo "${FILE}.o: ${FILE}.c " *.h -done >> $OUTPUT - -for i in $(ls qmckl_*.f90) ; do - FILE=${i%.f90} - echo "${FILE}.o: ${FILE}.f90" -done >> $OUTPUT - -for i in $(ls test_qmckl_*.c) ; do - FILE=${i%.c} - echo "${FILE}.o: ${FILE}.c qmckl.h" -done >> $OUTPUT - - -for i in $(ls test_qmckl*.f90) ; do - FILE=${i%.f90} - echo "${FILE}.o: ${FILE}.f90" -done >> $OUTPUT - - diff --git a/src/qmckl.org b/src/qmckl.org deleted file mode 100644 index c48e771..0000000 --- a/src/qmckl.org +++ /dev/null @@ -1,70 +0,0 @@ -# -*- mode: org -*- -# vim: syntax=c -#+TITLE: QMCkl C header - -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: - -This file produces the =qmckl.h= header file, which is included in all -other C header files. It is the main entry point to the library. - -#+BEGIN_SRC C :tangle qmckl.h -#ifndef QMCKL_H -#define QMCKL_H -#include -#include -#+END_SRC - -* Constants - -** Success/failure - - These are the codes returned by the functions to indicate success - or failure. All such functions should have as a return type =qmckl_exit_code=. - - #+BEGIN_SRC C :tangle qmckl.h -#define QMCKL_SUCCESS 0 -#define QMCKL_FAILURE 1 - -typedef int32_t qmckl_exit_code; -typedef int64_t qmckl_context ; - - #+END_SRC - - -** Precision-related constants - - Controlling numerical precision enables optimizations. Here, the - default parameters determining the target numerical precision and - range are defined. - - #+BEGIN_SRC C :tangle qmckl.h -#define QMCKL_DEFAULT_PRECISION 53 -#define QMCKL_DEFAULT_RANGE 11 - #+END_SRC - -* Header files - - All the functions expoed in the API are defined in the following - header files. - - #+BEGIN_SRC C :tangle qmckl.h - -#include "qmckl_memory.h" -#include "qmckl_context.h" - -#include "qmckl_distance.h" -#include "qmckl_ao.h" - #+END_SRC - -* End of header - -#+BEGIN_SRC C :tangle qmckl.h -#endif -#+END_SRC - - diff --git a/src/qmckl_ao.org b/src/qmckl_ao.org deleted file mode 100644 index c8e57a4..0000000 --- a/src/qmckl_ao.org +++ /dev/null @@ -1,495 +0,0 @@ -# -*- mode: org -*- -# vim: syntax=c -#+TITLE: Atomic Orbitals - -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: - -This files contains all the routines for the computation of the -values, gradients and Laplacian of the atomic basis functions. - -4 files are produced: -- a header file : =qmckl_ao.h= -- a source file : =qmckl_ao.f90= -- a C test file : =test_qmckl_ao.c= -- a Fortran test file : =test_qmckl_ao_f.f90= - -*** Header :noexport: - #+BEGIN_SRC C :comments link :tangle qmckl_ao.h -#ifndef QMCKL_AO_H -#define QMCKL_AO_H -#include "qmckl_context.h" -#include "qmckl_distance.h" - #+END_SRC - -*** Test :noexport: - #+BEGIN_SRC C :comments link :tangle test_qmckl_ao.c -#include -#include "qmckl.h" -#include "munit.h" -MunitResult test_qmckl_ao() { - qmckl_context context; - context = qmckl_context_create(); - #+END_SRC - - -* Polynomials - - \[ - P_l(\mathbf{r},\mathbf{R}_i) = (x-X_i)^a (y-Y_i)^b (z-Z_i)^c - \] - \begin{eqnarray*} - \frac{\partial }{\partial x} P_l\left(\mathbf{r},\mathbf{R}_i \right) & = & a (x-X_i)^{a-1} (y-Y_i)^b (z-Z_i)^c \\ - \frac{\partial }{\partial y} P_l\left(\mathbf{r},\mathbf{R}_i \right) & = & b (x-X_i)^a (y-Y_i)^{b-1} (z-Z_i)^c \\ - \frac{\partial }{\partial z} P_l\left(\mathbf{r},\mathbf{R}_i \right) & = & c (x-X_i)^a (y-Y_i)^b (z-Z_i)^{c-1} \\ - \end{eqnarray*} - \begin{eqnarray*} - \left( \frac{\partial }{\partial x^2} + - \frac{\partial }{\partial y^2} + - \frac{\partial }{\partial z^2} \right) P_l - \left(\mathbf{r},\mathbf{R}_i \right) & = & - a(a-1) (x-X_i)^{a-2} (y-Y_i)^b (z-Z_i)^c + \\ - && b(b-1) (x-X_i)^a (y-Y_i)^{b-1} (z-Z_i)^c + \\ - && c(c-1) (x-X_i)^a (y-Y_i)^b (z-Z_i)^{c-1} - \end{eqnarray*} - -** =qmckl_ao_powers= - - Computes all the powers of the =n= input data up to the given - maximum value given in input for each of the $n$ points: - - \[ P_{ij} = X_j^i \] - -*** Arguments - - | =context= | input | Global state | - | =n= | input | Number of values | - | =X(n)= | input | Array containing the input values | - | =LMAX(n)= | input | Array containing the maximum power for each value | - | =P(LDP,n)= | output | Array containing all the powers of =X= | - | =LDP= | input | Leading dimension of array =P= | - -*** Requirements - - - =context= is not 0 - - =n= > 0 - - =X= is allocated with at least $n \times 8$ bytes - - =LMAX= is allocated with at least $n \times 4$ bytes - - =P= is allocated with at least $n \times \max_i \text{LMAX}_i \times 8$ bytes - - =LDP= >= $\max_i$ =LMAX[i]= - -*** Header - #+BEGIN_SRC C :comments link :tangle qmckl_ao.h -qmckl_exit_code qmckl_ao_powers(qmckl_context context, - int64_t n, - double *X, int32_t *LMAX, - double *P, int64_t LDP); - #+END_SRC - -*** Source - #+BEGIN_SRC f90 :comments link :tangle qmckl_ao.f90 -integer function qmckl_ao_powers_f(context, n, X, LMAX, P, ldp) result(info) - implicit none - integer*8 , intent(in) :: context - integer*8 , intent(in) :: n - real*8 , intent(in) :: X(n) - integer , intent(in) :: LMAX(n) - real*8 , intent(out) :: P(ldp,n) - integer*8 , intent(in) :: ldp - - integer*8 :: i,j - - info = 0 - - if (context == 0_8) then - info = -1 - return - endif - - if (LDP < MAXVAL(LMAX)) then - info = -2 - return - endif - - do j=1,n - P(1,j) = X(j) - do i=2,LMAX(j) - P(i,j) = P(i-1,j) * X(j) - end do - end do - -end function qmckl_ao_powers_f - #+END_SRC - -*** C interface :noexport: - #+BEGIN_SRC f90 :comments link :tangle qmckl_ao.f90 -integer(c_int32_t) function qmckl_ao_powers(context, n, X, LMAX, P, ldp) & - 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 :: n - real (c_double) , intent(in) :: X(n) - integer (c_int32_t) , intent(in) :: LMAX(n) - real (c_double) , intent(out) :: P(ldp,n) - integer (c_int64_t) , intent(in) , value :: ldp - - integer, external :: qmckl_ao_powers_f - info = qmckl_ao_powers_f(context, n, X, LMAX, P, ldp) -end function qmckl_ao_powers - #+END_SRC - - #+BEGIN_SRC f90 :comments link :tangle qmckl_ao.fh - interface - integer(c_int32_t) function qmckl_ao_powers(context, n, X, LMAX, P, ldp) bind(C) - use, intrinsic :: iso_c_binding - integer (c_int64_t) , intent(in) , value :: context - integer (c_int64_t) , intent(in) , value :: n - integer (c_int64_t) , intent(in) , value :: ldp - real (c_double) , intent(in) :: X(n) - integer (c_int32_t) , intent(in) :: LMAX(n) - real (c_double) , intent(out) :: P(ldp,n) - end function qmckl_ao_powers - end interface - #+END_SRC - -*** Test :noexport: - #+BEGIN_SRC f90 :comments link :tangle test_qmckl_ao_f.f90 -integer(c_int32_t) function test_qmckl_ao_powers(context) bind(C) - use, intrinsic :: iso_c_binding - implicit none - include 'qmckl_ao.fh' - - integer(c_int64_t), intent(in), value :: context - - integer*8 :: n, LDP - integer, allocatable :: LMAX(:) - double precision, allocatable :: X(:), P(:,:) - integer*8 :: i,j - - n = 100; - LDP = 10; - - allocate(X(n), P(LDP,n), LMAX(n)) - - do j=1,n - X(j) = -5.d0 + 0.1d0 * dble(j) - LMAX(j) = 1 + int(mod(j, 9),4) - end do - - test_qmckl_ao_powers = qmckl_ao_powers(context, n, X, LMAX, P, LDP) - if (test_qmckl_ao_powers /= 0) return - - test_qmckl_ao_powers = -1 - - do j=1,n - do i=1,LMAX(j) - if ( dabs(1.d0 - P(i,j) / (X(j)**i)) > 1.d-14 ) return - end do - end do - - test_qmckl_ao_powers = 0 - deallocate(X,P,LMAX) -end function test_qmckl_ao_powers - #+END_SRC - - #+BEGIN_SRC C :comments link :tangle test_qmckl_ao.c -int test_qmckl_ao_powers(qmckl_context context); -munit_assert_int(0, ==, test_qmckl_ao_powers(context)); - #+END_SRC - -** =qmckl_ao_polynomial_vgl= - - Computes the values, gradients and Laplacians at a given point of - all polynomials with an angular momentum up to =lmax=. - -*** Arguments - - | =context= | input | Global state | - | =X(3)= | input | Array containing the coordinates of the points | - | =R(3)= | input | Array containing the x,y,z coordinates of the center | - | =lmax= | input | Maximum angular momentum | - | =n= | output | Number of computed polynomials | - | =L(ldl,n)= | output | Contains a,b,c for all =n= results | - | =ldl= | input | Leading dimension of =L= | - | =VGL(ldv,n)= | output | Value, gradients and Laplacian of the polynomials | - | =ldv= | input | Leading dimension of array =VGL= | - -*** Requirements - - - =context= is not 0 - - =n= > 0 - - =X= is allocated with at least $3 \times 8$ bytes - - =R= is allocated with at least $3 \times 8$ bytes - - =lmax= >= 0 - - On output, =n= should be equal to (=lmax=+1)(=lmax=+2)(=lmax=+3)/6 - - =L= is allocated with at least $3 \times n \times 4$ bytes - - =ldl= >= 3 - - =VGL= is allocated with at least $5 \times n \times 8$ bytes - - =ldv= >= 5 - -*** Header - #+BEGIN_SRC C :comments link :tangle qmckl_ao.h -qmckl_exit_code qmckl_ao_polynomial_vgl(qmckl_context context, - double *X, double *R, - int32_t lmax, int64_t *n, - int32_t *L, int64_t ldl, - double *VGL, int64_t ldv); - #+END_SRC - -*** Source - #+BEGIN_SRC f90 :comments link :tangle qmckl_ao.f90 -integer function qmckl_ao_polynomial_vgl_f(context, X, R, lmax, n, L, ldl, VGL, ldv) result(info) - implicit none - integer*8 , intent(in) :: context - real*8 , intent(in) :: X(3), R(3) - integer , intent(in) :: lmax - integer*8 , intent(out) :: n - integer , intent(out) :: L(ldl,(lmax+1)*(lmax+2)*(lmax+3)/6) - integer*8 , intent(in) :: ldl - real*8 , intent(out) :: VGL(ldv,(lmax+1)*(lmax+2)*(lmax+3)/6) - integer*8 , intent(in) :: ldv - - integer*8 :: i,j - integer :: a,b,c,d - real*8 :: Y(3) - integer :: lmax_array(3) - real*8 :: pows(-2:lmax,3) - integer, external :: qmckl_ao_powers_f - double precision :: xy, yz, xz - double precision :: da, db, dc, dd - - info = 0 - - if (context == 0_8) then - info = -1 - return - endif - - n = (lmax+1)*(lmax+2)*(lmax+3)/6 - - if (ldl < 3) then - info = -2 - return - endif - - if (ldv < 5) then - info = -3 - return - endif - - - do i=1,3 - Y(i) = X(i) - R(i) - end do - pows(-2:-1,1:3) = 0.d0 - pows(0,1:3) = 1.d0 - lmax_array(1:3) = lmax - info = qmckl_ao_powers_f(context, 1_8, Y(1), (/lmax/), pows(1,1), size(pows,1,kind=8)) - if (info /= 0) return - info = qmckl_ao_powers_f(context, 1_8, Y(2), (/lmax/), pows(1,2), size(pows,1,kind=8)) - if (info /= 0) return - info = qmckl_ao_powers_f(context, 1_8, Y(3), (/lmax/), pows(1,3), size(pows,1,kind=8)) - if (info /= 0) return - - - n=1 - vgl(1:5,1:n) = 0.d0 - l(1:3,n) = 0 - vgl(1,n) = 1.d0 - dd = 1.d0 - do d=1,lmax - da = 0.d0 - do a=0,d - db = 0.d0 - do b=0,d-a - c = d - a - b - dc = dd - da - db - n = n+1 - l(1,n) = a - l(2,n) = b - l(3,n) = c - - xy = pows(a,1) * pows(b,2) - yz = pows(b,2) * pows(c,3) - xz = pows(a,1) * pows(c,3) - - vgl(1,n) = xy * pows(c,3) - - xy = dc * xy - xz = db * xz - yz = da * yz - - vgl(2,n) = pows(a-1,1) * yz - vgl(3,n) = pows(b-1,2) * xz - vgl(4,n) = pows(c-1,3) * xy - - vgl(5,n) = & - (da-1.d0) * pows(a-2,1) * yz + & - (db-1.d0) * pows(b-2,2) * xz + & - (dc-1.d0) * pows(c-2,3) * xy - - db = db + 1.d0 - end do - da = da + 1.d0 - end do - dd = dd + 1.d0 - end do - -end function qmckl_ao_polynomial_vgl_f - #+END_SRC - -*** C interface :noexport: - #+BEGIN_SRC f90 :comments link :tangle qmckl_ao.f90 -integer(c_int32_t) function qmckl_ao_polynomial_vgl(context, X, R, lmax, n, L, ldl, VGL, ldv) & - bind(C) result(info) - use, intrinsic :: iso_c_binding - implicit none - integer (c_int64_t) , intent(in) , value :: context - real (c_double) , intent(in) :: X(3), R(3) - integer (c_int32_t) , intent(in) , value :: lmax - integer (c_int64_t) , intent(out) :: n - integer (c_int32_t) , intent(out) :: L(ldl,(lmax+1)*(lmax+2)*(lmax+3)/6) - integer (c_int64_t) , intent(in) , value :: ldl - real (c_double) , intent(out) :: VGL(ldv,(lmax+1)*(lmax+2)*(lmax+3)/6) - integer (c_int64_t) , intent(in) , value :: ldv - - integer, external :: qmckl_ao_polynomial_vgl_f - info = qmckl_ao_polynomial_vgl_f(context, X, R, lmax, n, L, ldl, VGL, ldv) -end function qmckl_ao_polynomial_vgl - #+END_SRC - - #+BEGIN_SRC f90 :comments link :tangle qmckl_ao.fh - interface - integer(c_int32_t) function qmckl_ao_polynomial_vgl(context, X, R, lmax, n, L, ldl, VGL, ldv) & - bind(C) - use, intrinsic :: iso_c_binding - integer (c_int64_t) , intent(in) , value :: context - integer (c_int32_t) , intent(in) , value :: lmax - integer (c_int64_t) , intent(in) , value :: ldl - integer (c_int64_t) , intent(in) , value :: ldv - real (c_double) , intent(in) :: X(3), R(3) - integer (c_int64_t) , intent(out) :: n - integer (c_int32_t) , intent(out) :: L(ldl,(lmax+1)*(lmax+2)*(lmax+3)/6) - real (c_double) , intent(out) :: VGL(ldv,(lmax+1)*(lmax+2)*(lmax+3)/6) - end function qmckl_ao_polynomial_vgl - end interface - #+END_SRC -*** Test :noexport: - #+BEGIN_SRC f90 :comments link :tangle test_qmckl_ao_f.f90 -integer(c_int32_t) function test_qmckl_ao_polynomial_vgl(context) bind(C) - use, intrinsic :: iso_c_binding - implicit none - include 'qmckl_ao.fh' - - integer(c_int64_t), intent(in), value :: context - - integer :: lmax, d, i - integer, allocatable :: L(:,:) - integer*8 :: n, ldl, ldv, j - double precision :: X(3), R(3), Y(3) - double precision, allocatable :: VGL(:,:) - double precision :: w - - X = (/ 1.1 , 2.2 , 3.3 /) - R = (/ 0.1 , 1.2 , -2.3 /) - Y(:) = X(:) - R(:) - - lmax = 4; - n = 0; - ldl = 3; - ldv = 100; - - d = (lmax+1)*(lmax+2)*(lmax+3)/6 - - allocate (L(ldl,100), VGL(ldv,100)) - - test_qmckl_ao_polynomial_vgl = & - qmckl_ao_polynomial_vgl(context, X, R, lmax, n, L, ldl, VGL, ldv) - if (test_qmckl_ao_polynomial_vgl /= 0) return - - test_qmckl_ao_polynomial_vgl = -1 - - if (n /= d) return - - do j=1,n - do i=1,3 - if (L(i,j) < 0) return - end do - if (dabs(1.d0 - VGL(1,j) / (& - Y(1)**L(1,j) * Y(2)**L(2,j) * Y(3)**L(3,j) & - )) > 1.d-14 ) return - - if (L(1,j) < 1) then - if (VGL(2,j) /= 0.d0) return - else - if (dabs(1.d0 - VGL(2,j) / (& - L(1,j) * Y(1)**(L(1,j)-1) * Y(2)**L(2,j) * Y(3)**L(3,j) & - )) > 1.d-14 ) return - end if - - if (L(2,j) < 1) then - if (VGL(3,j) /= 0.d0) return - else - if (dabs(1.d0 - VGL(3,j) / (& - L(2,j) * Y(1)**L(1,j) * Y(2)**(L(2,j)-1) * Y(3)**L(3,j) & - )) > 1.d-14 ) return - end if - - if (L(3,j) < 1) then - if (VGL(4,j) /= 0.d0) return - else - if (dabs(1.d0 - VGL(4,j) / (& - L(3,j) * Y(1)**L(1,j) * Y(2)**L(2,j) * Y(3)**(L(3,j)-1) & - )) > 1.d-14 ) return - end if - - w = 0.d0 - if (L(1,j) > 1) then - w = w + L(1,j) * (L(1,j)-1) * Y(1)**(L(1,j)-2) * Y(2)**L(2,j) * Y(3)**L(3,j) - end if - if (L(2,j) > 1) then - w = w + L(2,j) * (L(2,j)-1) * Y(1)**L(1,j) * Y(2)**(L(2,j)-2) * Y(3)**L(3,j) - end if - if (L(3,j) > 1) then - w = w + L(3,j) * (L(3,j)-1) * Y(1)**L(1,j) * Y(2)**L(2,j) * Y(3)**(L(3,j)-2) - end if - if (dabs(1.d0 - VGL(5,j) / w) > 1.d-14 ) return - end do - - test_qmckl_ao_polynomial_vgl = 0 - - deallocate(L,VGL) -end function test_qmckl_ao_polynomial_vgl - #+END_SRC - - #+BEGIN_SRC C :comments link :tangle test_qmckl_ao.c -int test_qmckl_ao_polynomial_vgl(qmckl_context context); -munit_assert_int(0, ==, test_qmckl_ao_polynomial_vgl(context)); - #+END_SRC - #+END_SRC - - -* TODO Gaussian basis functions - -* TODO Slater basis functions - -* End of files :noexport: - -*** Header - #+BEGIN_SRC C :comments link :tangle qmckl_ao.h -#endif - #+END_SRC - -*** Test - #+BEGIN_SRC C :comments link :tangle test_qmckl_ao.c - if (qmckl_context_destroy(context) != QMCKL_SUCCESS) - return QMCKL_FAILURE; - return MUNIT_OK; -} - - #+END_SRC diff --git a/src/qmckl_context.org b/src/qmckl_context.org deleted file mode 100644 index 00ca914..0000000 --- a/src/qmckl_context.org +++ /dev/null @@ -1,406 +0,0 @@ -# -*- mode: org -*- -# vim: syntax=c -#+TITLE: Context - -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: - - -This file is written in C because it is more natural to express the context in -C than in Fortran. - -3 files are produced: -- a header file : =qmckl_context.h= -- a source file : =qmckl_context.c= -- a test file : =test_qmckl_context.c= - -*** Header :noexport: - #+BEGIN_SRC C :comments link :tangle qmckl_context.h -#ifndef QMCKL_CONTEXT_H -#define QMCKL_CONTEXT_H -#include "qmckl.h" - #+END_SRC - -*** Source :noexport: - #+BEGIN_SRC C :comments link :tangle qmckl_context.c -#include "qmckl.h" - #+END_SRC - -*** Test :noexport: - #+BEGIN_SRC C :comments link :tangle test_qmckl_context.c -#include "qmckl.h" -#include "munit.h" -MunitResult test_qmckl_context() { - #+END_SRC - -* Context - - The context variable is a handle for the state of the library, and - is stored in the following data structure, which can't be seen - outside of the library. To simplify compatibility with other - languages, the pointer to the internal data structure is converted - into a 64-bit signed integer, defined in the =qmckl_context= type. - A value of 0 for the context is equivalent to a =NULL= pointer. - -*** Source - #+BEGIN_SRC C :comments link :tangle qmckl_context.c -typedef struct qmckl_context_struct { - struct qmckl_context_struct * prev; - uint32_t tag; - int32_t precision; - int32_t range; -} qmckl_context_struct; - -#define VALID_TAG 0xBEEFFACE -#define INVALID_TAG 0xDEADBEEF - #+END_SRC - - The tag is used internally to check if the memory domain pointed by - a pointer is a valid context. - -*** Test :noexport: - We declare here the variables used in the tests. - #+BEGIN_SRC C :comments link :tangle test_qmckl_context.c - qmckl_context context; - qmckl_context new_context; - #+END_SRC - - -** =qmckl_context_check= - - Checks if the domain pointed by the pointer is a valid context. - Returns the input =qmckl_context= if the context is valid, 0 otherwise. - -*** Header - #+BEGIN_SRC C :comments link :tangle qmckl_context.h -qmckl_context qmckl_context_check(const qmckl_context context) ; - #+END_SRC - -*** Source - #+BEGIN_SRC C :comments link :tangle qmckl_context.c -qmckl_context qmckl_context_check(const qmckl_context context) { - qmckl_context_struct * ctx; - - if (context == (qmckl_context) 0) return (qmckl_context) 0; - - ctx = (qmckl_context_struct*) context; - if (ctx->tag != VALID_TAG) return (qmckl_context) 0; - - return context; -} - #+END_SRC - -** =qmckl_context_create= - - To create a new context, use =qmckl_context_create()=. - - On success, returns a pointer to a context using the =qmckl_context= type - - Returns 0 upon failure to allocate the internal data structure - -*** Header - #+BEGIN_SRC C :comments link :tangle qmckl_context.h -qmckl_context qmckl_context_create(); - #+END_SRC - -*** Source - #+BEGIN_SRC C :comments link :tangle qmckl_context.c -qmckl_context qmckl_context_create() { - - qmckl_context_struct* context; - - context = (qmckl_context_struct*) qmckl_malloc ((qmckl_context) 0, sizeof(qmckl_context_struct)); - if (context == NULL) { - return (qmckl_context) 0; - } - - context->prev = NULL; - context->precision = QMCKL_DEFAULT_PRECISION; - context->range = QMCKL_DEFAULT_RANGE; - context->tag = VALID_TAG; - - return (qmckl_context) context; -} - #+END_SRC - -*** Test :noexport: - #+BEGIN_SRC C :comments link :tangle test_qmckl_context.c - context = qmckl_context_create(); - munit_assert_int64( context, !=, (qmckl_context) 0); - munit_assert_int64( qmckl_context_check(context), ==, context); - #+END_SRC - -** =qmckl_context_copy= - - This function makes a shallow copy of the current context. - - Copying the 0-valued context returns 0 - - On success, returns a pointer to the new context using the =qmckl_context= type - - Returns 0 upon failure to allocate the internal data structure - for the new context - -*** Header - #+BEGIN_SRC C :comments link :tangle qmckl_context.h -qmckl_context qmckl_context_copy(const qmckl_context context); - #+END_SRC - -*** Source - #+BEGIN_SRC C :comments link :tangle qmckl_context.c -qmckl_context qmckl_context_copy(const qmckl_context context) { - - qmckl_context_struct* old_context; - qmckl_context_struct* new_context; - qmckl_context checked_context; - - checked_context = qmckl_context_check(context); - - if (checked_context == (qmckl_context) 0) { - return (qmckl_context) 0; - } - - new_context = (qmckl_context_struct*) qmckl_malloc (context, sizeof(qmckl_context_struct)); - if (new_context == NULL) { - return (qmckl_context) 0; - } - - old_context = (qmckl_context_struct*) checked_context; - - new_context->prev = old_context; - new_context->precision = old_context->precision; - new_context->range = old_context->range; - new_context->tag = VALID_TAG; - - return (qmckl_context) new_context; -} - - #+END_SRC - -*** Test :noexport: - #+BEGIN_SRC C :comments link :tangle test_qmckl_context.c - new_context = qmckl_context_copy(context); - munit_assert_int64(new_context, !=, (qmckl_context) 0); - munit_assert_int64(new_context, !=, context); - munit_assert_int64(qmckl_context_check(new_context), ==, new_context); - #+END_SRC - -** =qmckl_context_previous= - - Returns the previous context - - On success, returns the ancestor of the current context - - Returns 0 for the initial context - - Returns 0 for the 0-valued context - -*** Header - #+BEGIN_SRC C :comments link :tangle qmckl_context.h -qmckl_context qmckl_context_previous(const qmckl_context context); - #+END_SRC - -*** Source - #+BEGIN_SRC C :comments link :tangle qmckl_context.c -qmckl_context qmckl_context_previous(const qmckl_context context) { - - qmckl_context checked_context; - qmckl_context_struct* ctx; - - checked_context = qmckl_context_check(context); - if (checked_context == (qmckl_context) 0) { - return (qmckl_context) 0; - } - - ctx = (qmckl_context_struct*) checked_context; - return qmckl_context_check((qmckl_context) ctx->prev); -} - #+END_SRC - -*** Test :noexport: - #+BEGIN_SRC C :comments link :tangle test_qmckl_context.c - munit_assert_int64(qmckl_context_previous(new_context), !=, (qmckl_context) 0); - munit_assert_int64(qmckl_context_previous(new_context), ==, context); - munit_assert_int64(qmckl_context_previous(context), ==, (qmckl_context) 0); - munit_assert_int64(qmckl_context_previous((qmckl_context) 0), ==, (qmckl_context) 0); - #+END_SRC - -** =qmckl_context_destroy= - - Destroys the current context, leaving the ancestors untouched. - - Succeeds if the current context is properly destroyed - - Fails otherwise - - Fails if the 0-valued context is given in argument - - Fails if the the pointer is not a valid context - -*** Header - #+BEGIN_SRC C :comments link :tangle qmckl_context.h -qmckl_exit_code qmckl_context_destroy(qmckl_context context); - #+END_SRC - -*** Source - #+BEGIN_SRC C :comments link :tangle qmckl_context.c -qmckl_exit_code qmckl_context_destroy(qmckl_context context) { - - qmckl_context_struct* ctx; - qmckl_context checked_context; - - checked_context = qmckl_context_check(context); - if (checked_context == (qmckl_context) 0) return QMCKL_FAILURE; - - ctx = (qmckl_context_struct*) context; - if (ctx == NULL) return QMCKL_FAILURE; - - ctx->tag = INVALID_TAG; - qmckl_free(ctx); - return QMCKL_SUCCESS; -} - #+END_SRC - -*** Test :noexport: - #+BEGIN_SRC C :comments link :tangle test_qmckl_context.c - munit_assert_int64(qmckl_context_check(new_context), ==, new_context); - munit_assert_int64(new_context, !=, (qmckl_context) 0); - munit_assert_int32(qmckl_context_destroy(new_context), ==, QMCKL_SUCCESS); - munit_assert_int64(qmckl_context_check(new_context), !=, new_context); - munit_assert_int64(qmckl_context_check(new_context), ==, (qmckl_context) 0); - munit_assert_int64(qmckl_context_destroy((qmckl_context) 0), ==, QMCKL_FAILURE); - #+END_SRC - - -* Precision - - The following functions set and get the expected required precision - and range. =precision= should be an integer between 2 and 53, and - =range= should be an integer between 2 and 11. - - The setter functions functions return a new context as a 64-bit integer. - The getter functions return the value, as a 32-bit integer. - The update functions return =QMCKL_SUCCESS= or =QMCKL_FAILURE=. - -** =qmckl_context_update_precision= -*** Source - #+BEGIN_SRC C :comments link :tangle qmckl_context.h -qmckl_exit_code qmckl_context_update_precision(const qmckl_context context, const int precision); - #+END_SRC - - #+BEGIN_SRC C :comments link :tangle qmckl_context.c -qmckl_exit_code qmckl_context_update_precision(const qmckl_context context, const int precision) { - qmckl_context_struct* ctx; - - if (precision < 2) return QMCKL_FAILURE; - if (precision > 53) return QMCKL_FAILURE; - - ctx = (qmckl_context_struct*) context; - if (ctx == NULL) return QMCKL_FAILURE; - - ctx->precision = precision; - return QMCKL_SUCCESS; -} - #+END_SRC - -*** TODO Tests :noexport: -** =qmckl_context_update_range= -*** Source - #+BEGIN_SRC C :comments link :tangle qmckl_context.h -qmckl_exit_code qmckl_context_update_range(const qmckl_context context, const int range); - #+END_SRC - - #+BEGIN_SRC C :comments link :tangle qmckl_context.c -qmckl_exit_code qmckl_context_update_range(const qmckl_context context, const int range) { - qmckl_context_struct* ctx; - - if (range < 2) return QMCKL_FAILURE; - if (range > 11) return QMCKL_FAILURE; - - ctx = (qmckl_context_struct*) context; - if (ctx == NULL) return QMCKL_FAILURE; - - ctx->range = range; - return QMCKL_SUCCESS; -} - #+END_SRC - -*** TODO Tests :noexport: -** =qmckl_context_set_precision= -*** Source - #+BEGIN_SRC C :comments link :tangle qmckl_context.h -qmckl_context qmckl_context_set_precision(const qmckl_context context, const int precision); - #+END_SRC - - #+BEGIN_SRC C :comments link :tangle qmckl_context.c -qmckl_context qmckl_context_set_precision(const qmckl_context context, const int precision) { - qmckl_context new_context; - - new_context = qmckl_context_copy(context); - if (new_context == 0) return 0; - - if (qmckl_context_update_precision(context, precision) == QMCKL_FAILURE) return 0; - - return new_context; -} - #+END_SRC - -*** TODO Tests :noexport: -** =qmckl_context_set_range= -*** Source - #+BEGIN_SRC C :comments link :tangle qmckl_context.h -qmckl_context qmckl_context_set_range(const qmckl_context context, const int range); - #+END_SRC - - #+BEGIN_SRC C :comments link :tangle qmckl_context.c -qmckl_context qmckl_context_set_range(const qmckl_context context, const int range) { - qmckl_context new_context; - - new_context = qmckl_context_copy(context); - if (new_context == 0) return 0; - - if (qmckl_context_update_range(context, range) == QMCKL_FAILURE) return 0; - - return new_context; -} - #+END_SRC - -*** TODO Tests :noexport: - -** =qmckl_context_get_precision= -*** Source - #+BEGIN_SRC C :comments link :tangle qmckl_context.h -int qmckl_context_get_precision(const qmckl_context context); - #+END_SRC - - #+BEGIN_SRC C :comments link :tangle qmckl_context.c -int qmckl_context_get_precision(const qmckl_context context) { - qmckl_context_struct* ctx; - ctx = (qmckl_context_struct*) context; - return ctx->precision; -} - #+END_SRC - -*** TODO Tests :noexport: -** =qmckl_context_get_range= -*** Source - - #+BEGIN_SRC C :comments link :tangle qmckl_context.h -int qmckl_context_get_range(const qmckl_context context); - #+END_SRC - - #+BEGIN_SRC C :comments link :tangle qmckl_context.c -int qmckl_context_get_range(const qmckl_context context) { - qmckl_context_struct* ctx; - ctx = (qmckl_context_struct*) context; - return ctx->range; -} - #+END_SRC - -*** TODO Tests :noexport: - -* End of files :noexport: - -*** Header - #+BEGIN_SRC C :comments link :tangle qmckl_context.h -#endif - #+END_SRC - -*** Test - #+BEGIN_SRC C :comments link :tangle test_qmckl_context.c - return MUNIT_OK; -} - #+END_SRC - diff --git a/src/qmckl_distance.org b/src/qmckl_distance.org deleted file mode 100644 index 6795b98..0000000 --- a/src/qmckl_distance.org +++ /dev/null @@ -1,378 +0,0 @@ -# -*- mode: org -*- -# vim: syntax=c -#+TITLE: Computation of distances - -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: - -Function for the computation of distances between particles. - -3 files are produced: -- a header file : =qmckl_distance.h= -- a source file : =qmckl_distance.f90= -- a C test file : =test_qmckl_distance.c= -- a Fortran test file : =test_qmckl_distance_f.f90= - -*** Header :noexport: - #+BEGIN_SRC C :comments link :tangle qmckl_distance.h -#ifndef QMCKL_DISTANCE_H -#define QMCKL_DISTANCE_H -#include "qmckl_context.h" - #+END_SRC - -*** Test :noexport: - #+BEGIN_SRC C :comments link :tangle test_qmckl_distance.c -#include -#include "qmckl.h" -#include "munit.h" -MunitResult test_qmckl_distance() { - qmckl_context context; - context = qmckl_context_create(); - - #+END_SRC - - -* Squared distance - -** =qmckl_distance_sq= - - Computes the matrix of the squared distances between all pairs of - points in two sets, one point within each set: - \[ - C_{ij} = \sum_{k=1}^3 (A_{k,i}-B_{k,j})^2 - \] - -*** Arguments - - | =context= | input | Global state | - | =transa= | input | Array =A= is =N=: Normal, =T=: Transposed | - | =transb= | input | Array =B= is =N=: Normal, =T=: Transposed | - | =m= | input | Number of points in the first set | - | =n= | input | Number of points in the second set | - | =A(lda,3)= | input | Array containing the $m \times 3$ matrix $A$ | - | =lda= | input | Leading dimension of array =A= | - | =B(ldb,3)= | input | Array containing the $n \times 3$ matrix $B$ | - | =ldb= | input | Leading dimension of array =B= | - | =C(ldc,n)= | output | Array containing the $m \times n$ matrix $C$ | - | =ldc= | input | Leading dimension of array =C= | - -*** Requirements - - - =context= is not 0 - - =m= > 0 - - =n= > 0 - - =lda= >= 3 if =transa= is =N= - - =lda= >= m if =transa= is =T= - - =ldb= >= 3 if =transb= is =N= - - =ldb= >= n if =transb= is =T= - - =ldc= >= m if =transa= is = - - =A= is allocated with at least $3 \times m \times 8$ bytes - - =B= is allocated with at least $3 \times n \times 8$ bytes - - =C= is allocated with at least $m \times n \times 8$ bytes - -*** Performance - - This function might be more efficient when =A= and =B= are - transposed. - -*** Header - #+BEGIN_SRC C :comments link :tangle qmckl_distance.h -qmckl_exit_code qmckl_distance_sq(qmckl_context context, - char transa, char transb, - int64_t m, int64_t n, - double *A, int64_t lda, - double *B, int64_t ldb, - double *C, int64_t ldc); - #+END_SRC - -*** Source - #+BEGIN_SRC f90 :comments link :tangle qmckl_distance.f90 -integer function qmckl_distance_sq_f(context, transa, transb, m, n, A, LDA, B, LDB, C, LDC) result(info) - implicit none - integer*8 , intent(in) :: context - character , intent(in) :: transa, transb - integer*8 , intent(in) :: m, n - integer*8 , intent(in) :: lda - real*8 , intent(in) :: A(lda,*) - integer*8 , intent(in) :: ldb - real*8 , intent(in) :: B(ldb,*) - integer*8 , intent(in) :: ldc - real*8 , intent(out) :: C(ldc,*) - - integer*8 :: i,j - real*8 :: x, y, z - integer :: transab - - info = 0 - - if (context == 0_8) then - info = -1 - return - endif - - if (m <= 0_8) then - info = -2 - return - endif - - if (n <= 0_8) then - info = -3 - return - endif - - if (transa == 'N' .or. transa == 'n') then - transab = 0 - else if (transa == 'T' .or. transa == 't') then - transab = 1 - else - transab = -100 - endif - - if (transb == 'N' .or. transb == 'n') then - continue - else if (transa == 'T' .or. transa == 't') then - transab = transab + 2 - else - transab = -100 - endif - - if (transab < 0) then - info = -4 - return - endif - - if (iand(transab,1) == 0 .and. LDA < 3) then - info = -5 - return - endif - - if (iand(transab,1) == 1 .and. LDA < m) then - info = -6 - return - endif - - if (iand(transab,2) == 0 .and. LDA < 3) then - info = -6 - return - endif - - if (iand(transab,2) == 2 .and. LDA < m) then - info = -7 - return - endif - - - select case (transab) - - case(0) - - do j=1,n - do i=1,m - x = A(1,i) - B(1,j) - y = A(2,i) - B(2,j) - z = A(3,i) - B(3,j) - C(i,j) = x*x + y*y + z*z - end do - end do - - case(1) - - do j=1,n - do i=1,m - x = A(i,1) - B(1,j) - y = A(i,2) - B(2,j) - z = A(i,3) - B(3,j) - C(i,j) = x*x + y*y + z*z - end do - end do - - case(2) - - do j=1,n - do i=1,m - x = A(1,i) - B(j,1) - y = A(2,i) - B(j,2) - z = A(3,i) - B(j,3) - C(i,j) = x*x + y*y + z*z - end do - end do - - case(3) - - do j=1,n - do i=1,m - x = A(i,1) - B(j,1) - y = A(i,2) - B(j,2) - z = A(i,3) - B(j,3) - C(i,j) = x*x + y*y + z*z - end do - end do - - end select - -end function qmckl_distance_sq_f - #+END_SRC - -*** C interface :noexport: - #+BEGIN_SRC f90 :comments link :tangle qmckl_distance.f90 -integer(c_int32_t) function qmckl_distance_sq(context, transa, transb, m, n, A, LDA, B, LDB, C, LDC) & - bind(C) result(info) - use, intrinsic :: iso_c_binding - implicit none - integer (c_int64_t) , intent(in) , value :: context - character (c_char) , intent(in) , value :: transa, transb - integer (c_int64_t) , intent(in) , value :: m, n - integer (c_int64_t) , intent(in) , value :: lda - real (c_double) , intent(in) :: A(lda,3) - integer (c_int64_t) , intent(in) , value :: ldb - real (c_double) , intent(in) :: B(ldb,3) - integer (c_int64_t) , intent(in) , value :: ldc - real (c_double) , intent(out) :: C(ldc,n) - - integer, external :: qmckl_distance_sq_f - info = qmckl_distance_sq_f(context, transa, transb, m, n, A, LDA, B, LDB, C, LDC) -end function qmckl_distance_sq - #+END_SRC - - #+BEGIN_SRC f90 :comments link :tangle qmckl_distance.fh - interface - integer(c_int32_t) function qmckl_distance_sq(context, transa, transb, m, n, A, LDA, B, LDB, C, LDC) & - bind(C) - use, intrinsic :: iso_c_binding - implicit none - integer (c_int64_t) , intent(in) , value :: context - character (c_char) , intent(in) , value :: transa, transb - integer (c_int64_t) , intent(in) , value :: m, n - integer (c_int64_t) , intent(in) , value :: lda - integer (c_int64_t) , intent(in) , value :: ldb - integer (c_int64_t) , intent(in) , value :: ldc - real (c_double) , intent(in) :: A(lda,3) - real (c_double) , intent(in) :: B(ldb,3) - real (c_double) , intent(out) :: C(ldc,n) - end function qmckl_distance_sq - end interface - #+END_SRC - -*** Test :noexport: - #+BEGIN_SRC f90 :comments link :tangle test_qmckl_distance_f.f90 -integer(c_int32_t) function test_qmckl_distance_sq(context) bind(C) - use, intrinsic :: iso_c_binding - implicit none - include 'qmckl_distance.fh' - integer(c_int64_t), intent(in), value :: context - - double precision, allocatable :: A(:,:), B(:,:), C(:,:) - integer*8 :: m, n, LDA, LDB, LDC - double precision :: x - integer*8 :: i,j - - m = 5 - n = 6 - LDA = m - LDB = n - LDC = 5 - - allocate( A(LDA,m), B(LDB,n), C(LDC,n) ) - - do j=1,m - do i=1,m - A(i,j) = -10.d0 + dble(i+j) - end do - end do - do j=1,n - do i=1,n - B(i,j) = -1.d0 + dble(i*j) - end do - end do - - test_qmckl_distance_sq = qmckl_distance_sq(context, 'X', 't', m, n, A, LDA, B, LDB, C, LDC) - if (test_qmckl_distance_sq == 0) return - - test_qmckl_distance_sq = qmckl_distance_sq(context, 't', 'X', m, n, A, LDA, B, LDB, C, LDC) - if (test_qmckl_distance_sq == 0) return - - test_qmckl_distance_sq = qmckl_distance_sq(context, 'T', 't', m, n, A, LDA, B, LDB, C, LDC) - if (test_qmckl_distance_sq /= 0) return - - test_qmckl_distance_sq = -1 - - do j=1,n - do i=1,m - x = (A(i,1)-B(j,1))**2 + & - (A(i,2)-B(j,2))**2 + & - (A(i,3)-B(j,3))**2 - if ( dabs(1.d0 - C(i,j)/x) > 1.d-14 ) return - end do - end do - - test_qmckl_distance_sq = qmckl_distance_sq(context, 'n', 'T', m, n, A, LDA, B, LDB, C, LDC) - if (test_qmckl_distance_sq /= 0) return - - test_qmckl_distance_sq = -1 - - do j=1,n - do i=1,m - x = (A(1,i)-B(j,1))**2 + & - (A(2,i)-B(j,2))**2 + & - (A(3,i)-B(j,3))**2 - if ( dabs(1.d0 - C(i,j)/x) > 1.d-14 ) return - end do - end do - - test_qmckl_distance_sq = qmckl_distance_sq(context, 'T', 'n', m, n, A, LDA, B, LDB, C, LDC) - if (test_qmckl_distance_sq /= 0) return - - test_qmckl_distance_sq = -1 - - do j=1,n - do i=1,m - x = (A(i,1)-B(1,j))**2 + & - (A(i,2)-B(2,j))**2 + & - (A(i,3)-B(3,j))**2 - if ( dabs(1.d0 - C(i,j)/x) > 1.d-14 ) return - end do - end do - - test_qmckl_distance_sq = qmckl_distance_sq(context, 'n', 'N', m, n, A, LDA, B, LDB, C, LDC) - if (test_qmckl_distance_sq /= 0) return - - test_qmckl_distance_sq = -1 - - do j=1,n - do i=1,m - x = (A(1,i)-B(1,j))**2 + & - (A(2,i)-B(2,j))**2 + & - (A(3,i)-B(3,j))**2 - if ( dabs(1.d0 - C(i,j)/x) > 1.d-14 ) return - end do - end do - - test_qmckl_distance_sq = 0 - - deallocate(A,B,C) -end function test_qmckl_distance_sq - #+END_SRC - - #+BEGIN_SRC C :comments link :tangle test_qmckl_distance.c -int test_qmckl_distance_sq(qmckl_context context); -munit_assert_int(0, ==, test_qmckl_distance_sq(context)); - #+END_SRC -* End of files :noexport: - -*** Header - #+BEGIN_SRC C :comments link :tangle qmckl_distance.h -#endif - #+END_SRC - -*** Test - #+BEGIN_SRC C :comments link :tangle test_qmckl_distance.c - if (qmckl_context_destroy(context) != QMCKL_SUCCESS) - return QMCKL_FAILURE; - return MUNIT_OK; -} - - #+END_SRC diff --git a/src/qmckl_memory.org b/src/qmckl_memory.org deleted file mode 100644 index b6326b2..0000000 --- a/src/qmckl_memory.org +++ /dev/null @@ -1,103 +0,0 @@ -# -*- mode: org -*- -# vim: syntax=c -#+TITLE: Memory management - -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: - - -We override the allocation functions to enable the possibility of -optimized libraries to fine-tune the memory allocation. - -3 files are produced: -- a header file : =qmckl_memory.h= -- a source file : =qmckl_memory.c= -- a test file : =test_qmckl_memory.c= - -** Header :noexport: - #+BEGIN_SRC C :comments link :tangle qmckl_memory.h -#ifndef QMCKL_MEMORY_H -#define QMCKL_MEMORY_H -#include "qmckl.h" - #+END_SRC - -** Source :noexport: - #+BEGIN_SRC C :comments link :tangle qmckl_memory.c -#include -#include "qmckl_memory.h" - #+END_SRC - -** Test :noexport: - #+BEGIN_SRC C :comments link :tangle test_qmckl_memory.c -#include "qmckl.h" -#include "munit.h" -MunitResult test_qmckl_memory() { - #+END_SRC - -* =qmckl_malloc= - Analogous of =malloc, but passing a context and a signed 64-bit integers as argument.= -** Header - #+BEGIN_SRC C :comments link :tangle qmckl_memory.h -void* qmckl_malloc(const qmckl_context ctx, const size_t size); - #+END_SRC - -** Source - #+BEGIN_SRC C :comments link :tangle qmckl_memory.c -void* qmckl_malloc(const qmckl_context ctx, const size_t size) { - if (ctx == (qmckl_context) 0) { - /* Avoids unused parameter error */ - return malloc( (size_t) size ); - } - return malloc( (size_t) size ); -} - - #+END_SRC - -** Test :noexport: - #+BEGIN_SRC C :comments link :tangle test_qmckl_memory.c - int *a; - a = (int*) qmckl_malloc( (qmckl_context) 1, 3*sizeof(int)); - a[0] = 1; - a[1] = 2; - a[2] = 3; - munit_assert_int(a[0], ==, 1); - munit_assert_int(a[1], ==, 2); - munit_assert_int(a[2], ==, 3); - #+END_SRC - -* =qmckl_free= - -** Header - #+BEGIN_SRC C :comments link :tangle qmckl_memory.h -void qmckl_free(void *ptr); - #+END_SRC - -** Source - #+BEGIN_SRC C :comments link :tangle qmckl_memory.c -void qmckl_free(void *ptr) { - free(ptr); -} - #+END_SRC - -** Test :noexport: - #+BEGIN_SRC C :comments link :tangle test_qmckl_memory.c - qmckl_free(a); - #+END_SRC - -* End of files :noexport: - -** Header - #+BEGIN_SRC C :comments link :tangle qmckl_memory.h -#endif - #+END_SRC - -** Test - #+BEGIN_SRC C :comments link :tangle test_qmckl_memory.c - return MUNIT_OK; -} - - #+END_SRC diff --git a/src/test_qmckl.org b/src/test_qmckl.org deleted file mode 100644 index bcd0fce..0000000 --- a/src/test_qmckl.org +++ /dev/null @@ -1,92 +0,0 @@ -#+TITLE: QMCkl test - -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: -#+HTML_HEAD: - -This file is the main program of the unit tests. The tests rely on the -$\mu$unit framework, which is provided as a git submodule. - -First, we use a script to find the list of all the produced test files: -#+NAME: test-files -#+BEGIN_SRC sh :exports none :results value -grep BEGIN_SRC *.org | \ - grep test_qmckl_ | \ - rev | \ - cut -d ' ' -f 1 | \ - rev | \ - sort | \ - uniq -#+END_SRC - -#+RESULTS: test-files -| test_qmckl_ao.c | -| test_qmckl_context.c | -| test_qmckl_distance.c | -| test_qmckl_memory.c | - -We generate the function headers -#+BEGIN_SRC sh :var files=test-files :exports output :results raw -echo "#+NAME: headers" -echo "#+BEGIN_SRC C :tangle no" -for file in $files -do - routine=${file%.c} - echo "MunitResult ${routine}();" -done -echo "#+END_SRC" -#+END_SRC - -#+RESULTS: -#+NAME: headers -#+BEGIN_SRC C :tangle no -MunitResult test_qmckl_ao(); -MunitResult test_qmckl_context(); -MunitResult test_qmckl_distance(); -MunitResult test_qmckl_memory(); -#+END_SRC - -and the required function calls: -#+BEGIN_SRC sh :var files=test-files :exports output :results raw -echo "#+NAME: calls" -echo "#+BEGIN_SRC C :tangle no" -for file in $files -do - routine=${file%.c} - echo " { (char*) \"${routine}\", ${routine}, NULL,NULL,MUNIT_TEST_OPTION_NONE,NULL}," -done -echo "#+END_SRC" -#+END_SRC - -#+RESULTS: -#+NAME: calls -#+BEGIN_SRC C :tangle no - { (char*) "test_qmckl_ao", test_qmckl_ao, NULL,NULL,MUNIT_TEST_OPTION_NONE,NULL}, - { (char*) "test_qmckl_context", test_qmckl_context, NULL,NULL,MUNIT_TEST_OPTION_NONE,NULL}, - { (char*) "test_qmckl_distance", test_qmckl_distance, NULL,NULL,MUNIT_TEST_OPTION_NONE,NULL}, - { (char*) "test_qmckl_memory", test_qmckl_memory, NULL,NULL,MUNIT_TEST_OPTION_NONE,NULL}, -#+END_SRC - -#+BEGIN_SRC C :comments link :noweb yes :tangle test_qmckl.c -#include "qmckl.h" -#include "munit.h" -<> - -int main(int argc, char* argv[MUNIT_ARRAY_PARAM(argc + 1)]) { - static MunitTest test_suite_tests[] = - { -<> - { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } - }; - - static const MunitSuite test_suite = - { - (char*) "", test_suite_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE - }; - - return munit_suite_main(&test_suite, (void*) "µnit", argc, argv); -} -#+END_SRC diff --git a/test_qmckl.html b/test_qmckl.html new file mode 100644 index 0000000..00c30c1 --- /dev/null +++ b/test_qmckl.html @@ -0,0 +1,237 @@ + + + + +QMCkl test + + + + + + + + + + + + + +
+

QMCkl test

+

+This file is the main program of the unit tests. The tests rely on the +$μ$unit framework, which is provided as a git submodule. +

+ +

+First, we use a script to find the list of all the produced test files: +We generate the function headers +

+
+ +
echo "#+NAME: headers"
+echo "#+BEGIN_SRC C :tangle no"
+for file in $files
+do
+  routine=${file%.c}
+  echo "MunitResult ${routine}();"
+done
+echo "#+END_SRC"
+
+
+ +
+ +
MunitResult test_qmckl_ao();
+MunitResult test_qmckl_context();
+MunitResult test_qmckl_distance();
+MunitResult test_qmckl_memory();
+
+
+ +

+and the required function calls: +

+
+ +
echo "#+NAME: calls"
+echo "#+BEGIN_SRC C :tangle no"
+for file in $files
+do
+  routine=${file%.c}
+  echo "  { (char*) \"${routine}\", ${routine}, NULL,NULL,MUNIT_TEST_OPTION_NONE,NULL},"
+done
+echo "#+END_SRC"
+
+
+ +
+ +
{ (char*) "test_qmckl_ao", test_qmckl_ao, NULL,NULL,MUNIT_TEST_OPTION_NONE,NULL},
+{ (char*) "test_qmckl_context", test_qmckl_context, NULL,NULL,MUNIT_TEST_OPTION_NONE,NULL},
+{ (char*) "test_qmckl_distance", test_qmckl_distance, NULL,NULL,MUNIT_TEST_OPTION_NONE,NULL},
+{ (char*) "test_qmckl_memory", test_qmckl_memory, NULL,NULL,MUNIT_TEST_OPTION_NONE,NULL},
+
+
+ +
+ +
#include "qmckl.h"
+#include "munit.h"
+MunitResult test_qmckl_ao();
+MunitResult test_qmckl_context();
+MunitResult test_qmckl_distance();
+MunitResult test_qmckl_memory();
+
+int main(int argc, char* argv[MUNIT_ARRAY_PARAM(argc + 1)]) {
+  static MunitTest test_suite_tests[] =
+    {
+{ (char*) "test_qmckl_ao", test_qmckl_ao, NULL,NULL,MUNIT_TEST_OPTION_NONE,NULL},
+{ (char*) "test_qmckl_context", test_qmckl_context, NULL,NULL,MUNIT_TEST_OPTION_NONE,NULL},
+{ (char*) "test_qmckl_distance", test_qmckl_distance, NULL,NULL,MUNIT_TEST_OPTION_NONE,NULL},
+{ (char*) "test_qmckl_memory", test_qmckl_memory, NULL,NULL,MUNIT_TEST_OPTION_NONE,NULL},
+     { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
+    };
+
+    static const MunitSuite test_suite =
+    {
+     (char*) "", test_suite_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE
+    };
+
+    return munit_suite_main(&test_suite, (void*) "µnit", argc, argv);
+}
+
+
+
+
+

Created: 2020-10-28 Wed 23:57

+

Emacs 25.2.2 (Org mode 8.2.10)

+

Validate

+
+ +