Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

563665 views
1
#include "typedef.h"
2
#include "gmp.h"
3
#include "longtools.h"
4
#include "matrix.h"
5
#include "bravais.h"
6
7
/***************************************************************************
8
@
9
@ --------------------------------------------------------------------------
10
@
11
@ FILE: row_spin.c
12
@
13
@ --------------------------------------------------------------------------
14
@
15
****************************************************************************/
16
17
static void product_of_stairs(MP_INT *x,MP_INT **A,int rows,int cols)
18
{
19
int i,
20
j;
21
22
mpz_set_si(x,1);
23
24
for (i=0;i<rows;i++){
25
for (j=0;j<cols && (mpz_cmp_si(A[i]+j,0) ==0);j++);
26
mpz_mul(x,x,A[i]+j);
27
}
28
29
mpz_abs(x,x);
30
31
return;
32
}
33
34
/*************************************************************************
35
@
36
@-------------------------------------------------------------------------
37
@
38
@ matrix_TYP *row_spin(matrix_TYP *x,matrix_TYP **G,int no,int option)
39
@
40
@ The function calculates a basis for the R module <x_i>_RG, where
41
@ x_i are the rows of x, G is assumed to be generated by the matrices G[i]
42
@ for 0 <= i <= no, and R is one of the rings Z or Q.
43
@ NOTE: this function will handle non integral matrices in G[i] as well.
44
@
45
@ matrix_TYP *x: see above. x is changed via kgv2rat and long_row_hnf.
46
@ matrix_TYP **G: see above. It is also changed by rat2kgv for each entry in G.
47
@ int no : will not be changed.
48
@ option : drives the behaviour of the function. in case
49
@ option % 2 == 0 it performs a Z-spinning algorithm,
50
@ option % 2 == 1 it performs a Q-spinning algorithm,
51
@ option % 4 == 0 perform a pair_red after spinning
52
@ the lattice. ONLY IN CONJUNCTION WITH
53
@ Z-spinning
54
@-------------------------------------------------------------------------
55
@
56
*************************************************************************/
57
matrix_TYP *row_spin(matrix_TYP *x,matrix_TYP **G,int no,int option)
58
{
59
int i,
60
j,
61
k,
62
l,
63
dim = x->cols,
64
rows = x->rows,
65
new_rows;
66
67
matrix_TYP *res;
68
69
long quot;
70
71
MP_INT **A,
72
**Gram,
73
**TR,
74
*merk,
75
tmp,
76
prod,
77
denominator;
78
79
/* check trivialities */
80
rat2kgv(x);
81
for (i=0;i<no;i++){
82
rat2kgv(G[i]);
83
if (G[i]->cols != dim || G[i]->rows!= dim){
84
fprintf(stderr,"error in row_spin:\n");
85
fprintf(stderr,"The %d-th given matrix is %dx%d,\n",
86
i,G[i]->rows,G[i]->cols);
87
exit(3);
88
}
89
}
90
91
/* inserted tilman 22/07/97 */
92
long_row_hnf(x);
93
94
/* prepare all the things */
95
if (x->rows>dim){
96
A = init_MP_mat(x->rows+1,dim);
97
}
98
else{
99
A = init_MP_mat(dim+1,dim);
100
}
101
for (i=0;i<rows;i++)
102
for (j=0;j<dim;j++)
103
mpz_set_si(A[i]+j,x->array.SZ[i][j]);
104
mpz_init(&tmp);
105
mpz_init_set_ui(&prod,0);
106
mpz_init_set_si(&denominator,x->kgv);
107
108
for (i=0;i<rows;i++){
109
for (j=0;j<no;j++){
110
/* multiply the the i-th row in A with the j-th generator in G,
111
and stick it in the rows-th row */
112
for (k=0;k<dim;k++){
113
mpz_set_si(A[rows]+k,0);
114
for (l=0;l<dim;l++){
115
/* A[rows][k] += A[i][l] * G[j]->array.SZ[k][l] */
116
mpz_set_si(&tmp,G[j]->array.SZ[l][k]);
117
mpz_mul(&tmp,&tmp,A[i]+l);
118
mpz_add(A[rows]+k,A[rows]+k,&tmp);
119
}
120
}
121
122
/* bare in mind what with the denominator happen */
123
if (G[j]->kgv != 1 && (option % 2 == 0)){
124
/* calculate the gcd of the rows-th row of A with G[j]->kgv */
125
mpz_set_si(&tmp,G[j]->kgv);
126
for (k=0;k<dim && mpz_cmp_si(&tmp,1)!=0;k++)
127
mpz_gcd(&tmp,&tmp,A[rows]+k);
128
129
/* divide all entries in the rows-th row of A by this gcd */
130
if (mpz_cmp_si(&tmp,1) !=0)
131
for (k=0;k<dim;k++)
132
mpz_div(A[rows]+k,A[rows]+k,&tmp);
133
134
/* now we have to destinguish two cases, the first (and
135
good) of which is that G[j]->kgv/tmp == 1, then the
136
denominator will not be changed. otherwise multiply
137
denominator by this quotient and multiply the rest of
138
A by it */
139
quot = abs(G[j]->kgv/mpz_get_si(&tmp));
140
if (quot != 1)
141
for (k=0;k<rows;k++)
142
for (l=0;l<dim;l++)
143
mpz_mul_ui(A[k]+l,A[k]+l,(unsigned long) quot);
144
145
mpz_mul_ui(&denominator,&denominator,(unsigned long)quot);
146
}
147
148
/* apply gauss */
149
new_rows = MP_row_gauss(A,rows+1,dim);
150
/* dump_MP_mat(A,new_rows,dim,"A vor"); */
151
152
/* make manhattan as far as feassible */
153
MP_row_gauss_reverse(A,new_rows,dim,option % 2);
154
155
/* dump_MP_mat(A,new_rows,dim,"A nach");
156
mpz_out_str(stdout,10,&denominator);
157
fprintf(stdout,"\n");
158
fflush(stdout); */
159
160
/* for a Q-spin the dimension is sufficient to describe the space */
161
if ((option % 2 == 1) && new_rows != rows){
162
i = 0;
163
j = 0;
164
}
165
166
/* for a Z-spin, compare the product of the elements of A
167
which are stair indices */
168
if (option == 0){
169
product_of_stairs(&tmp,A,new_rows,dim);
170
/* mpz_out_str(stdout,10,&prod);
171
fprintf(stdout,"\n");
172
mpz_out_str(stdout,10,&tmp);
173
fprintf(stdout,"\n");
174
fflush(stdout); */
175
if (mpz_cmp_si(&prod,0) == 0 ||
176
mpz_cmp(&prod,&tmp) != 0 ||
177
new_rows != rows){
178
i = 0;
179
j = 0;
180
}
181
mpz_set(&prod,&tmp);
182
}
183
184
rows = new_rows;
185
}
186
}
187
188
/* I like a good basis, so what's up with pair_red */
189
if (option % 2 == 0 || option % 4 == 0){
190
/* set the gram matrix */
191
Gram = init_MP_mat(rows,rows);
192
for (i=0;i<rows;i++){
193
for (j=0;j<rows;j++){
194
for (k=0;k<dim;k++){
195
/* Gram[i][j] += A[i][k]*A[j][k] */
196
mpz_mul(&tmp,A[i]+k,A[j]+k);
197
mpz_add(Gram[i]+j,Gram[i]+j,&tmp);
198
}
199
}
200
}
201
/* set the transformation matrix and do the pair_red */
202
TR = init_MP_mat(rows,rows);
203
for (i=0;i<rows;i++) mpz_set_si(TR[i]+i,1);
204
MP_pair_red(Gram,TR,rows);
205
206
free_MP_mat(Gram,rows,rows);
207
Gram = init_MP_mat(rows,dim);
208
209
/* multiply TR with A, stick it to Gram for a moment */
210
for (i=0;i<rows;i++){
211
for (j=0;j<dim;j++){
212
for (k=0;k<rows;k++){
213
/* Gram[i][j] += TR[i][k] * A[k][j] */
214
mpz_mul(&tmp,TR[i]+k,A[k]+j);
215
mpz_add(Gram[i]+j,Gram[i]+j,&tmp);
216
}
217
}
218
}
219
220
/* stick it back to A, and swap the pointers only */
221
for (i=0;i<rows;i++){
222
merk = A[i];
223
A[i] = Gram[i];
224
Gram[i] = merk;
225
}
226
227
/* we won't need TR and Gram anymore */
228
free_MP_mat(TR,rows,rows);
229
free_MP_mat(Gram,rows,dim);
230
}
231
232
res = init_mat(rows,dim,"");
233
write_MP_mat_to_matrix(res,A);
234
235
if (abs(denominator._mp_size>1)){
236
fprintf(stderr,"denominator in row_spin to large!\n");
237
fprintf(stderr,"(I thought this to be impossible)\n");
238
exit(3);
239
}
240
241
if (option == 0){
242
res->kgv = mpz_get_si(&denominator);
243
}
244
else{
245
res->kgv = 1;
246
}
247
248
Check_mat(res);
249
250
/* clear space */
251
if (x->rows>dim){
252
free_MP_mat(A,x->rows+1,dim);
253
}
254
else{
255
free_MP_mat(A,dim+1,dim);
256
}
257
free(A);
258
mpz_clear(&tmp);
259
mpz_clear(&denominator);
260
261
return res;
262
}
263
264
/**********************************************************************
265
@ bravais_TYP *representation_on_lattice(matrix_TYP *x,bravais_TYP *G,
266
@ int option)
267
@
268
@
269
***********************************************************************/
270
bravais_TYP *representation_on_lattice(matrix_TYP *x,bravais_TYP *G,
271
int option)
272
{
273
274
int i,
275
j;
276
277
bravais_TYP *H;
278
279
matrix_TYP *xtr,
280
*y,
281
*z,
282
**X;
283
284
/* init H as far as possible in this stage */
285
H = init_bravais(G->dim);
286
H->gen = (matrix_TYP **) malloc(G->gen_no * sizeof(matrix_TYP *));
287
H->gen_no = G->gen_no;
288
289
xtr = tr_pose(x);
290
291
for (i=0;i<H->gen_no;i++){
292
/* map x by the first generator of H */
293
y = mat_mul(x,G->gen[i]);
294
z = tr_pose(y);
295
296
/* firstly try to solve the GLS over a prime
297
p_lse_solve(); */
298
299
/* if this goes wrong, to it the hard way and solve it via Z */
300
X = long_solve_mat(xtr,z);
301
302
/* paranoia */
303
if (X[1] != NULL){
304
if (X[1]->cols!=0){
305
fprintf(stderr,"error in representation_on_lattice, X[1] wrong\n");
306
exit(3);
307
}
308
free_mat(X[1]);
309
}
310
311
H->gen[i] = tr_pose(X[0]);
312
313
free_mat(X[0]);
314
free(X);
315
free_mat(z);
316
free_mat(y);
317
318
}
319
320
/* clear up */
321
free_mat(xtr);
322
323
return H;
324
}
325
326
/****************************************************************************
327
@
328
@----------------------------------------------------------------------------
329
@
330
@ matrix_TYP *translation_lattice(matrix_TYP **G,int number,matrix_TYP *P)
331
@
332
@ Calculates a basis of the translation lattice of the space group
333
@ generated by the matrices given in G[i], 0<= i < number.
334
@ This lattice is returned via a matrix containing the columns of a basis
335
@ of the lattice (without the affine '1').
336
@
337
@ matrix_TYP **G : Generators for the spacegroup.
338
@ int number : see above
339
@ matrix_TYP *P : a matrix containing a presentation for the point group
340
@ to the space group. It has to be a presentation according
341
@ to the generators G[i], i.e { G[i] * T }/T fullfill
342
@ the relations given in P.
343
@
344
@----------------------------------------------------------------------------
345
@
346
*****************************************************************************/
347
matrix_TYP *translation_lattice(matrix_TYP **G,int number,matrix_TYP *P)
348
{
349
350
int i,
351
j,
352
k,
353
lcm;
354
355
matrix_TYP **Gtr,
356
**Ginv,
357
*B,
358
*X,
359
*Y;
360
361
/* check all the trivialities to avoid trouble */
362
for (i=0;i<number;i++){
363
rat2kgv(G[i]);
364
if (G[i]->cols != G[0]->cols ||
365
G[i]->rows != G[0]->cols){
366
fprintf(stderr,"uncompatible dimensions in translation_lattice\n");
367
exit(3);
368
}
369
}
370
371
/* init all the needed stuff */
372
Gtr = (matrix_TYP **) malloc(number * sizeof(matrix_TYP *));
373
for (i=0;i<number;i++) Gtr[i]=tr_pose(G[i]);
374
Ginv = (matrix_TYP **) calloc(number , sizeof(matrix_TYP *));
375
Y = init_mat(P->rows,G[0]->cols-1,"");
376
377
for (i=0;i<P->rows;i++){
378
X = init_mat(G[0]->cols,G[0]->cols,"1");
379
for (j=0;j<P->cols;j++){
380
if (P->array.SZ[i][j] != 0){
381
if (abs(P->array.SZ[i][j]) > number){
382
fprintf(stderr,"translation_lattice: you asked for the %d-th"
383
,P->array.SZ[i][j]);
384
fprintf(stderr," generator,\n but gave only %d\n",number);
385
exit(3);
386
}
387
388
/* the generator should be there */
389
if (P->array.SZ[i][j] > 0){
390
mat_muleq(X,G[P->array.SZ[i][j]-1]);
391
}
392
else if (P->array.SZ[i][j] < 0){
393
if (Ginv[-P->array.SZ[i][j]-1] == NULL)
394
Ginv[-P->array.SZ[i][j]-1] = mat_inv(G[-P->array.SZ[i][j]-1]);
395
mat_muleq(X,Ginv[-P->array.SZ[i][j]-1]);
396
}
397
Check_mat(X);
398
}
399
400
}
401
402
/* now we should have a trivial linear part in X, and the last
403
column of X gives a translation */
404
405
/* check whether the linear part is indeed trivial */
406
rat2kgv(X);
407
for (j=0;j<X->cols-1;j++){
408
for (k=0;k<X->rows-1;k++){
409
if ((k==j && X->array.SZ[k][j] != X->kgv) ||
410
(k!=j && X->array.SZ[k][j] != 0)){
411
fprintf(stderr,"translation_lattice: the linear part is not\n");
412
fprintf(stderr,"trivial. exiting!\n");
413
exit(3);
414
}
415
}
416
}
417
418
/* stick the resulting translation into Y */
419
lcm = X->kgv * Y->kgv/ GGT(X->kgv,Y->kgv);
420
if (lcm != Y->kgv)
421
for (j=0;j<i;j++)
422
for (k=0;k<Y->cols;k++)
423
Y->array.SZ[j][k] *= (lcm/Y->kgv);
424
425
Y->kgv = lcm;
426
427
for (j=0;j<X->rows-1;j++)
428
Y->array.SZ[i][j] = X->array.SZ[j][X->cols-1] * (lcm/X->kgv);
429
430
free_mat(X);
431
}
432
433
/* spin these (row) vector by Gtr */
434
for (i=0;i<number;i++) real_mat(Gtr[i],Gtr[i]->rows-1,Gtr[i]->cols-1);
435
X = row_spin(Y,Gtr,number,0);
436
437
B = tr_pose(X);
438
439
/* clear all the stuff */
440
for (i=0;i<number;i++) free_mat(Gtr[i]);
441
free(Gtr);
442
for (i=0;i<number;i++) if (Ginv[i] != NULL) free_mat(Ginv[i]);
443
free(Ginv);
444
free_mat(X);
445
free_mat(Y);
446
447
return B;
448
449
}
450
451