CYCLUS
comp_math.cc
Go to the documentation of this file.
1 #include "comp_math.h"
2 
3 #include <cmath>
4 #include <sstream>
5 
6 #include "cyc_arithmetic.h"
7 #include "error.h"
8 #include "pyne.h"
9 
10 // Undefines isnan from pyne
11 #ifdef isnan
12  #undef isnan
13 #endif
14 
15 namespace cyclus {
16 namespace compmath {
17 
18 CompMap Add(const CompMap& v1, const CompMap& v2) {
19  CompMap out(v1);
20  for (CompMap::const_iterator it = v2.begin(); it != v2.end(); ++it) {
21  int nuc = it->first;
22  out[nuc] += it->second;
23  }
24  return out;
25 }
26 
27 CompMap Sub(const CompMap& v1, const CompMap& v2) {
28  CompMap out(v1);
29  for (CompMap::const_iterator it = v2.begin(); it != v2.end(); ++it) {
30  int nuc = it->first;
31  out[nuc] -= it->second;
32  }
33  return out;
34 }
35 
36 double Sum(const CompMap& v) {
37  std::vector<double> vec;
38  vec.reserve(v.size());
39  for (CompMap::const_iterator it = v.begin(); it != v.end(); ++it) {
40  vec.push_back(it->second);
41  }
42  return CycArithmetic::KahanSum(vec);
43 }
44 
45 void ApplyThreshold(CompMap* v, double threshold) {
46  if (threshold < 0) {
47  std::stringstream ss;
48  ss << "The threshold cannot be negative. The value provided was '"
49  << threshold << "'.";
50  throw ValueError(ss.str());
51  }
52 
53  CompMap::iterator it = v->begin();
54  while (it != v->end()) {
55  if (std::abs(it->second) <= threshold) {
56  v->erase(it++);
57  } else {
58  it++;
59  }
60  }
61 }
62 
63 void Normalize(CompMap* v, double val) {
64  double sum = Sum(*v);
65  if (sum != val && sum != 0) {
66  double mult = val / sum;
67  for (CompMap::iterator it = v->begin(); it != v->end(); ++it) {
68  it->second *= mult;
69  }
70  }
71 }
72 
73 bool ValidNucs(const CompMap& v) {
74  CompMap::const_iterator it;
75  for (it = v.begin(); it != v.end(); ++it) {
76  if (!pyne::nucname::isnuclide(it->first)) {
77  return false;
78  }
79  }
80  return true;
81 }
82 
83 bool AllPositive(const CompMap& v) {
84  CompMap::const_iterator it;
85  for (it = v.begin(); it != v.end(); ++it) {
86  if (it->second < 0) {
87  return false;
88  }
89  }
90  return true;
91 }
92 
93 bool AlmostEq(const CompMap& v1, const CompMap& v2, double threshold) {
94  // I learned at
95  // http://www.ualberta.ca/~kbeach/comp_phys/fp_err.html#testing-for-equality
96  // that the following is less naive than the intuitive way of doing this...
97  // almost equal if :
98  // (abs(x-y) < abs(x)*eps) && (abs(x-y) < abs(y)*epsilon)
99  if (threshold < 0) {
100  std::stringstream ss;
101  ss << "The threshold cannot be negative. The value provided was '"
102  << threshold << "'.";
103  throw ValueError(ss.str());
104  }
105 
106  if (v1.size() != v2.size()) {
107  return false;
108  } else if (v1.empty() && v2.empty()) {
109  return true;
110  }
111 
112  CompMap n1(v1);
113  CompMap n2(v2);
114 
115  CompMap::iterator it;
116  for (it = n1.begin(); it != n1.end(); ++it) {
117  Nuc nuc = it->first;
118  if (n2.count(nuc) == 0) {
119  return false;
120  }
121  double minuend = n2[nuc];
122  double subtrahend = n1[nuc];
123  double diff = minuend - subtrahend;
124  if (std::abs(minuend) == 0 || std::abs(subtrahend) == 0) {
125  if (std::abs(diff) > std::abs(diff)*threshold) {
126  return false;
127  }
128  } else if (std::abs(diff) > std::abs(minuend)*threshold ||
129  std::abs(diff) > std::abs(subtrahend)*threshold) {
130  return false;
131  }
132  }
133  return true;
134 }
135 
136 } // namespace compmath
137 } // namespace cyclus
bool AllPositive(const CompMap &v)
Returns true if all nuclides in v have quantities greater than or equal to zero.
Definition: comp_math.cc:83
CompMap Sub(const CompMap &v1, const CompMap &v2)
Does component-wise subtraction of the nuclide quantities of v1 and v2 and returns the result...
Definition: comp_math.cc:27
bool isnuclide(std::string nuc)
Definition: pyne.cc:2671
For values that are too big, too small, etc.
Definition: error.h:41
bool ValidNucs(const CompMap &v)
Returns true if all nuclide keys in v are valid.
Definition: comp_math.cc:73
bool AlmostEq(const CompMap &v1, const CompMap &v2, double threshold)
Returns true if all nuclides of v1 and v2 are the same within threshold.
Definition: comp_math.cc:93
double Sum(const CompMap &v)
Sums the quantities of all nuclides without normalization.
Definition: comp_math.cc:36
std::map< Nuc, double > CompMap
a raw definition of nuclides and corresponding (dimensionless quantities).
Definition: composition.h:17
CompMap Add(const CompMap &v1, const CompMap &v2)
Does component-wise subtraction of the nuclide quantities of v1 and v2 and returns the result...
Definition: comp_math.cc:18
static double KahanSum(std::vector< double > input)
sums the materials in the vector in an intelligent way, to avoid floating point issues.
taken directly from OsiSolverInterface.cpp on 2/17/14 from https://projects.coin-or.org/Osi/browser/trunk.
Definition: agent.cc:14
Declares the CycArithmetic class, which holds arithmetic algorithms.
void Normalize(CompMap *v, double val)
The sum of quantities of all nuclides of v is normalized to val.
Definition: comp_math.cc:63
void ApplyThreshold(CompMap *v, double threshold)
All nuclides with quantities below threshold will have their quantity set to zero.
Definition: comp_math.cc:45
int Nuc
Definition: composition.h:12