GMIN MOVES module
Introduction
Alongside the implementation of CUDA L-BFGS, we are currently in the process of re-working how GMIN takes 'steps', perturbing the coordinates before minimising during each quench. A document describing the current state of this project can be found on the group Google Drive here. If you do not have access, please request it.
The module itself is located here:
~/svn/GMIN/source/moves.f90
This page is intended to provide an outline for the re-implementation of existing GMIN moves within the new framework of the MOVES module, including appropriate sanity checks in the new GMIN SANITY module.
Design principles
The design of the new system is very simple and covered in detail in the working document. In short, a new parser is being developed by Kyle to allow the construction of a highly flexible move set. When a step is to be taken, this information is passed to a potential specific driver routine. This driver routine then modifies the coordinates using the subroutines in MOVES as appropriate.
Coding principles
In order to keep ourselves from repeating the mistakes of the past, we all need to keep to the following coding guidelines. Please make sure you have read and understood the following points. If you make commits which do not conform to these guidelines, they will be reverted.
- code blocks must be indented in a manner consistent with the rest of the module (3 spaces)
- variable names must be understandable e.g. MAX_STEP rather than S
- avoid using GOTOs!
- all subroutines must be fully commented (in English)
- all required and optional arguments must be fully explained
- every move routine must have an optional final argument ATOM_LIST to apply the move to a subset of atoms. See the example below
- only utility modules (e.g. VEC3) may be USE'd from MOVES. This does NOT include COMMONS
- no potential specific information may be required by any routine in MOVES - this should be dealt with in the driver routine
- move routines should NOT print anything outside of STOP messages - printing should come from the appropriate driver routines
- where appropriate, sanity checks (GMIN SANITY module) and tests (GMIN TESTS module) should be included in move routines
Example routine: CARTESIAN_SPHERE
As a working example of the principles of this rewrite, here is the implementation of James Farrell's spherically symmetric Cartesian move subroutine from TAKESTEP, now in the MOVES module. In particular, this demonstrates how to correctly implement the optional ATOM_LISTS argument and the sanity checks that should be used in every move routine:
SUBROUTINE CARTESIAN_SPHERE(XYZ, MAX_STEP, ATOM_LIST) ! Add a random spherically symmetric displacement of up to MAXSTEP to each atom ! in the ATOM_LIST array if present, or all atoms if not. ! ! Arguments ! --------- ! ! Required: ! XYZ(in/out): coordinates array from GMIN, in Cartesian coordinates ! MAX_STEP(in): the maximum step size ! ! Optional: ! ATOM_LIST(in): list of atoms to be moved - if omitted, all are moved ! The VEC3 module (vec3.f90) contains helper functions for handling vectors and matricies USE VEC3 ! The SANITY module contains sanity check functions USE SANITY IMPLICIT NONE INTEGER :: I INTEGER :: NUM_ATOMS INTEGER, OPTIONAL, DIMENSION(:), INTENT(IN) :: ATOM_LIST DOUBLE PRECISION :: DPRAND DOUBLE PRECISION, INTENT(IN) :: MAX_STEP DOUBLE PRECISION, DIMENSION(:), INTENT(INOUT) :: XYZ LOGICAL, ALLOCATABLE, DIMENSION(:) :: ATOM_MASK LOGICAL :: TEST ! Sanity check - are the coordinates in XYZ Cartesian? ! Check if the SIZE is a multiple of 3 TEST=.FALSE. TEST=CHECK_DIMENSION(SIZE(XYZ),3) IF (.NOT.TEST) THEN STOP 'Coordinates in a non-Cartesian basis passed to CARTESIAN_SPHERE' ENDIF ! Set NUM_ATOMS NUM_ATOMS = SIZE(XYZ) / 3 ! Set up ATOM_MASK ALLOCATE(ATOM_MASK(NUM_ATOMS)) ATOM_MASK = .FALSE. ! Check to see if an ATOM_LIST was provided IF (PRESENT(ATOM_LIST)) THEN ! If so, determine which atoms the move applies to and set up ATOM_MASK DO I = 1, SIZE(ATOM_LIST) ATOM_MASK(ATOM_LIST(I)) = .TRUE. END DO ELSE ! Otherwise, apply the move to all atoms ATOM_MASK = .TRUE. ENDIF ! Apply the move to the atoms specified DO I = 1, NUM_ATOMS ! Skip atoms we do not want to move IF (.NOT. ATOM_MASK(I)) CYCLE ! Otherwise apply the move XYZ(3*I-2:3*I)=XYZ(3*I-2:3*I)+VEC_RANDOM()*(DPRAND()**(1.0D0/3.0D0))*MAX_STEP ENDDO END SUBROUTINE CARTESIAN_SPHERE
Testing new moves
As this is still a work in progress and the parser and driver routines are not currently functioning, the only way to test new moves is via the use of the NEWMOVES keyword in GMIN. This bypasses all existing step-taking routines in MC and will let you call your test move directly as required. Here is an example of this from mc.F showing a call to the old GROUPROTATION and new CARTESIAN_SPHERE routines that we have been using to test CUDAGMIN:
! csw34> Temporary calls to new step taking routines for testing IF (NEWMOVEST) THEN ! GROUPROTATION moves are in here for testing CUDAGMIN only IF (GROUPROTT) CALL GROUPROTSTEP(JP) ! Each new move should take a final, optional argument - ATOM_LIST ! This is the list of atoms in a integer array to which you want to ! apply the move. CALL CARTESIAN_SPHERE(COORDS(:,JP),STEP(JP)) ! CALL CARTESIAN_SPHERE(COORDS(:,JP),STEP(JP),ATOM_LIST) ! CALL CARTESIAN_SIMPLE(COORDS(:,JP),STEP(JP)) ! CALL CARTESIAN_SIMPLE(COORDS(:,JP),STEP(JP),ATOM_LIST) ELSE ... ... OLD STEP TAKING FOLLOWS
Please feel free to modify this section of code as required to test your move routines, but do not delete anything without consulting the person who implemented it - just comment out anything you don't want to use while you test.
--Csw34 17:24, 14 April 2014 (UTC)