From af028a7e08fa3faf4dbe0599d06c9de42af85427 Mon Sep 17 00:00:00 2001 From: Carl Poelking <cp605@cam.ac.uk> Date: Mon, 27 Mar 2017 18:50:12 +0100 Subject: [PATCH] Gobbledygook. --- src/soap/fieldtensor.cpp | 50 ++++++++++++++++++++-------- src/soap/fieldtensor.hpp | 22 +++++++++++-- src/soap/soapy/kernel.py | 70 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 123 insertions(+), 19 deletions(-) diff --git a/src/soap/fieldtensor.cpp b/src/soap/fieldtensor.cpp index 21e228b..fa9fa4a 100644 --- a/src/soap/fieldtensor.cpp +++ b/src/soap/fieldtensor.cpp @@ -1,5 +1,6 @@ #include "soap/fieldtensor.hpp" #include "soap/functions.hpp" +#include "soap/linalg/numpy.hpp" #include <boost/math/special_functions/legendre.hpp> namespace soap { @@ -26,7 +27,7 @@ AtomicSpectrumFT::AtomicSpectrumFT(Particle *center, int K, int L) AtomicSpectrumFT::~AtomicSpectrumFT() { GLOG() << "[~] Destruct " << this->getCenter()->getId() << std::endl; - // Deallocate body-order terms + // Deallocate body-order field terms for (int k=0; k <= _K; ++k) { field_map_t &fm = _body_map[k]; GLOG() << "[~] Deallocating k=" << k<< std::endl; @@ -36,6 +37,27 @@ AtomicSpectrumFT::~AtomicSpectrumFT() { delete it->second; } } + // Deallocate contraction coefficients + for (auto it = _coeff_map.begin(); it != _coeff_map.end(); ++it) { + GLOG() << "[~] Deallocating s1:s2 = " << it->first.first << ":" << it->first.second << std::endl; + delete it->second; + } +} + +boost::python::list AtomicSpectrumFT::getTypes() { + boost::python::list types; + // The highest-body-order term should have the complete set + for (auto it = _body_map[_K].begin(); it != _body_map[_K].end(); ++it) { + std::string type = it->first; + types.append(type); + } + return types; +} + +boost::python::object AtomicSpectrumFT::getCoefficientsNumpy(std::string s1, std::string s2) { + soap::linalg::numpy_converter npc(_numpy_t.c_str()); + channel_t channel(s1, s2); + return npc.ublas_to_numpy< dtype_t >(*_coeff_map[channel]); } void AtomicSpectrumFT::addField(int k, std::string type, field_t &flm) { @@ -143,24 +165,22 @@ void AtomicSpectrumFT::contract() { } int l1l2 = LambdaLambda_off_k+lambda1*Lambda1 + lambda2; GLOG() << " Store " << lambda1 << ":" << lambda2 << ":" << l << " @ " << l1l2 << ":" << l << " = " << phi_l_s1s2_l1l2 << std::endl; - coeffs(l1l2, l) = inv_alpha*phi_l_s1s2_l1l2; - } - } - } - - - } - } + coeffs(l1l2, l) = inv_alpha*phi_l_s1s2_l1l2.real(); + } // l + } // lambda 2 + } // lambda 1 + } // Channel type 2 + } // Channel type 1 GLOG() << std::endl; - - - } + return; } void AtomicSpectrumFT::registerPython() { using namespace boost::python; class_<AtomicSpectrumFT, AtomicSpectrumFT*>("AtomicSpectrumFT", init<Particle*, int, int>()) + .def("getTypes", &AtomicSpectrumFT::getTypes) + .def("getPower", &AtomicSpectrumFT::getCoefficientsNumpy) .def("getCenter", &AtomicSpectrumFT::getCenter, return_value_policy<reference_existing_object>()); } @@ -335,6 +355,8 @@ FTSpectrum::FTSpectrum(Structure &structure, Options &options) : _structure(&structure), _options(&options) { _cutoff = CutoffFunctionOutlet().create(_options->get<std::string>("radialcutoff.type")); _cutoff->configure(*_options); + _L = _options->get<int>("fieldtensor.L"); + _K = _options->get<int>("fieldtensor.K"); return; } @@ -429,8 +451,8 @@ void InteractUpdateSourceTarget( void FTSpectrum::compute() { GLOG() << "Computing FTSpectrum ..." << std::endl; - int K = 3; // TODO - int L = 3; // TODO + int K = _K; + int L = _L; Tlmlm T12(L); // CREATE ATOMIC SPECTRA diff --git a/src/soap/fieldtensor.hpp b/src/soap/fieldtensor.hpp index b78f572..87f9121 100644 --- a/src/soap/fieldtensor.hpp +++ b/src/soap/fieldtensor.hpp @@ -11,7 +11,7 @@ namespace soap { class AtomicSpectrumFT { public: - + typedef double dtype_t; static const std::string _numpy_t; // FIELD MOMENTS @@ -23,14 +23,16 @@ public: // CONTRACTIONS typedef std::pair<std::string, std::string> channel_t; - typedef ub::matrix<cmplx_t> coeff_t; // (k=1:0 k=1:l' k=2:l'l'', l) - typedef ub::zero_matrix<cmplx_t> coeff_zero_t; + typedef ub::matrix<dtype_t> coeff_t; // (k=1:0 k=1:l' k=2:l'l'', l) + typedef ub::zero_matrix<dtype_t> coeff_zero_t; typedef std::map<channel_t, coeff_t*> coeff_map_t; AtomicSpectrumFT(Particle *center, int K, int L); ~AtomicSpectrumFT(); Particle *getCenter() { return _center; } std::string getType() { return _type; } + boost::python::list getTypes(); + boost::python::object getCoefficientsNumpy(std::string s1, std::string s2); int getTypeIdx() { return _s; } static void registerPython(); @@ -52,6 +54,17 @@ private: int _L; // <- Angular momentum cutoff int _s; // <- Type index std::string _type; // <- Type string + std::list<std::string> _nb_types; +}; + +class FTBasis // TODO +{ +public: + FTBasis(Options &options) : _K(-1), _L(-1) {}; + ~FTBasis() {}; +private: + int _K; + int _L; }; class FTSpectrum @@ -74,6 +87,9 @@ private: Options *_options; CutoffFunction *_cutoff; + int _K; + int _L; + atomic_array_t _atomic_array; }; diff --git a/src/soap/soapy/kernel.py b/src/soap/soapy/kernel.py index 6c2b317..62c63dd 100644 --- a/src/soap/soapy/kernel.py +++ b/src/soap/soapy/kernel.py @@ -16,7 +16,7 @@ from momo import osio, endl, flush class DescriptorMap(object): """ - Structured data type that stores + Structured data type that stores descriptors as key-value pairs and emulates basic algebraic properties """ @@ -104,6 +104,71 @@ class TrajectoryLogger(object): self.ofs.close() return +class KernelAdaptorFTD(object): + def __init__(self, options, types_global): + self.types = types_global + self.S = len(types_global) + return + def adapt(self, spectrum, return_pos_matrix=False): + IX = np.zeros((0,0), dtype='float64') # feature matrix + dimX = -1 + IR = np.zeros((0,0), dtype='float64') # position matrix + types = [] + for atomic_i in spectrum: + Xi_unnorm, Xi_norm = self.adaptScalar(atomic_i) + Ri = atomic_i.getCenter().pos + types.append(atomic_i.getCenter().type) + dimX = Xi_norm.shape[0] + if not IX.any(): + IX = np.copy(Xi_norm) # TODO Is this necessary? + IX.resize((1, dimX)) + IR = np.copy(Ri) + IR.resize((1, 3)) + else: + i = IX.shape[0] + IX.resize((i+1, dimX)) + IX[-1,:] = Xi_norm + IR.resize((i+1, 3)) + IR[-1,:] = Ri + if return_pos_matrix: + return IX, IR, types + else: + return IX + def adaptScalar(self, atomic, epsilon=1e-20): + X = self.reduce(atomic, self.types) + X_mag = np.dot(X,X)**0.5 + if X_mag < epsilon: + X_mag = 1. + X_norm = X/X_mag + return X, X_norm + def reduce(self, atomic, types_global, verbose=False): + types_atomic = atomic.getTypes() + S = len(types_global) + SS = S*S + S_atomic = len(types_atomic) + X = None + dim_ab = -1 + dim_total = -1 + # Channel - type a + for i in range(S_atomic): + a = types_atomic[i] + sa = types_global.index(a) + # Channel - type b + for j in range(S_atomic): + b = types_atomic[j] + sb = types_global.index(b) + x = atomic.getPower(a,b) + # Initialize aggregated array + if i == 0 and j == 0: + dim_ab = x.shape[0]*x.shape[1] + dim_total = SS*dim_ab + X = np.zeros((dim_total,), dtype='float64') + # Locate in super-array X + i0 = (sa*S+sb)*dim_ab + i1 = i0 + dim_ab + X[i0:i1] = x.flatten() + return X + class Xnklab(object): def __init__(self, atomic, types_global): self.types_global = types_global @@ -683,7 +748,8 @@ KernelAdaptorFactory = { 'specific-unique-dmap': KernelAdaptorSpecificUniqueDMap, 'global-generic': KernelAdaptorGlobalGeneric, 'global-specific': KernelAdaptorGlobalSpecific, -'global-specific-energy': KernelAdaptorGlobalSpecificEnergy +'global-specific-energy': KernelAdaptorGlobalSpecificEnergy, +'ftd-specific': KernelAdaptorFTD } KernelFunctionFactory = { -- GitLab