def _read_g09(name): """ A method for reading in the output of g09 single point calculations to get the atomic positions with forces. Further, energy is also returned. **Parameters** name: *str* The name of the g09 simulation in questions. **Returns** new_energy: *float* The energy of the system in Hartree (Ha). new_atoms: *list,* :class:`structures.Atom` A list of atoms with the forces attached in units of Hartree per Angstrom (Ha/Ang). """ result = g09.parse_atoms(name, check_convergence=False, parse_all=False) if not result: raise Exception('parse_atoms failed') new_energy, new_atoms = result for a in new_atoms: a.fx = units.convert('Ha/Bohr', 'Ha/Ang', a.fx) a.fy = units.convert('Ha/Bohr', 'Ha/Ang', a.fy) a.fz = units.convert('Ha/Bohr', 'Ha/Ang', a.fz) return new_energy, new_atoms
def getData(self, unit=None): """Return all of the data in the channel, converting it if a type is specified.""" if unit is None: # No conversion needed return self.data if self.valueType in (list, tuple): return [[units.convert(d, self.unit, unit) for d in p] for p in self.data] # If the data type isn't a list, it should be a scalar return [units.convert(p, self.unit, unit) for p in self.data]
def g09_results(NEB, step_to_use, i, state): """ A method for reading in the output of Gaussian09 single point calculations for NEB calculations. This will both (a) assign forces to the atoms stored in state and (b) return the energy and atoms. **Parameters** NEB: :class:`NEB` An NEB container holding the main NEB simulation step_to_use: *int* Which iteration in the NEB sequence the output to be read in is on. i: *int* The index corresponding to which image on the frame is to be simulated. state: *list,* :class:`structures.Atom` A list of atoms describing the image on the frame associated with index *i*. **Returns** new_energy: *float* The energy of the system in Hartree (Ha). new_atoms: *list,* :class:`structures.Atom` A list of atoms with the forces attached in units of Hartree per Angstrom (Ha/Ang). """ result = g09.parse_atoms('%s-%d-%d' % (NEB.name, step_to_use, i), check_convergence=False, parse_all=False) if not result: raise Exception('parse_atoms failed') new_energy, new_atoms = result # Check if coordinates are aligned properly between state and new_atoms def check_atom_coords(atoms1, atoms2, precision=1e-6): for a1, a2 in zip(atoms1, atoms2): if (abs(a1.x - a2.x) > precision or abs(a1.y - a2.y) > precision or abs(a1.z - a2.z) > precision): print i, 'atoms not in same frame:', a1.x, a1.y, a1.z, print 'vs', a2.x, a2.y, a2.z print abs(a1.x - a2.x), abs(a1.y - a2.y), abs(a1.z - a2.z) exit() if i != 0 and i != len(NEB.states) - 1: check_atom_coords(state, new_atoms) for a, b in zip(state, new_atoms): b.fx = units.convert('Ha/Bohr', 'Ha/Ang', b.fx) b.fy = units.convert('Ha/Bohr', 'Ha/Ang', b.fy) b.fz = units.convert('Ha/Bohr', 'Ha/Ang', b.fz) a.fx = b.fx a.fy = b.fy a.fz = b.fz return new_energy, new_atoms
def getCSV(self, pref=None, exclude=[], excludeGrains=[]): """Returns a string that contains a CSV of the simulated data. Preferences can be passed in to set units that the values will be converted to. All log channels are included unless their names are in the include argument. """ out = '' outUnits = {} for chan in self.channels: if chan in exclude: continue # Get unit from preferences if pref is not None: outUnits[chan] = pref.getUnit(self.channels[chan].unit) else: outUnits[chan] = self.channels[chan].unit # Add title for column if self.channels[chan].valueType in (float, int): out += self.channels[chan].name if outUnits[chan] != '': out += '(' + outUnits[chan] + ')' out += ',' elif self.channels[chan].valueType in (list, tuple): for grain in range(1, len(self.channels[chan].getLast()) + 1): if grain - 1 not in excludeGrains: out += self.channels[chan].name + '(' out += 'G' + str(grain) if outUnits[chan] != '': out += ';' + outUnits[chan] out += '),' out = out[:-1] # Remove the last comma out += '\n' places = 5 for ind, time in enumerate(self.channels['time'].getData()): out += str(round(time, places)) + ',' for chan in self.channels: if chan in exclude: continue if chan != 'time': if self.channels[chan].valueType in (float, int): orig = self.channels[chan].getPoint(ind) conv = units.convert(orig, self.channels[chan].unit, outUnits[chan]) rounded = round(conv, places) out += str(rounded) + ',' elif self.channels[chan].valueType in (list, tuple): for gid, grainVal in enumerate(self.channels[chan].getPoint(ind)): if gid not in excludeGrains: conv = round(units.convert(grainVal, self.channels[chan].unit, outUnits[chan]), places) out += str(conv) + ',' out = out[:-1] # Remove the last comma out += '\n' return out
def get_basic(self, name=None, unit=None): """ Gets the value under the given name converting it into the given unit, if possible. For example: -- self.get_basic('x', 'km') will return the value of x in kilometers. -- self.get_basic('longitude', 'deg') will return the longitude angle in degrees. """ if name in self._cart_names: # Cartesian coordinate i = self._cart_names.index(name) return units.convert(self._cart_unit[i], unit, self._cart[i]) elif name in self._cart_names_pm: # Cartesian velocity i = self._cart_names_pm.index(name) return units.convert(self._cart_unit_pm[i], unit, self._cart_pm[i]) elif name in self._longitude_names: return units.convert(self._sph_unit[0], unit, self._sph[0]) elif name in self._longitude_names_pm: return units.convert(self._sph_unit_pm[0], unit, self._sph_pm[0]) elif name in self._latitude_names: return units.convert(self._sph_unit[1], unit, self._sph[1]) elif name in self._latitude_names_pm: return units.convert(self._sph_unit_pm[1], unit, self._sph_pm[1]) elif name in self._dist_names: return units.convert(self._sph_unit[2], unit, self._sph[2]) elif name in self._dist_names_pm: return units.convert(self._sph_unit_pm[2], unit, self._sph_pm[2]) else: raise Exception("Name not recognized: %s" % name)
def method_CLANCELOT(opt_method="LBFGS"): from files import read_xyz, write_xyz import neb from units import convert, convert_energy FPTR = "./../xyz/CNH_HCN.xyz" frames = read_xyz(FPTR) route = '! HF-3c' if RIGID_ROTATION: is_on = "ON" else: is_on = "OFF" print("\nRUNNING CLANCELOT SIMULATION WITH RIGID_ROTATION %s...\n" % is_on) run_name = 'CNH_HCN_c_' + opt_method new_opt_params = { 'step_size': ALPHA, 'step_size_adjustment': 0.5, 'max_step': MAX_STEP, 'linesearch': 'backtrack', 'accelerate': True, 'reset_step_size': 5, 'g_rms': convert("eV/Ang", "Ha/Ang", 0.03), 'g_max': convert("eV/Ang", "Ha/Ang", FMAX) } opt = neb.NEB(run_name, frames, route, k=convert_energy("eV", "Ha", 0.1), opt=opt_method, new_opt_params=new_opt_params) output = opt.optimize() frames = output[-1] write_xyz(frames, "CNH_HCN_opt_%s" % opt_method) print("\nDONE WITH CLANCELOT SIMULATION...\n")
def getValue(self,symtab): # Ok, we have to convert everything to be in the same units. lhs = self.lhs.eval(symtab) rhs = self.rhs.eval(symtab) if rhs.getUnit(symtab)==None: # If the rhs has no unit, we pretend it's in the # same unit. People are lazy, and the alternative # is to raise an error, which just infuriates users pass else: # Ok, the rhs has a unit, we need to convert it to # be the same as the left rhs=units.convert(rhs,rhs.getUnit(symtab),lhs.getUnit(symtab)) a=Value(eval("(lhs.getValue(symtab) "+self.op+" rhs.getValue(symtab))"),lhs.getUnit(symtab)) return a
def parse_nutrition(data): logger.debug('parsing {}'.format(data['name'])) nutrients = {} required = list(NUTRI_NAMES.keys()) for n in data['nutrients']: id = str(n['nutrient_id']) name = NUTRI_NAMES.get(id) if name is None: logger.debug('skipping {} ({})'.format(id, n['name'])) continue required.remove(id) # standardize units for nutrients # all nutrient measurements are per 100g # we convert to 1g qty = (float(n['value']) / 100, n['unit']) std_unit = STANDARD_UNITS[name] qty = units.convert(qty, std_unit) # merge if name in nutrients: nutrients[name]['value'] += qty[0] else: nutrients[name] = {'value': qty[0], 'unit': std_unit} # assume non-specified nutrients are 0 for id in required: name = NUTRI_NAMES[id] if name not in nutrients: std_unit = STANDARD_UNITS[name] nutrients[name] = {'value': 0, 'unit': std_unit} # measurement conversions seem to be identical # for all nutrients conversions = [] for m in data['nutrients'][0]['measures']: c = [(m['eqv'], m['eunit']), (m['qty'], m['label'])] conversions.append(c) return { 'id': data['ndbno'], 'name': data['name'], 'unit': data['ru'], # reporting unit 'nutrients': nutrients, 'conversions': conversions }
def getValue(self, symtab): # Ok, we have to convert everything to be in the same units. lhs = self.lhs.eval(symtab) rhs = self.rhs.eval(symtab) if rhs.getUnit(symtab) == None: # If the rhs has no unit, we pretend it's in the # same unit. People are lazy, and the alternative # is to raise an error, which just infuriates users pass else: # Ok, the rhs has a unit, we need to convert it to # be the same as the left rhs = units.convert(rhs, rhs.getUnit(symtab), lhs.getUnit(symtab)) a = Value( eval("(lhs.getValue(symtab) " + self.op + " rhs.getValue(symtab))"), lhs.getUnit(symtab)) return a
def get_tnc_packet(self, record): """Form the TNC2 packet used by CWOP.""" # Preamble to the TNC packet: _prefix = "%s>APRS,TCPIP*:" % (self.station,) # Time: _time_tt = time.gmtime(record['dateTime']) _time_str = time.strftime("@%d%H%Mz", _time_tt) # Position: _lat_str = latlon_string(self.latitude, ('N', 'S'), 'lat') _lon_str = latlon_string(self.longitude, ('E', 'W'), 'lon') _latlon_str = '%s%s%s/%s%s%s' % (_lat_str + _lon_str) # Wind and temperature _wt_list = [] for _obs_type in ['windDir', 'windSpeed', 'windGust', 'outTemp']: _v = record.get(_obs_type) _wt_list.append("%03d" % _v if _v is not None else '...') _wt_str = "_%s/%sg%st%s" % tuple(_wt_list) # Rain _rain_list = [] for _obs_type in ['hourRain', 'rain24', 'dayRain']: _v = record.get(_obs_type) _rain_list.append("%03d" % (_v * 100.0) if _v is not None else '...') _rain_str = "r%sp%sP%s" % tuple(_rain_list) # Barometer: _baro = record.get('altimeter') if _baro is None: _baro_str = "b....." else: # While everything else in the CWOP protocol is in US Customary, # they want the barometer in millibars. _new_baro = convert(_baro, 'inHg', 'mbar') _baro_str = "b%05d" % (_new_baro * 10.0) # Humidity: _humidity = record.get('outHumidity') if _humidity is None: _humid_str = "h.." else: _humid_str = ("h%02d" % _humidity) if _humidity < 100.0 else "h00" # Radiation: _radiation = record.get('radiation') if _radiation is None: _radiation_str = "" elif _radiation < 1000.0: _radiation_str = "L%03d" % _radiation elif _radiation < 2000.0: _radiation_str = "l%03d" % (_radiation - 1000) else: _radiation_str = "" # Station equipment _equipment_str = ".nimbus-%s" % self.station_type _tnc_packet = ''.join([_prefix, _time_str, _latlon_str, _wt_str, _rain_str, _baro_str, _humid_str, _radiation_str, _equipment_str, "\r\n"]) return _tnc_packet
def calculate(self, coords): self.calls_to_calculate += 1 # Update coordinates in states. This won't change anything on # the first run through, but will on subsequent ones coord_count = 0 for s in self.states[1:-1]: for a in s: a.x, a.y, a.z = coords[coord_count:coord_count + 3] coord_count += 3 # Start DFT jobs running_jobs = [] for i, state in enumerate(self.states): if (i == 0 or i == len(self.states) - 1) and self.step > 0: # No need to calculate anything for first and last states # after the first step pass else: running_jobs.append( self.start_job(self, i, state, self.charge, self.procs, self.queue, self.initial_guess, self.extra_section, self.mem, self.priority)) # Wait for jobs to finish for j in running_jobs: j.wait() # Get forces and energies from DFT calculations energies = [] for i, state in enumerate(self.states): # State 0 and state N-1 don't change, so just use result # from self.step == 0 if (i == 0 or i == len(self.states) - 1): step_to_use = 0 else: step_to_use = self.step new_energy, new_atoms = self.get_results(self, step_to_use, i, state) energies.append(new_energy) # V = potential energy from DFT. energies = V+springs V = copy.deepcopy(energies) # In climbing image ANEB, after a few iterations we take the highest # energy image and use that. if self.ci_ANEB and self.ci_img is None and self.step > self.ci_N: self.ci_img = V.index(max(V)) if self.ci_img in [0, len(self.states) - 1]: raise Exception("CI found endpoint. Is your band correct?") # Get positions in a flat array def get_positions(image): pos = np.array([np.empty([3]) for j in image]) for j, atom in enumerate(image): if j not in self.spring_atoms: continue pos[j] = np.array([atom.x, atom.y, atom.z]) return pos.flatten() # Add spring forces to atoms for i in range(1, len(self.states) - 1): a = get_positions(self.states[i - 1]) b = get_positions(self.states[i]) c = get_positions(self.states[i + 1]) real_force = np.array([np.empty([3]) for j in self.states[i]]) for j, atom in enumerate(self.states[i]): if j not in self.spring_atoms: continue real_force[j] = np.array([atom.fx, atom.fy, atom.fz]) real_force = real_force.flatten() # Find tangent tplus = c - b tminus = b - a dVmin = min(abs(V[i + 1] - V[i]), abs(V[i - 1] - V[i])) dVmax = max(abs(V[i + 1] - V[i]), abs(V[i - 1] - V[i])) if V[i + 1] > V[i] and V[i] > V[i - 1]: tangent = tplus.copy() elif V[i + 1] < V[i] and V[i] < V[i - 1]: tangent = tminus.copy() elif V[i + 1] > V[i - 1]: tangent = tplus * dVmax + tminus * dVmin else: tangent = tplus * dVmin + tminus * dVmax # Normalize tangent tangent_norm = np.sqrt(np.vdot(tangent, tangent)) if tangent_norm != 0: tangent /= tangent_norm F_spring_parallel = self.k[i - 1] * ( np.linalg.norm(tplus) - np.linalg.norm(tminus)) * tangent F_real_perpendicular = real_force -\ (np.vdot(real_force, tangent) * tangent) # Set ANEB forces # Note, in climbing image we have the formula: # F = F_real - 2*F_real*tau*tau # Vs the normal: # F = F_spring_parallel + F_real_perpendicular if self.ci_img is not None and i == self.ci_img: forces = real_force - 2.0 * np.vdot(real_force, tangent) * tangent else: forces = F_spring_parallel + F_real_perpendicular forces = forces.reshape((-1, 3)) for j, atom in enumerate(self.states[i]): if j not in self.spring_atoms: continue atom.fx, atom.fy, atom.fz = forces[j] # Remove net translation forces from the gradient if self.fit_rigid: net_translation_force = [] for state in self.states[1:-1]: net_force = np.zeros(3) for a in state: net_force += (a.fx, a.fy, a.fz) net_trans = np.sqrt((net_force**2).sum()) / len(state) net_translation_force.append(net_trans) for a in state: a.fx -= net_force[0] / len(state) a.fy -= net_force[1] / len(state) a.fz -= net_force[2] / len(state) max_translation_force = units.convert("Ha/Ang", "eV/Ang", max(net_translation_force)) else: max_translation_force = 0 # Set gradient self.gradient = [] for state in self.states[1:-1]: for a in state: # Gradient of self.error self.gradient += [-a.fx, -a.fy, -a.fz] # Calculate RMS Force and Max force force_mags = [(a.fx**2 + a.fy**2 + a.fz**2)**0.5 for state in self.states[1:-1] for a in state] RMS_force = geometry.rms(force_mags) self.RMS_force = RMS_force MAX_force = max(force_mags) self.MAX_force = MAX_force # Print data V = V[:1] + [ units.convert_energy("Ha", "kT_300", e - V[0]) for e in V[1:] ] MAX_energy = max(V) if self.prv_RMS is None or self.prv_RMS > RMS_force: rms = print_helper.color_set( float("%.4f" % units.convert_energy("Ha", "eV", RMS_force)), 'GREEN') else: rms = print_helper.color_set( float("%.4f" % units.convert_energy("Ha", "eV", RMS_force)), 'RED') if self.prv_MAX is None or self.prv_MAX > MAX_force: max_f = print_helper.color_set( float("%.4f" % units.convert_energy("Ha", "eV", MAX_force)), 'GREEN') else: max_f = print_helper.color_set( float("%.4f" % units.convert_energy("Ha", "eV", MAX_force)), 'RED') if self.prv_MAX_E is None or self.prv_MAX_E > MAX_energy: max_e = print_helper.color_set(float("%.1f" % MAX_energy), 'GREEN') else: max_e = print_helper.color_set(float("%.1f" % MAX_energy), 'RED') if self.step == 0: print("Step\tRMS_F (eV/Ang)\tMAX_F (eV/Ang)\tMAX_E (kT_300)\ \tMAX Translational Force (eV/Ang)\tEnergies (kT_300)\n----") print("%d\t%s\t\t%s\t\t%s\t\t%.4f" % (self.step, rms, max_f, max_e, max_translation_force)), print ' \t\t\t\t', '%7.5g +'\ % V[0], ('%5.1f ' * len(V[1:])) % tuple(V[1:]) self.energy_gaps = [V[1]] + [y - x for y, x in zip(V[2:], V[1:-1])] sys.stdout.flush() if self.prv_RMS is None: self.prv_RMS = RMS_force self.prv_RMS = min(RMS_force, self.prv_RMS) if self.prv_MAX is None: self.prv_MAX = MAX_force self.prv_MAX = min(MAX_force, self.prv_MAX) if self.prv_MAX_E is None: self.prv_MAX_E = MAX_energy self.prv_MAX_E = min(MAX_energy, self.prv_MAX_E) # Set error self.error = RMS_force # Increment step self.step += 1 if self.callback is not None: self.callback(self.states)
def __init__(self, precalculate=True, **kwargs): # Input units units_all = kwargs.pop('unit') # Set internal units. We store angles in rad, distances in pc, velocities in km/s and angular # velocities in rad/s self._sph_unit = ['rad', 'rad', 'pc'] self._cart_unit = ['pc', 'pc', 'pc'] self._sph_unit_pm = ['rad/s', 'rad/s', 'km/s'] self._cart_unit_pm = ['km/s', 'km/s', 'km/s'] if all(cart_name in kwargs for cart_name in self._cart_names): # Cartesian coordinates self._cart = [kwargs.pop('x'), kwargs.pop('y'), kwargs.pop('z')] # Transform cartesian coordinates to km self._cart[0] = units.convert(units_all[:3][0], self._cart_unit[0], self._cart[0]) self._cart[1] = units.convert(units_all[:3][1], self._cart_unit[1], self._cart[1]) self._cart[2] = units.convert(units_all[:3][2], self._cart_unit[2], self._cart[2]) if all(cart_name_pm in kwargs for cart_name_pm in self._cart_names_pm): # Cartesian velocities self._cart_pm = [kwargs.pop('xdot'), kwargs.pop('ydot'), kwargs.pop('zdot')] # Transform cartesian velocities to km/s self._cart_pm[0] = units.convert(units_all[3:][0], self._cart_unit_pm[0], self._cart_pm[0]) self._cart_pm[1] = units.convert(units_all[3:][1], self._cart_unit_pm[1], self._cart_pm[1]) self._cart_pm[2] = units.convert(units_all[3:][2], self._cart_unit_pm[2], self._cart_pm[2]) self._pm = True elif any(latitude in kwargs for latitude in self._latitude_names) and any(longitude in kwargs for longitude in self._longitude_names) and any(dist in kwargs for dist in self._dist_names): # Spherical coordinates names long_name = next(longitude for longitude in self._longitude_names if longitude in kwargs) lat_name = next(latitude for latitude in self._latitude_names if latitude in kwargs) dist_name = next(dist for dist in self._dist_names if dist in kwargs) # Spherical coordinates self._sph = [kwargs.pop(long_name), kwargs.pop(lat_name), kwargs.pop(dist_name)] aux_sph_unit = units_all[:3] # Convert angles to rad and distance to km self._sph[0] = units.convert(aux_sph_unit[0], self._sph_unit[0], self._sph[0]) self._sph[1] = units.convert(aux_sph_unit[1], self._sph_unit[1], self._sph[1]) self._sph[2] = units.convert(aux_sph_unit[2], self._sph_unit[2], self._sph[2]) if any(latitude_pm in kwargs for latitude_pm in self._latitude_names_pm) and any(longitude_pm in kwargs for longitude_pm in self._longitude_names_pm) and any(radvel in kwargs for radvel in self._dist_names_pm): # Spherical proper motions names long_name_pm = next(longitude_pm for longitude_pm in self._longitude_names_pm if longitude_pm in kwargs) lat_name_pm = next(latitude_pm for latitude_pm in self._latitude_names_pm if latitude_pm in kwargs) dist_name_pm = next(radvel for radvel in self._dist_names_pm if radvel in kwargs) # Spherical proper motions self._sph_pm = [kwargs.pop(long_name_pm), kwargs.pop(lat_name_pm), kwargs.pop(dist_name_pm)] aux_sph_unit_pm = units_all[3:] # Convert proper motions to rad/s and radial velocity to km/s self._sph_pm[0] = units.convert(aux_sph_unit_pm[0], self._sph_unit_pm[0], self._sph_pm[0]) self._sph_pm[1] = units.convert(aux_sph_unit_pm[1], self._sph_unit_pm[1], self._sph_pm[1]) self._sph_pm[2] = units.convert(aux_sph_unit_pm[2], self._sph_unit_pm[2], self._sph_pm[2]) self._pm = True else: raise Exception("%s initialized with insufficient or inconsistent data: %s" % (self._name.title(), kwargs)) if precalculate: # Work out cartesian or spherical right now self._calculate_other_coordinates()
def calculate(self, coords): self.calls_to_calculate += 1 # Update coordinates in states. This won't change anything on # the first run through, but will on subsequent ones coord_count = 0 for s in self.states[1:-1]: for a in s: a.x, a.y, a.z = coords[coord_count:coord_count + 3] coord_count += 3 # Start DFT jobs running_jobs = [] if self.initialize == True: # Run a single point calculation to determine energies before main curve-smoothing begins for i, state in enumerate(self.states): running_jobs.append( self.start_job(self, i, state, self.charge, self.procs, self.queue, self.initial_guess, self.extra_section, self.mem, self.priority)) else: # Once initialization is complete, run main spline_NEB simulation for curve smoothing for i, state in enumerate(self.states): if (i == 0 or i == self.peak or i == len(self.states) - 1) and self.step > 0: # No need to calculate anything for first and last states # after the first step pass else: running_jobs.append( self.start_job(self, i, state, self.charge, self.procs, self.queue, self.initial_guess, self.extra_section, self.mem, self.priority)) # Wait for jobs to finish for j in running_jobs: j.wait() # Get forces and energies from DFT calculations energies = [] for i, state in enumerate(self.states): # State 0 and state N-1 don't change, so just use result # from self.step == 0 if (i == 0 or i == self.peak or i == len(self.states) - 1): step_to_use = 0 else: step_to_use = self.step new_energy, new_atoms = self.get_results(self, step_to_use, i, state) energies.append(new_energy) # V = potential energy from DFT. energies = V+springs V = copy.deepcopy(energies) # Get positions in a flat array def get_positions(image): pos = np.array([np.empty([3]) for j in image]) for j, atom in enumerate(image): if j not in self.spring_atoms: continue pos[j] = np.array([atom.x, atom.y, atom.z]) return pos.flatten() if self.initialize == True: # During initialization phase, use single point energies previously calculated to # determine highest energy frame (peak) and generate spring constants between frames # Peak of reaction coordinate is highest energy frame self.peak = energies.index(max(energies)) #Calculate spring constants for smoothing curve d_before = np.linalg.norm( get_positions(self.states[self.peak]) - get_positions(self.states[0])) d_after = np.linalg.norm( get_positions(self.states[self.peak]) - get_positions(self.states[-1])) l_before = -d_before**2 / np.log(self.gamma) l_after = -d_after**2 / np.log(self.gamma) x1, x2 = [], [] for i in range(self.peak): v = (get_positions(self.states[i]) + get_positions(self.states[i+1])) / 2.0 - \ get_positions(self.states[0]) x1.append(np.linalg.norm(v)) for i in range(self.peak, len(self.states) - 1): v = (get_positions(self.states[i]) + get_positions(self.states[i+1])) / 2.0 - \ get_positions(self.states[0]) x2.append(np.linalg.norm(v)) for x in x1: self.k.append(self.k_max * exp(-((x - d_before)**2) / l_before)) for x in x2: self.k.append(self.k_max * exp(-((x - d_after)**2) / l_after)) # Add spring forces to atoms for i in range(1, len(self.states) - 1): if i == self.peak: # Set NEB forces at peak to 0 for j, atom in enumerate(self.states[i]): if j not in self.spring_atoms: continue atom.fx, atom.fy, atom.fz = [0, 0, 0] else: a = get_positions(self.states[i - 1]) b = get_positions(self.states[i]) c = get_positions(self.states[i + 1]) real_force = np.array([np.empty([3]) for j in self.states[i]]) for j, atom in enumerate(self.states[i]): if j not in self.spring_atoms: continue real_force[j] = np.array([atom.fx, atom.fy, atom.fz]) real_force = real_force.flatten() # Find tangent tplus = c - b tminus = b - a dVmin = min(abs(V[i + 1] - V[i]), abs(V[i - 1] - V[i])) dVmax = max(abs(V[i + 1] - V[i]), abs(V[i - 1] - V[i])) if V[i + 1] > V[i] and V[i] > V[i - 1]: tangent = tplus.copy() elif V[i + 1] < V[i] and V[i] < V[i - 1]: tangent = tminus.copy() elif V[i + 1] > V[i - 1]: tangent = tplus * dVmax + tminus * dVmin else: tangent = tplus * dVmin + tminus * dVmax # Normalize tangent tangent_norm = np.sqrt(np.vdot(tangent, tangent)) if tangent_norm != 0: tangent /= tangent_norm # Set NEB forces forces = (self.k[i] * np.linalg.norm(tplus) - self.k[i - 1] * np.linalg.norm(tminus)) * tangent forces = forces.reshape((-1, 3)) for j, atom in enumerate(self.states[i]): if j not in self.spring_atoms: continue atom.fx, atom.fy, atom.fz = forces[j] # Remove net translation forces from the gradient if self.fit_rigid: net_translation_force = [] for state in self.states[1:-1]: net_force = np.zeros(3) for a in state: net_force += (a.fx, a.fy, a.fz) net_trans = np.sqrt((net_force**2).sum()) / len(state) net_translation_force.append(net_trans) for a in state: a.fx -= net_force[0] / len(state) a.fy -= net_force[1] / len(state) a.fz -= net_force[2] / len(state) max_translation_force = units.convert("Ha/Ang", "eV/Ang", max(net_translation_force)) else: max_translation_force = 0 # Set gradient self.gradient = [] for state in self.states[1:-1]: for a in state: # Gradient of self.error self.gradient += [-a.fx, -a.fy, -a.fz] # Calculate RMS Force and Max force force_mags = [(a.fx**2 + a.fy**2 + a.fz**2)**0.5 for state in self.states[1:-1] for a in state] RMS_force = geometry.rms(force_mags) self.RMS_force = RMS_force MAX_force = max(force_mags) self.MAX_force = MAX_force # Print data V = V[:1] + [ units.convert_energy("Ha", "kT_300", e - V[0]) for e in V[1:] ] MAX_energy = max(V) if self.prv_RMS is None or self.prv_RMS > RMS_force: rms = print_helper.color_set( float("%.4f" % units.convert_energy("Ha", "eV", RMS_force)), 'GREEN') else: rms = print_helper.color_set( float("%.4f" % units.convert_energy("Ha", "eV", RMS_force)), 'RED') if self.prv_MAX is None or self.prv_MAX > MAX_force: max_f = print_helper.color_set( float("%.4f" % units.convert_energy("Ha", "eV", MAX_force)), 'GREEN') else: max_f = print_helper.color_set( float("%.4f" % units.convert_energy("Ha", "eV", MAX_force)), 'RED') if self.prv_MAX_E is None or self.prv_MAX_E > MAX_energy: max_e = print_helper.color_set(float("%.1f" % MAX_energy), 'GREEN') else: max_e = print_helper.color_set(float("%.1f" % MAX_energy), 'RED') if self.step == 0 and self.initialize == False: print("Step\tRMS_F (eV/Ang)\tMAX_F (eV/Ang)\tMAX_E (kT_300)\ \tMAX Translational Force (eV/Ang)\tEnergies (kT_300)\n----") print("%d\t%s\t\t%s\t\t%s\t\t%.4f" % (self.step, rms, max_f, max_e, max_translation_force)), print ' \t\t\t\t', '%7.5g +'\ % V[0], ('%5.1f ' * len(V[1:])) % tuple(V[1:]) sys.stdout.flush() if self.prv_RMS is None: self.prv_RMS = RMS_force self.prv_RMS = min(RMS_force, self.prv_RMS) if self.prv_MAX is None: self.prv_MAX = MAX_force self.prv_MAX = min(MAX_force, self.prv_MAX) if self.prv_MAX_E is None: self.prv_MAX_E = MAX_energy self.prv_MAX_E = min(MAX_energy, self.prv_MAX_E) # Set error self.error = RMS_force # Increment step self.step += 1 # End initialization phase self.initialize = False if self.callback is not None: self.callback(self.states)
def dispFormat(self, unit): return str(round(units.convert(self.value, self.unit, unit), 6)) + ' ' + unit
def engrad_read(input_file, force='Ha/Bohr', pos='Bohr'): """ General read in of all possible data from an Orca engrad file (.orca.engrad). **Parameters** input_file: *str* Orca .orca.engrad file to be parsed. force: *str, optional* Units you want force to be returned in. pos: *str, optional* Units you want position to be returned in. **Returns** atoms: *list,* :class:`structures.Atom` A list of the final atomic state, with forces appended to each atom. energy: *float* The total energy of this simulation. """ if not input_file.endswith('.engrad'): input_file = 'orca/%s/%s.orca.engrad' % (input_file, input_file) if not os.path.isfile(input_file): raise IOError("No engrad file %s exists in %s. \ Please run simulation with grad=True." % (input_file, os.getcwd())) data = open(input_file, 'r').read().split('\n') count, grad, atoms = 0, [], [] i = -1 while i < len(data): i += 1 line = data[i] if len(line) < 1: continue if line.strip()[0] == '#': continue if count == 0: num_atoms = int(line.strip()) count += 1 elif count == 1: # Get energy energy = float(line.strip()) count += 1 elif count == 2: # Get gradient for j in range(num_atoms): for k in range(3): grad.append(float(data[i + k].strip())) i += 3 count += 1 elif count == 3: # Get atom coordinates k = 0 for j in range(num_atoms): tmp = data[i].split() atoms.append(structures.Atom(tmp[0], units.convert_dist('Bohr', pos, float(tmp[1]) ), units.convert_dist('Bohr', pos, float(tmp[2]) ), units.convert_dist('Bohr', pos, float(tmp[3]) ) ) ) atoms[-1].fx = units.convert('Ha/Bohr', force, -grad[k]) atoms[-1].fy = units.convert('Ha/Bohr', force, -grad[k + 1]) atoms[-1].fz = units.convert('Ha/Bohr', force, -grad[k + 2]) i += 1 k += 3 break return atoms, energy
import yaml import numpy as np from colorama import Fore from mix import CON_NUTRI from units import convert from util import sum_quantity_key from usda import lookup_nutrition, STANDARD_UNITS # import logging; logging.basicConfig(level=logging.DEBUG) ingredients = yaml.load(open('shake.yaml', 'r')) nutritions = [lookup_nutrition(i['id']) for i in ingredients] for i, n in zip(ingredients, nutritions): i.update(n) mix = np.array([convert(i['qty'], 'g')[0] for i in ingredients]) for k, v in CON_NUTRI.items(): amt = sum_quantity_key(ingredients, mix, 'nutrients.{}.value'.format(k)) off_by = amt - v[0] percent = amt / v[0] * 100 if off_by >= 0: pre = Fore.GREEN else: pre = Fore.RED off_by = pre + '{}{:.2f}{}'.format('+' if off_by > 0 else '', off_by, STANDARD_UNITS[k]) + Fore.RESET percent = pre + '{:.1f}%'.format(percent) + Fore.RESET print('{: >20} {: >12} {: >12} {: <22} {: >20}'.format( k, '{:.2f}{}'.format(v[0], STANDARD_UNITS[k]), '{:.2f}{}'.format(amt, STANDARD_UNITS[k]), off_by, percent))
# cube root of the atomic volume, to have an estimate for # the for the distance between atoms in the solid. (d) # Repeat the calculations for uranium. # The volume of 1 mol of iron is obtained by dividing the molar mass of iron # by the density of iron. volume_1mol_fe = Fe().molar_mass / Fe().density #cm^3 print '2) a) The volume of 1 mol of iron is %.2f' % volume_1mol_fe, 'cm^3.' # The volume of one atom of iron is obtained by dividing the molar mass of iron # by Avogadro's constant and dividing this by the density of iron. volume_1atom_fe = Fe().molar_mass / Particle().N_A / Fe().density #cm^3 volume_1atom_fe = units.convert(volume_1atom_fe, 'centi', 'base', 3) #m^3 print ' b) The volume of 1 atom of iron is %.2e' % volume_1atom_fe, 'm^3.' atom_distance_fe = volume_1atom_fe ** (1.0 / 3.0) #m atom_distance_fe = units.convert(atom_distance_fe, 'base', 'nano', 1) #nm print ' c) The distance between atoms is %.3f' % atom_distance_fe, 'nm.' volume_1mol_u = U().molar_mass / U().density #cm^3 volume_1atom_u = U().molar_mass / Particle().N_A / U().density #cm^3 volume_1atom_u = units.convert(volume_1atom_u, 'centi', 'base', 3) #m^3 atom_distance_u = volume_1atom_u ** (1.0 / 3.0) #m atom_distance_u = units.convert(atom_distance_u, 'base', 'nano', 1) #nm print ' d) The volume of 1 mol of uranium is %.1f' % volume_1mol_u, 'cm^3.'
def __init__(self, precalculate=True, **kwargs): # Input units units_all = kwargs.pop('unit') # Set internal units. We store angles in rad, distances in pc, velocities in km/s and angular # velocities in rad/s self._sph_unit = ['rad', 'rad', 'pc'] self._cart_unit = ['pc', 'pc', 'pc'] self._sph_unit_pm = ['rad/s', 'rad/s', 'km/s'] self._cart_unit_pm = ['km/s', 'km/s', 'km/s'] if all(cart_name in kwargs for cart_name in self._cart_names): # Cartesian coordinates self._cart = [kwargs.pop('x'), kwargs.pop('y'), kwargs.pop('z')] # Transform cartesian coordinates to km self._cart[0] = units.convert(units_all[:3][0], self._cart_unit[0], self._cart[0]) self._cart[1] = units.convert(units_all[:3][1], self._cart_unit[1], self._cart[1]) self._cart[2] = units.convert(units_all[:3][2], self._cart_unit[2], self._cart[2]) if all(cart_name_pm in kwargs for cart_name_pm in self._cart_names_pm): # Cartesian velocities self._cart_pm = [ kwargs.pop('xdot'), kwargs.pop('ydot'), kwargs.pop('zdot') ] # Transform cartesian velocities to km/s self._cart_pm[0] = units.convert(units_all[3:][0], self._cart_unit_pm[0], self._cart_pm[0]) self._cart_pm[1] = units.convert(units_all[3:][1], self._cart_unit_pm[1], self._cart_pm[1]) self._cart_pm[2] = units.convert(units_all[3:][2], self._cart_unit_pm[2], self._cart_pm[2]) self._pm = True elif any(latitude in kwargs for latitude in self._latitude_names) and any( longitude in kwargs for longitude in self._longitude_names) and any( dist in kwargs for dist in self._dist_names): # Spherical coordinates names long_name = next(longitude for longitude in self._longitude_names if longitude in kwargs) lat_name = next(latitude for latitude in self._latitude_names if latitude in kwargs) dist_name = next(dist for dist in self._dist_names if dist in kwargs) # Spherical coordinates self._sph = [ kwargs.pop(long_name), kwargs.pop(lat_name), kwargs.pop(dist_name) ] aux_sph_unit = units_all[:3] # Convert angles to rad and distance to km self._sph[0] = units.convert(aux_sph_unit[0], self._sph_unit[0], self._sph[0]) self._sph[1] = units.convert(aux_sph_unit[1], self._sph_unit[1], self._sph[1]) self._sph[2] = units.convert(aux_sph_unit[2], self._sph_unit[2], self._sph[2]) if any(latitude_pm in kwargs for latitude_pm in self._latitude_names_pm) and any( longitude_pm in kwargs for longitude_pm in self._longitude_names_pm) and any( radvel in kwargs for radvel in self._dist_names_pm): # Spherical proper motions names long_name_pm = next( longitude_pm for longitude_pm in self._longitude_names_pm if longitude_pm in kwargs) lat_name_pm = next(latitude_pm for latitude_pm in self._latitude_names_pm if latitude_pm in kwargs) dist_name_pm = next(radvel for radvel in self._dist_names_pm if radvel in kwargs) # Spherical proper motions self._sph_pm = [ kwargs.pop(long_name_pm), kwargs.pop(lat_name_pm), kwargs.pop(dist_name_pm) ] aux_sph_unit_pm = units_all[3:] # Convert proper motions to rad/s and radial velocity to km/s self._sph_pm[0] = units.convert(aux_sph_unit_pm[0], self._sph_unit_pm[0], self._sph_pm[0]) self._sph_pm[1] = units.convert(aux_sph_unit_pm[1], self._sph_unit_pm[1], self._sph_pm[1]) self._sph_pm[2] = units.convert(aux_sph_unit_pm[2], self._sph_unit_pm[2], self._sph_pm[2]) self._pm = True else: raise Exception( "%s initialized with insufficient or inconsistent data: %s" % (self._name.title(), kwargs)) if precalculate: # Work out cartesian or spherical right now self._calculate_other_coordinates()
def read(input_file, atom_units="Ang"): """ General read in of all possible data from a JDFTx output file. **Parameters** input_file: *str* JDFTx output file to be parsed. atom_units: *str, optional* What units you want coordinates to be converted to. **Returns** data: :class:`results.DFT_out` Generic DFT output object containing all parsed results. """ # Check file exists, and open # Allow absolute paths as filenames if not input_file.startswith('/') and not os.path.isfile(input_file): input_path = 'jdftx/%s/%s.out' % (input_file, input_file) else: input_path = input_file if not os.path.isfile(input_path): raise IOError('Expected JDFTx output file does not exist at %s' % (input_path)) sys.exit() data = open(input_path, 'r').read() data_lines = data.splitlines() # Get coordinates section, frames, gradients = data, [], [] s = "# Ionic positions in cartesian coordinates:" ss = "# Forces in Cartesian coordinates:" while s in section: section = section[section.find(s) + len(s):] atom_block = section[:section.find('\n\n')].split('\n')[1:] frame, gradient = [], [] for i, line in enumerate(atom_block): a = line.split() frame.append( structures.Atom(a[1], units.convert_dist("Bohr", atom_units, float(a[2])), units.convert_dist("Bohr", atom_units, float(a[3])), units.convert_dist("Bohr", atom_units, float(a[4])), index=i)) frames.append(frame) # If we also have forces, read those in if ss in section: section = section[section.find(ss) + len(ss):] force_block = section[:section.find('\n\n')].split('\n')[1:] for i, line in enumerate(force_block): a = line.split() frames[-1][i].fx = units.convert("Ha/Bohr", "Ha/%s" % atom_units, float(a[2])) frames[-1][i].fy = units.convert("Ha/Bohr", "Ha/%s" % atom_units, float(a[3])) frames[-1][i].fz = units.convert("Ha/Bohr", "Ha/%s" % atom_units, float(a[4])) gradient.append( [frames[-1][i].fx, frames[-1][i].fy, frames[-1][i].fz]) gradients.append(gradient) atoms = None if frames: atoms = frames[-1] section, energies = data, [] s = "IonicMinimize: Iter:" while s in section: section = section[section.find(s) + len(s):] energy = float(section.split("\n")[0].strip().split()[2]) grad_k = float(section.split("\n")[0].strip().split()[4]) energies.append(energy) convergence = None if len(energies) > 2: section = data[data.find("ionic-minimize"):] de_criteria = float( section[section.find("energyDiffThreshold"):].split( "\n")[0].strip().split()[1]) k_criteria = float(section[section.find("knormThreshold"):].split("\n") [0].strip().split()[1]) de1 = abs(energies[-2] - energies[-3]) de2 = abs(energies[-1] - energies[-2]) convergence = [[ "Change in Energy 1", "%.2e" % de1, de_criteria, ["NO", "YES"][de_criteria > de1] ], [ "Change in Energy 2", "%.2e" % de2, de_criteria, ["NO", "YES"][de_criteria > de2] ], [ "K Norm", "%.2e" % abs(grad_k), k_criteria, ["NO", "YES"][k_criteria > abs(grad_k)] ]] # convergence = [ # ["dE 1 (%.2e)" % de_criteria, "dE 2 (%.2e)" % de_criteria, "K Norm (%.2e)" % k_criteria], # ["%.4e" % abs(energies[-2] - energies[-3]), "%.4e" % abs(energies[-1] - energies[-2]), "%.4e" % abs(grad_k)] # ] energy = None if energies: energy = energies[-1] converged = None finished = "Done!" in data if "IonicMinimize: Converged" in data: converged = True elif finished: converged = False time = None if "Duration:" in data: time = data[data.find("Duration:"):].split("\n")[0].split( "Duration:")[-1].strip()[:-1].split(":") # Time should be x-x:yy:zz.zz, thus: [x-x, yy, zz.zz] time = float(time[2]) + 60.0 * float(time[1]) + 3600.0 * float( time[0].split("-")[-1]) data = results.DFT_out(input_file, 'jdftx') # data.route = route # data.extra_section = extra_section # data.charge_and_multiplicity = charge_and_multiplicity.strip() data.frames = frames data.atoms = atoms data.gradients = gradients data.energies = energies data.energy = energy # data.charges_MULLIKEN = charges_MULLIKEN # data.charges_LOEWDIN = charges_LOEWDIN # data.charges_CHELPG = charges_CHELPG # data.charges = copy.deepcopy(charges_MULLIKEN) # data.MBO = MBO data.convergence = convergence data.converged = converged data.time = time # data.bandgaps = bandgaps # data.bandgap = bandgap # data.orbitals = orbitals data.finished = finished # data.warnings = warnings return data