]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Add a few operator overloads.
authorWolfgang Bangerth <bangerth@math.tamu.edu>
Thu, 5 Feb 2015 03:04:53 +0000 (21:04 -0600)
committerWolfgang Bangerth <bangerth@math.tamu.edu>
Thu, 12 Feb 2015 13:31:43 +0000 (07:31 -0600)
doc/news/changes.h
include/deal.II/base/tensor.h
include/deal.II/base/tensor_base.h

index f93ccf2afd8b4f52ff1200f6804f0118b981b8a9..221b07caaf1a12719da7c529227842576c06d709 100644 (file)
@@ -330,6 +330,19 @@ inconvenience this causes.
 <h3>Specific improvements</h3>
 
 <ol>
+  <li> Changed: If you take the product of a Tensor and a scalar number,
+  you previously got a Tensor back that stored its elements in the same
+  data type as the original tensor. This leads to problems if you
+  multiply a <code>Tensor@<1,dim,double@></code> by a
+  <code>std::complex@<double@></code> because the result clearly needs
+  to store its elements as complex numbers, rather than as double
+  variables. This is now changed: The result of the product of a Tensor
+  and a scalar number is now a Tensor that stores its elements in a data
+  type appropriate for this product.
+  <br>
+  (Wolfgang Bangerth, 2015/02/11)
+  </li>
+
   <li> New: There is now a new class ProductType that can be used
   to infer the type of the product of two objects. There is now also
   a class EnableIfScalar that helps restrict some templates to only
index 06b628d375e53892be1d075ebb0bff8e5d9226e9..df573e876e050c2a45f299c884e39457dde64ac5 100644 (file)
@@ -1992,6 +1992,65 @@ operator * (const Number                   factor,
 }
 
 
+/**
+ * Multiplication of a tensor of general rank with a scalar number from the
+ * right.
+ *
+ * The purpose of this operator is to enable only multiplication of a tensor
+ * by a scalar number (i.e., a floating point number, a complex floating point
+ * number, etc.). The function is written in a way that only allows the
+ * compiler to consider the function if the second argument is indeed a scalar
+ * number -- in other words, @p OtherNumber will not match, for example
+ * <code>std::vector@<double@></code> as the product of a tensor and a vector
+ * clearly would make no sense. The mechanism by which the compiler is
+ * prohibited of considering this operator for multiplication with non-scalar
+ * types are explained in the documentation of the EnableIfScalar class.
+ *
+ * The return type of the function is chosen so that it matches the types
+ * of both the tensor and the scalar argument. For example, if you multiply
+ * a <code>Tensor@<1,dim,double@></code> by <code>std::complex@<double@></code>,
+ * then the result will be a <code>Tensor@<1,dim,std::complex@<double@>@></code>.
+ * In other words, the type with which the returned tensor stores its
+ * components equals the type you would get if you multiplied an individual
+ * component of the input tensor by the scalar factor.
+ *
+ * @relates Tensor
+ * @relates EnableIfScalar
+ */
+template <int rank, int dim, typename Number, typename OtherNumber>
+inline
+Tensor<rank,dim,typename ProductType<Number,typename EnableIfScalar<OtherNumber>::type>::type>
+operator * (const Tensor<rank,dim,Number> &t,
+            const OtherNumber              factor)
+{
+  // recurse over the base objects
+  Tensor<rank,dim,typename ProductType<Number,OtherNumber>::type> tt;
+  for (unsigned int d=0; d<dim; ++d)
+    tt[d] = t[d] * factor;
+  return tt;
+}
+
+
+
+/**
+ * Multiplication of a tensor of general rank with a scalar number from the
+ * left. See the discussion with the operator with switched arguments for more
+ * information about template arguments and the return type.
+ *
+ * @relates Tensor
+ * @relates EnableIfScalar
+ */
+template <int rank, int dim, typename Number, typename OtherNumber>
+inline
+Tensor<rank,dim,typename ProductType<Number,typename EnableIfScalar<OtherNumber>::type>::type>
+operator * (const Number                        factor,
+            const Tensor<rank,dim,OtherNumber> &t)
+{
+  // simply forward to the operator above
+  return t * factor;
+}
+
+
 
 /**
  * Division of a tensor of general rank by a scalar Number.
index 852f59ab55d0189802bc8c740c30a89e5013d036..30cc1f1f49f6a3240c3810d36401e4338861539d 100644 (file)
@@ -26,6 +26,7 @@
 #include <deal.II/base/config.h>
 #include <deal.II/base/exceptions.h>
 #include <deal.II/base/table_indices.h>
+#include <deal.II/base/template_constraints.h>
 #include <vector>
 
 #include <cmath>
@@ -1322,6 +1323,69 @@ operator * (const Number                factor,
 }
 
 
+/**
+ * Multiplication of a tensor of rank 1 with a scalar number from the right.
+ *
+ * The purpose of this operator is to enable only multiplication of a tensor
+ * by a scalar number (i.e., a floating point number, a complex floating point
+ * number, etc.). The function is written in a way that only allows the
+ * compiler to consider the function if the second argument is indeed a scalar
+ * number -- in other words, @p OtherNumber will not match, for example
+ * <code>std::vector@<double@></code> as the product of a tensor and a vector
+ * clearly would make no sense. The mechanism by which the compiler is
+ * prohibited of considering this operator for multiplication with non-scalar
+ * types are explained in the documentation of the EnableIfScalar class.
+ *
+ * The return type of the function is chosen so that it matches the types
+ * of both the tensor and the scalar argument. For example, if you multiply
+ * a <code>Tensor@<1,dim,double@></code> by <code>std::complex@<double@></code>,
+ * then the result will be a <code>Tensor@<1,dim,std::complex@<double@>@></code>.
+ * In other words, the type with which the returned tensor stores its
+ * components equals the type you would get if you multiplied an individual
+ * component of the input tensor by the scalar factor.
+ *
+ * @relates Tensor<1,dim,Number>
+ * @relates EnableIfScalar
+ */
+template <int dim, typename Number, typename OtherNumber>
+inline
+Tensor<1,dim,typename ProductType<Number,typename EnableIfScalar<OtherNumber>::type>::type>
+operator * (const Tensor<1,dim,Number> &t,
+            const OtherNumber           factor)
+{
+  // form the product. we have to convert the two factors into the final
+  // type via explicit casts because, for awkward reasons, the C++
+  // standard committee saw it fit to not define an
+  //   operator*(float,std::complex<double>)
+  // (as well as with switched arguments and double<->float).
+  typedef typename ProductType<Number,OtherNumber>::type product_type;
+  Tensor<1,dim,product_type> tt (false);
+  for (unsigned int d=0; d<dim; ++d)
+    tt[d] = product_type(t[d]) * product_type(factor);
+  return tt;
+}
+
+
+
+/**
+ * Multiplication of a tensor of rank 1 with a scalar number from the left.
+ * See the discussion with the operator with switched arguments for more
+ * information about template arguments and the return type.
+ *
+ * @relates Tensor<1,dim,Number>
+ * @relates EnableIfScalar
+ */
+template <int dim, typename Number, typename OtherNumber>
+inline
+Tensor<1,dim,typename ProductType<Number,typename EnableIfScalar<OtherNumber>::type>::type>
+operator * (const Number                     factor,
+            const Tensor<1,dim,OtherNumber> &t)
+{
+  // simply forward to the other operator with switched arguments
+  return (t*factor);
+}
+
+
 
 /**
  * Division of a tensor of rank 1 by a scalar Number.

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.