LIBINT 2.7.2
uncontract.h
1/*
2 * Copyright (C) 2004-2021 Edward F. Valeev
3 *
4 * This file is part of Libint.
5 *
6 * Libint is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Libint is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Libint. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#ifndef _libint2_src_bin_libint_uncontract_h_
22#define _libint2_src_bin_libint_uncontract_h_
23
24#include <iostream>
25#include <string>
26#include <vector>
27#include <stdexcept>
28#include <cassert>
29#include <rr.h>
30#include <integral.h>
31#include <iter.h>
32#include <algebra.h>
33#include <context.h>
34#include <dims.h>
35#include <bfset.h>
36
37namespace libint2 {
38
42 protected:
43 virtual ~Uncontract_Integral_base() {}
44 };
45
49 template <class I>
52 public:
53 typedef I TargetType;
54 typedef TargetType ChildType;
55 typedef typename I::BasisFunctionType BFSet;
58
59 Uncontract_Integral(const SafePtr<I>&);
60 virtual ~Uncontract_Integral() {}
61
63 unsigned int num_children() const override { return children_.size(); }
65 SafePtr<TargetType> target() const { return target_; };
67 SafePtr<ChildType> child(unsigned int i) const;
69 SafePtr<DGVertex> rr_target() const override { return static_pointer_cast<DGVertex,TargetType>(target()); }
71 SafePtr<DGVertex> rr_child(unsigned int i) const override { return static_pointer_cast<DGVertex,ChildType>(child(i)); }
74 bool is_simple() const override {
75 return false;
76 }
77
78 private:
79 SafePtr<TargetType> target_;
80 std::vector< SafePtr<ChildType> > children_;
81
82 // contracting integrals only depends on the number of integrals in a set
83 // can simplify this to only refer to that number
84 std::string generate_label() const override {
85 std::ostringstream os;
86 os << "Generic Contract";
87 return os.str();
88 }
89
90 //
91 std::string spfunction_call(const SafePtr<CodeContext>& context,
92 const SafePtr<ImplicitDimensions>& dims) const override;
93
94 };
95
96
97 template <class I>
98 Uncontract_Integral<I>::Uncontract_Integral(const SafePtr<I>& Tint) :
99 target_(Tint)
100 {
101 target_ = Tint;
102
103 // create the uncontracted version
104 typedef typename I::BraType bratype;
105 typedef typename I::KetType kettype;
106 typedef typename I::OperType opertype;
107 bratype bra_unc = target_->bra();
108 kettype ket_unc = target_->ket();
109 // is it even contracted?
110 bool target_is_contracted = false;
111 {
112 const unsigned int np = bra_unc.num_part();
113 for(unsigned int p=0; p<np; ++p) {
114 const unsigned int nf = bra_unc.num_members(p);
115 for(unsigned int f=0; f<nf; ++f) {
116 target_is_contracted |= bra_unc.member(p,f).contracted();
117 bra_unc.member(p,f).uncontract();
118 }
119 }
120 }
121 {
122 const unsigned int np = ket_unc.num_part();
123 for(unsigned int p=0; p<np; ++p) {
124 const unsigned int nf = ket_unc.num_members(p);
125 for(unsigned int f=0; f<nf; ++f) {
126 target_is_contracted |= ket_unc.member(p,f).contracted();
127 ket_unc.member(p,f).uncontract();
128 }
129 }
130 }
131 opertype oper_unc = target_->oper();
132 const bool oper_contracted = oper_unc.descr().contracted();
133 target_is_contracted |= oper_contracted;
134 oper_unc.descr().uncontract();
135
136 if (target_is_contracted) {
137#if DEBUG
138 std::cout << "Uncontract_Integral: " << target_->description() << " is contracted" << std::endl;
139#endif
140 SafePtr<ChildType> c = ChildType::Instance(bra_unc, ket_unc,
141 target_->aux(),
142 oper_unc);
143 children_.push_back(c);
144 }
145 };
146
147 template <class I>
148 SafePtr<typename Uncontract_Integral<I>::ChildType>
149 Uncontract_Integral<I>::child(unsigned int i) const
150 {
151 return children_.at(i);
152 };
153
154 template <class I>
155 std::string
156 Uncontract_Integral<I>::spfunction_call(const SafePtr<CodeContext>& context,
157 const SafePtr<ImplicitDimensions>& dims) const {
158
159 const unsigned int s = target_->size();
160 SafePtr<CTimeEntity<int> > bdim(new CTimeEntity<int>(s));
161 SafePtr<Entity> bvecdim;
162 bool vectorize = false;
163 if (!dims->vecdim_is_static()) {
164 vectorize = true;
165 SafePtr< RTimeEntity<EntityTypes::Int> > vecdim = dynamic_pointer_cast<RTimeEntity<EntityTypes::Int>,Entity>(dims->vecdim());
166 bvecdim = vecdim * bdim;
167 }
168 else {
169 SafePtr< CTimeEntity<int> > vecdim = dynamic_pointer_cast<CTimeEntity<int>,Entity>(dims->vecdim());
170 vectorize = vecdim->value() == 1 ? false : true;
171 bvecdim = vecdim * bdim;
172 }
173
174 std::ostringstream os;
175 // contraction = reduction
176 if (!vectorize || !TrivialBFSet<BFSet>::result || context->cparams()->vectorize_by_line()) {
177 os << "_libint2_static_api_inc1_short_("
178 << context->value_to_pointer(rr_target()->symbol()) << ","
179 << context->value_to_pointer(rr_child(0)->symbol()) << ","
180 << bvecdim->id()
181 << ")" << context->end_of_stat() << std::endl;
182 }
183 else { // blockwise vectorize for a single integral
184 os << "_libint2_static_api_inc1_short_("
185 << context->value_to_pointer(rr_target()->symbol()) << "+vi,"
186 << context->value_to_pointer(rr_child(0)->symbol()) << ",1)" << context->end_of_stat() << std::endl;
187 }
188 unsigned int& nflops_ref = const_cast<unsigned int&>(nflops_);
189 nflops_ref += target_->size();
190
191 return os.str();
192 }
193
195 struct DecontractedIntegralSet : public std::unary_function<const SafePtr<DGVertex>&,bool> {
196 bool operator()(const SafePtr<DGVertex>& V) {
197 const unsigned int outdegree = V->num_exit_arcs();
198 if (outdegree == 0) return false;
199
200 const SafePtr<DGArc> arc0 = *(V->first_exit_arc());
201 // Is this DGArcRR?
202 const SafePtr<DGArcRR> arcrr = dynamic_pointer_cast<DGArcRR,DGArc>(arc0);
203 if (arcrr == 0) return false;
204 const SafePtr<Uncontract_Integral_base> uib_ptr = dynamic_pointer_cast<Uncontract_Integral_base,RecurrenceRelation>(arcrr->rr());
205 return uib_ptr != 0;
206 }
207 };
208
209};
210
211#endif
212
AlgebraicOperator is an algebraic operator that acts on objects of type T.
Definition: algebra.h:50
CTimeEntity is an Entity of type T that exists at compile-time of the generated code (hence has a val...
Definition: entity.h:189
Entity is a base class for all objects that exist at compile or runtime of the generated code.
Definition: entity.h:82
const std::string & id() const
Return id string.
Definition: entity.h:86
RecurrenceRelation describes all recurrence relations.
Definition: rr.h:99
Uncontract_Integral_base is dummy class used for dynamic casts only.
Definition: uncontract.h:41
Uncontract_Integral converts (a set of) contracted integral(s) to its uncontracted counterpart.
Definition: uncontract.h:51
SafePtr< DGVertex > rr_child(unsigned int i) const override
Implementation of RecurrenceRelation's child()
Definition: uncontract.h:71
bool is_simple() const override
to inline this would require a unary operator (+=).
Definition: uncontract.h:74
unsigned int num_children() const override
Implementation of RecurrenceRelation::num_children()
Definition: uncontract.h:63
SafePtr< ChildType > child(unsigned int i) const
child(i) returns pointer i-th child
Definition: uncontract.h:149
SafePtr< TargetType > target() const
target() returns pointer to target
Definition: uncontract.h:65
SafePtr< DGVertex > rr_target() const override
Implementation of RecurrenceRelation's target()
Definition: uncontract.h:69
RecurrenceRelation::ExprType ExprType
The type of expressions in which RecurrenceRelations result.
Definition: uncontract.h:57
Defaults definitions for various parameters assumed by Libint.
Definition: algebra.cc:24
return true if V is a decontracted IntegralSet
Definition: uncontract.h:195