4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-1997
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://rugmd0.chem.rug.nl/~gmx
27 * Great Red Oystrich Makes All Chemists Sane
29 static char *SRCID_steep_c
= "$Id$";
64 static void sp_header(FILE *out
,real epot
,real fsqrt
,real step
,real ftol
)
66 fprintf(out
,"STEEPEST DESCENTS:\n");
67 fprintf(out
," Stepsize = %12.5e\n",step
);
68 fprintf(out
," Tolerance = %12.5e\n",ftol
);
69 fprintf(out
," Starting rmsF = %30.20e\n",fsqrt
);
70 fprintf(out
," Starting Energy = %30.20e\n",epot
);
73 static void sp_header(FILE *out
,real epot
,real step
,real ftol
)
75 fprintf(out
,"STEEPEST DESCENTS:\n");
76 fprintf(out
," Stepsize = %12.5e\n",step
);
77 fprintf(out
," Tolerance = %12.5e\n",ftol
);
78 fprintf(out
," Starting Energy = %30.20e\n",epot
);
83 int left
,int right
,int nprocs
,
84 int start
,int end
,rvec grad
[])
89 /* This routine finds the largest force component (abs value)
90 * and returns it. On parallel machines the global max is taken.
92 fmax
= fabs(grad
[start
][0]);
94 for(i
=start
; (i
<end
); i
++)
95 for(m
=0; (m
<DIM
); m
++) {
102 for(i
=0; (i
<nprocs
-1); i
++) {
103 gmx_tx(left
,(void *)&fmax
,sizeof(fmax
));
104 gmx_rx(right
,(void *)&fmax_0
,sizeof(fmax_0
));
105 gmx_wait(left
,right
);
113 real
f_norm(FILE *log
,
114 int left
,int right
,int nprocs
,
115 int start
,int end
,rvec grad
[])
120 /* This routine finds the norm of the force
121 * and returns it. Parallel machines not supported.
125 for(i
=start
; (i
<end
); i
++)
126 for(m
=0; (m
<DIM
); m
++) {
127 fnorm
=fnorm
+grad
[i
][m
]*grad
[i
][m
];
134 fatal_error(0,"This version of Steepest Descents cannot be run in parallel");
138 real
f_sqrt(FILE *log
,
139 int left
,int right
,int nprocs
,
140 int start
,int end
,rvec f
[])
146 /* this routine calculates the route mean square force */
150 /* calculate the sum of the square force of this processor */
151 for(i
=start
;(i
<end
);i
++)
153 fsqr
+= sqr(f
[i
][m
]);
157 return sqrt(fsqr
)/(end
- start
);
160 fatal_error(0,"This version of f_sqrt cannot run in parrallel");
163 return ( sqrt(fsqr
) );
166 static void do_step(int start
,int end
,rvec x
[],rvec f
[],
167 bool bRandom
,real step
)
169 static int seed
=1993;
174 fprintf(stderr
,"\rRandom step\n");
175 for(i
=start
; (i
<end
); i
++) {
176 for(m
=0; (m
<DIM
); m
++) {
178 x
[i
][m
]=x
[i
][m
]+step
*r
;
183 /* New positions to try */
184 for(i
=start
; (i
<end
);i
++)
185 for(m
=0; (m
<DIM
); m
++)
186 x
[i
][m
] = x
[i
][m
]+step
*f
[i
][m
];
190 time_t do_steep(FILE *log
,int nfile
,t_filenm fnm
[],
191 t_parm
*parm
,t_topology
*top
,
192 t_groups
*grps
,t_nsborder
*nsb
,
193 rvec x
[],rvec grad
[],rvec buf
[],t_mdatoms
*mdatoms
,
194 tensor ekin
,real ener
[],t_nrnb nrnb
[],
195 bool bVerbose
,bool bDummies
,t_commrec
*cr
,t_graph
*graph
,
196 t_forcerec
*fr
,rvec box_size
)
198 static char *SD
="STEEPEST DESCENTS";
199 real step
,lambda
,ftol
,fmax
;
200 rvec
*pos
[2],*force
[2];
206 real vcm
[4],fnorm
,ustep
;
210 bool bNS
=TRUE
,bDone
,bLR
,bLJLR
,bBHAM
,b14
;
212 tensor force_vir
,shake_vir
;
218 int steps_accepted
=0;
221 /* Initiate some variables */
223 lambda
= parm
->ir
.init_lambda
;
228 calc_shifts(parm
->box
,box_size
,fr
->shift_vec
,FALSE
);
230 vcm
[0]=vcm
[1]=vcm
[2]=vcm
[3]=0.0;
232 /* Print to log file */
233 start_t
=print_date_and_time(log
,cr
->pid
,"Started Steepest Descents");
235 /* We need two coordinate arrays and two force arrays */
236 for(i
=0; (i
<2); i
++) {
237 snew(pos
[i
],nsb
->natoms
);
238 snew(force
[i
],nsb
->natoms
);
241 start
=nsb
->index
[cr
->pid
];
242 end
=nsb
->homenr
[cr
->pid
]-start
;
244 /* Open the enrgy file */
246 fp_ene
=open_enx(ftp2fn(efENX
,nfile
,fnm
),"w");
250 /* Set some booleans for the epot routines */
251 set_pot_bools(&(parm
->ir
),top
,&bLR
,&bLJLR
,&bBHAM
,&b14
);
253 /* Init bin for energy stuff */
254 mdebin
=init_mdebin(fp_ene
,grps
,&(top
->atoms
),&(top
->idef
),bLR
,bLJLR
,
255 bBHAM
,b14
,parm
->ir
.bPert
,parm
->ir
.epc
,
258 /* Clear some matrix variables */
259 clear_mat(force_vir
);
260 clear_mat(shake_vir
);
262 /* Copy coord vectors to our temp array */
263 for(i
=0; (i
<nsb
->natoms
); i
++) {
264 copy_rvec(x
[i
],pos
[Min
][i
]);
265 copy_rvec(x
[i
],pos
[TRY
][i
]);
268 /* Set variables for stepsize (in nm). This is the largest
269 * step that we are going to make in any direction.
271 step
=ustep
=parm
->ir
.em_stepsize
;
273 /* Tolerance for conversion */
274 ftol
=parm
->ir
.em_tol
;
276 /* Max number of steps */
277 number_steps
=parm
->ir
.nsteps
;
280 /* Print to the screen */
281 start_t
=print_date_and_time(log
,cr
->pid
,"Started EM");
282 fprintf(stderr
,"STEEPEST DESCENTS:\n");
283 fprintf(log
,"STEEPEST DESCENTS:\n");
284 fprintf(stderr
," Tolerance = %12.5g\n",ftol
);
285 fprintf(log
," Tolerance = %12.5g\n",ftol
);
288 /* Here starts the loop, count is the counter for the number of steps
289 * bDone is a BOOLEAN variable, which will be set TRUE when
290 * the minimization has converged.
292 for(count
=0,bDone
=FALSE
;
293 !(bDone
|| ((number_steps
> 0) && (count
==number_steps
))); count
++) {
295 /* set new coordinates, except for first step */
297 for(i
=start
; (i
<end
); i
++)
299 pos
[TRY
][i
][m
] = pos
[Min
][i
][m
] + step
* force
[Min
][i
][m
];
302 /* Construct dummy particles */
303 shift_self(graph
,fr
->shift_vec
,pos
[TRY
]);
304 construct_dummies(log
,pos
[TRY
],&(nrnb
[cr
->pid
]),1,NULL
,&top
->idef
);
305 unshift_self(graph
,fr
->shift_vec
,pos
[TRY
]);
308 /* Calc force & energy on new positions */
309 do_force(log
,cr
,parm
,nsb
,force_vir
,
310 count
,&(nrnb
[cr
->pid
]),top
,grps
,pos
[TRY
],buf
,force
[TRY
],buf
,
311 mdatoms
,ener
,bVerbose
&& !(PAR(cr
)),
312 lambda
,graph
,bNS
,FALSE
,fr
);
313 unshift_self(graph
,fr
->shift_vec
,pos
[TRY
]);
315 /* Spread the force on dummy particle to the other particles... */
316 spread_dummy_f(log
,pos
[TRY
],force
[TRY
],&(nrnb
[cr
->pid
]),&top
->idef
);
318 /* Sum the potential energy terms from group contributions */
319 sum_epot(&(parm
->ir
.opts
),grps
,ener
);
321 /* Clear stuff again */
322 clear_mat(force_vir
);
323 clear_mat(shake_vir
);
325 /* Communicat stuff when parallel */
327 global_stat(log
,cr
,ener
,force_vir
,shake_vir
,
328 &(parm
->ir
.opts
),grps
,&mynrnb
,nrnb
,vcm
,mu_tot
);
330 /* This is the new energy */
332 Fsqrt
[TRY
]=f_sqrt(log
,cr
->left
,cr
->right
,nsb
->nprocs
,start
,end
,force
[TRY
]);
334 Epot
[TRY
]=ener
[F_EPOT
];
336 /* Print it if necessary */
338 if ((bVerbose
|| (Fsqrt
[TRY
] < Fsqrt
[Min
])) && MASTER(cr
)) {
340 "\rStep = %5d, Dx = %12.5e, Epot = %12.5e rmsF = %12.5e\n",
341 count
,step
,Epot
[TRY
],Fsqrt
[TRY
]);
342 /* Store the new (lower) energies */
343 upd_mdebin(mdebin
,mdatoms
->tmass
,count
,ener
,parm
->box
,shake_vir
,
344 force_vir
,parm
->vir
,parm
->pres
,grps
,mu_tot
);
345 /* Print the energies allways when we should be verbose */
347 print_ebin(fp_ene
,TRUE
,FALSE
,log
,count
,count
,lambda
,
348 0.0,eprNORMAL
,TRUE
,mdebin
,grps
,&(top
->atoms
));
351 if ((bVerbose
|| (Epot
[TRY
] < Epot
[Min
])) && MASTER(cr
)) {
352 fprintf(stderr
,"\rStep = %5d, Dx = %12.5e, E-Pot = %30.20e\n",
353 count
,step
,Epot
[TRY
]);
355 /* Store the new (lower) energies */
356 upd_mdebin(mdebin
,mdatoms
->tmass
,count
,ener
,parm
->box
,shake_vir
,
357 force_vir
,parm
->vir
,parm
->pres
,grps
);
358 /* Print the energies allways when we should be verbose */
360 print_ebin(fp_ene
,log
,count
,count
,lambda
,0.0,eprNORMAL
,TRUE
,
361 mdebin
,grps
,&(top
->atoms
));
365 /* Now if the new energy is smaller than the previous...
366 * or if this is the first step!
367 * or if we did random steps!
371 if ( (count
==0) || (Fsqrt
[TRY
] < Fsqrt
[Min
]) ) {
373 if ( (count
==0) || (Epot
[TRY
] < Epot
[Min
]) ) {
376 if (do_per_step(steps_accepted
,parm
->ir
.nstfout
))
380 if (do_per_step(steps_accepted
,parm
->ir
.nstxout
)) {
382 write_traj(log
,cr
,ftp2fn(efTRN
,nfile
,fnm
),
383 nsb
,count
,(real
) count
,
384 lambda
,nrnb
,nsb
->natoms
,xx
,NULL
,ff
,parm
->box
);
388 /* Test whether the convergence criterion is met... */
390 bDone
=(Fsqrt
[TRY
] < ftol
);
392 /* Stop when the difference between two tries is less than
393 * the tolerance times the energy.
395 bDone
=(fabs(Epot
[Min
]-Epot
[TRY
]) < ftol
*fabs(Epot
[Min
]));
398 /* Copy the arrays for force, positions and energy */
399 /* The 'Min' array always holds the coords and forces of the minimal
403 /* increase step size */
408 fprintf(stderr,"\n"); */
411 /* If energy is not smaller make the step smaller... */
418 /* Determine new step */
419 fnorm
= f_norm(log
,cr
->left
,cr
->right
,nsb
->nprocs
,start
,end
,force
[Min
]);
422 } /* End of the loop */
424 /* Print some shit... */
426 fprintf(stderr
,"\nwriting lowest energy coordinates.\n");
429 write_traj(log
,cr
,ftp2fn(efTRN
,nfile
,fnm
),
430 nsb
,count
,(real
) count
,
431 lambda
,nrnb
,nsb
->natoms
,xx
,NULL
,ff
,parm
->box
);
432 write_sto_conf(ftp2fn(efSTO
,nfile
,fnm
),
433 *top
->name
, &(top
->atoms
),xx
,NULL
,parm
->box
);
435 fmax
=f_max(log
,cr
->left
,cr
->right
,nsb
->nprocs
,start
,end
,force
[Min
]);
436 fprintf(stderr
,"Maximum force: %12.5e\n",fmax
);
438 fprintf(stderr
,"\n%s converged to %8.6f \n",SD
,ftol
);
439 fprintf(log
,"%s converged to %8.6f \n",SD
,ftol
);
442 fprintf(stderr
,"\n%s did not converge in %d steps\n",SD
,number_steps
);
443 fprintf(log
,"%s did not converge in %d steps\n",SD
,number_steps
);
446 fprintf(stderr
," Minimum Root Mean Square Force = %12.4e\n",Fsqrt
[Min
]);
447 fprintf(log
," Minimum Root Mean Square Force = %12.4e\n",Fsqrt
[Min
]);
449 fprintf(stderr
," Function value at minimum = %12.4e\n",Epot
[Min
]);
450 fprintf(log
," Function value at minimum = %12.4e\n",Epot
[Min
]);
455 /* Put the coordinates back in the x array (otherwise the whole
456 * minimization would be in vain)
458 for(i
=0; (i
<nsb
->natoms
); i
++)
459 copy_rvec(pos
[Min
][i
],x
[i
]);
461 /* To print the actual number of steps we needed somewhere */
462 parm
->ir
.nsteps
=count
;
465 } /* That's all folks */