source: src/controller_MPQCCommandJob.cpp@ 6253ed

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 6253ed was 94d5ac6, checked in by Frederik Heber <heber@…>, 12 years ago

FIX: As we use GSL internally, we are as of now required to use GPL v2 license.

  • GNU Scientific Library is used at every place in the code, especially the sub-package LinearAlgebra is based on it which in turn is used really everywhere in the remainder of MoleCuilder. Hence, we have to use the GPL license for the whole of MoleCuilder. In effect, GPL's COPYING was present all along and stated the terms of the GPL v2 license.
  • Hence, I added the default GPL v2 disclaimer to every source file and removed the note about a (actually missing) LICENSE file.
  • also, I added a help-redistribute action which again gives the disclaimer of the GPL v2.
  • also, I changed in the disclaimer that is printed at every program start in builder_init.cpp.
  • TEST: Added check on GPL statement present in every module to test CodeChecks project-disclaimer.
  • Property mode set to 100644
File size: 13.7 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2012 University of Bonn. All rights reserved.
5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/*
24 * controller_MPQCCommandJob.cpp
25 *
26 * Created on: 01.06.2012
27 * Author: heber
28 */
29
30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35// boost asio needs specific operator new
36#include <boost/asio.hpp>
37
38#include <boost/archive/text_iarchive.hpp>
39#include <boost/archive/text_oarchive.hpp>
40
41#include "CodePatterns/MemDebug.hpp"
42
43#include "controller_MPQCCommandJob.hpp"
44
45#include <boost/assign.hpp>
46#include <boost/bind.hpp>
47#include <fstream>
48#include <string>
49
50#include "CodePatterns/Info.hpp"
51#include "CodePatterns/Log.hpp"
52
53#include "JobMarket/Controller/ControllerCommand.hpp"
54#include "JobMarket/Controller/ControllerCommandRegistry.hpp"
55#include "JobMarket/Controller/FragmentController.hpp"
56#include "JobMarket/JobId.hpp"
57#include "JobMarket/Jobs/FragmentJob.hpp"
58#include "JobMarket/Results/FragmentResult.hpp"
59
60#include "Fragmentation/EnergyMatrix.hpp"
61#include "Fragmentation/ForceMatrix.hpp"
62#include "Fragmentation/KeySetsContainer.hpp"
63#include "Fragmentation/defs.hpp"
64
65#include "Helpers/defs.hpp"
66
67#include "Jobs/MPQCCommandJob.hpp"
68#include "Jobs/MPQCCommandJob_MPQCData.hpp"
69
70#include "LinearAlgebra/defs.hpp"
71
72#include "ControllerOptions_MPQCCommandJob.hpp"
73
74/** Creates a MPQCCommandJob with argument \a filename.
75 *
76 * @param jobs created job is added to this vector
77 * @param command mpqc command to execute
78 * @param filename filename being argument to job
79 * @param nextid id for this job
80 */
81void parsejob(
82 std::vector<FragmentJob::ptr> &jobs,
83 const std::string &command,
84 const std::string &filename,
85 const JobId_t nextid)
86{
87 std::ifstream file;
88 file.open(filename.c_str());
89 ASSERT( file.good(), "parsejob() - file "+filename+" does not exist.");
90 std::string output((std::istreambuf_iterator<char>(file)),
91 std::istreambuf_iterator<char>());
92 FragmentJob::ptr testJob( new MPQCCommandJob(output, nextid, command) );
93 jobs.push_back(testJob);
94 file.close();
95 LOG(1, "INFO: Added MPQCCommandJob from file "+filename+".");
96}
97
98/** Print received results.
99 *
100 * @param results received results to print
101 */
102void printReceivedResults(const std::vector<FragmentResult::ptr> &results)
103{
104 for (std::vector<FragmentResult::ptr>::const_iterator iter = results.begin();
105 iter != results.end(); ++iter)
106 LOG(1, "RESULT: job #"+toString((*iter)->getId())+": "+toString((*iter)->result));
107}
108
109/** Print MPQCData from received results.
110 *
111 * @param results received results to extract MPQCData from
112 * @param KeySetFilename filename with keysets to associate forces correctly
113 * @param NoAtoms total number of atoms
114 */
115bool printReceivedMPQCResults(
116 const std::vector<FragmentResult::ptr> &results,
117 const std::string &KeySetFilename,
118 size_t NoAtoms)
119{
120 EnergyMatrix Energy;
121 EnergyMatrix EnergyFragments;
122 ForceMatrix Force;
123 ForceMatrix ForceFragments;
124 KeySetsContainer KeySet;
125
126 // align fragments
127 std::map< JobId_t, size_t > MatrixNrLookup;
128 size_t FragmentCounter = 0;
129 {
130 // bring ids in order ...
131 typedef std::map< JobId_t, FragmentResult::ptr> IdResultMap_t;
132 IdResultMap_t IdResultMap;
133 for (std::vector<FragmentResult::ptr>::const_iterator iter = results.begin();
134 iter != results.end(); ++iter) {
135 #ifndef NDEBUG
136 std::pair< IdResultMap_t::iterator, bool> inserter =
137 #endif
138 IdResultMap.insert( make_pair((*iter)->getId(), *iter) );
139 ASSERT( inserter.second,
140 "printReceivedMPQCResults() - two results have same id "
141 +toString((*iter)->getId())+".");
142 }
143 // ... and fill lookup
144 for(IdResultMap_t::const_iterator iter = IdResultMap.begin();
145 iter != IdResultMap.end(); ++iter)
146 MatrixNrLookup.insert( make_pair(iter->first, FragmentCounter++) );
147 }
148 LOG(1, "INFO: There are " << FragmentCounter << " fragments.");
149
150 // extract results
151 std::vector<MPQCData> fragmentData(results.size());
152 MPQCData combinedData;
153
154 LOG(2, "DEBUG: Parsing now through " << results.size() << " results.");
155 for (std::vector<FragmentResult::ptr>::const_iterator iter = results.begin();
156 iter != results.end(); ++iter) {
157 LOG(1, "RESULT: job #"+toString((*iter)->getId())+": "+toString((*iter)->result));
158 MPQCData extractedData;
159 std::stringstream inputstream((*iter)->result);
160 LOG(2, "DEBUG: First 50 characters FragmentResult's string: "+(*iter)->result.substr(0, 50));
161 boost::archive::text_iarchive ia(inputstream);
162 ia >> extractedData;
163 LOG(1, "INFO: extracted data is " << extractedData << ".");
164
165 // place results into EnergyMatrix ...
166 {
167 MatrixContainer::MatrixArray matrix;
168 matrix.resize(1);
169 matrix[0].resize(1, extractedData.energy);
170 if (!Energy.AddMatrix(
171 std::string("MPQCJob ")+toString((*iter)->getId()),
172 matrix,
173 MatrixNrLookup[(*iter)->getId()])) {
174 ELOG(1, "Adding energy matrix failed.");
175 return false;
176 }
177 }
178 // ... and ForceMatrix (with two empty columns in front)
179 {
180 MatrixContainer::MatrixArray matrix;
181 const size_t rows = extractedData.forces.size();
182 matrix.resize(rows);
183 for (size_t i=0;i<rows;++i) {
184 const size_t columns = 2+extractedData.forces[i].size();
185 matrix[i].resize(columns, 0.);
186 // for (size_t j=0;j<2;++j)
187 // matrix[i][j] = 0.;
188 for (size_t j=2;j<columns;++j)
189 matrix[i][j] = extractedData.forces[i][j-2];
190 }
191 if (!Force.AddMatrix(
192 std::string("MPQCJob ")+toString((*iter)->getId()),
193 matrix,
194 MatrixNrLookup[(*iter)->getId()])) {
195 ELOG(1, "Adding force matrix failed.");
196 return false;
197 }
198 }
199 }
200 // add one more matrix (not required for energy)
201 MatrixContainer::MatrixArray matrix;
202 matrix.resize(1);
203 matrix[0].resize(1, 0.);
204 if (!Energy.AddMatrix(std::string("MPQCJob total"), matrix, FragmentCounter))
205 return false;
206 // but for energy because we need to know total number of atoms
207 matrix.resize(NoAtoms);
208 for (size_t i = 0; i< NoAtoms; ++i)
209 matrix[i].resize(2+NDIM, 0.);
210 if (!Force.AddMatrix(std::string("MPQCJob total"), matrix, FragmentCounter))
211 return false;
212
213
214 // combine all found data
215 if (!Energy.InitialiseIndices()) return false;
216
217 if (!Force.ParseIndices(KeySetFilename.c_str())) return false;
218
219 if (!KeySet.ParseKeySets(KeySetFilename.c_str(), Force.RowCounter, Force.MatrixCounter)) return false;
220
221 if (!KeySet.ParseManyBodyTerms()) return false;
222
223 if (!EnergyFragments.AllocateMatrix(Energy.Header, Energy.MatrixCounter, Energy.RowCounter, Energy.ColumnCounter)) return false;
224 if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return false;
225
226 if(!Energy.SetLastMatrix(0., 0)) return false;
227 if(!Force.SetLastMatrix(0., 2)) return false;
228
229 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
230 // --------- sum up energy --------------------
231 LOG(1, "INFO: Summing energy of order " << BondOrder+1 << " ...");
232 if (!EnergyFragments.SumSubManyBodyTerms(Energy, KeySet, BondOrder)) return false;
233 if (!Energy.SumSubEnergy(EnergyFragments, NULL, KeySet, BondOrder, 1.)) return false;
234
235 // --------- sum up Forces --------------------
236 LOG(1, "INFO: Summing forces of order " << BondOrder+1 << " ...");
237 if (!ForceFragments.SumSubManyBodyTerms(Force, KeySet, BondOrder)) return false;
238 if (!Force.SumSubForces(ForceFragments, KeySet, BondOrder, 1.)) return false;
239 }
240
241 // for debugging print resulting energy and forces
242 LOG(1, "INFO: Resulting energy is " << Energy.Matrix[ FragmentCounter ][0][0]);
243 std::stringstream output;
244 for (int i=0; i< Force.RowCounter[FragmentCounter]; ++i) {
245 for (int j=0; j< Force.ColumnCounter[FragmentCounter]; ++j)
246 output << Force.Matrix[ FragmentCounter ][i][j] << " ";
247 output << "\n";
248 }
249 LOG(1, "INFO: Resulting forces are " << std::endl << output.str());
250
251 return true;
252}
253
254
255/** Helper function to get number of atoms somehow.
256 *
257 * Here, we just parse the number of lines in the adjacency file as
258 * it should correspond to the number of atoms, except when some atoms
259 * are not bonded, but then fragmentation makes no sense.
260 *
261 * @param path path to the adjacency file
262 */
263size_t getNoAtomsFromAdjacencyFile(const std::string &path)
264{
265 size_t NoAtoms = 0;
266
267 // parse in special file to get atom count (from line count)
268 std::string filename(path);
269 filename += FRAGMENTPREFIX;
270 filename += ADJACENCYFILE;
271 std::ifstream adjacency(filename.c_str());
272 if (adjacency.fail()) {
273 LOG(0, endl << "getNoAtomsFromAdjacencyFile() - Unable to open " << filename << ", is the directory correct?");
274 return false;
275 }
276 std::string buffer;
277 while (getline(adjacency, buffer))
278 NoAtoms++;
279 LOG(1, "INFO: There are " << NoAtoms << " atoms.");
280
281 return NoAtoms;
282}
283
284/** Creates a MPQCCommandJob out of give \a command with \a argument.
285 *
286 * @param controller reference to controller to add jobs
287 * @param ControllerInfo information on the job
288 */
289void AddJobs(FragmentController &controller, const ControllerOptions_MPQCCommandJob &ControllerInfo)
290{
291 std::vector<FragmentJob::ptr> jobs;
292 for (std::vector< std::string >::const_iterator iter = ControllerInfo.jobfiles.begin();
293 iter != ControllerInfo.jobfiles.end(); ++iter) {
294 const JobId_t next_id = controller.getAvailableId();
295 const std::string &filename = *iter;
296 LOG(1, "INFO: Creating MPQCCommandJob with filename '"
297 +filename+"', and id "+toString(next_id)+".");
298 parsejob(jobs, ControllerInfo.executable, filename, next_id);
299 }
300 controller.addJobs(jobs);
301 controller.sendJobs(ControllerInfo.server, ControllerInfo.serverport);
302}
303
304inline std::vector<std::string> getListOfCommands(const ControllerCommandRegistry &ControllerCommands)
305{
306 std::vector<std::string> Commands;
307 for (ControllerCommandRegistry::const_iterator iter = ControllerCommands.getBeginIter();
308 iter != ControllerCommands.getEndIter(); ++iter)
309 Commands.push_back(iter->first);
310
311 return Commands;
312}
313
314ControllerOptions *controller_MPQCCommandJob::allocateControllerInfo()
315{
316 return new ControllerOptions_MPQCCommandJob();
317}
318
319void controller_MPQCCommandJob::addSpecificCommands(
320 boost::function<void (ControllerCommand *)> &registrator,
321 FragmentController &controller,
322 ControllerOptions &ControllerInfo)
323{
324 ControllerOptions_MPQCCommandJob &CI =
325 reinterpret_cast<ControllerOptions_MPQCCommandJob &>(ControllerInfo);
326 registrator(new ControllerCommand("addjobs",
327 boost::assign::list_of< ControllerCommand::commands_t >
328 (boost::bind(&FragmentController::requestIds,
329 boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport),
330 boost::bind(&std::vector<std::string>::size, boost::cref(CI.jobfiles))))
331 (boost::bind(&AddJobs, boost::ref(controller), boost::cref(CI)))
332 ));
333 registrator(new ControllerCommand("receiveresults",
334 boost::assign::list_of< ControllerCommand::commands_t >
335 (boost::bind(&FragmentController::receiveResults,
336 boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport)))
337 (boost::bind(&printReceivedResults,
338 boost::bind(&FragmentController::getReceivedResults, boost::ref(controller))))
339 ));
340 registrator(new ControllerCommand("receivempqc",
341 boost::assign::list_of< ControllerCommand::commands_t >
342 (boost::bind(&FragmentController_JobIdProxy::setJobids,
343 boost::ref(controller), boost::cref(CI.ids)))
344 (boost::bind(&FragmentController::receiveResults,
345 boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport)))
346 (boost::bind(&printReceivedMPQCResults,
347 boost::bind(&FragmentController::getReceivedResults, boost::ref(controller)),
348 boost::cref(CI.fragmentpath),
349 boost::bind(&getNoAtomsFromAdjacencyFile, boost::cref(CI.fragmentpath))))
350 ));
351}
352
353void controller_MPQCCommandJob::addSpecificOptions(
354 boost::program_options::options_description_easy_init option)
355{
356 option
357 ("executable", boost::program_options::value< std::string >(), "executable for commands 'createjobs'")
358 ("fragment-path", boost::program_options::value< std::string >(), "path to fragment files for 'receivempqc'")
359 ("jobfiles", boost::program_options::value< std::vector< std::string > >()->multitoken(), "list of files as single argument toexecutable for 'addjobs'")
360 ("ids", boost::program_options::value< std::vector< JobId_t > >()->multitoken(), "list of jobids to request from server for 'receivempqc'")
361 ;
362}
363
364int controller_MPQCCommandJob::addOtherParsings(
365 ControllerOptions &ControllerInfo,
366 boost::program_options::variables_map &vm)
367{
368 ControllerOptions_MPQCCommandJob &CI =
369 reinterpret_cast<ControllerOptions_MPQCCommandJob &>(ControllerInfo);
370 int status = 0;
371 status = CI.parseExecutable(vm);
372 if (status) return status;
373 status = CI.parseFragmentpath(vm);
374 if (status) return status;
375 status = CI.parseJobfiles(vm);
376 if (status) return status;
377 status = CI.parseIds(vm);
378 return status;
379}
Note: See TracBrowser for help on using the repository browser.