scaling_lbc_stencil_gen_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 (scaling_lbc_stencil_gen_class) scaling_lbc_stencil_gen_procedures
!! author: Stefan Mijin 
!! 
!! Contains module procedures associated with the scaling logical boundary condition stencil generator class

implicit none

!-----------------------------------------------------------------------------------------------------------------------------------
contains
!-----------------------------------------------------------------------------------------------------------------------------------
module subroutine initScalingLBCGen(this,vspaceObj,isActive,fDeriv,fDerivReqIndices,colL,dx,includedDecompHarmonics) 
    !! Scaling logical boundary condition value generator initialization routine

    class(ScalingLBCStencilGen)               ,intent(inout)  :: this
    type(VSpace)                              ,intent(in)     :: vspaceObj !! VSpace object used to get grid data 
    logical                                   ,intent(in)     :: isActive !! Set to true if the process containing this has a boundary where this is to be applied 
    type(FScalingDerivation)                  ,intent(in)     :: fDeriv !! Derivation used to get scaling factors 
    integer(ik) ,dimension(:)                 ,intent(in)     :: fDerivReqIndices !! Indices required for scaling extrapolation derivation
    integer(ik)                               ,intent(in)     :: colL !! Column l harmonic
    real(rk)                                  ,intent(in)     :: dx !! Boundary cell width
    integer(ik) ,optional ,dimension(:)       ,intent(in)     :: includedDecompHarmonics  !! Harmonics to be included in the decomposition for this generator (useful for right boundary on staggered grid). Defaults to all harmonics.

    integer(ik) :: i 

    if (assertions) then 
        call assert(vspaceObj%isDefined(),"Undefined VSpace object passed to initScalingLBCGen")
        call assert(fDeriv%isDefined(),"Undefined FScalingDerivation object passed to initScalingLBCGen")
    end if

    this%isActive = isActive 

    this%fDeriv = fDeriv
    this%fDerivReqVarIndices = fDerivReqIndices

    this%colL = colL 

    this%vGrid = vspaceObj%getVGrid()
    this%vGridWidths = vspaceObj%getVCellWidths()

    allocate(this%bufferPl(size(this%vGrid),vspaceObj%getNumH()))

    if (present(includedDecompHarmonics)) then 
        this%includedDecompHarmonics = includedDecompHarmonics
    else
        this%includedDecompHarmonics = [(i,i=1,vspaceObj%getNumH())]
    end if

    this%dx = dx
    call this%makeDefined()

end subroutine initScalingLBCGen
!-----------------------------------------------------------------------------------------------------------------------------------
module subroutine calcScalingLBCVals(this,varCont,res,mbData,hostModel)
    !! Calculate scaling logical boundary condition values in place 

    class(ScalingLBCStencilGen)                  ,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

    integer(ik) :: i ,j ,coCell 

    real(rk) ,dimension(2) :: interpCoords, interpWidths ,interpCoeffs ,scalingFactors

    if (assertions) then 
        call assert(this%isDefined(),"calcScalingLBCVals called from undefined stencil generator")
        call assert(varCont%isDefined(),"Undefined VariableContainer passed to calcScalingLBCVals")
        call assert(present(mbData),"mbData must be present when calling calcScalingLBCVals")
        call assert(mbData%isDefined(),"Undefined mbData passed to calcScalingLBCVals")
    end if

    if (this%isActive) then

        if (.not. allocated(res)) then 
            allocate(res(size(this%vGrid)))
            do i = 1,size(res)-1
                allocate(res(i)%entry(2*size(this%includedDecompHarmonics)))
            end do
            allocate(res(size(res))%entry(size(this%includedDecompHarmonics)))
        else
            call assert(size(res)==size(this%vGrid),"res passed to calcScalingLBCVals not of expected size")
            do i = 1,size(res)-1
                call assert(size(res(i)%entry)==2*size(this%includedDecompHarmonics),&
                "res passed to calcScalingLBCVals not of expected size")
            end do
            call assert(size(res(size(res))%entry)==size(this%includedDecompHarmonics),&
                "res passed to calcScalingLBCVals not of expected size")
        end if

        select type (mbData)
        type is (ModelboundLBCData)

            this%bufferPl = mbData%getPll(this%colL)
            interpCoeffs = mbData%getInterpCoeffs()
            interpCoords = mbData%getInterpCoords()
            interpWidths = mbData%getInterpWidths()
            coCell = mbData%getCoCell()
            scalingFactors = this%fDeriv%getScalingFactors(varCont%variables,this%fDerivReqVarIndices)/this%dx

            !Cells before interpolation
            do i = 1,coCell - 2
                res(i)%entry = 0
                do j = 1,size(this%includedDecompHarmonics)
                    res(i)%entry(2*j-1) = scalingFactors(1+mod(this%includedDecompHarmonics(j)-1,2))&
                                     *this%vGrid(i)*this%bufferPl(i,this%includedDecompHarmonics(j))
                end do
            end do

            !Cells around interpolation
            do j = 1,size(this%includedDecompHarmonics)
                res(coCell-1)%entry(2*j-1) = scalingFactors(1+mod(this%includedDecompHarmonics(j)-1,2))&
                                         *interpCoords(1)**2*interpWidths(1)*interpCoeffs(1)&
                                         *this%bufferPl(coCell-1,this%includedDecompHarmonics(j))&
                                         /(this%vGrid(coCell-1)*this%vGridWidths(coCell-1))
                                         
                res(coCell-1)%entry(2*j) = scalingFactors(1+mod(this%includedDecompHarmonics(j)-1,2))&
                                         *interpCoords(1)**2*interpWidths(1)&
                                         *(real(1,kind=rk) - interpCoeffs(1))&
                                         *this%bufferPl(coCell-1,this%includedDecompHarmonics(j))&
                                         /(this%vGrid(coCell-1)*this%vGridWidths(coCell-1))
            end do

            do j = 1,size(this%includedDecompHarmonics)

                res(coCell)%entry(2*j-1) = scalingFactors(1+mod(this%includedDecompHarmonics(j)-1,2))&
                                            *interpCoords(2)**2*interpWidths(2)&
                                            *interpCoeffs(2)*this%bufferPl(coCell,this%includedDecompHarmonics(j))&
                                            /(this%vGrid(coCell)*this%vGridWidths(coCell))

               res(coCell)%entry(2*j) = scalingFactors(1+mod(this%includedDecompHarmonics(j)-1,2))&
                                    *interpCoords(2)**2*interpWidths(2)*(real(1,kind=rk)-interpCoeffs(2))&
                                    *this%bufferPl(coCell,this%includedDecompHarmonics(j))&
                                    /(this%vGrid(coCell)*this%vGridWidths(coCell))

            end do

            ! Cells after interpolation 

            do i = coCell+1,size(res)-1
                res(i)%entry = 0
                do j = 1,size(this%includedDecompHarmonics)
                    res(i)%entry(2*j-1) = scalingFactors(1+mod(this%includedDecompHarmonics(j)-1,2))&
                                      *this%vGrid(i)*this%bufferPl(i,this%includedDecompHarmonics(j))
                end do
            end do

            do j = 1,size(this%includedDecompHarmonics)
                res(size(res))%entry(j) = scalingFactors(1+mod(this%includedDecompHarmonics(j)-1,2))&
                                  *this%vGrid(size(res))*this%bufferPl(size(res),this%includedDecompHarmonics(j))
            end do

        class default 

            error stop "unsupported modelbound data detected in calcScalingLBCVals"

        end select

    else
        if (.not. allocated(res)) then 
            allocate(res(0))
        else
            call assert(size(res)==0,"res passed to calcScalingLBCVals not of expected size")
        end if
    end if

end subroutine calcScalingLBCVals
!-----------------------------------------------------------------------------------------------------------------------------------
!-----------------------------------------------------------------------------------------------------------------------------------
end submodule scaling_lbc_stencil_gen_procedures
!-----------------------------------------------------------------------------------------------------------------------------------