├── .gitignore ├── README.md ├── fixing_lattice_matrix └── cell_relax.patch └── fixing_stress_tensor ├── stress_relax.patch └── stress_relax_finner.patch /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore generated html files, 2 | constr_cell_relax.F 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VASP OPT AXIS 2 | This project provides patches enabling the ability to fix lattice vector component(s)/stress tensor component(s) during relaxation in VASP. 3 | 4 | __PLEASE READ THROUGH THIS FILE BEFORE PROCEED__ 5 | 6 | ## Stress tensor method 7 | This method is forked from [muchong](http://muchong.com/html/201107/3427823_2.html) and modified upon. 8 | 9 | The lattice vectors are updated after each SCF loop by following formula (you can find codes similar to the following in `dyna.F`): 10 | 11 | ``` 12 | DO J=1,3 13 | DO I=1,3 14 | A(I,J)=AC(I,J) 15 | DO K=1,3 16 | A(I,J)=A(I,J) + SSIF(I,K)*AC(K,J)*STEP 17 | ENDDO 18 | ENDDO 19 | ENDDO 20 | ``` 21 | 22 | Where `SSIF` is the (scaled) stress tensor (note that fortran uses Column-major order), `A` is the lattice vector matrix and `STEP` is the step size. 23 | 24 | __NOTE: This means that fixing the stress tensor elements does not necessarily fix the corresponding lattice components.__ 25 | 26 | ### Fixing only the diagonal term 27 | 28 | Put `stress_relax.patch` file in the root directory of your VASP distro. and type: 29 | ``` 30 | $ patch -p0 < stress_relax.patch 31 | ``` 32 | and recompile VASP. 33 | 34 | This patch lets VASP read a file called `OPTCELL` after each SCF loop and use the info inside to determine which diagonal stress component(s) to fix. 35 | 36 | `OPTCELL` file format: 37 | 38 | ``` 39 | xx yy zz 40 | ``` 41 | 42 | For example: 43 | ``` 44 | 1 1 0 45 | ``` 46 | will fix `zz` component of the stress tensor. 47 | 48 | Note that for this patch we can only fix the diagonal stress tensor element(s) so it's better suited for orthorhombic cell or at least lattice vector that is perpendicular to other lattice vectors. 49 | 50 | Also note that `ISIF=3` is needed for lattice relaxation. 51 | 52 | ### Fixing specific stress tensor element(s) 53 | 54 | Put `stress_relax_finner.patch` file in the root directory of your VASP distro. and type: 55 | ``` 56 | $ patch -p0 < stress_relax_finner.patch 57 | ``` 58 | and recompile VASP. 59 | 60 | This patch lets VASP read `IOPTCELL` tag directly from `INCAR`. 61 | 62 | `IOPTCELL` format: 63 | 64 | ``` 65 | IOPTCELL = xx yx zx xy yy zy xz yz zz 66 | ``` 67 | for example: 68 | ``` 69 | IOPTCELL = 1 1 0 1 1 0 0 0 0 70 | ``` 71 | will relax the `xx`, `xy`, `yx` and `yy` components of the stress tensor, while keeping the other components fixed (to zero). 72 | 73 | ## Direct fixing of the lattice method 74 | __WARNINIG: this method only works with `IBRION=2` and may induce numerical instabilities.__ 75 | 76 | This patch enables direct fixing of the lattice. 77 | 78 | This is achieved by re-assigning the original value of the lattice elements after each geometry updates of the conjugate gradient step. (modification made in `dyna.F`) 79 | 80 | Also, the stress tensor is modified to reduce instabilities introduced by direct fixing. (modification made in `constr_cell_relax.F`). 81 | 82 | To use this method: 83 | 84 | Put `cell_relax.patch` file in the root directory of your VASP distro. and type: 85 | ``` 86 | $ patch -p0 < cell_relax.patch 87 | ``` 88 | and recompile VASP. 89 | 90 | This patch lets VASP read `IOPTCELL` tag directly from `INCAR`. 91 | 92 | `IOPTCELL` format: 93 | 94 | ``` 95 | IOPTCELL = xx xy xz yx yy yz zx zy zz 96 | ``` 97 | for example: 98 | ``` 99 | IOPTCELL = 1 1 0 1 1 0 0 0 0 100 | ``` 101 | will relax the `xx`, `xy`, `yx` and `yy` components of the lattice matrix, while keeping the other components fixed. 102 | It will also fix the `xz`, `yz`, `zx`, `zy` and `zz` components of the stress tensor. 103 | 104 | ## Disclaimer 105 | 106 | *1. VASP is a commercial package, be sure you have a proper license to use it. 107 | 108 | *2. The correctness of this patch has been checked with few simple cases. However, this is not guaranteed to work for your specific system. Make sure you KNOW WHAT YOU ARE DOING! 109 | -------------------------------------------------------------------------------- /fixing_lattice_matrix/cell_relax.patch: -------------------------------------------------------------------------------- 1 | diff -ru src/constr_cell_relax.F ../../vasp.5.4.4/src/constr_cell_relax.F 2 | --- src/constr_cell_relax.F 2017-04-20 10:03:55.000000000 +0100 3 | +++ ../../vasp.5.4.4/src/constr_cell_relax.F 2021-05-06 14:37:13.460464000 +0100 4 | @@ -24,20 +24,59 @@ 5 | ! 6 | !----------------------------------------------------------------------- 7 | 8 | - SUBROUTINE CONSTR_CELL_RELAX(FCELL) 9 | + SUBROUTINE CONSTR_CELL_RELAX(IU5,IU0,FCELL) 10 | USE prec 11 | + IMPLICIT NONE 12 | REAL(q) FCELL(3,3) 13 | 14 | -! just one simple example 15 | -! relaxation in x directions only 16 | -! SAVE=FCELL(1,1) 17 | -! FCELL=0 ! F90 style: set the whole array to zero 18 | -! FCELL(1,1)=SAVE 19 | -! relaxation in z direction only 20 | -! SAVE=FCELL(3,3) 21 | -! FCELL=0 ! F90 style: set the whole array to zero 22 | -! FCELL(3,3)=SAVE 23 | + INTEGER IU5,IU0 24 | + ! local variables 25 | + INTEGER N, IERR, I, J 26 | + REAL(q) RDUM 27 | + COMPLEX(q) CDUM 28 | + LOGICAL LDUM 29 | + CHARACTER (1) :: CHARAC 30 | + 31 | + LOGICAL IOPTCELL 32 | + INTEGER :: ICELL(9)=1, IST(9)=1 33 | + 34 | + OPEN(UNIT=IU5,FILE="INCAR",STATUS='OLD') 35 | + 36 | + IOPTCELL=.FALSE. 37 | + CALL RDATAB(.FALSE.,"INCAR",IU5,'IOPTCELL','=','#',';','I', & 38 | + & ICELL,RDUM,CDUM,LDUM,CHARAC,N,9,IERR) 39 | + IF (((IERR/=0).AND.(IERR/=3)).OR. & 40 | + & ((IERR==0).AND.(N<1))) THEN 41 | + IF (IU0>=0) & 42 | + WRITE(IU0,*)'Error reading item ''IOPTCELL'' from file INCAR.' 43 | + ICELL(6)=1 44 | + ENDIF 45 | + 46 | + ! WRITE(*,*) ICELL 47 | + ! set logical 48 | + IF (ANY(ICELL .NE. (/1,1,1,1,1,1,1,1,1/) )) THEN 49 | + IOPTCELL=.TRUE. 50 | + ENDIF 51 | + CLOSE(IU5) 52 | + 53 | + ! IF (IU0>=0) WRITE(IU0,*) 'stress:', FCELL(1,2) 54 | + IF (IOPTCELL) THEN 55 | + DO I=1,3 56 | + ! only change stress tensor to zero if we are fixing 57 | + ! say for example x components of all lattice vectors. 58 | + IF (ICELL(0+I)==0 .AND. ICELL(3+I)==0 .AND. ICELL(6+I)==0) THEN 59 | + IST(0+I)=0 60 | + IST(3+I)=0 61 | + IST(6+I)=0 62 | + FCELL(I,1)=0.0 63 | + FCELL(I,2)=0.0 64 | + FCELL(I,3)=0.0 65 | + ENDIF 66 | + ENDDO 67 | + ! '(X,A,3I3,A,3I3,A,3I3)' 68 | + IF (IU0>=0) WRITE(IU0,'(X,A,3I3,A,3I3,A,3I3)') 'Constraining stress:',& 69 | + & IST(1:3), ' |', IST(4:6), ' |', IST(7:9) 70 | + ENDIF 71 | 72 | RETURN 73 | END SUBROUTINE 74 | - 75 | diff -ru src/dyna.F ../../vasp.5.4.4/src/dyna.F 76 | --- src/dyna.F 2017-04-20 10:03:56.000000000 +0100 77 | +++ ../../vasp.5.4.4/src/dyna.F 2021-05-07 08:04:02.912253000 +0100 78 | @@ -561,7 +561,7 @@ 79 | !********************************************************************* 80 | 81 | SUBROUTINE IONCGR(IFLAG,NIONS,TOTEN,A,B,NFREE,POSION,POSIOC, & 82 | - & FACT,F,FACTSI,FSIF,FL,S,DISMAX,IU6,IU0, & 83 | + & FACT,F,FACTSI,FSIF,FL,S,DISMAX,IU5,IU6,IU0, & 84 | & EBREAK,EDIFFG,E1TEST,LSTOP2) 85 | USE prec 86 | USE lattice 87 | @@ -586,6 +586,39 @@ 88 | DATA ICOUNT/0/, ICOUNT2/0/, STEP /1._q/,SNORM/1E-10_q/ 89 | DATA LTRIAL/.FALSE./ 90 | 91 | + ! CCX: add to fix cell 92 | + ! local variables 93 | + INTEGER IERR 94 | + REAL(q) RDUM 95 | + COMPLEX(q) CDUM 96 | + LOGICAL LDUM 97 | + CHARACTER (1) :: CHARAC 98 | + 99 | + LOGICAL IOPTCELL 100 | + INTEGER :: ICELL(9)=1 101 | + 102 | + OPEN(UNIT=IU5,FILE="INCAR",STATUS='OLD') 103 | + 104 | + IOPTCELL=.FALSE. 105 | + CALL RDATAB(.FALSE.,"INCAR",IU5,'IOPTCELL','=','#',';','I', & 106 | + & ICELL,RDUM,CDUM,LDUM,CHARAC,N,9,IERR) 107 | + IF (((IERR/=0).AND.(IERR/=3)).OR. & 108 | + & ((IERR==0).AND.(N<1))) THEN 109 | + IF (IU0>=0) & 110 | + WRITE(IU0,*)'Error reading item ''IOPTCELL'' from file INCAR.' 111 | + ICELL(6)=1 112 | + ENDIF 113 | + 114 | + IF (ANY(ICELL .NE. (/1,1,1,1,1,1,1,1,1/) )) THEN 115 | + IOPTCELL=.TRUE. 116 | + IF (IU0>=0) WRITE(IU0,'(X,A,3I3,A,3I3,A,3I3)') 'Constraining cell :',& 117 | + &ICELL(1:3),' |',ICELL(4:6),' |',ICELL(7:9) 118 | + ENDIF 119 | + CLOSE(IU5) 120 | + ! CCX: end modification 121 | + 122 | + 123 | + 124 | !======================================================================= 125 | ! if IFLAG =0 initialize everything 126 | !======================================================================= 127 | @@ -805,6 +838,10 @@ 128 | DO K=1,3 129 | A(I,J)=A(I,J) + SSIF(I,K)*AC(K,J)*STEP 130 | ENDDO 131 | + ! CCX: modify to fix lattice elements 132 | + IF (ICELL((J-1)*3+I)==0) A(I,J)=AC(I,J) 133 | + ! IF (IU0>=0) WRITE(IU0,*) I, ' ', J, ' ', SSIF(I,J) 134 | + ! IF (IU0>=0) WRITE(IU0,*) 'doing something' 135 | ENDDO 136 | ENDDO 137 | 138 | @@ -951,6 +988,10 @@ 139 | DO K=1,3 140 | A(I,J)=A(I,J) + SSIF(I,K)*AC(K,J)*DMOVE*STEP 141 | ENDDO 142 | + ! CCX: modify to fix lattice elements 143 | + IF (ICELL((J-1)*3+I)==0) A(I,J)=AC(I,J) 144 | + ! IF (IU0>=0) WRITE(IU0,*) I, ' ', J, ' ', AC(I,J), A(I,J), SSIF(I,J) 145 | + ! IF (IU0>=0) WRITE(IU0,*) 'doing something' 146 | ENDDO 147 | ENDDO 148 | DMOVEL=DMOVE 149 | diff -ru src/main.F ../../vasp.5.4.4/src/main.F 150 | --- src/main.F 2017-04-20 10:03:58.000000000 +0100 151 | +++ ../../vasp.5.4.4/src/main.F 2021-05-05 23:49:36.649065000 +0100 152 | @@ -3556,7 +3556,7 @@ 153 | ENDDO 154 | ENDIF 155 | 156 | - CALL CONSTR_CELL_RELAX(D2SIF) 157 | + CALL CONSTR_CELL_RELAX(IO%IU5,IO%IU0,D2SIF) 158 | 159 | IF (FACTSI/=0) THEN 160 | DO I=1,3 161 | @@ -3613,7 +3613,7 @@ 162 | IF ( LHYPER_NUDGE() ) EACC=1E10 ! energy not very accurate, use only force 163 | 164 | CALL IONCGR(IFLAG,T_INFO%NIONS,TOTEN,LATT_CUR%A,LATT_CUR%B,DYN%NFREE,DYN%POSION,DYN%POSIOC, & 165 | - FACT,DYN%D2C,FACTSI,D2SIF,DYN%D2,DYN%D3,DISMAX,IO%IU6,IO%IU0, & 166 | + FACT,DYN%D2C,FACTSI,D2SIF,DYN%D2,DYN%D3,DISMAX,IO%IU5,IO%IU6,IO%IU0, & 167 | EACC,DYN%EDIFFG,E1TEST,LSTOP2) 168 | ! if IFLAG=1 new trial step -> reinit of waveprediction 169 | INFO%LSTOP=.FALSE. 170 | -------------------------------------------------------------------------------- /fixing_stress_tensor/stress_relax.patch: -------------------------------------------------------------------------------- 1 | diff -ruN src/constr_cell_relax.F src_mod/constr_cell_relax.F 2 | --- src/constr_cell_relax.F 2017-04-20 17:03:55.000000000 +0800 3 | +++ src_mod/constr_cell_relax.F 2018-05-20 20:04:25.000000000 +0800 4 | @@ -25,8 +25,24 @@ 5 | !----------------------------------------------------------------------- 6 | 7 | SUBROUTINE CONSTR_CELL_RELAX(FCELL) 8 | - USE prec 9 | - REAL(q) FCELL(3,3) 10 | + USE PREC 11 | + REAL(Q) FCELL(3,3), SAVE(3) 12 | + LOGICAL FILFLG 13 | + INTEGER ICELL(3) 14 | + 15 | + INQUIRE(FILE='OPTCELL',EXIST=FILFLG) 16 | + IF (FILFLG) THEN 17 | + OPEN(67,FILE='OPTCELL',FORM='FORMATTED',STATUS='OLD') 18 | + READ(67,"(3I1)") (ICELL(I),I=1,3) 19 | + CLOSE(67) 20 | + DO I=1,3 21 | + SAVE(I)=FCELL(I,I) 22 | + ENDDO 23 | + FCELL=0.0d0 24 | + DO I=1,3 25 | + IF (ICELL(I)==1) FCELL(I,I)=SAVE(I) 26 | + ENDDO 27 | + ENDIF 28 | 29 | ! just one simple example 30 | ! relaxation in x directions only 31 | -------------------------------------------------------------------------------- /fixing_stress_tensor/stress_relax_finner.patch: -------------------------------------------------------------------------------- 1 | diff --color -bruN src/constr_cell_relax.F ../vasp.5.4.4_mod/src/constr_cell_relax.F 2 | --- src/constr_cell_relax.F 2017-04-20 10:03:55.000000000 +0100 3 | +++ ../vasp.5.4.4_mod/src/constr_cell_relax.F 2020-07-27 22:47:25.028165323 +0100 4 | @@ -24,10 +24,19 @@ 5 | ! 6 | !----------------------------------------------------------------------- 7 | 8 | - SUBROUTINE CONSTR_CELL_RELAX(FCELL) 9 | + SUBROUTINE CONSTR_CELL_RELAX(IU5,IU0,FCELL) 10 | USE prec 11 | + IMPLICIT NONE 12 | REAL(q) FCELL(3,3) 13 | 14 | + INTEGER IU5,IU0 15 | + ! local variables 16 | + INTEGER IDUM, N, IERR, I, J 17 | + REAL(q) RDUM 18 | + COMPLEX(q) CDUM 19 | + LOGICAL LOPEN,LDUM 20 | + CHARACTER (1) :: CHARAC 21 | + 22 | ! just one simple example 23 | ! relaxation in x directions only 24 | ! SAVE=FCELL(1,1) 25 | @@ -38,6 +47,39 @@ 26 | ! FCELL=0 ! F90 style: set the whole array to zero 27 | ! FCELL(3,3)=SAVE 28 | 29 | + LOGICAL IOPTCELL 30 | + INTEGER :: ICELL(9)=1 31 | + 32 | + LOPEN=.FALSE. 33 | + OPEN(UNIT=IU5,FILE="INCAR",STATUS='OLD') 34 | + 35 | + IOPTCELL=.FALSE. 36 | + CALL RDATAB(.FALSE.,"INCAR",IU5,'IOPTCELL','=','#',';','I', & 37 | + & ICELL,RDUM,CDUM,LDUM,CHARAC,N,9,IERR) 38 | + IF (((IERR/=0).AND.(IERR/=3)).OR. & 39 | + & ((IERR==0).AND.(N<1))) THEN 40 | + IF (IU0>=0) & 41 | + WRITE(IU0,*)'Error reading item ''IOPTCELL'' from file INCAR.' 42 | + ICELL(6)=1 43 | + ENDIF 44 | + 45 | + ! WRITE(*,*) ICELL 46 | + ! set logical 47 | + IF (ANY(ICELL .NE. (/1,1,1,1,1,1,1,1,1/) )) THEN 48 | + IOPTCELL=.TRUE. 49 | + !IF (IU0>=0) WRITE(IU0,'(X,A,I1,I1,I1,I1,I1,I1,I1,I1,I1)') 'Constraining cell:',ICELL(1),ICELL(2),ICELL(3),ICELL(4),ICELL(5),ICELL(6),ICELL(7),ICELL(8),ICELL(9) 50 | + IF (IU0>=0) WRITE(IU0,'(X,A,3I3,A,3I3,A,3I3)') 'Constraining cell:',ICELL(1:3),' |',ICELL(4:6),' |',ICELL(7:9) 51 | + ENDIF 52 | + CLOSE(IU5) 53 | + 54 | + IF (IOPTCELL) THEN 55 | + DO J=1,3 56 | + DO I=1,3 57 | + IF (ICELL((I-1)*3+J)==0) FCELL(I,J)=0.0 58 | + ENDDO 59 | + ENDDO 60 | + ENDIF 61 | + 62 | RETURN 63 | END SUBROUTINE 64 | 65 | diff --color -bruN src/main.F ../vasp.5.4.4_mod/src/main.F 66 | --- src/main.F 2017-04-20 10:03:58.000000000 +0100 67 | +++ ../vasp.5.4.4_mod/src/main.F 2020-07-27 22:48:46.484544288 +0100 68 | @@ -3556,7 +3556,7 @@ 69 | ENDDO 70 | ENDIF 71 | 72 | - CALL CONSTR_CELL_RELAX(D2SIF) 73 | + CALL CONSTR_CELL_RELAX(IO%IU5,IO%IU0,D2SIF) 74 | 75 | IF (FACTSI/=0) THEN 76 | DO I=1,3 77 | --------------------------------------------------------------------------------