1fcf85c8cSAdelekeBankole static char help[] = "A Chebyshev spectral method for the compressible Blasius boundary layer equations.\n\n"; 2fcf85c8cSAdelekeBankole 3fcf85c8cSAdelekeBankole /* 4fcf85c8cSAdelekeBankole Include "petscsnes.h" so that we can use SNES solvers. Note that this 5fcf85c8cSAdelekeBankole file automatically includes: 6fcf85c8cSAdelekeBankole petscsys.h - base PETSc routines petscvec.h - vectors 7fcf85c8cSAdelekeBankole petscmat.h - matrices 8fcf85c8cSAdelekeBankole petscis.h - index sets petscksp.h - Krylov subspace methods 9fcf85c8cSAdelekeBankole petscviewer.h - viewers petscpc.h - preconditioners 10fcf85c8cSAdelekeBankole petscksp.h - linear solvers 11fcf85c8cSAdelekeBankole Include "petscdt.h" so that we can have support for use of Quadrature formulas 12fcf85c8cSAdelekeBankole */ 13fcf85c8cSAdelekeBankole /*F 14fcf85c8cSAdelekeBankole This examples solves the compressible Blasius boundary layer equations 15fcf85c8cSAdelekeBankole 2(\rho\muf'')' + ff'' = 0 16fcf85c8cSAdelekeBankole (\rho\muh')' + Prfh' + Pr(\gamma-1)Ma^{2}\rho\muf''^{2} = 0 17fcf85c8cSAdelekeBankole following Howarth-Dorodnitsyn transformation with boundary conditions 18fcf85c8cSAdelekeBankole f(0) = f'(0) = 0, f'(\infty) = 1, h(\infty) = 1, h = \theta(0). Where \theta = T/T_{\infty} 19fcf85c8cSAdelekeBankole Note: density (\rho) and viscosity (\mu) are treated as constants in this example 20fcf85c8cSAdelekeBankole F*/ 21fcf85c8cSAdelekeBankole #include <petscsnes.h> 22fcf85c8cSAdelekeBankole #include <petscdt.h> 23fcf85c8cSAdelekeBankole 24fcf85c8cSAdelekeBankole /* 25fcf85c8cSAdelekeBankole User-defined routines 26fcf85c8cSAdelekeBankole */ 27fcf85c8cSAdelekeBankole 28fcf85c8cSAdelekeBankole extern PetscErrorCode FormFunction(SNES, Vec, Vec, void *); 29fcf85c8cSAdelekeBankole 30fcf85c8cSAdelekeBankole typedef struct { 31fcf85c8cSAdelekeBankole PetscReal Ma, Pr, h_0; 32fcf85c8cSAdelekeBankole PetscInt N; 33fcf85c8cSAdelekeBankole PetscReal dx_deta; 34fcf85c8cSAdelekeBankole PetscReal *x; 35fcf85c8cSAdelekeBankole PetscReal gamma; 36fcf85c8cSAdelekeBankole } Blasius; 37fcf85c8cSAdelekeBankole 38d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv) 39d71ae5a4SJacob Faibussowitsch { 40fcf85c8cSAdelekeBankole SNES snes; /* nonlinear solver context */ 41fcf85c8cSAdelekeBankole Vec x, r; /* solution, residual vectors */ 42fcf85c8cSAdelekeBankole PetscMPIInt size; 43fcf85c8cSAdelekeBankole Blasius *blasius; 44fcf85c8cSAdelekeBankole PetscReal L, *weight; /* L is size of the domain */ 45fcf85c8cSAdelekeBankole 46327415f7SBarry Smith PetscFunctionBeginUser; 47c8025a54SPierre Jolivet PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 48fcf85c8cSAdelekeBankole PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size)); 49fcf85c8cSAdelekeBankole PetscCheck(size == 1, PETSC_COMM_WORLD, PETSC_ERR_WRONG_MPI_SIZE, "Example is only for sequential runs"); 50fcf85c8cSAdelekeBankole 51fcf85c8cSAdelekeBankole // Read command-line arguments 52fcf85c8cSAdelekeBankole PetscCall(PetscCalloc1(1, &blasius)); 53fcf85c8cSAdelekeBankole blasius->Ma = 2; /* Mach number */ 54fcf85c8cSAdelekeBankole blasius->Pr = 0.7; /* Prandtl number */ 55fcf85c8cSAdelekeBankole blasius->h_0 = 2.; /* relative temperature at the wall */ 56fcf85c8cSAdelekeBankole blasius->N = 10; /* Number of Chebyshev terms */ 57fcf85c8cSAdelekeBankole blasius->gamma = 1.4; /* specific heat ratio */ 58fcf85c8cSAdelekeBankole L = 5; 59fcf85c8cSAdelekeBankole PetscOptionsBegin(PETSC_COMM_WORLD, NULL, "Compressible Blasius boundary layer equations", ""); 60fcf85c8cSAdelekeBankole PetscCall(PetscOptionsReal("-mach", "Mach number at freestream", "", blasius->Ma, &blasius->Ma, NULL)); 61fcf85c8cSAdelekeBankole PetscCall(PetscOptionsReal("-prandtl", "Prandtl number", "", blasius->Pr, &blasius->Pr, NULL)); 62fcf85c8cSAdelekeBankole PetscCall(PetscOptionsReal("-h_0", "Relative enthalpy at wall", "", blasius->h_0, &blasius->h_0, NULL)); 63fcf85c8cSAdelekeBankole PetscCall(PetscOptionsReal("-gamma", "Ratio of specific heats", "", blasius->gamma, &blasius->gamma, NULL)); 64fcf85c8cSAdelekeBankole PetscCall(PetscOptionsInt("-N", "Number of Chebyshev terms for f", "", blasius->N, &blasius->N, NULL)); 65fcf85c8cSAdelekeBankole PetscCall(PetscOptionsReal("-L", "Extent of the domain", "", L, &L, NULL)); 66fcf85c8cSAdelekeBankole PetscOptionsEnd(); 67fcf85c8cSAdelekeBankole blasius->dx_deta = 2 / L; /* this helps to map [-1,1] to [0,L] */ 68fcf85c8cSAdelekeBankole PetscCall(PetscMalloc2(blasius->N - 3, &blasius->x, blasius->N - 3, &weight)); 69fcf85c8cSAdelekeBankole PetscCall(PetscDTGaussQuadrature(blasius->N - 3, -1., 1., blasius->x, weight)); 70fcf85c8cSAdelekeBankole 71fcf85c8cSAdelekeBankole /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 72fcf85c8cSAdelekeBankole Create nonlinear solver context 73fcf85c8cSAdelekeBankole - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 74fcf85c8cSAdelekeBankole PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes)); 75fcf85c8cSAdelekeBankole 76fcf85c8cSAdelekeBankole /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 77fcf85c8cSAdelekeBankole Create matrix and vector data structures; set corresponding routines 78fcf85c8cSAdelekeBankole - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 79fcf85c8cSAdelekeBankole /* 80fcf85c8cSAdelekeBankole Create vectors for solution and nonlinear function 81fcf85c8cSAdelekeBankole */ 82fcf85c8cSAdelekeBankole PetscCall(VecCreate(PETSC_COMM_WORLD, &x)); 83fcf85c8cSAdelekeBankole PetscCall(VecSetSizes(x, PETSC_DECIDE, 2 * blasius->N - 1)); 84fcf85c8cSAdelekeBankole PetscCall(VecSetFromOptions(x)); 85fcf85c8cSAdelekeBankole PetscCall(VecDuplicate(x, &r)); 86fcf85c8cSAdelekeBankole 87fcf85c8cSAdelekeBankole /* 88fcf85c8cSAdelekeBankole Set function evaluation routine and vector. 89fcf85c8cSAdelekeBankole */ 90fcf85c8cSAdelekeBankole PetscCall(SNESSetFunction(snes, r, FormFunction, blasius)); 91fcf85c8cSAdelekeBankole { 92fcf85c8cSAdelekeBankole KSP ksp; 93fcf85c8cSAdelekeBankole PC pc; 943ba16761SJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 953ba16761SJacob Faibussowitsch PetscCall(KSPSetType(ksp, KSPPREONLY)); 963ba16761SJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 973ba16761SJacob Faibussowitsch PetscCall(PCSetType(pc, PCLU)); 98fcf85c8cSAdelekeBankole } 99fcf85c8cSAdelekeBankole /* 100fcf85c8cSAdelekeBankole Set SNES/KSP/KSP/PC runtime options, e.g., 101fcf85c8cSAdelekeBankole -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc> 102fcf85c8cSAdelekeBankole These options will override those specified above as long as 103fcf85c8cSAdelekeBankole SNESSetFromOptions() is called _after_ any other customization 104fcf85c8cSAdelekeBankole routines. 105fcf85c8cSAdelekeBankole */ 106fcf85c8cSAdelekeBankole PetscCall(SNESSetFromOptions(snes)); 107fcf85c8cSAdelekeBankole 108fcf85c8cSAdelekeBankole PetscCall(SNESSolve(snes, NULL, x)); 109fcf85c8cSAdelekeBankole //PetscCall(VecView(x,PETSC_VIEWER_STDOUT_WORLD)); 110fcf85c8cSAdelekeBankole 111fcf85c8cSAdelekeBankole /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 112fcf85c8cSAdelekeBankole Free work space. All PETSc objects should be destroyed when they 113fcf85c8cSAdelekeBankole are no longer needed. 114fcf85c8cSAdelekeBankole - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 115fcf85c8cSAdelekeBankole 116fcf85c8cSAdelekeBankole PetscCall(PetscFree2(blasius->x, weight)); 117fcf85c8cSAdelekeBankole PetscCall(PetscFree(blasius)); 118fcf85c8cSAdelekeBankole PetscCall(VecDestroy(&x)); 119fcf85c8cSAdelekeBankole PetscCall(VecDestroy(&r)); 120fcf85c8cSAdelekeBankole PetscCall(SNESDestroy(&snes)); 121fcf85c8cSAdelekeBankole PetscCall(PetscFinalize()); 122fcf85c8cSAdelekeBankole return 0; 123fcf85c8cSAdelekeBankole } 124fcf85c8cSAdelekeBankole 125f6dfbefdSBarry Smith /* 126fcf85c8cSAdelekeBankole Helper function to evaluate Chebyshev polynomials with a set of coefficients 127fcf85c8cSAdelekeBankole with all their derivatives represented as a recurrence table 128f6dfbefdSBarry Smith */ 129d71ae5a4SJacob Faibussowitsch static void ChebyshevEval(PetscInt N, const PetscScalar *Tf, PetscReal x, PetscReal dx_deta, PetscScalar *f) 130d71ae5a4SJacob Faibussowitsch { 131fcf85c8cSAdelekeBankole PetscScalar table[4][3] = { 1329371c9d4SSatish Balay {1, x, 2 * x * x - 1}, 1339371c9d4SSatish Balay {0, 1, 4 * x }, 1349371c9d4SSatish Balay {0, 0, 4 }, 1359371c9d4SSatish Balay {0, 0, 0 } /* Chebyshev polynomials T_0, T_1, T_2 of the first kind in (-1,1) */ 136fcf85c8cSAdelekeBankole }; 137ac530a7eSPierre Jolivet for (int i = 0; i < 4; i++) f[i] = table[i][0] * Tf[0] + table[i][1] * Tf[1] + table[i][2] * Tf[2]; /* i-th derivative of f */ 138fcf85c8cSAdelekeBankole for (int i = 3; i < N; i++) { 139fcf85c8cSAdelekeBankole table[0][i % 3] = 2 * x * table[0][(i - 1) % 3] - table[0][(i - 2) % 3]; /* T_n(x) = 2xT_{n-1}(x) - T_{n-2}(x) */ 140fcf85c8cSAdelekeBankole /* Differentiate Chebyshev polynomials with the recurrence relation */ 141ac530a7eSPierre Jolivet for (int j = 1; j < 4; j++) table[j][i % 3] = i * (2 * table[j - 1][(i - 1) % 3] + table[j][(i - 2) % 3] / (i - 2)); /* T'_{n}(x)/n = 2T_{n-1}(x) + T'_{n-2}(x)/n-2 */ 142ad540459SPierre Jolivet for (int j = 0; j < 4; j++) f[j] += table[j][i % 3] * Tf[i]; 143fcf85c8cSAdelekeBankole } 144fcf85c8cSAdelekeBankole for (int i = 1; i < 4; i++) { 145fcf85c8cSAdelekeBankole for (int j = 0; j < i; j++) f[i] *= dx_deta; /* Here happens the physics of the problem */ 146fcf85c8cSAdelekeBankole } 147fcf85c8cSAdelekeBankole } 148fcf85c8cSAdelekeBankole 149fcf85c8cSAdelekeBankole /* 150fcf85c8cSAdelekeBankole FormFunction - Evaluates nonlinear function, F(x). 151fcf85c8cSAdelekeBankole 152fcf85c8cSAdelekeBankole Input Parameters: 153fcf85c8cSAdelekeBankole . snes - the SNES context 154fcf85c8cSAdelekeBankole . X - input vector 155fcf85c8cSAdelekeBankole . ctx - optional user-defined context 156fcf85c8cSAdelekeBankole 157fcf85c8cSAdelekeBankole Output Parameter: 158fcf85c8cSAdelekeBankole . R - function vector 159fcf85c8cSAdelekeBankole */ 160*2a8381b2SBarry Smith PetscErrorCode FormFunction(SNES snes, Vec X, Vec R, PetscCtx ctx) 161d71ae5a4SJacob Faibussowitsch { 162fcf85c8cSAdelekeBankole Blasius *blasius = (Blasius *)ctx; 163fcf85c8cSAdelekeBankole const PetscScalar *Tf, *Th; /* Tf and Th are Chebyshev coefficients */ 164fcf85c8cSAdelekeBankole PetscScalar *r, f[4], h[4]; 165fcf85c8cSAdelekeBankole PetscInt N = blasius->N; 166fcf85c8cSAdelekeBankole PetscReal Ma = blasius->Ma, Pr = blasius->Pr; 167fcf85c8cSAdelekeBankole 1683ba16761SJacob Faibussowitsch PetscFunctionBeginUser; 169fcf85c8cSAdelekeBankole /* 170fcf85c8cSAdelekeBankole Get pointers to vector data. 171fcf85c8cSAdelekeBankole - For default PETSc vectors, VecGetArray() returns a pointer to 172fcf85c8cSAdelekeBankole the data array. Otherwise, the routine is implementation dependent. 173fcf85c8cSAdelekeBankole - You MUST call VecRestoreArray() when you no longer need access to 174fcf85c8cSAdelekeBankole the array. 175fcf85c8cSAdelekeBankole */ 176fcf85c8cSAdelekeBankole PetscCall(VecGetArrayRead(X, &Tf)); 177fcf85c8cSAdelekeBankole Th = Tf + N; 178fcf85c8cSAdelekeBankole PetscCall(VecGetArray(R, &r)); 179fcf85c8cSAdelekeBankole 180fcf85c8cSAdelekeBankole /* Compute function */ 181fcf85c8cSAdelekeBankole ChebyshevEval(N, Tf, -1., blasius->dx_deta, f); 182fcf85c8cSAdelekeBankole r[0] = f[0]; 183fcf85c8cSAdelekeBankole r[1] = f[1]; 184fcf85c8cSAdelekeBankole ChebyshevEval(N, Tf, 1., blasius->dx_deta, f); 185fcf85c8cSAdelekeBankole r[2] = f[1] - 1; /* Right end boundary condition */ 186fcf85c8cSAdelekeBankole for (int i = 0; i < N - 3; i++) { 187fcf85c8cSAdelekeBankole ChebyshevEval(N, Tf, blasius->x[i], blasius->dx_deta, f); 188fcf85c8cSAdelekeBankole r[3 + i] = 2 * f[3] + f[2] * f[0]; 189fcf85c8cSAdelekeBankole ChebyshevEval(N - 1, Th, blasius->x[i], blasius->dx_deta, h); 190fcf85c8cSAdelekeBankole r[N + 2 + i] = h[2] + Pr * f[0] * h[1] + Pr * (blasius->gamma - 1) * PetscSqr(Ma * f[2]); 191fcf85c8cSAdelekeBankole } 192fcf85c8cSAdelekeBankole ChebyshevEval(N - 1, Th, -1., blasius->dx_deta, h); 193fcf85c8cSAdelekeBankole r[N] = h[0] - blasius->h_0; /* Left end boundary condition */ 194fcf85c8cSAdelekeBankole ChebyshevEval(N - 1, Th, 1., blasius->dx_deta, h); 195fcf85c8cSAdelekeBankole r[N + 1] = h[0] - 1; /* Left end boundary condition */ 196fcf85c8cSAdelekeBankole 197fcf85c8cSAdelekeBankole /* Restore vectors */ 198fcf85c8cSAdelekeBankole PetscCall(VecRestoreArrayRead(X, &Tf)); 199fcf85c8cSAdelekeBankole PetscCall(VecRestoreArray(R, &r)); 2003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 201fcf85c8cSAdelekeBankole } 202fcf85c8cSAdelekeBankole 203fcf85c8cSAdelekeBankole /*TEST 204fcf85c8cSAdelekeBankole 205fcf85c8cSAdelekeBankole test: 206fcf85c8cSAdelekeBankole args: -snes_monitor -pc_type svd 207fcf85c8cSAdelekeBankole requires: !single 208fcf85c8cSAdelekeBankole 209fcf85c8cSAdelekeBankole TEST*/ 210