!> !> @file conmat2.tpl !> !> @brief !> !> @copyright !> Copyright (©) 2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) !> SPC (Swiss Plasma Center) !> !> SPClibs is free software: you can redistribute it and/or modify it under !> the terms of the GNU Lesser General Public License as published by the Free !> Software Foundation, either version 3 of the License, or (at your option) !> any later version. !> !> SPClibs is distributed in the hope that it will be useful, but WITHOUT ANY !> WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS !> FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. !> !> You should have received a copy of the GNU Lesser General Public License !> along with this program. If not, see . !> !> @author !> (in alphabetical order) !> @author Trach-Minh Tran !> ! ! In this version local matrices E and D are precalculted ! (on all n1/n2 intervals and nterms weak-form terms ! INTERFACE SUBROUTINE coefeq(x, y, idt, idw, c) DOUBLE PRECISION, INTENT(in) :: x, y INTEGER, INTENT(out) :: idt(:,:), idw(:,:) DOUBLE PRECISION, INTENT(out) :: c(:) END SUBROUTINE coefeq END INTERFACE INTEGER, OPTIONAL :: maxder(2) ! maximum oder of derivatives ! INTEGER :: n1, nidbas1, ndim1 INTEGER :: n2, nidbas2, ndim2 INTEGER :: ng1, ng2 INTEGER :: i1, i2, ig1, ig2 INTEGER :: igt1, igt2, igw1, igw2, irow, jcol INTEGER, ALLOCATABLE :: left1(:), left2(:) ! LOGICAL :: nlper1, nlper2 ! INTEGER :: kterms ! Number of terms in weak form INTEGER :: k, kmaxder, it1, iw1, it2, iw2 INTEGER, ALLOCATABLE :: idert(:,:), iderw(:,:) ! Derivative order DOUBLE PRECISION, ALLOCATABLE :: coefs(:,:,:) ! Terms in weak form DOUBLE PRECISION :: dummy(mat%nterms) ! DOUBLE PRECISION, POINTER :: xg1(:,:), xg2(:,:), wg1(:,:), wg2(:,:) DOUBLE PRECISION, ALLOCATABLE :: fun1(:,:,:), fun2(:,:,:) DOUBLE PRECISION, ALLOCATABLE :: mata(:,:,:,:), matc(:,:), matcd(:,:,:) DOUBLE PRECISION, ALLOCATABLE :: matd(:,:,:,:,:), mate(:,:,:,:,:) !=========================================================================== ! 1.0 Prologue ! ! Properties of spline space ! CALL get_dim(spl%sp1, ndim1, n1, nidbas1) CALL get_dim(spl%sp2, ndim2, n2, nidbas2) nlper1 = spl%sp1%period nlper2 = spl%sp2%period ! ! Gauss points and weights on all intervals ! xg1 => spl%sp1%gausx ! xg1(ng1,n1) wg1 => spl%sp1%gausw ! wg1(ng1,n1) ng1 = SIZE(xg1,1) xg2 => spl%sp2%gausx wg2 => spl%sp2%gausw ng2 = SIZE(xg2,1) ! ! Derivative orders in the weak form ! kterms = mat%nterms ALLOCATE(idert(kterms,2)) ALLOCATE(iderw(kterms,2)) CALL coefeq(xg1(1,1), xg2(1,1), idert, iderw, dummy) ! ! Precalc matrix E in dimension 1 ! kmaxder = 1 IF(PRESENT(maxder)) kmaxder = maxder(1) ALLOCATE(fun1(0:nidbas1,0:kmaxder,ng1)) ALLOCATE(left1(ng1)) ALLOCATE(mate(0:nidbas1,0:nidbas1,ng1,kterms,n1)) DO i1=1,n1 left1 = i1 CALL basfun(xg1(:,i1), spl%sp1, fun1, left1) DO k=1,kterms DO ig1=1,ng1 DO iw1=0,nidbas1 DO it1=0,nidbas1 mate(it1,iw1,ig1,k,i1) = wg1(ig1,i1) * & & fun1(it1,idert(k,1),ig1) * & & fun1(iw1,iderw(k,1),ig1) END DO END DO END DO END DO END DO DEALLOCATE(fun1) DEALLOCATE(left1) ! ! Precalc matrix D in dimension 2 ! kmaxder = 1 IF(PRESENT(maxder)) kmaxder = maxder(2) ALLOCATE(fun2(0:nidbas2,0:kmaxder,ng2)) ALLOCATE(left2(ng2)) ALLOCATE(matd(0:nidbas2,0:nidbas2,ng2,kterms,n2)) DO i2=1,n2 left2 = i2 CALL basfun(xg2(:,i2), spl%sp2, fun2, left2) DO k=1,kterms DO ig2=1,ng2 DO iw2=0,nidbas2 DO it2=0,nidbas2 matd(it2,iw2,ig2,k,i2) = wg2(ig2,i2) * & & fun2(it2,idert(k,2),ig2) * & & fun2(iw2,iderw(k,2),ig2) END DO END DO END DO END DO END DO DEALLOCATE(fun2) DEALLOCATE(left2) !=========================================================================== ! 2.0 Assembly loop ! ! Physical coefficients in Weak form ! ALLOCATE(coefs(kterms,ng1,ng2)) ALLOCATE(matc(ng1,ng2)) ! ! Allocate local matrix A ! ALLOCATE(mata(0:nidbas1,0:nidbas1,0:nidbas2,0:nidbas2)) ALLOCATE(matcd(ng1,0:nidbas2,0:nidbas2)) ! DO i1=1,n1 DO i2=1,n2 ! ! Coefficients of the weak form ! DO ig1=1,ng1 DO ig2=1,ng2 CALL coefeq(xg1(ig1,i1), xg2(ig2,i2), & & idert, iderw, coefs(:,ig1,ig2)) END DO END DO ! ! Compute local matrix: A <- E*(C*D^T) + A ! mata = 0.0d0 DO k=1,kterms ! matc(1:ng1,1:ng2) = coefs(k,1:ng1,1:ng2) ! CALL dgemm('N', 'T', ng1, (nidbas2+1)*(nidbas2+1), ng2, 1.0d0, & & matc, ng1, matd(0,0,1,k,i2), (nidbas2+1)*(nidbas2+1), 0.0d0, & & matcd, ng1) CALL dgemm('N', 'N', (nidbas1+1)*(nidbas1+1), (nidbas2+1)*(nidbas2+1), & & ng1, 1.0d0, mate(0,0,1,k,i1), (nidbas1+1)*(nidbas1+1), matcd, ng1, 1.0d0, & & mata, (nidbas1+1)*(nidbas1+1)) ! END DO ! ! Map local matrix A to global matrix ! DO it1=0,nidbas1 igt1 = i1+it1; IF(nlper1) igt1 = MODULO(igt1-1,n1) + 1 DO it2=0,nidbas2 igt2 = i2+it2; IF(nlper2) igt2 = MODULO(igt2-1, n2) + 1 irow = igt2 + (igt1-1)*n2 DO iw1=0,nidbas1 igw1 = i1+iw1; IF(nlper1) igw1 = MODULO(igw1-1,n1) + 1 DO iw2=0,nidbas2 igw2 = i2+iw2; IF(nlper2) igw2 = MODULO(igw2-1, n2) + 1 jcol = igw2 + (igw1-1)*n2 CALL updtmat(mat, irow, jcol, mata(it1,iw1,it2,iw2)) END DO END DO END DO END DO ! END DO END DO !=========================================================================== ! 9.0 Epilogue ! DEALLOCATE(idert, iderw, coefs) DEALLOCATE(mata) DEALLOCATE(matc) DEALLOCATE(matd) DEALLOCATE(matcd) DEALLOCATE(mate)