d2dv2_derivation_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 (d2dv2_derivation_class) d2dv2_derivation_procedures
!! author: Stefan Mijin 
!! 
!! Contains module procedures associated with the d2dv2 derivation class

implicit none

!-----------------------------------------------------------------------------------------------------------------------------------
contains
!-----------------------------------------------------------------------------------------------------------------------------------
module subroutine initD2DV2Derivation(this,vSpaceObj,outerV,innerV,vidfdvAtZero,targetH)
    !! Initialize second order velocity derivative derivation

    class(D2DV2Derivation)                  ,intent(inout) :: this
    type(VSpace)                            ,intent(in)    :: vSpaceObj
    type(RealArray) ,optional ,dimension(:) ,intent(in)    :: outerV !! Outer velocity vector corresponding to cell centres for each included harmonic. Defaults to ones.
    type(RealArray) ,optional ,dimension(:) ,intent(in)    :: innerV !! Inner velocity vector corresponding to right cell boundaries for each included harmonic. Defaults to ones.
    type(RealArray) ,optional ,dimension(:) ,intent(in)    :: vidfdvAtZero !! Extrapolation of v_i*df/dv at zero in the form A1*f(v1)+A2*f(v2) where A's correspond to included harmonics (default = 0)
    integer(ik) ,optional                   ,intent(in)    :: targetH !! Harmonic to take derivative of. If not present will return full distribution. 

    integer(ik) :: i ,numV

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

    if (assertions) call assert (vSpaceObj%isDefined(),"Undefined VSpace object passed to initD2DV2Derivation")

    this%numH = vSpaceObj%getNumH()
    this%dvCopy = vSpaceObj%getVCellWidths()

    numV = size(this%dvCopy)
    allocate(this%dvPlus(numV))
    this%dvPlus = 0
    vGrid = vSpaceObj%getVGrid()
    this%dvPlus(1:numV-1) = vGrid(2:numV) -  vGrid(1:numV-1)

    if (present(targetH)) then 
        this%includedHs = [targetH]
    else
        this%includedHs = [(i,i=1,this%numH)]
    end if

    allocate(this%vidfdvAtZero(size(this%includedHs)))
    allocate(this%outerV(size(this%includedHs)))
    allocate(this%innerV(size(this%includedHs)))

    do i = 1 ,size(this%includedHs)
        this%vidfdvAtZero(i)%entry = real([0,0],kind=rk)
        this%outerV(i)%entry = [(real(1,kind=rk),i=1,numV)]
        this%innerV(i)%entry = [(real(1,kind=rk),i=1,numV)]
    end do

    if (present(outerV)) then 
        if (assertions) then 
            call assert(size(outerV) == size(this%includedHs),&
            "outerV passed to initD2DV2Derivation does not conform with expected number of harmonics")
            do i = 1,size(outerV)
                call assert(size(outerV(i)%entry) == numV,"outerV entry passed to initD2DV2Derivation not of size numV")
            end do
        end if
        this%outerV = outerV
    end if

    if (present(innerV)) then 
        if (assertions) then 
            call assert(size(innerV) == size(this%includedHs),&
            "innerV passed to initD2DV2Derivation does not conform with expected number of harmonics")
            do i = 1,size(innerV)
                call assert(size(innerV(i)%entry) == numV,"innerV entry passed to initD2DV2Derivation not of size numV")
            end do
        end if
        this%innerV = innerV
    end if

    if (present(vidfdvAtZero)) then 
        if (assertions) then 
            call assert(size(vidfdvAtZero) == size(this%includedHs),&
            "vidfdvAtZero passed to initD2DV2Derivation does not conform with expected number of harmonics")
            do i = 1,size(vidfdvAtZero)
                call assert(size(vidfdvAtZero(i)%entry) == 2,"vidfdvAtZero entry passed to initD2DV2Derivation not of size 2")
            end do
        end if
        this%vidfdvAtZero = vidfdvAtZero
    end if
    
    call this%makeDefined()

end subroutine initD2DV2Derivation  
!-----------------------------------------------------------------------------------------------------------------------------------
module function calculateD2DV2(this,inputArray,indices) result(output)

    class(D2DV2Derivation)             ,intent(inout)    :: this 
    type(RealArray)       ,dimension(:) ,intent(in)    :: inputArray 
    integer(ik)           ,dimension(:) ,intent(in)    :: indices           
    real(rk) ,allocatable ,dimension(:)                :: output

    integer(ik) :: i ,j ,inferredNumX ,numV ,indOffset ,indOffsetOut ,lBoundInput ,hInd

    if (assertions) then 

        call assertPure(this%isDefined(),"calculateD2DV2 called on undefined derivation object")
        call assertPure(size(indices) == 1,"Number of indices passed to calculateD2DV2 must be 1")
        call assertPure(all(indices>0),"indices passed to calculateD2DV2 out of bounds - lower")
        call assertPure(all(indices<=size(inputArray)),"indices passed to calculateD2DV2 out of bounds - upper")

    end if

    numV = size(this%dvCopy)
    inferredNumX = size(inputArray(indices(1))%entry)/(this%numH*numV)
    lBoundInput = lbound(inputArray(indices(1))%entry,1)

    allocate(output(inferredNumX*size(this%includedHs)*numV))
    output = 0

    do i = 1,inferredNumX
        do j = 1,size(this%includedHs)
        indOffset = (i-1)*this%numH*numV+(this%includedHs(j)-1)*numV + lBoundInput - 1
        hInd = this%includedHs(j)-minval(this%includedHs) + 1
        indOffsetOut = (i-1)*size(this%includedHs)*numV+(hInd-1)*numV
        
        output(indOffsetOut + 1) = this%innerV(hInd)%entry(1)*(inputArray(indices(1))%entry(indOffset+2)&
                                    - inputArray(indices(1))%entry(indOffset+1))/this%dvPlus(1)&
                                    - inputArray(indices(1))%entry(indOffset+1) * this%vidfdvAtZero(hInd)%entry(1) &
                                    - inputArray(indices(1))%entry(indOffset+2) * this%vidfdvAtZero(hInd)%entry(2)

        output(indOffsetOut + 2 : indOffsetOut + numV - 1) = this%innerV(hInd)%entry(2:numV-1) *&
                                            (inputArray(indices(1))%entry(indOffset+3:indOffset+numV)&
                                            - inputArray(indices(1))%entry(indOffset+2:indOffset+numV-1) )/this%dvPlus(2:numV-1) &
                                - this%innerV(hInd)%entry(1:numV-2) * (inputArray(indices(1))%entry(indOffset+2:indOffset+numV-1) &
                                            - inputArray(indices(1))%entry(indOffset+1:indOffset+numV-2) )/this%dvPlus(1:numV-2)

        output(indOffsetOut + numV) = - this%innerV(hInd)%entry(numV-1) * (inputArray(indices(1))%entry(indOffset+numV) &
                                        - inputArray(indices(1))%entry(indOffset+numV-1) )/this%dvPlus(numV-1)

        output(indOffsetOut + 1:indOffsetOut + numV) = output(indOffsetOut + 1:indOffsetOut+numV) * &
                                                      this%outerV(hInd)%entry / this%dvCopy
        
        end do
    end do

end function calculateD2DV2
!-----------------------------------------------------------------------------------------------------------------------------------
end submodule d2dv2_derivation_procedures
!-----------------------------------------------------------------------------------------------------------------------------------