|
Intrepid
|
00001 // @HEADER 00002 // ************************************************************************ 00003 // 00004 // Intrepid Package 00005 // Copyright (2007) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 00009 // 00010 // 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
1.7.4