1 /* Copyright (c) 2015 Gerald Knizia
2 *
3 * This file is part of the IboView program (see: http://www.iboview.org)
4 *
5 * IboView is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3.
8 *
9 * IboView is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with bfint (LICENSE). If not, see http://www.gnu.org/licenses/
16 *
17 * Please see IboView documentation in README.txt for:
18 * -- A list of included external software and their licenses. The included
19 * external software's copyright is not touched by this agreement.
20 * -- Notes on re-distribution and contributions to/further development of
21 * the IboView software
22 */
23
24 #include "Iv.h"
25 #include "IvComputeWfForm.h"
26 #include "IvSettings.h"
27 #include "QPropertyModel.h"
28 #include "ui_ComputeWfForm.h"
29 #include "IvDocument.h"
30 #include "CtBasisSet.h"
31 #include "CtAtomSet.h"
32
33 extern "C" {
34 size_t getMemorySize(); // memory_size.c
35 }
36
FComputeWfForm(FDocument * document,QWidget * parent)37 FComputeWfForm::FComputeWfForm(FDocument *document, QWidget *parent)
38 : QDialog(parent),
39 ui(new Ui::ComputeWfForm),
40 m_pDocument(document),
41 m_bMemoryOkay(true),
42 m_bOtherError(false)
43 {
44 ui->setupUi(this);
45 // ui->label_WorkSpace->setVisible(false);
46 // ui->spinBox_WorkSpacePerThread->setVisible(false);
47 ui->spinBox_WorkSpacePerThread->setEnabled(false);
48
49 // ui->tabWidget->layout()->setContentsMargins(0, 0, 0, 0); // left, top, right, bottom
50
51 // m_pDocument->GetWfOptions()->setObjectName("WfOptions");
52 LinkPropertyWidgets(m_pDocument->GetWfOptions(), this, "wf_option");
53 connect(ui->checkBox_RunScf, SIGNAL(toggled(bool)), this, SLOT(ToggleScfPage(bool)));
54 connect(ui->checkBox_RunIbba, SIGNAL(toggled(bool)), this, SLOT(ToggleIbbaPage(bool)));
55
56 connect(ui->comboBox_ScfMethod, SIGNAL(currentIndexChanged(int)), this, SLOT(RecomputeMemory()));
57 connect(ui->comboBox_ScfOrbitalBasis, SIGNAL(currentIndexChanged(int)), this, SLOT(RecomputeMemory()));
58 connect(ui->comboBox_ScfFitBasis, SIGNAL(currentIndexChanged(int)), this, SLOT(RecomputeMemory()));
59 connect(ui->spinBox_NumThreads, SIGNAL(valueChanged(int)), this, SLOT(RecomputeMemory()));
60 connect(ui->spinBox_WorkSpacePerThread, SIGNAL(valueChanged(int)), this, SLOT(RecomputeMemory()));
61 connect(ui->spinBox_WfCharge, SIGNAL(valueChanged(int)), this, SLOT(RecomputeMemory()));
62 connect(ui->spinBox_WfSpin, SIGNAL(valueChanged(int)), this, SLOT(RecomputeMemory()));
63 RecomputeMemory();
64
65 CheckEcps();
66
67 // if there already is electronic structure stuff, don't make new IBOs by default, unless
68 // the user actually asked for it explicitly.
69 if (m_pDocument->GetCurrentFrame() && m_pDocument->GetCurrentFrame()->HaveOrbitals()) {
70 ui->checkBox_RunScf->setChecked(false);
71 }
72
73 ui->buttonBox->setFocus();
74
75 if (!IvRestoreWindowSize("ComputeWindow/Size", this))
76 IvGuessSubDialogSize(this);
77 }
78
79 // void FComputeWfForm::closeEvent(QCloseEvent *event)
80 // {
81 // IvSaveWindowSize("ComputeWindow/Size", this);
82 // return QDialog::closeEvent(event);
83 // }
84
85
~FComputeWfForm()86 FComputeWfForm::~FComputeWfForm()
87 {
88 IvSaveWindowSize("ComputeWindow/Size", this);
89 delete ui;
90 }
91
ToggleScfPage(bool Checked)92 void FComputeWfForm::ToggleScfPage(bool Checked)
93 {
94 ui->page_WfSetup->setEnabled(Checked);
95 if (Checked)
96 ui->tabWidget->setCurrentIndex(0);
97 else
98 ui->tabWidget->setCurrentIndex(1);
99 }
100
ToggleIbbaPage(bool Checked)101 void FComputeWfForm::ToggleIbbaPage(bool Checked)
102 {
103 ui->page_IbbaSetup->setEnabled(Checked);
104 if (Checked)
105 ui->tabWidget->setCurrentIndex(1);
106 }
107
SetMemoryText(QString s,FStatusClass Class)108 void FComputeWfForm::SetMemoryText(QString s, FStatusClass Class)
109 {
110 ui->label_MemoryGuess->setStyleSheet(QString("QLabel{padding: .2ex; font-size: 12pt; font-weight: bold; %1} QLabel::disabled{background: #444; color:#aaa}").arg(GetStatusStyle(Class)));
111 ui->label_MemoryGuess->setText(s);
112 }
113
114
RecomputeMemory()115 void FComputeWfForm::RecomputeMemory()
116 {
117 m_bMemoryOkay = true;
118 m_bOtherError = true; // will be cleared at end of 'try{..}'
119 try {
120 FFrame
121 *pFrame = m_pDocument->GetCurrentFrame();
122 ct::FAtomSet
123 *pOrigAtoms = 0;
124 if (pFrame)
125 pOrigAtoms = pFrame->pGetAtoms();
126 if (pOrigAtoms == 0)
127 return SetMemoryText("[no geometry]", STATUS_Confused);
128 // make a copy of the atom set and set the current bases.
129 ct::FAtomSet
130 Atoms(*pOrigAtoms);
131 FWfOptions
132 *pWfOptions = m_pDocument->GetWfOptions();
133 pWfOptions->AssignBasisSets(&Atoms);
134
135 // currently open-shell is not supported for KS... check number of electrons
136 // and extra spin. Should be fixed soon.
137 int
138 nElecTotal = (Atoms.NuclearCharge() - pWfOptions->GetCharge());
139 // IvEmit("!!nElecTotal = %1", nElecTotal);
140 if (nElecTotal < 0)
141 return SetMemoryText("[nElec < 0]", STATUS_Confused);
142 if (pWfOptions->GetExtraSpin() != 0 || (unsigned(nElecTotal) % 2) != 0)
143 return SetMemoryText("[open-shell not working]", STATUS_Confused);
144
145 // instanciate the fitting sets to see how large they are.
146 ct::FBasisSet
147 OrbBasis(Atoms, ct::BASIS_Orbital),
148 FitBasis(Atoms, ct::BASIS_JkFit);
149 size_t
150 nAo = OrbBasis.nFn(),
151 nFit = FitBasis.nFn();
152 // IvEmit("Basis sizes: nAo = %1 nFit = %2", nAo, nFit);
153
154 // that is the estimate for the fully caching small-molecule 3ix DF-RKS.
155 size_t
156 nThreads = (size_t)pWfOptions->GetNumThreads(),
157 nWorkSpaceShared = sizeof(double) * (8*nAo*nAo + nFit*nFit),
158 nMemEst = nWorkSpaceShared + sizeof(double) * (nFit*((nAo*(nAo+1))/2)),
159 // nMemEst = sizeof(double) * (8*nAo*nAo + nFit*nFit + nFit*((nAo*(nAo+1))/2)),
160 nSysMem = getMemorySize(); // amount of physical memory on the system.
161
162 size_t
163 nMinWorkSpacePerThread = size_t(20)<<20; // 20 MB
164 nMinWorkSpacePerThread += sizeof(double)*(std::max(size_t(2), size_t(FitBasis.nFnOfLargestShell())) * nAo*nAo);
165 // ^- 2 fock matrices per thread in AccXc and nFnOfLargestShell() for FormIntMNF
166 // as intermediate while building the cached integrals. The latter could certainly
167 // be reduced if I find some time. But for the moment this will have to work...
168 nMemEst += nThreads * nMinWorkSpacePerThread;
169 pWfOptions->SetWorkSpaceMb((nMinWorkSpacePerThread + nWorkSpaceShared/nThreads)>>20);
170
171 // nMemEst += size_t(pWfOptions->GetNumThreads()) * (size_t(pWfOptions->GetWorkSpaceMb()) << 20);
172
173 // nSysMem = size_t(8) << 30;
174
175 if (nSysMem == 0)
176 nSysMem = size_t(8) << 30; // assume 8 GB.
177
178 // IvEmit("This system has %1 GB of memory. Does it?", double(nSysMem)/double(1<<30));
179 double
180 f = (double(nMemEst) + double(size_t(2)<<30)) / double(nSysMem);
181 // convert to MB
182 nMemEst >>= 20;
183 FStatusClass
184 Class = STATUS_Confused;
185 if (f < 0.3)
186 Class = STATUS_Idle;
187 else if (f < 0.8)
188 Class = STATUS_Warning;
189 else {
190 Class = STATUS_Error;
191 m_bMemoryOkay = false;
192 }
193 SetMemoryText(QString("%1 MB").arg((int)nMemEst), Class);
194 m_bOtherError = false;
195
196 } catch (std::runtime_error &e) {
197 SetMemoryText("[failed to load basis set]", STATUS_Confused);
198 m_bOtherError = true;
199 }
200 }
201
CheckEcps()202 void FComputeWfForm::CheckEcps()
203 {
204 try {
205 FFrame
206 *pFrame = m_pDocument->GetCurrentFrame();
207 ct::FAtomSet
208 *pOrigAtoms = 0;
209 if (pFrame)
210 pOrigAtoms = pFrame->pGetAtoms();
211 if (pOrigAtoms == 0)
212 return SetMemoryText("[no geometry]", STATUS_Confused);
213 bool NeedsEcps = false;
214 for (size_t iAt = 0; iAt < pOrigAtoms->size(); ++ iAt) {
215 if ((*pOrigAtoms)[iAt].AtomicNumber > 36)
216 NeedsEcps = true;
217 }
218
219 if (NeedsEcps) {
220 ui->textBrowser_WfNotes->setText("<div style=\"font-size: 11pt; color:#ccc\"><p><div style=\"font-size: 13pt; color:white\">"
221 "Sorry, MicroScf currently cannot do this calculation :(.</div> "
222 "It can only compute Kohn-Sham wave functions up to element 36 (Kr), due to "
223 "a lack of ECP integrals.</p>"
224 "<p>Note: Chemical analysis of an imported wave function should still work.</p></div>");
225 ui->checkBox_RunScf->setChecked(false);
226 ui->checkBox_RunScf->setEnabled(false);
227 }
228 } catch (std::runtime_error &e) {
229 ui->textBrowser_WfNotes->setText("[failed to instanciate FAtomSet]");
230 }
231 }
232
233
234
235
236
GetRunScf() const237 bool FComputeWfForm::GetRunScf() const
238 {
239 return ui->checkBox_RunScf->isChecked();
240 }
241
GetRunIbba() const242 bool FComputeWfForm::GetRunIbba() const
243 {
244 return ui->checkBox_RunIbba->isChecked();
245 }
246
IsMemoryOkay() const247 bool FComputeWfForm::IsMemoryOkay() const
248 {
249 return m_bMemoryOkay;
250 }
251