/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2012 University of Bonn. All rights reserved. * Copyright (C) 2013 Frederik Heber. 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 . */ /* * controller_MPQCCommandJob.cpp * * Created on: 01.06.2012 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif // boost asio needs specific operator new #include #include #include #include "CodePatterns/MemDebug.hpp" #include "controller_MPQCCommandJob.hpp" #include #include #include #include #include "CodePatterns/Info.hpp" #include "CodePatterns/Log.hpp" #include "JobMarket/Controller/ControllerCommand.hpp" #include "JobMarket/Controller/ControllerCommandRegistry.hpp" #include "JobMarket/Controller/FragmentController.hpp" #include "JobMarket/JobId.hpp" #include "JobMarket/Jobs/FragmentJob.hpp" #include "JobMarket/Results/FragmentResult.hpp" #include "Fragmentation/EnergyMatrix.hpp" #include "Fragmentation/ForceMatrix.hpp" #include "Fragmentation/KeySetsContainer.hpp" #include "Fragmentation/defs.hpp" #include "Helpers/defs.hpp" #include "Jobs/MPQCCommandJob.hpp" #include "Fragmentation/Summation/Containers/MPQCData.hpp" #include "LinearAlgebra/defs.hpp" #include "ControllerOptions_MPQCCommandJob.hpp" /** 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 &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(file)), std::istreambuf_iterator()); FragmentJob::ptr testJob( new MPQCCommandJob(output, nextid, command) ); jobs.push_back(testJob); file.close(); LOG(1, "INFO: Added MPQCCommandJob from file "+filename+"."); } /** Print received results. * * @param results received results to print */ void printReceivedResults(const std::vector &results) { for (std::vector::const_iterator iter = results.begin(); iter != results.end(); ++iter) LOG(1, "RESULT: job #"+toString((*iter)->getId())+": "+toString((*iter)->result)); } /** Print MPQCData from received results. * * @param results received results to extract MPQCData from * @param KeySetFilename filename with keysets to associate forces correctly * @param NoAtoms total number of atoms */ bool printReceivedMPQCResults( const std::vector &results, const std::string &KeySetFilename, size_t NoAtoms) { EnergyMatrix Energy; EnergyMatrix EnergyFragments; ForceMatrix Force; ForceMatrix ForceFragments; KeySetsContainer KeySet; // align fragments std::map< JobId_t, size_t > MatrixNrLookup; size_t FragmentCounter = 0; { // bring ids in order ... typedef std::map< JobId_t, FragmentResult::ptr> IdResultMap_t; IdResultMap_t IdResultMap; for (std::vector::const_iterator iter = results.begin(); iter != results.end(); ++iter) { #ifndef NDEBUG std::pair< IdResultMap_t::iterator, bool> inserter = #endif IdResultMap.insert( make_pair((*iter)->getId(), *iter) ); ASSERT( inserter.second, "printReceivedMPQCResults() - two results have same id " +toString((*iter)->getId())+"."); } // ... and fill lookup for(IdResultMap_t::const_iterator iter = IdResultMap.begin(); iter != IdResultMap.end(); ++iter) MatrixNrLookup.insert( make_pair(iter->first, FragmentCounter++) ); } LOG(1, "INFO: There are " << FragmentCounter << " fragments."); // extract results std::vector fragmentData(results.size()); MPQCData combinedData; LOG(2, "DEBUG: Parsing now through " << results.size() << " results."); for (std::vector::const_iterator iter = results.begin(); iter != results.end(); ++iter) { LOG(1, "RESULT: job #"+toString((*iter)->getId())+": "+toString((*iter)->result)); MPQCData 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 of #" << (*iter)->getId() << " is " << extractedData << "."); // place results into EnergyMatrix ... { MatrixContainer::MatrixArray matrix; matrix.resize(1); matrix[0].resize(1, extractedData.energies.total); if (!Energy.AddMatrix( std::string("MPQCJob ")+toString((*iter)->getId()), matrix, MatrixNrLookup[(*iter)->getId()])) { ELOG(1, "Adding energy matrix failed."); return false; } } // ... and ForceMatrix (with two empty columns in front) { MatrixContainer::MatrixArray matrix; const size_t rows = extractedData.forces.size(); matrix.resize(rows); for (size_t i=0;igetId()), matrix, MatrixNrLookup[(*iter)->getId()])) { ELOG(1, "Adding force matrix failed."); return false; } } } // add one more matrix (not required for energy) MatrixContainer::MatrixArray matrix; matrix.resize(1); matrix[0].resize(1, 0.); if (!Energy.AddMatrix(std::string("MPQCJob total"), matrix, FragmentCounter)) return false; // but for energy because we need to know total number of atoms matrix.resize(NoAtoms); for (size_t i = 0; i< NoAtoms; ++i) matrix[i].resize(2+NDIM, 0.); if (!Force.AddMatrix(std::string("MPQCJob total"), matrix, FragmentCounter)) return false; // combine all found data if (!Energy.InitialiseIndices()) return false; if (!Force.ParseIndices(KeySetFilename.c_str())) return false; { std::stringstream filename; filename << FRAGMENTPREFIX << KEYSETFILE; if (!KeySet.ParseKeySets(KeySetFilename.c_str(), filename.str(), Force.MatrixCounter)) return 1; } if (!KeySet.ParseManyBodyTerms()) return false; if (!EnergyFragments.AllocateMatrix(Energy.Header, Energy.MatrixCounter, Energy.RowCounter, Energy.ColumnCounter)) return false; if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return false; if(!Energy.SetLastMatrix(0., 0)) return false; if(!Force.SetLastMatrix(0., 2)) return false; for (int BondOrder=0;BondOrder jobs; for (std::vector< std::string >::const_iterator iter = ControllerInfo.jobfiles.begin(); iter != ControllerInfo.jobfiles.end(); ++iter) { const JobId_t next_id = controller.getAvailableId(); const std::string &filename = *iter; LOG(1, "INFO: Creating MPQCCommandJob with filename '" +filename+"', and id "+toString(next_id)+"."); parsejob(jobs, ControllerInfo.executable, filename, next_id); } controller.addJobs(jobs); controller.sendJobs(ControllerInfo.server, ControllerInfo.serverport); } inline std::vector getListOfCommands(const ControllerCommandRegistry &ControllerCommands) { std::vector Commands; for (ControllerCommandRegistry::const_iterator iter = ControllerCommands.getBeginIter(); iter != ControllerCommands.getEndIter(); ++iter) Commands.push_back(iter->first); return Commands; } ControllerOptions *controller_MPQCCommandJob::allocateControllerInfo() { return new ControllerOptions_MPQCCommandJob(); } void controller_MPQCCommandJob::addSpecificCommands( boost::function ®istrator, FragmentController &controller, ControllerOptions &ControllerInfo) { ControllerOptions_MPQCCommandJob &CI = reinterpret_cast(ControllerInfo); registrator(new ControllerCommand("addjobs", boost::assign::list_of< ControllerCommand::commands_t > (boost::bind(&FragmentController::requestIds, boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport), boost::bind(&std::vector::size, boost::cref(CI.jobfiles)))) (boost::bind(&AddJobs, boost::ref(controller), boost::cref(CI))) )); registrator(new ControllerCommand("receiveresults", boost::assign::list_of< ControllerCommand::commands_t > (boost::bind(&FragmentController::receiveResults, boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport))) (boost::bind(&printReceivedResults, boost::bind(&FragmentController::getReceivedResults, boost::ref(controller)))) )); registrator(new ControllerCommand("receivempqc", boost::assign::list_of< ControllerCommand::commands_t > (boost::bind(&FragmentController_JobIdProxy::setJobids, boost::ref(controller), boost::cref(CI.ids))) (boost::bind(&FragmentController::receiveResults, boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport))) (boost::bind(&printReceivedMPQCResults, boost::bind(&FragmentController::getReceivedResults, boost::ref(controller)), boost::cref(CI.fragmentpath), boost::bind(&getNoAtomsFromAdjacencyFile, boost::cref(CI.fragmentpath)))) )); } void controller_MPQCCommandJob::addSpecificOptions( boost::program_options::options_description_easy_init option) { option ("executable", boost::program_options::value< std::string >(), "executable for commands 'createjobs'") ("fragment-path", boost::program_options::value< std::string >(), "path to fragment files for 'receivempqc'") ("jobfiles", boost::program_options::value< std::vector< std::string > >()->multitoken(), "list of files as single argument toexecutable for 'addjobs'") ("ids", boost::program_options::value< std::vector< JobId_t > >()->multitoken(), "list of jobids to request from server for 'receivempqc'") ; } int controller_MPQCCommandJob::addOtherParsings( ControllerOptions &ControllerInfo, boost::program_options::variables_map &vm) { ControllerOptions_MPQCCommandJob &CI = reinterpret_cast(ControllerInfo); int status = 0; status = CI.parseExecutable(vm); if (status) return status; status = CI.parseFragmentpath(vm); if (status) return status; status = CI.parseJobfiles(vm); if (status) return status; status = CI.parseIds(vm); return status; }