Commit 9333bc22b19f525f7d197d7c4a4dc48d0cd3b3b1
1 parent
057bed5a
started TIRA library
Showing
2 changed files
with
189 additions
and
14 deletions
Show diff stats
python/optics.py
@@ -359,17 +359,12 @@ class layersample: | @@ -359,17 +359,12 @@ class layersample: | ||
359 | def i(self, l, c, d): | 359 | def i(self, l, c, d): |
360 | i = l * 6 + d * 3 + c - 3 | 360 | i = l * 6 + d * 3 + c - 3 |
361 | return i | 361 | return i |
362 | - | ||
363 | - #create a matrix for a single plane wave specified by k and E | ||
364 | - # d = [dx, dy] are the x and y coordinates of the normalized direction of propagation | ||
365 | - # k0 is the free space wave number (2 pi / lambda0) | ||
366 | - # E is the electric field vector | ||
367 | - | ||
368 | - def solve1(self, d, k0, E): | ||
369 | - | ||
370 | - #s is the plane wave direction scaled by the refractive index | ||
371 | - s = np.array(d) * self.n[0] | ||
372 | 362 | ||
363 | + # generate the linear system corresponding to this layered sample and plane wave | ||
364 | + # s is the direction vector scaled by the refractive index | ||
365 | + # k0 is the free-space k-vector | ||
366 | + # E is the field vector for the incident plane wave | ||
367 | + def generate_linsys(self, s, k0, E): | ||
373 | #allocate space for the matrix | 368 | #allocate space for the matrix |
374 | L = len(self.n) | 369 | L = len(self.n) |
375 | M = np.zeros((6*(L-1), 6*(L-1)), dtype=np.complex128) | 370 | M = np.zeros((6*(L-1), 6*(L-1)), dtype=np.complex128) |
@@ -516,18 +511,33 @@ class layersample: | @@ -516,18 +511,33 @@ class layersample: | ||
516 | M[ei, self.i(l, 0, 1)] = B*sz1 | 511 | M[ei, self.i(l, 0, 1)] = B*sz1 |
517 | M[ei, self.i(l, 2, 1)] = B*s[0] | 512 | M[ei, self.i(l, 2, 1)] = B*s[0] |
518 | ei = ei + 1 | 513 | ei = ei + 1 |
514 | + | ||
515 | + return [M, b] | ||
516 | + | ||
517 | + #create a matrix for a single plane wave specified by k and E | ||
518 | + # d = [dx, dy] are the x and y coordinates of the normalized direction of propagation | ||
519 | + # k0 is the free space wave number (2 pi / lambda0) | ||
520 | + # E is the electric field vector | ||
521 | + | ||
522 | + def solve1(self, d, k0, E): | ||
519 | 523 | ||
520 | - #store the matrix and RHS vector (for debugging) | ||
521 | - self.M = M | ||
522 | - self.b = b | 524 | + #s is the plane wave direction scaled by the refractive index |
525 | + s = np.array(d) * self.n[0] | ||
526 | + | ||
527 | + | ||
528 | + #store the matrix and RHS vector (for debugging) | ||
529 | + [self.M, self.b] = self.generate_linsys(s, k0, E) | ||
530 | + #self.M = M | ||
531 | + #self.b = b | ||
523 | 532 | ||
524 | #evaluate the linear system | 533 | #evaluate the linear system |
525 | - P = np.linalg.solve(M, b) | 534 | + P = np.linalg.solve(self.M, self.b) |
526 | 535 | ||
527 | #save the results (also for debugging) | 536 | #save the results (also for debugging) |
528 | self.P = P | 537 | self.P = P |
529 | 538 | ||
530 | #store the coefficients for each layer | 539 | #store the coefficients for each layer |
540 | + L = len(self.n) # calculate the number of layers | ||
531 | self.Pt = np.zeros((3, L), np.complex128) | 541 | self.Pt = np.zeros((3, L), np.complex128) |
532 | self.Pr = np.zeros((3, L), np.complex128) | 542 | self.Pr = np.zeros((3, L), np.complex128) |
533 | for l in range(L): | 543 | for l in range(L): |
1 | +#include <iostream> | ||
2 | +#include <fstream> | ||
3 | +#include <complex> | ||
4 | + | ||
5 | +#ifndef LAPACK_COMPLEX_CUSTOM | ||
6 | +#define LAPACK_COMPLEX_CUSTOM | ||
7 | +#define lapack_complex_float std::complex<float> | ||
8 | +#define lapack_complex_double std::complex<double> | ||
9 | +#include "lapacke.h" | ||
10 | +#endif | ||
11 | + | ||
12 | +namespace tira { | ||
13 | + | ||
14 | + template <typename type> | ||
15 | + class Matrix { | ||
16 | + type* m_ptr; | ||
17 | + int m_rows, m_cols; | ||
18 | + | ||
19 | + void allocate(int rows, int cols) { | ||
20 | + if (m_ptr != NULL) | ||
21 | + free(m_ptr); | ||
22 | + m_rows = rows; | ||
23 | + m_cols = cols; | ||
24 | + m_ptr = (type*)malloc(m_rows * m_cols * sizeof(type)); | ||
25 | + } | ||
26 | + | ||
27 | + public: | ||
28 | + /// Default constructor, creates an empty matrix (generally filled as a parameter) | ||
29 | + Matrix() { | ||
30 | + m_rows = m_cols = 0; | ||
31 | + m_ptr = NULL; | ||
32 | + } | ||
33 | + | ||
34 | + /// Contructor, creates a rows x cols matrix with undefined values | ||
35 | + Matrix(int rows, int cols) : Matrix() { | ||
36 | + allocate(rows, cols); | ||
37 | + } | ||
38 | + | ||
39 | + /// De-allocate data and clear the matrix for garbage collection | ||
40 | + void del() { | ||
41 | + m_rows = 0; | ||
42 | + m_cols = 0; | ||
43 | + free(m_ptr); | ||
44 | + m_ptr = NULL; | ||
45 | + } | ||
46 | + | ||
47 | + void create(int rows, int cols) { | ||
48 | + allocate(rows, cols); | ||
49 | + } | ||
50 | + | ||
51 | + int rows() { return m_rows; } | ||
52 | + int cols() { return m_cols; } | ||
53 | + type* get_ptr() { return m_ptr; } | ||
54 | + | ||
55 | + void force_square() { | ||
56 | + if (m_rows != m_cols) | ||
57 | + throw "Matrix must be square!"; | ||
58 | + if (m_rows == 0 || m_cols == 0) | ||
59 | + throw "Matrix undefined!"; | ||
60 | + } | ||
61 | + | ||
62 | + inline void set(int row, int col, type val) { | ||
63 | + m_ptr[col * m_rows + row] = val; | ||
64 | + } | ||
65 | + | ||
66 | + inline type get(int row, int col) { | ||
67 | + return m_ptr[col * m_rows + row]; | ||
68 | + } | ||
69 | + | ||
70 | + /// Return the number of bytes in the matrix array | ||
71 | + size_t bytes() { return m_rows * m_cols * sizeof(type); } | ||
72 | + | ||
73 | + /// Create a deep copy of the current matrix and return it | ||
74 | + Matrix copy() { | ||
75 | + Matrix result(m_rows, m_cols); | ||
76 | + memcpy(result.m_ptr, m_ptr, bytes()); | ||
77 | + return result; | ||
78 | + } | ||
79 | + | ||
80 | + /// Calculate the determinant of the matrix | ||
81 | + type det() { | ||
82 | + force_square(); //throw an exception if the matrix isn't square | ||
83 | + Matrix tmp = copy(); //copy the current matrix to create space for LUP decomposition | ||
84 | + Matrix<int> idx = getrf(tmp); //perform LUP decomposition | ||
85 | + | ||
86 | + // multiply all elements along the diagonal | ||
87 | + type determinant = get(0, 0); //initialize the determinant | ||
88 | + for (int i = 1; i < m_rows; i++) //for each remaining element of the diagonal | ||
89 | + determinant *= tmp.get(i, i); //calculate the running factor | ||
90 | + tmp.del(); //delete memory for the temporary matrix | ||
91 | + | ||
92 | + // calculate the number of row swaps | ||
93 | + int swaps = 0; //initialize the number of row swaps | ||
94 | + for (int i = 0; i < m_rows; i++) //iterate through each element of the swap vector | ||
95 | + if (idx.get(i, 0) != i + 1) //if the element does not equal the row number | ||
96 | + swaps++; //a row was swapped, so increment the swap counter | ||
97 | + if (swaps % 2 != 0) //if there was an odd number of row swaps | ||
98 | + determinant *= (-1); //multiply the determinant by -1 | ||
99 | + return determinant; //return the determinant | ||
100 | + } | ||
101 | + | ||
102 | + /// Calculate the trace of the matrix | ||
103 | + type trace() { | ||
104 | + force_square(); //throw an exception if the matrix isn't square | ||
105 | + type trace = 0; //initialize the trace summation | ||
106 | + for (int i = 0; i < m_rows; i++) //for each element along the diagonal | ||
107 | + trace += get(i, i); //sum the trace | ||
108 | + return trace; //return the matrix trace result | ||
109 | + } | ||
110 | + | ||
111 | + /// Output the matrix to a CSV file | ||
112 | + void csv(std::string filename) { | ||
113 | + std::ofstream outfile(filename.c_str()); //open the file for writing | ||
114 | + for (int r = 0; r < m_rows; r++) { //for each row | ||
115 | + for (int c = 0; c < m_cols; c++) { //for each column | ||
116 | + outfile << get(r, c); //output the value to a file | ||
117 | + if (c != m_cols - 1) outfile << ","; //if this isn't the last column, add a comma | ||
118 | + } | ||
119 | + if (r != m_rows - 1) outfile << std::endl; //if this isn't the last row, end the line | ||
120 | + } | ||
121 | + } | ||
122 | + | ||
123 | + /* Static functions used to generate specialized matrices */ | ||
124 | + | ||
125 | + /// Static function for generating an identity matrix | ||
126 | + static Matrix I(int dim) { | ||
127 | + Matrix result(dim, dim); //create and allocate space for the matrix | ||
128 | + memset(result.m_ptr, 0, dim * dim * sizeof(type)); //set all elements to zero | ||
129 | + for (int i = 0; i < dim; i++) //for each element on the diagonal | ||
130 | + result.set(i, i, (type)1); //set that element to 1 | ||
131 | + return result; //return the completed matrix | ||
132 | + } | ||
133 | + | ||
134 | + /// Static function for generating a geometric matrix for robustness testing | ||
135 | + static Matrix geometric_matrix(int dim) { | ||
136 | + Matrix result(dim, dim); //create and allocate space for the matrix | ||
137 | + for (int r = 0; r < dim; r++) //for each row | ||
138 | + for (int c = 0; c < dim; c++) //for each column | ||
139 | + result.set(r, c, pow((type)(2 + r), c)); //set the geometric coefficient | ||
140 | + return result; //return the completed matrix | ||
141 | + } | ||
142 | + | ||
143 | + /// Static function analytically generates a solution (right hand side) vector for a geometric matrix | ||
144 | + static Matrix geometric_vector(int dim) { | ||
145 | + Matrix result(dim, 1); //generate and allocate space for the vector | ||
146 | + for (int r = 0; r < dim; r++) | ||
147 | + result.set(r, 0, (pow((type)(2 + r), dim) - 1) / (type)(r + 1)); | ||
148 | + return result; //return the completed vector | ||
149 | + } | ||
150 | + | ||
151 | + /* Static functions used for LAPACK and BLAS */ | ||
152 | + | ||
153 | + /// Calls the appropriate LAPACK GETRF function for performing LUP decomposition | ||
154 | + static Matrix<int> getrf(Matrix<float> M) { | ||
155 | + Matrix<int> idx(M.m_rows, 1); | ||
156 | + LAPACKE_sgetrf(LAPACK_COL_MAJOR, (int)M.m_rows, (int)M.m_cols, M.m_ptr, (int)M.m_rows, idx.get_ptr()); | ||
157 | + return idx; | ||
158 | + } | ||
159 | + static Matrix<int> getrf(Matrix<double> M) { | ||
160 | + Matrix<int> idx(M.m_rows, 1); | ||
161 | + LAPACKE_dgetrf(LAPACK_COL_MAJOR, (int)M.m_rows, (int)M.m_cols, M.m_ptr, (int)M.m_rows, idx.get_ptr()); | ||
162 | + return idx; | ||
163 | + } | ||
164 | + }; | ||
165 | +} | ||
0 | \ No newline at end of file | 166 | \ No newline at end of file |