MPQC 3.0.0-alpha
Loading...
Searching...
No Matches
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
28namespace sc {
29
30namespace sma2 {
31
33 public:
34 inline void operator()(double &res, double val) { res += val; }
35};
36
38 public:
39 inline void operator()(double &res, double val) { res /= val; }
40};
41
42template <int N, int N2>
43void get_all_indices(
44 const ContractPart<N> &array,
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
91template <int N>
92template <int N2, class Op>
93void 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
198template <int N>
199template <class Op>
200void 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
239template <int N>
240template <int Nl,int Nr>
241void 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
343template <int N>
344template <int Nl,int Nr>
345void 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
438template <int N>
439ContractPart<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
445template <int N>
446ContractPart<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
454template <int N>
455ContractPart<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
465template <int N>
466ContractPart<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
478template <int N>
479ContractPart<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
493template <int N>
494ContractPart<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
510template <int N>
511ContractPart<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
529template <int N>
530void ContractPart<N>::apply_factor(double f)
531{
532 factor_ *= f;
533}
534
535template <int N>
536double ContractPart<N>::factor() const
537{
538 return factor_;
539}
540
541template <int N>
542Array<N>& ContractPart<N>::array() const { return array_; }
543
544template <int N>
545const Index &ContractPart<N>::index(int i) const { return indices_[i]; }
546
547template <int N>
548template <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.
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 }
594 typename sma2::Array<N2>::blockmap_t::const_iterator
595 A_iter_begin = A.blockmap().lower_bound(first_A_bi);
596 typename sma2::Array<N2>::blockmap_t::const_iterator
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
610template <int N>
612 SumOperation op;
613 do_binary_op(1.0, o, true, op);
614}
615
616template <int N>
617template <int N2>
618void 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
623template <int N>
624void ContractPart<N>::operator += (const ContractPart<N> &o) const {
625 SumOperation op;
626 do_binary_op(1.0, o, false, op);
627}
628
629template <int N>
630template <int N2>
631void 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
636template <int N>
637void ContractPart<N>::operator /= (const ContractPart<N> &o) const {
638 DivOperation op;
639 do_binary_op(1.0, o, false, op);
640}
641
642template <int N>
643template <int N2>
644void 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
649template <int N>
650void ContractPart<N>::operator -= (const ContractPart<N> &o) const {
651 SumOperation op;
652 do_binary_op(-1.0, o, false, op);
653}
654
655template <int N>
656template <int Nl,int Nr>
657void ContractPart<N>::operator = (const ContractProd<Nl,Nr> &o) const {
658 doprod(1.0, o, true);
659}
660
661template <int N>
662template <int Nl,int Nr>
663void ContractPart<N>::operator += (const ContractProd<Nl,Nr> &o) const{
664 doprod(1.0, o, false);
665}
666
667template <int N>
668template <int Nl,int Nr>
669void ContractPart<N>::operator -= (const ContractProd<Nl,Nr> &o) const{
670 doprod(-1.0, o, false);
671}
672
673template <int N>
674template <int Nl,int Nr>
675void ContractPart<N>::operator |= (const ContractProd<Nl,Nr> &o) const {
676 dounion(o);
677}
678
679template <int N>
680ContractPart<N> operator *(double f, const ContractPart<N> &o)
681{
682 ContractPart<N> result(o);
683 result.apply_factor(f);
684 return result;
685}
686
687template <int N>
689{
690 ContractPart<N> result(*this);
691 result.clear_after_use_ = true;
692 return result;
693}
694
695template <int N>
697{
698 ContractPart<N> result(*this);
699 result.skip_bounds_update_ = true;
700 return result;
701}
702
703template <int N>
704double
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 }
721 typename Array<N>::blockmap_t::const_iterator
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
Implements a block sparse tensor.
Definition sma.h:1247
blockmap_t::value_type & add_unallocated_block(const BlockInfo< N > &b)
Adds block b.
Definition sma.h:1516
const blockmap_t & blockmap() const
Return the block map.
Definition sma.h:1490
const Range & index(int i) const
Gets the i'th Range.
Definition sma.h:1503
BlockInfo stores info about a block of data.
Definition sma.h:200
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
Represents an array and symbolic indices in a contraction.
Definition sma.h:1095
ContractPart< N > operator~() const
Instruct the contract routine to clear this array immediately after use.
Definition contractpartdef.h:688
double value()
Extract a value from the array.
Definition contractpartdef.h:705
ContractPart< N > skip_bounds_update() const
Causes the bounds to not be computed for the LHS operand for certain operations.
Definition contractpartdef.h:696
void operator|=(const ContractPart< N2 > &o) const
Add blocks to this corresponding the blocks already allocated in o.
Definition contractpartdef.h:549
Definition contractpartdef.h:37
An IndexList is a vector of indices.
Definition sma.h:160
bool symbolically_equivalent(const Index &i) const
Returns true if the indices have non-empty names which are the same.
Definition sma.h:1079
bool has_value() const
Returns true if the index has a value, indicating that the index is to be fixed.
Definition sma.h:1074
int value() const
Return the value of the index.
Definition sma.h:1071
int nindex() const
Returns the dimension of this range.
Definition sma.h:125
Definition contractpartdef.h:32
SpinCase1 other(SpinCase1 S)
given 1-spin return the other 1-spin
Contains all MPQC code up to version 3.
Definition mpqcin.h:14

Generated at Wed Sep 25 2024 02:45:29 for MPQC 3.0.0-alpha using the documentation package Doxygen 1.12.0.