Intrepid
/usr/src/RPM/BUILD/trilinos10-10.6.4/packages/intrepid/src/Shared/Intrepid_Utils.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 #ifndef INTREPID_UTILS_HPP
00036 #define INTREPID_UTILS_HPP
00037 
00038 #include "Intrepid_ConfigDefs.hpp"
00039 #include "Intrepid_Types.hpp"
00040 #include "Teuchos_Array.hpp"
00041 #include "Teuchos_oblackholestream.hpp"
00042 #include "Teuchos_RCP.hpp"
00043 
00044 namespace Intrepid {
00045 
00046 /***************************************************************************************************
00047  ***************************************************************************************************
00048  **                                                                                               **
00049  **  Declarations of non-templated utility functions for order and cardinality of operators       **
00050  **                                                                                               **
00051  ***************************************************************************************************
00052  ***************************************************************************************************/
00053   
00054   
00066   int getFieldRank(const EFunctionSpace spaceType); 
00067   
00068   
00069   
00105   int getOperatorRank(const EFunctionSpace spaceType,
00106                       const EOperator      operatorType,
00107                       const int            spaceDim);
00108   
00109   
00110   
00116   int getOperatorOrder(const EOperator operatorType);
00117   
00118   
00119   
00144   int getDkEnumeration(const int xMult,
00145                        const int yMult = -1,
00146                        const int zMult = -1);
00147   
00148   
00149   
00158   void getDkMultiplicities(Teuchos::Array<int>&  partialMult,
00159                            const int             derivativeEnum,
00160                            const EOperator       operatorType,
00161                            const int             spaceDim);
00162   
00163   
00164   
00183   int getDkCardinality(const EOperator operatorType,
00184                        const int       spaceDim);
00185   
00186   
00187   
00188 /***************************************************************************************************
00189  ***************************************************************************************************
00190  **                                                                                               **
00191  **                      Declarations of helper functions for the basis class                     **
00192  **                                                                                               **
00193  ***************************************************************************************************
00194  ***************************************************************************************************/
00195   
00207   void setOrdinalTagData(std::vector<std::vector<std::vector<int> > >   &tagToOrdinal,
00208                          std::vector<std::vector<int> >                 &ordinalToTag,
00209                          const int                                      *tags,
00210                          const int                                      basisCard,
00211                          const int                                      tagSize,
00212                          const int                                      posScDim,
00213                          const int                                      posScOrd,
00214                          const int                                      posDfOrd);
00215   
00216   
00217   
00218 /***************************************************************************************************
00219  ***************************************************************************************************
00220  **                                                                                               **
00221  **                      Declarations of templated utility functions                              **
00222  **                                                                                               **
00223  ***************************************************************************************************
00224  ***************************************************************************************************/
00225   
00226   enum TypeOfExactData{
00227     INTREPID_UTILS_FRACTION=0,
00228     INTREPID_UTILS_SCALAR
00229   };
00230   
00231 /***************************************************************************************************
00232  *                                                                                                 *
00233  *               Utility functions for handling external data in tests                             *
00234  *                                                                                                 *
00235  ***************************************************************************************************/
00236   
00249 template<class Scalar>
00250 int compareToAnalytic(const Teuchos::Array< Teuchos::Array<Scalar> > testMat,
00251                       std::ifstream & inputFile,
00252                       Scalar reltol,
00253                       int iprint,
00254                       TypeOfExactData analyticDataType = INTREPID_UTILS_FRACTION);
00255 
00269 template<class Scalar>
00270 int compareToAnalytic(const Scalar * testMat,
00271                       std::ifstream & inputFile,
00272                       Scalar reltol,
00273                       int iprint,
00274                       TypeOfExactData analyticDataType = INTREPID_UTILS_FRACTION);
00275 
00276 
00277 
00287 template<class Scalar>
00288 void getAnalytic(Teuchos::Array< Teuchos::Array<Scalar> > & testMat,
00289                  std::ifstream & inputFile,
00290                  TypeOfExactData analyticDataType = INTREPID_UTILS_FRACTION);
00291 
00301 template<class Scalar>
00302 void getAnalytic(Scalar * testMat,
00303                  std::ifstream & inputFile,
00304                  TypeOfExactData analyticDataType = INTREPID_UTILS_FRACTION);
00305 
00306 
00307 
00308 /***************************************************************************************************
00309  *                                                                                                 *
00310  *     Utility functions for checking requirements on ranks and dimensions of array arguments      *
00311  *                                                                                                 *
00312  ***************************************************************************************************/
00313 
00314   
00324   template<class Array>
00325   bool requireRankRange(std::string&   errmsg,
00326                         const Array&   array, 
00327                         const int      lowerBound, 
00328                         const int      upperBound);
00329 
00330   
00331   
00340   template<class Array1, class Array2>
00341   bool requireRankMatch(std::string&   errmsg, 
00342                         const Array1&  array1, 
00343                         const Array2&  array2);
00344 
00345 
00346   
00357   template<class Array>
00358   bool requireDimensionRange(std::string&  errmsg,
00359                              const Array&  array,
00360                              const int     dim,
00361                              const int     lowerBound,
00362                              const int     upperBound);
00363 
00364 
00365   
00376   template<class Array1, class Array2>
00377   bool requireDimensionMatch(std::string&   errmsg,
00378                              const Array1&  array1, 
00379                              const int      a1_dim0,
00380                              const Array2&  array2, 
00381                              const int      a2_dim0);
00382 
00383 
00384   
00397   template<class Array1, class Array2>
00398   bool requireDimensionMatch(std::string&   errmsg,
00399                              const Array1&  array1, 
00400                              const int      a1_dim0, const int a1_dim1,
00401                              const Array2&  array2, 
00402                              const int      a2_dim0, const int a2_dim1);
00403 
00404 
00405   
00420   template<class Array1, class Array2>
00421   bool requireDimensionMatch(std::string&   errmsg,
00422                              const Array1&  array1, 
00423                              const int      a1_dim0, const int a1_dim1, const int a1_dim2,
00424                              const Array2&  array2, 
00425                              const int      a2_dim0, const int a2_dim1, const int a2_dim2);
00426 
00427   
00428 
00445   template<class Array1, class Array2>
00446   bool requireDimensionMatch(std::string&   errmsg,
00447                              const Array1&  array1, 
00448                              const int      a1_dim0, const int a1_dim1, const int a1_dim2, const int a1_dim3,
00449                              const Array2&  array2, 
00450                              const int      a2_dim0, const int a2_dim1, const int a2_dim2, const int a2_dim3);
00451 
00452 
00453   
00472   template<class Array1, class Array2>
00473   bool requireDimensionMatch(std::string&   errmsg,
00474                              const Array1&  array1, 
00475                              const int      a1_dim0, const int a1_dim1, 
00476                              const int      a1_dim2, const int a1_dim3, const int a1_dim4,
00477                              const Array2&  array2, 
00478                              const int      a2_dim0, const int a2_dim1, 
00479                              const int      a2_dim2, const int a2_dim3, const int a2_dim4);
00480 
00481 
00482   
00491   template<class Array1, class Array2>
00492   bool requireDimensionMatch(std::string&   errmsg,
00493                              const Array1&  array1,
00494                              const Array2&  array2);
00495 
00496 
00497 
00498 /***************************************************************************************************
00499  ***************************************************************************************************
00500  **                                                                                               **
00501  **                           Definitions of templated functions                                  **
00502  **                                                                                               **
00503  ***************************************************************************************************
00504  ***************************************************************************************************/
00505 
00506 
00507 /***************************************************************************************************
00508  *                                                                                                 *
00509  *               Utility functions for handling external data in tests                             *
00510  *                                                                                                 *
00511  ***************************************************************************************************/
00512 
00513 template<class Scalar>
00514 int compareToAnalytic(const Teuchos::Array< Teuchos::Array<Scalar> > testMat,
00515                       std::ifstream & inputFile,
00516                       Scalar reltol,
00517                       int iprint,
00518                       TypeOfExactData analyticDataType ) {
00519   
00520   // This little trick lets us print to std::cout only if
00521   // iprint > 0.
00522   Teuchos::RCP<std::ostream> outStream;
00523   Teuchos::oblackholestream bhs; // outputs nothing
00524   if (iprint > 0)
00525     outStream = Teuchos::rcp(&std::cout, false);
00526   else
00527     outStream = Teuchos::rcp(&bhs, false);
00528   
00529   // Save the format state of the original std::cout.
00530   Teuchos::oblackholestream oldFormatState;
00531   oldFormatState.copyfmt(std::cout);
00532   
00533   std::string line;
00534   std::string chunk;
00535   Scalar testentry;
00536   Scalar abstol;
00537   Scalar absdiff;
00538   int i=0, j=0;
00539   int err = 0;
00540   
00541   while (! inputFile.eof() )
00542     {
00543     std::getline (inputFile,line);
00544     std::istringstream linestream(line);
00545     std::string chunk;
00546     j = 0;
00547     while( linestream >> chunk ) {
00548       int num1;
00549       int num2;
00550       std::string::size_type loc = chunk.find( "/", 0);
00551       if( loc != std::string::npos ) {
00552         chunk.replace( loc, 1, " ");
00553         std::istringstream chunkstream(chunk);
00554         chunkstream >> num1;
00555         chunkstream >> num2;
00556         testentry = (Scalar)(num1)/(Scalar)(num2);
00557         abstol = ( std::fabs(testentry) < reltol ? reltol : std::fabs(reltol*testentry) );
00558         absdiff = std::fabs(testentry - testMat[i][j]);
00559         if (absdiff > abstol) {
00560           err++;
00561           *outStream << "FAILURE --> ";
00562         }
00563         *outStream << "entry[" << i << "," << j << "]:" << "   "
00564           << testMat[i][j] << "   " << num1 << "/" << num2 << "   "
00565           << absdiff << "   " << "<?" << "   " << abstol << "\n";
00566       }
00567       else {
00568         std::istringstream chunkstream(chunk);
00569         if (analyticDataType == INTREPID_UTILS_FRACTION) {
00570           chunkstream >> num1;
00571           testentry = (Scalar)(num1);
00572         }
00573         else if (analyticDataType == INTREPID_UTILS_SCALAR)
00574           chunkstream >> testentry;
00575         abstol = ( std::fabs(testentry) < reltol ?reltol : std::fabs(reltol*testentry) );
00576         absdiff = std::fabs(testentry - testMat[i][j]);
00577         if (absdiff > abstol) {
00578           err++;
00579           *outStream << "FAILURE --> ";
00580         }
00581         *outStream << "entry[" << i << "," << j << "]:" << "   "
00582           << testMat[i][j] << "   " << testentry << "   "
00583           << absdiff << "   " << "<?" << "   " << abstol << "\n";
00584       }
00585       j++;
00586     }
00587     i++;
00588     }
00589   
00590   // reset format state of std::cout
00591   std::cout.copyfmt(oldFormatState);
00592   
00593   return err;
00594 } // end compareToAnalytic
00595 
00596 
00597 
00598 template<class Scalar>
00599 int compareToAnalytic(const Scalar * testMat,
00600                       std::ifstream & inputFile,
00601                       Scalar reltol,
00602                       int iprint,
00603                       TypeOfExactData analyticDataType ) {
00604   
00605   // This little trick lets us print to std::cout only if
00606   // iprint > 0.
00607   Teuchos::RCP<std::ostream> outStream;
00608   Teuchos::oblackholestream bhs; // outputs nothing
00609   if (iprint > 0)
00610     outStream = Teuchos::rcp(&std::cout, false);
00611   else
00612     outStream = Teuchos::rcp(&bhs, false);
00613   
00614   // Save the format state of the original std::cout.
00615   Teuchos::oblackholestream oldFormatState;
00616   oldFormatState.copyfmt(std::cout);
00617   
00618   std::string line;
00619   std::string chunk;
00620   Scalar testentry;
00621   Scalar abstol;
00622   Scalar absdiff;
00623   int i=0, j=0, offset=0;
00624   int err = 0;
00625   
00626   while (! inputFile.eof() )
00627     {
00628     std::getline (inputFile,line);
00629     std::istringstream linestream(line);
00630     std::string chunk;
00631     j = 0;
00632     while( linestream >> chunk ) {
00633       int num1;
00634       int num2;
00635       std::string::size_type loc = chunk.find( "/", 0);
00636       if( loc != std::string::npos ) {
00637         chunk.replace( loc, 1, " ");
00638         std::istringstream chunkstream(chunk);
00639         chunkstream >> num1;
00640         chunkstream >> num2;
00641         testentry = (Scalar)(num1)/(Scalar)(num2);
00642         abstol = ( std::fabs(testentry) < reltol ? reltol : std::fabs(reltol*testentry) );
00643         absdiff = std::fabs(testentry - testMat[i*offset+j]);
00644         if (absdiff > abstol) {
00645           err++;
00646           *outStream << "FAILURE --> ";
00647         }
00648         *outStream << "entry[" << i << "," << j << "]:" << "   "
00649           << testMat[i*offset+j] << "   " << num1 << "/" << num2 << "   "
00650           << absdiff << "   " << "<?" << "   " << abstol << "\n";
00651       }
00652       else {
00653         std::istringstream chunkstream(chunk);
00654         if (analyticDataType == INTREPID_UTILS_FRACTION) {
00655           chunkstream >> num1;
00656           testentry = (Scalar)(num1);
00657         }
00658         else if (analyticDataType == INTREPID_UTILS_SCALAR)
00659           chunkstream >> testentry;
00660         abstol = ( std::fabs(testentry) < reltol ?reltol : std::fabs(reltol*testentry) );
00661         absdiff = std::fabs(testentry - testMat[i*offset+j]);
00662         if (absdiff > abstol) {
00663           err++;
00664           *outStream << "FAILURE --> ";
00665         }
00666         *outStream << "entry[" << i << "," << j << "]:" << "   "
00667           << testMat[i*offset+j] << "   " << testentry << "   "
00668           << absdiff << "   " << "<?" << "   " << abstol << "\n";
00669       }
00670       j++;
00671     }
00672     i++;
00673     offset = j;
00674     }
00675   
00676   // reset format state of std::cout
00677   std::cout.copyfmt(oldFormatState);
00678   
00679   return err;
00680 } // end compareToAnalytic
00681 
00682 
00683 
00684 template<class Scalar>
00685 void getAnalytic(Teuchos::Array< Teuchos::Array<Scalar> > & testMat,
00686                  std::ifstream & inputFile,
00687                  TypeOfExactData analyticDataType ) {
00688   
00689   // Save the format state of the original std::cout.
00690   Teuchos::oblackholestream oldFormatState;
00691   oldFormatState.copyfmt(std::cout);
00692   
00693   std::string line;
00694   std::string chunk;
00695   Scalar testentry;
00696   int i=0, j=0;
00697   
00698   while (! inputFile.eof() )
00699     {
00700     std::getline (inputFile,line);
00701     std::istringstream linestream(line);
00702     std::string chunk;
00703     j = 0;
00704     while( linestream >> chunk ) {
00705       int num1;
00706       int num2;
00707       std::string::size_type loc = chunk.find( "/", 0);
00708       if( loc != std::string::npos ) {
00709         chunk.replace( loc, 1, " ");
00710         std::istringstream chunkstream(chunk);
00711         chunkstream >> num1;
00712         chunkstream >> num2;
00713         testentry = (Scalar)(num1)/(Scalar)(num2);
00714         testMat[i][j] = testentry;
00715       }
00716       else {
00717         std::istringstream chunkstream(chunk);
00718         if (analyticDataType == INTREPID_UTILS_FRACTION) {
00719           chunkstream >> num1;
00720           testentry = (Scalar)(num1);
00721         }
00722         else if (analyticDataType == INTREPID_UTILS_SCALAR)
00723           chunkstream >> testentry;
00724         testMat[i][j] = testentry;
00725       }
00726       j++;
00727     }
00728     i++;
00729     }
00730   
00731   // reset format state of std::cout
00732   std::cout.copyfmt(oldFormatState);
00733 } // end getAnalytic
00734 
00735 
00736 
00737 template<class Scalar>
00738 void getAnalytic(Scalar * testMat,
00739                  std::ifstream & inputFile,
00740                  TypeOfExactData analyticDataType) {
00741   
00742   // Save the format state of the original std::cout.
00743   Teuchos::oblackholestream oldFormatState;
00744   oldFormatState.copyfmt(std::cout);
00745   
00746   std::string line;
00747   std::string chunk;
00748   Scalar testentry;
00749   int i=0, j=0, offset=0;
00750   
00751   while (! inputFile.eof() )
00752     {
00753     std::getline (inputFile,line);
00754     std::istringstream linestream(line);
00755     std::string chunk;
00756     j = 0;
00757     while( linestream >> chunk ) {
00758       int num1;
00759       int num2;
00760       std::string::size_type loc = chunk.find( "/", 0);
00761       if( loc != std::string::npos ) {
00762         chunk.replace( loc, 1, " ");
00763         std::istringstream chunkstream(chunk);
00764         chunkstream >> num1;
00765         chunkstream >> num2;
00766         testentry = (Scalar)(num1)/(Scalar)(num2);
00767         testMat[i*offset+j] = testentry;
00768       }
00769       else {
00770         std::istringstream chunkstream(chunk);
00771         if (analyticDataType == INTREPID_UTILS_FRACTION) {
00772           chunkstream >> num1;
00773           testentry = (Scalar)(num1);
00774         }
00775         else if (analyticDataType == INTREPID_UTILS_SCALAR)
00776           chunkstream >> testentry;
00777         testMat[i*offset+j] = testentry;
00778       }
00779       j++;
00780     }
00781     i++;
00782     offset = j;
00783     }
00784   
00785   // reset format state of std::cout
00786   std::cout.copyfmt(oldFormatState);
00787 } // end getAnalytic
00788 
00789 
00790 /***************************************************************************************************
00791  *                                                                                                 *
00792  *     Utility functions for checking requirements on ranks and dimensions of array arguments      *
00793  *                                                                                                 *
00794  ***************************************************************************************************/
00795 
00796 
00797 template<class Array>
00798 bool requireRankRange(std::string&   errmsg,
00799                       const Array&   array, 
00800                       const int      lowerBound, 
00801                       const int      upperBound){
00802   
00803   TEST_FOR_EXCEPTION( (lowerBound > upperBound) , std::invalid_argument,
00804                       ">>> ERROR (Intrepid_Utils::requireRankRange): lowerBound <= upperBound required!");
00805   
00806   bool OK = true;
00807   if( (lowerBound == upperBound) && !(array.rank() == lowerBound) ) {
00808     errmsg += "\n>>> Array rank = ";
00809     errmsg += (char)(48 + array.rank() );
00810     errmsg += " while rank-";
00811     errmsg += (char) (48 + lowerBound);
00812     errmsg += " array required.";
00813     OK = false;
00814   }
00815   else if ( (lowerBound < upperBound) &&  !( (lowerBound <= array.rank() ) && (array.rank() <= upperBound)  ) ){
00816     errmsg += "\n>>> Array rank = ";
00817     errmsg += (char)(48 + array.rank() );
00818     errmsg += " while a rank between ";
00819     errmsg += (char) (48 + lowerBound);
00820     errmsg += " and ";
00821     errmsg += (char) (48 + upperBound);
00822     errmsg += " is required.";
00823     OK = false;
00824   }
00825   return OK;
00826 }
00827 
00828 
00829 template<class Array1, class Array2>
00830 bool requireRankMatch(std::string&   errmsg, 
00831                       const Array1&  array1, 
00832                       const Array2&  array2){    
00833   bool OK = true;
00834   if(array1.rank() != array2.rank() ) {
00835     errmsg += "\n>>> Array ranks are required to match.";
00836     OK = false; 
00837   }
00838   return OK;
00839 }
00840 
00841 
00842 template<class Array>
00843 bool requireDimensionRange(std::string&  errmsg,
00844                            const Array&  array,
00845                            const int     dim,
00846                            const int     lowerBound,
00847                            const int     upperBound){
00848   
00849   TEST_FOR_EXCEPTION( (lowerBound > upperBound) , std::invalid_argument,
00850                       ">>> ERROR (Intrepid_Utils::requireDimensionRange): lowerBound <= upperBound required!");
00851   TEST_FOR_EXCEPTION( !( (0 <= dim) && (dim < array.rank() ) ), 
00852                       std::invalid_argument,
00853                       ">>> ERROR (Intrepid_Utils::requireDimensionRange): 0 <= dim < array.rank() required!");
00854   
00855   bool OK = true;
00856   if( (lowerBound > upperBound) || ( dim >= array.rank() ) ) {
00857     errmsg += "\n>>> Unexpected error: ";
00858     OK = false;
00859   }  
00860   if( (lowerBound == upperBound) && !(array.dimension(dim) == lowerBound) ) {
00861     errmsg += "\n>>> dimension(";
00862     errmsg += (char)(48 + dim);
00863     errmsg += ") = ";
00864     errmsg += (char)(48 + array.dimension(dim) );
00865     errmsg += " while dimension(";
00866     errmsg += (char)(48 + dim);
00867     errmsg += ") = ";
00868     errmsg += (char)(48 + lowerBound);
00869     errmsg += " required.";
00870     OK = false;
00871   }
00872   else if( (lowerBound < upperBound) && 
00873            !( (lowerBound <= array.dimension(dim) ) && (array.dimension(dim) <= upperBound) ) ){
00874     errmsg += "\n>>> dimension(";
00875     errmsg += (char)(48 + dim);
00876     errmsg += ") = ";
00877     errmsg += (char)(48 + array.dimension(dim) );
00878     errmsg += " while ";
00879     errmsg += (char)(48 + lowerBound);
00880     errmsg += " <= dimension(";
00881     errmsg += (char)(48 + dim);
00882     errmsg += ") <= ";
00883     errmsg +=(char)(48 + upperBound);
00884     errmsg +=" required.";
00885     OK = false;
00886   }
00887   return OK;
00888 }
00889 
00890 
00891 
00892 template<class Array1, class Array2>
00893 bool requireDimensionMatch(std::string&   errmsg,
00894                            const Array1&  array1,
00895                            const int      a1_dim0,
00896                            const Array2&  array2, 
00897                            const int      a2_dim0){
00898   
00899   TEST_FOR_EXCEPTION( !( (0 <= a1_dim0) && (a1_dim0 < array1.rank() ) ), 
00900                       std::invalid_argument,
00901                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a1_dim0 < array1.rank() required!");
00902   TEST_FOR_EXCEPTION( !( (0 <= a2_dim0) && (a2_dim0 < array2.rank() ) ),
00903                       std::invalid_argument,
00904                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a2_dim0 < array2.rank() required!");
00905 
00906   bool OK = true;
00907   if(array1.dimension(a1_dim0) != array2.dimension(a2_dim0) ){
00908     errmsg += "\n>>> dimension(";
00909     errmsg += (char)(48 + a1_dim0);
00910     errmsg += ") of 1st array and dimension(";
00911     errmsg += (char)(48 + a2_dim0);
00912     errmsg += ") of 2nd array are required to match.";
00913     OK = false;
00914   }
00915   return OK;
00916 }
00917 
00918 
00919 
00920 template<class Array1, class Array2>
00921 bool requireDimensionMatch(std::string&   errmsg,
00922                            const Array1&  array1, 
00923                            const int      a1_dim0, const int a1_dim1,
00924                            const Array2&  array2, 
00925                            const int      a2_dim0, const int a2_dim1){
00926   
00927   TEST_FOR_EXCEPTION( !( (0 <= a1_dim0) && (a1_dim0 < array1.rank() ) ), 
00928                       std::invalid_argument,
00929                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a1_dim0 < array1.rank() required!");
00930   TEST_FOR_EXCEPTION( !( (0 <= a1_dim1) && (a1_dim1 < array1.rank() ) ), 
00931                       std::invalid_argument,
00932                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a1_dim1 < array1.rank() required!");
00933   TEST_FOR_EXCEPTION( !( (0 <= a2_dim0) && (a2_dim0 < array2.rank() ) ),
00934                       std::invalid_argument,
00935                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a2_dim0 < array2.rank() required!");
00936   TEST_FOR_EXCEPTION( !( (0 <= a2_dim1) && (a2_dim1 < array2.rank() ) ),
00937                       std::invalid_argument,
00938                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a2_dim1 < array2.rank() required!");
00939  
00940   bool OK = true;
00941   if( !requireDimensionMatch(errmsg, array1, a1_dim0, array2, a2_dim0) ){
00942     OK = false;
00943   }
00944   if( !requireDimensionMatch(errmsg, array1, a1_dim1, array2, a2_dim1) ){
00945     OK = false;
00946   }
00947   return OK;
00948 }
00949 
00950 
00951 
00952 template<class Array1, class Array2>
00953 bool requireDimensionMatch(std::string&   errmsg,
00954                            const Array1&  array1, 
00955                            const int      a1_dim0, const int a1_dim1, const int a1_dim2,
00956                            const Array2&  array2, 
00957                            const int      a2_dim0, const int a2_dim1, const int a2_dim2){
00958   
00959   TEST_FOR_EXCEPTION( !( (0 <= a1_dim0) && (a1_dim0 < array1.rank() ) ), 
00960                       std::invalid_argument,
00961                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a1_dim0 < array1.rank() required!");
00962   TEST_FOR_EXCEPTION( !( (0 <= a1_dim1) && (a1_dim1 < array1.rank() ) ), 
00963                       std::invalid_argument,
00964                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a1_dim1 < array1.rank() required!");
00965   TEST_FOR_EXCEPTION( !( (0 <= a1_dim2) && (a1_dim2 < array1.rank() ) ), 
00966                       std::invalid_argument,
00967                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a1_dim2 < array1.rank() required!");
00968   TEST_FOR_EXCEPTION( !( (0 <= a2_dim0) && (a2_dim0 < array2.rank() ) ),
00969                       std::invalid_argument,
00970                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a2_dim0 < array2.rank() required!");
00971   TEST_FOR_EXCEPTION( !( (0 <= a2_dim1) && (a2_dim1 < array2.rank() ) ),
00972                       std::invalid_argument,
00973                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a2_dim1 < array2.rank() required!");
00974   TEST_FOR_EXCEPTION( !( (0 <= a2_dim2) && (a2_dim2 < array2.rank() ) ),
00975                       std::invalid_argument,
00976                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a2_dim2 < array2.rank() required!");
00977   
00978   
00979   bool OK = true;
00980   if( !requireDimensionMatch(errmsg, array1, a1_dim0, array2, a2_dim0) ){
00981     OK = false;
00982   }
00983   if( !requireDimensionMatch(errmsg, array1, a1_dim1, array2, a2_dim1) ){
00984     OK = false;
00985   }
00986   if( !requireDimensionMatch(errmsg, array1, a1_dim2, array2, a2_dim2) ){
00987     OK = false;
00988   }
00989   return OK;
00990 }
00991 
00992 
00993 
00994 template<class Array1, class Array2>
00995 bool requireDimensionMatch(std::string&   errmsg,
00996                            const Array1&  array1, 
00997                            const int      a1_dim0, const int a1_dim1, const int a1_dim2, const int a1_dim3,
00998                            const Array2&  array2, 
00999                            const int      a2_dim0, const int a2_dim1, const int a2_dim2, const int a2_dim3){
01000   
01001   TEST_FOR_EXCEPTION( !( (0 <= a1_dim0) && (a1_dim0 < array1.rank() ) ), 
01002                       std::invalid_argument,
01003                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a1_dim0 < array1.rank() required!");
01004   TEST_FOR_EXCEPTION( !( (0 <= a1_dim1) && (a1_dim1 < array1.rank() ) ), 
01005                       std::invalid_argument,
01006                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a1_dim1 < array1.rank() required!");
01007   TEST_FOR_EXCEPTION( !( (0 <= a1_dim2) && (a1_dim2 < array1.rank() ) ), 
01008                       std::invalid_argument,
01009                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a1_dim2 < array1.rank() required!");
01010   TEST_FOR_EXCEPTION( !( (0 <= a1_dim3) && (a1_dim3 < array1.rank() ) ), 
01011                       std::invalid_argument,
01012                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a1_dim3 < array1.rank() required!");
01013   TEST_FOR_EXCEPTION( !( (0 <= a2_dim0) && (a2_dim0 < array2.rank() ) ),
01014                       std::invalid_argument,
01015                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a2_dim0 < array2.rank() required!");
01016   TEST_FOR_EXCEPTION( !( (0 <= a2_dim1) && (a2_dim1 < array2.rank() ) ),
01017                       std::invalid_argument,
01018                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a2_dim1 < array2.rank() required!");
01019   TEST_FOR_EXCEPTION( !( (0 <= a2_dim2) && (a2_dim2 < array2.rank() ) ),
01020                       std::invalid_argument,
01021                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a2_dim2 < array2.rank() required!");
01022   TEST_FOR_EXCEPTION( !( (0 <= a2_dim3) && (a2_dim3 < array2.rank() ) ),
01023                       std::invalid_argument,
01024                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a2_dim3 < array2.rank() required!");
01025   bool OK = true;
01026   if( !requireDimensionMatch(errmsg, array1, a1_dim0, array2, a2_dim0) ){
01027     OK = false;
01028   }
01029   if( !requireDimensionMatch(errmsg, array1, a1_dim1, array2, a2_dim1) ){
01030     OK = false;
01031   }
01032   if( !requireDimensionMatch(errmsg, array1, a1_dim2, array2, a2_dim2) ){
01033     OK = false;
01034   }
01035   if( !requireDimensionMatch(errmsg, array1, a1_dim3, array2, a2_dim3) ){
01036     OK = false;
01037   }
01038   return OK;
01039 }
01040 
01041 
01042 
01043 template<class Array1, class Array2>
01044 bool requireDimensionMatch(std::string&   errmsg,
01045                            const Array1&  array1, 
01046                            const int      a1_dim0, const int a1_dim1, const int a1_dim2, 
01047                            const int      a1_dim3, const int a1_dim4,
01048                            const Array2&  array2, 
01049                            const int      a2_dim0, const int a2_dim1, const int a2_dim2, 
01050                            const int      a2_dim3, const int a2_dim4){
01051   
01052   TEST_FOR_EXCEPTION( !( (0 <= a1_dim0) && (a1_dim0 < array1.rank() ) ), 
01053                       std::invalid_argument,
01054                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a1_dim0 < array1.rank() required!");
01055   TEST_FOR_EXCEPTION( !( (0 <= a1_dim1) && (a1_dim1 < array1.rank() ) ), 
01056                       std::invalid_argument,
01057                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a1_dim1 < array1.rank() required!");
01058   TEST_FOR_EXCEPTION( !( (0 <= a1_dim2) && (a1_dim2 < array1.rank() ) ), 
01059                       std::invalid_argument,
01060                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a1_dim2 < array1.rank() required!");
01061   TEST_FOR_EXCEPTION( !( (0 <= a1_dim3) && (a1_dim3 < array1.rank() ) ), 
01062                       std::invalid_argument,
01063                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a1_dim3 < array1.rank() required!");
01064   TEST_FOR_EXCEPTION( !( (0 <= a1_dim4) && (a1_dim4 < array1.rank() ) ), 
01065                       std::invalid_argument,
01066                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a1_dim4 < array1.rank() required!");
01067   TEST_FOR_EXCEPTION( !( (0 <= a2_dim0) && (a2_dim0 < array2.rank() ) ),
01068                       std::invalid_argument,
01069                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a2_dim0 < array2.rank() required!");
01070   TEST_FOR_EXCEPTION( !( (0 <= a2_dim1) && (a2_dim1 < array2.rank() ) ),
01071                       std::invalid_argument,
01072                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a2_dim1 < array2.rank() required!");
01073   TEST_FOR_EXCEPTION( !( (0 <= a2_dim2) && (a2_dim2 < array2.rank() ) ),
01074                       std::invalid_argument,
01075                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a2_dim2 < array2.rank() required!");
01076   TEST_FOR_EXCEPTION( !( (0 <= a2_dim3) && (a2_dim3 < array2.rank() ) ),
01077                       std::invalid_argument,
01078                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a2_dim3 < array2.rank() required!");
01079   TEST_FOR_EXCEPTION( !( (0 <= a2_dim4) && (a2_dim4 < array2.rank() ) ),
01080                       std::invalid_argument,
01081                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): 0 <= a2_dim4 < array2.rank() required!");
01082   
01083   bool OK = true;
01084   if( !requireDimensionMatch(errmsg, array1, a1_dim0, array2, a2_dim0) ){
01085     OK = false;
01086   }
01087   if( !requireDimensionMatch(errmsg, array1, a1_dim1, array2, a2_dim1) ){
01088     OK = false;
01089   }
01090   if( !requireDimensionMatch(errmsg, array1, a1_dim2, array2, a2_dim2) ){
01091     OK = false;
01092   }
01093   if( !requireDimensionMatch(errmsg, array1, a1_dim3, array2, a2_dim3) ){
01094     OK = false;
01095   }
01096   if( !requireDimensionMatch(errmsg, array1, a1_dim4, array2, a2_dim4) ){
01097     OK = false;
01098   }
01099   return OK;
01100 }
01101 
01102 
01103 
01104 template<class Array1, class Array2>
01105 bool requireDimensionMatch(std::string&   errmsg,
01106                            const Array1&  array1,
01107                            const Array2&  array2){
01108   
01109   TEST_FOR_EXCEPTION( !requireRankMatch(errmsg, array1, array2 ), std::invalid_argument,
01110                       ">>> ERROR (Intrepid_Utils::requireDimensionMatch): Arrays with equal ranks are required to test for all dimensions match." )
01111   
01112   bool OK = true;  
01113   for(int dim = 0; dim < array1.rank(); dim++){
01114     if( !requireDimensionMatch(errmsg, array1, dim, array2, dim) ){
01115       OK = false;
01116       break;
01117     }
01118   } 
01119   return OK;
01120 }
01121 
01122 
01123 } // end namespace Intrepid
01124 
01125 #endif