Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions config/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
os = host_machine.system()
fc = meson.get_compiler('fortran')
cc = fc
# cc = meson.get_compiler('c')
fc_id = fc.get_id()

if fc_id == 'gcc'
add_project_arguments(
'-ffree-line-length-none',
'-fbacktrace',
language: 'fortran',
)
elif fc_id == 'intel'
add_project_arguments(
'-traceback',
language: 'fortran',
)
endif
87 changes: 68 additions & 19 deletions docs/download_and_install.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,60 @@ setup.py test
```

<br />
## Source code

**Download the ddX source code** at:
## Source Code

**Download the ddX source code** from GitHub:

```
git@github.com:ddsolvation/ddX.git
git clone git@github.com:ddsolvation/ddX.git
```
**Download and install** ddX as follows:

Then change into the cloned directory:

```
> git clone git@github.com:ddsolvation/ddX.git
> cd ddX
> mkdir build
> cd build
> cmake ..
> make
cd ddX
```
Per default, the library is located in /src.

The main Fortran sources for ddX reside in the `src/` folder. You can build ddX using either **CMake** or **Meson**, as outlined below.

---

## Building with CMake

1. Create a build directory and enter it:
```bash
mkdir build
cd build
```
2. Run CMake to configure:
```bash
cmake ..
```
3. Compile the library and executables:
```bash
make
```
4. (Optional) Run the test suite:
```bash
make test
```

By default, the compiled library and executables will appear in the `build` folder. The original sources remain in `src/`.

**Build the documentation** as follows (after you have done the above process):
```
> cd build
> make docs
```bash
cd build
make docs
```
**To see the documentation**
```
> cd ../doxygen
> pwd
```bash
cd ../doxygen
pwd
```
Copy the link shown by pwd and add /index.html in a web browser
#### Hints and hacks
1. For specifying compilers use

**Specifying compilers** can be done by passing the desired compilers to CMake:
```
cmake -D CMAKE_CXX_COMPILER=/usr/local/bin/g++-11 CMAKE_Fortran_COMPILER=/usr/local/bin/gfortran-11 ..
```
Expand All @@ -53,3 +77,28 @@ or
cmake -D CMAKE_CXX_COMPILER=icx CMAKE_Fortran_COMPILER=ifort ..
```
**NOTE**: Replace with the compilers you desire.


---

## Building with Meson

[meson](https://mesonbuild.com) version 0.61 or newer, with
a build-system backend, *i.e.* [ninja](https://ninja-build.org) version 1.10 or newer, are required.

1. Set up a build directory:
```bash
meson setup build
```
2. Compile:
```bash
meson compile -C build
```
3. Run the test suite (and print any error logs):
```bash
meson test -C build
```

Again, the built library and any executables will appear in the `build` folder, while the ddX source remains in `src/`.


130 changes: 130 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
project('ddX',
'fortran',
'cpp',
version: '0.6.0',
license: 'LGPL-3.0-or-later',
meson_version: '>=0.57.2',
default_options: [
'default_library=both',
],
)

install = not (meson.is_subproject() and get_option('default_library') == 'static')
fc = meson.get_compiler('fortran')
fc_id = fc.get_id()
fortran_compiler = fc

lib_deps = []
if get_option('openmp')
omp_dep = dependency('openmp')
lib_deps += omp_dep
endif

lapack_vendor = get_option('lapack')
if lapack_vendor == 'auto'
if fc_id == 'intel'
lapack_vendor = 'mkl'
endif
endif

if lapack_vendor == 'mkl'
mkl_dep = []
if fc_id == 'intel'
mkl_dep += fc.find_library('mkl_intel_lp64')
if get_option('openmp')
mkl_dep += fc.find_library('mkl_intel_thread')
endif
elif fc_id == 'gcc'
mkl_dep += fc.find_library('mkl_gf_lp64')
if get_option('openmp')
mkl_dep += fc.find_library('mkl_gnu_thread')
endif
else
error('MKL not supported for this compiler')
endif
if not get_option('openmp')
mkl_dep += fc.find_library('mkl_tbb_thread')
endif
mkl_dep += fc.find_library('mkl_core')
lib_deps += mkl_dep
add_project_arguments(['-DWITH_MKL'], language: 'fortran')
elif lapack_vendor == 'mkl-rt'
mkl_dep = fc.find_library('mkl_rt')
lib_deps += mkl_dep
add_project_arguments(['-DWITH_MKL'], language: 'fortran')
elif lapack_vendor == 'openblas'
openblas_dep = dependency('openblas', required: false)
if not openblas_dep.found()
openblas_dep = fc.find_library('openblas')
endif
lib_deps += openblas_dep
if not fc.links('external dsytrs; call dsytrs(); end', dependencies: openblas_dep)
lapack_dep = dependency('lapack', required: false)
if not lapack_dep.found()
lapack_dep = fc.find_library('lapack')
endif
lib_deps += lapack_dep
endif

elif lapack_vendor == 'custom'
foreach lib: get_option('custom_libraries')
lib_deps += fc.find_library(lib)
endforeach

else
lapack_dep = dependency('lapack', required: false)
if not lapack_dep.found()
lapack_dep = fc.find_library('lapack')
endif
lib_deps += lapack_dep
blas_dep = dependency('blas', required: false)
if not blas_dep.found()
blas_dep = fc.find_library('blas')
endif
lib_deps += blas_dep
endif

subdir('config')

ddx_library = library(
'ddX',
sources: [
'src/ddx.f90',
'src/cbessel.f90',
'src/ddx_driver.f90',
'src/ddx_lpb_core.f90',
'src/ddx_workspace.f90',
'src/ddx_errors.f90',
'src/ddx_lpb.f90',
'src/llgnew.f',
'src/ddx_cinterface.f90',
'src/ddx_multipolar_solutes.f90',
'src/ddx_constants.f90',
'src/ddx_gradients.f90',
'src/ddx_operators.f90',
'src/ddx_core.f90',
'src/ddx_parameters.f90',
'src/ddx_cosmo.f90',
'src/ddx_harmonics.f90',
'src/ddx_pcm.f90',
'src/ddx_definitions.f90',
'src/ddx_legacy.f90',
'src/ddx_solvers.f90'
],
dependencies: lib_deps
)

ddx_dep = declare_dependency(
link_with: ddx_library,
dependencies: lib_deps
)

executable_target = executable(
'ddX_exec',
sources: ['src/ddx_driver.f90'],
link_with: [ddx_library],
dependencies: lib_deps
)

subdir('tests')
subdir('tests/standalone_tests')
24 changes: 24 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
option(
'lapack',
type: 'combo',
value: 'auto',
yield: true,
choices: ['auto', 'mkl', 'mkl-rt', 'openblas', 'netlib', 'custom'],
description : 'linear algebra backend',
)

option(
'custom_libraries',
type: 'array',
value: [],
yield: true,
description: 'libraries to load for custom linear algebra backend',
)

option(
'openmp',
type: 'boolean',
value: true,
yield: true,
description: 'use OpenMP parallelisation',
)
57 changes: 57 additions & 0 deletions tests/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
project_dir = meson.current_source_dir()

# Test sources with their arguments
test_sources = [
['ddx_core.f90', []],
['ddx_operators.f90', []],
['bessel.f90', []],
['force.f90', [join_paths(project_dir, 'Input_force.txt')]],
['ddx_driver.f90', [
join_paths(project_dir, 'data/ddpcm_force_fmm.in') + ' ' + join_paths(project_dir, 'data/ddpcm_force_fmm.out') + ' 1E-12',
join_paths(project_dir, 'data/ddcosmo_force_fmm.in') + ' ' + join_paths(project_dir, 'data/ddcosmo_force_fmm.out') + ' 1E-12'
]],
['force_ddlpb.f90', [join_paths(project_dir, 'data/ddlpb_force.txt')]],
['ddlpb_esolv.f90', [join_paths(project_dir, 'data/ddlpb_force.txt')]],
['matrix_derivatives.f90', [join_paths(project_dir, 'data/ddlpb_force.txt')]],
['matrix_adjoint.f90', [join_paths(project_dir, 'data/ddlpb_force.txt')]],
['matrix_solvers.f90', [join_paths(project_dir, 'data/ddlpb_force.txt')]],
['m2l.f90', []],
['multipolar_solutes.f90', []],
['error.f90', []]
]

# Create test executables and add tests
foreach source_entry : test_sources
src = source_entry[0]
args = source_entry[1]
executable_name = src.split('.')[0]

test_executable = executable(
executable_name,
src,
dependencies: [lib_deps, ddx_dep], # Link to ddx_dep
install: false
)

# If the executable is ddx_driver, store it for the extra test
if executable_name == 'ddx_driver'
ddx_driver_exe = test_executable
endif

if args.length() == 0
test(executable_name, test_executable)
else
idx = 0
foreach arg_set : args
test(
executable_name + '_' + idx.to_string(),
test_executable,
args: arg_set.split(),
timeout: 240
)
message('test ' + idx.to_string() + ' ' + executable_name + ' ' + arg_set)
idx += 1
endforeach
endif
endforeach

50 changes: 50 additions & 0 deletions tests/standalone_tests/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Copy run_test.py to the build directory
# (If run_test.py already has +x permission, this copy should preserve it on most OS.)
configure_file(
input: 'run_test.py',
output: 'run_test.py',
copy: true
)

# Define a list of test basenames.
standalone_tests = [
'cosmo',
'cosmo_fmm',
'cosmo_incore',
'pcm',
'pcm_fmm',
'pcm_incore',
'lpb',
'lpb_fmm',
'lpb_incore'
]

foreach t : standalone_tests
# Copy each test’s .txt and .ref files into the build dir.
configure_file(
input: t + '.txt',
output: t + '.txt',
copy: true
)
configure_file(
input: t + '.ref',
output: t + '.ref',
copy: true
)

# Generate a small shell wrapper from meson_test_wrapper.in
# We replace the placeholders with the actual test name and build directory.
meson_test_wrapper = configure_file(
input: 'meson_test_wrapper.in',
output: t + '_wrapper.sh',
configuration: {
'BUILD_DIR': meson.project_build_root(),
'TESTNAME': t
},
copy: false
)

# Finally, register the wrapper script as a test with Meson.
# This call has exactly two arguments: the test name, and the wrapper "File".
test(t, meson_test_wrapper)
endforeach
Loading
Loading