Example #1
0
morse_r0 = 1.4322
angle_k = 10.0
angle_a0 = np.deg2rad(120.0)
dihedral_k = 0.346
vdw_epsilonij = 0.0115
vdw_rminij = 3.4681

neighbor_list = [[] for _ in range(len(a))]
vdw_list = np.ones((len(a), len(a)), dtype=bool)
morses = []
angles = []
dihedrals = []
vdws = []

# create neighbor list
i_list, j_list, d_list, fixed_atoms = get_neighbours(atoms=a, r_cut=cutoff)
for i, j in zip(i_list, j_list):
    neighbor_list[i].append(j)
for i in range(len(neighbor_list)):
    neighbor_list[i].sort()

# create lists of morse, bending and torsion interactions
for i in range(len(a)):
    for jj in range(len(neighbor_list[i])):
        j = neighbor_list[i][jj]
        if j > i:
            morses.append(
                Morse(atomi=i,
                      atomj=j,
                      D=morse_D,
                      alpha=morse_alpha,
def forcefield_params(atoms0):
    # force field parameters for fulleren, Z. Berkai at al.
    # Energy Procedia, 74, 2015, 59-64
    a = atoms0
    cutoff = 1.5
    morse_D = 6.1322
    morse_alpha = 1.8502
    morse_r0 = 1.4322
    angle_k = 10.0
    angle_a0 = np.deg2rad(120.0)
    dihedral_k = 0.346
    vdw_epsilonij = 0.0115
    vdw_rminij = 3.4681

    neighbor_list = [[] for _ in range(len(a))]
    vdw_list = np.ones((len(a), len(a)), dtype=bool)
    morses = []
    angles = []
    dihedrals = []
    vdws = []

    # create neighbor list
    i_list, j_list, d_list, fixed_atoms = get_neighbours(atoms=a, r_cut=cutoff)
    for i, j in zip(i_list, j_list):
        neighbor_list[i].append(j)
    for i in range(len(neighbor_list)):
        neighbor_list[i].sort()

    # create lists of morse, bending and torsion interactions
    for i in range(len(a)):
        for jj in range(len(neighbor_list[i])):
            j = neighbor_list[i][jj]
            if j > i:
                morses.append(
                    Morse(atomi=i,
                          atomj=j,
                          D=morse_D,
                          alpha=morse_alpha,
                          r0=morse_r0))
            vdw_list[i, j] = vdw_list[j, i] = False
            for kk in range(jj + 1, len(neighbor_list[i])):
                k = neighbor_list[i][kk]
                angles.append(
                    Angle(atomi=j,
                          atomj=i,
                          atomk=k,
                          k=angle_k,
                          a0=angle_a0,
                          cos=True))
                vdw_list[j, k] = vdw_list[k, j] = False
                for ll in range(kk + 1, len(neighbor_list[i])):
                    l = neighbor_list[i][ll]
                    dihedrals.append(
                        Dihedral(atomi=j,
                                 atomj=i,
                                 atomk=k,
                                 atoml=l,
                                 k=dihedral_k))

    # create list of van der Waals interactions
    for i in range(len(a)):
        for j in range(i + 1, len(a)):
            if vdw_list[i, j]:
                vdws.append(
                    VdW(atomi=i,
                        atomj=j,
                        epsilonij=vdw_epsilonij,
                        rminij=vdw_rminij))

    return dict(morses=morses, angles=angles, dihedrals=dihedrals, vdws=vdws)
Example #3
0
    def _make_sparse_precon(self, atoms, initial_assembly=False,
                            force_stab=False):
        """Create a sparse preconditioner matrix based on the passed atoms.

        Args:
            atoms: the Atoms object used to create the preconditioner.

        Returns:
            A scipy.sparse.csr_matrix object, representing a d*N by d*N matrix
            (where N is the number of atoms, and d is the value of self.dim).
            BE AWARE that using numpy.dot() with this object will result in
            errors/incorrect results - use the .dot method directly on the
            sparse matrix instead.

        """
        #print('creating sparse precon: initial_assembly=%r, '
        #       'force_stab=%r, apply_positions=%r, apply_cell=%r' %
        #       (initial_assembly, force_stab, self.apply_positions,
        #       self.apply_cell))

        N = len(atoms)
        #start_time = time.time()
        if self.apply_positions:
            # compute neighbour list
            i_list, j_list, rij_list, fixed_atoms = get_neighbours(
                atoms, self.r_cut)
            #print('--- neighbour list created in %s s ---' %
            #            (time.time() - start_time))

        row = []
        col = []
        data = []

        # precon is mu_c*identity for cell DoF
        if isinstance(atoms, Filter):
            i = N - 3
            j = N - 2
            k = N - 1
            x = [3 * i, 3 * i + 1, 3 * i + 2, 3 * j, 3 *
                 j + 1, 3 * j + 2, 3 * k, 3 * k + 1, 3 * k + 2]
            row.extend(x)
            col.extend(x)
            if self.apply_cell:
                data.extend(np.repeat(self.mu_c, 9))
            else:
                data.extend(np.repeat(self.mu_c, 9))
        #print('--- computed triplet format in %s s ---' %
        #            (time.time() - start_time))

        conn = sparse.lil_matrix((N, N), dtype=bool)

        if self.apply_positions and not initial_assembly:

            if self.morses is not None:

                for n in range(len(self.morses)):
                    if self.hessian == 'reduced':
                        i, j, Hx = ff.get_morse_potential_reduced_hessian(
                            atoms, self.morses[n])
                    elif self.hessian == 'spectral':
                        i, j, Hx = ff.get_morse_potential_hessian(
                            atoms, self.morses[n], spectral=True)
                    else:
                        raise NotImplementedError('Not implemented hessian')
                    x = [3 * i, 3 * i + 1, 3 * i + 2,
                         3 * j, 3 * j + 1, 3 * j + 2]
                    row.extend(np.repeat(x, 6))
                    col.extend(np.tile(x, 6))
                    data.extend(Hx.flatten())
                    conn[i, j] = True
                    conn[j, i] = True

            if self.bonds is not None:

                for n in range(len(self.bonds)):
                    if self.hessian == 'reduced':
                        i, j, Hx = ff.get_bond_potential_reduced_hessian(
                            atoms, self.bonds[n], self.morses)
                    elif self.hessian == 'spectral':
                        i, j, Hx = ff.get_bond_potential_hessian(
                            atoms, self.bonds[n], self.morses, spectral=True)
                    else:
                        raise NotImplementedError('Not implemented hessian')
                    x = [3 * i, 3 * i + 1, 3 * i + 2,
                         3 * j, 3 * j + 1, 3 * j + 2]
                    row.extend(np.repeat(x, 6))
                    col.extend(np.tile(x, 6))
                    data.extend(Hx.flatten())
                    conn[i, j] = True
                    conn[j, i] = True

            if self.angles is not None:

                for n in range(len(self.angles)):
                    if self.hessian == 'reduced':
                        i, j, k, Hx = ff.get_angle_potential_reduced_hessian(
                            atoms, self.angles[n], self.morses)
                    elif self.hessian == 'spectral':
                        i, j, k, Hx = ff.get_angle_potential_hessian(
                            atoms, self.angles[n], self.morses, spectral=True)
                    else:
                        raise NotImplementedError('Not implemented hessian')
                    x = [3 * i, 3 * i + 1, 3 * i + 2, 3 * j, 3 *
                         j + 1, 3 * j + 2, 3 * k, 3 * k + 1, 3 * k + 2]
                    row.extend(np.repeat(x, 9))
                    col.extend(np.tile(x, 9))
                    data.extend(Hx.flatten())
                    conn[i, j] = conn[i, k] = conn[j, k] = True
                    conn[j, i] = conn[k, i] = conn[k, j] = True

            if self.dihedrals is not None:

                for n in range(len(self.dihedrals)):
                    if self.hessian == 'reduced':
                        i, j, k, l, Hx = \
                            ff.get_dihedral_potential_reduced_hessian(
                                atoms, self.dihedrals[n], self.morses)
                    elif self.hessian == 'spectral':
                        i, j, k, l, Hx = ff.get_dihedral_potential_hessian(
                            atoms, self.dihedrals[n], self.morses,
                            spectral=True)
                    else:
                        raise NotImplementedError('Not implemented hessian')
                    x = [3 * i, 3 * i + 1, 3 * i + 2,
                         3 * j, 3 * j + 1, 3 * j + 2,
                         3 * k, 3 * k + 1, 3 * k + 2,
                         3 * l, 3 * l + 1, 3 * l + 2]
                    row.extend(np.repeat(x, 12))
                    col.extend(np.tile(x, 12))
                    data.extend(Hx.flatten())
                    conn[i, j] = conn[i, k] = conn[i, l] = conn[
                        j, k] = conn[j, l] = conn[k, l] = True
                    conn[j, i] = conn[k, i] = conn[l, i] = conn[
                        k, j] = conn[l, j] = conn[l, k] = True

        if self.apply_positions:
            for i, j, rij in zip(i_list, j_list, rij_list):
                if not conn[i, j]:
                    coeff = self.get_coeff(rij)
                    x = [3 * i, 3 * i + 1, 3 * i + 2]
                    y = [3 * j, 3 * j + 1, 3 * j + 2]
                    row.extend(x + x)
                    col.extend(x + y)
                    data.extend(3 * [-coeff] + 3 * [coeff])

        row.extend(range(self.dim * N))
        col.extend(range(self.dim * N))
        if initial_assembly:
            data.extend([self.mu * self.c_stab] * self.dim * N)
        else:
            data.extend([self.c_stab] * self.dim * N)

        # create the matrix
        #start_time = time.time()
        self.P = sparse.csc_matrix(
            (data, (row, col)), shape=(self.dim * N, self.dim * N))
        #print('--- created CSC matrix in %s s ---' %
        #            (time.time() - start_time))

        if not initial_assembly:
            if len(fixed_atoms) != 0:
                self.P.tolil()
            for i in fixed_atoms:
                self.P[i, :] = 0.0
                self.P[:, i] = 0.0
                self.P[i, i] = 1.0

        self.P = self.P.tocsr()

        # Create solver
        if self.use_pyamg:
            #start_time = time.time()
            self.ml = smoothed_aggregation_solver(
                self.P, B=None,
                strength=('symmetric', {'theta': 0.0}),
                smooth=(
                    'jacobi', {'filter': True, 'weighting': 'local'}),
                improve_candidates=[('block_gauss_seidel',
                                     {'sweep': 'symmetric', 'iterations': 4}),
                                    None, None, None, None, None, None, None,
                                    None, None, None, None, None, None, None],
                aggregate='standard',
                presmoother=('block_gauss_seidel',
                             {'sweep': 'symmetric', 'iterations': 1}),
                postsmoother=('block_gauss_seidel',
                              {'sweep': 'symmetric', 'iterations': 1}),
                max_levels=15,
                max_coarse=300,
                coarse_solver='pinv')
            #print('--- multi grid solver created in %s s ---' %
            #            (time.time() - start_time))

        return self.P
Example #4
0
    def _make_sparse_precon(self, atoms, initial_assembly=False,
                            force_stab=False):
        """Create a sparse preconditioner matrix based on the passed atoms.

        Creates a general-purpose preconditioner for use with optimization
        algorithms, based on examining distances between pairs of atoms in the
        lattice. The matrix will be stored in the attribute self.P and
        returned. Note that this function will use self.mu, whatever it is.

        Args:
            atoms: the Atoms object used to create the preconditioner.

        Returns:
            A scipy.sparse.csr_matrix object, representing a d*N by d*N matrix
            (where N is the number of atoms, and d is the value of self.dim).
            BE AWARE that using numpy.dot() with this object will result in
            errors/incorrect results - use the .dot method directly on the
            sparse matrix instead.

        """
#         print('creating sparse precon: initial_assembly=%r, '
#               'force_stab=%r, apply_positions=%r, apply_cell=%r' %
#                (initial_assembly, force_stab, self.apply_positions,
#                self.apply_cell))

        N = len(atoms)
        diag_i = np.arange(N, dtype=int)
        #start_time = time.time()
        if self.apply_positions:
            # compute neighbour list
            i, j, rij, fixed_atoms = get_neighbours(atoms, self.r_cut)
            #print('--- neighbour list created in %s s ---' %
            #            ((time.time() - start_time)))

            # compute entries in triplet format: without the constraints
            #start_time = time.time()
            coeff = self.get_coeff(rij)
            diag_coeff = np.bincount(i, -coeff, minlength=N).astype(np.float64)
            if force_stab or len(fixed_atoms) == 0:
                #print('adding stabilisation to preconditioner')
                diag_coeff += self.mu * self.c_stab
        else:
            diag_coeff = np.ones(N)

        # precon is mu_c*identity for cell DoF
        if isinstance(atoms, Filter):
            if self.apply_cell:
                diag_coeff[-3] = self.mu_c
                diag_coeff[-2] = self.mu_c
                diag_coeff[-1] = self.mu_c
            else:
                diag_coeff[-3] = 1.0
                diag_coeff[-2] = 1.0
                diag_coeff[-1] = 1.0
        #print('--- computed triplet format in %s s ---' %
        #            (time.time() - start_time))

        if self.apply_positions and not initial_assembly:
            # apply the constraints
            #start_time = time.time()
            mask = np.ones(N)
            mask[fixed_atoms] = 0.0
            coeff *= mask[i] * mask[j]
            diag_coeff[fixed_atoms] = 1.0
            #print('--- applied fixed_atoms in %s s ---' %
            #            (time.time() - start_time))

        if self.apply_positions:
            # remove zeros
            #start_time = time.time()
            inz = np.nonzero(coeff)
            i = np.hstack((i[inz], diag_i))
            j = np.hstack((j[inz], diag_i))
            coeff = np.hstack((coeff[inz], diag_coeff))
            #print('--- remove zeros in %s s ---' %
            #            (time.time() - start_time))
        else:
            i = diag_i
            j = diag_i
            coeff = diag_coeff

        # create the matrix
        #start_time = time.time()
        csc_P = sparse.csc_matrix((coeff, (i, j)), shape=(N, N))
        #print('--- created CSC matrix in %s s ---' %
        #            (time.time() - start_time))

        self.csc_P = csc_P

        #start_time = time.time()
        if self.dim == 1:
            self.P = csc_P
        elif self.array_convention == 'F':
            csc_P = csc_P.tocsr()
            self.P = csc_P
            for i in range(self.dim - 1):
                self.P = sparse.block_diag((self.P, csc_P)).tocsr()
        else:
            # convert back to triplet and read the arrays
            csc_P = csc_P.tocoo()
            i = csc_P.row * self.dim
            j = csc_P.col * self.dim
            z = csc_P.data

            # N-dimensionalise, interlaced coordinates
            I = np.hstack([i + d for d in range(self.dim)])
            J = np.hstack([j + d for d in range(self.dim)])
            Z = np.hstack([z for d in range(self.dim)])
            self.P = sparse.csc_matrix((Z, (I, J)),
                                       shape=(self.dim * N, self.dim * N))
            self.P = self.P.tocsr()
        #print('--- N-dim precon created in %s s ---' %
        #            (time.time() - start_time))

        # Create solver
        if self.use_pyamg and have_pyamg:
            #start_time = time.time()
            self.ml = smoothed_aggregation_solver(
                self.P, B=None,
                strength=('symmetric', {'theta': 0.0}),
                smooth=(
                    'jacobi', {'filter': True, 'weighting': 'local'}),
                improve_candidates=[('block_gauss_seidel',
                                     {'sweep': 'symmetric', 'iterations': 4}),
                                    None, None, None, None, None, None, None,
                                    None, None, None, None, None, None, None],
                aggregate='standard',
                presmoother=('block_gauss_seidel',
                             {'sweep': 'symmetric', 'iterations': 1}),
                postsmoother=('block_gauss_seidel',
                              {'sweep': 'symmetric', 'iterations': 1}),
                max_levels=15,
                max_coarse=300,
                coarse_solver='pinv')
            #print('--- multi grid solver created in %s s ---' %
            #            (time.time() - start_time))

        return self.P
Example #5
0
    def _make_sparse_precon(self, atoms, initial_assembly=False,
                            force_stab=False):
        """Create a sparse preconditioner matrix based on the passed atoms.

        Args:
            atoms: the Atoms object used to create the preconditioner.

        Returns:
            A scipy.sparse.csr_matrix object, representing a d*N by d*N matrix
            (where N is the number of atoms, and d is the value of self.dim).
            BE AWARE that using numpy.dot() with this object will result in
            errors/incorrect results - use the .dot method directly on the
            sparse matrix instead.

        """
        logger.info('creating sparse precon: initial_assembly=%r, '
                    'force_stab=%r, apply_positions=%r, apply_cell=%r',
                    initial_assembly, force_stab, self.apply_positions,
                    self.apply_cell)

        N = len(atoms)
        start_time = time.time()
        if self.apply_positions:
            # compute neighbour list
            i_list, j_list, rij_list, fixed_atoms = get_neighbours(
                atoms, self.r_cut)
            logger.info('--- neighbour list created in %s s ---' %
                        (time.time() - start_time))

        row = []
        col = []
        data = []

        # precon is mu_c*identity for cell DoF
        if isinstance(atoms, Filter):
            i = N - 3
            j = N - 2
            k = N - 1
            x = [3 * i, 3 * i + 1, 3 * i + 2, 3 * j, 3 *
                 j + 1, 3 * j + 2, 3 * k, 3 * k + 1, 3 * k + 2]
            row.extend(x)
            col.extend(x)
            if self.apply_cell:
                data.extend(np.repeat(self.mu_c, 9))
            else:
                data.extend(np.repeat(self.mu_c, 9))
        logger.info('--- computed triplet format in %s s ---' %
                    (time.time() - start_time))

        conn = sparse.lil_matrix((N, N), dtype=bool)

        if self.apply_positions and not initial_assembly:

            if self.morses is not None:

                for n in range(len(self.morses)):
                    if self.hessian == 'reduced':
                        i, j, Hx = ff.get_morse_potential_reduced_hessian(
                            atoms, self.morses[n])
                    elif self.hessian == 'spectral':
                        i, j, Hx = ff.get_morse_potential_hessian(
                            atoms, self.morses[n], spectral=True)
                    else:
                        raise NotImplementedError('Not implemented hessian')
                    x = [3 * i, 3 * i + 1, 3 * i + 2,
                         3 * j, 3 * j + 1, 3 * j + 2]
                    row.extend(np.repeat(x, 6))
                    col.extend(np.tile(x, 6))
                    data.extend(Hx.flatten())
                    conn[i, j] = True
                    conn[j, i] = True

            if self.bonds is not None:

                for n in range(len(self.bonds)):
                    if self.hessian == 'reduced':
                        i, j, Hx = ff.get_bond_potential_reduced_hessian(
                            atoms, self.bonds[n], self.morses)
                    elif self.hessian == 'spectral':
                        i, j, Hx = ff.get_bond_potential_hessian(
                            atoms, self.bonds[n], self.morses, spectral=True)
                    else:
                        raise NotImplementedError('Not implemented hessian')
                    x = [3 * i, 3 * i + 1, 3 * i + 2,
                         3 * j, 3 * j + 1, 3 * j + 2]
                    row.extend(np.repeat(x, 6))
                    col.extend(np.tile(x, 6))
                    data.extend(Hx.flatten())
                    conn[i, j] = True
                    conn[j, i] = True

            if self.angles is not None:

                for n in range(len(self.angles)):
                    if self.hessian == 'reduced':
                        i, j, k, Hx = ff.get_angle_potential_reduced_hessian(
                            atoms, self.angles[n], self.morses)
                    elif self.hessian == 'spectral':
                        i, j, k, Hx = ff.get_angle_potential_hessian(
                            atoms, self.angles[n], self.morses, spectral=True)
                    else:
                        raise NotImplementedError('Not implemented hessian')
                    x = [3 * i, 3 * i + 1, 3 * i + 2, 3 * j, 3 *
                         j + 1, 3 * j + 2, 3 * k, 3 * k + 1, 3 * k + 2]
                    row.extend(np.repeat(x, 9))
                    col.extend(np.tile(x, 9))
                    data.extend(Hx.flatten())
                    conn[i, j] = conn[i, k] = conn[j, k] = True
                    conn[j, i] = conn[k, i] = conn[k, j] = True

            if self.dihedrals is not None:

                for n in range(len(self.dihedrals)):
                    if self.hessian == 'reduced':
                        i, j, k, l, Hx = \
                            ff.get_dihedral_potential_reduced_hessian(
                                atoms, self.dihedrals[n], self.morses)
                    elif self.hessian == 'spectral':
                        i, j, k, l, Hx = ff.get_dihedral_potential_hessian(
                            atoms, self.dihedrals[n], self.morses,
                            spectral=True)
                    else:
                        raise NotImplementedError('Not implemented hessian')
                    x = [3 * i, 3 * i + 1, 3 * i + 2,
                         3 * j, 3 * j + 1, 3 * j + 2,
                         3 * k, 3 * k + 1, 3 * k + 2,
                         3 * l, 3 * l + 1, 3 * l + 2]
                    row.extend(np.repeat(x, 12))
                    col.extend(np.tile(x, 12))
                    data.extend(Hx.flatten())
                    conn[i, j] = conn[i, k] = conn[i, l] = conn[
                        j, k] = conn[j, l] = conn[k, l] = True
                    conn[j, i] = conn[k, i] = conn[l, i] = conn[
                        k, j] = conn[l, j] = conn[l, k] = True

        if self.apply_positions:
            for i, j, rij in zip(i_list, j_list, rij_list):
                if not conn[i, j]:
                    coeff = self.get_coeff(rij)
                    x = [3 * i, 3 * i + 1, 3 * i + 2]
                    y = [3 * j, 3 * j + 1, 3 * j + 2]
                    row.extend(x + x)
                    col.extend(x + y)
                    data.extend(3 * [-coeff] + 3 * [coeff])

        row.extend(range(self.dim * N))
        col.extend(range(self.dim * N))
        if initial_assembly:
            data.extend([self.mu * self.c_stab] * self.dim * N)
        else:
            data.extend([self.c_stab] * self.dim * N)

        # create the matrix
        start_time = time.time()
        self.P = sparse.csc_matrix(
            (data, (row, col)), shape=(self.dim * N, self.dim * N))
        logger.info('--- created CSC matrix in %s s ---' %
                    (time.time() - start_time))

        if not initial_assembly:
            if len(fixed_atoms) != 0:
                self.P.tolil()
            for i in fixed_atoms:
                self.P[i, :] = 0.0
                self.P[:, i] = 0.0
                self.P[i, i] = 1.0

        self.P = self.P.tocsr()

        # Create solver
        if self.use_pyamg and have_pyamg:
            start_time = time.time()
            self.ml = smoothed_aggregation_solver(
                self.P, B=None,
                strength=('symmetric', {'theta': 0.0}),
                smooth=(
                    'jacobi', {'filter': True, 'weighting': 'local'}),
                improve_candidates=[('block_gauss_seidel',
                                     {'sweep': 'symmetric', 'iterations': 4}),
                                    None, None, None, None, None, None, None,
                                    None, None, None, None, None, None, None],
                aggregate='standard',
                presmoother=('block_gauss_seidel',
                             {'sweep': 'symmetric', 'iterations': 1}),
                postsmoother=('block_gauss_seidel',
                              {'sweep': 'symmetric', 'iterations': 1}),
                max_levels=15,
                max_coarse=300,
                coarse_solver='pinv')
            logger.info('--- multi grid solver created in %s s ---' %
                        (time.time() - start_time))

        return self.P
Example #6
0
    def _make_sparse_precon(self, atoms, initial_assembly=False,
                            force_stab=False):
        """Create a sparse preconditioner matrix based on the passed atoms.

        Creates a general-purpose preconditioner for use with optimization
        algorithms, based on examining distances between pairs of atoms in the
        lattice. The matrix will be stored in the attribute self.P and
        returned. Note that this function will use self.mu, whatever it is.

        Args:
            atoms: the Atoms object used to create the preconditioner.

        Returns:
            A scipy.sparse.csr_matrix object, representing a d*N by d*N matrix
            (where N is the number of atoms, and d is the value of self.dim).
            BE AWARE that using numpy.dot() with this object will result in
            errors/incorrect results - use the .dot method directly on the
            sparse matrix instead.

        """
        logger.info('creating sparse precon: initial_assembly=%r, '
                    'force_stab=%r, apply_positions=%r, apply_cell=%r',
                    initial_assembly, force_stab, self.apply_positions,
                    self.apply_cell)

        N = len(atoms)
        diag_i = np.arange(N, dtype=int)
        start_time = time.time()
        if self.apply_positions:
            # compute neighbour list
            i, j, rij, fixed_atoms = get_neighbours(atoms, self.r_cut)
            logger.info('--- neighbour list created in %s s ---' %
                        (time.time() - start_time))

            # compute entries in triplet format: without the constraints
            start_time = time.time()
            coeff = self.get_coeff(rij)
            diag_coeff = np.bincount(i, -coeff, minlength=N).astype(np.float64)
            if force_stab or len(fixed_atoms) == 0:
                logger.info('adding stabilisation to preconditioner')
                diag_coeff += self.mu * self.c_stab
        else:
            diag_coeff = np.ones(N)

        # precon is mu_c*identity for cell DoF
        if isinstance(atoms, Filter):
            if self.apply_cell:
                diag_coeff[-3] = self.mu_c
                diag_coeff[-2] = self.mu_c
                diag_coeff[-1] = self.mu_c
            else:
                diag_coeff[-3] = 1.0
                diag_coeff[-2] = 1.0
                diag_coeff[-1] = 1.0
        logger.info('--- computed triplet format in %s s ---' %
                    (time.time() - start_time))

        if self.apply_positions and not initial_assembly:
            # apply the constraints
            start_time = time.time()
            mask = np.ones(N)
            mask[fixed_atoms] = 0.0
            coeff *= mask[i] * mask[j]
            diag_coeff[fixed_atoms] = 1.0
            logger.info('--- applied fixed_atoms in %s s ---' %
                        (time.time() - start_time))

        if self.apply_positions:
            # remove zeros
            start_time = time.time()
            inz = np.nonzero(coeff)
            i = np.hstack((i[inz], diag_i))
            j = np.hstack((j[inz], diag_i))
            coeff = np.hstack((coeff[inz], diag_coeff))
            logger.info('--- remove zeros in %s s ---' %
                        (time.time() - start_time))
        else:
            i = diag_i
            j = diag_i
            coeff = diag_coeff

        # create the matrix
        start_time = time.time()
        csc_P = sparse.csc_matrix((coeff, (i, j)), shape=(N, N))
        logger.info('--- created CSC matrix in %s s ---' %
                    (time.time() - start_time))

        self.csc_P = csc_P

        start_time = time.time()
        if self.dim == 1:
            self.P = csc_P
        elif self.array_convention == 'F':
            csc_P = csc_P.tocsr()
            self.P = csc_P
            for i in range(self.dim - 1):
                self.P = sparse.block_diag((self.P, csc_P)).tocsr()
        else:
            # convert back to triplet and read the arrays
            csc_P = csc_P.tocoo()
            i = csc_P.row * self.dim
            j = csc_P.col * self.dim
            z = csc_P.data

            # N-dimensionalise, interlaced coordinates
            I = np.hstack([i + d for d in range(self.dim)])
            J = np.hstack([j + d for d in range(self.dim)])
            Z = np.hstack([z for d in range(self.dim)])
            self.P = sparse.csc_matrix((Z, (I, J)),
                                       shape=(self.dim * N, self.dim * N))
            self.P = self.P.tocsr()
        logger.info('--- N-dim precon created in %s s ---' %
                    (time.time() - start_time))

        # Create solver
        if self.use_pyamg and have_pyamg:
            start_time = time.time()
            self.ml = smoothed_aggregation_solver(
                self.P, B=None,
                strength=('symmetric', {'theta': 0.0}),
                smooth=(
                    'jacobi', {'filter': True, 'weighting': 'local'}),
                improve_candidates=[('block_gauss_seidel',
                                     {'sweep': 'symmetric', 'iterations': 4}),
                                    None, None, None, None, None, None, None,
                                    None, None, None, None, None, None, None],
                aggregate='standard',
                presmoother=('block_gauss_seidel',
                             {'sweep': 'symmetric', 'iterations': 1}),
                postsmoother=('block_gauss_seidel',
                              {'sweep': 'symmetric', 'iterations': 1}),
                max_levels=15,
                max_coarse=300,
                coarse_solver='pinv')
            logger.info('--- multi grid solver created in %s s ---' %
                        (time.time() - start_time))

        return self.P
Example #7
0
morse_r0 = 1.4322
angle_k = 10.0
angle_a0 = np.deg2rad(120.0)
dihedral_k = 0.346
vdw_epsilonij = 0.0115
vdw_rminij = 3.4681

neighbor_list = [[] for _ in range(len(a))]
vdw_list = np.ones((len(a), len(a)), dtype=bool)
morses = []
angles = []
dihedrals = []
vdws = []

# create neighbor list
i_list, j_list, d_list, fixed_atoms = get_neighbours(atoms=a, r_cut=cutoff)
for i, j in zip(i_list, j_list):
    neighbor_list[i].append(j)
for i in range(len(neighbor_list)):
    neighbor_list[i].sort()

# create lists of morse, bending and torsion interactions
for i in range(len(a)):
    for jj in range(len(neighbor_list[i])):
        j = neighbor_list[i][jj]
        if j > i:
            morses.append(Morse(atomi=i, atomj=j, D=morse_D,
                                alpha=morse_alpha, r0=morse_r0))
        vdw_list[i, j] = vdw_list[j, i] = False
        for kk in range(jj + 1, len(neighbor_list[i])):
            k = neighbor_list[i][kk]