1c4762a1bSJed Brown static const char help[] = "Steady-state 2D subduction flow, pressure and temperature solver.\n\ 2c4762a1bSJed Brown The flow is driven by the subducting slab.\n\ 3c4762a1bSJed Brown ---------------------------------ex30 help---------------------------------\n\ 4c4762a1bSJed Brown -OPTION <DEFAULT> = (UNITS) DESCRIPTION.\n\n\ 5c4762a1bSJed Brown -width <320> = (km) width of domain.\n\ 6c4762a1bSJed Brown -depth <300> = (km) depth of domain.\n\ 7c4762a1bSJed Brown -slab_dip <45> = (degrees) dip angle of the slab (determines the grid aspect ratio).\n\ 8c4762a1bSJed Brown -lid_depth <35> = (km) depth of the static conductive lid.\n\ 9c4762a1bSJed Brown -fault_depth <35> = (km) depth of slab-wedge mechanical coupling\n\ 10c4762a1bSJed Brown (fault dept >= lid depth).\n\ 11c4762a1bSJed Brown \n\ 12c4762a1bSJed Brown -ni <82> = grid cells in x-direction. (nj adjusts to accommodate\n\ 13c4762a1bSJed Brown the slab dip & depth). DO NOT USE -da_grid_x option!!!\n\ 14c4762a1bSJed Brown -ivisc <3> = rheology option.\n\ 15c4762a1bSJed Brown 0 --- constant viscosity.\n\ 16c4762a1bSJed Brown 1 --- olivine diffusion creep rheology (T&P-dependent, newtonian).\n\ 17c4762a1bSJed Brown 2 --- olivine dislocation creep rheology (T&P-dependent, non-newtonian).\n\ 18c4762a1bSJed Brown 3 --- Full mantle rheology, combination of 1 & 2.\n\ 19c4762a1bSJed Brown \n\ 20c4762a1bSJed Brown -slab_velocity <5> = (cm/year) convergence rate of slab into subduction zone.\n\ 21c4762a1bSJed Brown -slab_age <50> = (million yrs) age of slab for thermal profile boundary condition.\n\ 22c4762a1bSJed Brown -lid_age <50> = (million yrs) age of lid for thermal profile boundary condition.\n\ 23c4762a1bSJed Brown \n\ 24c4762a1bSJed Brown FOR OTHER PARAMETER OPTIONS AND THEIR DEFAULT VALUES, see SetParams() in ex30.c.\n\ 25c4762a1bSJed Brown ---------------------------------ex30 help---------------------------------\n"; 26c4762a1bSJed Brown 27c4762a1bSJed Brown /*F----------------------------------------------------------------------- 28c4762a1bSJed Brown 29c4762a1bSJed Brown This PETSc 2.2.0 example by Richard F. Katz 30c4762a1bSJed Brown http://www.ldeo.columbia.edu/~katz/ 31c4762a1bSJed Brown 32c4762a1bSJed Brown The problem is modeled by the partial differential equation system 33c4762a1bSJed Brown 34c4762a1bSJed Brown \begin{eqnarray} 35c4762a1bSJed Brown -\nabla P + \nabla \cdot [\eta (\nabla v + \nabla v^T)] & = & 0 \\ 36c4762a1bSJed Brown \nabla \cdot v & = & 0 \\ 37c4762a1bSJed Brown dT/dt + \nabla \cdot (vT) - 1/Pe \triangle^2(T) & = & 0 \\ 38c4762a1bSJed Brown \end{eqnarray} 39c4762a1bSJed Brown 40c4762a1bSJed Brown \begin{eqnarray} 41c4762a1bSJed Brown \eta(T,Eps\_dot) & = & \hbox{constant } \hbox{if ivisc} ==0 \\ 42c4762a1bSJed Brown & = & \hbox{diffusion creep (T,P-dependent) } \hbox{if ivisc} ==1 \\ 43c4762a1bSJed Brown & = & \hbox{dislocation creep (T,P,v-dependent)} \hbox{if ivisc} ==2 \\ 44c4762a1bSJed Brown & = & \hbox{mantle viscosity (difn and disl) } \hbox{if ivisc} ==3 45c4762a1bSJed Brown \end{eqnarray} 46c4762a1bSJed Brown 47c4762a1bSJed Brown which is uniformly discretized on a staggered mesh: 48c4762a1bSJed Brown -------$w_{ij}$------ 49c4762a1bSJed Brown $u_{i-1j}$ $P,T_{ij}$ $u_{ij}$ 50c4762a1bSJed Brown ------$w_{ij-1}$----- 51c4762a1bSJed Brown 52c4762a1bSJed Brown ------------------------------------------------------------------------F*/ 53c4762a1bSJed Brown 54c4762a1bSJed Brown #include <petscsnes.h> 55c4762a1bSJed Brown #include <petscdm.h> 56c4762a1bSJed Brown #include <petscdmda.h> 57c4762a1bSJed Brown 58c4762a1bSJed Brown #define VISC_CONST 0 59c4762a1bSJed Brown #define VISC_DIFN 1 60c4762a1bSJed Brown #define VISC_DISL 2 61c4762a1bSJed Brown #define VISC_FULL 3 62c4762a1bSJed Brown #define CELL_CENTER 0 63c4762a1bSJed Brown #define CELL_CORNER 1 64c4762a1bSJed Brown #define BC_ANALYTIC 0 65c4762a1bSJed Brown #define BC_NOSTRESS 1 66c4762a1bSJed Brown #define BC_EXPERMNT 2 67c4762a1bSJed Brown #define ADVECT_FV 0 68c4762a1bSJed Brown #define ADVECT_FROMM 1 69c4762a1bSJed Brown #define PLATE_SLAB 0 70c4762a1bSJed Brown #define PLATE_LID 1 71c4762a1bSJed Brown #define EPS_ZERO 0.00000001 72c4762a1bSJed Brown 73c4762a1bSJed Brown typedef struct { /* holds the variables to be solved for */ 74c4762a1bSJed Brown PetscScalar u,w,p,T; 75c4762a1bSJed Brown } Field; 76c4762a1bSJed Brown 77c4762a1bSJed Brown typedef struct { /* parameters needed to compute viscosity */ 78c4762a1bSJed Brown PetscReal A,n,Estar,Vstar; 79c4762a1bSJed Brown } ViscParam; 80c4762a1bSJed Brown 81c4762a1bSJed Brown typedef struct { /* physical and miscelaneous parameters */ 82c4762a1bSJed Brown PetscReal width, depth, scaled_width, scaled_depth, peclet, potentialT; 83c4762a1bSJed Brown PetscReal slab_dip, slab_age, slab_velocity, kappa, z_scale; 84c4762a1bSJed Brown PetscReal c, d, sb, cb, skt, visc_cutoff, lid_age, eta0, continuation; 85c4762a1bSJed Brown PetscReal L, V, lid_depth, fault_depth; 86c4762a1bSJed Brown ViscParam diffusion, dislocation; 87c4762a1bSJed Brown PetscInt ivisc, adv_scheme, ibound, output_ivisc; 88c4762a1bSJed Brown PetscBool quiet, param_test, output_to_file, pv_analytic; 89c4762a1bSJed Brown PetscBool interrupted, stop_solve, toggle_kspmon, kspmon; 90c4762a1bSJed Brown char filename[PETSC_MAX_PATH_LEN]; 91c4762a1bSJed Brown } Parameter; 92c4762a1bSJed Brown 93c4762a1bSJed Brown typedef struct { /* grid parameters */ 94c4762a1bSJed Brown DMBoundaryType bx,by; 95c4762a1bSJed Brown DMDAStencilType stencil; 96c4762a1bSJed Brown PetscInt corner,ni,nj,jlid,jfault,inose; 97c4762a1bSJed Brown PetscInt dof,stencil_width,mglevels; 98c4762a1bSJed Brown PetscReal dx,dz; 99c4762a1bSJed Brown } GridInfo; 100c4762a1bSJed Brown 101c4762a1bSJed Brown typedef struct { /* application context */ 102c4762a1bSJed Brown Vec x,Xguess; 103c4762a1bSJed Brown Parameter *param; 104c4762a1bSJed Brown GridInfo *grid; 105c4762a1bSJed Brown } AppCtx; 106c4762a1bSJed Brown 107c4762a1bSJed Brown /* Callback functions (static interface) */ 108c4762a1bSJed Brown extern PetscErrorCode FormFunctionLocal(DMDALocalInfo*,Field**,Field**,void*); 109c4762a1bSJed Brown 110c4762a1bSJed Brown /* Main routines */ 111c4762a1bSJed Brown extern PetscErrorCode SetParams(Parameter*, GridInfo*); 112c4762a1bSJed Brown extern PetscErrorCode ReportParams(Parameter*, GridInfo*); 113c4762a1bSJed Brown extern PetscErrorCode Initialize(DM); 114c4762a1bSJed Brown extern PetscErrorCode UpdateSolution(SNES,AppCtx*, PetscInt*); 115c4762a1bSJed Brown extern PetscErrorCode DoOutput(SNES,PetscInt); 116c4762a1bSJed Brown 117c4762a1bSJed Brown /* Post-processing & misc */ 118c4762a1bSJed Brown extern PetscErrorCode ViscosityField(DM,Vec,Vec); 119c4762a1bSJed Brown extern PetscErrorCode StressField(DM); 120c4762a1bSJed Brown extern PetscErrorCode SNESConverged_Interactive(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason*, void*); 121c4762a1bSJed Brown extern PetscErrorCode InteractiveHandler(int, void*); 122c4762a1bSJed Brown 123c4762a1bSJed Brown /*-----------------------------------------------------------------------*/ 124c4762a1bSJed Brown int main(int argc,char **argv) 125c4762a1bSJed Brown /*-----------------------------------------------------------------------*/ 126c4762a1bSJed Brown { 127c4762a1bSJed Brown SNES snes; 128c4762a1bSJed Brown AppCtx *user; /* user-defined work context */ 129c4762a1bSJed Brown Parameter param; 130c4762a1bSJed Brown GridInfo grid; 131c4762a1bSJed Brown PetscInt nits; 132c4762a1bSJed Brown MPI_Comm comm; 133c4762a1bSJed Brown DM da; 134c4762a1bSJed Brown 135*b122ec5aSJacob Faibussowitsch CHKERRQ(PetscInitialize(&argc,&argv,(char*)0,help)); 136c4762a1bSJed Brown PetscOptionsSetValue(NULL,"-file","ex30_output"); 137c4762a1bSJed Brown PetscOptionsSetValue(NULL,"-snes_monitor_short",NULL); 138c4762a1bSJed Brown PetscOptionsSetValue(NULL,"-snes_max_it","20"); 139c4762a1bSJed Brown PetscOptionsSetValue(NULL,"-ksp_max_it","1500"); 140c4762a1bSJed Brown PetscOptionsSetValue(NULL,"-ksp_gmres_restart","300"); 141c4762a1bSJed Brown PetscOptionsInsert(NULL,&argc,&argv,NULL); 142c4762a1bSJed Brown 143c4762a1bSJed Brown comm = PETSC_COMM_WORLD; 144c4762a1bSJed Brown 145c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 146c4762a1bSJed Brown Set up the problem parameters. 147c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1485f80ce2aSJacob Faibussowitsch CHKERRQ(SetParams(¶m,&grid)); 1495f80ce2aSJacob Faibussowitsch CHKERRQ(ReportParams(¶m,&grid)); 150c4762a1bSJed Brown 151c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 152c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1535f80ce2aSJacob Faibussowitsch CHKERRQ(SNESCreate(comm,&snes)); 1545f80ce2aSJacob Faibussowitsch CHKERRQ(DMDACreate2d(comm,grid.bx,grid.by,grid.stencil,grid.ni,grid.nj,PETSC_DECIDE,PETSC_DECIDE,grid.dof,grid.stencil_width,0,0,&da)); 1555f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions(da)); 1565f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(da)); 1575f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetDM(snes,da)); 1585f80ce2aSJacob Faibussowitsch CHKERRQ(DMDASetFieldName(da,0,"x-velocity")); 1595f80ce2aSJacob Faibussowitsch CHKERRQ(DMDASetFieldName(da,1,"y-velocity")); 1605f80ce2aSJacob Faibussowitsch CHKERRQ(DMDASetFieldName(da,2,"pressure")); 1615f80ce2aSJacob Faibussowitsch CHKERRQ(DMDASetFieldName(da,3,"temperature")); 162c4762a1bSJed Brown 163c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 164c4762a1bSJed Brown Create user context, set problem data, create vector data structures. 165c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscNew(&user)); 167c4762a1bSJed Brown user->param = ¶m; 168c4762a1bSJed Brown user->grid = &grid; 1695f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetApplicationContext(da,user)); 1705f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector(da,&(user->Xguess))); 171c4762a1bSJed Brown 172c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 173c4762a1bSJed Brown Set up the SNES solver with callback functions. 174c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1755f80ce2aSJacob Faibussowitsch CHKERRQ(DMDASNESSetFunctionLocal(da,INSERT_VALUES,(PetscErrorCode (*)(DMDALocalInfo*,void*,void*,void*))FormFunctionLocal,(void*)user)); 1765f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetFromOptions(snes)); 177c4762a1bSJed Brown 1785f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetConvergenceTest(snes,SNESConverged_Interactive,(void*)user,NULL)); 1795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPushSignalHandler(InteractiveHandler,(void*)user)); 180c4762a1bSJed Brown 181c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 182c4762a1bSJed Brown Initialize and solve the nonlinear system 183c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1845f80ce2aSJacob Faibussowitsch CHKERRQ(Initialize(da)); 1855f80ce2aSJacob Faibussowitsch CHKERRQ(UpdateSolution(snes,user,&nits)); 186c4762a1bSJed Brown 187c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 188c4762a1bSJed Brown Output variables. 189c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1905f80ce2aSJacob Faibussowitsch CHKERRQ(DoOutput(snes,nits)); 191c4762a1bSJed Brown 192c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 193c4762a1bSJed Brown Free work space. 194c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1955f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&user->Xguess)); 1965f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&user->x)); 1975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(user)); 1985f80ce2aSJacob Faibussowitsch CHKERRQ(SNESDestroy(&snes)); 1995f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&da)); 2005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPopSignalHandler()); 201*b122ec5aSJacob Faibussowitsch CHKERRQ(PetscFinalize()); 202*b122ec5aSJacob Faibussowitsch return 0; 203c4762a1bSJed Brown } 204c4762a1bSJed Brown 205c4762a1bSJed Brown /*===================================================================== 206c4762a1bSJed Brown PETSc INTERACTION FUNCTIONS (initialize & call SNESSolve) 207c4762a1bSJed Brown =====================================================================*/ 208c4762a1bSJed Brown 209c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 210c4762a1bSJed Brown /* manages solve: adaptive continuation method */ 211c4762a1bSJed Brown PetscErrorCode UpdateSolution(SNES snes, AppCtx *user, PetscInt *nits) 212c4762a1bSJed Brown { 213c4762a1bSJed Brown KSP ksp; 214c4762a1bSJed Brown PC pc; 215c4762a1bSJed Brown SNESConvergedReason reason = SNES_CONVERGED_ITERATING; 216c4762a1bSJed Brown Parameter *param = user->param; 217c4762a1bSJed Brown PetscReal cont_incr=0.3; 218c4762a1bSJed Brown PetscInt its; 219c4762a1bSJed Brown PetscBool q = PETSC_FALSE; 220c4762a1bSJed Brown DM dm; 221c4762a1bSJed Brown 222c4762a1bSJed Brown PetscFunctionBeginUser; 2235f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetDM(snes,&dm)); 2245f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector(dm,&user->x)); 2255f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetKSP(snes,&ksp)); 2265f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(ksp, &pc)); 2275f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetComputeSingularValues(ksp, PETSC_TRUE)); 228c4762a1bSJed Brown 229c4762a1bSJed Brown *nits=0; 230c4762a1bSJed Brown 231c4762a1bSJed Brown /* Isoviscous solve */ 232c4762a1bSJed Brown if (param->ivisc == VISC_CONST && !param->stop_solve) { 233c4762a1bSJed Brown param->ivisc = VISC_CONST; 234c4762a1bSJed Brown 2355f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSolve(snes,0,user->x)); 2365f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetConvergedReason(snes,&reason)); 2375f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetIterationNumber(snes,&its)); 238c4762a1bSJed Brown *nits += its; 2395f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(user->x,user->Xguess)); 240c4762a1bSJed Brown if (param->stop_solve) goto done; 241c4762a1bSJed Brown } 242c4762a1bSJed Brown 243c4762a1bSJed Brown /* Olivine diffusion creep */ 244c4762a1bSJed Brown if (param->ivisc >= VISC_DIFN && !param->stop_solve) { 2455f80ce2aSJacob Faibussowitsch if (!q) CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"Computing Variable Viscosity Solution\n")); 246c4762a1bSJed Brown 247c4762a1bSJed Brown /* continuation method on viscosity cutoff */ 248c4762a1bSJed Brown for (param->continuation=0.0;; param->continuation+=cont_incr) { 2495f80ce2aSJacob Faibussowitsch if (!q) CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Continuation parameter = %g\n", (double)param->continuation)); 250c4762a1bSJed Brown 251c4762a1bSJed Brown /* solve the non-linear system */ 2525f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(user->Xguess,user->x)); 2535f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSolve(snes,0,user->x)); 2545f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetConvergedReason(snes,&reason)); 2555f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetIterationNumber(snes,&its)); 256c4762a1bSJed Brown *nits += its; 2575f80ce2aSJacob Faibussowitsch if (!q) CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," SNES iterations: %D, Cumulative: %D\n", its, *nits)); 258c4762a1bSJed Brown if (param->stop_solve) goto done; 259c4762a1bSJed Brown 260c4762a1bSJed Brown if (reason<0) { 261c4762a1bSJed Brown /* NOT converged */ 262c4762a1bSJed Brown cont_incr = -PetscAbsReal(cont_incr)/2.0; 263c4762a1bSJed Brown if (PetscAbsReal(cont_incr)<0.01) goto done; 264c4762a1bSJed Brown 265c4762a1bSJed Brown } else { 266c4762a1bSJed Brown /* converged */ 2675f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(user->x,user->Xguess)); 268c4762a1bSJed Brown if (param->continuation >= 1.0) goto done; 269c4762a1bSJed Brown if (its<=3) cont_incr = 0.30001; 270c4762a1bSJed Brown else if (its<=8) cont_incr = 0.15001; 271c4762a1bSJed Brown else cont_incr = 0.10001; 272c4762a1bSJed Brown 273c4762a1bSJed Brown if (param->continuation+cont_incr > 1.0) cont_incr = 1.0 - param->continuation; 274c4762a1bSJed Brown } /* endif reason<0 */ 275c4762a1bSJed Brown } 276c4762a1bSJed Brown } 277c4762a1bSJed Brown done: 2785f80ce2aSJacob Faibussowitsch if (param->stop_solve && !q) CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"USER SIGNAL: stopping solve.\n")); 2795f80ce2aSJacob Faibussowitsch if (reason<0 && !q) CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"FAILED TO CONVERGE: stopping solve.\n")); 280c4762a1bSJed Brown PetscFunctionReturn(0); 281c4762a1bSJed Brown } 282c4762a1bSJed Brown 283c4762a1bSJed Brown /*===================================================================== 284c4762a1bSJed Brown PHYSICS FUNCTIONS (compute the discrete residual) 285c4762a1bSJed Brown =====================================================================*/ 286c4762a1bSJed Brown 287c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 2889fbee547SJacob Faibussowitsch static inline PetscScalar UInterp(Field **x, PetscInt i, PetscInt j) 289c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 290c4762a1bSJed Brown { 291c4762a1bSJed Brown return 0.25*(x[j][i].u+x[j+1][i].u+x[j][i+1].u+x[j+1][i+1].u); 292c4762a1bSJed Brown } 293c4762a1bSJed Brown 294c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 2959fbee547SJacob Faibussowitsch static inline PetscScalar WInterp(Field **x, PetscInt i, PetscInt j) 296c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 297c4762a1bSJed Brown { 298c4762a1bSJed Brown return 0.25*(x[j][i].w+x[j+1][i].w+x[j][i+1].w+x[j+1][i+1].w); 299c4762a1bSJed Brown } 300c4762a1bSJed Brown 301c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 3029fbee547SJacob Faibussowitsch static inline PetscScalar PInterp(Field **x, PetscInt i, PetscInt j) 303c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 304c4762a1bSJed Brown { 305c4762a1bSJed Brown return 0.25*(x[j][i].p+x[j+1][i].p+x[j][i+1].p+x[j+1][i+1].p); 306c4762a1bSJed Brown } 307c4762a1bSJed Brown 308c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 3099fbee547SJacob Faibussowitsch static inline PetscScalar TInterp(Field **x, PetscInt i, PetscInt j) 310c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 311c4762a1bSJed Brown { 312c4762a1bSJed Brown return 0.25*(x[j][i].T+x[j+1][i].T+x[j][i+1].T+x[j+1][i+1].T); 313c4762a1bSJed Brown } 314c4762a1bSJed Brown 315c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 316c4762a1bSJed Brown /* isoviscous analytic solution for IC */ 3179fbee547SJacob Faibussowitsch static inline PetscScalar HorizVelocity(PetscInt i, PetscInt j, AppCtx *user) 318c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 319c4762a1bSJed Brown { 320c4762a1bSJed Brown Parameter *param = user->param; 321c4762a1bSJed Brown GridInfo *grid = user->grid; 322c4762a1bSJed Brown PetscScalar st, ct, th, c=param->c, d=param->d; 323c4762a1bSJed Brown PetscReal x, z,r; 324c4762a1bSJed Brown 325c4762a1bSJed Brown x = (i - grid->jlid)*grid->dx; z = (j - grid->jlid - 0.5)*grid->dz; 326c4762a1bSJed Brown r = PetscSqrtReal(x*x+z*z); 327c4762a1bSJed Brown st = z/r; 328c4762a1bSJed Brown ct = x/r; 329c4762a1bSJed Brown th = PetscAtanReal(z/x); 330c4762a1bSJed Brown return ct*(c*th*st+d*(st+th*ct)) + st*(c*(st-th*ct)+d*th*st); 331c4762a1bSJed Brown } 332c4762a1bSJed Brown 333c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 334c4762a1bSJed Brown /* isoviscous analytic solution for IC */ 3359fbee547SJacob Faibussowitsch static inline PetscScalar VertVelocity(PetscInt i, PetscInt j, AppCtx *user) 336c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 337c4762a1bSJed Brown { 338c4762a1bSJed Brown Parameter *param = user->param; 339c4762a1bSJed Brown GridInfo *grid = user->grid; 340c4762a1bSJed Brown PetscScalar st, ct, th, c=param->c, d=param->d; 341c4762a1bSJed Brown PetscReal x, z, r; 342c4762a1bSJed Brown 343c4762a1bSJed Brown x = (i - grid->jlid - 0.5)*grid->dx; z = (j - grid->jlid)*grid->dz; 344c4762a1bSJed Brown r = PetscSqrtReal(x*x+z*z); st = z/r; ct = x/r; th = PetscAtanReal(z/x); 345c4762a1bSJed Brown return st*(c*th*st+d*(st+th*ct)) - ct*(c*(st-th*ct)+d*th*st); 346c4762a1bSJed Brown } 347c4762a1bSJed Brown 348c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 349c4762a1bSJed Brown /* isoviscous analytic solution for IC */ 3509fbee547SJacob Faibussowitsch static inline PetscScalar Pressure(PetscInt i, PetscInt j, AppCtx *user) 351c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 352c4762a1bSJed Brown { 353c4762a1bSJed Brown Parameter *param = user->param; 354c4762a1bSJed Brown GridInfo *grid = user->grid; 355c4762a1bSJed Brown PetscScalar x, z, r, st, ct, c=param->c, d=param->d; 356c4762a1bSJed Brown 357c4762a1bSJed Brown x = (i - grid->jlid - 0.5)*grid->dx; z = (j - grid->jlid - 0.5)*grid->dz; 358c4762a1bSJed Brown r = PetscSqrtReal(x*x+z*z); st = z/r; ct = x/r; 359c4762a1bSJed Brown return (-2.0*(c*ct-d*st)/r); 360c4762a1bSJed Brown } 361c4762a1bSJed Brown 362c4762a1bSJed Brown /* computes the second invariant of the strain rate tensor */ 3639fbee547SJacob Faibussowitsch static inline PetscScalar CalcSecInv(Field **x, PetscInt i, PetscInt j, PetscInt ipos, AppCtx *user) 364c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 365c4762a1bSJed Brown { 366c4762a1bSJed Brown Parameter *param = user->param; 367c4762a1bSJed Brown GridInfo *grid = user->grid; 368c4762a1bSJed Brown PetscInt ilim =grid->ni-1, jlim=grid->nj-1; 369c4762a1bSJed Brown PetscScalar uN,uS,uE,uW,wN,wS,wE,wW; 370c4762a1bSJed Brown PetscScalar eps11, eps12, eps22; 371c4762a1bSJed Brown 372c4762a1bSJed Brown if (i<j) return EPS_ZERO; 373c4762a1bSJed Brown if (i==ilim) i--; 374c4762a1bSJed Brown if (j==jlim) j--; 375c4762a1bSJed Brown 376c4762a1bSJed Brown if (ipos==CELL_CENTER) { /* on cell center */ 377c4762a1bSJed Brown if (j<=grid->jlid) return EPS_ZERO; 378c4762a1bSJed Brown 379c4762a1bSJed Brown uE = x[j][i].u; uW = x[j][i-1].u; 380c4762a1bSJed Brown wN = x[j][i].w; wS = x[j-1][i].w; 381c4762a1bSJed Brown wE = WInterp(x,i,j-1); 382c4762a1bSJed Brown if (i==j) { 383c4762a1bSJed Brown uN = param->cb; wW = param->sb; 384c4762a1bSJed Brown } else { 385c4762a1bSJed Brown uN = UInterp(x,i-1,j); wW = WInterp(x,i-1,j-1); 386c4762a1bSJed Brown } 387c4762a1bSJed Brown 388c4762a1bSJed Brown if (j==grid->jlid+1) uS = 0.0; 389c4762a1bSJed Brown else uS = UInterp(x,i-1,j-1); 390c4762a1bSJed Brown 391c4762a1bSJed Brown } else { /* on CELL_CORNER */ 392c4762a1bSJed Brown if (j<grid->jlid) return EPS_ZERO; 393c4762a1bSJed Brown 394c4762a1bSJed Brown uN = x[j+1][i].u; uS = x[j][i].u; 395c4762a1bSJed Brown wE = x[j][i+1].w; wW = x[j][i].w; 396c4762a1bSJed Brown if (i==j) { 397c4762a1bSJed Brown wN = param->sb; 398c4762a1bSJed Brown uW = param->cb; 399c4762a1bSJed Brown } else { 400c4762a1bSJed Brown wN = WInterp(x,i,j); 401c4762a1bSJed Brown uW = UInterp(x,i-1,j); 402c4762a1bSJed Brown } 403c4762a1bSJed Brown 404c4762a1bSJed Brown if (j==grid->jlid) { 405c4762a1bSJed Brown uE = 0.0; uW = 0.0; 406c4762a1bSJed Brown uS = -uN; 407c4762a1bSJed Brown wS = -wN; 408c4762a1bSJed Brown } else { 409c4762a1bSJed Brown uE = UInterp(x,i,j); 410c4762a1bSJed Brown wS = WInterp(x,i,j-1); 411c4762a1bSJed Brown } 412c4762a1bSJed Brown } 413c4762a1bSJed Brown 414c4762a1bSJed Brown eps11 = (uE-uW)/grid->dx; eps22 = (wN-wS)/grid->dz; 415c4762a1bSJed Brown eps12 = 0.5*((uN-uS)/grid->dz + (wE-wW)/grid->dx); 416c4762a1bSJed Brown 417c4762a1bSJed Brown return PetscSqrtReal(0.5*(eps11*eps11 + 2.0*eps12*eps12 + eps22*eps22)); 418c4762a1bSJed Brown } 419c4762a1bSJed Brown 420c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 421c4762a1bSJed Brown /* computes the shear viscosity */ 4229fbee547SJacob Faibussowitsch static inline PetscScalar Viscosity(PetscScalar T, PetscScalar eps, PetscScalar z, Parameter *param) 423c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 424c4762a1bSJed Brown { 425c4762a1bSJed Brown PetscReal result =0.0; 426c4762a1bSJed Brown ViscParam difn =param->diffusion, disl=param->dislocation; 427c4762a1bSJed Brown PetscInt iVisc =param->ivisc; 428c4762a1bSJed Brown PetscScalar eps_scale=param->V/(param->L*1000.0); 429c4762a1bSJed Brown PetscScalar strain_power, v1, v2, P; 430c4762a1bSJed Brown PetscScalar rho_g = 32340.0, R=8.3144; 431c4762a1bSJed Brown 432c4762a1bSJed Brown P = rho_g*(z*param->L*1000.0); /* Pa */ 433c4762a1bSJed Brown 434c4762a1bSJed Brown if (iVisc==VISC_CONST) { 435c4762a1bSJed Brown /* constant viscosity */ 436c4762a1bSJed Brown return 1.0; 437c4762a1bSJed Brown } else if (iVisc==VISC_DIFN) { 438c4762a1bSJed Brown /* diffusion creep rheology */ 439c4762a1bSJed Brown result = PetscRealPart((difn.A*PetscExpScalar((difn.Estar + P*difn.Vstar)/R/(T+273.0))/param->eta0)); 440c4762a1bSJed Brown } else if (iVisc==VISC_DISL) { 441c4762a1bSJed Brown /* dislocation creep rheology */ 442c4762a1bSJed Brown strain_power = PetscPowScalar(eps*eps_scale, (1.0-disl.n)/disl.n); 443c4762a1bSJed Brown 444c4762a1bSJed Brown result = PetscRealPart(disl.A*PetscExpScalar((disl.Estar + P*disl.Vstar)/disl.n/R/(T+273.0))*strain_power/param->eta0); 445c4762a1bSJed Brown } else if (iVisc==VISC_FULL) { 446c4762a1bSJed Brown /* dislocation/diffusion creep rheology */ 447c4762a1bSJed Brown strain_power = PetscPowScalar(eps*eps_scale, (1.0-disl.n)/disl.n); 448c4762a1bSJed Brown 449c4762a1bSJed Brown v1 = difn.A*PetscExpScalar((difn.Estar + P*difn.Vstar)/R/(T+273.0))/param->eta0; 450c4762a1bSJed Brown v2 = disl.A*PetscExpScalar((disl.Estar + P*disl.Vstar)/disl.n/R/(T+273.0))*strain_power/param->eta0; 451c4762a1bSJed Brown 452c4762a1bSJed Brown result = PetscRealPart(1.0/(1.0/v1 + 1.0/v2)); 453c4762a1bSJed Brown } 454c4762a1bSJed Brown 455c4762a1bSJed Brown /* max viscosity is param->eta0 */ 456c4762a1bSJed Brown result = PetscMin(result, 1.0); 457c4762a1bSJed Brown /* min viscosity is param->visc_cutoff */ 458c4762a1bSJed Brown result = PetscMax(result, param->visc_cutoff); 459c4762a1bSJed Brown /* continuation method */ 460c4762a1bSJed Brown result = PetscPowReal(result,param->continuation); 461c4762a1bSJed Brown return result; 462c4762a1bSJed Brown } 463c4762a1bSJed Brown 464c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 465c4762a1bSJed Brown /* computes the residual of the x-component of eqn (1) above */ 4669fbee547SJacob Faibussowitsch static inline PetscScalar XMomentumResidual(Field **x, PetscInt i, PetscInt j, AppCtx *user) 467c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 468c4762a1bSJed Brown { 469c4762a1bSJed Brown Parameter *param=user->param; 470c4762a1bSJed Brown GridInfo *grid =user->grid; 471c4762a1bSJed Brown PetscScalar dx = grid->dx, dz=grid->dz; 472c4762a1bSJed Brown PetscScalar etaN,etaS,etaE,etaW,epsN=0.0,epsS=0.0,epsE=0.0,epsW=0.0; 473c4762a1bSJed Brown PetscScalar TE=0.0,TN=0.0,TS=0.0,TW=0.0, dPdx, residual, z_scale; 474c4762a1bSJed Brown PetscScalar dudxW,dudxE,dudzN,dudzS,dwdxN,dwdxS; 475c4762a1bSJed Brown PetscInt jlim = grid->nj-1; 476c4762a1bSJed Brown 477c4762a1bSJed Brown z_scale = param->z_scale; 478c4762a1bSJed Brown 479c4762a1bSJed Brown if (param->ivisc==VISC_DIFN || param->ivisc>=VISC_DISL) { /* viscosity is T-dependent */ 480c4762a1bSJed Brown TS = param->potentialT * TInterp(x,i,j-1) * PetscExpScalar((j-1.0)*dz*z_scale); 481c4762a1bSJed Brown if (j==jlim) TN = TS; 482c4762a1bSJed Brown else TN = param->potentialT * TInterp(x,i,j) * PetscExpScalar(j*dz*z_scale); 483c4762a1bSJed Brown TW = param->potentialT * x[j][i].T * PetscExpScalar((j-0.5)*dz*z_scale); 484c4762a1bSJed Brown TE = param->potentialT * x[j][i+1].T * PetscExpScalar((j-0.5)*dz*z_scale); 485c4762a1bSJed Brown if (param->ivisc>=VISC_DISL) { /* olivine dislocation creep */ 486c4762a1bSJed Brown epsN = CalcSecInv(x,i,j, CELL_CORNER,user); 487c4762a1bSJed Brown epsS = CalcSecInv(x,i,j-1,CELL_CORNER,user); 488c4762a1bSJed Brown epsE = CalcSecInv(x,i+1,j,CELL_CENTER,user); 489c4762a1bSJed Brown epsW = CalcSecInv(x,i,j, CELL_CENTER,user); 490c4762a1bSJed Brown } 491c4762a1bSJed Brown } 492c4762a1bSJed Brown etaN = Viscosity(TN,epsN,dz*(j+0.5),param); 493c4762a1bSJed Brown etaS = Viscosity(TS,epsS,dz*(j-0.5),param); 494c4762a1bSJed Brown etaW = Viscosity(TW,epsW,dz*j,param); 495c4762a1bSJed Brown etaE = Viscosity(TE,epsE,dz*j,param); 496c4762a1bSJed Brown 497c4762a1bSJed Brown dPdx = (x[j][i+1].p - x[j][i].p)/dx; 498c4762a1bSJed Brown if (j==jlim) dudzN = etaN * (x[j][i].w - x[j][i+1].w)/dx; 499c4762a1bSJed Brown else dudzN = etaN * (x[j+1][i].u - x[j][i].u) /dz; 500c4762a1bSJed Brown dudzS = etaS * (x[j][i].u - x[j-1][i].u)/dz; 501c4762a1bSJed Brown dudxE = etaE * (x[j][i+1].u - x[j][i].u) /dx; 502c4762a1bSJed Brown dudxW = etaW * (x[j][i].u - x[j][i-1].u)/dx; 503c4762a1bSJed Brown 504c4762a1bSJed Brown residual = -dPdx /* X-MOMENTUM EQUATION*/ 505c4762a1bSJed Brown +(dudxE - dudxW)/dx 506c4762a1bSJed Brown +(dudzN - dudzS)/dz; 507c4762a1bSJed Brown 508c4762a1bSJed Brown if (param->ivisc!=VISC_CONST) { 509c4762a1bSJed Brown dwdxN = etaN * (x[j][i+1].w - x[j][i].w) /dx; 510c4762a1bSJed Brown dwdxS = etaS * (x[j-1][i+1].w - x[j-1][i].w)/dx; 511c4762a1bSJed Brown 512c4762a1bSJed Brown residual += (dudxE - dudxW)/dx + (dwdxN - dwdxS)/dz; 513c4762a1bSJed Brown } 514c4762a1bSJed Brown 515c4762a1bSJed Brown return residual; 516c4762a1bSJed Brown } 517c4762a1bSJed Brown 518c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 519c4762a1bSJed Brown /* computes the residual of the z-component of eqn (1) above */ 5209fbee547SJacob Faibussowitsch static inline PetscScalar ZMomentumResidual(Field **x, PetscInt i, PetscInt j, AppCtx *user) 521c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 522c4762a1bSJed Brown { 523c4762a1bSJed Brown Parameter *param=user->param; 524c4762a1bSJed Brown GridInfo *grid =user->grid; 525c4762a1bSJed Brown PetscScalar dx = grid->dx, dz=grid->dz; 526c4762a1bSJed Brown PetscScalar etaN =0.0,etaS=0.0,etaE=0.0,etaW=0.0,epsN=0.0,epsS=0.0,epsE=0.0,epsW=0.0; 527c4762a1bSJed Brown PetscScalar TE =0.0,TN=0.0,TS=0.0,TW=0.0, dPdz, residual,z_scale; 528c4762a1bSJed Brown PetscScalar dudzE,dudzW,dwdxW,dwdxE,dwdzN,dwdzS; 529c4762a1bSJed Brown PetscInt ilim = grid->ni-1; 530c4762a1bSJed Brown 531c4762a1bSJed Brown /* geometric and other parameters */ 532c4762a1bSJed Brown z_scale = param->z_scale; 533c4762a1bSJed Brown 534c4762a1bSJed Brown /* viscosity */ 535c4762a1bSJed Brown if (param->ivisc==VISC_DIFN || param->ivisc>=VISC_DISL) { /* viscosity is T-dependent */ 536c4762a1bSJed Brown TN = param->potentialT * x[j+1][i].T * PetscExpScalar((j+0.5)*dz*z_scale); 537c4762a1bSJed Brown TS = param->potentialT * x[j][i].T * PetscExpScalar((j-0.5)*dz*z_scale); 538c4762a1bSJed Brown TW = param->potentialT * TInterp(x,i-1,j) * PetscExpScalar(j*dz*z_scale); 539c4762a1bSJed Brown if (i==ilim) TE = TW; 540c4762a1bSJed Brown else TE = param->potentialT * TInterp(x,i,j) * PetscExpScalar(j*dz*z_scale); 541c4762a1bSJed Brown if (param->ivisc>=VISC_DISL) { /* olivine dislocation creep */ 542c4762a1bSJed Brown epsN = CalcSecInv(x,i,j+1,CELL_CENTER,user); 543c4762a1bSJed Brown epsS = CalcSecInv(x,i,j, CELL_CENTER,user); 544c4762a1bSJed Brown epsE = CalcSecInv(x,i,j, CELL_CORNER,user); 545c4762a1bSJed Brown epsW = CalcSecInv(x,i-1,j,CELL_CORNER,user); 546c4762a1bSJed Brown } 547c4762a1bSJed Brown } 548c4762a1bSJed Brown etaN = Viscosity(TN,epsN,dz*(j+1.0),param); 549c4762a1bSJed Brown etaS = Viscosity(TS,epsS,dz*(j+0.0),param); 550c4762a1bSJed Brown etaW = Viscosity(TW,epsW,dz*(j+0.5),param); 551c4762a1bSJed Brown etaE = Viscosity(TE,epsE,dz*(j+0.5),param); 552c4762a1bSJed Brown 553c4762a1bSJed Brown dPdz = (x[j+1][i].p - x[j][i].p)/dz; 554c4762a1bSJed Brown dwdzN = etaN * (x[j+1][i].w - x[j][i].w)/dz; 555c4762a1bSJed Brown dwdzS = etaS * (x[j][i].w - x[j-1][i].w)/dz; 556c4762a1bSJed Brown if (i==ilim) dwdxE = etaE * (x[j][i].u - x[j+1][i].u)/dz; 557c4762a1bSJed Brown else dwdxE = etaE * (x[j][i+1].w - x[j][i].w) /dx; 558c4762a1bSJed Brown dwdxW = 2.0*etaW * (x[j][i].w - x[j][i-1].w)/dx; 559c4762a1bSJed Brown 560c4762a1bSJed Brown /* Z-MOMENTUM */ 561c4762a1bSJed Brown residual = -dPdz /* constant viscosity terms */ 562c4762a1bSJed Brown +(dwdzN - dwdzS)/dz 563c4762a1bSJed Brown +(dwdxE - dwdxW)/dx; 564c4762a1bSJed Brown 565c4762a1bSJed Brown if (param->ivisc!=VISC_CONST) { 566c4762a1bSJed Brown dudzE = etaE * (x[j+1][i].u - x[j][i].u)/dz; 567c4762a1bSJed Brown dudzW = etaW * (x[j+1][i-1].u - x[j][i-1].u)/dz; 568c4762a1bSJed Brown 569c4762a1bSJed Brown residual += (dwdzN - dwdzS)/dz + (dudzE - dudzW)/dx; 570c4762a1bSJed Brown } 571c4762a1bSJed Brown 572c4762a1bSJed Brown return residual; 573c4762a1bSJed Brown } 574c4762a1bSJed Brown 575c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 576c4762a1bSJed Brown /* computes the residual of eqn (2) above */ 5779fbee547SJacob Faibussowitsch static inline PetscScalar ContinuityResidual(Field **x, PetscInt i, PetscInt j, AppCtx *user) 578c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 579c4762a1bSJed Brown { 580c4762a1bSJed Brown GridInfo *grid =user->grid; 581c4762a1bSJed Brown PetscScalar uE,uW,wN,wS,dudx,dwdz; 582c4762a1bSJed Brown 583c4762a1bSJed Brown uW = x[j][i-1].u; uE = x[j][i].u; dudx = (uE - uW)/grid->dx; 584c4762a1bSJed Brown wS = x[j-1][i].w; wN = x[j][i].w; dwdz = (wN - wS)/grid->dz; 585c4762a1bSJed Brown 586c4762a1bSJed Brown return dudx + dwdz; 587c4762a1bSJed Brown } 588c4762a1bSJed Brown 589c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 590c4762a1bSJed Brown /* computes the residual of eqn (3) above */ 5919fbee547SJacob Faibussowitsch static inline PetscScalar EnergyResidual(Field **x, PetscInt i, PetscInt j, AppCtx *user) 592c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 593c4762a1bSJed Brown { 594c4762a1bSJed Brown Parameter *param=user->param; 595c4762a1bSJed Brown GridInfo *grid =user->grid; 596c4762a1bSJed Brown PetscScalar dx = grid->dx, dz=grid->dz; 597c4762a1bSJed Brown PetscInt ilim =grid->ni-1, jlim=grid->nj-1, jlid=grid->jlid; 598c4762a1bSJed Brown PetscScalar TE, TN, TS, TW, residual; 599c4762a1bSJed Brown PetscScalar uE,uW,wN,wS; 600c4762a1bSJed Brown PetscScalar fN,fS,fE,fW,dTdxW,dTdxE,dTdzN,dTdzS; 601c4762a1bSJed Brown 602c4762a1bSJed Brown dTdzN = (x[j+1][i].T - x[j][i].T) /dz; 603c4762a1bSJed Brown dTdzS = (x[j][i].T - x[j-1][i].T)/dz; 604c4762a1bSJed Brown dTdxE = (x[j][i+1].T - x[j][i].T) /dx; 605c4762a1bSJed Brown dTdxW = (x[j][i].T - x[j][i-1].T)/dx; 606c4762a1bSJed Brown 607c4762a1bSJed Brown residual = ((dTdzN - dTdzS)/dz + /* diffusion term */ 608c4762a1bSJed Brown (dTdxE - dTdxW)/dx)*dx*dz/param->peclet; 609c4762a1bSJed Brown 610c4762a1bSJed Brown if (j<=jlid && i>=j) { 611c4762a1bSJed Brown /* don't advect in the lid */ 612c4762a1bSJed Brown return residual; 613c4762a1bSJed Brown } else if (i<j) { 614c4762a1bSJed Brown /* beneath the slab sfc */ 615c4762a1bSJed Brown uW = uE = param->cb; 616c4762a1bSJed Brown wS = wN = param->sb; 617c4762a1bSJed Brown } else { 618c4762a1bSJed Brown /* advect in the slab and wedge */ 619c4762a1bSJed Brown uW = x[j][i-1].u; uE = x[j][i].u; 620c4762a1bSJed Brown wS = x[j-1][i].w; wN = x[j][i].w; 621c4762a1bSJed Brown } 622c4762a1bSJed Brown 623c4762a1bSJed Brown if (param->adv_scheme==ADVECT_FV || i==ilim-1 || j==jlim-1 || i==1 || j==1) { 624c4762a1bSJed Brown /* finite volume advection */ 625c4762a1bSJed Brown TS = (x[j][i].T + x[j-1][i].T)/2.0; 626c4762a1bSJed Brown TN = (x[j][i].T + x[j+1][i].T)/2.0; 627c4762a1bSJed Brown TE = (x[j][i].T + x[j][i+1].T)/2.0; 628c4762a1bSJed Brown TW = (x[j][i].T + x[j][i-1].T)/2.0; 629c4762a1bSJed Brown fN = wN*TN*dx; fS = wS*TS*dx; 630c4762a1bSJed Brown fE = uE*TE*dz; fW = uW*TW*dz; 631c4762a1bSJed Brown 632c4762a1bSJed Brown } else { 633c4762a1bSJed Brown /* Fromm advection scheme */ 634c4762a1bSJed Brown fE = (uE *(-x[j][i+2].T + 5.0*(x[j][i+1].T+x[j][i].T)-x[j][i-1].T)/8.0 635c4762a1bSJed Brown - PetscAbsScalar(uE)*(-x[j][i+2].T + 3.0*(x[j][i+1].T-x[j][i].T)+x[j][i-1].T)/8.0)*dz; 636c4762a1bSJed Brown fW = (uW *(-x[j][i+1].T + 5.0*(x[j][i].T+x[j][i-1].T)-x[j][i-2].T)/8.0 637c4762a1bSJed Brown - PetscAbsScalar(uW)*(-x[j][i+1].T + 3.0*(x[j][i].T-x[j][i-1].T)+x[j][i-2].T)/8.0)*dz; 638c4762a1bSJed Brown fN = (wN *(-x[j+2][i].T + 5.0*(x[j+1][i].T+x[j][i].T)-x[j-1][i].T)/8.0 639c4762a1bSJed Brown - PetscAbsScalar(wN)*(-x[j+2][i].T + 3.0*(x[j+1][i].T-x[j][i].T)+x[j-1][i].T)/8.0)*dx; 640c4762a1bSJed Brown fS = (wS *(-x[j+1][i].T + 5.0*(x[j][i].T+x[j-1][i].T)-x[j-2][i].T)/8.0 641c4762a1bSJed Brown - PetscAbsScalar(wS)*(-x[j+1][i].T + 3.0*(x[j][i].T-x[j-1][i].T)+x[j-2][i].T)/8.0)*dx; 642c4762a1bSJed Brown } 643c4762a1bSJed Brown 644c4762a1bSJed Brown residual -= (fE - fW + fN - fS); 645c4762a1bSJed Brown 646c4762a1bSJed Brown return residual; 647c4762a1bSJed Brown } 648c4762a1bSJed Brown 649c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 650c4762a1bSJed Brown /* computes the shear stress---used on the boundaries */ 6519fbee547SJacob Faibussowitsch static inline PetscScalar ShearStress(Field **x, PetscInt i, PetscInt j, PetscInt ipos, AppCtx *user) 652c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 653c4762a1bSJed Brown { 654c4762a1bSJed Brown Parameter *param=user->param; 655c4762a1bSJed Brown GridInfo *grid =user->grid; 656c4762a1bSJed Brown PetscInt ilim =grid->ni-1, jlim=grid->nj-1; 657c4762a1bSJed Brown PetscScalar uN, uS, wE, wW; 658c4762a1bSJed Brown 659c4762a1bSJed Brown if (j<=grid->jlid || i<j || i==ilim || j==jlim) return EPS_ZERO; 660c4762a1bSJed Brown 661c4762a1bSJed Brown if (ipos==CELL_CENTER) { /* on cell center */ 662c4762a1bSJed Brown 663c4762a1bSJed Brown wE = WInterp(x,i,j-1); 664c4762a1bSJed Brown if (i==j) { 665c4762a1bSJed Brown wW = param->sb; 666c4762a1bSJed Brown uN = param->cb; 667c4762a1bSJed Brown } else { 668c4762a1bSJed Brown wW = WInterp(x,i-1,j-1); 669c4762a1bSJed Brown uN = UInterp(x,i-1,j); 670c4762a1bSJed Brown } 671c4762a1bSJed Brown if (j==grid->jlid+1) uS = 0.0; 672c4762a1bSJed Brown else uS = UInterp(x,i-1,j-1); 673c4762a1bSJed Brown 674c4762a1bSJed Brown } else { /* on cell corner */ 675c4762a1bSJed Brown 676c4762a1bSJed Brown uN = x[j+1][i].u; uS = x[j][i].u; 677c4762a1bSJed Brown wW = x[j][i].w; wE = x[j][i+1].w; 678c4762a1bSJed Brown 679c4762a1bSJed Brown } 680c4762a1bSJed Brown 681c4762a1bSJed Brown return (uN-uS)/grid->dz + (wE-wW)/grid->dx; 682c4762a1bSJed Brown } 683c4762a1bSJed Brown 684c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 685c4762a1bSJed Brown /* computes the normal stress---used on the boundaries */ 6869fbee547SJacob Faibussowitsch static inline PetscScalar XNormalStress(Field **x, PetscInt i, PetscInt j, PetscInt ipos, AppCtx *user) 687c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 688c4762a1bSJed Brown { 689c4762a1bSJed Brown Parameter *param=user->param; 690c4762a1bSJed Brown GridInfo *grid =user->grid; 691c4762a1bSJed Brown PetscScalar dx = grid->dx, dz=grid->dz; 692c4762a1bSJed Brown PetscInt ilim =grid->ni-1, jlim=grid->nj-1, ivisc; 693c4762a1bSJed Brown PetscScalar epsC =0.0, etaC, TC, uE, uW, pC, z_scale; 694c4762a1bSJed Brown if (i<j || j<=grid->jlid) return EPS_ZERO; 695c4762a1bSJed Brown 696c4762a1bSJed Brown ivisc=param->ivisc; z_scale = param->z_scale; 697c4762a1bSJed Brown 698c4762a1bSJed Brown if (ipos==CELL_CENTER) { /* on cell center */ 699c4762a1bSJed Brown 700c4762a1bSJed Brown TC = param->potentialT * x[j][i].T * PetscExpScalar((j-0.5)*dz*z_scale); 701c4762a1bSJed Brown if (ivisc>=VISC_DISL) epsC = CalcSecInv(x,i,j,CELL_CENTER,user); 702c4762a1bSJed Brown etaC = Viscosity(TC,epsC,dz*j,param); 703c4762a1bSJed Brown 704c4762a1bSJed Brown uW = x[j][i-1].u; uE = x[j][i].u; 705c4762a1bSJed Brown pC = x[j][i].p; 706c4762a1bSJed Brown 707c4762a1bSJed Brown } else { /* on cell corner */ 708c4762a1bSJed Brown if (i==ilim || j==jlim) return EPS_ZERO; 709c4762a1bSJed Brown 710c4762a1bSJed Brown TC = param->potentialT * TInterp(x,i,j) * PetscExpScalar(j*dz*z_scale); 711c4762a1bSJed Brown if (ivisc>=VISC_DISL) epsC = CalcSecInv(x,i,j,CELL_CORNER,user); 712c4762a1bSJed Brown etaC = Viscosity(TC,epsC,dz*(j+0.5),param); 713c4762a1bSJed Brown 714c4762a1bSJed Brown if (i==j) uW = param->sb; 715c4762a1bSJed Brown else uW = UInterp(x,i-1,j); 716c4762a1bSJed Brown uE = UInterp(x,i,j); pC = PInterp(x,i,j); 717c4762a1bSJed Brown } 718c4762a1bSJed Brown 719c4762a1bSJed Brown return 2.0*etaC*(uE-uW)/dx - pC; 720c4762a1bSJed Brown } 721c4762a1bSJed Brown 722c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 723c4762a1bSJed Brown /* computes the normal stress---used on the boundaries */ 7249fbee547SJacob Faibussowitsch static inline PetscScalar ZNormalStress(Field **x, PetscInt i, PetscInt j, PetscInt ipos, AppCtx *user) 725c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 726c4762a1bSJed Brown { 727c4762a1bSJed Brown Parameter *param=user->param; 728c4762a1bSJed Brown GridInfo *grid =user->grid; 729c4762a1bSJed Brown PetscScalar dz =grid->dz; 730c4762a1bSJed Brown PetscInt ilim =grid->ni-1, jlim=grid->nj-1, ivisc; 731c4762a1bSJed Brown PetscScalar epsC =0.0, etaC, TC; 732c4762a1bSJed Brown PetscScalar pC, wN, wS, z_scale; 733c4762a1bSJed Brown if (i<j || j<=grid->jlid) return EPS_ZERO; 734c4762a1bSJed Brown 735c4762a1bSJed Brown ivisc=param->ivisc; z_scale = param->z_scale; 736c4762a1bSJed Brown 737c4762a1bSJed Brown if (ipos==CELL_CENTER) { /* on cell center */ 738c4762a1bSJed Brown 739c4762a1bSJed Brown TC = param->potentialT * x[j][i].T * PetscExpScalar((j-0.5)*dz*z_scale); 740c4762a1bSJed Brown if (ivisc>=VISC_DISL) epsC = CalcSecInv(x,i,j,CELL_CENTER,user); 741c4762a1bSJed Brown etaC = Viscosity(TC,epsC,dz*j,param); 742c4762a1bSJed Brown wN = x[j][i].w; wS = x[j-1][i].w; pC = x[j][i].p; 743c4762a1bSJed Brown 744c4762a1bSJed Brown } else { /* on cell corner */ 745c4762a1bSJed Brown if ((i==ilim) || (j==jlim)) return EPS_ZERO; 746c4762a1bSJed Brown 747c4762a1bSJed Brown TC = param->potentialT * TInterp(x,i,j) * PetscExpScalar(j*dz*z_scale); 748c4762a1bSJed Brown if (ivisc>=VISC_DISL) epsC = CalcSecInv(x,i,j,CELL_CORNER,user); 749c4762a1bSJed Brown etaC = Viscosity(TC,epsC,dz*(j+0.5),param); 750c4762a1bSJed Brown if (i==j) wN = param->sb; 751c4762a1bSJed Brown else wN = WInterp(x,i,j); 752c4762a1bSJed Brown wS = WInterp(x,i,j-1); pC = PInterp(x,i,j); 753c4762a1bSJed Brown } 754c4762a1bSJed Brown 755c4762a1bSJed Brown return 2.0*etaC*(wN-wS)/dz - pC; 756c4762a1bSJed Brown } 757c4762a1bSJed Brown 758c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 759c4762a1bSJed Brown 760c4762a1bSJed Brown /*===================================================================== 761c4762a1bSJed Brown INITIALIZATION, POST-PROCESSING AND OUTPUT FUNCTIONS 762c4762a1bSJed Brown =====================================================================*/ 763c4762a1bSJed Brown 764c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 765c4762a1bSJed Brown /* initializes the problem parameters and checks for 766c4762a1bSJed Brown command line changes */ 767c4762a1bSJed Brown PetscErrorCode SetParams(Parameter *param, GridInfo *grid) 768c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 769c4762a1bSJed Brown { 770c4762a1bSJed Brown PetscReal SEC_PER_YR = 3600.00*24.00*365.2500; 771c4762a1bSJed Brown PetscReal alpha_g_on_cp_units_inverse_km = 4.0e-5*9.8; 772c4762a1bSJed Brown 773c4762a1bSJed Brown /* domain geometry */ 774c4762a1bSJed Brown param->slab_dip = 45.0; 775c4762a1bSJed Brown param->width = 320.0; /* km */ 776c4762a1bSJed Brown param->depth = 300.0; /* km */ 777c4762a1bSJed Brown param->lid_depth = 35.0; /* km */ 778c4762a1bSJed Brown param->fault_depth = 35.0; /* km */ 779c4762a1bSJed Brown 7805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetReal(NULL,NULL,"-slab_dip",&(param->slab_dip),NULL)); 7815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetReal(NULL,NULL,"-width",&(param->width),NULL)); 7825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetReal(NULL,NULL,"-depth",&(param->depth),NULL)); 7835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetReal(NULL,NULL,"-lid_depth",&(param->lid_depth),NULL)); 7845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetReal(NULL,NULL,"-fault_depth",&(param->fault_depth),NULL)); 785c4762a1bSJed Brown 786c4762a1bSJed Brown param->slab_dip = param->slab_dip*PETSC_PI/180.0; /* radians */ 787c4762a1bSJed Brown 788c4762a1bSJed Brown /* grid information */ 7895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetInt(NULL,NULL, "-jfault",&(grid->jfault),NULL)); 790c4762a1bSJed Brown grid->ni = 82; 7915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetInt(NULL,NULL, "-ni",&(grid->ni),NULL)); 792c4762a1bSJed Brown 793c4762a1bSJed Brown grid->dx = param->width/((PetscReal)(grid->ni-2)); /* km */ 794c4762a1bSJed Brown grid->dz = grid->dx*PetscTanReal(param->slab_dip); /* km */ 795c4762a1bSJed Brown grid->nj = (PetscInt)(param->depth/grid->dz + 3.0); /* gridpoints*/ 796c4762a1bSJed Brown param->depth = grid->dz*(grid->nj-2); /* km */ 797c4762a1bSJed Brown grid->inose = 0; /* gridpoints*/ 7985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetInt(NULL,NULL,"-inose",&(grid->inose),NULL)); 799c4762a1bSJed Brown grid->bx = DM_BOUNDARY_NONE; 800c4762a1bSJed Brown grid->by = DM_BOUNDARY_NONE; 801c4762a1bSJed Brown grid->stencil = DMDA_STENCIL_BOX; 802c4762a1bSJed Brown grid->dof = 4; 803c4762a1bSJed Brown grid->stencil_width = 2; 804c4762a1bSJed Brown grid->mglevels = 1; 805c4762a1bSJed Brown 806c4762a1bSJed Brown /* boundary conditions */ 807c4762a1bSJed Brown param->pv_analytic = PETSC_FALSE; 808c4762a1bSJed Brown param->ibound = BC_NOSTRESS; 8095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetInt(NULL,NULL,"-ibound",&(param->ibound),NULL)); 810c4762a1bSJed Brown 811c4762a1bSJed Brown /* physical constants */ 812c4762a1bSJed Brown param->slab_velocity = 5.0; /* cm/yr */ 813c4762a1bSJed Brown param->slab_age = 50.0; /* Ma */ 814c4762a1bSJed Brown param->lid_age = 50.0; /* Ma */ 815c4762a1bSJed Brown param->kappa = 0.7272e-6; /* m^2/sec */ 816c4762a1bSJed Brown param->potentialT = 1300.0; /* degrees C */ 817c4762a1bSJed Brown 8185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetReal(NULL,NULL,"-slab_velocity",&(param->slab_velocity),NULL)); 8195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetReal(NULL,NULL,"-slab_age",&(param->slab_age),NULL)); 8205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetReal(NULL,NULL,"-lid_age",&(param->lid_age),NULL)); 8215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetReal(NULL,NULL,"-kappa",&(param->kappa),NULL)); 8225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetReal(NULL,NULL,"-potentialT",&(param->potentialT),NULL)); 823c4762a1bSJed Brown 824c4762a1bSJed Brown /* viscosity */ 825c4762a1bSJed Brown param->ivisc = 3; /* 0=isovisc, 1=difn creep, 2=disl creep, 3=full */ 826c4762a1bSJed Brown param->eta0 = 1e24; /* Pa-s */ 827c4762a1bSJed Brown param->visc_cutoff = 0.0; /* factor of eta_0 */ 828c4762a1bSJed Brown param->continuation = 1.0; 829c4762a1bSJed Brown 830c4762a1bSJed Brown /* constants for diffusion creep */ 831c4762a1bSJed Brown param->diffusion.A = 1.8e7; /* Pa-s */ 832c4762a1bSJed Brown param->diffusion.n = 1.0; /* dim'less */ 833c4762a1bSJed Brown param->diffusion.Estar = 375e3; /* J/mol */ 834c4762a1bSJed Brown param->diffusion.Vstar = 5e-6; /* m^3/mol */ 835c4762a1bSJed Brown 836c4762a1bSJed Brown /* constants for param->dislocationocation creep */ 837c4762a1bSJed Brown param->dislocation.A = 2.8969e4; /* Pa-s */ 838c4762a1bSJed Brown param->dislocation.n = 3.5; /* dim'less */ 839c4762a1bSJed Brown param->dislocation.Estar = 530e3; /* J/mol */ 840c4762a1bSJed Brown param->dislocation.Vstar = 14e-6; /* m^3/mol */ 841c4762a1bSJed Brown 8425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetInt(NULL,NULL, "-ivisc",&(param->ivisc),NULL)); 8435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetReal(NULL,NULL,"-visc_cutoff",&(param->visc_cutoff),NULL)); 844c4762a1bSJed Brown 845c4762a1bSJed Brown param->output_ivisc = param->ivisc; 846c4762a1bSJed Brown 8475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetInt(NULL,NULL,"-output_ivisc",&(param->output_ivisc),NULL)); 8485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetReal(NULL,NULL,"-vstar",&(param->dislocation.Vstar),NULL)); 849c4762a1bSJed Brown 850c4762a1bSJed Brown /* output options */ 851c4762a1bSJed Brown param->quiet = PETSC_FALSE; 852c4762a1bSJed Brown param->param_test = PETSC_FALSE; 853c4762a1bSJed Brown 8545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHasName(NULL,NULL,"-quiet",&(param->quiet))); 8555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHasName(NULL,NULL,"-test",&(param->param_test))); 8565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetString(NULL,NULL,"-file",param->filename,sizeof(param->filename),&(param->output_to_file))); 857c4762a1bSJed Brown 858c4762a1bSJed Brown /* advection */ 859c4762a1bSJed Brown param->adv_scheme = ADVECT_FROMM; /* advection scheme: 0=finite vol, 1=Fromm */ 860c4762a1bSJed Brown 8615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetInt(NULL,NULL,"-adv_scheme",&(param->adv_scheme),NULL)); 862c4762a1bSJed Brown 863c4762a1bSJed Brown /* misc. flags */ 864c4762a1bSJed Brown param->stop_solve = PETSC_FALSE; 865c4762a1bSJed Brown param->interrupted = PETSC_FALSE; 866c4762a1bSJed Brown param->kspmon = PETSC_FALSE; 867c4762a1bSJed Brown param->toggle_kspmon = PETSC_FALSE; 868c4762a1bSJed Brown 869c4762a1bSJed Brown /* derived parameters for slab angle */ 870c4762a1bSJed Brown param->sb = PetscSinReal(param->slab_dip); 871c4762a1bSJed Brown param->cb = PetscCosReal(param->slab_dip); 872c4762a1bSJed Brown param->c = param->slab_dip*param->sb/(param->slab_dip*param->slab_dip-param->sb*param->sb); 873c4762a1bSJed Brown param->d = (param->slab_dip*param->cb-param->sb)/(param->slab_dip*param->slab_dip-param->sb*param->sb); 874c4762a1bSJed Brown 875c4762a1bSJed Brown /* length, velocity and time scale for non-dimensionalization */ 876c4762a1bSJed Brown param->L = PetscMin(param->width,param->depth); /* km */ 877c4762a1bSJed Brown param->V = param->slab_velocity/100.0/SEC_PER_YR; /* m/sec */ 878c4762a1bSJed Brown 879c4762a1bSJed Brown /* other unit conversions and derived parameters */ 880c4762a1bSJed Brown param->scaled_width = param->width/param->L; /* dim'less */ 881c4762a1bSJed Brown param->scaled_depth = param->depth/param->L; /* dim'less */ 882c4762a1bSJed Brown param->lid_depth = param->lid_depth/param->L; /* dim'less */ 883c4762a1bSJed Brown param->fault_depth = param->fault_depth/param->L; /* dim'less */ 884c4762a1bSJed Brown grid->dx = grid->dx/param->L; /* dim'less */ 885c4762a1bSJed Brown grid->dz = grid->dz/param->L; /* dim'less */ 886c4762a1bSJed Brown grid->jlid = (PetscInt)(param->lid_depth/grid->dz); /* gridcells */ 887c4762a1bSJed Brown grid->jfault = (PetscInt)(param->fault_depth/grid->dz); /* gridcells */ 888c4762a1bSJed Brown param->lid_depth = grid->jlid*grid->dz; /* dim'less */ 889c4762a1bSJed Brown param->fault_depth = grid->jfault*grid->dz; /* dim'less */ 890c4762a1bSJed Brown grid->corner = grid->jlid+1; /* gridcells */ 891c4762a1bSJed Brown param->peclet = param->V /* m/sec */ 892c4762a1bSJed Brown * param->L*1000.0 /* m */ 893c4762a1bSJed Brown / param->kappa; /* m^2/sec */ 894c4762a1bSJed Brown param->z_scale = param->L * alpha_g_on_cp_units_inverse_km; 895c4762a1bSJed Brown param->skt = PetscSqrtReal(param->kappa*param->slab_age*SEC_PER_YR); 8965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetReal(NULL,NULL,"-peclet",&(param->peclet),NULL)); 897c4762a1bSJed Brown 8985f80ce2aSJacob Faibussowitsch return 0; 899c4762a1bSJed Brown } 900c4762a1bSJed Brown 901c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 902c4762a1bSJed Brown /* prints a report of the problem parameters to stdout */ 903c4762a1bSJed Brown PetscErrorCode ReportParams(Parameter *param, GridInfo *grid) 904c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 905c4762a1bSJed Brown { 906c4762a1bSJed Brown char date[30]; 907c4762a1bSJed Brown 9085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscGetDate(date,30)); 909c4762a1bSJed Brown 910c4762a1bSJed Brown if (!(param->quiet)) { 9115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"---------------------BEGIN ex30 PARAM REPORT-------------------\n")); 9125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"Domain: \n")); 9135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Width = %g km, Depth = %g km\n",(double)param->width,(double)param->depth)); 9145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Slab dip = %g degrees, Slab velocity = %g cm/yr\n",(double)(param->slab_dip*180.0/PETSC_PI),(double)param->slab_velocity)); 9155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Lid depth = %5.2f km, Fault depth = %5.2f km\n",(double)(param->lid_depth*param->L),(double)(param->fault_depth*param->L))); 916c4762a1bSJed Brown 9175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"\nGrid: \n")); 9185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," [ni,nj] = %D, %D [dx,dz] = %g, %g km\n",grid->ni,grid->nj,(double)(grid->dx*param->L),(double)(grid->dz*param->L))); 9195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," jlid = %3D jfault = %3D \n",grid->jlid,grid->jfault)); 9205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Pe = %g\n",(double)param->peclet)); 921c4762a1bSJed Brown 9225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"\nRheology:")); 923c4762a1bSJed Brown if (param->ivisc==VISC_CONST) { 9245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Isoviscous \n")); 925c4762a1bSJed Brown if (param->pv_analytic) { 9265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Pressure and Velocity prescribed! \n")); 927c4762a1bSJed Brown } 928c4762a1bSJed Brown } else if (param->ivisc==VISC_DIFN) { 9295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Diffusion Creep (T-Dependent Newtonian) \n")); 9305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Viscosity range: %g--%g Pa-sec \n",(double)param->eta0,(double)(param->visc_cutoff*param->eta0))); 931c4762a1bSJed Brown } else if (param->ivisc==VISC_DISL) { 9325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Dislocation Creep (T-Dependent Non-Newtonian) \n")); 9335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Viscosity range: %g--%g Pa-sec \n",(double)param->eta0,(double)(param->visc_cutoff*param->eta0))); 934c4762a1bSJed Brown } else if (param->ivisc==VISC_FULL) { 9355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Full Rheology \n")); 9365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Viscosity range: %g--%g Pa-sec \n",(double)param->eta0,(double)(param->visc_cutoff*param->eta0))); 937c4762a1bSJed Brown } else { 9385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Invalid! \n")); 9395f80ce2aSJacob Faibussowitsch return 1; 940c4762a1bSJed Brown } 941c4762a1bSJed Brown 9425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"Boundary condition:")); 943c4762a1bSJed Brown if (param->ibound==BC_ANALYTIC) { 9445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Isoviscous Analytic Dirichlet \n")); 945c4762a1bSJed Brown } else if (param->ibound==BC_NOSTRESS) { 9465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Stress-Free (normal & shear stress)\n")); 947c4762a1bSJed Brown } else if (param->ibound==BC_EXPERMNT) { 9485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Experimental boundary condition \n")); 949c4762a1bSJed Brown } else { 9505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Invalid! \n")); 9515f80ce2aSJacob Faibussowitsch return 1; 952c4762a1bSJed Brown } 953c4762a1bSJed Brown 95460d4fc61SSatish Balay if (param->output_to_file) { 955c4762a1bSJed Brown #if defined(PETSC_HAVE_MATLAB_ENGINE) 9565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"Output Destination: Mat file \"%s\"\n",param->filename)); 957c4762a1bSJed Brown #else 9585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"Output Destination: PETSc binary file \"%s\"\n",param->filename)); 959c4762a1bSJed Brown #endif 96060d4fc61SSatish Balay } 961c4762a1bSJed Brown if (param->output_ivisc != param->ivisc) { 9625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD," Output viscosity: -ivisc %D\n",param->output_ivisc)); 963c4762a1bSJed Brown } 964c4762a1bSJed Brown 9655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"---------------------END ex30 PARAM REPORT---------------------\n")); 966c4762a1bSJed Brown } 967c4762a1bSJed Brown if (param->param_test) PetscEnd(); 9685f80ce2aSJacob Faibussowitsch return 0; 969c4762a1bSJed Brown } 970c4762a1bSJed Brown 971c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 972a5b23f4aSJose E. Roman /* generates an initial guess using the analytic solution for isoviscous 973c4762a1bSJed Brown corner flow */ 974c4762a1bSJed Brown PetscErrorCode Initialize(DM da) 975c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 976c4762a1bSJed Brown { 977c4762a1bSJed Brown AppCtx *user; 978c4762a1bSJed Brown Parameter *param; 979c4762a1bSJed Brown GridInfo *grid; 980c4762a1bSJed Brown PetscInt i,j,is,js,im,jm; 981c4762a1bSJed Brown Field **x; 982c4762a1bSJed Brown Vec Xguess; 983c4762a1bSJed Brown 984c4762a1bSJed Brown /* Get the fine grid */ 9855f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetApplicationContext(da,&user)); 986c4762a1bSJed Brown Xguess = user->Xguess; 987c4762a1bSJed Brown param = user->param; 988c4762a1bSJed Brown grid = user->grid; 9895f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCorners(da,&is,&js,NULL,&im,&jm,NULL)); 9905f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArray(da,Xguess,(void**)&x)); 991c4762a1bSJed Brown 992c4762a1bSJed Brown /* Compute initial guess */ 993c4762a1bSJed Brown for (j=js; j<js+jm; j++) { 994c4762a1bSJed Brown for (i=is; i<is+im; i++) { 995c4762a1bSJed Brown if (i<j) x[j][i].u = param->cb; 996c4762a1bSJed Brown else if (j<=grid->jlid) x[j][i].u = 0.0; 997c4762a1bSJed Brown else x[j][i].u = HorizVelocity(i,j,user); 998c4762a1bSJed Brown 999c4762a1bSJed Brown if (i<=j) x[j][i].w = param->sb; 1000c4762a1bSJed Brown else if (j<=grid->jlid) x[j][i].w = 0.0; 1001c4762a1bSJed Brown else x[j][i].w = VertVelocity(i,j,user); 1002c4762a1bSJed Brown 1003c4762a1bSJed Brown if (i<j || j<=grid->jlid) x[j][i].p = 0.0; 1004c4762a1bSJed Brown else x[j][i].p = Pressure(i,j,user); 1005c4762a1bSJed Brown 1006c4762a1bSJed Brown x[j][i].T = PetscMin(grid->dz*(j-0.5),1.0); 1007c4762a1bSJed Brown } 1008c4762a1bSJed Brown } 1009c4762a1bSJed Brown 1010c4762a1bSJed Brown /* Restore x to Xguess */ 10115f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArray(da,Xguess,(void**)&x)); 1012c4762a1bSJed Brown 1013c4762a1bSJed Brown return 0; 1014c4762a1bSJed Brown } 1015c4762a1bSJed Brown 1016c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 1017c4762a1bSJed Brown /* controls output to a file */ 1018c4762a1bSJed Brown PetscErrorCode DoOutput(SNES snes, PetscInt its) 1019c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 1020c4762a1bSJed Brown { 1021c4762a1bSJed Brown AppCtx *user; 1022c4762a1bSJed Brown Parameter *param; 1023c4762a1bSJed Brown GridInfo *grid; 1024c4762a1bSJed Brown PetscInt ivt; 1025c4762a1bSJed Brown PetscMPIInt rank; 1026c4762a1bSJed Brown PetscViewer viewer; 1027c4762a1bSJed Brown Vec res, pars; 1028c4762a1bSJed Brown MPI_Comm comm; 1029c4762a1bSJed Brown DM da; 1030c4762a1bSJed Brown 10315f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetDM(snes,&da)); 10325f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetApplicationContext(da,&user)); 1033c4762a1bSJed Brown param = user->param; 1034c4762a1bSJed Brown grid = user->grid; 1035c4762a1bSJed Brown ivt = param->ivisc; 1036c4762a1bSJed Brown 1037c4762a1bSJed Brown param->ivisc = param->output_ivisc; 1038c4762a1bSJed Brown 1039c4762a1bSJed Brown /* compute final residual and final viscosity/strain rate fields */ 10405f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetFunction(snes, &res, NULL, NULL)); 10415f80ce2aSJacob Faibussowitsch CHKERRQ(ViscosityField(da, user->x, user->Xguess)); 1042c4762a1bSJed Brown 1043c4762a1bSJed Brown /* get the communicator and the rank of the processor */ 10445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)snes, &comm)); 10455f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 1046c4762a1bSJed Brown 1047c4762a1bSJed Brown if (param->output_to_file) { /* send output to binary file */ 10485f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(comm, &pars)); 1049dd400576SPatrick Sanan if (rank == 0) { /* on processor 0 */ 10505f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(pars, 20, PETSC_DETERMINE)); 10515f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetFromOptions(pars)); 10525f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(pars,0, (PetscScalar)(grid->ni),INSERT_VALUES)); 10535f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(pars,1, (PetscScalar)(grid->nj),INSERT_VALUES)); 10545f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(pars,2, (PetscScalar)(grid->dx),INSERT_VALUES)); 10555f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(pars,3, (PetscScalar)(grid->dz),INSERT_VALUES)); 10565f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(pars,4, (PetscScalar)(param->L),INSERT_VALUES)); 10575f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(pars,5, (PetscScalar)(param->V),INSERT_VALUES)); 1058c4762a1bSJed Brown /* skipped 6 intentionally */ 10595f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(pars,7, (PetscScalar)(param->slab_dip),INSERT_VALUES)); 10605f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(pars,8, (PetscScalar)(grid->jlid),INSERT_VALUES)); 10615f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(pars,9, (PetscScalar)(param->lid_depth),INSERT_VALUES)); 10625f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(pars,10,(PetscScalar)(grid->jfault),INSERT_VALUES)); 10635f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(pars,11,(PetscScalar)(param->fault_depth),INSERT_VALUES)); 10645f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(pars,12,(PetscScalar)(param->potentialT),INSERT_VALUES)); 10655f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(pars,13,(PetscScalar)(param->ivisc),INSERT_VALUES)); 10665f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(pars,14,(PetscScalar)(param->visc_cutoff),INSERT_VALUES)); 10675f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(pars,15,(PetscScalar)(param->ibound),INSERT_VALUES)); 10685f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(pars,16,(PetscScalar)(its),INSERT_VALUES)); 1069c4762a1bSJed Brown } else { /* on some other processor */ 10705f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(pars, 0, PETSC_DETERMINE)); 10715f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetFromOptions(pars)); 1072c4762a1bSJed Brown } 10735f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(pars)); CHKERRQ(VecAssemblyEnd(pars)); 1074c4762a1bSJed Brown 1075c4762a1bSJed Brown /* create viewer */ 1076c4762a1bSJed Brown #if defined(PETSC_HAVE_MATLAB_ENGINE) 10775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerMatlabOpen(PETSC_COMM_WORLD,param->filename,FILE_MODE_WRITE,&viewer)); 1078c4762a1bSJed Brown #else 10795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerBinaryOpen(PETSC_COMM_WORLD,param->filename,FILE_MODE_WRITE,&viewer)); 1080c4762a1bSJed Brown #endif 1081c4762a1bSJed Brown 1082c4762a1bSJed Brown /* send vectors to viewer */ 10835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)res,"res")); 10845f80ce2aSJacob Faibussowitsch CHKERRQ(VecView(res,viewer)); 10855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)user->x,"out")); 10865f80ce2aSJacob Faibussowitsch CHKERRQ(VecView(user->x, viewer)); 10875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)(user->Xguess),"aux")); 10885f80ce2aSJacob Faibussowitsch CHKERRQ(VecView(user->Xguess, viewer)); 10895f80ce2aSJacob Faibussowitsch CHKERRQ(StressField(da)); /* compute stress fields */ 10905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)(user->Xguess),"str")); 10915f80ce2aSJacob Faibussowitsch CHKERRQ(VecView(user->Xguess, viewer)); 10925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)pars,"par")); 10935f80ce2aSJacob Faibussowitsch CHKERRQ(VecView(pars, viewer)); 1094c4762a1bSJed Brown 1095c4762a1bSJed Brown /* destroy viewer and vector */ 10965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDestroy(&viewer)); 10975f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pars)); 1098c4762a1bSJed Brown } 1099c4762a1bSJed Brown 1100c4762a1bSJed Brown param->ivisc = ivt; 1101c4762a1bSJed Brown return 0; 1102c4762a1bSJed Brown } 1103c4762a1bSJed Brown 1104c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 1105c4762a1bSJed Brown /* Compute both the second invariant of the strain rate tensor and the viscosity, at both cell centers and cell corners */ 1106c4762a1bSJed Brown PetscErrorCode ViscosityField(DM da, Vec X, Vec V) 1107c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 1108c4762a1bSJed Brown { 1109c4762a1bSJed Brown AppCtx *user; 1110c4762a1bSJed Brown Parameter *param; 1111c4762a1bSJed Brown GridInfo *grid; 1112c4762a1bSJed Brown Vec localX; 1113c4762a1bSJed Brown Field **v, **x; 1114c4762a1bSJed Brown PetscReal eps, /* dx,*/ dz, T, epsC, TC; 1115c4762a1bSJed Brown PetscInt i,j,is,js,im,jm,ilim,jlim,ivt; 1116c4762a1bSJed Brown 1117c4762a1bSJed Brown PetscFunctionBeginUser; 11185f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetApplicationContext(da,&user)); 1119c4762a1bSJed Brown param = user->param; 1120c4762a1bSJed Brown grid = user->grid; 1121c4762a1bSJed Brown ivt = param->ivisc; 1122c4762a1bSJed Brown param->ivisc = param->output_ivisc; 1123c4762a1bSJed Brown 11245f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalVector(da, &localX)); 11255f80ce2aSJacob Faibussowitsch CHKERRQ(DMGlobalToLocalBegin(da, X, INSERT_VALUES, localX)); 11265f80ce2aSJacob Faibussowitsch CHKERRQ(DMGlobalToLocalEnd(da, X, INSERT_VALUES, localX)); 11275f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArray(da,localX,(void**)&x)); 11285f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArray(da,V,(void**)&v)); 1129c4762a1bSJed Brown 1130c4762a1bSJed Brown /* Parameters */ 1131c4762a1bSJed Brown /* dx = grid->dx; */ dz = grid->dz; 1132c4762a1bSJed Brown 1133c4762a1bSJed Brown ilim = grid->ni-1; jlim = grid->nj-1; 1134c4762a1bSJed Brown 1135c4762a1bSJed Brown /* Compute real temperature, strain rate and viscosity */ 11365f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCorners(da,&is,&js,NULL,&im,&jm,NULL)); 1137c4762a1bSJed Brown for (j=js; j<js+jm; j++) { 1138c4762a1bSJed Brown for (i=is; i<is+im; i++) { 1139c4762a1bSJed Brown T = PetscRealPart(param->potentialT * x[j][i].T * PetscExpScalar((j-0.5)*dz*param->z_scale)); 1140c4762a1bSJed Brown if (i<ilim && j<jlim) { 1141c4762a1bSJed Brown TC = PetscRealPart(param->potentialT * TInterp(x,i,j) * PetscExpScalar(j*dz*param->z_scale)); 1142c4762a1bSJed Brown } else { 1143c4762a1bSJed Brown TC = T; 1144c4762a1bSJed Brown } 1145c4762a1bSJed Brown eps = PetscRealPart((CalcSecInv(x,i,j,CELL_CENTER,user))); 1146c4762a1bSJed Brown epsC = PetscRealPart(CalcSecInv(x,i,j,CELL_CORNER,user)); 1147c4762a1bSJed Brown 1148c4762a1bSJed Brown v[j][i].u = eps; 1149c4762a1bSJed Brown v[j][i].w = epsC; 1150c4762a1bSJed Brown v[j][i].p = Viscosity(T,eps,dz*(j-0.5),param); 1151c4762a1bSJed Brown v[j][i].T = Viscosity(TC,epsC,dz*j,param); 1152c4762a1bSJed Brown } 1153c4762a1bSJed Brown } 11545f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArray(da,V,(void**)&v)); 11555f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArray(da,localX,(void**)&x)); 11565f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreLocalVector(da, &localX)); 1157c4762a1bSJed Brown 1158c4762a1bSJed Brown param->ivisc = ivt; 1159c4762a1bSJed Brown PetscFunctionReturn(0); 1160c4762a1bSJed Brown } 1161c4762a1bSJed Brown 1162c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 1163c4762a1bSJed Brown /* post-processing: compute stress everywhere */ 1164c4762a1bSJed Brown PetscErrorCode StressField(DM da) 1165c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 1166c4762a1bSJed Brown { 1167c4762a1bSJed Brown AppCtx *user; 1168c4762a1bSJed Brown PetscInt i,j,is,js,im,jm; 1169c4762a1bSJed Brown Vec locVec; 1170c4762a1bSJed Brown Field **x, **y; 1171c4762a1bSJed Brown 11725f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetApplicationContext(da,&user)); 1173c4762a1bSJed Brown 1174c4762a1bSJed Brown /* Get the fine grid of Xguess and X */ 11755f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCorners(da,&is,&js,NULL,&im,&jm,NULL)); 11765f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArray(da,user->Xguess,(void**)&x)); 1177c4762a1bSJed Brown 11785f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalVector(da, &locVec)); 11795f80ce2aSJacob Faibussowitsch CHKERRQ(DMGlobalToLocalBegin(da, user->x, INSERT_VALUES, locVec)); 11805f80ce2aSJacob Faibussowitsch CHKERRQ(DMGlobalToLocalEnd(da, user->x, INSERT_VALUES, locVec)); 11815f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArray(da,locVec,(void**)&y)); 1182c4762a1bSJed Brown 1183c4762a1bSJed Brown /* Compute stress on the corner points */ 1184c4762a1bSJed Brown for (j=js; j<js+jm; j++) { 1185c4762a1bSJed Brown for (i=is; i<is+im; i++) { 1186c4762a1bSJed Brown x[j][i].u = ShearStress(y,i,j,CELL_CENTER,user); 1187c4762a1bSJed Brown x[j][i].w = ShearStress(y,i,j,CELL_CORNER,user); 1188c4762a1bSJed Brown x[j][i].p = XNormalStress(y,i,j,CELL_CENTER,user); 1189c4762a1bSJed Brown x[j][i].T = ZNormalStress(y,i,j,CELL_CENTER,user); 1190c4762a1bSJed Brown } 1191c4762a1bSJed Brown } 1192c4762a1bSJed Brown 1193c4762a1bSJed Brown /* Restore the fine grid of Xguess and X */ 11945f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArray(da,user->Xguess,(void**)&x)); 11955f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArray(da,locVec,(void**)&y)); 11965f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreLocalVector(da, &locVec)); 1197c4762a1bSJed Brown return 0; 1198c4762a1bSJed Brown } 1199c4762a1bSJed Brown 1200c4762a1bSJed Brown /*===================================================================== 1201c4762a1bSJed Brown UTILITY FUNCTIONS 1202c4762a1bSJed Brown =====================================================================*/ 1203c4762a1bSJed Brown 1204c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 1205c4762a1bSJed Brown /* returns the velocity of the subducting slab and handles fault nodes 1206c4762a1bSJed Brown for BC */ 12079fbee547SJacob Faibussowitsch static inline PetscScalar SlabVel(char c, PetscInt i, PetscInt j, AppCtx *user) 1208c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 1209c4762a1bSJed Brown { 1210c4762a1bSJed Brown Parameter *param = user->param; 1211c4762a1bSJed Brown GridInfo *grid = user->grid; 1212c4762a1bSJed Brown 1213c4762a1bSJed Brown if (c=='U' || c=='u') { 1214c4762a1bSJed Brown if (i<j-1) return param->cb; 1215c4762a1bSJed Brown else if (j<=grid->jfault) return 0.0; 1216c4762a1bSJed Brown else return param->cb; 1217c4762a1bSJed Brown 1218c4762a1bSJed Brown } else { 1219c4762a1bSJed Brown if (i<j) return param->sb; 1220c4762a1bSJed Brown else if (j<=grid->jfault) return 0.0; 1221c4762a1bSJed Brown else return param->sb; 1222c4762a1bSJed Brown } 1223c4762a1bSJed Brown } 1224c4762a1bSJed Brown 1225c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 1226c4762a1bSJed Brown /* solution to diffusive half-space cooling model for BC */ 12279fbee547SJacob Faibussowitsch static inline PetscScalar PlateModel(PetscInt j, PetscInt plate, AppCtx *user) 1228c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 1229c4762a1bSJed Brown { 1230c4762a1bSJed Brown Parameter *param = user->param; 1231c4762a1bSJed Brown PetscScalar z; 1232c4762a1bSJed Brown if (plate==PLATE_LID) z = (j-0.5)*user->grid->dz; 1233c4762a1bSJed Brown else z = (j-0.5)*user->grid->dz*param->cb; /* PLATE_SLAB */ 1234c4762a1bSJed Brown #if defined(PETSC_HAVE_ERF) 1235c4762a1bSJed Brown return (PetscReal)(erf((double)PetscRealPart(z*param->L/2.0/param->skt))); 1236c4762a1bSJed Brown #else 1237c4762a1bSJed Brown (*PetscErrorPrintf)("erf() not available on this machine\n"); 1238c4762a1bSJed Brown MPI_Abort(PETSC_COMM_SELF,1); 1239c4762a1bSJed Brown #endif 1240c4762a1bSJed Brown } 1241c4762a1bSJed Brown 1242c4762a1bSJed Brown /*===================================================================== 1243c4762a1bSJed Brown INTERACTIVE SIGNAL HANDLING 1244c4762a1bSJed Brown =====================================================================*/ 1245c4762a1bSJed Brown 1246c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 1247c4762a1bSJed Brown PetscErrorCode SNESConverged_Interactive(SNES snes, PetscInt it,PetscReal xnorm, PetscReal snorm, PetscReal fnorm, SNESConvergedReason *reason, void *ctx) 1248c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 1249c4762a1bSJed Brown { 1250c4762a1bSJed Brown AppCtx *user = (AppCtx*) ctx; 1251c4762a1bSJed Brown Parameter *param = user->param; 1252c4762a1bSJed Brown KSP ksp; 1253c4762a1bSJed Brown 1254c4762a1bSJed Brown PetscFunctionBeginUser; 1255c4762a1bSJed Brown if (param->interrupted) { 1256c4762a1bSJed Brown param->interrupted = PETSC_FALSE; 12575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"USER SIGNAL: exiting SNES solve. \n")); 1258c4762a1bSJed Brown *reason = SNES_CONVERGED_FNORM_ABS; 1259c4762a1bSJed Brown PetscFunctionReturn(0); 1260c4762a1bSJed Brown } else if (param->toggle_kspmon) { 1261c4762a1bSJed Brown param->toggle_kspmon = PETSC_FALSE; 1262c4762a1bSJed Brown 12635f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetKSP(snes, &ksp)); 1264c4762a1bSJed Brown 1265c4762a1bSJed Brown if (param->kspmon) { 12665f80ce2aSJacob Faibussowitsch CHKERRQ(KSPMonitorCancel(ksp)); 1267c4762a1bSJed Brown 1268c4762a1bSJed Brown param->kspmon = PETSC_FALSE; 12695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"USER SIGNAL: deactivating ksp singular value monitor. \n")); 1270c4762a1bSJed Brown } else { 1271c4762a1bSJed Brown PetscViewerAndFormat *vf; 12725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerAndFormatCreate(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_DEFAULT,&vf)); 12735f80ce2aSJacob Faibussowitsch CHKERRQ(KSPMonitorSet(ksp,(PetscErrorCode (*)(KSP,PetscInt,PetscReal,void*))KSPMonitorSingularValue,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy)); 1274c4762a1bSJed Brown 1275c4762a1bSJed Brown param->kspmon = PETSC_TRUE; 12765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"USER SIGNAL: activating ksp singular value monitor. \n")); 1277c4762a1bSJed Brown } 1278c4762a1bSJed Brown } 1279c4762a1bSJed Brown PetscFunctionReturn(SNESConvergedDefault(snes,it,xnorm,snorm,fnorm,reason,ctx)); 1280c4762a1bSJed Brown } 1281c4762a1bSJed Brown 1282c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 1283c4762a1bSJed Brown #include <signal.h> 1284c4762a1bSJed Brown PetscErrorCode InteractiveHandler(int signum, void *ctx) 1285c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 1286c4762a1bSJed Brown { 1287c4762a1bSJed Brown AppCtx *user = (AppCtx*) ctx; 1288c4762a1bSJed Brown Parameter *param = user->param; 1289c4762a1bSJed Brown 1290c4762a1bSJed Brown if (signum == SIGILL) { 1291c4762a1bSJed Brown param->toggle_kspmon = PETSC_TRUE; 1292c4762a1bSJed Brown #if !defined(PETSC_MISSING_SIGCONT) 1293c4762a1bSJed Brown } else if (signum == SIGCONT) { 1294c4762a1bSJed Brown param->interrupted = PETSC_TRUE; 1295c4762a1bSJed Brown #endif 1296c4762a1bSJed Brown #if !defined(PETSC_MISSING_SIGURG) 1297c4762a1bSJed Brown } else if (signum == SIGURG) { 1298c4762a1bSJed Brown param->stop_solve = PETSC_TRUE; 1299c4762a1bSJed Brown #endif 1300c4762a1bSJed Brown } 1301c4762a1bSJed Brown return 0; 1302c4762a1bSJed Brown } 1303c4762a1bSJed Brown 1304c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 1305c4762a1bSJed Brown /* main call-back function that computes the processor-local piece 1306c4762a1bSJed Brown of the residual */ 1307c4762a1bSJed Brown PetscErrorCode FormFunctionLocal(DMDALocalInfo *info,Field **x,Field **f,void *ptr) 1308c4762a1bSJed Brown /*---------------------------------------------------------------------*/ 1309c4762a1bSJed Brown { 1310c4762a1bSJed Brown AppCtx *user = (AppCtx*)ptr; 1311c4762a1bSJed Brown Parameter *param = user->param; 1312c4762a1bSJed Brown GridInfo *grid = user->grid; 1313c4762a1bSJed Brown PetscScalar mag_w, mag_u; 1314c4762a1bSJed Brown PetscInt i,j,mx,mz,ilim,jlim; 1315c4762a1bSJed Brown PetscInt is,ie,js,je,ibound; /* ,ivisc */ 1316c4762a1bSJed Brown 1317c4762a1bSJed Brown PetscFunctionBeginUser; 1318c4762a1bSJed Brown /* Define global and local grid parameters */ 1319c4762a1bSJed Brown mx = info->mx; mz = info->my; 1320c4762a1bSJed Brown ilim = mx-1; jlim = mz-1; 1321c4762a1bSJed Brown is = info->xs; ie = info->xs+info->xm; 1322c4762a1bSJed Brown js = info->ys; je = info->ys+info->ym; 1323c4762a1bSJed Brown 1324c4762a1bSJed Brown /* Define geometric and numeric parameters */ 1325c4762a1bSJed Brown /* ivisc = param->ivisc; */ ibound = param->ibound; 1326c4762a1bSJed Brown 1327c4762a1bSJed Brown for (j=js; j<je; j++) { 1328c4762a1bSJed Brown for (i=is; i<ie; i++) { 1329c4762a1bSJed Brown 1330c4762a1bSJed Brown /************* X-MOMENTUM/VELOCITY *************/ 1331c4762a1bSJed Brown if (i<j) f[j][i].u = x[j][i].u - SlabVel('U',i,j,user); 1332c4762a1bSJed Brown else if (j<=grid->jlid || (j<grid->corner+grid->inose && i<grid->corner+grid->inose)) { 1333c4762a1bSJed Brown /* in the lithospheric lid */ 1334c4762a1bSJed Brown f[j][i].u = x[j][i].u - 0.0; 1335c4762a1bSJed Brown } else if (i==ilim) { 1336c4762a1bSJed Brown /* on the right side boundary */ 1337c4762a1bSJed Brown if (ibound==BC_ANALYTIC) { 1338c4762a1bSJed Brown f[j][i].u = x[j][i].u - HorizVelocity(i,j,user); 1339c4762a1bSJed Brown } else { 1340c4762a1bSJed Brown f[j][i].u = XNormalStress(x,i,j,CELL_CENTER,user) - EPS_ZERO; 1341c4762a1bSJed Brown } 1342c4762a1bSJed Brown 1343c4762a1bSJed Brown } else if (j==jlim) { 1344c4762a1bSJed Brown /* on the bottom boundary */ 1345c4762a1bSJed Brown if (ibound==BC_ANALYTIC) { 1346c4762a1bSJed Brown f[j][i].u = x[j][i].u - HorizVelocity(i,j,user); 1347c4762a1bSJed Brown } else if (ibound==BC_NOSTRESS) { 1348c4762a1bSJed Brown f[j][i].u = XMomentumResidual(x,i,j,user); 1349c4762a1bSJed Brown } else { 1350c4762a1bSJed Brown /* experimental boundary condition */ 1351c4762a1bSJed Brown } 1352c4762a1bSJed Brown 1353c4762a1bSJed Brown } else { 1354c4762a1bSJed Brown /* in the mantle wedge */ 1355c4762a1bSJed Brown f[j][i].u = XMomentumResidual(x,i,j,user); 1356c4762a1bSJed Brown } 1357c4762a1bSJed Brown 1358c4762a1bSJed Brown /************* Z-MOMENTUM/VELOCITY *************/ 1359c4762a1bSJed Brown if (i<=j) { 1360c4762a1bSJed Brown f[j][i].w = x[j][i].w - SlabVel('W',i,j,user); 1361c4762a1bSJed Brown 1362c4762a1bSJed Brown } else if (j<=grid->jlid || (j<grid->corner+grid->inose && i<grid->corner+grid->inose)) { 1363c4762a1bSJed Brown /* in the lithospheric lid */ 1364c4762a1bSJed Brown f[j][i].w = x[j][i].w - 0.0; 1365c4762a1bSJed Brown 1366c4762a1bSJed Brown } else if (j==jlim) { 1367c4762a1bSJed Brown /* on the bottom boundary */ 1368c4762a1bSJed Brown if (ibound==BC_ANALYTIC) { 1369c4762a1bSJed Brown f[j][i].w = x[j][i].w - VertVelocity(i,j,user); 1370c4762a1bSJed Brown } else { 1371c4762a1bSJed Brown f[j][i].w = ZNormalStress(x,i,j,CELL_CENTER,user) - EPS_ZERO; 1372c4762a1bSJed Brown } 1373c4762a1bSJed Brown 1374c4762a1bSJed Brown } else if (i==ilim) { 1375c4762a1bSJed Brown /* on the right side boundary */ 1376c4762a1bSJed Brown if (ibound==BC_ANALYTIC) { 1377c4762a1bSJed Brown f[j][i].w = x[j][i].w - VertVelocity(i,j,user); 1378c4762a1bSJed Brown } else if (ibound==BC_NOSTRESS) { 1379c4762a1bSJed Brown f[j][i].w = ZMomentumResidual(x,i,j,user); 1380c4762a1bSJed Brown } else { 1381c4762a1bSJed Brown /* experimental boundary condition */ 1382c4762a1bSJed Brown } 1383c4762a1bSJed Brown 1384c4762a1bSJed Brown } else { 1385c4762a1bSJed Brown /* in the mantle wedge */ 1386c4762a1bSJed Brown f[j][i].w = ZMomentumResidual(x,i,j,user); 1387c4762a1bSJed Brown } 1388c4762a1bSJed Brown 1389c4762a1bSJed Brown /************* CONTINUITY/PRESSURE *************/ 1390c4762a1bSJed Brown if (i<j || j<=grid->jlid || (j<grid->corner+grid->inose && i<grid->corner+grid->inose)) { 1391c4762a1bSJed Brown /* in the lid or slab */ 1392c4762a1bSJed Brown f[j][i].p = x[j][i].p; 1393c4762a1bSJed Brown 1394c4762a1bSJed Brown } else if ((i==ilim || j==jlim) && ibound==BC_ANALYTIC) { 1395c4762a1bSJed Brown /* on an analytic boundary */ 1396c4762a1bSJed Brown f[j][i].p = x[j][i].p - Pressure(i,j,user); 1397c4762a1bSJed Brown 1398c4762a1bSJed Brown } else { 1399c4762a1bSJed Brown /* in the mantle wedge */ 1400c4762a1bSJed Brown f[j][i].p = ContinuityResidual(x,i,j,user); 1401c4762a1bSJed Brown } 1402c4762a1bSJed Brown 1403c4762a1bSJed Brown /************* TEMPERATURE *************/ 1404c4762a1bSJed Brown if (j==0) { 1405c4762a1bSJed Brown /* on the surface */ 1406c4762a1bSJed Brown f[j][i].T = x[j][i].T + x[j+1][i].T + PetscMax(PetscRealPart(x[j][i].T),0.0); 1407c4762a1bSJed Brown 1408c4762a1bSJed Brown } else if (i==0) { 1409c4762a1bSJed Brown /* slab inflow boundary */ 1410c4762a1bSJed Brown f[j][i].T = x[j][i].T - PlateModel(j,PLATE_SLAB,user); 1411c4762a1bSJed Brown 1412c4762a1bSJed Brown } else if (i==ilim) { 1413c4762a1bSJed Brown /* right side boundary */ 1414c4762a1bSJed Brown mag_u = 1.0 - PetscPowRealInt((1.0-PetscMax(PetscMin(PetscRealPart(x[j][i-1].u)/param->cb,1.0),0.0)), 5); 1415c4762a1bSJed Brown f[j][i].T = x[j][i].T - mag_u*x[j-1][i-1].T - (1.0-mag_u)*PlateModel(j,PLATE_LID,user); 1416c4762a1bSJed Brown 1417c4762a1bSJed Brown } else if (j==jlim) { 1418c4762a1bSJed Brown /* bottom boundary */ 1419c4762a1bSJed Brown mag_w = 1.0 - PetscPowRealInt((1.0-PetscMax(PetscMin(PetscRealPart(x[j-1][i].w)/param->sb,1.0),0.0)), 5); 1420c4762a1bSJed Brown f[j][i].T = x[j][i].T - mag_w*x[j-1][i-1].T - (1.0-mag_w); 1421c4762a1bSJed Brown 1422c4762a1bSJed Brown } else { 1423c4762a1bSJed Brown /* in the mantle wedge */ 1424c4762a1bSJed Brown f[j][i].T = EnergyResidual(x,i,j,user); 1425c4762a1bSJed Brown } 1426c4762a1bSJed Brown } 1427c4762a1bSJed Brown } 1428c4762a1bSJed Brown PetscFunctionReturn(0); 1429c4762a1bSJed Brown } 1430c4762a1bSJed Brown 1431c4762a1bSJed Brown /*TEST 1432c4762a1bSJed Brown 1433c4762a1bSJed Brown build: 1434c4762a1bSJed Brown requires: !complex erf 1435c4762a1bSJed Brown 1436c4762a1bSJed Brown test: 1437c4762a1bSJed Brown args: -ni 18 1438c4762a1bSJed Brown filter: grep -v Destination 1439c4762a1bSJed Brown requires: !single 1440c4762a1bSJed Brown 1441c4762a1bSJed Brown TEST*/ 1442