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, qabscmp
82 end interface abscmp
83
84 interface sort
85 module procedure sortrp, sorti4
86 end interface sort
87
88 interface swap
89 module procedure swapdp, swapi4
90 end interface swap
91
92 interface reord
93 module procedure reorddp, reordi4
94 end interface reord
95
96 interface flipv
97 module procedure flipvdp, flipvi4
98 end interface flipv
99
100 interface relcmp
101 module procedure srelcmp, drelcmp, qrelcmp
102 end interface relcmp
103
104 public :: abscmp, rzero, izero, row_zero, rone, copy, cmult, cadd, cfill, &
113 matinv39, &
119
120contains
121
123 pure function sabscmp(x, y, tol)
124 real(kind=sp), intent(in) :: x
125 real(kind=sp), intent(in) :: y
126 real(kind=sp), intent(in), optional :: tol
127 logical :: sabscmp
128
129 if (present(tol)) then
130 sabscmp = abs(x - y) .lt. tol
131 else
132 sabscmp = abs(x - y) .lt. neko_eps
133 end if
134
135 end function sabscmp
136
138 pure function dabscmp(x, y, tol)
139 real(kind=dp), intent(in) :: x
140 real(kind=dp), intent(in) :: y
141 real(kind=dp), intent(in), optional :: tol
142 logical :: dabscmp
143
144 if (present(tol)) then
145 dabscmp = abs(x - y) .lt. tol
146 else
147 dabscmp = abs(x - y) .lt. neko_eps
148 end if
149
150 end function dabscmp
151
153 pure function qabscmp(x, y, tol)
154 real(kind=qp), intent(in) :: x
155 real(kind=qp), intent(in) :: y
156 real(kind=qp), intent(in), optional :: tol
157 logical :: qabscmp
158
159 if (present(tol)) then
160 qabscmp = abs(x - y) .lt. tol
161 else
162 qabscmp = abs(x - y) .lt. neko_eps
163 end if
164
165 end function qabscmp
166
169 pure function srelcmp(x, y, eps)
170 real(kind=sp), intent(in) :: x
171 real(kind=sp), intent(in) :: y
172 real(kind=sp), intent(in), optional :: eps
173 logical :: srelcmp
174 if (present(eps)) then
175 srelcmp = abs(x - y) .le. eps*abs(y)
176 else
177 srelcmp = abs(x - y) .le. neko_eps*abs(y)
178 end if
179
180 end function srelcmp
181
184 pure function drelcmp(x, y, eps)
185 real(kind=dp), intent(in) :: x
186 real(kind=dp), intent(in) :: y
187 real(kind=dp), intent(in), optional :: eps
188 logical :: drelcmp
189 if (present(eps)) then
190 drelcmp = abs(x - y) .le. eps*abs(y)
191 else
192 drelcmp = abs(x - y) .le. neko_eps*abs(y)
193 end if
194
195 end function drelcmp
196
197
199 pure function qrelcmp(x, y, eps)
200 real(kind=qp), intent(in) :: x
201 real(kind=qp), intent(in) :: y
202 real(kind=qp), intent(in), optional :: eps
203 logical :: qrelcmp
204 if (present(eps)) then
205 qrelcmp = abs(x - y)/abs(y) .lt. eps
206 else
207 qrelcmp = abs(x - y)/abs(y) .lt. neko_eps
208 end if
209
210 end function qrelcmp
211
217 pure function lambert_w0(x, niter) result(w)
218 real(kind=rp), intent(in) :: x
219 integer, intent(in) :: niter
220 real(kind=rp) :: w
221 real(kind=rp) :: a
222 integer :: k
223
224 if (x == 0.0_rp) then
225 w = 0.0_rp
226 return
227 end if
228
229 a = 1.0_rp / (1.0_rp + 0.5_rp * log(1.0_rp + x))
230 w = log(1.0_rp + a * x)
231
232 do k = 1, max(niter, 0)
233 w = w / (1.0_rp + w) * (1.0_rp + log(x / w))
234 end do
235 end function lambert_w0
236
238 subroutine rzero(a, n)
239 integer, intent(in) :: n
240 real(kind=rp), dimension(n), intent(inout) :: a
241 integer :: i
242
243 !$omp parallel do
244 do i = 1, n
245 a(i) = 0.0_rp
246 end do
247 !$omp end parallel do
248
249 end subroutine rzero
250
252 subroutine izero(a, n)
253 integer, intent(in) :: n
254 integer, dimension(n), intent(inout) :: a
255 integer :: i
256
257 !$omp parallel do
258 do i = 1, n
259 a(i) = 0
260 end do
261 !$omp end parallel do
262
263 end subroutine izero
264
266 subroutine row_zero(a, m, n, e)
267 integer, intent(in) :: m, n, e
268 real(kind=rp), intent(inout) :: a(m,n)
269 integer :: j
270
271 !$omp parallel do
272 do j = 1, n
273 a(e,j) = 0.0_rp
274 end do
275 !$omp end parallel do
276
277 end subroutine row_zero
278
280 subroutine rone(a, n)
281 integer, intent(in) :: n
282 real(kind=rp), dimension(n), intent(inout) :: a
283 integer :: i
284
285 !$omp parallel do
286 do i = 1, n
287 a(i) = 1.0_rp
288 end do
289 !$omp end parallel do
290
291 end subroutine rone
292
294 subroutine copy(a, b, n)
295 integer, intent(in) :: n
296 real(kind=rp), dimension(n), intent(in) :: b
297 real(kind=rp), dimension(n), intent(inout) :: a
298 integer :: i
299
300 !$omp parallel do
301 do i = 1, n
302 a(i) = b(i)
303 end do
304 !$omp end parallel do
305
306 end subroutine copy
307
315 subroutine masked_copy_0(a, b, mask, n, n_mask)
316 integer, intent(in) :: n, n_mask
317 real(kind=rp), dimension(n), intent(in) :: b
318 real(kind=rp), dimension(n), intent(inout) :: a
319 integer, dimension(0:n_mask) :: mask
320 integer :: i, j
321
322 !$omp parallel do private(i, j)
323 do i = 1, n_mask
324 j = mask(i)
325 a(j) = b(j)
326 end do
327 !$omp end parallel do
328
329 end subroutine masked_copy_0
330
338 subroutine masked_copy(a, b, mask, n, n_mask)
339 integer, intent(in) :: n, n_mask
340 real(kind=rp), dimension(n), intent(in) :: b
341 real(kind=rp), dimension(n), intent(inout) :: a
342 integer, dimension(n_mask) :: mask
343 integer :: i, j
344
345 !$omp parallel do private(i, j)
346 do i = 1, n_mask
347 j = mask(i)
348 a(j) = b(j)
349 end do
350 !$omp end parallel do
351
352 end subroutine masked_copy
353
363 subroutine masked_gather_copy_0(a, b, mask, n, n_mask)
364 integer, intent(in) :: n, n_mask
365 real(kind=rp), dimension(n), intent(in) :: b
366 real(kind=rp), dimension(n_mask), intent(inout) :: a
367 integer, dimension(0:n_mask) :: mask
368 integer :: i, j
369
370 !$omp parallel do private(i, j)
371 do i = 1, n_mask
372 j = mask(i)
373 a(i) = b(j)
374 end do
375 !$omp end parallel do
376
377 end subroutine masked_gather_copy_0
378
388 subroutine face_masked_gather_copy_0(a, b, mask, facet, lx, ly, lz, n_mask)
389 integer, intent(in) :: lx, ly, lz, n_mask
390 real(kind=rp), dimension(n_mask), intent(inout) :: a
391 real(kind=rp), dimension(:, :, :, :), intent(in) :: b
392 integer, dimension(0:n_mask), intent(in) :: mask
393 integer, dimension(0:n_mask), intent(in) :: facet
394 integer :: l
395 integer :: idx(4)
396
397 !$omp parallel do private(l, idx)
398 do l = 1, n_mask
399 idx = nonlinear_index(mask(l), lx, ly, lz)
400
401 select case (facet(l))
402 case (1, 2)
403 a(l) = b(idx(2), idx(3), facet(l), idx(4))
404 case (3, 4)
405 a(l) = b(idx(1), idx(3), facet(l), idx(4))
406 case (5, 6)
407 a(l) = b(idx(1), idx(2), facet(l), idx(4))
408 end select
409 end do
410 !$omp end parallel do
411
412 end subroutine face_masked_gather_copy_0
413
423 subroutine masked_gather_copy(a, b, mask, n, n_mask)
424 integer, intent(in) :: n, n_mask
425 real(kind=rp), dimension(n), intent(in) :: b
426 real(kind=rp), dimension(n_mask), intent(inout) :: a
427 integer, dimension(n_mask) :: mask
428 integer :: i, j
429
430 !$omp parallel do private(i, j)
431 do i = 1, n_mask
432 j = mask(i)
433 a(i) = b(j)
434 end do
435 !$omp end parallel do
436
437 end subroutine masked_gather_copy
438
448 subroutine masked_scatter_copy_0(a, b, mask, n, n_mask)
449 integer, intent(in) :: n, n_mask
450 real(kind=rp), dimension(n_mask), intent(in) :: b
451 real(kind=rp), dimension(n), intent(inout) :: a
452 integer, dimension(0:n_mask) :: mask
453 integer :: i, j
454
455 !$omp parallel do private(i, j)
456 do i = 1, n_mask
457 j = mask(i)
458 a(j) = b(i)
459 end do
460 !$omp end parallel do
461
462 end subroutine masked_scatter_copy_0
463
473 subroutine masked_scatter_copy(a, b, mask, n, n_mask)
474 integer, intent(in) :: n, n_mask
475 real(kind=rp), dimension(n_mask), intent(in) :: b
476 real(kind=rp), dimension(n), intent(inout) :: a
477 integer, dimension(n_mask) :: mask
478 integer :: i, j
479
480 !$omp parallel do private(i, j)
481 do i = 1, n_mask
482 j = mask(i)
483 a(j) = b(i)
484 end do
485 !$omp end parallel do
486
487 end subroutine masked_scatter_copy
488
491 subroutine cfill_mask(a, c, n, mask, n_mask)
492 integer, intent(in) :: n, n_mask
493 real(kind=rp), dimension(n), intent(inout) :: a
494 real(kind=rp), intent(in) :: c
495 integer, dimension(n_mask), intent(in) :: mask
496 integer :: i
497
498 !$omp parallel do
499 do i = 1, n_mask
500 a(mask(i)) = c
501 end do
502 !$omp end parallel do
503
504 end subroutine cfill_mask
505
507 subroutine cmult(a, c, n)
508 integer, intent(in) :: n
509 real(kind=rp), dimension(n), intent(inout) :: a
510 real(kind=rp), intent(in) :: c
511 integer :: i
512
513 !$omp parallel do
514 do i = 1, n
515 a(i) = c * a(i)
516 end do
517 !$omp end parallel do
518
519 end subroutine cmult
520
522 subroutine cmult2(a, b, c, n)
523 integer, intent(in) :: n
524 real(kind=rp), dimension(n), intent(inout) :: a
525 real(kind=rp), dimension(n), intent(in) :: b
526 real(kind=rp), intent(in) :: c
527 integer :: i
528
529 !$omp parallel do
530 do i = 1, n
531 a(i) = c * b(i)
532 end do
533 !$omp end parallel do
534
535 end subroutine cmult2
536
538 subroutine cdiv(a, c, n)
539 integer, intent(in) :: n
540 real(kind=rp), dimension(n), intent(inout) :: a
541 real(kind=rp), intent(in) :: c
542 integer :: i
543
544 !$omp parallel do
545 do i = 1, n
546 a(i) = c / a(i)
547 end do
548 !$omp end parallel do
549
550 end subroutine cdiv
551
553 subroutine cdiv2(a, b, c, n)
554 integer, intent(in) :: n
555 real(kind=rp), dimension(n), intent(inout) :: a
556 real(kind=rp), dimension(n), intent(in) :: b
557 real(kind=rp), intent(in) :: c
558 integer :: i
559
560 !$omp parallel do
561 do i = 1, n
562 a(i) = c / b(i)
563 end do
564 !$omp end parallel do
565
566 end subroutine cdiv2
567
569 subroutine cadd(a, s, n)
570 integer, intent(in) :: n
571 real(kind=rp), dimension(n), intent(inout) :: a
572 real(kind=rp), intent(in) :: s
573 integer :: i
574
575 !$omp parallel do
576 do i = 1, n
577 a(i) = a(i) + s
578 end do
579 !$omp end parallel do
580
581 end subroutine cadd
582
584 subroutine cadd2(a, b, s, n)
585 integer, intent(in) :: n
586 real(kind=rp), dimension(n), intent(inout) :: a
587 real(kind=rp), dimension(n), intent(in) :: b
588 real(kind=rp), intent(in) :: s
589 integer :: i
590
591 !$omp parallel do
592 do i = 1,n
593 a(i) = b(i) + s
594 end do
595 !$omp end parallel do
596
597 end subroutine cadd2
598
600 subroutine cfill(a, c, n)
601 integer, intent(in) :: n
602 real(kind=rp), dimension(n), intent(inout) :: a
603 real(kind=rp), intent(in) :: c
604 integer :: i
605
606 !$omp parallel do
607 do i = 1, n
608 a(i) = c
609 end do
610 !$omp end parallel do
611
612 end subroutine cfill
613
615 subroutine cwrap(a, min_val, max_val, n)
616 integer, intent(in) :: n
617 real(kind=rp), dimension(n), intent(inout) :: a
618 real(kind=rp), intent(in) :: min_val, max_val
619 integer :: i
620
621 if (n .lt. 1 .or. max_val .le. min_val) return
622
623 !$omp parallel do
624 do i = 1, n
625 a(i) = modulo(a(i) - min_val, max_val - min_val) + min_val
626 end do
627 !$omp end parallel do
628
629 end subroutine cwrap
630
632 function glsum(a, n)
633 integer, intent(in) :: n
634 real(kind=rp), dimension(n) :: a
635 real(kind=rp) :: glsum
636 real(kind=xp) :: tmp
637 integer :: i, ierr
638
639 tmp = 0.0_rp
640 !$omp parallel do reduction(+:tmp)
641 do i = 1, n
642 tmp = tmp + a(i)
643 end do
644 !$omp end parallel do
645
646 call mpi_allreduce(mpi_in_place, tmp, 1, &
647 mpi_extra_precision, mpi_sum, neko_comm, ierr)
648 glsum = tmp
649
650 end function glsum
651
653 function glmax(a, n)
654 integer, intent(in) :: n
655 real(kind=rp), dimension(n) :: a
656 real(kind=rp) :: tmp, glmax
657 integer :: i, ierr
658
659 tmp = -huge(0.0_rp)
660 !$omp parallel do reduction(max:tmp)
661 do i = 1, n
662 tmp = max(tmp,a(i))
663 end do
664 !$omp end parallel do
665
666 call mpi_allreduce(tmp, glmax, 1, &
667 mpi_real_precision, mpi_max, neko_comm, ierr)
668
669 end function glmax
670
673 function glamax(a, n)
674 integer, intent(in) :: n
675 real(kind=rp), dimension(n) :: a
676 real(kind=rp) :: tmp, glamax
677 integer :: i, ierr
678
679 tmp = 0.0_rp
680 !$omp parallel do reduction(max:tmp)
681 do i = 1, n
682 tmp = max(tmp, abs(a(i)))
683 end do
684 !$omp end parallel do
685
686 call mpi_allreduce(tmp, glamax, 1, &
687 mpi_real_precision, mpi_max, neko_comm, ierr)
688
689 end function glamax
690
692 function glimax(a, n)
693 integer, intent(in) :: n
694 integer, dimension(n) :: a
695 integer :: tmp, glimax
696 integer :: i, ierr
697
698 tmp = -huge(0)
699 !$omp parallel do reduction(max:tmp)
700 do i = 1, n
701 tmp = max(tmp,a(i))
702 end do
703 !$omp end parallel do
704
705 call mpi_allreduce(tmp, glimax, 1, &
706 mpi_integer, mpi_max, neko_comm, ierr)
707
708 end function glimax
709
711 function glmin(a, n)
712 integer, intent(in) :: n
713 real(kind=rp), dimension(n) :: a
714 real(kind=rp) :: tmp, glmin
715 integer :: i, ierr
716
717 tmp = huge(0.0_rp)
718 !$omp parallel do reduction(min:tmp)
719 do i = 1, n
720 tmp = min(tmp,a(i))
721 end do
722 !$omp end parallel do
723
724 call mpi_allreduce(tmp, glmin, 1, &
725 mpi_real_precision, mpi_min, neko_comm, ierr)
726
727 end function glmin
728
730 function glimin(a, n)
731 integer, intent(in) :: n
732 integer, dimension(n) :: a
733 integer :: tmp, glimin
734 integer :: i, ierr
735
736 tmp = huge(0)
737 !$omp parallel do reduction(min:tmp)
738 do i = 1, n
739 tmp = min(tmp,a(i))
740 end do
741 !$omp end parallel do
742
743 call mpi_allreduce(tmp, glimin, 1, &
744 mpi_integer, mpi_min, neko_comm, ierr)
745
746 end function glimin
747
749 subroutine chsign(a, n)
750 integer, intent(in) :: n
751 real(kind=rp), dimension(n), intent(inout) :: a
752 integer :: i
753
754 !$omp parallel do
755 do i = 1, n
756 a(i) = -a(i)
757 end do
758 !$omp end parallel do
759
760 end subroutine chsign
761
763 function vlamax(vec,n) result(tamax)
764 integer :: n, i
765 real(kind=rp), intent(in) :: vec(n)
766 real(kind=rp) :: tamax
767
768 tamax = 0.0_rp
769 !$omp parallel do reduction(max:tamax)
770 do i = 1, n
771 tamax = max(tamax, abs(vec(i)))
772 end do
773 !$omp end parallel do
774
775 end function vlamax
776
778 function vlmax(vec,n) result(tmax)
779 integer :: n, i
780 real(kind=rp), intent(in) :: vec(n)
781 real(kind=rp) :: tmax
782
783 tmax = real(-99d20, rp)
784 !$omp parallel do reduction(max:tmax)
785 do i = 1, n
786 tmax = max(tmax, vec(i))
787 end do
788 !$omp end parallel do
789
790 end function vlmax
791
793 function vlmin(vec,n) result(tmin)
794 integer, intent(in) :: n
795 real(kind=rp), intent(in) :: vec(n)
796 real(kind=rp) :: tmin
797 integer :: i
798
799 tmin = real(99.0e20, rp)
800 !$omp parallel do reduction(min:tmin)
801 do i = 1, n
802 tmin = min(tmin, vec(i))
803 end do
804 !$omp end parallel do
805
806 end function vlmin
807
809 subroutine invcol1(a, n)
810 integer, intent(in) :: n
811 real(kind=rp), dimension(n), intent(inout) :: a
812 integer :: i
813
814 !$omp parallel do
815 do i = 1, n
816 a(i) = 1.0_xp / real(a(i), xp)
817 end do
818 !$omp end parallel do
819
820 end subroutine invcol1
821
823 subroutine invcol3(a, b, c, n)
824 integer, intent(in) :: n
825 real(kind=rp), dimension(n), intent(inout) :: a
826 real(kind=rp), dimension(n), intent(in) :: b, c
827 integer :: i
828
829 !$omp parallel do
830 do i = 1, n
831 a(i) = real(b(i), xp) / c(i)
832 end do
833 !$omp end parallel do
834
835 end subroutine invcol3
836
838 subroutine invers2(a, b, n)
839 integer, intent(in) :: n
840 real(kind=rp), dimension(n), intent(inout) :: a
841 real(kind=rp), dimension(n), intent(in) :: b
842 integer :: i
843
844 !$omp parallel do
845 do i = 1, n
846 a(i) = 1.0_xp / real(b(i), xp)
847 end do
848 !$omp end parallel do
849
850 end subroutine invers2
851
854 subroutine vcross(u1, u2, u3, v1, v2, v3, w1, w2, w3, n)
855 integer, intent(in) :: n
856 real(kind=rp), dimension(n), intent(in) :: v1, v2, v3
857 real(kind=rp), dimension(n), intent(in) :: w1, w2, w3
858 real(kind=rp), dimension(n), intent(out) :: u1, u2, u3
859 integer :: i
860
861 !$omp parallel do
862 do i = 1, n
863 u1(i) = v2(i)*w3(i) - v3(i)*w2(i)
864 u2(i) = v3(i)*w1(i) - v1(i)*w3(i)
865 u3(i) = v1(i)*w2(i) - v2(i)*w1(i)
866 end do
867 !$omp end parallel do
868
869 end subroutine vcross
870
873 subroutine vdot2(dot, u1, u2, v1, v2, n)
874 integer, intent(in) :: n
875 real(kind=rp), dimension(n), intent(in) :: u1, u2
876 real(kind=rp), dimension(n), intent(in) :: v1, v2
877 real(kind=rp), dimension(n), intent(out) :: dot
878 integer :: i
879
880 !$omp parallel do
881 do i = 1, n
882 dot(i) = u1(i)*v1(i) + u2(i)*v2(i)
883 end do
884 !$omp end parallel do
885
886 end subroutine vdot2
887
890 subroutine vdot3(dot, u1, u2, u3, v1, v2, v3, n)
891 integer, intent(in) :: n
892 real(kind=rp), dimension(n), intent(in) :: u1, u2, u3
893 real(kind=rp), dimension(n), intent(in) :: v1, v2, v3
894 real(kind=rp), dimension(n), intent(out) :: dot
895 integer :: i
896
897 !$omp parallel do
898 do i = 1, n
899 dot(i) = u1(i)*v1(i) + u2(i)*v2(i) + u3(i)*v3(i)
900 end do
901 !$omp end parallel do
902
903 end subroutine vdot3
904
906 function vlsc3(u, v, w, n) result(s)
907 integer, intent(in) :: n
908 real(kind=rp), dimension(n), intent(in) :: u, v, w
909 real(kind=rp) :: s
910 integer :: i
911
912 s = 0.0_rp
913 !$omp parallel do reduction(+:s)
914 do i = 1, n
915 s = s + u(i)*v(i)*w(i)
916 end do
917 !$omp end parallel do
918
919 end function vlsc3
920
922 function vlsc2(u, v, n) result(s)
923 integer, intent(in) :: n
924 real(kind=rp), dimension(n), intent(in) :: u, v
925 real(kind=rp) :: s
926 integer :: i
927
928 s = 0.0_rp
929 !$omp parallel do reduction(+:s)
930 do i = 1, n
931 s = s + u(i)*v(i)
932 end do
933 !$omp end parallel do
934
935 end function vlsc2
936
938 subroutine add2(a, b, n)
939 integer, intent(in) :: n
940 real(kind=rp), dimension(n), intent(inout) :: a
941 real(kind=rp), dimension(n), intent(in) :: b
942 integer :: i
943
944 !$omp parallel do
945 do i = 1, n
946 a(i) = a(i) + b(i)
947 end do
948 !$omp end parallel do
949
950 end subroutine add2
951
953 subroutine add3(a, b, c, n)
954 integer, intent(in) :: n
955 real(kind=rp), dimension(n), intent(inout) :: a
956 real(kind=rp), dimension(n), intent(in) :: b
957 real(kind=rp), dimension(n), intent(in) :: c
958 integer :: i
959
960 !$omp parallel do
961 do i = 1, n
962 a(i) = b(i) + c(i)
963 end do
964 !$omp end parallel do
965
966 end subroutine add3
967
969 subroutine add4(a, b, c, d, n)
970 integer, intent(in) :: n
971 real(kind=rp), dimension(n), intent(out) :: a
972 real(kind=rp), dimension(n), intent(in) :: d
973 real(kind=rp), dimension(n), intent(in) :: c
974 real(kind=rp), dimension(n), intent(in) :: b
975 integer :: i
976
977 !$omp parallel do
978 do i = 1, n
979 a(i) = b(i) + c(i) + d(i)
980 end do
981 !$omp end parallel do
982
983 end subroutine add4
984
986 subroutine sub2(a, b, n)
987 integer, intent(in) :: n
988 real(kind=rp), dimension(n), intent(inout) :: a
989 real(kind=rp), dimension(n), intent(in) :: b
990 integer :: i
991
992 !$omp parallel do
993 do i = 1, n
994 a(i) = a(i) - b(i)
995 end do
996 !$omp end parallel do
997
998 end subroutine sub2
999
1001 subroutine sub3(a, b, c, n)
1002 integer, intent(in) :: n
1003 real(kind=rp), dimension(n), intent(inout) :: a
1004 real(kind=rp), dimension(n), intent(in) :: b
1005 real(kind=rp), dimension(n), intent(in) :: c
1006 integer :: i
1007
1008 !$omp parallel do
1009 do i = 1, n
1010 a(i) = b(i) - c(i)
1011 end do
1012 !$omp end parallel do
1013
1014 end subroutine sub3
1015
1016
1019 subroutine add2s1(a, b, c1, n)
1020 integer, intent(in) :: n
1021 real(kind=rp), dimension(n), intent(inout) :: a
1022 real(kind=rp), dimension(n), intent(in) :: b
1023 real(kind=rp), intent(in) :: c1
1024 integer :: i
1025
1026 !$omp parallel do
1027 do i = 1, n
1028 a(i) = c1 * a(i) + b(i)
1029 end do
1030 !$omp end parallel do
1031
1032 end subroutine add2s1
1033
1036 subroutine add2s2(a, b, c1, n)
1037 integer, intent(in) :: n
1038 real(kind=rp), dimension(n), intent(inout) :: a
1039 real(kind=rp), dimension(n), intent(in) :: b
1040 real(kind=rp), intent(in) :: c1
1041 integer :: i
1042
1043 !$omp parallel do
1044 do i = 1, n
1045 a(i) = a(i) + c1 * b(i)
1046 end do
1047 !$omp end parallel do
1048
1049 end subroutine add2s2
1050
1052 subroutine addsqr2s2(a, b, c1, n)
1053 integer, intent(in) :: n
1054 real(kind=rp), dimension(n), intent(inout) :: a
1055 real(kind=rp), dimension(n), intent(in) :: b
1056 real(kind=rp), intent(in) :: c1
1057 integer :: i
1058
1059 !$omp parallel do
1060 do i = 1, n
1061 a(i) = a(i) + c1 * ( b(i) * b(i) )
1062 end do
1063 !$omp end parallel do
1064
1065 end subroutine addsqr2s2
1066
1068 subroutine invcol2(a, b, n)
1069 integer, intent(in) :: n
1070 real(kind=rp), dimension(n), intent(inout) :: a
1071 real(kind=rp), dimension(n), intent(in) :: b
1072 integer :: i
1073
1074 !$omp parallel do
1075 do i = 1, n
1076 a(i) = real(a(i), xp) / b(i)
1077 end do
1078 !$omp end parallel do
1079
1080 end subroutine invcol2
1081
1082
1084 subroutine col2(a, b, n)
1085 integer, intent(in) :: n
1086 real(kind=rp), dimension(n), intent(inout) :: a
1087 real(kind=rp), dimension(n), intent(in) :: b
1088 integer :: i
1089
1090 !$omp parallel do
1091 do i = 1, n
1092 a(i) = a(i) * b(i)
1093 end do
1094 !$omp end parallel do
1095
1096 end subroutine col2
1097
1099 subroutine col3(a, b, c, n)
1100 integer, intent(in) :: n
1101 real(kind=rp), dimension(n), intent(inout) :: a
1102 real(kind=rp), dimension(n), intent(in) :: b
1103 real(kind=rp), dimension(n), intent(in) :: c
1104 integer :: i
1105
1106 !$omp parallel do
1107 do i = 1, n
1108 a(i) = b(i) * c(i)
1109 end do
1110 !$omp end parallel do
1111
1112 end subroutine col3
1113
1115 subroutine subcol3(a, b, c, n)
1116 integer, intent(in) :: n
1117 real(kind=rp), dimension(n), intent(inout) :: a
1118 real(kind=rp), dimension(n), intent(in) :: b
1119 real(kind=rp), dimension(n), intent(in) :: c
1120 integer :: i
1121
1122 !$omp parallel do
1123 do i = 1, n
1124 a(i) = a(i) - b(i) * c(i)
1125 end do
1126 !$omp end parallel do
1127
1128 end subroutine subcol3
1129
1131 subroutine add3s2(a, b, c, c1, c2 ,n)
1132 integer, intent(in) :: n
1133 real(kind=rp), dimension(n), intent(inout) :: a
1134 real(kind=rp), dimension(n), intent(in) :: b
1135 real(kind=rp), dimension(n), intent(in) :: c
1136 real(kind=rp), intent(in) :: c1, c2
1137 integer :: i
1138
1139 !$omp parallel do
1140 do i = 1, n
1141 a(i) = c1 * b(i) + c2 * c(i)
1142 end do
1143 !$omp end parallel do
1144
1145 end subroutine add3s2
1146
1148 subroutine add4s3(a, b, c, d, c1, c2, c3, n)
1149 integer, intent(in) :: n
1150 real(kind=rp), dimension(n), intent(inout) :: a
1151 real(kind=rp), dimension(n), intent(in) :: b
1152 real(kind=rp), dimension(n), intent(in) :: c
1153 real(kind=rp), dimension(n), intent(in) :: d
1154 real(kind=rp), intent(in) :: c1, c2, c3
1155 integer :: i
1156
1157 !$omp parallel do
1158 do i = 1, n
1159 a(i) = c1 * b(i) + c2 * c(i) + c3 * d(i)
1160 end do
1161 !$omp end parallel do
1162
1163 end subroutine add4s3
1164
1166 subroutine add5s4(a, b, c, d, e, c1, c2, c3, c4, n)
1167 integer, intent(in) :: n
1168 real(kind=rp), dimension(n), intent(inout) :: a
1169 real(kind=rp), dimension(n), intent(in) :: b
1170 real(kind=rp), dimension(n), intent(in) :: c
1171 real(kind=rp), dimension(n), intent(in) :: d
1172 real(kind=rp), dimension(n), intent(in) :: e
1173 real(kind=rp), intent(in) :: c1, c2, c3, c4
1174 integer :: i
1175
1176 !$omp parallel do
1177 do i = 1, n
1178 a(i) = a(i) + c1 * b(i) + c2 * c(i) + c3 * d(i) + c4 * e(i)
1179 end do
1180 !$omp end parallel do
1181
1182 end subroutine add5s4
1183
1185 subroutine subcol4(a, b, c, d, n)
1186 integer, intent(in) :: n
1187 real(kind=rp), dimension(n), intent(inout) :: a
1188 real(kind=rp), dimension(n), intent(in) :: b
1189 real(kind=rp), dimension(n), intent(in) :: c
1190 real(kind=rp), dimension(n), intent(in) :: d
1191 integer :: i
1192
1193 !$omp parallel do
1194 do i = 1, n
1195 a(i) = a(i) - b(i) * c(i) * d(i)
1196 end do
1197 !$omp end parallel do
1198
1199 end subroutine subcol4
1200
1202 subroutine addcol3(a, b, c, n)
1203 integer, intent(in) :: n
1204 real(kind=rp), dimension(n), intent(inout) :: a
1205 real(kind=rp), dimension(n), intent(in) :: b
1206 real(kind=rp), dimension(n), intent(in) :: c
1207 integer :: i
1208
1209 !$omp parallel do
1210 do i = 1, n
1211 a(i) = a(i) + b(i) * c(i)
1212 end do
1213 !$omp end parallel do
1214
1215 end subroutine addcol3
1216
1218 subroutine addcol4(a, b, c, d, n)
1219 integer, intent(in) :: n
1220 real(kind=rp), dimension(n), intent(inout) :: a
1221 real(kind=rp), dimension(n), intent(in) :: b
1222 real(kind=rp), dimension(n), intent(in) :: c
1223 real(kind=rp), dimension(n), intent(in) :: d
1224 integer :: i
1225
1226 !$omp parallel do
1227 do i = 1, n
1228 a(i) = a(i) + b(i) * c(i) * d(i)
1229 end do
1230 !$omp end parallel do
1231
1232 end subroutine addcol4
1233
1235 subroutine addcol3s2(a, b, c, s, n)
1236 integer, intent(in) :: n
1237 real(kind=rp), dimension(n), intent(inout) :: a
1238 real(kind=rp), dimension(n), intent(in) :: b
1239 real(kind=rp), dimension(n), intent(in) :: c
1240 real(kind=rp), intent(in) :: s
1241 integer :: i
1242
1243 !$omp parallel do
1244 do i = 1, n
1245 a(i) = a(i) + s * b(i) * c(i)
1246 end do
1247 !$omp end parallel do
1248
1249 end subroutine addcol3s2
1250
1252 subroutine ascol5(a, b, c, d, e, n)
1253 integer, intent(in) :: n
1254 real(kind=rp), dimension(n), intent(inout) :: a
1255 real(kind=rp), dimension(n), intent(in) :: b
1256 real(kind=rp), dimension(n), intent(in) :: c
1257 real(kind=rp), dimension(n), intent(in) :: d
1258 real(kind=rp), dimension(n), intent(in) :: e
1259 integer :: i
1260
1261 !$omp parallel do
1262 do i = 1, n
1263 a(i) = b(i)*c(i) - d(i)*e(i)
1264 end do
1265 !$omp end parallel do
1266
1267 end subroutine ascol5
1268
1270 subroutine p_update(a, b, c, c1, c2, n)
1271 integer, intent(in) :: n
1272 real(kind=rp), dimension(n), intent(inout) :: a
1273 real(kind=rp), dimension(n), intent(in) :: b
1274 real(kind=rp), dimension(n), intent(in) :: c
1275 real(kind=rp), intent(in) :: c1, c2
1276 integer :: i
1277
1278 !$omp parallel do
1279 do i = 1, n
1280 a(i) = b(i) + c1*(a(i)-c2*c(i))
1281 end do
1282 !$omp end parallel do
1283
1284 end subroutine p_update
1285
1287 subroutine x_update(a, b, c, c1, c2, n)
1288 integer, intent(in) :: n
1289 real(kind=rp), dimension(n), intent(inout) :: a
1290 real(kind=rp), dimension(n), intent(in) :: b
1291 real(kind=rp), dimension(n), intent(in) :: c
1292 real(kind=rp), intent(in) :: c1, c2
1293 integer :: i
1294
1295 !$omp parallel do
1296 do i = 1, n
1297 a(i) = a(i) + c1*b(i)+c2*c(i)
1298 end do
1299 !$omp end parallel do
1300
1301 end subroutine x_update
1302
1304 function glsc2(a, b, n)
1305 integer, intent(in) :: n
1306 real(kind=rp), dimension(n), intent(in) :: a
1307 real(kind=rp), dimension(n), intent(in) :: b
1308 real(kind=rp) :: glsc2
1309 real(kind=xp) :: tmp
1310 integer :: i, ierr
1311
1312 tmp = 0.0_xp
1313 !$omp parallel do reduction(+:tmp)
1314 do i = 1, n
1315 tmp = tmp + a(i) * b(i)
1316 end do
1317 !$omp end parallel do
1318
1319 call mpi_allreduce(mpi_in_place, tmp, 1, &
1320 mpi_extra_precision, mpi_sum, neko_comm, ierr)
1321 glsc2 = tmp
1322 end function glsc2
1323
1325 function glsc3(a, b, c, n)
1326 integer, intent(in) :: n
1327 real(kind=rp), dimension(n), intent(in) :: a
1328 real(kind=rp), dimension(n), intent(in) :: b
1329 real(kind=rp), dimension(n), intent(in) :: c
1330 real(kind=rp) :: glsc3
1331 real(kind=xp) :: tmp
1332 integer :: i, ierr
1333
1334 tmp = 0.0_xp
1335 !$omp parallel do reduction(+:tmp)
1336 do i = 1, n
1337 tmp = tmp + a(i) * b(i) * c(i)
1338 end do
1339 !$omp end parallel do
1340
1341 call mpi_allreduce(mpi_in_place, tmp, 1, &
1342 mpi_extra_precision, mpi_sum, neko_comm, ierr)
1343 glsc3 = tmp
1344
1345 end function glsc3
1346 function glsc4(a, b, c, d, n)
1347 integer, intent(in) :: n
1348 real(kind=rp), dimension(n), intent(in) :: a
1349 real(kind=rp), dimension(n), intent(in) :: b
1350 real(kind=rp), dimension(n), intent(in) :: c
1351 real(kind=rp), dimension(n), intent(in) :: d
1352 real(kind=rp) :: glsc4
1353 real(kind=xp) :: tmp
1354 integer :: i, ierr
1355
1356 tmp = 0.0_xp
1357 !$omp parallel do reduction(+:tmp)
1358 do i = 1, n
1359 tmp = tmp + a(i) * b(i) * c(i) * d(i)
1360 end do
1361 !$omp end parallel do
1362
1363 call mpi_allreduce(mpi_in_place, tmp, 1, &
1364 mpi_extra_precision, mpi_sum, neko_comm, ierr)
1365 glsc4 = tmp
1366
1367 end function glsc4
1368
1371 function glsubnorm(a, b, n)
1372 integer, intent(in) :: n
1373 real(kind=rp), dimension(n), intent(in) :: a
1374 real(kind=rp), dimension(n), intent(in) :: b
1375 real(kind=rp) :: glsubnorm
1376 real(kind=xp) :: tmp
1377 integer :: i, ierr
1378
1379 tmp = 0.0_xp
1380 !$omp parallel do reduction(+:tmp)
1381 do i = 1, n
1382 tmp = tmp + (a(i) - b(i))**2
1383 end do
1384 !$omp end parallel do
1385
1386 call mpi_allreduce(mpi_in_place, tmp, 1, &
1387 mpi_extra_precision, mpi_sum, neko_comm, ierr)
1388 glsubnorm = sqrt(tmp)
1389
1390 end function glsubnorm
1391
1397 subroutine sortrp(a, ind, n)
1398 integer, intent(in) :: n
1399 real(kind=rp), intent(inout) :: a(n)
1400 integer, intent(out) :: ind(n)
1401 real(kind=rp) :: aa
1402 integer :: j, ir, i, ii, l
1403
1404 do j = 1, n
1405 ind(j) = j
1406 end do
1407
1408 if (n .le. 1) return
1409
1410
1411 l = n/2+1
1412 ir = n
1413 do while (.true.)
1414 if (l .gt. 1) then
1415 l = l-1
1416 aa = a(l)
1417 ii = ind(l)
1418 else
1419 aa = a(ir)
1420 ii = ind(ir)
1421 a(ir) = a(1)
1422 ind(ir) = ind(1)
1423 ir = ir - 1
1424 if (ir .eq. 1) then
1425 a(1) = aa
1426 ind(1) = ii
1427 return
1428 end if
1429 end if
1430 i = l
1431 j = l+l
1432 do while (j .le. ir)
1433 if (j .lt. ir) then
1434 if ( a(j) .lt. a(j+1) ) j = j + 1
1435 end if
1436 if (aa .lt. a(j)) then
1437 a(i) = a(j)
1438 ind(i) = ind(j)
1439 i = j
1440 j = j+j
1441 else
1442 j = ir+1
1443 end if
1444 end do
1445 a(i) = aa
1446 ind(i) = ii
1447 end do
1448 end subroutine sortrp
1449
1455 subroutine sorti4(a, ind, n)
1456 integer, intent(in) :: n
1457 integer(i4), intent(inout) :: a(n)
1458 integer, intent(out) :: ind(n)
1459 integer(i4) :: aa
1460 integer :: j, ir, i, ii, l
1461
1462 do j = 1, n
1463 ind(j) = j
1464 end do
1465
1466 if (n .le. 1) return
1467
1468 l = n/2+1
1469 ir = n
1470 do while (.true.)
1471 if (l .gt. 1) then
1472 l = l - 1
1473 aa = a(l)
1474 ii = ind(l)
1475 else
1476 aa = a(ir)
1477 ii = ind(ir)
1478 a(ir) = a( 1)
1479 ind(ir) = ind( 1)
1480 ir = ir - 1
1481 if (ir .eq. 1) then
1482 a(1) = aa
1483 ind(1) = ii
1484 return
1485 end if
1486 end if
1487 i = l
1488 j = l + l
1489 do while (j .le. ir)
1490 if (j .lt. ir) then
1491 if ( a(j) .lt. a(j + 1) ) j = j + 1
1492 end if
1493 if (aa .lt. a(j)) then
1494 a(i) = a(j)
1495 ind(i) = ind(j)
1496 i = j
1497 j = j + j
1498 else
1499 j = ir + 1
1500 end if
1501 end do
1502 a(i) = aa
1503 ind(i) = ii
1504 end do
1505 end subroutine sorti4
1506
1511 subroutine swapdp(b, ind, n)
1512 integer, intent(in) :: n
1513 real(kind=rp), intent(inout) :: b(n)
1514 integer, intent(in) :: ind(n)
1515 real(kind=rp) :: temp(n)
1516 integer :: i, jj
1517
1518 !$omp parallel private(i, jj)
1519 !$omp do
1520 do i = 1, n
1521 temp(i) = b(i)
1522 end do
1523 !$omp end do
1524 !$omp do
1525 do i = 1, n
1526 jj = ind(i)
1527 b(i) = temp(jj)
1528 end do
1529 !$omp end do
1530 !$omp end parallel
1531
1532 end subroutine swapdp
1533
1538 subroutine swapi4(b, ind, n)
1539 integer, intent(in) :: n
1540 integer(i4), intent(inout) :: b(n)
1541 integer, intent(in) :: ind(n)
1542 integer(i4) :: temp(n)
1543 integer :: i, jj
1544
1545 !$omp parallel private(i, jj)
1546 !$omp do
1547 do i = 1, n
1548 temp(i) = b(i)
1549 end do
1550 !$omp end do
1551 !$omp do
1552 do i = 1, n
1553 jj = ind(i)
1554 b(i) = temp(jj)
1555 end do
1556 !$omp end do
1557 !$omp end parallel
1558
1559 end subroutine swapi4
1560
1565 subroutine reorddp(b, ind, n)
1566 integer, intent(in) :: n
1567 real(kind=rp), intent(inout) :: b(n)
1568 integer, intent(in) :: ind(n)
1569 real(kind=rp) :: temp(n)
1570 integer :: i, jj
1571
1572 !$omp parallel private(i, jj)
1573 !$omp do
1574 do i = 1, n
1575 temp(i) = b(i)
1576 end do
1577 !$omp end do
1578 !$omp do
1579 do i = 1, n
1580 jj = ind(i)
1581 b(jj) = temp(i)
1582 end do
1583 !$omp end do
1584 !$omp end parallel
1585
1586 end subroutine reorddp
1587
1592 subroutine reordi4(b, ind, n)
1593 integer, intent(in) :: n
1594 integer(i4), intent(inout) :: b(n)
1595 integer, intent(in) :: ind(n)
1596 integer(i4) :: temp(n)
1597 integer :: i, jj
1598
1599 !$omp parallel private(i, jj)
1600 !$omp do
1601 do i = 1, n
1602 temp(i) = b(i)
1603 end do
1604 !$omp end do
1605 !$omp do
1606 do i = 1, n
1607 jj = ind(i)
1608 b(jj) = temp(i)
1609 end do
1610 !$omp end do
1611 !$omp end parallel
1612
1613 end subroutine reordi4
1614
1619 subroutine flipvdp(b, ind, n)
1620 integer, intent(in) :: n
1621 real(kind=rp), intent(inout) :: b(n)
1622 integer, intent(inout) :: ind(n)
1623 real(kind=rp) :: temp(n)
1624 integer :: tempind(n)
1625 integer :: i, jj
1626
1627 !$omp parallel private(i, jj)
1628 !$omp do
1629 do i = 1, n
1630 jj = n+1-i
1631 temp(jj) = b(i)
1632 tempind(jj) = ind(i)
1633 end do
1634 !$omp end do
1635 !$omp do
1636 do i = 1,n
1637 b(i) = temp(i)
1638 ind(i) = tempind(i)
1639 end do
1640 !$omp end do
1641 !$omp end parallel
1642
1643 end subroutine flipvdp
1644
1649 subroutine flipvi4(b, ind, n)
1650 integer, intent(in) :: n
1651 integer(i4), intent(inout) :: b(n)
1652 integer, intent(inout) :: ind(n)
1653 integer(i4) :: temp(n)
1654 integer :: tempind(n)
1655 integer :: i, jj
1656
1657 !$omp parallel private(i, jj)
1658 !$omp do
1659 do i = 1, n
1660 jj = n+1-i
1661 temp(jj) = b(i)
1662 tempind(jj) = ind(i)
1663 end do
1664 !$omp end do
1665 !$omp do
1666 do i = 1,n
1667 b(i) = temp(i)
1668 ind(i) = tempind(i)
1669 end do
1670 !$omp end do
1671 !$omp end parallel
1672
1673 end subroutine flipvi4
1674
1678 subroutine absval(a, n)
1679 integer, intent(in) :: n
1680 real(kind=rp), dimension(n), intent(inout) :: a
1681 integer :: i
1682
1683 !$omp parallel do
1684 do i = 1, n
1685 a(i) = abs(a(i))
1686 end do
1687 !$omp end parallel do
1688
1689 end subroutine absval
1690
1691 ! ========================================================================== !
1692 ! Point-wise operations
1693
1695 subroutine pwmax2(a, b, n)
1696 integer, intent(in) :: n
1697 real(kind=rp), dimension(n), intent(inout) :: a
1698 real(kind=rp), dimension(n), intent(in) :: b
1699 integer :: i
1700
1701 !$omp parallel do
1702 do i = 1, n
1703 a(i) = max(a(i), b(i))
1704 end do
1705 !$omp end parallel do
1706
1707 end subroutine pwmax2
1708
1710 subroutine pwmax3(a, b, c, n)
1711 integer, intent(in) :: n
1712 real(kind=rp), dimension(n), intent(inout) :: a
1713 real(kind=rp), dimension(n), intent(in) :: b, c
1714 integer :: i
1715
1716 !$omp parallel do
1717 do i = 1, n
1718 a(i) = max(b(i), c(i))
1719 end do
1720 !$omp end parallel do
1721
1722 end subroutine pwmax3
1723
1725 subroutine cpwmax2(a, b, n)
1726 integer, intent(in) :: n
1727 real(kind=rp), dimension(n), intent(inout) :: a
1728 real(kind=rp), intent(in) :: b
1729 integer :: i
1730
1731 !$omp parallel do
1732 do i = 1, n
1733 a(i) = max(a(i), b)
1734 end do
1735 !$omp end parallel do
1736
1737 end subroutine cpwmax2
1738
1740 subroutine cpwmax3(a, b, c, n)
1741 integer, intent(in) :: n
1742 real(kind=rp), dimension(n), intent(inout) :: a
1743 real(kind=rp), dimension(n), intent(in) :: b
1744 real(kind=rp), intent(in) :: c
1745 integer :: i
1746
1747 !$omp parallel do
1748 do i = 1, n
1749 a(i) = max(b(i), c)
1750 end do
1751 !$omp end parallel do
1752
1753 end subroutine cpwmax3
1754
1756 subroutine pwmin2(a, b, n)
1757 integer, intent(in) :: n
1758 real(kind=rp), dimension(n), intent(inout) :: a
1759 real(kind=rp), dimension(n), intent(in) :: b
1760 integer :: i
1761
1762 !$omp parallel do
1763 do i = 1, n
1764 a(i) = min(a(i), b(i))
1765 end do
1766 !$omp end parallel do
1767
1768 end subroutine pwmin2
1769
1771 subroutine pwmin3(a, b, c, n)
1772 integer, intent(in) :: n
1773 real(kind=rp), dimension(n), intent(inout) :: a
1774 real(kind=rp), dimension(n), intent(in) :: b, c
1775 integer :: i
1776
1777 !$omp parallel do
1778 do i = 1, n
1779 a(i) = min(b(i), c(i))
1780 end do
1781 !$omp end parallel do
1782
1783 end subroutine pwmin3
1784
1786 subroutine cpwmin2(a, b, n)
1787 integer, intent(in) :: n
1788 real(kind=rp), dimension(n), intent(inout) :: a
1789 real(kind=rp), intent(in) :: b
1790 integer :: i
1791
1792 !$omp parallel do
1793 do i = 1, n
1794 a(i) = min(a(i), b)
1795 end do
1796 !$omp end parallel do
1797
1798 end subroutine cpwmin2
1799
1801 subroutine cpwmin3(a, b, c, n)
1802 integer, intent(in) :: n
1803 real(kind=rp), dimension(n), intent(inout) :: a
1804 real(kind=rp), dimension(n), intent(in) :: b
1805 real(kind=rp), intent(in) :: c
1806 integer :: i
1807
1808 !$omp parallel do
1809 do i = 1, n
1810 a(i) = min(b(i), c)
1811 end do
1812 !$omp end parallel do
1813
1814 end subroutine cpwmin3
1815
1816 ! M33INV and M44INV by David G. Simpson pure function version from
1817 ! https://fortranwiki.org/fortran/show/Matrix+inversion
1818 ! Invert 3x3 matrix
1819 function matinv39(a11, a12, a13, a21, a22, a23, a31, a32, a33) &
1820 result(b)
1821 real(kind=rp), intent(in) :: a11, a12, a13, a21, a22, a23, a31, a32, a33
1822 real(xp) :: a(3,3) !! Matrix
1823 real(rp) :: b(3,3) !! Inverse matrix
1824 a(1,1) = a11
1825 a(1,2) = a12
1826 a(1,3) = a13
1827 a(2,1) = a21
1828 a(2,2) = a22
1829 a(2,3) = a23
1830 a(3,1) = a31
1831 a(3,2) = a32
1832 a(3,3) = a33
1833 b = matinv3(a)
1834 end function matinv39
1835
1840 function matinv3(A) result(B)
1841 !! Performs a direct calculation of the inverse of a 3×3 matrix.
1842 real(kind=xp), intent(in) :: a(3,3) !! Matrix
1843 real(kind=xp) :: b(3,3) !! Inverse matrix
1844 real(kind=xp) :: detinv
1845
1846 ! Calculate the inverse determinant of the matrix
1847 ! first index x,y,z, second r, s, t
1848 detinv = 1.0_xp / real(a(1,1)*a(2,2)*a(3,3) - a(1,1)*a(2,3)*a(3,2) &
1849 - a(1,2)*a(2,1)*a(3,3) + a(1,2)*a(2,3)*a(3,1)&
1850 + a(1,3)*a(2,1)*a(3,2) - a(1,3)*a(2,2)*a(3,1), xp)
1851 ! Calculate the inverse of the matrix
1852 ! first index r, s, t, second x, y, z
1853 b(1,1) = +detinv * (a(2,2)*a(3,3) - a(2,3)*a(3,2))
1854 b(2,1) = -detinv * (a(2,1)*a(3,3) - a(2,3)*a(3,1))
1855 b(3,1) = +detinv * (a(2,1)*a(3,2) - a(2,2)*a(3,1))
1856 b(1,2) = -detinv * (a(1,2)*a(3,3) - a(1,3)*a(3,2))
1857 b(2,2) = +detinv * (a(1,1)*a(3,3) - a(1,3)*a(3,1))
1858 b(3,2) = -detinv * (a(1,1)*a(3,2) - a(1,2)*a(3,1))
1859 b(1,3) = +detinv * (a(1,2)*a(2,3) - a(1,3)*a(2,2))
1860 b(2,3) = -detinv * (a(1,1)*a(2,3) - a(1,3)*a(2,1))
1861 b(3,3) = +detinv * (a(1,1)*a(2,2) - a(1,2)*a(2,1))
1862 end function matinv3
1863
1866 function math_stepf(x) result(val)
1867 real(kind=rp), intent(in) :: x
1868 real(kind=rp) :: val
1869 real(kind=rp), parameter :: xdmin = 0.0001_rp
1870 real(kind=rp), parameter :: xdmax = 0.9999_rp
1871 real(kind=rp) :: g
1872
1873 if (x <= xdmin) then
1874 ! Below the lower bound, the function is 0
1875 val = 0.0_rp
1876 else if (x >= xdmax) then
1877 ! Above the upper bound, the function is 1
1878 val = 1.0_rp
1879 else
1880 ! g(x) = 1/(x-1) + 1/x
1881 g = (1.0_rp / (x - 1.0_rp)) + (1.0_rp / x)
1882
1883 ! The sigmoid: S(x) = 1 / (1 + exp(g))
1884 val = 1.0_rp / (1.0_rp + exp(g))
1885 end if
1886 end function math_stepf
1887
1889 function math_dstepf(x) result(val)
1890 real(kind=rp), intent(in) :: x
1891 real(kind=rp) :: val
1892 real(kind=rp), parameter :: xdmin = 0.0001_rp
1893 real(kind=rp), parameter :: xdmax = 0.9999_rp
1894 real(kind=rp) :: arg, g, dg, s_val
1895
1896 if (x <= xdmin .or. x >= xdmax) then
1897 val = 0.0_rp
1898 else
1899 ! The step function is S(x) = 1 / (1 + exp(g(x)))
1900 ! where g(x) = 1/(x-1) + 1/x
1901 ! S'(x) = -S(x) * (1 - S(x)) * g'(x)
1902
1903 g = (1.0_rp / (x - 1.0_rp)) + (1.0_rp / x)
1904
1905 ! Derivative of g(x)
1906 dg = -(1.0_rp / ((x - 1.0_rp)**2)) - (1.0_rp / (x**2))
1907
1908 ! Recompute S(x) locally
1909 s_val = 1.0_rp / (1.0_rp + exp(g))
1910
1911 val = -s_val * (1.0_rp - s_val) * dg
1912 end if
1913 end function math_dstepf
1914
1916 subroutine sqrt_inplace(a, n)
1917 integer, intent(in) :: n
1918 real(kind=rp), dimension(n), intent(inout) :: a
1919 integer :: i
1920
1921 !$omp parallel do
1922 do i = 1, n
1923 a(i) = sqrt(a(i))
1924 end do
1925 !$omp end parallel do
1926
1927 end subroutine sqrt_inplace
1928
1930 subroutine power(ap, a, p, n)
1931 integer, intent(in) :: n
1932 real(kind=rp), dimension(n), intent(inout) :: ap
1933 real(kind=rp), dimension(n), intent(in) :: a
1934 real(kind=rp), intent(in) :: p
1935 integer :: i
1936
1937 !$omp parallel do
1938 do i = 1, n
1939 ap(i) = a(i)**p
1940 end do
1941 !$omp end parallel do
1942
1943 end subroutine power
1944
1951 pure subroutine eig_sym2(a11, a22, a12, e1, e2)
1952 real(kind=dp), intent(in) :: a11, a22, a12
1953 real(kind=dp), intent(out) :: e1, e2
1954 real(kind=dp) :: t, d, s
1955
1956 t = a11 + a22
1957 d = a11 * a22 - a12 * a12
1958 s = sqrt(max(0.0_dp, 0.25_dp * t * t - d))
1959 e1 = 0.5_dp * t + s
1960
1961 if (e1 .gt. 0.0_dp) then
1962 e2 = d / e1
1963 else
1964 e2 = 0.5_dp * t - s
1965 end if
1966
1967 end subroutine eig_sym2
1968
2002 pure subroutine eig_sym3(a11, a22, a33, a12, a13, a23, e1, e2, e3)
2003 real(kind=dp), intent(in) :: a11, a22, a33, a12, a13, a23
2004 real(kind=dp), intent(out) :: e1, e2, e3
2005 real(kind=dp) :: p1, p2, q, p, r, phi
2006 real(kind=dp) :: b11, b22, b33, b12, b13, b23
2007 real(kind=dp), parameter :: third = 1.0_dp / 3.0_dp
2008 real(kind=dp), parameter :: pi_third = 1.0471975511965976_dp
2009 real(kind=dp), parameter :: twopi_third = 2.0943951023931953_dp
2010
2011 p1 = a12 * a12 + a13 * a13 + a23 * a23
2012
2013 q = (a11 + a22 + a33) * third
2014 p2 = (a11 - q)**2 + (a22 - q)**2 + (a33 - q)**2 + 2.0_dp * p1
2015 p = sqrt(p2 / 6.0_dp)
2016
2017 if (p .le. 0.0_dp) then
2018 ! diagonal and isotropic, or all zero
2019 e1 = max(a11, max(a22, a33))
2020 e3 = min(a11, min(a22, a33))
2021 e2 = a11 + a22 + a33 - e1 - e3
2022 return
2023 end if
2024
2025 b11 = (a11 - q) / p
2026 b22 = (a22 - q) / p
2027 b33 = (a33 - q) / p
2028 b12 = a12 / p
2029 b13 = a13 / p
2030 b23 = a23 / p
2031
2032 r = 0.5_dp * (b11 * (b22 * b33 - b23 * b23) &
2033 - b12 * (b12 * b33 - b23 * b13) &
2034 + b13 * (b12 * b23 - b22 * b13))
2035
2036 ! r is in [-1, 1] analytically, round-off can push it out
2037 if (r .le. -1.0_dp) then
2038 phi = pi_third
2039 else if (r .ge. 1.0_dp) then
2040 phi = 0.0_dp
2041 else
2042 phi = acos(r) * third
2043 end if
2044
2045 e1 = q + 2.0_dp * p * cos(phi)
2046 e3 = q + 2.0_dp * p * cos(phi + twopi_third)
2047 e2 = 3.0_dp * q - e1 - e3
2048
2049 end subroutine eig_sym3
2050
2051
2052
2053end 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:508
subroutine, public cmult2(a, b, c, n)
Multiplication by constant c .
Definition math.f90:523
subroutine, public row_zero(a, m, n, e)
Sets row e to 0 in matrix a.
Definition math.f90:267
subroutine, public invcol2(a, b, n)
Vector division .
Definition math.f90:1069
real(kind=rp) function, public vlsc2(u, v, n)
Compute multiplication sum .
Definition math.f90:923
pure logical function, public dabscmp(x, y, tol)
Return double precision absolute comparison .
Definition math.f90:139
pure subroutine, public eig_sym3(a11, a22, a33, a12, a13, a23, e1, e2, e3)
Eigenvalues of a symmetric 3x3 matrix, descending.
Definition math.f90:2003
real(kind=rp), parameter, public pi
Definition math.f90:78
pure logical function qabscmp(x, y, tol)
Return double precision absolute comparison .
Definition math.f90:154
subroutine, public sqrt_inplace(a, n)
Sqrt a vector .
Definition math.f90:1917
real(kind=rp) function, public glsc3(a, b, c, n)
Weighted inner product .
Definition math.f90:1326
subroutine, public ascol5(a, b, c, d, e, n)
Returns .
Definition math.f90:1253
subroutine, public addcol3s2(a, b, c, s, n)
Returns .
Definition math.f90:1236
real(kind=rp) function, public glamax(a, n)
Max of the absolute value of a vector of length n.
Definition math.f90:674
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:474
subroutine, public invers2(a, b, n)
Compute inverted vector .
Definition math.f90:839
subroutine, public cadd2(a, b, s, n)
Add a scalar to vector .
Definition math.f90:585
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:389
real(rp) function, dimension(3, 3), public matinv39(a11, a12, a13, a21, a22, a23, a31, a32, a33)
Definition math.f90:1821
subroutine, public cadd(a, s, n)
Add a scalar to vector .
Definition math.f90:570
subroutine, public masked_copy(a, b, mask, n, n_mask)
Copy a masked vector .
Definition math.f90:339
subroutine reorddp(b, ind, n)
reorder double precision array - inverse of swap
Definition math.f90:1566
pure subroutine, public eig_sym2(a11, a22, a12, e1, e2)
Eigenvalues of a symmetric 2x2 matrix, descending.
Definition math.f90:1952
subroutine, public addsqr2s2(a, b, c1, n)
Returns .
Definition math.f90:1053
subroutine, public cwrap(a, min_val, max_val, n)
Wrap value around a range [min, max)
Definition math.f90:616
real(kind=rp) function, public glsc4(a, b, c, d, n)
Definition math.f90:1347
subroutine, public cdiv2(a, b, c, n)
Division of constant c by elements of a .
Definition math.f90:554
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:1867
subroutine swapdp(b, ind, n)
sort double precision array acording to ind vector
Definition math.f90:1512
subroutine flipvi4(b, ind, n)
Flip single integer vector b and ind.
Definition math.f90:1650
subroutine, public add2s1(a, b, c1, n)
Vector addition with scalar multiplication (multiplication on first argument)
Definition math.f90:1020
subroutine, public cpwmin2(a, b, n)
Point-wise minimum of scalar and vector .
Definition math.f90:1787
real(kind=rp) function, public glsc2(a, b, n)
Weighted inner product .
Definition math.f90:1305
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:449
subroutine, public subcol3(a, b, c, n)
Returns .
Definition math.f90:1116
subroutine, public rone(a, n)
Set all elements to one.
Definition math.f90:281
subroutine flipvdp(b, ind, n)
Flip double precision vector b and ind.
Definition math.f90:1620
subroutine, public cpwmin3(a, b, c, n)
Point-wise minimum of scalar and vector .
Definition math.f90:1802
subroutine, public pwmax3(a, b, c, n)
Point-wise maximum of two vectors .
Definition math.f90:1711
subroutine, public masked_gather_copy(a, b, mask, n, n_mask)
Gather a masked vector to reduced contigous vector .
Definition math.f90:424
subroutine, public x_update(a, b, c, c1, c2, n)
Returns .
Definition math.f90:1288
subroutine, public add3(a, b, c, n)
Vector addition .
Definition math.f90:954
subroutine swapi4(b, ind, n)
sort single integer array acording to ind vector
Definition math.f90:1539
integer function, public glimin(a, n)
Min of an integer vector of length n.
Definition math.f90:731
real(kind=rp) function, public glsum(a, n)
Sum a vector of length n.
Definition math.f90:633
subroutine, public sub3(a, b, c, n)
Vector subtraction .
Definition math.f90:1002
subroutine, public addcol4(a, b, c, d, n)
Returns .
Definition math.f90:1219
subroutine, public add2(a, b, n)
Vector addition .
Definition math.f90:939
subroutine, public cfill(a, c, n)
Set all elements to a constant c .
Definition math.f90:601
subroutine, public absval(a, n)
Take the absolute value of an array.
Definition math.f90:1679
subroutine, public invcol3(a, b, c, n)
Invert a vector .
Definition math.f90:824
subroutine, public add3s2(a, b, c, c1, c2, n)
Returns .
Definition math.f90:1132
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:1841
subroutine, public pwmax2(a, b, n)
Point-wise maximum of two vectors .
Definition math.f90:1696
subroutine, public pwmin2(a, b, n)
Point-wise minimum of two vectors .
Definition math.f90:1757
subroutine, public masked_gather_copy_0(a, b, mask, n, n_mask)
Gather a masked vector to reduced contigous vector .
Definition math.f90:364
subroutine, public subcol4(a, b, c, d, n)
Returns .
Definition math.f90:1186
subroutine sorti4(a, ind, n)
Heap Sort for single integer arrays.
Definition math.f90:1456
subroutine, public addcol3(a, b, c, n)
Returns .
Definition math.f90:1203
subroutine, public invcol1(a, n)
Invert a vector .
Definition math.f90:810
subroutine, public cdiv(a, c, n)
Division of constant c by elements of a .
Definition math.f90:539
real(kind=rp), parameter, public neko_m_ln2
Definition math.f90:75
subroutine, public chsign(a, n)
Change sign of vector .
Definition math.f90:750
subroutine, public cpwmax3(a, b, c, n)
Point-wise maximum of scalar and vector .
Definition math.f90:1741
subroutine, public col2(a, b, n)
Vector multiplication .
Definition math.f90:1085
subroutine, public izero(a, n)
Zero an integer vector.
Definition math.f90:253
real(kind=rp) function, public glmax(a, n)
Max of a vector of length n.
Definition math.f90:654
real(kind=sp), parameter, public neko_eps_sp
Definition math.f90:72
subroutine, public copy(a, b, n)
Copy a vector .
Definition math.f90:295
subroutine, public add4s3(a, b, c, d, c1, c2, c3, n)
Returns .
Definition math.f90:1149
subroutine, public add4(a, b, c, d, n)
Vector addition .
Definition math.f90:970
real(kind=rp) function, public vlamax(vec, n)
maximum absolute value of a vector of length n, rank-local
Definition math.f90:764
subroutine, public col3(a, b, c, n)
Vector multiplication with 3 vectors .
Definition math.f90:1100
subroutine, public add5s4(a, b, c, d, e, c1, c2, c3, c4, n)
Returns .
Definition math.f90:1167
real(kind=rp) function, public math_dstepf(x)
Derivative of math_stepf with respect to x: d(stepf)/dx.
Definition math.f90:1890
pure logical function drelcmp(x, y, eps)
Return double precision relative comparison .
Definition math.f90:185
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:891
pure logical function, public sabscmp(x, y, tol)
Return single precision absolute comparison .
Definition math.f90:124
pure logical function qrelcmp(x, y, eps)
Return quad precision relative comparison .
Definition math.f90:200
subroutine, public rzero(a, n)
Zero a real vector.
Definition math.f90:239
real(kind=rp) function, public glsubnorm(a, b, n)
Returns the norm of the difference of two vectors .
Definition math.f90:1372
subroutine, public vdot2(dot, u1, u2, v1, v2, n)
Compute a dot product (2-d version) assuming vector components etc.
Definition math.f90:874
subroutine, public cpwmax2(a, b, n)
Point-wise maximum of scalar and vector .
Definition math.f90:1726
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:794
subroutine, public cfill_mask(a, c, n, mask, n_mask)
Fill a constant to a masked vector. .
Definition math.f90:492
real(kind=rp) function, public vlmax(vec, n)
maximum value of a vector of length n
Definition math.f90:779
integer function, public glimax(a, n)
Max of an integer vector of length n.
Definition math.f90:693
subroutine sortrp(a, ind, n)
Heap Sort for double precision arrays.
Definition math.f90:1398
subroutine, public sub2(a, b, n)
Vector substraction .
Definition math.f90:987
subroutine, public pwmin3(a, b, c, n)
Point-wise minimum of two vectors .
Definition math.f90:1772
subroutine, public add2s2(a, b, c1, n)
Vector addition with scalar multiplication (multiplication on second argument)
Definition math.f90:1037
real(kind=rp) function, public glmin(a, n)
Min of a vector of length n.
Definition math.f90:712
subroutine, public masked_copy_0(a, b, mask, n, n_mask)
Copy a masked vector .
Definition math.f90:316
subroutine, public vcross(u1, u2, u3, v1, v2, v3, w1, w2, w3, n)
Compute a cross product assuming vector components etc.
Definition math.f90:855
pure logical function srelcmp(x, y, eps)
Return single precision relative comparison .
Definition math.f90:170
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:218
real(kind=rp) function, public vlsc3(u, v, w, n)
Compute multiplication sum .
Definition math.f90:907
subroutine, public power(ap, a, p, n)
Take the power of a vector .
Definition math.f90:1931
subroutine reordi4(b, ind, n)
reorder single integer array - inverse of swap
Definition math.f90:1593
subroutine, public p_update(a, b, c, c1, c2, n)
Returns .
Definition math.f90:1271
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