First attempt at Coulomb collisions

First attemp for Coulomb collisions based on the moments distribtuions.
Still the method is not done and far from being complete but input
options and basic math are implemented.
This commit is contained in:
Jorge Gonzalez 2023-02-24 21:46:01 +01:00
commit 601103105f
8 changed files with 295 additions and 26 deletions

View file

@ -300,7 +300,7 @@ MODULE moduleMesh
END FUNCTION inside_interface
PURE FUNCTION phy2log_interface(self,r) RESULT(Xi)
PURE FUNCTION phy2log_interface(self,r) RESULT(Xi)
IMPORT:: meshCell
CLASS(meshCell), INTENT(in):: self
REAL(8), INTENT(in):: r(1:3)
@ -387,17 +387,17 @@ MODULE moduleMesh
!Array of boundary elements
TYPE(meshEdgeCont), ALLOCATABLE:: edges(:)
!Global stiffness matrix
REAL(8), ALLOCATABLE, DIMENSION(:,:):: K
REAL(8), ALLOCATABLE, DIMENSION(:,:):: K
!Permutation matrix for P L U factorization
INTEGER, ALLOCATABLE, DIMENSION(:,:):: IPIV
!PROCEDURES SPECIFIC OF FILE TYPE
PROCEDURE(printOutput_interface), POINTER, PASS:: printOutput => NULL()
PROCEDURE(printEM_interface), POINTER, PASS:: printEM => NULL()
PROCEDURE(doCoulomb_interface), POINTER, PASS:: doCoulomb => NULL()
PROCEDURE(printAverage_interface), POINTER, PASS:: printAverage => NULL()
CONTAINS
!GENERIC PROCEDURES
PROCEDURE, PASS:: constructGlobalK
PROCEDURE, PASS:: doCoulomb
END TYPE meshParticles
@ -424,7 +424,7 @@ MODULE moduleMesh
CLASS(meshParticles), INTENT(inout):: self
END SUBROUTINE doCoulomb_interface
!Prints average values
SUBROUTINE printAverage_interface(self)
IMPORT meshParticles
@ -481,7 +481,11 @@ MODULE moduleMesh
!Logical to indicate if an specific mesh for MC Collisions is used
LOGICAL:: doubleMesh
!Logical to indicate if MCC collisions are performed
LOGICAL:: doMCC
LOGICAL:: doMCCollisions = .FALSE.
!Logical to indicate if Coulomb scattering is performed
LOGICAL:: doCoulombScattering = .FALSE.
!Logica to indicate if particles have to be listed in list inside the cells
LOGICAL:: listInCells = .FALSE.
!Complete path for the two meshes
CHARACTER(:), ALLOCATABLE:: pathMeshColl, pathMeshParticle
@ -511,7 +515,7 @@ MODULE moduleMesh
END DO
END DO
DEALLOCATE(n, localK)
END DO
@ -616,7 +620,7 @@ MODULE moduleMesh
tensorS = outerProduct(part%v, part%v)
sp = part%species%n
DO i = 1, nNodes
node => mesh%nodes(cellNodes(i))%obj
CALL OMP_SET_LOCK(node%lock)
@ -650,7 +654,7 @@ MODULE moduleMesh
part%Xi = Xi
part%n_in = .TRUE.
!Assign particle to listPart_in
IF (doMCC) THEN
IF (listInCells) THEN
CALL OMP_SET_LOCK(self%lock)
sp = part%species%n
CALL self%listPart_in(sp)%add(part)
@ -673,7 +677,7 @@ MODULE moduleMesh
CALL neighbourElement%fBoundary(part%species%n)%apply(neighbourElement,part)
!If particle is still inside the domain, call findCell
IF (part%n_in) THEN
IF (part%n_in) THEN
IF(PRESENT(oldCell)) THEN
CALL self%findCell(part, oldCell)
@ -719,13 +723,13 @@ MODULE moduleMesh
INTEGER:: sp
found = .FALSE.
cell => meshColl%cells(part%cellColl)%obj
DO WHILE(.NOT. found)
Xi = cell%phy2log(part%r)
IF (cell%inside(Xi)) THEN
part%cellColl = cell%n
IF (doMCC) THEN
IF (listInCells) THEN
CALL OMP_SET_LOCK(cell%lock)
sp = part%species%n
CALL cell%listPart_in(sp)%add(part)
@ -923,7 +927,7 @@ MODULE moduleMesh
END DO
END IF
!Deallocate arrays for next collision
DEALLOCATE(sigmaVrel, probabilityColl)
@ -946,9 +950,152 @@ MODULE moduleMesh
END SUBROUTINE doCollisions
SUBROUTINE doCoulomb(self)
USE moduleCoulomb
USE moduleRandom
USE moduleOutput
USE moduleList
USE moduleMath
USE moduleRefParam
USE moduleConstParam
IMPLICIT NONE
CLASS(meshParticles), INTENT(inout):: self
CLASS(meshParticles), INTENT(in), TARGET:: self
CLASS(meshCell), POINTER:: cell
INTEGER:: e
INTEGER:: k
INTEGER:: i, j
INTEGER:: n
TYPE(lNode), POINTER:: partTemp
REAL(8):: W(3), dW(2) !Relative velocity between particle and species and its increment
INTEGER(8), ALLOCATABLE:: cellNodes(:)
CLASS(meshNode), POINTER:: node
TYPE(outputFormat):: output
REAL(8), ALLOCATABLE:: densityNodes(:), velocityNodes(:,:), temperatureNodes(:) !values in node
REAL(8):: density, velocity(1:3), temperature!values at particle position
REAL(8), DIMENSION(1:3):: e1, e2, e3
REAL(8):: delta_par, delta_par_square, delta_per, delta_per_square
REAL(8):: l, lW, AW
REAL(8):: rnd
DO e = 1, self%numCells
cell => self%cells(e)%obj
cellNodes = cell%getNodes(cell%nNodes)
ALLOCATE(densityNodes(1:cell%nNodes), &
velocityNodes(1:cell%nNodes, 1:3), &
temperatureNodes(1:cell%nNodes))
DO k=1, nCoulombPairs
i = coulombMatrix(k)%sp_i%n
j = coulombMatrix(k)%sp_j%n
!Do scattering of particles from species_i due to species j
!Compute background properties of species_j
DO n = 1, cell%nNodes
node => self%nodes(cellNodes(n))%obj
CALL calculateOutput(node%output(j), output, node%v, coulombMatrix(k)%sp_j)
densityNodes(n) = output%density/n_ref
velocityNodes(n,1:3) = output%velocity(1:3)/v_ref
temperatureNodes(n) = output%temperature/T_ref
END DO
!Loop over particles of species_i
partTemp => cell%listPart_in(i)%head
DO WHILE(ASSOCIATED(partTemp))
density = cell%gatherF(partTemp%part%Xi, cell%nNodes, densityNodes)
velocity = cell%gatherF(partTemp%part%Xi, cell%nNodes, velocityNodes)
temperature = cell%gatherF(partTemp%part%Xi, cell%nNodes, temperatureNodes)
l = coulombMatrix(k)%l_j/SQRT(temperature)
W = partTemp%part%v - velocity
lW = l * NORM2(W)
AW = coulombMatrix(k)%A_ij/NORM2(W)
!Axis of the relative velocity
!First one is parallel to the relative velocity
e1 = normalize(W)
!Second one is perpendicular to it
e2(1) = -e1(2)
e2(2) = e1(1)
e2(3) = 0.D0
e2 = normalize(e2)
!Third one is perpendicular to the other two
e3 = crossProduct(e2, e1)
e3 = normalize(e3)
delta_par = -coulombMatrix(k)%A_ij*coulombMatrix(k)%one_plus_massRatio_ij*density*l**2*G(lW)
delta_par_square = AW*density*G(lW)
delta_per_square = AW*density*H(lW)
dW(1) = delta_par*tauMin + randomMaxwellian()*SQRT(delta_par_square*tauMin)
dW(2) = DABS(randomMaxwellian()*SQRT(delta_per_square*tauMin))
rnd = random()
partTemp%part%v = partTemp%part%v + dW(1)*e1 + dW(2)*(COS(PI2*rnd)*e2 + &
SIN(PI2*rnd)*e3)
partTemp => partTemp%next
END DO
IF (i /= j) THEN
!Do scattering of particles from species_j due to species i
DO n = 1, cell%nNodes
node => self%nodes(cellNodes(n))%obj
CALL calculateOutput(node%output(i), output, node%v, coulombMatrix(k)%sp_i)
densityNodes(n) = output%density/n_ref
velocityNodes(n,1:3) = output%velocity(1:3)/v_ref
temperatureNodes(n) = output%temperature/T_ref
END DO
partTemp => cell%listPart_in(j)%head
DO WHILE(ASSOCIATED(partTemp))
density = cell%gatherF(partTemp%part%Xi, cell%nNodes, densityNodes)
velocity = cell%gatherF(partTemp%part%Xi, cell%nNodes, velocityNodes)
temperature = cell%gatherF(partTemp%part%Xi, cell%nNodes, temperatureNodes)
l = coulombMatrix(k)%l_i/SQRT(temperature)
W = partTemp%part%v - velocity
lW = l * NORM2(W)
AW = coulombMatrix(k)%A_ji/NORM2(W)
!Axis of the relative velocity
!First one is parallel to the relative velocity
e1 = normalize(W)
!Second one is perpendicular to it
e2(1) = -e1(2)
e2(2) = e1(1)
e2(3) = 0.D0
e2 = normalize(e2)
!Third one is perpendicular to the other two
e3 = crossProduct(e2, e1)
e3 = normalize(e3)
delta_par = -coulombMatrix(k)%A_ji*coulombMatrix(k)%one_plus_massRatio_ji*density*l**2*G(lW)
delta_par_square = AW*density*G(lW)
delta_per_square = AW*density*H(lW)
dW(1) = delta_par*tauMin + randomMaxwellian()*SQRT(delta_par_square*tauMin)
dW(2) = DABS(randomMaxwellian()*SQRT(delta_per_square*tauMin))
rnd = random()
partTemp%part%v = partTemp%part%v + dW(1)*e1 + dW(2)*(COS(PI2*rnd)*e2 + &
SIN(PI2*rnd)*e3)
partTemp => partTemp%next
END DO
END IF
END DO
END DO
END SUBROUTINE doCoulomb