Index: src/LevMartester.cpp
===================================================================
--- src/LevMartester.cpp	(revision d76ce74b92b36c40ccdeb64d1b9aca242a189bcb)
+++ src/LevMartester.cpp	(revision 3e236eed34eca516200fd648209baf70fdf4a34b)
@@ -69,4 +69,6 @@
 #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"
@@ -172,4 +174,6 @@
       ("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< FunctionModel::charges_t >()->multitoken(), "charges specifying the fragment")
   ;
 
@@ -183,4 +187,5 @@
   }
 
+  // homology-file
   boost::filesystem::path homology_file;
   if (vm.count("homology-file")) {
@@ -188,6 +193,27 @@
     LOG(1, "INFO: Parsing " << homology_file.string() << ".");
   } else {
-    LOG(0, "homology-file level was not set.");
-  }
+    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
+  FunctionModel::charges_t charges;
+  if (vm.count("charges")) {
+    charges = vm["charges"].as< FunctionModel::charges_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)) {
@@ -197,9 +223,11 @@
       ia >> homologies;
     } else {
-      ELOG(2, "Failed to parse from " << homology_file.string() << ".");
+      ELOG(0, "Failed to parse from " << homology_file.string() << ".");
+      return 1;
     }
     returnstream.close();
   } else {
     ELOG(0, homology_file << " does not exist.");
+    return 1;
   }
 
@@ -212,33 +240,35 @@
   }
 
-  /******************** Angle TRAINING ********************/
-  FunctionModel::parameters_t angleparams(PairPotential_Angle::MAXPARAMS, 0.);
+  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 = getFirstGraphwithTimesSpecificElement(homologies,8,1);
     if (graph != HomologyGraph()) {
-      LOG(1, "First representative graph containing three saturated carbons is " << graph << ".");
+      LOG(1, "First representative graph containing charges is " << graph << ".");
 
       // Afterwards we go through all of this type and gather the distance and the energy value
-      PairPotential_Angle::ParticleTypes_t types =
-            boost::assign::list_of<PairPotential_Angle::ParticleType_t>
-            (8)(1)(1)
-          ;
-      PairPotential_Angle angle(types);
-      Fragment::charges_t h2o;
-      h2o += 8,1,1;
-      TrainingData AngleData(angle.getFragmentSpecificExtractor(h2o));
-      AngleData(homologies.getHomologousGraphs(graph));
-      LOG(1, "INFO: I gathered the following training data: " << AngleData);
+      TrainingData data(model->getFragmentSpecificExtractor(charges));
+      data(homologies.getHomologousGraphs(graph));
+      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
-      FunctionModel &model = angle;
-      FunctionApproximation approximator(AngleData, model);
-      if (model.isBoxConstraint() && approximator.checkParameterDerivatives()) {
+      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(AngleData);
-        LOG(0, "INFO: Initial parameters are " << angle.getParameters() << ".");
+        model->setParametersToRandomInitialValues(data);
+        LOG(0, "INFO: Initial parameters are " << model->getParameters() << ".");
         approximator(FunctionApproximation::ParameterDerivative);
       } else {
@@ -247,98 +277,15 @@
       }
 
-      LOG(0, "RESULT: " << angle << ".");
-
-      angleparams = model.getParameters();
+//      LOG(0, "RESULT: " << *model << ".");
+//
+      params = model->getParameters();
+
     }
   }
-
-  /******************** MORSE TRAINING ********************/
-  FunctionModel::parameters_t morseparams(PairPotential_Morse::MAXPARAMS, 0.);
-  {
-    // then we ought to pick the right HomologyGraph ...
-    const HomologyGraph graph = getFirstGraphwithTimesSpecificElement(homologies,8,1);
-    if (graph != HomologyGraph()) {
-      LOG(1, "First representative graph containing two saturated carbons is " << graph << ".");
-
-      // Afterwards we go through all of this type and gather the distance and the energy value
-      Fragment::charges_t h2o;
-      h2o += 8,1;
-      PairPotential_Morse::ParticleTypes_t types =
-            boost::assign::list_of<PairPotential_Morse::ParticleType_t>
-            (8)(1)
-          ;
-      PairPotential_Morse morse(types);
-      TrainingData MorseData(morse.getFragmentSpecificExtractor(h2o));
-      MorseData(homologies.getHomologousGraphs(graph));
-      LOG(1, "INFO: I gathered the following training data: " << MorseData);
-      // NOTICE that distance are in bohrradi as they come from MPQC!
-
-      // now perform the function approximation by optimizing the model function
-      FunctionModel &model = morse;
-      FunctionApproximation approximator(MorseData, model); // we only give CC distance, hence 1 input dim
-      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(MorseData);
-        LOG(0, "INFO: Initial parameters are " << morse.getParameters() << ".");
-        approximator(FunctionApproximation::ParameterDerivative);
-      } else {
-        ELOG(0, "We require parameter derivatives for a box constraint minimization.");
-        return 1;
-      }
-
-      LOG(0, "RESULT: " << morse << ".");
-
-      morseparams = model.getParameters();
-    }
-  }
-
-  /******************* SATURATION TRAINING *******************/
-  FunctionModel::parameters_t params(SaturationPotential::MAXPARAMS, 0.);
-  {
-    // then we ought to pick the right HomologyGraph ...
-    const HomologyGraph graph = getFirstGraphwithTimesSpecificElement(homologies,8,1);
-    if (graph != HomologyGraph()) {
-      LOG(1, "First representative graph containing one saturated carbon is " << graph << ".");
-
-      // Afterwards we go through all of this type and gather the distance and the energy value
-      Fragment::charges_t h2o;
-      h2o += 8,1,1;
-      SaturationPotential::ParticleTypes_t types =
-            boost::assign::list_of<SaturationPotential::ParticleType_t>
-            (8)(1)
-          ;
-      SaturationPotential saturation(types);
-      TrainingData TersoffData(saturation.getFragmentSpecificExtractor(h2o));
-      boost::function< std::vector<FunctionModel::arguments_t>(const argument_t &, const double)> triplefunction =
-          boost::bind(&getTripleFromArgument, boost::cref(TersoffData.getTrainingInputs()), _1, _2);
-      saturation.setTriplefunction(triplefunction);
-
-      TersoffData( homologies.getHomologousGraphs(graph) );
-      LOG(1, "INFO: I gathered the following training data: " << TersoffData);
-      // NOTICE that distance are in bohrradi as they come from MPQC!
-
-      // now perform the function approximation by optimizing the model function
-      FunctionModel &model = saturation;
-      FunctionApproximation approximator(TersoffData, model); // CH4 has 5 atoms, hence 5*4/2 distances
-      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(TersoffData);
-        approximator(FunctionApproximation::ParameterDerivative);
-      } else {
-        ELOG(0, "We require parameter derivatives for a box constraint minimization.");
-        return 1;
-      }
-
-      LOG(0, "RESULT: " << saturation << ".");
-
-      // check L2 and Lmax error against training set
-      LOG(1, "INFO: L2sum = " << TersoffData.getL2Error(model)
-          << ", LMax = " << TersoffData.getLMaxError(model) << ".");
-    }
-
-  }
+  delete model;
+  // remove static instances
+  PotentialFactory::purgeInstance();
 
   return 0;
 }
+
