|
41 | 41 | * \date 2015
|
42 | 42 | */
|
43 | 43 |
|
44 |
| -/*! \brief Builds the **anisotropic** IEFPCM matrix |
45 |
| - * \param[in] cav the discretized cavity |
46 |
| - * \param[in] gf_i Green's function inside the cavity |
47 |
| - * \param[in] gf_o Green's function outside the cavity |
48 |
| - * \return the \f$ \mathbf{K} = \mathbf{T}^{-1}\mathbf{R}\mathbf{A} \f$ matrix |
49 |
| - * |
50 |
| - * This function calculates the PCM matrix. We use the following definitions: |
51 |
| - * \f[ |
52 |
| - * \begin{align} |
53 |
| - * \mathbf{T} &= |
54 |
| - * \left(2\pi\mathbf{I} - \mathbf{D}_\mathrm{e}\mathbf{A}\right)\mathbf{S}_\mathrm{i} |
55 |
| - * +\mathbf{S}_\mathrm{e}\left(2\pi\mathbf{I} + |
56 |
| - * \mathbf{A}\mathbf{D}_\mathrm{i}^\dagger\right) \\ |
57 |
| - * \mathbf{R} &= |
58 |
| - * \left(2\pi\mathbf{A}^{-1} - \mathbf{D}_\mathrm{e}\right) - |
59 |
| - * \mathbf{S}_\mathrm{e}\mathbf{S}^{-1}_\mathrm{i}\left(2\pi\mathbf{A}^{-1}-\mathbf{D}_\mathrm{i}\right) |
60 |
| - * \end{align} |
61 |
| - * \f] |
62 |
| - * The matrix is not symmetrized and is not symmetry packed. |
63 |
| - */ |
64 |
| -inline Eigen::MatrixXd anisotropicIEFMatrix(const Cavity & cav, const IGreensFunction & gf_i, const IGreensFunction & gf_o) |
65 |
| -{ |
66 |
| - // The total size of the cavity |
67 |
| - PCMSolverIndex cavitySize = cav.size(); |
68 |
| - // The number of irreps in the group |
69 |
| - int nrBlocks = cav.pointGroup().nrIrrep(); |
70 |
| - // The size of the irreducible portion of the cavity |
71 |
| - int dimBlock = cav.irreducible_size(); |
72 |
| - |
73 |
| - // Compute SI, DI and SE, DE on the whole cavity, regardless of symmetry |
74 |
| - TIMER_ON("Computing SI"); |
75 |
| - Eigen::MatrixXd SI = gf_i.singleLayer(cav.elements()); |
76 |
| - TIMER_OFF("Computing SI"); |
77 |
| - TIMER_ON("Computing DI"); |
78 |
| - Eigen::MatrixXd DI = gf_i.doubleLayer(cav.elements()); |
79 |
| - TIMER_OFF("Computing DI"); |
80 |
| - TIMER_ON("Computing SE"); |
81 |
| - Eigen::MatrixXd SE = gf_o.singleLayer(cav.elements()); |
82 |
| - TIMER_OFF("Computing SE"); |
83 |
| - TIMER_ON("Computing DE"); |
84 |
| - Eigen::MatrixXd DE = gf_o.doubleLayer(cav.elements()); |
85 |
| - TIMER_OFF("Computing DE"); |
86 |
| - |
87 |
| - // Perform symmetry blocking |
88 |
| - // If the group is C1 avoid symmetry blocking, we will just pack the fullPCMMatrix |
89 |
| - // into "block diagonal" when all other manipulations are done. |
90 |
| - if (cav.pointGroup().nrGenerators() != 0) { |
91 |
| - TIMER_ON("Symmetry blocking"); |
92 |
| - symmetryBlocking(DI, cavitySize, dimBlock, nrBlocks); |
93 |
| - symmetryBlocking(SI, cavitySize, dimBlock, nrBlocks); |
94 |
| - symmetryBlocking(DE, cavitySize, dimBlock, nrBlocks); |
95 |
| - symmetryBlocking(SE, cavitySize, dimBlock, nrBlocks); |
96 |
| - TIMER_OFF("Symmetry blocking"); |
97 |
| - } |
98 |
| - |
99 |
| - Eigen::MatrixXd a = cav.elementArea().asDiagonal(); |
100 |
| - Eigen::MatrixXd Id = Eigen::MatrixXd::Identity(cavitySize, cavitySize); |
101 |
| - |
102 |
| - // 1. Form T |
103 |
| - TIMER_ON("Assemble T matrix"); |
104 |
| - Eigen::MatrixXd fullPCMMatrix = ((2 * M_PI * Id - DE * a) * SI + SE * (2 * M_PI * Id + a * DI.adjoint().eval())); |
105 |
| - TIMER_OFF("Assemble T matrix"); |
106 |
| - // 2. Invert T using LU decomposition with full pivoting |
107 |
| - // This is a rank-revealing LU decomposition, this allows us |
108 |
| - // to test if T is invertible before attempting to invert it. |
109 |
| - TIMER_ON("Invert T matrix"); |
110 |
| - Eigen::FullPivLU<Eigen::MatrixXd> T_LU(fullPCMMatrix); |
111 |
| - if (!(T_LU.isInvertible())) PCMSOLVER_ERROR("T matrix is not invertible!", BOOST_CURRENT_FUNCTION); |
112 |
| - fullPCMMatrix = T_LU.inverse(); |
113 |
| - TIMER_OFF("Invert T matrix"); |
114 |
| - Eigen::FullPivLU<Eigen::MatrixXd> SI_LU(SI); |
115 |
| - if (!(SI_LU.isInvertible())) PCMSOLVER_ERROR("SI matrix is not invertible!", BOOST_CURRENT_FUNCTION); |
116 |
| - TIMER_ON("Assemble T^-1R matrix"); |
117 |
| - fullPCMMatrix *= ((2 * M_PI * Id - DE * a) - SE * SI_LU.inverse() * (2 * M_PI * Id - DI * a)); |
118 |
| - TIMER_OFF("Assemble T^-1R matrix"); |
119 |
| - |
120 |
| - return fullPCMMatrix; |
121 |
| -} |
122 |
| - |
123 |
| -/*! \brief Builds the **isotropic** IEFPCM matrix |
124 |
| - * \param[in] cav the discretized cavity |
125 |
| - * \param[in] gf_i Green's function inside the cavity |
126 |
| - * \param[in] epsilon permittivity outside the cavity |
127 |
| - * \return the \f$ \mathbf{K} = \mathbf{T}^{-1}\mathbf{R}\mathbf{A} \f$ matrix |
128 |
| - * |
129 |
| - * This function calculates the PCM matrix. We use the following definitions: |
130 |
| - * \f[ |
131 |
| - * \begin{align} |
132 |
| - * \mathbf{T} &= |
133 |
| - * \left(2\pi\frac{\varepsilon+1}{\varepsilon-1}\mathbf{I} - \mathbf{D}_\mathrm{i}\mathbf{A}\right)\mathbf{S}_\mathrm{i} \\ |
134 |
| - * \mathbf{R} &= |
135 |
| - * \left(2\pi\mathbf{A}^{-1} - \mathbf{D}_\mathrm{i}\right) |
136 |
| - * \end{align} |
137 |
| - * \f] |
138 |
| - * The matrix is not symmetrized and is not symmetry packed. |
139 |
| - */ |
140 |
| -inline Eigen::MatrixXd isotropicIEFMatrix(const Cavity & cav, const IGreensFunction & gf_i, double epsilon) |
141 |
| -{ |
142 |
| - // The total size of the cavity |
143 |
| - PCMSolverIndex cavitySize = cav.size(); |
144 |
| - // The number of irreps in the group |
145 |
| - int nrBlocks = cav.pointGroup().nrIrrep(); |
146 |
| - // The size of the irreducible portion of the cavity |
147 |
| - int dimBlock = cav.irreducible_size(); |
148 |
| - |
149 |
| - // Compute SI and DI on the whole cavity, regardless of symmetry |
150 |
| - TIMER_ON("Computing SI"); |
151 |
| - Eigen::MatrixXd SI = gf_i.singleLayer(cav.elements()); |
152 |
| - TIMER_OFF("Computing SI"); |
153 |
| - TIMER_ON("Computing DI"); |
154 |
| - Eigen::MatrixXd DI = gf_i.doubleLayer(cav.elements()); |
155 |
| - TIMER_OFF("Computing DI"); |
156 |
| - |
157 |
| - // Perform symmetry blocking |
158 |
| - // If the group is C1 avoid symmetry blocking, we will just pack the fullPCMMatrix |
159 |
| - // into "block diagonal" when all other manipulations are done. |
160 |
| - if (cav.pointGroup().nrGenerators() != 0) { |
161 |
| - TIMER_ON("Symmetry blocking"); |
162 |
| - symmetryBlocking(DI, cavitySize, dimBlock, nrBlocks); |
163 |
| - symmetryBlocking(SI, cavitySize, dimBlock, nrBlocks); |
164 |
| - TIMER_OFF("Symmetry blocking"); |
165 |
| - } |
166 |
| - |
167 |
| - Eigen::MatrixXd a = cav.elementArea().asDiagonal(); |
168 |
| - Eigen::MatrixXd Id = Eigen::MatrixXd::Identity(cavitySize, cavitySize); |
169 |
| - |
170 |
| - // Tq = -Rv -> q = -(T^-1 * R)v = -Kv |
171 |
| - // T = (2 * M_PI * fact * aInv - DI) * a * SI; R = (2 * M_PI * aInv - DI) |
172 |
| - // fullPCMMatrix_ = K = T^-1 * R * a |
173 |
| - // 1. Form T |
174 |
| - double fact = (epsilon + 1.0)/(epsilon - 1.0); |
175 |
| - TIMER_ON("Assemble T matrix"); |
176 |
| - Eigen::MatrixXd fullPCMMatrix = (2 * M_PI * fact * Id - DI * a) * SI; |
177 |
| - TIMER_OFF("Assemble T matrix"); |
178 |
| - // 2. Invert T using LU decomposition with full pivoting |
179 |
| - // This is a rank-revealing LU decomposition, this allows us |
180 |
| - // to test if T is invertible before attempting to invert it. |
181 |
| - TIMER_ON("Invert T matrix"); |
182 |
| - Eigen::FullPivLU<Eigen::MatrixXd> T_LU(fullPCMMatrix); |
183 |
| - if (!(T_LU.isInvertible())) |
184 |
| - PCMSOLVER_ERROR("T matrix is not invertible!", BOOST_CURRENT_FUNCTION); |
185 |
| - fullPCMMatrix = T_LU.inverse(); |
186 |
| - TIMER_OFF("Invert T matrix"); |
187 |
| - // 3. Multiply T^-1 and R |
188 |
| - TIMER_ON("Assemble T^-1R matrix"); |
189 |
| - fullPCMMatrix *= (2 * M_PI * Id - DI * a); |
190 |
| - TIMER_OFF("Assemble T^-1R matrix"); |
191 |
| - |
192 |
| - return fullPCMMatrix; |
193 |
| -} |
194 |
| - |
195 | 44 | /*! \brief Builds the **anisotropic** \f$ \mathbf{T}_\varepsilon \f$ matrix
|
196 | 45 | * \param[in] cav the discretized cavity
|
197 | 46 | * \param[in] gf_i Green's function inside the cavity
|
@@ -322,9 +171,8 @@ inline Eigen::MatrixXd anisotropicRinfinity(const Cavity & cav, const IGreensFun
|
322 | 171 | Eigen::MatrixXd a = cav.elementArea().asDiagonal();
|
323 | 172 | Eigen::MatrixXd Id = Eigen::MatrixXd::Identity(cavitySize, cavitySize);
|
324 | 173 |
|
325 |
| - // Form T |
326 |
| - Eigen::FullPivLU<Eigen::MatrixXd> SI_LU(SI); |
327 |
| - if (!(SI_LU.isInvertible())) PCMSOLVER_ERROR("SI matrix is not invertible!", BOOST_CURRENT_FUNCTION); |
| 174 | + // Form R |
| 175 | + Eigen::PartialPivLU<Eigen::MatrixXd> SI_LU(SI); |
328 | 176 | return ((2 * M_PI * Id - DE * a) - SE * SI_LU.inverse() * (2 * M_PI * Id - DI * a));
|
329 | 177 | }
|
330 | 178 |
|
|
0 commit comments