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 */ 13d71ae5a4SJacob Faibussowitsch static PetscScalar Factorial(PetscInt n) 14d71ae5a4SJacob Faibussowitsch { 153d177a5cSEmil Constantinescu PetscInt i; 163d177a5cSEmil Constantinescu if (n < 12) { /* Can compute with 32-bit integers */ 173d177a5cSEmil Constantinescu PetscInt f = 1; 183d177a5cSEmil Constantinescu for (i = 2; i <= n; i++) f *= i; 193d177a5cSEmil Constantinescu return (PetscScalar)f; 203d177a5cSEmil Constantinescu } else { 213d177a5cSEmil Constantinescu PetscScalar f = 1.; 223d177a5cSEmil Constantinescu for (i = 2; i <= n; i++) f *= (PetscScalar)i; 233d177a5cSEmil Constantinescu return f; 243d177a5cSEmil Constantinescu } 253d177a5cSEmil Constantinescu } 263d177a5cSEmil Constantinescu 273d177a5cSEmil Constantinescu /* This function is pure */ 28d71ae5a4SJacob Faibussowitsch static PetscScalar CPowF(PetscScalar c, PetscInt p) 29d71ae5a4SJacob Faibussowitsch { 303d177a5cSEmil Constantinescu return PetscPowRealInt(PetscRealPart(c), p) / Factorial(p); 313d177a5cSEmil Constantinescu } 323d177a5cSEmil Constantinescu 33d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGLLEGetVecs(TS ts, DM dm, Vec *Z, Vec *Ydotstage) 34d71ae5a4SJacob Faibussowitsch { 353d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 363d177a5cSEmil Constantinescu 373d177a5cSEmil Constantinescu PetscFunctionBegin; 383d177a5cSEmil Constantinescu if (Z) { 393d177a5cSEmil Constantinescu if (dm && dm != ts->dm) { 409566063dSJacob Faibussowitsch PetscCall(DMGetNamedGlobalVector(dm, "TSGLLE_Z", Z)); 413d177a5cSEmil Constantinescu } else *Z = gl->Z; 423d177a5cSEmil Constantinescu } 433d177a5cSEmil Constantinescu if (Ydotstage) { 443d177a5cSEmil Constantinescu if (dm && dm != ts->dm) { 459566063dSJacob Faibussowitsch PetscCall(DMGetNamedGlobalVector(dm, "TSGLLE_Ydot", Ydotstage)); 463d177a5cSEmil Constantinescu } else *Ydotstage = gl->Ydot[gl->stage]; 473d177a5cSEmil Constantinescu } 483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 493d177a5cSEmil Constantinescu } 503d177a5cSEmil Constantinescu 51d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGLLERestoreVecs(TS ts, DM dm, Vec *Z, Vec *Ydotstage) 52d71ae5a4SJacob Faibussowitsch { 533d177a5cSEmil Constantinescu PetscFunctionBegin; 543d177a5cSEmil Constantinescu if (Z) { 5548a46eb9SPierre Jolivet if (dm && dm != ts->dm) PetscCall(DMRestoreNamedGlobalVector(dm, "TSGLLE_Z", Z)); 563d177a5cSEmil Constantinescu } 573d177a5cSEmil Constantinescu if (Ydotstage) { 5848a46eb9SPierre Jolivet if (dm && dm != ts->dm) PetscCall(DMRestoreNamedGlobalVector(dm, "TSGLLE_Ydot", Ydotstage)); 593d177a5cSEmil Constantinescu } 603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 613d177a5cSEmil Constantinescu } 623d177a5cSEmil Constantinescu 63d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_TSGLLE(DM fine, DM coarse, void *ctx) 64d71ae5a4SJacob Faibussowitsch { 653d177a5cSEmil Constantinescu PetscFunctionBegin; 663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 673d177a5cSEmil Constantinescu } 683d177a5cSEmil Constantinescu 69d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_TSGLLE(DM fine, Mat restrct, Vec rscale, Mat inject, DM coarse, void *ctx) 70d71ae5a4SJacob Faibussowitsch { 713d177a5cSEmil Constantinescu TS ts = (TS)ctx; 723d177a5cSEmil Constantinescu Vec Ydot, Ydot_c; 733d177a5cSEmil Constantinescu 743d177a5cSEmil Constantinescu PetscFunctionBegin; 759566063dSJacob Faibussowitsch PetscCall(TSGLLEGetVecs(ts, fine, NULL, &Ydot)); 769566063dSJacob Faibussowitsch PetscCall(TSGLLEGetVecs(ts, coarse, NULL, &Ydot_c)); 779566063dSJacob Faibussowitsch PetscCall(MatRestrict(restrct, Ydot, Ydot_c)); 789566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(Ydot_c, rscale, Ydot_c)); 799566063dSJacob Faibussowitsch PetscCall(TSGLLERestoreVecs(ts, fine, NULL, &Ydot)); 809566063dSJacob Faibussowitsch PetscCall(TSGLLERestoreVecs(ts, coarse, NULL, &Ydot_c)); 813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 823d177a5cSEmil Constantinescu } 833d177a5cSEmil Constantinescu 84d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSubDomainHook_TSGLLE(DM dm, DM subdm, void *ctx) 85d71ae5a4SJacob Faibussowitsch { 863d177a5cSEmil Constantinescu PetscFunctionBegin; 873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 883d177a5cSEmil Constantinescu } 893d177a5cSEmil Constantinescu 90d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSubDomainRestrictHook_TSGLLE(DM dm, VecScatter gscat, VecScatter lscat, DM subdm, void *ctx) 91d71ae5a4SJacob Faibussowitsch { 923d177a5cSEmil Constantinescu TS ts = (TS)ctx; 933d177a5cSEmil Constantinescu Vec Ydot, Ydot_s; 943d177a5cSEmil Constantinescu 953d177a5cSEmil Constantinescu PetscFunctionBegin; 969566063dSJacob Faibussowitsch PetscCall(TSGLLEGetVecs(ts, dm, NULL, &Ydot)); 979566063dSJacob Faibussowitsch PetscCall(TSGLLEGetVecs(ts, subdm, NULL, &Ydot_s)); 983d177a5cSEmil Constantinescu 999566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(gscat, Ydot, Ydot_s, INSERT_VALUES, SCATTER_FORWARD)); 1009566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(gscat, Ydot, Ydot_s, INSERT_VALUES, SCATTER_FORWARD)); 1013d177a5cSEmil Constantinescu 1029566063dSJacob Faibussowitsch PetscCall(TSGLLERestoreVecs(ts, dm, NULL, &Ydot)); 1039566063dSJacob Faibussowitsch PetscCall(TSGLLERestoreVecs(ts, subdm, NULL, &Ydot_s)); 1043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1053d177a5cSEmil Constantinescu } 1063d177a5cSEmil Constantinescu 107d71ae5a4SJacob Faibussowitsch 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) 108d71ae5a4SJacob Faibussowitsch { 1093d177a5cSEmil Constantinescu TSGLLEScheme scheme; 1103d177a5cSEmil Constantinescu PetscInt j; 1113d177a5cSEmil Constantinescu 1123d177a5cSEmil Constantinescu PetscFunctionBegin; 11308401ef6SPierre Jolivet PetscCheck(p >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Scheme order must be positive"); 11408401ef6SPierre Jolivet PetscCheck(r >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "At least one item must be carried between steps"); 11508401ef6SPierre Jolivet PetscCheck(s >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "At least one stage is required"); 1164f572ea9SToby Isaac PetscAssertPointer(inscheme, 10); 117c793f718SLisandro Dalcin *inscheme = NULL; 1189566063dSJacob Faibussowitsch PetscCall(PetscNew(&scheme)); 1193d177a5cSEmil Constantinescu scheme->p = p; 1203d177a5cSEmil Constantinescu scheme->q = q; 1213d177a5cSEmil Constantinescu scheme->r = r; 1223d177a5cSEmil Constantinescu scheme->s = s; 1233d177a5cSEmil Constantinescu 1249566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(s, &scheme->c, s * s, &scheme->a, r * s, &scheme->b, r * s, &scheme->u, r * r, &scheme->v)); 1259566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(scheme->c, c, s)); 1263d177a5cSEmil Constantinescu for (j = 0; j < s * s; j++) scheme->a[j] = (PetscAbsScalar(a[j]) < 1e-12) ? 0 : a[j]; 1273d177a5cSEmil Constantinescu for (j = 0; j < r * s; j++) scheme->b[j] = (PetscAbsScalar(b[j]) < 1e-12) ? 0 : b[j]; 1283d177a5cSEmil Constantinescu for (j = 0; j < s * r; j++) scheme->u[j] = (PetscAbsScalar(u[j]) < 1e-12) ? 0 : u[j]; 1293d177a5cSEmil Constantinescu for (j = 0; j < r * r; j++) scheme->v[j] = (PetscAbsScalar(v[j]) < 1e-12) ? 0 : v[j]; 1303d177a5cSEmil Constantinescu 1319566063dSJacob Faibussowitsch PetscCall(PetscMalloc6(r, &scheme->alpha, r, &scheme->beta, r, &scheme->gamma, 3 * s, &scheme->phi, 3 * r, &scheme->psi, r, &scheme->stage_error)); 1323d177a5cSEmil Constantinescu { 1333d177a5cSEmil Constantinescu PetscInt i, j, k, ss = s + 2; 1343d177a5cSEmil Constantinescu PetscBLASInt m, n, one = 1, *ipiv, lwork = 4 * ((s + 3) * 3 + 3), info, ldb; 1353d177a5cSEmil Constantinescu PetscReal rcond, *sing, *workreal; 1363d177a5cSEmil Constantinescu PetscScalar *ImV, *H, *bmat, *workscalar, *c = scheme->c, *a = scheme->a, *b = scheme->b, *u = scheme->u, *v = scheme->v; 1373d177a5cSEmil Constantinescu PetscBLASInt rank; 1389566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(PetscSqr(r), &ImV, 3 * s, &H, 3 * ss, &bmat, lwork, &workscalar, 5 * (3 + r), &workreal, r + s, &sing, r + s, &ipiv)); 1393d177a5cSEmil Constantinescu 1403d177a5cSEmil Constantinescu /* column-major input */ 1413d177a5cSEmil Constantinescu for (i = 0; i < r - 1; i++) { 1423d177a5cSEmil Constantinescu for (j = 0; j < r - 1; j++) ImV[i + j * r] = 1.0 * (i == j) - v[(i + 1) * r + j + 1]; 1433d177a5cSEmil Constantinescu } 1443d177a5cSEmil Constantinescu /* Build right hand side for alpha (tp - glm.B(2:end,:)*(glm.c.^(p)./factorial(p))) */ 1453d177a5cSEmil Constantinescu for (i = 1; i < r; i++) { 1463d177a5cSEmil Constantinescu scheme->alpha[i] = 1. / Factorial(p + 1 - i); 1473d177a5cSEmil Constantinescu for (j = 0; j < s; j++) scheme->alpha[i] -= b[i * s + j] * CPowF(c[j], p); 1483d177a5cSEmil Constantinescu } 1499566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(r - 1, &m)); 1509566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(r, &n)); 151792fecdfSBarry Smith PetscCallBLAS("LAPACKgesv", LAPACKgesv_(&m, &one, ImV, &n, ipiv, scheme->alpha + 1, &n, &info)); 15208401ef6SPierre Jolivet PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to GESV"); 15308401ef6SPierre Jolivet PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_MAT_LU_ZRPVT, "Bad LU factorization"); 1543d177a5cSEmil Constantinescu 1553d177a5cSEmil Constantinescu /* Build right hand side for beta (tp1 - glm.B(2:end,:)*(glm.c.^(p+1)./factorial(p+1)) - e.alpha) */ 1563d177a5cSEmil Constantinescu for (i = 1; i < r; i++) { 1573d177a5cSEmil Constantinescu scheme->beta[i] = 1. / Factorial(p + 2 - i) - scheme->alpha[i]; 1583d177a5cSEmil Constantinescu for (j = 0; j < s; j++) scheme->beta[i] -= b[i * s + j] * CPowF(c[j], p + 1); 1593d177a5cSEmil Constantinescu } 160792fecdfSBarry Smith PetscCallBLAS("LAPACKgetrs", LAPACKgetrs_("No transpose", &m, &one, ImV, &n, ipiv, scheme->beta + 1, &n, &info)); 16108401ef6SPierre Jolivet PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to GETRS"); 16208401ef6SPierre Jolivet PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Should not happen"); 1633d177a5cSEmil Constantinescu 1643d177a5cSEmil Constantinescu /* Build stage_error vector 1653d177a5cSEmil Constantinescu xi = glm.c.^(p+1)/factorial(p+1) - glm.A*glm.c.^p/factorial(p) + glm.U(:,2:end)*e.alpha; 1663d177a5cSEmil Constantinescu */ 1673d177a5cSEmil Constantinescu for (i = 0; i < s; i++) { 1683d177a5cSEmil Constantinescu scheme->stage_error[i] = CPowF(c[i], p + 1); 1693d177a5cSEmil Constantinescu for (j = 0; j < s; j++) scheme->stage_error[i] -= a[i * s + j] * CPowF(c[j], p); 1703d177a5cSEmil Constantinescu for (j = 1; j < r; j++) scheme->stage_error[i] += u[i * r + j] * scheme->alpha[j]; 1713d177a5cSEmil Constantinescu } 1723d177a5cSEmil Constantinescu 1733d177a5cSEmil Constantinescu /* alpha[0] (epsilon in B,J,W 2007) 1743d177a5cSEmil Constantinescu epsilon = 1/factorial(p+1) - B(1,:)*c.^p/factorial(p) + V(1,2:end)*e.alpha; 1753d177a5cSEmil Constantinescu */ 1763d177a5cSEmil Constantinescu scheme->alpha[0] = 1. / Factorial(p + 1); 1773d177a5cSEmil Constantinescu for (j = 0; j < s; j++) scheme->alpha[0] -= b[0 * s + j] * CPowF(c[j], p); 1783d177a5cSEmil Constantinescu for (j = 1; j < r; j++) scheme->alpha[0] += v[0 * r + j] * scheme->alpha[j]; 1793d177a5cSEmil Constantinescu 1803d177a5cSEmil Constantinescu /* right hand side for gamma (glm.B(2:end,:)*e.xi - e.epsilon*eye(s-1,1)) */ 1813d177a5cSEmil Constantinescu for (i = 1; i < r; i++) { 1823d177a5cSEmil Constantinescu scheme->gamma[i] = (i == 1 ? -1. : 0) * scheme->alpha[0]; 1833d177a5cSEmil Constantinescu for (j = 0; j < s; j++) scheme->gamma[i] += b[i * s + j] * scheme->stage_error[j]; 1843d177a5cSEmil Constantinescu } 185792fecdfSBarry Smith PetscCallBLAS("LAPACKgetrs", LAPACKgetrs_("No transpose", &m, &one, ImV, &n, ipiv, scheme->gamma + 1, &n, &info)); 18608401ef6SPierre Jolivet PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to GETRS"); 18708401ef6SPierre Jolivet PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Should not happen"); 1883d177a5cSEmil Constantinescu 1893d177a5cSEmil Constantinescu /* beta[0] (rho in B,J,W 2007) 1903d177a5cSEmil Constantinescu e.rho = 1/factorial(p+2) - glm.B(1,:)*glm.c.^(p+1)/factorial(p+1) ... 1913d177a5cSEmil Constantinescu + glm.V(1,2:end)*e.beta;% - e.epsilon; 1923d177a5cSEmil Constantinescu % Note: The paper (B,J,W 2007) includes the last term in their definition 1933d177a5cSEmil Constantinescu * */ 1943d177a5cSEmil Constantinescu scheme->beta[0] = 1. / Factorial(p + 2); 1953d177a5cSEmil Constantinescu for (j = 0; j < s; j++) scheme->beta[0] -= b[0 * s + j] * CPowF(c[j], p + 1); 1963d177a5cSEmil Constantinescu for (j = 1; j < r; j++) scheme->beta[0] += v[0 * r + j] * scheme->beta[j]; 1973d177a5cSEmil Constantinescu 1983d177a5cSEmil Constantinescu /* gamma[0] (sigma in B,J,W 2007) 1993d177a5cSEmil Constantinescu * e.sigma = glm.B(1,:)*e.xi + glm.V(1,2:end)*e.gamma; 2003d177a5cSEmil Constantinescu * */ 2013d177a5cSEmil Constantinescu scheme->gamma[0] = 0.0; 2023d177a5cSEmil Constantinescu for (j = 0; j < s; j++) scheme->gamma[0] += b[0 * s + j] * scheme->stage_error[j]; 2033d177a5cSEmil Constantinescu for (j = 1; j < r; j++) scheme->gamma[0] += v[0 * s + j] * scheme->gamma[j]; 2043d177a5cSEmil Constantinescu 2053d177a5cSEmil Constantinescu /* Assemble H 20663a3b9bcSJacob Faibussowitsch * % " PetscInt_FMT "etermine the error estimators phi 2073d177a5cSEmil Constantinescu H = [[cpow(glm.c,p) + C*e.alpha] [cpow(glm.c,p+1) + C*e.beta] ... 2083d177a5cSEmil Constantinescu [e.xi - C*(e.gamma + 0*e.epsilon*eye(s-1,1))]]'; 2093d177a5cSEmil Constantinescu % Paper has formula above without the 0, but that term must be left 2103d177a5cSEmil Constantinescu % out to satisfy the conditions they propose and to make the 2113d177a5cSEmil Constantinescu % example schemes work 2123d177a5cSEmil Constantinescu e.H = H; 2133d177a5cSEmil Constantinescu e.phi = (H \ [1 0 0;1 1 0;0 0 -1])'; 2143d177a5cSEmil Constantinescu e.psi = -e.phi*C; 2153d177a5cSEmil Constantinescu * */ 2163d177a5cSEmil Constantinescu for (j = 0; j < s; j++) { 2173d177a5cSEmil Constantinescu H[0 + j * 3] = CPowF(c[j], p); 2183d177a5cSEmil Constantinescu H[1 + j * 3] = CPowF(c[j], p + 1); 2193d177a5cSEmil Constantinescu H[2 + j * 3] = scheme->stage_error[j]; 2203d177a5cSEmil Constantinescu for (k = 1; k < r; k++) { 2213d177a5cSEmil Constantinescu H[0 + j * 3] += CPowF(c[j], k - 1) * scheme->alpha[k]; 2223d177a5cSEmil Constantinescu H[1 + j * 3] += CPowF(c[j], k - 1) * scheme->beta[k]; 2233d177a5cSEmil Constantinescu H[2 + j * 3] -= CPowF(c[j], k - 1) * scheme->gamma[k]; 2243d177a5cSEmil Constantinescu } 2253d177a5cSEmil Constantinescu } 2269371c9d4SSatish Balay bmat[0 + 0 * ss] = 1.; 2279371c9d4SSatish Balay bmat[0 + 1 * ss] = 0.; 2289371c9d4SSatish Balay bmat[0 + 2 * ss] = 0.; 2299371c9d4SSatish Balay bmat[1 + 0 * ss] = 1.; 2309371c9d4SSatish Balay bmat[1 + 1 * ss] = 1.; 2319371c9d4SSatish Balay bmat[1 + 2 * ss] = 0.; 2329371c9d4SSatish Balay bmat[2 + 0 * ss] = 0.; 2339371c9d4SSatish Balay bmat[2 + 1 * ss] = 0.; 2349371c9d4SSatish Balay bmat[2 + 2 * ss] = -1.; 2353d177a5cSEmil Constantinescu m = 3; 2369566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(s, &n)); 2379566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(ss, &ldb)); 2383d177a5cSEmil Constantinescu rcond = 1e-12; 2393d177a5cSEmil Constantinescu #if defined(PETSC_USE_COMPLEX) 2403d177a5cSEmil Constantinescu /* ZGELSS( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, WORK, LWORK, RWORK, INFO) */ 241792fecdfSBarry Smith PetscCallBLAS("LAPACKgelss", LAPACKgelss_(&m, &n, &m, H, &m, bmat, &ldb, sing, &rcond, &rank, workscalar, &lwork, workreal, &info)); 2423d177a5cSEmil Constantinescu #else 2433d177a5cSEmil Constantinescu /* DGELSS( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, WORK, LWORK, INFO) */ 244792fecdfSBarry Smith PetscCallBLAS("LAPACKgelss", LAPACKgelss_(&m, &n, &m, H, &m, bmat, &ldb, sing, &rcond, &rank, workscalar, &lwork, &info)); 2453d177a5cSEmil Constantinescu #endif 24608401ef6SPierre Jolivet PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to GELSS"); 24708401ef6SPierre Jolivet PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "SVD failed to converge"); 2483d177a5cSEmil Constantinescu 2493d177a5cSEmil Constantinescu for (j = 0; j < 3; j++) { 2503d177a5cSEmil Constantinescu for (k = 0; k < s; k++) scheme->phi[k + j * s] = bmat[k + j * ss]; 2513d177a5cSEmil Constantinescu } 2523d177a5cSEmil Constantinescu 2533d177a5cSEmil Constantinescu /* the other part of the error estimator, psi in B,J,W 2007 */ 2543d177a5cSEmil Constantinescu scheme->psi[0 * r + 0] = 0.; 2553d177a5cSEmil Constantinescu scheme->psi[1 * r + 0] = 0.; 2563d177a5cSEmil Constantinescu scheme->psi[2 * r + 0] = 0.; 2573d177a5cSEmil Constantinescu for (j = 1; j < r; j++) { 2583d177a5cSEmil Constantinescu scheme->psi[0 * r + j] = 0.; 2593d177a5cSEmil Constantinescu scheme->psi[1 * r + j] = 0.; 2603d177a5cSEmil Constantinescu scheme->psi[2 * r + j] = 0.; 2613d177a5cSEmil Constantinescu for (k = 0; k < s; k++) { 2623d177a5cSEmil Constantinescu scheme->psi[0 * r + j] -= CPowF(c[k], j - 1) * scheme->phi[0 * s + k]; 2633d177a5cSEmil Constantinescu scheme->psi[1 * r + j] -= CPowF(c[k], j - 1) * scheme->phi[1 * s + k]; 2643d177a5cSEmil Constantinescu scheme->psi[2 * r + j] -= CPowF(c[k], j - 1) * scheme->phi[2 * s + k]; 2653d177a5cSEmil Constantinescu } 2663d177a5cSEmil Constantinescu } 2679566063dSJacob Faibussowitsch PetscCall(PetscFree7(ImV, H, bmat, workscalar, workreal, sing, ipiv)); 2683d177a5cSEmil Constantinescu } 2693d177a5cSEmil Constantinescu /* Check which properties are satisfied */ 2703d177a5cSEmil Constantinescu scheme->stiffly_accurate = PETSC_TRUE; 2713d177a5cSEmil Constantinescu if (scheme->c[s - 1] != 1.) scheme->stiffly_accurate = PETSC_FALSE; 2729371c9d4SSatish Balay for (j = 0; j < s; j++) 2739371c9d4SSatish Balay if (a[(s - 1) * s + j] != b[j]) scheme->stiffly_accurate = PETSC_FALSE; 2749371c9d4SSatish Balay for (j = 0; j < r; j++) 2759371c9d4SSatish Balay if (u[(s - 1) * r + j] != v[j]) scheme->stiffly_accurate = PETSC_FALSE; 2763d177a5cSEmil Constantinescu scheme->fsal = scheme->stiffly_accurate; /* FSAL is stronger */ 2779371c9d4SSatish Balay for (j = 0; j < s - 1; j++) 2789371c9d4SSatish Balay if (r > 1 && b[1 * s + j] != 0.) scheme->fsal = PETSC_FALSE; 2793d177a5cSEmil Constantinescu if (b[1 * s + r - 1] != 1.) scheme->fsal = PETSC_FALSE; 2809371c9d4SSatish Balay for (j = 0; j < r; j++) 2819371c9d4SSatish Balay if (r > 1 && v[1 * r + j] != 0.) scheme->fsal = PETSC_FALSE; 2823d177a5cSEmil Constantinescu 2833d177a5cSEmil Constantinescu *inscheme = scheme; 2843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2853d177a5cSEmil Constantinescu } 2863d177a5cSEmil Constantinescu 287d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGLLESchemeDestroy(TSGLLEScheme sc) 288d71ae5a4SJacob Faibussowitsch { 2893d177a5cSEmil Constantinescu PetscFunctionBegin; 2909566063dSJacob Faibussowitsch PetscCall(PetscFree5(sc->c, sc->a, sc->b, sc->u, sc->v)); 2919566063dSJacob Faibussowitsch PetscCall(PetscFree6(sc->alpha, sc->beta, sc->gamma, sc->phi, sc->psi, sc->stage_error)); 2929566063dSJacob Faibussowitsch PetscCall(PetscFree(sc)); 2933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2943d177a5cSEmil Constantinescu } 2953d177a5cSEmil Constantinescu 296d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGLLEDestroy_Default(TS_GLLE *gl) 297d71ae5a4SJacob Faibussowitsch { 2983d177a5cSEmil Constantinescu PetscInt i; 2993d177a5cSEmil Constantinescu 3003d177a5cSEmil Constantinescu PetscFunctionBegin; 3013d177a5cSEmil Constantinescu for (i = 0; i < gl->nschemes; i++) { 3029566063dSJacob Faibussowitsch if (gl->schemes[i]) PetscCall(TSGLLESchemeDestroy(gl->schemes[i])); 3033d177a5cSEmil Constantinescu } 3049566063dSJacob Faibussowitsch PetscCall(PetscFree(gl->schemes)); 3053d177a5cSEmil Constantinescu gl->nschemes = 0; 3069566063dSJacob Faibussowitsch PetscCall(PetscMemzero(gl->type_name, sizeof(gl->type_name))); 3073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3083d177a5cSEmil Constantinescu } 3093d177a5cSEmil Constantinescu 310d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGLLEViewTable_Private(PetscViewer viewer, PetscInt m, PetscInt n, const PetscScalar a[], const char name[]) 311d71ae5a4SJacob Faibussowitsch { 3123d177a5cSEmil Constantinescu PetscBool iascii; 3133d177a5cSEmil Constantinescu PetscInt i, j; 3143d177a5cSEmil Constantinescu 3153d177a5cSEmil Constantinescu PetscFunctionBegin; 3169566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 3173d177a5cSEmil Constantinescu if (iascii) { 3189566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%30s = [", name)); 3193d177a5cSEmil Constantinescu for (i = 0; i < m; i++) { 3209566063dSJacob Faibussowitsch if (i) PetscCall(PetscViewerASCIIPrintf(viewer, "%30s [", "")); 3219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 32248a46eb9SPierre Jolivet for (j = 0; j < n; j++) PetscCall(PetscViewerASCIIPrintf(viewer, " %12.8g", (double)PetscRealPart(a[i * n + j]))); 3239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "]\n")); 3249566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 3253d177a5cSEmil Constantinescu } 3263d177a5cSEmil Constantinescu } 3273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3283d177a5cSEmil Constantinescu } 3293d177a5cSEmil Constantinescu 330d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGLLESchemeView(TSGLLEScheme sc, PetscBool view_details, PetscViewer viewer) 331d71ae5a4SJacob Faibussowitsch { 3323d177a5cSEmil Constantinescu PetscBool iascii; 3333d177a5cSEmil Constantinescu 3343d177a5cSEmil Constantinescu PetscFunctionBegin; 3359566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 3363d177a5cSEmil Constantinescu if (iascii) { 33763a3b9bcSJacob 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)); 3389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 3399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Stiffly accurate: %s, FSAL: %s\n", sc->stiffly_accurate ? "yes" : "no", sc->fsal ? "yes" : "no")); 3409371c9d4SSatish 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]))); 3419566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, 1, sc->s, sc->c, "Abscissas c")); 3423d177a5cSEmil Constantinescu if (view_details) { 3439566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, sc->s, sc->s, sc->a, "A")); 3449566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, sc->r, sc->s, sc->b, "B")); 3459566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, sc->s, sc->r, sc->u, "U")); 3469566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, sc->r, sc->r, sc->v, "V")); 3473d177a5cSEmil Constantinescu 3489566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, 3, sc->s, sc->phi, "Error estimate phi")); 3499566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, 3, sc->r, sc->psi, "Error estimate psi")); 3509566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, 1, sc->r, sc->alpha, "Modify alpha")); 3519566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, 1, sc->r, sc->beta, "Modify beta")); 3529566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, 1, sc->r, sc->gamma, "Modify gamma")); 3539566063dSJacob Faibussowitsch PetscCall(TSGLLEViewTable_Private(viewer, 1, sc->s, sc->stage_error, "Stage error xi")); 3543d177a5cSEmil Constantinescu } 3559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 35698921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Viewer type %s not supported", ((PetscObject)viewer)->type_name); 3573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3583d177a5cSEmil Constantinescu } 3593d177a5cSEmil Constantinescu 360d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGLLEEstimateHigherMoments_Default(TSGLLEScheme sc, PetscReal h, Vec Ydot[], Vec Xold[], Vec hm[]) 361d71ae5a4SJacob Faibussowitsch { 3623d177a5cSEmil Constantinescu PetscInt i; 3633d177a5cSEmil Constantinescu 3643d177a5cSEmil Constantinescu PetscFunctionBegin; 365cad9d221SBarry Smith PetscCheck(sc->r <= 64 && sc->s <= 64, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Ridiculous number of stages or items passed between stages"); 3663d177a5cSEmil Constantinescu /* build error vectors*/ 3673d177a5cSEmil Constantinescu for (i = 0; i < 3; i++) { 3683d177a5cSEmil Constantinescu PetscScalar phih[64]; 3693d177a5cSEmil Constantinescu PetscInt j; 3703d177a5cSEmil Constantinescu for (j = 0; j < sc->s; j++) phih[j] = sc->phi[i * sc->s + j] * h; 3719566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(hm[i])); 3729566063dSJacob Faibussowitsch PetscCall(VecMAXPY(hm[i], sc->s, phih, Ydot)); 3739566063dSJacob Faibussowitsch PetscCall(VecMAXPY(hm[i], sc->r, &sc->psi[i * sc->r], Xold)); 3743d177a5cSEmil Constantinescu } 3753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3763d177a5cSEmil Constantinescu } 3773d177a5cSEmil Constantinescu 378d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGLLECompleteStep_Rescale(TSGLLEScheme sc, PetscReal h, TSGLLEScheme next_sc, PetscReal next_h, Vec Ydot[], Vec Xold[], Vec X[]) 379d71ae5a4SJacob Faibussowitsch { 3803d177a5cSEmil Constantinescu PetscScalar brow[32], vrow[32]; 3813d177a5cSEmil Constantinescu PetscInt i, j, r, s; 3823d177a5cSEmil Constantinescu 3833d177a5cSEmil Constantinescu PetscFunctionBegin; 3843d177a5cSEmil Constantinescu /* Build the new solution from (X,Ydot) */ 3853d177a5cSEmil Constantinescu r = sc->r; 3863d177a5cSEmil Constantinescu s = sc->s; 3873d177a5cSEmil Constantinescu for (i = 0; i < r; i++) { 3889566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(X[i])); 3893d177a5cSEmil Constantinescu for (j = 0; j < s; j++) brow[j] = h * sc->b[i * s + j]; 3909566063dSJacob Faibussowitsch PetscCall(VecMAXPY(X[i], s, brow, Ydot)); 3913d177a5cSEmil Constantinescu for (j = 0; j < r; j++) vrow[j] = sc->v[i * r + j]; 3929566063dSJacob Faibussowitsch PetscCall(VecMAXPY(X[i], r, vrow, Xold)); 3933d177a5cSEmil Constantinescu } 3943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3953d177a5cSEmil Constantinescu } 3963d177a5cSEmil Constantinescu 397d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGLLECompleteStep_RescaleAndModify(TSGLLEScheme sc, PetscReal h, TSGLLEScheme next_sc, PetscReal next_h, Vec Ydot[], Vec Xold[], Vec X[]) 398d71ae5a4SJacob Faibussowitsch { 3993d177a5cSEmil Constantinescu PetscScalar brow[32], vrow[32]; 4003d177a5cSEmil Constantinescu PetscReal ratio; 4013d177a5cSEmil Constantinescu PetscInt i, j, p, r, s; 4023d177a5cSEmil Constantinescu 4033d177a5cSEmil Constantinescu PetscFunctionBegin; 4043d177a5cSEmil Constantinescu /* Build the new solution from (X,Ydot) */ 4053d177a5cSEmil Constantinescu p = sc->p; 4063d177a5cSEmil Constantinescu r = sc->r; 4073d177a5cSEmil Constantinescu s = sc->s; 4083d177a5cSEmil Constantinescu ratio = next_h / h; 4093d177a5cSEmil Constantinescu for (i = 0; i < r; i++) { 4109566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(X[i])); 4113d177a5cSEmil Constantinescu for (j = 0; j < s; j++) { 4129371c9d4SSatish 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])); 4133d177a5cSEmil Constantinescu } 4149566063dSJacob Faibussowitsch PetscCall(VecMAXPY(X[i], s, brow, Ydot)); 4153d177a5cSEmil Constantinescu for (j = 0; j < r; j++) { 4169371c9d4SSatish 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])); 4173d177a5cSEmil Constantinescu } 4189566063dSJacob Faibussowitsch PetscCall(VecMAXPY(X[i], r, vrow, Xold)); 4193d177a5cSEmil Constantinescu } 4203d177a5cSEmil Constantinescu if (r < next_sc->r) { 42108401ef6SPierre Jolivet PetscCheck(r + 1 == next_sc->r, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cannot accommodate jump in r greater than 1"); 4229566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(X[r])); 4233d177a5cSEmil Constantinescu for (j = 0; j < s; j++) brow[j] = h * PetscPowRealInt(ratio, p + 1) * sc->phi[0 * s + j]; 4249566063dSJacob Faibussowitsch PetscCall(VecMAXPY(X[r], s, brow, Ydot)); 4253d177a5cSEmil Constantinescu for (j = 0; j < r; j++) vrow[j] = PetscPowRealInt(ratio, p + 1) * sc->psi[0 * r + j]; 4269566063dSJacob Faibussowitsch PetscCall(VecMAXPY(X[r], r, vrow, Xold)); 4273d177a5cSEmil Constantinescu } 4283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4293d177a5cSEmil Constantinescu } 4303d177a5cSEmil Constantinescu 431d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGLLECreate_IRKS(TS ts) 432d71ae5a4SJacob Faibussowitsch { 4333d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 4343d177a5cSEmil Constantinescu 4353d177a5cSEmil Constantinescu PetscFunctionBegin; 4363d177a5cSEmil Constantinescu gl->Destroy = TSGLLEDestroy_Default; 4373d177a5cSEmil Constantinescu gl->EstimateHigherMoments = TSGLLEEstimateHigherMoments_Default; 4383d177a5cSEmil Constantinescu gl->CompleteStep = TSGLLECompleteStep_RescaleAndModify; 4399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(10, &gl->schemes)); 4403d177a5cSEmil Constantinescu gl->nschemes = 0; 4413d177a5cSEmil Constantinescu 4423d177a5cSEmil Constantinescu { 4433d177a5cSEmil Constantinescu /* p=1,q=1, r=s=2, A- and L-stable with error estimates of order 2 and 3 4443d177a5cSEmil Constantinescu * Listed in Butcher & Podhaisky 2006. On error estimation in general linear methods for stiff ODE. 4453d177a5cSEmil Constantinescu * irks(0.3,0,[.3,1],[1],1) 4463d177a5cSEmil Constantinescu * Note: can be made to have classical order (not stage order) 2 by replacing 0.3 with 1-sqrt(1/2) 4473d177a5cSEmil Constantinescu * but doing so would sacrifice the error estimator. 4483d177a5cSEmil Constantinescu */ 4493d177a5cSEmil Constantinescu const PetscScalar c[2] = {3. / 10., 1.}; 4509371c9d4SSatish Balay const PetscScalar a[2][2] = { 4519371c9d4SSatish Balay {3. / 10., 0 }, 4529371c9d4SSatish Balay {7. / 10., 3. / 10.} 4539371c9d4SSatish Balay }; 4549371c9d4SSatish Balay const PetscScalar b[2][2] = { 4559371c9d4SSatish Balay {7. / 10., 3. / 10.}, 4569371c9d4SSatish Balay {0, 1 } 4579371c9d4SSatish Balay }; 4589371c9d4SSatish Balay const PetscScalar u[2][2] = { 4599371c9d4SSatish Balay {1, 0}, 4609371c9d4SSatish Balay {1, 0} 4619371c9d4SSatish Balay }; 4629371c9d4SSatish Balay const PetscScalar v[2][2] = { 4639371c9d4SSatish Balay {1, 0}, 4649371c9d4SSatish Balay {0, 0} 4659371c9d4SSatish Balay }; 4669566063dSJacob Faibussowitsch PetscCall(TSGLLESchemeCreate(1, 1, 2, 2, c, *a, *b, *u, *v, &gl->schemes[gl->nschemes++])); 4673d177a5cSEmil Constantinescu } 4683d177a5cSEmil Constantinescu 4693d177a5cSEmil Constantinescu { 4703d177a5cSEmil Constantinescu /* p=q=2, r=s=3: irks(4/9,0,[1:3]/3,[0.33852],1) */ 4713d177a5cSEmil Constantinescu /* http://www.math.auckland.ac.nz/~hpod/atlas/i2a.html */ 47297a1619fSSatish Balay const PetscScalar c[3] = {1. / 3., 2. / 3., 1}; 47397a1619fSSatish Balay const PetscScalar a[3][3] = { 47497a1619fSSatish Balay {4. / 9., 0, 0 }, 47597a1619fSSatish Balay {1.03750643704090e+00, 4. / 9., 0 }, 47697a1619fSSatish Balay {7.67024779410304e-01, -3.81140216918943e-01, 4. / 9.} 47797a1619fSSatish Balay }; 47897a1619fSSatish Balay const PetscScalar b[3][3] = { 47997a1619fSSatish Balay {0.767024779410304, -0.381140216918943, 4. / 9. }, 48097a1619fSSatish Balay {0.000000000000000, 0.000000000000000, 1.000000000000000}, 48197a1619fSSatish Balay {-2.075048385225385, 0.621728385225383, 1.277197204924873} 48297a1619fSSatish Balay }; 48397a1619fSSatish Balay const PetscScalar u[3][3] = { 48497a1619fSSatish Balay {1.0000000000000000, -0.1111111111111109, -0.0925925925925922}, 48597a1619fSSatish Balay {1.0000000000000000, -0.8152842148186744, -0.4199095530877056}, 48697a1619fSSatish Balay {1.0000000000000000, 0.1696709930641948, 0.0539741070314165 } 48797a1619fSSatish Balay }; 48897a1619fSSatish Balay const PetscScalar v[3][3] = { 48997a1619fSSatish Balay {1.0000000000000000, 0.1696709930641948, 0.0539741070314165}, 49097a1619fSSatish Balay {0.000000000000000, 0.000000000000000, 0.000000000000000 }, 49197a1619fSSatish Balay {0.000000000000000, 0.176122795075129, 0.000000000000000 } 49297a1619fSSatish Balay }; 4939566063dSJacob Faibussowitsch PetscCall(TSGLLESchemeCreate(2, 2, 3, 3, c, *a, *b, *u, *v, &gl->schemes[gl->nschemes++])); 4943d177a5cSEmil Constantinescu } 4953d177a5cSEmil Constantinescu { 4963d177a5cSEmil Constantinescu /* p=q=3, r=s=4: irks(9/40,0,[1:4]/4,[0.3312 1.0050],[0.49541 1;1 0]) */ 49797a1619fSSatish Balay const PetscScalar c[4] = {0.25, 0.5, 0.75, 1.0}; 49897a1619fSSatish Balay const PetscScalar a[4][4] = { 49997a1619fSSatish Balay {9. / 40., 0, 0, 0 }, 50097a1619fSSatish Balay {2.11286958887701e-01, 9. / 40., 0, 0 }, 50197a1619fSSatish Balay {9.46338294287584e-01, -3.42942861246094e-01, 9. / 40., 0 }, 50297a1619fSSatish Balay {0.521490453970721, -0.662474225622980, 0.490476425459734, 9. / 40.} 50397a1619fSSatish Balay }; 50497a1619fSSatish Balay const PetscScalar b[4][4] = { 50597a1619fSSatish Balay {0.521490453970721, -0.662474225622980, 0.490476425459734, 9. / 40. }, 50697a1619fSSatish Balay {0.000000000000000, 0.000000000000000, 0.000000000000000, 1.000000000000000}, 50797a1619fSSatish Balay {-0.084677029310348, 1.390757514776085, -1.568157386206001, 2.023192696767826}, 50897a1619fSSatish Balay {0.465383797936408, 1.478273530625148, -1.930836081010182, 1.644872111193354} 50997a1619fSSatish Balay }; 51097a1619fSSatish Balay const PetscScalar u[4][4] = { 51197a1619fSSatish Balay {1.00000000000000000, 0.02500000000001035, -0.02499999999999053, -0.00442708333332865}, 51297a1619fSSatish Balay {1.00000000000000000, 0.06371304111232945, -0.04032173972189845, -0.01389438413189452}, 51397a1619fSSatish Balay {1.00000000000000000, -0.07839543304147778, 0.04738685705116663, 0.02032603595928376 }, 51497a1619fSSatish Balay {1.00000000000000000, 0.42550734619251651, 0.10800718022400080, -0.01726712647760034} 51597a1619fSSatish Balay }; 51697a1619fSSatish Balay const PetscScalar v[4][4] = { 51797a1619fSSatish Balay {1.00000000000000000, 0.42550734619251651, 0.10800718022400080, -0.01726712647760034}, 51897a1619fSSatish Balay {0.000000000000000, 0.000000000000000, 0.000000000000000, 0.000000000000000 }, 51997a1619fSSatish Balay {0.000000000000000, -1.761115796027561, -0.521284157173780, 0.258249384305463 }, 52097a1619fSSatish Balay {0.000000000000000, -1.657693358744728, -1.052227765232394, 0.521284157173780 } 52197a1619fSSatish Balay }; 5229566063dSJacob Faibussowitsch PetscCall(TSGLLESchemeCreate(3, 3, 4, 4, c, *a, *b, *u, *v, &gl->schemes[gl->nschemes++])); 5233d177a5cSEmil Constantinescu } 5243d177a5cSEmil Constantinescu { 5253d177a5cSEmil Constantinescu /* p=q=4, r=s=5: 5263d177a5cSEmil Constantinescu irks(3/11,0,[1:5]/5, [0.1715 -0.1238 0.6617],... 5273d177a5cSEmil Constantinescu [ -0.0812 0.4079 1.0000 5283d177a5cSEmil Constantinescu 1.0000 0 0 5293d177a5cSEmil Constantinescu 0.8270 1.0000 0]) 5303d177a5cSEmil Constantinescu */ 53197a1619fSSatish Balay const PetscScalar c[5] = {0.2, 0.4, 0.6, 0.8, 1.0}; 53297a1619fSSatish Balay const PetscScalar a[5][5] = { 53397a1619fSSatish Balay {2.72727272727352e-01, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00}, 53497a1619fSSatish Balay {-1.03980153733431e-01, 2.72727272727405e-01, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00}, 53597a1619fSSatish Balay {-1.58615400341492e+00, 7.44168951881122e-01, 2.72727272727309e-01, 0.00000000000000e+00, 0.00000000000000e+00}, 53697a1619fSSatish Balay {-8.73658042865628e-01, 5.37884671894595e-01, -1.63298538799523e-01, 2.72727272726996e-01, 0.00000000000000e+00}, 53797a1619fSSatish Balay {2.95489397443992e-01, -1.18481693910097e+00, -6.68029812659953e-01, 1.00716687860943e+00, 2.72727272727288e-01} 53897a1619fSSatish Balay }; 53997a1619fSSatish Balay const PetscScalar b[5][5] = { 54097a1619fSSatish Balay {2.95489397443992e-01, -1.18481693910097e+00, -6.68029812659953e-01, 1.00716687860943e+00, 2.72727272727288e-01}, 54197a1619fSSatish Balay {0.00000000000000e+00, 1.11022302462516e-16, -2.22044604925031e-16, 0.00000000000000e+00, 1.00000000000000e+00}, 54297a1619fSSatish Balay {-4.05882503986005e+00, -4.00924006567769e+00, -1.38930610972481e+00, 4.45223930308488e+00, 6.32331093108427e-01}, 54397a1619fSSatish Balay {8.35690179937017e+00, -2.26640927349732e+00, 6.86647884973826e+00, -5.22595158025740e+00, 4.50893068837431e+00}, 54497a1619fSSatish Balay {1.27656267027479e+01, 2.80882153840821e+00, 8.91173096522890e+00, -1.07936444078906e+01, 4.82534148988854e+00} 54597a1619fSSatish Balay }; 54697a1619fSSatish Balay const PetscScalar u[5][5] = { 54797a1619fSSatish Balay {1.00000000000000e+00, -7.27272727273551e-02, -3.45454545454419e-02, -4.12121212119565e-03, -2.96969696964014e-04}, 54897a1619fSSatish Balay {1.00000000000000e+00, 2.31252881006154e-01, -8.29487834416481e-03, -9.07191207681020e-03, -1.70378403743473e-03}, 54997a1619fSSatish Balay {1.00000000000000e+00, 1.16925777880663e+00, 3.59268562942635e-02, -4.09013451730615e-02, -1.02411119670164e-02}, 55097a1619fSSatish Balay {1.00000000000000e+00, 1.02634463704356e+00, 1.59375044913405e-01, 1.89673015035370e-03, -4.89987231897569e-03}, 55197a1619fSSatish Balay {1.00000000000000e+00, 1.27746320298021e+00, 2.37186008132728e-01, -8.28694373940065e-02, -5.34396510196430e-02} 55297a1619fSSatish Balay }; 55397a1619fSSatish Balay const PetscScalar v[5][5] = { 55497a1619fSSatish Balay {1.00000000000000e+00, 1.27746320298021e+00, 2.37186008132728e-01, -8.28694373940065e-02, -5.34396510196430e-02}, 55597a1619fSSatish Balay {0.00000000000000e+00, -1.77635683940025e-15, -1.99840144432528e-15, -9.99200722162641e-16, -3.33066907387547e-16}, 55697a1619fSSatish Balay {0.00000000000000e+00, 4.37280081906924e+00, 5.49221645016377e-02, -8.88913177394943e-02, 1.12879077989154e-01 }, 55797a1619fSSatish Balay {0.00000000000000e+00, -1.22399504837280e+01, -5.21287338448645e+00, -8.03952325565291e-01, 4.60298678047147e-01 }, 55897a1619fSSatish Balay {0.00000000000000e+00, -1.85178762883829e+01, -5.21411849862624e+00, -1.04283436528809e+00, 7.49030161063651e-01 } 55997a1619fSSatish Balay }; 5609566063dSJacob Faibussowitsch PetscCall(TSGLLESchemeCreate(4, 4, 5, 5, c, *a, *b, *u, *v, &gl->schemes[gl->nschemes++])); 5613d177a5cSEmil Constantinescu } 5623d177a5cSEmil Constantinescu { 5633d177a5cSEmil Constantinescu /* p=q=5, r=s=6; 5643d177a5cSEmil Constantinescu irks(1/3,0,[1:6]/6,... 5653d177a5cSEmil Constantinescu [-0.0489 0.4228 -0.8814 0.9021],... 5663d177a5cSEmil Constantinescu [-0.3474 -0.6617 0.6294 0.2129 5673d177a5cSEmil Constantinescu 0.0044 -0.4256 -0.1427 -0.8936 5683d177a5cSEmil Constantinescu -0.8267 0.4821 0.1371 -0.2557 5693d177a5cSEmil Constantinescu -0.4426 -0.3855 -0.7514 0.3014]) 5703d177a5cSEmil Constantinescu */ 57197a1619fSSatish Balay const PetscScalar c[6] = {1. / 6, 2. / 6, 3. / 6, 4. / 6, 5. / 6, 1.}; 57297a1619fSSatish Balay const PetscScalar a[6][6] = { 57397a1619fSSatish Balay {3.33333333333940e-01, 0, 0, 0, 0, 0 }, 57497a1619fSSatish Balay {-8.64423857333350e-02, 3.33333333332888e-01, 0, 0, 0, 0 }, 57597a1619fSSatish Balay {-2.16850174258252e+00, -2.23619072028839e+00, 3.33333333335204e-01, 0, 0, 0 }, 57697a1619fSSatish Balay {-4.73160970138997e+00, -3.89265344629268e+00, -2.76318716520933e-01, 3.33333333335759e-01, 0, 0 }, 57797a1619fSSatish Balay {-6.75187540297338e+00, -7.90756533769377e+00, 7.90245051802259e-01, -4.48352364517632e-01, 3.33333333328483e-01, 0 }, 57897a1619fSSatish Balay {-4.26488287921548e+00, -1.19320395589302e+01, 3.38924509887755e+00, -2.23969848002481e+00, 6.62807710124007e-01, 3.33333333335440e-01} 57997a1619fSSatish Balay }; 58097a1619fSSatish Balay const PetscScalar b[6][6] = { 58197a1619fSSatish Balay {-4.26488287921548e+00, -1.19320395589302e+01, 3.38924509887755e+00, -2.23969848002481e+00, 6.62807710124007e-01, 3.33333333335440e-01 }, 58297a1619fSSatish Balay {-8.88178419700125e-16, 4.44089209850063e-16, -1.54737334057131e-15, -8.88178419700125e-16, 0.00000000000000e+00, 1.00000000000001e+00 }, 58397a1619fSSatish Balay {-2.87780425770651e+01, -1.13520448264971e+01, 2.62002318943161e+01, 2.56943874812797e+01, -3.06702268304488e+01, 6.68067773510103e+00 }, 58497a1619fSSatish Balay {5.47971245256474e+01, 6.80366875868284e+01, -6.50952588861999e+01, -8.28643975339097e+01, 8.17416943896414e+01, -1.17819043489036e+01}, 58597a1619fSSatish Balay {-2.33332114788869e+02, 6.12942539462634e+01, -4.91850135865944e+01, 1.82716844135480e+02, -1.29788173979395e+02, 3.09968095651099e+01 }, 58697a1619fSSatish Balay {-1.72049132343751e+02, 8.60194713593999e+00, 7.98154219170200e-01, 1.50371386053218e+02, -1.18515423962066e+02, 2.50898277784663e+01 } 58797a1619fSSatish Balay }; 58897a1619fSSatish Balay const PetscScalar u[6][6] = { 58997a1619fSSatish Balay {1.00000000000000e+00, -1.66666666666870e-01, -4.16666666664335e-02, -3.85802469124815e-03, -2.25051440302250e-04, -9.64506172339142e-06}, 59097a1619fSSatish Balay {1.00000000000000e+00, 8.64423857327162e-02, -4.11484912671353e-02, -1.11450903217645e-02, -1.47651050487126e-03, -1.34395070766826e-04}, 59197a1619fSSatish Balay {1.00000000000000e+00, 4.57135912953434e+00, 1.06514719719137e+00, 1.33517564218007e-01, 1.11365952968659e-02, 6.12382756769504e-04 }, 59297a1619fSSatish Balay {1.00000000000000e+00, 9.23391519753404e+00, 2.22431212392095e+00, 2.91823807741891e-01, 2.52058456411084e-02, 1.22800542949647e-03 }, 59397a1619fSSatish Balay {1.00000000000000e+00, 1.48175480533865e+01, 3.73439117461835e+00, 5.14648336541804e-01, 4.76430038853402e-02, 2.56798515502156e-03 }, 59497a1619fSSatish Balay {1.00000000000000e+00, 1.50512347758335e+01, 4.10099701165164e+00, 5.66039141003603e-01, 3.91213893800891e-02, -2.99136269067853e-03} 59597a1619fSSatish Balay }; 59697a1619fSSatish Balay const PetscScalar v[6][6] = { 59797a1619fSSatish Balay {1.00000000000000e+00, 1.50512347758335e+01, 4.10099701165164e+00, 5.66039141003603e-01, 3.91213893800891e-02, -2.99136269067853e-03}, 59897a1619fSSatish Balay {0.00000000000000e+00, -4.88498130835069e-15, -6.43929354282591e-15, -3.55271367880050e-15, -1.22124532708767e-15, -3.12250225675825e-16}, 59997a1619fSSatish Balay {0.00000000000000e+00, 1.22250171233141e+01, -1.77150760606169e+00, 3.54516769879390e-01, 6.22298845883398e-01, 2.31647447450276e-01 }, 60097a1619fSSatish Balay {0.00000000000000e+00, -4.48339457331040e+01, -3.57363126641880e-01, 5.18750173123425e-01, 6.55727990241799e-02, 1.63175368287079e-01 }, 60197a1619fSSatish Balay {0.00000000000000e+00, 1.37297394708005e+02, -1.60145272991317e+00, -5.05319555199441e+00, 1.55328940390990e-01, 9.16629423682464e-01 }, 60297a1619fSSatish Balay {0.00000000000000e+00, 1.05703241119022e+02, -1.16610260983038e+00, -2.99767252773859e+00, -1.13472315553890e-01, 1.09742849254729e+00 } 60397a1619fSSatish Balay }; 6049566063dSJacob Faibussowitsch PetscCall(TSGLLESchemeCreate(5, 5, 6, 6, c, *a, *b, *u, *v, &gl->schemes[gl->nschemes++])); 6053d177a5cSEmil Constantinescu } 6063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6073d177a5cSEmil Constantinescu } 6083d177a5cSEmil Constantinescu 6093d177a5cSEmil Constantinescu /*@C 610bcf0153eSBarry Smith TSGLLESetType - sets the class of general linear method, `TSGLLE` to use for time-stepping 6113d177a5cSEmil Constantinescu 612c3339decSBarry Smith Collective 6133d177a5cSEmil Constantinescu 6143d177a5cSEmil Constantinescu Input Parameters: 615bcf0153eSBarry Smith + ts - the `TS` context 6163d177a5cSEmil Constantinescu - type - a method 6173d177a5cSEmil Constantinescu 6183d177a5cSEmil Constantinescu Options Database Key: 6193d177a5cSEmil Constantinescu . -ts_gl_type <type> - sets the method, use -help for a list of available method (e.g. irks) 6203d177a5cSEmil Constantinescu 621bcf0153eSBarry Smith Level: intermediate 622bcf0153eSBarry Smith 6233d177a5cSEmil Constantinescu Notes: 6243d177a5cSEmil Constantinescu See "petsc/include/petscts.h" for available methods (for instance) 6253d177a5cSEmil Constantinescu . TSGLLE_IRKS - Diagonally implicit methods with inherent Runge-Kutta stability (for stiff problems) 6263d177a5cSEmil Constantinescu 627*14d0ab18SJacob Faibussowitsch Normally, it is best to use the `TSSetFromOptions()` command and then set the `TSGLLE` type 628*14d0ab18SJacob Faibussowitsch from the options database rather than by using this routine. Using the options database 629*14d0ab18SJacob Faibussowitsch provides the user with maximum flexibility in evaluating the many different solvers. The 630*14d0ab18SJacob Faibussowitsch `TSGLLESetType()` routine is provided for those situations where it is necessary to set the 631*14d0ab18SJacob Faibussowitsch timestepping solver independently of the command line or options database. This might be the 632*14d0ab18SJacob Faibussowitsch case, for example, when the choice of solver changes during the execution of the program, and 633*14d0ab18SJacob Faibussowitsch the user's application is taking responsibility for choosing the appropriate method. 6343d177a5cSEmil Constantinescu 6351cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSGLLEType`, `TSGLLE` 6363d177a5cSEmil Constantinescu @*/ 637d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGLLESetType(TS ts, TSGLLEType type) 638d71ae5a4SJacob Faibussowitsch { 6393d177a5cSEmil Constantinescu PetscFunctionBegin; 6403d177a5cSEmil Constantinescu PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 6414f572ea9SToby Isaac PetscAssertPointer(type, 2); 642cac4c232SBarry Smith PetscTryMethod(ts, "TSGLLESetType_C", (TS, TSGLLEType), (ts, type)); 6433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6443d177a5cSEmil Constantinescu } 6453d177a5cSEmil Constantinescu 6463d177a5cSEmil Constantinescu /*@C 647bcf0153eSBarry Smith TSGLLESetAcceptType - sets the acceptance test for `TSGLLE` 6483d177a5cSEmil Constantinescu 649c3339decSBarry Smith Logically Collective 6503d177a5cSEmil Constantinescu 6513d177a5cSEmil Constantinescu Input Parameters: 652bcf0153eSBarry Smith + ts - the `TS` context 6533d177a5cSEmil Constantinescu - type - the type 6543d177a5cSEmil Constantinescu 6553d177a5cSEmil Constantinescu Options Database Key: 6563d177a5cSEmil Constantinescu . -ts_gl_accept_type <type> - sets the method used to determine whether to accept or reject a step 6573d177a5cSEmil Constantinescu 6583d177a5cSEmil Constantinescu Level: intermediate 6593d177a5cSEmil Constantinescu 660*14d0ab18SJacob Faibussowitsch Notes: 661*14d0ab18SJacob Faibussowitsch Time integrators that need to control error must have the option to reject a time step based 662*14d0ab18SJacob Faibussowitsch on local error estimates. This function allows different schemes to be set. 663*14d0ab18SJacob Faibussowitsch 6641cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSGLLE`, `TSGLLEAcceptRegister()`, `TSGLLEAdapt` 6653d177a5cSEmil Constantinescu @*/ 666d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGLLESetAcceptType(TS ts, TSGLLEAcceptType type) 667d71ae5a4SJacob Faibussowitsch { 6683d177a5cSEmil Constantinescu PetscFunctionBegin; 6693d177a5cSEmil Constantinescu PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 6704f572ea9SToby Isaac PetscAssertPointer(type, 2); 671cac4c232SBarry Smith PetscTryMethod(ts, "TSGLLESetAcceptType_C", (TS, TSGLLEAcceptType), (ts, type)); 6723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6733d177a5cSEmil Constantinescu } 6743d177a5cSEmil Constantinescu 6753d177a5cSEmil Constantinescu /*@C 676bcf0153eSBarry Smith TSGLLEGetAdapt - gets the `TSGLLEAdapt` object from the `TS` 6773d177a5cSEmil Constantinescu 6783d177a5cSEmil Constantinescu Not Collective 6793d177a5cSEmil Constantinescu 6803d177a5cSEmil Constantinescu Input Parameter: 681bcf0153eSBarry Smith . ts - the `TS` context 6823d177a5cSEmil Constantinescu 6833d177a5cSEmil Constantinescu Output Parameter: 684bcf0153eSBarry Smith . adapt - the `TSGLLEAdapt` context 6853d177a5cSEmil Constantinescu 6863d177a5cSEmil Constantinescu Level: advanced 6873d177a5cSEmil Constantinescu 688bcf0153eSBarry Smith Note: 689*14d0ab18SJacob Faibussowitsch This allows the user set options on the `TSGLLEAdapt` object. Usually it is better to do this 690*14d0ab18SJacob Faibussowitsch using the options database, so this function is rarely needed. 691bcf0153eSBarry Smith 6921cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSGLLE`, `TSGLLEAdapt`, `TSGLLEAdaptRegister()` 6933d177a5cSEmil Constantinescu @*/ 694d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGLLEGetAdapt(TS ts, TSGLLEAdapt *adapt) 695d71ae5a4SJacob Faibussowitsch { 6963d177a5cSEmil Constantinescu PetscFunctionBegin; 6973d177a5cSEmil Constantinescu PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 6984f572ea9SToby Isaac PetscAssertPointer(adapt, 2); 699cac4c232SBarry Smith PetscUseMethod(ts, "TSGLLEGetAdapt_C", (TS, TSGLLEAdapt *), (ts, adapt)); 7003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7013d177a5cSEmil Constantinescu } 7023d177a5cSEmil Constantinescu 703d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGLLEAccept_Always(TS ts, PetscReal tleft, PetscReal h, const PetscReal enorms[], PetscBool *accept) 704d71ae5a4SJacob Faibussowitsch { 7053d177a5cSEmil Constantinescu PetscFunctionBegin; 7063d177a5cSEmil Constantinescu *accept = PETSC_TRUE; 7073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7083d177a5cSEmil Constantinescu } 7093d177a5cSEmil Constantinescu 710d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGLLEUpdateWRMS(TS ts) 711d71ae5a4SJacob Faibussowitsch { 7123d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 7133d177a5cSEmil Constantinescu PetscScalar *x, *w; 7143d177a5cSEmil Constantinescu PetscInt n, i; 7153d177a5cSEmil Constantinescu 7163d177a5cSEmil Constantinescu PetscFunctionBegin; 7179566063dSJacob Faibussowitsch PetscCall(VecGetArray(gl->X[0], &x)); 7189566063dSJacob Faibussowitsch PetscCall(VecGetArray(gl->W, &w)); 7199566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(gl->W, &n)); 7203d177a5cSEmil Constantinescu for (i = 0; i < n; i++) w[i] = 1. / (gl->wrms_atol + gl->wrms_rtol * PetscAbsScalar(x[i])); 7219566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(gl->X[0], &x)); 7229566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(gl->W, &w)); 7233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7243d177a5cSEmil Constantinescu } 7253d177a5cSEmil Constantinescu 726d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGLLEVecNormWRMS(TS ts, Vec X, PetscReal *nrm) 727d71ae5a4SJacob Faibussowitsch { 7283d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 7293d177a5cSEmil Constantinescu PetscScalar *x, *w; 7303d177a5cSEmil Constantinescu PetscReal sum = 0.0, gsum; 7313d177a5cSEmil Constantinescu PetscInt n, N, i; 7323d177a5cSEmil Constantinescu 7333d177a5cSEmil Constantinescu PetscFunctionBegin; 7349566063dSJacob Faibussowitsch PetscCall(VecGetArray(X, &x)); 7359566063dSJacob Faibussowitsch PetscCall(VecGetArray(gl->W, &w)); 7369566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(gl->W, &n)); 7373d177a5cSEmil Constantinescu for (i = 0; i < n; i++) sum += PetscAbsScalar(PetscSqr(x[i] * w[i])); 7389566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(X, &x)); 7399566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(gl->W, &w)); 7401c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&sum, &gsum, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)ts))); 7419566063dSJacob Faibussowitsch PetscCall(VecGetSize(gl->W, &N)); 7423d177a5cSEmil Constantinescu *nrm = PetscSqrtReal(gsum / (1. * N)); 7433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7443d177a5cSEmil Constantinescu } 7453d177a5cSEmil Constantinescu 746d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGLLESetType_GLLE(TS ts, TSGLLEType type) 747d71ae5a4SJacob Faibussowitsch { 7483d177a5cSEmil Constantinescu PetscBool same; 7493d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 7505f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(TS); 7513d177a5cSEmil Constantinescu 7523d177a5cSEmil Constantinescu PetscFunctionBegin; 7533d177a5cSEmil Constantinescu if (gl->type_name[0]) { 7549566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(gl->type_name, type, &same)); 7553ba16761SJacob Faibussowitsch if (same) PetscFunctionReturn(PETSC_SUCCESS); 7569566063dSJacob Faibussowitsch PetscCall((*gl->Destroy)(gl)); 7573d177a5cSEmil Constantinescu } 7583d177a5cSEmil Constantinescu 7599566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(TSGLLEList, type, &r)); 7606adde796SStefano Zampini PetscCheck(r, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown TSGLLE type \"%s\" given", type); 7619566063dSJacob Faibussowitsch PetscCall((*r)(ts)); 762c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(gl->type_name, type, sizeof(gl->type_name))); 7633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7643d177a5cSEmil Constantinescu } 7653d177a5cSEmil Constantinescu 766d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGLLESetAcceptType_GLLE(TS ts, TSGLLEAcceptType type) 767d71ae5a4SJacob Faibussowitsch { 7683d177a5cSEmil Constantinescu TSGLLEAcceptFunction r; 7693d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 7703d177a5cSEmil Constantinescu 7713d177a5cSEmil Constantinescu PetscFunctionBegin; 7729566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(TSGLLEAcceptList, type, &r)); 7736adde796SStefano Zampini PetscCheck(r, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown TSGLLEAccept type \"%s\" given", type); 7743d177a5cSEmil Constantinescu gl->Accept = r; 7759566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(gl->accept_name, type, sizeof(gl->accept_name))); 7763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7773d177a5cSEmil Constantinescu } 7783d177a5cSEmil Constantinescu 779d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGLLEGetAdapt_GLLE(TS ts, TSGLLEAdapt *adapt) 780d71ae5a4SJacob Faibussowitsch { 7813d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 7823d177a5cSEmil Constantinescu 7833d177a5cSEmil Constantinescu PetscFunctionBegin; 7843d177a5cSEmil Constantinescu if (!gl->adapt) { 7859566063dSJacob Faibussowitsch PetscCall(TSGLLEAdaptCreate(PetscObjectComm((PetscObject)ts), &gl->adapt)); 7869566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)gl->adapt, (PetscObject)ts, 1)); 7873d177a5cSEmil Constantinescu } 7883d177a5cSEmil Constantinescu *adapt = gl->adapt; 7893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7903d177a5cSEmil Constantinescu } 7913d177a5cSEmil Constantinescu 792d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGLLEChooseNextScheme(TS ts, PetscReal h, const PetscReal hmnorm[], PetscInt *next_scheme, PetscReal *next_h, PetscBool *finish) 793d71ae5a4SJacob Faibussowitsch { 7943d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 7953d177a5cSEmil Constantinescu PetscInt i, n, cur_p, cur, next_sc, candidates[64], orders[64]; 7963d177a5cSEmil Constantinescu PetscReal errors[64], costs[64], tleft; 7973d177a5cSEmil Constantinescu 7983d177a5cSEmil Constantinescu PetscFunctionBegin; 7993d177a5cSEmil Constantinescu cur = -1; 8003d177a5cSEmil Constantinescu cur_p = gl->schemes[gl->current_scheme]->p; 8013d177a5cSEmil Constantinescu tleft = ts->max_time - (ts->ptime + ts->time_step); 8023d177a5cSEmil Constantinescu for (i = 0, n = 0; i < gl->nschemes; i++) { 8033d177a5cSEmil Constantinescu TSGLLEScheme sc = gl->schemes[i]; 8043d177a5cSEmil Constantinescu if (sc->p < gl->min_order || gl->max_order < sc->p) continue; 8053d177a5cSEmil Constantinescu if (sc->p == cur_p - 1) errors[n] = PetscAbsScalar(sc->alpha[0]) * hmnorm[0]; 8063d177a5cSEmil Constantinescu else if (sc->p == cur_p) errors[n] = PetscAbsScalar(sc->alpha[0]) * hmnorm[1]; 8073d177a5cSEmil Constantinescu else if (sc->p == cur_p + 1) errors[n] = PetscAbsScalar(sc->alpha[0]) * (hmnorm[2] + hmnorm[3]); 8083d177a5cSEmil Constantinescu else continue; 8093d177a5cSEmil Constantinescu candidates[n] = i; 8103d177a5cSEmil Constantinescu orders[n] = PetscMin(sc->p, sc->q); /* order of global truncation error */ 8113d177a5cSEmil Constantinescu costs[n] = sc->s; /* estimate the cost as the number of stages */ 8123d177a5cSEmil Constantinescu if (i == gl->current_scheme) cur = n; 8133d177a5cSEmil Constantinescu n++; 8143d177a5cSEmil Constantinescu } 815cad9d221SBarry Smith PetscCheck(cur >= 0 && gl->nschemes > cur, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Current scheme not found in scheme list"); 8169566063dSJacob Faibussowitsch PetscCall(TSGLLEAdaptChoose(gl->adapt, n, orders, errors, costs, cur, h, tleft, &next_sc, next_h, finish)); 8173d177a5cSEmil Constantinescu *next_scheme = candidates[next_sc]; 8189371c9d4SSatish 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, 8199371c9d4SSatish Balay gl->schemes[*next_scheme]->r, gl->schemes[*next_scheme]->s, (double)*next_h, PetscBools[*finish])); 8203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8213d177a5cSEmil Constantinescu } 8223d177a5cSEmil Constantinescu 823d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGLLEGetMaxSizes(TS ts, PetscInt *max_r, PetscInt *max_s) 824d71ae5a4SJacob Faibussowitsch { 8253d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 8263d177a5cSEmil Constantinescu 8273d177a5cSEmil Constantinescu PetscFunctionBegin; 8283d177a5cSEmil Constantinescu *max_r = gl->schemes[gl->nschemes - 1]->r; 8293d177a5cSEmil Constantinescu *max_s = gl->schemes[gl->nschemes - 1]->s; 8303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8313d177a5cSEmil Constantinescu } 8323d177a5cSEmil Constantinescu 833d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSSolve_GLLE(TS ts) 834d71ae5a4SJacob Faibussowitsch { 8353d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 8363d177a5cSEmil Constantinescu PetscInt i, k, its, lits, max_r, max_s; 8373d177a5cSEmil Constantinescu PetscBool final_step, finish; 8383d177a5cSEmil Constantinescu SNESConvergedReason snesreason; 8393d177a5cSEmil Constantinescu 8403d177a5cSEmil Constantinescu PetscFunctionBegin; 8419566063dSJacob Faibussowitsch PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol)); 8423d177a5cSEmil Constantinescu 8439566063dSJacob Faibussowitsch PetscCall(TSGLLEGetMaxSizes(ts, &max_r, &max_s)); 8449566063dSJacob Faibussowitsch PetscCall(VecCopy(ts->vec_sol, gl->X[0])); 84548a46eb9SPierre Jolivet for (i = 1; i < max_r; i++) PetscCall(VecZeroEntries(gl->X[i])); 8469566063dSJacob Faibussowitsch PetscCall(TSGLLEUpdateWRMS(ts)); 8473d177a5cSEmil Constantinescu 8483d177a5cSEmil Constantinescu if (0) { 8493d177a5cSEmil Constantinescu /* Find consistent initial data for DAE */ 8503d177a5cSEmil Constantinescu gl->stage_time = ts->ptime + ts->time_step; 8513d177a5cSEmil Constantinescu gl->scoeff = 1.; 8523d177a5cSEmil Constantinescu gl->stage = 0; 8533d177a5cSEmil Constantinescu 8549566063dSJacob Faibussowitsch PetscCall(VecCopy(ts->vec_sol, gl->Z)); 8559566063dSJacob Faibussowitsch PetscCall(VecCopy(ts->vec_sol, gl->Y)); 8569566063dSJacob Faibussowitsch PetscCall(SNESSolve(ts->snes, NULL, gl->Y)); 8579566063dSJacob Faibussowitsch PetscCall(SNESGetIterationNumber(ts->snes, &its)); 8589566063dSJacob Faibussowitsch PetscCall(SNESGetLinearSolveIterations(ts->snes, &lits)); 8599566063dSJacob Faibussowitsch PetscCall(SNESGetConvergedReason(ts->snes, &snesreason)); 8603d177a5cSEmil Constantinescu 8619371c9d4SSatish Balay ts->snes_its += its; 8629371c9d4SSatish Balay ts->ksp_its += lits; 8633d177a5cSEmil Constantinescu if (snesreason < 0 && ts->max_snes_failures > 0 && ++ts->num_snes_failures >= ts->max_snes_failures) { 8643d177a5cSEmil Constantinescu ts->reason = TS_DIVERGED_NONLINEAR_SOLVE; 86563a3b9bcSJacob 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)); 8663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8673d177a5cSEmil Constantinescu } 8683d177a5cSEmil Constantinescu } 8693d177a5cSEmil Constantinescu 87008401ef6SPierre Jolivet PetscCheck(gl->current_scheme >= 0, PETSC_COMM_SELF, PETSC_ERR_ORDER, "A starting scheme has not been provided"); 8713d177a5cSEmil Constantinescu 8723d177a5cSEmil Constantinescu for (k = 0, final_step = PETSC_FALSE, finish = PETSC_FALSE; k < ts->max_steps && !finish; k++) { 8733d177a5cSEmil Constantinescu PetscInt j, r, s, next_scheme = 0, rejections; 8743d177a5cSEmil Constantinescu PetscReal h, hmnorm[4], enorm[3], next_h; 8753d177a5cSEmil Constantinescu PetscBool accept; 8763d177a5cSEmil Constantinescu const PetscScalar *c, *a, *u; 8773d177a5cSEmil Constantinescu Vec *X, *Ydot, Y; 8783d177a5cSEmil Constantinescu TSGLLEScheme scheme = gl->schemes[gl->current_scheme]; 8793d177a5cSEmil Constantinescu 8809371c9d4SSatish Balay r = scheme->r; 8819371c9d4SSatish Balay s = scheme->s; 8823d177a5cSEmil Constantinescu c = scheme->c; 8839371c9d4SSatish Balay a = scheme->a; 8849371c9d4SSatish Balay u = scheme->u; 8853d177a5cSEmil Constantinescu h = ts->time_step; 8869371c9d4SSatish Balay X = gl->X; 8879371c9d4SSatish Balay Ydot = gl->Ydot; 8889371c9d4SSatish Balay Y = gl->Y; 8893d177a5cSEmil Constantinescu 8903d177a5cSEmil Constantinescu if (ts->ptime > ts->max_time) break; 8913d177a5cSEmil Constantinescu 8923d177a5cSEmil Constantinescu /* 8933d177a5cSEmil Constantinescu We only call PreStep at the start of each STEP, not each STAGE. This is because it is 8943d177a5cSEmil Constantinescu possible to fail (have to restart a step) after multiple stages. 8953d177a5cSEmil Constantinescu */ 8969566063dSJacob Faibussowitsch PetscCall(TSPreStep(ts)); 8973d177a5cSEmil Constantinescu 8983d177a5cSEmil Constantinescu rejections = 0; 8993d177a5cSEmil Constantinescu while (1) { 9003d177a5cSEmil Constantinescu for (i = 0; i < s; i++) { 9013d177a5cSEmil Constantinescu PetscScalar shift; 9023d177a5cSEmil Constantinescu gl->scoeff = 1. / PetscRealPart(a[i * s + i]); 9033d177a5cSEmil Constantinescu shift = gl->scoeff / ts->time_step; 9043d177a5cSEmil Constantinescu gl->stage = i; 9053d177a5cSEmil Constantinescu gl->stage_time = ts->ptime + PetscRealPart(c[i]) * h; 9063d177a5cSEmil Constantinescu 9073d177a5cSEmil Constantinescu /* 9083d177a5cSEmil Constantinescu * Stage equation: Y = h A Y' + U X 9093d177a5cSEmil Constantinescu * We assume that A is lower-triangular so that we can solve the stages (Y,Y') sequentially 9103d177a5cSEmil Constantinescu * Build the affine vector z_i = -[1/(h a_ii)](h sum_j a_ij y'_j + sum_j u_ij x_j) 9113d177a5cSEmil Constantinescu * Then y'_i = z + 1/(h a_ii) y_i 9123d177a5cSEmil Constantinescu */ 9139566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(gl->Z)); 91448a46eb9SPierre Jolivet for (j = 0; j < r; j++) PetscCall(VecAXPY(gl->Z, -shift * u[i * r + j], X[j])); 91548a46eb9SPierre Jolivet for (j = 0; j < i; j++) PetscCall(VecAXPY(gl->Z, -shift * h * a[i * s + j], Ydot[j])); 9163d177a5cSEmil Constantinescu /* Note: Z is used within function evaluation, Ydot = Z + shift*Y */ 9173d177a5cSEmil Constantinescu 9183d177a5cSEmil Constantinescu /* Compute an estimate of Y to start Newton iteration */ 9193d177a5cSEmil Constantinescu if (gl->extrapolate) { 9203d177a5cSEmil Constantinescu if (i == 0) { 9213d177a5cSEmil Constantinescu /* Linear extrapolation on the first stage */ 9229566063dSJacob Faibussowitsch PetscCall(VecWAXPY(Y, c[i] * h, X[1], X[0])); 9233d177a5cSEmil Constantinescu } else { 9243d177a5cSEmil Constantinescu /* Linear extrapolation from the last stage */ 9259566063dSJacob Faibussowitsch PetscCall(VecAXPY(Y, (c[i] - c[i - 1]) * h, Ydot[i - 1])); 9263d177a5cSEmil Constantinescu } 9273d177a5cSEmil Constantinescu } else if (i == 0) { /* Directly use solution from the last step, otherwise reuse the last stage (do nothing) */ 9289566063dSJacob Faibussowitsch PetscCall(VecCopy(X[0], Y)); 9293d177a5cSEmil Constantinescu } 9303d177a5cSEmil Constantinescu 9313d177a5cSEmil Constantinescu /* Solve this stage (Ydot[i] is computed during function evaluation) */ 9329566063dSJacob Faibussowitsch PetscCall(SNESSolve(ts->snes, NULL, Y)); 9339566063dSJacob Faibussowitsch PetscCall(SNESGetIterationNumber(ts->snes, &its)); 9349566063dSJacob Faibussowitsch PetscCall(SNESGetLinearSolveIterations(ts->snes, &lits)); 9359566063dSJacob Faibussowitsch PetscCall(SNESGetConvergedReason(ts->snes, &snesreason)); 9369371c9d4SSatish Balay ts->snes_its += its; 9379371c9d4SSatish Balay ts->ksp_its += lits; 9383d177a5cSEmil Constantinescu if (snesreason < 0 && ts->max_snes_failures > 0 && ++ts->num_snes_failures >= ts->max_snes_failures) { 9393d177a5cSEmil Constantinescu ts->reason = TS_DIVERGED_NONLINEAR_SOLVE; 94063a3b9bcSJacob 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)); 9413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9423d177a5cSEmil Constantinescu } 9433d177a5cSEmil Constantinescu } 9443d177a5cSEmil Constantinescu 9453d177a5cSEmil Constantinescu gl->stage_time = ts->ptime + ts->time_step; 9463d177a5cSEmil Constantinescu 9479566063dSJacob Faibussowitsch PetscCall((*gl->EstimateHigherMoments)(scheme, h, Ydot, gl->X, gl->himom)); 9483d177a5cSEmil Constantinescu /* hmnorm[i] = h^{p+i}x^{(p+i)} with i=0,1,2; hmnorm[3] = h^{p+2}(dx'/dx) x^{(p+1)} */ 94948a46eb9SPierre Jolivet for (i = 0; i < 3; i++) PetscCall(TSGLLEVecNormWRMS(ts, gl->himom[i], &hmnorm[i + 1])); 9503d177a5cSEmil Constantinescu enorm[0] = PetscRealPart(scheme->alpha[0]) * hmnorm[1]; 9513d177a5cSEmil Constantinescu enorm[1] = PetscRealPart(scheme->beta[0]) * hmnorm[2]; 9523d177a5cSEmil Constantinescu enorm[2] = PetscRealPart(scheme->gamma[0]) * hmnorm[3]; 9539566063dSJacob Faibussowitsch PetscCall((*gl->Accept)(ts, ts->max_time - gl->stage_time, h, enorm, &accept)); 9543d177a5cSEmil Constantinescu if (accept) goto accepted; 9553d177a5cSEmil Constantinescu rejections++; 95663a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(ts, "Step %" PetscInt_FMT " (t=%g) not accepted, rejections=%" PetscInt_FMT "\n", k, (double)gl->stage_time, rejections)); 9573d177a5cSEmil Constantinescu if (rejections > gl->max_step_rejections) break; 9583d177a5cSEmil Constantinescu /* 9593d177a5cSEmil Constantinescu There are lots of reasons why a step might be rejected, including solvers not converging and other factors that 9603d177a5cSEmil Constantinescu TSGLLEChooseNextScheme does not support. Additionally, the error estimates may be very screwed up, so I'm not 9613d177a5cSEmil Constantinescu convinced that it's safe to just compute a new error estimate using the same interface as the current adaptor 9623d177a5cSEmil Constantinescu (the adaptor interface probably has to change). Here we make an arbitrary and naive choice. This assumes that 9633d177a5cSEmil Constantinescu steps were written in Nordsieck form. The "correct" method would be to re-complete the previous time step with 9643d177a5cSEmil Constantinescu the correct "next" step size. It is unclear to me whether the present ad-hoc method of rescaling X is stable. 9653d177a5cSEmil Constantinescu */ 9663d177a5cSEmil Constantinescu h *= 0.5; 96748a46eb9SPierre Jolivet for (i = 1; i < scheme->r; i++) PetscCall(VecScale(X[i], PetscPowRealInt(0.5, i))); 9683d177a5cSEmil Constantinescu } 96963a3b9bcSJacob 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); 9703d177a5cSEmil Constantinescu 9713d177a5cSEmil Constantinescu accepted: 9723d177a5cSEmil Constantinescu /* This term is not error, but it *would* be the leading term for a lower order method */ 9739566063dSJacob Faibussowitsch PetscCall(TSGLLEVecNormWRMS(ts, gl->X[scheme->r - 1], &hmnorm[0])); 9743d177a5cSEmil Constantinescu /* Correct scaling so that these are equivalent to norms of the Nordsieck vectors */ 9753d177a5cSEmil Constantinescu 97663a3b9bcSJacob 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])); 9773d177a5cSEmil Constantinescu if (!final_step) { 9789566063dSJacob Faibussowitsch PetscCall(TSGLLEChooseNextScheme(ts, h, hmnorm, &next_scheme, &next_h, &final_step)); 9793d177a5cSEmil Constantinescu } else { 9803d177a5cSEmil Constantinescu /* Dummy values to complete the current step in a consistent manner */ 9813d177a5cSEmil Constantinescu next_scheme = gl->current_scheme; 9823d177a5cSEmil Constantinescu next_h = h; 9833d177a5cSEmil Constantinescu finish = PETSC_TRUE; 9843d177a5cSEmil Constantinescu } 9853d177a5cSEmil Constantinescu 9863d177a5cSEmil Constantinescu X = gl->Xold; 9873d177a5cSEmil Constantinescu gl->Xold = gl->X; 9883d177a5cSEmil Constantinescu gl->X = X; 9899566063dSJacob Faibussowitsch PetscCall((*gl->CompleteStep)(scheme, h, gl->schemes[next_scheme], next_h, Ydot, gl->Xold, gl->X)); 9903d177a5cSEmil Constantinescu 9919566063dSJacob Faibussowitsch PetscCall(TSGLLEUpdateWRMS(ts)); 9923d177a5cSEmil Constantinescu 9933d177a5cSEmil Constantinescu /* Post the solution for the user, we could avoid this copy with a small bit of cleverness */ 9949566063dSJacob Faibussowitsch PetscCall(VecCopy(gl->X[0], ts->vec_sol)); 9953d177a5cSEmil Constantinescu ts->ptime += h; 9963d177a5cSEmil Constantinescu ts->steps++; 9973d177a5cSEmil Constantinescu 9989566063dSJacob Faibussowitsch PetscCall(TSPostEvaluate(ts)); 9999566063dSJacob Faibussowitsch PetscCall(TSPostStep(ts)); 10009566063dSJacob Faibussowitsch PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol)); 10013d177a5cSEmil Constantinescu 10023d177a5cSEmil Constantinescu gl->current_scheme = next_scheme; 10033d177a5cSEmil Constantinescu ts->time_step = next_h; 10043d177a5cSEmil Constantinescu } 10053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10063d177a5cSEmil Constantinescu } 10073d177a5cSEmil Constantinescu 10083d177a5cSEmil Constantinescu /*------------------------------------------------------------*/ 10093d177a5cSEmil Constantinescu 1010d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSReset_GLLE(TS ts) 1011d71ae5a4SJacob Faibussowitsch { 10123d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 10133d177a5cSEmil Constantinescu PetscInt max_r, max_s; 10143d177a5cSEmil Constantinescu 10153d177a5cSEmil Constantinescu PetscFunctionBegin; 10163d177a5cSEmil Constantinescu if (gl->setupcalled) { 10179566063dSJacob Faibussowitsch PetscCall(TSGLLEGetMaxSizes(ts, &max_r, &max_s)); 10189566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(max_r, &gl->Xold)); 10199566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(max_r, &gl->X)); 10209566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(max_s, &gl->Ydot)); 10219566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(3, &gl->himom)); 10229566063dSJacob Faibussowitsch PetscCall(VecDestroy(&gl->W)); 10239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&gl->Y)); 10249566063dSJacob Faibussowitsch PetscCall(VecDestroy(&gl->Z)); 10253d177a5cSEmil Constantinescu } 10263d177a5cSEmil Constantinescu gl->setupcalled = PETSC_FALSE; 10273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10283d177a5cSEmil Constantinescu } 10293d177a5cSEmil Constantinescu 1030d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSDestroy_GLLE(TS ts) 1031d71ae5a4SJacob Faibussowitsch { 10323d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 10333d177a5cSEmil Constantinescu 10343d177a5cSEmil Constantinescu PetscFunctionBegin; 10359566063dSJacob Faibussowitsch PetscCall(TSReset_GLLE(ts)); 1036b3a6b972SJed Brown if (ts->dm) { 10379566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookRemove(ts->dm, DMCoarsenHook_TSGLLE, DMRestrictHook_TSGLLE, ts)); 10389566063dSJacob Faibussowitsch PetscCall(DMSubDomainHookRemove(ts->dm, DMSubDomainHook_TSGLLE, DMSubDomainRestrictHook_TSGLLE, ts)); 1039b3a6b972SJed Brown } 10409566063dSJacob Faibussowitsch if (gl->adapt) PetscCall(TSGLLEAdaptDestroy(&gl->adapt)); 10419566063dSJacob Faibussowitsch if (gl->Destroy) PetscCall((*gl->Destroy)(gl)); 10429566063dSJacob Faibussowitsch PetscCall(PetscFree(ts->data)); 10439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSGLLESetType_C", NULL)); 10449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSGLLESetAcceptType_C", NULL)); 10459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSGLLEGetAdapt_C", NULL)); 10463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10473d177a5cSEmil Constantinescu } 10483d177a5cSEmil Constantinescu 10493d177a5cSEmil Constantinescu /* 10503d177a5cSEmil Constantinescu This defines the nonlinear equation that is to be solved with SNES 10513d177a5cSEmil Constantinescu g(x) = f(t,x,z+shift*x) = 0 10523d177a5cSEmil Constantinescu */ 1053d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESTSFormFunction_GLLE(SNES snes, Vec x, Vec f, TS ts) 1054d71ae5a4SJacob Faibussowitsch { 10553d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 10563d177a5cSEmil Constantinescu Vec Z, Ydot; 10573d177a5cSEmil Constantinescu DM dm, dmsave; 10583d177a5cSEmil Constantinescu 10593d177a5cSEmil Constantinescu PetscFunctionBegin; 10609566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 10619566063dSJacob Faibussowitsch PetscCall(TSGLLEGetVecs(ts, dm, &Z, &Ydot)); 10629566063dSJacob Faibussowitsch PetscCall(VecWAXPY(Ydot, gl->scoeff / ts->time_step, x, Z)); 10633d177a5cSEmil Constantinescu dmsave = ts->dm; 10643d177a5cSEmil Constantinescu ts->dm = dm; 10659566063dSJacob Faibussowitsch PetscCall(TSComputeIFunction(ts, gl->stage_time, x, Ydot, f, PETSC_FALSE)); 10663d177a5cSEmil Constantinescu ts->dm = dmsave; 10679566063dSJacob Faibussowitsch PetscCall(TSGLLERestoreVecs(ts, dm, &Z, &Ydot)); 10683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10693d177a5cSEmil Constantinescu } 10703d177a5cSEmil Constantinescu 1071d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESTSFormJacobian_GLLE(SNES snes, Vec x, Mat A, Mat B, TS ts) 1072d71ae5a4SJacob Faibussowitsch { 10733d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 10743d177a5cSEmil Constantinescu Vec Z, Ydot; 10753d177a5cSEmil Constantinescu DM dm, dmsave; 10763d177a5cSEmil Constantinescu 10773d177a5cSEmil Constantinescu PetscFunctionBegin; 10789566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 10799566063dSJacob Faibussowitsch PetscCall(TSGLLEGetVecs(ts, dm, &Z, &Ydot)); 10803d177a5cSEmil Constantinescu dmsave = ts->dm; 10813d177a5cSEmil Constantinescu ts->dm = dm; 10823d177a5cSEmil Constantinescu /* gl->Xdot will have already been computed in SNESTSFormFunction_GLLE */ 10839566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobian(ts, gl->stage_time, x, gl->Ydot[gl->stage], gl->scoeff / ts->time_step, A, B, PETSC_FALSE)); 10843d177a5cSEmil Constantinescu ts->dm = dmsave; 10859566063dSJacob Faibussowitsch PetscCall(TSGLLERestoreVecs(ts, dm, &Z, &Ydot)); 10863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10873d177a5cSEmil Constantinescu } 10883d177a5cSEmil Constantinescu 1089d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSSetUp_GLLE(TS ts) 1090d71ae5a4SJacob Faibussowitsch { 10913d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 10923d177a5cSEmil Constantinescu PetscInt max_r, max_s; 10933d177a5cSEmil Constantinescu DM dm; 10943d177a5cSEmil Constantinescu 10953d177a5cSEmil Constantinescu PetscFunctionBegin; 10963d177a5cSEmil Constantinescu gl->setupcalled = PETSC_TRUE; 10979566063dSJacob Faibussowitsch PetscCall(TSGLLEGetMaxSizes(ts, &max_r, &max_s)); 10989566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vec_sol, max_r, &gl->X)); 10999566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vec_sol, max_r, &gl->Xold)); 11009566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vec_sol, max_s, &gl->Ydot)); 11019566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vec_sol, 3, &gl->himom)); 11029566063dSJacob Faibussowitsch PetscCall(VecDuplicate(ts->vec_sol, &gl->W)); 11039566063dSJacob Faibussowitsch PetscCall(VecDuplicate(ts->vec_sol, &gl->Y)); 11049566063dSJacob Faibussowitsch PetscCall(VecDuplicate(ts->vec_sol, &gl->Z)); 11053d177a5cSEmil Constantinescu 11063d177a5cSEmil Constantinescu /* Default acceptance tests and adaptivity */ 11079566063dSJacob Faibussowitsch if (!gl->Accept) PetscCall(TSGLLESetAcceptType(ts, TSGLLEACCEPT_ALWAYS)); 11089566063dSJacob Faibussowitsch if (!gl->adapt) PetscCall(TSGLLEGetAdapt(ts, &gl->adapt)); 11093d177a5cSEmil Constantinescu 11103d177a5cSEmil Constantinescu if (gl->current_scheme < 0) { 11113d177a5cSEmil Constantinescu PetscInt i; 11123d177a5cSEmil Constantinescu for (i = 0;; i++) { 11133d177a5cSEmil Constantinescu if (gl->schemes[i]->p == gl->start_order) break; 111463a3b9bcSJacob Faibussowitsch PetscCheck(i + 1 != gl->nschemes, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No schemes available with requested start order %" PetscInt_FMT, i); 11153d177a5cSEmil Constantinescu } 11163d177a5cSEmil Constantinescu gl->current_scheme = i; 11173d177a5cSEmil Constantinescu } 11189566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &dm)); 11199566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(dm, DMCoarsenHook_TSGLLE, DMRestrictHook_TSGLLE, ts)); 11209566063dSJacob Faibussowitsch PetscCall(DMSubDomainHookAdd(dm, DMSubDomainHook_TSGLLE, DMSubDomainRestrictHook_TSGLLE, ts)); 11213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11223d177a5cSEmil Constantinescu } 11233d177a5cSEmil Constantinescu /*------------------------------------------------------------*/ 11243d177a5cSEmil Constantinescu 1125d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSSetFromOptions_GLLE(TS ts, PetscOptionItems *PetscOptionsObject) 1126d71ae5a4SJacob Faibussowitsch { 11273d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 11283d177a5cSEmil Constantinescu char tname[256] = TSGLLE_IRKS, completef[256] = "rescale-and-modify"; 11293d177a5cSEmil Constantinescu 11303d177a5cSEmil Constantinescu PetscFunctionBegin; 1131d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "General Linear ODE solver options"); 11323d177a5cSEmil Constantinescu { 11333d177a5cSEmil Constantinescu PetscBool flg; 11349566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-ts_gl_type", "Type of GL method", "TSGLLESetType", TSGLLEList, gl->type_name[0] ? gl->type_name : tname, tname, sizeof(tname), &flg)); 113548a46eb9SPierre Jolivet if (flg || !gl->type_name[0]) PetscCall(TSGLLESetType(ts, tname)); 11369566063dSJacob 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)); 11379566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-ts_gl_max_order", "Maximum order to try", "TSGLLESetMaxOrder", gl->max_order, &gl->max_order, NULL)); 11389566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-ts_gl_min_order", "Minimum order to try", "TSGLLESetMinOrder", gl->min_order, &gl->min_order, NULL)); 11399566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-ts_gl_start_order", "Initial order to try", "TSGLLESetMinOrder", gl->start_order, &gl->start_order, NULL)); 11409566063dSJacob 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)); 11419566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-ts_gl_extrapolate", "Extrapolate stage solution from previous solution (sometimes unstable)", "TSGLLESetExtrapolate", gl->extrapolate, &gl->extrapolate, NULL)); 11429566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-ts_gl_atol", "Absolute tolerance", "TSGLLESetTolerances", gl->wrms_atol, &gl->wrms_atol, NULL)); 11439566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-ts_gl_rtol", "Relative tolerance", "TSGLLESetTolerances", gl->wrms_rtol, &gl->wrms_rtol, NULL)); 11449566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-ts_gl_complete", "Method to use for completing the step", "none", completef, completef, sizeof(completef), &flg)); 11453d177a5cSEmil Constantinescu if (flg) { 11463d177a5cSEmil Constantinescu PetscBool match1, match2; 11479566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(completef, "rescale", &match1)); 11489566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(completef, "rescale-and-modify", &match2)); 11493d177a5cSEmil Constantinescu if (match1) gl->CompleteStep = TSGLLECompleteStep_Rescale; 11503d177a5cSEmil Constantinescu else if (match2) gl->CompleteStep = TSGLLECompleteStep_RescaleAndModify; 11516adde796SStefano Zampini else SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_UNKNOWN_TYPE, "%s", completef); 11523d177a5cSEmil Constantinescu } 11533d177a5cSEmil Constantinescu { 11543d177a5cSEmil Constantinescu char type[256] = TSGLLEACCEPT_ALWAYS; 11559566063dSJacob 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)); 115648a46eb9SPierre Jolivet if (flg || !gl->accept_name[0]) PetscCall(TSGLLESetAcceptType(ts, type)); 11573d177a5cSEmil Constantinescu } 11583d177a5cSEmil Constantinescu { 11593d177a5cSEmil Constantinescu TSGLLEAdapt adapt; 11609566063dSJacob Faibussowitsch PetscCall(TSGLLEGetAdapt(ts, &adapt)); 1161dbbe0bcdSBarry Smith PetscCall(TSGLLEAdaptSetFromOptions(adapt, PetscOptionsObject)); 11623d177a5cSEmil Constantinescu } 11633d177a5cSEmil Constantinescu } 1164d0609cedSBarry Smith PetscOptionsHeadEnd(); 11653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11663d177a5cSEmil Constantinescu } 11673d177a5cSEmil Constantinescu 1168d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSView_GLLE(TS ts, PetscViewer viewer) 1169d71ae5a4SJacob Faibussowitsch { 11703d177a5cSEmil Constantinescu TS_GLLE *gl = (TS_GLLE *)ts->data; 11713d177a5cSEmil Constantinescu PetscInt i; 11723d177a5cSEmil Constantinescu PetscBool iascii, details; 11733d177a5cSEmil Constantinescu 11743d177a5cSEmil Constantinescu PetscFunctionBegin; 11759566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 11763d177a5cSEmil Constantinescu if (iascii) { 117763a3b9bcSJacob 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)); 11789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Error estimation: %s\n", TSGLLEErrorDirections[gl->error_direction])); 11799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Extrapolation: %s\n", gl->extrapolate ? "yes" : "no")); 11809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Acceptance test: %s\n", gl->accept_name[0] ? gl->accept_name : "(not yet set)")); 11819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 11829566063dSJacob Faibussowitsch PetscCall(TSGLLEAdaptView(gl->adapt, viewer)); 11839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 11849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " type: %s\n", gl->type_name[0] ? gl->type_name : "(not yet set)")); 118563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Schemes within family (%" PetscInt_FMT "):\n", gl->nschemes)); 11863d177a5cSEmil Constantinescu details = PETSC_FALSE; 11879566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_gl_view_detailed", &details, NULL)); 11889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 118948a46eb9SPierre Jolivet for (i = 0; i < gl->nschemes; i++) PetscCall(TSGLLESchemeView(gl->schemes[i], details, viewer)); 11901baa6e33SBarry Smith if (gl->View) PetscCall((*gl->View)(gl, viewer)); 11919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 11923d177a5cSEmil Constantinescu } 11933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11943d177a5cSEmil Constantinescu } 11953d177a5cSEmil Constantinescu 11963d177a5cSEmil Constantinescu /*@C 1197bcf0153eSBarry Smith TSGLLERegister - adds a `TSGLLE` implementation 11983d177a5cSEmil Constantinescu 11993d177a5cSEmil Constantinescu Not Collective 12003d177a5cSEmil Constantinescu 12013d177a5cSEmil Constantinescu Input Parameters: 120220f4b53cSBarry Smith + sname - name of user-defined general linear scheme 120320f4b53cSBarry Smith - function - routine to create method context 12043d177a5cSEmil Constantinescu 1205bcf0153eSBarry Smith Level: advanced 1206bcf0153eSBarry Smith 1207bcf0153eSBarry Smith Note: 1208bcf0153eSBarry Smith `TSGLLERegister()` may be called multiple times to add several user-defined families. 12093d177a5cSEmil Constantinescu 1210b43aa488SJacob Faibussowitsch Example Usage: 12113d177a5cSEmil Constantinescu .vb 12123d177a5cSEmil Constantinescu TSGLLERegister("my_scheme", MySchemeCreate); 12133d177a5cSEmil Constantinescu .ve 12143d177a5cSEmil Constantinescu 12153d177a5cSEmil Constantinescu Then, your scheme can be chosen with the procedural interface via 12163d177a5cSEmil Constantinescu $ TSGLLESetType(ts, "my_scheme") 12173d177a5cSEmil Constantinescu or at runtime via the option 12183d177a5cSEmil Constantinescu $ -ts_gl_type my_scheme 12193d177a5cSEmil Constantinescu 12201cc06b55SBarry Smith .seealso: [](ch_ts), `TSGLLE`, `TSGLLEType`, `TSGLLERegisterAll()` 12213d177a5cSEmil Constantinescu @*/ 1222d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGLLERegister(const char sname[], PetscErrorCode (*function)(TS)) 1223d71ae5a4SJacob Faibussowitsch { 12243d177a5cSEmil Constantinescu PetscFunctionBegin; 12259566063dSJacob Faibussowitsch PetscCall(TSGLLEInitializePackage()); 12269566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&TSGLLEList, sname, function)); 12273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12283d177a5cSEmil Constantinescu } 12293d177a5cSEmil Constantinescu 12303d177a5cSEmil Constantinescu /*@C 1231bcf0153eSBarry Smith TSGLLEAcceptRegister - adds a `TSGLLE` acceptance scheme 12323d177a5cSEmil Constantinescu 12333d177a5cSEmil Constantinescu Not Collective 12343d177a5cSEmil Constantinescu 12353d177a5cSEmil Constantinescu Input Parameters: 123620f4b53cSBarry Smith + sname - name of user-defined acceptance scheme 123720f4b53cSBarry Smith - function - routine to create method context 12383d177a5cSEmil Constantinescu 1239bcf0153eSBarry Smith Level: advanced 1240bcf0153eSBarry Smith 1241bcf0153eSBarry Smith Note: 1242bcf0153eSBarry Smith `TSGLLEAcceptRegister()` may be called multiple times to add several user-defined families. 12433d177a5cSEmil Constantinescu 1244b43aa488SJacob Faibussowitsch Example Usage: 12453d177a5cSEmil Constantinescu .vb 12463d177a5cSEmil Constantinescu TSGLLEAcceptRegister("my_scheme", MySchemeCreate); 12473d177a5cSEmil Constantinescu .ve 12483d177a5cSEmil Constantinescu 12493d177a5cSEmil Constantinescu Then, your scheme can be chosen with the procedural interface via 12503d177a5cSEmil Constantinescu $ TSGLLESetAcceptType(ts, "my_scheme") 12513d177a5cSEmil Constantinescu or at runtime via the option 12523d177a5cSEmil Constantinescu $ -ts_gl_accept_type my_scheme 12533d177a5cSEmil Constantinescu 12541cc06b55SBarry Smith .seealso: [](ch_ts), `TSGLLE`, `TSGLLEType`, `TSGLLERegisterAll()`, `TSGLLEAcceptFunction` 12553d177a5cSEmil Constantinescu @*/ 1256d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGLLEAcceptRegister(const char sname[], TSGLLEAcceptFunction function) 1257d71ae5a4SJacob Faibussowitsch { 12583d177a5cSEmil Constantinescu PetscFunctionBegin; 12599566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&TSGLLEAcceptList, sname, function)); 12603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12613d177a5cSEmil Constantinescu } 12623d177a5cSEmil Constantinescu 12633d177a5cSEmil Constantinescu /*@C 1264bcf0153eSBarry Smith TSGLLERegisterAll - Registers all of the general linear methods in `TSGLLE` 12653d177a5cSEmil Constantinescu 12663d177a5cSEmil Constantinescu Not Collective 12673d177a5cSEmil Constantinescu 12683d177a5cSEmil Constantinescu Level: advanced 12693d177a5cSEmil Constantinescu 12701cc06b55SBarry Smith .seealso: [](ch_ts), `TSGLLE`, `TSGLLERegisterDestroy()` 12713d177a5cSEmil Constantinescu @*/ 1272d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGLLERegisterAll(void) 1273d71ae5a4SJacob Faibussowitsch { 12743d177a5cSEmil Constantinescu PetscFunctionBegin; 12753ba16761SJacob Faibussowitsch if (TSGLLERegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS); 12763d177a5cSEmil Constantinescu TSGLLERegisterAllCalled = PETSC_TRUE; 12773d177a5cSEmil Constantinescu 12789566063dSJacob Faibussowitsch PetscCall(TSGLLERegister(TSGLLE_IRKS, TSGLLECreate_IRKS)); 12799566063dSJacob Faibussowitsch PetscCall(TSGLLEAcceptRegister(TSGLLEACCEPT_ALWAYS, TSGLLEAccept_Always)); 12803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12813d177a5cSEmil Constantinescu } 12823d177a5cSEmil Constantinescu 12833d177a5cSEmil Constantinescu /*@C 1284bcf0153eSBarry Smith TSGLLEInitializePackage - This function initializes everything in the `TSGLLE` package. It is called 1285bcf0153eSBarry Smith from `TSInitializePackage()`. 12863d177a5cSEmil Constantinescu 12873d177a5cSEmil Constantinescu Level: developer 12883d177a5cSEmil Constantinescu 12891cc06b55SBarry Smith .seealso: [](ch_ts), `PetscInitialize()`, `TSInitializePackage()`, `TSGLLEFinalizePackage()` 12903d177a5cSEmil Constantinescu @*/ 1291d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGLLEInitializePackage(void) 1292d71ae5a4SJacob Faibussowitsch { 12933d177a5cSEmil Constantinescu PetscFunctionBegin; 12943ba16761SJacob Faibussowitsch if (TSGLLEPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS); 12953d177a5cSEmil Constantinescu TSGLLEPackageInitialized = PETSC_TRUE; 12969566063dSJacob Faibussowitsch PetscCall(TSGLLERegisterAll()); 12979566063dSJacob Faibussowitsch PetscCall(PetscRegisterFinalize(TSGLLEFinalizePackage)); 12983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12993d177a5cSEmil Constantinescu } 13003d177a5cSEmil Constantinescu 13013d177a5cSEmil Constantinescu /*@C 1302bcf0153eSBarry Smith TSGLLEFinalizePackage - This function destroys everything in the `TSGLLE` package. It is 1303bcf0153eSBarry Smith called from `PetscFinalize()`. 13043d177a5cSEmil Constantinescu 13053d177a5cSEmil Constantinescu Level: developer 13063d177a5cSEmil Constantinescu 13071cc06b55SBarry Smith .seealso: [](ch_ts), `PetscFinalize()`, `TSGLLEInitializePackage()`, `TSInitializePackage()` 13083d177a5cSEmil Constantinescu @*/ 1309d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGLLEFinalizePackage(void) 1310d71ae5a4SJacob Faibussowitsch { 13113d177a5cSEmil Constantinescu PetscFunctionBegin; 13129566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDestroy(&TSGLLEList)); 13139566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDestroy(&TSGLLEAcceptList)); 13143d177a5cSEmil Constantinescu TSGLLEPackageInitialized = PETSC_FALSE; 13153d177a5cSEmil Constantinescu TSGLLERegisterAllCalled = PETSC_FALSE; 13163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13173d177a5cSEmil Constantinescu } 13183d177a5cSEmil Constantinescu 13193d177a5cSEmil Constantinescu /* ------------------------------------------------------------ */ 13203d177a5cSEmil Constantinescu /*MC 13213d177a5cSEmil Constantinescu TSGLLE - DAE solver using implicit General Linear methods 13223d177a5cSEmil Constantinescu 1323bcf0153eSBarry Smith Options Database Keys: 13243d177a5cSEmil Constantinescu + -ts_gl_type <type> - the class of general linear method (irks) 13253d177a5cSEmil Constantinescu . -ts_gl_rtol <tol> - relative error 13263d177a5cSEmil Constantinescu . -ts_gl_atol <tol> - absolute error 13273d177a5cSEmil Constantinescu . -ts_gl_min_order <p> - minimum order method to consider (default=1) 13283d177a5cSEmil Constantinescu . -ts_gl_max_order <p> - maximum order method to consider (default=3) 13293d177a5cSEmil Constantinescu . -ts_gl_start_order <p> - order of starting method (default=1) 13303d177a5cSEmil Constantinescu . -ts_gl_complete <method> - method to use for completing the step (rescale-and-modify or rescale) 13313d177a5cSEmil Constantinescu - -ts_adapt_type <method> - adaptive controller to use (none step both) 13323d177a5cSEmil Constantinescu 1333bcf0153eSBarry Smith Level: beginner 1334bcf0153eSBarry Smith 13353d177a5cSEmil Constantinescu Notes: 1336*14d0ab18SJacob Faibussowitsch These methods contain Runge-Kutta and multistep schemes as special cases. These special cases 1337*14d0ab18SJacob Faibussowitsch have some fundamental limitations. For example, diagonally implicit Runge-Kutta cannot have 1338*14d0ab18SJacob Faibussowitsch stage order greater than 1 which limits their applicability to very stiff systems. 1339*14d0ab18SJacob Faibussowitsch Meanwhile, multistep methods cannot be A-stable for order greater than 2 and BDF are not 1340*14d0ab18SJacob Faibussowitsch 0-stable for order greater than 6. GL methods can be A- and L-stable with arbitrarily high 1341*14d0ab18SJacob Faibussowitsch stage order and reliable error estimates for both 1 and 2 orders higher to facilitate 1342*14d0ab18SJacob Faibussowitsch adaptive step sizes and adaptive order schemes. All this is possible while preserving a 1343*14d0ab18SJacob Faibussowitsch singly diagonally implicit structure. 1344*14d0ab18SJacob Faibussowitsch 13453d177a5cSEmil Constantinescu This integrator can be applied to DAE. 13463d177a5cSEmil Constantinescu 1347*14d0ab18SJacob Faibussowitsch Diagonally implicit general linear (DIGL) methods are a generalization of diagonally implicit 1348*14d0ab18SJacob Faibussowitsch Runge-Kutta (DIRK). They are represented by the tableau 13493d177a5cSEmil Constantinescu 13503d177a5cSEmil Constantinescu .vb 13513d177a5cSEmil Constantinescu A | U 13523d177a5cSEmil Constantinescu ------- 13533d177a5cSEmil Constantinescu B | V 13543d177a5cSEmil Constantinescu .ve 13553d177a5cSEmil Constantinescu 1356*14d0ab18SJacob Faibussowitsch combined with a vector c of abscissa. "Diagonally implicit" means that A is lower 1357*14d0ab18SJacob Faibussowitsch triangular. A step of the general method reads 13583d177a5cSEmil Constantinescu 1359*14d0ab18SJacob Faibussowitsch $$ 13603d177a5cSEmil Constantinescu [ Y ] = [A U] [ Y' ] 13613d177a5cSEmil Constantinescu [X^k] = [B V] [X^{k-1}] 1362*14d0ab18SJacob Faibussowitsch $$ 13633d177a5cSEmil Constantinescu 1364*14d0ab18SJacob Faibussowitsch where Y is the multivector of stage values, Y' is the multivector of stage derivatives, X^k 1365*14d0ab18SJacob Faibussowitsch is the Nordsieck vector of the solution at step k. The Nordsieck vector consists of the first 1366*14d0ab18SJacob Faibussowitsch r moments of the solution, given by 13673d177a5cSEmil Constantinescu 1368*14d0ab18SJacob Faibussowitsch $$ 13693d177a5cSEmil Constantinescu X = [x_0,x_1,...,x_{r-1}] = [x, h x', h^2 x'', ..., h^{r-1} x^{(r-1)} ] 1370*14d0ab18SJacob Faibussowitsch $$ 13713d177a5cSEmil Constantinescu 13723d177a5cSEmil Constantinescu If A is lower triangular, we can solve the stages (Y, Y') sequentially 13733d177a5cSEmil Constantinescu 1374*14d0ab18SJacob Faibussowitsch $$ 13753d177a5cSEmil 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} 1376*14d0ab18SJacob Faibussowitsch $$ 13773d177a5cSEmil Constantinescu 13783d177a5cSEmil Constantinescu and then construct the pieces to carry to the next step 13793d177a5cSEmil Constantinescu 1380*14d0ab18SJacob Faibussowitsch $$ 13813d177a5cSEmil 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} 1382*14d0ab18SJacob Faibussowitsch $$ 13833d177a5cSEmil Constantinescu 1384*14d0ab18SJacob Faibussowitsch Note that when the equations are cast in implicit form, we are using the stage equation to 1385*14d0ab18SJacob Faibussowitsch define $y'_i$ in terms of $y_i$ and known stuff (y_j for j<i and x_j for all j). 13863d177a5cSEmil Constantinescu 13873d177a5cSEmil Constantinescu Error estimation 13883d177a5cSEmil Constantinescu 1389*14d0ab18SJacob Faibussowitsch At present, the most attractive GL methods for stiff problems are singly diagonally implicit 1390*14d0ab18SJacob Faibussowitsch schemes which posses Inherent Runge-Kutta Stability (`TSIRKS`). These methods have r=s, the 1391*14d0ab18SJacob Faibussowitsch number of items passed between steps is equal to the number of stages. The order and 1392*14d0ab18SJacob Faibussowitsch stage-order are one less than the number of stages. We use the error estimates in the 2007 1393*14d0ab18SJacob Faibussowitsch paper which provide the following estimates 13943d177a5cSEmil Constantinescu 1395*14d0ab18SJacob Faibussowitsch $$ 13963d177a5cSEmil Constantinescu h^{p+1} X^{(p+1)} = phi_0^T Y' + [0 psi_0^T] Xold 13973d177a5cSEmil Constantinescu h^{p+2} X^{(p+2)} = phi_1^T Y' + [0 psi_1^T] Xold 13983d177a5cSEmil Constantinescu h^{p+2} (dx'/dx) X^{(p+1)} = phi_2^T Y' + [0 psi_2^T] Xold 1399*14d0ab18SJacob Faibussowitsch $$ 14003d177a5cSEmil Constantinescu 14013d177a5cSEmil Constantinescu These estimates are accurate to O(h^{p+3}). 14023d177a5cSEmil Constantinescu 14033d177a5cSEmil Constantinescu Changing the step size 14043d177a5cSEmil Constantinescu 14053d177a5cSEmil Constantinescu We use the generalized "rescale and modify" scheme, see equation (4.5) of the 2007 paper. 14063d177a5cSEmil Constantinescu 14073d177a5cSEmil Constantinescu References: 1408606c0280SSatish Balay + * - John Butcher and Z. Jackieweicz and W. Wright, On error propagation in general linear methods for 14093d177a5cSEmil Constantinescu ordinary differential equations, Journal of Complexity, Vol 23, 2007. 1410606c0280SSatish Balay - * - John Butcher, Numerical methods for ordinary differential equations, second edition, Wiley, 2009. 14113d177a5cSEmil Constantinescu 14121cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSSetType()`, `TSType` 14133d177a5cSEmil Constantinescu M*/ 1414d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode TSCreate_GLLE(TS ts) 1415d71ae5a4SJacob Faibussowitsch { 14163d177a5cSEmil Constantinescu TS_GLLE *gl; 14173d177a5cSEmil Constantinescu 14183d177a5cSEmil Constantinescu PetscFunctionBegin; 14199566063dSJacob Faibussowitsch PetscCall(TSGLLEInitializePackage()); 14203d177a5cSEmil Constantinescu 14214dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&gl)); 14223d177a5cSEmil Constantinescu ts->data = (void *)gl; 14233d177a5cSEmil Constantinescu 14243d177a5cSEmil Constantinescu ts->ops->reset = TSReset_GLLE; 14253d177a5cSEmil Constantinescu ts->ops->destroy = TSDestroy_GLLE; 14263d177a5cSEmil Constantinescu ts->ops->view = TSView_GLLE; 14273d177a5cSEmil Constantinescu ts->ops->setup = TSSetUp_GLLE; 14283d177a5cSEmil Constantinescu ts->ops->solve = TSSolve_GLLE; 14293d177a5cSEmil Constantinescu ts->ops->setfromoptions = TSSetFromOptions_GLLE; 14303d177a5cSEmil Constantinescu ts->ops->snesfunction = SNESTSFormFunction_GLLE; 14313d177a5cSEmil Constantinescu ts->ops->snesjacobian = SNESTSFormJacobian_GLLE; 14323d177a5cSEmil Constantinescu 1433efd4aadfSBarry Smith ts->usessnes = PETSC_TRUE; 1434efd4aadfSBarry Smith 14353d177a5cSEmil Constantinescu gl->max_step_rejections = 1; 14363d177a5cSEmil Constantinescu gl->min_order = 1; 14373d177a5cSEmil Constantinescu gl->max_order = 3; 14383d177a5cSEmil Constantinescu gl->start_order = 1; 14393d177a5cSEmil Constantinescu gl->current_scheme = -1; 14403d177a5cSEmil Constantinescu gl->extrapolate = PETSC_FALSE; 14413d177a5cSEmil Constantinescu 14423d177a5cSEmil Constantinescu gl->wrms_atol = 1e-8; 14433d177a5cSEmil Constantinescu gl->wrms_rtol = 1e-5; 14443d177a5cSEmil Constantinescu 14459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSGLLESetType_C", &TSGLLESetType_GLLE)); 14469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSGLLESetAcceptType_C", &TSGLLESetAcceptType_GLLE)); 14479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSGLLEGetAdapt_C", &TSGLLEGetAdapt_GLLE)); 14483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14493d177a5cSEmil Constantinescu } 1450