Пример #1
0
    def _update_neigh(self, influence_distance: float):
        """
        Update neighbor list and model input.
        """

        # inquire information from conf
        cell = np.asarray(self.conf.cell, dtype=np.double)
        PBC = np.asarray(self.conf.PBC, dtype=np.intc)
        contributing_coords = np.asarray(self.conf.coords, dtype=np.double)
        contributing_species = self.conf.species
        num_contributing = self.conf.get_num_atoms()
        self.num_contributing_particles = num_contributing

        # species support and code
        unique_species = list(set(contributing_species))
        species_map = dict()
        for s in unique_species:
            if s in self.supported_species:
                species_map[s] = self.supported_species[s]
            else:
                report_error(f"species `{s}` not supported by model")
        contributing_species_code = np.array(
            [species_map[s] for s in contributing_species], dtype=np.intc)

        if any(PBC):  # need padding atoms
            out = nl.create_paddings(
                influence_distance,
                cell,
                PBC,
                contributing_coords,
                contributing_species_code,
            )
            padding_coords, padding_species_code, self.padding_image_of, error = out
            check_error(error, "nl.create_paddings")

            num_padding = padding_species_code.size
            self.num_particles = np.array([num_contributing + num_padding],
                                          dtype=np.intc)
            tmp = np.concatenate((contributing_coords, padding_coords))
            self.coords = np.asarray(tmp, dtype=np.double)
            tmp = np.concatenate(
                (contributing_species_code, padding_species_code))
            self.species_code = np.asarray(tmp, dtype=np.intc)
            self.particle_contributing = np.ones(self.num_particles[0],
                                                 dtype=np.intc)
            self.particle_contributing[num_contributing:] = 0

            # TODO check whether padding need neigh and create accordingly
            # for now, create neigh for all atoms, including paddings
            need_neigh = np.ones(self.num_particles[0], dtype=np.intc)

        else:  # do not need padding atoms
            self.padding_image_of = np.array([])
            self.num_particles = np.array([num_contributing], dtype=np.intc)
            self.coords = np.array(contributing_coords, dtype=np.double)
            self.species_code = np.array(contributing_species_code,
                                         dtype=np.intc)
            self.particle_contributing = np.ones(num_contributing,
                                                 dtype=np.intc)
            need_neigh = self.particle_contributing

        error = nl.build(
            self.neigh,
            self.coords,
            influence_distance,
            np.asarray([influence_distance], dtype=np.double),
            need_neigh,
        )
        check_error(error, "nl.build")
Пример #2
0
def test_main():

    # create contributing atoms
    alat = 2.46
    d = 3.35
    cell, contrib_coords, contrib_species = create_graphite_unit_cell(alat, d)

    # create padding atoms
    cutoffs = np.array([d + 0.01, d + 0.02], dtype=np.double)
    influence_dist = cutoffs[1]
    pbc = np.array([1, 1, 1], dtype=np.intc)
    out = nl.create_paddings(influence_dist, cell, pbc,
                             contrib_coords, contrib_species)
    pad_coords, pad_species, pad_image, error = out
    check_error(error, 'nl.create_padding')

    assert pad_coords.shape == (96, 3)
    # print('pad_coords is of shape:', pad_coords.shape)

    coords = np.concatenate((contrib_coords, pad_coords))
    coords = np.asarray(coords, dtype=np.double)
    species = np.concatenate((contrib_species, pad_species))
    species = np.asarray(species, dtype=np.intc)
    fname = 'atoms.xyz'
    write_XYZ(fname, cell, species, coords)

    # flag to indicate wheter create neighbor list for an atom
    n_pad = pad_coords.shape[0]
    n_contrib = contrib_coords.shape[0]
    need_neigh = np.concatenate((np.ones(n_contrib), np.zeros(n_pad)))
    need_neigh = np.asarray(need_neigh, dtype=np.intc)

    # create neighbor list
    neigh = nl.initialize()
    error = nl.build(neigh, coords, influence_dist, cutoffs, need_neigh)
    check_error(error, 'nl.build')

    # build again (it will automatically empty previous neigh list)
    error = nl.build(neigh, coords, influence_dist, cutoffs, need_neigh)
    check_error(error, 'nl.build')

    # test get neigh function
    neigh_list_index = 0
    particle = 1
    num_neigh, neighbors, error = nl.get_neigh(
        neigh, cutoffs, neigh_list_index, particle)
    check_error(error, 'nl.get_neigh')
    assert num_neigh == 14
    # print('Atom 1 has {} neighbors:'.format(num_neigh), end=' ')
    # for i in neighbors:
    #  print(i, end=' ')

    neigh_list_index = 1
    particle = 4
    num_neigh, neighbors, error = nl.get_neigh(
        neigh, cutoffs, neigh_list_index, particle)
    check_error(error, 'nl.get_neigh')
    assert num_neigh == 0

    # expect error message from this
    # neigh_list_index = 1
    # particle = n_contrib + n_pad
    # num_neigh, neighbors, error = nl.get_neigh(neigh, cutoffs, neigh_list_index, particle)
    # assert error == 1

    # delete neighbor list
    nl.clean(neigh)

    # remove the created file
    try:
        os.remove(fname)
        os.remove('kim.log')
    except:
        pass
Пример #3
0
 def build(self):
     return neighlist.build(self.neigh, self.coords, self.influence_dist,
                            self.cutoffs, self.need_neigh)
Пример #4
0
def test_main():
    modelname = 'ex_model_Ar_P_Morse_07C'
    print()
    print('=' * 80)
    print('Matching results for KIM model:', modelname)
    print()

    # create model
    requestedUnitsAccepted, kim_model, error = kimpy.model.create(
        kimpy.numbering.zeroBased,
        kimpy.length_unit.A,
        kimpy.energy_unit.eV,
        kimpy.charge_unit.e,
        kimpy.temperature_unit.K,
        kimpy.time_unit.ps,
        modelname,
    )
    check_error(error, 'kimpy.model.create')

    if not requestedUnitsAccepted:
        report_error('requested units not accepted in kimpy.model.create')

    # units
    l_unit, e_unit, c_unit, te_unit, ti_unit = kim_model.get_units()
    check_error(error, 'kim_model.get_units')
    print('Length unit is:', str(l_unit))
    print('Energy unit is:', str(e_unit))
    print('Charge unit is:', str(c_unit))
    print('Temperature unit is:', str(te_unit))
    print('Time unit is:', str(ti_unit))
    print()

    # create compute arguments
    compute_arguments, error = kim_model.compute_arguments_create()
    check_error(error, 'kim_model.compute_arguments_create')

    # check compute arguments
    num_compute_arguments = (
        kimpy.compute_argument_name.get_number_of_compute_argument_names())
    print('Number of compute_arguments:', num_compute_arguments)

    for i in range(num_compute_arguments):
        name, error = kimpy.compute_argument_name.get_compute_argument_name(i)
        check_error(error, 'kim_model.get_compute_argument_name')

        dtype, error = \
            kimpy.compute_argument_name.get_compute_argument_data_type(name)
        check_error(error, 'kim_model.get_compute_argument_data_type')

        support_status, error = \
            compute_arguments.get_argument_support_status(name)
        check_error(error, 'compute_argument.get_argument_support_status')

        n_space_1 = 21 - len(str(name))
        n_space_2 = 7 - len(str(dtype))

        print('Compute Argument name "{}" '.format(name) + ' ' * n_space_1 +
              'is of type "{}" '.format(dtype) + ' ' * n_space_2 +
              'and has support status "{}".'.format(support_status))

        # can only handle energy and force as a required arg
        if support_status == kimpy.support_status.required:
            if name not in (kimpy.compute_argument_name.partialEnergy,
                            kimpy.compute_argument_name.partialForces):
                report_error('Unsupported required ComputeArgument')

        # must have energy and forces
        if name in (kimpy.compute_argument_name.partialEnergy,
                    kimpy.compute_argument_name.partialForces):
            if support_status not in (kimpy.support_status.required,
                                      kimpy.support_status.optional):
                report_error('Energy or forces not available')
    print()

    # check compute callbacks
    num_callbacks = \
        kimpy.compute_callback_name.get_number_of_compute_callback_names()
    print('Number of callbacks:', num_callbacks)

    for i in range(num_callbacks):
        name, error = kimpy.compute_callback_name.get_compute_callback_name(i)
        check_error(error, 'kim_model.get_compute_callback_name')

        support_status, error = \
            compute_arguments.get_callback_support_status(name)
        check_error(error, 'compute_argument.get_callback_support_status')

        n_space = 18 - len(str(name))
        print('Compute callback "{}"'.format(name) + ' ' * n_space +
              'has support status "{}".'.format(support_status))

        # cannot handle any "required" callbacks
        if support_status == kimpy.support_status.required:
            report_error('Unsupported required ComputeCallback')
    print()

    # parameter
    num_params = kim_model.get_number_of_parameters()
    print('Number of parameters:', num_params)
    print()
    for i in range(num_params):
        out = kim_model.get_parameter_metadata(i)
        dtype, extent, name, description, error = out
        check_error(error, 'kim_model.get_parameter_metadata')
        print('Parameter No.', i)
        print('    data type:', dtype)
        print('    extent:', extent)
        print('    name:', name)
        print('    description:', description)
    print()

    # register argument
    argon = create_fcc_argon()

    coords = np.asarray(argon.get_positions(), dtype=np.double)
    N = coords.shape[0]
    print('Number of particles:', N)
    forces = np.zeros((N, 3), dtype=np.double)
    energy = np.array([0.0], dtype=np.double)
    num_particles = np.array([N], dtype=np.intc)
    species_code = np.zeros(num_particles, dtype=np.intc)
    particle_contributing = np.zeros(num_particles, dtype=np.intc)

    error = compute_arguments.set_argument_pointer(
        kimpy.compute_argument_name.numberOfParticles, num_particles)
    check_error(error, 'kimpy.compute_argument.set_argument_pointer')

    error = compute_arguments.set_argument_pointer(
        kimpy.compute_argument_name.particleSpeciesCodes, species_code)
    check_error(error, 'kimpy.compute_argument.set_argument_pointer')

    error = compute_arguments.set_argument_pointer(
        kimpy.compute_argument_name.particleContributing,
        particle_contributing)
    check_error(error, 'kimpy.compute_argument.set_argument_pointer')

    error = compute_arguments.set_argument_pointer(
        kimpy.compute_argument_name.coordinates, coords)
    check_error(error, 'kimpy.compute_argument.set_argument_pointer')

    error = compute_arguments.set_argument_pointer(
        kimpy.compute_argument_name.partialEnergy, energy)
    check_error(error, 'kimpy.compute_argument.set_argument_pointer')

    error = compute_arguments.set_argument_pointer(
        kimpy.compute_argument_name.partialForces, forces)
    check_error(error, 'kimpy.compute_argument.set_argument_pointer')

    # create neighbor list
    neigh = nl.initialize()

    # register get neigh callback

    error = compute_arguments.set_callback_pointer(
        kimpy.compute_callback_name.GetNeighborList, nl.get_neigh_kim(), neigh)
    check_error(error, 'kimpy.compute_argument.set_callback_pointer')

    # influence distance and cutoff of model
    model_influence_dist = kim_model.get_influence_distance()
    out = kim_model.get_neighbor_list_cutoffs_and_hints()
    model_cutoffs, padding_not_require_neigh_hints = out
    print('Model influence distance:', model_influence_dist)
    print('Model cutoffs:', model_cutoffs)
    print('Model padding neighbors hints:', padding_not_require_neigh_hints)
    print()

    # species support and code
    species_support, code, error = \
        kim_model.get_species_support_and_code(kimpy.species_name.Ar)
    check_error(error or not species_support,
                'kim_model.get_species_support_and_code')
    print('Species Ar is supported and its code is:', code)
    print()

    # setup particle species
    species_code[:] = code

    # setup particleContributing
    particle_contributing[:] = 1

    # setup neighbor list
    need_neigh = np.ones(N, dtype='intc')

    # compute energy and force for different structures
    alat = 5.26
    min_alat = 0.8 * 5.26
    max_alat = 1.2 * 5.26
    inc_alat = 0.025 * alat
    all_alat = np.arange(min_alat, max_alat, inc_alat)

    print('=' * 80)
    print('Result for KIM model:', modelname)
    print()
    print('       energy          force norm        lattice spacing')
    print()

    for a in all_alat:
        argon = create_fcc_argon(a)
        # NOTE cannot change coords address
        np.copyto(coords, argon.get_positions())
        error = nl.build(neigh, coords, model_influence_dist, model_cutoffs,
                         need_neigh)
        check_error(error, 'nl.build')
        error = kim_model.compute(compute_arguments)
        print('{:18.10e} {:18.10e} {:18.10e}'.format(energy[0],
                                                     np.linalg.norm(forces),
                                                     a))

    # destory neighbor list
    nl.clean(neigh)

    # destory compute arguments
    error = kim_model.compute_arguments_destroy(compute_arguments)
    check_error(error, 'kim_model.compute_arguments_destroy')

    # destory model
    kimpy.model.destroy(kim_model)