⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swcr.c

📁 gridgen是一款强大的网格生成程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************** * * File:           swcr.c * * Created:        19/03/2001 * * Author:         Pavel Sakov *                 CSIRO Marine Research * * Purpose:        Calculation of Schwarz-Christoffel transform * * Description:    Calculates Schwarz-Christoffel transform as described in: *                 Lloyd N. Trefethen, "Numerical Computation of the *                 Schwartz-Christoffel transformation", SIAM J. Sci. Stat. *                 Comput., 1980, 1(1), 82-102. *                 A fair amount of mission-critical code has been borrowed  *                 from SCPACK (ported from FORTRAN),  *                 see http://www.netlib.org/conformal. * * Revisions:      None * *****************************************************************************/#include "config.h"#include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include <math.h>#include <limits.h>#include <float.h>#include "zode.h"#include "swcr.h"#include "nan.h"#define NEWTON_NITER_MAX 20#define INTEGRATION_NINT_MAX 1000#define WABS_OK_MAX 1.1#define WABS_NEWTON_MAX 2.0#define ZZERO 0.0 + 0.0 * I#define min(x,y) ((x) < (y) ? (x) : (y))#if HAVE_TGAMMAdouble tgamma(double);#elif HAVE_LGAMMAdouble lgamma(double);#endifstruct swcr {    int n;    int nq;    double* betas;    double* nodes;    double* weights;    double* work;    int singular;               /* flag */};static void quit(char* format, ...){    va_list args;    va_start(args, format);    vfprintf(stderr, format, args);    va_end(args);    exit(1);}/* Borrowed from "sclibdbl.f" (SCPACK). * This procedure supplies the coefficients a(j), b(j) of the recurrence * relation * *   b[j] p[j](x) = (x - a[j]) p[j-1](x) - b[j-1] p[j-2](x) * * for the various classical (normalized) orthogonal polynomials, and the * zero-th moment * *   muzero = integral w(x) dx * * of the given polynomial's weight function w(x). Since the polynomials are * ortho-normalized, the tridiagonal matrix is guaranteed to be symmetric. */static double class(int n, double alpha, double beta, double* b, double* a){    int nm1 = n - 1;    double ab = alpha + beta;    double abi = ab + 2.0;    double abi2;    double bbaa = beta * beta - alpha * alpha;    double a1 = alpha + 1;    double b1 = beta + 1;#if HAVE_TGAMMA    double muzero = pow(2.0, ab + 1.0) * tgamma(a1) * tgamma(b1) / tgamma(abi);#elif HAVE_LGAMMA    double muzero = pow(2.0, ab + 1.0) * exp(lgamma(a1) + lgamma(b1) - lgamma(abi));#endif    int i;    a[0] = (beta - alpha) / abi;    b[0] = sqrt(4.0 * a1 * b1 / (ab + 3.0) / abi / abi);    for (i = 1; i < nm1; ++i) {        int i1 = i + 1;        abi = 2.0 * i1 + ab;        abi2 = abi * abi;        a[i] = bbaa / (abi - 2.0) / abi;        b[i] = sqrt(4.0 * i1 * (alpha + i1) * (beta + i1) * (ab + i1) / (abi2 - 1.0) / abi2);    }    abi += 2.0;    a[nm1] = bbaa / (abi - 2.0) / abi;    b[nm1] = 0.0;    return muzero;}/* Borrowed from "sclibdbl.f" (SCPACK). * This is a modified version of the eispack routine imtql2(). It finds the * eigenvalues and first components of the eigenvectors of a symmetric * tridiagonal matrix by the implicit ql method. */static void imtql2(int n, double* d, double* e, double* z){    int nm1 = n - 1;    double b, c, f, g, p, r, s;    int i, l;    if (n <= 1)        return;    e[nm1] = 0.0;    for (l = 0; l < n; ++l) {        int j = 0;        int m, mml;        while (1) {            for (m = l; m < nm1; ++m)                if (fabs(e[m]) < UROUND * (fabs(d[m]) + fabs(d[m + 1])))                    break;            p = d[l];            if (m == l)                goto continue_l;            if (j == 30)                quit("error: imtql2(): number of iterations > 30\n");            j++;            g = (d[l + 1] - p) / e[l] / 2.0;            r = sqrt(g * g + 1.0);            g = d[m] - p + e[l] / (g + copysign(r, g));            s = 1.0;            c = 1.0;            p = 0.0;            mml = m - l;            for (i = m - 1; i >= l; --i) {                f = s * e[i];                b = c * e[i];                if (fabs(f) >= fabs(g)) {                    c = g / f;                    r = sqrt(c * c + 1.0);                    e[i + 1] = f * r;                    s = 1.0 / r;                    c *= s;                } else {                    s = f / g;                    r = sqrt(s * s + 1.0);                    e[i + 1] = g * r;                    c = 1.0 / r;                    s *= c;                }                g = d[i + 1] - p;                r = (d[i] - g) * s + 2.0 * c * b;                p = s * r;                d[i + 1] = g + p;                g = c * r - b;                f = z[i + 1];                z[i + 1] = s * z[i] + c * f;                z[i] = c * z[i] - s * f;            }            d[l] -= p;            e[l] = g;            e[m] = 0.0;        }                       /* while (1) */      continue_l:        ;    }    for (i = 0; i < nm1; ++i) {        int k = i;        int j;        p = d[i];        for (j = i + 1; j < n; ++j) {            if (d[j] < p) {                k = j;                p = d[j];            }        }        if (k != i) {            d[k] = d[i];            d[i] = p;            p = z[i];            z[i] = z[k];            z[k] = p;        }    }}/* Borrowed from "sclibdbl.f" (SCPACK). * This routine computes the nodes t[] and weights w[] for Gauss-Jacobi * quadrature formulas. These are used when one wishes to approximate * *   integral (from a to b) f(x) w(x) dx * * by * *    n *   sum w[j] f(t[j]) *   j=1 * * (w(x) and w[j] have no connection with each other), where w(x) is the weight * function, * *   w(x) = (1-x)**alpha * (1+x)**beta * * on (-1, 1); alpha, beta > -1. * * @param n     The number of points used for the quadrature rule * @param alpha Parameter of the weight function * @param beta  Parameter of the weight function * @param b     Work array [n] * @param t     Nodes [n] (output) * @param w     Weights [n] (output) * * Subroutines required: class, imtql2 * * Reference: * * The routine has been adapted from the more general routine gaussq by Golub * and Welsch. See Golub, G. H., and Welsch, J. H., "Calculation of Gaussian * quadrature rules", Mathematics of computation, 23 (April 1969), pp. 221-230. */static void gaussj(int n, double alpha, double beta, double* b, double* t, double* w){    double mu0 = class(n, alpha, beta, b, t);    int i;    w[0] = 1.0;    imtql2(n, t, b, w);    for (i = 0; i < n; ++i)        w[i] = mu0 * w[i] * w[i];}/* Creates Schwarz-Christoffel transform structure. * @param n Number of prevertices * @param nq Number of nodes in Gauss-Jacobi quadrature formulas * @param betas Array of angle parameters [n]: betas[i] = alpha[i]/pi - 1,  *              where alpha[i] -- interior angle at i-th vertex * @return Pointer to Schwarz-Christoffel transform structure */swcr* sc_create(int n, int nq, double betas[]){    swcr* sc;    int i, ii;    if (nq <= 0)        return NULL;    sc = malloc(sizeof(swcr));    sc->n = n;    sc->nq = nq;    sc->betas = betas;    sc->nodes = malloc((n + 1) * nq * sizeof(double));    sc->weights = calloc((n + 1) * nq, sizeof(double));    sc->work = malloc(nq * sizeof(double));    sc->singular = 0;    for (i = 0; i < n; ++i) {        ii = nq * i;        if (betas[i] > -1.0)            gaussj(nq, 0.0, betas[i], sc->work, &sc->nodes[ii], &sc->weights[ii]);    }    ii = nq * n;    gaussj(nq, 0.0, 0.0, sc->work, &sc->nodes[ii], &sc->weights[ii]);    return sc;}/* Destroys Schwarz-Christoffel transform structure. * @param sc Structure to be destroyed */void sc_destroy(swcr* sc){    if (sc == NULL)        return;    free(sc->nodes);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -