Skip to content

Commit c19bbfd

Browse files
authored
Merge pull request #25 from libefp2/pylibefp3
pylibefp brought into sync with the latest version of libefp. Libefp code corrected to pass ci.yaml tests.
2 parents 79698c8 + 9963623 commit c19bbfd

45 files changed

Lines changed: 901 additions & 695 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ jobs:
2020
cmargs: >
2121
-D BUILD_SHARED_LIBS=ON
2222
-D LIBEFP_ENABLE_OPENMP=ON
23+
# uncomment the following two options to look for possible memory-related bugs in openmp
24+
# however, the tests will take ~10 times longer
25+
#-D CMAKE_C_FLAGS="-fsanitize=thread -g"
26+
#-D CMAKE_EXE_LINKER_FLAGS="-fsanitize=thread"
2327
pytest-marker-expr: "test" # i.e., all
2428

2529
- label: L-Gnu
@@ -30,6 +34,11 @@ jobs:
3034
cmargs: >
3135
-D BUILD_SHARED_LIBS=ON
3236
-D LIBEFP_ENABLE_OPENMP=ON
37+
# uncomment the following two options to look for possible memory-related bugs in openmp
38+
# however, the tests will take ~10 times longer
39+
# this workflow was crashing with these options in pytests due to conflict of TSan and libgomp
40+
#-D CMAKE_C_FLAGS="-fsanitize=thread -g"
41+
#-D CMAKE_EXE_LINKER_FLAGS="-fsanitize=thread"
3342
pytest-marker-expr: "test"
3443

3544
- label: L-Intel
@@ -48,18 +57,20 @@ jobs:
4857

4958
- label: M-Clang
5059
# NaNs in tests on macos-latest (macos-12)
51-
runs-on: macos-13
60+
#runs-on: macos-13
61+
runs-on: macos-latest
5262
python-version: "3.10"
5363
blas: OBL
5464
build_type: Release
5565
cmargs: >
5666
-D BUILD_SHARED_LIBS=ON
5767
-D LIBEFP_ENABLE_OPENMP=ON
58-
pytest-marker-expr: "test"
68+
pytest-marker-expr: "test"
5969
6070
- label: M-Clang
6171
# NaNs in tests on macos-latest (macos-12)
62-
runs-on: macos-13
72+
#runs-on: macos-13
73+
runs-on: macos-15-intel
6374
python-version: "3.10"
6475
blas: ACC
6576
build_type: Release
@@ -124,11 +135,20 @@ jobs:
124135
:
125136
sed -E -i.bak "s;#${{ matrix.cfg.blas }};;g" export.yaml
126137
fi
138+
# if [[ "${{ runner.os }}" == "Windows" ]]; then
139+
# :
140+
# sed -i "s;fortran-compiler;m2w64-gcc-fortran;g" export.yaml
141+
# sed -i "s;#${{ matrix.cfg.blas }};;g" export.yaml
142+
# sed -i "s;openmp;pthreads;g" export.yaml # W openblas is pthreads
143+
# sed -i "s;#- libpython;- libpython;g" export.yaml
144+
# fi
127145
if [[ "${{ runner.os }}" == "Windows" ]]; then
128-
:
129-
sed -i "s;fortran-compiler;m2w64-gcc-fortran;g" export.yaml
146+
# Use the modern conda-forge compilers instead of the old m2w64 ones
147+
sed -i "s;c-compiler;gcc;g" export.yaml
148+
sed -i "s;cxx-compiler;gxx;g" export.yaml
149+
sed -i "s;fortran-compiler;gfortran;g" export.yaml
130150
sed -i "s;#${{ matrix.cfg.blas }};;g" export.yaml
131-
sed -i "s;openmp;pthreads;g" export.yaml # W openblas is pthreads
151+
sed -i "s;openmp;pthreads;g" export.yaml
132152
sed -i "s;#- libpython;- libpython;g" export.yaml
133153
fi
134154
# model sed for L/W
@@ -182,6 +202,17 @@ jobs:
182202
- name: Test (CTest) - unit tests
183203
run: ctest --output-on-failure --test-dir "${{ github.workspace }}/build"
184204

205+
# - name: Test (CTest) with Valgrind
206+
# run: |
207+
# sudo apt-get update && sudo apt-get install -y valgrind
208+
# # Run valgrind directly on the ctest executable. The tests will take forever
209+
# valgrind --tool=memcheck \
210+
# --leak-check=full \
211+
# --track-origins=yes \
212+
# --trace-children=yes \
213+
# --error-exitcode=1 \
214+
# ctest --output-on-failure --test-dir "${{ github.workspace }}/build"
215+
185216
- name: Test (find_package) - consume installation
186217
run: |
187218
mkdir test_installed_library && cd test_installed_library
@@ -242,11 +273,19 @@ jobs:
242273
- name: Install Psi4 for QM/EFP testing
243274
if: ${{ matrix.cfg.blas == 'MKL' }}
244275
run: conda install psi4 -c conda-forge
245-
276+
246277
- name: Test (pytest) -- unit tests Python bindings
247278
run: |
248-
PYTHONPATH="${{ github.workspace }}/installed/lib" \
249-
pytest --cache-clear -v -rws --color=yes \
250-
--durations=50 --durations-min=1 --strict-markers \
251-
-k "${{ matrix.cfg.pytest-marker-expr }}" \
252-
"${{ github.workspace }}/installed/"
279+
# Setup PYTHONPATH
280+
SEP=$(python -c "import os; print(os.pathsep)")
281+
LIB_PATH="${{ github.workspace }}/installed/lib"
282+
TEST_PATH="${{ github.workspace }}/installed/lib/pylibefp/tests"
283+
export PYTHONPATH="${LIB_PATH}${SEP}${TEST_PATH}"
284+
echo "PYTHONPATH is set to: $PYTHONPATH"
285+
# PYTHONPATH="${{ github.workspace }}/installed/lib:${{ github.workspace }}/installed/lib/pylibefp/tests" \
286+
287+
# Run Pytest
288+
pytest -s --cache-clear -v -rws --color=yes \
289+
--durations=50 --durations-min=1 --strict-markers \
290+
-k "${{ matrix.cfg.pytest-marker-expr }}" \
291+
"${{ github.workspace }}/installed/"

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ if((${BUILD_SHARED_LIBS}) AND NOT ${BUILD_FPIC})
8181
endif()
8282

8383
### This option turns OPENMP ON and OFF!
84-
option_with_print(LIBEFP_ENABLE_OPENMP "Enable OpenMP parallelization. Psi4 wants OFF" OFF)
84+
option_with_print(LIBEFP_ENABLE_OPENMP "Enable OpenMP parallelization. Psi4 wants OFF" ON)
8585

8686
option_with_print(ENABLE_GENERIC "Enable mostly static linking in shared library" OFF)
8787
include(xhost) # defines: option(ENABLE_XHOST "Enable processor-specific optimization" ON)

efpmd/src/common.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -146,20 +146,24 @@ void print_geometry_pbc(struct efp *efp, int ligand)
146146
size_t n_frags;
147147
check_fail(efp_get_frag_count(efp, &n_frags));
148148

149+
if (ligand < 0)
150+
msg(" WARNING! Specify ligand tor printing PBC geometry\n\n");
151+
size_t lig = (size_t)ligand;
152+
149153
msg(" GEOMETRY IN PBC CELL (ANGSTROMS)\n\n");
150154

151-
double bx[6];
155+
double bx[6] = {0.0};
152156

153157
check_fail(efp_get_periodic_box(efp, bx));
154158
six_t box = {bx[0],bx[1],bx[2],bx[3],bx[4],bx[5]};
155159
//six_t box = {10.66, 12.03, 10.872, 90.0, 115.83, 90.0};
156160

157161
double lig_com[6];
158-
check_fail(efp_get_frag_xyzabc(efp,ligand,lig_com));
162+
check_fail(efp_get_frag_xyzabc(efp,lig,lig_com));
159163
for (size_t i = 0; i < n_frags; i++) {
160164

161165
vec_t cell = {0.0,0.0,0.0};
162-
if (i != ligand) {
166+
if (i != lig) {
163167
double frag_com[6];
164168
check_fail(efp_get_frag_xyzabc(efp, i, frag_com));
165169
vec_t dr = {frag_com[0] - lig_com[0], frag_com[1] - lig_com[1], frag_com[2] - lig_com[2]};
@@ -199,7 +203,7 @@ void print_geometry_pbc(struct efp *efp, int ligand)
199203
void print_energy(struct state *state)
200204
{
201205
// printf("Inside print_energy\n");
202-
struct efp_energy energy;
206+
struct efp_energy energy = {0.0};
203207

204208
check_fail(efp_get_energy(state->efp, &energy));
205209

@@ -346,25 +350,25 @@ void print_pair_energy(struct state *state) {
346350
check_fail(efp_get_coordinates(state->efp, coord));
347351

348352
struct efp_energy *energies;
349-
energies = xmalloc(n_frags * sizeof(struct efp_energy));
353+
energies = xcalloc(n_frags, sizeof(struct efp_energy));
350354
check_fail(efp_get_pairwise_energy(state->efp, energies));
351355

352356
char ligand[32];
353357
size_t lig_atoms;
354358

355-
size_t ligand_index = cfg_get_int(state->cfg, "ligand");
359+
size_t ligand_index = (size_t)cfg_get_int(state->cfg, "ligand");
360+
if (ligand_index >= n_frags)
361+
error("Ligand index is out of bound");
356362
check_fail(efp_get_frag_name(state->efp, ligand_index, sizeof(ligand),ligand));
357363
check_fail(efp_get_frag_atom_count(state->efp, ligand_index, &lig_atoms));
358364
struct efp_atom latoms[lig_atoms];
359365
check_fail(efp_get_frag_atoms(state->efp, ligand_index, lig_atoms, latoms));
360366

361367
char frag_name[32];
362368
size_t frag_atoms;
363-
double lattice_energy[6];
364-
for (size_t j=0; j<6; j++){
365-
lattice_energy[j]=0.0;
366-
}
367-
for (size_t i=0; i <n_frags; i++){
369+
double lattice_energy[6] = {0.0};
370+
371+
for (size_t i=0; i <n_frags; i++){
368372
check_fail(efp_get_frag_name(state->efp, i, sizeof(frag_name),frag_name));
369373
check_fail(efp_get_frag_atom_count(state->efp, i, &frag_atoms));
370374

efpmd/src/efield.c

Lines changed: 10 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,12 @@ sim_efield(struct state *state)
6363
msg("ELECTRIC FIELD IS IN ATOMIC UNITS\n\n");
6464

6565
for (size_t i = 0; i < n_frags; i++) {
66-
double field[3];
66+
double field[3] = {0.0};
6767
struct efp_atom *atoms;
6868
size_t n_atoms;
6969

7070
check_fail(efp_get_frag_atom_count(state->efp, i, &n_atoms));
71-
atoms = xmalloc(n_atoms * sizeof(struct efp_atom));
71+
atoms = xcalloc(n_atoms, sizeof(struct efp_atom));
7272
check_fail(efp_get_frag_atoms(state->efp, i, n_atoms, atoms));
7373

7474
for (size_t j = 0; j < n_atoms; j++) {
@@ -116,7 +116,7 @@ sim_elpot(struct state *state)
116116
size_t n_atoms;
117117

118118
check_fail(efp_get_frag_atom_count(state->efp, i, &n_atoms));
119-
atoms = xmalloc(n_atoms * sizeof(struct efp_atom));
119+
atoms = xcalloc(n_atoms, sizeof(struct efp_atom));
120120
check_fail(efp_get_frag_atoms(state->efp, i, n_atoms, atoms));
121121

122122
msg("ELECTROSTATIC POTENTIAL ON FRAGMENT %zu\n", i);
@@ -133,52 +133,27 @@ sim_elpot(struct state *state)
133133
msg("ELECTROSTATIC POTENTIAL JOB COMPLETED SUCCESSFULLY\n");
134134
}
135135

136-
/*
137-
void get_frag_elpot(struct state *state) {
138-
size_t spec_frag;
139-
spec_frag = cfg_get_int(state->cfg, "special_fragment");
140-
141-
double elpot;
142-
struct efp_atom *atoms;
143-
size_t n_atoms;
144-
145-
146-
check_fail(efp_get_frag_atom_count(state->efp, spec_frag, &n_atoms)); // SKP
147-
atoms = xmalloc(n_atoms * sizeof(struct efp_atom));
148-
check_fail(efp_get_frag_atoms(state->efp, spec_frag, n_atoms, atoms));
149-
//state->spec_elpot = malloc(n_atoms * sizeof(double));
150-
state->spec_elpot = xcalloc(n_atoms, sizeof(double));
151-
152-
153-
for (size_t j = 0; j < n_atoms; j++) {
154-
check_fail(efp_get_elec_potential(state->efp, spec_frag, &atoms[j].x, &elpot));
155-
state->spec_elpot[j] = elpot;
156-
print_elpot(atoms + j, elpot);
157-
}
158-
159-
free(atoms);
160-
}
161-
*/
162-
163136
void sim_frag_elpot(struct state *state) {
164137

165-
// size_t chosen_frag = cfg_get_int(state->cfg, "frag_num");
138+
if (cfg_get_int(state->cfg, "special_fragment") < 0)
139+
error("Special fragment is not defined in fragment elec potential calculation");
140+
166141
size_t spec_frag;
167-
spec_frag = cfg_get_int(state->cfg, "special_fragment");
142+
spec_frag = (size_t)cfg_get_int(state->cfg, "special_fragment");
168143

169144
msg("\n=============FRAG-ELECTROSTATIC POTENTIAL JOB======================\n\n");
170145

171146

172147
msg("\nCOORDINATES IN ANGSTROMS, ELECTROSTATIC POTENTIAL IN ATOMIC UNITS\n");
173148
msg(" ATOM X Y Z ELPOT \n\n");
174149

175-
double elpot;
150+
double elpot = 0.0;
176151
struct efp_atom *atoms;
177152
size_t n_atoms;
178153

179154

180-
check_fail(efp_get_frag_atom_count(state->efp, spec_frag, &n_atoms)); // SKP
181-
atoms = xmalloc(n_atoms * sizeof(struct efp_atom));
155+
check_fail(efp_get_frag_atom_count(state->efp, spec_frag, &n_atoms));
156+
atoms = xcalloc(n_atoms, sizeof(struct efp_atom));
182157
check_fail(efp_get_frag_atoms(state->efp, spec_frag, n_atoms, atoms));
183158

184159
msg("ELECTROSTATIC POTENTIAL ON FRAGMENT %zu\n", spec_frag);

efpmd/src/energy.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@
3737
void compute_energy(struct state *state, bool do_grad)
3838
{
3939
struct efp_atom *atoms;
40-
struct efp_energy efp_energy;
41-
double xyz[3], xyzabc[6], *grad;
40+
struct efp_energy efp_energy = {0.0};
41+
double xyz[3] = {0.0}, xyzabc[6] = {0.0}, *grad;
4242
size_t ifrag, nfrag, iatom, natom, spec_frag, n_special_atoms;
4343
int itotal;
4444

@@ -94,13 +94,16 @@ void compute_energy(struct state *state, bool do_grad)
9494

9595
if (cfg_get_bool(state->cfg, "enable_torch") && cfg_get_int(state->cfg, "opt_special_frag") > -1) {
9696

97-
spec_frag = cfg_get_int(state->cfg, "special_fragment");
98-
check_fail(efp_get_frag_atom_count(state->efp, spec_frag, &n_special_atoms)); // SKP
97+
spec_frag = (size_t)cfg_get_int(state->cfg, "special_fragment");
98+
check_fail(efp_get_frag_atom_count(state->efp, spec_frag, &n_special_atoms));
99+
100+
if (n_special_atoms < 1)
101+
error("ML special fragment does not have any atoms!");
99102

100103
if (cfg_get_bool(state->cfg, "enable_elpot")) {
101104
double *elpot;
102105
struct efp_atom *atoms;
103-
atoms = xmalloc(n_special_atoms * sizeof(struct efp_atom));
106+
atoms = xcalloc(n_special_atoms, sizeof(struct efp_atom));
104107
check_fail(efp_get_frag_atoms(state->efp, spec_frag, n_special_atoms, atoms));
105108
elpot = xcalloc(n_special_atoms, sizeof(double));
106109
for (size_t j = 0; j < n_special_atoms; j++) {
@@ -189,7 +192,7 @@ void compute_energy(struct state *state, bool do_grad)
189192

190193
for (ifrag = 0, itotal = 0; ifrag < nfrag; ifrag++) {
191194
check_fail(efp_get_frag_atom_count(state->efp, ifrag, &natom));
192-
atoms = xmalloc(natom * sizeof(struct efp_atom));
195+
atoms = xcalloc(natom, sizeof(struct efp_atom));
193196
check_fail(efp_get_frag_atoms(state->efp, ifrag, natom, atoms));
194197

195198
for (iatom = 0; iatom < natom; iatom++, itotal++)
@@ -204,7 +207,7 @@ void compute_energy(struct state *state, bool do_grad)
204207
for (ifrag = 0, itotal = 0, grad = state->grad; ifrag < nfrag; ifrag++, grad += 6) {
205208
check_fail(efp_get_frag_xyzabc(state->efp, ifrag, xyzabc));
206209
check_fail(efp_get_frag_atom_count(state->efp, ifrag, &natom));
207-
atoms = xmalloc(natom * sizeof(struct efp_atom));
210+
atoms = xcalloc(natom, sizeof(struct efp_atom));
208211
check_fail(efp_get_frag_atoms(state->efp, ifrag, natom, atoms));
209212

210213
for (iatom = 0; iatom < natom; iatom++, itotal++) {

0 commit comments

Comments
 (0)