source: util/src/NanoCreator.c@ 1b192d

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

Newest tries to get NanoCreator finally working for all chiral angles. Nanotubes work for one direction, the other not. Hence, Nanotorus seam is clearly visible

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