User Manual: Data Structures

From FLUX

Jump to: navigation, search

(go up to User Manual)

The FLUX data structures are defined in data.h, and some interface routines are in data.c. The principal ones are listed and annotated below, with the current fields in the C structure and their corresponding names in the Perl hash.

Laurel Rachmeler has generated a helpful diagram illustrating the connections between different objects in a simple case with a small number of fluxons and flux concentrations; it is below.

Contents

Overview

Binary trees for access

The main entities -- flux concentrations, fluxons, and vertices -- are tracked in several binary trees. The binary tree structure is expensive to add to (because it requires balancing the tree) but fast to access -- for example, on vintage-2008 hardware in a simulation with 1.5 million vertices, access times to a particular vertex are typically well under a microsecond, while rebalancing the vertex tree can take over 100 milliseconds.

Fluxons: Doubly linked lists of vertices

The vertices associated with each fluxon are also linked to one another in a doubly linked list, which is more natural to describe the topology of the fluxon. Each vertex also stores a collection of neighbors and a (different) collection of other vertices that consider this one to be a neighbor.

Neighbor lists: Variable-length arrays

Short ordered collections of entities can be stored in "dumblists", a roll-your-own variable-length array of pointers. Dumblists keep track of the current number of elements and the number of slots in the array, and expand when necessary to contain all of their elements.

Memory allocation/deallocation

As with many complex data structures in C, keeping track of allocation is tricky. In particular, each vertex is pointed to not only by its neighbors on its parent fluxon, but also by other vertices that consider it to be a neighbor. De-allocating a vertex, then, requires updating all of those links.

In general, pointers are maintained to be either valid or NULL. New data structures are created with new_<foo> routines that populate internal pointers with zero. Old ones are removed with free_<foo> routines that (hopefully) clean up dangling references from elsewhere in the data structure.

To aid debugging, some fenced and otherwise debugged malloc code is available; see data.c for details.

Primitive structures

These are used as the basis of the main structures (defined below):

NUM
This is an alias for double, and is the basic numeric type for FLUX variables. It is defined high in data.h, and can in principal be set to float to save memory. That has never yet happened.
POINT2D
Just an array of 2 NUMs.
POINT3D
Just an array of 3 NUMs.
LINKS
This is used to keep track of the myriad tree structures in the main data elements. LINKS just maintains the information required to be a node in a tree: left, right, and up are all generic pointers. There is also a subnode counter (n), a floating point value accumulator (sum), and a balance flag (balanced). LINKS structures abound in the larger structs like FLUXON (below), but using each one requires knowing which data structure it is a part of and hence the offset from the beginning of the data structure. (see "Offsets", below)
DUMBLIST
This is an extensible array, to avoid multiple allocations of frequently-reused arrays. It contains a generic array pointer (stuff, which is a void **, that is to say a pointer to an array of generic pointers), a current element count (n), and a currently-allocated size (size). Dumblists are used for keeping track of variable-length lists of things, such as neighbors of a particular fluxel. You can manipulate them with several routines in data.c
PLANE
Represents a plane in 3-space, with a point that is on the plane, together with a normal vector. In principle, this can be done with three numbers total (a unit vector requires two unique numbers, and the plane can be defined by an offset from the origin in the direction of the normal vector), but it's oh so much easier to represent the origin and a full vector. The PLANE structure is currently (summer 2007) only used for boundary conditions, and it gets, er, creatively re-used by some of the boundary condition routines. For example, the cylindrical boundary condition uses the six numbers in a different way.
PHOTOSPHERE
A PHOTOSPHERE is actually a boundary condition, just poorly named. The structure is also a little stupid -- it just clumps together a PLANE (above) and a type variable. that probably should be an enum but is handled as a collection of #defines in the C code. The current values are: 0 - none; 1 - plane; 2 - sphere; 3 - cylinder. The value of the type variable indicates how the numbers in the PLANE are to be interpreted -- only type 1 treats all six as an actual plane specification.

High-level structures

These hold information about the model itself, building on the lower-level stuff (e.g. these structures contain DUMBLISTs, POINT3Ds, and LINKSes). Each of the high level structures has a corresponding Perl object in the Perl control/interface side of the code.

VERTEX

VERTEX describes an individual fluxel. Recall, a fluxon is an ordered list of fluxels, with vertices between them. Each VERTEX stores the information about itself and the following fluxel on the same fluxon. Thus some values (for example the neighbor list) aren't valid for the last VERTEX in a fluxon data structure. VERTEX structures correspond to Perl objects of type Flux::Vertex.

Each VERTEX currently uses 320 bytes. The fields are as follows:

C name C type Perl name Perl type Perl R/W? Description
line FLUXON * line Flux::Fluxon R Pointer to the fluxon that contains this fluxel
prev

next

VERTEX * prev

next

Flux::Vertex R Forward and reverse links along the linked list of VERTEXes for this fluxon. (Zero/undefined values at the ends of the list).
x POINT3D x PDL (3) RW The current location of this vertex in 3-space
neighbors DUMBLIST neighbors list ref R The current collection of neighbor vertices, stored as a DUMBLIST (or readable in Perl as a Perl list of Flux::Vertex objects)
nearby DUMBLIST nearby list ref R The current collection of vertices who think that this vertex is their neighbor, stored as a DUMBLIST (or readable in Perl as a Perl list of Flux::Vertex objects)
scr POINT3D scr PDL (3) RW A scratch vector that is used during force/neighbor calculation
r

a

NUM r

a

scalar RW Scratch values used during hull operations (the 2-D distance and angle, respectively, to the current center of the hull being calculated)
passno long An anti-collision gate used during neighbor accumulation - holds a temporary longint designed to prevent gathering the same hull element twice.
b_vec POINT3D b_vec PDL (3) RW The current magnetic field vector at the center of the following fluxel (calculated by one of the B laws in physics.c)
b_mag NUM b_mag scalar RW The current magnetic field magnitude at the center of the following fluxel (calculated by one of the B laws in physics.c)
energy NUM energy scalar RW Accumulator for field energy calculations (calculated by routines in physics.c; may store the total energy for the spatial neighborhood around the following fluxel)
f_v

f_s f_t

POINT3D f_v

f_s f_t

PDL (3) RW Each of these holds a force accumulator into which routines in physics.c add force vectors: f_v is the current vector total force on the vertex itself (e.g. curvature forces, vertex pseudoforces), and f_s is the current vector total force on the following fluxel segment (e.g. magnetic pressure force). f_t is used to hold the sum of f_v and f_s after the force accumulation is finished.
f_s_tot

f_v_tot

NUM f_s_tot

f_v_tot

scalar RW Contain the sum-of-magnitudes of the vertex and following-segment forces; these are accumulated in by the routines in physics.c.
r_v

r_s

NUM r_v

r_s

scalar RW Contain the length scales associated with the segment and vertex forces, respectively.
r_cl NUM r_cl scalar RW This is the closest-approach distance (in 2-D) of any of the neighbors.
label long label scalar RW This is a unique longint assigned to each vertex as an access key. You should assign positive numbers greater than 10. Negative numbers are used for automatically generated vertices, and small positive numbers are used for the image fluxels that enforce boundary conditions.
world_links LINKS links_foo misc R world_links is the tree data structure that's used to keep track of all VERTEXes associated with a particular WORLD (simulation). The Perl side treats the individual links fields independently, as links_sum, links_n, links_up, links_left, and links_right. The links_up, links_left, and links_right fields are Flux::Vertex objects and read-only. The numeric fields are read/write, but probably shouldn't be tampered with.
plan_step POINT3D plan_step PDL (3) RW This is a scratch space for the calculated naive relaxation step, before large-eigenvector acceleration (see the discussion on stepping in model.c).

FLUXON

The FLUXON structure represents a single fluxon. It contains information that is tied to each fluxon but doesn't need to be repeated between vertices. Of course it contains the head and tail of a linked list of VERTEX structures. FLUXON structures correspond to Flux::Fluxon objects in the Perl environment.

C name C type Perl name Perl type Perl R/W? Description
world WORLD * A pointer to the WORLD that contains the fluxon.
flux NUM flux scalar RW The magnetic flux contained in the fluxon. This field is not currently used -- it is a placeholder for the flux-scaling code. The purpose is to generalize the hull routine by scaling the distance to neighbors.
label long label scalar RW The unique label of this fluxon -- can be used to find it with the Flux::World::fluxon() method.
start

end

VERTEX * start

end

FLUX::VERTEX R The start and end of the fluxon -- these are the ends of the linked list. In a well-constructed FLUXON these should never be NULL, and they should never be the same either. (During allocation or cleanup they might be NULL...)
v_ct long v_ct scalar RW This is the vertex count in the fluxon. You should probably not write to it from the Perl side, or some things (it's hard to predict what) will get screwed up. Inserting or deleting vertices via delete_vertex, add_vertex_pos, or add_vertex_after takes care of it for you.
all_links LINKS all_links_foo misc R This is the LINKS structure that's used to maintain a worldwide tree of all existing fluxons for quick access.
start_links LINKS start_links_foo misc R This is the LINKS structure that's used to maintain a tree of all fluxons that share the same starting (North pole) flux concentration.
end_links LINKS end_links_foo misc R This is the LINKS structure that's used to maintain a tree of all fluxons that share the same ending (South pole) flux concentration.
fc0

fc1

FLUX_

CONCENTRATION *

fc0

fc1

Flux::

Concentration

R Pointers to the flux concentrations that start and end this fluxon. These should never be NULL in any well-formed fluxon. There are some dummy flux concentrations in each WORLD, that represent open or plasmoid boundary conditions.
plasmoid char This is a flag indicating that the fluxon is actually a plasmoid. It should not be set arbitrarily, and exists as a convenience -- plasmoids should also be linked to the specific plasmoid flux concentrations associated with the WORLD that contains them.

FLUX_CONCENTRATION

These represent a pole on the solar photosphere -- a point at which some flux is anchored on the Sun. Each flux concentration can support many fluxons. Because they are all anchored to the flux concentration at a single point there is (currently) no conservation of twist between the different fluxons attached to a given concentration: everything is free to swivel and eliminate mutual currents. To represent current requires at least two different flux concentrations, to hold the fluxons in place against the untwisting forces imposed by the currents. FLUX_CONCENTRATION structures correspond to Perl objects of type Flux::Concentration.

C name C type Perl name Perl type Perl R/W? Description
world WORLD * A pointer to the WORLD that contains this flux concentration. Should never be null in a well-formed FLUX_CONCENTRATION.
flux NUM flux scalar rw Represents the total amount of flux contained in this flux concentration. Currently (Summer 2007) ignored; will become more important for code that includes evolving fluxes at the boundary from, say, feature tracking. Positive for north poles, negative for south poles. The sum of all the fluxes in all flux concentrations (including the dummy boundaries) in a WORLD should be zero, but that is not currently checked for (summer 2007).
label long label scalar RW The unique label used to identify this flux concentration. Positive for north poles, negative for south poles.
lines FLUXON * lines Flux::Fluxon R This is the root of the fluxon tree (either the start_links or the end_links tree, depending on the sign of the flux concentration -- positive for starts, negative for ends) containing all the FLUXONs associated with this flux concentration.
links LINKS links_foo misc R This is the link structure of a tree containing all the flux concentrations in the simulation.
x POINT3D x PDL (3) RW The location of the flux concentration.
locale_radius NUM locale_radius scalar RW This is intended to establish a size parameter for the flux concentration. It has been repurposed - for open boundary conditions, the location of the end flux concentration is regarded as the center of a large spherical boundary, and the locale_radius tells the radius of the sphere. Fluxons that begin or end at the open flux concentration are forced to have their endpoints on the sphere. The endpoint location is determined by allowing the endpoint to move under the curvature and pressure forces, and then projecting it radially onto the surface.
passno long Temporary variable used in hull routines (or not?)
bound void (*bound)(VERTEX *v) This is a function pointer to the boundary condition routine associated with this flux concentration. See the discussion on boundary conditions for details.

WORLD

The WORLD represents a simulation arena. It should contain everything that the coders are tempted to make into a global variable. WORLD structures correspond to Perl objects of type Flux::World.

C name C type Perl name Perl type Perl R/W? Description
frame_number long frame_number scalar RW This is the current elapsed number of relaxation steps in the simulation. It's used as a kind of odometer in current (Summer 2007) runs, constantly incrementing. It will probably one day be replaced with a pair of numbers representing frame number (for relaxation steps) at the current physical time, and a separate number representing the elapsed physical time in the model.
state long state long RW This is another very underused feature that is intended to be brought up to full utility. It is a number that indicates the current state of the WORLD -- whether it is freshly defined, freshly updated, relaxed, etc. The states are a pseudo-enum handled with a bunch of #define statements in the C code: 0 - NEW; 1 - LOADING; 2 - LOADED; 3 - WORKING; 4 - RELAXED; 5 - READY. The intent is that you should be able to restore a WORLD from disk and know exactly what stage of relaxation it was in when it was saved.
concentrations FLUX_

CONCENTRATION *

concentrations Flux::

Concentration

R This is the root of the tree holding all the flux concentrations. It could conceivably be NULL if the WORLD is empty, but is not generally.
lines FLUXON * lines Flux::Fluxon R This is the root of the all_links tree holding all the fluxons in the entire simulation. (The tree infrastructure is held in the FLUXON field all_links). It could conceivably be NULL if the WORLD is empty, but is not generally.
vertices VERTEX * vertices Flux::Vertex R This is the root of a tree containing all the vertices in the entire simulation (the links are held in the VERTEX field links). It could conceivably be NULL if the WORLD is empty, but is not generally.
photosphere PHOTOSPHERE The boundary condition structure for the photosphere. (See the discussion on boundary conditions).
image

image2

VERTEX * image

image2

Flux::Vertex R A workspace for holding image fluxels -- these are constructed on a per-fluxel basis by the geometry code to enforce the photospheric boundary. They should never be null in a well-constructed WORLD.
locale_radius NUM locale_radius scalar RW Meant to hold the default locale radius for flux concentrations, this field is largely ignored.
fc_ob

fc_oe

FLUX_

CONCENTRATION *

fc_ob

fc_oe

Flux::

Concentration

R These are dummy beginning and ending flux concentrations used for anchoring fluxons that are open. Technically they aren't required as you could make any old flux concentration an open flux concentration and terminate your fluxons at it, but these are recommended for that purpose as they concentrate (heh) all such fluxons in one place.
fc_pb

fc_pe

FLUX_

CONCENTRATION *

fc_pb

fc_pe

Flux::

Concentration

R These are dummy beginning and ending flux concentrations used for anchoring fluxons that are plasmoids. Technically they aren't required as you could make any old flux concentration a "plasmoid" concentration, terminate your fluxons at it, and mark their plasmoid flags -- but these are recommended for that purpose as they concentrate (heh) all such fluxons in one place.
verbosity long verbosity scalar RW Controls how much diagnostic information is printed during the simulation. Normal operation is at 0; setting it to 6 yields several megabytes of information per timestep with 100 fluxels.
f_funcs ((void *)())[] This is an array of function pointers to the force (and field) functions used at each step of the simulation. There is as yet no hash-like interface; you must use the force() method to read and/or set them, using a string lookup table of function names.
rc_funcs (RC_FUNC *)[] This is an array of function pointers to the reconnection-test routines in use for the simulations. Simulations can choose several parameterized tests for deciding where and whether reconnection will take place. The parameters are contained in the rc_params array (just below).
rc_params NUM[][]; This is a holding tank for numeric parameters used by the reconnection-test routines. The first index runs across position in rc_funcs (just above), and the second across parameter index within the function call.
step_scale.b_power

step_scale.d_power step_scale.s_power step_scale.ds_power

NUM scale_b_power

scale_d_power scale_s_power scale_ds_power

scalar RW These are scaling powers used in force law/step length calculation. Each corresponding variable is raised to the appropriate power and multiplied by the calculated force. The final product is the step length. The forces are: 'b' - magnetic field; 'd' - distance to nearest neighbor; 's' - stiffness coefficient (<1); 'ds' - relative difference in force between this segment and adjacent ones on the same fluxon. See User Manual: step law for more details.
passno long passno scalar RW Scratch space for hull algorithms
handle_skew long handle_skew scalar RW Turns on an experimental distance-scaling function that increases the effective distance between fluxels with a significant skew angle.
max_angle

mean_angle

NUM max_angle

mean_angle

scalar RW These are accumulators for keeping track of bend angle characteristics in the simulation. They are updated automatically during a relaxation step. The angles are poorly named: they are not angles in radians but rather (cosθ)2, because that takes many fewer cycles to calculate.
dtau NUM dtau scalar RW This is the relaxation time step, in units of linear relaxation times near equilibrium. The step size is scaled by dtau after all other factors are taken into account (check User Manual: step law for details). Numbers greater than about 0.3 are generally unstable. If you find yourself turning this up, e.g. late in the simulation, then you've probably screwed up your various power laws (above).
coeffs NUM[] coeffs PDL RW This is the array of acceleration coefficients (see User Manual: step law) for accelerating large relaxation modes with small eigenvalues.
n_coeffs long n_coeffs scalar RW This is the number of acceleration coefficients. Set to 0 for non-accelerated relaxation.
maxn_coeffs long maxn_coeffs scalar RW This is the maximum allowable number of acceleration coefficients. Do not write to this lightly, as it will probably break things. It's primarily there as a way of getting the #defined number MAXNUMCOEFFS out of the C world and into the perl world.

Example

To see how the various high level structures above link together it is helpful to refer to Laurel's diagram below (click on it for full size; it is 3179x2048 pixels). You can also get it in open-document or PDF formats.

Fluxon diagram (original size is 3179x2048)

The example WORLD has three flux concentrations, and two fluxons connecting them. Concentrations 7 and 9 each source one fluxon; concentration 8 sinks both of them. Each fluxon contains three vertices. Neighbor relations are not shown.