Line data Source code
1 : !!****m* ABINIT/predict_ga
2 : !! NAME
3 : !! predict_ga
4 : !!
5 : !! FUNCTION
6 : !! Given a given set of images, which represent a population, it predicts a new set of images.
7 : !! The implementation is based on a Genetic Algorithm idea, where the best fit candidates are passed
8 : !! to the next generation. Those are chosen from ga_opt_percent% best fit and (1-ga_opt_percent)% from Genetic rules
9 : !!
10 : !! COPYRIGHT
11 : !! Copyright (C) 2009-2026 ABINIT group (XG, AHR)
12 : !! This file is distributed under the terms of the
13 : !! GNU General Public License, see ~abinit/COPYING
14 : !! or http://www.gnu.org/copyleft/gpl.txt .
15 : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
16 : !!
17 : !! INPUTS
18 : !! itimimage=time index for image propagation (itimimage+1 is to be predicted here)
19 : !! itimimage_eff=time index in the history
20 : !! list_dynimage(nimage)=list of dynamical images.
21 : !! This is quite useful when ground states of the A and B states is known
22 : !! natom=dimension of vel_timimage and xred_timimage
23 : !! ndynimage=number of dynamical images
24 : !! nimage= population size
25 : !! ntimimage_stored=number of time steps stored in the history
26 : !!
27 : !! OUTPUT
28 : !!
29 : !! SIDE EFFECTS
30 : !! results_img(ntimimage_stored,nimage)=datastructure that holds the history of previous computations.
31 : !! results_img(:,:)%acell(3)
32 : !! at input, history of the values of acell for all images
33 : !! at output, the predicted values of acell for all images
34 : !! results_img(:,:)%results_gs
35 : !! at input, history of the values of energies and forces for all images
36 : !! results_img(:,:)%rprim(3,3)
37 : !! at input, history of the values of rprim for all images
38 : !! at output, the predicted values of rprim for all images
39 : !! results_img(:,:)%vel(3,natom)
40 : !! at input, history of the values of vel for all images
41 : !! at output, the predicted values of vel for all images
42 : !! results_img(:,:)%vel_cell(3,3)
43 : !! at input, history of the values of vel_cell for all images
44 : !! at output, the predicted values of vel_cell for all images
45 : !! results_img(:,:)%xred(3,natom)
46 : !! at input, history of the values of xred for all images
47 : !! at output, the predicted values of xred for all images
48 : !!
49 : !! SOURCE
50 :
51 : #if defined HAVE_CONFIG_H
52 : #include "config.h"
53 : #endif
54 :
55 : #include "abi_common.h"
56 :
57 : MODULE m_use_ga
58 :
59 : use defs_basis
60 : use m_abicore
61 : use m_ga
62 : use m_sort
63 :
64 : use m_symfind, only : symfind, symanal, symlatt
65 : use m_geometry, only : mkradim, mkrdim, metric, dist2
66 : use m_results_img, only : results_img_type,gather_array_img
67 : use m_numeric_tools, only : uniformrandom
68 :
69 : implicit none
70 :
71 : private
72 :
73 : public :: predict_ga
74 :
75 : CONTAINS
76 :
77 4 : subroutine predict_ga(itimimage_eff,idum,ga_param,natom,nimage,&
78 4 : & ntimimage_stored,results_img)
79 :
80 : !Arguments ------------------------------------
81 : !scalars
82 : integer,intent(in) :: itimimage_eff,natom,nimage,ntimimage_stored
83 : integer,intent(inout) :: idum
84 : !arrays
85 : type(results_img_type) :: results_img(nimage,ntimimage_stored)
86 : type(ga_type),intent(inout) :: ga_param
87 :
88 : !Local variables------------------------------
89 : !scalars
90 : integer :: ii,jj,kk,itmp,iimage,indiv,oper,iparent1,iparent2,ndimen
91 : integer :: next_itimimage,nsurvivor,nspinor
92 : !character(len=500) :: message
93 : !arrays
94 4 : integer,allocatable :: ieperm(:),ihperm(:),ibgoptperm(:,:),ibgperm(:,:)
95 4 : integer,allocatable :: zperm1(:),zperm2(:)
96 : real(dp) :: gprimd(3,3),rmet(3,3),gmet(3,3)
97 : real(dp) :: rprimdparent1(3,3),rprimdparent2(3,3)
98 : real(dp) :: rprimson1(3,3),rprimson2(3,3)
99 : real(dp) :: rprimdson1(3,3),rprimdson2(3,3)
100 : real(dp) :: acellson1(3),acellson2(3)
101 8 : real(dp) :: son1(3,natom),son2(3,natom)
102 8 : real(dp) :: parent1(3,natom),parent2(3,natom)
103 : ! store the energy and the enthalpy of all elements of the population
104 4 : real(dp),allocatable :: etotal_img(:),enthalpy_img(:),bg_img(:,:),bg_opt_img(:,:)
105 4 : real(dp),allocatable :: acell(:,:),acell_old(:,:),rprim(:,:,:),rprim_old(:,:,:),rprimd(:,:,:)
106 4 : real(dp),allocatable :: fitness(:),zcoor1(:),zcoor2(:)
107 4 : real(dp),allocatable :: coor(:,:),coor_old(:,:)
108 4 : real(dp),allocatable :: vson1(:),vson2(:)
109 :
110 : !real quantities
111 : real(dp) :: denom,sumH,Hmin,Hmax,ucvol,rtmp(3,3)
112 :
113 : ! *************************************************************************
114 :
115 : !DEBUG
116 : !write(std_out,*)' MODULE predict_ga : enter '
117 : !ENDDEBUG
118 :
119 : ! gen dimension
120 :
121 4 : ndimen=3*natom
122 4 : nspinor=results_img(nimage,itimimage_eff)%nsppol
123 :
124 16 : ABI_MALLOC(coor,(ndimen,nimage))
125 12 : ABI_MALLOC(coor_old,(ndimen,nimage))
126 12 : ABI_MALLOC(acell,(3,nimage))
127 8 : ABI_MALLOC(acell_old,(3,nimage))
128 12 : ABI_MALLOC(rprim,(3,3,nimage))
129 8 : ABI_MALLOC(rprimd,(3,3,nimage))
130 8 : ABI_MALLOC(rprim_old,(3,3,nimage))
131 :
132 12 : ABI_MALLOC(zperm1,(natom))
133 8 : ABI_MALLOC(zperm2,(natom))
134 12 : ABI_MALLOC(ieperm,(nimage))
135 8 : ABI_MALLOC(ihperm,(nimage))
136 16 : ABI_MALLOC(ibgperm,(nspinor,nimage))
137 12 : ABI_MALLOC(ibgoptperm,(nspinor,nimage))
138 :
139 12 : ABI_MALLOC(etotal_img,(nimage))
140 8 : ABI_MALLOC(enthalpy_img,(nimage))
141 :
142 : !to store locally the calculated band gaps
143 16 : ABI_MALLOC(bg_img,(nspinor,nimage))
144 12 : ABI_MALLOC(bg_opt_img,(nspinor,nimage))
145 :
146 8 : ABI_MALLOC(fitness,(nimage))
147 :
148 12 : ABI_MALLOC(zcoor1,(natom))
149 8 : ABI_MALLOC(zcoor2,(natom))
150 12 : ABI_MALLOC(vson1,(ndimen))
151 8 : ABI_MALLOC(vson2,(ndimen))
152 :
153 44 : call initialize_perm(ieperm,nimage)
154 8 : call initialize_perm(ihperm,nimage)
155 8 : do ii=1,nspinor
156 8 : call initialize_perm(ibgperm(ii,:),nimage)
157 12 : call initialize_perm(ibgoptperm(ii,:),nimage)
158 : enddo
159 :
160 : !from gs_results_image take energies, rprim and acell and build energy and enthalpy vectors reordered from larger to smaller
161 :
162 44 : do iimage=1,nimage
163 40 : etotal_img(iimage)=results_img(iimage,itimimage_eff)%results_gs%etotal
164 40 : call convert_coortogen(results_img(iimage,itimimage_eff)%xred(:,:),coor_old(:,iimage),natom)
165 160 : acell_old(:,iimage)=results_img(iimage,itimimage_eff)%acell(:)
166 520 : rprim_old(:,:,iimage)=results_img(iimage,itimimage_eff)%rprim(:,:)
167 40 : if (results_img(iimage,itimimage_eff)%results_gs%gaps(3,1) > 0.0_dp) then
168 80 : bg_img(:,iimage)=results_img(iimage,itimimage_eff)%results_gs%gaps(1,:)
169 80 : bg_opt_img(:,iimage)=results_img(iimage,itimimage_eff)%results_gs%gaps(2,:)
170 : else
171 0 : bg_img(:,iimage)=-100.0_dp
172 0 : bg_opt_img(:,iimage)=-100.0_dp
173 : endif
174 40 : call mkrdim(acell_old(:,iimage),rprim_old(:,:,iimage),rprimd(:,:,iimage))
175 40 : call metric(gmet,gprimd,-1,rmet,rprimd(:,:,iimage),ucvol)
176 : enthalpy_img(iimage)=etotal_img(iimage) &
177 164 : & +sum(results_img(iimage,itimimage_eff)%results_gs%strten(1:3))*ucvol
178 : enddo
179 :
180 : !sort energies
181 :
182 4 : call sort_dp(nimage,etotal_img,ieperm,tol9)
183 :
184 : !sort enthalpies
185 :
186 4 : call sort_dp(nimage,enthalpy_img,ihperm,tol9)
187 :
188 : !sort band gaps
189 :
190 8 : do ii=1,nspinor
191 4 : call sort_dp(nimage,bg_img(ii,:),ibgperm(ii,:),tol9)
192 8 : call sort_dp(nimage,bg_opt_img(ii,:),ibgoptperm(ii,:),tol9)
193 : enddo
194 :
195 : ! Fitness is calculated
196 :
197 44 : sumH=0.d0
198 : Hmin=minval(enthalpy_img)
199 : Hmax=maxval(enthalpy_img)
200 44 : fitness = zero
201 :
202 4 : select case (ga_param%ga_fitness)
203 : case ( 1 )
204 :
205 : ! Function weighted over the difference with respect to the minimum
206 :
207 44 : do iimage=1,nimage
208 44 : sumh=sumh+enthalpy_img(iimage); fitness(iimage)=sumh
209 : enddo
210 4 : denom=nimage*enthalpy_img(nimage)-sumh
211 44 : do iimage=1,nimage
212 44 : fitness(iimage)=(iimage*enthalpy_img(nimage)-fitness(iimage))/denom
213 : enddo
214 :
215 : case ( 2 )
216 :
217 : ! Botzmann like, using the enthalpy difference.
218 :
219 0 : do iimage=1,nimage
220 0 : fitness(iimage)=exp(-one*(enthalpy_img(iimage)-enthalpy_img(1)))
221 0 : sumH = sumH + fitness(iimage)
222 : enddo
223 0 : fitness = fitness/sumH
224 0 : do iimage=2,nimage
225 0 : fitness(iimage)=fitness(iimage)+fitness(iimage-1)
226 : enddo
227 :
228 : case ( 3 )
229 :
230 : ! weighted ove the position in the ordered list, with probability 1/i (non uniform)
231 :
232 0 : do iimage=1,nimage
233 0 : fitness(iimage)=one/float(iimage)
234 0 : sumH = sumH + fitness(iimage)
235 : enddo
236 0 : fitness = fitness/sumH
237 4 : do iimage=2,nimage
238 0 : fitness(iimage)=fitness(iimage)+fitness(iimage-1)
239 : enddo
240 :
241 : end select
242 :
243 : ! do a single GA boocle
244 :
245 4 : indiv=0
246 :
247 : ! Selection over the best ga_opt_percent of the population
248 :
249 4 : nsurvivor=int(ga_param%ga_opt_percent*nimage)
250 :
251 4 : if (nsurvivor < one) nsurvivor=1
252 :
253 : ! pass coordinates,rprim, acell of survivors to next generation
254 :
255 12 : do iimage=1,nsurvivor
256 8 : indiv=indiv+1
257 200 : coor(:,iimage)=coor_old(:,ihperm(iimage))
258 32 : acell(:,iimage)=acell_old(:,ihperm(iimage))
259 108 : rprim(:,:,iimage)=rprim_old(:,:,ihperm(iimage))
260 : enddo
261 :
262 : ! complete the number of individuals of the generation by choosing them through GA
263 :
264 62 : do while(indiv<nimage)
265 :
266 : ! ga_n_rules corresponds to the number of chosen Genetic rules
267 :
268 58 : oper=ga_param%ga_rules(int(ga_param%ga_n_rules*uniformrandom(idum)+1))
269 :
270 10 : select case(oper)
271 : case(1) ! cut and splice elements after a randomization
272 10 : iparent1=choosefather(fitness,nimage,idum)
273 10 : iparent2=choosefather(fitness,nimage,idum)
274 10 : call convert_gentocoor(parent1,coor_old(:,ihperm(iparent1)),natom)
275 10 : call convert_gentocoor(parent2,coor_old(:,ihperm(iparent2)),natom)
276 : ! randomize the cell: random rotation and translation
277 10 : call randomize_parent(parent1,natom,idum)
278 10 : call randomize_parent(parent2,natom,idum)
279 : ! choose direction of cutting plane
280 10 : itmp = int(3*uniformrandom(idum)+1)
281 : ! order coordinates from small to large along that random direction axis of both parents
282 90 : zcoor1(:)=parent1(itmp,:)
283 90 : zcoor2(:)=parent2(itmp,:)
284 90 : call initialize_perm(zperm1,natom)
285 10 : call initialize_perm(zperm2,natom)
286 10 : call sort_dp(natom,zcoor1,zperm1,tol9)
287 10 : call sort_dp(natom,zcoor2,zperm2,tol9)
288 : ! choose the atom position to take the cut and take atoms below from one parent and above from the other parent
289 10 : itmp=int(natom*uniformrandom(idum)+1)
290 68 : do ii=1,itmp
291 232 : son1(:,ii)=parent1(:,zperm1(ii))
292 242 : son2(:,ii)=parent2(:,zperm2(ii))
293 : enddo
294 32 : do ii=itmp+1,natom
295 88 : son1(:,ii)=parent2(:,zperm2(ii))
296 98 : son2(:,ii)=parent1(:,zperm1(ii))
297 : enddo
298 : ! random combination of rprimd from parents
299 10 : call mkrdim(acell_old(:,ihperm(iparent1)),rprim_old(:,:,ihperm(iparent1)),rprimdparent1)
300 10 : call mkrdim(acell_old(:,ihperm(iparent2)),rprim_old(:,:,ihperm(iparent2)),rprimdparent2)
301 40 : do ii=1,3
302 130 : do jj=1,3
303 120 : rtmp(ii,jj)=uniformrandom(idum)
304 : enddo
305 : enddo
306 130 : rprimdson1=(one-rtmp)*rprimdparent1+rtmp*rprimdparent2
307 40 : do ii=1,3
308 130 : do jj=1,3
309 120 : rtmp(ii,jj)=uniformrandom(idum)
310 : enddo
311 : enddo
312 130 : rprimdson2=(one-rtmp)*rprimdparent1+rtmp*rprimdparent2
313 : !create acell and rprim from rprimd of springoffs
314 10 : call mkradim(acellson1,rprimson1,rprimdson1)
315 10 : call mkradim(acellson2,rprimson2,rprimdson2)
316 : ! check distances of atoms of every springoff
317 10 : if (checkatomicdist(natom,son1,rprimdson1)==0 .and. indiv<nimage) then
318 2 : indiv=indiv+1
319 : !if any fix coordinate restore the parent coordinate without modifications
320 18 : do ii=1,natom
321 66 : do jj=1,3
322 64 : if (ga_param%ga_iatfix(jj,ii) == 1) son1(jj,ii)=parent1(jj,ii)
323 : enddo
324 : enddo
325 2 : call convert_coortogen(son1,coor(:,indiv),natom)
326 8 : acell(:,indiv)=acellson1
327 26 : rprim(:,:,indiv)=rprimson1
328 : endif
329 10 : if (checkatomicdist(natom,son2,rprimdson2)==0 .and. indiv<nimage) then
330 6 : indiv=indiv+1
331 : !if any fix coordinate restore the parent coordinate without modifications
332 54 : do ii=1,natom
333 198 : do jj=1,3
334 192 : if (ga_param%ga_iatfix(jj,ii) == 1) son2(jj,ii)=parent1(jj,ii)
335 : enddo
336 : enddo
337 6 : call convert_coortogen(son2,coor(:,indiv),natom)
338 24 : acell(:,indiv)=acellson2
339 78 : rprim(:,:,indiv)=rprimson2
340 : endif
341 : case(2)! vector flip mutation
342 19 : iparent1=choosefather(fitness,nimage,idum)
343 19 : ii=int(ndimen*uniformrandom(idum)+1)
344 19 : jj=int(ndimen*uniformrandom(idum)+1)
345 19 : if (ii>jj) then
346 12 : call swap(ii,jj)
347 : end if
348 195 : vson1(1:ii)=coor_old(1:ii,ihperm(iparent1))
349 172 : if (jj<ndimen) vson1(jj+1:ndimen)=coor_old(jj+1:ndimen,ihperm(iparent1))
350 165 : do kk=ii,jj
351 165 : vson1(kk)=coor_old(jj+1-kk,ihperm(iparent1))
352 : enddo
353 247 : rprimson1=rprim_old(:,:,ihperm(iparent1))
354 76 : acellson1=acell_old(:,ihperm(iparent1))
355 19 : call convert_gentocoor(son1,vson1,natom)
356 19 : call mkrdim(acellson1,rprimson1,rprimdson1)
357 : !if any fix coordinate restore the parent coordinate without modifications
358 171 : do ii=1,natom
359 627 : do jj=1,3
360 608 : if (ga_param%ga_iatfix(jj,ii) == 1) son1(jj,ii)=parent1(jj,ii)
361 : enddo
362 : enddo
363 19 : call convert_coortogen(son1,vson1,natom)
364 19 : if (checkatomicdist(natom,son1,rprimdson1)==0 .and. indiv<nimage) then
365 7 : indiv=indiv+1
366 175 : coor(:,indiv)=vson1
367 28 : acell(:,indiv)=acellson1
368 91 : rprim(:,:,indiv)=rprimson1
369 : endif
370 : case(3) ! random strain - nondiagonal
371 12 : iparent1=choosefather(fitness,nimage,idum)
372 12 : rtmp(1,1)=one+gaussian_random(idum,0.1_dp)
373 12 : rtmp(2,2)=one+gaussian_random(idum,0.1_dp)
374 12 : rtmp(3,3)=one+gaussian_random(idum,0.1_dp)
375 12 : rtmp(1,2)=gaussian_random(idum,0.1_dp)*half
376 12 : rtmp(1,3)=gaussian_random(idum,0.1_dp)*half
377 12 : rtmp(2,3)=gaussian_random(idum,0.1_dp)*half
378 12 : rtmp(2,1)=rtmp(1,2)
379 12 : rtmp(3,1)=rtmp(1,3)
380 12 : rtmp(3,2)=rtmp(2,3)
381 480 : rprimson1=matmul(rtmp,rprim_old(:,:,ihperm(iparent1)))
382 312 : vson1=coor_old(:,ihperm(iparent1))
383 48 : acellson1=acell_old(:,ihperm(iparent1))
384 12 : call convert_gentocoor(son1,vson1,natom)
385 12 : call mkrdim(acellson1,rprimson1,rprimdson1)
386 : !if any fix coordinate restore the parent coordinate without modifications
387 108 : do ii=1,natom
388 396 : do jj=1,3
389 384 : if (ga_param%ga_iatfix(jj,ii) == 1) son1(jj,ii)=parent1(jj,ii)
390 : enddo
391 : enddo
392 12 : call convert_coortogen(son1,vson1,natom)
393 12 : if (checkatomicdist(natom,son1,rprimdson1)==0 .and. indiv<nimage) then
394 11 : indiv=indiv+1
395 275 : coor(:,indiv)=vson1
396 44 : acell(:,indiv)=acellson1
397 143 : rprim(:,:,indiv)=rprimson1
398 : endif
399 : case(4) ! coordinates mutation
400 17 : iparent1=choosefather(fitness,nimage,idum)
401 442 : vson1=coor_old(:,ihperm(iparent1))
402 17 : itmp=ndimen/4
403 17 : if (itmp<1) itmp=1
404 119 : do jj=1,itmp
405 102 : ii=int(ndimen*uniformrandom(idum)+1)
406 102 : vson1(ii)=vson1(ii)+0.15*uniformrandom(idum)
407 102 : if (vson1(ii)>one) vson1(ii)=vson1(ii)-one
408 119 : if (vson1(ii)<zero) vson1(ii)=vson1(ii)+one
409 : enddo
410 221 : rprimson1=rprim_old(:,:,ihperm(iparent1))
411 68 : acellson1=acell_old(:,ihperm(iparent1))
412 17 : call convert_gentocoor(son1,vson1,natom)
413 17 : call mkrdim(acellson1,rprimson1,rprimdson1)
414 : !if any fix coordinate restore the parent coordinate without modifications
415 153 : do ii=1,natom
416 561 : do jj=1,3
417 544 : if (ga_param%ga_iatfix(jj,ii) == 1) son1(jj,ii)=parent1(jj,ii)
418 : enddo
419 : enddo
420 17 : call convert_coortogen(son1,vson1,natom)
421 75 : if (checkatomicdist(natom,son1,rprimdson1)==0 .and. indiv<nimage) then
422 6 : indiv=indiv+1
423 150 : coor(:,indiv)=vson1
424 24 : acell(:,indiv)=acellson1
425 78 : rprim(:,:,indiv)=rprimson1
426 : endif
427 : end select
428 : enddo
429 :
430 4 : next_itimimage=itimimage_eff+1
431 4 : if (next_itimimage>ntimimage_stored) next_itimimage=1
432 :
433 44 : do iimage=1,nimage
434 200 : results_img(iimage,next_itimimage)%acell = acell(:,iimage)
435 560 : results_img(iimage,next_itimimage)%rprim = rprim(:,:,iimage)
436 1360 : results_img(iimage,next_itimimage)%vel = results_img(iimage,itimimage_eff)%vel
437 560 : results_img(iimage,next_itimimage)%vel_cell = results_img(iimage,itimimage_eff)%vel_cell
438 44 : call convert_gentocoor(results_img(iimage,next_itimimage)%xred,coor(:,iimage),natom)
439 : enddo
440 :
441 4 : ABI_FREE(coor)
442 4 : ABI_FREE(acell)
443 4 : ABI_FREE(acell_old)
444 4 : ABI_FREE(rprim)
445 4 : ABI_FREE(rprimd)
446 4 : ABI_FREE(rprim_old)
447 4 : ABI_FREE(zcoor1)
448 4 : ABI_FREE(zcoor2)
449 4 : ABI_FREE(coor_old)
450 4 : ABI_FREE(zperm1)
451 4 : ABI_FREE(zperm2)
452 4 : ABI_FREE(ieperm)
453 4 : ABI_FREE(ihperm)
454 4 : ABI_FREE(ibgperm)
455 4 : ABI_FREE(ibgoptperm)
456 4 : ABI_FREE(etotal_img)
457 4 : ABI_FREE(bg_img)
458 4 : ABI_FREE(bg_opt_img)
459 4 : ABI_FREE(enthalpy_img)
460 4 : ABI_FREE(fitness)
461 4 : ABI_FREE(vson1)
462 4 : ABI_FREE(vson2)
463 :
464 4 : end subroutine predict_ga
465 :
466 : !!*************** local subroutines
467 :
468 68 : INTEGER FUNCTION choosefather(fitf,n,idum)
469 :
470 : integer,intent(in) :: n
471 : integer,intent(inout) :: idum
472 : real(dp), dimension(:), intent(in) :: fitf
473 :
474 : real(dp) :: x1
475 : integer :: ii
476 :
477 68 : x1=uniformrandom(idum);
478 68 : choosefather=1
479 415 : do ii=2,n
480 415 : if(fitf(ii-1)<x1.and.x1<=fitf(ii))then
481 : choosefather=ii
482 : exit
483 : endif
484 : enddo
485 68 : end FUNCTION choosefather
486 :
487 : !!
488 :
489 12 : SUBROUTINE swap(a,b)
490 :
491 : integer, intent(inout) :: a,b
492 : integer :: dum
493 12 : dum=a; a=b; b=dum
494 12 : END SUBROUTINE swap
495 :
496 : !!
497 :
498 : INTEGER FUNCTION comp_indiv(distances,indiv,natom,nimage)
499 :
500 : !! comparing individuals from the same generation and check they
501 : !! are not too close. We compare all individuals with individual: indiv.
502 : !! We assume, all distances for a given individual are ordered and
503 : !! we define a metric from the total difference distances between individuals.
504 : !! if comp_indiv is 0, means that two individuals are two close.
505 :
506 : integer, intent(in) :: indiv,natom,nimage
507 : real(dp),intent(in) ::distances(natom,nimage)
508 : real(dp) :: diff
509 :
510 : integer :: ii,jj
511 :
512 : comp_indiv=1
513 :
514 : do ii=1,indiv-1
515 : diff=0.0_dp
516 : do jj=1,natom
517 : diff=(distances(jj,indiv)-distances(jj,ii))**2
518 : enddo
519 : if (diff.le.0.001_dp) comp_indiv=0
520 : enddo
521 :
522 : end FUNCTION comp_indiv
523 :
524 : !!
525 :
526 20 : SUBROUTINE randomize_parent(parent,natom,idum)
527 :
528 : ! take a parent and randomize the positions of the atoms
529 :
530 : integer,intent(in) :: natom
531 : integer,intent(inout) :: idum
532 : real(dp),intent(inout) :: parent(3,natom)
533 :
534 : real(dp) :: tmp(3),rot(3,3)
535 : integer :: ii,jj
536 :
537 : !random rotation
538 :
539 180 : do ii=1,natom
540 160 : if (uniformrandom(idum)>half) then
541 312 : do jj=1,3
542 312 : tmp(jj)=uniformrandom(idum)*two_pi
543 : enddo
544 78 : rot(1,1)=cos(tmp(3))*cos(tmp(2))
545 78 : rot(1,2)=cos(tmp(3))*sin(tmp(1))*sin(tmp(2))-cos(tmp(1))*sin(tmp(3))
546 78 : rot(1,3)=cos(tmp(1))*cos(tmp(3))*sin(tmp(2))+sin(tmp(1))*sin(tmp(3))
547 78 : rot(2,1)=cos(tmp(2))*sin(tmp(3))
548 78 : rot(2,2)=cos(tmp(1))*cos(tmp(3))+sin(tmp(1))*sin(tmp(2))*sin(tmp(3))
549 78 : rot(2,3)=cos(tmp(1))*sin(tmp(2))*sin(tmp(3))-cos(tmp(3))*sin(tmp(1))
550 78 : rot(3,1)=-sin(tmp(2))
551 78 : rot(3,2)=cos(tmp(2))*sin(tmp(1))
552 78 : rot(3,3)=cos(tmp(1))*cos(tmp(2))
553 1482 : parent(:,ii)=matmul(rot(:,:),parent(:,ii))
554 : endif
555 :
556 : ! random reflection
557 160 : if (uniformrandom(idum)>half) then
558 336 : parent(:,ii)=-parent(:,ii)
559 : endif
560 :
561 : ! fold back all coordinates to reduced coordinates in cube [0,1]
562 660 : parent(:,ii)=parent(:,ii)-anint((parent(:,ii)-one)/two)
563 :
564 : enddo
565 :
566 : ! shift all atoms along a random direction
567 :
568 80 : do ii=1,3
569 80 : tmp(ii)=uniformrandom(idum)
570 : enddo
571 :
572 180 : do ii=1,natom
573 640 : parent(:,ii)=parent(:,ii)+tmp(:)
574 660 : parent(:,ii)=parent(:,ii)-anint(parent(:,ii)/two)
575 : enddo
576 :
577 20 : end SUBROUTINE randomize_parent
578 :
579 : !!
580 :
581 108 : SUBROUTINE convert_gentocoor(parent,coor,natom)
582 :
583 : ! convert gene (single vector) to coordinates (3,natom)
584 :
585 : integer,intent(in) :: natom
586 : double precision,intent(out) :: parent(3,natom)
587 : double precision,intent(in) :: coor(3*natom)
588 :
589 : integer :: ii,jj
590 :
591 :
592 972 : do ii=1,natom
593 864 : jj=(ii-1)*3
594 3564 : parent(:,ii)=coor(jj+1:jj+3)
595 : enddo
596 :
597 108 : end SUBROUTINE convert_gentocoor
598 :
599 : !!
600 :
601 96 : SUBROUTINE convert_coortogen(parent,coor,natom)
602 :
603 : ! convert coordinates in gene notation (single vector with all coordinates)
604 :
605 : integer,intent(in) :: natom
606 : double precision,intent(in) :: parent(3,natom)
607 : double precision,intent(out) :: coor(3*natom)
608 :
609 : integer :: ii,jj
610 :
611 864 : do ii=1,natom
612 768 : jj=(ii-1)*3
613 3168 : coor(jj+1:jj+3)=parent(:,ii)
614 : enddo
615 :
616 96 : end SUBROUTINE convert_coortogen
617 :
618 : !!
619 :
620 8 : SUBROUTINE initialize_perm(iperm,nimage)
621 :
622 : !! initialize the vector iperm with corresponding indices.
623 :
624 : integer, intent(in) :: nimage
625 : integer, intent(inout) :: iperm(nimage)
626 : integer :: ii
627 :
628 :
629 356 : do ii=1,nimage
630 356 : iperm(ii)=ii
631 : enddo
632 :
633 : end SUBROUTINE initialize_perm
634 :
635 : ! if after a genetic rule, check if two atoms in the same gen
636 : ! are too close
637 :
638 :
639 68 : INTEGER FUNCTION checkatomicdist(natom,coord,rprimd)
640 :
641 : !! check if two atoms are two close.
642 : !! if they are, checkatomicdist=0
643 :
644 : integer, intent(in) :: natom
645 : real(dp), intent(in) :: coord(3,natom),rprimd(3,3)
646 : real(dp) :: d,v1(3),v2(3)
647 : integer :: ii,jj
648 :
649 68 : checkatomicdist=0
650 612 : do ii=1,natom
651 2176 : v1=coord(:,ii)
652 2391 : do jj=ii+1,natom
653 7288 : v2=coord(:,jj)
654 1822 : d=dist2(v1,v2,rprimd,1)
655 2323 : if (d<1.0d0) then
656 : checkatomicdist=1
657 : EXIT
658 : endif
659 : enddo
660 : enddo
661 :
662 68 : END FUNCTION checkatomicdist
663 :
664 72 : DOUBLE PRECISION FUNCTION gaussian_random(idum,sigma)
665 :
666 :
667 : integer,intent(inout) :: idum
668 : real(dp), intent(in) :: sigma
669 :
670 : real(dp) :: r1,r2,w
671 : !! The polar form of the Box-Muller transformation
672 72 : w=two
673 159 : do while (w >= one .or. w == zero)
674 87 : r1=two*uniformrandom(idum)-one
675 87 : r2=two*uniformrandom(idum)-one
676 87 : w=r1*r1+r2*r2
677 : enddo
678 72 : w=sqrt(-two*log(w)/w)
679 72 : gaussian_random=r2*w*sigma
680 :
681 72 : END FUNCTION gaussian_random
682 :
683 : end MODULE m_use_ga
|