/
solverinterface.cpp
249 lines (172 loc) · 7.05 KB
/
solverinterface.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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/*******************************************************************************
Copyright (C) The University of Auckland
OpenCOR is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenCOR is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://gnu.org/licenses>.
*******************************************************************************/
//==============================================================================
// Solver interface
//==============================================================================
#include "solverinterface.h"
//==============================================================================
#include <QCoreApplication>
//==============================================================================
void doNonLinearSolve(char *pRuntime,
void (*pFunction)(double *, double *, void *),
double *pParameters, int pSize, void *pUserData)
{
// Retrieve the NLA solver which we should use and solve our NLA system
// Note: we shouldn't always have an NLA solver, but better be safe than
// sorry...
OpenCOR::Solver::NlaSolver *nlaSolver = OpenCOR::Solver::nlaSolver(pRuntime);
if (nlaSolver != nullptr) {
nlaSolver->solve(pFunction, pParameters, pSize, pUserData);
} else {
qWarning("WARNING | %s:%d: no NLA solver could be found.", __FILE__, __LINE__);
}
}
//==============================================================================
namespace OpenCOR {
//==============================================================================
extern "C" Q_DECL_EXPORT int solverInterfaceVersion()
{
// Version of the solver interface
return 2;
}
//==============================================================================
namespace Solver {
//==============================================================================
void Solver::setProperties(const Properties &pProperties)
{
// Set a property's value, but only if it is a valid property
mProperties = pProperties;
}
//==============================================================================
void Solver::emitError(const QString &pErrorMessage)
{
// Let people know that an error occured, but first reformat the error a
// bit, if needed
QString errorMessage = QString();
if (pErrorMessage.startsWith("Newton")) {
errorMessage = pErrorMessage;
} else if (!pErrorMessage.isEmpty()) {
errorMessage = pErrorMessage[0].toLower()+pErrorMessage.right(pErrorMessage.size()-1);
}
static const QString Dot = ".";
static const QString DotDotDot = "...";
if (errorMessage.right(3) == DotDotDot) {
emit error(errorMessage.left(errorMessage.size()-3));
} else if (errorMessage.right(1) == Dot) {
emit error(errorMessage.left(errorMessage.size()-1));
} else {
emit error(errorMessage);
}
}
//==============================================================================
void OdeSolver::initialize(double pVoi, int pRatesStatesCount,
double *pConstants, double *pRates, double *pStates,
double *pAlgebraic,
ComputeRatesFunction pComputeRates)
{
Q_UNUSED(pVoi)
// Initialise the ODE solver
mRatesStatesCount = pRatesStatesCount;
mConstants = pConstants;
mRates = pRates;
mStates = pStates;
mAlgebraic = pAlgebraic;
mComputeRates = pComputeRates;
}
//==============================================================================
void OdeSolver::reinitialize(double pVoi)
{
Q_UNUSED(pVoi)
// Nothing to do by default...
}
//==============================================================================
NlaSolver::~NlaSolver() = default;
//==============================================================================
NlaSolver * nlaSolver(const QString &pRuntimeAddress)
{
// Return the runtime's NLA solver
QVariant res = qApp->property(pRuntimeAddress.toUtf8().constData());
return res.isValid()?reinterpret_cast<NlaSolver *>(res.toULongLong()):nullptr;
}
//==============================================================================
void setNlaSolver(const QString &pRuntimeAddress, NlaSolver *pGlobalNlaSolver)
{
// Keep track of the runtime's NLA solver
qApp->setProperty(pRuntimeAddress.toUtf8().constData(),
quint64(pGlobalNlaSolver));
}
//==============================================================================
void unsetNlaSolver(const QString &pRuntimeAddress)
{
// Stop tracking the runtime's NLA solver
qApp->setProperty(pRuntimeAddress.toUtf8().constData(), QVariant::Invalid);
}
//==============================================================================
Property::Property(Type pType, const QString &pId,
const Descriptions &pDescriptions,
const QStringList &pListValues,
const QVariant &pDefaultValue, bool pHasVoiUnit) :
mType(pType),
mId(pId),
mDescriptions(pDescriptions),
mListValues(pListValues),
mDefaultValue(pDefaultValue),
mHasVoiUnit(pHasVoiUnit)
{
}
//==============================================================================
Property::Type Property::type() const
{
// Return our type
return mType;
}
//==============================================================================
QString Property::id() const
{
// Return our id
return mId;
}
//==============================================================================
Descriptions Property::descriptions() const
{
// Return our descriptions
return mDescriptions;
}
//==============================================================================
QStringList Property::listValues() const
{
// Return our list values
return mListValues;
}
//==============================================================================
QVariant Property::defaultValue() const
{
// Return our default value
return mDefaultValue;
}
//==============================================================================
bool Property::hasVoiUnit() const
{
// Return whether we have a VOI unit
return mHasVoiUnit;
}
//==============================================================================
} // namespace Solver
//==============================================================================
SolverInterface::~SolverInterface() = default;
//==============================================================================
} // namespace OpenCOR
//==============================================================================
// End of file
//==============================================================================