Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Actions/FragmentationAction/FragmentationAutomationAction.cpp

    r94d5ac6 rdb6f7d  
    3939#include "CodePatterns/MemDebug.hpp"
    4040
     41#include <boost/mpl/remove.hpp>
     42#include <boost/lambda/lambda.hpp>
     43
     44#include "CodePatterns/Assert.hpp"
    4145#include "CodePatterns/Info.hpp"
    4246#include "CodePatterns/Log.hpp"
    43 #include "JobMarket/Controller/FragmentController.hpp"
    4447#include "JobMarket/Jobs/FragmentJob.hpp"
    4548
    46 #include "Atom/atom.hpp"
     49#include "Fragmentation/Automation/createMatrixNrLookup.hpp"
     50#include "Fragmentation/Automation/extractJobIds.hpp"
     51#include "Fragmentation/Automation/FragmentationChargeDensity.hpp"
     52#include "Fragmentation/Automation/FragmentationResults.hpp"
     53#include "Fragmentation/Automation/MPQCFragmentController.hpp"
     54#include "Fragmentation/Automation/VMGDebugGridFragmentController.hpp"
     55#include "Fragmentation/Automation/VMGFragmentController.hpp"
    4756#include "Fragmentation/EnergyMatrix.hpp"
    4857#include "Fragmentation/ForceMatrix.hpp"
    4958#include "Fragmentation/Fragmentation.hpp"
     59#include "Fragmentation/SetValues/Fragment.hpp"
     60#include "Fragmentation/SetValues/Histogram.hpp"
     61#include "Fragmentation/SetValues/IndexedVectors.hpp"
    5062#include "Fragmentation/HydrogenSaturation_enum.hpp"
     63#include "Fragmentation/KeySet.hpp"
    5164#include "Fragmentation/KeySetsContainer.hpp"
     65#include "Fragmentation/Summation/writeTable.hpp"
    5266#include "Graph/DepthFirstSearchAnalysis.hpp"
    53 #include "Jobs/MPQCCommandJob.hpp"
    54 #include "molecule.hpp"
     67#include "Helpers/defs.hpp"
     68#include "Jobs/MPQCJob.hpp"
     69#include "Jobs/MPQCData.hpp"
     70#include "Jobs/MPQCData_printKeyNames.hpp"
     71#ifdef HAVE_VMG
     72#include "Jobs/VMGDebugGridJob.hpp"
     73#include "Jobs/VMGJob.hpp"
     74#include "Jobs/VMGData.hpp"
     75#include "Jobs/VMGDataFused.hpp"
     76#include "Jobs/VMGDataMap.hpp"
     77#include "Jobs/VMGData_printKeyNames.hpp"
     78#endif
    5579#include "World.hpp"
    5680
     81#include <fstream>
    5782#include <iostream>
    5883#include <string>
    5984#include <vector>
     85
     86#include <boost/mpl/for_each.hpp>
    6087
    6188#include "Actions/FragmentationAction/FragmentationAutomationAction.hpp"
     
    74101{
    75102  return NULL;
    76 }
    77 
    78 /** Creates a MPQCCommandJob with argument \a filename.
    79  *
    80  * @param jobs created job is added to this vector
    81  * @param command mpqc command to execute
    82  * @param filename filename being argument to job
    83  * @param nextid id for this job
    84  */
    85 void parsejob(
    86     std::vector<FragmentJob::ptr> &jobs,
    87     const std::string &command,
    88     const std::string &filename,
    89     const JobId_t nextid)
    90 {
    91   std::ifstream file;
    92   file.open(filename.c_str());
    93   ASSERT( file.good(), "parsejob() - file "+filename+" does not exist.");
    94   std::string output((std::istreambuf_iterator<char>(file)),
    95       std::istreambuf_iterator<char>());
    96   FragmentJob::ptr testJob( new MPQCCommandJob(output, nextid, command) );
    97   jobs.push_back(testJob);
    98   file.close();
    99   LOG(1, "INFO: Added MPQCCommandJob from file "+filename+".");
    100103}
    101104
     
    130133
    131134
    132 /** Print MPQCData from received results.
    133  *
    134  * @param results received results to extract MPQCData from
    135  * @param KeySetFilename filename with keysets to associate forces correctly
     135
     136/** Place results from FragmentResult into EnergyMatrix and ForceMatrix.
     137 *
     138 * @param fragmentData MPQCData resulting from the jobs
     139 * @param MatrixNrLookup Lookup up-map from job id to fragment number
     140 * @param FragmentCounter total number of fragments
    136141 * @param NoAtoms total number of atoms
     142 * @param Energy energy matrix to be filled on return
     143 * @param Force force matrix to be filled on return
     144 * @return true - everything ok, false - else
    137145 */
    138 bool printReceivedMPQCResults(
    139     const std::vector<FragmentResult::ptr> &results,
    140     const std::string &KeySetFilename,
    141     size_t NoAtoms)
     146bool putResultsintoMatrices(
     147    const std::map<JobId_t, MPQCData> &fragmentData,
     148    const std::map< JobId_t, size_t > &MatrixNrLookup,
     149    const size_t FragmentCounter,
     150    const size_t NoAtoms,
     151    EnergyMatrix &Energy,
     152    ForceMatrix &Force)
    142153{
    143   EnergyMatrix Energy;
    144   EnergyMatrix EnergyFragments;
    145   ForceMatrix Force;
    146   ForceMatrix ForceFragments;
    147   KeySetsContainer KeySet;
    148 
    149   // align fragments
    150   std::map< JobId_t, size_t > MatrixNrLookup;
    151   size_t FragmentCounter = 0;
    152   {
    153     // bring ids in order ...
    154     typedef std::map< JobId_t, FragmentResult::ptr> IdResultMap_t;
    155     IdResultMap_t IdResultMap;
    156     for (std::vector<FragmentResult::ptr>::const_iterator iter = results.begin();
    157         iter != results.end(); ++iter) {
    158   #ifndef NDEBUG
    159       std::pair< IdResultMap_t::iterator, bool> inserter =
    160   #endif
    161       IdResultMap.insert( make_pair((*iter)->getId(), *iter) );
    162       ASSERT( inserter.second,
    163           "printReceivedMPQCResults() - two results have same id "
    164           +toString((*iter)->getId())+".");
    165     }
    166     // ... and fill lookup
    167     for(IdResultMap_t::const_iterator iter = IdResultMap.begin();
    168         iter != IdResultMap.end(); ++iter)
    169       MatrixNrLookup.insert( make_pair(iter->first, FragmentCounter++) );
    170   }
    171   LOG(1, "INFO: There are " << FragmentCounter << " fragments.");
    172 
    173   // extract results
    174   std::vector<MPQCData> fragmentData(results.size());
    175   MPQCData combinedData;
    176 
    177   LOG(2, "DEBUG: Parsing now through " << results.size() << " results.");
    178   for (std::vector<FragmentResult::ptr>::const_iterator iter = results.begin();
    179       iter != results.end(); ++iter) {
    180     LOG(1, "RESULT: job #"+toString((*iter)->getId())+": "+toString((*iter)->result));
    181     MPQCData extractedData;
    182     std::stringstream inputstream((*iter)->result);
    183     LOG(2, "DEBUG: First 50 characters FragmentResult's string: "+(*iter)->result.substr(0, 50));
    184     boost::archive::text_iarchive ia(inputstream);
    185     ia >> extractedData;
    186     LOG(1, "INFO: extracted data is " << extractedData << ".");
    187 
     154  for (std::map<JobId_t, MPQCData>::const_iterator dataiter = fragmentData.begin();
     155      dataiter != fragmentData.end(); ++dataiter) {
     156    const MPQCData &extractedData = dataiter->second;
     157    const JobId_t &jobid = dataiter->first;
     158    std::map< JobId_t, size_t >::const_iterator nriter = MatrixNrLookup.find(jobid);
     159    ASSERT( nriter != MatrixNrLookup.end(),
     160        "putResultsintoMatrices() - MatrixNrLookup does not contain id "
     161        +toString(jobid)+".");
    188162    // place results into EnergyMatrix ...
    189163    {
    190164      MatrixContainer::MatrixArray matrix;
    191165      matrix.resize(1);
    192       matrix[0].resize(1, extractedData.energy);
     166      matrix[0].resize(1, extractedData.energies.total);
    193167      if (!Energy.AddMatrix(
    194           std::string("MPQCJob ")+toString((*iter)->getId()),
     168          std::string("MPQCJob ")+toString(jobid),
    195169          matrix,
    196           MatrixNrLookup[(*iter)->getId()])) {
     170          nriter->second)) {
    197171        ELOG(1, "Adding energy matrix failed.");
    198172        return false;
     
    213187      }
    214188      if (!Force.AddMatrix(
    215           std::string("MPQCJob ")+toString((*iter)->getId()),
     189          std::string("MPQCJob ")+toString(jobid),
    216190          matrix,
    217           MatrixNrLookup[(*iter)->getId()])) {
     191          nriter->second)) {
    218192        ELOG(1, "Adding force matrix failed.");
    219193        return false;
     
    234208    return false;
    235209
     210  return true;
     211}
     212
     213/** Print MPQCData from received results.
     214 *
     215 * @param fragmentData MPQCData resulting from the jobs, associated to job id
     216 * @param KeySetFilename filename with keysets to associate forces correctly
     217 * @param NoAtoms total number of atoms
     218 * @param full_sample summed up charge from fragments on return
     219 */
     220bool printReceivedMPQCResults(
     221    const std::map<JobId_t, MPQCData> &fragmentData,
     222    const std::string &KeySetFilename,
     223    size_t NoAtoms)
     224{
     225  // create a vector of all job ids
     226  std::vector<JobId_t> jobids;
     227  std::transform(fragmentData.begin(),fragmentData.end(),
     228      std::back_inserter(jobids),
     229      boost::bind( &std::map<JobId_t,MPQCData>::value_type::first, boost::lambda::_1 )
     230  );
     231
     232  // create lookup from job nr to fragment number
     233  size_t FragmentCounter = 0;
     234  const std::map< JobId_t, size_t > MatrixNrLookup=
     235      createMatrixNrLookup(jobids, FragmentCounter);
     236
     237  // place results into maps
     238  EnergyMatrix Energy;
     239  ForceMatrix Force;
     240  if (!putResultsintoMatrices(fragmentData, MatrixNrLookup, FragmentCounter, NoAtoms, Energy, Force))
     241    return false;
     242
     243  // initialise keysets
     244  KeySetsContainer KeySet;
     245  KeySetsContainer ForceKeySet;
     246  if (!Energy.InitialiseIndices()) return false;
     247
     248  if (!Force.ParseIndices(KeySetFilename.c_str())) return false;
     249
     250  {
     251    // else needs keysets without hydrogens
     252    std::stringstream filename;
     253    filename << FRAGMENTPREFIX << KEYSETFILE;
     254    if (!KeySet.ParseKeySets(KeySetFilename, filename.str(), FragmentCounter)) return false;
     255  }
     256
     257  {
     258    // forces need keysets including hydrogens
     259    std::stringstream filename;
     260    filename << FRAGMENTPREFIX << FORCESFILE;
     261    if (!ForceKeySet.ParseKeySets(KeySetFilename, filename.str(), FragmentCounter)) return false;
     262  }
    236263
    237264  // combine all found data
    238   if (!Energy.InitialiseIndices()) return false;
    239 
    240   if (!Force.ParseIndices(KeySetFilename.c_str())) return false;
    241 
    242   if (!KeySet.ParseKeySets(KeySetFilename.c_str(), Force.RowCounter, Force.MatrixCounter)) return false;
    243 
    244265  if (!KeySet.ParseManyBodyTerms()) return false;
    245266
     267  EnergyMatrix EnergyFragments;
     268  ForceMatrix ForceFragments;
    246269  if (!EnergyFragments.AllocateMatrix(Energy.Header, Energy.MatrixCounter, Energy.RowCounter, Energy.ColumnCounter)) return false;
    247270  if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return false;
     
    275298}
    276299
     300void writeToFile(const std::string &filename, const std::string contents)
     301{
     302  std::ofstream tablefile(filename.c_str());
     303  tablefile << contents;
     304  tablefile.close();
     305}
     306
     307/** Print MPQCData from received results.
     308 *
     309 * @param results summed up results container
     310 */
     311void printReceivedFullResults(
     312    const FragmentationResults &results)
     313{
     314  // print tables (without eigenvalues, they go extra)
     315  {
     316    typedef boost::mpl::remove<MPQCDataEnergyVector_t, MPQCDataFused::energy_eigenvalues>::type
     317      MPQCDataEnergyVector_noeigenvalues_t;
     318    const std::string energyresult =
     319        writeTable<MPQCDataEnergyMap_t, MPQCDataEnergyVector_noeigenvalues_t >()(
     320            results.Result_Energy_fused, results.getMaxLevel());
     321    LOG(0, "Energy table is \n" << energyresult);
     322    std::string filename;
     323    filename += FRAGMENTPREFIX + std::string("_Energy.dat");
     324    writeToFile(filename, energyresult);
     325  }
     326
     327  {
     328    const std::string gridresult =
     329        writeTable<VMGDataMap_t, VMGDataVector_t >()(
     330            results.Result_LongRange_fused, results.getMaxLevel(), 2);
     331    LOG(0, "VMG table is \n" << gridresult);
     332    std::string filename;
     333    filename += FRAGMENTPREFIX + std::string("_VMGEnergy.dat");
     334    writeToFile(filename, gridresult);
     335  }
     336
     337  {
     338    const std::string gridresult =
     339        writeTable<VMGDataLongRangeMap_t, VMGDataLongRangeVector_t >()(
     340            results.Result_LongRangeIntegrated_fused, results.getMaxLevel(), 2);
     341    LOG(0, "LongRange table is \n" << gridresult);
     342    std::string filename;
     343    filename += FRAGMENTPREFIX + std::string("_LongRangeEnergy.dat");
     344    writeToFile(filename, gridresult);
     345  }
     346
     347  {
     348    const std::string eigenvalueresult;
     349    LOG(0, "Eigenvalue table is \n" << eigenvalueresult);
     350    std::string filename;
     351    filename += FRAGMENTPREFIX + std::string("_Eigenvalues.dat");
     352    writeToFile(filename, eigenvalueresult);
     353  }
     354
     355  {
     356    const std::string forceresult =
     357        writeTable<MPQCDataForceMap_t, MPQCDataForceVector_t>()(
     358            results.Result_Force_fused, results.getMaxLevel());
     359    LOG(0, "Force table is \n" << forceresult);
     360    std::string filename;
     361    filename += FRAGMENTPREFIX + std::string("_Forces.dat");
     362    writeToFile(filename, forceresult);
     363  }
     364  // we don't want to print grid to a table
     365  {
     366    // print times (without flops for now)
     367    typedef boost::mpl::remove<
     368        boost::mpl::remove<MPQCDataTimeVector_t, MPQCDataFused::times_total_flops>::type,
     369        MPQCDataFused::times_gather_flops>::type
     370        MPQCDataTimeVector_noflops_t;
     371    const std::string timesresult =
     372        writeTable<MPQCDataTimeMap_t, MPQCDataTimeVector_noflops_t >()(
     373            results.Result_Time_fused, results.getMaxLevel());
     374    LOG(0, "Times table is \n" << timesresult);
     375    std::string filename;
     376    filename += FRAGMENTPREFIX + std::string("_Times.dat");
     377    writeToFile(filename, timesresult);
     378  }
     379}
     380
     381
    277382Action::state_ptr FragmentationFragmentationAutomationAction::performCall() {
    278383  boost::asio::io_service io_service;
    279   FragmentController controller(io_service);
    280384
    281385  // TODO: Have io_service run in second thread and merge with current again eventually
    282386
    283   // Phase One: obtain ids
    284   std::vector< boost::filesystem::path > jobfiles = params.jobfiles.get();
    285   controller.requestIds(params.host.get(), params.port.get(), jobfiles.size());
    286   {
    287     io_service.reset();
    288     Info info("io_service: Phase One");
    289     io_service.run();
    290   }
    291   // Phase Two: create and add jobs
    292   {
    293     std::vector<FragmentJob::ptr> jobs;
    294     for (std::vector< boost::filesystem::path >::const_iterator iter = jobfiles .begin();
    295         iter != jobfiles .end(); ++iter) {
    296       const std::string &filename = (*iter).string();
    297       if (boost::filesystem::exists(filename)) {
    298         const JobId_t next_id = controller.getAvailableId();
    299         LOG(1, "INFO: Creating MPQCCommandJob with filename'"
    300             +filename+"', and id "+toString(next_id)+".");
    301         parsejob(jobs, params.executable.get().string(), filename, next_id);
    302       } else {
    303         ELOG(1, "Fragment job "+filename+" does not exist.");
     387  size_t Exitflag = 0;
     388  std::map<JobId_t, MPQCData> fragmentData;
     389  {
     390    MPQCFragmentController mpqccontroller(io_service);
     391    mpqccontroller.setHost(params.host.get());
     392    mpqccontroller.setPort(params.port.get());
     393    mpqccontroller.setLevel(params.level.get());
     394    // Phase One: obtain ids
     395    std::vector< boost::filesystem::path > jobfiles = params.jobfiles.get();
     396    mpqccontroller.requestIds(jobfiles.size());
     397
     398    // Phase Two: create and add MPQCJobs
     399    if (!mpqccontroller.addJobsFromFiles(params.executable.get().string(), jobfiles))
     400      return Action::failure;
     401
     402    // Phase Three: calculate result
     403    mpqccontroller.waitforResults(jobfiles.size());
     404    mpqccontroller.getResults(fragmentData);
     405
     406    Exitflag += mpqccontroller.getExitflag();
     407  }
     408
     409#ifdef HAVE_VMG
     410  if (params.DoLongrange.get()) {
     411  if ( World::getInstance().getAllAtoms().size() == 0) {
     412    ELOG(1, "Please load the full molecule into the world before starting this action.");
     413    return Action::failure;
     414  }
     415
     416  // obtain combined charge density
     417  FragmentationChargeDensity summedChargeDensity(
     418      fragmentData,
     419      params.path.get());
     420  const std::vector<SamplingGrid> full_sample = summedChargeDensity.getFullSampledGrid();
     421
     422  LOG(1, "INFO: There are " << fragmentData.size() << " short-range and "
     423      << full_sample.size() << " level-wise long-range jobs.");
     424
     425  // Phase Four: obtain more ids
     426  std::map<JobId_t, VMGData> longrangeData;
     427  {
     428    VMGFragmentController vmgcontroller(io_service);
     429    vmgcontroller.setHost(params.host.get());
     430    vmgcontroller.setPort(params.port.get());
     431    const size_t NoJobs = fragmentData.size()+full_sample.size();
     432    vmgcontroller.requestIds(NoJobs);
     433
     434    // Phase Five: create VMGJobs
     435    const size_t near_field_cells = params.near_field_cells.get();
     436    const size_t interpolation_degree = params.interpolation_degree.get();
     437    if (!vmgcontroller.createLongRangeJobs(
     438        fragmentData,
     439        full_sample,
     440        summedChargeDensity.getFragment(),
     441        near_field_cells,
     442        interpolation_degree))
     443      return Action::failure;
     444
     445    // Phase Six: calculate result
     446    vmgcontroller.waitforResults(NoJobs);
     447    vmgcontroller.getResults(longrangeData);
     448    ASSERT( NoJobs == longrangeData.size(),
     449        "FragmentationFragmentationAutomationAction::performCall() - number of MPQCresults+"
     450        +toString(full_sample.size())+"="+toString(NoJobs)
     451        +" and VMGresults "+toString(longrangeData.size())+" don't match.");
     452    Exitflag += vmgcontroller.getExitflag();
     453  }
     454
     455  // remove full solution corresponding to full_sample from map (must be highest ids), has to be treated extra
     456  std::map<JobId_t, VMGData>::iterator iter = longrangeData.end();
     457  for (size_t i=0;i<full_sample.size();++i)
     458    --iter;
     459  std::map<JobId_t, VMGData>::iterator remove_iter = iter;
     460  std::vector<VMGData> fullsolutionData;
     461  for (; iter != longrangeData.end(); ++iter)
     462    fullsolutionData.push_back(iter->second);
     463  longrangeData.erase(remove_iter, longrangeData.end());
     464
     465  // Final phase: sum up and print result
     466  {
     467    FragmentationResults results(
     468        fragmentData,
     469        longrangeData,
     470        fullsolutionData,
     471        params.path.get(),
     472        getNoAtomsFromAdjacencyFile(params.path.get()),
     473        full_sample);
     474
     475    LOG(1, "INFO: Parsing fragment files from " << params.path.get() << ".");
     476    printReceivedFullResults(results);
     477  }
     478
     479  std::map<JobId_t, std::string> debugData;
     480  {
     481    if (!full_sample.empty()) {
     482      // create debug jobs for each level to print the summed-up potential to vtk files
     483      VMGDebugGridFragmentController debugcontroller(io_service);
     484      debugcontroller.setHost(params.host.get());
     485      debugcontroller.setPort(params.port.get());
     486      debugcontroller.requestIds(full_sample.size());
     487      if (!debugcontroller.createDebugJobs(full_sample))
    304488        return Action::failure;
    305       }
     489      debugcontroller.waitforResults(full_sample.size());
     490      debugcontroller.getResults(debugData);
     491      Exitflag += debugcontroller.getExitflag();
    306492    }
    307     controller.addJobs(jobs);
    308     controller.sendJobs(params.host.get(), params.port.get());
    309   }
    310   {
    311     io_service.reset();
    312     Info info("io_service: Phase Two");
    313     io_service.run();
    314   }
    315   // Phase Three: calculate result
    316   size_t NoCalculatedResults = 0;
    317   while (NoCalculatedResults != jobfiles.size()) {
    318     // wait a bit
    319     boost::asio::deadline_timer timer(io_service);
    320     timer.expires_from_now(boost::posix_time::milliseconds(500));
    321     timer.wait();
    322     // then request status
    323     controller.checkResults(params.host.get(), params.port.get());
    324     {
    325       io_service.reset();
    326       Info info("io_service: Phase Three");
    327       io_service.run();
    328     }
    329     const std::pair<size_t, size_t> JobStatus = controller.getJobStatus();
    330     LOG(1, "INFO: #" << JobStatus.first << " are waiting in the queue and #" << JobStatus.second << " jobs are calculated so far.");
    331     NoCalculatedResults = JobStatus.second;
    332   }
    333   // Phase Three: get result
    334   controller.receiveResults(params.host.get(), params.port.get());
    335   {
    336     io_service.reset();
    337     Info info("io_service: Phase Four");
    338     io_service.run();
    339   }
     493  }
     494  }
     495#else
    340496  // Final phase: print result
    341497  {
    342498    LOG(1, "INFO: Parsing fragment files from " << params.path.get() << ".");
    343     std::vector<FragmentResult::ptr> results = controller.getReceivedResults();
    344499    printReceivedMPQCResults(
    345         results,
     500        fragmentData,
    346501        params.path.get(),
    347502        getNoAtomsFromAdjacencyFile(params.path.get()));
    348503  }
    349   size_t Exitflag = controller.getExitflag();
     504#endif
    350505
    351506  return (Exitflag == 0) ? Action::success : Action::failure;
Note: See TracChangeset for help on using the changeset viewer.