|
Intrepid
|
00001 00002 // 00003 // File: Intrepid_PolylibDef.hpp 00004 // 00005 // For more information, please see: http://www.nektar.info 00006 // 00007 // The MIT License 00008 // 00009 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA), 00010 // Department of Aeronautics, Imperial College London (UK), and Scientific 00011 // Computing and Imaging Institute, University of Utah (USA). 00012 // 00013 // License for the specific language governing rights and limitations under 00014 // Permission is hereby granted, free of charge, to any person obtaining a 00015 // copy of this software and associated documentation files (the "Software"), 00016 // to deal in the Software without restriction, including without limitation 00017 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 00018 // and/or sell copies of the Software, and to permit persons to whom the 00019 // Software is furnished to do so, subject to the following conditions: 00020 // 00021 // The above copyright notice and this permission notice shall be included 00022 // in all copies or substantial portions of the Software. 00023 // 00024 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00025 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00026 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00027 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00028 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 00029 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00030 // DEALINGS IN THE SOFTWARE. 00031 // 00032 // Description: 00033 // This file is redistributed with the Intrepid package. It should be used 00034 // in accordance with the above MIT license, at the request of the authors. 00035 // This file is NOT covered by the usual Intrepid/Trilinos LGPL license. 00036 // 00037 // Origin: Nektar++ library, http://www.nektar.info, downloaded on 00038 // March 10, 2009. 00039 // 00041 00042 00049 #ifdef _MSC_VER 00050 #include "winmath.h" 00051 #endif 00052 00053 00054 namespace Intrepid { 00055 00057 #define INTREPID_POLYLIB_STOP 50 00058 00060 #define INTREPID_POLYLIB_POLYNOMIAL_DEFLATION 0 00061 00062 #ifdef INTREPID_POLYLIB_POLYNOMIAL_DEFLATION 00063 00064 #define jacobz(n,z,alpha,beta) Jacobz(n,z,alpha,beta) 00065 #else 00066 00067 #define jacobz(n,z,alpha,beta) JacZeros(n,z,alpha,beta) 00068 #endif 00069 00070 00071 template <class Scalar> 00072 void IntrepidPolylib::zwgj (Scalar *z, Scalar *w, const int np, const Scalar alpha, const Scalar beta){ 00073 register int i; 00074 Scalar fac, one = 1.0, two = 2.0, apb = alpha + beta; 00075 00076 IntrepidPolylib::jacobz (np,z,alpha,beta); 00077 IntrepidPolylib::jacobd (np,z,w,np,alpha,beta); 00078 00079 fac = std::pow(two,apb + one)*IntrepidPolylib::gammaF(alpha + np + one)*IntrepidPolylib::gammaF(beta + np + one); 00080 fac /= IntrepidPolylib::gammaF((Scalar)(np + one))*IntrepidPolylib::gammaF(apb + np + one); 00081 00082 for(i = 0; i < np; ++i) w[i] = fac/(w[i]*w[i]*(one-z[i]*z[i])); 00083 00084 return; 00085 } 00086 00087 00088 template <class Scalar> 00089 void IntrepidPolylib::zwgrjm(Scalar *z, Scalar *w, const int np, const Scalar alpha, const Scalar beta){ 00090 00091 if(np == 1){ 00092 z[0] = 0.0; 00093 w[0] = 2.0; 00094 } 00095 else{ 00096 register int i; 00097 Scalar fac, one = 1.0, two = 2.0, apb = alpha + beta; 00098 00099 z[0] = -one; 00100 IntrepidPolylib::jacobz (np-1,z+1,alpha,beta+1); 00101 IntrepidPolylib::jacobfd (np,z,w,(Scalar*)0,np-1,alpha,beta); 00102 00103 fac = std::pow(two,apb)*IntrepidPolylib::gammaF(alpha + np)*IntrepidPolylib::gammaF(beta + np); 00104 fac /= IntrepidPolylib::gammaF((Scalar)np)*(beta + np)*IntrepidPolylib::gammaF(apb + np + 1); 00105 00106 for(i = 0; i < np; ++i) w[i] = fac*(1-z[i])/(w[i]*w[i]); 00107 w[0] *= (beta + one); 00108 } 00109 00110 return; 00111 } 00112 00113 00114 template <class Scalar> 00115 void IntrepidPolylib::zwgrjp(Scalar *z, Scalar *w, const int np, const Scalar alpha, const Scalar beta){ 00116 00117 if(np == 1){ 00118 z[0] = 0.0; 00119 w[0] = 2.0; 00120 } 00121 else{ 00122 register int i; 00123 Scalar fac, one = 1.0, two = 2.0, apb = alpha + beta; 00124 00125 IntrepidPolylib::jacobz (np-1,z,alpha+1,beta); 00126 z[np-1] = one; 00127 IntrepidPolylib::jacobfd (np,z,w,(Scalar*)0,np-1,alpha,beta); 00128 00129 fac = std::pow(two,apb)*IntrepidPolylib::gammaF(alpha + np)*IntrepidPolylib::gammaF(beta + np); 00130 fac /= IntrepidPolylib::gammaF((Scalar)np)*(alpha + np)*IntrepidPolylib::gammaF(apb + np + 1); 00131 00132 for(i = 0; i < np; ++i) w[i] = fac*(1+z[i])/(w[i]*w[i]); 00133 w[np-1] *= (alpha + one); 00134 } 00135 00136 return; 00137 } 00138 00139 00140 template <class Scalar> 00141 void IntrepidPolylib::zwglj(Scalar *z, Scalar *w, const int np, const Scalar alpha, const Scalar beta){ 00142 00143 if( np == 1 ){ 00144 z[0] = 0.0; 00145 w[0] = 2.0; 00146 } 00147 else{ 00148 register int i; 00149 Scalar fac, one = 1.0, apb = alpha + beta, two = 2.0; 00150 00151 z[0] = -one; 00152 z[np-1] = one; 00153 IntrepidPolylib::jacobz (np-2,z + 1,alpha + one,beta + one); 00154 IntrepidPolylib::jacobfd (np,z,w,(Scalar*)0,np-1,alpha,beta); 00155 00156 fac = std::pow(two,apb + 1)*IntrepidPolylib::gammaF(alpha + np)*IntrepidPolylib::gammaF(beta + np); 00157 fac /= (np-1)*IntrepidPolylib::gammaF((Scalar)np)*IntrepidPolylib::gammaF(alpha + beta + np + one); 00158 00159 for(i = 0; i < np; ++i) w[i] = fac/(w[i]*w[i]); 00160 w[0] *= (beta + one); 00161 w[np-1] *= (alpha + one); 00162 } 00163 00164 return; 00165 } 00166 00167 00168 template <class Scalar> 00169 void IntrepidPolylib::Dgj(Scalar *D, const Scalar *z, const int np, const Scalar alpha, const Scalar beta) 00170 { 00171 00172 Scalar one = 1.0, two = 2.0; 00173 00174 if (np <= 0){ 00175 D[0] = 0.0; 00176 } 00177 else{ 00178 register int i,j; 00179 Scalar *pd; 00180 00181 pd = (Scalar *)malloc(np*sizeof(Scalar)); 00182 IntrepidPolylib::jacobd(np,z,pd,np,alpha,beta); 00183 00184 for (i = 0; i < np; i++){ 00185 for (j = 0; j < np; j++){ 00186 00187 if (i != j) 00188 //D[i*np+j] = pd[j]/(pd[i]*(z[j]-z[i])); <--- This is either a bug, or the derivative matrix is not defined consistently. 00189 D[i*np+j] = pd[i]/(pd[j]*(z[i]-z[j])); 00190 else 00191 D[i*np+j] = (alpha - beta + (alpha + beta + two)*z[j])/ 00192 (two*(one - z[j]*z[j])); 00193 } 00194 } 00195 free(pd); 00196 } 00197 return; 00198 } 00199 00200 00201 template <class Scalar> 00202 void IntrepidPolylib::Dgrjm(Scalar *D, const Scalar *z, const int np, const Scalar alpha, const Scalar beta) 00203 { 00204 00205 if (np <= 0){ 00206 D[0] = 0.0; 00207 } 00208 else{ 00209 register int i, j; 00210 Scalar one = 1.0, two = 2.0; 00211 Scalar *pd; 00212 00213 pd = (Scalar *)malloc(np*sizeof(Scalar)); 00214 00215 pd[0] = std::pow(-one,np-1)*IntrepidPolylib::gammaF((Scalar)np+beta+one); 00216 pd[0] /= IntrepidPolylib::gammaF((Scalar)np)*IntrepidPolylib::gammaF(beta+two); 00217 IntrepidPolylib::jacobd(np-1,z+1,pd+1,np-1,alpha,beta+1); 00218 for(i = 1; i < np; ++i) pd[i] *= (1+z[i]); 00219 00220 for (i = 0; i < np; i++) { 00221 for (j = 0; j < np; j++){ 00222 if (i != j) 00223 //D[i*np+j] = pd[j]/(pd[i]*(z[j]-z[i])); <--- This is either a bug, or the derivative matrix is not defined consistently. 00224 D[i*np+j] = pd[i]/(pd[j]*(z[i]-z[j])); 00225 else { 00226 if(j == 0) 00227 D[i*np+j] = -(np + alpha + beta + one)*(np - one)/ 00228 (two*(beta + two)); 00229 else 00230 D[i*np+j] = (alpha - beta + one + (alpha + beta + one)*z[j])/ 00231 (two*(one - z[j]*z[j])); 00232 } 00233 } 00234 } 00235 free(pd); 00236 } 00237 return; 00238 } 00239 00240 00241 template <class Scalar> 00242 void IntrepidPolylib::Dgrjp(Scalar *D, const Scalar *z, const int np, const Scalar alpha, const Scalar beta) 00243 { 00244 00245 if (np <= 0){ 00246 D[0] = 0.0; 00247 } 00248 else{ 00249 register int i, j; 00250 Scalar one = 1.0, two = 2.0; 00251 Scalar *pd; 00252 00253 pd = (Scalar *)malloc(np*sizeof(Scalar)); 00254 00255 00256 IntrepidPolylib::jacobd(np-1,z,pd,np-1,alpha+1,beta); 00257 for(i = 0; i < np-1; ++i) pd[i] *= (1-z[i]); 00258 pd[np-1] = -IntrepidPolylib::gammaF((Scalar)np+alpha+one); 00259 pd[np-1] /= IntrepidPolylib::gammaF((Scalar)np)*IntrepidPolylib::gammaF(alpha+two); 00260 00261 for (i = 0; i < np; i++) { 00262 for (j = 0; j < np; j++){ 00263 if (i != j) 00264 //D[i*np+j] = pd[j]/(pd[i]*(z[j]-z[i])); <--- This is either a bug, or the derivative matrix is not defined consistently. 00265 D[i*np+j] = pd[i]/(pd[j]*(z[i]-z[j])); 00266 else { 00267 if(j == np-1) 00268 D[i*np+j] = (np + alpha + beta + one)*(np - one)/ 00269 (two*(alpha + two)); 00270 else 00271 D[i*np+j] = (alpha - beta - one + (alpha + beta + one)*z[j])/ 00272 (two*(one - z[j]*z[j])); 00273 } 00274 } 00275 } 00276 free(pd); 00277 } 00278 return; 00279 } 00280 00281 00282 template <class Scalar> 00283 void IntrepidPolylib::Dglj(Scalar *D, const Scalar *z, const int np, const Scalar alpha, const Scalar beta) 00284 { 00285 00286 if (np <= 0){ 00287 D[0] = 0.0; 00288 } 00289 else{ 00290 register int i, j; 00291 Scalar one = 1.0, two = 2.0; 00292 Scalar *pd; 00293 00294 pd = (Scalar *)malloc(np*sizeof(Scalar)); 00295 00296 pd[0] = two*std::pow(-one,np)*IntrepidPolylib::gammaF((Scalar)np + beta); 00297 pd[0] /= IntrepidPolylib::gammaF((Scalar)np - one)*IntrepidPolylib::gammaF(beta + two); 00298 IntrepidPolylib::jacobd(np-2,z+1,pd+1,np-2,alpha+1,beta+1); 00299 for(i = 1; i < np-1; ++i) pd[i] *= (one-z[i]*z[i]); 00300 pd[np-1] = -two*IntrepidPolylib::gammaF((Scalar)np + alpha); 00301 pd[np-1] /= IntrepidPolylib::gammaF((Scalar)np - one)*IntrepidPolylib::gammaF(alpha + two); 00302 00303 for (i = 0; i < np; i++) { 00304 for (j = 0; j < np; j++){ 00305 if (i != j) 00306 //D[i*np+j] = pd[j]/(pd[i]*(z[j]-z[i])); <--- This is either a bug, or the derivative matrix is not defined consistently. 00307 D[i*np+j] = pd[i]/(pd[j]*(z[i]-z[j])); 00308 else { 00309 if (j == 0) 00310 D[i*np+j] = (alpha - (np-1)*(np + alpha + beta))/(two*(beta+ two)); 00311 else if (j == np-1) 00312 D[i*np+j] =-(beta - (np-1)*(np + alpha + beta))/(two*(alpha+ two)); 00313 else 00314 D[i*np+j] = (alpha - beta + (alpha + beta)*z[j])/ 00315 (two*(one - z[j]*z[j])); 00316 } 00317 } 00318 } 00319 free(pd); 00320 } 00321 return; 00322 } 00323 00324 00325 template <class Scalar> 00326 Scalar IntrepidPolylib::hgj (const int i, const Scalar z, const Scalar *zgj, 00327 const int np, const Scalar alpha, const Scalar beta) 00328 { 00329 00330 Scalar zi, dz, p, pd, h; 00331 00332 zi = *(zgj+i); 00333 dz = z - zi; 00334 if (std::abs(dz) < INTREPID_TOL) return 1.0; 00335 00336 IntrepidPolylib::jacobd (1, &zi, &pd , np, alpha, beta); 00337 IntrepidPolylib::jacobfd(1, &z , &p, (Scalar*)0 , np, alpha, beta); 00338 h = p/(pd*dz); 00339 00340 return h; 00341 } 00342 00343 00344 template <class Scalar> 00345 Scalar IntrepidPolylib::hgrjm (const int i, const Scalar z, const Scalar *zgrj, 00346 const int np, const Scalar alpha, const Scalar beta) 00347 { 00348 00349 Scalar zi, dz, p, pd, h; 00350 00351 zi = *(zgrj+i); 00352 dz = z - zi; 00353 if (std::abs(dz) < INTREPID_TOL) return 1.0; 00354 00355 IntrepidPolylib::jacobfd (1, &zi, &p , (Scalar*)0, np-1, alpha, beta + 1); 00356 // need to use this routine in case zi = -1 or 1 00357 IntrepidPolylib::jacobd (1, &zi, &pd, np-1, alpha, beta + 1); 00358 h = (1.0 + zi)*pd + p; 00359 IntrepidPolylib::jacobfd (1, &z, &p, (Scalar*)0, np-1, alpha, beta + 1); 00360 h = (1.0 + z )*p/(h*dz); 00361 00362 return h; 00363 } 00364 00365 00366 template <class Scalar> 00367 Scalar IntrepidPolylib::hgrjp (const int i, const Scalar z, const Scalar *zgrj, 00368 const int np, const Scalar alpha, const Scalar beta) 00369 { 00370 00371 Scalar zi, dz, p, pd, h; 00372 00373 zi = *(zgrj+i); 00374 dz = z - zi; 00375 if (std::abs(dz) < INTREPID_TOL) return 1.0; 00376 00377 IntrepidPolylib::jacobfd (1, &zi, &p , (Scalar*)0, np-1, alpha+1, beta ); 00378 // need to use this routine in case z = -1 or 1 00379 IntrepidPolylib::jacobd (1, &zi, &pd, np-1, alpha+1, beta ); 00380 h = (1.0 - zi)*pd - p; 00381 IntrepidPolylib::jacobfd (1, &z, &p, (Scalar*)0, np-1, alpha+1, beta); 00382 h = (1.0 - z )*p/(h*dz); 00383 00384 return h; 00385 } 00386 00387 00388 template <class Scalar> 00389 Scalar IntrepidPolylib::hglj (const int i, const Scalar z, const Scalar *zglj, 00390 const int np, const Scalar alpha, const Scalar beta) 00391 { 00392 Scalar one = 1., two = 2.; 00393 Scalar zi, dz, p, pd, h; 00394 00395 zi = *(zglj+i); 00396 dz = z - zi; 00397 if (std::abs(dz) < INTREPID_TOL) return 1.0; 00398 00399 IntrepidPolylib::jacobfd(1, &zi, &p , (Scalar*)0, np-2, alpha + one, beta + one); 00400 // need to use this routine in case z = -1 or 1 00401 IntrepidPolylib::jacobd (1, &zi, &pd, np-2, alpha + one, beta + one); 00402 h = (one - zi*zi)*pd - two*zi*p; 00403 IntrepidPolylib::jacobfd(1, &z, &p, (Scalar*)0, np-2, alpha + one, beta + one); 00404 h = (one - z*z)*p/(h*dz); 00405 00406 return h; 00407 } 00408 00409 00410 template <class Scalar> 00411 void IntrepidPolylib::Imgj(Scalar *im, const Scalar *zgj, const Scalar *zm, const int nz, 00412 const int mz, const Scalar alpha, const Scalar beta){ 00413 Scalar zp; 00414 register int i, j; 00415 00416 /* old Polylib code */ 00417 for (i = 0; i < mz; ++i) { 00418 zp = zm[i]; 00419 for (j = 0; j < nz; ++j) { 00420 im[i*nz+j] = IntrepidPolylib::hgj(j, zp, zgj, nz, alpha, beta); 00421 } 00422 } 00423 00424 /* original Nektar++ code: is this correct??? 00425 for (i = 0; i < nz; ++i) { 00426 for (j = 0; j < mz; ++j) 00427 { 00428 zp = zm[j]; 00429 im [i*mz+j] = IntrepidPolylib::hgj(i, zp, zgj, nz, alpha, beta); 00430 } 00431 } 00432 */ 00433 00434 return; 00435 } 00436 00437 00438 template <class Scalar> 00439 void IntrepidPolylib::Imgrjm(Scalar *im, const Scalar *zgrj, const Scalar *zm, const int nz, 00440 const int mz, const Scalar alpha, const Scalar beta) 00441 { 00442 Scalar zp; 00443 register int i, j; 00444 00445 for (i = 0; i < mz; i++) { 00446 zp = zm[i]; 00447 for (j = 0; j < nz; j++) { 00448 im[i*nz+j] = IntrepidPolylib::hgrjm(j, zp, zgrj, nz, alpha, beta); 00449 } 00450 } 00451 00452 /* original Nektar++ code: is this correct??? 00453 for (i = 0; i < nz; i++) { 00454 for (j = 0; j < mz; j++) 00455 { 00456 zp = zm[j]; 00457 im [i*mz+j] = IntrepidPolylib::hgrjm(i, zp, zgrj, nz, alpha, beta); 00458 } 00459 } 00460 */ 00461 00462 return; 00463 } 00464 00465 00466 template <class Scalar> 00467 void IntrepidPolylib::Imgrjp(Scalar *im, const Scalar *zgrj, const Scalar *zm, const int nz, 00468 const int mz, const Scalar alpha, const Scalar beta) 00469 { 00470 Scalar zp; 00471 register int i, j; 00472 00473 for (i = 0; i < mz; i++) { 00474 zp = zm[i]; 00475 for (j = 0; j < nz; j++) { 00476 im [i*nz+j] = IntrepidPolylib::hgrjp(j, zp, zgrj, nz, alpha, beta); 00477 } 00478 } 00479 00480 /* original Nektar++ code: is this correct? 00481 for (i = 0; i < nz; i++) { 00482 for (j = 0; j < mz; j++) 00483 { 00484 zp = zm[j]; 00485 im [i*mz+j] = IntrepidPolylib::hgrjp(i, zp, zgrj, nz, alpha, beta); 00486 } 00487 } 00488 */ 00489 00490 return; 00491 } 00492 00493 00494 template <class Scalar> 00495 void IntrepidPolylib::Imglj(Scalar *im, const Scalar *zglj, const Scalar *zm, const int nz, 00496 const int mz, const Scalar alpha, const Scalar beta) 00497 { 00498 Scalar zp; 00499 register int i, j; 00500 00501 for (i = 0; i < mz; i++) { 00502 zp = zm[i]; 00503 for (j = 0; j < nz; j++) { 00504 im[i*nz+j] = IntrepidPolylib::hglj(j, zp, zglj, nz, alpha, beta); 00505 } 00506 } 00507 00508 /* original Nektar++ code: is this correct? 00509 for (i = 0; i < nz; i++) { 00510 for (j = 0; j < mz; j++) 00511 { 00512 zp = zm[j]; 00513 im[i*mz+j] = IntrepidPolylib::hglj(i, zp, zglj, nz, alpha, beta); 00514 } 00515 } 00516 */ 00517 00518 return; 00519 } 00520 00521 00522 template <class Scalar> 00523 void IntrepidPolylib::jacobfd(const int np, const Scalar *z, Scalar *poly_in, Scalar *polyd, 00524 const int n, const Scalar alpha, const Scalar beta){ 00525 register int i; 00526 Scalar zero = 0.0, one = 1.0, two = 2.0; 00527 00528 if(!np) 00529 return; 00530 00531 if(n == 0){ 00532 if(poly_in) 00533 for(i = 0; i < np; ++i) 00534 poly_in[i] = one; 00535 if(polyd) 00536 for(i = 0; i < np; ++i) 00537 polyd[i] = zero; 00538 } 00539 else if (n == 1){ 00540 if(poly_in) 00541 for(i = 0; i < np; ++i) 00542 poly_in[i] = 0.5*(alpha - beta + (alpha + beta + two)*z[i]); 00543 if(polyd) 00544 for(i = 0; i < np; ++i) 00545 polyd[i] = 0.5*(alpha + beta + two); 00546 } 00547 else{ 00548 register int k; 00549 Scalar a1,a2,a3,a4; 00550 Scalar two = 2.0, apb = alpha + beta; 00551 Scalar *poly, *polyn1,*polyn2; 00552 00553 if(poly_in){ // switch for case of no poynomial function return 00554 polyn1 = (Scalar *)malloc(2*np*sizeof(Scalar)); 00555 polyn2 = polyn1+np; 00556 poly = poly_in; 00557 } 00558 else{ 00559 polyn1 = (Scalar *)malloc(3*np*sizeof(Scalar)); 00560 polyn2 = polyn1+np; 00561 poly = polyn2+np; 00562 } 00563 00564 for(i = 0; i < np; ++i){ 00565 polyn2[i] = one; 00566 polyn1[i] = 0.5*(alpha - beta + (alpha + beta + two)*z[i]); 00567 } 00568 00569 for(k = 2; k <= n; ++k){ 00570 a1 = two*k*(k + apb)*(two*k + apb - two); 00571 a2 = (two*k + apb - one)*(alpha*alpha - beta*beta); 00572 a3 = (two*k + apb - two)*(two*k + apb - one)*(two*k + apb); 00573 a4 = two*(k + alpha - one)*(k + beta - one)*(two*k + apb); 00574 00575 a2 /= a1; 00576 a3 /= a1; 00577 a4 /= a1; 00578 00579 for(i = 0; i < np; ++i){ 00580 poly [i] = (a2 + a3*z[i])*polyn1[i] - a4*polyn2[i]; 00581 polyn2[i] = polyn1[i]; 00582 polyn1[i] = poly [i]; 00583 } 00584 } 00585 00586 if(polyd){ 00587 a1 = n*(alpha - beta); 00588 a2 = n*(two*n + alpha + beta); 00589 a3 = two*(n + alpha)*(n + beta); 00590 a4 = (two*n + alpha + beta); 00591 a1 /= a4; a2 /= a4; a3 /= a4; 00592 00593 // note polyn2 points to polyn1 at end of poly iterations 00594 for(i = 0; i < np; ++i){ 00595 polyd[i] = (a1- a2*z[i])*poly[i] + a3*polyn2[i]; 00596 polyd[i] /= (one - z[i]*z[i]); 00597 } 00598 } 00599 00600 free(polyn1); 00601 } 00602 00603 return; 00604 } 00605 00606 00607 template <class Scalar> 00608 void IntrepidPolylib::jacobd(const int np, const Scalar *z, Scalar *polyd, const int n, 00609 const Scalar alpha, const Scalar beta) 00610 { 00611 register int i; 00612 Scalar one = 1.0; 00613 if(n == 0) 00614 for(i = 0; i < np; ++i) polyd[i] = 0.0; 00615 else{ 00616 //jacobf(np,z,polyd,n-1,alpha+one,beta+one); 00617 IntrepidPolylib::jacobfd(np,z,polyd,(Scalar*)0,n-1,alpha+one,beta+one); 00618 for(i = 0; i < np; ++i) polyd[i] *= 0.5*(alpha + beta + (Scalar)n + one); 00619 } 00620 return; 00621 } 00622 00623 00624 template <class Scalar> 00625 void IntrepidPolylib::Jacobz(const int n, Scalar *z, const Scalar alpha, const Scalar beta){ 00626 register int i,j,k; 00627 Scalar dth = M_PI/(2.0*(Scalar)n); 00628 Scalar poly,pder,rlast=0.0; 00629 Scalar sum,delr,r; 00630 Scalar one = 1.0, two = 2.0; 00631 00632 if(!n) 00633 return; 00634 00635 for(k = 0; k < n; ++k){ 00636 r = -std::cos((two*(Scalar)k + one) * dth); 00637 if(k) r = 0.5*(r + rlast); 00638 00639 for(j = 1; j < INTREPID_POLYLIB_STOP; ++j){ 00640 IntrepidPolylib::jacobfd(1,&r,&poly, &pder, n, alpha, beta); 00641 00642 for(i = 0, sum = 0.0; i < k; ++i) sum += one/(r - z[i]); 00643 00644 delr = -poly / (pder - sum * poly); 00645 r += delr; 00646 if( std::abs(delr) < INTREPID_TOL ) break; 00647 } 00648 z[k] = r; 00649 rlast = r; 00650 } 00651 return; 00652 } 00653 00654 00655 template <class Scalar> 00656 void IntrepidPolylib::JacZeros(const int n, Scalar *a, const Scalar alpha, const Scalar beta){ 00657 int i; 00658 Scalar apb, apbi,a2b2; 00659 Scalar *b; 00660 00661 if(!n) 00662 return; 00663 00664 b = (Scalar *) malloc(n*sizeof(Scalar)); 00665 00666 // generate normalised terms 00667 apb = alpha + beta; 00668 apbi = 2.0 + apb; 00669 00670 b[n-1] = std::pow(2.0,apb+1.0)*IntrepidPolylib::gammaF(alpha+1.0)*IntrepidPolylib::gammaF(beta+1.0)/gammaF(apbi); 00671 a[0] = (beta-alpha)/apbi; 00672 b[0] = std::sqrt(4.0*(1.0+alpha)*(1.0+beta)/((apbi+1.0)*apbi*apbi)); 00673 00674 a2b2 = beta*beta-alpha*alpha; 00675 for(i = 1; i < n-1; ++i){ 00676 apbi = 2.0*(i+1) + apb; 00677 a[i] = a2b2/((apbi-2.0)*apbi); 00678 b[i] = std::sqrt(4.0*(i+1)*(i+1+alpha)*(i+1+beta)*(i+1+apb)/ 00679 ((apbi*apbi-1)*apbi*apbi)); 00680 } 00681 00682 apbi = 2.0*n + apb; 00683 //a[n-1] = a2b2/((apbi-2.0)*apbi); // THIS IS A BUG!!! 00684 if (n>1) a[n-1] = a2b2/((apbi-2.0)*apbi); 00685 00686 // find eigenvalues 00687 IntrepidPolylib::TriQL(n, a, b); 00688 00689 free(b); 00690 return; 00691 } 00692 00693 00694 template <class Scalar> 00695 void IntrepidPolylib::TriQL(const int n, Scalar *d,Scalar *e) { 00696 int m,l,iter,i,k; 00697 Scalar s,r,p,g,f,dd,c,b; 00698 00699 for (l=0;l<n;l++) { 00700 iter=0; 00701 do { 00702 for (m=l;m<n-1;m++) { 00703 dd=std::abs(d[m])+std::abs(d[m+1]); 00704 if (std::abs(e[m])+dd == dd) break; 00705 } 00706 if (m != l) { 00707 if (iter++ == 50){ 00708 TEST_FOR_EXCEPTION((1), 00709 std::runtime_error, 00710 ">>> ERROR (IntrepidPolylib): Too many iterations in TQLI."); 00711 } 00712 g=(d[l+1]-d[l])/(2.0*e[l]); 00713 r=std::sqrt((g*g)+1.0); 00714 //g=d[m]-d[l]+e[l]/(g+sign(r,g)); 00715 g=d[m]-d[l]+e[l]/(g+((g)<0 ? -std::abs(r) : std::abs(r))); 00716 s=c=1.0; 00717 p=0.0; 00718 for (i=m-1;i>=l;i--) { 00719 f=s*e[i]; 00720 b=c*e[i]; 00721 if (std::abs(f) >= std::abs(g)) { 00722 c=g/f; 00723 r=std::sqrt((c*c)+1.0); 00724 e[i+1]=f*r; 00725 c *= (s=1.0/r); 00726 } else { 00727 s=f/g; 00728 r=std::sqrt((s*s)+1.0); 00729 e[i+1]=g*r; 00730 s *= (c=1.0/r); 00731 } 00732 g=d[i+1]-p; 00733 r=(d[i]-g)*s+2.0*c*b; 00734 p=s*r; 00735 d[i+1]=g+p; 00736 g=c*r-b; 00737 } 00738 d[l]=d[l]-p; 00739 e[l]=g; 00740 e[m]=0.0; 00741 } 00742 } while (m != l); 00743 } 00744 00745 // order eigenvalues 00746 for(i = 0; i < n-1; ++i){ 00747 k = i; 00748 p = d[i]; 00749 for(l = i+1; l < n; ++l) 00750 if (d[l] < p) { 00751 k = l; 00752 p = d[l]; 00753 } 00754 d[k] = d[i]; 00755 d[i] = p; 00756 } 00757 } 00758 00759 00760 template <class Scalar> 00761 Scalar IntrepidPolylib::gammaF(const Scalar x){ 00762 Scalar gamma = 1.0; 00763 00764 if (x == -0.5) gamma = -2.0*std::sqrt(M_PI); 00765 else if (!x) return gamma; 00766 else if ((x-(int)x) == 0.5){ 00767 int n = (int) x; 00768 Scalar tmp = x; 00769 00770 gamma = std::sqrt(M_PI); 00771 while(n--){ 00772 tmp -= 1.0; 00773 gamma *= tmp; 00774 } 00775 } 00776 else if ((x-(int)x) == 0.0){ 00777 int n = (int) x; 00778 Scalar tmp = x; 00779 00780 while(--n){ 00781 tmp -= 1.0; 00782 gamma *= tmp; 00783 } 00784 } 00785 else 00786 TEST_FOR_EXCEPTION((1), 00787 std::invalid_argument, 00788 ">>> ERROR (IntrepidPolylib): Argument is not of integer or half order."); 00789 return gamma; 00790 } 00791 00792 } // end of namespace Intrepid 00793
1.7.4