- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Actions/FragmentationAction/FragmentationAutomationAction.cpp
r94d5ac6 rdb6f7d 39 39 #include "CodePatterns/MemDebug.hpp" 40 40 41 #include <boost/mpl/remove.hpp> 42 #include <boost/lambda/lambda.hpp> 43 44 #include "CodePatterns/Assert.hpp" 41 45 #include "CodePatterns/Info.hpp" 42 46 #include "CodePatterns/Log.hpp" 43 #include "JobMarket/Controller/FragmentController.hpp"44 47 #include "JobMarket/Jobs/FragmentJob.hpp" 45 48 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" 47 56 #include "Fragmentation/EnergyMatrix.hpp" 48 57 #include "Fragmentation/ForceMatrix.hpp" 49 58 #include "Fragmentation/Fragmentation.hpp" 59 #include "Fragmentation/SetValues/Fragment.hpp" 60 #include "Fragmentation/SetValues/Histogram.hpp" 61 #include "Fragmentation/SetValues/IndexedVectors.hpp" 50 62 #include "Fragmentation/HydrogenSaturation_enum.hpp" 63 #include "Fragmentation/KeySet.hpp" 51 64 #include "Fragmentation/KeySetsContainer.hpp" 65 #include "Fragmentation/Summation/writeTable.hpp" 52 66 #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 55 79 #include "World.hpp" 56 80 81 #include <fstream> 57 82 #include <iostream> 58 83 #include <string> 59 84 #include <vector> 85 86 #include <boost/mpl/for_each.hpp> 60 87 61 88 #include "Actions/FragmentationAction/FragmentationAutomationAction.hpp" … … 74 101 { 75 102 return NULL; 76 }77 78 /** Creates a MPQCCommandJob with argument \a filename.79 *80 * @param jobs created job is added to this vector81 * @param command mpqc command to execute82 * @param filename filename being argument to job83 * @param nextid id for this job84 */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+".");100 103 } 101 104 … … 130 133 131 134 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 136 141 * @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 137 145 */ 138 bool printReceivedMPQCResults( 139 const std::vector<FragmentResult::ptr> &results, 140 const std::string &KeySetFilename, 141 size_t NoAtoms) 146 bool 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) 142 153 { 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)+"."); 188 162 // place results into EnergyMatrix ... 189 163 { 190 164 MatrixContainer::MatrixArray matrix; 191 165 matrix.resize(1); 192 matrix[0].resize(1, extractedData.energ y);166 matrix[0].resize(1, extractedData.energies.total); 193 167 if (!Energy.AddMatrix( 194 std::string("MPQCJob ")+toString( (*iter)->getId()),168 std::string("MPQCJob ")+toString(jobid), 195 169 matrix, 196 MatrixNrLookup[(*iter)->getId()])) {170 nriter->second)) { 197 171 ELOG(1, "Adding energy matrix failed."); 198 172 return false; … … 213 187 } 214 188 if (!Force.AddMatrix( 215 std::string("MPQCJob ")+toString( (*iter)->getId()),189 std::string("MPQCJob ")+toString(jobid), 216 190 matrix, 217 MatrixNrLookup[(*iter)->getId()])) {191 nriter->second)) { 218 192 ELOG(1, "Adding force matrix failed."); 219 193 return false; … … 234 208 return false; 235 209 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 */ 220 bool 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 } 236 263 237 264 // 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 244 265 if (!KeySet.ParseManyBodyTerms()) return false; 245 266 267 EnergyMatrix EnergyFragments; 268 ForceMatrix ForceFragments; 246 269 if (!EnergyFragments.AllocateMatrix(Energy.Header, Energy.MatrixCounter, Energy.RowCounter, Energy.ColumnCounter)) return false; 247 270 if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return false; … … 275 298 } 276 299 300 void 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 */ 311 void 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 277 382 Action::state_ptr FragmentationFragmentationAutomationAction::performCall() { 278 383 boost::asio::io_service io_service; 279 FragmentController controller(io_service);280 384 281 385 // TODO: Have io_service run in second thread and merge with current again eventually 282 386 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)) 304 488 return Action::failure; 305 } 489 debugcontroller.waitforResults(full_sample.size()); 490 debugcontroller.getResults(debugData); 491 Exitflag += debugcontroller.getExitflag(); 306 492 } 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 340 496 // Final phase: print result 341 497 { 342 498 LOG(1, "INFO: Parsing fragment files from " << params.path.get() << "."); 343 std::vector<FragmentResult::ptr> results = controller.getReceivedResults();344 499 printReceivedMPQCResults( 345 results,500 fragmentData, 346 501 params.path.get(), 347 502 getNoAtomsFromAdjacencyFile(params.path.get())); 348 503 } 349 size_t Exitflag = controller.getExitflag(); 504 #endif 350 505 351 506 return (Exitflag == 0) ? Action::success : Action::failure;
Note:
See TracChangeset
for help on using the changeset viewer.