00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00019
00025
00026
00027
00029
00030
00031 #include <cmath>
00032
00033
00034 #include <qapplication.h>
00035 #include <qcheckbox.h>
00036 #include <qcombobox.h>
00037 #include <qcursor.h>
00038 #include <qdir.h>
00039 #include <qdom.h>
00040 #include <qlabel.h>
00041 #include <qlayout.h>
00042 #include <qlistview.h>
00043 #include <qmessagebox.h>
00044 #include <qpixmap.h>
00045 #include <qpopupmenu.h>
00046 #include <qprogressbar.h>
00047 #include <qnamespace.h>
00048 #include <qrect.h>
00049 #include <qsplitter.h>
00050 #include <qstringlist.h>
00051 #include <qtextedit.h>
00052 #include <qtimer.h>
00053 #include <qwhatsthis.h>
00054
00055
00056 #include "atomset.h"
00057 #include "brabobase.h"
00058 #include "calculation.h"
00059 #include "crdfactory.h"
00060 #include "domutils.h"
00061 #include "glmoleculeview.h"
00062 #include "globalbase.h"
00063 #include "iconsets.h"
00064 #include "moleculepropertieswidget.h"
00065 #include "outputchooserwidget.h"
00066 #include "paths.h"
00067 #include "relaxbase.h"
00068 #include "statustext.h"
00069 #include "textviewwidget.h"
00070 #include "xbraboview.h"
00071 #include "version.h"
00072
00073 #if defined(USE_KMDI) || defined(USE_KMDI_DLL)
00074 #define QextMdiChildView KMdiChildView
00075 #endif
00076
00080
00082 XbraboView::XbraboView(QWidget* mainWin, QWidget* parent, QString title, const char* name, WFlags f) : QextMdiChildView( title, parent, name, f),
00083 globalSetup(0),
00084 braboSetup(0),
00085 relaxSetup(0),
00086 mainWindow(mainWin),
00087 calcDate(QDateTime::currentDateTime(Qt::UTC).toString(Qt::ISODate)),
00088 calculation(0)
00092 {
00093 calcCounter++;
00094 calcDefaultName = tr("unnamed") + QString::number(calcCounter);
00095 calcFileName = calcDefaultName;
00096
00098
00099
00100
00101
00103 atoms = new AtomSet();
00104
00106 BigLayout = new QVBoxLayout(this,10);
00107 Splitter = new QSplitter(this, 0);
00108 Splitter->setOrientation(QSplitter::Vertical);
00109 Splitter->setOpaqueResize(true);
00110 MoleculeView = new GLMoleculeView(atoms, Splitter);
00111 MoleculeView->setSizePolicy(QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding, false));
00112 QWidget* LayoutWidget = new QWidget(Splitter);
00113 StatusLayout = new QVBoxLayout(LayoutWidget,0);
00114 TextLabelStatus = new QLabel(LayoutWidget);
00115 TextLabelStatus->setText(tr("Status"));
00116 TextEditStatus = new StatusText(LayoutWidget);
00117 StatusLayout->addWidget(TextLabelStatus);
00118 StatusLayout->addWidget(TextEditStatus);
00119 BigLayout->addWidget(Splitter);
00120 ProgressLayout = new QHBoxLayout(BigLayout);
00121 TextLabelProgress = new QLabel(this);
00122 TextLabelProgress->setText(tr("Progress"));
00123 ProgressBar = new QProgressBar(this);
00124 ProgressBar->setCenterIndicator(true);
00125 ProgressLayout->addWidget(TextLabelProgress);
00126 ProgressLayout->addWidget(ProgressBar);
00127
00128 MoleculeView->resize(MoleculeView->width(),350);
00129 MoleculeView->resetView();
00130
00132 connect(TextEditStatus, SIGNAL(rightButtonClicked()),this, SLOT(popup()));
00133 #if defined(USE_KMDI) || defined(USE_KMDI_DLL)
00134 connect(this, SIGNAL(gotFocus(KMdiChildView*)), this, SIGNAL(changed()));
00135 #else
00136 connect(this, SIGNAL(gotFocus(QextMdiChildView*)), this, SIGNAL(changed()));
00137 #endif
00138 connect(MoleculeView, SIGNAL(modified()), this, SLOT(setModified()));
00139 connect(MoleculeView, SIGNAL(changed()), this, SIGNAL(changed()));
00140
00142 QWhatsThis::add(MoleculeView,
00143 tr("<p>Shows the molecular system in 3D. Pressing the right mouse button "
00144 "opens a context menu containing the most frequently used actions from the "
00145 "Molecule menu.</p>"
00146 "<p>The scene can be manipulated with the mouse and the keyboard. Here follows "
00147 "a list of possible manipulations and ways to invoke them. Directions are indicated "
00148 "either by the arrow keys or by dragging the mouse in the desired direction while "
00149 "pressing the left mouse button.</p>"
00150 "<ul>"
00151 "<li>Rotate around the X-axis: <em>Up</em> and <em>Down</em>"
00152 "<li>Rotate around the Y-axis: <em>Left</em> and <em>Right</em>"
00153 "<li>Rotate around the Z-axis: <em>Shift+Left</em> and <em>Shift+Right</em>"
00154 "<li>Zoom: <em>Shift+Up</em> and <em>Shift+Down</em> or using the scrollwheel of the mouse"
00155 "<li>Translate horizontally: <em>Ctrl+Left</em> and <em>Ctrl+Right</em>"
00156 "<li>Translate vertically: <em>Ctrl+Up</em> and <em>Ctrl+Down</em>"
00157 "</ul>"
00158 "<p>Atoms can be selected/deselected by clicking on them with the left mouse button. When a "
00159 "selection is present, all actions shown above can be applied to the selection only. This can "
00160 "be done either by holding the <em>Alt</em> modifier or selecting the <em>Manipulate Selection</em> "
00161 "button/menu-entry. Using the scrollwheel of the mouse will still zoom the entire system.</p>"
00162 "<p>When a bond, angle or torsion angle is selected, the internal coordinate (whose value is always visible) "
00163 "can be altered by using <em>Ctrl+Shift+Left</em> and <em>Ctrl+Shift+Right</em>.</p>"
00164 ));
00165 QWhatsThis::add(TextEditStatus,
00166 tr("<p>Shows a log of informational messages mostly when a calculation is running. Results presented "
00167 "here will not be saved but are always accessible through other means. Data can, however, be "
00168 "copied using the standard <em>Copy</em> action.</p><p>The size of this box can be changed by dragging "
00169 "the bar between this box and the 3D view above (not visible in all skins).</p>"));
00170 QWhatsThis::add(ProgressBar,
00171 tr("Indicates the progress of a running calculation. It will be reset shortly after a calculation has finished."));
00172
00174 setModified(false);
00175 }
00176
00178 XbraboView::~XbraboView()
00180 {
00181 delete atoms;
00182 }
00183
00185 unsigned int XbraboView::calculationType() const
00191 {
00192 if(globalSetup == 0)
00193 return GlobalBase::SinglePointEnergy;
00194
00195 return globalSetup->calculationType();
00196 }
00197
00199 unsigned int XbraboView::buurType() const
00204 {
00205 if(globalSetup == 0)
00206 return GlobalBase::NoBuur;
00207
00208 return globalSetup->buurType();
00209 }
00210
00212 bool XbraboView::isModified() const
00214 {
00215 return calcModified;
00216 }
00217
00218
00219
00221
00222
00223
00224
00226 QString XbraboView::name() const
00228 {
00229 if(globalSetup == 0)
00230 return calcDefaultName;
00231
00232 return globalSetup->name();
00233 }
00234
00236 QString XbraboView::fileName() const
00238 {
00239 return calcFileName;
00240 }
00241
00243 QString XbraboView::directory() const
00245 {
00246 if(globalSetup == 0)
00247 return QDir::convertSeparators(QDir::homeDirPath()) + QDir::separator() + calcDefaultName;
00248
00249 return globalSetup->directory();
00250 }
00251
00253 bool XbraboView::isRunning() const
00255 {
00256 if(calculation == 0)
00257 return false;
00258
00259 return calculation->isRunning();
00260 }
00261
00263 bool XbraboView::isPaused() const
00265 {
00266 if(calculation == 0)
00267 return false;
00268
00269 return calculation->isPaused();
00270 }
00271
00272
00273
00275
00276
00277
00278
00280 void XbraboView::cut()
00284 {
00285 TextEditStatus->cut();
00286 }
00287
00289 void XbraboView::copy()
00292 {
00293 TextEditStatus->copy();
00294 }
00295
00297 void XbraboView::paste()
00301 {
00302 TextEditStatus->paste();
00303 }
00304
00306 GLMoleculeView* XbraboView::moleculeView() const
00308 {
00309 return MoleculeView;
00310 }
00311
00313 bool XbraboView::loadCML(const QDomDocument* doc)
00315 {
00317 QDomElement root = doc->documentElement();
00318 if(root.tagName() != "cml")
00319 {
00320 QMessageBox::warning(this, Version::appName, tr("The selected file is a regular CML file"), QMessageBox::Ok, QMessageBox::NoButton);
00321 return false;
00322 }
00324 if(root.attribute("xmlns:" + DomUtils::ns) != DomUtils::uriDict10)
00325 {
00326
00327
00328
00329 QMessageBox::warning(this, Version::appName, tr("The selected file does not contain the correct version indicator."), QMessageBox::Ok, QMessageBox::NoButton);
00330 return false;
00331 }
00333 QDomNode metaNode = root.namedItem("metadataList");
00334 if(!metaNode.isNull())
00335 {
00336 QDomNode childNode = metaNode.firstChild();
00337 while(!childNode.isNull())
00338 {
00339 if(childNode.isElement() && childNode.toElement().tagName() == "metadata" && childNode.toElement().attribute("name") == "dc:date")
00340 {
00341 calcDate = childNode.toElement().attribute("content");
00342 break;
00343 }
00344 childNode = childNode.nextSibling();
00345 }
00346 }
00347
00348 TextEditStatus->append(tr("Loading data"));
00351 QDomElement section = root.namedItem("molecule").toElement();
00352 if(section.isNull())
00353 TextEditStatus->append("<font color=red>" + tr(" ...no coordinates found while loading") + "</font>");
00354 else
00355 {
00356 TextEditStatus->append(tr(" ...loading coordinates"));
00357 atoms->loadCML(§ion);
00358 }
00360 root = root.namedItem("parameterList").toElement();
00361 if(root.attribute("dictRef") != DomUtils::ns + ":settings")
00362 {
00363 TextEditStatus->append("<font color=red>" + tr(" ...no calculation related information found while loading") + "</font>");
00364 }
00365 else
00366 {
00367 section = root.firstChild().toElement();
00368 while(!section.isNull() && section.tagName() == "parameterList")
00369 {
00370 if(section.attribute("dictRef") == DomUtils::ns + ":geometry")
00371 {
00373 {
00374 TextEditStatus->append(tr(" ...setting geometry"));
00375 loadCMLLocal(§ion);
00376 }
00377 }
00378 else if(section.attribute("dictRef") == DomUtils::ns + ":view")
00379 {
00381 {
00382 TextEditStatus->append(tr(" ...loading view data"));
00383 MoleculeView->loadCML(§ion);
00384 }
00385 }
00386 else if(section.attribute("dictRef") == DomUtils::ns + ":global")
00387 {
00389 {
00390 TextEditStatus->append(tr(" ...loading Global data"));
00391 initGlobalSetup();
00392 globalSetup->loadCML(§ion);
00393 }
00394 }
00395 else if(section.attribute("dictRef") == DomUtils::ns + ":energy_and_forces")
00396 {
00398 {
00399 TextEditStatus->append(tr(" ...loading Energy & Forces data"));
00400 initBraboSetup();
00401 braboSetup->loadCML(§ion);
00402 }
00403 }
00404 else if(section.attribute("dictRef") == DomUtils::ns + ":geometry_optimization")
00405 {
00407 {
00408 TextEditStatus->append(tr(" ...loading Geometry Optimization data"));
00409 initRelaxSetup();
00410 relaxSetup->loadCML(§ion);
00411 }
00412 }
00413 else if(section.attribute("dictRef") == DomUtils::ns + ":calculation")
00414 {
00416 {
00417 TextEditStatus->append(tr(" ...loading Calculation data"));
00418 bool ok = initCalculation();
00419 calculation->loadCML(§ion);
00420 if(!ok)
00421 calculation->stop();
00422 }
00423 }
00424 section = section.nextSibling().toElement();
00425 }
00426 TextEditStatus->append(tr("Loading done"));
00427 }
00428
00429 updateBraboSetup();
00430 updateRelaxSetup();
00431 setModified(false);
00432 return true;
00433 }
00434
00436 QDomDocument* XbraboView::saveCML()
00438 {
00439 QDomDocument* doc = new QDomDocument();
00441 QDomProcessingInstruction instr = doc->createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
00442 doc->appendChild(instr);
00444
00445
00446
00448 QDomElement root = doc->createElement("cml");
00449 root.setAttribute("xmlns", DomUtils::uriNSCML);
00450 root.setAttribute("xmlns:" + DomUtils::nsCMLM, DomUtils::uriDictCMLM);
00451 root.setAttribute("xmlns:" + DomUtils::ns, DomUtils::uriDict10);
00452 root.setAttribute("xmlns:" + DomUtils::nsXSD, DomUtils::uriDictXSD);
00453 root.setAttribute("xmlns:" + DomUtils::nsAtomic, DomUtils::uriDictAtomic);
00454 root.setAttribute("xmlns:" + DomUtils::nsSI, DomUtils::uriDictSI);
00455 root.setAttribute("xmlns:" + DomUtils::nsDC, DomUtils::uriNSDC);
00456
00457 doc->appendChild(root);
00459 QDomElement childNode = doc->createElement("metadataList");
00460 childNode.setAttribute("title", "Generated by " + Version::appName);
00461 root.appendChild(childNode);
00462 QDomElement grandChildNode = doc->createElement("metadata");
00463 grandChildNode.setAttribute("name", DomUtils::nsDC + ":creator");
00464 grandChildNode.setAttribute("content", Version::appName + " " + Version::appVersion);
00465 childNode.appendChild(grandChildNode);
00466 grandChildNode = doc->createElement("metadata");
00467 childNode.appendChild(grandChildNode);
00468 grandChildNode.setAttribute("name", DomUtils::nsDC + ":description");
00469 grandChildNode.setAttribute("content", Version::appName + " Calculation File");
00470 grandChildNode = doc->createElement("metadata");
00471 grandChildNode.setAttribute("content", calcDate);
00472 grandChildNode.setAttribute("name", DomUtils::nsDC + ":date");
00473 childNode.appendChild(grandChildNode);
00475 childNode = doc->createElement("molecule");
00476 root.appendChild(childNode);
00477 atoms->saveCML(&childNode);
00479 childNode = doc->createElement("parameterList");
00480 childNode.setAttribute("dictRef", DomUtils::ns + ":settings");
00481 childNode.setAttribute("title", Version::appName + " specific data");
00482 root.appendChild(childNode);
00484 grandChildNode = doc->createElement("parameterList");
00485 grandChildNode.setAttribute("dictRef", DomUtils::ns + ":geometry");
00486 childNode.appendChild(grandChildNode);
00487 saveCMLLocal(&grandChildNode);
00489 grandChildNode = doc->createElement("parameterList");
00490 grandChildNode.setAttribute("dictRef", DomUtils::ns + ":view");
00491 childNode.appendChild(grandChildNode);
00492 MoleculeView->saveCML(&grandChildNode);
00494 if(globalSetup != 0)
00495 {
00496 grandChildNode = doc->createElement("parameterList");
00497 grandChildNode.setAttribute("dictRef", DomUtils::ns + ":global");
00498 childNode.appendChild(grandChildNode);
00499 globalSetup->saveCML(&grandChildNode);
00500 }
00501 if(braboSetup != 0)
00502 {
00503 grandChildNode = doc->createElement("parameterList");
00504 grandChildNode.setAttribute("dictRef", DomUtils::ns + ":energy_and_forces");
00505 childNode.appendChild(grandChildNode);
00506 braboSetup->saveCML(&grandChildNode);
00507 }
00508 if(relaxSetup != 0)
00509 {
00510 grandChildNode = doc->createElement("parameterList");
00511 grandChildNode.setAttribute("dictRef", DomUtils::ns + ":geometry_optimization");
00512 childNode.appendChild(grandChildNode);
00513 relaxSetup->saveCML(&grandChildNode);
00514 }
00516 if(calculation != 0)
00517 {
00518 grandChildNode = doc->createElement("parameterList");
00519 grandChildNode.setAttribute("dictRef", DomUtils::ns + ":calculation");
00520 childNode.appendChild(grandChildNode);
00521 calculation->saveCML(&grandChildNode);
00522 }
00523 return doc;
00524 }
00525
00527 void XbraboView::setFileName(const QString filename)
00529 {
00530 calcFileName = filename;
00531 updateCaptions();
00532 }
00533
00537
00539 void XbraboView::setModified(bool state)
00542 {
00543 calcModified = state;
00544 if(!state)
00545 {
00546
00547
00548 MoleculeView->setModified(false);
00549 if(calculation != 0)
00550 calculation->setModified(false);
00551 }
00552 updateCaptions();
00553 emit changed();
00554 }
00555
00557 void XbraboView::moleculeReadCoordinates()
00559 {
00560 QString filename;
00561 unsigned int result = CrdFactory::readFromFile(atoms, filename);
00562 switch(result)
00563 {
00564 case CrdFactory::OK:
00565 setModified();
00566 MoleculeView->updateAtomSet(true);
00567 if(calculation != 0)
00568 calculation->setContinuable(false);
00569 TextEditStatus->append(tr("New coordinates read: ") + QString::number(atoms->count()) + tr(" atoms"));
00570 break;
00571 case CrdFactory::UnknownExtension:
00572 QMessageBox::warning(this, tr("Unknown format"), "The file " + filename + " has an unknown extension", QMessageBox::Ok, QMessageBox::NoButton);
00573 break;
00574 case CrdFactory::ErrorOpen:
00575 QMessageBox::warning(this, tr("Error opening file"), "The file " + filename + " could not be opened for reading", QMessageBox::Ok, QMessageBox::NoButton);
00576 break;
00577 case CrdFactory::ErrorRead:
00578 QMessageBox::warning(this, tr("Parse error"), "The contents of the file " + filename + " could not be parsed correctly", QMessageBox::Ok, QMessageBox::NoButton);
00579 break;
00580 case CrdFactory::UnknownFormat:
00581 QMessageBox::warning(this, tr("Unknown format"), "The format (normal/extended) of the file " + filename + " could not be detected correctly", QMessageBox::Ok, QMessageBox::NoButton);
00582 break;
00583 }
00584 }
00585
00587 void XbraboView::moleculeSaveCoordinates()
00589 {
00590 unsigned short int result = CrdFactory::writeToFile(atoms);
00591 switch(result)
00592 {
00593 case CrdFactory::UnknownExtension:
00594 QMessageBox::warning(this, tr("Unknown format"), tr("The file has an unknown extension"), QMessageBox::Ok, QMessageBox::NoButton);
00595 break;
00596 case CrdFactory::ErrorOpen:
00597 QMessageBox::warning(this, tr("Error opening file"), tr("The file could not be opened for writing"), QMessageBox::Ok, QMessageBox::NoButton);
00598 break;
00599 case CrdFactory::ErrorWrite:
00600 QMessageBox::warning(this, tr("Error writing file"), tr("The file could not be written"), QMessageBox::Ok, QMessageBox::NoButton);
00601 break;
00602 }
00603 }
00604
00606 void XbraboView::moleculeFPS()
00608 {
00609 TextEditStatus->append(tr("Frames per second: ") + QString::number(MoleculeView->calculateFPS()));
00610 }
00611
00613 void XbraboView::setupGlobal()
00615 {
00616 initGlobalSetup();
00617 if(globalSetup->exec() == QDialog::Accepted)
00618 {
00620 setModified();
00621 updateBraboSetup();
00622 updateRelaxSetup();
00623 updateCaptions();
00624 }
00625 }
00626
00628 void XbraboView::setupBrabo()
00630 {
00631 initBraboSetup();
00632 if(braboSetup->exec() == QDialog::Accepted)
00633 {
00634 setModified();
00635 if(calculation != 0 && calculation->isRunning() && globalSetup->calculationType() != GlobalBase::SinglePointEnergy
00636 && globalSetup->calculationType() != GlobalBase::EnergyAndForces)
00637 {
00638 bool ok;
00639 QStringList basissetList = braboSetup->basissets(ok);
00640 if(!ok)
00641 return;
00642 QString atdens = braboSetup->generateAtdens(ok);
00643 if(!ok)
00644 return;
00645
00647 bool prefer;
00648 unsigned int size1, size2;
00649 QString startVector = braboSetup->startVector(prefer, size1, size2);
00650
00651 if(size1 == 0)
00652 return;
00653 calculation->setBraboInput(braboSetup->generateInput(BraboBase::BRABO), basissetList, startVector, prefer, size1, size2);
00654 calculation->setStockInput(braboSetup->generateInput(BraboBase::STOCK), atdens);
00655 }
00656 }
00657 }
00658
00660 void XbraboView::setupRelax()
00662 {
00663 initRelaxSetup();
00664 if(relaxSetup->exec() == QDialog::Accepted)
00665 {
00666 setModified();
00667 if(calculation != 0 && calculation->isRunning() && globalSetup->calculationType() == GlobalBase::GeometryOptimization)
00668 {
00670 std::vector<unsigned int> steps;
00671 std::vector<double> factors;
00672 relaxSetup->scaleFactors(steps, factors);
00673 calculation->setRelaxInput(relaxSetup->generateInput(RelaxBase::AFF), relaxSetup->generateInput(RelaxBase::MAFF),
00674 relaxSetup->inputGenerationFrequency(), relaxSetup->maxSteps(), steps, factors);
00675 }
00676 }
00677 }
00678
00680 void XbraboView::setupFreq()
00682 {
00683 }
00684
00686 void XbraboView::setupBuur()
00688 {
00689 }
00690
00692 void XbraboView::start()
00694 {
00695 if(calculation != 0 && calculation->isRunning())
00696 {
00697 if(calculation->isPaused())
00698 TextEditStatus->append("<font color=blue>" + tr("Calculation unpaused") + "</font>");
00699 calculation->start();
00700 emit changed();
00701 return;
00702 }
00703
00704
00706 if(!initCalculation())
00707 return;
00708
00710 if(calculation->start())
00711 globalSetup->allowChanges(false);
00712 else
00713 return;
00714
00716 TextEditStatus->append("<font color=blue>" + tr("Calculation started") + "</font>");
00717 QString tempItem = " * " + tr("Type") + ": ";
00718 unsigned int calcType = globalSetup->calculationType();
00719 switch(calcType)
00720 {
00721 case GlobalBase::SinglePointEnergy: tempItem += tr("Single Point Energy");
00722 break;
00723 case GlobalBase::EnergyAndForces: tempItem += tr("Energy & Forces");
00724 break;
00725 case GlobalBase::GeometryOptimization: tempItem += tr("Geometry Optimization");
00726 break;
00727 }
00728 TextEditStatus->append(tempItem);
00729 TextEditStatus->append(" * " + tr("Method") + ": " + braboSetup->method());
00730 if(calcType == GlobalBase::GeometryOptimization)
00731 TextEditStatus->append(" * " + tr("Optimization step") + " 1");
00732 TextEditStatus->append(" - " + tr("Calculating energy"));
00733
00734
00735 ProgressBar->reset();
00736 unsigned int numSteps = braboSetup->maxIterations();
00737 if(calcType != GlobalBase::SinglePointEnergy)
00738 numSteps *= 2;
00739 if(calcType == GlobalBase::GeometryOptimization)
00740 {
00741 unsigned int calcMaxSteps = relaxSetup->maxSteps();
00742 if(calcMaxSteps == 0)
00743 numSteps *= 3*atoms->count();
00744 else
00745 numSteps *= calcMaxSteps;
00746 }
00747 ProgressBar->setTotalSteps(numSteps);
00748 lastProgress = 0;
00749 ProgressBar->setProgress(lastProgress);
00750 emit changed();
00751 }
00752
00754 void XbraboView::pause()
00756 {
00757 if(calculation != 0)
00758 {
00759 if(calculation->pause())
00760 {
00761
00762 if(calculation->isPaused())
00763 TextEditStatus->append("<font color=blue>" + tr("Calculation paused") + "</font>" + tr("(effective after the current step)"));
00764 else
00765 TextEditStatus->append("<font color=blue>" + tr("Calculation unpaused") + "</font>");
00766 emit changed();
00767 }
00768 }
00769 }
00770
00772 void XbraboView::stop()
00774 {
00775 if(calculation != 0)
00776 {
00777 calculation->stop();
00778 emit changed();
00779 }
00780 }
00781
00783 void XbraboView::writeInput()
00785 {
00786 if(!initCalculation())
00787 return;
00788
00789 calculation->writeInput();
00790
00791
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805 }
00806
00808 void XbraboView::cleanCalculation()
00810 {
00811 if(calculation == 0 || calculation->isRunning())
00812 return;
00813 if(QMessageBox::information(this, "Clean up calculation", "This will remove all files pertaining to the calculation from the calculation directory", "Clean", "Cancel", QString::null, 0, 1) == 0)
00814 calculation->clean();
00815 }
00816
00818 void XbraboView::viewOutput()
00820 {
00822 OutputChooserWidget* outputChooser = new OutputChooserWidget(this, 0, true, 0);
00823 outputChooser->ListView->setSorting(-1);
00824 QPixmap pixmapPresent = IconSets::getPixmap(IconSets::OK);
00825
00826 if(calculation)
00827 {
00829 QListViewItem* item = new QListViewItem(outputChooser->ListView);
00830 item->setText(0, tr("last"));
00831 if(!calculation->braboOutput().isEmpty())
00832 item->setPixmap(1, pixmapPresent);
00833 if(!calculation->stockOutput().isEmpty())
00834 item->setPixmap(2, pixmapPresent);
00835 if(!calculation->relaxOutput().isEmpty())
00836 item->setPixmap(3, pixmapPresent);
00837 if(!calculation->affOutput().isEmpty())
00838 item->setPixmap(4, pixmapPresent);
00839
00841 vector<unsigned int> cycles;
00842 vector<bool> savedBrabo, savedStock, savedRelax, savedAFF;
00843 calculation->getAvailableOutputs(cycles, savedBrabo, savedStock, savedRelax, savedAFF);
00844 for(unsigned int i = 0; i < cycles.size(); i++)
00845 {
00846 item = new QListViewItem(outputChooser->ListView, item);
00847 item->setText(0, QString::number(cycles[i]));
00848 if(savedBrabo[i])
00849 item->setPixmap(1, pixmapPresent);
00850 if(savedStock[i])
00851 item->setPixmap(2, pixmapPresent);
00852 if(savedRelax[i])
00853 item->setPixmap(3, pixmapPresent);
00854 if(savedAFF[i])
00855 item->setPixmap(4, pixmapPresent);
00856 }
00857 }
00858
00860 connect(outputChooser->ListView, SIGNAL(clicked(QListViewItem*, const QPoint&, int)), SLOT(showOutput(QListViewItem*, const QPoint&, int)));
00861 connect(outputChooser->PushButtonClose, SIGNAL(clicked()), outputChooser, SLOT(close()));
00862 outputChooser->exec();
00863 delete outputChooser;
00864 }
00865
00867 void XbraboView::updatePVMHosts(const QStringList& hosts)
00869 {
00870 if(!braboSetup)
00871 hostListPVM = hosts;
00872 else
00873 braboSetup->setPVMHosts(hosts);
00874 }
00875
00876
00880
00882 void XbraboView::keyPressEvent(QKeyEvent* e)
00885 {
00886 if(isTopLevel())
00887
00888
00889
00890
00891 qApp->sendEvent(mainWindow, new QKeyEvent(QEvent::Accel, e->key(), e->ascii(), e->state(), e->text(), e->isAutoRepeat(), e->count()));
00892
00893 e->ignore();
00894 }
00895
00897 void XbraboView::mouseReleaseEvent(QMouseEvent* e)
00900 {
00901 if(e->button() == QMouseEvent::RightButton)
00902 popup();
00903
00904 }
00905
00906
00910
00912 void XbraboView::popup()
00914 {
00916 QPopupMenu* popup = new QPopupMenu(0,0);
00917 popup->insertItem(IconSets::getIconSet(IconSets::MoleculeRead), tr("Read coordinates..."), this, SLOT(moleculeReadCoordinates()));
00918 popup->insertItem(tr("Add atoms..."), MoleculeView, SLOT(addAtoms()));
00919 const int ID_MOLECULE_DELETE = popup->insertItem(tr("Delete selected atoms"), MoleculeView, SLOT(deleteSelectedAtoms()));
00920 popup->insertSeparator();
00921 const int ID_ALTER_CARTESIAN = popup->insertItem(tr("Alter cartesian coordinates"), MoleculeView, SLOT(alterCartesian()));
00922 const int ID_ALTER_INTERNAL = popup->insertItem(tr("Alter internal coordinate"), MoleculeView, SLOT(alterInternal()));
00923 popup->insertSeparator();
00924 popup->insertItem(tr("Select all"), MoleculeView, SLOT(selectAll()));
00925 popup->insertItem(tr("Select none"), MoleculeView, SLOT(unselectAll()));
00926 popup->insertSeparator();
00927 popup->insertItem(IconSets::getIconSet(IconSets::SetupGlobal), tr("Setup global"),this, SLOT(setupGlobal()));
00928 popup->insertItem(IconSets::getIconSet(IconSets::SetupBrabo), tr("Setup energy && Forces"),this, SLOT(setupBrabo()));
00929 const int ID_SETUP_RELAX = popup->insertItem(IconSets::getIconSet(IconSets::SetupRelax), tr("Setup geometry optimization"),this, SLOT(setupRelax()));
00930 popup->insertSeparator();
00931 const int ID_RUN_START = popup->insertItem(IconSets::getIconSet(IconSets::Start), tr("Start"), this, SLOT(start()));
00932 const int ID_RUN_PAUSE = popup->insertItem(IconSets::getIconSet(IconSets::Pause), tr("Pause"), this, SLOT(pause()));
00933 const int ID_RUN_STOP = popup->insertItem(IconSets::getIconSet(IconSets::Stop), tr("Stop"), this, SLOT(stop()));
00934 popup->insertItem(IconSets::getIconSet(IconSets::Outputs), tr("View output"), this, SLOT(viewOutput()));
00935
00936
00938
00939
00940
00941
00942
00944
00945
00946
00948
00949
00950
00952
00953
00954
00955
00956
00957
00959
00960
00961
00962
00963
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00983 if(MoleculeView->selectedAtoms() == 0 || isRunning())
00984 {
00985 popup->setItemEnabled(ID_ALTER_CARTESIAN, false);
00986 popup->setItemEnabled(ID_MOLECULE_DELETE, false);
00987 }
00988 if(MoleculeView->selectedAtoms() < 2 || MoleculeView->selectedAtoms() > 4)
00989 popup->setItemEnabled(ID_ALTER_INTERNAL, false);
00990
00992 if(globalSetup == 0 || globalSetup->calculationType() != GlobalBase::GeometryOptimization)
00993 popup->setItemEnabled(ID_SETUP_RELAX, false);
00994
00995
00996
00997
00998
01000 if(isRunning())
01001 popup->setItemEnabled(ID_RUN_START, false);
01002 else
01003 {
01004 popup->setItemEnabled(ID_RUN_PAUSE, false);
01005 popup->setItemEnabled(ID_RUN_STOP, false);
01006 }
01007
01009 popup->exec(QCursor::pos());
01010 delete popup;
01011 }
01012
01014 void XbraboView::updateIteration(unsigned int iteration, double energy)
01016 {
01017
01018 if(globalSetup->calculationType() == GlobalBase::SinglePointEnergy || globalSetup->calculationType() == GlobalBase::EnergyAndForces)
01019 TextEditStatus->append(" " + tr("Iteration") + " " + QString::number(iteration) + " : " + tr("Energy") + " = " + QString::number(energy,'f',8));
01020
01021
01022 if(iteration == 50)
01023 {
01024
01025 TextEditStatus->append(" - " + tr("Total energy") + " = " + QString::number(energy,'f',8));
01026 if(globalSetup->calculationType() != GlobalBase::SinglePointEnergy)
01027 TextEditStatus->append(" - " + tr("Calculating forces"));
01028
01029 }
01030
01031
01032 lastProgress++;
01033 ProgressBar->setProgress(lastProgress);
01034 }
01035
01037 void XbraboView::updateCycle(unsigned int cycle)
01039 {
01040 bool ref1, ref2, ref3, ref4, ref5;
01041 calculation->getRefinementParameters(ref1, ref2, ref3, ref4, ref5);
01042 QString refResult = " - " + tr("Refinement parameters") + ":";
01043 refResult += ref1 ? " +" : " -";
01044 refResult += ref2 ? " +" : " -";
01045 refResult += ref3 ? " +" : " -";
01046 refResult += ref4 ? " +" : " -";
01047 refResult += ref5 ? " +" : " -";
01048 TextEditStatus->append(refResult);
01049 TextEditStatus->append(" * " + tr("Optimization step") + " " + QString::number(cycle));
01050 TextEditStatus->append(" - " + tr("Calculating energy"));
01051 lastProgress += braboSetup->maxIterations();
01052 if(lastProgress >= static_cast<unsigned int>(ProgressBar->totalSteps()))
01053 ProgressBar->setTotalSteps(lastProgress + 2* braboSetup->maxIterations());
01054 ProgressBar->setProgress(lastProgress);
01055 }
01056
01057
01058
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01078 void XbraboView::cleanupCalculation(unsigned int error)
01080 {
01081 qDebug("XbraboView::cleanupCalculation() called");
01082
01083 switch(error)
01084 {
01085 case Calculation::NoError:
01086 {
01087 if(globalSetup->calculationType() == GlobalBase::GeometryOptimization)
01088 {
01089 TextEditStatus->append(" - " + tr("Refinement parameters") + ": + + + + +");
01090 TextEditStatus->append(" * " + tr("Structure optimized"));
01091 }
01092 TextEditStatus->append("<font color=green>" + tr("Calculation finished successfully") + "</font>");
01093 }
01094 break;
01095 case Calculation::UndefinedError:
01096 TextEditStatus->append("<font color=red>" + tr("Calculation finished with errors") + "</font>");
01097 break;
01098 case Calculation::NoConvergence:
01099 TextEditStatus->append("<font color=red>" + tr("Calculation finished with errors: no convergence") + "</font>");
01100 break;
01101 case Calculation::CloseNuclei:
01102 TextEditStatus->append("<font color=red>" + tr("Calculation finished with errors: nuclei too close") + "</font>");
01103 break;
01104 case Calculation::MaxCyclesExceeded:
01105 TextEditStatus->append("<font color=red>" + tr("Calculation finished with errors: maximum number of optimization cycles reached") + "</font>");
01106 break;
01107 case Calculation::ManualStop:
01108 TextEditStatus->append("<font color=red>" + tr("Calculation stopped immediately") + "</font>");
01109 break;
01110 }
01111
01112 if(globalSetup->calculationType() == GlobalBase::GeometryOptimization)
01113 calculation->setContinuable(true);
01114 ProgressBar->setProgress(ProgressBar->totalSteps());
01115 QTimer::singleShot(5*1000, ProgressBar, SLOT(reset()));
01116
01117 globalSetup->allowChanges(true);
01118 emit changed();
01119 }
01120
01122 void XbraboView::showOutput(QListViewItem* item, const QPoint&, int column)
01124 {
01126 if(item == 0 || column < 1 || column > 4 || calculation == 0)
01127 return;
01128
01130 if(item->pixmap(column) == 0)
01131 return;
01132
01134 unsigned int cycle;
01135 if(item->text(0) == tr("last"))
01136 cycle = 0;
01137 else
01138 cycle = item->text(0).toUInt();
01139
01141 QStringList contents;
01142 int fileWidth = 81;
01143 switch(column)
01144 {
01145 case 1:
01146 contents = calculation->braboOutput(cycle);
01147 fileWidth = 111;
01148 break;
01149 case 2:
01150 contents = calculation->stockOutput(cycle);
01151 fileWidth = 97;
01152 break;
01153 case 3:
01154 contents = calculation->relaxOutput(cycle);
01155 fileWidth = 131;
01156 break;
01157 case 4:
01158 contents = calculation->affOutput(cycle);
01159 break;
01160 }
01161 if(contents.isEmpty())
01162 return;
01163
01165 TextViewWidget* outputViewer = new TextViewWidget(this, 0, true, Qt::WDestructiveClose);
01166 outputViewer->TextEdit->setTextFormat(Qt::LogText);
01167 QFontMetrics metrics(outputViewer->TextEdit->currentFont());
01168 int newWidth = fileWidth*metrics.width(" ") + 2*outputViewer->layout()->margin() + outputViewer->TextEdit->verticalScrollBar()->sliderRect().width();
01169 outputViewer->resize(newWidth, outputViewer->height());
01170
01172 switch(column)
01173 {
01174 case 1:
01175 if(cycle == 0)
01176 outputViewer->setCaption(tr("Showing Brabo output from last cycle"));
01177 else
01178 outputViewer->setCaption(tr("Showing Brabo output from cycle") + " " + QString::number(cycle));
01179 outputViewer->TextEdit->setText(contents.join("\n"));
01180 break;
01181
01182
01183
01184
01185
01186
01187
01188
01189
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291 case 2:
01292 if(cycle == 0)
01293 outputViewer->setCaption(tr("Showing Stock output from last cycle"));
01294 else
01295 outputViewer->setCaption(tr("Showing Stock output from cycle") + " " + QString::number(cycle));
01296 outputViewer->TextEdit->setText(contents.join("\n"));
01297 break;
01298 case 3:
01299 if(cycle == 0)
01300 outputViewer->setCaption(tr("Showing Relax output from last cycle"));
01301 else
01302 outputViewer->setCaption(tr("Showing Relax output from cycle") + " " + QString::number(cycle));
01303 outputViewer->TextEdit->setText(contents.join("\n"));
01304 break;
01305 case 4:
01306 if(cycle == 0)
01307 outputViewer->setCaption(tr("Showing AFF file from last cycle"));
01308 else
01309 outputViewer->setCaption(tr("Showing AFF file from cycle") + " " + QString::number(cycle));
01310 outputViewer->TextEdit->setText(contents.join("\n"));
01311 break;
01312 }
01313
01315
01316
01317
01318 outputViewer->exec();
01319 }
01320
01322 void XbraboView::showProperties()
01325 {
01326 MoleculePropertiesWidget* properties = new MoleculePropertiesWidget(this, 0, true, 0);
01327 properties->ComboBoxRenderingType->setCurrentItem(MoleculeView->displayStyle(GLSimpleMoleculeView::Molecule));
01328 properties->ComboBoxForces->setCurrentItem(MoleculeView->displayStyle(GLSimpleMoleculeView::Forces));
01329 properties->CheckBoxElement->setChecked(MoleculeView->isShowingElements());
01330 properties->CheckBoxNumber->setChecked(MoleculeView->isShowingNumbers());
01331 if(MoleculeView->isShowingCharges(AtomSet::Mulliken))
01332 properties->ComboBoxCharge->setCurrentItem(AtomSet::Mulliken);
01333 else if(MoleculeView->isShowingCharges(AtomSet::Stockholder))
01334 properties->ComboBoxCharge->setCurrentItem(AtomSet::Stockholder);
01335 else
01336 properties->ComboBoxCharge->setCurrentItem(AtomSet::None);
01337
01338 if(properties->exec() == QDialog::Accepted)
01339 {
01340 MoleculeView->setDisplayStyle(GLSimpleMoleculeView::Molecule, properties->ComboBoxRenderingType->currentItem());
01341 MoleculeView->setDisplayStyle(GLSimpleMoleculeView::Forces, properties->ComboBoxForces->currentItem());
01342 MoleculeView->setLabels(properties->CheckBoxElement->isChecked(),
01343 properties->CheckBoxNumber->isChecked(),
01344 properties->ComboBoxCharge->currentItem());
01345 MoleculeView->updateGL();
01346 }
01347 delete properties;
01348 }
01349
01353
01355 void XbraboView::loadCMLLocal(const QDomElement* root)
01357 {
01358 int positionX = 0, positionY = 0, sizeWidth = 400, sizeHeight = 400;
01359 QValueList<int> splitterSizes;
01360 const QString prefix = "geometry_";
01361 QDomNode childNode = root->firstChild();
01362 while(!childNode.isNull())
01363 {
01364 if(childNode.isElement() && childNode.nodeName() == "parameter")
01365 {
01366 if(DomUtils::dictEntry(childNode, prefix + "position-x"))
01367 DomUtils::readNode(&childNode, &positionX);
01368 else if(DomUtils::dictEntry(childNode, prefix + "position-y"))
01369 DomUtils::readNode(&childNode, &positionY);
01370 else if(DomUtils::dictEntry(childNode, prefix + "width"))
01371 DomUtils::readNode(&childNode, &sizeWidth);
01372 else if(DomUtils::dictEntry(childNode, prefix + "height"))
01373 DomUtils::readNode(&childNode, &sizeHeight);
01374 else if(DomUtils::dictEntry(childNode, prefix + "splitter_sizes"))
01375 DomUtils::readNode(&childNode, &splitterSizes);
01376 }
01377 childNode = childNode.nextSibling();
01378 }
01379 QPoint position(positionX, positionY);
01380 QSize size(sizeWidth, sizeHeight);
01381 resize(size);
01382 move(position);
01383 if(splitterSizes.size() != 0)
01384 Splitter->setSizes(splitterSizes);
01385 }
01386
01388 void XbraboView::saveCMLLocal(QDomElement* root)
01390 {
01392 QRect geometry = internalGeometry();
01393 const QString prefix = "geometry_";
01394 DomUtils::makeNode(root, geometry.x(), prefix + "position-x");
01395 DomUtils::makeNode(root, geometry.y(), prefix + "position-y");
01396 DomUtils::makeNode(root, geometry.width(), prefix + "width");
01397 DomUtils::makeNode(root, geometry.height(), prefix + "height");
01398
01399 QValueList<int> list = Splitter->sizes();
01400 DomUtils::makeNode(root, list, prefix + "splitter_sizes");
01401 }
01402
01404 void XbraboView::updateCaptions()
01406 {
01407 QFileInfo fi = QFileInfo(calcFileName);
01408 QString tempString = fi.baseName(true);
01409 if(globalSetup != 0 && !globalSetup->description().isEmpty())
01410 tempString += QString(" - ") + globalSetup->description();
01411 if(isModified())
01412 tempString += tr(" [modified]");
01413 setCaption(tempString);
01414 setTabCaption(fi.baseName(true));
01415 }
01416
01418 void XbraboView::updateBraboSetup()
01420 {
01421 if(braboSetup == 0)
01422 return;
01423
01424 braboSetup->setForces(globalSetup->calculationType() != GlobalBase::SinglePointEnergy);
01425 braboSetup->setDescription(globalSetup->description());
01426 braboSetup->setName(globalSetup->name());
01427 braboSetup->setExtendedFormat(globalSetup->extendedFormat());
01428 }
01429
01431 void XbraboView::updateRelaxSetup()
01433 {
01434 if(relaxSetup == 0)
01435 return;
01436
01437 relaxSetup->setName(globalSetup->name());
01438 relaxSetup->setDescription(globalSetup->description());
01439 relaxSetup->setDir(globalSetup->directory());
01440 relaxSetup->setExtendedFormat(globalSetup->extendedFormat());
01441 }
01442
01444 bool XbraboView::makeDirCurrent(const QString dir, const QString title)
01447 {
01448 QDir workDir = dir;
01449 if(!workDir.exists())
01450 {
01451 if(!workDir.mkdir(workDir.path()))
01452 {
01453 QMessageBox::warning(this, title, tr("Unable to create the directory ") + workDir.path());
01454 return false;
01455 }
01456 }
01457 if(!QDir::setCurrent(workDir.path()))
01458 {
01459 QMessageBox::warning(this, title, tr("Unable to change to the directory ") + workDir.path());
01460 return false;
01461 }
01462 return true;
01463 }
01464
01466 void XbraboView::initGlobalSetup()
01468 {
01469 if(globalSetup != 0)
01470 return;
01471
01472 globalSetup = new GlobalBase(this, 0, true, 0);
01473 globalSetup->setDefaultName(calcDefaultName);
01474 globalSetup->setIcon(QPixmap::fromMimeSource("SetupGlobalNormal"));
01475 }
01476
01478 void XbraboView::initBraboSetup()
01481 {
01482 if(braboSetup != 0)
01483 return;
01484
01485 initGlobalSetup();
01486 braboSetup = new BraboBase(atoms, this, 0, true, 0);
01487
01488 updateBraboSetup();
01489 if(!hostListPVM.isEmpty())
01490 updatePVMHosts(hostListPVM);
01491 }
01492
01494 void XbraboView::initRelaxSetup()
01497 {
01498 if(relaxSetup != 0)
01499 return;
01500
01501 initGlobalSetup();
01502 relaxSetup = new RelaxBase(atoms, this, 0, true, 0);
01503 relaxSetup->setIcon(QPixmap::fromMimeSource("SetupRelaxNormal"));
01504 updateRelaxSetup();
01505 }
01506
01508 bool XbraboView::initCalculation()
01511 {
01512 if(calculation == 0)
01513 {
01514 calculation = new Calculation(atoms, this);
01515 connect(calculation, SIGNAL(newIteration(unsigned int, double)), this, SLOT(updateIteration(unsigned int, double)));
01516 connect(calculation, SIGNAL(newCycle(unsigned int)), this, SLOT(updateCycle(unsigned int)));
01517 connect(calculation, SIGNAL(updated()), MoleculeView, SLOT(updateGL()));
01518 connect(calculation, SIGNAL(finished(unsigned int)), this, SLOT(cleanupCalculation(unsigned int)));
01519 connect(calculation, SIGNAL(modified()), this, SIGNAL(changed()));
01520 }
01521
01523 if(atoms->count() == 0)
01524 {
01525 QMessageBox::warning(this, tr("Initialize calculation"), tr("There are no atoms present"));
01526 return false;
01527 }
01528
01530 initBraboSetup();
01531 calculation->setCalculationType(globalSetup->calculationType(), globalSetup->buurType());
01532 calculation->setParameters(globalSetup->name(), globalSetup->directory(), globalSetup->extendedFormat());
01533 calculation->setBackup(1, true, true, true, true, true);
01534
01536 bool ok;
01537 QStringList basissetList = braboSetup->basissets(ok);
01538 if(!ok)
01539 return false;
01540 QString atdens = braboSetup->generateAtdens(ok);
01541 if(!ok)
01542 return false;
01543 bool prefer;
01544 unsigned int size1, size2;
01545 QString startVector = braboSetup->startVector(prefer, size1, size2);
01546 if(size1 == 0)
01547 return false;
01548 calculation->setBraboInput(braboSetup->generateInput(BraboBase::BRABO), basissetList, startVector, prefer, size1, size2);
01549 calculation->setStockInput(braboSetup->generateInput(BraboBase::STOCK), atdens);
01550
01552 if(globalSetup->calculationType() == GlobalBase::GeometryOptimization)
01553 {
01554 initRelaxSetup();
01555 std::vector<unsigned int> steps;
01556 std::vector<double> factors;
01557 relaxSetup->scaleFactors(steps, factors);
01558 qDebug("XbraboView::start:");
01559 for(unsigned int i = 0; i < steps.size(); i++)
01560 qDebug(" %d, step %d, factor %f", i, steps[i], factors[i]);
01561
01562 calculation->setRelaxInput(relaxSetup->generateInput(RelaxBase::AFF), relaxSetup->generateInput(RelaxBase::MAFF),
01563 relaxSetup->inputGenerationFrequency(), relaxSetup->maxSteps(), steps, factors);
01564 }
01565 return true;
01566 }
01567
01569 void XbraboView::updateAtomSet()
01572 {
01573 if(calculation != 0)
01574 calculation->setContinuable(false);
01575
01576
01577
01578 }
01579
01583
01584 unsigned int XbraboView::calcCounter = 0;
01585