atomes 1.1.14
atomes: an atomic scale modeling tool box
Loading...
Searching...
No Matches
rings-primitive.F90
Go to the documentation of this file.
1! This file is part of the 'atomes' software.
2!
3! 'atomes' is free software: you can redistribute it and/or modify it under the terms
4! of the GNU Affero General Public License as published by the Free Software Foundation,
5! either version 3 of the License, or (at your option) any later version.
6!
7! 'atomes' is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
8! without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9! See the GNU General Public License for more details.
10!
11! You should have received a copy of the GNU Affero General Public License along with 'atomes'.
12! If not, see <https://www.gnu.org/licenses/>
13!
14! Copyright (C) 2022-2024 by CNRS and University of Strasbourg
15!
20
21INTEGER FUNCTION primitive_rings ()
22
23!
24! Primitive and strong ring statistics
25!
26#ifdef OPENMP
27!$ USE OMP_LIB
28#endif
29USE parameters
30
31IMPLICIT NONE
32
33INTEGER :: rid
34#ifdef OPENMP
35INTEGER :: numth
36LOGICAL :: doatoms=.false.
37#endif
38
39INTERFACE
40 INTEGER FUNCTION recrings(VID)
41 INTEGER, INTENT(IN) :: vid
42 END FUNCTION
43END INTERFACE
44
46
47! Dynamic allocation of pointers and tables used in the "RINGS" subroutine
48
49rid = 3
50if (calc_strings) rid = 4
51
52#ifdef OPENMP
53numth = omp_get_max_threads()
54doatoms=.false.
55! Dynamic allocation of pointers and tables used in the "RINGS" subroutine
56if (ns.ge.1 .and. ns.lt.numth) then
57 if (numth .ge. 2*(ns-1)) then
58 doatoms=.true.
59 else
60 numth=ns
61 endif
62endif
63
64if (all_atoms) doatoms=.true.
65
66if (doatoms) then
67 if (na.lt.numth) numth=na
68#ifdef DEBUG
69 write (6, *) "OpenMP on atoms, NUMTH= ",numth
70#endif
71 call primitive_ring_search_atoms (rid, numth)
72else
73#ifdef DEBUG
74 write (6, *) "OpenMP on MD steps, NUMTH= ",numth
75#endif
76 call primitive_ring_search_steps (rid, numth)
77endif
78#else
80#endif
81
83
84END FUNCTION
85
86#ifdef OPENMP
87SUBROUTINE primitive_ring_search_atoms (RID, NUMTH)
88
89USE parameters
90!$ USE OMP_LIB
91IMPLICIT NONE
92INTEGER, INTENT(IN) :: numth
93INTEGER, INTENT(IN) :: rid
94INTEGER, DIMENSION(:), ALLOCATABLE :: tring, indte
95INTEGER, DIMENSION(:,:,:), ALLOCATABLE :: savring, ordring
96INTEGER, DIMENSION(:,:,:), ALLOCATABLE :: savr, ordr
97INTEGER :: ri
98LOGICAL, DIMENSION(2) :: fndtab
99INTERFACE
100 INTEGER FUNCTION rings_to_ogl_menu (IDSEARCH, NRI)
101 USE parameters
102 INTEGER, INTENT(IN) :: idsearch
103 INTEGER, DIMENSION(TAILLR, NS), INTENT(IN) :: nri
104 END FUNCTION
105 INTEGER FUNCTION rings_to_ogl (STEP, IDSEARCH, NRI, RSAVED, OSAVED)
106 USE parameters
107 INTEGER, INTENT(IN) :: step, idsearch
108 INTEGER, DIMENSION(TAILLR,NS), INTENT(IN) :: nri
109 INTEGER, DIMENSION(TAILLR,NUMA,TAILLR), INTENT(IN) :: rsaved, osaved
110 END FUNCTION
111END INTERFACE
112
113ri = 0
114if(allocated(savring)) deallocate(savring)
115allocate(savring(taillr,numa,taillr), stat=err)
116if (err .ne. 0) then
117 alc_tab="SAVRING"
118 alc=.true.
119 goto 001
120endif
121if(allocated(ordring)) deallocate(ordring)
122allocate(ordring(taillr,numa,taillr), stat=err)
123if (err .ne. 0) then
124 alc_tab="ORDRING"
125 alc=.true.
126 goto 001
127endif
128if(allocated(cpat)) deallocate(cpat)
129allocate(cpat(nna), stat=err)
130if (err .ne. 0) then
131 alc_tab="CPAT"
132 alc=.true.
133 goto 001
134endif
135 if(allocated(vpat)) deallocate(vpat)
136allocate(vpat(nna,maxn), stat=err)
137if (err .ne. 0) then
138 alc_tab="VPAT"
139 alc=.true.
140 goto 001
141endif
142
143do i=1, ns
144
145 savring(:,:,:)=0
146 ordring(:,:,:)=0
147 call setup_cpat_vpat_ring (nna, i, contj, voisj, cpat, vpat)
148 ! OpenMP on atoms only
149 !$OMP PARALLEL NUM_THREADS(NUMTH) DEFAULT (NONE) &
150 !$OMP& PRIVATE(FNDTAB, MAXAT, MINAT, SAUT, PATH, PATHOUT, &
151 !$OMP& h, j, k, l, m, n, o, p, INDTE, APNA, RES_LIST, &
152 !$OMP& ERR, TRING, SAVR, ORDR, PRINGORD, NPRING, MATDIST, QUEUE, QUERNG) &
153 !$OMP& SHARED(NUMTH, i, RID, CALC_STRINGS, NS, NA, NNA, NNP, TLT, NSP, LOT, TAILLR, CONTJ, VOISJ, &
154 !$OMP& NUMA, MAXPNA, MINPNA, ABAB, NO_HOMO, TBR, ALC, ALC_TAB, SAVRING, ORDRING, CPAT, VPAT, &
155 !$OMP& NCELLS, THE_BOX, FULLPOS, PBC, MAXN, NRING, INDRING, PNA, ri)
156 if(allocated(matdist)) deallocate(matdist)
157 allocate(matdist(nna), stat=err)
158 if (err .ne. 0) then
159 alc_tab="MATDIST"
160 alc=.true.
161 goto 002
162 endif
163 if(allocated(queue)) deallocate(queue)
164 allocate(queue(nna), stat=err)
165 if (err .ne. 0) then
166 alc_tab="QUEUE"
167 alc=.true.
168 goto 002
169 endif
170 if (allocated(pringord)) deallocate(pringord)
171 allocate(pringord(numa*10,taillr), stat=err)
172 if (err .ne. 0) then
173 alc_tab="PRINGORD"
174 alc=.false.
175 goto 002
176 endif
177 if (allocated(npring)) deallocate(npring)
178 allocate(npring(nna), stat=err)
179 if (err .ne. 0) then
180 alc_tab="NPRING"
181 alc=.false.
182 goto 002
183 endif
184 if(allocated(res_list)) deallocate(res_list)
185 allocate(res_list(taillr), stat=err)
186 if (err .ne. 0) then
187 alc_tab="RES_LIST"
188 alc=.true.
189 goto 002
190 endif
191 if(allocated(savr)) deallocate(savr)
192 allocate(savr(taillr,numa,taillr), stat=err)
193 if (err .ne. 0) then
194 alc_tab="SAVR"
195 alc=.true.
196 goto 002
197 endif
198 if(allocated(ordr)) deallocate(ordr)
199 allocate(ordr(taillr,numa,taillr), stat=err)
200 if (err .ne. 0) then
201 alc_tab="ORDR"
202 alc=.true.
203 goto 002
204 endif
205 if(allocated(indte)) deallocate(indte)
206 allocate(indte(numa), stat=err)
207 if (err .ne. 0) then
208 alc_tab="INDTE"
209 goto 002
210 endif
211 if (allocated(tring)) deallocate(tring)
212 allocate(tring(taillr), stat=err)
213 if (err .ne. 0) then
214 alc_tab="TRING"
215 alc=.true.
216 goto 002
217 endif
218 if(allocated(apna)) deallocate(apna)
219 allocate(apna(taillr), stat=err)
220 if (err .ne. 0) then
221 alc_tab="APNA"
222 alc=.true.
223 goto 002
224 endif
225 savr(:,:,:)=0
226 ordr(:,:,:)=0
227 tring(:)=0
228 !$OMP DO SCHEDULE(STATIC,NA/NUMTH)
229 do j=nnp+1, nnp+na ! atoms-loop
230
231 if (tbr .or. alc) goto 003
232 if (tlt .eq. nsp+1 .or. lot(j-nnp) .eq. tlt) then
233
234 apna(:)=0
235 minat=taillr
236 maxat=1
237 saut=.true.
238
239 call dijkstra (j, cpat, vpat, queue, matdist)
240 if (tbr .or. alc) goto 003
241
242 do k=1, taillr/2 + mod(taillr,2) ! ring-sizes-loop
243
244 indte(:)=0
245 res_list(:)=0
246 path=0
247 do l=1, nna
248 if (matdist(l) .eq. k) then
249 call spath_rec (path,l,k,k,matdist,cpat,vpat,npring,pringord)
250 endif
251 enddo
252 h = path*(path-1)/2
253 if (allocated(querng)) deallocate(querng)
254 allocate(querng(h,2), stat=err)
255 if (err .ne. 0) then
256 alc_tab="QUERNG"
257 alc=.true.
258 goto 003
259 endif
260
261 l=0
262 do m=1, path-1
263 do n=m+1, path
264 l=l+1
265 querng(l,1)=m
266 querng(l,2)=n
267! Paths which share atoms ... so with overlap ... are deleted
268 pathout=.false.
269 do o=1, k-1
270 do p=1, k-1
271 if (pringord(m,o) .eq. pringord(n,p)) then
272 pathout=.true.
273 exit
274 endif
275 enddo
276 if (pathout) exit
277 enddo
278 if (pathout) then
279 querng(l,1)=0
280 querng(l,2)=0
281 l=l-1
282 endif
283 enddo
284 enddo
285 fndtab(:)=.false.
286 call prim_ring (fndtab, j, l, k, h, cpat, vpat, querng, pringord, matdist, &
287 savr, ordr, tring, indte, res_list)
288 if (tbr .or. alc) goto 003
289 m = 2*k
290 if (fndtab(1)) then
291 if (apna(m).eq.0) then
292 apna(m)=1
293 minat=min(minat,m)
294 maxat=max(maxat,m)
295 saut=.false.
296 endif
297 endif
298 if (fndtab(2)) then
299 m = m + 1
300 if (apna(m).eq.0) then
301 apna(m)=1
302 minat=min(minat,m)
303 maxat=max(maxat,m)
304 saut=.false.
305 endif
306 endif
307 if (allocated(querng)) deallocate(querng)
308
309 enddo ! end ring-sizes-loop
310
311 if (.not. saut) then
312 do k=3, taillr
313 do l=3, taillr
314 if (apna(k).eq.1 .and. apna(l).eq.1) then
315 !$OMP ATOMIC
316 pna(k,l,i)=pna(k,l,i)+1
317 endif
318 enddo
319 enddo
320 !$OMP ATOMIC
321 maxpna(maxat,i)=maxpna(maxat,i)+1
322 !$OMP ATOMIC
323 minpna(minat,i)=minpna(minat,i)+1
324 endif
325
326 endif
327
328 003 continue
329
330 enddo ! end atoms-loop
331 !$OMP END DO NOWAIT
332
333 if (tbr .or. alc) goto 002
334
335 !$OMP CRITICAL
336 do k=3, taillr
337 if (tring(k).gt.0) then
338 if (nring(k,i).gt.0) then
339 o = 0
340 do l=1, tring(k)
341 do m=1, nring(k,i)
342 saut=.true.
343 do n=1, k
344 if (savring(k,m,n) .ne. savr(k,l,n)) then
345 saut=.false.
346 exit
347 endif
348 enddo
349 if (saut) exit
350 enddo
351 if (.not.saut) then
352 o = o + 1
353 if (nring(k,i)+o .gt. numa) then
354 tbr=.true.
355 goto 004
356 endif
357 do m=1, k
358 savring(k,nring(k,i)+o,m) = savr(k,l,m)
359 ordring(k,nring(k,i)+o,m) = ordr(k,l,m)
360 enddo
361 endif
362 enddo
363 nring(k,i)=nring(k,i)+o
364 else
365 do l=1, tring(k)
366 do m=1, k
367 savring(k,l,m) = savr(k,l,m)
368 ordring(k,l,m) = ordr(k,l,m)
369 enddo
370 enddo
371 nring(k,i) = tring(k)
372 endif
373 endif
374 enddo
375
376 004 continue
377 !$OMP END CRITICAL
378
379 002 continue
380
381 if (allocated(indte)) deallocate (indte)
382 if (allocated(apna)) deallocate (apna)
383 if (allocated(tring)) deallocate (tring)
384 if (allocated(savr)) deallocate (savr)
385 if (allocated(ordr)) deallocate (ordr)
386 if (allocated(matdist)) deallocate(matdist)
387 if (allocated(queue)) deallocate(queue)
388 if (allocated(pringord)) deallocate(pringord)
389
390 !$OMP END PARALLEL
391
392 if (alc .or. tbr) goto 001
393 ri = ri + rings_to_ogl(i, rid, nring, savring, ordring)
394
395 do k=3, taillr
396 if (nring(k,i) .ne. 0) then
397! do j=1, NRING(k,i)
398!! The algorithm implies that you may have a problem for
399!! the biggest size of ring therefore lets put this size out of the proof checking.
400!! Furthermore we check results only if all atoms are used to initiate the search.
401! if (mod(INDRING(k,j,i), k).ne.0 .and. k.lt.TAILLR .and. LTLT.eq.0) then
402! write (6, 003) i, k, j, INDRING(k,j,i)
403! write (6, 007)
404! do l=1, k
405! write (6, '(i4,2x)', advance='no') RINGORD(k,j,l,i)
406! enddo
407! write (6, *)
408! write (6, 004)
409! if (ABAB) then
410! write (6, 008)
411! else
412! write (6, 005)
413! endif
414! write (6, *)
415! endif
416! enddo
417 endif
418 enddo
419
420enddo
421
422001 continue
423
424if (alc) then
425 call show_error ("Impossible to allocate memory"//char(0), &
426 "Subroutine: PRIMITIVE_RING_SEARCH_ATOMS"//char(0), "Table: "//alc_tab(1:len_trim(alc_tab))//char(0))
427endif
428
429if (allocated(cpat)) deallocate (cpat)
430if (allocated(vpat)) deallocate (vpat)
431if (allocated(savring)) deallocate (savring)
432if (allocated(ordring)) deallocate (ordring)
433
434if (ri .eq. ns) ri = rings_to_ogl_menu(rid, nring)
435
436END SUBROUTINE
437#endif
438
439#ifdef OPENMP
440SUBROUTINE primitive_ring_search_steps (RID, NUMTH)
441
442USE parameters
443!$ USE OMP_LIB
444IMPLICIT NONE
445INTEGER, INTENT(IN) :: numth
446#else
448
449USE parameters
450IMPLICIT NONE
451#endif
452INTEGER, INTENT(IN) :: RID
453INTEGER, DIMENSION(:), ALLOCATABLE :: TRING, INDTE
454INTEGER, DIMENSION(:,:,:), ALLOCATABLE :: SAVRING, ORDRING
455INTEGER :: ri
456LOGICAL, DIMENSION(2) :: FNDTAB
457INTERFACE
458 INTEGER FUNCTION rings_to_ogl_menu (IDSEARCH, NRI)
459 USE parameters
460 INTEGER, INTENT(IN) :: IDSEARCH
461 INTEGER, DIMENSION(TAILLR, NS), INTENT(IN) :: NRI
462 END FUNCTION
463 INTEGER FUNCTION rings_to_ogl (STEP, IDSEARCH, NRI, RSAVED, OSAVED)
464 USE parameters
465 INTEGER, INTENT(IN) :: STEP, IDSEARCH
466 INTEGER, DIMENSION(TAILLR,NS), INTENT(IN) :: NRI
467 INTEGER, DIMENSION(TAILLR,NUMA,TAILLR), INTENT(IN) :: RSAVED, OSAVED
468 END FUNCTION
469END INTERFACE
470
471ri = 0
472#ifdef OPENMP
473! OpenMP on steps only
474!$OMP PARALLEL NUM_THREADS(NUMTH) DEFAULT (NONE) &
475!$OMP& PRIVATE(FNDTAB, MAXAT, MINAT, SAUT, PATH, PATHOUT, &
476!$OMP& h, i, j, k, l, m, n, o, p, INDTE, APNA, RES_LIST, &
477!$OMP& ERR, TRING, SAVRING, ORDRING, CPAT, VPAT, &
478!$OMP& PRINGORD, NPRING, MATDIST, QUEUE, QUERNG) &
479!$OMP& SHARED(NUMTH, RID, CALC_STRINGS, NS, NA, NNA, NNP, TLT, NSP, LOT, TAILLR, CONTJ, VOISJ, &
480!$OMP& NUMA, MAXPNA, MINPNA, ABAB, NO_HOMO, TBR, ALC, ALC_TAB, &
481!$OMP& NCELLS, THE_BOX, FULLPOS, PBC, MAXN, NRING, INDRING, PNA, ri)
482#endif
483if(allocated(matdist)) deallocate(matdist)
484allocate(matdist(nna), stat=err)
485if (err .ne. 0) then
486 alc_tab="MATDIST"
487 alc=.true.
488 goto 001
489endif
490if(allocated(queue)) deallocate(queue)
491allocate(queue(nna), stat=err)
492if (err .ne. 0) then
493 alc_tab="QUEUE"
494 alc=.true.
495 goto 001
496endif
497if (allocated(pringord)) deallocate(pringord)
498allocate(pringord(numa*10,taillr), stat=err)
499if (err .ne. 0) then
500 alc_tab="PRINGORD"
501 alc=.false.
502 goto 001
503endif
504if (allocated(npring)) deallocate(npring)
505allocate(npring(nna), stat=err)
506if (err .ne. 0) then
507 alc_tab="NPRING"
508 alc=.false.
509 goto 001
510endif
511if(allocated(cpat)) deallocate(cpat)
512allocate(cpat(nna), stat=err)
513if (err .ne. 0) then
514 alc_tab="CPAT"
515 alc=.true.
516 goto 001
517endif
518if(allocated(vpat)) deallocate(vpat)
519allocate(vpat(nna,maxn), stat=err)
520if (err .ne. 0) then
521 alc_tab="VPAT"
522 alc=.true.
523 goto 001
524endif
525if(allocated(res_list)) deallocate(res_list)
526allocate(res_list(taillr), stat=err)
527if (err .ne. 0) then
528 alc_tab="RES_LIST"
529 alc=.true.
530 goto 001
531endif
532if(allocated(savring)) deallocate(savring)
533allocate(savring(taillr,numa,taillr), stat=err)
534if (err .ne. 0) then
535 alc_tab="SAVRING"
536 alc=.true.
537 goto 001
538endif
539if(allocated(ordring)) deallocate(ordring)
540allocate(ordring(taillr,numa,taillr), stat=err)
541if (err .ne. 0) then
542 alc_tab="ORDRING"
543 alc=.true.
544 goto 001
545endif
546if(allocated(indte)) deallocate(indte)
547allocate(indte(numa), stat=err)
548if (err .ne. 0) then
549 alc_tab="INDTE"
550 goto 001
551endif
552if (allocated(tring)) deallocate(tring)
553allocate(tring(taillr), stat=err)
554if (err .ne. 0) then
555 alc_tab="TRING"
556 alc=.true.
557 goto 001
558endif
559if(allocated(apna)) deallocate(apna)
560allocate(apna(taillr), stat=err)
561if (err .ne. 0) then
562 alc_tab="APNA"
563 alc=.true.
564 goto 001
565endif
566
567!$OMP DO SCHEDULE(STATIC,NS/NUMTH)
568do i=1, ns
569
570 if (tbr .or. alc) goto 002
571 savring(:,:,:)=0
572 ordring(:,:,:)=0
573 tring(:)=0
574 call setup_cpat_vpat_ring (nna, i, contj, voisj, cpat, vpat)
575
576 do j=nnp+1, nnp+na ! atoms-loop
577
578 if (tlt .eq. nsp+1 .or. lot(j-nnp) .eq. tlt) then
579
580 apna(:)=0
581 minat=taillr
582 maxat=1
583 saut=.true.
584
585 call dijkstra(j, cpat, vpat, queue, matdist)
586 if (tbr .or. alc) goto 002
587
588 do k=1, taillr/2 + mod(taillr,2) ! ring-sizes-loop
589
590 indte(:)=0
591 res_list(:)=0
592 path=0
593 do l=1, nna
594 if (matdist(l) .eq. k) then
595 call spath_rec (path,l,k,k,matdist,cpat,vpat,npring,pringord)
596 endif
597 enddo
598 h = path*(path-1)/2
599 if (allocated(querng)) deallocate(querng)
600 allocate(querng(h,2), stat=err)
601 if (err .ne. 0) then
602 alc_tab="QUERNG"
603 alc=.true.
604 goto 002
605 endif
606
607 l=0
608 do m=1, path-1
609 do n=m+1, path
610 l=l+1
611 querng(l,1)=m
612 querng(l,2)=n
613! Paths which share atoms ... so with overlap ... are deleted
614 pathout=.false.
615 do o=1, k-1
616 do p=1, k-1
617 if (pringord(m,o) .eq. pringord(n,p)) then
618 pathout=.true.
619 exit
620 endif
621 enddo
622 if (pathout) exit
623 enddo
624 if (pathout) then
625 querng(l,1)=0
626 querng(l,2)=0
627 l=l-1
628 endif
629 enddo
630 enddo
631 fndtab(:)=.false.
632 call prim_ring (fndtab, j, l, k, h, cpat, vpat, querng, pringord, matdist, &
633 savring, ordring, tring, indte, res_list)
634 if (tbr .or. alc) goto 002
635 m = 2*k
636 if (fndtab(1)) then
637 if (apna(m).eq.0) then
638 apna(m)=1
639 minat=min(minat,m)
640 maxat=max(maxat,m)
641 saut=.false.
642 endif
643 endif
644 if (fndtab(2)) then
645 m = m + 1
646 if (apna(m).eq.0) then
647 apna(m)=1
648 minat=min(minat,m)
649 maxat=max(maxat,m)
650 saut=.false.
651 endif
652 endif
653 if (allocated(querng)) deallocate(querng)
654
655 enddo ! end ring-sizes-loop
656
657 if (.not. saut) then
658 do k=3, taillr
659 do m=3, taillr
660 if (apna(k).eq.1 .and. apna(m).eq.1) then
661 pna(k,m,i)=pna(k,m,i)+1
662 endif
663 enddo
664 enddo
665 maxpna(maxat,i)=maxpna(maxat,i)+1
666 minpna(minat,i)=minpna(minat,i)+1
667 endif
668
669 endif
670
671 enddo ! end atoms-loop
672
673 do j=3, taillr
674 nring(j,i) = tring(j)
675 enddo
676
677 k = rings_to_ogl(i, rid, nring, savring, ordring)
678 !$OMP ATOMIC
679 ri = ri + k
680
681 do k=3, taillr
682 if (nring(k,i) .ne. 0) then
683! do j=1, NRING(k,i)
684!! The algorithm implies that you may have a problem for
685!! the biggest size of ring therefore lets put this size out of the proof checking.
686!! Furthermore we check results only if all atoms are used to initiate the search.
687! if (mod(INDRING(k,j,i), k).ne.0 .and. k.lt.TAILLR .and. LTLT.eq.0) then
688! write (6, 003) i, k, j, INDRING(k,j,i)
689! write (6, 007)
690! do l=1, k
691! write (6, '(i4,2x)', advance='no') RINGORD(k,j,l,i)
692! enddo
693! write (6, *)
694! write (6, 004)
695! if (ABAB) then
696! write (6, 008)
697! else
698! write (6, 005)
699! endif
700! write (6, *)
701! endif
702! enddo
703 endif
704 enddo
705
706 002 continue
707
708enddo
709#ifdef OPENMP
710!$OMP END DO NOWAIT
711#endif
712
713001 continue
714
715if (alc) then
716 call show_error ("Impossible to allocate memory"//char(0), &
717 "Subroutine: PRIMITIVE_RING_SEARCH_STEPS"//char(0), "Table: "//alc_tab(1:len_trim(alc_tab))//char(0))
718endif
719
720if (allocated(tring)) deallocate (tring)
721if (allocated(savring)) deallocate (savring)
722if (allocated(ordring)) deallocate (ordring)
723if (allocated(cpat)) deallocate (cpat)
724if (allocated(vpat)) deallocate (vpat)
725if (allocated(indte)) deallocate (indte)
726if (allocated(apna)) deallocate (apna)
727if(allocated(matdist)) deallocate(matdist)
728if(allocated(queue)) deallocate(queue)
729if (allocated(pringord)) deallocate(pringord)
730
731#ifdef OPENMP
732!$OMP END PARALLEL
733#endif
734
735if (ri .eq. ns) ri = rings_to_ogl_menu(rid, nring)
736
737END SUBROUTINE
738
739SUBROUTINE dijkstra(NODE, CPT, VPT, QUE, MATDIS)
740
741USE parameters
742
743IMPLICIT NONE
744
745INTEGER, INTENT(IN) :: NODE
746INTEGER, DIMENSION(NNA), INTENT(INOUT) :: QUE, MATDIS
747INTEGER, DIMENSION(NNA), INTENT(IN) :: CPT
748INTEGER, DIMENSION(NNA,MAXN), INTENT(IN) :: VPT
749INTEGER :: QBEGIN, QEND, QID, AT1, AT2, DAT1
750
751que(:)=0
752matdis(:)=nna+2
753que(1)=node
754matdis(node)=0
755qbegin=0
756qend=1
757
758! Trouver les plus cours chemin reliant un atome aux autres
759! Find the shortest paths between atoms
760
761do while (qbegin < qend)
762
763 qbegin=qbegin+1
764 at1=que(qbegin)
765 dat1=matdis(at1)+1
766
767 do qid=1, cpt(at1)
768
769 at2=vpt(at1,qid)
770 if (matdis(at2) .gt. dat1) then
771
772 matdis(at2) = dat1
773 if (dat1 < nna) then
774
775 qend=qend+1
776 que(qend)= at2
777
778 endif
779
780 endif
781
782 enddo
783
784enddo
785
786END SUBROUTINE
787
788RECURSIVE SUBROUTINE spath_rec (PTH, NODE, LENGTH, LNGTH, MATDIS, CPT, VPT, NPRI, PORDR)
789
790USE parameters
791
792IMPLICIT NONE
793
794INTEGER, INTENT(INOUT) :: pth
795INTEGER, INTENT(IN) :: node, length, lngth
796INTEGER, DIMENSION(NNA), INTENT(IN) :: cpt, matdis
797INTEGER, DIMENSION(NNA,MAXN), INTENT(IN) :: vpt
798INTEGER, DIMENSION(NNA), INTENT(INOUT) :: npri
799INTEGER, DIMENSION(NUMA*10,TAILLR), INTENT(INOUT) :: pordr
800INTEGER :: distnn, idv, vdi, idt
801
802npri(length) = node
803do idv=1, cpt(node)
804
805! Boucle sur tous les voisins du noeud "NODE"
806! Loop on all the neighbors of node "NODE"
807
808 vdi=vpt(node,idv) ! Selection du voisin - neighbor selection
809 distnn=matdis(vdi) ! Distance to starting atom = VDI in the node distance table
810
811 if (distnn .eq. 0) then
812
813 pth=pth+1
814 do idt=1, lngth
815 pordr(pth,idt)=npri(idt)
816 enddo
817
818 elseif (distnn .eq. length-1) then
819
820 call spath_rec (pth, vdi, distnn, lngth, matdis, cpt, vpt, npri, pordr)
821
822 endif
823
824enddo
825
826END SUBROUTINE
827
828INTEGER FUNCTION real_atom_id (IND, NATS)
829
830IMPLICIT NONE
831INTEGER, INTENT(IN) :: ind, nats
832
833real_atom_id= ind - (ind/nats)*nats
834if (real_atom_id .eq. 0) real_atom_id=nats
835
836END FUNCTION
837
838SUBROUTINE prim_ring (FNDTAB, NODE, PTH, LGTH, NPT, CPT, VPT, QRNG, PORD, MATDIS, &
839 RSAVED, OSAVED, TRIN, INDP, RESLP)
840
841USE parameters
842
843IMPLICIT NONE
844
845LOGICAL, DIMENSION(2), INTENT(INOUT) :: FNDTAB
846INTEGER, INTENT(IN) :: NODE, PTH, LGTH, NPT
847INTEGER, DIMENSION(NNA), INTENT(IN) :: CPT, MATDIS
848INTEGER, DIMENSION(TAILLR), INTENT(INOUT) :: TRIN
849INTEGER, DIMENSION(NNA,MAXN), INTENT(IN) :: VPT
850INTEGER, DIMENSION(NPT,2), INTENT(IN) :: QRNG
851INTEGER, DIMENSION(NUMA*10,TAILLR), INTENT(INOUT) :: PORD
852INTEGER, DIMENSION(TAILLR,NUMA,TAILLR), INTENT(INOUT) :: RSAVED, OSAVED
853INTEGER, DIMENSION(NUMA), INTENT(INOUT) :: INDP
854INTEGER, DIMENSION(TAILLR), INTENT(INOUT) :: RESLP
855INTEGER :: RM, RN, PR, PTH1, PTH2, IRS, IRX
856INTEGER :: ATB, ATA, ATC, ATD, ATE, MAXD, MIND
857INTEGER :: PROBE
858INTEGER, DIMENSION(TAILLR) :: TOPRIM, PRIMTO
859LOGICAL:: GOAL, TOSAVE
860LOGICAL, DIMENSION(NNA) :: CHK
861INTERFACE
862 INTEGER FUNCTION real_atom_id (IND, NATS)
863 INTEGER, INTENT(IN) :: IND, NATS
864 END FUNCTION
865END INTERFACE
866
867goal=.false.
868
869do pr=1, pth
870
871! Premier chemin i->j - First path i->j
872 pth1= qrng(pr,1)
873! Second chemin i->k - second path i->k
874 pth2= qrng(pr,2)
875
876 probe=0
877 ata= pord(pth1,lgth)
878 atb= pord(pth2,lgth)
879 do rm=1, cpt(ata)
880 ate=vpt(ata,rm)
881 if (ate .eq. atb) probe=1
882 enddo
883
884 if (ata .eq. atb .or. probe .eq. 1) then
885
886 do rm=1, lgth-1
887 do rn=rm, lgth-1+probe
888
889 atc= pord(pth1,rm)
890 atd= pord(pth2,rn)
891 maxd=matdis(atc)+matdis(atd)
892 mind=2*lgth+probe-maxd
893 chk(:)=.false.
894
895 call pair_search (goal, atc, atd, 1, maxd, mind, cpt, vpt, chk)
896 if (goal) then
897 goal= .false.
898 goto 001
899 endif
900
901 enddo
902 enddo
903
904 do rn=1, lgth-1
905 do rm=rn, lgth-1+probe
906
907 atc= pord(pth1,rm)
908 atd= pord(pth2,rn)
909 maxd=matdis(atc)+matdis(atd)
910 mind=2*lgth+probe-maxd
911 chk(:)=.false.
912
913 call pair_search (goal, atc, atd, 1, maxd, mind, cpt, vpt, chk)
914 if (goal) then
915 goal= .false.
916 goto 001
917 endif
918
919 enddo
920 enddo
921
922 if ((probe.eq.0 .and. 2*lgth.le.taillr) .or. (probe.eq.1 .and. 2*lgth.lt.taillr)) then
923
924 toprim(:)=0
925 primto(:)=0
926 do irx=1, lgth
927 toprim(irx)=pord(pth1,irx)
928 enddo
929 if (probe .eq. 1) toprim(lgth+1)=pord(pth2,lgth)
930 irs=lgth+probe
931 do irx=lgth-1, 1, -1
932 irs=irs+1
933 toprim(irs)=pord(pth2,irx)
934 enddo
935 toprim(irs+1)=node
936
937! To find atom id in the primitive unit cell
938 do irx=1, 2*lgth+probe
939 primto(irx)=real_atom_id(toprim(irx),na)
940 enddo
941 tosave=.true.
942 if (abab) then
943 if (probe .eq. 0) then
944 call testabab (tosave,lgth,primto)
945 else
946 tosave=.false.
947 endif
948 endif
949 if (no_homo) then
950 call testhomo(tosave,lgth,primto)
951 endif
952 if (tosave .and. lgth*2+probe.le.taillr) then
953
954 if (calc_strings) then
955 call strong_rings (fndtab, lgth, probe, toprim, primto, rsaved, osaved, trin, indp, reslp, cpt, vpt)
956 else
957 call save_dijkstra_ring (primto, lgth*2+probe, rsaved, osaved, trin, indp, reslp)
958 fndtab(1+probe)=.true.
959 endif
960 if (tbr .or. alc) goto 002
961
962 endif
963
964 endif
965
966 endif
967
968001 continue
969
970enddo
971
972002 continue
973
974END
975
976RECURSIVE SUBROUTINE pair_search (GOAL, AT1, AT2, LG, MAXM, MINM, CPT, VPT, CHK)
977
978USE parameters
979
980IMPLICIT NONE
981
982LOGICAL, INTENT(INOUT) :: goal
983INTEGER, INTENT(IN) :: at1, at2, lg, maxm, minm
984INTEGER, DIMENSION(NNA), INTENT(IN) :: cpt
985INTEGER, DIMENSION(NNA,MAXN), INTENT(IN) :: vpt
986LOGICAL, DIMENSION(NNA), INTENT(INOUT) :: chk
987INTEGER :: psc, at3
988
989chk(at1)=.true.
990
991if (at1 .eq. at2) then
992
993 goal=.true.
994
995else
996
997 do psc=1, cpt(at1)
998
999 at3=vpt(at1,psc)
1000
1001 if (.not.chk(at3)) then
1002
1003 if (at3.eq.at2) then
1004
1005 goal=.true.
1006 goto 001
1007
1008 elseif (lg.lt.maxm-1 .and. lg.lt.minm-1) then
1009
1010 call pair_search (goal, at3, at2, lg+1, maxm, minm, cpt, vpt, chk)
1011
1012 if (goal) then
1013 goto 001
1014 endif
1015
1016 endif
1017
1018 endif
1019
1020 enddo
1021
1022endif
1023
1024001 continue
1025
1026chk(at1)=.false.
1027
1028END SUBROUTINE
1029
1030SUBROUTINE strong_rings (FNDTAB, RLGTH, RPROBE, TOPRIM, PRIMTO, ASRING, OSRING, TRNG, INDT, RESL, CPT, VPT)
1031
1032USE parameters
1033
1034IMPLICIT NONE
1035
1036LOGICAL, DIMENSION(2), INTENT(INOUT) :: FNDTAB
1037INTEGER, INTENT(IN) :: RLGTH, RPROBE
1038INTEGER, DIMENSION(TAILLR), INTENT(IN) :: TOPRIM, PRIMTO
1039INTEGER, DIMENSION(TAILLR,NUMA,TAILLR), INTENT(INOUT) :: ASRING, OSRING
1040INTEGER, DIMENSION(NUMA), INTENT(INOUT) :: INDT
1041INTEGER, DIMENSION(TAILLR), INTENT(INOUT) :: TRNG, RESL
1042INTEGER, DIMENSION(NNA), INTENT(IN) :: CPT
1043INTEGER, DIMENSION(NNA,MAXN), INTENT(IN) :: VPT
1044INTEGER :: RM, RN, STLGT
1045LOGICAL, DIMENSION(NNA) :: CHKS
1046
1047LOGICAL :: DVSTR
1048LOGICAL :: SGOAL=.false.
1049LOGICAL :: FGOAL=.false.
1050
1051stlgt=2*rlgth+rprobe
1052
1053chks(:)=.false.
1054
1055do rm=1, stlgt-1
1056
1057 do rn=rm+1, stlgt
1058
1059 dvstr=.false.
1060 call search_strong_rings (dvstr, rm, rn, stlgt, stlgt, sgoal, fgoal, toprim, cpt, vpt, chks)
1061 if (tbr .or. alc) goto 002
1062 if (fgoal) goto 001
1063 if (sgoal) goto 002
1064
1065 enddo
1066
1067enddo
1068
1069001 continue
1070
1071call save_dijkstra_ring (primto, rlgth*2+rprobe, asring, osring, trng, indt, resl)
1072fndtab(1+rprobe)=.true.
1073
1074if (tbr .or. alc) goto 002
1075
1076002 continue
1077
1078END SUBROUTINE
1079
1080RECURSIVE SUBROUTINE search_strong_rings (DLOW, IDX, IDY, DLGTR, LGTR, SRGOAL, FRGOAL, TOTER, CPT, VPT, CHKS)
1081
1082USE parameters
1083
1084IMPLICIT NONE
1085
1086INTEGER, INTENT(IN) :: dlgtr, lgtr, idx, idy
1087LOGICAL, INTENT(INOUT) :: dlow, srgoal, frgoal
1088INTEGER, DIMENSION(DLGTR), INTENT(IN) :: toter
1089INTEGER, DIMENSION(NNA), INTENT(IN) :: cpt
1090INTEGER, DIMENSION(NNA,MAXN), INTENT(IN) :: vpt
1091LOGICAL, DIMENSION(NNA), INTENT(INOUT) :: chks
1092INTEGER :: dxy, dyx, dtest, dmin
1093INTEGER :: rg, rf, rh, rj, rl, ro, rp, rq, rr
1094INTEGER :: nbpath, idz
1095INTEGER, DIMENSION(:), ALLOCATABLE :: strst, newter
1096INTEGER, DIMENSION(:,:), ALLOCATABLE :: totpath
1097LOGICAL, DIMENSION(:), ALLOCATABLE :: cutring
1098LOGICAL, DIMENSION(NNA) :: chk
1099TYPE(ring), TARGET :: st_ring
1100TYPE(ring), POINTER :: sring, tmp_ri
1101
1102INTERFACE
1103 RECURSIVE SUBROUTINE path_search (AT0,AT1,AT2,IDT1,IDT2,DMAX,DMED,DARING,NPATH,DLPATH, &
1104 STPATH,ACRING,TPATH,CUTPATH,CPT,VPT,CHK,CHKS,SRING)
1105 USE parameters
1106 INTEGER, INTENT(IN) :: at0, at1, at2, idt1, idt2, dmax, dmed, daring
1107 INTEGER, INTENT(INOUT) :: npath
1108 LOGICAL, INTENT(INOUT) :: dlpath
1109 INTEGER, DIMENSION(DMAX*DMAX), INTENT(INOUT) :: stpath
1110 INTEGER, DIMENSION(DMAX*DMAX,DMAX), INTENT(INOUT) :: tpath
1111 INTEGER, DIMENSION(DMED), INTENT(IN) :: acring
1112 INTEGER, DIMENSION(NNA), INTENT(IN) :: cpt
1113 INTEGER, DIMENSION(NNA,MAXN), INTENT(IN) :: vpt
1114 LOGICAL, DIMENSION(DMAX*DMAX), INTENT(INOUT) :: cutpath
1115 LOGICAL, DIMENSION(NNA), INTENT(INOUT) :: chk, chks
1116 TYPE (ring), POINTER, INTENT(INOUT) :: sring
1117 END
1118 SUBROUTINE shortcut_ring (IDA, IDB, IDC, DLT, TABAB, SRING)
1119 USE parameters
1120 INTEGER, INTENT(IN) :: ida, idb, idc, dlt
1121 INTEGER, DIMENSION(DLT), INTENT(IN) :: tabab
1122 TYPE(ring), POINTER, INTENT(INOUT) :: sring
1123 END
1124 SUBROUTINE creat_ring (RING_INIT, ELEM_CR)
1125 USE parameters
1126 TYPE (ring), INTENT(INOUT) :: ring_init
1127 INTEGER, INTENT(IN) :: elem_cr
1128 END SUBROUTINE
1129 SUBROUTINE do_ring (THE_RING, ELEM_DO)
1130 USE parameters
1131 TYPE (ring), POINTER, INTENT(INOUT) :: the_ring
1132 INTEGER, INTENT(IN) :: elem_do
1133 END SUBROUTINE
1134END INTERFACE
1135
1136do rg=1, dlgtr
1137 chks(toter(rg))=.true.
1138enddo
1139
1140dxy=abs(idy-idx)
1141dyx=dlgtr-dxy
1142dmin=min(dxy,dyx)
1143dtest=lgtr-1-dmin
1144
1145! First we find find a ring starting from an atom i and enclosing
1146! all tested atoms, then this ring will be tested and so on
1147! if the size of the enclosing ring became smaller than
1148! DLGTR then the initial ring is not strong
1149
1150if (dtest.ge.2) then
1151
1152 do rj=2, dtest
1153
1154 if (allocated(totpath)) deallocate(totpath)
1155 allocate(totpath(rj*rj,rj), stat=err)
1156 if (err .ne. 0) then
1157 alc_tab="TOTPATH"
1158 alc=.true.
1159 goto 001
1160 endif
1161 if (allocated(cutring)) deallocate(cutring)
1162 allocate(cutring(rj*rj), stat=err)
1163 if (err .ne. 0) then
1164 alc_tab="CUTRING"
1165 alc=.true.
1166 goto 001
1167 endif
1168 if (allocated(strst)) deallocate(strst)
1169 allocate(strst(rj*rj), stat=err)
1170 if (err .ne. 0) then
1171 alc_tab="STRST"
1172 alc=.true.
1173 goto 001
1174 endif
1175
1176 nbpath=0
1177 strst(:)=0
1178 cutring(:)=.false.
1179 totpath(:,:)=0
1180 chk(:)=.false.
1181
1182 rr=1
1183 call creat_ring (st_ring, toter(idx))
1184 sring => st_ring
1185! On recherche tous les chemins de taille RJ entre les atomes TOTER(IDX) et TOTER(IDY)
1186! On stock ces NBPATH chemins dans le tableau TOTPATH
1187
1188! We are looking for all path of size RJ between atoms TOTER(IDX) and TOTER(IDY)
1189! Then these NBPATH are saved in the tab TOTPATH
1190
1191 call path_search (toter(idx),toter(idx),toter(idy),idx,idy,rj,dlgtr,lgtr,nbpath,dlow, &
1192 strst,toter,totpath,cutring,cpt,vpt,chk,chks,sring)
1193 if (alc) goto 001
1194 if (nbpath .ne. 0) then
1195
1196 do rh=1, nbpath
1197
1198 idz=0
1199 if (cutring(rh)) then
1200 do rg=1, dlgtr
1201 if (toter(rg) .eq. strst(rh)) then
1202 idz=rg
1203 exit
1204 endif
1205 enddo
1206 endif
1207
1208 if(idz.eq.0)then
1209
1210 if (.not.cutring(rh)) then
1211 call creat_ring (st_ring, toter(idx))
1212 sring => st_ring
1213 do rg=1, rj
1214 rr=rr+1
1215 call do_ring (sring, totpath(rh,rg))
1216 if (alc) goto 001
1217 enddo
1218 if (dxy .le. dyx) then
1219 do rg=idy+1, dlgtr
1220 call do_ring (sring, toter(rg))
1221 if (alc) goto 001
1222 enddo
1223 do rg=1, idx
1224 call do_ring (sring, toter(rg))
1225 if (alc) goto 001
1226 enddo
1227 else
1228 do rg=idy-1, idx, -1
1229 call do_ring (sring, toter(rg))
1230 if (alc) goto 001
1231 enddo
1232 endif
1233 else
1234 call creat_ring (st_ring, toter(1))
1235 sring => st_ring
1236 do rg=2, dlgtr
1237 call do_ring (sring, toter(rg))
1238 if (alc) goto 001
1239 enddo
1240 chks(totpath(rh,1))=.true.
1241 endif
1242
1243 else
1244
1245 call creat_ring (st_ring, totpath(rh,1))
1246 sring => st_ring
1247 call shortcut_ring (idx, idy, idz, dlgtr, toter, sring)
1248 if (alc) goto 001
1249
1250 endif
1251
1252! A new path as been found, so a new rings as been built according
1253! to the new list of atoms.
1254! The size of this new ring has to be tested
1255
1256 if (sring%SPEC+1 .lt. lgtr) then
1257
1258 tmp_ri => sring
1259 do rf=1, sring%SPEC
1260 tmp_ri => tmp_ri%PAST
1261 deallocate (tmp_ri%NEXT)
1262 enddo
1263 srgoal=.true.
1264 goto 001
1265
1266 else
1267
1268! If all the atoms are CHK and ring is bigger than the initial ring
1269! the initial ring is strong .. we have to check this
1270 rf=0
1271 do rg=1, nna
1272 if (chks(rg)) rf=rf+1
1273 enddo
1274 if (rf .eq. nna) then
1275
1276 tmp_ri => sring
1277 do rg=1, sring%SPEC
1278 tmp_ri => tmp_ri%PAST
1279 deallocate (tmp_ri%NEXT)
1280 enddo
1281 frgoal=.true.
1282 goto 001
1283
1284 else
1285
1286! Else the new ring has to be tested
1287 rr = sring%SPEC+1
1288 if (allocated(newter)) deallocate(newter)
1289 allocate(newter(rr), stat=err)
1290 if (err .ne. 0) then
1291 alc_tab="NEWTER"
1292 alc=.true.
1293 goto 001
1294 endif
1295 srgoal=.false.
1296 tmp_ri => sring
1297 do rg=1, rr
1298 newter(rr-rg+1)=tmp_ri%ATOM
1299 if (rg .lt. rr) then
1300 tmp_ri => tmp_ri%PAST
1301 deallocate (tmp_ri%NEXT)
1302 endif
1303 enddo
1304 dlow=.false.
1305 sring => st_ring
1306 if (idz.eq.0) then
1307 if (dmin .eq. 1) then
1308 ro=2
1309 rp=rj
1310 dlow=.true.
1311 else
1312 ro=1
1313 rp=rr-1
1314 endif
1315 else
1316 ro=1
1317 rp=rr-1
1318 endif
1319
1320 do rg=ro, rp
1321
1322 if (idz.eq.0) then
1323 if (dmin .eq. 1) then
1324 dlow=.true.
1325 rq=rj+2
1326 else
1327 rq=rg+1
1328 endif
1329 else
1330 rq=rg+1
1331 endif
1332
1333 do rf=rq, rr
1334 call search_strong_rings (dlow, rg, rf, rr, lgtr, srgoal, frgoal, newter, cpt, vpt, chks)
1335 if (tbr .or. alc) goto 001
1336 if (srgoal .or. frgoal) goto 001
1337 do rl=1, dlgtr
1338 chks(toter(rl))=.true.
1339 enddo
1340 if (idz.eq.0 .and. cutring(rh)) chks(totpath(rh,1))=.true.
1341 enddo
1342
1343 enddo
1344
1345 if (allocated(newter)) deallocate(newter)
1346
1347 endif
1348
1349 endif
1350
1351 if (idz.eq.0 .and. cutring(rh)) chks(totpath(rh,1))=.false.
1352
1353 enddo
1354
1355 else
1356
1357 srgoal=.false.
1358
1359 endif
1360
1361 if (allocated(totpath)) deallocate(totpath)
1362 if (allocated(cutring)) deallocate(cutring)
1363 if (allocated(strst)) deallocate(strst)
1364
1365 enddo
1366
1367endif
1368
1369001 continue
1370
1371if (allocated(totpath)) deallocate(totpath)
1372if (allocated(cutring)) deallocate(cutring)
1373if (allocated(strst)) deallocate(strst)
1374if (allocated(newter)) deallocate(newter)
1375
1376do rg=1, dlgtr
1377 chks(toter(rg))=.false.
1378enddo
1379
1380END SUBROUTINE
1381
1382RECURSIVE SUBROUTINE path_search (AT0,AT1,AT2,IDT1,IDT2,DMAX,DMED,DARING,NPATH,DLPATH, &
1383 STPATH,ACRING,TPATH,CUTPATH,CPT,VPT,CHK,CHKS,SRING)
1384USE parameters
1385IMPLICIT NONE
1386
1387INTEGER, INTENT(IN) :: at0, at1, at2, idt1, idt2, dmax, dmed, daring
1388INTEGER, INTENT(INOUT) :: npath
1389LOGICAL, INTENT(INOUT) :: dlpath
1390INTEGER, DIMENSION(DMAX*DMAX), INTENT(INOUT) :: stpath
1391INTEGER, DIMENSION(DMAX*DMAX,DMAX), INTENT(INOUT) :: tpath
1392INTEGER, DIMENSION(DMED), INTENT(IN) :: acring
1393INTEGER, DIMENSION(NNA), INTENT(IN) :: cpt
1394INTEGER, DIMENSION(NNA,MAXN), INTENT(IN) :: vpt
1395LOGICAL, DIMENSION(DMAX*DMAX), INTENT(INOUT) :: cutpath
1396LOGICAL, DIMENSION(NNA), INTENT(INOUT) :: chk, chks
1397TYPE (ring), POINTER, INTENT(INOUT) :: sring
1398
1399INTEGER :: at3, at4, at5, at6, at7
1400INTEGER :: duv, duw, dvw
1401LOGICAL :: val1, val2
1402LOGICAL :: touch
1403TYPE (ring), POINTER :: tmpr
1404
1405INTERFACE
1406 SUBROUTINE do_ring (THE_RING, ELEM_DO)
1407 USE parameters
1408 TYPE (ring), POINTER, INTENT(INOUT) :: the_ring
1409 INTEGER, INTENT(IN) :: elem_do
1410 END SUBROUTINE
1411END INTERFACE
1412
1413chk(at1)=.true.
1414
1415if (at1.eq.at2 .and. sring%SPEC.eq.dmax) then
1416
1417
1418 npath=npath+1
1419 tmpr => sring
1420 do at3=1, dmax
1421 tpath(npath,dmax-at3+1)=tmpr%ATOM
1422 if (at3 .lt. dmax) tmpr => tmpr%PAST
1423 enddo
1424
1425else
1426
1427 do at4=1, cpt(at1)
1428
1429 at3=vpt(at1,at4)
1430 if (.not.chk(at3)) then
1431
1432 call do_ring (sring, at3)
1433 if (alc) goto 001
1434 if (at3 .eq. at2 .and. sring%SPEC.eq.dmax) then
1435
1436 npath=npath+1
1437 tmpr => sring
1438 do at5=1, dmax
1439 tpath(npath,dmax-at5+1)=tmpr%ATOM
1440 if (at5 .lt. dmax) tmpr => tmpr%PAST
1441 enddo
1442
1443 elseif (sring%SPEC.lt.dmax .and. .not.chks(at3)) then
1444
1445 touch=.false.
1446 at7=0
1447 val1=.false.
1448 val2=.false.
1449 do at5=1, cpt(at3)
1450 at6=vpt(at3,at5)
1451 if (at6 .eq. at0) val1=.true.
1452 if (at6 .eq. at2) val2=.true.
1453 if (chks(at6)) then
1454 at7=at7+1
1455 if (at6.ne.at0 .and. at6.ne.at2) stpath(npath+1)=at6
1456 endif
1457 enddo
1458 at6=0
1459 do at5=1, dmed
1460 if (acring(at5) .eq. stpath(npath+1)) then
1461 at6=at5
1462 exit
1463 endif
1464 enddo
1465 if (at7 .eq. 0) then
1466 touch=.false.
1467 elseif (at7.eq.1 .and. val1 .and. .not.val2) then
1468 touch=.false.
1469 elseif (at7.eq.1 .and. val2 .and. .not.val1) then
1470 touch=.false.
1471 elseif (at7.eq.1 .and. .not.val1 .and. .not.val2) then
1472 touch=.true.
1473 elseif (at7.eq.2 .and. val1 .and. val2 .and. dmax.eq.2) then
1474 touch=.false.
1475 elseif (at7.gt.2 .and. val1 .and. val2 .and. dmax.eq.2) then
1476 if (dlpath) then
1477 touch=.true.
1478 else
1479 if (at6 .ne. 0) then
1480 if (at6 .lt. idt1) then
1481 duv=idt1-at6
1482 dvw=idt2-idt1
1483 duw=dmed-(idt2-at6)
1484 elseif(at6 .lt. idt2) then
1485 duv=at6-idt1
1486 dvw=dmed-(at2-at1)
1487 duw=idt2-at6
1488 elseif(at6 .gt. idt2) then
1489 duv=dmed-(at6-idt1)
1490 dvw=idt2-idt1
1491 duw=at6-idt2
1492 endif
1493 if (duv.lt.daring-1 .and. duw.lt.daring-1) then
1494 cutpath(npath+1)=.true.
1495 touch=.false.
1496 elseif (dvw.lt.daring-1 .and. duw.lt.daring-1) then
1497 cutpath(npath+1)=.true.
1498 touch=.false.
1499 elseif (duv.lt.daring-1 .and. dvw.lt.daring-1) then
1500 cutpath(npath+1)=.true.
1501 touch=.false.
1502 else
1503 touch=.true.
1504 endif
1505 else
1506 cutpath(npath+1)=.true.
1507 touch=.false.
1508 endif
1509 endif
1510 else
1511 touch=.true.
1512 endif
1513 if (.not.touch) then
1514 call path_search (at0,at3,at2,idt1,idt2,dmax,dmed,daring,npath,dlpath, &
1515 stpath,acring,tpath,cutpath,cpt,vpt,chk,chks,sring)
1516 if (alc) goto 001
1517 endif
1518 endif
1519 sring => sring%PAST
1520 deallocate (sring%NEXT)
1521
1522 endif
1523
1524 enddo
1525
1526endif
1527
1528chk(at1)=.false.
1529001 continue
1530
1531END SUBROUTINE
1532
1533SUBROUTINE shortcut_ring (IDA, IDB, IDC, DLT, TABAB, SRING)
1534
1535USE parameters
1536
1537IMPLICIT NONE
1538
1539INTEGER, INTENT(IN) :: IDA, IDB, IDC, DLT
1540INTEGER, DIMENSION(DLT), INTENT(IN) :: TABAB
1541TYPE(ring), POINTER, INTENT(INOUT) :: SRING
1542INTEGER :: IDD
1543INTEGER :: LXY, LXZ, LYZ
1544
1545INTERFACE
1546 SUBROUTINE do_ring (THE_RING, ELEM_DO)
1547 USE parameters
1548 TYPE (RING), POINTER, INTENT(INOUT) :: THE_RING
1549 INTEGER, INTENT(IN) :: ELEM_DO
1550 END SUBROUTINE
1551END INTERFACE
1552
1553if (ida .gt. idc) then
1554! IDB > IDA > IDC
1555 lxz=ida-idc
1556 lxy=idb-ida
1557 lyz=dlt-(idb-idc)
1558 if (lxy .gt. lyz) then
1559 if (lxy .gt. lxz) then
1560 do idd=ida, idb
1561 call do_ring (sring, tabab(idd))
1562 if (alc) goto 001
1563 enddo
1564 else
1565 do idd=idc, ida
1566 call do_ring (sring, tabab(idd))
1567 if (alc) goto 001
1568 enddo
1569 endif
1570 else
1571 if (lxz .gt. lyz) then
1572 do idd=idc, ida
1573 call do_ring (sring, tabab(idd))
1574 if (alc) goto 001
1575 enddo
1576 else
1577 do idd=idb, dlt
1578 call do_ring (sring, tabab(idd))
1579 if (alc) goto 001
1580 enddo
1581 do idd=1, idc
1582 call do_ring (sring, tabab(idd))
1583 if (alc) goto 001
1584 enddo
1585 endif
1586 endif
1587else
1588! IDB > IDA .and. IDC .gt. IDA
1589 if (idc .gt. idb) then
1590! IDB > IDA .and. IDC .gt. IDA .and. IDC .gt. IDB
1591! => IDC > IDB > IDA
1592 lxy=idb-ida
1593 lyz=idc-idb
1594 lxz=dlt-(idc-ida)
1595 if (lxy .gt. lyz) then
1596 if (lxy .gt. lxz) then
1597 do idd=ida, idb
1598 call do_ring (sring, tabab(idd))
1599 if (alc) goto 001
1600 enddo
1601 else
1602 do idd=idc, dlt
1603 call do_ring (sring, tabab(idd))
1604 if (alc) goto 001
1605 enddo
1606 do idd=1, ida
1607 call do_ring (sring, tabab(idd))
1608 if (alc) goto 001
1609 enddo
1610 endif
1611 else
1612 if (lyz .ge. lxz) then
1613 do idd=idb, idc
1614 call do_ring (sring, tabab(idd))
1615 if (alc) goto 001
1616 enddo
1617 else
1618 do idd=ida, idb
1619 call do_ring (sring, tabab(idd))
1620 if (alc) goto 001
1621 enddo
1622 endif
1623 endif
1624 else
1625! IDB > IDA .and. IDC .gt. IDA .and. IDB .gt. IDC
1626! => IDB > IDC > IDA
1627 lxy=dlt-(idb-ida)
1628 lyz=idb-idc
1629 lxz=idc-ida
1630 if (lxy .gt. lyz) then
1631 if (lxy .gt. lxz) then
1632 do idd=idb, dlt
1633 call do_ring (sring, tabab(idd))
1634 if (alc) goto 001
1635 enddo
1636 do idd=1, ida
1637 call do_ring (sring, tabab(idd))
1638 if (alc) goto 001
1639 enddo
1640 else
1641 do idd=ida, idc
1642 call do_ring (sring, tabab(idd))
1643 if (alc) goto 001
1644 enddo
1645 endif
1646 else
1647 if (lyz .gt. lxz) then
1648 do idd=idc, idb
1649 call do_ring (sring, tabab(idd))
1650 if (alc) goto 001
1651 enddo
1652 else
1653 do idd=ida, idc
1654 call do_ring (sring, tabab(idd))
1655 if (alc) goto 001
1656 enddo
1657 endif
1658 endif
1659 endif
1660endif
1661
1662001 continue
1663
1664END SUBROUTINE
1665
1666SUBROUTINE testabab(VALTEST, LGTEST, PRIMT)
1667
1668USE parameters
1669
1670IMPLICIT NONE
1671
1672LOGICAL, INTENT(INOUT) :: VALTEST
1673INTEGER, INTENT(IN) :: LGTEST
1674INTEGER, DIMENSION(TAILLR), INTENT(IN) :: PRIMT
1675INTEGER :: LTA, LTB, LTC, LTD
1676
1677lta=lot(primt(1))
1678ltb=lot(primt(2))
1679
1680valtest=.true.
1681if (lta .ne. ltb) then
1682 do ltd=3, 2*lgtest
1683 ltc=lot(primt(ltd))
1684 if (mod(ltd,2).eq.0 .and. ltc.ne.ltb) then
1685 valtest=.false.
1686 exit
1687 elseif (mod(ltd,2).ne.0 .and. ltc.ne.lta) then
1688 valtest=.false.
1689 exit
1690 endif
1691 enddo
1692else
1693 valtest=.false.
1694endif
1695
1696END SUBROUTINE
1697
1698SUBROUTINE testhomo(VALTEST, LGTEST, PRIMT)
1699
1700USE parameters
1701
1702IMPLICIT NONE
1703
1704LOGICAL, INTENT(INOUT) :: VALTEST
1705INTEGER, INTENT(IN) :: LGTEST
1706INTEGER, DIMENSION(TAILLR), INTENT(IN) :: PRIMT
1707INTEGER :: LTA, LTB
1708
1709valtest=.true.
1710do lta=1, 2*lgtest
1711 ltb=lta+1
1712 if (lta .eq. 2*lgtest) ltb=1
1713 if (lot(primt(lta)) .eq. lot(primt(ltb))) then
1714 valtest=.false.
1715 exit
1716 endif
1717enddo
1718
1719END SUBROUTINE
1720
1721SUBROUTINE save_dijkstra_ring (TAB, TLES, RSAVED, OSAVED, TRING, INDT, RESL)
1722
1723USE parameters
1724
1725IMPLICIT NONE
1726
1727INTEGER, DIMENSION(TAILLR), INTENT(IN) :: TAB
1728INTEGER, INTENT(IN) :: TLES
1729INTEGER, DIMENSION(TAILLR,NUMA,TAILLR), INTENT(INOUT) :: RSAVED, OSAVED
1730INTEGER, DIMENSION(NUMA), INTENT(INOUT) :: INDT
1731INTEGER, DIMENSION(TAILLR), INTENT(INOUT) :: RESL, TRING
1732INTEGER :: idx, idy
1733LOGICAL :: NEWRING
1734INTEGER, DIMENSION(TLES) :: TOTRI, TOSAV
1735
1736! A ring has been found, we need to check if it has already been found or not
1737
1738do idx=1, tles
1739
1740! Creation of two tab first for the numerical sorting of the list
1741! The other without sorting for output
1742 totri(idx)= tab(idx)
1743 tosav(idx)= tab(idx)
1744
1745enddo
1746
1747call tri(totri, tles)
1748
1749if (tring(tles) .ne. 0) then
1750
1751 do idx=1, tring(tles)
1752! do-loop on existing rings to check if the new on has already been found
1753
1754 newring=.false.
1755
1756 do idy=1, tles
1757 if (totri(idy) .ne. rsaved(tles,idx,idy)) then
1758 newring=.true.
1759 exit
1760 endif
1761 enddo
1762
1763 if (.not.newring) then
1764
1765 ! Already been found n-times, increment of the counter
1766 indt(idx)=indt(idx)+1
1767 exit
1768
1769 endif
1770
1771 enddo
1772
1773else
1774
1775 newring=.true.
1776
1777endif
1778
1779if (newring) then
1780
1781! A new ring has been found
1782! We save the data
1783 resl(tles)=resl(tles)+1
1784 tring(tles)=tring(tles)+1
1785 if (tring(tles) .gt. numa) then
1786 tbr=.true.
1787 goto 001
1788 endif
1789 indt(tring(tles))=indt(tring(tles))+1
1790 do idx=1, tles
1791 rsaved(tles,tring(tles),idx)=totri(idx)
1792 osaved(tles,tring(tles),idx)=tosav(idx)
1793 enddo
1794
1795endif
1796
1797001 continue
1798
1799END SUBROUTINE
#define min(a, b)
Definition global.h:75
#define max(a, b)
Definition global.h:74
void show_error(char *error, int val, GtkWidget *win)
show error message
Definition interface.c:293
logical abab
integer nna
logical tbr
integer taillr
integer numa
logical alc
logical calc_strings
integer, dimension(:), allocatable lot
logical no_homo
integer function recrings(vid)
Definition resrings.F90:22
subroutine setup_cpat_vpat_ring(nat, str, cont, vois, cpt, vpt)
subroutine save_dijkstra_ring(tab, tles, rsaved, osaved, tring, indt, resl)
subroutine testabab(valtest, lgtest, primt)
subroutine dijkstra(node, cpt, vpt, que, matdis)
integer function primitive_rings()
recursive subroutine pair_search(goal, at1, at2, lg, maxm, minm, cpt, vpt, chk)
recursive subroutine search_strong_rings(dlow, idx, idy, dlgtr, lgtr, srgoal, frgoal, toter, cpt, vpt, chks)
subroutine primitive_ring_search_steps(rid)
subroutine testhomo(valtest, lgtest, primt)
subroutine strong_rings(fndtab, rlgth, rprobe, toprim, primto, asring, osring, trng, indt, resl, cpt, vpt)
recursive subroutine spath_rec(pth, node, length, lngth, matdis, cpt, vpt, npri, pordr)
integer function real_atom_id(ind, nats)
subroutine shortcut_ring(ida, idb, idc, dlt, tabab, sring)
recursive subroutine path_search(at0, at1, at2, idt1, idt2, dmax, dmed, daring, npath, dlpath, stpath, acring, tpath, cutpath, cpt, vpt, chk, chks, sring)
subroutine prim_ring(fndtab, node, pth, lgth, npt, cpt, vpt, qrng, pord, matdis, rsaved, osaved, trin, indp, reslp)
integer function rings_to_ogl(step, idsearch, nri, rsaved, osaved)
Definition rings_ogl.F90:22
integer function rings_to_ogl_menu(idsearch, nri)
subroutine do_ring(the_ring, elem_do)
Definition utils.F90:77
subroutine creat_ring(ring_init, elem_cr)
Definition utils.F90:61
subroutine tri(tab, dimtab)
Definition utils.F90:581