atomes 1.3.1
atomes: an atomic scale modeling tool box
Loading...
Searching...
No Matches
molecules.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-2026 by CNRS and University of Strasbourg
15!
16!>
17!! @file molecules.F90
18!! @short Fragment(s) and molecule(s) analysis
19!! @author Sébastien Le Roux <sebastien.leroux@ipcms.unistra.fr>
20
21LOGICAL FUNCTION add_mol(this_mol, MOL_ID, STEP_ID)
22
23USE parameters
24
25IMPLICIT NONE
26
27TYPE (mol), POINTER, INTENT(INOUT) :: this_mol
28INTEGER, INTENT(IN) :: mol_id, step_id
29INTEGER :: aaa
30
31TYPE (mol), POINTER :: new
32
33allocate(new, stat=err)
34if (err .ne. 0) then
35 !call show_error ("Impossible to allocate memory"//CHAR(0), &
36 ! "Function: ADD_MOL"//CHAR(0), "Pointer: NEW"//CHAR(0))
37 add_mol = .false.
38 goto 001
39endif
40new%MID = mol_id
41new%STEP = step_id
42new%ATOMES = 0
43allocate(new%BSP(nsp), stat=err)
44if (err .ne. 0) then
45 !call show_error ("Impossible to allocate memory"//CHAR(0), &
46 ! "Function: ADD_MOL"//CHAR(0), "TABLE: NEW%BSP"//CHAR(0))
47 add_mol = .false.
48 goto 001
49endif
50nullify(new%FIRST_AT)
51do aaa=1, nsp
52 new%BSP(aaa) = 0
53enddo
54nullify(new%NEXT)
55new%PREV => this_mol
56this_mol%NEXT => new
57this_mol => new
58add_mol = .true.
59
60001 continue
61
62END FUNCTION
63
64LOGICAL FUNCTION add_ato(this_mol, ATOM_ID)
65
66USE parameters
67
68IMPLICIT NONE
69
70TYPE (mol), POINTER, INTENT(INOUT) :: this_mol
71INTEGER, INTENT(IN) :: atom_id
72
73TYPE (at), POINTER :: new
74
75allocate(new, stat=err)
76if (err .ne. 0) then
77 !call show_error ("Impossible to allocate memory"//CHAR(0), &
78 ! "Function: ADD_ATO"//CHAR(0), "POINTER: NEW"//CHAR(0))
79 add_ato = .false.
80 goto 001
81endif
82new%IND = atom_id
83new%PREV => this_mol%ATOM
84this_mol%ATOM%NEXT => new
85this_mol%ATOM => new
86add_ato=.true.
87
88001 continue
89
90END FUNCTION
91
92RECURSIVE SUBROUTINE setmol (this_mol, toglin, stmb, molcount, the_step, the_atom, the_id)
93
94USE parameters
95
96IMPLICIT NONE
97
98TYPE (mol), POINTER, INTENT(INOUT) :: this_mol
99INTEGER, INTENT(INOUT) :: molcount, stmb
100INTEGER, INTENT(IN) :: the_step, the_atom, the_id
101INTEGER, DIMENSION(NA), INTENT(INOUT) :: toglin
102INTEGER :: mc, md
103INTERFACE
104 LOGICAL FUNCTION add_ato(this_mol, ATOM_ID)
105 USE parameters
106 TYPE (mol), POINTER, INTENT(INOUT) :: this_mol
107 INTEGER, INTENT(IN) :: atom_id
108 END FUNCTION
109END INTERFACE
110
111molcount=molcount+1
112toglin(the_atom) = the_id
113this_mol%ATOMES = this_mol%ATOMES + 1
114this_mol%BSP(lot(the_atom)) = this_mol%BSP(lot(the_atom)) + 1
115stmb = stmb + 1
116if (this_mol%ATOMES > 1) then
117 if (.not. add_ato(this_mol, the_atom)) then
118 molcount=-1
119 goto 001
120 endif
121else
122 allocate(this_mol%FIRST_AT, stat=err)
123 if (err .ne. 0) then
124 !call show_error ("Impossible to allocate memory"//CHAR(0), &
125 ! "Function: SETMOL"//CHAR(0), "POINTER: this_mol%FIRST_AT"//CHAR(0))
126 molcount=-1
127 goto 001
128 endif
129 !write (6, '("Adding first atom:: Mol= ",i4,", At= ",i4)') this_mol%MID, the_atom
130 this_mol%FIRST_AT%IND = the_atom
131 this_mol%ATOM => this_mol%FIRST_AT
132endif
133if (stmb .eq. na) goto 002
134if (molcount.eq.10000) goto 001
135if (molcount.eq.-1) goto 001
136do mc=1, contj(the_atom, the_step)
137 md = voisj(mc,the_atom,the_step)
138 if (toglin(md).eq.0 .and. molcount.lt.10000) then
139 call setmol (this_mol, toglin, stmb, molcount, the_step, voisj(mc,the_atom,the_step), the_id)
140 endif
141 if (stmb .eq. na) goto 002
142 if (molcount.eq.10000) goto 001
143 if (molcount.eq.-1) goto 001
144enddo
145
146002 continue
147
148molcount=molcount-1
149
150001 continue
151
152END SUBROUTINE setmol
153
154INTEGER (KIND=c_int) FUNCTION molecules (frag_and_mol, allbonds) bind (C,NAME='molecules_')
155
156USE parameters
157
158#ifdef OPENMP
159!$ USE OMP_LIB
160#endif
161IMPLICIT NONE
162
163INTEGER (KIND=c_int), INTENT(IN) :: frag_and_mol, allbonds
164INTEGER :: totmol, molps, maxmol
165INTEGER, DIMENSION(:), ALLOCATABLE :: atmol
166INTEGER, DIMENSION(:), ALLOCATABLE :: atvs, mtmbs
167#ifdef OPENMP
168INTEGER :: numth
169#endif
170INTERFACE
171 LOGICAL FUNCTION add_mol(this_mol, MOL_ID, STEP_ID)
172 USE parameters
173 TYPE (mol), POINTER, INTENT(INOUT) :: this_mol
174 INTEGER, INTENT(IN) :: mol_id, step_id
175 END FUNCTION
176 RECURSIVE SUBROUTINE setmol (this_mol, toglin, stmb, molcount, the_step, the_atom, the_id)
177 USE parameters
178 TYPE (mol), POINTER, INTENT(INOUT) :: this_mol
179 INTEGER, INTENT(INOUT) :: molcount, stmb
180 INTEGER, INTENT(IN) :: the_step, the_atom, the_id
181 INTEGER, DIMENSION(NA), INTENT(INOUT) :: toglin
182 END SUBROUTINE
183END INTERFACE
184
185TYPE (at), POINTER :: tmpat
186TYPE (mol), ALLOCATABLE, TARGET :: themol
187TYPE (mol), POINTER :: tmpmol
188
189if (allocated(fullpos)) deallocate(fullpos)
190
191k = 0
192do i=1, ns
193 do j=1, na
194 if (contj(j,i) .eq. 0) k = k + 1
195 enddo
196enddo
197maxmol = k + allbonds/2;
198
199if (allocated(themol)) deallocate(themol)
200allocate(themol, stat=err)
201if (err .ne. 0) then
202 alc_tab="THEMOL"
203 alc=.true.
204 molecules = 0
205 goto 001
206endif
207if (allocated(mtmbs)) deallocate(mtmbs)
208allocate(mtmbs(ns), stat=err)
209if (err .ne. 0) then
210 alc_tab="MTMBS"
211 alc=.true.
212 molecules = 0
213 goto 001
214endif
215
216if (frag_and_mol .eq. 1) then
217 call allocate_mol_data ()
218endif
219
220molecules = 1
221#ifdef OPENMP
222numth = omp_get_max_threads()
223if (ns.lt.numth) numth=ns
224!$OMP PARALLEL NUM_THREADS(NUMTH) DEFAULT (NONE) &
225!$OMP& PRIVATE(i, j, k, l, m, n, o, ERR, TOGL, THEMOL, TMPMOL, &
226!$OMP& TOTMOL, MOLCOUNTER, TMBS, ATMOL, TMPAT, ATVS) &
227!$OMP& SHARED(NUMTH, frag_and_mol, NS, NA, NSP, LOT, MTMBS, CONTJ, VOISJ, ALC, ALC_TAB)
228#endif
229if (allocated(togl)) deallocate(togl)
230allocate(togl(na), stat=err)
231if (err .ne. 0) then
232 alc_tab="TOGL"
233 alc=.true.
234 molecules = 0
235#ifdef OPENMP
236 goto 005
237#else
238 goto 001
239#endif
240endif
241nullify(tmpat)
242#ifdef OPENMP
243 !$OMP DO SCHEDULE(STATIC,NS/NUMTH)
244#endif
245do i=1, ns
246
247#ifdef OPENMP
248 if (molecules .eq.0) goto 004
249#endif
250 allocate(tmpmol, stat=err)
251 if (err .ne. 0) then
252 alc_tab="TMPMOL"
253 alc=.true.
254 molecules = 0
255#ifdef OPENMP
256 goto 004
257#else
258 goto 001
259#endif
260 endif
261
262 togl(:)=0
263 themol%MID = 1
264 themol%STEP = i
265 themol%ATOMES = 0
266 nullify(themol%FIRST_AT)
267 allocate(themol%BSP(nsp), stat=err)
268 if (err .ne. 0) then
269 alc_tab="THEMOL%BSP"
270 alc=.true.
271 molecules = 0
272#ifdef OPENMP
273 goto 004
274#else
275 goto 001
276#endif
277 endif
278 do j=1, nsp
279 themol%BSP(j) = 0
280 enddo
281 nullify(themol%NEXT)
282 nullify(themol%PREV)
283 tmbs=0
284 totmol = 0
285 mtmbs(i)=0
286 molcounter=0
287
288 tmpmol => themol
289 n = 1
290 002 continue
291 do j=n, na
292 if (molcounter.eq.0 .and. togl(j).eq.0) then
293 totmol = totmol + 1
294 if (totmol > 1) then
295 if (.not.add_mol(tmpmol, mtmbs(i)+1, i)) then
296 alc_tab="ADD_MOL"
297 alc=.true.
298 molecules = 0
299#ifdef OPENMP
300 goto 004
301#else
302 goto 001
303#endif
304 endif
305 endif
306 mtmbs(i) = mtmbs(i) + 1
307 call setmol (tmpmol, togl, tmbs, molcounter, i, j, totmol)
308 if (molcounter .lt. 0) then
309 alc_tab="SETMOL"
310 alc=.true.
311#ifdef OPENMP
312 goto 004
313#else
314 goto 001
315#endif
316 endif
317 if (tmbs.eq.na) goto 003
318 ! The 10000 iterations break required because of F90 limitations
319 if (molcounter.eq.10000) goto 002
320 molcounter = 0
321 n = j
322 goto 002
323 else if (molcounter.gt.0 .and.togl(j).eq.totmol) then
324 do l=1, contj(j,i)
325 m = voisj(l,j,i)
326 if (togl(m).eq.0) then
327 molcounter = 0
328 call setmol (tmpmol, togl, tmbs, molcounter, i, voisj(l,j,i), totmol)
329 if (molcounter .lt. 0) then
330 alc_tab="SETMOL"
331 alc=.true.
332#ifdef OPENMP
333 goto 004
334#else
335 goto 001
336#endif
337 endif
338 if (tmbs.eq.na) goto 003
339 if (molcounter.eq.10000) goto 002
340 molcounter = 1
341 endif
342 enddo
343 endif
344 enddo
345
346 if (tmbs .lt. na) then
347 molcounter = 0
348 goto 002
349 endif
350
351 003 continue
352
353 if (frag_and_mol .eq. 1) then
354
355 tmpmol => themol
356 call allocate_mol_for_step (i, mtmbs(i))
357 do j=1, mtmbs(i)
358 allocate(atmol(tmpmol%ATOMES), stat=err)
359 if (err .ne. 0) then
360 alc_tab="ATMOL"
361 alc=.true.
362 molecules = 0
363#ifdef OPENMP
364 goto 004
365#else
366 goto 001
367#endif
368 endif
369
370 if (tmpmol%ATOMES .gt. 1) then
371 allocate(tmpat, stat=err)
372 if (err .ne. 0) then
373 alc_tab="TMPAT"
374 alc=.true.
375 molecules = 0
376#ifdef OPENMP
377 goto 004
378#else
379 goto 001
380#endif
381 endif
382 tmpat = tmpmol%FIRST_AT
383 do k=1, tmpmol%ATOMES
384 atmol(k) = tmpat%IND
385 if (k < tmpmol%ATOMES) then
386 tmpat => tmpat%NEXT
387 deallocate (tmpat%PREV)
388 endif
389 enddo
390 deallocate (tmpat)
391 else
392 atmol(1) = tmpmol%FIRST_AT%IND
393 deallocate (tmpmol%FIRST_AT)
394 endif
395 call send_mol_details (tmpmol%STEP, tmpmol%MID, tmpmol%ATOMES, nsp, tmpmol%BSP, atmol)
396 if (tmpmol%ATOMES .gt. 1) then
397 do l=1, tmpmol%ATOMES
398 m = atmol(l)
399 n = contj(m,tmpmol%STEP)
400 allocate(atvs(n), stat=err)
401 if (err .ne. 0) then
402 alc_tab="ATVS"
403 alc=.true.
404 molecules = 0
405#ifdef OPENMP
406 goto 004
407#else
408 goto 001
409#endif
410 endif
411 do o=1, n
412 atvs(o)= voisj(o,m,tmpmol%STEP)
413 enddo
414 call send_mol_neighbors (tmpmol%STEP, tmpmol%MID, m, n, atvs)
415 deallocate(atvs)
416 enddo
417 endif
418 deallocate(atmol)
419
420 if (j .lt. mtmbs(i)) tmpmol => tmpmol%NEXT
421
422 enddo
423 call setup_molecules (i)
424 endif
425
426 do while (tmpmol%MID .gt. 1)
427 tmpmol => tmpmol%PREV
428 deallocate (tmpmol%NEXT%BSP)
429 deallocate (tmpmol%NEXT)
430 enddo
431 deallocate (tmpmol%BSP)
432
433 call setup_fragments (i, togl)
434
435#ifdef OPENMP
436 004 continue
437#endif
438enddo
439
440#ifdef OPENMP
441!$OMP END DO NOWAIT
442005 continue
443if (allocated(togl)) deallocate (togl)
444if (allocated(themol)) deallocate(themol)
445if (allocated(atmol)) deallocate(atmol)
446if (allocated(atvs)) deallocate(atvs)
447!$OMP END PARALLEL
448#else
449if (allocated(togl)) deallocate (togl)
450if (allocated(themol)) deallocate(themol)
451if (allocated(atvs)) deallocate(atvs)
452if (allocated(atmol)) deallocate(atmol)
453#endif
454
455molps = 0
456j = 0
457do i=1, ns
458 molps = molps + mtmbs(i)
459 j = max(mtmbs(i), j)
460enddo
461call send_coord_opengl (2, 1, 0, 0, j, 1)
462call init_menu_fragmol (2)
463
464if (frag_and_mol .eq. 1) then
465 call setup_menu_molecules ()
466endif
467
468molecules=1
469
470001 continue
471
472if (alc) then
473 call show_error ("Impossible to allocate memory !"//char(0), &
474 "Function: molecules"//char(0), char(9)//"Table: "//alc_tab(1:len_trim(alc_tab))//char(0))
475endif
476
477if (allocated(mtmbs)) deallocate(mtmbs)
478
479END FUNCTION molecules
#define max(a, b)
Definition global.h:92
void setup_molecules()
void show_error(char *error, int val, GtkWidget *win)
show error message
Definition interface.c:299
recursive subroutine setmol(this_mol, toglin, stmb, molcount, the_step, the_atom, the_id)
Definition molecules.F90:93
logical function add_ato(this_mol, atom_id)
Definition molecules.F90:65
integer(kind=c_int) function molecules(frag_and_mol, allbonds)
logical function add_mol(this_mol, mol_id, step_id)
Definition molecules.F90:22
integer err
integer nsp