atomes 1.1.14
atomes: an atomic scale modeling tool box
Loading...
Searching...
No Matches
spherical.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
21! Bond order parameter from spherical harmonics
22
23INTEGER (KIND=c_int) FUNCTION sphericals (MAXL, SPC, GEO, IDC, COOSPH)
24
25 USE parameters
26#ifdef OPENMP
27!$ USE OMP_LIB
28#endif
29 IMPLICIT NONE
30
31 INTEGER (KIND=c_int), INTENT(IN) :: maxl, spc, geo, idc
32 INTEGER (KIND=c_int), DIMENSION(NSP), INTENT(IN) :: coosph
33 INTEGER :: nspsh
34 INTEGER, DIMENSION(:), ALLOCATABLE :: neigh
35 LOGICAL :: sphrun
36 DOUBLE PRECISION :: xc, yc, zc
37 DOUBLE PRECISION :: sr, st, sp
38 DOUBLE PRECISION, DIMENSION(0:MAXL,-MAXL:MAXL) :: hsp
39! DOUBLE PRECISION, DIMENSION(:,:,:), ALLOCATABLE :: THSP
40 DOUBLE PRECISION, DIMENSION(:,:), ALLOCATABLE :: athsp
41 DOUBLE PRECISION, DIMENSION(:,:), ALLOCATABLE :: sptshp
42 DOUBLE PRECISION, DIMENSION(0:MAXL) :: spha
43#ifdef OPENMP
44 INTEGER :: numth
45 LOGICAL :: doatoms
46#endif
47 INTERFACE
48 DOUBLE PRECISION FUNCTION plegendre (l, m, x)
49 INTEGER, INTENT(IN) :: l, m
50 DOUBLE PRECISION, INTENT(IN) :: x
51 END FUNCTION
52 DOUBLE PRECISION FUNCTION calcdij (R12, AT1, AT2, STEP_1, STEP_2, SID)
53 DOUBLE PRECISION, DIMENSION(3), INTENT(INOUT) :: r12
54 INTEGER, INTENT(IN) :: at1, at2, step_1, step_2, sid
55 END FUNCTION
56 END INTERFACE
57
58 if (allocated(neigh)) deallocate(neigh)
59 allocate(neigh(nsp), stat=err)
60 if (err .ne. 0) then
61 call show_error ("Impossible to allocate memory"//char(0), &
62 "Function: sphericals"//char(0), "Table: NEIGH"//char(0))
64 goto 001
65 endif
66
67! if (allocated(THSP)) deallocate(THSP)
68! allocate(THSP(NBONDS,0:MAXL,-MAXL:MAXL), STAT=ERR)
69! if (ERR .ne. 0) then
70! call show_error ("Impossible to allocate memory"//CHAR(0), &
71! "Function: sphericals"//CHAR(0), "Table: THSP"//CHAR(0))
72! sphericals=0
73! goto 001
74! endif
75 if (allocated(athsp)) deallocate(athsp)
76 allocate(athsp(0:maxl,-maxl:maxl), stat=err)
77 if (err .ne. 0) then
78 call show_error ("Impossible to allocate memory"//char(0), &
79 "Function: sphericals"//char(0), "Table: ATHSP"//char(0))
81 goto 001
82 endif
83 if (allocated(sptshp)) deallocate(sptshp)
84 allocate(sptshp(0:maxl,-maxl:maxl), stat=err)
85 if (err .ne. 0) then
86 call show_error ("Impossible to allocate memory"//char(0), &
87 "Function: sphericals"//char(0), "Table: SPTSHP"//char(0))
89 goto 001
90 endif
91
92 athsp(:,:)=0.0d0
93 sptshp(:,:)=0.0d0
94 anbonds=0
95 nspsh=0
96#ifdef OPENMP
97 numth = omp_get_max_threads()
98 doatoms=.false.
99 if (ns.lt.numth) then
100 if (numth .ge. 2*(ns-1)) then
101 doatoms=.true.
102 else
103 numth=ns
104 endif
105 endif
106
107 if (all_atoms) doatoms=.true.
108
109 if (doatoms) then
110 if (na.lt.numth) numth=na
111#ifdef DEBUG
112 write (6, *) "OpenMP on atoms, NUMTH= ",numth
113#endif
114 ! OpemMP on atoms
115 do i=1, ns
116
117 !$OMP PARALLEL NUM_THREADS(NUMTH) DEFAULT (NONE) &
118 !$OMP& PRIVATE(SPHRUN, NEIGH, Dij, Rij, j, k, l, m, XC, YC, ZC, SR, ST, SP, HSP) &
119 !$OMP& SHARED(NUMTH, i, NA, NSP, NCELLS, LOT, SPC, CONTJ, VOISJ, NSPSH, ATHSP, SPTSHP, ANBONDS, COOSPH, MAXL)
120 !$OMP DO SCHEDULE(STATIC,NA/NUMTH)
121 do j=1, na
122
123 if (lot(j) .eq. spc+1) then
124 sphrun=.true.
125 neigh(:)=0
126 do k=1, contj(j,i)
127 neigh(lot(voisj(k,j,i)))=neigh(lot(voisj(k,j,i)))+1
128 enddo
129
130 !$OMP ATOMIC
131 nspsh=nspsh+contj(j,i)
132 do k=1, nsp
133 if (neigh(k) .ne. coosph(k)) then
134 sphrun=.false.
135 exit
136 endif
137 enddo
138
139 if (sphrun) then
140 !$OMP ATOMIC
142 endif
143
144 do k=1, contj(j,i)
145 if (ncells .gt. 1) then
146 dij = calcdij(rij, j, voisj(k,j,i), i, i, i)
147 else
148 dij = calcdij(rij, j, voisj(k,j,i), i, i, 1)
149 endif
150 xc=rij(1)
151 yc=rij(2)
152 zc=rij(3)
153! NBONDS=NBONDS+1
154 call cart2spher(xc, yc, zc, sr, st, sp)
155 do l=0, maxl
156 do m=0, l
157 hsp(l,m) = 0.0d0
158 hsp(l,m) = plegendre(l, m, st) * cos(sp * m)
159 if (m .ne. 0) hsp(l,-m) = (-1)**m*hsp(l,m)
160 enddo
161 do m=-l, l
162! THSP(NBONDS,l,m)=HSP(l,m)
163 !$OMP ATOMIC
164 sptshp(l,m)=sptshp(l,m)+hsp(l,m)
165 if (sphrun) then
166 !$OMP ATOMIC
167 athsp(l,m)=athsp(l,m)+hsp(l,m)
168 endif
169 enddo
170 enddo
171 enddo
172 endif
173 enddo
174 !$OMP END DO NOWAIT
175 !$OMP END PARALLEL
176 enddo
177
178 else
179#ifdef DEBUG
180 write (6, *) "OpenMP on MD steps, NUMTH= ",numth
181#endif
182 ! OpemMP on MD steps
183 !$OMP PARALLEL NUM_THREADS(NUMTH) DEFAULT (NONE) &
184 !$OMP& PRIVATE(SPHRUN, NEIGH, Dij, Rij, i, j, k, l, m, XC, YC, ZC, SR, ST, SP, HSP) &
185 !$OMP& SHARED(NUMTH, NS, NA, NSP, NCELLS, LOT, SPC, CONTJ, VOISJ, NSPSH, ATHSP, SPTSHP, ANBONDS, COOSPH, MAXL)
186 !$OMP DO SCHEDULE(STATIC,NS/NUMTH)
187#endif
188 do i=1, ns
189 do j=1, na
190
191 if (lot(j) .eq. spc+1) then
192 sphrun=.true.
193 neigh(:)=0
194 do k=1, contj(j,i)
195 neigh(lot(voisj(k,j,i)))=neigh(lot(voisj(k,j,i)))+1
196 enddo
197#ifdef OPENMP
198 !$OMP ATOMIC
199#endif
200 nspsh=nspsh+contj(j,i)
201 do k=1, nsp
202 if (neigh(k) .ne. coosph(k)) then
203 sphrun=.false.
204 exit
205 endif
206 enddo
207
208 if (sphrun) then
209#ifdef OPENMP
210 !$OMP ATOMIC
211#endif
213 endif
214
215 do k=1, contj(j,i)
216 if (ncells .gt. 1) then
217 dij = calcdij(rij, j, voisj(k,j,i), i, i, i)
218 else
219 dij = calcdij(rij, j, voisj(k,j,i), i, i, 1)
220 endif
221 xc=rij(1)
222 yc=rij(2)
223 zc=rij(3)
224! NBONDS=NBONDS+1
225 call cart2spher(xc, yc, zc, sr, st, sp)
226 do l=0, maxl
227 do m=0, l
228 hsp(l,m) = 0.0d0
229 hsp(l,m) = plegendre(l, m, st) * cos(sp * m)
230 if (m .ne. 0) hsp(l,-m) = (-1)**m*hsp(l,m)
231 enddo
232 do m=-l, l
233! THSP(NBONDS,l,m)=HSP(l,m)
234#ifdef OPENMP
235 !$OMP ATOMIC
236#endif
237 sptshp(l,m)=sptshp(l,m)+hsp(l,m)
238 if (sphrun) then
239#ifdef OPENMP
240 !$OMP ATOMIC
241#endif
242 athsp(l,m)=athsp(l,m)+hsp(l,m)
243 endif
244 enddo
245 enddo
246 enddo
247 endif
248 enddo
249 enddo
250#ifdef OPENMP
251 !$OMP END DO NOWAIT
252 !$OMP END PARALLEL
253 endif
254#endif
255
256 if (geo .eq. 0) then
257 spha(:)=0.0d0
258 if (nspsh .gt. 0) then
259 do l=0, maxl
260 do m=-l, l
261 spha(l)=spha(l)+(sptshp(l,m)/nspsh)**2
262 enddo
263 spha(l)=sqrt(4*pi*spha(l)/(2*l+1))
264 enddo
265 endif
266 call save_curve (maxl+1, spha, idc-1, idsp)
267 endif
268 spha(:)=0.0d0
269 if (anbonds .gt. 0) then
270 do l=0, maxl
271 do m=-l, l
272 spha(l)=spha(l)+(athsp(l,m)/anbonds)**2
273 enddo
274 spha(l)=sqrt(4*pi*spha(l)/(2*l+1))
275 enddo
276 endif
277 call save_curve (maxl+1, spha, idc, idsp)
278
279 sphericals = 1
280
281 001 continue
282
283! if (allocated(THSP)) deallocate(THSP)
284 if (allocated(athsp)) deallocate(athsp)
285 if (allocated(sptshp)) deallocate(sptshp)
286 if (allocated(neigh)) deallocate(neigh)
287
288END FUNCTION
289
290SUBROUTINE cart2spher(XC, YC, ZC, RS, TS, PS)
291
292DOUBLE PRECISION, INTENT(IN) :: XC, YC, ZC
293DOUBLE PRECISION, INTENT(OUT) :: RS, TS, PS
294
295rs=0.0d0
296ts=0.0d0
297ps=0.0d0
298
299rs= sqrt(xc**2 + yc**2 + zc**2)
300ts= acos(zc/rs)
301ps= atan2(xc, yc)
302
303END SUBROUTINE
304
305! Adapted from Numercial Recipies !
306
307DOUBLE PRECISION FUNCTION plegendre (l, m, x)
308
309 DOUBLE PRECISION, PARAMETER :: pi=acos(-1.0)
310 INTEGER, INTENT(IN) :: l, m
311 DOUBLE PRECISION, INTENT(IN) :: x
312 DOUBLE PRECISION :: y
313 INTEGER :: i, ll
314 DOUBLE PRECISION :: fact, oldfact, pll, pmm, pmmp1, omx2
315
316 y=cos(x)
317 pmm=1.0
318 if (m > 0) then
319 omx2=(1.0-y)*(1.0+y)
320 fact=1.0
321 i = 1
322 do while (i.le.m)
323 pmm = pmm * (omx2*fact/(fact+1.0))
324 fact = fact + 2.0
325 i = i+1
326 enddo
327 endif
328 pmm=sqrt((2*m+1)*pmm/(4.0*pi))
329 if (mod(m,2) .eq. 1) pmm=-pmm
330
331 if (l .eq. m) then
332 plegendre=pmm
333 else
334 pmmp1=y*sqrt(2.0*m+3.0)*pmm
335 if (l .eq. (m+1)) then
336 plegendre=pmmp1
337 else
338 oldfact=sqrt(2.0*m+3.0)
339 ll=m+2
340 do while (ll.le.l)
341 fact=sqrt((4.0*ll*ll-1.0)/(ll*ll-m*m))
342 pll=(y*pmmp1-pmm/oldfact)*fact
343 oldfact=fact
344 pmm=pmmp1
345 pmmp1=pll
346 ll=ll+1
347 enddo
348 plegendre=pll
349 endif
350 endif
351
352END FUNCTION
353
354DOUBLE PRECISION FUNCTION plgndr(l, m, x)
355
356 DOUBLE PRECISION, PARAMETER :: pi=acos(-1.0)
357 INTEGER :: j
358 INTEGER, INTENT(IN) :: l, m
359 DOUBLE PRECISION, INTENT(IN) :: x
360 DOUBLE PRECISION :: prod
361
362 INTERFACE
363 DOUBLE PRECISION FUNCTION plegendre(l, m, x)
364 INTEGER, INTENT(IN) :: l, m
365 DOUBLE PRECISION, INTENT(IN) :: x
366 END FUNCTION
367 END INTERFACE
368
369 prod=1.0d0
370 j=l-m+1
371 do while (j.le.l+m)
372 prod = prod*j
373 j=j+1
374 enddo
375
376 plgndr=sqrt(4.0*pi*prod/(2*l+1))*plegendre(l,m,x)
377
378END FUNCTION
void show_error(char *error, int val, GtkWidget *win)
show error message
Definition interface.c:293
integer ncells
double precision x
integer, dimension(:,:), allocatable contj
integer idsp
integer err
double precision, dimension(3) rij
integer anbonds
integer, dimension(:,:,:), allocatable voisj
double precision dij
integer, dimension(:), allocatable lot
integer nsp
double precision, parameter pi
double precision function plgndr(l, m, x)
subroutine cart2spher(xc, yc, zc, rs, ts, ps)
integer(kind=c_int) function sphericals(maxl, spc, geo, idc, coosph)
Definition spherical.F90:24
double precision function plegendre(l, m, x)
double precision function calcdij(r12, at1, at2, step_1, step_2, sid)
Definition utils.F90:185