Allow use of external lmfit package
authorMark Abraham <mark.j.abraham@gmail.com>
Tue, 7 Jun 2016 17:07:56 +0000 (19:07 +0200)
committerMark Abraham <mark.j.abraham@gmail.com>
Thu, 23 Jun 2016 19:22:12 +0000 (21:22 +0200)
For packaging GROMACS for software distributions, we need to permit
maintainers to use external system libraries, rather than the versions
we bundle for convenience for general GROMACS users.

This patch implements the CMake option GMX_EXTERNAL_LMFIT. It
implements FindLmfit.cmake, which relies heavily on pkg-config, which
is supported by lmfit and widely available in the intended use case
(ie distribution maintainers), but can be worked around if lmfit is
available and pkg-config is not and somehow an external lmfit is
needed.

lmfit management now needs to happen at a higher point in the GROMACS
build system, so I have refactored the source code files that use
lmfit functionality. The former gmx_lmcurve.cpp in src/external was in
fact GROMACS code that calls the lmmin routine from lmfit and declares
a suitable callback, so it should never have been in
src/external. Moved it (and its header) to
src/gromacs/correlationfunctions.

Reverted the introduction of gmx_ prefixes in an earlier commit - that
approach permits a third party to link to their own lmfit without
symbol clashes, but doesn't resolve the distribution problem. If both
clients of lmfit can use the same external version, then the problem
is solved, and if each need a different version then there are various
further options. Updated the README accordingly, and noted various
other differences from stock lmfit 6.1.

Added file-level Doxygen for some files. Added mention to install
guide.

The implementation is quiet upon repeat cmake runs, and makes only
advanced or internal cache variables.

Fixes #1957

Change-Id: Ib05eee796c6cf13ea90d456cb9b54b166bfda717

17 files changed:
CMakeLists.txt
cmake/FindLmfit.cmake [new file with mode: 0644]
cmake/gmxManageLmfit.cmake [new file with mode: 0644]
docs/CMakeLists.txt
docs/conf-vars.py.cmakein
docs/install-guide/index.rst
src/external/lmfit/README
src/external/lmfit/gmx_lmcurve.cpp [deleted file]
src/external/lmfit/gmx_lmcurve.h [deleted file]
src/external/lmfit/lmmin.cpp [moved from src/external/lmfit/gmx_lmmin.cpp with 98% similarity]
src/external/lmfit/lmmin.h [moved from src/external/lmfit/gmx_lmmin.h with 83% similarity]
src/external/lmfit/lmstruct.h [moved from src/external/lmfit/gmx_lmstruct.h with 92% similarity]
src/gromacs/CMakeLists.txt
src/gromacs/correlationfunctions/CMakeLists.txt
src/gromacs/correlationfunctions/expfit.cpp
src/gromacs/correlationfunctions/gmx_lmcurve.cpp [new file with mode: 0644]
src/gromacs/correlationfunctions/gmx_lmcurve.h [new file with mode: 0644]

index 849383540cdf3b2dae1cfef3f61b48a3f0b173a0..739fb14da8f9eb0cecea71adbcaa163eb551664c 100644 (file)
@@ -568,6 +568,8 @@ endif()
 # Note this relies on zlib detection having already run
 include(gmxManageTNG)
 
+include(gmxManageLmfit)
+
 if(GMX_GPU)
     # now that we have detected the dependencies, do the second configure pass
     gmx_gpu_setup()
diff --git a/cmake/FindLmfit.cmake b/cmake/FindLmfit.cmake
new file mode 100644 (file)
index 0000000..5bf489a
--- /dev/null
@@ -0,0 +1,100 @@
+#
+# This file is part of the GROMACS molecular simulation package.
+#
+# Copyright (c) 2016, by the GROMACS development team, led by
+# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+# and including many others, as listed in the AUTHORS file in the
+# top-level source directory and at http://www.gromacs.org.
+#
+# GROMACS is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1
+# of the License, or (at your option) any later version.
+#
+# GROMACS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with GROMACS; if not, see
+# http://www.gnu.org/licenses, or write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+#
+# If you want to redistribute modifications to GROMACS, please
+# consider that scientific software is very special. Version
+# control is crucial - bugs must be traceable. We will be happy to
+# consider code for inclusion in the official distribution, but
+# derived work must not be called official GROMACS. Details are found
+# in the README & COPYING files - if they are missing, get the
+# official version at http://www.gromacs.org.
+#
+# To help us fund GROMACS development, we humbly ask that you cite
+# the research papers on the package. Check out http://www.gromacs.org.
+
+# This package tries to find an external lmfit library. It is intended
+# to work with pkg-config, because that is the mechanism supported in
+# lmfit. Upon exit, the following variables may be set:
+#
+# LMFIT_FOUND       - lmfit was found
+# LMFIT_INCLUDE_DIR - lmfit include directory
+# LMFIT_LIBRARIES   - lmfit libraries
+# LMFIT_LINKS_OK    - lmfit libraries link correctly
+# LMFIT_VERSION     - lmfit version string as "major.minor"
+#
+# If you cannot use pkg-config for some reason, then setting
+# LMFIT_INCLUDE_DIRS and LMFIT_LIBRARY_DIRS on the cmake command line
+# to suitable values will work.
+
+include(CMakePushCheckState)
+cmake_push_check_state()
+
+find_package(PkgConfig QUIET)
+if(PKG_CONFIG_FOUND)
+    if(LMFIT_FIND_VERSION)
+        # lmfit doesn't support CMake-based find_package version
+        # checking in 6.1, so this code does nothing.
+        if(LMFIT_FIND_VERSION_EXACT)
+            pkg_check_modules(PC_LMFIT lmfit=${LMFIT_FIND_VERSION})
+        else()
+            pkg_check_modules(PC_LMFIT lmfit>=${LMFIT_FIND_VERSION})
+        endif()
+    else()
+        pkg_check_modules(PC_LMFIT lmfit)
+        if (PC_LMFIT_VERSION)
+            string(REGEX REPLACE "^([0-9]+):([0-9]+)" "\\1.\\2" LMFIT_VERSION "${PC_LMFIT_VERSION}")
+        endif()
+    endif()
+endif()
+
+# Try to find lmfit, perhaps with help from pkg-config
+find_path(LMFIT_INCLUDE_DIRS lmcurve.h HINTS "${PC_LMFIT_INCLUDE_DIRS}" PATH_SUFFIXES include)
+find_library(LMFIT_LIBRARY_DIRS NAMES lmfit HINTS "${PC_LMFIT_LIBRARY_DIRS}" PATH_SUFFIXES lib64 lib)
+
+# Make sure we can also link, so that cross-compilation is properly supported
+if (LMFIT_INCLUDE_DIRS AND LMFIT_LIBRARY_DIRS)
+    include(CheckCXXSourceCompiles)
+    set(CMAKE_REQUIRED_INCLUDES ${LMFIT_INCLUDE_DIRS})
+    set(CMAKE_REQUIRED_LIBRARIES ${LMFIT_LIBRARY_DIRS})
+    check_cxx_source_compiles("#include <lmcurve.h>\nint main(){lmcurve(0,0,0,0,0,0,0,0);}" LMFIT_LINKS_OK)
+endif()
+
+if (LMFIT_LINKS_OK)
+    set(LMFIT_INCLUDE_DIR ${LMFIT_INCLUDE_DIRS})
+    set(LMFIT_LIBRARIES ${LMFIT_LIBRARY_DIRS})
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(lmfit
+    FOUND_VAR
+    LMFIT_FOUND
+    REQUIRED_VARS
+    LMFIT_INCLUDE_DIR
+    LMFIT_LIBRARIES
+    LMFIT_LINKS_OK
+    VERSION_VAR
+    LMFIT_VERSION)
+
+mark_as_advanced(LMFIT_INCLUDE_DIRS LMFIT_LIBRARY_DIRS)
+
+cmake_pop_check_state()
diff --git a/cmake/gmxManageLmfit.cmake b/cmake/gmxManageLmfit.cmake
new file mode 100644 (file)
index 0000000..182928f
--- /dev/null
@@ -0,0 +1,66 @@
+#
+# This file is part of the GROMACS molecular simulation package.
+#
+# Copyright (c) 2016, by the GROMACS development team, led by
+# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+# and including many others, as listed in the AUTHORS file in the
+# top-level source directory and at http://www.gromacs.org.
+#
+# GROMACS is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1
+# of the License, or (at your option) any later version.
+#
+# GROMACS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with GROMACS; if not, see
+# http://www.gnu.org/licenses, or write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+#
+# If you want to redistribute modifications to GROMACS, please
+# consider that scientific software is very special. Version
+# control is crucial - bugs must be traceable. We will be happy to
+# consider code for inclusion in the official distribution, but
+# derived work must not be called official GROMACS. Details are found
+# in the README & COPYING files - if they are missing, get the
+# official version at http://www.gromacs.org.
+#
+# To help us fund GROMACS development, we humbly ask that you cite
+# the research papers on the package. Check out http://www.gromacs.org.
+
+set(GMX_LMFIT_MINIMUM_REQUIRED_VERSION "6.1")
+set(GMX_BUNDLED_LMFIT_DIR "${CMAKE_SOURCE_DIR}/src/external/lmfit")
+
+option(GMX_EXTERNAL_LMFIT "Use external lmfit instead of compiling the version bundled with GROMACS." OFF)
+mark_as_advanced(GMX_EXTERNAL_LMFIT)
+
+macro(manage_lmfit)
+    if(GMX_EXTERNAL_LMFIT)
+        # Find an external lmfit library.
+        find_package(Lmfit ${GMX_LMFIT_MINIMUM_REQUIRED_VERSION})
+        if(NOT LMFIT_FOUND)
+            message(FATAL_ERROR "External lmfit could not be found, please adjust your pkg-config path to include the lmfit.pc file")
+        endif()
+    endif()
+endmacro()
+
+macro(get_lmfit_properties LMFIT_SOURCES_VAR LMFIT_LIBRARIES_VAR LMFIT_INCLUDE_DIR_VAR LMFIT_INCLUDE_DIR_ORDER_VAR)
+    if (GMX_EXTERNAL_LMFIT)
+        set(${LMFIT_INCLUDE_DIR_VAR} ${LMFIT_INCLUDE_DIR})
+        set(${LMFIT_INCLUDE_DIR_ORDER_VAR} "AFTER")
+        set(${LMFIT_SOURCES_VAR} "")
+        set(${LMFIT_LIBRARIES_VAR} ${LMFIT_LIBRARIES})
+    else()
+        set(${LMFIT_INCLUDE_DIR_VAR} ${GMX_BUNDLED_LMFIT_DIR})
+        set(${LMFIT_INCLUDE_DIR_ORDER_VAR} "BEFORE")
+        file(GLOB ${LMFIT_SOURCES_VAR} ${GMX_BUNDLED_LMFIT_DIR}/*.cpp)
+        set(${LMFIT_LIBRARIES_VAR} "")
+    endif()
+endmacro()
+
+manage_lmfit()
+
index 2f96538bb6dd1ecb1c36e9451bdfd15ccfd0fe27..0e9b7f47de432d4a88c822ec4910326b5e4706f4 100644 (file)
@@ -146,6 +146,7 @@ if (SPHINX_FOUND)
             REQUIRED_CUDA_COMPUTE_CAPABILITY REGRESSIONTEST_VERSION
             SOURCE_MD5SUM REGRESSIONTEST_MD5SUM_STRING
             GMX_TNG_MINIMUM_REQUIRED_VERSION
+            GMX_LMFIT_MINIMUM_REQUIRED_VERSION
         COMMENT "Configuring Sphinx configuration file")
     gmx_add_sphinx_input_file(${SPHINX_CONFIG_VARS_FILE})
     gmx_add_sphinx_source_files(FILES ${SPHINX_SOURCE_FILES})
index 4c3fd67d4531e292ab971ba1e34872ac5fc975da..a8bbe35e3c153b5f3ceb2bd6655ba3bc489b01b1 100644 (file)
@@ -45,5 +45,6 @@ variables = [
         ('REQUIRED_OPENCL_MIN_VERSION', '@REQUIRED_OPENCL_MIN_VERSION@'),
         ('SOURCE_MD5SUM', '@SOURCE_MD5SUM@'),
         ('REGRESSIONTEST_MD5SUM', '@REGRESSIONTEST_MD5SUM_STRING@'),
-        ('GMX_TNG_MINIMUM_REQUIRED_VERSION', '@GMX_TNG_MINIMUM_REQUIRED_VERSION@')
+        ('GMX_TNG_MINIMUM_REQUIRED_VERSION', '@GMX_TNG_MINIMUM_REQUIRED_VERSION@'),
+        ('GMX_LMFIT_MINIMUM_REQUIRED_VERSION', '@GMX_LMFIT_MINIMUM_REQUIRED_VERSION@')
     ]
index 598bb336a1424e0f684458e728895a84317f4402..b95f572d301cd662f953608db99a4c39a46f9dfa 100644 (file)
@@ -301,6 +301,10 @@ Other optional build components
   by setting ``-DGMX_EXTERNAL_TNG=yes``, but TNG
   |GMX_TNG_MINIMUM_REQUIRED_VERSION| is bundled in the |Gromacs|
   source already.
+* An external lmfit library for Levenberg-Marquardt curve fitting
+  can be used by setting ``-DGMX_EXTERNAL_LMFIT=yes``, but lmfit
+  |GMX_LMFIT_MINIMUM_REQUIRED_VERSION| is bundled in the |Gromacs|
+  source already.
 * zlib is used by TNG for compressing some kinds of trajectory data
 * Building the |Gromacs| documentation is optional, and requires
   ImageMagick, pdflatex, bibtex, doxygen, python 2.7, sphinx 1.2.4,
index c5703f072344992f7ecceb177bbbfafb930b3cda..3c0557bae7f322a3330db90c21869596864b0970 100644 (file)
@@ -1,9 +1,13 @@
-This directory contains only the barebone version of the
-lmfit package, version 5.1. Full version is available from
+This directory contains only the barebones version of the
+lmfit package, version 6.1. Full version is available from
 http://apps.jcns.fz-juelich.de/doku/sc/lmfit
 
-License in gromacs root directory in file COPYING
+The license under which lmfit is bundled may be found in the GROMACS
+root directory in file COPYING.
+
+This version contains minor modifications
+* to convert to C++,
+* to declare functions not used outside lmfit.cpp as static,
+* to remove some dead code, and
+* to introduce some explicit pointer casts to pacify compilers.
 
-Update 20151209
-In order to avoid conflicts with other version of the library all exported routines
-and data have been prepended with gmx_
diff --git a/src/external/lmfit/gmx_lmcurve.cpp b/src/external/lmfit/gmx_lmcurve.cpp
deleted file mode 100644 (file)
index 6539c4f..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Library:   lmfit (Levenberg-Marquardt least squares fitting)
- *
- * File:      lmcurve.c
- *
- * Contents:  Implements lmcurve, a simplified API for curve fitting
- *            using the generic Levenberg-Marquardt routine lmmin.
- *
- * Copyright: Joachim Wuttke, Forschungszentrum Juelich GmbH (2004-2013)
- *
- * License:   see ../COPYING (FreeBSD)
- *
- * Homepage:  apps.jcns.fz-juelich.de/lmfit
- *
- * Note to programmers: Don't patch and fork, but copy and variate!
- *   If you need to compute residues differently, then please do not patch
- * lmcurve.c, but copy it to a differently named file, and rename lmcurve(),
- * lmcurve_evaluate() and lmcurve_data_struct before adapting them to your
- * needs, like we have done in lmcurve_tyd.c.
- */
-#include "gmx_lmcurve.h"
-#include "gmx_lmmin.h"
-
-typedef struct {
-    const double* t;
-    const double* y;
-    const double* dy;
-    double (*f)(const double t, const double* par);
-} lmcurve_data_struct;
-
-static void lmcurve_evaluate(
-    const double* par, const int m_dat, const void* data, double* fvec,
-    int* info)
-{
-    lmcurve_data_struct* D = (lmcurve_data_struct*)data;
-    int i;
-    for (i = 0; i < m_dat; i++)
-    {
-        double dy = D->dy[i];
-        if (dy == 0)
-        {
-            dy = 1;
-        }
-        fvec[i] = (D->y[i] - D->f(D->t[i], par))/dy;
-    }
-    *info = 0;
-}
-
-void gmx_lmcurve(
-    const int n_par, double* par, const int m_dat,
-    const double* t, const double* y, const double *dy,
-    double (*f)(const double t, const double* par),
-    const lm_control_struct* control, lm_status_struct* status)
-{
-    lmcurve_data_struct data = { t, y, dy, f };
-
-    gmx_lmmin(n_par, par, m_dat, (const void*)&data, lmcurve_evaluate,
-          control, status);
-}
diff --git a/src/external/lmfit/gmx_lmcurve.h b/src/external/lmfit/gmx_lmcurve.h
deleted file mode 100644 (file)
index 1182fcc..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Library:   lmfit (Levenberg-Marquardt least squares fitting)
- *
- * File:      lmcurve.h
- *
- * Contents:  Declarations for Levenberg-Marquardt curve fitting.
- *
- * Copyright: Joachim Wuttke, Forschungszentrum Juelich GmbH (2004-2013)
- *
- * License:   see ../COPYING (FreeBSD)
- *
- * Homepage:  apps.jcns.fz-juelich.de/lmfit
- */
-
-#ifndef GMX_LMCURVE_H
-#define GMX_LMCURVE_H
-
-#include "gmx_lmstruct.h"
-
-void gmx_lmcurve( const int n_par, double *par, const int m_dat,
-                  const double *t, const double *y, const double *dy,
-                  double (*f)(const double t, const double *par ),
-                  const lm_control_struct *control,
-                  lm_status_struct *status );
-
-#endif /* GMX_LMCURVE_H */
similarity index 98%
rename from src/external/lmfit/gmx_lmmin.cpp
rename to src/external/lmfit/lmmin.cpp
index 15608cd249523b2e62a5e90f9027b8b2177c0174..0cb77e5545461bf7da5b613f1a30c88842f9ef18 100644 (file)
@@ -18,7 +18,7 @@
 #include <stdio.h>
 #include <math.h>
 #include <float.h>
-#include "gmx_lmmin.h"
+#include "lmmin.h"
 
 static double lm_enorm(int n, const double* x);
 
@@ -64,10 +64,10 @@ static void lm_qrsolv(const int n, double* r, const int ldr, const int* Pivot,
 */
 
 /* Predefined control parameter sets (msgfile=NULL means stdout). */
-const lm_control_struct gmx_lm_control_double = {
+const lm_control_struct lm_control_double = {
     LM_USERTOL, LM_USERTOL, LM_USERTOL, LM_USERTOL,
     100., 100, 1, NULL, 0, -1, -1};
-const lm_control_struct gmx_lm_control_float = {
+const lm_control_struct lm_control_float = {
     1.e-7, 1.e-7, 1.e-7, 1.e-7,
     100., 100, 1, NULL, 0, -1, -1};
 
@@ -75,7 +75,7 @@ const lm_control_struct gmx_lm_control_float = {
 /*  Message texts (indexed by status.info)                                    */
 /******************************************************************************/
 
-const char* gmx_lm_infmsg[] = {
+const char* lm_infmsg[] = {
     "found zero (sum of squares below underflow limit)",
     "converged  (the relative error in the sum of squares is at most tol)",
     "converged  (the relative error of the parameter vector is at most tol)",
@@ -106,10 +106,10 @@ static void lm_print_pars(int nout, const double* par, FILE* fout)
 /*  lmmin (main minimization routine)                                         */
 /******************************************************************************/
 
-void gmx_lmmin(const int n, double* x, const int m, const void* data,
-               void (*evaluate)(const double* par, const int m_dat,
-                                const void* data, double* fvec, int* userbreak),
-               const lm_control_struct* C, lm_status_struct* S)
+void lmmin(const int n, double* x, const int m, const void* data,
+           void (*evaluate)(const double* par, const int m_dat,
+                            const void* data, double* fvec, int* userbreak),
+           const lm_control_struct* C, lm_status_struct* S)
 {
     int j, i;
     double actred, dirder, fnorm, fnorm1, gnorm, pnorm, prered, ratio, step,
similarity index 83%
rename from src/external/lmfit/gmx_lmmin.h
rename to src/external/lmfit/lmmin.h
index 41803bfcb87021da2d8fe0c7b338d118ff0a81f9..17b4880c994445adc136e974e572e49cfad469e6 100644 (file)
  * Homepage:  apps.jcns.fz-juelich.de/lmfit
  */
 
-#ifndef GMX_LMMIN_H
-#define GMX_LMMIN_H
+#ifndef LMMIN_H
+#define LMMIN_H
 
-#include "gmx_lmstruct.h"
+#include "lmstruct.h"
 
 /*! \brief
  * Levenberg-Marquardt minimization.
@@ -56,9 +56,9 @@
  *      status contains OUTPUT variables that inform about the fit result,
  *        as declared and explained in lmstruct.h
  */
-void gmx_lmmin( const int n_par, double *par, const int m_dat, const void *data,
-                void (*evaluate) (const double *par, const int m_dat, const void *data,
-                                  double *fvec, int *userbreak),
-                const lm_control_struct *control, lm_status_struct *status );
+void lmmin( const int n_par, double *par, const int m_dat, const void *data,
+            void (*evaluate) (const double *par, const int m_dat, const void *data,
+                              double *fvec, int *userbreak),
+            const lm_control_struct *control, lm_status_struct *status );
 
-#endif /* GMX_LMMIN_H */
+#endif /* LMMIN_H */
similarity index 92%
rename from src/external/lmfit/gmx_lmstruct.h
rename to src/external/lmfit/lmstruct.h
index 8f69e0987aca43a543c947c644da7b07f996d94a..d545ff10754803f5bfb8bcd10b815ef4d3db6db2 100644 (file)
@@ -12,8 +12,8 @@
  * Homepage:  apps.jcns.fz-juelich.de/lmfit
  */
 
-#ifndef GMX_LMSTRUCT_H
-#define GMX_LMSTRUCT_H
+#ifndef LMSTRUCT_H
+#define LMSTRUCT_H
 
 #include <stdio.h>
 
@@ -59,12 +59,12 @@ typedef struct {
 } lm_status_struct;
 
 /* Preset (and recommended) control parameter settings. */
-extern const lm_control_struct gmx_lm_control_double;
-extern const lm_control_struct gmx_lm_control_float;
+extern const lm_control_struct lm_control_double;
+extern const lm_control_struct lm_control_float;
 
 /* Preset message texts. */
 
-extern const char *gmx_lm_infmsg[];
-extern const char *gmx_lm_shortmsg[];
+extern const charlm_infmsg[];
+extern const charlm_shortmsg[];
 
-#endif /* GMX_LMSTRUCT_H */
+#endif /* LMSTRUCT_H */
index ab9d64df47434432144fd59dd17a67e8fec9a433..fd321f1e1cbbe81b98e100baaeff7aabeebd6004 100644 (file)
@@ -124,6 +124,10 @@ list(APPEND LIBGROMACS_SOURCES ${THREAD_MPI_SOURCES})
 list(APPEND LIBGROMACS_SOURCES ${TNG_SOURCES})
 tng_set_source_properties(WITH_ZLIB ${HAVE_ZLIB})
 
+get_lmfit_properties(LMFIT_SOURCES LMFIT_LIBRARIES_TO_LINK LMFIT_INCLUDE_DIRECTORY LMFIT_INCLUDE_DIR_ORDER)
+include_directories(${LMFIT_INCLUDE_DIR_ORDER} SYSTEM "${LMFIT_INCLUDE_DIRECTORY}")
+list(APPEND LIBGROMACS_SOURCES ${LMFIT_SOURCES})
+
 configure_file(version.h.cmakein version.h)
 gmx_install_headers(
     analysisdata.h
@@ -179,6 +183,7 @@ target_link_libraries(libgromacs
                       ${TNG_IO_LIBRARIES}
                       ${FFT_LIBRARIES} ${LINEAR_ALGEBRA_LIBRARIES}
                       ${XML_LIBRARIES}
+                      ${LMFIT_LIBRARIES_TO_LINK}
                       ${THREAD_LIB} ${GMX_SHARED_LINKER_FLAGS} ${OPENCL_LIBRARIES}
                       ${GMX_STDLIB_LIBRARIES})
 set_target_properties(libgromacs PROPERTIES
index ea36bedd9b5c7f1e1fe5225404bcf3db2d1dfd61..564c52f14018b0430123051b31e89a3091f1a25b 100644 (file)
@@ -33,9 +33,8 @@
 # the research papers on the package. Check out http://www.gromacs.org.
 
 file(GLOB GMXCORRFUNC_SOURCES *.cpp)
-file(GLOB LMFIT_SOURCES ${CMAKE_SOURCE_DIR}/src/external/lmfit/*.cpp)
 
-set(LIBGROMACS_SOURCES ${LIBGROMACS_SOURCES} ${GMXCORRFUNC_SOURCES}  ${LMFIT_SOURCES} PARENT_SCOPE)
+set(LIBGROMACS_SOURCES ${LIBGROMACS_SOURCES} ${GMXCORRFUNC_SOURCES} PARENT_SCOPE)
 if (BUILD_TESTING)
     add_subdirectory(tests)
 endif()
index 11fbff4c68441193f2a0a2b15e4e27980efafbde..9eac51beae7037edd469542561bb48b78f2491e0 100644 (file)
@@ -52,7 +52,7 @@
 
 #include <algorithm>
 
-#include "external/lmfit/gmx_lmcurve.h"
+#include <lmstruct.h>
 
 #include "gromacs/correlationfunctions/integrate.h"
 #include "gromacs/fileio/xvgr.h"
@@ -64,6 +64,8 @@
 #include "gromacs/utility/real.h"
 #include "gromacs/utility/smalloc.h"
 
+#include "gmx_lmcurve.h"
+
 /*! \brief Number of parameters for each fitting function */
 static const int nfp_ffn[effnNR] = { 0, 1, 2, 3, 5, 7, 9, 2, 4, 3, 6 };
 
@@ -448,7 +450,7 @@ static gmx_bool lmfit_exp(int          nfit,
     /* Using default control structure for double precision fitting that
      * comes with the lmfit package (i.e. from the include file).
      */
-    control            = gmx_lm_control_double;
+    control            = lm_control_double;
     control.verbosity  = (bVerbose ? 1 : 0);
     control.n_maxpri   = 0;
     control.m_maxpri   = 0;
@@ -490,7 +492,7 @@ static gmx_bool lmfit_exp(int          nfit,
         {
             printf("status: fnorm = %g, nfev = %d, userbreak = %d\noutcome = %s\n",
                    status->fnorm, status->nfev, status->userbreak,
-                   gmx_lm_infmsg[status->outcome]);
+                   lm_infmsg[status->outcome]);
         }
         if (bVerbose)
         {
diff --git a/src/gromacs/correlationfunctions/gmx_lmcurve.cpp b/src/gromacs/correlationfunctions/gmx_lmcurve.cpp
new file mode 100644 (file)
index 0000000..f3a103c
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2016, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal
+ * \file
+ * \brief
+ * Defines a driver routine for lmfit, and a callback for it to use.
+ *
+ * \author David van der Spoel <david.vanderspoel@icm.uu.se>
+ * \ingroup module_correlationfunctions
+ */
+#include "gmxpre.h"
+
+#include "gmx_lmcurve.h"
+
+#include <lmmin.h>
+#include <lmstruct.h>
+
+typedef struct {
+    const double* t;
+    const double* y;
+    const double* dy;
+    double (*f)(const double t, const double* par);
+} lmcurve_data_struct;
+
+//! Callback function used by lmmin
+static void lmcurve_evaluate(
+        const double* par, const int m_dat, const void* data, double* fvec,
+        int* info)
+{
+    lmcurve_data_struct* D = (lmcurve_data_struct*)data;
+    int                  i;
+    for (i = 0; i < m_dat; i++)
+    {
+        double dy = D->dy[i];
+        if (dy == 0)
+        {
+            dy = 1;
+        }
+        fvec[i] = (D->y[i] - D->f(D->t[i], par))/dy;
+    }
+    *info = 0;
+}
+
+void gmx_lmcurve(
+        const int n_par, double* par, const int m_dat,
+        const double* t, const double* y, const double *dy,
+        double (*f)(double t, const double* par),
+        const lm_control_struct* control, lm_status_struct* status)
+{
+    lmcurve_data_struct data = { t, y, dy, f };
+
+    lmmin(n_par, par, m_dat, (const void*)&data, lmcurve_evaluate,
+          control, status);
+}
diff --git a/src/gromacs/correlationfunctions/gmx_lmcurve.h b/src/gromacs/correlationfunctions/gmx_lmcurve.h
new file mode 100644 (file)
index 0000000..0f6c957
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2016, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \libinternal
+ * \file
+ * \brief
+ * Declares a driver routine for lmfit.
+ *
+ * \author David van der Spoel <david.vanderspoel@icm.uu.se>
+ * \ingroup module_correlationfunctions
+ */
+#ifndef GMX_CORRELATION_FUNCTIONS_GMX_LMCURVE_H
+#define GMX_CORRELATION_FUNCTIONS_GMX_LMCURVE_H
+
+#include <lmstruct.h>
+
+//! Calls lmmin with the given data, with callback function \c f.
+void gmx_lmcurve( const int n_par, double *par, const int m_dat,
+                  const double *t, const double *y, const double *dy,
+                  double (*f)(double t, const double *par ),
+                  const lm_control_struct *control,
+                  lm_status_struct *status );
+
+#endif