Intrepid
/usr/src/RPM/BUILD/trilinos-11.12.1/packages/intrepid/src/Shared/MiniTensor/Intrepid_MiniTensor_Tensor4.t.h
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