forked from OpenChemistry/avogadrolibs
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Geoff Hutchison <[email protected]>
- Loading branch information
Showing
4 changed files
with
437 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
/****************************************************************************** | ||
This source file is part of the Avogadro project. | ||
This source code is released under the 3-Clause BSD License, (see "LICENSE"). | ||
******************************************************************************/ | ||
|
||
#include "gaussiansetconcurrent.h" | ||
|
||
#include <avogadro/core/gaussianset.h> | ||
#include <avogadro/core/gaussiansettools.h> | ||
#include <avogadro/core/molecule.h> | ||
#include <avogadro/core/mutex.h> | ||
|
||
#include <avogadro/core/cube.h> | ||
|
||
#include <QtConcurrent/QtConcurrentMap> | ||
|
||
namespace Avogadro::QtGui { | ||
|
||
using Core::BasisSet; | ||
using Core::Cube; | ||
using Core::GaussianSet; | ||
using Core::GaussianSetTools; | ||
using Core::Molecule; | ||
|
||
template <typename Derived> | ||
class BasisSetConcurrent | ||
{ | ||
void setMolecule(Molecule* mol) | ||
{ | ||
static_cast<Derived*>(this)->setMolecule(mol); | ||
} | ||
}; | ||
|
||
struct GaussianShell | ||
{ | ||
GaussianSetTools* tools; // A pointer to the tools, can't write to member vars | ||
Cube* tCube; // The target cube, used to initialise temp cubes too | ||
unsigned int pos; // The index of the point to calculate the MO for | ||
unsigned int state; // The MO number to calculate | ||
}; | ||
|
||
GaussianSetConcurrent::GaussianSetConcurrent(QObject* p) | ||
: QObject(p), m_gaussianShells(nullptr), m_set(nullptr), m_tools(nullptr) | ||
{ | ||
// Watch for the future | ||
connect(&m_watcher, SIGNAL(finished()), this, SLOT(calculationComplete())); | ||
} | ||
|
||
GaussianSetConcurrent::~GaussianSetConcurrent() | ||
{ | ||
delete m_gaussianShells; | ||
} | ||
|
||
void GaussianSetConcurrent::setMolecule(Core::Molecule* mol) | ||
{ | ||
if (!mol) | ||
return; | ||
m_set = dynamic_cast<GaussianSet*>(mol->basisSet()); | ||
|
||
delete m_tools; | ||
m_tools = new GaussianSetTools(mol); | ||
} | ||
|
||
bool GaussianSetConcurrent::calculateMolecularOrbital(Core::Cube* cube, | ||
unsigned int state, | ||
bool beta) | ||
{ | ||
// We can do some initial set up of the tools here to set electron type. | ||
if (!beta) | ||
m_tools->setElectronType(BasisSet::Alpha); | ||
else | ||
m_tools->setElectronType(BasisSet::Beta); | ||
|
||
return setUpCalculation(cube, state, GaussianSetConcurrent::processOrbital); | ||
} | ||
|
||
bool GaussianSetConcurrent::calculateElectronDensity(Core::Cube* cube) | ||
{ | ||
const MatrixX& matrix = m_set->densityMatrix(); | ||
if (matrix.rows() == 0 || matrix.cols() == 0) { | ||
// we don't have a density matrix, so calculate one | ||
m_set->generateDensityMatrix(); | ||
} | ||
|
||
return setUpCalculation(cube, 0, GaussianSetConcurrent::processDensity); | ||
} | ||
|
||
bool GaussianSetConcurrent::calculateSpinDensity(Core::Cube* cube) | ||
{ | ||
return setUpCalculation(cube, 0, GaussianSetConcurrent::processSpinDensity); | ||
} | ||
|
||
void GaussianSetConcurrent::calculationComplete() | ||
{ | ||
(*m_gaussianShells)[0].tCube->lock()->unlock(); | ||
delete m_gaussianShells; | ||
m_gaussianShells = nullptr; | ||
emit finished(); | ||
} | ||
|
||
bool GaussianSetConcurrent::setUpCalculation(Core::Cube* cube, | ||
unsigned int state, | ||
void (*func)(GaussianShell&)) | ||
{ | ||
if (!m_set || !m_tools) | ||
return false; | ||
|
||
m_set->initCalculation(); | ||
|
||
// Set up the points we want to calculate the density at. | ||
m_gaussianShells = | ||
new QVector<GaussianShell>(static_cast<int>(cube->data()->size())); | ||
|
||
for (int i = 0; i < m_gaussianShells->size(); ++i) { | ||
(*m_gaussianShells)[i].tools = m_tools; | ||
(*m_gaussianShells)[i].tCube = cube; | ||
(*m_gaussianShells)[i].pos = i; | ||
(*m_gaussianShells)[i].state = state; | ||
} | ||
|
||
// Lock the cube until we are done. | ||
cube->lock()->lock(); | ||
|
||
// The main part of the mapped reduced function... | ||
m_future = QtConcurrent::map(*m_gaussianShells, func); | ||
// Connect our watcher to our future | ||
m_watcher.setFuture(m_future); | ||
|
||
return true; | ||
} | ||
|
||
void GaussianSetConcurrent::processOrbital(GaussianShell& shell) | ||
{ | ||
Vector3 pos = shell.tCube->position(shell.pos); | ||
shell.tCube->setValue( | ||
shell.pos, shell.tools->calculateMolecularOrbital(pos, shell.state)); | ||
} | ||
|
||
void GaussianSetConcurrent::processDensity(GaussianShell& shell) | ||
{ | ||
Vector3 pos = shell.tCube->position(shell.pos); | ||
shell.tCube->setValue(shell.pos, shell.tools->calculateElectronDensity(pos)); | ||
} | ||
|
||
void GaussianSetConcurrent::processSpinDensity(GaussianShell& shell) | ||
{ | ||
Vector3 pos = shell.tCube->position(shell.pos); | ||
shell.tCube->setValue(shell.pos, shell.tools->calculateSpinDensity(pos)); | ||
} | ||
} // namespace Avogadro::QtGui |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/****************************************************************************** | ||
This source file is part of the Avogadro project. | ||
This source code is released under the 3-Clause BSD License, (see "LICENSE"). | ||
******************************************************************************/ | ||
|
||
#ifndef AVOGADRO_QTGUI_GAUSSIANSETCONCURRENT_H | ||
#define AVOGADRO_QTGUI_GAUSSIANSETCONCURRENT_H | ||
|
||
#include "avogadroqtguiexport.h" | ||
|
||
#include <QtCore/QFuture> | ||
#include <QtCore/QFutureWatcher> | ||
#include <QtCore/QObject> | ||
|
||
namespace Avogadro { | ||
|
||
namespace Core { | ||
class Cube; | ||
class Molecule; | ||
class GaussianSet; | ||
class GaussianSetTools; | ||
} // namespace Core | ||
|
||
namespace QtGui { | ||
|
||
struct GaussianShell; | ||
|
||
/** | ||
* @brief The GaussianSetConcurrent class uses GaussianSetTools to calculate | ||
* values of electronic structure properties from quantum output read in. | ||
* @author Marcus D. Hanwell | ||
*/ | ||
|
||
class AVOGADROQTGUI_EXPORT GaussianSetConcurrent : public QObject | ||
{ | ||
Q_OBJECT | ||
|
||
public: | ||
explicit GaussianSetConcurrent(QObject* p = nullptr); | ||
~GaussianSetConcurrent() override; | ||
|
||
void setMolecule(Core::Molecule* mol); | ||
|
||
bool calculateMolecularOrbital(Core::Cube* cube, unsigned int state, | ||
bool beta = false); | ||
bool calculateElectronDensity(Core::Cube* cube); | ||
bool calculateSpinDensity(Core::Cube* cube); | ||
|
||
QFutureWatcher<void>& watcher() { return m_watcher; } | ||
|
||
signals: | ||
/** | ||
* Emitted when the calculation is complete. | ||
*/ | ||
void finished(); | ||
|
||
private slots: | ||
/** | ||
* Slot to set the cube data once Qt Concurrent is done | ||
*/ | ||
void calculationComplete(); | ||
|
||
private: | ||
QFuture<void> m_future; | ||
QFutureWatcher<void> m_watcher; | ||
Core::Cube* m_cube; | ||
QVector<GaussianShell>* m_gaussianShells; | ||
|
||
Core::GaussianSet* m_set; | ||
Core::GaussianSetTools* m_tools; | ||
|
||
bool setUpCalculation(Core::Cube* cube, unsigned int state, | ||
void (*func)(GaussianShell&)); | ||
|
||
static void processOrbital(GaussianShell& shell); | ||
static void processDensity(GaussianShell& shell); | ||
static void processSpinDensity(GaussianShell& shell); | ||
}; | ||
} // namespace QtGui | ||
} // namespace Avogadro | ||
|
||
#endif // GAUSSIANSETCONCURRENT_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
/****************************************************************************** | ||
This source file is part of the Avogadro project. | ||
This source code is released under the 3-Clause BSD License, (see "LICENSE"). | ||
******************************************************************************/ | ||
|
||
#include "slatersetconcurrent.h" | ||
|
||
#include <avogadro/core/molecule.h> | ||
#include <avogadro/core/slaterset.h> | ||
#include <avogadro/core/slatersettools.h> | ||
|
||
#include <avogadro/core/cube.h> | ||
#include <avogadro/core/mutex.h> | ||
|
||
#include <QtConcurrent/QtConcurrentMap> | ||
|
||
namespace Avogadro::QtGui { | ||
|
||
using Core::Cube; | ||
using Core::SlaterSet; | ||
using Core::SlaterSetTools; | ||
|
||
struct SlaterShell | ||
{ | ||
SlaterSetTools* tools; // A pointer to the tools, cannot write to member vars | ||
Cube* tCube; // The target cube, used to initialise temp cubes too | ||
unsigned int pos; // The index of the point to calculate the MO for | ||
unsigned int state; // The MO number to calculate | ||
}; | ||
|
||
SlaterSetConcurrent::SlaterSetConcurrent(QObject* p) | ||
: QObject(p), m_shells(nullptr), m_set(nullptr), m_tools(nullptr) | ||
{ | ||
// Watch for the future | ||
connect(&m_watcher, SIGNAL(finished()), this, SLOT(calculationComplete())); | ||
} | ||
|
||
SlaterSetConcurrent::~SlaterSetConcurrent() | ||
{ | ||
delete m_shells; | ||
} | ||
|
||
void SlaterSetConcurrent::setMolecule(Core::Molecule* mol) | ||
{ | ||
if (!mol) | ||
return; | ||
m_set = dynamic_cast<SlaterSet*>(mol->basisSet()); | ||
|
||
delete m_tools; | ||
m_tools = new SlaterSetTools(mol); | ||
} | ||
|
||
bool SlaterSetConcurrent::calculateMolecularOrbital(Core::Cube* cube, | ||
unsigned int state) | ||
{ | ||
return setUpCalculation(cube, state, SlaterSetConcurrent::processOrbital); | ||
} | ||
|
||
bool SlaterSetConcurrent::calculateElectronDensity(Core::Cube* cube) | ||
{ | ||
return setUpCalculation(cube, 0, SlaterSetConcurrent::processDensity); | ||
} | ||
|
||
bool SlaterSetConcurrent::calculateSpinDensity(Core::Cube* cube) | ||
{ | ||
return setUpCalculation(cube, 0, SlaterSetConcurrent::processSpinDensity); | ||
} | ||
|
||
void SlaterSetConcurrent::calculationComplete() | ||
{ | ||
(*m_shells)[0].tCube->lock()->unlock(); | ||
delete m_shells; | ||
m_shells = nullptr; | ||
emit finished(); | ||
} | ||
|
||
bool SlaterSetConcurrent::setUpCalculation(Core::Cube* cube, unsigned int state, | ||
void (*func)(SlaterShell&)) | ||
{ | ||
if (!m_set || !m_tools) | ||
return false; | ||
|
||
m_set->initCalculation(); | ||
|
||
// Set up the points we want to calculate the density at. | ||
m_shells = new QVector<SlaterShell>(static_cast<int>(cube->data()->size())); | ||
|
||
for (int i = 0; i < m_shells->size(); ++i) { | ||
(*m_shells)[i].tools = m_tools; | ||
(*m_shells)[i].tCube = cube; | ||
(*m_shells)[i].pos = i; | ||
(*m_shells)[i].state = state; | ||
} | ||
|
||
// Lock the cube until we are done. | ||
cube->lock()->lock(); | ||
|
||
// The main part of the mapped reduced function... | ||
m_future = QtConcurrent::map(*m_shells, func); | ||
// Connect our watcher to our future | ||
m_watcher.setFuture(m_future); | ||
|
||
return true; | ||
} | ||
|
||
void SlaterSetConcurrent::processOrbital(SlaterShell& shell) | ||
{ | ||
Vector3 pos = shell.tCube->position(shell.pos); | ||
shell.tCube->setValue( | ||
shell.pos, shell.tools->calculateMolecularOrbital(pos, shell.state)); | ||
} | ||
|
||
void SlaterSetConcurrent::processDensity(SlaterShell& shell) | ||
{ | ||
Vector3 pos = shell.tCube->position(shell.pos); | ||
shell.tCube->setValue(shell.pos, shell.tools->calculateElectronDensity(pos)); | ||
} | ||
|
||
void SlaterSetConcurrent::processSpinDensity(SlaterShell& shell) | ||
{ | ||
Vector3 pos = shell.tCube->position(shell.pos); | ||
shell.tCube->setValue(shell.pos, shell.tools->calculateSpinDensity(pos)); | ||
} | ||
} // namespace Avogadro::QtGui |
Oops, something went wrong.
c398d05
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ERROR: clang-format-diff detected formatting issues. See the artifact for a patch or run clang-format on your branch.