Improve to collisions

Improvement into the collision model to better compute number of
particles collisions.
This commit is contained in:
Jorge Gonzalez 2022-04-23 18:57:27 +02:00
commit 78a97ed7a0
12 changed files with 227 additions and 219 deletions

View file

@ -7,8 +7,6 @@ MODULE moduleCollisions
!Abstract type for collision between two particles
TYPE, ABSTRACT:: collisionBinary
REAL(8):: rMass !Reduced mass
REAL(8):: sMassInv !Summed mass
TYPE(table1D):: crossSec !cross section of collision
CONTAINS
PROCEDURE(collideBinary_interface), PASS, DEFERRED:: collide
@ -16,14 +14,13 @@ MODULE moduleCollisions
END TYPE collisionBinary
ABSTRACT INTERFACE
SUBROUTINE collideBinary_interface(self, sigmaVRelMax, sigmaVrelMaxNew, part_i, part_j)
SUBROUTINE collideBinary_interface(self, part_i, part_j, vRel)
USE moduleSpecies
IMPORT:: collisionBinary
CLASS(collisionBinary), INTENT(in):: self
REAL(8), INTENT(in):: sigmaVrelMax
REAL(8), INTENT(inout):: sigmaVrelMaxNew
TYPE(particle), INTENT(inout), TARGET:: part_i, part_j
REAL(8), INTENT(in):: vRel
END SUBROUTINE
@ -71,9 +68,11 @@ MODULE moduleCollisions
!Type for interaction matrix
TYPE:: interactionsBinary
INTEGER:: amount
REAL(8):: rMass !Reduced mass
TYPE(collisionCont), ALLOCATABLE:: collisions(:)
CONTAINS
PROCEDURE, PASS:: init => initInteractionBinary
PROCEDURE, PASS:: getSigmaVrel => getSigmaVrelBinary
END TYPE interactionsBinary
@ -85,13 +84,14 @@ MODULE moduleCollisions
CONTAINS
!Velocity of center of mass of two particles
PURE FUNCTION velocityCM(m_i, v_i, m_j, v_j) RESULT(vCM)
IMPLICIT NONE
REAL(8), INTENT(in):: m_i, m_j
REAL(8), INTENT(in), DIMENSION(1:3):: v_i, v_j
REAL(8):: vCM(1:3)
vCM = (m_i*v_i + m_j*v_j)/(m_i + m_j)
vCM = (m_i*v_i + m_j*v_j) / (m_i + m_j)
END FUNCTION velocityCM
@ -123,6 +123,9 @@ MODULE moduleCollisions
nInteractions = (nSpecies*(nSpecies+1))/2
ALLOCATE(interactionMatrix(1:nInteractions))
interactionMatrix(:)%amount = 0
interactionMatrix(:)%rMass = 0.D0
END SUBROUTINE initInteractionMatrix
!Gets the interaction index from the collision matrix from index i,j
@ -139,21 +142,46 @@ MODULE moduleCollisions
END FUNCTION interactionIndex
!Inits the binary interaction
SUBROUTINE initInteractionBinary(self, amount)
SUBROUTINE initInteractionBinary(self, amount, mass_i, mass_j)
USE moduleMath
IMPLICIT NONE
CLASS(interactionsBinary), INTENT(inout):: self
INTEGER, INTENT(in):: amount
REAL(8), INTENT(in):: mass_i, mass_j
self%amount = amount
self%rMass = reducedMass(mass_i, mass_j)
ALLOCATE(self%collisions(1:self%amount))
END SUBROUTINE initInteractionBinary
SUBROUTINE getSigmaVrelBinary (self, vRel, eRel, sigmaVrelTotal, sigmaVrel)
IMPLICIT NONE
CLASS(interactionsBinary), INTENT(in):: self
REAL(8), INTENT(in):: vRel, eRel
REAL(8), INTENT(out):: sigmaVrelTotal
REAL(8), INTENT(out), ALLOCATABLE:: sigmaVrel(:)
INTEGER:: k
sigmaVrelTotal = 0.D0
ALLOCATE(sigmaVrel(1:self%amount))
DO k = 1, self%amount
sigmaVrel(k) = self%collisions(k)%obj%crossSec%get(eRel)*vRel
END DO
sigmaVrelTotal = SUM(sigmaVrel)
END SUBROUTINE getSigmaVrelBinary
!ELASTIC COLLISIONS
!Inits binary elastic collision
SUBROUTINE initBinaryElastic(collision, crossSectionFilename, mass_i, mass_j)
SUBROUTINE initBinaryElastic(collision, crossSectionFilename)
USE moduleTable
USE moduleRefParam
USE moduleConstParam
@ -161,7 +189,6 @@ MODULE moduleCollisions
CLASS(collisionBinary), INTENT(out), ALLOCATABLE:: collision
CHARACTER(:), ALLOCATABLE, INTENT(in):: crossSectionFilename
REAL(8), INTENT(in):: mass_i, mass_j
ALLOCATE(collisionBinaryElastic:: collision)
@ -171,15 +198,10 @@ MODULE moduleCollisions
!Convert to no-dimensional units
CALL collision%crossSec%convert(eV2J/(m_ref*v_ref**2), 1.D0/L_ref**2)
!Calculates reduced mass
collision%sMassInv = 1.D0/(mass_i+mass_j)
collision%rMass = (mass_i*mass_j)*collision%sMassInv
END SUBROUTINE initBinaryElastic
!Binary elastic process
SUBROUTINE collideBinaryElastic(self, sigmaVrelMax, sigmaVrelMaxNew, &
part_i, part_j)
SUBROUTINE collideBinaryElastic(self, part_i, part_j, vRel)
USE moduleSpecies
USE moduleConstParam
USE moduleRandom
@ -187,38 +209,27 @@ MODULE moduleCollisions
IMPLICIT NONE
CLASS(collisionBinaryElastic), INTENT(in):: self
REAL(8), INTENT(in):: sigmaVrelMax
REAL(8), INTENT(inout):: sigmaVrelMaxNew
TYPE(particle), INTENT(inout), TARGET:: part_i, part_j
REAL(8):: sigmaVrel
REAL(8):: vRel !relative velocity
REAL(8):: eRel !relative energy
REAL(8), INTENT(in):: vRel
REAL(8):: m_i, m_j
REAL(8), DIMENSION(1:3):: vCM
REAL(8):: vp(1:3)
vRel = NORM2(part_i%v-part_j%v)
eRel = self%rMass*vRel**2
sigmaVrel = self%crossSec%get(eRel)*vRel
sigmaVrelMaxNew = sigmaVrelMaxNew + sigmaVrel
IF (sigmaVrelMaxNew/sigmaVrelMax > random()) THEN
m_i = part_i%species%m
m_j = part_j%species%m
!Applies the collision
vCM = velocityCM(m_i, part_i%v, m_j, part_j%v)
vp = vRel*randomDirectionVHS()
m_i = part_i%species%m
m_j = part_j%species%m
!Applies the collision
vCM = velocityCM(m_i, part_i%v, m_j, part_j%v)
vp = vRel*randomDirectionVHS()
!Assign velocities to particles
part_i%v = vCM + m_j*vp*self%sMassInv
part_j%v = vCM - m_i*vp*self%sMassInv
END IF
!Assign velocities to particles
part_i%v = vCM + m_j*vp / (m_i + m_j)
part_j%v = vCM - m_i*vp / (m_i + m_j)
END SUBROUTINE collideBinaryElastic
!ELECTRON IMPACT IONIZATION
!Inits electron impact ionization
SUBROUTINE initBinaryIonization(collision, crossSectionFilename, energyThreshold, mass_i, mass_j, electron)
SUBROUTINE initBinaryIonization(collision, crossSectionFilename, energyThreshold, electron)
USE moduleTable
USE moduleRefParam
USE moduleConstParam
@ -229,7 +240,6 @@ MODULE moduleCollisions
CLASS(collisionBinary), INTENT(out), ALLOCATABLE:: collision
CHARACTER(:), ALLOCATABLE, INTENT(in):: crossSectionFilename
REAL(8), INTENT(in):: energyThreshold
REAL(8), INTENT(in):: mass_i, mass_j
CHARACTER(:), ALLOCATABLE, INTENT(in):: electron
INTEGER:: electronIndex
@ -241,10 +251,6 @@ MODULE moduleCollisions
!Convert to no-dimensional units
CALL collision%crossSec%convert(eV2J/(m_ref*v_ref**2), 1.D0/L_ref**2)
!Calculates reduced mass
collision%sMassInv = 1.D0/(mass_i+mass_j)
collision%rMass = (mass_i*mass_j)*collision%sMassInv
!Specific parameters for ionization collision
SELECT TYPE(collision)
TYPE IS(collisionBinaryIonization)
@ -267,8 +273,7 @@ MODULE moduleCollisions
END SUBROUTINE initBinaryIonization
!Binary electron impact ionization process
SUBROUTINE collideBinaryIonization(self, sigmaVrelMax, sigmaVrelMaxNew, &
part_i, part_j)
SUBROUTINE collideBinaryIonization(self, part_i, part_j, vRel)
USE moduleSpecies
USE moduleErrors
USE moduleList
@ -278,80 +283,71 @@ MODULE moduleCollisions
IMPLICIT NONE
CLASS(collisionBinaryIonization), INTENT(in):: self
REAL(8), INTENT(in):: sigmaVrelMax
REAL(8), INTENT(inout):: sigmaVrelMaxNew
TYPE(particle), INTENT(inout), TARGET:: part_i, part_j
REAL(8), INTENT(in):: vRel
REAL(8):: rMass, eRel
TYPE(particle), POINTER:: electron => NULL(), neutral => NULL()
TYPE(particle), POINTER:: newElectron
REAL(8):: vRel, eRel
REAL(8):: sigmaVrel
REAL(8), DIMENSION(1:3):: vp_e, vp_n
!eRel (in units of [m][L]^2[t]^-2
vRel = NORM2(part_i%v-part_j%v)
eRel = self%rMass*vRel**2
rMass = reducedMass(part_i%species%m, part_j%species%m)
eRel = rMass*vRel**2
!Relative energy must be higher than threshold
IF (eRel > self%eThreshold) THEN
sigmaVrel = self%crossSec%get(eRel)*vRel
sigmaVrelMaxNew = sigmaVrelMaxNew + sigmaVrel
IF (sigmaVrelMaxNew/sigmaVrelMax > random()) THEN
!Find which particle is the ionizing electron
IF (ASSOCIATED(part_i%species, self%electron)) THEN
electron => part_i
neutral => part_j
IF (ASSOCIATED(part_i%species, self%electron)) THEN
electron => part_i
neutral => part_j
ELSEIF(ASSOCIATED(part_j%species, self%electron)) THEN
electron => part_j
neutral => part_i
ELSEIF(ASSOCIATED(part_j%species, self%electron)) THEN
electron => part_j
neutral => part_i
ELSE
CALL criticalError("No matching between input particles and ionizing species", 'collideBinaryIonization')
END IF
!Exchange energy between
vp_e = electron%v*(1.D0 - self%deltaV/NORM2(electron%v))
vp_n = neutral%v* (1.D0 + self%deltaV/NORM2(neutral%v) )
!Changes velocity of impacting electron
electron%v = vp_e
!Creates a new electron from ionization
ALLOCATE(newElectron)
newElectron%species => electron%species
newElectron%v = vp_n
newElectron%r = neutral%r
newElectron%xi = neutral%xi
newElectron%n_in = .TRUE.
newElectron%vol = neutral%vol
newElectron%volColl = neutral%volColl
newElectron%weight = neutral%weight
newElectron%qm = electron%qm
!Ionize neutral particle
SELECT TYPE(sp => neutral%species)
TYPE IS(speciesNeutral)
CALL sp%ionize(neutral)
CLASS DEFAULT
CALL criticalError(sp%name // " is not a neutral", 'collideBinaryIonization')
END SELECT
!Adds new electron to list of new particles from collisions
CALL OMP_SET_LOCK(lockCollisions)
CALL partCollisions%add(newElectron)
CALL OMP_UNSET_LOCK(lockCollisions)
ELSE
CALL criticalError("No matching between input particles and ionizing species", 'collideBinaryIonization')
END IF
!Exchange energy between
vp_e = electron%v*(1.D0 - self%deltaV/NORM2(electron%v))
vp_n = neutral%v* (1.D0 + self%deltaV/NORM2(neutral%v) )
!Changes velocity of impacting electron
electron%v = vp_e
!Creates a new electron from ionization
ALLOCATE(newElectron)
newElectron%species => electron%species
newElectron%v = vp_n
newElectron%r = neutral%r
newElectron%xi = neutral%xi
newElectron%n_in = .TRUE.
newElectron%vol = neutral%vol
newElectron%volColl = neutral%volColl
newElectron%weight = neutral%weight
newElectron%qm = electron%qm
!Ionize neutral particle
SELECT TYPE(sp => neutral%species)
TYPE IS(speciesNeutral)
CALL sp%ionize(neutral)
CLASS DEFAULT
CALL criticalError(sp%name // " is not a neutral", 'collideBinaryIonization')
END SELECT
!Adds new electron to list of new particles from collisions
CALL OMP_SET_LOCK(lockCollisions)
CALL partCollisions%add(newElectron)
CALL OMP_UNSET_LOCK(lockCollisions)
END IF
END SUBROUTINE collideBinaryIonization
!ELECTRON ION RESONANT RECOMBINATION
!Inits electron ion recombination
SUBROUTINE initBinaryRecombination(collision, crossSectionFilename, energyBinding, mass_i, mass_j, electron)
SUBROUTINE initBinaryRecombination(collision, crossSectionFilename, energyBinding, electron)
USE moduleTable
USE moduleRefParam
USE moduleConstParam
@ -362,7 +358,6 @@ MODULE moduleCollisions
CLASS(collisionBinary), INTENT(out), ALLOCATABLE:: collision
CHARACTER(:), ALLOCATABLE, INTENT(in):: crossSectionFilename
REAL(8), INTENT(in):: energyBinding
REAL(8), INTENT(in):: mass_i, mass_j
CHARACTER(:), ALLOCATABLE, INTENT(in):: electron
INTEGER:: electronIndex
@ -374,10 +369,6 @@ MODULE moduleCollisions
!Convert to no-dimensional units
CALL collision%crossSec%convert(eV2J/(m_ref*v_ref**2), 1.D0/L_ref**2)
!Calculates reduced mass
collision%sMassInv = 1.D0/(mass_i+mass_j)
collision%rMass = (mass_i*mass_j)*collision%sMassInv
!Specific parameters for ionization collision
SELECT TYPE(collision)
TYPE IS(collisionBinaryRecombination)
@ -399,9 +390,8 @@ MODULE moduleCollisions
END SUBROUTINE initBinaryRecombination
!Binary electron impact ionization process
SUBROUTINE collideBinaryRecombination(self, sigmaVrelMax, sigmaVrelMaxNew, &
part_i, part_j)
!Binary recombination
SUBROUTINE collideBinaryRecombination(self, part_i, part_j, vRel)
USE moduleSpecies
USE moduleErrors
USE moduleList
@ -410,59 +400,47 @@ MODULE moduleCollisions
IMPLICIT NONE
CLASS(collisionBinaryRecombination), INTENT(in):: self
REAL(8), INTENT(in):: sigmaVrelMax
REAL(8), INTENT(inout):: sigmaVrelMaxNew
REAL(8), INTENT(in):: vRel
TYPE(particle), INTENT(inout), TARGET:: part_i, part_j
TYPE(particle), POINTER:: electron => NULL(), ion => NULL()
REAL(8):: vRel, eRel
REAL(8):: sigmaVrel
REAL(8), DIMENSION(1:3):: vp_i
!eRel (in units of [m][L]^2[t]^-2
vRel = NORM2(part_i%v-part_j%v)
eRel = self%rMass*vRel**2
!Relative energy must be higher than threshold
sigmaVrel = self%crossSec%get(eRel)*vRel
sigmaVrelMaxNew = sigmaVrelMaxNew + sigmaVrel
IF (sigmaVrelMaxNew/sigmaVrelMax > random()) THEN
!Find which particle is the ionizing electron
IF (ASSOCIATED(part_i%species, self%electron)) THEN
electron => part_i
ion => part_j
IF (ASSOCIATED(part_i%species, self%electron)) THEN
electron => part_i
ion => part_j
ELSEIF(ASSOCIATED(part_j%species, self%electron)) THEN
electron => part_j
ion => part_i
ELSEIF(ASSOCIATED(part_j%species, self%electron)) THEN
electron => part_j
ion => part_i
ELSE
CALL criticalError("No matching between input particles and ionizing species", 'collideBinaryIonization')
END IF
!Excess energy
!TODO: This energy should be transformed into photons
vp_i = ion%v* (1.D0 - (vRel + self%deltaV)/NORM2(ion%v))
!Remove electron from simulation
electron%n_in = .FALSE.
!Neutralize ion particle
SELECT TYPE(sp => ion%species)
TYPE IS(speciesCharged)
CALL sp%neutralize(ion)
CLASS DEFAULT
CALL criticalError(sp%name // " is not a charge", 'collideBinaryRecombination')
END SELECT
ELSE
CALL criticalError("No matching between input particles and ionizing species", 'collideBinaryIonization')
END IF
!Excess energy
!TODO: This energy should be transformed into photons
vp_i = ion%v* (1.D0 - (vRel + self%deltaV)/NORM2(ion%v))
!Remove electron from simulation
electron%n_in = .FALSE.
!Neutralize ion particle
SELECT TYPE(sp => ion%species)
TYPE IS(speciesCharged)
CALL sp%neutralize(ion)
CLASS DEFAULT
CALL criticalError(sp%name // " is not a charge", 'collideBinaryRecombination')
END SELECT
END SUBROUTINE collideBinaryRecombination
!RESONANT CHARGE EXCHANGE
!Inits resonant charge exchange
SUBROUTINE initBinaryChargeExchange(collision, crossSectionFilename, mass_i, mass_j)
SUBROUTINE initBinaryChargeExchange(collision, crossSectionFilename)
USE moduleTable
USE moduleRefParam
USE moduleConstParam
@ -470,7 +448,6 @@ MODULE moduleCollisions
CLASS(collisionBinary), INTENT(out), ALLOCATABLE:: collision
CHARACTER(:), ALLOCATABLE, INTENT(in):: crossSectionFilename
REAL(8), INTENT(in):: mass_i, mass_j
ALLOCATE(collisionBinaryChargeExchange:: collision)
@ -480,56 +457,39 @@ MODULE moduleCollisions
!Convert to no-dimensional units
CALL collision%crossSec%convert(eV2J/(m_ref*v_ref**2), 1.D0/L_ref**2)
!Calculates reduced mass
collision%sMassInv = 1.D0/(mass_i+mass_j)
collision%rMass = (mass_i*mass_j)/collision%sMassInv
END SUBROUTINE initBinaryChargeExchange
SUBROUTINE collideBinaryChargeExchange(self, sigmaVrelMax, sigmaVrelMaxNew, &
part_i, part_j)
SUBROUTINE collideBinaryChargeExchange(self, part_i, part_j, vRel)
USE moduleSpecies
USE moduleRandom
USE moduleMath
IMPLICIT NONE
CLASS(collisionBinaryChargeExchange), INTENT(in):: self
REAL(8), INTENT(in):: sigmaVrelMax
REAL(8), INTENT(inout):: sigmaVrelMaxNew
REAL(8), INTENT(in):: vRel
TYPE(particle), INTENT(inout), TARGET:: part_i, part_j
REAL(8):: sigmaVrel
REAL(8):: vRel !relative velocity
REAL(8):: eRel !relative energy
!eRel (in units of [m][L]^2[t]^-2
vRel = NORM2(part_i%v-part_j%v)
eRel = self%rMass*vRel**2
sigmaVrel = self%crossSec%get(eRel)*vRel
sigmaVrelMaxNew = sigmaVrelMaxNew + sigmaVrel
IF (sigmaVrelMaxNew/sigmaVrelMax > random()) THEN
SELECT TYPE(sp => part_i%species)
TYPE IS (speciesNeutral)
!Species i is neutral, ionize particle i
CALL sp%ionize(part_i)
SELECT TYPE(sp => part_i%species)
TYPE IS (speciesNeutral)
!Species i is neutral, ionize particle i
CALL sp%ionize(part_i)
TYPE IS (speciesCharged)
!Species i is charged, neutralize particle i
CALL sp%neutralize(part_i)
TYPE IS (speciesCharged)
!Species i is charged, neutralize particle i
CALL sp%neutralize(part_i)
END SELECT
END SELECT
SELECT TYPE(sp => part_j%species)
TYPE IS (speciesNeutral)
!Species j is neutral, ionize particle j
CALL sp%ionize(part_j)
SELECT TYPE(sp => part_j%species)
TYPE IS (speciesNeutral)
!Species j is neutral, ionize particle j
CALL sp%ionize(part_j)
TYPE IS (speciesCharged)
!Species j is charged, neutralize particle j
CALL sp%neutralize(part_j)
TYPE IS (speciesCharged)
!Species j is charged, neutralize particle j
CALL sp%neutralize(part_j)
END SELECT
END IF
END SELECT
END SUBROUTINE collideBinaryChargeExchange