Index: src/Actions/FragmentationAction/FitPotentialAction.cpp
===================================================================
--- src/Actions/FragmentationAction/FitPotentialAction.cpp	(revision 7c10913cd7643f0bb610d97273b66628c8faa10d)
+++ src/Actions/FragmentationAction/FitPotentialAction.cpp	(revision baccf631d831c6d19bca920b5838a840eebd19f5)
@@ -60,5 +60,9 @@
 #include "FunctionApproximation/TrainingData.hpp"
 #include "FunctionApproximation/writeDistanceEnergyTable.hpp"
+#include "Potentials/CompoundPotential.hpp"
+#include "Potentials/PotentialDeserializer.hpp"
 #include "Potentials/PotentialFactory.hpp"
+#include "Potentials/PotentialRegistry.hpp"
+#include "Potentials/PotentialSerializer.hpp"
 #include "Potentials/SerializablePotential.hpp"
 
@@ -109,11 +113,4 @@
 
 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;
@@ -122,4 +119,51 @@
     std::transform(fragment.begin(), fragment.end(), std::back_inserter(fragmentnumbers),
         boost::bind(&element::getAtomicNumber, _1));
+  }
+
+  // either charges and a potential is specified or a file
+  if (boost::filesystem::exists(params.potential_file.get())) {
+    std::ifstream returnstream(params.potential_file.get().string().c_str());
+    if (returnstream.good()) {
+      PotentialDeserializer deserialize(returnstream);
+      deserialize();
+    } else {
+      ELOG(0, "Failed to parse from " << params.potential_file.get().string() << ".");
+      return Action::failure;
+    }
+    returnstream.close();
+
+    LOG(0, "STATUS: I'm training now a set of potentials parsed from "
+        << params.potential_file.get().string() << " on a fragment "
+        << fragmentnumbers << " on data from " << params.homology_file.get() << ".");
+
+  } else {
+    if (params.charges.get().empty()) {
+      ELOG(1, "Neither charges nor potential file given!");
+      return Action::failure;
+    } else {
+      // 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));
+      }
+
+      LOG(0, "STATUS: I'm training now a " << params.potentialtype.get()
+          << " potential on charges " << chargenumbers << " on data from "
+          << params.homology_file.get() << ".");
+
+      // register desired potential and an additional constant one
+      EmpiricalPotential *potential =
+          PotentialFactory::getInstance().createInstance(
+              params.potentialtype.get(),
+              chargenumbers);
+      PotentialRegistry::getInstance().registerInstance(potential);
+      EmpiricalPotential *constant =
+          PotentialFactory::getInstance().createInstance(
+              std::string("constant"),
+              SerializablePotential::ParticleTypes_t());
+      PotentialRegistry::getInstance().registerInstance(constant);
+    }
   }
 
@@ -149,121 +193,119 @@
   }
 
-  LOG(0, "STATUS: I'm training now a " << params.potentialtype.get() << " potential on charges "
-      << chargenumbers << " on data from " << params.homology_file.get() << ".");
+  // 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 << ".");
+  } else {
+    ELOG(1, "Specific fragment " << fragmentnumbers << " not found in homologies!");
+    return Action::failure;
+  }
+
+  // fit potential
+  FunctionModel *model = new CompoundPotential(graph);
+  ASSERT( model != NULL,
+      "FragmentationFitPotentialAction::performCall() - model is NULL.");
 
   /******************** 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() << ".");
+    // 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 << ").");
         }
       }
-      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.");
+
+      // 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 << ".");
+
+    // print fitted potentials
+    std::stringstream potentials;
+    PotentialSerializer serialize(potentials);
+    serialize();
+    LOG(1, "STATUS: Resulting parameters are " << std::endl << potentials.str());
   }
   delete model;
Index: src/Actions/FragmentationAction/FitPotentialAction.def
===================================================================
--- src/Actions/FragmentationAction/FitPotentialAction.def	(revision 7c10913cd7643f0bb610d97273b66628c8faa10d)
+++ src/Actions/FragmentationAction/FitPotentialAction.def	(revision baccf631d831c6d19bca920b5838a840eebd19f5)
@@ -11,4 +11,5 @@
 #include <vector>
 
+#include "Parameters/Validators/DummyValidator.hpp"
 #include "Parameters/Validators/RangeValidator.hpp"
 #include "Parameters/Validators/STLVectorValidator.hpp"
@@ -20,13 +21,14 @@
 // 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 paramtypes (boost::filesystem::path)(std::string)(boost::filesystem::path)(std::vector<const element *>)(std::vector<const element *>)(unsigned int)
+#define paramtokens ("homology-file")("fit-potential")("potential-file")("potential-charges")("fragment-charges")("take-best-of")
+#define paramdescriptions ("homology file to parse")("potential type to fit")("potential file specifying multiple potentials 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)(NOPARAM_DEFAULT)(PARAM_DEFAULT(3))
+#define paramreferences (homology_file)(potentialtype)(potential_file)(charges)(fragment)(best_of_howmany)
 #define paramvalids \
 (FilePresentValidator()) \
 (PotentialTypeValidator()) \
-(STLVectorValidator< std::vector<const element *> >(1,99, ElementValidator())) \
+(DummyValidator<boost::filesystem::path>()) \
+(STLVectorValidator< std::vector<const element *> >(0,99, ElementValidator())) \
 (STLVectorValidator< std::vector<const element *> >(1,99, ElementValidator())) \
 (RangeValidator< unsigned int>(1,99))
Index: tests/Python/AllActions/options.dat
===================================================================
--- tests/Python/AllActions/options.dat	(revision 7c10913cd7643f0bb610d97273b66628c8faa10d)
+++ tests/Python/AllActions/options.dat	(revision baccf631d831c6d19bca920b5838a840eebd19f5)
@@ -134,4 +134,5 @@
 position	"9.78 2.64 2.64"
 potential-charges	"1 1"
+potential-file	"test.potentials"
 radius	"20."
 random-atom-displacement	"0."
Index: tests/regression/Fragmentation/FitPotential/testsuite-fragmentation-fit-potential.at
===================================================================
--- tests/regression/Fragmentation/FitPotential/testsuite-fragmentation-fit-potential.at	(revision 7c10913cd7643f0bb610d97273b66628c8faa10d)
+++ tests/regression/Fragmentation/FitPotential/testsuite-fragmentation-fit-potential.at	(revision baccf631d831c6d19bca920b5838a840eebd19f5)
@@ -21,5 +21,4 @@
 AT_SETUP([Fragmentation - Fit morse potential to water])
 AT_KEYWORDS([fragmentation fit-potential morse])
-AT_XFAIL_IF([/bin/true])
 AT_SKIP_IF([../../molecuilder --help --actionname fit-potential; if test $? -eq 5; then /bin/true; else /bin/false; fi])
 
@@ -31,5 +30,5 @@
 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_CHECK([grep "morse:.*particle_type1=8,.*particle_type2=1,.*spring_constant=1.27.*,.*equilibrium_distance=1.78.*,.*dissociation_energy=0.19.*;" stdout], 0, [ignore], [ignore])
 
 AT_CLEANUP
@@ -37,5 +36,4 @@
 AT_SETUP([Fragmentation - Fit harmonic_angle potential to water])
 AT_KEYWORDS([fragmentation fit-potential harmonic_angle])
-AT_XFAIL_IF([/bin/true])
 AT_SKIP_IF([../../molecuilder --help --actionname fit-potential; if test $? -eq 5; then /bin/true; else /bin/false; fi])
 
@@ -47,5 +45,5 @@
 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_CHECK([grep "harmonic_angle:.*particle_type1=1,.*particle_type2=8,.*particle_type3=1,.*spring_constant=0.10.*,.*equilibrium_distance=-0.27.*;" stdout], 0, [ignore], [ignore])
 
 AT_CLEANUP
