First implementation of Non-Analogue Scheme using volume weighting. The

scheme to use is chosen in the input file. Additional schemes could be
added easily.
This commit is contained in:
Jorge Gonzalez 2020-12-03 08:57:34 +01:00
commit 7859a73274
8 changed files with 151 additions and 54 deletions

View file

@ -37,10 +37,10 @@ moduleOutput.o: moduleSpecies.o moduleRefParam.o moduleOutput.f95
moduleRefParam.o: moduleConstParam.o moduleRefParam.f95
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
moduleSpecies.o: moduleCaseParam.o moduleSpecies.f95
moduleSpecies.o: moduleErrors.o moduleCaseParam.o moduleSpecies.f95
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
moduleSolver.o: moduleEM.o moduleSpecies.o moduleRefParam.o moduleMesh.o moduleOutput.o moduleSolver.f95
moduleSolver.o: moduleList.o moduleEM.o moduleSpecies.o moduleRefParam.o moduleMesh.o moduleOutput.o moduleSolver.f95
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
moduleTable.o: moduleErrors.o moduleTable.f95

View file

@ -13,8 +13,8 @@ MODULE moduleInject
INTEGER:: sp !Species of injection
INTEGER:: nEdges
INTEGER, ALLOCATABLE:: edges(:) !Array with edges
REAL(8), ALLOCATABLE:: weight(:) !weight of cells for injection
REAL(8):: sumWeight
! REAL(8), ALLOCATABLE:: weight(:) !weight of cells for injection
! REAL(8):: sumWeight
CONTAINS
PROCEDURE, PASS:: init => initInject
PROCEDURE, PASS:: addParticles => addParticlesMaxwellian
@ -79,22 +79,22 @@ MODULE moduleInject
self%nEdges = COUNT(phSurface == physicalSurface)
ALLOCATE(inject(i)%edges(1:self%nEdges))
ALLOCATE(inject(i)%weight(1:self%nEdges))
! ALLOCATE(inject(i)%weight(1:self%nEdges))
et = 0
DO e=1, mesh%numEdges
IF (mesh%edges(e)%obj%physicalSurface == physicalSurface) THEN
et = et + 1
self%edges(et) = mesh%edges(e)%obj%n
SELECT TYPE(edge => mesh%edges(e)%obj)
CLASS IS (meshEdgeCyl)
self%weight(et) = (edge%r(1)+edge%r(2))/2.D0
END SELECT
! SELECT TYPE(edge => mesh%edges(e)%obj)
! CLASS IS (meshEdgeCyl)
! self%weight(et) = (edge%r(1)+edge%r(2))/2.D0
!
! END SELECT
END IF
END DO
self%sumWeight = SUM(self%weight)
! self%sumWeight = SUM(self%weight)
END SUBROUTINE
@ -105,7 +105,6 @@ MODULE moduleInject
IMPLICIT NONE
INTEGER:: i
LOGICAL:: mask(1:nInject)
!$OMP SINGLE
nPartInj = 0
@ -148,8 +147,8 @@ MODULE moduleInject
IMPLICIT NONE
CLASS(injectGeneric), INTENT(in):: self
REAL(8):: randomX
INTEGER:: i, j
INTEGER:: randomX
INTEGER:: i!, j
INTEGER, SAVE:: nMin, nMax !Min and Max index in partInj array
INTEGER:: n
CLASS(meshEdge), POINTER:: randomEdge
@ -180,14 +179,15 @@ MODULE moduleInject
!$OMP DO
DO n = nMin, nMax
!Select edge randomly from which inject particle
randomX = RAND()*self%sumWeight
DO j = 1, self%nEdges
IF (randomX < self%weight(j)) EXIT
randomX = randomX - self%weight(j)
! randomX = RAND()*self%sumWeight
! DO j = 1, self%nEdges
! IF (randomX < self%weight(j)) EXIT
! randomX = randomX - self%weight(j)
!
! END DO
randomX = INT(DBLE(self%nEdges-1)*RAND()) + 1
END DO
randomEdge => mesh%edges(self%edges(j))%obj
randomEdge => mesh%edges(self%edges(randomX))%obj
!Random position in edge
partInj(n)%r = randomEdge%randPos()
!Volume associated to the edge:

View file

@ -31,9 +31,6 @@ MODULE moduleInput
!Read species
CALL readSpecies(config)
!Reads case parameters
CALL readCase(config)
!Read interactions between species
CALL readInteractions(config)
@ -44,6 +41,10 @@ MODULE moduleInput
CALL verboseError('Reading Geometry...')
CALL readGeometry(config)
!Reads case parameters
CALL verboseError('Reading Case Parameters...')
CALL readCase(config)
!Read boundary for EM field
CALL readEMBoundary(config)
@ -267,6 +268,9 @@ MODULE moduleInput
!TODO: In a future, this should include the particles from init states
nPartOld = 0
!Initialize the lock for the non-analogue (NA) list of particles
CALL OMP_INIT_LOCK(lockNAScheme)
END SUBROUTINE readSpecies
!Reads information about interactions between species

View file

@ -1,7 +1,6 @@
!Linked list of particles
MODULE moduleList
USE moduleSpecies
USE OMP_LIB
IMPLICIT NONE
TYPE lNode
@ -21,9 +20,7 @@ MODULE moduleList
END TYPE listNode
INTEGER(KIND=OMP_LOCK_KIND):: resetLock
TYPE(listNode):: partNew
TYPE(listNode):: partNAScheme !Particles comming from the nonAnalogue scheme
TYPE pointerArray
TYPE(particle), POINTER:: part

View file

@ -1034,13 +1034,8 @@ MODULE moduleMeshCyl
CLASS(*), POINTER:: nextElement
xi = self%phy2log(part%r)
!Checks if particle is inside of current cell
!Checks if particle is inside 'self' cell
IF (self%inside(xi)) THEN
! IF (PRESENT(oldCell)) THEN
! !If oldCell, recalculate particle weight, as particle has entered a new cell.
! part%weight = part%weight*oldCell%volume/self%volume
!
! END IF
part%vol = self%n
part%xi = xi
part%n_in = .TRUE.

View file

@ -40,10 +40,14 @@ MODULE moduleSolver
END SUBROUTINE solveEM_interface
!Apply nonAnalogue scheme to a particle
SUBROUTINE nonAnalogue_interface(part)
SUBROUTINE nonAnalogue_interface(part, volOld, volNew)
USE moduleSpecies
USE moduleMesh
IMPLICIT NONE
TYPE(particle), INTENT(inout):: part
CLASS(meshVol), POINTER, INTENT(in):: volOld
CLASS(meshVol), POINTER, INTENT(inout):: volNew
END SUBROUTINE nonAnalogue_interface
@ -97,12 +101,16 @@ MODULE moduleSolver
!Initialize the non-analogue scheme
SUBROUTINE initNA(self, NAType)
USE moduleMesh
IMPLICIT NONE
CLASS(solverGeneric), INTENT(inout):: self
CHARACTER(:), ALLOCATABLE:: NAType
SELECT CASE(NAType)
CASE ('Volume')
self%nonAnalogue => volumeNAScheme
CASE DEFAULT
self%nonAnalogue => noNAScheme
@ -170,8 +178,6 @@ MODULE moduleSolver
END IF
part_temp%v(2) = cos_alpha*v_p_oh_star(2)+sin_alpha*v_p_oh_star(3)
part_temp%v(3) = -sin_alpha*v_p_oh_star(2)+cos_alpha*v_p_oh_star(3)
part_temp%sp = part%sp
part_temp%vol = part%vol
part_temp%n_in = .FALSE. !Assume particle is outside until cell is found
!Copy temporal particle to particle
part=part_temp
@ -238,12 +244,14 @@ MODULE moduleSolver
SUBROUTINE doReset()
USE moduleSpecies
USE moduleList
IMPLICIT NONE
INTEGER:: nn, n
INTEGER, SAVE:: nPartNew
INTEGER, SAVE:: nInjIn, nOldIn
INTEGER, SAVE:: nInjIn, nOldIn, nNAScheme
TYPE(particle), ALLOCATABLE, SAVE:: partTemp(:)
TYPE(lNode), POINTER:: partCurr, partNext
!$OMP SECTIONS
!$OMP SECTION
@ -258,13 +266,15 @@ MODULE moduleSolver
nOldIn = COUNT(partOld%n_in)
END IF
!$OMP SECTION
nNAScheme = partNAScheme%amount
!$OMP END SECTIONS
!$OMP BARRIER
!$OMP SINGLE
CALL MOVE_ALLOC(partOld, partTemp)
nPartNew = nInjIn + nOldIn
nPartNew = nInjIn + nOldIn + nNAScheme
ALLOCATE(partOld(1:nPartNew))
!$OMP END SINGLE
@ -290,6 +300,20 @@ MODULE moduleSolver
END IF
END DO
!$OMP SECTION
nn = nInjIn + nOldIn
partCurr => partNAScheme%head
DO n = 1, nNAScheme
partNext => partCurr%next
partOld(nn+n) = partCurr%part
DEALLOCATE(partCurr)
partCurr => partNext
END DO
IF (ASSOCIATED(partNAScheme%head)) NULLIFY(partNAScheme%head)
IF (ASSOCIATED(partNAScheme%tail)) NULLIFY(partNAScheme%tail)
partNAScheme%amount = 0
!$OMP END SECTIONS
!$OMP SINGLE
@ -373,12 +397,88 @@ MODULE moduleSolver
END SUBROUTINE noEMField
!Empty procedure that does no computation of EM field for neutral cases
SUBROUTINE noNAScheme(part)
!Modify particle weight as a function of cell volume and splits particle
SUBROUTINE volumeNAScheme(part, volOld, volNew)
USE moduleSpecies
USE moduleMesh
IMPLICIT NONE
TYPE(particle), INTENT(inout):: part
CLASS(meshVol), POINTER, INTENT(in):: volOld
CLASS(meshVol), POINTER, INTENT(inout):: volNew
REAL(8):: fractionVolume, fractionWeight
INTEGER:: nSplit
!If particle has change cell, call nonAnalogue scheme
IF (volOld%n /= volNew%n) THEN
fractionVolume = volOld%volume/volNew%volume
part%weight = part%weight * fractionVolume
fractionWeight = part%weight / species(part%sp)%obj%weight
IF (fractionWeight >= 2.D0) THEN
nSplit = FLOOR(fractionWeight)
CALL splitParticle(part, nSplit, volNew)
ELSEIF (part%weight < 1.D0) THEN
!Particle has lost statistical meaning and will be terminated
part%n_in = .FALSE.
END IF
END IF
END SUBROUTINE volumeNAScheme
!Subroutine to split the particle 'part' into a number 'nSplit' of particles.
!'nSplit-1' particles are added to the partNAScheme list
SUBROUTINE splitParticle(part, nSplit, vol)
USE moduleSpecies
USE moduleList
USE moduleMesh
USE OMP_LIB
IMPLICIT NONE
TYPE(particle), INTENT(inout):: part
INTEGER, INTENT(in):: nSplit
CLASS(meshVol), INTENT(inout):: vol
REAL(8):: newWeight
TYPE(particle), POINTER:: newPart
INTEGER:: p
newWeight = part%weight / nSplit
!Assign new weight to original particle
part%weight = newWeight
!Add new particles to list of NA particles
DO p = 2, nSplit
!Allocate the pointer for the new particles
ALLOCATE(newPart)
!Copy data from original particle
newPart = part
CALL OMP_SET_LOCK(lockNAScheme)
CALL partNAScheme%add(newPart)
CALL OMP_UNSET_LOCK(lockNASCheme)
!Add particle to cell list
CALL OMP_SET_lock(vol%lock)
CALL vol%listPart_in%add(newPart)
CALL OMP_UNSET_lock(vol%lock)
END DO
END SUBROUTINE splitParticle
!Empty procedure that does no computation of EM field for neutral cases
SUBROUTINE noNAScheme(part, volOld, volNew)
USE moduleSpecies
USE moduleMesh
IMPLICIT NONE
TYPE(particle), INTENT(inout):: part
CLASS(meshVol), POINTER, INTENT(in):: volOld
CLASS(meshVol), POINTER, INTENT(inout):: volNew
END SUBROUTINE noNAScheme
@ -389,17 +489,13 @@ MODULE moduleSolver
CLASS(solverGeneric), INTENT(in):: self
TYPE(particle), INTENT(inout):: part
CLASS(meshVol), POINTER:: vol
INTEGER:: volOld !Old cell for particle
CLASS(meshVol), POINTER:: volOld, volNew
volOld = part%vol
vol => mesh%vols(volOld)%obj
CALL vol%findCell(part)
!If particle has change cell, call nonAnalogue scheme
IF (volOld /= part%vol) THEN
CALL self%nonAnalogue(part)
END IF
volOld => mesh%vols(part%vol)%obj
CALL volOld%findCell(part)
volNew => mesh%vols(part%vol)%obj
!Call the NA shcme
CALL self%nonAnalogue(part, volOld, volNew)
END SUBROUTINE updateParticleCell

View file

@ -1,6 +1,7 @@
!Contains the information about species (particles)
MODULE moduleSpecies
USE moduleCaseParam
USE OMP_LIB
IMPLICIT NONE
TYPE, ABSTRACT:: speciesGeneric
@ -44,9 +45,11 @@ MODULE moduleSpecies
!Arrays that contain the particles
TYPE(particle), ALLOCATABLE, DIMENSION(:), TARGET:: partOld !array of particles from previous iteration
TYPE(particle), ALLOCATABLE, DIMENSION(:), TARGET:: partInj !array of inject particles
INTEGER(KIND=OMP_LOCK_KIND):: lockNAScheme !Lock for the NA list of particles
CONTAINS
FUNCTION speciesName2Index(speciesName) RESULT(sp)
USE moduleErrors
IMPLICIT NONE
CHARACTER(:), ALLOCATABLE:: speciesName
@ -60,7 +63,8 @@ MODULE moduleSpecies
EXIT
END IF
END DO
!TODO: add error handling when species not found
!If no species is found, call a critical error
IF (sp == 0) CALL criticalError('Species ' // speciesName // ' not found.', 'speciesName2Index')
END FUNCTION speciesName2Index