I still have to figure out how to do this properly, but I am tired of working on my laptop.
164 lines
4.9 KiB
Fortran
164 lines
4.9 KiB
Fortran
!Contains the information about species (particles)
|
|
MODULE moduleSpecies
|
|
USE moduleCaseParam
|
|
USE OMP_LIB
|
|
IMPLICIT NONE
|
|
|
|
!Basic type that defines a macro-particle
|
|
TYPE:: particle
|
|
REAL(8):: r(1:3) !Position
|
|
REAL(8):: v(1:3) !Velocity
|
|
CLASS(speciesGeneric), POINTER:: species !Pointer to species associated with this particle
|
|
INTEGER:: cell !Index of element in which the particle is located. TODO: Make these pointers
|
|
INTEGER:: cellColl !Index of element in which the particle is located in the Collision Mesh
|
|
REAL(8):: Xi(1:3) !Logical coordinates of particle in element e_p.
|
|
LOGICAL:: n_in !Flag that indicates if a particle is in the domain
|
|
REAL(8):: weight=0.D0 !weight of particle
|
|
|
|
END TYPE particle
|
|
|
|
!Wrapper to store the particles per species
|
|
TYPE:: particleArray
|
|
TYPE(particle), ALLOCATABLE, DIMENSION(:):: p
|
|
|
|
END TYPE particleArray
|
|
|
|
!Array of pointers for the species to be pushed
|
|
TYPE:: particleArray_pointer
|
|
TYPE(particle), POINTER, DIMENSION(:):: p
|
|
|
|
END TYPE particleArray_pointer
|
|
|
|
!Number of old particles
|
|
INTEGER, ALLOCATABLE, DIMENSION(:):: nPartOld
|
|
INTEGER:: nPartOldTotal
|
|
!Number of injected particles
|
|
INTEGER:: nPartInj
|
|
!Arrays that contain the particles
|
|
TYPE(particle), ALLOCATABLE, TARGET, DIMENSION(:):: partInj !array of inject particles
|
|
TYPE(particleArray), ALLOCATABLE, TARGET, DIMENSION(:):: partOld !array of particles from previous iteration
|
|
TYPE(particleArray_pointer), ALLOCATABLE, DIMENSION(:):: particlesToPush !particles pushed in each iteration
|
|
|
|
INTEGER:: nSpeciesToPush
|
|
INTEGER, ALLOCATABLE, DIMENSION(:):: nPartOldToPush
|
|
|
|
!Generic species type
|
|
TYPE, ABSTRACT:: speciesGeneric
|
|
INTEGER:: n=0 !Index of species
|
|
CHARACTER(:), ALLOCATABLE:: name !Name of species
|
|
!Mass, default weight of species and charge over mass
|
|
REAL(8):: mass=0.D0, weight=0.D0, qm=0.D0
|
|
INTEGER:: every !How many interations between advancing the species
|
|
LOGICAL:: pushSpecies !Boolean to indicate if the species is moved in the iteration
|
|
|
|
END TYPE speciesGeneric
|
|
|
|
!Neutral species
|
|
TYPE, EXTENDS(speciesGeneric):: speciesNeutral
|
|
CLASS(speciesGeneric), POINTER:: ion => NULL()
|
|
CONTAINS
|
|
PROCEDURE, PASS:: ionize => ionizeNeutral
|
|
|
|
END TYPE speciesNeutral
|
|
|
|
!Charged species
|
|
TYPE, EXTENDS(speciesGeneric):: speciesCharged
|
|
REAL(8):: q=0.D0
|
|
CLASS(speciesGeneric), POINTER:: ion => NULL(), neutral => NULL()
|
|
CONTAINS
|
|
PROCEDURE, PASS:: ionize => ionizeCharged
|
|
PROCEDURE, PASS:: neutralize => neutralizeCharged
|
|
|
|
END TYPE speciesCharged
|
|
|
|
!Wrapper for species
|
|
TYPE:: speciesCont
|
|
CLASS(speciesGeneric), ALLOCATABLE:: obj
|
|
|
|
END TYPE
|
|
|
|
!Number of species
|
|
INTEGER:: nSpecies
|
|
!Array for species
|
|
TYPE(speciesCont), ALLOCATABLE, TARGET:: species(:)
|
|
|
|
CONTAINS
|
|
FUNCTION speciesName2Index(speciesName) RESULT(sp)
|
|
USE moduleErrors
|
|
IMPLICIT NONE
|
|
|
|
CHARACTER(:), ALLOCATABLE:: speciesName
|
|
INTEGER:: sp
|
|
INTEGER:: s
|
|
|
|
sp = 0
|
|
DO s = 1, nSpecies
|
|
IF (speciesName == species(s)%obj%name) THEN
|
|
sp = species(s)%obj%n
|
|
EXIT !If a species is found, exit the loop
|
|
|
|
END IF
|
|
|
|
END DO
|
|
|
|
!If no species is found, call a critical error
|
|
IF (sp == 0) CALL criticalError('Species ' // speciesName // ' not found.', 'speciesName2Index')
|
|
|
|
END FUNCTION speciesName2Index
|
|
|
|
!Change particle type to corresponding ion (neutral species)
|
|
SUBROUTINE ionizeNeutral(self, part)
|
|
USE moduleErrors
|
|
IMPLICIT NONE
|
|
|
|
CLASS(speciesNeutral), INTENT(IN):: self
|
|
TYPE(particle), INTENT(inout):: part
|
|
|
|
IF (ASSOCIATED(self%ion)) THEN
|
|
part%species => self%ion
|
|
|
|
ELSE
|
|
CALL criticalError('No ion defined for species :' // self%name, 'ionizeNeutral')
|
|
|
|
END IF
|
|
|
|
END SUBROUTINE ionizeNeutral
|
|
|
|
!Change particle type to corresponding ion (charged species)
|
|
SUBROUTINE ionizeCharged(self, part)
|
|
USE moduleErrors
|
|
IMPLICIT NONE
|
|
|
|
CLASS(speciesCharged), INTENT(IN):: self
|
|
TYPE(particle), INTENT(inout):: part
|
|
|
|
IF (ASSOCIATED(self%ion)) THEN
|
|
part%species => self%ion
|
|
|
|
ELSE
|
|
CALL criticalError('No ion defined for species :' // self%name, 'ionizeCharged')
|
|
|
|
END IF
|
|
|
|
END SUBROUTINE ionizeCharged
|
|
|
|
!Change particle type to corresponding neutral
|
|
SUBROUTINE neutralizeCharged(self, part)
|
|
USE moduleErrors
|
|
IMPLICIT NONE
|
|
|
|
CLASS(speciesCharged), INTENT(in):: self
|
|
TYPE(particle), INTENT(inout):: part
|
|
|
|
IF (ASSOCIATED(self%neutral)) THEN
|
|
part%species => self%neutral
|
|
|
|
ELSE
|
|
CALL criticalError('No neutral defined for species' // self%name, 'neutralizeCharged')
|
|
|
|
END IF
|
|
|
|
END SUBROUTINE neutralizeCharged
|
|
|
|
END MODULE moduleSpecies
|
|
|