module ProlongMeshAndSolution use SMConstants use NodalStorageClass use FacePatchClass private public ProlongMeshToGaussPoints, ProlongSolutionToGaussPoints contains subroutine ProlongMeshToGaussPoints(e,spA,N1,N2) ! ! ************************************************************************* ! ! The code arrives to this subroutine if any Nmesh != Nout. This ! needs the mesh coordinates to be extrapolated to the solution order. ! This is not a major issue for straight sided element. ! ! For curved elements, one might extend the order just evaluating the ! mapping at the new set of Gauss points, but to reduce the order, ! it is required that the mapping is evaluated at a new set of ! Chebyshev-Lobatto points, and then evaluated again to Gauss points. ! Just for safety, all elements are traduced to Chebyshev points first, ! and then to Gauss points. This could be avoided in the future. ! ! ************************************************************************* ! use TransfiniteMapClass use MappedGeometryClass use Storage implicit none type(Element_t) :: e type(NodalStorage_t), target, intent(in) :: spA(0:) integer , intent(in) :: N1(3) integer , intent(in) :: N2(3) ! ! --------------- ! Local variables ! --------------- ! ////////////////// ! // spA pointers // ! ////////////////// type(NodalStorage_t), pointer :: spAMxi type(NodalStorage_t), pointer :: spAMeta type(NodalStorage_t), pointer :: spAMzeta type(NodalStorage_t), pointer :: spAOxi type(NodalStorage_t), pointer :: spAOeta type(NodalStorage_t), pointer :: spAOzeta ! //////////////////////////////////////// ! // Mesh mapping prolongation to faces // ! //////////////////////////////////////// real(kind=RP) :: face1Original(1:3, 0:e % Nmesh(1), 0:e % Nmesh(3)) real(kind=RP) :: face2Original(1:3, 0:e % Nmesh(1), 0:e % Nmesh(3)) real(kind=RP) :: face3Original(1:3, 0:e % Nmesh(1), 0:e % Nmesh(2)) real(kind=RP) :: face4Original(1:3, 0:e % Nmesh(2), 0:e % Nmesh(3)) real(kind=RP) :: face5Original(1:3, 0:e % Nmesh(1), 0:e % Nmesh(2)) real(kind=RP) :: face6Original(1:3, 0:e % Nmesh(2), 0:e % Nmesh(3)) ! ///////////////////////////////////////// ! // Chebyshev-Lobatto face interpolants // ! ///////////////////////////////////////// real(kind=RP) :: xiCL (0:e % Nout(1)) real(kind=RP) :: etaCL (0:e % Nout(2)) real(kind=RP) :: zetaCL (0:e % Nout(3)) real(kind=RP) :: face1CL(1:3, 0:e % Nout(1), 0:e % Nout(3)) real(kind=RP) :: face2CL(1:3, 0:e % Nout(1), 0:e % Nout(3)) real(kind=RP) :: face3CL(1:3, 0:e % Nout(1), 0:e % Nout(2)) real(kind=RP) :: face4CL(1:3, 0:e % Nout(2), 0:e % Nout(3)) real(kind=RP) :: face5CL(1:3, 0:e % Nout(1), 0:e % Nout(2)) real(kind=RP) :: face6CL(1:3, 0:e % Nout(2), 0:e % Nout(3)) ! ///////////////////////////// ! // Define the new element // ! ///////////////////////////// type(FacePatch) :: facePatches(6) type(TransfiniteHexMap) :: hexMap integer :: i, j, k real(kind=RP) :: localCoords(3) ! Define some pointers ! -------------------- spAMxi => spA(N1(1)) spAMeta => spA(N1(2)) spAMzeta => spA(N1(3)) spAOxi => spA(N2(1)) spAOeta => spA(N2(2)) spAOzeta => spA(N2(3)) ! ! Get the faces coordinates from the mapping ! ------------------------------------------ call InterpolateFaces(e % Nmesh,spAMxi,spAMeta,spAMzeta,e % x,face1Original,& face2Original,& face3Original,& face4Original,& face5Original,& face6Original ) ! ! Construct face patches ! ---------------------- call facePatches(1) % Construct( spAMxi % x , spAMzeta % x, face1Original ) call facePatches(2) % Construct( spAMxi % x , spAMzeta % x, face2Original ) call facePatches(3) % Construct( spAMxi % x , spAMeta % x , face3Original ) call facePatches(4) % Construct( spAMeta % x , spAMzeta % x, face4Original ) call facePatches(5) % Construct( spAMxi % x , spAMeta % x , face5Original ) call facePatches(6) % Construct( spAMeta % x , spAMzeta % x, face6Original ) ! ! Construct the interpolants based on Chebyshev-Lobatto points ! ------------------------------------------------------------ xiCL = RESHAPE( (/ ( -cos((i)*PI/(e % Nout(1))),i=0, e % Nout(1)) /), (/ e % Nout(1) + 1 /) ) etaCL = RESHAPE( (/ ( -cos((i)*PI/(e % Nout(2))),i=0, e % Nout(2)) /), (/ e % Nout(2) + 1 /) ) zetaCL = RESHAPE( (/ ( -cos((i)*PI/(e % Nout(3))),i=0, e % Nout(3)) /), (/ e % Nout(3) + 1 /) ) call ProjectFaceToNewPoints(facePatches(1), e % Nout(1), xiCL , e % Nout(3), zetaCL, face1CL) call ProjectFaceToNewPoints(facePatches(2), e % Nout(1), xiCL , e % Nout(3), zetaCL, face2CL) call ProjectFaceToNewPoints(facePatches(3), e % Nout(1), xiCL , e % Nout(2), etaCL , face3CL) call ProjectFaceToNewPoints(facePatches(4), e % Nout(2), etaCL, e % Nout(3), zetaCL, face4CL) call ProjectFaceToNewPoints(facePatches(5), e % Nout(1), xiCL , e % Nout(2), etaCL , face5CL) call ProjectFaceToNewPoints(facePatches(6), e % Nout(2), etaCL, e % Nout(3), zetaCL, face6CL) ! ! Destruct face patches ! --------------------- call facePatches(1) % Destruct() call facePatches(2) % Destruct() call facePatches(3) % Destruct() call facePatches(4) % Destruct() call facePatches(5) % Destruct() call facePatches(6) % Destruct() ! ! Construct the new Chebyshev-Lobatto face patches ! ------------------------------------------------ call facePatches(1) % Construct( xiCL , zetaCL, face1CL ) call facePatches(2) % Construct( xiCL , zetaCL, face2CL ) call facePatches(3) % Construct( xiCL , etaCL , face3CL ) call facePatches(4) % Construct( etaCL, zetaCL, face4CL ) call facePatches(5) % Construct( xiCL , etaCL , face5CL ) call facePatches(6) % Construct( etaCL, zetaCL, face6CL ) ! ! Construct the geometry mapper ! ----------------------------- call hexMap % constructWithFaces( facePatches ) ! ! Construct the mapping interpolant ! --------------------------------- do k = 0, e % Nout(3) ; do j = 0, e % Nout(2) ; do i = 0, e % Nout(1) localCoords = (/ spAOxi % x(i), spAOeta % x(j), spAOzeta % x(k) /) e % xOut(:,i,j,k) = hexMap % transfiniteMapAt(localCoords) end do ; end do ; end do ! ! Destruct face patches ! --------------------- call facePatches(1) % Destruct() call facePatches(2) % Destruct() call facePatches(3) % Destruct() call facePatches(4) % Destruct() call facePatches(5) % Destruct() call facePatches(6) % Destruct() call hexMap % Destruct() end subroutine ProlongMeshToGaussPoints subroutine ProlongSolutionToGaussPoints(NEQ,Nsol,Q,Nout,Qout,Tx,Ty,Tz) implicit none integer, intent(in) :: NEQ integer, intent(in) :: Nsol(3) real(kind=RP), intent(in) :: Q(1:NEQ,0:Nsol(1),0:Nsol(2),0:Nsol(3)) integer, intent(in) :: Nout(3) real(kind=RP), intent(out) :: Qout(1:NEQ,0:Nout(1),0:Nout(2),0:Nout(3)) real(kind=RP), intent(in) :: Tx(0:Nout(1),0:Nsol(1)) real(kind=RP), intent(in) :: Ty(0:Nout(2),0:Nsol(2)) real(kind=RP), intent(in) :: Tz(0:Nout(3),0:Nsol(3)) ! ! --------------- ! Local variables ! --------------- ! integer :: i, j, k, l, m, n Qout = 0.0_RP do n = 0, Nsol(3) ; do m = 0, Nsol(2) ; do l = 0, Nsol(1) do k = 0, Nout(3) ; do j = 0, Nout(2) ; do i = 0, Nout(1) Qout(:,i,j,k) = Qout(:,i,j,k) + Q(:,l,m,n) * Tx(i,l) * Ty(j,m) * Tz(k,n) end do ; end do ; end do end do ; end do ; end do end subroutine ProlongSolutionToGaussPoints ! !///////////////////////////////////////////////////////////////////////////////////////// ! ! Auxiliary subroutines ! -------------------- ! !///////////////////////////////////////////////////////////////////////////////////////// ! subroutine InterpolateFaces(N,spAxi,spAeta,spAzeta,x,face1,face2,face3,face4,face5,face6) ! ! **************************************************************** ! ! This subroutine obtains the faces coordinates from the ! mapping interpolant x. ! ! **************************************************************** ! implicit none integer, intent(in) :: N(3) type(NodalStorage_t), intent(in) :: spAxi type(NodalStorage_t), intent(in) :: spAeta type(NodalStorage_t), intent(in) :: spAzeta real(kind=RP), intent(in) :: x(1:3,0:N(1),0:N(2),0:N(3)) real(kind=RP), intent(out) :: face1(1:3,0:N(1),0:N(3)) real(kind=RP), intent(out) :: face2(1:3,0:N(1),0:N(3)) real(kind=RP), intent(out) :: face3(1:3,0:N(1),0:N(2)) real(kind=RP), intent(out) :: face4(1:3,0:N(2),0:N(3)) real(kind=RP), intent(out) :: face5(1:3,0:N(1),0:N(2)) real(kind=RP), intent(out) :: face6(1:3,0:N(2),0:N(3)) ! ! --------------- ! Local variables ! --------------- ! integer :: i, j, k ! ! faces (1,2) - eta direction ! --------------------------- face1 = 0.0_RP face2 = 0.0_RP do k = 0, N(3) ; do j = 0, N(2) ; do i = 0, N(1) face1(:,i,k) = face1(:,i,k) + x(:,i,j,k) * spAeta % v(j,1) face2(:,i,k) = face2(:,i,k) + x(:,i,j,k) * spAeta % v(j,2) end do ; end do ; end do ! ! faces (3,5) - zeta direction ! ---------------------------- face3 = 0.0_RP face5 = 0.0_RP do k = 0, N(3) ; do j = 0, N(2) ; do i = 0, N(1) face3(:,i,j) = face3(:,i,j) + x(:,i,j,k) * spAzeta % v(k,1) face5(:,i,j) = face5(:,i,j) + x(:,i,j,k) * spAzeta % v(k,2) end do ; end do ; end do ! ! faces (4,6) - xi direction ! -------------------------- face4 = 0.0_RP face6 = 0.0_RP do k = 0, N(3) ; do j = 0, N(2) ; do i = 0, N(1) face4(:,j,k) = face4(:,j,k) + x(:,i,j,k) * spAxi % v(i,1) face6(:,j,k) = face6(:,j,k) + x(:,i,j,k) * spAxi % v(i,2) end do ; end do ; end do end subroutine InterpolateFaces end module ProlongMeshAndSolution