def write_cube(atoms: np.ndarray, coords: np.ndarray, origin: np.ndarray, vectors: np.ndarray, gridshape: tuple, values: Union[list, np.ndarray], fname: str, comment: str = None, gauss_style: bool = False): """Write cubefile in Gaussian format. Parameters ---------- atoms : np.ndarray Atoms of the molecule, atomic symbols. coords : np.ndarray((natoms, 3), dtype=float) Spacial coordinates of atoms, in Bohr. origin : np.ndarray((3,), dtype=float) Where to place the origin of the axis. gridshape : tuple(3) Number of steps performed in each direction (nx, ny, nz). values : np.ndarray(dtype=float) Array with all the values arranged so z moves first, then y then x. comment : str First two lines of the cubefile. gauss_style : bool Whether to print the values at each point as in Gaussian (5 values per line). False option prints each value per line. """ if comment is None: comment = default_comment natoms = len(atoms) head = "{:5}{:12.6f}{:12.6f}{:12.6f}\n" satoms = "{:5}{:12.6f}{:12.6f}{:12.6f}{:12.6f}\n" if atoms.dtype == '<U2' or atoms.dtype == '<U1': numbers = [pt.to_atomic_number(a) for a in atoms] elif atoms.dtype == 'int': numbers = atoms else: raise TypeError("`atoms` must be provided as str or int.") with open(fname, "w") as output: output.write(comment) output.write(head.format(natoms, origin[0], origin[1], origin[2])) for i in range(3): output.write(head.format(gridshape[i], vectors[i, 0], vectors[i, 1], vectors[i, 2])) for i in range(natoms): output.write(satoms.format(numbers[i], 0.0, coords[i, 0], coords[i, 1], coords[i, 2])) for n, value in enumerate(values): if gauss_style: if (n+1) % 6 == 0 or n == len(values)-1: output.write("{:12.6e}\n".format(value)) else: output.write("{:12.6e} ".format(value)) else: output.write("{:12.6e}\n".format(value))
def from_qcschema(cls, qcschema): new_mol = cls() topology = qcschema["molecule"] at_symbs = topology["symbols"] new_mol.atoms = [ periodictable.to_atomic_number(atom) for atom in at_symbs ] new_mol.identifiers = {} new_mol.trajectories = [] new_mol.charge = topology[ "molecular_charge"] if "molecular_charge" in topology.keys( ) else None new_mol.bonds = topology[ "connectivity"] if "connectivity" in topology.keys() else [] new_mol.multiplicity = topology["molecular_multiplicity"] if "molecular_multiplicity" in topology.keys() \ else None if "name" in topology.keys(): new_mol.identifiers["name"] = [topology["name"]] return new_mol
def test_write_and_read(): dic = os.getenv('FDETADATA') name = 'solvent_charge_density_aroud_acetone.cube' fname = os.path.join(dic, name) data = read_cubefile(fname) grid_shape = data["grid_shape"] vectors = data["vectors"] origin = data["origin"] atoms = data["atoms"] coords = data["coords"] values = data["values"] numbers = np.array([pt.to_atomic_number(a) for a in atoms]) fname = "solvent_new.cube" write_cube(numbers, coords, origin, vectors, grid_shape, values, fname) data2 = read_cubefile('solvent_new.cube') assert (data['atoms'] == data2['atoms']).all() assert np.allclose(data['coords'], data2['coords']) assert np.allclose(data['origin'], data2['origin']) assert np.allclose(data['vectors'], data2['vectors']) assert data['grid_shape'] == data2['grid_shape'] os.remove('solvent_new.cube')
def atom_to_charge(atom: Union[str, int]) -> float: """Give the nucleus atomic charge.""" return float(periodictable.to_atomic_number(atom))
def from_qcmol(cls, qcmol: QCMol) -> 'Geometry': new_geom = cls() new_geom.atoms = torch.tensor([periodictable.to_atomic_number(symbol) for symbol in qcmol.symbols]) new_geom.xyz = torch.tensor(qcmol.geometry, dtype=torch.float32) return new_geom
def write_parameters_file(elements: Union[List, np.ndarray], surnames: Union[List, np.ndarray], coords: np.ndarray, vcharge: Union[List, np.ndarray], vsigma: Union[List, np.ndarray], vepsilon: Union[List, np.ndarray], fname: str = "pars.in", comment: str = "Input made with FDETA module.\n"): """Write text file with parameters for MDFT. Parameters ---------- elements : list or array of str Elements of the fragment or molecule. surnames : list or array of str Surnames for the elements of the fragment or molecule. coords : np.ndarray Cartesian coordinates in Angstrom of the fragment or molecule. vcharge : list or array [float] Vector with charges for each element. vsigma : list or array [float] Vector with sigma values (LJ parameters). vepsilon : list or array [float] Vector with epsilon values (LJ parameters). comment : str Comment to be added in the first line of the file. """ # Check all arrays have the same lenght check_length([elements, surnames, coords, vcharge, vsigma, vepsilon]) # Check for repeated and unique elements natoms = len(elements) repeated = [] uniques = [None] * natoms count = 0 for i in range(natoms): for j in range(i + 1, natoms): # Assumes that vsigma and vepsilon are always paired (same value) if vcharge[i] == vcharge[j] and vsigma[i] == vsigma[j]: repeated += [i, j] if not uniques[j]: uniques[j] = i + 1 - count count += 1 else: if not uniques[i]: if i not in repeated: uniques[i] = i + 1 - count else: uniques[i] = i + 2 - count if not uniques[-1]: uniques[-1] = natoms - count nuniques = natoms - count title_format = '{:3} {:^10} {:^10} {:10} {:^13} {:^13} {:^13} {:^8} {:^10} {:^8}\n' header = title_format.format('#', 'charge', 'sigma', 'epsilon', 'x', 'y', 'z', 'Z', 'Atom name', 'Surname') out = "" for i in range(natoms): out += '{:3}'.format(str(uniques[i])) out += '{:10.6f}'.format(vcharge[i]) out += '{:10.6f}'.format(vsigma[i]) out += '{:10.6f}'.format(vepsilon[i]) for j in range(3): out += '{:>15.10f}'.format(coords[i, j]) out += '{:>5}'.format(str(periodictable.to_atomic_number(elements[i]))) out += '{:^19}'.format(elements[i]) out += '{}\n'.format(surnames[i]) # Write file with open(fname, 'w') as outfile: outfile.write(comment) outfile.write("%d %d\n" % (natoms, nuniques)) outfile.write(header) outfile.write(out)