1c4762a1bSJed Brown 2c4762a1bSJed Brown static char help[] = "Solves biharmonic equation in 1d.\n"; 3c4762a1bSJed Brown 4c4762a1bSJed Brown /* 5c4762a1bSJed Brown Solves the equation 6c4762a1bSJed Brown 7c4762a1bSJed Brown u_t = - kappa \Delta \Delta u 8c4762a1bSJed Brown Periodic boundary conditions 9c4762a1bSJed Brown 10c4762a1bSJed Brown Evolve the biharmonic heat equation: 11c4762a1bSJed Brown --------------- 12c4762a1bSJed Brown ./biharmonic -ts_monitor -snes_monitor -pc_type lu -draw_pause .1 -snes_converged_reason -draw_pause -2 -ts_type cn -da_refine 5 -mymonitor 13c4762a1bSJed Brown 14c4762a1bSJed Brown Evolve with the restriction that -1 <= u <= 1; i.e. as a variational inequality 15c4762a1bSJed Brown --------------- 16c4762a1bSJed Brown ./biharmonic -ts_monitor -snes_monitor -pc_type lu -draw_pause .1 -snes_converged_reason -draw_pause -2 -ts_type cn -da_refine 5 -mymonitor 17c4762a1bSJed Brown 18c4762a1bSJed Brown u_t = kappa \Delta \Delta u + 6.*u*(u_x)^2 + (3*u^2 - 12) \Delta u 19c4762a1bSJed Brown -1 <= u <= 1 20c4762a1bSJed Brown Periodic boundary conditions 21c4762a1bSJed Brown 22c4762a1bSJed Brown Evolve the Cahn-Hillard equations: double well Initial hump shrinks then grows 23c4762a1bSJed Brown --------------- 24c4762a1bSJed Brown ./biharmonic -ts_monitor -snes_monitor -pc_type lu -draw_pause .1 -snes_converged_reason -draw_pause -2 -ts_type cn -da_refine 6 -kappa .00001 -ts_dt 5.96046e-06 -cahn-hillard -ts_monitor_draw_solution --mymonitor 25c4762a1bSJed Brown 26c4762a1bSJed Brown Initial hump neither shrinks nor grows when degenerate (otherwise similar solution) 27c4762a1bSJed Brown 28c4762a1bSJed Brown ./biharmonic -ts_monitor -snes_monitor -pc_type lu -draw_pause .1 -snes_converged_reason -draw_pause -2 -ts_type cn -da_refine 6 -kappa .00001 -ts_dt 5.96046e-06 -cahn-hillard -degenerate -ts_monitor_draw_solution --mymonitor 29c4762a1bSJed Brown 30c4762a1bSJed Brown ./biharmonic -ts_monitor -snes_monitor -pc_type lu -draw_pause .1 -snes_converged_reason -draw_pause -2 -ts_type cn -da_refine 6 -kappa .00001 -ts_dt 5.96046e-06 -cahn-hillard -snes_vi_ignore_function_sign -ts_monitor_draw_solution --mymonitor 31c4762a1bSJed Brown 32c4762a1bSJed Brown Evolve the Cahn-Hillard equations: double obstacle 33c4762a1bSJed Brown --------------- 34c4762a1bSJed Brown ./biharmonic -ts_monitor -snes_monitor -pc_type lu -draw_pause .1 -snes_converged_reason -draw_pause -2 -ts_type cn -da_refine 5 -kappa .00001 -ts_dt 5.96046e-06 -cahn-hillard -energy 2 -snes_linesearch_monitor -ts_monitor_draw_solution --mymonitor 35c4762a1bSJed Brown 36c4762a1bSJed Brown Evolve the Cahn-Hillard equations: logarithmic + double well (never shrinks and then grows) 37c4762a1bSJed Brown --------------- 38c4762a1bSJed Brown ./biharmonic -ts_monitor -snes_monitor -pc_type lu --snes_converged_reason -draw_pause -2 -ts_type cn -da_refine 5 -kappa .0001 -ts_dt 5.96046e-06 -cahn-hillard -energy 3 -snes_linesearch_monitor -theta .00000001 -ts_monitor_draw_solution --ts_max_time 1. -mymonitor 39c4762a1bSJed Brown 40c4762a1bSJed Brown ./biharmonic -ts_monitor -snes_monitor -pc_type lu --snes_converged_reason -draw_pause -2 -ts_type cn -da_refine 5 -kappa .0001 -ts_dt 5.96046e-06 -cahn-hillard -energy 3 -snes_linesearch_monitor -theta .00000001 -ts_monitor_draw_solution --ts_max_time 1. -degenerate -mymonitor 41c4762a1bSJed Brown 42c4762a1bSJed Brown Evolve the Cahn-Hillard equations: logarithmic + double obstacle (never shrinks, never grows) 43c4762a1bSJed Brown --------------- 44c4762a1bSJed Brown ./biharmonic -ts_monitor -snes_monitor -pc_type lu --snes_converged_reason -draw_pause -2 -ts_type cn -da_refine 5 -kappa .00001 -ts_dt 5.96046e-06 -cahn-hillard -energy 4 -snes_linesearch_monitor -theta .00000001 -ts_monitor_draw_solution --mymonitor 45c4762a1bSJed Brown 46c4762a1bSJed Brown */ 47c4762a1bSJed Brown #include <petscdm.h> 48c4762a1bSJed Brown #include <petscdmda.h> 49c4762a1bSJed Brown #include <petscts.h> 50c4762a1bSJed Brown #include <petscdraw.h> 51c4762a1bSJed Brown 52c4762a1bSJed Brown extern PetscErrorCode FormFunction(TS,PetscReal,Vec,Vec,void*),FormInitialSolution(DM,Vec),MyMonitor(TS,PetscInt,PetscReal,Vec,void*),MyDestroy(void**),FormJacobian(TS,PetscReal,Vec,Mat,Mat,void*); 53c4762a1bSJed Brown typedef struct {PetscBool cahnhillard;PetscBool degenerate;PetscReal kappa;PetscInt energy;PetscReal tol;PetscReal theta,theta_c;PetscInt truncation;PetscBool netforce; PetscDrawViewPorts *ports;} UserCtx; 54c4762a1bSJed Brown 55c4762a1bSJed Brown int main(int argc,char **argv) 56c4762a1bSJed Brown { 57c4762a1bSJed Brown TS ts; /* nonlinear solver */ 58c4762a1bSJed Brown Vec x,r; /* solution, residual vectors */ 59c4762a1bSJed Brown Mat J; /* Jacobian matrix */ 60c4762a1bSJed Brown PetscInt steps,Mx; 61c4762a1bSJed Brown DM da; 62c4762a1bSJed Brown PetscReal dt; 63c4762a1bSJed Brown PetscBool mymonitor; 64c4762a1bSJed Brown UserCtx ctx; 65c4762a1bSJed Brown 66c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 67c4762a1bSJed Brown Initialize program 68c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 69*327415f7SBarry Smith PetscFunctionBeginUser; 709566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc,&argv,(char*)0,help)); 71c4762a1bSJed Brown ctx.kappa = 1.0; 729566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(NULL,NULL,"-kappa",&ctx.kappa,NULL)); 73c4762a1bSJed Brown ctx.degenerate = PETSC_FALSE; 749566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,NULL,"-degenerate",&ctx.degenerate,NULL)); 75c4762a1bSJed Brown ctx.cahnhillard = PETSC_FALSE; 769566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,NULL,"-cahn-hillard",&ctx.cahnhillard,NULL)); 77c4762a1bSJed Brown ctx.netforce = PETSC_FALSE; 789566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,NULL,"-netforce",&ctx.netforce,NULL)); 79c4762a1bSJed Brown ctx.energy = 1; 809566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL,NULL,"-energy",&ctx.energy,NULL)); 81c4762a1bSJed Brown ctx.tol = 1.0e-8; 829566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(NULL,NULL,"-tol",&ctx.tol,NULL)); 83c4762a1bSJed Brown ctx.theta = .001; 84c4762a1bSJed Brown ctx.theta_c = 1.0; 859566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(NULL,NULL,"-theta",&ctx.theta,NULL)); 869566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(NULL,NULL,"-theta_c",&ctx.theta_c,NULL)); 87c4762a1bSJed Brown ctx.truncation = 1; 889566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL,NULL,"-truncation",&ctx.truncation,NULL)); 899566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL,NULL,"-mymonitor",&mymonitor)); 90c4762a1bSJed Brown 91c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 92c4762a1bSJed Brown Create distributed array (DMDA) to manage parallel grid and vectors 93c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 949566063dSJacob Faibussowitsch PetscCall(DMDACreate1d(PETSC_COMM_WORLD, DM_BOUNDARY_PERIODIC, 10,1,2,NULL,&da)); 959566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(da)); 969566063dSJacob Faibussowitsch PetscCall(DMSetUp(da)); 979566063dSJacob Faibussowitsch PetscCall(DMDASetFieldName(da,0,"Biharmonic heat equation: u")); 989566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da,0,&Mx,0,0,0,0,0,0,0,0,0,0,0)); 99c4762a1bSJed Brown dt = 1.0/(10.*ctx.kappa*Mx*Mx*Mx*Mx); 100c4762a1bSJed Brown 101c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 102c4762a1bSJed Brown Extract global vectors from DMDA; then duplicate for remaining 103c4762a1bSJed Brown vectors that are the same types 104c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1059566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(da,&x)); 1069566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x,&r)); 107c4762a1bSJed Brown 108c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 109c4762a1bSJed Brown Create timestepping solver context 110c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1119566063dSJacob Faibussowitsch PetscCall(TSCreate(PETSC_COMM_WORLD,&ts)); 1129566063dSJacob Faibussowitsch PetscCall(TSSetDM(ts,da)); 1139566063dSJacob Faibussowitsch PetscCall(TSSetProblemType(ts,TS_NONLINEAR)); 1149566063dSJacob Faibussowitsch PetscCall(TSSetRHSFunction(ts,NULL,FormFunction,&ctx)); 1159566063dSJacob Faibussowitsch PetscCall(DMSetMatType(da,MATAIJ)); 1169566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(da,&J)); 1179566063dSJacob Faibussowitsch PetscCall(TSSetRHSJacobian(ts,J,J,FormJacobian,&ctx)); 1189566063dSJacob Faibussowitsch PetscCall(TSSetMaxTime(ts,.02)); 1199566063dSJacob Faibussowitsch PetscCall(TSSetExactFinalTime(ts,TS_EXACTFINALTIME_INTERPOLATE)); 120c4762a1bSJed Brown 121c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 122c4762a1bSJed Brown Create matrix data structure; set Jacobian evaluation routine 123c4762a1bSJed Brown 124c4762a1bSJed Brown Set Jacobian matrix data structure and default Jacobian evaluation 125c4762a1bSJed Brown routine. User can override with: 126c4762a1bSJed Brown -snes_mf : matrix-free Newton-Krylov method with no preconditioning 127c4762a1bSJed Brown (unless user explicitly sets preconditioner) 128c4762a1bSJed Brown -snes_mf_operator : form preconditioning matrix as set by the user, 129c4762a1bSJed Brown but use matrix-free approx for Jacobian-vector 130c4762a1bSJed Brown products within Newton-Krylov method 131c4762a1bSJed Brown 132c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 133c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 134c4762a1bSJed Brown Customize nonlinear solver 135c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1369566063dSJacob Faibussowitsch PetscCall(TSSetType(ts,TSCN)); 137c4762a1bSJed Brown 138c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 139c4762a1bSJed Brown Set initial conditions 140c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1419566063dSJacob Faibussowitsch PetscCall(FormInitialSolution(da,x)); 1429566063dSJacob Faibussowitsch PetscCall(TSSetTimeStep(ts,dt)); 1439566063dSJacob Faibussowitsch PetscCall(TSSetSolution(ts,x)); 144c4762a1bSJed Brown 145c4762a1bSJed Brown if (mymonitor) { 146c4762a1bSJed Brown ctx.ports = NULL; 1479566063dSJacob Faibussowitsch PetscCall(TSMonitorSet(ts,MyMonitor,&ctx,MyDestroy)); 148c4762a1bSJed Brown } 149c4762a1bSJed Brown 150c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 151c4762a1bSJed Brown Set runtime options 152c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1539566063dSJacob Faibussowitsch PetscCall(TSSetFromOptions(ts)); 154c4762a1bSJed Brown 155c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 156c4762a1bSJed Brown Solve nonlinear system 157c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1589566063dSJacob Faibussowitsch PetscCall(TSSolve(ts,x)); 1599566063dSJacob Faibussowitsch PetscCall(TSGetStepNumber(ts,&steps)); 1609566063dSJacob Faibussowitsch PetscCall(VecView(x,PETSC_VIEWER_BINARY_WORLD)); 161c4762a1bSJed Brown 162c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 163c4762a1bSJed Brown Free work space. All PETSc objects should be destroyed when they 164c4762a1bSJed Brown are no longer needed. 165c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1669566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 1679566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 1689566063dSJacob Faibussowitsch PetscCall(VecDestroy(&r)); 1699566063dSJacob Faibussowitsch PetscCall(TSDestroy(&ts)); 1709566063dSJacob Faibussowitsch PetscCall(DMDestroy(&da)); 171c4762a1bSJed Brown 1729566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 173b122ec5aSJacob Faibussowitsch return 0; 174c4762a1bSJed Brown } 175c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 176c4762a1bSJed Brown /* 177c4762a1bSJed Brown FormFunction - Evaluates nonlinear function, F(x). 178c4762a1bSJed Brown 179c4762a1bSJed Brown Input Parameters: 180c4762a1bSJed Brown . ts - the TS context 181c4762a1bSJed Brown . X - input vector 182c4762a1bSJed Brown . ptr - optional user-defined context, as set by SNESSetFunction() 183c4762a1bSJed Brown 184c4762a1bSJed Brown Output Parameter: 185c4762a1bSJed Brown . F - function vector 186c4762a1bSJed Brown */ 187c4762a1bSJed Brown PetscErrorCode FormFunction(TS ts,PetscReal ftime,Vec X,Vec F,void *ptr) 188c4762a1bSJed Brown { 189c4762a1bSJed Brown DM da; 190c4762a1bSJed Brown PetscInt i,Mx,xs,xm; 191c4762a1bSJed Brown PetscReal hx,sx; 192c4762a1bSJed Brown PetscScalar *x,*f,c,r,l; 193c4762a1bSJed Brown Vec localX; 194c4762a1bSJed Brown UserCtx *ctx = (UserCtx*)ptr; 195c4762a1bSJed Brown PetscReal tol = ctx->tol, theta=ctx->theta,theta_c=ctx->theta_c,a,b; /* a and b are used in the cubic truncation of the log function */ 196c4762a1bSJed Brown 197c4762a1bSJed Brown PetscFunctionBegin; 1989566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts,&da)); 1999566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(da,&localX)); 2009566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE)); 201c4762a1bSJed Brown 202c4762a1bSJed Brown hx = 1.0/(PetscReal)Mx; sx = 1.0/(hx*hx); 203c4762a1bSJed Brown 204c4762a1bSJed Brown /* 205c4762a1bSJed Brown Scatter ghost points to local vector,using the 2-step process 206c4762a1bSJed Brown DMGlobalToLocalBegin(),DMGlobalToLocalEnd(). 207c4762a1bSJed Brown By placing code between these two statements, computations can be 208c4762a1bSJed Brown done while messages are in transition. 209c4762a1bSJed Brown */ 2109566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX)); 2119566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX)); 212c4762a1bSJed Brown 213c4762a1bSJed Brown /* 214c4762a1bSJed Brown Get pointers to vector data 215c4762a1bSJed Brown */ 2169566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArrayRead(da,localX,&x)); 2179566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(da,F,&f)); 218c4762a1bSJed Brown 219c4762a1bSJed Brown /* 220c4762a1bSJed Brown Get local grid boundaries 221c4762a1bSJed Brown */ 2229566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL)); 223c4762a1bSJed Brown 224c4762a1bSJed Brown /* 225c4762a1bSJed Brown Compute function over the locally owned part of the grid 226c4762a1bSJed Brown */ 227c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 228c4762a1bSJed Brown if (ctx->degenerate) { 229c4762a1bSJed Brown c = (1. - x[i]*x[i])*(x[i-1] + x[i+1] - 2.0*x[i])*sx; 230c4762a1bSJed Brown r = (1. - x[i+1]*x[i+1])*(x[i] + x[i+2] - 2.0*x[i+1])*sx; 231c4762a1bSJed Brown l = (1. - x[i-1]*x[i-1])*(x[i-2] + x[i] - 2.0*x[i-1])*sx; 232c4762a1bSJed Brown } else { 233c4762a1bSJed Brown c = (x[i-1] + x[i+1] - 2.0*x[i])*sx; 234c4762a1bSJed Brown r = (x[i] + x[i+2] - 2.0*x[i+1])*sx; 235c4762a1bSJed Brown l = (x[i-2] + x[i] - 2.0*x[i-1])*sx; 236c4762a1bSJed Brown } 237c4762a1bSJed Brown f[i] = -ctx->kappa*(l + r - 2.0*c)*sx; 238c4762a1bSJed Brown if (ctx->cahnhillard) { 239c4762a1bSJed Brown switch (ctx->energy) { 240c4762a1bSJed Brown case 1: /* double well */ 241c4762a1bSJed Brown f[i] += 6.*.25*x[i]*(x[i+1] - x[i-1])*(x[i+1] - x[i-1])*sx + (3.*x[i]*x[i] - 1.)*(x[i-1] + x[i+1] - 2.0*x[i])*sx; 242c4762a1bSJed Brown break; 243c4762a1bSJed Brown case 2: /* double obstacle */ 244c4762a1bSJed Brown f[i] += -(x[i-1] + x[i+1] - 2.0*x[i])*sx; 245c4762a1bSJed Brown break; 246c4762a1bSJed Brown case 3: /* logarithmic + double well */ 247c4762a1bSJed Brown f[i] += 6.*.25*x[i]*(x[i+1] - x[i-1])*(x[i+1] - x[i-1])*sx + (3.*x[i]*x[i] - 1.)*(x[i-1] + x[i+1] - 2.0*x[i])*sx; 248c4762a1bSJed Brown if (ctx->truncation==2) { /* log function with approximated with a quadratic polynomial outside -1.0+2*tol, 1.0-2*tol */ 249c4762a1bSJed Brown if (PetscRealPart(x[i]) < -1.0 + 2.0*tol) f[i] += (.25*theta/(tol-tol*tol))*(x[i-1] + x[i+1] - 2.0*x[i])*sx; 250c4762a1bSJed Brown else if (PetscRealPart(x[i]) > 1.0 - 2.0*tol) f[i] += (.25*theta/(tol-tol*tol))*(x[i-1] + x[i+1] - 2.0*x[i])*sx; 251c4762a1bSJed Brown else f[i] += 2.0*theta*x[i]/((1.0-x[i]*x[i])*(1.0-x[i]*x[i]))*.25*(x[i+1] - x[i-1])*(x[i+1] - x[i-1])*sx + (theta/(1.0-x[i]*x[i]))*(x[i-1] + x[i+1] - 2.0*x[i])*sx; 252c4762a1bSJed Brown } else { /* log function is approximated with a cubic polynomial outside -1.0+2*tol, 1.0-2*tol */ 253c4762a1bSJed Brown a = 2.0*theta*(1.0-2.0*tol)/(16.0*tol*tol*(1.0-tol)*(1.0-tol)); 254c4762a1bSJed Brown b = theta/(4.0*tol*(1.0-tol)) - a*(1.0-2.0*tol); 255c4762a1bSJed Brown if (PetscRealPart(x[i]) < -1.0 + 2.0*tol) f[i] += -1.0*a*.25*(x[i+1] - x[i-1])*(x[i+1] - x[i-1])*sx + (-1.0*a*x[i] + b)*(x[i-1] + x[i+1] - 2.0*x[i])*sx; 256c4762a1bSJed Brown else if (PetscRealPart(x[i]) > 1.0 - 2.0*tol) f[i] += 1.0*a*.25*(x[i+1] - x[i-1])*(x[i+1] - x[i-1])*sx + ( a*x[i] + b)*(x[i-1] + x[i+1] - 2.0*x[i])*sx; 257c4762a1bSJed Brown else f[i] += 2.0*theta*x[i]/((1.0-x[i]*x[i])*(1.0-x[i]*x[i]))*.25*(x[i+1] - x[i-1])*(x[i+1] - x[i-1])*sx + (theta/(1.0-x[i]*x[i]))*(x[i-1] + x[i+1] - 2.0*x[i])*sx; 258c4762a1bSJed Brown } 259c4762a1bSJed Brown break; 260c4762a1bSJed Brown case 4: /* logarithmic + double obstacle */ 261c4762a1bSJed Brown f[i] += -theta_c*(x[i-1] + x[i+1] - 2.0*x[i])*sx; 262c4762a1bSJed Brown if (ctx->truncation==2) { /* quadratic */ 263c4762a1bSJed Brown if (PetscRealPart(x[i]) < -1.0 + 2.0*tol) f[i] += (.25*theta/(tol-tol*tol))*(x[i-1] + x[i+1] - 2.0*x[i])*sx; 264c4762a1bSJed Brown else if (PetscRealPart(x[i]) > 1.0 - 2.0*tol) f[i] += (.25*theta/(tol-tol*tol))*(x[i-1] + x[i+1] - 2.0*x[i])*sx; 265c4762a1bSJed Brown else f[i] += 2.0*theta*x[i]/((1.0-x[i]*x[i])*(1.0-x[i]*x[i]))*.25*(x[i+1] - x[i-1])*(x[i+1] - x[i-1])*sx + (theta/(1.0-x[i]*x[i]))*(x[i-1] + x[i+1] - 2.0*x[i])*sx; 266c4762a1bSJed Brown } else { /* cubic */ 267c4762a1bSJed Brown a = 2.0*theta*(1.0-2.0*tol)/(16.0*tol*tol*(1.0-tol)*(1.0-tol)); 268c4762a1bSJed Brown b = theta/(4.0*tol*(1.0-tol)) - a*(1.0-2.0*tol); 269c4762a1bSJed Brown if (PetscRealPart(x[i]) < -1.0 + 2.0*tol) f[i] += -1.0*a*.25*(x[i+1] - x[i-1])*(x[i+1] - x[i-1])*sx + (-1.0*a*x[i] + b)*(x[i-1] + x[i+1] - 2.0*x[i])*sx; 270c4762a1bSJed Brown else if (PetscRealPart(x[i]) > 1.0 - 2.0*tol) f[i] += 1.0*a*.25*(x[i+1] - x[i-1])*(x[i+1] - x[i-1])*sx + ( a*x[i] + b)*(x[i-1] + x[i+1] - 2.0*x[i])*sx; 271c4762a1bSJed Brown else f[i] += 2.0*theta*x[i]/((1.0-x[i]*x[i])*(1.0-x[i]*x[i]))*.25*(x[i+1] - x[i-1])*(x[i+1] - x[i-1])*sx + (theta/(1.0-x[i]*x[i]))*(x[i-1] + x[i+1] - 2.0*x[i])*sx; 272c4762a1bSJed Brown } 273c4762a1bSJed Brown break; 274c4762a1bSJed Brown } 275c4762a1bSJed Brown } 276c4762a1bSJed Brown 277c4762a1bSJed Brown } 278c4762a1bSJed Brown 279c4762a1bSJed Brown /* 280c4762a1bSJed Brown Restore vectors 281c4762a1bSJed Brown */ 2829566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArrayRead(da,localX,&x)); 2839566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(da,F,&f)); 2849566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(da,&localX)); 285c4762a1bSJed Brown PetscFunctionReturn(0); 286c4762a1bSJed Brown } 287c4762a1bSJed Brown 288c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 289c4762a1bSJed Brown /* 290c4762a1bSJed Brown FormJacobian - Evaluates nonlinear function's Jacobian 291c4762a1bSJed Brown 292c4762a1bSJed Brown */ 293c4762a1bSJed Brown PetscErrorCode FormJacobian(TS ts,PetscReal ftime,Vec X,Mat A,Mat B,void *ptr) 294c4762a1bSJed Brown { 295c4762a1bSJed Brown DM da; 296c4762a1bSJed Brown PetscInt i,Mx,xs,xm; 297c4762a1bSJed Brown MatStencil row,cols[5]; 298c4762a1bSJed Brown PetscReal hx,sx; 299c4762a1bSJed Brown PetscScalar *x,vals[5]; 300c4762a1bSJed Brown Vec localX; 301c4762a1bSJed Brown UserCtx *ctx = (UserCtx*)ptr; 302c4762a1bSJed Brown 303c4762a1bSJed Brown PetscFunctionBegin; 3049566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts,&da)); 3059566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(da,&localX)); 3069566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE)); 307c4762a1bSJed Brown 308c4762a1bSJed Brown hx = 1.0/(PetscReal)Mx; sx = 1.0/(hx*hx); 309c4762a1bSJed Brown 310c4762a1bSJed Brown /* 311c4762a1bSJed Brown Scatter ghost points to local vector,using the 2-step process 312c4762a1bSJed Brown DMGlobalToLocalBegin(),DMGlobalToLocalEnd(). 313c4762a1bSJed Brown By placing code between these two statements, computations can be 314c4762a1bSJed Brown done while messages are in transition. 315c4762a1bSJed Brown */ 3169566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX)); 3179566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX)); 318c4762a1bSJed Brown 319c4762a1bSJed Brown /* 320c4762a1bSJed Brown Get pointers to vector data 321c4762a1bSJed Brown */ 3229566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArrayRead(da,localX,&x)); 323c4762a1bSJed Brown 324c4762a1bSJed Brown /* 325c4762a1bSJed Brown Get local grid boundaries 326c4762a1bSJed Brown */ 3279566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL)); 328c4762a1bSJed Brown 329c4762a1bSJed Brown /* 330c4762a1bSJed Brown Compute function over the locally owned part of the grid 331c4762a1bSJed Brown */ 332c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 333c4762a1bSJed Brown row.i = i; 334c4762a1bSJed Brown if (ctx->degenerate) { 335c4762a1bSJed Brown /*PetscScalar c,r,l; 336c4762a1bSJed Brown c = (1. - x[i]*x[i])*(x[i-1] + x[i+1] - 2.0*x[i])*sx; 337c4762a1bSJed Brown r = (1. - x[i+1]*x[i+1])*(x[i] + x[i+2] - 2.0*x[i+1])*sx; 338c4762a1bSJed Brown l = (1. - x[i-1]*x[i-1])*(x[i-2] + x[i] - 2.0*x[i-1])*sx; */ 339c4762a1bSJed Brown } else { 340c4762a1bSJed Brown cols[0].i = i - 2; vals[0] = -ctx->kappa*sx*sx; 341c4762a1bSJed Brown cols[1].i = i - 1; vals[1] = 4.0*ctx->kappa*sx*sx; 342c4762a1bSJed Brown cols[2].i = i ; vals[2] = -6.0*ctx->kappa*sx*sx; 343c4762a1bSJed Brown cols[3].i = i + 1; vals[3] = 4.0*ctx->kappa*sx*sx; 344c4762a1bSJed Brown cols[4].i = i + 2; vals[4] = -ctx->kappa*sx*sx; 345c4762a1bSJed Brown } 3469566063dSJacob Faibussowitsch PetscCall(MatSetValuesStencil(B,1,&row,5,cols,vals,INSERT_VALUES)); 347c4762a1bSJed Brown 348c4762a1bSJed Brown if (ctx->cahnhillard) { 349c4762a1bSJed Brown switch (ctx->energy) { 350c4762a1bSJed Brown case 1: /* double well */ 351c4762a1bSJed Brown /* f[i] += 6.*.25*x[i]*(x[i+1] - x[i-1])*(x[i+1] - x[i-1])*sx + (3.*x[i]*x[i] - 1.)*(x[i-1] + x[i+1] - 2.0*x[i])*sx; */ 352c4762a1bSJed Brown break; 353c4762a1bSJed Brown case 2: /* double obstacle */ 354c4762a1bSJed Brown /* f[i] += -(x[i-1] + x[i+1] - 2.0*x[i])*sx; */ 355c4762a1bSJed Brown break; 356c4762a1bSJed Brown case 3: /* logarithmic + double well */ 357c4762a1bSJed Brown break; 358c4762a1bSJed Brown case 4: /* logarithmic + double obstacle */ 359c4762a1bSJed Brown break; 360c4762a1bSJed Brown } 361c4762a1bSJed Brown } 362c4762a1bSJed Brown 363c4762a1bSJed Brown } 364c4762a1bSJed Brown 365c4762a1bSJed Brown /* 366c4762a1bSJed Brown Restore vectors 367c4762a1bSJed Brown */ 3689566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArrayRead(da,localX,&x)); 3699566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(da,&localX)); 3709566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY)); 3719566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY)); 372c4762a1bSJed Brown if (A != B) { 3739566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY)); 3749566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY)); 375c4762a1bSJed Brown } 376c4762a1bSJed Brown PetscFunctionReturn(0); 377c4762a1bSJed Brown } 378c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 379c4762a1bSJed Brown PetscErrorCode FormInitialSolution(DM da,Vec U) 380c4762a1bSJed Brown { 381c4762a1bSJed Brown PetscInt i,xs,xm,Mx,N,scale; 382c4762a1bSJed Brown PetscScalar *u; 383c4762a1bSJed Brown PetscReal r,hx,x; 384c4762a1bSJed Brown const PetscScalar *f; 385c4762a1bSJed Brown Vec finesolution; 386c4762a1bSJed Brown PetscViewer viewer; 387c4762a1bSJed Brown 388c4762a1bSJed Brown PetscFunctionBegin; 3899566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE)); 390c4762a1bSJed Brown 391c4762a1bSJed Brown hx = 1.0/(PetscReal)Mx; 392c4762a1bSJed Brown 393c4762a1bSJed Brown /* 394c4762a1bSJed Brown Get pointers to vector data 395c4762a1bSJed Brown */ 3969566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(da,U,&u)); 397c4762a1bSJed Brown 398c4762a1bSJed Brown /* 399c4762a1bSJed Brown Get local grid boundaries 400c4762a1bSJed Brown */ 4019566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL)); 402c4762a1bSJed Brown 403c4762a1bSJed Brown /* 404c4762a1bSJed Brown Seee heat.c for how to generate InitialSolution.heat 405c4762a1bSJed Brown */ 4069566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD,"InitialSolution.heat",FILE_MODE_READ,&viewer)); 4079566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD,&finesolution)); 4089566063dSJacob Faibussowitsch PetscCall(VecLoad(finesolution,viewer)); 4099566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 4109566063dSJacob Faibussowitsch PetscCall(VecGetSize(finesolution,&N)); 411c4762a1bSJed Brown scale = N/Mx; 4129566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(finesolution,&f)); 413c4762a1bSJed Brown 414c4762a1bSJed Brown /* 415c4762a1bSJed Brown Compute function over the locally owned part of the grid 416c4762a1bSJed Brown */ 417c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 418c4762a1bSJed Brown x = i*hx; 419c4762a1bSJed Brown r = PetscSqrtReal((x-.5)*(x-.5)); 420c4762a1bSJed Brown if (r < .125) u[i] = 1.0; 421c4762a1bSJed Brown else u[i] = -.5; 422c4762a1bSJed Brown 423c4762a1bSJed Brown /* With the initial condition above the method is first order in space */ 424c4762a1bSJed Brown /* this is a smooth initial condition so the method becomes second order in space */ 425c4762a1bSJed Brown /*u[i] = PetscSinScalar(2*PETSC_PI*x); */ 426c4762a1bSJed Brown u[i] = f[scale*i]; 427c4762a1bSJed Brown } 4289566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(finesolution,&f)); 4299566063dSJacob Faibussowitsch PetscCall(VecDestroy(&finesolution)); 430c4762a1bSJed Brown 431c4762a1bSJed Brown /* 432c4762a1bSJed Brown Restore vectors 433c4762a1bSJed Brown */ 4349566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(da,U,&u)); 435c4762a1bSJed Brown PetscFunctionReturn(0); 436c4762a1bSJed Brown } 437c4762a1bSJed Brown 438c4762a1bSJed Brown /* 439c4762a1bSJed Brown This routine is not parallel 440c4762a1bSJed Brown */ 441c4762a1bSJed Brown PetscErrorCode MyMonitor(TS ts,PetscInt step,PetscReal time,Vec U,void *ptr) 442c4762a1bSJed Brown { 443c4762a1bSJed Brown UserCtx *ctx = (UserCtx*)ptr; 444c4762a1bSJed Brown PetscDrawLG lg; 445c4762a1bSJed Brown PetscScalar *u,l,r,c; 446c4762a1bSJed Brown PetscInt Mx,i,xs,xm,cnt; 447c4762a1bSJed Brown PetscReal x,y,hx,pause,sx,len,max,xx[4],yy[4],xx_netforce,yy_netforce,yup,ydown,y2,len2; 448c4762a1bSJed Brown PetscDraw draw; 449c4762a1bSJed Brown Vec localU; 450c4762a1bSJed Brown DM da; 451c4762a1bSJed Brown int colors[] = {PETSC_DRAW_YELLOW,PETSC_DRAW_RED,PETSC_DRAW_BLUE,PETSC_DRAW_PLUM,PETSC_DRAW_BLACK}; 452c4762a1bSJed Brown /* 453c4762a1bSJed Brown const char *const legend[3][3] = {{"-kappa (\\grad u,\\grad u)","(1 - u^2)^2"},{"-kappa (\\grad u,\\grad u)","(1 - u^2)"},{"-kappa (\\grad u,\\grad u)","logarithmic"}}; 454c4762a1bSJed Brown */ 455c4762a1bSJed Brown PetscDrawAxis axis; 456c4762a1bSJed Brown PetscDrawViewPorts *ports; 457c4762a1bSJed Brown PetscReal tol = ctx->tol, theta=ctx->theta,theta_c=ctx->theta_c,a,b; /* a and b are used in the cubic truncation of the log function */ 458c4762a1bSJed Brown PetscReal vbounds[] = {-1.1,1.1}; 459c4762a1bSJed Brown 460c4762a1bSJed Brown PetscFunctionBegin; 4619566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawSetBounds(PETSC_VIEWER_DRAW_(PETSC_COMM_WORLD),1,vbounds)); 4629566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawResize(PETSC_VIEWER_DRAW_(PETSC_COMM_WORLD),800,600)); 4639566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts,&da)); 4649566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(da,&localU)); 4659566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE, 466b122ec5aSJacob Faibussowitsch PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE)); 4679566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL)); 468c4762a1bSJed Brown hx = 1.0/(PetscReal)Mx; sx = 1.0/(hx*hx); 4699566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(da,U,INSERT_VALUES,localU)); 4709566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(da,U,INSERT_VALUES,localU)); 4719566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArrayRead(da,localU,&u)); 472c4762a1bSJed Brown 4739566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(PETSC_VIEWER_DRAW_(PETSC_COMM_WORLD),1,&lg)); 4749566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg,&draw)); 4759566063dSJacob Faibussowitsch PetscCall(PetscDrawCheckResizedWindow(draw)); 476c4762a1bSJed Brown if (!ctx->ports) { 4779566063dSJacob Faibussowitsch PetscCall(PetscDrawViewPortsCreateRect(draw,1,3,&ctx->ports)); 478c4762a1bSJed Brown } 479c4762a1bSJed Brown ports = ctx->ports; 4809566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetAxis(lg,&axis)); 4819566063dSJacob Faibussowitsch PetscCall(PetscDrawLGReset(lg)); 482c4762a1bSJed Brown 483c4762a1bSJed Brown xx[0] = 0.0; xx[1] = 1.0; cnt = 2; 4849566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetRealArray(NULL,NULL,"-zoom",xx,&cnt,NULL)); 485c4762a1bSJed Brown xs = xx[0]/hx; xm = (xx[1] - xx[0])/hx; 486c4762a1bSJed Brown 487c4762a1bSJed Brown /* 488c4762a1bSJed Brown Plot the energies 489c4762a1bSJed Brown */ 4909566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetDimension(lg,1 + (ctx->cahnhillard ? 1 : 0) + (ctx->energy == 3))); 4919566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetColors(lg,colors+1)); 4929566063dSJacob Faibussowitsch PetscCall(PetscDrawViewPortsSet(ports,2)); 493c4762a1bSJed Brown x = hx*xs; 494c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 495c4762a1bSJed Brown xx[0] = xx[1] = xx[2] = x; 496c4762a1bSJed Brown if (ctx->degenerate) yy[0] = PetscRealPart(.25*(1. - u[i]*u[i])*ctx->kappa*(u[i-1] - u[i+1])*(u[i-1] - u[i+1])*sx); 497c4762a1bSJed Brown else yy[0] = PetscRealPart(.25*ctx->kappa*(u[i-1] - u[i+1])*(u[i-1] - u[i+1])*sx); 498c4762a1bSJed Brown 499c4762a1bSJed Brown if (ctx->cahnhillard) { 500c4762a1bSJed Brown switch (ctx->energy) { 501c4762a1bSJed Brown case 1: /* double well */ 502c4762a1bSJed Brown yy[1] = .25*PetscRealPart((1. - u[i]*u[i])*(1. - u[i]*u[i])); 503c4762a1bSJed Brown break; 504c4762a1bSJed Brown case 2: /* double obstacle */ 505c4762a1bSJed Brown yy[1] = .5*PetscRealPart(1. - u[i]*u[i]); 506c4762a1bSJed Brown break; 507c4762a1bSJed Brown case 3: /* logarithm + double well */ 508c4762a1bSJed Brown yy[1] = .25*PetscRealPart((1. - u[i]*u[i])*(1. - u[i]*u[i])); 509c4762a1bSJed Brown if (PetscRealPart(u[i]) < -1.0 + 2.0*tol) yy[2] = .5*theta*(2.0*tol*PetscLogReal(tol) + PetscRealPart(1.0-u[i])*PetscLogReal(PetscRealPart(1.-u[i])/2.0)); 510c4762a1bSJed Brown else if (PetscRealPart(u[i]) > 1.0 - 2.0*tol) yy[2] = .5*theta*(PetscRealPart(1.0+u[i])*PetscLogReal(PetscRealPart(1.0+u[i])/2.0) + 2.0*tol*PetscLogReal(tol)); 511c4762a1bSJed Brown else yy[2] = .5*theta*(PetscRealPart(1.0+u[i])*PetscLogReal(PetscRealPart(1.0+u[i])/2.0) + PetscRealPart(1.0-u[i])*PetscLogReal(PetscRealPart(1.0-u[i])/2.0)); 512c4762a1bSJed Brown break; 513c4762a1bSJed Brown case 4: /* logarithm + double obstacle */ 514c4762a1bSJed Brown yy[1] = .5*theta_c*PetscRealPart(1.0-u[i]*u[i]); 515c4762a1bSJed Brown if (PetscRealPart(u[i]) < -1.0 + 2.0*tol) yy[2] = .5*theta*(2.0*tol*PetscLogReal(tol) + PetscRealPart(1.0-u[i])*PetscLogReal(PetscRealPart(1.-u[i])/2.0)); 516c4762a1bSJed Brown else if (PetscRealPart(u[i]) > 1.0 - 2.0*tol) yy[2] = .5*theta*(PetscRealPart(1.0+u[i])*PetscLogReal(PetscRealPart(1.0+u[i])/2.0) + 2.0*tol*PetscLogReal(tol)); 517c4762a1bSJed Brown else yy[2] = .5*theta*(PetscRealPart(1.0+u[i])*PetscLogReal(PetscRealPart(1.0+u[i])/2.0) + PetscRealPart(1.0-u[i])*PetscLogReal(PetscRealPart(1.0-u[i])/2.0)); 518c4762a1bSJed Brown break; 519c4762a1bSJed Brown default: 520c4762a1bSJed Brown SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"It will always be one of the values"); 521c4762a1bSJed Brown } 522c4762a1bSJed Brown } 5239566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg,xx,yy)); 524c4762a1bSJed Brown x += hx; 525c4762a1bSJed Brown } 5269566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPause(draw,&pause)); 5279566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw,0.0)); 5289566063dSJacob Faibussowitsch PetscCall(PetscDrawAxisSetLabels(axis,"Energy","","")); 5299566063dSJacob Faibussowitsch /* PetscCall(PetscDrawLGSetLegend(lg,legend[ctx->energy-1])); */ 5309566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 531c4762a1bSJed Brown 532c4762a1bSJed Brown /* 533c4762a1bSJed Brown Plot the forces 534c4762a1bSJed Brown */ 5359566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetDimension(lg,0 + (ctx->cahnhillard ? 2 : 0) + (ctx->energy == 3))); 5369566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetColors(lg,colors+1)); 5379566063dSJacob Faibussowitsch PetscCall(PetscDrawViewPortsSet(ports,1)); 5389566063dSJacob Faibussowitsch PetscCall(PetscDrawLGReset(lg)); 539c4762a1bSJed Brown x = xs*hx; 540c4762a1bSJed Brown max = 0.; 541c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 542c4762a1bSJed Brown xx[0] = xx[1] = xx[2] = xx[3] = x; 543c4762a1bSJed Brown xx_netforce = x; 544c4762a1bSJed Brown if (ctx->degenerate) { 545c4762a1bSJed Brown c = (1. - u[i]*u[i])*(u[i-1] + u[i+1] - 2.0*u[i])*sx; 546c4762a1bSJed Brown r = (1. - u[i+1]*u[i+1])*(u[i] + u[i+2] - 2.0*u[i+1])*sx; 547c4762a1bSJed Brown l = (1. - u[i-1]*u[i-1])*(u[i-2] + u[i] - 2.0*u[i-1])*sx; 548c4762a1bSJed Brown } else { 549c4762a1bSJed Brown c = (u[i-1] + u[i+1] - 2.0*u[i])*sx; 550c4762a1bSJed Brown r = (u[i] + u[i+2] - 2.0*u[i+1])*sx; 551c4762a1bSJed Brown l = (u[i-2] + u[i] - 2.0*u[i-1])*sx; 552c4762a1bSJed Brown } 553c4762a1bSJed Brown yy[0] = PetscRealPart(-ctx->kappa*(l + r - 2.0*c)*sx); 554c4762a1bSJed Brown yy_netforce = yy[0]; 555c4762a1bSJed Brown max = PetscMax(max,PetscAbs(yy[0])); 556c4762a1bSJed Brown if (ctx->cahnhillard) { 557c4762a1bSJed Brown switch (ctx->energy) { 558c4762a1bSJed Brown case 1: /* double well */ 559c4762a1bSJed Brown yy[1] = PetscRealPart(6.*.25*u[i]*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + (3.*u[i]*u[i] - 1.)*(u[i-1] + u[i+1] - 2.0*u[i])*sx); 560c4762a1bSJed Brown break; 561c4762a1bSJed Brown case 2: /* double obstacle */ 562c4762a1bSJed Brown yy[1] = -PetscRealPart(u[i-1] + u[i+1] - 2.0*u[i])*sx; 563c4762a1bSJed Brown break; 564c4762a1bSJed Brown case 3: /* logarithmic + double well */ 565c4762a1bSJed Brown yy[1] = PetscRealPart(6.*.25*u[i]*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + (3.*u[i]*u[i] - 1.)*(u[i-1] + u[i+1] - 2.0*u[i])*sx); 566c4762a1bSJed Brown if (ctx->truncation==2) { /* quadratic */ 567c4762a1bSJed Brown if (PetscRealPart(u[i]) < -1.0 + 2.0*tol) yy[2] = (.25*theta/(tol-tol*tol))*PetscRealPart(u[i-1] + u[i+1] - 2.0*u[i])*sx; 568c4762a1bSJed Brown else if (PetscRealPart(u[i]) > 1.0 - 2.0*tol) yy[2] = (.25*theta/(tol-tol*tol))*PetscRealPart(u[i-1] + u[i+1] - 2.0*u[i])*sx; 569c4762a1bSJed Brown else yy[2] = PetscRealPart(2.0*theta*u[i]/((1.0-u[i]*u[i])*(1.0-u[i]*u[i]))*.25*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + (theta/(1.0-u[i]*u[i]))*(u[i-1] + u[i+1] - 2.0*u[i])*sx); 570c4762a1bSJed Brown } else { /* cubic */ 571c4762a1bSJed Brown a = 2.0*theta*(1.0-2.0*tol)/(16.0*tol*tol*(1.0-tol)*(1.0-tol)); 572c4762a1bSJed Brown b = theta/(4.0*tol*(1.0-tol)) - a*(1.0-2.0*tol); 573c4762a1bSJed Brown if (PetscRealPart(u[i]) < -1.0 + 2.0*tol) yy[2] = PetscRealPart(-1.0*a*.25*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + (-1.0*a*u[i] + b)*(u[i-1] + u[i+1] - 2.0*u[i])*sx); 574c4762a1bSJed Brown else if (PetscRealPart(u[i]) > 1.0 - 2.0*tol) yy[2] = PetscRealPart(1.0*a*.25*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + ( a*u[i] + b)*(u[i-1] + u[i+1] - 2.0*u[i])*sx); 575c4762a1bSJed Brown else yy[2] = PetscRealPart(2.0*theta*u[i]/((1.0-u[i]*u[i])*(1.0-u[i]*u[i]))*.25*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + (theta/(1.0-u[i]*u[i]))*(u[i-1] + u[i+1] - 2.0*u[i])*sx); 576c4762a1bSJed Brown } 577c4762a1bSJed Brown break; 578c4762a1bSJed Brown case 4: /* logarithmic + double obstacle */ 579c4762a1bSJed Brown yy[1] = theta_c*PetscRealPart(-(u[i-1] + u[i+1] - 2.0*u[i]))*sx; 580c4762a1bSJed Brown if (ctx->truncation==2) { 581c4762a1bSJed Brown if (PetscRealPart(u[i]) < -1.0 + 2.0*tol) yy[2] = (.25*theta/(tol-tol*tol))*PetscRealPart(u[i-1] + u[i+1] - 2.0*u[i])*sx; 582c4762a1bSJed Brown else if (PetscRealPart(u[i]) > 1.0 - 2.0*tol) yy[2] = (.25*theta/(tol-tol*tol))*PetscRealPart(u[i-1] + u[i+1] - 2.0*u[i])*sx; 583c4762a1bSJed Brown else yy[2] = PetscRealPart(2.0*theta*u[i]/((1.0-u[i]*u[i])*(1.0-u[i]*u[i]))*.25*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + (theta/(1.0-u[i]*u[i]))*(u[i-1] + u[i+1] - 2.0*u[i])*sx); 584c4762a1bSJed Brown } 585c4762a1bSJed Brown else { 586c4762a1bSJed Brown a = 2.0*theta*(1.0-2.0*tol)/(16.0*tol*tol*(1.0-tol)*(1.0-tol)); 587c4762a1bSJed Brown b = theta/(4.0*tol*(1.0-tol)) - a*(1.0-2.0*tol); 588c4762a1bSJed Brown if (PetscRealPart(u[i]) < -1.0 + 2.0*tol) yy[2] = PetscRealPart(-1.0*a*.25*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + (-1.0*a*u[i] + b)*(u[i-1] + u[i+1] - 2.0*u[i])*sx); 589c4762a1bSJed Brown else if (PetscRealPart(u[i]) > 1.0 - 2.0*tol) yy[2] = PetscRealPart(1.0*a*.25*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + ( a*u[i] + b)*(u[i-1] + u[i+1] - 2.0*u[i])*sx); 590c4762a1bSJed Brown else yy[2] = PetscRealPart(2.0*theta*u[i]/((1.0-u[i]*u[i])*(1.0-u[i]*u[i]))*.25*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + (theta/(1.0-u[i]*u[i]))*(u[i-1] + u[i+1] - 2.0*u[i])*sx); 591c4762a1bSJed Brown } 592c4762a1bSJed Brown break; 593c4762a1bSJed Brown default: 594c4762a1bSJed Brown SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"It will always be one of the values"); 595c4762a1bSJed Brown } 596c4762a1bSJed Brown if (ctx->energy < 3) { 597c4762a1bSJed Brown max = PetscMax(max,PetscAbs(yy[1])); 598c4762a1bSJed Brown yy[2] = yy[0]+yy[1]; 599c4762a1bSJed Brown yy_netforce = yy[2]; 600c4762a1bSJed Brown } else { 601c4762a1bSJed Brown max = PetscMax(max,PetscAbs(yy[1]+yy[2])); 602c4762a1bSJed Brown yy[3] = yy[0]+yy[1]+yy[2]; 603c4762a1bSJed Brown yy_netforce = yy[3]; 604c4762a1bSJed Brown } 605c4762a1bSJed Brown } 606c4762a1bSJed Brown if (ctx->netforce) { 6079566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg,&xx_netforce,&yy_netforce)); 608c4762a1bSJed Brown } else { 6099566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg,xx,yy)); 610c4762a1bSJed Brown } 611c4762a1bSJed Brown x += hx; 612c4762a1bSJed Brown /*if (max > 7200150000.0) */ 613c4762a1bSJed Brown /* printf("max very big when i = %d\n",i); */ 614c4762a1bSJed Brown } 6159566063dSJacob Faibussowitsch PetscCall(PetscDrawAxisSetLabels(axis,"Right hand side","","")); 6169566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetLegend(lg,NULL)); 6179566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 618c4762a1bSJed Brown 619c4762a1bSJed Brown /* 620c4762a1bSJed Brown Plot the solution 621c4762a1bSJed Brown */ 6229566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetDimension(lg,1)); 6239566063dSJacob Faibussowitsch PetscCall(PetscDrawViewPortsSet(ports,0)); 6249566063dSJacob Faibussowitsch PetscCall(PetscDrawLGReset(lg)); 625c4762a1bSJed Brown x = hx*xs; 6269566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetLimits(lg,x,x+(xm-1)*hx,-1.1,1.1)); 6279566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetColors(lg,colors)); 628c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 629c4762a1bSJed Brown xx[0] = x; 630c4762a1bSJed Brown yy[0] = PetscRealPart(u[i]); 6319566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg,xx,yy)); 632c4762a1bSJed Brown x += hx; 633c4762a1bSJed Brown } 6349566063dSJacob Faibussowitsch PetscCall(PetscDrawAxisSetLabels(axis,"Solution","","")); 6359566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 636c4762a1bSJed Brown 637c4762a1bSJed Brown /* 638c4762a1bSJed Brown Print the forces as arrows on the solution 639c4762a1bSJed Brown */ 640c4762a1bSJed Brown x = hx*xs; 641c4762a1bSJed Brown cnt = xm/60; 642c4762a1bSJed Brown cnt = (!cnt) ? 1 : cnt; 643c4762a1bSJed Brown 644c4762a1bSJed Brown for (i=xs; i<xs+xm; i += cnt) { 645c4762a1bSJed Brown y = yup = ydown = PetscRealPart(u[i]); 646c4762a1bSJed Brown c = (u[i-1] + u[i+1] - 2.0*u[i])*sx; 647c4762a1bSJed Brown r = (u[i] + u[i+2] - 2.0*u[i+1])*sx; 648c4762a1bSJed Brown l = (u[i-2] + u[i] - 2.0*u[i-1])*sx; 649c4762a1bSJed Brown len = -.5*PetscRealPart(ctx->kappa*(l + r - 2.0*c)*sx)/max; 6509566063dSJacob Faibussowitsch PetscCall(PetscDrawArrow(draw,x,y,x,y+len,PETSC_DRAW_RED)); 651c4762a1bSJed Brown if (ctx->cahnhillard) { 652c4762a1bSJed Brown if (len < 0.) ydown += len; 653c4762a1bSJed Brown else yup += len; 654c4762a1bSJed Brown 655c4762a1bSJed Brown switch (ctx->energy) { 656c4762a1bSJed Brown case 1: /* double well */ 657c4762a1bSJed Brown len = .5*PetscRealPart(6.*.25*u[i]*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + (3.*u[i]*u[i] - 1.)*(u[i-1] + u[i+1] - 2.0*u[i])*sx)/max; 658c4762a1bSJed Brown break; 659c4762a1bSJed Brown case 2: /* double obstacle */ 660c4762a1bSJed Brown len = -.5*PetscRealPart(u[i-1] + u[i+1] - 2.0*u[i])*sx/max; 661c4762a1bSJed Brown break; 662c4762a1bSJed Brown case 3: /* logarithmic + double well */ 663c4762a1bSJed Brown len = .5*PetscRealPart(6.*.25*u[i]*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + (3.*u[i]*u[i] - 1.)*(u[i-1] + u[i+1] - 2.0*u[i])*sx)/max; 664c4762a1bSJed Brown if (len < 0.) ydown += len; 665c4762a1bSJed Brown else yup += len; 666c4762a1bSJed Brown 667c4762a1bSJed Brown if (ctx->truncation==2) { /* quadratic */ 668c4762a1bSJed Brown if (PetscRealPart(u[i]) < -1.0 + 2.0*tol) len2 = .5*(.25*theta/(tol-tol*tol))*PetscRealPart(u[i-1] + u[i+1] - 2.0*u[i])*sx/max; 669c4762a1bSJed Brown else if (PetscRealPart(u[i]) > 1.0 - 2.0*tol) len2 = .5*(.25*theta/(tol-tol*tol))*PetscRealPart(u[i-1] + u[i+1] - 2.0*u[i])*sx/max; 670c4762a1bSJed Brown else len2 = PetscRealPart(.5*(2.0*theta*u[i]/((1.0-u[i]*u[i])*(1.0-u[i]*u[i]))*.25*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + (theta/(1.0-u[i]*u[i]))*(u[i-1] + u[i+1] - 2.0*u[i])*sx)/max); 671c4762a1bSJed Brown } else { /* cubic */ 672c4762a1bSJed Brown a = 2.0*theta*(1.0-2.0*tol)/(16.0*tol*tol*(1.0-tol)*(1.0-tol)); 673c4762a1bSJed Brown b = theta/(4.0*tol*(1.0-tol)) - a*(1.0-2.0*tol); 674c4762a1bSJed Brown if (PetscRealPart(u[i]) < -1.0 + 2.0*tol) len2 = PetscRealPart(.5*(-1.0*a*.25*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + (-1.0*a*u[i] + b)*(u[i-1] + u[i+1] - 2.0*u[i])*sx)/max); 675c4762a1bSJed Brown else if (PetscRealPart(u[i]) > 1.0 - 2.0*tol) len2 = PetscRealPart(.5*(a*.25*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + ( a*u[i] + b)*(u[i-1] + u[i+1] - 2.0*u[i])*sx)/max); 676c4762a1bSJed Brown else len2 = PetscRealPart(.5*(2.0*theta*u[i]/((1.0-u[i]*u[i])*(1.0-u[i]*u[i]))*.25*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + (theta/(1.0-u[i]*u[i]))*(u[i-1] + u[i+1] - 2.0*u[i])*sx)/max); 677c4762a1bSJed Brown } 678c4762a1bSJed Brown y2 = len < 0 ? ydown : yup; 6799566063dSJacob Faibussowitsch PetscCall(PetscDrawArrow(draw,x,y2,x,y2+len2,PETSC_DRAW_PLUM)); 680c4762a1bSJed Brown break; 681c4762a1bSJed Brown case 4: /* logarithmic + double obstacle */ 682c4762a1bSJed Brown len = -.5*theta_c*PetscRealPart(-(u[i-1] + u[i+1] - 2.0*u[i])*sx/max); 683c4762a1bSJed Brown if (len < 0.) ydown += len; 684c4762a1bSJed Brown else yup += len; 685c4762a1bSJed Brown 686c4762a1bSJed Brown if (ctx->truncation==2) { /* quadratic */ 687c4762a1bSJed Brown if (PetscRealPart(u[i]) < -1.0 + 2.0*tol) len2 = .5*(.25*theta/(tol-tol*tol))*PetscRealPart(u[i-1] + u[i+1] - 2.0*u[i])*sx/max; 688c4762a1bSJed Brown else if (PetscRealPart(u[i]) > 1.0 - 2.0*tol) len2 = .5*(.25*theta/(tol-tol*tol))*PetscRealPart(u[i-1] + u[i+1] - 2.0*u[i])*sx/max; 689c4762a1bSJed Brown else len2 = PetscRealPart(.5*(2.0*theta*u[i]/((1.0-u[i]*u[i])*(1.0-u[i]*u[i]))*.25*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + (theta/(1.0-u[i]*u[i]))*(u[i-1] + u[i+1] - 2.0*u[i])*sx)/max); 690c4762a1bSJed Brown } else { /* cubic */ 691c4762a1bSJed Brown a = 2.0*theta*(1.0-2.0*tol)/(16.0*tol*tol*(1.0-tol)*(1.0-tol)); 692c4762a1bSJed Brown b = theta/(4.0*tol*(1.0-tol)) - a*(1.0-2.0*tol); 693c4762a1bSJed Brown if (PetscRealPart(u[i]) < -1.0 + 2.0*tol) len2 = .5*PetscRealPart(-1.0*a*.25*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + (-1.0*a*u[i] + b)*(u[i-1] + u[i+1] - 2.0*u[i])*sx)/max; 694c4762a1bSJed Brown else if (PetscRealPart(u[i]) > 1.0 - 2.0*tol) len2 = .5*PetscRealPart(a*.25*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + ( a*u[i] + b)*(u[i-1] + u[i+1] - 2.0*u[i])*sx)/max; 695c4762a1bSJed Brown else len2 = .5*PetscRealPart(2.0*theta*u[i]/((1.0-u[i]*u[i])*(1.0-u[i]*u[i]))*.25*(u[i+1] - u[i-1])*(u[i+1] - u[i-1])*sx + (theta/(1.0-u[i]*u[i]))*(u[i-1] + u[i+1] - 2.0*u[i])*sx)/max; 696c4762a1bSJed Brown } 697c4762a1bSJed Brown y2 = len < 0 ? ydown : yup; 6989566063dSJacob Faibussowitsch PetscCall(PetscDrawArrow(draw,x,y2,x,y2+len2,PETSC_DRAW_PLUM)); 699c4762a1bSJed Brown break; 700c4762a1bSJed Brown } 7019566063dSJacob Faibussowitsch PetscCall(PetscDrawArrow(draw,x,y,x,y+len,PETSC_DRAW_BLUE)); 702c4762a1bSJed Brown } 703c4762a1bSJed Brown x += cnt*hx; 704c4762a1bSJed Brown } 7059566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArrayRead(da,localU,&x)); 7069566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(da,&localU)); 7079566063dSJacob Faibussowitsch PetscCall(PetscDrawStringSetSize(draw,.2,.2)); 7089566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 7099566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw,pause)); 7109566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 711c4762a1bSJed Brown PetscFunctionReturn(0); 712c4762a1bSJed Brown } 713c4762a1bSJed Brown 714c4762a1bSJed Brown PetscErrorCode MyDestroy(void **ptr) 715c4762a1bSJed Brown { 716c4762a1bSJed Brown UserCtx *ctx = *(UserCtx**)ptr; 717c4762a1bSJed Brown 718c4762a1bSJed Brown PetscFunctionBegin; 7199566063dSJacob Faibussowitsch PetscCall(PetscDrawViewPortsDestroy(ctx->ports)); 720c4762a1bSJed Brown PetscFunctionReturn(0); 721c4762a1bSJed Brown } 722c4762a1bSJed Brown 723c4762a1bSJed Brown /*TEST 724c4762a1bSJed Brown 725c4762a1bSJed Brown test: 726c4762a1bSJed Brown TODO: currently requires initial condition file generated by heat 727c4762a1bSJed Brown 728c4762a1bSJed Brown TEST*/ 729