Octopus
math.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
22module math_oct_m
23 use debug_oct_m
24 use global_oct_m
25 use, intrinsic :: iso_fortran_env
30
31 implicit none
32
33 private
34 public :: &
35 is_close, &
37 ylmr_cmplx, &
38 ylmr_real, &
39 weights, &
40 factorial, &
41 hermite, &
46 ddelta, &
47 member, &
51 even, &
52 odd, &
56 pad, &
57 pad_pow2, &
58 log2, &
60 phi1, &
61 phi2, &
63 is_prime, &
74
75
76 interface is_close
77 module procedure dis_close_scalar, zis_close_scalar
78 end interface
79
80 interface diagonal_matrix
82 end interface diagonal_matrix
83
87
91
92
93 ! ------------------------------------------------------------------------------
96 interface interpolate
99 end interface interpolate
100 ! ------------------------------------------------------------------------------
101
102 interface log2
103 module procedure dlog2, ilog2, llog2
104 end interface log2
105
106 interface pad
107 module procedure pad4, pad8, pad48, pad88
108 end interface pad
109
110contains
111
130 elemental logical function dis_close_scalar(x, y, rtol, atol)
131 real(real64), intent(in) :: x, y
132 real(real64), optional, intent(in) :: rtol
133 real(real64), optional, intent(in) :: atol
134 real(real64) :: atol_, rtol_
135
136 atol_ = optional_default(atol, 1.e-8_real64)
137 rtol_ = optional_default(rtol, 1.e-5_real64)
138
139 dis_close_scalar = abs(x - y) <= (atol_ + rtol_ * abs(y))
140 end function dis_close_scalar
141
143 elemental logical function zis_close_scalar(x, y, rtol, atol)
144 complex(real64), intent(in) :: x, y
145 real(real64), optional, intent(in) :: rtol
146 real(real64), optional, intent(in) :: atol
147 real(real64) :: atol_, rtol_
148
149 atol_ = optional_default(atol, 1.e-8_real64)
150 rtol_ = optional_default(rtol, 1.e-5_real64)
151
152 zis_close_scalar = abs(x - y) <= (atol_ + rtol_ * abs(y))
153 end function zis_close_scalar
154
155
156 ! ---------------------------------------------------------
159 pure function idiagonal_matrix(dim, diag) result(matrix)
160 integer, intent(in) :: dim
161 integer, intent(in) :: diag
162 integer :: matrix(dim, dim)
163
164 integer :: ii
165
166 matrix = 0
167 do ii = 1, dim
168 matrix(ii, ii) = diag
169 end do
170
171 end function idiagonal_matrix
172
173 ! ---------------------------------------------------------
174 recursive function hermite(n, x) result (h)
175 integer, intent(in) :: n
176 real(real64), intent(in) :: x
178 real(real64) :: h
179
180 ! no push_sub, called too frequently
182 if (n <= 0) then
183 h = m_one
184 elseif (n == 1) then
185 h = m_two*x
186 else
187 h = m_two*x*hermite(n-1,x) - m_two*(n-1)*hermite(n-2,x)
188 end if
190 end function hermite
191
192
193 ! ---------------------------------------------------------
194 recursive function factorial (n) RESULT (fac)
195 integer, intent(in) :: n
196
197 integer :: fac
198
199 ! no push_sub for recursive function
200
201 if (n <= 1) then
202 fac = 1
203 else
204 fac = n * factorial(n-1)
205 end if
206 end function factorial
207
208 ! ---------------------------------------------------------
210 subroutine ylmr_cmplx(xx, li, mi, ylm)
211 real(real64), intent(in) :: xx(3)
212 integer, intent(in) :: li, mi
213 complex(real64), intent(out) :: ylm
214
215 integer :: i
216 real(real64) :: dx, dy, dz, r, plm, cosm, sinm, cosmm1, sinmm1, cosphi, sinphi
217 real(real64), parameter :: tiny = 1.e-15_real64
218
219 ! no push_sub: this routine is called too many times
220
221 ! if l=0, no calculations are required
222 if (li == 0) then
223 ylm = cmplx(sqrt(m_one/(m_four*m_pi)), m_zero, real64)
224 return
225 end if
226
227 r = sqrt(xx(1)**2 + xx(2)**2 + xx(3)**2)
228
229 ! if r=0, direction is undefined => make ylm=0 except for l=0
230 if (r <= tiny) then
231 ylm = m_z0
232 return
233 end if
234 dx = xx(1)/r
235 dy = xx(2)/r
236 dz = xx(3)/r
237
238 ! get the associated Legendre polynomial (including the normalization factor)
239 ! We need to avoid getting outside [-1:1] due to rounding errors
240 if(abs(dz) > m_one) dz = sign(m_one, dz)
241 plm = loct_legendre_sphplm(li, abs(mi), dz)
242
243 ! compute sin(|m|*phi) and cos(|m|*phi)
244 r = sqrt(dx*dx + dy*dy)
245 if(r > tiny) then
246 cosphi = dx/r
247 sinphi = dy/r
248 else ! In this case the values are ill defined so we choose \phi=0
249 cosphi = m_zero
250 sinphi = m_zero
251 end if
253 cosm = m_one
254 sinm = m_zero
255 do i = 1, abs(mi)
256 cosmm1 = cosm
257 sinmm1 = sinm
258 cosm = cosmm1*cosphi - sinmm1*sinphi
259 sinm = cosmm1*sinphi + sinmm1*cosphi
260 end do
261
262 !And now ylm
263 ylm = plm*cmplx(cosm, sinm, real64)
264
265 if (mi < 0) then
266 ylm = conjg(ylm)
267 do i = 1, abs(mi)
268 ylm = -ylm
269 end do
270 end if
271
272 end subroutine ylmr_cmplx
273
274
275 ! ---------------------------------------------------------
281 subroutine ylmr_real(xx, li, mi, ylm)
282 real(real64), intent(in) :: xx(3)
283 integer, intent(in) :: li, mi
284 real(real64), intent(out) :: ylm
285
286 integer, parameter :: lmaxd = 20
287 real(real64), parameter :: tiny = 1.e-15_real64
288 integer :: i, ilm0, l, m, mabs
289 integer, save :: lmax = -1
290
291 real(real64) :: cmi, cosm, cosmm1, cosphi, dphase, dplg, fac, &
292 fourpi, plgndr, phase, pll, pmm, pmmp1, sinm, &
293 sinmm1, sinphi, rsize, rx, ry, rz, xysize
294 real(real64), save :: c(0:(lmaxd+1)*(lmaxd+1))
295
296 ! no push_sub: called too frequently
297
298 ! evaluate normalization constants once and for all
299 if (li > lmax) then
300 fourpi = m_four*m_pi
301 do l = 0, li
302 ilm0 = l*l + l
303 do m = 0, l
304 fac = (2*l+1)/fourpi
305 do i = l - m + 1, l + m
306 fac = fac/i
307 end do
308 c(ilm0 + m) = sqrt(fac)
309 ! next line because ylm are real combinations of m and -m
310 if (m /= 0) c(ilm0 + m) = c(ilm0 + m)*sqrt(m_two)
311 c(ilm0 - m) = c(ilm0 + m)
312 end do
313 end do
314 lmax = li
315 end if
316
317 ! if l=0, no calculations are required
318 if (li == 0) then
319 ylm = c(0)
320 return
321 end if
322
323 ! if r=0, direction is undefined => make ylm=0 except for l=0
324 rsize = sqrt(xx(1)**2 + xx(2)**2 + xx(3)**2)
325 if (rsize < tiny) then
326 ylm = m_zero
327 return
328 end if
329
330 rx = xx(1)/rsize
331 ry = xx(2)/rsize
332 rz = xx(3)/rsize
333
334 ! explicit formulas for l=1 and l=2
335 if (li == 1) then
336 select case (mi)
337 case (-1)
338 ylm = (-c(1))*ry
339 case (0)
340 ylm = c(2)*rz
341 case (1)
342 ylm = (-c(3))*rx
343 end select
344 return
345 end if
346
347 if (li == 2) then
348 select case (mi)
349 case (-2)
350 ylm = c(4)*6.0_real64*rx*ry
351 case (-1)
352 ylm = (-c(5))*m_three*ry*rz
353 case (0)
354 ylm = c(6)*m_half*(m_three*rz*rz - m_one)
355 case (1)
356 ylm = (-c(7))*m_three*rx*rz
357 case (2)
358 ylm = c(8)*m_three*(rx*rx - ry*ry)
359 end select
360 return
361 end if
362
363 ! general algorithm based on routine plgndr of numerical recipes
364 mabs = abs(mi)
365 xysize = sqrt(max(rx*rx + ry*ry, tiny))
366 cosphi = rx/xysize
367 sinphi = ry/xysize
368 cosm = m_one
369 sinm = m_zero
370 do m = 1, mabs
371 cosmm1 = cosm
372 sinmm1 = sinm
373 cosm = cosmm1*cosphi - sinmm1*sinphi
374 sinm = cosmm1*sinphi + sinmm1*cosphi
375 end do
376
377 if (mi < 0) then
378 phase = sinm
379 dphase = mabs*cosm
380 else
381 phase = cosm
382 dphase = (-mabs)*sinm
383 end if
384
385 pmm = m_one
386 fac = m_one
387
388 if (mabs > m_zero) then
389 do i = 1, mabs
390 pmm = (-pmm)*fac*xysize
391 fac = fac + m_two
392 end do
393 end if
394
395 if (li == mabs) then
396 plgndr = pmm
397 dplg = (-li)*rz*pmm/(xysize**2)
398 else
399 pmmp1 = rz*(2*mabs + 1)*pmm
400 if (li == mabs + 1) then
401 plgndr = pmmp1
402 dplg = -((li*rz*pmmp1 - (mabs + li)*pmm)/(xysize**2))
403 else
404 do l = mabs + 2, li
405 pll = (rz*(2*l - 1)*pmmp1 - (l + mabs - 1)*pmm)/(l - mabs)
406 pmm = pmmp1
407 pmmp1 = pll
408 end do
409 plgndr = pll
410 dplg = -((li*rz*pll - (l + mabs - 1)*pmm)/(xysize**2))
411 end if
412 end if
413
414 ilm0 = li*li + li
415 cmi = c(ilm0 + mi)
416 ylm = cmi*plgndr*phase
417
418 end subroutine ylmr_real
419
420
421 ! ---------------------------------------------------------
431 subroutine weights(N, M, cc, side)
432 integer, intent(in) :: n, m
433 real(real64), intent(out) :: cc(0:,0:,0:)
434 integer, optional, intent(in) :: side
435
436 integer :: i, j, k, mn, side_
437 real(real64) :: c1, c2, c3, c4, c5, xi
438 real(real64), allocatable :: x(:)
439
440 push_sub(weights)
441
442 safe_allocate(x(0:m))
443
444 if (present(side)) then
445 side_ = side
446 else
447 side_ = 0
448 end if
449
450 select case (side_)
451 case (-1)
452 ! grid-points for left-side finite-difference formulas on an equi-spaced grid
453 mn = m
454 x(:) = (/(-i,i=0,mn)/)
455 case (+1)
456 ! grid-points for right-side finite-difference formulas on an equi-spaced grid
457 mn = m
458 x(:) = (/(i,i=0,mn)/)
459 case default
460 ! grid-points for centered finite-difference formulas on an equi-spaced grid
461 mn = m/2
462 x(:) = (/0,(-i,i,i=1,mn)/)
463 end select
464
465
466
467 xi = m_zero ! point at which the approx. are to be accurate
468
469 cc = m_zero
470 cc(0,0,0) = m_one
471
472 c1 = m_one
473 c4 = x(0) - xi
474
475 do j = 1, m
476 mn = min(j,n)
477 c2 = m_one
478 c5 = c4
479 c4 = x(j) - xi
480
481 do k = 0, j - 1
482 c3 = x(j) - x(k)
483 c2 = c2*c3
484
485 if (j <= n) cc(k, j - 1, j) = m_zero
486 cc(k, j, 0) = c4*cc(k, j - 1, 0)/c3
487
488 do i = 1, mn
489 cc(k, j, i) = (c4*cc(k, j - 1, i) - i*cc(k, j - 1, i - 1))/c3
490 end do
491
492 cc(j, j, 0) = -c1*c5*cc(j - 1, j - 1, 0) / c2
493 end do
494
495 do i = 1, mn
496 cc(j, j, i) = c1*(i*cc(j - 1, j - 1, i - 1) - c5*cc(j - 1, j - 1, i))/c2
497 end do
498
499 c1 = c2
500 end do
501
502 safe_deallocate_a(x)
503 pop_sub(weights)
504 end subroutine weights
505
506 ! ---------------------------------------------------------
507 real(real64) pure function ddelta(i, j)
508 integer, intent(in) :: i
509 integer, intent(in) :: j
510
511 ! no push_sub in pure function
512
513 if (i == j) then
514 ddelta = m_one
515 else
516 ddelta = m_zero
517 end if
518
519 end function ddelta
520
521
522 ! ---------------------------------------------------------
525 subroutine make_idx_set(n, out, length, in)
526 integer, intent(in) :: n
527 integer, allocatable, intent(out) :: out(:)
528 integer, intent(out) :: length
529 integer, optional, intent(in) :: in(:)
530
531 integer :: i
532
533 push_sub(make_idx_set)
534
535 if (present(in)) then
536 length = ubound(in, 1)
537 safe_allocate(out(1:length))
538 out(:) = in(:)
539 else
540 length = n
541 safe_allocate(out(1:length))
542 do i = 1, length
543 out(i) = i
544 end do
545 end if
546
547 pop_sub(make_idx_set)
548 end subroutine make_idx_set
549
550
551 ! ---------------------------------------------------------
554 logical function member(n, a)
555 integer, intent(in) :: n
556 integer, intent(in) :: a(:)
557
558 integer :: i
559
560 ! no push_sub, called too frequently
561
562 member = .false.
563
564 do i = 1, ubound(a, 1)
565 if (a(i) == n) then
566 member = .true.
567 exit
568 end if
569 end do
570
571 end function member
572
573
574 ! ---------------------------------------------------------
575 subroutine interpolation_coefficients(nn, xa, xx, cc)
576 integer, intent(in) :: nn
577 real(real64), intent(in) :: xa(:)
578 real(real64), intent(in) :: xx
579 real(real64), intent(out) :: cc(:)
580
581 integer :: ii, kk
582
583 ! no push_sub, called too frequently
584
585 do ii = 1, nn
586 cc(ii) = m_one
587 do kk = 1, nn
588 if (kk == ii) cycle
589 cc(ii) = cc(ii)*(xx - xa(kk))/(xa(ii) - xa(kk))
590 end do
591 end do
592
593 end subroutine interpolation_coefficients
594
595
596 ! ---------------------------------------------------------
598 logical pure function even(n)
599 integer, intent(in) :: n
601 even = (mod(n, 2) == 0)
602
603 end function even
604
605
606 ! ---------------------------------------------------------
608 logical pure function odd(n)
609 integer, intent(in) :: n
610
611 odd = .not. even(n)
612
613 end function odd
614
615 ! ---------------------------------------------------------
619 real(real64), intent(in) :: x(:)
620 real(real64), intent(out) :: u(:)
621
622 integer :: n, k, j
623 real(real64) :: sumx2
624 real(real64), allocatable :: xx(:)
625
627
628 n = size(x)
629 assert(n>1)
630 assert(size(u) == n-1)
631
632 ! These lines make the code less machine-dependent.
633 safe_allocate(xx(1:n))
634 do j = 1, n
635 if (abs(x(j))<1.0e-8_real64) then
636 xx(j) = m_zero
637 else
638 xx(j) = x(j)
639 end if
640 end do
641
642 u = m_zero
643 do k = 1, n-1
644 sumx2 = m_zero
645 do j = k+1, n
646 sumx2 = sumx2 + xx(j)**2
647 end do
648 if (abs(sumx2) <= m_epsilon .and. abs(xx(k)) <= m_epsilon) exit
649 if (k < n - 1) then
650 u(k) = atan2(sqrt(sumx2), xx(k))
651 else
652 u(n-1) = atan2(xx(n), xx(n-1))
653 end if
654 end do
655
656
658 end subroutine cartesian2hyperspherical
659 ! ---------------------------------------------------------
660
661
662 ! ---------------------------------------------------------
665 subroutine hyperspherical2cartesian(u, x)
666 real(real64), intent(in) :: u(:)
667 real(real64), intent(out) :: x(:)
669 integer :: n, j, k
670
672
673 n = size(x)
674 assert(n>1)
675 assert(size(u) == n-1)
676
677 if (n == 2) then
678 x(1) = cos(u(1))
679 x(2) = sin(u(1))
680 elseif (n == 3) then
681 x(1) = cos(u(1))
682 x(2) = sin(u(1))*cos(u(2))
683 x(3) = sin(u(1))*sin(u(2))
684 else
685 x(1) = cos(u(1))
686 x(2) = sin(u(1))*cos(u(2))
687 x(3) = sin(u(1))*sin(u(2))*cos(u(3))
688 do j = 4, n - 1
689 x(j) = m_one
690 do k = 1, j - 1
691 x(j) = x(j) * sin(u(k))
692 end do
693 x(j) = x(j) * cos(u(j))
694 end do
695 x(n) = m_one
696 do k = 1, n - 2
697 x(n) = x(n) * sin(u(k))
698 end do
699 x(n) = x(n) * sin(u(n-1))
700 end if
703 end subroutine hyperspherical2cartesian
704 ! ---------------------------------------------------------
705
706
707 ! ---------------------------------------------------------
711 subroutine hypersphere_grad_matrix(grad_matrix, r, x)
712 real(real64), intent(out) :: grad_matrix(:,:)
713 real(real64), intent(in) :: r
714 real(real64), intent(in) :: x(:)
715
716 integer :: n, l, m
717
719
720 n = size(x)+1 ! the dimension of the matrix is (n-1)x(n)
721
722 ! --- l=1 ---
723 grad_matrix = m_one
724 grad_matrix(1,1) = -r*sin(x(1))
725 do m = 2, n-1
726 grad_matrix(m,1) = m_zero
727 end do
728
729 ! --- l=2..(n-1) ---
730 do l=2, n-1
731 do m=1, n-1
732 if (m == l) then
733 grad_matrix(m,l) = -r*grad_matrix(m,l)*product(sin(x(1:l)))
734 elseif (m < l) then
735 grad_matrix(m,l) = grad_matrix(m,l)*r*cos(x(m))*cos(x(l))*product(sin(x(1:m-1)))*product(sin(x(m+1:l-1)))
736 else
737 grad_matrix(m,l) = m_zero
738 end if
739 end do
740 end do
741
742 ! --- l=n ---
743 do m=1, n-1
744 grad_matrix(m,n) = r*cos(x(m))*grad_matrix(m,n)*product(sin(x(1:m-1)))*product(sin(x(m+1:n-1)))
745 end do
746
748 end subroutine hypersphere_grad_matrix
749
750 ! ---------------------------------------------------------
751 integer(int64) pure function pad88(size, blk)
752 integer(int64), intent(in) :: size
753 integer(int64), intent(in) :: blk
754
755 integer(int64) :: mm
756
757 mm = mod(size, blk)
758 if (mm == 0) then
759 pad88 = size
760 else
761 pad88 = size + blk - mm
762 end if
763 end function pad88
764
765 ! ---------------------------------------------------------
766 integer(int64) pure function pad48(size, blk)
767 integer, intent(in) :: size
768 integer(int64), intent(in) :: blk
769
770 pad48 = pad88(int(size, int64), blk)
771 end function pad48
772
773 ! ---------------------------------------------------------
774 integer(int64) pure function pad8(size, blk)
775 integer(int64), intent(in) :: size
776 integer, intent(in) :: blk
777
778 pad8 = pad88(size, int(blk, int64))
779 end function pad8
780
781 ! ---------------------------------------------------------
782 integer pure function pad4(size, blk)
783 integer, intent(in) :: size
784 integer, intent(in) :: blk
785
786 pad4 = int(pad88(int(size, int64), int(blk, int64)), int32)
787 end function pad4
788
789 ! ---------------------------------------------------------
790
795 integer pure function pad_pow2(size)
796 integer, intent(in) :: size
797
798 integer :: mm, mm2
799
800 mm = size
801 pad_pow2 = 1
802
803 ! loop below never terminates otherwise! just pick 1 as value.
804 if (size == 0) return
805
806 ! first we divide by two all the times we can, so we catch exactly
807 ! the case when size is already a power of two
808 do
809 mm2 = mm/2
810 if (mm - 2*mm2 /= 0) exit
812 mm = mm2
813 end do
814
815 ! the rest is handled by log2
816 if (mm /= 1) then
817 pad_pow2 = pad_pow2*2**(ceiling(log(real(mm, real64) )/log(2.0_8)))
818 end if
819
820 end function pad_pow2
821
822 ! -------------------------------------------------------
823
824 real(real64) pure function dlog2(xx)
825 real(real64), intent(in) :: xx
826
827 dlog2 = log(xx)/log(m_two)
828 end function dlog2
829
830 ! -------------------------------------------------------
831
832 integer pure function ilog2(xx)
833 integer, intent(in) :: xx
834
835 ilog2 = nint(log2(real(xx, real64) ))
836 end function ilog2
837
838 ! -------------------------------------------------------
839
840 integer(int64) pure function llog2(xx)
841 integer(int64), intent(in) :: xx
842
843 llog2 = nint(log2(real(xx, real64) ), kind=int64)
844 end function llog2
845
846 ! -------------------------------------------------------
848 complex(real64) pure function exponential(z)
849 complex(real64), intent(in) :: z
850
851 exponential = exp(z)
852 end function exponential
853
854 ! -------------------------------------------------------
860 complex(real64) pure function phi1(z)
861 complex(real64), intent(in) :: z
862
863 real(real64), parameter :: cut = 0.002_real64
864
865 if (abs(z) < cut) then
866 phi1 = m_one + m_half*z*(m_one + z/m_three*(m_one + m_fourth*z*(m_one + z/m_five)))
867 else
868 phi1 = (exp(z) - m_z1)/z
869 end if
870 end function phi1
871
872 ! -------------------------------------------------------
879 complex(real64) pure function phi2(z)
880 complex(real64), intent(in) :: z
881
882 real(real64), parameter :: cut = 0.002_real64
883
884 if (abs(z) < cut) then
885 phi2 = m_half + z/6.0_real64*(m_one + m_fourth*z*(m_one + z/m_five*(m_one + z/6.0_real64)))
886 else
887 phi2 = (exp(z) - z - m_z1)/z**2
888 end if
889 end function phi2
890
891 ! -------------------------------------------------------
893 real(real64) pure function square_root(x)
894 real(real64), intent(in) :: x
895
896 square_root = sqrt(x)
897 end function square_root
898
899 ! -------------------------------------------------------
900
901 logical function is_prime(n)
902 integer, intent(in) :: n
903
904 integer :: i, root
905
906 push_sub(is_prime)
907
908 if (n < 1) then
909 message(1) = "Internal error: is_prime does not take negative numbers."
910 call messages_fatal(1)
911 end if
912 if (n == 1) then
913 is_prime = .false.
914 pop_sub(is_prime)
915 return
916 end if
918 root = nint(sqrt(real(n, real64) ))
919 do i = 2, root
920 if (mod(n,i) == 0) then
921 is_prime = .false.
922 pop_sub(is_prime)
923 return
924 end if
925 end do
926
927 is_prime = .true.
928 pop_sub(is_prime)
929 end function is_prime
930
931 ! ---------------------------------------------------------
936 subroutine generate_rotation_matrix(R, ff, tt)
937 real(real64), intent(out) :: r(:,:)
938 real(real64), intent(in) :: ff(:)
939 real(real64), intent(in) :: tt(:)
940
941 integer :: dim, i, j
942 real(real64) :: th, uv, uu, vv, ft
943 real(real64), allocatable :: axis(:), u(:), v(:), f(:), t(:), p(:)
944
946
947 dim = size(ff,1)
948
949 assert((dim < 3) .or. (dim > 2))
950 assert(size(tt,1) == dim)
951 assert((size(r,1) == dim) .and. (size(r,2) == dim))
952
953 safe_allocate(u(1:dim))
954 safe_allocate(v(1:dim))
955 safe_allocate(f(1:dim))
956 safe_allocate(t(1:dim))
957
958
959 !normalize
960 f = ff / norm2(ff)
961 t = tt / norm2(tt)
962
963 ft = dot_product(f,t)
964
965 if (abs(ft) < m_one) then
966 select case (dim)
967 case (2)
968 th = acos(ft)
969 r(1,1) = cos(th)
970 r(1,2) = -sin(th)
971
972 r(2,1) = sin(th)
973 r(2,2) = cos(th)
974
975 case (3)
976 if (.false.) then
977 !Old implementation
978 safe_allocate(axis(1:dim))
979 th = acos(ft)
980
981 u = f / dot_product(f,f)
982 v = t /dot_product(t,t)
983
984 axis = dcross_product(u,v)
985 axis = axis / norm2(axis)
987 r(1,1) = cos(th) + axis(1)**2 * (1 - cos(th))
988 r(1,2) = axis(1)*axis(2)*(1-cos(th)) + axis(3)*sin(th)
989 r(1,3) = axis(1)*axis(3)*(1-cos(th)) - axis(2)*sin(th)
990
991 r(2,1) = axis(2)*axis(1)*(1-cos(th)) - axis(3)*sin(th)
992 r(2,2) = cos(th) + axis(2)**2 * (1 - cos(th))
993 r(2,3) = axis(2)*axis(3)*(1-cos(th)) + axis(1)*sin(th)
995 r(3,1) = axis(3)*axis(1)*(1-cos(th)) + axis(2)*sin(th)
996 r(3,2) = axis(3)*axis(2)*(1-cos(th)) - axis(1)*sin(th)
997 r(3,3) = cos(th) + axis(3)**2 * (1 - cos(th))
998
999 safe_deallocate_a(axis)
1000 end if
1001
1002 if (.true.) then
1003 !Naive implementation
1004 th = acos(ft)
1005 u = dcross_product(f,t)
1006 u = u / norm2(u)
1007
1008 r(1,1) = u(1)**2 + (1-u(1)**2)*cos(th)
1009 r(1,2) = u(1)*u(2)*(1-cos(th)) - u(3)*sin(th)
1010 r(1,3) = u(1)*u(3) + u(2)*sin(th)
1011
1012 r(2,1) = u(1)*u(2)*(1-cos(th)) + u(3)*sin(th)
1013 r(2,2) = u(2)**2 + (1-u(2)**2)*cos(th)
1014 r(2,3) = u(2)*u(3)*(1-cos(th)) - u(1)*sin(th)
1015
1016 r(3,1) = u(1)*u(3)*(1-cos(th)) - u(2)*sin(th)
1017 r(3,2) = u(2)*u(3)*(1-cos(th)) + u(1)*sin(th)
1018 r(3,3) = u(3)**2 + (1-u(3)**2)*cos(th)
1019 end if
1020
1021 if (.false.) then
1022 !Fast
1023 safe_allocate(p(1:dim))
1024
1025 if (abs(f(1)) <= abs(f(2)) .and. abs(f(1)) < abs(f(3))) then
1026 p = (/m_one, m_zero, m_zero/)
1027 else if (abs(f(2)) < abs(f(1)) .and. abs(f(2)) <= abs(f(3))) then
1028 p = (/m_zero, m_one, m_zero/)
1029 else if (abs(f(3)) <= abs(f(1)) .and. abs(f(3)) < abs(f(2))) then
1030 p = (/m_zero, m_zero, m_one/)
1031 end if
1032
1033 u = p - f
1034 v = p - t
1035
1036 uu = dot_product(u,u)
1037 vv = dot_product(v,v)
1038 uv = dot_product(u,v)
1039
1040 do i = 1,3
1041 do j = 1,3
1042
1043 r(i,j) = ddelta(i,j) - m_two * u(i)*u(j)/uu - m_two * v(i)*v(j)/vv &
1044 + 4_real64*uv * v(i)*u(j) /(uu*vv)
1045
1046 end do
1047 end do
1048
1049 safe_deallocate_a(p)
1050 end if
1051
1052
1053 end select
1054
1055 else
1056
1057 r = m_zero
1058 do i = 1,dim
1059 r(i,i) = m_one
1060 end do
1061
1062 end if
1063
1064
1065 safe_deallocate_a(u)
1066 safe_deallocate_a(v)
1067
1069 end subroutine generate_rotation_matrix
1070
1071 ! ---------------------------------------------------------
1080 subroutine numder_ridders(x, h, res, err, f)
1081 implicit none
1082 real(real64), intent(in) :: x, h
1083 real(real64), intent(out) :: res, err
1084 interface
1085 subroutine f(x, fx)
1086 use, intrinsic :: iso_fortran_env
1087 implicit none
1088 real(real64), intent(in) :: x
1089 real(real64), intent(inout) :: fx
1090 end subroutine f
1091 end interface
1092
1093 real(real64), parameter :: con = 1.4_real64, big = 1.0e30_real64, safe = m_two
1094 integer, parameter :: ntab = 20
1095 integer :: i, j
1096 real(real64) :: errt, fac, hh, fx1, fx2
1097 real(real64), allocatable :: a(:, :)
1098
1099 push_sub(numder_ridders)
1100
1101 if (abs(h) <= m_epsilon) then
1102 message(1) = "h must be nonzero in numder_ridders"
1103 call messages_fatal(1)
1104 end if
1105
1106 safe_allocate(a(1:ntab, 1:ntab))
1107
1108 hh = h
1109 call f(x+hh, fx1)
1110 call f(x-hh, fx2)
1111 a(1,1) = (fx1-fx2) / (m_two*hh)
1112 err = big
1113 do i = 2, ntab
1114 hh = hh / con
1115 call f(x+hh, fx1)
1116 call f(x-hh, fx2)
1117 a(1,i) = (fx1-fx2) / (m_two*hh)
1118 fac = con**2
1119 do j = 2, i
1120 a(j,i) = (a(j-1,i)*fac-a(j-1,i-1)) / (fac-m_one)
1121 fac = con**2*fac
1122 errt = max(abs(a(j,i)-a(j-1,i)),abs(a(j,i)-a(j-1,i-1)))
1123 if (errt .le. err) then
1124 err = errt
1125 res = a(j,i)
1126 end if
1127 end do
1128 if (abs(a(i,i)-a(i-1,i-1)) .ge. safe*err) return
1129 end do
1130
1131 safe_deallocate_a(a)
1132 pop_sub(numder_ridders)
1133 end subroutine numder_ridders
1134
1135 ! ---------------------------------------------------------
1136 pure function dzcross_product(a, b) result(c)
1137 real(real64), intent(in) :: a(:)
1138 complex(real64), intent(in) :: b(:)
1139
1140 complex(real64) :: c(1:3)
1141
1142 c(1) = a(2)*b(3) - a(3)*b(2)
1143 c(2) = a(3)*b(1) - a(1)*b(3)
1144 c(3) = a(1)*b(2) - a(2)*b(1)
1145
1146 end function dzcross_product
1147
1148 ! ---------------------------------------------------------
1149 pure function zdcross_product(a, b) result(c)
1150 complex(real64), intent(in) :: a(:)
1151 real(real64), intent(in) :: b(:)
1152
1153 complex(real64) :: c(1:3)
1154
1155 c(1) = a(2)*b(3) - a(3)*b(2)
1156 c(2) = a(3)*b(1) - a(1)*b(3)
1157 c(3) = a(1)*b(2) - a(2)*b(1)
1158
1159 end function zdcross_product
1160
1161
1162!*****************************************************************************80
1163!
1164!! LM_POLYNOMIAL evaluates Laguerre polynomials Lm(n,m,x).
1165!
1166! First terms:
1167!
1168! M = 0
1169!
1170! Lm(0,0,X) = 1
1171! Lm(1,0,X) = -X + 1
1172! Lm(2,0,X) = X^2 - 4 X + 2
1173! Lm(3,0,X) = -X^3 + 9 X^2 - 18 X + 6
1174! Lm(4,0,X) = X^4 - 16 X^3 + 72 X^2 - 96 X + 24
1175! Lm(5,0,X) = -X^5 + 25 X^4 - 200 X^3 + 600 X^2 - 600 x + 120
1176! Lm(6,0,X) = X^6 - 36 X^5 + 450 X^4 - 2400 X^3 + 5400 X^2 - 4320 X + 720
1177!
1178! M = 1
1179!
1180! Lm(0,1,X) = 0
1181! Lm(1,1,X) = -1,
1182! Lm(2,1,X) = 2 X - 4,
1183! Lm(3,1,X) = -3 X^2 + 18 X - 18,
1184! Lm(4,1,X) = 4 X^3 - 48 X^2 + 144 X - 96
1185!
1186! M = 2
1187!
1188! Lm(0,2,X) = 0
1189! Lm(1,2,X) = 0,
1190! Lm(2,2,X) = 2,
1191! Lm(3,2,X) = -6 X + 18,
1192! Lm(4,2,X) = 12 X^2 - 96 X + 144
1193!
1194! M = 3
1195!
1196! Lm(0,3,X) = 0
1197! Lm(1,3,X) = 0,
1198! Lm(2,3,X) = 0,
1199! Lm(3,3,X) = -6,
1200! Lm(4,3,X) = 24 X - 96
1201!
1202! M = 4
1203!
1204! Lm(0,4,X) = 0
1205! Lm(1,4,X) = 0
1206! Lm(2,4,X) = 0
1207! Lm(3,4,X) = 0
1208! Lm(4,4,X) = 24
1209!
1210! Recursion:
1211!
1212! Lm(0,M,X) = 1
1213! Lm(1,M,X) = (M+1-X)
1214!
1215! if 2 <= N:
1216!
1217! Lm(N,M,X) = ( (M+2*N-1-X) * Lm(N-1,M,X)
1218! + (1-M-N) * Lm(N-2,M,X) ) / N
1219!
1220! Special values:
1221!
1222! For M = 0, the associated Laguerre polynomials Lm(N,M,X) are equal
1223! to the Laguerre polynomials L(N,X).
1224!
1225! Licensing:
1226!
1227! This code is distributed under the GNU LGPL license.
1228!
1229! Modified:
1230!
1231! 08 February 2003
1232!
1233! Author:
1234!
1235! John Burkardt
1236!
1237! Reference:
1238!
1239! Milton Abramowitz, Irene Stegun,
1240! Handbook of Mathematical Functions,
1241! National Bureau of Standards, 1964,
1242! ISBN: 0-486-61272-4,
1243! LC: QA47.A34.
1244!
1245! Parameters:
1246!
1247! Input, integer ( kind = 4 ) MM, the number of evaluation points.
1248!
1249! Input, integer ( kind = 4 ) N, the highest order polynomial to compute.
1250! Note that polynomials 0 through N will be computed.
1251!
1252! Input, integer ( kind = 4 ) M, the parameter. M must be nonnegative.
1253!
1254! Input, real ( kind = rk ) X(MM), the evaluation points.
1255!
1256! Output, real ( kind = rk ) CX(MM,0:N), the associated Laguerre polynomials
1257! of degrees 0 through N evaluated at the evaluation points.
1258!
1259! Taken from
1260! https://people.sc.fsu.edu/~jburkardt/f_src/laguerre_polynomial/laguerre_polynomial.html
1261! and adapted to Octopus by N. Tancogne-Dejean
1262 subroutine generalized_laguerre_polynomial ( np, nn, mm, xx, cx )
1263 integer, intent(in) :: np
1264 integer, intent(in) :: nn, mm
1265 real(real64), intent(in) :: xx(np)
1266 real(real64), intent(out) :: cx(np)
1267
1268 integer ii
1269 real(real64), allocatable :: cx_tmp(:,:)
1270
1271 assert(mm >= 0)
1272
1273 safe_allocate(cx_tmp(1:np, 0:nn))
1274
1275 if (nn < 0) then
1276 cx = m_zero
1277 return
1278 end if
1279
1280 if (nn == 0) then
1281 cx(1:np) = m_one
1282 return
1283 end if
1284
1285 cx_tmp(1:np,0) = m_one
1286 cx_tmp(1:np,1) = real(mm + 1, real64) - xx(1:np)
1287
1288 do ii = 2, nn
1289 cx_tmp(1:np, ii) = &
1290 (( real(mm + 2*ii - 1, real64) - xx(1:np)) * cx_tmp(1:np,ii-1) &
1291 + real(-mm -ii + 1, real64) * cx_tmp(1:np,ii-2)) / real(ii, real64)
1292 end do
1293
1294 cx(1:np) = cx_tmp(1:np, nn)
1295
1296 safe_deallocate_a(cx_tmp)
1297
1298 end subroutine generalized_laguerre_polynomial
1299
1300 subroutine dupper_triangular_to_hermitian(nn, aa)
1301 integer, intent(in) :: nn
1302 real(real64), intent(inout) :: aa(:, :)
1303
1304 integer :: ii, jj
1305
1306 do jj = 1, nn
1307 do ii = 1, jj-1
1308 aa(jj, ii) = aa(ii, jj)
1309 end do
1310 end do
1311 end subroutine dupper_triangular_to_hermitian
1312
1313 subroutine zupper_triangular_to_hermitian(nn, aa)
1314 integer, intent(in) :: nn
1315 complex(real64), intent(inout) :: aa(:, :)
1316
1317 integer :: ii, jj
1318
1319 do jj = 1, nn
1320 do ii = 1, jj-1
1321 aa(jj, ii) = conjg(aa(ii, jj))
1322 end do
1323 aa(jj, jj) = real(aa(jj, jj), real64)
1324 end do
1325 end subroutine zupper_triangular_to_hermitian
1326
1327 subroutine dlower_triangular_to_hermitian(nn, aa)
1328 integer, intent(in) :: nn
1329 real(real64), intent(inout) :: aa(:, :)
1330
1331 integer :: ii, jj
1332
1333 do jj = 1, nn
1334 do ii = 1, jj-1
1335 aa(ii, jj) = aa(jj, ii)
1336 end do
1337 end do
1338 end subroutine dlower_triangular_to_hermitian
1339
1340 subroutine zlower_triangular_to_hermitian(nn, aa)
1341 integer, intent(in) :: nn
1342 complex(real64), intent(inout) :: aa(:, :)
1343
1344 integer :: ii, jj
1345
1346 do jj = 1, nn
1347 do ii = 1, jj-1
1348 aa(ii, jj) = conjg(aa(jj, ii))
1349 end do
1350 aa(jj, jj) = real(aa(jj, jj), real64)
1351 end do
1352 end subroutine zlower_triangular_to_hermitian
1353
1354
1355 subroutine dsymmetrize_matrix(nn, aa)
1356 integer, intent(in) :: nn
1357 real(real64), intent(inout) :: aa(:, :)
1358
1359 integer :: ii, jj
1360
1361 do ii = 1, nn
1362 do jj = ii+1, nn
1363 aa(ii, jj) = m_half * (aa(ii, jj) + aa(jj, ii))
1364 aa(jj, ii) = aa(ii, jj)
1365 end do
1366 end do
1367 end subroutine dsymmetrize_matrix
1368
1369 subroutine dzero_small_elements_matrix(nn, aa, tol)
1370 integer, intent(in) :: nn
1371 real(real64), intent(inout) :: aa(:, :)
1372 real(real64) :: tol
1373
1374 where(abs(aa)<tol)
1375 aa = m_zero
1376 end where
1377 end subroutine dzero_small_elements_matrix
1378
1379 ! ---------------------------------------------------------
1381 logical pure function is_diagonal(dim, matrix, tol)
1382 integer, intent(in) :: dim
1383 real(real64), intent(in) :: matrix(:, :)
1384 real(real64), intent(in) :: tol
1385
1386 integer :: ii, jj
1387 real(real64) :: max_diag
1388
1389 max_diag = m_zero
1390 do ii = 1, dim
1391 max_diag = max(abs(matrix(ii, ii)), max_diag)
1392 end do
1394 is_diagonal = .true.
1395 do ii = 1, dim
1396 do jj = 1, dim
1397 if (ii == jj) cycle
1398 if (abs(matrix(ii, jj)) > tol*max_diag) is_diagonal = .false.
1399 end do
1400 end do
1401
1402 end function is_diagonal
1403
1405 subroutine convert_to_base(num, base, converted)
1406 integer, intent(in) :: num
1407 integer, intent(in) :: base
1408 integer, intent(out) :: converted(:)
1409
1410 integer :: i, num_, length
1411
1412 ! no PUSH_SUB, called too often
1413
1414 converted = 0
1415 if (num > 0) then
1416 ! length of converted number
1417 length = floor(log(real(num, real64)) / log(real(base, real64))) + 1
1418 assert(size(converted) >= length)
1419
1420 num_ = num
1421 ! do conversion by repeated division
1422 do i = 1, size(converted)
1423 converted(i) = mod(num_, base)
1424 num_ = num_ / base
1425 end do
1426 end if
1427
1428 end subroutine convert_to_base
1429
1431 subroutine convert_from_base(converted, base, num)
1432 integer, intent(in) :: converted(:)
1433 integer, intent(in) :: base
1434 integer, intent(out) :: num
1435
1436 integer :: i
1437
1438 ! no PUSH_SUB, called too often
1439
1440 num = m_zero
1441 do i = 1, size(converted)
1442 num = num + converted(i) * base**(i-1)
1443 end do
1444
1445 end subroutine convert_from_base
1446
1447
1448#include "undef.F90"
1449#include "complex.F90"
1450#include "math_inc.F90"
1451
1452#include "undef.F90"
1453#include "real.F90"
1454#include "math_inc.F90"
1455
1456end module math_oct_m
1457
1458!! Local Variables:
1459!! mode: f90
1460!! coding: utf-8
1461!! End:
This is the common interface to a simple-minded polynomical interpolation procedure (simple use of th...
Definition: math.F90:189
double acos(double __x) __attribute__((__nothrow__
double log(double __x) __attribute__((__nothrow__
double exp(double __x) __attribute__((__nothrow__
double sin(double __x) __attribute__((__nothrow__
double sqrt(double __x) __attribute__((__nothrow__
double cos(double __x) __attribute__((__nothrow__
double atan2(double __y, double __x) __attribute__((__nothrow__
double floor(double __x) __attribute__((__nothrow__
real(real64), parameter, public m_two
Definition: global.F90:190
real(real64), parameter, public m_zero
Definition: global.F90:188
real(real64), parameter, public m_four
Definition: global.F90:192
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:186
complex(real64), parameter, public m_z0
Definition: global.F90:198
real(real64), parameter, public m_half
Definition: global.F90:194
real(real64), parameter, public m_one
Definition: global.F90:189
real(real64), parameter, public m_three
Definition: global.F90:191
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:115
subroutine, public dsymmetrize_matrix(nn, aa)
Definition: math.F90:1449
complex(real64) pure function, public phi2(z)
Compute phi2(z) = (phi1(z)-1)/z = (exp(z) - z - 1)/z^2.
Definition: math.F90:973
integer pure function ilog2(xx)
Definition: math.F90:926
logical pure function, public even(n)
Returns if n is even.
Definition: math.F90:692
pure real(real64) function, dimension(dim, dim) ddiagonal_matrix(dim, diag)
Currently only returns a matrix whose diagonal elements are all the same. Note that the integer versi...
Definition: math.F90:1803
subroutine, public generalized_laguerre_polynomial(np, nn, mm, xx, cx)
Definition: math.F90:1356
complex(real64) pure function, public exponential(z)
Wrapper for exponential.
Definition: math.F90:942
subroutine dinterpolate_0(xa, ya, x, y)
Definition: math.F90:1881
subroutine, public ylmr_cmplx(xx, li, mi, ylm)
Computes spherical harmonics ylm at position (x, y, z)
Definition: math.F90:304
subroutine zinterpolate_0(xa, ya, x, y)
Definition: math.F90:1690
subroutine, public convert_to_base(num, base, converted)
convert an integer in base 10 to a different base
Definition: math.F90:1499
subroutine dinterpolate_1(xa, ya, x, y)
Definition: math.F90:1853
real(real64) pure function dlog2(xx)
Definition: math.F90:918
integer(int64) pure function pad88(size, blk)
Definition: math.F90:845
real(real64) pure function, public square_root(x)
Wrapper for sqrt.
Definition: math.F90:987
logical function, public member(n, a)
Considers a(1:ubound(a, 1)) as an integer set and checks if n is a member of it.
Definition: math.F90:648
integer pure function pad4(size, blk)
Definition: math.F90:876
subroutine dlower_triangular_to_hermitian(nn, aa)
Definition: math.F90:1421
pure complex(real64) function, dimension(1:3), public dzcross_product(a, b)
Definition: math.F90:1230
subroutine, public cartesian2hyperspherical(x, u)
Performs a transformation of an n-dimensional vector from Cartesian coordinates to hyperspherical coo...
Definition: math.F90:712
integer pure function, public pad_pow2(size)
create array size, which is padded to powers of 2
Definition: math.F90:889
subroutine zinterpolate_1(xa, ya, x, y)
Definition: math.F90:1662
pure real(real64) function, dimension(1:3), public dcross_product(a, b)
Definition: math.F90:1906
integer(int64) pure function pad48(size, blk)
Definition: math.F90:860
subroutine, public ylmr_real(xx, li, mi, ylm)
This is a Numerical Recipes-based subroutine computes real spherical harmonics ylm at position (x,...
Definition: math.F90:375
subroutine dupper_triangular_to_hermitian(nn, aa)
Definition: math.F90:1394
subroutine, public interpolation_coefficients(nn, xa, xx, cc)
Definition: math.F90:669
subroutine, public generate_rotation_matrix(R, ff, tt)
Generates a rotation matrix R to rotate a vector f to t.
Definition: math.F90:1030
elemental logical function zis_close_scalar(x, y, rtol, atol)
Same as dis_close_scalar for complex numbers.
Definition: math.F90:237
logical pure function, public odd(n)
Returns if n is odd.
Definition: math.F90:702
real(real64) pure function, public ddelta(i, j)
Definition: math.F90:601
subroutine, public make_idx_set(n, out, length, in)
Construct out(1:length) = (/1, ..., n/) if in is not present, out(1:length) = in otherwise.
Definition: math.F90:619
logical function, public is_prime(n)
Definition: math.F90:995
complex(real64) pure function, public phi1(z)
Compute phi1(z) = (exp(z)-1)/z.
Definition: math.F90:954
pure complex(real64) function, dimension(1:3), public zcross_product(a, b)
Definition: math.F90:1715
subroutine, public weights(N, M, cc, side)
Compute the weights for finite-difference calculations:
Definition: math.F90:525
subroutine zinterpolate_2(xa, ya, x, y)
Definition: math.F90:1627
pure complex(real64) function, dimension(dim, dim) zdiagonal_matrix(dim, diag)
Currently only returns a matrix whose diagonal elements are all the same. Note that the integer versi...
Definition: math.F90:1612
subroutine zlower_triangular_to_hermitian(nn, aa)
Definition: math.F90:1434
logical pure function, public is_diagonal(dim, matrix, tol)
Returns true is the matrix of size dim x dim is diagonal, given a relative tolerance.
Definition: math.F90:1475
subroutine zupper_triangular_to_hermitian(nn, aa)
Definition: math.F90:1407
pure integer function, dimension(dim, dim) idiagonal_matrix(dim, diag)
Currently only returns a matrix whose diagonal elements are all the same. Note that the real and comp...
Definition: math.F90:253
integer(int64) pure function pad8(size, blk)
Definition: math.F90:868
subroutine dinterpolate_2(xa, ya, x, y)
Definition: math.F90:1818
subroutine, public numder_ridders(x, h, res, err, f)
Numerical derivative (Ridder`s algorithm).
Definition: math.F90:1174
integer(int64) pure function llog2(xx)
Definition: math.F90:934
recursive real(real64) function, public hermite(n, x)
Definition: math.F90:268
elemental logical function dis_close_scalar(x, y, rtol, atol)
Are and equal within a tolerance.
Definition: math.F90:224
pure complex(real64) function, dimension(1:3), public zdcross_product(a, b)
Definition: math.F90:1243
subroutine, public convert_from_base(converted, base, num)
convert an integer to base 10 from a different base
Definition: math.F90:1525
subroutine, public hyperspherical2cartesian(u, x)
Performs the inverse transformation of cartesian2hyperspherical.
Definition: math.F90:759
subroutine, public dzero_small_elements_matrix(nn, aa, tol)
Definition: math.F90:1463
subroutine, public hypersphere_grad_matrix(grad_matrix, r, x)
Gives the hyperspherical gradient matrix, which contains the derivatives of the Cartesian coordinates...
Definition: math.F90:805
recursive integer function, public factorial(n)
Definition: math.F90:288
static double f(double w, void *p)
int true(void)