406
407
408 TYPE(LRB_TYPE),INTENT(IN) :: LRB1,LRB2
409 INTEGER(8), intent(in) :: LA
410 REAL, intent(inout) :: A(LA)
411 INTEGER,INTENT(IN) :: NFRONT, SYM, TOL_OPT
412 INTEGER,INTENT(INOUT) :: IFLAG, IERROR
413 INTEGER(8), INTENT(IN) :: POSELTT
414 REAL, INTENT(IN), OPTIONAL :: DIAG(*)
415 INTEGER,INTENT(IN), OPTIONAL :: LD_DIAG, IW2(*)
416 INTEGER,intent(in) :: MIDBLK_COMPRESS, KPERCENT
417 REAL, intent(in) :: TOLEPS
418 REAL :: ALPHA,BETA
419 LOGICAL, INTENT(OUT) :: BUILDQ
420 REAL, intent(inout), OPTIONAL :: BLOCK(*)
421 INTEGER, INTENT(IN), OPTIONAL :: LorU
422 LOGICAL, INTENT(IN) :: LUA_ACTIVATED
423 INTEGER, INTENT(IN), OPTIONAL :: MAXI_CLUSTER
424 INTEGER, INTENT(IN), OPTIONAL :: MAXI_RANK
425 TYPE(LRB_TYPE), INTENT(INOUT), OPTIONAL :: LRB3
426 REAL, POINTER, DIMENSION(:,:) :: XY_YZ
427 REAL, ALLOCATABLE, TARGET, DIMENSION(:,:) :: XQ, R_Y
428 REAL, POINTER, DIMENSION(:,:) :: X, Y, Y1, Y2, Z
429 CHARACTER(len=1) :: SIDE, TRANSY
430 INTEGER :: K_XY, K_YZ, LDY, LDY1, LDY2, K_Y
431 INTEGER :: LDXY_YZ, SAVE_K
432 INTEGER :: I, J, RANK, MAXRANK, INFO, LWORK
433 REAL, ALLOCATABLE :: RWORK_RRQR(:)
434 REAL, ALLOCATABLE :: WORK_RRQR(:), TAU_RRQR(:),
435 & Y_RRQR(:,:)
436 INTEGER, ALLOCATABLE :: JPVT_RRQR(:)
437 INTEGER :: allocok, MREQ
438 REAL, EXTERNAL ::snrm2
439 REAL :: ONE, MONE, ZERO
440 parameter(one = 1.0e0, mone=-1.0e0)
441 parameter(zero=0.0e0)
442 IF (lrb1%M.EQ.0) THEN
443 RETURN
444 ENDIF
445 IF (lrb2%M.EQ.0) THEN
446 ENDIF
447 rank = 0
448 buildq = .false.
449 IF (lrb1%ISLR.AND.lrb2%ISLR) THEN
450 IF ((lrb1%K.EQ.0).OR.(lrb2%K.EQ.0)) THEN
451 GOTO 1200
452 ENDIF
453 allocate(y(lrb1%K,lrb2%K),stat=allocok)
454 IF (allocok > 0) THEN
455 mreq = lrb1%K*lrb2%K
456 GOTO 1570
457 ENDIF
458 x => lrb1%Q
459 k_y = lrb1%N
460 IF (sym .EQ. 0) THEN
461 y1 => lrb1%R
462 ELSE
463 allocate(y1(lrb1%K,lrb1%N),stat=allocok)
464 IF (allocok > 0) THEN
465 mreq = lrb1%K*lrb1%N
466 GOTO 1570
467 ENDIF
468 DO j=1,lrb1%N
469 DO i=1,lrb1%K
470 y1(i,j) = lrb1%R(i,j)
471 ENDDO
472 ENDDO
473 CALL smumps_lrgemm_scaling(lrb1, y1, a, la, diag,
474 & ld_diag, iw2, poseltt, nfront, block,
475 & maxi_cluster)
476 ENDIF
477 ldy1 = lrb1%K
478 z => lrb2%Q
479 y2 => lrb2%R
480 ldy2 = lrb2%K
481 CALL sgemm(
'N',
'T', lrb1%K, lrb2%K, k_y, one,
482 & y1(1,1), ldy1, y2(1,1), ldy2, zero, y(1,1), lrb1%K )
483 IF (midblk_compress.GE.1) THEN
484 lwork = lrb2%K*(lrb2%K+1)
485 allocate(y_rrqr(lrb1%K,lrb2%K),
486 & work_rrqr(lwork), rwork_rrqr(2*lrb2%K),
487 & tau_rrqr(
min(lrb1%K,lrb2%K)),
488 & jpvt_rrqr(lrb2%K),stat=allocok)
489 IF (allocok > 0) THEN
490 mreq = lrb1%K*lrb2%K + lwork + 2*lrb2%K +
491 &
min(lrb1%K,lrb2%K) + lrb2%K
492 GOTO 1570
493 ENDIF
494 DO j=1,lrb2%K
495 DO i=1,lrb1%K
496 y_rrqr(i,j) = y(i,j)
497 ENDDO
498 ENDDO
499 maxrank =
min(lrb1%K, lrb2%K)-1
500 maxrank =
max(1, int((maxrank*kpercent/100)))
501 jpvt_rrqr = 0
503 & lrb1%K, jpvt_rrqr, tau_rrqr, work_rrqr,
504 & lrb2%K, rwork_rrqr, toleps, tol_opt, rank,
505 & maxrank, info,
506 & buildq)
507 IF (rank.GT.maxrank) THEN
508 deallocate(y_rrqr, work_rrqr, rwork_rrqr, tau_rrqr,
509 & jpvt_rrqr)
510 buildq = .false.
511 ELSE
512 buildq = .true.
513 ENDIF
514 IF (buildq) THEN
515 IF (rank.EQ.0) THEN
516 deallocate(y_rrqr, work_rrqr, rwork_rrqr, tau_rrqr,
517 & jpvt_rrqr)
518 deallocate(y)
519 nullify(y)
520
521
522
523 IF (sym .NE. 0) deallocate(y1)
524 GOTO 1200
525 ELSE
526 allocate(xq(lrb1%M,rank), r_y(rank,lrb2%K),
527 & stat=allocok)
528 IF (allocok > 0) THEN
529 mreq = lrb1%M*rank + rank*lrb2%K
530 GOTO 1570
531 ENDIF
532 DO j=1, lrb2%K
533 r_y(1:
min(rank,j),jpvt_rrqr(j)) =
534 & y_rrqr(1:
min(rank,j),j)
535 IF(j.LT.rank) r_y(
min(rank,j)+1:
536 & rank,jpvt_rrqr(j))= zero
537 END DO
538
539
541 & (lrb1%K, rank, rank, y_rrqr(1,1),
542 & lrb1%K, tau_rrqr(1),
543 & work_rrqr(1), lwork, info )
544 CALL sgemm(
'N',
'N', lrb1%M, rank, lrb1%K, one,
545 & x(1,1), lrb1%M, y_rrqr(1,1), lrb1%K, zero,
546 & xq(1,1), lrb1%M)
547 deallocate(y_rrqr, work_rrqr, rwork_rrqr, tau_rrqr,
548 & jpvt_rrqr)
549 nullify(x)
550 x => xq
551 k_xy = rank
552 deallocate(y)
553 nullify(y)
554 y => r_y
555 ldy = rank
556 k_yz = lrb2%K
557 transy = 'N'
558 side = 'R'
559 ENDIF
560 ENDIF
561 ENDIF
562 IF (.NOT.buildq) THEN
563 ldy = lrb1%K
564 k_xy = lrb1%K
565 k_yz = lrb2%K
566 transy = 'N'
567 IF (lrb1%K .GE. lrb2%K) THEN
568 side = 'L'
569 ELSE
570 side = 'R'
571 ENDIF
572 ENDIF
573 ENDIF
574 IF (lrb1%ISLR.AND.(.NOT.lrb2%ISLR)) THEN
575 IF (lrb1%K.EQ.0) THEN
576 GOTO 1200
577 ENDIF
578 side = 'R'
579 k_xy = lrb1%K
580 transy = 'N'
581 z => lrb2%Q
582 x => lrb1%Q
583 ldy = lrb1%K
584 IF (sym .EQ. 0) THEN
585 y => lrb1%R
586 ELSE
587 allocate(y(lrb1%K,lrb1%N),stat=allocok)
588 IF (allocok > 0) THEN
589 mreq = lrb1%K*lrb1%N
590 GOTO 1570
591 ENDIF
592 DO j=1,lrb1%N
593 DO i=1,lrb1%K
594 y(i,j) = lrb1%R(i,j)
595 ENDDO
596 ENDDO
597 CALL smumps_lrgemm_scaling(lrb1, y, a, la, diag,
598 & ld_diag, iw2, poseltt, nfront, block,
599 & maxi_cluster)
600 ENDIF
601 k_yz = lrb2%N
602 ENDIF
603 IF ((.NOT.lrb1%ISLR).AND.lrb2%ISLR) THEN
604 IF (lrb2%K.EQ.0) THEN
605 GOTO 1200
606 ENDIF
607 side = 'L'
608 k_yz = lrb2%K
609 x => lrb1%Q
610 transy = 'T'
611 k_xy = lrb1%N
612 IF (sym .EQ. 0) THEN
613 y => lrb2%R
614 ELSE
615 allocate(y(lrb2%K,lrb2%N),stat=allocok)
616 IF (allocok > 0) THEN
617 mreq = lrb2%K*lrb2%N
618 GOTO 1570
619 ENDIF
620 DO j=1,lrb2%N
621 DO i=1,lrb2%K
622 y(i,j) = lrb2%R(i,j)
623 ENDDO
624 ENDDO
625 CALL smumps_lrgemm_scaling(lrb2, y, a, la, diag,
626 & ld_diag, iw2, poseltt, nfront, block,
627 & maxi_cluster)
628 ENDIF
629 ldy = lrb2%K
630 z => lrb2%Q
631 ENDIF
632 IF ((.NOT.lrb1%ISLR).AND.(.NOT.lrb2%ISLR)) THEN
633 IF (sym .EQ. 0) THEN
634 x => lrb1%Q
635 ELSE
636 allocate(x(lrb1%M,lrb1%N),stat=allocok)
637 IF (allocok > 0) THEN
638 mreq = lrb1%M*lrb1%N
639 GOTO 1570
640 ENDIF
641 DO j=1,lrb1%N
642 DO i=1,lrb1%M
643 x(i,j) = lrb1%Q(i,j)
644 ENDDO
645 ENDDO
646 CALL smumps_lrgemm_scaling(lrb1, x, a, la, diag,
647 & ld_diag, iw2, poseltt, nfront, block,
648 & maxi_cluster)
649 ENDIF
650 side = 'N'
651 z => lrb2%Q
652 k_xy = lrb1%N
653 ENDIF
654 IF (lua_activated) THEN
655 save_k = lrb3%K
656 IF (side == 'L') THEN
657 lrb3%K = lrb3%K+k_yz
658 ELSEIF (side == 'R') THEN
659 lrb3%K = lrb3%K+k_xy
660 ENDIF
661 ENDIF
662 IF (side == 'L') THEN
663 IF (.NOT.lua_activated) THEN
664 allocate(xy_yz(lrb1%M,k_yz),stat=allocok)
665 IF (allocok > 0) THEN
666 mreq = lrb1%M*k_yz
667 GOTO 1570
668 ENDIF
669 ldxy_yz = lrb1%M
670 ELSE
671 IF (save_k+k_yz.GT.maxi_rank) THEN
672 write(*,*) 'Internal error in SMUMPS_LRGEMM4 1a',
673 & 'K_ACC+K_CUR>K_MAX:',save_k,k_yz,maxi_rank
675 ENDIF
676 IF (lrb3%M.NE.lrb1%M) THEN
677 write(*,*) 'Internal error in SMUMPS_LRGEMM4 1b',
678 & 'LRB1%M =/= LRB3%M',lrb1%M,lrb3%M
680 ENDIF
681 xy_yz => lrb3%Q(1:lrb1%M,save_k+1:save_k+k_yz)
682 ldxy_yz = maxi_cluster
683 DO i=1,k_yz
684 lrb3%R(save_k+i,1:lrb2%M) = z(1:lrb2%M,i)
685 ENDDO
686 ENDIF
687 CALL sgemm(
'N', transy, lrb1%M, k_yz, k_xy, one,
688 & x(1,1), lrb1%M, y(1,1), ldy, zero, xy_yz(1,1),
689 & ldxy_yz)
690 IF (.NOT.lua_activated) THEN
691 CALL sgemm(
'N',
'T', lrb1%M, lrb2%M, k_yz,
alpha,
692 & xy_yz(1,1), lrb1%M, z(1,1), lrb2%M, beta,
693 & a(poseltt), nfront)
694 deallocate(xy_yz)
695 ENDIF
696 ELSEIF (side == 'R') THEN
697 IF (.NOT.lua_activated) THEN
698 allocate(xy_yz(k_xy,lrb2%M),stat=allocok)
699 IF (allocok > 0) THEN
700 mreq = k_xy*lrb2%M
701 GOTO 1570
702 ENDIF
703 ldxy_yz = k_xy
704 ELSE
705 IF (save_k+k_xy.GT.maxi_rank) THEN
706 write(*,*) 'Internal error in SMUMPS_LRGEMM4 2a',
707 & 'K_ACC+K_CUR>K_MAX:',save_k,k_xy,maxi_rank
709 ENDIF
710 IF (lrb3%N.NE.lrb2%M) THEN
711 write(*,*) 'Internal error in SMUMPS_LRGEMM4 2b',
712 & 'LRB2%M =/= LRB3%N',lrb2%M,lrb3%N
714 ENDIF
715 xy_yz => lrb3%R(save_k+1:save_k+k_xy,1:lrb2%M)
716 ldxy_yz = maxi_rank
717 DO i=1,k_xy
718 lrb3%Q(1:lrb1%M,save_k+i) = x(1:lrb1%M,i)
719 ENDDO
720 ENDIF
721 CALL sgemm(transy,
'T', k_xy, lrb2%M, k_yz, one,
722 & y(1,1), ldy, z(1,1), lrb2%M, zero, xy_yz(1,1),
723 & ldxy_yz)
724 IF (.NOT.lua_activated) THEN
725 CALL sgemm(
'N',
'N', lrb1%M, lrb2%M, k_xy,
alpha,
726 & x(1,1), lrb1%M, xy_yz(1,1), k_xy, beta, a(poseltt),
727 & nfront)
728 deallocate(xy_yz)
729 ENDIF
730 ELSE
731 CALL sgemm(
'N',
'T', lrb1%M, lrb2%M, k_xy,
alpha,
732 & x(1,1), lrb1%M, z(1,1), lrb2%M, beta, a(poseltt),
733 & nfront)
734 ENDIF
735 GOTO 1580
736 1570 CONTINUE
737
738 iflag = -13
739 ierror = mreq
740 RETURN
741 1580 CONTINUE
742
743 IF ((.NOT.lrb1%ISLR).AND.(.NOT.lrb2%ISLR)) THEN
744 IF (sym .NE. 0) deallocate(x)
745 ELSEIF ((.NOT.lrb1%ISLR).AND.lrb2%ISLR) THEN
746 IF (sym .NE. 0) deallocate(y)
747 ELSEIF (lrb1%ISLR.AND.(.NOT.lrb2%ISLR)) THEN
748 IF (sym .NE. 0) deallocate(y)
749 ELSE
750 IF (sym .NE. 0) deallocate(y1)
751 IF ((midblk_compress.GE.1).AND.buildq) THEN
752 deallocate(xq)
753 deallocate(r_y)
754 ELSE
755 deallocate(y)
756 ENDIF
757 ENDIF
758 1200 CONTINUE