Compare commits
4 commits
06a797de49
...
55645e18b0
| Author | SHA1 | Date | |
|---|---|---|---|
| 55645e18b0 | |||
| bd67bd6606 | |||
| ab120c0e8d | |||
| 02773c7ad9 |
5 changed files with 184 additions and 2 deletions
Binary file not shown.
|
|
@ -619,7 +619,7 @@ make
|
||||||
Required values are:
|
Required values are:
|
||||||
|
|
||||||
\textbf{potential}: Real.
|
\textbf{potential}: Real.
|
||||||
Potential for Dirichlet boundary condition.
|
Potential for Dirichlet boundary condition.
|
||||||
|
|
||||||
\textbf{temporalProfile}: Character.
|
\textbf{temporalProfile}: Character.
|
||||||
Filename of the 2 column file containing the time variable profile.
|
Filename of the 2 column file containing the time variable profile.
|
||||||
|
|
@ -627,6 +627,12 @@ make
|
||||||
The first column is the time in $\unit{s}$.
|
The first column is the time in $\unit{s}$.
|
||||||
The second column is the factor that will multiply the value set in \textbf{potential}.
|
The second column is the factor that will multiply the value set in \textbf{potential}.
|
||||||
|
|
||||||
|
\item \textbf{neumann}: Constant value of the electric field normal to the surface.
|
||||||
|
Required fields are:
|
||||||
|
|
||||||
|
\textbf{electricField}: Real.
|
||||||
|
Value of the electric field constant to the surface.
|
||||||
|
|
||||||
\item \textbf{floating}: The potential is adjusted over time to maintain a zero current on the surface, \textit{i. e.}, the surface is \textit{floating}.
|
\item \textbf{floating}: The potential is adjusted over time to maintain a zero current on the surface, \textit{i. e.}, the surface is \textit{floating}.
|
||||||
\textbf{potential}: Real.
|
\textbf{potential}: Real.
|
||||||
Initial potential of the surface.
|
Initial potential of the surface.
|
||||||
|
|
|
||||||
|
|
@ -972,6 +972,11 @@ MODULE moduleInput
|
||||||
|
|
||||||
call initFloating(self, config, object)
|
call initFloating(self, config, object)
|
||||||
|
|
||||||
|
case ("freeCurrent")
|
||||||
|
allocate(boundaryEMFreeCurrent:: self)
|
||||||
|
|
||||||
|
call initFreeCurrent(self, config, object)
|
||||||
|
|
||||||
case default
|
case default
|
||||||
call criticalError('Boundary type ' // bType // ' not supported', 'readBoundaryEM')
|
call criticalError('Boundary type ' // bType // ' not supported', 'readBoundaryEM')
|
||||||
|
|
||||||
|
|
@ -1334,8 +1339,25 @@ MODULE moduleInput
|
||||||
! If the boundary for the species is linked to the one analysing, add the edges
|
! If the boundary for the species is linked to the one analysing, add the edges
|
||||||
if (associated(physicalSurfaces(ps)%EM, bound)) then
|
if (associated(physicalSurfaces(ps)%EM, bound)) then
|
||||||
bound%nodes = [bound%nodes, physicalSurfaces(ps)%nodes]
|
bound%nodes = [bound%nodes, physicalSurfaces(ps)%nodes]
|
||||||
|
|
||||||
end if
|
end if
|
||||||
|
|
||||||
|
! Specific assignments per type
|
||||||
|
select type(bound)
|
||||||
|
type is(boundaryEMFreeCurrent)
|
||||||
|
if (associated(physicalSurfaces(ps)%EM, bound)) then
|
||||||
|
bound%edges = [bound%edges, physicalSurfaces(ps)%edges]
|
||||||
|
|
||||||
|
bound%nEdges = size(bound%edges)
|
||||||
|
allocate(bound%electricField(1:bound%nEdges))
|
||||||
|
bound%electricField = 0.0d0
|
||||||
|
allocate(bound%surfaceCharge(1:bound%nEdges))
|
||||||
|
bound%surfaceCharge = 0.0d0
|
||||||
|
|
||||||
|
end if
|
||||||
|
|
||||||
|
end select
|
||||||
|
|
||||||
end do
|
end do
|
||||||
|
|
||||||
bound%nNodes = size(bound%nodes)
|
bound%nNodes = size(bound%nodes)
|
||||||
|
|
|
||||||
|
|
@ -1113,6 +1113,34 @@ MODULE moduleMesh
|
||||||
|
|
||||||
end interface
|
end interface
|
||||||
|
|
||||||
|
! Calculates the electric field normal to the surface based on Ampere's law (without magnetic field)
|
||||||
|
type, extends(boundaryEMGeneric):: boundaryEMFreeCurrent
|
||||||
|
integer:: nEdges
|
||||||
|
type(meshEdgePointer), allocatable:: edges(:) ! Edges included in the boundary
|
||||||
|
real(8), allocatable:: electricField(:) ! Electric field normal to the edge that must be applied with a Neumann boundary condition
|
||||||
|
real(8), allocatable:: surfaceCharge(:) ! Surface charge density
|
||||||
|
contains
|
||||||
|
procedure, pass:: apply => applyFreeCurrent
|
||||||
|
|
||||||
|
end type boundaryEMFreeCurrent
|
||||||
|
|
||||||
|
interface
|
||||||
|
module subroutine initFreeCurrent(self, config, object)
|
||||||
|
use json_module
|
||||||
|
|
||||||
|
class(boundaryEMGeneric), allocatable, intent(inout):: self
|
||||||
|
type(json_file), intent(inout):: config
|
||||||
|
character(:), allocatable, intent(in):: object
|
||||||
|
|
||||||
|
end subroutine initFreeCurrent
|
||||||
|
|
||||||
|
module subroutine applyFreeCurrent(self, vectorF)
|
||||||
|
class(boundaryEMFreeCurrent), intent(in):: self
|
||||||
|
real(8), intent(inout):: vectorF(:)
|
||||||
|
|
||||||
|
end subroutine applyFreeCurrent
|
||||||
|
|
||||||
|
end interface
|
||||||
! Container for boundary conditions
|
! Container for boundary conditions
|
||||||
TYPE:: boundaryEMCont
|
TYPE:: boundaryEMCont
|
||||||
CLASS(boundaryEMGeneric), ALLOCATABLE:: obj
|
CLASS(boundaryEMGeneric), ALLOCATABLE:: obj
|
||||||
|
|
|
||||||
|
|
@ -238,7 +238,6 @@ submodule(moduleMesh) boundaryEM
|
||||||
|
|
||||||
! Update
|
! Update
|
||||||
subroutine updateFloating(self)
|
subroutine updateFloating(self)
|
||||||
use moduleMesh, only: qSpecies, meshNode
|
|
||||||
use moduleCaseParam, only: tauMin
|
use moduleCaseParam, only: tauMin
|
||||||
implicit none
|
implicit none
|
||||||
|
|
||||||
|
|
@ -309,6 +308,133 @@ submodule(moduleMesh) boundaryEM
|
||||||
|
|
||||||
end subroutine writeFloating
|
end subroutine writeFloating
|
||||||
|
|
||||||
|
! Free current
|
||||||
|
! Init
|
||||||
|
module subroutine initFreeCurrent(self, config, object)
|
||||||
|
use json_module
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
class(boundaryEMGeneric), allocatable, intent(inout):: self
|
||||||
|
type(json_file), intent(inout):: config
|
||||||
|
character(:), allocatable, intent(in):: object
|
||||||
|
|
||||||
|
select type(self)
|
||||||
|
type is(boundaryEMFreeCurrent)
|
||||||
|
allocate(self%edges(0))
|
||||||
|
|
||||||
|
self%update => updateFreeCurrent
|
||||||
|
self%print => writeFreeCurrent
|
||||||
|
|
||||||
|
end select
|
||||||
|
|
||||||
|
end subroutine initFreeCurrent
|
||||||
|
|
||||||
|
! Apply
|
||||||
|
module subroutine applyFreeCurrent(self, vectorF)
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
class(boundaryEMFreeCurrent), intent(in):: self
|
||||||
|
real(8), intent(inout):: vectorF(:)
|
||||||
|
integer:: e, n
|
||||||
|
integer, allocatable:: nodes(:)
|
||||||
|
real(8), allocatable:: fPsi(:)
|
||||||
|
|
||||||
|
do e = 1, self%nEdges
|
||||||
|
associate(edge => self%edges(e)%obj)
|
||||||
|
fPsi = edge%fPsi(edge%centerXi(), edge%nNodes)
|
||||||
|
|
||||||
|
nodes = edge%getNodes(edge%nNodes)
|
||||||
|
|
||||||
|
do n = 1, edge%nNodes
|
||||||
|
associate(node => mesh%nodes(nodes(n))%obj)
|
||||||
|
! Assign to each node the corresponding weight of the Neumann BC
|
||||||
|
vectorF(node%n) = vectorF(node%n) - fPsi(n) * self%electricField(e)/node%v
|
||||||
|
|
||||||
|
end associate
|
||||||
|
|
||||||
|
end do
|
||||||
|
|
||||||
|
end associate
|
||||||
|
|
||||||
|
deallocate(fPsi, nodes)
|
||||||
|
|
||||||
|
end do
|
||||||
|
|
||||||
|
end subroutine applyFreeCurrent
|
||||||
|
|
||||||
|
! Update
|
||||||
|
subroutine updateFreeCurrent(self)
|
||||||
|
use moduleCaseParam, only: tauMin
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
class(boundaryEMGeneric), intent(inout):: self
|
||||||
|
integer:: e, n, s
|
||||||
|
integer, allocatable:: nodes(:)
|
||||||
|
real(8), allocatable:: mom_nodes(:)
|
||||||
|
class(meshNode), pointer:: node
|
||||||
|
real(8):: mom_center, edgeDensityCurrent
|
||||||
|
|
||||||
|
select type(self)
|
||||||
|
type is(boundaryEMFreeCurrent)
|
||||||
|
do e=1, self%nEdges
|
||||||
|
edgeDensityCurrent = 0.0d0
|
||||||
|
|
||||||
|
associate(edge => self%edges(e)%obj)
|
||||||
|
|
||||||
|
! Gather the current density at the edge
|
||||||
|
nodes = edge%getNodes(edge%nNodes)
|
||||||
|
allocate(mom_nodes(1:edge%nNodes))
|
||||||
|
do s = 1, nSpecies
|
||||||
|
mom_center = 0.0d0
|
||||||
|
do n = 1, self%nNodes
|
||||||
|
node => mesh%nodes(nodes(n))%obj
|
||||||
|
|
||||||
|
! Minus sign to get the flux exiting the edge
|
||||||
|
mom_nodes(n) = - dot_product(node%output(s)%mom, edge%normal)
|
||||||
|
|
||||||
|
end do
|
||||||
|
|
||||||
|
mom_center = edge%gatherF(edge%centerXi(), edge%nNodes, mom_nodes)
|
||||||
|
|
||||||
|
edgeDensityCurrent = edgeDensityCurrent + qSpecies(s) * mom_center
|
||||||
|
|
||||||
|
end do
|
||||||
|
|
||||||
|
end associate
|
||||||
|
|
||||||
|
self%surfaceCharge(e) = self%surfaceCharge(e) + edgeDensityCurrent * tauMin
|
||||||
|
|
||||||
|
self%electricField(e) = - self%surfaceCharge(e)
|
||||||
|
|
||||||
|
end do
|
||||||
|
|
||||||
|
end select
|
||||||
|
|
||||||
|
end subroutine updateFreeCurrent
|
||||||
|
|
||||||
|
! Write
|
||||||
|
subroutine writeFreeCurrent(self, fileID)
|
||||||
|
! use moduleOutput, only: fmtColReal
|
||||||
|
use moduleConstParam, only: qe, eps_0
|
||||||
|
use moduleRefParam, only: EF_ref, L_ref, n_ref, v_ref, ti_ref
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
class(boundaryEMGeneric), intent(inout):: self
|
||||||
|
integer, intent(in):: fileID
|
||||||
|
integer:: e
|
||||||
|
|
||||||
|
write(fileID, '(A)') self%name
|
||||||
|
select type(self)
|
||||||
|
type is(boundaryEMFreeCurrent)
|
||||||
|
do e = 1, self%nEdges
|
||||||
|
print*, self%edges(e)%obj%n, self%electricField(e)*EF_ref, self%surfaceCharge(e)*qe*n_ref*v_ref*ti_ref
|
||||||
|
|
||||||
|
end do
|
||||||
|
|
||||||
|
end select
|
||||||
|
|
||||||
|
end subroutine writeFreeCurrent
|
||||||
|
|
||||||
! Get the index of the boundary based on the name
|
! Get the index of the boundary based on the name
|
||||||
module function boundaryEMName_to_Index(boundaryName) result(bp)
|
module function boundaryEMName_to_Index(boundaryName) result(bp)
|
||||||
use moduleErrors
|
use moduleErrors
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue