source: util/src/NanoCreator.c@ e1a46d

Last change on this file since e1a46d was e1a46d, checked in by Frederik Heber <heber@…>, 16 years ago

All of my python script put into ESPACK and adapted with @PYTHON@ and so on.

  • Property mode set to 100644
File size: 63.9 KB
Line 
1#include <stdlib.h>
2#include <stdio.h>
3#include <string.h>
4#include <math.h>
5#include <time.h>
6
7#include <gsl/gsl_matrix.h>
8#include <gsl/gsl_vector.h>
9#include <gsl/gsl_eigen.h>
10#include <gsl/gsl_blas.h>
11
12#include "NanoCreator.h"
13
14
15// ---------------------------------- F U N C T I O N S ----------------------------------------------
16
17// ================================= File functions ==============================
18
19#define LINE_SIZE 80
20#define NDIM 3
21
22/** Allocs memory and prints a message on fail.
23 * \param *size size of alloc in bytes
24 * \param *msg error msg
25 * \return pointer to allocated memory
26 */
27void * Malloc (size_t size, const char *msg)
28{
29 void *ptr = malloc(size);
30 if (ptr == NULL) {
31 if (msg == NULL)
32 fprintf(stdout, "ERROR: Malloc\n");
33 else
34 fprintf(stdout, "ERROR: Malloc - %s\n", msg);
35 return NULL;
36 } else {
37 return ptr;
38 }
39}
40
41/** Callocs memory and prints a message on fail.
42 * \param *size size of alloc in bytes
43 * \param *value pointer to initial value
44 * \param *msg error msg
45 * \return pointer to allocated memory
46 */
47void * Calloc (size_t size, double value, const char *msg)
48{
49 void *ptr = calloc(size, value);
50 if (ptr == NULL) {
51 if (msg == NULL)
52 fprintf(stdout, "ERROR: Calloc\n");
53 else
54 fprintf(stdout, "ERROR: Calloc - %s\n", msg);
55 return NULL;
56 } else {
57 return ptr;
58 }
59}
60
61/** Frees memory only if ptr != NULL.
62 * \param *ptr pointer to array
63 * \param *msg
64 */
65void Free(void * ptr, const char *msg)
66{
67 if (ptr != NULL)
68 free(ptr);
69 else {
70 if (msg == NULL)
71 fprintf(stdout, "ERROR: Free\n");
72 else
73 fprintf(stdout, "ERROR: Free - %s\n", msg);
74 }
75}
76
77/** Allocs memory and prints a message on fail.
78 * \param **old_ptr pointer to old memory range
79 * \param *newsize new size of alloc in bytes
80 * \param *msg error msg
81 * \return pointer to allocated memory
82 */
83void * Realloc (void *old_ptr, size_t newsize, const char *msg)
84{
85 if (old_ptr == NULL) {
86 fprintf(stdout, "ERROR: Realloc - old_ptr NULL\n");
87 exit(255);
88 }
89 void *ptr = realloc(old_ptr, newsize);
90 if (ptr == NULL) {
91 if (msg == NULL)
92 fprintf(stdout, "ERROR: Realloc\n");
93 else
94 fprintf(stdout, "ERROR: Realloc - %s\n", msg);
95 return NULL;
96 } else {
97 return ptr;
98 }
99}
100
101/** Reads a file's contents into a char buffer of appropiate size.
102 * \param *filename name of file
103 * \param pointer to integer holding read/allocated buffer length
104 * \return pointer to allocated segment with contents
105 */
106char * ReadBuffer (char *filename, int *bufferlength)
107{
108 if ((filename == NULL) || (bufferlength == NULL)) {
109 fprintf(stderr, "ERROR: ReadBuffer - ptr to filename or bufferlength NULL\n");
110 exit(255);
111 }
112 char *buffer = Malloc(sizeof(char)*LINE_SIZE, "ReadBuffer: buffer");
113 int i = 0, number;
114 FILE *file = fopen(filename, "r");
115 if (file == NULL) {
116 fprintf(stderr, "File open error: %s", filename);
117 exit(255);
118 }
119 while ((number = fread(&buffer[i], sizeof(char), LINE_SIZE, file)) == LINE_SIZE) {
120 //fprintf(stdout, "%s", &buffer[i]);
121 i+= LINE_SIZE;
122 buffer = (char *) Realloc(buffer, i+LINE_SIZE, "ReadBuffer: buffer");
123 }
124 fclose(file);
125 fprintf(stdout, "Buffer length is %i\n", i);
126 *bufferlength = i+(number);
127 return buffer;
128}
129
130/** Extracts next line out of a buffer.
131 * \param *buffer buffer to parse for newline
132 * \param *line contains complete line on return
133 * \return length of line, 0 if end of file
134 */
135int GetNextline(char *buffer, char *line)
136{
137 if ((buffer == NULL) || (line == NULL)) {
138 fprintf(stderr, "ERROR: GetNextline - ptr to buffer or line NULL\n");
139 exit(255);
140 }
141 int length;
142 char *ptr = strchr(buffer, '\n');
143 //fprintf(stdout, "Newline at %p from %p\n", ptr, buffer);
144 if (ptr == NULL) { // buffer ends
145 return 0;
146 } else {
147 //fprintf(stdout, "length of line is %d\n", length);
148 length = (int)(ptr - buffer)/sizeof(char);
149 strncpy(line, buffer, length);
150 line[length]='\0';
151 return length+1;
152 }
153}
154
155/** Adds commentary stuff (needed for further stages) to Cell xyz files.
156 * \param *filename file name
157 * \param atomicnumner number of atoms in xyz
158 * \param **Vector list of three unit cell vectors
159 * \param **Recivector list of three reciprocal unit cell vectors
160 * \param atomicnumber number of atoms in cell
161 */
162void AddAtomicNumber(char *filename, int atomicnumber, double **Vector, double **Recivector)
163{
164 if ((filename == NULL) || (Vector == NULL) || (Recivector == NULL)) {
165 fprintf(stdout, "ERROR: AddAtomicNumber - ptr to filename, Vector or Recivector NULL\n");
166 exit(255);
167 }
168 int bufferlength;
169 char *buffer = ReadBuffer(filename, &bufferlength);
170 FILE *file2 = fopen(filename, "w+");
171 if (file2 == NULL) {
172 fprintf(stdout, "ERROR: AddAtomicNumber: %s can't open for writing\n", filename);
173 exit(255);
174 }
175 double volume = Determinant(Vector);
176 time_t now;
177
178 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time'
179 // open for writing and prepend
180 fprintf(file2,"%d\n", atomicnumber); // 2
181 fprintf(file2,"\tgenerated with Nanotube creator on %s", ctime(&now));
182 fwrite(buffer, sizeof(char), bufferlength, file2); // append buffer
183
184 // Add primitive vectors as comment
185 fprintf(file2,"\n****************************************\n\n");
186 fprintf(file2,"Primitive vectors\n");
187 fprintf(file2,"a(1) = %f\t%f\t%f\n", Vector[0][0], Vector[0][1], Vector[0][2]);
188 fprintf(file2,"a(2) = %f\t%f\t%f\n", Vector[1][0], Vector[1][1], Vector[1][2]);
189 fprintf(file2,"a(3) = %f\t%f\t%f\n", Vector[2][0], Vector[2][1], Vector[2][2]);
190 fprintf(file2,"\nVolume = %f", volume);
191 fprintf(file2,"\nReciprocal Vectors\n");
192 fprintf(file2,"b(1) = %f\t%f\t%f\n", Recivector[0][0], Recivector[0][1], Recivector[0][2]);
193 fprintf(file2,"b(2) = %f\t%f\t%f\n", Recivector[1][0], Recivector[1][1], Recivector[1][2]);
194 fprintf(file2,"b(3) = %f\t%f\t%f\n", Recivector[2][0], Recivector[2][1], Recivector[2][2]);
195
196 fclose(file2); // close file
197 Free(buffer, "AddAtomicNumber: buffer");
198}
199
200/** Adds commentary stuff (needed for further stages) to Sheet xyz files.
201 * \param *filename file name
202 * \param *axis array with major, minor and no axis
203 * \param *chiral pointer to array with both chiral values
204 * \param *factors pointer to array with length and radius factor
205 * \param seed random number seed
206 * \param numbercell number of atoms in unit cell, needed as length of \a *randomness
207 * \param *randomness for each atom in unit cell a factor between 0..1, giving its probability of appearance
208 */
209void AddSheetInfo(char *filename, int *axis, int *chiral, int *factors, int seed, int numbercell, double *randomness)
210{
211 int i;
212 if ((filename == NULL) || (axis == NULL) || (chiral == NULL) || (factors == NULL)) {
213 fprintf(stdout, "ERROR: AddSheetInfo - ptr to filename, axis, chiral or factors NULL\n");
214 exit(255);
215 }
216 // open for writing and append
217 FILE *file2 = fopen(filename,"a");
218 if (file2 == NULL) {
219 fprintf(stderr, "ERROR: AddSheetInfo - can't open %s for appending\n", filename);
220 exit(255);
221 }
222 // Add primitive vectors as comment
223 fprintf(file2,"\n****************************************\n\n");
224 fprintf(file2,"Axis %d\t%d\t%d\n", axis[0], axis[1], axis[2]);
225 fprintf(file2,"(n,m) %d\t%d\n", chiral[0], chiral[1]);
226 fprintf(file2,"factors %d\t%d\n", factors[0], factors[1]);
227 fprintf(file2,"seed %d\n", seed);
228 fprintf(file2,"\nRandomness\n");
229 for (i=0; i<numbercell; i++) {
230 fprintf(file2,"%d %g\n", i, randomness[i]);
231 }
232 fclose(file2);
233}
234
235
236// ================================= Vector functions ==============================
237
238/** Transforms a vector b with a matrix A: Ab = x.
239 * \param **matrixref reference to NDIMxNDIM matrix A
240 * \param *vectorref reference to NDIM vector b
241 * \return reference to resulting NDIM vector Ab = x
242 */
243double *MatrixTrafo(double **matrixref, double *vectorref)
244{
245 if ((matrixref == NULL) || (vectorref == NULL)) {
246 fprintf(stderr, "ERROR: MatrixTrafo: ptr to matrixref or vectorref NULL\n");
247 exit(255);
248 }
249 //double *returnvector = Calloc(sizeof(double)*NDIM, 0., "MatrixTrafo: returnvector");
250 double *returnvector = calloc(sizeof(double)*NDIM, 0.);
251 if (returnvector == NULL) {
252 fprintf(stderr, "ERROR: MatrixTrafo - returnvector\n");
253 exit(255);
254 }
255 int i,j;
256
257 for (i=0;i<NDIM;i++)
258 for (j=0;j<NDIM;j++)
259 returnvector[j] += matrixref[i][j] * vectorref[i];
260
261 return returnvector;
262}
263double *MatrixTrafoInverse(double *vectorref, double **matrixref)
264{
265 if ((matrixref == NULL) || (vectorref == NULL)) {
266 fprintf(stderr, "ERROR: MatrixTrafo: ptr to matrixref or vectorref NULL\n");
267 exit(255);
268 }
269 //double *returnvector = Calloc(sizeof(double)*NDIM, 0., "MatrixTrafo: returnvector");
270 double *returnvector = calloc(sizeof(double)*NDIM, 0.);
271 if (returnvector == NULL) {
272 fprintf(stderr, "ERROR: MatrixTrafo - returnvector\n");
273 exit(255);
274 }
275 int i,j;
276
277 for (i=0;i<NDIM;i++)
278 for (j=0;j<NDIM;j++)
279 returnvector[i] += matrixref[i][j] * vectorref[j];
280
281 return returnvector;
282}
283
284/** Inverts a NDIMxNDIM matrix.
285 * \param **matrix to be inverted
286 * \param **inverse allocated space for inverse of \a **matrix
287 */
288void MatrixInversion(double **matrix, double **inverse)
289{
290 if ((matrix == NULL) || (inverse == NULL)) {
291 fprintf(stderr, "ERROR: MatrixInversion: ptr to matrix or inverse NULL\n");
292 exit(255);
293 }
294 // determine inverse
295 double det = Determinant(matrix);
296 inverse[0][0] = (matrix[1][1]*matrix[2][2] - matrix[1][2]*matrix[2][1])/det;
297 inverse[1][0] = (matrix[0][2]*matrix[2][1] - matrix[0][1]*matrix[2][2])/det;
298 inverse[2][0] = (matrix[0][1]*matrix[1][2] - matrix[0][2]*matrix[1][1])/det;
299 inverse[0][1] = (matrix[1][2]*matrix[2][0] - matrix[1][0]*matrix[2][2])/det;
300 inverse[1][1] = (matrix[0][0]*matrix[2][2] - matrix[0][2]*matrix[2][0])/det;
301 inverse[2][1] = (matrix[0][2]*matrix[1][0] - matrix[0][0]*matrix[1][2])/det;
302 inverse[0][2] = (matrix[1][0]*matrix[2][1] - matrix[1][1]*matrix[2][0])/det;
303 inverse[1][2] = (matrix[0][1]*matrix[2][0] - matrix[0][0]*matrix[2][1])/det;
304 inverse[2][2] = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0])/det;
305
306 // check inverse
307 int flag = 0;
308 int i,j,k;
309 double tmp;
310 fprintf(stdout, "Checking inverse ... ");
311 for (i=0;i<NDIM;i++)
312 for (j=0;j<NDIM;j++) {
313 tmp = 0.;
314 for (k=0;k<NDIM;k++)
315 tmp += matrix[i][k]*inverse[j][k];
316 if (!flag) {
317 if (i == j) {
318 flag = (fabs(1.-tmp) > MYEPSILON) ? 1 : 0;
319 } else {
320 flag = (fabs(tmp) > MYEPSILON) ? 1 : 0;
321 }
322 }
323 }
324 if (!flag)
325 fprintf(stdout, "ok\n");
326 else
327 fprintf(stdout, "false\n");
328}
329
330/** Flips to double numbers in place.
331 * \param *number1 pointer to first double
332 * \param *number2 pointer to second double
333 */
334void flip(double *number1, double *number2)
335{
336 if ((number1 == NULL) || (number2 == NULL)) {
337 fprintf(stderr, "ERROR: flip: ptr to number1 or number2 NULL\n");
338 exit(255);
339 }
340 double tmp = *number1;
341 *number1 = *number2;
342 *number2 = tmp;
343}
344
345/** Transposes a matrix.
346 * \param **matrix pointer to NDIMxNDIM-matrix array
347 */
348void Transpose(double **matrix)
349{
350 if (matrix == NULL) {
351 fprintf(stderr, "ERROR: Transpose: ptr to matrix NULL\n");
352 exit(255);
353 }
354 int i,j;
355 for (i=0;i<NDIM;i++)
356 for (j=0;j<i;j++)
357 flip(&matrix[i][j],&matrix[j][i]);
358}
359
360
361/** Computes the determinant of a NDIMxNDIM matrix.
362 * \param **matrix pointer to matrix array
363 * \return det(matrix)
364 */
365double Determinant(double **matrix) {
366 if (matrix == NULL) {
367 fprintf(stderr, "ERROR: Determinant: ptr to Determinant NULL\n");
368 exit(255);
369 }
370 double det = matrix[0][0] * (matrix[1][1]*matrix[2][2] - matrix[1][2]*matrix[2][1])
371 - matrix[1][1] * (matrix[0][0]*matrix[2][2] - matrix[0][2]*matrix[2][0])
372 + matrix[2][2] * (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
373 return det;
374}
375
376/** Adds \a *vector1 onto \a *vector2 coefficient-wise.
377 * \param *vector1 first vector, on return contains sum
378 * \param *vector2 vector which is projected
379 * \return sum of the two vectors
380 */
381double * VectorAdd(double *vector1, double *vector2)
382{
383 if ((vector1 == NULL) || (vector2 == NULL)) {
384 fprintf(stderr, "ERROR: VectorAdd: ptr to vector1 or vector2 NULL\n");
385 exit(255);
386 }
387 //double *returnvector = Calloc(sizeof(double)*NDIM, 0., "VectorAdd: returnvector");
388 double *returnvector = calloc(sizeof(double)*NDIM, 0.);
389 if (returnvector == NULL) {
390 fprintf(stderr, "ERROR: VectorAdd - returnvector\n");
391 exit(255);
392 }
393 int i;
394
395 for (i=0;i<NDIM;i++)
396 returnvector[i] = vector1[i] + vector2[i];
397
398 return returnvector;
399}
400
401/** Fixed GramSchmidt-Orthogonalization for NDIM vectors
402 * \param @orthvector reference to NDIMxNDIM matrix
403 * \param @orthbetrag reference to NDIM vector with vector magnitudes
404 * \param @axis major-, minor- and noaxis for specific order for the GramSchmidt procedure
405 */
406void Orthogonalize(double **orthvector, int *axis)
407{
408 if ((orthvector == NULL) || (axis == NULL)) {
409 fprintf(stderr, "ERROR: Orthogonalize: ptr to orthvector or axis NULL\n");
410 exit(255);
411 }
412 double betrag;
413 int i;
414
415 // first vector is untouched
416 // second vector
417 betrag = Projection(orthvector[axis[1]], orthvector[axis[0]]);
418 fprintf(stdout,"%lg\t",betrag);
419 for (i=0;i<NDIM;i++)
420 orthvector[axis[1]][i] -= orthvector[axis[0]][i] * betrag;
421 // third vector
422 betrag = Projection(orthvector[axis[0]], orthvector[axis[2]]);
423 fprintf(stdout,"%lg\t",betrag);
424 for (i=0;i<NDIM;i++)
425 orthvector[axis[2]][i] -= orthvector[axis[0]][i] * betrag;
426 betrag = Projection(orthvector[axis[1]], orthvector[axis[2]]);
427 fprintf(stdout,"%lg\n",betrag);
428 for (i=0;i<NDIM;i++)
429 orthvector[axis[2]][i] -= orthvector[axis[1]][i] * betrag;
430}
431
432/** Computes projection of \a *vector2 onto \a *vector1.
433 * \param *vector1 reference vector
434 * \param *vector2 vector which is projected
435 * \return projection
436 */
437double Projection(double *vector1, double *vector2)
438{
439 if ((vector1 == NULL) || (vector2 == NULL)) {
440 fprintf(stderr, "ERROR: Projection: ptr to vector1 or vector2 NULL\n");
441 exit(255);
442 }
443 return (ScalarProduct(vector1, vector2)/Norm(vector1)/Norm(vector2));
444}
445
446/** Determine scalar product between two vectors.
447 * \param *vector1 first vector
448 * \param *vector2 second vector
449 * \return scalar product
450 */
451double ScalarProduct(double *vector1, double *vector2)
452{
453 if ((vector1 == NULL) || (vector2 == NULL)) {
454 fprintf(stderr, "ERROR: ScalarProduct: ptr to vector1 or vector2 NULL\n");
455 exit(255);
456 }
457 double scp = 0.;
458 int i;
459
460 for (i=0;i<NDIM;i++)
461 scp += vector1[i] * vector2[i];
462
463 return scp;
464}
465
466/** Computes norm of \a *vector.
467 * \param *vector pointer to NDIM vector
468 * \return norm of \a *vector
469 */
470double Norm(double *vector)
471{
472 if (vector == NULL) {
473 fprintf(stderr, "ERROR: Norm: ptr to vector NULL\n");
474 exit(255);
475 }
476 return sqrt(ScalarProduct(vector, vector));
477}
478
479/** Prints vector to \a *file.
480 * \param *file file or e.g. stdout
481 * \param *vector vector to be printed
482 */
483void PrintVector(FILE *file, double *vector)
484{
485 if ((file == NULL) || (vector == NULL)) {
486 fprintf(stderr, "ERROR: PrintVector: ptr to file or vector NULL\n");
487 exit(255);
488 }
489 int i;
490 for (i=0;i<NDIM;i++)
491 fprintf(file, "%5.5f\t", vector[i]);
492 fprintf(file, "\n");
493}
494
495/** Prints matrix to \a *file.
496 * \param *file file or e.g. stdout
497 * \param **matrix matrix to be printed
498 */
499void PrintMatrix(FILE *file, double **matrix)
500{
501 if ((file == NULL) || (matrix == NULL)) {
502 fprintf(stderr, "ERROR: PrintMatrix: ptr to file or matrix NULL\n");
503 exit(255);
504 }
505 int i,j;
506 for (i=0;i<NDIM;i++) {
507 for (j=0;j<NDIM;j++)
508 fprintf(file, "%5.5f\t", matrix[i][j]);
509 fprintf(file, "\n");
510 }
511}
512
513/** Returns greatest common denominator.
514 * \param a first integer
515 * \param b second integer
516 * \return GCD of a and b
517 */
518int GCD(int a, int b)
519{
520 int c;
521 do {
522 c = a % b; /* Rest of integer divison */
523 a = b; b = c; /* flip the two values */
524 } while( c != 0);
525 return a;
526}
527
528/** Determines the biggest diameter of a sheet.
529 * \param **matrix reference to NDIMxNDIM matrix with row vectors
530 * \param *axis reference to NDIM vector with permutation of axis indices [0,1,2]
531 * \param *factors factorsfor axis[0] and axis[1]
532 * \return biggest diameter of sheet
533*/
534double DetermineBiggestDiameter(double **matrix, int *axis, int *factors)
535{
536 if ((axis == NULL) || (factors == NULL) || (matrix == NULL)) {
537 fprintf(stderr, "ERROR: DetermineBiggestDiameter: ptr to factors, axis or matrix NULL\n");
538 exit(255);
539 }
540 double diameter[2] = {0.,0.};
541 int i, biggest;
542
543 for (i=0;i<NDIM;i++) {
544 diameter[0] += (matrix[axis[0]][i]*factors[0] - matrix[axis[1]][i]*factors[1]) * (matrix[axis[0]][i]*factors[0] - matrix[axis[1]][i]*factors[1]);
545 diameter[1] += (matrix[axis[0]][i]*factors[0] + matrix[axis[1]][i]*factors[1]) * (matrix[axis[0]][i]*factors[0] + matrix[axis[1]][i]*factors[1]);
546 }
547 if ((diameter[0] - diameter[1]) > MYEPSILON) {
548 biggest = 0;
549 } else {
550 biggest = 1;
551 }
552 diameter[0] = sqrt(diameter[0]);
553 diameter[1] = sqrt(diameter[1]);
554 fprintf(stdout, "\n\nMajor diameter of the sheet is %5.5f, minor diameter is %5.5f.\n",diameter[biggest],diameter[(biggest+1)%2]);
555
556 return diameter[biggest];
557}
558
559/** Determines the center of gravity of atoms in a buffer \a bufptr with given \a number
560 * \param *bufptr pointer to char buffer with atoms in (name x y z)-manner
561 * \param number number of atoms/lines to scan
562 * \return NDIM vector (allocated doubles) pointing back to center of gravity
563 */
564double * CenterOfGravity(char *bufptr, int number)
565{
566 if (bufptr == NULL) {
567 fprintf(stderr, "ERROR: CenterOfGravity - bufptr NULL\n");
568 exit(255);
569 }
570 double *cog = calloc(sizeof(double)*NDIM, 0.);
571 if (cog == NULL) {
572 fprintf(stderr, "ERROR: CenterOfGravity - cog\n");
573 exit(255);
574 }
575 double *atom = Malloc(sizeof(double)*NDIM, "CenterOfGravity: atom");
576 char name[255], line[255];
577 int i,j;
578
579 // Determine center of gravity
580 for (i=0;i<number;i++) {
581 bufptr += GetNextline(bufptr, line);
582 sscanf(line, "%s %lg %lg %lg", name, &atom[0], &atom[1], &atom[2]);
583 //fprintf(stdout, "Read Atom %s %lg %lg %lg\n", name, atom[0], atom[1], atom[2]);
584 for (j=0;j<NDIM;j++)
585 cog[j] += atom[j];
586 }
587 for (i=0;i<NDIM;i++)
588 cog[i] /= -number;
589
590 Free(atom, "CenterOfGravity: atom");
591 return cog;
592}
593
594/** Creates orthogonal vectors to directions axis[0] and axis[1], assuming that axis[2] is always orthogonal.
595 * \param **OrthoVector contains vectors set on return with axis[2] equal to Vector[axis[2]]
596 * \param **Vector vectors to orthogonalize against
597 * \param *axis lookup for which direction is which.
598 */
599void CreateOrthogonalAxisVectors(double **OrthoVector, double **Vector, int *axis) {
600 int i,j;
601 double factor;
602 // allocate memory
603 int *TempAxis = (int *) Malloc(sizeof(int)*NDIM, "Main: *TempAxis");
604 double **TempVectors = (double **) Malloc(sizeof(double *)*NDIM, "Main: *TempVectors");
605 for (i=0; i<NDIM; i++)
606 TempVectors[i] = (double *) Malloc(sizeof(double)*NDIM, "Main: TempVectors");
607
608 for (i=0; i<NDIM; i++)
609 for (j=0; j<NDIM; j++)
610 TempVectors[i][j] = Vector[i][j];
611 // GramSchmidt generates Vector[1] orthogonal to Vector[0] and Vector[2] ortho. to Vector[1] and Vector[0]!
612 TempAxis[0] = axis[2]; // (axis 2 is the orthogonal plane axis)
613 TempAxis[1] = axis[0];
614 TempAxis[2] = axis[1];
615 Orthogonalize(TempVectors, TempAxis);
616 factor = Norm(Vector[axis[0]])/Norm(TempVectors[TempAxis[2]]);
617 factor *= (Projection(TempVectors[TempAxis[2]], Vector[axis[0]]) > 0) ? 1. : -1.;
618 for (i=0; i<NDIM; i++)
619 OrthoVector[axis[0]][i] = TempVectors[TempAxis[2]][i]*factor;
620
621 TempAxis[1] = axis[1];
622 TempAxis[2] = axis[0];
623 for (i=0; i<NDIM; i++)
624 for (j=0; j<NDIM; j++)
625 TempVectors[i][j] = Vector[i][j];
626 Orthogonalize(TempVectors, TempAxis);
627 factor = Norm(Vector[axis[1]])/Norm(TempVectors[TempAxis[2]]);
628 factor *= (Projection(TempVectors[TempAxis[2]], Vector[axis[1]]) > 0) ? 1. : -1.;
629 for (i=0; i<NDIM; i++)
630 OrthoVector[axis[1]][i] = TempVectors[TempAxis[2]][i]*factor;
631
632 for (i=0; i<NDIM; i++)
633 OrthoVector[axis[2]][i] = Vector[axis[2]][i];
634 //print vectors
635 fprintf(stdout, "Orthogonal vectors are: \n");
636 for (i=0; i<NDIM; i++) {
637 for (j=0; j<NDIM; j++)
638 fprintf(stdout, "%lg\t", OrthoVector[axis[i]][j]);
639 fprintf(stdout, "\n");
640 }
641
642 // free memory
643 Free(TempAxis, "CreateOrthogonalAxisVectors: *TempAxis");
644 for (i=0; i<NDIM; i++ )
645 Free(TempVectors[i], "CreateOrthogonalAxisVectors: TempVectors");
646 Free(TempVectors, "CreateOrthogonalAxisVectors: *TempVectors");
647};
648
649// ================================= other functions ==============================
650
651/** Prints a debug message.
652 * \param *msg debug message
653 */
654void Debug(char *msg)
655{
656 if (msg == NULL) {
657 fprintf(stderr, "ERROR: Debug: ptr to msg NULL\n");
658 exit(255);
659 }
660 fprintf(stdout, "%s", msg);
661}
662
663
664// --------------------------------------- M A I N ---------------------------------------------------
665int main(int argc, char **argv) {
666 char *filename = NULL;
667 char *CellFilename = NULL, *SheetFilename = NULL, *TubeFilename = NULL, *TorusFilename = NULL;
668 char *SheetFilenameAligned = NULL, *TubeFilenameAligned = NULL;
669 double **Vector, **OrthoVector, **Recivector = NULL, **Tubevector = NULL, **TubevectorInverse = NULL;
670 double *atom = NULL, *atom_transformed = NULL;
671 double *x = NULL, *coord = NULL, *tempvector = NULL, *offset = NULL;
672 //double *cog = NULL, *cog_projected = NULL;
673 char stage[6];
674 int axis[NDIM] = {0,1,2}, chiral[2] = {1,1}, factors[NDIM] = {1,1,1};
675 char name[255], line[255], input = 'n';
676 char *CellBuffer = NULL, *SheetBuffer = NULL, *TubeBuffer = NULL, *bufptr = NULL;
677 double *randomness = NULL, percentage; // array with percentages for presence in sheet and beyond
678 int i,j, ggT;
679 int length;
680
681 // Read command line arguments
682 if (argc <= 2) {
683 fprintf(stdout, "Usage: %s <file> <stage>\n\tWhere <file> specifies a file to start from <stage> or a basename\n\t<stage> is either None, Cell, Sheet, Tube, Torus and specifies where to start the rolling up from.\n\tNote: The .Aligned. files can't be used (rotation is essential).\n", argv[0]);
684 exit(255);
685 } else {
686 // store variables
687 filename = argv[1];
688 strncpy(stage, argv[2], 5);
689 fprintf(stdout, "I will begin at stage %s.\n", stage);
690
691 // build filenames
692 char *ptr = strrchr(filename, '.');
693 length = strlen(filename);
694 if (ptr != NULL) {
695 length = ((int)(ptr-filename) >= length-5) ? (int)(ptr-filename) : length;
696 filename[length] = '\0'; // eventueller
697 }
698 fprintf(stdout, "I will use \'%s' as base for the filenames.\n\n", filename);
699 CellFilename = Malloc(sizeof(char)*(length+10), "Main: CellFilename");
700 SheetFilename = Malloc(sizeof(char)*(length+11), "Main: SheetFilename");
701 TubeFilename = Malloc(sizeof(char)*(length+10), "Main: TubeFilename");
702 TorusFilename = Malloc(sizeof(char)*(length+11), "Main: TorusFilename");
703 SheetFilenameAligned = Malloc(sizeof(char)*(length+20), "Main: SheetFilenameAligned");
704 TubeFilenameAligned = Malloc(sizeof(char)*(length+19), "Main: TubeFilenameAligned");
705 sprintf(CellFilename, "%s.Cell.xyz", filename);
706 sprintf(SheetFilename, "%s.Sheet.xyz", filename);
707 sprintf(TubeFilename, "%s.Tube.xyz", filename);
708 sprintf(TorusFilename, "%s.Torus.xyz", filename);
709 sprintf(SheetFilenameAligned, "%s.Sheet.Aligned.xyz", filename);
710 sprintf(TubeFilenameAligned, "%s.Tube.Aligned.xyz", filename);
711 }
712
713 // Allocating memory
714 Debug ("Allocating memory\n");
715 atom = (double *) Malloc(sizeof(double)*NDIM, "Main: atom");
716 Vector = (double **) Malloc(sizeof(double *)*NDIM, "Main: *Vector");
717 OrthoVector = (double **) Malloc(sizeof(double *)*NDIM, "Main: *OrthoVector");
718 Recivector = (double **) Malloc(sizeof(double *)*NDIM, "Main: *Recivector");
719 Tubevector = (double **) Malloc(sizeof(double *)*NDIM, "Main: *Tubevector");
720 TubevectorInverse = (double **) Malloc(sizeof(double *)*NDIM, "Main: *TubevectorInverse");
721 for (i=0; i<NDIM; i++ ) {
722 Vector[i] = (double *) Malloc(sizeof(double)*NDIM, "Main: Vector");
723 OrthoVector[i] = (double *) Malloc(sizeof(double)*NDIM, "Main: OrthoVector");
724 Recivector[i] = (double *) Malloc(sizeof(double)*NDIM, "Main: Recivector");
725 Tubevector[i] = (double *) Malloc(sizeof(double)*NDIM, "Main: Tubevector");
726 TubevectorInverse[i] = (double *) Malloc(sizeof(double)*NDIM, "Main: TubevectorInverse");
727 }
728
729 // ======================== STAGE: Cell ==============================
730 // The cell is simply created by transforming relative coordinates within the cell
731 // into cartesian ones using the unit cell vectors.
732
733 double volume;
734 int numbercell;
735 FILE *CellFile;
736
737 Debug ("STAGE: None\n");
738 // Read cell vectors from stdin or from file
739 if (!strncmp(stage, "Non", 3)) {
740 fprintf(stdout, "You will give the unit cell of the given substance.\nAfterwards, the programme will create a Sheet, a Tube and a Torus, each with their own xyz-file named accordingly.\n\n");
741 fprintf(stdout, "Enter 1st primitive vector: ");
742 fscanf(stdin, "%lg %lg %lg", &Vector[0][0], &Vector[0][1], &Vector[0][2]);
743 fprintf(stdout, "Enter 2nd primitive vector: ");
744 fscanf(stdin, "%lg %lg %lg", &Vector[1][0], &Vector[1][1], &Vector[1][2]);
745 fprintf(stdout, "Enter 3rd primitive vector: ");
746 fscanf(stdin, "%lg %lg %lg", &Vector[2][0], &Vector[2][1], &Vector[2][2]);
747 fprintf(stdout,"Unit vectors are\n");
748 PrintMatrix(stdout, Vector);
749 } else {
750 char *ptr = NULL;
751 char dummy[10];
752 CellBuffer = bufptr = ReadBuffer(CellFilename, &length);
753 for (i=0;i<NDIM;i++) {
754 sprintf(dummy, "a(%i) = ", i+1);
755 fprintf(stdout, "%s", dummy);
756 while ((length = GetNextline(bufptr, line)) != -1) {
757 bufptr += (length)*sizeof(char);
758 //fprintf(stdout, "LINE at %p: %s\n", bufptr, line);
759 if ((ptr = strstr(line, dummy)) != NULL)
760 break;
761 }
762 ptr += strlen(dummy);
763 sscanf(ptr, "%lg %lg %lg", &Vector[i][0], &Vector[i][1], &Vector[i][2]);
764 fprintf(stdout, "%5.5lg %5.5lg %5.5lg\n", Vector[i][0], Vector[i][1], Vector[i][2]);
765 }
766 }
767
768 volume = Determinant(Vector);
769 fprintf(stdout,"Volume is %lg\n", volume);
770 MatrixInversion(Vector, Recivector);
771 //Transpose(Recivector); // inverse's got row vectors if normal matrix' got column ones
772 fprintf(stdout, "Reciprocal vector is ");
773 PrintMatrix(stdout, Recivector);
774 fprintf(stdout, "Reciprocal volume is %lg\n", Determinant(Recivector));
775
776 fprintf(stdout, "Vector magnitudes: %5.5lg %5.5lg %5.5lg\n", Norm(Vector[0]), Norm(Vector[1]), Norm(Vector[2]));
777
778 Debug ("STAGE: Cell\n");
779 if (!strncmp(stage, "Non", 3)) {
780 fprintf(stdout, "\nHow many atoms are in the unit cell: ");
781 fscanf(stdin, "%i", &numbercell);
782 CellFile = fopen(CellFilename, "w");
783 if (CellFile == NULL) {
784 fprintf(stderr, "ERROR: main - can't open %s for writing\n", CellFilename);
785 exit(255);
786 }
787 fprintf(stdout, "\nNext, you have to enter each atom in the cell as follows, e.g.\n");
788 fprintf(stdout, "Enter \'ChemicalSymbol X Y Z\' (relative to primitive vectors): C 0.5 0.25 0.5\n\n");
789 for (i = 0; i < numbercell; i++) {
790 fprintf(stdout, "Enter for atom %i \'ChemicalSymbol X Y Z\': ", i+1);
791 fscanf(stdin, "%s %lg %lg %lg", name, &atom[0], &atom[1], &atom[2]);
792 tempvector = MatrixTrafo(Vector, atom);
793 fprintf(stdout, "Atom %i: %s %5.5lg %5.5lg %5.5lg\n", i, name, tempvector[0], tempvector[1], tempvector[2]);
794 fprintf(stdout, "Probe: %s %5.5lg %5.5lg %5.5lg\n", name,
795 atom[0]*Vector[0][0]+atom[1]*Vector[1][0]+atom[2]*Vector[2][0],
796 atom[0]*Vector[0][1]+atom[1]*Vector[1][1]+atom[2]*Vector[2][1],
797 atom[0]*Vector[0][2]+atom[1]*Vector[1][2]+atom[2]*Vector[2][2]
798 );
799 fprintf(CellFile, "%s %lg %lg %lg\n", name, tempvector[0], tempvector[1], tempvector[2]);
800 Free(tempvector, "Main: At stage Cell - tempvector");
801 }
802 fflush(CellFile);
803 fclose(CellFile);
804 AddAtomicNumber(CellFilename, numbercell, Vector, Recivector);
805
806 CellBuffer = ReadBuffer(CellFilename, &length);
807
808 sprintf(stage, "Cell");
809 } else {
810 bufptr = CellBuffer;
811 GetNextline(bufptr, line);
812 sscanf(line, "%i", &numbercell);
813 }
814
815 fprintf(stdout, "\nThere are %i atoms in the cell.\n", numbercell);
816
817 // ======================== STAGE: Sheet =============================
818 // The sheet is a bit more complex. We read the cell in cartesian coordinates
819 // from the file. Next, we have to rotate the unit cell vectors by the so called
820 // chiral angle. This gives a slanted and elongated section upon the sheet of
821 // periodically repeated original unit cells. It only matches up if the factors
822 // were all integer! (That's why the rotation is discrete and the chiral angle
823 // specified not as (cos alpha, sin alpha) but as (n,m)) Also, we want this
824 // section to be rectangular, thus we orthogonalize the original unit vectors
825 // to gain our (later) tube axis.
826 // By looking at the biggest possible diameter we know whose original cells to
827 // look at and check if their respective compounds (contained atoms) still reside
828 // in the rotated, elongated section we need for the later tube.
829 // Then in a for loop we go through every cell. By projecting the vector leading
830 // from the origin to the specific atom down onto the major and minor axis we
831 // know if it's still within the boundaries spanned by these rotated and elongated
832 // (radius-, length factor) unit vectors or not. If yes, its coordinates are
833 // written to file.
834
835 int numbersheet, biggestdiameter, sheetnr[NDIM], tmp, seed;
836 double x1,x2,x3, angle;
837 char flag = 'n';
838 FILE *SheetFile = NULL;
839 FILE *SheetFileAligned = NULL;
840
841 Debug ("STAGE: Sheet\n");
842 if (!strncmp(stage, "Cell", 4)) {
843 fprintf(stdout, "\nEnter seed unequal 0 if any of the bonds shall have a randomness in their being: ");
844 fscanf(stdin, "%d", &seed);
845 if (seed != 0)
846 input = 'y';
847 randomness = (double *) Malloc(sizeof(double)*numbercell, "Main: at sheet - randomness");
848 for(i=0;i<numbercell;i++)
849 randomness[i] = 0.;
850 i = 0;
851 fprintf(stdout, "\n");
852 while (input == 'y') {
853 fprintf(stdout, "Enter atom number (-1 0 to end) and percentage (0.0...1.0): ");
854 fscanf(stdin, "%d %lg", &i, &percentage);
855 if (i == -1) { input = 'n'; fprintf(stdout, "Breaking\n"); }
856 else { randomness[i] = 1.-percentage; }
857 };
858
859 fprintf(stdout, "\nSpecify the axis permutation that is going to be perpendicular to the sheet [tubeaxis, torusaxis, noaxis]: ");
860 fscanf(stdin, "%d %d %d", &axis[0], &axis[1], &axis[2]);
861 fprintf(stdout, "axis: %d %d %d\n", axis[0], axis[1], axis[2]);
862
863 // create orthogonal vectors individually for each unit cell vector
864 CreateOrthogonalAxisVectors(OrthoVector, Vector, axis);
865 fprintf(stdout, "Orthogonal vector axis[0] %lg\n", Projection(Vector[axis[0]], OrthoVector[axis[0]]));
866 fprintf(stdout, "Orthogonal vector axis[1] %lg\n", Projection(Vector[axis[1]], OrthoVector[axis[1]]));
867
868 do {
869 fprintf(stdout, "\nNow specify the two natural numbers (m n) defining the chiral angle, \nif the result is crap, try flipping to (m,n): ");
870 fscanf(stdin, "%d %d", &chiral[0], &chiral[1]);
871 ggT = GCD(2*chiral[1]+chiral[0],2*chiral[0]+chiral[1]);
872 fprintf(stdout, "Greatest Common Denominator of (2n+m, 2m+n) is %d\n", ggT);
873 fprintf(stdout, "chiral0: %d\tchiral1: %d\n", chiral[0], chiral[1]);
874 for (i=0;i<NDIM;i++) {
875 Tubevector[axis[0]][i] = (double)chiral[0] * Vector[axis[0]][i] + (double)chiral[1] * Vector[axis[1]][i];
876 //Tubevector[axis[0]][i] = chiral[0] * Vector[axis[0]][i] + chiral[1] * Vector[axis[1]][i];
877 //Tubevector[axis[0]][i] = (2.*chiral[0]+chiral[1])/(double)ggT * Vector[axis[0]][i] + (-chiral[0]-2.*chiral[1])/(double)ggT * Vector[axis[1]][i];
878 //Tubevector[axis[1]][i] = -chiral[1] * Vector[axis[0]][i] + chiral[0] * Vector[axis[1]][i];
879 Tubevector[axis[1]][i] = (double)chiral[0] * OrthoVector[axis[0]][i] - (double)chiral[1] * OrthoVector[axis[1]][i];
880 //Tubevector[axis[1]][i] = (-chiral[0]-2.*chiral[1])/(double)ggT * Vector[axis[0]][i] + (2.*chiral[0]+chiral[1])/(double)ggT * Vector[axis[1]][i];
881// fprintf(stderr, "Tubevector[axis[0]][i] = (double)chiral[0] * Vector[axis[0]][i] + (double)chiral[1] * Vector[axis[1]][i]\n = %lg * %lg + %lg * %lg = %lg + %lg = %lg\n\n",
882// (double)chiral[0], Vector[axis[0]][i], (double)chiral[1], Vector[axis[1]][i],
883// (double)chiral[0] * Vector[axis[0]][i], (double)chiral[1] * Vector[axis[1]][i],
884// Tubevector[axis[0]][i]);
885 Tubevector[axis[2]][i] = Vector[axis[2]][i];
886 }
887 // here we assume, that Vector[axis[2]] is along z direction!
888 gsl_matrix *M = gsl_matrix_alloc(2,2);
889 gsl_matrix *C = gsl_matrix_alloc(2,2);
890 gsl_matrix *evec = gsl_matrix_alloc(2,2);
891 gsl_vector *eval = gsl_vector_alloc(2);
892 gsl_vector *v = gsl_vector_alloc(2);
893 gsl_vector *u = gsl_vector_alloc(2);
894 gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc(2);
895 gsl_matrix_set(C, 0,0, Vector[axis[0]][0]);
896 gsl_matrix_set(C, 1,0, Vector[axis[0]][1]);
897 gsl_matrix_set(C, 0,1, Vector[axis[1]][0]);
898 gsl_matrix_set(C, 1,1, Vector[axis[1]][1]);
899 gsl_blas_dgemm(CblasTrans,CblasNoTrans, 1.0, C, C, 0.0, M);
900 fprintf(stdout, "M: \t%lg\t%lg\n\t%lg\t%lg\n", gsl_matrix_get(M,0,0), gsl_matrix_get(M,0,1), gsl_matrix_get(M,1,0), gsl_matrix_get(M,1,1));
901 gsl_eigen_symmv(M, eval, evec, w);
902 gsl_eigen_symmv_sort(eval,evec,GSL_EIGEN_SORT_ABS_DESC);
903 fprintf(stdout, "Eigenvalues: %lg\t%lg\n", gsl_vector_get(eval,0), gsl_vector_get(eval,1));
904 fprintf(stdout, "Eigenvectors: \t%lg\t%lg\n\t\t%lg\t%lg\n", gsl_matrix_get(evec,0,0), gsl_matrix_get(evec,0,1), gsl_matrix_get(evec,1,0), gsl_matrix_get(evec,1,1));
905 gsl_matrix_set(M, 0,0, 0.);
906 gsl_matrix_set(M, 1,0, 1.);
907 gsl_matrix_set(M, 0,1, -gsl_vector_get(eval,1)/gsl_vector_get(eval,0));
908 gsl_matrix_set(M, 1,1, 0.);
909 gsl_vector_set(v,0,(double)chiral[0]);
910 gsl_vector_set(v,1,(double)chiral[1]);
911 gsl_blas_dgemm(CblasNoTrans,CblasNoTrans, 1.0, evec, M, 0.0, C);
912 gsl_blas_dgemm(CblasNoTrans,CblasTrans, 1.0, C, evec, 0.0, M);
913 fprintf(stdout, "M: \t%lg\t%lg\n\t%lg\t%lg\n", gsl_matrix_get(M,0,0), gsl_matrix_get(M,0,1), gsl_matrix_get(M,1,0), gsl_matrix_get(M,1,1));
914 gsl_blas_dgemv(CblasNoTrans, 1.0, M, v, 0.0, u);
915 fprintf(stdout, "Looking for factor to integer...\n");
916 for(i=1;i<(chiral[0]+chiral[1])*(chiral[0]+chiral[1]);i++) {
917 x1 = gsl_vector_get(u,0)*(double)i;
918 x2 = gsl_vector_get(u,1)*(double)i;
919 x3 =
920 fprintf(stdout, "%d: %d\t%d vs. %lg\t%lg\n",i, ((int)(x1+x1/fabs(x1)*.5)), ((int)(x2+x2/fabs(x2)*.5)), (x1), (x2));
921 if (( fabs( ((int)(x1+x1/fabs(x1)*.5)) - (x1) ) < 1e-6) && ( fabs( ((int)(x2+x2/fabs(x2)*.5)) - (x2) ) < 1e-6 )) {
922 gsl_blas_dscal((double)i, u);
923 break;
924 }
925 }
926 fprintf(stdout, "(c,d) = (%lg,%lg)\n",gsl_vector_get(u,0), gsl_vector_get(u,1));
927
928 // get length
929 double x[NDIM];
930 for (i=0;i<NDIM;i++)
931 x[i] = gsl_vector_get(u,0) * Vector[axis[0]][i] + gsl_vector_get(u,1) * Vector[axis[1]][i];
932 angle = Norm(x)/Norm(Tubevector[axis[1]]) ;//ScalarProduct(x,Tubevector[axis[1]])/Norm(Tubevector[axis[1]]);
933 fprintf(stdout, "angle is %lg\n", angle);
934 for (i=0;i<NDIM;i++) {
935 Tubevector[axis[1]][i] = gsl_vector_get(u,0) * Vector[axis[0]][i] + gsl_vector_get(u,1) * Vector[axis[1]][i];
936 }
937
938 // Probe
939 gsl_matrix_set(M, 0,0, Vector[axis[0]][0]);
940 gsl_matrix_set(M, 1,0, Vector[axis[0]][1]);
941 gsl_matrix_set(M, 0,1, Vector[axis[1]][0]);
942 gsl_matrix_set(M, 1,1, Vector[axis[1]][1]);
943 gsl_vector_set(v,0,(double)chiral[0]);
944 gsl_vector_set(v,1,(double)chiral[1]);
945 gsl_blas_dgemv(CblasNoTrans, 1.0, M, u, 0.0, eval);
946 gsl_blas_dgemv(CblasNoTrans, 1.0, M, v, 0.0, u);
947 x1=1.;
948 gsl_blas_ddot(u,eval,&x1);
949 fprintf(stdout, "Testing (c,d): (a,b) M^t M (c,d)^t = 0 ? : %lg\n", x1);
950
951 gsl_matrix_free(M);
952 gsl_matrix_free(C);
953 gsl_matrix_free(evec);
954 gsl_vector_free(eval);
955 gsl_vector_free(v);
956 gsl_vector_free(u);
957 gsl_eigen_symmv_free(w);
958
959 if (fabs(x1) > 1e-6) {
960 fprintf(stderr,"Resulting TubeVectors of axis %d and %d and not orthogonal, aborting.\n", axis[0], axis[1]);
961 return(128);
962 }
963
964
965 angle = Projection(Tubevector[axis[1]], Vector[axis[0]]);
966 fprintf(stdout, "Projection Tubevector1 axis[0] %lg %lg\n", angle, 1./angle);
967 angle = Projection(Tubevector[axis[1]], Vector[axis[1]]);
968 fprintf(stdout, "Projection Tubevector1 axis[1] %lg %lg\n", angle, 1./angle);
969
970/* fprintf(stdout, "Vector\n");
971 PrintMatrix(stdout, Vector);
972 fprintf(stdout, "Tubevector\n");
973 PrintMatrix(stdout, Tubevector);
974 for (i=0;i<NDIM;i++) {
975 fprintf(stdout, "Tubevector %d in Unit cell vectors:\t", axis[i]);
976 tempvector = MatrixTrafoInverse(Tubevector[axis[i]], Recivector);
977 PrintVector(stdout, tempvector);
978 Free(tempvector, "Main:tempvector");
979 }*/
980
981 // Give info for length and radius factors
982 fprintf(stdout, "\nThe chiral angle then is %lg degrees with tube radius %5.5f A and length %5.5f A, i.e. torus radius of %5.5f A.\n",
983 acos(Projection(Vector[axis[0]], Tubevector[axis[0]]))/M_PI*180.,
984 Norm(Tubevector[axis[0]])/(2.*M_PI),
985 Norm(Tubevector[axis[1]]),
986 Norm(Tubevector[axis[1]])/(2.*M_PI)
987 );
988 fprintf(stdout, "\nGive integer factors for length and radius of tube (multiple of %d suggested) : ", ggT);
989 fscanf(stdin, "%d %d", &factors[1], &factors[0]);
990 fprintf(stdout, "\nThe chiral angle then is %5.5f degrees with tube radius %5.5f A and length %5.5f A, i.e. torus radius of %5.5f A.\n",
991 acos(Projection(Vector[axis[0]], Tubevector[axis[0]]))/M_PI*180.,
992 (double)factors[0]*Norm(Tubevector[axis[0]])/(2.*M_PI),
993 (double)factors[1]*Norm(Tubevector[axis[1]]),
994 (double)factors[1]*Norm(Tubevector[axis[1]])/(2.*M_PI)
995 );
996 fprintf(stdout, "Satisfied? [yn] ");
997 fscanf(stdin, "%c", &flag);
998 fscanf(stdin, "%c", &flag);
999 } while (flag != 'y');
1000 } else {
1001 char *ptr = NULL;
1002 char dummy[10];
1003 double dummydouble;
1004
1005 SheetBuffer = bufptr = ReadBuffer(SheetFilename, &length);
1006 bufptr += (GetNextline(bufptr, line))*sizeof(char);
1007 sscanf(line, "%d", &numbersheet);
1008
1009 // retrieve axis permutation
1010 sprintf(dummy, "Axis");
1011 fprintf(stdout, "%s ", dummy);
1012 while ((length = GetNextline(bufptr, line)) != 0) {
1013 bufptr += (length)*sizeof(char);
1014 if ((ptr = strstr(line, dummy)) != NULL)
1015 break;
1016 }
1017 if (length == 0) {
1018 fprintf(stderr, "ERROR: Main at stage Sheet - could not find %s in %s\n", dummy, SheetFilename);
1019 exit(255);
1020 }
1021 ptr += strlen(dummy);
1022 sscanf(ptr, "%d %d %d", &axis[0], &axis[1], &axis[2]);
1023 fprintf(stdout, "%d %d %d\n", axis[0], axis[1], axis[2]);
1024
1025 // retrieve chiral numbers
1026 sprintf(dummy, "(n,m)");
1027 fprintf(stdout, "%s ", dummy);
1028 while ((length = GetNextline(bufptr, line)) != 0) {
1029 bufptr += (length)*sizeof(char);
1030 if ((ptr = strstr(line, dummy)) != NULL)
1031 break;
1032 }
1033 if (length == 0) {
1034 fprintf(stderr, "ERROR: Main at stage Sheet - could not find %s in %s\n", dummy, SheetFilename);
1035 exit(255);
1036 }
1037 ptr += strlen(dummy);
1038 sscanf(ptr, "%d %d", &chiral[0], &chiral[1]);
1039 fprintf(stdout, "%d %d\n", chiral[0], chiral[1]);
1040 ggT = GCD(2*chiral[1]+chiral[0],2*chiral[0]+chiral[1]);
1041 fprintf(stdout, "Greatest Common Denominator of (2n+m, 2m+n) is %d\n", ggT);
1042
1043 // retrieve length and radius factors
1044 sprintf(dummy, "factors");
1045 fprintf(stdout, "%s ", dummy);
1046 while ((length = GetNextline(bufptr, line)) != 0) {
1047 bufptr += (length)*sizeof(char);
1048 if ((ptr = strstr(line, dummy)) != NULL)
1049 break;
1050 }
1051 if (length == 0) {
1052 fprintf(stderr, "ERROR: Main at stage Sheet - could not find %s in %s\n", dummy, SheetFilename);
1053 exit(255);
1054 }
1055 ptr += strlen(dummy);
1056 sscanf(ptr, "%d %d %d", &factors[0], &factors[1], &factors[2]);
1057 fprintf(stdout, "%d %d %d\n", factors[0], factors[1], factors[2]);
1058
1059 // create orthogonal vectors individually for each unit cell vector
1060 CreateOrthogonalAxisVectors(OrthoVector, Vector, axis);
1061 fprintf(stdout, "Orthogonal vector axis[0] %lg", Projection(Vector[axis[0]], OrthoVector[axis[0]]));
1062 fprintf(stdout, "Orthogonal vector axis[1] %lg", Projection(Vector[axis[1]], OrthoVector[axis[1]]));
1063 // create Tubevectors
1064 for (i=0;i<NDIM;i++) {
1065 Tubevector[axis[0]][i] = chiral[0] * Vector[axis[0]][i] + chiral[1] * Vector[axis[1]][i];
1066 //Tubevector[axis[0]][i] = (2.*chiral[0]+chiral[1])/(double)ggT * Vector[axis[0]][i] + (-chiral[0]-2.*chiral[1])/(double)ggT * Vector[axis[1]][i];
1067 //Tubevector[axis[1]][i] = -chiral[1] * Vector[axis[0]][i] + chiral[0] * Vector[axis[1]][i];
1068 Tubevector[axis[1]][i] = chiral[0] * OrthoVector[axis[0]][i] + chiral[1] * OrthoVector[axis[1]][i];
1069 //Tubevector[axis[1]][i] = (-chiral[0]-2.*chiral[1])/(double)ggT * Vector[axis[0]][i] + (2.*chiral[0]+chiral[1])/(double)ggT * Vector[axis[1]][i];
1070 Tubevector[axis[2]][i] = Vector[axis[2]][i];
1071 }
1072 // here we assume, that Vector[axis[2]] is along z direction!
1073 gsl_matrix *M = gsl_matrix_alloc(2,2);
1074 gsl_matrix *C = gsl_matrix_alloc(2,2);
1075 gsl_matrix *evec = gsl_matrix_alloc(2,2);
1076 gsl_vector *eval = gsl_vector_alloc(2);
1077 gsl_vector *v = gsl_vector_alloc(2);
1078 gsl_vector *u = gsl_vector_alloc(2);
1079 gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc(2);
1080 gsl_matrix_set(C, 0,0, Vector[axis[0]][0]);
1081 gsl_matrix_set(C, 1,0, Vector[axis[0]][1]);
1082 gsl_matrix_set(C, 0,1, Vector[axis[1]][0]);
1083 gsl_matrix_set(C, 1,1, Vector[axis[1]][1]);
1084 gsl_blas_dgemm(CblasTrans,CblasNoTrans, 1.0, C, C, 0.0, M);
1085 fprintf(stdout, "M: \t%lg\t%lg\n\t%lg\t%lg\n", gsl_matrix_get(M,0,0), gsl_matrix_get(M,0,1), gsl_matrix_get(M,1,0), gsl_matrix_get(M,1,1));
1086 gsl_eigen_symmv(M, eval, evec, w);
1087 gsl_eigen_symmv_sort(eval,evec,GSL_EIGEN_SORT_ABS_DESC);
1088 fprintf(stdout, "Eigenvalues: %lg\t%lg\n", gsl_vector_get(eval,0), gsl_vector_get(eval,1));
1089 fprintf(stdout, "Eigenvectors: \t%lg\t%lg\n\t\t%lg\t%lg\n", gsl_matrix_get(evec,0,0), gsl_matrix_get(evec,0,1), gsl_matrix_get(evec,1,0), gsl_matrix_get(evec,1,1));
1090 gsl_matrix_set(M, 0,0, 0.);
1091 gsl_matrix_set(M, 1,0, 1.);
1092 gsl_matrix_set(M, 0,1, -gsl_vector_get(eval,1)/gsl_vector_get(eval,0));
1093 gsl_matrix_set(M, 1,1, 0.);
1094 gsl_vector_set(v,0,(double)chiral[0]);
1095 gsl_vector_set(v,1,(double)chiral[1]);
1096 gsl_blas_dgemm(CblasNoTrans,CblasNoTrans, 1.0, evec, M, 0.0, C);
1097 gsl_blas_dgemm(CblasNoTrans,CblasTrans, 1.0, C, evec, 0.0, M);
1098 fprintf(stdout, "M: \t%lg\t%lg\n\t%lg\t%lg\n", gsl_matrix_get(M,0,0), gsl_matrix_get(M,0,1), gsl_matrix_get(M,1,0), gsl_matrix_get(M,1,1));
1099 gsl_blas_dgemv(CblasNoTrans, 1.0, M, v, 0.0, u);
1100 fprintf(stdout, "Looking for factor to integer...\n");
1101 for(i=1;i<(chiral[0]+chiral[1])*(chiral[0]+chiral[1]);i++) {
1102 x1 = gsl_vector_get(u,0)*(double)i;
1103 x2 = gsl_vector_get(u,1)*(double)i;
1104 x3 =
1105 fprintf(stdout, "%d: %d\t%d vs. %lg\t%lg\n",i, ((int)(x1+x1/fabs(x1)*.5)), ((int)(x2+x2/fabs(x2)*.5)), (x1), (x2));
1106 if (( fabs( ((int)(x1+x1/fabs(x1)*.5)) - (x1) ) < 1e-6) && ( fabs( ((int)(x2+x2/fabs(x2)*.5)) - (x2) ) < 1e-6 )) {
1107 gsl_blas_dscal((double)i, u);
1108 break;
1109 }
1110 }
1111 fprintf(stdout, "(c,d) = (%lg,%lg)\n",gsl_vector_get(u,0), gsl_vector_get(u,1));
1112
1113 // get length
1114 double x[NDIM];
1115 for (i=0;i<NDIM;i++)
1116 x[i] = gsl_vector_get(u,0) * Vector[axis[0]][i] + gsl_vector_get(u,1) * Vector[axis[1]][i];
1117 angle = Norm(x)/Norm(Tubevector[axis[1]]) ;//ScalarProduct(x,Tubevector[axis[1]])/Norm(Tubevector[axis[1]]);
1118 fprintf(stdout, "angle is %lg\n", angle);
1119 for (i=0;i<NDIM;i++) {
1120 Tubevector[axis[1]][i] = gsl_vector_get(u,0) * Vector[axis[0]][i] + gsl_vector_get(u,1) * Vector[axis[1]][i];
1121 }
1122
1123 // Probe
1124 gsl_matrix_set(M, 0,0, Vector[axis[0]][0]);
1125 gsl_matrix_set(M, 1,0, Vector[axis[0]][1]);
1126 gsl_matrix_set(M, 0,1, Vector[axis[1]][0]);
1127 gsl_matrix_set(M, 1,1, Vector[axis[1]][1]);
1128 gsl_vector_set(v,0,(double)chiral[0]);
1129 gsl_vector_set(v,1,(double)chiral[1]);
1130 gsl_blas_dgemv(CblasNoTrans, 1.0, M, u, 0.0, eval);
1131 gsl_blas_dgemv(CblasNoTrans, 1.0, M, v, 0.0, u);
1132 x1=1.;
1133 gsl_blas_ddot(u,eval,&x1);
1134 fprintf(stdout, "Testing (c,d): (a,b) M^t M (c,d)^t = 0 ? : %lg\n", x1);
1135
1136 gsl_matrix_free(M);
1137 gsl_matrix_free(C);
1138 gsl_matrix_free(evec);
1139 gsl_vector_free(eval);
1140 gsl_vector_free(v);
1141 gsl_vector_free(u);
1142 gsl_eigen_symmv_free(w);
1143
1144 if (fabs(x1) > 1e-6) {
1145 fprintf(stderr,"Resulting TubeVectors of axis %d and %d and not orthogonal, aborting.\n", axis[0], axis[1]);
1146 return(128);
1147 }
1148
1149 // retrieve seed ...
1150 randomness = (double *) Calloc(sizeof(double)*numbercell, 0., "Main: at sheet - randomness");
1151 sprintf(dummy, "seed");
1152 fprintf(stdout, "%s ", dummy);
1153 while ((length = GetNextline(bufptr, line)) != 0) {
1154 bufptr += (length)*sizeof(char);
1155 if ((ptr = strstr(line, dummy)) != NULL)
1156 break;
1157 }
1158 if (length == 0) {
1159 fprintf(stderr, "ERROR: Main at stage Sheet - could not find %s in %s\n", dummy, SheetFilename);
1160 exit(255);
1161 }
1162 ptr += strlen(dummy);
1163 sscanf(ptr, "%d", &seed);
1164 fprintf(stdout, "%d\n", seed);
1165
1166 // ... and randomness
1167 if (seed != 0) { // only parse for values if a seed, i.e. randomness wanted, was specified
1168 sprintf(dummy, "Randomness");
1169 fprintf(stdout, "%s\n", dummy);
1170 while ((length = GetNextline(bufptr, line)) != 0) {
1171 bufptr += (length)*sizeof(char);
1172 if ((ptr = strstr(line, dummy)) != NULL)
1173 break;
1174 }
1175 if (length == 0) {
1176 fprintf(stderr, "ERROR: Main at stage Sheet - could not find %s in %s\n", dummy, SheetFilename);
1177 exit(255);
1178 }
1179 sprintf(dummy, "probability values");
1180 for (i=0;i<numbercell;i++) {
1181 length = GetNextline(bufptr, line);
1182 if (length == 0) {
1183 fprintf(stderr, "ERROR: Main at stage Sheet - could not find %s in %s\n", dummy, SheetFilename);
1184 exit(255);
1185 }
1186 bufptr += (length)*sizeof(char);
1187 sscanf(line, "%d %lg", &j, &dummydouble);
1188 randomness[j] = dummydouble;
1189 fprintf(stdout, "%d %g\n", j, randomness[j]);
1190 }
1191 }
1192 }
1193
1194 //int OrthOrder[NDIM] = { axis[2], axis[0], axis[1] };
1195 //Orthogonalize(Tubevector,OrthOrder);
1196 angle = acos(Projection(Vector[axis[0]], Vector[axis[1]])); // calcs angle between shanks in unit cell
1197 fprintf(stdout, "The basic angle between the two shanks of the unit cell is %lg %lg\n", angle/M_PI*180., Projection(Vector[axis[0]], Vector[axis[1]]));
1198 if ( angle/M_PI*180. > 90 ) {
1199 fprintf(stderr, "There seems to be something wrong with the unit cell! for nanotube the angle should be 60 degrees for example!\n");
1200 return 1;
1201 }
1202 angle = acos(Projection(Tubevector[axis[0]], Tubevector[axis[1]])); // calcs angle between shanks in unit cell
1203 fprintf(stdout, "The basic angle between the two shanks of the tube unit cell is %lg %lg\n", angle/M_PI*180., Projection(Tubevector[axis[0]], Tubevector[axis[1]]));
1204 //angle -= acos(Projection(Vector[axis[0]], Tubevector[axis[0]]));
1205 //angle = 30./180.*M_PI - acos(Projection(Vector[axis[0]], Tubevector[axis[0]]));
1206 //angle = acos(Projection(Tubevector[axis[0]], Vector[axis[0]]));
1207 fprintf(stdout, "The relative alignment rotation angle then is %lg\n", angle/M_PI*180.);
1208 if (fabs(Tubevector[axis[0]][0]) > MYEPSILON)
1209 angle = -M_PI/2. + acos(Tubevector[axis[0]][0]/Norm(Tubevector[axis[0]]));
1210 else
1211 angle = 0.;
1212 fprintf(stdout, "The absolute alignment rotation angle then is %lg %lg\n", angle/M_PI*180., Tubevector[axis[0]][0]/Norm(Tubevector[axis[0]]));
1213 fprintf(stdout, "\nThe chiral angle then is %5.5f degrees with tube radius %5.5f A and length %5.5f A, i.e. final torus radius of %5.5f A.\n",
1214 acos(Projection(Vector[axis[0]], Tubevector[axis[0]]))/M_PI*180.,
1215 (double)factors[0]*Norm(Tubevector[axis[0]])/(2.*M_PI),
1216 (double)factors[1]*Norm(Tubevector[axis[1]]),
1217 (double)factors[1]*Norm(Tubevector[axis[1]])/(2.*M_PI)
1218 );
1219 Orthogonalize(Tubevector, axis); // with correct translational vector, not needed anymore (? what's been done here. Hence, re-inserted)
1220 fprintf(stdout, "Tubevector magnitudes: %5.5lg %5.5lg %5.5lg\n", Norm(Tubevector[0]), Norm(Tubevector[1]), Norm(Tubevector[2]));
1221 fprintf(stdout, "Tubevectors are \n");
1222 PrintMatrix(stdout, Tubevector);
1223 MatrixInversion(Tubevector, TubevectorInverse);
1224 //Transpose(TubevectorInverse);
1225 fprintf(stdout, "Vector\n");
1226 PrintMatrix(stdout, Vector);
1227 fprintf(stdout, "TubevectorInverse\n");
1228 PrintMatrix(stdout, TubevectorInverse);
1229 for (i=0;i<NDIM;i++) {
1230 fprintf(stdout, "Vector %d in TubeVectorInverse vectors:\t", axis[i]);
1231 tempvector = MatrixTrafoInverse(Vector[axis[i]], TubevectorInverse);
1232 PrintVector(stdout, tempvector);
1233 Free(tempvector, "Main:tempvector");
1234 }
1235 fprintf(stdout, "Reciprocal Tubebvectors are \n");
1236 PrintMatrix(stdout, TubevectorInverse);
1237 fprintf(stdout, "Tubevector magnitudes: %5.5lg %5.5lg %5.5lg\n", Norm(Tubevector[0]), Norm(Tubevector[1]), Norm(Tubevector[2]));
1238
1239 biggestdiameter = DetermineBiggestDiameter(Tubevector, axis, factors);
1240 for (i=0;i<NDIM;i++) {
1241 sheetnr[i] = 0;
1242 }
1243 for (i=0;i<NDIM;i++) {
1244 for (j=0;j<NDIM;j++) {
1245// sheetnr[j] = ceil(biggestdiameter/Norm(Vector[j]));
1246 if (fabs(Vector[i][j]) > MYEPSILON) {
1247 tmp = ceil(biggestdiameter/fabs(Vector[i][j]));
1248 } else {
1249 tmp = 0;
1250 }
1251 sheetnr[j] = sheetnr[j] > tmp ? sheetnr[j] : tmp;
1252 }
1253 }
1254 fprintf(stdout, "Maximum indices to regard: %d %d %d\n", sheetnr[0], sheetnr[1], sheetnr[2]);
1255 for (i=0;i<NDIM;i++) {
1256 fprintf(stdout, "For axis %d: (%5.5lg\t%5.5lg\t%5.5lg) with %5.5lg\n", i, (Vector[i][0]*sheetnr[i]), (Vector[i][1]*sheetnr[i]), (Vector[i][2]*sheetnr[i]), Norm(Vector[i]));
1257 }
1258
1259 //if (!strncmp(stage, "Cell", 4)) {
1260 // parse in atoms for quicker processing
1261 struct Atoms *atombuffer = malloc(sizeof(struct Atoms)*numbercell);
1262 bufptr = CellBuffer;
1263 bufptr += GetNextline(bufptr, line)*sizeof(char);
1264 bufptr += GetNextline(bufptr, line)*sizeof(char);
1265 for (i=0;i<numbercell;i++) {
1266 if ((length = GetNextline(bufptr, line)) != 0) {
1267 bufptr += length*sizeof(char);
1268 sscanf(line, "%s %lg %lg %lg", atombuffer[i].name, &(atombuffer[i].x[0]), &(atombuffer[i].x[1]), &(atombuffer[i].x[2]));
1269 fprintf(stdout, "Read Atombuffer Nr %i: %s %5.5lg %5.5lg %5.5lg\n", i+1, atombuffer[i].name, atombuffer[i].x[0], atombuffer[i].x[1], atombuffer[i].x[2]);
1270 } else {
1271 fprintf(stdout, "Error reading Atom Nr. %i\n", i+1);
1272 break;
1273 }
1274 }
1275 SheetFile = fopen(SheetFilename, "w");
1276 if (SheetFile == NULL) {
1277 fprintf(stderr, "ERROR: main - can't open %s for writing\n", SheetFilename);
1278 exit(255);
1279 }
1280 SheetFileAligned = fopen(SheetFilenameAligned, "w");
1281 if (SheetFile == NULL) {
1282 fprintf(stderr, "ERROR: main - can't open %s for writing\n", SheetFilenameAligned);
1283 exit(255);
1284 }
1285 // Now create the sheet
1286 double index[NDIM];
1287 int nr;//, nummer = 0;
1288 numbersheet = 0;
1289 index[axis[2]] = 0;
1290 // initialise pseudo random number generator with given seed
1291 fprintf(stdout, "Initialising pseudo random number generator with given seed %d.\n", seed);
1292 srand(seed);
1293 //for (index[axis[0]] = 0; index[axis[0]] <= sheetnr[axis[0]]; index[axis[0]]++) { // NOTE: minor axis may start from 0! Check on this later ...
1294 for (index[axis[0]] = -sheetnr[axis[0]]+1; index[axis[0]] < sheetnr[axis[0]]; index[axis[0]]++) { // NOTE: minor axis may start from 0! Check on this later ...
1295 //for (index[axis[1]] = 0; index[axis[1]] <= sheetnr[axis[1]]; index[axis[1]]++) { // These are all the cells that need be checked on
1296 for (index[axis[1]] = -sheetnr[axis[1]]+1; index[axis[1]] < sheetnr[axis[1]]; index[axis[1]]++) { // These are all the cells that need be checked on
1297 // Calculate offset in cartesian coordinates
1298 offset = MatrixTrafo(Vector, index);
1299
1300 //fprintf(stdout, "Now dealing with numbercell atoms in unit cell at R = (%lg,%lg,%lg)\n", offset[0], offset[1], offset[2]);
1301 for (nr = 0; nr < numbercell; nr++) {
1302 percentage = rand()/(RAND_MAX+1.0);
1303 //fprintf(stdout, "Lucky number for %d is %lg >? %lg\n", nr, percentage, randomness[nr]);
1304 if (percentage >= randomness[nr]) {
1305 // Create coordinates at atom site
1306 coord = VectorAdd(atombuffer[nr].x, offset);
1307 //fprintf(stdout, "Atom Nr. %i: ", (numbersheet+1));
1308 //PrintVector(stdout, coord);
1309 // project down on major and minor Tubevectors and check for length if out of sheet
1310 tempvector = MatrixTrafoInverse(coord, TubevectorInverse);
1311 if (((tempvector[axis[0]] + MYEPSILON) > 0) && ((factors[0] - tempvector[axis[0]]) > MYEPSILON) &&
1312 ((tempvector[axis[1]] + MYEPSILON) > 0) && ((factors[1] - tempvector[axis[1]]) > MYEPSILON) &&
1313 ((tempvector[axis[2]] + MYEPSILON) > 0) && ((factors[2] - tempvector[axis[2]]) > MYEPSILON)) { // check if within rotated cell numbersheet++;
1314 //if (nummer >= 2) strcpy(atombuffer[nr].name, "O");
1315 //nummer++;
1316 fprintf(SheetFile, "%s\t%5.5lg\t%5.5lg\t%5.5lg\n", atombuffer[nr].name, coord[0], coord[1], coord[2]);
1317 // rotate to align the sheet in xy plane
1318 x1 = coord[0]*cos(-angle) + coord[1] * sin(-angle);
1319 x2 = coord[0]*(-sin(-angle)) + coord[1] * cos(-angle);
1320 x3 = coord[2];
1321 fprintf(SheetFileAligned, "%s\t%5.5lg\t%5.5lg\t%5.5lg\n", atombuffer[nr].name, x1, x2, x3);
1322 //fprintf(SheetFile, "O\t%5.5lg\t%5.5lg\t%5.5lg\n", coord[0], coord[1], coord[2]);
1323 //fprintf(stdout, "%s/%d\t(%lg\t%lg\t%lg)\t", atombuffer[nr].name, numbersheet+1, coord[0], coord[1], coord[2]);
1324 //PrintVector(stdout, tempvector);
1325 numbersheet++;
1326 //fprintf(stdout, "%i,", nr);
1327 } //else {
1328 //numbersheet++;
1329 //fprintf(SheetFile, "B\t%lg\t%lg\t%lg\n", coord[0], coord[1], coord[2]);
1330 //fprintf(stdout, "O \t(%lg\t%lg\t%lg)\n", coord[0], coord[1], coord[2]);
1331 //fprintf(stdout, "!!%i!!, ", nr);
1332 //}
1333 Free(tempvector, "Main: At stage Sheet - tempvector");
1334 Free(coord, "Main: At stage Sheet - coord");
1335 }
1336 }
1337 Free(offset, "Main: At stage Sheet - offset");
1338 }
1339 //fprintf(stdout, "\n";
1340 }
1341
1342 fclose(SheetFile);
1343 fclose(SheetFileAligned);
1344 AddAtomicNumber(SheetFilename,numbersheet, Vector, Recivector); // prepend atomic number and comment
1345 AddAtomicNumber(SheetFilenameAligned,numbersheet, Vector, Recivector); // prepend atomic number and comment
1346 AddSheetInfo(SheetFilename,axis,chiral, factors, seed, numbercell, randomness);
1347 fprintf(stdout, "\nThere are %i atoms in the created sheet.\n", numbersheet);
1348
1349 strncpy(stage, "Sheet", 5);
1350 //}
1351 SheetBuffer = ReadBuffer(SheetFilename, &length);
1352
1353
1354 // ======================== STAGE: Tube ==============================
1355 // The tube starts with the rectangular (due to the orthogonalization) sheet
1356 // just created (or read). Along the minor axis it is rolled up, i.e. projected
1357 // from a 2d surface onto a cylindrical surface (x,y,z <-> r,alpha,z). The only
1358 // thing that's a bit complex is that the sheet it not aligned along the cartesian
1359 // axis but along major and minor. That's why we have to transform the atomic
1360 // cartesian coordinates into the orthogonal tubevector base, do the rolling up
1361 // there (and regard that minor and major axis must not necessarily be of equal
1362 // length) and afterwards transform back again (where we need the $halfaxis due to
1363 // the above possible inequality).
1364
1365 FILE *TubeFile = NULL;
1366 FILE *TubeFileAligned = NULL;
1367
1368 Debug ("STAGE: Tube\n");
1369 if (!strncmp(stage, "Sheet", 4)) {
1370 TubeFile = fopen(TubeFilename, "w");
1371 if (TubeFile == NULL) {
1372 fprintf(stderr, "ERROR: Main - can't open %s for writing\n", TubeFilename);
1373 exit(255);
1374 }
1375 TubeFileAligned = fopen(TubeFilenameAligned, "w");
1376 if (TubeFile == NULL) {
1377 fprintf(stderr, "ERROR: Main - can't open %s for writing\n", TubeFilenameAligned);
1378 exit(255);
1379 }
1380 bufptr = SheetBuffer;
1381 bufptr += GetNextline(bufptr, line); // write numbers to file
1382 bufptr += GetNextline(bufptr, line); // write comment to file
1383
1384 //cog = CenterOfGravity(bufptr, numbersheet);
1385 //cog_projected = MatrixTrafoInverse(cog, TubevectorInverse);
1386 //fprintf(stdout, "\nCenter of Gravity at (%5.5lg\t%5.5lg\t%5.5lg) and projected at (%5.5lg\t%5.5lg\t%5.5lg)\n", cog[0], cog[1], cog[2], cog_projected[0], cog_projected[1], cog_projected[2]);
1387
1388 // restart
1389 bufptr = SheetBuffer;
1390 bufptr += GetNextline(bufptr, line); // write numbers to file
1391 bufptr += GetNextline(bufptr, line); // write numbers to file
1392
1393 // determine half axis as tube vector not necessarily have the same length
1394 double halfaxis[NDIM];
1395 for (i=0;i<NDIM;i++)
1396 halfaxis[i] = factors[0]*Norm(Tubevector[axis[0]])/Norm(Tubevector[i]);
1397
1398 double arg, radius;
1399 for (i=0;i<numbersheet;i++) {
1400 // scan next atom
1401 bufptr += GetNextline(bufptr, line);
1402 sscanf(line, "%s %lg %lg %lg", name, &atom[0], &atom[1], &atom[2]);
1403
1404 // transform atom coordinates in cartesian system to the axis eigensystem
1405 x = MatrixTrafoInverse(atom, TubevectorInverse);
1406 //x = VectorAdd(y, cog_projected);
1407 //free(y);
1408
1409 // roll up (project (x,y,z) on cylindrical coordinates (radius,arg,z))
1410 arg = 2.*M_PI*x[axis[0]]/(factors[0]) - M_PI; // is angle
1411 radius = 1./(2.*M_PI); // is length of sheet in units of axis vector, divide by pi to get radius (from circumference)
1412 // fprintf(stdout, "arg: %5.2f (c%2.2f,s%2.2f)\t",$arg, cos($arg), sin($arg));
1413 x[axis[0]] = cos(arg)*halfaxis[axis[0]]*(radius+x[axis[2]]/halfaxis[axis[2]]); // as both vectors are not normalized additional betrag has to be taken into account!
1414 x[axis[2]] = sin(arg)*halfaxis[axis[2]]*(radius+x[axis[2]]/halfaxis[axis[2]]); // due to the back-transformation from eigensystem to cartesian one
1415 //fprintf(stdout, "rotated: (%5.2f,%5.2f,%5.2f)\n",x[0],x[1],x[2]);
1416 atom_transformed = MatrixTrafo(Tubevector, x);
1417 fprintf(TubeFile, "%s\t%lg\t%lg\t%lg\n", name, atom_transformed[0], atom_transformed[1], atom_transformed[2]);
1418 // rotate and flip to align tube in z-direction
1419 x1 = atom_transformed[0]*cos(-angle) + atom_transformed[1] * sin(-angle);
1420 x2 = atom_transformed[0]*(-sin(-angle)) + atom_transformed[1] * cos(-angle);
1421 x3 = atom_transformed[2];
1422 fprintf(TubeFileAligned, "%s\t%lg\t%lg\t%lg\n", name, x3, x2, x1); // order so that symmetry is along z axis
1423 //fprintf(stdout, "%s\t%5.5lg\t%5.5lg\t%5.5lg\n", name, atom_transformed[0], atom_transformed[1] ,atom_transformed[2]);
1424
1425 Free(x, "Main: at stage Tube - x");
1426 Free(atom_transformed, "Main: at stage Tube - atom_transformed");
1427 }
1428
1429
1430 fclose(TubeFile);
1431 fclose(TubeFileAligned);
1432 //free(cog);
1433 //free(cog_projected);
1434 AddAtomicNumber(TubeFilename,numbersheet, Vector, Recivector); // prepend atomic number and comment
1435 AddAtomicNumber(TubeFilenameAligned,numbersheet, Vector, Recivector); // prepend atomic number and comment
1436 AddSheetInfo(TubeFilename,axis,chiral, factors, seed, numbercell, randomness);
1437 fprintf(stdout, "\nThere are %i atoms in the created tube.\n", numbersheet);
1438
1439 strncpy(stage, "Tube", 4);
1440 } else {
1441 }
1442
1443 TubeBuffer = ReadBuffer(TubeFilename, &length);
1444
1445 // ======================== STAGE: Torus =============================
1446 // The procedure for the torus is very much alike to the one used to make the
1447 // tube. Only the projection is not from 2d surface onto a cylindrical one but
1448 // from a cylindrial onto a torus surface
1449 // (x,y,z) <-> (cos(s)*(R+r*cos(t)), sin(s)*(R+rcos(t)), r*sin(t)).
1450 // Here t is the angle within the tube with radius r, s is the torus angle with
1451 // radius R. We get R from the tubelength (that's why we need lengthfactor to
1452 // make it long enough). And due to fact that we have it already upon a cylindrical
1453 // surface, r*cos(t) and r*sin(t) already reside in $minoraxis and $noaxis.
1454
1455 FILE *TorusFile;
1456
1457 Debug ("STAGE: Torus\n");
1458 if (!strncmp(stage, "Tube", 4)) {
1459 TorusFile = fopen(TorusFilename, "w");
1460 if (TorusFile == NULL) {
1461 fprintf(stderr, "ERROR: main - can't open %s for writing\n", TorusFilename);
1462 exit(255);
1463 }
1464 bufptr = TubeBuffer;
1465 bufptr += GetNextline(bufptr, line); // write numbers to file
1466 bufptr += GetNextline(bufptr, line); // write comment to file
1467
1468 //cog = CenterOfGravity(bufptr, numbersheet);
1469 //cog_projected = MatrixTrafoInverse(cog, TubevectorInverse);
1470 //fprintf(stdout, "\nCenter of Gravity at (%5.5lg\t%5.5lg\t%5.5lg) and projected at (%5.5lg\t%5.5lg\t%5.5lg)\n", cog[0], cog[1], cog[2], cog_projected[0], cog_projected[1], cog_projected[2]);
1471
1472 // determine half axis as tube vectors not necessarily have same length
1473 double halfaxis[NDIM];
1474 for (i=0;i<NDIM;i++)
1475 halfaxis[i] = Norm(Tubevector[axis[1]])/Norm(Tubevector[i]);
1476
1477 double arg, radius;
1478 for (i=0;i<numbersheet;i++) {
1479 // scan next atom
1480 bufptr += GetNextline(bufptr, line);
1481 sscanf(line, "%s %lg %lg %lg", name, &atom[0], &atom[1], &atom[2]);
1482
1483 // transform atom coordinates in cartesian system to the axis eigensystem
1484 x = MatrixTrafoInverse(atom, TubevectorInverse);
1485 //x = VectorAdd(y, cog_projected);
1486 //free(y);
1487
1488 // roll up (project (x,y,z) on cylindrical coordinates (radius,arg,z))
1489 arg = 2.*M_PI*x[axis[1]]/(factors[1]) - M_PI; // is angle
1490 radius = (factors[1])/(2.*M_PI) + x[axis[0]]/halfaxis[axis[0]]; // is length of sheet in units of axis vector, divide by pi to get radius (from circumference)
1491 // fprintf(stdout, "arg: %5.2f (c%2.2f,s%2.2f)\t",$arg, cos($arg), sin($arg));
1492 x[axis[0]] = cos(arg)*halfaxis[axis[0]]*radius; // as both vectors are not normalized additional betrag has to be taken into account!
1493 x[axis[1]] = sin(arg)*halfaxis[axis[1]]*radius; // due to the back-transformation from eigensystem to cartesian one
1494 //fprintf(stdout, "rotated: (%5.2f,%5.2f,%5.2f)\n",x[0],x[1],x[2]);
1495 atom_transformed = MatrixTrafo(Tubevector, x);
1496 fprintf(TorusFile, "%s\t%lg\t%lg\t%lg\n", name, atom_transformed[0], atom_transformed[1] ,atom_transformed[2]);
1497 //fprintf(stdout, "%s\t%5.5lg\t%5.5lg\t%5.5lg\n", name, atom_transformed[0], atom_transformed[1] ,atom_transformed[2]);
1498
1499 Free(x, "Main: at stage Torus - x");
1500 Free(atom_transformed, "Main: at stage Torus - atom_transformed");
1501 }
1502
1503 fclose(TorusFile);
1504 //free(cog);
1505 //free(cog_projected);
1506 AddAtomicNumber(TorusFilename,numbersheet, Vector, Recivector); // prepend atomic number and comment
1507 AddSheetInfo(TorusFilename,axis,chiral, factors, seed, numbercell, randomness);
1508 fprintf(stdout, "\nThere are %i atoms in the created torus.\n", numbersheet);
1509
1510 strncpy(stage, "Torus", 5);
1511 } else {
1512 }
1513
1514 // Free memory
1515 for (i=0; i<NDIM; i++ ) {
1516 Free(Vector[i], "Main: end of stages - *Vector");
1517 Free(Recivector[i], "Main: end of stages - *Recivector");
1518 Free(Tubevector[i], "Main: end of stages - *Tubevector");
1519 Free(TubevectorInverse[i], "Main: end of stages - *TubevectorInverse");
1520 }
1521 Free(atom, "Main: end of stages - atom");
1522 Free(Vector, "Main: end of stages - Vector");
1523 Free(Recivector, "Main: end of stages - Recivector");
1524 Free(Tubevector, "Main: end of stages - Tubevector");
1525 Free(TubevectorInverse, "Main: end of stages - TubevectorInverse");
1526 Free(randomness, "Main: at stage Sheet - randomness");
1527
1528 if (CellBuffer != NULL) Free(CellBuffer, "Main: end of stages - CellBuffer");
1529 if (SheetBuffer != NULL) Free(SheetBuffer, "Main: end of stages - SheetBuffer");
1530 if (TubeBuffer != NULL) Free(TubeBuffer, "Main: end of stages - TubeBuffer");
1531
1532 Free(CellFilename, "Main: end of stafes - CellFilename");
1533 Free(SheetFilename, "Main: end of stafes - CellFilename");
1534 Free(TubeFilename, "Main: end of stafes - CellFilename");
1535 Free(TorusFilename, "Main: end of stafes - CellFilename");
1536 Free(SheetFilenameAligned, "Main: end of stafes - CellFilename");
1537 Free(TubeFilenameAligned, "Main: end of stafes - CellFilename");
1538
1539 // exit
1540 exit(0);
1541}
Note: See TracBrowser for help on using the repository browser.