def compute_composition_vector(self, composition_space): """ Returns the composition vector of the organism, as a numpy array. Args: composition_space: the CompositionSpace of the search. """ if composition_space.objective_function == 'epa': return None elif composition_space.objective_function == 'pd': # make CompoundPhaseDiagram and PDAnalyzer objects pdentries = [] for endpoint in composition_space.endpoints: pdentries.append(PDEntry(endpoint, -10)) compound_pd = CompoundPhaseDiagram(pdentries, composition_space.endpoints) # transform the organism's composition transformed_entry = compound_pd.transform_entries( [PDEntry(self.composition, 10)], composition_space.endpoints) # get the transformed species and amounts if len(transformed_entry[0]) == 0: return None transformed_list = str(transformed_entry[0][0]).split() del transformed_list[0] popped = '' while popped != 'with': popped = transformed_list.pop() # separate the dummy species symbols from the amounts symbols = [] amounts = [] for entry in transformed_list: split_entry = entry.split('0+') symbols.append(split_entry[0]) amounts.append(float(split_entry[1])) # make a dictionary mapping dummy species to amounts dummy_species_amounts = {} for i in range(len(symbols)): dummy_species_amounts[DummySpecie(symbol=symbols[i])] = \ amounts[i] # make Composition object with dummy species, get decomposition dummy_comp = Composition(dummy_species_amounts) decomp = compound_pd.get_decomposition(dummy_comp) # get amounts of the decomposition in terms of the (untransformed) # composition space endpoints formatted_decomp = {} for key in decomp: key_dict = key.as_dict() comp = Composition(key_dict['entry']['composition']) formatted_decomp[comp] = decomp[key] # make the composition vector composition_vector = [] # because the random organism creator shuffles the endpoints composition_space.endpoints.sort() for endpoint in composition_space.endpoints: if endpoint in formatted_decomp: composition_vector.append(formatted_decomp[endpoint]) else: composition_vector.append(0.0) return np.array(composition_vector)
def scale_volume_pd(self, organism, composition_space, pool): """ Returns a boolean indicating whether volume scaling did not fail. Args: organism: the Organism whose volume to scale composition_space: the CompositionSpace of the search pool: the Pool Description: 1. Computes the decomposition of the organism - that is, which structures on the convex hull (and their relative amounts) that the organism would decompose to, based on its composition. 2. Computes the weighted average volume per atom of the structures in the decomposition. 3. Scales the volume per atom of the organism to the computed value. """ # make CompoundPhaseDiagram object pdentries = [] for org in pool.promotion_set: pdentries.append(PDEntry(org.composition, org.total_energy)) compound_pd = CompoundPhaseDiagram(pdentries, composition_space.endpoints) # transform the organism's composition transformed_entry = compound_pd.transform_entries( [PDEntry(organism.composition, 10)], composition_space.endpoints) # get the transformed species and amounts transformed_list = str(transformed_entry[0][0]).split() del transformed_list[0] popped = '' while popped != 'with': popped = transformed_list.pop() # separate the dummy species symbols from the amounts symbols = [] amounts = [] for entry in transformed_list: split_entry = entry.split('0+') symbols.append(split_entry[0]) amounts.append(float(split_entry[1])) # make a dictionary mapping dummy species to amounts dummy_species_amounts = {} for i in range(len(symbols)): dummy_species_amounts[DummySpecie(symbol=symbols[i])] = amounts[i] # make Composition object with dummy species, get decomposition dummy_comp = Composition(dummy_species_amounts) decomp = compound_pd.get_decomposition(dummy_comp) # get original compositions and amounts from the decomposition fractions = [] comps = [] for item in decomp: fractions.append(decomp[item]) first_split = str(item).split(',') second_split = first_split[0].split() while second_split[0] != 'composition': del second_split[0] del second_split[0] # build the composition string comp_string = '' for symbol in second_split: comp_string += str(symbol) comps.append(Composition(comp_string)) # get weighted average volume per atom of the organisms in the # decomposition vpa_mean = 0 for i in range(len(comps)): for org in pool.promotion_set: if (comps[i].reduced_composition).almost_equals( org.composition.reduced_composition): vpa_mean += (org.cell.volume / len(org.cell.sites)) * fractions[i] # compute the new volume and scale to it num_atoms = len(organism.cell.sites) new_vol = vpa_mean * num_atoms # this is to suppress the warnings produced if the # scale_lattice method fails with warnings.catch_warnings(): warnings.simplefilter('ignore') organism.cell.scale_lattice(new_vol) if str(organism.cell.lattice.a) == 'nan' or \ organism.cell.lattice.a > 100: print('Volume scaling failed on organism {} during ' 'development '.format(organism.id)) return False return True