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 | 359 | def i(self, l, c, d): |
360 | 360 | i = l * 6 + d * 3 + c - 3 |
361 | 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 | 368 | #allocate space for the matrix |
374 | 369 | L = len(self.n) |
375 | 370 | M = np.zeros((6*(L-1), 6*(L-1)), dtype=np.complex128) |
... | ... | @@ -516,18 +511,33 @@ class layersample: |
516 | 511 | M[ei, self.i(l, 0, 1)] = B*sz1 |
517 | 512 | M[ei, self.i(l, 2, 1)] = B*s[0] |
518 | 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 | 533 | #evaluate the linear system |
525 | - P = np.linalg.solve(M, b) | |
534 | + P = np.linalg.solve(self.M, self.b) | |
526 | 535 | |
527 | 536 | #save the results (also for debugging) |
528 | 537 | self.P = P |
529 | 538 | |
530 | 539 | #store the coefficients for each layer |
540 | + L = len(self.n) # calculate the number of layers | |
531 | 541 | self.Pt = np.zeros((3, L), np.complex128) |
532 | 542 | self.Pr = np.zeros((3, L), np.complex128) |
533 | 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 | 166 | \ No newline at end of file | ... | ... |