Program Listing for File combine_potentials.hpp#
↰ Return to documentation for file (source/pele/combine_potentials.hpp)
#ifndef _PELE_COMBINE_POTENTIALS_H_
#define _PELE_COMBINE_POTENTIALS_H_
#include <cstddef>
#include <list>
#include <memory>
#include "base_potential.hpp"
namespace pele {
class CombinedPotential : public BasePotential {
protected:
std::list<std::shared_ptr<BasePotential>> _potentials;
public:
CombinedPotential() {}
virtual ~CombinedPotential() {}
virtual void add_potential(std::shared_ptr<BasePotential> potential) {
_potentials.push_back(potential);
}
virtual double get_energy(Array<double> const &x) {
double energy = 0.;
for (auto &pot_ptr : _potentials) {
energy += pot_ptr->get_energy(x);
}
return energy;
}
virtual double get_energy_gradient(Array<double> const &x,
Array<double> &grad) {
if (x.size() != grad.size()) {
throw std::invalid_argument("the gradient has the wrong size");
}
double energy = 0.;
grad.assign(0.);
for (auto &pot_ptr : _potentials) {
energy += pot_ptr->add_energy_gradient(x, grad);
}
return energy;
}
virtual double get_energy_gradient_hessian(Array<double> const &x,
Array<double> &grad,
Array<double> &hess) {
if (x.size() != grad.size()) {
throw std::invalid_argument("the gradient has the wrong size");
}
if (hess.size() != x.size() * x.size()) {
throw std::invalid_argument("the Hessian has the wrong size");
}
double energy = 0.;
grad.assign(0.);
hess.assign(0.);
for (auto &pot_ptr : _potentials) {
energy += pot_ptr->add_energy_gradient_hessian(x, grad, hess);
}
return energy;
}
virtual void get_hessian(Array<double> const &x, Array<double> &hessian) {
if (hessian.size() != x.size() * x.size()) {
throw std::invalid_argument("the Hessian has the wrong size");
}
hessian.assign(0.);
for (auto &pot_ptr : _potentials) {
pot_ptr->add_hessian(x, hessian);
}
}
};
class ExtendedPotential : public CombinedPotential {
private:
bool use_extended_potential_;
size_t nhev_extension;
size_t nfev_extension;
size_t neev_extension;
public:
ExtendedPotential(std::shared_ptr<BasePotential> main_potential,
std::shared_ptr<BasePotential> extension_potential)
: CombinedPotential() {
add_potential(main_potential);
if (extension_potential != nullptr) {
add_potential(extension_potential);
}
use_extended_potential_ = false;
};
void switch_on_extended_potential() { use_extended_potential_ = true; }
void switch_off_extended_potential() { use_extended_potential_ = false; }
bool get_use_extended_potential() { return use_extended_potential_; }
double get_energy(Array<double> const &x) {
if (!use_extended_potential_) {
return _potentials.front()->get_energy(x);
} else {
neev_extension += 1;
return CombinedPotential::get_energy(x);
}
}
double get_energy_gradient(Array<double> const &x, Array<double> &grad) {
if (!use_extended_potential_) {
return _potentials.front()->get_energy_gradient(x, grad);
} else {
nfev_extension += 1;
return CombinedPotential::get_energy_gradient(x, grad);
}
}
double get_energy_gradient_hessian(Array<double> const &x,
Array<double> &grad, Array<double> &hess) {
if (!use_extended_potential_) {
return _potentials.front()->get_energy_gradient_hessian(x, grad, hess);
} else {
nhev_extension += 1;
return CombinedPotential::get_energy_gradient_hessian(x, grad, hess);
}
}
void get_hessian(Array<double> const &x, Array<double> &hess) {
if (!use_extended_potential_) {
return _potentials.front()->get_hessian(x, hess);
} else {
nhev_extension += 1;
return CombinedPotential::get_hessian(x, hess);
}
}
void get_hessian_extended(Array<double> const &x, Array<double> &hess) {
nhev_extension += 1;
return CombinedPotential::get_hessian(x, hess);
}
size_t get_nfev_extension() { return nfev_extension; }
size_t get_neev_extension() { return neev_extension; }
size_t get_nhev_extension() { return nhev_extension; }
}; // ExtendedPotential
} // namespace pele
#endif