Skip to content

Commit

Permalink
Merge pull request #44 from tovrstra/comlist
Browse files Browse the repository at this point in the history
First attempt at center of mass layer in ForcePartValence
  • Loading branch information
tovrstra authored Apr 1, 2018
2 parents ac1bb4b + 2c68f3a commit 83c8ae1
Show file tree
Hide file tree
Showing 9 changed files with 456 additions and 5 deletions.
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,14 @@
ext_modules=[
Extension("yaff.pes.ext",
sources=['yaff/pes/ext.pyx', 'yaff/pes/nlist.c',
'yaff/pes/pair_pot.c', 'yaff/pes/ewald.c',
'yaff/pes/pair_pot.c', 'yaff/pes/ewald.c', 'yaff/pes/comlist.c',
'yaff/pes/dlist.c', 'yaff/pes/grid.c', 'yaff/pes/iclist.c',
'yaff/pes/vlist.c', 'yaff/pes/cell.c',
'yaff/pes/truncation.c', 'yaff/pes/slater.c'],
depends=['yaff/pes/nlist.h', 'yaff/pes/nlist.pxd',
'yaff/pes/pair_pot.h', 'yaff/pes/pair_pot.pxd',
'yaff/pes/ewald.h', 'yaff/pes/ewald.pxd',
'yaff/pes/comlist.h', 'yaff/pes/comlist.pxd',
'yaff/pes/dlist.h', 'yaff/pes/dlist.pxd',
'yaff/pes/grid.h', 'yaff/pes/grid.pxd',
'yaff/pes/iclist.h', 'yaff/pes/iclist.pxd',
Expand Down
1 change: 1 addition & 0 deletions yaff/pes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"""

from yaff.pes.ext import *
from yaff.pes.comlist import *
from yaff.pes.dlist import *
from yaff.pes.iclist import *
from yaff.pes.vlist import *
Expand Down
75 changes: 75 additions & 0 deletions yaff/pes/comlist.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// YAFF is yet another force-field code.
// Copyright (C) 2011 Toon Verstraelen <Toon.Verstraelen@UGent.be>,
// Louis Vanduyfhuys <Louis.Vanduyfhuys@UGent.be>, Center for Molecular Modeling
// (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise
// stated.
//
// This file is part of YAFF.
//
// YAFF is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// YAFF is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://www.gnu.org/licenses/>
//
// --


#include "comlist.h"


void comlist_forward(dlist_row_type* deltas, double *pos, double* compos, long* comsizes,
comlist_row_type* comtab, long ncom) {
int icom;
for (icom = 0; icom < ncom; icom++) {
double cx = 0, cy = 0, cz = 0;
long i0 = (*comtab).i;
double wtot = (*comtab).w;
int i;
comtab++;
for (i = *comsizes - 2; i >= 0; i--) {
cx += (*comtab).w*(*deltas).dx;
cy += (*comtab).w*(*deltas).dy;
cz += (*comtab).w*(*deltas).dz;
deltas++;
comtab++;
}
comsizes++;
compos[icom*3] = cx/wtot + pos[i0*3];
compos[icom*3 + 1] = cy/wtot + pos[i0*3 + 1];
compos[icom*3 + 2] = cz/wtot + pos[i0*3 + 2];
}
}

void comlist_back(dlist_row_type* deltas, double *gpos, double* gcompos, long* comsizes,
comlist_row_type* comtab, long ncom) {
int icom;
for (icom = 0; icom < ncom; icom++) {
long i0 = (*comtab).i;
double wtot = (*comtab).w;
double gcx = gcompos[3*icom];
double gcy = gcompos[3*icom + 1];
double gcz = gcompos[3*icom + 2];
int i;
comtab++;
gpos[3*i0] += gcx;
gpos[3*i0 + 1] += gcy;
gpos[3*i0 + 2] += gcz;
for (i = *comsizes - 2; i >= 0; i--) {
double wratio = (*comtab).w/wtot;
(*deltas).gx += gcx*wratio;
(*deltas).gy += gcy*wratio;
(*deltas).gz += gcz*wratio;
deltas++;
comtab++;
}
comsizes++;
}
}
40 changes: 40 additions & 0 deletions yaff/pes/comlist.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// YAFF is yet another force-field code.
// Copyright (C) 2011 Toon Verstraelen <Toon.Verstraelen@UGent.be>,
// Louis Vanduyfhuys <Louis.Vanduyfhuys@UGent.be>, Center for Molecular Modeling
// (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise
// stated.
//
// This file is part of YAFF.
//
// YAFF is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// YAFF is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://www.gnu.org/licenses/>
//
// --


#ifndef YAFF_COMLIST_H
#define YAFF_COMLIST_H

#include "dlist.h"

typedef struct {
long i; // atom or relative vector index.
double w; // group or atom weight
} comlist_row_type;

void comlist_forward(dlist_row_type* deltas, double *pos, double* compos, long* comsizes,
comlist_row_type* comtab, long ncom);
void comlist_back(dlist_row_type* deltas, double *gpos, double* gcompos, long* comsizes,
comlist_row_type* comtab, long ncom);

#endif
36 changes: 36 additions & 0 deletions yaff/pes/comlist.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
# YAFF is yet another force-field code.
# Copyright (C) 2011 Toon Verstraelen <Toon.Verstraelen@UGent.be>,
# Louis Vanduyfhuys <Louis.Vanduyfhuys@UGent.be>, Center for Molecular Modeling
# (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise
# stated.
#
# This file is part of YAFF.
#
# YAFF is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# YAFF is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>
#
# --


cimport dlist

cdef extern from "comlist.h":
ctypedef struct comlist_row_type:
long i
double w

void comlist_forward(dlist.dlist_row_type* deltas, double *pos, double* compos,
long* comsizes, comlist_row_type* comtab, long ncom)
void comlist_back(dlist.dlist_row_type* deltas, double *gpos, double* gcompos,
long* comsizes, comlist_row_type* comtab, long ncom)
102 changes: 102 additions & 0 deletions yaff/pes/comlist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# -*- coding: utf-8 -*-
# YAFF is yet another force-field code.
# Copyright (C) 2011 Toon Verstraelen <Toon.Verstraelen@UGent.be>,
# Louis Vanduyfhuys <Louis.Vanduyfhuys@UGent.be>, Center for Molecular Modeling
# (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise
# stated.
#
# This file is part of YAFF.
#
# YAFF is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# YAFF is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>
#
# --
"""Valence interactions between centers of mass."""


import numpy as np

from yaff.pes.ext import delta_dtype, dlist_forward, dlist_back, comlist_dtype, \
comlist_forward, comlist_back


__all__ = ['COMList']


class COMList(object):
"""Center of Mass List."""

def __init__(self, system, groups):
"""Initialize a COMList
Parameters
----------
system : yaff.system.System
An object describing the atomistic system.
groups : list of (indices, weights) arrays.
Each item is a tuple with first an array of atom indices for who the center
of mass is to be computed and second an array with weights, used for the
center of mass of these atoms. Weights do not have to add up to one but they
should be positive (not checked).
"""
self.system = system
self.cell = self.system.cell
self.groups = groups

self.pos = np.zeros((len(groups), 3), float)
self.gpos = np.zeros((len(groups), 3), float)

self.comsizes = np.array([len(iatoms) for iatoms, weights in groups], dtype=int)
# natom is the number of centers of mass. This is confusing but necessary because
# we need to mimic the API of the system object.
self.natom = len(self.comsizes)

# Centers of mass are computed from relative vectors because some groups may
# be split over unit cell boundaries. On each relative vector, the minimum
# image convention is applied before computing weighted averages.
ndelta = self.comsizes.sum() - len(self.comsizes)
self.deltas = np.zeros(ndelta, delta_dtype)
self.comtab = np.zeros(self.comsizes.sum(), comlist_dtype)
idelta = 0
icom = 0
for iatoms, weights in groups:
# The first record in a group contains the reference atom and the total weight
# of the group.
self.comtab[icom]['i'] = iatoms[0]
self.comtab[icom]['w'] = weights.sum()
icom += 1
for iatom, weight in zip(iatoms[1:], weights[1:]):
self.deltas[idelta]['i'] = iatoms[0]
self.deltas[idelta]['j'] = iatom
# Subsquent records in one group then contain indices of relative vectors
# and weights of the corresponding atoms.
self.comtab[icom]['i'] = idelta
self.comtab[icom]['w'] = weight
idelta += 1
icom += 1

def forward(self):
"""Evaluate the relative vectors for ``self.system.pos``
The actual computation is carried out by a low-level C routine.
"""
dlist_forward(self.system.pos, self.system.cell, self.deltas, len(self.deltas))
comlist_forward(self.deltas, self.system.pos, self.pos, self.comsizes, self.comtab)

def back(self, gpos, vtens):
"""Derive gpos and virial from the derivatives towards the relative vectors
The actual computation is carried out by a low-level C routine.
"""
comlist_back(self.deltas, gpos, self.gpos, self.comsizes, self.comtab)
dlist_back(gpos, vtens, self.deltas, len(self.deltas))
93 changes: 93 additions & 0 deletions yaff/pes/ext.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ cimport cell
cimport nlist
cimport pair_pot
cimport ewald
cimport comlist
cimport dlist
cimport iclist
cimport vlist
Expand All @@ -58,6 +59,7 @@ __all__ = [
'PairPotEiSlater1sp1spCorr', 'PairPotOlpSlater1s1s','PairPotChargeTransferSlater1s1s',
'compute_ewald_reci', 'compute_ewald_reci_dd', 'compute_ewald_corr_dd',
'compute_ewald_corr',
'comlist_dtype', 'comlist_forward', 'comlist_back',
'delta_dtype', 'dlist_forward', 'dlist_back',
'iclist_dtype', 'iclist_forward', 'iclist_back',
'vlist_dtype', 'vlist_forward', 'vlist_back',
Expand Down Expand Up @@ -2553,6 +2555,97 @@ def compute_ewald_corr_dd(np.ndarray[double, ndim=2] pos,
)


#
# COM list
#


cdef comlist.comlist_row_type _comlist_row_tmp
comlist_dtype = np.asarray(<comlist.comlist_row_type[:1]>(&_comlist_row_tmp)).dtype


def comlist_forward(np.ndarray[dlist.dlist_row_type, ndim=1] deltas not None,
np.ndarray[double, ndim=2] pos not None,
np.ndarray[double, ndim=2] compos not None,
np.ndarray[long, ndim=1] comsizes not None,
np.ndarray[comlist.comlist_row_type, ndim=1] comtab not None):
'''Compute centers of masses of groups, taking into account periodic boundaries.
**Arguments:**
deltas
The delta list array
pos
The atomic positions. numpy array with shape (natom, 3).
compos
The center of mass positions. numpy array with shape (ncom, 3).
comsizes
The size of each group for which the center of mass is computed.
comtab
Indices and weights used to compute the center of mass.
'''
assert deltas.flags['C_CONTIGUOUS']
assert pos.flags['C_CONTIGUOUS']
assert pos.shape[1] == 3
assert compos.flags['C_CONTIGUOUS']
assert compos.shape[1] == 3
assert comsizes.flags['C_CONTIGUOUS']
assert comtab.flags['C_CONTIGUOUS']
comlist.comlist_forward(
<dlist.dlist_row_type*>deltas.data,
<double*>pos.data,
<double*>compos.data,
<long*>comsizes.data,
<comlist.comlist_row_type*>comtab.data,
len(comsizes))


def comlist_back(np.ndarray[dlist.dlist_row_type, ndim=1] deltas not None,
np.ndarray[double, ndim=2] gpos not None,
np.ndarray[double, ndim=2] gcompos not None,
np.ndarray[long, ndim=1] comsizes not None,
np.ndarray[comlist.comlist_row_type, ndim=1] comtab not None):
'''The back-propagation step of the delta list
**Arguments:**
deltas
The delta list array
gpos
The derivatives of the energy w.r.t. atomic positions. numpy array with shape
(natom, 3). (adding to output only)
gcompos
The derivatives of the energy w.r.t. the center of mass positions. numpy array
with shape (ncom, 3).
comsizes
The size of each group for which the center of mass is computed.
comtab
Indices and weights used to compute the center of mass.
'''
assert deltas.flags['C_CONTIGUOUS']
assert gpos.flags['C_CONTIGUOUS']
assert gpos.shape[1] == 3
assert gcompos.flags['C_CONTIGUOUS']
assert gcompos.shape[1] == 3
assert comsizes.flags['C_CONTIGUOUS']
assert comtab.flags['C_CONTIGUOUS']
comlist.comlist_back(
<dlist.dlist_row_type*>deltas.data,
<double*>gpos.data,
<double*>gcompos.data,
<long*>comsizes.data,
<comlist.comlist_row_type*>comtab.data,
len(comsizes))


#
# Delta list
#
Expand Down
Loading

0 comments on commit 83c8ae1

Please sign in to comment.