File: epsilon_to_delta.cc

package info (click to toggle)
cadabra2 2.4.3.2-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 78,732 kB
  • sloc: ansic: 133,450; cpp: 92,064; python: 1,530; javascript: 203; sh: 184; xml: 182; objc: 53; makefile: 51
file content (114 lines) | stat: -rw-r--r-- 3,317 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

#include "algorithms/epsilon_to_delta.hh"
#include "algorithms/reduce_delta.hh"
#include "properties/EpsilonTensor.hh"
#include "properties/Metric.hh"

using namespace cadabra;

epsilon_to_delta::epsilon_to_delta(const Kernel& k, Ex& tr, bool r)
	: Algorithm(k, tr), reduce(r)
	{
	}

bool epsilon_to_delta::can_apply(iterator st)
	{
	if(*st->name!="\\prod")
		return false;

	epsilons.clear();
	// Find the two epsilon tensors in the product.
	std::multimap<std::string,Ex::iterator> emap;
	sibling_iterator it=tr.begin(st);
	while(it!=tr.end(st)) {
		const EpsilonTensor *eps=kernel.properties.get<EpsilonTensor>(it);
		if(eps) emap.insert(std::pair<std::string,Ex::iterator>(get_index_set_name(begin_index(it)),it));
		++it;
		}
	signature=1;
	std::multimap<std::string,Ex::iterator>::iterator eit=emap.begin();
	while(epsilons.size()<2 && eit!=emap.end()) {
		if(emap.count(eit->first)>1) {
			epsilons.push_back(eit->second);
			++eit;
			epsilons.push_back(eit->second);
			const EpsilonTensor *eps=kernel.properties.get<EpsilonTensor>(eit->second);
			if(eps->metric.begin()!=eps->metric.end()) {
				const Metric *met=kernel.properties.get<Metric>(eps->metric.begin());
				if(met)
					signature=met->signature;
				}
			if(eps->krdelta.begin()!=eps->krdelta.end())
				repdelta=eps->krdelta;
			}
		++eit;
		}
	if(epsilons.size()<2)
		return false;

	if(repdelta.begin()==repdelta.end())
		return false;
	else repdelta.erase_children(repdelta.begin());

	return true;
	}

Algorithm::result_t epsilon_to_delta::apply(iterator& st)
	{
	Ex       rep(repdelta);
	iterator delta=rep.begin();

	// std::cerr << Ex(st) << std::endl;

	sibling_iterator eps1=tr.begin(epsilons[0]);
	sibling_iterator eps2=tr.begin(epsilons[1]);
	while(eps1!=tr.end(epsilons[0])) {
		rep.append_child(delta, *eps1);
		rep.append_child(delta, *eps2);
		++eps1;
		++eps2;
		}
//	std::cerr << "result: " << rep.begin() << std::endl;
	multiply(st->multiplier, *epsilons[0]->multiplier);
	multiply(st->multiplier, *epsilons[1]->multiplier);
	tr.erase(epsilons[0]);
	//	std::cerr << tr.number_of_children(epsilons[1]) << std::endl;
	//	std::cerr << " -> " << *st->multiplier << " * " << combin::fact(multiplier_t(tr.number_of_children(epsilons[1]))) << std::endl;
	multiply(st->multiplier, combin::fact(multiplier_t(tr.number_of_children(epsilons[1]))));
	//	std::cerr << "A:" << *st->multiplier << std::endl;
	multiply(st->multiplier, signature);
	//	std::cerr << "B:" << *st->multiplier << std::endl;

	iterator gend=tr.replace(epsilons[1], rep.begin());
	//	std::cerr << "B2:" << *st->multiplier << std::endl;

	if(reduce) {
		//		std::cerr << "reducing" << std::endl;
		reduce_delta rg(kernel, tr);
		if(rg.can_apply(gend))
			rg.apply(gend);
		if(*gend->multiplier==0) {
			zero(st->multiplier);
			return result_t::l_applied;
			}
		}

	if(*gend->multiplier!=1) {
		//		std::cerr << "B3:" << *st->multiplier << std::endl;
		//		std::cerr << "B3:" << *gend->multiplier << std::endl;
		multiply(tr.parent(gend)->multiplier, *gend->multiplier);
		one(gend->multiplier);
		//		std::cerr << "C:" << *st->multiplier << std::endl;
		}

	if(tr.number_of_children(st)==1) {
		multiply(tr.begin(st)->multiplier, *st->multiplier);
		tr.flatten(st);
		st=tr.erase(st);
		}

	//	std::cerr << Ex(st) << std::endl;

	return result_t::l_applied;
	}