Branch data Line data Source code
1 : : /* *****************************************************************
2 : : MESQUITE -- The Mesh Quality Improvement Toolkit
3 : :
4 : : Copyright 2009 Sandia National Laboratories. Developed at the
5 : : University of Wisconsin--Madison under SNL contract number
6 : : 624796. The U.S. Government and the University of Wisconsin
7 : : retain certain rights to this software.
8 : :
9 : : This library is free software; you can redistribute it and/or
10 : : modify it under the terms of the GNU Lesser General Public
11 : : License as published by the Free Software Foundation; either
12 : : version 2.1 of the License, or (at your option) any later version.
13 : :
14 : : This library is distributed in the hope that it will be useful,
15 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : : Lesser General Public License for more details.
18 : :
19 : : You should have received a copy of the GNU Lesser General Public License
20 : : (lgpl.txt) along with this library; if not, write to the Free Software
21 : : Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 : :
23 : : (2009) [email protected]
24 : :
25 : : ***************************************************************** */
26 : :
27 : : /** \file TMPDerivs.hpp
28 : : * \brief Utility methods for calculating derivatives of TMP metrics
29 : : * \author Jason Kraftcheck
30 : : */
31 : :
32 : : #ifndef MSQ_TMP_DERIVS_HPP
33 : : #define MSQ_TMP_DERIVS_HPP
34 : :
35 : : #include "Mesquite.hpp"
36 : : #include "MsqMatrix.hpp"
37 : :
38 : : /** If defined, then \f$ (A \otimes B)_{i,j} = row(A,i)^t \otimes row(B,j) \f$
39 : : otherwise \f$ (A \otimes B)_{i,j} = column(A,i) \otimes column(B,j)^t \f$
40 : : */
41 : : #define MSQ_ROW_BASED_OUTER_PRODUCT
42 : :
43 : : namespace MBMesquite
44 : : {
45 : :
46 : : /**\brief \f$ R *= s \f$ */
47 : : template < unsigned D >
48 : : inline void hess_scale_t( MsqMatrix< D, D > R[D * ( D + 1 ) / 2], double alpha );
49 : :
50 : 0 : inline void hess_scale( MsqMatrix< 3, 3 > R[6], double alpha )
51 : : {
52 : 0 : hess_scale_t< 3 >( R, alpha );
53 : 0 : }
54 : :
55 : 0 : inline void hess_scale( MsqMatrix< 2, 2 > R[3], double alpha )
56 : : {
57 : 0 : hess_scale_t< 2 >( R, alpha );
58 : 0 : }
59 : :
60 : : /**\brief \f$ R = \alpha I_9 \f$
61 : : *
62 : : *\param R The 6 blocks of the upper triangular portion of a 9x9
63 : : * symmetric matrix.
64 : : */
65 : : inline void set_scaled_I( MsqMatrix< 3, 3 > R[6], double alpha );
66 : :
67 : : /**\brief \f$ R += \alpha I_9 \f$
68 : : *
69 : : *\param R The 6 blocks of the upper triangular portion of a 9x9
70 : : * symmetric matrix.
71 : : */
72 : : inline void pluseq_scaled_I( MsqMatrix< 3, 3 > R[6], double alpha );
73 : :
74 : : /**\brief \f$ R += \alpha I_9 \f$
75 : : *
76 : : *\param R The 6 blocks of the upper triangular portion of a 9x9
77 : : * symmetric matrix.
78 : : */
79 : : inline void pluseq_scaled_I( MsqMatrix< 3, 3 >& R, double alpha );
80 : :
81 : : /**\brief \f$ R = \alpha I_4 \f$
82 : : *
83 : : *\param R The 3 blocks of the upper triangular portion of a 4x4
84 : : * symmetric matrix.
85 : : */
86 : : inline void set_scaled_I( MsqMatrix< 2, 2 > R[3], double alpha );
87 : :
88 : : /**\brief \f$ R += \alpha I_4 \f$
89 : : *
90 : : *\param R The 3 blocks of the upper triangular portion of a 4x4
91 : : * symmetric matrix.
92 : : */
93 : : inline void pluseq_scaled_I( MsqMatrix< 2, 2 > R[3], double alpha );
94 : :
95 : : /**\brief \f$ R += \alpha I_4 \f$
96 : : *
97 : : *\param R The 3 blocks of the upper triangular portion of a 4x4
98 : : * symmetric matrix.
99 : : */
100 : : inline void pluseq_scaled_I( MsqMatrix< 2, 2 >& R, double alpha );
101 : :
102 : : /**\brief \f$ R += \alpha \frac{\partial}{\partial T}det(T) \f$
103 : : *
104 : : *\param R The 6 blocks of the upper triangular portion of a 9x9
105 : : * symmetric matrix.
106 : : */
107 : : inline void pluseq_scaled_2nd_deriv_of_det( MsqMatrix< 3, 3 > R[6], double alpha, const MsqMatrix< 3, 3 >& T );
108 : :
109 : : /**\brief \f$ R += \alpha \frac{\partial}{\partial T}det(T) \f$
110 : : *
111 : : *\param R The 3 blocks of the upper triangular portion of a 4x4
112 : : * symmetric matrix.
113 : : */
114 : : inline void pluseq_scaled_2nd_deriv_of_det( MsqMatrix< 2, 2 > R[3], double alpha );
115 : 0 : inline void pluseq_scaled_2nd_deriv_of_det( MsqMatrix< 2, 2 > R[3], double alpha, const MsqMatrix< 2, 2 >& )
116 : : {
117 : 0 : pluseq_scaled_2nd_deriv_of_det( R, alpha );
118 : 0 : }
119 : :
120 : : /**\brief \f$ R = \alpha \frac{\partial}{\partial T}det(T) \f$
121 : : *
122 : : *\param R The 6 blocks of the upper triangular portion of a 9x9
123 : : * symmetric matrix.
124 : : */
125 : : inline void set_scaled_2nd_deriv_of_det( MsqMatrix< 3, 3 > R[6], double alpha, const MsqMatrix< 3, 3 >& T );
126 : :
127 : : /**\brief \f$ R = \alpha \frac{\partial}{\partial T}det(T) \f$
128 : : *
129 : : *\param R The 3 blocks of the upper triangular portion of a 4x4
130 : : * symmetric matrix.
131 : : */
132 : : inline void set_scaled_2nd_deriv_of_det( MsqMatrix< 2, 2 > R[3], double alpha );
133 : : inline void set_scaled_2nd_deriv_of_det( MsqMatrix< 2, 2 > R[3], double alpha, const MsqMatrix< 2, 2 >& )
134 : : {
135 : : set_scaled_2nd_deriv_of_det( R, alpha );
136 : : }
137 : :
138 : : /**\brief \f$ R += \alpha \frac{\partial^2}{\partial T^2}tr(adj T) \f$
139 : : *
140 : : * Note: 2nd deriv is a constant, so T is not passed as an argument.
141 : : */
142 : : inline void pluseq_scaled_2nd_deriv_tr_adj( MsqMatrix< 2, 2 > R[3], double alpha );
143 : :
144 : : /**\brief \f$ R += \alpha \frac{\partial^2}{\partial T^2}tr(adj T) \f$
145 : : *
146 : : * Note: 2nd deriv is a constant, so T is not passed as an argument.
147 : : */
148 : : inline void pluseq_scaled_2nd_deriv_tr_adj( MsqMatrix< 3, 3 > R[6], double alpha );
149 : :
150 : : /**\brief \f$ R += \alpha \frac{\partial^2}{\partial T^2}|adj T|^2 \f$
151 : : */
152 : : inline void set_scaled_2nd_deriv_norm_sqr_adj( MsqMatrix< 2, 2 > R[3], double alpha, const MsqMatrix< 2, 2 >& T );
153 : :
154 : : /**\brief \f$ R += \alpha \frac{\partial^2}{\partial T^2}|adj T|^2 \f$
155 : : */
156 : : inline void set_scaled_2nd_deriv_norm_sqr_adj( MsqMatrix< 3, 3 > R[6], double alpha, const MsqMatrix< 3, 3 >& T );
157 : :
158 : : /**\brief \f$ R += \alpha \left( M \otimes M \right) \f$
159 : : *
160 : : *\param R The 6 blocks of the upper triangular portion of a 9x9
161 : : * symmetric matrix.
162 : : */
163 : : template < unsigned D >
164 : : inline void pluseq_scaled_outer_product_t( MsqMatrix< D, D > R[D * ( D + 1 ) / 2], double alpha,
165 : : const MsqMatrix< D, D >& M );
166 : 118180 : inline void pluseq_scaled_outer_product( MsqMatrix< 3, 3 > R[6], double alpha, const MsqMatrix< 3, 3 >& M )
167 : : {
168 : 118180 : pluseq_scaled_outer_product_t< 3 >( R, alpha, M );
169 : 118180 : }
170 : :
171 : 0 : inline void pluseq_scaled_outer_product( MsqMatrix< 2, 2 > R[3], double alpha, const MsqMatrix< 2, 2 >& M )
172 : : {
173 : 0 : pluseq_scaled_outer_product_t< 2 >( R, alpha, M );
174 : 0 : }
175 : :
176 : : /**\brief \f$ R = \alpha \left( M \otimes M \right) \f$
177 : : *
178 : : *\param R The 6 blocks of the upper triangular portion of a 9x9
179 : : * symmetric matrix.
180 : : */
181 : : template < unsigned D >
182 : : inline void set_scaled_outer_product_t( MsqMatrix< D, D > R[D * ( D + 1 ) / 2], double alpha,
183 : : const MsqMatrix< D, D >& M );
184 : :
185 : 236360 : inline void set_scaled_outer_product( MsqMatrix< 3, 3 > R[6], double alpha, const MsqMatrix< 3, 3 >& M )
186 : : {
187 : 236360 : set_scaled_outer_product_t< 3 >( R, alpha, M );
188 : 236360 : }
189 : :
190 : 0 : inline void set_scaled_outer_product( MsqMatrix< 2, 2 > R[3], double alpha, const MsqMatrix< 2, 2 >& M )
191 : : {
192 : 0 : set_scaled_outer_product_t< 2 >( R, alpha, M );
193 : 0 : }
194 : :
195 : : /**\brief \f$ R += \alpha \left( A \otimes B + B \otimes A \right) \f$
196 : : *
197 : : *\param R The 6 blocks of the upper triangular portion of a 9x9
198 : : * symmetric matrix.
199 : : */
200 : : inline void pluseq_scaled_sum_outer_product( MsqMatrix< 3, 3 > R[6], double alpha, const MsqMatrix< 3, 3 >& A,
201 : : const MsqMatrix< 3, 3 >& B );
202 : :
203 : : /**\brief \f$ R += \alpha \left( A \otimes B + B \otimes A \right) \f$
204 : : *
205 : : *\param R The 3 blocks of the upper triangular portion of a 4x4
206 : : * symmetric matrix.
207 : : */
208 : : inline void pluseq_scaled_sum_outer_product( MsqMatrix< 2, 2 > R[3], double alpha, const MsqMatrix< 2, 2 >& A,
209 : : const MsqMatrix< 2, 2 >& B );
210 : :
211 : : /**\brief \f$ R = \alpha \left( A \otimes B + B \otimes A \right) \f$
212 : : *
213 : : *\param R The 6 blocks of the upper triangular portion of a 9x9
214 : : * symmetric matrix.
215 : : */
216 : : inline void set_scaled_sum_outer_product( MsqMatrix< 3, 3 > R[6], double alpha, const MsqMatrix< 3, 3 >& A,
217 : : const MsqMatrix< 3, 3 >& B );
218 : :
219 : : /**\brief \f$ R = \alpha \left( A \otimes B + B \otimes A \right) \f$
220 : : *
221 : : *\param R The 3 blocks of the upper triangular portion of a 4x4
222 : : * symmetric matrix.
223 : : */
224 : : inline void set_scaled_sum_outer_product( MsqMatrix< 2, 2 > R[3], double alpha, const MsqMatrix< 2, 2 >& A,
225 : : const MsqMatrix< 2, 2 >& B );
226 : :
227 : : /**\brief \f$ R += \alpha (I \otimes I) \f$
228 : : *
229 : : *\param R The 6 blocks of the upper triangular portion of a 9x9
230 : : * symmetric matrix.
231 : : */
232 : : inline void pluseq_scaled_outer_product_I_I( MsqMatrix< 3, 3 > R[6], double alpha );
233 : :
234 : : /**\brief \f$ R += \alpha (I \otimes I) \f$
235 : : *
236 : : *\param R The 3 blocks of the upper triangular portion of a 4x4
237 : : * symmetric matrix.
238 : : */
239 : : inline void pluseq_scaled_outer_product_I_I( MsqMatrix< 2, 2 > R[3], double alpha );
240 : :
241 : : /**\brief \f$ R += I \otimes A \f$
242 : : *
243 : : *\param R The 6 blocks of the upper triangular portion of a 9x9
244 : : * symmetric matrix.
245 : : */
246 : : inline void pluseq_I_outer_product( MsqMatrix< 3, 3 > R[6], const MsqMatrix< 3, 3 >& A );
247 : :
248 : : /**\brief \f$ R += A \otimes I \f$
249 : : *
250 : : *\param R The 6 blocks of the upper triangular portion of a 9x9
251 : : * symmetric matrix.
252 : : */
253 : : inline void pluseq_outer_product_I( MsqMatrix< 3, 3 > R[6], const MsqMatrix< 3, 3 >& A );
254 : :
255 : : /**\brief \f$ R += \alpha \left( I \otimes A + A \otimes I \right) \f$
256 : : *
257 : : *\param R The 6 blocks of the upper triangular portion of a 9x9
258 : : * symmetric matrix.
259 : : */
260 : : template < unsigned D >
261 : : inline void pluseq_scaled_sum_outer_product_I_t( MsqMatrix< D, D > R[D * ( D + 1 ) / 2], double alpha,
262 : : const MsqMatrix< D, D >& A );
263 : 0 : inline void pluseq_scaled_sum_outer_product_I( MsqMatrix< 3, 3 > R[6], double alpha, const MsqMatrix< 3, 3 >& A_in )
264 : : {
265 : 0 : pluseq_scaled_sum_outer_product_I_t< 3 >( R, alpha, A_in );
266 : 0 : }
267 : :
268 : 0 : inline void pluseq_scaled_sum_outer_product_I( MsqMatrix< 2, 2 > R[2], double alpha, const MsqMatrix< 2, 2 >& A_in )
269 : : {
270 : 0 : pluseq_scaled_sum_outer_product_I_t< 2 >( R, alpha, A_in );
271 : 0 : }
272 : :
273 : : /**\brief \f$ \frac{\partial^2 f}{\partial (AZ)^2} \Rightarrow \frac{\partial^2 f}{\partial A^2} \f$
274 : : *
275 : : * Given the second derivatives of a function with respect to
276 : : * a matrix product, calculate the derivatives of the function
277 : : * with respect to the first matrix in the product.
278 : : */
279 : : template < unsigned D >
280 : : inline void second_deriv_wrt_product_factor_t( MsqMatrix< D, D > R[D * ( D + 1 ) / 2], const MsqMatrix< D, D >& Z );
281 : :
282 : 236360 : inline void second_deriv_wrt_product_factor( MsqMatrix< 3, 3 > R[6], const MsqMatrix< 3, 3 >& Z )
283 : : {
284 : 236360 : second_deriv_wrt_product_factor_t< 3 >( R, Z );
285 : 236360 : }
286 : :
287 : : inline void second_deriv_wrt_product_factor( MsqMatrix< 2, 2 > R[3], const MsqMatrix< 2, 2 >& Z )
288 : : {
289 : : second_deriv_wrt_product_factor_t< 2 >( R, Z );
290 : : }
291 : :
292 : : /**\brief \f$ R = \alpha * \frac{\partial^2 \psi(T)}{\partial T^2} \f$
293 : : *
294 : : * \f$ \psi(T) = \sqrt{ |T|^2 + 2 \tau } \f$
295 : : */
296 : : inline void set_scaled_2nd_deriv_wrt_psi( MsqMatrix< 2, 2 > R[3], const double alpha, const double psi,
297 : : const MsqMatrix< 2, 2 >& T );
298 : :
299 : : /**\brief \f$ R = R + \alpha * Z \f$
300 : : */
301 : : template < unsigned D >
302 : : inline void pluseq_scaled_t( MsqMatrix< D, D > R[D * ( D + 1 ) / 2], double alpha,
303 : : const MsqMatrix< D, D > Z[D * ( D + 1 ) / 2] );
304 : :
305 : 0 : void set_scaled_I( MsqMatrix< 3, 3 > R[6], double alpha )
306 : : {
307 : 0 : R[0] = R[3] = R[5] = MsqMatrix< 3, 3 >( alpha );
308 : 0 : R[1] = R[2] = R[4] = MsqMatrix< 3, 3 >( 0.0 );
309 : 0 : }
310 : :
311 : 1046099 : void pluseq_scaled_I( MsqMatrix< 3, 3 >& R, double alpha )
312 : : {
313 : 1046099 : R( 0, 0 ) += alpha;
314 : 1046099 : R( 1, 1 ) += alpha;
315 : 1046099 : R( 2, 2 ) += alpha;
316 : 1046099 : }
317 : :
318 : 562262 : void pluseq_scaled_I( MsqMatrix< 2, 2 >& R, double alpha )
319 : : {
320 : 562262 : R( 0, 0 ) += alpha;
321 : 562262 : R( 1, 1 ) += alpha;
322 : 562262 : }
323 : :
324 : 236360 : void pluseq_scaled_I( MsqMatrix< 3, 3 > R[6], double alpha )
325 : : {
326 : 236360 : pluseq_scaled_I( R[0], alpha );
327 : 236360 : pluseq_scaled_I( R[3], alpha );
328 : 236360 : pluseq_scaled_I( R[5], alpha );
329 : 236360 : }
330 : :
331 : 0 : void set_scaled_I( MsqMatrix< 2, 2 > R[3], double alpha )
332 : : {
333 : 0 : R[0] = R[2] = MsqMatrix< 2, 2 >( alpha );
334 : 0 : R[1] = MsqMatrix< 2, 2 >( 0.0 );
335 : 0 : }
336 : :
337 : 0 : void pluseq_scaled_I( MsqMatrix< 2, 2 > R[3], double alpha )
338 : : {
339 : 0 : pluseq_scaled_I( R[0], alpha );
340 : 0 : pluseq_scaled_I( R[2], alpha );
341 : 0 : }
342 : :
343 : 236360 : void pluseq_scaled_2nd_deriv_of_det( MsqMatrix< 3, 3 > R[6], double alpha, const MsqMatrix< 3, 3 >& T )
344 : : {
345 : 236360 : MsqMatrix< 3, 3 > A( T );
346 [ + - ]: 236360 : A *= alpha;
347 : :
348 [ + - ][ + - ]: 236360 : R[1]( 0, 1 ) += A( 2, 2 );
349 [ + - ][ + - ]: 236360 : R[1]( 1, 0 ) -= A( 2, 2 );
350 [ + - ][ + - ]: 236360 : R[1]( 0, 2 ) -= A( 2, 1 );
351 [ + - ][ + - ]: 236360 : R[1]( 2, 0 ) += A( 2, 1 );
352 [ + - ][ + - ]: 236360 : R[1]( 1, 2 ) += A( 2, 0 );
353 [ + - ][ + - ]: 236360 : R[1]( 2, 1 ) -= A( 2, 0 );
354 : :
355 [ + - ][ + - ]: 236360 : R[2]( 0, 1 ) -= A( 1, 2 );
356 [ + - ][ + - ]: 236360 : R[2]( 1, 0 ) += A( 1, 2 );
357 [ + - ][ + - ]: 236360 : R[2]( 0, 2 ) += A( 1, 1 );
358 [ + - ][ + - ]: 236360 : R[2]( 2, 0 ) -= A( 1, 1 );
359 [ + - ][ + - ]: 236360 : R[2]( 1, 2 ) -= A( 1, 0 );
360 [ + - ][ + - ]: 236360 : R[2]( 2, 1 ) += A( 1, 0 );
361 : :
362 [ + - ][ + - ]: 236360 : R[4]( 0, 1 ) += A( 0, 2 );
363 [ + - ][ + - ]: 236360 : R[4]( 1, 0 ) -= A( 0, 2 );
364 [ + - ][ + - ]: 236360 : R[4]( 0, 2 ) -= A( 0, 1 );
365 [ + - ][ + - ]: 236360 : R[4]( 2, 0 ) += A( 0, 1 );
366 [ + - ][ + - ]: 236360 : R[4]( 1, 2 ) += A( 0, 0 );
367 [ + - ][ + - ]: 236360 : R[4]( 2, 1 ) -= A( 0, 0 );
368 : 236360 : }
369 : :
370 : 0 : void set_scaled_2nd_deriv_of_det( MsqMatrix< 3, 3 > R[6], double alpha, const MsqMatrix< 3, 3 >& T )
371 : : {
372 : 0 : MsqMatrix< 3, 3 > A( T );
373 [ # # ]: 0 : A *= alpha;
374 : :
375 [ # # ]: 0 : R[0] = R[3] = R[5] = MsqMatrix< 3, 3 >( 0.0 );
376 : :
377 [ # # ][ # # ]: 0 : R[1]( 0, 0 ) = R[1]( 1, 1 ) = R[1]( 2, 2 ) = 0;
[ # # ]
378 [ # # ][ # # ]: 0 : R[1]( 0, 1 ) = A( 2, 2 );
379 [ # # ][ # # ]: 0 : R[1]( 1, 0 ) = -A( 2, 2 );
380 [ # # ][ # # ]: 0 : R[1]( 0, 2 ) = -A( 2, 1 );
381 [ # # ][ # # ]: 0 : R[1]( 2, 0 ) = A( 2, 1 );
382 [ # # ][ # # ]: 0 : R[1]( 1, 2 ) = A( 2, 0 );
383 [ # # ][ # # ]: 0 : R[1]( 2, 1 ) = -A( 2, 0 );
384 : :
385 [ # # ][ # # ]: 0 : R[2]( 0, 0 ) = R[2]( 1, 1 ) = R[2]( 2, 2 ) = 0;
[ # # ]
386 [ # # ][ # # ]: 0 : R[2]( 0, 1 ) = -A( 1, 2 );
387 [ # # ][ # # ]: 0 : R[2]( 1, 0 ) = A( 1, 2 );
388 [ # # ][ # # ]: 0 : R[2]( 0, 2 ) = A( 1, 1 );
389 [ # # ][ # # ]: 0 : R[2]( 2, 0 ) = -A( 1, 1 );
390 [ # # ][ # # ]: 0 : R[2]( 1, 2 ) = -A( 1, 0 );
391 [ # # ][ # # ]: 0 : R[2]( 2, 1 ) = A( 1, 0 );
392 : :
393 [ # # ][ # # ]: 0 : R[4]( 0, 0 ) = R[4]( 1, 1 ) = R[4]( 2, 2 ) = 0;
[ # # ]
394 [ # # ][ # # ]: 0 : R[4]( 0, 1 ) = A( 0, 2 );
395 [ # # ][ # # ]: 0 : R[4]( 1, 0 ) = -A( 0, 2 );
396 [ # # ][ # # ]: 0 : R[4]( 0, 2 ) = -A( 0, 1 );
397 [ # # ][ # # ]: 0 : R[4]( 2, 0 ) = A( 0, 1 );
398 [ # # ][ # # ]: 0 : R[4]( 1, 2 ) = A( 0, 0 );
399 [ # # ][ # # ]: 0 : R[4]( 2, 1 ) = -A( 0, 0 );
400 : 0 : }
401 : :
402 : 0 : void pluseq_scaled_2nd_deriv_of_det( MsqMatrix< 2, 2 > R[3], double alpha )
403 : : {
404 : 0 : R[1]( 0, 1 ) += alpha;
405 : 0 : R[1]( 1, 0 ) -= alpha;
406 : 0 : }
407 : :
408 : : void set_scaled_2nd_deriv_of_det( MsqMatrix< 2, 2 > R[3], double alpha )
409 : : {
410 : : R[0] = R[2] = MsqMatrix< 2, 2 >( 0.0 );
411 : : R[1]( 0, 0 ) = 0.0;
412 : : R[1]( 0, 1 ) = alpha;
413 : : R[1]( 1, 0 ) = -alpha;
414 : : R[1]( 1, 1 ) = 0.0;
415 : : }
416 : :
417 : : void pluseq_scaled_2nd_deriv_tr_adj( MsqMatrix< 2, 2 >*, double )
418 : : {
419 : : // 2nd derivative is zero
420 : : }
421 : :
422 : 0 : void pluseq_scaled_2nd_deriv_tr_adj( MsqMatrix< 3, 3 > R[6], double alpha )
423 : : {
424 : 0 : R[1]( 0, 1 ) += alpha;
425 : 0 : R[1]( 1, 0 ) -= alpha;
426 : 0 : R[2]( 0, 2 ) += alpha;
427 : 0 : R[2]( 2, 0 ) -= alpha;
428 : 0 : R[4]( 1, 2 ) += alpha;
429 : 0 : R[4]( 2, 1 ) -= alpha;
430 : 0 : }
431 : :
432 : : void set_scaled_2nd_deriv_norm_sqr_adj( MsqMatrix< 2, 2 > R[3], double alpha, const MsqMatrix< 2, 2 >& )
433 : : {
434 : : set_scaled_I( R, 2 * alpha );
435 : : }
436 : :
437 : 0 : void set_scaled_2nd_deriv_norm_sqr_adj( MsqMatrix< 3, 3 > R[6], double alpha, const MsqMatrix< 3, 3 >& T )
438 : : {
439 [ # # ]: 0 : set_scaled_outer_product( R, 1, T );
440 : : double tmp01, tmp02, tmp12;
441 : : // R[1] = 2*R[1] - transpose(R[1]);
442 [ # # ]: 0 : tmp01 = R[1]( 0, 1 );
443 [ # # ]: 0 : tmp02 = R[1]( 0, 2 );
444 [ # # ]: 0 : tmp12 = R[1]( 1, 2 );
445 [ # # ][ # # ]: 0 : R[1]( 0, 1 ) = 2 * R[1]( 0, 1 ) - R[1]( 1, 0 );
[ # # ]
446 [ # # ][ # # ]: 0 : R[1]( 0, 2 ) = 2 * R[1]( 0, 2 ) - R[1]( 2, 0 );
[ # # ]
447 [ # # ][ # # ]: 0 : R[1]( 1, 2 ) = 2 * R[1]( 1, 2 ) - R[1]( 2, 1 );
[ # # ]
448 [ # # ][ # # ]: 0 : R[1]( 1, 0 ) = 2 * R[1]( 1, 0 ) - tmp01;
449 [ # # ][ # # ]: 0 : R[1]( 2, 0 ) = 2 * R[1]( 2, 0 ) - tmp02;
450 [ # # ][ # # ]: 0 : R[1]( 2, 1 ) = 2 * R[1]( 2, 1 ) - tmp12;
451 : : // R[2] = 2*R[2] - transpose(R[1]);
452 [ # # ]: 0 : tmp01 = R[2]( 0, 1 );
453 [ # # ]: 0 : tmp02 = R[2]( 0, 2 );
454 [ # # ]: 0 : tmp12 = R[2]( 1, 2 );
455 [ # # ][ # # ]: 0 : R[2]( 0, 1 ) = 2 * R[2]( 0, 1 ) - R[2]( 1, 0 );
[ # # ]
456 [ # # ][ # # ]: 0 : R[2]( 0, 2 ) = 2 * R[2]( 0, 2 ) - R[2]( 2, 0 );
[ # # ]
457 [ # # ][ # # ]: 0 : R[2]( 1, 2 ) = 2 * R[2]( 1, 2 ) - R[2]( 2, 1 );
[ # # ]
458 [ # # ][ # # ]: 0 : R[2]( 1, 0 ) = 2 * R[2]( 1, 0 ) - tmp01;
459 [ # # ][ # # ]: 0 : R[2]( 2, 0 ) = 2 * R[2]( 2, 0 ) - tmp02;
460 [ # # ][ # # ]: 0 : R[2]( 2, 1 ) = 2 * R[2]( 2, 1 ) - tmp12;
461 : : // R[4] = 2*R[4] - transpose(R[1]);
462 [ # # ]: 0 : tmp01 = R[4]( 0, 1 );
463 [ # # ]: 0 : tmp02 = R[4]( 0, 2 );
464 [ # # ]: 0 : tmp12 = R[4]( 1, 2 );
465 [ # # ][ # # ]: 0 : R[4]( 0, 1 ) = 2 * R[4]( 0, 1 ) - R[4]( 1, 0 );
[ # # ]
466 [ # # ][ # # ]: 0 : R[4]( 0, 2 ) = 2 * R[4]( 0, 2 ) - R[4]( 2, 0 );
[ # # ]
467 [ # # ][ # # ]: 0 : R[4]( 1, 2 ) = 2 * R[4]( 1, 2 ) - R[4]( 2, 1 );
[ # # ]
468 [ # # ][ # # ]: 0 : R[4]( 1, 0 ) = 2 * R[4]( 1, 0 ) - tmp01;
469 [ # # ][ # # ]: 0 : R[4]( 2, 0 ) = 2 * R[4]( 2, 0 ) - tmp02;
470 [ # # ][ # # ]: 0 : R[4]( 2, 1 ) = 2 * R[4]( 2, 1 ) - tmp12;
471 : :
472 [ # # ][ # # ]: 0 : const MsqMatrix< 3, 3 > TpT = transpose( T ) * T;
473 [ # # ]: 0 : R[0] -= TpT;
474 [ # # ]: 0 : R[3] -= TpT;
475 [ # # ]: 0 : R[5] -= TpT;
476 : :
477 [ # # ][ # # ]: 0 : const MsqMatrix< 3, 3 > TTp = T * transpose( T );
478 [ # # ]: 0 : const double ns = sqr_Frobenius( T );
479 [ # # ][ # # ]: 0 : R[0]( 0, 0 ) += ns - TTp( 0, 0 );
480 [ # # ][ # # ]: 0 : R[0]( 1, 1 ) += ns - TTp( 0, 0 );
481 [ # # ][ # # ]: 0 : R[0]( 2, 2 ) += ns - TTp( 0, 0 );
482 [ # # ][ # # ]: 0 : R[1]( 0, 0 ) += -TTp( 0, 1 );
483 [ # # ][ # # ]: 0 : R[1]( 1, 1 ) += -TTp( 0, 1 );
484 [ # # ][ # # ]: 0 : R[1]( 2, 2 ) += -TTp( 0, 1 );
485 [ # # ][ # # ]: 0 : R[2]( 0, 0 ) += -TTp( 0, 2 );
486 [ # # ][ # # ]: 0 : R[2]( 1, 1 ) += -TTp( 0, 2 );
487 [ # # ][ # # ]: 0 : R[2]( 2, 2 ) += -TTp( 0, 2 );
488 [ # # ][ # # ]: 0 : R[3]( 0, 0 ) += ns - TTp( 1, 1 );
489 [ # # ][ # # ]: 0 : R[3]( 1, 1 ) += ns - TTp( 1, 1 );
490 [ # # ][ # # ]: 0 : R[3]( 2, 2 ) += ns - TTp( 1, 1 );
491 [ # # ][ # # ]: 0 : R[4]( 0, 0 ) += -TTp( 1, 2 );
492 [ # # ][ # # ]: 0 : R[4]( 1, 1 ) += -TTp( 1, 2 );
493 [ # # ][ # # ]: 0 : R[4]( 2, 2 ) += -TTp( 1, 2 );
494 [ # # ][ # # ]: 0 : R[5]( 0, 0 ) += ns - TTp( 2, 2 );
495 [ # # ][ # # ]: 0 : R[5]( 1, 1 ) += ns - TTp( 2, 2 );
496 [ # # ][ # # ]: 0 : R[5]( 2, 2 ) += ns - TTp( 2, 2 );
497 : :
498 : 0 : alpha *= 2;
499 [ # # ]: 0 : R[0] *= alpha;
500 [ # # ]: 0 : R[1] *= alpha;
501 [ # # ]: 0 : R[2] *= alpha;
502 [ # # ]: 0 : R[3] *= alpha;
503 [ # # ]: 0 : R[4] *= alpha;
504 [ # # ]: 0 : R[5] *= alpha;
505 : 0 : }
506 : :
507 : : #ifdef MSQ_ROW_BASED_OUTER_PRODUCT
508 : : template < unsigned D >
509 : 118180 : void pluseq_scaled_outer_product_t( MsqMatrix< D, D > R[D * ( D + 1 ) / 2], double alpha, const MsqMatrix< D, D >& M )
510 : : {
511 : 118180 : MsqMatrix< D, D > aM( M );
512 [ + - ][ # # ]: 118180 : aM *= alpha;
513 : 118180 : unsigned h = 0;
514 [ + + ][ # # ]: 472720 : for( unsigned i = 0; i < D; ++i )
515 [ + + ][ # # ]: 1063620 : for( unsigned j = i; j < D; ++j )
516 [ + - ][ + - ]: 709080 : R[h++] += transpose( aM.row( i ) ) * M.row( j );
[ + - ][ + - ]
[ + - ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
517 : 118180 : }
518 : : #else
519 : : template < unsigned D >
520 : : void pluseq_scaled_outer_product_t( MsqMatrix< D, D > R[D * ( D + 1 ) / 2], double alpha, const MsqMatrix< D, D >& M )
521 : : {
522 : : MsqMatrix< D, D > aM( transpose( M ) );
523 : : aM *= alpha;
524 : : unsigned h = 0;
525 : : for( unsigned i = 0; i < D; ++i )
526 : : for( unsigned j = i; j < D; ++j )
527 : : R[h++] += M.column( i ) * aM.row( 0 );
528 : : }
529 : : #endif
530 : :
531 : : #ifdef MSQ_ROW_BASED_OUTER_PRODUCT
532 : : template < unsigned D >
533 : 236360 : void set_scaled_outer_product_t( MsqMatrix< D, D > R[D * ( D + 1 ) / 2], double alpha, const MsqMatrix< D, D >& M )
534 : : {
535 : 236360 : MsqMatrix< D, D > aM( M );
536 [ # # ][ + - ]: 236360 : aM *= alpha;
537 : 236360 : unsigned h = 0;
538 [ # # ][ + + ]: 945440 : for( unsigned i = 0; i < D; ++i )
539 [ # # ][ + + ]: 2127240 : for( unsigned j = i; j < D; ++j )
540 [ # # ][ # # ]: 1418160 : R[h++] = transpose( aM.row( i ) ) * M.row( j );
[ # # ][ # # ]
[ + - ][ + - ]
[ + - ][ + - ]
541 : 236360 : }
542 : : #else
543 : : template < unsigned D >
544 : : void set_scaled_outer_product_t( MsqMatrix< D, D > R[D * ( D + 1 ) / 2], double alpha, const MsqMatrix< D, D >& M )
545 : : {
546 : : MsqMatrix< D, D > aM( transpose( M ) );
547 : : aM *= alpha;
548 : : unsigned h = 0;
549 : : for( unsigned i = 0; i < D; ++i )
550 : : for( unsigned j = i; j < D; ++j )
551 : : R[h++] = M.column( i ) * aM.row( j );
552 : : }
553 : : #endif
554 : :
555 : : #ifdef MSQ_ROW_BASED_OUTER_PRODUCT
556 : 236360 : void pluseq_scaled_sum_outer_product( MsqMatrix< 3, 3 > R[6], double alpha, const MsqMatrix< 3, 3 >& A_in,
557 : : const MsqMatrix< 3, 3 >& B )
558 : : {
559 : : // apply scalar first
560 [ + - ]: 236360 : MsqMatrix< 3, 3 > A( A_in ), tmp;
561 [ + - ]: 236360 : A *= alpha;
562 : :
563 : : // block 0,0
564 [ + - ][ + - ]: 236360 : tmp = transpose( A.row( 0 ) ) * B.row( 0 );
[ + - ][ + - ]
565 [ + - ]: 236360 : R[0] += tmp;
566 [ + - ][ + - ]: 236360 : R[0] += transpose( tmp );
567 : :
568 : : // block 1,1
569 [ + - ][ + - ]: 236360 : tmp = transpose( A.row( 1 ) ) * B.row( 1 );
[ + - ][ + - ]
570 [ + - ]: 236360 : R[3] += tmp;
571 [ + - ][ + - ]: 236360 : R[3] += transpose( tmp );
572 : :
573 : : // block 2,2
574 [ + - ][ + - ]: 236360 : tmp = transpose( A.row( 2 ) ) * B.row( 2 );
[ + - ][ + - ]
575 [ + - ]: 236360 : R[5] += tmp;
576 [ + - ][ + - ]: 236360 : R[5] += transpose( tmp );
577 : :
578 : : // block 0,1
579 [ + - ][ + - ]: 236360 : R[1] += transpose( A.row( 0 ) ) * B.row( 1 ) + transpose( B.row( 0 ) ) * A.row( 1 );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
580 : :
581 : : // block 0,2
582 [ + - ][ + - ]: 236360 : R[2] += transpose( A.row( 0 ) ) * B.row( 2 ) + transpose( B.row( 0 ) ) * A.row( 2 );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
583 : :
584 : : // block 1,2
585 [ + - ][ + - ]: 236360 : R[4] += transpose( A.row( 1 ) ) * B.row( 2 ) + transpose( B.row( 1 ) ) * A.row( 2 );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
586 : 236360 : }
587 : : void set_scaled_sum_outer_product( MsqMatrix< 3, 3 > R[6], double alpha, const MsqMatrix< 3, 3 >& A_in,
588 : : const MsqMatrix< 3, 3 >& B )
589 : : {
590 : : // apply scalar first
591 : : MsqMatrix< 3, 3 > A( A_in );
592 : : A *= alpha;
593 : :
594 : : // block 0,0
595 : : R[0] = transpose( A.row( 0 ) ) * B.row( 0 );
596 : : R[0] += transpose( R[0] );
597 : :
598 : : // block 1,1
599 : : R[3] = transpose( A.row( 1 ) ) * B.row( 1 );
600 : : R[3] += transpose( R[3] );
601 : :
602 : : // block 2,2
603 : : R[5] = transpose( A.row( 2 ) ) * B.row( 2 );
604 : : R[5] += transpose( R[5] );
605 : :
606 : : // block 0,1
607 : : R[1] = transpose( A.row( 0 ) ) * B.row( 1 );
608 : : R[1] += transpose( B.row( 0 ) ) * A.row( 1 );
609 : :
610 : : // block 0,2
611 : : R[2] = transpose( A.row( 0 ) ) * B.row( 2 );
612 : : R[2] += transpose( B.row( 0 ) ) * A.row( 2 );
613 : :
614 : : // block 1,2
615 : : R[4] = transpose( A.row( 1 ) ) * B.row( 2 );
616 : : R[4] += transpose( B.row( 1 ) ) * A.row( 2 );
617 : : }
618 : : #else
619 : : void pluseq_scaled_sum_outer_product( MsqMatrix< 3, 3 > R[6], double alpha, const MsqMatrix< 3, 3 >& A_in,
620 : : const MsqMatrix< 3, 3 >& B )
621 : : {
622 : : // apply scalar first
623 : : MsqMatrix< 3, 3 > A( A_in ), tmp;
624 : : A *= alpha;
625 : :
626 : : // block 0,0
627 : : tmp = A.column( 0 ) * transpose( B.column( 0 ) );
628 : : R[0] += tmp;
629 : : R[0] += transpose( tmp );
630 : :
631 : : // block 1,1
632 : : tmp = A.column( 1 ) * transpose( B.column( 1 ) );
633 : : R[3] += tmp;
634 : : R[3] += transpose( tmp );
635 : :
636 : : // block 2,2
637 : : tmp = A.column( 2 ) * transpose( B.column( 2 ) );
638 : : R[5] += tmp;
639 : : R[5] += transpose( tmp );
640 : :
641 : : // block 0,1
642 : : R[1] += A.column( 0 ) * transpose( B.column( 1 ) ) + B.column( 0 ) * transpose( A.column( 1 ) );
643 : :
644 : : // block 0,2
645 : : R[2] += A.column( 0 ) * transpose( B.column( 2 ) ) + B.column( 0 ) * transpose( A.column( 2 ) );
646 : :
647 : : // block 1,2
648 : : R[4] += A.column( 1 ) * transpose( B.column( 2 ) ) + B.column( 1 ) * transpose( A.column( 2 ) );
649 : : }
650 : : void set_scaled_sum_outer_product( MsqMatrix< 3, 3 > R[6], double alpha, const MsqMatrix< 3, 3 >& A_in,
651 : : const MsqMatrix< 3, 3 >& B )
652 : : {
653 : : // apply scalar first
654 : : MsqMatrix< 3, 3 > A( A_in );
655 : : A *= alpha;
656 : :
657 : : // block 0,0
658 : : R[0] = A.column( 0 ) * transpose( B.column( 0 ) );
659 : : R[0] += transpose( R[0] );
660 : :
661 : : // block 1,1
662 : : R[3] = A.column( 1 ) * transpose( B.column( 1 ) );
663 : : R[3] += transpose( R[3] );
664 : :
665 : : // block 2,2
666 : : R[5] = A.column( 2 ) * transpose( B.column( 2 ) );
667 : : R[5] += transpose( R[5] );
668 : :
669 : : // block 0,1
670 : : R[1] = A.column( 0 ) * transpose( B.column( 1 ) );
671 : : R[1] += B.column( 0 ) * transpose( A.column( 1 ) );
672 : :
673 : : // block 0,2
674 : : R[2] = A.column( 0 ) * transpose( B.column( 2 ) );
675 : : R[2] += B.column( 0 ) * transpose( A.column( 2 ) );
676 : :
677 : : // block 1,2
678 : : R[4] = A.column( 1 ) * transpose( B.column( 2 ) );
679 : : R[4] += B.column( 1 ) * transpose( A.column( 2 ) );
680 : : }
681 : : #endif
682 : :
683 : : #ifdef MSQ_ROW_BASED_OUTER_PRODUCT
684 : 0 : void pluseq_scaled_sum_outer_product( MsqMatrix< 2, 2 > R[3], double alpha, const MsqMatrix< 2, 2 >& A_in,
685 : : const MsqMatrix< 2, 2 >& B )
686 : : {
687 : : // apply scalar first
688 [ # # ]: 0 : MsqMatrix< 2, 2 > A( A_in ), tmp;
689 [ # # ]: 0 : A *= alpha;
690 : :
691 : : // block 0,0
692 [ # # ][ # # ]: 0 : tmp = transpose( A.row( 0 ) ) * B.row( 0 );
[ # # ][ # # ]
693 [ # # ]: 0 : R[0] += tmp;
694 [ # # ][ # # ]: 0 : R[0] += transpose( tmp );
695 : :
696 : : // block 1,1
697 [ # # ][ # # ]: 0 : tmp = transpose( A.row( 1 ) ) * B.row( 1 );
[ # # ][ # # ]
698 [ # # ]: 0 : R[2] += tmp;
699 [ # # ][ # # ]: 0 : R[2] += transpose( tmp );
700 : :
701 : : // block 0,1
702 [ # # ][ # # ]: 0 : R[1] += transpose( A.row( 0 ) ) * B.row( 1 ) + transpose( B.row( 0 ) ) * A.row( 1 );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
703 : 0 : }
704 : 0 : void set_scaled_sum_outer_product( MsqMatrix< 2, 2 > R[3], double alpha, const MsqMatrix< 2, 2 >& A_in,
705 : : const MsqMatrix< 2, 2 >& B )
706 : : {
707 : : // apply scalar first
708 : 0 : MsqMatrix< 2, 2 > A( A_in );
709 [ # # ]: 0 : A *= alpha;
710 : :
711 : : // block 0,0
712 [ # # ][ # # ]: 0 : R[0] = transpose( A.row( 0 ) ) * B.row( 0 );
[ # # ][ # # ]
713 [ # # ][ # # ]: 0 : R[0] += transpose( R[0] );
714 : :
715 : : // block 1,1
716 [ # # ][ # # ]: 0 : R[2] = transpose( A.row( 1 ) ) * B.row( 1 );
[ # # ][ # # ]
717 [ # # ][ # # ]: 0 : R[2] += transpose( R[2] );
718 : :
719 : : // block 0,1
720 [ # # ][ # # ]: 0 : R[1] = transpose( A.row( 0 ) ) * B.row( 1 );
[ # # ][ # # ]
721 [ # # ][ # # ]: 0 : R[1] += transpose( B.row( 0 ) ) * A.row( 1 );
[ # # ][ # # ]
[ # # ]
722 : 0 : }
723 : : #else
724 : : void pluseq_scaled_sum_outer_product( MsqMatrix< 2, 2 > R[3], double alpha, const MsqMatrix< 2, 2 >& A_in,
725 : : const MsqMatrix< 2, 2 >& B )
726 : : {
727 : : // apply scalar first
728 : : MsqMatrix< 2, 2 > A( A_in ), tmp;
729 : : A *= alpha;
730 : :
731 : : // block 0,0
732 : : tmp = A.column( 0 ) * transpose( B.column( 0 ) );
733 : : R[0] += tmp;
734 : : R[0] += transpose( tmp );
735 : :
736 : : // block 1,1
737 : : tmp = A.column( 1 ) * transpose( B.column( 1 ) );
738 : : R[2] += tmp;
739 : : R[2] += transpose( tmp );
740 : :
741 : : // block 0,1
742 : : R[1] += A.column( 0 ) * transpose( B.column( 1 ) ) + B.column( 0 ) * transpose( A.column( 1 ) );
743 : : }
744 : : void set_scaled_sum_outer_product( MsqMatrix< 2, 2 > R[3], double alpha, const MsqMatrix< 2, 2 >& A_in,
745 : : const MsqMatrix< 2, 2 >& B )
746 : : {
747 : : // apply scalar first
748 : : MsqMatrix< 2, 2 > A( A_in );
749 : : A *= alpha;
750 : :
751 : : // block 0,0
752 : : R[0] = A.column( 0 ) * transpose( B.column( 0 ) );
753 : : R[0] += transpose( R[0] );
754 : :
755 : : // block 1,1
756 : : R[2] = A.column( 1 ) * transpose( B.column( 1 ) );
757 : : R[2] += transpose( R[2] );
758 : :
759 : : // block 0,1
760 : : R[1] = A.column( 0 ) * transpose( B.column( 1 ) );
761 : : R[1] += B.column( 0 ) * transpose( A.column( 1 ) );
762 : : }
763 : : #endif
764 : :
765 : 0 : void pluseq_scaled_outer_product_I_I( MsqMatrix< 3, 3 > R[6], double alpha )
766 : : {
767 : 0 : R[0]( 0, 0 ) += alpha;
768 : 0 : R[1]( 0, 1 ) += alpha;
769 : 0 : R[2]( 0, 2 ) += alpha;
770 : 0 : R[3]( 1, 1 ) += alpha;
771 : 0 : R[4]( 1, 2 ) += alpha;
772 : 0 : R[5]( 2, 2 ) += alpha;
773 : 0 : }
774 : :
775 : 0 : void pluseq_scaled_outer_product_I_I( MsqMatrix< 2, 2 > R[3], double alpha )
776 : : {
777 : 0 : R[0]( 0, 0 ) += alpha;
778 : 0 : R[1]( 0, 1 ) += alpha;
779 : 0 : R[2]( 1, 1 ) += alpha;
780 : 0 : }
781 : :
782 : : #ifdef MSQ_ROW_BASED_OUTER_PRODUCT
783 : 0 : inline void pluseq_I_outer_product( MsqMatrix< 3, 3 > R[6], const MsqMatrix< 3, 3 >& A )
784 : : {
785 [ # # ]: 0 : R[0].add_row( 0, A.row( 0 ) );
786 [ # # ]: 0 : R[1].add_row( 0, A.row( 1 ) );
787 [ # # ]: 0 : R[2].add_row( 0, A.row( 2 ) );
788 [ # # ]: 0 : R[3].add_row( 1, A.row( 1 ) );
789 [ # # ]: 0 : R[4].add_row( 1, A.row( 2 ) );
790 [ # # ]: 0 : R[5].add_row( 2, A.row( 2 ) );
791 : 0 : }
792 : 0 : inline void pluseq_I_outer_product( MsqMatrix< 2, 2 > R[3], const MsqMatrix< 2, 2 >& A )
793 : : {
794 [ # # ]: 0 : R[0].add_row( 0, A.row( 0 ) );
795 [ # # ]: 0 : R[1].add_row( 0, A.row( 1 ) );
796 [ # # ]: 0 : R[2].add_row( 1, A.row( 1 ) );
797 : 0 : }
798 : : #else
799 : : inline void pluseq_I_outer_product( MsqMatrix< 3, 3 > R[6], const MsqMatrix< 3, 3 >& A )
800 : : {
801 : : R[0].add_row( 0, transpose( A.column( 0 ) ) );
802 : : R[1].add_row( 0, transpose( A.column( 1 ) ) );
803 : : R[2].add_row( 0, transpose( A.column( 2 ) ) );
804 : : R[3].add_row( 1, transpose( A.column( 1 ) ) );
805 : : R[4].add_row( 1, transpose( A.column( 2 ) ) );
806 : : R[5].add_row( 2, transpose( A.column( 2 ) ) );
807 : : }
808 : : inline void pluseq_I_outer_product( MsqMatrix< 2, 2 > R[3], const MsqMatrix< 2, 2 >& A )
809 : : {
810 : : R[0].add_row( 0, transpose( A.column( 0 ) ) );
811 : : R[1].add_row( 0, transpose( A.column( 1 ) ) );
812 : : R[2].add_row( 1, transpose( A.column( 1 ) ) );
813 : : }
814 : : #endif
815 : :
816 : : #ifdef MSQ_ROW_BASED_OUTER_PRODUCT
817 : 0 : inline void pluseq_outer_product_I( MsqMatrix< 3, 3 > R[6], const MsqMatrix< 3, 3 >& A )
818 : : {
819 [ # # ][ # # ]: 0 : R[0].add_column( 0, transpose( A.row( 0 ) ) );
820 [ # # ][ # # ]: 0 : R[1].add_column( 1, transpose( A.row( 0 ) ) );
821 [ # # ][ # # ]: 0 : R[2].add_column( 2, transpose( A.row( 0 ) ) );
822 [ # # ][ # # ]: 0 : R[3].add_column( 1, transpose( A.row( 1 ) ) );
823 [ # # ][ # # ]: 0 : R[4].add_column( 2, transpose( A.row( 1 ) ) );
824 [ # # ][ # # ]: 0 : R[5].add_column( 2, transpose( A.row( 2 ) ) );
825 : 0 : }
826 : 0 : inline void pluseq_outer_product_I( MsqMatrix< 2, 2 > R[3], const MsqMatrix< 2, 2 >& A )
827 : : {
828 [ # # ][ # # ]: 0 : R[0].add_column( 0, transpose( A.row( 0 ) ) );
829 [ # # ][ # # ]: 0 : R[1].add_column( 1, transpose( A.row( 0 ) ) );
830 [ # # ][ # # ]: 0 : R[2].add_column( 1, transpose( A.row( 1 ) ) );
831 : 0 : }
832 : : #else
833 : : inline void pluseq_outer_product_I( MsqMatrix< 3, 3 > R[6], const MsqMatrix< 3, 3 >& A )
834 : : {
835 : : R[0].add_column( 0, A.column( 0 ) );
836 : : R[1].add_column( 1, A.column( 0 ) );
837 : : R[2].add_column( 2, A.column( 0 ) );
838 : : R[3].add_column( 1, A.column( 1 ) );
839 : : R[4].add_column( 2, A.column( 1 ) );
840 : : R[5].add_column( 2, A.column( 2 ) );
841 : : }
842 : : inline void pluseq_outer_product_I( MsqMatrix< 2, 2 > R[3], const MsqMatrix< 2, 2 >& A )
843 : : {
844 : : R[0].add_column( 0, A.column( 0 ) );
845 : : R[1].add_column( 1, A.column( 0 ) );
846 : : R[2].add_column( 1, A.column( 1 ) );
847 : : }
848 : : #endif
849 : :
850 : : template < unsigned D >
851 : 0 : void pluseq_scaled_sum_outer_product_I_t( MsqMatrix< D, D > R[D * ( D + 1 ) / 2], double alpha,
852 : : const MsqMatrix< D, D >& A_in )
853 : : {
854 : : // apply scalar first
855 : 0 : MsqMatrix< D, D > A( A_in );
856 [ # # ][ # # ]: 0 : A *= alpha;
857 [ # # ][ # # ]: 0 : pluseq_I_outer_product( R, A );
858 [ # # ][ # # ]: 0 : pluseq_outer_product_I( R, A );
859 : 0 : }
860 : :
861 : : template < unsigned D >
862 : 236360 : void second_deriv_wrt_product_factor_t( MsqMatrix< D, D > R[D * ( D + 1 ) / 2], const MsqMatrix< D, D >& Z )
863 : : {
864 [ + - ]: 236360 : const MsqMatrix< D, D > Zt = transpose( Z );
865 [ + + ]: 1654520 : for( unsigned i = 0; i < D * ( D + 1 ) / 2; ++i )
866 [ + - ][ + - ]: 1418160 : R[i] = ( Z * R[i] ) * Zt;
867 : 236360 : }
868 : :
869 : 0 : void set_scaled_2nd_deriv_wrt_psi( MsqMatrix< 2, 2 > R[3], const double alpha, const double psi,
870 : : const MsqMatrix< 2, 2 >& T )
871 : : {
872 : 0 : const double t = trace( T );
873 : 0 : const double f = alpha / ( psi * psi * psi );
874 : 0 : const double s = T( 0, 1 ) - T( 1, 0 );
875 : 0 : R[0]( 0, 0 ) = R[1]( 0, 1 ) = R[2]( 1, 1 ) = f * s * s;
876 : 0 : R[0]( 0, 1 ) = R[0]( 1, 0 ) = R[1]( 1, 1 ) = -f * s * t;
877 : 0 : R[1]( 0, 0 ) = R[2]( 0, 1 ) = R[2]( 1, 0 ) = f * s * t;
878 : 0 : R[0]( 1, 1 ) = R[2]( 0, 0 ) = -( R[1]( 1, 0 ) = -f * t * t );
879 : 0 : }
880 : :
881 : : template < unsigned D >
882 : : inline void pluseq_scaled( MsqMatrix< D, D > R[D * ( D + 1 ) / 2], double alpha,
883 : : const MsqMatrix< D, D > Z[D * ( D + 1 ) / 2] )
884 : : {
885 : : for( unsigned i = 0; i < D * ( D + 1 ) / 2; ++i )
886 : : R[i] += alpha * Z[i];
887 : : }
888 : :
889 : : /**\brief \f$ R *= s */
890 : : template < unsigned D >
891 : 0 : inline void hess_scale_t( MsqMatrix< D, D > R[D * ( D + 1 ) / 2], double alpha )
892 : : {
893 [ # # ][ # # ]: 0 : for( unsigned i = 0; i < D * ( D + 1 ) / 2; ++i )
894 : 0 : R[i] *= alpha;
895 : 0 : }
896 : :
897 : : } // namespace MBMesquite
898 : :
899 : : #endif
|