def test_process_units_object(units_preparation): natoms, frames, comment, conver_xyz, conver_cell = units_preparation output = "objects" filedesc, xyz, atom_names = xyz_gen.xyz_traj_filedesc( natoms, frames, comment) cell = mt.abc2h(1.0, 1.0, 1.0, np.pi / 2.0, np.pi / 2.0, np.pi / 2.0) masses = [] _count = 0 for _at in atom_names: print(Elements.mass(_at), _count, _at) masses.append(Elements.mass(_at)) _count += 1 masses = np.array(masses) res = testing.process_units( comment, cell.copy(), xyz.copy(), np.array(atom_names).copy(), np.array(masses).copy(), output=output, ) npt.assert_array_almost_equal(res["atoms"].q, xyz * conver_xyz, 5) npt.assert_array_almost_equal(res["atoms"].m, masses, 5) npt.assert_array_almost_equal(res["cell"].h, cell * conver_cell, 5) npt.assert_array_equal(res["atoms"].names, atom_names, 5)
def test_process_units_noobj(units_preparation): natoms, frames, comment, conver_xyz, conver_cell = units_preparation output = 'noobj' filedesc, xyz, atom_names = xyz_gen.xyz_traj_filedesc(natoms, frames, comment) cell = mt.abc2h(1.0, 1.0, 1.0, np.pi/2.0, np.pi/2.0, np.pi/2.0) masses = [] _count = 0 print 'atom_names', atom_names for _at in atom_names: print Elements.mass(_at), _count, _at masses.append(Elements.mass(_at)) _count += 1 masses = np.array(masses) type(masses) res = testing.process_units(comment, cell.copy(), xyz.copy(), np.array(atom_names).copy(), np.array(masses).copy(), output=output) print xyz,res['data'] npt.assert_array_almost_equal(res['data'], xyz * conver_xyz, 5) npt.assert_array_almost_equal(res['masses'], masses, 5) npt.assert_array_almost_equal(res['cell'], cell * conver_cell, 5) npt.assert_array_equal(res['names'], atom_names, 5) assert res['natoms'] == natoms
def test_process_units_noobj(units_preparation): natoms, frames, comment, conver_xyz, conver_cell = units_preparation output = "noobj" filedesc, xyz, atom_names = xyz_gen.xyz_traj_filedesc( natoms, frames, comment) cell = mt.abc2h(1.0, 1.0, 1.0, np.pi / 2.0, np.pi / 2.0, np.pi / 2.0) masses = [] _count = 0 print("atom_names", atom_names) for _at in atom_names: print(Elements.mass(_at), _count, _at) masses.append(Elements.mass(_at)) _count += 1 masses = np.array(masses) type(masses) res = testing.process_units( comment, cell.copy(), xyz.copy(), np.array(atom_names).copy(), np.array(masses).copy(), output=output, ) print(xyz, res["data"]) npt.assert_array_almost_equal(res["data"], xyz * conver_xyz, 5) npt.assert_array_almost_equal(res["masses"], masses, 5) npt.assert_array_almost_equal(res["cell"], cell * conver_cell, 5) npt.assert_array_equal(res["names"], atom_names, 5) assert res["natoms"] == natoms
def test_process_units_object(units_preparation): natoms, frames, comment, conver_xyz, conver_cell = units_preparation output = 'objects' filedesc, xyz, atom_names = xyz_gen.xyz_traj_filedesc(natoms, frames, comment) cell = mt.abc2h(1.0, 1.0, 1.0, np.pi / 2.0, np.pi / 2.0, np.pi / 2.0) masses = [] _count = 0 for _at in atom_names: print Elements.mass(_at), _count, _at masses.append(Elements.mass(_at)) _count += 1 masses = np.array(masses) res = testing.process_units(comment, cell.copy(), xyz.copy(), np.array(atom_names).copy(), np.array(masses).copy(), output=output) npt.assert_array_almost_equal(res['atoms'].q, xyz * conver_xyz, 5) npt.assert_array_almost_equal(res['atoms'].m, masses, 5) npt.assert_array_almost_equal(res['cell'].h, cell * conver_cell, 5) npt.assert_array_equal(res['atoms'].names, atom_names, 5)
def test_process_units_noobj(units_preparation): natoms, frames, comment, conver_xyz, conver_cell = units_preparation output = 'noobj' filedesc, xyz, atom_names = xyz_gen.xyz_traj_filedesc(natoms, frames, comment) cell = mt.abc2h(1.0, 1.0, 1.0, np.pi / 2.0, np.pi / 2.0, np.pi / 2.0) masses = [] _count = 0 print 'atom_names', atom_names for _at in atom_names: print Elements.mass(_at), _count, _at masses.append(Elements.mass(_at)) _count += 1 masses = np.array(masses) type(masses) res = testing.process_units(comment, cell.copy(), xyz.copy(), np.array(atom_names).copy(), np.array(masses).copy(), output=output) print xyz, res['data'] npt.assert_array_almost_equal(res['data'], xyz * conver_xyz, 5) npt.assert_array_almost_equal(res['masses'], masses, 5) npt.assert_array_almost_equal(res['cell'], cell * conver_cell, 5) npt.assert_array_equal(res['names'], atom_names, 5) assert res['natoms'] == natoms
def create_random_xyz_traj_to_write(request): natoms, frames, comment, expected_cell, precision = request.param a, b, c, alpha, beta, gamma = mt.h2abc_deg(expected_cell) fmt_header = "# CELL(abcABC): %10.5f %10.5f %10.5f %10.5f %10.5f %10.5f %s" comment = fmt_header % (a, b, c, alpha, beta, gamma, comment) filedesc, xyz, atom_names = xyz_gen.xyz_traj_filedesc(natoms, frames, comment) filedesc.seek(0) masses = [Elements.mass(_am) for _am in atom_names] cell_list = [] atoms_list = [] for _fr in xrange(frames): cell = Cell(expected_cell) atoms = Atoms(natoms) atoms.q[:] = xyz[_fr * natoms * 3:(_fr + 1) * natoms * 3] atoms.names = atom_names[_fr * natoms:(_fr + 1) * natoms] atoms.m[:] = masses[_fr * natoms:(_fr + 1) * natoms] atoms_list.append(atoms) cell_list.append(cell) return (filedesc, atoms_list, cell_list, comment, precision)
def read_pdb(filedesc, **kwargs): """Reads a PDB-style file and creates an Atoms and Cell object. Args: filedesc: An open readable file object from a pdb formatted file. Returns: An Atoms object with the appropriate atom labels, masses and positions, and a Cell object with the appropriate cell dimensions and an estimate of a reasonable cell mass. """ header = filedesc.readline() comment = '' if "TITLE" in header: # skip the comment field comment = copy.copy(header) header = filedesc.readline() if 'positions{' not in comment: comment = comment.strip() comment += ' positions{angstrom}\n' if 'cell{' not in comment: comment = comment.strip() comment += ' cell{angstrom}\n' if header == "": raise EOFError("End of file or empty header in PDB file") a = float(header[6:15]) b = float(header[15:24]) c = float(header[24:33]) alpha = float(header[33:40]) beta = float(header[40:47]) gamma = float(header[47:54]) alpha *= np.pi / 180.0 beta *= np.pi / 180.0 gamma *= np.pi / 180.0 h = mt.abc2h(a, b, c, alpha, beta, gamma) cell = h natoms = 0 body = filedesc.readline() qatoms = [] names = [] masses = [] while (body.strip() != "" and body.strip() != "END"): natoms += 1 name = body[12:16].strip() names.append(name) masses.append(Elements.mass(name)) x = float(body[31:39]) y = float(body[39:47]) z = float(body[47:55]) qatoms.append(x) qatoms.append(y) qatoms.append(z) body = filedesc.readline() return comment, cell, np.asarray(qatoms), np.asarray( names, dtype='|S4'), np.asarray(masses)
def create_xyz_sample_file(request): """ Create a fake xyz file and build the atoms and cell object from it. """ natoms, frames, comment, expected_cell, units_conv_at, units_conv_cell = request.param filedesc, xyz, atoms_names = xyz_gen.xyz_traj_filedesc(natoms, frames, comment) # init_file needs to read from a real file... tmp_file = tmp.NamedTemporaryFile(mode='wr', prefix='ipi_testing-tmp', delete=False) tmp_file.seek(0) tmp_file.write(filedesc.read()) tmp_file.close() filedesc.close() masses = np.zeros(natoms * frames) for _ii, _at in enumerate(atoms_names): masses[_ii] = Elements.mass(_at) ratoms = [] for _fr in range(frames): ratoms.append(Atoms(natoms)) ratoms[-1].q = xyz[_fr * natoms * 3:3 * (_fr + 1) * natoms] * units_conv_at ratoms[-1].m = masses[_fr * natoms:(_fr + 1) * natoms] ratoms[-1].names = atoms_names[_fr * natoms:(_fr + 1) * natoms] cell = Cell(expected_cell * units_conv_cell) # remove temp file created during this test def delete_files_after_testing(): if os.path.isfile(tmp_file.name): os.remove(tmp_file.name) request.addfinalizer(delete_files_after_testing) return tmp_file, cell, ratoms
def read_xyz(filedesc): """Reads an XYZ-style file with i-PI style comments and returns data in raw format for further units transformation and other post processing. Args: filedesc: An open readable file object from a xyz formatted file with i-PI header comments. Returns: i-Pi comment line, cell array, data (positions, forces, etc.), atoms names and masses """ try: natoms = int(filedesc.next()) except (StopIteration, ValueError): raise EOFError comment = filedesc.next() # Extracting cell cell = [key.search(comment) for key in cell_re] usegenh = False if cell[0] is not None: # abcABC a, b, c = [float(x) for x in cell[0].group(1).split()[:3]] alpha, beta, gamma = [float(x) * deg2rad for x in cell[0].group(1).split()[3:6]] h = mt.abc2h(a, b, c, alpha, beta, gamma) elif cell[1] is not None: # GENH h = np.array(cell[1].group(1).split()[:9], float) h.resize((3, 3)) elif cell[2] is not None: # H genh = np.array(cell[2].group(1).split()[:9], float) genh.resize((3, 3)) invgenh = np.linalg.inv(genh) # convert back & forth from abcABC representation to get an upper triangular h h = mt.abc2h(*mt.genh2abc(genh)) usegenh = True else: # defaults to unit box h = np.array([[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, -1.0]]) cell = h qatoms = np.zeros(3 * natoms) names = np.zeros(natoms, dtype='|S4') masses = np.zeros(natoms) # Extracting a time-frame information atom_counter = 0 for iat, line in enumerate(filedesc): body = line.split() names[iat], masses[iat] = body[0], Elements.mass(body[0]) x, y, z = float(body[1]), float(body[2]), float(body[3]) # TODO: The following in matrices would use vectorial computaiton if usegenh: # must convert from the input cell parameters to the internal convention u = np.array([x, y, z]) us = np.dot(u, invgenh) u = np.dot(h, us) x, y, z = u qatoms[3 * iat], qatoms[3 * iat + 1], qatoms[3 * iat + 2] = x, y, z atom_counter += 1 if atom_counter == natoms: break if natoms != len(names): raise ValueError("The number of atom records does not match the header of the xyz file.") return comment, cell, qatoms, names, masses
def RDF(prefix, temp, A, B, nbins, r_min, r_max, ss=0, unit='angstrom'): # Adding fortran functions (when exist) sys.path.append(os.path.abspath(os.path.dirname(sys.argv[0]))[:-2] + 'f90') try: import fortran except: print( 'WARNING: No compiled fortran module for fast calculations have been found.\n' 'Proceeding the calculations is not possible.') sys.exit(0) temperature = unit_to_internal("temperature", "kelvin", float(temp)) # simulation temperature skipSteps = int(ss) # steps to skip nbins = int(nbins) fns_pos = sorted(glob.glob(prefix + ".pos*")) fns_for = sorted(glob.glob(prefix + ".for*")) fn_out_rdf, fn_out_rdf_q = prefix + '.' + A + B + ".rdf.dat", prefix + '.' + A + B + ".rdf-ppi.dat" # check that we found the same number of positions and forces files nbeads = len(fns_pos) if nbeads != len(fns_for): print fns_pos print fns_for raise ValueError( "Mismatch between number of input files for forces and positions.") # print some information print 'temperature = {:f} K'.format(float(temp)) print print 'number of beads = {:d}'.format(nbeads) print print 'positions and forces file names:' for fn_pos, fn_for in zip(fns_pos, fns_for): print '{:s} {:s}'.format(fn_pos, fn_for) print print 'output file names:' print fn_out_rdf print fn_out_rdf_q print # open input and output files ipos = [open(fn, "r") for fn in fns_pos] ifor = [open(fn, "r") for fn in fns_for] #iRDF, iRDFq = open(fn_out_rdf, "w"), open(fn_out_rdf_q, "w") # Species for RDF species = (A, B) speciesMass = np.array( [Elements.mass(species[0]), Elements.mass(species[1])], order='F') r_min = unit_to_internal('length', unit, float(r_min)) # Minimal distance for RDF r_max = unit_to_internal('length', unit, float(r_max)) # Maximal distance for RDF dr = (r_max - r_min) / nbins # RDF step rdf = np.array([[r_min + (0.5 + i) * dr, 0] for i in range(nbins)], order='F') # conventional RDF # RDF auxiliary variables cell = None # simulation cell matrix inverseCell = None # inverse simulation sell matrix cellVolume = None # simulation cell volume natomsA = 0 # the total number of A type particles in the system natomsB = 0 # the total number of B type particles in the system # Here A and B are the types of elements used for RDF calculations # temp variables f2 = 0.0 # the sum of square forces divided by corresponding masses (f2/m) f2rdf = np.zeros( nbins, order='F') # the sum f2/m multiplied by the rdf at each time step frdf = np.zeros( nbins, order='F' ) # the sum of f/m multiplied by the rdf derivative at each time step natoms = 0 # total number of atoms ifr = 0 # time frame number pos, force, mass = None, None, None # positions, forces, and mass arrays noteof = True # end of file test variable while noteof: # Reading input files and calculating PPI correction if ifr % 100 == 0: print '\rProcessing frame {:d}'.format(ifr), sys.stdout.flush() try: for i in range(nbeads): ret = read_file("xyz", ipos[i]) if natoms == 0: mass, natoms = ret["atoms"].m, ret["atoms"].natoms pos = np.zeros((nbeads, 3 * natoms), order='F') force = np.zeros((nbeads, 3 * natoms), order='F') cell = ret["cell"].h inverseCell = ret["cell"].get_ih() cellVolume = ret["cell"].get_volume() pos[i, :] = ret["atoms"].q force[i, :] = read_file("xyz", ifor[i])["atoms"].q except EOFError: # finished reading files noteof = False if noteof: if ifr >= skipSteps: # RDF calculations species_A = [ 3 * i + j for i in np.where(mass == speciesMass[0])[0] for j in range(3) ] species_B = [ 3 * i + j for i in np.where(mass == speciesMass[1])[0] for j in range(3) ] natomsA = len(species_A) natomsB = len(species_B) posA = np.zeros((nbeads, natomsA), order='F') posB = np.zeros((nbeads, natomsB), order='F') forA = np.zeros((nbeads, natomsA), order='F') forB = np.zeros((nbeads, natomsB), order='F') for bead in range(nbeads): posA[bead, :] = pos[bead, species_A] forA[bead, :] = force[bead, species_A] posB[bead, :] = pos[bead, species_B] forB[bead, :] = force[bead, species_B] # RDF amd PPI RDF calculations f2temp = fortran.f2divm(force, mass, natoms, nbeads) f2 += f2temp fortran.updateqrdf(rdf, f2rdf, frdf, posA, posB, forA, forB, natomsA / 3, natomsB / 3, nbins, r_min, r_max, cell, inverseCell, nbeads, f2temp, speciesMass[0], speciesMass[1]) ifr += 1 else: ifr += 1 # Some constants const = 1.0 / float(ifr - skipSteps) alpha = Constants.hbar**2 / (24.0 * nbeads**3 * (temperature * Constants.kb)**3) beta = Constants.hbar**2 / (12.0 * nbeads**3 * (temperature * Constants.kb)**2) # Normalization rdf[:, 1] *= const / nbeads f2 *= alpha * const f2rdf[:] *= alpha * const frdf[:] *= beta * const # PPI correction rdfQ = np.copy(rdf) for bin in range(nbins): rdfQ[bin, 1] += (rdf[bin, 1] * f2 - f2rdf[bin] / nbeads) rdfQ[bin, 1] -= frdf[bin] / 2.0 # Creating RDF from N(r) const, dr = cellVolume / (4 * np.pi / 3.0), rdf[1, 0] - rdf[0, 0] for bin in range(nbins): rdf[bin, 1] = const * rdf[bin, 1] / ((rdf[bin, 0] + 0.5 * dr)**3 - (rdf[bin, 0] - 0.5 * dr)**3) rdfQ[bin, 1] = const * rdfQ[bin, 1] / ((rdfQ[bin, 0] + 0.5 * dr)**3 - (rdfQ[bin, 0] - 0.5 * dr)**3) for bin in range(nbins): rdf[bin, 0] = unit_to_user('length', unit, rdf[bin, 0]) rdfQ[bin, 0] = unit_to_user('length', unit, rdfQ[bin, 0]) # Writing the results into files np.savetxt(fn_out_rdf, rdf) np.savetxt(fn_out_rdf_q, rdfQ)
def read_xyz(filedesc): """Reads an XYZ-style file with i-PI style comments and returns data in raw format for further units transformation and other post processing. Args: filedesc: An open readable file object from a xyz formatted file with i-PI header comments. Returns: i-Pi comment line, cell array, data (positions, forces, etc.), atoms names and masses """ try: natoms = int(filedesc.next()) except (StopIteration, ValueError): raise EOFError comment = filedesc.next() # Extracting cell cell = [key.search(comment) for key in cell_re] usegenh = False if cell[0] is not None: # abcABC a, b, c = [float(x) for x in cell[0].group(1).split()[:3]] alpha, beta, gamma = [float(x) * deg2rad for x in cell[0].group(1).split()[3:6]] h = mt.abc2h(a, b, c, alpha, beta, gamma) elif cell[1] is not None: # H h = np.array(cell[1].group(1).split()[:9], float) h.resize((3, 3)) elif cell[2] is not None: # GENH genh = np.array(cell[2].group(1).split()[:9], float) genh.resize((3, 3)) invgenh = np.linalg.inv(genh) # convert back & forth from abcABC representation to get an upper triangular h h = mt.abc2h(*mt.genh2abc(genh)) usegenh = True else: # defaults to unit box h = np.array([[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, -1.0]]) cell = h qatoms = np.zeros(3 * natoms) names = np.zeros(natoms, dtype='|S4') masses = np.zeros(natoms) # Extracting a time-frame information atom_counter = 0 for iat, line in enumerate(filedesc): body = line.split() names[iat], masses[iat] = body[0], Elements.mass(body[0]) x, y, z = float(body[1]), float(body[2]), float(body[3]) if usegenh: # must convert from the input cell parameters to the internal convention u = np.array([x, y, z]) us = np.dot(u, invgenh) u = np.dot(h, us) x, y, z = u qatoms[3 * iat], qatoms[3 * iat + 1], qatoms[3 * iat + 2] = x, y, z atom_counter += 1 if atom_counter == natoms: break if natoms != len(names): raise ValueError("The number of atom records does not match the header of the xyz file.") return comment, cell, qatoms, names, masses