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