MPQC  3.0.0-alpha
contractpartdef.h
1 
2 /*
3  * Copyright 2009 Sandia Corporation. Under the terms of Contract
4  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
5  * retains certain rights in this software.
6  *
7  * This file is a part of the MPQC LMP2 library.
8  *
9  * The MPQC LMP2 library is free software: you can redistribute it
10  * and/or modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation, either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this program. If not, see
21  * <http://www.gnu.org/licenses/>.
22  *
23  */
24 
25 #ifndef _chemistry_qc_lmp2_contractpartdef_h
26 #define _chemistry_qc_lmp2_contractpartdef_h
27 
28 namespace sc {
29 
30 namespace sma2 {
31 
32 class SumOperation {
33  public:
34  inline void operator()(double &res, double val) { res += val; }
35 };
36 
37 class DivOperation {
38  public:
39  inline void operator()(double &res, double val) { res /= val; }
40 };
41 
42 template <int N, int N2>
43 void get_all_indices(
44  const ContractPart<N> &array,
45  const ContractPart<N2> &other,
46  std::vector<int> &fixed, std::vector<int> &fixed_values,
47  std::vector<int> &external, std::vector<int> &external_on_other,
48  bool same_external_index_order_required)
49 {
50  for (int i=0; i<array.array().nindex(); i++) {
51  bool found = false, isfixed = false;
52  // see if the index is fixed
53  if (array.index(i).has_value()) {
54  isfixed = true;
55  if (i != fixed.size()) {
56  throw std::runtime_error("fixed indices must be first");
57  }
58  fixed.push_back(i);
59  fixed_values.push_back(array.index(i).value());
60  }
61  // see if the index is external
62  // note: it is possible for an index to be both fixed and external
63  for (int j=0; j<other.array().nindex(); j++) {
64  if (array.index(i).symbolically_equivalent(other.index(j))) {
65  external.push_back(i);
66  external_on_other.push_back(j);
67  found = true;
68  break;
69  }
70  }
71  if (isfixed && !found) {
72  if (!array.array().index(i).all_size_one()) {
73  throw std::runtime_error("nonexternal fixed indices require blocksize == 1");
74  }
75  }
76  if (!found && !isfixed) {
77  throw std::runtime_error("index not found");
78  }
79  }
80 
81  if (same_external_index_order_required) {
82  for (int i=1; i<external_on_other.size(); i++) {
83  if (external_on_other[i] < external_on_other[i-1]) {
84  throw
85  std::runtime_error("external indices must be in same order");
86  }
87  }
88  }
89 }
90 
91 template <int N>
92 template <int N2, class Op>
93 void ContractPart<N>::do_binary_op_with_fixed_indices(
94  double f, const ContractPart<N2> &o, bool initarray, Op &op) const
95 {
96  double alpha = f * o.factor() / factor();
97  if (initarray) {
98  array_.allocate_blocks();
99  array_.zero();
100  }
101 
102  // compute the index arrays for C
103  sma2::Array<N> &C = array_;
104  std::vector<int> C_fixed, C_fixed_values;
105  std::vector<int> C_external, C_external_on_A;
106  get_all_indices(*this, o, C_fixed, C_fixed_values, C_external,
107  C_external_on_A, false);
108 
109  // compute the index arrays for A
110  const sma2::Array<N2> &A = o.array();
111  std::vector<int> A_fixed, A_fixed_values;
112  std::vector<int> A_external, A_external_on_C;
113  get_all_indices(o, *this, A_fixed, A_fixed_values, A_external,
114  A_external_on_C, false);
115 
116  // Fill in the blocks in A that are fixed. The remaining
117  // indices will be filled from C's external indices.
118  sma2::BlockInfo<N2> A_bi;
119  for (int i=0; i<A_fixed.size(); i++) {
120 // std::cout << "assigning A_bi.block(" << A_fixed[i] << ") to "
121 // << A_fixed_values[i]
122 // << std::endl;
123  A_bi.block(A_fixed[i]) = A_fixed_values[i];
124  }
125 
126  // These index lists are needed to set up A's BlockInfo
127  sma2::IndexList A_external_il(A_external);
128  sma2::IndexList A_external_on_C_il(A_external_on_C);
129 
130  // find the range for the blocks in C that have the correct
131  // fixed indices
132  sma2::BlockInfo<N> first_C_bi;
133  sma2::BlockInfo<N> last_C_bi;
134  for (int i=0; i<N; i++) {
135  first_C_bi.block(i) = 0;
136  last_C_bi.block(i) = C.index(i).nindex();
137  }
138  for (int i=0; i<C_fixed.size(); i++) {
139  first_C_bi.block(C_fixed[i]) = C_fixed_values[i];
140  last_C_bi.block(C_fixed[i]) = C_fixed_values[i];
141  }
142  typename sma2::Array<N>::blockmap_t::const_iterator
143  C_iter_begin = C.blockmap().lower_bound(first_C_bi);
144  typename sma2::Array<N>::blockmap_t::const_iterator
145  C_iter_fence = C.blockmap().upper_bound(last_C_bi);
146 
147  bool same_index_order = A_external_on_C_il.is_identity();
148 
149 // std::cout << "in sum routine" << std::endl;
150 
151 // std::cout << "A_external_on_C_il:" << std::endl;
152 // for (int i=0; i<A_external_on_C_il.n(); i++) {
153 // std::cout << " " << A_external_on_C_il.i(i);
154 // }
155 // std::cout << std::endl;
156 
157 // std::cout << "A_external_il:" << std::endl;
158 // for (int i=0; i<A_external_il.n(); i++) {
159 // std::cout << " " << A_external_il.i(i);
160 // }
161 // std::cout << std::endl;
162 
163  // iterate through relevant blocks in C
164  for (typename sma2::Array<N>::blockmap_t::const_iterator C_iter = C_iter_begin;
165  C_iter != C_iter_fence;
166  C_iter++) {
167  const sma2::BlockInfo<N> &C_bi = C_iter->first;
168  // find the contributing block in A
169  A_bi.assign_blocks(A_external_il, C_bi, A_external_on_C_il);
170 // std::cout << "C block " << C_bi
171 // << " A block " << A_bi
172 // << std::endl;
173  typename sma2::Array<N2>::blockmap_t::const_iterator
174  A_iter = A.blockmap().find(A_bi);
175  if (A_iter == A.blockmap().end()) continue;
176  double *C_data = C_iter->second;
177  double *A_data = A_iter->second;
178  int sz = C.block_size(C_bi);
179 // std::cout << " sz = " << sz << std::endl;
180  if (same_index_order) {
181  for (int i=0; i<sz; i++) {
182  op(C_data[i], alpha * A_data[i]);
183  }
184  }
185  else {
186  BlockIter<N> cbiter(C.indices(),C_bi);
187  int coff = 0;
188  for (cbiter.start(); cbiter.ready(); cbiter++,coff++) {
189  int aoff = cbiter.subset_offset(A_external_on_C_il);
190  op(C_data[coff], alpha * A_data[aoff]);
191  }
192  }
193  }
194 
195  if (!skip_bounds_update_) C.compute_bounds();
196 }
197 
198 template <int N>
199 template <class Op>
200 void ContractPart<N>::do_binary_op(double f, const ContractPart<N> &o,
201  bool initarray, Op &op) const {
202  int nvalue = 0;
203  for (int i=0; i<N; i++) {
204  if (index(i).has_value()) nvalue++;
205  }
206  for (int i=0; i<N; i++) {
207  if (o.index(i).has_value()) nvalue++;
208  }
209  if (nvalue) {
210  do_binary_op_with_fixed_indices(f,o,initarray,op);
211  return;
212  }
213 
214  std::vector<int> indvec;
215  for (int i=0; i<N; i++) {
216  for (int j=0; j<N; j++) {
217  if (o.index(i) == index(j)) {
218  indvec.push_back(j);
219  break;
220  }
221  }
222  }
223  if (indvec.size() != N) {
224  throw std::invalid_argument("sma::ContractPart: nindex != N");
225  }
226  double alpha = f * o.factor() / factor();
227  IndexList indlist(indvec);
228  if (initarray) {
229  array_.allocate_blocks();
230  array_.zero();
231  // the blocks and indices should already be initialized
232  // so this shouldn't be needed.
233  for (int i=0; i<N; i++)
234  array_.set_index(indlist.i(i),o.array().index(i));
235  }
236  binary_op(array_, alpha, o.array(), indlist, skip_bounds_update_, op);
237 }
238 
239 template <int N>
240 template <int Nl,int Nr>
241 void ContractPart<N>::doprod(double f, const ContractProd<Nl,Nr> &o,
242  bool initarray) const {
243  std::vector<int> extCAv, extCBv, extAv, extBv, intAv, intBv;
244  std::vector<int> fixextCAv, fixextCBv, fixextAv, fixextBv;
245 
246  for (int i=0; i<N; i++) {
247  for (int j=0; j<Nl; j++) {
248  if (indices_[i].symbolically_equivalent(o.l.index(j))) {
249  extAv.push_back(j);
250  extCAv.push_back(i);
251  if (o.l.index(j).has_value() != indices_[i].has_value()
252  || (indices_[i].has_value()
253  && indices_[i].value() != o.l.index(j).value())) {
254  throw std::runtime_error("ContractPart<N>::doprod: two equivalent indices do not have the same value");
255  }
256  if (indices_[i].has_value()) {
257  fixextAv.push_back(j);
258  fixextCAv.push_back(i);
259  }
260  }
261  }
262  }
263 
264  for (int i=0; i<N; i++) {
265  for (int j=0; j<Nr; j++) {
266  if (indices_[i].symbolically_equivalent(o.r.index(j))) {
267  extBv.push_back(j);
268  extCBv.push_back(i);
269  if (o.r.index(j).has_value() != indices_[i].has_value()
270  || (indices_[i].has_value()
271  && indices_[i].value() != o.r.index(j).value())) {
272  throw std::runtime_error("ContractPart::doprod: two equivalent indices do not have the same value");
273  }
274  if (indices_[i].has_value()) {
275  fixextBv.push_back(j);
276  fixextCBv.push_back(i);
277  }
278  }
279  }
280  }
281 
282  for (int i=0; i<Nl; i++) {
283  for (int j=0; j<Nr; j++) {
284  if (o.l.index(i).symbolically_equivalent(o.r.index(j))) {
285  intAv.push_back(i);
286  intBv.push_back(j);
287  }
288  }
289  }
290 
291  IndexList extCA(extCAv), extCB(extCBv);
292  IndexList intA(intAv), extA(extAv);
293  IndexList intB(intBv), extB(extBv);
294  IndexList fixextCA(fixextCAv), fixextCB(fixextCBv);
295  IndexList fixextA(fixextAv), fixextB(fixextBv);
296 
297  // Find the values of the fixed indices.
298  std::vector<int> fixCv, fixAv, fixBv;
299  std::vector<sma2::bi_t> fixvalCv, fixvalAv, fixvalBv;
300  for (int i=0; i<N; i++) {
301  if (indices_[i].has_value()) {
302  fixCv.push_back(i);
303  fixvalCv.push_back(indices_[i].value());
304  }
305  }
306  for (int i=0; i<Nl; i++) {
307  if (o.l.index(i).has_value()) {
308  fixAv.push_back(i);
309  fixvalAv.push_back(o.l.index(i).value());
310  }
311  }
312  for (int i=0; i<Nr; i++) {
313  if (o.r.index(i).has_value()) {
314  fixBv.push_back(i);
315  fixvalBv.push_back(o.r.index(i).value());
316  }
317  }
318 
319  IndexList fixC(fixCv), fixA(fixAv), fixB(fixBv);
320  BlockInfo<N> fixvalC(fixvalCv);
321  BlockInfo<Nl> fixvalA(fixvalAv);
322  BlockInfo<Nr> fixvalB(fixvalBv);
323 
324  double ABfactor = f * o.l.factor() * o.r.factor() / factor();
325 
326  if (initarray) {
327  array_.allocate_blocks();
328  array_.zero();
329  for (int i=0; i<extCA.n(); i++) {
330  array_.set_index(extCA.i(i), o.l.array().index(extA.i(i)));
331  }
332  for (int i=0; i<extCB.n(); i++) {
333  array_.set_index(extCB.i(i), o.r.array().index(extB.i(i)));
334  }
335  }
336 
337  contract(array_, extCA, extCB, fixextCA, fixextCB, fixC, fixvalC,
338  o.l.array(), extA, fixextA, intA, fixA, fixvalA, o.l.clear_after_use(),
339  o.r.array(), extB, fixextB, intB, fixB, fixvalB, o.r.clear_after_use(),
340  ABfactor, initarray, o.regtimer);
341 }
342 
343 template <int N>
344 template <int Nl,int Nr>
345 void ContractPart<N>::dounion(const ContractProd<Nl,Nr> &o) const {
346  std::vector<int> extCAv, extCBv, extAv, extBv, intAv, intBv;
347 
348  for (int i=0; i<N; i++) {
349  for (int j=0; j<Nl; j++) {
350  if (indices_[i].symbolically_equivalent(o.l.index(j))) {
351  extAv.push_back(j);
352  extCAv.push_back(i);
353  }
354  }
355  }
356 
357  for (int i=0; i<N; i++) {
358  for (int j=0; j<Nr; j++) {
359  if (indices_[i].symbolically_equivalent(o.r.index(j))) {
360  extBv.push_back(j);
361  extCBv.push_back(i);
362  }
363  }
364  }
365 
366  for (int i=0; i<Nl; i++) {
367  for (int j=0; j<Nr; j++) {
368  if (o.l.index(i).symbolically_equivalent(o.r.index(j))) {
369  intAv.push_back(i);
370  intBv.push_back(j);
371  }
372  }
373  }
374 
375  IndexList extCA(extCAv), extCB(extCBv);
376  IndexList intA(intAv), extA(extAv);
377  IndexList intB(intBv), extB(extBv);
378 
379  std::vector<int> fixCv, fixAv, fixBv;
380  std::vector<sma2::bi_t> fixvalCv, fixvalAv, fixvalBv;
381  for (int i=0; i<N; i++) {
382  if (indices_[i].has_value()) {
383  if (fixCv.size() != i)
384  throw std::invalid_argument("fixed indices must be first (in C)");
385  fixCv.push_back(i);
386  fixvalCv.push_back(indices_[i].value());
387  if (fixvalCv[i] >= array().index(i).nblock()) {
388  throw std::invalid_argument("fixed index out of range (in C)");
389  }
390  }
391  }
392  for (int i=0; i<Nl; i++) {
393  if (o.l.index(i).has_value()) {
394  if (fixAv.size() != i)
395  throw std::invalid_argument("fixed indices must be first (in A)");
396  fixAv.push_back(i);
397  fixvalAv.push_back(o.l.index(i).value());
398  if (fixvalAv[i] >= o.l.array().index(i).nblock()) {
399  throw std::invalid_argument("fixed index out of range (in A)");
400  }
401  }
402  }
403  for (int i=0; i<Nr; i++) {
404  if (o.r.index(i).has_value()) {
405  fixBv.push_back(i);
406  fixvalBv.push_back(o.r.index(i).value());
407  if (fixvalBv[i] >= o.r.array().index(i).nblock()) {
408  throw std::invalid_argument("fixed index out of range (in B)");
409  }
410  }
411  }
412 
413  IndexList fixC(fixCv), fixA(fixAv), fixB(fixBv);
414  BlockInfo<N> fixvalC(fixvalCv);
415  BlockInfo<Nl> fixvalA(fixvalAv);
416  BlockInfo<Nr> fixvalB(fixvalBv);
417 
418  bool bad_index = false;
419  for (int i=0; i<extCA.n(); i++) {
420  if (array_.index(extCA.i(i)) != o.l.array().index(extA.i(i)))
421  bad_index = true;
422  //array_.set_index(extCA.i(i), o.l.array().index(extA.i(i)));
423  }
424  for (int i=0; i<extCB.n(); i++) {
425  if (array_.index(extCB.i(i)) != o.r.array().index(extB.i(i)))
426  bad_index = true;
427  //array_.set_index(extCB.i(i), o.r.array().index(extB.i(i)));
428  }
429  if (bad_index) {
430  throw std::invalid_argument("sma2::contract_union: C range inconsistency");
431  }
432 
433  contract_union(array_, extCA, extCB, fixC, fixvalC,
434  o.l.array(), extA, intA, fixA, fixvalA,
435  o.r.array(), extB, intB, fixB, fixvalB);
436 }
437 
438 template <int N>
439 ContractPart<N>::ContractPart(Array<N> &array):
440  array_(array), factor_(1.0), clear_after_use_(false),
441  skip_bounds_update_(false) {
442  if (N != 0) throw std::invalid_argument("sma::ContractPart: N != 0");
443 }
444 
445 template <int N>
446 ContractPart<N>::ContractPart(Array<N> &array,
447  const Index &i1):
448  array_(array), factor_(1.0), clear_after_use_(false),
449  skip_bounds_update_(false) {
450  if (N != 1) throw std::invalid_argument("sma::ContractPart: N != 1");
451  indices_.push_back(i1);
452 }
453 
454 template <int N>
455 ContractPart<N>::ContractPart(Array<N> &array,
456  const Index &i1,
457  const Index &i2):
458  array_(array), factor_(1.0), clear_after_use_(false),
459  skip_bounds_update_(false) {
460  if (N != 2) throw std::invalid_argument("sma::ContractPart: N != 2");
461  indices_.push_back(i1);
462  indices_.push_back(i2);
463 }
464 
465 template <int N>
466 ContractPart<N>::ContractPart(Array<N> &array,
467  const Index &i1,
468  const Index &i2,
469  const Index &i3):
470  array_(array), factor_(1.0), clear_after_use_(false),
471  skip_bounds_update_(false) {
472  if (N != 3) throw std::invalid_argument("sma::ContractPart: N != 3");
473  indices_.push_back(i1);
474  indices_.push_back(i2);
475  indices_.push_back(i3);
476 }
477 
478 template <int N>
479 ContractPart<N>::ContractPart(Array<N> &array,
480  const Index &i1,
481  const Index &i2,
482  const Index &i3,
483  const Index &i4):
484  array_(array), factor_(1.0), clear_after_use_(false),
485  skip_bounds_update_(false) {
486  if (N != 4) throw std::invalid_argument("sma::ContractPart: N != 4");
487  indices_.push_back(i1);
488  indices_.push_back(i2);
489  indices_.push_back(i3);
490  indices_.push_back(i4);
491 }
492 
493 template <int N>
494 ContractPart<N>::ContractPart(Array<N> &array,
495  const Index &i1,
496  const Index &i2,
497  const Index &i3,
498  const Index &i4,
499  const Index &i5):
500  array_(array), factor_(1.0), clear_after_use_(false),
501  skip_bounds_update_(false) {
502  if (N != 5) throw std::invalid_argument("sma::ContractPart: N != 5");
503  indices_.push_back(i1);
504  indices_.push_back(i2);
505  indices_.push_back(i3);
506  indices_.push_back(i4);
507  indices_.push_back(i5);
508 }
509 
510 template <int N>
511 ContractPart<N>::ContractPart(Array<N> &array,
512  const Index &i1,
513  const Index &i2,
514  const Index &i3,
515  const Index &i4,
516  const Index &i5,
517  const Index &i6):
518  array_(array), factor_(1.0), clear_after_use_(false),
519  skip_bounds_update_(false) {
520  if (N != 6) throw std::invalid_argument("sma::ContractPart: N != 6");
521  indices_.push_back(i1);
522  indices_.push_back(i2);
523  indices_.push_back(i3);
524  indices_.push_back(i4);
525  indices_.push_back(i5);
526  indices_.push_back(i6);
527 }
528 
529 template <int N>
530 void ContractPart<N>::apply_factor(double f)
531 {
532  factor_ *= f;
533 }
534 
535 template <int N>
536 double ContractPart<N>::factor() const
537 {
538  return factor_;
539 }
540 
541 template <int N>
542 Array<N>& ContractPart<N>::array() const { return array_; }
543 
544 template <int N>
545 const Index &ContractPart<N>::index(int i) const { return indices_[i]; }
546 
547 template <int N>
548 template <int N2>
550 {
551  // compute the index arrays for C
552  sma2::Array<N> &C = array_;
553  std::vector<int> C_fixed, C_fixed_values;
554  std::vector<int> C_external, C_external_on_A;
555  get_all_indices(*this, o, C_fixed, C_fixed_values, C_external,
556  C_external_on_A, false);
557 
558  // compute the index arrays for A
559  const sma2::Array<N2> &A = o.array();
560  std::vector<int> A_fixed, A_fixed_values;
561  std::vector<int> A_external, A_external_on_C;
562  get_all_indices(o, *this, A_fixed, A_fixed_values, A_external,
563  A_external_on_C, false);
564 
565  for (int i=0; i<A_external.size(); i++) {
566  if (A.index(A_external[i]) != C.index(A_external_on_C[i])) {
567  throw std::invalid_argument("|=: Range conflict between A and C");
568  }
569  }
570 
571  // Fill in the blocks in C that are fixed. The remaining
572  // indices will be filled from A's external indices.
573  sma2::BlockInfo<N> C_bi;
574  for (int i=0; i<C_fixed.size(); i++) {
575  C_bi.block(C_fixed[i]) = C_fixed_values[i];
576  }
577 
578  // These index lists are needed to set up A's BlockInfo
579  sma2::IndexList A_external_il(A_external);
580  sma2::IndexList C_external_il(A_external_on_C);
581 
582  // find the range for the blocks in A that have the correct
583  // fixed indices
584  sma2::BlockInfo<N2> first_A_bi;
585  sma2::BlockInfo<N2> last_A_bi;
586  for (int i=0; i<N2; i++) {
587  first_A_bi.block(i) = 0;
588  last_A_bi.block(i) = A.index(i).nindex();
589  }
590  for (int i=0; i<A_fixed.size(); i++) {
591  first_A_bi.block(A_fixed[i]) = A_fixed_values[i];
592  last_A_bi.block(A_fixed[i]) = A_fixed_values[i];
593  }
595  A_iter_begin = A.blockmap().lower_bound(first_A_bi);
597  A_iter_fence = A.blockmap().upper_bound(last_A_bi);
598 
599  // iterate through relevant blocks in A
600  for (typename sma2::Array<N2>::blockmap_t::const_iterator A_iter = A_iter_begin;
601  A_iter != A_iter_fence;
602  A_iter++) {
603  const typename sma2::BlockInfo<N2> &A_bi = A_iter->first;
604  // find the contributing block in C
605  C_bi.assign_blocks(C_external_il, A_bi, A_external_il);
606  C.add_unallocated_block(C_bi);
607  }
608 }
609 
610 template <int N>
611 void ContractPart<N>::operator = (const ContractPart<N> &o) const {
612  SumOperation op;
613  do_binary_op(1.0, o, true, op);
614 }
615 
616 template <int N>
617 template <int N2>
618 void ContractPart<N>::operator = (const ContractPart<N2> &o) const {
619  SumOperation op;
620  do_binary_op_with_fixed_indices(1.0,o,true,op);
621 }
622 
623 template <int N>
624 void ContractPart<N>::operator += (const ContractPart<N> &o) const {
625  SumOperation op;
626  do_binary_op(1.0, o, false, op);
627 }
628 
629 template <int N>
630 template <int N2>
631 void ContractPart<N>::operator += (const ContractPart<N2> &o) const {
632  SumOperation op;
633  do_binary_op_with_fixed_indices(1.0,o,false,op);
634 }
635 
636 template <int N>
637 void ContractPart<N>::operator /= (const ContractPart<N> &o) const {
638  DivOperation op;
639  do_binary_op(1.0, o, false, op);
640 }
641 
642 template <int N>
643 template <int N2>
644 void ContractPart<N>::operator /= (const ContractPart<N2> &o) const {
645  DivOperation op;
646  do_binary_op_with_fixed_indices(1.0,o,false,op);
647 }
648 
649 template <int N>
650 void ContractPart<N>::operator -= (const ContractPart<N> &o) const {
651  SumOperation op;
652  do_binary_op(-1.0, o, false, op);
653 }
654 
655 template <int N>
656 template <int Nl,int Nr>
657 void ContractPart<N>::operator = (const ContractProd<Nl,Nr> &o) const {
658  doprod(1.0, o, true);
659 }
660 
661 template <int N>
662 template <int Nl,int Nr>
663 void ContractPart<N>::operator += (const ContractProd<Nl,Nr> &o) const{
664  doprod(1.0, o, false);
665 }
666 
667 template <int N>
668 template <int Nl,int Nr>
669 void ContractPart<N>::operator -= (const ContractProd<Nl,Nr> &o) const{
670  doprod(-1.0, o, false);
671 }
672 
673 template <int N>
674 template <int Nl,int Nr>
675 void ContractPart<N>::operator |= (const ContractProd<Nl,Nr> &o) const {
676  dounion(o);
677 }
678 
679 template <int N>
680 ContractPart<N> operator *(double f, const ContractPart<N> &o)
681 {
682  ContractPart<N> result(o);
683  result.apply_factor(f);
684  return result;
685 }
686 
687 template <int N>
689 {
690  ContractPart<N> result(*this);
691  result.clear_after_use_ = true;
692  return result;
693 }
694 
695 template <int N>
697 {
698  ContractPart<N> result(*this);
699  result.skip_bounds_update_ = true;
700  return result;
701 }
702 
703 template <int N>
704 double
706 {
707  if (indices_.size() != N) {
708  throw std::runtime_error("ContractPart::value: indices_.size() != N");
709  }
710  BlockInfo<N> bi;
711  for (int i=0; i<N; i++) {
712  if (!indices_[i].has_value()) {
713  throw std::runtime_error("ContractPart::value: requires fixed indices");
714  }
715  bi.block(i) = indices_[i].value();
716  }
717  size_t blocksize = array_.block_size(bi);
718  if (blocksize > 1) {
719  throw std::runtime_error("ContractPart::value: blocksize must be 1");
720  }
722  biter = array_.blockmap().find(bi);
723  if (biter == array_.blockmap().end()) {
724  return 0.0;
725  }
726  if (biter->second == 0) {
727  throw std::runtime_error("ContractPart::value: array not allocated");
728  }
729  return *biter->second;
730 }
731 
732 }
733 
734 }
735 
736 #endif
sc::sma2::DivOperation
Definition: contractpartdef.h:37
sc::sma2::ContractPart::value
double value()
Extract a value from the array.
Definition: contractpartdef.h:705
sc::sma2::Array::index
const Range & index(int i) const
Gets the i'th Range.
Definition: sma.h:1503
sc::sma2::ContractPart::skip_bounds_update
ContractPart< N > skip_bounds_update() const
Causes the bounds to not be computed for the LHS operand for certain operations.
Definition: contractpartdef.h:696
sc::sma2::Array::add_unallocated_block
blockmap_t::value_type & add_unallocated_block(const BlockInfo< N > &b)
Adds block b.
Definition: sma.h:1516
sc::sma2::ContractPart::operator|=
void operator|=(const ContractPart< N2 > &o) const
Add blocks to this corresponding the blocks already allocated in o.
Definition: contractpartdef.h:549
sc::sma2::Index::symbolically_equivalent
bool symbolically_equivalent(const Index &i) const
Returns true if the indices have non-empty names which are the same.
Definition: sma.h:1079
sc::sma2::Index::value
int value() const
Return the value of the index.
Definition: sma.h:1071
sc::sma2::BlockInfo
BlockInfo stores info about a block of data.
Definition: sma.h:200
sc::sma2::Array
Implements a block sparse tensor.
Definition: sma.h:1088
sc::sma2::ContractPart::operator~
ContractPart< N > operator~() const
Instruct the contract routine to clear this array immediately after use.
Definition: contractpartdef.h:688
sc::sma2::IndexList
An IndexList is a vector of indices.
Definition: sma.h:160
sc::sma2::ContractPart
Represents an array and symbolic indices in a contraction.
Definition: sma.h:1095
sc::other
SpinCase1 other(SpinCase1 S)
given 1-spin return the other 1-spin
sc::sma2::Range::nindex
int nindex() const
Returns the dimension of this range.
Definition: sma.h:125
sc::sma2::BlockInfo::assign_blocks
void assign_blocks(const IndexList &il, const BlockInfo< N2 > &bi2, const IndexList &il2)
Assign blocks to those in another BlockInfo, bi2, given an IndexList that specifies the index mapping...
Definition: sma.h:268
sc::sma2::Index::has_value
bool has_value() const
Returns true if the index has a value, indicating that the index is to be fixed.
Definition: sma.h:1074
sc::sma2::Array::blockmap
const blockmap_t & blockmap() const
Return the block map.
Definition: sma.h:1490
sc
Contains all MPQC code up to version 3.
Definition: mpqcin.h:14
sc::sma2::SumOperation
Definition: contractpartdef.h:32

Generated at Sun Jan 26 2020 23:23:58 for MPQC 3.0.0-alpha using the documentation package Doxygen 1.8.16.