The Open FUSION Toolkit 1.0.0-8905cc5
Modeling tools for plasma and fusion research and engineering
Loading...
Searching...
No Matches
MUG Example: Spheromak Tilt

This example demonstrates the use of MUG to model the ideal tilt instability in a spheromak confined in a "tall" cylindrical flux conserver. Such a system is unstable to this instability when the ratio of the cylinder's height to radius is greater than 1.3. This result was shown first by Bondeson and Marklin, where the instablity acts to dissipate energy and drive the magnetic configuration toward the Taylor state (see Computing Initial Conditions).

Code Walk Through

The code consists of three basic sections, required imports and variable definitions, finite element setup, and system creation and solution.

Module Includes

The first thing that we must do is include the OFT modules which contain the required functions and variables. It is good practice to restrict the included elements to only those needed. This is done using the ONLY: clause to specifically include only certain definitions. The exceptions to this practice are the oft_local and oft_base modules, which contain a controlled set of commonly used elements that can be safely imported as a whole.

PROGRAM mug_sph_tilt
!---Runtime
!---Grid
!---Linear algebra
!---Lagrange FE space
!---H1 FE space (Grad(H^1) subspace)
!---Full H(Curl) FE space
!---Physics
IMPLICIT NONE
Multigrid initialization using nested meshes.
Definition multigrid_build.F90:14
subroutine multigrid_add_quad(mg_mesh)
Add node points for quadratic elements.
Definition multigrid_build.F90:164
subroutine multigrid_construct(mg_mesh, grnd_pt)
Construct multi-level mesh.
Definition multigrid_build.F90:440
Multi-Level grid implementation using nested meshes.
Definition multigrid.F90:14
Base environment functions and aliases for Open FUSION Toolkit.
Definition oft_base.F90:23
Base scalar H^1 FE class and basis evaluation.
Definition h1_basis.F90:22
subroutine oft_h1_setup(mg_mesh, order, ml_h1_obj, ml_bh1_obj, minlev)
Construct H^1 scalar FE on each mesh level.
Definition h1_basis.F90:99
H^1 FE operator definitions.
Definition h1_operators.F90:22
subroutine oft_h1_getlop(fe_rep, mat, bc)
Construct laplacian matrix for H^1 scalar representation.
Definition h1_operators.F90:389
Base H(Curl) FE class and basis evaluation.
Definition hcurl_basis.F90:22
subroutine oft_hcurl_grad_setup(ml_hcurl_obj, ml_h1_obj, ml_hcurl_grad_obj, ml_h1grad_obj, minlev)
Construct a vector FE space for H(Curl) and it's compliment ( )
Definition hcurl_basis.F90:176
subroutine oft_hcurl_setup(mg_mesh, order, ml_hcurl_obj, ml_bhcurl_obj, minlev)
Construct H(Curl) FE basis on each mesh level.
Definition hcurl_basis.F90:104
FE operators for full H(Curl) + Grad(H^1) space.
Definition hcurl_grad_operators.F90:27
subroutine hcurl_grad_mc(mesh, a, hcpc, hcpv, new_tol)
Compute the 0-th order gradient due to a jump plane.
Definition hcurl_grad_operators.F90:600
Abstract vector and matrix interfaces.
Definition lin_alg_base.F90:20
Base Lagrange FE class and basis evaluation.
Definition lagrange_basis.F90:22
subroutine oft_lag_setup(mg_mesh, order, ml_lag_obj, ml_blag_obj, ml_vlag_obj, minlev)
Construct lagrange scalar FE on each mesh level.
Definition lagrange_basis.F90:317
Abstract solver interfaces and select native implementations.
Definition solver_base.F90:32
Matrix and vector management routines.
Definition solver_utils.F90:14
subroutine create_ilu_pre(pre)
Create ILU(0) preconditioner (native or MKL)
Definition solver_utils.F90:633
subroutine create_diag_pre(pre)
Needs docs.
Definition solver_utils.F90:619
subroutine create_bjacobi_pre(pre, nlocal)
Needs docs.
Definition solver_utils.F90:647
subroutine create_cg_solver(solver, force_native)
Needs docs.
Definition solver_utils.F90:437
Subroutines and fields for Taylor state calculations using mimetic operators.
Definition taylor.F90:21
subroutine taylor_hmodes(self, nm, rst_filename)
Compute 'taylor_nm' Force-Free eignemodes.
Definition taylor.F90:295
Module for modeling extended MHD with a mixed conforming/lagrange basis set.
Definition xmhd.F90:73
subroutine, public xmhd_lin_run(equil_fields, pert_fields, escale)
Main driver subroutine for extended MHD time advance.
Definition xmhd.F90:1101
type(oft_ml_fem_comp_type), pointer, public xmhd_ml_hcurl_grad
Definition xmhd.F90:395
subroutine, public xmhd_run(initial_fields, driver, probes, profile_only)
Main driver subroutine for extended MHD time advance.
Definition xmhd.F90:554
type(oft_ml_fem_type), pointer, public xmhd_ml_lagrange
Definition xmhd.F90:391
type(oft_ml_fem_comp_type), pointer, public xmhd_ml_vlagrange
Definition xmhd.F90:396
type(oft_ml_fem_type), pointer, public xmhd_ml_h1
Definition xmhd.F90:392
integer(i4), public xmhd_taxis
Axis for toroidal flux and current.
Definition xmhd.F90:354
subroutine, public xmhd_plot(probes)
Plotting subroutine for xMHD post-processing.
Definition xmhd.F90:4562
type(oft_ml_fem_type), pointer, public xmhd_ml_hcurl
Definition xmhd.F90:394
type(oft_ml_fem_type), pointer, public xmhd_ml_h1grad
Definition xmhd.F90:393
Multigrid meshes and ML context structure.
Definition multigrid.F90:44
Needs docs.
Definition h1_operators.F90:76
Clean the divergence from a H(Curl) + Grad(H^1) vector field.
Definition hcurl_grad_operators.F90:103
Abstract matrix class.
Definition lin_alg_base.F90:566
Abstract vector class.
Definition lin_alg_base.F90:69
Base class for OFT solvers.
Definition solver_base.F90:99
Force-free, uniform eigenmode object.
Definition taylor.F90:75
Object for sub-fields used by oft_xmhd_push and oft_xmhd_pop.
Definition xmhd.F90:245

Local Variables

Next we define the local variables needed to initialize our case and run the time-dependent solve and post-processing.

!---H(Curl) divergence cleaner
CLASS(oft_solver), POINTER :: linv => null()
TYPE(oft_hcurl_grad_divout) :: divout
CLASS(oft_matrix), pointer :: lop => null()
!---Local variables
INTEGER(i4) :: ierr,io_unit
REAL(r8), POINTER, DIMENSION(:) :: tmp => null()
TYPE(xmhd_sub_fields) :: ic_fields,pert_fields
TYPE(multigrid_mesh) :: mg_mesh
TYPE(oft_taylor_hmodes) :: taylor_states
TYPE(oft_h1_zerogrnd), TARGET :: h1_zerogrnd
!---Runtime options
INTEGER(i4) :: order = 2
REAL(r8) :: b0_scale = 1.e-1_r8
REAL(r8) :: b1_scale = 1.e-5_r8
REAL(r8) :: n0 = 1.d19
REAL(r8) :: t0 = 6.d0
LOGICAL :: pm=.false.
LOGICAL :: linear=.false.
LOGICAL :: plot_run=.false.
NAMELIST/sph_tilt_options/order,b0_scale,b1_scale,plot_run,linear,pm,n0,t0

OFT Initialization

See API Example 1: Helmholtz solve for a detailed description of calls in this section.

!---Read in options
OPEN(newunit=io_unit,file=oft_env%ifile)
READ(io_unit,sph_tilt_options,iostat=ierr)
CLOSE(io_unit)
!------------------------------------------------------------------------------
! Setup grid
!------------------------------------------------------------------------------
CALL multigrid_construct(mg_mesh,[2.d0,0.d0,0.d0])
!------------------------------------------------------------------------------
! Build FE structures
!------------------------------------------------------------------------------
!--- Lagrange
CALL oft_lag_setup(mg_mesh,order,xmhd_ml_lagrange,ml_vlag_obj=xmhd_ml_vlagrange,minlev=-1)
!--- Grad(H^1) subspace
CALL oft_h1_setup(mg_mesh,order+1,xmhd_ml_h1,minlev=-1)
!--- H(Curl) subspace
CALL oft_hcurl_setup(mg_mesh,order,xmhd_ml_hcurl,minlev=-1)
!--- Full H(Curl) space
h1_zerogrnd%ML_H1_rep=>xmhd_ml_h1grad
type(oft_env_type) oft_env
Global container for environment information.
Definition oft_base.F90:145
subroutine oft_init(nthreads)
Initializes Open FUSION Toolkit run environment.
Definition oft_base.F90:193

Perform post-processing

To visualize the solution fields once a simulation has completed, the xmhd_plot subroutine is used. This subroutine steps through the restart files produced by xmhd_run or xmhd_lin_run and generates plot files, and optionally probe signals at evenly spaced points in time as specified in the input file, see xmhd_plot and Post-Processing options.

IF(plot_run)THEN
!---Run post-processing routine
CALL xmhd_plot
!---Finalize enviroment and exit
CALL oft_finalize()
END IF
subroutine oft_finalize()
Finalize Open FUSION Toolkit environment.
Definition oft_base.F90:356

Computing Initial Conditions

The spheromak mode corresponds to the thrid lowest force-free eignstate of the flux conserver. This can be computed using the taylor_hmodes subroutine and with the desired number of modes set to three. The fact that this mode is the third eigenstate is indicative of the ideal instability we wish to simulate with this example as there are two magentic configurations (actually a sin/cosine-like pair) that contain less energy for a given helicity. As a result, we would expect an instability to exist that will drive the configuration toward one of these minimum energy states. This also leads us to our choice of an intial perturbation to the equilibrium, which we will chose to match field of the lowest eigenstate.

CALL taylor_states%setup(xmhd_ml_hcurl,xmhd_ml_lagrange)
CALL taylor_hmodes(taylor_states,3)
CALL xmhd_ml_lagrange%set_level(xmhd_ml_lagrange%nlevels)

The taylor_hmodes subroutine computes the vector potential for each of the requested eignestates. However, the MHD solver uses magnetic field as the primary variable. With force-free eigenstate solutions the vector potential and magentic field can be related by a gauge transformation. Here this fact is used to produce an appropriate initial condition from the vector potential without changing the representation order or projecting the field.

The gauge is transformed using a divergence cleaning procedure to remove divergence from the vector potential by adding a gradient. The taylor_hmodes already sets the gauge such that \( \nabla \cdot \textbf{A} = 0 \), however it does so while enforcing \( \textbf{A} \times \hat{\textbf{n}} = 0 \). We now recompute the desired gauge fixing with the boundary condition \( \textbf{A} \cdot \hat{\textbf{n}} = 0 \), which provides a suitable initialization magnetic field. This process is performed on both the equilibrium and perturbing fields.

!------------------------------------------------------------------------------
! Create divergence cleaner
!------------------------------------------------------------------------------
NULLIFY(lop)
CALL oft_h1_getlop(xmhd_ml_h1%current_level,lop,"grnd")
CALL create_cg_solver(linv)
linv%A=>lop
linv%its=-2
CALL create_bjacobi_pre(linv%pre,-1)
DEALLOCATE(linv%pre%pre)
CALL create_ilu_pre(linv%pre%pre)
divout%solver=>linv
divout%bc=>h1_zerogrnd
divout%pm=.true.
!------------------------------------------------------------------------------
! Setup initial conditions
!------------------------------------------------------------------------------
!---Apply to equilibrium field
CALL xmhd_ml_hcurl_grad%vec_create(ic_fields%B)
CALL taylor_states%hffa(3,xmhd_ml_hcurl%level)%f%get_local(tmp)
CALL ic_fields%B%restore_local(tmp,1)
CALL divout%apply(ic_fields%B)
!---Apply to perturbation field
CALL xmhd_ml_hcurl_grad%vec_create(pert_fields%B)
CALL taylor_states%hffa(1,xmhd_ml_hcurl%level)%f%get_local(tmp)
CALL pert_fields%B%restore_local(tmp,1)
CALL divout%apply(pert_fields%B)
!---Clean up solver
NULLIFY(divout%solver)
CALL divout%delete()
CALL linv%pre%pre%delete()
DEALLOCATE(linv%pre%pre)
CALL linv%pre%delete()
DEALLOCATE(linv%pre)
CALL linv%delete()
DEALLOCATE(linv)

With the required fields computed the full initial conditions can now be set. For the linear case we set the magnetic equilibrium (3rd eigenmode) and the perturbation field (1st eigenmode). For the nonlinear case these fields are combined to yield the combined initial condition. In both cases, the velocity field, temperature, and density fields are also created. The velocity field is initialized to zero everywhere, while the temperature and density fields, which are not evolved in this case, are set to uniform values for the equilibrium and zero for the perturbation.

CALL ic_fields%B%scale(b0_scale*taylor_states%hlam(3,xmhd_ml_hcurl%level))
CALL pert_fields%B%scale(b1_scale*taylor_states%hlam(1,xmhd_ml_hcurl%level))
IF(.NOT.linear)THEN
CALL ic_fields%B%add(1.d0,1.d0,pert_fields%B)
CALL pert_fields%B%delete
DEALLOCATE(pert_fields%B)
END IF
!---Create velocity field
CALL xmhd_ml_vlagrange%vec_create(ic_fields%V)
IF(linear)CALL xmhd_ml_vlagrange%vec_create(pert_fields%V)
!---Create static density/temperature
CALL xmhd_ml_lagrange%vec_create(ic_fields%Ne)
CALL xmhd_ml_lagrange%vec_create(ic_fields%Ti)
CALL ic_fields%Ne%set(n0)
CALL ic_fields%Ti%set(t0)
IF(linear)THEN
CALL xmhd_ml_lagrange%vec_create(pert_fields%Ne)
CALL xmhd_ml_lagrange%vec_create(pert_fields%Ti)
END IF
!---Clean up temporary matrices and fields
CALL lop%delete
DEALLOCATE(tmp,lop)

Run Simulation

Finally, the simulation can be run using either the driver routine for linear (xmhd_lin_run) or non-linear MHD (xmhd_run). These routines both advance the solution in time with the physics specified in the input file, see the documentation for xmhd_lin_run and xmhd_run, and produces restart files that contain the solution at different times.

Several quantities are also recorded to a history file xmhd.hist during the simulation, including the toroidal current (where the symmetry axis is specified by xmhd_taxis). The data in the history file may be plotted using the script plot_mug_hist.py, which is located in src/utilities/scripts or python directories for the repository and an installation respectively.

Note
OFT plotting scripts require the python packages numpy and matplotlib as well as path access to the python modules provided in python for installations or src/utilities in the repo.
xmhd_taxis=3
oft_env%pm=pm
!---Run simulation
IF(linear)THEN
CALL xmhd_lin_run(ic_fields,pert_fields)
ELSE
CALL xmhd_run(ic_fields)
END IF
!---Finalize enviroment and exit
END PROGRAM MUG_sph_tilt
void oft_finalize()

Input file

Below is an input file which can be used with this example in a parallel environment. This example should not be run with only a single process as solving the time-depedent MHD equations is significantly more challenging than previous examples. For more information on the options in the xmhd_options group see xmhd_run.

&runtime_options
 ppn=1
 debug=0
/

&mesh_options
 meshname='test'
 cad_type=0
 nlevels=2
 nbase=1
 grid_order=2
 fix_boundary=T
/

&native_mesh_options
 filename='cyl_tilt.h5'
/

&sph_tilt_options
 order=2
 linear=F
 b0_scale=1.e-1
 b1_scale=1.e-4
 n0=1.E19
 t0=3.
 plot_run=F
 pm=F
/

&xmhd_options
 xmhd_adv_den=F    ! Do not advance density
 xmhd_adv_temp=F   ! Do not advance temperature
 bbc='bc'          ! Perfectly-conducting BC for B-field
 vbc='all'         ! Zero-flow BC for velocity
 dt=2.e-7          ! Maximum time step
 eta=1.            ! Resistivity
 nu_par=10.        ! Fluid viscosity
 nsteps=3000       ! Number of time steps to take
 rst_freq=10       ! Restart file frequency
 lin_tol=1.E-10    ! Linear solver tolerance
 nl_tol=1.E-5      ! Non-linear solver tolerance
 xmhd_mfnk=T       ! Use matrix-free Jacobian operator
 rst_ind=0         ! Index of file to restart from (0 -> use subroutine arguments)
 ittarget=40       ! Target for # of linear iterations per time step
 mu_ion=2.         ! Ion mass (atomic units)
 xmhd_prefreq=20   ! Preconditioner update frequency
/

Solver specification

Time dependent MHD solvers are accelerated significantly by the use of a more sophisticated preconditioner than the default method. Below is an example oft_in.xml file that constructs an appropriate ILU(0) preconditioner. Currently, this preconditioner method is the suggested starting preconditioner for all time-dependent MHD solves.

<oft>
<xmhd>
<pre type="gmres">
<its>8</its>
<nrits>8</nrits>
<pre type="block_jacobi">
<nlocal>-1</nlocal>
<solver type="ilu"></solver>
</pre>
</pre>
</xmhd>
</oft>

This solver can be used by specifying both the FORTRAN input and XML input files to the executable as below.

~$ ./MUG_sph_tilt oft.in oft_in.xml

Post-Processing options

During the simulation the evolution of some global quantities is written to the history file xmhd.hist. A utility script (plot_mug_hist.py located in bin after installation) is included as part of OFT for plotting the signals in this file. This is useful for monitoring general progress of the simulation as well as numerical parameters like the iteration count and solver time. Using this script we can see the instability growth and relaxation of the initial magnetic equilibrium to the lowest energy state.

~$ python plot_mug_hist.py xmhd.hist
Time evolution of kinetic energy throughout simulation, showing initial linear growth of instability.
Time evolution of toroidal current. The rapid drop is current corresponds to the transition from a toroidally symmetric to a helical structure with zero net current.

Creating plot files

To generate 3D plots, and perform additional diagnostic sampling (see oft_xmhd_probe), a plot run can be performed by setting plot_run=T in the sph_tilt_options input group, which calls xmhd_plot. With this option additional run time options are available in the xmhd_plot_options group that control how restart files are sampled for plotting.

&xmhd_plot_options
 t0=1.E-8
 dt=1.E-5
 rst_start=0
 rst_end=3000
/

Once the post-processing run is complete bin/build_xdmf.py can be used to generate *.xmf files that can be loaded by VisIt, ParaView, or other visualization programs.

Magnetic field distribution of the initial (left) and final (right) states

Mesh Creation

A mesh file cyl_tilt.h5 is provided with this example. Instructions to generate your own mesh for the geometry using CUBIT and GMSH.

Meshing with CUBIT

A suitable mesh for this example, with radius of 1m and height of 2m, can be created using the CUBIT script below.

reset

create Cylinder height 2 radius 1

volume 1 scheme Tetmesh
set tetmesher interior points on
set tetmesher optimize level 3 optimize overconstrained  off sliver  off
set tetmesher boundary recovery  off
volume 1 size .2
mesh volume 1

set duplicate block elements off
block 1 add volume 1 
block 1 element type tetra10

set large exodus file on
export Genesis  "cyl_tilt.g" overwrite block 1

Once complete the mesh should be converted into the native mesh format using the convert_cubit.py script as below. The script is located in bin following installation or src/utilities in the base repo.

~$ python convert_cubit.py --in_file=cyl_tilt.g

Meshing with Gmsh

If the CUBIT mesh generation codes is not avilable the mesh can be created using the Gmsh code and the geometry script below.

Coherence;
Point(1) = {0, 0, 0, 1.0};
Point(2) = {1, 0, 0, 1.0};
Point(3) = {0, 1, 0, 1.0};
Point(4) = {-1, 0, 0, 1.0};
Point(5) = {0, -1, 0, 1.0};
Circle(1) = {2, 1, 3};
Circle(2) = {3, 1, 4};
Circle(3) = {4, 1, 5};
Circle(4) = {5, 1, 2};
Line Loop(5) = {2, 3, 4, 1};
Plane Surface(6) = {5};
Extrude {0, 0, 2} {
  Surface{6};
}

To generate a mesh, with resolution matching the Cubit example above, place the script contents in a file called cyl_tilt.geo and run the following command.

~$ gmsh -3 -format mesh -optimize -clscale .2 -order 2 -o cyl_tilt.mesh cyl_tilt.geo

Once complete the mesh should be converted into the native mesh format using the convert_gmsh.py script as below. The script is located in bin following installation or src/utilities in the base repo.

~$ python convert_gmsh.py --in_file=cyl_tilt.mesh

Complete Source

PROGRAM mug_sph_tilt
!---Runtime
!---Grid
!---Linear algebra
!---Lagrange FE space
!---H1 FE space (Grad(H^1) subspace)
!---Full H(Curl) FE space
!---Physics
IMPLICIT NONE
!------------------------------------------------------------------------------
! Local Variables
!------------------------------------------------------------------------------
!---H(Curl) divergence cleaner
CLASS(oft_solver), POINTER :: linv => null()
TYPE(oft_hcurl_grad_divout) :: divout
CLASS(oft_matrix), pointer :: lop => null()
!---Local variables
INTEGER(i4) :: ierr,io_unit
REAL(r8), POINTER, DIMENSION(:) :: tmp => null()
TYPE(xmhd_sub_fields) :: ic_fields,pert_fields
TYPE(multigrid_mesh) :: mg_mesh
TYPE(oft_taylor_hmodes) :: taylor_states
TYPE(oft_h1_zerogrnd), TARGET :: h1_zerogrnd
!---Runtime options
INTEGER(i4) :: order = 2
REAL(r8) :: b0_scale = 1.e-1_r8
REAL(r8) :: b1_scale = 1.e-5_r8
REAL(r8) :: n0 = 1.d19
REAL(r8) :: t0 = 6.d0
LOGICAL :: pm=.false.
LOGICAL :: linear=.false.
LOGICAL :: plot_run=.false.
NAMELIST/sph_tilt_options/order,b0_scale,b1_scale,plot_run,linear,pm,n0,t0
!------------------------------------------------------------------------------
! OFT Initialization
!------------------------------------------------------------------------------
!---Read in options
OPEN(newunit=io_unit,file=oft_env%ifile)
READ(io_unit,sph_tilt_options,iostat=ierr)
CLOSE(io_unit)
!------------------------------------------------------------------------------
! Setup grid
!------------------------------------------------------------------------------
CALL multigrid_construct(mg_mesh,[2.d0,0.d0,0.d0])
!------------------------------------------------------------------------------
! Build FE structures
!------------------------------------------------------------------------------
!--- Lagrange
CALL oft_lag_setup(mg_mesh,order,xmhd_ml_lagrange,ml_vlag_obj=xmhd_ml_vlagrange,minlev=-1)
!--- Grad(H^1) subspace
CALL oft_h1_setup(mg_mesh,order+1,xmhd_ml_h1,minlev=-1)
!--- H(Curl) subspace
CALL oft_hcurl_setup(mg_mesh,order,xmhd_ml_hcurl,minlev=-1)
!--- Full H(Curl) space
h1_zerogrnd%ML_H1_rep=>xmhd_ml_h1grad
!------------------------------------------------------------------------------
! Perform post-processing
!------------------------------------------------------------------------------
IF(plot_run)THEN
!---Run post-processing routine
CALL xmhd_plot
!---Finalize enviroment and exit
CALL oft_finalize()
END IF
!------------------------------------------------------------------------------
! Computing Initial Conditions
!------------------------------------------------------------------------------
CALL taylor_states%setup(xmhd_ml_hcurl,xmhd_ml_lagrange)
CALL taylor_hmodes(taylor_states,3)
CALL xmhd_ml_lagrange%set_level(xmhd_ml_lagrange%nlevels)
!------------------------------------------------------------------------------
! Create divergence cleaner
!------------------------------------------------------------------------------
NULLIFY(lop)
CALL oft_h1_getlop(xmhd_ml_h1%current_level,lop,"grnd")
CALL create_cg_solver(linv)
linv%A=>lop
linv%its=-2
CALL create_bjacobi_pre(linv%pre,-1)
DEALLOCATE(linv%pre%pre)
CALL create_ilu_pre(linv%pre%pre)
divout%solver=>linv
divout%bc=>h1_zerogrnd
divout%pm=.true.
!------------------------------------------------------------------------------
! Setup initial conditions
!------------------------------------------------------------------------------
!---Apply to equilibrium field
CALL xmhd_ml_hcurl_grad%vec_create(ic_fields%B)
CALL taylor_states%hffa(3,xmhd_ml_hcurl%level)%f%get_local(tmp)
CALL ic_fields%B%restore_local(tmp,1)
CALL divout%apply(ic_fields%B)
!---Apply to perturbation field
CALL xmhd_ml_hcurl_grad%vec_create(pert_fields%B)
CALL taylor_states%hffa(1,xmhd_ml_hcurl%level)%f%get_local(tmp)
CALL pert_fields%B%restore_local(tmp,1)
CALL divout%apply(pert_fields%B)
!---Clean up solver
NULLIFY(divout%solver)
CALL divout%delete()
CALL linv%pre%pre%delete()
DEALLOCATE(linv%pre%pre)
CALL linv%pre%delete()
DEALLOCATE(linv%pre)
CALL linv%delete()
DEALLOCATE(linv)
CALL ic_fields%B%scale(b0_scale*taylor_states%hlam(3,xmhd_ml_hcurl%level))
CALL pert_fields%B%scale(b1_scale*taylor_states%hlam(1,xmhd_ml_hcurl%level))
IF(.NOT.linear)THEN
CALL ic_fields%B%add(1.d0,1.d0,pert_fields%B)
CALL pert_fields%B%delete
DEALLOCATE(pert_fields%B)
END IF
!---Create velocity field
CALL xmhd_ml_vlagrange%vec_create(ic_fields%V)
IF(linear)CALL xmhd_ml_vlagrange%vec_create(pert_fields%V)
!---Create static density/temperature
CALL xmhd_ml_lagrange%vec_create(ic_fields%Ne)
CALL xmhd_ml_lagrange%vec_create(ic_fields%Ti)
CALL ic_fields%Ne%set(n0)
CALL ic_fields%Ti%set(t0)
IF(linear)THEN
CALL xmhd_ml_lagrange%vec_create(pert_fields%Ne)
CALL xmhd_ml_lagrange%vec_create(pert_fields%Ti)
END IF
!---Clean up temporary matrices and fields
CALL lop%delete
DEALLOCATE(tmp,lop)
!------------------------------------------------------------------------------
! Run Simulation
!------------------------------------------------------------------------------
oft_env%pm=pm
!---Run simulation
IF(linear)THEN
CALL xmhd_lin_run(ic_fields,pert_fields)
ELSE
CALL xmhd_run(ic_fields)
END IF
!---Finalize enviroment and exit
END PROGRAM MUG_sph_tilt