v_diffusion_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 (v_diffusion_stencil_gen_class) v_diffusion_stencil_gen_procedures
!! author: Stefan Mijin 
!! 
!! Contains module procedures associated with the d(Ad/dv)/dv stencil generator class

implicit none

!-----------------------------------------------------------------------------------------------------------------------------------
contains
!-----------------------------------------------------------------------------------------------------------------------------------
module subroutine initVDiffValGen(this,partitionObj,vspaceObj,procRank,activeXCoords,fixedA,mbA,adfAtZero) 
    !! d(Ad/dv)/dv stencil value generator initialization routine

    class(VDiffStencilGen)                    ,intent(inout)  :: this
    type(Partition)                           ,intent(in)     :: partitionObj !! Partition object used to determine local number of rows
    type(VSpace)                              ,intent(in)     :: vspaceObj !! VSpace object used to get interpolation object
    integer(ik)                               ,intent(in)     :: procRank !! Current processor rank
    integer(ik) ,dimension(:)                 ,intent(in)     :: activeXCoords !! List of active global x coords
    real(rk) ,optional   ,dimension(:)        ,intent(in)     :: fixedA !! Fixed A values (size numV). Defaults to ones.
    character(*) ,optional                    ,intent(in)     :: mbA !! Optional modelbound value for A (single harmonic variable). Overrides fixed values.
    real(rk) ,optional ,dimension(2)          ,intent(in)     :: adfAtZero !! Optional extrapolation of A*df/dv at zero in the form A1*f(v1)+A2*f(v2) where all A's are fixed. 

    integer(ik) :: i ,minX ,maxX

    real(rk) ,allocatable ,dimension(:) :: vGridCopy

    if (assertions) then 
        call assert(partitionObj%isDefined(),"Undefined partition passed to velocity diffusion stencil value generator constructor")
        call assert(vspaceObj%isDefined(),"Undefined VSpace passed to velocity diffusion stencil value generator constructor")
    end if

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

    this%usedXCoords = pack(activeXCoords,activeXCoords >= minX .and. activeXCoords <= maxX) - minX + 1

    this%numV = vspaceObj%getNumV()

    this%bufferA = [(real(1,kind=rk),i=1,this%numV)]

    if (present(fixedA)) then
        if (assertions) call assert(size(fixedA)==this%numV,&
        "fixedA passed to velocity diffusion stencil value generator constructor not of size numV")

        this%bufferA = fixedA
    end if

    if (present(mbA)) then
        deallocate(this%bufferA) 
        this%modelboundA = mbA 
    end if 

    this%adfAtZero = 0
    if (present(adfAtZero)) this%adfAtZero = adfAtZero

    this%vGridWidths = vspaceObj%getVCellWidths()
    vGridCopy = vspaceObj%getVGrid()
    allocate(this%dvPlus(this%numV))
    this%dvPlus = 0
    this%dvPlus(1:this%numV-1) = vGridCopy(2:this%numV) -  vGridCopy(1:this%numV-1)

    call this%makeDefined()

end subroutine initVDiffValGen
!-----------------------------------------------------------------------------------------------------------------------------------
module subroutine calcVDiffVals(this,varCont,res,mbData,hostModel)
    !! Calculate d(Ad/dv)/dv stencil values in place (does not depend on varCont)

    class(VDiffStencilGen)                      ,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 ,k ,offsetA
    if (assertions) then 
        call assert(this%isDefined(),"calcVDiffVals called from undefined stencil generator")
        call assert(varCont%isDefined(),"Undefined varCont passed to calcVDiffVals")
        if (allocated(this%modelboundA)) &
        call assert(present(mbData),"No mbData passed to calcVDiffVals when expected")
    end if

    if (allocated(res)) then
        if (assertions) call assert(size(res) == size(this%usedXCoords)*this%numV,"res passed to calcVDiffVals has unexpected size")
    else
        allocate(res(size(this%usedXCoords)*this%numV))
    end if

    if (allocated(this%modelboundA)) then 
        call mbData%copyData(this%modelboundA,this%bufferA)
        offsetA = (size(this%bufferA) - this%numV*this%locNumX)/2 + lbound(this%bufferA,1) - 1
        offsetA = offsetA/this%numV 
    end if
    
    k = 1

    if (allocated(this%modelboundA)) then 
        
            do i = 1,size(this%usedXCoords)

                !At first v cell
                res(k)%entry = [-this%bufferA((this%usedXCoords(i)+offsetA-1)*this%numV+1)/this%dvPlus(1)-this%adfAtZero(1),&
                                this%bufferA((this%usedXCoords(i)+offsetA-1)*this%numV+1)&
                                /this%dvPlus(1)-this%adfAtZero(2)]
                
                res(k)%entry = res(k)%entry/this%vGridWidths(1) 

                k = k + 1 
                do j = 2,this%numV-1
                    res(k)%entry = [this%bufferA((this%usedXCoords(i)+offsetA-1)*this%numV+j-1)/this%dvPlus(j-1),& 
                                    -this%bufferA((this%usedXCoords(i)+offsetA-1)*this%numV+j-1)/this%dvPlus(j-1)&
                                    -this%bufferA((this%usedXCoords(i)+offsetA-1)*this%numV+j)/this%dvPlus(j),&
                                    this%bufferA((this%usedXCoords(i)+offsetA-1)*this%numV+j)/this%dvPlus(j)]

                    res(k)%entry = res(k)%entry/this%vGridWidths(j) 

                    k = k + 1
                end do
                ! Last v cell
                res(k)%entry = [this%bufferA((this%usedXCoords(i)+offsetA)*this%numV-1)/this%dvPlus(this%numV-1),& 
                                -this%bufferA((this%usedXCoords(i)+offsetA)*this%numV-1)/this%dvPlus(this%numV-1)]

                res(k)%entry = res(k)%entry/this%vGridWidths(this%numV) 
                
                k = k + 1

            end do

    else
        
            do i = 1,size(this%usedXCoords)

                !At first v cell
                res(k)%entry = [-this%bufferA(1)/this%dvPlus(1)-this%adfAtZero(1),&
                                this%bufferA(1)/this%dvPlus(1)-this%adfAtZero(2)]
                res(k)%entry = res(k)%entry/this%vGridWidths(1) 
                
                k = k + 1 
                do j = 2,this%numV-1
                    res(k)%entry = [this%bufferA(j-1)/this%dvPlus(j-1),& 
                                    -this%bufferA(j-1)/this%dvPlus(j-1)&
                                    -this%bufferA(j)/this%dvPlus(j),&
                                    this%bufferA(j)/this%dvPlus(j)]

                    res(k)%entry = res(k)%entry/this%vGridWidths(j) 
                    
                    k = k + 1
                end do
                ! Last v cell
                res(k)%entry = [this%bufferA(this%numV-1)/this%dvPlus(this%numV-1),& 
                                -this%bufferA(this%numV-1)/this%dvPlus(this%numV-1)]
                
                res(k)%entry = res(k)%entry/this%vGridWidths(this%numV) 
                
                k = k + 1

            end do
    
    end if

end subroutine calcVDiffVals
!-----------------------------------------------------------------------------------------------------------------------------------
!-----------------------------------------------------------------------------------------------------------------------------------
end submodule v_diffusion_stencil_gen_procedures
!-----------------------------------------------------------------------------------------------------------------------------------