ddv_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 (ddv_stencil_gen_class) ddv_stencil_gen_procedures
!! author: Stefan Mijin 
!! 
!! Contains module procedures associated with the ddv stencil generator class

implicit none

!-----------------------------------------------------------------------------------------------------------------------------------
contains
!-----------------------------------------------------------------------------------------------------------------------------------
module subroutine initDDVValGen(this,partitionObj,vspaceObj,procRank,activeXCoords,fixedC,fixedInterp,mbC,mbInterp,cfAtZero) 
    !! d/dv stencil value generator initialization routine

    class(DDVStencilGenerator)                ,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)     :: fixedC !! Fixed C values (size numV). Defaults to ones.
    real(rk) ,optional   ,dimension(:)        ,intent(in)     :: fixedInterp !! Fixed vel interpolation values (size numV). Defaults to values from VSpace.
    character(*) ,optional                    ,intent(in)     :: mbC !! Optional modelbound value for C (single harmonic variable). Overrides fixed values.
    character(*) ,optional                    ,intent(in)     :: mbInterp !! Optional modelbound value for interpolation weight (single harmonic variable). Overrides fixed values.
    real(rk) ,optional ,dimension(2)          ,intent(in)     :: cfAtZero !! Optional extrapolation of C*f at zero in the form A1*f(v1)+A2*f(v2) where all A's are fixed. Defaults to 0.

    integer(ik) :: i ,minX ,maxX

    if (assertions) then 
        call assert(partitionObj%isDefined(),"Undefined partition passed to ddv stencil value generator constructor")
        call assert(vspaceObj%isDefined(),"Undefined VSpace passed to ddv 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%bufferC = [(real(1,kind=rk),i=1,this%numV)]
    this%bufferInterp = vspaceObj%getVLinInterp()

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

        this%bufferC = fixedC
    end if

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

        this%bufferInterp = fixedInterp
    end if

    if (present(mbC)) then
        deallocate(this%bufferC) 
        this%modelboundC = mbC 
    end if 

    if (present(mbInterp)) then 
        deallocate(this%bufferInterp)
        this%modelboundInterp = mbInterp
    end if

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

    this%vGridWidths = vspaceObj%getVCellWidths()

    call this%makeDefined()

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

    class(DDVStencilGenerator)                  ,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 ,offsetC ,offsetInterp
    if (assertions) then 
        call assert(this%isDefined(),"calcDDVVals called from undefined stencil generator")
        call assert(varCont%isDefined(),"Undefined varCont passed to calcDDVVals")
        if (allocated(this%modelboundC) .or. allocated(this%modelboundInterp)) &
        call assert(present(mbData),"No mbData passed to calcDDVVals when expected")
    end if

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

    if (allocated(this%modelboundC)) then 
        call mbData%copyData(this%modelboundC,this%bufferC)
        offsetC = (size(this%bufferC) - this%numV*this%locNumX)/2 + lbound(this%bufferC,1) - 1
        offsetC = offsetC/this%numV 
    end if
    if (allocated(this%modelboundInterp)) then 
        call mbData%copyData(this%modelboundInterp,this%bufferInterp)
        offsetInterp = (size(this%bufferInterp) - this%numV*this%locNumX)/2 + lbound(this%bufferInterp,1) - 1

        offsetInterp = offsetInterp/this%numV 
    end if
    k = 1

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

                    !At first v cell
                    res(k)%entry = [this%bufferC((this%usedXCoords(i)+offsetC-1)*this%numV+1)*(real(1,kind=rk)&
                                   -this%bufferInterp((this%usedXCoords(i)+offsetInterp-1)*this%numV+1))-this%cfAtZero(1),&
                                    this%bufferC((this%usedXCoords(i)+offsetC-1)*this%numV+1)&
                                    *this%bufferInterp((this%usedXCoords(i)+offsetInterp-1)*this%numV+1)-this%cfAtZero(2)]

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

                    k = k + 1 

                    do j = 2,this%numV-1
                        res(k)%entry = [-this%bufferC((this%usedXCoords(i)+offsetC-1)*this%numV+j-1)&
                        *(real(1,kind=rk)-this%bufferInterp((this%usedXCoords(i)+offsetInterp-1)*this%numV+j-1)),& 
                                        -this%bufferC((this%usedXCoords(i)+offsetC-1)*this%numV+j-1)&
                                        *this%bufferInterp((this%usedXCoords(i)+offsetInterp-1)*this%numV+j-1)&
                                        +this%bufferC((this%usedXCoords(i)+offsetC-1)*this%numV+j)&
                                        *(real(1,kind=rk)-this%bufferInterp((this%usedXCoords(i)+offsetInterp-1)*this%numV+j)),&
                                        this%bufferC((this%usedXCoords(i)+offsetC-1)*this%numV+j)&
                                        *this%bufferInterp((i+offsetInterp-1)*this%numV+j)]

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

                        k = k + 1
                    end do
                    ! Last v cell
                    res(k)%entry = [-this%bufferC((this%usedXCoords(i)+offsetC)*this%numV-1)*(real(1,kind=rk)&
                                    -this%bufferInterp((this%usedXCoords(i)+offsetInterp)*this%numV-1)),& 
                                    -this%bufferC((this%usedXCoords(i)+offsetC)*this%numV-1)&
                                    *this%bufferInterp((this%usedXCoords(i)+offsetInterp)*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%bufferC((this%usedXCoords(i)+offsetC-1)*this%numV+1)*(real(1,kind=rk)&
                               -this%bufferInterp(1))-this%cfAtZero(1),&
                                this%bufferC((this%usedXCoords(i)+offsetC-1)*this%numV+1)&
                                *this%bufferInterp(1)-this%cfAtZero(2)]
                
                res(k)%entry = res(k)%entry/this%vGridWidths(1) 

                k = k + 1 
                do j = 2,this%numV-1
                    res(k)%entry = [-this%bufferC((this%usedXCoords(i)+offsetC-1)*this%numV+j-1)&
                    *(real(1,kind=rk)-this%bufferInterp(j-1)),& 
                                    -this%bufferC((this%usedXCoords(i)+offsetC-1)*this%numV+j-1)*this%bufferInterp(j-1)&
                                    +this%bufferC((this%usedXCoords(i)+offsetC-1)*this%numV+j)&
                                    *(real(1,kind=rk)-this%bufferInterp(j)),&
                                    this%bufferC((this%usedXCoords(i)+offsetC-1)*this%numV+j)*this%bufferInterp(j)]

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

                    k = k + 1
                end do
                ! Last v cell
                res(k)%entry = [-this%bufferC((this%usedXCoords(i)+offsetC)*this%numV-1)*(real(1,kind=rk)&
                                -this%bufferInterp(this%numV-1)),& 
                                -this%bufferC((this%usedXCoords(i)+offsetC)*this%numV-1)*this%bufferInterp(this%numV-1)]

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

            end do
    
        end if
    else
        if (allocated(this%modelboundInterp)) then 
            do i = 1,size(this%usedXCoords)

                !At first v cell
                res(k)%entry = [this%bufferC(1)*(real(1,kind=rk)&
                               -this%bufferInterp((this%usedXCoords(i)+offsetInterp-1)*this%numV+1))-this%cfAtZero(1),&
                                this%bufferC(1)&
                                *this%bufferInterp((this%usedXCoords(i)+offsetInterp-1)*this%numV+1)-this%cfAtZero(2)]

                res(k)%entry = res(k)%entry/this%vGridWidths(1) 
                
                k = k + 1 
                do j = 2,this%numV-1
                    res(k)%entry = [-this%bufferC(j-1)&
                    *(real(1,kind=rk)-this%bufferInterp((this%usedXCoords(i)+offsetInterp-1)*this%numV+j-1)),& 
                                    -this%bufferC(j-1)*this%bufferInterp((this%usedXCoords(i)+offsetInterp-1)*this%numV+j-1)&
                                    +this%bufferC(j)&
                                    *(real(1,kind=rk)-this%bufferInterp((this%usedXCoords(i)+offsetInterp-1)*this%numV+j)),&
                                    this%bufferC(j)*this%bufferInterp((this%usedXCoords(i)+offsetInterp-1)*this%numV+j)]

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

                    k = k + 1
                end do
                ! Last v cell
                res(k)%entry = [-this%bufferC(this%numV-1)*(real(1,kind=rk)&
                                -this%bufferInterp((this%usedXCoords(i)+offsetInterp)*this%numV-1)),& 
                                -this%bufferC(this%numV-1)*this%bufferInterp((i+offsetInterp)*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%bufferC(1)*(real(1,kind=rk)&
                               -this%bufferInterp(1))-this%cfAtZero(1),&
                                this%bufferC(1)&
                                *this%bufferInterp(1)-this%cfAtZero(2)]
                res(k)%entry = res(k)%entry/this%vGridWidths(1) 
                
                k = k + 1 
                do j = 2,this%numV-1
                    res(k)%entry = [-this%bufferC(j-1)&
                    *(real(1,kind=rk)-this%bufferInterp(j-1)),& 
                                    -this%bufferC(j-1)*this%bufferInterp(j-1)&
                                    +this%bufferC(j)&
                                    *(real(1,kind=rk)-this%bufferInterp(j)),&
                                    this%bufferC(j)*this%bufferInterp(j)]

                    res(k)%entry = res(k)%entry/this%vGridWidths(j) 
                    
                    k = k + 1
                end do
                ! Last v cell
                res(k)%entry = [-this%bufferC(this%numV-1)*(real(1,kind=rk)&
                                -this%bufferInterp(this%numV-1)),& 
                                -this%bufferC(this%numV-1)*this%bufferInterp(this%numV-1)]
                
                res(k)%entry = res(k)%entry/this%vGridWidths(this%numV) 
                
                k = k + 1

            end do
    
        end if
    end if

end subroutine calcDDVVals
!-----------------------------------------------------------------------------------------------------------------------------------
!-----------------------------------------------------------------------------------------------------------------------------------
end submodule ddv_stencil_gen_procedures
!-----------------------------------------------------------------------------------------------------------------------------------