This file is indexed.

/usr/include/trilinos/Intrepid_FieldContainer.hpp is in libtrilinos-intrepid-dev 12.4.2-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
// @HEADER
// ************************************************************************
//
//                           Intrepid Package
//                 Copyright (2007) Sandia Corporation
//
// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
// license for use of this work by or on behalf of the U.S. Government.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the Corporation nor the names of the
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Questions? Contact Pavel Bochev  (pbboche@sandia.gov)
//                    Denis Ridzal  (dridzal@sandia.gov), or
//                    Kara Peterson (kjpeter@sandia.gov)
//
// ************************************************************************
// @HEADER

/** \file   Intrepid_FieldContainer.hpp
    \brief  Header file for utility class to provide multidimensional containers.
    \author Created by P. Bochev and D. Ridzal.
*/

#ifndef INTREPID_FIELDCONTAINER_HPP
#define INTREPID_FIELDCONTAINER_HPP

#include "Intrepid_ConfigDefs.hpp"
#include "Intrepid_Types.hpp"
#include "Intrepid_Utils.hpp"
#include "Teuchos_Array.hpp"
#include "Teuchos_ArrayRCP.hpp"
#include "Teuchos_ArrayView.hpp"
#include "Shards_Array.hpp"
#include "Teuchos_RCP.hpp"
#include "Teuchos_BLAS.hpp"
#include "Teuchos_oblackholestream.hpp"
#include "Teuchos_Assert.hpp"

namespace Intrepid {
  
  /** \class Intrepid::FieldContainer
  \brief Implementation of a templated lexicographical container for a multi-indexed scalar quantity. 
  FieldContainer object stores a multi-indexed scalar value using the lexicographical index ordering: the
  rightmost index changes first and the leftmost index changes last. FieldContainer can be viewed
  as a dynamic multidimensional array whose values can be accessed in two ways: by their
  multi-index or by their enumeration, using an overloaded [] operator. The enumeration of a value
  gives the sequential order of the multi-indexed value in the container. The number of indices, i.e.,
  the rank of the container is unlimited. For containers with ranks up to 5 many of the methods are 
  optimized for faster execution. An overloaded () operator is also provided for such low-rank containers
  to allow element access by multi-index without having to create an auxiliary array for the multi-index.
  */
  template<class Scalar, int ArrayTypeId=0>
  class FieldContainer {
  public:
    //! The template parameter of this class; the type of objects stored.
    typedef Scalar scalar_type;

  protected:
    
    /** \brief Array to store the multi-indexed quantity 
    */
    Teuchos::ArrayRCP<Scalar> data_;

    typedef typename Teuchos::ArrayRCP<Scalar>::iterator data_ptr_t;
    data_ptr_t data_ptr_;    

    /**\brief Array to store dimensions (dimensions) for the multi-indices. Admissible range (dimension)
     for  the k-th index is <var>0 <= i_k < dimensions_[k]</var>. Size of this array defines the rank of 
     the multi-indexed quantity, i.e., the number of its indices.  
    */
    Teuchos::Array<int> dimensions_;
    
    /** \brief 1st dimension of the array */
    int dim0_;
    
    /** \brief 2nd dimension of the array */
    int dim1_;
    
    /** \brief 3rd dimension of the array */
    int dim2_;
    
    /** \brief 4th dimension of the array */
    int dim3_;
    
    /** \brief 5th dimension of the array */
    int dim4_;
    
  public:
    

    /** \brief Default destructor.
    */
    ~FieldContainer() {};
    
    
    /** \brief Default constructor.
    */
    FieldContainer() : dim0_(0), dim1_(0), dim2_(0), dim3_(0), dim4_(0) 
    {
      data_.resize(0);
      data_ptr_ = Teuchos::NullIteratorTraits<data_ptr_t>::getNull();
      dimensions_.resize(0);
    } ;
    
    
    /** \brief Copy constructor.
    */
    FieldContainer(const FieldContainer& right);
 
    
    /** \brief Creates a rank-1 FieldContainer with the specified dimension, initialized by 0.
      
      \param dim0    [in]      - dimension for the only index 
    */
    FieldContainer(const int dim0);
    
    
    /** \brief Creates a rank-2 FieldContainer with the specified dimensions, initialized by 0.
      
      \param dim0    [in]      - dimension for the 1st index 
      \param dim1    [in]      - dimension for the 2nd index 
    */
    FieldContainer(const int dim0,
                   const int dim1);

    
    /** \brief Creates a rank-3 FieldContainer with the specified dimensions, initialized by 0.
      
      \param dim0    [in]      - dimension for the 1st index 
      \param dim1    [in]      - dimension for the 2nd index 
      \param dim2    [in]      - dimension for the 3rd index 
    */
    FieldContainer(const int dim0,
                   const int dim1,
                   const int dim2);

    
    /** \brief Creates a rank-4 FieldContainer with the specified dimensions, initialized by 0.
      
      \param dim0    [in]      - dimension for the 1st index 
      \param dim1    [in]      - dimension for the 2nd index 
      \param dim2    [in]      - dimension for the 3rd index 
      \param dim3    [in]      - dimension for the 4th index 
    */
    FieldContainer(const int dim0,
                   const int dim1,
                   const int dim2,
                   const int dim3);
    
    
    /** \brief Creates a rank-5 FieldContainer with the specified dimensions, initialized by 0.
      
      \param dim0    [in]      - dimension for the 1st index 
      \param dim1    [in]      - dimension for the 2nd index 
      \param dim2    [in]      - dimension for the 3rd index 
      \param dim3    [in]      - dimension for the 4th index 
      \param dim4    [in]      - dimension for the 5th index 
    */
    FieldContainer(const int dim0,
                   const int dim1,
                   const int dim2,
                   const int dim3,
                   const int dim4);
    
    
    /** \brief Creates a  FieldContainer of arbitrary rank,, initialized by 0, using dimensions 
      specified in an array. The size of the input array implicitely defines the rank of the 
      container and its capacity is defined by the specified dimensions. 
      
      \param dimensions[in]           - array with container dimensions
    */
    FieldContainer(const Teuchos::Array<int>& dimensions);
    
    
    /** \brief Creates a FieldContainer of arbitrary rank, using dimensions specified in the
               <var><b>dimensions</b></var> array, and fills it by deep-copying data from a
               Teuchos::ArrayView array (which implicitly doubles as Teuchos::ArrayRCP or
               Teuchos::Array). If the input data array is a Teuchos::ArrayRCP, then '()' should
               be appended to it when calling this function. This forces direct conversion to a
               Teuchos::ArrayView, and prevents the call to the shallow-copy constructor that
               takes a Teuchos::ArrayRCP.
      
        \param dimensions[in]           - array with container dimensions
        \param data[in]                 - array with container values
    */
    FieldContainer(const Teuchos::Array<int>&        dimensions,
                   const Teuchos::ArrayView<Scalar>& data);


    /** \brief Creates a FieldContainer of arbitrary rank, using dimensions specified in the
               <var><b>dimensions</b></var> array, and wraps (shallow-copies) the data pointed
               to by the input Teuchos::ArrayRCP array. If a deep copy is desired instead,
               one can force the use of the constructor that takes Teuchos::ArrayView by
               appending () to the input Teuchos::ArrayRCP parameter. This forces direct
               conversion to a Teuchos::ArrayView.
      
        \param dimensions[in]           - array with container dimensions
        \param data[in]                 - array with container values
    */
    FieldContainer(const Teuchos::Array<int>&       dimensions,
                   const Teuchos::ArrayRCP<Scalar>& data);


    /** \brief Creates a FieldContainer of arbitrary rank, using dimensions specified in the
               <var><b>dimensions</b></var> array, and either wraps (shallow-copies) Scalar*
               <var><b>data</b></var>, or deep-copies it, based on the value of the parameter
               <var><b>deep_copy</b></var>. Memory management through FieldContainer, via
               its Teuchos::ArrayRCP data member, can be enabled.
      
        \param dimensions[in]           - array with container dimensions
        \param data[in]                 - array with container values
        \param deep_copy[in]            - if true, then deep-copy, otherwise shallow-copy; default: false
        \param owns_mem[in]             - if true, the field container will manage memory; default: false
    */
    FieldContainer(const Teuchos::Array<int>&    dimensions,
                   Scalar*                       data,
                   const bool                    deep_copy = false,
                   const bool                    owns_mem  = false);


    /** \brief Creates a FieldContainer either as a wrapper of the shards::Array<Scalar,shards::NaturalOrder>
               array <var><b>data</b></var>, or as its deep copy, based on the value of the parameter
               <var><b>deep_copy</b></var>. Memory management through FieldContainer, via
               its Teuchos::ArrayRCP data member, can be enabled.
      
        \param data[in]                 - array with container values
        \param deep_copy[in]            - if true, then deep-copy, otherwise shallow-copy; default: false
        \param owns_mem[in]             - if true, the field container will manage memory; default: false
    */
    FieldContainer(const shards::Array<Scalar,shards::NaturalOrder>&  data,
                   const bool                                         deep_copy = false,
                   const bool                                         owns_mem  = false);



    
    //--------------------------------------------------------------------------------------------//
    //                                                                                            //
    //                            Access methods of FieldContainer class                          //
    //                                                                                            //
    //--------------------------------------------------------------------------------------------//
    
    /** \brief Return rank of the FieldContainer = number of indices used to tag the multi-indexed value
      */
    int rank() const;
    
    
    /** \brief Returns size of the FieldContainer defined as the product of its dimensions.
      */
    int size() const;
    
    
    /** \brief Returns array with the dimensions of the container
      */
    template<class Vector>
    void dimensions(Vector& dimensions) const;
    
    
    /** \brief Returns the specified dimension
      
      \param whichDim     [in]      - order of the dimension we want to get
      */
    int dimension(const int whichDim) const;

    
    /** \brief Returns enumeration of a value (its order relative to the container), based on its 
      multi-index, for rank-1 containers. 
      
      \param i0         [in]        - 1st index
      */
    int getEnumeration(const int i0) const;
    
    
    /** \brief Returns enumeration of a value (its order relative to the container), based on its 
      multi-index, for rank-2 containers. 
      
      \param i0         [in]        - 1st index
      \param i1         [in]        - 2nd index
      */
    int getEnumeration(const int i0,
                       const int i1) const;
    
    
    /** \brief Returns enumeration of a value (its order relative to the container), based on its 
      multi-index, for rank-3 containers. 
      
      \param i0         [in]        - 1st index
      \param i1         [in]        - 2nd index
      \param i2         [in]        - 3rd index
      */
    int getEnumeration(const int i0,
                       const int i1,
                       const int i2) const;
 
    
    /** \brief Returns enumeration of a value (its order relative to the container), based on its 
      multi-index, for rank-4 containers. 
      
      \param i0         [in]        - 1st index
      \param i1         [in]        - 2nd index
      \param i2         [in]        - 3rd index
      \param i3         [in]        - 4th index
      */
    int getEnumeration(const int i0,
                       const int i1,
                       const int i2,
                       const int i3) const;
    
    
    /** \brief Returns enumeration of a value (its order relative to the container), based on its 
      multi-index, for rank-5 containers. 
      
      \param i0         [in]        - 1st index
      \param i1         [in]        - 2nd index
      \param i2         [in]        - 3rd index
      \param i3         [in]        - 4th index
      \param i4         [in]        - 5th index
      */
    int getEnumeration(const int i0,
                       const int i1,
                       const int i2,
                       const int i3,
                       const int i4) const;
    
        
    /** \brief Returns enumeration of a value (its order relative to the container), based on its 
      multi-index, for containers of arbitrary rank. 
      
      \param multiIndex   [in]      - array representing a multi-index
    */
    int getEnumeration(const Teuchos::Array<int>& multiIndex) const;
    
    
    /** \brief  Returns the multi-index of a value, based on its enumeration, as a list, for
      rank-1 containers.
      
      \param i0         [out]        - 1st index
      \param valueEnum  [in]         - enumeration of the value (its order relative to the container)      
    */
    void getMultiIndex(int &     i0,
                       const int valueEnum) const;
    
    
    /** \brief  Returns the multi-index of a value, based on its enumeration, as a list, for
      rank-2 containers.
      
      \param i0         [out]        - 1st index
      \param i1         [out]        - 2nd index
      \param valueEnum  [in]         - enumeration of the value (its order relative to the container)      
    */
    void getMultiIndex(int &     i0,
                       int &     i1,
                       const int valueEnum) const;
    
    
    /** \brief  Returns the multi-index of a value, based on its enumeration, as a list, for
      rank-3 containers.
      
      \param i0         [out]        - 1st index
      \param i1         [out]        - 2nd index
      \param i2         [out]        - 3rd index
      \param valueEnum  [in]         - enumeration of the value (its order relative to the container)      
      */
    void getMultiIndex(int &     i0,
                       int &     i1,
                       int &     i2,
                       const int valueEnum) const;
    
    
    /** \brief  Returns the multi-index of a value, based on its enumeration, as a list, for
      rank-4 containers.
      
      \param i0         [out]        - 1st index
      \param i1         [out]        - 2nd index
      \param i2         [out]        - 3rd index
      \param i3         [out]        - 4th index
      \param valueEnum  [in]         - enumeration of the value (its order relative to the container)      
      */
    void getMultiIndex(int &     i0,
                       int &     i1,
                       int &     i2,
                       int &     i3,
                       const int valueEnum) const;
    
    
    /** \brief  Returns the multi-index of a value, based on its enumeration, as a list, for
      rank-5 containers.
      
      \param i0         [out]        - 1st index
      \param i1         [out]        - 2nd index
      \param i2         [out]        - 3rd index
      \param i3         [out]        - 4th index
      \param i4         [out]        - 5th index
      \param valueEnum  [in]         - enumeration of the value (its order relative to the container)      
      */
    void getMultiIndex(int &     i0,
                       int &     i1,
                       int &     i2,
                       int &     i3,
                       int &     i4,
                       const int valueEnum) const;
    
    
    /** \brief Returns the multi-index of a value, based on its enumeration, as a vector, for
      containers of arbitrary rank. The template argument must support the following subset of
      std::vector interface:
      \li   Vector.size()
      \li   Vector.resize()
      \li   Vector[]
      
      \param multiIndex   [out]       - vector containg multi-index of the specified enumeration
      \param valueEnum    [in]        - enumeration of the value (its order relative to the container)
    */
    template<class Vector>
    void getMultiIndex(Vector&    multiIndex,
                       const int  valueEnum) const;
    
    //--------------------------------------------------------------------------------------------//
    //                                                                                            //
    //                          Methods to shape (resize) a field container                       //
    //                                                                                            //
    //--------------------------------------------------------------------------------------------//
    
    
    /** \brief Clears FieldContainer to trivial container (one with rank = 0 and size = 0)
    */
    void clear();
    
    
    /** \brief Resizes FieldContainer to a rank-1 container with the specified dimension, initialized by 0. 
      
      \param dim0    [in]      - dimension for the 1st index 
    */
    void resize(const int dim0);
    
    
    /** \brief Resizes FieldContainer to a rank-2 container with specified dimensions, initialized by 0. 

      \param dim0    [in]      - dimension for the 1st index 
      \param dim1    [in]      - dimension for the 2nd index 
    */
    void resize(const int dim0,
                const int dim1);
    
    
    /** \brief Resizes FieldContainer to a rank-3 container with specified dimensions, initialized by 0. 
      
      \param dim0    [in]      - dimension for the 1st index 
      \param dim1    [in]      - dimension for the 2nd index 
      \param dim2    [in]      - dimension for the 3rd index 
    */
    void resize(const int dim0,
                const int dim1,
                const int dim2);

    
    /** \brief Resizes FieldContainer to a rank-4 container with specified dimensions, initialized by 0. 
      
      \param dim0    [in]      - dimension for the 1st index 
      \param dim1    [in]      - dimension for the 2nd index 
      \param dim2    [in]      - dimension for the 3rd index 
      \param dim3    [in]      - dimension for the 4th index 
    */
    void resize(const int dim0,
                const int dim1,
                const int dim2,
                const int dim3);
    
    
    /** \brief Resizes FieldContainer to a rank-5 container with specified dimensions, initialized by 0. 
      
      \param dim0    [in]      - dimension for the 1st index 
      \param dim1    [in]      - dimension for the 2nd index 
      \param dim2    [in]      - dimension for the 3rd index 
      \param dim3    [in]      - dimension for the 4th index 
      \param dim4    [in]      - dimension for the 5th index 
    */
    void resize(const int dim0,
                const int dim1,
                const int dim2,
                const int dim3,
                const int dim4);
    
    
    /** \brief Resizes FieldContainer to arbitrary rank container, initialized by 0, with dimensions 
      specified in the input array. The size of this array implicitely defined the rank of the FieldContainer.
      
      \param newDimensions[in]          - new upper values for index ranges
    */
    void resize(const Teuchos::Array<int>& newDimensions);
        
    
    /** \brief Resizes FieldContainer to have the same rank and dimensions as another FieldContainer,
      and initializes by 0.
      
      \param anotherContainer[in]          - a FieldContainer
      */
    void resize(const FieldContainer<Scalar, ArrayTypeId>& anotherContainer);
    
    
    /** \brief Resizes FieldContainer to a container whose rank depends on the specified field and 
      operator types and the space dimension, initialized by 0. The admissible combinations of these 
      arguments, the rank of the resulitng container and its dimensions are summarized in the following table:
      \verbatim
      |--------------------|-------------------|-------------------|-------------------|
      |operator/field rank |       rank 0      | rank 1 2D/3D      | rank 2 2D/3D      |
      |--------------------|-------------------|-------------------|-------------------|
      |       VALUE        | (P,F)             | (P,F,D)           | (P,F,D,D)         |
      |--------------------|-------------------|-------------------|-------------------|
      |     GRAD, D1       | (P,F,D)           | (P,F,D,D)         | (P,F,D,D,D)       |
      |--------------------|-------------------|-------------------|-------------------|
      |        CURL        | (P,F,D) (undef3D) | (P,F)/(P,F,D)     | (P,F,D)/(P,F,D,D) |
      |--------------------|-------------------|-------------------|-------------------|
      |        DIV         | (P,F,D) (only 1D) | (P,F)             | (P,F,D)           |
      |--------------------|-------------------|-------------------|-------------------|
      |    D1,D2,..,D10    | (P,F,K)           | (P,F,D,K)         | (P,F,D,D,K)       |
      |--------------------|-------------------|-------------------|-------------------|
      
      |------|----------------------|---------------------------|
      |      |         Index        |         Dimension         |
      |------|----------------------|---------------------------|
      |   P  |         point        |  0 <= P < numPoints       |
      |   F  |         field        |  0 <= F < numFields       |
      |   D  |   field coordinate   |  0 <= D < spaceDim        |
      |   K  |   enumeration of Dk  |  0 <= K < DkCardinality   |
      |------|----------------------|---------------------------|
      \endverbatim
      \remarks 
      \li Enumeration of Dk (derivatives of total order k) follows the lexicographical order of 
      the partial derivatives; see getDkEnumeration() for details.
      
      
      \param numPoints       [in]        - number of evaluation points
      \param numFields       [in]        - number of fields that will be evaluated
      \param spaceType       [in]        - type of the function space whose basis will be evaluated
      \param operatorType    [in]        - type of the operator that will be applied to the basis
      \param spaceDim        [in]        - dimension of the ambient space
    */
    void resize(const int             numPoints,
                const int             numFields,
                const EFunctionSpace  spaceType,
                const EOperator       operatorType,
                const int             spaceDim);
    
    //--------------------------------------------------------------------------------------------//
    //                                                                                            //
    //                     Methods to read and write values to FieldContainer                     //
    //                                                                                            //
    //--------------------------------------------------------------------------------------------//

    
    /** \brief Initializes a field container by assigning <var>value</var> to all its elements.  
      */
    void initialize(const Scalar value = 0); 
        
    
    /** \brief Retrieve value by its multi-index. To retrieve it by enumeration use the overloaded [].
      
      \param multiIndex [in]            - array containing multi-index of the desired value
      */
    Scalar getValue(const Teuchos::Array<int>& multiIndex) const;
    
    
    /** \brief Assign value by its multi-index. 
      
      \param dataValue [in]             - value to be assigned
      \param multiIndex [in]            - multi-index of the value
      */
    void setValue(const Scalar               dataValue,
                  const Teuchos::Array<int>& multiIndex);
    
    
    /** \brief Assign value by its enumeration (order relative to the FieldContainer)
      
      \param dataValue [in]             - value to be assigned
      \param order     [in]             - enumeration of the value 
      */
    void setValue(const Scalar  dataValue,
                  const int     order);
    
    
    /**\brief Fills an existing FieldContainer with Scalars stored in a Teuchos::Array without changing 
      rank and dimensions of the container. Size of the input array must match the size of the container.
      
      \param dataArray[in]               - new values
    */
    void setValues(const Teuchos::ArrayView<Scalar>& dataArray);
    
    
    /** \brief Fills an existing FieldContainer with Scalars referenced by <var>dataPtr</var> without
      changing rank and dimensions of the container. Number of data must match the size of the container.
      
      \param dataPtr  [in]               - new values
      \param numData  [in]               - number of values
    */
    void setValues(const Scalar* dataPtr, 
                   const int     numData); 
    
    
    /** \brief Exposes data of FieldContainer, data can be modified.
    */
    Teuchos::ArrayRCP<Scalar> getData() {
      return data_;
    }    


    /** \brief Exposes data of FieldContainer, data cannot be modified.
    */
    Teuchos::ArrayRCP<const Scalar> getData() const {
      return data_;
    }    


    /** \brief Overloaded () operators for rank-1 containers. Data <strong>cannot</strong> be modified.
      
      \param i0         [in]        - 1st index
    */
    const Scalar& operator () (const int i0) const;
    
    /** \brief Overloaded () operators for rank-1 containers. Data <strong>can</strong> be modified.
      
      \param i0         [in]        - 1st index
    */
    Scalar&       operator () (const int i0);
    
    
    /** \brief Overloaded () operators for rank-2 containers. Data <strong>cannot</strong> be modified.
      
      \param i0         [in]        - 1st index
      \param i1         [in]        - 2nd index
    */
    const Scalar& operator () (const int i0,
                               const int i1) const;
    
    /** \brief Overloaded () operators for rank-2 containers. Data <strong>can</strong> be modified.
      
      \param i0         [in]        - 1st index
      \param i1         [in]        - 2nd index
    */
    Scalar&       operator () (const int i0,
                               const int i1);
    
    
    /** \brief Overloaded () operator for rank-3 containers. Data <strong>cannot</strong> be modified.
      
      \param i0         [in]        - 1st index
      \param i1         [in]        - 2nd index
      \param i2         [in]        - 3rd index
    */
    const Scalar& operator () (const int i0,
                               const int i1,
                               const int i2) const;
    
    /** \brief Overloaded () operator for rank-3 containers. Data <strong>can</strong> be modified.
      
      \param i0         [in]        - 1st index
      \param i1         [in]        - 2nd index
      \param i2         [in]        - 3rd index
      */
    Scalar&       operator () (const int i0,
                               const int i1,
                               const int i2);
    
    
    /** \brief Overloaded () operator for rank-4 containers. Data <strong>cannot</strong> be modified.
      
      \param i0         [in]        - 1st index
      \param i1         [in]        - 2nd index
      \param i2         [in]        - 3rd index
      \param i3         [in]        - 4th index
    */
    const Scalar& operator () (const int i0,
                               const int i1,
                               const int i2,
                               const int i3) const;
    
    /** \brief Overloaded () operator for rank-4 containers. Data <strong>can</strong> be modified.
      
      \param i0         [in]        - 1st index
      \param i1         [in]        - 2nd index
      \param i2         [in]        - 3rd index
      \param i3         [in]        - 4th index
    */
    Scalar&       operator () (const int i0,
                               const int i1,
                               const int i2,
                               const int i3);
    
    
    /** \brief Overloaded () operator for rank-5 containers. Data <strong>cannot</strong> be modified.
      
      \param i0         [in]        - 1st index
      \param i1         [in]        - 2nd index
      \param i2         [in]        - 3rd index
      \param i3         [in]        - 4th index
      \param i4         [in]        - 5th index
    */
    const Scalar& operator () (const int i0,
                               const int i1,
                               const int i2,
                               const int i3,
                               const int i4) const;
    
    /** \brief Overloaded () operator for rank-5 containers. Data <strong>can</strong> be modified.
      
      \param i0         [in]        - 1st index
      \param i1         [in]        - 2nd index
      \param i2         [in]        - 3rd index
      \param i3         [in]        - 4th index
      \param i4         [in]        - 5th index
    */
    Scalar&       operator () (const int i0,
                               const int i1,
                               const int i2,
                               const int i3,
                               const int i4);
    
        
    /** \brief   Overloaded [] operator. Returns value based on its enumeration.
      Data <strong>cannot</strong> be modified.
    */
    const Scalar & operator [] (const int address) const;

    
    /** \brief   Overloaded [] operator. Returns value based on its enumeration.
      Data <strong>can</strong> be modified.
      */
    Scalar &       operator [] (const int address);
    
    
    /** \brief Assignment operator <var>*this = right</var>.
    */
    FieldContainer& operator  = (const FieldContainer& right);
    
  }; // end class FieldContainer
  
  
  //--------------------------------------------------------------------------------------------//
  //                                                                                            //
  //                        Function declarations related to FieldContainer                     //
  //                                                                                            //
  //--------------------------------------------------------------------------------------------//
  
  /** \relates FieldContainer
  Outputs a formated stream with FieldContainer data. For debugging purposes.
  */
  template<class Scalar, int ArrayTypeId>
    std::ostream& operator << (std::ostream& os, const FieldContainer<Scalar, ArrayTypeId>& container);
 
  
} // end namespace Intrepid

// include templated definitions
#include <Intrepid_FieldContainerDef.hpp>

#endif

/**
\page md_array_page               Multi-dimensional array (MD array) template arguments
 
 
 \section md_array_intro_sec       Introduction
 
 This page describes basic requirements for multi-dimensional array (MD array) template arguments in 
 Intrepid. MD array is a fundamental concept for managing a wide range of numerical data arising in
 PDE-based simulations. An MD array is a collection of members of a given scalar data type that are 
 identified through a multi-index. Therefore, allowing for an MD array template argument provides a
 convenient mechanism to share numerical data between Intrepid and user applications. 
 
 The scalar data type members of a multi-dimensional array are stored in a contiguous block of memory.  
 Contiguous memory storage is not necessary to the concept of an array; however, in order to achieve 
 the best performance from cache-based computer memory systems contiguity of member storage has proven 
 to be essential.
 
 
 \section md_array_def_sec        Definitions
 
 The following rules and definitions apply to all MD arrays used as template arguments in Intrepid.
 
 \li A scalar value that is uniquely identified by a set of interegs <var>{i0,i1,...,iN}</var>  is called 
 a multi-indexed value;
 \li The set of all multi-indexed values such that <var>0 <= ik < dim_k</var> is called MD array;
 \li The integer <var>ik</var> is the kth index of the MD array; the N-tuple <var>{i0,...,iN}</var>
 is the multi-index of the MD array;
 \li The integer <var>dim_k</var> is the kth dimension of the MD array; the N-tuple <var>{dim_0,...,dim_N}</var>
 is the multi-dimension of the MD array
 \li The integer <var>N+1</var> is the rank of the MD array;
 \li A map <var>{i0,...,iN} -> {0,1,2,...}</var> from the set of all multi-indices to the set of the
 natural numbers is called enumeration of the MD array;
 \li The numerical position of an element indexed by <var>{i0,...,iN}</var>, established by the
 enumeration is called ordinal number of that element or simply ordinal.
 
 Enumeration of all MD arrays passed as template arguments to Intrepid must follow the natural 
 lexicographical order: the leftmost index <var>i0</var> changes last and the rightmost index 
 <var>iN</var> changes first. In summary, an MD array pased to Intrepid should comply with the
 following rules:
 
 \li the indices are zero-based;
 \li dimensions are counted from 0; e.g., a rank-4 array has dimensions <var>{dim_0,dim_1,dim_2,dim_3}</var>
 \li the enumeration is induced by the natural lexicographical order;
 \li the MD array is not strongly type on its dimensions and rank.
 
 
 \section md_array_interface_sec  MD Array interface
 
 An MD array type passed as a template argument to Intrepid is expected to implement the following 
 minimal interface:
 
 \li int rank()                      - returns number of dimensions
 \li int dimension(dim_k)            - returns the kth dimension (dimensions are dim0, dim1, etc.)
 \li int size()                      - returns size, i.e., dim0*dim1*...*dim_k
 \li const Scalar& operator(i,j,...,k)  - const accessor using multi-index
 \li       Scalar& operator(i,j,...,k)  - non-const accessor using multi-index
 \li const Scalar& operator[i]          - const accessor using the ordinal of the array element
 \li       Scalar& operator[i]          - non-const accessor using the ordinal of the array element
 
 
 \section md_array_notation_sec   MD Array notation and examples
 
 In addition to the generic index and dimension notation <var>ik</var> and <var>dim_k</var> it is 
 convenient to introduce data-specific notation for indices and dimensions of MD arrays that recur
 in PDE-based simulation codes. 
 \verbatim
 |-------------------------------------------------------------------------------------------------|
 |   Index type              | Dimension |  Description                                            |
 |---------------------------|-----------|---------------------------------------------------------|
 |   point                   |     P     |  number of points stored in an MD array                 |
 |   vertex                  |     V     |  number of nodes stored in an MD aray                |
 |   field                   |     F     |  number of fields stored in an MD array                 |
 |   basis field             |     B     |  number of basis fields stored in an MD array           |
 |   cell                    |     C     |  number of cells stored in an MD array                  |
 |   field coordinate        |     D     |  space dimension                                        |
 |   derivative ordinal      |     K     |  cardinality of the set of kth derivatives              |
 |-------------------------------------------------------------------------------------------------|
 \endverbatim
 
 \remarks 
 \li The totality of all derivatives whose order equals k (OPERATOR_Dk in Intrepid) forms a multiset;
 see http://mathworld.wolfram.com/Multiset.html . In Intrepid this multiset is enumerated using the 
 lexicographical order of the partial derivatives; see getDkEnumeration() for details.
 
 
 This notation is used throughout Intrepid's documentation as a means to add further clarity to the 
 specifications of MD array passed to and returned from Intrepid methods. The following is a list of
 typical MD arrays that arise in PDE-based simulation codes:
 \verbatim
 |-------------------------------------------------------------------------------------------------|
 | Rank | Multi-dimension | Multi-index    | Description                                           |
 |-------------------------------------------------------------------------------------------------|
 |  1   | (P)             | (p)            | Scalar (rank 0) field evaluated at P points           |
 |  2   | (P,D)           | (p,d)          | Vector (rank 1) field evaluated at P points           |
 |  3   | (P,D,D)         | (p,d,d)        | Tensor (rank 2) field evaluated at P points           |           
 |-------------------------------------------------------------------------------------------------|
 |  2   | (P,F)           | (p,f)          | F scalar fields evaluated at P points                 |
 |  3   | (P,F,D)         | (p,f,d)        | F vector fields evaluated at P points                 |
 |  4   | (P,F,D,D)       | (p,f,d,d)      | F tensor fields evaluated at P points                 |
 |-------------------------------------------------------------------------------------------------|
 |  3   | (P,F,K)         | (p,f,k)        | kth deriv. of F scalar fields evaluated at P points   |       
 |  4   | (P,F,D,K)       | (p,f,d,k)      | kth deriv. of F vector fields evaluated at P points   |       
 |  5   | (P,F,D,D,K)     | (p,f,d,d,k)    | kth deriv. of F tensor fields evaluated at P points   |           
 |-------------------------------------------------------------------------------------------------|
 |  3   | (C,V,D)         | (c,v,d )       | Vertex coords. of C cells having V vertices each      |
 |  3   | (C,P,D)         | (c,p,d )       | Coords. of C*P points in C cells, P per cell          |
 |-------------------------------------------------------------------------------------------------| 
 \endverbatim
 
 
 \section md_array_intrepid_sec   MD Array implementaion in Intrepid
 
 The FieldContainer class provides an implementation of an MD array type that is used throughout Intrepid.
 A FieldContainer object is templated on a Scalar type. Its rank and dimensions are runtime parameters,
 i.e., a FieldContainer is not strongly typed on rank and dimension.
 
 */