def Return_U_from_Aniso_Expand(inputs, new_crystal_matrix, coordinate_file, Parameter_file, Program, output_file_name, molecules_in_coord): # Converting the crystal matrix parameter to lattice parameters new_lattice_parameters = Ex.crystal_matrix_to_lattice_parameters( Ex.array_to_triangle_crystal_matrix(new_crystal_matrix)) # Determining the file ending of the coordinate file file_ending = psf.assign_coordinate_file_ending(Program) # Determine the input coordinate files lattice parameters old_lattice_parameters = psf.Lattice_parameters(Program, coordinate_file) # Expand input coordinate file using the new lattice parameters Ex.Expand_Structure(inputs, coordinate_file, 'lattice_parameters', output_file_name, dlattice_parameters=new_lattice_parameters[:6] - old_lattice_parameters) # Computing the potential energy of the new expanded structure U = psf.Potential_energy( output_file_name + file_ending, Program, Parameter_file=Parameter_file) / molecules_in_coord return U
def anisotropic_gradient_settings_1D(inputs, dC_dLambda): # Determining the file ending based on the program file_ending = psf.assign_coordinate_file_ending(inputs.program) # Setting the energy cutoff cutoff = program_cutoff(inputs.program) # Lambda step sizes to take steps = np.array([5e-02, 1e-01, 5e-01, 1e01, 5e01, 1e02, 5e02, 1e03, 5e03]) # Number of total step sizes n_steps = len(steps) # Potential energy of input file and a place to store the expanded structures potential energy U_0 = psf.Potential_energy(inputs.coordinate_file, inputs.program, Parameter_file=inputs.tinker_parameter_file) / \ inputs.number_of_molecules U = np.zeros(n_steps) for i in range(n_steps): dlattice_matrix = Ex.array_to_triangle_crystal_matrix(steps[i] * dC_dLambda) Ex.Expand_Structure(inputs, inputs.coordinate_file, 'crystal_matrix', inputs.output, dcrystal_matrix=dlattice_matrix) U[i] = psf.Potential_energy(inputs.output + file_ending, inputs.program, Parameter_file=inputs.tinker_parameter_file ) / inputs.number_of_molecules subprocess.call(['rm', inputs.output + file_ending]) if (U[i] - U_0) > cutoff: LocGrd_dLambda = steps[i] end_plot = i break # Plotting the results plt.plot(np.log10(steps[:end_plot + 1]), U[:end_plot + 1] - U_0, linestyle='--', marker='o') plt.xlabel('$\log({d\lambda})$', fontsize=22) plt.ylabel('$\Delta U$ [kcal/mol]', fontsize=22) plt.ylim((0., 2 * cutoff)) plt.axhline(y=cutoff, c='grey', linestyle='--') plt.tight_layout() plt.savefig(inputs.output + '_LocGrd_Lambda_FracStep.pdf') plt.close() print('dLambda used: ', LocGrd_dLambda) # returning the value of dV return LocGrd_dLambda
def Output_QE_Coordinate_File(Coordinate_file, Parameter_file, coordinates, lattice_parameters, Output): coordlines = open(Coordinate_file, 'r').readlines() struct = open(Output + '.pw', 'w') latt = open(Output + '.pwbv', 'w') print(coordlines) numatoms = np.shape(coordinates)[0] print(numatoms) for x in range(0, 3): struct.write(coordlines[x]) struct.write('ATOMIC_POSITIONS angstrom' + '\n') for x in range(4, 4 + numatoms): atomtype = coordlines[x].split()[0] struct.write(atomtype + ' ' + str(coordinates[x - 4, 0]) + ' ' + str(coordinates[x - 4, 1]) + ' ' + str(coordinates[x - 4, 2]) + '\n') latt.write('CELL_PARAMETERS angstrom' + '\n') lattice_parameters = np.transpose( Ex.Lattice_parameters_to_Crystal_matrix(lattice_parameters)) for x in range(0, 3): latt.write( str(lattice_parameters[x, 0]) + ' ' + str(lattice_parameters[x, 1]) + ' ' + str(lattice_parameters[x, 2]) + '\n')
def getEnt(EnergyState):#finds entanglement entropy for a given state of H(phi) Exstate = Ex.Expand(EnergyState,S,N,Jcurr) RhoA = VN.bipartDM(Exstate,Na,Nb) eigsA = np.linalg.eigvals(RhoA) return(np.mean(VN.VNEnt(eigsA)).real)
def QE_Lattice_Parameters(Coordinate_file): lfile = open(Coordinate_file + 'bv') lines = lfile.readlines() matrix = np.zeros((3, 3)) for x in range(0, 3): vect = lines[x + 1] matrix[x, 0] = float(vect.split()[0]) matrix[x, 1] = float(vect.split()[1]) matrix[x, 2] = float(vect.split()[2]) lattice_parameters = Ex.crystal_matrix_to_lattice_parameters( np.transpose(matrix)) return lattice_parameters
def program_wavenumbers(coordinate_file: str, tinker_parameter_file: str, output: str, original_coordinate_file: str, program: str, method: str): r""" Returns the list of wavenumbers of a given coordinate file Paramaeters ----------- coordinate_file: str coorindate file specific to the program tinker_parameter_file: str parameter file for Tinker output: str name for output files original_coordinate_file: str used for the Test program program: str program to use to compute the potential for [Tinker, Test, CP2K, QE] method: str QHA method being used Returns ------- wavenumber: Wavenumbers [cm$^{-1}$] of the coordinate file """ if program == 'Tinker': wavenumbers = Tinker_Wavenumber(coordinate_file, tinker_parameter_file) elif program == 'CP2K': wavenumbers = CP2K_Wavenumber(coordinate_file, tinker_parameter_file, Output=output) elif program == 'QE': wavenumbers = QE_Wavenumber(coordinate_file, tinker_parameter_file, Output=output) elif program == 'Test': if method == 'GaQ': wavenumbers = Test_Wavenumber( coordinate_file, Ex.Lattice_parameters_to_Crystal_matrix( np.load(original_coordinate_file))) else: wavenumbers = Test_Wavenumber(coordinate_file, True) return wavenumbers
def Return_QE_Coordinates(Coordinate_file, lattice_parameters): with open(Coordinate_file) as f: coordlines = f.readlines() coords = np.zeros((len(coordlines) - 4, 3)) for x in range(0, len(coordlines) - 4): coords[x, :] = coordlines[x + 4].split()[1:4] # Opening xyz coordinate file to expand for x in range(0, len(coordlines)): if '(crystal)' in coordlines[x].split(): crystal = True else: crystal = False if crystal == True: for x in range(0, len(coordlines) - 3): coords[x, :] = Ex.crystal_coord_to_cartesian( coords[x, :], lattice_parameters) return coords
def constrained_minimization(inputs, Coordinate_file, Program, Parameter_file=''): # Determining the file ending of the coordinate file file_ending = psf.assign_coordinate_file_ending(Program) # Determining the lattice parameters and volume of the input coordinate file lp_0 = psf.Lattice_parameters(Program, Coordinate_file) V0 = Pr.Volume(lattice_parameters=lp_0) cm_0 = Ex.triangle_crystal_matrix_to_array( Ex.Lattice_parameters_to_Crystal_matrix(lp_0)) bnds = np.matrix([[cm_0[0] - cm_0[0] * 0.2, cm_0[0] + cm_0[0] * 0.2], [cm_0[1] - cm_0[1] * 0.2, cm_0[1] + cm_0[1] * 0.2], [cm_0[2] - cm_0[2] * 0.2, cm_0[2] + cm_0[2] * 0.2], [cm_0[3] - cm_0[0] * 0.2, cm_0[3] + cm_0[0] * 0.2], [cm_0[4] - cm_0[0] * 0.2, cm_0[4] + cm_0[0] * 0.2], [cm_0[5] - cm_0[0] * 0.2, cm_0[5] + cm_0[0] * 0.2]]) output = scipy.optimize.minimize( Return_U_from_Aniso_Expand, cm_0, (inputs, Coordinate_file, Parameter_file, Program, 'constV_minimize', 4), method='SLSQP', constraints=({ 'type': 'eq', 'fun': lambda cm: np.linalg.det(Ex.array_to_triangle_crystal_matrix(cm)) - V0 }), bounds=bnds, tol=1e-08, options={ 'ftol': float(1e-6), 'disp': True, 'eps': float(1e-4) }) dlattice_parameters = Ex.crystal_matrix_to_lattice_parameters( Ex.array_to_triangle_crystal_matrix(output.x)) - lp_0 Ex.Expand_Structure(inputs, Coordinate_file, 'lattice_parameters', 'constV_minimize', dlattice_parameters=dlattice_parameters) subprocess.call(['mv', 'constV_minimize' + file_ending, Coordinate_file])
def Get_Aniso_Gruneisen_Wavenumbers(gruneisen, wavenumber_ref, crystal_matrix_ref, strained_coordinate_file, program): r""" Computes the isotropic wavenumbers using the Gruneisen parmaeters due to an isotropic volume change to the crystal lattice. Parameters ---------- gruneisen: List[float] Anisotropic Gruneisen parameters. wavenumbers_ref: List[float] Wavenumbers [cm$^{-1}$] of the lattice minimum structure. crystal_matrix_ref: List[float] Lattice tensor [$\AA$] of the lattice minimum structure. strained_coordinate_file: float Coordinate file of the anisotropically expanded crystal that the wavenumbers need to be computed for. program: str Program being used. Returns ------- wavenumbers: List[float] Wavenumbers [cm$^{-1}$] of the crystal structure in the strained crystal. """ # Determining the strain placed on the expanded crystal relative to the reference matrix new_crystal_matrix = Ex.Lattice_parameters_to_Crystal_matrix( psf.Lattice_parameters(program, strained_coordinate_file)) applied_strain = Pr.RotationFree_StrainArray_from_CrystalMatrix( crystal_matrix_ref, new_crystal_matrix) # Setting a blank array for new wavenumbers wavenumbers = np.zeros(len(wavenumber_ref)) # Computing the change to each wavenumber due to the current strain for i in np.arange(3, len(wavenumbers), 1): wavenumbers[i] = wavenumber_ref[i] * np.exp( -1. * np.sum(np.dot(applied_strain, gruneisen[i]))) return wavenumbers
def anisotropic_gradient_settings(inputs, data, input_file): # Determining the file ending based on the program file_ending = psf.assign_coordinate_file_ending(inputs.program) # Setting the energy cutoff cutoff = program_cutoff(inputs.program) # Fractional step sizes to take steps = np.array([ 5e-05, 1e-04, 5e-04, 1e-03, 5e-03, 1e-02, 5e-02, 1e-01, 5e-01, 1., 5., 1e01, 5e01, 1e02, 5e02, 1e03, 5e03, 1e04, 5e04 ]) # Number of total step sizes n_steps = len(steps) # Potential energy of input file and a place to store the expanded structures potential energy U_0 = psf.Potential_energy(inputs.coordinate_file, inputs.program, Parameter_file=inputs.tinker_parameter_file) / \ inputs.number_of_molecules U = np.zeros((6, n_steps)) # Determining the tensor parameters of the input file crystal_matrix = Ex.Lattice_parameters_to_Crystal_matrix( psf.Lattice_parameters(inputs.program, inputs.coordinate_file)) crystal_matrix_array = Ex.triangle_crystal_matrix_to_array(crystal_matrix) LocGrd_CMatrix_FracStep = np.zeros(6) LocGrd_CMatrix_Step = np.zeros(6) for j in range(6): for i in range(n_steps): dlattice_matrix_array = np.zeros(6) dlattice_matrix_array[j] = np.absolute(crystal_matrix_array[j] * steps[i]) if np.absolute(crystal_matrix_array[j]) < 1e-4: dlattice_matrix_array[j] = steps[i] dlattice_matrix = Ex.array_to_triangle_crystal_matrix( dlattice_matrix_array) Ex.Expand_Structure(inputs, inputs.coordinate_file, 'crystal_matrix', inputs.output, dcrystal_matrix=dlattice_matrix) U[j, i] = psf.Potential_energy( inputs.output + file_ending, inputs.program, Parameter_file=inputs.tinker_parameter_file ) / inputs.number_of_molecules subprocess.call(['rm', inputs.output + file_ending]) if (U[j, i] - U_0) > cutoff: LocGrd_CMatrix_FracStep[j] = 10**np.interp( cutoff, U[j, i - 1:i + 1] - U_0, np.log10(steps[i - 1:i + 1])) LocGrd_CMatrix_Step[j] = np.absolute( crystal_matrix_array[j] * LocGrd_CMatrix_FracStep[j]) if np.absolute(crystal_matrix_array[j]) < 1e-4: LocGrd_CMatrix_Step[j] = LocGrd_CMatrix_FracStep[j] break plt.scatter(np.log10(LocGrd_CMatrix_FracStep[j]), cutoff, marker='x', color='r') plt.plot(np.log10(steps[:i + 1]), U[j, :i + 1] - U_0, linestyle='--', marker='o', label='C' + str(j + 1)) # Plotting the results plt.xlabel('$\log({dC/C_{0}})$', fontsize=22) plt.ylabel('$\Delta U$ [kcal/mol]', fontsize=22) plt.ylim((0., 2 * cutoff)) plt.axhline(y=cutoff, c='grey', linestyle='--') plt.legend(loc='upper right', ncol=2, fontsize=18) plt.tight_layout() plt.savefig(inputs.output + '_LocGrd_CMatrix_FracStep.pdf') plt.close() # Printing step size print("After analysis, LocGrd_CMatrix_FracStep = ", LocGrd_CMatrix_FracStep) data['gradient']['matrix_fractions'] = LocGrd_CMatrix_FracStep.tolist() with open(input_file, 'w') as yaml_file: yaml.dump(data, yaml_file, default_flow_style=False) # returning the value of dV return LocGrd_CMatrix_Step
def pressure_setup(Temperature=[0.0, 25.0, 50.0, 75.0, 100.0], Pressure=1., Method='HA', Program='Test', Output='out', Coordinate_file='molecule.xyz', Parameter_file='keyfile.key', molecules_in_coord=1, properties_to_save=['G', 'T'], NumAnalysis_method='RK4', NumAnalysis_step=25.0, LocGrd_Vol_FracStep='', LocGrd_CMatrix_FracStep='', StepWise_Vol_StepFrac=1.5e-3, StepWise_Vol_LowerFrac=0.97, StepWise_Vol_UpperFrac=1.16, Statistical_mechanics='Classical', Gruneisen_Vol_FracStep=1.5e-3, Gruneisen_Lat_FracStep=1.0e-3, Wavenum_Tol=-1., Gradient_MaxTemp=300.0, Aniso_LocGrad_Type='6D', min_RMS_gradient=0.01, eq_of_state='Murnaghan', gru_from_0T_0P=True, cp2kroot='BNZ_NMA_p2'): if Method == 'HA': print( "Pressure vs. Temperature methods have not been implimented for the Harmonic Approximation" ) sys.exit() elif (Method == 'GaQ') or (Method == 'GaQg'): print( "Pressure vs. Temperature methods have not been implimented for anisotropic expansion" ) sys.exit() file_ending = psf.assign_coordinate_file_ending(Program) # Making an array of volume fractions V_frac = np.arange(StepWise_Vol_LowerFrac, 1.0, StepWise_Vol_StepFrac) V_frac = np.arange(StepWise_Vol_LowerFrac, StepWise_Vol_UpperFrac, StepWise_Vol_StepFrac) # Volume of lattice minimum strucutre V0 = Pr.Volume(Program=Program, Coordinate_file=Coordinate_file) # Making an array to store the potential energy and volume of each structure U = np.zeros(len(V_frac)) V = np.zeros(len(V_frac)) for i in range(len(V_frac)): # Expanding the structures and saving the required data Ex.Call_Expansion(Method, 'expand', Program, Coordinate_file, molecules_in_coord, min_RMS_gradient, volume_fraction_change=V_frac[i], Output='temporary', Parameter_file=Parameter_file) U[i] = psf.Potential_energy('temporary' + file_ending, Program, Parameter_file=Parameter_file) V[i] = Pr.Volume(Program=Program, Coordinate_file='temporary' + file_ending) subprocess.call(['rm', 'temporary' + file_ending]) V0 = Pr.Volume(Program=Program, Coordinate_file=Coordinate_file) E0 = psf.Potential_energy(Coordinate_file, Program, Parameter_file=Parameter_file) if eq_of_state != 'None': [B, dB], _ = scipy.optimize.curve_fit( lambda V, B, dB: eos.EV_EOS(V, V0, B, dB, E0, eq_of_state), V, U, p0=[2., 2.]) np.save(Output + '_EOS', [V0, B, dB, E0]) plt.plot(V, (eos.EV_EOS(V, V0, B, dB, E0, eq_of_state) - U) / molecules_in_coord) plt.xlabel('Volume [Ang.$^{3}$]', fontsize=18) plt.ylabel('$\delta(U_{EOS})$ [kcal/mol]', fontsize=18) plt.tight_layout() plt.savefig(Output + '_EOS_dU.pdf') plt.close() plt.plot( V, eos.EV_EOS(V, V0, B, dB, E0, eq_of_state) / molecules_in_coord) plt.scatter(V, U / molecules_in_coord) plt.xlabel('Volume [Ang.$^{3}$]', fontsize=18) plt.ylabel('$U$ [kcal/mol]', fontsize=18) plt.tight_layout() plt.savefig(Output + '_EOS_U.pdf') plt.close() if gru_from_0T_0P == True: EOS_TvP_Gru_0T_0P(Method, Temperature, Pressure, Program, Output, Coordinate_file, Parameter_file, molecules_in_coord, properties_to_save, Statistical_mechanics, Gruneisen_Vol_FracStep, Wavenum_Tol, min_RMS_gradient, eq_of_state, cp2kroot, V0, B, dB, E0) sys.exit() else: lattice_parameter_name = Coordinate_file.split('.')[0] for i in range(len(Pressure)): v_p = scipy.optimize.minimize(pressure_minimization_at_0T, V0, args=(Pressure[i], V0, B, dB, eq_of_state), method='Nelder-Mead', tol=1.e-15).x print(Pressure[i], v_p) V = np.arange(100, 5000, 10) plt.plot( V, eos.EV_EOS(V, V0, B, dB, E0, eq_of_state) + Pressure[i] * V) plt.scatter( v_p, eos.EV_EOS(v_p, V0, B, dB, E0, eq_of_state) + Pressure[i] * v_p) plt.show() else: print("WARNING: Option of None for EOS is not set up yet, exiting.") sys.exit()
def Setup_Anisotropic_Gruneisen(inputs): r""" Computes the anisotropic Gruneisen parameters of the lattice minimum structure Parameters ---------- inputs: Class Contains all user defined values and filled in with default program values Returns ------- gruneisen: List[float] Anisotropic Gruneisen parameters. wavenumbers_ref: List[float] Wavenumbers [cm$^{-1}$] of the lattice minimum structure. """ # Determining the file ending for the program used file_ending = psf.assign_coordinate_file_ending(inputs.program) # Determining if the anisotropic Gruneisen parameters have already been calculated # Typically, this take a long time. It may be advantageous to parallelize this in the future. re_run = False if os.path.isfile('GRU_wvn.npy') and os.path.isfile('GRU_eigen.npy'): # Loading in previously computed Gruneisen parameters wavenumbers = np.load('GRU_wvn.npy') eigenvectors = np.load('GRU_eigen.npy') re_run = True else: # Computing the reference wavenumbers and eigenvectors (the lattice minimum structure fed in) wavenumbers_ref, eigenvectors_ref = psf.Wavenumber_and_Vectors( inputs.program, inputs.coordinate_file, inputs.tinker_parameter_file) # Setting the number of vibrational modes number_of_modes = int(len(wavenumbers_ref)) number_of_atoms = psf.atoms_count(inputs.program, inputs.coordinate_file) # Setting a place to store all the wavenumbers and eigenvalues for the Gruenisen parameters wavenumbers = np.zeros((7, number_of_modes)) eigenvectors = np.zeros((7, number_of_modes, 3 * number_of_atoms)) wavenumbers[0] = wavenumbers_ref eigenvectors[0] = eigenvectors_ref # Out putting information for user output NO.start_anisoGru() # Saving that data computed thusfar in case the system crashes or times out np.save('GRU_eigen', eigenvectors) np.save('GRU_wvn', wavenumbers) # Cycling through the six principle six principal strains for i in range(6): if re_run and (wavenumbers[i + 1, 3] != 0.): # Skipping a given strain if the wavenumbers have previously been computed and loaded in pass else: # Expanding the lattice minimum structure in the direction of the i-th principal strain applied_strain = np.zeros(6) applied_strain[i] = inputs.gruneisen_matrix_strain_stepsize Ex.Expand_Structure( inputs, inputs.coordinate_file, 'strain', 'temp', strain=Ex.strain_matrix(applied_strain), crystal_matrix=Ex.Lattice_parameters_to_Crystal_matrix( psf.Lattice_parameters(inputs.program, inputs.coordinate_file))) # Computing the strained wavenumbers and eigenvectors wavenumbers_unorganized, eigenvectors_unorganized = psf.Wavenumber_and_Vectors( inputs.program, 'temp' + file_ending, inputs.tinker_parameter_file) # Determining how the strained eigenvectors match up with the reference structure z, weight = matching_eigenvectors_of_modes( number_of_modes, eigenvectors[0], eigenvectors_unorganized) NO.GRU_weight( weight ) # Writing out the precision of matching the modes with one another # Re-organizing the expanded wavenumbers wavenumbers[i + 1], eigenvectors[i + 1] = reorder_modes( z, wavenumbers_unorganized, eigenvectors_unorganized) # Saving the eigenvectors and wavenumbers np.save('GRU_eigen', eigenvectors) np.save('GRU_wvn', wavenumbers) # Removing the strained coordinate file subprocess.call(['rm', 'temp' + file_ending]) # Calculating the Gruneisen parameters due to the six principal strains gruneisen = np.zeros((number_of_modes, 6)) for i in range(6): # Calculating the Gruneisen parameters gruneisen[3:, i] = -(np.log(wavenumbers[i + 1, 3:]) - np.log(wavenumbers[0, 3:])) \ / inputs.gruneisen_matrix_strain_stepsize return gruneisen, wavenumbers[0]
def Setup_Isotropic_Gruneisen(inputs): r""" Computes the isotropic Gruneisen parameters of the lattice minimum structure Parameters ---------- inputs: Class Contains all user defined values and filled in with default program values Returns ------- gruneisen: List[float] Isotropic Gruneisen parameters. wavenumbers_ref: List[float] Wavenumbers [cm$^{-1}$] of the lattice minimum structure. volume_ref: float Volume [$\AA^{3}$] of the lattice minimum structure. """ # Change in lattice parameters for expanded structure dLattice_Parameters = Ex.Isotropic_Change_Lattice_Parameters( (1 + inputs.gruneisen_volume_fraction_stepsize), inputs.program, inputs.coordinate_file) # Determining wavenumbers of lattice strucutre and expanded structure lattice_parameters = psf.Lattice_parameters(inputs.program, inputs.coordinate_file) # Expanding structure Ex.Expand_Structure(inputs, inputs.coordinate_file, 'lattice_parameters', 'temp', dlattice_parameters=dLattice_Parameters) # File ending of the coordinate file file_ending = psf.assign_coordinate_file_ending(inputs.program) # Computing the reference wavenumbers and eigenvectors wavenumbers_ref, eigenvectors_ref = psf.Wavenumber_and_Vectors( inputs.program, inputs.coordinate_file, inputs.tinker_parameter_file) number_of_modes = len(wavenumbers_ref) # Number of vibrational modes # Computing the strained wavenumbers and eigenvectors wavenumbers_unorganized, eigenvectors_unorganized = psf.Wavenumber_and_Vectors( inputs.program, 'temp' + file_ending, inputs.tinker_parameter_file) # Determining how the strained eigenvectors match up with the reference structure z, weight = matching_eigenvectors_of_modes(number_of_modes, eigenvectors_ref, eigenvectors_unorganized) # Outputing information for user output NO.start_isoGru() NO.GRU_weight(weight) # Re-organizing the expanded wavenumbers wavenumbers_organized, eigenvectors_organized = reorder_modes( z, wavenumbers_unorganized, eigenvectors_unorganized) # Calculating the volume of the lattice minimum and expanded structure volume_ref = Pr.Volume(lattice_parameters=lattice_parameters) volume_expand = volume_ref + inputs.gruneisen_volume_fraction_stepsize * volume_ref # Computing the Gruneisen parameters gruneisen = np.zeros(len(wavenumbers_ref)) gruneisen[3:] = -(np.log(wavenumbers_ref[3:]) - np.log(wavenumbers_organized[3:])) / \ (np.log(volume_ref) - np.log(volume_expand)) for x in range(0, len(gruneisen)): if wavenumbers_ref[x] == 0: gruneisen[x] = 0.0 # Removing extra files created in process subprocess.call(['rm', 'temp' + file_ending]) return gruneisen, wavenumbers_ref, volume_ref
def temperature_lattice_dynamics(inputs, data, input_file='input.yaml'): # Geometry and lattice optimizing the input structure if inputs.tinker_xtalmin and (inputs.program == 'Tinker'): psf.tinker_xtalmin(inputs) inputs.tinker_xtalmin = False # Running the harmonic approximation if inputs.method == 'HA': print("Performing Harmonic Approximation") # Determining if the wavenumbers have already been calculated if os.path.isfile(inputs.output + '_' + inputs.method + '_WVN.npy'): # Loading in te wavenumbers wavenumbers = np.load(inputs.output + '_' + inputs.method + '_WVN.npy') print(" Importing wavenumbers from:" + inputs.output + '_' + inputs.method + '_WVN.npy') else: # Computing the wavenumbers and saving them print(" Computing wavenumbers of coordinate file") wavenumbers = Wvn.Call_Wavenumbers(inputs, Coordinate_file=inputs.coordinate_file, Parameter_file=inputs.tinker_parameter_file) np.save(inputs.output + '_' + inputs.method + '_WVN', wavenumbers) # Making sure all wavenumbers are within the user specified tolerance if all(wavenumbers[:3] < inputs.wavenumber_tolerance) and \ all(wavenumbers[:3] > -1. * inputs.wavenumber_tolerance): print(" All wavenumbers are greater than tolerance of: " + str(inputs.wavenumber_tolerance) + " cm^-1") properties = Pr.Properties_with_Temperature_and_Pressure(inputs, inputs.coordinate_file, wavenumbers) print(" All properties have been saved in " + inputs.output + "_raw.npy") np.save(inputs.output + '_raw', properties) print(" Saving user specified properties in indipendent files:") Pr.Save_Properties_2D(inputs, properties) exit() else: if not os.path.isdir('Cords'): print("Creating directory 'Cords/' to store structures along Gibbs free energy path") subprocess.call(['mkdir', 'Cords']) # Expanding the crystal with the zero point energy if (inputs.statistical_mechanics == 'Quantum') and (inputs.coordinate_file != 'ezp_minimum' + psf.assign_coordinate_file_ending(inputs.program)): if any(inputs.gradient_matrix_fractions != 0.): crystal_matrix_array = Ex.triangle_crystal_matrix_to_array(Ex.Lattice_parameters_to_Crystal_matrix( psf.Lattice_parameters(inputs.program, inputs.coordinate_file))) LocGrd_dC = np.absolute(inputs.gradient_matrix_fractions * crystal_matrix_array) for i in range(len(LocGrd_dC)): if LocGrd_dC[i] == 0.: LocGrd_dC[i] = inputs.gradient_matrix_fractions[i] else: LocGrd_dC = Ss.anisotropic_gradient_settings(inputs, data, input_file) TNA.anisotropic_gradient_expansion_ezp(inputs, LocGrd_dC) inputs.coordinate_file = 'ezp_minimum' + psf.assign_coordinate_file_ending(inputs.program) # Running through QHA if (inputs.method == 'SiQ') or (inputs.method == 'SiQg'): # Stepwise Isotropic QHA print("Performing Stepwise Isotropic Quasi-Harmonic Approximation") properties = TNA.stepwise_expansion(inputs) print(" Saving user specified properties in indipendent files:") Pr.Save_Properties_1D(inputs, properties) elif (inputs.method == 'GiQ') or (inputs.method == 'GiQg'): if inputs.gradient_vol_fraction == (0. or None): LocGrd_dV = Ss.isotropic_gradient_settings(inputs) else: V_0 = Pr.Volume(Program=inputs.program, Coordinate_file=inputs.coordinate_file) LocGrd_dV = inputs.gradient_vol_fraction * V_0 # Gradient Isotropic QHA print("Performing Gradient Isotropic Quasi-Harmonic Approximation") properties = TNA.Isotropic_Gradient_Expansion(inputs, LocGrd_dV) print(" Saving user specified properties in indipendent files:") Pr.Save_Properties_1D(inputs, properties) elif (inputs.method == 'GaQ') or (inputs.method == 'GaQg'): if inputs.statistical_mechanics == 'Classical': if any(inputs.gradient_matrix_fractions != 0.): crystal_matrix_array = Ex.triangle_crystal_matrix_to_array(Ex.Lattice_parameters_to_Crystal_matrix( psf.Lattice_parameters(inputs.program, inputs.coordinate_file))) LocGrd_dC = np.absolute(inputs.gradient_matrix_fractions * crystal_matrix_array) for i in range(len(LocGrd_dC)): if LocGrd_dC[i] == 0.: LocGrd_dC[i] = inputs.gradient_matrix_fractions[i] else: LocGrd_dC = Ss.anisotropic_gradient_settings(inputs, data, input_file) if inputs.anisotropic_type != '1D': print("Performing Gradient Anisotropic Quasi-Harmonic Approximation") properties = TNA.Anisotropic_Gradient_Expansion(inputs, LocGrd_dC) print(" Saving user specified properties in independent files:") Pr.Save_Properties_1D(inputs, properties) else: print("Performing 1D-Gradient Anisotropic Quasi-Harmonic Approximation") properties = TNA.Anisotropic_Gradient_Expansion_1D(inputs, LocGrd_dC) print(" Saving user specified properties in independent files:") Pr.Save_Properties_1D(inputs, properties) elif inputs.method == 'SaQply': print("Performing Quasi-Anisotropic Quasi-Harmonic Approximation") properties = TNA.stepwise_expansion(inputs) print(" Saving user specified properties in independent files:") Pr.Save_Properties_1D(inputs, properties) print("Lattice dynamic calculation is complete!")
def isotropic_gradient_settings(inputs): #Coordinate_file, Program, Parameter_file, molecules_in_coord, min_RMS_gradient, Output, # Pressure): # Determining the file ending based on the program file_ending = psf.assign_coordinate_file_ending(inputs.program) # Setting the energy cutoff cutoff = program_cutoff(inputs.program) # Fractional step sizes to take steps = np.array( [5e-05, 1e-04, 5e-04, 1e-03, 5e-03, 1e-02, 5e-02, 1e-01, 5e-01]) # Number of total step sizes n_steps = len(steps) # Potential energy of input file and a place to store the expanded structures potential energy U_0 = (psf.Potential_energy(inputs.coordinate_file, inputs.program, Parameter_file=inputs.tinker_parameter_file) \ + Pr.PV_energy(inputs.pressure, Pr.Volume(Program=inputs.program, Coordinate_file=inputs.coordinate_file))) / \ inputs.number_of_molecules U = np.zeros((n_steps)) for i in range(n_steps): # Setting how much the lattice parameters must be changed dlattice_parameters = Ex.Isotropic_Change_Lattice_Parameters( 1. + steps[i], inputs.program, inputs.coordinate_file) # Expanding the strucutre Ex.Expand_Structure(inputs, inputs.coordinate_file, 'lattice_parameters', inputs.output, dlattice_parameters=dlattice_parameters) # Computing the potential energy U[i] = (psf.Potential_energy(inputs.output + file_ending, inputs.program, Parameter_file=inputs.tinker_parameter_file) \ + Pr.PV_energy(inputs.pressure, Pr.Volume(Program=inputs.program, Coordinate_file=inputs.output + file_ending))) / \ inputs.number_of_molecules subprocess.call(['rm', inputs.output + file_ending]) if (U[i] - U_0) > cutoff: # Ending the run if we've exceeded the energy cut-off LocGrd_Vol_FracStep = steps[i] steps = steps[:i + 1] U = U[:i + 1] break # Plotting the results plt.plot(np.log10(steps), U - U_0, linestyle='--', marker='o') plt.xlabel('$\log({dV/V_{0}})$', fontsize=22) plt.ylabel('$\Delta U$ [kcal/mol]', fontsize=22) plt.ylim((0., 2 * cutoff)) plt.axhline(y=cutoff, c='grey', linestyle='--') plt.tight_layout() plt.savefig(inputs.output + '_LocGrd_Vol_FracStep.pdf') plt.close() # Printing step size print("After analysis, LocGrd_Vol_FracStep = ", LocGrd_Vol_FracStep) # initial volume V_0 = Pr.Volume(Program=inputs.program, Coordinate_file=inputs.coordinate_file) # returning the value of dV return LocGrd_Vol_FracStep * V_0
def getEnt(EnergyState): Exstate = Ex.Expand(EnergyState, S, N, Jcurr) RhoA = VN.bipartDM(Exstate, Na, Nb) eigsA = np.linalg.eigvals(RhoA) return (VN.VNEnt(eigsA))
def Test_Wavenumber(Coordinate_file, ref_crystal_matrix, function='Test3', Gru=False): """ This function takes a set of lattice parameters in a .npy file and returns a set of wavenumbers Random functions can be input here to run different tests and implimented new methods efficiently **Required Inputs Coordinate_file = File containing lattice parameters and atom coordinates """ lattice_parameters = np.load(Coordinate_file) if function == 'Test1': wavenumbers = np.array([0., 0., 0., 52., 380., 1570., 3002.]) for i in np.arange(3, len(wavenumbers[3:]) + 3): # probably should be 3? wavenumbers[i] = wavenumbers[i] * (1 / 3.) * ( ((lattice_parameters[0] - 16) / 6)**2 + ((lattice_parameters[1] - 12) / 5)**2 + ((lattice_parameters[2] - 23) / 11)**2) elif function == 'Test2': wavenumbers = np.arange(1, 200) wavenumbers = wavenumbers**( 5.0 / 3.0) # get something in the right range = 400^(4/3) = 2941 wavenumbers[0:3] = [0, 0, 0] # zero translation [refx, refy, refz] = [ lattice_parameters[0] / 10., lattice_parameters[1] / 12., lattice_parameters[2] / 15. ] # [refx,refy,refz] = [lattice_parameters[0]/5,lattice_parameters[1]/6,lattice_parameters[2]/8] for i in range(3, len(wavenumbers[3:]) + 3): wavenumbers[i] = wavenumbers[i] * ( 1.0 / 15.0) * (2 * refx**4.8 + 10 * refy**4.2 + 4 * np.sin(2 * np.pi * refx) + 3 * refz**4.8) elif function == 'Test3': # Determining if the wavenumbers at the lattice minimum and the way they change are present if os.path.isfile('wvn0_test.npy') and os.path.isfile( 'wvnChange_test.npy'): if np.all(ref_crystal_matrix == True): strain = np.zeros(6) strain[:3] = (Pr.Volume(Program='Test', Coordinate_file=Coordinate_file) / 570.88883075)**(1. / 3.) - 1. elif np.all(ref_crystal_matrix == False): strain = np.zeros(6) else: new_crystal_matrix = Ex.Lattice_parameters_to_Crystal_matrix( Lattice_parameters('Test', Coordinate_file)) strain = Pr.RotationFree_StrainArray_from_CrystalMatrix( ref_crystal_matrix, new_crystal_matrix) if Gru == True: for i in range(6): if strain[i] != max(strain): strain[i] = 0. wvn0 = np.load('wvn0_test.npy') change = np.load('wvnChange_test.npy') wavenumbers = np.zeros(len(wvn0)) for i in range(3, len(wavenumbers)): wavenumbers[i] = wvn0[i] * np.exp(-1. * np.sum( np.dot(strain, change[i]))) # + strain**2*(change[i]**2))) else: # Setting random wavenumbers wavenumbers = np.zeros(303) wavenumbers[3:241] = np.random.uniform(10., 2000., len(wavenumbers[3:241])) wavenumbers[241:] = np.random.uniform(2800., 3200., len(wavenumbers[241:])) wavenumbers = np.sort(wavenumbers) np.save('wvn0_test', wavenumbers) # Setting gruneisen parameters change = np.zeros((len(wavenumbers), 6)) for i in range(3, len(wavenumbers)): change[i, :3] = np.random.uniform( -2 * np.exp(-wavenumbers[i] / 200.) - 0.001, 7 * np.exp(-wavenumbers[i] / 500.) + 0.001) for j in range(3, 6): change[j] = np.random.uniform( -0.5 * np.absolute(lattice_parameters[j] - 90.) * np.exp(-wavenumbers[i] / 100.) - 0.01, 0.5 * np.absolute(lattice_parameters[j] - 90.) * np.exp(-wavenumbers[i] / 100.) + 0.01) np.save('wvnChange_test.npy', change) return wavenumbers
Htot = H.nlegHeisenberg.blockH(N, S, nlegs, c, Js=[1, 1], gamma=[0.0, 4.0], full='True') Hfull = sum(Htot).todense() eigs, vecs = np.linalg.eigh(Hfull) Eigvecs = np.asarray(vecs.T) print(list(eigs)) Envecs = [] for vc in Eigvecs: A = ex.Expand(vc, S, N, Jcurr) Envecs.append(A) statelist = t.Statelist(N, S) Statevecs = [] for state in statelist: vec = [] up = [1, 0] down = [0, 1] for i in state: if i == 0: vec.append(down) elif i == 1:
def DisVEntOld(N, Nlegs, Na, Nb, phiamt, Nstates=30, Jcurr=0, J1=1, J2=0, gamamt=50, modex2='open', modey2='open'): ''' N = 16 Nstates = 30 Jcurr = 0 phiamt = 100 gamamt = 50 Nlegs = 8 Na = 8 Nb = 8 J1=1 J2=1 ''' #print('here') S = 0.5 c = np.sqrt(2) phis = np.linspace(-np.pi * 0.5, np.pi * 0.5, phiamt) gammas = np.linspace(0.5, 8, gamamt) betas = [c, 0] NAsites = [0, 1, 2, 3, 4, 5, 6, 7] NBsites = [8, 9, 10, 11, 12, 13, 14, 15] SA = [] for gamma1 in gammas: Ent1 = [] start1 = time.time() for phi1 in phis: Hfull = H.nlegHeisenberg.blockH( N, S, Nlegs, c, Js=[J1, J2], gamma=[0, gamma1], phi=[0, phi1], modex1=modex2, modey1=modey2 ) #H.TwoDHeisenberg.H(N,Nlegs,S,J = [-1,0],delx=del1,dely=del2,delz=del3,beta=betas,gamma=[gammas[i],0],phi = [phis[j],0])#H.OneDHeisenberg.H(N,S,J1=-1,gamma=gammas[i],beta=c,phi=phis[j], mode='open')### Generate Hamiltonian Htot = sum(Hfull) #end1 = time.time() #print('Hamiltonian Generateion time:', end1-start1) #H1 = rows@[email protected]#Reduce to Sz=Jcurr Hamiltonian #start = time.time() Energy, EnergyStates = fs.filterHstates( Htot, Nstates) #filter states close to energy density #Entropies = [] for EnergyState in EnergyStates: Exstate = Ex.Expand( EnergyState, S, N, Jcurr ) #expand reduced-hamiltonian state to hilbert space of full hamiltonian #print(Exstate.tolist()) #RhoA = VN.reducedDM(EnergyState,NAsites,NBsites,N,S,Jcurr=Jcurr) RhoA = VN.bipartDM(Exstate, Na, Nb) #print(RhoA) eigsA = np.linalg.eigvals(RhoA) Ent1.append(VN.VNEnt(eigsA)) SA.append(np.mean(Ent1).real) end = time.time() print('Time for one phi:', end - start1) #print(np.mean(Ent1)) #SA.append(np.mean(Ent1)) str1 = pl.PurePath(modex2 + 'x_' + modey2 + 'y') path = pl.PurePath( os.getcwd() ).parent / 'Data' / str1 / 'Entropy' ###path and filepaths are objects which allow print(str(path)) filename = '%dx%d_%dphis_%dNstates_J1_%d__J2_%d__%dgammas_Na_%d__Nb_%d__%sx_%sy' % ( N / Nlegs, Nlegs, phiamt, Nstates, J1, J2, gamamt, Na, Nb, modex2, modey2) filepath = path / filename np.save(str(filepath), SA)