From 2292ddf5c8e83898e7f2390f12c8ab586c66072b Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Wed, 4 Feb 2015 21:04:53 -0600 Subject: [PATCH] Add a few operator overloads. --- doc/news/changes.h | 13 ++++++ include/deal.II/base/tensor.h | 59 +++++++++++++++++++++++++++ include/deal.II/base/tensor_base.h | 64 ++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) diff --git a/doc/news/changes.h b/doc/news/changes.h index f93ccf2afd..221b07caaf 100644 --- a/doc/news/changes.h +++ b/doc/news/changes.h @@ -330,6 +330,19 @@ inconvenience this causes.

Specific improvements

    +
  1. 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 Tensor@<1,dim,double@> by a + std::complex@ 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. +
    + (Wolfgang Bangerth, 2015/02/11) +
  2. +
  3. 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 diff --git a/include/deal.II/base/tensor.h b/include/deal.II/base/tensor.h index 06b628d375..df573e876e 100644 --- a/include/deal.II/base/tensor.h +++ b/include/deal.II/base/tensor.h @@ -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 + * std::vector@ 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 Tensor@<1,dim,double@> by std::complex@, + * then the result will be a Tensor@<1,dim,std::complex@@>. + * 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 +inline +Tensor::type>::type> +operator * (const Tensor &t, + const OtherNumber factor) +{ + // recurse over the base objects + Tensor::type> tt; + for (unsigned int d=0; d +inline +Tensor::type>::type> +operator * (const Number factor, + const Tensor &t) +{ + // simply forward to the operator above + return t * factor; +} + + /** * Division of a tensor of general rank by a scalar Number. diff --git a/include/deal.II/base/tensor_base.h b/include/deal.II/base/tensor_base.h index 852f59ab55..30cc1f1f49 100644 --- a/include/deal.II/base/tensor_base.h +++ b/include/deal.II/base/tensor_base.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -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 + * std::vector@ 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 Tensor@<1,dim,double@> by std::complex@, + * then the result will be a Tensor@<1,dim,std::complex@@>. + * 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 +inline +Tensor<1,dim,typename ProductType::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) + // (as well as with switched arguments and double<->float). + typedef typename ProductType::type product_type; + Tensor<1,dim,product_type> tt (false); + for (unsigned int d=0; d + * @relates EnableIfScalar + */ +template +inline +Tensor<1,dim,typename ProductType::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. -- 2.39.5