def computeEnergy(self, structure, return_prj_mat=False): logging.info("Start energy ...") energy = 0.0 spectrum = soap.Spectrum(structure, self.options, self.basis) spectrum.compute() spectrum.computePower() spectrum.computePowerGradients() # TODO The kernel policy should take care of this: if self.use_global_spectrum: spectrum.computeGlobal() IX_acqu = self.adaptor.adapt(spectrum) n_acqu = IX_acqu.shape[0] dim_acqu = IX_acqu.shape[1] logging.info("Compute energy from %d atomic environments ..." % n_acqu) projection_matrix = [] for n in range(n_acqu): X = IX_acqu[n] #print "X_MAG", np.dot(X,X) ic = self.kernelfct.compute(self.IX, X) energy += self.alpha.dot(ic) #print "Projection", ic projection_matrix.append(ic) if return_prj_mat: return energy, projection_matrix else: return energy
def acquire(self, structure, alpha): logging.info("Acquire ...") spectrum = soap.Spectrum(structure, self.options, self.basis) spectrum.compute() spectrum.computePower() spectrum.computePowerGradients() # New X's logging.info("Adapt spectrum ...") IX_acqu = self.adaptor.adapt(spectrum, self.pid_list_acquire) n_acqu = IX_acqu.shape[0] dim_acqu = IX_acqu.shape[1] # New alpha's alpha_acqu = np.zeros((n_acqu)) alpha_acqu.fill(alpha) if not self.dimX: # First time ... self.dimX = dim_acqu self.IX = IX_acqu self.alpha = alpha_acqu else: # Check and extend ... assert self.dimX == dim_acqu # Acquired descr. should match linear dim. of previous descr.'s I = self.IX.shape[0] self.IX.resize((I + n_acqu, self.dimX)) self.IX[I:I + n_acqu, :] = IX_acqu self.alpha.resize((I + n_acqu)) self.alpha[I:I + n_acqu] = alpha_acqu #print self.alpha #print self.IX logging.info("Acquired %d environments." % n_acqu) return
def compute_soap(struct, options): # OPTIONS options_soap = soap.Options() for key, val in options.items(): if isinstance(val, list): continue options_soap.set(key, val) # Exclusions excl_targ_list = options['exclude_targets'] excl_cent_list = options['exclude_centers'] options_soap.excludeCenters(excl_cent_list) options_soap.excludeTargets(excl_targ_list) # Compute spectrum spectrum = soap.Spectrum(struct, options_soap) spectrum.compute() spectrum.computePower() if options['spectrum.gradients']: spectrum.computePowerGradients() if options['spectrum.global']: spectrum.computeGlobal() # Adapt spectrum adaptor = soap.soapy.kernel.KernelAdaptorFactory[options['kernel.adaptor']]( options_soap, types_global=options['type_list']) IX, IR, types = adaptor.adapt(spectrum, return_pos_matrix=True) # Calculate average X_avg = IX.sum(axis=0) X_avg = X_avg / X_avg.dot(X_avg)**0.5 return IX, X_avg, IR, types
def compute_spectrum(config, options_dict, exclude_centers, exclude_targets): # ANNOUNCE global MP_LOCK MP_LOCK.acquire() osio << osio.item \ << "Soap for: " << config.config_file \ << "PID=%d" % mp.current_process().pid << endl MP_LOCK.release() # SET OPTIONS options = soap.Options() for item in options_dict.iteritems(): options.set(*item) options.excludeCenters(exclude_centers) options.excludeTargets(exclude_targets) # PROCESS STRUCTURE structure = soap.tools.setup_structure_ase(config.config_file, config.atoms) for particle in structure: particle.sigma = 0.5 * element_vdw_radius[particle.type] particle.weight = element_valence_order[particle.type] # COMPUTE SPECTRUM spectrum = soap.Spectrum(structure, options) spectrum.compute() spectrum.computePower() spectrum.save('%s.spectrum' % config.config_file) return config.config_file
def load(self, hdf5_handle): g = hdf5_handle # SETTINGS self.settings = g.attrs self.label = g["class"].attrs["label"] if self.verbose: self.log << self.log.mb << "Loading power spectrum '%s'" % self.label << self.log.endl # HELPER FUNCTIONS def load_dict_array_data(h): D = [] for idx in range(len(h)): hh = h["%d" % idx] d = {t: hh[t].value for t in hh} D.append(d) return D def load_descriptor_map_matrix(h): D = soap.soapy.kernel.DescriptorMapMatrix() for idx in range(len(h)): d = soap.soapy.kernel.DescriptorMap() hh = h['%d' % idx] for t in hh: d[t] = hh[t].value D.append(d) return D # LOAD FIELDS if self.settings["store_cxx_serial"]: if self.verbose: self.log << "[h5] Loading cxx serial and spectrum" << self.log.endl cxx_serial = g["cxx_serial"].value.tostring() self.spectrum = soap.Spectrum() self.spectrum.loads(cxx_serial) self.has_spectrum = True # DENSITY EXPANSION COEFFICIENTS if self.settings["store_cmap"]: if self.verbose: self.log << "[h5] Loading coefficient map" << self.log.endl self.cmap = load_dict_array_data(g["cmap"]) if self.settings["store_gcmap"]: if self.verbose: self.log << "[h5] Loading global coefficient map" << self.log.endl self.cmap = load_dict_array_data(g["gcmap"]) # POWER SPECTRUM COEFFICIENTS if self.settings["store_sdmap"]: if self.verbose: self.log << "[h5] Loading descriptor map" << self.log.endl self.sdmap = load_descriptor_map_matrix(g["sdmap"]) if self.settings["store_gsdmap"]: if self.verbose: self.log << "[h5] Loading global descriptor map" << self.log.endl self.gsdmap = load_descriptor_map_matrix(g["gsdmap"]) if self.settings["store_sd"]: if self.verbose: self.log << "[h5] Loading descriptor matrix" << self.log.endl self.sd = g["sd"].value return self
def compute(self, config, options, config_target=None, converter=None): if self.has_cnlm: pass else: # CONVERT ASE ATOMS TO SOAPXX TOPOLOGY if converter is None: converter = PowerSpectrum.converter self.structure = converter.convert(self.config) if config_target is not None: self.structure_target = converter.convert(self.config_target) self.has_structure = True # COMPUTE SPECTRUM options_cxx = convert_json_to_cxx(options) self.spectrum = soap.Spectrum(self.structure, options_cxx) if self.verbose: self.log << "[cc] Computing density expansion" << self.log.endl if self.structure_target is not None: self.spectrum.compute(self.structure, self.structure_target) else: self.spectrum.compute() self.has_spectrum = True # EXTRACT CNLM ATOMIC if PowerSpectrum.settings["store_cmap"]: if self.verbose: self.log << "[py] Storing coefficient map (-> cmap)" << self.log.endl self.cmap = [] for atomic in self.spectrum: cmap = {} types = atomic.getTypes() for t in types: cnlm = atomic.getLinear(t).array cmap[t] = cnlm self.cmap.append(cmap) # EXTRACT CNLM GLOBAL if PowerSpectrum.settings["store_gcmap"]: if self.verbose: self.log << "[cc] Computing global coefficient map" << self.log.endl self.gcmap = [] self.spectrum_global = self.spectrum.computeGlobal() if self.verbose: self.log << "[py] Storing global coefficient map (-> gcmap)" << self.log.endl types = atomic.getTypes() for t in types: self.gcmap.append({t: atomic.getLinear(t).array}) self.has_spectrum_global = True self.has_cnlm = True # COMPUTE POWER SPECTRUM? if PowerSpectrum.settings["cxx_compute_power"]: self.computePower() return
def computeForces(self, structure, verbose=False): logging.info("Start forces ...") if verbose: for p in structure: print p.pos forces = [np.zeros((3)) for i in range(structure.n_particles)] logging.info("Compute forces on %d particles ..." % structure.n_particles) # Compute X's, dX's spectrum = soap.Spectrum(structure, self.options, self.basis) spectrum.compute() spectrum.computePower() spectrum.computePowerGradients() if self.use_global_spectrum: atomic_global = spectrum.computeGlobal() spectrum_iter = [atomic_global] else: spectrum_iter = spectrum # Extract & compute force for atomic in spectrum_iter: pid = atomic.getCenter().id if not self.use_global_spectrum else -1 #if not pid in self.pid_list_force: # logging.debug("Skip forces derived from environment with pid = %d" % pid) # continue #if pid != 1: continue nb_pids = atomic.getNeighbourPids() logging.info(" Center %d" % (pid)) # neighbour-pid-independent kernel "prevector" (outer derivative) X_unnorm, X_norm = self.adaptor.adaptScalar(atomic) dIC = self.kernelfct.computeDerivativeOuter(self.IX, X_norm) alpha_dIC = self.alpha.dot(dIC) for nb_pid in nb_pids: # Force on neighbour logging.info(" -> Nb %d" % (nb_pid)) dX_dx, dX_dy, dX_dz = self.adaptor.adaptGradients( atomic, nb_pid, X_unnorm) force_x = -alpha_dIC.dot(dX_dx) force_y = -alpha_dIC.dot(dX_dy) force_z = -alpha_dIC.dot(dX_dz) forces[nb_pid - 1][0] += force_x forces[nb_pid - 1][1] += force_y forces[nb_pid - 1][2] += force_z #print forces #raw_input('...') return forces
def compute(self, config, options): if self.has_cnlm: pass else: # CONVERT ASE ATOMS TO SOAPXX TOPOLOGY self.config, self.structure, top, frag_bond_mat, atom_bond_mat, frag_labels, atom_labels = \ soap.tools.structure_from_ase( config, do_partition=False, add_fragment_com=False, log=None) self.has_structure = True # COMPUTE SPECTRUM options_cxx = self.getCxxOptions(options) self.spectrum = soap.Spectrum(self.structure, options_cxx) if self.verbose: self.log << "[cc] Computing density expansion" << self.log.endl self.spectrum.compute() self.has_spectrum = True # EXTRACT CNLM ATOMIC if PowerSpectrum.settings["store_cmap"]: if self.verbose: self.log << "[py] Storing coefficient map (-> cmap)" << self.log.endl self.cmap = [] for atomic in self.spectrum: cmap = {} types = atomic.getTypes() for t in types: cnlm = atomic.getLinear(t).array cmap[t] = cnlm self.cmap.append(cmap) # EXTRACT CNLM GLOBAL if PowerSpectrum.settings["store_gcmap"]: if self.verbose: self.log << "[cc] Computing global coefficient map" << self.log.endl self.gcmap = [] self.spectrum_global = self.spectrum.computeGlobal() if self.verbose: self.log << "[py] Storing global coefficient map (-> gcmap)" << self.log.endl types = atomic.getTypes() for t in types: self.gcmap.append({t: atomic.getLinear(t).array}) self.has_spectrum_global = True self.has_cnlm = True # COMPUTE POWER SPECTRUM? if PowerSpectrum.settings["cxx_compute_power"]: self.computePower() return
def computeEnergy(self, structure): logging.info("Start energy ...") energy = 0.0 spectrum = soap.Spectrum(structure, self.options, self.basis) spectrum.compute() spectrum.computePower() spectrum.computePowerGradients() IX_acqu = self.adaptor.adapt(spectrum, self.pid_list_acquire) n_acqu = IX_acqu.shape[0] dim_acqu = IX_acqu.shape[1] logging.info("Compute energy from %d atomic environments ..." % n_acqu) for n in range(n_acqu): X = IX_acqu[n] ic = self.kernelfct.compute(self.IX, X) energy += self.alpha.dot(ic) print "Projection", ic return energy
def compute_soap(struct, options, fragment_based=False): # OPTIONS options_soap = soap.Options() for key, val in options.items(): if type(val) == list: continue options_soap.set(key, val) # Exclusions excl_targ_list = options['exclude_targets'] excl_cent_list = options['exclude_centers'] excl_targ_list.append('COM') if not fragment_based: excl_cent_list.append('COM') options_soap.excludeCenters(excl_cent_list) options_soap.excludeTargets(excl_targ_list) # SPECTRUM spectrum = soap.Spectrum(struct, options_soap) # Compute density expansion if fragment_based: # Divide onto segments and their COM representatives seg_by_name = {} comseg_by_name = {} for seg in struct.segments: if seg.name.split('.')[-1] == 'COM': comseg_by_name[seg.name] = seg else: seg_by_name[seg.name] = seg # Compute segment descriptors for name, seg in seg_by_name.items(): comseg = comseg_by_name[name + '.COM'] spectrum.compute(comseg, seg) else: spectrum.compute() # Compute power spectrum, spectrum.computePower() if options['spectrum.gradients']: spectrum.computePowerGradients() if options['spectrum.global']: spectrum.computeGlobal() # Adapt spectrum adaptor = soap.soapy.kernel.KernelAdaptorFactory[ options['kernel.adaptor']](options_soap, types_global=options['type_list']) IX, IR, types = adaptor.adapt(spectrum, return_pos_matrix=True) return IX, IR, types
def acquire(self, reset=True): if reset: self.reset() # Compute spectrum self.spectrum = soap.Spectrum(self.structure, self.options, self.basis) self.spectrum.compute() self.spectrum.computePower() self.spectrum.computePowerGradients() self.spectrum.computeGlobal() # PID-resolved storage for X, dX for atomic in self.adaptor.getListAtomic(self.spectrum): pid = atomic.getCenterId() X_unnorm, X_norm = self.adaptor.adaptScalar( atomic) # TODO Done again below in ::adapt => simplify self.pid_X_unnorm[pid] = X_unnorm self.pid_X_norm[pid] = X_norm self.pid_nbpid_dX[pid] = {} # NB-PID-resolved derivatives nb_pids = atomic.getNeighbourPids() for nb_pid in nb_pids: dX_dx, dX_dy, dX_dz = self.adaptor.adaptGradients( atomic, nb_pid, X_unnorm) self.pid_nbpid_dX[pid][nb_pid] = (dX_dx, dX_dy, dX_dz) # New X's IX_acqu = self.adaptor.adapt(self.spectrum) n_acqu = IX_acqu.shape[0] dim_acqu = IX_acqu.shape[1] if not self.dimX: # First time ... self.dimX = dim_acqu self.IX = IX_acqu else: # Check and extend ... assert self.dimX == dim_acqu # Acquired descr. should match linear dim. of previous descr.'s I = self.IX.shape[0] self.IX.resize((I + n_acqu, self.dimX)) self.IX[I:I + n_acqu, :] = IX_acqu return
#! /usr/bin/env python import soap import soap.tools import os import numpy as np from momo import osio, endl, flush archfile = 'config_000057.xyz.spectrum.arch' # SPECTRUM spectrum = soap.Spectrum(archfile) structure = spectrum.structure basis = spectrum.basis options = spectrum.options osio << osio.mb << options << endl center_id = 1 center_type = "C" density_type = "O" # TARGET EXTRACTION atomic = spectrum.getAtomic(center_id, center_type) center = atomic.getCenter() atomic_xnkl = atomic.getPower(density_type, density_type).array # INVERT XKNL => QNLM atomic_inv_qnlm = soap.tools.invert_xnkl_aa(atomic_xnkl, basis, l_smaller=0, l_larger=1) # CREATE INVERSION EXPANSION basisexp = soap.BasisExpansion(basis)
target = target_map[id1][id2] # READ COORDINATES ase_config_list = soap.tools.ase_load_all('dim') assert len(ase_config_list) == 1 config = ase_config_list[0] # PROCESS STRUCTURE structure = soap.tools.setup_structure_ase(config.config_file, config.atoms) for particle in structure: particle.sigma = 0.5 * element_vdw_radius[particle.type] particle.weight = element_valence_order[particle.type] if particle.id > 28: #print particle.id, particle.name particle.weight *= -1. # COMPUTE SPECTRUM spectrum = soap.Spectrum(structure, options) basis = spectrum.basis spectrum.compute() spectrum.computePower() # EXTRACT XNKL x_pair = soap.PowerExpansion(spectrum.basis) xnkl_pair = x_pair.array norm = 0. for atomic in spectrum: xnkl_pair = xnkl_pair + atomic.getPower("", "").array norm += 1. xnkl_pair = xnkl_pair / norm xnkl_pair = xnkl_pair.real xnkl_pair = xnkl_pair.reshape(basis.N * basis.N * (basis.L + 1)) # SAVE TO HARDDRIVE np.save('xnkl.array.npy', xnkl_pair)
def setupVertexFeatures(self, atoms, options): n_atoms = len(atoms) positions = [atom.position for atom in atoms] descriptor_type = options['graph']['descriptor'] options_descriptor = options['descriptor'][descriptor_type] if descriptor_type == 'atom_type': feature_map = {} feature_list = options_descriptor['type_map'] dim = len(feature_list) P = np.zeros((n_atoms, dim)) for idx, atom in enumerate(atoms): p = np.zeros((dim)) atom_type = atom.number for i in range(dim): if feature_list[i] == atom_type: p[i] = 1 else: p[i] = 0 P[idx, :] = p elif descriptor_type == 'soap': # Structure structure = soap.tools.setup_structure_ase(self.label, atoms) # Customize density density_type = options["atomic_density"]["density_type"] use_covrad = options["atomic_density"]["use_covrad"] atom_rad_scale = float(options["atomic_density"]["atomic_radius"]) # ... Particle radii if use_covrad: radius_map = soap.soapy.elements.periodic_table.getPropertyDict( "covrad", convert=lambda x: x * atom_rad_scale) else: radius_map = {} for elem in soap.soapy.elements.PeriodicTable.element_names: radius_map[elem] = atom_rad_scale # ... Particle 'charge' if density_type == "elneg_density": charge_map = soap.soapy.elements.periodic_table.getPropertyDict( "elneg") elif density_type == "z_density": charge_map = soap.soapy.elements.periodic_table.getPropertyDict( "z") elif density_type == "number_density": charge_map = {} for elem in soap.soapy.elements.PeriodicTable.element_names: charge_map[elem] = 1. elif density_type == "number_density_generic": charge_map = {} for elem in soap.soapy.elements.PeriodicTable.element_names: charge_map[elem] = 1. elif density_type == "valence_charge_density": charge_map = soap.soapy.elements.periodic_table.getPropertyDict( "valence") else: raise NotImplementedError("Density type '%s'" % density_type) # ... Apply soap.tools.setup_structure_density(structure, radius_map=radius_map, charge_map=charge_map) # Options options_soap = soap.Options() for item in options_descriptor.items(): key = item[0] val = item[1] if type(val) == list: continue # TODO Exclusions loaded separately, fix this options_soap.set(key, val) options_soap.excludeCenters(options_descriptor['exclude_centers']) options_soap.excludeTargets(options_descriptor['exclude_targets']) # Spectrum spectrum = soap.Spectrum(structure, options_soap) spectrum.compute() spectrum.computePower() if options_descriptor['spectrum.gradients']: spectrum.computePowerGradients() spectrum.computeGlobal() # Adapt spectrum adaptor = kern.KernelAdaptorFactory[options_soap.get( 'kernel.adaptor')]( options_soap, types_global=options_descriptor['type_list']) ix = adaptor.adapt(spectrum) dim = ix.shape[1] P = ix if options_soap.get('kernel.adaptor') in [ 'global-generic', 'global-specific' ]: pass else: assert P.shape[0] == n_atoms elif descriptor_type == 'soap-quippy': atoms_quippy = datasets.gdb.convert_ase2quippy_atomslist([atoms ])[0] # Read options options_xml_file = options_descriptor["options_xml"] opt_interface = momo.OptionsInterface() xml_options = opt_interface.ParseOptionsFile( options_xml_file, 'options') # Finalize options xml_options.kernel.alchemy = xml_options.kernel.alchemy.As(str) xml_options.kernel.alchemy_rules = xml_options.kernel.alchemy xml_options.soap.nocenter = xml_options.soap.nocenter.As(str) xml_options.soap.noatom = [] # TODO if xml_options.soap.nocenter and xml_options.soap.nocenter != 'None': xml_options.soap.nocenter = map( int, xml_options.soap.nocenter.split()) else: xml_options.soap.nocenter = [] datasets.soap.finalize_options([], xml_options) # Process z_types = options_descriptor["z_type_list"] struct = libmatch.structures.structure(xml_options.kernel.alchemy) soap_raw = struct.parse(atoms_quippy, xml_options.soap.R.As(float), xml_options.soap.N.As(int), xml_options.soap.L.As(int), xml_options.soap.sigma.As(float), xml_options.soap.w0.As(float), xml_options.soap.nocenter, xml_options.soap.noatom, types=z_types, kit=xml_options.kernel.kit) # Assign raw soaps to atoms (currently stored by z-key) z_idx_counter = {} for z in soap_raw: #print z, soap_raw[z].shape z_idx_counter[z] = 0 ix = [] for i, z in enumerate(atoms.get_atomic_numbers()): z_idx = z_idx_counter[z] ix.append(soap_raw[z][z_idx]) z_idx_counter[z] += 1 #print z, z_idx P = np.array(ix) dim = P.shape[1] assert P.shape[0] == n_atoms #print P.dot(P.T) elif descriptor_type == 'npy_load': folder = options_descriptor["folder"] npy_file = '%s/%s.x.npy' % (folder, self.label) #print npy_file P = np.load(npy_file) dim = P.shape[1] assert P.shape[0] == n_atoms elif descriptor_type == 'none': dim = 1 P = np.zeros((n_atoms, dim)) for idx, atom in enumerate(atoms): P[idx, 0] = 1. else: raise NotImplementedError(descriptor_type) return P, positions