Index: src/Actions/FragmentationAction/FragmentationAutomationAction.cpp
===================================================================
--- src/Actions/FragmentationAction/FragmentationAutomationAction.cpp	(revision 34340193276773ab7abaeb6bbee9133e14de0dfb)
+++ src/Actions/FragmentationAction/FragmentationAutomationAction.cpp	(revision c44322dead4b532287ef5f5ad002e748690ccd77)
@@ -45,10 +45,8 @@
 #include "CodePatterns/Info.hpp"
 #include "CodePatterns/Log.hpp"
-#include "JobMarket/Controller/FragmentController.hpp"
 #include "JobMarket/Jobs/FragmentJob.hpp"
 
-#include "Atom/atom.hpp"
-#include "Box.hpp"
-#include "Element/element.hpp"
+#include "Fragmentation/Automation/MPQCFragmentController.hpp"
+#include "Fragmentation/Automation/VMGFragmentController.hpp"
 #include "Fragmentation/EnergyMatrix.hpp"
 #include "Fragmentation/ForceMatrix.hpp"
@@ -63,5 +61,4 @@
 #include "Fragmentation/Summation/SumUpPerLevel.hpp"
 #include "Fragmentation/Summation/OrthogonalFullSummator.hpp"
-#include "Fragmentation/Summation/OrthogonalSummation.hpp"
 #include "Fragmentation/Summation/writeTable.hpp"
 #include "Graph/DepthFirstSearchAnalysis.hpp"
@@ -71,5 +68,4 @@
 #include "Jobs/MPQCData_printKeyNames.hpp"
 #include "Jobs/Grid/SamplingGrid.hpp"
-#include "LinearAlgebra/RealSpaceMatrix.hpp"
 #ifdef HAVE_VMG
 #include "Jobs/VMGJob.hpp"
@@ -79,5 +75,4 @@
 #include "Jobs/VMGData_printKeyNames.hpp"
 #endif
-#include "molecule.hpp"
 #include "World.hpp"
 
@@ -103,36 +98,4 @@
 {
   return NULL;
-}
-
-const int LEVEL = 5;
-
-/** Creates a MPQCCommandJob with argument \a filename.
- *
- * @param jobs created job is added to this vector
- * @param command mpqc command to execute
- * @param filename filename being argument to job
- * @param nextid id for this job
- */
-void parsejob(
-    std::vector<FragmentJob::ptr> &jobs,
-    const std::string &command,
-    const std::string &filename,
-    const JobId_t nextid)
-{
-  std::ifstream file;
-  file.open(filename.c_str());
-  ASSERT( file.good(), "parsejob() - file "+filename+" does not exist.");
-  std::string output((std::istreambuf_iterator<char>(file)),
-      std::istreambuf_iterator<char>());
-  double begin[NDIM] = { 0., 0., 0. };
-  const RealSpaceMatrix& M = World::getInstance().getDomain().getM();
-  const double size = M.at(0,0);
-  ASSERT( M.determinant() == size*size*size,
-      "parsejob() - current domain matrix "+toString(M)+" is not cubic.");
-  const int level = LEVEL;
-  FragmentJob::ptr testJob( new MPQCJob(nextid, output, begin, size, level) );
-  jobs.push_back(testJob);
-  file.close();
-  LOG(1, "INFO: Added MPQCCommandJob from file "+filename+".");
 }
 
@@ -166,33 +129,4 @@
 }
 
-/** Extracts MPQCData from received vector of FragmentResults.
- *
- * @param results results to extract MPQCData from
- * @param fragmentData on return array filled with extracted MPQCData
- */
-template <typename T>
-void ConvertFragmentResultTo(
-    const std::vector<FragmentResult::ptr> &results,
-    std::map<JobId_t, T> &fragmentData)
-{
-  // extract results
-  fragmentData.clear();
-
-  LOG(2, "DEBUG: Parsing now through " << results.size() << " results.");
-  for (std::vector<FragmentResult::ptr>::const_iterator iter = results.begin();
-      iter != results.end(); ++iter) {
-    //LOG(1, "RESULT: job #"+toString((*iter)->getId())+": "+toString((*iter)->result));
-    T extractedData;
-    std::stringstream inputstream((*iter)->result);
-    LOG(2, "DEBUG: First 50 characters FragmentResult's string: "+(*iter)->result.substr(0, 50));
-    boost::archive::text_iarchive ia(inputstream);
-    ia >> extractedData;
-    LOG(1, "INFO: extracted data is " << extractedData << ".");
-    fragmentData.insert( std::make_pair( (*iter)->getId(), extractedData) );
-  }
-
-  ASSERT( results.size() == fragmentData.size(),
-      "ConvertFragmentResultTo() - the number of extracted data differs from the number of results.");
-}
 
 /** Creates a lookup from FragmentJob::id to the true fragment  number.
@@ -653,123 +587,12 @@
 
 
-void RunService(
-    boost::asio::io_service &io_service,
-    std::string message)
-{
-  message = std::string("io_service: ") + message;
-  io_service.reset();
-  Info info(message.c_str());
-  io_service.run();
-}
-
-void requestIds(
-    FragmentController &controller,
-    const FragmentationFragmentationAutomationAction::FragmentationFragmentationAutomationParameters &params,
-    const size_t numberjobs)
-{
-  controller.requestIds(params.host.get(), params.port.get(), numberjobs);
-}
-
-bool createJobsFromFiles(
-    FragmentController &controller,
-    const FragmentationFragmentationAutomationAction::FragmentationFragmentationAutomationParameters &params,
-    const std::vector< boost::filesystem::path > &jobfiles)
-{
-  std::vector<FragmentJob::ptr> jobs;
-  for (std::vector< boost::filesystem::path >::const_iterator iter = jobfiles.begin();
-      iter != jobfiles .end(); ++iter) {
-    const std::string &filename = (*iter).string();
-    if (boost::filesystem::exists(filename)) {
-      const JobId_t next_id = controller.getAvailableId();
-      LOG(1, "INFO: Creating MPQCCommandJob with filename'"
-          +filename+"', and id "+toString(next_id)+".");
-      parsejob(jobs, params.executable.get().string(), filename, next_id);
-    } else {
-      ELOG(1, "Fragment job "+filename+" does not exist.");
-      return false;
-    }
-  }
-  controller.addJobs(jobs);
-  controller.sendJobs(params.host.get(), params.port.get());
-  return true;
-}
-
-#ifdef HAVE_VMG
-bool createLongRangeJobs(
-    FragmentController &controller,
-    const FragmentationFragmentationAutomationAction::FragmentationFragmentationAutomationParameters &params,
-    const std::map<JobId_t, MPQCData> &fragmentData,
-    const SamplingGrid &full_sampled_grid,
-    const Fragment &full_fragment)
-{
-  std::vector<FragmentJob::ptr> jobs;
-  // add one job for each fragment as the short-range correction which we need
-  // to subtract from the obtained full potential to get the long-range part only
-  for (std::map<JobId_t, MPQCData>::const_iterator iter = fragmentData.begin();
-      iter != fragmentData.end(); ++iter) {
-    const JobId_t next_id = controller.getAvailableId();
-    LOG(1, "INFO: Creating VMGJob with " << iter->second.sampled_grid.sampled_grid.size()
-        << " gridpoints and " << iter->second.charges.size() << " particle charges.");
-    FragmentJob::ptr testJob(
-        new VMGJob(next_id, iter->second.sampled_grid, iter->second.positions, iter->second.charges) );
-    jobs.push_back(testJob);
-  }
-
-  {
-    const World::AtomComposite &atoms = World::getInstance().getAllAtoms();
-    std::vector< std::vector<double> > positions;
-    positions.reserve(atoms.size());
-    std::vector<double> charges;
-    charges.reserve(atoms.size());
-    std::vector<double> position(3, 0.);
-    for (World::AtomComposite::const_iterator iter = atoms.begin();
-        iter != atoms.end(); ++iter) {
-      const Vector &pos = (*iter)->getPosition();
-      for (size_t i=0;i<3;++i) position[i] = pos[i];
-      positions.push_back(position);
-      charges.push_back((double)((*iter)->getElement().getAtomicNumber()));
-    }
-    const JobId_t next_id = controller.getAvailableId();
-    LOG(1, "INFO: Creating full VMGJob with " << full_sampled_grid.sampled_grid.size()
-        << " gridpoints and " << charges.size() << " particle charges.");
-    FragmentJob::ptr testJob(
-        new VMGJob(next_id, full_sampled_grid, positions, charges) );
-    jobs.push_back(testJob);
-  }
-
-  // then send jobs to controller
-  controller.addJobs(jobs);
-  controller.sendJobs(params.host.get(), params.port.get());
-  return true;
-}
-#endif
-
-void WaitforResults(
-    boost::asio::io_service &io_service,
-    FragmentController &controller,
-    const FragmentationFragmentationAutomationAction::FragmentationFragmentationAutomationParameters &params,
-    const size_t NoExpectedResults
-    )
-{
-  size_t NoCalculatedResults = 0;
-  while (NoCalculatedResults != NoExpectedResults) {
-    // wait a bit
-    boost::asio::deadline_timer timer(io_service);
-    timer.expires_from_now(boost::posix_time::milliseconds(500));
-    timer.wait();
-    // then request status
-    controller.checkResults(params.host.get(), params.port.get());
-    RunService(io_service, "Checking on results");
-
-    const std::pair<size_t, size_t> JobStatus = controller.getJobStatus();
-    LOG(1, "INFO: #" << JobStatus.first << " are waiting in the queue and #" << JobStatus.second << " jobs are calculated so far.");
-    NoCalculatedResults = JobStatus.second;
-  }
-}
-
-
 Action::state_ptr FragmentationFragmentationAutomationAction::performCall() {
   boost::asio::io_service io_service;
-  FragmentController controller(io_service);
+  MPQCFragmentController mpqccontroller(io_service);
+  mpqccontroller.setHost(params.host.get());
+  mpqccontroller.setPort(params.port.get());
+  VMGFragmentController vmgcontroller(io_service);
+  vmgcontroller.setHost(params.host.get());
+  vmgcontroller.setPort(params.port.get());
 
   // TODO: Have io_service run in second thread and merge with current again eventually
@@ -777,19 +600,14 @@
   // Phase One: obtain ids
   std::vector< boost::filesystem::path > jobfiles = params.jobfiles.get();
-  requestIds(controller, params, jobfiles.size());
-  RunService(io_service, "Requesting ids");
+  mpqccontroller.requestIds(jobfiles.size());
 
   // Phase Two: create and add MPQCJobs
-  if (!createJobsFromFiles(controller, params, jobfiles))
+  if (!mpqccontroller.addJobsFromFiles(params.executable.get().string(), jobfiles))
     return Action::failure;
-  RunService(io_service, "Adding MPQCJobs");
 
   // Phase Three: calculate result
-  WaitforResults(io_service, controller, params, jobfiles.size());
-  controller.receiveResults(params.host.get(), params.port.get());
-  RunService(io_service, "Requesting short-range results");
-  std::vector<FragmentResult::ptr> MPQCresults = controller.getReceivedResults();
+  mpqccontroller.waitforResults(jobfiles.size());
   std::map<JobId_t, MPQCData> fragmentData;
-  ConvertFragmentResultTo<MPQCData>(MPQCresults, fragmentData);
+  mpqccontroller.getResults(fragmentData);
 
 #ifdef HAVE_VMG
@@ -797,10 +615,4 @@
   ASSERT( World::getInstance().getAllAtoms().size() != 0,
       "FragmentationFragmentationAutomationAction::performCall() - please load the full molecule into the World before.");
-
-  // create a vector of all job ids
-  std::vector<JobId_t> jobids(MPQCresults.size(), JobId::IllegalJob);
-  std::transform(MPQCresults.begin(), MPQCresults.end(), jobids.begin(),
-      boost::bind(&FragmentResult::getId,
-          boost::bind(&FragmentResult::ptr::operator->, _1)));
 
   // obtain combined charge density
@@ -815,22 +627,18 @@
 
   // Phase Four: obtain more ids
-  requestIds(controller, params, fragmentData.size()+1);
-  RunService(io_service, "Requesting ids");
+  vmgcontroller.requestIds(fragmentData.size()+1);
 
   // Phase Five: create VMGJobs
-  if (!createLongRangeJobs(controller, params, fragmentData, full_sample, full_fragment))
+  if (!vmgcontroller.createLongRangeJobs(fragmentData, full_sample, full_fragment))
     return Action::failure;
-  RunService(io_service, "Adding VMGJobs");
 
   // Phase Six: calculate result
-  WaitforResults(io_service, controller, params, fragmentData.size()+1);
-  controller.receiveResults(params.host.get(), params.port.get());
-  RunService(io_service, "Requesting long-range results");
-  std::vector<FragmentResult::ptr> VMGresults = controller.getReceivedResults();
-  ASSERT( MPQCresults.size()+1 == VMGresults.size(),
-      "FragmentationFragmentationAutomationAction::performCall() - number of MPQCresultd and VMGresults don't match.");
-
+  vmgcontroller.waitforResults(fragmentData.size()+1);
   std::map<JobId_t, VMGData> longrangeData;
-  ConvertFragmentResultTo<VMGData>(VMGresults, longrangeData);
+  vmgcontroller.getResults(longrangeData);
+  ASSERT( fragmentData.size()+1 == longrangeData.size(),
+      "FragmentationFragmentationAutomationAction::performCall() - number of MPQCresults+1 "
+      +toString(fragmentData.size()+1)+" and VMGresults "+toString(longrangeData.size())+" don't match.");
+
   // remove full solution from map (must be highest id), has to be treated extra
   VMGData fullsolutionData = (--longrangeData.end())->second;
@@ -860,5 +668,5 @@
   }
 #endif
-  size_t Exitflag = controller.getExitflag();
+  size_t Exitflag = vmgcontroller.getExitflag() + mpqccontroller.getExitflag();
 
   return (Exitflag == 0) ? Action::success : Action::failure;
