LCOV - code coverage report
Current view: top level - init - efield.f90 (source / functions) Hit Total Coverage
Test: FLEUR test coverage Lines: 44 372 11.8 %
Date: 2024-04-19 04:21:58 Functions: 3 12 25.0 %

          Line data    Source code
       1             :       MODULE m_efield
       2             :       USE m_juDFT
       3             :       USE m_constants
       4             :       IMPLICIT NONE
       5             :       PRIVATE
       6             :       PUBLIC :: e_field
       7             :       CONTAINS
       8          80 :       SUBROUTINE e_field(atoms,  stars, sym, vacuum, cell, input,efield)
       9             : !
      10             : !*********************************************************************
      11             : !     sets the values of the sheets of charge for external electric
      12             : !     fields by requiring charge neutrality.
      13             : !     the position of the sheets of charge relative to the vacuum
      14             : !     boundary is fixed (10 a.u.), but can be set to a different
      15             : !     value in the file apwefl.
      16             : !
      17             : !     modified and fixed 10-99
      18             : !*********************************************************************
      19             : 
      20             :       USE m_types
      21             :       !USE m_setcor, ONLY: setcor
      22             :       IMPLICIT NONE
      23             : !     ..
      24             : !     .. Scalar Arguments ..
      25             :       TYPE(t_atoms), INTENT (IN)    :: atoms
      26             :       Type(t_stars),INTENT(IN)      :: stars
      27             :       TYPE(t_sym),INTENT(IN)        :: sym
      28             :       TYPE(t_vacuum),INTENT(IN)     :: vacuum
      29             :       TYPE(t_cell),INTENT(IN)       :: cell
      30             :       TYPE(t_input),INTENT(IN)      :: input
      31             :       TYPE(t_efield),INTENT(INOUT)  :: efield
      32             : !     ..
      33             : !     ..
      34             : !     .. Local Scalars ..
      35             :       REAL, parameter :: eps = 1.0e-7
      36             :       REAL  qn,qe,bmu
      37             :       INTEGER n,iwd,nst,nc
      38             : !     ..
      39             : !     ..
      40             : !     .. Local Parameters ..
      41             :       INTEGER, PARAMETER :: pTOP = 1, pBOT = 2, pTOPBOT = 3
      42             :       INTEGER, PARAMETER :: pADD = 1, pREPLACE = 2
      43             :       INTEGER, PARAMETER :: pALL = 1, pZERO = 2, pNONZERO = 3
      44             : !
      45             : !--->    obtain total nuclear charge
      46             : !
      47          80 :       qn=0.0
      48         217 :       DO n=1,atoms%ntype
      49         217 :          qn=qn+atoms%neq(n)*atoms%zatom(n)
      50             :       ENDDO
      51             : !
      52             : !--->    obtain total electronic charge (in electron units)
      53             : !
      54          80 :       qe=0.0
      55             : !---> core electrons
      56         217 :       DO n = 1,atoms%ntype
      57         217 :          IF (atoms%zatom(n).GE.1.0) THEN
      58         137 :             qe=qe+atoms%neq(n)*atoms%econf(n)%core_electrons
      59         137 :             WRITE (oUnit,*) 'neq= ',atoms%neq(n),'  ncore= ',qe
      60             :          ENDIF
      61             :       ENDDO
      62             : !---> semi-core and valence electrons
      63          80 :       qe=qe+input%zelec
      64          80 :       WRITE (oUnit,"(A, F16.8)") 'zelec=  ',input%zelec
      65             : 
      66          80 :       WRITE (oUnit, '(/,/,a)') ' parameters for external electric field:'
      67          80 :       WRITE (oUnit, '(3x,a,f12.5)') 'total electronic charge   =', qe
      68          80 :       WRITE (oUnit, '(3x,a,f12.5)') 'total nuclear charge      =', qn
      69             : 
      70          80 :       CALL read_efield (efield, stars%mx1, stars%mx2, vacuum%nvac, cell%area)
      71             : 
      72             :       ! Sign convention of electric field: E>0 repels electrons,
      73             :       ! consistent with conventional choice that current is
      74             :       ! opposite to electron flow. With this choice, qe < qn
      75             :       ! corresponds to E>0
      76             :       ! In case of Dirichlet boundary conditions, we ignore the
      77             :       ! value of "sigma" and take the surplus charge into account
      78             :       ! in vvac.
      79          80 :       if (efield%autocomp .or. efield%dirichlet) efield%sigma = 0.5*(qe-qn)
      80             : 
      81          80 :       CALL print_efield (oUnit,efield, cell%area, vacuum%nvac, cell%amat,vacuum%dvac)
      82             : 
      83             :       IF (.NOT. efield%dirichlet&
      84         240 :      &    .AND. ABS (SUM (efield%sig_b) + 2*efield%sigma - (qe-qn)) > eps) THEN
      85           0 :         IF (ABS (SUM (efield%sig_b) - (qe-qn)) < eps) THEN
      86             :           CALL juDFT_error&
      87             :      &          ("E field: top+bottom+film charge does not add up to "&
      88             :      &           //"zero.",&
      89             :      &           hint="Consider setting 'autocomp = false' in apwefl. "&
      90             :      &           //"(By default, the number of electrons in the energy "&
      91             :      &           //"window is automatically compensated via the charge "&
      92             :      &           //"sheets.)",&
      93           0 :      &           calledby ="efield")
      94             :         END IF
      95             :         CALL juDFT_error&
      96             :      &        ("E field: top+bottom+film charge does not add up to zero"&
      97           0 :      &        ,calledby ="efield")
      98             :       ENDIF
      99             : 
     100         240 :       IF (ABS (efield%sigma) > 0.49 .OR. ANY (ABS (efield%sig_b) > 0.49)) THEN
     101           0 :         WRITE (oUnit,*) 'If you really want to calculate an e-field this'
     102           0 :         WRITE (oUnit,*) 'big, uncomment STOP in efield.f !'
     103             :         CALL juDFT_error("E-field too big or No. of e- not correct"&
     104           0 :      &       ,calledby ="efield")
     105             :       ENDIF
     106             : 
     107          80 :       IF (efield%l_segmented) THEN
     108             :         CALL V_seg_EF(&
     109             :      &                efield,&
     110           0 :      &                vacuum, stars)
     111             : 
     112           0 :         IF (efield%plot_rho)&
     113             :      &    CALL print_rhoEF(&
     114             :      &                     efield, stars%mx1, stars%mx2, vacuum%nvac, stars%ng2, sym%nop, sym%nop2,&
     115             :      &                     stars%ng2, stars%kv2, sym%mrot, sym%symor, sym%tau, sym%invtab,&
     116           0 :      &                     cell%area, stars%nstr2, cell%amat)
     117             :       END IF
     118             : 
     119          80 :       IF (ALLOCATED (efield%sigEF)) DEALLOCATE (efield%sigEF)
     120             : 
     121          80 :       IF (efield%dirichlet .AND. ALLOCATED (efield%rhoEF))&
     122           0 :      &  call set_dirchlet_coeff (efield, vacuum%dvac, stars%ng2, stars%sk2, vacuum%nvac)
     123             : 
     124             :       CONTAINS
     125             : 
     126           0 :       SUBROUTINE set_dirchlet_coeff (E, dvac, nq2, sk2, nvac)
     127             :         TYPE(t_efield), INTENT(INOUT), TARGET :: E
     128             :         REAL, INTENT(IN) :: dvac
     129             :         INTEGER, INTENT(IN) :: nq2, nvac
     130             :         REAL, INTENT(IN) :: sk2(:)
     131             : 
     132           0 :         COMPLEX, POINTER :: V(:,:)
     133             :         REAL :: x, y, g
     134             :         INTEGER :: ig, ivac1, ivac2
     135             : 
     136           0 :         ALLOCATE (E%C1(nq2-1), E%C2(nq2-1))
     137           0 :         E%l_dirichlet_coeff = .true.
     138             : 
     139           0 :         V => E%rhoEF
     140           0 :         ivac1 = 1
     141           0 :         ivac2 = nvac
     142             : 
     143           0 :         DO ig = 1, nq2-1
     144           0 :           g = sk2(ig+1)
     145           0 :           x = EXP ( g*(E%zsigma+Dvac/2.0))
     146           0 :           y = EXP (-g*(E%zsigma+Dvac/2.0))
     147           0 :           E%C1(ig) = (V(ig, ivac1)*x - V(ig, ivac2)*y) / (x**2-y**2)
     148           0 :           E%C2(ig) = (V(ig, ivac2)*x - V(ig, ivac1)*y) / (x**2-y**2)
     149             :         END DO
     150           0 :       END SUBROUTINE set_dirchlet_coeff
     151             : 
     152             : ! Read the electric field parameters from the 'apwefl' file
     153             : ! (except for sigma, which is determined by the charge in the film).
     154             : !
     155             : ! The position of the charged sheet can be given (in a.u.) via
     156             : ! zsigma, an additional, in x-y homogeneous field can be given via
     157             : ! sig_b(1) and sig_b(2). NOTE: The position zsigma counts from the
     158             : ! interstitial-vacuum boundary ("z1") and not from the center (z=0).
     159             : !
     160             : ! There are two input formats. The old format is
     161             : !    zsigma
     162             : !    sig_b(nvac)
     163             : ! where sig_b is optional. zsigma is 10.0 by default while b_sig is zero.
     164             : !
     165             : ! In the new format, lines starting with "!" or "#" are treated as comments
     166             : ! and all keywords are case insensitive.
     167             : !
     168             : ! Namelist (optionally, defaults to the shown values):
     169             : !   &efield zsigma=10.0, sig_b=0.0,0.0, plot_charge=f, plot_rho=f,
     170             : !           autocomp=t, dirichlet=f, eV=f /
     171             : !
     172             : ! By default, Neumann boundary conditions are assumed and additional charge
     173             : ! is placed as surface charge density at the charge sheets located at zsigma.
     174             : ! If Dirichlet is true, a (segmented) metal plate at zsigma is assumed,
     175             : ! which has a charge of zero - or the value given by sig_b or via adding
     176             : ! different shapes. In case of Dirichlet boundary conditions, the value is
     177             : ! regarded as potential in Hartree (or [electron] Volt, if "eV" is set to
     178             : ! true.)
     179             : !
     180             : ! A fancy potential can now be created by placing charge in a rectangular
     181             : ! or circular region via the "rect" and "circ" directive. Both directives
     182             : ! are followed by "top, "bot" or "TopBot"/"BotTop" and then a point (x,y),
     183             : ! which denotes for "rect" the bottom-left coordinate and for "circ" the
     184             : ! centre. Next parameter is the width/height for "rect" and the diameter
     185             : ! radius for "circ". Followed by a parameter for the charge (or the
     186             : ! potential in case of Dirichlet boundary conditions). Optional
     187             : ! arguments: The charge can be added ("add", default) to the previous
     188             : ! charge in this sheet - or it replaces ("replace") the charge. The
     189             : ! charge can be placed in the whole area ("all", default) or only where
     190             : ! previously no charge ("zero") or a "nonzero" charge was.
     191             : ! The sig_b charge is added after all the shapes and is thus treated like
     192             : ! a "rect 0,0 top/bot  1.0,1.0 b_sig(1)/b_sig(2)" would be.
     193             : !
     194             : ! Note: All coordinates are relative coordinates. The regions can exceed the
     195             : ! x-y extend of the film; e.g. using
     196             : !   circ top 0,0  0.25  0.5
     197             : ! one places 1/2 an electron in a quarter circle with origin (0,0).
     198             : !
     199             : ! WARNING: "circ" creates a perfect circle on the grid, however, it only
     200             : ! matches a circle and not an ellipse if the k1d/k2d ratio matches the
     201             : ! crystal a/b ratio.
     202             : ! TODO: Support input in absolute values instead of relative ones.
     203             : ! (Could be an option to the namelist or another (optional) tag.)
     204             : !
     205             : ! rectSinX: Create a sinusoidal potential in x direction (constant in y
     206             : ! direction for any x value), i.e.
     207             : !   V(x,y) = A * sin(2*pi*n*x + 2*pi*delta)
     208             : ! A is the amplitude; however, the argument in apwefl is not A directly
     209             : ! but   A' = A * Lz, where Lz is the number of points in z direction.
     210             : ! Contrary to "circ" and "rect", charges are mask out without being
     211             : ! redistributed to non-masked positions. Note:
     212             : !  Int_0^(2pi) A*|sin(x)| dx = 4*A)
     213             : ! n is the order and delta the offset. "x" is relative to the rectangle
     214             : ! and thus between 0 and 1. The syntax is:
     215             : !   rectSinX top/bot  x,y  w,h,  A', n, delta  [options]
     216             : !
     217             : !   datafile top/bot filename [zero_avg] [option]
     218             : ! Read data points from "filename"; if zero_avg is present, average the
     219             : ! read data to zero; replace/add is supported, but zero/not_zero is not.
     220             : !
     221             : ! polygon: Create a polygon-shaped charge distribution; note that the
     222             : ! currently used algorithm does not always give the perfactly shaped
     223             : ! polygon - and the edge points are not always included in the polygon.
     224             : ! Syntax:
     225             : !   polygon top/bot n_points, x1,y1, ..., xn,yn charge [options]
     226             : !
     227             : !
     228             : ! Example 1: To have two top plates (segments):
     229             : !   rect top 0,  0  0.5,1.0  0.2
     230             : !   rect top 0.5,0  0.5,1.0 -0.2
     231             : !
     232             : ! Example 2: To have a charged ring with 0.2e and -0.2e of charge
     233             : ! evenly distributed outside this ring:
     234             : !   circ topBot 0.5,0.50.2  1           ! Create temporary an inner ring
     235             : !   circ topBot 0.5,0.50.3  0.2 zero    ! Create outer ring
     236             : !   circ topBot 0.5,0.50.2  0   replace ! Delete inner ring
     237             : !   rect topBot 0,0     1,1 -0.2 zero    ! Place smeared opposite charge
     238             : !
     239             : !
     240             : ! If autocomp is .true., the extra charge in the film (Window) is distributed
     241             : ! over both external sheets; if it is .false. one needs to compensate it
     242             : ! manually.
     243             : !
     244             : ! Note: The namelist has to be placed before the shapes when Dirichlet
     245             : ! boundary conditions are used as otherwise the potential is divided by
     246             : ! the number of grid points...
     247             : 
     248          80 :       SUBROUTINE read_efield (E, k1d, k2d, nvac, area)
     249             :         TYPE(t_efield), INTENT(INOUT) :: E
     250             :         INTEGER, INTENT(IN) :: k1d, k2d, nvac
     251             :         REAL, INTENT(IN) :: area
     252             : 
     253             :         REAL ::   tmp
     254             :         INTEGER :: i
     255             : 
     256             :         ! New format
     257         400 :         ALLOCATE(E%sigEF(3*k1d, 3*k2d, nvac))
     258      207681 :         E%sigEF = 0.0
     259          80 :         if (allocated(e%shapes)) then
     260          80 :         DO i=1,SIZE(e%shapes)
     261          80 :            CALL read_shape (E, e%shapes(i), nvac)
     262             :         END DO
     263             :         endif
     264          80 :         IF (e%l_eV) THEN
     265           0 :           E%sig_b(:) = E%sig_b/hartree_to_ev_const
     266           0 :           E%sigEF(:,:,:) = E%sigEF/hartree_to_ev_const
     267             :         END IF
     268             :         ! Save average sigEF potential in sig_b and remove it from
     269             :         ! sigEF to avoid double counting; i.e. make g_|| = 0 of sigEF == 0.
     270          80 :         IF (E%dirichlet) THEN
     271           0 :           tmp = sum(E%sigEF(:,:,1))/SIZE(E%sigEF)*nvac
     272           0 :           E%sig_b(1) = E%sig_b(1) + tmp
     273           0 :           E%sigEF(:,:,1) = E%sigEF(:,:,1) - tmp
     274             :         ELSE
     275      111020 :           tmp = sum(E%sigEF(:,:,1))
     276          80 :           E%sig_b(1) = E%sig_b(1) + tmp
     277      111260 :           E%sigEF(:,:,1) = E%sigEF(:,:,1) - tmp/SIZE(E%sigEF)*nvac
     278             :         END IF
     279          80 :         IF (nvac > 1) THEN
     280          71 :           IF (E%dirichlet) THEN
     281           0 :             tmp = sum(E%sigEF(:,:,2))/SIZE(E%sigEF)*nvac
     282           0 :             E%sig_b(2) = E%sig_b(2) + tmp
     283           0 :             E%sigEF(:,:,2) = E%sigEF(:,:,2) - tmp
     284             :           ELSE
     285       96581 :             tmp = sum(E%sigEF(:,:,2))
     286          71 :             E%sig_b(2) = E%sig_b(2) + tmp
     287       96794 :             E%sigEF(:,:,2) = E%sigEF(:,:,2) - tmp/SIZE(E%sigEF)*nvac
     288             :           END IF
     289           9 :         ELSE IF (E%sig_b(2) /= 0.0) THEN
     290             :            CALL juDFT_error&
     291             :      &          ("z-mirror/inversion symmetry but second e-field"//&
     292           0 :      &          "sheet specified",calledby ="efield")
     293             :         END IF
     294             : 
     295      207681 :         IF (ALL (E%sigEF == 0.0)) THEN
     296          80 :           DEALLOCATE (E%sigEF)
     297             :         ELSE
     298           0 :           E%l_segmented = .TRUE.
     299             :         END IF
     300          80 :       END SUBROUTINE read_efield
     301             : 
     302           0 :       SUBROUTINE read_shape (E, orig_str, nvac)
     303             :         USE m_constants, ONLY : pimach
     304             :         TYPE(t_efield), INTENT(INOUT) :: E
     305             :         CHARACTER(*), INTENT(IN) :: orig_str
     306             :         INTEGER, INTENT(IN) :: nvac
     307             : 
     308             :         REAL :: TWO_PI
     309             :         INTEGER :: ipos, action, iopt, ivac, ix, iy, nx, ny, cnt, i, j
     310             :         INTEGER :: np
     311             :         CHARACTER(10) :: tag, pos
     312             :         CHARACTER(200) :: str
     313             :         REAL :: x, y, h, w, radius, charge, order, shift, tmp
     314           0 :         REAL, ALLOCATABLE :: poly(:,:)
     315           0 :         REAL :: data(UBOUND(E%sigEF, dim=1), UBOUND(E%sigEF, dim=2))
     316           0 :         LOGICAL :: mask(UBOUND(E%sigEF, dim=1), UBOUND(E%sigEF, dim=2))
     317             : 
     318           0 :         TWO_PI = 2.0 * pimach()
     319           0 :         str = lower_case (orig_str)
     320             : 
     321           0 :         IF (str(1:8) == 'rectsinx') THEN
     322           0 :           READ (str, *) tag, pos, x, y, w, h, charge, order, shift
     323           0 :           IF (tag /= 'rectsinx')&
     324             :      &        CALL juDFT_error("Internal error in read_shape (rectSinX)"&
     325           0 :      &        ,calledby ="efield")
     326           0 :         ELSE IF (str(1:4) == 'circ') THEN
     327           0 :           READ (str, *) tag, pos, x, y, radius, charge
     328           0 :           IF (tag /= 'circ')  CALL juDFT_error&
     329             :      &         ("Internal error in read_shape (circ)",calledby ="efield"&
     330           0 :      &         )
     331           0 :         ELSE IF (str(1:4) == 'rect') THEN
     332           0 :           READ (str, *) tag, pos, x, y, w, h, charge
     333           0 :           IF (tag /= 'rect')  CALL juDFT_error&
     334             :      &         ("Internal error in read_shape (rect)",calledby ="efield"&
     335           0 :      &         )
     336           0 :         ELSE IF (str(1:7) == 'polygon') THEN
     337           0 :           READ (str, *) tag, pos, np
     338           0 :           ALLOCATE (poly(2,np))
     339           0 :           READ (str, *) tag, pos, np, poly, charge
     340           0 :           IF (tag /= 'polygon')&
     341             :      &         CALL juDFT_error("Internal error in read_shape (polygon)"&
     342           0 :      &         ,calledby ="efield")
     343           0 :         ELSE IF (str(1:8) == "datafile") THEN
     344           0 :           READ (str, *) tag, pos
     345           0 :           IF (tag /= 'datafile')  CALL juDFT_error&
     346           0 :      &         ("Internal error in read_shape",calledby ="efield")
     347             :         ELSE
     348           0 :            CALL juDFT_error("ERROR reading ",calledby ="efield")
     349             :         END IF
     350             : 
     351           0 :         IF (pos == 'top') THEN
     352           0 :           ipos = pTOP
     353           0 :         ELSEIF (pos == 'bot') THEN
     354           0 :           ipos = pBOT
     355           0 :         ELSEIF (pos == 'topbot' .OR. pos == 'bottop') THEN
     356           0 :           ipos = pTOPBOT
     357             :         ELSE
     358           0 :            CALL juDFT_error("ERROR reading ",calledby ="efield")
     359             :         END IF
     360             : 
     361           0 :         IF (nvac == 1 .AND. ipos /= pTOP)&
     362           0 :      &       CALL juDFT_error("ERROR reading ",calledby ="efield")
     363             : 
     364           0 :         action = pADD
     365           0 :         IF (INDEX (str, 'replace') > 0) action = pREPLACE
     366           0 :         iopt = pALL
     367           0 :         IF (INDEX (str, ' zero') > 0) iopt = pZERO
     368           0 :         IF (INDEX (str, 'nonzero') > 0) iopt = pNONZERO
     369             : 
     370           0 :         mask = .false.
     371           0 :         nx = UBOUND (mask, dim=1)
     372           0 :         ny = UBOUND (mask, dim=2)
     373             : 
     374           0 :         IF (tag == 'rect') THEN
     375             :           mask(MAX (FLOOR(x*nx-0.5)+2,1) : MIN (FLOOR((x+w)*nx+0.5),nx),&
     376             :      &         MAX (FLOOR(y*ny-0.5)+2,1) : MIN (FLOOR((y+h)*ny+0.5),ny))&
     377           0 :      &      = .true.
     378           0 :           WRITE (oUnit, *) tag, pos2str (ipos), x, y, h, w, charge,&
     379           0 :      &                 action2str (action), opt2str (iopt)
     380           0 :         ELSE IF (tag == 'rectsinx') THEN
     381             :           mask(MAX (FLOOR(x*nx-0.5)+2,1) : MIN (FLOOR((x+w)*nx+0.5),nx),&
     382             :      &         MAX (FLOOR(y*ny-0.5)+2,1) : MIN (FLOOR((y+h)*ny+0.5),ny))&
     383           0 :      &      = .true.
     384           0 :           WRITE (oUnit, *) tag, pos2str (ipos), x, y, h, w, charge, order,&
     385           0 :      &                 shift, action2str (action), opt2str (iopt)
     386           0 :         ELSE IF (tag == 'circ') THEN
     387           0 :           DO iy = 1, ny
     388           0 :             DO ix = 1, nx
     389           0 :               IF (SQRT ((REAL (ix)/nx - x)**2 + (REAL(iy)/ny - y)**2)&
     390             :      &            <= radius)&
     391           0 :      &          mask(ix, iy) = .true.
     392             :             END DO
     393             :           END DO
     394           0 :           WRITE (oUnit, *) tag, pos2str (ipos), x, y, radius, charge,&
     395           0 :      &                 action2str (action), opt2str (iopt)
     396           0 :         ELSE IF (tag == 'datafile') THEN
     397           0 :           WRITE (oUnit, '(1x,a,1x,a)', advance="no") tag, pos2str (ipos)
     398           0 :           call readDataFile (str, data)
     399           0 :           WRITE (oUnit, *) action2str (action), opt2str (iopt)
     400           0 :           mask = .true.
     401           0 :         ELSE IF (tag == 'polygon') THEN
     402           0 :           DO iy = 1, ny
     403           0 :             DO ix = 1, nx
     404             :               mask(ix, iy) = in_polygon (np, poly, (/real(ix-1)/nx,&
     405           0 :      &                                               real(iy-1)/ny/))
     406             :             END DO
     407             :           END DO
     408             :         ELSE
     409             :            CALL juDFT_error("Internal error in read_shape",calledby&
     410           0 :      &          ="efield")
     411             :         END IF
     412             : 
     413           0 :         IF (action == pADD) THEN
     414             :           ! All relevant vacua
     415           0 :           DO ivac = 2 - MOD (ipos, 2), MIN (ipos, 2)
     416           0 :             IF (iopt == pZERO) THEN
     417           0 :               mask = mask .and. (E%sigEF(:,:,ivac) == 0.0)
     418           0 :             ELSE IF (iopt == pNONZERO) THEN
     419           0 :               mask = mask .and. (E%sigEF(:,:,ivac) /= 0.0)
     420             :             END IF
     421             : 
     422           0 :             IF (tag == 'rectsinx') THEN
     423             :               ! number of grid points in y direction
     424           0 :               IF (E%dirichlet) THEN
     425             :                 cnt = 1
     426             :               ELSE
     427           0 :                 cnt = MAXVAL (COUNT (mask, dim=2))
     428             :               END IF
     429           0 :               i = MAX (FLOOR(x*nx-0.5)+2,1)
     430           0 :               j = MIN (FLOOR((x+w)*nx+0.5),nx)
     431           0 :               DO ix = i, j
     432           0 :                 tmp = REAL (ix-1)/REAL (j) ! Range: [0,1)
     433           0 :                 DO iy = 1, ny
     434           0 :                   IF (.NOT. mask (ix, iy)) CYCLE
     435             :                   E%sigEF(ix,iy,ivac) = E%sigEF(ix,iy,ivac)&
     436           0 :      &                   + charge/cnt * SIN (TWO_PI*(order*tmp+shift))
     437             :                 END DO
     438             :               END DO
     439           0 :             ELSE IF (tag == 'datafile') THEN
     440           0 :               WHERE (mask) E%sigEF(:,:,ivac) = E%sigEF(:,:,ivac) + data
     441             :             ELSE ! circ, rect
     442           0 :               IF (E%dirichlet) THEN
     443             :                 cnt = 1
     444             :               ELSE
     445           0 :                 cnt = COUNT (mask)
     446             :               END IF
     447             :               WHERE (mask) E%sigEF(:,:,ivac) = E%sigEF(:,:,ivac)&
     448           0 :      &                                         + charge/cnt
     449             :             END IF
     450             :          END DO ! ivac
     451             :         ELSE ! pREPLACE
     452             :           ! All relevant vacua
     453           0 :           DO ivac = 2 - MOD (ipos, 2), MIN (ipos, 2)
     454           0 :             IF (iopt == pZERO) THEN
     455           0 :               mask = mask .and. (E%sigEF(:,:,ivac) == 0.0)
     456           0 :             ELSE IF (iopt == pNONZERO) THEN
     457           0 :               mask = mask .and. (E%sigEF(:,:,ivac) /= 0.0)
     458             :             END IF
     459             : 
     460           0 :             IF (tag == 'rectsinx') THEN
     461             :               ! number of grid points in y direction
     462           0 :               IF (E%dirichlet) THEN
     463             :                 cnt = 1
     464             :               ELSE
     465           0 :                 cnt = MAXVAL (COUNT (mask, dim=2))
     466             :               END IF
     467           0 :               i = MAX (FLOOR(x*nx-0.5)+2,1)
     468           0 :               j = MIN (FLOOR((x+w)*nx+0.5),nx)
     469           0 :               DO ix = i, j
     470           0 :                 tmp = REAL (ix-1)/REAL (j) ! Range: [0,1)
     471           0 :                 DO iy = 1, ny
     472           0 :                   IF (.NOT. mask (ix, iy)) CYCLE
     473             :                     E%sigEF(ix,iy,ivac) =&
     474           0 :      &                     + charge/cnt * SIN (TWO_PI*(order*tmp+shift))
     475             :                 END DO
     476             :               END DO
     477           0 :             ELSE IF (tag == 'datafile') THEN
     478           0 :               WHERE (mask) E%sigEF(:,:,ivac) = data
     479             :             ELSE ! circ, rect
     480           0 :               IF (E%dirichlet) THEN
     481             :                 cnt = 1
     482             :               ELSE
     483           0 :                 cnt = COUNT (mask)
     484             :               END IF
     485           0 :              WHERE (mask) E%sigEF(:,:,ivac) = charge/cnt
     486             :             END IF
     487             :           END DO ! ivac
     488             :         END IF
     489           0 :       END SUBROUTINE read_shape
     490             : 
     491             :       ! Read electric-field data points from "file"
     492             :       ! Format: First line, number of x and y points
     493             :       !         Second line: charge(x=1,y=1)
     494             :       !         Third line:  charge(x=1,y=2)
     495             :       !         etc.
     496           0 :       SUBROUTINE readDataFile (str, data)
     497             :         CHARACTER(*), intent(in) :: str
     498             :         REAL, intent(out) :: data(:,:)
     499             : 
     500             :         integer :: i, j, nx, ny
     501             :         logical :: l_exist
     502           0 :         character(len (str)) :: file, dummy
     503             : 
     504           0 :         read(str, *) dummy, dummy, file
     505             : 
     506           0 :         nx = ubound(data, dim=1)
     507           0 :         ny = ubound(data, dim=2)
     508             : 
     509           0 :         INQUIRE (file=file, exist=l_exist)
     510           0 :         IF (.not. l_exist) GOTO 110
     511             : 
     512           0 :         OPEN (1243, file=file, status='old')
     513           0 :         READ (1243, *, end=110) i, j  ! nx ny
     514           0 :         IF (i /= nx .or. j /= ny) THEN
     515           0 :           WRITE (*,'(3a)') "ERROR: Invalid number of points in '",&
     516           0 :      &           trim(file), "' during electrical field dataFile"
     517           0 :           WRITE (*,"(a,i0,a,i0,a)") "Expected: ", nx, ",", ny
     518           0 :           WRITE (*,"(a,i0,a,i0,a)") "Read    : ", i, ", ", j
     519             :           CALL juDFT_error("ERROR: dataFile of electric fiel&
     520           0 :      &d",calledby ="efield")
     521             :         END IF
     522             : 
     523           0 :         DO j = 1, ny
     524           0 :           DO i = 1, nx
     525           0 :             READ (1243, *) data(i,j)
     526             :           END DO
     527             :         END DO
     528           0 :         CLOSE (1243)
     529             : 
     530           0 :         WRITE (oUnit, '(1x,3a,1x)', advance="no") '"', trim (file), '"'
     531           0 :         IF (INDEX (lower_case (str), 'zero_avg') > 0) THEN
     532           0 :           data(:,:) = data - sum(data)/(nx*ny)
     533           0 :           WRITE (oUnit, '(a,1x)', advance="no") "zero_avg"
     534             :         END IF
     535             : 
     536           0 :         RETURN ! No error
     537             : 
     538             :         ! ERROR
     539           0 : 110     WRITE (*,'(3a)') "ERROR: While reading '",trim(file),&
     540           0 :      &                   "' during electrical field dataFile"
     541           0 :         WRITE (*,"(a,i0,a,i0,a)") "Expecting  ", nx, ",", ny, " points"
     542             :         CALL juDFT_error("ERROR: dataFile of electric field",calledby&
     543           0 :      &       ="efield")
     544             :       END SUBROUTINE readDataFile
     545             : 
     546             : 
     547             : ! Give a polygon and a trial point. Now a line is taken from the edge
     548             : ! of the grid and it is counted how many times an edges of the polygon
     549             : ! is crossed. If it was an odd time until one reaches the point, it is
     550             : ! in the polygon - otherwise not.
     551             : ! Note: The technique does not always find the optimal polygon.
     552             : !
     553             : ! Cf. http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
     554             : !
     555           0 :       PURE FUNCTION in_polygon (n, poly, point)
     556             :         INTEGER, intent(in) :: n
     557             :         REAL, intent(in) :: poly(2,n), point(2)
     558             :         LOGICAL :: in_polygon
     559             :         INTEGER :: i, j
     560             : 
     561           0 :         i = 1
     562           0 :         j = n
     563           0 :         in_polygon = .FALSE.
     564           0 :         DO
     565           0 :           IF (i > n) EXIT
     566           0 :           IF ((poly(2,i) > point(2)) .NEQV. (poly(2,j) > point(2))) THEN
     567           0 :             IF (point(1) <  (poly(1,j) - poly(1,i))&
     568             :      &                    * (point(2)-poly(2,i)) / (poly(2,j)-poly(2,i))&
     569             :      &                    + poly(1,i))&
     570           0 :      &      in_polygon = .NOT. in_polygon
     571             :           END IF
     572           0 :           j = i
     573           0 :           i = i+1
     574             :         END DO
     575           0 :       END FUNCTION in_polygon
     576             : 
     577           0 :       PURE FUNCTION pos2str (ipos)
     578             :         INTEGER, INTENT(IN) :: ipos
     579             :         CHARACTER(6) :: pos2str
     580           0 :         IF (ipos == pTOP) THEN
     581           0 :           pos2str = 'Top'
     582           0 :         ELSE IF (ipos == pBOT) THEN
     583           0 :           pos2str = 'Bot'
     584             :         ELSE
     585           0 :           pos2str = 'TopBot'
     586             :         END IF
     587           0 :       END FUNCTION pos2str
     588             : 
     589             : 
     590           0 :       PURE FUNCTION action2str (action)
     591             :         INTEGER, INTENT(IN) :: action
     592             :         CHARACTER(7) :: action2str
     593           0 :         IF (action == pADD) THEN
     594           0 :           action2str = 'Add'
     595             :         ELSE
     596           0 :           action2str = 'Replace'
     597             :         END IF
     598           0 :       END FUNCTION action2str
     599             : 
     600             : 
     601           0 :       PURE FUNCTION opt2str (iopt)
     602             :         INTEGER, INTENT(IN) :: iopt
     603             :         CHARACTER(7) :: opt2str
     604           0 :         IF (iopt == pALL) THEN
     605           0 :           opt2str = 'All'
     606           0 :         ELSE IF (iopt == pZERO) THEN
     607           0 :           opt2str = 'Zero'
     608             :         ELSE
     609           0 :           opt2str = 'NonZero'
     610             :         END IF
     611           0 :       END FUNCTION opt2str
     612             : 
     613             : 
     614          80 :       SUBROUTINE print_efield (unit, E, area, nvac, amat,dvac)
     615             :           INTEGER, INTENT(IN)        :: unit, nvac
     616             :           TYPE(t_efield), INTENT(IN) :: E
     617             :           REAL, INTENT(IN)           :: area, amat(3,3),dvac
     618             : 
     619             :           ! electric constant
     620             :           REAL, PARAMETER :: epsilon0 = 8.854187817620e-12 ! F/m
     621             :           ! Bohr radius
     622             :           REAL, PARAMETER :: a0       = 0.52917720859e-10  ! m
     623             :           ! elemental charge
     624             :           REAL, PARAMETER :: ec       = 1.602176487e-19    ! C
     625             : 
     626             :           ! htr -> electron Volt
     627             :           REAL, PARAMETER :: htr_eV   = 27.21138386 ! eV
     628             : 
     629             :           ! Conversion of surface charge sigma to an electric field
     630             :           ! near a plate: E = -sigma[1/m^2]*e/eps0
     631             :           !                 = -sigma[1/a0^2]*e/(eps0 * a0^2)
     632             :           ! Assuming field in V/cm and charge in atomic units
     633             :           ! The 10^-2 is due to centimetres
     634             :           !
     635             :           ! NOTE: This equation assumes that one has two plates, one
     636             :           ! charged "sigma" and one "-sigma"; then E = sigma/eps0.
     637             :           ! If one plate were 0 and the other sigma, one had to use
     638             :           !   E = sigma/(2*eps0)
     639             :           ! Cf. http://hyperphysics.phy-astr.gsu.edu/hbase/electric/elesht.html
     640             :           !
     641             :           ! BE CAREFUL TO AVOID DOUBLE COUNTING
     642             :           REAL, PARAMETER :: sig_to_E = -ec/(epsilon0*a0**2)*1e-2
     643             : 
     644             :           REAL :: tmp, pt_rel(3), pt_abs(3)
     645             :           INTEGER :: ivac, i, j, nx, ny
     646             : 
     647             :           IF (SUM (ABS (E%sig_b)) < 1e-15&
     648             :              &.AND. ABS (E%sigma) < 1e-15&
     649             :              &.AND. .NOT. ALLOCATED (E%sigEF)&
     650         240 :      &        .AND. .NOT. E%dirichlet) RETURN
     651             : 
     652           0 :           WRITE (unit,'(3x,a,2(f12.5,a))')'z-z1 of external sheet    =',&
     653           0 :      &          E%zsigma, ' a0 = ', E%zsigma*a0*1e10, ' A'
     654             : 
     655             : 
     656           0 :           IF (E%dirichlet) THEN
     657             : 
     658           0 :           IF (E%sigma > 0)&
     659           0 :      &      WRITE (unit,'(3x,a,f12.5)') 'Surplus charge: ', 2.0*E%sigma
     660             : 
     661           0 :           IF (ALLOCATED(E%sigEF))&
     662           0 :      &      WRITE (unit,'(3x,a)') 'Average potential:'
     663           0 :           WRITE (unit, '(3x,a,f12.5,a, f12.5,a)') 'on sheet 1: ',&
     664           0 :      &       E%sig_b(1),' htr = ',E%sig_b(1)*hartree_to_ev_const,' V'
     665           0 :           IF (nvac > 1) THEN
     666           0 :             WRITE (unit, '(3x,a,f12.5,a, f12.5,a)') 'on sheet 2: ',&
     667           0 :      &         E%sig_b(2),' htr = ',E%sig_b(2)*hartree_to_ev_const,' V'
     668             : 
     669             :             WRITE (unit,'(3x,a,f14.5,a)')&
     670           0 :      &            'Average field (plate to plate):',&
     671           0 :      &            (E%sig_b(2)-E%sig_b(1))/((2*E%zsigma+Dvac)*a0*100),&
     672           0 :      &            ' V/cm'
     673             :           END IF ! nvac > 1
     674             : 
     675             :           ELSE ! Neumann
     676             : 
     677           0 :           IF (ALLOCATED(E%sigEF))&
     678           0 :      &      WRITE (unit,'(3x,a)') 'Average charges:'
     679           0 :           tmp = E%sigma+E%sig_b(1)
     680             :           WRITE (unit, '((3x,a,f12.5,5x,a,f12.5,a))')&
     681           0 :      &          'charge on external sheet 1 =', tmp,&
     682           0 :      &          '(surface density=', tmp/area, '  e/a.u.**2)'
     683           0 :           tmp = tmp/area*sig_to_E
     684             :           WRITE (unit, '(3x,a,e13.5,5x,a)')&
     685           0 :      &          'external field on sheet 1 =', tmp, 'V/cm'
     686             : 
     687           0 :           IF (nvac > 1) THEN
     688           0 :             tmp = E%sigma+E%sig_b(2)
     689             :             WRITE (unit, '((3x,a,f12.5,5x,a,f12.5,a))')&
     690           0 :      &            'charge on external sheet 2 =', tmp,&
     691           0 :      &            '(surface density=', tmp/area, '  e/a.u.**2)'
     692           0 :             tmp = tmp/area*sig_to_E
     693             :             WRITE (unit, '(3x,a,e13.5,5x,a)')&
     694           0 :      &            'external field on sheet 2 =', tmp, 'V/cm'
     695             : 
     696             :             ! Cf. comment above, where "sig_to_E" is defined
     697             :             WRITE (unit, '(a,/,a)') 'NOTE: The equation for the E field'&
     698           0 :      &         // ' assumes two oppositely charged plates.',&
     699             :      &            '      You may need to divide by two before '&
     700           0 :      &         //'summing the external fields to avoid double counting'
     701             :           ELSE
     702             :             WRITE (unit, '(a)') 'NOTE: The equation for the E field '&
     703             :      &            // 'already assumes two oppositely charged plates - '&
     704           0 :      &            // 'be careful to avoid double counting'
     705             :           END IF ! nvac > 1
     706             : 
     707             :           END IF ! Neumann (vs. Dirichlet)
     708             : 
     709           0 :           IF (ALLOCATED (E%sigEF) .AND. E%plot_charge) THEN
     710           0 :             nx = UBOUND (E%sigEF, dim=1) - 1
     711           0 :             ny = UBOUND (E%sigEF, dim=2) - 1
     712           0 :             DO ivac = 1, nvac
     713           0 :               IF (ivac == 1) THEN
     714           0 :                 OPEN (748, file='efield-1.dat')
     715             :               ELSE
     716           0 :                 OPEN (748, file='efield-2.dat')
     717             :               END IF
     718           0 :               IF (E%dirichlet) THEN
     719           0 :                 WRITE (748, '(3a)') '# X[a0]     Y[a0]   X[rel]   ',&
     720           0 :      &                'Y[rel]    potential[htr]  potential[V]'
     721             :               ELSE ! Neumann
     722           0 :                 WRITE (748, '(3a)') '# X[a0]     Y[a0]   X[rel]   ',&
     723           0 :      &                'Y[rel]    charge per grid point',&
     724           0 :      &                '    E_field (V/cm) in vicinity of the grid point'
     725             :               END IF
     726           0 :               pt_rel(3) = 0.0
     727           0 :               DO i = 1, nx+1
     728           0 :                 pt_rel(1) = REAL(i-1)/nx
     729           0 :                 DO j = 1, ny+1
     730           0 :                   pt_rel(2) = REAL(j-1)/ny
     731           0 :                   pt_abs=matmul(amat,pt_rel)
     732           0 :                   IF (E%dirichlet) THEN
     733             :                     WRITE (748, '(4f12.5,2g16.5)')&
     734           0 :      &                pt_abs(1:2), pt_rel(1:2),&
     735             :      &                E%sigEF(i,j,ivac)&
     736           0 :      &                + E%sig_b(ivac),&
     737             :      &                (E%sigEF(i,j,ivac)&
     738           0 :      &                + E%sig_b(ivac))*hartree_to_ev_const
     739             :                   ELSE ! Neumann
     740             :                     WRITE (748, '(4f12.5,2g16.5)')&
     741           0 :      &                pt_abs(1:2), pt_rel(1:2),&
     742             :      &                E%sigEF(i,j,ivac)&
     743           0 :      &                + (E%sigma + E%sig_b(ivac))/((nx+1)*(ny+1)),&
     744             :      &                (E%sigEF(i,j,ivac)*((nx+1)*(ny+1))&
     745           0 :      &                + E%sigma + E%sig_b(ivac))/area*sig_to_E
     746             :                   END IF
     747             :                 END DO
     748           0 :                 WRITE (748, *)
     749             :               END DO
     750           0 :               CLOSE (748)
     751             :             END DO
     752             :           END IF
     753             :         END SUBROUTINE print_efield
     754             : 
     755           0 :         SUBROUTINE V_seg_EF(&
     756             :      &                      efield,&
     757             :      &                      vacuum, stars)
     758             :           USE m_fft2d
     759             :           use m_types
     760             :           ! Dummy variables:
     761             :           TYPE(t_efield), INTENT(INOUT) :: efield
     762             :           TYPE(t_vacuum), INTENT(IN) :: vacuum
     763             :           TYPE(t_stars), INTENT(IN) :: stars
     764             : 
     765             :           ! Local variables:
     766             :           INTEGER :: i, ivac
     767             :           REAL :: fg, fgi
     768           0 :           COMPLEX :: fgfull(stars%ng2)
     769           0 :           REAL :: rhoRS(3*stars%mx1,3*stars%mx2), rhoRSimag(3*stars%mx1,3*stars%mx2) ! Real space density
     770             : 
     771           0 :           ALLOCATE (efield%rhoEF (stars%ng2-1, vacuum%nvac))
     772             : 
     773           0 :           DO ivac = 1, vacuum%nvac
     774           0 :             rhoRSimag = 0.0 ! Required in the loop. fft2d overrides this
     775             :             ! The fft2d algorithm puts the normalization to the  isn=-1
     776             :             ! (r->k) transformation, thus we need to multiply by
     777             :             ! ifft2 = 3*k1d*3*k2d to compensate.
     778           0 :             IF (efield%dirichlet) THEN
     779           0 :               rhoRS(:,:) = efield%sigEF(:,:,ivac)
     780             :             ELSE
     781           0 :               rhoRS(:,:) = efield%sigEF(:,:,ivac)*(3*stars%mx1*3*stars%mx2)
     782             :             END IF
     783             : 
     784             :             ! FFT rhoRS(r_2d) -> rhoEF(g_2d)
     785             :             CALL fft2d (&
     786             :      &                  stars,&
     787             :      &                  rhoRS, rhoRSimag,&
     788           0 :      &                  fgfull,  -1)
     789           0 :                         efield%rhoEF(:,ivac) = fgfull(2:)
     790             : !           FFT gives the the average charge per grid point
     791             : !           while sig_b stores the (total) charge per sheet
     792           0 :             IF (efield%dirichlet .and. ABS (REAL(fgfull(1))) > 1.0e-15) THEN
     793           0 :               PRINT *, 'INFO: Difference of average potential: fg=',&
     794           0 :      &                 REAL(fgfull(1)),', sig_b=', efield%sig_b(ivac),&
     795           0 :      &                 ", ivac=", ivac
     796           0 :             ELSE IF (ABS (REAL(fgfull(1))/(3*stars%mx1*3*stars%mx2)) > 1.0e-15) THEN
     797           0 :               PRINT *, 'INFO: Difference of average potential: fg=',&
     798           0 :      &                 REAL(fgfull(1))/(3*stars%mx1*3*stars%mx2),', sig_b=', efield%sig_b(ivac),&
     799           0 :      &                 ", ivac=", ivac
     800             :             END IF
     801             :           END DO ! ivac
     802           0 :         END SUBROUTINE V_seg_EF
     803             : 
     804             : 
     805           0 :         SUBROUTINE print_rhoEF(&
     806             :      &                         efield, k1d, k2d, nvac, n2d, nop, nop2,&
     807           0 :      &                         nq2, kv2, mrot, symor, tau, invtab, area,&
     808           0 :      &                         nstr2, amat)
     809             :           USE m_starf, ONLY: starf2
     810             :           ! Arguments
     811             :           TYPE(t_efield), INTENT(IN) :: efield
     812             :           INTEGER, INTENT(IN) :: k1d, k2d, nvac, n2d, nq2, nop, nop2
     813             :           REAL,    INTENT (IN) :: area
     814             :           LOGICAL, INTENT (IN) :: symor
     815             :           INTEGER, INTENT (IN) :: nstr2(n2d), kv2(2,n2d), mrot(3,3,nop),&
     816             :      &                            invtab(nop)
     817             :           REAL,    INTENT (IN) :: tau(3,nop), amat(3,3)
     818             : 
     819             :           ! Local variables
     820             :           real :: pt_rel(3), pt_abs(3), rcc(3)
     821             :           integer :: ix, iy, ivac, k, nix, niy
     822             :           real :: rhoOut, rhoOutIm
     823           0 :           complex :: sf2(n2d)
     824             : 
     825           0 :           nix = 3*k1d-1
     826           0 :           niy = 3*k2d-1
     827             : 
     828           0 :           DO ivac = 1,nvac
     829           0 :             IF (ivac == 1) THEN
     830           0 :               OPEN (754,file='efield-fft-1.dat')
     831             :             ELSE
     832           0 :               OPEN (754,file='efield-fft-2.dat')
     833             :             END IF
     834             : 
     835           0 :             IF (efield%dirichlet) THEN
     836           0 :               WRITE (754, '(2a)') '# X[a0]   Y[a0]  X[rel]  Y[rel]   ',&
     837           0 :      &           'potential per grid point (Re, Im, Abs), grid (ix, iy)'
     838             :             ELSE ! Neumann
     839           0 :               WRITE (754, '(2a)') '# X[a0]   Y[a0]  X[rel]  Y[rel]   ',&
     840           0 :      &           'charge per grid point (Re, Im, Abs), grid (ix, iy)'
     841             :             END IF
     842           0 :             pt_rel(3) = 0.0
     843           0 :             DO ix = 0, nix
     844           0 :               pt_rel(1) = REAL (ix)/REAL (nix)
     845           0 :               DO iy = 0, niy
     846           0 :                 pt_rel(2) = REAL (iy)/REAL (niy)
     847             :                 CALL starf2 (&
     848             :      &                       nop2,nq2,kv2,mrot,symor,tau,pt_rel,invtab,&
     849           0 :      &                       sf2)
     850           0 :                 IF (efield%dirichlet) THEN
     851           0 :                   rhoOut = efield%sig_b(ivac)
     852             :                 ELSE
     853           0 :                   rhoOut = (efield%sigma + efield%sig_b(ivac))/area
     854             :                 END IF
     855           0 :                 rhoOutIm = 0.0
     856             :                 ! As we moved the normalization to g-space while the
     857             :                 ! fft2d routine works in r space, we need to compensate
     858             :                 ! by dividing by ifft2 = 3*k1d*3*k2d
     859           0 :                 DO k = 2, nq2
     860           0 :                   IF (efield%dirichlet) THEN
     861             :                     rhoOut = rhoOut&
     862             :      &                       + REAL (efield%rhoEF(k-1,ivac)*sf2(k))&
     863           0 :      &                         * nstr2(k)
     864             :                     rhoOutIm = rhoOutIm&
     865             :      &                        + AIMAG (efield%rhoEF(k-1,ivac)*sf2(k))&
     866           0 :      &                          * nstr2(k)
     867             :                   ELSE
     868             :                     rhoOut = rhoOut&
     869             :      &                       + REAL (efield%rhoEF(k-1,ivac)*sf2(k))&
     870           0 :      &                         * nstr2(k)/(3*k1d*3*k2d)
     871             :                     rhoOutIm = rhoOutIm&
     872             :      &                        + AIMAG (efield%rhoEF(k-1,ivac)*sf2(k))&
     873           0 :      &                          * nstr2(k)/(3*k1d*3*k2d)
     874             :                   END IF
     875             :                 END DO ! k
     876           0 :                 pt_abs=matmul(amat,pt_rel)
     877             :                 WRITE (754,'(4f14.7,3g16.7,2i6)')&
     878           0 :      &            pt_abs(1:2),pt_rel(1:2),&
     879           0 :      &            rhoOut, rhoOutIm, SQRT (rhoOut**2+rhoOutIm**2), ix, iy
     880             :               END DO ! iy
     881           0 :               WRITE (754,*)
     882             :             END DO ! ix
     883           0 :             CLOSE (754)
     884             :           END DO ! ivac
     885           0 :         END SUBROUTINE print_rhoEF
     886             :       END SUBROUTINE e_field
     887             : 
     888             :       SUBROUTINE read_namelist (iou, E, eV)
     889             :         USE m_types, only: t_efield
     890             :         INTEGER, INTENT(IN) :: iou
     891             :         TYPE(t_efield), INTENT(INOUT) :: E
     892             :         LOGICAL, INTENT(INOUT) :: eV
     893             : 
     894             :         REAL :: zsigma, sig_b(2)
     895             :         LOGICAL :: plot_charge
     896             :         LOGICAL :: plot_rho
     897             :         LOGICAL :: autocomp
     898             :         LOGICAL :: dirichlet
     899             :         NAMELIST /efield/ zsigma, sig_b, plot_charge, plot_rho,&
     900             :      &                    autocomp, dirichlet, eV
     901             : 
     902             :         zsigma = E%zsigma
     903             :         plot_charge = E%plot_charge
     904             :         plot_rho = E%plot_rho
     905             :         autocomp = E%autocomp
     906             :         dirichlet = E%dirichlet
     907             :         sig_b = E%sig_b
     908             : 
     909             :         READ (iou,nml=efield)
     910             : 
     911             :         E%zsigma = zsigma
     912             :         E%plot_charge = plot_charge
     913             :         E%plot_rho = plot_rho
     914             :         E%autocomp = autocomp
     915             :         E%dirichlet = dirichlet
     916             :         E%sig_b = sig_b
     917             :       END SUBROUTINE read_namelist
     918             : 
     919             : 
     920           0 :       ELEMENTAL FUNCTION lower_case(string)
     921             :         CHARACTER(len=*), INTENT(IN) :: string
     922             :         CHARACTER(len=len(string))   :: lower_case
     923             : 
     924             :         INTEGER :: i
     925             : 
     926           0 :         DO i = 1, LEN (string)
     927             :           IF (      IACHAR ('A') <= IACHAR (string(i:i)) &
     928           0 :               .and. IACHAR ('Z') >= IACHAR (string(i:i))) THEN
     929             :             lower_case(i:i) = ACHAR (IACHAR (string(i:i))&
     930           0 :                               + IACHAR ('a') - IACHAR ('A'))
     931             :           ELSE
     932           0 :             lower_case(i:i) = string(i:i)
     933             :           END IF
     934             :         END do
     935           0 :       END FUNCTION lower_case
     936             :     END MODULE m_efield

Generated by: LCOV version 1.14