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