The mcx matrix calculator
mcx is a stack-based matrix calculator. Two-dimensional matrices are read from disk files (or generated by other constructs) and pushed onto a stack. Unary operations (such as inversion or scaling by a constant) manipulate the top array on the stack. Binary operations (such as addition) operate on the top two elements on the stack.
mcx does not manipulate symbolic matrices, but will in many places convert expressions from user-defined and other internally generated variables, such as the number of rows or columns of an array.
See Instruction Summary for a listing of all mcx instructions.
Table of Contents
- Table of Contents
- Preliminaries
- 1. Introduction
- 2. Examples
- Example 2.1. Add mat1 to mat2
- Example 2.2 Standard input and standard output
- Example 2.3 Manipulations of eigenvalues and eigenvectors of an array
- Example 2.4 Numerical integration, differentiation, and interpolation of a function
- Example 2.5 Convert a k-point given in Cartesian coordinates to multiples of the reciprocal lattice vectors
- Example 2.6 Rotation matrices
- 3. mcx manual
- Repeated Iteration of Command Line Arguments
- Instruction summary
- Other resources
Preliminaries
The calculator manipulates array elements on the stack. The most recent, or top-level array is called s0; arrays deeper in the stack are called s1, s2, ….
Arrays are normally read from disk files, which have the standard Questaal format, and a few other formats. Data parsed in files makes use of the programming language capabilities of the preprocessor.
mcx is required and is assumed to be in your path. This manual is written for version 1.062. To see what version you are using, do:
$ mcx --version
See Instruction Summary.
1. Introduction
mcx is a matrix extension of an ordinary calculator. It is mainly designed to work with 2D arrays; it operates on numerical arrays. It is command-line driven and can efficiently manipulate arrays for analysis. Some Questaal testing scripts make use of it to analyze whether a test passes a certain criterion.
Usually arrays are read from disk files in ASCII format, though mcx can read binary files, and has limited ability to create arrays from command-line arguments (see for example the –array and -1 constructs). mcx is stack-based: each time you read an array from a file (or create a new array by some other means) it is pushed onto the stack. Arrays are called s0, s1, s2, ….
You read an array from disk by naming the file in a command-line argument, e.g. mcx h
attempts to read an array from file h. The contents are parsed and if the reading is successful, pushed on the stack, becoming array s0. The old s0 becomes s1, the old s1 becomes s2, etc. The ASCII format of the file is quite flexible; you can specify the number of rows nr and number of columns nc in a number of ways:
You can specify the number of columns on the command line, with −nc=#; similarly with the number of rows (−nr=#). −nc=#; this switch is used in Example 2.2.
You can include a directive at the start of the file, before any data is read. mcx passes the input through a file preprocessor first; in addition a directive specifying some combination nr and nc, e.g.
% rows #1 cols #2
supplies the needed information to mcx.
In the absence of an explicit specification, mcx will infer nc by counting how many numbers (more generally expressions) are on the first line.
If nc is obtained somehow but not nr, mcx determines it by counting the number of expressions in the entire file and dividing by nc.
Note: : if the −nc=# or −nr=# switches are not used, mcx determines them from the standard Questaal algorithm for reading 2D arrays, described in more detail here.
1.1 Named arrays
You can copy s0 to a permanent array with a name. It remains fixed as the stack varies. To push it onto the stack, refer to by using the array name a command-line argument. If the name is found among the list of permanent arrays, it will push the internally named array onto the stack, rather than try to read a file of that name.
For example suppose files h and s contain arrays. The command
mcx h -a h s -a s s h -show
does the following:
- Loads the contents of file h onto the stack. It becomes s0.
- Copies s0 to an internal array named h and pops s0 off the stack.
- Loads the contents of file s onto the stack. It becomes s0.
- Copies s0 to an internal array named s and pops it off the stack.
- Pushes the contents of internal array s onto the stack.
- Pushes the contents of internal array h onto the stack.
- Lists permanent and stack arrays (there are two of each), and their attributes.
See Instruction Summary.
2. Examples
This section develops a few examples to provide an intuitive feel for how mcx works and to illustrate some features.
A systematic description of mcx’s features and arguments is given in Section 3.
Cut and paste the following data into array into file mat1
1.1 2.2
3.3 4.4
and this data into file mat2.
5 6
7 8
Example 2.1. Add mat1 to mat2
If you do the following:
mcx mat1 mat2 -+
you should see
% rows 2 cols 2 real
6.100000 8.200000
10.300000 12.400000
Any argument that begins with “−“ is a switch or an operator (as distinct from data). The string following “−“ names the operator.
Thus:
mat1 : reads file mat1 from disk and pushes it onto the stack; call it s0.
mat2 : reads file mat2 and pushes it onto the stack so s0 → s1 and the contents of mat2 → s0.
−+ : is the binary operation “add.” If s0 and s1 exist, they are summed and popped off the stack. Their sum is pushed onto top-level array s0.
Note: if operations occur before arrays are given, they are push on an operations stack and execute when arrays become available. The following commands accomplish the same thing
$ mcx -+ mat1 mat2
$ mcx mat1 -+ mat2
$ mcx mat1 mat2 -+
Use −show to see the stack. Try this
mcx -f2f8.1 mat1 mat2 -show -+
`
You should get
# 0 named arrays, 2 on stack; pending 0 unops 0 bops (vsn 1.057)
# stack nr nc cast
# 2 2 2 real
# 1 2 2 real
% rows 2 cols 2 real
6.1 8.2
10.3 12.4
−show prints out what arrays are in the calculator; the addition is subsequently performed and the result printed.
“−f…“ is a formatting statement; 2f8.1 follows the fortran convention for formatting real numbers.
Example 2.2 Standard input and standard output
After all the command-line arguments are parsed, usually mcx prints the top-level array s0, and exits silently.
However,
If s0 is not present, mcx waits for you to enter an array from standard input.
For example try$ mcx -f2f8.1 $ 1 2 $ 3 $ 4 <ctrl-D>
mcx should print out
% rows 2 cols 2 real 1.0 2.0 3.0 4.0
If the last command is −show, mcx just prints out information about named arrays and the stack and exits (even if the stack has no arrays). Thus the command
mcx -f2f8.1 mat1 mat2 -show -+ -show
does the same as it did in Example 2.1 but prints out stack contents a second time, instead of printing s0.
You can also tell mcx to read the next array from standard input by using a full stop (“ . “) in lieu of file name. Thus
echo 1 -2 3 -4 | mcx .
pushes a 1×4 array onto s0, while
echo 1 -2 3 -4 | mcx -nc=2 . mat2 -+
pushes a 2×2 array onto s0, then pushes mat2, and adds the two so that a single array remains on the stack. −nc=2 tells mcx to treat the line from stdin as an array with 2 columns.
Example 2.3 Manipulations of eigenvalues and eigenvectors of an array
This example finds the eigenvalues e and eigenvectors z of mat2, and shows that mat2 z = z e.
First try
mcx mat2 -evl
You should see a 2×1 complex array
% rows 2 cols 1 complex
-0.152067
13.152067
0.000000
0.000000
The eigenvalues are complex because the matrix is not hermitian. The imaginary part follows the real part; this is how mcx displays and reads complex arrays in ASCII format.
You can force mat2 to be hermitian (symmetric since mat2 is real) with −herm. Now do
mcx mat2 -herm -a h h -evl h -evc -ap z -tog -v2dia -x h z -x --
These instructions do the following:
mat2 : reads file mat2 and pushes it onto s0.
−herm : symmetrizes s0.
−a h : copies s0 to a named array h and pops it from the stack. The stack is now empty.
h −evl : pushes h onto s0 and replaces s0 with its eigenvalues. Because h is hermitian, s0 is real.
h −evc : pushes h onto the stack and replaces s0 with its eigenvectors. Now the stack has two arrays, s0 = z and s1 = e.
−ap z : copies s0 to a named array z.
−tog : toggles s0 and s1, making s1 = z and s0 = e.
−v2dia : Turns s0 (a vector or 2×1 array of eigenvalues) into a diagonal 2×2 array.
−x : multiplies s1 × s0. One array remains on the stack, s0 = z × e.
h z −x : pushes h and z onto the stack and multiplies them. Now s0 = h × z, while s1 = z × e
−− : Adds s1 to −s0. s1 and s1 are mathematically identical so the difference should be zero.
Note: this formula should still work even if h is not hermitian.
Example 2.4 Numerical integration, differentiation, and interpolation of a function
Integrate and differentiate the function , by tabulating it on a mesh and evaluating integrals and derivatives numerically. This example also uses the tabulated data to interpolate it to another mesh.
Copy the contents of the box below into file dat.
% const n=100 p=1 lam=2
% save
% macro iy(z) exp(-lam*z)*(-lam*z-1)/lam^2
% repeat i= 0:n
% var x=10*i/n
{x} {x^p*exp(-lam*x)}
% end
This creates 101 rows of xy pairs with x ranging between 0 and 10.
Note: : The number of points n+1, and also p and λ are declared in the file with the const preprocessor directive. You can override the values assigned there with command-line arguments, e.g. −vp=#. The save directive retains the variables declared in this file after it is read. The macro directive will be used for the indefinite integral, below.
Note: : A macro can also be specified on the command line, e.g. ‘-miy(z)=exp(-lamz)(-lam*z-1)/lam^2’
Derivative
The derivative is readily found to be
Try some of the following commands
$ mcx -vp=2 dat -diff
$ mcx -vp=2 dat -diff -e3 x1 x2 'x1^(p-1)*(p-lam*x1)*exp(-lam*x1)'
$ mcx -vp=2 -f3f15.10 dat -diff:nord=5 -e3 x1 x2 'x1^(p-1)*(p-lam*x1)*exp(-lam*x1)' -e3 x1 x2 x2-x3
All of them differentiate the second column with respect to the first, using p=2.
- The first returns two columns with x and y′.
- The second returns three columns with x, y′, and the analytic derivative of y′.
- The third returns three columns (more decimals) with x, y′, and the error in the numerical estimate for y′.
Unpacking the third command:
Argument | Function |
−vp=2 | Declares variable p and assigns the value 2. This overrides the assignment in dat. |
−f3f15.10 | Formats output (fortran format 3f15.10) |
dat | read s0 from dat. |
−diff:nord=5 | Replace column 2 with a numerical estimate for y′ Use a 5-point polynomial to interpolate the data; estimate is derivative of polynomial interpolation |
−e3 x1 x2 ‘x1^(p−1)*(p−lam*x1)*exp(−lam*x1)’ | replace s0 with a three column array consisting of x, y′, and the analytic derivative of y′ |
−e3 x1 x2 x2−x3 | replace s0 with a three column array consisting of x, y′, and difference between the numerical and analytical y′ |
Some observations:
- The largest error appears for x→0. The interpolation is less accurate when all the data lies on one side of the interpolating point.
- The error improves when higher order polynomials (nord=#) are used, or when the mesh is made finer (−vn=#).
- If you use p<1, y′ diverges at the origin. The numerical derivative cannot reproduce this.
Integral
y is small at x=10 if λ=−2, provided p is 3 or less; so we will use 10 in place of ∞.
Try some of the following commands
$ mcx -vp=1 dat -int 0 10
$ mcx -vp=2 dat -int 0 10
$ mcx -vp=3 dat -int 0 10
These commands calculate I between 0 and 10 for three values of p.
You should find that I is close to , i.e. 1/4, 1/4, and 3/8 for p=1,2,3. Some numerical errors appear in the 6th digit. The integral is carried out by fitting the data to a polynomial of order nord−1, and integrating the polynomial. You can reduce the error by using a higher order than the default value of 4 for nord, viz
$ mcx -vp=3 dat -int:nord=6 0 10
Also for p>3 you should increase the upper bound beyond 10 since the integral from 10 to ∞ is on the order of 10−6.
Indefinite Integral
As noted I must be evaluated between definite limits. However, you can make mcx simulate an indefinite integral by integrating over a range of upper bounds.
To compare with exact results, note that when p=1 the indefinite integral is
The macro in dat evaluates this integral.
Try the following:
$ mcx dat -int 0 0:2:.2 -e3 x1 x2 'iy(x1)-iy(0)'
This evaluates I for a lower bound of 0 and a uniform mesh of points for the upper bound between 0 and 2. In the third column the analytic integral is evaluated from the macro iy at the upper and lower bounds.
You should that the numerical and analytic integrals agree to about 6 decimal places:
% rows 11 cols 3 real
0.000000 0.000000 0.000000
0.200000 0.015387 0.015388
0.400000 0.047801 0.047802
0.600000 0.084343 0.084343
0.800000 0.118767 0.118767
1.000000 0.148498 0.148499
1.200000 0.172890 0.172890
1.400000 0.192230 0.192230
1.600000 0.207200 0.207200
1.800000 0.218578 0.218578
2.000000 0.227105 0.227105
Alternatively, you specify macro on the command line and omit it from the dat file
$ mcx '-miy(z)=exp(-lam*z)*(-lam*z-1)/lam^2' dat -int 0 0:2:.2 -e3 x1 x2 'iy(x1)-iy(0)'
Interpolation
Interpolation proceeds much in the same was as integration; only interpolation has lower bound. Try
$ mcx -vp=2 dat -intrp .5:1:.05 -e3 x1 x2 'x1^p*exp(-lam*x1)' -e3 x1 x2 x2-x3
This returns the abscissa on a mesh twice finer than the original mesh. Every odd point is perfectly interpolated (they lie on the original mesh); the even points reflect the error of the interpolation.
See Instruction Summary.
Example 2.5 Convert a k-point given in Cartesian coordinates to multiples of the reciprocal lattice vectors
Often it is necessary to convert a k point given in Cartesian coordinates a vector expressed as multiples of the reciprocal lattice vectors, or vice-versa. This example provides a simple recipe for the conversion using mcx.
The valence band maximum of an insulator was found to occur at q=(0.702085,0.711920,0.231304) in Cartesian coordinates, in units of 2π/a, where a is the lattice constant.
The real and reciprocal space lattice vectors are
Plat Qlat
1.070990 0.000000 -0.685190 0.933715 0.000000 0.000000
0.000000 1.000000 0.000000 0.000000 1.000000 0.000000
0.000000 0.000000 1.189949 0.537647 0.000000 0.840372
Let and be the same point expressed as multiples of Cartesian vectors (, , ) and reciprocal lattice vectors Q. In the snippet above (taken from lmf standard output) row i corresponds to the ith lattice vector Pi or Qi. Thus element in the 3×3 matrix shown for Q corresponds to Cartesian component j of Qi. Call this ; note that it is the transpose of the matrix in the snippet. Note also, according to standard definitions, .
By definition,
Writing as a row vector ,
To obtain using mcx, invoke
mcx '-array[3,3]' 1.070990,0,-0.685190,0,1,0,0,0,1.189949 -a plat '-array[1,3]' 0.702085,0.711920,0.231304 plat -x
It should yield 0.593439 0.711920 0.275240
.
Example 2.6 Rotation matrices
mcx can generate rotation matrices, for example:
mcx -rot='(0,0,1)pi/2'
generates the following 3×3 matrix:
0.000000 1.000000 0.000000
-1.000000 0.000000 0.000000
0.000000 0.000000 1.000000
Operating on a column vector, it maps into , into , and into itself.
Thus rotations are defined in the following sense: for a right-handed coordinate system (meaning positive rotation around is counterclockwise) You can think of it either :
- An “intrinsic” or “passive” convention where the coordinate system is rotated instead of space, in the opposite direction. In the above example, the coordinate system rotates clockwise for positive angle π/2.
- An “extrinsic” or “active” convention where space rotated. In the above example, are rotated counterclockwise to .
-rot
can accept a sequence of rotations. For example, Euler angles are a specification of three rotations: first about by , then about the new by , finally about the new by . To generate the rotation matrix for Euler angles , , , do:
mcx -rot='(0,0,1)pi/4,(0,1,0)pi/3,(0,0,1)pi/2 or
mcx -rot=z:pi/4,y:pi/3,z:pi/2
To confirm that this operation is a compound of the three rotations, make them separately and multiply them out:
mcx -rot='z:pi/4' -a r1 -rot='y:pi/3' -a r2 -rot='z:pi/2' -a r3 r3 r2 r1 -x -x
mcx can also generate the rotation matrix rotating real harmonics to spherical harmonics and vice-versa.
mcx -f18f12.6 -ylm~r2s~l=2
It can also rotate from real or spherical harmonics to the relativistic basis by quantum numbers , (or , ).
mcx -f18f12.6 -ylm~r2kmu~l=2
3. mcx manual
mcx is a stack-based, command-line driven calculator for matrices. Matrices reside on the stack, ordered as s0, s1, … . There are unary operators that operate on the top-level element s0, replacing it with some transformation, and binary operators that operate on s1 and s0 replacing both of them with the result of some operation, e.g. s1 × s0.
Usage:
mcx [−switches] data-file -ops …
Arguments that do not begin with “−“ or ”[“ must be files, stored in the form of a 2D array. For ASCII files, data is read using the standard Questaal format which features programming language capabilities.
Any argument that begins with “−“ is a switch, a unary operator, or a binary operator.
Any argument that begins with ”[“ is a declaration of a command-line looping construct where command arguments between ”[“ and ”]” are iterated over, as described below.
When a file is read, its contents (together with the number of rows nr and columns nc) is pushed onto the stack and becomes the top-level stack element s0. Elements already existing on the stack get pushed down one level. If there are n such elements, si-1 → si for i = n, n−1, …, and the new element becomes s0.
Data is normally read from a file; however if data-file is a full stop (“ . ”), data is read from standard input in lieu of a file. (It can occur only once). See Example 2.2.
Switches
These are switches that modify variables and describe or control formatting of data files that are read and written.
- −nc=# (nr=#)
Stipulate that next matrix read has # columns (rows). See Example 2.2 for an illustration. - −vvar=#
create variable var if it does not already exist, and assign value to #. This is the standard way Questaal programs assign variables from the command line. Since data files are parsed by the preprocessor, such variables may enter into preprocessor directives or as part of expressions in the data itself. - −show
show data stack and any operations pending. See Example 2.1. - −mmymacro</FONT>(arg1,arg2,...)=expr</FONT></i>(arg1,arg2,...)\\ Creates a macro that is parsed in the same way as explained in the documentation for [macro preprocessor directives](/docs/input/preprocessor/#macro-directive). (You can also include macros as preprocessor directives in data files, as was done in [Example 2.4](#example-24--numerical-integration-differentiation-and-interpolation-of-a-function).\\ _Example:_{: style="color: coral"} macro max takes the maximum value of two numbers: `'-mmax(x1,x2)=x1>x2?x1:x2'` .
- −w[:switches] fname | −bw[:switches] fname
write s0 to file fname.
−bw writes to a binary file.
Optional switches are separated by whatever character follows −w (assumed to be ’:’ here).- :l=label include a label in the header
- :nohead Suppress writing the header line
- −wap
(complex arrays only) write s0 as (amplitude,phase) rather than (Re, Im). - −a[nr=#|:nc=#] nam | −ap nam
assign s0 to nam, and pop s0 off the stack. −ap nam performs the assignment but does not pop s0 off the stack. - −av[ir,ic] var
assigns scalar variable var to element from s0(ir,ic). If ir and ic are specified, the (1,1) element is used. −r:tags
tags are separated by whatever character follows −r (assumed to be ’:’ here). Tags are::qr read with fortran read (fast, no algebra) :s=# skips # records before reading :open leaves file open after reading; thus if you read the file again it will read the next array :br[nr,nc] read from binary file. If not specified read nr and nc from first record. :h5~switches read a dataset from a file in hdf5 format, which must be an array of n dimensions. One or two of the n are selected out.
Switches are separated by the character after h5 (assumed to be ’~’ here).
The following switches are required:
~id=name dataset name. Number of columns and dimension for each are read from the file.
~c=#1,#2,… read #1,#2,… elements from columns 1,2,… of the dataset. # unspecifed or 0 ⇒ file dimension. Only 2 elements may exceed 1.
The following switches are optional:
~check print properties of dataset, without reading contents
~i indicate that the dataset consists of an integer array
~z indicate that the dataset consists of a complex array
~o=#1,#2,… offsets to columns 1,2,… of the dataset. Unspecified elements default to 0
~s=#1,#2,… (stride) spacing between elements in columns 1,2,… of the dataset. Unspecified elements default to 1
Example: print elements (1:20,68,1:2,20) of dataset cphi in files cphi.h5. cphi is a complex array dimensioned (205,72,2,22).
Note offsets start at 0 and the use of 0 in ~c=.
mcx -r:h5~z~id=cphi~o=0,67,0,19~c=20,1,0,1 cphi.h5:spc load in sparse format - −px[:nprec]
write in row (column) compressed storage format, displaying only elements larger than a tolerance By default the tolerance is 10−8. If nprec is supplied, the tolerance is 10−nprec. - −pxc
Not documented.
See Instruction Summary.
Unary operators
These operators act on the top level matrix, s0, and replace it with the result of the unop.
Where expr appears in the switches below, algebraic variables declared from directives may be used; also you can use xn for the contents of the nth column.
- −p:
Pushes top array s0 onto stack, duplicating it. - −p+n (-p-n):
Pushes nth array (from bottom) onto stack - −pop:
Pops s0 from stack, shifting the other elements up one level. - −popu:
Pop a unary operator from the stack, if present - −popb:
Pop a binary operator from the stack, if present - −csum[:list]
Sums the columns of s0, replacing it with a matrix of one column. - −rsum[:list]
Sums the rows of s0, replacing it with a matrix of one row. - −s#:
Scale s0 by # (may use -s#real,#imag) - −shft=#:
Adds a constant # to s0 - −sort expr
Sorts rows s0, ordering them by the result of expr - −i | − iq:
Inverts s0 - −1:n
Pushes unit matrix, dimension n, onto stack - −evl | −evc
Replaces s0 by its eigenvalues (eigenvectors) - −t:
Transposes s0 - −cc:
Take complex conjugate of s0 - −herm: Replaces s0 with its hermitian part
- −real:
Replaces s0 with its real part - −v2dia:
If s0 is a vector, it is expanded into diagonal matrix.
If s0 is a square matrix, its diagonal elements are used to form a vector. - −split nam row-markers column-markers
Splits s0 into subblocks. row-markers and column-markers. Both markers consist of standard Questaal integer lists, and delineate the first row (column) of a subblock, and also implicitly delineate the last row (column) of the prior subblock. Thus 1,6,20 comprises two subblocks, the first with range [1,5], the other with range [6,19].
For each i and j, where i and j are the ith and jth subblock, a permanent array called namij will be created. Thus -split creates n1×n2 new named arrays, with n1 and n2 being the number of row and column subblocks.
Example: suppose myfile contains 27 rows and 4 columns. Then
mcx myfile -sub 1,27,1,4 -split x 1:nr+1:9 1,2,nc+1 -show
creates 6 new arrays named x11, x12, x21, x22, x31, x32. All have 9 rows; x11, x21, x31 have one column while x12, x22, x32 have three columns.
Note 1: You can use nr and nc to refer the number of rows and columns, respectively.
Note 2: You can use . in lieu of an integer list for either row-markers or column-markers. It is equivalent to the list 1,nr+1 for the rows and 1,nc+1 for the columns. - −rep:n1,n2
Concatenates replicas of s0 to create (nr×n1,nc×n2) array. - −roll:#1[,#2]
Cyclically shifts rows (and columns, respectively) by #1 (and #2) elements. - −pwr=#:
Raises (col-1) matrix to a power - −wl expr
For each row in the top-level array, evaluate expr and return 1 if nonzero, or 0 if zero. If nr is the number of rows, nr numbers will be returned in a single column.
Example:
mcx '-array[4,2]' -6.2625636,-6.2605747,-6.2625635,-6.2605746,1,2,1,3 -t -wl 'abs(x1-x3)+abs(x2-x4)>1d-6'
returns two lines : 0 in the first line and 1 on the second. - −tp [nc~]list
Generates matrix from list. Elements in list is a sequence of real numbers, in the form of standard Questaal syntax for integer lists. - −rot=strn
Create a 3×3 rotation matrix defined by elementary rotations in strn.
strn should take the standard Questaal syntax for rotations constructed from a product of elementary rotations about specified angles. - −roteu
Converts a rotation matrix resident on the stack to Euler angles (an inverse operation to −rot=). Examples:
mcx -rot=x:pi/2
pushes a new 3x3 array (rotation) on the stack while
mcx -rot=x:pi/2 -roteu
returns the Euler angles for that rotation
−ylm~l=l [~switches]
A multifunction rotator of spherical harmonics.
you must specify a value l which, depending on the mode specifies a particular l block of real or spherical harmonics Ylm.- Default mode
- returns a square array of rank (l+1)2, a matrix R that rotates a a linear combination of Ylm in one reference frame to the corresponding combination in a rotated reference frame. If the linear combination is specified by column vector C, The corresponding combination in the rotated frame is R C.
No special switches are required but a 3×3 rotation matrix must be on the top level of the stack (you can make one with −rot=strn).
Example: : a π/2 rotation around z rotates (x,y) into (−y,x) (clockwise active rotation of vectors; or anticlockwise passive rotation of coordinates).
The l=2, m=−2, and l=2, m=2 orbitals, which are xy and x2-y2, are mapped into their negatives, −xy and y2−x2.
The l=2, m=−1 orbital (yz) is mapped to −xz; the l=2, m=+1 orbital (xz) is mapped to yz.
the l=2, m=0 orbital (3z2−1) is mapped to itself.
mcx -f9f12.6 -rot=z:pi/2 -p -ylm~l=2 -sub 5,9,5,9
Optional switches available in this mode:
~spin creates a 2×2 superarray with the (1:2,1:2) subblocks corresponding to spins ±1/2. each subblock of the superarray is a diagonal, constant matrix of rank (l+1)2. The orbital part is not rotated.
~spin+o Combines spin and orbital rotations. The superarry is a product of the spinor and orbital rotations.
~spin+only Also creates a 2×2 superarray, but only orbital part is rotated.
~sh works with true spherical harmonics instead of real ones.
~sh2 Same, but m is ordered l, l−1, …, −l (reversed from the normal ordering). - mode ~v=x,y,z
- Evaluates the real form of the spherical harmonics polynomial at a point x,y,z; see this page.
- modes ~s2r and ~r2s, and ~s2rl and ~r2sl
- ~r2s pushes onto the stack the complex conjugate u* of matrix u defined by Eq. (9) in the spherical harmonics documentation.
u* is a square array of rank (l+1)2 that rotates a linear combination of real harmonics , to the corresponding combination of true spherical harmonics .
If C is a vector representing a linear combination of , u* C is the corresponding linear combination of .
You must specify a particular l (use ~l=#). No arrays are needed from the stack.
s2r and s2rl are the same (as are r2s, and r2sl) except that the former prints out the matrix for all l up to the specified one, while the latter prints the matrix for one particular l.- s2r, s2rl matrix to rotate spherical to real harmonics, i.e. generate (u*)−1 = uT
- r2s, r2sl matrix to rotate real to spherical harmonics, i.e. generate u*
Example: : rotate l=2 spherical harmonics into real harmonics.
and .
These 2×2 matrices can be extracted from (1,5) and (2,4) columns of the 5×5 rotation matrix generated by-ylm~s2rl~l=2
:
mcx -ylm~s2rl~l=2 -coll 1,5 -rowl 1,5
mcx -ylm~s2rl~l=2 -coll 2,4 -rowl 2,4
- modes ~r2kmu and ~s2kmu, and ~kmu2r and ~kmu2s
- pushes onto the stack the matrix rotating either real to spherical harmonics to relativistic angular momenta given by quantum numbers , . The latter two forms are the inverse operations.
- ~rots mode
- rotates a square structure matrix Smm′ which represents an expansion in bilinear spherical harmonics |Ylm(1)> Smm′ <Ylm′ (2)|. S is rotated to R S R−1.
In this mode S must be the top-level array on the stack. Additionally you must specify a rotation matrix. There are three options:- ~eula=#,#,# The three Euler angles α, β, γ that define a rotation matrix
- ~rot=strn A string defining a rotation (same syntax ax −rot=strn above)
- ~ntry=# makes a stochastic search for a rotation that minimizes the off-diagonal part of S
- −array[#1,#2] #,#,#,…
Push onto the stack a new real array of dimension (#1,#2). The second argument must consist of #1×#2 expressions separated by commas. They specify elements
(1,1), (1,2), … (1,#2), (2,1), (1,2), … (1,#2), … (#1,1), (#1,2), … (#1,#2) .
Example:mcx -f18f8.2 -array[2,3] 6,5,4,3,2,1
creates a 2×3 array with the second row containing elements 3,2,1, respectively. - −sarray[#1,#2] | −sarrayr[#1,#2] | −sarrayc[#1,#2] | −sarrayz[#1,#2]
Assemble a superarray of #1×#2 arrays pre-existing on the stack. It is an error these stack arrays are not present.- −sarray[#1,#2] : The top rows of the superarray are constructed from the first #2 arrays on the stack; The bottom rows from the last #2 arrays.
- −sarrayz[#1,#2] : reverses stack order, so the (1,1) and (#1,#2) elements of the superarray are copied respectively from from s#1×#2 and s0.
- −sarrayc[#1,#2] : reverses column order but not row order of stack.
- −sarrayr[#1,#2] : reverses row order but not column order of stack.
Constituents of each superblock row (e.g. the first row, s0, s1, …, s#2−1) must have a fixed number of rows. Also each superblock row must combine to make the same number of columns.
See below for an example.
See Instruction Summary.
Row and column Unary Operators
These unops treat s0 as an array of nr rows and nc columns.
- −rowl list | −coll list
Creates a new array from a list of rows (columns) of s0 - −rowl:mirr | −coll:mirr
Rearranges rows (columns) in reverse order - −rowl:pf=fnam | −coll:pf=fnam | −rowl:ipf=fnam | −coll:ipf=fnam
Same as −rowl (−coll) but list is read from permutation file fnam. ipf reverses the sense of the permutation.
Example: file perm contains 2 3 1 4. Then- −rowl:pf=perm returns s0 with rows 2,3,1,4 permuted into 1,2,3,4
- −rowl:ipf=perm returns s0 w/ rows 3,1,2,4 permuted into 1,2,3,4
- −inc expr
Retains rows from s0 for which expr is nonzero. - −sub t,b,l,r | -sub t,l
Extracts a subblock of s0. In second form, bottom right corner = (nr,nc). - −subs:# t,b,l,r
Scales a subblock of s0 by #. - −subv:# t,b,l,r
Copies # to subblock of s0. - −e# expr1 expr2 … expr#
Create new matrix of # columns with values expr1 expr2 … expr# .
Variables x1, x2, … can be used in the expressions. These variables refer to the elements of s0in columns 1, 2, …, and change with each row.
This switch is used in Example 2.4.
Note: : at present this switch does not work for complex arrays. - −abs
takes the absolute value of each element - −max[:i|g]
puts the largest element in a given row into the first column.
Optional g returns max value of the entire array
Optional i returns index to max value. - −nint[#1]
Replaces each element with nearest integer.
Optional #1: scale array by #1 before operation, and by 1/#1 after. Thus -nint:1000 rounds to nearest thousandth.
See Instruction Summary.
Unary Operators that treat data as discretized continuous functions of the first column
In these unops, column 1 (x1) is treated as an the independent variable.
Three of these unops fit data in other columns with a polynomial in x1. The polynomial is used to differentiate (−diff), integrate (−int), or interpolate (−intrp) data in the remaining columns. There are some modifiers (called [:opts] in the documentation below):
- :nord=# will change the number of points in fitting polynomial to # (polynomial order is #−1). The default value is #=4.
- :rat will use a rational polynomial, rather than an ordinary one. Good for data with singularities.
- :mesh (applies to −int only) replaces s0 with its integral on the same mesh as the original set of values x1. A trapezoidal rule is used at present.
You can string the options together. These three unops are demonstrated in Example 2.4.
- −diff[:opts]
differentiates columns 2…nc using column 1 as the abscissa s0 is returned as a table of points with list in the first column and the remaining columns replacing the function value at each x1 with its (numeric) derivative. - −int[:opts] xlo list
integrates columns 2…nc using column 1 as the abscissa, from the lower bound xlo to a set of upper bounds, given by list.
s0 is returned as a table of points with list in the first column and the result of the integral in the remaining columns. - −intrp[:opts] list
interpolates column 2 to points in list, using column 1 as the abscissa.
s0 is returned as a table of points with list in the first column and the result of the interpolation in the remaining columns. - −smo width,xmin,xmax,dx:
smooths vector of delta-functions with gaussians - −unx[:i1] #1,#2
(uncross) exchanges points in columns #1 and #2 after their point of closest approach - −unx2[:i1] #1,#2
(cross) exchanges points in columns #1 and #2 at their point of closest approach, if they do not cross. - −at[:i1] val expr
find adjacent rows that bracket expr=val. Array contains linearly interpolated x1 and expr. - −ipoly=x
Constructs a Lagrange interpolating polynomial from points in column 1. s0 must be an array with one column; the order of polynomial is the number of points. This switch returns weights to use at the given points in order to interpolate some object (e.g. a function or matrix) known at the given points to point x.
Example:mc '-array[3,1]' 1/2,0,1 -ipoly=1/4 -t
returns a three-element vector, 3/4, 3/8, -1/8. Applying these weights to a linear combination of some object known at points 1/2, 0, 1, will estimate the object at x=1/4, using a quadratic interpolation. Note that the sum of the weights must be unity.
See Instruction Summary.
Find numerical differences read from a pair of files with mixed text and numbers
mcx has a special mode, which you invoke with the command-line argument -cmpf
. It does not act on the stack but instead reads two files, comparing line by line, extracting words (i.e. strings separated by spaces) that appear to be floating point numbers, and numerically evaluating their difference.
Its default operation is to print out information about the file, such as:
lines 1:29 cols 1:75 words 152 chars 1214 ndiff 3 max 10
You can print print out a subset of this information (see printopt below). This is intended for scripts that compare differences in the numerical values in two files.
Blank lines in either file are skipped over. There is no facility, such as with the diff command, to re-align lines where extra lines are present in only one file.
The syntax for this switch is:
-cmpf[~ln=..][~col=..][~sep=<i>c</i>][~quiet][~verb][~long][~char|~tol=#][~rnge=#1,#2][~incl=<i>s</i>][~excl=<i>s</i>][~term=<i>c</i>][<i>printopt</i>]~fn1=<i>f1</i>~fn2=<i>f2</i>|~diffy=#
The first character following -cmpf
is the delimiter separating tags (assumed here to be ~). ~fn1
and ~fn2
are required; the rest are optional. (Alternatively, ~diffy
may substitute for ~fn2
.)
Their meaning is:
- ~ln=#[,#2]
Compare only the first # lines, or if #2 is present, lines in the range (#,#2).
If #2 is present with value zero, lines #…END are compared - ~col=#[,#2]
Compare only the first # columns, or if #2 is present, columns in the range (#,#2) - ~sep=c
If a word contains character c, it is split into separate words using c as the delimiter.
Thus if c is “=”, the word DQ=1e-6 is split into two words, the second being a number.
Note that c can be a sequence of characters. - ~quiet
silent mode : prints out nothing but returns the number of differences to stdout (capped at 255) - ~verb | ~vverb
verbose mode: prints out information about each line. The latter is a very verbose mode: it also prints out the lines themselves. - ~long
compares longest of the two lines. The shorter line is filled with blanks. By default, lines are compared only up to the smaller number of words in the two lines. - ~char
a special mode that does no numerical conversions, but compares lines character by character - ~tol=#
If the difference in numerical values of words converted into numbers is less than #, the two are treated as equal. - ~rnge=#1,#2
If a number extracted from either f1 or f2 lies outside the range (#1,#2), no comparison is made. - ~excl=s
Tells mcx to exclude lines containing character string s. If ~excl appears more than once, mcx will exclude lines containing any of the associated strings. - ~incl=s
Tells mcx to compare only lines containing character string s. If ~incl appears more than once, mcx will include lines containing any of the associated strings. - ~term=c
When a character c is encountered in either file, mcx terminates the comparison .
Note that c can be a sequence of characters. - printopt is one of the keywords below. Its function is to change mcx output write a single number. printopt should be one of:
- ~nchar returns the total number of characters in the rows and columns read.
- ~nword returns the number of words
- ~ndiff returns the number of instances of numerical words found to be different, or if ~char is present, the number of differences in characters
- ~max returns the global maximum numerical difference encountered
- ~fn1=f1
f1 is the first file to be compared. - ~fn2=f2
f2 is the second file to be compared. - ~diffy=#
This may be used as an alternative to ~fn2=f2. Then f1 must contain side-by-side differences of two files generated by the unix diff command. To create f1, run diff on the two files to compare (call them filea and fileb as follows:
diff -W # [--suppress-common-lines] -y filea fileb | expand > f1
Note that # is the width of the combined file. Use the same value when running mcx asmcx -cmpf~fn1=f1~diffy=#...
Example: Compare how –help differs between lm and lmf. Assuming lm, lmf, and mcx are in your path, do :
lm --help > file1
lmf --help > file2
mcx -cmpf~fn1=file1~fn2=file2~col=40~vverb
You should see the first 40 columns of the two outputs displayed line by line, a summary of the differences found for each line pair, and at the end a summary similar to:
lines 1:29 cols 1:40 words 99 chars 814 ndiff 3 max 10
Binary Operators
These operate on the top two matrices in the stack, s1 and s0. s1 and s0 are popped from the stack, and the result of the binary operation is put into s0.
Dimensions for s0 and s1 are not independent; for example if they are added they must have the same number of rows and columns.
- −tog
Toggle s0 and s1. - −+
Add s1 + s0 - −−
Add s1 − s0 - −x
Multiply s1 × s0 - −xe
Multiply s1 and s0 element by element - −de
Divide s1 / s0 element by element - −x3
Multiply s1 s0 are thou they are 3D arrays: s1 = s1(n11,n21,n31) s0 = s0(n10,n20,n30) where n10=nr(0)/n20,n20=nc(1),n30=nc(0); n11=n10,n21=nr(1)/n11,n31=n20 Result(i,j,k) = sum_m s1(i,j,m) s0(i,m,k) is condensed into 2D (nr(1),nc(0)) - −gevl | −gevc
Same as −evl | −evc, but for the generalized eigenvalue problem. s1 is the nonorthogonal matrix. - −orthos:
Replace s0 with s1-1/2 s0 s1-1/2 - −ccat:
Concatenate columns of s1 and s0 into a single array - −rcat:
Concatenate rows of s1 and s0 into a single array - −cross:
Cross product s1(1,1..3) x s0(:,1..3) - −suba[#] t,b,l,r | -suba[#] t,l
Copy s1 to subblock of s0. Conventions for subblock are the same as for −suba t,b,l,r | -sub t,l.
Optional # copies #×s1 into s0. - −index:
Use s0 as an row index to s1. s0(i) is overwritten by s1(s0(i)). s1 is preserved. New s0 has row dimensions of the original s0 and column dimensions of s1. - −alignqp:
Aligns two lists of vectors (row length must be 3).
Example: Four vectors are entered twice (each as 3×4 arrays), in different order. −alignqp returns a 4×1 array showing the permutation order (which is 4,1,3,2 in this example):
mcx -f3f5.0 ‘-array[3,4]’ ‘1 2 3 4 5 6 7 8 9 -1 -2 -3’ ‘-array[3,4]’ ‘-1 -2 -3 1 2 3 7 8 9 4 5 6’ -alignqp
Repeated Iteration of Command Line Arguments
Command line arguments can be repeated by enclosing them in brackets, with the syntax
[ name=list arg1 arg2 arg3 ... argn ]
list
is a standard Questaal integer list.
mcx executes the sequence of command line arguments arg1, arg2, arg3, …, argn for each element in list. Within this special construct, arg1, arg2, … are treated as strings that are parsed for expression substitution. In particular, variables name and i are loaded and recalculated each pass. name is the value of the current integer, and i is the index in the list.
name= is not required; mcx will use ir as the loop variable if it is omitted.
The scheme is best explained by a concrete illustratation.
Example 1:
Suppose files a0, a1 and a4 reside on disk, with a0 a 4×4 symmetrix matrix, a1 4×4 hermitian, and a4 1×3 real. The command
mcx [ k=0,1,4 'a{k}' ] -show
should get expanded to a sequence of four arguments
loopcounter i | k | argument | action | |
1 | 1 | 0 | a{k} | a0 loaded onto stack |
2 | 2 | 1 | a{k} | a1 loaded onto stack |
3 | 3 | 4 | a{k} | a4 loaded onto stack |
4 | - | - | -show | displays stack |
Note tha both loop counter i and loop variable k are remade each iteration.
You should see the following:
# 0 named arrays, 3 on stack; pending 0 unops 0 bops (vsn 1.058)
# stack nr nc cast
# 3 1 3 real
# 2 4 4 herm
# 1 4 4 symm
Conditional evaluation of an argument
Within the [ … ] construct, an argument that begins with ? is treated as an expression. The result of that expression determines whether the subsequent argument should be evaluated or skipped. Thus the construct
mcx ... [ ... '?expr' argi ... ]
parses expr as an expression. If it evaluates nonzero, argi is executed. Otherwise, argi is passed over.
Example 2:
mcx [ 0:2 'a{ir}' '?i>1' -rcat ]
Pushes a0 on the stack (note that variable ir is used as default, since no name wsa spcified)
Evaluates expression
?i>1
. In the first pass the loop counter is 1, so the expression evaluates to false and the next argument is ignored.Pushes a1 on the stack
Evaluates expression
?i>1
, which now evaluates to true. The-rcat
argument is parsed, row-concatenating a0 and a1 leaving a single array on the stackPushes a2 on the stack, can row-concatenates it to the existing stack
The final stack consists of a single array which concatenates a0, … , a2.
Special handling of the last iteration
You can prevent the last argument (or arguments) in the loop from executing, by appending a / to the [. A single slash suppresses the last argument, two slashes suppress the last two arguments, and so on.
Example 3: cut and paste the 2×2 matrix in the box below to file a.
1 x
x x*x
Then do:
mcx [/ 1:3 '-vx={i}' a -+ ]
This sums three instances of a with x=1, x=2, and x=3. Note that three arrays are loaded but there are only two additions, so −+ should be suppressed the last iteration.
You should see the following output:
% rows 2 cols 2 real
3.000000 6.000000
6.000000 14.000000
The (1,1) element is the sum of x0 for x=1…3, while (1,2) and (2,1) are the sum of x1 and (2,2) is the sum of x2.
To see the arguments being parsed in detail, use the -debug
switch:
mcx -debug [/ 1:3 '-vx={i}' a -+ ]
Nested iterations of commands
The looping construct can be nested, as illustrated by the following example. It makes a 6×6 array from assembling 9 instances (3 rows and three columns) of a single 2×2 array, modifying each instance.
Example 4:
Use nested loops to make the following array
% rows 6 cols 6 real
14.00 12.00 0.00 0.00 0.00 0.00
13.00 11.00 0.00 0.00 0.00 0.00
0.00 0.00 24.00 22.00 0.00 0.00
0.00 0.00 23.00 21.00 0.00 0.00
0.00 0.00 0.00 0.00 34.00 32.00
0.00 0.00 0.00 0.00 33.00 31.00
The three diagonal 2×2 blocks are the array [[4,3],[2,1]]
, shifted respectively by 10, 20, 30. The following command makes this array:
mcx -f18f8.2 [ ix=1:3 [ jx=1:3 '-array[2,2]' 4,3,2,1 "-shft=jx*10" '?jx<>ix' -s0 ] ] '-sarray[3,3]'
Compare what happens when you load elements in reverse order, e.g. with -sarrayz[3,3]
, -sarrayr[3,3]
, -sarrayc[3,3]
.
Example 5: Given a pair of 32×32 arrays in files A and B, split each into four 16×16 subblocks, and create an interleaved 64×64 array of the form
In the following command, -1:16 -s0 -a z
creates a 16×16 array of zero value, named z. The two -split commands create four subblocks each of arrays a and b. Finally the 16 subblocks are pushed onto the stack in the order as they occur in the array, and assembled with -sarray[4,4]
.
mcx -f16f12.6 -1:16 -s0 -a z A -split a 1:nr+1:16 1:nc+1:16 -pop B -split b 1:nr+1:16 1:nc+1:16 -pop \
a11 z a12 z z b11 z b12 a21 z a22 z z b21 z b22 '-sarray[4,4]'
Return to Table of Contents.
Instruction summary
This section summarizes available mcx instructions, with hyperlinks to the descriptions in the manual.
Switches that affect variables and formatting of data files that are read and written.
−nc=# (nr=#)
−vvar=#
−show
−mmacroname(arg1,arg2,…)=expr(arg1,arg2,…) −w[l=string] fname | −bw[l=string] fname
−wap
−a[nr=#|:nc=#] nam | −ap nam
−av[ir,ic] vvar
−r~switches
−px[:nprec]
−pxc
Operators that act on the top level matrix and replace it with the result of the unary operator:
−p −p+n −(-p-n)
−pop −popu −popb
−csum[:list] −rsum[:list]
−s#
−shft=#
−sort expr
−i | − iq
−1:n
−evl | −evc
−t −cc
−herm −real
−v2dia
−split nam row-markers column-markers
−rep:n1,n2
−roll:#1[,#2]
−pwr=#
−tp [nc~]list
−rot=strn
−roteu
−ylm~l=l[~sh|~sh2|~s2r|~2rs][~spin|~spin+o|~spin+oonly]
−array[#1,#2] #,#,#,…
−sarray[#1,#2] | −sarrayr[#1,#2] | −sarrayc[#1,#2] | −sarrayz[#1,#2]
Row and column Unary Operators
Row and column manipulations of the top-level array
−rowl list −rowl:mirr
−coll list −coll:mirr
−rowl:pf=fnam −coll:pf=fnam −rowl:ipf=fnam −coll:ipf=fnam
−inc expr
−sub t,b,l,r −subs:# t,b,l,r −subv:# t,b,l,r
−e# expr1 expr2 … expr#
Unary Operators treating data as discretized continuous functions of the first column
−diff[:opts]
−int[:opts] xlo list
−intrp[:opts] list
−smo width,xmin,xmax,dx
−abs
−max[:i|g]
−unx[:i1] #1,#2 −unx2[:i1] #1,#2
−at[:i1] val expr
−nint[#1]
Operator that replace the contents of the two matrices on the stack with the result of a binary operation. if they are added they must have the same number of rows and columns.
−tog −+ −− −x −xe −de
−x3
−gevl −gevc
−orthos
−ccat −rcat
−cross
−suba[#] t,b,l,r -suba[#] t,l
−index
Use -cmpf to compare numbers between two files with mixed text and numbers.
Repeated Iteration of Command Line Arguments
Loop over arguments inside [ .. ]
Return to Table of Contents.
Other resources
The source code to mcx can be found in the bitbucket repository.