00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <globalsearch/optimizer.h>
00017
00018 #include <globalsearch/macros.h>
00019 #include <globalsearch/optbase.h>
00020 #include <globalsearch/optimizerdialog.h>
00021 #include <globalsearch/queueinterface.h>
00022 #include <globalsearch/structure.h>
00023
00024 #include <openbabel/obconversion.h>
00025 #include <openbabel/mol.h>
00026
00027 #include <Eigen/Core>
00028
00029 #include <QtCore/QDebug>
00030 #include <QtCore/QDir>
00031 #include <QtCore/QReadLocker>
00032 #include <QtCore/QSettings>
00033 #include <QtCore/QString>
00034
00035 #define KCAL_PER_MOL_TO_EV 0.043364122
00036
00037 using namespace OpenBabel;
00038
00039 namespace GlobalSearch {
00040
00041 Optimizer::Optimizer(OptBase *parent, const QString &filename) :
00042 QObject(parent),
00043 m_opt(parent),
00044 m_hasDialog(true),
00045 m_dialog(0)
00046 {
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 m_stdinFilename = "";
00092 m_stdoutFilename = "";
00093 m_stderrFilename = "";
00094
00095
00096 m_idString = "Generic";
00097
00098 if (m_opt->queueInterface()) {
00099 updateQueueInterface();
00100 }
00101 connect(m_opt, SIGNAL(queueInterfaceChanged(QueueInterface*)),
00102 this, SLOT(updateQueueInterface()));
00103
00104 readSettings(filename);
00105 }
00106
00107 Optimizer::~Optimizer()
00108 {
00109 }
00110
00111 void Optimizer::readSettings(const QString &filename)
00112 {
00113
00114 if (filename.isEmpty()) {
00115 return;
00116 }
00117
00118 SETTINGS(filename);
00119
00120 readTemplatesFromSettings(filename);
00121 readUserValuesFromSettings(filename);
00122 readDataFromSettings(filename);
00123 }
00124
00125 void Optimizer::readTemplatesFromSettings(const QString &filename)
00126 {
00127 SETTINGS(filename);
00128
00129 QStringList filenames = getTemplateNames();
00130 for (int i = 0; i < filenames.size(); i++) {
00131 m_templates.insert(filenames.at(i),
00132 settings->value(m_opt->getIDString().toLower() +
00133 "/optimizer/" +
00134 getIDString() + "/" +
00135 filenames.at(i) + "_list",
00136 "").toStringList());
00137 }
00138
00139
00140 settings->beginGroup(m_opt->getIDString().toLower() +
00141 "/optimizer/" +
00142 getIDString() + "/QI/" +
00143 m_opt->queueInterface()->getIDString());
00144 filenames = m_QITemplates.keys();
00145 for (QStringList::const_iterator
00146 it = filenames.constBegin(),
00147 it_end = filenames.constEnd();
00148 it != it_end;
00149 ++it) {
00150 m_QITemplates.insert(*it,
00151 settings->value((*it) + "_list",
00152 "").toStringList());
00153 }
00154 settings->endGroup();
00155
00156 fixTemplateLengths();
00157
00158 DESTROY_SETTINGS(filename);
00159 }
00160
00161 void Optimizer::readUserValuesFromSettings(const QString &filename)
00162 {
00163 SETTINGS(filename);
00164
00165 settings->beginGroup(m_opt->getIDString().toLower() +
00166 "/optimizer/" +
00167 getIDString());
00168 m_user1 = settings->value("/user1", "").toString();
00169 m_user2 = settings->value("/user2", "").toString();
00170 m_user3 = settings->value("/user3", "").toString();
00171 m_user4 = settings->value("/user4", "").toString();
00172 settings->endGroup();
00173 }
00174
00175 void Optimizer::readDataFromSettings(const QString &filename)
00176 {
00177 SETTINGS(filename);
00178
00179 QStringList ids = getDataIdentifiers();
00180 for (int i = 0; i < ids.size(); i++) {
00181 m_data.insert(ids.at(i),
00182 settings->value(m_opt->getIDString().toLower() +
00183 "/optimizer/" +
00184 getIDString() + "/data/" +
00185 ids.at(i),
00186 ""));
00187 }
00188 }
00189
00190 void Optimizer::writeSettings(const QString &filename)
00191 {
00192
00193 if (filename.isEmpty()) {
00194 return;
00195 }
00196
00197 SETTINGS(filename);
00198
00199 writeTemplatesToSettings(filename);
00200 writeUserValuesToSettings(filename);
00201 writeDataToSettings(filename);
00202 if (m_opt->queueInterface()) {
00203 m_opt->queueInterface()->writeSettings(filename);
00204 }
00205
00206 DESTROY_SETTINGS(filename);
00207 }
00208
00209 void Optimizer::writeTemplatesToSettings(const QString &filename)
00210 {
00211 SETTINGS(filename);
00212 QStringList filenames = getTemplateNames();
00213 for (int i = 0; i < filenames.size(); i++) {
00214 settings->setValue(m_opt->getIDString().toLower() +
00215 "/optimizer/" +
00216 getIDString() + "/" +
00217 filenames.at(i) + "_list",
00218 m_templates.value(filenames.at(i)));
00219 }
00220
00221
00222 settings->beginGroup(m_opt->getIDString().toLower() +
00223 "/optimizer/" +
00224 getIDString() + "/QI/" +
00225 m_opt->queueInterface()->getIDString());
00226 filenames = m_QITemplates.keys();
00227 for (QStringList::const_iterator
00228 it = filenames.constBegin(),
00229 it_end = filenames.constEnd();
00230 it != it_end;
00231 ++it) {
00232 settings->setValue((*it) + "_list",
00233 m_QITemplates.value(*it));
00234 }
00235 settings->endGroup();
00236
00237 DESTROY_SETTINGS(filename);
00238 }
00239
00240 void Optimizer::writeUserValuesToSettings(const QString &filename)
00241 {
00242 SETTINGS(filename);
00243
00244 settings->setValue(m_opt->getIDString().toLower() +
00245 "/optimizer/" +
00246 getIDString() +
00247 "/user1",
00248 m_user1);
00249 settings->setValue(m_opt->getIDString().toLower() +
00250 "/optimizer/" +
00251 getIDString() +
00252 "/user2",
00253 m_user2);
00254 settings->setValue(m_opt->getIDString().toLower() +
00255 "/optimizer/" +
00256 getIDString() +
00257 "/user3",
00258 m_user3);
00259 settings->setValue(m_opt->getIDString().toLower() +
00260 "/optimizer/" +
00261 getIDString() +
00262 "/user4",
00263 m_user4);
00264 }
00265
00266 void Optimizer::writeDataToSettings(const QString &filename)
00267 {
00268 SETTINGS(filename);
00269 QStringList ids = getDataIdentifiers();
00270 for (int i = 0; i < ids.size(); i++) {
00271 settings->setValue(m_opt->getIDString().toLower() +
00272 "/optimizer/" +
00273 getIDString() +
00274 "/data/" +
00275 ids.at(i),
00276 m_data.value(ids.at(i)));
00277 }
00278 }
00279
00280 QHash<QString, QString>
00281 Optimizer::getInterpretedTemplates(Structure *structure)
00282 {
00283
00284 QReadLocker locker (structure->lock());
00285
00286
00287 int optStep = structure->getCurrentOptStep();
00288
00289 Q_ASSERT_X(optStep <= m_opt->optimizer()->getNumberOfOptSteps(),
00290 Q_FUNC_INFO, QString("OptStep of Structure %1 exceeds "
00291 "number of known OptSteps (%2, limit %3).")
00292 .arg(structure->getIDString()).arg(optStep)
00293 .arg(m_opt->optimizer()->getNumberOfOptSteps()).toStdString().c_str());
00294
00295
00296 QHash<QString, QString> hash;
00297 QStringList filenames = m_templates.keys();
00298 QString contents;
00299 for (QStringList::const_iterator
00300 it = filenames.constBegin(),
00301 it_end = filenames.constEnd();
00302 it != it_end;
00303 it++) {
00304 hash.insert((*it), m_opt->interpretTemplate(m_templates.value(*it)
00305 .at(optStep - 1),
00306 structure));
00307 }
00308
00309 filenames = m_QITemplates.keys();
00310 for (QStringList::const_iterator
00311 it = filenames.constBegin(),
00312 it_end = filenames.constEnd();
00313 it != it_end;
00314 it++) {
00315 hash.insert((*it), m_opt->interpretTemplate(m_QITemplates.value(*it)
00316 .at(optStep - 1),
00317 structure));
00318 }
00319
00320 return hash;
00321 }
00322
00323 QDialog* Optimizer::dialog()
00324 {
00325 if (!m_dialog) {
00326 m_dialog = new OptimizerConfigDialog (m_opt->dialog(),
00327 m_opt,
00328 this);
00329 }
00330 OptimizerConfigDialog *d =
00331 qobject_cast<OptimizerConfigDialog*>(m_dialog);
00332 d->updateGUI();
00333
00334 return d;
00335 }
00336
00337 void Optimizer::updateQueueInterface()
00338 {
00339 m_QITemplates.clear();
00340
00341 QStringList init;
00342 for (unsigned int i = 0; i < getNumberOfOptSteps(); ++i) {
00343 init << "";
00344 }
00345
00346 QStringList filenames = m_opt->queueInterface()->getTemplateFileNames();
00347 for (QStringList::const_iterator
00348 it = filenames.constBegin(),
00349 it_end = filenames.constEnd();
00350 it != it_end;
00351 ++it) {
00352 m_QITemplates.insert(*it, init);
00353 }
00354 }
00355
00356 bool Optimizer::checkIfOutputFileExists(Structure *s, bool *exists)
00357 {
00358 return m_opt->queueInterface()->checkIfFileExists(s,
00359 m_completionFilename,
00360 exists);
00361 }
00362
00363 bool Optimizer::checkForSuccessfulOutput(Structure *s, bool *success)
00364 {
00365 int ec;
00366 *success = false;
00367 for (QStringList::const_iterator
00368 it = m_completionStrings.constBegin(),
00369 it_end = m_completionStrings.constEnd();
00370 it != it_end;
00371 ++it) {
00372 if (!m_opt->queueInterface()->grepFile(s,
00373 (*it),
00374 m_completionFilename,
00375 0,
00376 &ec)) {
00377 return false;
00378 }
00379 if (ec == 0) {
00380 *success = true;
00381 return true;
00382 }
00383 }
00384 return true;
00385 }
00386
00387 bool Optimizer::update(Structure *structure)
00388 {
00389
00390 QWriteLocker locker (structure->lock());
00391
00392 structure->stopOptTimer();
00393
00394
00395 locker.unlock();
00396 bool ok = m_opt->queueInterface()->prepareForStructureUpdate(structure);
00397 locker.relock();
00398 if (!ok) {
00399 m_opt->warning(tr("Optimizer::update: Error while preparing to update structure %1")
00400 .arg(structure->getIDString()));
00401 return false;
00402 }
00403
00404
00405 ok = false;
00406 for (int i = 0; i < m_outputFilenames.size(); i++) {
00407 if (read(structure,
00408 structure->fileName() + "/" + m_outputFilenames.at(i))) {
00409 ok = true;
00410 break;
00411 }
00412 }
00413 if (!ok) {
00414 m_opt->warning(tr("Optimizer::Update: Error loading structure at %1")
00415 .arg(structure->fileName()));
00416 return false;
00417 }
00418
00419 structure->setJobID(0);
00420 locker.unlock();
00421 return true;
00422 }
00423
00424 bool Optimizer::load(Structure *structure)
00425 {
00426 QWriteLocker locker (structure->lock());
00427
00428
00429 bool ok = false;
00430 for (int i = 0; i < m_outputFilenames.size(); i++) {
00431 if (read(structure,
00432 structure->fileName() + "/" + m_outputFilenames.at(i))) {
00433 ok = true;
00434 break;
00435 }
00436 }
00437 if (!ok) {
00438 m_opt->warning(tr("Optimizer::load: Error loading structure at %1")
00439 .arg(structure->fileName()));
00440 return false;
00441 }
00442 return true;
00443 }
00444
00445 bool Optimizer::read(Structure *structure,
00446 const QString & filename) {
00447
00448 QFile file (filename);
00449 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
00450 return false;
00451 }
00452 file.close();
00453
00454
00455
00456
00457
00458 m_opt->sOBMutex->lock();
00459 OBConversion conv;
00460 OBFormat* inFormat = conv.FormatFromExt(QString(QFile::encodeName(filename.trimmed())).toAscii());
00461
00462 if ( !inFormat || !conv.SetInFormat( inFormat ) ) {
00463 m_opt->warning(tr("Optimizer::read: Error setting openbabel format for file %1")
00464 .arg(filename));
00465 m_opt->sOBMutex->unlock();
00466 return false;
00467 }
00468
00469 OBMol obmol;
00470 if (!conv.ReadFile( &obmol, QString(QFile::encodeName(filename)).toStdString())) {
00471 m_opt->error(tr("Cannot update structure %1 from file \n%2")
00472 .arg(structure->getIDString())
00473 .arg(QString(QFile::encodeName(filename))));
00474 m_opt->sOBMutex->unlock();
00475 return false;
00476 }
00477 m_opt->sOBMutex->unlock();
00478
00479
00480 if (obmol.NumAtoms() == 0)
00481 return false;
00482
00483
00484 double energy=0.0;
00485 double enthalpy=0.0;
00486 QList<unsigned int> atomicNums;
00487 QList<Eigen::Vector3d> coords;
00488 Eigen::Matrix3d cellMat = Eigen::Matrix3d::Zero();
00489
00490
00491 FOR_ATOMS_OF_MOL(atm, obmol) {
00492 coords.append(Eigen::Vector3d(atm->x(), atm->y(), atm->z()));
00493 atomicNums.append(atm->GetAtomicNum());
00494 }
00495
00496
00497 if (obmol.HasData("Enthalpy (kcal/mol)")) {
00498 enthalpy = QString(obmol.GetData("Enthalpy (kcal/mol)")->GetValue().c_str()
00499 ).toDouble() * KCAL_PER_MOL_TO_EV;
00500 }
00501
00502
00503 energy = obmol.GetEnergy() * KCAL_PER_MOL_TO_EV;
00504
00505
00506 OBUnitCell *cell = static_cast<OBUnitCell*>(obmol.GetData(OBGenericDataType::UnitCell));
00507
00508 if (cell != NULL) {
00509 for (int i = 0; i < 3; i++) {
00510 for (int j = 0; j < 3; j++) {
00511 cellMat(i,j) = cell->GetCellMatrix().Get(i,j);
00512 }
00513 }
00514 }
00515
00516 if (m_opt->isStarting) {
00517 structure->updateAndSkipHistory(atomicNums, coords, energy, enthalpy, cellMat);
00518 }
00519 else {
00520 structure->updateAndAddToHistory(atomicNums, coords, energy, enthalpy, cellMat);
00521 }
00522
00523 return true;
00524 }
00525
00526 int Optimizer::getNumberOfOptSteps() {
00527 if (m_templates.isEmpty())
00528 return 0;
00529 else
00530 return m_templates.values().first().size();
00531 }
00532
00533 bool Optimizer::setTemplate(const QString &filename,
00534 const QString &templateData,
00535 int optStepIndex)
00536 {
00537 Q_ASSERT(m_templates.contains(filename) ||
00538 m_QITemplates.contains(filename));
00539 Q_ASSERT(optStepIndex >= 0 && optStepIndex < getNumberOfOptSteps());
00540
00541 resolveTemplateHash(filename)[filename][optStepIndex] = templateData;
00542 return true;
00543 }
00544
00545 bool Optimizer::setTemplate(const QString &filename,
00546 const QStringList &templateData)
00547 {
00548 Q_ASSERT(m_templates.contains(filename) ||
00549 m_QITemplates.contains(filename));
00550
00551 resolveTemplateHash(filename).insert(filename, templateData);
00552 return true;
00553 }
00554
00555
00556 QString Optimizer::getTemplate(const QString &filename,
00557 int optStepIndex)
00558 {
00559 Q_ASSERT(m_templates.contains(filename) ||
00560 m_QITemplates.contains(filename));
00561 Q_ASSERT(optStepIndex >= 0 && optStepIndex < getNumberOfOptSteps());
00562
00563 return resolveTemplateHash(filename)[filename][optStepIndex];
00564 }
00565
00566 QStringList Optimizer::getTemplate(const QString &filename)
00567 {
00568 Q_ASSERT(m_templates.contains(filename) ||
00569 m_QITemplates.contains(filename));
00570
00571 return resolveTemplateHash(filename)[filename];
00572 }
00573
00574 bool Optimizer::appendTemplate(const QString &filename,
00575 const QString &templateData)
00576 {
00577 Q_ASSERT(m_templates.contains(filename) ||
00578 m_QITemplates.contains(filename));
00579
00580 resolveTemplateHash(filename)[filename].append(templateData);
00581 return true;
00582 }
00583
00584 bool Optimizer::removeAllTemplatesForOptStep(int optStepIndex)
00585 {
00586 Q_ASSERT(optStepIndex >= 0 &&
00587 optStepIndex < getNumberOfOptSteps());
00588
00589
00590 QList<QString> templateKeys = m_templates.keys();
00591 QList<QString> QITemplateKeys = m_QITemplates.keys();
00592 for (QStringList::const_iterator
00593 it = templateKeys.constBegin(),
00594 it_end = templateKeys.constEnd();
00595 it != it_end; ++it) {
00596 m_templates[*it].removeAt(optStepIndex);
00597 }
00598 for (QStringList::const_iterator
00599 it = QITemplateKeys.constBegin(),
00600 it_end = QITemplateKeys.constEnd();
00601 it != it_end; ++it) {
00602 m_QITemplates[*it].removeAt(optStepIndex);
00603 }
00604
00605 return true;
00606 }
00607
00608 bool Optimizer::setData(const QString &identifier, const QVariant &data)
00609 {
00610 Q_ASSERT(m_data.contains(identifier));
00611
00612 m_data.insert(identifier, data);
00613 return true;
00614 }
00615
00616 QVariant Optimizer::getData(const QString &identifier)
00617 {
00618 Q_ASSERT(m_data.contains(identifier));
00619
00620 return m_data.value(identifier);
00621 }
00622
00623 QHash<QString, QStringList> &
00624 Optimizer::resolveTemplateHash(const QString &filename)
00625 {
00626 if (m_templates.contains(filename)) {
00627 return m_templates;
00628 }
00629 else if (m_QITemplates.contains(filename)) {
00630 return m_QITemplates;
00631 }
00632 else {
00633 qFatal("In %s:\n\t%s '%s'\n",
00634 Q_FUNC_INFO,
00635 "No current template contains file",
00636 filename.toStdString().c_str());
00637 }
00638
00639 Q_ASSERT(false);
00640 return *(new QHash<QString, QStringList>());
00641 }
00642
00643 const QHash<QString, QStringList> &
00644 Optimizer::resolveTemplateHash(const QString &filename) const
00645 {
00646 if (m_templates.contains(filename)) {
00647 return m_templates;
00648 }
00649 else if (m_QITemplates.contains(filename)) {
00650 return m_QITemplates;
00651 }
00652 else {
00653 qFatal("In %s:\n\t%s '%s'\n",
00654 Q_FUNC_INFO,
00655 "No current template contains file",
00656 filename.toStdString().c_str());
00657 }
00658
00659 Q_ASSERT(false);
00660 return *(new QHash<QString, QStringList>());
00661 }
00662
00663 void Optimizer::fixTemplateLengths()
00664 {
00665 int steps = getNumberOfOptSteps();
00666 if (steps < 1) {
00667 steps = 1;
00668 }
00669
00670
00671 QStringList filenames = m_templates.keys();
00672 for (QStringList::const_iterator
00673 it = filenames.constBegin(),
00674 it_end = filenames.constEnd();
00675 it != it_end;
00676 ++it) {
00677 QStringList ¤t = m_templates[*it];
00678 while (current.size() > steps) {
00679 current.removeLast();
00680 }
00681 while (current.size() < steps) {
00682 current << "";
00683 }
00684 }
00685
00686
00687 filenames = m_QITemplates.keys();
00688 for (QStringList::const_iterator
00689 it = filenames.constBegin(),
00690 it_end = filenames.constEnd();
00691 it != it_end;
00692 ++it) {
00693 QStringList ¤t = m_QITemplates[*it];
00694 while (current.size() > steps) {
00695 current.removeLast();
00696 }
00697 while (current.size() < steps) {
00698 current << "";
00699 }
00700 }
00701 }
00702
00703 }