Skip to content

Commit a786df7

Browse files
committed
Expose proper interface for MMFQ
1 parent 7bc4631 commit a786df7

File tree

13 files changed

+225
-96
lines changed

13 files changed

+225
-96
lines changed

src/bin/run_pcm.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,12 @@ int main(int argc, char * argv[]) {
7070
// First compute the potential from the classical point multipoles distribution
7171
// then add the one from the molecule
7272
TIMER_ON("Computing MEP");
73-
// FIXME currently hardcoded to the dipole-dipole interaction potential in vacuum
74-
Eigen::VectorXd mep =
75-
computeDipolarPotential(context_.getCenters(), input.multipoles());
7673
// FIXME
77-
// 1. Try to understand why this is needed
74+
// 1. Currently hardcoded to the dipole-dipole interaction potential in vacuum
7875
// 2. Try to re-write this such that the input object is not needed!!!
76+
Eigen::VectorXd mep = Eigen::VectorXd::Zero(size);
77+
if (input.MEPfromChargeDistribution())
78+
mep += computeDipolarPotential(context_.getCenters(), input.multipoles());
7979
if (input.MEPfromMolecule())
8080
mep += computeMEP(context_.molecule(), context_.getCenters());
8181
TIMER_OFF("Computing MEP");
@@ -90,6 +90,7 @@ int main(int argc, char * argv[]) {
9090
Eigen::VectorXd rsp_asc(size);
9191
context_.getSurfaceFunction(rsp_asc.size(), rsp_asc.data(), "RspASC");
9292
TIMER_OFF("Computing ASC");
93+
context_.printSurfaceFunction("ASC");
9394
// Compute energy and print it out
9495
pcmsolver_out << "Solvation energy = "
9596
<< std::setprecision(std::numeric_limits<long double>::digits10)

src/interface/Input.cpp

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,9 @@ void Input::reader(const std::string & filename) {
160160
isDynamic_ = medium.getBool("NONEQUILIBRIUM");
161161

162162
const Section & chgdist = input_.getSect("CHARGEDISTRIBUTION");
163+
MEPfromChargeDist_ = false;
163164
if (chgdist.isDefined()) {
165+
MEPfromChargeDist_ = true;
164166
// Set monopoles
165167
if (chgdist.getKey<std::vector<double> >("MONOPOLES").isDefined()) {
166168
std::vector<double> mono = chgdist.getDblVec("MONOPOLES");
@@ -190,26 +192,27 @@ void Input::reader(const std::string & filename) {
190192
j += 6;
191193
}
192194
}
193-
// Set fluctuating charges
194-
isFQ_ = false;
195-
const Section & mmfq = input_.getSect("MMFQ");
196-
if (mmfq.isDefined()) {
197-
isFQ_ = true;
198-
fragments_.nSitesPerFragment =
199-
static_cast<PCMSolverIndex>(mmfq.getInt("SITESPERFRAGMENT"));
200-
std::vector<double> sites = mmfq.getDblVec("SITES");
201-
int j = 0;
202-
int n = int(sites.size() / 5);
203-
fragments_.sites = Eigen::Matrix3Xd::Zero(3, n);
204-
fragments_.chi = Eigen::VectorXd::Zero(n);
205-
fragments_.eta = Eigen::VectorXd::Zero(n);
206-
for (int i = 0; i < n; ++i) {
207-
fragments_.sites.col(i) =
208-
(Eigen::Vector3d() << sites[j], sites[j + 1], sites[j + 2]).finished();
209-
fragments_.chi(i) = sites[j + 3];
210-
fragments_.eta(i) = sites[j + 4];
211-
j += 5;
212-
}
195+
}
196+
// Set fluctuating charges
197+
isFQ_ = false;
198+
const Section & mmfq = input_.getSect("MMFQ");
199+
if (mmfq.isDefined()) {
200+
isFQ_ = true;
201+
fragments_.nSitesPerFragment =
202+
static_cast<PCMSolverIndex>(mmfq.getInt("SITESPERFRAGMENT"));
203+
std::vector<double> sites = mmfq.getDblVec("SITES");
204+
int j = 0;
205+
int n = int(sites.size() / 5);
206+
fragments_.nFragments = int(n / fragments_.nSitesPerFragment);
207+
fragments_.sites = Eigen::Matrix3Xd::Zero(3, n);
208+
fragments_.chi = Eigen::VectorXd::Zero(n);
209+
fragments_.eta = Eigen::VectorXd::Zero(n);
210+
for (int i = 0; i < n; ++i) {
211+
fragments_.sites.col(i) =
212+
(Eigen::Vector3d() << sites[j], sites[j + 1], sites[j + 2]).finished();
213+
fragments_.chi(i) = sites[j + 3];
214+
fragments_.eta(i) = sites[j + 4];
215+
j += 5;
213216
}
214217
}
215218

src/interface/Input.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ class PCMSolver_EXPORT Input {
136136
ChargeDistribution multipoles() const { return multipoles_; }
137137
MMFQ fragments() const { return fragments_; }
138138
bool MEPfromMolecule() { return MEPfromMolecule_; }
139+
bool MEPfromChargeDistribution() { return MEPfromChargeDist_; }
139140

140141
/// Operators
141142
/// operator<<
@@ -249,6 +250,8 @@ class PCMSolver_EXPORT Input {
249250
bool isFQ_;
250251
/// Whether to calculate the MEP from the molecular geometry
251252
bool MEPfromMolecule_;
253+
/// Whether to calculate the MEP from the charge distribution
254+
bool MEPfromChargeDist_;
252255
/// Classical charge distribution of point multipoles
253256
ChargeDistribution multipoles_;
254257
/// Classical fluctuating charges MM force field

src/interface/Meddle.cpp

Lines changed: 86 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -145,18 +145,25 @@ void Meddle::CTORBody() {
145145
<< std::endl;
146146
infoStream_ << "Input parsing done " << input_.providedBy() << std::endl;
147147

148-
TIMER_ON("Meddle::initCavity");
149-
initCavity();
150-
TIMER_OFF("Meddle::initCavity");
151-
152-
TIMER_ON("Meddle::initStaticSolver");
153-
initStaticSolver();
154-
TIMER_OFF("Meddle::initStaticSolver");
155-
156-
if (input_.isDynamic()) {
157-
TIMER_ON("Meddle::initDynamicSolver");
158-
initDynamicSolver();
159-
TIMER_OFF("Meddle::initDynamicSolver");
148+
if (input_.isFQ()) { /* MMFQ calculation */
149+
hasFQ_ = true;
150+
TIMER_ON("Meddle::initMMFQ");
151+
initMMFQ();
152+
TIMER_OFF("Meddle::initMMFQ");
153+
} else { /* Pure PCM calculation */
154+
TIMER_ON("Meddle::initCavity");
155+
initCavity();
156+
TIMER_OFF("Meddle::initCavity");
157+
158+
TIMER_ON("Meddle::initStaticSolver");
159+
initStaticSolver();
160+
TIMER_OFF("Meddle::initStaticSolver");
161+
162+
if (input_.isDynamic()) {
163+
TIMER_ON("Meddle::initDynamicSolver");
164+
initDynamicSolver();
165+
TIMER_OFF("Meddle::initDynamicSolver");
166+
}
160167
}
161168
}
162169

@@ -167,7 +174,8 @@ Meddle::Meddle(const Input & input, const HostWriter & write)
167174
cavity_(nullptr),
168175
K_0_(nullptr),
169176
K_d_(nullptr),
170-
hasDynamic_(false) {
177+
hasDynamic_(false),
178+
hasFQ_(false) {
171179
input_.initMolecule();
172180
CTORBody();
173181
}
@@ -179,7 +187,8 @@ Meddle::Meddle(const std::string & inputFileName, const HostWriter & write)
179187
cavity_(nullptr),
180188
K_0_(nullptr),
181189
K_d_(nullptr),
182-
hasDynamic_(false) {
190+
hasDynamic_(false),
191+
hasFQ_(false) {
183192
input_.initMolecule();
184193
CTORBody();
185194
}
@@ -196,7 +205,8 @@ Meddle::Meddle(int nr_nuclei,
196205
cavity_(nullptr),
197206
K_0_(nullptr),
198207
K_d_(nullptr),
199-
hasDynamic_(false) {
208+
hasDynamic_(false),
209+
hasFQ_(false) {
200210
TIMER_ON("Meddle::initInput");
201211
initInput(nr_nuclei, charges, coordinates, symmetry_info);
202212
TIMER_OFF("Meddle::initInput");
@@ -216,7 +226,8 @@ Meddle::Meddle(int nr_nuclei,
216226
cavity_(nullptr),
217227
K_0_(nullptr),
218228
K_d_(nullptr),
219-
hasDynamic_(false) {
229+
hasDynamic_(false),
230+
hasFQ_(false) {
220231
TIMER_ON("Meddle::initInput");
221232
initInput(nr_nuclei, charges, coordinates, symmetry_info);
222233
TIMER_OFF("Meddle::initInput");
@@ -235,7 +246,8 @@ Meddle::Meddle(int nr_nuclei,
235246
cavity_(nullptr),
236247
K_0_(nullptr),
237248
K_d_(nullptr),
238-
hasDynamic_(false) {
249+
hasDynamic_(false),
250+
hasFQ_(false) {
239251
// This one does a deferred initialization:
240252
// The CTORBody function is not called at this point, but during refresh
241253
TIMER_ON("Meddle::initInput");
@@ -250,22 +262,26 @@ void pcmsolver_delete(pcmsolver_context_t * context) {
250262
delete AS_TYPE(pcm::Meddle, context);
251263
}
252264
pcm::Meddle::~Meddle() {
253-
delete cavity_;
254-
delete K_0_;
255-
if (hasDynamic_)
256-
delete K_d_;
265+
if (hasFQ_) { /* MMFQ calculation */
266+
delete FQ_;
267+
} else { /* Pure PCM calculation */
268+
delete cavity_;
269+
delete K_0_;
270+
if (hasDynamic_)
271+
delete K_d_;
272+
}
257273
}
258274

259275
PCMSolverIndex pcmsolver_get_cavity_size(pcmsolver_context_t * context) {
260276
return (AS_CTYPE(pcm::Meddle, context)->getCavitySize());
261277
}
262-
PCMSolverIndex pcm::Meddle::getCavitySize() const { return cavity_->size(); }
278+
PCMSolverIndex pcm::Meddle::getCavitySize() const { return std::get<0>(size_); }
263279

264280
PCMSolverIndex pcmsolver_get_irreducible_cavity_size(pcmsolver_context_t * context) {
265281
return (AS_CTYPE(pcm::Meddle, context)->getIrreducibleCavitySize());
266282
}
267283
PCMSolverIndex pcm::Meddle::getIrreducibleCavitySize() const {
268-
return cavity_->irreducible_size();
284+
return std::get<1>(size_);
269285
}
270286

271287
void pcmsolver_get_centers(pcmsolver_context_t * context, double centers[]) {
@@ -275,16 +291,26 @@ void pcmsolver_get_centers(pcmsolver_context_t * context, double centers[]) {
275291
}
276292
void pcm::Meddle::getCenters(double centers[]) const {
277293
TIMER_ON("Meddle::getCenters");
278-
Eigen::Map<Eigen::Matrix3Xd>(centers, 3, cavity_->size()) =
279-
cavity_->elementCenter();
294+
if (hasFQ_) { /* MMFQ calculation */
295+
PCMSolverIndex size = input_.fragments().sites.cols();
296+
Eigen::Map<Eigen::Matrix3Xd>(centers, 3, size) = input_.fragments().sites;
297+
} else { /* Pure PCM calculation */
298+
Eigen::Map<Eigen::Matrix3Xd>(centers, 3, cavity_->size()) =
299+
cavity_->elementCenter();
300+
}
280301
TIMER_OFF("Meddle::getCenters");
281302
}
282303

283304
void pcmsolver_get_center(pcmsolver_context_t * context, int its, double center[]) {
284305
AS_CTYPE(pcm::Meddle, context)->getCenter(its, center);
285306
}
286307
void pcm::Meddle::getCenter(int its, double center[]) const {
287-
Eigen::Map<Eigen::Vector3d>(center, 3, 1) = cavity_->elementCenter(its - 1);
308+
if (hasFQ_) { /* MMFQ calculation */
309+
Eigen::Map<Eigen::Matrix3Xd>(center, 3, 1) =
310+
input_.fragments().sites.col(its - 1);
311+
} else { /* Pure PCM calculation */
312+
Eigen::Map<Eigen::Vector3d>(center, 3, 1) = cavity_->elementCenter(its - 1);
313+
}
288314
}
289315

290316
void pcmsolver_get_areas(pcmsolver_context_t * context, double areas[]) {
@@ -303,7 +329,16 @@ double pcmsolver_compute_polarization_energy(pcmsolver_context_t * context,
303329
}
304330
double pcm::Meddle::computePolarizationEnergy(const std::string & mep_name,
305331
const std::string & asc_name) const {
306-
double energy = functions_.at(mep_name).dot(functions_.at(asc_name));
332+
double energy = 0.0;
333+
if (hasFQ_) { /* MMFQ calculation */
334+
// Dot product of MEP + Electronegativities times Fluctuating charges
335+
energy = (functions_.at(mep_name) + input_.fragments().chi)
336+
.dot(functions_.at(asc_name));
337+
} else { /* Pure PCM calculation */
338+
// Dot product of MEP and ASC surface function
339+
energy =
340+
functions_.at(mep_name).dot(functions_.at(asc_name));
341+
}
307342
return (energy / 2.0);
308343
}
309344

@@ -335,9 +370,14 @@ void pcm::Meddle::computeASC(const std::string & mep_name,
335370
int irrep) {
336371
// Get the proper iterators
337372
SurfaceFunctionMapConstIter iter_pot = functions_.find(mep_name);
338-
Eigen::VectorXd asc = K_0_->computeCharge(iter_pot->second, irrep);
339-
// Renormalize
340-
asc /= double(cavity_->pointGroup().nrIrrep());
373+
Eigen::VectorXd asc = Eigen::VectorXd::Zero(iter_pot->second.size());
374+
if (hasFQ_) { /* MMFQ calculation */
375+
asc = FQ_->computeCharge(iter_pot->second);
376+
} else { /* Pure PCM calculation */
377+
asc = K_0_->computeCharge(iter_pot->second, irrep);
378+
// Renormalize
379+
asc /= double(cavity_->pointGroup().nrIrrep());
380+
}
341381
// Insert it into the map
342382
if (functions_.count(asc_name) == 1) { // Key in map already
343383
functions_[asc_name] = asc;
@@ -360,14 +400,18 @@ void pcm::Meddle::computeResponseASC(const std::string & mep_name,
360400
int irrep) {
361401
// Get the proper iterators
362402
SurfaceFunctionMapConstIter iter_pot = functions_.find(mep_name);
363-
Eigen::VectorXd asc(cavity_->size());
364-
if (hasDynamic_) {
365-
asc = K_d_->computeCharge(iter_pot->second, irrep);
366-
} else {
367-
asc = K_0_->computeCharge(iter_pot->second, irrep);
403+
Eigen::VectorXd asc = Eigen::VectorXd::Zero(iter_pot->second.size());
404+
if (hasFQ_) { /* MMFQ calculation */
405+
asc = FQ_->computeCharge(iter_pot->second);
406+
} else { /* Pure PCM calculation */
407+
if (hasDynamic_) {
408+
asc = K_d_->computeCharge(iter_pot->second, irrep);
409+
} else {
410+
asc = K_0_->computeCharge(iter_pot->second, irrep);
411+
}
412+
// Renormalize
413+
asc /= double(cavity_->pointGroup().nrIrrep());
368414
}
369-
// Renormalize
370-
asc /= double(cavity_->pointGroup().nrIrrep());
371415
if (functions_.count(asc_name) == 1) { // Key in map already
372416
functions_[asc_name] = asc;
373417
} else { // Create key-value pair
@@ -387,7 +431,7 @@ void pcmsolver_get_surface_function(pcmsolver_context_t * context,
387431
void pcm::Meddle::getSurfaceFunction(PCMSolverIndex size,
388432
double values[],
389433
const std::string & name) const {
390-
if (cavity_->size() != size)
434+
if (std::get<0>(size_) != size)
391435
PCMSOLVER_ERROR("The " + name + " SurfaceFunction is bigger than the cavity!");
392436

393437
SurfaceFunctionMapConstIter iter = functions_.find(name);
@@ -408,7 +452,7 @@ void pcmsolver_set_surface_function(pcmsolver_context_t * context,
408452
void pcm::Meddle::setSurfaceFunction(PCMSolverIndex size,
409453
double values[],
410454
const std::string & name) {
411-
if (cavity_->size() != size)
455+
if (std::get<0>(size_) != size)
412456
PCMSOLVER_ERROR("The " + name + " SurfaceFunction is bigger than the cavity!");
413457

414458
Eigen::VectorXd func = Eigen::Map<Eigen::VectorXd>(values, size, 1);
@@ -460,7 +504,7 @@ void pcmsolver_load_surface_function(pcmsolver_context_t * context,
460504
void pcm::Meddle::loadSurfaceFunction(const std::string & name) {
461505
hostWriter_("\nLoading surface function " + name + " from .npy file");
462506
Eigen::VectorXd values = cnpy::custom::npy_load<double>(name + ".npy");
463-
if (values.size() != cavity_->size())
507+
if (values.size() != std::get<0>(size_))
464508
PCMSOLVER_ERROR("The loaded " + name +
465509
" surface function is bigger than the cavity!");
466510
// Append to global map
@@ -656,6 +700,7 @@ void Meddle::initInput(int nr_nuclei,
656700
void Meddle::initCavity() {
657701
cavity_ = cavity::bootstrapFactory().create(input_.cavityParams().cavityType,
658702
input_.cavityParams());
703+
size_ = std::make_tuple(cavity_->size(), cavity_->irreducible_size());
659704
cavity_->saveCavity();
660705

661706
infoStream_ << "========== Cavity " << std::endl;
@@ -679,7 +724,7 @@ void Meddle::initStaticSolver() {
679724
delete biop;
680725

681726
// Perform Gauss' theorem check for nuclear charges
682-
GaussCheck();
727+
if (!hasFQ_) GaussCheck();
683728

684729
infoStream_ << "========== Static solver " << std::endl;
685730
infoStream_ << *K_0_ << std::endl;

0 commit comments

Comments
 (0)