Statistiques
| Révision :

root / src / Calc_zmat.f90

Historique | Voir | Annoter | Télécharger (33,22 ko)

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

    
4
!----------------------------------------------------------------------
5
!  Copyright 2003-2014 Ecole Normale Sup?rieure de Lyon, 
6
!  Centre National de la Recherche Scientifique,
7
!  Universit? Claude Bernard Lyon 1. All rights reserved.
8
!
9
!  This work is registered with the Agency for the Protection of Programs 
10
!  as IDDN.FR.001.100009.000.S.P.2014.000.30625
11
!
12
!  Authors: P. Fleurat-Lessard, P. Dayal
13
!  Contact: optnpath@gmail.com
14
!
15
! This file is part of "Opt'n Path".
16
!
17
!  "Opt'n Path" is free software: you can redistribute it and/or modify
18
!  it under the terms of the GNU Affero General Public License as
19
!  published by the Free Software Foundation, either version 3 of the License,
20
!  or (at your option) any later version.
21
!
22
!  "Opt'n Path" is distributed in the hope that it will be useful,
23
!  but WITHOUT ANY WARRANTY; without even the implied warranty of
24
!
25
!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
!  GNU Affero General Public License for more details.
27
!
28
!  You should have received a copy of the GNU Affero General Public License
29
!  along with "Opt'n Path". If not, see <http://www.gnu.org/licenses/>.
30
!
31
! Contact The Office of Technology Licensing, valorisation@ens-lyon.fr,
32
! for commercial licensing opportunities.
33
!----------------------------------------------------------------------
34

    
35
      use Path_module, only : Pi,max_Z, NMaxL, Nom, KINT, KREAL
36
      use Io_module, only :  IoOut
37

    
38
      IMPLICIT NONE
39

    
40
! Number of atoms
41
      integer(KINT), INTENT(IN) :: na
42
! Mass number of atoms
43
      INTEGER(KINT), INTENT(IN) :: atome(na)
44
! Coordinates
45
      real(KREAL), INTENT(IN) ::  x(na),y(na),z(na)
46
! Covalent radii
47
      REAL(KREAL), INTENT(IN) :: R_cov(Max_Z)
48
! Factor to determine connectivity
49
      REAL(KREAL) :: Fact
50
! Zmat index and values
51
      integer(KINT), INTENT(OUT) :: ind_zmat(na,5)
52
      real(KREAL),INTENT(OUT) ::  val_zmat(na,3)
53

    
54

    
55
      INTEGER(KINT), ALLOCATABLE :: LIAISONS(:,:) !(na,0:NMaxL
56
      INTEGER(KINT), ALLOCATABLE :: LiaisonsBis(:,:) ! na,0:NMaxL
57
      INTEGER(KINT), ALLOCATABLE :: LieS_CP(:,:),LieS_CF(:,:) ! (na,0:NMaxL)
58
      INTEGER(KINT), ALLOCATABLE :: NbAt3(:,:) !(Na,2)
59
      INTEGER(KINT), ALLOCATABLE :: CycleAt(:) !(Na)
60
      INTEGER(KINT), ALLOCATABLE :: CAFaire(:) ! Na
61

    
62
      Integer(KINT) :: AtTypCycl(Max_Z)
63
      Integer(KINT) :: NbCycle
64
      real(KREAL) ::  vx1,vy1,vz1,norm1
65
      real(KREAL) ::  vx2,vy2,vz2,norm2
66
      real(KREAL) ::  val
67
      Logical PasFini,AtTerm,Debug,Bicycle,FLie3,FirstCycle
68
      LOGICAL, ALLOCATABLE ::  Former3(:), DejaFait(:) ! Na
69
      Logical FTmp
70
      LOGICAL F1213, F1223,F1323
71

    
72
      INTEGER(KINT) :: I,J,K, IZM, N1,n2, N3, IL, JL
73
      INTEGER(KINT) :: IdAt0, I3, IAt3, Idx3, I1, I0, IAf
74
      INTEGER(KINT) :: Izm1,Izm2, IZm3,IZm4, VCF, ICat
75
      INTEGER(KINT) :: IOld, IndFin, IdAtL, IndAFaire
76
      INTEGER(KINT) :: IAti, IAtD, IAtv, IIAtDh, IAtDh
77
      INTEGER(KINT) :: IAt0, IAta, IAt, Jat,Idx
78
      INTEGER(KINT) :: ITmp, IAtTmp, NbAt0
79
      INTEGER(KINT) :: NbLies, ICycle, IMax
80
      REAL(KREAL) :: d,d12, d13,d32
81

    
82
  INTERFACE
83
     function valid(string) result (isValid)
84
       CHARACTER(*), intent(in) :: string
85
       logical                  :: isValid
86
     END function VALID
87

    
88
     FUNCTION angle(v1x,v1y,v1z,norm1,v2x,v2y,v2z,norm2)
89
        use Path_module, only :  Pi,KINT, KREAL
90
       real(KREAL) ::  v1x,v1y,v1z,norm1
91
       real(KREAL) ::  v2x,v2y,v2z,norm2
92
       real(KREAL) ::  angle
93
     END FUNCTION ANGLE
94

    
95

    
96
  END INTERFACE
97

    
98

    
99

    
100
      debug=valid("Calc_zmat")
101
      if (debug) WRITE(*,*) "========== Entering Calc_zmat =========="
102

    
103
      FirstCycle=.TRUE.
104
      FTmp=.FALSE.
105
      NbCycle=0
106
      DO i=1,na
107
         DO J=1,5
108
            Ind_Zmat(i,J)=0
109
         END DO
110
      END DO
111
      ALLOCATE(Former3(Na), DejaFait(Na))
112
      ALLOCATE(CaFaire(Na), CycleAt(Na))
113
      ALLOCATE(NbAt3(Na,2))
114
      ALLOCATE(Liaisons(na,0:NMaxL),LiaisonsBis(na,0:NMaxL))
115
      ALLOCATE(Lies_CP(na,0:NMaxL), Lies_CF(na,0:NMaxL))
116

    
117

    
118
      WRITE(IOOUT,*) Na
119
      WRITE(IOOUT,*) 'Calc_zmat'
120
      DO I=1,na
121
         WRITE(IOOUT,*) NOM(Atome(I)),X(i),y(i),z(i)
122
      END DO
123

    
124
      if (na.le.2) THEN
125
         WRITE(*,*) "I do not work for less than 2 atoms :-p"
126
         RETURN
127
      END IF
128

    
129
!     Cas particulier: 3 atomes ou moins...
130
      if (Na.eq.3) THEN
131
         d12=sqrt((x(1)-x(2))**2+(y(1)-y(2))**2+(z(1)-z(2))**2)
132
         d13=sqrt((x(1)-x(3))**2+(y(1)-y(3))**2+(z(1)-z(3))**2)
133
         d32=sqrt((x(3)-x(2))**2+(y(3)-y(2))**2+(z(3)-z(2))**2)
134
         F1213=(d12<=d13)
135
         F1323=(d13<=d32)
136
         F1223=(d12<=d32)
137
         if (debug) THEN
138
            WRITE(*,*) "DEBUG Calc_Zmat 3 atoms"
139
            WRITE(*,*) "d12,d13,d32:",d12,d13,d32
140
            WRITE(*,*) "F1213,F1323,F1223:",F1213,F1323,F1223
141
         END IF
142
         if (F1213) THEN
143
            if (F1323) THEN
144
               ind_zmat(1,1)=3
145
               ind_zmat(2,1)=1
146
               ind_zmat(2,2)=3
147
               ind_zmat(3,1)=2
148
               ind_zmat(3,2)=1
149
               ind_zmat(3,3)=3
150
            ELSE
151
               ind_zmat(1,1)=1
152
               ind_zmat(2,1)=2
153
               ind_zmat(2,2)=1
154
               ind_zmat(3,1)=3
155
               ind_zmat(3,2)=2
156
               ind_zmat(3,3)=1
157
            END IF
158
         ELSE
159
            IF (F1223) THEN
160
               ind_zmat(1,1)=2
161
               ind_zmat(2,1)=1
162
               ind_zmat(2,2)=2
163
               ind_zmat(3,1)=3
164
               ind_zmat(3,2)=1
165
               ind_zmat(3,3)=2
166
            ELSE
167
               ind_zmat(1,1)=2
168
               ind_zmat(2,1)=3
169
               ind_zmat(2,2)=2
170
               ind_zmat(3,1)=1
171
               ind_zmat(3,2)=3
172
               ind_zmat(3,3)=2
173
            END IF
174
         END IF
175
         IF (debug) THEN
176
            DO i=1,na
177
               WRITE(*,*) (ind_zmat(i,j),j=1,5)
178
            END DO
179
         END IF
180

    
181
!     We have ind_zmat, we fill val_zmat
182
         val_zmat(1,1)=0.
183
         val_zmat(1,2)=0.
184
         val_zmat(1,3)=0.
185
         n2=ind_zmat(2,1)
186
         n1=ind_zmat(2,2)
187
         d=sqrt((x(n1)-x(n2))**2+(y(n1)-y(n2))**2+ &
188
              (z(n1)-z(n2))**2)
189
         val_zmat(2,1)=d
190
         val_zmat(2,2)=0.
191
         val_zmat(2,3)=0.
192
         n1=ind_zmat(3,1)
193
         n2=ind_zmat(3,2)
194
         n3=ind_zmat(3,3)
195
         CALL vecteur(n2,n1,x,y,z,vx1,vy1,vz1,norm1)
196
         if (debug) write(*,*) n1,n2,norm1
197
         val_zmat(3,1)=norm1
198

    
199
         CALL vecteur(n2,n3,x,y,z,vx2,vy2,vz2,norm2)
200
         val=angle(vx1,vy1,vz1,norm1,vx2,vy2,vz2,norm2)
201
         if (debug) write(*,*) n2,n3,norm2,val
202
         val_zmat(3,2)=val
203
         val_zmat(3,3)=0.
204

    
205
         RETURN
206
      END IF
207

    
208

    
209
!     Premiere etape : calcul des connectivites
210
      DO I=1,na
211
         DejaFait(I)=.FALSE.
212
         Former3(I)=.False.
213
         Do J=0,NMaxL
214
            Liaisons(I,j)=0
215
            LiaisonsBis(I,j)=0
216
         END DO
217
         DO J=1,5
218
            ind_zmat(I,J)=0
219
         END DO
220
      END DO
221

    
222
      if (debug) WRITE(IOOUT,*) "Liaisons initialiazed"
223
!     DO IL=1,na
224
!     WRITE(IOOUT,1003) Il,(LIAISONS(IL,JL),JL=0,NMaxL)
225
!     WRITE(IOOUT,1003) Il,(LIAISONSBis(IL,JL),JL=0,NMaxL)
226
!     END DO
227

    
228
      Call CalcCnct(na,atome,x,y,z,LIAISONS,r_cov,fact)
229

    
230
      if (debug) THEN
231
         WRITE(IOOUT,*) "Connections calculated"
232
         DO IL=1,na
233
            WRITE(IOOUT,1003) Il,(LIAISONS(IL,JL),JL=0,NMaxL)
234
         END DO
235
      END IF
236

    
237

    
238
!     on va maintenant trier ces connectivites en 2 :
239
!     Lies_CF : vers l'exterieur de la molecule
240
!     Lies_CP : vers l'interieur de la molecule
241
!     Pour cela, on procede 'a l'envers' : on regarde les atomes
242
!     auxquels sont lies les atomes attaches -> on remplit Lies_CF/P
243
!     et on supprime ces atomes...
244

    
245
!     v2.0 on copie Liaison dans LiaisonBis. On analyse LiaisonBis
246
!     tout en modifiant Liaison. Cela evite de fausser l'analyse: un atome
247
!     qui est lie initialement a 2 atomes (et qui n'est donc pas terminal)
248
!     peut devenir terminal en milieu de traitement si on annule la liaison
249
!     qui le liait a un atome terminal situ? avant lui...
250
!     ex: H2O code dans l'ordre H,O,H.
251
      PasFini=.True.
252
      AtTerm=.True.
253
      DO WHILE (PasFini.AND.AtTerm)
254
         PasFini=.False.
255
         AtTerm=.False.
256
         DO I=1,na
257
            DO J=0,NMaxL
258
               LiaisonsBis(I,J)=Liaisons(I,J)
259
            END DO
260
         END DO
261
!     DO IL=1,na
262
!     WRITE(IOOUT,1003) Il,(LIAISONS(IL,JL),JL=0,NMaxL)
263
!     WRITE(IOOUT,1003) Il,(LIAISONSBis(IL,JL),JL=0,NMaxL)
264
!     END DO
265
!     WRITE(IOOUT,*) "=================================="
266

    
267

    
268
         DO I=1,na
269
            if ((LiaisonsBis(I,0).eq.1).AND.Liaisons(I,0).ne.0) THEN
270
               AtTerm=.True.
271
!     On enleve cet atome
272
               Liaisons(I,0)=0
273
               NbLies=Lies_CP(I,0)+1
274
               Lies_CP(I,NbLies)=Liaisons(I,1)
275
               Lies_CP(I,0)=NbLies
276
               Liaisons(Liaisons(I,1),0)=Liaisons(Liaisons(I,1),0)-1
277

    
278
               NbLies=Lies_CF(Liaisons(I,1),0)+1
279
               Lies_CF(Liaisons(I,1),NbLies)=I
280
               Lies_CF(Liaisons(I,1),0)=NbLies
281

    
282
               Call Annul(Liaisons,Liaisons(I,1),I)
283

    
284
            END IF
285

    
286
            if (Liaisons(I,0).ge.1) THEN
287
               PasFini=.TRUE.
288
            END IF
289

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

    
461
                  Call Annul(Liaisons,I1,I0)
462
                  Liaisons(I1,0)=Liaisons(I1,0)-1
463
                  Liaisons(I0,0)=Liaisons(I0,0)-1
464

    
465
                  DO IL=1,na
466
                     WRITE(IOOUT,1003) Il,(LIAISONS(IL,JL),JL=0,NMaxL)
467
                  END DO
468
                  I0=I1
469
                  I1=Liaisons(I0,1)
470

    
471
               end do
472
               Call Annul(Liaisons,I1,I0)
473
               Liaisons(I1,0)=Liaisons(I1,0)-1
474
               Liaisons(I0,0)=Liaisons(I0,0)-1
475
            END IF
476
         END IF
477
         DO IL=1,na
478
            WRITE(IOOUT,1003) Il,(LIAISONS(IL,JL),JL=0,NMaxL)
479
         END DO
480
!     WRITE(IOOUT,*) "=================================="
481
!     WRITE(IOOUT,*) "=================================="
482
      END DO
483

    
484
!     WRITE(IOOUT,*) "=================================="
485
!     Il ne reste plus que des atomes lies a rien...
486
!     ce sont les 'centres' de la molecule. On repart
487
!     d'eux pour construire le reste de la molecule.
488

    
489
 1003 FORMAT(1X,I4,' - ',15(I5))
490
!     Avant de partir, on va classer, pour chaque atome, les atomes CF par
491
!     nombre de masse decroissant.
492
      DO I=1,na
493
!     WRITE(*,*) I,Lies_CF(I,0),(Atome(Lies_CF(I,J)),j=1,Lies_CF(I,0))
494
         DO J=1,Lies_CF(I,0)-1
495
            DO K=J+1,Lies_CF(I,0)
496
               if (atome(Lies_CF(I,K))>atome(Lies_CF(I,J))) THEN
497
                  Itmp=Lies_CF(I,K)
498
                  Lies_CF(I,K)=Lies_CF(I,J)
499
                  Lies_CF(I,J)=Itmp
500
               END IF
501
            END DO
502
         END DO
503
!     WRITE(*,*) I,Lies_CF(I,0),(Atome(Lies_CF(I,J)),j=1,Lies_CF(I,0))
504
      END DO
505

    
506
      IF (Debug) THEN
507
         WRITE(IOOUT,*) 'LIAISONS'
508
         DO I=1,na
509
            WRITE(IOOUT,1003) i,(LIAISONS(I,J),J=0,NMaxL)
510
         END DO
511

    
512
         WRITE(IOOUT,*) 'LIes_CF'
513
         DO I=1,na
514
            WRITE(IOOUT,1003) i,(LIeS_CF(I,J),J=0,NMaxL)
515
         END DO
516

    
517
         WRITE(IOOUT,*) 'LIes_CP'
518
         DO I=1,na
519
            WRITE(IOOUT,1003) i,(LIeS_CP(I,J),J=0,NMaxL)
520
         END DO
521
      END IF
522

    
523

    
524
!     On compte le nb d'atomes sans atomes CP (centripetes)
525
      NbAt0=0
526
      DO I=1,na
527
         IF (Lies_CP(I,0).eq.0) THEN
528
            NbAt0=NbAt0+1
529
            IF (DEBUG) WRITE(*,*) "Center atom",NbAt0,I,Atome(I)
530
         END IF
531
      END DO
532

    
533
!     On va les traiter tous en construisant les molecules en partant d'eux
534
!     Le premier atome sans CP est different des autres car il fixe
535
!     l'origine
536

    
537
      IZm=1
538
!     Boucle pour trouver celui qui a le plus d'atomes CF
539
      IdAt0=0
540
      VCF=0
541
      DO ICAt=1,na
542
         if ((Lies_CP(ICaT,0).eq.0).AND.(Lies_CF(ICAt,0).gt.VCF)) THEN
543
            IdAt0=ICat
544
            VCF=Lies_CF(ICAt,0)
545
         END IF
546
      END DO
547
      Lies_CP(IdAt0,0)=-1
548

    
549
!     WRITE(IOOUT,*) 'Atome 1', IdAt0, Nom(Atome(IdAt0))
550
      Izm1=IdAt0
551
      ind_zmat(izm,1)=Izm1
552
      ind_zmat(izm,2)=0
553
      ind_zmat(izm,3)=0
554
      ind_zmat(izm,4)=0
555
      ind_zmat(izm,5)=0
556
      val_zmat(izm,1)=0.0
557
      val_zmat(izm,2)=0.0
558
      val_zmat(izm,3)=0.0
559
      DejaFait(Izm1)=.True.
560

    
561
!     Les atomes CF lies a IdAt0 sont mis en attente pour
562
!     etre traites
563

    
564
      IndFin=1
565
      Do iaf=1,Lies_CF(IdAt0,0)
566
         CAfaire(IndFin)=Lies_CF(IdAt0,Iaf)
567
         IndFin=IndFin+1
568
      END DO
569
      CAfaire(IndFin)=0
570

    
571
!     On construit la premiere couche qui est speciale car elle fixe les
572
!     axes.
573
!     Plusieurs cas sont possibles suivant le nb d'atomes CF
574

    
575
      IF (Lies_CF(IdAt0,0).ge.3) THEN
576
         if (debug) WRITE(*,*) 'Cas tres simple,',IdAt0, &
577
              ' li? a plus de 3 atomes'
578
         IZm2=Lies_CF(IdAt0,1)
579
         IZm3=Lies_CF(IdAt0,2)
580
!     WRITE(IOOUT,*) 'Atome 2' , Izm2, Nom(Atome(Izm2))
581
!     WRITE(IOOUT,*) 'Atome 3' ,Izm3, Nom(Atome(izm3))
582

    
583
         Izm=2
584
         CALL vecteur(IZm1,IZm2,x,y,z,vx1,vy1,vz1,norm1)
585
!     write(*,11) n1,n2,norm1
586

    
587
         ind_zmat(izm,1)=izm2
588
         ind_zmat(izm,2)=izm1
589
         ind_zmat(izm,3)=0
590
         ind_zmat(izm,4)=0
591
         ind_zmat(izm,5)=0
592
         val_zmat(izm,1)=norm1
593
         val_zmat(izm,2)=0.0
594
         val_zmat(izm,3)=0.0
595
         DejaFait(Izm2)=.TRUE.
596

    
597
         Izm=3
598
         CALL vecteur(izm1,izm3,x,y,z,vx2,vy2,vz2,norm2)
599
         val=angle(vx1,vy1,vz1,norm1,vx2,vy2,vz2,norm2)
600

    
601
!     write(*,11) n1,n2,norm1,n3,val
602

    
603
         ind_zmat(izm,1)=izm3
604
         ind_zmat(izm,2)=izm1
605
         ind_zmat(izm,3)=izm2
606
         ind_zmat(izm,4)=0
607
         ind_zmat(izm,5)=0
608
         val_zmat(izm,1)=norm2
609
         val_zmat(izm,2)=val
610
         val_zmat(izm,3)=0.0
611
         DejaFait(Izm3)=.TRUE.
612

    
613
         DO IdAtl=3,Lies_CF(IdAt0,0)
614
            Izm4= Lies_CF(IdAt0,IdAtl)
615
!     WRITE(IOOUT,*) 'Atome ',Izm+1,Izm4,Nom(Atome(Izm4)),Izm1,
616
!     $Izm2,Izm3
617
            Izm=Izm+1
618
            Call AddLigne(Izm,Izm4,Izm1,Izm2,Izm3,ind_zmat,val_zmat, &
619
                 x,y,z)
620
            DejaFait(Izm4)=.TRUE.
621
         END DO
622
      END IF
623

    
624
      IF (Lies_CF(Izm1,0).eq.2) THEN
625
         if (debug) WRITE(*,*) 'Cas simple,',IdAt0, &
626
              ' li? a 2 atomes'
627

    
628
         IZm2=Lies_CF(IdAt0,1)
629
         IZm3=Lies_CF(IdAt0,2)
630
         Izm=2
631
         CALL vecteur(IZm1,IZm2,x,y,z,vx1,vy1,vz1,norm1)
632
!     write(*,11) n1,n2,norm1
633

    
634
         ind_zmat(izm,1)=izm2
635
         ind_zmat(izm,2)=izm1
636
         ind_zmat(izm,3)=0
637
         ind_zmat(izm,4)=0
638
         ind_zmat(izm,5)=0
639
         val_zmat(izm,1)=norm1
640
         val_zmat(izm,2)=0.0
641
         val_zmat(izm,3)=0.0
642
         DejaFait(Izm2)=.TRUE.
643

    
644
         Izm=3
645

    
646
         CALL vecteur(izm1,izm3,x,y,z,vx2,vy2,vz2,norm2)
647
         val=angle(vx1,vy1,vz1,norm1, &
648
              vx2,vy2,vz2,norm2)
649

    
650
!     write(*,11) n1,n2,norm1,n3,val
651

    
652
         ind_zmat(izm,1)=izm3
653
         ind_zmat(izm,2)=izm1
654
         ind_zmat(izm,3)=izm2
655
         ind_zmat(izm,4)=0
656
         ind_zmat(izm,5)=0
657
         val_zmat(izm,1)=norm2
658
         val_zmat(izm,2)=val
659
         val_zmat(izm,3)=0.0
660
         DejaFait(Izm3)=.TRUE.
661

    
662
      END IF
663

    
664
      IF (Lies_CF(Izm1,0).eq.1) THEN
665
         if (debug) WRITE(*,*) 'Cas merdouille,',IdAt0, &
666
              ' li? a 1 atome'
667

    
668
         IZm2=Lies_CF(IdAt0,1)
669
         Izm=2
670
         CALL vecteur(IZm1,IZm2,x,y,z,vx1,vy1,vz1,norm1)
671
!     write(*,11) n1,n2,norm1
672

    
673
         ind_zmat(izm,1)=izm2
674
         ind_zmat(izm,2)=izm1
675
         ind_zmat(izm,3)=0
676
         ind_zmat(izm,4)=0
677
         ind_zmat(izm,5)=0
678
         val_zmat(izm,1)=norm1
679
         val_zmat(izm,2)=0.0
680
         val_zmat(izm,3)=0.0
681
         DejaFait(Izm2)=.TRUE.
682

    
683
!     Pour les autres atomes, on prend les atomes
684
!     CF lie a l'tome CF lie a At0... en esperant
685
!     qu'il en a !!!
686
!     => il faudra voir le cas ou il n'en a pas !!!
687
!     en attendant on rajoute le test...
688
         IF (Lies_CF(Izm2,0).Eq.0) THEN
689
            WRITE(*,*) "Je n'arrive pas a trouver les premiers"
690
            WRITE(*,*) "atomes pour construire la molecule"
691
            WRITE(*,*) "Atome central li? au plus a 1 atome",Izm1,izm2
692
            WRITE(*,*) "Et atome 2 li? a rien... moi perdu"
693
            STOP
694
         END IF
695

    
696
!     On ajoute les atomes lies a cet atome dans la liste a faire
697
         Do iaf=1,Lies_CF(Izm2,0)
698
            CAfaire(IndFin)=Lies_CF(Izm2,Iaf)
699
            IndFin=IndFin+1
700
         END DO
701
         CAfaire(IndFin)=0
702
         Izm3= Lies_CF(Izm2,1)
703
         Izm=3
704
         CALL vecteur(izm2,izm1,x,y,z,vx1,vy1,vz1,norm1)
705

    
706
         CALL vecteur(izm2,izm3,x,y,z,vx2,vy2,vz2,norm2)
707
         val=angle(vx1,vy1,vz1,norm1, &
708
              vx2,vy2,vz2,norm2)
709

    
710
!     write(*,11) n1,n2,norm1,n3,val
711

    
712
         ind_zmat(izm,1)=izm3
713
         ind_zmat(izm,2)=izm2
714
         ind_zmat(izm,3)=izm1
715
         ind_zmat(izm,4)=0
716
         ind_zmat(izm,5)=0
717
         val_zmat(izm,1)=norm1
718
         val_zmat(izm,2)=val
719
         val_zmat(izm,3)=0.0
720
         DejaFait(Izm3)=.TRUE.
721

    
722
!     je pense que ce qui suit est totalement inutile
723
!     C     DO IdAtl=3,Lies_CF(IdAt0,0)
724
!     C     Izm4= Lies_CF(IdAt0,IdAtl)
725
!     C     Izm=Izm+1
726
!     C     Call AddLigne(Izm,Izm4,Izm1,Izm2,Izm3,ind_zmat,val_zmat
727
!     C     $,x,y,z)
728
!     C     DejaFait(Izm4)=.TRUE.
729
!     C     END DO
730
      END IF
731

    
732
!     on a cree la premiere couche autour du premier centre
733
!     reste a finir les autres couches
734
      IndAFaire=1
735
      if (debug) WRITE(IOOUT,*) "CaFaire:",CaFaire
736
      Do WHILE (Cafaire(IndAFaire).ne.0)
737
         IAt0=Cafaire(IndAfaire)
738
         if (debug) WRITE(*,*) "IndAFaire,IAt0,Lies_CF(IAt0,0)", &
739
              IndAFaire,IAt0,Lies_CF(IAt0,0)
740
         if (Lies_CF(IAt0,0).ge.1) THEN
741
!     IAt0 est l'atome pour lequel on construit la couche suivante
742
!     le premier atome lie est particulier car il definit l'orientation
743
!     de ce fragment
744
            IAti=Lies_CF(IAt0,1)
745
!     WRITE(IOOUT,*) 'IAti:',IAti
746
            IAtd=IAt0
747
!     WRITE(IOOUT,*) 'IAtd:',IAtd
748
            IAtv=Lies_CP(IAt0,1)
749
!     WRITE(IOOUT,*) 'IAtv:',IAtv
750
            IIAtdh=1
751
            IAtdh=Lies_CF(IAtv,IIatdh)
752
            DO WHILE (Iatdh.eq.IAt0)
753
               IIatdh=IIatdh+1
754
               IAtdh=Lies_CF(IAtv,IIatdh)
755
            END DO
756
            IF (IAtdh.eq.0) IAtdh=Lies_CP(IAtv,1)
757
!     WRITE(IOOUT,*) 'IAtdh:',IAtdh
758
            IF (.NOT.DejaFait(IAti)) THEN
759
               Izm=Izm+1
760
               if (debug) WRITE(*,*) 'izm,IAti,IAtd,IAtv,IAtdh', &
761
                    izm,IAti,IAtd,IAtv,IAtdh
762
               Call AddLigne(Izm,IAti,IAtd,IAtv,IAtdh,ind_zmat,val_zmat &
763
                    ,x,y,z)
764
               DejaFait(IAti)=.TRUE.
765
            END IF
766

    
767
            CAfaire(IndFin)=Lies_CF(IAt0,1)
768
            IndFin=IndFin+1
769
!     Le traitement des autres est plus facile
770
            IAtdh=Lies_CF(IAt0,1)
771
            DO IAta=2,Lies_CF(IAt0,0)
772
               IAtI=Lies_CF(IAt0,IAta)
773
                     if (debug) WRITE(*,*) " Problem is here; IndFin:",I
774
               CAfaire(IndFin)=IAtI
775
               IndFin=IndFin+1
776

    
777
               IF (.NOT.DejaFait(IAti)) THEN
778
                  Izm=Izm+1
779
                  Call AddLigne(Izm,IAti,IAtd,IAtv,IAtdh,ind_zmat &
780
                       ,val_zmat,x,y,z)
781
                  DejaFait(IAti)=.TRUE.
782
               END IF
783
            END DO
784

    
785
            CAfaire(IndFin)=0
786
         END IF
787
         IndAFaire=IndAFaire+1
788
      END DO
789

    
790

    
791
!     On a fini de creer la molecule autour du premier atome 'centre'
792
!     Pour les autres c'est presque id... sauf que les axes sont deja fixes
793
!     On pourrait imaginer de mettre des atomes fictifs pour redefinir des axes
794
!     locaux... dans une autre version
795
!     V2.0
796
      NbAt0=NbAt0-1
797
      DO I=1,NbAt0
798
!     Boucle pour trouver celui qui a le plus d'atomes CF
799

    
800
         IdAt0=0
801
         VCF=0
802

    
803
         DO ICAt=1,na
804
            if ((Lies_CP(ICaT,0).eq.0).AND.(Lies_CF(ICAt,0).gt.VCF)) &
805
                 THEN
806
               IdAt0=ICat
807
               VCF=Lies_CF(ICAt,0)
808
            END IF
809
         END DO
810
         Lies_CP(IdAt0,0)=-1
811

    
812
         IF (debug) WRITE(*,*) 'Adding fragment centered on ',IdAt0, &
813
              LIAISONS(IdAt0,0)
814
         IF (debug) WRITE(*,*) 'Center linked to ',Lies_CF(IdAt0,0), &
815
              ' atoms'
816
!     if (LIAISONS(IdAt0,0).EQ.0) goto 12345
817

    
818
         if (debug) THEN
819
            WRITE(IOOUT,*) 'LIAISONS tralala',nbcycle
820
            DO IAt=1,na
821
               WRITE(IOOUT,1003) iat,(LIAISONS(Iat,Jat),Jat=0,NMaxL)
822
            END DO
823
         END IF
824

    
825
!     Boucle pour voir quel est l'atome du fragment precedent qui est le plus
826
!     proche de celui ci
827
!     Rq: si ce sont des cycles lies, il pourrait etre malin de rechercher
828
!     a quoi il etait lie.
829
         norm2=1.e6
830
         Idx=0
831
         DO ICAt=1,Izm
832
            CALL vecteur(Idat0,ind_zmat(icat,1),x,y,z,vx1,vy1,vz1,norm1)
833
            if (norm2.ge.norm1) THEN
834
               norm2=norm1
835
               Idx=Icat
836
            END IF
837
         END DO
838
         IF (debug) WRITE(*,*) 'Link between fragments ',IdAt0, &
839
              ind_zmat(Idx,1), ' -- Idx=',Idx
840

    
841
!     on a l'indice... on va rajouter cet atome a la liste !
842
         izm=izm+1
843
         n1=ind_zmat(Idx,1)
844
!     Petit probleme si Idx<=2
845
         IF (Idx.EQ.1) THEN
846
!     Pb non negligeable ...
847
            IF (izm.ge.2) THEN
848
               IAtv=ind_zmat(2,1)
849
               IAtdh=ind_zmat(3,1)
850
            ELSE
851
               WRITE(*,*) '2 fragments, le 1er a moins de 2 atomes...'
852
               WRITE(*,*) "J'ai merde... "
853
               STOP
854
            END IF
855
         ELSEIF (Idx.EQ.2) THEN
856
            IAtv=1
857
            IF (izm.ge.2) THEN
858
               IAtdh=ind_zmat(3,1)
859
            ELSE
860
               WRITE(*,*) '2 fragments, le 1er a moins de 2 atomes...'
861
               WRITE(*,*) "J'ai merde... "
862
               STOP
863
            END IF
864
         ELSE
865
            IAtv=ind_zmat(Idx,2)
866
            IAtdh=ind_zmat(Idx,3)
867
         END IF
868

    
869
!     WRITE(*,*) "Outchilou IAtv, IAtdh", IAtv, IAtdh,n1
870
         CALL vecteur(n1,IdAt0,x,y,z,vx1,vy1,vz1,norm1)
871
         CALL vecteur(n1,IAtv,x,y,z,vx2,vy2,vz2,norm2)
872
         val=angle(vx1,vy1,vz1,norm1, &
873
              vx2,vy2,vz2,norm2)
874
         if (debug) WRITE(*,*) 'Angle val:1',IdAt0,n1,IAtv,val
875
         if ((abs(val).LE.10.).OR.(abs(pi-val).le.10.)) THEN
876
            IAtv=IAtdh
877
!     Ceci pose pb si Idx<=3... a traiter plus tard
878
            IF (Idx.ge.3) THEN
879
               IAtdh=ind_zmat(Idx,4)
880
            ELSE
881
               if (izm.ge.4) THEN
882
                  IAtdh=4
883
               ELSE
884
                  WRITE(*,*) 'Pb Angle Val+idx=3+izm<=4'
885
                  STOP
886
               END IF
887
            END IF
888
         END IF
889
         Call AddLigne(Izm,IdAt0,ind_zmat(Idx,1),IAtv,IAtdh, &
890
              ind_zmat,val_zmat,x,y,z)
891

    
892

    
893
         IndFin=1
894
         IAtd=IdAt0
895
         n1=IAtdh
896
         IAtdh=IAtv
897
         IAtv=ind_zmat(Idx,1)
898
!     On ajoute les atomes lies a cet atome dans la liste a faire
899
         Do iaf=1,Lies_CF(IdAt0,0)
900
            IatI=Lies_CF(IdAt0,Iaf)
901
!     We check that this atom is not the one that is the closest to
902
!     the center atom
903
            if (IAtv.Ne.IAtI) THEN
904
               IF (debug) WRITE(*,*) 'Adding atom',IAtI, &
905
                    'to CAFaire in pos',iaf
906
               CAfaire(IndFin)=IAtI
907
               IndFin=IndFin+1
908
!     On les ajoute aussi dans la zmat
909
               If (.NOT.DejaFait(IatI)) THEN
910
                  izm=izm+1
911
!     WRITE(*,*) "Outchili IAtv, IAtdh,IAtI", IAtv, IAtdh,IAtI
912
                  CALL vecteur(IAtI,IAtD,x,y,z,vx1,vy1,vz1,norm1)
913
                  CALL vecteur(IAtI,IAtv,x,y,z,vx2,vy2,vz2,norm2)
914
                  val=angle(vx1,vy1,vz1,norm1, vx2,vy2,vz2,norm2)
915
                  if (debug) WRITE(*,*) 'Angle val:2',IAtI,IAtD,IAtv,val
916
                  if ((abs(val).LE.10.).OR.(abs(180.-abs(val)).le.10.)) &
917
                       THEN
918
                     Call AddLigne(Izm,IAtI,IAtv,IAtdh,n1, &
919
                          ind_zmat,val_zmat,x,y,z)
920
                  ELSE
921

    
922
                     Call AddLigne(Izm,IAtI,IAtD,IAtv,IAtdh, &
923
                          ind_zmat,val_zmat,x,y,z)
924
                  END IF
925
               END IF
926
            END IF
927
         END DO
928
         CAfaire(IndFin)=0
929

    
930
!     On traite le reste de ce fragment !!
931
         IndAFaire=1
932
         WRITE(IOOUT,*) CaFaire
933
         Do WHILE (Cafaire(IndAFaire).ne.0)
934
            IAt0=Cafaire(IndAfaire)
935
            if (Lies_CF(IAt0,0).ge.1) THEN
936
!     IAt0 est l'atome pour lequel on construit la couche suivante
937
!     le premier atome lie est particulier car il definit l'orientation
938
!     de ce fragment
939
               Itmp=1
940
               IAti=Lies_CF(IAt0,Itmp)
941
               DO WHILE (DejaFait(IAti).AND.(Itmp.Le.Lies_CF(IAt0,0)))
942
                  Itmp=Itmp+1
943
                  IAti=Lies_CF(IAt0,ITmp)
944
               END DO
945
               If (.NOT.DejaFait(Iati)) THEN
946
                  IF (debug) WRITE(IOOUT,*) 'IAti:',IAti
947
                  IAtd=IAt0
948
                  IF (debug)     WRITE(IOOUT,*) 'IAtd:',IAtd
949
                  IAtv=Lies_CP(IAt0,1)
950
                  IF (debug)     WRITE(IOOUT,*) 'IAtv:',IAtv
951
                  IIAtdh=1
952
                  IAtdh=Lies_CF(IAtv,IIatdh)
953
                  DO WHILE (Iatdh.eq.IAt0)
954
                     IIatdh=IIatdh+1
955
                     IAtdh=Lies_CF(IAtv,IIatdh)
956
                  END DO
957
                  IF (IAtdh.eq.0) IAtdh=Lies_CP(IAtv,1)
958
                  IF (debug) WRITE(IOOUT,*) 'IAtdh:',IAtdh
959
                  Izm=Izm+1
960
                  Call AddLigne(Izm,IAti,IAtd,IAtv,IAtdh, &
961
                       ind_zmat,val_zmat,x,y,z)
962
!     Le traitement des autres est plus facile
963
                  IAtdh=Lies_CF(IAt0,ITmp)
964
                  DO IAta=ITmp+1,Lies_CF(IAt0,0)
965
                     IAtI=Lies_CF(IAt0,IAta)
966
                     If (.NOT.DejaFait(IAtI)) THEN
967
                        Izm=Izm+1
968
                        Call AddLigne(Izm,IAti,IAtd,IAtv,IAtdh, &
969
                             ind_zmat,val_zmat,x,y,z)
970
                     END IF
971
                  END DO
972
               END IF
973

    
974
!     On ajoute les atomes lies a cet atome dans la liste a faire
975
               Do iaf=1,Lies_CF(IAt0,0)
976
                  CAfaire(IndFin)=Lies_CF(IAt0,Iaf)
977
                  IndFin=IndFin+1
978
               END DO
979
               CAfaire(IndFin)=0
980
            END IF
981
            IndAFaire=IndAFaire+1
982
         END DO
983
!12345    CONTINUE
984
      END DO
985

    
986
      if (debug) THEN
987
         WRITE(*,*) 'ind_zmat'
988
         DO I=1,na
989
            WRITE(*,'(1X,5I5)') (ind_zmat(i,j),j=1,5)
990
         END DO
991
      END IF
992

    
993

    
994

    
995
      if (debug) WRITE(*,*) "====================== Exiting Calc_zmat ==================="
996

    
997
    END SUBROUTINE Calc_Zmat
998