11
11
// - the copyright holder be liable for any direct, indirect, incidental or -
12
12
// - special damages arising in any way out of the use of this software. -
13
13
// ---------------------------------------------------------------------------
14
// - copyright (c) 1999-2012 amaury darsch -
14
// - copyright (c) 1999-2015 amaury darsch -
15
15
// ---------------------------------------------------------------------------
17
17
#include "Real.hpp"
19
19
#include "Vector.hpp"
20
20
#include "Newton.hpp"
21
21
#include "Linear.hpp"
22
#include "Boolean.hpp"
23
#include "Integer.hpp"
22
24
#include "Runnable.hpp"
23
25
#include "QuarkZone.hpp"
24
26
#include "Exception.hpp"
28
// the default verification mode
29
static const bool NTW_VF_DEF = false;
30
29
// the iteration factor for the newton solver
31
static const long NTW_NI_DEF = 100L;
30
static const long NTW_MNI_DEF = 100L;
33
32
// -------------------------------------------------------------------------
34
33
// - class section -
35
34
// -------------------------------------------------------------------------
37
// create a default linear solver
36
// create a default newton solver
39
38
Newton::Newton (void) {
44
// create a solver by verification flag
46
Newton::Newton (const bool avf) {
51
// create a solver by verification flag and mni value
53
Newton::Newton (const bool avf, const long mni) {
40
Object::iref (p_lnr = new Linear);
43
// create a newton solver with a linear solver
45
Newton::Newton (Solver* lnr) {
47
Object::iref (p_lnr = lnr);
58
50
// copy construct this object
60
52
Newton::Newton (const Newton& that) {
64
55
d_mni = that.d_mni;
56
Object::iref (p_lnr = that.p_lnr);
105
// set the newton linear solver
107
void Newton::setlnr (Solver* lnr) {
111
Object::dref (p_lnr);
120
// get the newton linear solver
122
Solver* Newton::getlnr (void) const {
125
Solver* result = p_lnr;
134
// set the number of newton iterations
136
void Newton::setmni (const long mni) {
147
// get the number of newton iterations
149
long Newton::getmni (void) const {
105
161
// find a function root with the newton method
107
163
t_real Newton::solve (const Rfi& fo, const t_real xi) {
110
166
// initialize current point
112
// get the number of iteration
113
long ni = (d_mni <= 0) ? NTW_NI_DEF : d_mni;
115
for (long i = 0; i < ni; i++) {
169
for (long k = 0L; k < d_mni; k++) {
116
170
// check for zero
117
171
t_real xz = fo.compute (xn);
118
172
if (Math::rcmp (0, xz) == true) {
146
195
Rvi* Newton::solve (const Rni& so, const Rvi& xi) {
148
// get the number of iteration
149
long ni = (d_mni <= 0) ? NTW_NI_DEF : d_mni;
150
197
// initialize the current point
151
198
Rvi* xn = dynamic_cast <Rvi*> (xi.clone ());
152
199
Object::iref (xn);
158
// create the linear solver
205
// check for a linear solver
207
throw Exception ("newton-error",
208
"no linear solver bound to newton solver");
161
for (long i = 0; i < ni; i++) {
211
for (long k = 0L; k < d_mni; k++) {
162
212
// check rhs for zero
163
rhs = so.getrhs (xn);
213
rhs = so.getrhs (xn); Object::iref (rhs);
164
214
if (rhs == nilp) {
165
215
throw Exception ("newton-error", "null rhs in convergence loop");
167
217
if (Math::rcmp (0, rhs->norm ()) == true) {
168
218
Object::tref (xn);
172
223
// get the lhs by operand
173
Rmi* lhs = so.getlhs (xn);
224
Rmi* lhs = so.getlhs (xn); Object::iref (lhs);
174
225
// try to solve the system
175
xd = lnr.solve (*lhs, *rhs);
226
xd = p_lnr->solve (lhs, *rhs);
176
227
// clean elements
177
228
Object::dref (lhs); lhs = nilp;
178
229
Object::dref (rhs); rhs = nilp;
179
230
// check for null delta
180
231
if (xd == nilp) {
181
throw Exception ("newton-error", "null delta in convergence loop");
232
throw Exception ("newton-error", "newton linear solver failure");
186
t_real nx = xn->norm ();
187
t_real nd = xd->norm ();
188
236
delete xd; xd = nilp;
189
// check for null updated point
190
if (Math::rcmp (0, nx) == true) {
191
rhs = so.getrhs (xn);
193
throw Exception ("newton-error", "null rhs in convergence loop");
195
// check for valid point
196
if (Math::rcmp (0, rhs->norm ()) == true) {
202
throw Exception ("newton-error", "invalid point in convergence loop");
204
// check for convergence
205
if (Math::rcmp (nd, nx) == true) {
211
throw Exception ("newton-error", "zero loop convergence failure");
238
throw Exception ("newton-error", "newton loop convergence failure");
214
241
Object::dref (xn);
222
249
// -------------------------------------------------------------------------
223
250
// - object section -
224
251
// -------------------------------------------------------------------------
226
253
// the quark zone
227
static const long QUARK_ZONE_LENGTH = 1;
254
static const long QUARK_ZONE_LENGTH = 5;
228
255
static QuarkZone zone (QUARK_ZONE_LENGTH);
230
// the rvi supported quarks
231
static const long QUARK_SOLVE = zone.intern ("solve");
257
// the object supported quarks
258
static const long QUARK_SOLVE = zone.intern ("solve");
259
static const long QUARK_SETLNR = zone.intern ("set-linear-solver");
260
static const long QUARK_GETLNR = zone.intern ("get-linear-solver");
261
static const long QUARK_SETMNI = zone.intern ("set-newton-iterations");
262
static const long QUARK_GETMNI = zone.intern ("get-newton-iterations");
233
264
// create a new object in a generic way
239
270
if (argc == 0) return new Newton;
240
271
// check for 1 argument
242
bool avf = argv->getbool (0);
243
return new Newton (avf);
245
// check for 2 arguments
247
bool avf = argv->getbool (0);
248
long mni = argv->getlong (1);
249
return new Newton (avf, mni);
273
Object* obj = argv->get (0);
274
// check for a solver
275
Solver* slv = dynamic_cast <Solver*> (obj);
276
if (slv != nilp) return new Newton (slv);
278
throw Exception ("type-error", "invalid object for newton solver",
251
281
// invalid arguments
252
282
throw Exception ("argument-error", "invalid arguments with newton object");
272
302
// get the number of arguments
273
303
long argc = (argv == nilp) ? 0 : argv->length ();
305
// dipatch 0 argument
307
if (quark == QUARK_GETMNI) return new Integer (getmni ());
308
if (quark == QUARK_GETLNR) {
311
Solver* result = getlnr ();
321
// dispatch 1 argument
323
if (quark == QUARK_SETMNI) {
324
long mni = argv->getlong (0);
328
if (quark == QUARK_SETLNR) {
329
Object* obj = argv->get (0);
330
Solver* lnr = dynamic_cast <Solver*> (obj);
332
throw Exception ("type-error",
333
"invalid object with set-linear-solver",
275
340
// dispatch 2 arguments
277
342
if (quark == QUARK_SOLVE) {