00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include <iostream>
00028
00029 #include <cfloat>
00030
00031 #include "CollocWt.h"
00032 #include "f77-fcn.h"
00033 #include "lo-error.h"
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 static void
00056 dif (octave_idx_type nt, double *root, double *dif1, double *dif2,
00057 double *dif3)
00058 {
00059
00060
00061 for (octave_idx_type i = 0; i < nt; i++)
00062 {
00063 double x = root[i];
00064
00065 dif1[i] = 1.0;
00066 dif2[i] = 0.0;
00067 dif3[i] = 0.0;
00068
00069 for (octave_idx_type j = 0; j < nt; j++)
00070 {
00071 if (j != i)
00072 {
00073 double y = x - root[j];
00074
00075 dif3[i] = y * dif3[i] + 3.0 * dif2[i];
00076 dif2[i] = y * dif2[i] + 2.0 * dif1[i];
00077 dif1[i] = y * dif1[i];
00078 }
00079 }
00080 }
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 static bool
00144 jcobi (octave_idx_type n, octave_idx_type n0, octave_idx_type n1,
00145 double alpha, double beta, double *dif1, double *dif2,
00146 double *dif3, double *root)
00147 {
00148 assert (n0 == 0 || n0 == 1);
00149 assert (n1 == 0 || n1 == 1);
00150
00151 octave_idx_type nt = n + n0 + n1;
00152
00153 assert (nt > 1);
00154
00155
00156
00157
00158 double ab = alpha + beta;
00159 double ad = beta - alpha;
00160 double ap = beta * alpha;
00161
00162 dif1[0] = (ad / (ab + 2.0) + 1.0) / 2.0;
00163 dif2[0] = 0.0;
00164
00165 if (n >= 2)
00166 {
00167 for (octave_idx_type i = 1; i < n; i++)
00168 {
00169 double z1 = i;
00170 double z = ab + 2 * z1;
00171
00172 dif1[i] = (ab * ad / z / (z + 2.0) + 1.0) / 2.0;
00173
00174 if (i == 1)
00175 dif2[i] = (ab + ap + z1) / z / z / (z + 1.0);
00176 else
00177 {
00178 z = z * z;
00179 double y = z1 * (ab + z1);
00180 y = y * (ap + y);
00181 dif2[i] = y / z / (z - 1.0);
00182 }
00183 }
00184 }
00185
00186
00187
00188
00189 double x = 0.0;
00190
00191 for (octave_idx_type i = 0; i < n; i++)
00192 {
00193 bool done = false;
00194
00195 int k = 0;
00196
00197 while (! done)
00198 {
00199 double xd = 0.0;
00200 double xn = 1.0;
00201 double xd1 = 0.0;
00202 double xn1 = 0.0;
00203
00204 for (octave_idx_type j = 0; j < n; j++)
00205 {
00206 double xp = (dif1[j] - x) * xn - dif2[j] * xd;
00207 double xp1 = (dif1[j] - x) * xn1 - dif2[j] * xd1 - xn;
00208
00209 xd = xn;
00210 xd1 = xn1;
00211 xn = xp;
00212 xn1 = xp1;
00213 }
00214
00215 double zc = 1.0;
00216 double z = xn / xn1;
00217
00218 if (i != 0)
00219 {
00220 for (octave_idx_type j = 1; j <= i; j++)
00221 zc = zc - z / (x - root[j-1]);
00222 }
00223
00224 z = z / zc;
00225 x = x - z;
00226
00227
00228
00229
00230 if (++k > 100 || xisnan (z))
00231 return false;
00232
00233 if (std::abs (z) <= 100 * DBL_EPSILON)
00234 done = true;
00235 }
00236
00237 root[i] = x;
00238 x = x + sqrt (DBL_EPSILON);
00239 }
00240
00241
00242
00243 if (n0 != 0)
00244 {
00245 for (octave_idx_type i = n; i > 0; i--)
00246 root[i] = root[i-1];
00247
00248 root[0] = 0.0;
00249 }
00250
00251 if (n1 != 0)
00252 root[nt-1] = 1.0;
00253
00254 dif (nt, root, dif1, dif2, dif3);
00255
00256 return true;
00257 }
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 static void
00306 dfopr (octave_idx_type n, octave_idx_type n0, octave_idx_type n1,
00307 octave_idx_type i, octave_idx_type id, double *dif1,
00308 double *dif2, double *dif3, double *root, double *vect)
00309 {
00310 assert (n0 == 0 || n0 == 1);
00311 assert (n1 == 0 || n1 == 1);
00312
00313 octave_idx_type nt = n + n0 + n1;
00314
00315 assert (nt > 1);
00316
00317 assert (id == 1 || id == 2 || id == 3);
00318
00319 if (id != 3)
00320 assert (i >= 0 && i < nt);
00321
00322
00323
00324
00325 if (id != 3)
00326 {
00327 for (octave_idx_type j = 0; j < nt; j++)
00328 {
00329 if (j == i)
00330 {
00331 if (id == 1)
00332 vect[i] = dif2[i] / dif1[i] / 2.0;
00333 else
00334 vect[i] = dif3[i] / dif1[i] / 3.0;
00335 }
00336 else
00337 {
00338 double y = root[i] - root[j];
00339
00340 vect[j] = dif1[i] / dif1[j] / y;
00341
00342 if (id == 2)
00343 vect[j] = vect[j] * (dif2[i] / dif1[i] - 2.0 / y);
00344 }
00345 }
00346 }
00347 else
00348 {
00349 double y = 0.0;
00350
00351 for (octave_idx_type j = 0; j < nt; j++)
00352 {
00353 double x = root[j];
00354
00355 double ax = x * (1.0 - x);
00356
00357 if (n0 == 0)
00358 ax = ax / x / x;
00359
00360 if (n1 == 0)
00361 ax = ax / (1.0 - x) / (1.0 - x);
00362
00363 vect[j] = ax / (dif1[j] * dif1[j]);
00364
00365 y = y + vect[j];
00366 }
00367
00368 for (octave_idx_type j = 0; j < nt; j++)
00369 vect[j] = vect[j] / y;
00370 }
00371 }
00372
00373
00374
00375 void
00376 CollocWt::error (const char* msg)
00377 {
00378 (*current_liboctave_error_handler) ("fatal CollocWt error: %s", msg);
00379 }
00380
00381 CollocWt&
00382 CollocWt::set_left (double val)
00383 {
00384 if (val >= rb)
00385 {
00386 error ("left bound greater than right bound");
00387 return *this;
00388 }
00389
00390 lb = val;
00391 initialized = 0;
00392 return *this;
00393 }
00394
00395 CollocWt&
00396 CollocWt::set_right (double val)
00397 {
00398 if (val <= lb)
00399 {
00400 error ("right bound less than left bound");
00401 return *this;
00402 }
00403
00404 rb = val;
00405 initialized = 0;
00406 return *this;
00407 }
00408
00409 void
00410 CollocWt::init (void)
00411 {
00412
00413
00414 double wid = rb - lb;
00415 if (wid <= 0.0)
00416 {
00417 error ("width less than or equal to zero");
00418 return;
00419 }
00420
00421 octave_idx_type nt = n + inc_left + inc_right;
00422
00423 if (nt < 0)
00424 {
00425 error ("total number of collocation points less than zero");
00426 return;
00427 }
00428 else if (nt == 0)
00429 return;
00430
00431 Array<double> dif1 (dim_vector (nt, 1));
00432 double *pdif1 = dif1.fortran_vec ();
00433
00434 Array<double> dif2 (dim_vector (nt, 1));
00435 double *pdif2 = dif2.fortran_vec ();
00436
00437 Array<double> dif3 (dim_vector (nt, 1));
00438 double *pdif3 = dif3.fortran_vec ();
00439
00440 Array<double> vect (dim_vector (nt, 1));
00441 double *pvect = vect.fortran_vec ();
00442
00443 r.resize (nt, 1);
00444 q.resize (nt, 1);
00445 A.resize (nt, nt);
00446 B.resize (nt, nt);
00447
00448 double *pr = r.fortran_vec ();
00449
00450
00451
00452 if (! jcobi (n, inc_left, inc_right, Alpha, Beta, pdif1, pdif2, pdif3, pr))
00453 {
00454 error ("jcobi: newton iteration failed");
00455 return;
00456 }
00457
00458 octave_idx_type id;
00459
00460
00461
00462 id = 1;
00463 for (octave_idx_type i = 0; i < nt; i++)
00464 {
00465 dfopr (n, inc_left, inc_right, i, id, pdif1, pdif2, pdif3, pr, pvect);
00466
00467 for (octave_idx_type j = 0; j < nt; j++)
00468 A(i,j) = vect(j);
00469 }
00470
00471
00472
00473 id = 2;
00474 for (octave_idx_type i = 0; i < nt; i++)
00475 {
00476 dfopr (n, inc_left, inc_right, i, id, pdif1, pdif2, pdif3, pr, pvect);
00477
00478 for (octave_idx_type j = 0; j < nt; j++)
00479 B(i,j) = vect(j);
00480 }
00481
00482
00483
00484 id = 3;
00485 double *pq = q.fortran_vec ();
00486 dfopr (n, inc_left, inc_right, id, id, pdif1, pdif2, pdif3, pr, pq);
00487
00488 initialized = 1;
00489 }
00490
00491 std::ostream&
00492 operator << (std::ostream& os, const CollocWt& a)
00493 {
00494 if (a.left_included ())
00495 os << "left boundary is included\n";
00496 else
00497 os << "left boundary is not included\n";
00498
00499 if (a.right_included ())
00500 os << "right boundary is included\n";
00501 else
00502 os << "right boundary is not included\n";
00503
00504 os << "\n";
00505
00506 os << a.Alpha << " " << a.Beta << "\n\n"
00507 << a.r << "\n\n"
00508 << a.q << "\n\n"
00509 << a.A << "\n"
00510 << a.B << "\n";
00511
00512 return os;
00513 }