variable_boltzmann_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 (variable_boltzmann_stencil_gen_class) variable_boltzmann_stencil_gen_procedures
!! author: Stefan Mijin 
!! 
!! Contains module procedures associated with the variable mapping Boltzmann stencil generator class

implicit none

!-----------------------------------------------------------------------------------------------------------------------------------
contains
!-----------------------------------------------------------------------------------------------------------------------------------
module subroutine initVarBoltzGen(this,vspaceObj,transitionIndex,lNum,absorptionTerm,superelasticTerm) 
    !! Boltzmann emission/absorption stencil value generator initialization routine with variable cross-sections and weights

    class(VariableBoltzmannStencilGen)        ,intent(inout)  :: this
    type(VSpace)                              ,intent(in)     :: vspaceObj !! VSpace object used to get grid
    integer(ik)                               ,intent(in)     :: transitionIndex !! Index of transition whose cross-section is required
    integer(ik) ,optional                     ,intent(in)     :: lNum !! Harmonic index of cross-section required. Used only if absorption term
    logical     ,optional                     ,intent(in)     :: absorptionTerm !! True if this is an absorption term stencil generator. Defaults to false.
    logical     ,optional                     ,intent(in)     :: superelasticTerm !! True if this is for a superelastic term (negative transition cost). Defaults to false.

    if (assertions) call assert(vspaceObj%isDefined(),"Undefined VSpace object passed to initVarBoltzGen")

    this%vGridCopy = vspaceObj%getVGrid()

    this%transitionIndex = transitionIndex 
    this%lNum = 0

    if (present(lNum)) this%lNum = lNum

    this%absorptionTerm = .false.

    if (present(absorptionTerm)) this%absorptionTerm = absorptionTerm

    this%superelasticTerm = .false.

    if (present(superelasticTerm)) this%superelasticTerm = superelasticTerm

    call this%makeDefined()

end subroutine initVarBoltzGen
!-----------------------------------------------------------------------------------------------------------------------------------
module subroutine calcVarBoltzVals(this,varCont,res,mbData,hostModel)
    !! Calculate Boltzmann emission/absorption stencil values in place (does not depend on varCont)

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

    real(rk) ,allocatable ,dimension(:) :: csVals ,emissionVec ,energyCost

    integer(ik) :: i ,j ,inferredXSize

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

    select type (mbData)

    type is (ModelboundCRMData) 

        if (this%absorptionTerm) then 
            csVals =  mbData%getTransitionCrossSection(this%lNum+1,this%transitionIndex)
        else
            csVals =  mbData%getTransitionCrossSection(1,this%transitionIndex) 
        end if

        if (allocated(res)) then
            call assert(size(res)==size(csVals),"res passed to calcVarBoltzVals not of expected size")
        else
            allocate(res(size(csVals)))
        end if
        inferredXSize = size(csVals) / size(this%vGridCopy)

        energyCost = mbData%getTransitionEnergy(this%transitionIndex)
        if (assertions) then 
            call assert(size(energyCost) == inferredXSize,"energyCost vector in calcVarBoltzVals does not conform with&
                                                            & inferred spatial size from cross-section values")
            call assert(all(energyCost<0) .eqv. this%superelasticTerm,"energyCost vector in calcVarBoltzVals must have values with&
                                                                    & sign according to whether the term is superelastic or not")
        end if
        if (this%absorptionTerm) then 

            do j = 1, inferredXSize

                if (.not. allocated(this%bufferW)) then 
                    allocate(this%bufferW)
                    call this%bufferW%init(rowIndices=[(i,i=1,size(this%vGridCopy))],&
                                           colVectors=triangularIntArray(size(this%vGridCopy),this%superelasticTerm))
                    
                end if

                call mbData%interpolateW(energyCost(j),this%bufferW)

                do i = 1,size(this%bufferW%rowIndex)
                    res((j-1)*size(this%vGridCopy) + this%bufferW%rowIndex(i))%entry = this%bufferW%values(i)%entry &
                    * csVals((j-1)*size(this%vGridCopy)+ this%bufferW%columnVector(i)%entry)&
                    * this%vGridCopy(this%bufferW%columnVector(i)%entry)
                end do
            end do
        else

            do j = 1, inferredXSize
                emissionVec = mbData%getInterpolatedEmissionVector(energyCost(j))
                do i = 1,size(this%vGridCopy)
                    res((j-1) * size(this%vGridCopy) + i)%entry =&
                    [-csVals((j-1) * size(this%vGridCopy) +i)*this%vGridCopy(i)*emissionVec(i)]
                end do
            end do  
        end if
    class default 

        error stop "calcVarBoltzVals expects ModelboundCRMData for mbData"

    end select 

end subroutine calcVarBoltzVals
!-----------------------------------------------------------------------------------------------------------------------------------
!-----------------------------------------------------------------------------------------------------------------------------------
end submodule variable_boltzmann_stencil_gen_procedures
!-----------------------------------------------------------------------------------------------------------------------------------