Index: configure.ac
===================================================================
--- configure.ac	(revision 57f14c9b30bd737681a0792dea763fb79e3b0be1)
+++ configure.ac	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
@@ -251,6 +251,11 @@
 
 # Check for Levenberg-Marquardt implementation
-enable_levmar=no
-AX_LAPACK([enable_levmar=yes],[enable_levmar=no])
+AC_ARG_ENABLE(
+  [levmar],
+  AS_HELP_STRING([--enable-levmar],[turn on LevMar feature [default=no]]),
+  enable_levmar=$enableval,
+  enable_levmar="no")
+AS_IF([test x"$enable_levmar" = x"yes"],[
+	AX_LAPACK([enable_levmar=yes],[enable_levmar=no])])
 AC_MSG_CHECKING(whether to compile in Levenberg-Marquardt)
 AS_IF([test x"$enable_levmar" = x"yes"],[
Index: src/Actions/FragmentationAction/FitPotentialAction.cpp
===================================================================
--- src/Actions/FragmentationAction/FitPotentialAction.cpp	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
+++ src/Actions/FragmentationAction/FitPotentialAction.cpp	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
@@ -0,0 +1,285 @@
+/*
+ * Project: MoleCuilder
+ * Description: creates and alters molecular systems
+ * Copyright (C)  2013 University of Bonn. All rights reserved.
+ * 
+ *
+ *   This file is part of MoleCuilder.
+ *
+ *    MoleCuilder is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    MoleCuilder 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with MoleCuilder.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * FitPotentialAction.cpp
+ *
+ *  Created on: Apr 09, 2013
+ *      Author: heber
+ */
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+// needs to come before MemDebug due to placement new
+#include <boost/archive/text_iarchive.hpp>
+
+#include "CodePatterns/MemDebug.hpp"
+
+#include <algorithm>
+#include <boost/bind.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/foreach.hpp>
+#include <map>
+#include <string>
+#include <sstream>
+
+#include "Actions/FragmentationAction/FitPotentialAction.hpp"
+
+#include "CodePatterns/Log.hpp"
+
+#include "Element/element.hpp"
+#include "Fragmentation/Homology/HomologyContainer.hpp"
+#include "Fragmentation/Homology/HomologyGraph.hpp"
+#include "Fragmentation/Summation/SetValues/Fragment.hpp"
+#include "FunctionApproximation/Extractors.hpp"
+#include "FunctionApproximation/FunctionApproximation.hpp"
+#include "FunctionApproximation/FunctionModel.hpp"
+#include "FunctionApproximation/TrainingData.hpp"
+#include "FunctionApproximation/writeDistanceEnergyTable.hpp"
+#include "Potentials/PotentialFactory.hpp"
+#include "Potentials/SerializablePotential.hpp"
+
+using namespace MoleCuilder;
+
+// and construct the stuff
+#include "FitPotentialAction.def"
+#include "Action_impl_pre.hpp"
+/** =========== define the function ====================== */
+
+HomologyGraph getFirstGraphwithSpecifiedElements(
+    const HomologyContainer &homologies,
+    const SerializablePotential::ParticleTypes_t &types)
+{
+  ASSERT( !types.empty(),
+      "getFirstGraphwithSpecifiedElements() - charges is empty?");
+  // create charges
+  Fragment::charges_t charges;
+  charges.resize(types.size());
+  std::transform(types.begin(), types.end(),
+      charges.begin(), boost::lambda::_1);
+  // convert into count map
+  Extractors::elementcounts_t counts_per_charge =
+      Extractors::_detail::getElementCounts(charges);
+  ASSERT( !counts_per_charge.empty(),
+      "getFirstGraphwithSpecifiedElements() - charge counts are empty?");
+  LOG(2, "DEBUG: counts_per_charge is " << counts_per_charge << ".");
+  // we want to check each (unique) key only once
+  HomologyContainer::const_key_iterator olditer = homologies.key_end();
+  for (HomologyContainer::const_key_iterator iter =
+      homologies.key_begin(); iter != homologies.key_end(); olditer = iter++) {
+    // if it's the same as the old one, skip it
+    if (*olditer == *iter)
+      continue;
+    // if it's a new key, check if every element has the right number of counts
+    Extractors::elementcounts_t::const_iterator countiter = counts_per_charge.begin();
+    for (; countiter != counts_per_charge.end(); ++countiter)
+      if (!(*iter).hasTimesAtomicNumber(countiter->first,countiter->second))
+        break;
+    if( countiter == counts_per_charge.end())
+      return *iter;
+  }
+  return HomologyGraph();
+}
+
+Action::state_ptr FragmentationFitPotentialAction::performCall() {
+  // charges specify the potential type
+  SerializablePotential::ParticleTypes_t chargenumbers;
+  {
+    const std::vector<const element *> &charges = params.charges.get();
+    std::transform(charges.begin(), charges.end(), std::back_inserter(chargenumbers),
+        boost::bind(&element::getAtomicNumber, _1));
+  }
+  // fragment specifies the homology fragment to use
+  SerializablePotential::ParticleTypes_t fragmentnumbers;
+  {
+    const std::vector<const element *> &fragment = params.fragment.get();
+    std::transform(fragment.begin(), fragment.end(), std::back_inserter(fragmentnumbers),
+        boost::bind(&element::getAtomicNumber, _1));
+  }
+
+  // parse homologies into container
+  HomologyContainer homologies;
+  if (boost::filesystem::exists(params.homology_file.get())) {
+    std::ifstream returnstream(params.homology_file.get().string().c_str());
+    if (returnstream.good()) {
+      boost::archive::text_iarchive ia(returnstream);
+      ia >> homologies;
+    } else {
+      ELOG(0, "Failed to parse from " << params.homology_file.get().string() << ".");
+      return Action::failure;
+    }
+    returnstream.close();
+  } else {
+    ELOG(0, params.homology_file.get() << " does not exist.");
+    return Action::failure;
+  }
+
+  // first we try to look into the HomologyContainer
+  LOG(1, "INFO: Listing all present homologies ...");
+  for (HomologyContainer::container_t::const_iterator iter =
+      homologies.begin(); iter != homologies.end(); ++iter) {
+    LOG(1, "INFO: graph " << iter->first << " has Fragment " << iter->second.first
+        << " and associated energy " << iter->second.second << ".");
+  }
+
+  LOG(0, "STATUS: I'm training now a " << params.potentialtype.get() << " potential on charges "
+      << chargenumbers << " on data from " << params.homology_file.get() << ".");
+
+  /******************** TRAINING ********************/
+  // fit potential
+  FunctionModel *model =
+      PotentialFactory::getInstance().createInstance(
+          params.potentialtype.get(),
+          chargenumbers);
+  ASSERT( model != NULL,
+      "main() - model returned from PotentialFactory is NULL.");
+  FunctionModel::parameters_t bestparams(model->getParameterDimension(), 0.);
+  {
+    // then we ought to pick the right HomologyGraph ...
+    const HomologyGraph graph = getFirstGraphwithSpecifiedElements(homologies,fragmentnumbers);
+    if (graph != HomologyGraph()) {
+      LOG(1, "First representative graph containing fragment "
+          << fragmentnumbers << " is " << graph << ".");
+
+      // Afterwards we go through all of this type and gather the distance and the energy value
+      TrainingData data(model->getFragmentSpecificExtractor());
+      data(homologies.getHomologousGraphs(graph));
+
+      // print distances and energies if desired for debugging
+      if (!data.getTrainingInputs().empty()) {
+        // print which distance is which
+        size_t counter=1;
+        if (DoLog(3)) {
+          const FunctionModel::arguments_t &inputs = data.getTrainingInputs()[0];
+          for (FunctionModel::arguments_t::const_iterator iter = inputs.begin();
+              iter != inputs.end(); ++iter) {
+            const argument_t &arg = *iter;
+            LOG(3, "DEBUG: distance " << counter++ << " is between (#"
+                << arg.indices.first << "c" << arg.types.first << ","
+                << arg.indices.second << "c" << arg.types.second << ").");
+          }
+        }
+
+        // print table
+        LOG(3, "DEBUG: I gathered the following training data:\n" <<
+            _detail::writeDistanceEnergyTable(data.getDistanceEnergyTable()));
+      }
+
+      // now perform the function approximation by optimizing the model function
+      FunctionApproximation approximator(data, *model);
+      if (model->isBoxConstraint() && approximator.checkParameterDerivatives()) {
+        double l2error = std::numeric_limits<double>::infinity();
+        // seed with current time
+        srand((unsigned)time(0));
+        for (unsigned int runs=0; runs < params.best_of_howmany.get(); ++runs) {
+          // generate new random initial parameter values
+          model->setParametersToRandomInitialValues(data);
+          LOG(1, "INFO: Initial parameters of run " << runs << " are "
+              << model->getParameters() << ".");
+          approximator(FunctionApproximation::ParameterDerivative);
+          LOG(1, "INFO: Final parameters of run " << runs << " are "
+              << model->getParameters() << ".");
+          const double new_l2error = data.getL2Error(*model);
+          if (new_l2error < l2error) {
+            // store currently best parameters
+            l2error = new_l2error;
+            bestparams = model->getParameters();
+            LOG(1, "STATUS: New fit from run " << runs
+                << " has better error of " << l2error << ".");
+          }
+        }
+        // reset parameters from best fit
+        model->setParameters(bestparams);
+        LOG(1, "INFO: Best parameters with L2 error of "
+            << l2error << " are " << model->getParameters() << ".");
+      } else {
+        ELOG(0, "We require parameter derivatives for a box constraint minimization.");
+        return Action::failure;
+      }
+
+      // create a map of each fragment with error.
+      typedef std::multimap< double, size_t > WorseFragmentMap_t;
+      WorseFragmentMap_t WorseFragmentMap;
+      HomologyContainer::range_t fragmentrange = homologies.getHomologousGraphs(graph);
+      // fragments make it into the container in reversed order, hence count from top down
+      size_t index= std::distance(fragmentrange.first, fragmentrange.second)-1;
+      for (HomologyContainer::const_iterator iter = fragmentrange.first;
+          iter != fragmentrange.second;
+          ++iter) {
+        const Fragment& fragment = iter->second.first;
+        const double &energy = iter->second.second;
+
+        // create arguments from the fragment
+        FunctionModel::extractor_t extractor = model->getFragmentSpecificExtractor();
+        FunctionModel::arguments_t args = extractor(fragment, 1);
+
+        // calculate value from potential
+        const double fitvalue = (*model)(args)[0];
+
+        // insert difference into map
+        const double error = fabs(energy - fitvalue);
+        WorseFragmentMap.insert( std::make_pair( error, index-- ) );
+
+        {
+          // give only the distances in the debugging text
+          std::stringstream streamargs;
+          BOOST_FOREACH (argument_t arg, args) {
+            streamargs << " " << arg.distance*AtomicLengthToAngstroem;
+          }
+          LOG(2, "DEBUG: frag.#" << index+1 << "'s error is |" << energy << " - " << fitvalue
+              << "| = " << error << " for args " << streamargs.str() << ".");
+        }
+      }
+      LOG(0, "RESULT: WorstFragmentMap " << WorseFragmentMap << ".");
+
+      SerializablePotential *potential = dynamic_cast<SerializablePotential *>(model);
+      if (potential != NULL) {
+        LOG(1, "STATUS: Resulting parameters are " << std::endl << *potential);
+      } else {
+        LOG(1, "INFO: FunctionModel is no serializable potential.");
+      }
+    }
+  }
+  delete model;
+
+  return Action::success;
+}
+
+Action::state_ptr FragmentationFitPotentialAction::performUndo(Action::state_ptr _state) {
+  return Action::success;
+}
+
+Action::state_ptr FragmentationFitPotentialAction::performRedo(Action::state_ptr _state){
+  return Action::success;
+}
+
+bool FragmentationFitPotentialAction::canUndo() {
+  return false;
+}
+
+bool FragmentationFitPotentialAction::shouldUndo() {
+  return false;
+}
+/** =========== end of function ====================== */
Index: src/Actions/FragmentationAction/FitPotentialAction.def
===================================================================
--- src/Actions/FragmentationAction/FitPotentialAction.def	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
+++ src/Actions/FragmentationAction/FitPotentialAction.def	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
@@ -0,0 +1,47 @@
+/*
+ * FitPotentialAction.def
+ *
+ *  Created on: Apr 08, 2013
+ *      Author: heber
+ */
+
+// all includes and forward declarations necessary for non-integral types below
+#include <boost/filesystem/path.hpp>
+#include <string>
+#include <vector>
+
+#include "Parameters/Validators/RangeValidator.hpp"
+#include "Parameters/Validators/STLVectorValidator.hpp"
+#include "Parameters/Validators/Specific/ElementValidator.hpp"
+#include "Parameters/Validators/Specific/FilePresentValidator.hpp"
+#include "Parameters/Validators/Specific/PotentialTypeValidator.hpp"
+
+// i.e. there is an integer with variable name Z that can be found in
+// ValueStorage by the token "Z" -> first column: int, Z, "Z"
+// "undefine" if no parameters are required, use (NOPARAM_DEFAULT) for each (undefined) default value
+#define paramtypes (boost::filesystem::path)(std::string)(std::vector<const element *>)(std::vector<const element *>)(unsigned int)
+#define paramtokens ("homology-file")("fit-potential")("potential-charges")("fragment-charges")("take-best-of")
+#define paramdescriptions ("homology file to parse")("potential type to fit")("charges specifying the potential")("charges specifying the fragment")("take the best among this many approximations")
+#define paramdefaults (NOPARAM_DEFAULT)(NOPARAM_DEFAULT)(NOPARAM_DEFAULT)(NOPARAM_DEFAULT)(PARAM_DEFAULT(3))
+#define paramreferences (homology_file)(potentialtype)(charges)(fragment)(best_of_howmany)
+#define paramvalids \
+(FilePresentValidator()) \
+(PotentialTypeValidator()) \
+(STLVectorValidator< std::vector<const element *> >(1,99, ElementValidator())) \
+(STLVectorValidator< std::vector<const element *> >(1,99, ElementValidator())) \
+(RangeValidator< unsigned int>(1,99))
+
+#undef statetypes
+#undef statereferences
+
+// some defines for all the names, you may use ACTION, STATE and PARAMS
+#define CATEGORY Fragmentation
+#define MENUNAME "fragmentation"
+#define MENUPOSITION 6
+#define ACTIONNAME FitPotential
+#define TOKEN "fit-potential"
+
+
+// finally the information stored in the ActionTrait specialization
+#define DESCRIPTION "fit an empirical potential to the given part of a specified fragment"
+#undef SHORTFORM
Index: src/Actions/FragmentationAction/FitPotentialAction.hpp
===================================================================
--- src/Actions/FragmentationAction/FitPotentialAction.hpp	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
+++ src/Actions/FragmentationAction/FitPotentialAction.hpp	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
@@ -0,0 +1,22 @@
+/*
+ * FitPotentialAction.hpp
+ *
+ *  Created on: Apr 09, 2013
+ *      Author: heber
+ */
+
+#ifndef FITPOTENTIALACTION_HPP_
+#define FITPOTENTIALACTION_HPP_
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include "Actions/Action.hpp"
+
+#include "FitPotentialAction.def"
+#include "Action_impl_header.hpp"
+
+#endif /* FITPOTENTIALACTION_HPP_ */
Index: src/Actions/GlobalListOfActions.hpp
===================================================================
--- src/Actions/GlobalListOfActions.hpp	(revision 57f14c9b30bd737681a0792dea763fb79e3b0be1)
+++ src/Actions/GlobalListOfActions.hpp	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
@@ -122,6 +122,6 @@
   (SelectionNotAllShapes) \
   (SelectionNotShapeByName) \
+  (FragmentationAnalyseFragmentationResults) \
   (FragmentationFragmentation) \
-  (FragmentationAnalyseFragmentationResults) \
   (FragmentationStoreSaturatedFragment) \
   (FillRegularGrid) \
@@ -136,5 +136,5 @@
 // we need to append the automation action in case we have the JobMarket
 #ifdef HAVE_JOBMARKET
-#define GLOBALLISTOFACTIONS \
+#define GLOBALLISTOFACTIONS_JOBMARKET \
     BOOST_PP_SEQ_PUSH_BACK( \
         BOOST_PP_SEQ_PUSH_BACK( \
@@ -145,8 +145,22 @@
     )
 #else
-#define GLOBALLISTOFACTIONS \
+#define GLOBALLISTOFACTIONS_JOBMARKET \
     GLOBALLISTOFACTIONS_initial
 #endif /* HAVE_JOBMARKET */
 
+#ifdef HAVE_LEVMAR
+#define GLOBALLISTOFACTIONS_LEVMAR \
+    BOOST_PP_SEQ_PUSH_BACK( \
+        GLOBALLISTOFACTIONS_JOBMARKET, \
+        FragmentationFitPotential \
+    )
+#else
+#define GLOBALLISTOFACTIONS_LEVMAR \
+    GLOBALLISTOFACTIONS_JOBMARKET
+#endif /* HAVE_LEVMAR */
+
+// define final list
+#define GLOBALLISTOFACTIONS GLOBALLISTOFACTIONS_LEVMAR
+
 #endif /* GLOBALLISTOFACTIONS_HPP_ */
 
Index: src/Actions/Makefile.am
===================================================================
--- src/Actions/Makefile.am	(revision 57f14c9b30bd737681a0792dea763fb79e3b0be1)
+++ src/Actions/Makefile.am	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
@@ -234,4 +234,14 @@
   Actions/FragmentationAction/ParseFragmentJobsAction.def
 endif
+
+if CONDLEVMAR
+FRAGMENTATIONACTIONSOURCE += \
+  Actions/FragmentationAction/FitPotentialAction.cpp
+FRAGMENTATIONACTIONHEADER += \
+  Actions/FragmentationAction/FitPotentialAction.hpp
+FRAGMENTATIONACTIONDEFS += \
+  Actions/FragmentationAction/FitPotentialAction.def
+endif
+
 
 GRAPHACTIONSOURCE = \
@@ -543,4 +553,7 @@
 libMolecuilderActionPrototypes_la_CPPFLAGS += $(JobMarket_CFLAGS)
 endif
+if CONDLEVMAR
+libMolecuilderActionPrototypes_la_CPPFLAGS += $(LEVMAR_CPPFLAGS)
+endif
 libMolecuilderActions_la_includedir = $(includedir)/MoleCuilder/
 libMolecuilderActionPrototypes_la_includedir = $(includedir)/MoleCuilder/
Index: c/LevMartester.cpp
===================================================================
--- src/LevMartester.cpp	(revision 57f14c9b30bd737681a0792dea763fb79e3b0be1)
+++ 	(revision )
@@ -1,382 +1,0 @@
-/*
- * Project: MoleCuilder
- * Description: creates and alters molecular systems
- * Copyright (C)  2012 University of Bonn. All rights reserved.
- * Please see the COPYING file or "Copyright notice" in builder.cpp for details.
- * 
- *
- *   This file is part of MoleCuilder.
- *
- *    MoleCuilder is free software: you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation, either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    MoleCuilder 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 General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with MoleCuilder.  If not, see <http://www.gnu.org/licenses/>. 
- */
-
-/*
- * LevMartester.cpp
- *
- *  Created on: Sep 27, 2012
- *      Author: heber
- */
-
-
-// include config.h
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <boost/archive/text_iarchive.hpp>
-
-#include "CodePatterns/MemDebug.hpp"
-
-#include <boost/assign.hpp>
-#include <boost/assign/list_of.hpp>
-#include <boost/bind.hpp>
-#include <boost/filesystem.hpp>
-#include <boost/foreach.hpp>
-#include <boost/function.hpp>
-#include <boost/lambda/lambda.hpp>
-#include <boost/program_options.hpp>
-
-#include <cstdlib>
-#include <ctime>
-#include <fstream>
-#include <iostream>
-#include <iterator>
-#include <list>
-#include <vector>
-
-#include <levmar.h>
-
-#include "CodePatterns/Assert.hpp"
-#include "CodePatterns/Log.hpp"
-
-#include "LinearAlgebra/Vector.hpp"
-
-#include "Fragmentation/Homology/HomologyContainer.hpp"
-#include "Fragmentation/Summation/SetValues/Fragment.hpp"
-#include "FunctionApproximation/Extractors.hpp"
-#include "FunctionApproximation/FunctionApproximation.hpp"
-#include "FunctionApproximation/FunctionModel.hpp"
-#include "FunctionApproximation/TrainingData.hpp"
-#include "FunctionApproximation/writeDistanceEnergyTable.hpp"
-#include "Helpers/defs.hpp"
-#include "Potentials/PotentialFactory.hpp"
-#include "Potentials/PotentialRegistry.hpp"
-#include "Potentials/Specifics/PairPotential_Morse.hpp"
-#include "Potentials/Specifics/PairPotential_Angle.hpp"
-#include "Potentials/Specifics/SaturationPotential.hpp"
-#include "types.hpp"
-
-namespace po = boost::program_options;
-
-using namespace boost::assign;
-
-HomologyGraph getFirstGraphwithSpecifiedElements(
-    const HomologyContainer &homologies,
-    const SerializablePotential::ParticleTypes_t &types)
-{
-  ASSERT( !types.empty(),
-      "getFirstGraphwithSpecifiedElements() - charges is empty?");
-  // create charges
-  Fragment::charges_t charges;
-  charges.resize(types.size());
-  std::transform(types.begin(), types.end(),
-      charges.begin(), boost::lambda::_1);
-  // convert into count map
-  Extractors::elementcounts_t counts_per_charge =
-      Extractors::_detail::getElementCounts(charges);
-  ASSERT( !counts_per_charge.empty(),
-      "getFirstGraphwithSpecifiedElements() - charge counts are empty?");
-  LOG(2, "DEBUG: counts_per_charge is " << counts_per_charge << ".");
-  // we want to check each (unique) key only once
-  HomologyContainer::const_key_iterator olditer = homologies.key_end();
-  for (HomologyContainer::const_key_iterator iter =
-      homologies.key_begin(); iter != homologies.key_end(); olditer = iter++) {
-    // if it's the same as the old one, skip it
-    if (*olditer == *iter)
-      continue;
-    // if it's a new key, check if every element has the right number of counts
-    Extractors::elementcounts_t::const_iterator countiter = counts_per_charge.begin();
-    for (; countiter != counts_per_charge.end(); ++countiter)
-      if (!(*iter).hasTimesAtomicNumber(countiter->first,countiter->second))
-        break;
-    if( countiter == counts_per_charge.end())
-      return *iter;
-  }
-  return HomologyGraph();
-}
-
-/** This function returns the elements of the sum over index "k" for an
- * argument containing indices "i" and "j"
- * @param inputs vector of all configuration (containing each a vector of all arguments)
- * @param arg argument containing indices "i" and "j"
- * @param cutoff cutoff criterion for sum over k
- * @return vector of argument pairs (a vector) of ik and jk for at least all k
- *        within distance of \a cutoff to i
- */
-std::vector<FunctionModel::arguments_t>
-getTripleFromArgument(const FunctionApproximation::inputs_t &inputs, const argument_t &arg, const double cutoff)
-{
-  typedef std::list<argument_t> arg_list_t;
-  typedef std::map<size_t, arg_list_t > k_args_map_t;
-  k_args_map_t tempresult;
-  ASSERT( inputs.size() > arg.globalid,
-      "getTripleFromArgument() - globalid "+toString(arg.globalid)
-      +" is greater than all inputs "+toString(inputs.size())+".");
-  const FunctionModel::arguments_t &listofargs = inputs[arg.globalid];
-  for (FunctionModel::arguments_t::const_iterator argiter = listofargs.begin();
-      argiter != listofargs.end();
-      ++argiter) {
-    // first index must be either i or j but second index not
-    if (((argiter->indices.first == arg.indices.first)
-        || (argiter->indices.first == arg.indices.second))
-      && ((argiter->indices.second != arg.indices.first)
-          && (argiter->indices.second != arg.indices.second))) {
-      // we need arguments ik and jk
-      std::pair< k_args_map_t::iterator, bool> inserter =
-          tempresult.insert( std::make_pair( argiter->indices.second, arg_list_t(1,*argiter)));
-      if (!inserter.second) {
-        // is present one ik or jk, if ik insert jk at back
-        if (inserter.first->second.begin()->indices.first == arg.indices.first)
-          inserter.first->second.push_back(*argiter);
-        else // if jk, insert ik at front
-          inserter.first->second.push_front(*argiter);
-      }
-    }
-//    // or second index must be either i or j but first index not
-//    else if (((argiter->indices.first != arg.indices.first)
-//              && (argiter->indices.first != arg.indices.second))
-//            && ((argiter->indices.second == arg.indices.first)
-//                || (argiter->indices.second == arg.indices.second))) {
-//      // we need arguments ki and kj
-//      std::pair< k_args_map_t::iterator, bool> inserter =
-//          tempresult.insert( std::make_pair( argiter->indices.first, arg_list_t(1,*argiter)));
-//      if (!inserter.second) {
-//        // is present one ki or kj, if ki insert kj at back
-//        if (inserter.first->second.begin()->indices.second == arg.indices.first)
-//          inserter.first->second.push_back(*argiter);
-//        else // if kj, insert ki at front
-//          inserter.first->second.push_front(*argiter);
-//      }
-//    }
-  }
-  // check that i,j are NOT contained
-  ASSERT( tempresult.count(arg.indices.first) == 0,
-      "getTripleFromArgument() - first index of argument present in k_args_map?");
-  ASSERT( tempresult.count(arg.indices.second) == 0,
-      "getTripleFromArgument() - first index of argument present in k_args_map?");
-
-  // convert
-  std::vector<FunctionModel::arguments_t> result;
-  for (k_args_map_t::const_iterator iter = tempresult.begin();
-      iter != tempresult.end();
-      ++iter) {
-    ASSERT( iter->second.size() == 2,
-        "getTripleFromArgument() - for index "+toString(iter->first)+" we did not find both ik and jk.");
-    result.push_back( FunctionModel::arguments_t(iter->second.begin(), iter->second.end()) );
-  }
-  return result;
-}
-
-int main(int argc, char **argv)
-{
-  std::cout << "Hello to the World from LevMar!" << std::endl;
-
-//  setVerbosity(4);
-
-  // load homology file
-  po::options_description desc("Allowed options");
-  desc.add_options()
-      ("help", "produce help message")
-      ("homology-file", po::value< boost::filesystem::path >(), "homology file to parse")
-      ("fit-potential", po::value< std::string >(), "potential type to fit")
-      ("charges", po::value< SerializablePotential::ParticleTypes_t >()->multitoken(), "charges specifying the potential")
-      ("fragment", po::value< SerializablePotential::ParticleTypes_t >()->multitoken(), "all charges in the fragment")
-  ;
-
-  po::variables_map vm;
-  po::store(po::parse_command_line(argc, argv, desc), vm);
-  po::notify(vm);
-
-  if (vm.count("help")) {
-      std::cout << desc << "\n";
-      return 1;
-  }
-
-  // homology-file
-  boost::filesystem::path homology_file;
-  if (vm.count("homology-file")) {
-    homology_file = vm["homology-file"].as<boost::filesystem::path>();
-    LOG(1, "INFO: Parsing " << homology_file.string() << ".");
-  } else {
-    ELOG(0, "homology file (homology-file) was not set.");
-    return 1;
-  }
-
-  // type of potential to fit
-  std::string potentialtype;
-  if (vm.count("fit-potential")) {
-    potentialtype = vm["fit-potential"].as<std::string>();
-  } else {
-    ELOG(0, "potential type to fit (fit-potential) was not set.");
-    return 1;
-  }
-
-  // charges
-  SerializablePotential::ParticleTypes_t charges;
-  if (vm.count("charges")) {
-    charges = vm["charges"].as< SerializablePotential::ParticleTypes_t >();
-  } else {
-    ELOG(0, "Vector of charges specifying the potential (charges) was not set.");
-    return 1;
-  }
-
-  // fragment
-  SerializablePotential::ParticleTypes_t fragment;
-  if (vm.count("fragment")) {
-    fragment = vm["fragment"].as< SerializablePotential::ParticleTypes_t >();
-  } else {
-    ELOG(0, "Vector of charges specifying the fragment (charges) was not set.");
-    return 1;
-  }
-
-  // parse homologies into container
-  HomologyContainer homologies;
-  if (boost::filesystem::exists(homology_file)) {
-    std::ifstream returnstream(homology_file.string().c_str());
-    if (returnstream.good()) {
-      boost::archive::text_iarchive ia(returnstream);
-      ia >> homologies;
-    } else {
-      ELOG(0, "Failed to parse from " << homology_file.string() << ".");
-      return 1;
-    }
-    returnstream.close();
-  } else {
-    ELOG(0, homology_file << " does not exist.");
-    return 1;
-  }
-
-  // first we try to look into the HomologyContainer
-  LOG(1, "INFO: Listing all present homologies ...");
-  for (HomologyContainer::container_t::const_iterator iter =
-      homologies.begin(); iter != homologies.end(); ++iter) {
-    LOG(1, "INFO: graph " << iter->first << " has Fragment " << iter->second.first
-        << " and associated energy " << iter->second.second << ".");
-  }
-
-  LOG(0, "STATUS: I'm training now a " << potentialtype << " potential on charges "
-      << charges << ".");
-
-  /******************** TRAINING ********************/
-  // fit potential
-  FunctionModel *model =
-      PotentialFactory::getInstance().createInstance(
-          potentialtype,
-          charges);
-  ASSERT( model != NULL,
-      "main() - model returned from PotentialFactory is NULL.");
-  FunctionModel::parameters_t params(model->getParameterDimension(), 0.);
-  {
-    // then we ought to pick the right HomologyGraph ...
-    const HomologyGraph graph = getFirstGraphwithSpecifiedElements(homologies,fragment);
-    if (graph != HomologyGraph()) {
-      LOG(1, "First representative graph containing fragment "
-          << fragment << " is " << graph << ".");
-
-      // Afterwards we go through all of this type and gather the distance and the energy value
-      TrainingData data(model->getFragmentSpecificExtractor());
-      data(homologies.getHomologousGraphs(graph));
-      if (!data.getTrainingInputs().empty()) {
-        // print which distance is which
-        size_t counter=1;
-        const FunctionModel::arguments_t &inputs = data.getTrainingInputs()[0];
-        for (FunctionModel::arguments_t::const_iterator iter = inputs.begin();
-            iter != inputs.end(); ++iter) {
-          const argument_t &arg = *iter;
-          LOG(1, "INFO: distance " << counter++ << " is between (#"
-              << arg.indices.first << "c" << arg.types.first << ","
-              << arg.indices.second << "c" << arg.types.second << ").");
-        }
-
-        // print table
-        LOG(1, "INFO: I gathered the following training data:\n" <<
-            _detail::writeDistanceEnergyTable(data.getDistanceEnergyTable()));
-      }
-      // NOTICE that distance are in bohrradi as they come from MPQC!
-
-      // now perform the function approximation by optimizing the model function
-      FunctionApproximation approximator(data, *model);
-      if (model->isBoxConstraint() && approximator.checkParameterDerivatives()) {
-        // we set parameters here because we want to test with default ones
-        srand((unsigned)time(0)); // seed with current time
-        model->setParametersToRandomInitialValues(data);
-        LOG(0, "INFO: Initial parameters are " << model->getParameters() << ".");
-        approximator(FunctionApproximation::ParameterDerivative);
-      } else {
-        ELOG(0, "We require parameter derivatives for a box constraint minimization.");
-        return 1;
-      }
-
-      // create a map of each fragment with error.
-      typedef std::multimap< double, size_t > WorseFragmentMap_t;
-      WorseFragmentMap_t WorseFragmentMap;
-      HomologyContainer::range_t fragmentrange = homologies.getHomologousGraphs(graph);
-      // fragments make it into the container in reversed order, hence count from top down
-      size_t index= std::distance(fragmentrange.first, fragmentrange.second)-1;
-      for (HomologyContainer::const_iterator iter = fragmentrange.first;
-          iter != fragmentrange.second;
-          ++iter) {
-        const Fragment& fragment = iter->second.first;
-        const double &energy = iter->second.second;
-
-        // create arguments from the fragment
-        FunctionModel::extractor_t extractor = model->getFragmentSpecificExtractor();
-        FunctionModel::arguments_t args = extractor(fragment, 1);
-
-        // calculate value from potential
-        const double fitvalue = (*model)(args)[0];
-
-        // insert difference into map
-        const double error = fabs(energy - fitvalue);
-        WorseFragmentMap.insert( std::make_pair( error, index-- ) );
-
-        {
-          // give only the distances in the debugging text
-          std::stringstream streamargs;
-          BOOST_FOREACH (argument_t arg, args) {
-            streamargs << " " << arg.distance*AtomicLengthToAngstroem;
-          }
-          LOG(2, "DEBUG: frag.#" << index+1 << "'s error is |" << energy << " - " << fitvalue
-              << "| = " << error << " for args " << streamargs.str() << ".");
-        }
-      }
-      LOG(0, "RESULT: WorstFragmentMap " << WorseFragmentMap << ".");
-
-      params = model->getParameters();
-
-      SerializablePotential *potential = dynamic_cast<SerializablePotential *>(model);
-      if (potential != NULL) {
-        LOG(1, "STATUS: Resulting parameters are " << std::endl << *potential << ".");
-      } else {
-        LOG(1, "INFO: FunctionModel is no serializable potential.");
-      }
-    }
-  }
-  delete model;
-  // remove static instances
-  PotentialFactory::purgeInstance();
-
-  return 0;
-}
-
Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(revision 57f14c9b30bd737681a0792dea763fb79e3b0be1)
+++ src/Makefile.am	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
@@ -488,26 +488,4 @@
 endif
 
-if CONDLEVMAR
-bin_PROGRAMS += LevMartester
-LevMartester_SOURCES = LevMartester.cpp
-LevMartester_CPPFLAGS = $(AM_CPPFLAGS) $(LEVMAR_CPPFLAGS)
-LevMartester_LDFLAGS = $(AM_LDFLAGS) $(BOOST_SERIALIZATION_LDFLAGS) $(BOOST_PROGRAM_OPTIONS_LDFLAGS) $(BOOST_FILESYSTEM_LDFLAGS) $(BOOST_SYSTEM_LDFLAGS) ${CodePatterns_LDFLAGS} $(LEVMAR_LDFLAGS)
-LevMartester_LDADD = \
-	libMolecuilderPotentials.la \
-	libMolecuilderFunctionApproximation.la \
-	libMolecuilderFragmentation.la \
-	libMolecuilderFragmentation_getFromKeysetStub.la \
-	libMolecuilderFragmentationSetValues.la \
-	libMolecuilderHelpers.la \
-	$(top_builddir)/LinearAlgebra/src/LinearAlgebra/libLinearAlgebra.la \
-	$(BOOST_SERIALIZATION_LIBS) \
-	$(BOOST_PROGRAM_OPTIONS_LIBS) \
-	$(BOOST_FILESYSTEM_LIBS) \
-	$(BOOST_SYSTEM_LIBS) \
-	${CodePatterns_LIBS} \
-	$(LEVMAR_LIBS) \
-	$(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS)
-endif
-
 unity_SOURCES = unity.cpp
 unity_CPPFLAGS = $(AM_CPPFLAGS) 
Index: src/documentation/constructs/constructs.dox
===================================================================
--- src/documentation/constructs/constructs.dox	(revision 57f14c9b30bd737681a0792dea763fb79e3b0be1)
+++ src/documentation/constructs/constructs.dox	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
@@ -31,6 +31,6 @@
  *  \li \ref observers
  *  \li \ref parameters
- *  \li \ref parsers
- *  \li \ref potentials
+ *  \li \ref parsers "Parsers"
+ *  \li \ref potentials "Potentials"
  *  \li \ref qt-gui
  *  \li \ref queries
@@ -47,5 +47,5 @@
  *
  *
- * \date 2013-02-07
+ * \date 2013-04-09
  *
  */
Index: src/documentation/constructs/potentials.dox
===================================================================
--- src/documentation/constructs/potentials.dox	(revision 57f14c9b30bd737681a0792dea763fb79e3b0be1)
+++ src/documentation/constructs/potentials.dox	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
@@ -71,8 +71,9 @@
  *    perform the fit.
  *
- * \section potentials-howto Howto use the potentials
+ * \section potentials-howto-use Howto use the potentials
  *
  *  We just give a brief run-down in terms of code on how to use the potentials.
- *  Here, we just describe what to do in order to perform the fitting.
+ *  Here, we just describe what to do in order to perform the fitting. This is
+ *  basically what is implemented in FragmentationFitPotentialAction.
  *
  *  \code
@@ -102,5 +103,5 @@
  *  // give initial parameter
  *  FunctionModel::parameters_t params(PairPotential_Angle::MAXPARAMS, 0.);
- *  ... set some initial parameters
+ *  // ... set some potential-specific initial parameters in params struct
  *  angle.setParameters(params);
  *
@@ -123,8 +124,31 @@
  *  // evaluate
  *  FunctionModel::arguments_t args;
- *  .. initialise args to the desired distances
+ *  // .. initialise args to the desired distances
  *  const double value = angle(args)[0]; // output is a vector!
  *  \endcode
  *
- * \date 2012-11-28
+ * \section potentials-stability-of-fit note in stability of fit
+ *
+ *  As we always start from random initial parameters (within a certain sensible
+ *  range at least), the non-linear fit does not always converge. For this case
+ *  the FragmentationFitPotentialAction has the option "take-best-of" to allow
+ *  for multiple fits where the best (in terms of l2 error) is taken eventually.
+ *
+ * \section potentials-howto-add Howto add new potentials
+ *
+ *  Adding a new potential requires the following:
+ *  -# Add the new modules to Potentials/Specifics
+ *  -# Add a unit test on the potential in Potentials/Specifics/unittests
+ *  -# Give the potential a type name and add it to PotentialTypes.def. Note
+ *     that the name must not contain white space.
+ *  -# Add the potential name as case to PotentialFactory such that it knows
+ *     how to instantiate your new potential when requested.
+ *
+ * PotentialTypes.def contains a boost::preprocessor sequence of all
+ * potential names. PotentialFactory uses this sequence to build its enum to
+ * type map and inverse which the user sees when specifying the potential to
+ * fit via PotentialTypeValidator.
+ *
+ *
+ * \date 2013-04-09
  */
Index: src/documentation/install.dox
===================================================================
--- src/documentation/install.dox	(revision 57f14c9b30bd737681a0792dea763fb79e3b0be1)
+++ src/documentation/install.dox	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
@@ -55,4 +55,6 @@
  *    -# MPQC: see below for instructions
  *    -# ScaFaCoS: see below for instructions
+ *    -# VTK: see below for instructions
+ *    -# levmar: see below for instructions
  *
  *  If you are programming with or for MoleCuilder, the following packages are
@@ -109,8 +111,8 @@
  *  \subsubsection install-prerequisites-other-scafacos ScaFaCoS
  *
- *  ScaFaCoS is a library of fast Coulomb solvers, created by the same-named BMBF
- *  funded project. The library contains Versatile MultiGrid (vmg) as one of its
- *  solvers which is used in the BOSSANOVA scheme for the calculation of
- *  long-range forces.
+ *  ScaFaCoS (http://www.scafacos.org/) is a library of fast Coulomb solvers,
+ *  created by the same-named BMBF funded project. The library contains Versatile
+ *  MultiGrid (vmg) as one of its solvers which is used in the BOSSANOVA scheme
+ *  for the calculation of long-range forces.
  *
  *  ScaFaCoS requires the following packages to compile:
@@ -118,4 +120,29 @@
  *  -# F2C: libf2c2-dev
  *  -# Fortran compiler: gfortan
+ *  -# VTK >=5.10
+ *
+ *  Firstly, you should obtain a recent copy of the visualization tool kit (VTK)
+ *  (http://www.vtk.org/) and compile as
+ *  \code
+ *  export MPI_HOME=$( which mpirun | sed 's#/bin/mpirun##g')
+ *  export CXX_FLAGS=-fPIC
+ *  cmake -DCMAKE_INSTALL_PREFIX:PATH=<install-path> \
+ *        -DBUILD_SHARED_LIBS=TRUE \
+ *        -DCMAKE_BUILD_WITH_INSTALL_RPATH:BOOL=OFF \
+ *        -DCMAKE_INSTALL_RPATH:PATH=<install-path>/lib/vtk-<install-version> \
+ *        -DCMAKE_INSTALL_RPATH_USE_LINK_PATH:BOOL=ON \
+ *        -DCMAKE_SKIP_BUILD_RPATH:BOOL=OFF \
+ *        -DVTK_USE_PARALLEL:BOOL=ON \
+ *        -DVTK_USE_MPI:BOOL=ON \
+ *        -DMPI_LIBRARY:PATH=${MPI_HOME}/lib/libmpi.so \
+ *        -DMPI_EXTRA_LIBRARY:PATH=${MPI_HOME}/lib/libmpi_cxx.so \
+ *        -DMPI_INCLUDE_PATH:PATH=${MPI_HOME}/include/mpi \
+ *        ..
+ *  make -j4
+ *  make install
+ *  \endcode
+ *  where we force rpath-linking and shared libraries (MPI is actually not
+ *  required here).
+ *
  *  Compilation additionally required use of
  *  \code CPPFLAGS="-fPIC" \endcode
@@ -125,8 +152,38 @@
  *  for a debug compile you might want to use:
  *  \code
- *  ../configure -C --prefix=<path> --enable-shared BSPLINE_DEG=3 MPICC=mpicc.openmpi
- *  MPICXX=mpicxx.openmpi MPIEXEC=mpirun.openmpi CPPFLAGS="-Wall -g3 -O0 -ggdb -fPIC"
- *  --enable-mpi --with-boost-libdir=/usr/lib --with-boost=/usr --enable-fcs-solvers=vmg
+ *  ../configure \
+ *    -C \
+ *    --prefix=<path> \
+ *    --enable-shared \
+ *    BSPLINE_DEG=3 \
+ *    MPICC=mpicc.openmpi \
+ *    MPICXX=mpicxx.openmpi \
+ *    MPIEXEC=mpirun.openmpi \
+ *    CPPFLAGS="-Wall -g3 -O0 -ggdb -fPIC" \
+ *    --enable-mpi \
+ *    --with-boost-libdir=/usr/lib --with-boost=/usr \
+ *    --with-vtk=<path-to-vtk> --with-vtk-version=<vtk-version path string, i.e. -5.10> \
+ *    --enable-fcs-solvers=vmg
  *  \endcode
+ *  where we specify a recent boost and the installed VTK version from above.
+ *
+ *  \subsubsection install-prerequisites-other-levmar LevMar
+ *
+ *   We also require the levmar (http://www.ics.forth.gr/~lourakis/levmar/) which
+ *   implements a Levenberg-Marquardt for non-linear regression which is employed
+ *   for fitting empirical potentials to energies obtained from calculated
+ *   fragment energies.
+ *
+ *   Compile and install as follows
+ *   \code
+ *    cmake \
+ *      -DCMAKE_INSTALL_PREFIX:PATH=<install-path> \
+ *      -DCMAKE_C_FLAGS="-fPIC" \
+ *      ..
+ *    make
+ *    cp -f liblevmar.a <install-path>/lib
+ *    cp -f levmar.h <install-path>/include
+ *   \endcode
+ *   where we have to copy the stuff by hand as no \a install target exists.
  *
  *  \subsubsection install-prerequisites-other-mpqc MPQC
@@ -276,4 +333,4 @@
  *  from a distributed archive. This is checked for each release version.
  *
- * \date 2012-12-20
+ * \date 2013-04-09
  */
Index: tests/Python/AllActions/options.dat
===================================================================
--- tests/Python/AllActions/options.dat	(revision 57f14c9b30bd737681a0792dea763fb79e3b0be1)
+++ tests/Python/AllActions/options.dat	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
@@ -75,5 +75,7 @@
 fill-void	"water.data"
 fill-void	"water.xyz"
+fit-potential	"morse"
 forces-file	"test.forces"
+fragment-charges	"1 1"
 fragment-executable	"mpqc"
 fragment-jobs	"Job00.in"
@@ -131,4 +133,5 @@
 position	"7.283585982 3.275186040 3.535886037"
 position	"9.78 2.64 2.64"
+potential-charges	"1 1"
 radius	"20."
 random-atom-displacement	"0."
@@ -201,4 +204,5 @@
 stretch-shapes	"1. 2. 3."
 suspend-in-water	"1.0"
+take-best-of		"5"
 tesselation-radius	"5."
 time-step-zero	"0"
Index: tests/regression/Fragmentation/FitPotential/pre/angle_homology.dat
===================================================================
--- tests/regression/Fragmentation/FitPotential/pre/angle_homology.dat	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
+++ tests/regression/Fragmentation/FitPotential/pre/angle_homology.dat	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
@@ -0,0 +1,46 @@
+22 serialization::archive 9 1 0
+0 0 0 11 0 0 0 1 0
+1 0 0 2 0 0 0 1 0
+2 1 1 2
+3 8 2 1 0 0 1 0 0 0 1 0
+4 0 0 1 8 2 0 0 0 0 0 0 3 0 0 0 3 0 8.5896635844410625 9.6204232145853279 17.555668962744846 8 3 0 9.9616046521493598 9.6204232145853279 16.404825835700283 1 3 0 7.2177225167327634 9.6204232145853279 16.404825835700283 1 -76.022632770584352
+5 2 0
+6 1 1 2
+7 8 2 1 1 0
+8 1 8 2 3 0 3 0 19.928019516009087 9.6204232145853279 17.555668962744846 8 3 0 21.349093459420438 9.6204232145853279 16.465297067334806 1 3 0 18.506945572503252 9.6204232145853279 16.465297067334806 1 -76.023547665466879
+9 2 0
+10 1 1 2
+11 8 2 1 1 0
+12 1 8 2 3 0 3 0 31.266375447482627 9.6204232145853279 17.555668962744846 8 3 0 32.732802814619873 9.6204232145853279 16.527658024957912 1 3 0 29.799948080345384 9.6204232145853279 16.527658024957912 1 -76.023113326862159
+13 2 0
+14 1 1 2
+15 8 2 1 1 0
+16 1 8 2 3 0 3 0 8.5896635844410625 20.958779146039969 17.555668962744846 8 3 0 10.099554649315621 20.958779146039969 16.593798434558174 1 3 0 7.0797725195665011 20.958779146039969 16.593798434558174 1 -76.021400507773564
+17 2 0
+18 1 1 2
+19 8 2 1 1 0
+20 1 8 2 3 0 3 0 19.928019516009087 20.958779146039969 17.555668962744846 8 3 0 21.479484552632382 20.958779146039969 16.659938844158436 1 3 0 18.376554479291304 20.958779146039969 16.659938844158436 1 -76.018536676645738
+21 2 0
+22 1 1 2
+23 8 2 1 1 0
+24 1 8 2 3 0 3 0 31.266375447482627 20.958779146039969 17.555668962744846 8 3 0 32.855635003877502 20.958779146039969 16.727968979747278 1 3 0 29.677115891087755 20.958779146039969 16.727968979747278 1 -76.014724714579245
+25 2 0
+26 1 1 2
+27 8 2 1 1 0
+28 1 8 2 3 0 3 0 8.5896635844410625 32.297135077513509 17.555668962744846 8 3 0 10.212938208630357 32.297135077513509 16.799778567313275 1 3 0 6.9663889602517663 32.297135077513509 16.799778567313275 1 -76.010054441419953
+29 2 0
+30 1 1 2
+31 8 2 1 1 0
+32 1 8 2 3 0 3 0 19.928019516009087 32.297135077513509 17.555668962744846 8 3 0 21.07886264305365 32.297135077513509 16.183727895036547 1 3 0 18.777176388870036 32.297135077513509 16.183727895036547 1 -76.003229442345031
+33 2 0
+34 1 1 2
+35 8 2 1 1 0
+36 1 8 2 3 0 3 0 31.266375447482627 32.297135077513509 17.555668962744846 8 3 0 32.475800080173137 32.297135077513509 16.234750496728175 1 3 0 30.056950814792117 32.297135077513509 16.234750496728175 1 -76.010564187565677
+37 2 0
+38 1 1 2
+39 8 2 1 1 0
+40 1 8 2 3 0 3 0 8.5896635844410625 9.6204232145853279 28.894024894293974 8 3 0 9.8557799967889395 9.6204232145853279 27.627908481946093 1 3 0 7.3235471720931828 9.6204232145853279 27.627908481946093 1 -76.016246779376232
+41 2 0
+42 1 1 2
+43 8 2 1 1 0
+44 1 8 2 3 0 3 0 19.928019516009087 9.6204232145853279 28.894024894293974 8 3 0 21.248937982025755 9.6204232145853279 27.684600261603464 1 3 0 18.607101049897931 9.6204232145853279 27.684600261603464 1 -76.020252697645645
Index: tests/regression/Fragmentation/FitPotential/pre/length_homology.dat
===================================================================
--- tests/regression/Fragmentation/FitPotential/pre/length_homology.dat	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
+++ tests/regression/Fragmentation/FitPotential/pre/length_homology.dat	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
@@ -0,0 +1,47 @@
+22 serialization::archive 9 1 0
+0 0 0 11 0 0 0 1 0
+1 0 0 2 0 0 0 1 0
+2 1 1 2
+3 8 2 1 0 0 1 0 0 0 1 0
+4 0 0 1 8 2 0 0 0 0 0 0 3 0 0 0 3 0 19.643930708933407 9.6204232145853279 17.304850786073761 8 3 0 20.711625892480502 9.6204232145853279 16.492268610984823 1 3 0 18.574345799435534 9.6204232145853279 16.492268610984823 1 -75.802065322141132
+5 2 0
+6 1 1 2
+7 8 2 1 1 0
+8 1 8 2 3 0 3 0 31.052206501984369 9.6204232145853279 17.359652839742548 8 3 0 32.191711273097461 9.6204232145853279 16.492268610984823 1 3 0 29.912701730871277 9.6204232145853279 16.492268610984823 1 -75.900390796104375
+9 2 0
+10 1 1 2
+11 8 2 1 1 0
+12 1 8 2 3 0 3 0 8.4473042266410818 20.958779146039969 17.414454893411339 8 3 0 9.6586185853201716 20.958779146039969 16.492268610984823 1 3 0 7.2359898679619921 20.958779146039969 16.492268610984823 1 -75.963836597121713
+13 2 0
+14 1 1 2
+15 8 2 1 1 0
+16 1 8 2 3 0 3 0 19.857469745642828 20.958779146039969 17.469256947080126 8 3 0 21.138703965899335 20.958779146039969 16.492268610984823 1 3 0 18.574345799435534 20.958779146039969 16.492268610984823 1 -76.000835395147234
+17 2 0
+18 1 1 2
+19 8 2 1 1 0
+20 1 8 2 3 0 3 0 31.265745538693785 20.958779146039969 17.522169274760337 8 3 0 32.620679072504871 20.958779146039969 16.492268610984823 1 3 0 29.912701730871277 20.958779146039969 16.492268610984823 1 -76.018998365367352
+21 2 0
+22 1 1 2
+23 8 2 1 1 0
+24 1 8 2 3 0 3 0 8.6608432633505004 32.297135077513509 17.576971328429124 8 3 0 10.085696658739007 32.297135077513509 16.492268610984823 1 3 0 7.2359898679619921 32.297135077513509 16.492268610984823 1 -76.023565812196225
+25 2 0
+26 1 1 2
+27 8 2 1 1 0
+28 1 8 2 3 0 3 0 20.071008782352244 32.297135077513509 17.631773382097915 8 3 0 21.565782039318172 32.297135077513509 16.492268610984823 1 3 0 18.574345799435534 32.297135077513509 16.492268610984823 1 -76.018267496089152
+29 2 0
+30 1 1 2
+31 8 2 1 1 0
+32 1 8 2 3 0 3 0 31.479284575403202 32.297135077513509 17.684685709778126 8 3 0 33.047757145923711 32.297135077513509 16.492268610984823 1 3 0 29.912701730871277 32.297135077513509 16.492268610984823 1 -76.005974295644549
+33 2 0
+34 1 1 2
+35 8 2 1 1 0
+36 1 8 2 3 0 3 0 8.8743823000599189 9.6204232145853279 29.077843694863763 8 3 0 10.512774732157846 9.6204232145853279 27.830624542401672 1 3 0 7.2359898679619921 9.6204232145853279 27.830624542401672 1 -75.988686025497699
+37 2 0
+38 1 1 2
+39 8 2 1 1 0
+40 1 8 2 3 0 3 0 20.284547819061661 9.6204232145853279 29.13264574853255 8 3 0 21.994749838725586 9.6204232145853279 27.830624542401672 1 3 0 18.574345799435534 9.6204232145853279 27.830624542401672 1 -75.967785084848572
+41 2 0
+42 1 2 2
+43 8 2 1 2 0
+44 1 1 1
+45 1 8 2 3 0 3 0 8.2337651899316633 9.6204232145853279 17.251938458393553 8 3 0 9.2315405119013345 9.6204232145853279 16.492268610984823 1 3 0 7.2359898679619921 9.6204232145853279 16.492268610984823 1 -75.657620232219088
Index: tests/regression/Fragmentation/FitPotential/testsuite-fragmentation-fit-potential.at
===================================================================
--- tests/regression/Fragmentation/FitPotential/testsuite-fragmentation-fit-potential.at	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
+++ tests/regression/Fragmentation/FitPotential/testsuite-fragmentation-fit-potential.at	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
@@ -0,0 +1,48 @@
+#
+#    MoleCuilder - creates and alters molecular systems
+#    Copyright (C) 2013 University of Bonn
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation, either version 3 of the License, or
+#    (at your option) any later version.
+#
+#    This program 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 General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+### fit some potentials
+
+AT_SETUP([Fragmentation - Fit morse potential to water])
+AT_KEYWORDS([fragmentation fit-potential morse])
+AT_SKIP_IF([../../molecuilder --fit-potential; if test ! $? -eq 0; then /bin/true;fi])
+
+file=length_homology.dat
+AT_CHECK([/bin/cp -f ${abs_top_srcdir}/tests/regression/Fragmentation/FitPotential/pre/$file $file], 0)
+AT_CHECK([chmod u+w $file], 0, [ignore], [ignore])
+AT_CHECK([../../molecuilder --fit-potential "morse" --homology-file $file --potential-charges 8 1 --fragment-charges 1 8 1 --take-best-of 5], 0, [stdout], [ignore])
+# check that L_2 error is below 1e-6
+AT_CHECK([grep "Best parameters with L2 error" stdout | awk '{if ($8 > 1e-6) exit 1}'], 0, [ignore], [ignore])
+# check parameters to printed precision
+AT_CHECK([grep "morse:.*particle_type1=8,.*particle_type2=1,.*spring_constant=1.2652,.*equilibrium_distance=1.78095,.*dissociation_energy=0.401285;" stdout], 0, [ignore], [ignore])
+
+AT_CLEANUP
+
+AT_SETUP([Fragmentation - Fit harmonic_angle potential to water])
+AT_KEYWORDS([fragmentation fit-potential harmonic_angle])
+AT_SKIP_IF([../../molecuilder --fit-potential; if test ! $? -eq 0; then /bin/true;fi])
+
+file=angle_homology.dat
+AT_CHECK([/bin/cp -f ${abs_top_srcdir}/tests/regression/Fragmentation/FitPotential/pre/$file $file], 0)
+AT_CHECK([chmod u+w $file], 0, [ignore], [ignore])
+AT_CHECK([../../molecuilder --fit-potential "harmonic_angle" --homology-file $file --potential-charges 1 8 1 --fragment-charges 1 8 1 --take-best-of 5], 0, [stdout], [ignore])
+# check that L_2 error is below 1e-6
+AT_CHECK([grep "||e||_2:" stdout | awk '{if ($7 > 1e-6) exit 1}'], 0, [ignore], [ignore])
+# check parameters to printed precision
+AT_CHECK([grep "harmonic_angle:.*particle_type1=1,.*particle_type2=8,.*particle_type3=1,.*spring_constant=0.100497,.*equilibrium_distance=-0.274675;" stdout], 0, [ignore], [ignore])
+
+AT_CLEANUP
Index: tests/regression/Fragmentation/testsuite-fragmentation.at
===================================================================
--- tests/regression/Fragmentation/testsuite-fragmentation.at	(revision 57f14c9b30bd737681a0792dea763fb79e3b0be1)
+++ tests/regression/Fragmentation/testsuite-fragmentation.at	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
@@ -29,2 +29,5 @@
 # check storing saturated fragment
 m4_include([Fragmentation/StoreSaturatedFragment/testsuite-fragmentation-store-saturated-fragment.at])
+
+# fitting potential to fragment results
+m4_include([Fragmentation/FitPotential/testsuite-fragmentation-fit-potential.at])
Index: tests/regression/Makefile.am
===================================================================
--- tests/regression/Makefile.am	(revision 57f14c9b30bd737681a0792dea763fb79e3b0be1)
+++ tests/regression/Makefile.am	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
@@ -73,4 +73,5 @@
 	$(srcdir)/Fragmentation/testsuite-fragmentation.at \
 	$(srcdir)/Fragmentation/AnalyseFragmentationResults/testsuite-fragmentation-analyse-fragment-results.at \
+	$(srcdir)/Fragmentation/FitPotential/testsuite-fragmentation-fit-potential.at \
 	$(srcdir)/Fragmentation/FragmentMolecule/testsuite-fragmentation-fragment-molecule.at \
 	$(srcdir)/Fragmentation/FragmentMolecule-MaxOrder/testsuite-fragmentation-fragment-molecule-maxorder.at \
Index: tests/regression/testsuite.at
===================================================================
--- tests/regression/testsuite.at	(revision 57f14c9b30bd737681a0792dea763fb79e3b0be1)
+++ tests/regression/testsuite.at	(revision 48d20d12c40193473e911ec536adb1dfb3d14bff)
@@ -22,5 +22,5 @@
 
 AT_INIT([Molecular Builder])
-AT_TESTED(diff grep egrep fgrep)
+AT_TESTED(diff grep egrep fgrep awk)
 
 # makes functions in CheckCommand.sh available within the tests
