OPTIMIZATION_FFF

See the web page http://sprg.ssl.berkeley.edu/~jimm/fff/optimization_fff.html

Optimization_fff: A Non-Linear Force-Free-Field Extrapolation Program

The IDL program optimization_fff performs a non-linear
force-free-field extrapolation of the solar magnetic field using the
optimization method of Wheatland, Roumelotis and Sturrock (2000, Apj,
540,1150). The method works by minimizing an objective function, L,
which is the integral of |JxB|^2+|div B|^2 over a volume. If the
integral over the given volume is zero, then both JxB and div B must
be zero throughout the entire volume. (For a more detailed
explanation, read the paper).

Calling Sequence:

Optimization_fff, bx_in, by_in, bz_in, $
                  filename = filename, $
                  x_in = x_in, y_in = y_in, z_in = z_in, $
                  Restart_flag = restart_flag, $ 
                  Bc_flag = bc_flag, $
                  potlin = potlin, iterations = iterations, $
                  Dt = dt, nsave = nsave, double = double, $
                  convergence_level = convergence_level, $
                  pr_iter = pr_iter, $
                  alpha_in = alpha_in, $
                  slow_way = slow_way, $
                  spherical = spherical, $
                  dont_kill_input = dont_kill_input,$
                  use_fortran = use_fortran, $
                  fortran_exe = fortran_exe, $
                  use_sdf = use_sdf,$
                  wfile=wfile, weight_in=weight_in, wtype=wtype
		  
Input:

bx_in, by_in, bz_in = the input x, y, and z (or r, theta and phi)
components of the magnetic field. Each array can be two or three
dimensions; two dimensional input arrays are considered to be the
fields at z=0, the surface of the sun. Three dimensional input fields
define the full extrapolation volume.

Keyword Input:

filename = The name of a file that contains the input magnetic
field. For this option, then input B arrays must be 3D. The file
should be an ascii file, with format:

xsize ysize zsize
bx
by
bz

where xsize, ysize, and zsize are the grid sizes of the x, y, and z
directions, bx, by, and bz are the 3 components of the field. This
option is useful for restarting calculations.

x_in, y_in, z_in = input spatial grids.  If the input B's are 3D, then
the number of elements in each input grid must match the appropriate
size in the B array:e.g., If you input 128x64x32 B fields, then x_in
must be 128 elements, y_in must be 64 elements, and z_in must be 32
elements. If you pass in 2D arrays for B, then only x_in and y_in must
match. The default for grid creation is to use uniform size grids in
all 3 directions, with the largest transverse grid (x or y) evenly
divided between -1.0 and 1.0, and equal grid spacing for all three
directions: E.g., in the 128x64x32 example, the x grid will stretch
from -1 to 1 in 128 steps, the y grid will be from -0.5 to 0.5 in 64
steps and the z grid will be from 0 to 0.5 in 32 steps. The default is
to use uniformly spaced grids, but the user may pass in any grids.

If the input is 2D, then the z grid is chosen to be the same size as
the minimum transverse grid, e.g., for 128x64 input, the 3D fields
will be 128x64x64, with the xgrid from -1.0 to 1.0 in 128 steps, the y
grid from -0.5 to 0.5 in 64 steps, and the z grid from 0 to 1 in 64
steps. Note that the code has been changed from the original version
in order for this to be true, Updated on 28-Nov-2005.

restart_flag = if set, then the program will read in the B field from
a file (You must use the filename option), and use this field as the
starting point.

bc_flag = if set, then the B field on all boundaries is set to the
boundary value for the input field. (This means that the input field
must be 3D.) The boundary field remains unchanged for the entire
calculation. If not set (or set to zero), then only the bottom
boundary is used for the calculation, and the field on the upper and
side boundaries is given by the initial potential or linear force-free
approximation. Note that the boundary field remains unchanged for the
entire calculation for this case too.  The default is 0, lower BC's
only.

potlin = If 0 or unset, then the initial field is a potential
extrapolation (from Tom Metcalfs FFF.pro).  If set to 1 then the
initial field is set to a linear FFF extrapolation. If set to 2 to the
the field is linear FFF near the origin, but varies gradually to be
potential on the outer boundaries. The Default is 0
 
iterations = The maximum number of iterations allowed. The default is
10000.

dt = The initial step size in t. The default is 1.0e-5. The value of
dt will increase by 1% for each successful iteration, for unsuccessful
iterations, dt is cut in half.

nsave = all of the output is save every nsave iterations, the default
is 500.

double  = if set, use double precision

convergence_level = If the fractional difference objective function L
is less than this then the program stops.

pr_iter = Every pr_iter iterations,an entry to the 'lhist.dat' file is
made.  The columns in this file are (1) the iteration, (2) the value
of dt, (3) the current value of L, the objective function.

alpha_in = An initial value of alpha for use in the initial linear FFF
approximation, only used for potlin = 1. The default is to use the
average value of alpha calculated on the lower boundary.

slow_way = If set, then use the program calc_lin_fff to do the initial
field (potential or linear FFF) instead of fff.pro. Calc_lin_fff uses
a Green's function calculation (Chiu & Hilton, 1977) to get the
initial field, while fff.pro uses a Fourier method. This is very slow,
especially for large arrays.

dont_kill_input = If set, don't overwrite the input arrays for the
case where the input is 3D. (2D input is not overwritten.)

spherical = If set, then use spherical coordinates, with x, y, z
becoming r, theta, phi. For this case, the input field must be 3D, and
the initial conditions must be present, (bc_flag = 1 and restart_flag
= 1, must be set). There is currently no method for initializing the
field in spherical coordinates. We're working on it...

Added Feb-2008

use_fortran = if set, this will do the iterations useing the new
fortran program

fortran_exe = the name of the fortran routine used, the default is
'optimization_fff.exe'. Full path, please.

use_sdf = if set, all data i/o is dealt with using SDF ('simple data
format') files. This includes the stuff that is passed to the FORTRAN
program. These files will have .sdf as a suffix. Note that the output
"lhist" files are ASCII files. To get the Software needed for use of
the SDF format, go to:
http://solarmuri.ssl.berkeley.edu/~fisher/public/software/SDF/

For weighting function options:
weight_in = an input function, for weighting the objective function,
must be (rsize, tsize, vsize), i.e., the same dimensions of the 3d B
field.

wfile = an input file, from which you can read in a weight function
         File needs a format,
         printf, unit, rsize, tsize, vsize
         printf, unit, wf

The use_sdf functionality of this has not been tested, but those
variable names are needed, rsize is the number of x (or r) grid
points, tsize is the number of y (or theta) grid points, vsize is the
number of z (or phi) grid points, and wf is the function name.

wtype = a number for a given functional type that will be created:
         1: Function varies as  cos((!pi/2)*(z/max(z)) Or r for spherical
         2: Function varies as cos((!pi/2)*(dist/max(dist))) Where dist
         is sqrt(x^2+y^2+z^2), not used for spherical -- if spherical
         is set then you get the same as wtype=1
         3: Function varies as the inverse of dz for variable grids
            (or dr for spherical)
         4: Function varies as the inverse of dV, from the origin 


Output: 

There are no output parameters in the argument list. Instead, the
magnetic field is output into a file named "field.dat". This file can
be read using the program read_bfield_fff.pro, which is included in
the software.

Read_bfield_fff, 'field.dat', xsize, ysize, zsize, bx, by, bz, x, y, z 


returns the grid sizes, xsize, ysize, zsize, the field vectors bx, by,
bz, and the spatial grids x, y, z.

The file, "lhist.dat", contains the iteration history of the
extrapolation, The columns in this file are (1) the iteration, (2) the
value of dt, (3) the value of L, the objective function. 

Other files are also created. The file "pfield.dat" contains the
initial potential or linear force-free field. This does not include
the lower boundary or other boundaries (for the bc_flag = 1 case). It
can be read in the same way as "field.dat". Another file, "field0.dat"
is created that contains the initial potential or linear FF field, but
has the lower and other boundaries (for bc_flag=1) set to those that
will be used in the calculation. This file is used to initialize the
FORTRAN program.

If the /use_fortran keyword is set, then a file "fff_input_pars.dat" is
created, for input to the FORTRAN program. This file contains:
<pre>
dt                 ;the initial value of dt
convergence_level  ;the convergence_level
iterations         ;the max number of iterations
qsphere            ;1 for spherical coordinates, 0 for cartesian
slow               ; set to 0 this is not used!!!
alpha              ;the value of alpha for the init field (usually 0.0)
sdfu               ;1 if using sdf, 0 if not
</pre>

If a weighting function is used, and the /use_fortran keyword is set,
then a file weight0.dat is created to pass to the FORTRAN routine.

If the /use_sdf option has been set, then the field and weight files
are sdf's. The lhist file, and fff_input.dat are always ascii files.

Examples: 

Using optimization_fff is pretty straightforward. Given valuse for bx,
by, and bz on the surface, with no non-default options, just type in:

optimization_fff, bx, by, bz

But, this can take a while. An extrapolation of a 64x64 vector
magnetogram will take a couple of hours on a 2GHz linux machine. So
you might want to write a command line script and run in batch
mode. 

Some sample data has been included with the software in the test_data
directory. The file "bfield_nlfff1.sav" contains an actual non-linear
force free field created using the method of Low and Lou (1990, Apj
352, 343.). Here is how you might use the field in this file to test
to see how well the extrapolation works on a known field:

restore, '/ssw/packages/nlfff/test_data/bfield_nlfff1.sav'
help, bx0, by0, bz0                       ;these will be 64x64x64 arrays
optimization_fff, bx0, by0, bz0, $        ;The input is 3D
                  bc_flag = 1, $          ;This means that all BC's are present
                  /double, $              ;Double precision works better with test data, takes longer...
                  /slow, $                ;Uses Green's function for initialization
                  convergence = 1.0e-8, $ ;this is extreme, the default is 1.0e-6
                  iter = 50000l, $        ;A high limit
                  nsave = 5000            ;save results every 5000 iterations


(This command took 816 minutes on a 2 GHz processor pc, with 2
Gbytes of RAM. But probably the calculation could have been cut off
earlier, we don't have a good handle on how long to allow a test
calculation to go before the answer is "good enough". Real magnetogram
data, which is noisy, actually converges much more quickly.)

Since the output file name is hardwired, you might want to move
the output files. (Note -- The spawn commands are for a linux/unix
system. I have no clue how to do this in windows or Mac. The
extrapolation code should work for any operating system, though.)

spawn, '/bin/cp lhist.dat lhist__nlfff1.dat'      ;history file
spawn, '/bin/cp field.dat field__nlfff1.dat'      ;output field
spawn, '/bin/cp pfield.dat pfield__nlfff1.dat'    ;initial (potential) field

Or you may want to save the output in a save file:

read_bfield_fff, 'field.dat', rsize, tsize, vsize, bx, by, bz, x, y, z

save, rsize, tsize, vsize, bx, by, bz, x, y, z, file = 'field__nlfff1.sav'

Say that you want to test what happens in this case when you only
put in the lower boundary:

restore, 'bfield_nlfff1.sav'
help, bx0, by0, bz0                       ;these will be 64x64x64 arrays
optimization_fff, bx0, by0, bz0, $        ;The input is 3D, but only z=0 field is used
                  bc_flag = 0, $          ;Lower BC's are present, (default)
etc....


Fieldlines? 

A program has been included for fieldline plotting. This is limited to
cases for which all of the grids have uniform spacing. If you have
your own fieldline-tracing program, use it.

fieldlines_fff, bx_in, by_in, bz_in, ix_in, iy_in, x_in, y_in, z_in, $
                angx = angx, angz = angz, $
                thick = thick, $
                oplot = oplot, linecolor = linecolor, $
                title = title, pick_lines = pick_lines, $
                n_lines = n_lines, window_number = window_number

The first input is a magnetic field, bx_in, by_in, bz_in
 
Inputs ix_in, iy_in, are x and y subscripts of field lines. You can
set them yourself. Ix_in and iy_in must have the same number of
elements.
 
Use the /pick_lines keyword to choose field lines, and return ix,
iy. If n_lines is set, then there will be this many lines, the default
for n_lines is 20.
 
You can pass in the spatial grids, x_in, y_in, and z_in. This program
requires uniform grids, and probably the same number of points in the
x and y grids.
 
Angx and angz are angles for orientation, the defaults are angx =
30.0, and angz = 30.0, unless /pick_lines is set, then angx = 90.0 and
angz = 0.0, regardless of the inputs
 
Thick controls the thickness of the plotted line, the default is 1.0.
 
If /oplot is set, this oplots on the current window.
 
linecolor controls the color of the lines.

title is a title for the plot

Use the keyword window_number to set a new window.

Example:

So say that you want to view the sample B field from the file
"field__nlfff1.sav".

restore, 'field__nlfff1.sav' fieldlines_fff, bx, by, bz, ix, iy, x, y, z, /pick_lines

You'll see the message: 
'Pick      20  Fieldline starting points:'
Then click on the image 20 times, the fieldlines are drawn on the image, 
and the x and y starting points are saved in the arrays, ix and iy.

You'll get an image:
You can change the view of the image by changing the angles:

fieldlines_fff, bx, by, bz, ix, iy, x, y, z, angx=45, angz=45


Say you want to see what the potential field for this case looked
like. You didn't save it before, so you need to read in the data.

read_bfield_fff, 'pfield__nlfff1.dat', rsize, tsize, vsize, pbx, pby, pbz, x, y, z

fieldlines_fff, pbx, pby, pbz, ix, iy, x, y, z, angx=45, angz=45

Yes, the fields do look different. 

In the future, we'll add tools for the quantitative evaluation of
the differences between fields.

