evaluate all modes at all interpolation points, making use of the tensor product: y_ij = DOFs_mn * SIN(mt_i - nz_j ) => SIN(mt_i) DOFs_mn COS(nz_j) -COS(mt_i) DOFs_mn SIN(nz_j) y_ij = DOFs_mn * COS(mt_i - nz_j ) => COS(mt_i) DOFs_mn COS(nz_j) +SIN(mt_i) DOFs_mn SIN(nz_j) => a1_im DOFs_mn b1_nj + a2_im DOFs_mn b2_nj can be written as 2 SPECIAL MATMAT operations: c(i,1,n)=a1(i,m) DOFs(m,n) , c(i,2,n) = a2(i,m) DOFs(m,n) => c(i,d,n) = DOT_PROD(a(i,d,1:mmax),DOFs(1:mmax,n)) y(i,j) = c(i,1,n) b1(n,j) + c(i,2,n) b2(n,j) = DOT_PROD(c(i,1:2,1:nmax),b(1:2,1:nmax,j) the 1D ordering in y does not neead a reshape, y(i,j) => y(1:mn_IP), 1D array data can be kept, as it is passed (with its start adress) to DGEMM.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(in) | :: | sf |
self |
||
| integer, | intent(in) | :: | deriv |
=0: base, =2: dthet , =3: dzeta |
||
| real(kind=wp), | intent(in) | :: | DOFs(:) |
array of all modes (sf%modes) |
FUNCTION fBase_evalDOF_IP_tens(sf,deriv,DOFs) RESULT(y_IP) ! MODULES IMPLICIT NONE !----------------------------------------------------------------------------------------------------------------------------------- ! INPUT VARIABLES CLASS(t_fBase), INTENT(IN ) :: sf !! self INTEGER , INTENT(IN ) :: deriv !! =0: base, =2: dthet , =3: dzeta REAL(wp) , INTENT(IN ) :: DOFs(:)!! array of all modes (sf%modes) !----------------------------------------------------------------------------------------------------------------------------------- ! OUTPUT VARIABLES REAL(wp) :: y_IP(sf%mn_IP) !----------------------------------------------------------------------------------------------------------------------------------- ! LOCAL VARIABLES INTEGER :: iMode,offset,mTotal,nTotal REAL(wp) :: Amn(1:sf%mTotal1D,-sf%mn_max(2):sf%mn_max(2)) REAL(wp) :: Ctmp(1:sf%mn_nyq(1),1:2,-sf%mn_max(2):sf%mn_max(2)) !=================================================================================================================================== IF(SIZE(DOFs,1).NE.sf%modes) CALL abort(__STAMP__, & 'nDOF not correct when calling fBase_evalDOF_IP_tens' ) offset=sf%mTotal1D-(sf%mn_max(1)+1) !=0 if sin or cos, =sf%mn_max(1)+1 if sin+cos !initialize non existing modes to zero Amn(1,-sf%mn_max(2):0)=0.0_wp IF(offset.GT.0) Amn(offset+1,-sf%mn_max(2):0)=0.0_wp !copy DOFs to (0:m_max , -n_max:n_max) matrix, careful: Xmn(2,:) has nfp factor! DO iMode=sf%sin_range(1)+1,sf%sin_range(2) Amn(1+sf%Xmn(1,iMode),sf%Xmn(2,iMode)/sf%nfp)=DOFs(iMode) END DO DO iMode=sf%cos_range(1)+1,sf%cos_range(2) Amn(offset+1+sf%Xmn(1,iMode),sf%Xmn(2,iMode)/sf%nfp)=DOFs(iMode) END DO mTotal= sf%mTotal1D nTotal=2*sf%mn_max(2)+1 !-n_max:n_nax SELECT CASE(deriv) CASE(0) ! DO n=-sf%mn_max(2),sf%mn_max(2) ! DO i=1,sf%mn_nyq(1) ! Ctmp(i,1,n)=SUM(sf%base1D_IPthet(i,1,:)*Amn(:,n)) ! Ctmp(i,2,n)=SUM(sf%base1D_IPthet(i,2,:)*Amn(:,n)) ! END DO !i ! END DO !n ! k=0 ! DO j=1,sf%mn_nyq(2) ! DO i=1,sf%mn_nyq(1) ! k=k+1 ! y_IP(k)=SUM(Ctmp(i,1:2,:)*sf%base1D_IPzeta(1:2,:,j)) ! END DO !i ! END DO !j __DGEMM_NN(Ctmp,2*sf%mn_nyq(1), mTotal,sf%base1D_IPthet, mTotal, nTotal,Amn) __DGEMM_NN(y_IP, sf%mn_nyq(1),2*nTotal, Ctmp,2*nTotal,sf%mn_nyq(2),sf%base1D_IPzeta) CASE(DERIV_THET) __DGEMM_NN(Ctmp,2*sf%mn_nyq(1), mTotal,sf%base1D_dthet_IPthet, mTotal, nTotal,Amn) __DGEMM_NN(y_IP, sf%mn_nyq(1),2*nTotal, Ctmp,2*nTotal,sf%mn_nyq(2),sf%base1D_IPzeta) CASE(DERIV_ZETA) __DGEMM_NN(Ctmp,2*sf%mn_nyq(1), mTotal,sf%base1D_IPthet, mTotal, nTotal,Amn) __DGEMM_NN(y_IP, sf%mn_nyq(1),2*nTotal, Ctmp,2*nTotal,sf%mn_nyq(2),sf%base1D_dzeta_IPzeta) CASE DEFAULT !for other derivatives, resort to not precomputed/ explicit computation: y_IP = sf%evalDOF_xn(sf%mn_IP,sf%x_IP,deriv,DOFs) END SELECT END FUNCTION fBase_evalDOF_IP_tens