Intrepid
/usr/src/RPM/BUILD/trilinos10-10.6.4/packages/intrepid/src/Shared/Intrepid_FieldContainerDef.hpp
Go to the documentation of this file.
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 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Pavel Bochev (pbboche@sandia.gov) or
00025 //                    Denis Ridzal (dridzal@sandia.gov).
00026 //
00027 // ************************************************************************
00028 // @HEADER
00029 
00035 namespace Intrepid {
00036 
00037   
00038   //--------------------------------------------------------------------------------------------//
00039   //                                                                                            //
00040   //                 Member function definitions of the class FieldContainer                    //
00041   //                                                                                            //
00042   //--------------------------------------------------------------------------------------------//
00043   
00044 
00045 template<class Scalar, int ArrayTypeId>
00046 FieldContainer<Scalar, ArrayTypeId>::FieldContainer(const FieldContainer<Scalar, ArrayTypeId>& right) {
00047   
00048   // Copy dimensions and data values from right
00049   dimensions_.assign(right.dimensions_.begin(),right.dimensions_.end());  
00050   data_.assign(right.data_.begin(),right.data_.end());
00051   dim0_ = right.dim0_;
00052   dim1_ = right.dim1_;
00053   dim2_ = right.dim2_;
00054   dim3_ = right.dim3_;
00055   dim4_ = right.dim4_;
00056 }
00057 
00058 //--------------------------------------------------------------------------------------------//
00059 //                                                                                            //
00060 //                              Constructors of FieldContainer class                          //
00061 //                                                                                            //
00062 //--------------------------------------------------------------------------------------------//
00063 
00064 
00065 template<class Scalar, int ArrayTypeId>
00066 FieldContainer<Scalar, ArrayTypeId>::FieldContainer(const int dim0) : dim0_(dim0), dim1_(0), dim2_(0), dim3_(0), dim4_(0) 
00067 {
00068   using Teuchos::as;
00069   using Teuchos::Ordinal;
00070 #ifdef HAVE_INTREPID_DEBUG
00071   TEST_FOR_EXCEPTION( (0 > dim0), std::invalid_argument, 
00072                       ">>> ERROR (FieldContainer): FieldContainer cannot have a negative dimension.");
00073 
00074 #endif
00075   dimensions_.resize(as<Ordinal>(1)); 
00076   dimensions_[0] = dim0_;
00077   data_.assign(as<Ordinal>(dim0_), as<Scalar>(0));
00078 }
00079 
00080 
00081 
00082 template<class Scalar, int ArrayTypeId>
00083 FieldContainer<Scalar, ArrayTypeId>::FieldContainer(const int dim0,
00084                                        const int dim1) : dim0_(dim0), dim1_(dim1), dim2_(0), dim3_(0), dim4_(0)
00085 {
00086   using Teuchos::as;
00087   using Teuchos::Ordinal;
00088 #ifdef HAVE_INTREPID_DEBUG
00089   TEST_FOR_EXCEPTION( (0 > dim0), std::invalid_argument, 
00090                       ">>> ERROR (FieldContainer): FieldContainer cannot have a negative 1st dimension.");
00091   TEST_FOR_EXCEPTION( (0 > dim1), std::invalid_argument, 
00092                       ">>> ERROR (FieldContainer): FieldContainer cannot have a negative 2nd dimension.");
00093   
00094 #endif
00095   dimensions_.resize(2); 
00096   dimensions_[0] = dim0_;   
00097   dimensions_[1] = dim1_;  
00098   data_.assign(as<Ordinal>(dim0_*dim1_), as<Scalar>(0));
00099 }
00100 
00101 
00102 
00103 template<class Scalar, int ArrayTypeId>
00104 FieldContainer<Scalar, ArrayTypeId>::FieldContainer(const int dim0,
00105                                        const int dim1,
00106                                        const int dim2) : dim0_(dim0), dim1_(dim1), dim2_(dim2), dim3_(0), dim4_(0)
00107 {
00108 #ifdef HAVE_INTREPID_DEBUG
00109   TEST_FOR_EXCEPTION( (0 > dim0), std::invalid_argument, 
00110                       ">>> ERROR (FieldContainer): FieldContainer cannot have a negative 1st dimension.");
00111   TEST_FOR_EXCEPTION( (0 > dim1), std::invalid_argument, 
00112                       ">>> ERROR (FieldContainer): FieldContainer cannot have a negative 2nd dimension.");
00113   TEST_FOR_EXCEPTION( (0 > dim2), std::invalid_argument, 
00114                       ">>> ERROR (FieldContainer): FieldContainer cannot have a negative 3rd dimension.");
00115 #endif
00116   dimensions_.resize(3); 
00117   dimensions_[0] = dim0_;  
00118   dimensions_[1] = dim1_; 
00119   dimensions_[2] = dim2_;  
00120   data_.assign(dim0_*dim1_*dim2_, (Scalar)0);
00121 }
00122 
00123 
00124 
00125 template<class Scalar, int ArrayTypeId>
00126 FieldContainer<Scalar, ArrayTypeId>::FieldContainer(const int dim0,
00127                                        const int dim1,
00128                                        const int dim2,
00129                                        const int dim3) : dim0_(dim0), dim1_(dim1), dim2_(dim2), dim3_(dim3), dim4_(0)
00130 {
00131 #ifdef HAVE_INTREPID_DEBUG
00132   TEST_FOR_EXCEPTION( (0 > dim0), std::invalid_argument, 
00133                       ">>> ERROR (FieldContainer): FieldContainer cannot have a negative 1st dimension.");
00134   TEST_FOR_EXCEPTION( (0 > dim1), std::invalid_argument, 
00135                       ">>> ERROR (FieldContainer): FieldContainer cannot have a negative 2nd dimension.");
00136   TEST_FOR_EXCEPTION( (0 > dim2), std::invalid_argument, 
00137                       ">>> ERROR (FieldContainer): FieldContainer cannot have a negative 3rd dimension.");
00138   TEST_FOR_EXCEPTION( (0 > dim3), std::invalid_argument, 
00139                       ">>> ERROR (FieldContainer): FieldContainer cannot have a negative 4th dimension.");  
00140 #endif
00141   dimensions_.resize(4); 
00142   dimensions_[0] = dim0_;  
00143   dimensions_[1] = dim1_; 
00144   dimensions_[2] = dim2_;  
00145   dimensions_[3] = dim3_; 
00146   data_.assign(dim0_*dim1_*dim2_*dim3_, (Scalar)0);
00147 }
00148 
00149 
00150 
00151 template<class Scalar, int ArrayTypeId>
00152 FieldContainer<Scalar, ArrayTypeId>::FieldContainer(const int dim0,
00153                                        const int dim1,
00154                                        const int dim2,
00155                                        const int dim3,
00156                                        const int dim4) : dim0_(dim0), dim1_(dim1), dim2_(dim2), dim3_(dim3), dim4_(dim4)
00157 {
00158 #ifdef HAVE_INTREPID_DEBUG
00159   TEST_FOR_EXCEPTION( (0 > dim0), std::invalid_argument, 
00160                       ">>> ERROR (FieldContainer): FieldContainer cannot have a negative 1st dimension.");
00161   TEST_FOR_EXCEPTION( (0 > dim1), std::invalid_argument, 
00162                       ">>> ERROR (FieldContainer): FieldContainer cannot have a negative 2nd dimension.");
00163   TEST_FOR_EXCEPTION( (0 > dim2), std::invalid_argument, 
00164                       ">>> ERROR (FieldContainer): FieldContainer cannot have a negative 3rd dimension.");
00165   TEST_FOR_EXCEPTION( (0 > dim3), std::invalid_argument, 
00166                       ">>> ERROR (FieldContainer): FieldContainer cannot have a negative 4th dimension.");  
00167   TEST_FOR_EXCEPTION( (0 > dim4), std::invalid_argument, 
00168                       ">>> ERROR (FieldContainer): FieldContainer cannot have a negative 5th dimension.");  
00169 #endif
00170   dimensions_.resize(5); 
00171   dimensions_[0] = dim0_;
00172   dimensions_[1] = dim1_;
00173   dimensions_[2] = dim2_;  
00174   dimensions_[3] = dim3_;  
00175   dimensions_[4] = dim4_;  
00176   data_.assign(dim0_*dim1_*dim2_*dim3_*dim4_, (Scalar)0);
00177 }
00178 
00179 
00180 
00181 template<class Scalar, int ArrayTypeId>
00182 FieldContainer<Scalar, ArrayTypeId>::FieldContainer(const Teuchos::Array<int>& dimensions) {  
00183   
00184 #ifdef HAVE_INTREPID_DEBUG
00185 // srkenno@sandia.gov 6/12/10: changed unsigned int to int - this was causing a warning on compilers that 
00186 //   signed & unsigned int's were being comparied.
00187   for( int dim = 0; dim < dimensions.size(); dim++) {
00188     TEST_FOR_EXCEPTION( (0 > dimensions[dim] ), std::invalid_argument,  
00189                         ">>> ERROR (FieldContainer): One or more negative dimensions");  
00190   }
00191 #endif
00192   
00193   // Copy dimensions and resize container storage to match them
00194   dimensions_.assign(dimensions.begin(),dimensions.end());  
00195   
00196   // Copy first 5 dimensions to optimize class for low rank containers
00197   unsigned int rank = dimensions_.size();
00198   switch(rank) {
00199     case 1:
00200       dim0_ = dimensions_[0]; 
00201       dim1_ = 0;
00202       dim2_ = 0;
00203       dim3_ = 0;
00204       dim4_ = 0;
00205       break;
00206       
00207     case 2:
00208       dim0_ = dimensions_[0]; 
00209       dim1_ = dimensions_[1]; 
00210       dim2_ = 0;
00211       dim3_ = 0;
00212       dim4_ = 0;
00213       break;
00214       
00215     case 3:
00216       dim0_ = dimensions_[0]; 
00217       dim1_ = dimensions_[1]; 
00218       dim2_ = dimensions_[2]; 
00219       dim3_ = 0;
00220       dim4_ = 0;
00221       break;
00222       
00223     case 4:
00224       dim0_ = dimensions_[0]; 
00225       dim1_ = dimensions_[1]; 
00226       dim2_ = dimensions_[2]; 
00227       dim3_ = dimensions_[3]; 
00228       dim4_ = 0;
00229       break;
00230       
00231     case 5:
00232     default:
00233       dim0_ = dimensions_[0]; 
00234       dim1_ = dimensions_[1]; 
00235       dim2_ = dimensions_[2]; 
00236       dim3_ = dimensions_[3]; 
00237       dim4_ = dimensions_[4]; 
00238   }
00239 
00240   // resize data array according to specified dimensions
00241   data_.assign( this -> size(), (Scalar)0);
00242   
00243 }
00244 
00245 
00246 
00247 template<class Scalar, int ArrayTypeId>
00248 FieldContainer<Scalar, ArrayTypeId>::FieldContainer(const Teuchos::Array<int>&         dimensions,
00249                                        const Teuchos::ArrayView<Scalar>&  data) {
00250  
00251   // Copy all dimensions
00252   dimensions_.assign(dimensions.begin(),dimensions.end());
00253   
00254   // Copy first 5 dimensions to optimize class for low rank containers
00255   unsigned int rank = dimensions_.size();
00256   switch(rank) {
00257     case 0:
00258       dim0_ = 0; 
00259       dim1_ = 0;
00260       dim2_ = 0;
00261       dim3_ = 0;
00262       dim4_ = 0;
00263       break;
00264 
00265     case 1:
00266       dim0_ = dimensions_[0]; 
00267       dim1_ = 0;
00268       dim2_ = 0;
00269       dim3_ = 0;
00270       dim4_ = 0;
00271       break;
00272       
00273     case 2:
00274       dim0_ = dimensions_[0]; 
00275       dim1_ = dimensions_[1]; 
00276       dim2_ = 0;
00277       dim3_ = 0;
00278       dim4_ = 0;
00279       break;
00280       
00281     case 3:
00282       dim0_ = dimensions_[0]; 
00283       dim1_ = dimensions_[1]; 
00284       dim2_ = dimensions_[2]; 
00285       dim3_ = 0;
00286       dim4_ = 0;
00287       break;
00288       
00289     case 4:
00290       dim0_ = dimensions_[0]; 
00291       dim1_ = dimensions_[1]; 
00292       dim2_ = dimensions_[2]; 
00293       dim3_ = dimensions_[3]; 
00294       dim4_ = 0;
00295       break;
00296       
00297     case 5:
00298     default:
00299       dim0_ = dimensions_[0]; 
00300       dim1_ = dimensions_[1]; 
00301       dim2_ = dimensions_[2]; 
00302       dim3_ = dimensions_[3]; 
00303       dim4_ = dimensions_[4]; 
00304   }
00305   
00306     // Validate input: size of data array must match container size specified by its dimensions
00307 #ifdef HAVE_INTREPID_DEBUG
00308   TEST_FOR_EXCEPTION( ( (int)data.size() != this -> size() ),
00309                       std::invalid_argument,
00310                       ">>> ERROR (FieldContainer): Size of input data does not match size of this container.");
00311 #endif
00312   
00313   // Deep-copy ArrayView data.
00314   data_.assign(data.begin(),data.end());
00315 }
00316 
00317 
00318 
00319 template<class Scalar, int ArrayTypeId>
00320 FieldContainer<Scalar, ArrayTypeId>::FieldContainer(const Teuchos::Array<int>&        dimensions,
00321                                        const Teuchos::ArrayRCP<Scalar>&  data) {
00322  
00323   // Copy all dimensions
00324   dimensions_.assign(dimensions.begin(),dimensions.end());
00325   
00326   // Copy first 5 dimensions to optimize class for low rank containers
00327   unsigned int rank = dimensions_.size();
00328   switch(rank) {
00329     case 0:
00330       dim0_ = 0; 
00331       dim1_ = 0;
00332       dim2_ = 0;
00333       dim3_ = 0;
00334       dim4_ = 0;
00335       break;
00336 
00337     case 1:
00338       dim0_ = dimensions_[0]; 
00339       dim1_ = 0;
00340       dim2_ = 0;
00341       dim3_ = 0;
00342       dim4_ = 0;
00343       break;
00344       
00345     case 2:
00346       dim0_ = dimensions_[0]; 
00347       dim1_ = dimensions_[1]; 
00348       dim2_ = 0;
00349       dim3_ = 0;
00350       dim4_ = 0;
00351       break;
00352       
00353     case 3:
00354       dim0_ = dimensions_[0]; 
00355       dim1_ = dimensions_[1]; 
00356       dim2_ = dimensions_[2]; 
00357       dim3_ = 0;
00358       dim4_ = 0;
00359       break;
00360       
00361     case 4:
00362       dim0_ = dimensions_[0]; 
00363       dim1_ = dimensions_[1]; 
00364       dim2_ = dimensions_[2]; 
00365       dim3_ = dimensions_[3]; 
00366       dim4_ = 0;
00367       break;
00368       
00369     case 5:
00370     default:
00371       dim0_ = dimensions_[0]; 
00372       dim1_ = dimensions_[1]; 
00373       dim2_ = dimensions_[2]; 
00374       dim3_ = dimensions_[3]; 
00375       dim4_ = dimensions_[4]; 
00376   }
00377   
00378     // Validate input: size of data array must match container size specified by its dimensions
00379 #ifdef HAVE_INTREPID_DEBUG
00380   TEST_FOR_EXCEPTION( ( (int)data.size() != this -> size() ),
00381                       std::invalid_argument,
00382                       ">>> ERROR (FieldContainer): Size of input data does not match size of this container.");
00383 #endif
00384   
00385   // Shallow-copy ArrayRCP data.
00386   data_ = data;
00387 }
00388 
00389 
00390 
00391 template<class Scalar, int ArrayTypeId>
00392 FieldContainer<Scalar, ArrayTypeId>::FieldContainer(const Teuchos::Array<int>&    dimensions,
00393                                        Scalar*                       data,
00394                                        const bool                    deep_copy,
00395                                        const bool                    owns_mem) {
00396  
00397   // Copy all dimensions
00398   dimensions_.assign(dimensions.begin(),dimensions.end());
00399   
00400   // Copy first 5 dimensions to optimize class for low rank containers
00401   unsigned int rank = dimensions_.size();
00402   switch(rank) {
00403     case 0:
00404       dim0_ = 0; 
00405       dim1_ = 0;
00406       dim2_ = 0;
00407       dim3_ = 0;
00408       dim4_ = 0;
00409       break;
00410 
00411     case 1:
00412       dim0_ = dimensions_[0]; 
00413       dim1_ = 0;
00414       dim2_ = 0;
00415       dim3_ = 0;
00416       dim4_ = 0;
00417       break;
00418       
00419     case 2:
00420       dim0_ = dimensions_[0]; 
00421       dim1_ = dimensions_[1]; 
00422       dim2_ = 0;
00423       dim3_ = 0;
00424       dim4_ = 0;
00425       break;
00426       
00427     case 3:
00428       dim0_ = dimensions_[0]; 
00429       dim1_ = dimensions_[1]; 
00430       dim2_ = dimensions_[2]; 
00431       dim3_ = 0;
00432       dim4_ = 0;
00433       break;
00434       
00435     case 4:
00436       dim0_ = dimensions_[0]; 
00437       dim1_ = dimensions_[1]; 
00438       dim2_ = dimensions_[2]; 
00439       dim3_ = dimensions_[3]; 
00440       dim4_ = 0;
00441       break;
00442       
00443     case 5:
00444     default:
00445       dim0_ = dimensions_[0]; 
00446       dim1_ = dimensions_[1]; 
00447       dim2_ = dimensions_[2]; 
00448       dim3_ = dimensions_[3]; 
00449       dim4_ = dimensions_[4]; 
00450   }
00451   
00452 
00453   if (deep_copy) {
00454     Teuchos::ArrayRCP<Scalar> arrayrcp = Teuchos::arcp<Scalar>(data, 0, this -> size(), false);
00455     data_.deepCopy(arrayrcp());
00456   }
00457   else {
00458     data_ = Teuchos::arcp<Scalar>(data, 0, this -> size(), owns_mem);
00459   }
00460 }
00461 
00462 
00463 
00464 template<class Scalar, int ArrayTypeId>
00465 FieldContainer<Scalar, ArrayTypeId>::FieldContainer(const shards::Array<Scalar,shards::NaturalOrder>&  data,
00466                                        const bool                                         deep_copy,
00467                                        const bool                                         owns_mem) {
00468  
00469   // Copy all dimensions
00470   dimensions_.resize(data.rank());
00471   
00472   // Copy first 5 dimensions to optimize class for low rank containers
00473   unsigned int rank = dimensions_.size();
00474   switch(rank) {
00475     case 1:
00476       dimensions_[0] = data.dimension(0);
00477       dim0_ = dimensions_[0]; 
00478       dim1_ = 0;
00479       dim2_ = 0;
00480       dim3_ = 0;
00481       dim4_ = 0;
00482       break;
00483       
00484     case 2:
00485       dimensions_[0] = data.dimension(0);
00486       dimensions_[1] = data.dimension(1);
00487       dim0_ = dimensions_[0]; 
00488       dim1_ = dimensions_[1]; 
00489       dim2_ = 0;
00490       dim3_ = 0;
00491       dim4_ = 0;
00492       break;
00493       
00494     case 3:
00495       dimensions_[0] = data.dimension(0);
00496       dimensions_[1] = data.dimension(1);
00497       dimensions_[2] = data.dimension(2);
00498       dim0_ = dimensions_[0]; 
00499       dim1_ = dimensions_[1]; 
00500       dim2_ = dimensions_[2]; 
00501       dim3_ = 0;
00502       dim4_ = 0;
00503       break;
00504       
00505     case 4:
00506       dimensions_[0] = data.dimension(0);
00507       dimensions_[1] = data.dimension(1);
00508       dimensions_[2] = data.dimension(2);
00509       dimensions_[3] = data.dimension(3);
00510       dim0_ = dimensions_[0]; 
00511       dim1_ = dimensions_[1]; 
00512       dim2_ = dimensions_[2]; 
00513       dim3_ = dimensions_[3]; 
00514       dim4_ = 0;
00515       break;
00516       
00517     case 5:
00518       dimensions_[0] = data.dimension(0);
00519       dimensions_[1] = data.dimension(1);
00520       dimensions_[2] = data.dimension(2);
00521       dimensions_[3] = data.dimension(3);
00522       dimensions_[4] = data.dimension(4);
00523       dim0_ = dimensions_[0]; 
00524       dim1_ = dimensions_[1]; 
00525       dim2_ = dimensions_[2]; 
00526       dim3_ = dimensions_[3]; 
00527       dim4_ = dimensions_[4]; 
00528       break;
00529 
00530     default:
00531       for (int i=0; i<data.rank(); i++) {
00532         dimensions_[i] = data.dimension(i);
00533       }
00534       dim0_ = dimensions_[0]; 
00535       dim1_ = dimensions_[1]; 
00536       dim2_ = dimensions_[2]; 
00537       dim3_ = dimensions_[3]; 
00538       dim4_ = dimensions_[4]; 
00539   }
00540   
00541 
00542   if (deep_copy) {
00543     Teuchos::ArrayRCP<Scalar> arrayrcp = Teuchos::arcp<Scalar>(data.contiguous_data(), 0, this -> size(), false);
00544     data_.deepCopy(arrayrcp());
00545   }
00546   else {
00547     data_ = Teuchos::arcp<Scalar>(data.contiguous_data(), 0, this -> size(), owns_mem);
00548   }
00549 }
00550 
00551 
00552 
00553 //--------------------------------------------------------------------------------------------//
00554 //                                                                                            //
00555 //                            Access methods of FieldContainer class                          //
00556 //                                                                                            //
00557 //--------------------------------------------------------------------------------------------//
00558 
00559 
00560 template<class Scalar, int ArrayTypeId>
00561 inline int FieldContainer<Scalar, ArrayTypeId>::rank() const {
00562   return dimensions_.size();
00563 }
00564   
00565 
00566 
00567 template<class Scalar, int ArrayTypeId>
00568 int FieldContainer<Scalar, ArrayTypeId>::size() const {
00569   // Important! This method is used by constructors to find out what is the needed size of data_
00570   // based on the specified dimensions. Therefore, it cannot be implmented by returning data_.size
00571   // and must be able to compute the size of the container based only on its specified dimensions
00572   
00573   // Size equals product of all dimensions stored in dimensions_
00574   int rank = dimensions_.size();
00575   
00576   // If container has no dimensions its size is zero
00577   if(rank == 0) {
00578     return 0;
00579   }
00580   else {
00581     int size = dim0_;
00582     
00583     // Compute size directly to optimize method for low rank (<=5) containers
00584     switch(rank) {
00585       case 5:
00586         size *= dim1_*dim2_*dim3_*dim4_;
00587         break;
00588         
00589       case 4:
00590         size *= dim1_*dim2_*dim3_;
00591         break;
00592         
00593       case 3:
00594         size *= dim1_*dim2_;
00595         break;
00596         
00597       case 2:
00598         size *= dim1_;
00599         break;
00600         
00601       case 1:
00602         break;
00603         
00604         // Compute size for containers with ranks hihger than 5
00605       default:
00606         for(int r = 1; r < rank ; r++){
00607           size *= dimensions_[r];
00608         }
00609     }
00610     return size;
00611   }
00612 }
00613 
00614 
00615 
00616 template<class Scalar, int ArrayTypeId>
00617 template<class Vector>
00618 inline void FieldContainer<Scalar, ArrayTypeId>::dimensions(Vector& dimensions) const {
00619   dimensions.assign(dimensions_.begin(),dimensions_.end());
00620 }
00621 
00622 
00623 
00624 template<class Scalar, int ArrayTypeId>
00625 inline int FieldContainer<Scalar, ArrayTypeId>::dimension(const int whichDim) const {
00626 #ifdef HAVE_INTREPID_DEBUG
00627   TEST_FOR_EXCEPTION( (0 > whichDim), std::invalid_argument,
00628                       ">>> ERROR (FieldContainer): dimension order cannot be negative");
00629   TEST_FOR_EXCEPTION( (whichDim >= this -> rank() ), std::invalid_argument,
00630                       ">>> ERROR (FieldContainer): dimension order cannot exceed rank of the container");
00631 #endif
00632   return dimensions_[whichDim];
00633 }
00634 
00635 
00636 
00637 template<class Scalar, int ArrayTypeId>
00638 inline int FieldContainer<Scalar, ArrayTypeId>::getEnumeration(const int i0) const {
00639 #ifdef HAVE_INTREPID_DEBUG
00640   TEST_FOR_EXCEPTION( ( this -> rank() != 1), std::invalid_argument, 
00641                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
00642   TEST_FOR_EXCEPTION( ( (i0 < 0) || ( i0 >= dim0_) ), std::invalid_argument,
00643                       ">>> ERROR (FieldContainer): index is out of range.");
00644 #endif
00645   return i0;
00646 }
00647 
00648 
00649 
00650 template<class Scalar, int ArrayTypeId>
00651 inline int FieldContainer<Scalar, ArrayTypeId>::getEnumeration(const int i0,
00652                                                   const int i1) const {
00653 #ifdef HAVE_INTREPID_DEBUG
00654   TEST_FOR_EXCEPTION( ( this -> rank() != 2), std::invalid_argument, 
00655                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
00656   TEST_FOR_EXCEPTION( ( (i0 < 0) || ( i0 >= dim0_) ), std::invalid_argument,
00657                       ">>> ERROR (FieldContainer): 1st index is out of range.");    
00658   TEST_FOR_EXCEPTION( ( (i1 < 0) || (i1 >= dim1_) ), std::invalid_argument,
00659                       ">>> ERROR (FieldContainer): 2nd index is out of range.");    
00660 #endif
00661   return i0*dim1_ + i1;
00662 }
00663 
00664 
00665 
00666 template<class Scalar, int ArrayTypeId>
00667 inline int FieldContainer<Scalar, ArrayTypeId>::getEnumeration(const int i0,
00668                                                   const int i1,
00669                                                   const int i2) const {
00670 #ifdef HAVE_INTREPID_DEBUG
00671   TEST_FOR_EXCEPTION( ( this -> rank() != 3), std::invalid_argument, 
00672                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
00673   TEST_FOR_EXCEPTION( ( (i0 < 0) || ( i0 >= dim0_) ), std::invalid_argument,
00674                       ">>> ERROR (FieldContainer): 1st index is out of range.");    
00675   TEST_FOR_EXCEPTION( ( (i1 < 0) || (i1 >= dim1_) ), std::invalid_argument,
00676                       ">>> ERROR (FieldContainer): 2nd index is out of range.");    
00677   TEST_FOR_EXCEPTION( ( (i2 < 0) || (i2 >= dim2_) ), std::invalid_argument,
00678                       ">>> ERROR (FieldContainer): 3rd index is out of range.");    
00679 #endif
00680   return (i0*dim1_ + i1)*dim2_ + i2;
00681 }
00682 
00683 
00684 
00685 template<class Scalar, int ArrayTypeId>
00686 inline int FieldContainer<Scalar, ArrayTypeId>::getEnumeration(const int i0,
00687                                                   const int i1,
00688                                                   const int i2,
00689                                                   const int i3) const {
00690 #ifdef HAVE_INTREPID_DEBUG
00691   TEST_FOR_EXCEPTION( ( this -> rank() != 4), std::invalid_argument, 
00692                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
00693   TEST_FOR_EXCEPTION( ( (i0 < 0) || ( i0 >= dim0_) ), std::invalid_argument,
00694                       ">>> ERROR (FieldContainer): 1st index is out of range.");    
00695   TEST_FOR_EXCEPTION( ( (i1 < 0) || (i1 >= dim1_) ), std::invalid_argument,
00696                       ">>> ERROR (FieldContainer): 2nd index is out of range.");    
00697   TEST_FOR_EXCEPTION( ( (i2 < 0) || (i2 >= dim2_) ), std::invalid_argument,
00698                       ">>> ERROR (FieldContainer): 3rd index is out of range.");    
00699   TEST_FOR_EXCEPTION( ( (i3 < 0) || (i3 >= dim3_) ), std::invalid_argument,
00700                       ">>> ERROR (FieldContainer): 4th index is out of range.");    
00701 #endif
00702   return ( (i0*dim1_ + i1 )*dim2_ + i2 )*dim3_ + i3;
00703 }
00704 
00705 
00706 
00707 template<class Scalar, int ArrayTypeId>
00708 inline int FieldContainer<Scalar, ArrayTypeId>::getEnumeration(const int i0,
00709                                                   const int i1,
00710                                                   const int i2,
00711                                                   const int i3,
00712                                                   const int i4) const {
00713 #ifdef HAVE_INTREPID_DEBUG
00714   TEST_FOR_EXCEPTION( ( this -> rank() != 5), std::invalid_argument, 
00715                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
00716   TEST_FOR_EXCEPTION( ( (i0 < 0) || ( i0 >= dim0_) ), std::invalid_argument,
00717                       ">>> ERROR (FieldContainer): 1st index is out of range.");    
00718   TEST_FOR_EXCEPTION( ( (i1 < 0) || (i1 >= dim1_) ), std::invalid_argument,
00719                       ">>> ERROR (FieldContainer): 2nd index is out of range.");    
00720   TEST_FOR_EXCEPTION( ( (i2 < 0) || (i2 >= dim2_) ), std::invalid_argument,
00721                       ">>> ERROR (FieldContainer): 3rd index is out of range.");    
00722   TEST_FOR_EXCEPTION( ( (i3 < 0) || (i3 >= dim3_) ), std::invalid_argument,
00723                       ">>> ERROR (FieldContainer): 4th index is out of range.");    
00724   TEST_FOR_EXCEPTION( ( (i4 < 0) || (i4 >= dim4_) ), std::invalid_argument,
00725                       ">>> ERROR (FieldContainer): 5th index is out of range.");    
00726 #endif
00727   return ( ( (i0*dim1_ + i1 )*dim2_ + i2 )*dim3_ + i3 )*dim4_ + i4;
00728 }
00729 
00730 
00731 
00732 
00733 template<class Scalar, int ArrayTypeId>
00734 int FieldContainer<Scalar, ArrayTypeId>::getEnumeration(const Teuchos::Array<int>& multiIndex) const {
00735 
00736 #ifdef HAVE_INTREPID_DEBUG
00737   // Check if number of multi-indices matches rank of the FieldContainer object
00738   TEST_FOR_EXCEPTION( ( multiIndex.size() != dimensions_.size() ),
00739                       std::invalid_argument,
00740                       ">>> ERROR (FieldContainer): Number of multi-indices does not match rank of container.");
00741   TEST_FOR_EXCEPTION( ( ( multiIndex[0] < 0) || ( multiIndex[0] >= dim0_) ),
00742                       std::invalid_argument,
00743                       ">>> ERROR (FieldContainer): 1st index is out of range.");    
00744 #endif  
00745 
00746   int rank = dimensions_.size();
00747   int address = 0;
00748   switch (rank) {
00749     
00750     // Optimize enumeration computation for low rank (<= 5) containers
00751     case 5:
00752 #ifdef HAVE_INTREPID_DEBUG
00753       TEST_FOR_EXCEPTION( ( (multiIndex[4] < 0) || (multiIndex[4] >= dim4_) ),
00754                           std::invalid_argument,
00755                           ">>> ERROR (FieldContainer): 5th index is out of range.");    
00756       TEST_FOR_EXCEPTION( ( (multiIndex[3] < 0) || (multiIndex[3] >= dim3_) ),
00757                           std::invalid_argument,
00758                           ">>> ERROR (FieldContainer): 4th index is out of range.");    
00759       TEST_FOR_EXCEPTION( ( (multiIndex[2] < 0) || (multiIndex[2] >= dim2_) ),
00760                           std::invalid_argument,
00761                           ">>> ERROR (FieldContainer): 3rd index is out of range.");    
00762       TEST_FOR_EXCEPTION( ( (multiIndex[1] < 0) || (multiIndex[1] >= dim1_) ),
00763                           std::invalid_argument,
00764                           ">>> ERROR (FieldContainer): 2nd index is out of range.");    
00765 #endif
00766       address = (((multiIndex[0]*dim1_ + multiIndex[1])*dim2_ + multiIndex[2])*dim3_ + multiIndex[3])*dim4_ + multiIndex[4];
00767       break;
00768       
00769     case 4:
00770 #ifdef HAVE_INTREPID_DEBUG
00771       TEST_FOR_EXCEPTION( ( (multiIndex[3] < 0) || (multiIndex[3] >= dim3_) ),
00772                           std::invalid_argument,
00773                           ">>> ERROR (FieldContainer): 4th index is out of range.");    
00774       TEST_FOR_EXCEPTION( ( (multiIndex[2] < 0) || (multiIndex[2] >= dim2_) ),
00775                           std::invalid_argument,
00776                           ">>> ERROR (FieldContainer): 3rd index is out of range.");    
00777       TEST_FOR_EXCEPTION( ( (multiIndex[1] < 0) || (multiIndex[1] >= dim1_) ),
00778                           std::invalid_argument,
00779                           ">>> ERROR (FieldContainer): 2nd index is out of range.");    
00780 #endif
00781       address = ((multiIndex[0]*dim1_ + multiIndex[1])*dim2_ + multiIndex[2])*dim3_ + multiIndex[3];
00782       break;
00783 
00784     case 3:
00785 #ifdef HAVE_INTREPID_DEBUG
00786       TEST_FOR_EXCEPTION( ( (multiIndex[2] < 0) || (multiIndex[2] >= dim2_) ),
00787                           std::invalid_argument,
00788                           ">>> ERROR (FieldContainer): 3rd index is out of range.");    
00789       TEST_FOR_EXCEPTION( ( (multiIndex[1] < 0) || (multiIndex[1] >= dim1_) ),
00790                           std::invalid_argument,
00791                           ">>> ERROR (FieldContainer): 2nd index is out of range.");    
00792 #endif
00793       address = (multiIndex[0]*dim1_ + multiIndex[1])*dim2_ + multiIndex[2];
00794       break;
00795 
00796     case 2:
00797 #ifdef HAVE_INTREPID_DEBUG
00798       TEST_FOR_EXCEPTION( ( (multiIndex[1] < 0) || (multiIndex[1] >= dim1_) ),
00799                           std::invalid_argument,
00800                           ">>> ERROR (FieldContainer): 2nd index is out of range.");    
00801 #endif
00802       address = multiIndex[0]*dim1_ + multiIndex[1];
00803       break;
00804       
00805     case 1:
00806       address = multiIndex[0];
00807       break;
00808 
00809     default:
00810       
00811       // Arbitrary rank: compute address using Horner's nested scheme: intialize address to 0th index value
00812       address = multiIndex[0];
00813       for (int r = 0; r < rank - 1; r++){
00814 #ifdef HAVE_INTREPID_DEBUG
00815         TEST_FOR_EXCEPTION( ( (multiIndex[r+1] < 0) || (multiIndex[r+1] >= dimensions_[r+1]) ),
00816                             std::invalid_argument,
00817                             ">>> ERROR (FieldContainer): Multi-index component out of range.");    
00818 #endif
00819         // Add increment
00820         address = address*dimensions_[r+1] + multiIndex[r+1];
00821       }
00822   } // end switch(rank)
00823 
00824   return address;
00825 }
00826 
00827 
00828 
00829 template<class Scalar, int ArrayTypeId>
00830 void FieldContainer<Scalar, ArrayTypeId>::getMultiIndex(int & i0,
00831                                            const int valueEnum) const 
00832 {
00833 #ifdef HAVE_INTREPID_DEBUG
00834   TEST_FOR_EXCEPTION( ( this -> rank() != 1), std::invalid_argument, 
00835                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
00836   TEST_FOR_EXCEPTION( ( (valueEnum < 0) || (valueEnum >= (int)data_.size()) ),
00837                       std::invalid_argument,
00838                       ">>> ERROR (FieldContainer): Value enumeration is out of range.");    
00839 #endif
00840   i0 = valueEnum;
00841 }
00842 
00843 
00844 
00845 template<class Scalar, int ArrayTypeId>
00846 void FieldContainer<Scalar, ArrayTypeId>::getMultiIndex(int & i0,
00847                                            int & i1,
00848                                            const int valueEnum) const 
00849 {
00850 #ifdef HAVE_INTREPID_DEBUG
00851   TEST_FOR_EXCEPTION( ( this -> rank() != 2), std::invalid_argument, 
00852                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
00853   TEST_FOR_EXCEPTION( ( (valueEnum < 0) || (valueEnum >= (int)data_.size()) ),
00854                       std::invalid_argument,
00855                       ">>> ERROR (FieldContainer): Value enumeration is out of range.");    
00856 #endif
00857   
00858   i0 = valueEnum/dim1_;
00859   i1 = valueEnum - i0*dim1_;
00860 }
00861 
00862 
00863 
00864 template<class Scalar, int ArrayTypeId>
00865 void FieldContainer<Scalar, ArrayTypeId>::getMultiIndex(int & i0,
00866                                            int & i1,
00867                                            int & i2,
00868                                            const int valueEnum) const 
00869 {
00870 #ifdef HAVE_INTREPID_DEBUG
00871   TEST_FOR_EXCEPTION( ( this -> rank() != 3), std::invalid_argument, 
00872                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
00873   TEST_FOR_EXCEPTION( ( (valueEnum < 0) || (valueEnum >= (int)data_.size()) ),
00874                       std::invalid_argument,
00875                       ">>> ERROR (FieldContainer): Value enumeration is out of range.");    
00876 #endif
00877   int tempDim = dim1_*dim2_;
00878   int tempEnu = valueEnum;
00879   i0 = tempEnu/tempDim;
00880   
00881   tempEnu -= i0*tempDim;
00882   tempDim /= dim1_;
00883   i1 = tempEnu/tempDim;
00884   
00885   tempEnu -= i1*tempDim;
00886   tempDim /= dim2_;
00887   i2 = tempEnu/tempDim;
00888 }
00889 
00890 
00891 
00892 template<class Scalar, int ArrayTypeId>
00893 void FieldContainer<Scalar, ArrayTypeId>::getMultiIndex(int & i0,
00894                                            int & i1,
00895                                            int & i2,
00896                                            int & i3,
00897                                            const int valueEnum) const 
00898 {
00899 #ifdef HAVE_INTREPID_DEBUG
00900   TEST_FOR_EXCEPTION( ( this -> rank() != 4), std::invalid_argument, 
00901                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
00902   TEST_FOR_EXCEPTION( ( (valueEnum < 0) || (valueEnum >= (int)data_.size()) ),
00903                       std::invalid_argument,
00904                       ">>> ERROR (FieldContainer): Value enumeration is out of range.");    
00905 #endif
00906   int tempDim = dim1_*dim2_*dim3_;
00907   int tempEnu = valueEnum;
00908   i0 = tempEnu/tempDim;
00909   
00910   tempEnu -= i0*tempDim;
00911   tempDim /= dim1_;
00912   i1 = tempEnu/tempDim;
00913   
00914   tempEnu -= i1*tempDim;
00915   tempDim /= dim2_;
00916   i2 = tempEnu/tempDim;
00917   
00918   tempEnu -= i2*tempDim;
00919   tempDim /= dim3_;
00920   i3 = tempEnu/tempDim;
00921 }
00922 
00923 
00924 
00925 
00926 template<class Scalar, int ArrayTypeId>
00927 void FieldContainer<Scalar, ArrayTypeId>::getMultiIndex(int & i0,
00928                                            int & i1,
00929                                            int & i2,
00930                                            int & i3,
00931                                            int & i4,
00932                                            const int valueEnum) const 
00933 {
00934 #ifdef HAVE_INTREPID_DEBUG
00935   TEST_FOR_EXCEPTION( ( this -> rank() != 5), std::invalid_argument, 
00936                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
00937   TEST_FOR_EXCEPTION( ( (valueEnum < 0) || (valueEnum >= (int)data_.size()) ),
00938                       std::invalid_argument,
00939                       ">>> ERROR (FieldContainer): Value enumeration is out of range.");    
00940 #endif
00941   int tempDim = dim1_*dim2_*dim3_*dim4_;
00942   int tempEnu = valueEnum;
00943   i0 = tempEnu/tempDim;
00944   
00945   tempEnu -= i0*tempDim;
00946   tempDim /= dim1_;
00947   i1 = tempEnu/tempDim;
00948   
00949   tempEnu -= i1*tempDim;
00950   tempDim /= dim2_;
00951   i2 = tempEnu/tempDim;
00952   
00953   tempEnu -= i2*tempDim;
00954   tempDim /= dim3_;
00955   i3 = tempEnu/tempDim;
00956 
00957   tempEnu -= i3*tempDim;
00958   tempDim /= dim4_;
00959   i4 = tempEnu/tempDim;
00960 }
00961 
00962 
00963 
00964 template<class Scalar, int ArrayTypeId>
00965 template<class Vector>
00966 void FieldContainer<Scalar, ArrayTypeId>::getMultiIndex(Vector &             multiIndex,
00967                                            const int            valueEnum) const 
00968 {
00969   
00970   // Verify address is in the admissible range for this FieldContainer
00971 #ifdef HAVE_INTREPID_DEBUG
00972   TEST_FOR_EXCEPTION( ( (valueEnum < 0) || (valueEnum >= (int)data_.size()) ),
00973                       std::invalid_argument,
00974                       ">>> ERROR (FieldContainer): Value enumeration is out of range.");    
00975 #endif
00976   
00977   // make sure multiIndex has the right size to hold all multi-indices
00978   int rank = dimensions_.size();
00979   multiIndex.resize(rank);
00980   
00981   // Initializations
00982   int temp_enum = valueEnum;
00983   int temp_range = 1;
00984   
00985   // Compute product of all but the first upper bound
00986   for(int r = 1; r < rank ; r++){
00987     temp_range *=dimensions_[r];
00988   }
00989   
00990   // Index 0 is computed first using integer division
00991   multiIndex[0] = temp_enum/temp_range;
00992   
00993   // Indices 1 to (rank - 2) are computed next; will be skipped if rank <=2
00994   for(int r = 1; r < rank - 1; r++){
00995     temp_enum  -= multiIndex[r-1]*temp_range;
00996     temp_range /= dimensions_[r];
00997     multiIndex[r] = temp_enum/temp_range;
00998   }
00999   
01000   // Index (rank - 1) is computed last, skip if rank = 1 and keep if rank = 2
01001   if(rank > 1) {
01002     multiIndex[rank - 1] = temp_enum - multiIndex[rank - 2]*temp_range;
01003   }
01004 }
01005 
01006 //--------------------------------------------------------------------------------------------//
01007 //                                                                                            //
01008 //                          Methods to shape (resize) a field container                       //
01009 //                                                                                            //
01010 //--------------------------------------------------------------------------------------------//
01011 
01012 template<class Scalar, int ArrayTypeId>
01013 inline void FieldContainer<Scalar, ArrayTypeId>::clear() {
01014   dimensions_.resize(0);
01015   
01016   // Reset first five dimensions:
01017   dim0_ = 0;
01018   dim1_ = 0;
01019   dim2_ = 0;
01020   dim3_ = 0;
01021   dim4_ = 0;
01022   
01023   // Clears data array and sets to zero length
01024   data_.clear();
01025 }
01026 
01027 
01028 
01029 template<class Scalar, int ArrayTypeId>
01030 void FieldContainer<Scalar, ArrayTypeId>::resize(const Teuchos::Array<int>& newDimensions) {
01031   
01032   // First handle the trivial case of zero dimensions
01033   if( newDimensions.size() == 0) {
01034     dimensions_.resize(0);
01035     dim0_ = 0;
01036     dim1_ = 0;
01037     dim2_ = 0;
01038     dim3_ = 0;
01039     dim4_ = 0;
01040     data_.resize(0);
01041   }
01042   else {
01043     
01044     // Copy upper index bounds and resize container storage to match new upper bounds.
01045     dimensions_.assign(newDimensions.begin(),newDimensions.end());  
01046     
01047     // Copy first 5 dimensions for faster access
01048     unsigned int rank = dimensions_.size();
01049     switch(rank) {
01050       case 1:
01051         dim0_ = dimensions_[0]; 
01052         dim1_ = 0;
01053         dim2_ = 0;
01054         dim3_ = 0;
01055         dim4_ = 0;
01056         break;
01057         
01058       case 2:
01059         dim0_ = dimensions_[0]; 
01060         dim1_ = dimensions_[1]; 
01061         dim2_ = 0;
01062         dim3_ = 0;
01063         dim4_ = 0;
01064         break;
01065         
01066       case 3:
01067         dim0_ = dimensions_[0]; 
01068         dim1_ = dimensions_[1]; 
01069         dim2_ = dimensions_[2]; 
01070         dim3_ = 0;
01071         dim4_ = 0;
01072         break;
01073         
01074       case 4:
01075         dim0_ = dimensions_[0]; 
01076         dim1_ = dimensions_[1]; 
01077         dim2_ = dimensions_[2]; 
01078         dim3_ = dimensions_[3]; 
01079         dim4_ = 0;
01080         break;
01081         
01082       case 5:
01083       default:
01084         dim0_ = dimensions_[0]; 
01085         dim1_ = dimensions_[1]; 
01086         dim2_ = dimensions_[2]; 
01087         dim3_ = dimensions_[3]; 
01088         dim4_ = dimensions_[4]; 
01089     }
01090     
01091     // Resize data array
01092     data_.resize(this -> size());
01093   }
01094 }
01095 
01096 
01097 
01098 template<class Scalar, int ArrayTypeId>
01099 inline void FieldContainer<Scalar, ArrayTypeId>::resize(const int dim0) {
01100   dim0_ = dim0;  
01101   dim1_ = 0;  
01102   dim2_ = 0;  
01103   dim3_ = 0;  
01104   dim4_ = 0;
01105   dimensions_.resize(1);  
01106   dimensions_[0] = dim0_; 
01107   data_.resize(dim0_); 
01108 }
01109 
01110 
01111 
01112 template<class Scalar, int ArrayTypeId>
01113 inline void FieldContainer<Scalar, ArrayTypeId>::resize(const int dim0,
01114                                            const int dim1) {
01115   dim0_ = dim0;  
01116   dim1_ = dim1;  
01117   dim2_ = 0;  
01118   dim3_ = 0;  
01119   dim4_ = 0;
01120   dimensions_.resize(2);  
01121   dimensions_[0] = dim0_;  
01122   dimensions_[1] = dim1_;  
01123   data_.resize(dim0_*dim1_); 
01124 }
01125 
01126 
01127 
01128 template<class Scalar, int ArrayTypeId>
01129 inline void FieldContainer<Scalar, ArrayTypeId>::resize(const int dim0,
01130                                            const int dim1,
01131                                            const int dim2) {
01132   dim0_ = dim0;
01133   dim1_ = dim1;
01134   dim2_ = dim2;
01135   dim3_ = 0;  
01136   dim4_ = 0;
01137   dimensions_.resize(3);  
01138   dimensions_[0] = dim0_; 
01139   dimensions_[1] = dim1_;  
01140   dimensions_[2] = dim2_;  
01141   data_.resize(dim0_*dim1_*dim2_); 
01142 }
01143 
01144 
01145 
01146 template<class Scalar, int ArrayTypeId>
01147 inline void FieldContainer<Scalar, ArrayTypeId>::resize(const int dim0,
01148                                            const int dim1,
01149                                            const int dim2,
01150                                            const int dim3) {
01151   dim0_ = dim0;
01152   dim1_ = dim1;
01153   dim2_ = dim2;
01154   dim3_ = dim3;
01155   dim4_ = 0;
01156   dimensions_.resize(4);  
01157   dimensions_[0] = dim0_;  
01158   dimensions_[1] = dim1_;  
01159   dimensions_[2] = dim2_;  
01160   dimensions_[3] = dim3_;  
01161   data_.resize(dim0_*dim1_*dim2_*dim3_); 
01162 }
01163 
01164 
01165 
01166 template<class Scalar, int ArrayTypeId>
01167 inline void FieldContainer<Scalar, ArrayTypeId>::resize(const int dim0,
01168                                            const int dim1,
01169                                            const int dim2,
01170                                            const int dim3,
01171                                            const int dim4) {
01172   dim0_ = dim0;
01173   dim1_ = dim1;
01174   dim2_ = dim2;
01175   dim3_ = dim3;
01176   dim4_ = dim4;
01177   dimensions_.resize(5);  
01178   dimensions_[0] = dim0_;  
01179   dimensions_[1] = dim1_;  
01180   dimensions_[2] = dim2_;  
01181   dimensions_[3] = dim3_;  
01182   dimensions_[4] = dim4_;  
01183   data_.resize(dim0_*dim1_*dim2_*dim3_*dim4_); 
01184 }
01185 
01186 
01187 
01188 template<class Scalar, int ArrayTypeId>
01189 inline void FieldContainer<Scalar, ArrayTypeId>::resize(const FieldContainer<Scalar, ArrayTypeId>& anotherContainer) {
01190   
01191   // Copy dimensions from the specified container
01192   anotherContainer.dimensions(dimensions_);
01193   int newRank = dimensions_.size();
01194   
01195   // Copy first 5 dimensions for faster access
01196   switch(newRank) {
01197     case 1:
01198       dim0_ = dimensions_[0]; 
01199       dim1_ = 0;
01200       dim2_ = 0;
01201       dim3_ = 0;
01202       dim4_ = 0;
01203       break;
01204       
01205     case 2:
01206       dim0_ = dimensions_[0]; 
01207       dim1_ = dimensions_[1]; 
01208       dim2_ = 0;
01209       dim3_ = 0;
01210       dim4_ = 0;
01211       break;
01212       
01213     case 3:
01214       dim0_ = dimensions_[0]; 
01215       dim1_ = dimensions_[1]; 
01216       dim2_ = dimensions_[2]; 
01217       dim3_ = 0;
01218       dim4_ = 0;
01219       break;
01220       
01221     case 4:
01222       dim0_ = dimensions_[0]; 
01223       dim1_ = dimensions_[1]; 
01224       dim2_ = dimensions_[2]; 
01225       dim3_ = dimensions_[3]; 
01226       dim4_ = 0;
01227       break;
01228       
01229     case 5:
01230     default:
01231       dim0_ = dimensions_[0]; 
01232       dim1_ = dimensions_[1]; 
01233       dim2_ = dimensions_[2]; 
01234       dim3_ = dimensions_[3]; 
01235       dim4_ = dimensions_[4]; 
01236   }
01237   
01238   // Resize data array
01239   data_.resize(this->size());  
01240 }
01241 
01242 
01243 template<class Scalar, int ArrayTypeId>
01244 void FieldContainer<Scalar, ArrayTypeId>::resize(const int             numPoints,
01245                                     const int             numFields,
01246                                     const EFunctionSpace  spaceType,
01247                                     const EOperator       operatorType,
01248                                     const int             spaceDim) {  
01249   // Validate input
01250 #ifdef HAVE_INTREPID_DEBUG
01251   TEST_FOR_EXCEPTION( ( numPoints < 0),
01252                       std::invalid_argument,
01253                       ">>> ERROR (FieldContainer): Number of points cannot be negative!");  
01254   TEST_FOR_EXCEPTION( ( numFields < 0),
01255                       std::invalid_argument,
01256                       ">>> ERROR (FieldContainer): Number of fields cannot be negative!");  
01257   TEST_FOR_EXCEPTION( !( (1 <=  spaceDim ) && ( spaceDim <= 3  ) ),
01258                       std::invalid_argument,
01259                       ">>> ERROR (FieldContainer): Invalid space dimension.");  
01260 #endif  
01261   
01262   // Find out field and operator ranks
01263   int fieldRank    = getFieldRank(spaceType);
01264   int operatorRank = getOperatorRank(spaceType,operatorType,spaceDim);
01265   
01266   // Compute rank of the container = 1(numPoints) + 1(numFields) + fieldRank + operatorRank
01267   int rank = 1 + 1 + fieldRank + operatorRank;
01268   
01269   // Define temp array for the dimensions
01270   Teuchos::Array<int> newDimensions(rank);
01271   
01272   // Dimensions 0 and 1 are number of points and number of fields, resp.
01273   newDimensions[0] = numPoints;
01274   newDimensions[1] = numFields;
01275   
01276   // The rest of the dimensions depend on whether we had VALUE, GRAD (D1), CURL, DIV or Dk, k>1
01277   switch(operatorType) {
01278     
01279     case OPERATOR_VALUE:
01280     case OPERATOR_GRAD:
01281     case OPERATOR_D1:
01282     case OPERATOR_CURL:
01283     case OPERATOR_DIV:
01284       
01285       // For these operators all dimensions from 2 to 2 + fieldRank + OperatorRank are bounded by spaceDim
01286       for(int i = 0; i < fieldRank + operatorRank; i++){
01287         newDimensions[2 + i] = spaceDim; 
01288       }
01289       break;
01290       
01291     case OPERATOR_D2:
01292     case OPERATOR_D3:
01293     case OPERATOR_D4:
01294     case OPERATOR_D5:
01295     case OPERATOR_D6:
01296     case OPERATOR_D7:
01297     case OPERATOR_D8:
01298     case OPERATOR_D9:
01299     case OPERATOR_D10:
01300       
01301       // All dimensions from 2 to 2 + fieldRank, if any, are bounded by spaceDim
01302       for(int i = 0; i < fieldRank; i++){
01303         newDimensions[2 + i] = spaceDim; 
01304       }
01305       
01306       // We know that for Dk operatorRank = 1 and so there's just one more dimension left
01307       // given by the cardinality of the set of all derivatives of order k
01308       newDimensions[2 + fieldRank] = getDkCardinality(operatorType,spaceDim);
01309       break;
01310       
01311     default:
01312       TEST_FOR_EXCEPTION( !(Intrepid::isValidOperator(operatorType) ), std::invalid_argument,
01313                           ">>> ERROR (FieldContainer): Invalid operator type");    
01314   }
01315   
01316   // Resize FieldContainer using the newDimensions in the array
01317   this -> resize(newDimensions);
01318 }
01319 
01320 //--------------------------------------------------------------------------------------------//
01321 //                                                                                            //
01322 //                     Methods to read and write values to FieldContainer                     //
01323 //                                                                                            //
01324 //--------------------------------------------------------------------------------------------//
01325 
01326 
01327 
01328 template<class Scalar, int ArrayTypeId>
01329 inline void FieldContainer<Scalar, ArrayTypeId>::initialize(const Scalar value) {
01330   for (int i=0; i < this->size(); i++) {
01331     data_[i] = value;
01332   } 
01333 }
01334 
01335 
01336 
01337 template<class Scalar, int ArrayTypeId>
01338 inline Scalar FieldContainer<Scalar, ArrayTypeId>::getValue(const Teuchos::Array<int>& multiIndex) const {
01339   return data_[this -> getEnumeration(multiIndex)];
01340 }
01341 
01342 
01343 
01344 template<class Scalar, int ArrayTypeId>
01345 inline void FieldContainer<Scalar, ArrayTypeId>::setValue(const Scalar dataValue, 
01346                                              const Teuchos::Array<int>& multiIndex) {
01347   data_[this -> getEnumeration(multiIndex)] = dataValue; 
01348 }
01349 
01350 
01351 
01352 template<class Scalar, int ArrayTypeId>
01353 inline void FieldContainer<Scalar, ArrayTypeId>::setValue(const Scalar dataValue, 
01354                                              const int    order) {
01355   data_[order] = dataValue; 
01356 }
01357 
01358 
01359 
01360 template<class Scalar, int ArrayTypeId>
01361 void FieldContainer<Scalar, ArrayTypeId>::setValues(const Teuchos::ArrayView<Scalar>& dataArray) {
01362 #ifdef HAVE_INTREPID_DEBUG
01363   TEST_FOR_EXCEPTION( (dataArray.size() != (data_.size()) ),
01364                       std::invalid_argument,
01365                       ">>> ERROR (FieldContainer): Size of argument does not match the size of container.");  
01366 #endif  
01367   data_.assign(dataArray.begin(),dataArray.end());
01368 }
01369 
01370 
01371 
01372 template<class Scalar, int ArrayTypeId>
01373 void FieldContainer<Scalar, ArrayTypeId>::setValues(const Scalar* dataPtr, 
01374                                        const int numData) 
01375 {
01376 #ifdef HAVE_INTREPID_DEBUG
01377   TEST_FOR_EXCEPTION( (numData != this -> size() ), std::invalid_argument,
01378                       ">>> ERROR (FieldContainer): Number of data does not match the size of container.");  
01379 
01380 #endif
01381   data_.assign(dataPtr, dataPtr + numData);  
01382 }
01383 
01384 
01385 
01386 template<class Scalar, int ArrayTypeId>
01387 inline const Scalar& FieldContainer<Scalar, ArrayTypeId>::operator () (const int i0) const 
01388 {
01389 #ifdef HAVE_INTREPID_DEBUG
01390   TEST_FOR_EXCEPTION( ( this -> rank() != 1), std::invalid_argument, 
01391                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
01392   TEST_FOR_EXCEPTION( ( (i0 < 0) || (i0 >= dim0_) ), std::invalid_argument,
01393                       ">>> ERROR (FieldContainer): index is out of range.");    
01394 #endif
01395   return data_[i0]; 
01396 }
01397 
01398 
01399 template<class Scalar, int ArrayTypeId>
01400 inline Scalar& FieldContainer<Scalar, ArrayTypeId>::operator () (const int i0)  
01401 {
01402 #ifdef HAVE_INTREPID_DEBUG
01403   TEST_FOR_EXCEPTION( ( this -> rank() != 1), std::invalid_argument, 
01404                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
01405   TEST_FOR_EXCEPTION( ( (i0 < 0) || (i0 >= dim0_) ), std::invalid_argument,
01406                       ">>> ERROR (FieldContainer): index is out of range.");    
01407 #endif
01408   return data_[i0]; 
01409 }
01410 
01411 
01412 
01413 template<class Scalar, int ArrayTypeId>
01414 inline const Scalar& FieldContainer<Scalar, ArrayTypeId>::operator () (const int i0,
01415                                                           const int i1) const 
01416 {
01417 #ifdef HAVE_INTREPID_DEBUG
01418   TEST_FOR_EXCEPTION( ( this -> rank() != 2), std::invalid_argument, 
01419                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
01420   TEST_FOR_EXCEPTION( ( (i0 < 0) || (i0 >= dim0_) ), std::invalid_argument,
01421                       ">>> ERROR (FieldContainer): 1st index is out of range.");    
01422   TEST_FOR_EXCEPTION( ( (i1 < 0) || (i1 >= dim1_) ), std::invalid_argument,
01423                       ">>> ERROR (FieldContainer): 2nd index is out of range.");    
01424 #endif
01425   return data_[i0*dim1_ + i1]; 
01426 }
01427 
01428 
01429 template<class Scalar, int ArrayTypeId>
01430 inline Scalar& FieldContainer<Scalar, ArrayTypeId>::operator () (const int i0,
01431                                                     const int i1)  
01432 {
01433 #ifdef HAVE_INTREPID_DEBUG
01434   TEST_FOR_EXCEPTION( ( this -> rank() != 2), std::invalid_argument, 
01435                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
01436   TEST_FOR_EXCEPTION( ( (i0 < 0) || (i0 >= dim0_) ), std::invalid_argument,
01437                       ">>> ERROR (FieldContainer): 1st index is out of range.");    
01438   TEST_FOR_EXCEPTION( ( (i1 < 0) || (i1 >= dim1_) ), std::invalid_argument,
01439                       ">>> ERROR (FieldContainer): 2nd index is out of range.");    
01440 #endif
01441   return data_[i0*dim1_ + i1]; 
01442 }
01443 
01444 
01445 
01446 template<class Scalar, int ArrayTypeId>
01447 inline const Scalar& FieldContainer<Scalar, ArrayTypeId>::operator () (const int i0,
01448                                                           const int i1,
01449                                                           const int i2) const 
01450 {
01451 #ifdef HAVE_INTREPID_DEBUG
01452   TEST_FOR_EXCEPTION( ( this -> rank() != 3), std::invalid_argument, 
01453                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
01454   TEST_FOR_EXCEPTION( ( (i0 < 0) || (i0 >= dim0_) ), std::invalid_argument,
01455                       ">>> ERROR (FieldContainer): 1st index is out of range.");    
01456   TEST_FOR_EXCEPTION( ( (i1 < 0) || (i1 >= dim1_) ), std::invalid_argument,
01457                       ">>> ERROR (FieldContainer): 2nd index is out of range.");    
01458   TEST_FOR_EXCEPTION( ( (i2 < 0) || (i2 >= dim2_) ), std::invalid_argument,
01459                       ">>> ERROR (FieldContainer): 3rd index is out of range.");    
01460 #endif
01461   return data_[(i0*dim1_ + i1)*dim2_ + i2]; 
01462 }
01463 
01464 template<class Scalar, int ArrayTypeId>
01465 inline Scalar& FieldContainer<Scalar, ArrayTypeId>::operator () (const int i0,
01466                                                     const int i1,
01467                                                     const int i2) 
01468 {
01469 #ifdef HAVE_INTREPID_DEBUG
01470   TEST_FOR_EXCEPTION( ( this -> rank() != 3), std::invalid_argument, 
01471                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
01472   TEST_FOR_EXCEPTION( ( (i0 < 0) || (i0 >= dim0_) ), std::invalid_argument,
01473                       ">>> ERROR (FieldContainer): 1st index is out of range.");    
01474   TEST_FOR_EXCEPTION( ( (i1 < 0) || (i1 >= dim1_) ), std::invalid_argument,
01475                       ">>> ERROR (FieldContainer): 2nd index is out of range.");    
01476   TEST_FOR_EXCEPTION( ( (i2 < 0) || (i2 >= dim2_) ), std::invalid_argument,
01477                       ">>> ERROR (FieldContainer): 3rd index is out of range.");    
01478 #endif
01479   return data_[(i0*dim1_ + i1)*dim2_ + i2]; 
01480 }
01481 
01482 
01483 
01484 template<class Scalar, int ArrayTypeId>
01485 inline const Scalar& FieldContainer<Scalar, ArrayTypeId>::operator ()  (const int i0,
01486                                                            const int i1,
01487                                                            const int i2,
01488                                                            const int i3) const {
01489 #ifdef HAVE_INTREPID_DEBUG
01490   TEST_FOR_EXCEPTION( ( this -> rank() != 4), std::invalid_argument, 
01491                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
01492   TEST_FOR_EXCEPTION( ( (i0 < 0) || (i0 >= dim0_) ), std::invalid_argument,
01493                       ">>> ERROR (FieldContainer): 1st index is out of range.");    
01494   TEST_FOR_EXCEPTION( ( (i1 < 0) || (i1 >= dim1_) ), std::invalid_argument,
01495                       ">>> ERROR (FieldContainer): 2nd index is out of range.");    
01496   TEST_FOR_EXCEPTION( ( (i2 < 0) || (i2 >= dim2_) ), std::invalid_argument,
01497                       ">>> ERROR (FieldContainer): 3rd index is out of range.");    
01498   TEST_FOR_EXCEPTION( ( (i3 < 0) || (i3 >= dim3_) ), std::invalid_argument,
01499                       ">>> ERROR (FieldContainer): 4th index is out of range.");    
01500 #endif
01501   return data_[( (i0*dim1_ + i1 )*dim2_ + i2 )*dim3_ + i3];
01502 }
01503 
01504 
01505 template<class Scalar, int ArrayTypeId>
01506 inline Scalar& FieldContainer<Scalar, ArrayTypeId>::operator ()  (const int i0,
01507                                                      const int i1,
01508                                                      const int i2,
01509                                                      const int i3) {
01510 #ifdef HAVE_INTREPID_DEBUG
01511   TEST_FOR_EXCEPTION( ( this -> rank() != 4), std::invalid_argument, 
01512                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
01513   TEST_FOR_EXCEPTION( ( (i0 < 0) || (i0 >= dim0_) ), std::invalid_argument,
01514                       ">>> ERROR (FieldContainer): 1st index is out of range.");    
01515   TEST_FOR_EXCEPTION( ( (i1 < 0) || (i1 >= dim1_) ), std::invalid_argument,
01516                       ">>> ERROR (FieldContainer): 2nd index is out of range.");    
01517   TEST_FOR_EXCEPTION( ( (i2 < 0) || (i2 >= dim2_) ), std::invalid_argument,
01518                       ">>> ERROR (FieldContainer): 3rd index is out of range.");    
01519   TEST_FOR_EXCEPTION( ( (i3 < 0) || (i3 >= dim3_) ), std::invalid_argument,
01520                       ">>> ERROR (FieldContainer): 4th index is out of range.");    
01521 #endif
01522   return data_[( (i0*dim1_ + i1 )*dim2_ + i2 )*dim3_ + i3];
01523 }
01524 
01525 
01526 
01527 template<class Scalar, int ArrayTypeId>
01528 inline const Scalar& FieldContainer<Scalar, ArrayTypeId>::operator ()  (const int i0,
01529                                                            const int i1,
01530                                                            const int i2,
01531                                                            const int i3,
01532                                                            const int i4) const {
01533 #ifdef HAVE_INTREPID_DEBUG
01534   TEST_FOR_EXCEPTION( ( this -> rank() != 5), std::invalid_argument, 
01535                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
01536   TEST_FOR_EXCEPTION( ( (i0 < 0) || (i0 >= dim0_) ), std::invalid_argument,
01537                       ">>> ERROR (FieldContainer): 1st index is out of range.");    
01538   TEST_FOR_EXCEPTION( ( (i1 < 0) || (i1 >= dim1_) ), std::invalid_argument,
01539                       ">>> ERROR (FieldContainer): 2nd index is out of range.");    
01540   TEST_FOR_EXCEPTION( ( (i2 < 0) || (i2 >= dim2_) ), std::invalid_argument,
01541                       ">>> ERROR (FieldContainer): 3rd index is out of range.");    
01542   TEST_FOR_EXCEPTION( ( (i3 < 0) || (i3 >= dim3_) ), std::invalid_argument,
01543                       ">>> ERROR (FieldContainer): 4th index is out of range.");    
01544   TEST_FOR_EXCEPTION( ( (i4 < 0) || (i4 >= dim4_) ), std::invalid_argument,
01545                       ">>> ERROR (FieldContainer): 5th index is out of range.");    
01546 #endif
01547   return data_[( ( (i0*dim1_ + i1 )*dim2_ + i2 )*dim3_ + i3 )*dim4_ + i4];
01548 }
01549 
01550 template<class Scalar, int ArrayTypeId>
01551 inline Scalar& FieldContainer<Scalar, ArrayTypeId>::operator ()  (const int i0,
01552                                                      const int i1,
01553                                                      const int i2,
01554                                                      const int i3,
01555                                                      const int i4) {
01556 #ifdef HAVE_INTREPID_DEBUG
01557   TEST_FOR_EXCEPTION( ( this -> rank() != 5), std::invalid_argument, 
01558                       ">>> ERROR (FieldContainer): Number of indices does not match rank of the container.");  
01559   TEST_FOR_EXCEPTION( ( (i0 < 0) || (i0 >= dim0_) ), std::invalid_argument,
01560                       ">>> ERROR (FieldContainer): 1st index is out of range.");    
01561   TEST_FOR_EXCEPTION( ( (i1 < 0) || (i1 >= dim1_) ), std::invalid_argument,
01562                       ">>> ERROR (FieldContainer): 2nd index is out of range.");    
01563   TEST_FOR_EXCEPTION( ( (i2 < 0) || (i2 >= dim2_) ), std::invalid_argument,
01564                       ">>> ERROR (FieldContainer): 3rd index is out of range.");    
01565   TEST_FOR_EXCEPTION( ( (i3 < 0) || (i3 >= dim3_) ), std::invalid_argument,
01566                       ">>> ERROR (FieldContainer): 4th index is out of range.");    
01567   TEST_FOR_EXCEPTION( ( (i4 < 0) || (i4 >= dim4_) ), std::invalid_argument,
01568                       ">>> ERROR (FieldContainer): 5th index is out of range.");    
01569 #endif
01570   return data_[( ( (i0*dim1_ + i1 )*dim2_ + i2 )*dim3_ + i3 )*dim4_ + i4];
01571 }
01572 
01573 
01574 
01575 template<class Scalar, int ArrayTypeId>
01576 const Scalar& FieldContainer<Scalar, ArrayTypeId>::operator [] (const int address) const {
01577 #ifdef HAVE_INTREPID_DEBUG
01578   TEST_FOR_EXCEPTION( ( (address < 0) || (address >= (int)data_.size() ) ),
01579                       std::invalid_argument,
01580                       ">>> ERROR (FieldContainer): Specified address is out of range.");
01581 #endif
01582   return data_[address];
01583 }
01584 
01585 
01586 
01587 template<class Scalar, int ArrayTypeId>
01588 Scalar& FieldContainer<Scalar, ArrayTypeId>::operator [] (const int address) {
01589 #ifdef HAVE_INTREPID_DEBUG
01590   TEST_FOR_EXCEPTION( ( (address < 0) || (address >= (int)data_.size() ) ),
01591                       std::invalid_argument,
01592                       ">>> ERROR (FieldContainer): Specified address is out of range.");
01593 #endif
01594   return data_[address];
01595 }
01596 
01597 
01598 
01599 template<class Scalar, int ArrayTypeId>
01600 inline FieldContainer<Scalar, ArrayTypeId>& FieldContainer<Scalar, ArrayTypeId>::operator = (const FieldContainer<Scalar, ArrayTypeId>& right)
01601 {
01602 #ifdef HAVE_INTREPID_DEBUG
01603   TEST_FOR_EXCEPTION( ( this == &right ),
01604                       std::invalid_argument,
01605                       ">>> ERROR (FieldContainer): Invalid right-hand side to '='. Self-assignment prohibited.");
01606 #endif
01607   dim0_ = right.dim0_;
01608   dim1_ = right.dim1_;
01609   dim2_ = right.dim2_;
01610   dim3_ = right.dim3_;
01611   dim4_ = right.dim4_;
01612   data_.deepCopy(right.data_());
01613   dimensions_ = right.dimensions_; 
01614   return *this;
01615 }
01616 
01617 
01618 //===========================================================================//
01619 //                                                                           //
01620 //           END of member definitions; START friends and related            //
01621 //                                                                           //
01622 //===========================================================================//
01623 
01624 
01625 template<class Scalar, int ArrayTypeId>
01626 std::ostream& operator << (std::ostream& os, const FieldContainer<Scalar, ArrayTypeId>& container) {
01627   
01628   // Save the format state of the original ostream os.
01629   Teuchos::oblackholestream oldFormatState;
01630   oldFormatState.copyfmt(os);  
01631 
01632   os.setf(std::ios_base::scientific, std::ios_base::floatfield);
01633   os.setf(std::ios_base::right);
01634   int myprec = os.precision();
01635   
01636   int size = container.size();
01637   int rank = container.rank();
01638   Teuchos::Array<int> multiIndex(rank);
01639   Teuchos::Array<int> dimensions;
01640   container.dimensions(dimensions);
01641   
01642   os<< "===============================================================================\n"\
01643     << "\t Container size = " << size << "\n"
01644     << "\t Container rank = " << rank << "\n" ;
01645   
01646   if( (rank == 0 ) && (size == 0) ) {
01647     os<< "====================================================================================\n"\
01648       << "|                        *** This is an empty container ****                       |\n";
01649   }
01650   else {
01651     os<< "\t Dimensions     = ";
01652     
01653     for(int r = 0; r < rank; r++){
01654       os << " (" << dimensions[r] <<") ";
01655     }
01656     os << "\n";
01657     
01658     os<< "====================================================================================\n"\
01659       << "|              Multi-index          Enumeration             Value                  |\n"\
01660       << "====================================================================================\n";
01661   }
01662   
01663   for(int address = 0; address < size; address++){
01664     container.getMultiIndex(multiIndex,address);
01665     std::ostringstream mistring;
01666     for(int r = 0; r < rank; r++){
01667       mistring <<  multiIndex[r] << std::dec << " "; 
01668     }
01669     os.setf(std::ios::right, std::ios::adjustfield);
01670     os << std::setw(27) << mistring.str(); 
01671     os << std::setw(20) << address;
01672     os << "             ";
01673     os.setf(std::ios::left, std::ios::adjustfield);
01674     os << std::setw(myprec+8) << container[address] << "\n";
01675   }
01676   
01677   os<< "====================================================================================\n\n";
01678 
01679   // reset format state of os
01680   os.copyfmt(oldFormatState);
01681 
01682   return os;
01683 }
01684 // End member, friend, and related function definitions of class FieldContainer.
01685 
01686 } // end namespace Intrepid