|
Intrepid
|
00001 // @HEADER 00002 // ************************************************************************ 00003 // 00004 // Intrepid Package 00005 // Copyright (2007) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions: Alejandro Mota (amota@sandia.gov) 00038 // 00039 // ************************************************************************ 00040 // @HEADER 00041 00042 #if !defined(Intrepid_MiniTensor_Tensor4_t_h) 00043 #define Intrepid_MiniTensor_Tensor4_t_h 00044 00045 namespace Intrepid { 00046 00047 namespace { 00048 00049 template< typename T, Index N> 00050 inline 00051 void ones_in_ikjl(Tensor4<T, N> & A) 00052 { 00053 00054 Index const 00055 dimension = A.get_dimension(); 00056 00057 for (Index i = 0; i < dimension; ++i) { 00058 for (Index j = 0; j < dimension; ++j) { 00059 for (Index k = 0; k < dimension; ++k) { 00060 for (Index l = 0; l < dimension; ++l) { 00061 if (i == k && j == l) { 00062 A(i,j,k,l) = 1; 00063 } 00064 } 00065 } 00066 } 00067 } 00068 00069 return; 00070 } 00071 00072 template< typename T, Index N> 00073 inline 00074 void ones_in_iljk(Tensor4<T, N> & A) 00075 { 00076 00077 Index const 00078 dimension = A.get_dimension(); 00079 00080 for (Index i = 0; i < dimension; ++i) { 00081 for (Index j = 0; j < dimension; ++j) { 00082 for (Index k = 0; k < dimension; ++k) { 00083 for (Index l = 0; l < dimension; ++l) { 00084 if (i == l && j == k) { 00085 A(i,j,k,l) = 1; 00086 } 00087 } 00088 } 00089 } 00090 } 00091 00092 return; 00093 } 00094 00095 template< typename T, Index N> 00096 inline 00097 void ones_in_ijkl(Tensor4<T, N> & A) 00098 { 00099 00100 Index const 00101 dimension = A.get_dimension(); 00102 00103 for (Index i = 0; i < dimension; ++i) { 00104 for (Index j = 0; j < dimension; ++j) { 00105 for (Index k = 0; k < dimension; ++k) { 00106 for (Index l = 0; l < dimension; ++l) { 00107 if (i == j && k == l) { 00108 A(i,j,k,l) = 1; 00109 } 00110 } 00111 } 00112 } 00113 } 00114 00115 return; 00116 } 00117 00118 } // anonymous namespace 00119 00120 // 00121 // 4th-order identity I1 00122 // \return \f$ \delta_{ik} \delta_{jl} \f$ such that \f$ A = I_1 A \f$ 00123 // 00124 template<typename T, Index N> 00125 const Tensor4<T, N> 00126 identity_1() 00127 { 00128 Tensor4<T, N> I(N, ZEROS); 00129 ones_in_ikjl(I); 00130 return I; 00131 } 00132 00133 template<typename T> 00134 const Tensor4<T, DYNAMIC> 00135 identity_1(Index const dimension) 00136 { 00137 Tensor4<T, DYNAMIC> I(dimension, ZEROS); 00138 ones_in_ikjl(I); 00139 return I; 00140 } 00141 00142 template<typename T, Index N> 00143 const Tensor4<T, N> 00144 identity_1(Index const dimension) 00145 { 00146 if (N != DYNAMIC) assert(dimension == N); 00147 00148 Tensor4<T, N> I(dimension, ZEROS); 00149 ones_in_ikjl(I); 00150 return I; 00151 } 00152 00153 // 00154 // 4th-order identity I2 00155 // \return \f$ \delta_{il} \delta_{jk} \f$ such that \f$ A^T = I_2 A \f$ 00156 // 00157 template<typename T, Index N> 00158 const Tensor4<T, N> 00159 identity_2() 00160 { 00161 Tensor4<T, N> I(N, ZEROS); 00162 ones_in_iljk(I); 00163 return I; 00164 } 00165 00166 template<typename T> 00167 const Tensor4<T, DYNAMIC> 00168 identity_2(Index const dimension) 00169 { 00170 Tensor4<T, DYNAMIC> I(dimension, ZEROS); 00171 ones_in_iljk(I); 00172 return I; 00173 } 00174 00175 template<typename T, Index N> 00176 const Tensor4<T, N> 00177 identity_2(Index const dimension) 00178 { 00179 if (N != DYNAMIC) assert(dimension == N); 00180 00181 Tensor4<T, N> I(dimension, ZEROS); 00182 ones_in_iljk(I); 00183 return I; 00184 } 00185 00186 // 00187 // 4th-order identity I3 00188 // \return \f$ \delta_{ij} \delta_{kl} \f$ such that \f$ I_A I = I_3 A \f$ 00189 // 00190 template<typename T, Index N> 00191 const Tensor4<T, N> 00192 identity_3() 00193 { 00194 Tensor4<T, N> I(N, ZEROS); 00195 ones_in_ijkl(I); 00196 return I; 00197 } 00198 00199 template<typename T> 00200 const Tensor4<T, DYNAMIC> 00201 identity_3(Index const dimension) 00202 { 00203 Tensor4<T, DYNAMIC> I(dimension, ZEROS); 00204 ones_in_ijkl(I); 00205 return I; 00206 } 00207 00208 template<typename T, Index N> 00209 const Tensor4<T, N> 00210 identity_3(Index const dimension) 00211 { 00212 if (N != DYNAMIC) assert(dimension == N); 00213 00214 Tensor4<T, N> I(dimension, ZEROS); 00215 ones_in_ijkl(I); 00216 return I; 00217 } 00218 00219 // 00220 // 4th-order tensor transpose 00221 // per Holzapfel 1.157 00222 // 00223 template<typename T, Index N> 00224 Tensor4<T, N> 00225 transpose(Tensor4<T, N> const & A) 00226 { 00227 Index const 00228 dimension = A.get_dimension(); 00229 00230 Tensor4<T, N> 00231 B(dimension); 00232 00233 for (Index i = 0; i < dimension; ++i) { 00234 for (Index j = 0; j < dimension; ++j) { 00235 for (Index k = 0; k < dimension; ++k) { 00236 for (Index l = 0; l < dimension; ++l) { 00237 B(i, j, k, l) = A(k, l, i, j); 00238 } 00239 } 00240 } 00241 } 00242 00243 return B; 00244 } 00245 00246 // 00247 // 4th-order tensor vector dot product 00248 // \param A 4th-order tensor 00249 // \param u vector 00250 // \return 3rd-order tensor \f$ B = A \cdot u := B_{ijk}=A_{ijkp} u_{p} \f$ 00251 // 00252 template<typename S, typename T, Index N> 00253 Tensor3<typename Promote<S, T>::type, N> 00254 dot(Tensor4<T, N> const & A, Vector<S, N> const & u) 00255 { 00256 Index const 00257 dimension= A.get_dimension(); 00258 00259 assert(u.get_dimension() == dimension); 00260 00261 Tensor3<typename Promote<S, T>::type, N> 00262 B(dimension); 00263 00264 for (Index i = 0; i < dimension; ++i) { 00265 for (Index j = 0; j < dimension; ++j) { 00266 for (Index k = 0; k < dimension; ++k) { 00267 00268 typename Promote<S, T>::type 00269 s = 0.0; 00270 00271 for (Index p = 0; p < dimension; ++p) { 00272 s += A(i,j,k,p) * u(p); 00273 } 00274 B(i,j,k) = s; 00275 } 00276 } 00277 } 00278 00279 return B; 00280 } 00281 00282 // 00283 // vector 4th-order tensor dot product 00284 // \param A 4th-order tensor 00285 // \param u vector 00286 // \return 3rd-order tensor \f$ u dot A \f$ as \f$ B_{ijk}=u_{p} A_{pijk} \f$ 00287 // 00288 template<typename S, typename T, Index N> 00289 Tensor3<typename Promote<S, T>::type, N> 00290 dot(Vector<S, N> const & u, Tensor4<T, N> const & A) 00291 { 00292 Index const 00293 dimension = A.get_dimension(); 00294 00295 assert(u.get_dimension() == dimension); 00296 00297 Tensor3<typename Promote<S, T>::type, N> 00298 B(dimension); 00299 00300 for (Index i = 0; i < dimension; ++i) { 00301 for (Index j = 0; j < dimension; ++j) { 00302 for (Index k = 0; k < dimension; ++k) { 00303 00304 typename Promote<S, T>::type 00305 s = 0.0; 00306 00307 for (Index p = 0; p < dimension; ++p) { 00308 s += u(p) * A(p,i,j,k); 00309 } 00310 B(i,j,k) = s; 00311 } 00312 } 00313 } 00314 00315 return B; 00316 } 00317 00318 // 00319 // 4th-order tensor vector dot2 product 00320 // \param A 4th-order tensor 00321 // \param u vector 00322 // \return 3rd-order tensor \f$ B = A \cdot u := B_{ijk} = A_{ijpk} u_{p} \f$ 00323 // 00324 template<typename S, typename T, Index N> 00325 Tensor3<typename Promote<S, T>::type, N> 00326 dot2(Tensor4<T, N> const & A, Vector<S, N> const & u) 00327 { 00328 Index const 00329 dimension = A.get_dimension(); 00330 00331 assert(u.get_dimension() == dimension); 00332 00333 Tensor3<typename Promote<S, T>::type, N> 00334 B(dimension); 00335 00336 for (Index i = 0; i < dimension; ++i) { 00337 for (Index j = 0; j < dimension; ++j) { 00338 for (Index k = 0; k < dimension; ++k) { 00339 00340 typename Promote<S, T>::type 00341 s = 0.0; 00342 00343 for (Index p = 0; p < dimension; ++p) { 00344 s += A(i,j,p,k) * u(p); 00345 } 00346 B(i,j,k) = s; 00347 } 00348 } 00349 } 00350 00351 return B; 00352 } 00353 00354 // 00355 // vector 4th-order tensor dot2 product 00356 // \param A 4th-order tensor 00357 // \param u vector 00358 // \return 3rd-order tensor \f$ u dot2 A \f$ as \f$ B_{ijk}=u_{p} A_{ipjk} \f$ 00359 // 00360 template<typename S, typename T, Index N> 00361 Tensor3<typename Promote<S, T>::type, N> 00362 dot2(Vector<S, N> const & u, Tensor4<T, N> const & A) 00363 { 00364 Index const 00365 dimension = A.get_dimension(); 00366 00367 assert(u.get_dimension() == dimension); 00368 00369 Tensor3<typename Promote<S, T>::type, N> 00370 B(dimension); 00371 00372 for (Index i = 0; i < dimension; ++i) { 00373 for (Index j = 0; j < dimension; ++j) { 00374 for (Index k = 0; k < dimension; ++k) { 00375 00376 typename Promote<S, T>::type 00377 s = 0.0; 00378 00379 for (Index p = 0; p < dimension; ++p) { 00380 s += u(p) * A(i,p,j,k); 00381 } 00382 B(i,j,k) = s; 00383 } 00384 } 00385 } 00386 00387 return B; 00388 } 00389 00390 // 00391 // \return 2nd-order tensor \f$ C = A : B := C_{ij} = A_{ijpq} B_{pq} \f$ 00392 // 00393 template<typename S, typename T, Index N> 00394 Tensor<typename Promote<S, T>::type, N> 00395 dotdot(Tensor4<T, N> const & A, Tensor<S, N> const & B) 00396 { 00397 Index const 00398 dimension = A.get_dimension(); 00399 00400 assert(B.get_dimension() == dimension); 00401 00402 Tensor<typename Promote<S, T>::type, N> 00403 C(dimension); 00404 00405 for (Index i = 0; i < dimension; ++i) { 00406 for (Index j = 0; j < dimension; ++j) { 00407 00408 typename Promote<S, T>::type 00409 s = 0.0; 00410 00411 for (Index p = 0; p < dimension; ++p) { 00412 for (Index q = 0; q < dimension; ++q) { 00413 s += A(i,j,p,q) * B(p,q); 00414 } 00415 } 00416 C(i,j) = s; 00417 } 00418 } 00419 00420 return C; 00421 } 00422 00423 // 00424 // \return 2nd-order tensor \f$ C = B : A := C_{ij} = B_{pq} A_{pqij} \f$ 00425 // 00426 template<typename S, typename T, Index N> 00427 Tensor<typename Promote<S, T>::type, N> 00428 dotdot(Tensor<S, N> const & B, Tensor4<T, N> const & A) 00429 { 00430 Index const 00431 dimension = A.get_dimension(); 00432 00433 assert(B.get_dimension() == dimension); 00434 00435 Tensor<typename Promote<S, T>::type, N> 00436 C(dimension); 00437 00438 for (Index i = 0; i < dimension; ++i) { 00439 for (Index j = 0; j < dimension; ++j) { 00440 00441 typename Promote<S, T>::type 00442 s = 0.0; 00443 00444 for (Index p = 0; p < dimension; ++p) { 00445 for (Index q = 0; q < dimension; ++q) { 00446 s += B(p,q) * A(p,q,i,j); 00447 } 00448 } 00449 C(i,j) = s; 00450 } 00451 } 00452 00453 return C; 00454 } 00455 00456 // 00457 // \return \f$ C = A : B := C_{ijkl} = A_{ijpq} B{pqkl} \f$ 00458 // 00459 template<typename S, typename T, Index N> 00460 Tensor4<typename Promote<S, T>::type, N> 00461 dotdot(Tensor4<S, N> const & A, Tensor4<T, N> const & B) 00462 { 00463 Index const 00464 dimension = A.get_dimension(); 00465 00466 assert(B.get_dimension() == dimension); 00467 00468 Tensor4<typename Promote<S, T>::type, N> 00469 C(dimension); 00470 00471 for (Index i = 0; i < dimension; ++i) { 00472 for (Index j = 0; j < dimension; ++j) { 00473 for (Index k = 0; k < dimension; ++k) { 00474 for (Index l = 0; l < dimension; ++l) { 00475 00476 typename Promote<S, T>::type 00477 s = 0.0; 00478 00479 for (Index p = 0; p < dimension; ++p) { 00480 for (Index q = 0; q < dimension; ++q) { 00481 s += A(i,j,p,q) * B(p,q,k,l); 00482 } 00483 } 00484 C(i,j,k,l) = s; 00485 } 00486 } 00487 } 00488 } 00489 00490 return C; 00491 } 00492 00493 // 00494 // \return \f$ C = A \otimes B := C_{ijkl} = A_{ij} B_{kl} \f$ 00495 // 00496 template<typename S, typename T, Index N> 00497 Tensor4<typename Promote<S, T>::type, N> 00498 tensor(Tensor<S, N> const & A, Tensor<T, N> const & B) 00499 { 00500 Index const 00501 dimension = A.get_dimension(); 00502 00503 assert(B.get_dimension() == dimension); 00504 00505 Tensor4<typename Promote<S, T>::type, N> 00506 C(dimension); 00507 00508 for (Index i = 0; i < dimension; ++i) { 00509 for (Index j = 0; j < dimension; ++j) { 00510 for (Index k = 0; k < dimension; ++k) { 00511 for (Index l = 0; l < dimension; ++l) { 00512 C(i,j,k,l) = A(i,j) * B(k,l); 00513 } 00514 } 00515 } 00516 } 00517 00518 return C; 00519 } 00520 00521 // 00522 // \return \f$ C_{ijkl} = A_{ik} B_{jl} \f$ 00523 // 00524 template<typename S, typename T, Index N> 00525 Tensor4<typename Promote<S, T>::type, N> 00526 tensor2(Tensor<S, N> const & A, Tensor<T, N> const & B) 00527 { 00528 Index const 00529 dimension = A.get_dimension(); 00530 00531 assert(B.get_dimension() == dimension); 00532 00533 Tensor4<typename Promote<S, T>::type, N> 00534 C(dimension); 00535 00536 for (Index i = 0; i < dimension; ++i) { 00537 for (Index j = 0; j < dimension; ++j) { 00538 for (Index k = 0; k < dimension; ++k) { 00539 for (Index l = 0; l < dimension; ++l) { 00540 C(i,j,k,l) = A(i,k) * B(j,l); 00541 } 00542 } 00543 } 00544 } 00545 00546 return C; 00547 } 00548 00549 // 00550 // \return \f$ C_{ijkl} = A_{il} B_{kj} \f$ 00551 // 00552 template<typename S, typename T, Index N> 00553 Tensor4<typename Promote<S, T>::type, N> 00554 tensor3(Tensor<S, N> const & A, Tensor<T, N> const & B) 00555 { 00556 Index const 00557 dimension = A.get_dimension(); 00558 00559 assert(B.get_dimension() == dimension); 00560 00561 Tensor4<typename Promote<S, T>::type, N> 00562 C(dimension); 00563 00564 for (Index i = 0; i < dimension; ++i) { 00565 for (Index j = 0; j < dimension; ++j) { 00566 for (Index k = 0; k < dimension; ++k) { 00567 for (Index l = 0; l < dimension; ++l) { 00568 C(i,j,k,l) = A(i,l) * B(k,j); 00569 } 00570 } 00571 } 00572 } 00573 00574 return C; 00575 } 00576 00577 // 00578 // \return \f$ C = A \cdot B := C_{ijkl} = A_{ijkp} B_{pl} \f$ 00579 // 00580 template<typename S, typename T, Index N> 00581 Tensor4<typename Promote<S, T>::type, N> 00582 dot(Tensor4<T, N> const & A, Tensor<S, N> const & B) 00583 { 00584 Index const 00585 dimension = A.get_dimension(); 00586 00587 assert(B.get_dimension() == dimension); 00588 00589 Tensor4<typename Promote<S, T>::type, N> 00590 C(dimension); 00591 00592 for (Index i = 0; i < dimension; ++i) { 00593 for (Index j = 0; j < dimension; ++j) { 00594 for (Index k = 0; k < dimension; ++k) { 00595 for (Index l = 0; l < dimension; ++l) { 00596 00597 typename Promote<S, T>::type 00598 s = 0.0; 00599 00600 for (Index p = 0; p < dimension; ++p) { 00601 s += A(i,j,k,p) * B(p,l); 00602 } 00603 C(i,j,k,l) = s; 00604 } 00605 } 00606 } 00607 } 00608 00609 return C; 00610 } 00611 00612 // 00613 // \return \f$ C = A \cdot B^T := C_{ijkl} = A_{ijkp} B_{lp} \f$ 00614 // 00615 template<typename S, typename T, Index N> 00616 Tensor4<typename Promote<S, T>::type, N> 00617 dot_t(Tensor4<T, N> const & A, Tensor<S, N> const & B) 00618 { 00619 Index const 00620 dimension = A.get_dimension(); 00621 00622 assert(B.get_dimension() == dimension); 00623 00624 Tensor4<typename Promote<S, T>::type, N> 00625 C(dimension); 00626 00627 for (Index i = 0; i < dimension; ++i) { 00628 for (Index j = 0; j < dimension; ++j) { 00629 for (Index k = 0; k < dimension; ++k) { 00630 for (Index l = 0; l < dimension; ++l) { 00631 00632 typename Promote<S, T>::type 00633 s = 0.0; 00634 00635 for (Index p = 0; p < dimension; ++p) { 00636 s += A(i,j,k,p) * B(l,p); 00637 } 00638 C(i,j,k,l) = s; 00639 } 00640 } 00641 } 00642 } 00643 00644 return C; 00645 } 00646 00647 // 00648 // \return \f$ C = A \cdot B := C_{ijkl} = A_{ip} B_{pjkl} \f$ 00649 // 00650 template<typename S, typename T, Index N> 00651 Tensor4<typename Promote<S, T>::type, N> 00652 dot(Tensor<S, N> const & A, Tensor4<T, N> const & B) 00653 { 00654 Index const 00655 dimension = A.get_dimension(); 00656 00657 assert(B.get_dimension() == dimension); 00658 00659 Tensor4<typename Promote<S, T>::type, N> 00660 C(dimension); 00661 00662 for (Index i = 0; i < dimension; ++i) { 00663 for (Index j = 0; j < dimension; ++j) { 00664 for (Index k = 0; k < dimension; ++k) { 00665 for (Index l = 0; l < dimension; ++l) { 00666 00667 typename Promote<S, T>::type 00668 s = 0.0; 00669 00670 for (Index p = 0; p < dimension; ++p) { 00671 s += A(i,p) * B(p,j,k,l); 00672 } 00673 C(i,j,k,l) = s; 00674 } 00675 } 00676 } 00677 } 00678 00679 return C; 00680 } 00681 00682 // 00683 // \return \f$ C = A^T \cdot B := C_{ijkl} = A_{pi} B_{pjkl} \f$ 00684 // 00685 template<typename S, typename T, Index N> 00686 Tensor4<typename Promote<S, T>::type, N> 00687 t_dot(Tensor<S, N> const & A, Tensor4<T, N> const & B) 00688 { 00689 Index const 00690 dimension = A.get_dimension(); 00691 00692 assert(B.get_dimension() == dimension); 00693 00694 Tensor4<typename Promote<S, T>::type, N> 00695 C(dimension); 00696 00697 for (Index i = 0; i < dimension; ++i) { 00698 for (Index j = 0; j < dimension; ++j) { 00699 for (Index k = 0; k < dimension; ++k) { 00700 for (Index l = 0; l < dimension; ++l) { 00701 00702 typename Promote<S, T>::type 00703 s = 0.0; 00704 00705 for (Index p = 0; p < dimension; ++p) { 00706 s += A(p,i) * B(p,j,k,l); 00707 } 00708 C(i,j,k,l) = s; 00709 } 00710 } 00711 } 00712 } 00713 00714 return C; 00715 } 00716 00717 // 00718 // \return \f$ C = A \cdot B := C_{ijkl} = A_{ijpl} B_{pk} \f$ 00719 // 00720 template<typename S, typename T, Index N> 00721 Tensor4<typename Promote<S, T>::type, N> 00722 dot2(Tensor4<T, N> const & A, Tensor<S, N> const & B) 00723 { 00724 Index const 00725 dimension = A.get_dimension(); 00726 00727 assert(B.get_dimension() == dimension); 00728 00729 Tensor4<typename Promote<S, T>::type, N> 00730 C(dimension); 00731 00732 for (Index i = 0; i < dimension; ++i) { 00733 for (Index j = 0; j < dimension; ++j) { 00734 for (Index k = 0; k < dimension; ++k) { 00735 for (Index l = 0; l < dimension; ++l) { 00736 00737 typename Promote<S, T>::type 00738 s = 0.0; 00739 00740 for (Index p = 0; p < dimension; ++p) { 00741 s += A(i,j,p,l) * B(p,k); 00742 } 00743 C(i,j,k,l) = s; 00744 } 00745 } 00746 } 00747 } 00748 00749 return C; 00750 } 00751 00752 // 00753 // \return \f$ C = A \cdot B^T := C_{ijkl} = A_{ijpl} B_{kp} \f$ 00754 // 00755 template<typename S, typename T, Index N> 00756 Tensor4<typename Promote<S, T>::type, N> 00757 dot2_t(Tensor4<T, N> const & A, Tensor<S, N> const & B) 00758 { 00759 Index const 00760 dimension = A.get_dimension(); 00761 00762 assert(B.get_dimension() == dimension); 00763 00764 Tensor4<typename Promote<S, T>::type, N> 00765 C(dimension); 00766 00767 for (Index i = 0; i < dimension; ++i) { 00768 for (Index j = 0; j < dimension; ++j) { 00769 for (Index k = 0; k < dimension; ++k) { 00770 for (Index l = 0; l < dimension; ++l) { 00771 00772 typename Promote<S, T>::type 00773 s = 0.0; 00774 00775 for (Index p = 0; p < dimension; ++p) { 00776 s += A(i,j,p,l) * B(k,p); 00777 } 00778 C(i,j,k,l) = s; 00779 } 00780 } 00781 } 00782 } 00783 00784 return C; 00785 } 00786 00787 // 00788 // \return \f$ C = A \cdot B := C_{ijkl} = A_{jp} B_{ipkl} \f$ 00789 // 00790 template<typename S, typename T, Index N> 00791 Tensor4<typename Promote<S, T>::type, N> 00792 dot2(Tensor<S, N> const & A, Tensor4<T, N> const & B) 00793 { 00794 Index const 00795 dimension = A.get_dimension(); 00796 00797 assert(B.get_dimension() == dimension); 00798 00799 Tensor4<typename Promote<S, T>::type, N> 00800 C(dimension); 00801 00802 for (Index i = 0; i < dimension; ++i) { 00803 for (Index j = 0; j < dimension; ++j) { 00804 for (Index k = 0; k < dimension; ++k) { 00805 for (Index l = 0; l < dimension; ++l) { 00806 00807 typename Promote<S, T>::type 00808 s = 0.0; 00809 00810 for (Index p = 0; p < dimension; ++p) { 00811 s += A(j,p) * B(i,p,k,l); 00812 } 00813 C(i,j,k,l) = s; 00814 } 00815 } 00816 } 00817 } 00818 00819 return C; 00820 } 00821 00822 // 00823 // \return \f$ C = A^T \cdot B := C_{ijkl} = A_{pj} B_{ipkl} \f$ 00824 // 00825 template<typename S, typename T, Index N> 00826 Tensor4<typename Promote<S, T>::type, N> 00827 t_dot2(Tensor<S, N> const & A, Tensor4<T, N> const & B) 00828 { 00829 Index const 00830 dimension = A.get_dimension(); 00831 00832 assert(B.get_dimension() == dimension); 00833 00834 Tensor4<typename Promote<S, T>::type, N> 00835 C(dimension); 00836 00837 for (Index i = 0; i < dimension; ++i) { 00838 for (Index j = 0; j < dimension; ++j) { 00839 for (Index k = 0; k < dimension; ++k) { 00840 for (Index l = 0; l < dimension; ++l) { 00841 00842 typename Promote<S, T>::type 00843 s = 0.0; 00844 00845 for (Index p = 0; p < dimension; ++p) { 00846 s += A(p,j) * B(i,p,k,l); 00847 } 00848 C(i,j,k,l) = s; 00849 } 00850 } 00851 } 00852 } 00853 00854 return C; 00855 } 00856 00857 // 00858 // odot operator useful for \f$ \frac{\partial A^{-1}}{\partial A} \f$ 00859 // see Holzapfel eqn 6.165 00860 // \param A 2nd-order tensor 00861 // \param B 2nd-order tensor 00862 // \return \f$ A \odot B \f$ which is 00863 // \f$ C_{ijkl} = \frac{1}{2}(A_{ik} B_{jl} + A_{il} B_{jk}) \f$ 00864 // 00865 template<typename S, typename T, Index N> 00866 Tensor4<typename Promote<S, T>::type, N> 00867 odot(Tensor<S, N> const & A, Tensor<T, N> const & B) 00868 { 00869 Index const 00870 dimension = A.get_dimension(); 00871 00872 assert(B.get_dimension() == dimension); 00873 00874 Tensor4<typename Promote<S, T>::type, N> 00875 C(dimension); 00876 00877 for (Index i = 0; i < dimension; ++i) { 00878 for (Index j = 0; j < dimension; ++j) { 00879 for (Index k = 0; k < dimension; ++k) { 00880 for (Index l = 0; l < dimension; ++l) { 00881 C(i,j,k,l) = 0.5 * (A(i,k) * B(j,l) + A(i,l) * B(j,k)); 00882 } 00883 } 00884 } 00885 } 00886 00887 return C; 00888 } 00889 00890 // 00891 // \return \f$ C'_{i'j'k'l'} = Q_{i'i} Q_{j'j} Q_{k'k} Q_{l'l} C_{ijkl} \f$ 00892 // 00893 template<typename S, typename T, Index N> 00894 Tensor4<typename Promote<S, T>::type, N> 00895 kronecker(Tensor<S, N> const & A, Tensor4<T, N> const & B) 00896 { 00897 Index const 00898 dimension = A.get_dimension(); 00899 00900 assert(B.get_dimension() == dimension); 00901 00902 Tensor4<typename Promote<S, T>::type, N> 00903 C(dimension); 00904 00905 for (Index i = 0; i < dimension; ++i) { 00906 for (Index j = 0; j < dimension; ++j) { 00907 for (Index k = 0; k < dimension; ++k) { 00908 for (Index l = 0; l < dimension; ++l) { 00909 00910 typename Promote<S, T>::type 00911 s = 0.0; 00912 00913 for (Index p = 0; p < dimension; ++p) { 00914 for (Index q = 0; q < dimension; ++q) { 00915 for (Index m = 0; m < dimension; ++m) { 00916 for (Index n = 0; n < dimension; ++n) { 00917 s += A(i,p) * A(j,q) * A(k,m) * A(l,n) * B(p,q,m,n); 00918 } 00919 } 00920 } 00921 } 00922 C(i,j,k,l) = s; 00923 } 00924 } 00925 } 00926 } 00927 00928 return C; 00929 } 00930 00931 // 00932 // 4th-order input 00933 // \param A 4th-order tensor 00934 // \param is input stream 00935 // \return is input stream 00936 // 00937 template<typename T, Index N> 00938 std::istream & 00939 operator>>(std::istream & is, Tensor4<T, N> & A) 00940 { 00941 Index const 00942 dimension = A.get_dimension(); 00943 00944 for (Index i = 0; i < dimension; ++i) { 00945 for (Index j = 0; j < dimension; ++j) { 00946 for (Index k = 0; k < dimension; ++k) { 00947 for (Index l = 0; l < dimension; ++l) { 00948 is >> A(i,j,k,l); 00949 } 00950 } 00951 } 00952 } 00953 00954 return is; 00955 } 00956 00957 // 00958 // 4th-order output 00959 // \param A 4th-order tensor 00960 // \param os output stream 00961 // \return os output stream 00962 // 00963 template<typename T, Index N> 00964 std::ostream & 00965 operator<<(std::ostream & os, Tensor4<T, N> const & A) 00966 { 00967 Index const 00968 dimension = A.get_dimension(); 00969 00970 if (dimension == 0) { 00971 return os; 00972 } 00973 00974 for (Index i = 0; i < dimension; ++i) { 00975 00976 for (Index j = 0; j < dimension; ++j) { 00977 00978 for (Index k = 0; k < dimension; ++k) { 00979 00980 os << std::scientific << std::setprecision(16) << A(i,j,k,0); 00981 00982 for (Index l = 1; l < dimension; ++l) { 00983 00984 os << "," << std::scientific << std::setprecision(16) << A(i,j,k,l); 00985 } 00986 00987 os << std::endl; 00988 00989 } 00990 00991 os << std::endl; 00992 os << std::endl; 00993 00994 } 00995 00996 os << std::endl; 00997 00998 } 00999 01000 return os; 01001 } 01002 01003 } // namespace Intrepid 01004 01005 #endif // Intrepid_MiniTensor_Tensor4_t_h
1.7.6.1