An electric field term (Cython part) — MMTK User Guide 2.7.7 documentation

### Navigation

- index
- modules |
- MMTK User Guide 2.7.7 documentation »

# An electric field term (Cython part)

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    # Example for a forcefield implementation in Cython.

    #
    # Get all the required declarations
    #
    include "MMTK/python.pxi"
    include "MMTK/numeric.pxi"
    include "MMTK/core.pxi"
    include "MMTK/universe.pxi"
    include 'MMTK/forcefield.pxi'

    #
    # The force field term implementation.
    # The rules:
    #
    # - The class must inherit from EnergyTerm.
    #
    # - EnergyTerm.__init__() must be called with the arguments
    #   shown here. The third argument is the name of the EnergyTerm
    #   object, the fourth a tuple of the names of all the terms it
    #   implements (one object can implement several terms).
    #   The assignment to self.eval_func is essential, without it
    #   any energy evaluation will crash.
    #
    # - The function "evaluate" must have exactly the parameter
    #   list from this example.
    #
    cdef class ElectricFieldTerm(EnergyTerm):

        cdef ArrayType charges
        cdef vector3 strength

        def __init__(self, universe, charges, strength):
            EnergyTerm.__init__(self, universe,
                                "electric_field", ("electric_field",))
            self.eval_func = <void *>ElectricFieldTerm.evaluate
            self.charges = charges
            self.strength[0] = strength[0]
            self.strength[1] = strength[1]
            self.strength[2] = strength[2]

        # The function evaluate is called for every single energy
        # evaluation and should therefore be optimized for speed.
        # Its first argument is the global energy evaluator object,
        # which is needed only for parallelized energy terms.
        # The second argument is a C structure that contains all the
        # input data, in particular the particle configuration.
        # The third argument is a C structure that contains the
        # energy term fields and gradient arrays for storing the results.
        # For details, see MMTK_forcefield.pxi.
        cdef void evaluate(self, EnergyEvaluator eval,
                           energy_spec *input, energy_data *energy):
            cdef vector3 *coordinates, *gradients
            cdef double *q
            cdef double e
            cdef int natoms, i

            coordinates = <vector3 *>input.coordinates.data
            natoms = input.coordinates.dimensions[0]
            q = <double *>self.charges.data

            energy.energy_terms[self.index] = 0.
            if energy.gradients != NULL:
                gradients = <vector3 *>(<PyArrayObject *> energy.gradients).data

            for i from 0 <= i < natoms:
                e = q[i]*(self.strength[0]*coordinates[i][0]
                          + self.strength[1]*coordinates[i][1]
                          + self.strength[2]*coordinates[i][2])
                energy.energy_terms[self.index] = \
                                    energy.energy_terms[self.index] + e
                energy.energy_terms[self.virial_index] = \
                                    energy.energy_terms[self.virial_index] - e
                if energy.gradients != NULL:
                    gradients[i][0] += q[i]*self.strength[0]
                    gradients[i][1] += q[i]*self.strength[1]
                    gradients[i][2] += q[i]*self.strength[2]

### Navigation

- index
- modules |
- MMTK User Guide 2.7.7 documentation »