diff --git a/src/angularbasis.cpp b/src/angularbasis.cpp index 7449a00c1619d01fcd7268c8c792b364114ab472..89da443f333a5231b72e7ef266643d2ae027d5e1 100644 --- a/src/angularbasis.cpp +++ b/src/angularbasis.cpp @@ -1,4 +1,5 @@ #include "angularbasis.hpp" + #include <math.h> #include <boost/math/special_functions/spherical_harmonic.hpp> @@ -9,29 +10,6 @@ void AngularBasis::configure(Options &options) { _L = options.get<int>("angularbasis.L"); } -AngularCoefficients AngularBasis::computeCoefficients(vec d, double r) { - AngularCoefficients coeffs(this->_L); - if (r < 1e-10) { - // Radius is virtually zero => set isotropic - std::complex<double> c00 = boost::math::spherical_harmonic<double,double>(0, 0, 0.0, 0.0); - coeffs.set(0, 0, c00); - } - else { - // Radius not zero => compute moments - double theta = acos(d.getZ()); - double phi = atan2(d.getY(), d.getX()); - // Shift [-pi, -0] to [pi, 2*pi] - if (phi < 0.) phi += 2*M_PI; - for (int l=0; l<=_L; ++l) { - for (int m=-l; m<=l; ++m) { - std::complex<double> clm = boost::math::spherical_harmonic<double,double>(l, m, theta, phi); - coeffs.set(l, m, clm); - } - } - } - return coeffs; -} - void AngularBasis::computeCoefficients(vec d, double r, angcoeff_t &save_here) { if (r < AngularBasis::RADZERO) { std::complex<double> c00 = boost::math::spherical_harmonic<double,double>(0, 0, 0.0, 0.0); @@ -53,20 +31,9 @@ void AngularBasis::computeCoefficients(vec d, double r, angcoeff_t &save_here) { return; } -AngularCoefficients AngularBasis::computeCoefficientsAllZero() { - AngularCoefficients coeffs(this->_L); - for (int l=0; l<=_L; ++l) { - for (int m=-l; m<=l; ++m) { - coeffs.set(l, m, std::complex<double>(0,0)); - } - } - return coeffs; -} - void AngularBasisFactory::registerAll(void) { AngularBasisOutlet().Register<AngularBasis>("spherical-harmonic"); } - -} +} /* CLOSE NAMESPACE */ diff --git a/src/angularbasis.hpp b/src/angularbasis.hpp index 8ede17028ab5493e53b0a20422bdd6fbc03e0611..d5affe2fc8fca1be86e055df7ad82938d87f0d68 100644 --- a/src/angularbasis.hpp +++ b/src/angularbasis.hpp @@ -13,34 +13,6 @@ namespace soap { namespace ub = boost::numeric::ublas; -class AngularCoefficients : public ub::vector< std::complex<double> > -{ -public: - - AngularCoefficients(int L) : _L(L) { - this->resize((L+1)*(L+1)); - for (int i=0; i!=size(); ++i) { - (*this)[i] = std::complex<double>(0,0); - } - } - void set(int l, int m, std::complex<double> c) { - if (this->checkSize(l, m)) (*this)[l*l+l+m] = c; - else throw soap::base::OutOfRange("AngularCoefficients::set"); - } - std::complex<double> &get(int l, int m) { - if (this->checkSize(l, m)) return (*this)[l*l+l+m]; - else throw soap::base::OutOfRange("AngularCoefficients::get"); - } - bool checkSize(int l, int m) { return (std::abs(m) <= l && l <= _L); } - void conjugate() { - for (int i = 0; i != size(); ++i) { - (*this)[i] = std::conj((*this)[i]); - } - } -protected: - int _L; -}; - class AngularBasis { @@ -48,14 +20,13 @@ public: typedef ub::vector< std::complex<double> > angcoeff_t; typedef ub::zero_vector< std::complex<double> > angcoeff_zero_t; + AngularBasis() : _type("spherical-harmonic"), _L(0) {;} + virtual ~AngularBasis() {;} + std::string &identify() { return _type; } const int &L() { return _L; } - AngularBasis() : _type("spherical-harmonic"), _L(0) {;} - virtual ~AngularBasis() {;} virtual void configure(Options &options); virtual void computeCoefficients(vec d, double r, angcoeff_t &save_here); - virtual AngularCoefficients computeCoefficients(vec d, double r); - virtual AngularCoefficients computeCoefficientsAllZero(); template<class Archive> void serialize(Archive &arch, const unsigned int version) { @@ -64,15 +35,13 @@ public: } protected: - std::string _type; int _L; static constexpr double RADZERO = 1e-10; }; -class AngularBasisFactory - : public soap::base::ObjectFactory<std::string, AngularBasis> +class AngularBasisFactory : public soap::base::ObjectFactory<std::string, AngularBasis> { private: AngularBasisFactory() {} @@ -98,6 +67,6 @@ inline AngularBasis *AngularBasisFactory::create(const std::string &key) { } } -} +} /* CLOSE NAMESPACE */ #endif diff --git a/src/atomicspectrum.cpp b/src/atomicspectrum.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c039531a7ed2180a7adb04b04097da65ae44e5f --- /dev/null +++ b/src/atomicspectrum.cpp @@ -0,0 +1,11 @@ +#include <fstream> +#include <boost/format.hpp> +#include <boost/archive/binary_oarchive.hpp> +#include <boost/archive/binary_iarchive.hpp> + +#include "atomicspectrum.hpp" + +namespace soap { + +} + diff --git a/src/atomicspectrum.hpp b/src/atomicspectrum.hpp new file mode 100644 index 0000000000000000000000000000000000000000..934f67e2f7af3efb5ce4e74c05093bebcac564a2 --- /dev/null +++ b/src/atomicspectrum.hpp @@ -0,0 +1,134 @@ +#ifndef _SOAP_ATOMICSPECTRUM_HPP +#define _SOAP_ATOMICSPECTRUM_HPP + +#include <assert.h> +#include <boost/serialization/vector.hpp> +#include <boost/serialization/map.hpp> +#include <boost/serialization/complex.hpp> +#include <boost/serialization/base_object.hpp> + +#include "base/logger.hpp" +#include "types.hpp" +#include "globals.hpp" +#include "options.hpp" +#include "structure.hpp" +#include "basis.hpp" +#include "power.hpp" + + +namespace soap { + + +class AtomicSpectrum : public std::map<std::string, BasisExpansion*> +{ +public: + typedef BasisExpansion qnlm_t; + typedef PowerExpansion xnkl_t; + typedef std::map<std::string, qnlm_t*> map_qnlm_t; // <- key: center type, e.g. 'C' + typedef std::map<std::pair<std::string, std::string>, xnkl_t*> map_xnkl_t; // <- key: type string pair, e.g. ('C','H') + + AtomicSpectrum(Particle *center, Basis *basis) : + _center(center), + _center_pos(center->getPos()), + _center_type(center->getType()), + _basis(basis), + _xnkl_generic_coherent(NULL), + _xnkl_generic_incoherent(NULL) { + _qnlm_generic = new BasisExpansion(_basis); + } + AtomicSpectrum() : + _center(NULL), + _center_pos(vec(0,0,0)), + _center_type("?"), + _basis(NULL), + _qnlm_generic(NULL), + _xnkl_generic_coherent(NULL), + _xnkl_generic_incoherent(NULL) { ; } + ~AtomicSpectrum() { + // Clean Qnlm's + for (map_qnlm_t::iterator it = _map_qnlm.begin(); it != _map_qnlm.end(); ++it) delete it->second; + _map_qnlm.clear(); + if (_qnlm_generic) { + delete _qnlm_generic; + _qnlm_generic = NULL; + } + // Clean Xnkl's + for (map_xnkl_t::iterator it = _map_xnkl.begin(); it != _map_xnkl.end(); ++it) delete it->second; + _map_xnkl.clear(); + if (_xnkl_generic_coherent) { + delete _xnkl_generic_coherent; + _xnkl_generic_coherent = NULL; + } + if (_xnkl_generic_incoherent) { + delete _xnkl_generic_incoherent; + _xnkl_generic_incoherent = NULL; + } + } + // CENTER & BASIS METHODS + Particle *getCenter() { return _center; } + std::string &getCenterType() { return _center_type; } + vec &getCenterPos() { return _center_pos; } + Basis *getBasis() { return _basis; } + // QNLM METHODS + void addQnlm(std::string type, qnlm_t &nb_expansion) { + assert(nb_expansion.getBasis() == _basis && + "Should not sum expansions linked against different bases."); + iterator it = _map_qnlm.find(type); + if (it == _map_qnlm.end()) { + _map_qnlm[type] = new BasisExpansion(_basis); + it = _map_qnlm.find(type); + } + it->second->add(nb_expansion); + _qnlm_generic->add(nb_expansion); + return; + } + qnlm_t *getQnlmGeneric() { return _qnlm_generic; } + qnlm_t *getQnlm(std::string type) { + if (type == "") { + return _qnlm_generic; + } + iterator it = _map_qnlm.find(type); + if (it == _map_qnlm.end()) { + throw soap::base::OutOfRange("AtomicSpectrum: No such type '" + type + "'"); + return NULL; + } + else { + return it->second; + } + } + + template<class Archive> + void serialize(Archive &arch, const unsigned int version) { + // Center & basis + arch & _center; + arch & _center_pos; + arch & _center_type; + arch & _basis; + // Qnlm's + arch & _map_qnlm; + arch & _qnlm_generic; + // Xnkl's + arch & _map_xnkl; + arch & _xnkl_generic_coherent; + arch & _xnkl_generic_incoherent; + return; + } +protected: + // CENTER & BASIS LINKS + Particle *_center; + vec _center_pos; + std::string _center_type; + Basis *_basis; + // DENSITY EXPANSION + map_qnlm_t _map_qnlm; + qnlm_t *_qnlm_generic; + // POWER DENSITY EXPANSION + map_xnkl_t _map_xnkl; + xnkl_t *_xnkl_generic_coherent; + xnkl_t *_xnkl_generic_incoherent; +}; + + +} + +#endif /* _SOAP_ATOMICSPECTRUM_HPP_ */ diff --git a/src/basis.cpp b/src/basis.cpp index 0415e53c6c2ee2fb25313669e12886d8349e25a1..5af0576b1a6d3816dbc127f7bed156aa15e2a821 100644 --- a/src/basis.cpp +++ b/src/basis.cpp @@ -3,5 +3,190 @@ namespace soap { +// ===== +// Basis +// ===== + +Basis::Basis(Options *options) : + _options(options) { + GLOG() << "Configuring basis ..." << std::endl; + // CONFIGURE RADIAL BASIS + _radbasis = RadialBasisOutlet().create(_options->get<std::string>("radialbasis.type")); + _radbasis->configure(*options); + // CONFIGURE ANGULAR BASIS + _angbasis = AngularBasisOutlet().create(_options->get<std::string>("angularbasis.type")); + _angbasis->configure(*options); + // CONFIGURE CUTOFF FUNCTION + _cutoff = CutoffFunctionOutlet().create(_options->get<std::string>("radialcutoff.type")); + _cutoff->configure(*options); +} + +Basis::~Basis() { + delete _radbasis; + _radbasis = NULL; + delete _angbasis; + _angbasis = NULL; + delete _cutoff; + _cutoff = NULL; +} + +// ============== +// BasisExpansion +// ============== + +BasisExpansion::BasisExpansion(Basis *basis) : + _basis(basis), + _radbasis(basis->getRadBasis()), + _angbasis(basis->getAngBasis()) { + int L = _angbasis->L(); + int N = _radbasis->N(); + _radcoeff = RadialBasis::radcoeff_zero_t(N,L+1); + _angcoeff = AngularBasis::angcoeff_zero_t((L+1)*(L+1)); + _coeff = coeff_zero_t(N,(L+1)*(L+1)); +} + +BasisExpansion::~BasisExpansion() { + _basis = NULL; + _radbasis = NULL; + _angbasis = NULL; + _radcoeff.clear(); + _angcoeff.clear(); +} + +void BasisExpansion::computeCoefficients(double r, vec d, double weight, double sigma) { + _radbasis->computeCoefficients(r, sigma, _radcoeff); + _angbasis->computeCoefficients(d, r, _angcoeff); + for (int n = 0; n != _radbasis->N(); ++n) { + for (int l = 0; l != _angbasis->L()+1; ++l) { + for (int m = -l; m != l+1; ++m) { + _coeff(n, l*l+l+m) = _radcoeff(n,l)*_angcoeff(l*l+l+m); + } + } + } + _coeff *= weight; + return; +} + +void BasisExpansion::conjugate() { + for (int n = 0; n != _radbasis->N(); ++n) { + for (int l = 0; l != _angbasis->L()+1; ++l) { + for (int m = -l; m != l+1; ++m) { + _coeff(n, l*l+l+m) = std::conj(_coeff(n, l*l+l+m)); + } + } + } +} + +void BasisExpansion::writeDensityOnGrid( + std::string filename, + Options *options, + Structure *structure, + Particle *center, + bool fromExpansion) { + + if (_angbasis == NULL || _radbasis == NULL) { + throw soap::base::APIError("<BasisExpansion::writeDensityOnGrid> " + "Object not linked against basis."); + } + + int I = options->get<int>("densitygrid.N"); + int Nx = 2*I+1; + int Ny = Nx; + int Nz = Nx; + + double dx = options->get<double>("densitygrid.dx"); + double dy = dx; + double dz = dx; + + double conv = soap::constants::ANGSTROM_TO_BOHR; + + vec r0 = -I * vec(dx,dy,dz); + + std::ofstream ofs; + ofs.open(filename.c_str(), std::ofstream::out); + if (!ofs.is_open()) { + throw soap::base::IOError("Bad file handle: " + filename); + } + + ofs << "DENSITY ON GRID" << std::endl; + ofs << "Generated by BasisCoefficients::writeDensityOnGrid" << std::endl; + ofs << boost::format("%1$d %2$+1.4f %3$+1.4f %4$+1.4f") + % structure->particles().size() % (r0.x()*conv) % (r0.y()*conv) % (r0.z()*conv) << std::endl; + ofs << boost::format("%1$d %2$+1.4f +0.0000 +0.0000") % Nx % (dx*conv) << std::endl; + ofs << boost::format("%1$d +0.0000 %2$+1.4f +0.0000") % Ny % (dy*conv) << std::endl; + ofs << boost::format("%1$d +0.0000 +0.0000 %2$+1.4f") % Nz % (dz*conv) << std::endl; + + Structure::particle_it_t pit; + for (pit = structure->beginParticles(); pit != structure->endParticles(); ++pit) { + vec dr = structure->connect(center->getPos(), (*pit)->getPos()); + ofs << boost::format("%1$d 0.0 %2$+1.4f %3$+1.4f %4$+1.4f\n") + % (*pit)->getTypeId() % (dr.x()*conv) % (dr.y()*conv) % (dr.z()*conv); + } + + GLOG() << "Fill grid " << std::flush; + double int_density_dr = 0.0; + int ijk = 0; + for (int i = -I; i <= I; ++i) { + if (((i+I) % 5) == 0) GLOG() << "." << std::flush; + for (int j = -I; j <= I; ++j) { + for (int k = -I; k <= I; ++k) { + double density_dr = 0.0; + + // Note that expansion is computed with respect to center-particle position: + // Hence no shifting required + vec dr(i*dx, j*dy, k*dz); + double r = soap::linalg::abs(dr); + vec d = dr/r; + + // DENSITY BASED ON EXPANSION + if (fromExpansion) { + BasisExpansion density_exp_dr(_basis); + density_exp_dr.computeCoefficients(r, d, 1., 0.); + density_exp_dr.conjugate(); + + BasisExpansion::coeff_t &c_nlm_dr = density_exp_dr.getCoefficients(); + BasisExpansion::coeff_t &c_nlm = this->getCoefficients(); + // Something like this would be desirable to replace n-l-m loop below: + //double density_dr = ub::inner_prod(c_nlm, c_nlm_dr); + for (int n = 0; n < _radbasis->N(); ++n) { + for (int l = 0; l <= _angbasis->L(); ++l) { + for (int m = -l; m <= l; ++m) { + double voxel_density_dr = (c_nlm(n, l*l+l+m)*c_nlm_dr(n, l*l+l+m)).real(); + density_dr += voxel_density_dr; + int_density_dr += voxel_density_dr*dx*dy*dz; + } + } + } + } + + // DENSITY BASED ON SMEARED PARTICLES + else { + for (pit = structure->beginParticles(); pit != structure->endParticles(); ++pit) { + vec dr_center_particle = structure->connect(center->getPos(), (*pit)->getPos()); + vec dr_particle_target = dr - dr_center_particle; + double r_particle_target = soap::linalg::abs(dr_particle_target); + double sigma = (*pit)->getSigma(); + double weight = (*pit)->getWeight(); + density_dr += weight*pow(1./(2.*M_PI*sigma*sigma), 1.5) + * exp(-r_particle_target*r_particle_target/(2*sigma*sigma)); + } + int_density_dr += density_dr*dx*dy*dz; + } + + ofs << density_dr << " "; + ijk += 1; + ijk = ijk % 6; + if (ijk == 0) { + ofs << std::endl; + } + + } + } + } + ofs.close(); + GLOG() << " Volume integral = " << int_density_dr << std::endl; + return; +} + } diff --git a/src/basis.hpp b/src/basis.hpp index 4fecaac6647660e10035b3f3c0f54b6f0489f446..a08e74f698c98187ede21f06427a8349ea70077f 100644 --- a/src/basis.hpp +++ b/src/basis.hpp @@ -21,27 +21,10 @@ namespace ub = boost::numeric::ublas; class Basis { public: - Basis(Options *options) : _options(options) { - GLOG() << "Configuring basis ..." << std::endl; - // CONFIGURE RADIAL BASIS - _radbasis = RadialBasisOutlet().create(_options->get<std::string>("radialbasis.type")); - _radbasis->configure(*options); - // CONFIGURE ANGULAR BASIS - _angbasis = AngularBasisOutlet().create(_options->get<std::string>("angularbasis.type")); - _angbasis->configure(*options); - // CONFIGURE CUTOFF FUNCTION - _cutoff = CutoffFunctionOutlet().create(_options->get<std::string>("radialcutoff.type")); - _cutoff->configure(*options); - } + Basis(Options *options); Basis() : _options(NULL), _radbasis(NULL), _angbasis(NULL), _cutoff(NULL) {;} - ~Basis() { - delete _radbasis; - _radbasis = NULL; - delete _angbasis; - _angbasis = NULL; - delete _cutoff; - _cutoff = NULL; - } + ~Basis(); + RadialBasis *getRadBasis() { return _radbasis; } AngularBasis *getAngBasis() { return _angbasis; } CutoffFunction *getCutoff() { return _cutoff; } @@ -68,162 +51,20 @@ public: typedef ub::matrix< std::complex<double> > coeff_t; typedef ub::zero_matrix< std::complex<double> > coeff_zero_t; - BasisExpansion(Basis *basis) : - _basis(basis), _radbasis(basis->getRadBasis()), _angbasis(basis->getAngBasis()) { - int L = _angbasis->L(); - int N = _radbasis->N(); - _radcoeff = RadialBasis::radcoeff_zero_t(N,L+1); - _angcoeff = AngularBasis::angcoeff_zero_t((L+1)*(L+1)); - _coeff = coeff_zero_t(N,(L+1)*(L+1)); - } - BasisExpansion() : - _basis(NULL), _radbasis(NULL), _angbasis(NULL) {;} - ~BasisExpansion() { - _basis = NULL; - _radbasis = NULL; - _angbasis = NULL; - _radcoeff.clear(); - _angcoeff.clear(); - } + BasisExpansion(Basis *basis); + BasisExpansion() : _basis(NULL), _radbasis(NULL), _angbasis(NULL) {;} + ~BasisExpansion(); + Basis *getBasis() { return _basis; } coeff_t &getCoefficients() { return _coeff; } - void computeCoefficients(double r, vec d, double weight, double sigma) { - _radbasis->computeCoefficients(r, sigma, _radcoeff); - _angbasis->computeCoefficients(d, r, _angcoeff); - for (int n = 0; n != _radbasis->N(); ++n) { - for (int l = 0; l != _angbasis->L()+1; ++l) { - for (int m = -l; m != l+1; ++m) { - _coeff(n, l*l+l+m) = _radcoeff(n,l)*_angcoeff(l*l+l+m); - } - } - } - _coeff *= weight; - return; - } - void add(BasisExpansion &other) { - _coeff = _coeff + other._coeff; - } - void conjugate() { - for (int n = 0; n != _radbasis->N(); ++n) { - for (int l = 0; l != _angbasis->L()+1; ++l) { - for (int m = -l; m != l+1; ++m) { - _coeff(n, l*l+l+m) = std::conj(_coeff(n, l*l+l+m)); - } - } - } - } - void writeDensityOnGrid( - std::string filename, - Options *options, - Structure *structure, - Particle *center, - bool fromExpansion) { - - if (_angbasis == NULL || _radbasis == NULL) { - throw soap::base::APIError("<BasisExpansion::writeDensityOnGrid> " - "Object not linked against basis."); - } - - int I = options->get<int>("densitygrid.N"); - int Nx = 2*I+1; - int Ny = Nx; - int Nz = Nx; - - double dx = options->get<double>("densitygrid.dx"); - double dy = dx; - double dz = dx; - - double conv = soap::constants::ANGSTROM_TO_BOHR; - - vec r0 = -I * vec(dx,dy,dz); - - std::ofstream ofs; - ofs.open(filename.c_str(), std::ofstream::out); - if (!ofs.is_open()) { - throw soap::base::IOError("Bad file handle: " + filename); - } - - ofs << "DENSITY ON GRID" << std::endl; - ofs << "Generated by BasisCoefficients::writeDensityOnGrid" << std::endl; - ofs << boost::format("%1$d %2$+1.4f %3$+1.4f %4$+1.4f") - % structure->particles().size() % (r0.x()*conv) % (r0.y()*conv) % (r0.z()*conv) << std::endl; - ofs << boost::format("%1$d %2$+1.4f +0.0000 +0.0000") % Nx % (dx*conv) << std::endl; - ofs << boost::format("%1$d +0.0000 %2$+1.4f +0.0000") % Ny % (dy*conv) << std::endl; - ofs << boost::format("%1$d +0.0000 +0.0000 %2$+1.4f") % Nz % (dz*conv) << std::endl; - - Structure::particle_it_t pit; - for (pit = structure->beginParticles(); pit != structure->endParticles(); ++pit) { - vec dr = structure->connect(center->getPos(), (*pit)->getPos()); - ofs << boost::format("%1$d 0.0 %2$+1.4f %3$+1.4f %4$+1.4f\n") - % (*pit)->getTypeId() % (dr.x()*conv) % (dr.y()*conv) % (dr.z()*conv); - } - - GLOG() << "Fill grid " << std::flush; - double int_density_dr = 0.0; - int ijk = 0; - for (int i = -I; i <= I; ++i) { - if (((i+I) % 5) == 0) GLOG() << "." << std::flush; - for (int j = -I; j <= I; ++j) { - for (int k = -I; k <= I; ++k) { - double density_dr = 0.0; - - // Note that expansion is computed with respect to center-particle position: - // Hence no shifting required - vec dr(i*dx, j*dy, k*dz); - double r = soap::linalg::abs(dr); - vec d = dr/r; - - // DENSITY BASED ON EXPANSION - if (fromExpansion) { - BasisExpansion density_exp_dr(_basis); - density_exp_dr.computeCoefficients(r, d, 1., 0.); - density_exp_dr.conjugate(); - - BasisExpansion::coeff_t &c_nlm_dr = density_exp_dr.getCoefficients(); - BasisExpansion::coeff_t &c_nlm = this->getCoefficients(); - // Something like this would be desirable to replace n-l-m loop below: - //double density_dr = ub::inner_prod(c_nlm, c_nlm_dr); - for (int n = 0; n < _radbasis->N(); ++n) { - for (int l = 0; l <= _angbasis->L(); ++l) { - for (int m = -l; m <= l; ++m) { - double voxel_density_dr = (c_nlm(n, l*l+l+m)*c_nlm_dr(n, l*l+l+m)).real(); - density_dr += voxel_density_dr; - int_density_dr += voxel_density_dr*dx*dy*dz; - } - } - } - } - - // DENSITY BASED ON SMEARED PARTICLES - else { - for (pit = structure->beginParticles(); pit != structure->endParticles(); ++pit) { - vec dr_center_particle = structure->connect(center->getPos(), (*pit)->getPos()); - vec dr_particle_target = dr - dr_center_particle; - double r_particle_target = soap::linalg::abs(dr_particle_target); - double sigma = (*pit)->getSigma(); - double weight = (*pit)->getWeight(); - density_dr += weight*pow(1./(2.*M_PI*sigma*sigma), 1.5) - * exp(-r_particle_target*r_particle_target/(2*sigma*sigma)); - } - int_density_dr += density_dr*dx*dy*dz; - } - - ofs << density_dr << " "; - ijk += 1; - ijk = ijk % 6; - if (ijk == 0) { - ofs << std::endl; - } - - } - } - } - ofs.close(); - GLOG() << " Volume integral = " << int_density_dr << std::endl; - return; - } RadialBasis::radcoeff_t &getRadCoeffs() { return _radcoeff; } - AngularBasis::angcoeff_t &getAngCoeffs() { return _angcoeff; } + AngularBasis::angcoeff_t &getAngCoeffs() { return _angcoeff; } + + void computeCoefficients(double r, vec d, double weight, double sigma); + void add(BasisExpansion &other) { _coeff = _coeff + other._coeff; } + void conjugate(); + void writeDensityOnGrid(std::string filename, Options *options, + Structure *structure, Particle *center, bool fromExpansion); template<class Archive> void serialize(Archive &arch, const unsigned int version) { @@ -243,149 +84,6 @@ private: coeff_t _coeff; // access via (n, l*l+l+m) }; - - -struct BasisCoefficients -{ - BasisCoefficients(RadialCoefficients &c_n, AngularCoefficients &c_lm) - : _c_n(c_n), _c_lm(c_lm), _radbasis(NULL), _angbasis(NULL) { - _c_nlm.resize(c_n.size(), c_lm.size()); - _c_nlm = ub::outer_prod(_c_n, _c_lm); - } - void linkBasis(RadialBasis *radbasis, AngularBasis *angbasis) { - _radbasis = radbasis; - _angbasis = angbasis; - } - std::complex<double> &get(int n, int l, int m) { - if (_c_lm.checkSize(l, m) && _c_n.checkSize(n)) { - return _c_nlm(n, l*l+l+m); - } - else { - throw soap::base::OutOfRange("BasisCoefficients::get"); - } - } - void add(BasisCoefficients &other) { - _c_nlm = _c_nlm + other._c_nlm; - } - - void writeDensityOnGrid( - std::string filename, - Options *options, - Structure *structure, - Particle *center, - bool fromExpansion) { - - if (_angbasis == NULL || _radbasis == NULL) { - throw soap::base::APIError("<BasisCoefficients::writeDensityOnGrid> " - "Object not linked against basis."); - } - - int I = options->get<int>("densitygrid.N"); - int Nx = 2*I+1; - int Ny = Nx; - int Nz = Nx; - - double dx = options->get<double>("densitygrid.dx"); - double dy = dx; - double dz = dx; - - double conv = soap::constants::ANGSTROM_TO_BOHR; - - vec r0 = -I * vec(dx,dy,dz); // center->getPos(); - - std::ofstream ofs; - ofs.open(filename.c_str(), std::ofstream::out); - if (!ofs.is_open()) { - throw soap::base::IOError("Bad file handle: " + filename); - } - - ofs << "DENSITY ON GRID" << std::endl; - ofs << "Generated by BasisCoefficients::writeDensityOnGrid" << std::endl; - ofs << boost::format("%1$d %2$+1.4f %3$+1.4f %4$+1.4f") - % structure->particles().size() % (r0.x()*conv) % (r0.y()*conv) % (r0.z()*conv) << std::endl; - ofs << boost::format("%1$d %2$+1.4f +0.0000 +0.0000") % Nx % (dx*conv) << std::endl; - ofs << boost::format("%1$d +0.0000 %2$+1.4f +0.0000") % Ny % (dy*conv) << std::endl; - ofs << boost::format("%1$d +0.0000 +0.0000 %2$+1.4f") % Nz % (dz*conv) << std::endl; - - Structure::particle_it_t pit; - for (pit = structure->beginParticles(); pit != structure->endParticles(); ++pit) { - vec dr = structure->connect(center->getPos(), (*pit)->getPos()); - ofs << boost::format("%1$d 0.0 %2$+1.4f %3$+1.4f %4$+1.4f\n") - % (*pit)->getTypeId() % (dr.x()*conv) % (dr.y()*conv) % (dr.z()*conv); - } - - GLOG() << "Fill grid " << std::flush; - double int_density_dr = 0.0; - int ijk = 0; - for (int i = -I; i <= I; ++i) { - if (((i+I) % 5) == 0) GLOG() << "." << std::flush; - for (int j = -I; j <= I; ++j) { - for (int k = -I; k <= I; ++k) { - double density_dr = 0.0; - - // Note that expansion is computed with respect to center-particle position: - // Hence no shifting required - vec dr(i*dx, j*dy, k*dz); - double r = soap::linalg::abs(dr); - vec d = dr/r; - - // DENSITY BASED ON EXPANSION - if (fromExpansion) { - RadialCoefficients c_n_dr = _radbasis->computeCoefficients(r); - AngularCoefficients c_lm_dr = _angbasis->computeCoefficients(d, r); - c_lm_dr.conjugate(); - BasisCoefficients c_nlm_dr(c_n_dr, c_lm_dr); - // Something like this would be desirable to replace n-l-m loop below: - //double density_dr = ub::inner_prod(c_nlm, c_nlm_dr); - for (int n = 0; n < _radbasis->N(); ++n) { - for (int l = 0; l <= _angbasis->L(); ++l) { - for (int m = -l; m <= l; ++m) { - double voxel_density_dr = (this->get(n, l, m)*c_nlm_dr.get(n, l, m)).real(); - density_dr += voxel_density_dr; - int_density_dr += voxel_density_dr*dx*dy*dz; - } - } - } - } - - // DENSITY BASED ON SMEARED PARTICLES - else { - for (pit = structure->beginParticles(); pit != structure->endParticles(); ++pit) { - vec dr_center_particle = structure->connect(center->getPos(), (*pit)->getPos()); - vec dr_particle_target = dr - dr_center_particle; - double r_particle_target = soap::linalg::abs(dr_particle_target); - double sigma = 0.5; - density_dr += pow(1./(2.*M_PI*sigma*sigma), 1.5) - * exp(-r_particle_target*r_particle_target/(2*sigma*sigma)); - } - int_density_dr += density_dr*dx*dy*dz; - } - - ofs << density_dr << " "; - ijk += 1; - ijk = ijk % 6; - if (ijk == 0) { - ofs << std::endl; - } - - } - } - } - - GLOG() << " Volume integral = " << int_density_dr << std::endl; - - ofs.close(); - - return; - } - - ub::matrix< std::complex<double> > _c_nlm; - RadialCoefficients _c_n; - AngularCoefficients _c_lm; - RadialBasis *_radbasis; - AngularBasis *_angbasis; -}; - } #endif diff --git a/src/cutoff.cpp b/src/cutoff.cpp index e0529bf772c27be06ff8a0600e5dd4d2b8260da2..df61c1dd3593747fbe9af16343c882f71d0fbb83 100644 --- a/src/cutoff.cpp +++ b/src/cutoff.cpp @@ -7,6 +7,11 @@ void CutoffFunction::configure(Options &options) { _Rc = options.get<double>("radialcutoff.Rc"); _Rc_width = options.get<double>("radialcutoff.Rc_width"); _center_weight = options.get<double>("radialcutoff.center_weight"); + + GLOG() << "Weighting function with " + << "Rc = " << _Rc + << ", _Rc_width = " << _Rc_width + << ", central weigth = " << _center_weight << std::endl; } void CutoffFunctionFactory::registerAll(void) { diff --git a/src/cutoff.hpp b/src/cutoff.hpp index b1dc8d70a3e6cda29fb7fb3a97495257134ad55d..439b8ebbb549530be775106742608a37e9d54d2d 100644 --- a/src/cutoff.hpp +++ b/src/cutoff.hpp @@ -7,6 +7,7 @@ #include "base/exceptions.hpp" #include "base/objectfactory.hpp" +#include "globals.hpp" #include "options.hpp" namespace soap { diff --git a/src/functions.cpp b/src/functions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f0586bd43917a31e82c56f358ec2eb5c31073ed8 --- /dev/null +++ b/src/functions.cpp @@ -0,0 +1,95 @@ +#include "functions.hpp" + +#include <boost/math/special_functions/erf.hpp> + +namespace soap { + +// ====================== +// RadialGaussian +// ====================== + +RadialGaussian::RadialGaussian(double r0, double sigma) +: _r0(r0), + _sigma(sigma), + _alpha(1./(2.*sigma*sigma)) { + + // COMPUTE NORMALIZATION S g^2 r^2 dr + // This normalization is to be used for radial basis functions + double w = 2*_alpha; + double W0 = 2*_alpha*_r0; + _integral_r2_g2_dr = + 1./(4.*pow(w, 2.5))*exp(-w*_r0*_r0)*( + 2*sqrt(w)*W0 + + sqrt(M_PI)*exp(W0*W0/w)*(w+2*W0*W0)*( + 1 - boost::math::erf<double>(-W0/sqrt(w)) + ) + ); + _norm_r2_g2_dr = 1./sqrt(_integral_r2_g2_dr); + + // COMPUTE NORMALIZATION S g r^2 dr + // This normalization is to be used for "standard" radial Gaussians + w = _alpha; + W0 = _alpha*_r0; + _integral_r2_g_dr = + 1./(4.*pow(w, 2.5))*exp(-w*_r0*_r0)*( + 2*sqrt(w)*W0 + + sqrt(M_PI)*exp(W0*W0/w)*(w+2*W0*W0)*( + 1 - boost::math::erf<double>(-W0/sqrt(w)) + ) + ); + _norm_r2_g_dr = 1./_integral_r2_g_dr; +} + +RadialGaussian::RadialGaussian() : + _r0(0.), + _sigma(0.), + _alpha(1./0.), + _integral_r2_g2_dr(0.), + _norm_r2_g2_dr(0.), + _integral_r2_g_dr(0.), + _norm_r2_g_dr(0.) { + ; +} + +double RadialGaussian::at(double r) { + double p = _alpha*(r-_r0)*(r-_r0); + if (p < 40) return _norm_r2_g2_dr * exp(-p); + else return 0.0; +} + +// ====================== +// SphericalGaussian +// ====================== + +SphericalGaussian::SphericalGaussian(vec r0, double sigma) : + _r0(r0), _sigma(sigma), _alpha(1./(2*sigma*sigma)) { + _norm_g_dV = pow(_alpha/M_PI, 1.5); +} + +// ====================== +// ModSphBessel1stKind +// ====================== + +std::vector<double> ModifiedSphericalBessel1stKind::eval(int degree, double r) { + std::vector<double> il; + if (r < RADZERO) { + il.push_back(1.); + il.push_back(0.); + } + else { + il.push_back(sinh(r)/r); + il.push_back(cosh(r)/r - sinh(r)/(r*r)); + } + for (int l = 2; l <= degree; ++l) { + if (r < RADZERO) { + il.push_back(0.); + } + else { + if (il[l-1] < SPHZERO) il.push_back(0.); + else il.push_back( il[l-2] - (2*(l-1)+1)/r*il[l-1] ); + } + } + return il; +} + +} /* CLOSE NAMESPACE */ diff --git a/src/functions.hpp b/src/functions.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c36807599de6dcf2901fbc1bdb4cf0418672248f --- /dev/null +++ b/src/functions.hpp @@ -0,0 +1,57 @@ +#ifndef _SOAP_FUNCTIONS_H +#define _SOAP_FUNCTIONS_H + +#include <math.h> +#include <vector> + +#include "types.hpp" + +namespace soap { + +struct RadialGaussian +{ + RadialGaussian(double r0, double sigma); + RadialGaussian(); + double at(double r); + + template<class Archive> + void serialize(Archive &arch, const unsigned int version) { + arch & _r0; + arch & _sigma; + arch & _alpha; + arch & _norm_r2_g2_dr; + arch & _norm_r2_g_dr; + } + + double _r0; + double _sigma; + double _alpha; + // Integral S g^2 r^2 dr + double _integral_r2_g2_dr; + double _norm_r2_g2_dr; + // Integral S g r^2 dr + double _integral_r2_g_dr; + double _norm_r2_g_dr; +}; + +struct SphericalGaussian +{ + SphericalGaussian(vec r0, double sigma); + + vec _r0; + double _sigma; + double _alpha; + double _norm_g_dV; +}; + +struct ModifiedSphericalBessel1stKind +{ + static std::vector<double> eval(int degree, double r); + static constexpr double RADZERO = 1e-10; + static constexpr double SPHZERO = 1e-4; +}; + + +} + +#endif diff --git a/src/options.cpp b/src/options.cpp index 97ec249d331c316353254887d32b621355f47e0e..279c3d0d178595b2e663e555da5b6291546e85ea 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -2,7 +2,41 @@ namespace soap { - + +Options::Options() : + _center_excludes(boost::python::list()) { + + // Set defaults + this->set("radialbasis.type", "gaussian"); + this->set("radialbasis.mode", "equispaced"); + this->set("radialbasis.N", 9); + this->set("radialbasis.sigma", 0.5); + this->set("radialbasis.integration_steps", 15); + this->set("radialcutoff.type", "shifted-cosine"); + this->set("radialcutoff.Rc", 4.); + this->set("radialcutoff.Rc_width", 0.5); + this->set("radialcutoff.center_weight", 1.); + this->set("angularbasis.type", "spherical-harmonic"); + this->set("angularbasis.L", 6); + this->set("densitygrid.N", 20); + this->set("densitygrid.dx", 0.15); +} + +//template<typename return_t> +//return_t Options::get(std::string key) { + //return soap::lexical_cast<return_t, std::string>(_key_value_map[key], "wrong or missing type in " + key); +//} + +std::string Options::summarizeOptions() { + std::string info = ""; + info += "Options:\n"; + std::map<std::string, std::string>::iterator it; + for (it = _key_value_map.begin(); it != _key_value_map.end(); ) { + info += (boost::format(" o %1$-30s : %2$s") % it->first % it->second).str(); + if (++it != _key_value_map.end()) info += "\n"; + } + return info; +} void Options::registerPython() { using namespace boost::python; @@ -11,11 +45,8 @@ void Options::registerPython() { void (Options::*set_string)(std::string, std::string) = &Options::set; class_<Options>("Options") - .def("configureRealBasis", &Options::configureRealBasis) - .def("configureReciprocalBasis", &Options::configureReciprocalBasis) .def("summarizeOptions", &Options::summarizeOptions) .def("configureCenters", &Options::configureCenters) - .def("configureReciprocalLattice", &Options::configureReciprocalLattice) .def("set", set_int) .def("set", set_double) .def("set", set_string); diff --git a/src/options.hpp b/src/options.hpp index e7cb8540d3259990a4b57d00184d8bd86b4eaadc..9f81594d809a2ab36a24755efa17346d1e9ba841 100644 --- a/src/options.hpp +++ b/src/options.hpp @@ -1,89 +1,37 @@ #ifndef _SOAP_OPTIONS_HPP #define _SOAP_OPTIONS_HPP + +#include <map> #include <boost/format.hpp> + #include "types.hpp" -#include <map> namespace soap { class Options { public: - Options() - : _N_real(8), _L_real(6), _Rc_real(5.), - _N_recip(8), _L_recip(6), _Rc_recip(5.), - _b1(vec(1,0,0)), _b2(vec(0,1,0)), _b3(vec(0,0,1)), - _center_w0(1.), _center_excludes(boost::python::list()) { - // SET DEFAULTS - this->set("radialbasis.integration_steps", 15); - this->set("radialbasis.mode", "equispaced"); - } - ~Options() {} + typedef std::map<std::string, std::string> map_options_t; + // CONSTRUCT & DESTRUCT + Options(); + ~Options() {} + + // GET & SET template<typename return_t> return_t get(std::string key) { return soap::lexical_cast<return_t, std::string>(_key_value_map[key], "wrong or missing type in " + key); } - void set(std::string key, std::string value) { _key_value_map[key] = value; } void set(std::string key, int value) { this->set(key, boost::lexical_cast<std::string>(value)); } void set(std::string key, double value) { this->set(key, boost::lexical_cast<std::string>(value)); } + void configureCenters(boost::python::list center_excludes) { _center_excludes = center_excludes; } + std::string summarizeOptions(); - /* - template<class value_t> - void set(std::string key, value_t value) { - std::cout << "value" << value << "_" << std::endl; - _key_value_map[key] = boost::lexical_cast<std::string>(value); - } - */ - - void configureRealBasis(int N_real, int L_real, double Rc_real, std::string type) { - _N_real = N_real; - _L_real = L_real; - _Rc_real = Rc_real; - _type_real = type; - _key_value_map["radialbasis.Rc"] = boost::lexical_cast<std::string>(_Rc_real); - _key_value_map["radialbasis.L"] = boost::lexical_cast<std::string>(_L_real); - _key_value_map["radialbasis.N"] = boost::lexical_cast<std::string>(_N_real); - _key_value_map["radialbasis.type"] = boost::lexical_cast<std::string>(_type_real); - } - void configureReciprocalBasis(int N_recip, int L_recip, double Rc_recip) { - _N_recip = N_recip; - _L_recip = L_recip; - _Rc_recip = Rc_recip; - } - void configureCenters(double center_w0, boost::python::list center_excludes) { - _center_w0 = center_w0; - _center_excludes = center_excludes; - } - void configureReciprocalLattice(vec b1, vec b2, vec b3) { - _b1 = b1; - _b2 = b2; - _b3 = b3; - } - std::string summarizeOptions() { - std::string info = ""; - info += "Options:\n"; -// info += "o Centers: "; -// info += (boost::format("W0=%1% Excl#=%2%\n") % _center_w0 % boost::python::len(_center_excludes)).str(); -// info += "o Real-space basis: "; -// info += (boost::format("N=%1% L=%2% Rc=%3%\n") % _N_real % _L_real % _Rc_real).str(); -// info += "o Reciprocal-space basis: "; -// info += (boost::format("N=%1% L=%2% Rc=%3%\n") % _N_recip % _L_recip % _Rc_recip).str(); -// info += "o Reciprocal-space lattice: "; -// info += (boost::format("b1x=%1% b1y=%2% b1z=%3% ") % _b1.x() % _b1.y() % _b1.z()).str(); -// info += (boost::format("b2x=%1% b2y=%2% b2z=%3% ") % _b2.x() % _b2.y() % _b2.z()).str(); -// info += (boost::format("b3x=%1% b3y=%2% b3z=%3% ") % _b3.x() % _b3.y() % _b3.z()).str(); - - std::map<std::string, std::string>::iterator it; - for (it = _key_value_map.begin(); it != _key_value_map.end(); ) { - info += (boost::format(" o %1$-30s : %2$s") % it->first % it->second).str(); - if (++it != _key_value_map.end()) info += "\n"; - } - return info; - } + // PYTHON static void registerPython(); + // SERIALIZATION template<class Archive> void serialize(Archive &arch, const unsigned int version) { arch & _key_value_map; @@ -91,24 +39,8 @@ public: } private: - // REAL SPACE - int _N_real; - int _L_real; - double _Rc_real; - std::string _type_real; - // RECIPROCAL SPACE - int _N_recip; - int _L_recip; - double _Rc_recip; - vec _b1; - vec _b2; - vec _b3; - // CENTERS - double _center_w0; boost::python::list _center_excludes; - - std::map<std::string, std::string> _key_value_map; - + map_options_t _key_value_map; }; } diff --git a/src/power.cpp b/src/power.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9fdca82ede7501d1055b6a2a2944f2965c9ed0dc --- /dev/null +++ b/src/power.cpp @@ -0,0 +1,6 @@ +#include "power.hpp" + +namespace soap { + +} + diff --git a/src/power.hpp b/src/power.hpp new file mode 100644 index 0000000000000000000000000000000000000000..de1dfc89fa1b318849164de7f45b40286708a6d2 --- /dev/null +++ b/src/power.hpp @@ -0,0 +1,42 @@ +#ifndef _SOAP_POWER_HPP +#define _SOAP_POWER_HPP + +#include <string> +#include <math.h> +#include <vector> +#include <fstream> + +#include "base/exceptions.hpp" +#include "basis.hpp" + +namespace soap { + +namespace ub = boost::numeric::ublas; + + +class PowerExpansion +{ +public: + typedef ub::matrix< std::complex<double> > coeff_t; + typedef ub::zero_matrix< std::complex<double> > coeff_zero_t; + + PowerExpansion() { + ; + } + PowerExpansion(BasisExpansion *basex) { + ; + } + + template<class Archive> + void serialize(Archive &arch, const unsigned int version) { + ; + } + +private: + + coeff_t _coeff; // access via (N*n+k, l) with shape (N*N, L+1) +}; + +} + +#endif diff --git a/src/radialbasis.cpp b/src/radialbasis.cpp index 92524099cb29265b3542568f11d2970854515d78..ae1b5372105bbbb819b1b0773c391434f5a72b61 100644 --- a/src/radialbasis.cpp +++ b/src/radialbasis.cpp @@ -23,33 +23,33 @@ namespace ub = boost::numeric::ublas; void RadialBasis::configure(Options &options) { _N = options.get<int>("radialbasis.N"); - _Rc = options.get<double>("radialcutoff.Rc"); + _Rc = options.get<double>("radialcutoff.Rc"); // <- !! Modified below for adaptive basis sets !! _integration_steps = options.get<int>("radialbasis.integration_steps"); _mode = options.get<std::string>("radialbasis.mode"); } -RadialCoefficients RadialBasis::computeCoefficients(double r) { - RadialCoefficients coeffs(this->_N); - throw soap::base::NotImplemented("RadialBasis::computeCoefficients"); - return coeffs; -} - void RadialBasis::computeCoefficients(double r, double particle_sigma, radcoeff_t &save_here) { throw soap::base::NotImplemented("RadialBasis::computeCoefficients"); return; } -RadialCoefficients RadialBasis::computeCoefficientsAllZero() { - RadialCoefficients coeffs(this->_N); - for (int i = 0; i < _N; ++i) coeffs(i) = 0.0; - return coeffs; -} - - // ====================== // RadialBasisGaussian // ====================== +RadialBasisGaussian::RadialBasisGaussian() { + _type = "gaussian"; + _is_ortho = false; + _sigma = 0.5; +} + +void RadialBasisGaussian::clear() { + for (basis_it_t bit=_basis.begin(); bit!=_basis.end(); ++bit) { + delete *bit; + } + _basis.clear(); +} + void RadialBasisGaussian::configure(Options &options) { RadialBasis::configure(options); _sigma = options.get<double>("radialbasis.sigma"); @@ -68,10 +68,10 @@ void RadialBasisGaussian::configure(Options &options) { } else if (_mode == "adaptive") { //double delta = 0.5; - int L = 6; + int L = options.get<int>("angularbasis.L"); double r = 0.; double sigma = 0.; - double sigma_0 = 0.5; + double sigma_0 = _sigma; double sigma_stride_factor = 0.5; // while (r < _Rc) { // sigma = sqrt(4./(2*L+1))*(r+delta); @@ -82,7 +82,7 @@ void RadialBasisGaussian::configure(Options &options) { for (int i = 0; i < _N; ++i) { //sigma = sqrt(4./(2*L+1))*(r+delta); sigma = sqrt(4./(2*L+1)*r*r + sigma_0*sigma_0); - std::cout << r << " " << sigma << std::endl; + //std::cout << r << " " << sigma << std::endl; r = r + sigma_stride_factor*sigma; } double scale = 1.; //_Rc/(r-sigma); @@ -91,9 +91,13 @@ void RadialBasisGaussian::configure(Options &options) { sigma = sqrt(4./(2*L+1)*r*r + sigma_0*sigma_0); basis_fct_t *new_fct = new basis_fct_t(scale*r, sigma); _basis.push_back(new_fct); - std::cout << r << " " << sigma << std::endl; + //std::cout << r << " " << sigma << std::endl; r = r+sigma_stride_factor*sigma; } + _Rc = r - sigma_stride_factor*sigma; + options.set("radialcutoff.Rc", _Rc); + GLOG() << "Adjusted radial cutoff to " << _Rc + << " based on sigma_0 = " << sigma_0 << ", L = " << L << ", stride = " << sigma_stride_factor << std::endl; } else { throw std::runtime_error("Not implemented."); @@ -167,67 +171,6 @@ void RadialBasisGaussian::configure(Options &options) { } } -RadialCoefficients RadialBasisGaussian::computeCoefficients(double r) { - - ub::vector<double> coeffs_raw(_N); - basis_it_t it; - int i; - for (it = _basis.begin(), i = 0; it != _basis.end(); ++it, ++i) { - coeffs_raw(i) = (*it)->at(r); - } - - coeffs_raw = ub::prod(_Tij, coeffs_raw); - - RadialCoefficients coeffs(this->_N); - for (int n = 0; n < _N; ++n) { - coeffs.set(n, coeffs_raw(n)); - } - - return coeffs; -} - -struct SphericalGaussian -{ - SphericalGaussian(vec r0, double sigma) : - _r0(r0), _sigma(sigma), _alpha(1./(2*sigma*sigma)) { - _norm_g_dV = pow(_alpha/M_PI, 1.5); - } - - vec _r0; - double _sigma; - double _alpha; - double _norm_g_dV; -}; - -struct ModifiedSphericalBessel1stKind -{ - static std::vector<double> eval(int degree, double r) { - std::vector<double> il; - if (r < RADZERO) { - il.push_back(1.); - il.push_back(0.); - } - else { - il.push_back(sinh(r)/r); - il.push_back(cosh(r)/r - sinh(r)/(r*r)); - } - for (int l = 2; l <= degree; ++l) { - if (r < RADZERO) { - il.push_back(0.); - } - else { - if (il[l-1] < SPHZERO) il.push_back(0.); - else il.push_back( il[l-2] - (2*(l-1)+1)/r*il[l-1] ); - } - } - return il; - } - - static constexpr double RADZERO = 1e-10; - static constexpr double SPHZERO = 1e-4; -}; - - void RadialBasisGaussian::computeCoefficients(double r, double particle_sigma, radcoeff_t &save_here) { // Delta-type expansion => // Second (l) dimension of <save_here> and <particle_sigma> ignored here @@ -389,50 +332,6 @@ void RadialBasisGaussian::computeCoefficients(double r, double particle_sigma, r return; } - -// ====================== -// RadialGaussian -// ====================== - -RadialGaussian::RadialGaussian(double r0, double sigma) -: _r0(r0), - _sigma(sigma), - _alpha(1./(2.*sigma*sigma)) { - - // COMPUTE NORMALIZATION S g^2 r^2 dr - // This normalization is to be used for radial basis functions - double w = 2*_alpha; - double W0 = 2*_alpha*_r0; - _integral_r2_g2_dr = - 1./(4.*pow(w, 2.5))*exp(-w*_r0*_r0)*( - 2*sqrt(w)*W0 + - sqrt(M_PI)*exp(W0*W0/w)*(w+2*W0*W0)*( - 1 - boost::math::erf<double>(-W0/sqrt(w)) - ) - ); - _norm_r2_g2_dr = 1./sqrt(_integral_r2_g2_dr); - - // COMPUTE NORMALIZATION S g r^2 dr - // This normalization is to be used for "standard" radial Gaussians - w = _alpha; - W0 = _alpha*_r0; - _integral_r2_g_dr = - 1./(4.*pow(w, 2.5))*exp(-w*_r0*_r0)*( - 2*sqrt(w)*W0 + - sqrt(M_PI)*exp(W0*W0/w)*(w+2*W0*W0)*( - 1 - boost::math::erf<double>(-W0/sqrt(w)) - ) - ); - _norm_r2_g_dr = 1./_integral_r2_g_dr; -} - -double RadialGaussian::at(double r) { - double p = _alpha*(r-_r0)*(r-_r0); - if (p < 40) return _norm_r2_g2_dr * exp(-p); - else return 0.0; -} - - // ====================== // RadialBasisFactory // ====================== diff --git a/src/radialbasis.hpp b/src/radialbasis.hpp index 041b9a39a4602723777472c5f7d7f79198ce4048..d1ab523729dbd30dc794638158bb5a6a618f1271 100644 --- a/src/radialbasis.hpp +++ b/src/radialbasis.hpp @@ -9,29 +9,17 @@ #include "base/exceptions.hpp" #include "base/objectfactory.hpp" #include "options.hpp" +#include "functions.hpp" namespace soap { namespace ub = boost::numeric::ublas; -class RadialCoefficients : public ub::vector<double> -{ -public: - RadialCoefficients(int N) { - this->resize(N); - for (int i = 0; i < N; ++i) (*this)[i] = 0.0; - } - void set(int n, double c) { - if (this->checkSize(n)) (*this)[n] = c; - else throw soap::base::OutOfRange("RadialCoefficients::set"); - } - double &get(int n) { - if (this->checkSize(n)) return (*this)[n]; - else throw soap::base::OutOfRange("RadialCoefficients::get"); - } - bool checkSize(int n) { return this->size() > n; } -}; - +// CLASSES IN THIS HEADER +// RadialBasis +// RadialBasisGaussian +// RadialBasisLegendre +// RadialBasisFactory class RadialBasis { @@ -39,13 +27,13 @@ public: typedef ub::matrix<double> radcoeff_t; typedef ub::zero_matrix<double> radcoeff_zero_t; + virtual ~RadialBasis() {;} + std::string &identify() { return _type; } const int &N() { return _N; } - virtual ~RadialBasis() {;} + virtual void configure(Options &options); - virtual RadialCoefficients computeCoefficients(double r); virtual void computeCoefficients(double r, double particle_sigma, radcoeff_t &save_here); - virtual RadialCoefficients computeCoefficientsAllZero(); template<class Archive> void serialize(Archive &arch, const unsigned int version) { @@ -57,42 +45,17 @@ public: } protected: - bool _is_ortho; std::string _type; int _N; double _Rc; int _integration_steps; std::string _mode; // <- 'equispaced' or 'adaptive' + bool _is_ortho; static constexpr double RADZERO = 1e-10; }; -struct RadialGaussian -{ - RadialGaussian(double r0, double sigma); - RadialGaussian() {;} - double at(double r); - double _r0; - double _sigma; - double _alpha; - // Integral S g^2 r^2 dr - double _integral_r2_g2_dr; - double _norm_r2_g2_dr; - // Integral S g r^2 dr - double _integral_r2_g_dr; - double _norm_r2_g_dr; - - template<class Archive> - void serialize(Archive &arch, const unsigned int version) { - arch & _r0; - arch & _sigma; - arch & _alpha; - arch & _norm_r2_g2_dr; - arch & _norm_r2_g_dr; - } -}; - class RadialBasisGaussian : public RadialBasis { public: @@ -100,22 +63,11 @@ public: typedef std::vector<RadialGaussian*> basis_t; typedef basis_t::iterator basis_it_t; - RadialBasisGaussian() { - _type = "gaussian"; - _is_ortho = false; - _sigma = 0.5; - } - ~RadialBasisGaussian() { - this->clear(); - } - void clear() { - for (basis_it_t bit=_basis.begin(); bit!=_basis.end(); ++bit) { - delete *bit; - } - _basis.clear(); + RadialBasisGaussian(); + ~RadialBasisGaussian() { this->clear(); } + void clear(); void configure(Options &options); - RadialCoefficients computeCoefficients(double r); void computeCoefficients(double r, double particle_sigma, radcoeff_t &save_here); template<class Archive> @@ -131,20 +83,14 @@ public: protected: double _sigma; basis_t _basis; + // ORTHONORMALIZATION ub::matrix<double> _Sij; // Overlap ub::matrix<double> _Uij; // Cholesky factor ub::matrix<double> _Tij; // Transformation matrix - }; - - - - - - class RadialBasisLegendre : public RadialBasis { public: @@ -155,7 +101,6 @@ public: }; - class RadialBasisFactory : public soap::base::ObjectFactory<std::string, RadialBasis> { @@ -183,7 +128,7 @@ inline RadialBasis *RadialBasisFactory::create(const std::string &key) { } } -} +} /* CLOSE NAMESPACE */ BOOST_CLASS_EXPORT_KEY(soap::RadialBasis); BOOST_CLASS_EXPORT_KEY(soap::RadialBasisGaussian); diff --git a/src/spectrum.cpp b/src/spectrum.cpp index 12b535f053c3c3e254f20347619be865943d7495..0428ca79830f5e36e42a99c9a685ecbaf5c79e86 100644 --- a/src/spectrum.cpp +++ b/src/spectrum.cpp @@ -81,9 +81,9 @@ void Spectrum::writeDensityOnGrid(int slot_idx, std::string center_type, std::st } // WRITE CUBE FILES if (atomic_spectrum) { - atomic_spectrum->getExpansion(density_type)->writeDensityOnGrid( + atomic_spectrum->getQnlm(density_type)->writeDensityOnGrid( "density.expanded.cube", _options, _structure, atomic_spectrum->getCenter(), true); - atomic_spectrum->getExpansion(density_type)->writeDensityOnGrid( + atomic_spectrum->getQnlm(density_type)->writeDensityOnGrid( "density.explicit.cube", _options, _structure, atomic_spectrum->getCenter(), false); } return; @@ -94,9 +94,6 @@ AtomicSpectrum *Spectrum::computeAtomic(Particle *center) { GLOG() << "Compute atomic spectrum for particle " << center->getId() << " (type " << center->getType() << ")" << std::endl; - std::string type_this = center->getType(); - - // RadialCoefficients c_n_zero = _radbasis->computeCoefficientsAllZero(); // AngularCoefficients c_lm_zero = _angbasis->computeCoefficientsAllZero(); // BasisCoefficients c_nlm(c_n_zero, c_lm_zero); @@ -108,11 +105,11 @@ AtomicSpectrum *Spectrum::computeAtomic(Particle *center) { Structure::particle_it_t pit; for (pit = _structure->beginParticles(); pit != _structure->endParticles(); ++pit) { - // FIND DISTANCE & DIRECTION, APPLY CUTOFF + // FIND DISTANCE & DIRECTION, APPLY CUTOFF (= WEIGHT REDUCTION) vec dr = _structure->connect(center->getPos(), (*pit)->getPos()); double r = soap::linalg::abs(dr); double weight_scale = this->_basis->getCutoff()->calculateWeight(r); - if (weight_scale < 0.) continue; + if (weight_scale < 0.) continue; // <- Negative cutoff weight means: skip vec d = dr/r; // APPLY WEIGHT IF CENTER @@ -124,7 +121,7 @@ AtomicSpectrum *Spectrum::computeAtomic(Particle *center) { BasisExpansion nb_expansion(this->_basis); nb_expansion.computeCoefficients(r, d, weight_scale*(*pit)->getWeight(), (*pit)->getSigma()); std::string type_other = (*pit)->getType(); - atomic_spectrum->add(type_other, nb_expansion); + atomic_spectrum->addQnlm(type_other, nb_expansion); // nbhood_expansion->add(nb_expansion); diff --git a/src/spectrum.hpp b/src/spectrum.hpp index 5af86db10266db250960ffa8dbe7c6af8a8d85f0..cb9ea9a2043e90853e4ff8c4e4c8d854cc4c38dd 100644 --- a/src/spectrum.hpp +++ b/src/spectrum.hpp @@ -13,107 +13,14 @@ #include "options.hpp" #include "structure.hpp" #include "basis.hpp" +#include "power.hpp" +#include "atomicspectrum.hpp" namespace soap { -class AtomicSpectrum : public std::map<std::string, BasisExpansion*> -{ -public: - AtomicSpectrum(Particle *center, Basis *basis) : - _center(center), - _center_pos(center->getPos()), - _center_type(center->getType()), - _basis(basis) { - _expansion_reduced = new BasisExpansion(_basis); - } - AtomicSpectrum() : - _center(NULL), - _center_pos(vec(0,0,0)), - _center_type("?"), - _basis(NULL), - _expansion_reduced(NULL) { ; } - ~AtomicSpectrum() { - iterator it; - for (it = this->begin(); it != this->end(); ++it) delete it->second; - this->clear(); - delete _expansion_reduced; - } - void add(std::string type, BasisExpansion &nb_expansion) { - assert(nb_expansion.getBasis() == _basis && - "Should not sum expansions linked against different bases."); - iterator it = this->find(type); - if (it == this->end()) { - (*this)[type] = new BasisExpansion(_basis); - it = this->find(type); - } - it->second->add(nb_expansion); - _expansion_reduced->add(nb_expansion); - return; - } - Particle *getCenter() { return _center; } - std::string &getCenterType() { return _center_type; } - vec &getCenterPos() { return _center_pos; } - BasisExpansion *getReduced() { return _expansion_reduced; } - BasisExpansion *getExpansion(std::string type) { - if (type == "") { - return _expansion_reduced; - } - iterator it = this->find(type); - if (it == this->end()) { - throw soap::base::OutOfRange("AtomicSpectrum: No such type '" + type + "'"); - return NULL; - } - else { - return it->second; - } - } - Basis *getBasis() { return _basis; } - - template<class Archive> - void serialize(Archive &arch, const unsigned int version) { - arch & _center; - arch & _center_pos; - arch & _center_type; - arch & _basis; - arch & _expansion_reduced; - return; - } -protected: - Particle *_center; - vec _center_pos; - std::string _center_type; - Basis *_basis; - BasisExpansion *_expansion_reduced; - //std::map<std::string, BasisExpansion*> _map_type_expansion; -}; - - -class CenterDensity -{ - CenterDensity() {} -}; - - -class TargetDensity -{ - TargetDensity() {} -}; - -class Center -{ - Center() {} -}; - -class Target -{ - Target() {} -}; - -// Need this: Spectrum(System1, System2, options) where Sys1 <> Sources, Sys2 <> Targets - - +// TODO Spectrum(System1, System2, options) where Sys1 <> Sources, Sys2 <> Targets class Spectrum { public: @@ -162,10 +69,6 @@ private: }; - - - - class PairSpectrum { public: diff --git a/src/structure.cpp b/src/structure.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d9f25c983adae643ebb04e301145f33a1cf52422 --- /dev/null +++ b/src/structure.cpp @@ -0,0 +1,167 @@ +#include "structure.hpp" + + +namespace soap { + +// ======== +// PARTICLE +// ======== + +void Particle::null() { + _id = -1; + _pos = vec(0,0,0); + _name = "?"; + _type_id = -1; + _type = "?"; + _mass = 0.; + _weight = 0.; + _sigma = 0.; + _segment = NULL; +} + +boost::python::numeric::array Particle::getPosNumeric() { + boost::python::numeric::array pos(boost::python::make_tuple(_pos.x(), _pos.y(), _pos.z())); return pos; +} + +void Particle::registerPython() { + using namespace boost::python; + class_<Particle, Particle*>("Particle", init<int>()) + .add_property("pos", &Particle::getPosNumeric, &Particle::setPosNumeric) + .add_property("id", &Particle::getId, &Particle::setId) + .add_property("name", make_function(&Particle::getName, copy_non_const()), &Particle::setName) + .add_property("type", make_function(&Particle::getType, copy_non_const()), &Particle::setType) + .add_property("type_id", make_function(&Particle::getTypeId, copy_non_const()), &Particle::setTypeId) + .add_property("mass", make_function(&Particle::getMass, copy_non_const()), &Particle::setMass) + .add_property("weight", make_function(&Particle::getWeight, copy_non_const()), &Particle::setWeight) + .add_property("sigma", make_function(&Particle::getSigma, copy_non_const()), &Particle::setSigma); +} + +// ======= +// SEGMENT +// ======= + +Particle &Segment::addParticle(Particle *new_part) { + _particles.push_back(new_part); + return *new_part; +} + +void Segment::registerPython() { + using namespace boost::python; + class_<Segment>("Segment", init<int>()) + .def("addParticle", &Segment::addParticle, return_value_policy<reference_existing_object>()); +} + + +// ========= +// STRUCTURE +// ========= + +Structure::Structure(std::string label) { + this->null(); + _label = label; + +} + +Structure::Structure() { + this->null(); +} + +void Structure::null() { + _id = -1; + _label = "?"; + _box = NULL; + _center = NULL; + _has_center = false; + matrix box; + box.ZeroMatrix(); + this->setBoundary(box); +} + +Structure::~Structure() { + delete _box; + _box = NULL; + segment_it_t sit; + for (sit = _segments.begin(); sit != _segments.end(); ++sit) { + delete *sit; + } + _segments.clear(); + particle_it_t pit; + for (pit = _particles.begin(); pit != _particles.end(); ++pit) { + delete *pit; + } + _particles.clear(); +} + +Segment &Structure::addSegment() { + int id = _segments.size()+1; + Segment *new_seg = new Segment(id); + _segments.push_back(new_seg); + return *new_seg; +} + +Particle &Structure::addParticle(Segment &seg) { + int id = _particles.size()+1; + Particle *new_part = new Particle(id); + _particles.push_back(new_part); + seg.addParticle(new_part); + return *new_part; +} + +boost::python::numeric::array Structure::connectNumeric( + const boost::python::numeric::array &a1, + const boost::python::numeric::array &a2) { + vec r1(a1); + vec r2(a2); + vec dr = this->connect(r1, r2); + return boost::python::numeric::array(boost::python::make_tuple( + dr.x(), dr.y(), dr.z())); +} + +void Structure::setBoundary(const matrix &box) { + delete _box; + if(box.get(0,0)==0 && box.get(0,1)==0 && box.get(0,2)==0 && + box.get(1,0)==0 && box.get(1,1)==0 && box.get(1,2)==0 && + box.get(2,0)==0 && box.get(2,1)==0 && box.get(2,2)==0) { + _box = new BoundaryOpen(box); + } + else if(box.get(0,1)==0 && box.get(0,2)==0 && + box.get(1,0)==0 && box.get(1,2)==0 && + box.get(2,0)==0 && box.get(2,1)==0) { + _box = new BoundaryOrthorhombic(box); + } + else { + _box = new BoundaryTriclinic(box); + } + return; +} + +void Structure::setBoundaryNumeric(const boost::python::numeric::array &m) { + matrix box(m); + this->setBoundary(box); +} + +boost::python::numeric::array Structure::getBoundaryNumeric() { + matrix box = _box->getBox(); + boost::python::numeric::array box_np(boost::python::make_tuple( + box.get(0,0), box.get(0,1), box.get(0,2), + box.get(1,0), box.get(1,1), box.get(1,2), + box.get(2,0), box.get(2,1), box.get(2,2))); + box_np.resize(3,3); + return box_np; +} + +void Structure::registerPython() { + using namespace boost::python; + class_<Structure>("Structure", init<std::string>()) + .def("addSegment", &Structure::addSegment, return_value_policy<reference_existing_object>()) + .def("addParticle", &Structure::addParticle, return_value_policy<reference_existing_object>()) + .def("__iter__", range<return_value_policy<reference_existing_object> >(&Structure::beginParticles, &Structure::endParticles)) + .add_property("particles", range<return_value_policy<reference_existing_object> >(&Structure::beginParticles, &Structure::endParticles)) + .def("connect", &Structure::connectNumeric) + .add_property("box", &Structure::getBoundaryNumeric, &Structure::setBoundaryNumeric) + .add_property("label", make_function(&Structure::getLabel, copy_non_const()), &Structure::setLabel); + class_<particle_array_t>("ParticleContainer") + .def(vector_indexing_suite<particle_array_t>()); +} + +} /* CLOSE NAMESPACE */ diff --git a/src/structure.hpp b/src/structure.hpp index 523e0b5cdf1d562a8c3de07a1cd9740394557e7b..2834d2caa6bce587af66fafa26d0f7497f41770c 100644 --- a/src/structure.hpp +++ b/src/structure.hpp @@ -18,58 +18,40 @@ class Structure; class Particle { public: - Particle(int id) : - _id(id), _pos(vec(0,0,0)), _name(""), - _type_id(-1), _type(""), _mass(.0), - _weight(.0), _sigma(.0), _segment(NULL) { ; } - Particle() : - _id(-1), _pos(vec(0,0,0)), _name(""), - _type_id(-1), _type(""), _mass(.0), - _weight(.0), _sigma(.0), _segment(NULL) { ; } - ~Particle() { - ; - } - - static void registerPython() { - using namespace boost::python; - class_<Particle, Particle*>("Particle", init<int>()) - .add_property("pos", &Particle::getPosNumeric, &Particle::setPosNumeric) - .add_property("id", &Particle::getId, &Particle::setId) - .add_property("name", make_function(&Particle::getName, copy_non_const()), &Particle::setName) - .add_property("type", make_function(&Particle::getType, copy_non_const()), &Particle::setType) - .add_property("type_id", make_function(&Particle::getTypeId, copy_non_const()), &Particle::setTypeId) - .add_property("mass", make_function(&Particle::getMass, copy_non_const()), &Particle::setMass) - .add_property("weight", make_function(&Particle::getWeight, copy_non_const()), &Particle::setWeight) - .add_property("sigma", make_function(&Particle::getSigma, copy_non_const()), &Particle::setSigma); - } - + Particle(int id) { this->null(); _id = id; } + Particle() { this->null(); } + ~Particle() {;} + void null(); + // Position void setPos(vec &pos) { _pos = pos; } void setPos(double x, double y, double z) { _pos = vec(x,y,z); } - void setPosNumeric(const boost::python::numeric::array &pos) { _pos = vec(pos); } vec &getPos() { return _pos; } - boost::python::numeric::array getPosNumeric() { boost::python::numeric::array pos(boost::python::make_tuple(_pos.x(), _pos.y(), _pos.z())); return pos; } - + void setPosNumeric(const boost::python::numeric::array &pos) { _pos = vec(pos); } + boost::python::numeric::array getPosNumeric(); + // Name void setName(std::string name) { _name = name; } std::string &getName() { return _name; } - + // Id void setId(int id) { _id = id; } int getId() { return _id; } - + // Type Id void setTypeId(int id) { _type_id = id; } int &getTypeId() { return _type_id; } - + // Type void setType(std::string type) { _type = type; } std::string &getType() { return _type; } - + // Mass void setMass(double mass) { _mass = mass; } double &getMass() { return _mass; } - + // Weight void setWeight(double weight) { _weight = weight; } double &getWeight() { return _weight; } - + // Sigma void setSigma(double sigma) { _sigma = sigma; } double &getSigma() { return _sigma; } + static void registerPython(); + template<class Archive> void serialize(Archive &arch, const unsigned int version) { arch & _segment; @@ -86,7 +68,7 @@ public: private: Segment *_segment; - // Book-keeping + // Labels int _id; std::string _name; int _type_id; @@ -102,20 +84,15 @@ private: class Segment { public: + typedef std::vector<Particle*> particle_array_t; + Segment(int id) : _id(id) { ; } Segment() : _id(-1) { ; } - ~Segment() { - _particles.clear(); - } - static void registerPython() { - using namespace boost::python; - class_<Segment>("Segment", init<int>()) - .def("addParticle", &Segment::addParticle, return_value_policy<reference_existing_object>()); - } - Particle &addParticle(Particle *new_part) { - _particles.push_back(new_part); - return *new_part; - } + ~Segment() { _particles.clear(); } + + Particle &addParticle(Particle *new_part); + + static void registerPython(); template<class Archive> void serialize(Archive &arch, const unsigned int version) { @@ -126,114 +103,44 @@ public: private: int _id; - std::vector<Particle*> _particles; + particle_array_t _particles; }; class Structure { public: + typedef std::vector<Particle*> particle_array_t; typedef std::vector<Particle*>::iterator particle_it_t; + typedef std::vector<Segment*> segment_array_t; + typedef std::vector<Segment*>::iterator segment_it_t; + + Structure(std::string label); + Structure(); + ~Structure(); + void null(); + + particle_array_t &particles() { return _particles; } + particle_it_t beginParticles() { return _particles.begin(); } + particle_it_t endParticles() { return _particles.end(); } - Structure(std::string label) : _id(-1), _label(label), _box(NULL) { - matrix box; - box.ZeroMatrix(); - this->setBoundary(box); - } - Structure() : _id(-1), _label("?"), _box(NULL) { - matrix box; - box.ZeroMatrix(); - this->setBoundary(box); - } - ~Structure() { - delete _box; - _box = NULL; - std::vector<Segment*>::iterator sit; - for (sit = _segments.begin(); sit != _segments.end(); ++sit) { - delete *sit; - } - _segments.clear(); - std::vector<Particle*>::iterator pit; - for (pit = _particles.begin(); pit != _particles.end(); ++pit) { - delete *pit; - } - _particles.clear(); - } - static void registerPython() { - using namespace boost::python; - class_<Structure>("Structure", init<std::string>()) - .def("addSegment", &Structure::addSegment, return_value_policy<reference_existing_object>()) - .def("addParticle", &Structure::addParticle, return_value_policy<reference_existing_object>()) - .def("__iter__", range<return_value_policy<reference_existing_object> >(&Structure::beginParticles, &Structure::endParticles)) - .add_property("particles", range<return_value_policy<reference_existing_object> >(&Structure::beginParticles, &Structure::endParticles)) - .def("connect", &Structure::connectNumeric) - .add_property("box", &Structure::getBoundaryNumeric, &Structure::setBoundaryNumeric) - .add_property("label", make_function(&Structure::getLabel, copy_non_const()), &Structure::setLabel); - class_< std::vector<Particle*> >("ParticleContainer") - .def(vector_indexing_suite<std::vector<Particle*> >()); - } - std::vector<Particle*> &particles() { return _particles; } - std::vector<Particle*>::iterator beginParticles() { return _particles.begin(); } - std::vector<Particle*>::iterator endParticles() { return _particles.end(); } std::string &getLabel() { return _label; } void setLabel(std::string label) { _label = label; } + // PARTICLE CREATION & INTERFACE - Segment &addSegment() { - int id = _segments.size()+1; - Segment *new_seg = new Segment(id); - _segments.push_back(new_seg); - return *new_seg; - } - Particle &addParticle(Segment &seg) { - int id = _particles.size()+1; - Particle *new_part = new Particle(id); - _particles.push_back(new_part); - seg.addParticle(new_part); - return *new_part; - } + Segment &addSegment(); + Particle &addParticle(Segment &seg); + // BOUNDARY CREATION & INTERFACE - vec connect(const vec &r1, const vec &r2) { - return _box->connect(r1, r2); // Points from r1 to r2 - } - boost::python::numeric::array connectNumeric( - const boost::python::numeric::array &a1, - const boost::python::numeric::array &a2) { - vec r1(a1); - vec r2(a2); - vec dr = this->connect(r1, r2); - return boost::python::numeric::array(boost::python::make_tuple( - dr.x(), dr.y(), dr.z())); - } - void setBoundary(const matrix &box) { - delete _box; - if(box.get(0,0)==0 && box.get(0,1)==0 && box.get(0,2)==0 && - box.get(1,0)==0 && box.get(1,1)==0 && box.get(1,2)==0 && - box.get(2,0)==0 && box.get(2,1)==0 && box.get(2,2)==0) { - _box = new BoundaryOpen(box); - } - else if(box.get(0,1)==0 && box.get(0,2)==0 && - box.get(1,0)==0 && box.get(1,2)==0 && - box.get(2,0)==0 && box.get(2,1)==0) { - _box = new BoundaryOrthorhombic(box); - } - else { - _box = new BoundaryTriclinic(box); - } - return; - } - void setBoundaryNumeric(const boost::python::numeric::array &m) { - matrix box(m); - this->setBoundary(box); - } - boost::python::numeric::array getBoundaryNumeric() { - matrix box = _box->getBox(); - boost::python::numeric::array box_np(boost::python::make_tuple( - box.get(0,0), box.get(0,1), box.get(0,2), - box.get(1,0), box.get(1,1), box.get(1,2), - box.get(2,0), box.get(2,1), box.get(2,2))); - box_np.resize(3,3); - return box_np; - } + void setBoundary(const matrix &box); + vec connect(const vec &r1, const vec &r2) { return _box->connect(r1, r2); /* 1->2 */ } + void setBoundaryNumeric(const boost::python::numeric::array &m); + boost::python::numeric::array getBoundaryNumeric(); + boost::python::numeric::array connectNumeric( + const boost::python::numeric::array &a1, + const boost::python::numeric::array &a2); + + static void registerPython(); template<class Archive> void serialize(Archive &arch, const unsigned int version) { @@ -248,8 +155,11 @@ public: private: int _id; std::string _label; - std::vector<Segment*> _segments; - std::vector<Particle*> _particles; + segment_array_t _segments; + particle_array_t _particles; + + Particle* _center; + bool _has_center; Boundary *_box; }; diff --git a/src/tools/loadwrite.py b/src/tools/loadwrite.py index 0a4caba7438d8eb878caa4500cd1fba56ae33d63..a4d43dd3195c8f31c484774f58fc396e9baf73f3 100644 --- a/src/tools/loadwrite.py +++ b/src/tools/loadwrite.py @@ -20,7 +20,11 @@ def write_xyz(xyz_file, structure): def ase_load_all(folder): cwd = os.getcwd() os.chdir(folder) - config_files = sorted(os.listdir('./')) + config_listdir = sorted(os.listdir('./')) + config_files = [] + for config_file in config_listdir: + if os.path.isfile(config_file): + config_files.append(config_file) ase_config_list = AseConfigList(config_files) os.chdir(cwd) return ase_config_list diff --git a/test/test.py b/test/test.py index 895cbd59f9ea7165b801375fd52b0dd57eaabc1f..228c983bed30dd4b17b4d8b2b84763d6938899df 100755 --- a/test/test.py +++ b/test/test.py @@ -20,27 +20,32 @@ element_mass = { } ase_config_list = soap.tools.ase_load_all('configs') -config = ase_config_list[1] +for config in ase_config_list: + print config.config_file +config = ase_config_list[4] osio << config.atoms << endl +sigma = 0.5 + # INITIALIZE OPTIONS options = soap.Options() options.set('radialbasis.type', 'gaussian') options.set('radialbasis.mode', 'adaptive') #options.set('radialbasis.mode', 'equispaced') options.set('radialbasis.N', 9) -options.set('radialbasis.sigma', 0.5) +options.set('radialbasis.sigma', sigma) options.set('radialbasis.integration_steps', 15) #options.set('radialbasis.N', 9) -options.set('radialcutoff.Rc', 4.) +options.set('radialcutoff.Rc', 6.8) options.set('radialcutoff.Rc_width', 0.5) options.set('radialcutoff.type', 'shifted-cosine') -options.set('radialcutoff.center_weight', -7.) options.set('radialcutoff.center_weight', 1.) +#options.set('radialcutoff.center_weight', -7.) options.set('angularbasis.type', 'spherical-harmonic') options.set('angularbasis.L', 6) -#options.set('angularbasis.L', 6) +#options.set('angularbasis.L', 12) +#options.set('densitygrid.N', 20) options.set('densitygrid.N', 20) options.set('densitygrid.dx', 0.15) @@ -50,75 +55,24 @@ structure = soap.tools.setup_structure_ase(config.config_file, config.atoms) osio << osio.mg << structure.label << endl for atom in structure: - atom.sigma = 0.5 # 0.4*element_vdw_radius[atom.type] + atom.sigma = sigma # 0.5 # 0.4*element_vdw_radius[atom.type] atom.weight = 1. #element_mass[atom.type] #atom.sigma = 0.5*element_vdw_radius[atom.type] #atom.weight = element_mass[atom.type] osio << atom.name << atom.type << atom.weight << atom.sigma << atom.pos << endl + #if atom.id > 60: atom.weight *= -1 # COMPUTE SPECTRUM spectrum = soap.Spectrum(structure, options) spectrum.compute() -#spectrum.writeDensityOnGrid(1, "C", "") +spectrum.writeDensityOnGrid(1, "C", "") +#spectrum.writeDensityOnGrid(2, "S", "") +#spectrum.writeDensityOnGrid(7, "C", "") # line.xyz +#spectrum.writeDensityOnGrid(3, "C", "") # linedot.xyz +#spectrum.writeDensityOnGrid(41, "C", "") # C60_pair.xyz spectrum.save("test_serialization/%s.spectrum.arch" % structure.label) osio.okquit() - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -structure = soap.Structure(config.config_file) - -# BOX TESTS -osio << osio.mg << "Box checks ..." << endl -r1 = np.array([0.2,0.3,0.4]) -r2 = np.array([0.8,1.0,1.2]) -# OPEN BOX -structure.box = np.array([[0,0,0],[0,0,0],[0,0,0]]) -print "Connect", r1, r2, " => ", structure.connect(r1,r2) -# CUBIC BOX -a = np.array([0.9,0,0]) -b = np.array([0,0.7,0]) -c = np.array([0,0,0.5]) -structure.box = np.array([a,b,c]) -print "Connect", r1, r2, " => ", structure.connect(r1,r2) - - -segment = structure.addSegment() -particle = structure.addParticle(segment) -particle.pos = np.array([-1,0,1]) # vec(0,1,-1) -print type(particle.pos), particle.pos -particle.mass = 12. -