############################################################################# ## #A zass.gi Cryst library Bettina Eick #A Franz G"ahler #A Werner Nickel ## #Y Copyright 1997-1999 by Bettina Eick, Franz G"ahler and Werner Nickel ## ## Routines for the determination of space groups for a given a point group ##
############################################################################# ## #F NullBlockMat( <d>, <d1>, <d2> ). . . . . . d1xd2-matrix of d-NullMatrices ##
NullBlockMat := function( d, d1, d2 ) # return d1 x d2 matrix, whose entries are d x d NullMatrices
return List( [1..d1], i -> List( [1..d2], j -> NullMat( d, d ) ) ); end;
############################################################################# ## #F FlattenedBlockMat( < BlockMat > ). . . . . . . . . flattened block matrix ##
FlattenedBlockMat := function( mat ) # flatten a matrix whose entries are matrices to a normal matrix
local m;
m := mat;
m := List( [1..Length(m[1])],
j -> Concatenation( List([1..Length(m)], i -> m[i][j] ) ) );
m := TransposedMat( Concatenation( List( [1..Length(m)],
i -> TransposedMat(m[i]) ) ) );
return m; end;
############################################################################# ## #F MakeSpaceGroup( <d>, <Pgens>, <transl>, <transp> ) construct space group ##
MakeSpaceGroup := function( d, Pgens, transl, transp ) # construct space group from point group and translation vector
local Sgens, i, m, S;
# first the non-translational generators
Sgens := List( [1..Length( Pgens )], i ->
AugmentedMatrix( Pgens[i], transl{[(i-1)*d+1..i*d]} ) );
# the pure translation generators for i in [1..d] do
m := IdentityMat( d+1 );
m[d+1][i] := 1;
Add( Sgens, m );
od;
# make the space group and return it if transp then
Sgens := List( Sgens, TransposedMat );
S := AffineCrystGroupOnLeftNC( Sgens, IdentityMat(d+1) ); else
S := AffineCrystGroupOnRightNC( Sgens, IdentityMat(d+1) ); fi;
AddTranslationBasis( S, IdentityMat( d ) );
return S;
end;
############################################################################# ## #F GroupExtEquations( <d>, <gens>, <rels> ) . equations for group extensions ##
GroupExtEquations := function( d, gens, rels ) # construct equations which determine the non-primitive translations
local mat, i, j, k, r, r0, max, prod;
mat := NullBlockMat( d, Length(gens), Length(rels) ); for i in [1..Length(rels)] do
# interface to GAP-3 format
r0 := rels[i]; r := []; for k in [1..Length(r0)/2] do
max := r0[2*k]; if max > 0then for j in [1..max] do
Add( r, r0[2*k-1] );
od; else for j in [1..-max] do
Add( r, -r0[2*k-1] );
od; fi;
od;
prod := IdentityMat(d); for j in Reversed([1..Length(r)]) do if r[j]>0then
mat[ r[j] ][i] := mat[ r[j] ][i]+prod;
prod := gens[ r[j] ]*prod; else
prod := gens[-r[j] ]^-1*prod;
mat[-r[j] ][i] := mat[-r[j] ][i]-prod; fi;
od;
od;
return FlattenedBlockMat( mat ); end;
############################################################################# ## #F StandardTranslation( <trans>, <nullspace> ) . .reduce to std. translation ##
StandardTranslation := function( L, NN ) # reduce non-primitive translations to "standard" form
local N, j, k;
# first apply "continuous" translations for N in NN[1] do
j := PositionProperty( N, x -> x=1 );
L := L-L[j]*N;
od;
L := List( L, FractionModOne );
# and then "discrete" translations for N in NN[2] do
j := PositionProperty( N, x -> x<>0 );
k := Int( L[j] / N[j] ); if k > 0then
L := List( L-k*N, FractionModOne ); fi;
od;
return L;
end;
############################################################################# ## #F SolveHomEquationsModZ( <mat> ) . . . . . . . . . . . solve x*mat=0 mod Z ##
SolveHomEquationsModZ := function( M )
local Q, L, N, N2;
Q := IdentityMat( Length(M) );
# first diagonalize M
M := TransposedMat(M);
M := RowEchelonForm( M ); while Length(M) > 0 and not IsDiagonalMat(M) do
M := TransposedMat(M);
M := RowEchelonFormT(M,Q); if not IsDiagonalMat(M) then
M := TransposedMat(M);
M := RowEchelonForm(M); fi;
od;
# and then determine the solutions of x*M=0 mod Z if Length(M)>0then
L := List( [1..Length(M)], i -> [ 0 .. M[i][i]-1 ] / M[i][i] );
L := List( Cartesian( L ), l -> l * Q{[1..Length(M)]} ); else
L := NullMat( 1, Length(Q) ); fi;
# we later need the space in which one can freely shift # non-primitive translations; first the translations which # can be applied with rational coefficients
if Length(M)<Length(Q) then
N := Q{[Length(M)+1..Length(Q)]};
TriangulizeMat( N ); else
N := []; fi;
# and now those which allow only integral coefficients if N<>[] then
N2 := List( N, n -> List( n, FractionModOne ) );
N2 := ReducedLatticeBasis( N2 );
N2 := List( N2, n -> List( n, FractionModOne ) );
N2 := Filtered( N2, n -> n<>0*N[1] ); else
N2 := []; fi;
# reduce non-primitive translations to standard form
L := Set( List( L, x -> StandardTranslation( x, [ N, N2 ] ) ) );
# check for conjugacy with generators of the normalizer of grp in GL(n,Z)
local cent, d, gens, sgens, res, orb, x, y, c, n, i, j, sg, h, m;
norm := Set( Filtered( norm, x -> not x in grp ) );
cent := Filtered( norm,
x -> ForAll( GeneratorsOfGroup( grp ), g -> x*g=g*x ) );
SubtractSet( norm, cent );
d := DimensionOfMatrixGroup( grp );
gens := GeneratorsOfGroup( grp );
sgens := List( gens, g -> AugmentedMatrix( g, List( [1..d], x -> 0 ) ) );
res := [ ]; while ll<>[] do
orb := [ ll[1] ]; for x in orb do
# first the generators which are in the centralizer for c in cent do
y := List([1..Length(gens)], i -> x{ [(i-1)*d+1..i*d] }*c );
y := StandardTranslation( Concatenation(y), nn ); if not y in orb then
Add( orb, y ); fi;
od;
# then the remaining ones; this is more complicated for n in norm do for i in [1..Length(gens)] do for j in [1..d] do
sgens[i][d+1][j]:=x[(i-1)*d+j];
od;
od;
sg := Group( sgens, IdentityMat( d+1 ) );
SetIsFinite( sg, false );
h :=GroupHomomorphismByImagesNC( sg, grp, sgens, gens );
y :=[]; for i in [1..Length(gens)] do
m := PreImagesRepresentativeNC( h, n*gens[i]*n^-1 );
Append( y, m[d+1]{[1..d]}*n );
od;
y := StandardTranslation( y, nn ); if not y in orb then
Add( orb, y ); fi;
od;
local d, S, N, F, Fam, rels, gens, mat, ext, lst, res;
d := DimensionOfMatrixGroup( grp ); if transpose then
grp := TransposedMatrixGroup( grp );
norm := List( norm, TransposedMat ); fi;
if not IsIntegerMatrixGroup( grp ) then
Error( "the point group must be an integer matrix group" ); fi;
if not IsFinite( grp ) then
Error("the point group must be finite" ); fi;
# catch the trivial case if IsTrivial( grp ) then
S := MakeSpaceGroup( d, [], [], transpose ); if orbsflag then
return [[S]]; else
return [ S ]; fi; fi;
# first get group relators for grp
N := NiceObject( grp );
F := Image( IsomorphismFpGroupByGenerators( N, GeneratorsOfGroup( N ) ) );
rels := List( RelatorsOfFpGroup( F ), ExtRepOfObj );
gens := GeneratorsOfGroup( grp );
# construct equations which determine the non-primitive translations # an alternative would be # mat := MatJacobianMatrix( F, gens );
mat := GroupExtEquations( d, gens, rels );
# now solve them modulo integers
ext := SolveHomEquationsModZ( mat );
# collect group extensions which are equivalent as space groups
lst := CollectEquivExtensions( ext[1], ext[2], norm, grp );
# make the space groups if orbsflag then
res := List( lst, x -> List( x,
y -> MakeSpaceGroup( d, gens, y, transpose ) ) ); else
res := List( lst, x -> MakeSpaceGroup( d, gens, x[1], transpose ) ); fi;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.