From 19ddabf1b6abc5faf514933976c225a6bf6188f2 Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Tue, 29 Mar 2005 18:53:50 +0000 Subject: [PATCH] Rewrite the entire accessor stuff so that we can also handle higher order tensors. Doesn't work for rank-4 tensors right now, though... git-svn-id: https://svn.dealii.org/trunk@10293 0785d39b-7218-0410-832d-ea1e28bc413d --- deal.II/base/include/base/symmetric_tensor.h | 386 +++++++++++++++---- 1 file changed, 303 insertions(+), 83 deletions(-) diff --git a/deal.II/base/include/base/symmetric_tensor.h b/deal.II/base/include/base/symmetric_tensor.h index 3dec8de531..2335c94815 100644 --- a/deal.II/base/include/base/symmetric_tensor.h +++ b/deal.II/base/include/base/symmetric_tensor.h @@ -28,8 +28,32 @@ namespace internal * internal to how the SymmetricTensor * class works. */ - namespace SymmetricTensor + namespace SymmetricTensorAccessors { + /** + * Create a TableIndices<2> + * object where the first entries + * up to position-1 are + * taken from previous_indices, + * and new_index is put at + * position + * position. The + * remaining indices remain in + * invalid state. + */ + TableIndices<2> merge (const TableIndices<2> &previous_indices, + const unsigned int new_index, + const unsigned int position) + { + Assert (position < 2, ExcIndexRange (position, 0, 2)); + + if (position == 0) + return TableIndices<2>(new_index); + else + return TableIndices<2>(previous_indices[0], new_index); + } + + /** * Declaration of typedefs for the type * of data structures which are used to @@ -127,7 +151,7 @@ namespace internal template struct AccessorTypes { - typedef const ::SymmetricTensor tensor_type; + typedef const SymmetricTensor tensor_type; typedef double reference; }; @@ -144,95 +168,267 @@ namespace internal template struct AccessorTypes { - typedef ::SymmetricTensor tensor_type; + typedef SymmetricTensor tensor_type; typedef double &reference; }; - template - class Accessor; - - /** - * Accessor class to access the elements - * of individual rows in a symmetric - * tensor of rank 2. Since the elements - * of symmetric tensors are not stored as - * in a table, the accessors are a little - * more involved. However, for tensors of - * rank 2 they are still relatively - * simple in that an accessor is created - * by the SymmetricTensor class with the - * first access to operator[]; - * the accessor thereby points to a row - * of the tensor. Calling - * operator[] on the accessor - * then selects an entry of this - * row. Note that if this entry is not - * actually stored, then the transpose - * entry is chosen as that is guaranteed - * to be stored. - * - * @author Wolfgang Bangerth, 2005 - */ - template - class Accessor<2,dim,constness> +/** + * @internal + * + * Class that acts as accessor to elements of type + * SymmetricTensor. The template parameter C may be either + * true or false, and indicates whether the objects worked on are + * constant or not (i.e. write access is only allowed if the value is + * false). + * + * Since with N indices, the effect of applying + * operator[] is getting access to something we N-1 + * indices, we have to implement these accessor classes recursively, + * with stopping when we have only one index left. For the latter + * case, a specialization of this class is declared below, where + * calling operator[] gives you access to the objects + * actually stored by the tensor; the tensor class also makes sure + * that only those elements are actually accessed which we actually + * store, i.e. it reorders indices if necessary. The template + * parameter P indicates how many remaining indices there + * are. For a rank-2 tensor, P may be two, and when using + * operator[], an object with P=1 emerges. + * + * As stated for the entire namespace, you will not usually have to do + * with these classes directly, and should not try to use their + * interface directly as it may change without notice. In fact, since + * the constructors are made private, you will not even be able to + * generate objects of this class, as they are only thought as + * temporaries for access to elements of the table class, not for + * passing them around as arguments of functions, etc. + * + * This class is an adaptation of a similar class used for the Table + * class. + * + * @author Wolfgang Bangerth, 2002, 2005 + */ + template + class Accessor { public: /** - * Import which tensor we work on. + * Import two typedefs from the + * switch class above. */ - typedef - typename AccessorTypes<2,dim,constness>::tensor_type - tensor_type; + typedef typename AccessorTypes::reference reference; + typedef typename AccessorTypes::tensor_type tensor_type; + private: /** - * The type of a reference to an - * individual element of the - * symmetric tensor. If the tensor - * is constant, we can only return - * a value instead of a reference. + * Constructor. Take a + * reference to the tensor + * object which we will + * access. + * + * The second argument + * denotes the values of + * previous indices into the + * tensor. For example, for a + * rank-4 tensor, if P=2, + * then we will already have + * had two successive element + * selections (e.g. through + * tensor[1][2]), + * and the two index values + * have to be stored + * somewhere. This class + * therefore only makes use + * of the first rank-P + * elements of this array, + * but passes it on to the + * next level with P-1 which + * fills the next entry, and + * so on. + * + * The constructor is made + * private in order to prevent + * you having such objects + * around. The only way to + * create such objects is via + * the Table class, which + * only generates them as + * temporary objects. This + * guarantees that the accessor + * objects go out of scope + * earlier than the mother + * object, avoid problems with + * data consistency. */ - typedef typename AccessorTypes<2,dim,constness>::reference reference; + Accessor (tensor_type &tensor, + const TableIndices &previous_indices); /** - * Constructor. Take the tensor to - * access as well as the row we - * point to as arguments. + * Default constructor. Not + * needed, and invisible, so + * private. + */ + Accessor (); + + /** + * Copy constructor. Not + * needed, and invisible, so + * private. */ - Accessor (tensor_type &tensor, - const unsigned int row); + Accessor (const Accessor &a); + public: + /** - * Return a reference to an element - * of this row (if we point to a - * non-const tensor), or the value - * of the element (in case this is - * a constant tensor). + * Index operator. */ - reference operator[] (const unsigned int column); - + Accessor operator [] (const unsigned int i); + + private: + /** + * Store the data given to the + * constructor. + */ + tensor_type &tensor; + const TableIndices previous_indices; + + // declare some other classes + // as friends. make sure to + // work around bugs in some + // compilers +#ifndef DEAL_II_NAMESP_TEMPL_FRIEND_BUG + template friend class SymmetricTensor; + template + friend class Accessor; +# ifndef DEAL_II_TEMPL_SPEC_FRIEND_BUG + friend class SymmetricTensor; + friend class Accessor; +# endif +#else + friend class SymmetricTensor; + friend class Accessor; +#endif + }; + + + +/** + * @internal + * Accessor class for SymmetricTensor. This is the specialization for the last + * index, which actually allows access to the elements of the table, + * rather than recursively returning access objects for further + * subsets. The same holds for this specialization as for the general + * template; see there for more information. + * + * @author Wolfgang Bangerth, 2002, 2005 + */ + template + class Accessor + { + public: + /** + * Import two typedefs from the + * switch class above. + */ + typedef typename AccessorTypes::reference reference; + typedef typename AccessorTypes::tensor_type tensor_type; + private: /** - * Reference to the tensor we + * Constructor. Take a + * reference to the tensor + * object which we will * access. + * + * The second argument + * denotes the values of + * previous indices into the + * tensor. For example, for a + * rank-4 tensor, if P=2, + * then we will already have + * had two successive element + * selections (e.g. through + * tensor[1][2]), + * and the two index values + * have to be stored + * somewhere. This class + * therefore only makes use + * of the first rank-P + * elements of this array, + * but passes it on to the + * next level with P-1 which + * fills the next entry, and + * so on. + * + * For this particular + * specialization, i.e. for + * P==1, all but the last + * index are already filled. + * + * The constructor is made + * private in order to prevent + * you having such objects + * around. The only way to + * create such objects is via + * the Table class, which + * only generates them as + * temporary objects. This + * guarantees that the accessor + * objects go out of scope + * earlier than the mother + * object, avoid problems with + * data consistency. */ - tensor_type &tensor; + Accessor (tensor_type &tensor, + const TableIndices &previous_indices); /** - * Index of the row we access. + * Default constructor. Not + * needed, and invisible, so + * private. */ - const unsigned int row; + Accessor (); /** - * Make the symmetric tensor - * classes a friend, since they are - * the only ones who can create - * objects like this. + * Copy constructor. Not + * needed, and invisible, so + * private. */ - template class ::SymmetricTensor; - }; + Accessor (const Accessor &a); + public: + + /** + * Index operator. + */ + reference operator [] (const unsigned int); + + private: + /** + * Store the data given to the + * constructor. + */ + tensor_type &tensor; + const TableIndices previous_indices; + + // declare some other classes + // as friends. make sure to + // work around bugs in some + // compilers +#ifndef DEAL_II_NAMESP_TEMPL_FRIEND_BUG + template friend class SymmetricTensor; + template + friend class Accessor; +# ifndef DEAL_II_TEMPL_SPEC_FRIEND_BUG + friend class SymmetricTensor; + friend class Accessor; +# endif +#else + friend class SymmetricTensor; + friend class Accessor; +#endif + }; } } @@ -410,7 +606,7 @@ class SymmetricTensor * symmetric tensor. This function is * called for constant tensors. */ - internal::SymmetricTensor::Accessor + internal::SymmetricTensorAccessors::Accessor operator [] (const unsigned int row) const; /** @@ -418,7 +614,7 @@ class SymmetricTensor * symmetric tensor. This function is * called for non-constant tensors. */ - internal::SymmetricTensor::Accessor + internal::SymmetricTensorAccessors::Accessor operator [] (const unsigned int row); /** @@ -463,7 +659,7 @@ class SymmetricTensor /** * Data storage for a symmetric tensor. */ - typename internal::SymmetricTensor::StorageType<2,dim>::base_tensor_type data; + typename internal::SymmetricTensorAccessors::StorageType<2,dim>::base_tensor_type data; }; @@ -472,26 +668,48 @@ class SymmetricTensor namespace internal { - namespace SymmetricTensor + namespace SymmetricTensorAccessors { - template - Accessor<2,dim,constness>:: - Accessor (tensor_type &tensor, - const unsigned int row) - : - tensor (tensor), - row (row) +// template +// Accessor:: +// Accessor (const tensor_type &tensor, +// const TableIndices &previous_indices) +// : +// tensor (tensor), +// previous_indices (previous_indices) +// {} + + + +// template +// Accessor +// Accessor::operator[] (const unsigned int i) +// { +// return Accessor (tensor, +// merge (previous_indices, i, rank-P)); +// } + + + + template + Accessor:: + Accessor (tensor_type &tensor, + const TableIndices &previous_indices) + : + tensor (tensor), + previous_indices (previous_indices) {} - template - typename Accessor<2,dim,constness>::reference - Accessor<2,dim,constness>:: - operator[] (const unsigned int column) + template + typename Accessor::reference + Accessor::operator[] (const unsigned int i) { - return tensor(TableIndices<2> (row, column)); + return tensor(merge (previous_indices, i, rank-1)); } + + } } @@ -661,7 +879,7 @@ unsigned int SymmetricTensor::memory_consumption () { return - internal::SymmetricTensor::StorageType::memory_consumption (); + internal::SymmetricTensorAccessors::StorageType::memory_consumption (); } @@ -853,21 +1071,23 @@ SymmetricTensor<2,3>::operator () (const TableIndices<2> &indices) const template -internal::SymmetricTensor::Accessor +internal::SymmetricTensorAccessors::Accessor SymmetricTensor::operator [] (const unsigned int row) const { return - internal::SymmetricTensor::Accessor (*this, row); + internal::SymmetricTensorAccessors:: + Accessor (*this, TableIndices (row)); } template -internal::SymmetricTensor::Accessor +internal::SymmetricTensorAccessors::Accessor SymmetricTensor::operator [] (const unsigned int row) { return - internal::SymmetricTensor::Accessor (*this, row); + internal::SymmetricTensorAccessors:: + Accessor (*this, TableIndices (row)); } -- 2.39.5