Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
math.F90
Go to the documentation of this file.
1! Copyright (c) 2008-2020, UCHICAGO ARGONNE, LLC.
2!
3! The UChicago Argonne, LLC as Operator of Argonne National
4! Laboratory holds copyright in the Software. The copyright holder
5! reserves all rights except those expressly granted to licensees,
6! and U.S. Government license rights.
7!
8! Redistribution and use in source and binary forms, with or without
9! modification, are permitted provided that the following conditions
10! are met:
11!
12! 1. Redistributions of source code must retain the above copyright
13! notice, this list of conditions and the disclaimer below.
14!
15! 2. Redistributions in binary form must reproduce the above copyright
16! notice, this list of conditions and the disclaimer (as noted below)
17! in the documentation and/or other materials provided with the
18! distribution.
19!
20! 3. Neither the name of ANL nor the names of its contributors
21! may be used to endorse or promote products derived from this software
22! without specific prior written permission.
23!
24! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
28! UCHICAGO ARGONNE, LLC, THE U.S. DEPARTMENT OF
29! ENERGY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
31! TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32! DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33! THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34! (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35! OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36!
37! Additional BSD Notice
38! ---------------------
39! 1. This notice is required to be provided under our contract with
40! the U.S. Department of Energy (DOE). This work was produced at
41! Argonne National Laboratory under Contract
42! No. DE-AC02-06CH11357 with the DOE.
43!
44! 2. Neither the United States Government nor UCHICAGO ARGONNE,
45! LLC nor any of their employees, makes any warranty,
46! express or implied, or assumes any liability or responsibility for the
47! accuracy, completeness, or usefulness of any information, apparatus,
48! product, or process disclosed, or represents that its use would not
49! infringe privately-owned rights.
50!
51! 3. Also, reference herein to any specific commercial products, process,
52! or services by trade name, trademark, manufacturer or otherwise does
53! not necessarily constitute or imply its endorsement, recommendation,
54! or favoring by the United States Government or UCHICAGO ARGONNE LLC.
55! The views and opinions of authors expressed
56! herein do not necessarily state or reflect those of the United States
57! Government or UCHICAGO ARGONNE, LLC, and shall
58! not be used for advertising or product endorsement purposes.
59!
60module math
61 use num_types, only : rp, dp, sp, qp, i4, xp
63 use mpi_f08, only : mpi_min, mpi_max, mpi_sum, mpi_in_place, mpi_integer, &
64 mpi_allreduce
65 use utils, only : nonlinear_index
66 implicit none
67 private
68
70 real(kind=rp), public, parameter :: neko_eps = epsilon(1.0_rp)
71 real(kind=dp), public, parameter :: neko_eps_dp = epsilon(1.0_dp)
72 real(kind=sp), public, parameter :: neko_eps_sp = epsilon(1.0_sp)
73
75 real(kind=rp), public, parameter :: neko_m_ln2 = log(2.0_rp)
76
78 real(kind=rp), public, parameter :: pi = 4._rp*atan(1._rp)
79
80 interface abscmp
81 module procedure sabscmp, dabscmp
82#ifdef HAVE_REAL128
83 module procedure qabscmp
84#endif
85 end interface abscmp
86
87 interface sort
88 module procedure sortrp, sorti4
89 end interface sort
90
91 interface swap
92 module procedure swapdp, swapi4
93 end interface swap
94
95 interface reord
96 module procedure reorddp, reordi4
97 end interface reord
98
99 interface flipv
100 module procedure flipvdp, flipvi4
101 end interface flipv
102
103 interface relcmp
104 module procedure srelcmp, drelcmp
105#ifdef HAVE_REAL128
106 module procedure qrelcmp
107#endif
108 end interface relcmp
109
110 public :: abscmp, rzero, izero, row_zero, rone, copy, cmult, cadd, cfill, &
119 matinv39, &
125
126contains
127
129 pure function sabscmp(x, y, tol)
130 real(kind=sp), intent(in) :: x
131 real(kind=sp), intent(in) :: y
132 real(kind=sp), intent(in), optional :: tol
133 logical :: sabscmp
134
135 if (present(tol)) then
136 sabscmp = abs(x - y) .lt. tol
137 else
138 sabscmp = abs(x - y) .lt. neko_eps
139 end if
140
141 end function sabscmp
142
144 pure function dabscmp(x, y, tol)
145 real(kind=dp), intent(in) :: x
146 real(kind=dp), intent(in) :: y
147 real(kind=dp), intent(in), optional :: tol
148 logical :: dabscmp
149
150 if (present(tol)) then
151 dabscmp = abs(x - y) .lt. tol
152 else
153 dabscmp = abs(x - y) .lt. neko_eps
154 end if
155
156 end function dabscmp
157
158#ifdef HAVE_REAL128
159
160 pure function qabscmp(x, y, tol)
161 real(kind=qp), intent(in) :: x
162 real(kind=qp), intent(in) :: y
163 real(kind=qp), intent(in), optional :: tol
164 logical :: qabscmp
165
166 if (present(tol)) then
167 qabscmp = abs(x - y) .lt. tol
168 else
169 qabscmp = abs(x - y) .lt. neko_eps
170 end if
171
172 end function qabscmp
173#endif
174
177 pure function srelcmp(x, y, eps)
178 real(kind=sp), intent(in) :: x
179 real(kind=sp), intent(in) :: y
180 real(kind=sp), intent(in), optional :: eps
181 logical :: srelcmp
182 if (present(eps)) then
183 srelcmp = abs(x - y) .le. eps*abs(y)
184 else
185 srelcmp = abs(x - y) .le. neko_eps*abs(y)
186 end if
187
188 end function srelcmp
189
192 pure function drelcmp(x, y, eps)
193 real(kind=dp), intent(in) :: x
194 real(kind=dp), intent(in) :: y
195 real(kind=dp), intent(in), optional :: eps
196 logical :: drelcmp
197 if (present(eps)) then
198 drelcmp = abs(x - y) .le. eps*abs(y)
199 else
200 drelcmp = abs(x - y) .le. neko_eps*abs(y)
201 end if
202
203 end function drelcmp
204
205
206#ifdef HAVE_REAL128
207
208 pure function qrelcmp(x, y, eps)
209 real(kind=qp), intent(in) :: x
210 real(kind=qp), intent(in) :: y
211 real(kind=qp), intent(in), optional :: eps
212 logical :: qrelcmp
213 if (present(eps)) then
214 qrelcmp = abs(x - y)/abs(y) .lt. eps
215 else
216 qrelcmp = abs(x - y)/abs(y) .lt. neko_eps
217 end if
218
219 end function qrelcmp
220#endif
221
227 pure function lambert_w0(x, niter) result(w)
228 real(kind=rp), intent(in) :: x
229 integer, intent(in) :: niter
230 real(kind=rp) :: w
231 real(kind=rp) :: a
232 integer :: k
233
234 if (x == 0.0_rp) then
235 w = 0.0_rp
236 return
237 end if
238
239 a = 1.0_rp / (1.0_rp + 0.5_rp * log(1.0_rp + x))
240 w = log(1.0_rp + a * x)
241
242 do k = 1, max(niter, 0)
243 w = w / (1.0_rp + w) * (1.0_rp + log(x / w))
244 end do
245 end function lambert_w0
246
248 subroutine rzero(a, n)
249 integer, intent(in) :: n
250 real(kind=rp), dimension(n), intent(inout) :: a
251 integer :: i
252
253 !$omp parallel do
254 do i = 1, n
255 a(i) = 0.0_rp
256 end do
257 !$omp end parallel do
258
259 end subroutine rzero
260
262 subroutine izero(a, n)
263 integer, intent(in) :: n
264 integer, dimension(n), intent(inout) :: a
265 integer :: i
266
267 !$omp parallel do
268 do i = 1, n
269 a(i) = 0
270 end do
271 !$omp end parallel do
272
273 end subroutine izero
274
276 subroutine row_zero(a, m, n, e)
277 integer, intent(in) :: m, n, e
278 real(kind=rp), intent(inout) :: a(m,n)
279 integer :: j
280
281 !$omp parallel do
282 do j = 1, n
283 a(e,j) = 0.0_rp
284 end do
285 !$omp end parallel do
286
287 end subroutine row_zero
288
290 subroutine rone(a, n)
291 integer, intent(in) :: n
292 real(kind=rp), dimension(n), intent(inout) :: a
293 integer :: i
294
295 !$omp parallel do
296 do i = 1, n
297 a(i) = 1.0_rp
298 end do
299 !$omp end parallel do
300
301 end subroutine rone
302
304 subroutine copy(a, b, n)
305 integer, intent(in) :: n
306 real(kind=rp), dimension(n), intent(in) :: b
307 real(kind=rp), dimension(n), intent(inout) :: a
308 integer :: i
309
310 !$omp parallel do
311 do i = 1, n
312 a(i) = b(i)
313 end do
314 !$omp end parallel do
315
316 end subroutine copy
317
325 subroutine masked_copy_0(a, b, mask, n, n_mask)
326 integer, intent(in) :: n, n_mask
327 real(kind=rp), dimension(n), intent(in) :: b
328 real(kind=rp), dimension(n), intent(inout) :: a
329 integer, dimension(0:n_mask) :: mask
330 integer :: i, j
331
332 !$omp parallel do private(i, j)
333 do i = 1, n_mask
334 j = mask(i)
335 a(j) = b(j)
336 end do
337 !$omp end parallel do
338
339 end subroutine masked_copy_0
340
348 subroutine masked_copy(a, b, mask, n, n_mask)
349 integer, intent(in) :: n, n_mask
350 real(kind=rp), dimension(n), intent(in) :: b
351 real(kind=rp), dimension(n), intent(inout) :: a
352 integer, dimension(n_mask) :: mask
353 integer :: i, j
354
355 !$omp parallel do private(i, j)
356 do i = 1, n_mask
357 j = mask(i)
358 a(j) = b(j)
359 end do
360 !$omp end parallel do
361
362 end subroutine masked_copy
363
373 subroutine masked_gather_copy_0(a, b, mask, n, n_mask)
374 integer, intent(in) :: n, n_mask
375 real(kind=rp), dimension(n), intent(in) :: b
376 real(kind=rp), dimension(n_mask), intent(inout) :: a
377 integer, dimension(0:n_mask) :: mask
378 integer :: i, j
379
380 !$omp parallel do private(i, j)
381 do i = 1, n_mask
382 j = mask(i)
383 a(i) = b(j)
384 end do
385 !$omp end parallel do
386
387 end subroutine masked_gather_copy_0
388
398 subroutine face_masked_gather_copy_0(a, b, mask, facet, lx, ly, lz, n_mask)
399 integer, intent(in) :: lx, ly, lz, n_mask
400 real(kind=rp), dimension(n_mask), intent(inout) :: a
401 real(kind=rp), dimension(:, :, :, :), intent(in) :: b
402 integer, dimension(0:n_mask), intent(in) :: mask
403 integer, dimension(0:n_mask), intent(in) :: facet
404 integer :: l
405 integer :: idx(4)
406
407 !$omp parallel do private(l, idx)
408 do l = 1, n_mask
409 idx = nonlinear_index(mask(l), lx, ly, lz)
410
411 select case (facet(l))
412 case (1, 2)
413 a(l) = b(idx(2), idx(3), facet(l), idx(4))
414 case (3, 4)
415 a(l) = b(idx(1), idx(3), facet(l), idx(4))
416 case (5, 6)
417 a(l) = b(idx(1), idx(2), facet(l), idx(4))
418 end select
419 end do
420 !$omp end parallel do
421
422 end subroutine face_masked_gather_copy_0
423
433 subroutine masked_gather_copy(a, b, mask, n, n_mask)
434 integer, intent(in) :: n, n_mask
435 real(kind=rp), dimension(n), intent(in) :: b
436 real(kind=rp), dimension(n_mask), intent(inout) :: a
437 integer, dimension(n_mask) :: mask
438 integer :: i, j
439
440 !$omp parallel do private(i, j)
441 do i = 1, n_mask
442 j = mask(i)
443 a(i) = b(j)
444 end do
445 !$omp end parallel do
446
447 end subroutine masked_gather_copy
448
458 subroutine masked_scatter_copy_0(a, b, mask, n, n_mask)
459 integer, intent(in) :: n, n_mask
460 real(kind=rp), dimension(n_mask), intent(in) :: b
461 real(kind=rp), dimension(n), intent(inout) :: a
462 integer, dimension(0:n_mask) :: mask
463 integer :: i, j
464
465 !$omp parallel do private(i, j)
466 do i = 1, n_mask
467 j = mask(i)
468 a(j) = b(i)
469 end do
470 !$omp end parallel do
471
472 end subroutine masked_scatter_copy_0
473
483 subroutine masked_scatter_copy(a, b, mask, n, n_mask)
484 integer, intent(in) :: n, n_mask
485 real(kind=rp), dimension(n_mask), intent(in) :: b
486 real(kind=rp), dimension(n), intent(inout) :: a
487 integer, dimension(n_mask) :: mask
488 integer :: i, j
489
490 !$omp parallel do private(i, j)
491 do i = 1, n_mask
492 j = mask(i)
493 a(j) = b(i)
494 end do
495 !$omp end parallel do
496
497 end subroutine masked_scatter_copy
498
501 subroutine cfill_mask(a, c, n, mask, n_mask)
502 integer, intent(in) :: n, n_mask
503 real(kind=rp), dimension(n), intent(inout) :: a
504 real(kind=rp), intent(in) :: c
505 integer, dimension(n_mask), intent(in) :: mask
506 integer :: i
507
508 !$omp parallel do
509 do i = 1, n_mask
510 a(mask(i)) = c
511 end do
512 !$omp end parallel do
513
514 end subroutine cfill_mask
515
517 subroutine cmult(a, c, n)
518 integer, intent(in) :: n
519 real(kind=rp), dimension(n), intent(inout) :: a
520 real(kind=rp), intent(in) :: c
521 integer :: i
522
523 !$omp parallel do
524 do i = 1, n
525 a(i) = c * a(i)
526 end do
527 !$omp end parallel do
528
529 end subroutine cmult
530
532 subroutine cmult2(a, b, c, n)
533 integer, intent(in) :: n
534 real(kind=rp), dimension(n), intent(inout) :: a
535 real(kind=rp), dimension(n), intent(in) :: b
536 real(kind=rp), intent(in) :: c
537 integer :: i
538
539 !$omp parallel do
540 do i = 1, n
541 a(i) = c * b(i)
542 end do
543 !$omp end parallel do
544
545 end subroutine cmult2
546
548 subroutine cdiv(a, c, n)
549 integer, intent(in) :: n
550 real(kind=rp), dimension(n), intent(inout) :: a
551 real(kind=rp), intent(in) :: c
552 integer :: i
553
554 !$omp parallel do
555 do i = 1, n
556 a(i) = c / a(i)
557 end do
558 !$omp end parallel do
559
560 end subroutine cdiv
561
563 subroutine cdiv2(a, b, c, n)
564 integer, intent(in) :: n
565 real(kind=rp), dimension(n), intent(inout) :: a
566 real(kind=rp), dimension(n), intent(in) :: b
567 real(kind=rp), intent(in) :: c
568 integer :: i
569
570 !$omp parallel do
571 do i = 1, n
572 a(i) = c / b(i)
573 end do
574 !$omp end parallel do
575
576 end subroutine cdiv2
577
579 subroutine cadd(a, s, n)
580 integer, intent(in) :: n
581 real(kind=rp), dimension(n), intent(inout) :: a
582 real(kind=rp), intent(in) :: s
583 integer :: i
584
585 !$omp parallel do
586 do i = 1, n
587 a(i) = a(i) + s
588 end do
589 !$omp end parallel do
590
591 end subroutine cadd
592
594 subroutine cadd2(a, b, s, n)
595 integer, intent(in) :: n
596 real(kind=rp), dimension(n), intent(inout) :: a
597 real(kind=rp), dimension(n), intent(in) :: b
598 real(kind=rp), intent(in) :: s
599 integer :: i
600
601 !$omp parallel do
602 do i = 1,n
603 a(i) = b(i) + s
604 end do
605 !$omp end parallel do
606
607 end subroutine cadd2
608
610 subroutine cfill(a, c, n)
611 integer, intent(in) :: n
612 real(kind=rp), dimension(n), intent(inout) :: a
613 real(kind=rp), intent(in) :: c
614 integer :: i
615
616 !$omp parallel do
617 do i = 1, n
618 a(i) = c
619 end do
620 !$omp end parallel do
621
622 end subroutine cfill
623
625 subroutine cwrap(a, min_val, max_val, n)
626 integer, intent(in) :: n
627 real(kind=rp), dimension(n), intent(inout) :: a
628 real(kind=rp), intent(in) :: min_val, max_val
629 integer :: i
630
631 if (n .lt. 1 .or. max_val .le. min_val) return
632
633 !$omp parallel do
634 do i = 1, n
635 a(i) = modulo(a(i) - min_val, max_val - min_val) + min_val
636 end do
637 !$omp end parallel do
638
639 end subroutine cwrap
640
642 function glsum(a, n)
643 integer, intent(in) :: n
644 real(kind=rp), dimension(n) :: a
645 real(kind=rp) :: glsum
646 real(kind=xp) :: tmp
647 integer :: i, ierr
648
649 tmp = 0.0_rp
650 !$omp parallel do reduction(+:tmp)
651 do i = 1, n
652 tmp = tmp + a(i)
653 end do
654 !$omp end parallel do
655
656 call mpi_allreduce(mpi_in_place, tmp, 1, &
657 mpi_extra_precision, mpi_sum, neko_comm, ierr)
658 glsum = tmp
659
660 end function glsum
661
663 function glmax(a, n)
664 integer, intent(in) :: n
665 real(kind=rp), dimension(n) :: a
666 real(kind=rp) :: tmp, glmax
667 integer :: i, ierr
668
669 tmp = -huge(0.0_rp)
670 !$omp parallel do reduction(max:tmp)
671 do i = 1, n
672 tmp = max(tmp,a(i))
673 end do
674 !$omp end parallel do
675
676 call mpi_allreduce(tmp, glmax, 1, &
677 mpi_real_precision, mpi_max, neko_comm, ierr)
678
679 end function glmax
680
683 function glamax(a, n)
684 integer, intent(in) :: n
685 real(kind=rp), dimension(n) :: a
686 real(kind=rp) :: tmp, glamax
687 integer :: i, ierr
688
689 tmp = 0.0_rp
690 !$omp parallel do reduction(max:tmp)
691 do i = 1, n
692 tmp = max(tmp, abs(a(i)))
693 end do
694 !$omp end parallel do
695
696 call mpi_allreduce(tmp, glamax, 1, &
697 mpi_real_precision, mpi_max, neko_comm, ierr)
698
699 end function glamax
700
702 function glimax(a, n)
703 integer, intent(in) :: n
704 integer, dimension(n) :: a
705 integer :: tmp, glimax
706 integer :: i, ierr
707
708 tmp = -huge(0)
709 !$omp parallel do reduction(max:tmp)
710 do i = 1, n
711 tmp = max(tmp,a(i))
712 end do
713 !$omp end parallel do
714
715 call mpi_allreduce(tmp, glimax, 1, &
716 mpi_integer, mpi_max, neko_comm, ierr)
717
718 end function glimax
719
721 function glmin(a, n)
722 integer, intent(in) :: n
723 real(kind=rp), dimension(n) :: a
724 real(kind=rp) :: tmp, glmin
725 integer :: i, ierr
726
727 tmp = huge(0.0_rp)
728 !$omp parallel do reduction(min:tmp)
729 do i = 1, n
730 tmp = min(tmp,a(i))
731 end do
732 !$omp end parallel do
733
734 call mpi_allreduce(tmp, glmin, 1, &
735 mpi_real_precision, mpi_min, neko_comm, ierr)
736
737 end function glmin
738
740 function glimin(a, n)
741 integer, intent(in) :: n
742 integer, dimension(n) :: a
743 integer :: tmp, glimin
744 integer :: i, ierr
745
746 tmp = huge(0)
747 !$omp parallel do reduction(min:tmp)
748 do i = 1, n
749 tmp = min(tmp,a(i))
750 end do
751 !$omp end parallel do
752
753 call mpi_allreduce(tmp, glimin, 1, &
754 mpi_integer, mpi_min, neko_comm, ierr)
755
756 end function glimin
757
759 subroutine chsign(a, n)
760 integer, intent(in) :: n
761 real(kind=rp), dimension(n), intent(inout) :: a
762 integer :: i
763
764 !$omp parallel do
765 do i = 1, n
766 a(i) = -a(i)
767 end do
768 !$omp end parallel do
769
770 end subroutine chsign
771
773 function vlamax(vec,n) result(tamax)
774 integer :: n, i
775 real(kind=rp), intent(in) :: vec(n)
776 real(kind=rp) :: tamax
777
778 tamax = 0.0_rp
779 !$omp parallel do reduction(max:tamax)
780 do i = 1, n
781 tamax = max(tamax, abs(vec(i)))
782 end do
783 !$omp end parallel do
784
785 end function vlamax
786
788 function vlmax(vec,n) result(tmax)
789 integer :: n, i
790 real(kind=rp), intent(in) :: vec(n)
791 real(kind=rp) :: tmax
792
793 tmax = real(-99d20, rp)
794 !$omp parallel do reduction(max:tmax)
795 do i = 1, n
796 tmax = max(tmax, vec(i))
797 end do
798 !$omp end parallel do
799
800 end function vlmax
801
803 function vlmin(vec,n) result(tmin)
804 integer, intent(in) :: n
805 real(kind=rp), intent(in) :: vec(n)
806 real(kind=rp) :: tmin
807 integer :: i
808
809 tmin = real(99.0e20, rp)
810 !$omp parallel do reduction(min:tmin)
811 do i = 1, n
812 tmin = min(tmin, vec(i))
813 end do
814 !$omp end parallel do
815
816 end function vlmin
817
819 subroutine invcol1(a, n)
820 integer, intent(in) :: n
821 real(kind=rp), dimension(n), intent(inout) :: a
822 integer :: i
823
824 !$omp parallel do
825 do i = 1, n
826 a(i) = 1.0_xp / real(a(i), xp)
827 end do
828 !$omp end parallel do
829
830 end subroutine invcol1
831
833 subroutine invcol3(a, b, c, n)
834 integer, intent(in) :: n
835 real(kind=rp), dimension(n), intent(inout) :: a
836 real(kind=rp), dimension(n), intent(in) :: b, c
837 integer :: i
838
839 !$omp parallel do
840 do i = 1, n
841 a(i) = real(b(i), xp) / c(i)
842 end do
843 !$omp end parallel do
844
845 end subroutine invcol3
846
848 subroutine invers2(a, b, n)
849 integer, intent(in) :: n
850 real(kind=rp), dimension(n), intent(inout) :: a
851 real(kind=rp), dimension(n), intent(in) :: b
852 integer :: i
853
854 !$omp parallel do
855 do i = 1, n
856 a(i) = 1.0_xp / real(b(i), xp)
857 end do
858 !$omp end parallel do
859
860 end subroutine invers2
861
864 subroutine vcross(u1, u2, u3, v1, v2, v3, w1, w2, w3, n)
865 integer, intent(in) :: n
866 real(kind=rp), dimension(n), intent(in) :: v1, v2, v3
867 real(kind=rp), dimension(n), intent(in) :: w1, w2, w3
868 real(kind=rp), dimension(n), intent(out) :: u1, u2, u3
869 integer :: i
870
871 !$omp parallel do
872 do i = 1, n
873 u1(i) = v2(i)*w3(i) - v3(i)*w2(i)
874 u2(i) = v3(i)*w1(i) - v1(i)*w3(i)
875 u3(i) = v1(i)*w2(i) - v2(i)*w1(i)
876 end do
877 !$omp end parallel do
878
879 end subroutine vcross
880
883 subroutine vdot2(dot, u1, u2, v1, v2, n)
884 integer, intent(in) :: n
885 real(kind=rp), dimension(n), intent(in) :: u1, u2
886 real(kind=rp), dimension(n), intent(in) :: v1, v2
887 real(kind=rp), dimension(n), intent(out) :: dot
888 integer :: i
889
890 !$omp parallel do
891 do i = 1, n
892 dot(i) = u1(i)*v1(i) + u2(i)*v2(i)
893 end do
894 !$omp end parallel do
895
896 end subroutine vdot2
897
900 subroutine vdot3(dot, u1, u2, u3, v1, v2, v3, n)
901 integer, intent(in) :: n
902 real(kind=rp), dimension(n), intent(in) :: u1, u2, u3
903 real(kind=rp), dimension(n), intent(in) :: v1, v2, v3
904 real(kind=rp), dimension(n), intent(out) :: dot
905 integer :: i
906
907 !$omp parallel do
908 do i = 1, n
909 dot(i) = u1(i)*v1(i) + u2(i)*v2(i) + u3(i)*v3(i)
910 end do
911 !$omp end parallel do
912
913 end subroutine vdot3
914
916 function vlsc3(u, v, w, n) result(s)
917 integer, intent(in) :: n
918 real(kind=rp), dimension(n), intent(in) :: u, v, w
919 real(kind=rp) :: s
920 integer :: i
921
922 s = 0.0_rp
923 !$omp parallel do reduction(+:s)
924 do i = 1, n
925 s = s + u(i)*v(i)*w(i)
926 end do
927 !$omp end parallel do
928
929 end function vlsc3
930
932 function vlsc2(u, v, n) result(s)
933 integer, intent(in) :: n
934 real(kind=rp), dimension(n), intent(in) :: u, v
935 real(kind=rp) :: s
936 integer :: i
937
938 s = 0.0_rp
939 !$omp parallel do reduction(+:s)
940 do i = 1, n
941 s = s + u(i)*v(i)
942 end do
943 !$omp end parallel do
944
945 end function vlsc2
946
948 subroutine add2(a, b, n)
949 integer, intent(in) :: n
950 real(kind=rp), dimension(n), intent(inout) :: a
951 real(kind=rp), dimension(n), intent(in) :: b
952 integer :: i
953
954 !$omp parallel do
955 do i = 1, n
956 a(i) = a(i) + b(i)
957 end do
958 !$omp end parallel do
959
960 end subroutine add2
961
963 subroutine add3(a, b, c, n)
964 integer, intent(in) :: n
965 real(kind=rp), dimension(n), intent(inout) :: a
966 real(kind=rp), dimension(n), intent(in) :: b
967 real(kind=rp), dimension(n), intent(in) :: c
968 integer :: i
969
970 !$omp parallel do
971 do i = 1, n
972 a(i) = b(i) + c(i)
973 end do
974 !$omp end parallel do
975
976 end subroutine add3
977
979 subroutine add4(a, b, c, d, n)
980 integer, intent(in) :: n
981 real(kind=rp), dimension(n), intent(out) :: a
982 real(kind=rp), dimension(n), intent(in) :: d
983 real(kind=rp), dimension(n), intent(in) :: c
984 real(kind=rp), dimension(n), intent(in) :: b
985 integer :: i
986
987 !$omp parallel do
988 do i = 1, n
989 a(i) = b(i) + c(i) + d(i)
990 end do
991 !$omp end parallel do
992
993 end subroutine add4
994
996 subroutine sub2(a, b, n)
997 integer, intent(in) :: n
998 real(kind=rp), dimension(n), intent(inout) :: a
999 real(kind=rp), dimension(n), intent(in) :: b
1000 integer :: i
1001
1002 !$omp parallel do
1003 do i = 1, n
1004 a(i) = a(i) - b(i)
1005 end do
1006 !$omp end parallel do
1007
1008 end subroutine sub2
1009
1011 subroutine sub3(a, b, c, n)
1012 integer, intent(in) :: n
1013 real(kind=rp), dimension(n), intent(inout) :: a
1014 real(kind=rp), dimension(n), intent(in) :: b
1015 real(kind=rp), dimension(n), intent(in) :: c
1016 integer :: i
1017
1018 !$omp parallel do
1019 do i = 1, n
1020 a(i) = b(i) - c(i)
1021 end do
1022 !$omp end parallel do
1023
1024 end subroutine sub3
1025
1026
1029 subroutine add2s1(a, b, c1, n)
1030 integer, intent(in) :: n
1031 real(kind=rp), dimension(n), intent(inout) :: a
1032 real(kind=rp), dimension(n), intent(in) :: b
1033 real(kind=rp), intent(in) :: c1
1034 integer :: i
1035
1036 !$omp parallel do
1037 do i = 1, n
1038 a(i) = c1 * a(i) + b(i)
1039 end do
1040 !$omp end parallel do
1041
1042 end subroutine add2s1
1043
1046 subroutine add2s2(a, b, c1, n)
1047 integer, intent(in) :: n
1048 real(kind=rp), dimension(n), intent(inout) :: a
1049 real(kind=rp), dimension(n), intent(in) :: b
1050 real(kind=rp), intent(in) :: c1
1051 integer :: i
1052
1053 !$omp parallel do
1054 do i = 1, n
1055 a(i) = a(i) + c1 * b(i)
1056 end do
1057 !$omp end parallel do
1058
1059 end subroutine add2s2
1060
1062 subroutine addsqr2s2(a, b, c1, n)
1063 integer, intent(in) :: n
1064 real(kind=rp), dimension(n), intent(inout) :: a
1065 real(kind=rp), dimension(n), intent(in) :: b
1066 real(kind=rp), intent(in) :: c1
1067 integer :: i
1068
1069 !$omp parallel do
1070 do i = 1, n
1071 a(i) = a(i) + c1 * ( b(i) * b(i) )
1072 end do
1073 !$omp end parallel do
1074
1075 end subroutine addsqr2s2
1076
1078 subroutine invcol2(a, b, n)
1079 integer, intent(in) :: n
1080 real(kind=rp), dimension(n), intent(inout) :: a
1081 real(kind=rp), dimension(n), intent(in) :: b
1082 integer :: i
1083
1084 !$omp parallel do
1085 do i = 1, n
1086 a(i) = real(a(i), xp) / b(i)
1087 end do
1088 !$omp end parallel do
1089
1090 end subroutine invcol2
1091
1092
1094 subroutine col2(a, b, n)
1095 integer, intent(in) :: n
1096 real(kind=rp), dimension(n), intent(inout) :: a
1097 real(kind=rp), dimension(n), intent(in) :: b
1098 integer :: i
1099
1100 !$omp parallel do
1101 do i = 1, n
1102 a(i) = a(i) * b(i)
1103 end do
1104 !$omp end parallel do
1105
1106 end subroutine col2
1107
1109 subroutine col3(a, b, c, n)
1110 integer, intent(in) :: n
1111 real(kind=rp), dimension(n), intent(inout) :: a
1112 real(kind=rp), dimension(n), intent(in) :: b
1113 real(kind=rp), dimension(n), intent(in) :: c
1114 integer :: i
1115
1116 !$omp parallel do
1117 do i = 1, n
1118 a(i) = b(i) * c(i)
1119 end do
1120 !$omp end parallel do
1121
1122 end subroutine col3
1123
1125 subroutine subcol3(a, b, c, n)
1126 integer, intent(in) :: n
1127 real(kind=rp), dimension(n), intent(inout) :: a
1128 real(kind=rp), dimension(n), intent(in) :: b
1129 real(kind=rp), dimension(n), intent(in) :: c
1130 integer :: i
1131
1132 !$omp parallel do
1133 do i = 1, n
1134 a(i) = a(i) - b(i) * c(i)
1135 end do
1136 !$omp end parallel do
1137
1138 end subroutine subcol3
1139
1141 subroutine add3s2(a, b, c, c1, c2 ,n)
1142 integer, intent(in) :: n
1143 real(kind=rp), dimension(n), intent(inout) :: a
1144 real(kind=rp), dimension(n), intent(in) :: b
1145 real(kind=rp), dimension(n), intent(in) :: c
1146 real(kind=rp), intent(in) :: c1, c2
1147 integer :: i
1148
1149 !$omp parallel do
1150 do i = 1, n
1151 a(i) = c1 * b(i) + c2 * c(i)
1152 end do
1153 !$omp end parallel do
1154
1155 end subroutine add3s2
1156
1158 subroutine add4s3(a, b, c, d, c1, c2, c3, n)
1159 integer, intent(in) :: n
1160 real(kind=rp), dimension(n), intent(inout) :: a
1161 real(kind=rp), dimension(n), intent(in) :: b
1162 real(kind=rp), dimension(n), intent(in) :: c
1163 real(kind=rp), dimension(n), intent(in) :: d
1164 real(kind=rp), intent(in) :: c1, c2, c3
1165 integer :: i
1166
1167 !$omp parallel do
1168 do i = 1, n
1169 a(i) = c1 * b(i) + c2 * c(i) + c3 * d(i)
1170 end do
1171 !$omp end parallel do
1172
1173 end subroutine add4s3
1174
1176 subroutine add5s4(a, b, c, d, e, c1, c2, c3, c4, n)
1177 integer, intent(in) :: n
1178 real(kind=rp), dimension(n), intent(inout) :: a
1179 real(kind=rp), dimension(n), intent(in) :: b
1180 real(kind=rp), dimension(n), intent(in) :: c
1181 real(kind=rp), dimension(n), intent(in) :: d
1182 real(kind=rp), dimension(n), intent(in) :: e
1183 real(kind=rp), intent(in) :: c1, c2, c3, c4
1184 integer :: i
1185
1186 !$omp parallel do
1187 do i = 1, n
1188 a(i) = a(i) + c1 * b(i) + c2 * c(i) + c3 * d(i) + c4 * e(i)
1189 end do
1190 !$omp end parallel do
1191
1192 end subroutine add5s4
1193
1195 subroutine subcol4(a, b, c, d, n)
1196 integer, intent(in) :: n
1197 real(kind=rp), dimension(n), intent(inout) :: a
1198 real(kind=rp), dimension(n), intent(in) :: b
1199 real(kind=rp), dimension(n), intent(in) :: c
1200 real(kind=rp), dimension(n), intent(in) :: d
1201 integer :: i
1202
1203 !$omp parallel do
1204 do i = 1, n
1205 a(i) = a(i) - b(i) * c(i) * d(i)
1206 end do
1207 !$omp end parallel do
1208
1209 end subroutine subcol4
1210
1212 subroutine addcol3(a, b, c, n)
1213 integer, intent(in) :: n
1214 real(kind=rp), dimension(n), intent(inout) :: a
1215 real(kind=rp), dimension(n), intent(in) :: b
1216 real(kind=rp), dimension(n), intent(in) :: c
1217 integer :: i
1218
1219 !$omp parallel do
1220 do i = 1, n
1221 a(i) = a(i) + b(i) * c(i)
1222 end do
1223 !$omp end parallel do
1224
1225 end subroutine addcol3
1226
1228 subroutine addcol4(a, b, c, d, n)
1229 integer, intent(in) :: n
1230 real(kind=rp), dimension(n), intent(inout) :: a
1231 real(kind=rp), dimension(n), intent(in) :: b
1232 real(kind=rp), dimension(n), intent(in) :: c
1233 real(kind=rp), dimension(n), intent(in) :: d
1234 integer :: i
1235
1236 !$omp parallel do
1237 do i = 1, n
1238 a(i) = a(i) + b(i) * c(i) * d(i)
1239 end do
1240 !$omp end parallel do
1241
1242 end subroutine addcol4
1243
1245 subroutine addcol3s2(a, b, c, s, n)
1246 integer, intent(in) :: n
1247 real(kind=rp), dimension(n), intent(inout) :: a
1248 real(kind=rp), dimension(n), intent(in) :: b
1249 real(kind=rp), dimension(n), intent(in) :: c
1250 real(kind=rp), intent(in) :: s
1251 integer :: i
1252
1253 !$omp parallel do
1254 do i = 1, n
1255 a(i) = a(i) + s * b(i) * c(i)
1256 end do
1257 !$omp end parallel do
1258
1259 end subroutine addcol3s2
1260
1262 subroutine ascol5(a, b, c, d, e, n)
1263 integer, intent(in) :: n
1264 real(kind=rp), dimension(n), intent(inout) :: a
1265 real(kind=rp), dimension(n), intent(in) :: b
1266 real(kind=rp), dimension(n), intent(in) :: c
1267 real(kind=rp), dimension(n), intent(in) :: d
1268 real(kind=rp), dimension(n), intent(in) :: e
1269 integer :: i
1270
1271 !$omp parallel do
1272 do i = 1, n
1273 a(i) = b(i)*c(i) - d(i)*e(i)
1274 end do
1275 !$omp end parallel do
1276
1277 end subroutine ascol5
1278
1280 subroutine p_update(a, b, c, c1, c2, n)
1281 integer, intent(in) :: n
1282 real(kind=rp), dimension(n), intent(inout) :: a
1283 real(kind=rp), dimension(n), intent(in) :: b
1284 real(kind=rp), dimension(n), intent(in) :: c
1285 real(kind=rp), intent(in) :: c1, c2
1286 integer :: i
1287
1288 !$omp parallel do
1289 do i = 1, n
1290 a(i) = b(i) + c1*(a(i)-c2*c(i))
1291 end do
1292 !$omp end parallel do
1293
1294 end subroutine p_update
1295
1297 subroutine x_update(a, b, c, c1, c2, n)
1298 integer, intent(in) :: n
1299 real(kind=rp), dimension(n), intent(inout) :: a
1300 real(kind=rp), dimension(n), intent(in) :: b
1301 real(kind=rp), dimension(n), intent(in) :: c
1302 real(kind=rp), intent(in) :: c1, c2
1303 integer :: i
1304
1305 !$omp parallel do
1306 do i = 1, n
1307 a(i) = a(i) + c1*b(i)+c2*c(i)
1308 end do
1309 !$omp end parallel do
1310
1311 end subroutine x_update
1312
1314 function glsc2(a, b, n)
1315 integer, intent(in) :: n
1316 real(kind=rp), dimension(n), intent(in) :: a
1317 real(kind=rp), dimension(n), intent(in) :: b
1318 real(kind=rp) :: glsc2
1319 real(kind=xp) :: tmp
1320 integer :: i, ierr
1321
1322 tmp = 0.0_xp
1323 !$omp parallel do reduction(+:tmp)
1324 do i = 1, n
1325 tmp = tmp + a(i) * b(i)
1326 end do
1327 !$omp end parallel do
1328
1329 call mpi_allreduce(mpi_in_place, tmp, 1, &
1330 mpi_extra_precision, mpi_sum, neko_comm, ierr)
1331 glsc2 = tmp
1332 end function glsc2
1333
1335 function glsc3(a, b, c, n)
1336 integer, intent(in) :: n
1337 real(kind=rp), dimension(n), intent(in) :: a
1338 real(kind=rp), dimension(n), intent(in) :: b
1339 real(kind=rp), dimension(n), intent(in) :: c
1340 real(kind=rp) :: glsc3
1341 real(kind=xp) :: tmp
1342 integer :: i, ierr
1343
1344 tmp = 0.0_xp
1345 !$omp parallel do reduction(+:tmp)
1346 do i = 1, n
1347 tmp = tmp + a(i) * b(i) * c(i)
1348 end do
1349 !$omp end parallel do
1350
1351 call mpi_allreduce(mpi_in_place, tmp, 1, &
1352 mpi_extra_precision, mpi_sum, neko_comm, ierr)
1353 glsc3 = tmp
1354
1355 end function glsc3
1356 function glsc4(a, b, c, d, n)
1357 integer, intent(in) :: n
1358 real(kind=rp), dimension(n), intent(in) :: a
1359 real(kind=rp), dimension(n), intent(in) :: b
1360 real(kind=rp), dimension(n), intent(in) :: c
1361 real(kind=rp), dimension(n), intent(in) :: d
1362 real(kind=rp) :: glsc4
1363 real(kind=xp) :: tmp
1364 integer :: i, ierr
1365
1366 tmp = 0.0_xp
1367 !$omp parallel do reduction(+:tmp)
1368 do i = 1, n
1369 tmp = tmp + a(i) * b(i) * c(i) * d(i)
1370 end do
1371 !$omp end parallel do
1372
1373 call mpi_allreduce(mpi_in_place, tmp, 1, &
1374 mpi_extra_precision, mpi_sum, neko_comm, ierr)
1375 glsc4 = tmp
1376
1377 end function glsc4
1378
1381 function glsubnorm(a, b, n)
1382 integer, intent(in) :: n
1383 real(kind=rp), dimension(n), intent(in) :: a
1384 real(kind=rp), dimension(n), intent(in) :: b
1385 real(kind=rp) :: glsubnorm
1386 real(kind=xp) :: tmp
1387 integer :: i, ierr
1388
1389 tmp = 0.0_xp
1390 !$omp parallel do reduction(+:tmp)
1391 do i = 1, n
1392 tmp = tmp + (a(i) - b(i))**2
1393 end do
1394 !$omp end parallel do
1395
1396 call mpi_allreduce(mpi_in_place, tmp, 1, &
1397 mpi_extra_precision, mpi_sum, neko_comm, ierr)
1398 glsubnorm = sqrt(tmp)
1399
1400 end function glsubnorm
1401
1407 subroutine sortrp(a, ind, n)
1408 integer, intent(in) :: n
1409 real(kind=rp), intent(inout) :: a(n)
1410 integer, intent(out) :: ind(n)
1411 real(kind=rp) :: aa
1412 integer :: j, ir, i, ii, l
1413
1414 do j = 1, n
1415 ind(j) = j
1416 end do
1417
1418 if (n .le. 1) return
1419
1420
1421 l = n/2+1
1422 ir = n
1423 do while (.true.)
1424 if (l .gt. 1) then
1425 l = l-1
1426 aa = a(l)
1427 ii = ind(l)
1428 else
1429 aa = a(ir)
1430 ii = ind(ir)
1431 a(ir) = a(1)
1432 ind(ir) = ind(1)
1433 ir = ir - 1
1434 if (ir .eq. 1) then
1435 a(1) = aa
1436 ind(1) = ii
1437 return
1438 end if
1439 end if
1440 i = l
1441 j = l+l
1442 do while (j .le. ir)
1443 if (j .lt. ir) then
1444 if ( a(j) .lt. a(j+1) ) j = j + 1
1445 end if
1446 if (aa .lt. a(j)) then
1447 a(i) = a(j)
1448 ind(i) = ind(j)
1449 i = j
1450 j = j+j
1451 else
1452 j = ir+1
1453 end if
1454 end do
1455 a(i) = aa
1456 ind(i) = ii
1457 end do
1458 end subroutine sortrp
1459
1465 subroutine sorti4(a, ind, n)
1466 integer, intent(in) :: n
1467 integer(i4), intent(inout) :: a(n)
1468 integer, intent(out) :: ind(n)
1469 integer(i4) :: aa
1470 integer :: j, ir, i, ii, l
1471
1472 do j = 1, n
1473 ind(j) = j
1474 end do
1475
1476 if (n .le. 1) return
1477
1478 l = n/2+1
1479 ir = n
1480 do while (.true.)
1481 if (l .gt. 1) then
1482 l = l - 1
1483 aa = a(l)
1484 ii = ind(l)
1485 else
1486 aa = a(ir)
1487 ii = ind(ir)
1488 a(ir) = a( 1)
1489 ind(ir) = ind( 1)
1490 ir = ir - 1
1491 if (ir .eq. 1) then
1492 a(1) = aa
1493 ind(1) = ii
1494 return
1495 end if
1496 end if
1497 i = l
1498 j = l + l
1499 do while (j .le. ir)
1500 if (j .lt. ir) then
1501 if ( a(j) .lt. a(j + 1) ) j = j + 1
1502 end if
1503 if (aa .lt. a(j)) then
1504 a(i) = a(j)
1505 ind(i) = ind(j)
1506 i = j
1507 j = j + j
1508 else
1509 j = ir + 1
1510 end if
1511 end do
1512 a(i) = aa
1513 ind(i) = ii
1514 end do
1515 end subroutine sorti4
1516
1521 subroutine swapdp(b, ind, n)
1522 integer, intent(in) :: n
1523 real(kind=rp), intent(inout) :: b(n)
1524 integer, intent(in) :: ind(n)
1525 real(kind=rp) :: temp(n)
1526 integer :: i, jj
1527
1528 !$omp parallel private(i, jj)
1529 !$omp do
1530 do i = 1, n
1531 temp(i) = b(i)
1532 end do
1533 !$omp end do
1534 !$omp do
1535 do i = 1, n
1536 jj = ind(i)
1537 b(i) = temp(jj)
1538 end do
1539 !$omp end do
1540 !$omp end parallel
1541
1542 end subroutine swapdp
1543
1548 subroutine swapi4(b, ind, n)
1549 integer, intent(in) :: n
1550 integer(i4), intent(inout) :: b(n)
1551 integer, intent(in) :: ind(n)
1552 integer(i4) :: temp(n)
1553 integer :: i, jj
1554
1555 !$omp parallel private(i, jj)
1556 !$omp do
1557 do i = 1, n
1558 temp(i) = b(i)
1559 end do
1560 !$omp end do
1561 !$omp do
1562 do i = 1, n
1563 jj = ind(i)
1564 b(i) = temp(jj)
1565 end do
1566 !$omp end do
1567 !$omp end parallel
1568
1569 end subroutine swapi4
1570
1575 subroutine reorddp(b, ind, n)
1576 integer, intent(in) :: n
1577 real(kind=rp), intent(inout) :: b(n)
1578 integer, intent(in) :: ind(n)
1579 real(kind=rp) :: temp(n)
1580 integer :: i, jj
1581
1582 !$omp parallel private(i, jj)
1583 !$omp do
1584 do i = 1, n
1585 temp(i) = b(i)
1586 end do
1587 !$omp end do
1588 !$omp do
1589 do i = 1, n
1590 jj = ind(i)
1591 b(jj) = temp(i)
1592 end do
1593 !$omp end do
1594 !$omp end parallel
1595
1596 end subroutine reorddp
1597
1602 subroutine reordi4(b, ind, n)
1603 integer, intent(in) :: n
1604 integer(i4), intent(inout) :: b(n)
1605 integer, intent(in) :: ind(n)
1606 integer(i4) :: temp(n)
1607 integer :: i, jj
1608
1609 !$omp parallel private(i, jj)
1610 !$omp do
1611 do i = 1, n
1612 temp(i) = b(i)
1613 end do
1614 !$omp end do
1615 !$omp do
1616 do i = 1, n
1617 jj = ind(i)
1618 b(jj) = temp(i)
1619 end do
1620 !$omp end do
1621 !$omp end parallel
1622
1623 end subroutine reordi4
1624
1629 subroutine flipvdp(b, ind, n)
1630 integer, intent(in) :: n
1631 real(kind=rp), intent(inout) :: b(n)
1632 integer, intent(inout) :: ind(n)
1633 real(kind=rp) :: temp(n)
1634 integer :: tempind(n)
1635 integer :: i, jj
1636
1637 !$omp parallel private(i, jj)
1638 !$omp do
1639 do i = 1, n
1640 jj = n+1-i
1641 temp(jj) = b(i)
1642 tempind(jj) = ind(i)
1643 end do
1644 !$omp end do
1645 !$omp do
1646 do i = 1,n
1647 b(i) = temp(i)
1648 ind(i) = tempind(i)
1649 end do
1650 !$omp end do
1651 !$omp end parallel
1652
1653 end subroutine flipvdp
1654
1659 subroutine flipvi4(b, ind, n)
1660 integer, intent(in) :: n
1661 integer(i4), intent(inout) :: b(n)
1662 integer, intent(inout) :: ind(n)
1663 integer(i4) :: temp(n)
1664 integer :: tempind(n)
1665 integer :: i, jj
1666
1667 !$omp parallel private(i, jj)
1668 !$omp do
1669 do i = 1, n
1670 jj = n+1-i
1671 temp(jj) = b(i)
1672 tempind(jj) = ind(i)
1673 end do
1674 !$omp end do
1675 !$omp do
1676 do i = 1,n
1677 b(i) = temp(i)
1678 ind(i) = tempind(i)
1679 end do
1680 !$omp end do
1681 !$omp end parallel
1682
1683 end subroutine flipvi4
1684
1688 subroutine absval(a, n)
1689 integer, intent(in) :: n
1690 real(kind=rp), dimension(n), intent(inout) :: a
1691 integer :: i
1692
1693 !$omp parallel do
1694 do i = 1, n
1695 a(i) = abs(a(i))
1696 end do
1697 !$omp end parallel do
1698
1699 end subroutine absval
1700
1701 ! ========================================================================== !
1702 ! Point-wise operations
1703
1705 subroutine pwmax2(a, b, n)
1706 integer, intent(in) :: n
1707 real(kind=rp), dimension(n), intent(inout) :: a
1708 real(kind=rp), dimension(n), intent(in) :: b
1709 integer :: i
1710
1711 !$omp parallel do
1712 do i = 1, n
1713 a(i) = max(a(i), b(i))
1714 end do
1715 !$omp end parallel do
1716
1717 end subroutine pwmax2
1718
1720 subroutine pwmax3(a, b, c, n)
1721 integer, intent(in) :: n
1722 real(kind=rp), dimension(n), intent(inout) :: a
1723 real(kind=rp), dimension(n), intent(in) :: b, c
1724 integer :: i
1725
1726 !$omp parallel do
1727 do i = 1, n
1728 a(i) = max(b(i), c(i))
1729 end do
1730 !$omp end parallel do
1731
1732 end subroutine pwmax3
1733
1735 subroutine cpwmax2(a, b, n)
1736 integer, intent(in) :: n
1737 real(kind=rp), dimension(n), intent(inout) :: a
1738 real(kind=rp), intent(in) :: b
1739 integer :: i
1740
1741 !$omp parallel do
1742 do i = 1, n
1743 a(i) = max(a(i), b)
1744 end do
1745 !$omp end parallel do
1746
1747 end subroutine cpwmax2
1748
1750 subroutine cpwmax3(a, b, c, n)
1751 integer, intent(in) :: n
1752 real(kind=rp), dimension(n), intent(inout) :: a
1753 real(kind=rp), dimension(n), intent(in) :: b
1754 real(kind=rp), intent(in) :: c
1755 integer :: i
1756
1757 !$omp parallel do
1758 do i = 1, n
1759 a(i) = max(b(i), c)
1760 end do
1761 !$omp end parallel do
1762
1763 end subroutine cpwmax3
1764
1766 subroutine pwmin2(a, b, n)
1767 integer, intent(in) :: n
1768 real(kind=rp), dimension(n), intent(inout) :: a
1769 real(kind=rp), dimension(n), intent(in) :: b
1770 integer :: i
1771
1772 !$omp parallel do
1773 do i = 1, n
1774 a(i) = min(a(i), b(i))
1775 end do
1776 !$omp end parallel do
1777
1778 end subroutine pwmin2
1779
1781 subroutine pwmin3(a, b, c, n)
1782 integer, intent(in) :: n
1783 real(kind=rp), dimension(n), intent(inout) :: a
1784 real(kind=rp), dimension(n), intent(in) :: b, c
1785 integer :: i
1786
1787 !$omp parallel do
1788 do i = 1, n
1789 a(i) = min(b(i), c(i))
1790 end do
1791 !$omp end parallel do
1792
1793 end subroutine pwmin3
1794
1796 subroutine cpwmin2(a, b, n)
1797 integer, intent(in) :: n
1798 real(kind=rp), dimension(n), intent(inout) :: a
1799 real(kind=rp), intent(in) :: b
1800 integer :: i
1801
1802 !$omp parallel do
1803 do i = 1, n
1804 a(i) = min(a(i), b)
1805 end do
1806 !$omp end parallel do
1807
1808 end subroutine cpwmin2
1809
1811 subroutine cpwmin3(a, b, c, n)
1812 integer, intent(in) :: n
1813 real(kind=rp), dimension(n), intent(inout) :: a
1814 real(kind=rp), dimension(n), intent(in) :: b
1815 real(kind=rp), intent(in) :: c
1816 integer :: i
1817
1818 !$omp parallel do
1819 do i = 1, n
1820 a(i) = min(b(i), c)
1821 end do
1822 !$omp end parallel do
1823
1824 end subroutine cpwmin3
1825
1826 ! M33INV and M44INV by David G. Simpson pure function version from
1827 ! https://fortranwiki.org/fortran/show/Matrix+inversion
1828 ! Invert 3x3 matrix
1829 function matinv39(a11, a12, a13, a21, a22, a23, a31, a32, a33) &
1830 result(b)
1831 real(kind=rp), intent(in) :: a11, a12, a13, a21, a22, a23, a31, a32, a33
1832 real(xp) :: a(3,3) !! Matrix
1833 real(rp) :: b(3,3) !! Inverse matrix
1834 a(1,1) = a11
1835 a(1,2) = a12
1836 a(1,3) = a13
1837 a(2,1) = a21
1838 a(2,2) = a22
1839 a(2,3) = a23
1840 a(3,1) = a31
1841 a(3,2) = a32
1842 a(3,3) = a33
1843 b = matinv3(a)
1844 end function matinv39
1845
1850 function matinv3(A) result(B)
1851 !! Performs a direct calculation of the inverse of a 3×3 matrix.
1852 real(kind=xp), intent(in) :: a(3,3) !! Matrix
1853 real(kind=xp) :: b(3,3) !! Inverse matrix
1854 real(kind=xp) :: detinv
1855
1856 ! Calculate the inverse determinant of the matrix
1857 ! first index x,y,z, second r, s, t
1858 detinv = 1.0_xp / real(a(1,1)*a(2,2)*a(3,3) - a(1,1)*a(2,3)*a(3,2) &
1859 - a(1,2)*a(2,1)*a(3,3) + a(1,2)*a(2,3)*a(3,1)&
1860 + a(1,3)*a(2,1)*a(3,2) - a(1,3)*a(2,2)*a(3,1), xp)
1861 ! Calculate the inverse of the matrix
1862 ! first index r, s, t, second x, y, z
1863 b(1,1) = +detinv * (a(2,2)*a(3,3) - a(2,3)*a(3,2))
1864 b(2,1) = -detinv * (a(2,1)*a(3,3) - a(2,3)*a(3,1))
1865 b(3,1) = +detinv * (a(2,1)*a(3,2) - a(2,2)*a(3,1))
1866 b(1,2) = -detinv * (a(1,2)*a(3,3) - a(1,3)*a(3,2))
1867 b(2,2) = +detinv * (a(1,1)*a(3,3) - a(1,3)*a(3,1))
1868 b(3,2) = -detinv * (a(1,1)*a(3,2) - a(1,2)*a(3,1))
1869 b(1,3) = +detinv * (a(1,2)*a(2,3) - a(1,3)*a(2,2))
1870 b(2,3) = -detinv * (a(1,1)*a(2,3) - a(1,3)*a(2,1))
1871 b(3,3) = +detinv * (a(1,1)*a(2,2) - a(1,2)*a(2,1))
1872 end function matinv3
1873
1876 function math_stepf(x) result(val)
1877 real(kind=rp), intent(in) :: x
1878 real(kind=rp) :: val
1879 real(kind=rp), parameter :: xdmin = 0.0001_rp
1880 real(kind=rp), parameter :: xdmax = 0.9999_rp
1881 real(kind=rp) :: g
1882
1883 if (x <= xdmin) then
1884 ! Below the lower bound, the function is 0
1885 val = 0.0_rp
1886 else if (x >= xdmax) then
1887 ! Above the upper bound, the function is 1
1888 val = 1.0_rp
1889 else
1890 ! g(x) = 1/(x-1) + 1/x
1891 g = (1.0_rp / (x - 1.0_rp)) + (1.0_rp / x)
1892
1893 ! The sigmoid: S(x) = 1 / (1 + exp(g))
1894 val = 1.0_rp / (1.0_rp + exp(g))
1895 end if
1896 end function math_stepf
1897
1899 function math_dstepf(x) result(val)
1900 real(kind=rp), intent(in) :: x
1901 real(kind=rp) :: val
1902 real(kind=rp), parameter :: xdmin = 0.0001_rp
1903 real(kind=rp), parameter :: xdmax = 0.9999_rp
1904 real(kind=rp) :: arg, g, dg, s_val
1905
1906 if (x <= xdmin .or. x >= xdmax) then
1907 val = 0.0_rp
1908 else
1909 ! The step function is S(x) = 1 / (1 + exp(g(x)))
1910 ! where g(x) = 1/(x-1) + 1/x
1911 ! S'(x) = -S(x) * (1 - S(x)) * g'(x)
1912
1913 g = (1.0_rp / (x - 1.0_rp)) + (1.0_rp / x)
1914
1915 ! Derivative of g(x)
1916 dg = -(1.0_rp / ((x - 1.0_rp)**2)) - (1.0_rp / (x**2))
1917
1918 ! Recompute S(x) locally
1919 s_val = 1.0_rp / (1.0_rp + exp(g))
1920
1921 val = -s_val * (1.0_rp - s_val) * dg
1922 end if
1923 end function math_dstepf
1924
1926 subroutine sqrt_inplace(a, n)
1927 integer, intent(in) :: n
1928 real(kind=rp), dimension(n), intent(inout) :: a
1929 integer :: i
1930
1931 !$omp parallel do
1932 do i = 1, n
1933 a(i) = sqrt(a(i))
1934 end do
1935 !$omp end parallel do
1936
1937 end subroutine sqrt_inplace
1938
1940 subroutine power(ap, a, p, n)
1941 integer, intent(in) :: n
1942 real(kind=rp), dimension(n), intent(inout) :: ap
1943 real(kind=rp), dimension(n), intent(in) :: a
1944 real(kind=rp), intent(in) :: p
1945 integer :: i
1946
1947 !$omp parallel do
1948 do i = 1, n
1949 ap(i) = a(i)**p
1950 end do
1951 !$omp end parallel do
1952
1953 end subroutine power
1954
1961 pure subroutine eig_sym2(a11, a22, a12, e1, e2)
1962 real(kind=dp), intent(in) :: a11, a22, a12
1963 real(kind=dp), intent(out) :: e1, e2
1964 real(kind=dp) :: t, d, s
1965
1966 t = a11 + a22
1967 d = a11 * a22 - a12 * a12
1968 s = sqrt(max(0.0_dp, 0.25_dp * t * t - d))
1969 e1 = 0.5_dp * t + s
1970
1971 if (e1 .gt. 0.0_dp) then
1972 e2 = d / e1
1973 else
1974 e2 = 0.5_dp * t - s
1975 end if
1976
1977 end subroutine eig_sym2
1978
2012 pure subroutine eig_sym3(a11, a22, a33, a12, a13, a23, e1, e2, e3)
2013 real(kind=dp), intent(in) :: a11, a22, a33, a12, a13, a23
2014 real(kind=dp), intent(out) :: e1, e2, e3
2015 real(kind=dp) :: p1, p2, q, p, r, phi
2016 real(kind=dp) :: b11, b22, b33, b12, b13, b23
2017 real(kind=dp), parameter :: third = 1.0_dp / 3.0_dp
2018 real(kind=dp), parameter :: pi_third = 1.0471975511965976_dp
2019 real(kind=dp), parameter :: twopi_third = 2.0943951023931953_dp
2020
2021 p1 = a12 * a12 + a13 * a13 + a23 * a23
2022
2023 q = (a11 + a22 + a33) * third
2024 p2 = (a11 - q)**2 + (a22 - q)**2 + (a33 - q)**2 + 2.0_dp * p1
2025 p = sqrt(p2 / 6.0_dp)
2026
2027 if (p .le. 0.0_dp) then
2028 ! diagonal and isotropic, or all zero
2029 e1 = max(a11, max(a22, a33))
2030 e3 = min(a11, min(a22, a33))
2031 e2 = a11 + a22 + a33 - e1 - e3
2032 return
2033 end if
2034
2035 b11 = (a11 - q) / p
2036 b22 = (a22 - q) / p
2037 b33 = (a33 - q) / p
2038 b12 = a12 / p
2039 b13 = a13 / p
2040 b23 = a23 / p
2041
2042 r = 0.5_dp * (b11 * (b22 * b33 - b23 * b23) &
2043 - b12 * (b12 * b33 - b23 * b13) &
2044 + b13 * (b12 * b23 - b22 * b13))
2045
2046 ! r is in [-1, 1] analytically, round-off can push it out
2047 if (r .le. -1.0_dp) then
2048 phi = pi_third
2049 else if (r .ge. 1.0_dp) then
2050 phi = 0.0_dp
2051 else
2052 phi = acos(r) * third
2053 end if
2054
2055 e1 = q + 2.0_dp * p * cos(phi)
2056 e3 = q + 2.0_dp * p * cos(phi + twopi_third)
2057 e2 = 3.0_dp * q - e1 - e3
2058
2059 end subroutine eig_sym3
2060
2061
2062
2063end module math
__inline__ __device__ void nonlinear_index(const int idx, const int lx, int *index)
Definition bc_utils.h:44
double real
Definition comm.F90:1
type(mpi_datatype), public mpi_real_precision
MPI type for working precision of REAL types.
Definition comm.F90:54
type(mpi_comm), public neko_comm
MPI communicator.
Definition comm.F90:46
type(mpi_datatype), public mpi_extra_precision
Definition comm.F90:55
Object for handling masks in Neko.
Definition mask.f90:34
Definition math.F90:60
subroutine, public cmult(a, c, n)
Multiplication by constant c .
Definition math.F90:518
subroutine, public cmult2(a, b, c, n)
Multiplication by constant c .
Definition math.F90:533
subroutine, public row_zero(a, m, n, e)
Sets row e to 0 in matrix a.
Definition math.F90:277
subroutine, public invcol2(a, b, n)
Vector division .
Definition math.F90:1079
real(kind=rp) function, public vlsc2(u, v, n)
Compute multiplication sum .
Definition math.F90:933
pure logical function, public dabscmp(x, y, tol)
Return double precision absolute comparison .
Definition math.F90:145
pure subroutine, public eig_sym3(a11, a22, a33, a12, a13, a23, e1, e2, e3)
Eigenvalues of a symmetric 3x3 matrix, descending.
Definition math.F90:2013
real(kind=rp), parameter, public pi
Definition math.F90:78
subroutine, public sqrt_inplace(a, n)
Sqrt a vector .
Definition math.F90:1927
real(kind=rp) function, public glsc3(a, b, c, n)
Weighted inner product .
Definition math.F90:1336
subroutine, public ascol5(a, b, c, d, e, n)
Returns .
Definition math.F90:1263
subroutine, public addcol3s2(a, b, c, s, n)
Returns .
Definition math.F90:1246
real(kind=rp) function, public glamax(a, n)
Max of the absolute value of a vector of length n.
Definition math.F90:684
subroutine, public masked_scatter_copy(a, b, mask, n, n_mask)
Scatter a contigous vector to masked positions in a target array .
Definition math.F90:484
subroutine, public invers2(a, b, n)
Compute inverted vector .
Definition math.F90:849
subroutine, public cadd2(a, b, s, n)
Add a scalar to vector .
Definition math.F90:595
subroutine, public face_masked_gather_copy_0(a, b, mask, facet, lx, ly, lz, n_mask)
Gather values from a face-local SEM field to a reduced contiguous vector.
Definition math.F90:399
real(rp) function, dimension(3, 3), public matinv39(a11, a12, a13, a21, a22, a23, a31, a32, a33)
Definition math.F90:1831
subroutine, public cadd(a, s, n)
Add a scalar to vector .
Definition math.F90:580
subroutine, public masked_copy(a, b, mask, n, n_mask)
Copy a masked vector .
Definition math.F90:349
subroutine reorddp(b, ind, n)
reorder double precision array - inverse of swap
Definition math.F90:1576
pure subroutine, public eig_sym2(a11, a22, a12, e1, e2)
Eigenvalues of a symmetric 2x2 matrix, descending.
Definition math.F90:1962
subroutine, public addsqr2s2(a, b, c1, n)
Returns .
Definition math.F90:1063
subroutine, public cwrap(a, min_val, max_val, n)
Wrap value around a range [min, max)
Definition math.F90:626
real(kind=rp) function, public glsc4(a, b, c, d, n)
Definition math.F90:1357
subroutine, public cdiv2(a, b, c, n)
Division of constant c by elements of a .
Definition math.F90:564
real(kind=rp) function, public math_stepf(x)
Smooth step function S(x) Returns 0 for x <= 0, 1 for x >= 1, and smooth transition in between.
Definition math.F90:1877
subroutine swapdp(b, ind, n)
sort double precision array acording to ind vector
Definition math.F90:1522
subroutine flipvi4(b, ind, n)
Flip single integer vector b and ind.
Definition math.F90:1660
subroutine, public add2s1(a, b, c1, n)
Vector addition with scalar multiplication (multiplication on first argument)
Definition math.F90:1030
subroutine, public cpwmin2(a, b, n)
Point-wise minimum of scalar and vector .
Definition math.F90:1797
real(kind=rp) function, public glsc2(a, b, n)
Weighted inner product .
Definition math.F90:1315
subroutine, public masked_scatter_copy_0(a, b, mask, n, n_mask)
Scatter a contigous vector to masked positions in a target array .
Definition math.F90:459
subroutine, public subcol3(a, b, c, n)
Returns .
Definition math.F90:1126
subroutine, public rone(a, n)
Set all elements to one.
Definition math.F90:291
subroutine flipvdp(b, ind, n)
Flip double precision vector b and ind.
Definition math.F90:1630
subroutine, public cpwmin3(a, b, c, n)
Point-wise minimum of scalar and vector .
Definition math.F90:1812
subroutine, public pwmax3(a, b, c, n)
Point-wise maximum of two vectors .
Definition math.F90:1721
subroutine, public masked_gather_copy(a, b, mask, n, n_mask)
Gather a masked vector to reduced contigous vector .
Definition math.F90:434
subroutine, public x_update(a, b, c, c1, c2, n)
Returns .
Definition math.F90:1298
subroutine, public add3(a, b, c, n)
Vector addition .
Definition math.F90:964
subroutine swapi4(b, ind, n)
sort single integer array acording to ind vector
Definition math.F90:1549
integer function, public glimin(a, n)
Min of an integer vector of length n.
Definition math.F90:741
real(kind=rp) function, public glsum(a, n)
Sum a vector of length n.
Definition math.F90:643
subroutine, public sub3(a, b, c, n)
Vector subtraction .
Definition math.F90:1012
subroutine, public addcol4(a, b, c, d, n)
Returns .
Definition math.F90:1229
subroutine, public add2(a, b, n)
Vector addition .
Definition math.F90:949
subroutine, public cfill(a, c, n)
Set all elements to a constant c .
Definition math.F90:611
subroutine, public absval(a, n)
Take the absolute value of an array.
Definition math.F90:1689
subroutine, public invcol3(a, b, c, n)
Invert a vector .
Definition math.F90:834
subroutine, public add3s2(a, b, c, c1, c2, n)
Returns .
Definition math.F90:1142
real(kind=xp) function, dimension(3, 3), public matinv3(a)
Performs a direct calculation of the inverse of a 3×3 matrix. M33INV and M44INV by David G....
Definition math.F90:1851
subroutine, public pwmax2(a, b, n)
Point-wise maximum of two vectors .
Definition math.F90:1706
subroutine, public pwmin2(a, b, n)
Point-wise minimum of two vectors .
Definition math.F90:1767
subroutine, public masked_gather_copy_0(a, b, mask, n, n_mask)
Gather a masked vector to reduced contigous vector .
Definition math.F90:374
subroutine, public subcol4(a, b, c, d, n)
Returns .
Definition math.F90:1196
subroutine sorti4(a, ind, n)
Heap Sort for single integer arrays.
Definition math.F90:1466
subroutine, public addcol3(a, b, c, n)
Returns .
Definition math.F90:1213
subroutine, public invcol1(a, n)
Invert a vector .
Definition math.F90:820
subroutine, public cdiv(a, c, n)
Division of constant c by elements of a .
Definition math.F90:549
real(kind=rp), parameter, public neko_m_ln2
Definition math.F90:75
subroutine, public chsign(a, n)
Change sign of vector .
Definition math.F90:760
subroutine, public cpwmax3(a, b, c, n)
Point-wise maximum of scalar and vector .
Definition math.F90:1751
subroutine, public col2(a, b, n)
Vector multiplication .
Definition math.F90:1095
subroutine, public izero(a, n)
Zero an integer vector.
Definition math.F90:263
real(kind=rp) function, public glmax(a, n)
Max of a vector of length n.
Definition math.F90:664
real(kind=sp), parameter, public neko_eps_sp
Definition math.F90:72
subroutine, public copy(a, b, n)
Copy a vector .
Definition math.F90:305
subroutine, public add4s3(a, b, c, d, c1, c2, c3, n)
Returns .
Definition math.F90:1159
subroutine, public add4(a, b, c, d, n)
Vector addition .
Definition math.F90:980
real(kind=rp) function, public vlamax(vec, n)
maximum absolute value of a vector of length n, rank-local
Definition math.F90:774
subroutine, public col3(a, b, c, n)
Vector multiplication with 3 vectors .
Definition math.F90:1110
subroutine, public add5s4(a, b, c, d, e, c1, c2, c3, c4, n)
Returns .
Definition math.F90:1177
real(kind=rp) function, public math_dstepf(x)
Derivative of math_stepf with respect to x: d(stepf)/dx.
Definition math.F90:1900
pure logical function drelcmp(x, y, eps)
Return double precision relative comparison .
Definition math.F90:193
real(kind=rp), parameter, public neko_eps
Machine epsilon .
Definition math.F90:70
subroutine, public vdot3(dot, u1, u2, u3, v1, v2, v3, n)
Compute a dot product (3-d version) assuming vector components etc.
Definition math.F90:901
pure logical function, public sabscmp(x, y, tol)
Return single precision absolute comparison .
Definition math.F90:130
subroutine, public rzero(a, n)
Zero a real vector.
Definition math.F90:249
real(kind=rp) function, public glsubnorm(a, b, n)
Returns the norm of the difference of two vectors .
Definition math.F90:1382
subroutine, public vdot2(dot, u1, u2, v1, v2, n)
Compute a dot product (2-d version) assuming vector components etc.
Definition math.F90:884
subroutine, public cpwmax2(a, b, n)
Point-wise maximum of scalar and vector .
Definition math.F90:1736
real(kind=dp), parameter, public neko_eps_dp
Definition math.F90:71
real(kind=rp) function, public vlmin(vec, n)
minimun value of a vector of length n
Definition math.F90:804
subroutine, public cfill_mask(a, c, n, mask, n_mask)
Fill a constant to a masked vector. .
Definition math.F90:502
real(kind=rp) function, public vlmax(vec, n)
maximum value of a vector of length n
Definition math.F90:789
integer function, public glimax(a, n)
Max of an integer vector of length n.
Definition math.F90:703
subroutine sortrp(a, ind, n)
Heap Sort for double precision arrays.
Definition math.F90:1408
subroutine, public sub2(a, b, n)
Vector substraction .
Definition math.F90:997
subroutine, public pwmin3(a, b, c, n)
Point-wise minimum of two vectors .
Definition math.F90:1782
subroutine, public add2s2(a, b, c1, n)
Vector addition with scalar multiplication (multiplication on second argument)
Definition math.F90:1047
real(kind=rp) function, public glmin(a, n)
Min of a vector of length n.
Definition math.F90:722
subroutine, public masked_copy_0(a, b, mask, n, n_mask)
Copy a masked vector .
Definition math.F90:326
subroutine, public vcross(u1, u2, u3, v1, v2, v3, w1, w2, w3, n)
Compute a cross product assuming vector components etc.
Definition math.F90:865
pure logical function srelcmp(x, y, eps)
Return single precision relative comparison .
Definition math.F90:178
pure real(kind=rp) function, public lambert_w0(x, niter)
Approximate the principal real branch of the Lambert W function for non-negative real x.
Definition math.F90:228
real(kind=rp) function, public vlsc3(u, v, w, n)
Compute multiplication sum .
Definition math.F90:917
subroutine, public power(ap, a, p, n)
Take the power of a vector .
Definition math.F90:1941
subroutine reordi4(b, ind, n)
reorder single integer array - inverse of swap
Definition math.F90:1603
subroutine, public p_update(a, b, c, c1, c2, n)
Returns .
Definition math.F90:1281
integer, parameter, public qp
Definition num_types.f90:12
integer, parameter, public i4
Definition num_types.f90:6
integer, parameter, public xp
Definition num_types.f90:16
integer, parameter, public dp
Definition num_types.f90:10
integer, parameter, public sp
Definition num_types.f90:8
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Utilities.
Definition utils.f90:35
#define max(a, b)
Definition tensor.cu:40