|
| 1 | + |
| 2 | +#include <algorithm> |
| 3 | +#include <cmath> |
| 4 | +#include <complex> |
| 5 | +#include <vector> |
| 6 | + |
| 7 | +using namespace std; |
| 8 | + |
| 9 | +typedef unsigned int uint; |
| 10 | + |
| 11 | +namespace pfasst { |
| 12 | + |
| 13 | + template<typename ptype> |
| 14 | + class polynomial { |
| 15 | + vector<ptype> c; |
| 16 | + |
| 17 | + public: |
| 18 | + |
| 19 | + polynomial(uint n) : c(n) { |
| 20 | + fill(c.begin(), c.end(), 0.0); |
| 21 | + } |
| 22 | + |
| 23 | + uint order() const { |
| 24 | + return c.size()-1; |
| 25 | + } |
| 26 | + |
| 27 | + ptype& operator[](const unsigned int i) { return c.at(i); } |
| 28 | + |
| 29 | + polynomial<ptype> differentiate() const { |
| 30 | + polynomial<ptype> p(c.size()-1); |
| 31 | + for (int j=1; j<c.size(); j++) |
| 32 | + p[j-1] = j * c[j]; |
| 33 | + return p; |
| 34 | + } |
| 35 | + |
| 36 | + polynomial<ptype> integrate() const { |
| 37 | + polynomial<ptype> p(c.size()+1); |
| 38 | + for (int j=0; j<c.size(); j++) |
| 39 | + p[j+1] = c[j] / (j+1); |
| 40 | + return p; |
| 41 | + } |
| 42 | + |
| 43 | + template<typename xtype> |
| 44 | + xtype evaluate(const xtype x) const { |
| 45 | + int n = c.size()-1; |
| 46 | + xtype v = c[n]; |
| 47 | + for (int j=n-1; j>=0; j--) |
| 48 | + v = x * v + c[j]; |
| 49 | + return v; |
| 50 | + } |
| 51 | + |
| 52 | + polynomial<ptype> normalize() const { |
| 53 | + polynomial<ptype> p(c.size()); |
| 54 | + for (int j=0; j<c.size(); j++) |
| 55 | + p[j] = c[j] / c[c.size()-1]; |
| 56 | + return p; |
| 57 | + } |
| 58 | + |
| 59 | + vector<ptype> roots() const { |
| 60 | + uint n = c.size()-1; |
| 61 | + |
| 62 | + // initial guess |
| 63 | + polynomial<complex<ptype>> z0(n), z1(n); |
| 64 | + for (int j=0; j<n; j++) { |
| 65 | + z0[j] = pow((0.4, 0.9), j); |
| 66 | + z1[j] = z0[j]; |
| 67 | + } |
| 68 | + |
| 69 | + // durand-kerner-weierstrass iterations |
| 70 | + polynomial<ptype> p = normalize(); |
| 71 | + for (int k=0; k<100; k++) { |
| 72 | + complex<ptype> num, den; |
| 73 | + for (int i=0; i<n; i++) { |
| 74 | + num = p.evaluate(z0[i]); |
| 75 | + den = 1.0; |
| 76 | + for (int j=0; j<n; j++) { |
| 77 | + if (j == i) continue; |
| 78 | + den = den * (z0[i] - z0[j]); |
| 79 | + } |
| 80 | + z0[i] = z0[i] - num / den; |
| 81 | + } |
| 82 | + |
| 83 | + // converged? |
| 84 | + ptype acc = 0.0; |
| 85 | + for (int j=0; j<n; j++) |
| 86 | + acc += abs(z0[j] - z1[j]); |
| 87 | + if (acc < 1e-24) |
| 88 | + break; |
| 89 | + |
| 90 | + z1 = z0; |
| 91 | + } |
| 92 | + |
| 93 | + vector<ptype> roots(n); |
| 94 | + for (int j=0; j<n; j++) |
| 95 | + roots[j] = abs(z0[j]) < 1e-12 ? 0.0 : real(z0[j]); |
| 96 | + |
| 97 | + sort(roots.begin(), roots.end()); |
| 98 | + return roots; |
| 99 | + } |
| 100 | + |
| 101 | + static polynomial<ptype> legendre(const uint order) |
| 102 | + { |
| 103 | + if (order == 0) { |
| 104 | + polynomial<ptype> p(1); |
| 105 | + p[0] = 1.0; |
| 106 | + return p; |
| 107 | + } |
| 108 | + |
| 109 | + if (order == 1) { |
| 110 | + polynomial<ptype> p(2); |
| 111 | + p[0] = 0.0; |
| 112 | + p[1] = 1.0; |
| 113 | + return p; |
| 114 | + } |
| 115 | + |
| 116 | + polynomial<ptype> p0(order+1), p1(order+1), p2(order+1); |
| 117 | + p0[0] = 1.0; p1[1] = 1.0; |
| 118 | + |
| 119 | + // (n + 1) P_{n+1} = (2n + 1) x P_{n} - n P_{n-1} |
| 120 | + for (int m=1; m<order; m++) { |
| 121 | + for (int j=1; j<order+1; j++) |
| 122 | + p2[j] = ( (2*m + 1) * p1[j-1] - m * p0[j] ) / (m + 1); |
| 123 | + p2[0] = - m * p0[0] / (m + 1); |
| 124 | + |
| 125 | + for (int j=0; j<order+1; j++) { |
| 126 | + p0[j] = p1[j]; |
| 127 | + p1[j] = p2[j]; |
| 128 | + } |
| 129 | + } |
| 130 | + |
| 131 | + return p2; |
| 132 | + } |
| 133 | + }; |
| 134 | + |
| 135 | + //#define pi 3.1415926535897932384626433832795028841971693993751 |
| 136 | + |
| 137 | + template<typename ntype> |
| 138 | + vector<ntype> compute_nodes(int nnodes, string qtype) |
| 139 | + { |
| 140 | + vector<ntype> nodes(nnodes); |
| 141 | + |
| 142 | + if (qtype == "gauss-legendre") { |
| 143 | + auto roots = polynomial<ntype>::legendre(nnodes).roots(); |
| 144 | + for (int j=0; j<nnodes; j++) |
| 145 | + nodes[j] = 0.5 * (1.0 + roots[j]); |
| 146 | + } else if (qtype == "gauss-lobatto") { |
| 147 | + auto roots = polynomial<ntype>::legendre(nnodes-1).differentiate().roots(); |
| 148 | + for (int j=0; j<nnodes-2; j++) |
| 149 | + nodes[j+1] = 0.5 * (1.0 + roots[j]); |
| 150 | + nodes[0] = 0.0; nodes[nnodes-1] = 1.0; |
| 151 | + } |
| 152 | + |
| 153 | + return nodes; |
| 154 | + } |
| 155 | + |
| 156 | + |
| 157 | +// void sdc_smat(sdc_mat *smat, |
| 158 | +// const int n, const int m, const int sign, |
| 159 | +// const sdc_dtype *dst, const sdc_dtype *src, |
| 160 | +// const int *flags, int ndst, int nsrc) |
| 161 | +// { |
| 162 | +// /* for (int n=0; n<(ndst-1)*nsrc; n++) */ |
| 163 | +// /* smat[n] = 0.0; */ |
| 164 | + |
| 165 | +// sdc_dtype p[nsrc+1], p1[nsrc+1]; |
| 166 | +// for (int i=0; i<nsrc; i++) { |
| 167 | +// if ((flags[i] & SDC_NODE_PROPER) == 0) continue; |
| 168 | + |
| 169 | +// // construct interpolating polynomial coefficients |
| 170 | +// p[0] = 1.0; for (int j=1; j<nsrc+1; j++) p[j] = 0.0; |
| 171 | +// for (int m=0; m<nsrc; m++) { |
| 172 | +// if (((flags[m] & SDC_NODE_PROPER) == 0) || (m == i)) continue; |
| 173 | +// // p_{m+1}(x) = (x - x_j) * p_m(x) |
| 174 | +// p1[0] = 0.0; |
| 175 | +// for (int j=0; j<nsrc; j++) p1[j+1] = p[j]; |
| 176 | +// for (int j=0; j<nsrc+1; j++) p1[j] -= p[j] * src[m]; |
| 177 | +// for (int j=0; j<nsrc+1; j++) p[j] = p1[j]; |
| 178 | +// } |
| 179 | + |
| 180 | +// // evaluate integrals |
| 181 | +// sdc_dtype den = poly_eval(p, nsrc, src[i]); |
| 182 | +// poly_int(p, nsrc+1); |
| 183 | +// for (int j=1; j<ndst; j++) { |
| 184 | +// sdc_dtype s = poly_eval(p, nsrc, dst[j]) - poly_eval(p, nsrc, dst[j-1]); |
| 185 | +// sdc_mat_setvalue(smat, n+j-1, m+i, s / den, sign); |
| 186 | +// } |
| 187 | +// } |
| 188 | +// } |
| 189 | + |
| 190 | + |
| 191 | + |
| 192 | +} |
0 commit comments