-
Notifications
You must be signed in to change notification settings - Fork 0
/
asepmd.F90
378 lines (292 loc) · 10.4 KB
/
asepmd.F90
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
!##############################################################################
!# Copyright 2011,2012 Ignacio Fdez. Galván, M. Luz Sánchez, #
!# Aurora Muñoz Losa, M. Elena Martín, Manuel A. Aguilar #
!# #
!# ASEP-MD 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. #
!# #
!# ASEP-MD 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 ASEP-MD. If not, see <http://www.gnu.org/licenses/>. #
!##############################################################################
PROGRAM ASEPMD
USE Parametros
USE Entrada
USE Moldy
USE Malla
USE Cavidad
USE Configuraciones
USE Sistema
USE Ejecutar
USE Optimizacion
USE Utilidades
USE UtilidadesFis
IMPLICIT NONE
DOUBLE PRECISION, DIMENSION(:), ALLOCATABLE :: Potencial,ASEP
DOUBLE PRECISION, DIMENSION(:,:), ALLOCATABLE :: CargasAjustadas
DOUBLE PRECISION, DIMENSION(4) :: ErrAjuste
DOUBLE PRECISION, DIMENSION(2) :: IntMD
DOUBLE PRECISION :: EnergiaAnt,CargaTotal
INTEGER :: U,i,Iter,Num,NumCargas,Error
!>>> Iniciar datos
EnergiaAnt=0.0D0
IntMD(:)=0.0D0
!>>> Leer la entrada
CALL EscribirTitulo()
CALL LeerEntrada(5)
CALL EscribirValores()
SELECT CASE (ProgramaMM)
CASE (0) !Genérico
U=NuevaUnidad()
OPEN(U,FILE=TRIM(EntradaMM),ACTION='READ',STATUS='OLD')
CALL LeerSistemaGenerico(U)
CLOSE(U)
!Si no se usa Moldy, sólo se centra la molécula
CALL OrientarMolecula(Soluto(:),-1)
CALL OrientarMolecula(Disolvente(:),-1)
CALL OrientarMolecula(Disolvente2(:),-1)
CASE (1) !Moldy
U=NuevaUnidad()
OPEN(U,FILE=TRIM(EntradaMM),ACTION='READ',STATUS='OLD')
CALL LeerControlMoldy(U)
CLOSE(U)
U=NuevaUnidad()
OPEN(U,FILE=TRIM(MoldyInput),ACTION='READ',STATUS='OLD')
CALL LeerSistemaMoldy(U)
CLOSE(U)
CALL OrientarMolecula(Soluto(:),0)
CALL OrientarMolecula(Disolvente(:),0)
CALL OrientarMolecula(Disolvente2(:),0)
END SELECT
!>>> Cálculo cuántico inicial
Iter=0
WRITE(Extension,*) Iter
Extension='.cic.'//ADJUSTL(Extension)
IF (ALLOCATED(MolQM)) DEALLOCATE(MolQM)
ALLOCATE(MolQM(SIZE(Soluto,1)))
MolQM=Soluto
IF (InicioVacio) THEN
CALL EjecutarQM(0)
Soluto=MolQM
CALL EscribirASEPMD()
ELSE
ALLOCATE(DisolvQM(0,5),PotQM(0,4))
END IF
!>>> Empieza el ciclo ASEP/MD
DO Iter=Inicio,MaxIter
WRITE(Extension,*) Iter
Extension='.cic.'//ADJUSTL(Extension)
EnergiaAnt=EnergiaQM+EnergiaVdW
!>>> Generar la "cavidad" para el soluto y las cargas explícitas del disolvente
CALL GenerarCavidad
!>>> Lanzar la dinámica
CALL EjecutarMM(.TRUE.)
CALL Promedios(0,Soluto) !Abre el fichero UConf
IntMD(1)=EnergiaEMM
IntMD(2)=EnergiaVdW
!>>> Calcular el potencial promedio y cargas explícitas
CALL MallaMolecula(Soluto,MallaSoluto)
CALL PotencialYCargas
!>>> Ajustar las cargas externas
CALL AjusteCargasExternas
!>>> Cálculo cuántico con disolvente
IF (MaxIterOpt > 0) THEN
U=NuevaUnidad()
OPEN(U,FILE=TRIM(SalidaOpt)//TRIM(Extension),ACTION='WRITE',STATUS='REPLACE')
CALL OptimizarGeometria(Soluto,U)
CLOSE(U)
IF (ProgramaMM == 1) THEN
CALL OrientarMolecula(Soluto(:),0)
ELSE
!Si no se usa Moldy, sólo se centra la molécula
CALL OrientarMolecula(Soluto(:),-1)
END IF
ELSE
IF (ALLOCATED(MolQM)) DEALLOCATE(MolQM)
ALLOCATE(MolQM(SIZE(Soluto,1)))
MolQM=Soluto
CALL EjecutarQM(0)
Soluto=MolQM
END IF
CALL CerrarUConf()
CALL EscribirASEPMD()
END DO
!>>> Escribe el sistema final (útil para las cargas del soluto)
Extension='.final'
CALL EjecutarMM(.FALSE.)
CONTAINS
! Escribe la cabecera en la salida
SUBROUTINE EscribirTitulo
#ifndef LANG
#define LANG Espanol
#endif
USE LANG
INTEGER :: i
DO i=1,SIZE(Titulo)
WRITE(6,101) TRIM(Titulo(i))
END DO
WRITE(6,*)
101 FORMAT(A)
END SUBROUTINE EscribirTitulo
! Escribe los datos correspondientes de un ciclo ASEP/MD
SUBROUTINE EscribirASEPMD
#ifndef LANG
#define LANG Espanol
#endif
USE LANG
WRITE(6,*)
WRITE(6,101) TRIM(Textos(8)),Iter
WRITE(6,20)
IF (Iter > 0) THEN
WRITE(6,100) TRIM(Textos(24))
WRITE(6,10)
WRITE(6,103) TRIM(Textos(26)),IntMD(1),'Eh'
WRITE(6,104) '',IntMD(1)/KcalmolAtomica,'kcal/mol'
WRITE(6,103) TRIM(Textos(27)),IntMD(2),'Eh'
WRITE(6,104) '',IntMD(2)/KcalmolAtomica,'kcal/mol'
WRITE(6,*)
WRITE(6,100) TRIM(Textos(33))
WRITE(6,10)
WRITE(6,105) TRIM(Textos(34)),NumCargas
WRITE(6,105) TRIM(Textos(35)),SIZE(CargasDisolvente,1)
WRITE(6,105) TRIM(Textos(40)),SIZE(ASEP,1)
WRITE(6,106) TRIM(Textos(36)),ErrAjuste(1)
WRITE(6,106) TRIM(Textos(37)),ErrAjuste(2),'Eh/e'
WRITE(6,106) TRIM(Textos(38)),ErrAjuste(3)
WRITE(6,106) TRIM(Textos(39)),ErrAjuste(4),'Eh/e'
END IF
WRITE(6,*)
WRITE(6,100) TRIM(Textos(25))
WRITE(6,10)
WRITE(6,102) TRIM(Textos(23)),EnergiaQM,'Eh'
IF (Iter > 0) THEN
WRITE(6,102) TRIM(Textos(29)),EnergiaQM+EnergiaVdW,'Eh'
WRITE(6,102) TRIM(Textos(30)),EnergiaQM+EnergiaVdW-EnergiaAnt,'Eh'
END IF
WRITE(6,103) TRIM(Textos(28)),SQRT(SUM(DipoloQM(:)*DipoloQM(:))),'e*a0'
WRITE(6,104) '',SQRT(SUM(DipoloQM(:)*DipoloQM(:)))/DebyeAtomica,'D'
IF (Iter > 0) THEN
WRITE(6,103) TRIM(Textos(31)),EnergiaEQM,'Eh'
WRITE(6,104) '',EnergiaEQM/KcalmolAtomica,'kcal/mol'
WRITE(6,103) TRIM(Textos(26)),EnergiaEMM,'Eh'
WRITE(6,104) '',EnergiaEMM/KcalmolAtomica,'kcal/mol'
WRITE(6,103) TRIM(Textos(27)),EnergiaVdW,'Eh'
WRITE(6,104) '',EnergiaVdW/KcalmolAtomica,'kcal/mol'
WRITE(6,102) TRIM(Textos(32)),EnergiaQM-EnergiaEQM,'Eh'
END IF
WRITE(6,20)
10 FORMAT(80('-'))
20 FORMAT(80('='))
100 FORMAT(T10,A)
101 FORMAT(A,1X,I3)
102 FORMAT(A,T54,F18.10,1X,A)
103 FORMAT(A,T50,'/',T54,F18.10,1X,A)
104 FORMAT(A,T50,'\',T54,F18.10,1X,A)
105 FORMAT(T15,A,T64,I8,1X,A)
106 FORMAT(T15,A,T54,F18.10,1X,A)
END SUBROUTINE
! Construye la "cavidad" y calcula las posiciones de las cargas ajustadas en la
! superficie
SUBROUTINE GenerarCavidad
DOUBLE PRECISION, DIMENSION(:,:), ALLOCATABLE :: Esf
! Según el tipo de cavidad, se define el número y tamaño adecuado de
! las esferas que forman la cavidad
IF (TipoCavidad == 0) THEN
ALLOCATE(Esf(1,4))
Esf(1,:)=(/0.0D0,0.0D0,0.0D0,RadioCavidad/)
ELSE
ALLOCATE(Esf(SIZE(Soluto,1),4))
DO i=1,SIZE(Esf,1)
Esf(i,1:3)=Soluto(i)%pos(:)
IF (TipoCavidad == 1) THEN
Esf(i,4)=RadiosVdW(Soluto(i)%z)
ELSE
Esf(:,4)=1.0D0
END IF
END DO
Esf(:,4)=RadioCavidad*Esf(:,4)
END IF
! Una superficie un poco más grande donde se sitúan las cargas ajustadas
! (en dos capas)
CALL ConstruirCavidad(Esf(:,1:3),Esf(:,4)+RadioDisolvente,RadioDisolvente, &
Subdivisiones)
IF (ALLOCATED(CargasAjustadas)) DEALLOCATE(CargasAjustadas)
ALLOCATE(CargasAjustadas(SIZE(CavVert,1)+SIZE(CavCent,1),4))
! Las caras están más cerca
CargasAjustadas(1:SIZE(CavCent,1),1:3)=CavCent(:,1:3)
! Los vértices, que son menos, están más lejos
CALL ConstruirCavidad(Esf(:,1:3),Esf(:,4)+2.0D0*RadioDisolvente,RadioDisolvente, &
Subdivisiones)
CargasAjustadas(SIZE(CavCent,1)+1:,1:3)=CavVert(:,1:3)
! Otra final, para separarar las moléculas que están dentro, y es la
! que permanece en el resto del cálculo
CALL ConstruirCavidad(Esf(:,1:3),Esf(:,4),RadioDisolvente)
DEALLOCATE(Esf)
END SUBROUTINE GenerarCavidad
! Calcula el potencial sobre el soluto y las cargas del disolvente
SUBROUTINE PotencialYCargas
DOUBLE PRECISION, DIMENSION(3) :: Pos
INTEGER :: Utmp,i,j
IF (ALLOCATED(Potencial)) DEALLOCATE(Potencial)
IF (ALLOCATED(ASEP)) DEALLOCATE(ASEP)
ALLOCATE(Potencial(SIZE(MallaSoluto,1)),ASEP(SIZE(MallaSoluto,1)))
Utmp=NuevaUnidad()
OPEN(Utmp,STATUS='SCRATCH',ACTION='READWRITE',FORM='UNFORMATTED')
U=NuevaUnidad()
ASEP(:)=0.0D0
Num=0
NumCargas=0
CALL AbrirUConf()
DO
CALL LeerConfig(Error)
IF (Error /= 0) EXIT
CALL PotencialMM(MallaSoluto,Potencial)
ASEP(:)=ASEP(:)+Potencial(:)
CALL SeleccionarMols(Utmp,NumCargas)
Num=Num+1
END DO
CALL ReducirCargas(Utmp,NumCargas,CargasDisolvente)
CargasDisolvente(:,4)=CargasDisolvente(:,4)/DBLE(Num)
! Se hacen cero las cargas explícitas que están muy cerca de las ajustadas
DO i=1,SIZE(CargasDisolvente,1)
Pos=CargasDisolvente(i,1:3)
DO j=1,SIZE(CargasAjustadas,1)
IF (Distancia(Pos(:),CargasAjustadas(j,1:3)) < DistCargas) THEN
CargasDisolvente(i,4)=0.0D0
EXIT
END IF
END DO
END DO
CALL PotencialCargas(CargasDisolvente(:,:),MallaSoluto(:,:),Potencial(:))
ASEP(:)=ASEP(:)/DBLE(Num)
CLOSE(Utmp)
END SUBROUTINE PotencialYCargas
! Calcula el valor de las cargas del disolvente por ajuste al potencial sobre
! el soluto
SUBROUTINE AjusteCargasExternas
DOUBLE PRECISION, DIMENSION(:,:), ALLOCATABLE :: Pot
ALLOCATE(Pot(SIZE(ASEP),4))
Pot(:,1:3)=MallaSoluto(:,1:3)
Pot(:,4)=ASEP(:)-Potencial(:)
CargaTotal=SUM(CargasDisolvente(:,4))+SUM(MolQM(:)%q)
CALL AjusteCargas(CargasAjustadas(:,1:3),Pot(:,:),-CargaTotal, &
CargasAjustadas(:,4),ErrAjuste(1:3),1.0D-6)
Pot(:,4)=Potencial(:)
CALL PotencialCargas(CargasAjustadas(:,:),MallaSoluto(:,:),Potencial(:))
Potencial(:)=Potencial(:)+Pot(:,4)
ErrAjuste(4)=MAXVAL(ABS(Potencial(:)-ASEP(:)))
DEALLOCATE(Pot)
IF (ALLOCATED(DisolvQM)) DEALLOCATE(DisolvQM)
Num=SIZE(CargasAjustadas,1)+SIZE(CargasDisolvente,1)
ALLOCATE(DisolvQM(Num,5))
DisolvQM(1:SIZE(CargasAjustadas,1),1:4)=CargasAjustadas(:,:)
DisolvQM(SIZE(CargasAjustadas,1)+1:,1:4)=CargasDisolvente(:,:)
DisolvQM(:,5)=0.0D0
END SUBROUTINE AjusteCargasExternas
END PROGRAM ASEPMD