Statistiques
| Révision :

root / src / Calc_zmat.f90 @ 2

Historique | Voir | Annoter | Télécharger (32,19 ko)

1
      SUBROUTINE Calc_Zmat(na,atome,ind_zmat,val_zmat,x,y,z, &
2
           r_cov,  fact)
3

    
4
      use Path_module, only : Pi,max_Z, NMaxL, Nom, KINT, KREAL
5
      use Io_module, only : IoIn, IoOut
6

    
7
      IMPLICIT NONE
8

    
9
! Number of atoms
10
      integer(KINT), INTENT(IN) :: na
11
! Mass number of atoms
12
      INTEGER(KINT), INTENT(IN) :: atome(na)
13
! Coordinates
14
      real(KREAL), INTENT(IN) ::  x(na),y(na),z(na)
15
! Covalent radii
16
      REAL(KREAL), INTENT(IN) :: R_cov(Max_Z)
17
! Factor to determine connectivity
18
      REAL(KREAL) :: Fact
19
! Zmat index and values
20
      integer(KINT), INTENT(OUT) :: ind_zmat(na,5)
21
      real(KREAL),INTENT(OUT) ::  val_zmat(na,3)
22

    
23
      character(2) :: ATOM
24
      integer(KINT) :: at,long
25

    
26
      real(KREAL) ::  vx,vy,vz,dist
27
      INTEGER(KINT), ALLOCATABLE :: LIAISONS(:,:) !(na,0:NMaxL
28
      INTEGER(KINT), ALLOCATABLE :: LiaisonsBis(:,:) ! na,0:NMaxL
29
      INTEGER(KINT), ALLOCATABLE :: LieS_CP(:,:),LieS_CF(:,:) ! (na,0:NMaxL)
30
      INTEGER(KINT), ALLOCATABLE :: NbAt3(:,:) !(Na,2)
31
      INTEGER(KINT), ALLOCATABLE :: CycleAt(:) !(Na)
32
      INTEGER(KINT) :: Nbli,Nblj
33
      INTEGER(KINT), ALLOCATABLE :: CAFaire(:) ! Na
34

    
35
      Integer(KINT) :: AtTypCycl(Max_Z)
36
      Integer(KINT) :: NbCycle
37
      real(KREAL) ::  vx1,vy1,vz1,norm1
38
      real(KREAL) ::  vx2,vy2,vz2,norm2
39
      real(KREAL) ::  vx3,vy3,vz3,norm3
40
      real(KREAL) ::  vx4,vy4,vz4,norm4
41
      real(KREAL) ::  vx5,vy5,vz5,norm5
42
      real(KREAL) ::  val,val_d
43
      Logical PasFini,AtTerm,Debug,Bicycle,FLie3,FirstCycle
44
      LOGICAL, ALLOCATABLE ::  Former3(:), DejaFait(:) ! Na
45
      Logical FTmp
46
      LOGICAL F1213, F1223,F1323
47

    
48
      INTEGER(KINT) :: I,J,K, IZM, N1,n2, N3, IL, JL
49
      INTEGER(KINT) :: IdAt0, I3, IAt3, Idx3, I1, I0, IAf
50
      INTEGER(KINT) :: Izm1,Izm2, IZm3,IZm4, VCF, ICat
51
      INTEGER(KINT) :: IOld, IndFin, IdAtL, IndAFaire
52
      INTEGER(KINT) :: IAti, IAtD, IAtv, IIAtDh, IAtDh
53
      INTEGER(KINT) :: IAt0, IAta, IAt, Jat,Idx
54
      INTEGER(KINT) :: ITmp, IAtTmp, NbAt0
55
      INTEGER(KINT) :: NbLies, ICycle, IMax
56
      REAL(KREAL) :: d,d12, d13,d32
57

    
58
  INTERFACE
59
     function valid(string) result (isValid)
60
       CHARACTER(*), intent(in) :: string
61
       logical                  :: isValid
62
     END function VALID
63

    
64
     FUNCTION angle(v1x,v1y,v1z,norm1,v2x,v2y,v2z,norm2)
65
        use Path_module, only :  Pi,KINT, KREAL
66
       real(KREAL) ::  v1x,v1y,v1z,norm1
67
       real(KREAL) ::  v2x,v2y,v2z,norm2
68
       real(KREAL) ::  angle
69
     END FUNCTION ANGLE
70

    
71

    
72
  END INTERFACE
73

    
74

    
75

    
76
      debug=valid("Calc_zmat")
77
      if (debug) WRITE(*,*) "========== Entering Calc_zmat =========="
78

    
79
      FirstCycle=.TRUE.
80
      FTmp=.FALSE.
81
      NbCycle=0
82
      DO i=1,na
83
         DO J=1,5
84
            Ind_Zmat(i,J)=0
85
         END DO
86
      END DO
87
      ALLOCATE(Former3(Na), DejaFait(Na))
88
      ALLOCATE(CaFaire(Na), CycleAt(Na))
89
      ALLOCATE(NbAt3(Na,2))
90
      ALLOCATE(Liaisons(na,0:NMaxL),LiaisonsBis(na,0:NMaxL))
91
      ALLOCATE(Lies_CP(na,0:NMaxL), Lies_CF(na,0:NMaxL))
92

    
93

    
94
      WRITE(IOOUT,*) Na
95
      WRITE(IOOUT,*) 'Calc_zmat'
96
      DO I=1,na
97
         WRITE(IOOUT,*) NOM(Atome(I)),X(i),y(i),z(i)
98
      END DO
99

    
100
      if (na.le.2) THEN
101
         WRITE(*,*) "I do not work for less than 2 atoms :-p"
102
         RETURN
103
      END IF
104

    
105
!     Cas particulier: 3 atomes ou moins...
106
      if (Na.eq.3) THEN
107
         d12=sqrt((x(1)-x(2))**2+(y(1)-y(2))**2+(z(1)-z(2))**2)
108
         d13=sqrt((x(1)-x(3))**2+(y(1)-y(3))**2+(z(1)-z(3))**2)
109
         d32=sqrt((x(3)-x(2))**2+(y(3)-y(2))**2+(z(3)-z(2))**2)
110
         F1213=(d12<=d13)
111
         F1323=(d13<=d32)
112
         F1223=(d12<=d32)
113
         if (debug) THEN
114
            WRITE(*,*) "DEBUG Calc_Zmat 3 atoms"
115
            WRITE(*,*) "d12,d13,d32:",d12,d13,d32
116
            WRITE(*,*) "F1213,F1323,F1223:",F1213,F1323,F1223
117
         END IF
118
         if (F1213) THEN
119
            if (F1323) THEN
120
               ind_zmat(1,1)=3
121
               ind_zmat(2,1)=1
122
               ind_zmat(2,2)=3
123
               ind_zmat(3,1)=2
124
               ind_zmat(3,2)=1
125
               ind_zmat(3,3)=3
126
            ELSE
127
               ind_zmat(1,1)=1
128
               ind_zmat(2,1)=2
129
               ind_zmat(2,2)=1
130
               ind_zmat(3,1)=3
131
               ind_zmat(3,2)=2
132
               ind_zmat(3,3)=1
133
            END IF
134
         ELSE
135
            IF (F1223) THEN
136
               ind_zmat(1,1)=2
137
               ind_zmat(2,1)=1
138
               ind_zmat(2,2)=2
139
               ind_zmat(3,1)=3
140
               ind_zmat(3,2)=1
141
               ind_zmat(3,3)=2
142
            ELSE
143
               ind_zmat(1,1)=2
144
               ind_zmat(2,1)=3
145
               ind_zmat(2,2)=2
146
               ind_zmat(3,1)=1
147
               ind_zmat(3,2)=3
148
               ind_zmat(3,3)=2
149
            END IF
150
         END IF
151
         IF (debug) THEN
152
            DO i=1,na
153
               WRITE(*,*) (ind_zmat(i,j),j=1,5)
154
            END DO
155
         END IF
156

    
157
!     We have ind_zmat, we fill val_zmat
158
         val_zmat(1,1)=0.
159
         val_zmat(1,2)=0.
160
         val_zmat(1,3)=0.
161
         n2=ind_zmat(2,1)
162
         n1=ind_zmat(2,2)
163
         d=sqrt((x(n1)-x(n2))**2+(y(n1)-y(n2))**2+ &
164
              (z(n1)-z(n2))**2)
165
         val_zmat(2,1)=d
166
         val_zmat(2,2)=0.
167
         val_zmat(2,3)=0.
168
         n1=ind_zmat(3,1)
169
         n2=ind_zmat(3,2)
170
         n3=ind_zmat(3,3)
171
         CALL vecteur(n2,n1,x,y,z,vx1,vy1,vz1,norm1)
172
         if (debug) write(*,*) n1,n2,norm1
173
         val_zmat(3,1)=norm1
174

    
175
         CALL vecteur(n2,n3,x,y,z,vx2,vy2,vz2,norm2)
176
         val=angle(vx1,vy1,vz1,norm1,vx2,vy2,vz2,norm2)
177
         if (debug) write(*,*) n2,n3,norm2,val
178
         val_zmat(3,2)=val
179
         val_zmat(3,3)=0.
180

    
181
         RETURN
182
      END IF
183

    
184

    
185
 1036 FORMAT(I2)
186

    
187
!     Premiere etape : calcul des connectivites
188
      DO I=1,na
189
         DejaFait(I)=.FALSE.
190
         Former3(I)=.False.
191
         Do J=0,NMaxL
192
            Liaisons(I,j)=0.
193
            LiaisonsBis(I,j)=0.
194
         END DO
195
         DO J=1,5
196
            ind_zmat(I,J)=0
197
         END DO
198
      END DO
199

    
200
      if (debug) WRITE(IOOUT,*) "Liaisons initialiazed"
201
!     DO IL=1,na
202
!     WRITE(IOOUT,1003) Il,(LIAISONS(IL,JL),JL=0,NMaxL)
203
!     WRITE(IOOUT,1003) Il,(LIAISONSBis(IL,JL),JL=0,NMaxL)
204
!     END DO
205

    
206
      Call CalcCnct(na,atome,x,y,z,LIAISONS,r_cov,fact)
207

    
208
      if (debug) THEN
209
         WRITE(IOOUT,*) "Connections calculated"
210
         DO IL=1,na
211
            WRITE(IOOUT,1003) Il,(LIAISONS(IL,JL),JL=0,NMaxL)
212
         END DO
213
      END IF
214

    
215

    
216
!     on va maintenant trier ces connectivites en 2 :
217
!     Lies_CF : vers l'exterieur de la molecule
218
!     Lies_CP : vers l'interieur de la molecule
219
!     Pour cela, on procede 'a l'envers' : on regarde les atomes
220
!     auxquels sont lies les atomes attaches -> on remplit Lies_CF/P
221
!     et on supprime ces atomes...
222

    
223
!     v2.0 on copie Liaison dans LiaisonBis. On analyse LiaisonBis
224
!     tout en modifiant Liaison. Cela evite de fausser l'analyse: un atome
225
!     qui est lie initialement a 2 atomes (et qui n'est donc pas terminal)
226
!     peut devenir terminal en milieu de traitement si on annule la liaison
227
!     qui le liait a un atome terminal situ? avant lui...
228
!     ex: H2O code dans l'ordre H,O,H.
229
      PasFini=.True.
230
      AtTerm=.True.
231
      DO WHILE (PasFini.AND.AtTerm)
232
         PasFini=.False.
233
         AtTerm=.False.
234
         DO I=1,na
235
            DO J=0,NMaxL
236
               LiaisonsBis(I,J)=Liaisons(I,J)
237
            END DO
238
         END DO
239
!     DO IL=1,na
240
!     WRITE(IOOUT,1003) Il,(LIAISONS(IL,JL),JL=0,NMaxL)
241
!     WRITE(IOOUT,1003) Il,(LIAISONSBis(IL,JL),JL=0,NMaxL)
242
!     END DO
243
!     WRITE(IOOUT,*) "=================================="
244

    
245

    
246
         DO I=1,na
247
            if ((LiaisonsBis(I,0).eq.1).AND.Liaisons(I,0).ne.0) THEN
248
               AtTerm=.True.
249
!     On enleve cet atome
250
               Liaisons(I,0)=0
251
               NbLies=Lies_CP(I,0)+1
252
               Lies_CP(I,NbLies)=Liaisons(I,1)
253
               Lies_CP(I,0)=NbLies
254
               Liaisons(Liaisons(I,1),0)=Liaisons(Liaisons(I,1),0)-1
255

    
256
               NbLies=Lies_CF(Liaisons(I,1),0)+1
257
               Lies_CF(Liaisons(I,1),NbLies)=I
258
               Lies_CF(Liaisons(I,1),0)=NbLies
259

    
260
               Call Annul(Liaisons,Liaisons(I,1),I)
261

    
262
            END IF
263

    
264
            if (Liaisons(I,0).ge.1) THEN
265
               PasFini=.TRUE.
266
            END IF
267

    
268
         END DO
269
         if (debug) WRITE(*,*) 'PasFini, AtTerm',PasFini,AtTerm
270
         If (PasFini.AND.(.Not.AtTerm)) THEN
271
!     Pas d'atomes terminaux lors de l'exploration precedente.
272
!     On a soit une erreur, soit un cycle. Je ne sais pas encore gerer
273
!     tous les  cas :  on affiche un warning
274
            WRITE(*,*) "Je ne trouve pas d'atomes terminaux"
275
            WRITE(*,*) "Possibilite de molecule cyclique"
276
            WRITE(*,*) "Cas en cours de traitement: verifier l'output"
277
!     On va d'abord voir si on a des atomes li?s a plus de 2 centres.
278
            AtTerm=.TRUE.
279
            Bicycle=.False.
280
            ICycle=0
281
            IMax=0
282
            DO I=1,na
283
               if (Liaisons(I,0).gt.2) THEN
284
                  ICycle=ICycle+1
285
                  BiCycle=.True.
286
                  If (Liaisons(I,0).gt.IMax) Imax=Liaisons(I,0)
287
                  Former3(I)=.True.
288
               END IF
289
            END DO
290
            IF (BiCycle) THEN
291
!     On a des atomes lies a 3 ou plus d'atomes...
292
!     donc soit des bicycles, soit plusieurs
293
!     cycles attaches par un sommet...
294
               WRITE(*,*) "On dirait un bicyle... on essaie"
295
               WRITE(*,*) ICycle, "atomes lies a plus de 2 atomes"
296
               WRITe(*,*) "Nb Attaches max:",IMax
297
!     Plusieurs cas possibles pour un bicycle:
298
!     1) 2 cycles relies par un sommet, ICycle=2, IMax=3
299
!     2) 2 cycles relies par une arrete, ICycle=2, Imax=3
300
               If (Imax.Eq.3) THEN
301
!     on doit pouvoir traiter celui la...
302
!     On classe les atomes li?s a trois atomes, par le nombre d'atomes
303
!     lies a trois atomes
304
!     auxquels ils sont li?s ... interessant pour les composes asterisques.
305
                  I3=0
306
                  FLie3=.False.
307
                  DO I=1,Na
308
                     If (Liaisons(I,0).EQ.3) THEN
309
                        I3=I3+1
310
                        K=0
311
                        DO J=1,Liaisons(I,0)
312
                           If (Liaisons(Liaisons(I,J),0).Eq.3) THEN
313
                              k=k+1
314
                              FLie3=.True.
315
                           END IF
316
                        END DO
317
                        NbAt3(I3,2)=k
318
                        NbAt3(I3,1)=I
319
                     END IF
320
                  END DO
321
!     A-t-on deux atomes a 3 lies ensemble ?
322
                  IF (FLie3) THEN
323
!     on les classe pas nb at lies a 3
324
                     IAt3=0
325
                     Idx3=0
326
                     DO I=1,I3
327
                        IF (NbAt3(I,2).ge.Iat3) THEN
328
                           IAt3=NbAt3(I,2)
329
                           Idx3=NbAt3(I,1)
330
                        END IF
331
                     END DO
332
!     On va enlever ces liaisons entre atomes a 3, en les mettant
333
!     en CF de l'atome 'central'
334
                     if (debug) WRITE(*,*) "Atome ",Idx3, &
335
                          " retenu, li? a",IAt3," atomes 3"
336
                     DO I=1,Liaisons(Idx3,0)
337
                        I1=Liaisons(Idx3,I)
338
                        If (Liaisons(I1,0).EQ.3) THEN
339
                           if (debug) WRITE(*,*) "Traitement ",I1,Idx3
340
                           NbLies=Lies_CF(Idx3,0)+1
341
                           Lies_CF(Idx3,NbLies)=I1
342
                           Lies_CF(Idx3,0)=NbLies
343
                           NbLies=Lies_CP(I1,0)+1
344
                           Lies_CP(I1,NbLies)=Idx3
345
                           Call Annul(Liaisons,I1,Idx3)
346
                           Call Annul(Liaisons,Idx3,I1)
347
                           Liaisons(Idx3,0)=Liaisons(Idx3,0)-1
348
                           Liaisons(I1,0)=Liaisons(I1,0)-1
349
                        END IF
350
                     END DO
351
                  ELSE
352
                     WRITE(*,*) "Aucune liaisons entre deux atomes li?s"
353
                     WRITE(*,*) "Pas encore trait?"
354
                     STOP
355
                  END IF        !FLie3=T ?
356
               END IF           !Imax=3 ?
357
            ELSE                ! BiCyle ?
358
!     Un seul cycle. Facile :-)
359
               WRITE(*,*) "Un  cycle identifie..."
360
               NbCycle=NbCycle+1
361
               if (debug) WRITE(*,*) 'Considering cycle ',NbCycle
362
               If (NbCycle.ge.2) THEN
363
!     si ce n'est pas le premier cycle que l'on met, on regarde si parmi les
364
!     atomes du cycle, l'un d'eux etait avant attache a 3 atomes...
365
                  I=1
366
                  DO WHILE (Liaisons(I,0).ne.2)
367
                     I=I+1
368
                  END DO
369
                  if (debug) WRITE(*,*) "I>2:",I,Former3(I)
370
                  FTmp=Former3(I)
371
                  I0=I
372
                  IOld=I
373
                  I1=I
374
                  I=Liaisons(I,1)
375
                  DO WHILE (.NOT.FTmp)
376
                     I1=Liaisons(I,1)
377
                     If (I1.Eq.IOld) I1=Liaisons(I,2)
378
                     FTmp=Former3(I1)
379
                     if (debug) WRITE(*,*) "I,I1,I0,IOld",I,I1,I0, &
380
                          IOld,FTmp
381
                     IF (I1.eq.I0) FTmp=.TRUE.
382
                     if (debug) WRITE(*,*) "I,I1,I0,IOld",I,I1,I0, &
383
                          IOld,FTmp
384
                     IOld=I
385
                     I=I1
386
                  END DO
387
                  if (debug) WRITE(*,*)  "I,I1,I0,IOld",I,I1,I0, &
388
                       IOld,FTmp
389
                  IF (Former3(I1)) THEN
390
!     On a notre atome particulier ... cool :-)
391
                     if (debug) WRITE(*,*) "Atome former3",I1
392
                     ITmp=I1
393
                  END IF
394
               END IF           ! NbCycle >=2
395
               IF (.NOT.Ftmp) THEN
396
                  if (debug) WRITE(*,*) "Pas trouve de former3"
397
!     on regarde si il y a un atome particulier.. ie un heteroatome ou autre.
398
                  DO I=1,Max_Z
399
                     AtTypCycl(I)=0
400
                  END DO
401
                  DO I=1,na
402
                     if (Liaisons(I,0).eq.2) &
403
                          AtTypCycl(Atome(I))=AtTypCycl(Atome(I))+1
404
                     if (debug) WRITE(*,*) I,Atome(I), &
405
                          AtTypCycl(Atome(I)), &
406
                          Liaisons(I,0)
407
                  END DO
408
                  Itmp=NmaxL+1
409
                  IAtTmp=0
410
                  DO I=1,Max_Z
411
                     If ((AtTypCycl(I).gt.0).and.(AtTypCycl(I).le.Itmp)) &
412
                          THEN
413
                        Itmp=AtTypCycl(I)
414
                        IAtTmp=I
415
                     END IF
416
                  END DO
417
                  if (debug) WRITE(*,*) 'Itmp,IAtTmp:',Itmp,IAtTmp
418
!     On a le type de l'atome particulier... on va prendre le premier venu
419
                  DO I=na,1,-1
420
                     If ((Atome(I).eq.IAtTmp).AND.(Liaisons(I,0).Eq.2)) &
421
                          Itmp=I
422
                  END DO
423
               END IF
424
               if (debug) WRITE(*,*) 'Atome ',Itmp,'(',IAtTmp,') retenu'
425
!     On va tricher en enlevant les liaisons de cet atome a la main...
426
               I0=Itmp
427
               I1=Liaisons(I0,1)
428
               DO WHILE (I1.Ne.ITmp)
429
                  if (debug) WRITE(*,*) "Going from",I0,"to ",I1
430
!     On rajoute ces deux liaisons en CF de Itmp
431
                  NbLies=Lies_CF(I0,0)+1
432
                  Lies_CF(I0,NbLies)=Liaisons(I0,1)
433
                  Lies_CF(I0,0)=NbLies
434
!     et les liaisons vers Itmp deviennent des CP pour les autres atomes
435
                  NbLies=Lies_CP(I1,0)+1
436
                  Lies_CP(I1,NbLies)=I0
437
                  Lies_CP(I1,0)=NbLies
438

    
439
                  Call Annul(Liaisons,I1,I0)
440
                  Liaisons(I1,0)=Liaisons(I1,0)-1
441
                  Liaisons(I0,0)=Liaisons(I0,0)-1
442

    
443
                  DO IL=1,na
444
                     WRITE(IOOUT,1003) Il,(LIAISONS(IL,JL),JL=0,NMaxL)
445
                  END DO
446
                  I0=I1
447
                  I1=Liaisons(I0,1)
448

    
449
               end do
450
               Call Annul(Liaisons,I1,I0)
451
               Liaisons(I1,0)=Liaisons(I1,0)-1
452
               Liaisons(I0,0)=Liaisons(I0,0)-1
453
            END IF
454
         END IF
455
         DO IL=1,na
456
            WRITE(IOOUT,1003) Il,(LIAISONS(IL,JL),JL=0,NMaxL)
457
         END DO
458
!     WRITE(IOOUT,*) "=================================="
459
!     WRITE(IOOUT,*) "=================================="
460
      END DO
461

    
462
!     WRITE(IOOUT,*) "=================================="
463
!     Il ne reste plus que des atomes lies a rien...
464
!     ce sont les 'centres' de la molecule. On repart
465
!     d'eux pour construire le reste de la molecule.
466

    
467
 1003 FORMAT(1X,I4,' - ',15(I5))
468
!     Avant de partir, on va classer, pour chaque atome, les atomes CF par
469
!     nombre de masse decroissant.
470
      DO I=1,na
471
!     WRITE(*,*) I,Lies_CF(I,0),(Atome(Lies_CF(I,J)),j=1,Lies_CF(I,0))
472
         DO J=1,Lies_CF(I,0)-1
473
            DO K=J+1,Lies_CF(I,0)
474
               if (atome(Lies_CF(I,K))>atome(Lies_CF(I,J))) THEN
475
                  Itmp=Lies_CF(I,K)
476
                  Lies_CF(I,K)=Lies_CF(I,J)
477
                  Lies_CF(I,J)=Itmp
478
               END IF
479
            END DO
480
         END DO
481
!     WRITE(*,*) I,Lies_CF(I,0),(Atome(Lies_CF(I,J)),j=1,Lies_CF(I,0))
482
      END DO
483

    
484
      IF (Debug) THEN
485
         WRITE(IOOUT,*) 'LIAISONS'
486
         DO I=1,na
487
            WRITE(IOOUT,1003) i,(LIAISONS(I,J),J=0,NMaxL)
488
         END DO
489

    
490
         WRITE(IOOUT,*) 'LIes_CF'
491
         DO I=1,na
492
            WRITE(IOOUT,1003) i,(LIeS_CF(I,J),J=0,NMaxL)
493
         END DO
494

    
495
         WRITE(IOOUT,*) 'LIes_CP'
496
         DO I=1,na
497
            WRITE(IOOUT,1003) i,(LIeS_CP(I,J),J=0,NMaxL)
498
         END DO
499
      END IF
500

    
501

    
502
!     On compte le nb d'atomes sans atomes CP (centripetes)
503
      NbAt0=0
504
      DO I=1,na
505
         IF (Lies_CP(I,0).eq.0) THEN
506
            NbAt0=NbAt0+1
507
            IF (DEBUG) WRITE(*,*) "Center atom",NbAt0,I,Atome(I)
508
         END IF
509
      END DO
510

    
511
!     On va les traiter tous en construisant les molecules en partant d'eux
512
!     Le premier atome sans CP est different des autres car il fixe
513
!     l'origine
514

    
515
      IZm=1
516
!     Boucle pour trouver celui qui a le plus d'atomes CF
517
      IdAt0=0
518
      VCF=0
519
      DO ICAt=1,na
520
         if ((Lies_CP(ICaT,0).eq.0).AND.(Lies_CF(ICAt,0).gt.VCF)) THEN
521
            IdAt0=ICat
522
            VCF=Lies_CF(ICAt,0)
523
         END IF
524
      END DO
525
      Lies_CP(IdAt0,0)=-1
526

    
527
!     WRITE(IOOUT,*) 'Atome 1', IdAt0, Nom(Atome(IdAt0))
528
      Izm1=IdAt0
529
      ind_zmat(izm,1)=Izm1
530
      ind_zmat(izm,2)=0
531
      ind_zmat(izm,3)=0
532
      ind_zmat(izm,4)=0
533
      ind_zmat(izm,5)=0
534
      val_zmat(izm,1)=0.0
535
      val_zmat(izm,2)=0.0
536
      val_zmat(izm,3)=0.0
537
      DejaFait(Izm1)=.True.
538

    
539
!     Les atomes CF lies a IdAt0 sont mis en attente pour
540
!     etre traites
541

    
542
      IndFin=1
543
      Do iaf=1,Lies_CF(IdAt0,0)
544
         CAfaire(IndFin)=Lies_CF(IdAt0,Iaf)
545
         IndFin=IndFin+1
546
      END DO
547
      CAfaire(IndFin)=0
548

    
549
!     On construit la premiere couche qui est speciale car elle fixe les
550
!     axes.
551
!     Plusieurs cas sont possibles suivant le nb d'atomes CF
552

    
553
      IF (Lies_CF(IdAt0,0).ge.3) THEN
554
         if (debug) WRITE(*,*) 'Cas tres simple,',IdAt0, &
555
              ' li? a plus de 3 atomes'
556
         IZm2=Lies_CF(IdAt0,1)
557
         IZm3=Lies_CF(IdAt0,2)
558
!     WRITE(IOOUT,*) 'Atome 2' , Izm2, Nom(Atome(Izm2))
559
!     WRITE(IOOUT,*) 'Atome 3' ,Izm3, Nom(Atome(izm3))
560

    
561
         Izm=2
562
         CALL vecteur(IZm1,IZm2,x,y,z,vx1,vy1,vz1,norm1)
563
!     write(*,11) n1,n2,norm1
564

    
565
         ind_zmat(izm,1)=izm2
566
         ind_zmat(izm,2)=izm1
567
         ind_zmat(izm,3)=0
568
         ind_zmat(izm,4)=0
569
         ind_zmat(izm,5)=0
570
         val_zmat(izm,1)=norm1
571
         val_zmat(izm,2)=0.0
572
         val_zmat(izm,3)=0.0
573
         DejaFait(Izm2)=.TRUE.
574

    
575
         Izm=3
576
         CALL vecteur(izm1,izm3,x,y,z,vx2,vy2,vz2,norm2)
577
         val=angle(vx1,vy1,vz1,norm1,vx2,vy2,vz2,norm2)
578

    
579
!     write(*,11) n1,n2,norm1,n3,val
580

    
581
         ind_zmat(izm,1)=izm3
582
         ind_zmat(izm,2)=izm1
583
         ind_zmat(izm,3)=izm2
584
         ind_zmat(izm,4)=0
585
         ind_zmat(izm,5)=0
586
         val_zmat(izm,1)=norm2
587
         val_zmat(izm,2)=val
588
         val_zmat(izm,3)=0.0
589
         DejaFait(Izm3)=.TRUE.
590

    
591
         DO IdAtl=3,Lies_CF(IdAt0,0)
592
            Izm4= Lies_CF(IdAt0,IdAtl)
593
!     WRITE(IOOUT,*) 'Atome ',Izm+1,Izm4,Nom(Atome(Izm4)),Izm1,
594
!     $Izm2,Izm3
595
            Izm=Izm+1
596
            Call AddLigne(Izm,Izm4,Izm1,Izm2,Izm3,ind_zmat,val_zmat, &
597
                 x,y,z)
598
            DejaFait(Izm4)=.TRUE.
599
         END DO
600
      END IF
601

    
602
      IF (Lies_CF(Izm1,0).eq.2) THEN
603
         if (debug) WRITE(*,*) 'Cas simple,',IdAt0, &
604
              ' li? a 2 atomes'
605

    
606
         IZm2=Lies_CF(IdAt0,1)
607
         IZm3=Lies_CF(IdAt0,2)
608
         Izm=2
609
         CALL vecteur(IZm1,IZm2,x,y,z,vx1,vy1,vz1,norm1)
610
!     write(*,11) n1,n2,norm1
611

    
612
         ind_zmat(izm,1)=izm2
613
         ind_zmat(izm,2)=izm1
614
         ind_zmat(izm,3)=0
615
         ind_zmat(izm,4)=0
616
         ind_zmat(izm,5)=0
617
         val_zmat(izm,1)=norm1
618
         val_zmat(izm,2)=0.0
619
         val_zmat(izm,3)=0.0
620
         DejaFait(Izm2)=.TRUE.
621

    
622
         Izm=3
623

    
624
         CALL vecteur(izm1,izm3,x,y,z,vx2,vy2,vz2,norm2)
625
         val=angle(vx1,vy1,vz1,norm1, &
626
              vx2,vy2,vz2,norm2)
627

    
628
!     write(*,11) n1,n2,norm1,n3,val
629

    
630
         ind_zmat(izm,1)=izm3
631
         ind_zmat(izm,2)=izm1
632
         ind_zmat(izm,3)=izm2
633
         ind_zmat(izm,4)=0
634
         ind_zmat(izm,5)=0
635
         val_zmat(izm,1)=norm2
636
         val_zmat(izm,2)=val
637
         val_zmat(izm,3)=0.0
638
         DejaFait(Izm3)=.TRUE.
639

    
640
      END IF
641

    
642
      IF (Lies_CF(Izm1,0).eq.1) THEN
643
         if (debug) WRITE(*,*) 'Cas merdouille,',IdAt0, &
644
              ' li? a 1 atome'
645

    
646
         IZm2=Lies_CF(IdAt0,1)
647
         Izm=2
648
         CALL vecteur(IZm1,IZm2,x,y,z,vx1,vy1,vz1,norm1)
649
!     write(*,11) n1,n2,norm1
650

    
651
         ind_zmat(izm,1)=izm2
652
         ind_zmat(izm,2)=izm1
653
         ind_zmat(izm,3)=0
654
         ind_zmat(izm,4)=0
655
         ind_zmat(izm,5)=0
656
         val_zmat(izm,1)=norm1
657
         val_zmat(izm,2)=0.0
658
         val_zmat(izm,3)=0.0
659
         DejaFait(Izm2)=.TRUE.
660

    
661
!     Pour les autres atomes, on prend les atomes
662
!     CF lie a l'tome CF lie a At0... en esperant
663
!     qu'il en a !!!
664
!     => il faudra voir le cas ou il n'en a pas !!!
665
!     en attendant on rajoute le test...
666
         IF (Lies_CF(Izm2,0).Eq.0) THEN
667
            WRITE(*,*) "Je n'arrive pas a trouver les premiers"
668
            WRITE(*,*) "atomes pour construire la molecule"
669
            WRITE(*,*) "Atome central li? au plus a 1 atome",Izm1,izm2
670
            WRITE(*,*) "Et atome 2 li? a rien... moi perdu"
671
            STOP
672
         END IF
673

    
674
!     On ajoute les atomes lies a cet atome dans la liste a faire
675
         Do iaf=1,Lies_CF(Izm2,0)
676
            CAfaire(IndFin)=Lies_CF(Izm2,Iaf)
677
            IndFin=IndFin+1
678
         END DO
679
         CAfaire(IndFin)=0
680
         Izm3= Lies_CF(Izm2,1)
681
         Izm=3
682
         CALL vecteur(izm2,izm1,x,y,z,vx1,vy1,vz1,norm1)
683

    
684
         CALL vecteur(izm2,izm3,x,y,z,vx2,vy2,vz2,norm2)
685
         val=angle(vx1,vy1,vz1,norm1, &
686
              vx2,vy2,vz2,norm2)
687

    
688
!     write(*,11) n1,n2,norm1,n3,val
689

    
690
         ind_zmat(izm,1)=izm3
691
         ind_zmat(izm,2)=izm2
692
         ind_zmat(izm,3)=izm1
693
         ind_zmat(izm,4)=0
694
         ind_zmat(izm,5)=0
695
         val_zmat(izm,1)=norm1
696
         val_zmat(izm,2)=val
697
         val_zmat(izm,3)=0.0
698
         DejaFait(Izm3)=.TRUE.
699

    
700
!     je pense que ce qui suit est totalement inutile
701
!     C     DO IdAtl=3,Lies_CF(IdAt0,0)
702
!     C     Izm4= Lies_CF(IdAt0,IdAtl)
703
!     C     Izm=Izm+1
704
!     C     Call AddLigne(Izm,Izm4,Izm1,Izm2,Izm3,ind_zmat,val_zmat
705
!     C     $,x,y,z)
706
!     C     DejaFait(Izm4)=.TRUE.
707
!     C     END DO
708
      END IF
709

    
710
!     on a cree la premiere couche autour du premier centre
711
!     reste a finir les autres couches
712
      IndAFaire=1
713
      if (debug) WRITE(IOOUT,*) "CaFaire:",CaFaire
714
      Do WHILE (Cafaire(IndAFaire).ne.0)
715
         IAt0=Cafaire(IndAfaire)
716
         if (debug) WRITE(*,*) "IndAFaire,IAt0,Lies_CF(IAt0,0)", &
717
              IndAFaire,IAt0,Lies_CF(IAt0,0)
718
         if (Lies_CF(IAt0,0).ge.1) THEN
719
!     IAt0 est l'atome pour lequel on construit la couche suivante
720
!     le premier atome lie est particulier car il definit l'orientation
721
!     de ce fragment
722
            IAti=Lies_CF(IAt0,1)
723
!     WRITE(IOOUT,*) 'IAti:',IAti
724
            IAtd=IAt0
725
!     WRITE(IOOUT,*) 'IAtd:',IAtd
726
            IAtv=Lies_CP(IAt0,1)
727
!     WRITE(IOOUT,*) 'IAtv:',IAtv
728
            IIAtdh=1
729
            IAtdh=Lies_CF(IAtv,IIatdh)
730
            DO WHILE (Iatdh.eq.IAt0)
731
               IIatdh=IIatdh+1
732
               IAtdh=Lies_CF(IAtv,IIatdh)
733
            END DO
734
            IF (IAtdh.eq.0) IAtdh=Lies_CP(IAtv,1)
735
!     WRITE(IOOUT,*) 'IAtdh:',IAtdh
736
            IF (.NOT.DejaFait(IAti)) THEN
737
               Izm=Izm+1
738
               if (debug) WRITE(*,*) 'izm,IAti,IAtd,IAtv,IAtdh', &
739
                    izm,IAti,IAtd,IAtv,IAtdh
740
               Call AddLigne(Izm,IAti,IAtd,IAtv,IAtdh,ind_zmat,val_zmat &
741
                    ,x,y,z)
742
               DejaFait(IAti)=.TRUE.
743
            END IF
744

    
745
            CAfaire(IndFin)=Lies_CF(IAt0,1)
746
            IndFin=IndFin+1
747
!     Le traitement des autres est plus facile
748
            IAtdh=Lies_CF(IAt0,1)
749
            DO IAta=2,Lies_CF(IAt0,0)
750
               IAtI=Lies_CF(IAt0,IAta)
751
                     if (debug) WRITE(*,*) " Problem is here; IndFin:",I
752
               CAfaire(IndFin)=IAtI
753
               IndFin=IndFin+1
754

    
755
               IF (.NOT.DejaFait(IAti)) THEN
756
                  Izm=Izm+1
757
                  Call AddLigne(Izm,IAti,IAtd,IAtv,IAtdh,ind_zmat &
758
                       ,val_zmat,x,y,z)
759
                  DejaFait(IAti)=.TRUE.
760
               END IF
761
            END DO
762

    
763
            CAfaire(IndFin)=0
764
         END IF
765
         IndAFaire=IndAFaire+1
766
      END DO
767

    
768

    
769
!     On a fini de creer la molecule autour du premier atome 'centre'
770
!     Pour les autres c'est presque id... sauf que les axes sont deja fixes
771
!     On pourrait imaginer de mettre des atomes fictifs pour redefinir des axes
772
!     locaux... dans une autre version
773
!     V2.0
774
      NbAt0=NbAt0-1
775
      DO I=1,NbAt0
776
!     Boucle pour trouver celui qui a le plus d'atomes CF
777

    
778
         IdAt0=0
779
         VCF=0
780

    
781
         DO ICAt=1,na
782
            if ((Lies_CP(ICaT,0).eq.0).AND.(Lies_CF(ICAt,0).gt.VCF)) &
783
                 THEN
784
               IdAt0=ICat
785
               VCF=Lies_CF(ICAt,0)
786
            END IF
787
         END DO
788
         Lies_CP(IdAt0,0)=-1
789

    
790
         IF (debug) WRITE(*,*) 'Adding fragment centered on ',IdAt0, &
791
              LIAISONS(IdAt0,0)
792
         IF (debug) WRITE(*,*) 'Center linked to ',Lies_CF(IdAt0,0), &
793
              ' atoms'
794
!     if (LIAISONS(IdAt0,0).EQ.0) goto 12345
795

    
796
         if (debug) THEN
797
            WRITE(IOOUT,*) 'LIAISONS tralala',nbcycle
798
            DO IAt=1,na
799
               WRITE(IOOUT,1003) iat,(LIAISONS(Iat,Jat),Jat=0,NMaxL)
800
            END DO
801
         END IF
802

    
803
!     Boucle pour voir quel est l'atome du fragment precedent qui est le plus
804
!     proche de celui ci
805
!     Rq: si ce sont des cycles lies, il pourrait etre malin de rechercher
806
!     a quoi il etait lie.
807
         norm2=1.e6
808
         Idx=0
809
         DO ICAt=1,Izm
810
            CALL vecteur(Idat0,ind_zmat(icat,1),x,y,z,vx1,vy1,vz1,norm1)
811
            if (norm2.ge.norm1) THEN
812
               norm2=norm1
813
               Idx=Icat
814
            END IF
815
         END DO
816
         IF (debug) WRITE(*,*) 'Link between fragments ',IdAt0, &
817
              ind_zmat(Idx,1), ' -- Idx=',Idx
818

    
819
!     on a l'indice... on va rajouter cet atome a la liste !
820
         izm=izm+1
821
         n1=ind_zmat(Idx,1)
822
!     Petit probleme si Idx<=2
823
         IF (Idx.EQ.1) THEN
824
!     Pb non negligeable ...
825
            IF (izm.ge.2) THEN
826
               IAtv=ind_zmat(2,1)
827
               IAtdh=ind_zmat(3,1)
828
            ELSE
829
               WRITE(*,*) '2 fragments, le 1er a moins de 2 atomes...'
830
               WRITE(*,*) "J'ai merde... "
831
               STOP
832
            END IF
833
         ELSEIF (Idx.EQ.2) THEN
834
            IAtv=1
835
            IF (izm.ge.2) THEN
836
               IAtdh=ind_zmat(3,1)
837
            ELSE
838
               WRITE(*,*) '2 fragments, le 1er a moins de 2 atomes...'
839
               WRITE(*,*) "J'ai merde... "
840
               STOP
841
            END IF
842
         ELSE
843
            IAtv=ind_zmat(Idx,2)
844
            IAtdh=ind_zmat(Idx,3)
845
         END IF
846

    
847
!     WRITE(*,*) "Outchilou IAtv, IAtdh", IAtv, IAtdh,n1
848
         CALL vecteur(n1,IdAt0,x,y,z,vx1,vy1,vz1,norm1)
849
         CALL vecteur(n1,IAtv,x,y,z,vx2,vy2,vz2,norm2)
850
         val=angle(vx1,vy1,vz1,norm1, &
851
              vx2,vy2,vz2,norm2)
852
         if (debug) WRITE(*,*) 'Angle val:1',IdAt0,n1,IAtv,val
853
         if ((abs(val).LE.10.).OR.(abs(pi-val).le.10.)) THEN
854
            IAtv=IAtdh
855
!     Ceci pose pb si Idx<=3... a traiter plus tard
856
            IF (Idx.ge.3) THEN
857
               IAtdh=ind_zmat(Idx,4)
858
            ELSE
859
               if (izm.ge.4) THEN
860
                  IAtdh=4
861
               ELSE
862
                  WRITE(*,*) 'Pb Angle Val+idx=3+izm<=4'
863
                  STOP
864
               END IF
865
            END IF
866
         END IF
867
         Call AddLigne(Izm,IdAt0,ind_zmat(Idx,1),IAtv,IAtdh, &
868
              ind_zmat,val_zmat,x,y,z)
869

    
870

    
871
         IndFin=1
872
         IAtd=IdAt0
873
         n1=IAtdh
874
         IAtdh=IAtv
875
         IAtv=ind_zmat(Idx,1)
876
!     On ajoute les atomes lies a cet atome dans la liste a faire
877
         Do iaf=1,Lies_CF(IdAt0,0)
878
            IatI=Lies_CF(IdAt0,Iaf)
879
!     We check that this atom is not the one that is the closest to
880
!     the center atom
881
            if (IAtv.Ne.IAtI) THEN
882
               IF (debug) WRITE(*,*) 'Adding atom',IAtI, &
883
                    'to CAFaire in pos',iaf
884
               CAfaire(IndFin)=IAtI
885
               IndFin=IndFin+1
886
!     On les ajoute aussi dans la zmat
887
               If (.NOT.DejaFait(IatI)) THEN
888
                  izm=izm+1
889
!     WRITE(*,*) "Outchili IAtv, IAtdh,IAtI", IAtv, IAtdh,IAtI
890
                  CALL vecteur(IAtI,IAtD,x,y,z,vx1,vy1,vz1,norm1)
891
                  CALL vecteur(IAtI,IAtv,x,y,z,vx2,vy2,vz2,norm2)
892
                  val=angle(vx1,vy1,vz1,norm1, vx2,vy2,vz2,norm2)
893
                  if (debug) WRITE(*,*) 'Angle val:2',IAtI,IAtD,IAtv,val
894
                  if ((abs(val).LE.10.).OR.(abs(180.-abs(val)).le.10.)) &
895
                       THEN
896
                     Call AddLigne(Izm,IAtI,IAtv,IAtdh,n1, &
897
                          ind_zmat,val_zmat,x,y,z)
898
                  ELSE
899

    
900
                     Call AddLigne(Izm,IAtI,IAtD,IAtv,IAtdh, &
901
                          ind_zmat,val_zmat,x,y,z)
902
                  END IF
903
               END IF
904
            END IF
905
         END DO
906
         CAfaire(IndFin)=0
907

    
908
!     On traite le reste de ce fragment !!
909
         IndAFaire=1
910
         WRITE(IOOUT,*) CaFaire
911
         Do WHILE (Cafaire(IndAFaire).ne.0)
912
            IAt0=Cafaire(IndAfaire)
913
            if (Lies_CF(IAt0,0).ge.1) THEN
914
!     IAt0 est l'atome pour lequel on construit la couche suivante
915
!     le premier atome lie est particulier car il definit l'orientation
916
!     de ce fragment
917
               Itmp=1
918
               IAti=Lies_CF(IAt0,Itmp)
919
               DO WHILE (DejaFait(IAti).AND.(Itmp.Le.Lies_CF(IAt0,0)))
920
                  Itmp=Itmp+1
921
                  IAti=Lies_CF(IAt0,ITmp)
922
               END DO
923
               If (.NOT.DejaFait(Iati)) THEN
924
                  IF (debug) WRITE(IOOUT,*) 'IAti:',IAti
925
                  IAtd=IAt0
926
                  IF (debug)     WRITE(IOOUT,*) 'IAtd:',IAtd
927
                  IAtv=Lies_CP(IAt0,1)
928
                  IF (debug)     WRITE(IOOUT,*) 'IAtv:',IAtv
929
                  IIAtdh=1
930
                  IAtdh=Lies_CF(IAtv,IIatdh)
931
                  DO WHILE (Iatdh.eq.IAt0)
932
                     IIatdh=IIatdh+1
933
                     IAtdh=Lies_CF(IAtv,IIatdh)
934
                  END DO
935
                  IF (IAtdh.eq.0) IAtdh=Lies_CP(IAtv,1)
936
                  IF (debug) WRITE(IOOUT,*) 'IAtdh:',IAtdh
937
                  Izm=Izm+1
938
                  Call AddLigne(Izm,IAti,IAtd,IAtv,IAtdh, &
939
                       ind_zmat,val_zmat,x,y,z)
940
!     Le traitement des autres est plus facile
941
                  IAtdh=Lies_CF(IAt0,ITmp)
942
                  DO IAta=ITmp+1,Lies_CF(IAt0,0)
943
                     IAtI=Lies_CF(IAt0,IAta)
944
                     If (.NOT.DejaFait(IAtI)) THEN
945
                        Izm=Izm+1
946
                        Call AddLigne(Izm,IAti,IAtd,IAtv,IAtdh, &
947
                             ind_zmat,val_zmat,x,y,z)
948
                     END IF
949
                  END DO
950
               END IF
951

    
952
!     On ajoute les atomes lies a cet atome dans la liste a faire
953
               Do iaf=1,Lies_CF(IAt0,0)
954
                  CAfaire(IndFin)=Lies_CF(IAt0,Iaf)
955
                  IndFin=IndFin+1
956
               END DO
957
               CAfaire(IndFin)=0
958
            END IF
959
            IndAFaire=IndAFaire+1
960
         END DO
961
12345    CONTINUE
962
      END DO
963

    
964
      if (debug) THEN
965
         WRITE(*,*) 'ind_zmat'
966
         DO I=1,na
967
            WRITE(*,'(1X,5I5)') (ind_zmat(i,j),j=1,5)
968
         END DO
969
      END IF
970

    
971

    
972

    
973
      if (debug) WRITE(*,*) "====================== Exiting Calc_zmat ==================="
974

    
975
    END SUBROUTINE Calc_Zmat
976