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
예제 #2
0
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
예제 #3
0
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')
예제 #4
0
 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)
예제 #5
0
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
예제 #6
0
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
예제 #7
0
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])
예제 #9
0
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
예제 #10
0
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
예제 #11
0
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()
예제 #12
0
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]
예제 #13
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
예제 #14
0
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!")
예제 #15
0
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
예제 #16
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))
예제 #17
0
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
예제 #18
0
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:
예제 #19
0
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)