FrontISTR  6.0.0
Large-scale structural analysis program with finit element method
hecmw_mf_kernel.F90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
2 ! Copyright (c) 2026 FrontISTR Commons
3 ! This software is released under the MIT License, see LICENSE.txt
4 !-------------------------------------------------------------------------------
18  use hecmw_util
19  implicit none
20 
21  private
22  public :: hecmw_mf_kernel_ldlt
23  public :: hecmw_mf_kernel_trsm
26  public :: hecmw_mf_kernel_scale
27  public :: hecmw_mf_kernel_gemm
28  public :: hecmw_mf_kernel_trsv
29  public :: hecmw_mf_kernel_trsv_t
30  public :: hecmw_mf_kernel_dsolve
31  public :: hecmw_mf_kernel_gemv
32  public :: hecmw_mf_kernel_gemv_t
33  public :: hecmw_mf_kernel_lu
34  public :: hecmw_mf_kernel_trsm_rt
37  public :: hecmw_mf_kernel_usolve
39  public :: hecmw_mf_kernel_compress
40  public :: hecmw_mf_kernel_mult_nn
41  public :: hecmw_mf_kernel_mult_tn
42  public :: hecmw_mf_kernel_mult_tv
44 
45 contains
46 
49  subroutine hecmw_mf_kernel_ldlt(n, lda, a, zero, info)
50  implicit none
51  integer(kind=kint), intent(in) :: n, lda
52  real(kind=kreal), intent(inout) :: a(lda,*)
53  real(kind=kreal), intent(in) :: zero
54  integer(kind=kint), intent(out) :: info
55  integer(kind=kint) :: i, j, k
56  real(kind=kreal) :: d, l
57 
58  info = 0
59  do k = 1, n
60  d = a(k,k)
61  if (.not. (abs(d) > zero)) then
62  info = k
63  return
64  endif
65  do j = k+1, n
66  l = a(j,k) / d
67  do i = j, n
68  a(i,j) = a(i,j) - a(i,k)*l
69  enddo
70  enddo
71  do i = k+1, n
72  a(i,k) = a(i,k) / d
73  enddo
74  enddo
75  end subroutine hecmw_mf_kernel_ldlt
76 
78  subroutine hecmw_mf_kernel_trsm(m, n, ldl, l, lda, a)
79  implicit none
80  integer(kind=kint), intent(in) :: m, n, ldl, lda
81  real(kind=kreal), intent(in) :: l(ldl,*)
82  real(kind=kreal), intent(inout) :: a(lda,*)
83  integer(kind=kint) :: i, j
84 #ifdef HECMW_WITH_LAPACK
85  external :: dtrsm
86 
87  call dtrsm('R', 'L', 'T', 'U', m, n, 1.0d0, l, ldl, a, lda)
88  do j = 1, n
89  do i = 1, m
90  a(i,j) = a(i,j) / l(j,j)
91  enddo
92  enddo
93 #else
94  integer(kind=kint) :: k
95 
96  ! the updates need the unit solve of the earlier columns, so D is divided out afterwards
97  do j = 1, n
98  do k = 1, j-1
99  do i = 1, m
100  a(i,j) = a(i,j) - a(i,k)*l(j,k)
101  enddo
102  enddo
103  enddo
104  do j = 1, n
105  do i = 1, m
106  a(i,j) = a(i,j) / l(j,j)
107  enddo
108  enddo
109 #endif
110  end subroutine hecmw_mf_kernel_trsm
111 
115  subroutine hecmw_mf_kernel_panel_nopiv(m, n, lda, a, u, zero, info)
116  implicit none
117  integer(kind=kint), intent(in) :: m, n, lda
118  real(kind=kreal), intent(inout) :: a(lda,*)
119  real(kind=kreal), intent(in) :: u, zero
120  integer(kind=kint), intent(out) :: info
121  integer(kind=kint) :: i, j
122  real(kind=kreal) :: uinv
123 
124  call hecmw_mf_kernel_ldlt(n, lda, a, zero, info)
125  if (info /= 0) return
126  if (m > n) call hecmw_mf_kernel_trsm(m-n, n, lda, a, lda, a(n+1,1))
127  uinv = 1.0d0 / u
128  do j = 1, n
129  do i = j+1, m
130  if (.not. (abs(a(i,j)) <= uinv)) then
131  info = j
132  return
133  endif
134  enddo
135  enddo
136  end subroutine hecmw_mf_kernel_panel_nopiv
137 
146  subroutine hecmw_mf_kernel_panel_piv(m, n, lda, a, blk, u, alpha, zero, allow_delay, wk, &
147  npiv, perm, ptype, dsub, nswap, n2x2, info)
148  implicit none
149  integer(kind=kint), intent(in) :: m, n, lda
150  real(kind=kreal), intent(inout) :: a(lda,*)
151  integer(kind=kint), intent(inout) :: blk(n)
152  real(kind=kreal), intent(in) :: u, alpha, zero
153  logical, intent(in) :: allow_delay
154  real(kind=kreal), intent(inout) :: wk(2*m)
155  integer(kind=kint), intent(out) :: npiv, perm(n), ptype(n), nswap, n2x2, info
156  real(kind=kreal), intent(out) :: dsub(n)
157  integer(kind=kint) :: p, nrem, i, r, pass
158  real(kind=kreal) :: lam, app, best, uinv
159  logical :: accepted, same
160 
161  uinv = 1.0d0 / u
162  do i = 1, n
163  perm(i) = i
164  ptype(i) = 0
165  dsub(i) = 0.0d0
166  enddo
167  p = 1
168  nrem = n
169  nswap = 0
170  n2x2 = 0
171  info = 0
172  do while (p <= nrem)
173  lam = 0.0d0
174  do i = p+1, m
175  lam = max(lam, abs(a(i,p)))
176  enddo
177  app = abs(a(p,p))
178  if (app > zero .and. app >= u*lam) then
179  call pivot_1x1()
180  cycle
181  endif
182  accepted = .false.
183  if (lam > zero) then
184  do pass = 1, 2
185  r = 0
186  best = zero
187  do i = p+1, nrem
188  same = (blk(i) == blk(p))
189  if (same .neqv. (pass == 1)) cycle
190  if (abs(a(i,p)) > best) then
191  best = abs(a(i,p))
192  r = i
193  endif
194  enddo
195  if (r == 0) cycle
196  call try_partner(r, accepted)
197  if (accepted) exit
198  enddo
199  endif
200  if (accepted) cycle
201  if (.not. allow_delay) then
202  ! the two best-coupled candidates can both fail the growth test on a regular
203  ! indefinite panel; with no parent to delay to, every remaining partner is tried
204  ! before the panel is declared unsolvable (the accepting runs never reach here,
205  ! so the pivot sequence of a succeeding factorization is unchanged)
206  do r = p+1, nrem
207  call try_partner(r, accepted)
208  if (accepted) exit
209  enddo
210  if (accepted) cycle
211  info = p
212  return
213  endif
214  if (nrem > p) call swap(p, nrem)
215  nrem = nrem - 1
216  enddo
217  npiv = p - 1
218 
219  contains
220 
222  subroutine try_partner(r, accepted)
223  integer(kind=kint), intent(in) :: r
224  logical, intent(out) :: accepted
225  integer(kind=kint) :: i
226  real(kind=kreal) :: sig, arr, aa, bb, cc, det, cp, cr, g1, g2
227 
228  accepted = .false.
229  sig = 0.0d0
230  do i = p, r-1
231  sig = max(sig, abs(a(r,i)))
232  enddo
233  do i = r+1, m
234  sig = max(sig, abs(a(i,r)))
235  enddo
236  arr = abs(a(r,r))
237  if (arr > zero .and. arr >= alpha*sig) then
238  call swap(p, r)
239  nswap = nswap + 1
240  call pivot_1x1()
241  accepted = .true.
242  return
243  endif
244  if (r /= p+1) call swap(p+1, r)
245  aa = a(p,p)
246  bb = a(p+1,p)
247  cc = a(p+1,p+1)
248  det = aa*cc - bb*bb
249  if (abs(det) > zero*zero) then
250  cp = 0.0d0
251  cr = 0.0d0
252  do i = p+2, m
253  cp = max(cp, abs(a(i,p)))
254  cr = max(cr, abs(a(i,p+1)))
255  enddo
256  g1 = (abs(cc)*cp + abs(bb)*cr) / abs(det)
257  g2 = (abs(bb)*cp + abs(aa)*cr) / abs(det)
258  if (g1 <= uinv .and. g2 <= uinv) then
259  if (r /= p+1) nswap = nswap + 1
260  call pivot_2x2()
261  n2x2 = n2x2 + 1
262  accepted = .true.
263  return
264  endif
265  endif
266  if (r /= p+1) call swap(p+1, r)
267  end subroutine try_partner
268 
270  subroutine pivot_1x1()
271  integer(kind=kint) :: i, j
272  real(kind=kreal) :: d, l
273 
274  d = a(p,p)
275  do j = p+1, nrem
276  l = a(j,p) / d
277  do i = j, m
278  a(i,j) = a(i,j) - a(i,p)*l
279  enddo
280  enddo
281  do i = p+1, m
282  a(i,p) = a(i,p) / d
283  enddo
284  ptype(p) = 1
285  p = p + 1
286  end subroutine pivot_1x1
287 
289  subroutine pivot_2x2()
290  integer(kind=kint) :: i, j
291  real(kind=kreal) :: aa, bb, cc, det
292 
293  aa = a(p,p)
294  bb = a(p+1,p)
295  cc = a(p+1,p+1)
296  det = aa*cc - bb*bb
297  do i = p+2, m
298  wk(i) = (cc*a(i,p) - bb*a(i,p+1)) / det
299  wk(m+i) = (aa*a(i,p+1) - bb*a(i,p)) / det
300  enddo
301  do j = p+2, nrem
302  do i = j, m
303  a(i,j) = a(i,j) - wk(i)*a(j,p) - wk(m+i)*a(j,p+1)
304  enddo
305  enddo
306  do i = p+2, m
307  a(i,p) = wk(i)
308  a(i,p+1) = wk(m+i)
309  enddo
310  a(p+1,p) = 0.0d0
311  ptype(p) = 2
312  ptype(p+1) = 3
313  dsub(p) = bb
314  p = p + 2
315  end subroutine pivot_2x2
316 
318  subroutine swap(x, y)
319  integer(kind=kint), intent(in) :: x, y
320  integer(kind=kint) :: i, t
321  real(kind=kreal) :: v
322 
323  v = a(x,x)
324  a(x,x) = a(y,y)
325  a(y,y) = v
326  do i = 1, x-1
327  v = a(x,i)
328  a(x,i) = a(y,i)
329  a(y,i) = v
330  enddo
331  do i = x+1, y-1
332  v = a(i,x)
333  a(i,x) = a(y,i)
334  a(y,i) = v
335  enddo
336  do i = y+1, m
337  v = a(i,x)
338  a(i,x) = a(i,y)
339  a(i,y) = v
340  enddo
341  t = perm(x)
342  perm(x) = perm(y)
343  perm(y) = t
344  t = blk(x)
345  blk(x) = blk(y)
346  blk(y) = t
347  end subroutine swap
348 
349  end subroutine hecmw_mf_kernel_panel_piv
350 
352  subroutine hecmw_mf_kernel_scale(m, n, ldl, l, ptype, dsub, lda, a, w)
353  implicit none
354  integer(kind=kint), intent(in) :: m, n, ldl, lda
355  real(kind=kreal), intent(in) :: l(ldl,*)
356  integer(kind=kint), intent(in) :: ptype(n)
357  real(kind=kreal), intent(in) :: dsub(n)
358  real(kind=kreal), intent(in) :: a(lda,*)
359  real(kind=kreal), intent(out) :: w(m,n)
360  integer(kind=kint) :: i, j
361  real(kind=kreal) :: d11, d21, d22
362 
363  do j = 1, n
364  if (ptype(j) == 1) then
365  do i = 1, m
366  w(i,j) = a(i,j) * l(j,j)
367  enddo
368  else if (ptype(j) == 2) then
369  d11 = l(j,j)
370  d21 = dsub(j)
371  d22 = l(j+1,j+1)
372  do i = 1, m
373  w(i,j) = a(i,j)*d11 + a(i,j+1)*d21
374  w(i,j+1) = a(i,j)*d21 + a(i,j+1)*d22
375  enddo
376  endif
377  enddo
378  end subroutine hecmw_mf_kernel_scale
379 
381  subroutine hecmw_mf_kernel_gemm(m, n, k, ldw, w, ldb, b, ldc, c)
382  implicit none
383  integer(kind=kint), intent(in) :: m, n, k, ldw, ldb, ldc
384  real(kind=kreal), intent(in) :: w(ldw,*)
385  real(kind=kreal), intent(in) :: b(ldb,*)
386  real(kind=kreal), intent(inout) :: c(ldc,*)
387 #ifdef HECMW_WITH_LAPACK
388  external :: dgemm
389 
390  call dgemm('N', 'T', m, n, k, -1.0d0, w, ldw, b, ldb, 1.0d0, c, ldc)
391 #else
392  integer(kind=kint) :: i, j, p
393 
394  do j = 1, n
395  do p = 1, k
396  do i = 1, m
397  c(i,j) = c(i,j) - w(i,p)*b(j,p)
398  enddo
399  enddo
400  enddo
401 #endif
402  end subroutine hecmw_mf_kernel_gemm
403 
405  subroutine hecmw_mf_kernel_trsv(n, ldl, l, x)
406  implicit none
407  integer(kind=kint), intent(in) :: n, ldl
408  real(kind=kreal), intent(in) :: l(ldl,*)
409  real(kind=kreal), intent(inout) :: x(n)
410  integer(kind=kint) :: i, j
411 
412  do j = 1, n
413  do i = j+1, n
414  x(i) = x(i) - l(i,j)*x(j)
415  enddo
416  enddo
417  end subroutine hecmw_mf_kernel_trsv
418 
420  subroutine hecmw_mf_kernel_trsv_t(n, ldl, l, x)
421  implicit none
422  integer(kind=kint), intent(in) :: n, ldl
423  real(kind=kreal), intent(in) :: l(ldl,*)
424  real(kind=kreal), intent(inout) :: x(n)
425  integer(kind=kint) :: i, j
426 
427  do j = n, 1, -1
428  do i = j+1, n
429  x(j) = x(j) - l(i,j)*x(i)
430  enddo
431  enddo
432  end subroutine hecmw_mf_kernel_trsv_t
433 
435  subroutine hecmw_mf_kernel_dsolve(n, ldl, l, ptype, dsub, x)
436  implicit none
437  integer(kind=kint), intent(in) :: n, ldl
438  real(kind=kreal), intent(in) :: l(ldl,*)
439  integer(kind=kint), intent(in) :: ptype(n)
440  real(kind=kreal), intent(in) :: dsub(n)
441  real(kind=kreal), intent(inout) :: x(n)
442  integer(kind=kint) :: j
443  real(kind=kreal) :: d11, d21, d22, det, x1, x2
444 
445  do j = 1, n
446  if (ptype(j) == 1) then
447  x(j) = x(j) / l(j,j)
448  else if (ptype(j) == 2) then
449  d11 = l(j,j)
450  d21 = dsub(j)
451  d22 = l(j+1,j+1)
452  det = d11*d22 - d21*d21
453  x1 = x(j)
454  x2 = x(j+1)
455  x(j) = (d22*x1 - d21*x2) / det
456  x(j+1) = (d11*x2 - d21*x1) / det
457  endif
458  enddo
459  end subroutine hecmw_mf_kernel_dsolve
460 
462  subroutine hecmw_mf_kernel_gemv(m, n, lda, a, x, y)
463  implicit none
464  integer(kind=kint), intent(in) :: m, n, lda
465  real(kind=kreal), intent(in) :: a(lda,*)
466  real(kind=kreal), intent(in) :: x(n)
467  real(kind=kreal), intent(inout) :: y(m)
468  integer(kind=kint) :: i, j
469 
470  do j = 1, n
471  do i = 1, m
472  y(i) = y(i) - a(i,j)*x(j)
473  enddo
474  enddo
475  end subroutine hecmw_mf_kernel_gemv
476 
478  subroutine hecmw_mf_kernel_gemv_t(m, n, lda, a, x, y)
479  implicit none
480  integer(kind=kint), intent(in) :: m, n, lda
481  real(kind=kreal), intent(in) :: a(lda,*)
482  real(kind=kreal), intent(in) :: x(m)
483  real(kind=kreal), intent(inout) :: y(n)
484  integer(kind=kint) :: i, j
485 
486  do j = 1, n
487  do i = 1, m
488  y(j) = y(j) - a(i,j)*x(i)
489  enddo
490  enddo
491  end subroutine hecmw_mf_kernel_gemv_t
492 
496  subroutine hecmw_mf_kernel_lu(n, lda, a, ldb, b, zero, info)
497  implicit none
498  integer(kind=kint), intent(in) :: n, lda, ldb
499  real(kind=kreal), intent(inout) :: a(lda,*), b(ldb,*)
500  real(kind=kreal), intent(in) :: zero
501  integer(kind=kint), intent(out) :: info
502  integer(kind=kint) :: i, j, k
503  real(kind=kreal) :: d, l, u
504 
505  info = 0
506  do k = 1, n
507  d = a(k,k)
508  if (.not. (abs(d) > zero)) then
509  info = k
510  return
511  endif
512  do i = k+1, n
513  a(i,k) = a(i,k) / d
514  enddo
515  do j = k+1, n
516  u = b(j,k)
517  do i = j, n
518  a(i,j) = a(i,j) - a(i,k)*u
519  enddo
520  l = a(j,k)
521  do i = j+1, n
522  b(i,j) = b(i,j) - b(i,k)*l
523  enddo
524  enddo
525  enddo
526  end subroutine hecmw_mf_kernel_lu
527 
529  subroutine hecmw_mf_kernel_trsm_rt(m, n, ldt, t, unit, lda, a)
530  implicit none
531  integer(kind=kint), intent(in) :: m, n, ldt, lda
532  real(kind=kreal), intent(in) :: t(ldt,*)
533  logical, intent(in) :: unit
534  real(kind=kreal), intent(inout) :: a(lda,*)
535 #ifdef HECMW_WITH_LAPACK
536  external :: dtrsm
537 
538  if (unit) then
539  call dtrsm('R', 'L', 'T', 'U', m, n, 1.0d0, t, ldt, a, lda)
540  else
541  call dtrsm('R', 'L', 'T', 'N', m, n, 1.0d0, t, ldt, a, lda)
542  endif
543 #else
544  integer(kind=kint) :: i, j, k
545 
546  do j = 1, n
547  do k = 1, j-1
548  do i = 1, m
549  a(i,j) = a(i,j) - a(i,k)*t(j,k)
550  enddo
551  enddo
552  if (.not. unit) then
553  do i = 1, m
554  a(i,j) = a(i,j) / t(j,j)
555  enddo
556  endif
557  enddo
558 #endif
559  end subroutine hecmw_mf_kernel_trsm_rt
560 
564  subroutine hecmw_mf_kernel_panel_lu_nopiv(m, n, lda, a, ldb, b, u, zero, info)
565  implicit none
566  integer(kind=kint), intent(in) :: m, n, lda, ldb
567  real(kind=kreal), intent(inout) :: a(lda,*), b(ldb,*)
568  real(kind=kreal), intent(in) :: u, zero
569  integer(kind=kint), intent(out) :: info
570  integer(kind=kint) :: i, j
571  real(kind=kreal) :: uinv
572 
573  call hecmw_mf_kernel_lu(n, lda, a, ldb, b, zero, info)
574  if (info /= 0) return
575  if (m > n) then
576  do j = 1, n
577  b(j,j) = a(j,j)
578  enddo
579  call hecmw_mf_kernel_trsm_rt(m-n, n, ldb, b, .false., lda, a(n+1,1))
580  call hecmw_mf_kernel_trsm_rt(m-n, n, lda, a, .true., ldb, b(n+1,1))
581  endif
582  uinv = 1.0d0 / u
583  do j = 1, n
584  do i = j+1, m
585  if (.not. (abs(a(i,j)) <= uinv)) then
586  info = j
587  return
588  endif
589  enddo
590  enddo
591  end subroutine hecmw_mf_kernel_panel_lu_nopiv
592 
600  subroutine hecmw_mf_kernel_panel_lu_piv(m, n, lda, a, ldb, b, blk, blkr, u, zero, allow_delay, &
601  npiv, permc, permr, nswap, info)
602  implicit none
603  integer(kind=kint), intent(in) :: m, n, lda, ldb
604  real(kind=kreal), intent(inout) :: a(lda,*), b(ldb,*)
605  integer(kind=kint), intent(inout) :: blk(n), blkr(n)
606  real(kind=kreal), intent(in) :: u, zero
607  logical, intent(in) :: allow_delay
608  integer(kind=kint), intent(out) :: npiv, permc(n), permr(n), nswap, info
609  integer(kind=kint) :: p, nrem, i, r, pass
610  real(kind=kreal) :: lam, best
611  logical :: same
612 
613  do i = 1, n
614  permc(i) = i
615  permr(i) = i
616  enddo
617  p = 1
618  nrem = n
619  nswap = 0
620  info = 0
621  do while (p <= nrem)
622  lam = 0.0d0
623  do i = p, m
624  lam = max(lam, abs(a(i,p)))
625  enddo
626  r = 0
627  if (lam > zero) then
628  do pass = 1, 2
629  best = 0.0d0
630  do i = p, nrem
631  same = (blkr(i) == blk(p))
632  if (same .neqv. (pass == 1)) cycle
633  if (abs(a(i,p)) > best) then
634  best = abs(a(i,p))
635  r = i
636  endif
637  enddo
638  if (r /= 0) then
639  if (best >= u*lam) exit
640  r = 0
641  endif
642  enddo
643  endif
644  if (r == 0) then
645  if (.not. allow_delay) then
646  info = p
647  return
648  endif
649  if (nrem > p) call swap_sym(p, nrem)
650  nrem = nrem - 1
651  cycle
652  endif
653  if (r /= p) then
654  call swap_row(p, r)
655  nswap = nswap + 1
656  endif
657  call pivot()
658  enddo
659  npiv = p - 1
660 
661  contains
662 
664  subroutine pivot()
665  integer(kind=kint) :: i, j
666  real(kind=kreal) :: d, l, uu
667 
668  d = a(p,p)
669  do i = p+1, m
670  a(i,p) = a(i,p) / d
671  enddo
672  do j = p+1, nrem
673  uu = b(j,p)
674  do i = j, m
675  a(i,j) = a(i,j) - a(i,p)*uu
676  enddo
677  l = a(j,p)
678  do i = j+1, m
679  b(i,j) = b(i,j) - b(i,p)*l
680  enddo
681  enddo
682  p = p + 1
683  end subroutine pivot
684 
686  subroutine swap_row(x, y)
687  integer(kind=kint), intent(in) :: x, y
688  integer(kind=kint) :: c, t
689  real(kind=kreal) :: v
690 
691  do c = 1, x
692  v = a(x,c)
693  a(x,c) = a(y,c)
694  a(y,c) = v
695  enddo
696  do c = x+1, y-1
697  v = b(c,x)
698  b(c,x) = a(y,c)
699  a(y,c) = v
700  enddo
701  v = b(y,x)
702  b(y,x) = a(y,y)
703  a(y,y) = v
704  do c = y+1, m
705  v = b(c,x)
706  b(c,x) = b(c,y)
707  b(c,y) = v
708  enddo
709  t = permr(x)
710  permr(x) = permr(y)
711  permr(y) = t
712  t = blkr(x)
713  blkr(x) = blkr(y)
714  blkr(y) = t
715  end subroutine swap_row
716 
718  subroutine swap_sym(x, y)
719  integer(kind=kint), intent(in) :: x, y
720  integer(kind=kint) :: i, t
721  real(kind=kreal) :: v
722 
723  v = a(x,x)
724  a(x,x) = a(y,y)
725  a(y,y) = v
726  do i = 1, x-1
727  v = a(x,i)
728  a(x,i) = a(y,i)
729  a(y,i) = v
730  v = b(x,i)
731  b(x,i) = b(y,i)
732  b(y,i) = v
733  enddo
734  do i = x+1, y-1
735  v = a(i,x)
736  a(i,x) = b(y,i)
737  b(y,i) = v
738  v = a(y,i)
739  a(y,i) = b(i,x)
740  b(i,x) = v
741  enddo
742  v = a(y,x)
743  a(y,x) = b(y,x)
744  b(y,x) = v
745  do i = y+1, m
746  v = a(i,x)
747  a(i,x) = a(i,y)
748  a(i,y) = v
749  v = b(i,x)
750  b(i,x) = b(i,y)
751  b(i,y) = v
752  enddo
753  t = permc(x)
754  permc(x) = permc(y)
755  permc(y) = t
756  t = permr(x)
757  permr(x) = permr(y)
758  permr(y) = t
759  t = blk(x)
760  blk(x) = blk(y)
761  blk(y) = t
762  t = blkr(x)
763  blkr(x) = blkr(y)
764  blkr(y) = t
765  end subroutine swap_sym
766 
767  end subroutine hecmw_mf_kernel_panel_lu_piv
768 
771  subroutine hecmw_mf_kernel_usolve(n, ldl, l, ldu, ut, x)
772  implicit none
773  integer(kind=kint), intent(in) :: n, ldl, ldu
774  real(kind=kreal), intent(in) :: l(ldl,*), ut(ldu,*)
775  real(kind=kreal), intent(inout) :: x(n)
776  integer(kind=kint) :: i, j
777 
778  do j = n, 1, -1
779  do i = j+1, n
780  x(j) = x(j) - ut(i,j)*x(i)
781  enddo
782  x(j) = x(j) / l(j,j)
783  enddo
784  end subroutine hecmw_mf_kernel_usolve
785 
787  function hecmw_mf_kernel_blr_available() result(avail)
788  implicit none
789  logical :: avail
790 
791 #ifdef HECMW_WITH_LAPACK
792  avail = .true.
793 #else
794  avail = .false.
795 #endif
796  end function hecmw_mf_kernel_blr_available
797 
840  subroutine hecmw_mf_kernel_compress(m, n, lda, a, eps, ldv, v, rank, rcap)
841  implicit none
842  integer(kind=kint), intent(in) :: m, n, lda, ldv
843  real(kind=kreal), intent(inout) :: a(lda,*)
844  real(kind=kreal), intent(in) :: eps
845  real(kind=kreal), intent(out) :: v(ldv,*)
846  integer(kind=kint), intent(out) :: rank
847  integer(kind=kint), intent(in), optional :: rcap
848 #ifdef HECMW_WITH_LAPACK
849  integer(kind=kint), allocatable :: jpvt(:)
850  real(kind=kreal), allocatable :: tau(:), vn1(:), vn2(:), wk(:)
851  integer(kind=kint) :: i, j, k, p, r, rlim, itmp
852  real(kind=kreal) :: r11, rkk, akk, tol3z, tmp, tmp2, dtmp
853  real(kind=kreal), external :: dnrm2, dlamch
854  external :: dlarfg, dgemv, dger
855 
856  rank = -1
857  ! largest rank whose low rank form takes fewer than m*n words; always below min(m,n)
858  rlim = int((int(m, 8)*n - 1)/(int(m, 8) + n), kind=kint)
859  if (present(rcap)) rlim = min(rlim, max(rcap, 0))
860  tol3z = sqrt(dlamch('Epsilon'))
861  allocate(jpvt(n), tau(rlim + 1), vn1(n), vn2(n), wk(n))
862  do j = 1, n
863  jpvt(j) = j
864  vn1(j) = dnrm2(m, a(1,j), 1)
865  vn2(j) = vn1(j)
866  enddo
867  r11 = 0.0d0
868  r = 0
869  do k = 1, rlim + 1
870  p = k
871  do j = k + 1, n
872  if (vn1(j) > vn1(p)) p = j
873  enddo
874  if (p /= k) then
875  do i = 1, m
876  dtmp = a(i,k)
877  a(i,k) = a(i,p)
878  a(i,p) = dtmp
879  enddo
880  itmp = jpvt(k)
881  jpvt(k) = jpvt(p)
882  jpvt(p) = itmp
883  dtmp = vn1(k)
884  vn1(k) = vn1(p)
885  vn1(p) = dtmp
886  dtmp = vn2(k)
887  vn2(k) = vn2(p)
888  vn2(p) = dtmp
889  endif
890  rkk = dnrm2(m - k + 1, a(k,k), 1)
891  if (k == 1) r11 = rkk
892  if (.not. (rkk > eps*r11)) then
893  r = k - 1
894  exit
895  endif
896  if (k > rlim) then
897  deallocate(jpvt, tau, vn1, vn2, wk)
898  return
899  endif
900  call dlarfg(m - k + 1, a(k,k), a(k+1,k), 1, tau(k))
901  akk = a(k,k)
902  a(k,k) = 1.0d0
903  call dgemv('T', m - k + 1, n - k, 1.0d0, a(k,k+1), lda, a(k,k), 1, 0.0d0, wk, 1)
904  call dger(m - k + 1, n - k, -tau(k), a(k,k), 1, wk, 1, a(k,k+1), lda)
905  a(k,k) = akk
906  do j = k + 1, n
907  if (vn1(j) /= 0.0d0) then
908  tmp = max(1.0d0 - (abs(a(k,j))/vn1(j))**2, 0.0d0)
909  tmp2 = tmp*(vn1(j)/vn2(j))**2
910  if (tmp2 <= tol3z) then
911  vn1(j) = dnrm2(m - k, a(k+1,j), 1)
912  vn2(j) = vn1(j)
913  else
914  vn1(j) = vn1(j)*sqrt(tmp)
915  endif
916  endif
917  enddo
918  enddo
919  do j = 1, n
920  do k = 1, r
921  if (k <= j) then
922  v(jpvt(j), k) = a(k, j)
923  else
924  v(jpvt(j), k) = 0.0d0
925  endif
926  enddo
927  enddo
928  do k = r, 1, -1
929  if (k < r) then
930  a(k,k) = 1.0d0
931  call dgemv('T', m - k + 1, r - k, 1.0d0, a(k,k+1), lda, a(k,k), 1, 0.0d0, wk, 1)
932  call dger(m - k + 1, r - k, -tau(k), a(k,k), 1, wk, 1, a(k,k+1), lda)
933  endif
934  do i = k + 1, m
935  a(i,k) = -tau(k)*a(i,k)
936  enddo
937  a(k,k) = 1.0d0 - tau(k)
938  do i = 1, k - 1
939  a(i,k) = 0.0d0
940  enddo
941  enddo
942  rank = r
943  deallocate(jpvt, tau, vn1, vn2, wk)
944 #else
945  rank = -1
946 #endif
947  end subroutine hecmw_mf_kernel_compress
948 
950  subroutine hecmw_mf_kernel_mult_nn(m, n, k, lda, a, ldb, b, ldc, c)
951  implicit none
952  integer(kind=kint), intent(in) :: m, n, k, lda, ldb, ldc
953  real(kind=kreal), intent(in) :: a(lda,*), b(ldb,*)
954  real(kind=kreal), intent(out) :: c(ldc,*)
955 #ifdef HECMW_WITH_LAPACK
956  external :: dgemm
957 
958  call dgemm('N', 'N', m, n, k, 1.0d0, a, lda, b, ldb, 0.0d0, c, ldc)
959 #else
960  integer(kind=kint) :: i, j, p
961 
962  do j = 1, n
963  do i = 1, m
964  c(i,j) = 0.0d0
965  enddo
966  do p = 1, k
967  do i = 1, m
968  c(i,j) = c(i,j) + a(i,p)*b(p,j)
969  enddo
970  enddo
971  enddo
972 #endif
973  end subroutine hecmw_mf_kernel_mult_nn
974 
976  subroutine hecmw_mf_kernel_mult_tn(m, n, k, lda, a, ldb, b, ldc, c)
977  implicit none
978  integer(kind=kint), intent(in) :: m, n, k, lda, ldb, ldc
979  real(kind=kreal), intent(in) :: a(lda,*), b(ldb,*)
980  real(kind=kreal), intent(out) :: c(ldc,*)
981 #ifdef HECMW_WITH_LAPACK
982  external :: dgemm
983 
984  call dgemm('T', 'N', m, n, k, 1.0d0, a, lda, b, ldb, 0.0d0, c, ldc)
985 #else
986  integer(kind=kint) :: i, j, p
987 
988  do j = 1, n
989  do i = 1, m
990  c(i,j) = 0.0d0
991  do p = 1, k
992  c(i,j) = c(i,j) + a(p,i)*b(p,j)
993  enddo
994  enddo
995  enddo
996 #endif
997  end subroutine hecmw_mf_kernel_mult_tn
998 
1000  subroutine hecmw_mf_kernel_mult_tv(m, n, lda, a, x, y)
1001  implicit none
1002  integer(kind=kint), intent(in) :: m, n, lda
1003  real(kind=kreal), intent(in) :: a(lda,*)
1004  real(kind=kreal), intent(in) :: x(m)
1005  real(kind=kreal), intent(out) :: y(n)
1006  integer(kind=kint) :: i, j
1007 
1008  do j = 1, n
1009  y(j) = 0.0d0
1010  do i = 1, m
1011  y(j) = y(j) + a(i,j)*x(i)
1012  enddo
1013  enddo
1014  end subroutine hecmw_mf_kernel_mult_tv
1015 
1017  subroutine hecmw_mf_kernel_scale_rows(n, r, ldl, l, ptype, dsub, ldv, v, ldw, w)
1018  implicit none
1019  integer(kind=kint), intent(in) :: n, r, ldl, ldv, ldw
1020  real(kind=kreal), intent(in) :: l(ldl,*)
1021  integer(kind=kint), intent(in) :: ptype(n)
1022  real(kind=kreal), intent(in) :: dsub(n)
1023  real(kind=kreal), intent(in) :: v(ldv,*)
1024  real(kind=kreal), intent(out) :: w(ldw,*)
1025  integer(kind=kint) :: q, c
1026  real(kind=kreal) :: d11, d21, d22
1027 
1028  q = 1
1029  do while (q <= n)
1030  if (ptype(q) == 1) then
1031  do c = 1, r
1032  w(q,c) = v(q,c) * l(q,q)
1033  enddo
1034  q = q + 1
1035  else
1036  d11 = l(q,q)
1037  d21 = dsub(q)
1038  d22 = l(q+1,q+1)
1039  do c = 1, r
1040  w(q,c) = v(q,c)*d11 + v(q+1,c)*d21
1041  w(q+1,c) = v(q,c)*d21 + v(q+1,c)*d22
1042  enddo
1043  q = q + 2
1044  endif
1045  enddo
1046  end subroutine hecmw_mf_kernel_scale_rows
1047 
1048 end module hecmw_mf_kernel
Dense kernels of the multifrontal solver, symmetric (LDLt) and unsymmetric (LU) mode.
subroutine, public hecmw_mf_kernel_gemm(m, n, k, ldw, w, ldb, b, ldc, c)
c(m,n) <- c - w(m,k) * b(n,k)^T
subroutine, public hecmw_mf_kernel_scale(m, n, ldl, l, ptype, dsub, lda, a, w)
w(m,n) <- a * D with the block diagonal D of the factored tile l(n,n).
subroutine, public hecmw_mf_kernel_compress(m, n, lda, a, eps, ldv, v, rank, rcap)
Truncated rank revealing QR of a(m,n) with the truncation |R(k,k)| <= eps |R(1,1)|: on success the le...
subroutine, public hecmw_mf_kernel_panel_lu_piv(m, n, lda, a, ldb, b, blk, blkr, u, zero, allow_delay, npiv, permc, permr, nswap, info)
LU of the panel a(m,n), b(m,n) with threshold partial pivoting among its n rows: column p takes the r...
subroutine, public hecmw_mf_kernel_gemv(m, n, lda, a, x, y)
y(m) <- y - a(m,n) * x(n)
subroutine, public hecmw_mf_kernel_panel_nopiv(m, n, lda, a, u, zero, info)
Factor the panel a(m,n) (leading n x n block LDLt, rows below by the panel solve) without pivoting an...
logical function, public hecmw_mf_kernel_blr_available()
Whether the BLR compression is available (LAPACK build).
subroutine, public hecmw_mf_kernel_dsolve(n, ldl, l, ptype, dsub, x)
x <- D^-1 x with the block diagonal D of the factored tile l(n,n).
subroutine, public hecmw_mf_kernel_trsv(n, ldl, l, x)
x <- L^-1 x with the unit lower triangle of the tile l(n,n).
subroutine, public hecmw_mf_kernel_trsm_rt(m, n, ldt, t, unit, lda, a)
a(m,n) <- a * T^-T with the lower triangle of t(n,n), unit diagonal when unit.
subroutine, public hecmw_mf_kernel_mult_nn(m, n, k, lda, a, ldb, b, ldc, c)
c(m,n) <- a(m,k) * b(k,n)
subroutine, public hecmw_mf_kernel_usolve(n, ldl, l, ldu, ut, x)
x <- U^-1 x with the diagonal of U on the diagonal of l(n,n) and its strictly upper part transposed i...
subroutine, public hecmw_mf_kernel_mult_tv(m, n, lda, a, x, y)
y(n) <- a(m,n)^T * x(m)
subroutine, public hecmw_mf_kernel_gemv_t(m, n, lda, a, x, y)
y(n) <- y - a(m,n)^T * x(m)
subroutine, public hecmw_mf_kernel_trsm(m, n, ldl, l, lda, a)
a(m,n) <- a * L^-T * D^-1 with L, D taken from the factored tile l(n,n) (1x1 pivots only).
subroutine, public hecmw_mf_kernel_panel_lu_nopiv(m, n, lda, a, ldb, b, u, zero, info)
LU of the panel a(m,n), b(m,n) (leading n x n block, rows below by the panel solves) without pivoting...
subroutine, public hecmw_mf_kernel_scale_rows(n, r, ldl, l, ptype, dsub, ldv, v, ldw, w)
w(n,r) <- D * v(n,r) with the block diagonal D of the factored tile l(n,n).
subroutine, public hecmw_mf_kernel_ldlt(n, lda, a, zero, info)
In place LDLt of the lower triangle of a(n,n) without pivoting; info is the index of the first pivot ...
subroutine, public hecmw_mf_kernel_mult_tn(m, n, k, lda, a, ldb, b, ldc, c)
c(m,n) <- a(k,m)^T * b(k,n)
subroutine, public hecmw_mf_kernel_lu(n, lda, a, ldb, b, zero, info)
In place LU of the n x n block held in a (diagonal and below) and b (above, transposed) without pivot...
subroutine, public hecmw_mf_kernel_panel_piv(m, n, lda, a, blk, u, alpha, zero, allow_delay, wk, npiv, perm, ptype, dsub, nswap, n2x2, info)
Factor the panel a(m,n) with 1x1 and 2x2 pivots chosen among its n columns. A column is accepted as a...
subroutine, public hecmw_mf_kernel_trsv_t(n, ldl, l, x)
x <- L^-T x with the unit lower triangle of the tile l(n,n).
I/O and Utility.
Definition: hecmw_util_f.F90:7
integer(kind=4), parameter kint
integer(kind=4), parameter kreal