Space Group Symmetry

**SgInfo** is library of ANSI C routines

- for the
*generation*of symmetry matrices - for the
*derivation*of- International Tables Volume A space group name & number
- crystal system
- point group
- laue group
- semi-invariant vectors and moduli

*from symmetry matrices alone* - to assist in the treatment of symmetry in reciprocal space
- easy on-line access to a total of
*530 settings*of all space groups listed in the International Tables Volume I (1952) (ITVI) and Volume A (1983) (ITVA)

The design of the routines is based on the notation introduced by Hall which enables unambiguous and practically unrestricted definition of space group, setting, and origin. Input Hall symbols are translated into Seitz matrices, which, in turn, are used to generate the full set of symmetry operations. After the input Hall symbol has been translated, the matrices are sorted and reduced back to an output Hall symbol. For a given space group and setting, the reduction process will always result in the same Hall symbol, regardless of the way the group was generated; i.e., Seitz matrices from any source may be passed to the symmetry generating routines and a well defined Hall symbol will be produced.

Part of the library is a table which associates ITVA space group numbers, Schönflies symbols, Hermann-Mauguin symbols, and Hall symbols. This table is used in two ways. Space group numbers and symbols can be translated to a Hall symbol, which is used to generate the symmetry matrices. Alternatively, the Hall symbol produced by the reduction algorithm of the library is used to find the appropriate entry in the table.

What follows in this document, is meant to be an

There is also a

**where each structure, subroutine, and macro is explained
in detail**.

Table of Content for this document:

- SgInfo Demonstration Program
- Getting SgInfo
- Other space group software and web sites
- Known Bugs
- Using SgInfo in your application
- Using the space group finder
- Copyright Notice
- References

The **SgInfo** package comes with a demonstration
program which also has a certain value on its own. Running
`sginfo` without arguments will produce a
little help screen:

usage: sginfo [options] [SpaceGroupName_or_# [SpaceGroupName_or_#]] -Hall|VolA|VolI select conventions -ListTable[=#] print [parts of] internal table -CIF print internal table in CIF format -XYZ print something like "-x, y+1/2, z" -AllXYZ print all symmetry operations -Maple print symmetry matrices in Maple format -Space print symmetry file for AVS SpaceModule -Shelx print Shelx LATT & SYMM cards -Schakal print Schakal DU & SY cards -hklList print simple hkl listing -Standard compute transformation to "standard" setting -UnitCell="a..g" unit cell constants a, b, c, alpha, beta, gamma -v be more verbose -Verify debug option: verify transformations -ClearError debug option: clear errors and continue examples: sginfo 68 sginfo C2/m:c2 -XYZ sginfo "Oh^3" -Shelx sginfo -Hall "-F 4y 2" -Standard sginfo -VolI 15 -VolA 15 sginfo -ListTable=68

Try some of the examples:

% sginfo 68 Space Group 68:1 D2h^22 Ccca:1 C 2 2 -1bc Point Group mmm Laue Group mmm Orthorhombic Note: Inversion operation off origin Order 16 Order P 8 s.i.Vector Modulus 1 0 0 2 0 0 1 2

What does all this mean?

The first line tells you what the lookup in the internal table
has produced for "`68`". This is the entry
for space group `68`, *Origin Choice 1*
(`:1`).
This space group has the Schönflies symbol
`D2h^22`, the Herman-Mauguin symbol `Ccca`
and the Hall symbol "`C 2 2 -1bc`".

After `sginfo` has found the table entry, it
translates the Hall symbol to symmetry matrices. Next - through
repetive multiplication of these generator matrices - the whole
group, i.e. all symmetry matrices of this space group, are
computed.

Knowing all symmetry matrices, `sginfo`
derives that space group `68` belongs to point group
`mmm`, laue group `mmm`, and the orthorhombic
crystal system.
Furthermore, space group `68` is centro-symmetric, but
the inversion operation is not at the origin (of course this is what
ITVA *Origin Choice 1* means, but `sginfo`
finds out without looking at this).

The maximum number of equivalent positions in
space group `68` is indicated by `Order 16`.
To help people who want to use the **SgInfo** library
routines in their own applications, **SgInfo** also
stores the maximum number of positions of the
primitive "`P`" subgroup of
the space group. In this case
`Order P 8` is reported.

*Direct Methods* people might be delighted to see that
**SgInfo** also knows how to derive semi-invariant
vectors and moduli from a set of symmetry matrices. Here we have
two semi-invariant vectors - one along x (1 0 0), one along z (0 0 1)
- with modulus "`2`".

In the next example, `sginfo` demonstrates its
ability to look up Schönflies symbols. In addition, a
list of the symmetry operations in **SHELX**
format is requested. For all who do not have
**SHELX-TL(TM)**, this could help avoiding a lot
of typos:

% sginfo "Oh^3" -Shelx Space Group 223 Oh^3 Pm-3n -P 4n 2 3 Point Group m-3m Laue Group m-3m Cubic Order 48 Order P 48 s.i.Vector Modulus 1 1 1 2 LATT 1 SYMM .5-Y, .5+X, .5+Z SYMM -X, -Y, Z SYMM .5+Y, .5-X, .5+Z SYMM .5+X, .5-Z, .5+Y SYMM X, -Y, -Z SYMM .5+X, .5+Z, .5-Y SYMM .5+Z, .5+Y, .5-X SYMM -X, Y, -Z SYMM .5-Z, .5+Y, .5+X SYMM Z, X, Y SYMM Y, Z, X SYMM -Y, -Z, X SYMM Z, -X, -Y SYMM -Y, Z, -X SYMM -Z, -X, Y SYMM -Z, X, -Y SYMM Y, -Z, -X SYMM .5+Y, .5+X, .5-Z SYMM .5-Y, .5-X, .5-Z SYMM .5-X, .5+Z, .5+Y SYMM .5-X, .5-Z, .5-Y SYMM .5+Z, .5-Y, .5+X SYMM .5-Z, .5-Y, .5-X

The next example again demonstrates two new features: how to enter a Hall symbol from the command line and how to find out which space group is generated by this Hall symbol:

% sginfo -Hall "-F 4y 2" -Standard Setting A: Hall Symbol -F 4y 2 Point Group 4/mmm Laue Group 4/mmm Tetragonal Unique Axis y Order 64 Order P 16 s.i.Vector Modulus 1 1 1 2 Setting B: Space Group 139 D4h^17 I4/mmm -I 4 2 Point Group 4/mmm Laue Group 4/mmm Tetragonal Unique Axis z Order 32 Order P 16 s.i.Vector Modulus 0 0 1 2 Change of Basis Setting A -> Setting B: CBMx = x+z, x-z, y InvCBMx = 1/2*x+1/2*y, z, 1/2*x-1/2*y

First of all, `sginfo` processes the Hall symbol and
reports the results under "`Setting A`". Since
"`Unique Axis y`" is a very strange
setting for a tetragonal space group, `sginfo` cannot
find an entry in the internal table and hence only reports the (newly
generated) Hall symbol.

Fortunately there is the "`-Standard`"
option, which tells `sginfo` to try harder to find out
about the ITVA space group number. Therefore `sginfo`
tries to match the generators of all space groups in the internal
table (which do belong to the same point group) to the actual set
of symmetry matrices by building the proper *change-of-basis
matrix*, in this case coming up with space group `I4/mmm`.

The result of the space group finding process is not necessarily
the "standard" setting, but a certain *reference
setting*. Therefore `sginfo` evaluates which
"conventions", either option "`-VolI`"
or "`-VolA`" (which is the default) are
currently selected, obtains the corresponding standard setting
und reports the results under "`Setting B`".
Again `sginfo` starts to search for the reference
setting, this time only to get the corresponding change-of-basis
matrix.

In the last step, `sginfo` combines the change-of-basis
matrices for "Setting A -> Reference Setting" and
"Setting B -> Reference Setting" to obtain the matrix
and its inverse for "Setting A -> Setting B".

If you do not trust `sginfo` and/or want to see
the individual change-of-basis matrices to the reference setting,
run `sginfo` with the "`-Verify`"
option set.

Maybe it is sensible to add the following short definition:

` "CBMx`" transforms
the *coordinates* of Setting A to coordinates of
Setting B.

"`InvCBMx`" transforms
the coordinates of Setting B to coordinates of
Setting A.

BTW: the execution time on a 486 DX2 66 MHz PC running Linux is less than 0.5 seconds for the whole process above (two times generation of the symmetry operations, two times finding the space group with construction of the change-of-basis matrix).

The last example illustrates how easy it is to get the change-of-basis matrix for the transformation of the "old" standard setting of ITVI to the "new" standard setting of ITVA:

% sginfo -VolI 15 -VolA 15 Setting A: Space Group 15:-c1 C2h^6 C2/c:-c1 = B112/b = B2/b -B 2b Point Group 2/m Laue Group 2/m Monoclinic Unique Axis z Order 8 Order P 4 s.i.Vector Modulus 0 1 0 2 0 0 1 2 Setting B: Space Group 15:b1 C2h^6 C2/c:b1 = C12/c1 -C 2yc Point Group 2/m Laue Group 2/m Monoclinic Unique Axis y Order 8 Order P 4 s.i.Vector Modulus 1 0 0 2 0 0 1 2 Change of Basis Setting A -> Setting B: CBMx = x-y-1/4, z+1/4, -y InvCBMx = x-z+1/4, -z, y-1/4

A xray powder pattern has been indexed with the **POWDER**
program of *D. Taupin* [1].
The unit cell as found by the program was monoclinic,
*a*=8.63289, *b*=9.10859, *c*=17.699,
*gamma*=108.45. Examination of systematic absences
suggested space group *P 1 1 2 _{1}/n*.

What is the standard setting of this space group and what are the corresponding cell constants?

% sginfo "P 1 1 21/n" -Standard -UnitCell="8.63289 9.10859 17.699 108.45" Setting A: Space Group 14:c2 C2h^5 P21/c:c2 = P1121/n -P 2n Point Group 2/m Laue Group 2/m Monoclinic Unique Axis z Order 4 Order P 4 s.i.Vector Modulus 1 0 0 2 0 1 0 2 0 0 1 2 Setting B: Space Group 14:b1 C2h^5 P21/c:b1 = P121/c1 -P 2ybc Point Group 2/m Laue Group 2/m Monoclinic Unique Axis y Order 4 Order P 4 s.i.Vector Modulus 1 0 0 2 0 1 0 2 0 0 1 2 Change of Basis Setting A -> Setting B: CBMx = x-y, z, -y InvCBMx = x-z, -z, y Setting A UnitCell 8.63289 9.10859 17.699 90 90 108.45 Setting B UnitCell 8.63289 17.699 10.3789 90 123.644 90

If you have the ITVA at hand, it is not a big trick to obtain
the standard setting *P 1 2 _{1}/c 1*.
What is more of
a problem is to find the correct change-of-basis matrix, even if you
have the ITVA. This is where

The formula for the transformation of the metrical matrix G(A) of Setting A to the metrical matrix G(B) of Setting B is (see e.g. Boisen & Gibbs [2]):

G(B) = transpose(InvCBMx) * G(A) * InvCBMx

By applying this formula `sginfo` finally
produces the cell parameters for Setting B.

For those who not want to learn more about **SgInfo**
at this point and want to play on their own machine right away:
here are some hot links:

- Windows 32-bit executable (Expected to run also on 64-bit Windows systems.)
- DOS executable (from 1995)
- Mac OS X 10.4 Intel executable
- Mac OS X 10.4 PPC executable
- Macintosh executable (from 1996) (for 68000 Macs, runs also on PowerMacs) [*]
- Linux executable (RedHat 8.0) (Expected to run on most systems.)
- Linux executable (from 1995)
- SunOS 4 executable
- Sun Solaris 2.3 executable [+]
- IBM AIX 3.2 executable
- Silicon Graphics IRIX 5 executable
- VMS VAX executable
- VMS Alpha executable
- OSF1 Alpha executable

[*] Courtesy Jon Tischler (TischlerJZ@ornl.gov)

[+] Courtesy Andreas Karrer (karrer@ife.ee.ethz.ch)

For all who want to test their compilier: some source code:

You want more Space Group Info?

There is more available:

- The Space Group Explorer

A free Windows program based on SgInfo. - Bilbao Crystallographic Server

**Warning:**
If you do not know the basics of **C**,
the rest of this document will be very boring.

- sginfo.h: TabSgName: wrong P_42_1_2, correct P_4_21_2
- sginfo.h: TabSgName: wrong R_32, correct R_3_2
- sghkl.c: SetListMin_hkl(): wrong results for some trigonal space groups
- sgclib.c: TransformSgInfo(): unit translations need to be transformed since they can give rise to fractional translations
- sgfind.c: Depending on the orientation of the basis vectors corresponding to the input symmetry operations, space group Pa-3 is sometimes not recognized.

The **SgInfo** library routines are grouped
into five C source code files and one C header file:

sginfo.h header file with global definitions sgclib.c core library routines sgio.c input/output routines sgfind.c space group finding routines sghkl.c reciprocal space routines sgsi.c semi-invariant routines

To demonstrate how to use the library there are two additional files with driver routines:

sginfo.c the driver for the examples above sgquick.c a very simple template driver

Have a look at `sgquick.c`. This driver takes
one command line argument,
e.g. `sgquick "VolA P2"`,
and sends this string to `BuildSpgrInfo()`.

The first half of `BuildSgInfo()` does nothing
more than splitting the input string `SgName`
into the part which selects the conventions
(like the `-Hall|VolA|VolI` options in the
preceding examples) and the space group symbol itself.

The first call to the **SgInfo** library is
`FindTabSgNameEntry()`. This routine maps
space group numbers, Schönflies symbols, and
Hermann-Mauguin symbols to Hall symbols.

In the next section we allocate memory to hold the Seitz matrices and some additional parameters. Then the SgInfo structure is initialized, the Hall symbol is translated to Seitz matrices, thereby generating the whole group through multiplication.

The final step is a call to `CompleteSgInfo()`.
This routine sorts and reduces the list of Seitz matrices,
determines crystal system and point group, and a new
Hall symbol is derived from the symmetry operations.
This new Hall symbol is used to find the entry in the
internal table; if the entry is known in advance,
**SgInfo** just verifies if the new result
is the same (or signals an "Internal Error"
otherwise). If there is no matching entry,
**SgInfo** does not report the
ITVA space group name and number at this point.

#include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> #include "sginfo.h" static int str_ibegin(const char *s1, const char *s2) /* string ignore-case */ { /* begin */ char u1, u2; while (*s1 && *s2) { u1 = toupper(*s1++); u2 = toupper(*s2++); if (u1 < u2) return -1; else if (u1 > u2) return 1; } if (*s2) return -1; return 0; } int BuildSgInfo(T_SgInfo *SgInfo, const char *SgName) { int VolLetter; const T_TabSgName *tsgn; /* look for "VolA", "VolI", or "Hall" */ while (*SgName && isspace(*SgName)) SgName++; VolLetter = -1; if (isdigit(*SgName)) VolLetter = 'A'; else if (str_ibegin(SgName, "VolA") == 0) { VolLetter = 'A'; SgName += 4; } else if ( str_ibegin(SgName, "VolI") == 0 || str_ibegin(SgName, "Vol1") == 0) { VolLetter = 'I'; SgName += 4; } else if (str_ibegin(SgName, "Hall") == 0) { VolLetter = 0; SgName += 4; } while (*SgName && isspace(*SgName)) SgName++; /* default is "VolA" */ if (VolLetter == -1) VolLetter = 'A'; /* if we do not have a Hall symbol do a table look-up */ tsgn = NULL; if (VolLetter) { tsgn = FindTabSgNameEntry(SgName, VolLetter); if (tsgn == NULL) return -1; /* no matching table entry */ SgName = tsgn->HallSymbol; } /* Allocate memory for the list of Seitz matrices and a supporting list which holds the characteristics of the rotation parts of the Seitz matrices */ SgInfo->MaxList = 192; /* absolute maximum number of symops */ SgInfo->ListSeitzMx = malloc(SgInfo->MaxList * sizeof (*SgInfo->ListSeitzMx)); if (SgInfo->ListSeitzMx == NULL) { SetSgError("Not enough core"); return -1; } SgInfo->ListRotMxInfo = malloc(SgInfo->MaxList * sizeof (*SgInfo->ListRotMxInfo)); if (SgInfo->ListRotMxInfo == NULL) { SetSgError("Not enough core"); return -1; } /* Initialize the SgInfo structure */ InitSgInfo(SgInfo); SgInfo->TabSgName = tsgn; /* in case we know the table entry */ /* Translate the Hall symbol and generate the whole group */ ParseHallSymbol(SgName, SgInfo); if (SgError != NULL) return -1; /* Do some book-keeping and derive crystal system, point group, and - if not already set - find the entry in the internal table of space group symbols */ return CompleteSgInfo(SgInfo); } int main(int argc, char *argv[]) { T_SgInfo SgInfo; if (argc == 2) { if (BuildSgInfo(&SgInfo, argv[1]) != 0) fprintf(stderr, "%s\n", SgError); else { ListSgInfo(&SgInfo, 1, 0, stdout); if (SgError) fprintf(stderr, "%s\n", SgError); } } return 0; }

Of course there is no big point in passing a pointer to a structure
to some strange routine without knowing what you get back.
We need to investigate the definition of `T_SgInfo`,
taken from `sginfo.h`:

typedef struct { int GenOption; int Centric; int InversionOffOrigin; const T_LatticeInfo *LatticeInfo; int StatusLatticeTr; int OriginShift[3]; int nList; int MaxList; T_RTMx *ListSeitzMx; T_RotMxInfo *ListRotMxInfo; int OrderL; int OrderP; int XtalSystem; int UniqueRefAxis; int UniqueDirCode; int ExtraInfo; int PointGroup; int nGenerator; int Generator_iList[4]; char HallSymbol[MaxLenHallSymbol + 1]; const T_TabSgName *TabSgName; const int *CCMx_LP; int n_si_Vector; int si_Vector[9]; int si_Modulus[3]; } T_SgInfo;

Live is not that easy, the definition of `T_SgInfo`
obviously needs four previous definitions, namely of
`T_LatticeInfo`,
`T_RTMx`,
`T_RotMxInfo`, and
`T_TabSgName`.

Now we approach `T_SgInfo` the following way: we just
want to know how to get hold of the symmetry matrices.

In case of a *primitive and acentric* space group
this is pretty simple: you need

`SgInfo.nList`to know how many Seitz matrices are stored in`SgInfo.ListSeitzMx`,- and the definition of
`T_RTMx`to know how to use`SgInfo.ListSeitzMx`.

Here we go:

typedef union { struct { int R[9], T[3]; } s; int a[12]; } T_RTMx;

`T_RTMx` is a union of a `struct`
with 12 `int` and a simple array of 12 `int`.

If you are scared by unions of structs and arrays,
you might be delighted to learn that
`T_LatticeInfo` as well as `T_RotMxInfo`
as well as `T_TabSgName` are simple structs
of basic data types. But we save this for later.

How does a "Rotation-Translation-Matrix"
`T_RTMx` look like for, e.g., a 2-fold screw
along `z`, also known as as
"`-x, -y, z+1/2`"?

The debugger always knows the truth:

(dbx) print SgInfo->ListSeitzMx[1] union { s = struct { R = { [0] -1 [1] 0 [2] 0 [3] 0 [4] -1 [5] 0 [6] 0 [7] 0 [8] 1 } T = { [0] 0 [1] 0 [2] 6 } } a = { [0] -1 [1] 0 [2] 0 [3] 0 [4] -1 [5] 0 [6] 0 [7] 0 [8] 1 [9] 0 [10] 0 [11] 6 } }

The rotation part `R` is pretty obvious,
"1" encodes
"`x`"
or "`y`"
or "`z`",
depending on the position;
"-1" encodes
"`-x`"
or "`-y`"
or "`-z`".

The translation part `T` needs a further definition:
the *Seitz Matrix Translation Base Factor*
"`STBF`". This factor is defined to be
`12` in `sginfo.h`.
Therefore `T[2] = 6` translates
to "`+6/12 = +1/2`".

Using the ITVA "augmented 4*4 matrix" notation, the mapping
of a position `(x,y,z)` to the symmetry equivalent
position `(xs,ys,zs)` by an element of
`SgInfo.ListSeitzMx` can be summerized by:

( xs ) ( R[0] R[1] R[2] T[0]/STBF ) ( x ) ( ys ) = ( R[3] R[4] R[5] T[1]/STBF ) ( y ) ( zs ) ( R[6] R[7] R[8] T[2]/STBF ) ( z ) ( 1 ) ( 0 0 0 1 ) ( 1 )

For *primitve centro-symmetric* space groups things are
slightly more involved. You have to evaluate two variables,
`SgInfo.Centric` and
`SgInfo.InversionOffOrigin`.

If - *after* calling `CompleteSgInfo()` -
both variables are set to `0`, the space group
is acentric. If `SgInfo.Centric` is set
to `-1`, there is an inversion operation at the origin
and `SgInfo.ListSeitzMx` will contain only an acentric
subset of the space group. If you need all symmetry operations
you have to - mathematically spoken - multiply each of the matrices in
`SgInfo.ListSeitzMx` with the inversion matrix.
In practive this means you simply have to take each element of
a matrix with reversed sign.

If `SgInfo.Centric` is `0` but
`SgInfo.InversionOffOrigin` is set to `1`,
`SgInfo.ListSeitzMx` will contain the whole (primitive)
space group. No further action has to be taken to get all
symmetry operations. In fact, if you only need to know how to
get all operations, you just need to take care of
`SgInfo.Centric`.

typedef struct { int Code; int nTrVector; const int *TrVector; } T_LatticeInfo;

`LatticeInfo.Code` is one of
`{'P', 'A', 'B', 'C', 'I', 'R', 'S', 'T', 'F'}`.
Except for `'S'` and `'T'` this should be
clear. For now forget about these strange lattice codes
`'S'` and `'T'`.

Understanding `LatticeInfo.nTrVector` is equally
straightforward. It gives the number of lattice translation
vectors which are stored in the location to which
`LatticeInfo.TrVector` points.

`TrVector[0..2]` gives the first vector
(in *any* case `{ 0,0,0 }`),
`TrVector[3..5]` gives the second, and so on,
four at maximum. The elements of
`LatticeInfo.TrVector` are multiplied by
`STBF`, hence compatible to the translation parts
of the Seitz matrices.

A little table summarizes all possibilities for
`SgInfo.LatticeInfo`:

Code nTrVector TrVector 'P' 1 0,0,0 'A' 2 0,0,0 0 ,1/2,1/2 'B' 2 0,0,0 1/2, 0 ,1/2 'C' 2 0,0,0 1/2,1/2, 0 'I' 2 0,0,0 1/2,1/2,1/2 'R' 3 0,0,0 2/3,1/3,1/3 1/3,2/3,2/3 'S' 3 0,0,0 1/3,1/3,2/3 2/3,2/3,1/3 'T' 3 0,0,0 1/3,2/3,1/3 2/3,1/3,2/3 'F' 4 0,0,0 0 ,1/2,1/2 1/2, 0 ,1/2 1/2,1/2, 0

Maybe the whole SgInfo structure stuff got somewhat abstract. A small piece of code says more than 1000 words!

So far you have seen how to pass a space group symbol
or number to **SgInfo** and how to obtain
the symmetry matrices. But this is not all you can
do with **SgInfo**.

Say, you have a program which takes
atom coordinates, looks for symmetry elements and
produces a list of the operations found.
Now you can either take the International
Tables to find out what space group you are dealing
with, or you can make life easier for yourself and use
**SgInfo**:
just pass the list of operations to the library
and wait a few milli-seconds for the
space group finder to do the job for you. You will not only
get the space group number, but also the change-of-basis matrix
from your arbitrary setting to a reference setting.

Here is how to do that:

#include <everything_you_like.h> #include "sginfo.h" int main(int argc, char *argv[]) { /* This is your program, you do anything you can to find weird symmetry matrices. You did not forget to declare SgInfo plus making two calls to malloc() to get memory for SgInfo.ListSeitzMx and SgInfo.ListRotMxInfo. Copy this from sgquick.c. This time you do not have space group symbols in advance and you do not need the table look-up. You just start with: */ InitSgInfo(&SgInfo); while (you_think_you_have_to_loop) { /* Fine. Now, everytime you found a new operation, you set up a buffer SeitzMx (do never, never, never ever set SgInfo.ListSeitzMx directly!). Passing the buffer SeitzMx to the library is exceptionally simple: */ if (Add2ListSeitzMx(&SgInfo, &SeitzMx) < 0) { /* if Add2ListSeitzMx() returns a value < 0 an error has occured and the global variable SgError has been set. A possible consequence: */ fprintf(stderr, "%s\n", SgError); exit(1); } } /* Fine. After you have passed _all_ symmetry operations - including a possible inversion operation and lattice centring vectors (rotation part of SeitzMx = identity, translation part = centring vector) - via Add2ListSeitzMx() you are ready to call: */ if (CompleteSgInfo(&SgInfo) != 0) { /* an error has occured, evaluate SgError, terminate */ } /* Fine. Now you know you have a "legal" space group. Maybe you are lucky and you hit a setting which is in the internal table. Simply ask: */ if (SgInfo.TabSgName != NULL) { /* Yes, really! If you are not interested in change-of-basis matrices you are done. You could, e.g., print out the table entry and terminate: */ PrintTabSgNameEntry(SgInfo.TabSgName, 0, 0, stdout); putc('\n', stdout); exit(0); } /* Hm. Now you have to have declared const T_TabSgName *ReferenceTabSgName; T_RTMx CBMx, InvCBMx; somewhere before. Try the hard way: */ ReferenceTabSgName = FindReferenceSpaceGroup(&SgInfo, &CBMx, &InvCBMx); if (ReferenceTabSgName == NULL) { /* This is really bad! If you arrive here an internal error has occured and SgError has been set. This means, either you have corrupted SgInfo in some way or I (see bottom line) have made some stupid error. Let me know! Do it right now! */ } /* Bingo! For the sake of simplicity we ignore CBMx and InvCBMx here. Print the reference setting and finish: */ PrintTabSgNameEntry(ReferenceTabSgName, 0, 0, stdout); putc('\n', stdout); return 0; } /* P.S.: If you made it to this point you might like to learn that there are two routines which help you adding the inversion operation and lattice centring vectors: AddInversion2ListSeitzMx(); AddLatticeTr2ListSeitzMx(); Look for more details in the reference section. */

Permission to use and distribute this software and its documentation for noncommercial use and without fee is hereby granted, provided that the above copyright notice appears in all copies and that both that copyright notice and this permission notice appear in the supporting documentation. It is not allowed to sell this software in any way. This software is not in the public domain.

IF YOU COPY AND/OR USE THIS SOFTWARE, YOU AGREE THAT THE SOFTWARE IS FURNISHED ON AN "AS IS" BASIS AND THAT THE AUTHOR IN NO WAY WARRANTS THE SOFTWARE OR ANY OF ITS RESULTS AND IS IN NO WAY LIABLE FOR ANY USE YOU MAKE OF THE SOFTWARE.

- [1]
D. Taupin;
Enhancements in Powder-Pattern Indexing;
J.Appl.Cryst.(1989),
**V22**, 455-459. - [2] M.B. Boisen, Jr. & G.V. Gibbs; Mathematical Crystallography; Reviews in Mineralogy, Volume 15, Revised Edition; Mineralogical Society of America; Washington D.C. 1990

Ralf W. Grosse-Kunstleve <rwgk@cci.lbl.gov>