Intrepid
/usr/src/RPM/BUILD/trilinos-11.12.1/packages/intrepid/src/Shared/MiniTensor/Intrepid_MiniTensor_Mechanics.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_Mechanics_t_h)
00043 #define Intrepid_MiniTensor_Mechanics_t_h
00044 
00045 namespace Intrepid {
00046 
00047 //
00048 // Push forward covariant vector
00049 // \param \f$ F, u \f$
00050 // \return \f$ F^{-T} u \f$
00051 //
00052 template<typename T, Index N>
00053 Vector<T, N>
00054 push_forward_covariant(Tensor<T, N> const & F, Vector<T, N> const & u)
00055 {
00056   Index const
00057   dimension = F.get_dimension();
00058 
00059   Vector<T, N>
00060   v(dimension);
00061 
00062   T const
00063   J = det(F);
00064 
00065   assert(J > 0.0);
00066 
00067   switch (dimension) {
00068 
00069     default:
00070       std::cerr << "ERROR: " << __PRETTY_FUNCTION__;
00071       std::cerr << std::endl;
00072       std::cerr << "Supports only 2D and 3D. Found dimension: " << N;
00073       std::cerr << std::endl;
00074       exit(1);
00075       break;
00076 
00077     case 3:
00078       v(0) = (
00079           (-F(1,2)*F(2,1) + F(1,1)*F(2,2)) * u(0) +
00080           ( F(1,2)*F(2,0) - F(1,0)*F(2,2)) * u(1) +
00081           (-F(1,1)*F(2,0) + F(1,0)*F(2,1)) * u(2)) / J;
00082 
00083       v(1) = (
00084           ( F(0,2)*F(2,1) - F(0,1)*F(2,2)) * u(0) +
00085           (-F(0,2)*F(2,0) + F(0,0)*F(2,2)) * u(1) +
00086           ( F(0,1)*F(2,0) - F(0,0)*F(2,1)) * u(2)) / J;
00087 
00088       v(2) = (
00089           (-F(0,2)*F(1,1) + F(0,1)*F(1,2)) * u(0) +
00090           ( F(0,2)*F(1,0) - F(0,0)*F(1,2)) * u(1) +
00091           (-F(0,1)*F(1,0) + F(0,0)*F(1,1)) * u(2)) / J;
00092 
00093       break;
00094 
00095     case 2:
00096       v(0) = ( F(1,1) * u(0) - F(1,0) * u(1)) / J;
00097       v(1) = (-F(0,1) * u(0) + F(0,0) * u(1)) / J;
00098       break;
00099 
00100   }
00101 
00102   return v;
00103 }
00104 
00105 //
00106 // Pull back covariant vector
00107 // \param \f$ F, v \f$
00108 // \return \f$ F^T v \f$
00109 //
00110 template<typename T, Index N>
00111 Vector<T, N>
00112 pull_back_covariant(Tensor<T, N> const & F, Vector<T, N> const & u)
00113 {
00114   Index const
00115   dimension = F.get_dimension();
00116 
00117   Vector<T, N>
00118   v(dimension);
00119 
00120   switch (dimension) {
00121 
00122     default:
00123       std::cerr << "ERROR: " << __PRETTY_FUNCTION__;
00124       std::cerr << std::endl;
00125       std::cerr << "Supports only 2D and 3D. Found dimension: " << N;
00126       std::cerr << std::endl;
00127       exit(1);
00128       break;
00129 
00130     case 3:
00131       v(0) = F(0,0) * u(0) + F(1,0) * u(1) + F(2,0) * u(2);
00132       v(1) = F(0,1) * u(0) + F(1,1) * u(1) + F(2,1) * u(2);
00133       v(2) = F(0,2) * u(0) + F(1,2) * u(1) + F(2,2) * u(2);
00134 
00135       break;
00136 
00137     case 2:
00138       v(0) = F(0,0) * u(0) + F(1,0) * u(1);
00139       v(1) = F(0,1) * u(0) + F(1,1) * u(1);
00140 
00141       break;
00142 
00143   }
00144 
00145   return v;
00146 }
00147 
00148 //
00149 // Push forward contravariant vector
00150 // \param \f$ F, u \f$
00151 // \return \f$ F u \f$
00152 //
00153 template<typename T, Index N>
00154 Vector<T, N>
00155 push_forward_contravariant(Tensor<T, N> const & F, Vector<T, N> const & u)
00156 {
00157   Index const
00158   dimension = F.get_dimension();
00159 
00160   Vector<T, N>
00161   v(dimension);
00162 
00163   switch (dimension) {
00164 
00165     default:
00166       std::cerr << "ERROR: " << __PRETTY_FUNCTION__;
00167       std::cerr << std::endl;
00168       std::cerr << "Supports only 2D and 3D. Found dimension: " << N;
00169       std::cerr << std::endl;
00170       exit(1);
00171       break;
00172 
00173     case 3:
00174       v(0) = F(0,0) * u(0) + F(0,1) * u(1) + F(0,2) * u(2);
00175       v(1) = F(1,0) * u(0) + F(1,1) * u(1) + F(1,2) * u(2);
00176       v(2) = F(2,0) * u(0) + F(2,1) * u(1) + F(2,2) * u(2);
00177 
00178       break;
00179 
00180     case 2:
00181       v(0) = F(0,0) * u(0) + F(0,1) * u(1);
00182       v(1) = F(1,0) * u(0) + F(1,1) * u(1);
00183 
00184       break;
00185 
00186   }
00187 
00188   return v;
00189 }
00190 
00191 //
00192 // Pull back contravariant vector
00193 // \param \f$ F, u \f$
00194 // \return \f$ F^{-1} u \f$
00195 //
00196 template<typename T, Index N>
00197 Vector<T, N>
00198 pull_back_contravariant(Tensor<T, N> const & F, Vector<T, N> const & u)
00199 {
00200   Index const
00201   dimension = F.get_dimension();
00202 
00203   Vector<T, N>
00204   v(dimension);
00205 
00206   T const
00207   J = det(F);
00208 
00209   assert(J > 0.0);
00210 
00211   switch (dimension) {
00212 
00213     default:
00214       std::cerr << "ERROR: " << __PRETTY_FUNCTION__;
00215       std::cerr << std::endl;
00216       std::cerr << "Supports only 2D and 3D. Found dimension: " << N;
00217       std::cerr << std::endl;
00218       exit(1);
00219       break;
00220 
00221     case 3:
00222       v(0) = (
00223           (-F(1,2)*F(2,1) + F(1,1)*F(2,2)) * u(0) +
00224           ( F(0,2)*F(2,1) - F(0,1)*F(2,2)) * u(1) +
00225           (-F(0,2)*F(1,1) + F(0,1)*F(1,2)) * u(2)) / J;
00226 
00227       v(1) = (
00228           ( F(1,2)*F(2,0) - F(1,0)*F(2,2)) * u(0) +
00229           (-F(0,2)*F(2,0) + F(0,0)*F(2,2)) * u(1) +
00230           ( F(0,2)*F(1,0) - F(0,0)*F(1,2)) * u(2)) / J;
00231 
00232       v(2) = (
00233           (-F(1,1)*F(2,0) + F(1,0)*F(2,1)) * u(0) +
00234           ( F(0,1)*F(2,0) - F(0,0)*F(2,1)) * u(1) +
00235           (-F(0,1)*F(1,0) + F(0,0)*F(1,1)) * u(2)) / J;
00236 
00237       break;
00238 
00239     case 2:
00240       v(0) = ( F(1,1) * u(0) - F(0,1) * u(1)) / J;
00241       v(1) = (-F(1,0) * u(0) + F(0,0) * u(1)) / J;
00242       break;
00243 
00244   }
00245 
00246   return v;
00247 }
00248 
00249 //
00250 // Push forward covariant tensor
00251 // \param \f$ F, A \f$
00252 // \return \f$ F^{-T} A F^{-1} \f$
00253 //
00254 template<typename T, Index N>
00255 Tensor<T, N>
00256 push_forward_covariant(Tensor<T, N> const & F, Tensor<T, N> const & A)
00257 {
00258   Index const
00259   dimension = F.get_dimension();
00260 
00261   Tensor<T, N>
00262   G(dimension);
00263 
00264   T const
00265   J = det(F);
00266 
00267   assert(J > 0.0);
00268 
00269   switch (dimension) {
00270 
00271     default:
00272       std::cerr << "ERROR: " << __PRETTY_FUNCTION__;
00273       std::cerr << std::endl;
00274       std::cerr << "Supports only 2D and 3D. Found dimension: " << N;
00275       std::cerr << std::endl;
00276       exit(1);
00277       break;
00278 
00279     case 3:
00280       G(0,0) = (-F(1,2)*F(2,1) + F(1,1)*F(2,2)) / J;
00281       G(0,1) = ( F(0,2)*F(2,1) - F(0,1)*F(2,2)) / J;
00282       G(0,2) = (-F(0,2)*F(1,1) + F(0,1)*F(1,2)) / J;
00283 
00284       G(1,0) = ( F(1,2)*F(2,0) - F(1,0)*F(2,2)) / J;
00285       G(1,1) = (-F(0,2)*F(2,0) + F(0,0)*F(2,2)) / J;
00286       G(1,2) = ( F(0,2)*F(1,0) - F(0,0)*F(1,2)) / J;
00287 
00288       G(2,0) = (-F(1,1)*F(2,0) + F(1,0)*F(2,1)) / J;
00289       G(2,1) = ( F(0,1)*F(2,0) - F(0,0)*F(2,1)) / J;
00290       G(2,2) = (-F(0,1)*F(1,0) + F(0,0)*F(1,1)) / J;
00291       break;
00292 
00293     case 2:
00294       G(0,0) =  F(1,1) / J;
00295       G(0,1) = -F(0,1) / J;
00296 
00297       G(1,0) = -F(1,0) / J;
00298       G(1,1) =  F(0,0) / J;
00299       break;
00300 
00301   }
00302 
00303   return t_dot(G, dot(A, G));
00304 }
00305 
00306 //
00307 // Pull back covariant tensor
00308 // \param \f$ F, A \f$
00309 // \return \f$ F^T A F\f$
00310 //
00311 template<typename T, Index N>
00312 Tensor<T, N>
00313 pull_back_covariant(Tensor<T, N> const & F, Tensor<T, N> const & A)
00314 {
00315   return t_dot(F, dot(A, F));
00316 }
00317 
00318 //
00319 // Push forward contravariant tensor
00320 // \param \f$ F, A \f$
00321 // \return \f$ F A F^T \f$
00322 //
00323 template<typename T, Index N>
00324 Tensor<T, N>
00325 push_forward_contravariant(Tensor<T, N> const & F, Tensor<T, N> const & A)
00326 {
00327   return dot_t(dot(F, A), F);
00328 }
00329 
00330 //
00331 // Pull back contravariant tensor
00332 // \param \f$ F, A \f$
00333 // \return \f$ F^{-1} A F^{-T} \f$
00334 //
00335 template<typename T, Index N>
00336 Tensor<T, N>
00337 pull_back_contravariant(Tensor<T, N> const & F, Tensor<T, N> const & A)
00338 {
00339   Index const
00340   dimension = F.get_dimension();
00341 
00342   Tensor<T, N>
00343   G(dimension);
00344 
00345   T const
00346   J = det(F);
00347 
00348   assert(J > 0.0);
00349 
00350   switch (dimension) {
00351 
00352     default:
00353       std::cerr << "ERROR: " << __PRETTY_FUNCTION__;
00354       std::cerr << std::endl;
00355       std::cerr << "Supports only 2D and 3D. Found dimension: " << N;
00356       std::cerr << std::endl;
00357       exit(1);
00358       break;
00359 
00360     case 3:
00361       G(0,0) = (-F(1,2)*F(2,1) + F(1,1)*F(2,2)) / J;
00362       G(0,1) = ( F(0,2)*F(2,1) - F(0,1)*F(2,2)) / J;
00363       G(0,2) = (-F(0,2)*F(1,1) + F(0,1)*F(1,2)) / J;
00364 
00365       G(1,0) = ( F(1,2)*F(2,0) - F(1,0)*F(2,2)) / J;
00366       G(1,1) = (-F(0,2)*F(2,0) + F(0,0)*F(2,2)) / J;
00367       G(1,2) = ( F(0,2)*F(1,0) - F(0,0)*F(1,2)) / J;
00368 
00369       G(2,0) = (-F(1,1)*F(2,0) + F(1,0)*F(2,1)) / J;
00370       G(2,1) = ( F(0,1)*F(2,0) - F(0,0)*F(2,1)) / J;
00371       G(2,2) = (-F(0,1)*F(1,0) + F(0,0)*F(1,1)) / J;
00372       break;
00373 
00374     case 2:
00375       G(0,0) =  F(1,1) / J;
00376       G(0,1) = -F(0,1) / J;
00377 
00378       G(1,0) = -F(1,0) / J;
00379       G(1,1) =  F(0,0) / J;
00380       break;
00381 
00382   }
00383 
00384   return dot_t(dot(G, A), G);
00385 }
00386 
00387 //
00388 // Piola transformation for vector
00389 // \param \f$ F, u \f$
00390 // \return \f$ \det F F^{-1} u \f$
00391 //
00392 template<typename T, Index N>
00393 Vector<T, N>
00394 piola(Tensor<T, N> const & F, Vector<T, N> const & u)
00395 {
00396   Index const
00397   dimension = F.get_dimension();
00398 
00399   Vector<T, N>
00400   v(dimension);
00401 
00402   switch (dimension) {
00403 
00404     default:
00405       std::cerr << "ERROR: " << __PRETTY_FUNCTION__;
00406       std::cerr << std::endl;
00407       std::cerr << "Supports only 2D and 3D. Found dimension: " << N;
00408       std::cerr << std::endl;
00409       exit(1);
00410       break;
00411 
00412     case 3:
00413       v(0) = (
00414           (-F(1,2)*F(2,1) + F(1,1)*F(2,2)) * u(0) +
00415           ( F(0,2)*F(2,1) - F(0,1)*F(2,2)) * u(1) +
00416           (-F(0,2)*F(1,1) + F(0,1)*F(1,2)) * u(2));
00417 
00418       v(1) = (
00419           ( F(1,2)*F(2,0) - F(1,0)*F(2,2)) * u(0) +
00420           (-F(0,2)*F(2,0) + F(0,0)*F(2,2)) * u(1) +
00421           ( F(0,2)*F(1,0) - F(0,0)*F(1,2)) * u(2));
00422 
00423       v(2) = (
00424           (-F(1,1)*F(2,0) + F(1,0)*F(2,1)) * u(0) +
00425           ( F(0,1)*F(2,0) - F(0,0)*F(2,1)) * u(1) +
00426           (-F(0,1)*F(1,0) + F(0,0)*F(1,1)) * u(2));
00427 
00428       break;
00429 
00430     case 2:
00431       v(0) = ( F(1,1) * u(0) - F(0,1) * u(1));
00432       v(1) = (-F(1,0) * u(0) + F(0,0) * u(1));
00433       break;
00434 
00435   }
00436 
00437   return v;
00438 }
00439 
00440 //
00441 // Inverse Piola transformation for vector
00442 // \param \f$ F, u \f$
00443 // \return \f$ (\det F)^{-1} F u \f$
00444 //
00445 template<typename T, Index N>
00446 Vector<T, N>
00447 piola_inverse(Tensor<T, N> const & F, Vector<T, N> const & u)
00448 {
00449   Index const
00450   dimension = F.get_dimension();
00451 
00452   Vector<T, N>
00453   v(dimension);
00454 
00455   T const
00456   J = det(F);
00457 
00458   assert(J > 0.0);
00459 
00460   switch (dimension) {
00461 
00462     default:
00463       std::cerr << "ERROR: " << __PRETTY_FUNCTION__;
00464       std::cerr << std::endl;
00465       std::cerr << "Supports only 2D and 3D. Found dimension: " << N;
00466       std::cerr << std::endl;
00467       exit(1);
00468       break;
00469 
00470     case 3:
00471       v(0) = (F(0,0) * u(0) + F(0,1) * u(1) + F(0,2) * u(2)) / J;
00472       v(1) = (F(1,0) * u(0) + F(1,1) * u(1) + F(1,2) * u(2)) / J;
00473       v(2) = (F(2,0) * u(0) + F(2,1) * u(1) + F(2,2) * u(2)) / J;
00474 
00475       break;
00476 
00477     case 2:
00478       v(0) = (F(0,0) * u(0) + F(0,1) * u(1)) / J;
00479       v(1) = (F(1,0) * u(0) + F(1,1) * u(1)) / J;
00480 
00481       break;
00482 
00483   }
00484 
00485   return v;
00486 }
00487 
00488 //
00489 // Piola transformation for tensor, applied on second
00490 // index. Useful for transforming Cauchy stress to 1PK stress.
00491 // \param \f$ F, \sigma \f$
00492 // \return \f$ \det F \sigma F^{-T} \f$
00493 //
00494 template<typename T, Index N>
00495 Tensor<T, N>
00496 piola(Tensor<T, N> const & F, Tensor<T, N> const & sigma)
00497 {
00498   Index const
00499   dimension = F.get_dimension();
00500 
00501   Tensor<T, N>
00502   G(dimension);
00503 
00504   switch (dimension) {
00505 
00506     default:
00507       std::cerr << "ERROR: " << __PRETTY_FUNCTION__;
00508       std::cerr << std::endl;
00509       std::cerr << "Supports only 2D and 3D. Found dimension: " << N;
00510       std::cerr << std::endl;
00511       exit(1);
00512       break;
00513 
00514     case 3:
00515       G(0,0) = (-F(1,2)*F(2,1) + F(1,1)*F(2,2));
00516       G(0,1) = ( F(0,2)*F(2,1) - F(0,1)*F(2,2));
00517       G(0,2) = (-F(0,2)*F(1,1) + F(0,1)*F(1,2));
00518 
00519       G(1,0) = ( F(1,2)*F(2,0) - F(1,0)*F(2,2));
00520       G(1,1) = (-F(0,2)*F(2,0) + F(0,0)*F(2,2));
00521       G(1,2) = ( F(0,2)*F(1,0) - F(0,0)*F(1,2));
00522 
00523       G(2,0) = (-F(1,1)*F(2,0) + F(1,0)*F(2,1));
00524       G(2,1) = ( F(0,1)*F(2,0) - F(0,0)*F(2,1));
00525       G(2,2) = (-F(0,1)*F(1,0) + F(0,0)*F(1,1));
00526       break;
00527 
00528     case 2:
00529       G(0,0) =  F(1,1);
00530       G(0,1) = -F(0,1);
00531 
00532       G(1,0) = -F(1,0);
00533       G(1,1) =  F(0,0);
00534       break;
00535 
00536   }
00537 
00538   return dot_t(sigma, G);
00539 }
00540 
00541 //
00542 // Inverse Piola transformation for tensor, applied on second
00543 // index. Useful for transforming 1PK stress to Cauchy stress.
00544 // \param \f$ F, P \f$
00545 // \return \f$ (\det F)^{-1} P F^T \f$
00546 //
00547 template<typename T, Index N>
00548 Tensor<T, N>
00549 piola_inverse(Tensor<T, N> const & F, Tensor<T, N> const & P)
00550 {
00551   T const
00552   J = det(F);
00553 
00554   assert(J > 0.0);
00555 
00556   return dot_t(P, F) / J;
00557 }
00558 
00559 //
00560 // Smallest eigenvalue by inverse iteration.
00561 //
00562 template<typename T, Index N>
00563 T
00564 smallest_eigenvalue(Tensor<T, N> const & A)
00565 {
00566   Tensor<T, N>
00567   B = inverse(A);
00568 
00569   T const
00570   tolerance = machine_epsilon<T>();
00571 
00572   Index const
00573   dimension = A.get_dimension();
00574 
00575   Vector<T, N>
00576   v(dimension, ONES);
00577 
00578   Index const
00579   maximum_iterations = 128;
00580 
00581   T
00582   relative_error = 1.0;
00583 
00584   Index
00585   k = 0;
00586 
00587   while (relative_error > tolerance && k < maximum_iterations) {
00588 
00589     Vector<T, N> const
00590     w = v;
00591 
00592     v = unit(B * w);
00593 
00594     relative_error = norm(v - w) / norm(w);
00595 
00596     ++k;
00597   }
00598 
00599   return v * A * v;
00600 }
00601 
00602 //
00603 // Check strict ellipticity condition for 4th-order tensor.
00604 // Assume A has major symmetries.
00605 //
00606 template<typename T, Index N>
00607 bool
00608 check_strict_ellipticity(Tensor4<T, N> const & A)
00609 {
00610   // Convert to 2nd-order tensor
00611   Tensor<T, dimension_square<N>::value> const
00612   B(A);
00613 
00614   // Check bounds for eigenvalues
00615   T const
00616   lower_bound = bounds_eigenvalues(B).first;
00617 
00618   if (lower_bound > 0.0) {
00619     return true;
00620   }
00621 
00622   // Get eigenvalue closest to zero only
00623   T const
00624   smallest_eigenvalue = smallest_eigenvavlue(B);
00625 
00626   if (smallest_eigenvalue > 0.0) {
00627     return true;
00628   }
00629 
00630   return false;
00631 }
00632 
00633 //
00634 // Check strong ellipticity condition for 4th-order tensor.
00635 // Assume A has major and minor symmetries.
00636 //
00637 template<typename T, Index N>
00638 std::pair<bool, Vector<T, N> >
00639 check_strong_ellipticity(Tensor4<T, N> const & A)
00640 {
00641   bool
00642   is_elliptic = true;
00643 
00644   Index const
00645   dimension = A.get_dimension();
00646 
00647   Vector<T, N>
00648   eigenvector(dimension, 1.0 / dimension);
00649 
00650   Index const
00651   maximum_iterarions = 128;
00652 
00653   T const
00654   tolerance = machine_epsilon<T>();
00655 
00656   T
00657   error = 1.0;
00658 
00659   T
00660   prev_eigenvalue =
00661       std::numeric_limits<typename Sacado::ScalarType<T>::type>::max();
00662 
00663   T
00664   curr_eigenvalue = prev_eigenvalue;
00665 
00666   Index
00667   iteration = 0;
00668 
00669   while (error > tolerance && iteration < maximum_iterarions) {
00670 
00671     Tensor<T, N>
00672     Q = dot(eigenvector, dot(A, eigenvector));
00673 
00674     Tensor<T, N>
00675     V;
00676 
00677     Tensor<T, N>
00678     D;
00679 
00680     boost::tie(V, D) = eig_sym(Q);
00681 
00682     curr_eigenvalue = D(dimension - 1, dimension - 1);
00683 
00684     eigenvector = col(V, dimension - 1);
00685 
00686     error = std::abs(prev_eigenvalue) / std::abs(curr_eigenvalue) - 1.0;
00687 
00688     prev_eigenvalue = curr_eigenvalue;
00689 
00690     ++iteration;
00691   }
00692 
00693   if (curr_eigenvalue <= 0.0) {
00694     is_elliptic = false;
00695   }
00696 
00697   return std::make_pair(is_elliptic, eigenvector);
00698 }
00699 
00700 } // namespace Intrepid
00701 
00702 #endif // Intrepid_MiniTensor_Mechanics_t_h
00703 
00704 
00705 
00706