Cantera  2.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
refine.cpp
Go to the documentation of this file.
1 //! @file refine.cpp
2 #include "cantera/oneD/refine.h"
3 #include "cantera/oneD/StFlow.h"
4 
5 using namespace std;
6 
7 namespace Cantera
8 {
9 Refiner::Refiner(Domain1D& domain) :
10  m_ratio(10.0), m_slope(0.8), m_curve(0.8), m_prune(-0.001),
11  m_min_range(0.01), m_domain(&domain), m_npmax(3000),
12  m_gridmin(1e-10)
13 {
14  m_nv = m_domain->nComponents();
15  m_active.resize(m_nv, true);
16  m_thresh = std::sqrt(std::numeric_limits<double>::epsilon());
17 }
18 
19 void Refiner::setCriteria(doublereal ratio, doublereal slope,
20  doublereal curve, doublereal prune)
21 {
22  if (ratio < 2.0) {
23  throw CanteraError("Refiner::setCriteria",
24  "'ratio' must be greater than 2.0 (" + fp2str(ratio) +
25  " was specified).");
26  } else if (slope < 0.0 || slope > 1.0) {
27  throw CanteraError("Refiner::setCriteria",
28  "'slope' must be between 0.0 and 1.0 (" + fp2str(slope) +
29  " was specified).");
30  } else if (curve < 0.0 || curve > 1.0) {
31  throw CanteraError("Refiner::setCriteria",
32  "'curve' must be between 0.0 and 1.0 (" + fp2str(curve) +
33  " was specified).");
34  } else if (prune > curve || prune > slope) {
35  throw CanteraError("Refiner::setCriteria",
36  "'prune' must be less than 'curve' and 'slope' (" + fp2str(prune) +
37  " was specified).");
38  }
39  m_ratio = ratio;
40  m_slope = slope;
41  m_curve = curve;
42  m_prune = prune;
43 }
44 
45 int Refiner::analyze(size_t n, const doublereal* z,
46  const doublereal* x)
47 {
48  if (n >= m_npmax) {
49  writelog("max number of grid points reached ("+int2str(m_npmax)+".\n");
50  return -2;
51  }
52 
53  if (m_domain->nPoints() <= 1) {
54  return 0;
55  }
56 
57  m_loc.clear();
58  m_c.clear();
59  m_keep.clear();
60 
61  m_keep[0] = 1;
62  m_keep[n-1] = 1;
63 
64  m_nv = m_domain->nComponents();
65 
66  // check consistency
67  if (n != m_domain->nPoints()) {
68  throw CanteraError("analyze","inconsistent");
69  }
70 
71  // find locations where cell size ratio is too large.
72  vector_fp v(n), s(n-1);
73 
74  vector_fp dz(n-1);
75  for (size_t j = 0; j < n-1; j++) {
76  dz[j] = z[j+1] - z[j];
77  }
78 
79  for (size_t i = 0; i < m_nv; i++) {
80  if (m_active[i]) {
81  string name = m_domain->componentName(i);
82  // get component i at all points
83  for (size_t j = 0; j < n; j++) {
84  v[j] = value(x, i, j);
85  }
86 
87  // slope of component i
88  for (size_t j = 0; j < n-1; j++) {
89  s[j] = (value(x, i, j+1) - value(x, i, j))/(z[j+1] - z[j]);
90  }
91 
92  // find the range of values and slopes
93  doublereal vmin = *min_element(v.begin(), v.end());
94  doublereal vmax = *max_element(v.begin(), v.end());
95  doublereal smin = *min_element(s.begin(), s.end());
96  doublereal smax = *max_element(s.begin(), s.end());
97 
98  // max absolute values of v and s
99  doublereal aa = std::max(fabs(vmax), fabs(vmin));
100  doublereal ss = std::max(fabs(smax), fabs(smin));
101 
102  // refine based on component i only if the range of v is
103  // greater than a fraction 'min_range' of max |v|. This
104  // eliminates components that consist of small fluctuations
105  // on a constant background.
106  if ((vmax - vmin) > m_min_range*aa) {
107  // maximum allowable difference in value between adjacent
108  // points.
109  doublereal dmax = m_slope*(vmax - vmin) + m_thresh;
110  for (size_t j = 0; j < n-1; j++) {
111  doublereal r = fabs(v[j+1] - v[j])/dmax;
112  if (r > 1.0 && dz[j] >= 2 * m_gridmin) {
113  m_loc[j] = 1;
114  m_c[name] = 1;
115  }
116  if (r >= m_prune) {
117  m_keep[j] = 1;
118  m_keep[j+1] = 1;
119  } else if (m_keep[j] == 0) {
120  m_keep[j] = -1;
121  }
122  }
123  }
124 
125  // refine based on the slope of component i only if the
126  // range of s is greater than a fraction 'min_range' of max
127  // |s|. This eliminates components that consist of small
128  // fluctuations on a constant slope background.
129  if ((smax - smin) > m_min_range*ss) {
130  // maximum allowable difference in slope between
131  // adjacent points.
132  doublereal dmax = m_curve*(smax - smin);
133  for (size_t j = 0; j < n-2; j++) {
134  doublereal r = fabs(s[j+1] - s[j]) / (dmax + m_thresh/dz[j]);
135  if (r > 1.0 && dz[j] >= 2 * m_gridmin &&
136  dz[j+1] >= 2 * m_gridmin) {
137  m_c[name] = 1;
138  m_loc[j] = 1;
139  m_loc[j+1] = 1;
140  }
141  if (r >= m_prune) {
142  m_keep[j+1] = 1;
143  } else if (m_keep[j+1] == 0) {
144  m_keep[j+1] = -1;
145  }
146  }
147  }
148  }
149  }
150 
151  FreeFlame* fflame = dynamic_cast<FreeFlame*>(m_domain);
152 
153  // Refine based on properties of the grid itself
154  for (size_t j = 1; j < n-1; j++) {
155  // Add a new point if the ratio with left interval is too large
156  if (dz[j] > m_ratio*dz[j-1]) {
157  m_loc[j] = 1;
158  m_c["point "+int2str(j)] = 1;
159  m_keep[j-1] = 1;
160  m_keep[j] = 1;
161  m_keep[j+1] = 1;
162  m_keep[j+2] = 1;
163  }
164 
165  // Add a point if the ratio with right interval is too large
166  if (dz[j] < dz[j-1]/m_ratio) {
167  m_loc[j-1] = 1;
168  m_c["point "+int2str(j-1)] = 1;
169  m_keep[j-2] = 1;
170  m_keep[j-1] = 1;
171  m_keep[j] = 1;
172  m_keep[j+1] = 1;
173  }
174 
175  // Keep the point if removing would make the ratio with the left
176  // interval too large.
177  if (j > 1 && z[j+1]-z[j-1] > m_ratio * dz[j-2]) {
178  m_keep[j] = 1;
179  }
180 
181  // Keep the point if removing would make the ratio with the right
182  // interval too large.
183  if (j < n-2 && z[j+1]-z[j-1] > m_ratio * dz[j+1]) {
184  m_keep[j] = 1;
185  }
186 
187  // Keep the point where the temperature is fixed
188  if (fflame && z[j] == fflame->m_zfixed) {
189  m_keep[j] = 1;
190  }
191  }
192 
193  // Don't allow pruning to remove multiple adjacent grid points
194  // in a single pass.
195  for (size_t j = 2; j < n-1; j++) {
196  if (m_keep[j] == -1 && m_keep[j-1] == -1) {
197  m_keep[j] = 1;
198  }
199  }
200 
201  return int(m_loc.size());
202 }
203 
204 double Refiner::value(const double* x, size_t i, size_t j)
205 {
206  return x[m_domain->index(i,j)];
207 }
208 
209 void Refiner::show()
210 {
211  if (!m_loc.empty()) {
212  writeline('#', 78);
213  writelog(string("Refining grid in ") +
214  m_domain->id()+".\n"
215  +" New points inserted after grid points ");
216  map<size_t, int>::const_iterator b = m_loc.begin();
217  for (; b != m_loc.end(); ++b) {
218  writelog(int2str(b->first)+" ");
219  }
220  writelog("\n");
221  writelog(" to resolve ");
222  map<string, int>::const_iterator bb = m_c.begin();
223  for (; bb != m_c.end(); ++bb) {
224  writelog(string(bb->first)+" ");
225  }
226  writelog("\n");
227  writeline('#', 78);
228  } else if (m_domain->nPoints() > 1) {
229  writelog("no new points needed in "+m_domain->id()+"\n");
230  }
231 }
232 
233 int Refiner::getNewGrid(int n, const doublereal* z,
234  int nn, doublereal* zn)
235 {
236  int nnew = static_cast<int>(m_loc.size());
237  if (nnew + n > nn) {
238  throw CanteraError("Refine::getNewGrid", "array size too small.");
239  }
240 
241  if (m_loc.empty()) {
242  copy(z, z + n, zn);
243  return 0;
244  }
245 
246  int jn = 0;
247  for (int j = 0; j < n - 1; j++) {
248  zn[jn] = z[j];
249  jn++;
250  if (m_loc.count(j)) {
251  zn[jn] = 0.5*(z[j] + z[j+1]);
252  jn++;
253  }
254  }
255  zn[jn] = z[n-1];
256  return 0;
257 }
258 }
std::string int2str(const int n, const std::string &fmt)
Convert an int to a string using a format converter.
Definition: stringUtils.cpp:39
size_t nPoints() const
Number of grid points in this domain.
Definition: Domain1D.h:186
virtual std::string componentName(size_t n) const
Name of the nth component. May be overloaded.
Definition: Domain1D.h:208
doublereal m_gridmin
minimum grid spacing [m]
Definition: refine.h:93
size_t nComponents() const
Number of components at each grid point.
Definition: Domain1D.h:164
void setCriteria(doublereal ratio=10.0, doublereal slope=0.8, doublereal curve=0.8, doublereal prune=-0.1)
Set grid refinement criteria.
Definition: refine.cpp:19
std::string fp2str(const double x, const std::string &fmt)
Convert a double into a c++ string.
Definition: stringUtils.cpp:28
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:99
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
Definition: ct_defs.h:157
void writelog(const std::string &msg)
Write a message to the screen.
Definition: global.cpp:33