예제 #1
0
def makecrack_main(params, stem):
    """Given a CrackParams object `param`, construct and return a new crack slab Atoms object."""

    xmlfilename = stem+'.xml'

    print_title('Initialisation')

    verbosity_push(params.io_verbosity)
    params.print_()

    print("Initialising classical potential with args " + params.classical_args.strip() +
          " from file " + xmlfilename)
    classicalpot = Potential(params.classical_args, param_filename=xmlfilename)
    classicalpot.print_()

    mpi_glob = MPI_context()

    crack_slab, width, height, E, v, v2, bulk = crack_make_slab(params, classicalpot)
    if params.crack_free_surfaces:
       depth = crack_slab.pos[3,:].max() - crack_slab.pos[3,:].min()
    else:
       depth = crack_slab.lattice[3,3]

    # Save bulk cube (used for qm_rescale_r parameter in crack code)
    if params.qm_args.startswith('TB'):
        bigger_bulk = supercell(bulk, 2, 2, 2)
        bulk = bigger_bulk
    bulk.write(stem+'_bulk.xyz')

    crack_slab.write(stem+'_slab.xyz')

    crack_slab.params['OrigWidth'] = width
    crack_slab.params['OrigHeight'] = height
    crack_slab.params['OrigDepth'] = depth

    crack_slab.params['YoungsModulus'] = E
    crack_slab.params['PoissonRatio_yx'] = v
    crack_slab.params['PoissonRatio_yz'] = v2

    # Open surfaces, remain periodic in z direction (normal to plane)
    # and optionally also in x direction if crack_double_ended is true
    if not params.crack_double_ended:
        crack_slab.lattice[1,1] = crack_slab.lattice[1,1] + params.crack_vacuum_size

    crack_slab.lattice[2,2] = crack_slab.lattice[2,2] + params.crack_vacuum_size
    crack_slab.set_lattice(crack_slab.lattice, False)

    # 3D crack with free surfaces at z = +/- depth/2
    if params.crack_free_surfaces:
        crack_slab.pos[3,:] -= crack_slab.pos[3,:].mean() # center on z=0
        crack_slab.lattice[3,3] = crack_slab.lattice[3,3] + params.crack_vacuum_size

    crack_slab.set_lattice(crack_slab.lattice, False)

    # Map atoms into cell AFTER changing to the new lattice
    crack_slab.map_into_cell()

    miny, maxy = crack_slab.pos[2,:].min(), crack_slab.pos[2,:].max()
    assert abs((maxy-miny) - height) < 1e-5  # be sure that remapping didn't change height of slab

    # Add various properties to crack_slab
    crack_slab.add_property('hybrid', 0)
    crack_slab.add_property('hybrid_mark', HYBRID_NO_MARK)
    crack_slab.add_property('changed_nn', 0)
    crack_slab.add_property('move_mask', 0)
    crack_slab.add_property('nn', 0)
    crack_slab.add_property('old_nn', 0)
    crack_slab.add_property('md_old_changed_nn', 0)
    crack_slab.add_property('edge_mask', 0)
    crack_slab.add_property('crack_surface', False)
    crack_slab.add_property('crack_front', False)
    if params.crack_fix_dipoles:
	crack_slab.add_property('fixdip', False)

    print_title('Fixing Atoms')

    # Fix top and bottom edges - anything within crack_edge_fix_tol of ymax or ymin is fixed

    miny, maxy = crack_slab.pos[2,:].min(), crack_slab.pos[2,:].max()

    crack_slab.move_mask[:] = 1
    crack_slab.move_mask[(abs(crack_slab.pos[2,:]-maxy) < params.crack_edge_fix_tol) |
                         (abs(crack_slab.pos[2,:]-miny) < params.crack_edge_fix_tol)] = 0

    if params.crack_fix_sides:
        maxx, minx = crack_slab.pos[1,:].min(), crack_slab.pos[1,:].max()
        crack_slab.move_mask[(abs(crack_slab.pos[1,:]-maxx) < params.crack_edge_fix_tol) |
                             (abs(crack_slab.pos[1,:]-minx) < params.crack_edge_fix_tol)] = 0


    print('%d atoms. %d fixed atoms' % (crack_slab.n, crack_slab.n - crack_slab.move_mask.sum()))

    print_title('Setting edge mask')

    crack_slab.edge_mask[:] = 0

    minx, maxx = crack_slab.pos[1,:].min(), crack_slab.pos[1,:].max()
    crack_slab.edge_mask[(abs(crack_slab.pos[1,:]-minx) < params.selection_edge_tol) |
                         (abs(crack_slab.pos[1,:]-maxx) < params.selection_edge_tol)] = 1

    miny, maxy = crack_slab.pos[2,:].min(), crack_slab.pos[2,:].max()
    crack_slab.edge_mask[(abs(crack_slab.pos[2,:]-miny) < params.selection_edge_tol) |
                         (abs(crack_slab.pos[2,:]-maxy) < params.selection_edge_tol)] = 1

    if params.crack_free_surfaces:
        # Open surfaces at +/- z
        minz, maxz = crack_slab.pos[3,:].min(), crack_slab.pos[3,:].max()
        crack_slab.edge_mask[(abs(crack_slab.pos[3,:]-minz) < params.selection_edge_tol) |
                             (abs(crack_slab.pos[3,:]-maxz) < params.selection_edge_tol)] = 1

    if params.crack_fix_dipoles:
        print_title('Fixing dipoles')
        crack_slab.fixdip[(abs(crack_slab.pos[2,:]-maxy) < params.crack_fix_dipoles_tol) |
                          (abs(crack_slab.pos[2,:]-miny) < params.crack_fix_dipoles_tol)] = 1
        if params.crack_fix_sides:
                maxx, minx = crack_slab.pos[1,:].min(), crack_slab.pos[1,:].max()
                crack_slab.fixdip[(abs(crack_slab.pos[1,:]-maxx) < params.crack_fix_dipoles_tol) |
                                  (abs(crack_slab.pos[1,:]-minx) < params.crack_fix_dipoles_tol)] = 1


    if params.crack_curved_front:
       crack_make_seed_curved_front(crack_slab, params)
    else:
       crack_make_seed(crack_slab, params)
       if params.crack_apply_initial_load:
          crack_calc_load_field(crack_slab, params, classicalpot,
                              params.crack_loading, overwrite_pos=True,
                              mpi=mpi_glob)

    crack_slab.write('dump.xyz')
    crack_update_connect(crack_slab, params)

    if not params.simulation_classical:
        if (params.selection_method.strip() == 'crack_front' or
            params.crack_tip_method.strip() == 'local_energy'):
            classicalpot.calc(crack_slab, local_energy=True)

        crack_setup_marks(crack_slab, params)
        crack_update_selection(crack_slab, params)

    if params.any_per_atom_tau():
        # Set up per_atom_tau property for ramped Langevin thermostat:
        #
        #    tau
        #    ^
        #    |\        /|                     |\        /|  max_tau
        #    | \      / |                     | \      / |
        #    |  \    /  |     constant E      |  \    /  |
        #    |   \  /   |      (tau = 0)      |   \  /   |
        #    |    \/    |                     |    \/    |
        #    +----------+---------------------+----------+---> x
        #   -w/2      -w/2+r                 w/2-r      w/2

        w_by_2   = crack_slab.OrigWidth/2.
        ramp_len = params.crack_thermostat_ramp_length
        max_tau  = params.crack_thermostat_ramp_max_tau
        print 'Adding thermostat ramp with length', ramp_len, 'max_tau', max_tau

        @np.vectorize
        def tau(x):
            if x < -w_by_2 + ramp_len/2:
                q = (x+w_by_2)/(ramp_len/2.)
                return max_tau*(1.- q)
            elif (x > -w_by_2 + ramp_len/2 and
                  x < -w_by_2 + ramp_len):
                q = (x+w_by_2-ramp_len/2.)/(ramp_len/2.)
                return max_tau*q
            elif (x > -w_by_2 + ramp_len and
                  x < w_by_2 - ramp_len):
                return 0.
            elif (x > w_by_2 - ramp_len and
                  x < w_by_2 - ramp_len/2):
                q = (x-w_by_2+ramp_len)/(ramp_len/2.)
                return max_tau*(1.- q)
            else:
                q = (x-w_by_2+ramp_len/2.)/(ramp_len/2.)
                return max_tau*q
        crack_slab.add_property('per_atom_tau', tau(crack_slab.pos[1,:]))

    return crack_slab
예제 #2
0
def crack_strain_energy_release_rate(at, bulk=None, f_min=.8, f_max=.9, stem=None, avg_pos=False):
    """
    Compute strain energy release rate G from elastic potential energy in a strip
    """

    print 'Analytical effective elastic modulus E\' = ', at.YoungsModulus/(1-at.PoissonRatio_yx**2), 'GPa'
    print 'Analytical energy release rate G = ', crack_measure_g(at, at.YoungsModulus, at.PoissonRatio_yx, at.OrigHeight), 'J/m^2'

    if bulk is None:
        if stem is None: raise ValueError('Either "bulk" or "stem" must be present')
        bulk = Atoms(stem+'_bulk.xyz')

    if not hasattr(at, 'local_energy') or not hasattr(bulk, 'energy'):
        if stem is None: raise ValueError('local_energy property not found in Atoms and "stem" is missing')
        xmlfile = stem+'.xml'
        params = CrackParams(xmlfile)
        pot = Potential(params.classical_args, param_filename=stem+'.xml')
        pot.print_()

        if not hasattr(at, 'local_energy'):
            if avg_pos:
                tmp_pos = at.pos.copy()
                at.pos[...] = at.avgpos
            at.set_cutoff(pot.cutoff()+1.)
            at.calc_connect()
            pot.calc(at, args_str="local_energy")
            if avg_pos:
                at.pos[...] = tmp_pos

        if not hasattr(bulk, 'energy'):
            bulk.set_cutoff(pot.cutoff()+1.)
            bulk.calc_connect()
            pot.calc(bulk, args_str='energy')

    h = at.pos[2,:].max() - at.pos[2,:].min()
    h0 = at.OrigHeight
    strain = (h - h0)/h0
    print 'Applied strain', strain

    x_min = f_min*at.OrigWidth - at.OrigWidth/2.
    x_max = f_max*at.OrigWidth - at.OrigWidth/2.
    strip = np.logical_and(at.move_mask == 1, np.logical_and(at.pos[1,:] > x_min, at.pos[1,:] < x_max))
    at.add_property('strip', strip, overwrite=True)

    strip_depth = at.lattice[3,3]
    strip_width = at.pos[1,strip].max() - at.pos[1,strip].min()
    strip_height = at.pos[2,strip].max() - at.pos[2,strip].min()
    strip_volume = strip_width*strip_height*strip_depth
    print 'Strip contains', strip.sum(), 'atoms', 'width', strip_width, 'height', strip_height, 'volume', strip_volume

    strain_energy_density = (at.local_energy[strip].sum() - bulk.energy/bulk.n*strip.sum())/strip_volume

    print 'Strain energy density in strip', strain_energy_density, 'eV/A**3'

    E_effective = 2*strain_energy_density/strain**2*GPA
    print 'Effective elastic modulus E =', E_effective, 'GPa'

    G_effective = strain_energy_density*strip_height*J_PER_M2
    print 'Effective energy release rate G =', G_effective, 'J/m^2'

    return G_effective
예제 #3
0
def molecular_dynamics(system,
                       potential,
                       potential_filename=None,
                       temperature=300,
                       total_steps=1100000,
                       timestep=1.0,
                       connect_interval=200,
                       write_interval=20000,
                       equilibration_steps=100000,
                       out_of_plane=None,
                       random_seed=None):
    """
    Run very simple molecular dynamics to generate some configurations. Writes
    configurations out as xyz and CASTEP files.
    """

    info("Inside MD.")
    if random_seed is None:
        random_seed = random.SystemRandom().randint(0, 2**63)
    quippy.system.system_set_random_seeds(random_seed)
    info("Quippy Random Seed {0}.".format(random_seed))
    system = Atoms(system)

    # Can take Potential objects, or just use a string
    if not isinstance(potential, Potential):
        if potential_filename:
            potential = Potential(potential, param_filename=potential_filename)
        else:
            potential = Potential(potential)
    system.set_calculator(potential)

    dynamical_system = DynamicalSystem(system)
    with Capturing(debug_on_exit=True):
        dynamical_system.rescale_velo(temperature)

    if out_of_plane is not None:
        # Stop things moving vertically in the cell
        dynamical_system.atoms.velo[3, :] = 0

    base_dir = os.getcwd()
    run_path = '{0}_{1:g}/'.format(system.info['name'], temperature)
    info("Putting files in {0}.".format(run_path))
    os.mkdir(run_path)
    os.chdir(run_path)

    trajectory = 'traj_{0}_{1:g}.xyz'.format(system.info['name'], temperature)
    out = AtomsWriter(trajectory)

    dynamical_system.atoms.set_cutoff(potential.cutoff() + 2.0)
    dynamical_system.atoms.calc_connect()
    potential.calc(dynamical_system.atoms,
                   force=True,
                   energy=True,
                   virial=True)

    structure_count = 0

    # Basic NVE molecular dynamics
    for step_number in range(1, total_steps + 1):
        dynamical_system.advance_verlet1(timestep,
                                         virial=dynamical_system.atoms.virial)
        potential.calc(dynamical_system.atoms,
                       force=True,
                       energy=True,
                       virial=True)
        dynamical_system.advance_verlet2(timestep,
                                         f=dynamical_system.atoms.force,
                                         virial=dynamical_system.atoms.virial)

        # Maintenance of the system
        if not step_number % connect_interval:
            debug("Connect at step {0}".format(step_number))
            dynamical_system.atoms.calc_connect()
            if step_number < equilibration_steps:
                with Capturing(debug_on_exit=True):
                    dynamical_system.rescale_velo(temperature)

        if not step_number % write_interval:
            debug("Status at step {0}".format(step_number))
            # Print goes to captured stdout
            with Capturing(debug_on_exit=True):
                dynamical_system.print_status(
                    epot=dynamical_system.atoms.energy)
                dynamical_system.rescale_velo(temperature)

            if step_number > equilibration_steps:
                debug("Write at step {0}".format(step_number))
                out.write(dynamical_system.atoms)
                sp_path = '{0:03d}'.format(structure_count)
                write_filename = '{0}_{1:g}.{2:03d}'.format(
                    system.info['name'], temperature, structure_count)
                os.mkdir(sp_path)
                os.chdir(sp_path)
                castep_write(dynamical_system.atoms, filename=write_filename)
                espresso_write(dynamical_system.atoms, prefix=write_filename)
                write_extxyz("{0}.xyz".format(write_filename),
                             dynamical_system.atoms)
                info("Wrote a configuration {0}.".format(write_filename))
                os.chdir('..')
                structure_count += 1

    out.close()
    os.chdir(base_dir)

    info("MD Done.")
예제 #4
0
# setup clusters to be calculated
d = diamond(5.44, 14)
at = supercell(d, 2, 2, 2)
at.rattle(0.05)
at.calc_connect()
clusters = list(
    iter_atom_centered_clusters(at, buffer_hops=4, randomise_buffer=False))

pot = Potential('IP SW', param_filename='params.xml')

for i, c in enumerate(clusters):
    client_id, nstep = i % N_JOBS, i // N_JOBS
    data = pack_atoms_to_reftraj_str(c, nstep)
    cluster_map[(client_id, nstep)] = (c, i)
    input_qs[client_id].put(data)
    pot.calc(c, args_str='energy force virial')

t_clus = time.time()

# write initial input file for each client
for client_id, input_q in enumerate(input_qs):
    data = input_q.get()
    c, i = cluster_map[(client_id, 0)]
    c.write('atoms.%d.xyz' % client_id, real_format=MSG_FLOAT_FORMAT)
    scp = subprocess.Popen(
        ['scp', 'atoms.%d.xyz' % client_id, remote_host + ':'])
    scp.wait()

t_input = time.time()

for param_file in param_files:
예제 #5
0
def quippy_client(ip, port, client_id, maxsteps):
    pot = Potential('IP SW')
    args_str = 'force energy virial'

    print 'Starting client with ID %d maxsteps %d' % (client_id, maxsteps)
    
    for step in range(maxsteps):
        
        # open connection to server
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((ip, port))
        try:
            # say hello and ask server for some Atoms (status 'A')
            # identify ourselves with an ID number, formatted as an 8-byte ascii string
            id_str = ('A%7d' % client_id).encode('ascii')
            totalsent = 0
            while totalsent < MSG_LEN_SIZE:
                sent = sock.send(id_str[totalsent:])
                if sent == 0:
                    raise RuntimeError('socket connection broken while sending client ID')
                totalsent += sent

            # now receive the length of the data, formatted as an 8-byte ascii string
            data_length = ''
            while len(data_length) < MSG_LEN_SIZE:
                chunk = sock.recv(MSG_LEN_SIZE - len(data_length))
                if not chunk:
                    raise RuntimeError('socket connection broken while reading length')
                data_length += chunk
            data_length = int(data_length)

            # now receive the data itself
            data = ''
            while len(data) < data_length:
                chunk = sock.recv(data_length - len(data))
                if not chunk:
                    raise RuntimeError('socket connection broken while reading data')
                data += chunk

            # and finally receive the end marker
            marker = ''
            while len(marker) < MSG_END_MARKER_SIZE:
                chunk = sock.recv(MSG_END_MARKER_SIZE - len(marker))
                if not chunk:
                    raise RuntimeError('socket connection broken while reading end marker')
                marker += chunk

            assert marker == MSG_END_MARKER

        finally:
            sock.close()

        # construct Atoms object from data string in REFTRAJ format
        at = unpack_reftraj_str_to_atoms(data)

        # do the calculation - this will take a long time in real use-case
        pot.calc(at, args_str=args_str)

        print 'client %d calculation on %d atoms complete' % (client_id, len(at))

        # format the results into a string, cf. vasp_driver REJTRAJ_OUTPUT format
        data = pack_results_to_reftraj_output_str(at)

        # open a new connection to the server to send back the results
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((ip, port))
        try:
            # say hello and tell server we've got some results (status 'R')
            # identify ourselves with an ID number, formatted as an 8-byte ascii string
            id_str = ('R%7d' % client_id).encode('ascii')
            totalsent = 0
            while totalsent < MSG_LEN_SIZE:
                sent = sock.send(id_str[totalsent:])
                if sent == 0:
                    raise RuntimeError('socket connection broken while sending client ID')
                totalsent += sent

            # send back results of the calculation
            totalsent = 0
            while totalsent < len(data):
                sent = sock.send(data[totalsent:])
                if sent == 0:
                    raise RuntimeError('socket connection broken while sending results')
                totalsent += sent

            # wait to receive the end marker
            marker = ''
            while len(marker) < MSG_END_MARKER_SIZE:
                chunk = sock.recv(MSG_END_MARKER_SIZE - len(marker))
                if not chunk:
                    raise RuntimeError('socket connection broken while reading end marker')
                marker += chunk

            assert marker == MSG_END_MARKER

        finally:
            sock.close()
예제 #6
0
                              w_epsilon=10000.0, w_epsilon_factor=10000.0,
                              t=TEMPERATURE)
dynamical_system.add_thermostat(type=THERMOSTAT_ALL_PURPOSE, t=TEMPERATURE, tau=100.0)
dynamical_system.rescale_velo(TEMPERATURE)

total_steps = 1100000
timestep = 0.1  # fs
connect_interval = 200
write_interval = 20000
equilibration_steps = 100000

trajectory = 'traj_{}_{}.xyz'.format(lattice.func_name, TEMPERATURE)
out = AtomsWriter(trajectory)

dynamical_system.atoms.calc_connect()
fs_potential.calc(dynamical_system.atoms, force=True, energy=True, virial=True)

# Basic NVE molecular dynamics
for step_number in range(1, total_steps+1):
    dynamical_system.advance_verlet1(timestep,
                                     virial=dynamical_system.atoms.virial)
    fs_potential.calc(dynamical_system.atoms, force=True,
                      energy=True, virial=True)
    dynamical_system.advance_verlet2(timestep, f=dynamical_system.atoms.force,
                                     virial=dynamical_system.atoms.virial)

    # Maintenance of the system
    if not step_number % connect_interval:
        dynamical_system.atoms.calc_connect()
        if step_number < equilibration_steps:
            dynamical_system.rescale_velo(TEMPERATURE)