fb_diff_stencil_procedures.f90 Source File


Source Code

!-----------------------------------------------------------------------------------------------------------------------------------
! This file is part of ReMKiT1D.
!
! ReMKiT1D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as 
! published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
!
! ReMKiT1D 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 General Public License along with ReMKiT1D. If not, see <https://www.gnu.org/licenses/>. 
!
! Copyright 2023 United Kingdom Atomic Energy Authority (stefan.mijin@ukaea.uk)
!-----------------------------------------------------------------------------------------------------------------------------------
submodule (fb_diff_stencil_gen_class) fb_diff_stencil_gen_procedures
!! author: Stefan Mijin 
!! 
!! Contains module procedures associated with the forward/backward difference stencil value generator class

implicit none

!-----------------------------------------------------------------------------------------------------------------------------------
contains
!-----------------------------------------------------------------------------------------------------------------------------------
module subroutine initFBValGen(this,partitionObj,procRank,innerJ,outerJ,xPeriodic,backwardsDiff,staggeredGridMode) 
    !! Forward/backward differentiation stencil value generator initialization routine

    class(FBDiffStencilValGenerator)          ,intent(inout)  :: this
    type(Partition)                           ,intent(in)     :: partitionObj !! Partition object used to determine local number of rows
    integer(ik)                               ,intent(in)     :: procRank !! Current processor rank
    real(rk) ,dimension(:)                    ,intent(in)     :: innerJ !! Inner/column jacobian/hodge star (should conform to x-grid)
    real(rk) ,dimension(:)                    ,intent(in)     :: outerJ !! Outer/row inverse jacobian/hodge star (should conform to x-grid)
    logical ,optional                         ,intent(in)     :: xPeriodic !! Used to determine if outer processors should have their stencils trimmed. 
                                                                           !! Defaults to .false.  
    logical ,optional                         ,intent(in)     :: backwardsDiff !! If true the difference is backwards. Defaults to .false.
    logical ,optional                         ,intent(in)     :: staggeredGridMode !! If true will zero out the rightmost contribution to backwards differencing or remove last row for forward differencing

    integer(ik) :: inferredGridSize

    if (assertions .or. assertionLvl >= 0) call assert(partitionObj%isDefined(),&
    "Undefined partition object passed to fb diff val generator constructor")

    inferredGridSize = maxval(partitionObj%getMaxX())

    if (assertions .or. assertionLvl >= 0) then 
        call assert(size(innerJ) == inferredGridSize,"innerJ passed to initFBValGen does not conform to inferred grid size")
        call assert(size(outerJ) == inferredGridSize,"outerJ passed to initFBValGen does not conform to inferred grid size")
    end if

    this%periodicGrid = .false. 
    this%backwardsDiff = .false. 

    if (present(xPeriodic)) this%periodicGrid = xPeriodic
    if (present(backwardsDiff)) this%backwardsDiff = backwardsDiff 

    this%minX = partitionObj%getMinXAtInd(procRank+1)
    this%maxX = partitionObj%getMaxXAtInd(procRank+1)

    this%innerJ = innerJ 
    this%outerJ = outerJ

    this%staggeredGridMode = .false. 
    if (present(staggeredGridMode)) this%staggeredGridMode = staggeredGridMode
    
    call this%makeDefined()

end subroutine initFBValGen
!-----------------------------------------------------------------------------------------------------------------------------------
module subroutine calcFBVals(this,varCont,res,mbData,hostModel)
    !! Calculate forward/backwards diff stencil values in place (does not depend on varCont)

    class(FBDiffStencilValGenerator)            ,intent(inout) :: this
    type(VariableContainer)                     ,intent(in)    :: varCont
    type(RealArray) ,allocatable ,dimension(:)  ,intent(inout) :: res
    class(ModelboundData) ,optional             ,intent(in)    :: mbData
    class(ModelSurrogate) ,optional             ,intent(in)    :: hostModel

    logical :: containsLeftBoundary ,containsRightBoundary

    integer(ik) :: i ,localSize

    if (assertions) then 
        call assert(this%isDefined(),"calcFBVals called from undefined stencil value generator")
        call assert(varCont%isDefined(),"Undefined variable container passed to calcFBVals")
    end if

    containsLeftBoundary = this%minX == 1
    containsRightBoundary = this%maxX == size(this%innerJ)

    localSize = this%maxX - this%minX + 1
    if (.not. this%periodicGrid .and. this%staggeredGridMode) then 
        if (.not. this%backwardsDiff .and. containsRightBoundary) localSize = localSize - 1
    end if

    if (allocated(res)) then 
        if (assertions) &
        call assert(size(res) == localSize,"res passed to calcFBVals does not conform to local x-grid size")
    else
        allocate(res(localSize))
    end if
        
    if (this%backwardsDiff) then 
        if (containsLeftBoundary) then 
            if (this%periodicGrid) then 
                res(1)%entry = this%outerJ(this%minX)*[-this%innerJ(size(this%innerJ)),this%innerJ(this%minX)]
            else
                res(1)%entry = this%outerJ(this%minX)*[this%innerJ(this%minX)]
            end if
        else 
            res(1)%entry = this%outerJ(this%minX)*[-this%innerJ(this%minX-1),this%innerJ(this%minX)]
        end if

        do i = 1,this%maxX - this%minX - 1
            res(i+1)%entry = this%outerJ(this%minX+i)*[-this%innerJ(this%minX-1+i),this%innerJ(this%minX+i)]
        end do

        if (this%staggeredGridMode .and. (.not. this%periodicGrid ).and. containsRightBoundary) then 
            res(size(res))%entry = this%outerJ(this%maxX)*[-this%innerJ(this%maxX-1),real(0,kind=rk)]
        else
            res(size(res))%entry = this%outerJ(this%maxX)*[-this%innerJ(this%maxX-1),this%innerJ(this%maxX)]
        end if

    else

        do i = 1,this%maxX - this%minX
            res(i)%entry = this%outerJ(this%minX+i-1)*[-this%innerJ(this%minX-1+i),this%innerJ(this%minX+i)]
            
        end do

        if (containsRightBoundary) then 
            if (this%periodicGrid) then 
                res(size(res))%entry = this%outerJ(this%maxX)*[-this%innerJ(this%maxX),this%innerJ(1)]
            else if (.not. this%staggeredGridMode) then
                res(size(res))%entry = this%outerJ(this%maxX)*[-this%innerJ(this%maxX)]
            end if
        else 
            res(size(res))%entry = this%outerJ(this%maxX)*[-this%innerJ(this%maxX),this%innerJ(this%maxX+1)]
        end if
    end if

end subroutine calcFBVals
!-----------------------------------------------------------------------------------------------------------------------------------
!-----------------------------------------------------------------------------------------------------------------------------------
end submodule fb_diff_stencil_gen_procedures
!-----------------------------------------------------------------------------------------------------------------------------------