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 | */
|
---|
21 | void * 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 | */
|
---|
41 | void * 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 | */
|
---|
59 | void 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 | */
|
---|
77 | void * 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 | */
|
---|
100 | char * 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 | */
|
---|
129 | int 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 | */
|
---|
156 | void 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 | */
|
---|
203 | void 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 | */
|
---|
237 | double *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 | }
|
---|
257 | double *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 | */
|
---|
282 | void 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 | */
|
---|
328 | void 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 | */
|
---|
342 | void 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 | */
|
---|
359 | double 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 | */
|
---|
375 | double * 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 | */
|
---|
400 | void 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 betrag1, betrag2;
|
---|
407 | int i;
|
---|
408 |
|
---|
409 | // first vector is untouched
|
---|
410 | // second vector
|
---|
411 | betrag1 = Projection(orthvector[axis[1]], orthvector[axis[0]]);
|
---|
412 | for (i=0;i<NDIM;i++)
|
---|
413 | orthvector[axis[0]][i] -= orthvector[axis[1]][i] * betrag1;
|
---|
414 | // third vector
|
---|
415 | betrag1 = Projection(orthvector[axis[0]], orthvector[axis[2]]);
|
---|
416 | betrag2 = Projection(orthvector[axis[1]], orthvector[axis[2]]);
|
---|
417 | for (i=0;i<NDIM;i++)
|
---|
418 | orthvector[axis[2]][i] -= orthvector[axis[0]][i] * betrag1 + orthvector[axis[1]][i] * betrag2;
|
---|
419 | }
|
---|
420 |
|
---|
421 | /** Computes projection of \a *vector2 onto \a *vector1.
|
---|
422 | * \param *vector1 reference vector
|
---|
423 | * \param *vector2 vector which is projected
|
---|
424 | * \return projection
|
---|
425 | */
|
---|
426 | double Projection(double *vector1, double *vector2)
|
---|
427 | {
|
---|
428 | if ((vector1 == NULL) || (vector2 == NULL)) {
|
---|
429 | fprintf(stderr, "ERROR: Projection: ptr to vector1 or vector2 NULL\n");
|
---|
430 | exit(255);
|
---|
431 | }
|
---|
432 | return (ScalarProduct(vector1, vector2)/Norm(vector1)/Norm(vector2));
|
---|
433 | }
|
---|
434 |
|
---|
435 | /** Determine scalar product between two vectors.
|
---|
436 | * \param *vector1 first vector
|
---|
437 | * \param *vector2 second vector
|
---|
438 | * \return scalar product
|
---|
439 | */
|
---|
440 | double ScalarProduct(double *vector1, double *vector2)
|
---|
441 | {
|
---|
442 | if ((vector1 == NULL) || (vector2 == NULL)) {
|
---|
443 | fprintf(stderr, "ERROR: ScalarProduct: ptr to vector1 or vector2 NULL\n");
|
---|
444 | exit(255);
|
---|
445 | }
|
---|
446 | double scp = 0.;
|
---|
447 | int i;
|
---|
448 |
|
---|
449 | for (i=0;i<NDIM;i++)
|
---|
450 | scp += vector1[i] * vector2[i];
|
---|
451 |
|
---|
452 | return scp;
|
---|
453 | }
|
---|
454 |
|
---|
455 | /** Computes norm of \a *vector.
|
---|
456 | * \param *vector pointer to NDIM vector
|
---|
457 | * \return norm of \a *vector
|
---|
458 | */
|
---|
459 | double Norm(double *vector)
|
---|
460 | {
|
---|
461 | if (vector == NULL) {
|
---|
462 | fprintf(stderr, "ERROR: Norm: ptr to vector NULL\n");
|
---|
463 | exit(255);
|
---|
464 | }
|
---|
465 | return sqrt(ScalarProduct(vector, vector));
|
---|
466 | }
|
---|
467 |
|
---|
468 | /** Prints vector to \a *file.
|
---|
469 | * \param *file file or e.g. stdout
|
---|
470 | * \param *vector vector to be printed
|
---|
471 | */
|
---|
472 | void PrintVector(FILE *file, double *vector)
|
---|
473 | {
|
---|
474 | if ((file == NULL) || (vector == NULL)) {
|
---|
475 | fprintf(stderr, "ERROR: PrintVector: ptr to file or vector NULL\n");
|
---|
476 | exit(255);
|
---|
477 | }
|
---|
478 | int i;
|
---|
479 | for (i=0;i<NDIM;i++)
|
---|
480 | fprintf(file, "%5.5f\t", vector[i]);
|
---|
481 | fprintf(file, "\n");
|
---|
482 | }
|
---|
483 |
|
---|
484 | /** Prints matrix to \a *file.
|
---|
485 | * \param *file file or e.g. stdout
|
---|
486 | * \param **matrix matrix to be printed
|
---|
487 | */
|
---|
488 | void PrintMatrix(FILE *file, double **matrix)
|
---|
489 | {
|
---|
490 | if ((file == NULL) || (matrix == NULL)) {
|
---|
491 | fprintf(stderr, "ERROR: PrintMatrix: ptr to file or matrix NULL\n");
|
---|
492 | exit(255);
|
---|
493 | }
|
---|
494 | int i,j;
|
---|
495 | for (i=0;i<NDIM;i++) {
|
---|
496 | for (j=0;j<NDIM;j++)
|
---|
497 | fprintf(file, "%5.5f\t", matrix[i][j]);
|
---|
498 | fprintf(file, "\n");
|
---|
499 | }
|
---|
500 | }
|
---|
501 |
|
---|
502 | /** Returns greatest common denominator.
|
---|
503 | * \param a first integer
|
---|
504 | * \param b second integer
|
---|
505 | * \return GCD of a and b
|
---|
506 | */
|
---|
507 | int GCD(int a, int b)
|
---|
508 | {
|
---|
509 | int c;
|
---|
510 | do {
|
---|
511 | c = a % b; /* Rest of integer divison */
|
---|
512 | a = b; b = c; /* flip the two values */
|
---|
513 | } while( c != 0);
|
---|
514 | return a;
|
---|
515 | }
|
---|
516 |
|
---|
517 | /** Determines the biggest diameter of a sheet.
|
---|
518 | * \param **matrix reference to NDIMxNDIM matrix with row vectors
|
---|
519 | * \param *axis reference to NDIM vector with permutation of axis indices [0,1,2]
|
---|
520 | * \param *factors factorsfor axis[0] and axis[1]
|
---|
521 | * \return biggest diameter of sheet
|
---|
522 | */
|
---|
523 | double DetermineBiggestDiameter(double **matrix, int *axis, int *factors)
|
---|
524 | {
|
---|
525 | if ((axis == NULL) || (factors == NULL) || (matrix == NULL)) {
|
---|
526 | fprintf(stderr, "ERROR: DetermineBiggestDiameter: ptr to factors, axis or matrix NULL\n");
|
---|
527 | exit(255);
|
---|
528 | }
|
---|
529 | double diameter[2] = {0.,0.};
|
---|
530 | int i, biggest;
|
---|
531 |
|
---|
532 | for (i=0;i<NDIM;i++) {
|
---|
533 | 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]);
|
---|
534 | 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]);
|
---|
535 | }
|
---|
536 | if ((diameter[0] - diameter[1]) > MYEPSILON) {
|
---|
537 | biggest = 0;
|
---|
538 | } else {
|
---|
539 | biggest = 1;
|
---|
540 | }
|
---|
541 | diameter[0] = sqrt(diameter[0]);
|
---|
542 | diameter[1] = sqrt(diameter[1]);
|
---|
543 | fprintf(stdout, "\n\nMajor diameter of the sheet is %5.5f, minor diameter is %5.5f.\n",diameter[biggest],diameter[(biggest+1)%2]);
|
---|
544 |
|
---|
545 | return diameter[biggest];
|
---|
546 | }
|
---|
547 |
|
---|
548 | /** Determines the center of gravity of atoms in a buffer \a bufptr with given \a number
|
---|
549 | * \param *bufptr pointer to char buffer with atoms in (name x y z)-manner
|
---|
550 | * \param number number of atoms/lines to scan
|
---|
551 | * \return NDIM vector (allocated doubles) pointing back to center of gravity
|
---|
552 | */
|
---|
553 | double * CenterOfGravity(char *bufptr, int number)
|
---|
554 | {
|
---|
555 | if (bufptr == NULL) {
|
---|
556 | fprintf(stderr, "ERROR: CenterOfGravity - bufptr NULL\n");
|
---|
557 | exit(255);
|
---|
558 | }
|
---|
559 | double *cog = calloc(sizeof(double)*NDIM, 0.);
|
---|
560 | if (cog == NULL) {
|
---|
561 | fprintf(stderr, "ERROR: CenterOfGravity - cog\n");
|
---|
562 | exit(255);
|
---|
563 | }
|
---|
564 | double *atom = Malloc(sizeof(double)*NDIM, "CenterOfGravity: atom");
|
---|
565 | char name[255], line[255];
|
---|
566 | int i,j;
|
---|
567 |
|
---|
568 | // Determine center of gravity
|
---|
569 | for (i=0;i<number;i++) {
|
---|
570 | bufptr += GetNextline(bufptr, line);
|
---|
571 | sscanf(line, "%s %lg %lg %lg", name, &atom[0], &atom[1], &atom[2]);
|
---|
572 | //fprintf(stdout, "Read Atom %s %lg %lg %lg\n", name, atom[0], atom[1], atom[2]);
|
---|
573 | for (j=0;j<NDIM;j++)
|
---|
574 | cog[j] += atom[j];
|
---|
575 | }
|
---|
576 | for (i=0;i<NDIM;i++)
|
---|
577 | cog[i] /= -number;
|
---|
578 |
|
---|
579 | Free(atom, "CenterOfGravity: atom");
|
---|
580 | return cog;
|
---|
581 | }
|
---|
582 |
|
---|
583 | // ================================= other functions ==============================
|
---|
584 |
|
---|
585 | void Debug(char *msg)
|
---|
586 | {
|
---|
587 | if (msg == NULL) {
|
---|
588 | fprintf(stderr, "ERROR: Debug: ptr to msg NULL\n");
|
---|
589 | exit(255);
|
---|
590 | }
|
---|
591 | fprintf(stdout, "%s", msg);
|
---|
592 | }
|
---|
593 |
|
---|
594 | // --------------------------------------- M A I N ---------------------------------------------------
|
---|
595 | int main(int argc, char **argv) {
|
---|
596 | char *filename = NULL;
|
---|
597 | char *CellFilename = NULL, *SheetFilename = NULL, *TubeFilename = NULL, *TorusFilename = NULL;
|
---|
598 | char *SheetFilenameAligned = NULL, *TubeFilenameAligned = NULL;
|
---|
599 | double **Vector, **Recivector = NULL, **Tubevector = NULL, **TubevectorInverse = NULL;
|
---|
600 | double *atom = NULL, *atom_transformed = NULL;
|
---|
601 | double *x = NULL, *coord = NULL, *tempvector = NULL, *offset = NULL;
|
---|
602 | //double *cog = NULL, *cog_projected = NULL;
|
---|
603 | char stage[6];
|
---|
604 | int axis[NDIM] = {0,1,2}, chiral[2] = {1,1}, factors[NDIM] = {1,1,1};
|
---|
605 | char name[255], line[255], input = 'n';
|
---|
606 | char *CellBuffer = NULL, *SheetBuffer = NULL, *TubeBuffer = NULL, *bufptr = NULL;
|
---|
607 | double *randomness = NULL, percentage; // array with percentages for presence in sheet and beyond
|
---|
608 | int i,j, ggT;
|
---|
609 | int length;
|
---|
610 |
|
---|
611 | // Read command line arguments
|
---|
612 | if (argc <= 2) {
|
---|
613 | 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]);
|
---|
614 | exit(255);
|
---|
615 | } else {
|
---|
616 | // store variables
|
---|
617 | filename = argv[1];
|
---|
618 | strncpy(stage, argv[2], 5);
|
---|
619 | fprintf(stdout, "I will begin at stage %s.\n", stage);
|
---|
620 |
|
---|
621 | // build filenames
|
---|
622 | char *ptr = strrchr(filename, '.');
|
---|
623 | int length = strlen(filename);
|
---|
624 | if (ptr != NULL) {
|
---|
625 | length = ((int)(ptr-filename) >= length-5) ? (int)(ptr-filename) : length;
|
---|
626 | filename[length] = '\0'; // eventueller
|
---|
627 | }
|
---|
628 | fprintf(stdout, "I will use \'%s' as base for the filenames.\n\n", filename);
|
---|
629 | CellFilename = Malloc(sizeof(char)*(length+10), "Main: CellFilename");
|
---|
630 | SheetFilename = Malloc(sizeof(char)*(length+11), "Main: SheetFilename");
|
---|
631 | TubeFilename = Malloc(sizeof(char)*(length+10), "Main: TubeFilename");
|
---|
632 | TorusFilename = Malloc(sizeof(char)*(length+11), "Main: TorusFilename");
|
---|
633 | SheetFilenameAligned = Malloc(sizeof(char)*(length+20), "Main: SheetFilenameAligned");
|
---|
634 | TubeFilenameAligned = Malloc(sizeof(char)*(length+19), "Main: TubeFilenameAligned");
|
---|
635 | sprintf(CellFilename, "%s.Cell.xyz", filename);
|
---|
636 | sprintf(SheetFilename, "%s.Sheet.xyz", filename);
|
---|
637 | sprintf(TubeFilename, "%s.Tube.xyz", filename);
|
---|
638 | sprintf(TorusFilename, "%s.Torus.xyz", filename);
|
---|
639 | sprintf(SheetFilenameAligned, "%s.Sheet.Aligned.xyz", filename);
|
---|
640 | sprintf(TubeFilenameAligned, "%s.Tube.Aligned.xyz", filename);
|
---|
641 | }
|
---|
642 |
|
---|
643 | // Allocating memory
|
---|
644 | Debug ("Allocating memory\n");
|
---|
645 | atom = (double *) Malloc(sizeof(double)*NDIM, "Main: atom");
|
---|
646 | Vector = (double **) Malloc(sizeof(double *)*NDIM, "Main: *Vector");
|
---|
647 | Recivector = (double **) Malloc(sizeof(double *)*NDIM, "Main: *Recivector");
|
---|
648 | Tubevector = (double **) Malloc(sizeof(double *)*NDIM, "Main: *Tubevector");
|
---|
649 | TubevectorInverse = (double **) Malloc(sizeof(double *)*NDIM, "Main: *TubevectorInverse");
|
---|
650 | for (i=0; i<NDIM; i++ ) {
|
---|
651 | Vector[i] = (double *) Malloc(sizeof(double)*NDIM, "Main: Vector");
|
---|
652 | Recivector[i] = (double *) Malloc(sizeof(double)*NDIM, "Main: Recivector");
|
---|
653 | Tubevector[i] = (double *) Malloc(sizeof(double)*NDIM, "Main: Tubevector");
|
---|
654 | TubevectorInverse[i] = (double *) Malloc(sizeof(double)*NDIM, "Main: TubevectorInverse");
|
---|
655 | }
|
---|
656 |
|
---|
657 | // ======================== STAGE: Cell ==============================
|
---|
658 | // The cell is simply created by transforming relative coordinates within the cell
|
---|
659 | // into cartesian ones using the unit cell vectors.
|
---|
660 |
|
---|
661 | double volume;
|
---|
662 | int numbercell;
|
---|
663 | FILE *CellFile;
|
---|
664 |
|
---|
665 | Debug ("STAGE: None\n");
|
---|
666 | // Read cell vectors from stdin or from file
|
---|
667 | if (!strncmp(stage, "Non", 3)) {
|
---|
668 | 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");
|
---|
669 | fprintf(stdout, "Enter 1st primitive vector: ");
|
---|
670 | fscanf(stdin, "%lg %lg %lg", &Vector[0][0], &Vector[0][1], &Vector[0][2]);
|
---|
671 | fprintf(stdout, "Enter 2nd primitive vector: ");
|
---|
672 | fscanf(stdin, "%lg %lg %lg", &Vector[1][0], &Vector[1][1], &Vector[1][2]);
|
---|
673 | fprintf(stdout, "Enter 3rd primitive vector: ");
|
---|
674 | fscanf(stdin, "%lg %lg %lg", &Vector[2][0], &Vector[2][1], &Vector[2][2]);
|
---|
675 | fprintf(stdout,"Unit vectors are\n");
|
---|
676 | PrintMatrix(stdout, Vector);
|
---|
677 | } else {
|
---|
678 | char *ptr = NULL;
|
---|
679 | char dummy[10];
|
---|
680 | CellBuffer = bufptr = ReadBuffer(CellFilename, &length);
|
---|
681 | for (i=0;i<NDIM;i++) {
|
---|
682 | sprintf(dummy, "a(%i) = ", i+1);
|
---|
683 | fprintf(stdout, "%s", dummy);
|
---|
684 | while ((length = GetNextline(bufptr, line)) != -1) {
|
---|
685 | bufptr += (length)*sizeof(char);
|
---|
686 | //fprintf(stdout, "LINE at %p: %s\n", bufptr, line);
|
---|
687 | if ((ptr = strstr(line, dummy)) != NULL)
|
---|
688 | break;
|
---|
689 | }
|
---|
690 | ptr += strlen(dummy);
|
---|
691 | sscanf(ptr, "%lg %lg %lg", &Vector[i][0], &Vector[i][1], &Vector[i][2]);
|
---|
692 | fprintf(stdout, "%5.5lg %5.5lg %5.5lg\n", Vector[i][0], Vector[i][1], Vector[i][2]);
|
---|
693 | }
|
---|
694 | }
|
---|
695 |
|
---|
696 | volume = Determinant(Vector);
|
---|
697 | fprintf(stdout,"Volume is %lg\n", volume);
|
---|
698 | MatrixInversion(Vector, Recivector);
|
---|
699 | //Transpose(Recivector); // inverse's got row vectors if normal matrix' got column ones
|
---|
700 | fprintf(stdout, "Reciprocal vector is ");
|
---|
701 | PrintMatrix(stdout, Recivector);
|
---|
702 | fprintf(stdout, "Reciprocal volume is %lg\n", Determinant(Recivector));
|
---|
703 |
|
---|
704 | fprintf(stdout, "Vector magnitudes: %5.5lg %5.5lg %5.5lg\n", Norm(Vector[0]), Norm(Vector[1]), Norm(Vector[2]));
|
---|
705 |
|
---|
706 | Debug ("STAGE: Cell\n");
|
---|
707 | if (!strncmp(stage, "Non", 3)) {
|
---|
708 | fprintf(stdout, "\nHow many atoms are in the unit cell: ");
|
---|
709 | fscanf(stdin, "%i", &numbercell);
|
---|
710 | CellFile = fopen(CellFilename, "w");
|
---|
711 | if (CellFile == NULL) {
|
---|
712 | fprintf(stderr, "ERROR: main - can't open %s for writing\n", CellFilename);
|
---|
713 | exit(255);
|
---|
714 | }
|
---|
715 | fprintf(stdout, "\nNext, you have to enter each atom in the cell as follows, e.g.\n");
|
---|
716 | fprintf(stdout, "Enter \'ChemicalSymbol X Y Z\' (relative to primitive vectors): C 0.5 0.25 0.5\n\n");
|
---|
717 | for (i = 0; i < numbercell; i++) {
|
---|
718 | fprintf(stdout, "Enter for atom %i \'ChemicalSymbol X Y Z\': ", i+1);
|
---|
719 | fscanf(stdin, "%s %lg %lg %lg", name, &atom[0], &atom[1], &atom[2]);
|
---|
720 | tempvector = MatrixTrafo(Vector, atom);
|
---|
721 | fprintf(stdout, "Atom %i: %s %5.5lg %5.5lg %5.5lg\n", i, name, tempvector[0], tempvector[1], tempvector[2]);
|
---|
722 | fprintf(stdout, "Probe: %s %5.5lg %5.5lg %5.5lg\n", name,
|
---|
723 | atom[0]*Vector[0][0]+atom[1]*Vector[1][0]+atom[2]*Vector[2][0],
|
---|
724 | atom[0]*Vector[0][1]+atom[1]*Vector[1][1]+atom[2]*Vector[2][1],
|
---|
725 | atom[0]*Vector[0][2]+atom[1]*Vector[1][2]+atom[2]*Vector[2][2]
|
---|
726 | );
|
---|
727 | fprintf(CellFile, "%s %lg %lg %lg\n", name, tempvector[0], tempvector[1], tempvector[2]);
|
---|
728 | Free(tempvector, "Main: At stage Cell - tempvector");
|
---|
729 | }
|
---|
730 | fflush(CellFile);
|
---|
731 | fclose(CellFile);
|
---|
732 | AddAtomicNumber(CellFilename, numbercell, Vector, Recivector);
|
---|
733 |
|
---|
734 | CellBuffer = ReadBuffer(CellFilename, &length);
|
---|
735 |
|
---|
736 | sprintf(stage, "Cell");
|
---|
737 | } else {
|
---|
738 | bufptr = CellBuffer;
|
---|
739 | GetNextline(bufptr, line);
|
---|
740 | sscanf(line, "%i", &numbercell);
|
---|
741 | }
|
---|
742 |
|
---|
743 | fprintf(stdout, "\nThere are %i atoms in the cell.\n", numbercell);
|
---|
744 |
|
---|
745 | // ======================== STAGE: Sheet =============================
|
---|
746 | // The sheet is a bit more complex. We read the cell in cartesian coordinates
|
---|
747 | // from the file. Next, we have to rotate the unit cell vectors by the so called
|
---|
748 | // chiral angle. This gives a slanted and elongated section upon the sheet of
|
---|
749 | // periodically repeated original unit cells. It only matches up if the factors
|
---|
750 | // were all integer! (That's why the rotation is discrete and the chiral angle
|
---|
751 | // specified not as (cos alpha, sin alpha) but as (n,m)) Also, we want this
|
---|
752 | // section to be rectangular, thus we orthogonalize the original unit vectors
|
---|
753 | // to gain our (later) tube axis.
|
---|
754 | // By looking at the biggest possible diameter we know whose original cells to
|
---|
755 | // look at and check if their respective compounds (contained atoms) still reside
|
---|
756 | // in the rotated, elongated section we need for the later tube.
|
---|
757 | // Then in a for loop we go through every cell. By projecting the vector leading
|
---|
758 | // from the origin to the specific atom down onto the major and minor axis we
|
---|
759 | // know if it's still within the boundaries spanned by these rotated and elongated
|
---|
760 | // (radius-, length factor) unit vectors or not. If yes, its coordinates are
|
---|
761 | // written to file.
|
---|
762 |
|
---|
763 | int numbersheet, biggestdiameter, sheetnr[NDIM], tmp, seed;
|
---|
764 | double x1,x2,x3, angle;
|
---|
765 | char flag = 'n';
|
---|
766 | FILE *SheetFile = NULL;
|
---|
767 | FILE *SheetFileAligned = NULL;
|
---|
768 |
|
---|
769 | Debug ("STAGE: Sheet\n");
|
---|
770 | if (!strncmp(stage, "Cell", 4)) {
|
---|
771 | fprintf(stdout, "\nEnter seed unequal 0 if any of the bonds shall have a randomness in their being: ");
|
---|
772 | fscanf(stdin, "%d", &seed);
|
---|
773 | if (seed != 0)
|
---|
774 | input = 'y';
|
---|
775 | randomness = (double *) Malloc(sizeof(double)*numbercell, "Main: at sheet - randomness");
|
---|
776 | for(i=0;i<numbercell;i++)
|
---|
777 | randomness[i] = 0.;
|
---|
778 | i = 0;
|
---|
779 | fprintf(stdout, "\n");
|
---|
780 | while (input == 'y') {
|
---|
781 | fprintf(stdout, "Enter atom number (-1 0 to end) and percentage (0.0...1.0): ");
|
---|
782 | fscanf(stdin, "%d %lg", &i, &percentage);
|
---|
783 | if (i == -1) { input = 'n'; fprintf(stdout, "Breaking\n"); }
|
---|
784 | else { randomness[i] = 1.-percentage; }
|
---|
785 | };
|
---|
786 |
|
---|
787 | fprintf(stdout, "\nSpecify the axis permutation that is going to be perpendicular to the sheet [tubeaxis, torusaxis, noaxis]: ");
|
---|
788 | fscanf(stdin, "%d %d %d", &axis[0], &axis[1], &axis[2]);
|
---|
789 | fprintf(stdout, "axis: %d %d %d\n", axis[0], axis[1], axis[2]);
|
---|
790 | do {
|
---|
791 | fprintf(stdout, "\nNow specify the two natural numbers (m n) defining the chiral angle, \nif the result is crap, try flipping to (m,n): ");
|
---|
792 | fscanf(stdin, "%d %d", &chiral[0], &chiral[1]);
|
---|
793 | ggT = GCD(2*chiral[1]+chiral[0],2*chiral[0]+chiral[1]);
|
---|
794 | fprintf(stdout, "Greatest Common Denominator of (2n+m, 2m+n) is %d\n", ggT);
|
---|
795 | fprintf(stdout, "chiral0: %d\tchiral1: %d\n", chiral[0], chiral[1]);
|
---|
796 | for (i=0;i<NDIM;i++) {
|
---|
797 | //Tubevector[axis[0]][i] = (double)chiral[0] * Vector[axis[0]][i] + (double)chiral[1] * Vector[axis[1]][i];
|
---|
798 | Tubevector[axis[0]][i] = chiral[0] * Vector[axis[0]][i] + chiral[1] * Vector[axis[1]][i];
|
---|
799 | //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];
|
---|
800 | Tubevector[axis[1]][i] = -chiral[1] * Vector[axis[0]][i] + chiral[0] * Vector[axis[1]][i];
|
---|
801 | //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];
|
---|
802 | // 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",
|
---|
803 | // (double)chiral[0], Vector[axis[0]][i], (double)chiral[1], Vector[axis[1]][i],
|
---|
804 | // (double)chiral[0] * Vector[axis[0]][i], (double)chiral[1] * Vector[axis[1]][i],
|
---|
805 | // Tubevector[axis[0]][i]);
|
---|
806 | Tubevector[axis[2]][i] = Vector[axis[2]][i];
|
---|
807 | }
|
---|
808 | /* fprintf(stdout, "Vector\n");
|
---|
809 | PrintMatrix(stdout, Vector);
|
---|
810 | fprintf(stdout, "Tubevector\n");
|
---|
811 | PrintMatrix(stdout, Tubevector);
|
---|
812 | for (i=0;i<NDIM;i++) {
|
---|
813 | fprintf(stdout, "Tubevector %d in Unit cell vectors:\t", axis[i]);
|
---|
814 | tempvector = MatrixTrafoInverse(Tubevector[axis[i]], Recivector);
|
---|
815 | PrintVector(stdout, tempvector);
|
---|
816 | Free(tempvector, "Main:tempvector");
|
---|
817 | }*/
|
---|
818 |
|
---|
819 | // Give info for length and radius factors
|
---|
820 | 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",
|
---|
821 | acos(Projection(Vector[axis[0]], Tubevector[axis[0]]))/M_PI*180.,
|
---|
822 | Norm(Tubevector[axis[0]])/(2.*M_PI),
|
---|
823 | Norm(Tubevector[axis[1]]),
|
---|
824 | Norm(Tubevector[axis[1]])/(2.*M_PI)
|
---|
825 | );
|
---|
826 | fprintf(stdout, "\nGive integer factors for length and radius of tube (multiple of %d suggested) : ", ggT);
|
---|
827 | fscanf(stdin, "%d %d", &factors[1], &factors[0]);
|
---|
828 | 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",
|
---|
829 | acos(Projection(Vector[axis[0]], Tubevector[axis[0]]))/M_PI*180.,
|
---|
830 | (double)factors[0]*Norm(Tubevector[axis[0]])/(2.*M_PI),
|
---|
831 | (double)factors[1]*Norm(Tubevector[axis[1]]),
|
---|
832 | (double)factors[1]*Norm(Tubevector[axis[1]])/(2.*M_PI)
|
---|
833 | );
|
---|
834 | fprintf(stdout, "Satisfied? [yn] ");
|
---|
835 | fscanf(stdin, "%c", &flag);
|
---|
836 | fscanf(stdin, "%c", &flag);
|
---|
837 | } while (flag != 'y');
|
---|
838 | } else {
|
---|
839 | char *ptr = NULL;
|
---|
840 | char dummy[10];
|
---|
841 | double dummydouble;
|
---|
842 | SheetBuffer = bufptr = ReadBuffer(SheetFilename, &length);
|
---|
843 | bufptr += (GetNextline(bufptr, line))*sizeof(char);
|
---|
844 | sscanf(line, "%d", &numbersheet);
|
---|
845 |
|
---|
846 | // retrieve axis permutation
|
---|
847 | sprintf(dummy, "Axis");
|
---|
848 | fprintf(stdout, "%s ", dummy);
|
---|
849 | while ((length = GetNextline(bufptr, line)) != 0) {
|
---|
850 | bufptr += (length)*sizeof(char);
|
---|
851 | if ((ptr = strstr(line, dummy)) != NULL)
|
---|
852 | break;
|
---|
853 | }
|
---|
854 | if (length == 0) {
|
---|
855 | fprintf(stderr, "ERROR: Main at stage Sheet - could not find %s in %s\n", dummy, SheetFilename);
|
---|
856 | exit(255);
|
---|
857 | }
|
---|
858 | ptr += strlen(dummy);
|
---|
859 | sscanf(ptr, "%d %d %d", &axis[0], &axis[1], &axis[2]);
|
---|
860 | fprintf(stdout, "%d %d %d\n", axis[0], axis[1], axis[2]);
|
---|
861 |
|
---|
862 | // retrieve chiral numbers
|
---|
863 | sprintf(dummy, "(n,m)");
|
---|
864 | fprintf(stdout, "%s ", dummy);
|
---|
865 | while ((length = GetNextline(bufptr, line)) != 0) {
|
---|
866 | bufptr += (length)*sizeof(char);
|
---|
867 | if ((ptr = strstr(line, dummy)) != NULL)
|
---|
868 | break;
|
---|
869 | }
|
---|
870 | if (length == 0) {
|
---|
871 | fprintf(stderr, "ERROR: Main at stage Sheet - could not find %s in %s\n", dummy, SheetFilename);
|
---|
872 | exit(255);
|
---|
873 | }
|
---|
874 | ptr += strlen(dummy);
|
---|
875 | sscanf(ptr, "%d %d", &chiral[0], &chiral[1]);
|
---|
876 | fprintf(stdout, "%d %d\n", chiral[0], chiral[1]);
|
---|
877 | ggT = GCD(2*chiral[1]+chiral[0],2*chiral[0]+chiral[1]);
|
---|
878 | fprintf(stdout, "Greatest Common Denominator of (2n+m, 2m+n) is %d\n", ggT);
|
---|
879 |
|
---|
880 | // retrieve length and radius factors
|
---|
881 | sprintf(dummy, "factors");
|
---|
882 | fprintf(stdout, "%s ", dummy);
|
---|
883 | while ((length = GetNextline(bufptr, line)) != 0) {
|
---|
884 | bufptr += (length)*sizeof(char);
|
---|
885 | if ((ptr = strstr(line, dummy)) != NULL)
|
---|
886 | break;
|
---|
887 | }
|
---|
888 | if (length == 0) {
|
---|
889 | fprintf(stderr, "ERROR: Main at stage Sheet - could not find %s in %s\n", dummy, SheetFilename);
|
---|
890 | exit(255);
|
---|
891 | }
|
---|
892 | ptr += strlen(dummy);
|
---|
893 | sscanf(ptr, "%d %d %d", &factors[0], &factors[1], &factors[2]);
|
---|
894 | fprintf(stdout, "%d %d %d\n", factors[0], factors[1], factors[2]);
|
---|
895 |
|
---|
896 | // create Tubevectors
|
---|
897 | for (i=0;i<NDIM;i++) {
|
---|
898 | Tubevector[axis[0]][i] = chiral[0] * Vector[axis[0]][i] + chiral[1] * Vector[axis[1]][i];
|
---|
899 | //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];
|
---|
900 | Tubevector[axis[1]][i] = -chiral[1] * Vector[axis[0]][i] + chiral[0] * Vector[axis[1]][i];
|
---|
901 | //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];
|
---|
902 | Tubevector[axis[2]][i] = Vector[axis[2]][i];
|
---|
903 | }
|
---|
904 |
|
---|
905 | // retrieve seed ...
|
---|
906 | randomness = (double *) Calloc(sizeof(double)*numbercell, 0., "Main: at sheet - randomness");
|
---|
907 | sprintf(dummy, "seed");
|
---|
908 | fprintf(stdout, "%s ", dummy);
|
---|
909 | while ((length = GetNextline(bufptr, line)) != 0) {
|
---|
910 | bufptr += (length)*sizeof(char);
|
---|
911 | if ((ptr = strstr(line, dummy)) != NULL)
|
---|
912 | break;
|
---|
913 | }
|
---|
914 | if (length == 0) {
|
---|
915 | fprintf(stderr, "ERROR: Main at stage Sheet - could not find %s in %s\n", dummy, SheetFilename);
|
---|
916 | exit(255);
|
---|
917 | }
|
---|
918 | ptr += strlen(dummy);
|
---|
919 | sscanf(ptr, "%d", &seed);
|
---|
920 | fprintf(stdout, "%d\n", seed);
|
---|
921 |
|
---|
922 | // ... and randomness
|
---|
923 | if (seed != 0) { // only parse for values if a seed, i.e. randomness wanted, was specified
|
---|
924 | sprintf(dummy, "Randomness");
|
---|
925 | fprintf(stdout, "%s\n", dummy);
|
---|
926 | while ((length = GetNextline(bufptr, line)) != 0) {
|
---|
927 | bufptr += (length)*sizeof(char);
|
---|
928 | if ((ptr = strstr(line, dummy)) != NULL)
|
---|
929 | break;
|
---|
930 | }
|
---|
931 | if (length == 0) {
|
---|
932 | fprintf(stderr, "ERROR: Main at stage Sheet - could not find %s in %s\n", dummy, SheetFilename);
|
---|
933 | exit(255);
|
---|
934 | }
|
---|
935 | sprintf(dummy, "probability values");
|
---|
936 | for (i=0;i<numbercell;i++) {
|
---|
937 | length = GetNextline(bufptr, line);
|
---|
938 | if (length == 0) {
|
---|
939 | fprintf(stderr, "ERROR: Main at stage Sheet - could not find %s in %s\n", dummy, SheetFilename);
|
---|
940 | exit(255);
|
---|
941 | }
|
---|
942 | bufptr += (length)*sizeof(char);
|
---|
943 | sscanf(line, "%d %lg", &j, &dummydouble);
|
---|
944 | randomness[j] = dummydouble;
|
---|
945 | fprintf(stdout, "%d %g\n", j, randomness[j]);
|
---|
946 | }
|
---|
947 | }
|
---|
948 | }
|
---|
949 |
|
---|
950 | //Orthogonalize(Tubevector,axis);
|
---|
951 | angle = acos(Projection(Vector[axis[0]], Vector[axis[1]])); // calcs angle between shanks in unit cell
|
---|
952 | fprintf(stdout, "The basic angle between the two shanks of the unit cell is %lg\n", angle/M_PI*180.);
|
---|
953 | angle = acos(Projection(Tubevector[axis[0]], Tubevector[axis[1]])); // calcs angle between shanks in unit cell
|
---|
954 | fprintf(stdout, "The basic angle between the two shanks of the tube unit cell is %lg\n", angle/M_PI*180.);
|
---|
955 | //angle -= acos(Projection(Vector[axis[0]], Tubevector[axis[0]]));
|
---|
956 | //angle = 30./180.*M_PI - acos(Projection(Vector[axis[0]], Tubevector[axis[0]]));
|
---|
957 | angle = - acos(Projection(Tubevector[axis[0]], Vector[axis[0]]));
|
---|
958 | fprintf(stdout, "The relative alignment rotation angle then is %lg\n", angle/M_PI*180.);
|
---|
959 | angle += acos(Projection(Vector[axis[0]], Vector[axis[1]]))/2.;
|
---|
960 | fprintf(stdout, "The absolute alignment rotation angle then is %lg\n", angle/M_PI*180.);
|
---|
961 | 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",
|
---|
962 | acos(Projection(Vector[axis[0]], Tubevector[axis[0]]))/M_PI*180.,
|
---|
963 | (double)factors[0]*Norm(Tubevector[axis[0]])/(2.*M_PI),
|
---|
964 | (double)factors[1]*Norm(Tubevector[axis[1]]),
|
---|
965 | (double)factors[1]*Norm(Tubevector[axis[1]])/(2.*M_PI)
|
---|
966 | );
|
---|
967 | Orthogonalize(Tubevector, axis); // with correct translational vector, not needed anymore (? what's been done here. Hence, re-inserted)
|
---|
968 | fprintf(stdout, "Tubevector magnitudes: %5.5lg %5.5lg %5.5lg\n", Norm(Tubevector[0]), Norm(Tubevector[1]), Norm(Tubevector[2]));
|
---|
969 | fprintf(stdout, "Tubebvectors are \n");
|
---|
970 | PrintMatrix(stdout, Tubevector);
|
---|
971 | MatrixInversion(Tubevector, TubevectorInverse);
|
---|
972 | //Transpose(TubevectorInverse);
|
---|
973 | fprintf(stdout, "Vector\n");
|
---|
974 | PrintMatrix(stdout, Vector);
|
---|
975 | fprintf(stdout, "TubevectorInverse\n");
|
---|
976 | PrintMatrix(stdout, TubevectorInverse);
|
---|
977 | for (i=0;i<NDIM;i++) {
|
---|
978 | fprintf(stdout, "Vector %d in TubeVectorInverse vectors:\t", axis[i]);
|
---|
979 | tempvector = MatrixTrafoInverse(Vector[axis[i]], TubevectorInverse);
|
---|
980 | PrintVector(stdout, tempvector);
|
---|
981 | Free(tempvector, "Main:tempvector");
|
---|
982 | }
|
---|
983 | fprintf(stdout, "Reciprocal Tubebvectors are \n");
|
---|
984 | PrintMatrix(stdout, TubevectorInverse);
|
---|
985 | fprintf(stdout, "Tubevector magnitudes: %5.5lg %5.5lg %5.5lg\n", Norm(Tubevector[0]), Norm(Tubevector[1]), Norm(Tubevector[2]));
|
---|
986 |
|
---|
987 | biggestdiameter = DetermineBiggestDiameter(Tubevector, axis, factors);
|
---|
988 | for (i=0;i<NDIM;i++) {
|
---|
989 | sheetnr[i] = 0;
|
---|
990 | }
|
---|
991 | for (i=0;i<NDIM;i++) {
|
---|
992 | for (j=0;j<NDIM;j++) {
|
---|
993 | // sheetnr[j] = ceil(biggestdiameter/Norm(Vector[j]));
|
---|
994 | if (fabs(Vector[i][j]) > MYEPSILON) {
|
---|
995 | tmp = ceil(biggestdiameter/fabs(Vector[i][j]));
|
---|
996 | } else {
|
---|
997 | tmp = 0;
|
---|
998 | }
|
---|
999 | sheetnr[j] = sheetnr[j] > tmp ? sheetnr[j] : tmp;
|
---|
1000 | }
|
---|
1001 | }
|
---|
1002 | fprintf(stdout, "Maximum indices to regard: %d %d %d\n", sheetnr[0], sheetnr[1], sheetnr[2]);
|
---|
1003 | for (i=0;i<NDIM;i++) {
|
---|
1004 | 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]));
|
---|
1005 | }
|
---|
1006 |
|
---|
1007 | //if (!strncmp(stage, "Cell", 4)) {
|
---|
1008 | // parse in atoms for quicker processing
|
---|
1009 | struct Atoms *atombuffer = malloc(sizeof(struct Atoms)*numbercell);
|
---|
1010 | bufptr = CellBuffer;
|
---|
1011 | bufptr += GetNextline(bufptr, line)*sizeof(char);
|
---|
1012 | bufptr += GetNextline(bufptr, line)*sizeof(char);
|
---|
1013 | for (i=0;i<numbercell;i++) {
|
---|
1014 | if ((length = GetNextline(bufptr, line)) != 0) {
|
---|
1015 | bufptr += length*sizeof(char);
|
---|
1016 | sscanf(line, "%s %lg %lg %lg", atombuffer[i].name, &(atombuffer[i].x[0]), &(atombuffer[i].x[1]), &(atombuffer[i].x[2]));
|
---|
1017 | 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]);
|
---|
1018 | } else {
|
---|
1019 | fprintf(stdout, "Error reading Atom Nr. %i\n", i+1);
|
---|
1020 | break;
|
---|
1021 | }
|
---|
1022 | }
|
---|
1023 | SheetFile = fopen(SheetFilename, "w");
|
---|
1024 | if (SheetFile == NULL) {
|
---|
1025 | fprintf(stderr, "ERROR: main - can't open %s for writing\n", SheetFilename);
|
---|
1026 | exit(255);
|
---|
1027 | }
|
---|
1028 | SheetFileAligned = fopen(SheetFilenameAligned, "w");
|
---|
1029 | if (SheetFile == NULL) {
|
---|
1030 | fprintf(stderr, "ERROR: main - can't open %s for writing\n", SheetFilenameAligned);
|
---|
1031 | exit(255);
|
---|
1032 | }
|
---|
1033 | // Now create the sheet
|
---|
1034 | double index[NDIM];
|
---|
1035 | int nr;//, nummer = 0;
|
---|
1036 | numbersheet = 0;
|
---|
1037 | index[axis[2]] = 0;
|
---|
1038 | // initialise pseudo random number generator with given seed
|
---|
1039 | fprintf(stdout, "Initialising pseudo random number generator with given seed %d.\n", seed);
|
---|
1040 | srand(seed);
|
---|
1041 | //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 ...
|
---|
1042 | 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 ...
|
---|
1043 | //for (index[axis[1]] = 0; index[axis[1]] <= sheetnr[axis[1]]; index[axis[1]]++) { // These are all the cells that need be checked on
|
---|
1044 | 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
|
---|
1045 | // Calculate offset in cartesian coordinates
|
---|
1046 | offset = MatrixTrafo(Vector, index);
|
---|
1047 |
|
---|
1048 | //fprintf(stdout, "Now dealing with numbercell atoms in unit cell at R = (%lg,%lg,%lg)\n", offset[0], offset[1], offset[2]);
|
---|
1049 | for (nr = 0; nr < numbercell; nr++) {
|
---|
1050 | percentage = rand()/(RAND_MAX+1.0);
|
---|
1051 | //fprintf(stdout, "Lucky number for %d is %lg >? %lg\n", nr, percentage, randomness[nr]);
|
---|
1052 | if (percentage >= randomness[nr]) {
|
---|
1053 | // Create coordinates at atom site
|
---|
1054 | coord = VectorAdd(atombuffer[nr].x, offset);
|
---|
1055 | //fprintf(stdout, "Atom Nr. %i: ", (numbersheet+1));
|
---|
1056 | //PrintVector(stdout, coord);
|
---|
1057 | // project down on major and minor Tubevectors and check for length if out of sheet
|
---|
1058 | tempvector = MatrixTrafoInverse(coord, TubevectorInverse);
|
---|
1059 | if (((tempvector[axis[0]] + MYEPSILON) >= 0) && ((factors[0] - tempvector[axis[0]]) > MYEPSILON) &&
|
---|
1060 | ((tempvector[axis[1]] + MYEPSILON) >= 0) && ((factors[1] - tempvector[axis[1]]) > MYEPSILON) &&
|
---|
1061 | ((tempvector[axis[2]] + MYEPSILON) >= 0) && ((factors[2] - tempvector[axis[2]]) > MYEPSILON)) { // check if within rotated cell numbersheet++;
|
---|
1062 | //if (nummer >= 2) strcpy(atombuffer[nr].name, "O");
|
---|
1063 | //nummer++;
|
---|
1064 | fprintf(SheetFile, "%s\t%5.5lg\t%5.5lg\t%5.5lg\n", atombuffer[nr].name, coord[0], coord[1], coord[2]);
|
---|
1065 | // rotate to align the sheet in xy plane
|
---|
1066 | x1 = coord[0]*cos(-angle) + coord[1] * sin(-angle);
|
---|
1067 | x2 = coord[0]*(-sin(-angle)) + coord[1] * cos(-angle);
|
---|
1068 | x3 = coord[2];
|
---|
1069 | fprintf(SheetFileAligned, "%s\t%5.5lg\t%5.5lg\t%5.5lg\n", atombuffer[nr].name, x1, x2, x3);
|
---|
1070 | //fprintf(SheetFile, "O\t%5.5lg\t%5.5lg\t%5.5lg\n", coord[0], coord[1], coord[2]);
|
---|
1071 | //fprintf(stdout, "%s/%d\t(%lg\t%lg\t%lg)\t", atombuffer[nr].name, numbersheet+1, coord[0], coord[1], coord[2]);
|
---|
1072 | //PrintVector(stdout, tempvector);
|
---|
1073 | numbersheet++;
|
---|
1074 | //fprintf(stdout, "%i,", nr);
|
---|
1075 | } //else {
|
---|
1076 | //numbersheet++;
|
---|
1077 | //fprintf(SheetFile, "B\t%lg\t%lg\t%lg\n", coord[0], coord[1], coord[2]);
|
---|
1078 | //fprintf(stdout, "O \t(%lg\t%lg\t%lg)\n", coord[0], coord[1], coord[2]);
|
---|
1079 | //fprintf(stdout, "!!%i!!, ", nr);
|
---|
1080 | //}
|
---|
1081 | Free(tempvector, "Main: At stage Sheet - tempvector");
|
---|
1082 | Free(coord, "Main: At stage Sheet - coord");
|
---|
1083 | }
|
---|
1084 | }
|
---|
1085 | Free(offset, "Main: At stage Sheet - offset");
|
---|
1086 | }
|
---|
1087 | //fprintf(stdout, "\n";
|
---|
1088 | }
|
---|
1089 |
|
---|
1090 | fclose(SheetFile);
|
---|
1091 | fclose(SheetFileAligned);
|
---|
1092 | AddAtomicNumber(SheetFilename,numbersheet, Vector, Recivector); // prepend atomic number and comment
|
---|
1093 | AddAtomicNumber(SheetFilenameAligned,numbersheet, Vector, Recivector); // prepend atomic number and comment
|
---|
1094 | AddSheetInfo(SheetFilename,axis,chiral, factors, seed, numbercell, randomness);
|
---|
1095 | fprintf(stdout, "\nThere are %i atoms in the created sheet.\n", numbersheet);
|
---|
1096 |
|
---|
1097 | strncpy(stage, "Sheet", 5);
|
---|
1098 | //}
|
---|
1099 | SheetBuffer = ReadBuffer(SheetFilename, &length);
|
---|
1100 |
|
---|
1101 |
|
---|
1102 | // ======================== STAGE: Tube ==============================
|
---|
1103 | // The tube starts with the rectangular (due to the orthogonalization) sheet
|
---|
1104 | // just created (or read). Along the minor axis it is rolled up, i.e. projected
|
---|
1105 | // from a 2d surface onto a cylindrical surface (x,y,z <-> r,alpha,z). The only
|
---|
1106 | // thing that's a bit complex is that the sheet it not aligned along the cartesian
|
---|
1107 | // axis but along major and minor. That's why we have to transform the atomic
|
---|
1108 | // cartesian coordinates into the orthogonal tubevector base, do the rolling up
|
---|
1109 | // there (and regard that minor and major axis must not necessarily be of equal
|
---|
1110 | // length) and afterwards transform back again (where we need the $halfaxis due to
|
---|
1111 | // the above possible inequality).
|
---|
1112 |
|
---|
1113 | FILE *TubeFile = NULL;
|
---|
1114 | FILE *TubeFileAligned = NULL;
|
---|
1115 |
|
---|
1116 | Debug ("STAGE: Tube\n");
|
---|
1117 | if (!strncmp(stage, "Sheet", 4)) {
|
---|
1118 | TubeFile = fopen(TubeFilename, "w");
|
---|
1119 | if (TubeFile == NULL) {
|
---|
1120 | fprintf(stderr, "ERROR: Main - can't open %s for writing\n", TubeFilename);
|
---|
1121 | exit(255);
|
---|
1122 | }
|
---|
1123 | TubeFileAligned = fopen(TubeFilenameAligned, "w");
|
---|
1124 | if (TubeFile == NULL) {
|
---|
1125 | fprintf(stderr, "ERROR: Main - can't open %s for writing\n", TubeFilenameAligned);
|
---|
1126 | exit(255);
|
---|
1127 | }
|
---|
1128 | bufptr = SheetBuffer;
|
---|
1129 | bufptr += GetNextline(bufptr, line); // write numbers to file
|
---|
1130 | bufptr += GetNextline(bufptr, line); // write comment to file
|
---|
1131 |
|
---|
1132 | //cog = CenterOfGravity(bufptr, numbersheet);
|
---|
1133 | //cog_projected = MatrixTrafoInverse(cog, TubevectorInverse);
|
---|
1134 | //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]);
|
---|
1135 |
|
---|
1136 | // restart
|
---|
1137 | bufptr = SheetBuffer;
|
---|
1138 | bufptr += GetNextline(bufptr, line); // write numbers to file
|
---|
1139 | bufptr += GetNextline(bufptr, line); // write numbers to file
|
---|
1140 |
|
---|
1141 | // determine half axis as tube vector not necessarily have the same length
|
---|
1142 | double halfaxis[NDIM];
|
---|
1143 | for (i=0;i<NDIM;i++)
|
---|
1144 | halfaxis[i] = factors[0]*Norm(Tubevector[axis[0]])/Norm(Tubevector[i]);
|
---|
1145 |
|
---|
1146 | double arg, radius;
|
---|
1147 | for (i=0;i<numbersheet;i++) {
|
---|
1148 | // scan next atom
|
---|
1149 | bufptr += GetNextline(bufptr, line);
|
---|
1150 | sscanf(line, "%s %lg %lg %lg", name, &atom[0], &atom[1], &atom[2]);
|
---|
1151 |
|
---|
1152 | // transform atom coordinates in cartesian system to the axis eigensystem
|
---|
1153 | x = MatrixTrafoInverse(atom, TubevectorInverse);
|
---|
1154 | //x = VectorAdd(y, cog_projected);
|
---|
1155 | //free(y);
|
---|
1156 |
|
---|
1157 | // roll up (project (x,y,z) on cylindrical coordinates (radius,arg,z))
|
---|
1158 | arg = 2.*M_PI*x[axis[0]]/(factors[0]) - M_PI; // is angle
|
---|
1159 | radius = 1./(2.*M_PI); // is length of sheet in units of axis vector, divide by pi to get radius (from circumference)
|
---|
1160 | // fprintf(stdout, "arg: %5.2f (c%2.2f,s%2.2f)\t",$arg, cos($arg), sin($arg));
|
---|
1161 | 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!
|
---|
1162 | 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
|
---|
1163 | //fprintf(stdout, "rotated: (%5.2f,%5.2f,%5.2f)\n",x[0],x[1],x[2]);
|
---|
1164 | atom_transformed = MatrixTrafo(Tubevector, x);
|
---|
1165 | fprintf(TubeFile, "%s\t%lg\t%lg\t%lg\n", name, atom_transformed[0], atom_transformed[1], atom_transformed[2]);
|
---|
1166 | // rotate and flip to align tube in z-direction
|
---|
1167 | x1 = atom_transformed[0]*cos(angle) + atom_transformed[1] * sin(angle);
|
---|
1168 | x2 = atom_transformed[0]*(-sin(angle)) + atom_transformed[1] * cos(angle);
|
---|
1169 | x3 = atom_transformed[2];
|
---|
1170 | fprintf(TubeFileAligned, "%s\t%lg\t%lg\t%lg\n", name, x1, x3, x2);
|
---|
1171 | //fprintf(stdout, "%s\t%5.5lg\t%5.5lg\t%5.5lg\n", name, atom_transformed[0], atom_transformed[1] ,atom_transformed[2]);
|
---|
1172 |
|
---|
1173 | Free(x, "Main: at stage Tube - x");
|
---|
1174 | Free(atom_transformed, "Main: at stage Tube - atom_transformed");
|
---|
1175 | }
|
---|
1176 |
|
---|
1177 |
|
---|
1178 | fclose(TubeFile);
|
---|
1179 | fclose(TubeFileAligned);
|
---|
1180 | //free(cog);
|
---|
1181 | //free(cog_projected);
|
---|
1182 | AddAtomicNumber(TubeFilename,numbersheet, Vector, Recivector); // prepend atomic number and comment
|
---|
1183 | AddAtomicNumber(TubeFilenameAligned,numbersheet, Vector, Recivector); // prepend atomic number and comment
|
---|
1184 | AddSheetInfo(TubeFilename,axis,chiral, factors, seed, numbercell, randomness);
|
---|
1185 | fprintf(stdout, "\nThere are %i atoms in the created tube.\n", numbersheet);
|
---|
1186 |
|
---|
1187 | strncpy(stage, "Tube", 4);
|
---|
1188 | } else {
|
---|
1189 | }
|
---|
1190 |
|
---|
1191 | TubeBuffer = ReadBuffer(TubeFilename, &length);
|
---|
1192 |
|
---|
1193 | // ======================== STAGE: Torus =============================
|
---|
1194 | // The procedure for the torus is very much alike to the one used to make the
|
---|
1195 | // tube. Only the projection is not from 2d surface onto a cylindrical one but
|
---|
1196 | // from a cylindrial onto a torus surface
|
---|
1197 | // (x,y,z) <-> (cos(s)*(R+r*cos(t)), sin(s)*(R+rcos(t)), r*sin(t)).
|
---|
1198 | // Here t is the angle within the tube with radius r, s is the torus angle with
|
---|
1199 | // radius R. We get R from the tubelength (that's why we need lengthfactor to
|
---|
1200 | // make it long enough). And due to fact that we have it already upon a cylindrical
|
---|
1201 | // surface, r*cos(t) and r*sin(t) already reside in $minoraxis and $noaxis.
|
---|
1202 |
|
---|
1203 | FILE *TorusFile;
|
---|
1204 |
|
---|
1205 | Debug ("STAGE: Torus\n");
|
---|
1206 | if (!strncmp(stage, "Tube", 4)) {
|
---|
1207 | TorusFile = fopen(TorusFilename, "w");
|
---|
1208 | if (TorusFile == NULL) {
|
---|
1209 | fprintf(stderr, "ERROR: main - can't open %s for writing\n", TorusFilename);
|
---|
1210 | exit(255);
|
---|
1211 | }
|
---|
1212 | bufptr = TubeBuffer;
|
---|
1213 | bufptr += GetNextline(bufptr, line); // write numbers to file
|
---|
1214 | bufptr += GetNextline(bufptr, line); // write comment to file
|
---|
1215 |
|
---|
1216 | //cog = CenterOfGravity(bufptr, numbersheet);
|
---|
1217 | //cog_projected = MatrixTrafoInverse(cog, TubevectorInverse);
|
---|
1218 | //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]);
|
---|
1219 |
|
---|
1220 | // determine half axis as tube vectors not necessarily have same length
|
---|
1221 | double halfaxis[NDIM];
|
---|
1222 | for (i=0;i<NDIM;i++)
|
---|
1223 | halfaxis[i] = Norm(Tubevector[axis[1]])/Norm(Tubevector[i]);
|
---|
1224 |
|
---|
1225 | double arg, radius;
|
---|
1226 | for (i=0;i<numbersheet;i++) {
|
---|
1227 | // scan next atom
|
---|
1228 | bufptr += GetNextline(bufptr, line);
|
---|
1229 | sscanf(line, "%s %lg %lg %lg", name, &atom[0], &atom[1], &atom[2]);
|
---|
1230 |
|
---|
1231 | // transform atom coordinates in cartesian system to the axis eigensystem
|
---|
1232 | x = MatrixTrafoInverse(atom, TubevectorInverse);
|
---|
1233 | //x = VectorAdd(y, cog_projected);
|
---|
1234 | //free(y);
|
---|
1235 |
|
---|
1236 | // roll up (project (x,y,z) on cylindrical coordinates (radius,arg,z))
|
---|
1237 | arg = 2.*M_PI*x[axis[1]]/(factors[1]) - M_PI; // is angle
|
---|
1238 | 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)
|
---|
1239 | // fprintf(stdout, "arg: %5.2f (c%2.2f,s%2.2f)\t",$arg, cos($arg), sin($arg));
|
---|
1240 | x[axis[0]] = cos(arg)*halfaxis[axis[0]]*radius; // as both vectors are not normalized additional betrag has to be taken into account!
|
---|
1241 | x[axis[1]] = sin(arg)*halfaxis[axis[1]]*radius; // due to the back-transformation from eigensystem to cartesian one
|
---|
1242 | //fprintf(stdout, "rotated: (%5.2f,%5.2f,%5.2f)\n",x[0],x[1],x[2]);
|
---|
1243 | atom_transformed = MatrixTrafo(Tubevector, x);
|
---|
1244 | fprintf(TorusFile, "%s\t%lg\t%lg\t%lg\n", name, atom_transformed[0], atom_transformed[1] ,atom_transformed[2]);
|
---|
1245 | //fprintf(stdout, "%s\t%5.5lg\t%5.5lg\t%5.5lg\n", name, atom_transformed[0], atom_transformed[1] ,atom_transformed[2]);
|
---|
1246 |
|
---|
1247 | Free(x, "Main: at stage Torus - x");
|
---|
1248 | Free(atom_transformed, "Main: at stage Torus - atom_transformed");
|
---|
1249 | }
|
---|
1250 |
|
---|
1251 | fclose(TorusFile);
|
---|
1252 | //free(cog);
|
---|
1253 | //free(cog_projected);
|
---|
1254 | AddAtomicNumber(TorusFilename,numbersheet, Vector, Recivector); // prepend atomic number and comment
|
---|
1255 | AddSheetInfo(TorusFilename,axis,chiral, factors, seed, numbercell, randomness);
|
---|
1256 | fprintf(stdout, "\nThere are %i atoms in the created torus.\n", numbersheet);
|
---|
1257 |
|
---|
1258 | strncpy(stage, "Torus", 5);
|
---|
1259 | } else {
|
---|
1260 | }
|
---|
1261 |
|
---|
1262 | // Free memory
|
---|
1263 | for (i=0; i<NDIM; i++ ) {
|
---|
1264 | Free(Vector[i], "Main: end of stages - *Vector");
|
---|
1265 | Free(Recivector[i], "Main: end of stages - *Recivector");
|
---|
1266 | Free(Tubevector[i], "Main: end of stages - *Tubevector");
|
---|
1267 | Free(TubevectorInverse[i], "Main: end of stages - *TubevectorInverse");
|
---|
1268 | }
|
---|
1269 | Free(atom, "Main: end of stages - atom");
|
---|
1270 | Free(Vector, "Main: end of stages - Vector");
|
---|
1271 | Free(Recivector, "Main: end of stages - Recivector");
|
---|
1272 | Free(Tubevector, "Main: end of stages - Tubevector");
|
---|
1273 | Free(TubevectorInverse, "Main: end of stages - TubevectorInverse");
|
---|
1274 | Free(randomness, "Main: at stage Sheet - randomness");
|
---|
1275 |
|
---|
1276 | if (CellBuffer != NULL) Free(CellBuffer, "Main: end of stages - CellBuffer");
|
---|
1277 | if (SheetBuffer != NULL) Free(SheetBuffer, "Main: end of stages - SheetBuffer");
|
---|
1278 | if (TubeBuffer != NULL) Free(TubeBuffer, "Main: end of stages - TubeBuffer");
|
---|
1279 |
|
---|
1280 | Free(CellFilename, "Main: end of stafes - CellFilename");
|
---|
1281 | Free(SheetFilename, "Main: end of stafes - CellFilename");
|
---|
1282 | Free(TubeFilename, "Main: end of stafes - CellFilename");
|
---|
1283 | Free(TorusFilename, "Main: end of stafes - CellFilename");
|
---|
1284 | Free(SheetFilenameAligned, "Main: end of stafes - CellFilename");
|
---|
1285 | Free(TubeFilenameAligned, "Main: end of stafes - CellFilename");
|
---|
1286 |
|
---|
1287 | // exit
|
---|
1288 | exit(0);
|
---|
1289 | }
|
---|