-
Notifications
You must be signed in to change notification settings - Fork 0
/
boundary.cpp
166 lines (140 loc) · 4.75 KB
/
boundary.cpp
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// C/C++
#include <iostream>
// cantera
#include <cantera/base/stringUtils.h>
#include <cantera/thermo/ThermoPhase.h>
// c3m
#include "boundary.hpp"
double Connector::initialValue(size_t n, size_t j) { return 0.; }
std::string Connector::componentName(size_t n) const {
return solution()->thermo()->speciesName(n);
}
void Connector::setSpeciesDirichlet(const std::string& xin) {
auto xmap = Cantera::parseCompString(xin);
// will throw an exception if the species are not in the phase
auto mf = solution()->thermo()->getCompositionFromMap(xmap);
for (auto x : xmap) {
DirichletBC bc;
bc.id = componentIndex(x.first);
bc.value = x.second;
dirichlet.push_back(bc);
}
}
void Connector::setSpeciesNeumann(const std::string& xin) {
auto xmap = Cantera::parseCompString(xin);
// will throw an exception if the species are not in the phase
auto mf = solution()->thermo()->getCompositionFromMap(xmap);
for (auto x : xmap) {
NeumannBC bc;
bc.id = componentIndex(x.first);
bc.value = x.second;
neumann.push_back(bc);
}
}
void Connector::eval(size_t jGlobal, double* xGlobal, double* rsdGlobal,
integer* diagGlobal, double rdt) {
// If evaluating a Jacobian, and the global point is outside the domain of
// influence for this domain, then skip evaluating the residual
if (jGlobal != Cantera::npos &&
(jGlobal + 1 < firstPoint() || jGlobal > lastPoint() + 1)) {
return;
}
if (left() != nullptr) {
if (left()->isConnector()) {
throw Cantera::CanteraError("Connector::eval",
"Left domain cannot be a connector");
}
}
if (right() != nullptr) {
if (right()->isConnector()) {
throw Cantera::CanteraError("Connector::eval",
"Right domain cannot be a connector");
}
}
Eigen::VectorXd vleft(nComponents());
vleft.setZero();
Eigen::VectorXd vright(nComponents());
vright.setZero();
// start of local part of global arrays
double* x = xGlobal + loc();
double* rsd = rsdGlobal + loc();
// apply dirichlet boundary conditions
for (auto bc : dirichlet) {
x[bc.id] = bc.value;
rsd[bc.id] = 0.;
if (left() != nullptr) {
size_t nv = left()->nComponents();
double* xleft = xGlobal + left()->loc() + left()->size() - nv;
xleft[bc.id] = bc.value;
vleft(bc.id) = bc.value;
}
if (right() != nullptr) {
double* xright = xGlobal + right()->loc();
xright[bc.id] = bc.value;
vright(bc.id) = bc.value;
}
}
// apply neumann boundary conditions
for (auto bc : neumann) {
double *xleft, *xright;
if (left() != nullptr) {
size_t nv = left()->nComponents();
size_t points = right()->nPoints();
double dz = left()->z(points - 1) - left()->z(points - 2);
xleft = xGlobal + left()->loc() + left()->size() - nv;
xleft[bc.id] = xleft[bc.id + nv] - bc.value * dz;
vleft(bc.id) = bc.value * dz;
left()->B(points - 2) += left()->C(points - 2);
}
if (right() != nullptr) {
size_t nv = right()->nComponents();
double dz = right()->z(1) - right()->z(0);
xright = xGlobal + right()->loc();
xright[bc.id] = xright[bc.id + nv] - bc.value * dz;
vright(bc.id) = -bc.value * dz;
right()->B(1) += right()->A(1);
}
if (left() != nullptr && right() != nullptr) {
x[bc.id] = 0.5 * (xleft[bc.id] + xright[bc.id]);
rsd[bc.id] = xright[bc.id] - xleft[bc.id];
} else if (left() != nullptr) {
x[bc.id] = xleft[bc.id];
rsd[bc.id] = 0.;
} else if (right() != nullptr) {
x[bc.id] = xright[bc.id];
rsd[bc.id] = 0.;
} else {
throw Cantera::CanteraError("Connector::eval",
"Neumann boundary condition without domain");
}
}
if (left()) {
size_t points = left()->nPoints();
Eigen::VectorXd vD = left()->C(points - 2) * vleft;
size_t start = left()->loc() + left()->size() - 2 * left()->nComponents();
// for (size_t n = 0; n < nComponents(); ++n) {
// rsdGlobal[start + n] -= vD(n);
// }
left()->C(points - 2).setZero();
}
if (right()) {
Eigen::VectorXd vD = right()->A(1) * vright;
size_t start = right()->loc() + right()->nComponents();
// for (size_t n = 0; n < nComponents(); ++n) {
// rsdGlobal[start + n] -= vD(n);
// }
right()->A(1).setZero();
}
}
SurfaceBoundary::SurfaceBoundary(std::string const& id,
std::shared_ptr<Cantera::Solution> sol)
: Connector(sol->thermo()->nSpecies(), 1) {
setSolution(sol);
setID(id);
}
SpaceBoundary::SpaceBoundary(std::string const& id,
std::shared_ptr<Cantera::Solution> sol)
: Connector(sol->thermo()->nSpecies(), 1) {
setSolution(sol);
setID(id);
}