XPLASMA

Xplasma -- D. McCune Apr. 2000 -- PPPL -- dmccune@pppl.gov Xplasma2 -- D. McCune Sept. 2006 -- PPPL -- dmccune@pppl.gov This document describes xplasma -- a set of routines for numerical representation of fusion plasma MHD equilibrium and plasma parameter profiles. Abstract (Sept 2006 updated version) -- The xplasma software offers a representation standard for tokamak plasma MHD equilibria and plasma parameter profiles defined over a variety of coordinates. Each xplasma dataset defines a "dictionary", a single namespace, in which each name refers to a specific data item-- typically, a list, a grid discretizing a coordinate, or a profile defined over one, two, or three gridded coordinates. Xplasma provides efficient methods for accessing the data associated with these items, or for adding any number of new items to the dictionary and collective dataset. An xplasma dataset (dictionary and all item contents) can be written to or restored from a NetCDF file by means of simple subroutine calls. The original implementation (xplasma 1.0) provided a single global xplasma dataset that was accessible by a set of fortran-77 style calls. An executable program could only contains one xplasma dataset at a time. The full fortran-95 implementation (xplasma 2.0) allows multiple instantiation of xplasma datasets in a single process, while preserving the fortran-77 interface with an implied reference to a "golden" xplasma pointer set aside for this purpose. Layered over efficient spline interpolation software (pspline [1]), xplasma has been used for several years to communicate data between integrated simulation codes (e.g. TRANSP, ONETWO) and NTCC modules (e.g. NUBEAM). There are also widely used applications for accessing experimental data (TRANSP & EFIT MDSplus trees) that use xplasma for internal storage of data items. It is planned to use xplasma for implementation of a plasma state component in the Fusion Simulation Project (SciDAC-2 SWIM project). [1] http://w3.pppl.gov/NTCC/PSPLINE/pspline.html

Home | Top |

Organization_of_help_document

The main topics are: Introductory Information F95 Upgrade (changes from xplasma vsn 1 to xplasma vsn 2). F95 (vsn 2) xplasma basic concepts Using F95 xplasma data Here, methods for accessing existing xplasma data are described. Initializing F95 xplasma data Here, first steps for creating a new xplasma object from scratch. Modifying F95 xplasma data Here, methods for writing data into xplasma are introduced. Error Handling Time evolution of xplasma Here, a discussion of what can and what cannot be easily changed. Creation and update of named xplasma data items More information on writing data into xplasma Global Items A few bits of modifiable globally accessible xplasma data Saving to File -- the remainder of the document: the original xplasma 1 (f77 interface) documentation.

Home | Top |

Xplasma_Introductory_Information

Xplasma is currently being used to communicate numerical representations of axisymmetric tokamak plasma timeslices between experimental databases and simulation codes, and between components or processes of multi- component or multi-process (distributed) simulation codes. Xplasma defines a sorted dictionary of named data items. It provides efficient mechanisms for looking up and accessing data. And it allows new data to be named and added in a straight-forward manner. The details are given in the subtopics. The contents of each xplasma dataset is thought of as a snapshot of the plasma state at a particular time in an experiment or simulation.

Home | Top |

Xplasma_Data_Item_Identification

Each xplasma data item has a dictionary entry with: a) a unique NAME[1] b) a unique integer ID code c) an AUTHOR name [1] d) a LABEL [2] e) a UNITS label [2] f) an integer data TYPE code The xplasma public module defines: integer, parameter, public :: xplasma_listType = 1 ! LIST data type code integer, parameter, public :: xplasma_coordType= 2 ! COORDinate data type integer, parameter, public :: xplasma_gridType = 3 ! GRID data type code integer, parameter, public :: xplasma_profType = 4 ! PROFILE data type code integer, parameter, public :: xplasma_blkbxType= 5 ! BLACK BOX data type code Notes: [1] up to 32 characters long, uppercase converted alphanumeric characters and underscore ("_"); first character must not be a numeric digit. [2] any ascii character string, or blank. Although xplasma does not restrict the length, these labels may be used by graphical display codes which may impose their own length restrictions e.g. by truncation. Recommendations: labels <~ 50 characters, units <~ 16 characters.

Home | Top |

Xplasma_Data_Types

COORDINATES-- an abstract coordinate, discretized by zero or more grids. There are two types: periodic, and non-periodic. Periodic coordinates are discretized by grids spanning [-pi:pi] or [0:2*pi]. For purposes of interpolation, there are no bounds: shifts of 2*pi*N are applied to bring interpolation coordinate data into bounds. For very large values of |N|, accuracy of interpolation will be lost. Non-periodic coordinates have fixed minimum and maximum values. Xplasma enforces prescribed limits for some coordinates; otherwise the minimum and maximum values are defined when the first grid discretizing the coordinate is provided. The xplasma public module defines (this is a partial list): integer, parameter, public :: xplasma_rho_coord = 1 ! radial flux coord. integer, parameter, public :: xplasma_theta_coord = 2 ! poloidal angle coord. integer, parameter, public :: xplasma_phi_coord = 3 ! toroidal angle coord. integer, parameter, public :: xplasma_R_coord = 4 ! R coord integer, parameter, public :: xplasma_Z_coord = 5 ! Z coord Xplasma methods exist for finding the periodicity attribute, min and max value (when defined), and number of GRIDs discretizing the coordinate. GRIDS-- specific discretization of a coordinate. A grid is a strictly ascending finite sequence of numbers, the first of which precisely matches the minimum value of the corresponding coordinate (or -pi or 0 in the case of a periodic coordinate), and the last of which precisely matches the maximum value of the corresponding coordinate (or pi or 2*pi in the case of a periodic coordinate). In gridded calculations, the GRID in the xplasma sense of the word is usually the set of boundaries of the finite zones of the calculation. The set of zone centers only constitutes a grid in the xplasma sense of the word, when it is augmented with the inner and outer boundaries of the gridded region. Xplasma methods exist for finding the size of any grid and retrieving its values. PROFILES-- 1d, 2d, or 3d interpolating functions based on array data defined over xplasma GRIDs. Interpolation method is defined when the profile is defined; there are at present 4 options: type: storage requirement: 1d 2d 3d NC step function N-1 (N1-1)* (N1-1)*(N2-1)*(N3-1) (N2-1) C0 piecewise linear N N1*N2 N1*N2*N3 f continuous C1 cubic Hermite 2*N 4*N1*N2 8*N1*N2*N3 df/dx continuous C2 cubic Spline 2*N 4*N1*N2 8*N1*N2*N3 d2f/dx2 continuous (N, N1, N2, N3 refer to the sizes of GRIDs discretizing known coordinates). When profile data is accessed by interpolation, it is only necessary to know the coordinates over which it is defined, not the specific grids. On the other hand, if the original data is needed, it is straightforward to acquire the specific grid information and the original data upon which the profile interpolating function is based. Cubic interpolation is affected by boundary conditions. For data defined over periodic coordinates, periodic boundary conditions are employed. For data defined over non-periodic coordinates, the boundary conditions are set when the data is defined. Xplasma methods exist for interpolating profiles as well as finding the underlying coordinates and grids. For multidimensional profiles, input coordinate data are tagged by COORDINATE or GRID ids; it is not necessary for the caller to know the order of storage of the data. Xplasma methods also allow straightforward means of acquiring information on the interpolation method and underlying grids. LISTS-- a list, identified by a single name, can contain 1 or more elements; each element consists of: -- a 32 character name (not part of the xplasma dictionary namespace). -- an integer value -- a (real*8) floating point value -- character data, any length, trailing blanks trimmed away. List lengths, element names, and contents are readily acquired by available xplasma methods. BLACK BOXES-- a named BLACK BOX consists of: -- an integer type code. The meaning is user defined meaning, but, it should be noted that xplasma itself uses black box type codes K, 0 <= K <= 101, to aid internal calculations and methods. User defined type codes should be outside this range. -- an integer 1d array of length specified by the user. -- a floating point (real*8) 1d array of length specified by the user. Black box datasets are used by xplasma for various purposes. Examples are: data caches for flux surface integration, representation of quantities defined over non-rectilinear grids.

Home | Top |

Conventions

Xplasma was developed for communication of data on axisymmetric tokamaks. Physics units: MKS; KeV for temperatures and particle energies. Flux coordinates: Radial flux coordinate "rho" -- rho = sqrt([enclosed-toroidal-flux]/[toroidal-flux-enclosed-by-boundary]) Poloidal angle coordinate "theta" -- theta=0 on large major radius side of plasma; theta increases along flux surfaces in counter-clockwise direction when plasma cross-section is viewed to the right of the axis of symmetry. But: data access methods provide optional controls to enable user data to be interpreted as theta_rev = 2*pi - theta grad(theta_rev) = -grad(theta), i.e. a clockwise poloidal angle coordinate. Toroidal angle coordinate "phi" -- increasing phi draws a circle in a counter-clockwise direction about the axis of symmetry, when the machine is viewed from above. ------------------- Note: adaptation of xplasma for non-tokamak applications may well be possible, but has not been attempted as of September 2006. A major effort would be required, e.g. to support stellarators or other non-axisymmetric plasma configurations.

Home | Top |

Setting_theta_orientation

Setting the orientation of the poloidal angle coordinate "theta" (aka "chi" in the fortran-77 interface) can now ONLY be done on a call-by-call basis. In the xplasma (vsn 2) fortran-95 interface, use the ccwflag[n] optional logical arguments. I.e. if the 2nd coordinate of a 2d profile evaluation call is a poloidal angle which is to be interpreted as having reversed orientation, set the optional argument ccwflag2=.FALSE.; if these arguments are omitted the normal orientation (.TRUE.) is assumed to apply. In the fortran-77 interface, most routines affected by the poloidal angle orientation include a vector size argument (ivec). To signal that the poloidal angle is to be considered reversed, set ivec to [the vector size] x (-1). I.e. a negative value of ivec signals poloidal coordinate interpretation is to be reversed. This will be verified in the documentation of the specific routines.

Home | Top |

Interpolation_Methods

xplasma supports several interpolation methods for data. The interpolation method is defined when an interpolating function is set up. In the xplasma software documentation, the desired interpolation method is indicated by an argument "iorder" in the setup routine. (Sometimes also referred to as the "spline type"). Generally the following methods are available: iorder name comment -1 zonal data step function 0 piecewise linear 1st derivatives defined, not continuous 1 Akima Hermite 1st derivatives continuous 2 Cubic Spline 1st & 2nd derivatives continuous Hermite is a piecewise cubic method that is C1 given 1st derivatives at the grid points. Akima Hermite uses a numerical method [1] for computing these derivatives which minimizes "ringing" in the case of noisy data. Cubic splines are C2 and preferable for smooth data, but can yield "ringing" artifacts in the case of noisy data. [1] Hiroshi Akima, Communications of the ACM, Jan 1974, Vol. 17 No. 1

Home | Top |

Axisymmetric-core-plasma

The core plasma is represented on a user defined flux coordinate grid (rho,theta), where "rho" is a flux surface label-- by convention, rho=sqrt(normalized-toroidal-flux) in xplasma itself, although physics applications can use any coordinate as long as the mapping to rho is known. After completion of the setup sequence, xplasma's core plasma model will contain * the flux surface geometry R(rho,theta), Z(rho,theta), in m. * equilibrium related magnetic profiles g(rho) (Tesla*m), and the poloidal flux profile psi(rho) (Wb/rad). Other magnetic profiles such as q(rho) are optional but often present. * the field components BR(rho,theta),BZ(rho,theta), and [mod(B)](rho,theta), all in Tesla. * any number of user defined 1d plasma parameter profiles f(rho) * any number of user defined 2d plasma parameter profiles g(rho,theta). The flux surface geometry and field components are represented as bicubic splines. User defined plasma parameter profiles are represented according to the user's specification, with splines, Hermite, piecewise linear, and zonal step function representations being available. For each profile there is an associated id number and name string. For reasons of efficiency, the id numbers are used for profile identification in the interpolation routines. Routines for fetching the id number from the name are provided and are efficient to log(N) of the number of names, but still should not be used in applications' innermost loops.

Home | Top |

Limiter-description

There are two options for the "limiter" or "vessel wall" specification: * a closed sequence of (R,Z) points outside the core plasma, and, * a list of bounding circles and infinite lines enclosing a space that contains the core plasma. The "scrape off plasma" is considered to be in the space inside the limiters but outside the core plasma. Generally, after the limiter is specified the user will want to set up an (R,Z) rectilinear grid which covers a rectangular space enclosing both the core plasma and the scrape-off-layer region between the core plasma and the limiters or vessel wall as given. Automatic generation of evenly spaced (R,Z) meshes is available as an option. Once this is done, xplasma will construct a piecewise bilinear function d(R,Z), where d gives (in R,Z units) the distance of (R,Z) from the nearest limiter, and * a negative number denotes a position inside the limiter * a zero denotes a position on the limiter * a positive number denotes a position outside the limiter.

Home | Top |

Scrape-off-plasma-coverage

After limiters are defined, a rectilinear (R,Z) grid can be constructed which covers both the core plasma and the scrape-off plasma. An (R,Z) representation of equilibrium, fields, and plasma profiles can then be built up as needed.

Home | Top |

Intended_applications

It is envisioned that xplasma might be used as follows: (1) a transport simulation code evolves a plasma MHD equilibrium and a set of plasma parameters. (2) "physics modules" are programmed to acquire data from the xplasma module and write data back into it. (3) the transport simulation code uses routines that add data to xplasma, to specify the plasma equilibrium and necessary plasma parameter profiles, and then it calls the physics module. (4) the physics modules reads its input data using the xplasma read routines, and then does its modeling calculations, developing a set of output profiles. (5) the physics module writes its results back into xplasma using more data definition routines, then exits. (6) the transport simulation code reads back the data created by the physics module. This reading and writing through xplasma will handle interpolation so that the main transport code and the physics module need not share COMMON blocks nor use the same numerical grids.

Home | Top |

Physical_units_conventions

Since the purpose of xplasma is to facilitate communication of data between separately developed physics models, it is necessary to recommend a convention regarding physical units. The convention adopted is based on emerging consensus in the tokamak physics modeling community: MKS for all quantities, except for temperatures and energies where KeV are used. Thus: MKS/KeV NOT cgs/eV (sorry, TRANSP...) "g" Tesla*m NOT gauss*cm "psi" Webers/rad NOT gauss*cm**2/rad "R,Z" m NOT cm "Te,Ti" KeV NOT eV "ne" m**-3 NOT cm**-3 [note it is customary to give the poloidal flux function normalized per unit toroidal angle; then Bpol = (1/R)*grad(psi), note (1/R) not (1/(2*pi*R))].

Home | Top |

Performance_considerations

Considerable effort has gone into optimization of the performance of xplasma subroutines. In particular, xplasma is layered over the pspline library, which has been shown to work well on modern vector and super- scalar computer architectures. But, general purpose routines (e.g. for interpolation) necessarily have a fair amount of control logic and error checking to support general purpose use. This will inevitably result in performance somewhat less than what is optimally achievable for a specific code. Codes for which e.g. field or metric interpolation are critical performance considerations likely already have optimized code for these purposes. In many cases it will be best simply to use xplasma as a way to load the input data structures for these optimized routines at the start of the calculation, and use the optimized routines (not xplasma calls) in the innermost loops of the calculation.

Home | Top |

Non-axisymmetry

Although the xplasma interface is designed to allow eventual support of non-axisymmetric field equilibria, the September 2006 version of the software is limited to axisymmetric configurations only.

Home | Top |

F95_Upgrade

A project has been completed to upgrade xplasma for the Fusion Simulation Project. The upgrade includes: -- simplified fortran-95 interface; simplified underlying data structures. -- object-oriented implementation, allowing multiple xplasma "instances" to co-exist independently in memory. (This is fortran-95; the term "object-oriented" is used loosely). -- ability to update equilibrium without deleting entire object contents and rebuilding from the ground up. The fortran-77 style original xplasma interface is maintained for the most part, but a few routines have been dropped-- see subtopic. The f77 routines all refer implicitly to a reserved xplasma object pointer set aside for this purpose. To use f77 routines to modify any other xplasma object, it is necessary to reset the f77 object pointer: see the subtopic

Home | Top |

Reset_F77_pointer

To reset the f77 xplasma pointer-- which defines the xplasma object to which all legacy f77 xplasma calls refer-- use the following module and its pair of contained routines grab_f77_xplasma(swant,ierr) release_f77_xplasma(ierr) -------------------------------------- details: use xplasma_obj_instance ... ! the following points to an xplasma object, to which future ! f77 xplasma calls should refer. This pointer has been initialized ! elsewhere...! type (xplasma), pointer :: swant integer :: ierr ! status code, 0=normal on exit ! reset the f77 xplasma pointer with this call: call grab_f77_xplasma(swant,ierr) if(ierr.ne.0) [handle-unlikely-error] To later restore the f77 xplasma pointer to its prior state, use: call release_f77_xplasma(ierr) if(ierr.ne.0) [handle-unlikely-error] Note that these calls should occur in pairs! If (e.g. due to error handling logic) the pairing is broken, there are two likely serious consequences: (a) F77 xplasma calls interact unexpectedly with a different xplasma object, with unpredictable results; (b) eventual f77 xplasma pointer stack underflow or overflow error.

Home | Top |

Deprecated_F77_Routines

The "C" interface to fortran-77 xplasma will be frozen. The "R4" interface to fortran-77 xplasma will be frozen. All the fortran-95 interfaces are in REAL*8 precision. The following fortran-77 style routines will be dropped in the upgraded version: eqm_flxbdy / eqm_rbdy -- "move limiter to plasma boundary" / "restore original limiter". dropped because: (a) no evidence of use; (b) error-prone; if "eqm_flxbdy" call is not followed by "eqm_rbdy", xplasma suffers a side effect; distance to limiter calculations, used e.g. for fast ion orbit loss calculations, are modified. advice: codes wishing to treat the plasma boundary as the limiter can use routines like "eq_dfast" to compute distance-to-boundary. Such routines return a positive number for locations beyond the plasma boundary, and a negative number for locations within the plasma boundary. eqm_chi_cwdir_set, eqm_chi_cwdir_restore, eqm_chi_cwdir, eq_get_chi_cwdir control clockwise/counter-clockwise orientation of poloidal angle variable. Dropped due to being error prone-- side effect of a subroutine's reset of chi_cwdir seen by all subsequent calls to xplasma routines. advice: In the xplasma fortran-95 interface, optional arguments are provided to specify angle coordinate orientations. In affected fortran-77 interface routines, the poloidal angle coordinate orientation can be reversed, separately on each call, by setting the argument vector length to a negative number. Details are provided in the updated subroutine documentation, below. eqm_phi_cwdir_set, eqm_phi_cwdir_restore, eqm_phi_cwdir, eq_get_phi_cwdir dropped: no evidence of use. Optional arguments in fortran-95 interface only. eqm_spordr_set, eqm_spordr_get dropped: xplasma feature to control spline storage mode (compact or non-compact) was found to be unnecessary and has been removed. eqm_nfast dropped: control of resolution of a 2nd (R,Z)->(rho,theta) inverse map, no longer necessary.

Home | Top |

Nomenclature

The original fortran-77 xplasma API used "chi" to designate the poloidal angle coordinate in a 2d flux coordinate representation of a tokamak plasma equilibrium. The new fortran-95 interface uses "theta" to designate this coordinate. However, since the fortran-77 and fortran-95 interfaces are both maintained, both names persist in the xplasma API. Hopefully this will not cause much confusion.

Home | Top |

F95_Xplasma_Basics

In order to use the Fortran-95 Xplasma Interface in code, it is necessary to be able to refer to xplasma objects. A consequence of the design goal of allowing multiple xplasma objects to co-exist, is that each subroutine that accesses or manipulates xplasma data must include an argument which specifies which instance of xplasma is to be affected or used. This argument is a "pointer to an xplasma object". A pointer is used, because each xplasma object can be quite large, such that it is sometimes advantageous to reuse existing xplasma code by means of resetting a pointer, rather than having to explicitly copy the entire contents from one xplasma object to another. Advanced users may want for various reasons to invent additional fortran-95 modules which declare xplasma objects and pointers. However, for starting out it is recommended to use the public module provided with the software: use xplasma_obj_instance This causes the following pointers to be defined, with suggested semantics: s -- pointer to currently active xplasma object F77 xplasma calls implicitly refer to this one. s1-- pointer to previous xplasma object (e.g. from a prior timestep in a time-dependent simulation). s2-- spare. The module xplasma_obj_instance also imports all public xplasma modules and definitions. INITIALIZATION-- xplasma_obj_instance defines SAVEd global data. Because fortran-95 does not yet allow pointers to be initialized at compile time to point to any particular object, the pointers are initially NULL. To be activated, the pointers in this module must be initialized with by calling a public subroutine defined in the module: call xoi_init(ierr) This call simply associates the pointers with specific xplasma objects inside the module; no data initialization is performed. It also sets a flag inside the module indicating that initialization has been performed, so that if the call is repeated, no action is taken. The integer argument "ierr" returns a status code, 0=normal. Almost all xplasma subroutine calls return such a status code. (NOTE: spelling variant: some xplasma routines spell this "ier" in their argument lists). Nearly all f95 xplasma calls take an xplasma object pointer as their first argument. In the documentation, the symbol "s" is used for this pointer. In some applications of xplasma, the symbol can be taken as short hand for "plasma state". Almost all xplasma calls also have a status code "ierr" as their final required argument. Ordering of calling arguments in f95 xplasma calls: Example: call xplasma_eval_prof(s,id,x,result,ierr,ideriv1=1,n_out_of_bounds=iout) 1st argument -- s -- xplasma object pointer next set of arguments -- id,x -- required inputs (here, the profile id and the x values at which to evaluate it) next set of arguments -- result,ierr -- required outputs (here, the result of the evaluation, and an error status code) ("ierr" is almost always the last required output argument). next set of arguments -- ideriv1 -- optional inputs (here, requesting the 1st derivative of the profile w.r.t. x). (the documentation will indicate that the default is to return the profile value unless otherwise directed by optional arguments). final set of arguments -- n_out_of_bounds -- optional outputs (here, the number of x values that were out of bounds, with respect to the coordinate over which the profile identified by "id" is defined). Of course, not all xplasma subroutines contain arguments in every one of these categories. Nevertheless, the ordering of arguments is consistent with this ordering for all f95 xplasma public interfaces.

Home | Top |

Xplasma_public_modules

xplasma_obj_instance uses "xplasma_obj_instance_mod" (where xplasma objects, pointers and xoi_init are defined). uses "xplasma_definitions", which... uses "xplasma_profs" -- methods for creating certain profiles. uses "xplasma_mcgrid"-- methods for creating and accessing a type of fast ion distribution function "black box" and related items. uses "xplasma_rzgeo" -- methods for defining MHD equilibrium geometry and related profiles. uses "xplasma_flxint"-- methods for computing flux surface integrals and averages. uses "xplasma_sol" -- methods for defining limiter and scrape-off region. uses "xplasma_ctran" -- coordinate transformation methods and evaluation of metric jacobian. uses "xplasma_obj" -- the kernel -- dictionary and supported data types; error handling support; NetCDF i/o.

Home | Top |

Xplasma_public_constants

The following are public parameters that are defined in the public xplasma modules, which may be helpful in user applications: Data types known to the xplasma dictionary: integer, parameter, public :: xplasma_listType = 1 ! LIST data type code integer, parameter, public :: xplasma_coordType= 2 ! COORDinate data type integer, parameter, public :: xplasma_gridType = 3 ! GRID data type code integer, parameter, public :: xplasma_profType = 4 ! PROFILE data type code integer, parameter, public :: xplasma_blkbxType= 5 ! BLACK BOX data type code Commonly used coordinates: integer, parameter, public :: xplasma_rho_coord = 1 ! radial flux coord. integer, parameter, public :: xplasma_theta_coord = 2 ! poloidal angle coord. integer, parameter, public :: xplasma_phi_coord = 3 ! toroidal angle coord. integer, parameter, public :: xplasma_R_coord = 4 ! R coord integer, parameter, public :: xplasma_Z_coord = 5 ! Z coord Designation for coordinate subsets (usable as argument in a handful of xplasma routines): integer, parameter, public :: xplasma_flux_coords = 1 ! generic flux coord. integer, parameter, public :: xplasma_cyl_coords = 2 ! generic cyl. coord. Author name usable to designate quantities that should be deleted when the plasma MHD equilibrium changes: character*32, parameter, public :: xplasma_xmhd = '__XPLASMA_MHDEQ_DERIVED' The following arguments define algorithm choices for the [R,Z] -> [rho,theta] inverse map, in order from the slowest but most accurate to the fastest but most approximate... integer, parameter, public :: xp_imap_newton = 1 integer, parameter, public :: xp_imap_polar = 2 integer, parameter, public :: xp_imap_rzlinear = 3

Home | Top |

Reserved_names

For reasons of compatibility with the original xplasma implementation and existing uses of the software, certain item names related to the plasma MHD equilibrium are reserved. These are: name -- definition (all are profiles unless otherwise specified) G -- g(rho) = R*B_phi PSI -- psi(rho); (1/R)*grad(Psi) = B_pol P -- P(rho), plasma pressure for MHD equilibrium Q -- q(rho), rotational transform d[toroidal_flux]/d[poloidal_flux] R -- R(rho,theta), (with Z) position of flux surfaces Z -- Z(rho,theta), (with R) position of flux surfaces PSI_RZ -- Psi(R,Z) BR -- BR(rho,theta), field component in R direction BZ -- BZ(rho,theta), field component in Z direction BPHI -- Bphi(rho,theta), field component in phi direction BMOD -- mod(B)(rho,theta), total field magnitude BR_RZ -- BR(R,Z), field component in R direction BZ_RZ -- BZ(R,Z), field component in Z direction BPHI_RZ -- Bphi(R,Z), field component in phi direction BMOD_RZ -- mod(B)(R,Z), total field magnitude MAG_AXIS -- list, [R,Z] at magnetic axis BDY_RZ_MINMAX -- list,{Rmin,Rmax,Zmin,Zmax} of plasma boundary (nominal last closed flux surface). User applications should avoid using these names for storage of items in xplasma. Several additional named items created by XPLASMA start with "__", two consecutive underscores. Users should avoid defining names that start with this prefix.

Home | Top |

User_defined_modules

Although the public module xplasma_obj_instance defines sevaral xplasma instances and associated pointers, the user may want to define his own xplasma instances at some point. The existing modules old_xplasma/xplasma_obj_instance.f90 old_xplasma/xplasma_obj_instance_mod.f90 can be used as examples for how to do this. The user's code will need to see use xplasma_definitions in order to make use of xplasma calls.

Home | Top |

Using_F95_Xplasma_Data

In this section, the new Fortran-95 Xplasma interface is described, with emphasis on methods for using data in an existing dataset. The xplasma pointers (s,s1) defined in xplasma_obj_instance are presumed to be available in the coding examples. The argument "ierr" is always a return status code, 0=normal. For simplicity of examples, error checking / error handling code is usually omitted -- but real codes should check the error codes! To access any xplasma call, the calling code must declare use xplasma_obj_instance or else use a user-defined module that otherwise provides access to xplasma object and interface definitions. In all f95 code examples it is assumed that this has been done.

Home | Top |

Example_code

The xplasma module comes with a debug library, which supports SGlib/ElVis graphical examination of xplasma datasets. The library is called xplasma_debug.a; the main source code for this library is xplasma_debug_module.f90-- this code has examples of pretty much every kind of access to xplasma data. Given an xplasma file path, or a URL pointing to a publicly accessible xplasma file, the data can be plotted running "plot_xplasma", a command line interactive fortran program, which uses the debug library. The f77 interface to xplasma has been re-implemented by using the f95 xplasma routines internally. This interface resides in the library old_xplasma.a; the source routines for this library, e.g. eqm_rhofun.f90, contain examples of use of xplasma f95 routines. This may be useful especially for anyone already familiar with the f77 routines.

Home | Top |

Copy_and_read

! copy contents of "s" to "s1". Prior contents of "s1" are removed; all ! associated memory is freed; "s" is not changed. call xplasma_copy(s,s1,ierr) ! read in new contents of "s" from a file. Prior contents of "s", if any, ! are removed, and associated memory is freed. "s" and "s1" are not sharing ! any memory, so, the removal of the prior contents of "s" has no effect on ! "s1". call xplasma_read(s,filename,ierr) ! "filename" is a character string variable containing a file path to ! a read accessible xplasma NetCDF file. !-------------------------- ! example: use xplasma_obj_instance use my_module ! defines "file_path" and "runid" character string variables. implicit NONE character*100 filename filename = trim(file_path)//trim(runid)//'_my_xplasma.cdf' call xplasma_read(s,filename,ierr) if(ierr.ne.0) then write(6,*) ' ? xplasma open or read failure: '//trim(filename) call xplasma_error(s,ierr,6) call bad_exit endif Note: if the filename argument has the form of a URL (i.e. starts with " http://"), xplasma_read will attempt to spawn a /usr/bin/curl process to download the indicated URL to a local disk file (in the process current working directory), and will then attempt a read of the downloaded file.

Home | Top |

Global_information

Certain global information, such as a global label, the current simulation or experiment time in seconds, sign or orientation of the toroidal field and toroidal plasma current, are stored in each xplasma. The accuracy of this information depends on the software that created the original xplasma object or file. To retrieve this information use the following routine. Other than the status code, all arguments are optional, allowing the user to select which piece or pieces of information are desired. subroutine xplasma_global_info(s,ier, & initLabel,time,axisymm,scrapeoff,bphi_ccw,jphi_ccw,nitems, & prof_counter,eq_counter,bdytol,ajac_maxVaR,rzOrder,kmom) ! this routine returns global xplasma object information, according ! to which optional arguments are provided... type (xplasma), pointer :: s integer, intent(out) :: ier ! error set iff s is uninitialized. ! this is the label passed in an xplasma_(re)Init call... character*(*), intent(out), optional :: initLabel ! can also use xplasma_time_get for this: real*8, intent(out), optional :: time logical, intent(out), optional :: axisymm ! axisymmetry flag logical, intent(out), optional :: scrapeoff ! SOL flag integer, intent(out), optional :: bphi_ccw ! Bphi counter-clockwise flag ! 0 means: never specified; 1: counter-clockwise (CCW); -1: CW integer, intent(out), optional :: jphi_ccw ! Jphi counter-clockwise flag ! 0 means: never specified; 1: counter-clockwise (CCW); -1: CW integer, intent(out), optional :: nitems ! number of items in xplasma ! dictionary at time of call. integer, intent(out), optional :: prof_counter ! profile counter ! global counter incremented for each creation or update of each profile integer, intent(out), optional :: eq_counter ! profile counter ! global counter incremented for each update of MHD equilibrium real*8, intent(out), optional :: bdytol ! out-of-range error tolerance ! relative tolerance applied for interpolations over non-periodic ! coordinates; for periodic coordinates shifts of 2*n*pi are applied ! as necessary to bring interpolations in range real*8, intent(out), optional :: ajac_maxVar ! det[J] variation tol. ! relative tolerance for variations of det[J] within a flux surface; ! used to check for singular or near-singular metric tensor in ! R(rho,theta),Z(rho,theta) flux surface definitions. integer, intent(out), optional :: rzOrder ! spline fit order for MHD ! equilibrium geometry R(rho,theta) z(rho,theta) data ! 1 for C1 Hermite; 2 (the default) for C2 Spline. integer, intent(out), optional :: kmom ! #moments for Fourier ! representation of equilibrium Also available: subroutine xplasma_time_get(s,ztime,ier) ! fetch the time (seconds) affiliated with xplasma object "s". type (xplasma), pointer :: s real*8, intent(out) :: ztime integer, intent(out) :: ier

Home | Top |

Equilibrium_derived_information

The plasma MHD equilibrium defines the transformation between magnetic flux coordinates (rho,phi,theta) and cylindrical coordinates (R,phi,Z). It also defines the magnetic field and flux surface geometry. Xplasma provides a routine for transforming coordinate sets between cartesian, cylindrical, and flux coordinate spaces. It also provides for retrieval or calculation of extrema-- e.g. minimum and maximum R, Z, and mod(B) on any flux surface, and for finding the distance to the nearest point on any flux surface. These are described in the subtopics...

Home | Top |

Magnetic_axis

To get the magnetic axis postion (m) and field strength(T): real*8 :: R_axis, Z_axis, B_axis Use this call: call xplasma_mag_axis(s,ierr, raxis=R_axis, zaxis=Z_axis, baxis=B_axis) Note that the last 3 arguments are keyworded and optional-- any user selected subset of the information may also be had using the same subroutine. The B field information is mod(B); to get the sign use xplasma_global_info and fetch "bphi_ccw" (see preceding topic). Note that this is the actual field strength, not the "vacuum" field-- i.e. g(0)/R_axis, not g(1)/R_axis, where g = R*B_phi, constant on each flux surface-- xplasma profile name "G".

Home | Top |

Flux_surface_extrema

To find the minimum and maximum R and/or Z and/or |B| occuring on a plasma flux surface: real*8 :: R_min, R_max, Z_min, Z_max ! spatial extrema, m real*8 :: B_min, B_max ! extrema in mod(B), T For the plasma boundary surface: subroutine xplasma_RZminmax_plasma(s, rmin,rmax, zmin,zmax, ier, & ccw_theta,i2pi, thRmin,thRmax, thZmin,thZmax) ! return the plasma boundary R & Z min & max type(xplasma), pointer :: s real*8, intent(out) :: Rmin,Rmax real*8, intent(out) :: Zmin,Zmax integer, intent(out) :: ier ! optionally return the poloidal angle locations of the extrema logical, intent(in), optional :: ccw_theta ! Theta CCW in poloidal plane, default=T integer, intent(in), optional :: i2pi ! angle coord normalization options ! i2pi=1 (default) returned value in range [0,2pi] ! i2pi=2 returned value in range [-pi,pi] real*8, intent(out), optional :: thRmin,thRmax real*8, intent(out), optional :: thZmin,thZmax The optional controls ccw_theta and i2pi only have an effect if theta location of extrema are being returned. For any plasma surface identified by "rho": subroutine xplasma_RZminmax(s,rho,ier, phi, & ccw_theta,i2pi, & rmin,rmax, zmin,zmax, & thRmin,thRmax, thZmin,thZmax) ! very accurately determine Rmin/max, Zmin/max of a flux surface. type (xplasma), pointer :: s real*8, intent(in) :: rho ! required input: flux surface. integer, intent(out) :: ier ! completion code real*8, intent(in), optional :: phi ! toroidal angle location ! ignored for axisymmetric cases real*8, intent(out), optional :: rmin,rmax ! Rmin & Rmax of surface real*8, intent(out), optional :: zmin,zmax ! Zmin & Zmax of surface ! optionally return the poloidal angle locations of the extrema logical, intent(in), optional :: ccw_theta ! Theta CCW in poloidal plane, default=T integer, intent(in), optional :: i2pi ! angle coord normalization options ! i2pi=1 (default) returned value in range [0,2pi] ! i2pi=2 returned value in range [-pi,pi] real*8, intent(out), optional :: thRmin,thRmax real*8, intent(out), optional :: thZmin,thZmax The optional controls ccw_theta and i2pi only have an effect if theta location of extrema are being returned. For the minimum and maximum mod(B) on any surface "rho": subroutine xplasma_Bminmax(s,rho,ier, phi, & ccw_theta,i2pi, bmin,bmax, thbmin,thbmax) use eqi_rzbox_module ! very accurately determine Bmin/max of a flux surface type (xplasma), pointer :: s real*8, intent(in) :: rho ! required input: flux surface. integer, intent(out) :: ier ! completion code real*8, intent(in), optional :: phi ! toroidal angle location ! ignored for axisymmetric cases logical, intent(in), optional :: ccw_theta ! Theta CCW in poloidal plane, default=T integer, intent(in), optional :: i2pi ! angle coord normalization options ! i2pi=1 (default) returned value in range [0,2pi] ! i2pi=2 returned value in range [-pi,pi] real*8, intent(out), optional :: Bmin,Bmax ! Bmin & Bmax of surface real*8, intent(out), optional :: thBmin,thBmax The optional controls ccw_theta and i2pi only have an effect of thBmin and/or thBmax are being returned.

Home | Top |

Computational_domain_extrema

For the computational domain (this generally encompasses a rectangle in [R,Z] space that covers and extends beyond the plasma boundary; if there is no [R,Z] rectangle defined, the plasma boundary extrema are returned: subroutine xplasma_RZminmax_extended(s, rmin,rmax, zmin,zmax, ier, & sol, id_Rgrid, id_Zgrid) ! return the R & Z min & max of the extended mapped region; if ! there is no such region return the R & Z min & max of the ! plasma type(xplasma), pointer :: s real*8, intent(out) :: Rmin,Rmax real*8, intent(out) :: Zmin,Zmax integer, intent(out) :: ier

Home | Top |

Coordinate_transform

A single interface "xplasma_ctrans" enables computation of any coordinate transformation between cartesian, cylindric, and flux coordinates. The interface xplasma_ctrans aliases two routines xplasma_ctran1 and xplasma_ctrann which accept scalar and vector arguments, respectively. The transformations are defined as follows: (R,phi,Z) --> (x,y,z) x = R*cos(phi) y = R*sin(phi) z = Z (x,y,z) --> (R,phi,Z) R = sqrt(x**2+y**2) if R > 0, phi = atan2(y,x), otherwise phi = 0 Z = z (rho,theta) --> (R,Z) bicubic splines R(rho,theta), Z(rho,theta) are evaluated. An extrapolation of the system defines (rho,theta) --> (R,Z) for rho > 1 -- it is continuous at the boundary rho=1 with the interior splines, but not continuously differentiable. (R,Z) --> (rho,theta) various options for estimating the inverse map are provided. The options control an accuracy/speed trade off. If many evaluations are needed (e.g. for straight line tracking in flux coordinate space), the fastest option is to compute a bilinear profile interpolant pair rho(R,Z) and theta(R,Z) on some grid. The map is calculated accurately at the grid points; the interpolation of theta(R,Z) is handled carefully in the vicinity of the theta branch cut (2*pi discontinuity). This method is supported by the "maptype=xp_imap_rzlinear" option and is sufficient for many purposes. For greater cost in cpu time, the (R,Z) splines can be inverted using a Newton method with accuracy tolerances set down near machine precision if necessary: "maptype=xp_imap_newton", the default, combined with "tol=<desired relative accuracy tolerance>"; code comments: real*8, intent(in), optional :: tol ! map tolerance ! tol applies to Newton map (maptype = xp_imap_newton = default) ONLY ! (R_in,Z_in)->(rho_out,theta_out): ! |R_in-R(rho_out,theta_out)| < tol*max(R_in,|Z_in|) ! |Z_in-Z(rho_out,theta_out)| < tol*max(R_in,|Z_in|) ! default: s%bdytol ! s%bdytol's own default value is 1.0d-10 ! cf xplasma_bdytol_set; xplasma_global_info. An option of intermediate speed that is generally accurate to ~1.0d-4 and requires no pre-tabulation of map data, can be had by setting "maptype=xp_imap_polar". Almost all arguments are optional-- the presence of arguments defines what transformation is desired. Examples: INTEGER, PARAMETER :: R8=SELECTED_REAL_KIND(12,100) real(R8) :: r,z,rho,theta ! real*8 also works... real(R8) :: r2(2),z2(2),rho2(2),theta2(2) ! scalar (rho,theta) -> (R,Z) call xplasma_ctrans(s,ierr,rho_in=1.0_R8,theta_in=0.0_R8, & r_out=r,z_out=z) ! scalar (R,Z) -> (rho,theta) call xplasma_ctrans(s,ierr,r_in=r,z_in=z,rho_out=rho,theta_out=theta) r2(1)=r r2(2)=r-0.01_R8 z2(1:2)=z ! vector (R,Z) -> (rho,theta) call xplasma_ctrans(s,xp_use_coord_vecsize,ier, & r_in=r2, z_in=z2, rho_out=rho2, theta_out=theta2) "xp_use_coord_vecsize" is a logical parameter (value is .TRUE.) defined by the xplasma public module; it means the vector size is inferred from the arguments (all sizes must match). The alternative is "xp_set_coord_vecsize" (.FALSE.) which allows a size less than or equal to the smallest passed vector size to be used. Full interface: interface xplasma_ctrans module procedure xplasma_ctran1 ! scalar module procedure xplasma_ctrann ! vector end interface Scalar interface: subroutine xplasma_ctran1(s,ier, & x_in,y_in,z_in, r_in,phi_in, rho_in,theta_in, & tol, maptype, ccw_theta,ccw_phi, i2pi, & x_out,y_out,z_out, r_out,phi_out, rho_out,theta_out, & nregion,cosphi,sinphi) Vector interface: subroutine xplasma_ctrann(s,vsize_flag,ier, & isize, & x_in,y_in,z_in, r_in,phi_in, rho_in,theta_in, & tol, maptype, ccw_theta,ccw_phi, i2pi, & x_out,y_out,z_out, r_out,phi_out, rho_out,theta_out, & nregion,cosphi,sinphi) ! VECTOR coordinate mapping interface type (xplasma), pointer :: s logical, intent(in) :: vsize_flag ! vector size flag ! .TRUE. means size is to be inferred from passed vector sizes, ! all of which must match; ! .FALSE. means size is to be set by optional argument "isize"; ! all vectors must size.ge.isize then. integer, intent(out) :: ier ! completion code 0=OK !------------------------ ! optional inputs... integer, intent(in), optional :: isize ! vector size if(vsize_flag) real*8, intent(in), dimension(:), optional :: x_in,y_in,z_in ! Cartesian Coords in real*8, intent(in), dimension(:), optional :: r_in,phi_in ! Cylindric Coords (z also) real*8, intent(in), dimension(:), optional :: rho_in,theta_in ! Flux Coords (phi also) !------------------------------------------------------------ ! the following applies to (R,Z) -> (rho,theta) "inverse" map: real*8, intent(in), optional :: tol ! map tolerance ! tol applies to Newton map (maptype = xp_imap_newton = default) ONLY ! (R_in,Z_in)->(rho_out,theta_out): ! |R_in-R(rho_out,theta_out)| < tol*max(R_in,|Z_in|) ! |Z_in-Z(rho_out,theta_out)| < tol*max(R_in,|Z_in|) ! default: s%bdytol; s%bdytol's own default value is 1.0d-10 integer, intent(in), optional :: maptype ! = 1 = xp_imap_newton = default -- iterative Newton root finder ! with initial guess generator using polar map (slowest but ! most accurate, accuracy can be controlled with tol. ! = 2 = xp_imap_polar -- polar map inversion method ! much faster, not as accurate as Newton map ! = 3 = xp_imap_rzlinear -- bilinear inverse map -- after ! initialization (using polar map), the fastest, but less ! accurate still (depends on R,Z grid resolution). This ! method requires a user defined (R,Z) rectangle grid; if ! none is available the polar map is used instead. !------------------------------------------------------------ logical, intent(in), optional :: ccw_phi ! Phi CCW view from above, default=T logical, intent(in), optional :: ccw_theta ! Theta CCW in poloidal plane, default=T integer, intent(in), optional :: i2pi ! angle coord normalization options ! i2pi=1 (default) returned value in range [0,2pi] ! i2pi=2 returned value in range [-pi,pi] !------------------------- ! optional outputs... real*8, intent(out), dimension(:), optional :: x_out,y_out,z_out ! Cartesian Coords in real*8, intent(out), dimension(:), optional :: r_out,phi_out ! Cyl. Coords (z also) real*8, intent(out), dimension(:), optional :: rho_out,theta_out ! Flux Coords (phi also) real*8, intent(out), dimension(:), optional :: cosphi,sinphi ! phi sin & cos integer, intent(out), dimension(:), optional :: nregion ! region code ! 0=not checked; 1=inside core plasma; 2=outside plasma but inside ! mapped region; 3=beyond mapped region.

Home | Top |

Metric_jacobian

The 2x2 form of the metric jacobian [J] [ dR/drho dR/dtheta ] [ dZ/drho dZ/dtheta ] This is useful for various calculations. For example, 2*pi*R*det[J]*drho*dtheta is the differential volume element; grad(rho) and grad(theta) are readily derived from [J]; for f=f(rho,theta), grad(f) = (df/drho)*grad(rho) + (df/dtheta)*grad(theta). There is a generic interface xplasma_rzjac that maps to two specific routines: xplasma_rzjac1 for all scalar arguments; xplasma_rzjacn for all vector arguments. The metric jacobian array elements, or R, or Z, or det[J], or components of grad(rho) or grad(theta), or any combination thereof, can be acquired with xplasma_rzjac. The full interface follows... Full interface: interface xplasma_rzjac module procedure xplasma_rzjac1 ! scalar module procedure xplasma_rzjacn ! vector end interface Scalar interface: subroutine xplasma_rzjac1(s,rho_in,theta_in,ier, ccwflag1, & r1,z1,drdrho1,dzdrho1,drdtheta1,dzdtheta1, & rzdetj1,drhodr1,drhodz1,dthdr1,dthdz1) Vector interface: subroutine xplasma_rzjacn(s,rho_in,theta_in,ier, & ccwflag, r,z,drdrho,dzdrho,drdtheta,dzdtheta, & rzdetj, drhodr,drhodz, dthdr,dthdz) ! evaluate terms associated with 2d Jacobean -- vector version ! [dR/drho dR/dtheta] ! [dZ/drho dZ/dtheta] ! *** all vectors must be of the same length *** type (xplasma), pointer :: s real*8, dimension(:) :: rho_in ! vector of radial coordinate in real*8, dimension(:) :: theta_in ! vector of poloidal angle coordinate in ! (see ccwflag below) integer, intent(out) :: ier ! completion code 0=OK ! Poloidal angle orientation: TRUE (default) if dZ/dtheta is ! positive on the large major radius size and negative on the ! small major radius side of each flux surface; FALSE for the ! reverse. logical, intent(in), optional :: ccwflag real*8, intent(out), dimension(:), optional :: r,z ! (R,Z) values if desired real*8, intent(out), dimension(:), optional :: drdrho,dzdrho ! rho derivatives if desired real*8, intent(out), dimension(:), optional :: drdtheta,dzdtheta ! theta derivatives if desired real*8, intent(out), dimension(:), optional :: rzdetj ! determinant of 2x2 jacobian matrix real*8, intent(out), dimension(:), optional :: drhodr,drhodz ! grad(rho) components if desired real*8, intent(out), dimension(:), optional :: dthdr,dthdz ! grad(theta) components if desired

Home | Top |

Distance_to_flux_surface

For any point [R,Z] or a vector of points {R(1:n),Z(1:n)}, it is possible to very accurately find the closest point of approach on a chosen plasma flux surface. The public interface xplasma_bdfind aliases two routines, xplasma_bdfind1 with scalar input and output arguments, and xplasma_bdfindn with vector input and output arguments, to compute these distances. Three methods are available, which trade accuracy for speed-- as described in the interface comments. Distances returned are in meters; positive numbers denote points outside the flux surface; negative numbers denote points inside. The user can optionally receive information on the location of the point on the flux surface which is closest to the input point(s). Both these routines are aliased to "xplasma_bdfind" in the module interface. Full interface: interface xplasma_bdfind module procedure xplasma_bdfind1 ! scalar module procedure xplasma_bdfindn ! vector end interface Scalar arguments: subroutine xplasma_bdfind1(s,zR,zZ,ier, & maptype, phi_in, rho_in, ccw_theta, ccw_phi, i2pi, outside_only, & theta_out, phi_out, dist) Vector arguments: subroutine xplasma_bdfindn(s,isize,zR,zZ,ier, & maptype, phi_in, rho_in, ccw_theta, ccw_phi, i2pi, outside_only, & theta_out, phi_out, dist) ! accurately find the distance of points (R,Z) from a flux surface ! and the closest point on the flux surface ! although phi arguments are supplied to support a possible future ! upgrade to 3d, these have no effect on axisymmetric calculations. use eqi_rzbox_module type (xplasma), pointer :: s integer, intent(in) :: isize ! vector size ! all array arguments' sizes must be .ge.isize ! the target points whose distances from a surface are to be ! calculated: real*8, dimension(:), intent(in) :: zR ! R values real*8, dimension(:), intent(in) :: zZ ! Z values integer, intent(out) :: ier ! completion code 0=OK !------------ ! optional arguments integer, intent(in), optional :: maptype ! = 1 = xp_imap_newton = default -- iterative Newton root finder ! with initial guess by searching method, accurate w.r.t. ! spline fit of R & Z, to machine precision, but costly... ! = 2 = xp_imap_polar -- polar "circle-fit" distance estimate: ! The boundary is treated as a piecewise linear interpolation ! between circles fit to nearby points on the boundary ! much faster, not as accurate as Newton map ! = 3 = xp_imap_rzlinear -- bilinear inverse map -- after ! initialization (using polar map), the fastest, but less ! accurate still (depends on R,Z grid resolution). This ! method requires a user defined (R,Z) rectangle grid; if ! none is available the polar map is used instead. real*8, dimension(:), intent(in), optional :: phi_in ! toroidal angle ! (not needed for axisymmetric equilibria) real*8, intent(in), optional :: rho_in ! **SCALAR** -- the surface from ! which to calculate distances. DEFAULT is the boundary surface rho=1.0 logical, intent(in), optional :: ccw_phi ! Phi CCW view from above, default=T logical, intent(in), optional :: ccw_theta ! Theta CCW in poloidal plane, default=T integer, intent(in), optional :: i2pi ! angle coord normalization options ! i2pi=1 (default) returned value in range [0,2pi] ! i2pi=2 returned value in range [-pi,pi] logical, intent(in), optional :: outside_only ! flag that caller only ! expects to need data from beyond plasma boundary (default .FALSE.) ! (this switch only useful for optimization of maptype=3 calls). !------------- ! results-- optional but at least one should be present real*8, dimension(:), intent(out), optional :: theta_out ! theta of ! nearest point on surface real*8, dimension(:), intent(out), optional :: phi_out ! phi of ! nearest point on surface real*8, dimension(:), intent(out), optional :: dist ! distance to ! surface. If dist(j) > 0.0 then (zR(j),zZ(j)) is outside the test ! surface; if dist(j) < 0.0 then the point is inside the test surface; ! if dist(j) = 0.0 then the point is on the test flux surface. A caveat: when the fastest (bilinear) map is used: the distance information is good to within the resolution of the map, but... the location-on-surface (theta_out) data can be inaccurate in the vicinity of discontinuities in the location of the nearest point. These discontinuities occur when passing through a plane where two widely separate nearest points are equidistant. The bilinear interpolation of the fast map data then yields a theta value somewhere between the two nearly equidistant points, which is not correct. The solution, when the accuracy of the angle coordinate of the nearest point on the surface is of concern, is to use the slower but more accurate mapping options.

Home | Top |

Volume_and_Area

When xplasma is loaded with an equilibrium, two spline functions Volume(rho) -- volume, m**3, enclosed by rho surface, 0 <= rho <= 1. Area(rho) -- area, m**2, of poloidal cross section enclosed by rho surface, 0 <= rho <= 1. These are splines defined on the rho grid of the equilibrium. Two convenience routines are for evaluating these functions: xplasma_volume and xplasma_area. These are interface names that map to two actual routines, one which just returns the total plasma enclosed volume (or area), the other accepting vector of rho values for which either the volume (area) or its derivative w.r.t. rho may be returned. This may best be illustrated by example: real*8, parameter :: rho_bdy = 1.0d0 real*8 :: plasma_volume, plasma_area real*8 :: my_rho_grid(5) = (/ 0.0d0, 0.25d0, 0.5d0, 0.75d0, 1.0d0 /) real*8 :: my_vols(5),my_areas(5) call xplasma_volume(s,plasma_volume, ierr) call xplasma_volume(s,my_rho_grid,my_vols, ierr) call xplasma_area(s,plasma_area, ierr) call xplasma_area(s,my_rho_grid,my_areas, ierr) The variant with vector arguments accepts an optional argument with which the derivative of the volume are area may be retrieved: interface xplasma_volume module procedure xplasma_vol1 module procedure xplasma_voln end interface subroutine xplasma_voln(s,xs,ans,ier, ideriv) ! ** public ** ! return Volume(x) or dVol/dx -- calculate if needed. type (xplasma), pointer :: s real*8, dimension(:), intent(in) :: xs ! evaluation vector real*8, dimension(:), intent(out) :: ans ! result of evaluation integer, intent(out) :: ier ! completion code 0=OK integer, intent(in), optional :: ideriv ! derivative option 0,1,2 (Here "x" is used for "rho" -- radial flux coordinate). The accuracies of volumes and areas are to 64 bit machine precision for the given equilibrium representation (see next subtopic).

Home | Top |

Flux_surface_integration

There are many flux surface averaged metric and/or field quantities that may be needed in a plasma simulation, beyond area and volume. So, xplasma includes a highly efficient and accurate facility for computing flux surface integrated or averaged metrics on any user specified grid. To do this, a program using the xplasma library needs write access (see subtopic). The steps involved are: a) enable write access to xplasma (xplasma_author_set). b) define integration grid & have xplasma initialize data structures to support integration. c) have xplasma compute each desired integration, one at a time. If integrand data caching is enabled, the efficiency is greatly improved, when multiple integrals or averages need to be computed. d) clean up temporary data structures e) release write access (xplasma_author_clear).

Home | Top |

Algorithm_and_accuracy

The integration method used is a 10 point gauss-kronrod-patterson non- adaptive method, segmented to evaluate a separate 10 point sum between each pair of grid points on the equilibrium grid. This means that that the segments, or, algebraic sums, products, and quotients of cubic spline segments for the geometry and magnetic fields as interpolated over the equilibrium grid. For non-singular integrands, this yields accuracy to 64 bit machine precision, as has been verified by comparing to higher-N gauss-kronrod-patterson summations. The code to carry this out is derived from www.netlib.org quadpack/dqng.for. Of the standard integrations, only the "neoclassical" flux surface averages "<F(H)NCLASS>S" and "<F(H)NC_TSC>S" involve integrand singularities. These are of the form sqrt(1-B/Bmax). At present, for the sake of convenience and speed, these are evaluated using the same non-adaptive method with a simple patch to the singularity, resulting in accuracy of about 1 part in 10**4 compared to a slow, precise method. This is thought to be sufficient for the purposes of these quantities. User defined spline profiles f(rho,theta) can also be integrated or averaged, but the machine precision accuracy will only be obtained if the user splines are defined over the equilibrium grid-- i.e. the same grid as used by "R", R(rho,theta), "Z", Z(rho,theta), and the magnetic field splines BMOD, BZ, etc. The accuracies claimed are with respect to these spline representations of the equilibrium geometry and fields.

Home | Top |

Write_access_to_xplasma

Using the flux surface integration facility requires writing working data to be written into xplasma-- so, it is necessary to introduce routines to enable this. By default, xplasma is opened "write locked"-- dictionary items may not be added. To open xplasma to allow new items to be written, it is necessary to call the following pair of routines: character*32 :: author_name = <name-of-my-program-in-quotes> call xplasma_author_set(s,author_name,ierr) [... execute code requiring write access to xplasma ...] call xplasma_author_clear(s,author_name,ierr) The code actually maintains a stack of author names-- i.e. the code executed could include subroutine calls to another library which writes xplasma data under a different authorname, with its own pair of xplasma_author_set and xplasma_author_clear calls. (If a routine fails to issue the trailing xplasma_author_clear call, the next routine that does issue such a call will see an error, because the author_name passed will not match the author_name at the top of the author stack).

Home | Top |

Define_integration_grid

The user's integration grid spans a subspace of rho [0,1] containing at least one grid zone. The entire [0,1] space need not be covered. The subdivided space is defined by passing the rho zone boundaries to the setup routine: real*8 :: my_rho_grid(5) = (/ 0.0d0, 0.25d0, 0.5d0, 0.75d0, 1.0d0 /) integer :: id_integ ! integrator object ID call xplasma_create_integ(s,'my_integrator',my_rho_grid,id_integ,ierr, & cache_enable = .TRUE.) Subsequent integrations using this grid will refer to the integer ID "id_integ" to reference the integrator. The integrator defined is now ready to compute surface averages at each of the grid points (my_rho_grid(1:5)), or, zonal averages covering the grid zones my_rho_grid(1:2), my_rho_grid(2:3), etc. For many applications, the 1d integrator is all that is needed. However, it is also possible to set up a 2d grid, with an additional subdivision of space by the poloidal angle coordinate: integer ::id_integ_2d ! 2d integrator object ID real*8 :: my_theta_grida(n) my_theta_grid(1) = 0.0d0 ... my_theta_grid(n) = 2*pi ! can also use [-pi,pi] ! or perhaps not span the entire theta coordinate range. call xplasma_augment_integ(s,'my_2d_integrator',id_integ,my_theta_grid, & id_integ_2d,ierr) Note that now two integrators are defined, with IDs: id_integ -- 1d integrator id_integ_2d -- 2d integrator.

Home | Top |

Execute integrations

The typical call to evaluate a flux surface average looks like this: real*8 :: answer(nn) ! nn the grid size specified earlier to real*8 :: ans_zon(nn-1) ! "xplasma_creat_integ"... real*8 :: ans_2d(nth,nn) ! nth the theta grid size specified earlier real*8 :: ans_2dzon(nth,nn-1) ! to "xplasma_augment_integ"... ! get the differential volume averaged <1/R^2> on my flux surfaces... call xplasma_rho_zonint(s,id_integ,'<1/R^2>S',answer,ierr) ! one can also evaluate call xplasma_rho_zonint(s,id_integ,'<1/R^2>',ans_zon,ierr) ! BUT it is much slower and usually the differential average is enough ! for modeling applications... ! <1/R^2> = zonal integral[dVol*(1/R**2)]/integral[dVol] over entire zone ! <1/R^2>S = surface integral[dVol*(1/R**2)]/integral[dVol] ! = surface integral[dVol*(1/R**2)]/(dVol/drho at surface) ! dVol = 2*pi*R*[(dl/dtheta)/grad(rho)]*dtheta*drho ! (available from the equilibrium metric tensor) ! integrations can also be done separately for each theta zone. The ! 1st dimension of ans_2d or ans_2dzon must match the number of theta ! zones: ! get volume of each zone in a 2d partitioning of flux space: call xplasma_2d_zonint(s,id_integ_2d,'dVOL',ans_2dzon,ierr) Note that the 3rd argument (character string) identifies the integration to be computed. The following integrals and averages are available. The intregral name passed argument must match one of these exactly, after uppercase conversion: surface-oriented zone-oriented remark "VOL" enclosed volume, m**3 "dVOL" volume in each zone "AREA" enclosed cross sectional area, m**2 "dAREA" area in each zone "DVDRHO" dVol/drho at each surface, m**3 "LPOL" poloidal path length, m "SURF" area of flux surface, m**2 "ITOR" enclosed toroidal current, A "<1/R^2>S" "<1/R^2>" m**-2 "<1/R>S" "<1/R>" m**-1 "<1/R^3>S" "<1/R^3>" m**-2 "<R^2>S" "<R^2>" m**2 "<R>S" "<R>" m "<1/B^2>S" "<1/B^2>" T**-2 "<1/B>S" "<1/B>" T**-1 "<B^2>S" "<B^2>" T**2 "<B>S" "<B>" T "<BZ^2>S" "<BZ^2>" T**2 "<grad(RHO)>S" "<grad(RHO)>" m**-1 "<grad(RHO)^2>S" "<grad(RHO)^2>" m**-2 "<grad(RHO)^2/R^2>S" "<grad(RHO)^2/R^2>" m**-4 "<grad(RHO)^2/R^3>S" "<grad(RHO)^2/R^3>" m**-5 "<R^2*grad(RHO)^2>S" "<R^2*grad(RHO)^2>" dimensionless "<1/(R*grad(RHO))>S" "<1/(R*grad(RHO))>" dimensionless "<grad(RHO)^2/B^2>S" "<grad(RHO)^2/B^2>" m**-2*T**-2 the following have sqrt singularities; the result is less accurate than with continuously differentiable integrands: "<F(H)NCLASS>S" <(1-sqrt(1-h))(1+h/2)/(h*h)>; h=B/Bmax "<F(H)NC_TSC>S" <(1/B**2)*sqrt(1-h)*(2+h)/3>; h=B/Bmax if "USER_FUNC" is the name of a profile vs. (rho,theta) existing in the current xplasma: "<USER_FUNC>S" "<USER_FUNC>" surface or zone averaged USER_FUNC "I(USER_FUNC)S" "I(USER_FUNC)" surface or zone integral of USER_FUNC Any profile of (rho,theta) can be integrated or averaged in this way.

Home | Top |

xplasma_rho_zonint

subroutine xplasma_rho_zonint(s,idi,int_name,result,ier, & dvol_out,iwarn_dvol,dvdrho_out,iwarn_dvdrho) ! integrator -- over rho zones result of form f(rho) indexed by zone ! 1 result per zone (#zones) ! or rho surfaces, also result of form f(rho) ! 1 result persurface (#zones + 1) type (xplasma), pointer :: s integer, intent(in) :: idi ! integrator data structure ("black box") id character*(*),intent(in) :: int_name ! name of desired integration real*8, dimension(:), intent(out) :: result integer, intent(out) :: ier ! status code 0=OK ! ** optional outputs ** real*8, dimension(:), optional :: dvol_out ! zone volumes integer, intent(out), optional :: iwarn_dvol ! =0 if zone volumes OK ! iwarn_dvol=1: zone volumes not available; =2: array dimension error. real*8, dimension(:), optional :: dvdrho_out ! dV/drho @ surfaces integer, intent(out), optional :: iwarn_dvdrho ! =0 if dV/drho OK ! iwarn_dvdrho=1: dV/drho not available; =2: array dimension error.

Home | Top |

xplasma_2d_zonint

subroutine xplasma_2d_zonint(s,idi,int_name,result,ier, & dvol_out,iwarn_dvol,dvdrho_out,iwarn_dvdrho) ! integrator -- 2d domain; return integrations or averages ! over theta^rho zones or across theta zones at rho surfaces. type (xplasma), pointer :: s integer, intent(in) :: idi ! integrator data structure ("black box") id character*(*),intent(in) :: int_name ! name of desired integration real*8, dimension(:,:), intent(out) :: result integer, intent(out) :: ier ! status code 0=OK ! result is dimension [#theta-zones,#rho-zones] or ! [#theta-zones,#rho-surfaces] according as the integrand ! specified is zone oriented or surface oriented. ! The #zones are defined when the integrator dataset (idi) ! is defined. ! ** optional outputs ** real*8, dimension(:,:), optional :: dvol_out ! zone volumes integer, intent(out), optional :: iwarn_dvol ! =0 if zone volumes OK ! iwarn_dvol=1: zone volumes not available; =2: array dimension error. real*8, dimension(:,:), optional :: dvdrho_out ! dV/drho @ surfaces integer, intent(out), optional :: iwarn_dvdrho ! =0 if dV/drho OK ! iwarn_dvdrho=1: dV/drho not available; =2: array dimension error. ! Options for integrands is the same as for xplasma_rho_zonint; ! Surface oriented results e.g. LPOL are on rho surfaces at each theta ! zone; ! Zone orented results e.g. dVol are on rho^theta zones.

Home | Top |

Cleanup

After completion of use of the integrator or integrators, it is a good idea to clean up, i.e. free the memory and temporary data associated with the integrators. call xplasma_remove_item(s,id_integ,ierr) ! remove integrator (rho) ...and if integrations segmented in theta space were done: call xplasma_remove_item(s,id_integ_2d,ierr) ! remove integrator (rho,theta) (In general, "xplasma_remove_item" will report an error in case of an attempt to remove a non-existent item, or an item not owned by the current author). Finally, as previously mentioned, it is important to close the "write" connection to xplasma: call xplasma_author_clear(s,author_name,ierr) (author_name the same character string as used in a prior xplasma_author_set call).

Home | Top |

Poloidal_flux_grid

For codes that use a grid based on poloidal flux, it can be useful to get a mapping to rho=sqrt(toroidal_flux/toroidal_flux_at_bdy). The following xplasma subroutine provides a precise mapping: subroutine xplasma_rhopsi_find(s,psivals,rhovals,ierr, tol, iwarn) ! find rho values corresponding to a specified set of Psi values ! Psi -- Poloidal flux, Wb/rad ! rho -- sqrt(Tor_flux/Tor_flux_at_bdy) ! all input Psi values should be in the range [Psimin,Psimax] where ! Psimin corresponds to the magnetic axis and Psimax-Psimin ! corresponds to the (unsigned) poloidal flux, Wb/rad, enclosed ! within the core plasma. Usually Psimin=0 is set. type (xplasma), pointer :: s real*8, dimension(:), intent(in) :: Psivals ! Psi values in any order real*8, dimension(:), intent(out) :: rhovals ! rho values output ! sizes of Psivals and rhovals must match integer, intent(out) :: ierr ! status code, =0 on normal exit ! error occurs if xplasma is unitialized or contains no MHD equilibrium; ! Psi-out-of-range is handled (see iwarn, below). real*8, intent(in), optional :: tol ! accuracy tolerance ! on output, rho values satisfy ! abs(Psi(rhovals(i))-Psivals(i)) <= tol*[Psi at bdy] ! (1:npsi) -- sqrt(toroidal_flux/toroidal_flux_at_bdy) ! 0 on axis, 1 at the edge. integer, intent(out), optional :: iwarn ! #of Psi values out of range ! if Psi <= Psimin, rho=0 is returned; if Psi >= Psimax rho=1 is ! returned. Caution-- note that the input Psi values are in physical units, Wb/rad, not normalized to 1.000 at the boundary. But the following conventions are used: Psi=0 at the magnetic axis Psi is "unsigned", always non-negative; rho > 0 ==> Psi'(rho) > 0. The range of currently known Psi values within the plasma can be had with the following call: real*8 psimin,psimax call xplasma_psi_range(s,psimin,psimax) The sign of the poloidal flux can be had by fetching jphi_ccw, as in: integer :: jphi_ccw call xplasma_global_info(s,ierr, jphi_ccw=jphi_ccw) The convention is: jphi_ccw=1 means that toroidal current flows counter- clockwise in the tokamak as viewed from above.

Home | Top |

Find_data_items

Acquiring xplasma data generally involves two steps: a) translate name to integer ID (look up in dictionary) b) access the data, using the ID. This section describes step (a). If data of a known type is expected to exist under a known name, the following calls are the easiest to use: character*32 :: name integer :: id name = <the-name-you-want> call xplasma_profId(s,name,id) ! look up a PROFILE --or-- call xplasma_gridId(s,name,id) ! look up a GRID --or-- call xplasma_coordId(s,name,id) ! look up a PROFILE --or-- call xplasma_listId(s,name,id) ! look up a LIST --or-- call xplasma_blkbxId(s,name,id) ! look up a BLACK BOX Note there is no "ierr" code. If the item does not exist, or if it is of the wrong type, or if there is some other error (e.g. "s" is a NULL pointer), id=0 is returned.

Home | Top |

Alternate_method:

! this returns the ID of an item, no matter what its type is. ! setting nf_noerr=.TRUE. causes non-existence of the item not to ! be considered an error; this is an optional argument. call xplasma_find_item(s,name,id,ierr,nf_noerr=.TRUE.) ! itype is an integer... call xplasma_get_item_info(s,id,ierr, itype=itype) if(itype.eq.xplasma_profType) then <it is a profile> else if(itype.eq.xplasma_gridType) then <it is a grid> ...etc...

Home | Top |

xplasma_common_ids

The following call is used mainly within xplasma to retrieve the IDs of commonly used items; it is publicly accessible: subroutine xplasma_common_ids(s,ier, & id_g,id_psi,id_P,id_R,id_Z,id_Bmod,id_BR,id_BZ, & id_axis,id_RZminmax) ! return commonly requested profile IDs ! g(rho), psi(rho), R(rho,theta), Z(rho,theta) type (xplasma), pointer :: s integer, intent(out) :: ier integer, intent(out), optional :: id_g integer, intent(out), optional :: id_psi integer, intent(out), optional :: id_P integer, intent(out), optional :: id_R integer, intent(out), optional :: id_Z integer, intent(out), optional :: id_BR integer, intent(out), optional :: id_BZ integer, intent(out), optional :: id_BMOD integer, intent(out), optional :: id_axis integer, intent(out), optional :: id_RZminmax

Home | Top |

Information_on_items

Use "xplasma_get_item_info" to retrieve one or more of the following: character*32 :: name character*32 :: author character*(*) :: label character*(*) :: units integer :: itype ! type of item (list, profile, grid, etc.) All the return arguments are OPTIONAL and keyworded outputs. An optional input argument nf_noerr can be set .TRUE. to ignore "invalid ID" errors, i.e. not to create a message or set an error code in this case. Example: character*32 :: my_name,my_author call xplasma_get_item_info(s,id,ierr, name=my_name, author=my_author) Full interface: subroutine xplasma_get_item_info(s,id,ier, & nf_noerr, & name,label,units,itype,author) ! return info on item-- what info determined by presence of ! optional arguments type (xplasma), pointer :: s integer, intent(in) :: id ! id of item for which info is requested integer, intent(out) :: ier ! return status code (0=OK) ! optional control: logical, intent(in), optional :: nf_noerr ! .TRUE. to allow ivalid id ! here is what can be returned... character*(*), intent(out), optional :: name ! name of item character*(*), intent(out), optional :: label ! item label character*(*), intent(out), optional :: units ! item units label integer, intent(out), optional :: itype ! item type character*(*), intent(out), optional :: author ! name of author

Home | Top |

Tables_of_contents

It is possible to retrieve an entire table of contents of any category of xplasma data type. Since the interface uses optional arguments, the user's code decides what type of table of contents list is to be fetched. In addition, there is special treatment of lists containing elements that identify profiles (list element name and integer value match name and id of profile). The following routine fetches the lengths of the ID lists for tables of contents: subroutine xplasma_num_items(s,ier, & author_only, & num_lists, num_plists, num_coords, num_grids, num_profs, num_blkbxs) ! return the total numbers of items of various types in xplasma ! container object. type (xplasma), pointer :: s integer, intent(out) :: ier ! error code -- only set if s not initialized character*(*), intent(in), optional :: author_only ! set this to restrict the list to items owned by the specified author integer, intent(out), optional :: num_lists ! no. of lists integer, intent(out), optional :: num_plists ! no. lists refering ! to profiles integer, intent(out), optional :: num_coords ! no. of coordinates integer, intent(out), optional :: num_grids ! no. of grids integer, intent(out), optional :: num_profs ! no. of profiles integer, intent(out), optional :: num_blkbxs ! no. of black boxes The following routine fetches the actual lists of ids of the indicated type. Note that ierr=60 is returned if a passed integer array meant to receive the contents list is too small... subroutine xplasma_contents(s,ier, & author_only, & id_lists, id_plists, id_coords, id_grids, id_profs, id_blkbxs) ! return sorted list(s) of ids of objects of indicated type(s). ! lists of lists, lists of profiles, etc. type (xplasma), pointer :: s integer, intent(out) :: ier ! error code, 0=OK character*(*), intent(in), optional :: author_only ! set this to restrict the list to items owned by the specified author integer, dimension(:), intent(out), optional :: id_lists ! lists integer, dimension(:), intent(out), optional :: id_plists ! lists that ! refer to profiles integer, dimension(:), intent(out), optional :: id_coords ! coordinates integer, dimension(:), intent(out), optional :: id_grids ! grids integer, dimension(:), intent(out), optional :: id_profs ! profiles integer, dimension(:), intent(out), optional :: id_blkbxs ! black boxes The returned contents lists are sorted in alphabetic order of the names corresponding to each item ID.

Home | Top |

Lists

The LIST is one of the data types supported within xplasma. Each list has a name, and contains a named set of elements. Each element in addition to its name can have an integer, a floating point value, and a character string associated with it. Element names must be unique within the list but are not part of and do not conflict with the xplasma namespace-- indeed, one of the uses of lists is to gather the names and IDs of related xplasma data items. Some example applications of lists: -- storage of commonly referenced data, such as the plasma magnetic axis location; -- storage of scalar data, such as plasma ion species lists with the Z and A of each ion species specified. -- storage of lists of names and IDs of useful sets of xplasma profiles. If a list name is known, use the following call to get its integer ID: call xplasma_listId(s,name,id) ! look up a LIST Methods for accessing list data are described in the subtopics.

Home | Top |

xplasma_list_info

This routine optionally returns the size of a list and labeling information for the list (the list itself, not the member elements): subroutine xplasma_list_info(s,id,ier, & nelems,name,label,units,author) ! ! get the size of an existing list ! type (xplasma), pointer :: s integer, intent(in) :: id ! id of list item integer, intent(out) :: ier ! completion code integer, intent(out), optional :: nelems ! no. of list elements in list character*(*), intent(out), optional :: name character*(*), intent(out), optional :: label character*(*), intent(out), optional :: units character*(*), intent(out), optional :: author

Home | Top |

xplasma_getList_size

To just get the size of a list: subroutine xplasma_getList_size(s,id,nelems,ier) ! ! get the size of an existing list ! type (xplasma), pointer :: s integer, intent(in) :: id ! id of list item integer, intent(out) :: nelems ! no. of list elements in list integer, intent(out) :: ier ! completion code

Home | Top |

xplasma_getList_names

To get the names of list elements, and, optionally, element data and/or global labels for lists, this routine can be used: subroutine xplasma_getList_names(s,id,enames,ier, & name,label,units,author,ivals,r8vals,chvals) ! ! get the element names from an existing list ! optional arguments allow additional data to be fetched as well. ! type (xplasma), pointer :: s integer, intent(in) :: id ! id of list item character*(*), dimension(:), intent(out) :: enames ! the names... integer, intent(out) :: ier ! completion code character*(*), intent(out), optional :: name ! name (of whole list) character*(*), intent(out), optional :: label ! label (for whole list) character*(*), intent(out), optional :: units ! units label (whole list) character*(*), intent(out), optional :: author ! author integer, intent(out), dimension(:), optional :: ivals ! integer values real*8, intent(out), dimension(:), optional :: r8vals ! real*8 values character*(*), intent(out), dimension(:), optional :: chvals ! str vals

Home | Top |

xplasma_getList_ivals

subroutine xplasma_getList_ivals(s,id,ivals,ier) ! ! get integer values in list (r4 precision) ! type (xplasma), pointer :: s integer, intent(in) :: id ! id of list item integer, dimension(:), intent(out) :: ivals ! the integer values integer, intent(out) :: ier ! completion code

Home | Top |

xplasma_getList_r8vals

subroutine xplasma_getList_r8vals(s,id,r8vals,ier) ! ! get real*8 values in list ! type (xplasma), pointer :: s integer, intent(in) :: id ! id of list item real*8, dimension(:), intent(out) :: r8vals ! the real*8 values integer, intent(out) :: ier ! completion code 4 xplasma_getList_r4vals subroutine xplasma_getList_r4vals(s,id,r4vals,ier) ! ! get floating point values in list (r4 precision) ! type (xplasma), pointer :: s integer, intent(in) :: id ! id of list item real, dimension(:), intent(out) :: r4vals ! the floating point values integer, intent(out) :: ier ! completion code

Home | Top |

xplasma_getList_chvals

subroutine xplasma_getList_chvals(s,id,chvals,ier) ! ! get character string values in list ! type (xplasma), pointer :: s integer, intent(in) :: id ! id of list item character*(*), dimension(:), intent(out) :: chvals ! the character string values integer, intent(out) :: ier ! completion code

Home | Top |

Coordinates

The COORDINATE is one of the data types supported within xplasma. It contains little actual data-- it exists mainly as a mechanism to define the semantics of grids, with the following associations: (a) profiles are defined over grids; (b) grids are associated with coordinates. Each specific grid is associated with a single coordinate. Multiple grids can be associated with the same coordinate. Interpolation of profiles is organized by means of coordinates. Like all xplasma data items, coordinates have names, labels, physical units, and authors. Additional attributes of coordinates are: (a) whether or not a coordinate is periodic; (b) the minimum and maximum value (range) of a coordinate. When an xplasma object is initialized, several coordinates are predefined; their IDs are public parameters supplied by xplasma f90 modules: integer, parameter, public :: xplasma_rho_coord = 1 ! radial flux coord. integer, parameter, public :: xplasma_theta_coord = 2 ! poloidal angle coord. integer, parameter, public :: xplasma_phi_coord = 3 ! toroidal angle coord. integer, parameter, public :: xplasma_R_coord = 4 ! R coord integer, parameter, public :: xplasma_Z_coord = 5 ! Z coord integer, parameter, public :: xplasma_rhox_coord =6 ! "rho" extrapolation integer, parameter, public :: xplasma_thx_coord = 7 ! "theta" extrapolation integer, parameter, public :: xplasma_B_coord = 8 ! mod(B) grid integer, parameter, public :: xplasma_vpv_coord = 9 ! vpll/v coord. These parameters are frequently used, e.g. to identify the coordinates of input arguments in multivariate profile interpolation calls. The above list is sufficient for some applications. However, codes may define additional coordinates. For example, in the NUBEAM fast ion Monte Carlo model, a separate energy coordinate is defined for each fast ion species distribution function, because, the energy range desired for distribution functions varies from species to species, e.g. fusion product ion species vs. beam ion species. Several routines exist for making inquiries about coordinates, as shown in the subtopics.

Home | Top |

xplasma_coord_info

subroutine xplasma_coord_info(s,id,ier, & ngrids,periodic,xmin,xmax,name,label,units,author) type (xplasma), pointer :: s integer, intent(in) :: id ! coordinate object id integer, intent(out) :: ier ! completion code, 0=OK integer, intent(out), optional :: ngrids ! # of grid discretizations logical, intent(out), optional :: periodic ! periodicity flag real*8, intent(out), optional :: xmin ! min value real*8, intent(out), optional :: xmax ! max value character*(*), intent(out), optional :: name character*(*), intent(out), optional :: label character*(*), intent(out), optional :: units character*(*), intent(out), optional :: author

Home | Top |

xplasma_coord_gridId

It is possible to retrieve the IDs of specific grids discretizing a coordinate. This is probably not how it will be done in applications, which are more likely to find grids by starting from a profile ID. Nevertheless, this public interface is supplied. The value of the input argument "indx" should be between 1 and "ngrids", the upper limit being the number of grids known to discretize the coordinate (see the xplasma_coord_info call). subroutine xplasma_coord_gridId(s,id,indx,idgrid,ier) ! get grid id from coordinate grid list index type (xplasma), pointer :: s integer, intent(in) :: id ! coordinate object id integer, intent(in) :: indx ! which grid is desired integer, intent(out) :: idgrid ! grid id of desired grid integer, intent(out) :: ier ! completion code, 0=OK

Home | Top |

xplasma_coord_isPeriodic

This public interface is provided; the periodicity attribute can also be obtained through an optional argument in the xplasma_coord_info call. subroutine xplasma_coord_isPeriodic(s,id,periodic,ier) ! get information whether coordinate object is a periodic angle coord. type (xplasma), pointer :: s integer, intent(in) :: id ! coordinate object id logical, intent(out) :: periodic ! T if this is a periodic coordinate integer, intent(out) :: ier ! completion code, 0=OK

Home | Top |

Grids

The GRID is one of the data types supported within xplasma. Each grid is a strict ascending sequence of numbers covering a specific range, and is associated with and discretizes a specific COORDINATE. Some coordinates have a prescribed range-- e.g. the normalized radial flux coordinate xplasma_rho_coord always covers the range 0 (the magnetic axis) to 1 (the plasma boundary). Grids over periodic coordinates cover a range of either [0,2pi] or [-pi,pi]. Some coordinates have their ranges defined by the first discretizing grid-- e.g. xplasma_R_coord and xplasma_Z_coord-- the dimensions of the [R,Z] box defining a computational region that will vary from tokamak to tokamak. With the exception of periodic coordinates, all grids discretizing a given coordinate must cover exactly the same range-- i.e. the first and last elements of the sequence of numbers defining the grid are constrained by the coordinate discretized by the grid. If the name of a grid is known and its ID is needed, the following call can be used: call xplasma_gridId(s,name,id) ! look up a GRID

Home | Top |

xplasma_grid_size

Get the size of a grid... subroutine xplasma_grid_size(s,id,nx,ier) ! get grid size type (xplasma), pointer :: s integer, intent(in) :: id ! grid object id integer, intent(out) :: nx ! grid size integer, intent(out) :: ier ! completion code, 0=OK

Home | Top |

xplasma_grid

Get the grid itself. The array "x" must precisely match the size of the grid. subroutine xplasma_grid(s,id,x,ier, ccwflag) ! get grid type (xplasma), pointer :: s integer, intent(in) :: id ! grid id object real*8, intent(out) :: x(:) ! the grid returned integer, intent(out) :: ier ! completion code, 0=OK logical, intent(in), optional :: ccwflag ! orientation flag ! default value is .TRUE., signifying counter-clockwise orientation If the grid is periodic, ccwflag=.FALSE. causes the grid to be returned in reverse order, corresponding e.g. to a clockwise drawn angle coordinate. The internal grid is always stored with clockwise orientation. The ccwflag=.FALSE. transform of a periodic grid theta(...) with ntheta points covering range [-pi:pi] is: theta_reverse(j) = -pi + (pi - theta(ntheta+1-j)) for j=1:ntheta

Home | Top |

xplasma_grid_info

This routine returns information on a grid and its associated coordinate. Other than the xplasma object pointer, the ID, and return status code, all arguments are optional, so, the caller can select the information desired. subroutine xplasma_grid_info(s,id,ier, & size,xmin,xmax,perio,coord,nrefs,name,label,units,author) ! get grid reference count (# of profile items using this grid) type (xplasma), pointer :: s integer, intent(in) :: id ! grid id object integer, intent(out) :: ier ! completion code, 0=OK integer, intent(out), optional :: size ! size of grid real*8, intent(out), optional :: xmin ! minimum grid value real*8, intent(out), optional :: xmax ! maximum grid value logical, intent(out), optional :: perio ! T for periodic grids integer, intent(out), optional :: coord ! coordinate associated w/grid integer, intent(out), optional :: nrefs ! no. of references to grid character*(*), intent(out), optional :: name character*(*), intent(out), optional :: label character*(*), intent(out), optional :: units character*(*), intent(out), optional :: author

Home | Top |

Profiles

The PROFILE is one of the data types supported within xplasma. Indeed, xplasma was largely invented to support the storage, retrieval, and interpolation of profiles used in plasma simulations. Profiles are defined over grids (and hence over coordinates as well). For purposes of interpolation, it is generally enough to know the coordinates over which a profile is defined, but, it is of course possible to retrieve the underlying grids, and the original un- interpolated data, if desired. Profiles can be 1d, 2d, or 3d-- i.e. defined over 1, 2, or 3 grids (coordinates). The interpolation method for a profile is defined by the creator of the profile. The possibilities are the methods supported by the PSPLINE NTCC module-- piecewise linear (continuous), cubic Hermite (continuous and continuously once differentiable), and cubic spline (continuous and continuously twice differentiable along any coordinate). In addition, XPLASMA allows zonal step function data to be defined. For more information on interpolation, see the PSPLINE NTCC web page, http://w3.pppl.gov/NTCC/PSPLINE. There is a generic interface for profile interpolation: xplasma_eval_prof. Using this interface, retrieval of profile information basically comes down to making an appropriate xplasma_eval_prof call. This method will be described in detail. If the name of a profile is known, the following xplasma call retrieves its ID: call xplasma_profId(s,name,id) ! look up a PROFILE

Home | Top |

xplasma_prof_info

The following call allows access to detailed information on a given profile, as identified by its ID. Many of the arguments are self- explanatory, but further information on those that might not be is given below. subroutine xplasma_prof_info(s,id,ier, & rank,splineType,gridId1,gridId2,gridId3,profId1,gridType,counter, & name,label,units,author) ! base argauments in/out type (xplasma), pointer :: s integer, intent(in) :: id ! profile object id integer, intent(out) :: ier ! completion code, 0=OK !--------------------------------------------------- ! select desired information with optional arguments... integer, intent(out), optional :: rank ! rank integer, intent(out), optional :: splineType ! -1 for step function; 0 for piecewise linear, ! 1 for C1 Hermite, 2 for C2 cubic spline integer, intent(out), optional :: gridId1 ! id of 1st grid integer, intent(out), optional :: gridId2 ! id of 2nd grid (or zero) integer, intent(out), optional :: gridId3 ! id of 3rd grid (or zero) integer, intent(out), optional :: profId1 ! id of associated profile ! (sometimes f(R,Z) has an associated f(rho,theta) profile available, ! and vice versa). integer, intent(out), optional :: gridType ! generic grid type code ! 0=unknown or mixed ! 1=flux coords (rho) or (rho,theta) [phi someday] ! 2=cylindric coordinates (R,Z) [phi someday] integer, intent(out), optional :: counter ! profile counter ! each new version of this profile gets a new counter value. character*(*), intent(out), optional :: name character*(*), intent(out), optional :: label character*(*), intent(out), optional :: units character*(*), intent(out), optional :: author Notes on argumentes: rank -- the dimensionality of the profile: 1 for 1d, 2 for 2d, 3 for 3d. profId1 -- ID for quantity defined over "alternate" grids. For some profiles there are two versions-- one defined over flux coordinates and one defined over [R,Z] coordinates. If for the input profile ID an alternate version exists, the alternate version ID can be returned with this argument. When interpolations are performed, if the coordinates supplied are not appropriate for a given profile ID, the profile's alternate ID, if available, will be tried before giving up. gridType -- this can be used to determine if the profile is defined over flux coordinates or cylindrical coordinates. The following public parameters are available for reference: integer, parameter, public :: xplasma_flux_coords = 1 ! generic flux coord. integer, parameter, public :: xplasma_cyl_coords = 2 ! generic cyl. coord.

Home | Top |

xplasma_prof_gridInfo

An alternate method of acquiring a profile's grid information is shown here; xplasma_prof_info can also be used. subroutine xplasma_prof_gridInfo(s,id,icoord,idgrid,ierr, & id_actual) type (xplasma), pointer :: s integer, intent(in) :: id ! id of profile about which info is sought integer, intent(in) :: icoord ! coordinate sought integer, intent(out) :: idgrid ! grid over this coordinate, or zero ! zero means profile identified by "id" is not a function of the ! specified coordinate; this is not considered an error. integer, intent(out) :: ierr ! error status code returned, 0=OK ! errors: profile id is invalid; coordinate id is invalid... integer, intent(out), optional :: id_actual ! "actual" profile id ! explanation: for some quantities there are two representations, ! e.g. Bphi(R,Z) and Bphi(rho,theta). The passed id can refer to ! either of these; the coordinate sought is found for the appropriate ! representation. Thus, if id points to Bphi(R,Z) and info on a rho ! grid is sought, id_actual (if present) will be set to the id of ! Bphi(rho,theta).

Home | Top |

xplasma_eval_prof

xplasma_eval_prof is a generic interface that can be used in any of the following modes: (1) interpolate 1d, 2d, or 3d profiles to given target coordinates. (2) interpolate 1d, 2d, or 3d profiles using previously calculated lookup information. (3) retrieve the original profile data (no interpolation). Each type of use is considered in the subtopics.

Home | Top |

standard_interpolation

Interpolations are supported on 1d, 2d, and 3d profiles, and, in a single call it is possible to perform interpolations on 1 profile or multiple profiles, at 1 target location or at a vector of target locations. Function values or derivatives can be returned. Angle coordinates may optionally be reversed with transformations theta -> 2pi - theta. When the rank of the profiles being evaluated exceeds one, the coordinate arguments can be given in any order, with grid or coordinate ID information given to indicate which is which. Generally for non-periodic coordinates it is an error to provide target coordinate data that is out of bounds; this behavior can be overridden with an optional argument "force_bounds". The number of out of bounds target points can be returned in the optional output argument "n_out_of_bounds". The relative tolerance for out-of-bounds tests is "bdytol", available with the call: call xplasma_global_info(s,ierr, bdytol=bdytol); interpolation target coordinates that exceed the coordinate minimum xmin or maximum xmax by more than bdytol*[xmax-xmin] are considered out of bounds. The result "ans" returned is a scalar if there is a single profile id and a scalar target point. It is a vector if there is either a list of profile ids or a vector of target points. If there is both a list of profile ids and a vector of target points, ans is a 2d array with size(ans,1) matching the target vector dimension, and size(ans,2) matching the number of profile ids; ans(:,1) will be the results of the evaluation of the 1st profile; ans(2,:) will be the results for all profiles at the 2nd target coordinate location. Here are some example calls: integer :: id1,id2(2) real*8 :: x,xvec(3),yvec(3) real*8 :: ans00,ans2(2),ans3(3),ans2d(3,2) ! 1 id, 1 target, eval 1st derivative call xplasma_eval_prof(s,id1,x,ans00,ier, ideriv1=1) ! 2 ids, 1 target, eval profile value call xplasma_eval_prof(s,id2,x,ans2,ier) ! 1 id, vector target, eval profile values call xplasma_eval_prof(s,id,xvec,ans3,ier) ! 2 ids, vector target, eval value of 1st profile, derivative of 2nd call xplasma_eval_prof(s,id2,xvec,ans32,ier, ideriv1s = (/0,1/)) ! 2d profile evaluation (no derivatives; xvec is "rho"; yvec is "theta"): call xplasma_eval_prof(s,id2, & xplasma_rho_coord,xvec, xplasma_theta_coord,yvec, ans32, ier) When the 2d or higher evaluation routine is called, it is possible for some of the profiles evaluated to be 1d, provided that the coordinate scalar or vector argument needed for evaluation of the 1d profile is present. What follows is the full interface for the calls mapped to when multiple ids and a vector target is provided to xplasma_eval_prof. For 1d profile evaluation: subroutine xplasma_eval_1dprofsxs(s,ids,xs,ans,ier, & ideriv1,ideriv1s,ccwflag1,force_bounds,n_out_of_bounds) ! evaluate multiple profiles f(x) 1d at a vector of points type (xplasma), pointer :: s integer, dimension(:), intent(in) :: ids ! profile ids real*8, dimension(:), intent(in) :: xs ! evaluation vector real*8, dimension(:,:), intent(out) :: ans ! result of evaluations integer, intent(out) :: ier ! completion code 0=OK ! ans(1:size(xs),1) -- result of eval of profile ids(1) ! ans(1:size(xs),2) -- result of eval of profile ids(2) ...etc... ! default: 0= fcn value integer, intent(in), optional :: ideriv1 ! derivative control ! 1 for df/dx; 2 for d2f/dx2; 3 for d3f/dx3 ! 2 & 3 available only for C2 spline fits integer, intent(in), dimension(:), optional :: ideriv1s ! as ideriv1 but specified separately for each profile ! default: T -- CCW orientation, no CW->CCW transform logical, intent(in), optional :: ccwflag1 ! default: F -- T to force all points in bounds with min & max logical, intent(in), optional :: force_bounds ! optional output: return no. of target points out of range integer, intent(out), optional :: n_out_of_bounds .............. For 2d profile evaluation: subroutine xplasma_eval_2dprofsxs(s,ids,idx1,x1s,idx2,x2s,ans,ier, & ideriv1,ideriv1s,ideriv2,ideriv2s, & ccwflag1,ccwflag2,force_bounds,n_out_of_bounds) ! evaluate multiple profiles f(x1,x2) 2d at a vector of points type (xplasma), pointer :: s integer, dimension(:), intent(in) :: ids ! profile ids integer :: idx1 ! id of x1 grid or coord. real*8, dimension(:), intent(in) :: x1s ! evaluation vector x1 integer :: idx2 ! id of x2 grid or coord. real*8, dimension(:), intent(in) :: x2s ! evaluation vector x2 real*8, dimension(:,:), intent(out) :: ans ! result of evaluations integer, intent(out) :: ier ! completion code 0=OK ! size(x1s)=size(x2s)=size(ans,1) expected... ! ans(1:size(x1s),1) -- result of eval of profile ids(1) ! ans(1:size(x1s),2) -- result of eval of profile ids(2) ...etc... ! default: 0= fcn value integer, intent(in), optional :: ideriv1 ! derivative control ! 1 for df/d[x1]; 2 for d2f/d[x1]2; 3 for d3f/d[x1]3 ! 2 & 3 available only for C2 spline fits integer, intent(in), dimension(:), optional :: ideriv1s ! as ideriv1, 1 per evaluation profile id ! default: 0= fcn value integer, intent(in), optional :: ideriv2 ! derivative control ! 1 for df/d[x2]; 2 for d2f/d[x2]2; 3 for d3f/d[x2]3 ! 2 & 3 available only for C2 spline fits integer, intent(in), dimension(:), optional :: ideriv2s ! as ideriv2, 1 per evaluation profile id ! default: T -- CCW orientation, no CW->CCW transform logical, intent(in), optional :: ccwflag1 ! for x1 logical, intent(in), optional :: ccwflag2 ! for x2 ! (these are ignored except for theta and phi angle coordinates ! default: F -- T to force all points in bounds with min & max logical, intent(in), optional :: force_bounds ! optional output: return no. of target points out of range integer, intent(out), optional :: n_out_of_bounds For 3d profile evaluation: subroutine xplasma_eval_3dprofsxs(s,ids,idx1,x1s,idx2,x2s,idx3,x3s, & ans,ier, & ideriv1,ideriv1s,ideriv2,ideriv2s,ideriv3,ideriv3s, & ccwflag1,ccwflag2,ccwflag3,force_bounds,n_out_of_bounds) ! evaluate multiple profiles f(x1,x2) 2d at a vector of points type (xplasma), pointer :: s integer, dimension(:), intent(in) :: ids ! profile ids integer :: idx1 ! id of x1 grid or coord. real*8, dimension(:), intent(in) :: x1s ! evaluation vector x1 integer :: idx2 ! id of x2 grid or coord. real*8, dimension(:), intent(in) :: x2s ! evaluation vector x2 integer :: idx3 ! id of x3 grid or coord. real*8, dimension(:), intent(in) :: x3s ! evaluation vector x3 real*8, dimension(:,:), intent(out) :: ans ! result of evaluations integer, intent(out) :: ier ! completion code 0=OK ! size(x1s)=size(x2s)=size(x3s)=size(ans,1) expected... ! ans(1:size(x1s),1) -- result of eval of profile ids(1) ! ans(1:size(x1s),2) -- result of eval of profile ids(2) ...etc... ! default: 0= fcn value integer, intent(in), optional :: ideriv1 ! derivative control ! 1 for df/d[x1]; 2 for d2f/d[x1]2; 3 for d3f/d[x1]3 ! 2 & 3 available only for C2 spline fits integer, intent(in), dimension(:), optional :: ideriv1s ! as ideriv1, but separately specified for each evaluation ! default: 0= fcn value integer, intent(in), optional :: ideriv2 ! derivative control ! 1 for df/d[x2]; 2 for d2f/d[x2]2; 3 for d3f/d[x2]3 ! 2 & 3 available only for C2 spline fits integer, intent(in), dimension(:), optional :: ideriv2s ! as ideriv2, but separately specified for each evaluation ! default: 0= fcn value integer, intent(in), optional :: ideriv3 ! derivative control ! 1 for df/d[x3]; 2 for d2f/d[x3]2; 3 for d3f/d[x3]3 ! 2 & 3 available only for C2 spline fits integer, intent(in), dimension(:), optional :: ideriv3s ! as ideriv3, but separately specified for each evaluation ! default: T -- CCW orientation, no CW->CCW transform logical, intent(in), optional :: ccwflag1 ! for x1 logical, intent(in), optional :: ccwflag2 ! for x2 logical, intent(in), optional :: ccwflag3 ! for x3 ! (these are ignored except for theta and phi angle coordinates ! default: F -- T to force all points in bounds with min & max logical, intent(in), optional :: force_bounds ! optional output: return no. of target points out of range integer, intent(out), optional :: n_out_of_bounds

Home | Top |

interpolation_using_prior_lookup

Every interpolation involves two steps: zone lookup, and evaluation. Especially in the case of profiles defined over unevenly spaced grids, the zone lookup is a significant portion of the computational cost of the interpolation. Sometimes it is possible, and worth the effort, to pre-evaluate zone lookup and reuse this information through several interpolation calls. Xplasma provides a way to do this. In order for the user application to take advantage of this capability, it needs to declare special data structures, given public definitions in the xplasma modules, to store the results of a zone lookup calculation in such a way that it can be passed on to an xplasma interpolation routine built for this purpose. Such a declaration will look something like this: type (xpeval) :: x1_intrp,x2_intrp,x3_intrp Then, a generic interface xplasma_x_lookup can be used which will accept evaluation of a lookup either for a single scalar value or for a vector of values-- see the subtopic for information on the lookup pre-evaluation routines "xplasma_x_lookup". Once the lookups have been evaluated, xplasma_eval_prof can be called, supplying this information, to perform actual interpolations. Each xpeval item contains the lookup information either for a single point on a single coordinate, or a vector of points on a single coordinate. The evaluation routines expect to do a vector evaluation; at least one of the xpeval items must contain a vector of n lookup results. Those with only scalar lookup data will be replicated n times on evaluation. xplasma_eval_prof will make the following call for interpolation of a 1d profile: subroutine xplasma_xpeval_1dprof(s,id,xinfo,ans,ier, ideriv) ! evaluate a single 1d profile function f(x) at a vector of ! target points for which lookup has already been executed ! and stored in "xinfo". ! the x axis grid id of the profile and of the xinfo must match ! the size of the output and the no. of points in the xinfo must ! match. ! xinfo was set up by a prior xplasma_x_lookup call. type(xplasma), pointer :: s integer, intent(in) :: id ! 1d function to evaluate type (xpeval) :: xinfo ! prepared interpolation information real*8, dimension(:), intent(out) :: ans ! interpolation result integer, intent(out) :: ier ! status code, 0=OK integer, intent(in), optional :: ideriv ! derivative selection The following call is generated for interpolation of a 2d profile: subroutine xplasma_xpeval_2dprof(s,id,xinfo1,xinfo2,ans,ier, & ideriv1, ideriv2) type(xplasma), pointer :: s integer, intent(in) :: id ! 2d function to evaluate type (xpeval) :: xinfo1,xinfo2 ! prepared interpolation information sets real*8, dimension(:), intent(out) :: ans ! interpolation result integer, intent(out) :: ier ! status code, 0=OK integer, intent(in), optional :: ideriv1 ! derivative selection, x1 integer, intent(in), optional :: ideriv2 ! derivative selection, x2 And the following call is generated for interpolation of a 3d profile: subroutine xplasma_xpeval_3dprof(s,id,xinfo1,xinfo2,xinfo3,ans,ier, & ideriv1, ideriv2, ideriv3) type(xplasma), pointer :: s integer, intent(in) :: id ! 3d function to evaluate type (xpeval) :: xinfo1,xinfo2,xinfo3 ! prepared interpolation information sets real*8, dimension(:), intent(out) :: ans ! interpolation result integer, intent(out) :: ier ! status code, 0=OK integer, intent(in), optional :: ideriv1 ! derivative selection, x1 integer, intent(in), optional :: ideriv2 ! derivative selection, x2 integer, intent(in), optional :: ideriv3 ! derivative selection, x3 In all of these calls, the optional arguments default to zero-- meaning, interpolate the function value, not a derivative. ideriv*=1 means to evaluate the 1st derivative along the indicated coordinate. ideriv*=2 means to evaluate the 2nd derivative along the indicated coordinate. With these methods one interpolates one profile at a time.

Home | Top |

lookup_routines

These routines must be called to load the xpeval structures BEFORE calling one of the xplasma_xpeval routines (via xplasma_eval_prof): When done it is important to FREE MEMORY associated with the xpeval structure, called "xinfo" in the interfaces below. Failure to free memory after use will result in memory leaks (pointers are involved). !------------------------------------------------------ subroutine xpeval_free(xinfo) type(xpeval) :: xinfo ! deallocate & clean up xinfo !------------------------------------------------------ interface xplasma_x_lookup module procedure xplasma_x_lookup1 module procedure xplasma_x_lookupn end interface subroutine xplasma_x_lookup1(s,idx,x,xinfo,ier, & ccwflag,force_bounds,n_out_of_bounds) ! do x lookup -- scalar x value type (xplasma), pointer :: s integer, intent(in) :: idx ! x grid (grid) id real*8, intent(in) :: x ! single scalar x value type (xpeval) :: xinfo ! *** lookup results integer, intent(out) :: ier ! status code, 0=OK ! default: T -- CCW orientation, no CW->CCW transform logical, intent(in), optional :: ccwflag ! default: F -- T to force all points in bounds with min & max logical, intent(in), optional :: force_bounds ! optional output: return no. of target points out of range integer, intent(out), optional :: n_out_of_bounds ............... subroutine xplasma_x_lookupn(s,idx,x,xinfo,ier, & ccwflag,force_bounds,n_out_of_bounds) ! do x lookup -- scalar x value type (xplasma), pointer :: s integer, intent(in) :: idx ! x grid (grid) id real*8, intent(in), dimension(:) :: x ! vector of x values type (xpeval) :: xinfo ! *** lookup results integer, intent(out) :: ier ! status code, 0=OK ! default: T -- CCW orientation, no CW->CCW transform logical, intent(in), optional :: ccwflag ! default: F -- T to force all points in bounds with min & max logical, intent(in), optional :: force_bounds ! optional output: return no. of target points out of range integer, intent(out), optional :: n_out_of_bounds ............... Some further notes on arguments: idx -- this must be a grid ID, not a coordinate ID. x -- if scalar, the generic interface maps to xplasma_x_lookup1; if vector, the generic interface maps to xplasma_x_lookupn. xinfo -- dummy argument name for xpeval object, where the results of the interpolation lookup are stored. optional arguments: ccwflag -- if idx points to a grid over an angle coordinate, e.g. the poloidal angle flux coordinate, setting this flag to .FALSE. will cause the input data to be transformed by the formula theta -> 2pi - theta which would be appropriate if the caller's code wants to treat the poloidal angle coordinate as drawn clockwise around the flux surface (inside xplasma, the internal representation is always drawn counterclockwise). force_bounds -- force all input arguments to be in range using min and max function calls. This has no effect on periodic coordinate arguments, which always brought in range with 2*n*pi shifts as needed. n_out_of_bounds (out) -- number of x values not in bounds. Normally it is an error for out of bounds x values to be provided.

Home | Top |

data_retrieval

The original profile data can be retrieved using xplasma_eval_prof with the arguments shown for the following non-generic interfaces. In all cases, the arrays receiving the data must EXACTLY match the dimensioning of the profile being retrieved. The dimensioning can be reconstructed (i.e. use xplasma_prof_info to retrieve rank and grid IDs; use xplasma_grid_size to get sizes of individual grids, which are also the correct profile array dimensions). Error codes will be set if there is a mismatch in array dimension sizes or array rank; if the return code "ier" is set to a non-zero value, use: call xplasma_error(s,ier,6) to cause the error report to be printed on fortran unit 6 (stdout). Optional arguments "ccwflag*" are used to specify orientation of periodic coordinates. These have the same meaning as the corresponding arguments used when the profile is created. Setting ccwflag<n> to .FALSE. will reverse the indexing order of the data along the <n>th dimension, if that dimension corresponds to a periodic coordinate. If the <n>th coordinate is not periodic, ccwflag<n> is ignored. --------------- Retrieve 1d profile (this method in the xplasma_eval_prof generic interface): subroutine xplasma_getprof_1data(s,id,zdata,ier, & ccwflag1) ! return the original data associated with this profile type (xplasma), pointer :: s integer, intent(in) :: id ! profile id real*8, dimension(:), intent(out) :: zdata ! data returned integer, intent(out) :: ier ! completion code 0=OK logical, intent(in), optional :: ccwflag1 ! CCW flag (default T) Retrieve 2d profile (this method in the xplasma_eval_prof generic interface): subroutine xplasma_getprof_2data(s,id,zdata,ier, & ccwflag1,ccwflag2) ! return the original data associated with this profile type (xplasma), pointer :: s integer, intent(in) :: id ! profile id real*8, dimension(:,:), intent(out) :: zdata ! data returned integer, intent(out) :: ier ! completion code 0=OK logical, intent(in), optional :: ccwflag1 ! dim. 1 CCW flag (default T) logical, intent(in), optional :: ccwflag2 ! dim. 2 CCW flag (default T) Retrieve 3d profile (this method in the xplasma_eval_prof generic interface): subroutine xplasma_getprof_3data(s,id,zdata,ier, & ccwflag1,ccwflag2,ccwflag3) ! return the original data associated with this profile type (xplasma), pointer :: s integer, intent(in) :: id ! profile id real*8, dimension(:,:,:), intent(out) :: zdata ! data returned integer, intent(out) :: ier ! completion code 0=OK logical, intent(in), optional :: ccwflag1 ! dim. 1 CCW flag (default T) logical, intent(in), optional :: ccwflag2 ! dim. 2 CCW flag (default T) logical, intent(in), optional :: ccwflag3 ! dim. 3 CCW flag (default T)

Home | Top |

xplasma_RZeval_2d

This is a specialized routine for evaluating R(rho,theta) and/or Z(rho,theta), with automatic failover to extrapolated profiles of R and Z for rho > 1, when these are available. In general, if xplasma has scrap off layer information, i.e. limiter locations, it will, when updating the MHD equilibrium, create extrapolated (rho,theta) -> (R,Z) map which however is not differentiable across the rho=1 boundary. This routine gives access to both the original and extrapolated R and Z in the context of a single call. subroutine xplasma_RZeval_2d(s,ids,idx1,x1s,idx2,x2s,ans,ier, & ideriv1,ideriv1s,ideriv2,ideriv2s, & ccwflag1,ccwflag2,force_bounds,n_out_of_bounds) ! use xplasma_eval_2dprofsxs to ! evaluate multiple profiles f(x1,x2) 2d at a vector of points ! IF all the profiles are "R" and "Z", ! and IF there is a scrape-off region, ! split the evaluation so that points inside the plasma use ! the standard R & Z, and points outside use the extrapolated ! profiles. type (xplasma), pointer :: s integer, dimension(:), intent(in) :: ids ! profile ids integer :: idx1 ! id of x1 grid or coord. real*8, dimension(:), intent(in) :: x1s ! evaluation vector x1 integer :: idx2 ! id of x2 grid or coord. real*8, dimension(:), intent(in) :: x2s ! evaluation vector x2 real*8, dimension(:,:), intent(out) :: ans ! result of evaluations integer, intent(out) :: ier ! completion code 0=OK ! size(x1s)=size(x2s)=size(ans,1) expected... ! ans(1:size(x1s),1) -- result of eval of profile ids(1) ! ans(1:size(x1s),2) -- result of eval of profile ids(2) ...etc... ! default: 0= fcn value integer, intent(in), optional :: ideriv1 ! derivative control ! 1 for df/d[x1]; 2 for d2f/d[x1]2; 3 for d3f/d[x1]3 ! 2 & 3 available only for C2 spline fits integer, intent(in), dimension(:), optional :: ideriv1s ! as ideriv1, 1 per evaluation profile id ! default: 0= fcn value integer, intent(in), optional :: ideriv2 ! derivative control ! 1 for df/d[x2]; 2 for d2f/d[x2]2; 3 for d3f/d[x2]3 ! 2 & 3 available only for C2 spline fits integer, intent(in), dimension(:), optional :: ideriv2s ! as ideriv2, 1 per evaluation profile id ! default: T -- CCW orientation, no CW->CCW transform logical, intent(in), optional :: ccwflag1 ! for x1 logical, intent(in), optional :: ccwflag2 ! for x2 ! (these are ignored except for theta and phi angle coordinates ! default: F -- T to force all points in bounds with min & max logical, intent(in), optional :: force_bounds ! optional output: return no. of target points out of range integer, intent(out), optional :: n_out_of_bounds

Home | Top |

Generic_blackBoxes

The BLACK BOX is one of the data types supported within xplasma. A black box is a storage mechanism for data not fitting into other types. It consists of the following: a) a user defined integer "type" code; b) a user specified 1d array or buffer of any size, of integers; c) a user specified 1d array or buffer of any size, of 64 bit (real*8) floating point numbers. The black box is used within xplasma for a number of purposes-- caches for flux surface integration, data to support rapid methods for evaluation of coordinate transformations, "MCgrid" data, ... Integer black box type codes in the range 0 to 101 are used by xplasma library software; it is recommended that user defined black boxes stay away from using type codes in this range. In order to avoid unnecesary and costly copying of large arrays, the black box data access allows pointers to the black box integer and floating point array data to be returned. This means however that the contents of black box datasets can be modified directly by assignment of (pointer) array elements, without going through an interface call. User caution is advised.

Home | Top |

xplasma_blackBox_info

The black box type code, buffer sizes, and generic xplasma item labeling can be retrieved with this call. Except for the status code, output arguments are optional, allowing the caller to control what information is to be returned. subroutine xplasma_blackBox_info(s,id,ier, & type,isize,r8size,name,label,units,author) ! ! get the size of an existing list ! type (xplasma), pointer :: s integer, intent(in) :: id ! id of black box item integer, intent(out) :: ier ! completion code integer, intent(out), optional :: type ! "type" of black box ! generally, meaning of iitype is user defined... integer, intent(out), optional :: isize ! number of integer words integer, intent(out), optional :: r8size ! number of floating pt words character*(*), intent(out), optional :: name character*(*), intent(out), optional :: label character*(*), intent(out), optional :: units character*(*), intent(out), optional :: author

Home | Top |

xplasma_blackBox_retrieve

Black box data, or pointers to data, can be retrieved with this call. As usual, most output arguments are optional: subroutine xplasma_blackBox_retrieve(s,id,ier, & itype,iarray,r8array,ia_ptr,r8a_ptr,name,label,units,author) ! retrieve blackBox data ! optional arguments; user controls what data is wanted. type (xplasma), pointer :: s integer, intent(in) :: id ! id of black box item integer, intent(out) :: ier ! completion code, 0=OK integer, intent(out), optional :: itype ! "type" of black box ! meaning is user defined. ! if copies of arrays are wanted: integer, dimension(:), intent(out), optional :: iarray real*8, dimension(:), intent(out), optional :: r8array ! if pointers to arrays are wanted: integer, dimension(:), pointer, optional :: ia_ptr real*8, dimension(:), pointer, optional :: r8a_ptr ! optional labeling info... character*(*), intent(out), optional :: name ! item name character*(*), intent(out), optional :: label ! item label character*(*), intent(out), optional :: units ! item units label character*(*), intent(out), optional :: author ! author

Home | Top |

Limiter_information

Xplasma supports the notion of an axisymmetric "limiter" or vessel wall. The region between the limiter and the core plasma contains plasma and neutral gas on open field lines and is referred to here as the scrape off layer. For reasons related to legacy code, xplasma supports two methods for defining an axisymmetric limiter. Therefore, the routine for retrieving limiter information supports both representations. However, the routines "xplasma_bdycon" and "xplasma_limcon" support methods for returning the plasma boundary and limiter represented as a closed contour (to good approximation), regardless of the internal representation. The interface xplasma_lim_distance allows quick access to the distance from any point in space to the nearest limiter point. Specific call interfaces are in the subtopics.

Home | Top |

xplasma_lim_info

subroutine xplasma_lim_info(s,ier, & itype, npts,rpts,zpts, & dist, & nlines, Rl, Zl, thl, & ncircs, Rc, Zc, rad) ! retrieve limiter information type(xplasma), pointer :: s integer, intent(out) :: ier integer, intent(out), optional :: itype ! itype=100 means piecewise linear closed contour (axisymmetric limiter) ! itype=101 means list of circles & infinite lines integer, intent(out), optional :: npts ! #pts in contour (itype=100 only) real*8, dimension(:), intent(out), optional :: rpts,zpts ! the closed contour; rpts(npts)=rpts(1) and zpts(npts)=zpts(1) (m). real*8, intent(out), optional :: dist ! itype=101 limiters only... ! if .ge.0.0d0, the plasma boundary + dist is considered a limiter ! if .lt.0.0d0-- no plasma boundary based limiter. integer, intent(out), optional :: nlines ! #lines in itype=101 limiter real*8, dimension(:), intent(out), optional :: Rl,Zl,thl ! point (m) through which line passes, and line orientation in DEGREES ! e.g. 45.0 means up and to the right... integer, intent(out), optional :: ncircs ! #circles in itype=101 limiter real*8, dimension(:), intent(out), optional :: Rc,Zc,rad ! center location and radius of each circle (m)

Home | Top |

xplasma_lim_RZminmax

subroutine xplasma_lim_rzminmax(s,zRmin,zRmax,zZmin,zZmax,ier, & itype) ! get the Rmin,Rmax,Zmin,Zmax of the vacuum region ! enclosed by the mechanical limiter ! optional: get a limiter type code also. type (xplasma), pointer :: s real*8, intent(out) :: zRmin,zRmax,zZmin,zZmax ! R & Z min & max (m) integer, intent(out) :: ier integer, intent(out), optional :: itype ! limiter representation ! within xplasma: 100 for piecewise contour; 101 for "circles and ! lines" possibly augmented by a fixed distance from the plasma ! boundary.

Home | Top |

xplasma_limcon

subroutine xplasma_limcon(s,rlim,zlim,inum_got,ier, & tol,maptype) ! return a closed contour of length size(rlim)=size(zlim) or less ! describing the limiter. ! if tol.le.0.0d0 -- the length of the description is size(rlim) exactly ! if tol.gt.0.0d0 -- length may be shortened to remove colinear points. ! also, if the limiter was originally given in contour form, and, ! size(rlim) is sufficient, the original specification will be ! returned. type (xplasma), pointer :: s real*8, dimension(:), intent(out) :: rlim,zlim ! limiter contour ! the sizes of these vectors must be the same. ! unless the original specification is being returned, the code ! requires a minimum size of 30 points. integer, intent(out) :: inum_got ! contour length returned ! if inum_got.lt.size(rlim), rlim(inum_got+1:size(rlim))=0 on exit. ! similarly for zlim. integer, intent(out) :: ier ! status code, 0=OK real*8, intent(in), optional :: tol ! tolerance specification ! if zero or negative, no shortening of the limiter description is ! attempted. If .gt. 0.0, adjacent segments that are colinear to within ! tol*[Rmax] are replaced by a single segment. DEFAULT: s%bdytol integer, intent(in), optional :: maptype ! mapping option ! 1=slowest but most exact; 2=intermediate; 3=bilinear interpolation ! 2 or 3 recommended. DEFAULT: 2

Home | Top |

xplasma_bdycon

Return a closed contour describing the plasma boundary; length of contour taken from size of vector arguments provided: subroutine xplasma_bdycon(s,rbdy,zbdy,ier) ! return a closed contour around the plasma boundary, similar to ! xplasma_limcon... type (xplasma), pointer :: s real*8, dimension(:), intent(out) :: rbdy,zbdy ! bdy contour ! the sizes of these vectors must be the same. integer, intent(out) :: ier

Home | Top |

xplasma_lim_distance

interface xplasma_lim_distance module procedure xplasma_lim_dist1 module procedure xplasma_lim_distn end interface subroutine xplasma_lim_dist1(s,r,z,d,ier, maptype, rlim1,zlim1) ! scalar version of xplasma_lim_distn -- axisymmetry assumed. type (xplasma), pointer :: s real*8, intent(in) :: R,Z ! input location (m) real*8, intent(out) :: d ! output distance from nearest point ! on limiter or wall (m). integer, intent(out) :: ier integer, intent(in), optional :: maptype ! see xplasma_lim_distn real*8, intent(out), optional :: rlim1,zlim1 ! nearest limiter point end subroutine xplasma_lim_dist1 subroutine xplasma_lim_distn(s,rvec,zvec,dist,ier, & maptype,rlim,zlim) ! find distance from each element of a vector of (R,Z) pairs ! to the nearest point on a limiter. ! optionally return the location of that point on the limiter ! in (R,Z). ! the routine assumes axisymmetry. Optional phi arguments may ! be added someday. type (xplasma), pointer :: s real*8, intent(in), dimension(:) :: rvec,zvec ! (R,Z) input vector real*8, intent(out), dimension(:) :: dist ! distance values returned integer, intent(out) :: ier integer, intent(in), optional :: maptype ! distance map option ! if it is required to compute the distance from the (R,Z) point to ! the plasma boundary, this specifies the option (for xplasma_bdfind). ! Default is the circle-fit option (2). (1) is slower but more ! precise; (3) is less accurate but would be faster if a bilinear ! distance map has already been computed. real*8, intent(out), dimension(:), optional :: rlim,zlim ! locations ! of nearest contact points on limiter, for each ! input location.

Home | Top |

MCgrid_Data

The MCgrid, or "Monte Carlo grid", is an irregular 2d spatial grid that was developed originally for capture of 2d binned data in a Monte Carlo calculation (NUBEAM). It is used for fast ion distribution functions and for certain spatially 2d profiles output by NUBEAM-- such as, beam halo thermal neutral sources, beam-target and beam-beam fusion rates. The grid is aligned with flux coordinates. It is constructed of "zone rows" that are equally spaced in rho=sqrt(Psi_tor/Psi_tor_at_bdy); each zone row is subdivided into a different number of zones equispaced in the equilibrium poloidal angle coordinate theta, with fewer subdivisions for zone rows near the axis, and more for zone rows in the edge. The result is a set of zones all with roughly equal volume and cross sectional area, as is desirable for consistency of Monte Carlo summation statistics. The number of poloidal zones per zone row is linear in the zone row index: typically, 4 in the 1st zone row adjacent to the magnetic axis, 8 in the next row out, 12 in the next row, etc. There are two variants, according as the underlying MHD equilibrium is updown symmetric, or updown asymmetric. As internally stored, the first row layout is this for the updown symmetric variant: _____ / | \ / 2 | 1 \ |___|___| with theta=0 on the large major radius side; increasing to theta=pi on the large major radius side covering the upper half of the plasma cross section above the midplane. The next row out would have 4 zones, the next 6 zones, etc. And this for the updown asymmetric variant: _____ / | \ / 4 | 3 \ |___|___| | | | \ 1 | 2 / \__|__/ with theta=-pi on the lower branch on the small major radius side, theta=0 on the large major radius side, and theta=pi on the upper branch on the small major radius side. The next zone row contains 8 zones, the next 12 zones, and so on. Poloidal zones are stored contiguously, with the poloidal zone index increasing with increasing theta coordinate, theta being oriented counter-clockwise in the plasma cross section drawn to the right of the machine axis of symmetry. This is how the data is stored internally. Note, however, that on retrieval of MCgrid data, there are options to reverse the storage order to be consistent with a clockwise oriented poloidal angle coordinate (as preferred by some codes), and, for both updown symmetric and updown asymmetric data, the start point for theta zone indexing can be specified as either 0, -pi, or the default (which is 0 for updown symmetric data and -pi for updown asymmetric data). These choices are controlled by optional arguments in the MCgrid data access routines. The MCgrid itself is a named "black box" item in the xplasma dataset; in principle there could be multiple MCgrids defined, but in practice there is usually only one. Each profiles defined over an MCgrid is itself a named "black box" item. When a MCgrid is set up, the volume of each MCgrid zone is computed, and this is itself stored as a profile over the MCgrid; the name is the MCgrid name with the suffix "_DVOL" appended. These integer parameters define the black box type codes used for MCgrids and their associated profiles: integer, parameter, public :: xplasma_bbgtype=17 ! MC grid type integer, parameter, public :: xplasma_bbftype=18 ! MC profile type Although information on these grids and profile could be obtained by using generic black box data access calls, it is better to use the calls specifically provided to support MCgrid items, which are described in the subtopics. Calls for access to MCgrid data are shown here; calls to create MCgrid data are given under the section heading Modifying_F95_Xplasma_Data.

Home | Top |

Finding_MCgrid_ID

Usually there is only one MCgrid per dataset, so, the optional argument id_mcgrid1 can be used in the public interface shown below. If the MCgrid is known to have been created by a named author, the search can be constrained by that name: e.g "author_only='NUBEAM'". subroutine xplasma_mcgrid_find(s,ierr, author_only, & id_mcgrid1,num_mcgrids,id_mcgrids) ! find MCgrid grid definitions that are available in the current ! xplasma-- usually there will be only one we think. type(xplasma), pointer :: s integer, intent(out) :: ierr ! status code returned (0=OK) character*(*), intent(in), optional :: author_only ! restrict search to MCgrid objects written by this author or code integer, intent(out), optional :: id_mcgrid1 ! MCgrid id returned, if... ! if exactly one exists. If none exist, id_mcgrid1=0 is returned; if ! >1 exists,id_mcgrid1=-<the number of MCgrids> is returned. integer, intent(out), optional :: num_mcgrids ! number of MCgrids found. integer, dimension(:), optional :: id_mcgrids ! MCgrid ids returned.

Home | Top |

MCgrid_info

The following interface enables access to details on the MCgrid. It should be noted that for historical reasons the MCgrid supports an extension beyond the plasma boundary, but, known applications of the MCgrid are restricted to the plasma core at present. Other than the error code, the return arguments are optional, so, the caller can select just the information that is needed. subroutine xplasma_mcgrid_info(s,id_mcgrid,ierr, & nzrow,nzrow_ext, nzons,nzons_ext, nth0,nphi, nths, udsym, & name,label) ! fetch information on xplasma_mcgrid grid type(xplasma), pointer :: s integer, intent(in) :: id_mcgrid ! id of MCgrid object to be queried integer, intent(out):: ierr ! status code 0=OK integer, intent(out), optional :: nzrow ! # of zone rows in plasma integer, intent(out), optional :: nzrow_ext ! # inside and outside integer, intent(out), optional :: nzons ! # of zones in plasma integer, intent(out), optional :: nzons_ext ! # inside and outside integer, intent(out), optional :: nth0 ! # of zones @axis cover [0:pi] integer, intent(out), optional :: nphi ! # of phi zones (1:axisymmetry) integer, dimension(:), intent(out), optional :: nths ! number of theta zones in each zone row logical, intent(out), optional :: udsym character*(*), intent(out), optional :: name character*(*), intent(out), optional :: label character*(*), intent(out), optional :: author ----------- It is important to notice that nth0 gives only the number of zones in the upper (or lower) halfplane of the first zone row, regardless of whether the underlying MCgrid is updown symmetric or updown asymmetric. Thus, an updown symmetric grid with 2 zones in the first row, and an updown asymmtric grid with 4 zones in the first row, would both return a value of 2 for nth0.

Home | Top |

MCgrid_zone_indexing_example

[A working example is in xplasma_debug_module.f90] integer :: id_mcgrid real*8 :: rho = 0.375d0 ! rho where index is wanted real*8 :: th = 0.2d0 ! theta angle where index is wanted real*8, parameter :: rhomax = 1.0d0 ! only looking at core plasma region... integer :: nrow,irow ! zone rows integer, dimension(:), allocatable :: nths,nthsum logical :: udsym ! updown symmetry flag integer :: indx call xplasma_find_mcgrid(s,ierr, id_mcgrid1=id_mcgrid) if(ierr.ne.0) [handle xplasma error] if(id_mcgrid.eq.0) [no MCgrid exists] if(id_mcgrid.lt.0) [multiple MCgrids exist] call xplasma_mcgrid_info(s,id_mcgrid,ierr, nzrow=nrow, udsym=udsym) allocate(nths(nrow),nthsum(0:nrow)) call xplasma_mcgrid_info(s,id_mcgrid,ierr, nths=nths) nthsum(0)=0 do irow=1,nrow nthsum(irow)=nthsum(irow-1)+nths(irow) enddo ! find row index using subroutine. The indexing is counting from -pi, ! regardless of the symmetry flag-- there is an implicit assumption that ! MCgrid profile data is fetched with this option!!! call mcindx(rho,th,udsym,nrows,rhomax,nths,nthsum,indx) !------------------------- subroutine mcindx(rho,th,udsym,nrow,rhomax,nths,nthsum,indx) ! private ! this routine assumes that the theta indexing is oriented ! counterclockwise and that it starts at -pi for each row, ! *even* for updown symmetric data. real*8, intent(in) :: rho,th ! flux coords in logical, intent(in) :: udsym ! updown symmetry flag integer, intent(in) :: nrow ! #rows real*8, intent(in) :: rhomax ! max rho in range integer, intent(in) :: nths(nrow) ! # theta zones / row integer, intent(in) :: nthsum(0:nrow) ! # in prior rows integer, intent(out) :: indx !---------------------------------------- integer :: irho,ith real*8 :: zth,zthlim real*8, parameter :: CPI = 3.1415926535897931D+00 real*8, parameter :: ZERO = 0.0d0 !---------------------------------------- indx = 0 if(udsym) then zth = -abs(th) zthlim = ZERO else zth = th zthlim = CPI endif irho = 1 + rho*nrow/rhomax if((irho.ge.1).and.(irho.le.nrow)) then ith = 1 + (zth+CPI)*nths(irho)/(zthlim+CPI) if((ith.ge.1).and.(ith.le.nths(irho))) then indx = nthsum(irho-1) + ith endif endif end subroutine mcindx

Home | Top |

MCgrid_zone_volumes

The following interface allows retrieval of the volumes of all the MCgrid individual zones: subroutine xplasma_mcgrid_volumes(s,id_mcgrid,vols,ierr, & lstart0_th,ccwflag_th) ! return the zone volumes associated with a MCgrid. Compute them ! if necessary. type(xplasma), pointer :: s integer, intent(in) :: id_mcgrid ! MC grid id real*8, dimension(:) :: vols ! the array of volume elements integer, intent(out) :: ierr ! status code (0=OK) ! theta indexing options logical, intent(in), optional :: lstart0_th ! default depends on symmetry logical, intent(in), optional :: ccwflag_th ! default: T ! lstart0_th=T means user's first theta zone lower bdy is 0; F means it ! is -pi. If defaulted: updown symmetric data assumed to start at 0; ! updown asymmetric data assumed to start at -pi. ! ccwflag_th=T means zone index increases as one goes along a row of ! zones at fixed radial index in a counter-clockwise direction; F means ! the opposite. T is the default.

Home | Top |

List_of_MCgrid_profiles

The following routine allows retrieval of a list of IDs of available profiles defined over a MCgrid. In typical usage, a first call might get the number of such profiles, followed by allocation of an integer array to hold the list of profile IDs, followed by a second call to actually fetch the IDs. subroutine xplasma_mcgrid_findProfs(s,id_mcgrid,ierr, & author_only, num_profs, id_profs) ! find profiles defined over given MCgrid type(xplasma), pointer :: s integer, intent(in) :: id_mcgrid ! MC grid id integer, intent(out) :: ierr ! status code returned (0=OK) character*(*), intent(in), optional :: author_only ! restrict search to MCgrid profiles written by this author or code integer, intent(out), optional :: num_profs ! number of profiles found. integer, dimension(:), optional :: id_profs ! profile ids returned.

Home | Top |

Information_on_MCgrid_profile

This routine returns information on an individual MCgrid profile. Except for the status code, all output arguments are optional, allowing the caller to select the desired information: subroutine xplasma_mcgrid_profInfo(s,id_mcprof,ierr, & id_mcgrid,nzons,irank,idim1,idim2, & gridId1,gridId2,normcode, & name,label,units,author) ! fetch information on a single profile defined over an MCgrid... type (xplasma), pointer :: s integer, intent(in) :: id_mcprof ! profile ID integer, intent(out) :: ierr ! status code returned: 0=OK integer, intent(out), optional :: id_mcgrid ! MCgrid ID integer, intent(out), optional :: nzons ! #spatial zones integer, intent(out), optional :: irank ! #non-spatial dimensions integer, intent(out), optional :: idim1,idim2 ! non-spatial dim. sizes ! grid IDs for non-spatial dimensions (if available) integer, intent(out), optional :: gridId1 integer, intent(out), optional :: gridId2 ! normalization code integer, intent(out), optional :: normcode !------------- character*(*), intent(out), optional :: name character*(*), intent(out), optional :: label character*(*), intent(out), optional :: units character*(*), intent(out), optional :: author For multidimensional profiles with velocity space coordinates (i.e. distribution functions), the arguments gridId1 and gridId2 can be used to retrieve the IDs of the velocity space coordinates used.

Home | Top |

Fetch_MCgrid_profile_data

This routine retrieves the actual profile data into a user provided array. An array with correct dimensioning must be supplied by the user. The last dimension of the user supplied array is the spatial dimension, matching the MCgrid size-- the value of the "nzons" argument returned by xplasma_mcgrid_info(...), for profiles defined just over the core plasma region. subroutine xplasma_mcgrid_getobj(s,id_p,ierr, & lstart0_th,ccwflag_th, & data_1d,data_2d,data_3d,label,units) ! retrieve previously stored MCgrid profile ! (see xplasma_mcgrid_putobj) type (xplasma), pointer :: s integer, intent(in) :: id_p ! MCgrid profile ID integer, intent(out) :: ierr ! exit status code (0=OK) ! theta indexing options logical, intent(in), optional :: lstart0_th ! default depends on symmetry logical, intent(in), optional :: ccwflag_th ! default: T ! lstart0_th=T means user's first theta zone lower bdy is 0; F means it ! is -pi. If defaulted: updown symmetric data assumed to start at 0; ! updown asymmetric data assumed to start at -pi. ! ccwflag_th=T means zone index increases as one goes along a row of ! zones at fixed radial index in a counter-clockwise direction; F means ! the opposite. !----------------- ! one of the optional arguments data_1d, data_2d, data_3d must ! be provided to receive the data. ! the provided data array sizes must match the stored data. real*8, dimension(:), intent(out), optional :: data_1d real*8, dimension(:,:), intent(out), optional :: data_2d real*8, dimension(:,:,:), intent(out), optional :: data_3d !----------------- character*(*), intent(out), optional :: name character*(*), intent(out), optional :: labels character*(*), intent(out), optional :: units character*(*), intent(out), optional :: author

Home | Top |

Initializing_F95_Xplasma_Data

The previous sections discussed methods for accessing data in an xplasma object that was already created. This and the following sections describe how to build up an xplasma object from scratch, and how to evolve it in a time dependent simulation. The following pieces of an xplasma dataset normally do not evolve in time; rather, they are initialized once at the start of the lifetime of an xplasma object: (a) the flux coordinate grids "rho" and "theta" over which equilibrium profiles are defined: flux surface label "rho" = sqrt(toroidal_flux/toroidal_flux_at_bdy) poloidal angle "theta" -- in the internal xplasma representation, moving in the direction of +theta at fixed rho traces out a flux surface in the counter-clockwise direction, when the flux surface cross section is drawn to the right of the tokamak axis of symmetry (R=0). (b) the location of an axisymmetric limiter or vacuum vessel wall, usually specified as a closed contour sequence of [R,Z] pairs. (c) the R and Z grids covering a rectangle in space that encloses the limiters and will enclose the core plasma at all times. (d) additional coordinates and grids as may be defined by the user, e.g. in velocity space; multiple grids may discretize the same coordinates. The items that do evolve over the lifetime of an xplasma object are: (e) the equilibrium over flux coordinates R(theta,rho), Z(theta,rho) -- the geometry of flux surfaces (m). g(rho) = R*|B_phi|, a flux surface constant, m*T; B_phi = bphi_ccw*(g/R); bphi_ccw=+1 if toroidal field points counter-clockwise -1 if clockwise, viewed from above Psi(rho) = poloidal flux function, Wb/rad, zero on axis, dPsi/drho > 0, with relation to the poloidal field Bpol = -jphi_ccw*(1/R)*grad(Psi); jphi_ccw=+1 if toroidal current flows counter-clockwise -1 if clockwise, viewed from above P(rho) = a profile representing the pressure used in the Grad- Shafranov equation to produce the equilibrium The derived profile BR(theta,rho), BZ(theta,rho), BPHI(theta,rho), BMOD(theta,rho) give spline approximations to the field components. (f) the equilibrium over (R,Z) coordinates Psi(R,Z), Wb/rad, Bpol = -jphi_ccw*(1/R)*grad(Psi) BR_RZ(R,Z), BZ_RZ(R,Z), BPHI_RZ(R,Z), BMOD_RZ(R,Z) are provided as spline approximations to the field components over (R,Z) coordinates. (g) any collection of named data items-- * profiles-- zonal data, piecewise linear data, or splines over up to 3 independent coordinates * lists -- each containing its own collection of named, labeled elements with associated scalar integer and floating point values. * black boxes -- generic storage of "unstructured" integer and floating point data. The INITIALIZATION of an xplasma object consists of the definition of the elements that do not (normally) vary in time. The most direct method of initialization is to start from an EFIT G-eqdsk file containing a free boundary equilibrium reconstruction: use xplasma_obj_instance character*32 :: author_name = 'My_code' character*60 :: filename = <path to G-eqdsk file> call xoi_init(ier) ! init xplasma pointers in module call xplasma_author_set(s,author_name,ier) call xplasma_fromgeqdsk(s,filename,ier, & nrho = <number of numerical flux surfaces including axis>, & ntheta = <number of poloidal grid points covering 0:2pi>) ! also a good idea: real*8 :: curtime curtime = <current time of simulation> call xplasma_time_set(s,curtime,ier) call xplasma_author_clear(s,author_name,ier) The optional arguments specify the desired equilibrium flux coordinate grid resolutions; if defaulted, the code uses nrho=51, ntheta=101. Loading xplasma from a G-eqdsk file for the first time, items (a)-(c), are defined, and initial values for items (e)-(f) are also provided. The equilibrium can subsequently be modified with later calls to xplasma_fromgeqdsk, reading modified G-eqdsk files, but then the limiter and [R,Z] grids found must be the same as were given in the first G-eqdsk file read; this is checked and an error will be reported if there is a mismatch. Further initializations may involve the definition of additional coordinates and grids, e.g. in velocity space, which are application dependent. The xplasma public interfaces include the following routines likely to be used in initialization: xplasma_create_coordinate xplasma_create_grid which will be described below.

Home | Top |

Alternate_initialization_method

The alternative to using a G-eqdsk file is to use a series of calls to spell out each of the components of the equilibrium. In this context, initialization consists in the definition of the flux coordinate grids, the limiters, and the [R,Z] grids. Code to do this is sketched below. Details on the interfaces used will be given below. !-------------------------- ! on the FIRST call, the rho and theta grids need to be defined... character*32 :: author_name = 'My_code' call xplasma_author_set(s,author_name,ier) allocate(rho(inrho),th(inth)) <fill in rho values; rho(1)=0.0; rho(inrho)=1.0> <fill in th values over range -pi:pi or 0:2pi> call xplasma_create_grid(s,'my_rho',xplasma_rho_coordinate,rho,id_rho,ier, & label='my rho grid for the equilibrium') call xplasma_create_grid(s,'my_theta',xplasma_theta_coordinate,th,id_th, & ier, label='my theta grid for the equilibrium') ! the field SIGNS also have to be set, once, at the beginning of the ! lifetime of the xplasma object: ! bphi_ccw=1 means the toroidal field points counter clockwise; ! jphi_ccw=-1 means the toroidal current flows clockwise ! these orientations as viewed from above the tokamak ! values of +/-1 are allowed for each of these arguments call xplasma_field_ccw_set(s,ier, bphi_ccw=1, jphi_ccw=-1) ! example ! also on the first call, a LIMITER should be defined... allocate(rpts(nlim),zpts(nlim)) <fill in with sequence of (R,Z) pairs defining a closed contour> <rpts(1)=rpts(nlim) and zpts(1)=zpts(nlim) are expected> call xplasma_mklim_contour(s,rpts(1:nlim),zpts(1:nlim),iwarn,ier) ! and an [R,Z] rectangular space covering the plasma and limiter should be ! defined: allocate(rgrid(nrgrid),zgrid(nzgrid)) <fill in desired R and Z grids which should at least span the limiter> < i.e. rgrid(1) <= minval(rpts); rgrid(nrgrid) >= maxval(rpts) > < i.e. zgrid(1) <= minval(zpts); zgrid(nzgrid) >= maxval(zpts) > call xplasma_create_rzgrid(s,rgrid(1:nrgrid),zgrid(1:nzgrid), & id_rgrid,id_zgrid,ier) ! these arguments returned... ! done for now... call xplasma_author_clear(s,author_name,ier)

Home | Top |

Modifying_F95_Xplasma_Data

In this section, the new Fortran-95 Xplasma interface is described, with emphasis on methods for adding data to an existing dataset, or, creating one from scratch. The xplasma pointers (s,s1) defined in xplasma_obj_instance are presumed to be available in the coding examples. The argument "ierr" is always a return status code, 0=normal. For simplicity of examples, error checking / error handling code is usually omitted -- don't try this at home!

Home | Top |

Code_authorship

Since xplasma is envisioned as a means of communication between disparate code modules or even separately executing processes, it is useful to be able to trace the origin of xplasma data items to specific codes or modules. In practice, this means a code must "identify itself" to access xplasma. A code that writes into xplasma must provide an "author id", which is any alphanumeric name, not starting with a digit, up to 32 characters long. Failure to do this will usually result in an "xplasma locked" error report. Codes which write to xplasma should use the following pair of calls: character*32 author_name author_name = "my_code" ! or whatever name you choose... call xplasma_author_set(s,author_name,ier) ! push my name onto author stack <write stuff into xplasma> call xplasma_author_clear(s,author_name,ier) ! pop my name off the stack An error could conceivably occur on the latter call, if an intervening call (after xplasma_author_set) was made to another module, which issued another xplasma_author_set but failed to issue a matching call to xplasma_author_clear; the software would then detect that the passed name does not match the name at the top of the author stack. To prevent such errors, it is important to always pair these calls.

Home | Top |

Update_the_MHD_equilibrium

FREE BOUNDARY MHD equilibria are best read into xplasma from a G-eqdsk file: call xplasma_author_set(s,author_name,ier) call xplasma_fromgeqdsk(s,filename,ier, [...optional arguments...]) ! also a good idea: real*8 :: curtime curtime = <current time of simulation> call xplasma_time_set(s,curtime,ier) call xplasma_author_clear(s,author_name,ier) The first time this is done, the resolution of the flux coordinate "rho" and "theta" grids can be specified-- note that only evenly spaced grids are allowed for equilibria built from G-eqdsk at present. If the grid size optional arguments "nrho" and "nth" are omitted, the default values nrho=51 and nth=101 are used-- sufficient for many purposes. On subsequent calls, the equilibrium flux coordinate grids are reused from the prior state. PRESCRIBED BOUNDARY MHD equilibria are updated through a sequence of calls which redefine the equilibrium profiles-- as described in the subtopic.

Home | Top |

xplasma_fromgeqdsk

The full xplasma_fromgeqdsk interface is copied below. Except possibly for specifying "nrho" and "nth" on the first call, most users should leave the optional arguments unspecified-- the default values are well tested and reliable. The argument "filename" can be either a unix file path to a read-accessible G-eqdsk file in the standard GA-documented EFIT format, or, it can be a path to an MDS+ tree (access to experimental database). MDS+ path strings take the following form: MDS+[/<time-option>]:<server>[:<port>]:<tree>(<shot>;t=<time>) items in square brackets [,] are optional (though sometimes a port number is required to access a particular server); items in angle brackets <,> are to be replaced with their correct values; everything else is literal. <time-option> can be REDUCE (the default) or NOREDUCE. REDUCE means: select the nearest available time; read only that time from the MDS+ database. NOREDUCE means: read all available times from the database; interpolate linearly between available times to get to the <time> requested. In applications which loop over all times in an experiment, it is more efficient to use NOREDUCE (fewer network data accesses). <server> or <server>[:<port>] is the network address of the MDS+ server. Examples: alcdata.psfc.mit.edu (CMOD); europa.pppl.gov:8501 (NSTX). <tree> is the name of the tree containing time dependent EFIT G-eqdsk data. Typical examples: EFIT01 (NSTX, DIII-D), ANALYSIS (CMOD). <shot> is the integer shot or pulse number of the experimental data. <time> is time in seconds in any decodable floating point format. Example: MDS+/REDUCE:EUROPA.PPPL.GOV:8501:EFIT06(116313;t=0.9) ---------------------- CAUTION: MDS+ server access may be restricted, depending on the policy of the experimental project that owns the server. ---------------------- subroutine xplasma_fromgeqdsk(s,filename,ier, & new_device, nrho, nth, lhermite, & bdy0, cratio_min, rzspace, rhobrk_adj_axis, mom_rtol, & equal_arc, & gs_errmax) ! (re)build equilibrium inverse represenation from EFIT g-eqdsk data ! R(rho,theta), Z(rho,theta), g(rho),q(rho),P(rho). type (xplasma), pointer :: s character*(*), intent(in) :: filename ! Geqdsk filename or MDS+ path ! ...or...EFIT_INDEX:filename(t=<time>) specification ! see comments in source/xplasma/eqm_fromgeqdsk.f90 integer, intent(out) :: ier ! integer status code (returned; 0=OK) !--------------- ! optional... logical, intent(in), optional :: new_device ! flag, .TRUE. if reading ! equilibrium for a new device. Default: .TRUE. when reading the ! first equilibrium in the history of the xplasma object; .FALSE. ! subsequently. When this is not .TRUE., the limiter data is presumed ! already known to xplasma. integer, intent(in), optional :: nrho ! no. of flux surfaces ! covering rho = [0:1] ! rho = normalized(sqrt(Psi-tor/Psi-tor-at-bdy)) ! for 20 zones specify nrho=21 -- count includes axis and plasma ! boundary-- evenly spaced in rho ! DEFAULT: nrho=51 if new_device is .TRUE.; otherwise the value from ! the old equilibrium is taken. integer, intent(in), optional :: nth ! no. of theta points -- no. of ! evenly spaced points spanning 0:2pi inclusive. ! DEFAULT: nth=101 if new_device is .TRUE.; otherwise the value from ! the old equilibrium is taken. logical, intent(in), optional :: lhermite ! flag, .TRUE. for Hermite ! interpolation of {R,Z}(rho,theta) -- by default, bicubic spline ! interpolation is used. real*8, intent(in), optional :: bdy0 ! initial Psi_bdy/Psi_sep ! (default 1.0d0) fraction of Psi to enclose in mapped region ! The issue here is that a separatrix surface generally cannot be ! used as a boundary in an inverse representation, due to q=infinity ! and the kink in the surface shape. So instead one backs off from ! the Psi_sep flux, defining a boundary just inside the separatrix. ! Recommendation: the default. "cratio_min" causes the code to ! iterate to find a suitable boundary surface. ! Accepted range: 0.95d0 to 1.00d0 real*8, intent(in), optional :: cratio_min ! minimum curvature ratio ! (default 0.080d0) minimum acceptable local curvature radius, ! normalized to midplane half width. A separatrix kink has a curvature ! radius of zero. This is tested by fitting a circle through successive ! sequences of 3 points on the boundary grid [1:nth] and looking at this ! circle's radius compared to an estimate of the plasma midplane half- ! width. ! Recommendation: the default, based on experience. ! Accepted range: 0.01d0 to 0.15d0 logical, intent(in), optional :: rzspace ! .TRUE. to save (R,Z) ! grids using the EFIT grids, and compute B(R,Z). Default = .TRUE. ! Setting this .FALSE. may speed some applications. integer, intent(in), optional :: kmom ! number of Fourier moments ! to use in Fourier Spline representation of equilibrium ! (default: not set here; xplasma default is 16). real*8, intent(in), optional :: rhobrk_adj_axis ! delta(rho) for ! moments trimming operations, and, the maximum rho where flux ! surfaces can be touched, in order to assure that d/drho[R0,Z0] --> 0 ! as rho--> 0, an attributed needed by codes (e.g. RF solvers) that ! use the inverted equilibrium. ! Default value: 0.15d0. To disable this feature, set ! rhobrk_adj_axis = -1.0d0 or any other negative number real*8, intent(in), optional :: mom_rtol ! moments trimming ratio ! (default 1.0d-6). The EFIT Psi(R,Z) inversion involves a Fourier ! representation; this control specifies a method for trimming away ! higher order moments that are very small over wide regions of space. ! Accepted range: 0.0d0 to 1.0d-4 logical, intent(in), optional :: equal_arc ! .TRUE. to use an equal ! arc definition for the poloidal angle coordinate; .FALSE. (default) ! for VMEC/descur moments power spectrum minimization definition, the ! traditional definition for past usage. real*8, intent(out), optional :: gs_errmax ! normalized measure of ! Grad Shafranof (GS) error in the EFIT equilibrium.

Home | Top |

xplasma_geqdsk_rewrite

Immediately after reading an xplasma file or MDS+ tree (i.e. after an xplasma_fromgeqdsk call) it is possible to rewrite the G-eqdsk data into a separately named standard EFIT G-eqdsk file. This is used mainly to extract MDS+ tree data into files, so that legacy codes which only know to read G-eqdsk as files, not as MDS+ records, can work: subroutine xplasma_geqdsk_rewrite(filename,ier) ! rewrite g-eqdsk file e.g. under new filename, after reading ! (e.g. inside an eqi_fromgeqdsk call). ! WARNING: the information written is based on the most recent ! read of g-eqdsk information. Information to reconstruct the ! g-eqdsk from the data as originally read is NOT saved with each ! xplasma object. Hence: no s pointer argument. character*(*), intent(in) :: filename integer, intent(out) :: ier NOTE that there is no xplasma object pointer-- this simply rewrites the most recently read G-eqdsk data. The xplasma library is using a subsidiary, non-object-oriented library for EFIT G-eqdsk I/O. So, this method should be used with care.

Home | Top |

xplasma_wr_geqdsk

After an equilibrium has been created within xplasma, by whatever means, it can be written as a G-file. The method here differs from xplasma_geqdsk_rewrite as follows: (a) the output [R,Z] domain and resolution can be redefined; (b) the equilibrium could have been created by means other than an "xplasma_fromgeqdsk" call. subroutine xplasma_wr_geqdsk(s,ierr, & lun_geqdsk, filename, label, Rmin, Rmax, Zmin, Zmax, & cur, id_qprof, id_pprof, & nh, nv, nbdy) use eqi_geq_mod ! Build and write a G-eqdsk file (disk file) from current xplasma ! contents. This differs from "xplasma_geqdsk_rewrite" as the latter ! just echoes data read in from another G-eqdsk file or MDSplus data ! structure. This actual constructs the information from current ! xplasma contents -- interpolation is involved. ! The xplasma object must contain a complete free boundary or ! extrapolated equilibrium, so that Psi(R,Z) covering a rectangle ! enclosing the plasma is defined. !----------------- ! required: type (xplasma), pointer :: s ! XPLASMA object containing equilibrium integer, intent(out) :: ierr ! status code on exit: 0=OK ! optional: integer, intent(in), optional :: lun_geqdsk ! FORTRAN LUN on which to write file. If omitted, the LUN used for ! reading G-eqdsk files, in the geqdsk_mds library, is used. ! (call geq_getlun(ilun)) (geqdsk_mod default value: 77 as of 7/2006). character*(*), intent(in), optional :: filename ! default " "; if non-blank, it is the ! name of the file to write. If blank or omitted, the code simply ! writes to lun_geqdsk; it would be up to the caller to OPEN a file. character*(*), intent(in), optional :: label ! default " "; default means: use xplasma global label; ! if non-blank, the 1st 48 characters are used as a label string in the ! G-eqdsk file being written. real*8, intent(in), optional :: Rmin,Rmax, Zmin,Zmax ! [R,Z] domain over which Psi(R,Z) is written in the G-eqdsk file. ! default: use the [R,Z] grid limits already stored in xplasma. If ! explicit limits are provided, overriding the defaults, these must ! not extend beyond the grid limits. real*8, intent(in), optional :: cur ! total plasma current. Default: use value implied by equilibrium data. integer, intent(in), optional :: id_qprof ! ID of profile f(rho) defining q(rho). Default: use value derived from ! equilibrium-- calculated here, it will be named Q_EQDSK integer, intent(in), optional :: id_pprof ! ID of profile f(rho) defining equilibrium pressure. Default: use value ! previously tagged as equilibrium pressure. If this is not available, ! the code will attempt to compute a pressure using the surface averaged ! GS equation JxB=grad(P). This could lead to a non-physical result if ! there are errors in the equilibrium data already provided, or if the ! assumption of a scalar P is inappropriate. If a pressure profile is ! calculated, it will be named P_EQDSK-- done using an xplasma_gen_p ! call. integer, intent(in), optional :: nh,nv ! number of horizontal and vertical grid points, respectively. If ! defaulted, the sizes of the [R,Z] grids are used. NOTE that nh also ! controls the size of the 1d profiles f,ff',P,P',and q written in the ! G-eqdsk profiles. These 1d profiles are written over an implied ! evenly spaced Psi grid going from Psi(min) at the axis to Psi(max) ! at the boundary. integer, intent(in), optional :: nbdy ! number of points to use to described plasma boundary and limiter. ! default: 200.

Home | Top |

Prescribed_boundary_equilibrium_update

A working example is given in the xplasma test program xplasma_fsp_test. Here a sketch of the code is provided. Details on individual calls are provided in other parts of this document. Prescribed boundary codes like TRANSP use this method. Many details must be specified-- one reason why using a G-eqdsk instead is often more convenient... call xplasma_author_set(s,author_name,ier) !-------------------------- ! on the FIRST call, the rho and theta grids need to be defined... ! this is presumed done already; the rho and theta grid IDs are ! presumed known and stored in integers "id_rho" and "id_th". integer :: id_rho, id_th ! grid IDs integer :: inrho, inth ! grid sizes ! can retrieve this grid IDs e.g. as follows: integer :: id_R call xplasma_common_ids(s,ier, id_R=id_R) ! retrieve R(theta,rho) ID call xplasma_prof_info(s,id_R,ier, gridId1=id_th, gridId2=id_rho) ! can get grid sizes this way: call xplasma_grid_size(s,id_rho,inrho,ier) call xplasma_grid_size(s,id_th,inth,ier) ! can also fetch actual grids with "xplasma_grid" calls. !-------------------------- ! on calls other than the FIRST call, the following call will DELETE ! the old equilibrium profiles: logical :: rzonly ! TRUE to delete R,Z only; FALSE to delete {R,Z,g,p,Psi} <set rzonly to desired value> call xplasma_eqClear(s,rzonly,ier) !-------------------------- allocate(R(inth,inrho),Z(inth,inrho)) ! dimensions match equilibrium ! flux coordinate grids <update R and Z data arrays to desired new geometry> ! define the geometry ! optional arguments allow specification of dR/drho and dZ/drho ! boundary conditions if desired. call xplasma_rzmag(s,id_th,id_rho,R,Z,id_R,id_Z,ier, [options...]) allocate(g(inrho),psi(inrho),p(inrho),q(inrho)) <update G, psi, P, q data arrays> call xplasma_create_prof(s,'G',id_rho,g,id_g,ier) call xplasma_create_prof(s,'Psi',id_rho,psi,id_psi,ier) call xplasma_create_prof(s,'Q',id_rho,q,id_q,ier) ! or... call xplasma_create_prof(s,'P',id_rho,p,id_p,ier) ! (Q can also be computed by xplasma, once G and Psi have been provided) ispline=2 call xplasma_gen_q(s,'Q',ispline,id_q,ier) ! enough information has now been specified to check the equilibrium and ! compute field component splines iforce=.TRUE. ! do the computation unconditionally call xplasma_eqCheck(s,iforce,icount,ier) ! the error code should be checked!! if the (R,Z) geometry contains ! metric singularities, it will be detected. Such errors cannot be ! ignored as these would otherwise cause a zoo of failures later on... ! finally, to create an environment similar to the one provided by ! a free boundary equilibrium, based however only on a rough extrapolation ! of the fields to a [R,Z] rectangle covering the core and scrapeoff plasma ! DO NOT USE this if a free boundary Psi(R,Z), defining a real external ! field, is available... call xplasma_brz_extrap(s,ier, [options...]) ! also a good idea: real*8 :: curtime curtime = <current time of simulation> call xplasma_time_set(s,curtime,ier) call xplasma_author_clear(s,author_name,ier)

Home | Top |

Error_handling

Xplasma routines never write messages to files or to stdout-- all error handling is by means of a status code. Almost all xplasma subroutine calls return an integer status code "ierr". If the value of ierr returned is 0, there is no error, completion status is normal. (NOTE: spelling variant: some xplasma routines spell this "ier" in their argument lists). Codes using xplasma need to check for and handle errors. Xplasma "tries hard" to avoid errors; if it fails the error is generally not ignorable. It is expected that the normal action after an xplasma error will be to shut down the software as gracefully as possible with appropriate explanatory messages. Messages associated with errors are created and stored within a small message buffer in the xplasma object. It is up to the code using xplasma to control the disposition of these messages. If an f95 xplasma routine returns a non-zero error code, the following call should be used: call xplasma_error(s,ierr,ilun) with "s" the xplasma object pointer, (integer) ierr the status code, *input* to this routine, and (integer) ilun the fortran I/O unit on which to write messages associated with this error. In addition, the user software should generally write some message such as perhaps "unexpected xplasma error in subroutine XYZ, exiting..."; good messages of this type are a tremendous help in debugging large codes. Generally, specific error codes are associated with specific errors. For example, ierr=101 indicates that a NULL s pointer was passed.

Home | Top |

Time_evolving_xplasma

A major change to F95 xplasma compared to the original version, is the ability to update the xplasma equilibrium on the fly, while preserving other profiles. (In the original F77 xplasma version, an equilibrium change required reconstruction of the entire xplasma contents). Some items are marked as "derived from the equilibrium"-- these are generally built internally within xplasma and have the following author ID: character*32, parameter, public :: xplasma_xmhd = '__XPLASMA_MHDEQ_DERIVED' These items will be deleted and rebuilt, each time the equilibrium changes. Examples of such items are: -- list giving magnetic axis parameters R_axis, Z_axis, B_axis -- list giving R, Z, B extrema of boundary surface -- data related to flux surface averages -- data related to coordinate transformations ---------------------------------------------------------------- There are some structural limits on changes over time. The contraints are as follows. Although profiles, including those describing the equilibrium, can be updated or replaced at any time, underlying grids are not so easily changed. In particular, the software does not allow a grid to be deleted or replaced, if it detects that any existing profiles are using that grid. If it were necessary for a time dependent code to regrid to a finer mesh, all affected profiles would need to be reinterpolated accordingly. This can be done, but there is no standard method at present. Some code would have to be written. Because F95 xplasma supports multiple instantiation of xplasma objects, it would not be too difficult. A sketch of the code to carry this out would look like this: integer :: ier,ii,idg,inum_profs,inum_modify integer :: idg1,idg2,idg3,icoord integer, dimension(:), allocatable :: ids, ids_modify character*32 gname idg = [id of grid that will be changed] ! retrieve name and associated coordinate ID ! (in a real code these are probably known already) call xplasma_grid_info(s,idg,ier, name=gname, coord=icoord) ! make a copy of the xplasma object "s" to "s2" call xplasma_copy(s,s2,ier) ! get the full list of profiles call xplasma_num_items(s,ier, num_profs=inum_profs) allocate(ids(inum_profs),ids_modify(inum_profs)) call xplasma_contents(s,ier, id_profs=ids) ! delete profiles which use "idg"; build list of deleted profiles inum_modify = 0 do ii=1,inum_profs call xplasma_prof_info(s,ids(ii),ier, & gridId1=idg1,gridId2=idg2,gridId3=idg3) if((idg1.eq.idg).or.(idg2.eq.idg).or.(idg3.eq.idg)) then ! this profile uses the marked grid inum_modify = inum_modify + 1 ids_modify(inum_modify) = ids(ii) call xplasma_remove_item(s,ids(ii),ier) endif enddo ! remove the old idg grid-- this should succeed now, since all the profiles ! using idg were removed from "s". call xplasma_remove_item(s,idg,ier); [check ier status] <form new grid data real*8 x(1:n)> -- same name, same id will result. call xplasma_create_grid(s,gname,icoord,s,idg,ier,label='...') do ii=1,inum_modify <using s2 copy of profile, form a local array copy reinterpolated to the new grid> <for multidimensional profiles this involves a loop over each of the other coordinates> call xplasma_create_prof(s,...) ! Insert interpolated profile into "s". enddo call xplasma_free(s2,ier) ! done with "s2"-- free the memory.

Home | Top |

Creation_and_update_of_named_items

Coordinates, grids, profiles, lists, and "black boxes" can be created or replaced by the user, within the following constraints: (a) When a grid is created, the coordinate to which it belongs must be identified. Conversely, coordinates cannot be removed or replaced if there are any grids currently associated with the coordinate. (b) When a profile is created, the grid or grids over which it is defined must be specified. Conversely, grids cannot be removed or redefined when they are "in use" by any profile. Every item within xplasma has a unique name and integer ID. Since the name translation and lookup is somewhat expensive, most calls which refer to an item requires its integer ID. Full names are used when items are created, and when their IDs are retrieved, per the following table: item type CREATE call LOOKUP call coordinate xplasma_create_coordinate xplasma_coordId grid xplasma_create_grid xplasma_gridId profile xplasma_create_prof xplasma_profId list xplasma_create_list xplasma_listId black box xplasma_create_blackBox xplasma_blkbxId The lookup calls all take the arguments (s,name,id) where s is the xplasma object pointer, name is the item name, id is the integer id returned. The interfaces for the CREATE routines are described in the subtopics. Some specialized methods are available. These are: xplasma_irhofun -- create a smoothed integrated profile xplasma_rzprof -- create a profile f(R,Z), e.g. from f(rho). xplasma_rzprof_fun -- xplasma_rzprof with a user provided function call xplasma_mcgrid_define -- create an irregular "Monte Carlo" grid (MCgrid). xplasma_mcgrid_putobj -- create a profile over a MCgrid. -------------- All blocks of code using the CREATE methods should be bracked by the pair of calls requesting and releasing write authority: call xplasma_author_set(s,author_name,ier) [create stuff] call xplasma_author_clear(s,author_name,ier)

Home | Top |

xplasma_label_item

The label and physical units of an item are generally optional arguments in the xplasma_create subroutines. These can be provided later, by means of this call: character*50 :: label = <very brief description of item> character*16 :: units = <physical units label, should be MKS> call xplasma_label_item(s,id,ier, label=label, units=units) !------------------- subroutine xplasma_label_item(s,id,ier, & label,units) ! label an existing item as identified by "id"... type (xplasma), pointer :: s integer, intent(in) :: id ! id of existing item integer, intent(out) :: ier ! status code returned character*(*), intent(in), optional :: label ! label for item character*(*), intent(in), optional :: units ! units label for item

Home | Top |

xplasma_create_coordinate

subroutine xplasma_create_coord(s,coordname,periodic,id,ier, & label,units) ! create a coordinate with the specified name; return new coord id type (xplasma), pointer :: s character*(*), intent(in) :: coordname logical, intent(in) :: periodic ! T if named coordinate is periodic integer, intent(out) :: id ! id of coordinate object integer, intent(out) :: ier ! completion code character*(*), intent(in), optional :: label character*(*), intent(in), optional :: units

Home | Top |

xplasma_create_grid

subroutine xplasma_create_grid(s,gridname,icoord,x,id,ier, & ccwflag,label) ! create a new grid with the specified name; return new grid id type (xplasma), pointer :: s character*(*), intent(in) :: gridname integer, intent(in) :: icoord ! id of coordinate object to which the ! grid object belongs ! icoord can also be a grid id, in which case the coordinate associated ! with this new grid is the one associated with grid (icoord) real*8, intent(in) :: x(:) ! the grid, x(j).lt.x(j+1) required. integer, intent(out) :: id ! id of grid object integer, intent(out) :: ier ! completion code ! specify if toroidal or poloidal angle grid is drawn counterclockwise: logical, intent(in), OPTIONAL :: ccwflag ! theta: when viewing plasma cross section to right of machine ! centerline ! phi: when viewing machine from above ! Default: .TRUE. character*(*), intent(in), optional :: label ! units label inherited from associated coordinate object ! NOTE: xplasma saves all angle grids with CCW orientation; a CW ! oriented grid will be redefined with its direction reversed: ! angle -> 2pi - angle

Home | Top |

xplasma_create_prof

Generally, the following arguments are required: xplasma object pointer profile name grid ID(s) profile data -- array dimensions must match gridsizes EXACTLY. profile ID returned error status returned Optional arguments: ispline -- type of interpolation -1 -- zonal data (step function): this is the default if the data dimension sizes are 1 less than the corresponding grid sizes. 0 -- piecewise linear (the default) 1 -- C1 Akima Hermite 2 -- C2 Cubic Spline Boundary conditions (for ispline=1 or ispline=2). For rank N data, each explicit boundary condition data array is of rank N-1; array dimensions must match appropriate gridsizes EXACTLY. But-- there are many cases where explicit boundary conditions are not required; it depends on the application of the data. ccwflag arguments -- in effect these specify that the storage order of the data along a periodic grid dimension is reversed-- but, the end points must match the referenced grid. assoc_id -- pairs of profiles can be associated. This is to support the idea that a physical quantity, e.g. a B field component, might have both a flux coordinate representation and an [R,Z] representation. When profiles are associated, the IDs for the flux coordinate versions and [R,Z] coordinate versions of the data can be used interchangeably, i.e. providing the flux coordinate profile ID to an [R,Z] interpolation call will not result in an error. label & units Verbatim interfaces for 1d 2d and 3d profile create routines follow... interface xplasma_create_prof module procedure xplasma_create_1dprof module procedure xplasma_create_2dprof module procedure xplasma_create_3dprof end interface subroutine xplasma_create_1dprof(s,profname,idx,data,idf,ier, & ispline,ibca,zbca,ibcb,zbcb,ccwflag,assoc_id,label,units) ! create a new profile with the specified name !-------- ! standard INPUT arguments... type (xplasma), pointer :: s character*(*), intent(in) :: profname ! name of profile integer, intent(in) :: idx ! id of grid over which it is defined real*8, dimension(:), intent(in) :: data ! the profile data ! (NOTE: size of data must match size of grid) !-------- ! standard OUTPUT arguments... integer, intent(out) :: idf ! id of profile now being (re)defined. integer, intent(out) :: ier ! completion code (0=normal) !-------- ! optional input arguments... ! defaults: pc linear; for splines: "not a knot" BC ! angle grid: normal CCW orientation. integer, intent(in), optional :: ispline ! order of fit ! 0 -- pc linear; 1 -- Hermite; 2 -- cubic spline; integer, intent(in), optional :: ibca ! BC control @ LHS of grid real*8, intent(in), optional :: zbca ! BC data @ LHS of grid integer, intent(in), optional :: ibcb ! BC control @ RHS of grid real*8, intent(in), optional :: zbcb ! BC data @ RHS of grid ! ibca=ibcb=0 = default: "not a knot" for splines; Akima for Hermite ! for periodic functions BC args are ignored; periodic BC is used. ! ibc[*]=1 -- df/dx specified in zbc[*] (0 if absent) ! ibc[*]=2 -- d^2f/dx^2 specified in zbc[*] (0 if absent) logical, intent(in), optional :: ccwflag ! T means data vs. CCW angle ! grid; F means CW. Default=T. ccwflag is ignored if the x grid of ! the profile is not an angle coordinate. integer, intent(in), optional :: assoc_id character*(*), intent(in), optional :: label character*(*), intent(in), optional :: units !------------------------------------------ subroutine xplasma_create_2dprof(s,profname, & idx1,idx2,data,idf,ier, & ispline,ibcx1a,zbcx1a,ibcx1b,zbcx1b, & ibcx2a,zbcx2a,ibcx2b,zbcx2b, ccwflag1,ccwflag2, & assoc_id, label,units) ! create a new profile with the specified name !-------- ! standard INPUT arguments... type (xplasma), pointer :: s character*(*), intent(in) :: profname ! name of profile integer, intent(in) :: idx1 ! id of 1st grid over which it is defined integer, intent(in) :: idx2 ! id of 2nd grid over which it is defined real*8, dimension(:,:), intent(in) :: data ! the profile data ! (NOTE: sizes of dimensions MUST match sizes of identified grids) !-------- ! standard OUTPUT arguments... integer, intent(out) :: idf ! id of container for this profile. integer, intent(out) :: ier ! completion code (0=normal) !-------- ! optional input arguments... ! defaults: pc linear; for splines: "not a knot" BC ! angle grid: normal CCW orientation. integer, intent(in), optional :: ispline ! order of fit ! 0 -- pc linear; 1 -- Hermite; 2 -- cubic spline; integer, intent(in), optional :: ibcx1a ! BC control @ LHS of grid x1 real*8, intent(in), dimension(:), optional :: zbcx1a ! BC data @ LHS of grid x1 integer, intent(in), optional :: ibcx1b ! BC control @ RHS of grid x1 real*8, intent(in), dimension(:), optional :: zbcx1b ! BC data @ RHS of grid x1 integer, intent(in), optional :: ibcx2a ! BC control @ LHS of grid x2 real*8, intent(in), dimension(:), optional :: zbcx2a ! BC data @ LHS of grid x2 integer, intent(in), optional :: ibcx2b ! BC control @ RHS of grid x2 real*8, intent(in), dimension(:), optional :: zbcx2b ! BC data @ RHS of grid x2 ! ibc*a=ibc*b=0 = default: "not a knot" for splines; Akima for Hermite ! for periodic functions BC args are ignored; periodic BC is used. ! ibc[*]=1 -- df/dx specified in zbc[*] (0 if absent) ! ibc[*]=2 -- d^2f/dx^2 specified in zbc[*] (0 if absent) logical, intent(in), optional :: ccwflag1 ! T means data vs. CCW angle ! grid; F means CW. Default=T. logical, intent(in), optional :: ccwflag2 ! T means data vs. CCW angle ! grid; F means CW. Default=T. integer, intent(in), optional :: assoc_id ! id of associated profile character*(*), intent(in), optional :: label character*(*), intent(in), optional :: units !------------------------------------------ subroutine xplasma_create_3dprof(s,profname, & idx1,idx2,idx3,data,idf,ier, & ispline,ibcx1a,zbcx1a,ibcx1b,zbcx1b, & ibcx2a,zbcx2a,ibcx2b,zbcx2b, & ibcx3a,zbcx3a,ibcx3b,zbcx3b, & ccwflag1,ccwflag2,ccwflag3, assoc_id,label,units) ! create a new profile with the specified name !-------- ! standard INPUT arguments... type (xplasma), pointer :: s character*(*), intent(in) :: profname ! name of profile integer, intent(in) :: idx1 ! id of 1st grid over which it is defined integer, intent(in) :: idx2 ! id of 2nd grid over which it is defined integer, intent(in) :: idx3 ! id of 3rd grid over which it is defined real*8, dimension(:,:,:), intent(in) :: data ! the profile data ! (NOTE: sizes of dimensions MUST match sizes of identified grids) !-------- ! standard OUTPUT arguments... integer, intent(out) :: idf ! id of newly created profile. integer, intent(out) :: ier ! completion code (0=normal) !-------- ! optional input arguments... ! defaults: pc linear; for splines: "not a knot" BC ! angle grid: normal CCW orientation. integer, intent(in), optional :: ispline ! order of fit ! 0 -- pc linear; 1 -- Hermite; 2 -- cubic spline; integer, intent(in), optional :: ibcx1a ! BC control @ LHS of grid x1 real*8, intent(in), dimension(:,:), optional :: zbcx1a ! BC data @ LHS of grid x1 integer, intent(in), optional :: ibcx1b ! BC control @ RHS of grid x1 real*8, intent(in), dimension(:,:), optional :: zbcx1b ! BC data @ RHS of grid x1 integer, intent(in), optional :: ibcx2a ! BC control @ LHS of grid x2 real*8, intent(in), dimension(:,:), optional :: zbcx2a ! BC data @ LHS of grid x2 integer, intent(in), optional :: ibcx2b ! BC control @ RHS of grid x2 real*8, intent(in), dimension(:,:), optional :: zbcx2b ! BC data @ RHS of grid x2 integer, intent(in), optional :: ibcx3a ! BC control @ LHS of grid x3 real*8, intent(in), dimension(:,:), optional :: zbcx3a ! BC data @ LHS of grid x3 integer, intent(in), optional :: ibcx3b ! BC control @ RHS of grid x3 real*8, intent(in), dimension(:,:), optional :: zbcx3b ! BC data @ RHS of grid x3 ! ibc*a=ibc*b=0 = default: "not a knot" for splines; Akima for Hermite ! for periodic functions BC args are ignored; periodic BC is used. ! ibc[*]=1 -- df/dx specified in zbc[*] (0 if absent) ! ibc[*]=2 -- d^2f/dx^2 specified in zbc[*] (0 if absent) logical, intent(in), optional :: ccwflag1 ! T means data vs. CCW angle ! grid; F means CW. Default=T. logical, intent(in), optional :: ccwflag2 ! T means data vs. CCW angle ! grid; F means CW. Default=T. logical, intent(in), optional :: ccwflag3 ! T means data vs. CCW angle ! grid; F means CW. Default=T. ! ccwflag1 applies to x1 if it is periodic; otherwise it is ignored. ! ccwflag2 applies to x2 if it is periodic; otherwise it is ignored. ! ccwflag3 applies to x3 if it is periodic; otherwise it is ignored. integer, intent(in), optional :: assoc_id ! id of associated profile character*(*), intent(in), optional :: label character*(*), intent(in), optional :: units

Home | Top |

xplasma_prof_lintrans

A linear transformation f -> a*f + b can be applied to an existing profile: subroutine xplasma_prof_lintrans(s,id,ierr, factor, offset) type (xplasma), pointer :: s integer, intent(in) :: id ! profile ID integer, intent(out) :: ierr ! status code returned 0 = normal real*8, intent(in), optional :: factor ! multiplicative factor real*8, intent(in), optional :: offset ! additive offset where a is specified as "factor" and b is specified as "offset". If neither optional argument is specified, the subroutine returns without doing anything, since the default value for "factor" is a=1 and the default value for "offset" is b=0. Note: the current author (enabled to write xplasma data) must own the profile being transformed; i.e. use xplasma_author_set(...) and xplasma_author_clear(...) calls if necessary to modify and restore access control settings.

Home | Top |

xplasma_create_list

When a list is created, its elements must all be named. Corresponding values can either be given at create time, or may be supplied later. subroutine xplasma_create_list(s,listname,enames,id,ier, & label, units, ivals, r8vals, chvals) ! ! create list & define list elements ! type (xplasma), pointer :: s character*(*), intent(in) :: listname ! name of list being created character*(*), intent(in), dimension(:) :: enames ! names of elements integer, intent(out) :: id ! id of list item integer, intent(out) :: ier ! completion code character*(*), intent(in), optional :: label ! label for entire list character*(*), intent(in), optional :: units ! units label for list integer,intent(in), dimension(:), optional :: ivals ! integer values real*8, intent(in), dimension(:), optional :: r8vals ! real*8 values character*(*), intent(in), dimension(:), optional :: chvals ! str values Methods for setting the list element values are given in the subtopics.

Home | Top |

xplasma_setList_r8vals

subroutine xplasma_setList_r8vals(s,id,r8vals,ier) ! ! set real*8 values in list ! type (xplasma), pointer :: s integer, intent(in) :: id ! id of list item real*8, dimension(:), intent(in) :: r8vals ! the real*8 values integer, intent(out) :: ier ! completion code

Home | Top |

xplasma_setList_ivals

subroutine xplasma_setList_ivals(s,id,ivals,ier) ! ! set integer values in list ! type (xplasma), pointer :: s integer, intent(in) :: id ! id of list item integer, dimension(:), intent(in) :: ivals ! the integer values integer, intent(out) :: ier ! completion code

Home | Top |

xplasma_setList_chvals

subroutine xplasma_setList_chvals(s,id,chvals,ier) ! ! set character string values in list ! type (xplasma), pointer :: s integer, intent(in) :: id ! id of list item character*(*), dimension(:), intent(in) :: chvals ! the character string values integer, intent(out) :: ier ! completion code

Home | Top |

xplasma_create_blackBox

A black box is basically a pair of buffers (one for integers, one for real*8 floating point) in which the data interpretation is completely left to the user. Xplasma internally makes use of black boxes for various purposes-- caches for numerical integration, data to speed coordinate transformations, and implementation of MCgrids. Each black box has a type code "itype". Types between 0 and 101 are used by xplasma. User defined types should select a type code outside this range. The item name should also be chosen to give a hint as to the meaning of the data. subroutine xplasma_create_blackBox(s,iname,itype,id,ier, & iarray,r8array,iasize,r8asize,label,units, & ia_ptr,r8a_ptr) ! create a blackBox -- a structure which contains the following ! -- a scalar integer TYPE (user defined meaning) ! -- an integer array ! -- a real*8 array ! Xplasma provides a mechanism for storage and retrieval of ! Black boxes; they are included in Xplasma NetCDF state files. ! The only methods supported are: ! xplasma_create_blackBox -- create the item; store the data ! xplasma_blackBox_info -- retrieve info on item (e.g. array sizes) ! xplasma_blackBox_retrieve -- retrieve black box item data ! Xplasma makes internal use of blackboxes, e.g. to define limiters ! or set up data for efficient numerical integration for flux surface ! averages. But, there are no reserved TYPE codes-- the significance ! of the blackBox TYPE, like the data itself, is entirely up to the ! user. type (xplasma), pointer :: s character*(*), intent(in) :: iname ! name of black box item integer, intent(in) :: itype ! Black Box type code (user defined). integer, intent(out) :: id ! id of newly created black box item integer, intent(out) :: ier ! completion code ! independently for the integer and floating point arrays, ! --either data must be provided, or, data sizes must be provided. integer, dimension(:), intent(in), optional :: iarray ! integer data real*8, dimension(:), intent(in), optional :: r8array ! real*8 data ! --but not both! integer, intent(in), optional :: iasize ! size of integer data integer, intent(in), optional :: r8asize ! size of real*8 data ! optional labels... character*(*), intent(in), optional :: label,units ! optional output: pointers to blackbox arrays (null if ierr.ne.0) integer, dimension(:), pointer, optional :: ia_ptr real*8, dimension(:), pointer, optional :: r8a_ptr

Home | Top |

xplasma_irhofun

This subroutine creates a lightly smoothed interpolating profile for an "integrated profile" function defined over a grid of the caller's choosing. An example of such a function would be: P_NBI(x) = Integrated NBI power, watts, from the plasma magnetic axis to flux surface "x". The input gives a grid identification, the data, i.e. the integrated value to each point on the grid, and the name to be used for identifying the function. The output is an identifier for the interpolating function. The control "iflag" is 1 for volume integrated density profiles; 2 for area integrated density profiles such as current drive profiles. NOTE-- smoothing can produce unexpected artifacts-- for example, regions of very small negative power density in a heating profile. But, the integrated power will be faithful to the original within half a zone width... !------------------------------------------ subroutine xplasma_irhofun(s,id_axis,zlbl,inprof,zprof,iflag,id,ierr) ! make XPLASMA profile -- integrated quantity; smooth by 1/2 zone width ! to insure smooth derivative from spline type (xplasma), pointer :: s integer, intent(in) :: id_axis ! axis id -- must be rho or akin to rho character*(*), intent(in) :: zlbl ! name for profile function to create integer, intent(in) :: inprof ! size of the integrated data profile real*8, intent(in) :: zprof(inprof) ! the integrated data provided ! if inprof = size(x_axis) zprof(1)=0 is expected ! if inprof = size(x_axis)-1 the axial data point ! is presumed to be omitted. integer, intent(in) :: iflag ! =1 -- volume normalization; ! derivative evaluations -> W/m^3, #/sec/m^3, etc. ! =2 -- area normalization; ! derivative evaluations -> A/m^2 (current density). integer, intent(out) :: id ! id of stored profile (if successful) integer, intent(out) :: ierr ! completion code, 0=OK. ! if an error occurs and ierr is set, id=0 will be returned. !-----------------------------------------------------------------

Home | Top |

xplasma_rzprof

subroutine xplasma_rzprof(s,fname,id_out,ier, & id_Rgrid,id_Zgrid, & ispline,sm_edge, & id_fun_in,lamda, & label,units,data) ! create a profile f(R,Z) from existing data with extrapolation, ! or with array data provided. ! either an existing function (id_fun_in) or input data (data) or ! both must be provided. ! modes of use: ! (id_fun_in omitted, data(:,:) provided) -- just use the data given ! (id_fun_in provided, data(:,:) omitted) -- use existing profile ! at id_fun_in to give variation inside plasma; use extrapolation ! based on distance map: f_outside = f_bdy*exp(-d/lamda) where ! d is the distance from the plasma ! (both id_fun_in and data(:,:) provided) -- use existing profile ! at id_fun_in to give variation inside plasma: use data to ! specify the variation beyond the plasma. ! ispline -- 0 = Bilinear, 1 = C1 Hermite, 2 = C2 Spline ! sm_edge -- Meters -- gives smoothing in vicinity of boundary ! a hat function convolution of half width sm_edge is applied ! in the vicinity of the boundary type(xplasma), pointer :: s character*(*), intent(in) :: fname ! name of profile to create... integer, intent(out) :: id_out ! ID of function just created integer, intent(out) :: ier ! completion code 0=OK !------ integer, intent(in), optional :: id_Rgrid,id_Zgrid ! R & Z grids to use ! (default: __RGRID & __ZGRID) integer, intent(in), optional :: ispline ! interpolation order ! -1: zonal step function; 0: piecewise linear; ! 1: C1 Hermite; 2: C2 Spline real*8, intent(in), optional :: sm_edge ! edge smoothing control ! default: no smoothing integer,intent(in), optional :: id_fun_in ! f(rho) from which to ! form f(R,Z) (default: 0, none) real*8, intent(in), optional :: lamda ! scrape off distance ! default: huge, making for flat extrapolation character*(*), intent(in), optional :: label,units ! labeling info real*8, intent(inout), dimension(:,:), optional :: data ! f(R,Z) data ! default: NONE ! data must be defined in extrapolated region-- internal region ! will be filled in...

Home | Top |

xplasma_rzprof_fun

!------------------------------------------------------- subroutine xplasma_rzprof_fun(s,fname,user_fcn,user_iarg,id_out,ier, & id_Rgrid,id_Zgrid,ispline,sm_edge,id_fun_in,no_extrap, & label,units) ! create a profile f(R,Z) from a user provided callable function ! possibly combined with existing data. ! the callable function covers the entire region inside the limiters ! if id_fun_in is omitted; it covers only the region outside the plasma ! and inside the limiters if id_fun_in is included. ! modes of use: ! (id_fun_in omitted) -- just use the given callable function. ! (id_fun_in provided)-- use existing profile ! at id_fun_in to give variation inside plasma; use the given ! function to define the variation beyond the plasma boundary. ! the region beyond the limiters is defined by a simple extrapolation. ! unless no_extrap is set, in which case the function is used even ! beyond the limiters. ! sm_edge -- Meters -- gives smoothing in vicinity of boundary ! a hat function convolution of half width sm_edge is applied ! in the vicinity of the boundary type(xplasma), pointer :: s character*(*), intent(in) :: fname ! name of profile to create... real*8, external :: user_fcn ! user provided function... integer, intent(in) :: user_iarg ! argument for user_fcn: ! real*8 function user_fcn(user_iarg,R,Z,Phi,ier) integer, intent(out) :: id_out ! ID of function just created integer, intent(out) :: ier ! completion code 0=OK !------ integer, intent(in), optional :: id_Rgrid,id_Zgrid ! R & Z grids to use ! (default: __RGRID & __ZGRID) integer, intent(in), optional :: ispline ! interpolation order ! -1: zonal step function; 0: piecewise linear; ! 1: C1 Hermite; 2: C2 Spline real*8, intent(in), optional :: sm_edge ! edge smoothing control ! default: no smoothing integer,intent(in), optional :: id_fun_in ! f(rho) from which to ! form f(R,Z) (default: 0, none) logical, intent(in), optional :: no_extrap ! T to suppress extrapolation ! beyond limiter. In this case user_fcn calls are used for (R,Z) even ! for points outside the limiter. character*(*), intent(in), optional :: label,units ! labeling info

Home | Top |

xplasma_mcgrid_define

This routine is used to create an irregular "Monte Carlo grid" or MCgrid. This is a grid used by the NUBEAM fast ion Monte Carlo code. The description of the MCgrid won't be repeated here, it is well described elsewhere in the document (look for "mcgrid"), including in the f77 section. subroutine xplasma_mcgrid_define(s,mcname,inth0,inrow,id,ierr, & nphi,udsym,label,nrow_ext_in,nrow_ext_out) type(xplasma), pointer :: s character*(*), intent(in) :: mcname ! name of MC grid integer, intent(in) :: inth0 ! no. of zones covering [0,pi] ! in 1st row at axis integer, intent(in) :: inrow ! no. of rows covering plasma integer, intent(out) :: id ! MC grid id returned (0 if error) integer, intent(out) :: ierr ! status code returned (0=OK) integer, intent(in), optional :: nphi ! number of Phi=const zones ! default:1 (axisymmetry) logical, intent(in), optional :: udsym ! updown symmetry flag ! default:.FALSE. (do not assume updown symmetric MHD equilibrium). character*(*), intent(in), optional :: label ! optional label for MCgrid integer, intent(in), optional :: nrow_ext_in ! no. of external rows ! requested (default: 0, meaning: use internal calculation). If non- ! zero value is given, inrow >= nrow_ext_in >= 3 will be enforced. integer, intent(out), optional :: nrow_ext_out ! actual no. of external ! zone rows created.

Home | Top |

xplasma_mcgrid_putobj

Use this method to create a profile over an MCgrid. The sister routine xplasma_mcgrid_getobj is used to retrieve the profile. subroutine xplasma_mcgrid_putobj(s,id_mcgrid,pname,id_p,ierr, & lstart0_th,ccwflag_th, & data_1d,data_2d,data_3d, & gridId1,gridId2,normcode, & label,units) ! define a profile "object" over a MCgrid. This can define ! a single data value per grid zone (use data_1d), or a vector of ! of data values per grid zone (use data_2d) or a 2d array of values ! per grid zone (use data_3d). type(xplasma), pointer :: s integer, intent(in) :: id_mcgrid ! MCgrid over which profile is defined. character*(*), intent(in) :: pname ! name of profile integer, intent(out) :: id_p ! xplasma ID of profile returned integer, intent(out) :: ierr ! status code (0=OK) ! theta indexing options logical, intent(in), optional :: lstart0_th ! default depends on symmetry logical, intent(in), optional :: ccwflag_th ! default: T ! lstart0_th=T means user's first theta zone lower bdy is 0; F means it ! is -pi. If defaulted: updown symmetric data assumed to start at 0; ! updown asymmetric data assumed to start at -pi. ! ccwflag_th=T means zone index increases as one goes along a row of ! zones at fixed radial index in a counter-clockwise direction; F means ! the opposite. T is the default. ! NOTE: similar options for phi mapping could be defined but that has ! not yet been done; may be an issue if/when we get beyond axisymmetry ! in XPLASMA... ! Although following arguments are optional, exactly one must be ! provided. The last dimension of the array must match the size ! of the entire grid, or of the subset of the grid covering the ! plasma (either or) real*8, intent(in), dimension(:), optional :: data_1d real*8, intent(in), dimension(:,:), optional :: data_2d real*8, intent(in), dimension(:,:,:), optional :: data_3d ! if data_2d or data_3d is specified-- it is desirable to specify ! a grid which corresponds to the 1st dimension of the data (default ! 0, meaning no grid was specified). integer, intent(in), optional :: gridId1 ! if data_3d is specified-- it is desirable to specify a grid which ! corresponds to the 2nd dimension of the data integer, intent(in), optional :: gridId2 ! (the actual data_2d or data_3d array dimensions will be one less ! than the corresponding grid sizes, for zone oriented "binned" data). !------------------- ! normalization code ! 0 - none -- default -- no information ! -1 - divide by vol(...) to get a density ! +1 - multiply by vol(...) to integrate a density ! +2 -- multiply by vol(...)*d[grid1]*d[grid2]/2 (FBM normalization) integer, intent(in), optional :: normcode !----------------- character*(*), intent(in), optional :: label character*(*), intent(in), optional :: units

Home | Top |

Xplasma_global_items

The following interfaces allow various xplasma global attributes or data items to be updated. Generally the values are retrieved with a call to xplasma_global_info using optional arguments subroutine xplasma_time_set(s,ztime,ier) ! set the time (seconds) affiliated with xplasma object "s". type (xplasma), pointer :: s real*8, intent(in) :: ztime integer, intent(out) :: ier retrieval: call xplasma_time_get(s,ztime,ier) ...or... call xplasma_global_info(s,ier, time=ztime) ------------------------------------------------------------- subroutine xplasma_bdytol_set(s,zbtol,ier) ! set the out-of-bounds tolerance for profile interpolations ! a maximum value of 1.0d-4 is allowed... type (xplasma), pointer :: s real*8, intent(in) :: zbtol integer, intent(out) :: ier retrieval: call xplasma_global_info(s,ier, bdytol=zbtol) ------------------------------------------------------------- subroutine xplasma_kmom_set(s,kmom,ier) ! set the # of Fourier moments for the optional Fourier representation ! of the current equilibrium. Default value is 16 not counting the ! 0'th moment. Minimum value is 2, max is 64. type (xplasma), pointer :: s integer, intent(in) :: kmom integer, intent(out) :: ier retrieval: call xplasma_global_info(s,ier, kmom=kmom) ------------------------------------------------------------- subroutine xplasma_ajac_maxvar_set(s,zvar,ier) ! set the amount of variation of det[J] to be allowed on a flux ! surface-- numerical control for detection of singular equilibria ! det J is det | dR/drho dR/dtheta | ! | dZ/drho dZ/dtehta | type (xplasma), pointer :: s real*8, intent(in) :: zvar integer, intent(out) :: ier retrieval: call xplasma_global_info(s,ier, ajac_maxVar=zvar) ------------------------------------------------------------- subroutine xplasma_field_ccw_set(s,ier, bphi_ccw,jphi_ccw) ! set the Bphi and/or Jphi orientations (for tokamak fields) ! CCW -- counter-clockwise ! 1 means (B or J is pointed) CCW looking down on machine from above ! -1 means CW, clockwise orientation. type (xplasma), pointer :: s integer, intent(out) :: ier ! status code, 0=OK ! for the toroidal magnetic field: integer, intent(in), optional :: bphi_ccw ! CCW value for Bphi ! for the toroidal plasma current: integer, intent(in), optional :: jphi_ccw ! CCW value for Jphi retrieval: call xplasma_global_info(s,ier, bphi_ccw=bphi_ccw, jphi_ccw=jphi_ccw) ------------------------------------------------------------- subroutine xplasma_rzOrder_set(s,irzOrder,ier) ! set the default fit order for R(rho,theta),Z(rho,theta) ! equilibrium specification ! min value: 1 -- C1 Hermite fit will be used ! max value: 2 -- C2 Spline fit will be used (default) type (xplasma), pointer :: s integer, intent(in) :: irzOrder integer, intent(out) :: ier retrieval: call xplasma_global_info(s,ier, rzOrder=irzOrder)

Home | Top |

Saving_xplasma_to_file

The entire contents of an xplasma object "s" can be written to a NetCDF file, with the following call: character*(*) filename ! i.e. unix path to file call xplasma_write(s,filename,ier) Other codes can load "s" (replacing any prior contents), with: call xplasma_read(s,filename,ier)

Home | Top |

Precision_and_F77_R4_interface

(With this section, original xplasma1 (f77 xplasma) documentation resumes). (old f77 xplasma 1 documentation) Note: the R4 interface is available for the fortran-77 xplasma routines only. The fortran-90 interface uses strictly REAL*8 precision throughout. The REAL*8 precision is compatible with fortran-90 floating point KINDs which map to this (8-byte 64 bit) precision which is available on all modern hardware. Advice: code with IMPLICIT NONE to avoid inadvertant creation of 4-byte reals; be careful with handling of hard coded constants. The xplasma software is written in REAL*8 precision. Routines described in the sections "Setup_Routines" and "Data_Access_Routines" are coded for REAL*8 floating point arguments. To call a fortran-77 style XPLASMA routine <name> instead with REAL arguments, use R4_<name>. For example, real*8 rhoR8,zeffR8 ! rhoR8 input, zeffR8 output real rhoR4,zeffR4 ! rhoR4 input, zeffR4 output integer id_Zeff ! Zeff profile id (input) integer ierr ! completion code, 0=OK (output) ! pass REAL*8 argument, get REAL*8 result rhoR8=0.5d0 call eq_rgetf(1,rhoR8,id_Zeff,0,zeffR8,ierr) ! pass REAL(*4) argument, get REAL(*4) result rhoR4=rhoR8 call r4_eq_rgetf(1,rhoR4,id_Zeff,0,zeffR4,ierr) --or-- fortran-90 codes can use xplasma_calls which defines "eq_rgetf" as a generic subroutine name. This means that if it the compiler sees that the routine has REAL*8 arguments it will call the usual eq_rget subroutine, but, if the compiler sees REAL*4 arguments, r4_eq_rgetf gets called. The compiler can also check that all arguments are of the right type and all arrays of the correct rank. The xplasma_calls module and the R4_ interfaces are automatically generated from the standard interfaces by means of a script which makes use of the "ftoken" tools in the NTCC modules library. CAUTION: for routines which take an external subroutine or function as an argument, the passed routine MUST use a REAL*8 precision interface.

Home | Top |

C_F77_interface

(old f77 xplasma 1 documentation) FROZEN in xplasma Version 2-- C interface routines exist for most of the Version 1 xplasma fortran-77 style interface, but the development has been discontinued, due to lack of evidence of use. PLEASE: if you are interested in further development of the xplasma C interface, please contact the authors (email dmccune@pppl.gov). The following is an edited description of the original C interface for Version 1 xplasma f77-style subroutine calls: All arguments for f77 xplasma (v1) routines were INTEGER, REAL*8, or CHARACTER*(*). C routines can use int* and double* to access the INTEGER and REAL*8 arguments. Generally, routines which have character arguments should have explicit C interface routines provided, as well. These routines will have names generated from the standard names by prepending "C_". fortran routine C callable routine eq_save F77NAME(c_eq_save) eqm_msgs F77NAME(c_eqm_msgs) (where F77NAME is a macro provided in NTCC module FPREPROC to "decorate" the names as needed to meet the requirements of the current system's ld or binary loader software). Where the standard fortran routines accept fortran CHARACTER data, the c routine will take a null terminated byte string instead. NTCC "Portlib" module routines are used for converting C-strings to fortran-strings. The C_ interfaces were generated automatically from standard xplasma sources, using tools from the ftoken module in the NTCC modules library. (These tools are not extensible to the fortran-90 interfaces of XPLASMA v2).

Home | Top |

F77_Setup_Routines

(old f77 xplasma 1 documentation) [This is the original xplasma 1.0 documentation]. The xplasma setup routines are used to load the plasma field equilibrium and plasma parameters into the xplasma module, with generation of spline or Hermite coefficients as needed for later use by the Data Access Routines (Note the subsections describe only the standard routines, although the R4_ and C_ interfaces are also available).

Home | Top |

Error_Message_Control

By default, xplasma error messages are written to stdout via FORTRAN i/o unit number 6. To override this: ! input integer ilun_msgs ! FORTRAN i/o unit number for messages character*(*) msg_file ! file to receive messages ! output integer ierr ! completion code, returned, 0=OK call eqm_msgs(ilun_msgs,msg_file,ierr) ...subroutine eqm_msgs tries to open `msg_file' on unit ilun_msgs, if the `msg_file' character string is non-blank. If it is blank, the error message i/o unit number is still changed to ilun_msgs. If a file open is attempted and fails, ierr.ne.0 is returned.

Home | Top |

xplasma_calls

(old f77 xplasma 1 documentation) This module defines the fortran-77 xplasma calls only. Included with "xplasma" is an "interface" module for fortran-90 code, which can be accessed by inserting the line use xplasma_calls at the top of each fortran-90 subroutine that makes xplasma subroutine calls. This module does the following: (1) allows generic names (e.g. eq_rgetf and eqm_frhochi) to be used for both REAL*8 and REAL(*4) codes. Without the module, REAL(*4) codes must call the R4 interface routines (e.g. r4_eq_rgetf, r4_eqm_frhochi) by their full names. (2) allows the compiler to check all subroutine arguments at compile time. The use of this module is optional. There are situations where functionally correct calls to xplasma routines will not survive the compiler's argument check.

Home | Top |

Initialization

To delete the contents of xplasma, e.g. as a first step to storing plasma parameters and equilibrium at a new time: ! input character*(*) model_string ! name of equilibrium model integer ilaxi ! axisymmetry flag (1 for TRUE). call eqm_select(model_string,ilaxi) `model_string' contains a short string which may identify something about the current or intended contents of xplasma. This string is used only as a prologue for certain messages. Caution: as of May 2000, ilaxi=1 is required. Non-axisymmetry is not yet supported in xplasma. As xplasma is meant to contain a timeslice representing the current plasma equilibrium and profiles, the user may choose to associate a time with the current contents of xplasma, by means of the call: real*8 ztime ! physical time of xplasma data call eqm_time(ztime)

Home | Top |

Customizations

(old f77 xplasma 1 documentation) The call to `eqm_select' sets default values for certain user adjustable model characteristics: (a) fit order for equilibrium representation {R(rho,chi),Z(rho,chi)}. Default is iorder=2 (splines). However iorder=1 (Akima Hermite) is also allowed. (b) underlying Fourier representation-- highest order retained Fourier moments. Default is 8; for some applications it may be desirable to reduce this. Details: Axisymmetric "xplasma", based on pspline [1], can use either 2nd order (piecewise bicubic spline) or 1st order (piecewise bicubic Hermite) interpolation functions to represent flux surface geometry {R(rho,chi),Z(rho,chi)}. The default is to use splines (iorder=2). This produces a smoother output for smooth input data, but for input data that is not smooth there is a potential for "ringing", an oscillatory propagation of a sharp feature in the input data. By using Hermite (iorder=1), such ringing can be suppressed at a cost to overall smoothness. integer iorder ! 2 for R,Z splines (default) ! 1 for R,Z bicubic Hermite representation call eqm_rzordr_set(iorder) Later, use the following call to determine what setting was chosen call eq_rzordr_get(iorder) ** This routine should be called right after eqm_select is called. [1] http://w3.pppl.gov/NTCC/PSPLINE/pspline.html When "xplasma" is built from a psi(R,Z) representation (e.g. a G-EQdsk file), part of the process involves a Fourier analysis and recomposition. By default, 8 moments are retained, but this number can be changed by the call: kmom=5 ! retain moments 0:5 only in Fourier composition call xmoments_kmom_set(kmom) In systems with known well behaved boundaries, the higher order moments may not be needed and can be a source of "noise". The call to "xmoments_kmom_set" will effect the results of subsequent calls to "xmoments_kmom_get" and "eqmom_Rcos" and similar routines, after the xplasma setup is complete, as described in the subsection "Fourier Spline Representation" under the description of Data Access Routines.

Home | Top |

customized_initialization_example

! fit order for (R,Z) and B(rho,chi) components integer, parameter :: iordr_rz = 2 ! 2 for spline 1 for Hermite ! axisymmetry flag (axisymmetry required, ilaxi=1 REQUIRED). integer, parameter :: ilaxi = 1 ! maximum retained Fourier Moments specification integer, parameter :: kmom = 5 ... call eqm_select('your_xplasma',ilaxi) call eqm_rzordr_set(iorder_rz) call xmoments_kmom_set(kmom)

Home | Top |

Free_up_memory

(old f77 xplasma 1 documentation) To erase xplasma contents and free up the memory used in the xplasma module: call eqm_free

Home | Top |

Packages

(old f77 xplasma 1 documentation) The full setup of an xplasma MHD equilibrium representation is fairly complicated, involving as it does the requirement to define a large number of data items. Common sources for equilibrium data are: TRANSP runs in files or MDS+, and EFIT (G-EQDSK) data in files or MDS+. Canned routines, encapsulating the appropriate sequence of xplasma "eqm" calls, are provided for the construction of xplasma representations from these standard data sources.

Home | Top |

trxplib_module

call trx_connect(...) ! connect to a TRANSP run call trx_time(...) ! set time of interest call trx_init_xplasma(...) ! xplasma initialization call trx_mhd(...) ! build xplasma from TRANSP MHD data call trx_wall_rz(...) ! acquire limiter locations (optional) call trx_scal(...) ! acquire any TRANSP scalar data item call trx_prof(...) ! acquire any TRANSP profile data item Xplasma "vacuum field extrapolation" software allows an environment to be created in which full field information is available in (R,Z) space or in magnetic coordinates. Details are given in the documentation of the NTCC module "trxplib".

Home | Top |

eqm_fromgeqdsk

(old f77 xplasma 1 documentation) Use this routine to acquire all xplasma MHD data from an EFIT G-EQDSK file. The software finds closed contours of psi(R,Z), equally spaced in sqrt(toroidal flux), from which to construct the magnetic-coordinate based equilibrium representation, at the same time preserving the (R,Z) information: psi(R,Z), all components of B vs. (R,Z) as bicubic Hermite interpolating functions. To use this routine: ! identifying information character*30 label ! xplasma label character*150 zfile ! G-EQDSK file path or MDS+ path ! or "index file" expression... ! resolution of mag. coordinates representation integer ns ! abs(ns) = number of flux surfaces integer nth ! number of theta grid points ! specify ns.lt.0 for Hermite instead of Spline fits of ! R(rho,chi),Z(rho,chi),BR(rho,chi),BZ(rho,chi),[mod(B)](rho,chi). ! Adjustment factor for psi(bdy) real*8 fbdy ! psi(bdy(mag)) = fbdy*psi(bdy(efit)) ! Alternate bdy adjustment option: minimum curvature parameter real*8 cbdy ! require curv(bdy)/a .gt. cbdy ! (R,Z) extension flag integer irz ! =1: extend xplasma representation to ! cover EFIT's (R,Z) box; define ! psi(R,Z) & B(R,Z) as xplasma objects. ! =0: do not extend (less work). ! error status code returned integer ierr ! returns 0 = OK ... ... call eqm_fromgeqdsk(label,zfile,ns,nth,fbdy,cbdy,irz,ierr) The factor "fbdy" is allowed to vary between 0.95 and 1.00. This may be needed because some G-EQDSK data may give a psi(bdy) value which corresponds to an open field line or the exact last closed flux surface which has a shape that is kinked through a separatrix. For codes requiring a smooth boundary, fbdy = ~ 0.99 may be needed. BUT: read on. The factor "cbdy" gives a semi-automatic way to select a boundary contour that is suitable. The software will reject a boundary contour if any of the following conditions arise: -- contour reverses direction or escapes (R,Z) box (open field line) -- minimum curvature divided by midplane minor radius is less than "cbdy". The result is effective in preventing a "kinked" contour just inside a separatrix, which might cause numerical problems for inverted coordinate systems or equilibrium representations downstream. The maximum allowed value of cbdy is 0.2; we recommend: fbdy = 1.000 cbdy = 0.080

Home | Top |

Call examples:

fbdy = 1.000 cbdy = 0.080 ns = 51 nth = 76 ! read from file "geqdsk.dat"; create xplasma "G-EQDSK-file" call eqm_fromgeqdsk('G-EQDSK-file','geqdsk.dat',ns,nth,fbdy,cbdy, & ierr) if(ierr.ne.0) then ... [ process error ] ! or, read from MDSplus zfile = 'MDS+:EUROPA.PPPL.GOV:8501:EFIT01(103875;t=.25)' call eqm_fromgeqdsk('G-EQDSK-MDSplus',zfile,ns,nth,fbdy,cbdy,ierr) if(ierr.ne.0) then ... [ process error ] The string specification "zfile" contains the following components: MDS+[/NOREDUCE]:<server-name[:port]>:<tree-name>(<shot-no>;t=<time>) Generally, each experiment supports an MDSplus server for its MDSplus data; in the case of the NSTX experiment at PPPL, the server to use is EUROPA.PPPL.GOV (port 8501). The data is taken from tree "EFIT01", NSTX shot 103875, at time t=0.25. Because the option "/REDUCE" is set by default, the eqm_fromgeqdsk call only caches the single time point of EFIT data closest to 0.25 seconds; with "/NOREDUCE", it would cache the entire time variation of the EFIT tree in memory, making subsequent calls to eqm_fromgeqdsk on the same shot but at different times much faster, since a networked data access operation would be avoided. Generally, collaborators need to obtain permission to read data from MDSplus servers maintained by tokamak experiments, and, the user should consult with responsible scientists about the suitability of selected data. Note that if <server-name> is given as "LOCAL" or "CONNECTED", then, the eqm_fromgeqdsk call does not attempt to connect to and later disconnect from the MDSplus server. This is desirable e.g. if the calling code is taking care of MDSplus server connect/disconnect operations. Note that if <tree-name> is given as "OPENED", then, eqm_fromgeqdsk does not attempt to open and later close the EFIT MDS+ tree. This is desirable if the calling code is taking care of the MDS+ tree open and close operations.

Home | Top |

More_MDSplus_access_info

eqm_fromgeqdsk can be used to access G-EQDSK data over the net from an MDSplus server. To do this, one simply uses an MDSplus path instead of a file path in the subroutine's "zfile" argument. Here are comments from the code on this subject: c c zfile - a file path, e.g. /u/efit/nstx/g123456_6800.eqdsk c --or-- c an MDSplus path: c c MDS+[/reduce|/noreduce]:<server[:port]|LOCAL>:<tree>(<shot>;t=<time>) c c where the initial MDS+ specifies MDSplus not a file; c c /reduce means just read the specified timeslice (this is the default) c /noreduce means read and cache data from all available EFIT times c c <server...> specifies the MDSplus server, can be "LOCAL" c c <tree> specifies the MDSplus tree, e.g. "EFIT01" or "EFIT02" c c <shot> specifies the MDSplus (or experiment) shot number c <time> is an ascii encoding of the currently desired time of interest c c examples of valid MDSplus paths: c c MDS+:LOCAL:EFIT01(104370;t=0.15) c MDS+/reduce:europa.pppl.gov:8501:EFIT01(104370;t=1.0e-1) c MDS+/noreduce:cmoda.psfc.mit.edu:EFIT09(123456789;t=2.3) c The /reduce option (default) is recommended for codes which are really only going to look at one timepoint. For a code that is going to loop over time, the /noreduce option allows all the data to be read in and cached, obviating the need for repeated connections to the remote MDSplus server. Note: option names, server names and tree-names are case-insensitive. Thus for example, "/reduce" and "/REDUCE" have the same effect. Also, the time keyword after the shot number can be "t", "T", "time" or "TIME" or "TiMe" or any combination which when mapped to uppercase yields "T" or "TIME".

Home | Top |

EFIT_INDEX_files

In order to support access to time dependent EFIT datasets without having to use MDS+, an alternative file-based access scheme is supported: access indirectly via an "EFIT_INDEX" file. This is a file that correlates G-eqdsk filenames with physical times in seconds. For example: [tshare@dhcp-dmccune scrunch2]$ cat 8500index.txt ntimes=4 path='/pub/outgoing/pshare' time=0.15 filename=g008500.00150 time=0.20 filename=g008500.00200 time=0.25 filename=g008500.00250 time=0.294 filename=g008500.00294 G-eqdsk files can be referred to directly by filename, or, indirectly via an index file. Thus in the above example, the same result would follow from an eqm_fromgeqdsk call with argument zfile = "g008500.00294" or with zfile = "EFIT_INDEX:8500index.txt( 4)" (blanks are allowed between the parentheses in which the time index is given). Note that the "path" field is ignored; the g-eqdsk files are expected to be found in the same directory in which the index file itself is found. This provides a mechanism for correlating files in g-eqdsk file collections with specific times, without having to parse time information out of the filename, a procedure which tends to be different at each EFIT user site.

Home | Top |

eqm_wr_geqdsk

(old f77 xplasma 1 documentation) If EFIT data is acquired via MDSplus, then there is an option to write a local G-EQDSK file from the MDSplus data: character*(*) file_out ! name of file to write integer ier ! completion code returned, 0=OK call eqm_wr_geqdsk(file_out,ier) This provides a mechanism for generating G-EQDSK files from remote MDSplus trees. The data is as acquired from the MDSplus tree, i.e. not modified by xplasma. There is another routine eq_geqdsk, which can generate and write a G-EQDSK file from any XPLASMA equilibrium, howsoever obtained. But this method involves interpolation and so is less accurate than using eqm_wr_geqdsk if the purpose at hand is to write an MDSplus time slice to disk.

Home | Top |

Flux_Coordinate_Grids

(old f77 xplasma 1 documentation) The radial flux coordinate is designated as "rho" in xplasma documentation. The poloidal angle flux coordinate is designated as "chi" in xplasma documentation. Before any spline, Hermite, or piecewise linear f(rho) can be defined, rho itself must be given; before any bicubic spline, Hermite, or bilinear f(chi,rho) can be defined, both rho and chi must be given. The "rho" coordinate grid is to be surface oriented, covering the entire plasma from magnetic axis to numeric boundary near the last closed flux surface. The "chi" coordinate is periodic with period 2pi, i.e. chi(nchi)-chi(1)=2pi. Usually the coordinate as given spans [0,2pi] or [-pi,pi]. All grids x must be strict ascending, i.e. x(j).gt.x(j-1). Even spacing is not required. Once the "basic" rho, chi grids are defined, alternate rho, chi grids can also be given. This gives a foundation for support, within "xplasma", of objects with different radial and/or angular resolution.

Home | Top |

Radial_Flux_Coordinate(rho)

(old f77 xplasma 1 documentation) The following call sets the grid for the radial flux coordinate. It is recommended to use the following flux coordinate: normalized sqrt(toroidal flux), range 0 to 1 The problem with using a flux coordinate psi directly, is that grad(psi) -> 0 on axis, which means, for any f such that grad(f) does NOT -> 0 on axis, df/dpsi -> +/-infinity on axis; this singularity leads to numerical problems e.g. "ringing" in spline interpolation. ! input integer nsurf ! no. of flux surfaces, including axis real*8 zrho(nsurf) ! flux coordinate, strict ascending real*8 ztol ! d(zrho) variance tolerance ! ztol -- if the deviation of actual rho grid spacing varies ! from the average spacing by less than ztol, then, the ! grid is deemed evenly spaced. ! ...average spacing is (zrho(nsurf)-zrho(1))/(nsurf-1) ! ...actual spacing is (zrho(j+1)-zrho(j)) ! with j in {1,2,...,(nsurf-1)} ! output integer id_rho ! xplasma id code for rho grid integer ierr ! completion code, 0=OK ... call eqm_rho(zrho,nsurf,ztol,id_rho,ierr)

Home | Top |

Poloidal_Angle_Coordinate(chi)

(old f77 xplasma 1 documentation) The following call sets up the grid for the poloidal angle coordinate. Note that the grid array is either input or output, depending how the automatic generation switch is set. The xplasma software makes no restriction about the type of poloidal angle coordinate-- "Hamada", "Boozer", "Vmec", all are acceptable. However, for a plasma poloidal cross section to the right of the axis of symmetry, an increasing poloidal angle parameter is expected to describe the flux surface going around in a counterclockwise direction, and, chi=0.0 is by convention associated with the large major radius side of the plasma. The first and last points in the chi grid must differ by exactly 2pi. Typically the given grid covers the range [0,2pi] or [-pi,+pi]. ! input integer inum_chi ! no. of chi grid points integer iauto ! =1 to generate automatic chi grid real*8 ztol ! d(zchi) variance tolerance ! ztol -- if the deviation of actual chi grid spacing varies ! from the average spacing by less than ztol, then, the ! grid is deemed evenly spaced. If iauto=1, ztol is ! ignored; the iauto=1 grid is always evenly spaced. ! input/output real*8 zchi(inum_chi) ! chi grid, output if iauto=1 ! output integer id_chi ! xplasma id code for chi grid integer ierr ! completion code, 0=OK ... call eqm_chi(zchi,iauto,inum_chi,ztol,id_chi,ierr) Although the poloidal angle grid is always stored internally with the counter-clockwise orientation, clockwise grids can be provided as input using this call: call eqm_chi_setccw(-1,zchi,iauto,inum_chi,ztol,id_chi,ierr) The grid orientation will then be reversed prior to storage. Note however that XPLASMA does not "remember" that a clockwise oriented grid was provided as input. Subsequent calls involving objects defined over a clockwise grid must indicate this explicitly each time. In the XPLASMA f77 interface this is done by specifying a negative value for an array size, as documented on a routine-by-routine basis below. In the f90 interface, this is indicated by setting a flag in an optional argument.

Home | Top |

Alternate_grids

(old f77 xplasma 1 documentation) Once the basic "rho" and "chi" coordinate grids have been established, or indeed once any coordinate grid is established, the user can define alternate grids for these same coordinates. An alternate grid has the following properties: * strict ascending sequence * spans exactly the same range as the original grid * need not contain the same number of grid points. Thus, for example, if zrho(1:nsurf) is the real*8 array of values used to define "rho" in a call to eqm_rho, zrho2(1:nsurf2) can be a regridding of zrho(1:nsurf) if zrho2(j).lt.zrho(j+1) for j = 1 to nsurf2-1, and, zrho(1)=zrho2(1), and, zrho(nsurf)=zrho2(nsurf2). To establish an alternate grid, use subroutine `eqm_uaxis': ! input: character*(*) aname ! name for alt. grid, not "RHO" or "CHI" integer id_orig ! id of original grid ! for which new grid is an alternate, ! or, zero if this is a new "user grid". integer iper ! =1 if this is a periodic dimension, ! 0 if not periodic ! -1 if periodic with clockwise orientation integer inum ! #of points in alternate grid real*8 zaxis(inum) ! the alternate grid points real*8 ztol ! even spacing tolerance ! ! output: integer id ! xplasma id code for this new grid integer ierr ! completion code, 0=OK ... call eqm_uaxis(aname,id_orig,iper,zaxis,inum,ztol,id,ierr) ! notes: ! * aname should be unique & specific, i.e. not "RHO" or "CHI" ! or "R" or "Z". NAMES ARE CASE INSENSITIVE. ! * iper=1 should be set for angle-type coordinate grids ! * id_orig should be the value returned from eqm_rho or eqm_chi ! or eqm_rzgrid. ! * inum.ge.4 is required. ! * zaxis must be strict ascending and its endpoints must match ! the endpoints of the "id_orig" axis. ! * ztol sets a tolerance for endpoint matching and also for ! determining if this grid is evenly spaced: if ! dzavg = (zaxis(inum)-zaxis(1))/(inum-1), and, ! maxval(abs(zaxis(2:inum)-zaxis(1:inum-1)-dzavg)).lt.ztol ! then the grid is declared evenly spaced, and the faster ! even spacing algorithm can be used for zone lookup during ! interpolation.

Home | Top |

Mod(B)_grid

(old f77 xplasma 1 documentation) A grid of ascending mod(B) values can be defined. This might be used e.g. to gather data binned by field strength. If this is needed, use the following... ! input: integer inum ! #of mod(B) grid points wanted integer iauto ! =1 for automatic grid generation ! input or output: real*8 zbb(inum) ! mod(B) grid, input if iauto=0 ! output if iauto=1 ! input: real*8 ztol ! even spacing tolerance ! output: integer id_Bgrid ! xplasma axis id for mod(B) grid ! output: integer ierr ! completion status code, 0=OK ... call eqm_bbin(zbb,iauto,inum,ztol,id_Bgrid,ierr) ! note: if the variance of delta(zbb) = zbb(j+1)-zb(j) from ! <delta(zbb)> = (zbb(inum)-zbb(1))/(inum-1) is .lt. ztol, ! then the grid is considered evenly spaced, allowing use ! of a faster lookup algorithm

Home | Top |

User_grids

(old f77 xplasma 1 documentation) The eqm_uaxis routine can also be used to establish an arbitrary "user grid", i.e. an ascending sequence of numbers spanning some specified range. For example, an energy grid, pitch angle grid, or mod(B) grid might be defined. To establish a user grid, use eqm_uaxis (cf Alternate_grids section), but set id_orig=0 to indicate a new grid type unrelated to grids previously defined. Data Access routines are provided for efficient binning into user defined axis grids.

Home | Top |

Summary

(old f77 xplasma 1 documentation) ! set up rho grid subroutine eqm_rho(zrho,nsurf,ztol,id_rho,ierr) ! set up chi grid subroutine eqm_chi(zchi,iauto,inum_chi,ztol,id_chi,ierr) ! set up alternate grid (axis) subroutine eqm_uaxis('grid-name',id_orig,iper,zaxis,inum,ztol, > id,ierr)

Home | Top |

function_definitions

(old f77 xplasma 1 documentation) The following item types can be defined: f(rho) e.g. psi(rho),q(rho),Te(rho), ... f(rho,chi) e.g. R(rho,chi), Z(rho,chi) f(R,Z) e.g. Te(R,Z): Te(rho) mapped and extrapolated into the scrape-off layer. Generally, data for items can be "updated" by calling the function set-up routine with iorder=99 set. However, R(rho,chi) and Z(rho,chi) cannot be updated in this manner -- xplasma must be re-initialized if the flux surface geometry is to change. Caution: xplasma generally cannot enforce consistency of data items just because one is updated. If "G" or "PSI" are updated, then B(rho,chi) will be updated as well. However, an update of B(R,Z) would require a separate call by the user. Although there are some situations where updates of profiles in the context of a fixed geometry might be useful, such methods should be used with care. More typically, as plasma profiles change the flux surface geometry also changes; in this case, xplasma must be re-initialized and reconstructed from scratch for each new timeslice.

Home | Top |

_1d_Profiles_f(rho)_etc

(old f77 xplasma 1 documentation)

Home | Top |

eqm_rhofun

(old f77 xplasma 1 documentation) A special routine is provided for setting up a profile function f(rho). This profile can be a piecewise cubic spline, piecewise cubic Hermite, or piecewise linear. Thus: ! input: integer iorder ! "order" of interpolating function integer id_rho ! rho coordinate grid id (orig. or alt.) character*(*) fname ! unique name of profile function real*8 zdata(*) ! the function data (#pts: id_rho axis) integer ibc1 ! boundary condition code, at rho(1) real*8 zbc1 ! boundary condition data, at rho(1) integer ibc2 ! boundary condition code, at rho(nrho) real*8 zbc2 ! boundary condition data, at rho(nrho) ! output: integer id_rhofun ! unique xplasma id for this function integer ierr ! completion code, 0=OK ... call eqm_rhofun(iorder,id_rho,fname,zdata, > ibc1,zbc1, > ibc2,zbc2, > id_rhofun,ierr) if(ierr.ne.0) then [...handle error...] endif ! notes: ! * the amount of data expected in zdata(...) depends on the selected ! axis (id_rho) and the interpolation order (iorder). Let nrho= ! the number of data points in the "id_rho" grid. Then, ! ! => iorder = 0 ... piecewise linear function, zdata(1:nrho) ! must be defined; ! => iorder = 1 ... piecewise cubic Hermite fcn, zdata(1:nrho) ! must be defined, Akima Hermite is used; ! => iorder = 2 ... piecewise spline function, zdata(1:nrho) ! must be defined; ! for iorder.ge.0, the interpolating function f(rho) will satisfy ! f(rho(i))=zdata(i) for i=1:nrho. ! ! note: set iorder = 99 to update data for an already defined ! item. The original interpolation method is retained and ! the axis id must match. ! ! * the name 'fname' must uniquely identify the function. The ! names "R","Z","RHO,"CHI","G","PSI", "BR", "BZ", "BPHI" and ! "BMOD" are reserved to xplasma. NAMES ARE CASE INSENSITIVE. ! ! * boundary conditions -- ignored if iorder.le.0 ! ibc1,zbc1 -- controls at rho(1), i.e. the "magnetic axis" ! ibc2,zbc2 -- controls at rho(nrho), i.e. the "plasma bdy". ! options: ! ibc1|2 = 0 -- "not a knot" or default at axis | bdy ! ibc1|2 = 1 -- zbc1|2 contains df/drho at the axis | bdy ! ibc1|2 = 2 -- splines only -- zbc1|2 contains d2f/drho2 at ! the axis | bdy. ! ! * id_rhofun -- on normal exit (ierr.eq.0), id_rhofun contains the ! xplasma index to the interpolating function. This may be worth ! saving for efficient access to the interpolating function.

Home | Top |

eqm_irhofun

(old f77 xplasma 1 documentation) This subroutine creates a lightly smoothed interpolating profile for an "integrated profile" function defined over a grid of the caller's choosing. An example of such a function would be: P_NBI(x) = Integrated NBI power, watts, from the plasma magnetic axis to flux surface "x". The input gives a grid identification, the data, i.e. the integrated value to each point on the grid, and the name to be used for identifying the function. The output is an identifier for the interpolating function. The control "iflag" is 1 for volume integrated density profiles; 2 for area integrated density profiles such as current drive profiles. subroutine eqm_irhofun(id_axis,zlbl,inprof,zprof,iflag,id,ierr) ! make XPLASMA profile -- integrated quantity; smooth by 1/2 zone width ! to insure smooth derivative from spline implicit NONE integer, intent(in) :: id_axis ! axis id -- must be rho or akin to rho character*(*), intent(in) :: zlbl ! name for profile function to be created integer, intent(in) :: inprof ! size of the integrated data profile real*8, intent(in) :: zprof(inprof) ! the integrated data provided ! if inprof = size(x_axis) zprof(1)=0 is expected ! if inprof = size(x_axis)-1 the axial data point ! is presumed to be omitted. integer, intent(in) :: iflag ! =1 -- volume normalization; ! derivative evaluations -> W/m^3, #/sec/m^3, etc. ! =2 -- area normalization; ! derivative evaluations -> A/m^2 (current density). integer, intent(out) :: id ! id of stored profile (if successful) integer, intent(out) :: ierr ! completion code, 0=OK. ! if an error occurs and ierr is set, id=0 will be returned.

Home | Top |

Required_1d_Magnetic_Profiles

(old f77 xplasma 1 documentation) In order for (axisymmetric) xplasma to form a complete specification of the magnetic field, two 2d profile functions must be provided: g -- name must be "g" or "G" -- g(rho) is the toroidal field in the form R*Btor. MKS units would be Tesla*m. Units given must be consistent with other data given to xplasma. psi-- name must be "psi" or "PSI" -- poloidal flux function psi(rho) -- 1/(2*pi) * area integral of poloidal field through flux zones. MKS units would be Webers/radian. Units given must be consistent with other data given to xplasma. The field specification will be completed by giving the flux surface geometry R(chi,rho) and Z(chi,rho). Then, Btor(chi,rho) = g(rho)/R(chi,rho) Bpol(chi,rho) = grad(psi(rho))/R(chi,rho) = [d(psi)/d(rho)]*grad(rho)/R(chi,rho) ------------- use eqm_rhofun to set up the g and psi profiles in xplasma.

Home | Top |

eqm_mark_pmhd

(old f77 xplasma 1 documentation) Another profile associated with MHD equilibrium is the plasma pressure. There are some variations as to how this may be defined, and the name for the pressure profile within xplasma is not standardized. However, a specific profile can be "tagged" as "the" MHD equilibrium pressure profile by calling this routine: integer :: id_p ! MHD pressure profile id (1d profile f(rho)) (input) integer :: ier ! status code returned (0=normal) (output) call eqm_mark_pmhd(id_p,ier)

Home | Top |

eqm_f1d

(old f77 xplasma 1 documentation) This routine is provided for setting up a general 1d profile function f(x); x is a user defined axis with a presumption of no particular relationship to magnetic or cylindric coordinates. This profile can be a piecewise cubic spline, piecewise cubic Hermite, or piecewise linear. Thus: ! input: integer iorder ! "order" of interpolating function integer id_axis ! user specified x axis character*(*) fname ! unique name of profile function real*8 zdata(*) ! the function data (#pts: id_rho axis) integer ibc1 ! boundary condition code, at rho(1) real*8 zbc1 ! boundary condition data, at rho(1) integer ibc2 ! boundary condition code, at rho(nrho) real*8 zbc2 ! boundary condition data, at rho(nrho) ! output: integer id_f1d ! unique xplasma id for this function integer ierr ! completion code, 0=OK ... call eqm_f1d(iorder,id_axis,fname,zdata, > ibc1,zbc1, > ibc2,zbc2, > id_f1d,ierr) if(ierr.ne.0) then [...handle error...] endif These arguments are a 1-to-1 analog to the arguments of eqm_rhofun. The notes to the description of arguments for that routine apply here as well.

Home | Top |

Summary

(old f77 xplasma 1 documentation) To set up a profile f(rho)... call eqm_rhofun(iorder,id_rho,'f-name',zdata, > ibc1,zbc1,ibc2,zbc2, > id_rhofun,ierr) if(ierr.ne.0) then [...handle the error...] endif The "G" and "PSI" profiles are required, if xplasma is to generate a continuous differentiable field representation. To set up a profile f(x), for a user defined x axis... call eqm_f1d(iorder,id_axis,'f-name',zdata, > ibc1,zbc1,ibc2,zbc2, > id_f1d,ierr) if(ierr.ne.0) then [...handle the error...] endif

Home | Top |

_2d_Profiles_f(chi,rho)

(old f77 xplasma 1 documentation) This section discusses methods for defining 2d profile functions f(chi,rho). To have an (axisymmetric) equilibrium, at least R(chi,rho) and Z(chi,rho) must be defined. R(chi,rho) and Z(chi,rho) must be defined before any other f(chi,rho), and one of the special purpose routines (eqm_rzmag, eqm_rzmagb, eqm_rzmag2) must be used for this. Once R and Z are defined, additional functions f(chi,rho) can be defined using eqm_frhochi.

Home | Top |

eqm_rzmag

(old f77 xplasma 1 documentation) ! ! establish R(chi,rho) and Z(chi,rho) bicubic splines. ! periodic in chi, not-a-knot BC @ rho bdys ! (for more control of rho BCs use eqm_rzmagb) ! ! ***note the R & Z arrays must be defined on the same grids as ! were specified by earlier eqm_rho and eqm_chi calls. ! ! input arguments: ! integer id1,id2 ! R,Z array dimensions real*8 Rarr(id1,id2) ! R array - (1:nchi)x(1:nrho) points used real*8 Zarr(id1,id2) ! Z array - (1:nchi)x(1:nrho) points used ! integer idrho ! =1: id1 is "rho" dimension; =2: id2 is. ! ! if idrho.eq.1, id1.ge.nrho & id2.ge.nchi ! R(1:nrho,1:nchi) & Z(1:nrho,1:nchi) are used ! if idrho.eq.2, id1.ge.nchi & id2.ge.nrho ! R(1:nchi,1:nrho) & Z(1:nchi,1:nrho) are used ! ! output arguments: ! integer id_R ! xplasma id for "R" bicubic spline (returned) integer id_Z ! xplasma id for "Z" bicubic spline (returned) ! integer ierr ! completion code (0 = OK) ! .... call eqm_rzmag(Rarr,Zarr,id1,id2,idrho, id_R,id_Z,ierr)

Home | Top |

eqm_rzmagb

(old f77 xplasma 1 documentation) ! ! establish R(chi,rho) and Z(chi,rho) bicubic splines. ! periodic in chi, not-a-knot BC @ rho bdys ! use the BC controls to specify the boundary conditions at ! rho(1) (mag. axis) and rho(nrho) (plasma boundary); there ! are separate BC controls for R and for Z. ! ! ***note the R & Z arrays must be defined on the same grids as ! were specified by earlier eqm_rho and eqm_chi calls. ! ! input arguments: ! integer id1,id2 ! R,Z array dimensions real*8 Rarr(id1,id2) ! R array - (1:nchi)x(1:nrho) points used real*8 Zarr(id1,id2) ! Z array - (1:nchi)x(1:nrho) points used ! integer idrho ! =1: id1 is "rho" dimension; =2: id2 is. ! ! if idrho.eq.1, id1.ge.nrho & id2.ge.nchi ! R(1:nrho,1:nchi) & Z(1:nrho,1:nchi) are used ! if idrho.eq.2, id1.ge.nchi & id2.ge.nrho ! R(1:nchi,1:nrho) & Z(1:nchi,1:nrho) are used ! ! ** boundary conditions ** ! ! BC controls are as in "pspline": 0 -- default, 1 -- fix df/drho ! 2 -- fix d2f/drho2 ...f is R or Z ! ! for BC types 1 & 2, data must be supplied: nchi 1st or 2nd ! derivative values, repsectively; for other types the "zbc" ! arrays are ignored. ! integer ibcR0 ! R BC type @ rho(1) real*8 zbcR0(*) ! R BC data @ rho(1) (if needed) integer ibcR1 ! R BC type @ rho(nrho) real*8 zbcR1(*) ! R BC data @ rho(nrho) (if needed) ! integer ibcZ0 ! Z BC type @ rho(1) real*8 zbcZ0(*) ! Z BC data @ rho(1) (if needed) integer ibcZ1 ! Z BC type @ rho(nrho) real*8 zbcZ1(*) ! Z BC data @ rho(nrho) (if needed) ! ! output arguments: ! integer id_R ! xplasma id for "R" bicubic spline (returned) integer id_Z ! xplasma id for "Z" bicubic spline (returned) ! integer ierr ! completion code (0 = OK) ! .... call eqm_rzmagb(Rarr,Zarr,id1,id2,idrho, & & ibcR0,zbcR0,ibcR1,zbcR1, & & ibcZ0,zbcZ0,ibcZ1,zbcZ1, & & id_R,id_Z,ierr)

Home | Top |

eqm_rzmag2

(old f77 xplasma 1 documentation) This routine sets up R(chi,rho) and Z(chi,rho) from a user supplied mapping subroutine rzmapper:(rho,chi) -> (R,Z). R and Z are defined as bicubic splines. `rzmapper' is the name of the mapping subroutine as given in the documentation and source code comments, but of course the actual programmer can choose any name. In detail: The user will supply a subroutine with the following interface: subroutine rzmapper(rho,chi,R,Z,ierr) real*8 rho,chi ! magnetic coordinates (in) real*8 R,Z ! cylindric coordinates (out) integer ierr ! completion code, 0=OK ... [compute (R,Z) from (rho,chi)...] ... end And then call eqm_rzmag2 to create the bicubic splines (with "not a knot" rho boundary conditions) for R,Z: ! input: external rzmapper ! mapping routine ! output: integer id_R ! xplasma index to R spline integer id_Z ! xplasma index to Z spline integer ierr ! completion code, 0=OK ... call eqm_rzmag2(rzmapper,id_R,id_Z,ierr) ... Note that the rho and chi grids used to drive rzmapper have to have already been defined by prior calls to eqm_rho and eqm_chi. These axes determine the size of the bicubic spline "objects" created.

Home | Top |

technical_note

(old f77 xplasma 1 documentation) The eqm_rzmag* routines test the orientation of the chi parameter. The xplasma internal representation is standardized on a "counter- clockwise" increasing poloidal angle parameter. If the R and Z data imply the reverse orientation, the data is "reversed" so that a counter-clockwise internal representation is used. To reference data with respect to the original, clockwise oriented poloidal angle coordinate, use appropriate "ccwflag" optional logical arguments (fortran-90 interface) or set vector lengths to negative values (fortran-77 interface). Xplasma does not "remember" the orientation of the original R & Z flux surface data.

Home | Top |

eqm_frhochi

(old f77 xplasma 1 documentation) A special routine is provided for setting up a 2d profile function f(chi,rho). This profile can be a piecewise bicubic spline, piecewise bicubic Hermite (Akima), or piecewise bilinear. Thus: ! input: integer iorder ! "order" of interpolating function integer id_axis1 ! rho or chi coordinate grid id integer id_axis2 ! chi or rho coordinate grid id ! these axes determine the size and layout requirements for ! zdata(:,:) character*(*) fname ! unique name of profile function ! integer idim1 ! size of 1st dimension of zdata real*8 zdata(idim1,*) ! the function data ! integer ibcrho0 ! boundary condition code, at rho(1) real*8 zbcrho0(*) ! boundary condition data, at rho(1) integer ibcrho1 ! boundary condition code, at rho(nrho) real*8 zbcrho1(*) ! boundary condition data, at rho(nrho) ! output: integer id_fun ! unique xplasma id for this new function integer ierr ! completion code, 0=OK ... call eqm_frhochi(iorder,id_axis1,id_axis2,fname, > zdata,idim1, > ibc1,zbc1, > ibc2,zbc2, > id_fun,ierr) if(ierr.ne.0) then [...handle error...] endif ! notes: ! * the amount and ordering of data expected in zdata(...) depends ! on the selected axes (id_axis1, id_axis2), and the interpolation ! order (iorder). Let nrho = the number of data points in the ! "id_rho" grid; let nchi = the number of data points in the chi ! grid. Let's suppose id_axis1.eq.id_rho & id_axis2.eq.id_chi. ! then: ! ! => iorder = 0 ... piecewise bilinear interpolating function; ! zdata(1:nrho,1:nchi) or zdata(1:nchi,1:nrho) ! according as id_axis1 and id_axis2 are set. ! => iorder = 1 ... piecewise bicubic Akima Hermite function; ! zdata(1:nrho,1:nchi) or zdata(1:nchi,1:nrho) ! according as id_axis1 and id_axis2 are set. ! => iorder = 2 ... piecewise bicubic spline function vs. chi,rho. ! zdata(1:nrho,1:nchi) or zdata(1:nchi,1:nrho) ! according as id_axis1 and id_axis2 are set. ! ! for iorder.ge.0, the interpolating function f(rho) will satisfy ! f(rho(i),chi(j))=zdata(i,j) for i=1:nrho, j=1:nchi. ! ! note: set iorder = 99 to update data for an already defined ! item. The original interpolation method is retained and ! the axis ids must match. ** "R" and "Z" cannot be updated ! by this method. ! ! * the name 'fname' must uniquely identify the function. The ! names "R","Z","RHO,"CHI","G","PSI", "BR", "BZ", "BPHI" and ! "BMOD" are reserved to xplasma. NAMES ARE CASE INSENSITIVE. ! ! * the double data array zdata(idim1,*) has a first dimension idim1; ! idim1 must be .ge.nrho, or, .ge.nchi, depending on how ! id_axis1 and id_axis2 are set. ! ! * boundary conditions -- ignored if iorder.le.0 ! ibc1,zbc1(*) -- controls at rho(1), i.e. the "magnetic axis" ! ibc2,zbc2(*) -- controls at rho(nrho), i.e. the "plasma bdy". ! options: ! ibc1|2 = 0 -- "not a knot" or default at axis | bdy; zbc1|2 ! ignored. ! ibc1|2 = 1 -- zbc1|2 contains df/drho vs. chi at the axis|bdy ! ibc1|2 = 2 -- splines only -- zbc1|2 contains d2f/drho2 vs. chi ! at the axis|bdy. ! ! * id_fun -- on normal exit (ierr.eq.0), id_fun contains the ! xplasma index to the interpolating function. This may be worth ! saving for efficient access to the interpolating function. ! ! * after the subroutine returns, the value of ierr should be ! examined and appropriate action taken if an error is ! indicated.

Home | Top |

poloidal_angle_orientation

(old f77 xplasma 1 documentation) Input profiles to eqm_frhochi are assumed to be defined w.r.t. a standard counter-clockwise oriented poloidal angle coordinate. If this is not the case, there is an alternate call that may be used to indicate a profile defined over a clockwise oriented poloidal angle coordinate: iccw=0 call eqm_frhochi_ccw(iccw, > iorder,id_axis1,id_axis2,fname, > zdata,idim1, > ibc1,zbc1, > ibc2,zbc2, > id_fun,ierr) if(ierr.ne.0) then [...handle error...] endif Except for "iccw" the arguments are the same as for eqm_frhochi above.

Home | Top |

summary

(old f77 xplasma 1 documentation) The profiles R(chi,rho) and Z(chi,rho) must be provided in order to give the flux surface geometry. Use one of the special purpose routines eqm_rzmag, eqm_rzmagb, or eqm_rzmag2 to define R and Z. Then, use eqm_frhochi to define additional functions f(chi,rho). The general purpose routine eqm_frhochi for constructing f(chi,rho) 2d profiles may be used, or, the special purpose routine eqm_rzmag2 might be used as a more convenient alternative. To set up R(chi,rho) and Z(chi,rho) from user supplied data arrays using default "not a knot" spline boundary conditions: To set up R(chi,rho) and Z(chi,rho) from user supplied data arrays with full control of boundary conditions at the rho extrema: To set up R(chi,rho) and Z(chi,rho) splines from a user supplied subroutine: subroutine eqm_rzmag2(rzmapper,id_R,id_Z,ierr) ! in out out out ...where rzmapper stands for a user supplied routine with the interface subroutine rzmapper(rho,chi,R,Z,ierr) real*8 rho,chi ! magnetic coordinates (in) real*8 R,Z ! cylindric coordinates (out) integer ierr ! completion code (out) 0=OK To set up any function f(chi,rho): subroutine eqm_frhochi(iorder,id_axis1,id_axis2,'fname', > zdata,idim_1, > ibcrho0,zbcrho0,ibcrho1,zbcrho1, > id_fun,ierr) where the first dimension of zdata(idim_1,*) is rho or chi (as specified by id_axis1), and the 2nd dimension is chi or rho (as specified by id_axis2). The fit order is controlled by "iorder" but is forced to be a bicubic spline if the data is named "R" or "Z". Boundary condition controls specify treatment of the data at rho(1) and rho(nrho). After the interpolating function is successfully set up, the xplasma identifer is returned as id_fun.

Home | Top |

B(chi,rho)

(old f77 xplasma 1 documentation) (for axisymmetric tokamak equilibria...) To compute the magnetic field in the region mapped by magnetic coordinates, the following quantities need to be defined: -> 1d profiles: g(rho), psi(rho) (...see _1d_Profiles_f(rho)...) -> 2d profiles: R(chi,rho), Z(chi,rho) (...see _2d_profiles...) -> sign factors: given integer isnccwb,isnccwi ! isnccwb = +1 if Bphi is counterclockwise (CCW) looking down ! on the torus ! = -1 if Bphi is clockwise (CW) looking down on the ! torus. ! ! isnccwi = +1 if Ip (plasma current) is CCW looking down on ! the torus ! -1 if Ip is CW looking down on the torus. call eqm_bset(isnccwb,isnccwi) ! use eqm_bset to inform xplasma of the sign orientation of ! the toroidal field and plasma current (hence poloidal field). Subsequently, one may use call eq_bchk_sign(isnccwb,isnccwi) to retrieve the sign factors as previously set; if the field has not been initialized then this routine will return zeroes. When all of the above information is known to xplasma, it will go ahead and compute BR(chi,rho) -- R component of B field -- bicubic spline BZ(chi,rho) -- Z component of B field -- bicubic spline BMOD(chi,rho) -- mod(B) -- bicubic spline (note Bphi(chi,rho) = isnccwb*g(rho)/R(chi,rho) is known implicitly). (note also that the signs of g(rho) and d(psi)/d(rho) will not be used to compute B. Instead, "G" as stored by xplasma as a positive definite function, and "PSI" is standardized such that psi(rho(1))=0.0d0 and psi(rho) is strictly increasing. The call to eqm_bset is required to set the signs of the field vector components.) A sketched example of code that would supply enough information for xplasma to evaluate the B field vs. magnetic coordinates: call eqm_rho(...) ! set up rho grid call eqm_chi(...) ! set up chi grid call eqm_rhofun(...,'g',...) ! set up g(rho) call eqm_rhofun(...,'psi',...) ! set up psi(rho) call eqm_frhochi(...,'R',...) ! set up R(chi,rho) call eqm_frhochi(...,'Z',...) ! set up Z(chi,rho) call eqm_bset(isnccwb,isnccwi) ! specify sign conventions

Home | Top |

Limiters_and_RZ_grid

In xplasma the "limiter" refers to traditional limiters, vacuum vessel walls, divertor throats-- any mechanical bounding surface that faces the plasma or the vacuum region surrounding the plasma. Generally, the (R,Z) cartesian grid is set up at the same time as the limiter, because the limiter location determines the range of (R,Z) rectangular grid required to cover both the core plasma and the scrape off plasma between the core and the limiters. xplasma supports 3 types of limiter specifications: * fixed distance "dlim" from plasma boundary, but constrained by a box [Rmin,Rmax]x[Zmin,Zmax]. dlim.ge.zero, and the box contains (and does not cut into) the core plasma. If dlim=0, the limiter and the plasma boundary are the same. => use eqm_dbdy_grid or eqm_rzgrid followed by eqm_dbdy * a list of infinite lines and circles. Each line j divides space into two half-planes one of which contains the plasma, call this half plane Hj. Each circle k divides space into the region inside the circle and the region outside, one of which contains the plasma; call this region Ck. The intersection I of all Hj and Ck then defines a space containing the plasma. The boundary of I, which consists of segments of the given lines and arcs of the given circles, defines the limiter. It is an error if one of the limiter lines or circles cuts into the plasma. => use eqm_tbdy_grid or eqm_tbdy followed by eqm_rzgrid * a contour defined by a closed sequence of points {(R(i),Y(i))}, i=1:nc, R(1)=R(nc),Y(1)=Y(nc), and the contour does not cross itself, and the contour does not cut into the plasma. => use eqm_cbdy_grid or eqm_cbdy followed by eqm_rzgrid

Home | Top |

eqm_dbdy_methods

(old f77 xplasma 1 documentation) If evenly spaced (R,Z) grids are OK, use eqm_dbdy_grid, as follows: To define the limiter (input to eqm_dbdy_grid or eqm_dbdy) real*8 dlim ! fixed distance out from plasma bdy real*8 rmin,rmax ! Rmin and Rmax of constraining box real*8 zmin,zmax ! Zmin and Zmax of constraining box To define the (R,Z) grids (input to eqm_dbdy_grid or eqm_rzgrid) integer inumR ! no. of R grid points integer inumZ ! no. of Z grid points Information returned (from eqm_dbdy_grid or eqm_rzgrid) integer id_R ! xplasma R grid id code integer id_Z ! xplasma Z grid id code integer ierr ! completion code 0 = OK ... call eqm_dbdy_grid(dlim,rmin,rmax,zmin,zmax, > inumR,inumZ, > id_R,id_Z,ierr) ----------------------------------------------------- Or... To explicitly control the (R,Z) grids... Add the declarations... real*8 Rgrid(inumR) ! user's desired R grid for eqm_rzgrid real*8 Zgrid(inumZ) ! user's desired Z grid for eqm_rzgrid ! *** Rgrid and Zgrid must be strict ascending, and, ! [Rgrid(1),Rgrid(inumR)]x[Zgrid(1),Zgrid(inumZ)] must ! cover the plasma integer iauto ! if iauto.le.0 user supplies grid ! if iauto.eq.0 the grid is padded with ! two "gaurd rows" on each edge ! if iauto.eq.-1 the grid is not padded. real*8 ztol ! (R,Z) grid even-spacing tolerance ! recommend about 1.0d-6*Rmax ... ! set up grid FIRST call eqm_rzgrid(Rgrid,Zgrid,iauto,iauto,inumR,inumZ,ztol, > id_R,id_Z,ierr) ! THEN set up limiter. call eqm_dbdy(dlim,Rgrid(1),Rgrid(inumR),Zgrid(1),Zgrid(inumZ), ierr) -- or -- call eqm_dbdy(dlim,Rmin,Rmax,Zmin,Zmax, ierr) ! but note: ! if Rmin.lt.Rgrid(1), Rgrid(1) is used, ! if Rmax.gt.Rgrid(inumR), Rgrid(inumR) is used, ! if Zmin.lt.Zgrid(1), Zgrid(1) is used, ! if Zmax.gt.Zgrid(inumZ), Zgrid(inumZ) is used,

Home | Top |

eqm_tbdy_methods

(old f77 xplasma 1 documentation) If evenly spaced (R,Z) grids are OK, use eqm_tbdy_grid, as follows: To define the line limiters (input to eqm_tbdy_grid or eqm_tbdy): integer ilines ! number of infinite line "limiters" real*8 Rl(ilines),Zl(ilines) ! 1 point given on each line real*8 thl(ilines) ! orientation angle in DEGREES ! thl(j) = 0 or 180 or -180 -- line j is horizontal ! thl(j) = +/- 90 -- line j is vertical ! thl(j) = 45 -- line runs in (+1,+1) or (-1,-1) direction along the line in (R,Z) space ! thl(j) = -45 -- line runs in (-1,+1) or (+1,-1) direction along the line in (R,Z) space To define the circle limiters (input to eqm_tbdy_grid or eqm_tbdy): integer icircs ! number of circle "limiters" real*8 Rc(icircs),Zc(icircs) ! (R,Z) centers of circles real*8 rad(icircs) ! radii of circles To define the (R,Z) grids (input to eqm_tbdy_grid or eqm_rzgrid) integer inumR ! no. of R grid points integer inumZ ! no. of Z grid points Information returned (from eqm_tbdy_grid or eqm_rzgrid) integer id_R ! xplasma R grid id code integer id_Z ! xplasma Z grid id code integer ierr ! completion code 0 = OK ... call eqm_tbdy_grid(ilines,Rl,Zl,thl, > icircs,Rc,Zc,rad, > inumR,inumZ, > id_R,id_Z,ierr) ----------------------------------------------------- Or... To explicitly control the (R,Z) grids... Add the declarations... ! for eqm_rzgrid: real*8 Rgrid(inumR) ! desired R grid real*8 Zgrid(inumZ) ! desired Z grid ! if Rgrid and Zgrid are not generated, then, ! *** Rgrid and Zgrid must be strict ascending, and, ! [Rgrid(1),Rgrid(inumR)]x[Zgrid(1),Zgrid(inumZ)] must ! cover the plasma AND scrapeoff layer integer iautoR = 0 ! user supplies Rgrid if iautoR=0 integer iautoZ = 0 ! user supplies Zgrid if iautoZ=0 real*8 ztol ! (R,Z) grid even-spacing tolerance ! recommend about 1.0d-6*Rmax ... integer itype ! limiter type code from eq_bdlims real*8 zRmin,zRmax ! limiter Rmin & Rmax from eq_bdlims real*8 zZmin,zZmax ! limiter Zmin & Zmax from eq_bdlims ! set up limiter FIRST call eqm_tbdy(ilines,Rl,Zl,thl, > icircs,Rc,Zc,rad, ierr) if(ierr.ne.0) then [...handle error...] endif ! find Rmin,Rmax, Zmin,Zmax of limiters (use eq_bdlims subroutine) call eq_bdlims(itype,zRmin,zRmax,zZmin,zZmax,ierr) ! generate a grid which covers the necessary range + some margin ! **for example** code to generate an evenly spaced (R,Z) grid: zRmid=0.5d0*(zRmin+zRmax) zZmid=0.5d0*(zZmin+zZmax) zdelR=(inumR-1)*0.5d0*(zRmax-zRmin)/(inumR-4) ! 1.5 zone margin zdelZ=(inumZ-1)*0.5d0*(zZmax-zZmin)/(inumZ-4) ! 1.5 zone margin do i=1,inumR zRgrid(i)=zRmid-zdelR + (i-1)*2.0d0*zdelR/(inumR-1) enddo do i=1,inumZ zZgrid(i)=zZmid-zdelZ + (i-1)*2.0d0*zdelZ/(inumZ-1) enddo ! but note an evenly spaced grid is not required. ! finally, call eqm_rzgrid to set up the (R,Z) grid call eqm_rzgrid(Rgrid,Zgrid,iautoR,iautoZ,inumR,inumZ,ztol, > id_R,id_Z,ierr)

Home | Top |

eqm_cbdy_methods

(old f77 xplasma 1 documentation) If evenly spaced (R,Z) grids are OK, use eqm_cbdy_grid, as follows: To define the limiter contour, an ordered, closed sequence of (R,Z) points, for eqm_cbdy_grid or eqm_cbdy: integer ipts ! number of points in piecewise linear ! limiter contour real*8 Rlim(ipts),Zlim(ipts) ! count (R,Z) point data ! Rlim(1)=Rlim(ipts) and Zlim(1)=Zlim(ipts) is required, and, ! the arrays must describe a simple closed contour that does not ! cross itself, and which does not cut into the core plasma. To define the (R,Z) grids (input to eqm_cbdy_grid or eqm_rzgrid) integer inumR ! no. of R grid points integer inumZ ! no. of Z grid points Information returned (from eqm_cbdy_grid or eqm_rzgrid) integer id_R ! xplasma R grid id code integer id_Z ! xplasma Z grid id code integer ierr ! completion code 0 = OK ... call eqm_cbdy_grid(ipts,Rlim,Zlim, > inumR,inumZ, > id_R,id_Z,ierr) ----------------------------------------------------- Or... To explicitly control the (R,Z) grids... Add the declarations... ! for eqm_rzgrid: real*8 Rgrid(inumR) ! desired R grid real*8 Zgrid(inumZ) ! desired Z grid ! if Rgrid and Zgrid are not generated, then, ! *** Rgrid and Zgrid must be strict ascending, and, ! [Rgrid(1),Rgrid(inumR)]x[Zgrid(1),Zgrid(inumZ)] must ! cover the plasma AND scrapeoff layer integer iautoR = 0 ! user supplies Rgrid if iautoR=0 integer iautoZ = 0 ! user supplies Zgrid if iautoZ=0 real*8 ztol ! (R,Z) grid even-spacing tolerance ! recommend about 1.0d-6*Rmax ... integer itype ! limiter type code from eq_bdlims real*8 zRmin,zRmax ! limiter Rmin & Rmax from eq_bdlims real*8 zZmin,zZmax ! limiter Zmin & Zmax from eq_bdlims ! set up limiter FIRST call eqm_cbdy(ipts,Rlim,Zlim, ierr) if(ierr.ne.0) then [...handle error...] endif ! find Rmin,Rmax, Zmin,Zmax of limiters (use eq_bdlims subroutine) call eq_bdlims(itype,zRmin,zRmax,zZmin,zZmax,ierr) ! generate a grid which covers the necessary range + some margin ! **for example** code to generate an evenly spaced (R,Z) grid: zRmid=0.5d0*(zRmin+zRmax) zZmid=0.5d0*(zZmin+zZmax) zdelR=(inumR-1)*0.5d0*(zRmax-zRmin)/(inumR-4) ! 1.5 zone margin zdelZ=(inumZ-1)*0.5d0*(zZmax-zZmin)/(inumZ-4) ! 1.5 zone margin do i=1,inumR zRgrid(i)=zRmid-zdelR + (i-1)*2.0d0*zdelR/(inumR-1) enddo do i=1,inumZ zZgrid(i)=zZmid-zdelZ + (i-1)*2.0d0*zdelZ/(inumZ-1) enddo ! but note an evenly spaced grid is **not** required. ! finally, call eqm_rzgrid to set up the user (R,Z) grid call eqm_rzgrid(Rgrid,Zgrid,iautoR,iautoZ,inumR,inumZ,ztol, > id_R,id_Z,ierr)

Home | Top |

_2d_Profiles_f(R,Z)

(old f77 xplasma 1 documentation) After the limiter and (R,Z) grids have been established, the user can define profiles over the (R,Z) grid. These functions will cover both the core plasma and the scrape-off plasma. For (R,Z) points which are behind the limiter, a smooth automatic extrap- olation is provided. Interpolating profile functions f(R,Z) are characterized by an "order" which corresponds to fitting method: order description 0 bilinear interpolation, continuous 1 Akima Hermite interpolation, continuous & differentiable 2 Spline interpolation, continuous & twice differentiable However, bicubic splines should be used with care, as noise in the data can cause "ringing" artifacts. If this is in the plasma edge region, a smoothing option is available. Three subroutines are available for defining functions f(R,Z): eqm_rzfun -- from an existing flux surface function f(rho), define f(R,Z) using f(rho) in the core region and f(rho(bdy))*exp(-d/lamda) in the scrape off region, where d = distance beyond plasma boundary. The parameter "lamda", the scrape- off length, is a subroutine argument. eqm_rzfunf-- from an existing flux surface function f(rho), define f(R,Z) using f(rho) in the core region and using a user supplied function (passed as a subroutine argument) for the scrape-off layer. The user supplied function is only called for (R,Z) values which are outside the plasma but inside the limiter. eqm_rzfun2-- load f(R,Z) from a user supplied function which is passed as a subroutine argument. The user supplied function is called for all (R,Z) values which are inside the limiter, including inside the core plasma. eqm_rzfunda- load f(R,Z) from a user supplied data array. As with f(rho) & f(rho,chi) routines, an existing item can receive a "data update" by calling the appropriate routine with iorder=99 specified. However, it is up to the programmer to enforce consistency of profiles in the context of updates.

Home | Top |

eqm_rzfun

(old f77 xplasma 1 documentation) Use this subroutine to define a profile f(R,Z) from an existing flux surface function profile f(rho), using a "scrape-off length" parameter to specify the variation outside the core plasma boundary. Input arguments: integer id_fun ! xplasma id for existing function f(rho) ! if necessary: call eq_gfnum('TE',id_fun) to fetch a function ! id given the function name; here 'TE' might be the label for ! "electron temperature". real*8 lamda ! scrape-off length ! outside the plasma boundary, f(R,Z)=f(rho(bdy))*exp(-d/lamda), ! where f(rho(bdy)) is the value of f(rho) at the plasma boundary, ! and d(R,Z) gives the distance from the plasma boundary. integer iorder ! interpolation method, 0=bilinear, ! 1=Hermite, 2=Spline real*8 delta ! smoothing parameter (0.0d0 for none) Output argument: integer ierr ! completion code, 0=OK ... call eqm_rzfun(id_fun,lamda,iorder,delta,ierr) if(ierr.ne.0) then [...handle error...] After a successful call to eqm_rzfun, the interpolation object indexed by "id_fun" is a "compound object" containing both representations f(rho) and f(R,Z), which are designed to co-exist.

Home | Top |

eqm_rzfunf

(old f77 xplasma 1 documentation) Use this subroutine to define a profile f(R,Z) from an existing flux surface function profile f(rho), using a user supplied function "userfcn" to specify the profile variation outside the core plasma but inside the limiter. "userfcn" is the name used for the function dummy argument and in this documentation, but in practice for any particular call to eqm_rzfunf the user chooses an appropriate specific name for this function. The "userfcn" routine must have the following interface: real*8 function "userfcn"(iarg,R,Z,phi,ierr) with inputs: integer iarg ! integer argument, pass through eqm_rzfunf real*8 R,Z,phi ! cylindric coordinates (for axisymmetric ! cases phi will not be used). Points passed ! to userfcn will be outside the core plasma ! but inside the limiter and outputs: (function value) ! the value of the function "f" at (R,Z,phi) integer ierr ! completion code, 0=OK, else an error. Assuming "userfcn" exists, then, the arguments to eqm_rzfunf are as follows. Input arguments: character*(*) zname ! name of new function, must be unique. ! if necessary: call eq_gfnum('TE',id_fun) to fetch a function ! id given the function name; here 'TE' might be the label for ! "electron temperature". external <your-userfcn> ! the name of your "userfcn" routine integer iarg ! pass-through argument for "userfcn" integer iorder ! interpolation method, 0=bilinear, ! 1=Hermite, 2=Spline real*8 delta ! smoothing parameter (0.0d0 for none) Output arguments: integer id_fun ! xplasma id for new function (returned). integer ierr ! completion code, 0=OK ... call eqm_rzfunf(id_fun,<your-userfcn>,iarg,iorder,delta,ierr) if(ierr.ne.0) then [...handle error...]

Home | Top |

eqm_rzfun2

(old f77 xplasma 1 documentation) Use this subroutine to define a new profile function f(R,Z), using a user supplied function "userfcn" to specify the profile variation both inside the core plasma and also outside the core plasma but inside the limiter. "userfcn" is the name used for the function dummy argument and in this documentation, but in practice for any particular call to eqm_rzfun2 the user chooses an appropriate specific name for this function. The "userfcn" must have the following interface: real*8 function "userfcn"(iarg,R,Z,phi,ierr) with inputs: integer iarg ! integer argument, pass through eqm_rzfun2 real*8 R,Z,phi ! cylindric coordinates (for axisymmetric ! cases phi will not be used). Points passed ! to userfcn will be inside the limiter and outputs: (function value) ! the value of the function "f" at (R,Z,phi) integer ierr ! completion code, 0=OK, else an error. Assuming "userfcn" exists, then, the arguments to eqm_rzfun2 are as follows. Input arguments: character*(*) zname ! name of function external <your-userfcn> ! the name of your "userfcn" routine integer iarg ! pass-through argument for "userfcn" integer iorder ! interpolation method, 0=bilinear, ! 1=Hermite, 2=Spline real*8 delta ! smoothing parameter (0.0d0 for none) Output arguments: integer id_fun ! xplasma id for function integer ierr ! completion code, 0=OK ... call eqm_rzfun2(zname,id_fun,<your-userfcn>,iarg,iorder,delta, > ierr) if(ierr.ne.0) then [...handle error...] After a successful call to eqm_rzfun, the interpolation object indexed by "id_fun" is a "compound object" containing both representations f(rho) and f(R,Z), which are designed to co-exist.

Home | Top |

eqm_rzfunda

(old f77 xplasma 1 documentation) Use this subroutine to define a new profile function f(R,Z), using array data supplied by the user. The data must be dimensioned f(nR,nZ) where nR and nZ are the R and Z grids, respectively. The function covers the entire R-Z box, including points beyond the limiters. Input arguments: character*(*) zname ! name of function integer inR,inZ ! array dimensions -- must match R, Z grids real*8 zdata(inR,inZ) ! data array-- R,Z grid dimensions. integer iorder ! interpolation method, 0=bilinear, ! 1=Hermite, 2=Spline real*8 delta ! smoothing parameter (0.0d0 for none) Output arguments: integer id_fun ! xplasma id for function integer ierr ! completion code, 0=OK ... call eqm_rzfunda(zname,id_fun,zdata,inR,inZ,iorder,delta,ierr) if(ierr.ne.0) then [...handle error...] After a successful call to eqm_rzfun, the interpolation object indexed by "id_fun" is a "compound object" containing both representations f(rho) and f(R,Z), which are designed to co-exist.

Home | Top |

Smoothing

(old f77 xplasma 1 documentation) Often noise occurs in the vicinity of the plasma boundary; to ameliorate this there is a smoothing parameter "delta" given in units of (R,Z). Data at points (Rd,Zd) within distance 0.5*delta of the plasma boundary are smoothed by a weighted convolution over data in the region [Rd-delta,Rd+delta]x[Zd-delta,Zd+delta] with the weighting a pyramid shaped function favoring the points close to the original (Rd,Zd). For points in the bands from 0.5*delta to 1.5*delta away from the boundary, reduced smoothing is done, the less smoothing the further away, until at 1.5*delta remove no smoothing is done at all. The smoothing parameter "delta" is a calling argument in the subroutines eqm_rzfun* used for defining profile functions f(R,Z). To disable smoothing, specify delta = 0.0D0 ...

Home | Top |

B(R,Z)

(old f77 xplasma 1 documentation) The xplasma package permits formation of a representation of the magnetic field vector over the (R,Z) grid, and therefore covering the scrape-off region as well as the core plasma. To load this representation, the user calls subroutine "eqm_brz" which itself takes a field specification subroutine as an argument. For this field specification subroutine, the user must either (a) provide a user written subroutine "userbvec", with the required interface, which specifies he field everywhere, or, (b) if B(chi,rho) is available in the core region but there is no data for B in the scrape-off region, use the xplasma supplied extrapolator for B(R,Z): eqm_brz_adhoc -- ad hoc extrapolation, fast and smooth. (the old method eqm_brzx -- div(B)=curl(B)=0 extrapolation has been continued; eqm_brzx and eqm_brz_adhoc now both yield the same result). (more details below). (c) if data specifying psi(R,Z) is available, enter this into xplasma using e.g. eqm_rzfun with iorder=1 or iorder=2, then use "eqm_bpsi", which will use grad(phi) x grad(psi) for BR and BZ, and g/R for Bphi. Option (b) should only be used in cases where an independent data source for reconstruction of B(R,Z) outside the core plasma is unavailable. For example, if reading data from a source such as a TRANSP run, which lacks outside-the-plasma data, option (b) may have to be used. But, if reading from a source such as an EFIT G EQDSK file which gives psi(R,Z), options (a) or (c) should be used. The call to eqm_brz takes the following form: input arguments: external <your-userbvec | eqm_brz_adhoc | eqm_bpsi > ! your B(R,Z) extrapolation data subroutine real*8 delta ! edge smoothing parameter output argument: integer ierr ! completion code, 0=OK ... call eqm_brz(<your B(R,Z) extrapolation data subroutine>, > delta, ierr) if(ierr.ne.0) then [... handle error ...] A successful call to eqm_brz results in the creation of functions BR(R,Z), BZ(R,Z) and BPHI(R,Z), interpolations on which are usually done by one of the eq_get* data access subroutines. If "eqm_brz_adhoc" is used, the poloidal flux function psi(R,Z) is also formed and associated with psi(rho) from inside the plasma. Note: at present this system is only valid for axisymmetric plasma field configurations. Non-axisymmetry will require significant new options.

Home | Top |

your-userbvec

(old f77 xplasma 1 documentation) If you write your own routine for specifying the field, it must have the following interface: subroutine <your-userbvec>( > ivec,R,Z,phi, > init, > BR,BZ,BPHI, > Psi,ipsi, > ierr) ! input arguments: integer ivec ! vector dimensioning real*8 R(ivec),Z(ivec),phi(ivec) ! coordinates at which ! ! to evaluate BR,BZ,Bphi integer init ! call flag ! init=1 -- initialization call (or just set ipsi) ! init=2 -- cleanup call (or do nothing) ! init=0 -- standard call ! ! the purpose of init is to allow the subroutine to perform ! initializations before it is first used, and to perform ! cleanup operations after the last time it is used. Of ! course some <your-userbvec> routines might not require ! initialization or cleanup. ! ! within an eqm_brz routine, the first call to <your-userbvec> ! has init=1, subsequent calls have init=0, and then there is ! a final call with init=2. ! output arguments: ! if init=1, only ipsi need be output ! if init=2, no output is required ! if init=0, all output is required ! real*8 BR(ivec),BZ(ivec),BPHI(ivec) ! the field components ! ! at the given coordinates ! ! optional output: real*8 Psi(ivec) ! the poloidal flux integer ipsi ! =1 if poloidal flux is ! ! output ! ! status code ! integer ierr ! exit code, 0=OK ! notes: ! * the phi(ivec) argument is provided for compatibility, in case ! the software is extended for non-axisymmetry in the future. ! For an axisymmetric code it can be ignored. ! * ipsi must be set =1 if the routine returns psi(R,Z) in addition ! to the field components. Otherwise set ipsi=0. ! * the routine is expected to return BR(j),BZ(j),BPHI(j) and ! possibly psi(j), i.e. the field, at R(j),Z(j),phi(j), ! for j = 1 to ivec. If the field cannot be evaluated at ! any one or more of these points, the status code ierr ! should be set to a non-zero number. ! ! it may be helpful to look at the source code for eqm_brz_adhoc ! and eqm_bpsi -- two routines which satisfy these interface ! requirements.

Home | Top |

eqm_brzx_OR_eqm_brz_adhoc

(old f77 xplasma 1 documentation) CORRECTION: eqm_brzx has been remapped to point to eqm_brz_adhoc. For stability/robustness reasons, the original eqm_brzx described here has been discontinued. Xplasma supplies 2 B(R,Z) extrapolator routines. Either subroutine eqm_brz_adhoc(ivec,zR,zZ,zphi,init,BR,BZ,BPHI,zpsi, > ipsi,ierr) or subroutine eqm_brzx(ivec,zR,zZ,zphi,init,BR,BZ,BPHI,zpsi, > ipsi,ierr) ...can be passed to eqm_brz as the external subroutine argument. Eqm_brz_adhoc uses a fast, approximate ad hoc method for extrapolating B(R,Z), described in detail below. In summary, the external toroidal field is taken as g(rho_bdy)/R, while the external poloidal field is assumed to allign with an ad hoc numerical extrapolation of the (rho,chi) flux coordinate system. The poloidal variation of the poloidal field occurring at the boundary is preserved, but the magnitude is scaled down by the ratio of the poloidal path length at the extrapolated rho surface to the poloidal path length of the boundary surface (at rho_bdy). An extrapolation of the poloidal flux function psi is also provided and is roughly consistent with the extrapolated poloidal field. The original Eqm_brzx used a block-tridiagonal finite difference solver to extrapolate the core field, assuming axisymmetry and div(B)=0, and, initially, curl(B)=0. As the extrapolation advances, instabilities are detected and repaired by introducing current (curl(b).ne.0). Physically, this can be thought of as "guessing" where the coils are that hold the field in place in the actual experiment. This stabilized extrapolation will result in a field estimate whose deviation from the actual experimental field will increase, the further one moves from the core plasma region where the field is known. However, the field should have roughly the right behaviour close to the core plasma. On the other hand, the stabilization method is purely ad hoc. The purpose of eqm_brz_adhoc and eqm_brzx is to provide an (R,Z) extrapolation when the original field data is unavailable outside the core plasma. If the original field data is available, it should be used in preference to these routines. A sketch of the actual eqm_brz_adhoc algorithm executed by xplasma: 1. compute an ad hoc extrapolation of the (chi,rho) magnetic coordinate system. This extrapolation produces a set of nested surfaces but not flux surfaces; outside the core plasma, psi is a function of (chi,rho), not just (rho). 2. for rho>rho_bdy compute Lpol(rho) = poloidal path length around rho "flux" surface. and then take mod(Bpol(rho,chi)) = mod(Bpol(rho_bdy,chi)) * L_ratio where L_ratio = Lpol(rho_bdy)/Lpol(rho) < 1. while the direction of Bpol is tangent to the rho surface with sign consistent with the interior Bpol field. also take Bphi(rho,chi) = nsnccwb*g(rho_bdy)/R(rho,chi) i.e. use the "1/R" vacuum toroidal field beyond the plasma boundary. 3. form a poloidal variation spline fRB(chi)) = (R*Bpol(rho_bdy,chi))/(Rmax*Bpol(rho_bdy,Rmax)) (Bpol(rho_bdy,Rmax) is found by finding chi_Rmax = the poloidal angle at which the max R on the rho surface occurs, then Bpol(rho_bdy,Rmax)=Bpol(rho_bdy,chi_Rmax) is used). 4. Along the contour (rho,chi_Rmax(rho)) compute the extrapolated poloidal field and poloidal flux function differential d(psi) = Rmax(rho)*d(Rmax)*Bpol(rho,chi_Rmax(rho)) and integrate this to form psi(rho,chi_Rmax(rho)) 5. Take psi(rho,chi) = fRB(chi)*psi(rho,chi_Rmax(rho)) The result is quickly calculated, numerically well behaved, gives reasonable results near the boundary, but, it does not precisely satisfy physics constraints (del.B=0, curl.B=0, Bpol=grad(psi)/R are NOT satisfied accurately). A sketch of the original eqm_brzx algorithm: *** NO LONGER AVAILABLE *** 1. compute an ad hoc extrapolation of the (chi,rho) magnetic coordinate system. This extrapolation produces a set of nested surfaces but not flux surfaces; outside the core plasma, psi is a function of (chi,rho), not just (rho). 2. on this ad hoc coordinate system, advance from rho(j-1) to rho(j), for all chi, using a block tridiagonal solver for BR(1:nchi,j), BZ(1:nchi,j), with the triagonal system derived by finite differences from div(B)=0, curl(B)=0. 3. detect and repair fluctuations in Bchi, by adding current (in the form curl(B)) where needed to keep Bchi smooth. (this is an entirely ad hoc method). 4. move on to the next surface-- keep going until the (R,Z) grid rectangle is entirely covered. The main computations are done on the init=1 call to eqm_brzx. The init=0 calls return the resulting field components to eqm_brz, and the init=2 call is used to clean up memory management related to the calculation. Bottom line: eqm_brz_adhoc is faster and more stable. Both extrapolators have "arbitrary" ad hoc features. If a calculation requires accurate B(R,Z) beyond the plasma boundary, there is no substitute for providing the actual data based on coil positions, coil currents, and a free boundary equilibrium reconstruction (e.g. EFIT) that actually covers the vacuum region. An EFIT-based or equivalent psi(R,Z) profile can also be used (see the eqm_bpsi B(R,Z) data extrapolation routine). Since many datasets (e.g. TRANSP results) do not retain the necessary vacuum field data, the extrapolation tools are provided as a convenience.

Home | Top |

eqm_bpsi

(old f77 xplasma 1 documentation) subroutine eqm_bpsi(ivec,zR,zZ,zphi,init,BR,BZ,BPHI,zpsi,ipsi, > ierr) ...can be passed to eqm_brz as the external subroutine argument. This routine can be used when psi(R,Z) has been defined as an xplasma function (e.g. with eqm_rzfun). The routine computes Bphi from g(rho)/R, where rho=rho(R,Z) inside the core plasma, and, rho=rhobdy at the edge and outside the core plasma. The routine computes BR and BZ from grad(phi) x grad(psi) which looks like BR(i) = nsnccwi*(dpsi/dZ)/R BZ(i) = -nsnccwi*(dpsi/dR)/R where nsnccwi (+/-1) specifies the direction of the toroidal plasma current. If core field data BR(chi,rho) and BZ(chi,rho) are available, xplasma will use this in preference to grad(psi)/R. If necessary, edge smoothing can be employed to improve the blending of the core and external regions.

Home | Top |

Smoothing

Often noise occurs in the vicinity of the plasma boundary; to ameliorate this there is a smoothing parameter "delta" given in units of (R,Z). Data at points (Rd,Zd) within distance 0.5*delta of the plasma boundary are smoothed by a weighted convolution over data in the region [Rd-delta,Rd+delta]x[Zd-delta,Zd+delta] with the weighting a pyramid shaped function favoring the points close to the original (Rd,Zd). For points in the bands from 0.5*delta to 1.5*delta away from the boundary, reduced smoothing is done, the less smoothing the further away, until at 1.5*delta remove no smoothing is done at all. The smoothing parameter "delta" is a calling argument in the subroutines eqm_rzfun* used for defining profile functions f(R,Z). To disable smoothing, specify delta = 0.0D0 ...

Home | Top |

lists

XPLASMA now supports a generic facility for creating and accessing lists. Each list has a name (max 32 characters, one alphanumeric word, treated as uppercase), a label (max 60 characters), and a size which specifies the number of elements in the list. Each list element has a name (max 32 characters, one alphanumeric word, treated as uppercase), and the following associated data: a character string (max 60 characters) in addition to the name a floating point number an integer. Lists can be used to communicate such information as: -> a list of plasma spacies and the Z and A values of each species: name of example list: TR_THERMAL_SPECIES, size = 3 (label: "list of thermal ion species") name character data floating data integer data H (blank) 1.000 1 D (blank) 2.000 1 HE4 (blank) 4.000 2 interpretation: floating data gives "A", integer gives "Z". -> a timestep name of example list: TR_TIMESTEP, size = 2 (label: "timestep for TRANSP sources") name character data floating data integer data TR_TS1 S 1.010 0 TR_TS2 S 1.020 0 interpretation: character data gives physical units, floating data gives actual time values. -> a collection of related profile data items name of example list: TR_EHEAT, size = 5 (label: "integrated electron heating profiles") name character data floating data integer data TR_PBE W 3.073e4 310 TR_PFE W 0.000 311 TR_PEICRF W 0.000 312 TR_PEECRF W 0.000 313 TR_PELH W 0.000 314 interpretation: a list of heating profiles. Character data gives physical units, floating data gives total amount (power, W, in this context), and the integer gives XPLASMA id of the interpolating function f(rho). The methods for creation of lists are described here. Methods for finding and accessing lists and list contents are described under "Data Access Routines".

Home | Top |

eqm_list_create

(old f77 xplasma 1 documentation) ! inputs: character*32 :: list_name ! 1 word, treated as uppercase in XPLASMA character*60 :: list_label ! any label string integer :: list_size ! number of elements in list character*32 :: element_names(list_size) ! names of elements (1 word each) ! outputs: integer :: list_id ! list id -- used to refer to list in subsequent calls. integer :: ierr ! completion code, 0=OK ... call eqm_list_create(list_name,list_label,list_size,element_names, & & list_id,ierr)

Home | Top |

eqm_list_chval

(old f77 xplasma 1 documentation) ! inputs: integer :: list_id integer :: list_size ! should match size in prior eqm_list_create call character*60 chvals(list_size) ! character data ! output: integer :: ierr ! completion code, 0=OK call eqm_list_chval(list_id,list_size,chvals,ierr)

Home | Top |

eqm_list_ival

(old f77 xplasma 1 documentation) ! inputs: integer :: list_id integer :: list_size ! should match size in prior eqm_list_create call integer :: ivals(list_size) ! integer data ! output: integer :: ierr ! completion code, 0=OK call eqm_list_ival(list_id,list_size,ivals,ierr)

Home | Top |

eqm_list_r8val

(old f77 xplasma 1 documentation) ! inputs: integer :: list_id integer :: list_size ! should match size in prior eqm_list_create call real*8 r8vals(list_size) ! 8 byte floating point data ! output: integer :: ierr ! completion code, 0=OK call eqm_list_r8val(list_id,list_size,r8vals,ierr)

Home | Top |

eqm_list_r4val

(old f77 xplasma 1 documentation) ! inputs: integer :: list_id integer :: list_size ! should match size in prior eqm_list_create call real*4 r4vals(list_size) ! 4 byte floating point data ! output: integer :: ierr ! completion code, 0=OK call eqm_list_r4val(list_id,list_size,r4vals,ierr)

Home | Top |

list_name_rules:

(old f77 xplasma 1 documentation) -- max 32 characters. -- no imbedded blanks. -- alphanumeric characters + "$" + "_" only. -- all alphabetic characters treated as uppercase. -- first character should not be a numerical digit [0-9].

Home | Top |

additional_items

(old f77 xplasma 1 documentation) A subroutine to numerically compute the q(rho) profile, using the formula q = d(Phi)/d(Psi) = [d(Phi)/d(rho)]/[d(Psi)/d(rho)] is provided: character*10 qname -- desired XPLASMA name of q profile (input) id_q -- id of XPLASMA profile created (output) ierr -- completion code (0 = normal) (output) call eqm_gen_q(qname,id_q,ierr) The profile is a piecewise cubic Hermite function. [d(Psi)/d(rho)] > 0 near the axis is forced, but, the numerical value of q near axis can still jump, in cases with low axial current density.

Home | Top |

F77_Data_Access_Routines

(old f77 xplasma 1 documentation) [This is the original xplasma 1.0 documentation]. After xplasma setup has been completed, the xplasma module contains a list of items identifiable by unique names and integer id codes. Data Access Routines can be used. The following is a partial list of the types of routines that are provided: * coordinate transformations between cartesian, cylindric, and magnetic coordinate systems. * interpolation of plasma parameters and field vector, and their gradients, to target locations given in cartesian, cylindric or magnetic coordinates. * determination of location inside or outside the core plasma boundary and/or limiter, and by what distance, given target points in cartesian, cylindric or magnetic coordinates. * metric tensor information. * flux surface oriented statistics, such as Rmin, Rmax, Zmin, Zmax, Bmin and Bmax on a given flux surface. Many routines are **vectorized**, i.e. they accept vector arguments and return vector results. Taking advantage of vector features is good for code performance, on modern workstations as well as traditional vector supercomputers.

Home | Top |

identification

(old f77 xplasma 1 documentation) Associated with each xplasma dataset is a (30 character) label, an "axisymmetry" flag, and a "scrape-off layer" flag. Optionally, a timeslice time can also be associated with the dataset. To retrieve the label and flags: character*30 xplasma_label integer axisymm_flag ! axisymmetry flag, =1 means axisymmetric integer scrapeoff_flag ! scrapeoff layer flag, =1 means defined call eq_ident(xplasma_label,axisymm_flag,scrapeoff_flag) Notes: Any meaning or interpretation of the label is up to the user (it was set by a prior eqm_select(...) xplasma initialization call); xplasma only uses the label for informational messages. As of April 2003-- axisymm_flag=1 always. The setting scrapeoff_flag=1 means that xplasma has a limiter or vacuum vessel wall description, and, an (R,Z) grid that extends beyond the plasma boundary is defined. If a time has been associated with the current xplasma dataset, it can be retrieved with the call: real*8 ztime ! xplasma time, seconds. call eq_time(ztime) The xplasma time is user information only-- it is not used internally by the xplasma library code.

Home | Top |

name_translation

(old f77 xplasma 1 documentation) There are two types of named "xplasma" entities: "grids" and "profiles". Each of these entities carries a unique name and id number. Most of the xplasma software requires the id number to be supplied. Applications should keep frequently used xplasma id numbers on hand, for performance reasons, i.e. to minimize time spent doing name lookup and translation. Even so, the following name translation routines are available. All names are case insensitive. character*(*) zname ! name of entity integer id ! integer entity id code integer nlist ! length of list character*(*) znames(nlist) ! list of names integer idlist(nlist) ! list of entity id codes integer ierr ! completion code, 0=OK ... ! get a grid id call eq_ganum(zname,id) ! e.g.: call eq_ganum("rho",id) ! id=0 if translation fails ! get a profile function id call eq_gfnum(zname,id) ! e.g.: call eq_gfnum("psi",id) ! id=0 if translation fails ! get a list of profile function ids call eq_gflist(nlist,znames,idlist,ierr) ! ...ierr.ne.0 if any translation fails... Reverse translations can also be done: given the id return the name string: call eq_get_aname(id,zname) ! get name of axis grid call eq_get_fname(id,zname) ! get name of profile function

Home | Top |

grid_information

(old f77 xplasma 1 documentation) The xplasma module contains a set of grids, each identifiable ! size of a grid integer id_grid ! xplasma grid id (in) integer isize ! size (no. of points) in grid (out) call eq_ngrid(id_grid,isize) ! the grid itself integer imax ! max size of grid (in) integer igot ! actual size of grid (out) real*8 zdata(imax) ! array for grid data (out) integer ierr ! completion code, 0=OK (out) call eq_grid(id_grid,zdata,imax,igot,ierr) ! grid "zone centers" -- if grid contains N pts, this is a ! sequence of N-1 values; the jth value is half way point j and ! point j+1 in the original (boundary oriented) grid. call eq_grid_zc(id_grid,zdata,imax,igot,ierr) ! sizes of "common grids"... integer inumrho ! no. of flux surface pts integer inumchi ! no. of poloidal angle pts integer inumphi ! no. of toroidal angle pts integer inumR ! no. of R grid pts integer inumZ ! no. of Z grid pts call eq_ngrids(inumrho,inumchi,inumphi,inumR,inumZ) ! inumphi=1 is returned for axisymmetric cases. Otherwise, if ! any grid is undefined, a zero size is returned.

Home | Top |

zone_lookup

(old f77 xplasma 1 documentation) A vectorized zone lookup routines is provided: eq_nindx -- for a vector of values along a given grid, return a vector of zone indices, with a warning flag set if any of the values are out of range. eq_nindx is intended for "binning". A returned index value of j means that the corresponding input value is between grid point j and grid point j+1. eq_nindx returns j=0 for points that are out of range low, and j=N for points that are out of range high. Note that, if an axis is periodic, then, no point will ever be out of range, as the software will apply 2*pi*n shifts as necessary to bring the target value into the selected grid's normal range. Periodicity is an attribute of the grid which is defined at setup time (cf eqm_rho, eqm_chi, eqm_bbin, or eqm_uaxis). further details: see the subtopic.

Home | Top |

eq_nindx

(old f77 xplasma 1 documentation) Details on the "eq_nindx" subroutine call: ! input: integer id_grid ! grid id code integer ivec ! vector size real*8 zvals(ivec) ! vector of input values ! ! the "zvals" are along the "id_grid" axis. ! ! output: integer kindx(ivec) ! corresponding zone indices integer iwarn ! warning flag, 0=normal ... call eq_nindx(id_grid,ivec,zvals,kindx,iwarn) Note that iwarn=0 indicates normal completion, no warning. iwarn=+M means M points were out of range relative to the grid indicated by id_grid. For each value zvals(i), j=kindx(i) specifies the zone in which zvals(i) lies, i.e. x(j).le.zvals(i).le.x(j+1), where x(...) is the grid indicated by id_grid. If N is the size of the grid, 1 <= j < N for all points zvals(i) that are in range. If zvals(i) is out of range low, kindx(i)=0 is returned and the warning flag is incremented. If zvals(i) is out of range high, kindx(i)=N is returned and the warning flag is incremented. The caller should check the warning flag value. However, if "id_grid" is a "periodic" axis such as a poloidal or toroidal angle coordinate, out-of-range errors will never occur.

Home | Top |

coordinate_transformation

(old f77 xplasma 1 documentation) The xplasma module supports 3 coordinate systems: cylindric: (R,Z,phi) cartesian: (x,y,z) magnetic: (rho,chi,phi), rho and chi as defined during setup (xplasma makes no assumption about any possible physical meaning of rho and chi). A collection of coordinate transformation routines are supported. The following is a summary: (R,phi) -> (x,y) subroutine eq_xcyl(ivec,R,phi,x,y) subroutine eq_xcylcs(ivec,R,phi,x,y,cosphi,sinphi) x=R*cos(phi), y=R*sin(phi), (z=Z) (x,y) -> (R,phi) subroutine eq_rcyl(ivec,x,y,R,phi) subroutine eq_rcylcs(ivec,x,y,R,phi,cosphi,sinphi) R=sqrt(x**2+y**2), phi=atan2(y,x), (z=Z) In the following: To have "chi" interpreted as lying on a reversed (clockwise oriented) poloidal angle grid, substitute a negative number -ivec for ivec in the calling argument list. (rho,chi,phi) -> (R,Z,phi) subroutine eq_rzget(ivec,rho,chi,phi,R,Z,nregion,ierr) R=R(rho,chi,phi) & Z=Z(rho,chi,phi) by interpolation (phi ignored for axisymmetric cases). (rho,chi,phi) -> (x,y,z) subroutine eq_xget(ivec,rho,chi,phi,x,y,z,nregion,ierr) (call eq_rzget then eq_xcyl) (R,Z,phi) -> (rho,chi,phi) subroutine eq_inv(ivec,R,Z,phi,tol,rho,chi,nregion,ierr) Newton's method with "fast map" initial guess generator and using d[R,Z,phi]/d[rho,chi,phi]. Accuracy: if one uses eq_rzget to compute (R',Z') from (rho,chi,phi), then, max(|R-R'|,|Z-Z'|) <= tol*max(R,|Z|) (x,y,z) -> (rho,chi,phi) subroutine eqx_inv(ivec,x,y,z,tol,rho,chi,phi,nregion,ierr) (call eq_rcyl, then eq_inv)

Home | Top |

subroutine_arguments

(old f77 xplasma 1 documentation) All of the coordinate transformation routines have similar arguments, drawn from the following set. Which are input and which are output depend on context, except where noted. Note that except for ivec and ierr, all arguments are vectors. integer ivec ! (always input) vector dimensioning real*8 R(ivec) ! major radius (cylindrical coordinate) real*8 Z(ivec) ! elevation (cylindrical coordinate ! or cartesian coordinate) (z=Z). real*8 phi(ivec) ! toroidal angle (cylindrical coordinate) real*8 cosphi(ivec) ! cos(phi) (always output) real*8 sinphi(ivec) ! sin(phi) (always output) real*8 x(ivec) ! cartesian coordinate, x axis along phi=0 real*8 y(ivec) ! cartesian coordinate, perp to x & Z. real*8 rho(ivec) ! radial flux coordinate real*8 chi(ivec) ! poloidal angle coordinate integer nregion(ivec) ! region code (always output) ! nregion(i)=1 means input position (i) ! is in the space mapped by (rho,chi,phi) ! nregion(i).gt.1 means it is outside the ! region mapped by magnetic coordinates. integer ierr ! (always output) completion code, 0=OK ! ierr.ne.0 means a serious error. ! A point (i) being outside the magnetic ! coordinate mapped region does NOT cause ! ierr to be set.

Home | Top |

min_max_info

(old f77 xplasma 1 documentation) Several routines are available for finding useful minima and maxima: (a) minimum and maximum "rho" coordinate ! output: real*8 rho_axis ! "rho" at magnetic axis real*8 rho_bdy ! "rho" at plasma boundary ... call eq_rholim(rho_axis,rho_bdy) (b) minimum and maximum R and Z ocurring on a flux surface ! input: real*8 rho ! "rho" where min/max info is wanted ! output: real*8 Rmin,Rmax ! minimum and maximum R on "rho" surface real*8 Zmin,Zmax ! minimum and maximum Z on "rho" surface integer ierr ! completion code (0=OK) ... call eq_glimrz(rho,Rmin,Rmax,Zmin,Zmax,ierr) (c) minimum and maximum B ocurring on a flux surface ! output: real*8 Bmin,Bmax ! minimum and maximum mod(B) ... call eq_glimb(rho,Bmin,Bmax,ierr) ...or... real*8 phi ! input; use e.g. phi=0 for axisymmetric case real*8 chi_Bmin,chi_Bmax ! ouput: angles of min & max B call eq_glimb1(rho,phi,Bmin,chi_Bmin,Bmax,chi_Bmax,ierr) (d) minimum and maximum R and Z of space enclosed by limiters (i.e. minimum and maximum R and Z of scrape-off plasma). ! output: integer itype ! xplasma modules limiter type ! =1: same as plasma boundary ! =2: circles & lines ! =3: piecewise linear contour ! =4: in box, fixed distance from bdy ! (for more information on limiters, see section on limiters in ! the description of xplasma setup routines). ... call eq_bdlims(itype,Rmin,Rmax,Zmin,Zmax,ierr) (e) minimum and maximum R and Z of (R,Z) grids defined in xplasma module. call eq_rzlims(Rmin,Rmax,Zmin,Zmax,ierr) This gives the space over which B(R,Z), psi(R,Z), f(R,Z), etc. are defined. (f) elongation,triangularity,indentation,midplane intercepts for a set of flux surfaces The midplane intercepts are defined as the major radiaus at the height of the centroid of the flux surface. The rho value will be forced to be larger then 1.e-5*(rho_bdy-rho_axis). Date: Wed, 22 Sep 1999 11:59:40 -0400 From: Glenn Bateman <bateman@fusion.physics.lehigh.edu> Consider a toroidal magnetic surface (also called a flux surface). Use the following variables R_out = major radius to the outboard edge of the flux surface that is, the largest value of major radius anywhere on the surface R_in = major radius to the inboard edge (ie, smallest value of major radius) R_top = major radius to the top edge of the flux surface that is, to the highest point on the flux surface cross section R_bottom = major radius to the lowest point on the flux surface height = distance between the elevations of the highest point and the lowest point R_dent_in = major radius to the most indented inboard part of the surface in cases where the flux surface is bean shaped with a dent on the inboard edge Note: R_dent_in = R_in whenever the flux surface is not indented R_dent_out = major radius to the most indented outboard part of the surface r_minor = half width = (R_out - R_in ) / 2 (usually called minor radius) r_major = ( R_out + R_in ) / 2 (usually called major radius) elongation: kappa = height / ( R_out - R_in ) tiangularity: delta = ( r_major - min ( R_top, R_bottom ) ) / r_minor indentation: indent = max ( ( R_dent_in - R_in ) / rminor , ( R_dent_out - R_out ) / rminor ) Note: For normal convex surfaces, indent = 0.0 For bean-shaped surfaces with indentation on the inboard edge, indent > 0 For bean-shaped surfaces with indentation on the outboard edge, indent < 0 For surfaces with the point of the triangle facing outward, delta > 0.0, while if the triangle points inward, delta < 0.0 For vertically elongated surfaces, kappa > 1.0 For horizontally elongated surfaces, kappa < 1.0. ! input: integer, intent(in) :: ivec ! number of surfaces real*8, intent(in) :: rho(ivec) ! radial coordinate of flux surface real*8, intent(in) :: phi(ivec) ! toroidal coordinate of flux surface integer, intent(in) :: ntheta ! number of poloidal points to use around ! the flux surface or 0 for the default of 400 ! output: real*8, intent(out) :: elong(ivec) ! surface elongation real*8, intent(out) :: triang(ivec) ! triangularity real*8, intent(out) :: indent(ivec) ! indentation real*8, intent(out) :: zmidp (ivec) ! height of flux surface centroid real*8, intent(out) :: rmnmidp(ivec) ! inner midplane intercept at centroid height real*8, intent(out) :: rmjmidp(ivec) ! outer midplane intercept at centroid height real*8, intent(out) :: limits(9,ivec) ! surface limits used for elong,triang,indent ! 1 -> R_in ! 2 -> R_out ! 3 -> R_top ! 4 -> Z_top ! 5 -> R_bottom ! 6 -> Z_bottom ! 7 -> R_dent_in ! 8 -> R_dent_out ! 9 -> R_centroid integer, intent(out) :: ier ! nonzero on error ... call eq_surfgeo(ivec, rho, phi, ntheta, & elong, triang, indent, zmidp, rmnmidp, rmjmidp, limits, ier)

Home | Top |

volume_and_area

(old f77 xplasma 1 documentation) When an xplasma geometry is defined, splines are set up containing estimates of enclosed plasma volume and enclosed cross-sectional area as a function of flux surface. These estimates are accurate to machine precision at the rho grid points, and well behaved inbetween. Method: Gauss's theorem is exploited to derive accurate expressions for enclosed volume (area) as 1d integrals at each flux surface rather than using 2d integrals convering the volume (area). To access the results of these fits (Volume, d[Volume]/drho, d2[Volume]/drho2, Area, d[Area]/drho, d2[Area]/drho2): ! input: integer ivec ! input data vector dimension real*8 x(ivec) ! vector of "x" values integer iwant ! 0: value, 1: df/drho, 2: d2f/drho2 ! output: real*8 zval(ivec) ! interpolation results, returned integer ierr ! completion code, 0=OK ... call eq_volume(ivec,rho,iwant,zval,ierr) ! Volume info. (m**3) call eq_area(ivec,rho,iwant,zval,ierr) ! Xsect. Area info. (m**2)

Home | Top |

function_information

(old f77 xplasma 1 documentation) (for information on translating an integer id code into a name, or vice-versa, see "name_translation") Given a function id integer code, the "eq_fun" call can be used to get a description of the available fundation data: fits to magnetic coordinates and dimenstionality; fits to cylindric coordinates and dimensionality, as follows. ! input: integer id_fun ! function id code ! output: integer magdim ! dimensionality vs. mag. coordinates integer magfit ! type of fit integer cyldim ! dimensionality vs. cyl. coordinates integer cylfit ! type of fit integer iwarn ! 0=OK, set if function is "internal". integer ierr ! 0=OK, set if invalid id code is passed ... call eq_fun(id_fun,magdim,magfit,cyldim,cylfit,iwarn,ierr) the output arguments should be interpreted as follows: magdim=0 => no fit to magnetic coordinates magdim=1 => f(rho) fit available -- flux function magdim=2 => f(rho,chi) fit available -- f(flux & pol. angle) magdim=3 => f(rho,chi,phi) fit available. magfit=0 => piecewise linear fit, f continuous magfit=1 => piecewise cubic Hermite, f' continuous magfit=2 => piecewise cubic spline, f'' continuous cyldim=0 => no fit to cylindric coordinates cyldim=2 => f(R,Z) fit available cyldim=3 => f(R,Z,phi) fit available cylfit=0 => piecewise linear fit, f continuous cylfit=1 => piecewise cubic Hermite, f' continuous cylfit=2 => piecewise cubic spline, f'' continuous

Home | Top |

function_grid_information

(old f77 xplasma 1 documentation) Given an appropriate function id, these routines return the indicated independent coordinate grid (axis) id. In all cases, if the function does not exist or does not have the type of independent coordinate grid requested, 0 is returned. input: integer id_fun ! function id code output: integer id_grid ! indep. coord. grid id, or zero (0) ! 0 returned if no such grid or function call eq_fun_rhogrid(id_fun,id_grid) ! rho grid id ! OK for f(rho), f(rho,chi), f(rho,chi,phi) call eq_fun_chigrid(id_fun,id_grid) ! chi grid id ! OK for f(rho,chi), f(rho,chi,phi) call eq_fun_Rgrid(id_fun,id_grid) ! R grid id ! OK for f(R,Z), f(R,Z,phi) call eq_fun_Zgrid(id_fun,id_grid) ! Z grid id ! OK for f(R,Z), f(R,Z,phi) if xplasma is extended for non-axisymmetric applications some day, then: call eq_fun_phigrid(id_fun,id_grid) ! phi grid id ! OK for f(R,Z,phi), f(rho,chi,phi)

Home | Top |

_1d_interpolation

(old f77 xplasma 1 documentation) The following simplified routines may be useful for interpolation of profile functions of "rho" only: (a) for interpolation on a single profile f(rho) prepared previously by an eqm_rhofun call: ! input: integer ivec ! input data vector dimension real*8 rho(ivec) ! vector of "rho" values integer id_fun ! xplasma id of profile function f(rho) integer iwant ! 0: value, 1: df/drho, 2: d2f/drho2 ! output: real*8 zval(ivec) ! interpolation results, returned integer ierr ! completion code, 0=OK ... call eq_rgetf(ivec,rho,id_fun,iwant,zval,ierr) The error code will be set if either an invalid function id is passed or if some of the "rho" values are out of range. Note: iwant=2 is valid only if f(rho) is a cubic spline. (b) for interpolation on a multiple profiles f(rho). arguments are as above, except: ! input: integer nlist ! length of list of xplasma ids integer id_funs(nlist) ! list of xplasma function ids integer ivecd ! output vector dimension ! output: real*8 zvals(ivecd,nlist) ! interpolation results, all fcns ... call eq_rgetff(ivec,rho,nlist,id_funs,iwant,ivecd, > zvals,ierr) (c) for interpolation on a single profile f(x) prepared previously by an eqm_f1d call: ! input: integer ivec ! input data vector dimension real*8 x(ivec) ! vector of "x" values integer id_fun ! xplasma id of profile function f(x) integer iwant ! 0: value, 1: df/dx, 2: d2f/dx2 ! output: real*8 zval(ivec) ! interpolation results, returned integer ierr ! completion code, 0=OK ... call eq_xgetf(ivec,rho,id_fun,iwant,zval,ierr) The error code will be set if either an invalid function id is passed or if some of the "x" values are out of range. Note: iwant=2 is valid only if f(x) is a cubic spline.

Home | Top |

_1d_interpolation_with_smoothing

(old f77 xplasma 1 documentation) Two combined interpolation/smooth routines are provided, one for ordinary profiles, and one for integrated profiles (such as are output by several NTCC physics modules). For ordinary profiles: eq_rget_sm For integrated profiles: eq_rget_binsm

Home | Top |

eq_rget_sm

subroutine eq_rget_sm(inrho,zrho,id,zdelta,zval,ierr) ! ! return a profile interpolated and then smoothed. ! caution: not recommended for volume- or area-integrated profiles; see ! eq_rget_bin(...) or eq_rget_binsm(...) ! implicit NONE integer, intent(in) :: inrho ! target gridsize, must be .gt.1 real*8, intent(in) :: zrho(inrho) ! target grid-- strict ascending order integer, intent(in) :: id ! function id of f(rho) profile real*8, intent(in) :: zdelta ! smoothing parameter ! zdelta defines the base half-width of a triangular weighting function ! used for smoothing. The smoothed output profile at each rho is ! weighted average of the original function over the range ! (rho-zdelta,rho+zdelta) with weight 1/zdelta at rho linearly ! declining to weight 0 at the end points. (area of weighting ! triangle is unity). real*8, intent(out) :: zval(inrho) ! results of smoothed interpolation ! zval(rho) is a weighted average of the original profile over the ! range [rho-zdelta,rho+zdelta] with a triangular weighting ! function whose weight goes to 0 at the interval enpoints. integer ierr ! completion code 0=OK

Home | Top |

eq_rget_bin

subroutine eq_rget_bin(inrho,zrho,id,iint,zval,ierr) ! ! given an integrated profile function id, ! return an integrated profile on the user's grid. ! ! if the interpolation order is >1, just do an interpolation. ! if the interpolation order is =1 (piecewise linear), do an integration ! of the step function of the inferred density ! implicit NONE integer, intent(in) :: inrho ! target gridsize, must be .gt.1 real*8, intent(in) :: zrho(inrho) ! target grid-- strict ascending order integer, intent(in) :: id ! function id of f(rho) profile integer, intent(in) :: iint ! data type id ! iint=1 -- area integral profile being smoothed -- ! Examples: current density profiles ! iint=2 -- volume integral profile being smoothed -- ! Examples: density, energy density, ptcl/power/momentum source ! functions, ... ! real*8, intent(out) :: zval(inrho) ! results of interpolation/integration integer ierr ! completion code 0=OK

Home | Top |

eq_rget_binsm

subroutine eq_rget_binsm(inrho,zrho,id,zdelta,iint,zval,ierr) ! ! given an integrated profile function id, ! ! return an integrated profile, smoothed onto the user's grid ! from the step-function defined by binning the density on the function's ! original grid. ! implicit NONE integer, intent(in) :: inrho ! target gridsize, must be .gt.1 real*8, intent(in) :: zrho(inrho) ! target grid-- strict ascending order integer, intent(in) :: id ! function id of f(rho) profile real*8, intent(in) :: zdelta ! smoothing parameter ! if <0, zdelta=delta(rho) assumed. integer, intent(in) :: iint ! data type id ! iint=1 -- area integral profile being smoothed -- ! Examples: current density profiles ! iint=2 -- volume integral profile being smoothed -- ! Examples: density, energy density, ptcl/power/momentum source ! functions, ... ! ! for iint > 0, the data is binned on the original grid, but smoothed ! on the user grid. The unsmoothed unintegrated profile (e.g. density ! profile) becomes a step function with step widths matching the original ! grid of the data. It is smoothed using a triangular weighting function ! whose base half-width (smoothing parameter) is zdelta. ! ! If the smoothing parameter is too small, the step- ! function-like behavior of the binned density profile will remain ! evident in the result ! ! zdelta =~ delta(rho) ! ! is recommended, where delta(rho) is the stepsize of the function's ! underlying rho grid. The recommended value is used if the passed ! value for zdelta is < 0. If zdelta=0, no smoothing occurs. ! if zdelta > 0, smoothing occurs using the user specified zdelta. ! ! note that the result is independent of the interpolating function ! xplasma has for the (integrated) profile function #id. ! ! NOTE: smoothing integrated profiles directly, e.g. with eq_rget_sm, ! is hazardous, because, if d/dV of the smoothed result is evaluated ! near the axis it will generally have a pole singularity there. real*8, intent(out) :: zval(inrho) ! results of smoothed interpolation ! zval(rho) is a weighted average of the original profile over the ! range [rho-zdelta,rho+zdelta] with a triangular weighting ! function whose weight goes to 0 at the interval endpoints. integer ierr ! completion code 0=OK

Home | Top |

_2d_f(rho,chi)_interpolation

(old f77 xplasma 1 documentation) When a given function or set of functions is known to be represented in f(rho,chi) form, the fastest interpolation routines are: eq_frhochi -- for a given set of (rho,chi) target points, return the values of all functions on the function list. eq_grhochi -- for a given set of (rho,chi) target points, return the df/drho and df/dchi of all functions on the function list. eq_hrhochi -- for a given set of (rho,chi) target points, return a user specified combination of values and derivatives (up to 2nd order derivatives). The user specifies what is wanted via the "ictwant" integer array. ! input: integer ivec ! vector dimension (vector of coordinates) real*8 zrho(ivec) ! rho of target points real*8 zchi(ivec) ! chi of target points integer nlist ! number of functions in function list integer ifcns(nlist) ! function ids of functions wanted ! integer ivecd ! 1st (vector) dimension of output buffer ! eq_frhochi output: real*8 fans(ivecd,nlist) ! function values returned ! fans(j,k) = value of k'th function ! at zrho(j),zchi(j) ! eq_grhochi output: real*8 gans(ivecd,2,nlist) ! df/drho, df/dchi values returned ! gans(j,1,k) = df/drho of k'th function ! at zrho(j),zchi(j) ! gans(j,2,k) = df/dchi of k'th function ! at zrho(j),zchi(j) ! output (for both): integer ierr ! completion code, 0=OK ... ... call eq_frhochi(ivec,zrho,zchi,nlist,ifcns,ivecd,fans,ierr) ... ... call eq_grhochi(ivec,zrho,zchi,nlist,ifcns,ivecd,gans,ierr) To have "zchi" interpreted as lying on a reversed (clockwise oriented) poloidal angle grid, substitute a negative number -ivec for ivec in the calling argument list.

Home | Top |

eq_hrhochi

(old f77 xplasma 1 documentation) This routine has the same arguments as "eq_frhochi" and "eq_grhochi" except this input array: integer ictwant(6) ! selector array ! ! each element of ictwant(1:6) should be 0 or 1 ! use 1 to indicate a desired item; use 0 otherwise: ! ! ictwant(1) -- function values ! ictwant(2) -- functions' df/drho values ! ictwant(3) -- functions' df/dchi values ! ictwant(4) -- functions' d2f/drho2 values ! ictwant(5) -- functions' d2f/dchi2 values ! ictwant(6) -- functions' d2f/drhodchi values and the output array is interpreted differently: REAL*8 zans(ivecd,nlist*max(1,sum(ictwant))) ! results ! ! ** let ictnum = # of non-zero elements of ictwant. ! (ictnum=sum(ictwant)). Then... ! zans(1:ivec,1) = value or derivative for function id iflist(1) ! indicated by first non-zero value of ictwant(...) ! zans(1:ivec,2) = value or derivative for function id iflist(1) ! indicated by second non-zero value of ictwant(...) ! ... ! zans(1:ivec,ictnum) = value or derivative for function id iflist(1) ! indicated by last non-zero value of ictwant(...) ! ! or generally, ! for 1 .le. j .le. nlist ! for 1 .le. k .le. ictnum, ! ... ! zans(1:ivec,(j-1)*ictnum+k) = value or derivative for function ! id iflist(j), corresponding to k'th ! non-zero element of ictwant(...) ! ... ... call eq_hrhochi(ivec,zrho,zchi,nlist,ifcns, & & ictwant,ivecd,gans,ierr) To have "zchi" interpreted as lying on a reversed (clockwise oriented) poloidal angle grid, substitute a negative number -ivec for ivec in the calling argument list.

Home | Top |

_2d_f(R,Z)_interpolation

(old f77 xplasma 1 documentation) When a given function or set of functions is known to be represented in f(R,Z) form, the fastest interpolation routines are: eq_fRZ -- for a given set of (R,Z) target points, return the values of all functions on the function list. eq_gRZ -- for a given set of (R,Z) target points, return the df/dR and df/dZ of all functions on the function list. eq_hRZ -- for a given set of (R,Z) target points, return a user specified set of values and derivatives up to 2nd order. ! input: integer ivec ! vector dimension (vector of coordinates) real*8 zR(ivec) ! R of target points real*8 zZ(ivec) ! Z of target points integer nlist ! number of functions in function list integer ifcns(nlist) ! function ids of functions wanted ! integer ivecd ! 1st (vector) dimension of output buffer ! eq_fRZ output: real*8 fans(ivecd,nlist) ! function values returned ! fans(j,k) = value of k'th function ! at zR(j),zZ(j) ! eq_gRZ output: real*8 gans(ivecd,2,nlist) ! function df/dR, df/dZ values returned ! gans(j,1,k) = df/dR of k'th function ! at zR(j),zZ(j) ! gans(j,2,k) = df/dZ of k'th function ! at zR(j),zZ(j) ! output (for both): integer ierr ! completion code, 0=OK ... ... call eq_fRZ(ivec,zR,zZ,nlist,ifcns,ivecd,fans,ierr) ... ... call eq_gRZ(ivec,zR,zZ,nlist,ifcns,ivecd,gans,ierr)

Home | Top |

eq_hRZ

(old f77 xplasma 1 documentation) This routine has the same arguments as "eq_fRZ" and "eq_gRZ" except this input array: integer ictwant(6) ! selector array ! ! each element of ictwant(1:6) should be 0 or 1 ! use 1 to indicate a desired item; use 0 otherwise: ! ! ictwant(1) -- function values ! ictwant(2) -- functions' df/dR values ! ictwant(3) -- functions' df/dZ values ! ictwant(4) -- functions' d2f/dR2 values ! ictwant(5) -- functions' d2f/dZ2 values ! ictwant(6) -- functions' d2f/dRdZ values and the output array is interpreted differently: REAL*8 zans(ivecd,nlist*max(1,sum(ictwant))) ! results ! ! ** let ictnum = # of non-zero elements of ictwant. ! (ictnum=sum(ictwant)). Then... ! zans(1:ivec,1) = value or derivative for function id iflist(1) ! indicated by first non-zero value of ictwant(...) ! zans(1:ivec,2) = value or derivative for function id iflist(1) ! indicated by second non-zero value of ictwant(...) ! ... ! zans(1:ivec,ictnum) = value or derivative for function id iflist(1) ! indicated by last non-zero value of ictwant(...) ! ! or generally, ! for 1 .le. j .le. nlist ! for 1 .le. k .le. ictnum, ! ... ! zans(1:ivec,(j-1)*ictnum+k) = value or derivative for function ! id iflist(j), corresponding to k'th ! non-zero element of ictwant(...) ! ... ... call eq_hRZ(ivec,zR,zZ,nlist,ifcns, & & ictwant,ivecd,zans,ierr)

Home | Top |

general_interpolation

(old f77 xplasma 1 documentation) A set of routines exists to find values and gradients of a set of functions, whose representation might be known a priori to the caller. There are 3 series of functions: eqxyz_*get -- given vectors of (x,y,z) coordinates, return function values, gradients (d/dx,d/dy,d/dz), Bfield vector, and Bfield gradient tensor. (rho,chi,phi) vectors can also be obtained. eqrz_*get -- given vectors of (R,Z,phi) coordinates, return function values, gradients (d/dR,d/dZ,1/R*d/dphi), Bfield vector, and Bfield gradient tensor. (rho,chi,phi) vectors can also be obtained. eq_*get -- given vectors of (rho,chi,phi), return function values, gradients, Bfield vector, and Bfield gradient tensor. (R,Z,phi) vectors can also be obtained. The gradients and field can be returned in cylindric- or flux-surface aligned coordinates: c if irzmode=1: (df/dR,df/dZ,(1/R)*df/dphi) @ (rho,chi,phi) c if irzmode=0: (df/dsperp,df/dschi,(1/R)*df/dphi) @ (rho,chi,phi) where sperp denotes ds in a flux durface normal direction, and dschi denotes ds tangential to the surface in the poloidal plane. Similarly, the the field will be returned with irzmode=1 as (BR,BZ,Bphi), or (0,Bchi,Bphi) for irzmode=0.

Home | Top |

performance_considerations

(old f77 xplasma 1 documentation) (1) it is faster to use eq_frz or eq_frhochi, if the function representation is known a priori, then to use eq*get*. However, eq*get* have the "smarts" to define the field and gradients in various coordinate systems, whereas eq_frz and eq_frhochi just return function values and derivatives. (2) vectorization and function grouping... Performance is improved both by using vectors of target points rather than individual target points, and, by evaluating groups of functions together, rather than each function individually. On cache oriented workstations, for a fixed total number of evaluations, we have seen factors of 25 (!) performance difference by evaluating individual functions one target point at a time, vs. evaluating groups of 10 functions in a single calls with target vectors of length 100. (This of course gives a 1000:1 difference in the amount of data returned by a single interpolation call). We think we are seeing the power of workstation data and instruction caches in these performace figures. Tests were done on an Alpha 500au running DEC UNIX / compaq fortran, and on an Intel P-II 400MHz Linux running fujitsu fortran -- with similar scaling results. (DEC alpha 500au results): jupiter.pppl.gov 7 Jun 2000: 500,000 function evaluations (10 functions x 50,000 target pts): cpu time, seconds function evaluations per cal vector Nfcn=1 Nfcn=10 size 1 15.24 2.52 10 4.88 .77 100 4.07 .61

Home | Top |

eqxyz_*get

(old f77 xplasma 1 documentation) generic interface (f90): For routines involving flux coordinates: To have "zchi" interpreted as lying on a reversed (clockwise oriented) poloidal angle grid, substitute a negative number -ivec for ivec in the calling argument list. use xplasma_get ... call eqxyz_get(...) specific interfaces (f77/f90): arguments used by this series of routines: ! input: integer ivec ! vector dimension (vector of coordinates) real*8 xx(ivec) ! x coordinate, each vector element real*8 yy(ivec) ! y coordinate, each vector element real*8 zz(ivec) ! z coordinate, each vector element ! output: real*8 zrho(ivec) ! rho coordinate, each vector element real*8 zchi(ivec) ! chi coordinate, each vector element real*8 zphi(ivec) ! phi coordinate, each vector element ! input: real*8 ztol ! rel. tolerance for coord. mapping ! (rho,chi,phi) maps to (x',y',z') ! with max(|x-x'|,|y-y'|,|z-z'|) ! .le. tol*[R of mag. axis]. ! output: real*8 bvec(3,ivec) ! field vector at each target point real*8 gbtensr(3,3,ivec) ! gbtensr(1:3,j,k)=grad(bvec(j,k)) ! input: integer ifcn ! a single fcn id, or... integer nlist ! no. of fcns to evaluate integer ifcns(nlist) ! list of fcn ids integer ivecd ! vector dimension for output arrays ! output: real*8 fval(ivec) ! function values, (single function) real*8 fgrad(3,ivec) ! function gradient (single function) ! ..or.. real*8 fvals(ivecd,nlist) ! function values returned real*8 fgrads(3,ivecd,nlist) ! function gradients returned. integer nregion(ivec) ! region code for each target point ! for target point j: ! nregion(j)=1: core plasma ! nregion(j)=2: scrape off layer ! nregion(j)=3: outside limiter ! nregion(j)=4: beyond (R,Z) grid integer ierr ! completion code, 0=OK ! ierr.ne.0 means a "serious error". ! note: B field is [Bx,By,Bz]. ! all gradients are: [d/dx,d/dy,d/dz]. --->(return values of a single function) (f only) CALL eqxyz_fget(ivec,xx,yy,zz,ztol,ifcn,fval,nregion,ierr) (f, grad(f)) CALL eqxyz_fgrad(ivec,xx,yy,zz,ztol,ifcn, > fval,fgrad,nregion,ierr) (f, (rho,chi,phi)) CALL eqxyzmap_fget(ivec,xx,yy,zz,zrho,zchi,zphi,ztol, > ifcn,fval,nregion,ierr) (f, grad(f), (rho,chi,phi)) CALL eqxyzmap_fgrad(ivec,xx,yy,zz,zrho,zchi,zphi,ztol, > ifcn,fval,fgrad,nregion,ierr) -->(return values of multiple functions) (f only) CALL eqxyz_ffget(ivec,xx,yy,zz,ztol,nlist,ifcns, > ivecd,fvals,nregion,ierr) (f, grad(f)) CALL eqxyz_ffgrad(ivec,xx,yy,zz,ztol,nlist,ifcns, > ivecd,fvals,fgrads,nregion,ierr) (f, (rho,chi,phi)) CALL eqxyzmap_ffget(ivec,xx,yy,zz,zrho,zchi,zphi, > ztol,nlist,ifcns, > ivecd,fvals,nregion,ierr) (f, grad(f), (rho,chi,phi)) CALL eqxyzmap_ffgrad(ivec,xx,yy,zz,zrho,zchi,zphi, > ztol,nlist,ifcns, > ivecd,fvals,fgrads,nregion,ierr) -->(return values of B field only) (B only) CALL eqxyz_bget(ivec,xx,yy,zz,ztol,bvec,nregion,ierr) (B, grad(B)) CALL eqxyz_bgrad(ivec,xx,yy,zz,ztol,bvec,gbtensr,nregion, > ierr) (B, (rho,chi,phi)) CALL eqxyzmap_bget(ivec,xx,yy,zz,zrho,zchi,zphi,ztol, > bvec,nregion,ierr) (B, grad(B), (rho,chi,phi)) CALL eqxyzmap_bgrad(ivec,xx,yy,zz,zrho,zchi,zphi,ztol, > bvec,gbtensr,nregion,ierr) -->(return values of B field & multiple functions) (f, B only) CALL eqxyz_bffget(ivec,xx,yy,zz,ztol,bvec,nlist,ifcns, > ivecd,fvals,nregion,ierr) (f, grad(f), B, grad(B)) CALL eqxyz_bffgrad(ivec,xx,yy,zz,ztol,bvec,gbtensr, > nlist,ifcns, > ivecd,fvals,fgrads,nregion,ierr) (f, B, (rho,chi,phi)) CALL eqxyzmap_bffget(ivec,xx,yy,zz,zrho,zchi,zphi, > ztol,bvec,nlist,ifcns, > ivecd,fvals,nregion,ierr) (f, grad(f), B, grad(B), (rho,chi,phi)) CALL eqxyzmap_bffgrad(ivec,xx,yy,zz,zrho,zchi,zphi, > ztol,bvec,gbtensr,nlist,ifcns, > ivecd,fvals,fgrads,nregion,ierr)

Home | Top |

eqrz_*get

(old f77 xplasma 1 documentation) generic interface (f90): use xplasma_get ... call eqrz_get(...) For routines using flux coordinate: To have "zchi" interpreted as lying on a reversed (clockwise oriented) poloidal angle grid, substitute a negative number -ivec for ivec in the calling argument list. specific interfaces (f77/f90): arguments used by this series of routines: ! input: integer ivec ! vector dimension (vector of coordinates) real*8 zR(ivec) ! R coordinate, each vector element real*8 zZ(ivec) ! Z coordinate, each vector element real*8 zphi(ivec) ! phi coordinate, each vector element ! output: real*8 zrho(ivec) ! rho coordinate, each vector element real*8 zchi(ivec) ! chi coordinate, each vector element ! input: real*8 ztol ! rel. tolerance for coord. mapping ! (rho,chi,phi) maps to (x',y',z') ! with max(|x-x'|,|y-y'|,|z-z'|) ! .le. tol*[R of mag. axis]. ! output: real*8 bvec(3,ivec) ! field vector at each target point real*8 gbtensr(3,3,ivec) ! gbtensr(1:3,j,k)=grad(bvec(j,k)) ! input: integer ifcn ! a single fcn id, or... integer nlist ! no. of fcns to evaluate integer ifcns(nlist) ! list of fcn ids integer ivecd ! vector dimension for output arrays ! output: real*8 fval(ivec) ! function values, (single function) real*8 fgrad(3,ivec) ! function gradient (single function) ! ..or.. real*8 fvals(ivecd,nlist) ! function values returned real*8 fgrads(3,ivecd,nlist) ! function gradients returned. integer nregion(ivec) ! region code for each target point ! for target point j: ! nregion(j)=1: core plasma ! nregion(j)=2: scrape off layer ! nregion(j)=3: outside limiter ! nregion(j)=4: beyond (R,Z) grid integer ierr ! completion code, 0=OK ! ierr.ne.0 means a "serious error". ! note: B field is [BR,BZ,Bphi]. ! all gradients are: [d/dR,d/dZ,(1/R)d/dphi]. --->(return values of a single function) (f only) CALL eqrz_fget(ivec,zR,zZ,zphi,ztol,ifcn,fval,nregion,ierr) (f, grad(f)) CALL eqrz_fgrad(ivec,zR,zZ,zphi,ztol,ifcn, > fval,fgrad,nregion,ierr) (f, (rho,chi)) CALL eqrzmap_fget(ivec,zR,zZ,zphi,zrho,zchi,ztol, > ifcn,fval,nregion,ierr) (f, grad(f), (rho,chi)) CALL eqrzmap_fgrad(ivec,zR,zZ,zphi,zrho,zchi,ztol, > ifcn,fval,fgrad,nregion,ierr) -->(return values of multiple functions) (f only) CALL eqrz_ffget(ivec,zR,zZ,zphi,ztol,nlist,ifcns, > ivecd,fvals,nregion,ierr) (f, grad(f)) CALL eqrz_ffgrad(ivec,zR,zZ,zphi,ztol,nlist,ifcns, > ivecd,fvals,fgrads,nregion,ierr) (f, (rho,chi)) CALL eqrzmap_ffget(ivec,zR,zZ,zphi,zrho,zchi, > ztol,nlist,ifcns, > ivecd,fvals,nregion,ierr) (f, grad(f), (rho,chi)) CALL eqrzmap_ffgrad(ivec,zR,zZ,zphi,zrho,zchi, > ztol,nlist,ifcns, > ivecd,fvals,fgrads,nregion,ierr) -->(return values of B field only) (B only) CALL eqrz_bget(ivec,zR,zZ,zphi,ztol,bvec,nregion,ierr) (B, grad(B)) CALL eqrz_bgrad(ivec,zR,zZ,zphi,ztol,bvec,gbtensr,nregion, > ierr) (B, (rho,chi)) CALL eqrzmap_bget(ivec,zR,zZ,zphi,zrho,zchi,ztol, > bvec,nregion,ierr) (B, grad(B), (rho,chi)) CALL eqrzmap_bgrad(ivec,zR,zZ,zphi,zrho,zchi,ztol, > bvec,gbtensr,nregion,ierr) -->(return values of B field & multiple functions) (f, B only) CALL eqrz_bffget(ivec,zR,zZ,zphi,ztol,bvec,nlist,ifcns, > ivecd,fvals,nregion,ierr) (f, grad(f), B, grad(B)) CALL eqrz_bffgrad(ivec,zR,zZ,zphi,ztol,bvec,gbtensr, > nlist,ifcns, > ivecd,fvals,fgrads,nregion,ierr) (f, B, (rho,chi)) CALL eqrzmap_bffget(ivec,zR,zZ,zphi,zrho,zchi, > ztol,bvec,nlist,ifcns, > ivecd,fvals,nregion,ierr) (f, grad(f), B, grad(B), (rho,chi)) CALL eqrzmap_bffgrad(ivec,zR,zZ,zphi,zrho,zchi, > ztol,bvec,gbtensr,nlist,ifcns, > ivecd,fvals,fgrads,nregion,ierr)

Home | Top |

eq_*get

(old f77 xplasma 1 documentation) generic interface (f90): use xplasma_get ... call eq_get(...) To have "zchi" interpreted as lying on a reversed (clockwise oriented) poloidal angle grid, substitute a negative number -ivec for ivec in the calling argument list. specific interfaces (f77/f90): arguments used by this series of routines: ! input: integer ivec ! vector dimension (vector of coordinates) real*8 zrho(ivec) ! rho coordinate, each vector element real*8 zchi(ivec) ! chi coordinate, each vector element real*8 zphi(ivec) ! phi coordinate, each vector element ! output: real*8 zR(ivec) ! R coordinate, each vector element real*8 zZ(ivec) ! Z coordinate, each vector element ! input: integer irzmode ! =1: output B & grads in (R,Z,phi) ! =0: output B & grads in (sperp,chi,phi) ! output: real*8 bvec(3,ivec) ! field vector at each target point real*8 gbtensr(3,3,ivec) ! gbtensr(1:3,j,k)=grad(bvec(j,k)) ! input: integer ifcn ! a single fcn id, or... integer nlist ! no. of fcns to evaluate integer ifcns(nlist) ! list of fcn ids integer ivecd ! vector dimension for output arrays ! output: real*8 fval(ivec) ! function values, (single function) real*8 fgrad(3,ivec) ! function gradient (single function) ! ..or.. real*8 fvals(ivecd,nlist) ! function values returned real*8 fgrads(3,ivecd,nlist) ! function gradients returned. integer nregion(ivec) ! region code for each target point ! for target point j: ! nregion(j)=1: core plasma ! nregion(j)=2: scrape off layer ! nregion(j)=3: outside limiter ! nregion(j)=4: beyond (R,Z) grid integer ierr ! completion code, 0=OK ! ierr.ne.0 means a "serious error". ! note: if irzmode.eq.1: ! B field is [BR,BZ,Bphi]. ! all gradients are: [d/dR,d/dZ,(1/R)d/dphi]. ! if irzmode.eq.0: ! B field is [0,Bchi,Bphi] ! all gradients are: [d/dsperp,d/dschi,(1/R)d/dphi] ! where dsperp is ds in the direction normal to the ! flux surface, and, ! dschi is ds in the direction tangential to ! the flux surface in the poloidal plane. --->(return values of a single function) (f only) CALL eq_fget(ivec,zrho,zchi,zphi,irzmode,ifcn,fval,nregion, > ierr) (f, grad(f)) CALL eq_fgrad(ivec,zrho,zchi,zphi,irzmode,ifcn, > fval,fgrad,nregion,ierr) (f, (R,Z)) CALL eqmap_fget(ivec,zrho,zchi,zphi,zR,zZ,irzmode, > ifcn,fval,nregion,ierr) (f, grad(f), (R,Z)) CALL eqmap_fgrad(ivec,zrho,zchi,zphi,zR,zZ,irzmode, > ifcn,fval,fgrad,nregion,ierr) -->(return values of multiple functions) (f only) CALL eq_ffget(ivec,zrho,zchi,zphi,irzmode,nlist,ifcns, > ivecd,fvals,nregion,ierr) (f, grad(f)) CALL eq_ffgrad(ivec,zrho,zchi,zphi,irzmode,nlist,ifcns, > ivecd,fvals,fgrads,nregion,ierr) (f, (R,Z)) CALL eqmap_ffget(ivec,zrho,zchi,zphi,zR,zZ, > irzmode,nlist,ifcns, > ivecd,fvals,nregion,ierr) (f, (R,Z)) CALL eqmap_ffgrad(ivec,zrho,zchi,zphi,zR,zZ, > irzmode,nlist,ifcns, > ivecd,fvals,fgrads,nregion,ierr) -->(return values of B field only) (B only) CALL eq_bget(ivec,zrho,zchi,zphi,irzmode,bvec,nregion,ierr) (B, grad(B)) CALL eq_bgrad(ivec,zrho,zchi,zphi,irzmode,bvec,gbtensr,nregion, > ierr) (B, (R,Z)) CALL eqmap_bget(ivec,zrho,zchi,zphi,zR,zZ,irzmode, > bvec,nregion,ierr) (B, grad(B), (R,Z)) CALL eqmap_bgrad(ivec,zrho,zchi,zphi,zR,zZ,irzmode, > bvec,gbtensr,nregion,ierr) -->(return values of B field & multiple functions) (f, B only) CALL eq_bffget(ivec,zrho,zchi,zphi,irzmode,bvec,nlist,ifcns, > ivecd,fvals,nregion,ierr) (f, grad(f), B, grad(B)) CALL eq_bffgrad(ivec,zrho,zchi,zphi,irzmode,bvec,gbtensr, > nlist,ifcns, > ivecd,fvals,fgrads,nregion,ierr) (f, B, (R,Z)) CALL eqmap_bffget(ivec,zrho,zchi,zphi,zR,zZ, > irzmode,bvec,nlist,ifcns, > ivecd,fvals,nregion,ierr) (f, grad(f), B, grad(B), (R,Z)) CALL eqmap_bffgrad(ivec,zrho,zchi,zphi,zR,zZ, > irzmode,bvec,gbtensr,nlist,ifcns, > ivecd,fvals,fgrads,nregion,ierr)

Home | Top |

xplasma_get

(old f77 xplasma 1 documentation) The fortran-90 module use xplasma_get can be employed to allow the generic names call eq_get(...) call eqrz_get(...) call eqxyz_get(...) for all of the interpolation routines described in the neighbouring sections, and, the R4_ versions of the routines as well. The xplasma_get module contains a description of all the specific calls. The compiler decides which one to call by analyzing the calling arguments. Caution#1: "xplasma_get" and "xplasma_calls" cannot both be used in the same routine; Caution#2: there exist functionally correct calls to the software for which the fortran-90 compiler will fail to match up the proper routine, giving a compile-time error instead. The use of this module is optional. In its absence, full subroutine names must be used.

Home | Top |

lists

(old f77 xplasma 1 documentation) XPLASMA now supports a generic facility for creating and accessing lists. Each list has a name (max 32 characters, one alphanumeric word, treated as uppercase), a label (max 60 characters), and a size which specifies the number of elements in the list. Each list element has a name (max 32 characters, one alphanumeric word, treated as uppercase), and the following associated data: a character string (max 60 characters) in addition to the name a floating point number an integer. Lists can be used to communicate such information as: -> a list of plasma spacies and the Z and A values of each species: name of example list: TR_THERMAL_SPECIES, size = 3 (label: "list of thermal ion species") name character data floating data integer data H (blank) 1.000 1 D (blank) 2.000 1 HE4 (blank) 4.000 2 interpretation: floating data gives "A", integer gives "Z". -> a timestep name of example list: TR_TIMESTEP, size = 2 (label: "timestep for TRANSP sources") name character data floating data integer data TR_TS1 S 1.010 0 TR_TS2 S 1.020 0 interpretation: character data gives physical units, floating data gives actual time values. -> a collection of related profile data items name of example list: TR_EHEAT, size = 5 (label: "integrated electron heating profiles") name character data floating data integer data TR_PBE W 3.073e4 310 TR_PFE W 0.000 311 TR_PEICRF W 0.000 312 TR_PEECRF W 0.000 313 TR_PELH W 0.000 314 interpretation: a list of heating profiles. Character data gives physical units, floating data gives total amount (power, W, in this context), and the integer gives XPLASMA id of the interpolating function f(rho). The methods for finding and accessing lists are described here. Methods for creating lists and list contents are described under "Setup Routines".

Home | Top |

eq_nlist

(old f77 xplasma 1 documentation) To get the number of lists currently known to XPLASMA: integer :: num_lists ! value returned by subroutine call call eq_nlist(num_lists)

Home | Top |

eq_lists

(old f77 xplasma 1 documentation) To get the names and ids of *all* lists currently known to XPLASMA: ! input: integer :: num_lists ! should match value returned by eq_nlists ! output: character*32 :: list_names(num_lists) ! names of lists integer :: list_ids(num_lists) ! list id codes integer :: ierr ! completion code (0=OK) call eq_lists(num_lists,list_names,list_ids,ierr) The list of names is retunred in alphabetic order. To refer to a specific list, its id code is needed.

Home | Top |

eq_nlist_p

(old f77 xplasma 1 documentation) To get the number of lists currently known to XPLASMA which contain XPLASMA profile data: integer :: num_lists ! value returned by subroutine call call eq_nlists(num_lists)

Home | Top |

eq_lists_p

(old f77 xplasma 1 documentation) To get the names and ids of *all* lists containing XPLASMA profile data: ! input: integer :: num_lists ! should match value returned by eq_nlists ! output: character*32 :: list_names(num_lists) ! names of lists integer :: list_ids(num_lists) ! list id codes integer :: ierr ! completion code (0=OK) call eq_lists(num_lists,list_names,list_ids,ierr) The list of names is retunred in alphabetic order. To refer to a specific list, its id code is needed.

Home | Top |

eq_glistnum

(old f77 xplasma 1 documentation) To find the list_id associated with a specific list name: ! input: character*32 :: list_name ! name of a specific list ! output: integer :: list_id ! corresponding id code call eq_glistnum(list_name,list_id) If there is no such list in the current XPLASMA, list_id = 0 is returned.

Home | Top |

eq_list_size

(old f77 xplasma 1 documentation) To find the size (number of elements) of a specific list: ! input: integer :: list_id ! id of an existing list ! output: integer :: isize ! list size (no. of elements) call eq_list_size(list_id,list_size) If the id is invalid, list_size = 0 is returned.

Home | Top |

eq_list_maxsize

(old f77 xplasma 1 documentation) To find them maximum number of elements (isze) of any list: ! output: integer :: max_size call eq_list_maxSize(max_size) If there are no lists, max_size = 0 is returned.

Home | Top |

eq_list_label

(old f77 xplasma 1 documentation) To fetch the label for a list: ! input: integer :: list_id ! id of an existing list ! output: character*60 alabel ! list label (arb. string) returned call eq_list_label(list_id,alabel)

Home | Top |

eq_list_enames

(old f77 xplasma 1 documentation) To get list element names: ! input: integer :: list_id ! id of an existing list integer :: list_size ! size of list (should match eq_list_size value) ! output: character*32 :: enames(list_size) ! list element names returned. integer :: ierr ! completion code, 0=OK call eq_list_enames(list_id,list_size,enames,ierr) ierr is set, and enames = " " returned, if the list id is invalid or if the list_size value is less than the actual size of the list.

Home | Top |

eq_list_ivals

(old f77 xplasma 1 documentation) To get integer data associated with each list element: ! input: integer :: list_id ! id of an existing list integer :: list_size ! size of list (should match eq_list_size value) ! output: integer :: ivals(list_size) ! integer list data integer :: ierr ! completion code, 0=OK call eq_list_ivals(list_id,list_size,ivals,ierr) ierr is set, and ivals = 0 returned, if the list id is invalid or if the list_size value is less than the actual size of the list.

Home | Top |

eq_list_chvals

(old f77 xplasma 1 documentation) To get character data associated with each list element: ! input: integer :: list_id ! id of an existing list integer :: list_size ! size of list (should match eq_list_size value) ! output: character*60 :: chvals(list_size) ! character data with each list element integer :: ierr ! completion code, 0=OK call eq_list_chvals(list_id,list_size,chvals,ierr) ierr is set, and chvals = " " returned, if the list id is invalid or if the list_size value is less than the actual size of the list.

Home | Top |

eq_list_r8vals

(old f77 xplasma 1 documentation) To get floating point data associated with each list element: ! input: integer :: list_id ! id of an existing list integer :: list_size ! size of list (should match eq_list_size value) ! output: real*8 :: r8vals(list_size) ! floating point list data integer :: ierr ! completion code, 0=OK call eq_list_r8vals(list_id,list_size,r8vals,ierr) ierr is set, and r8vals = 0 returned, if the list id is invalid or if the list_size value is less than the actual size of the list.

Home | Top |

eq_list_r4vals

(old f77 xplasma 1 documentation) To get floating point data associated with each list element: ! input: integer :: list_id ! id of an existing list integer :: list_size ! size of list (should match eq_list_size value) ! output: real :: r4vals(list_size) ! floating point list data integer :: ierr ! completion code, 0=OK call eq_list_r4vals(list_id,list_size,r4vals,ierr) ierr is set, and r4vals = 0 returned, if the list id is invalid or if the list_size value is less than the actual size of the list.

Home | Top |

jacobian_matrix

(old f77 xplasma 1 documentation) for irzmode=0: This routine finds the jacobian matrix d[x,y,z]/d[rho,chi,phi] for each point from a set of (rho,chi,phi) vectors. for irzmode=1: this routine returns the jacobian matrix d[R,Z,Lphi]/d[rho,chi,phi]; Lphi=(spatial displacement in phi direction -- R*phi) in axisymmetric case: [(dR/drho) (dR/dchi) 0 ] [(dZ/drho) (dZ/dchi) 0 ] [ 0 0 R ] and det(J)= -R*((dR/drho)*(dZ/dchi)-(dR/dchi)*(dZ/drho)) (-sign as (R,Z,phi) is left-handed) ! input: integer ivec ! vector dimension (vector of coordinates) real*8 rho(ivec) ! rho coordinate, each vector element real*8 chi(ivec) ! chi coordinate, each vector element real*8 phi(ivec) ! phi coordinate, each vector element ! output: real*8 jtens(3,3,ivec) ! Jacobian real*8 detj(ivec) ! det(jtens), determinant ! **** det(jtens) not dependent on irzmode ! integer ierr ! completion code, 0=OK ! notes for (irzmode=0): ! jtens(1:3,1,1:ivec) = (dx/drho,dx/dchi,dx/dphi), all elements ! jtens(1:3,2,1:ivec) = (dy/drho,dy/dchi,dy/dphi), all elements ! jtens(1:3,3,1:ivec) = (dz/drho,dz/dchi,dz/dphi), all elements ! ! notes for (irzmode=1): ! jtens(1:3,1,1:ivec) = (dR/drho,dR/dchi,dR/dphi), all elements ! jtens(1:3,2,1:ivec) = (dZ/drho,dZ/dchi,dZ/dphi), all elements ! jtens(1:3,3,1:ivec) = R*(dphi/drho,dphi/dchi,1), all elements ! ... ... call eq_getjac(ivec,rho,chi,phi,irzmode,jtens,detj,ierr) To have "chi" interpreted as lying on a reversed (clockwise oriented) poloidal angle grid, substitute a negative number -ivec for ivec in the calling argument list.

Home | Top |

determinant_of_jacobian

(old f77 xplasma 1 documentation) This routine returns the determinant of the jacobian matrix d[R,Z,Lphi]/d[rho,chi,phi]; Lphi=(spatial displacement in phi direction -- R*phi) in axisymmetric case: [(dR/drho) (dR/dchi) 0 ] [(dZ/drho) (dZ/dchi) 0 ] [ 0 0 R ] and det(J)= -R*((dR/drho)*(dZ/dchi)-(dR/dchi)*(dZ/drho)) (-sign as (R,Z,phi) is left-handed) ! input: integer ivec ! vector dimension (vector of coordinates) real*8 rho(ivec) ! rho coordinate, each vector element real*8 chi(ivec) ! chi coordinate, each vector element real*8 phi(ivec) ! phi coordinate, each vector element real*8 zscale ! scale factor to apply to result (e.g. 1.0) ! output: real*8 detj(ivec) ! det(jtens), determinant ! integer ierr ! completion code, 0=OK call eq_getdetj(ivec,rho,chi,phi,zscale,detj,ierr) To have "chi" interpreted as lying on a reversed (clockwise oriented) poloidal angle grid, substitute a negative number -ivec for ivec in the calling argument list.

Home | Top |

distance_to_plasma

(old f77 xplasma 1 documentation) The following routines can be used to determine the distance from any point in space to a specified surface on the plasma (usually the plasma boundary). These routines have the convention that if the returned distance is positive, the point is outside the surface by the given amount; if the distance is negative, the point is inside by the given amount. (a) distance of cartesian coordinate point(s) (x,y,z) to plasma boundary --fast, approximate solution subroutine eqx_dfast(ivec,x,y,z,dist,ierr) (b) distance of cylindrical coordinate point(s) (R,Z,phi) to plasma boundary --fast, approximate solution subroutine eq_dfast(ivec,R,Z,phi,dist,ierr) To have "chi_out" interpreted as lying on a reversed (clockwise oriented) poloidal angle grid, substitute a negative number -ivec for ivec in the calling argument list. (c) distance of cartesian coordinate point(s) (x,y,z) to any "rho" surface in plasma --slow, precise solution subroutine eqx_bdfind(ivec,x,y,z,rho_in,chi_out,phi_out,dist,ierr) (d) distance of cylindrical coordinate point(s) (R,Z,phi) to any "rho" surface in plasma --slow, precise solution subroutine eq_bdfind(ivec,R,Z,phi,rho_in,chi_out,phi_out,dist,ierr) The fast routines function by using a bilinear lookup on a table of precomputed exact solutions; the precise routines solve the distance minimization problem to high accuracy with a root finder, and also give the (chi,phi) of the nearest point on the requested rho surface. Note: the data for the fast evaluations are only available after the limiters and (R,Z) grid have been set up. If this setup is not done, the code reverts to the accurate but slow method. The routines share many arguments: ! input: integer ivec ! vector dimension, no. of pts to solve real*8 x(ivec),y(ivec),z(ivec) ! cartesian coordinate points ! or... real*8 R(ivec),Z(ivec),phi(ivec) ! cylindrical coordinate points ! ! extra input, bdfind routines: ! real*8 rho_in ! "rho" of desired surface ! ! output: real*8 dist(ivec) ! distance to bdy or selected surface ! .gt.0 -- outside, .lt.0 -- inside ! .eq.0 -- the point is on the surface. integer ierr ! completion code, 0=OK ! ! extra output, bdfind routines: ! real*8 chi_out(ivec) ! "chi" of nearest point on target surface real*8 phi_out(ivec) ! "phi" of nearest point on target surface

Home | Top |

distance_to_limiter

(old f77 xplasma 1 documentation) The following routines compute the distance from given points to the nearest limiter. If the distance is positive, the point is behind the limiter by the given amount; if the distance is negative, the point is on the plasma side of the limiter by the given amount. (a) distance of cartesian coordinate point(s) (x,y,z) to limiter subroutine eqx_dist(ivec,x,y,z,dist,ilopt,Rlim,Zlim,philim,ierr) (b) distance of cylindrical coordinate point(s) (R,Z,phi) to limiter subroutine eq_rzdist(ivec,R,Z,phi,dist,ilopt,Rlim,Zlim,philim,ierr) For both of these routines, if the control flag "iopt" is set, then, the cylindrical coordinates of nearest limiter point are also returned. The arguments are: ! input: integer ivec ! vector dimension, no. of pts to solve real*8 x(ivec),y(ivec),z(ivec) ! cartesian coordinate points ! or... real*8 R(ivec),Z(ivec),phi(ivec) ! cylindrical coordinate points ! output: real*8 dist(ivec) ! distance to limiter ! .gt.0 -- outside, .lt.0 -- inside ! .eq.0 -- the point is on the limiter. ! input: integer ilopt ! if ilopt=1, compute Rlim,Zlim,philimm ! output, only if ilopt.eq.1 ... real*8 Rlim(ivec) ! R of nearest limiter point real*8 Zlim(ivec) ! Z of nearest limiter point real*8 philim(ivec) ! phi of nearest limiter point ! general output: integer ierr ! completion code, 0=OK

Home | Top |

segment_bdy_locator

(old f77 xplasma 1 documentation) It sometimes happens that one has a line segment AB, such that A is outside and B is inside a boundary (either the limiter boundary or the core plasma boundary), and the need is to find the point on AB which intersects the boundary in question. The vectorized routine eq_fxcep can be used to find such segment boundary intersections: ! input: integer ivec ! vector dimension (# of segments) integer itype ! =1: want plasma bdy; =2: limiter integer idinit ! =1: endpoint distances are known ! more input: real*8 ra(ivec),za(ivec) ! "A" endpoints of segments real*8 phia(ivec) ! "A" endpoints phi locations ! input (if idinit.eq.1) or output (if idinit.ne.1): real*8 da(ivec) ! distance, "A" to chosen bdy ! more input: real*8 rb(ivec),zb(ivec) ! "B" endpoints of segments real*8 phib(ivec) ! "B" endpoints phi locations ! input (if idinit.eq.1) or output (if idinit.ne.1): real*8 db(ivec) ! distance, "B" to chosen bdy ! input: real*8 tol ! accuracy tolerance ! approximate accuracy of intercept positions: ! tol*[system size], system size = ~midplane half width ! of plasma (approx). ! output: real*8 rx(ivec),zx(ivec) ! segment bdy intercept pts returned real*8 phix(ivec) ! segment bdy intercept phi values ! integer istat(ivec) ! segment status code (see below) ! integer ierr ! completion code, 0=OK ! ierr is only set for "serious" errors. ! segment status codes: on output, ! ! istat(j)=2 -- both endpoints outside bdy ! istat(j)=1 -- 1st endpoint outside, 2nd endpoint inside ! istat(j)=-1 -- 1st endpoint inside, 2nd endpoint outside ! istat(j)=-2 -- both endpoints inside bdy ! (rx(j),zx(j)) contains bdy intercept only if abs(istat(j))=1. ... ... call eq_fxcep(ivec,itype,idinit, > ra,za,phia,da, rb,zb,phib,db, > tol, > rx,zx,phix, istat, ierr) ! the routine can be used to define a start point for RF rays ! or neutral atom tracks or diagnostic sightline - plasma ! intersections.

Home | Top |

mag_axis_finder

(old f77 xplasma 1 documentation) The following routine returns R, Z, and mod(B) at the magnetic axis, for given phi value. (For axisymmetric equilibria, the phi value has no effect; one can use ivec=1 and phi(1)=0.0d0). ! input: integer ivec ! vector dimension real*8 phi(ivec) ! toroidal angle coordinate ! output: real*8 B_axis(ivec) ! mod(B) on axis real*8 R_axis(ivec) ! R of magnetic axis real*8 Z_axis(ivec) ! Z of magnetic axis ... call eq_gaxis(ivec,phi,B_axis,R_axis,Z_axis) --> simplified routine for axisymmetric case: call eq_sgaxis(b_axis,r_axis,z_axis) returns the single axial values for B, R, and Z; the arguments can be real*8 scalars.

Home | Top |

Fourier_Spline_Representation

(old f77 xplasma 1 documentation) The (R,Z) MHD equilibrium may be retrieved in Fourier Spline form, i.e. the coeffcient profiles Rc[i](x), Rs[i](x), Zc[i](x), Zs[i](x) satisfying R(x,theta) = Rc[0](x) + sum(Rc[i](x)*cos(i*theta)+Rs[i](x)*sin(i*theta)) Z(x,theta) = Zc[0](x) + sum(Zc[i](x)*cos(i*theta)+Zs[i](x)*sin(i*theta)) ! generally x is normalized sqrt(toroidal_flux), aka "rho". where the sum is from i=1 to kmom, where kmom is the maximum Fourier coefficient retained. To get kmom: integer :: kmom call xmoments_kmom_get(kmom) The moments profile retrieval routines can return either the moments coefficients themselves, or, a scaled representation Rcx[i] = Rc[i]/x**j, j=min(i,kmaxe) which has been constructed in a way such that the behavior as x->0 is kept smooth, i.e. Rc[i] is proportional to x**i in the limit as x->0. (kmaxe can be fetched by an undocumented xplasma routine-- work in progress-- for now users should just get the unnormalized coefficient). Each moment coefficient is fetched by a separate call, using one of the following four subroutines: eqmom_Rcos(...) for Rc[i] eqmom_Rsin(...) for Rs[i] eqmom_Zcos(...) for Zc[i] eqmom_Zsin(...) for Zs[i] All of the above routines have the following arguments: for input: integer nx ! number of x points at which the coefficient is desired. real*8 x(nx) ! the actual x points (x = sqrt(phi/philim) = "rho"). integer inorm ! =0 to get the coefficient, =1 to get coeff with ! normalization-- context dependent, do not use... integer i ! the moment index of the desired coefficient for output: real*8 momarr(nx) ! the coefficients (or coeff/x**i) returned. integer iwarn ! =0: OK; =-1: "i" not in range 0 to kmom. if the warning flag is set, momarr=0.0 is returned. The form of the call is then: call eqmom_Rcos(x,nx,inorm,i,momarr,iwarn) ! inorm=0 recommended and a sample fragment showing the use of these routines follows: integer kmom real*8, dimension(:,:), allocatable :: rc,rs,zc,zs ! x(1:nx) contains the user's grid. call xmoments_kmom_get(kmom) allocate(rc(0:kmom,nx),rs(0:kmom,nx)) allocate(zc(0:kmom,nx),zs(0:kmom,nx)) do i=0,kmom call eqmom_Rcos(x,nx,0,i,rc(i,1:nx),iwarn) ! get the coeffs. call eqmom_Rsin(x,nx,0,i,rs(i,1:nx),iwarn) call eqmom_Zcos(x,nx,0,i,zc(i,1:nx),iwarn) call eqmom_Zsin(x,nx,0,i,zs(i,1:nx),iwarn) enddo The Fourier Representation is available after xplasma has been initialized from any data source.

Home | Top |

NCLASS Poloidal Moments

(old f77 xplasma 1 documentation) The poloidal moments of a geometric factor used to compute the Pfirsch-Schluter contribution of the viscosity for NCLASS as described in Houlberg,Shaing,Hirshman,Zarnstorff, "Bootstrap current and neoclassical transport in tokamaks of arbitray collisionality and aspect ratio", Phys. Plasmas 4 (9), September 1997, pg 3230-3242 are returned by the eq_psmom function. The Fm moments from this paper are returned in the PSMOM argument. For rho<RHOMIN, axis values are returned. The relative error returned by ZERROR =|sum(Fm) - <(n.grad(B))**2>/<B**2>| / max(<(n.grad(B))**2>/<B**2>) should go to zero for increasing number of moments. ! input integer :: ivec ! number of surfaces real*8 :: rho(ivec) ! radial coordinate real*8 :: rhomin ! rho values below this are considered on axis integer :: nmom ! number of moments to compute real*8 :: phi1 ! toroidal coordinate, same one used for all surfaces integer :: idmom ! dimension of the psmom array ! real*8 :: psmom(idmom,ivec) ! PS moments real*8 :: gamma(ivec) ! wayne's gamma = 2*pi/integral_0_2pi[Bmod/B.grad(theta)]_dtheta real*8 :: ngrdb2(ivec) ! <(n.grad(B))**2> real*8 :: b2(ivec) ! <B**2> real*8 :: zerror(ivec) !|sum(Fm)-<(n.grad(B))**2>/<B**2>|/max(<(n.grad(B))**2>/<B**2>) integer :: ier ! nonzero on error call eq_psmom(ivec, rho, rhomin, nmom, phi1, idmom, psmom, gamma, ngrdb2, b2, zerror, ier)

Home | Top |

Numerical_Integration

(old f77 xplasma 1 documentation) (dmc: 20 Sept 2000. Although these interfaces are written with eventual extension to 3d non-axisymmetric in mind, currently only axisymmetric geometry is supported).

Home | Top |

Introduction

(old f77 xplasma 1 documentation) Once the magnetic coordinates (rho,chi) are established, the spline functions g(rho), psi(rho), R(rho,chi), Z(rho,chi), and the vector B(rho,chi) have been constructed, it becomes possible to evaluate metric and field flux surface / flux zone averages and integrals. Generally the integrands are algebraic combinations of spline functions, optionally weighted by the determinant of the Jacobian, which is also an algebraic combination of splines. Integrals are evalaluated numerically using an 11-point Gauss Legendre method within each spline grid zone, and summing across multiple zones. For typical integrands the (bi)cubic pieces within spline-grid zones are C-infinity, which means that components of the sum forming the integral are estimated to an accuracy within REAL*8 machine precision, as is readily verified by comparison to higher order Gauss Legendre formulae. Integrations are performed on a set of flux surfaces-- not necessarily the same set of surfaces as given by the rho spline grid -- or over flux zones between successive flux surfaces. Integrations are performed over entire surfaces or zones (poloidal angle chi varying from 0 to 2pi), or, over a user defined discreet set of chi subzones, again not necessarily the same zones as defined by the chi spline grid. Six types numerical integrations are available. In these expressions: "f" is the user selected integrand function "det(J)" is the absolute value of the determinant of the Jacobian (i.e. R*[(dR/drho)*(dZ/dchi)-(dZ/drho)*(dR/dchi)] in axisymmetric geometry). When det(J) is used, the software verifies that sign(det(J)) does not change; an error will be reported if it does. a) surface integral: Integral[phi = 0 to 2pi] dphi * Integral[chi = 0 to 2pi] dchi * f = 2pi * Integral[chi = 0 to 2pi] dchi * f (in axisymmetric geometry) --computed at each of N rho surface (see setup routines) --also available split into chi subzones b) volume weighted surface integral: Integral[phi = 0 to 2pi] dphi * Integral[chi = 0 to 2pi] dchi * f * det(J) = 2pi * Integral[chi = 0 to 2pi] dchi * f * det(J) (in axisymmetric geometry) --computed at each of N rho surface (see setup routines) --also available split into chi subzones c) volume weighted surface average: A type(b) integral, normalized by Integral[phi = 0 to 2pi] dphi * Integral[chi = 0 to 2pi] dchi * det(J) --computed at each of N rho surface (see setup routines) --also available split into chi subzones d) zone integral: Integral[phi = 0 to 2pi] dphi * Integral[chi = 0 to 2pi] dchi * Integral[rho = rho(j) to rho(j+1)] drho * f = 2pi * Integral[chi = 0 to 2pi] dchi * Integral[rho = rho(j) to rho(j+1)] drho * f (in axisymmetric geometry) --computed in the N-1 zones between the N rho surfaces --also available split into chi subzones e) volume weighted zone integral Integral[phi = 0 to 2pi] dphi * Integral[chi = 0 to 2pi] dchi * Integral[rho = rho(j) to rho(j+1)] drho * f * det(J) = 2pi * Integral[chi = 0 to 2pi] dchi * Integral[rho = rho(j) to rho(j+1)] drho * f * det(J) (in axisymmetric geometry) --computed in the N-1 zones between the N rho surfaces --also available split into chi subzones Note that if f=1 the integral result is the zone volume, which (for chi = 0 to 2pi) we'll call delta_volume(j). f) volume weighted zone average a type (e) integral, normalized in each zone j by dividing by delta_volume(j). --computed in the N-1 zones between the N rho surfaces --also available split into chi subzones

Home | Top |

setup

(old f77 xplasma 1 documentation) A rho grid for integrations needs to be defined. This can be but need not necessarily be the same rho grid as was used for setting up the g, psi, R, Z, and B field splines. The rho grid identifies an ascending sequence of rho surfaces, at which / between which numerical integrations are to be performed. Optionally, a chi grid can also be defined, to allow breaking up an integration into zones [rho(j),rho(j+1)]x[chi(k),chi(k+1)], or surface intervals [chi(k),chi(k+1)] at each surface rho(j), for surface integrals. The integration rho grid (chi grid) can be redefined any number of times, so that, for a given xplasma geometry and field, the call sequence setup rho-grid-A (optionally set up chi-grid-A) evaluate metric integrals on rho-grid-A (chi-grid-A) setup rho-grid-B (optionally set up chi-grid-B) evaluate metric integrals on rho-grid-B (chi-grid-B) is readily done.

Home | Top |

basic_setup

(old f77 xplasma 1 documentation) The basic setup call defines the integration rho grid: integer iauto ! =1 for automatic generation of rho sequence ! =0 for user supplied rho sequence integer inumrhos ! number of rho points (each identifies a surface) real*8 zrho(inumrhos) ! the actual rho values ! if iauto=1, evenly spaced values from rho(axis) ! to rho(bdy), inclusive, are output. ! if iauto=0, user supplied values must lie within ! the range defined by the splines. real*8 zrhomin ! minimum safe rho (approach to axial singularity) ! det(J) --> 0 as rho --> rho(axis). ! a typical safe choice: ! rho(axis)+1.0d-7*(rho(bdy)-rho(axix)) ! ! output: integer ierr ! completion code, 0=OK ........ call eq_flxint_init(iauto,inumrhos,zrho,zrhomin,ierr) The setup evaluates the zone volumes between successive rho surfaces; it uses this integration as a test to set "ineed". An example of the use of eq_flxint_init can be found in xplasma in the source code: eqdbg_flxint.for

Home | Top |

optional_chi_grid

(old f77 xplasma 1 documentation) This optional further setup call defines the integration chi grid: integer iauto ! =1 for automatic generation of chi sequence ! =0 for user supplied chi sequence integer inumchis ! number of chi points ! each identifies a chi interval boundary. real*8 zchi(inumchis) ! the actual chi values ! if iauto=1, evenly spaced values from chi(min) ! to chi(max), inclusive, are output; the extrema ! are taken from the chi spline grid. ! if iauto=0, user supplied values must be given ! in increasing order, and must lie within one ! period of the periodic chi grid. ! ! output: ! integer ierr ! completion code, 0=OK ........ call eq_flxint_chinit(iauto,inumchis,zchi,ierr) Note that this call must come *after* an eq_flxint_init call. Note also, in related documentation of the integration routines, the quantity "inumchi" refers to the number of chi intervals, which is (inumchis - 1).

Home | Top |

Predefined_Integrations

(old f77 xplasma 1 documentation) Certain "canned" integrations are available by calling "eq_flxint"...

Home | Top |

eq_flxint subroutine

(old f77 xplasma 1 documentation) ! eq_flxint input: character*20 iname ! name-of-desired-integral integer noption ! accuracy control (noption=1 recommended) ! ! noption=0 -- evaluate quadrature to near machine precision accuracy; ! a message is generated recommending a non-zero ! noption value that would be sufficiently accurate. ! noption=1 -- use 11-point Gauss-Legendre integration on each segment ! =2 -- use 21-point Gauss-Legendre integration on each segment ! =3 -- use 43-point Gauss-Legendre integration on each segment ! (each segment is a continuous segment btw spline grid pts) ! ! **(generally noption=1 is sufficient real*8 machine precision, ! and it is the fastest by far) ! inteter inumchi ! chi dimension of results array ! --if inumchi=1, do whole flux surface ! integrals. ! --if inumchi.ge.(# of chi intervals ! specified via a prior eq_flxint_chinit ! call), break up the integral into the ! chi intervals and store the partial ! results ! --if inumchi.gt.1 but less than the ! no. of intervals: this is an error. integer inumrho ! rho dimension of results array ! --must be .ge. the number of zones or ! number of surfaces, depending on the ! type of integral. ! eq_flxint output: real*8 result(inumchi,inumrho) ! integration results integer ierr ! completion code, 0=OK .... call eq_flxint(name,noption,result,inumchi,inumrho,ierr) Examples: call eq_flxint('DVOL',1,result,30,20,ierr) --valid if no. of rho surfaces is .le.21 --valid if chi intervals are defined and there are at least 30 of them (i.e. 31 chi interval boundaries). result(j,k) = the volume in the region [chi(j),chi(j+1)]x[rho(k),rho(k+1)] j = 1 to (#of chi intervals) k = 1 to (#of rho zones) call eq_flxint('<1/R^2>',1,result,1,20,ierr) --valid if no. of rho surfaces is .le.21 result(k) = volume weighted average of 1/R**2, integrating chi = 0 to 2pi, between surfaces at rho(k) and rho(k+1). k = 1 to (#of rho zones) More realistic code examples of the use of eq_flxint can be found in xplasma in the source code: eqdbg_flxint.for The minimum required inum, inumchi was determined by preceding initialization calls (eq_flxint_init, eq_flxint_chinit); the values can be retrieved as follows: call fluxav_nzones_get(inumchi,inumrho) ! inumrho = #of rho zones --or-- call fluxav_nsurfs_get(inumchi,inumrho) ! inumrho = #of rho surfaces ! = (#of rho zones) + 1 ! inumchi = #of chi intervals ! (defined by prior eq_flxint_chinit call) ! ( =1 if no prior eq_flxint_chinit call)

Home | Top |

Integration names

(old f77 xplasma 1 documentation) These are the character string names passed to "eq_flxint". All names are case-insensitive. Basic metrics: inumrho = #of rho zones inumchi = 1 --or-- #of rho zones * #of chi zones DVOL -- zone volumes (units of R,Z)^3 DAREA -- cross sectional area btw successive rho surfaces (units of R,Z)^2 inumrho = #of rho surfaces inumchi = 1 --or-- #of rho surfaces * #of chi zones SURF -- surface area of each rho surface (units of R,Z)^2 LPOL -- poloidal path length around each rho surface (units of R,Z) DVDRHO -- dV/drho at each rho surface (units of R,Z)^3 Zonal volume averages --integrands are volume integrated; then zone volume is divided out inumrho = #of rho zones inumchi = 1 --or-- #of chi zones moments of R: <R^2> <R> <1/R> <1/R^2> <1/R^3> moments of |grad(rho)| <grad(rho)> <grad(rho)^2> moments involving |grad(rho)| and R <grad(rho)^2/R^2> <grad(rho)^2/R^3> <R^2*grad(rho)^2> <1/(R*grad(rho))> moment involving |grad(rho)| and mod(B) <grad(rho)^2/B^2> moments of B (mod(B)) or vertical component of B, BZ <B^2> <B> <1/B> <1/B^2> <BZ^2> Volume weighted surface averages inumrho = #of rho surfaces inumchi = 1 --or-- #of chi zones --names as above, but with "S" appended, e.g. <R^2>S or <grad(rho)^2/R^2>S These quantities are are the flux surface integrals normalized by DVDRHO. Since at the axis DVDRHO=0.0, the averages there are just the local values of the integrand. (note: dmc 21 Sept 2000: several additional metric averages will be added soon, to complete the set needed by NCLASS. Also, suggestions for additional canned integrations are welcome, send to dmccune@pppl.gov).

Home | Top |

user_defined_integrations

(old f77 xplasma 1 documentation) Any quantity that can be represented as a bicubic spline can be integrated, with the following routines. The procedure is as follows: 1. construct an array f(nchi,nrho) containing the integrand function values f(j,k) = f(chi(j),rho(k)), where the {chi(j)} and {rho(k)} values are from the *original* grid used to set up the R and Z splines, *not* the integration zone grids. 2. call the integrator routine, which will a) construct a temporary (bicubic) spline from f b) perform the requested integral c) discard the temporary spline Four types of integrations are available: c *** iwant *** specifies the type of integration desired: c here "f" denotes the interpolating function generated from the c passed array data. c c iwant=1: surface integral: c inumchi=1: c int[phi=0 to 2pi] dphi * { c int[chi=0 to 2pi] dchi * f } c c result(1:inumrho) computed; inumrho = #of surfaces c result(1,j) -- integrated at rho(j) c c inumchi=(# of chi intervals) c result(1:inumchi,1:inumrho) computed; c result(i,j) -- integrated from chi(i) to chi(i+1) at rho(j). c c iwant=5: volume weighted surface integral: c inumchi=1: c int[phi=0 to 2pi] dphi * { c int[chi=0 to 2pi] dchi * f * det(Jacobian) } c c result(1:inumrho) computed; inumrho = #of surfaces c result(1,j) -- integrated at rho(j) c c inumchi=(# of chi intervals) c result(1:inumchi,1:inumrho) computed; c result(i,j) -- integrated from chi(i) to chi(i+1) at rho(j). c c **caution** if rho(1) corresponds to the mag. axis, a c det(Jacobian)=0 and a value of 0.0 is always returned! c c iwant=6: volume weighted surface average: c inumchi=1: c c int[phi=0 to 2pi] dphi * { c int[chi=0 to 2pi] dchi * f * det(Jacobian)} c ----------------------------------------------- c int[phi=0 to 2pi] dphi * { c int[chi=0 to 2pi] dchi * det(Jacobian)} c c result(1:inumrho) computed; inumrho = #of surfaces c result(1,j) -- integrated at rho(j) c c inumchi=(# of chi intervals) c result(1:inumchi,1:inumrho) computed; c result(i,j) -- integrated from chi(i) to chi(i+1) at rho(j). c c **caution** if rho(1) corresponds to the mag. axis, c the value "f" evaluated at the axis is returned there. c c zonal integrals: result(1:inumchi,1:inumrho) are computed c c iwant=2: integrate f*drho*dchi*dphi: c inumchi=1: c int[rho=rho(j) to rho(j+1)] drho * { c int[phi=0 to 2pi] dphi * { c int[chi=0 to 2pi] dchi * f } } c c result(1:inumrho) computed; inumrho = #of surfaces - 1 c result(1,j) -- integrated from rho(j) to rho(j+1). c c inumchi=(# of chi intervals) c result(1:inumchi,1:inumrho) computed; c result(i,j) -- doubly integrated from chi(i) to chi(i+1), c rho(j) to rho(j+1) c c iwant=3: integrate f*dV (use det(Jacobian)) c c int[rho=rho(j) to rho(j+1)] drho * { c int[phi=0 to 2pi] dphi * { c int[chi=0 to 2pi] dchi * f * det(Jacobian) } } c c result(1:inumrho) computed; inumrho = #of surfaces - 1 c result(1,j) -- integrated from rho(j) to rho(j+1). c c inumchi=(# of chi intervals) c result(1:inumchi,1:inumrho) computed; c result(i,j) -- doubly integrated from chi(i) to chi(i+1), c rho(j) to rho(j+1) c c iwant=4: compute <f> = (integrated f*dV)/dVol c where dVol is the volume btw rho(j) and rho(j+1) c c result(1:inumrho) computed; inumrho = #of surfaces - 1 c result(1,j) -- integrated from rho(j) to rho(j+1). c c inumchi=(# of chi intervals) c result(1:inumchi,1:inumrho) computed; c result(i,j) -- doubly integrated from chi(i) to chi(i+1), c rho(j) to rho(j+1) c c **caution** in axisymmetric case there is no variation with phi, c but a factor of 2pi still arises from the phi integration... c To control the boundary conditions on the temporary spline, use "eq_flxint_arr2s" For default boundary conditions (not-a-knot) use "eq_flxint_arr2".

Home | Top |

eq_flxint_arr2s

(old f77 xplasma 1 documentation) input: real*8 zdata(nchi,nrho) ! the integrand function data integer ibcrho0 ! rho(1) BC option real*8 zbcrho0(*) ! rho(1) BC data integer ibcrho1 ! rho(nrho) BC option real*8 zbcrho1(*) ! rho(nrho) BC data c c BC type values: for ibcrho0: c =0 -- use "not a knot", zbcrho0(...) ignored c =1 -- match slope, given at x(1),chi(ichi) by zbcrho0(ichi) c =2 -- match 2nd deriv., given at x(1),chi(ichi) by zbcrho0(ichi) c =3 -- boundary condition is slope=0 (df/dx=0) at x(1), all chi(j) c (zbcrho0(...) ignored). c and similarly for (ibcrho1,zbcrho1(...)). c c if zbcrho0,zbcrho1 are used, nchi points must be defined. integer iwant ! type of integration ! =1 -- surface integral of f*dchi*dphi ! =5 -- surface integral of f*det(Jacobian)*dchi*dphi ! =6 -- surface average: ! int(f*det(Jacobian)*dchi*dphi)/ ! int(det(Jacobian)*dchi*dphi) ! =2 -- zone integral of f*dchi*dphi*drho ! =3 -- volume integeral, f*det(Jacobian)*dchi*dphi*drho ! =4 -- volume average: vol. integral / delta_volume ! ** caution: dphi integration -> factor of 2pi integer inumchi,inumrho ! results dimensions ! *** see eq_flxint *** output: real*8 result(inumrho,inumchi) ! integration results integer ierr ! completion code, 0=OK .... call eq_flxint_arr2s(zdata, > ibcrho0,zbcrho0,ibcrho1,zbcrho1, > iwant,result,inumchi,inumrho,ierr)

Home | Top |

eq_flxint_arr2

(old f77 xplasma 1 documentation) input: real*8 zdata(nchi,nrho) ! the integrand function data integer iwant ! type of integration ! =1 -- surface integral of f*dchi*dphi ! =5 -- surface integral of f*det(Jacobian)*dchi*dphi ! =6 -- surface average: ! int(f*det(Jacobian)*dchi*dphi)/ ! int(det(Jacobian)*dchi*dphi) ! =2 -- zone integral of f*dchi*dphi*drho ! =3 -- volume integeral, f*det(Jacobian)*dchi*dphi*drho ! =4 -- volume average: vol. integral / delta_volume ! ** caution: dphi integration -> factor of 2pi integer inumchi,inumrho ! results dimensions ! *** see eq_flxint *** output: real*8 result(*) ! integration results integer ierr ! completion code, 0=OK .... call eq_flxint_arr2(zdata, > iwant,result,inumchi,inumrho,ierr)

Home | Top |

Example

(old f77 xplasma 1 documentation) (real codes should check the return status code ierr). ! set up rho integration zones call eq_flxint_init(0,nsurfs,rho_surfs,rho_min,ierr) ! (optional) set up chi integration zones call eq_flxint_chinit(0,nchbdys,chi_bdys,ierr) ! ! (re)fetch flux integration zone grid sizes ! call fluxav_nzones_get(nchi_zones,nrho_zones) ! compute standard metric integrals -- chi = 0 to 2pi ichizons=1 allocate(result(ichizons,nrho_zones)) iaccuracy=1 call eq_flxint('DVOL',iaccuracy,result,ichizons,nrho_zones,ierr) ... call eq_flxint('<1/R^2>',iaccuracy,result,ichizons,nrho_zones,ierr) ... call eq_flxint('<grad(rho)^2/R^2>',iaccuracy, & result,ichizons,nrho_zones,ierr) ! compute standard metric integrals -- discrete chi zones ichizons=nchi_zones allocate(result(ichizons,nrho_zones)) call eq_flxint('DVOL',iaccuracy,result,ichizons,nrho_zones,ierr) ! given an array f(1:nchi,1:nrho) on the (R,Z) original spline grid ! (NOT the integration grid)... compute various integrals iwant=1 ! surface integrals f*dphi*dchi nrho_surfs = nrho_zones+1 allocate(result(ichizons,nrho_surfs)) call eq_flxint_arr2(f,iwant,result,ichizons,nrho_surfs,ierr) iwant=2 ! zone integrals f*drho*dphi*dchi allocate(result(ichizons,nrho_zones)) call eq_flxint_arr2(f,iwant,result,ichizons,nrho_zones,ierr) iwant=3 ! volume integrals f*det(J)*drho*dphi*dchi allocate(result(ichizons,nrho_zones)) call eq_flxint_arr2(f,iwant,result,ichizons,nrho_zones,ierr) iwant=4 ! volume avgs (as iwant=3, div. by dVol) ! dVol = integral det(J)*drho*dphi*dchi allocate(result(ichizons,nrho_zones)) call eq_flxint_arr2(f,iwant,result,ichizons,nrho_zones,ierr) ! these calls create temporary spline fits. to control boundary ! conditions use eq_flxint_arr2s.

Home | Top |

Summary

(old f77 xplasma 1 documentation) eq_flxint_init, eq_flxint_chinit -- initialization eq_flxint -- canned integrations eq_flxint_arr2, eq_flxint_arr2s -- user defined integrations

Home | Top |

Miscellaneous

Home | Top |

limiter_contour_sequence

(old f77 xplasma 1 documentation) (eq_limcon) (Axisymmetric geometry only...) Regardless of the method chosen to represent the limiter, the routine "eq_limcon" can be used to return a piecewise linear contour representation of the limiter: ! input: integer imax ! max no. of points in contour returned ! output: integer inum ! actual no. of points in contour real*8 rlim(inum),zlim(inum) ! the contour itself ! input: real*8 dtol ! colinearity tolerance (R,Z units) ! output: integer ierr ! completion status code, 0=OK ... call eq_limcon(imax,inum,rlim,zlim,dtol,ierr) The contour returned is a closed finite sequence of (R,Z) points. Closed means rlim(1)=rlim(inum) & zlim(1)=zlim(inum). The colinearity tolerance "dtol" controls the deletion of extraneous contour points: If 3 consecutive points A,B,C are colinear to tolerance dtol, i.e. B is .le.dtol away from the segment AC, then, B is eliminated, reducing the size of the contour returned. Sample use of eq_limcon: create a limiter contour sequence suitable for writing into a G EQDSK file.

Home | Top |

psi_rho_grid_mapping

(old f77 xplasma 1 documentation) (eq_rhopsi, eq_rhopsin) -- these routines can be used to generate the sequence of "rho" values corresponding to a specified sequence of psi-poloidal values. "eq_rhopsin" will generate the sequence of rho values corresponding to an equispaced psi grid going from the magnetic axis to the plasma boundary; "eq_rhopsi" will find the sequence of rho values {rho[j]} satisfying psi(rho[j]) = psi[j] (j = 1 to npsi) for any given sequence of psi values {psi[j]}. To use these eq_rhopsin: integer npsi ! no. of pts in psi sequence (input) real*8 rhovals(npsi) ! corresponding rho values (output) integer ierr ! completion code, 0=OK (output) ... call eq_rhopsin(npsi,rhovals,ierr) ! rhovals(1:npsi) is the set of rho values which map ! to an equispaced psi grid ranging from the plasma ! magnetic axis to the plasma boundary ! the accuracy tolerance is ! 10*[machine epsilon]*[rho(bdy)] To use eq_rhopsi: npsi, rhovals, ierr as above, and... real*8 psivals(npsi) ! psi values for which rho values ! are sought... real*8 ztol ! accuracy tolerance (in rho) ! for the root finder ... call eq_rhopsi(npsi,psivals,rhovals,ztol,ierr)

Home | Top |

F77_MCgrid_Routines

(old f77 xplasma 1 documentation) XPLASMA supports a legacy 2d spatial grid mechanism that derives from TRANSP and NUBEAM: the "Monte Carlo" grid, or MCgrid. This is the spatial grid used for NUBEAM spatially 2d outputs, including the fast ion distribution function, fusion rate profiles, etc. This grid consists of radial zone rows each of which are partitioned into evenly spaced poloidal zones-- with the number of zones proportional to radius, i.e. fewer poloidal partitions at the center, more at the edge. This yields a grid where each zone has roughly equivalent volume and cross-sectional area, which is well suited to Monte Carlo uses, i.e. there are no "tiny" zones near the axis as would be the case with a regularly structured polar mesh. Such tiny zones would be hard to find by Monte Carlo parameter summation methods, leading to high statistical variance or noise in output. Using MCgrid avoids this. A typical MCgrid has 10 radial zone rows inside the plasma. For historical reasons, MCgrids also support a set of extrapolated zone rows mapping a region somewhat beyond the plasma boundary. A MCgrid supports the notion of updown symmetry, allowing a smaller grid to be used in the case of symmetric equilibrium. Although the interface has been coded to allow eventual generalization to 3d, actual use has been limited to axisymmetric geometries so far. The main parameters defining the grid are: iudsym -- =1 for updown symmetry =2 for updown asymmetry inznbmri -- no. of zone rows inside the plasma (typical value: 10) inth0 -- no. of theta zones in first (centermost) zone row spanning the range poloidal angle range [0,pi] (typical value: 2). The number of zones in the n'th zone rows is n*iudsym*inth0. The following chart illustrates the zone counts in the "typical" MCgrid -- this is the grid historically used for most NUBEAM calculations in TRANSP over the years. no. of poloidal zones per zone row updown symmetric updown asymmetric [0,pi] [-pi,pi] zone row 1 2 4 2 4 8 3 6 12 4 8 16 5 10 20 6 12 24 7 14 28 8 16 32 9 18 36 10 20 40 ----------------------------------------------------------plasma bdy 11 22 44 12 24 48 13 26 52 zones inside plasma: 110 220 total zones: 182 364 The radial zone rows are evenly spaced in the XPLASMA radial coordinate "rho".

Home | Top |

Definition

(old f77 xplasma 1 documentation) Input variables (traditional/suggested values in parentheses): integer :: inphi ! no. of phi zones -- toroidal variation (1) integer :: iudsym ! updown symmetry 1=yes 2=no (1 or 2) integer :: inth0 ! no. of poloidal zones subtending [0,pi] at axis (2) integer :: inznri ! no. of radial zone rows inside plasma (10) Output variables integer :: inznrx ! no. of radial zones including extrapolated region integer :: id_mcgrid ! XPLASMA id for MC grid just defined. call mcgrid_define(inphi,iudsym,inth0,inznri, & inznrx, id_mcgrid) If there is an error, id_mcgrid = 0 will be returned, and messages will be written on the i/o unit open for XPLASMA messages.

Home | Top |

Retrieve_basic_grid_info

(old f77 xplasma 1 documentation) Each of these routines retrieves information from the definition. In each case, the XPLASMA id "id_mcgrid" is input, and the grid description parameters are output. All arguments are integers. ! get symmetry information: call mcgrid_getsym(id_mcgrid,iudsym) ! iudsym=1 means updown symmetric; 2 means updown asymmetric. ! get number of zone rows: call mcgrid_getnumr(id_mcgrid,inznrx,inznri) ! inznrx -- *total* number of zone rows inside and outside plasma ! inznri -- number of zone rows inside plasma ! ** note order: inznrx then inznri ** ! get number of zone rows: call mcgrid_getnumz(id_mcgrid,inzonx,inzoni) ! inzonx -- *total* number of zones inside and outside plasma ! inzoni -- number of zones inside plasma ! ** note order: inzonx then inzoni ** ! get number of zones covering [0,pi] on axis; get no. of phi zones. call mcgrid_getnuma(id_mcgrid,inth0,inphi) ! inth0 -- no. of poloidal zones covering [0,pi] on axis ! inphi -- no. of phi zones (1 means axisymmetry). ! get array of numbers of poloidal zones per zone row integer, dimension(:), allocatable :: inthzns allocate inthzns(inznrx) call mcgrid_getnumzns(id_mcgrid,inthzns) ! for this it is also possible to use the simple formula ! inthzns(k)=iudsym*inth0*k

Home | Top |

Define_Data_over_MCgrid

(old f77 xplasma 1 documentation) These routines are used to create data objects defined over an existing MCgrid. For a scalar function use "mcgrid_putobj" (REAL*8 precision) or "mcgrid_putobj_r4" (REAL precision). There is also a call (used for specifying the beam distribution function) which allows a 2d array of data to be associated with each MCgrid zone. This is "mcgrid_putarr2" (REAL*8 precision) or "mcgrid_putarr2_r4" (REAL precision). The data is stored in XPLASMA in REAL*8 precision, regardless of which call is used. Specific functions are defined by names. Each defined MCgrid supports its own "name space". Example of use: the NUBEAM NTCC module uses these routines, to make fast ion distribution functions, and other 2d profiles, such as neutron emission rates, available externally. The REAL*8 routine is shown; the REAL interface is identical except for the floating point precision of zmks and zdata arguments. input: integer :: id_mcgrid ! MCgrid id character*(*) :: zname ! (unique) name to use for this function integer :: ist_th ! theta grid start point indicator: ! =0: grid starts at theta=0; ! =-1: grid starts at -pi integer :: ist_ph ! phi grid start point indicator (for ! axisymmetric case choose either value): ! =0: grid starts at theta=0; ! =-1: grid starts at -pi integer :: iextend ! flag if data is defined beyond plasma boundary integer :: idim ! zdata array dimension real*8 :: zmks ! multiply data by this to put it in MKS units real*8 :: zdata(idim) ! the data to be stored in XPLASMA. output: integer :: ierr ! status code 0=normal call mcgrid_putobj(id_mcgrid, zname, ist_th, ist_ph, iextend, & zmks, zdata, idim, ierr) For the distribution function definition, the above arguments are extended to define the 3 array dimensions of the input data-- size of array, and the subset of numbers actually used: integer :: idim1,idim2,idim3 ! array dimensions ! zdata(idim1,idim2,idim3) integer :: in1,in2 ! data used: zdata(1:in1,1:in2,:) call mcgrid_putarr2(id_mcgrid, zname, ist_th, ist_ph, iextend, & zmks, zdata, in1, in2, idim1, idim2, idim3, & ierr)

Home | Top |

Fetch_Data_over_MCgrid

(old f77 xplasma 1 documentation) These routines are used to fetch data objects that have been defined over an existing MCgrid. For a scalar function use "mcrid_getobj" (REAL*8 precision) or "mcgrid_getobj_r4" (REAL precision). The precision is that desired by the caller; XPLASMA internal storage is always REAL*8. There is also a call (used for fetching the beam distribution function) which allows a 2d array of data to be associated with each MCgrid zone. This is "mcgrid_getarr2" (REAL*8 precision) or "mcgrid_getarr2_r4" (REAL precision). Again, the precision is that desired by the caller. Specific functions are defined by names. Each defined MCgrid supports its own "name space". Example of use: the TRANSP code retrieves spatially 2d NUBEAM module outputs, including fast ion distribution function data, using these calls. The REAL*8 routine is shown; the REAL interface is identical except for the floating point precision of zmks and zdata arguments. input: integer :: id_mcgrid ! MCgrid id character*(*) :: zname ! (unique) name to use for this function integer :: ist_th ! caller's theta grid start point indicator: ! =0: grid starts at theta=0; ! =-1: grid starts at -pi integer :: ist_ph ! caller's phi grid start point indicator (for ! axisymmetric case choose either value): ! =0: grid starts at theta=0; ! =-1: grid starts at -pi integer :: idim ! zdata array dimension real*8 :: zconv ! multiply data by this to put it into the ! physical units desired by caller. The data ! as stored is in MKS/KeV in XPLASMA. output: real*8 :: zdata(idim) ! the data to be returned XPLASMA. integer :: ierr ! status code 0=normal call mcgrid_getobj([-]id_mcgrid, zname, ist_th, ist_ph, & zconv, zdata, idim, ierr) For the distribution function definition, the above arguments are extended to define the 3 array dimensions of the input data-- size of array, and the subset of numbers actually used: integer :: idim1,idim2,idim3 ! array dimensions ! zdata(idim1,idim2,idim3) input/output: subset of dimensioned array space actually in use. If in1>0 on input, the actual space used must match this value. If in1<= 0, the actual space usage will be returned; similarly for in2. integer :: in1,in2 ! data used: zdata(1:in1,1:in2,:) call mcgrid_getarr2([-]id_mcgrid, zname, ist_th, ist_ph, iextend, & zmks, zdata, idim1, idim2, idim3, in1, in2, & ierr) Notes: 1. if the MCgrid is updown symmetric, only data covering the range [0,pi] or [-pi,0] are copied, depending on the setting of ist_th. I.e. the order of the poloidal indexing is reversed, within each zone row. 2. if the non-existance of a function should not be treated as an error, and the output data should be set to zero in this case, pass -id_mcgrid instead of id_mcgrid as the first argument. 3. errors are flagged in case of argument values out of range, or if array dimensions are too small to hold the available data. Messages are written to the XPLASMA messages i/o unit.

Home | Top |

Zone_Volumes

(old f77 xplasma 1 documentation) When an MCgrid is defined, a scalar function "ZONE_VOLUME" is automatically defined along with it, giving the volume of each zone in m**3. This data can be fetched by the call call mcgrid_getobj([-]id_mcgrid, 'ZONE_VOLUME', ist_th, ist_ph, & zconv, zdata, idim, ierr) where the arguments are as described in the preceding section.

Home | Top |

More_on_indexing

(old f77 xplasma 1 documentation) The mapping [(rho,theta) -> zone index] will depend on whether or not the geometry is updown symmetric, and, e.g. in the case of updown asymmetry, on whether the user's poloidal angle grid spans [-pi,pi] or [0,2pi]. It will also depend on whether the user's code makes use of the extrapolated zone rows or not. Here is some sample code which could be adapted or optimized for a particular situation. integer function izmap(id_mcgrid,rho,theta) ! MCgrid zone map, with assumptions: ! 1. axisymmetry ! 2. ignore zones outside plasma ! 3. updown symmetric theta range: [0,pi] ! 4. updown asymmetric theta range: [-pi,pi] integer, intent(in) :: id_mcgrid ! grid id (axisymmetry assumed) real*8, intent(in) :: rho,theta ! (rho,theta in) !------------------------------------ ! info on zone rows logical, save :: init = .FALSE. integer, dimension(:), allocatable, save :: izns,iztot integer, save :: inznr,inznri,iudsym,inth0 integer, save :: id_mcgrid_int = 0 !------------------------------------ integer i,izr,inth,ith,idum real*8 ztheta real*8, parameter :: cpi = 3.1415926535897931D+00 real*8, parameter :: c2pi = 6.2831853071795862D+00 ! check if id matches the one stored; if not, re-initialize... if(id_mcgrid.ne.id_mcgrid_int) init = .FALSE. if(.not.init) then ! ** initialize ** ! get no. of zones per row; add up cumulative number call mcgrid_getnumr(id_mcgrid,inznr,inznri) if(inznr.eq.0) then izmap=0 ! invalid MCgrid, evidently. return endif call mcgrid_getsym(id_mcgrid,iudsym) allocate(izns(inznr),iztot(0:inznr)) call mcgrid_getnumzns(id_mcgrid,izns) iztot(0)=0 do i=1,inznr iztot(i)=iztot(i-1)+izns(i) enddo init = .TRUE. endif izr = 1 + rho*inznri ! zone row index -- inznri are inside bdy izr = max(1,min(inznri,izr)) ! forced inside plasma inth = izns(izr) ! no. of poloidal zones, this row ztheta = theta ! force theta in range [-pi,pi do while ( ztheta < -cpi ) ztheta = ztheta + c2pi enddo do while ( ztheta > cpi ) ztheta = ztheta - c2pi enddo if(iudsym.eq.1) then ztheta = abs(ztheta) ! updown symmetry: map to upper half-plane ith=1 + ztheta*inth/cpi ith = max(1,min(inth,ith)) else ith=1 + (ztheta+cpi)*inth/c2pi ith = max(1,min(inth,ith)) endif izmap = iztot(izr-1)+ith end function izmap This sort of routine could also be generalized for piecewise linear interpolation of functions defined over an MCgrid, but, higher-order interpolation methods probably require mapping to a regular polar mesh, and, care would have to be taken at the axis, boundary, and poloidal angle branch cut.

Home | Top |

Support_Routines_&_Programs

Home | Top |

Visualization_Routine

The current contents of the xplasma module can be visualized via the command line / menu driven interactive fortran subroutine: (fortran-95): call xplasma_debug_access(s) type (xplasma), pointer :: s (fortran-77): call eqdbg_plot which use the NTCC modules SGLIB, UREADSUB, and TRGRAF.

Home | Top |

Save_and_Restore_Routines

The current contents of the xplasma module can be written to a netcdf file: character*(*) filename ! name of file to write integer ierr ! completion code, 0=OK [the filename must be set...] (fortran-95): call xplasma_write(s,filename,ierr) type (xplasma), pointer :: s (fortran-77): call eq_save(filename,ierr) ! ierr should be checked A file previously written by `eq_save' can be read back in using character*(*) filename ! name of file to write integer ierr ! completion code, 0=OK [the filename must be set...] (fortran-95): call xplasma_read(s,filename,ierr) type (xplasma), pointer :: s (fortran-77): call eq_restore(filename,ierr) ! ierr should be checked these routines use the NTCC module EZCDF.

Home | Top |

miscellaneous_f77

Home | Top |

LUN_for_messages

(old f77 xplasma 1 documentation) The f77 xplasma interface writes messages to a fortran i/o unit (logical unit number or LUN). To fetch the fortran logical unit number currently used for messages: integer ilun ! l.u.n. (Returned) call eq_get_lunerr(ilun)

Home | Top |

Spline_fit_order_RZ

(old f77 xplasma 1 documentation) To fetch the order of R(rho,chi), Z(rho,chi) and component B(rho,chi) spline fits, use integer iorder ! fit order call eq_rzordr_get(iorder) where the value returned is 1 for Hermite, 2 for spline.

Home | Top |

eq_GEQDSK

(old f77 xplasma 1 documentation) This routine will write a GEQDSK (EFIT-style) ascii file, with format as per the notes of Lang Lao (General Atomic), Februrary 2000. Psi(R,Z) and B(R,Z) must be defined. "q" and "P" profiles must also be provided. The calling routine is responsible for naming and opening the file and providing a logical unit number on which the file may be written. Input arguments: integer lun_geqdsk ! logical unit number of open file character*48 geqdsk_lbl ! label string, written into file. The following define the limits of evenly spaced (R,Z) grids over which psi(R,Z) will be written. These limits must cover the core plasma but not exceed the extent of the (R,Z) grids defined in the xplasma module. real*8 Rmin,Rmax ! R extrema real*8 Zmin,Zmax ! Z extrema The total toroidal plasma current (amps) must be specified real*8 zcur ! plasma current, amps Xplasma id codes for the pressure and q profiles: integer id_p ! xplasma id: Pressure profile integer id_q ! xplasma id: q profile The following integers specify the resolution of the grids integer nh ! no. of horizontal (R) grid points. ! also the no. of flux grid points. integer nv ! no. of vertical (Z) grid points. integer nb ! no. of points in plasma bdy contour ! also, upper limit on limiter contour. Output: integer ierr ! completion code, 0=OK ... call eq_geqdsk(lun_geqdsk,geqdsk_lbl, > Rmin,Rmax, Zmin,Zmax, zcur, > id_p, id_q, nh, nv, nb, > ierr) The GEQDSK file will contain: Psi(R,Z) on evenly spaced (R,Z) grid covering [Rmin,Rmax]x[Zmin,Zmax] and on an evenly spaced psi grid mapping from the plasma mag. axis out the plasma boundary, f(psi) = R*Bt f*f' P(psi) P' q where the "'" denotes d/dpsi. ..... The caller should check the error code; if it is non-zero, the open file on lun_geqdsk should be deleted (i.e. close(lun_geqdsk,status='delete')).

Home | Top |

plot_xplasma

Given a file written by a prior call to eq_save (see the neighbouring topic Save_and_Restore_Routines), this program can be used to examine and visualize the contents. The program employs a simple command line menu driven interface and vector graphics, using the NTCC modules SGLIB, UREADSUB, and TRGRAF. The program can be run in an xterm emulator window (must be a real xterm, some clones like aixterm will not work). The environment variable TERMINAL_TYPE must be set to XTERM. The environment variable PLOT should usually be undefined. To run the program, simply type its name and give the name of the netcdf file previously written by the xplasma eq_save subroutine. This program works with F95 xplasma as well.

Home | Top |

test_xplasma

This is a test program for the xplasma NTCC module. It's data source is an ascii file derived from TRANSP data. (A general tool for building an xplasma from TRANSP MDS+ or file data is available in the NTCC module "trxplib"). The test_xplasma program comes with a controlling script, script.ind so that > test_xplasma @script will produce a canned sequence of plots. This is the same set of plots as are stored in "script_output.ps", which comes with the xplasma distribution. Details on building the software and running test_xplasma are in the module's README file. This program has been upgraded to F95 xplasma.

Home | Top |

geqxpl

this is a 2nd test program for the xplasma NTCC module. This program demonstrates construction of an xplasma from EFIT output, a G-EQDSK file. The program comes with a controlling script, nstx_geqxpl.ind, so that > geqxpl @nstx_geqdsk will produce a canned sequence of plots. This is the same set of plots as are stored in "geqxpl_output.ps", which comes with the xplasma distribution. Details on building the software and running test_xplasma are in the module's README file. This program works with F95 xplasma.

Home | Top |

About this document

This Document was created byhlptohtml