1c4762a1bSJed Brown /* Program usage: mpiexec -n <proc> minsurf2 [-help] [all TAO options] */ 2c4762a1bSJed Brown 3c4762a1bSJed Brown /* 4c4762a1bSJed Brown Include "petsctao.h" so we can use TAO solvers. 5c4762a1bSJed Brown petscdmda.h for distributed array 6c4762a1bSJed Brown */ 7c4762a1bSJed Brown #include <petsctao.h> 8c4762a1bSJed Brown #include <petscdmda.h> 9c4762a1bSJed Brown 109371c9d4SSatish Balay static char help[] = "This example demonstrates use of the TAO package to \n\ 11c4762a1bSJed Brown solve an unconstrained minimization problem. This example is based on a \n\ 12c4762a1bSJed Brown problem from the MINPACK-2 test suite. Given a rectangular 2-D domain and \n\ 13c4762a1bSJed Brown boundary values along the edges of the domain, the objective is to find the\n\ 14c4762a1bSJed Brown surface with the minimal area that satisfies the boundary conditions.\n\ 15c4762a1bSJed Brown The command line options are:\n\ 16*9f1eecfaSStefano Zampini -da_grid_x <xg>, where <xg> = number of grid points in the 1st coordinate direction\n\ 17*9f1eecfaSStefano Zampini -da_grid_y <yg>, where <yg> = number of grid points in the 2nd coordinate direction\n\ 18c4762a1bSJed Brown -start <st>, where <st> =0 for zero vector, <st> >0 for random start, and <st> <0 \n\ 19c4762a1bSJed Brown for an average of the boundary conditions\n\n"; 20c4762a1bSJed Brown 21c4762a1bSJed Brown /* 22c4762a1bSJed Brown User-defined application context - contains data needed by the 234936d809SStefano Zampini application-provided call-back routines, FormFunction(), 244936d809SStefano Zampini FormFunctionGradient(), and FormHessian(). 25c4762a1bSJed Brown */ 26c4762a1bSJed Brown typedef struct { 27c4762a1bSJed Brown PetscInt mx, my; /* discretization in x, y directions */ 28c4762a1bSJed Brown PetscReal *bottom, *top, *left, *right; /* boundary values */ 29c4762a1bSJed Brown DM dm; /* distributed array data structure */ 30c4762a1bSJed Brown Mat H; /* Hessian */ 31c4762a1bSJed Brown } AppCtx; 32c4762a1bSJed Brown 33c4762a1bSJed Brown /* -------- User-defined Routines --------- */ 34c4762a1bSJed Brown 35c4762a1bSJed Brown static PetscErrorCode MSA_BoundaryConditions(AppCtx *); 36c4762a1bSJed Brown static PetscErrorCode MSA_InitialPoint(AppCtx *, Vec); 374936d809SStefano Zampini static PetscErrorCode QuadraticH(AppCtx *, Vec, Mat); 384936d809SStefano Zampini static PetscErrorCode FormFunction(Tao, Vec, PetscReal *, void *); 394936d809SStefano Zampini static PetscErrorCode FormFunctionGradient(Tao, Vec, PetscReal *, Vec, void *); 404936d809SStefano Zampini static PetscErrorCode FormGradient(Tao, Vec, Vec, void *); 414936d809SStefano Zampini static PetscErrorCode FormHessian(Tao, Vec, Mat, Mat, void *); 424936d809SStefano Zampini static PetscErrorCode My_Monitor(Tao, void *); 43c4762a1bSJed Brown 44d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv) 45d71ae5a4SJacob Faibussowitsch { 46c4762a1bSJed Brown Vec x; /* solution, gradient vectors */ 47*9f1eecfaSStefano Zampini PetscBool viewmat; /* flags */ 48c4762a1bSJed Brown PetscBool fddefault, fdcoloring; /* flags */ 49c4762a1bSJed Brown Tao tao; /* TAO solver context */ 50c4762a1bSJed Brown AppCtx user; /* user-defined work context */ 51c4762a1bSJed Brown ISColoring iscoloring; 52c4762a1bSJed Brown MatFDColoring matfdcoloring; 53c4762a1bSJed Brown 54c4762a1bSJed Brown /* Initialize TAO */ 55327415f7SBarry Smith PetscFunctionBeginUser; 569566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &argv, (char *)0, help)); 57c4762a1bSJed Brown 58c4762a1bSJed Brown /* Create distributed array (DM) to manage parallel grid and vectors */ 59*9f1eecfaSStefano Zampini PetscCall(DMDACreate2d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DMDA_STENCIL_BOX, 10, 10, PETSC_DECIDE, PETSC_DECIDE, 1, 1, NULL, NULL, &user.dm)); 609566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(user.dm)); 619566063dSJacob Faibussowitsch PetscCall(DMSetUp(user.dm)); 624936d809SStefano Zampini PetscCall(DMDASetUniformCoordinates(user.dm, -0.5, 0.5, -0.5, 0.5, PETSC_DECIDE, PETSC_DECIDE)); 63*9f1eecfaSStefano Zampini PetscCall(DMDAGetInfo(user.dm, PETSC_IGNORE, &user.mx, &user.my, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE)); 64*9f1eecfaSStefano Zampini 65*9f1eecfaSStefano Zampini PetscCall(PetscPrintf(MPI_COMM_WORLD, "\n---- Minimum Surface Area Problem -----\n")); 66*9f1eecfaSStefano Zampini PetscCall(PetscPrintf(MPI_COMM_WORLD, "mx: %" PetscInt_FMT " my: %" PetscInt_FMT " \n\n", user.mx, user.my)); 67c4762a1bSJed Brown 68c4762a1bSJed Brown /* Create TAO solver and set desired solution method.*/ 699566063dSJacob Faibussowitsch PetscCall(TaoCreate(PETSC_COMM_WORLD, &tao)); 709566063dSJacob Faibussowitsch PetscCall(TaoSetType(tao, TAOCG)); 71c4762a1bSJed Brown 72c4762a1bSJed Brown /* 73c4762a1bSJed Brown Extract global vector from DA for the vector of variables -- PETSC routine 74c4762a1bSJed Brown Compute the initial solution -- application specific, see below 75c4762a1bSJed Brown Set this vector for use by TAO -- TAO routine 76c4762a1bSJed Brown */ 779566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(user.dm, &x)); 789566063dSJacob Faibussowitsch PetscCall(MSA_BoundaryConditions(&user)); 799566063dSJacob Faibussowitsch PetscCall(MSA_InitialPoint(&user, x)); 809566063dSJacob Faibussowitsch PetscCall(TaoSetSolution(tao, x)); 81c4762a1bSJed Brown 82c4762a1bSJed Brown /* 83c4762a1bSJed Brown Initialize the Application context for use in function evaluations -- application specific, see below. 84c4762a1bSJed Brown Set routines for function and gradient evaluation 85c4762a1bSJed Brown */ 864936d809SStefano Zampini PetscCall(TaoSetObjective(tao, FormFunction, (void *)&user)); 879566063dSJacob Faibussowitsch PetscCall(TaoSetObjectiveAndGradient(tao, NULL, FormFunctionGradient, (void *)&user)); 88c4762a1bSJed Brown 89c4762a1bSJed Brown /* 90c4762a1bSJed Brown Given the command line arguments, calculate the hessian with either the user- 91c4762a1bSJed Brown provided function FormHessian, or the default finite-difference driven Hessian 92c4762a1bSJed Brown functions 93c4762a1bSJed Brown */ 949566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-tao_fddefault", &fddefault)); 959566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-tao_fdcoloring", &fdcoloring)); 96c4762a1bSJed Brown 97c4762a1bSJed Brown /* 98c4762a1bSJed Brown Create a matrix data structure to store the Hessian and set 99d5b43468SJose E. Roman the Hessian evaluation routine. 100d5b43468SJose E. Roman Set the matrix structure to be used for Hessian evaluations 101c4762a1bSJed Brown */ 1029566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(user.dm, &user.H)); 1039566063dSJacob Faibussowitsch PetscCall(MatSetOption(user.H, MAT_SYMMETRIC, PETSC_TRUE)); 104c4762a1bSJed Brown 105c4762a1bSJed Brown if (fdcoloring) { 1069566063dSJacob Faibussowitsch PetscCall(DMCreateColoring(user.dm, IS_COLORING_GLOBAL, &iscoloring)); 1079566063dSJacob Faibussowitsch PetscCall(MatFDColoringCreate(user.H, iscoloring, &matfdcoloring)); 1089566063dSJacob Faibussowitsch PetscCall(ISColoringDestroy(&iscoloring)); 1099566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))FormGradient, (void *)&user)); 1109566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 1119566063dSJacob Faibussowitsch PetscCall(TaoSetHessian(tao, user.H, user.H, TaoDefaultComputeHessianColor, (void *)matfdcoloring)); 112c4762a1bSJed Brown } else if (fddefault) { 1139566063dSJacob Faibussowitsch PetscCall(TaoSetHessian(tao, user.H, user.H, TaoDefaultComputeHessian, (void *)NULL)); 114c4762a1bSJed Brown } else { 1159566063dSJacob Faibussowitsch PetscCall(TaoSetHessian(tao, user.H, user.H, FormHessian, (void *)&user)); 116c4762a1bSJed Brown } 117c4762a1bSJed Brown 118c4762a1bSJed Brown /* 119c4762a1bSJed Brown If my_monitor option is in command line, then use the user-provided 120c4762a1bSJed Brown monitoring function 121c4762a1bSJed Brown */ 1229566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-my_monitor", &viewmat)); 1231baa6e33SBarry Smith if (viewmat) PetscCall(TaoSetMonitor(tao, My_Monitor, NULL, NULL)); 124c4762a1bSJed Brown 125c4762a1bSJed Brown /* Check for any tao command line options */ 1269566063dSJacob Faibussowitsch PetscCall(TaoSetFromOptions(tao)); 127c4762a1bSJed Brown 128c4762a1bSJed Brown /* SOLVE THE APPLICATION */ 1299566063dSJacob Faibussowitsch PetscCall(TaoSolve(tao)); 130c4762a1bSJed Brown 1319566063dSJacob Faibussowitsch PetscCall(TaoView(tao, PETSC_VIEWER_STDOUT_WORLD)); 132c4762a1bSJed Brown 133c4762a1bSJed Brown /* Free TAO data structures */ 1349566063dSJacob Faibussowitsch PetscCall(TaoDestroy(&tao)); 135c4762a1bSJed Brown 136c4762a1bSJed Brown /* Free PETSc data structures */ 1379566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 1389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user.H)); 13948a46eb9SPierre Jolivet if (fdcoloring) PetscCall(MatFDColoringDestroy(&matfdcoloring)); 1409566063dSJacob Faibussowitsch PetscCall(PetscFree(user.bottom)); 1419566063dSJacob Faibussowitsch PetscCall(PetscFree(user.top)); 1429566063dSJacob Faibussowitsch PetscCall(PetscFree(user.left)); 1439566063dSJacob Faibussowitsch PetscCall(PetscFree(user.right)); 1449566063dSJacob Faibussowitsch PetscCall(DMDestroy(&user.dm)); 1459566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 146b122ec5aSJacob Faibussowitsch return 0; 147c4762a1bSJed Brown } 148c4762a1bSJed Brown 1494936d809SStefano Zampini /* -------------------------------------------------------------------- */ 1504936d809SStefano Zampini /* 1514936d809SStefano Zampini FormFunction - Evaluates the objective function. 1524936d809SStefano Zampini 1534936d809SStefano Zampini Input Parameters: 1544936d809SStefano Zampini . tao - the Tao context 1554936d809SStefano Zampini . X - input vector 1564936d809SStefano Zampini . userCtx - optional user-defined context, as set by TaoSetObjective() 1574936d809SStefano Zampini 1584936d809SStefano Zampini Output Parameters: 1594936d809SStefano Zampini . fcn - the newly evaluated function 1604936d809SStefano Zampini */ 1614936d809SStefano Zampini PetscErrorCode FormFunction(Tao tao, Vec X, PetscReal *fcn, void *userCtx) 162d71ae5a4SJacob Faibussowitsch { 1634936d809SStefano Zampini AppCtx *user = (AppCtx *)userCtx; 1644936d809SStefano Zampini PetscInt i, j; 1654936d809SStefano Zampini PetscInt mx = user->mx, my = user->my; 1664936d809SStefano Zampini PetscInt xs, xm, gxs, gxm, ys, ym, gys, gym; 1674936d809SStefano Zampini PetscReal ft = 0.0; 1684936d809SStefano Zampini PetscReal hx = 1.0 / (mx + 1), hy = 1.0 / (my + 1), area = 0.5 * hx * hy; 1694936d809SStefano Zampini PetscReal rhx = mx + 1, rhy = my + 1; 1704936d809SStefano Zampini PetscReal f2, f4, d1, d2, d3, d4, xc, xl, xr, xt, xb; 1714936d809SStefano Zampini PetscReal **x; 1724936d809SStefano Zampini Vec localX; 173c4762a1bSJed Brown 174c4762a1bSJed Brown PetscFunctionBegin; 1754936d809SStefano Zampini /* Get local mesh boundaries */ 1764936d809SStefano Zampini PetscCall(DMGetLocalVector(user->dm, &localX)); 1774936d809SStefano Zampini PetscCall(DMDAGetCorners(user->dm, &xs, &ys, NULL, &xm, &ym, NULL)); 1784936d809SStefano Zampini PetscCall(DMDAGetGhostCorners(user->dm, &gxs, &gys, NULL, &gxm, &gym, NULL)); 1794936d809SStefano Zampini 1804936d809SStefano Zampini /* Scatter ghost points to local vector */ 1814936d809SStefano Zampini PetscCall(DMGlobalToLocalBegin(user->dm, X, INSERT_VALUES, localX)); 1824936d809SStefano Zampini PetscCall(DMGlobalToLocalEnd(user->dm, X, INSERT_VALUES, localX)); 1834936d809SStefano Zampini 1844936d809SStefano Zampini /* Get pointers to vector data */ 1854936d809SStefano Zampini PetscCall(DMDAVecGetArray(user->dm, localX, (void **)&x)); 1864936d809SStefano Zampini 1874936d809SStefano Zampini /* Compute function and gradient over the locally owned part of the mesh */ 1884936d809SStefano Zampini for (j = ys; j < ys + ym; j++) { 1894936d809SStefano Zampini for (i = xs; i < xs + xm; i++) { 1904936d809SStefano Zampini xc = x[j][i]; 1914936d809SStefano Zampini 1924936d809SStefano Zampini if (i == 0) { /* left side */ 1934936d809SStefano Zampini xl = user->left[j - ys + 1]; 1944936d809SStefano Zampini } else { 1954936d809SStefano Zampini xl = x[j][i - 1]; 1964936d809SStefano Zampini } 1974936d809SStefano Zampini 1984936d809SStefano Zampini if (j == 0) { /* bottom side */ 1994936d809SStefano Zampini xb = user->bottom[i - xs + 1]; 2004936d809SStefano Zampini } else { 2014936d809SStefano Zampini xb = x[j - 1][i]; 2024936d809SStefano Zampini } 2034936d809SStefano Zampini 2044936d809SStefano Zampini if (i + 1 == gxs + gxm) { /* right side */ 2054936d809SStefano Zampini xr = user->right[j - ys + 1]; 2064936d809SStefano Zampini } else { 2074936d809SStefano Zampini xr = x[j][i + 1]; 2084936d809SStefano Zampini } 2094936d809SStefano Zampini 2104936d809SStefano Zampini if (j + 1 == gys + gym) { /* top side */ 2114936d809SStefano Zampini xt = user->top[i - xs + 1]; 2124936d809SStefano Zampini } else { 2134936d809SStefano Zampini xt = x[j + 1][i]; 2144936d809SStefano Zampini } 2154936d809SStefano Zampini 2164936d809SStefano Zampini d1 = (xc - xl); 2174936d809SStefano Zampini d2 = (xc - xr); 2184936d809SStefano Zampini d3 = (xc - xt); 2194936d809SStefano Zampini d4 = (xc - xb); 2204936d809SStefano Zampini 2214936d809SStefano Zampini d1 *= rhx; 2224936d809SStefano Zampini d2 *= rhx; 2234936d809SStefano Zampini d3 *= rhy; 2244936d809SStefano Zampini d4 *= rhy; 2254936d809SStefano Zampini 2264936d809SStefano Zampini f2 = PetscSqrtReal(1.0 + d1 * d1 + d4 * d4); 2274936d809SStefano Zampini f4 = PetscSqrtReal(1.0 + d3 * d3 + d2 * d2); 2284936d809SStefano Zampini 2294936d809SStefano Zampini ft = ft + (f2 + f4); 2304936d809SStefano Zampini } 2314936d809SStefano Zampini } 2324936d809SStefano Zampini 2334936d809SStefano Zampini /* Compute triangular areas along the border of the domain. */ 2344936d809SStefano Zampini if (xs == 0) { /* left side */ 2354936d809SStefano Zampini for (j = ys; j < ys + ym; j++) { 2364936d809SStefano Zampini d3 = (user->left[j - ys + 1] - user->left[j - ys + 2]) * rhy; 2374936d809SStefano Zampini d2 = (user->left[j - ys + 1] - x[j][0]) * rhx; 2384936d809SStefano Zampini ft = ft + PetscSqrtReal(1.0 + d3 * d3 + d2 * d2); 2394936d809SStefano Zampini } 2404936d809SStefano Zampini } 2414936d809SStefano Zampini if (ys == 0) { /* bottom side */ 2424936d809SStefano Zampini for (i = xs; i < xs + xm; i++) { 2434936d809SStefano Zampini d2 = (user->bottom[i + 1 - xs] - user->bottom[i - xs + 2]) * rhx; 2444936d809SStefano Zampini d3 = (user->bottom[i - xs + 1] - x[0][i]) * rhy; 2454936d809SStefano Zampini ft = ft + PetscSqrtReal(1.0 + d3 * d3 + d2 * d2); 2464936d809SStefano Zampini } 2474936d809SStefano Zampini } 2484936d809SStefano Zampini if (xs + xm == mx) { /* right side */ 2494936d809SStefano Zampini for (j = ys; j < ys + ym; j++) { 2504936d809SStefano Zampini d1 = (x[j][mx - 1] - user->right[j - ys + 1]) * rhx; 2514936d809SStefano Zampini d4 = (user->right[j - ys] - user->right[j - ys + 1]) * rhy; 2524936d809SStefano Zampini ft = ft + PetscSqrtReal(1.0 + d1 * d1 + d4 * d4); 2534936d809SStefano Zampini } 2544936d809SStefano Zampini } 2554936d809SStefano Zampini if (ys + ym == my) { /* top side */ 2564936d809SStefano Zampini for (i = xs; i < xs + xm; i++) { 2574936d809SStefano Zampini d1 = (x[my - 1][i] - user->top[i - xs + 1]) * rhy; 2584936d809SStefano Zampini d4 = (user->top[i - xs + 1] - user->top[i - xs]) * rhx; 2594936d809SStefano Zampini ft = ft + PetscSqrtReal(1.0 + d1 * d1 + d4 * d4); 2604936d809SStefano Zampini } 2614936d809SStefano Zampini } 2624936d809SStefano Zampini if (ys == 0 && xs == 0) { 2634936d809SStefano Zampini d1 = (user->left[0] - user->left[1]) / hy; 2644936d809SStefano Zampini d2 = (user->bottom[0] - user->bottom[1]) * rhx; 2654936d809SStefano Zampini ft += PetscSqrtReal(1.0 + d1 * d1 + d2 * d2); 2664936d809SStefano Zampini } 2674936d809SStefano Zampini if (ys + ym == my && xs + xm == mx) { 2684936d809SStefano Zampini d1 = (user->right[ym + 1] - user->right[ym]) * rhy; 2694936d809SStefano Zampini d2 = (user->top[xm + 1] - user->top[xm]) * rhx; 2704936d809SStefano Zampini ft += PetscSqrtReal(1.0 + d1 * d1 + d2 * d2); 2714936d809SStefano Zampini } 2724936d809SStefano Zampini 2734936d809SStefano Zampini ft = ft * area; 2744936d809SStefano Zampini PetscCall(MPIU_Allreduce(&ft, fcn, 1, MPIU_REAL, MPIU_SUM, MPI_COMM_WORLD)); 2754936d809SStefano Zampini 2764936d809SStefano Zampini /* Restore vectors */ 2774936d809SStefano Zampini PetscCall(DMDAVecRestoreArray(user->dm, localX, (void **)&x)); 2784936d809SStefano Zampini PetscCall(DMRestoreLocalVector(user->dm, &localX)); 2793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 280c4762a1bSJed Brown } 281c4762a1bSJed Brown 282c4762a1bSJed Brown /* -------------------------------------------------------------------- */ 2834936d809SStefano Zampini /* 2844936d809SStefano Zampini FormFunctionGradient - Evaluates the function and corresponding gradient. 285c4762a1bSJed Brown 286c4762a1bSJed Brown Input Parameters: 287c4762a1bSJed Brown . tao - the Tao context 2884936d809SStefano Zampini . X - input vector 289a82e8c82SStefano Zampini . userCtx - optional user-defined context, as set by TaoSetObjectiveAndGradient() 290c4762a1bSJed Brown 291c4762a1bSJed Brown Output Parameters: 292c4762a1bSJed Brown . fcn - the newly evaluated function 2934936d809SStefano Zampini . G - vector containing the newly evaluated gradient 294c4762a1bSJed Brown */ 295d71ae5a4SJacob Faibussowitsch PetscErrorCode FormFunctionGradient(Tao tao, Vec X, PetscReal *fcn, Vec G, void *userCtx) 296d71ae5a4SJacob Faibussowitsch { 297c4762a1bSJed Brown AppCtx *user = (AppCtx *)userCtx; 298c4762a1bSJed Brown PetscInt i, j; 299c4762a1bSJed Brown PetscInt mx = user->mx, my = user->my; 300c4762a1bSJed Brown PetscInt xs, xm, gxs, gxm, ys, ym, gys, gym; 301c4762a1bSJed Brown PetscReal ft = 0.0; 302c4762a1bSJed Brown PetscReal hx = 1.0 / (mx + 1), hy = 1.0 / (my + 1), hydhx = hy / hx, hxdhy = hx / hy, area = 0.5 * hx * hy; 303c4762a1bSJed Brown PetscReal rhx = mx + 1, rhy = my + 1; 304c4762a1bSJed Brown PetscReal f1, f2, f3, f4, f5, f6, d1, d2, d3, d4, d5, d6, d7, d8, xc, xl, xr, xt, xb, xlt, xrb; 305c4762a1bSJed Brown PetscReal df1dxc, df2dxc, df3dxc, df4dxc, df5dxc, df6dxc; 306c4762a1bSJed Brown PetscReal **g, **x; 307c4762a1bSJed Brown Vec localX; 308c4762a1bSJed Brown 309c4762a1bSJed Brown PetscFunctionBegin; 310c4762a1bSJed Brown /* Get local mesh boundaries */ 3119566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(user->dm, &localX)); 3129566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(user->dm, &xs, &ys, NULL, &xm, &ym, NULL)); 3139566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(user->dm, &gxs, &gys, NULL, &gxm, &gym, NULL)); 314c4762a1bSJed Brown 315c4762a1bSJed Brown /* Scatter ghost points to local vector */ 3169566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(user->dm, X, INSERT_VALUES, localX)); 3179566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(user->dm, X, INSERT_VALUES, localX)); 318c4762a1bSJed Brown 319c4762a1bSJed Brown /* Get pointers to vector data */ 3209566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(user->dm, localX, (void **)&x)); 3219566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(user->dm, G, (void **)&g)); 322c4762a1bSJed Brown 323c4762a1bSJed Brown /* Compute function and gradient over the locally owned part of the mesh */ 324c4762a1bSJed Brown for (j = ys; j < ys + ym; j++) { 325c4762a1bSJed Brown for (i = xs; i < xs + xm; i++) { 326c4762a1bSJed Brown xc = x[j][i]; 327c4762a1bSJed Brown xlt = xrb = xl = xr = xb = xt = xc; 328c4762a1bSJed Brown 329c4762a1bSJed Brown if (i == 0) { /* left side */ 330c4762a1bSJed Brown xl = user->left[j - ys + 1]; 331c4762a1bSJed Brown xlt = user->left[j - ys + 2]; 332c4762a1bSJed Brown } else { 333c4762a1bSJed Brown xl = x[j][i - 1]; 334c4762a1bSJed Brown } 335c4762a1bSJed Brown 336c4762a1bSJed Brown if (j == 0) { /* bottom side */ 337c4762a1bSJed Brown xb = user->bottom[i - xs + 1]; 338c4762a1bSJed Brown xrb = user->bottom[i - xs + 2]; 339c4762a1bSJed Brown } else { 340c4762a1bSJed Brown xb = x[j - 1][i]; 341c4762a1bSJed Brown } 342c4762a1bSJed Brown 343c4762a1bSJed Brown if (i + 1 == gxs + gxm) { /* right side */ 344c4762a1bSJed Brown xr = user->right[j - ys + 1]; 345c4762a1bSJed Brown xrb = user->right[j - ys]; 346c4762a1bSJed Brown } else { 347c4762a1bSJed Brown xr = x[j][i + 1]; 348c4762a1bSJed Brown } 349c4762a1bSJed Brown 350c4762a1bSJed Brown if (j + 1 == gys + gym) { /* top side */ 351c4762a1bSJed Brown xt = user->top[i - xs + 1]; 352c4762a1bSJed Brown xlt = user->top[i - xs]; 353c4762a1bSJed Brown } else { 354c4762a1bSJed Brown xt = x[j + 1][i]; 355c4762a1bSJed Brown } 356c4762a1bSJed Brown 357ad540459SPierre Jolivet if (i > gxs && j + 1 < gys + gym) xlt = x[j + 1][i - 1]; 358ad540459SPierre Jolivet if (j > gys && i + 1 < gxs + gxm) xrb = x[j - 1][i + 1]; 359c4762a1bSJed Brown 360c4762a1bSJed Brown d1 = (xc - xl); 361c4762a1bSJed Brown d2 = (xc - xr); 362c4762a1bSJed Brown d3 = (xc - xt); 363c4762a1bSJed Brown d4 = (xc - xb); 364c4762a1bSJed Brown d5 = (xr - xrb); 365c4762a1bSJed Brown d6 = (xrb - xb); 366c4762a1bSJed Brown d7 = (xlt - xl); 367c4762a1bSJed Brown d8 = (xt - xlt); 368c4762a1bSJed Brown 369c4762a1bSJed Brown df1dxc = d1 * hydhx; 370c4762a1bSJed Brown df2dxc = (d1 * hydhx + d4 * hxdhy); 371c4762a1bSJed Brown df3dxc = d3 * hxdhy; 372c4762a1bSJed Brown df4dxc = (d2 * hydhx + d3 * hxdhy); 373c4762a1bSJed Brown df5dxc = d2 * hydhx; 374c4762a1bSJed Brown df6dxc = d4 * hxdhy; 375c4762a1bSJed Brown 376c4762a1bSJed Brown d1 *= rhx; 377c4762a1bSJed Brown d2 *= rhx; 378c4762a1bSJed Brown d3 *= rhy; 379c4762a1bSJed Brown d4 *= rhy; 380c4762a1bSJed Brown d5 *= rhy; 381c4762a1bSJed Brown d6 *= rhx; 382c4762a1bSJed Brown d7 *= rhy; 383c4762a1bSJed Brown d8 *= rhx; 384c4762a1bSJed Brown 385c4762a1bSJed Brown f1 = PetscSqrtReal(1.0 + d1 * d1 + d7 * d7); 386c4762a1bSJed Brown f2 = PetscSqrtReal(1.0 + d1 * d1 + d4 * d4); 387c4762a1bSJed Brown f3 = PetscSqrtReal(1.0 + d3 * d3 + d8 * d8); 388c4762a1bSJed Brown f4 = PetscSqrtReal(1.0 + d3 * d3 + d2 * d2); 389c4762a1bSJed Brown f5 = PetscSqrtReal(1.0 + d2 * d2 + d5 * d5); 390c4762a1bSJed Brown f6 = PetscSqrtReal(1.0 + d4 * d4 + d6 * d6); 391c4762a1bSJed Brown 392c4762a1bSJed Brown ft = ft + (f2 + f4); 393c4762a1bSJed Brown 394c4762a1bSJed Brown df1dxc /= f1; 395c4762a1bSJed Brown df2dxc /= f2; 396c4762a1bSJed Brown df3dxc /= f3; 397c4762a1bSJed Brown df4dxc /= f4; 398c4762a1bSJed Brown df5dxc /= f5; 399c4762a1bSJed Brown df6dxc /= f6; 400c4762a1bSJed Brown 401c4762a1bSJed Brown g[j][i] = (df1dxc + df2dxc + df3dxc + df4dxc + df5dxc + df6dxc) * 0.5; 402c4762a1bSJed Brown } 403c4762a1bSJed Brown } 404c4762a1bSJed Brown 405c4762a1bSJed Brown /* Compute triangular areas along the border of the domain. */ 406c4762a1bSJed Brown if (xs == 0) { /* left side */ 407c4762a1bSJed Brown for (j = ys; j < ys + ym; j++) { 408c4762a1bSJed Brown d3 = (user->left[j - ys + 1] - user->left[j - ys + 2]) * rhy; 409c4762a1bSJed Brown d2 = (user->left[j - ys + 1] - x[j][0]) * rhx; 410c4762a1bSJed Brown ft = ft + PetscSqrtReal(1.0 + d3 * d3 + d2 * d2); 411c4762a1bSJed Brown } 412c4762a1bSJed Brown } 413c4762a1bSJed Brown if (ys == 0) { /* bottom side */ 414c4762a1bSJed Brown for (i = xs; i < xs + xm; i++) { 415c4762a1bSJed Brown d2 = (user->bottom[i + 1 - xs] - user->bottom[i - xs + 2]) * rhx; 416c4762a1bSJed Brown d3 = (user->bottom[i - xs + 1] - x[0][i]) * rhy; 417c4762a1bSJed Brown ft = ft + PetscSqrtReal(1.0 + d3 * d3 + d2 * d2); 418c4762a1bSJed Brown } 419c4762a1bSJed Brown } 420c4762a1bSJed Brown 421c4762a1bSJed Brown if (xs + xm == mx) { /* right side */ 422c4762a1bSJed Brown for (j = ys; j < ys + ym; j++) { 423c4762a1bSJed Brown d1 = (x[j][mx - 1] - user->right[j - ys + 1]) * rhx; 424c4762a1bSJed Brown d4 = (user->right[j - ys] - user->right[j - ys + 1]) * rhy; 425c4762a1bSJed Brown ft = ft + PetscSqrtReal(1.0 + d1 * d1 + d4 * d4); 426c4762a1bSJed Brown } 427c4762a1bSJed Brown } 428c4762a1bSJed Brown if (ys + ym == my) { /* top side */ 429c4762a1bSJed Brown for (i = xs; i < xs + xm; i++) { 430c4762a1bSJed Brown d1 = (x[my - 1][i] - user->top[i - xs + 1]) * rhy; 431c4762a1bSJed Brown d4 = (user->top[i - xs + 1] - user->top[i - xs]) * rhx; 432c4762a1bSJed Brown ft = ft + PetscSqrtReal(1.0 + d1 * d1 + d4 * d4); 433c4762a1bSJed Brown } 434c4762a1bSJed Brown } 435c4762a1bSJed Brown 436c4762a1bSJed Brown if (ys == 0 && xs == 0) { 437c4762a1bSJed Brown d1 = (user->left[0] - user->left[1]) / hy; 438c4762a1bSJed Brown d2 = (user->bottom[0] - user->bottom[1]) * rhx; 439c4762a1bSJed Brown ft += PetscSqrtReal(1.0 + d1 * d1 + d2 * d2); 440c4762a1bSJed Brown } 441c4762a1bSJed Brown if (ys + ym == my && xs + xm == mx) { 442c4762a1bSJed Brown d1 = (user->right[ym + 1] - user->right[ym]) * rhy; 443c4762a1bSJed Brown d2 = (user->top[xm + 1] - user->top[xm]) * rhx; 444c4762a1bSJed Brown ft += PetscSqrtReal(1.0 + d1 * d1 + d2 * d2); 445c4762a1bSJed Brown } 446c4762a1bSJed Brown 447c4762a1bSJed Brown ft = ft * area; 448712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&ft, fcn, 1, MPIU_REAL, MPIU_SUM, MPI_COMM_WORLD)); 449c4762a1bSJed Brown 450c4762a1bSJed Brown /* Restore vectors */ 4519566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(user->dm, localX, (void **)&x)); 4529566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(user->dm, G, (void **)&g)); 4539566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(user->dm, &localX)); 4549566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(67.0 * xm * ym)); 4553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 456c4762a1bSJed Brown } 457c4762a1bSJed Brown 4584936d809SStefano Zampini PetscErrorCode FormGradient(Tao tao, Vec X, Vec G, void *userCtx) 4594936d809SStefano Zampini { 4604936d809SStefano Zampini PetscReal fcn; 4614936d809SStefano Zampini 4624936d809SStefano Zampini PetscFunctionBegin; 4634936d809SStefano Zampini PetscCall(FormFunctionGradient(tao, X, &fcn, G, userCtx)); 4644936d809SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 4654936d809SStefano Zampini } 4664936d809SStefano Zampini 467c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 468c4762a1bSJed Brown /* 469c4762a1bSJed Brown FormHessian - Evaluates Hessian matrix. 470c4762a1bSJed Brown 471c4762a1bSJed Brown Input Parameters: 472c4762a1bSJed Brown . tao - the Tao context 473c4762a1bSJed Brown . x - input vector 474a82e8c82SStefano Zampini . ptr - optional user-defined context, as set by TaoSetHessian() 475c4762a1bSJed Brown 476c4762a1bSJed Brown Output Parameters: 477c4762a1bSJed Brown . H - Hessian matrix 478c4762a1bSJed Brown . Hpre - optionally different preconditioning matrix 479c4762a1bSJed Brown . flg - flag indicating matrix structure 480c4762a1bSJed Brown 481c4762a1bSJed Brown */ 482d71ae5a4SJacob Faibussowitsch PetscErrorCode FormHessian(Tao tao, Vec X, Mat H, Mat Hpre, void *ptr) 483d71ae5a4SJacob Faibussowitsch { 484c4762a1bSJed Brown AppCtx *user = (AppCtx *)ptr; 485c4762a1bSJed Brown 486c4762a1bSJed Brown PetscFunctionBegin; 487c4762a1bSJed Brown /* Evaluate the Hessian entries*/ 4889566063dSJacob Faibussowitsch PetscCall(QuadraticH(user, X, H)); 4893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 490c4762a1bSJed Brown } 491c4762a1bSJed Brown 492c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 493c4762a1bSJed Brown /* 494c4762a1bSJed Brown QuadraticH - Evaluates Hessian matrix. 495c4762a1bSJed Brown 496c4762a1bSJed Brown Input Parameters: 497c4762a1bSJed Brown . user - user-defined context, as set by TaoSetHessian() 498c4762a1bSJed Brown . X - input vector 499c4762a1bSJed Brown 500c4762a1bSJed Brown Output Parameter: 501c4762a1bSJed Brown . H - Hessian matrix 502c4762a1bSJed Brown */ 503d71ae5a4SJacob Faibussowitsch PetscErrorCode QuadraticH(AppCtx *user, Vec X, Mat Hessian) 504d71ae5a4SJacob Faibussowitsch { 505c4762a1bSJed Brown PetscInt i, j, k; 506c4762a1bSJed Brown PetscInt mx = user->mx, my = user->my; 507c4762a1bSJed Brown PetscInt xs, xm, gxs, gxm, ys, ym, gys, gym; 508c4762a1bSJed Brown PetscReal hx = 1.0 / (mx + 1), hy = 1.0 / (my + 1), hydhx = hy / hx, hxdhy = hx / hy; 509c4762a1bSJed Brown PetscReal f1, f2, f3, f4, f5, f6, d1, d2, d3, d4, d5, d6, d7, d8, xc, xl, xr, xt, xb, xlt, xrb; 510c4762a1bSJed Brown PetscReal hl, hr, ht, hb, hc, htl, hbr; 511c4762a1bSJed Brown PetscReal **x, v[7]; 512c4762a1bSJed Brown MatStencil col[7], row; 513c4762a1bSJed Brown Vec localX; 514c4762a1bSJed Brown PetscBool assembled; 515c4762a1bSJed Brown 516c4762a1bSJed Brown PetscFunctionBegin; 517c4762a1bSJed Brown /* Get local mesh boundaries */ 5189566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(user->dm, &localX)); 519c4762a1bSJed Brown 5209566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(user->dm, &xs, &ys, NULL, &xm, &ym, NULL)); 5219566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(user->dm, &gxs, &gys, NULL, &gxm, &gym, NULL)); 522c4762a1bSJed Brown 523c4762a1bSJed Brown /* Scatter ghost points to local vector */ 5249566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(user->dm, X, INSERT_VALUES, localX)); 5259566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(user->dm, X, INSERT_VALUES, localX)); 526c4762a1bSJed Brown 527c4762a1bSJed Brown /* Get pointers to vector data */ 5289566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(user->dm, localX, (void **)&x)); 529c4762a1bSJed Brown 530c4762a1bSJed Brown /* Initialize matrix entries to zero */ 5319566063dSJacob Faibussowitsch PetscCall(MatAssembled(Hessian, &assembled)); 5329566063dSJacob Faibussowitsch if (assembled) PetscCall(MatZeroEntries(Hessian)); 533c4762a1bSJed Brown 534c4762a1bSJed Brown /* Set various matrix options */ 5359566063dSJacob Faibussowitsch PetscCall(MatSetOption(Hessian, MAT_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE)); 536c4762a1bSJed Brown 537c4762a1bSJed Brown /* Compute Hessian over the locally owned part of the mesh */ 538c4762a1bSJed Brown for (j = ys; j < ys + ym; j++) { 539c4762a1bSJed Brown for (i = xs; i < xs + xm; i++) { 540c4762a1bSJed Brown xc = x[j][i]; 541c4762a1bSJed Brown xlt = xrb = xl = xr = xb = xt = xc; 542c4762a1bSJed Brown 543c4762a1bSJed Brown /* Left side */ 544c4762a1bSJed Brown if (i == 0) { 545c4762a1bSJed Brown xl = user->left[j - ys + 1]; 546c4762a1bSJed Brown xlt = user->left[j - ys + 2]; 547c4762a1bSJed Brown } else { 548c4762a1bSJed Brown xl = x[j][i - 1]; 549c4762a1bSJed Brown } 550c4762a1bSJed Brown 551c4762a1bSJed Brown if (j == 0) { 552c4762a1bSJed Brown xb = user->bottom[i - xs + 1]; 553c4762a1bSJed Brown xrb = user->bottom[i - xs + 2]; 554c4762a1bSJed Brown } else { 555c4762a1bSJed Brown xb = x[j - 1][i]; 556c4762a1bSJed Brown } 557c4762a1bSJed Brown 558c4762a1bSJed Brown if (i + 1 == mx) { 559c4762a1bSJed Brown xr = user->right[j - ys + 1]; 560c4762a1bSJed Brown xrb = user->right[j - ys]; 561c4762a1bSJed Brown } else { 562c4762a1bSJed Brown xr = x[j][i + 1]; 563c4762a1bSJed Brown } 564c4762a1bSJed Brown 565c4762a1bSJed Brown if (j + 1 == my) { 566c4762a1bSJed Brown xt = user->top[i - xs + 1]; 567c4762a1bSJed Brown xlt = user->top[i - xs]; 568c4762a1bSJed Brown } else { 569c4762a1bSJed Brown xt = x[j + 1][i]; 570c4762a1bSJed Brown } 571c4762a1bSJed Brown 572ad540459SPierre Jolivet if (i > 0 && j + 1 < my) xlt = x[j + 1][i - 1]; 573ad540459SPierre Jolivet if (j > 0 && i + 1 < mx) xrb = x[j - 1][i + 1]; 574c4762a1bSJed Brown 575c4762a1bSJed Brown d1 = (xc - xl) / hx; 576c4762a1bSJed Brown d2 = (xc - xr) / hx; 577c4762a1bSJed Brown d3 = (xc - xt) / hy; 578c4762a1bSJed Brown d4 = (xc - xb) / hy; 579c4762a1bSJed Brown d5 = (xrb - xr) / hy; 580c4762a1bSJed Brown d6 = (xrb - xb) / hx; 581c4762a1bSJed Brown d7 = (xlt - xl) / hy; 582c4762a1bSJed Brown d8 = (xlt - xt) / hx; 583c4762a1bSJed Brown 584c4762a1bSJed Brown f1 = PetscSqrtReal(1.0 + d1 * d1 + d7 * d7); 585c4762a1bSJed Brown f2 = PetscSqrtReal(1.0 + d1 * d1 + d4 * d4); 586c4762a1bSJed Brown f3 = PetscSqrtReal(1.0 + d3 * d3 + d8 * d8); 587c4762a1bSJed Brown f4 = PetscSqrtReal(1.0 + d3 * d3 + d2 * d2); 588c4762a1bSJed Brown f5 = PetscSqrtReal(1.0 + d2 * d2 + d5 * d5); 589c4762a1bSJed Brown f6 = PetscSqrtReal(1.0 + d4 * d4 + d6 * d6); 590c4762a1bSJed Brown 5919371c9d4SSatish Balay hl = (-hydhx * (1.0 + d7 * d7) + d1 * d7) / (f1 * f1 * f1) + (-hydhx * (1.0 + d4 * d4) + d1 * d4) / (f2 * f2 * f2); 5929371c9d4SSatish Balay hr = (-hydhx * (1.0 + d5 * d5) + d2 * d5) / (f5 * f5 * f5) + (-hydhx * (1.0 + d3 * d3) + d2 * d3) / (f4 * f4 * f4); 5939371c9d4SSatish Balay ht = (-hxdhy * (1.0 + d8 * d8) + d3 * d8) / (f3 * f3 * f3) + (-hxdhy * (1.0 + d2 * d2) + d2 * d3) / (f4 * f4 * f4); 5949371c9d4SSatish Balay hb = (-hxdhy * (1.0 + d6 * d6) + d4 * d6) / (f6 * f6 * f6) + (-hxdhy * (1.0 + d1 * d1) + d1 * d4) / (f2 * f2 * f2); 595c4762a1bSJed Brown 596c4762a1bSJed Brown hbr = -d2 * d5 / (f5 * f5 * f5) - d4 * d6 / (f6 * f6 * f6); 597c4762a1bSJed Brown htl = -d1 * d7 / (f1 * f1 * f1) - d3 * d8 / (f3 * f3 * f3); 598c4762a1bSJed Brown 5999371c9d4SSatish Balay hc = hydhx * (1.0 + d7 * d7) / (f1 * f1 * f1) + hxdhy * (1.0 + d8 * d8) / (f3 * f3 * f3) + hydhx * (1.0 + d5 * d5) / (f5 * f5 * f5) + hxdhy * (1.0 + d6 * d6) / (f6 * f6 * f6) + (hxdhy * (1.0 + d1 * d1) + hydhx * (1.0 + d4 * d4) - 2 * d1 * d4) / (f2 * f2 * f2) + (hxdhy * (1.0 + d2 * d2) + hydhx * (1.0 + d3 * d3) - 2 * d2 * d3) / (f4 * f4 * f4); 600c4762a1bSJed Brown 6019371c9d4SSatish Balay hl /= 2.0; 6029371c9d4SSatish Balay hr /= 2.0; 6039371c9d4SSatish Balay ht /= 2.0; 6049371c9d4SSatish Balay hb /= 2.0; 6059371c9d4SSatish Balay hbr /= 2.0; 6069371c9d4SSatish Balay htl /= 2.0; 6079371c9d4SSatish Balay hc /= 2.0; 608c4762a1bSJed Brown 6099371c9d4SSatish Balay row.j = j; 6109371c9d4SSatish Balay row.i = i; 611c4762a1bSJed Brown k = 0; 612c4762a1bSJed Brown if (j > 0) { 613c4762a1bSJed Brown v[k] = hb; 6149371c9d4SSatish Balay col[k].j = j - 1; 6159371c9d4SSatish Balay col[k].i = i; 616c4762a1bSJed Brown k++; 617c4762a1bSJed Brown } 618c4762a1bSJed Brown 619c4762a1bSJed Brown if (j > 0 && i < mx - 1) { 620c4762a1bSJed Brown v[k] = hbr; 6219371c9d4SSatish Balay col[k].j = j - 1; 6229371c9d4SSatish Balay col[k].i = i + 1; 623c4762a1bSJed Brown k++; 624c4762a1bSJed Brown } 625c4762a1bSJed Brown 626c4762a1bSJed Brown if (i > 0) { 627c4762a1bSJed Brown v[k] = hl; 6289371c9d4SSatish Balay col[k].j = j; 6299371c9d4SSatish Balay col[k].i = i - 1; 630c4762a1bSJed Brown k++; 631c4762a1bSJed Brown } 632c4762a1bSJed Brown 633c4762a1bSJed Brown v[k] = hc; 6349371c9d4SSatish Balay col[k].j = j; 6359371c9d4SSatish Balay col[k].i = i; 636c4762a1bSJed Brown k++; 637c4762a1bSJed Brown 638c4762a1bSJed Brown if (i < mx - 1) { 639c4762a1bSJed Brown v[k] = hr; 6409371c9d4SSatish Balay col[k].j = j; 6419371c9d4SSatish Balay col[k].i = i + 1; 642c4762a1bSJed Brown k++; 643c4762a1bSJed Brown } 644c4762a1bSJed Brown 645c4762a1bSJed Brown if (i > 0 && j < my - 1) { 646c4762a1bSJed Brown v[k] = htl; 6479371c9d4SSatish Balay col[k].j = j + 1; 6489371c9d4SSatish Balay col[k].i = i - 1; 649c4762a1bSJed Brown k++; 650c4762a1bSJed Brown } 651c4762a1bSJed Brown 652c4762a1bSJed Brown if (j < my - 1) { 653c4762a1bSJed Brown v[k] = ht; 6549371c9d4SSatish Balay col[k].j = j + 1; 6559371c9d4SSatish Balay col[k].i = i; 656c4762a1bSJed Brown k++; 657c4762a1bSJed Brown } 658c4762a1bSJed Brown 659c4762a1bSJed Brown /* 660c4762a1bSJed Brown Set matrix values using local numbering, which was defined 661c4762a1bSJed Brown earlier, in the main routine. 662c4762a1bSJed Brown */ 6639566063dSJacob Faibussowitsch PetscCall(MatSetValuesStencil(Hessian, 1, &row, k, col, v, INSERT_VALUES)); 664c4762a1bSJed Brown } 665c4762a1bSJed Brown } 666c4762a1bSJed Brown 6679566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(user->dm, localX, (void **)&x)); 6689566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(user->dm, &localX)); 669c4762a1bSJed Brown 6709566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(Hessian, MAT_FINAL_ASSEMBLY)); 6719566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(Hessian, MAT_FINAL_ASSEMBLY)); 672c4762a1bSJed Brown 6739566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(199.0 * xm * ym)); 6743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 675c4762a1bSJed Brown } 676c4762a1bSJed Brown 677c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 678c4762a1bSJed Brown /* 679c4762a1bSJed Brown MSA_BoundaryConditions - Calculates the boundary conditions for 680c4762a1bSJed Brown the region. 681c4762a1bSJed Brown 682c4762a1bSJed Brown Input Parameter: 683c4762a1bSJed Brown . user - user-defined application context 684c4762a1bSJed Brown 685c4762a1bSJed Brown Output Parameter: 686c4762a1bSJed Brown . user - user-defined application context 687c4762a1bSJed Brown */ 688d71ae5a4SJacob Faibussowitsch static PetscErrorCode MSA_BoundaryConditions(AppCtx *user) 689d71ae5a4SJacob Faibussowitsch { 690c4762a1bSJed Brown PetscInt i, j, k, limit = 0, maxits = 5; 691c4762a1bSJed Brown PetscInt xs, ys, xm, ym, gxs, gys, gxm, gym; 692c4762a1bSJed Brown PetscInt mx = user->mx, my = user->my; 693c4762a1bSJed Brown PetscInt bsize = 0, lsize = 0, tsize = 0, rsize = 0; 694c4762a1bSJed Brown PetscReal one = 1.0, two = 2.0, three = 3.0, tol = 1e-10; 695c4762a1bSJed Brown PetscReal fnorm, det, hx, hy, xt = 0, yt = 0; 696c4762a1bSJed Brown PetscReal u1, u2, nf1, nf2, njac11, njac12, njac21, njac22; 697c4762a1bSJed Brown PetscReal b = -0.5, t = 0.5, l = -0.5, r = 0.5; 698c4762a1bSJed Brown PetscReal *boundary; 699c4762a1bSJed Brown PetscBool flg; 700c4762a1bSJed Brown 701c4762a1bSJed Brown PetscFunctionBegin; 702c4762a1bSJed Brown /* Get local mesh boundaries */ 7039566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(user->dm, &xs, &ys, NULL, &xm, &ym, NULL)); 7049566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(user->dm, &gxs, &gys, NULL, &gxm, &gym, NULL)); 705c4762a1bSJed Brown 706c4762a1bSJed Brown bsize = xm + 2; 707c4762a1bSJed Brown lsize = ym + 2; 708c4762a1bSJed Brown rsize = ym + 2; 709c4762a1bSJed Brown tsize = xm + 2; 710c4762a1bSJed Brown 7119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bsize, &user->bottom)); 7129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(tsize, &user->top)); 7139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lsize, &user->left)); 7149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rsize, &user->right)); 715c4762a1bSJed Brown 7169371c9d4SSatish Balay hx = (r - l) / (mx + 1); 7179371c9d4SSatish Balay hy = (t - b) / (my + 1); 718c4762a1bSJed Brown 719c4762a1bSJed Brown for (j = 0; j < 4; j++) { 720c4762a1bSJed Brown if (j == 0) { 721c4762a1bSJed Brown yt = b; 722c4762a1bSJed Brown xt = l + hx * xs; 723c4762a1bSJed Brown limit = bsize; 724c4762a1bSJed Brown boundary = user->bottom; 725c4762a1bSJed Brown } else if (j == 1) { 726c4762a1bSJed Brown yt = t; 727c4762a1bSJed Brown xt = l + hx * xs; 728c4762a1bSJed Brown limit = tsize; 729c4762a1bSJed Brown boundary = user->top; 730c4762a1bSJed Brown } else if (j == 2) { 731c4762a1bSJed Brown yt = b + hy * ys; 732c4762a1bSJed Brown xt = l; 733c4762a1bSJed Brown limit = lsize; 734c4762a1bSJed Brown boundary = user->left; 735c4762a1bSJed Brown } else { /* if (j==3) */ 736c4762a1bSJed Brown yt = b + hy * ys; 737c4762a1bSJed Brown xt = r; 738c4762a1bSJed Brown limit = rsize; 739c4762a1bSJed Brown boundary = user->right; 740c4762a1bSJed Brown } 741c4762a1bSJed Brown 742c4762a1bSJed Brown for (i = 0; i < limit; i++) { 743c4762a1bSJed Brown u1 = xt; 744c4762a1bSJed Brown u2 = -yt; 745c4762a1bSJed Brown for (k = 0; k < maxits; k++) { 746c4762a1bSJed Brown nf1 = u1 + u1 * u2 * u2 - u1 * u1 * u1 / three - xt; 747c4762a1bSJed Brown nf2 = -u2 - u1 * u1 * u2 + u2 * u2 * u2 / three - yt; 748c4762a1bSJed Brown fnorm = PetscSqrtReal(nf1 * nf1 + nf2 * nf2); 749c4762a1bSJed Brown if (fnorm <= tol) break; 750c4762a1bSJed Brown njac11 = one + u2 * u2 - u1 * u1; 751c4762a1bSJed Brown njac12 = two * u1 * u2; 752c4762a1bSJed Brown njac21 = -two * u1 * u2; 753c4762a1bSJed Brown njac22 = -one - u1 * u1 + u2 * u2; 754c4762a1bSJed Brown det = njac11 * njac22 - njac21 * njac12; 755c4762a1bSJed Brown u1 = u1 - (njac22 * nf1 - njac12 * nf2) / det; 756c4762a1bSJed Brown u2 = u2 - (njac11 * nf2 - njac21 * nf1) / det; 757c4762a1bSJed Brown } 758c4762a1bSJed Brown 759c4762a1bSJed Brown boundary[i] = u1 * u1 - u2 * u2; 760c4762a1bSJed Brown if (j == 0 || j == 1) { 761c4762a1bSJed Brown xt = xt + hx; 762c4762a1bSJed Brown } else { /* if (j==2 || j==3) */ 763c4762a1bSJed Brown yt = yt + hy; 764c4762a1bSJed Brown } 765c4762a1bSJed Brown } 766c4762a1bSJed Brown } 767c4762a1bSJed Brown 768c4762a1bSJed Brown /* Scale the boundary if desired */ 769c4762a1bSJed Brown if (1 == 1) { 770c4762a1bSJed Brown PetscReal scl = 1.0; 771c4762a1bSJed Brown 7729566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(NULL, NULL, "-bottom", &scl, &flg)); 773c4762a1bSJed Brown if (flg) { 774c4762a1bSJed Brown for (i = 0; i < bsize; i++) user->bottom[i] *= scl; 775c4762a1bSJed Brown } 776c4762a1bSJed Brown 7779566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(NULL, NULL, "-top", &scl, &flg)); 778c4762a1bSJed Brown if (flg) { 779c4762a1bSJed Brown for (i = 0; i < tsize; i++) user->top[i] *= scl; 780c4762a1bSJed Brown } 781c4762a1bSJed Brown 7829566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(NULL, NULL, "-right", &scl, &flg)); 783c4762a1bSJed Brown if (flg) { 784c4762a1bSJed Brown for (i = 0; i < rsize; i++) user->right[i] *= scl; 785c4762a1bSJed Brown } 786c4762a1bSJed Brown 7879566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(NULL, NULL, "-left", &scl, &flg)); 788c4762a1bSJed Brown if (flg) { 789c4762a1bSJed Brown for (i = 0; i < lsize; i++) user->left[i] *= scl; 790c4762a1bSJed Brown } 791c4762a1bSJed Brown } 7923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 793c4762a1bSJed Brown } 794c4762a1bSJed Brown 795c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 796c4762a1bSJed Brown /* 797c4762a1bSJed Brown MSA_InitialPoint - Calculates the initial guess in one of three ways. 798c4762a1bSJed Brown 799c4762a1bSJed Brown Input Parameters: 800c4762a1bSJed Brown . user - user-defined application context 801c4762a1bSJed Brown . X - vector for initial guess 802c4762a1bSJed Brown 803c4762a1bSJed Brown Output Parameters: 804c4762a1bSJed Brown . X - newly computed initial guess 805c4762a1bSJed Brown */ 806d71ae5a4SJacob Faibussowitsch static PetscErrorCode MSA_InitialPoint(AppCtx *user, Vec X) 807d71ae5a4SJacob Faibussowitsch { 808c4762a1bSJed Brown PetscInt start2 = -1, i, j; 809c4762a1bSJed Brown PetscReal start1 = 0; 810c4762a1bSJed Brown PetscBool flg1, flg2; 811c4762a1bSJed Brown 812c4762a1bSJed Brown PetscFunctionBegin; 8139566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(NULL, NULL, "-start", &start1, &flg1)); 8149566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-random", &start2, &flg2)); 815c4762a1bSJed Brown 816c4762a1bSJed Brown if (flg1) { /* The zero vector is reasonable */ 8179566063dSJacob Faibussowitsch PetscCall(VecSet(X, start1)); 818c4762a1bSJed Brown } else if (flg2 && start2 > 0) { /* Try a random start between -0.5 and 0.5 */ 8199371c9d4SSatish Balay PetscRandom rctx; 8209371c9d4SSatish Balay PetscReal np5 = -0.5; 821c4762a1bSJed Brown 8229566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PETSC_COMM_WORLD, &rctx)); 8239566063dSJacob Faibussowitsch PetscCall(VecSetRandom(X, rctx)); 8249566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&rctx)); 8259566063dSJacob Faibussowitsch PetscCall(VecShift(X, np5)); 826c4762a1bSJed Brown } else { /* Take an average of the boundary conditions */ 827c4762a1bSJed Brown PetscInt xs, xm, ys, ym; 828c4762a1bSJed Brown PetscInt mx = user->mx, my = user->my; 829c4762a1bSJed Brown PetscReal **x; 830c4762a1bSJed Brown 831c4762a1bSJed Brown /* Get local mesh boundaries */ 8329566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(user->dm, &xs, &ys, NULL, &xm, &ym, NULL)); 833c4762a1bSJed Brown 834c4762a1bSJed Brown /* Get pointers to vector data */ 8359566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(user->dm, X, (void **)&x)); 836c4762a1bSJed Brown 837c4762a1bSJed Brown /* Perform local computations */ 838c4762a1bSJed Brown for (j = ys; j < ys + ym; j++) { 839ad540459SPierre Jolivet for (i = xs; i < xs + xm; i++) x[j][i] = (((j + 1) * user->bottom[i - xs + 1] + (my - j + 1) * user->top[i - xs + 1]) / (my + 2) + ((i + 1) * user->left[j - ys + 1] + (mx - i + 1) * user->right[j - ys + 1]) / (mx + 2)) / 2.0; 840c4762a1bSJed Brown } 8419566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(user->dm, X, (void **)&x)); 8429566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(9.0 * xm * ym)); 843c4762a1bSJed Brown } 8443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 845c4762a1bSJed Brown } 846c4762a1bSJed Brown 847c4762a1bSJed Brown /*-----------------------------------------------------------------------*/ 848d71ae5a4SJacob Faibussowitsch PetscErrorCode My_Monitor(Tao tao, void *ctx) 849d71ae5a4SJacob Faibussowitsch { 850c4762a1bSJed Brown Vec X; 851c4762a1bSJed Brown 852c4762a1bSJed Brown PetscFunctionBegin; 8539566063dSJacob Faibussowitsch PetscCall(TaoGetSolution(tao, &X)); 8549566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 8553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 856c4762a1bSJed Brown } 857c4762a1bSJed Brown 858c4762a1bSJed Brown /*TEST 859c4762a1bSJed Brown 860c4762a1bSJed Brown build: 861c4762a1bSJed Brown requires: !complex 862c4762a1bSJed Brown 863c4762a1bSJed Brown test: 864*9f1eecfaSStefano Zampini args: -tao_smonitor -tao_type lmvm -da_grid_x 10 -da_grid_y 8 -tao_gatol 1.e-3 865c4762a1bSJed Brown requires: !single 866c4762a1bSJed Brown 867c4762a1bSJed Brown test: 868c4762a1bSJed Brown suffix: 2 869c4762a1bSJed Brown nsize: 2 870c4762a1bSJed Brown args: -tao_smonitor -tao_type nls -tao_nls_ksp_max_it 15 -tao_gatol 1.e-4 871c4762a1bSJed Brown filter: grep -v "nls ksp" 872c4762a1bSJed Brown requires: !single 873c4762a1bSJed Brown 874c4762a1bSJed Brown test: 8754936d809SStefano Zampini suffix: 2_snes 8764936d809SStefano Zampini nsize: 2 8774936d809SStefano Zampini args: -tao_smonitor -tao_type snes -ksp_converged_maxits -ksp_max_it 15 -snes_atol 1.e-4 8784936d809SStefano Zampini filter: grep -v "nls ksp" 8794936d809SStefano Zampini requires: !single 8804936d809SStefano Zampini 8814936d809SStefano Zampini test: 882c4762a1bSJed Brown suffix: 3 883c4762a1bSJed Brown nsize: 3 884*9f1eecfaSStefano Zampini args: -tao_smonitor -tao_type cg -tao_cg_type fr -da_grid_x 10 -da_grid_y 10 -tao_gatol 1.e-3 885c4762a1bSJed Brown requires: !single 886c4762a1bSJed Brown 887c4762a1bSJed Brown test: 8884936d809SStefano Zampini suffix: 3_snes 8894936d809SStefano Zampini nsize: 3 890*9f1eecfaSStefano Zampini args: -tao_smonitor -tao_type snes -snes_type ncg -snes_ncg_type fr -da_grid_x 10 -da_grid_y 10 -snes_atol 1.e-4 8914936d809SStefano Zampini requires: !single 8924936d809SStefano Zampini 8934936d809SStefano Zampini test: 8944936d809SStefano Zampini suffix: 4_snes_ngmres 895*9f1eecfaSStefano Zampini args: -tao_type snes -snes_type ngmres -npc_snes_type ncg -da_grid_x 10 -da_grid_y 10 -snes_atol 1.e-4 -npc_snes_ncg_type fr -snes_converged_reason -snes_monitor ::ascii_info_detail -snes_ngmres_monitor -snes_ngmres_select_type {{linesearch difference}separate output} 8964936d809SStefano Zampini requires: !single 8974936d809SStefano Zampini 8984936d809SStefano Zampini test: 899c4762a1bSJed Brown suffix: 5 900c4762a1bSJed Brown nsize: 2 901*9f1eecfaSStefano Zampini args: -tao_smonitor -tao_type bmrm -da_grid_x 10 -da_grid_y 8 -tao_gatol 1.e-3 902c4762a1bSJed Brown requires: !single 903c4762a1bSJed Brown 904c4762a1bSJed Brown TEST*/ 905