Compadre  1.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Compadre_LinearAlgebra_Definitions.hpp
Go to the documentation of this file.
1 #ifndef _COMPADRE_LINEAR_ALGEBRA_DEFINITIONS_HPP_
2 #define _COMPADRE_LINEAR_ALGEBRA_DEFINITIONS_HPP_
3 
5 
6 namespace Compadre {
7 namespace GMLS_LinearAlgebra {
8 
9 KOKKOS_INLINE_FUNCTION
10 void createM(const member_type& teamMember, scratch_matrix_right_type M_data, scratch_matrix_right_type weighted_P, const int columns, const int rows) {
11  /*
12  * Creates M = P^T * W * P
13  */
14 
15  for (int i=0; i<columns; ++i) {
16  // offdiagonal entries
17  for (int j=0; j<i; ++j) {
18  double M_data_entry_i_j = 0;
19  teamMember.team_barrier();
20 
21  Kokkos::parallel_reduce(Kokkos::TeamThreadRange(teamMember,rows), [=] (const int k, double &entry_val) {
22  // assumes layout left input matrix
23  double val_i = weighted_P(k, i);
24  double val_j = weighted_P(k, j);
25  entry_val += val_i*val_j;
26  }, M_data_entry_i_j );
27 
28  Kokkos::single(Kokkos::PerTeam(teamMember), [&] () {
29  M_data(i,j) = M_data_entry_i_j;
30  M_data(j,i) = M_data_entry_i_j;
31  });
32  teamMember.team_barrier();
33  }
34  // diagonal entries
35  double M_data_entry_i_j = 0;
36  teamMember.team_barrier();
37 
38  Kokkos::parallel_reduce(Kokkos::TeamThreadRange(teamMember,rows), [=] (const int k, double &entry_val) {
39  // assumes layout left input matrix
40  double val = weighted_P(k, i);
41  entry_val += val*val;
42  }, M_data_entry_i_j );
43 
44  Kokkos::single(Kokkos::PerTeam(teamMember), [&] () {
45  M_data(i,i) = M_data_entry_i_j;
46  });
47  teamMember.team_barrier();
48  }
49  teamMember.team_barrier();
50 
51 }
52 
53 
54 KOKKOS_INLINE_FUNCTION
55 void largestTwoEigenvectorsThreeByThreeSymmetric(const member_type& teamMember, scratch_matrix_right_type V, scratch_matrix_right_type PtP, const int dimensions, pool_type& random_number_pool) {
56 
57  Kokkos::single(Kokkos::PerTeam(teamMember), [&] () {
58 
59  double maxRange = 100;
60 
61  generator_type rand_gen = random_number_pool.get_state();
62  // put in a power method here and a deflation by first found eigenvalue
63  double eigenvalue_relative_tolerance = 1e-6; // TODO: use something smaller, but really anything close is acceptable for this manifold
64 
65 
66  double v[3] = {1,1,1};
67  double v_old[3] = {v[0], v[1], v[2]};
68 
69  double error = 1;
70  double norm_v;
71 
72  while (error > eigenvalue_relative_tolerance) {
73 
74  double tmp1 = v[0];
75  v[0] = PtP(0,0)*tmp1 + PtP(0,1)*v[1];
76  if (dimensions>2) v[0] += PtP(0,2)*v[2];
77 
78  double tmp2 = v[1];
79  v[1] = PtP(1,0)*tmp1 + PtP(1,1)*tmp2;
80  if (dimensions>2) v[1] += PtP(1,2)*v[2];
81 
82  if (dimensions>2)
83  v[2] = PtP(2,0)*tmp1 + PtP(2,1)*tmp2 + PtP(2,2)*v[2];
84 
85  norm_v = v[0]*v[0] + v[1]*v[1];
86  if (dimensions>2) norm_v += v[2]*v[2];
87  norm_v = std::sqrt(norm_v);
88 
89  v[0] = v[0] / norm_v;
90  v[1] = v[1] / norm_v;
91  if (dimensions>2) v[2] = v[2] / norm_v;
92 
93  error = (v[0]-v_old[0])*(v[0]-v_old[0]) + (v[1]-v_old[1])*(v[1]-v_old[1]);
94  if (dimensions>2) error += (v[2]-v_old[2])*(v[2]-v_old[2]);
95  error = std::sqrt(error);
96  error /= norm_v;
97 
98 
99  v_old[0] = v[0];
100  v_old[1] = v[1];
101  if (dimensions>2) v_old[2] = v[2];
102  }
103 
104  double dot_product;
105  double norm;
106 
107  // if 2D, orthonormalize second vector
108  if (dimensions==2) {
109 
110  for (int i=0; i<2; ++i) {
111  V(0,i) = v[i];
112  }
113 
114  // orthonormalize second eigenvector against first
115  V(1,0) = 1.0; V(1,1) = 1.0;
116  dot_product = V(0,0)*V(1,0) + V(0,1)*V(1,1);
117  V(1,0) -= dot_product*V(0,0);
118  V(1,1) -= dot_product*V(0,1);
119 
120  norm = std::sqrt(V(1,0)*V(1,0) + V(1,1)*V(1,1));
121  V(1,0) /= norm;
122  V(1,1) /= norm;
123 
124  } else { // otherwise, work on second eigenvalue
125 
126  for (int i=0; i<3; ++i) {
127  V(0,i) = v[i];
128  for (int j=0; j<3; ++j) {
129  PtP(i,j) -= norm_v*v[i]*v[j];
130  }
131  }
132 
133  error = 1;
134  v[0] = rand_gen.drand(maxRange); v[1] = rand_gen.drand(maxRange); v[2] = rand_gen.drand(maxRange);
135  v_old[0] = v[0]; v_old[1] = v[1]; v_old[2] =v[2];
136  while (error > eigenvalue_relative_tolerance) {
137 
138  double tmp1 = v[0];
139  v[0] = PtP(0,0)*tmp1 + PtP(0,1)*v[1] + PtP(0,2)*v[2];
140 
141  double tmp2 = v[1];
142  v[1] = PtP(1,0)*tmp1 + PtP(1,1)*tmp2 + PtP(1,2)*v[2];
143 
144  v[2] = PtP(2,0)*tmp1 + PtP(2,1)*tmp2 + PtP(2,2)*v[2];
145 
146  norm_v = std::sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
147 
148  v[0] = v[0] / norm_v;
149  v[1] = v[1] / norm_v;
150  v[2] = v[2] / norm_v;
151 
152  error = std::sqrt((v[0]-v_old[0])*(v[0]-v_old[0]) + (v[1]-v_old[1])*(v[1]-v_old[1]) + (v[2]-v_old[2])*(v[2]-v_old[2])) / norm_v;
153 
154  v_old[0] = v[0];
155  v_old[1] = v[1];
156  v_old[2] = v[2];
157  }
158 
159  for (int i=0; i<3; ++i) {
160  V(1,i) = v[i];
161  }
162 
163  // orthonormalize second eigenvector against first
164  dot_product = V(0,0)*V(1,0) + V(0,1)*V(1,1) + V(0,2)*V(1,2);
165 
166  V(1,0) -= dot_product*V(0,0);
167  V(1,1) -= dot_product*V(0,1);
168  V(1,2) -= dot_product*V(0,2);
169 
170  norm = std::sqrt(V(1,0)*V(1,0) + V(1,1)*V(1,1) + V(1,2)*V(1,2));
171  V(1,0) /= norm;
172  V(1,1) /= norm;
173  V(1,2) /= norm;
174 
175  // get normal from cross product
176  V(2,0) = V(0,1)*V(1,2) - V(1,1)*V(0,2);
177  V(2,1) = V(1,0)*V(0,2) - V(0,0)*V(1,2);
178  V(2,2) = V(0,0)*V(1,1) - V(1,0)*V(0,1);
179 
180  // orthonormalize third eigenvector (just to be sure)
181  norm = std::sqrt(V(2,0)*V(2,0) + V(2,1)*V(2,1) + V(2,2)*V(2,2));
182  V(2,0) /= norm;
183  V(2,1) /= norm;
184  V(2,2) /= norm;
185 
186  }
187 
188  random_number_pool.free_state(rand_gen);
189  });
190 
191 }
192 
193 } // GMLS_LinearAlgebra
194 } // Compadre
195 
196 #endif
197 
pool_type::generator_type generator_type
team_policy::member_type member_type
KOKKOS_INLINE_FUNCTION void largestTwoEigenvectorsThreeByThreeSymmetric(const member_type &teamMember, scratch_matrix_right_type V, scratch_matrix_right_type PtP, const int dimensions, pool_type &random_number_pool)
Calculates two eigenvectors corresponding to two dominant eigenvalues.
Kokkos::View< double **, layout_right, Kokkos::MemoryTraits< Kokkos::Unmanaged > > scratch_matrix_right_type
Kokkos::Random_XorShift64_Pool pool_type
KOKKOS_INLINE_FUNCTION void createM(const member_type &teamMember, scratch_matrix_right_type M_data, scratch_matrix_right_type weighted_P, const int columns, const int rows)
Creates a matrix M=A^T*A from a matrix A.