Coulomb Scattering fully conservative

Coulomb scattering is now fully conservative thanks to the method in
lemos2009small.

The trick was to conserve the momentum and energy of ALL particles
involved in the scattering in each cell.

The substeps in Coulomb collisions have been removed as they are no
longer necessary.

Still some issues with e-i, but I don't know right now.
This commit is contained in:
Jorge Gonzalez 2023-07-16 14:28:07 +02:00
commit e05c0d4635
3 changed files with 175 additions and 115 deletions

View file

@ -637,7 +637,6 @@ MODULE moduleInput
CHARACTER(:), ALLOCATABLE:: electron CHARACTER(:), ALLOCATABLE:: electron
INTEGER:: e INTEGER:: e
CLASS(meshCell), POINTER:: cell CLASS(meshCell), POINTER:: cell
INTEGER:: subSteps
!Firstly, check if the object 'interactions' exists !Firstly, check if the object 'interactions' exists
CALL config%info('interactions', found) CALL config%info('interactions', found)
@ -771,13 +770,8 @@ MODULE moduleInput
pt_i = speciesName2Index(species_i) pt_i = speciesName2Index(species_i)
CALL config%get(object // '.species_j', species_j, found) CALL config%get(object // '.species_j', species_j, found)
pt_j = speciesName2Index(species_j) pt_j = speciesName2Index(species_j)
CALL config%get(object // '.subSteps', subSteps, found)
IF (.NOT. found) THEN
subSteps = 1
END IF CALL coulombMatrix(i)%init(pt_i, pt_j)
CALL coulombMatrix(i)%init(pt_i, pt_j, subSteps)
END DO END DO

View file

@ -966,7 +966,6 @@ MODULE moduleMesh
INTEGER:: k INTEGER:: k
INTEGER:: i, j INTEGER:: i, j
INTEGER:: n INTEGER:: n
INTEGER:: t
INTEGER:: p INTEGER:: p
TYPE(lNode), POINTER:: partTemp TYPE(lNode), POINTER:: partTemp
INTEGER(8), ALLOCATABLE:: cellNodes(:) INTEGER(8), ALLOCATABLE:: cellNodes(:)
@ -978,7 +977,6 @@ MODULE moduleMesh
REAL(8):: l, lW, l2 REAL(8):: l, lW, l2
REAL(8):: GlW, HlW REAL(8):: GlW, HlW
REAL(8):: normC REAL(8):: normC
REAL(8):: theta, phi !angles between w and c
REAL(8):: cosThe, sinThe REAL(8):: cosThe, sinThe
REAL(8):: cosPhi, sinPhi REAL(8):: cosPhi, sinPhi
REAL(8):: rotation(1:3,1:3) !Rotation matrix to go back to laboratory frame REAL(8):: rotation(1:3,1:3) !Rotation matrix to go back to laboratory frame
@ -986,8 +984,13 @@ MODULE moduleMesh
REAL(8):: deltaW_par, deltaW_par_square, deltaW_per_square !Increments of W REAL(8):: deltaW_par, deltaW_par_square, deltaW_per_square !Increments of W
REAL(8):: theta_per !Random angle for perpendicular direction REAL(8):: theta_per !Random angle for perpendicular direction
REAL(8):: eps = 1.D-12 REAL(8):: eps = 1.D-12
REAL(8):: preV(1:3), totalP_ij(1:3), totalP_ji(1:3) REAL(8), ALLOCATABLE, DIMENSION(:,:):: deltaV_ij, p_ij
REAL(8), ALLOCATABLE:: deltaV_ji(:,:) REAL(8), ALLOCATABLE, DIMENSION(:):: mass_ij
REAL(8):: massSum_ij
REAL(8), ALLOCATABLE, DIMENSION(:,:):: deltaV_ji, p_ji
REAL(8), ALLOCATABLE, DIMENSION(:):: mass_ji
REAL(8):: massSum_ji
REAL(8):: alpha_num, alpha_den, alpha, beta(1:3)
!$OMP DO SCHEDULE(DYNAMIC) PRIVATE(partTemp) !$OMP DO SCHEDULE(DYNAMIC) PRIVATE(partTemp)
@ -1015,9 +1018,12 @@ MODULE moduleMesh
END DO END DO
totalP_ij = 0.D0 ALLOCATE(deltaV_ij(1:cell%listPart_in(i)%amount, 1:3))
ALLOCATE(p_ij(1:cell%listPart_in(i)%amount, 1:3))
ALLOCATE(mass_ij(1:cell%listPart_in(i)%amount))
!Loop over particles of species_i !Loop over particles of species_i
partTemp => cell%listPart_in(i)%head partTemp => cell%listPart_in(i)%head
p = 1
DO WHILE(ASSOCIATED(partTemp)) DO WHILE(ASSOCIATED(partTemp))
density = cell%gatherF(partTemp%part%Xi, cell%nNodes, densityNodes) density = cell%gatherF(partTemp%part%Xi, cell%nNodes, densityNodes)
velocity = cell%gatherF(partTemp%part%Xi, cell%nNodes, velocityNodes) velocity = cell%gatherF(partTemp%part%Xi, cell%nNodes, velocityNodes)
@ -1037,8 +1043,6 @@ MODULE moduleMesh
A = pair%A_i*density A = pair%A_i*density
!Do the required substeps
DO t = 1, pair%nSubSteps
C = partTemp%part%v - velocity C = partTemp%part%v - velocity
normC = NORM2(C) normC = NORM2(C)
@ -1062,9 +1066,9 @@ MODULE moduleMesh
AW = A / normC AW = A / normC
!Calculate changes in W due to collision process !Calculate changes in W due to collision process
deltaW_par = - A * pair%one_plus_massRatio_ij * l2 * GlW * pair%tauSub deltaW_par = - A * pair%one_plus_massRatio_ij * l2 * GlW * tauMin
deltaW_par_square = SQRT(AW * GlW * pair%tauSub)*randomMaxwellian() deltaW_par_square = SQRT(AW * GlW * tauMin)*randomMaxwellian()
deltaW_per_square = SQRT(AW * HlW * pair%tauSub)*randomMaxwellian() deltaW_per_square = SQRT(AW * HlW * tauMin)*randomMaxwellian()
!Random angle to distribute perpendicular change in velocity !Random angle to distribute perpendicular change in velocity
theta_per = PI2*random() theta_per = PI2*random()
@ -1074,15 +1078,14 @@ MODULE moduleMesh
W(2) = deltaW_per_square * SIN(theta_per) W(2) = deltaW_per_square * SIN(theta_per)
W(3) = normC + deltaW_par + deltaW_par_square W(3) = normC + deltaW_par + deltaW_par_square
!Update particle velocity and return to laboratory frame !Compute changes in velocity for each particle
preV = partTemp%part%v deltaV_ij(p,1:3) = MATMUL(rotation, W) + velocity - partTemp%part%v
partTemp%part%v = MATMUL(rotation, W) + velocity mass_ij(p) = pair%sp_i%m*partTemp%part%weight
totalP_ij = totalP_ij + pair%sp_i%m*(partTemp%part%v - preV) p_ij(p,1:3) = mass_ij(p)*partTemp%part%v
END DO
!Move to the next particle in the list !Move to the next particle in the list
partTemp => partTemp%next partTemp => partTemp%next
p = p + 1
END DO END DO
@ -1099,8 +1102,9 @@ MODULE moduleMesh
END DO END DO
totalP_ji = 0.D0
ALLOCATE(deltaV_ji(1:cell%listPart_in(j)%amount, 1:3)) ALLOCATE(deltaV_ji(1:cell%listPart_in(j)%amount, 1:3))
ALLOCATE(p_ji(1:cell%listPart_in(j)%amount, 1:3))
ALLOCATE(mass_ji(1:cell%listPart_in(j)%amount))
!Loop over particles of species_j !Loop over particles of species_j
partTemp => cell%listPart_in(j)%head partTemp => cell%listPart_in(j)%head
p = 1 p = 1
@ -1122,8 +1126,6 @@ MODULE moduleMesh
END IF END IF
A = pair%A_j*density A = pair%A_j*density
!Do the required substeps
DO t = 1, pair%nSubSteps
C = partTemp%part%v - velocity C = partTemp%part%v - velocity
normC = NORM2(C) normC = NORM2(C)
@ -1147,9 +1149,9 @@ MODULE moduleMesh
AW = A / normC AW = A / normC
!Calculate changes in W due to collision process !Calculate changes in W due to collision process
deltaW_par = - A * pair%one_plus_massRatio_ij * l2 * GlW * pair%tauSub deltaW_par = - A * pair%one_plus_massRatio_ij * l2 * GlW * tauMin
deltaW_par_square = SQRT(AW * GlW * pair%tauSub)*randomMaxwellian() deltaW_par_square = SQRT(AW * GlW * tauMin)*randomMaxwellian()
deltaW_per_square = SQRT(AW * HlW * pair%tauSub)*randomMaxwellian() deltaW_per_square = SQRT(AW * HlW * tauMin)*randomMaxwellian()
!Random angle to distribute perpendicular change in velocity !Random angle to distribute perpendicular change in velocity
theta_per = PI2*random() theta_per = PI2*random()
@ -1159,20 +1161,90 @@ MODULE moduleMesh
W(2) = deltaW_per_square * SIN(theta_per) W(2) = deltaW_per_square * SIN(theta_per)
W(3) = normC + deltaW_par + deltaW_par_square W(3) = normC + deltaW_par + deltaW_par_square
preV = partTemp%part%v !Compute changes in velocity for each particle
partTemp%part%v = MATMUL(rotation, W) + velocity deltaV_ji(p,1:3) = MATMUL(rotation, W) + velocity - partTemp%part%v
totalP_ji = totalP_ji + pair%sp_j%m*(partTemp%part%v - preV) mass_ji(p) = pair%sp_j%m*partTemp%part%weight
p_ji(p,1:3) = mass_ji(p)*partTemp%part%v
END DO
!Move to the next particle in the list !Move to the next particle in the list
partTemp => partTemp%next partTemp => partTemp%next
p = p + 1
END DO END DO
END IF END IF
print *, k, NORM2(totalP_ij), NORM2(totalP_ji) !Calculate correction
!Total mass
massSum_ij = SUM(mass_ij)
massSum_ji = 0.D0
!Beta
beta = 0.D0
DO p = 1, cell%listPart_in(i)%amount
beta = beta + mass_ij(p) * deltaV_ij(p,1:3)
END DO
IF (i /= j) THEN
massSum_ji = SUM(mass_ji)
DO p = 1, cell%listPart_in(j)%amount
beta = beta + mass_ji(p) * deltaV_ji(p,1:3)
END DO
END IF
beta = beta / (massSum_ij + massSum_ji)
!Alpha
alpha_num = 0.D0
alpha_den = 0.D0
DO p =1, cell%listPart_in(i)%amount
alpha_num = alpha_num + DOT_PRODUCT(p_ij(p,1:3), deltav_ij(p,1:3) - beta(1:3))
alpha_den = alpha_den + mass_ij(p) * NORM2(deltav_ij(p,1:3) - beta(1:3))**2
END DO
IF (i /= j) THEN
DO p = 1, cell%listPart_in(j)%amount
alpha_num = alpha_num + DOT_PRODUCT(p_ji(p,1:3), deltav_ji(p,1:3) - beta(1:3))
alpha_den = alpha_den + mass_ji(p) * NORM2(deltav_ji(p,1:3) - beta(1:3))**2
END DO
END IF
alpha = -2.D0*alpha_num / alpha_den
!Apply correction to particles velocity
partTemp => cell%listPart_in(i)%head
p = 1
DO WHILE(ASSOCIATED(partTemp))
partTemp%part%v = partTemp%part%v + alpha * (deltaV_ij(p,1:3) - beta(1:3))
partTemp => partTemp%next
p = p + 1
END DO
IF (i /= j) THEN
partTemp => cell%listPart_in(j)%head
p = 1
DO WHILE(ASSOCIATED(partTemp))
partTemp%part%v = partTemp%part%v + alpha * (deltaV_ji(p,1:3) - beta(1:3))
partTemp => partTemp%next
p = p + 1
END DO
END IF
DEALLOCATE(deltaV_ij, p_ij, mass_ij)
IF (i /= j) THEN
DEALLOCATE(deltaV_ji, p_ji, mass_ji)
END IF
END DO END DO

View file

@ -14,8 +14,6 @@ MODULE moduleCoulomb
REAL(8):: A_j REAL(8):: A_j
REAL(8):: l2_j REAL(8):: l2_j
REAL(8):: l2_i REAL(8):: l2_i
REAL(8):: tauSub
INTEGER:: nSubSteps
CONTAINS CONTAINS
PROCEDURE, PASS:: init => initInteractionCoulomb PROCEDURE, PASS:: init => initInteractionCoulomb
@ -48,7 +46,7 @@ MODULE moduleCoulomb
END FUNCTION H END FUNCTION H
SUBROUTINE initInteractionCoulomb(self, i, j, subSteps) SUBROUTINE initInteractionCoulomb(self, i, j)
USE moduleSpecies USE moduleSpecies
USE moduleErrors USE moduleErrors
USE moduleConstParam USE moduleConstParam
@ -56,14 +54,10 @@ MODULE moduleCoulomb
IMPLICIT NONE IMPLICIT NONE
CLASS(interactionsCoulomb), INTENT(out):: self CLASS(interactionsCoulomb), INTENT(out):: self
INTEGER, INTENT(in):: subSteps
INTEGER, INTENT(in):: i, j INTEGER, INTENT(in):: i, j
REAL(8):: Z_i, Z_j REAL(8):: Z_i, Z_j
REAL(8):: scaleFactor REAL(8):: scaleFactor
self%nSubSteps = subSteps
self%tauSub = tauMin / REAL(self%nSubSteps)
self%sp_i => species(i)%obj self%sp_i => species(i)%obj
self%sp_j => species(j)%obj self%sp_j => species(j)%obj