Version 2 (modified by 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 ) byUsing 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
, setlMHD
toT
.
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