Hammer  1.0.0
Helicity Amplitude Module for Matrix Element Reweighting
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Tensor.cc
Go to the documentation of this file.
1 ///
2 /// @file Tensor.cc
3 /// @brief Hammer tensor class
4 ///
5 
6 //**** This file is a part of the HAMMER library
7 //**** Copyright (C) 2016 - 2020 The HAMMER Collaboration
8 //**** HAMMER is licensed under version 3 of the GPL; see COPYING for details
9 //**** Please note the MCnet academic guidelines; see GUIDELINES for details
10 
11 // -*- C++ -*-
12 #include "Hammer/Math/Tensor.hh"
13 #include "Hammer/Exceptions.hh"
15 
20 #include <iostream>
21 
22 using namespace std;
23 
24 namespace Hammer {
25 
26  namespace MD = MultiDimensional;
27 
28  Tensor::Tensor() : _name{"Tensor"},
29  _data{MD::makeEmptyScalar()} {
30  }
31 
32  Tensor::Tensor(const string& name) : _name{name},
33  _data{MD::makeEmptyScalar()} {
34  }
35 
36  Tensor::Tensor(const string& name, MultiDimensional::TensorData container) : _name{name}, _data{move(container)} {
37  }
38 
39  Tensor::Tensor(const std::string& name, std::vector<std::pair<MultiDimensional::SharedTensorData, bool>>&& data) : _name{name} {
40  _data = MD::combineSharedTensors(move(data));
41  }
42 
43  Tensor::Tensor(const Tensor& other)
44  : _name{other._name}, _data{other._data->clone()} {
45  }
46 
47  Tensor& Tensor::operator=(const Tensor& other) {
48  _name = other._name;
49  _data = other._data->clone();
50  return *this;
51  }
52 
53  Tensor::Tensor(Tensor&& other) : _name{move(other._name)}, _data{move(other._data)} {
54 
55  }
56 
58  _name = move(other._name);
59  _data = move(other._data);
60  return *this;
61  }
62 
64  _data.reset();
65  }
66 
67  complex<double>& Tensor::element(const IndexList& indices) {
68  return _data->element(indices);
69  }
70 
71  complex<double> Tensor::element(const IndexList& indices) const {
72  return const_cast<const MD::IContainer*>(_data.get())->element(indices);
73  }
74 
75  size_t Tensor::rank() const {
76  return _data->rank();
77  }
78 
80  return _data->dims();
81  }
82 
84  return _data->labels();
85  }
86 
87  bool Tensor::hasWCLabels() const {
88  auto labs = labels();
89  return find_if(labs.begin(), labs.end(), [&](IndexLabel& lab)-> bool {return (lab > WC_INDEX_START && lab < WC_INDEX_END);}) != labs.end();
90  }
91 
92  bool Tensor::hasFFLabels() const {
93  auto labs = labels();
94  return find_if(labs.begin(), labs.end(), [&](IndexLabel& lab)-> bool {return (lab > FF_INDEX_START && lab < FF_INDEX_END);}) != labs.end();
95  }
96 
97  bool Tensor::hasFFVarLabels() const {
98  auto labs = labels();
99  return find_if(labs.begin(), labs.end(), [&](IndexLabel& lab)-> bool {return (lab > FF_VAR_INDEX_START && lab < FF_VAR_INDEX_END);}) != labs.end();
100  }
101 
102  const string& Tensor::name() const {
103  return _name;
104  }
105 
106  bool Tensor::isEqualTo(const Tensor& other) const {
107  return _data->compare(*other._data);
108  }
109 
110  Log& Tensor::getLog() const {
111  return Log::getLog("Hammer.Tensor." + _name);
112  }
113 
114  Tensor& Tensor::dot(const Tensor& other, const UniqueLabelsList& indices) {
115  if (other.rank() == 0) {
116  operator*=(other.element());
117  return *this;
118  }
119  if (rank() == 0) {
120  complex<double> val = element();
121  _data = other._data->clone();
122  operator*=(val);
123  return *this;
124  }
125  UniqueLabelsList tmpIndices;
126  if (indices.size() == 0) {
127  auto labs = labels();
128  tmpIndices.insert(labs.begin(), labs.end());
129  }
130  else {
131  tmpIndices.insert(indices.begin(), indices.end());
132  }
133  IndexPairList positions = _data->getSameLabelPairs(*other._data, tmpIndices);
134  if (positions.size() > 0) {
135  _data = MD::calcDot(move(_data), *other._data, positions);
136  }
137  else {
138  MD::TensorData tmp{new MD::OuterContainer{move(_data), other._data->clone()}};
139  _data.swap(tmp);
140  }
141  return *this;
142  }
143 
145  if(rank() == 0) {
146  return *this;
147  }
148  IndexPairList positions = _data->getSpinLabelPairs();
149  if(positions.size() > 0) {
150  _data = MD::calcTrace(move(_data), positions);
151  }
152  return *this;
153  }
154 
156  size_t oldDim = _data->numValues();
157  spinSum();
158  size_t newDim = _data->numValues();
159  return operator*=((static_cast<double>(newDim))/(static_cast<double>(oldDim)));
160  }
161 
163  if (rank() == 0) {
164  element() = element()*conj(element());
165  return *this;
166  }
167  _data = MD::calcSquare(move(_data));
168  return *this;
169  }
170 
172  _data = MD::toVector(move(_data));
173  return *this;
174  }
175 
176  Tensor& Tensor::operator*=(double val) {
177  _data->operator*=(val);
178  return *this;
179  }
180 
181  Tensor& Tensor::operator*=(const complex<double> val) {
182  _data->operator*=(val);
183  return *this;
184  }
185 
186 
188  if (rank() == other.rank()) {
189  if(rank() == 0) {
190  element() += other.element();
191  return (*this);
192  }
193  if(_data->isSameShape(*other._data)) {
194  _data = MD::sum(move(_data), *other._data);
195  return (*this);
196  }
197  }
198  throw Error("Tensor rank/sizes do not match. Whose gonna do it you, you Lieutenant Weinberg? I have a greater responsibility than you can possibly fathom.");
199  }
200 
202  if (rank() == other.rank()) {
203  if (rank() == 0) {
204  element() *= other.element();
205  return (*this);
206  }
207  if (_data->isSameShape(*other._data)) {
208  _data = MD::elementMultiply(move(_data), *other._data);
209  return (*this);
210  }
211  }
212  throw Error("Tensor rank/sizes do not match");
213  }
214 
216  if (rank() == other.rank()) {
217  if (rank() == 0) {
218  element() /= other.element();
219  return (*this);
220  }
221  if (_data->isSameShape(*other._data)) {
222  _data = MD::elementDivide(move(_data), *other._data);
223  return (*this);
224  }
225  }
226  throw Error("Tensor rank/sizes do not match. Whose gonna do it you, you Lieutenant Weinberg? I have a greater responsibility than you can possibly fathom.");
227  }
228 
230  _data->clear();
231  }
232 
233  void Tensor::write(flatbuffers::FlatBufferBuilder* msgwriter, flatbuffers::Offset<Serial::FBTensor>* msg) const {
234  auto serialname = msgwriter->CreateString(_name);
235  _data = MD::reOptimize(move(_data));
236  auto serialvalue = _data->write(msgwriter);
237  Serial::FBTensorBuilder serialTensor{*msgwriter};
238  serialTensor.add_name(serialname);
239  serialTensor.add_data_type(serialvalue.second);
240  serialTensor.add_data(serialvalue.first);
241  *msg = serialTensor.Finish();
242  }
243 
244 
245  void Tensor::read(const Serial::FBTensor* msgreader) {
246  if (msgreader != nullptr) {
247  _data = MD::read(msgreader);
248  }
249  }
250 
251  // Tensor&
252  // Tensor::fillTensorElements(const vector<pair<vector<size_t>, complex<double>>>& values) {
253  // for (auto& elem : values) {
254  // element(elem.first) = elem.second;
255  // }
256  // return *this;
257  // }
258 
259  Tensor& Tensor::addAt(const Tensor& t, IndexLabel coord, IndexType position) {
260  if(rank() != 0 && _data->canAddAt(*t._data, coord, position)) {
261  IndexType index = _data->labelToIndex(coord);
262  _data = MD::addAt(move(_data), *t._data, index, position);
263  return *this;
264  }
265  throw IndexLabelError("Unable to addAt");
266  }
267 
268  Tensor dot(const Tensor& first, const Tensor& second, const set<IndexLabel>& indices) {
269  Tensor result(first);
270  result.dot(second, indices);
271  return result;
272  }
273 
274  Tensor spinSum(const Tensor& first) {
275  Tensor result(first);
276  result.spinSum();
277  return result;
278  }
279 
280  Tensor spinAverage(const Tensor& first) {
281  Tensor result(first);
282  result.spinAverage();
283  return result;
284  }
285 
286  Tensor operator*(const Tensor& first, double val) {
287  Tensor result(first);
288  result *= val;
289  return result;
290  }
291 
292  Tensor operator*(double val, const Tensor& first) {
293  Tensor result(first);
294  result *= val;
295  return result;
296  }
297 
298  Tensor operator*(const complex<double> val, const Tensor& first) {
299  Tensor result(first);
300  result *= val;
301  return result;
302  }
303 
304  Tensor operator*(const Tensor& first, const complex<double> val) {
305  Tensor result(first);
306  result *= val;
307  return result;
308  }
309 
310  Tensor operator+(const Tensor& first, const Tensor& second) {
311  Tensor result(first);
312  result += second;
313  return result;
314  }
315 
316  Tensor outerSquare(const Tensor& first) {
317  Tensor result(first);
318  result.outerSquare();
319  return result;
320  }
321 
322  Tensor elementMultiply(const Tensor& first, const Tensor& second) {
323  Tensor result(first);
324  result.elementMultiplyBy(second);
325  return result;
326  }
327 
328  Tensor elementDivide(const Tensor& first, const Tensor& second) {
329  Tensor result(first);
330  result.elementDivideBy(second);
331  return result;
332  }
333 
334 }
TensorData toVector(TensorData origin)
Definition: Operations.cc:114
Tensor elementDivide(const Tensor &first, const Tensor &second)
divides two tensors of the same rank and same dimensions element by element
Definition: Tensor.cc:328
Tensor & outerSquare()
creates a tensor with twice the rank by multiplying the tensor with its hermitean conjugate ...
Definition: Tensor.cc:162
Tensor & spinSum()
trace some of the indices of this tensor
Definition: Tensor.cc:144
Log & getLog() const
logging facility
Definition: Tensor.cc:110
std::complex< double > & element(const IndexList &indices={})
access an element given its indices
Definition: Tensor.cc:67
Tensor & spinAverage()
trace over the traceable spin indices and divide by the product of the dimensions of the traced indic...
Definition: Tensor.cc:155
Tensor & toVector()
forces conversion of a tensor to vector type
Definition: Tensor.cc:171
Tensor & addAt(const Tensor &t, IndexLabel coord, IndexType position)
add a tensor of rank N-1 to a specific position in a specific coordinate the dimension of the tensor ...
Definition: Tensor.cc:259
Tensor & operator+=(const Tensor &other)
sums another tensor to itself
Definition: Tensor.cc:187
TensorData read(const Serial::FBTensor *msgreader)
Definition: Operations.cc:76
std::vector< IndexPair > IndexPairList
LabelsList labels() const
get the labels of all the indices at once
Definition: Tensor.cc:83
const std::string & name() const
get the tensor name
Definition: Tensor.cc:102
Tensor outerSquare(const Tensor &first)
creates a tensor with twice the rank by multiplying the tensor with it&#39;s hermitean conjugate ...
Definition: Tensor.cc:316
TensorData calcTrace(TensorData origin, const IndexPairList &indices)
Definition: Operations.cc:46
void write(flatbuffers::FlatBufferBuilder *msgwriter, flatbuffers::Offset< Serial::FBTensor > *msg) const
write the contents of the tensor for serialization
Definition: Tensor.cc:233
Tensor elementMultiply(const Tensor &first, const Tensor &second)
multiplies two tensors of the same rank and same dimensions element by element
Definition: Tensor.cc:322
bool hasFFLabels() const
checks if Tensor has indices in the FF range
Definition: Tensor.cc:92
uint16_t IndexType
Tensor operations.
TensorData calcDot(TensorData origin, const IContainer &other, const IndexPairList &indices)
Definition: Operations.cc:41
std::unique_ptr< IContainer > TensorData
size_t rank() const
rank of the tensor
Definition: Tensor.cc:75
static Log & getLog(const std::string &name)
Get a logger with the given name.
Definition: Logging.cc:139
Tensor spinSum(const Tensor &first)
trace a tensor
Definition: Tensor.cc:274
Tensor & operator*=(double val)
multiply all the elements of the tensor by a real number
Definition: Tensor.cc:176
(Sum of) Outer product tensor data container
Hammer exception definitions.
Interface class for tensor container data structure.
MultiDimensional::TensorData _data
Definition: Tensor.hh:196
std::vector< IndexType > IndexList
Order-0 tensor data container.
Logging class.
Definition: Logging.hh:33
Invalid index label error class.
Definition: Exceptions.hh:39
TensorData calcSquare(TensorData origin)
Definition: Operations.cc:51
IndexLabel
label identifiers of tensor indices they are used to determine which indices can be contracted togeth...
Definition: IndexLabels.hh:27
Multidimensional tensor class with complex numbers as elements.
Definition: Tensor.hh:33
Generic error class.
Definition: Exceptions.hh:23
bool isEqualTo(const Tensor &other) const
Definition: Tensor.cc:106
Tensor operator*(const Tensor &first, double val)
left multiplies a tensor by a real constant
Definition: Tensor.cc:286
void clearData()
sets all the elements to 0
Definition: Tensor.cc:229
TensorData elementMultiply(TensorData origin, const IContainer &other)
Definition: Operations.cc:61
std::string _name
the tensor name
Definition: Tensor.hh:195
TensorData combineSharedTensors(std::vector< std::pair< SharedTensorData, bool >> &&data)
TensorData addAt(TensorData origin, const IContainer &other, IndexType index, IndexType position)
Definition: Operations.cc:71
std::vector< IndexLabel > LabelsList
std::set< IndexLabel > UniqueLabelsList
Tensor & elementDivideBy(const Tensor &other)
divide two tensors element by element and stores the result in this tensor
Definition: Tensor.cc:215
Tensor spinAverage(const Tensor &first)
trace a tensor over the traceable spin indices and divide by the product of the dimensions of the tra...
Definition: Tensor.cc:280
Tensor & dot(const Tensor &other, const UniqueLabelsList &indices={})
contract this tensor with another and stores the result in this tensor
Definition: Tensor.cc:114
TensorData reOptimize(TensorData origin)
Definition: Operations.cc:104
IndexList dims() const
get the dimensions of all the indices at once
Definition: Tensor.cc:79
Tensor & elementMultiplyBy(const Tensor &other)
multiply two tensors element by element and stores the result in this tensor
Definition: Tensor.cc:201
void read(const Serial::FBTensor *msgreader)
read the contents of the tensor for serialization
Definition: Tensor.cc:245
TensorData elementDivide(TensorData origin, const IContainer &other)
Definition: Operations.cc:66
TensorData sum(TensorData origin, const IContainer &other)
Definition: Operations.cc:56
Histogram operator+(const Histogram &first, const Histogram &second)
Definition: Histogram.cc:412
Hammer tensor class.
Serialization related typedefs and includes.
bool hasFFVarLabels() const
checks if Tensor has indices in the FF Var range
Definition: Tensor.cc:97
Tensor & operator=(const Tensor &other)
Definition: Tensor.cc:47
bool hasWCLabels() const
checks if Tensor has indices in the WC range
Definition: Tensor.cc:87
Tensor dot(const Tensor &first, const Tensor &second, const set< IndexLabel > &indices)
Definition: Tensor.cc:268