crm_secondary_el_source_term_generator_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 (crm_secondary_el_source_term_generator_class) crm_secondary_el_source_term_generator_procedures
!! author: Stefan Mijin 
!! 
!! Contains procedures associated with the CRMSecElTermGenerator class

implicit none

!-----------------------------------------------------------------------------------------------------------------------------------
contains
!-----------------------------------------------------------------------------------------------------------------------------------
module subroutine initCRMSecElTermGenerator(this,envObj,crmData,distributionName,generatorTag,includedTransitionIndices) 
    !! Constructor routine for CRM secondary electron source/sink term generator 

    class(CRMSecElTermGenerator)        ,intent(inout) :: this 
    type(EnvironmentWrapper) ,target    ,intent(in)    :: envObj !! Environment wrapper used to get species data, partition info, etc.
    type(ModelboundCRMData)             ,intent(in)    :: crmData !! CRM data object used to get transition data
    character(*)                        ,intent(in)    :: distributionName !! Evolved distribution name
    character(*)                        ,intent(in)    :: generatorTag
    integer(ik) ,optional ,dimension(:) ,intent(in)    :: includedTransitionIndices !! Optional list of transitions to be included 
                                                                                    !! in source calculations by this generator.
                                                                                    !! Defaults to all transitions

    integer(ik) ,allocatable ,dimension(:) ::  usedTransitionIndices ,inStates

    integer(ik) ,allocatable ,dimension(:,:) :: popChangeMat ,densityDat
    
    integer(ik) :: i,l,k ,numTerms ,implicitSpeciesID

    type(VarData) ,allocatable :: tempVData 

    character(len=80) :: transIndexBuffer

    if (assertions .or. assertionLvl >= 0) then 

        call assert(envObj%isDefined(),"Undefined environment wrapper passed to CRMDensTermGenerator constructor")
        call assert(crmData%isDefined(),"Undefined modelbound CRM data passed to CRMDensTermGenerator constructor")

    end if

    this%envPointer => envObj

    if (present(includedTransitionIndices)) then 
        usedTransitionIndices = includedTransitionIndices
    else
        usedTransitionIndices = [(i,i=1,crmData%getNumTransitions())]
    end if
    popChangeMat = crmData%getPopulationChangeMatrix([0],usedTransitionIndices)

    numTerms = count(popChangeMat /= 0)

    allocate(this%popChange(numTerms))
    allocate(this%vData(numTerms))
    allocate(this%implicitVars(numTerms))

    k=1
    do i = 1,size(usedTransitionIndices)

        if (allocated(tempVData)) deallocate(tempVData)
        allocate(tempVData)
        densityDat = crmData%getRequiredDensityData(usedTransitionIndices(i),removeLastState=.true.)

        allocate(tempVData%rowVars(size(densityDat,1)))
        do l = 1,size(tempVData%rowVars)
            !Assumes density is associated as the first variable
            tempVData%rowVars(l)%string = envObj%speciesListObj%getSpeciesVarFromID(densityDat(l,1),1) 
        end do

        tempVData%rowVarPowers = real(densityDat(:,2),kind=rk)
        write(transIndexBuffer,'(I0)') usedTransitionIndices(i)
        tempVData%modelboundRowVars = [StringArray("rate0index"//trim(transIndexBuffer))]

        inStates = crmData%getTransitionIngoingStates(usedTransitionIndices(i))

        implicitSpeciesID = inStates(size(inStates))

        if (popChangeMat(1,i) /=0 ) then

            this%popChange(k) = popChangeMat(1,i)
            this%vData(k) = tempVData
            this%implicitVars(k)%string = envObj%speciesListObj%getSpeciesVarFromID(implicitSpeciesID,1)
            k=k+1
        end if

    end do 

    this%distributionName = distributionName

    call this%setGeneratorPrefix(generatorTag)
    call this%makeDefined()
    
end subroutine initCRMSecElTermGenerator
!-----------------------------------------------------------------------------------------------------------------------------------
module subroutine generateSecElSourceTerms(this,mbData) 
    !! Generates and allocates parent implicit secondary electron source/sink terms 

    class(CRMSecElTermGenerator)  ,intent(inout) :: this 
    class(ModelboundData) ,optional ,intent(in) :: mbData

    type(MatTermContainer) ,allocatable, dimension(:) :: matTerms 
    type(TermContainer)    ,allocatable, dimension(:) :: genTerms

    type(GeneralMatrixTerm) ,allocatable :: termBuffer

    type(StencilTemplate) ,allocatable :: templateObj

    type(CoordProfiles) :: cProfs

    integer(ik) :: i

    integer(ik) ,dimension(0) :: dummyXCells

    if (assertions .or. assertionLvl >= 0) call assert(this%isDefined(),"generate called from undefined CRMDensTermGenerator")

    allocate(genTerms(0))
    allocate(matTerms(size(this%vData)))

    cProfs%vProfile = 1/(4 * pi * this%envPointer%vSpaceObj%getVGrid()**2 * this%envPointer%vSpaceObj%getVCellWidths())

    do i = 1, size(this%vData)

        if (allocated(templateObj)) deallocate(templateObj)
        allocate(templateObj)

        call initKinDiagonalStencilTemplateDirect(templateObj,this%envPointer,this%distributionName,&
                                                  this%implicitVars(i)%string,dummyXCells,[1],[1])
        allocate(termBuffer)
        call termBuffer%init(this%envPointer%gridObj,this%envPointer%partitionObj,this%envPointer%indexingObj,&
                            this%envPointer%mpiCont%getWorldRank(),&
                            this%distributionName ,this%implicitVars(i)%string,this%envPointer%externalVars,templateObj,&
                            vData=this%vData(i),normConst=real(this%popChange(i),kind=rk),coordProfile=cProfs,mbData=mbData)

        call move_alloc(termBuffer,matTerms(i)%entry)
    end do

    call this%setImplicitTerms(matTerms)
    call this%setGeneralTerms(genTerms)

end subroutine generateSecElSourceTerms
!-----------------------------------------------------------------------------------------------------------------------------------
elemental module subroutine finalizeCRMSecElGenerator(this) 
!! Deallocate pointer component

    type(CRMSecElTermGenerator)                    ,intent(inout) :: this
    
    nullify(this%envPointer)

end subroutine finalizeCRMSecElGenerator 
!-----------------------------------------------------------------------------------------------------------------------------------
end submodule crm_secondary_el_source_term_generator_procedures
!-----------------------------------------------------------------------------------------------------------------------------------