wiki:MagnetoHydroDynamics

Version 2 (modified by Jonathan, 4 years ago) ( diff )

Units in Astrobear

Astrobear uses something like rationalized electromagnetic units (extra factor of in the electric and magnetic fields) - or Lorentz-Heaviside but scaling the field by and the charge density (and current ) by

Using the approach in the appendix of Jackson, we have

This allows us to write Maxwell's equations as

as well as

Lorentz Force Law
Coulomb's Law

Most of the time we don't care about , , or , however for the Hall MHD terms, we need to determine the electron charge in our system of units.

For our system of equations, the elementary charge is

MHD equations

Using the system of units described above, we can write the following simplified equations

Induction equation
Ampere's equation (without Maxwell's correction)
Lorentz Force Law
Poynting's theorem (electromagnetic energy)
Poynting vector

Equations for momentum, magnetic energy, and magnetic field

Subsituting Ampere's equation and the definition of the Poynting vector into the equations for momentum, magnetic energy, and the magnetic field, we arrive at

Ohm's Law

Not the momentum equation only involves the magnetic field and is the same regardless of the electric field . Note it is also already in a form involving a total divergence making it straightforward to implement in a conservative finite volume scheme. The energy and induction equation, however, will depend on our choice of .

The field can be calculated using a Generalized Ohm's law

Under under certain conditions, we can ignore various terms resulting in the following approximations

Resistive + Hall MHD
Resistive MHD
Ideal MHD

Ideal MHD

For ideal MHD we substitute

into the equations above and after some vector calculus (including a very messy vector quadruple product with a del operator), manage to write the energy term as a total divergence (and the field as a curl)

Resistive MHD

For resistive MHD, it will be convenient to define the resistive component of the electric field

Then our total electric field is given by

We then need to add this contribution to the induction equation and the energy equation where it enters both the Poynting flux and the work done on the the charge distribution .

However the work done on the charge distribution would need to also be added to the thermal energy cancelling any changes in the total energy due to the term. This leaves us with.

Note the resistive part of the induction equation

can be expanded as

Which hints to the diffusive nature of the resistive term. It also involves a second derivative so the time stepping criteria will be and an implicit solve might be worth considering.

Hall+Resistive MHD

As in resistive MHD, it will be convenient to define the Hall component of the electric field

Then our total electric field is given by

Again we need to add the additional electric field component to the energy equation (in both the Poynting Flux and the work on the charge distribution) as well as the induction equation. Also note in this case the electric field is perpendicular to the current - so it does no work on the charge distribution.

So as in the Resistive case, only the Poynting Flux term needs to be added to the energy equation.

MHD

To enable MHD:

  • In physics.data, set lMHD to T.

If the code is using constrained transport, then the logical flag MaintainAuxArrays will be .True.. In that case you will need to initialize the face averaged magnetic field values in the aux array in your module file. The following diagram displays the various aux variables and what positions they correspond to - as well as the positions of the EMF as well as the vector potential.

Here is an example for an initial magnetic field that is

dx = (/(merge(1d0,0d0,nDim >= i),i=1,3)/)*levels(Info%level)%dx

DO i=1, Info%mX(1)
  x = Info%xBounds(1,1)+(REAL(i)-.5d0)*dx(1)
  DO j=1, Info%mX(2)
    y = Info%xBounds(2,1)+(REAL(j)-.5d0)*dx(2)
    DO k=1, Info%mX(3)
      z = Info%xBounds(3,1)+(REAL(k)-.5d0)*dx(3)
      Info%q(i,j,k,iBx)=Bx(x,y,z)
      Info%q(i,j,k,iBy)=By(x,y,z)
      Info%q(i,j,k,iBz)=Bz(x,y,z)
    END DO
  END DO
END DO

IF (MaintainAuxArrays) THEN
  IF (nDim >= 1) THEN
    !Note the +1 in the i loop DO statement and the -1d0 in 
    !the x coordinate calculation instead of -.5d0
    DO i=1, Info%mX(1)+1
      x = Info%xBounds(1,1)+(REAL(i)-1d0)*dx(1)
      DO j=1, Info%mX(2)
        y = Info%xBounds(2,1)+(REAL(j)-.5d0)*dx(2)
        DO k=1, Info%mX(3)
          z = Info%xBounds(3,1)+(REAL(k)-.5d0)*dx(3)
          Info%aux(i,j,k,1)=Bx(x,y,z)
        END DO
      END DO
    END DO

    !Now we can update the cell centered value with the adjacent face average
    Info%q(1:Info%mX(1),1:Info%mX(2),1:Info%mX(3),iBx)=.5d0 * (&
      Info%aux(1:Info%mX(1),1:Info%mX(2),1:Info%mX(3),1) + &
      Info%aux(2:Info%mX(1)+1,1:Info%mX(2),1:Info%mX(3),1) )


    IF (nDim >= 2) THEN
      !Note the +1 in the j loop DO statement and the -1d0 in 
      !the y coordinate calculation instead of -.5d0
      DO i=1, Info%mX(1)
        x = Info%xBounds(1,1)+(REAL(i)-.5d0)*dx(1)
        DO j=1, Info%mX(2)+1
          y = Info%xBounds(2,1)+(REAL(j)-1d0)*dx(2)
          DO k=1, Info%mX(3)
            z = Info%xBounds(3,1)+(REAL(k)-.5d0)*dx(3)
            Info%aux(i,j,k,2)=By(x,y,z)
          END DO
        END DO
      END DO

      !Now we can update the cell centered value with the adjacent face average  
      Info%q(1:Info%mX(1),1:Info%mX(2),1:Info%mX(3),iBy)=.5d0 * (&
        Info%aux(1:Info%mX(1),1:Info%mX(2),1:Info%mX(3),2) + &
        Info%aux(1:Info%mX(1),2:Info%mX(2)+1,1:Info%mX(3),2) )

      IF (nDim >= 3) THEN
       !Note the +1 in the k loop DO statement and the -1d0 in 
       !the z coordinate calculation instead of -.5d0
       DO i=1, Info%mX(1)
         x = Info%xBounds(1,1)+(REAL(i)-.5d0)*dx(1)
         DO j=1, Info%mX(2)
           y = Info%xBounds(2,1)+(REAL(j)-.5d0)*dx(2)
           DO k=1, Info%mX(3)+1
             z = Info%xBounds(3,1)+(REAL(k)-1d0)*dx(3)
             Info%aux(i,j,k,3)=Bz(x,y,z)
           END DO
         END DO
       END DO

      !Now we can update the cell centered value with the adjacent face average
       Info%q(1:Info%mX(1),1:Info%mX(2),1:Info%mX(3),iBz)=.5d0 * (&
         Info%aux(1:Info%mX(1),1:Info%mX(2),1:Info%mX(3),3) + &
         Info%aux(1:Info%mX(1),1:Info%mX(2),2:Info%mX(3)+1,3) )
      END IF
    END IF
  END IF
END IF

Of course the above example works for any field - but does not impose the divergence free constraint. Presumably the functions Bx, By, and Bz would take care of that to the degree they are accurate face averages - but a better approach is to instead approximate the vector potential at cell edges and then discretely difference it to get the face average fields.

IF (nDim == 2) THEN
  !In 2D the only component of the vector potential that matters is Az
  ALLOCATE(A(1:Info%mX(1)+1,1:Info%mX(2)+1,1,1))
  DO i=1, Info%mX(1)+1
    x = Info%xBounds(1,1)+(REAL(i)-1d0)*dx(1)
    DO j=1, Info%mX(2)+1
      y = Info%xBounds(2,1)+(REAL(j)-1d0)*dx(2)
      A(i,j,1,1)=Az(x,y,z)
    END DO
  END DO

  !Then take the curl of A to get B
  FORALL(i=1:Info%mX(1)+1,j=1:Info%mX(2))
    Info%aux(i,j,1,1)=+(A(i,j+1,1,1)-A(i,j,1,1))/dx(2)
  END FORALL
  FORALL(i=1:Info%mX(1),j=1:Info%mX(2)+1)
    Info%aux(i,j,1,2)=-(A(i+1,j,1,1)-A(i,j,1,1))/dx(1)
  END FORALL

ELSEIF (nDim == 3) THEN
  !Now the vector potential is a 3 component vector
  ALLOCATE(A(1:Info%mX(1)+1,1:Info%mX(2)+1,1:Info%mX(3)+1,3))

  !We could do this with three separate loops to avoid calculating 
  !A(:,:,Info%mX(3)+1,3),A(:,Info%mX(2)+1,:,2), and A(Info%mX(1)+1,:,:,1)
  !Since these do not get used in taking the curl...

  DO i=1, Info%mX(1)+1
    x = Info%xBounds(1,1)+(REAL(i)-1d0)*dx(1)
    DO j=1, Info%mX(2)+1
      y = Info%xBounds(2,1)+(REAL(j)-1d0)*dx(2)
      DO k=1, Info%mX(3)+1
        z = Info%xBounds(3,1)+(REAL(k)-1d0)*dx(3)
        A(i,j,k,1)=Ax(x+half*dx(1),y,z)
        A(i,j,k,2)=Ay(x,y+half*dx(2),z)
        A(i,j,k,3)=Az(x,y,z+half*dx(3))
      END DO
    END DO
  END DO

  !Then take the curl of A to get B
  FORALL(i=1:Info%mX(1)+1,j=1:Info%mX(2),k=1:Info%mX(3))
    Info%aux(i,j,k,1)=+(A(i,j+1,k,3)-A(i,j,k,3))/dx(2)-(A(i,j,k+1,2)-A(i,j,k,2))/dx(3)
  END FORALL
  FORALL(i=1:Info%mX(1),j=1:Info%mX(2)+1,k=1:Info%mX(3))
    Info%aux(i,j,k,2)=+(A(i,j,k+1,1)-A(i,j,k,1))/dx(3)-(A(i+1,j,k,3)-A(i,j,k,3))/dx(1)
  END FORALL
  FORALL(i=1:Info%mX(1),j=1:Info%mX(2),k=1:Info%mX(3)+1)
    Info%aux(i,j,k,3)=+(A(i+1,j,k,2)-A(i,j,k,2))/dx(1)-(A(i,j+1,k,1)-A(i,j,k,1))/dx(2)
  END FORALL
END IF

Note: See TracWiki for help on using the wiki.