13d177a5cSEmil Constantinescu 23d177a5cSEmil Constantinescu #include <../src/ts/impls/implicit/glle/glle.h> /*I "petscts.h" I*/ 33d177a5cSEmil Constantinescu #include <petscdm.h> 43d177a5cSEmil Constantinescu #include <petscblaslapack.h> 53d177a5cSEmil Constantinescu 6c793f718SLisandro Dalcin static const char *TSGLLEErrorDirections[] = {"FORWARD", "BACKWARD", "TSGLLEErrorDirection", "TSGLLEERROR_", NULL}; 73d177a5cSEmil Constantinescu static PetscFunctionList TSGLLEList; 83d177a5cSEmil Constantinescu static PetscFunctionList TSGLLEAcceptList; 93d177a5cSEmil Constantinescu static PetscBool TSGLLEPackageInitialized; 103d177a5cSEmil Constantinescu static PetscBool TSGLLERegisterAllCalled; 113d177a5cSEmil Constantinescu 123d177a5cSEmil Constantinescu /* This function is pure */ 13*9371c9d4SSatish Balay static PetscScalar Factorial(PetscInt n) { 143d177a5cSEmil Constantinescu PetscInt i; 153d177a5cSEmil Constantinescu if (n < 12) { /* Can compute with 32-bit integers */ 163d177a5cSEmil Constantinescu PetscInt f = 1; 173d177a5cSEmil Constantinescu for (i = 2; i <= n; i++) f *= i; 183d177a5cSEmil Constantinescu return (PetscScalar)f; 193d177a5cSEmil Constantinescu } else { 203d177a5cSEmil Constantinescu PetscScalar f = 1.; 213d177a5cSEmil Constantinescu for (i = 2; i <= n; i++) f *= (PetscScalar)i; 223d177a5cSEmil Constantinescu return f; 233d177a5cSEmil Constantinescu } 243d177a5cSEmil Constantinescu } 253d177a5cSEmil Constantinescu 263d177a5cSEmil Constantinescu /* This function is pure */ 27*9371c9d4SSatish Balay static PetscScalar CPowF(PetscScalar c, PetscInt p) { 283d177a5cSEmil Constantinescu return PetscPowRealInt(PetscRealPart(c), p) / Factorial(p); 293d177a5cSEmil Constantinescu } 303d177a5cSEmil Constantinescu 31*9371c9d4SSatish Balay static PetscErrorCode TSGLLEGetVecs(TS ts, DM dm, Vec *Z, Vec *Ydotstage) { 323d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 333d177a5cSEmil Constantinescu 343d177a5cSEmil Constantinescu PetscFunctionBegin; 353d177a5cSEmil Constantinescu if (Z) { 363d177a5cSEmil Constantinescu if (dm && dm != ts->dm) { 379566063dSJacob Faibussowitsch PetscCall(DMGetNamedGlobalVector(dm, "TSGLLE_Z", Z)); 383d177a5cSEmil Constantinescu } else *Z = gl->Z; 393d177a5cSEmil Constantinescu } 403d177a5cSEmil Constantinescu if (Ydotstage) { 413d177a5cSEmil Constantinescu if (dm && dm != ts->dm) { 429566063dSJacob Faibussowitsch PetscCall(DMGetNamedGlobalVector(dm, "TSGLLE_Ydot", Ydotstage)); 433d177a5cSEmil Constantinescu } else *Ydotstage = gl->Ydot[gl->stage]; 443d177a5cSEmil Constantinescu } 453d177a5cSEmil Constantinescu PetscFunctionReturn(0); 463d177a5cSEmil Constantinescu } 473d177a5cSEmil Constantinescu 48*9371c9d4SSatish Balay static PetscErrorCode TSGLLERestoreVecs(TS ts, DM dm, Vec *Z, Vec *Ydotstage) { 493d177a5cSEmil Constantinescu PetscFunctionBegin; 503d177a5cSEmil Constantinescu if (Z) { 51*9371c9d4SSatish Balay if (dm && dm != ts->dm) { PetscCall(DMRestoreNamedGlobalVector(dm, "TSGLLE_Z", Z)); } 523d177a5cSEmil Constantinescu } 533d177a5cSEmil Constantinescu if (Ydotstage) { 54*9371c9d4SSatish Balay if (dm && dm != ts->dm) { PetscCall(DMRestoreNamedGlobalVector(dm, "TSGLLE_Ydot", Ydotstage)); } 553d177a5cSEmil Constantinescu } 563d177a5cSEmil Constantinescu PetscFunctionReturn(0); 573d177a5cSEmil Constantinescu } 583d177a5cSEmil Constantinescu 59*9371c9d4SSatish Balay static PetscErrorCode DMCoarsenHook_TSGLLE(DM fine, DM coarse, void *ctx) { 603d177a5cSEmil Constantinescu PetscFunctionBegin; 613d177a5cSEmil Constantinescu PetscFunctionReturn(0); 623d177a5cSEmil Constantinescu } 633d177a5cSEmil Constantinescu 64*9371c9d4SSatish Balay static PetscErrorCode DMRestrictHook_TSGLLE(DM fine, Mat restrct, Vec rscale, Mat inject, DM coarse, void *ctx) { 653d177a5cSEmil Constantinescu TS ts = (TS)ctx; 663d177a5cSEmil Constantinescu Vec Ydot, Ydot_c; 673d177a5cSEmil Constantinescu 683d177a5cSEmil Constantinescu PetscFunctionBegin; 699566063dSJacob Faibussowitsch PetscCall(TSGLLEGetVecs(ts, fine, NULL, &Ydot)); 709566063dSJacob Faibussowitsch PetscCall(TSGLLEGetVecs(ts, coarse, NULL, &Ydot_c)); 719566063dSJacob Faibussowitsch PetscCall(MatRestrict(restrct, Ydot, Ydot_c)); 729566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(Ydot_c, rscale, Ydot_c)); 739566063dSJacob Faibussowitsch PetscCall(TSGLLERestoreVecs(ts, fine, NULL, &Ydot)); 749566063dSJacob Faibussowitsch PetscCall(TSGLLERestoreVecs(ts, coarse, NULL, &Ydot_c)); 753d177a5cSEmil Constantinescu PetscFunctionReturn(0); 763d177a5cSEmil Constantinescu } 773d177a5cSEmil Constantinescu 78*9371c9d4SSatish Balay static PetscErrorCode DMSubDomainHook_TSGLLE(DM dm, DM subdm, void *ctx) { 793d177a5cSEmil Constantinescu PetscFunctionBegin; 803d177a5cSEmil Constantinescu PetscFunctionReturn(0); 813d177a5cSEmil Constantinescu } 823d177a5cSEmil Constantinescu 83*9371c9d4SSatish Balay static PetscErrorCode DMSubDomainRestrictHook_TSGLLE(DM dm, VecScatter gscat, VecScatter lscat, DM subdm, void *ctx) { 843d177a5cSEmil Constantinescu TS ts = (TS)ctx; 853d177a5cSEmil Constantinescu Vec Ydot, Ydot_s; 863d177a5cSEmil Constantinescu 873d177a5cSEmil Constantinescu PetscFunctionBegin; 889566063dSJacob Faibussowitsch PetscCall(TSGLLEGetVecs(ts, dm, NULL, &Ydot)); 899566063dSJacob Faibussowitsch PetscCall(TSGLLEGetVecs(ts, subdm, NULL, &Ydot_s)); 903d177a5cSEmil Constantinescu 919566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(gscat, Ydot, Ydot_s, INSERT_VALUES, SCATTER_FORWARD)); 929566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(gscat, Ydot, Ydot_s, INSERT_VALUES, SCATTER_FORWARD)); 933d177a5cSEmil Constantinescu 949566063dSJacob Faibussowitsch PetscCall(TSGLLERestoreVecs(ts, dm, NULL, &Ydot)); 959566063dSJacob Faibussowitsch PetscCall(TSGLLERestoreVecs(ts, subdm, NULL, &Ydot_s)); 963d177a5cSEmil Constantinescu PetscFunctionReturn(0); 973d177a5cSEmil Constantinescu } 983d177a5cSEmil Constantinescu 99*9371c9d4SSatish Balay static PetscErrorCode TSGLLESchemeCreate(PetscInt p, PetscInt q, PetscInt r, PetscInt s, const PetscScalar *c, const PetscScalar *a, const PetscScalar *b, const PetscScalar *u, const PetscScalar *v, TSGLLEScheme *inscheme) { 1003d177a5cSEmil Constantinescu TSGLLEScheme scheme; 1013d177a5cSEmil Constantinescu PetscInt j; 1023d177a5cSEmil Constantinescu 1033d177a5cSEmil Constantinescu PetscFunctionBegin; 10408401ef6SPierre Jolivet PetscCheck(p >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Scheme order must be positive"); 10508401ef6SPierre Jolivet PetscCheck(r >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "At least one item must be carried between steps"); 10608401ef6SPierre Jolivet PetscCheck(s >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "At least one stage is required"); 107064a246eSJacob Faibussowitsch PetscValidPointer(inscheme, 10); 108c793f718SLisandro Dalcin *inscheme = NULL; 1099566063dSJacob Faibussowitsch PetscCall(PetscNew(&scheme)); 1103d177a5cSEmil Constantinescu scheme->p = p; 1113d177a5cSEmil Constantinescu scheme->q = q; 1123d177a5cSEmil Constantinescu scheme->r = r; 1133d177a5cSEmil Constantinescu scheme->s = s; 1143d177a5cSEmil Constantinescu 1159566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(s, &scheme->c, s * s, &scheme->a, r * s, &scheme->b, r * s, &scheme->u, r * r, &scheme->v)); 1169566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(scheme->c, c, s)); 1173d177a5cSEmil Constantinescu for (j = 0; j < s * s; j++) scheme->a[j] = (PetscAbsScalar(a[j]) < 1e-12) ? 0 : a[j]; 1183d177a5cSEmil Constantinescu for (j = 0; j < r * s; j++) scheme->b[j] = (PetscAbsScalar(b[j]) < 1e-12) ? 0 : b[j]; 1193d177a5cSEmil Constantinescu for (j = 0; j < s * r; j++) scheme->u[j] = (PetscAbsScalar(u[j]) < 1e-12) ? 0 : u[j]; 1203d177a5cSEmil Constantinescu for (j = 0; j < r * r; j++) scheme->v[j] = (PetscAbsScalar(v[j]) < 1e-12) ? 0 : v[j]; 1213d177a5cSEmil Constantinescu 1229566063dSJacob Faibussowitsch PetscCall(PetscMalloc6(r, &scheme->alpha, r, &scheme->beta, r, &scheme->gamma, 3 * s, &scheme->phi, 3 * r, &scheme->psi, r, &scheme->stage_error)); 1233d177a5cSEmil Constantinescu { 1243d177a5cSEmil Constantinescu PetscInt i, j, k, ss = s + 2; 1253d177a5cSEmil Constantinescu PetscBLASInt m, n, one = 1, *ipiv, lwork = 4 * ((s + 3) * 3 + 3), info, ldb; 1263d177a5cSEmil Constantinescu PetscReal rcond, *sing, *workreal; 1273d177a5cSEmil Constantinescu PetscScalar *ImV, *H, *bmat, *workscalar, *c = scheme->c, *a = scheme->a, *b = scheme->b, *u = scheme->u, *v = scheme->v; 1283d177a5cSEmil Constantinescu PetscBLASInt rank; 1299566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(PetscSqr(r), &ImV, 3 * s, &H, 3 * ss, &bmat, lwork, &workscalar, 5 * (3 + r), &workreal, r + s, &sing, r + s, &ipiv)); 1303d177a5cSEmil Constantinescu 1313d177a5cSEmil Constantinescu /* column-major input */ 1323d177a5cSEmil Constantinescu for (i = 0; i < r - 1; i++) { 1333d177a5cSEmil Constantinescu for (j = 0; j < r - 1; j++) ImV[i + j * r] = 1.0 * (i == j) - v[(i + 1) * r + j + 1]; 1343d177a5cSEmil Constantinescu } 1353d177a5cSEmil Constantinescu /* Build right hand side for alpha (tp - glm.B(2:end,:)*(glm.c.^(p)./factorial(p))) */ 1363d177a5cSEmil Constantinescu for (i = 1; i < r; i++) { 1373d177a5cSEmil Constantinescu scheme->alpha[i] = 1. / Factorial(p + 1 - i); 1383d177a5cSEmil Constantinescu for (j = 0; j < s; j++) scheme->alpha[i] -= b[i * s + j] * CPowF(c[j], p); 1393d177a5cSEmil Constantinescu } 1409566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(r - 1, &m)); 1419566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(r, &n)); 142792fecdfSBarry Smith PetscCallBLAS("LAPACKgesv", LAPACKgesv_(&m, &one, ImV, &n, ipiv, scheme->alpha + 1, &n, &info)); 14308401ef6SPierre Jolivet PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to GESV"); 14408401ef6SPierre Jolivet PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_MAT_LU_ZRPVT, "Bad LU factorization"); 1453d177a5cSEmil Constantinescu 1463d177a5cSEmil Constantinescu /* Build right hand side for beta (tp1 - glm.B(2:end,:)*(glm.c.^(p+1)./factorial(p+1)) - e.alpha) */ 1473d177a5cSEmil Constantinescu for (i = 1; i < r; i++) { 1483d177a5cSEmil Constantinescu scheme->beta[i] = 1. / Factorial(p + 2 - i) - scheme->alpha[i]; 1493d177a5cSEmil Constantinescu for (j = 0; j < s; j++) scheme->beta[i] -= b[i * s + j] * CPowF(c[j], p + 1); 1503d177a5cSEmil Constantinescu } 151792fecdfSBarry Smith PetscCallBLAS("LAPACKgetrs", LAPACKgetrs_("No transpose", &m, &one, ImV, &n, ipiv, scheme->beta + 1, &n, &info)); 15208401ef6SPierre Jolivet PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to GETRS"); 15308401ef6SPierre Jolivet PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Should not happen"); 1543d177a5cSEmil Constantinescu 1553d177a5cSEmil Constantinescu /* Build stage_error vector 1563d177a5cSEmil Constantinescu xi = glm.c.^(p+1)/factorial(p+1) - glm.A*glm.c.^p/factorial(p) + glm.U(:,2:end)*e.alpha; 1573d177a5cSEmil Constantinescu */ 1583d177a5cSEmil Constantinescu for (i = 0; i < s; i++) { 1593d177a5cSEmil Constantinescu scheme->stage_error[i] = CPowF(c[i], p + 1); 1603d177a5cSEmil Constantinescu for (j = 0; j < s; j++) scheme->stage_error[i] -= a[i * s + j] * CPowF(c[j], p); 1613d177a5cSEmil Constantinescu for (j = 1; j < r; j++) scheme->stage_error[i] += u[i * r + j] * scheme->alpha[j]; 1623d177a5cSEmil Constantinescu } 1633d177a5cSEmil Constantinescu 1643d177a5cSEmil Constantinescu /* alpha[0] (epsilon in B,J,W 2007) 1653d177a5cSEmil Constantinescu epsilon = 1/factorial(p+1) - B(1,:)*c.^p/factorial(p) + V(1,2:end)*e.alpha; 1663d177a5cSEmil Constantinescu */ 1673d177a5cSEmil Constantinescu scheme->alpha[0] = 1. / Factorial(p + 1); 1683d177a5cSEmil Constantinescu for (j = 0; j < s; j++) scheme->alpha[0] -= b[0 * s + j] * CPowF(c[j], p); 1693d177a5cSEmil Constantinescu for (j = 1; j < r; j++) scheme->alpha[0] += v[0 * r + j] * scheme->alpha[j]; 1703d177a5cSEmil Constantinescu 1713d177a5cSEmil Constantinescu /* right hand side for gamma (glm.B(2:end,:)*e.xi - e.epsilon*eye(s-1,1)) */ 1723d177a5cSEmil Constantinescu for (i = 1; i < r; i++) { 1733d177a5cSEmil Constantinescu scheme->gamma[i] = (i == 1 ? -1. : 0) * scheme->alpha[0]; 1743d177a5cSEmil Constantinescu for (j = 0; j < s; j++) scheme->gamma[i] += b[i * s + j] * scheme->stage_error[j]; 1753d177a5cSEmil Constantinescu } 176792fecdfSBarry Smith PetscCallBLAS("LAPACKgetrs", LAPACKgetrs_("No transpose", &m, &one, ImV, &n, ipiv, scheme->gamma + 1, &n, &info)); 17708401ef6SPierre Jolivet PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to GETRS"); 17808401ef6SPierre Jolivet PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Should not happen"); 1793d177a5cSEmil Constantinescu 1803d177a5cSEmil Constantinescu /* beta[0] (rho in B,J,W 2007) 1813d177a5cSEmil Constantinescu e.rho = 1/factorial(p+2) - glm.B(1,:)*glm.c.^(p+1)/factorial(p+1) ... 1823d177a5cSEmil Constantinescu + glm.V(1,2:end)*e.beta;% - e.epsilon; 1833d177a5cSEmil Constantinescu % Note: The paper (B,J,W 2007) includes the last term in their definition 1843d177a5cSEmil Constantinescu * */ 1853d177a5cSEmil Constantinescu scheme->beta[0] = 1. / Factorial(p + 2); 1863d177a5cSEmil Constantinescu for (j = 0; j < s; j++) scheme->beta[0] -= b[0 * s + j] * CPowF(c[j], p + 1); 1873d177a5cSEmil Constantinescu for (j = 1; j < r; j++) scheme->beta[0] += v[0 * r + j] * scheme->beta[j]; 1883d177a5cSEmil Constantinescu 1893d177a5cSEmil Constantinescu /* gamma[0] (sigma in B,J,W 2007) 1903d177a5cSEmil Constantinescu * e.sigma = glm.B(1,:)*e.xi + glm.V(1,2:end)*e.gamma; 1913d177a5cSEmil Constantinescu * */ 1923d177a5cSEmil Constantinescu scheme->gamma[0] = 0.0; 1933d177a5cSEmil Constantinescu for (j = 0; j < s; j++) scheme->gamma[0] += b[0 * s + j] * scheme->stage_error[j]; 1943d177a5cSEmil Constantinescu for (j = 1; j < r; j++) scheme->gamma[0] += v[0 * s + j] * scheme->gamma[j]; 1953d177a5cSEmil Constantinescu 1963d177a5cSEmil Constantinescu /* Assemble H 19763a3b9bcSJacob Faibussowitsch * % " PetscInt_FMT "etermine the error estimators phi 1983d177a5cSEmil Constantinescu H = [[cpow(glm.c,p) + C*e.alpha] [cpow(glm.c,p+1) + C*e.beta] ... 1993d177a5cSEmil Constantinescu [e.xi - C*(e.gamma + 0*e.epsilon*eye(s-1,1))]]'; 2003d177a5cSEmil Constantinescu % Paper has formula above without the 0, but that term must be left 2013d177a5cSEmil Constantinescu % out to satisfy the conditions they propose and to make the 2023d177a5cSEmil Constantinescu % example schemes work 2033d177a5cSEmil Constantinescu e.H = H; 2043d177a5cSEmil Constantinescu e.phi = (H \ [1 0 0;1 1 0;0 0 -1])'; 2053d177a5cSEmil Constantinescu e.psi = -e.phi*C; 2063d177a5cSEmil Constantinescu * */ 2073d177a5cSEmil Constantinescu for (j = 0; j < s; j++) { 2083d177a5cSEmil Constantinescu H[0 + j * 3] = CPowF(c[j], p); 2093d177a5cSEmil Constantinescu H[1 + j * 3] = CPowF(c[j], p + 1); 2103d177a5cSEmil Constantinescu H[2 + j * 3] = scheme->stage_error[j]; 2113d177a5cSEmil Constantinescu for (k = 1; k < r; k++) { 2123d177a5cSEmil Constantinescu H[0 + j * 3] += CPowF(c[j], k - 1) * scheme->alpha[k]; 2133d177a5cSEmil Constantinescu H[1 + j * 3] += CPowF(c[j], k - 1) * scheme->beta[k]; 2143d177a5cSEmil Constantinescu H[2 + j * 3] -= CPowF(c[j], k - 1) * scheme->gamma[k]; 2153d177a5cSEmil Constantinescu } 2163d177a5cSEmil Constantinescu } 217*9371c9d4SSatish Balay bmat[0 + 0 * ss] = 1.; 218*9371c9d4SSatish Balay bmat[0 + 1 * ss] = 0.; 219*9371c9d4SSatish Balay bmat[0 + 2 * ss] = 0.; 220*9371c9d4SSatish Balay bmat[1 + 0 * ss] = 1.; 221*9371c9d4SSatish Balay bmat[1 + 1 * ss] = 1.; 222*9371c9d4SSatish Balay bmat[1 + 2 * ss] = 0.; 223*9371c9d4SSatish Balay bmat[2 + 0 * ss] = 0.; 224*9371c9d4SSatish Balay bmat[2 + 1 * ss] = 0.; 225*9371c9d4SSatish Balay bmat[2 + 2 * ss] = -1.; 2263d177a5cSEmil Constantinescu m = 3; 2279566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(s, &n)); 2289566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(ss, &ldb)); 2293d177a5cSEmil Constantinescu rcond = 1e-12; 2303d177a5cSEmil Constantinescu #if defined(PETSC_USE_COMPLEX) 2313d177a5cSEmil Constantinescu /* ZGELSS( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, WORK, LWORK, RWORK, INFO) */ 232792fecdfSBarry Smith PetscCallBLAS("LAPACKgelss", LAPACKgelss_(&m, &n, &m, H, &m, bmat, &ldb, sing, &rcond, &rank, workscalar, &lwork, workreal, &info)); 2333d177a5cSEmil Constantinescu #else 2343d177a5cSEmil Constantinescu /* DGELSS( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, WORK, LWORK, INFO) */ 235792fecdfSBarry Smith PetscCallBLAS("LAPACKgelss", LAPACKgelss_(&m, &n, &m, H, &m, bmat, &ldb, sing, &rcond, &rank, workscalar, &lwork, &info)); 2363d177a5cSEmil Constantinescu #endif 23708401ef6SPierre Jolivet PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to GELSS"); 23808401ef6SPierre Jolivet PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "SVD failed to converge"); 2393d177a5cSEmil Constantinescu 2403d177a5cSEmil Constantinescu for (j = 0; j < 3; j++) { 2413d177a5cSEmil Constantinescu for (k = 0; k < s; k++) scheme->phi[k + j * s] = bmat[k + j * ss]; 2423d177a5cSEmil Constantinescu } 2433d177a5cSEmil Constantinescu 2443d177a5cSEmil Constantinescu /* the other part of the error estimator, psi in B,J,W 2007 */ 2453d177a5cSEmil Constantinescu scheme->psi[0 * r + 0] = 0.; 2463d177a5cSEmil Constantinescu scheme->psi[1 * r + 0] = 0.; 2473d177a5cSEmil Constantinescu scheme->psi[2 * r + 0] = 0.; 2483d177a5cSEmil Constantinescu for (j = 1; j < r; j++) { 2493d177a5cSEmil Constantinescu scheme->psi[0 * r + j] = 0.; 2503d177a5cSEmil Constantinescu scheme->psi[1 * r + j] = 0.; 2513d177a5cSEmil Constantinescu scheme->psi[2 * r + j] = 0.; 2523d177a5cSEmil Constantinescu for (k = 0; k < s; k++) { 2533d177a5cSEmil Constantinescu scheme->psi[0 * r + j] -= CPowF(c[k], j - 1) * scheme->phi[0 * s + k]; 2543d177a5cSEmil Constantinescu scheme->psi[1 * r + j] -= CPowF(c[k], j - 1) * scheme->phi[1 * s + k]; 2553d177a5cSEmil Constantinescu scheme->psi[2 * r + j] -= CPowF(c[k], j - 1) * scheme->phi[2 * s + k]; 2563d177a5cSEmil Constantinescu } 2573d177a5cSEmil Constantinescu } 2589566063dSJacob Faibussowitsch PetscCall(PetscFree7(ImV, H, bmat, workscalar, workreal, sing, ipiv)); 2593d177a5cSEmil Constantinescu } 2603d177a5cSEmil Constantinescu /* Check which properties are satisfied */ 2613d177a5cSEmil Constantinescu scheme->stiffly_accurate = PETSC_TRUE; 2623d177a5cSEmil Constantinescu if (scheme->c[s - 1] != 1.) scheme->stiffly_accurate = PETSC_FALSE; 263*9371c9d4SSatish Balay for (j = 0; j < s; j++) 264*9371c9d4SSatish Balay if (a[(s - 1) * s + j] != b[j]) scheme->stiffly_accurate = PETSC_FALSE; 265*9371c9d4SSatish Balay for (j = 0; j < r; j++) 266*9371c9d4SSatish Balay if (u[(s - 1) * r + j] != v[j]) scheme->stiffly_accurate = PETSC_FALSE; 2673d177a5cSEmil Constantinescu scheme->fsal = scheme->stiffly_accurate; /* FSAL is stronger */ 268*9371c9d4SSatish Balay for (j = 0; j < s - 1; j++) 269*9371c9d4SSatish Balay if (r > 1 && b[1 * s + j] != 0.) scheme->fsal = PETSC_FALSE; 2703d177a5cSEmil Constantinescu if (b[1 * s + r - 1] != 1.) scheme->fsal = PETSC_FALSE; 271*9371c9d4SSatish Balay for (j = 0; j < r; j++) 272*9371c9d4SSatish Balay if (r > 1 && v[1 * r + j] != 0.) scheme->fsal = PETSC_FALSE; 2733d177a5cSEmil Constantinescu 2743d177a5cSEmil Constantinescu *inscheme = scheme; 2753d177a5cSEmil Constantinescu PetscFunctionReturn(0); 2763d177a5cSEmil Constantinescu } 2773d177a5cSEmil Constantinescu 278*9371c9d4SSatish Balay static PetscErrorCode TSGLLESchemeDestroy(TSGLLEScheme sc) { 2793d177a5cSEmil Constantinescu PetscFunctionBegin; 2809566063dSJacob Faibussowitsch PetscCall(PetscFree5(sc->c, sc->a, sc->b, sc->u, sc->v)); 2819566063dSJacob Faibussowitsch PetscCall(PetscFree6(sc->alpha, sc->beta, sc->gamma, sc->phi, sc->psi, sc->stage_error)); 2829566063dSJacob Faibussowitsch PetscCall(PetscFree(sc)); 2833d177a5cSEmil Constantinescu PetscFunctionReturn(0); 2843d177a5cSEmil Constantinescu } 2853d177a5cSEmil Constantinescu 286*9371c9d4SSatish Balay static PetscErrorCode TSGLLEDestroy_Default(TS_GLLE *gl) { 2873d177a5cSEmil Constantinescu PetscInt i; 2883d177a5cSEmil Constantinescu 2893d177a5cSEmil Constantinescu PetscFunctionBegin; 2903d177a5cSEmil Constantinescu for (i = 0; i < gl->nschemes; i++) { 2919566063dSJacob Faibussowitsch if (gl->schemes[i]) PetscCall(TSGLLESchemeDestroy(gl->schemes[i])); 2923d177a5cSEmil Constantinescu } 2939566063dSJacob Faibussowitsch PetscCall(PetscFree(gl->schemes)); 2943d177a5cSEmil Constantinescu gl->nschemes = 0; 2959566063dSJacob Faibussowitsch PetscCall(PetscMemzero(gl->type_name, sizeof(gl->type_name))); 2963d177a5cSEmil Constantinescu PetscFunctionReturn(0); 2973d177a5cSEmil Constantinescu } 2983d177a5cSEmil Constantinescu 299*9371c9d4SSatish Balay static PetscErrorCode TSGLLEViewTable_Private(PetscViewer viewer, PetscInt m, PetscInt n, const PetscScalar a[], const char name[]) { 3003d177a5cSEmil Constantinescu PetscBool iascii; 3013d177a5cSEmil Constantinescu PetscInt i, j; 3023d177a5cSEmil Constantinescu 3033d177a5cSEmil Constantinescu PetscFunctionBegin; 3049566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 3053d177a5cSEmil Constantinescu if (iascii) { 3069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%30s = [", name)); 3073d177a5cSEmil Constantinescu for (i = 0; i < m; i++) { 3089566063dSJacob Faibussowitsch if (i) PetscCall(PetscViewerASCIIPrintf(viewer, "%30s [", "")); 3099566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 310*9371c9d4SSatish Balay for (j = 0; j < n; j++) { PetscCall(PetscViewerASCIIPrintf(viewer, " %12.8g", (double)PetscRealPart(a[i * n + j]))); } 3119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "]\n")); 3129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 3133d177a5cSEmil Constantinescu } 3143d177a5cSEmil Constantinescu } 3153d177a5cSEmil Constantinescu PetscFunctionReturn(0); 3163d177a5cSEmil Constantinescu } 3173d177a5cSEmil Constantinescu 318*9371c9d4SSatish Balay static PetscErrorCode TSGLLESchemeView(TSGLLEScheme sc, PetscBool view_details, PetscViewer viewer) { 3193d177a5cSEmil Constantinescu PetscBool iascii; 3203d177a5cSEmil Constantinescu 3213d177a5cSEmil Constantinescu PetscFunctionBegin; 3229566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 3233d177a5cSEmil Constantinescu if (iascii) { 32463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "GL scheme p,q,r,s = %" PetscInt_FMT ",%" PetscInt_FMT ",%" PetscInt_FMT ",%" PetscInt_FMT "\n", sc->p, sc->q, sc->r, sc->s)); 3259566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 3269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Stiffly accurate: %s, FSAL: %s\n", sc->stiffly_accurate ? "yes" : "no", sc->fsal ? "yes" : "no")); 327*9371c9d4SSatish Balay PetscCall(PetscViewerASCIIPrintf(viewer, "Leading error constants: %10.3e %10.3e %10.3e\n", (double)PetscRealPart(sc->alpha[0]), (double)PetscRealPart(sc->beta[0]), (double)PetscRealPart(sc->gamma[0]))); 3289566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, 1, sc->s, sc->c, "Abscissas c")); 3293d177a5cSEmil Constantinescu if (view_details) { 3309566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, sc->s, sc->s, sc->a, "A")); 3319566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, sc->r, sc->s, sc->b, "B")); 3329566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, sc->s, sc->r, sc->u, "U")); 3339566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, sc->r, sc->r, sc->v, "V")); 3343d177a5cSEmil Constantinescu 3359566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, 3, sc->s, sc->phi, "Error estimate phi")); 3369566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, 3, sc->r, sc->psi, "Error estimate psi")); 3379566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, 1, sc->r, sc->alpha, "Modify alpha")); 3389566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, 1, sc->r, sc->beta, "Modify beta")); 3399566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, 1, sc->r, sc->gamma, "Modify gamma")); 3409566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, 1, sc->s, sc->stage_error, "Stage error xi")); 3413d177a5cSEmil Constantinescu } 3429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 34398921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Viewer type %s not supported", ((PetscObject)viewer)->type_name); 3443d177a5cSEmil Constantinescu PetscFunctionReturn(0); 3453d177a5cSEmil Constantinescu } 3463d177a5cSEmil Constantinescu 347*9371c9d4SSatish Balay static PetscErrorCode TSGLLEEstimateHigherMoments_Default(TSGLLEScheme sc, PetscReal h, Vec Ydot[], Vec Xold[], Vec hm[]) { 3483d177a5cSEmil Constantinescu PetscInt i; 3493d177a5cSEmil Constantinescu 3503d177a5cSEmil Constantinescu PetscFunctionBegin; 351cad9d221SBarry Smith PetscCheck(sc->r <= 64 && sc->s <= 64, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Ridiculous number of stages or items passed between stages"); 3523d177a5cSEmil Constantinescu /* build error vectors*/ 3533d177a5cSEmil Constantinescu for (i = 0; i < 3; i++) { 3543d177a5cSEmil Constantinescu PetscScalar phih[64]; 3553d177a5cSEmil Constantinescu PetscInt j; 3563d177a5cSEmil Constantinescu for (j = 0; j < sc->s; j++) phih[j] = sc->phi[i * sc->s + j] * h; 3579566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(hm[i])); 3589566063dSJacob Faibussowitsch PetscCall(VecMAXPY(hm[i], sc->s, phih, Ydot)); 3599566063dSJacob Faibussowitsch PetscCall(VecMAXPY(hm[i], sc->r, &sc->psi[i * sc->r], Xold)); 3603d177a5cSEmil Constantinescu } 3613d177a5cSEmil Constantinescu PetscFunctionReturn(0); 3623d177a5cSEmil Constantinescu } 3633d177a5cSEmil Constantinescu 364*9371c9d4SSatish Balay static PetscErrorCode TSGLLECompleteStep_Rescale(TSGLLEScheme sc, PetscReal h, TSGLLEScheme next_sc, PetscReal next_h, Vec Ydot[], Vec Xold[], Vec X[]) { 3653d177a5cSEmil Constantinescu PetscScalar brow[32], vrow[32]; 3663d177a5cSEmil Constantinescu PetscInt i, j, r, s; 3673d177a5cSEmil Constantinescu 3683d177a5cSEmil Constantinescu PetscFunctionBegin; 3693d177a5cSEmil Constantinescu /* Build the new solution from (X,Ydot) */ 3703d177a5cSEmil Constantinescu r = sc->r; 3713d177a5cSEmil Constantinescu s = sc->s; 3723d177a5cSEmil Constantinescu for (i = 0; i < r; i++) { 3739566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(X[i])); 3743d177a5cSEmil Constantinescu for (j = 0; j < s; j++) brow[j] = h * sc->b[i * s + j]; 3759566063dSJacob Faibussowitsch PetscCall(VecMAXPY(X[i], s, brow, Ydot)); 3763d177a5cSEmil Constantinescu for (j = 0; j < r; j++) vrow[j] = sc->v[i * r + j]; 3779566063dSJacob Faibussowitsch PetscCall(VecMAXPY(X[i], r, vrow, Xold)); 3783d177a5cSEmil Constantinescu } 3793d177a5cSEmil Constantinescu PetscFunctionReturn(0); 3803d177a5cSEmil Constantinescu } 3813d177a5cSEmil Constantinescu 382*9371c9d4SSatish Balay static PetscErrorCode TSGLLECompleteStep_RescaleAndModify(TSGLLEScheme sc, PetscReal h, TSGLLEScheme next_sc, PetscReal next_h, Vec Ydot[], Vec Xold[], Vec X[]) { 3833d177a5cSEmil Constantinescu PetscScalar brow[32], vrow[32]; 3843d177a5cSEmil Constantinescu PetscReal ratio; 3853d177a5cSEmil Constantinescu PetscInt i, j, p, r, s; 3863d177a5cSEmil Constantinescu 3873d177a5cSEmil Constantinescu PetscFunctionBegin; 3883d177a5cSEmil Constantinescu /* Build the new solution from (X,Ydot) */ 3893d177a5cSEmil Constantinescu p = sc->p; 3903d177a5cSEmil Constantinescu r = sc->r; 3913d177a5cSEmil Constantinescu s = sc->s; 3923d177a5cSEmil Constantinescu ratio = next_h / h; 3933d177a5cSEmil Constantinescu for (i = 0; i < r; i++) { 3949566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(X[i])); 3953d177a5cSEmil Constantinescu for (j = 0; j < s; j++) { 396*9371c9d4SSatish Balay brow[j] = h * (PetscPowRealInt(ratio, i) * sc->b[i * s + j] + (PetscPowRealInt(ratio, i) - PetscPowRealInt(ratio, p + 1)) * (+sc->alpha[i] * sc->phi[0 * s + j]) + (PetscPowRealInt(ratio, i) - PetscPowRealInt(ratio, p + 2)) * (+sc->beta[i] * sc->phi[1 * s + j] + sc->gamma[i] * sc->phi[2 * s + j])); 3973d177a5cSEmil Constantinescu } 3989566063dSJacob Faibussowitsch PetscCall(VecMAXPY(X[i], s, brow, Ydot)); 3993d177a5cSEmil Constantinescu for (j = 0; j < r; j++) { 400*9371c9d4SSatish Balay vrow[j] = (PetscPowRealInt(ratio, i) * sc->v[i * r + j] + (PetscPowRealInt(ratio, i) - PetscPowRealInt(ratio, p + 1)) * (+sc->alpha[i] * sc->psi[0 * r + j]) + (PetscPowRealInt(ratio, i) - PetscPowRealInt(ratio, p + 2)) * (+sc->beta[i] * sc->psi[1 * r + j] + sc->gamma[i] * sc->psi[2 * r + j])); 4013d177a5cSEmil Constantinescu } 4029566063dSJacob Faibussowitsch PetscCall(VecMAXPY(X[i], r, vrow, Xold)); 4033d177a5cSEmil Constantinescu } 4043d177a5cSEmil Constantinescu if (r < next_sc->r) { 40508401ef6SPierre Jolivet PetscCheck(r + 1 == next_sc->r, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cannot accommodate jump in r greater than 1"); 4069566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(X[r])); 4073d177a5cSEmil Constantinescu for (j = 0; j < s; j++) brow[j] = h * PetscPowRealInt(ratio, p + 1) * sc->phi[0 * s + j]; 4089566063dSJacob Faibussowitsch PetscCall(VecMAXPY(X[r], s, brow, Ydot)); 4093d177a5cSEmil Constantinescu for (j = 0; j < r; j++) vrow[j] = PetscPowRealInt(ratio, p + 1) * sc->psi[0 * r + j]; 4109566063dSJacob Faibussowitsch PetscCall(VecMAXPY(X[r], r, vrow, Xold)); 4113d177a5cSEmil Constantinescu } 4123d177a5cSEmil Constantinescu PetscFunctionReturn(0); 4133d177a5cSEmil Constantinescu } 4143d177a5cSEmil Constantinescu 415*9371c9d4SSatish Balay static PetscErrorCode TSGLLECreate_IRKS(TS ts) { 4163d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 4173d177a5cSEmil Constantinescu 4183d177a5cSEmil Constantinescu PetscFunctionBegin; 4193d177a5cSEmil Constantinescu gl->Destroy = TSGLLEDestroy_Default; 4203d177a5cSEmil Constantinescu gl->EstimateHigherMoments = TSGLLEEstimateHigherMoments_Default; 4213d177a5cSEmil Constantinescu gl->CompleteStep = TSGLLECompleteStep_RescaleAndModify; 4229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(10, &gl->schemes)); 4233d177a5cSEmil Constantinescu gl->nschemes = 0; 4243d177a5cSEmil Constantinescu 4253d177a5cSEmil Constantinescu { 4263d177a5cSEmil Constantinescu /* p=1,q=1, r=s=2, A- and L-stable with error estimates of order 2 and 3 4273d177a5cSEmil Constantinescu * Listed in Butcher & Podhaisky 2006. On error estimation in general linear methods for stiff ODE. 4283d177a5cSEmil Constantinescu * irks(0.3,0,[.3,1],[1],1) 4293d177a5cSEmil Constantinescu * Note: can be made to have classical order (not stage order) 2 by replacing 0.3 with 1-sqrt(1/2) 4303d177a5cSEmil Constantinescu * but doing so would sacrifice the error estimator. 4313d177a5cSEmil Constantinescu */ 4323d177a5cSEmil Constantinescu const PetscScalar c[2] = {3. / 10., 1.}; 433*9371c9d4SSatish Balay const PetscScalar a[2][2] = { 434*9371c9d4SSatish Balay {3. / 10., 0 }, 435*9371c9d4SSatish Balay {7. / 10., 3. / 10.} 436*9371c9d4SSatish Balay }; 437*9371c9d4SSatish Balay const PetscScalar b[2][2] = { 438*9371c9d4SSatish Balay {7. / 10., 3. / 10.}, 439*9371c9d4SSatish Balay {0, 1 } 440*9371c9d4SSatish Balay }; 441*9371c9d4SSatish Balay const PetscScalar u[2][2] = { 442*9371c9d4SSatish Balay {1, 0}, 443*9371c9d4SSatish Balay {1, 0} 444*9371c9d4SSatish Balay }; 445*9371c9d4SSatish Balay const PetscScalar v[2][2] = { 446*9371c9d4SSatish Balay {1, 0}, 447*9371c9d4SSatish Balay {0, 0} 448*9371c9d4SSatish Balay }; 4499566063dSJacob Faibussowitsch PetscCall(TSGLLESchemeCreate(1, 1, 2, 2, c, *a, *b, *u, *v, &gl->schemes[gl->nschemes++])); 4503d177a5cSEmil Constantinescu } 4513d177a5cSEmil Constantinescu 4523d177a5cSEmil Constantinescu { 4533d177a5cSEmil Constantinescu /* p=q=2, r=s=3: irks(4/9,0,[1:3]/3,[0.33852],1) */ 4543d177a5cSEmil Constantinescu /* http://www.math.auckland.ac.nz/~hpod/atlas/i2a.html */ 455*9371c9d4SSatish Balay const PetscScalar c[3] = 456*9371c9d4SSatish Balay { 457*9371c9d4SSatish Balay 1. / 3., 2. / 3., 1 458*9371c9d4SSatish Balay }, 459*9371c9d4SSatish Balay a[3][3] = {{4. / 9., 0, 0}, {1.03750643704090e+00, 4. / 9., 0}, {7.67024779410304e-01, -3.81140216918943e-01, 4. / 9.}}, b[3][3] = {{0.767024779410304, -0.381140216918943, 4. / 9.}, {0.000000000000000, 0.000000000000000, 1.000000000000000}, {-2.075048385225385, 0.621728385225383, 1.277197204924873}}, u[3][3] = {{1.0000000000000000, -0.1111111111111109, -0.0925925925925922}, {1.0000000000000000, -0.8152842148186744, -0.4199095530877056}, {1.0000000000000000, 0.1696709930641948, 0.0539741070314165}}, v[3][3] = {{1.0000000000000000, 0.1696709930641948, 0.0539741070314165}, {0.000000000000000, 0.000000000000000, 0.000000000000000}, {0.000000000000000, 0.176122795075129, 0.000000000000000}}; 4609566063dSJacob Faibussowitsch PetscCall(TSGLLESchemeCreate(2, 2, 3, 3, c, *a, *b, *u, *v, &gl->schemes[gl->nschemes++])); 4613d177a5cSEmil Constantinescu } 4623d177a5cSEmil Constantinescu { 4633d177a5cSEmil Constantinescu /* p=q=3, r=s=4: irks(9/40,0,[1:4]/4,[0.3312 1.0050],[0.49541 1;1 0]) */ 464*9371c9d4SSatish Balay const PetscScalar c[4] = 465*9371c9d4SSatish Balay { 466*9371c9d4SSatish Balay 0.25, 0.5, 0.75, 1.0 467*9371c9d4SSatish Balay }, 468*9371c9d4SSatish Balay a[4][4] = {{9. / 40., 0, 0, 0}, {2.11286958887701e-01, 9. / 40., 0, 0}, {9.46338294287584e-01, -3.42942861246094e-01, 9. / 40., 0}, {0.521490453970721, -0.662474225622980, 0.490476425459734, 9. / 40.}}, b[4][4] = {{0.521490453970721, -0.662474225622980, 0.490476425459734, 9. / 40.}, {0.000000000000000, 0.000000000000000, 0.000000000000000, 1.000000000000000}, {-0.084677029310348, 1.390757514776085, -1.568157386206001, 2.023192696767826}, {0.465383797936408, 1.478273530625148, -1.930836081010182, 1.644872111193354}}, u[4][4] = {{1.00000000000000000, 0.02500000000001035, -0.02499999999999053, -0.00442708333332865}, {1.00000000000000000, 0.06371304111232945, -0.04032173972189845, -0.01389438413189452}, {1.00000000000000000, -0.07839543304147778, 0.04738685705116663, 0.02032603595928376}, {1.00000000000000000, 0.42550734619251651, 0.10800718022400080, -0.01726712647760034}}, v[4][4] = {{1.00000000000000000, 0.42550734619251651, 0.10800718022400080, -0.01726712647760034}, {0.000000000000000, 0.000000000000000, 0.000000000000000, 0.000000000000000}, {0.000000000000000, -1.761115796027561, -0.521284157173780, 0.258249384305463}, {0.000000000000000, -1.657693358744728, -1.052227765232394, 0.521284157173780}}; 4699566063dSJacob Faibussowitsch PetscCall(TSGLLESchemeCreate(3, 3, 4, 4, c, *a, *b, *u, *v, &gl->schemes[gl->nschemes++])); 4703d177a5cSEmil Constantinescu } 4713d177a5cSEmil Constantinescu { 4723d177a5cSEmil Constantinescu /* p=q=4, r=s=5: 4733d177a5cSEmil Constantinescu irks(3/11,0,[1:5]/5, [0.1715 -0.1238 0.6617],... 4743d177a5cSEmil Constantinescu [ -0.0812 0.4079 1.0000 4753d177a5cSEmil Constantinescu 1.0000 0 0 4763d177a5cSEmil Constantinescu 0.8270 1.0000 0]) 4773d177a5cSEmil Constantinescu */ 478*9371c9d4SSatish Balay const PetscScalar c[5] = 479*9371c9d4SSatish Balay { 480*9371c9d4SSatish Balay 0.2, 0.4, 0.6, 0.8, 1.0 481*9371c9d4SSatish Balay }, 482*9371c9d4SSatish Balay a[5][5] = {{2.72727272727352e-01, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00}, {-1.03980153733431e-01, 2.72727272727405e-01, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00}, {-1.58615400341492e+00, 7.44168951881122e-01, 2.72727272727309e-01, 0.00000000000000e+00, 0.00000000000000e+00}, {-8.73658042865628e-01, 5.37884671894595e-01, -1.63298538799523e-01, 2.72727272726996e-01, 0.00000000000000e+00}, {2.95489397443992e-01, -1.18481693910097e+00, -6.68029812659953e-01, 1.00716687860943e+00, 2.72727272727288e-01}}, b[5][5] = {{2.95489397443992e-01, -1.18481693910097e+00, -6.68029812659953e-01, 1.00716687860943e+00, 2.72727272727288e-01}, {0.00000000000000e+00, 1.11022302462516e-16, -2.22044604925031e-16, 0.00000000000000e+00, 1.00000000000000e+00}, {-4.05882503986005e+00, -4.00924006567769e+00, -1.38930610972481e+00, 4.45223930308488e+00, 6.32331093108427e-01}, {8.35690179937017e+00, -2.26640927349732e+00, 6.86647884973826e+00, -5.22595158025740e+00, 4.50893068837431e+00}, {1.27656267027479e+01, 2.80882153840821e+00, 8.91173096522890e+00, -1.07936444078906e+01, 4.82534148988854e+00}}, u[5][5] = {{1.00000000000000e+00, -7.27272727273551e-02, -3.45454545454419e-02, -4.12121212119565e-03, -2.96969696964014e-04}, {1.00000000000000e+00, 2.31252881006154e-01, -8.29487834416481e-03, -9.07191207681020e-03, -1.70378403743473e-03}, {1.00000000000000e+00, 1.16925777880663e+00, 3.59268562942635e-02, -4.09013451730615e-02, -1.02411119670164e-02}, {1.00000000000000e+00, 1.02634463704356e+00, 1.59375044913405e-01, 1.89673015035370e-03, -4.89987231897569e-03}, {1.00000000000000e+00, 1.27746320298021e+00, 2.37186008132728e-01, -8.28694373940065e-02, -5.34396510196430e-02}}, v[5][5] = {{1.00000000000000e+00, 1.27746320298021e+00, 2.37186008132728e-01, -8.28694373940065e-02, -5.34396510196430e-02}, {0.00000000000000e+00, -1.77635683940025e-15, -1.99840144432528e-15, -9.99200722162641e-16, -3.33066907387547e-16}, {0.00000000000000e+00, 4.37280081906924e+00, 5.49221645016377e-02, -8.88913177394943e-02, 1.12879077989154e-01}, {0.00000000000000e+00, -1.22399504837280e+01, -5.21287338448645e+00, -8.03952325565291e-01, 4.60298678047147e-01}, {0.00000000000000e+00, -1.85178762883829e+01, -5.21411849862624e+00, -1.04283436528809e+00, 7.49030161063651e-01}}; 4839566063dSJacob Faibussowitsch PetscCall(TSGLLESchemeCreate(4, 4, 5, 5, c, *a, *b, *u, *v, &gl->schemes[gl->nschemes++])); 4843d177a5cSEmil Constantinescu } 4853d177a5cSEmil Constantinescu { 4863d177a5cSEmil Constantinescu /* p=q=5, r=s=6; 4873d177a5cSEmil Constantinescu irks(1/3,0,[1:6]/6,... 4883d177a5cSEmil Constantinescu [-0.0489 0.4228 -0.8814 0.9021],... 4893d177a5cSEmil Constantinescu [-0.3474 -0.6617 0.6294 0.2129 4903d177a5cSEmil Constantinescu 0.0044 -0.4256 -0.1427 -0.8936 4913d177a5cSEmil Constantinescu -0.8267 0.4821 0.1371 -0.2557 4923d177a5cSEmil Constantinescu -0.4426 -0.3855 -0.7514 0.3014]) 4933d177a5cSEmil Constantinescu */ 494*9371c9d4SSatish Balay const PetscScalar c[6] = 495*9371c9d4SSatish Balay { 496*9371c9d4SSatish Balay 1. / 6, 2. / 6, 3. / 6, 4. / 6, 5. / 6, 1. 497*9371c9d4SSatish Balay }, 498*9371c9d4SSatish Balay a[6][6] = {{3.33333333333940e-01, 0, 0, 0, 0, 0}, {-8.64423857333350e-02, 3.33333333332888e-01, 0, 0, 0, 0}, {-2.16850174258252e+00, -2.23619072028839e+00, 3.33333333335204e-01, 0, 0, 0}, {-4.73160970138997e+00, -3.89265344629268e+00, -2.76318716520933e-01, 3.33333333335759e-01, 0, 0}, {-6.75187540297338e+00, -7.90756533769377e+00, 7.90245051802259e-01, -4.48352364517632e-01, 3.33333333328483e-01, 0}, {-4.26488287921548e+00, -1.19320395589302e+01, 3.38924509887755e+00, -2.23969848002481e+00, 6.62807710124007e-01, 3.33333333335440e-01}}, b[6][6] = {{-4.26488287921548e+00, -1.19320395589302e+01, 3.38924509887755e+00, -2.23969848002481e+00, 6.62807710124007e-01, 3.33333333335440e-01}, {-8.88178419700125e-16, 4.44089209850063e-16, -1.54737334057131e-15, -8.88178419700125e-16, 0.00000000000000e+00, 1.00000000000001e+00}, {-2.87780425770651e+01, -1.13520448264971e+01, 2.62002318943161e+01, 2.56943874812797e+01, -3.06702268304488e+01, 6.68067773510103e+00}, {5.47971245256474e+01, 6.80366875868284e+01, -6.50952588861999e+01, -8.28643975339097e+01, 8.17416943896414e+01, -1.17819043489036e+01}, {-2.33332114788869e+02, 6.12942539462634e+01, -4.91850135865944e+01, 1.82716844135480e+02, -1.29788173979395e+02, 3.09968095651099e+01}, {-1.72049132343751e+02, 8.60194713593999e+00, 7.98154219170200e-01, 1.50371386053218e+02, -1.18515423962066e+02, 2.50898277784663e+01}}, u[6][6] = {{1.00000000000000e+00, -1.66666666666870e-01, -4.16666666664335e-02, -3.85802469124815e-03, -2.25051440302250e-04, -9.64506172339142e-06}, {1.00000000000000e+00, 8.64423857327162e-02, -4.11484912671353e-02, -1.11450903217645e-02, -1.47651050487126e-03, -1.34395070766826e-04}, {1.00000000000000e+00, 4.57135912953434e+00, 1.06514719719137e+00, 1.33517564218007e-01, 1.11365952968659e-02, 6.12382756769504e-04}, {1.00000000000000e+00, 9.23391519753404e+00, 2.22431212392095e+00, 2.91823807741891e-01, 2.52058456411084e-02, 1.22800542949647e-03}, {1.00000000000000e+00, 1.48175480533865e+01, 3.73439117461835e+00, 5.14648336541804e-01, 4.76430038853402e-02, 2.56798515502156e-03}, {1.00000000000000e+00, 1.50512347758335e+01, 4.10099701165164e+00, 5.66039141003603e-01, 3.91213893800891e-02, -2.99136269067853e-03}}, v[6][6] = {{1.00000000000000e+00, 1.50512347758335e+01, 4.10099701165164e+00, 5.66039141003603e-01, 3.91213893800891e-02, -2.99136269067853e-03}, {0.00000000000000e+00, -4.88498130835069e-15, -6.43929354282591e-15, -3.55271367880050e-15, -1.22124532708767e-15, -3.12250225675825e-16}, {0.00000000000000e+00, 1.22250171233141e+01, -1.77150760606169e+00, 3.54516769879390e-01, 6.22298845883398e-01, 2.31647447450276e-01}, {0.00000000000000e+00, -4.48339457331040e+01, -3.57363126641880e-01, 5.18750173123425e-01, 6.55727990241799e-02, 1.63175368287079e-01}, {0.00000000000000e+00, 1.37297394708005e+02, -1.60145272991317e+00, -5.05319555199441e+00, 1.55328940390990e-01, 9.16629423682464e-01}, {0.00000000000000e+00, 1.05703241119022e+02, -1.16610260983038e+00, -2.99767252773859e+00, -1.13472315553890e-01, 1.09742849254729e+00}}; 4999566063dSJacob Faibussowitsch PetscCall(TSGLLESchemeCreate(5, 5, 6, 6, c, *a, *b, *u, *v, &gl->schemes[gl->nschemes++])); 5003d177a5cSEmil Constantinescu } 5013d177a5cSEmil Constantinescu PetscFunctionReturn(0); 5023d177a5cSEmil Constantinescu } 5033d177a5cSEmil Constantinescu 5043d177a5cSEmil Constantinescu /*@C 5053d177a5cSEmil Constantinescu TSGLLESetType - sets the class of general linear method to use for time-stepping 5063d177a5cSEmil Constantinescu 5073d177a5cSEmil Constantinescu Collective on TS 5083d177a5cSEmil Constantinescu 5093d177a5cSEmil Constantinescu Input Parameters: 5103d177a5cSEmil Constantinescu + ts - the TS context 5113d177a5cSEmil Constantinescu - type - a method 5123d177a5cSEmil Constantinescu 5133d177a5cSEmil Constantinescu Options Database Key: 5143d177a5cSEmil Constantinescu . -ts_gl_type <type> - sets the method, use -help for a list of available method (e.g. irks) 5153d177a5cSEmil Constantinescu 5163d177a5cSEmil Constantinescu Notes: 5173d177a5cSEmil Constantinescu See "petsc/include/petscts.h" for available methods (for instance) 5183d177a5cSEmil Constantinescu . TSGLLE_IRKS - Diagonally implicit methods with inherent Runge-Kutta stability (for stiff problems) 5193d177a5cSEmil Constantinescu 5203d177a5cSEmil Constantinescu Normally, it is best to use the TSSetFromOptions() command and 5213d177a5cSEmil Constantinescu then set the TSGLLE type from the options database rather than by using 5223d177a5cSEmil Constantinescu this routine. Using the options database provides the user with 5233d177a5cSEmil Constantinescu maximum flexibility in evaluating the many different solvers. 5243d177a5cSEmil Constantinescu The TSGLLESetType() routine is provided for those situations where it 5253d177a5cSEmil Constantinescu is necessary to set the timestepping solver independently of the 5263d177a5cSEmil Constantinescu command line or options database. This might be the case, for example, 5273d177a5cSEmil Constantinescu when the choice of solver changes during the execution of the 5283d177a5cSEmil Constantinescu program, and the user's application is taking responsibility for 5293d177a5cSEmil Constantinescu choosing the appropriate method. 5303d177a5cSEmil Constantinescu 5313d177a5cSEmil Constantinescu Level: intermediate 5323d177a5cSEmil Constantinescu 5333d177a5cSEmil Constantinescu @*/ 534*9371c9d4SSatish Balay PetscErrorCode TSGLLESetType(TS ts, TSGLLEType type) { 5353d177a5cSEmil Constantinescu PetscFunctionBegin; 5363d177a5cSEmil Constantinescu PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5373d177a5cSEmil Constantinescu PetscValidCharPointer(type, 2); 538cac4c232SBarry Smith PetscTryMethod(ts, "TSGLLESetType_C", (TS, TSGLLEType), (ts, type)); 5393d177a5cSEmil Constantinescu PetscFunctionReturn(0); 5403d177a5cSEmil Constantinescu } 5413d177a5cSEmil Constantinescu 5423d177a5cSEmil Constantinescu /*@C 5433d177a5cSEmil Constantinescu TSGLLESetAcceptType - sets the acceptance test 5443d177a5cSEmil Constantinescu 5453d177a5cSEmil Constantinescu Time integrators that need to control error must have the option to reject a time step based on local error 5463d177a5cSEmil Constantinescu estimates. This function allows different schemes to be set. 5473d177a5cSEmil Constantinescu 5483d177a5cSEmil Constantinescu Logically Collective on TS 5493d177a5cSEmil Constantinescu 5503d177a5cSEmil Constantinescu Input Parameters: 5513d177a5cSEmil Constantinescu + ts - the TS context 5523d177a5cSEmil Constantinescu - type - the type 5533d177a5cSEmil Constantinescu 5543d177a5cSEmil Constantinescu Options Database Key: 5553d177a5cSEmil Constantinescu . -ts_gl_accept_type <type> - sets the method used to determine whether to accept or reject a step 5563d177a5cSEmil Constantinescu 5573d177a5cSEmil Constantinescu Level: intermediate 5583d177a5cSEmil Constantinescu 559db781477SPatrick Sanan .seealso: `TS`, `TSGLLE`, `TSGLLEAcceptRegister()`, `TSGLLEAdapt`, `set` `type` 5603d177a5cSEmil Constantinescu @*/ 561*9371c9d4SSatish Balay PetscErrorCode TSGLLESetAcceptType(TS ts, TSGLLEAcceptType type) { 5623d177a5cSEmil Constantinescu PetscFunctionBegin; 5633d177a5cSEmil Constantinescu PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5643d177a5cSEmil Constantinescu PetscValidCharPointer(type, 2); 565cac4c232SBarry Smith PetscTryMethod(ts, "TSGLLESetAcceptType_C", (TS, TSGLLEAcceptType), (ts, type)); 5663d177a5cSEmil Constantinescu PetscFunctionReturn(0); 5673d177a5cSEmil Constantinescu } 5683d177a5cSEmil Constantinescu 5693d177a5cSEmil Constantinescu /*@C 5703d177a5cSEmil Constantinescu TSGLLEGetAdapt - gets the TSGLLEAdapt object from the TS 5713d177a5cSEmil Constantinescu 5723d177a5cSEmil Constantinescu Not Collective 5733d177a5cSEmil Constantinescu 5743d177a5cSEmil Constantinescu Input Parameter: 5753d177a5cSEmil Constantinescu . ts - the TS context 5763d177a5cSEmil Constantinescu 5773d177a5cSEmil Constantinescu Output Parameter: 5783d177a5cSEmil Constantinescu . adapt - the TSGLLEAdapt context 5793d177a5cSEmil Constantinescu 5803d177a5cSEmil Constantinescu Notes: 5813d177a5cSEmil Constantinescu This allows the user set options on the TSGLLEAdapt object. Usually it is better to do this using the options 5823d177a5cSEmil Constantinescu database, so this function is rarely needed. 5833d177a5cSEmil Constantinescu 5843d177a5cSEmil Constantinescu Level: advanced 5853d177a5cSEmil Constantinescu 586db781477SPatrick Sanan .seealso: `TSGLLEAdapt`, `TSGLLEAdaptRegister()` 5873d177a5cSEmil Constantinescu @*/ 588*9371c9d4SSatish Balay PetscErrorCode TSGLLEGetAdapt(TS ts, TSGLLEAdapt *adapt) { 5893d177a5cSEmil Constantinescu PetscFunctionBegin; 5903d177a5cSEmil Constantinescu PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5913d177a5cSEmil Constantinescu PetscValidPointer(adapt, 2); 592cac4c232SBarry Smith PetscUseMethod(ts, "TSGLLEGetAdapt_C", (TS, TSGLLEAdapt *), (ts, adapt)); 5933d177a5cSEmil Constantinescu PetscFunctionReturn(0); 5943d177a5cSEmil Constantinescu } 5953d177a5cSEmil Constantinescu 596*9371c9d4SSatish Balay static PetscErrorCode TSGLLEAccept_Always(TS ts, PetscReal tleft, PetscReal h, const PetscReal enorms[], PetscBool *accept) { 5973d177a5cSEmil Constantinescu PetscFunctionBegin; 5983d177a5cSEmil Constantinescu *accept = PETSC_TRUE; 5993d177a5cSEmil Constantinescu PetscFunctionReturn(0); 6003d177a5cSEmil Constantinescu } 6013d177a5cSEmil Constantinescu 602*9371c9d4SSatish Balay static PetscErrorCode TSGLLEUpdateWRMS(TS ts) { 6033d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 6043d177a5cSEmil Constantinescu PetscScalar *x, *w; 6053d177a5cSEmil Constantinescu PetscInt n, i; 6063d177a5cSEmil Constantinescu 6073d177a5cSEmil Constantinescu PetscFunctionBegin; 6089566063dSJacob Faibussowitsch PetscCall(VecGetArray(gl->X[0], &x)); 6099566063dSJacob Faibussowitsch PetscCall(VecGetArray(gl->W, &w)); 6109566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(gl->W, &n)); 6113d177a5cSEmil Constantinescu for (i = 0; i < n; i++) w[i] = 1. / (gl->wrms_atol + gl->wrms_rtol * PetscAbsScalar(x[i])); 6129566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(gl->X[0], &x)); 6139566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(gl->W, &w)); 6143d177a5cSEmil Constantinescu PetscFunctionReturn(0); 6153d177a5cSEmil Constantinescu } 6163d177a5cSEmil Constantinescu 617*9371c9d4SSatish Balay static PetscErrorCode TSGLLEVecNormWRMS(TS ts, Vec X, PetscReal *nrm) { 6183d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 6193d177a5cSEmil Constantinescu PetscScalar *x, *w; 6203d177a5cSEmil Constantinescu PetscReal sum = 0.0, gsum; 6213d177a5cSEmil Constantinescu PetscInt n, N, i; 6223d177a5cSEmil Constantinescu 6233d177a5cSEmil Constantinescu PetscFunctionBegin; 6249566063dSJacob Faibussowitsch PetscCall(VecGetArray(X, &x)); 6259566063dSJacob Faibussowitsch PetscCall(VecGetArray(gl->W, &w)); 6269566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(gl->W, &n)); 6273d177a5cSEmil Constantinescu for (i = 0; i < n; i++) sum += PetscAbsScalar(PetscSqr(x[i] * w[i])); 6289566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(X, &x)); 6299566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(gl->W, &w)); 6301c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&sum, &gsum, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)ts))); 6319566063dSJacob Faibussowitsch PetscCall(VecGetSize(gl->W, &N)); 6323d177a5cSEmil Constantinescu *nrm = PetscSqrtReal(gsum / (1. * N)); 6333d177a5cSEmil Constantinescu PetscFunctionReturn(0); 6343d177a5cSEmil Constantinescu } 6353d177a5cSEmil Constantinescu 636*9371c9d4SSatish Balay static PetscErrorCode TSGLLESetType_GLLE(TS ts, TSGLLEType type) { 6373d177a5cSEmil Constantinescu PetscBool same; 6383d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 6395f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(TS); 6403d177a5cSEmil Constantinescu 6413d177a5cSEmil Constantinescu PetscFunctionBegin; 6423d177a5cSEmil Constantinescu if (gl->type_name[0]) { 6439566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(gl->type_name, type, &same)); 6443d177a5cSEmil Constantinescu if (same) PetscFunctionReturn(0); 6459566063dSJacob Faibussowitsch PetscCall((*gl->Destroy)(gl)); 6463d177a5cSEmil Constantinescu } 6473d177a5cSEmil Constantinescu 6489566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(TSGLLEList, type, &r)); 6493c633725SBarry Smith PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown TSGLLE type \"%s\" given", type); 6509566063dSJacob Faibussowitsch PetscCall((*r)(ts)); 6519566063dSJacob Faibussowitsch PetscCall(PetscStrcpy(gl->type_name, type)); 6523d177a5cSEmil Constantinescu PetscFunctionReturn(0); 6533d177a5cSEmil Constantinescu } 6543d177a5cSEmil Constantinescu 655*9371c9d4SSatish Balay static PetscErrorCode TSGLLESetAcceptType_GLLE(TS ts, TSGLLEAcceptType type) { 6563d177a5cSEmil Constantinescu TSGLLEAcceptFunction r; 6573d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 6583d177a5cSEmil Constantinescu 6593d177a5cSEmil Constantinescu PetscFunctionBegin; 6609566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(TSGLLEAcceptList, type, &r)); 6613c633725SBarry Smith PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown TSGLLEAccept type \"%s\" given", type); 6623d177a5cSEmil Constantinescu gl->Accept = r; 6639566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(gl->accept_name, type, sizeof(gl->accept_name))); 6643d177a5cSEmil Constantinescu PetscFunctionReturn(0); 6653d177a5cSEmil Constantinescu } 6663d177a5cSEmil Constantinescu 667*9371c9d4SSatish Balay static PetscErrorCode TSGLLEGetAdapt_GLLE(TS ts, TSGLLEAdapt *adapt) { 6683d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 6693d177a5cSEmil Constantinescu 6703d177a5cSEmil Constantinescu PetscFunctionBegin; 6713d177a5cSEmil Constantinescu if (!gl->adapt) { 6729566063dSJacob Faibussowitsch PetscCall(TSGLLEAdaptCreate(PetscObjectComm((PetscObject)ts), &gl->adapt)); 6739566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)gl->adapt, (PetscObject)ts, 1)); 6749566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)ts, (PetscObject)gl->adapt)); 6753d177a5cSEmil Constantinescu } 6763d177a5cSEmil Constantinescu *adapt = gl->adapt; 6773d177a5cSEmil Constantinescu PetscFunctionReturn(0); 6783d177a5cSEmil Constantinescu } 6793d177a5cSEmil Constantinescu 680*9371c9d4SSatish Balay static PetscErrorCode TSGLLEChooseNextScheme(TS ts, PetscReal h, const PetscReal hmnorm[], PetscInt *next_scheme, PetscReal *next_h, PetscBool *finish) { 6813d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 6823d177a5cSEmil Constantinescu PetscInt i, n, cur_p, cur, next_sc, candidates[64], orders[64]; 6833d177a5cSEmil Constantinescu PetscReal errors[64], costs[64], tleft; 6843d177a5cSEmil Constantinescu 6853d177a5cSEmil Constantinescu PetscFunctionBegin; 6863d177a5cSEmil Constantinescu cur = -1; 6873d177a5cSEmil Constantinescu cur_p = gl->schemes[gl->current_scheme]->p; 6883d177a5cSEmil Constantinescu tleft = ts->max_time - (ts->ptime + ts->time_step); 6893d177a5cSEmil Constantinescu for (i = 0, n = 0; i < gl->nschemes; i++) { 6903d177a5cSEmil Constantinescu TSGLLEScheme sc = gl->schemes[i]; 6913d177a5cSEmil Constantinescu if (sc->p < gl->min_order || gl->max_order < sc->p) continue; 6923d177a5cSEmil Constantinescu if (sc->p == cur_p - 1) errors[n] = PetscAbsScalar(sc->alpha[0]) * hmnorm[0]; 6933d177a5cSEmil Constantinescu else if (sc->p == cur_p) errors[n] = PetscAbsScalar(sc->alpha[0]) * hmnorm[1]; 6943d177a5cSEmil Constantinescu else if (sc->p == cur_p + 1) errors[n] = PetscAbsScalar(sc->alpha[0]) * (hmnorm[2] + hmnorm[3]); 6953d177a5cSEmil Constantinescu else continue; 6963d177a5cSEmil Constantinescu candidates[n] = i; 6973d177a5cSEmil Constantinescu orders[n] = PetscMin(sc->p, sc->q); /* order of global truncation error */ 6983d177a5cSEmil Constantinescu costs[n] = sc->s; /* estimate the cost as the number of stages */ 6993d177a5cSEmil Constantinescu if (i == gl->current_scheme) cur = n; 7003d177a5cSEmil Constantinescu n++; 7013d177a5cSEmil Constantinescu } 702cad9d221SBarry Smith PetscCheck(cur >= 0 && gl->nschemes > cur, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Current scheme not found in scheme list"); 7039566063dSJacob Faibussowitsch PetscCall(TSGLLEAdaptChoose(gl->adapt, n, orders, errors, costs, cur, h, tleft, &next_sc, next_h, finish)); 7043d177a5cSEmil Constantinescu *next_scheme = candidates[next_sc]; 705*9371c9d4SSatish Balay PetscCall(PetscInfo(ts, "Adapt chose scheme %" PetscInt_FMT " (%" PetscInt_FMT ",%" PetscInt_FMT ",%" PetscInt_FMT ",%" PetscInt_FMT ") with step size %6.2e, finish=%s\n", *next_scheme, gl->schemes[*next_scheme]->p, gl->schemes[*next_scheme]->q, 706*9371c9d4SSatish Balay gl->schemes[*next_scheme]->r, gl->schemes[*next_scheme]->s, (double)*next_h, PetscBools[*finish])); 7073d177a5cSEmil Constantinescu PetscFunctionReturn(0); 7083d177a5cSEmil Constantinescu } 7093d177a5cSEmil Constantinescu 710*9371c9d4SSatish Balay static PetscErrorCode TSGLLEGetMaxSizes(TS ts, PetscInt *max_r, PetscInt *max_s) { 7113d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 7123d177a5cSEmil Constantinescu 7133d177a5cSEmil Constantinescu PetscFunctionBegin; 7143d177a5cSEmil Constantinescu *max_r = gl->schemes[gl->nschemes - 1]->r; 7153d177a5cSEmil Constantinescu *max_s = gl->schemes[gl->nschemes - 1]->s; 7163d177a5cSEmil Constantinescu PetscFunctionReturn(0); 7173d177a5cSEmil Constantinescu } 7183d177a5cSEmil Constantinescu 719*9371c9d4SSatish Balay static PetscErrorCode TSSolve_GLLE(TS ts) { 7203d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 7213d177a5cSEmil Constantinescu PetscInt i, k, its, lits, max_r, max_s; 7223d177a5cSEmil Constantinescu PetscBool final_step, finish; 7233d177a5cSEmil Constantinescu SNESConvergedReason snesreason; 7243d177a5cSEmil Constantinescu 7253d177a5cSEmil Constantinescu PetscFunctionBegin; 7269566063dSJacob Faibussowitsch PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol)); 7273d177a5cSEmil Constantinescu 7289566063dSJacob Faibussowitsch PetscCall(TSGLLEGetMaxSizes(ts, &max_r, &max_s)); 7299566063dSJacob Faibussowitsch PetscCall(VecCopy(ts->vec_sol, gl->X[0])); 730*9371c9d4SSatish Balay for (i = 1; i < max_r; i++) { PetscCall(VecZeroEntries(gl->X[i])); } 7319566063dSJacob Faibussowitsch PetscCall(TSGLLEUpdateWRMS(ts)); 7323d177a5cSEmil Constantinescu 7333d177a5cSEmil Constantinescu if (0) { 7343d177a5cSEmil Constantinescu /* Find consistent initial data for DAE */ 7353d177a5cSEmil Constantinescu gl->stage_time = ts->ptime + ts->time_step; 7363d177a5cSEmil Constantinescu gl->scoeff = 1.; 7373d177a5cSEmil Constantinescu gl->stage = 0; 7383d177a5cSEmil Constantinescu 7399566063dSJacob Faibussowitsch PetscCall(VecCopy(ts->vec_sol, gl->Z)); 7409566063dSJacob Faibussowitsch PetscCall(VecCopy(ts->vec_sol, gl->Y)); 7419566063dSJacob Faibussowitsch PetscCall(SNESSolve(ts->snes, NULL, gl->Y)); 7429566063dSJacob Faibussowitsch PetscCall(SNESGetIterationNumber(ts->snes, &its)); 7439566063dSJacob Faibussowitsch PetscCall(SNESGetLinearSolveIterations(ts->snes, &lits)); 7449566063dSJacob Faibussowitsch PetscCall(SNESGetConvergedReason(ts->snes, &snesreason)); 7453d177a5cSEmil Constantinescu 746*9371c9d4SSatish Balay ts->snes_its += its; 747*9371c9d4SSatish Balay ts->ksp_its += lits; 7483d177a5cSEmil Constantinescu if (snesreason < 0 && ts->max_snes_failures > 0 && ++ts->num_snes_failures >= ts->max_snes_failures) { 7493d177a5cSEmil Constantinescu ts->reason = TS_DIVERGED_NONLINEAR_SOLVE; 75063a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", nonlinear solve solve failures %" PetscInt_FMT " greater than current TS allowed, stopping solve\n", ts->steps, ts->num_snes_failures)); 7513d177a5cSEmil Constantinescu PetscFunctionReturn(0); 7523d177a5cSEmil Constantinescu } 7533d177a5cSEmil Constantinescu } 7543d177a5cSEmil Constantinescu 75508401ef6SPierre Jolivet PetscCheck(gl->current_scheme >= 0, PETSC_COMM_SELF, PETSC_ERR_ORDER, "A starting scheme has not been provided"); 7563d177a5cSEmil Constantinescu 7573d177a5cSEmil Constantinescu for (k = 0, final_step = PETSC_FALSE, finish = PETSC_FALSE; k < ts->max_steps && !finish; k++) { 7583d177a5cSEmil Constantinescu PetscInt j, r, s, next_scheme = 0, rejections; 7593d177a5cSEmil Constantinescu PetscReal h, hmnorm[4], enorm[3], next_h; 7603d177a5cSEmil Constantinescu PetscBool accept; 7613d177a5cSEmil Constantinescu const PetscScalar *c, *a, *u; 7623d177a5cSEmil Constantinescu Vec *X, *Ydot, Y; 7633d177a5cSEmil Constantinescu TSGLLEScheme scheme = gl->schemes[gl->current_scheme]; 7643d177a5cSEmil Constantinescu 765*9371c9d4SSatish Balay r = scheme->r; 766*9371c9d4SSatish Balay s = scheme->s; 7673d177a5cSEmil Constantinescu c = scheme->c; 768*9371c9d4SSatish Balay a = scheme->a; 769*9371c9d4SSatish Balay u = scheme->u; 7703d177a5cSEmil Constantinescu h = ts->time_step; 771*9371c9d4SSatish Balay X = gl->X; 772*9371c9d4SSatish Balay Ydot = gl->Ydot; 773*9371c9d4SSatish Balay Y = gl->Y; 7743d177a5cSEmil Constantinescu 7753d177a5cSEmil Constantinescu if (ts->ptime > ts->max_time) break; 7763d177a5cSEmil Constantinescu 7773d177a5cSEmil Constantinescu /* 7783d177a5cSEmil Constantinescu We only call PreStep at the start of each STEP, not each STAGE. This is because it is 7793d177a5cSEmil Constantinescu possible to fail (have to restart a step) after multiple stages. 7803d177a5cSEmil Constantinescu */ 7819566063dSJacob Faibussowitsch PetscCall(TSPreStep(ts)); 7823d177a5cSEmil Constantinescu 7833d177a5cSEmil Constantinescu rejections = 0; 7843d177a5cSEmil Constantinescu while (1) { 7853d177a5cSEmil Constantinescu for (i = 0; i < s; i++) { 7863d177a5cSEmil Constantinescu PetscScalar shift; 7873d177a5cSEmil Constantinescu gl->scoeff = 1. / PetscRealPart(a[i * s + i]); 7883d177a5cSEmil Constantinescu shift = gl->scoeff / ts->time_step; 7893d177a5cSEmil Constantinescu gl->stage = i; 7903d177a5cSEmil Constantinescu gl->stage_time = ts->ptime + PetscRealPart(c[i]) * h; 7913d177a5cSEmil Constantinescu 7923d177a5cSEmil Constantinescu /* 7933d177a5cSEmil Constantinescu * Stage equation: Y = h A Y' + U X 7943d177a5cSEmil Constantinescu * We assume that A is lower-triangular so that we can solve the stages (Y,Y') sequentially 7953d177a5cSEmil Constantinescu * Build the affine vector z_i = -[1/(h a_ii)](h sum_j a_ij y'_j + sum_j u_ij x_j) 7963d177a5cSEmil Constantinescu * Then y'_i = z + 1/(h a_ii) y_i 7973d177a5cSEmil Constantinescu */ 7989566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(gl->Z)); 799*9371c9d4SSatish Balay for (j = 0; j < r; j++) { PetscCall(VecAXPY(gl->Z, -shift * u[i * r + j], X[j])); } 800*9371c9d4SSatish Balay for (j = 0; j < i; j++) { PetscCall(VecAXPY(gl->Z, -shift * h * a[i * s + j], Ydot[j])); } 8013d177a5cSEmil Constantinescu /* Note: Z is used within function evaluation, Ydot = Z + shift*Y */ 8023d177a5cSEmil Constantinescu 8033d177a5cSEmil Constantinescu /* Compute an estimate of Y to start Newton iteration */ 8043d177a5cSEmil Constantinescu if (gl->extrapolate) { 8053d177a5cSEmil Constantinescu if (i == 0) { 8063d177a5cSEmil Constantinescu /* Linear extrapolation on the first stage */ 8079566063dSJacob Faibussowitsch PetscCall(VecWAXPY(Y, c[i] * h, X[1], X[0])); 8083d177a5cSEmil Constantinescu } else { 8093d177a5cSEmil Constantinescu /* Linear extrapolation from the last stage */ 8109566063dSJacob Faibussowitsch PetscCall(VecAXPY(Y, (c[i] - c[i - 1]) * h, Ydot[i - 1])); 8113d177a5cSEmil Constantinescu } 8123d177a5cSEmil Constantinescu } else if (i == 0) { /* Directly use solution from the last step, otherwise reuse the last stage (do nothing) */ 8139566063dSJacob Faibussowitsch PetscCall(VecCopy(X[0], Y)); 8143d177a5cSEmil Constantinescu } 8153d177a5cSEmil Constantinescu 8163d177a5cSEmil Constantinescu /* Solve this stage (Ydot[i] is computed during function evaluation) */ 8179566063dSJacob Faibussowitsch PetscCall(SNESSolve(ts->snes, NULL, Y)); 8189566063dSJacob Faibussowitsch PetscCall(SNESGetIterationNumber(ts->snes, &its)); 8199566063dSJacob Faibussowitsch PetscCall(SNESGetLinearSolveIterations(ts->snes, &lits)); 8209566063dSJacob Faibussowitsch PetscCall(SNESGetConvergedReason(ts->snes, &snesreason)); 821*9371c9d4SSatish Balay ts->snes_its += its; 822*9371c9d4SSatish Balay ts->ksp_its += lits; 8233d177a5cSEmil Constantinescu if (snesreason < 0 && ts->max_snes_failures > 0 && ++ts->num_snes_failures >= ts->max_snes_failures) { 8243d177a5cSEmil Constantinescu ts->reason = TS_DIVERGED_NONLINEAR_SOLVE; 82563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", nonlinear solve solve failures %" PetscInt_FMT " greater than current TS allowed, stopping solve\n", ts->steps, ts->num_snes_failures)); 8263d177a5cSEmil Constantinescu PetscFunctionReturn(0); 8273d177a5cSEmil Constantinescu } 8283d177a5cSEmil Constantinescu } 8293d177a5cSEmil Constantinescu 8303d177a5cSEmil Constantinescu gl->stage_time = ts->ptime + ts->time_step; 8313d177a5cSEmil Constantinescu 8329566063dSJacob Faibussowitsch PetscCall((*gl->EstimateHigherMoments)(scheme, h, Ydot, gl->X, gl->himom)); 8333d177a5cSEmil Constantinescu /* hmnorm[i] = h^{p+i}x^{(p+i)} with i=0,1,2; hmnorm[3] = h^{p+2}(dx'/dx) x^{(p+1)} */ 834*9371c9d4SSatish Balay for (i = 0; i < 3; i++) { PetscCall(TSGLLEVecNormWRMS(ts, gl->himom[i], &hmnorm[i + 1])); } 8353d177a5cSEmil Constantinescu enorm[0] = PetscRealPart(scheme->alpha[0]) * hmnorm[1]; 8363d177a5cSEmil Constantinescu enorm[1] = PetscRealPart(scheme->beta[0]) * hmnorm[2]; 8373d177a5cSEmil Constantinescu enorm[2] = PetscRealPart(scheme->gamma[0]) * hmnorm[3]; 8389566063dSJacob Faibussowitsch PetscCall((*gl->Accept)(ts, ts->max_time - gl->stage_time, h, enorm, &accept)); 8393d177a5cSEmil Constantinescu if (accept) goto accepted; 8403d177a5cSEmil Constantinescu rejections++; 84163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(ts, "Step %" PetscInt_FMT " (t=%g) not accepted, rejections=%" PetscInt_FMT "\n", k, (double)gl->stage_time, rejections)); 8423d177a5cSEmil Constantinescu if (rejections > gl->max_step_rejections) break; 8433d177a5cSEmil Constantinescu /* 8443d177a5cSEmil Constantinescu There are lots of reasons why a step might be rejected, including solvers not converging and other factors that 8453d177a5cSEmil Constantinescu TSGLLEChooseNextScheme does not support. Additionally, the error estimates may be very screwed up, so I'm not 8463d177a5cSEmil Constantinescu convinced that it's safe to just compute a new error estimate using the same interface as the current adaptor 8473d177a5cSEmil Constantinescu (the adaptor interface probably has to change). Here we make an arbitrary and naive choice. This assumes that 8483d177a5cSEmil Constantinescu steps were written in Nordsieck form. The "correct" method would be to re-complete the previous time step with 8493d177a5cSEmil Constantinescu the correct "next" step size. It is unclear to me whether the present ad-hoc method of rescaling X is stable. 8503d177a5cSEmil Constantinescu */ 8513d177a5cSEmil Constantinescu h *= 0.5; 852*9371c9d4SSatish Balay for (i = 1; i < scheme->r; i++) { PetscCall(VecScale(X[i], PetscPowRealInt(0.5, i))); } 8533d177a5cSEmil Constantinescu } 85463a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_CONV_FAILED, "Time step %" PetscInt_FMT " (t=%g) not accepted after %" PetscInt_FMT " failures", k, (double)gl->stage_time, rejections); 8553d177a5cSEmil Constantinescu 8563d177a5cSEmil Constantinescu accepted: 8573d177a5cSEmil Constantinescu /* This term is not error, but it *would* be the leading term for a lower order method */ 8589566063dSJacob Faibussowitsch PetscCall(TSGLLEVecNormWRMS(ts, gl->X[scheme->r - 1], &hmnorm[0])); 8593d177a5cSEmil Constantinescu /* Correct scaling so that these are equivalent to norms of the Nordsieck vectors */ 8603d177a5cSEmil Constantinescu 86163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(ts, "Last moment norm %10.2e, estimated error norms %10.2e %10.2e %10.2e\n", (double)hmnorm[0], (double)enorm[0], (double)enorm[1], (double)enorm[2])); 8623d177a5cSEmil Constantinescu if (!final_step) { 8639566063dSJacob Faibussowitsch PetscCall(TSGLLEChooseNextScheme(ts, h, hmnorm, &next_scheme, &next_h, &final_step)); 8643d177a5cSEmil Constantinescu } else { 8653d177a5cSEmil Constantinescu /* Dummy values to complete the current step in a consistent manner */ 8663d177a5cSEmil Constantinescu next_scheme = gl->current_scheme; 8673d177a5cSEmil Constantinescu next_h = h; 8683d177a5cSEmil Constantinescu finish = PETSC_TRUE; 8693d177a5cSEmil Constantinescu } 8703d177a5cSEmil Constantinescu 8713d177a5cSEmil Constantinescu X = gl->Xold; 8723d177a5cSEmil Constantinescu gl->Xold = gl->X; 8733d177a5cSEmil Constantinescu gl->X = X; 8749566063dSJacob Faibussowitsch PetscCall((*gl->CompleteStep)(scheme, h, gl->schemes[next_scheme], next_h, Ydot, gl->Xold, gl->X)); 8753d177a5cSEmil Constantinescu 8769566063dSJacob Faibussowitsch PetscCall(TSGLLEUpdateWRMS(ts)); 8773d177a5cSEmil Constantinescu 8783d177a5cSEmil Constantinescu /* Post the solution for the user, we could avoid this copy with a small bit of cleverness */ 8799566063dSJacob Faibussowitsch PetscCall(VecCopy(gl->X[0], ts->vec_sol)); 8803d177a5cSEmil Constantinescu ts->ptime += h; 8813d177a5cSEmil Constantinescu ts->steps++; 8823d177a5cSEmil Constantinescu 8839566063dSJacob Faibussowitsch PetscCall(TSPostEvaluate(ts)); 8849566063dSJacob Faibussowitsch PetscCall(TSPostStep(ts)); 8859566063dSJacob Faibussowitsch PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol)); 8863d177a5cSEmil Constantinescu 8873d177a5cSEmil Constantinescu gl->current_scheme = next_scheme; 8883d177a5cSEmil Constantinescu ts->time_step = next_h; 8893d177a5cSEmil Constantinescu } 8903d177a5cSEmil Constantinescu PetscFunctionReturn(0); 8913d177a5cSEmil Constantinescu } 8923d177a5cSEmil Constantinescu 8933d177a5cSEmil Constantinescu /*------------------------------------------------------------*/ 8943d177a5cSEmil Constantinescu 895*9371c9d4SSatish Balay static PetscErrorCode TSReset_GLLE(TS ts) { 8963d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 8973d177a5cSEmil Constantinescu PetscInt max_r, max_s; 8983d177a5cSEmil Constantinescu 8993d177a5cSEmil Constantinescu PetscFunctionBegin; 9003d177a5cSEmil Constantinescu if (gl->setupcalled) { 9019566063dSJacob Faibussowitsch PetscCall(TSGLLEGetMaxSizes(ts, &max_r, &max_s)); 9029566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(max_r, &gl->Xold)); 9039566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(max_r, &gl->X)); 9049566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(max_s, &gl->Ydot)); 9059566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(3, &gl->himom)); 9069566063dSJacob Faibussowitsch PetscCall(VecDestroy(&gl->W)); 9079566063dSJacob Faibussowitsch PetscCall(VecDestroy(&gl->Y)); 9089566063dSJacob Faibussowitsch PetscCall(VecDestroy(&gl->Z)); 9093d177a5cSEmil Constantinescu } 9103d177a5cSEmil Constantinescu gl->setupcalled = PETSC_FALSE; 9113d177a5cSEmil Constantinescu PetscFunctionReturn(0); 9123d177a5cSEmil Constantinescu } 9133d177a5cSEmil Constantinescu 914*9371c9d4SSatish Balay static PetscErrorCode TSDestroy_GLLE(TS ts) { 9153d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 9163d177a5cSEmil Constantinescu 9173d177a5cSEmil Constantinescu PetscFunctionBegin; 9189566063dSJacob Faibussowitsch PetscCall(TSReset_GLLE(ts)); 919b3a6b972SJed Brown if (ts->dm) { 9209566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookRemove(ts->dm, DMCoarsenHook_TSGLLE, DMRestrictHook_TSGLLE, ts)); 9219566063dSJacob Faibussowitsch PetscCall(DMSubDomainHookRemove(ts->dm, DMSubDomainHook_TSGLLE, DMSubDomainRestrictHook_TSGLLE, ts)); 922b3a6b972SJed Brown } 9239566063dSJacob Faibussowitsch if (gl->adapt) PetscCall(TSGLLEAdaptDestroy(&gl->adapt)); 9249566063dSJacob Faibussowitsch if (gl->Destroy) PetscCall((*gl->Destroy)(gl)); 9259566063dSJacob Faibussowitsch PetscCall(PetscFree(ts->data)); 9269566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSGLLESetType_C", NULL)); 9279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSGLLESetAcceptType_C", NULL)); 9289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSGLLEGetAdapt_C", NULL)); 9293d177a5cSEmil Constantinescu PetscFunctionReturn(0); 9303d177a5cSEmil Constantinescu } 9313d177a5cSEmil Constantinescu 9323d177a5cSEmil Constantinescu /* 9333d177a5cSEmil Constantinescu This defines the nonlinear equation that is to be solved with SNES 9343d177a5cSEmil Constantinescu g(x) = f(t,x,z+shift*x) = 0 9353d177a5cSEmil Constantinescu */ 936*9371c9d4SSatish Balay static PetscErrorCode SNESTSFormFunction_GLLE(SNES snes, Vec x, Vec f, TS ts) { 9373d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 9383d177a5cSEmil Constantinescu Vec Z, Ydot; 9393d177a5cSEmil Constantinescu DM dm, dmsave; 9403d177a5cSEmil Constantinescu 9413d177a5cSEmil Constantinescu PetscFunctionBegin; 9429566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 9439566063dSJacob Faibussowitsch PetscCall(TSGLLEGetVecs(ts, dm, &Z, &Ydot)); 9449566063dSJacob Faibussowitsch PetscCall(VecWAXPY(Ydot, gl->scoeff / ts->time_step, x, Z)); 9453d177a5cSEmil Constantinescu dmsave = ts->dm; 9463d177a5cSEmil Constantinescu ts->dm = dm; 9479566063dSJacob Faibussowitsch PetscCall(TSComputeIFunction(ts, gl->stage_time, x, Ydot, f, PETSC_FALSE)); 9483d177a5cSEmil Constantinescu ts->dm = dmsave; 9499566063dSJacob Faibussowitsch PetscCall(TSGLLERestoreVecs(ts, dm, &Z, &Ydot)); 9503d177a5cSEmil Constantinescu PetscFunctionReturn(0); 9513d177a5cSEmil Constantinescu } 9523d177a5cSEmil Constantinescu 953*9371c9d4SSatish Balay static PetscErrorCode SNESTSFormJacobian_GLLE(SNES snes, Vec x, Mat A, Mat B, TS ts) { 9543d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 9553d177a5cSEmil Constantinescu Vec Z, Ydot; 9563d177a5cSEmil Constantinescu DM dm, dmsave; 9573d177a5cSEmil Constantinescu 9583d177a5cSEmil Constantinescu PetscFunctionBegin; 9599566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 9609566063dSJacob Faibussowitsch PetscCall(TSGLLEGetVecs(ts, dm, &Z, &Ydot)); 9613d177a5cSEmil Constantinescu dmsave = ts->dm; 9623d177a5cSEmil Constantinescu ts->dm = dm; 9633d177a5cSEmil Constantinescu /* gl->Xdot will have already been computed in SNESTSFormFunction_GLLE */ 9649566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobian(ts, gl->stage_time, x, gl->Ydot[gl->stage], gl->scoeff / ts->time_step, A, B, PETSC_FALSE)); 9653d177a5cSEmil Constantinescu ts->dm = dmsave; 9669566063dSJacob Faibussowitsch PetscCall(TSGLLERestoreVecs(ts, dm, &Z, &Ydot)); 9673d177a5cSEmil Constantinescu PetscFunctionReturn(0); 9683d177a5cSEmil Constantinescu } 9693d177a5cSEmil Constantinescu 970*9371c9d4SSatish Balay static PetscErrorCode TSSetUp_GLLE(TS ts) { 9713d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 9723d177a5cSEmil Constantinescu PetscInt max_r, max_s; 9733d177a5cSEmil Constantinescu DM dm; 9743d177a5cSEmil Constantinescu 9753d177a5cSEmil Constantinescu PetscFunctionBegin; 9763d177a5cSEmil Constantinescu gl->setupcalled = PETSC_TRUE; 9779566063dSJacob Faibussowitsch PetscCall(TSGLLEGetMaxSizes(ts, &max_r, &max_s)); 9789566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vec_sol, max_r, &gl->X)); 9799566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vec_sol, max_r, &gl->Xold)); 9809566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vec_sol, max_s, &gl->Ydot)); 9819566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vec_sol, 3, &gl->himom)); 9829566063dSJacob Faibussowitsch PetscCall(VecDuplicate(ts->vec_sol, &gl->W)); 9839566063dSJacob Faibussowitsch PetscCall(VecDuplicate(ts->vec_sol, &gl->Y)); 9849566063dSJacob Faibussowitsch PetscCall(VecDuplicate(ts->vec_sol, &gl->Z)); 9853d177a5cSEmil Constantinescu 9863d177a5cSEmil Constantinescu /* Default acceptance tests and adaptivity */ 9879566063dSJacob Faibussowitsch if (!gl->Accept) PetscCall(TSGLLESetAcceptType(ts, TSGLLEACCEPT_ALWAYS)); 9889566063dSJacob Faibussowitsch if (!gl->adapt) PetscCall(TSGLLEGetAdapt(ts, &gl->adapt)); 9893d177a5cSEmil Constantinescu 9903d177a5cSEmil Constantinescu if (gl->current_scheme < 0) { 9913d177a5cSEmil Constantinescu PetscInt i; 9923d177a5cSEmil Constantinescu for (i = 0;; i++) { 9933d177a5cSEmil Constantinescu if (gl->schemes[i]->p == gl->start_order) break; 99463a3b9bcSJacob Faibussowitsch PetscCheck(i + 1 != gl->nschemes, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No schemes available with requested start order %" PetscInt_FMT, i); 9953d177a5cSEmil Constantinescu } 9963d177a5cSEmil Constantinescu gl->current_scheme = i; 9973d177a5cSEmil Constantinescu } 9989566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &dm)); 9999566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(dm, DMCoarsenHook_TSGLLE, DMRestrictHook_TSGLLE, ts)); 10009566063dSJacob Faibussowitsch PetscCall(DMSubDomainHookAdd(dm, DMSubDomainHook_TSGLLE, DMSubDomainRestrictHook_TSGLLE, ts)); 10013d177a5cSEmil Constantinescu PetscFunctionReturn(0); 10023d177a5cSEmil Constantinescu } 10033d177a5cSEmil Constantinescu /*------------------------------------------------------------*/ 10043d177a5cSEmil Constantinescu 1005*9371c9d4SSatish Balay static PetscErrorCode TSSetFromOptions_GLLE(TS ts, PetscOptionItems *PetscOptionsObject) { 10063d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 10073d177a5cSEmil Constantinescu char tname[256] = TSGLLE_IRKS, completef[256] = "rescale-and-modify"; 10083d177a5cSEmil Constantinescu 10093d177a5cSEmil Constantinescu PetscFunctionBegin; 1010d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "General Linear ODE solver options"); 10113d177a5cSEmil Constantinescu { 10123d177a5cSEmil Constantinescu PetscBool flg; 10139566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-ts_gl_type", "Type of GL method", "TSGLLESetType", TSGLLEList, gl->type_name[0] ? gl->type_name : tname, tname, sizeof(tname), &flg)); 1014*9371c9d4SSatish Balay if (flg || !gl->type_name[0]) { PetscCall(TSGLLESetType(ts, tname)); } 10159566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-ts_gl_max_step_rejections", "Maximum number of times to attempt a step", "None", gl->max_step_rejections, &gl->max_step_rejections, NULL)); 10169566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-ts_gl_max_order", "Maximum order to try", "TSGLLESetMaxOrder", gl->max_order, &gl->max_order, NULL)); 10179566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-ts_gl_min_order", "Minimum order to try", "TSGLLESetMinOrder", gl->min_order, &gl->min_order, NULL)); 10189566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-ts_gl_start_order", "Initial order to try", "TSGLLESetMinOrder", gl->start_order, &gl->start_order, NULL)); 10199566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-ts_gl_error_direction", "Which direction to look when estimating error", "TSGLLESetErrorDirection", TSGLLEErrorDirections, (PetscEnum)gl->error_direction, (PetscEnum *)&gl->error_direction, NULL)); 10209566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-ts_gl_extrapolate", "Extrapolate stage solution from previous solution (sometimes unstable)", "TSGLLESetExtrapolate", gl->extrapolate, &gl->extrapolate, NULL)); 10219566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-ts_gl_atol", "Absolute tolerance", "TSGLLESetTolerances", gl->wrms_atol, &gl->wrms_atol, NULL)); 10229566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-ts_gl_rtol", "Relative tolerance", "TSGLLESetTolerances", gl->wrms_rtol, &gl->wrms_rtol, NULL)); 10239566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-ts_gl_complete", "Method to use for completing the step", "none", completef, completef, sizeof(completef), &flg)); 10243d177a5cSEmil Constantinescu if (flg) { 10253d177a5cSEmil Constantinescu PetscBool match1, match2; 10269566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(completef, "rescale", &match1)); 10279566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(completef, "rescale-and-modify", &match2)); 10283d177a5cSEmil Constantinescu if (match1) gl->CompleteStep = TSGLLECompleteStep_Rescale; 10293d177a5cSEmil Constantinescu else if (match2) gl->CompleteStep = TSGLLECompleteStep_RescaleAndModify; 103098921bdaSJacob Faibussowitsch else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "%s", completef); 10313d177a5cSEmil Constantinescu } 10323d177a5cSEmil Constantinescu { 10333d177a5cSEmil Constantinescu char type[256] = TSGLLEACCEPT_ALWAYS; 10349566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-ts_gl_accept_type", "Method to use for determining whether to accept a step", "TSGLLESetAcceptType", TSGLLEAcceptList, gl->accept_name[0] ? gl->accept_name : type, type, sizeof(type), &flg)); 1035*9371c9d4SSatish Balay if (flg || !gl->accept_name[0]) { PetscCall(TSGLLESetAcceptType(ts, type)); } 10363d177a5cSEmil Constantinescu } 10373d177a5cSEmil Constantinescu { 10383d177a5cSEmil Constantinescu TSGLLEAdapt adapt; 10399566063dSJacob Faibussowitsch PetscCall(TSGLLEGetAdapt(ts, &adapt)); 1040dbbe0bcdSBarry Smith PetscCall(TSGLLEAdaptSetFromOptions(adapt, PetscOptionsObject)); 10413d177a5cSEmil Constantinescu } 10423d177a5cSEmil Constantinescu } 1043d0609cedSBarry Smith PetscOptionsHeadEnd(); 10443d177a5cSEmil Constantinescu PetscFunctionReturn(0); 10453d177a5cSEmil Constantinescu } 10463d177a5cSEmil Constantinescu 1047*9371c9d4SSatish Balay static PetscErrorCode TSView_GLLE(TS ts, PetscViewer viewer) { 10483d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 10493d177a5cSEmil Constantinescu PetscInt i; 10503d177a5cSEmil Constantinescu PetscBool iascii, details; 10513d177a5cSEmil Constantinescu 10523d177a5cSEmil Constantinescu PetscFunctionBegin; 10539566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 10543d177a5cSEmil Constantinescu if (iascii) { 105563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " min order %" PetscInt_FMT ", max order %" PetscInt_FMT ", current order %" PetscInt_FMT "\n", gl->min_order, gl->max_order, gl->schemes[gl->current_scheme]->p)); 10569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Error estimation: %s\n", TSGLLEErrorDirections[gl->error_direction])); 10579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Extrapolation: %s\n", gl->extrapolate ? "yes" : "no")); 10589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Acceptance test: %s\n", gl->accept_name[0] ? gl->accept_name : "(not yet set)")); 10599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 10609566063dSJacob Faibussowitsch PetscCall(TSGLLEAdaptView(gl->adapt, viewer)); 10619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 10629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " type: %s\n", gl->type_name[0] ? gl->type_name : "(not yet set)")); 106363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Schemes within family (%" PetscInt_FMT "):\n", gl->nschemes)); 10643d177a5cSEmil Constantinescu details = PETSC_FALSE; 10659566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_gl_view_detailed", &details, NULL)); 10669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 1067*9371c9d4SSatish Balay for (i = 0; i < gl->nschemes; i++) { PetscCall(TSGLLESchemeView(gl->schemes[i], details, viewer)); } 10681baa6e33SBarry Smith if (gl->View) PetscCall((*gl->View)(gl, viewer)); 10699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 10703d177a5cSEmil Constantinescu } 10713d177a5cSEmil Constantinescu PetscFunctionReturn(0); 10723d177a5cSEmil Constantinescu } 10733d177a5cSEmil Constantinescu 10743d177a5cSEmil Constantinescu /*@C 10753d177a5cSEmil Constantinescu TSGLLERegister - adds a TSGLLE implementation 10763d177a5cSEmil Constantinescu 10773d177a5cSEmil Constantinescu Not Collective 10783d177a5cSEmil Constantinescu 10793d177a5cSEmil Constantinescu Input Parameters: 10803d177a5cSEmil Constantinescu + name_scheme - name of user-defined general linear scheme 10813d177a5cSEmil Constantinescu - routine_create - routine to create method context 10823d177a5cSEmil Constantinescu 10833d177a5cSEmil Constantinescu Notes: 10843d177a5cSEmil Constantinescu TSGLLERegister() may be called multiple times to add several user-defined families. 10853d177a5cSEmil Constantinescu 10863d177a5cSEmil Constantinescu Sample usage: 10873d177a5cSEmil Constantinescu .vb 10883d177a5cSEmil Constantinescu TSGLLERegister("my_scheme",MySchemeCreate); 10893d177a5cSEmil Constantinescu .ve 10903d177a5cSEmil Constantinescu 10913d177a5cSEmil Constantinescu Then, your scheme can be chosen with the procedural interface via 10923d177a5cSEmil Constantinescu $ TSGLLESetType(ts,"my_scheme") 10933d177a5cSEmil Constantinescu or at runtime via the option 10943d177a5cSEmil Constantinescu $ -ts_gl_type my_scheme 10953d177a5cSEmil Constantinescu 10963d177a5cSEmil Constantinescu Level: advanced 10973d177a5cSEmil Constantinescu 1098db781477SPatrick Sanan .seealso: `TSGLLERegisterAll()` 10993d177a5cSEmil Constantinescu @*/ 1100*9371c9d4SSatish Balay PetscErrorCode TSGLLERegister(const char sname[], PetscErrorCode (*function)(TS)) { 11013d177a5cSEmil Constantinescu PetscFunctionBegin; 11029566063dSJacob Faibussowitsch PetscCall(TSGLLEInitializePackage()); 11039566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&TSGLLEList, sname, function)); 11043d177a5cSEmil Constantinescu PetscFunctionReturn(0); 11053d177a5cSEmil Constantinescu } 11063d177a5cSEmil Constantinescu 11073d177a5cSEmil Constantinescu /*@C 11083d177a5cSEmil Constantinescu TSGLLEAcceptRegister - adds a TSGLLE acceptance scheme 11093d177a5cSEmil Constantinescu 11103d177a5cSEmil Constantinescu Not Collective 11113d177a5cSEmil Constantinescu 11123d177a5cSEmil Constantinescu Input Parameters: 11133d177a5cSEmil Constantinescu + name_scheme - name of user-defined acceptance scheme 11143d177a5cSEmil Constantinescu - routine_create - routine to create method context 11153d177a5cSEmil Constantinescu 11163d177a5cSEmil Constantinescu Notes: 11173d177a5cSEmil Constantinescu TSGLLEAcceptRegister() may be called multiple times to add several user-defined families. 11183d177a5cSEmil Constantinescu 11193d177a5cSEmil Constantinescu Sample usage: 11203d177a5cSEmil Constantinescu .vb 11213d177a5cSEmil Constantinescu TSGLLEAcceptRegister("my_scheme",MySchemeCreate); 11223d177a5cSEmil Constantinescu .ve 11233d177a5cSEmil Constantinescu 11243d177a5cSEmil Constantinescu Then, your scheme can be chosen with the procedural interface via 11253d177a5cSEmil Constantinescu $ TSGLLESetAcceptType(ts,"my_scheme") 11263d177a5cSEmil Constantinescu or at runtime via the option 11273d177a5cSEmil Constantinescu $ -ts_gl_accept_type my_scheme 11283d177a5cSEmil Constantinescu 11293d177a5cSEmil Constantinescu Level: advanced 11303d177a5cSEmil Constantinescu 1131db781477SPatrick Sanan .seealso: `TSGLLERegisterAll()` 11323d177a5cSEmil Constantinescu @*/ 1133*9371c9d4SSatish Balay PetscErrorCode TSGLLEAcceptRegister(const char sname[], TSGLLEAcceptFunction function) { 11343d177a5cSEmil Constantinescu PetscFunctionBegin; 11359566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&TSGLLEAcceptList, sname, function)); 11363d177a5cSEmil Constantinescu PetscFunctionReturn(0); 11373d177a5cSEmil Constantinescu } 11383d177a5cSEmil Constantinescu 11393d177a5cSEmil Constantinescu /*@C 11403d177a5cSEmil Constantinescu TSGLLERegisterAll - Registers all of the general linear methods in TSGLLE 11413d177a5cSEmil Constantinescu 11423d177a5cSEmil Constantinescu Not Collective 11433d177a5cSEmil Constantinescu 11443d177a5cSEmil Constantinescu Level: advanced 11453d177a5cSEmil Constantinescu 1146db781477SPatrick Sanan .seealso: `TSGLLERegisterDestroy()` 11473d177a5cSEmil Constantinescu @*/ 1148*9371c9d4SSatish Balay PetscErrorCode TSGLLERegisterAll(void) { 11493d177a5cSEmil Constantinescu PetscFunctionBegin; 11503d177a5cSEmil Constantinescu if (TSGLLERegisterAllCalled) PetscFunctionReturn(0); 11513d177a5cSEmil Constantinescu TSGLLERegisterAllCalled = PETSC_TRUE; 11523d177a5cSEmil Constantinescu 11539566063dSJacob Faibussowitsch PetscCall(TSGLLERegister(TSGLLE_IRKS, TSGLLECreate_IRKS)); 11549566063dSJacob Faibussowitsch PetscCall(TSGLLEAcceptRegister(TSGLLEACCEPT_ALWAYS, TSGLLEAccept_Always)); 11553d177a5cSEmil Constantinescu PetscFunctionReturn(0); 11563d177a5cSEmil Constantinescu } 11573d177a5cSEmil Constantinescu 11583d177a5cSEmil Constantinescu /*@C 11593d177a5cSEmil Constantinescu TSGLLEInitializePackage - This function initializes everything in the TSGLLE package. It is called 11608a690491SBarry Smith from TSInitializePackage(). 11613d177a5cSEmil Constantinescu 11623d177a5cSEmil Constantinescu Level: developer 11633d177a5cSEmil Constantinescu 1164db781477SPatrick Sanan .seealso: `PetscInitialize()` 11653d177a5cSEmil Constantinescu @*/ 1166*9371c9d4SSatish Balay PetscErrorCode TSGLLEInitializePackage(void) { 11673d177a5cSEmil Constantinescu PetscFunctionBegin; 11683d177a5cSEmil Constantinescu if (TSGLLEPackageInitialized) PetscFunctionReturn(0); 11693d177a5cSEmil Constantinescu TSGLLEPackageInitialized = PETSC_TRUE; 11709566063dSJacob Faibussowitsch PetscCall(TSGLLERegisterAll()); 11719566063dSJacob Faibussowitsch PetscCall(PetscRegisterFinalize(TSGLLEFinalizePackage)); 11723d177a5cSEmil Constantinescu PetscFunctionReturn(0); 11733d177a5cSEmil Constantinescu } 11743d177a5cSEmil Constantinescu 11753d177a5cSEmil Constantinescu /*@C 11763d177a5cSEmil Constantinescu TSGLLEFinalizePackage - This function destroys everything in the TSGLLE package. It is 11773d177a5cSEmil Constantinescu called from PetscFinalize(). 11783d177a5cSEmil Constantinescu 11793d177a5cSEmil Constantinescu Level: developer 11803d177a5cSEmil Constantinescu 1181db781477SPatrick Sanan .seealso: `PetscFinalize()` 11823d177a5cSEmil Constantinescu @*/ 1183*9371c9d4SSatish Balay PetscErrorCode TSGLLEFinalizePackage(void) { 11843d177a5cSEmil Constantinescu PetscFunctionBegin; 11859566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDestroy(&TSGLLEList)); 11869566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDestroy(&TSGLLEAcceptList)); 11873d177a5cSEmil Constantinescu TSGLLEPackageInitialized = PETSC_FALSE; 11883d177a5cSEmil Constantinescu TSGLLERegisterAllCalled = PETSC_FALSE; 11893d177a5cSEmil Constantinescu PetscFunctionReturn(0); 11903d177a5cSEmil Constantinescu } 11913d177a5cSEmil Constantinescu 11923d177a5cSEmil Constantinescu /* ------------------------------------------------------------ */ 11933d177a5cSEmil Constantinescu /*MC 11943d177a5cSEmil Constantinescu TSGLLE - DAE solver using implicit General Linear methods 11953d177a5cSEmil Constantinescu 11963d177a5cSEmil Constantinescu These methods contain Runge-Kutta and multistep schemes as special cases. These special cases have some fundamental 11973d177a5cSEmil Constantinescu limitations. For example, diagonally implicit Runge-Kutta cannot have stage order greater than 1 which limits their 11983d177a5cSEmil Constantinescu applicability to very stiff systems. Meanwhile, multistep methods cannot be A-stable for order greater than 2 and BDF 11993d177a5cSEmil Constantinescu are not 0-stable for order greater than 6. GL methods can be A- and L-stable with arbitrarily high stage order and 12003d177a5cSEmil Constantinescu reliable error estimates for both 1 and 2 orders higher to facilitate adaptive step sizes and adaptive order schemes. 12013d177a5cSEmil Constantinescu All this is possible while preserving a singly diagonally implicit structure. 12023d177a5cSEmil Constantinescu 12033d177a5cSEmil Constantinescu Options database keys: 12043d177a5cSEmil Constantinescu + -ts_gl_type <type> - the class of general linear method (irks) 12053d177a5cSEmil Constantinescu . -ts_gl_rtol <tol> - relative error 12063d177a5cSEmil Constantinescu . -ts_gl_atol <tol> - absolute error 12073d177a5cSEmil Constantinescu . -ts_gl_min_order <p> - minimum order method to consider (default=1) 12083d177a5cSEmil Constantinescu . -ts_gl_max_order <p> - maximum order method to consider (default=3) 12093d177a5cSEmil Constantinescu . -ts_gl_start_order <p> - order of starting method (default=1) 12103d177a5cSEmil Constantinescu . -ts_gl_complete <method> - method to use for completing the step (rescale-and-modify or rescale) 12113d177a5cSEmil Constantinescu - -ts_adapt_type <method> - adaptive controller to use (none step both) 12123d177a5cSEmil Constantinescu 12133d177a5cSEmil Constantinescu Notes: 12143d177a5cSEmil Constantinescu This integrator can be applied to DAE. 12153d177a5cSEmil Constantinescu 12163d177a5cSEmil Constantinescu Diagonally implicit general linear (DIGL) methods are a generalization of diagonally implicit Runge-Kutta (DIRK). 12173d177a5cSEmil Constantinescu They are represented by the tableau 12183d177a5cSEmil Constantinescu 12193d177a5cSEmil Constantinescu .vb 12203d177a5cSEmil Constantinescu A | U 12213d177a5cSEmil Constantinescu ------- 12223d177a5cSEmil Constantinescu B | V 12233d177a5cSEmil Constantinescu .ve 12243d177a5cSEmil Constantinescu 12253d177a5cSEmil Constantinescu combined with a vector c of abscissa. "Diagonally implicit" means that A is lower triangular. 12263d177a5cSEmil Constantinescu A step of the general method reads 12273d177a5cSEmil Constantinescu 12283d177a5cSEmil Constantinescu .vb 12293d177a5cSEmil Constantinescu [ Y ] = [A U] [ Y' ] 12303d177a5cSEmil Constantinescu [X^k] = [B V] [X^{k-1}] 12313d177a5cSEmil Constantinescu .ve 12323d177a5cSEmil Constantinescu 12333d177a5cSEmil Constantinescu where Y is the multivector of stage values, Y' is the multivector of stage derivatives, X^k is the Nordsieck vector of 12343d177a5cSEmil Constantinescu the solution at step k. The Nordsieck vector consists of the first r moments of the solution, given by 12353d177a5cSEmil Constantinescu 12363d177a5cSEmil Constantinescu .vb 12373d177a5cSEmil Constantinescu X = [x_0,x_1,...,x_{r-1}] = [x, h x', h^2 x'', ..., h^{r-1} x^{(r-1)} ] 12383d177a5cSEmil Constantinescu .ve 12393d177a5cSEmil Constantinescu 12403d177a5cSEmil Constantinescu If A is lower triangular, we can solve the stages (Y,Y') sequentially 12413d177a5cSEmil Constantinescu 12423d177a5cSEmil Constantinescu .vb 12433d177a5cSEmil Constantinescu y_i = h sum_{j=0}^{s-1} (a_ij y'_j) + sum_{j=0}^{r-1} u_ij x_j, i=0,...,{s-1} 12443d177a5cSEmil Constantinescu .ve 12453d177a5cSEmil Constantinescu 12463d177a5cSEmil Constantinescu and then construct the pieces to carry to the next step 12473d177a5cSEmil Constantinescu 12483d177a5cSEmil Constantinescu .vb 12493d177a5cSEmil Constantinescu xx_i = h sum_{j=0}^{s-1} b_ij y'_j + sum_{j=0}^{r-1} v_ij x_j, i=0,...,{r-1} 12503d177a5cSEmil Constantinescu .ve 12513d177a5cSEmil Constantinescu 12523d177a5cSEmil Constantinescu Note that when the equations are cast in implicit form, we are using the stage equation to define y'_i 12533d177a5cSEmil Constantinescu in terms of y_i and known stuff (y_j for j<i and x_j for all j). 12543d177a5cSEmil Constantinescu 12553d177a5cSEmil Constantinescu Error estimation 12563d177a5cSEmil Constantinescu 12573d177a5cSEmil Constantinescu At present, the most attractive GL methods for stiff problems are singly diagonally implicit schemes which posses 12583d177a5cSEmil Constantinescu Inherent Runge-Kutta Stability (IRKS). These methods have r=s, the number of items passed between steps is equal to 12593d177a5cSEmil Constantinescu the number of stages. The order and stage-order are one less than the number of stages. We use the error estimates 12603d177a5cSEmil Constantinescu in the 2007 paper which provide the following estimates 12613d177a5cSEmil Constantinescu 12623d177a5cSEmil Constantinescu .vb 12633d177a5cSEmil Constantinescu h^{p+1} X^{(p+1)} = phi_0^T Y' + [0 psi_0^T] Xold 12643d177a5cSEmil Constantinescu h^{p+2} X^{(p+2)} = phi_1^T Y' + [0 psi_1^T] Xold 12653d177a5cSEmil Constantinescu h^{p+2} (dx'/dx) X^{(p+1)} = phi_2^T Y' + [0 psi_2^T] Xold 12663d177a5cSEmil Constantinescu .ve 12673d177a5cSEmil Constantinescu 12683d177a5cSEmil Constantinescu These estimates are accurate to O(h^{p+3}). 12693d177a5cSEmil Constantinescu 12703d177a5cSEmil Constantinescu Changing the step size 12713d177a5cSEmil Constantinescu 12723d177a5cSEmil Constantinescu We use the generalized "rescale and modify" scheme, see equation (4.5) of the 2007 paper. 12733d177a5cSEmil Constantinescu 12743d177a5cSEmil Constantinescu Level: beginner 12753d177a5cSEmil Constantinescu 12763d177a5cSEmil Constantinescu References: 1277606c0280SSatish Balay + * - John Butcher and Z. Jackieweicz and W. Wright, On error propagation in general linear methods for 12783d177a5cSEmil Constantinescu ordinary differential equations, Journal of Complexity, Vol 23, 2007. 1279606c0280SSatish Balay - * - John Butcher, Numerical methods for ordinary differential equations, second edition, Wiley, 2009. 12803d177a5cSEmil Constantinescu 1281db781477SPatrick Sanan .seealso: `TSCreate()`, `TS`, `TSSetType()` 12823d177a5cSEmil Constantinescu 12833d177a5cSEmil Constantinescu M*/ 1284*9371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode TSCreate_GLLE(TS ts) { 12853d177a5cSEmil Constantinescu TS_GLLE *gl; 12863d177a5cSEmil Constantinescu 12873d177a5cSEmil Constantinescu PetscFunctionBegin; 12889566063dSJacob Faibussowitsch PetscCall(TSGLLEInitializePackage()); 12893d177a5cSEmil Constantinescu 12909566063dSJacob Faibussowitsch PetscCall(PetscNewLog(ts, &gl)); 12913d177a5cSEmil Constantinescu ts->data = (void *)gl; 12923d177a5cSEmil Constantinescu 12933d177a5cSEmil Constantinescu ts->ops->reset = TSReset_GLLE; 12943d177a5cSEmil Constantinescu ts->ops->destroy = TSDestroy_GLLE; 12953d177a5cSEmil Constantinescu ts->ops->view = TSView_GLLE; 12963d177a5cSEmil Constantinescu ts->ops->setup = TSSetUp_GLLE; 12973d177a5cSEmil Constantinescu ts->ops->solve = TSSolve_GLLE; 12983d177a5cSEmil Constantinescu ts->ops->setfromoptions = TSSetFromOptions_GLLE; 12993d177a5cSEmil Constantinescu ts->ops->snesfunction = SNESTSFormFunction_GLLE; 13003d177a5cSEmil Constantinescu ts->ops->snesjacobian = SNESTSFormJacobian_GLLE; 13013d177a5cSEmil Constantinescu 1302efd4aadfSBarry Smith ts->usessnes = PETSC_TRUE; 1303efd4aadfSBarry Smith 13043d177a5cSEmil Constantinescu gl->max_step_rejections = 1; 13053d177a5cSEmil Constantinescu gl->min_order = 1; 13063d177a5cSEmil Constantinescu gl->max_order = 3; 13073d177a5cSEmil Constantinescu gl->start_order = 1; 13083d177a5cSEmil Constantinescu gl->current_scheme = -1; 13093d177a5cSEmil Constantinescu gl->extrapolate = PETSC_FALSE; 13103d177a5cSEmil Constantinescu 13113d177a5cSEmil Constantinescu gl->wrms_atol = 1e-8; 13123d177a5cSEmil Constantinescu gl->wrms_rtol = 1e-5; 13133d177a5cSEmil Constantinescu 13149566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSGLLESetType_C", &TSGLLESetType_GLLE)); 13159566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSGLLESetAcceptType_C", &TSGLLESetAcceptType_GLLE)); 13169566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSGLLEGetAdapt_C", &TSGLLEGetAdapt_GLLE)); 13173d177a5cSEmil Constantinescu PetscFunctionReturn(0); 13183d177a5cSEmil Constantinescu } 1319