xref: /petsc/src/snes/tutorials/ex28.c (revision 4e8208cbcbc709572b8abe32f33c78b69c819375)
1c4762a1bSJed Brown static const char help[] = "1D multiphysics prototype with analytic Jacobians to solve individual problems and a coupled problem.\n\n";
2c4762a1bSJed Brown 
3c4762a1bSJed Brown /* Solve a PDE coupled to an algebraic system in 1D
4c4762a1bSJed Brown  *
5c4762a1bSJed Brown  * PDE (U):
6c4762a1bSJed Brown  *     -(k u_x)_x = 1 on (0,1), subject to u(0) = 0, u(1) = 1
7c4762a1bSJed Brown  * Algebraic (K):
8c4762a1bSJed Brown  *     exp(k-1) + k = 1/(1/(1+u) + 1/(1+u_x^2))
9c4762a1bSJed Brown  *
10c4762a1bSJed Brown  * The discretization places k at staggered points, and a separate DMDA is used for each "physics".
11c4762a1bSJed Brown  *
12c4762a1bSJed Brown  * This example is a prototype for coupling in multi-physics problems, therefore residual evaluation and assembly for
13c4762a1bSJed Brown  * each problem (referred to as U and K) are written separately.  This permits the same "physics" code to be used for
14c4762a1bSJed Brown  * solving each uncoupled problem as well as the coupled system.  In particular, run with -problem_type 0 to solve only
15c4762a1bSJed Brown  * problem U (with K fixed), -problem_type 1 to solve only K (with U fixed), and -problem_type 2 to solve both at once.
16c4762a1bSJed Brown  *
17c4762a1bSJed Brown  * In all cases, a fully-assembled analytic Jacobian is available, so the systems can be solved with a direct solve or
18c4762a1bSJed Brown  * any other standard method.  Additionally, by running with
19c4762a1bSJed Brown  *
20c4762a1bSJed Brown  *   -pack_dm_mat_type nest
21c4762a1bSJed Brown  *
22c4762a1bSJed Brown  * The same code assembles a coupled matrix where each block is stored separately, which allows the use of PCFieldSplit
23c4762a1bSJed Brown  * without copying values to extract submatrices.
24c4762a1bSJed Brown  */
25c4762a1bSJed Brown 
26c4762a1bSJed Brown #include <petscsnes.h>
27c4762a1bSJed Brown #include <petscdm.h>
28c4762a1bSJed Brown #include <petscdmda.h>
29c4762a1bSJed Brown #include <petscdmcomposite.h>
30c4762a1bSJed Brown 
31c4762a1bSJed Brown typedef struct _UserCtx *User;
32c4762a1bSJed Brown struct _UserCtx {
33c4762a1bSJed Brown   PetscInt ptype;
34c4762a1bSJed Brown   DM       pack;
35c4762a1bSJed Brown   Vec      Uloc, Kloc;
36c4762a1bSJed Brown };
37c4762a1bSJed Brown 
FormFunctionLocal_U(User user,DMDALocalInfo * info,const PetscScalar u[],const PetscScalar k[],PetscScalar f[])38d71ae5a4SJacob Faibussowitsch static PetscErrorCode FormFunctionLocal_U(User user, DMDALocalInfo *info, const PetscScalar u[], const PetscScalar k[], PetscScalar f[])
39d71ae5a4SJacob Faibussowitsch {
40c4762a1bSJed Brown   PetscReal hx = 1. / info->mx;
41c4762a1bSJed Brown   PetscInt  i;
42c4762a1bSJed Brown 
43c4762a1bSJed Brown   PetscFunctionBeginUser;
44c4762a1bSJed Brown   for (i = info->xs; i < info->xs + info->xm; i++) {
45c4762a1bSJed Brown     if (i == 0) f[i] = 1. / hx * u[i];
46c4762a1bSJed Brown     else if (i == info->mx - 1) f[i] = 1. / hx * (u[i] - 1.0);
47c4762a1bSJed Brown     else f[i] = hx * ((k[i - 1] * (u[i] - u[i - 1]) - k[i] * (u[i + 1] - u[i])) / (hx * hx) - 1.0);
48c4762a1bSJed Brown   }
493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50c4762a1bSJed Brown }
51c4762a1bSJed Brown 
FormFunctionLocal_K(User user,DMDALocalInfo * info,const PetscScalar u[],const PetscScalar k[],PetscScalar f[])52d71ae5a4SJacob Faibussowitsch static PetscErrorCode FormFunctionLocal_K(User user, DMDALocalInfo *info, const PetscScalar u[], const PetscScalar k[], PetscScalar f[])
53d71ae5a4SJacob Faibussowitsch {
54c4762a1bSJed Brown   PetscReal hx = 1. / info->mx;
55c4762a1bSJed Brown   PetscInt  i;
56c4762a1bSJed Brown 
57c4762a1bSJed Brown   PetscFunctionBeginUser;
58c4762a1bSJed Brown   for (i = info->xs; i < info->xs + info->xm; i++) {
599371c9d4SSatish Balay     const PetscScalar ubar = 0.5 * (u[i + 1] + u[i]), gradu = (u[i + 1] - u[i]) / hx, g = 1. + gradu * gradu, w = 1. / (1. + ubar) + 1. / g;
60c4762a1bSJed Brown     f[i] = hx * (PetscExpScalar(k[i] - 1.0) + k[i] - 1. / w);
61c4762a1bSJed Brown   }
623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
63c4762a1bSJed Brown }
64c4762a1bSJed Brown 
FormFunction_All(SNES snes,Vec X,Vec F,PetscCtx ctx)65*2a8381b2SBarry Smith static PetscErrorCode FormFunction_All(SNES snes, Vec X, Vec F, PetscCtx ctx)
66d71ae5a4SJacob Faibussowitsch {
67c4762a1bSJed Brown   User          user = (User)ctx;
68c4762a1bSJed Brown   DM            dau, dak;
69c4762a1bSJed Brown   DMDALocalInfo infou, infok;
70c4762a1bSJed Brown   PetscScalar  *u, *k;
71c4762a1bSJed Brown   PetscScalar  *fu, *fk;
72c4762a1bSJed Brown   Vec           Uloc, Kloc, Fu, Fk;
73c4762a1bSJed Brown 
74c4762a1bSJed Brown   PetscFunctionBeginUser;
759566063dSJacob Faibussowitsch   PetscCall(DMCompositeGetEntries(user->pack, &dau, &dak));
769566063dSJacob Faibussowitsch   PetscCall(DMDAGetLocalInfo(dau, &infou));
779566063dSJacob Faibussowitsch   PetscCall(DMDAGetLocalInfo(dak, &infok));
789566063dSJacob Faibussowitsch   PetscCall(DMCompositeGetLocalVectors(user->pack, &Uloc, &Kloc));
79c4762a1bSJed Brown   switch (user->ptype) {
80c4762a1bSJed Brown   case 0:
819566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dau, X, INSERT_VALUES, Uloc));
829566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dau, X, INSERT_VALUES, Uloc));
839566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(dau, Uloc, &u));
849566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(dak, user->Kloc, &k));
859566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(dau, F, &fu));
869566063dSJacob Faibussowitsch     PetscCall(FormFunctionLocal_U(user, &infou, u, k, fu));
879566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(dau, F, &fu));
889566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(dau, Uloc, &u));
899566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(dak, user->Kloc, &k));
90c4762a1bSJed Brown     break;
91c4762a1bSJed Brown   case 1:
929566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dak, X, INSERT_VALUES, Kloc));
939566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dak, X, INSERT_VALUES, Kloc));
949566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(dau, user->Uloc, &u));
959566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(dak, Kloc, &k));
969566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(dak, F, &fk));
979566063dSJacob Faibussowitsch     PetscCall(FormFunctionLocal_K(user, &infok, u, k, fk));
989566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(dak, F, &fk));
999566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(dau, user->Uloc, &u));
1009566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(dak, Kloc, &k));
101c4762a1bSJed Brown     break;
102c4762a1bSJed Brown   case 2:
1039566063dSJacob Faibussowitsch     PetscCall(DMCompositeScatter(user->pack, X, Uloc, Kloc));
1049566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(dau, Uloc, &u));
1059566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(dak, Kloc, &k));
1069566063dSJacob Faibussowitsch     PetscCall(DMCompositeGetAccess(user->pack, F, &Fu, &Fk));
1079566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(dau, Fu, &fu));
1089566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(dak, Fk, &fk));
1099566063dSJacob Faibussowitsch     PetscCall(FormFunctionLocal_U(user, &infou, u, k, fu));
1109566063dSJacob Faibussowitsch     PetscCall(FormFunctionLocal_K(user, &infok, u, k, fk));
1119566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(dau, Fu, &fu));
1129566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(dak, Fk, &fk));
1139566063dSJacob Faibussowitsch     PetscCall(DMCompositeRestoreAccess(user->pack, F, &Fu, &Fk));
1149566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(dau, Uloc, &u));
1159566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(dak, Kloc, &k));
116c4762a1bSJed Brown     break;
117c4762a1bSJed Brown   }
1189566063dSJacob Faibussowitsch   PetscCall(DMCompositeRestoreLocalVectors(user->pack, &Uloc, &Kloc));
1193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
120c4762a1bSJed Brown }
121c4762a1bSJed Brown 
FormJacobianLocal_U(User user,DMDALocalInfo * info,const PetscScalar u[],const PetscScalar k[],Mat Buu)122d71ae5a4SJacob Faibussowitsch static PetscErrorCode FormJacobianLocal_U(User user, DMDALocalInfo *info, const PetscScalar u[], const PetscScalar k[], Mat Buu)
123d71ae5a4SJacob Faibussowitsch {
124c4762a1bSJed Brown   PetscReal hx = 1. / info->mx;
125c4762a1bSJed Brown   PetscInt  i;
126c4762a1bSJed Brown 
127c4762a1bSJed Brown   PetscFunctionBeginUser;
128c4762a1bSJed Brown   for (i = info->xs; i < info->xs + info->xm; i++) {
129c4762a1bSJed Brown     PetscInt    row = i - info->gxs, cols[] = {row - 1, row, row + 1};
130c4762a1bSJed Brown     PetscScalar val = 1. / hx;
131c4762a1bSJed Brown     if (i == 0) {
1329566063dSJacob Faibussowitsch       PetscCall(MatSetValuesLocal(Buu, 1, &row, 1, &row, &val, INSERT_VALUES));
133c4762a1bSJed Brown     } else if (i == info->mx - 1) {
1349566063dSJacob Faibussowitsch       PetscCall(MatSetValuesLocal(Buu, 1, &row, 1, &row, &val, INSERT_VALUES));
135c4762a1bSJed Brown     } else {
136c4762a1bSJed Brown       PetscScalar vals[] = {-k[i - 1] / hx, (k[i - 1] + k[i]) / hx, -k[i] / hx};
1379566063dSJacob Faibussowitsch       PetscCall(MatSetValuesLocal(Buu, 1, &row, 3, cols, vals, INSERT_VALUES));
138c4762a1bSJed Brown     }
139c4762a1bSJed Brown   }
1403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
141c4762a1bSJed Brown }
142c4762a1bSJed Brown 
FormJacobianLocal_K(User user,DMDALocalInfo * info,const PetscScalar u[],const PetscScalar k[],Mat Bkk)143d71ae5a4SJacob Faibussowitsch static PetscErrorCode FormJacobianLocal_K(User user, DMDALocalInfo *info, const PetscScalar u[], const PetscScalar k[], Mat Bkk)
144d71ae5a4SJacob Faibussowitsch {
145c4762a1bSJed Brown   PetscReal hx = 1. / info->mx;
146c4762a1bSJed Brown   PetscInt  i;
147c4762a1bSJed Brown 
148c4762a1bSJed Brown   PetscFunctionBeginUser;
149c4762a1bSJed Brown   for (i = info->xs; i < info->xs + info->xm; i++) {
150c4762a1bSJed Brown     PetscInt    row    = i - info->gxs;
151c4762a1bSJed Brown     PetscScalar vals[] = {hx * (PetscExpScalar(k[i] - 1.) + (PetscScalar)1.)};
1529566063dSJacob Faibussowitsch     PetscCall(MatSetValuesLocal(Bkk, 1, &row, 1, &row, vals, INSERT_VALUES));
153c4762a1bSJed Brown   }
1543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
155c4762a1bSJed Brown }
156c4762a1bSJed Brown 
FormJacobianLocal_UK(User user,DMDALocalInfo * info,DMDALocalInfo * infok,const PetscScalar u[],const PetscScalar k[],Mat Buk)157d71ae5a4SJacob Faibussowitsch static PetscErrorCode FormJacobianLocal_UK(User user, DMDALocalInfo *info, DMDALocalInfo *infok, const PetscScalar u[], const PetscScalar k[], Mat Buk)
158d71ae5a4SJacob Faibussowitsch {
159c4762a1bSJed Brown   PetscReal   hx = 1. / info->mx;
160c4762a1bSJed Brown   PetscInt    i;
161c4762a1bSJed Brown   PetscInt    row, cols[2];
162c4762a1bSJed Brown   PetscScalar vals[2];
163c4762a1bSJed Brown 
164c4762a1bSJed Brown   PetscFunctionBeginUser;
1653ba16761SJacob Faibussowitsch   if (!Buk) PetscFunctionReturn(PETSC_SUCCESS); /* Not assembling this block */
166c4762a1bSJed Brown   for (i = info->xs; i < info->xs + info->xm; i++) {
167c4762a1bSJed Brown     if (i == 0 || i == info->mx - 1) continue;
168c4762a1bSJed Brown     row     = i - info->gxs;
1699371c9d4SSatish Balay     cols[0] = i - 1 - infok->gxs;
1709371c9d4SSatish Balay     vals[0] = (u[i] - u[i - 1]) / hx;
1719371c9d4SSatish Balay     cols[1] = i - infok->gxs;
1729371c9d4SSatish Balay     vals[1] = (u[i] - u[i + 1]) / hx;
1739566063dSJacob Faibussowitsch     PetscCall(MatSetValuesLocal(Buk, 1, &row, 2, cols, vals, INSERT_VALUES));
174c4762a1bSJed Brown   }
1753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
176c4762a1bSJed Brown }
177c4762a1bSJed Brown 
FormJacobianLocal_KU(User user,DMDALocalInfo * info,DMDALocalInfo * infok,const PetscScalar u[],const PetscScalar k[],Mat Bku)178d71ae5a4SJacob Faibussowitsch static PetscErrorCode FormJacobianLocal_KU(User user, DMDALocalInfo *info, DMDALocalInfo *infok, const PetscScalar u[], const PetscScalar k[], Mat Bku)
179d71ae5a4SJacob Faibussowitsch {
180c4762a1bSJed Brown   PetscInt  i;
181c4762a1bSJed Brown   PetscReal hx = 1. / (info->mx - 1);
182c4762a1bSJed Brown 
183c4762a1bSJed Brown   PetscFunctionBeginUser;
1843ba16761SJacob Faibussowitsch   if (!Bku) PetscFunctionReturn(PETSC_SUCCESS); /* Not assembling this block */
185c4762a1bSJed Brown   for (i = infok->xs; i < infok->xs + infok->xm; i++) {
186c4762a1bSJed Brown     PetscInt    row = i - infok->gxs, cols[2];
187c4762a1bSJed Brown     PetscScalar vals[2];
1889371c9d4SSatish Balay     const PetscScalar ubar = 0.5 * (u[i] + u[i + 1]), ubar_L = 0.5, ubar_R = 0.5, gradu = (u[i + 1] - u[i]) / hx, gradu_L = -1. / hx, gradu_R = 1. / hx, g = 1. + PetscSqr(gradu), g_gradu = 2. * gradu, w = 1. / (1. + ubar) + 1. / g, w_ubar = -1. / PetscSqr(1. + ubar), w_gradu = -g_gradu / PetscSqr(g), iw = 1. / w, iw_ubar = -w_ubar * PetscSqr(iw), iw_gradu = -w_gradu * PetscSqr(iw);
1899371c9d4SSatish Balay     cols[0] = i - info->gxs;
1909371c9d4SSatish Balay     vals[0] = -hx * (iw_ubar * ubar_L + iw_gradu * gradu_L);
1919371c9d4SSatish Balay     cols[1] = i + 1 - info->gxs;
1929371c9d4SSatish Balay     vals[1] = -hx * (iw_ubar * ubar_R + iw_gradu * gradu_R);
1939566063dSJacob Faibussowitsch     PetscCall(MatSetValuesLocal(Bku, 1, &row, 2, cols, vals, INSERT_VALUES));
194c4762a1bSJed Brown   }
1953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
196c4762a1bSJed Brown }
197c4762a1bSJed Brown 
FormJacobian_All(SNES snes,Vec X,Mat J,Mat B,PetscCtx ctx)198*2a8381b2SBarry Smith static PetscErrorCode FormJacobian_All(SNES snes, Vec X, Mat J, Mat B, PetscCtx ctx)
199d71ae5a4SJacob Faibussowitsch {
200c4762a1bSJed Brown   User          user = (User)ctx;
201c4762a1bSJed Brown   DM            dau, dak;
202c4762a1bSJed Brown   DMDALocalInfo infou, infok;
203c4762a1bSJed Brown   PetscScalar  *u, *k;
204c4762a1bSJed Brown   Vec           Uloc, Kloc;
205c4762a1bSJed Brown 
206c4762a1bSJed Brown   PetscFunctionBeginUser;
2079566063dSJacob Faibussowitsch   PetscCall(DMCompositeGetEntries(user->pack, &dau, &dak));
2089566063dSJacob Faibussowitsch   PetscCall(DMDAGetLocalInfo(dau, &infou));
2099566063dSJacob Faibussowitsch   PetscCall(DMDAGetLocalInfo(dak, &infok));
2109566063dSJacob Faibussowitsch   PetscCall(DMCompositeGetLocalVectors(user->pack, &Uloc, &Kloc));
211c4762a1bSJed Brown   switch (user->ptype) {
212c4762a1bSJed Brown   case 0:
2139566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dau, X, INSERT_VALUES, Uloc));
2149566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dau, X, INSERT_VALUES, Uloc));
2159566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(dau, Uloc, &u));
2169566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(dak, user->Kloc, &k));
2179566063dSJacob Faibussowitsch     PetscCall(FormJacobianLocal_U(user, &infou, u, k, B));
2189566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(dau, Uloc, &u));
2199566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(dak, user->Kloc, &k));
220c4762a1bSJed Brown     break;
221c4762a1bSJed Brown   case 1:
2229566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dak, X, INSERT_VALUES, Kloc));
2239566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dak, X, INSERT_VALUES, Kloc));
2249566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(dau, user->Uloc, &u));
2259566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(dak, Kloc, &k));
2269566063dSJacob Faibussowitsch     PetscCall(FormJacobianLocal_K(user, &infok, u, k, B));
2279566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(dau, user->Uloc, &u));
2289566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(dak, Kloc, &k));
229c4762a1bSJed Brown     break;
230c4762a1bSJed Brown   case 2: {
231c4762a1bSJed Brown     Mat       Buu, Buk, Bku, Bkk;
232c4762a1bSJed Brown     PetscBool nest;
233c4762a1bSJed Brown     IS       *is;
2349566063dSJacob Faibussowitsch     PetscCall(DMCompositeScatter(user->pack, X, Uloc, Kloc));
2359566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(dau, Uloc, &u));
2369566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(dak, Kloc, &k));
2379566063dSJacob Faibussowitsch     PetscCall(DMCompositeGetLocalISs(user->pack, &is));
2389566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSubMatrix(B, is[0], is[0], &Buu));
2399566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSubMatrix(B, is[0], is[1], &Buk));
2409566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSubMatrix(B, is[1], is[0], &Bku));
2419566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSubMatrix(B, is[1], is[1], &Bkk));
2429566063dSJacob Faibussowitsch     PetscCall(FormJacobianLocal_U(user, &infou, u, k, Buu));
2439566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, MATNEST, &nest));
244c4762a1bSJed Brown     if (!nest) {
245c4762a1bSJed Brown       /*
246c4762a1bSJed Brown          DMCreateMatrix_Composite()  for a nested matrix does not generate off-block matrices that one can call MatSetValuesLocal() on, it just creates dummy
247c4762a1bSJed Brown          matrices with no entries; there cannot insert values into them. Commit b6480e041dd2293a65f96222772d68cdb4ed6306
248c4762a1bSJed Brown          changed Mat_Nest() from returning NULL pointers for these submatrices to dummy matrices because PCFIELDSPLIT could not
249c4762a1bSJed Brown          handle the returned null matrices.
250c4762a1bSJed Brown       */
2519566063dSJacob Faibussowitsch       PetscCall(FormJacobianLocal_UK(user, &infou, &infok, u, k, Buk));
2529566063dSJacob Faibussowitsch       PetscCall(FormJacobianLocal_KU(user, &infou, &infok, u, k, Bku));
253c4762a1bSJed Brown     }
2549566063dSJacob Faibussowitsch     PetscCall(FormJacobianLocal_K(user, &infok, u, k, Bkk));
2559566063dSJacob Faibussowitsch     PetscCall(MatRestoreLocalSubMatrix(B, is[0], is[0], &Buu));
2569566063dSJacob Faibussowitsch     PetscCall(MatRestoreLocalSubMatrix(B, is[0], is[1], &Buk));
2579566063dSJacob Faibussowitsch     PetscCall(MatRestoreLocalSubMatrix(B, is[1], is[0], &Bku));
2589566063dSJacob Faibussowitsch     PetscCall(MatRestoreLocalSubMatrix(B, is[1], is[1], &Bkk));
2599566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(dau, Uloc, &u));
2609566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(dak, Kloc, &k));
261c4762a1bSJed Brown 
2629566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is[0]));
2639566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is[1]));
2649566063dSJacob Faibussowitsch     PetscCall(PetscFree(is));
265c4762a1bSJed Brown   } break;
266c4762a1bSJed Brown   }
2679566063dSJacob Faibussowitsch   PetscCall(DMCompositeRestoreLocalVectors(user->pack, &Uloc, &Kloc));
2689566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
2699566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
270c4762a1bSJed Brown   if (J != B) {
2719566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
2729566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
273c4762a1bSJed Brown   }
2743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
275c4762a1bSJed Brown }
276c4762a1bSJed Brown 
FormInitial_Coupled(User user,Vec X)277d71ae5a4SJacob Faibussowitsch static PetscErrorCode FormInitial_Coupled(User user, Vec X)
278d71ae5a4SJacob Faibussowitsch {
279c4762a1bSJed Brown   DM            dau, dak;
280c4762a1bSJed Brown   DMDALocalInfo infou, infok;
281c4762a1bSJed Brown   Vec           Xu, Xk;
282c4762a1bSJed Brown   PetscScalar  *u, *k, hx;
283c4762a1bSJed Brown   PetscInt      i;
284c4762a1bSJed Brown 
285c4762a1bSJed Brown   PetscFunctionBeginUser;
2869566063dSJacob Faibussowitsch   PetscCall(DMCompositeGetEntries(user->pack, &dau, &dak));
2879566063dSJacob Faibussowitsch   PetscCall(DMCompositeGetAccess(user->pack, X, &Xu, &Xk));
2889566063dSJacob Faibussowitsch   PetscCall(DMDAVecGetArray(dau, Xu, &u));
2899566063dSJacob Faibussowitsch   PetscCall(DMDAVecGetArray(dak, Xk, &k));
2909566063dSJacob Faibussowitsch   PetscCall(DMDAGetLocalInfo(dau, &infou));
2919566063dSJacob Faibussowitsch   PetscCall(DMDAGetLocalInfo(dak, &infok));
292c4762a1bSJed Brown   hx = 1. / (infok.mx);
293c4762a1bSJed Brown   for (i = infou.xs; i < infou.xs + infou.xm; i++) u[i] = (PetscScalar)i * hx * (1. - (PetscScalar)i * hx);
294c4762a1bSJed Brown   for (i = infok.xs; i < infok.xs + infok.xm; i++) k[i] = 1.0 + 0.5 * PetscSinScalar(2 * PETSC_PI * i * hx);
2959566063dSJacob Faibussowitsch   PetscCall(DMDAVecRestoreArray(dau, Xu, &u));
2969566063dSJacob Faibussowitsch   PetscCall(DMDAVecRestoreArray(dak, Xk, &k));
2979566063dSJacob Faibussowitsch   PetscCall(DMCompositeRestoreAccess(user->pack, X, &Xu, &Xk));
2989566063dSJacob Faibussowitsch   PetscCall(DMCompositeScatter(user->pack, X, user->Uloc, user->Kloc));
2993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
300c4762a1bSJed Brown }
301c4762a1bSJed Brown 
main(int argc,char * argv[])302d71ae5a4SJacob Faibussowitsch int main(int argc, char *argv[])
303d71ae5a4SJacob Faibussowitsch {
304c4762a1bSJed Brown   DM              dau, dak, pack;
305c4762a1bSJed Brown   const PetscInt *lxu;
306c4762a1bSJed Brown   PetscInt       *lxk, m, sizes;
307c4762a1bSJed Brown   User            user;
308c4762a1bSJed Brown   SNES            snes;
309c4762a1bSJed Brown   Vec             X, F, Xu, Xk, Fu, Fk;
310c4762a1bSJed Brown   Mat             B;
311c4762a1bSJed Brown   IS             *isg;
312c4762a1bSJed Brown   PetscBool       pass_dm;
3131afe20e5SStefano Zampini   VecType         vtype;
314c4762a1bSJed Brown 
315327415f7SBarry Smith   PetscFunctionBeginUser;
3169566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &argv, 0, help));
3179566063dSJacob Faibussowitsch   PetscCall(DMDACreate1d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, 10, 1, 1, NULL, &dau));
3189566063dSJacob Faibussowitsch   PetscCall(DMSetOptionsPrefix(dau, "u_"));
3199566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(dau));
3209566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dau));
3219566063dSJacob Faibussowitsch   PetscCall(DMDAGetOwnershipRanges(dau, &lxu, 0, 0));
3229566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(dau, 0, &m, 0, 0, &sizes, 0, 0, 0, 0, 0, 0, 0, 0));
3239566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(sizes, &lxk));
3249566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(lxk, lxu, sizes));
325c4762a1bSJed Brown   lxk[0]--;
3269566063dSJacob Faibussowitsch   PetscCall(DMDACreate1d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, m - 1, 1, 1, lxk, &dak));
3279566063dSJacob Faibussowitsch   PetscCall(DMSetOptionsPrefix(dak, "k_"));
3289566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(dak));
3299566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dak));
3309566063dSJacob Faibussowitsch   PetscCall(PetscFree(lxk));
331c4762a1bSJed Brown 
3329566063dSJacob Faibussowitsch   PetscCall(DMCompositeCreate(PETSC_COMM_WORLD, &pack));
3339566063dSJacob Faibussowitsch   PetscCall(DMSetOptionsPrefix(pack, "pack_"));
3349566063dSJacob Faibussowitsch   PetscCall(DMCompositeAddDM(pack, dau));
3359566063dSJacob Faibussowitsch   PetscCall(DMCompositeAddDM(pack, dak));
3369566063dSJacob Faibussowitsch   PetscCall(DMDASetFieldName(dau, 0, "u"));
3379566063dSJacob Faibussowitsch   PetscCall(DMDASetFieldName(dak, 0, "k"));
3389566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(pack));
339c4762a1bSJed Brown 
3401afe20e5SStefano Zampini   /* if we call -pack_dm_vec_type xxx it does not get propagated to the subDMs */
3411afe20e5SStefano Zampini   PetscCall(DMGetVecType(pack, &vtype));
3421afe20e5SStefano Zampini   PetscCall(DMSetVecType(dau, vtype));
3431afe20e5SStefano Zampini   PetscCall(DMSetVecType(dak, vtype));
3441afe20e5SStefano Zampini 
3459566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(pack, &X));
3469566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(X, &F));
347c4762a1bSJed Brown 
3489566063dSJacob Faibussowitsch   PetscCall(PetscNew(&user));
349c4762a1bSJed Brown 
350c4762a1bSJed Brown   user->pack = pack;
351c4762a1bSJed Brown 
3529566063dSJacob Faibussowitsch   PetscCall(DMCompositeGetGlobalISs(pack, &isg));
3539566063dSJacob Faibussowitsch   PetscCall(DMCompositeGetLocalVectors(pack, &user->Uloc, &user->Kloc));
3549566063dSJacob Faibussowitsch   PetscCall(DMCompositeScatter(pack, X, user->Uloc, user->Kloc));
355c4762a1bSJed Brown 
356d0609cedSBarry Smith   PetscOptionsBegin(PETSC_COMM_WORLD, NULL, "Coupled problem options", "SNES");
357c4762a1bSJed Brown   {
3589371c9d4SSatish Balay     user->ptype = 0;
3599371c9d4SSatish Balay     pass_dm     = PETSC_TRUE;
360c4762a1bSJed Brown 
3619566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-problem_type", "0: solve for u only, 1: solve for k only, 2: solve for both", 0, user->ptype, &user->ptype, NULL));
3629566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-pass_dm", "Pass the packed DM to SNES to use when determining splits and forward into splits", 0, pass_dm, &pass_dm, NULL));
363c4762a1bSJed Brown   }
364d0609cedSBarry Smith   PetscOptionsEnd();
365c4762a1bSJed Brown 
3669566063dSJacob Faibussowitsch   PetscCall(FormInitial_Coupled(user, X));
367c4762a1bSJed Brown 
3689566063dSJacob Faibussowitsch   PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes));
369c4762a1bSJed Brown   switch (user->ptype) {
370c4762a1bSJed Brown   case 0:
37110ca579bSBarry Smith     PetscCall(DMCompositeGetAccess(pack, X, &Xu, PETSC_NULLPTR));
37210ca579bSBarry Smith     PetscCall(DMCompositeGetAccess(pack, F, &Fu, PETSC_NULLPTR));
3739566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(dau, &B));
3749566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes, Fu, FormFunction_All, user));
3759566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, B, B, FormJacobian_All, user));
3769566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes));
3779566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes, dau));
3789566063dSJacob Faibussowitsch     PetscCall(SNESSolve(snes, NULL, Xu));
37910ca579bSBarry Smith     PetscCall(DMCompositeRestoreAccess(pack, X, &Xu, PETSC_NULLPTR));
38010ca579bSBarry Smith     PetscCall(DMCompositeRestoreAccess(pack, F, &Fu, PETSC_NULLPTR));
381c4762a1bSJed Brown     break;
382c4762a1bSJed Brown   case 1:
38310ca579bSBarry Smith     PetscCall(DMCompositeGetAccess(pack, X, PETSC_NULLPTR, &Xk));
38410ca579bSBarry Smith     PetscCall(DMCompositeGetAccess(pack, F, PETSC_NULLPTR, &Fk));
3859566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(dak, &B));
3869566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes, Fk, FormFunction_All, user));
3879566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, B, B, FormJacobian_All, user));
3889566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes));
3899566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes, dak));
3909566063dSJacob Faibussowitsch     PetscCall(SNESSolve(snes, NULL, Xk));
39110ca579bSBarry Smith     PetscCall(DMCompositeRestoreAccess(pack, X, PETSC_NULLPTR, &Xk));
39210ca579bSBarry Smith     PetscCall(DMCompositeRestoreAccess(pack, F, PETSC_NULLPTR, &Fk));
393c4762a1bSJed Brown     break;
394c4762a1bSJed Brown   case 2:
3959566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(pack, &B));
396c4762a1bSJed Brown     /* This example does not correctly allocate off-diagonal blocks. These options allows new nonzeros (slow). */
3979566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_FALSE));
3989566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
3999566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes, F, FormFunction_All, user));
4009566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, B, B, FormJacobian_All, user));
4019566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes));
402c4762a1bSJed Brown     if (!pass_dm) { /* Manually provide index sets and names for the splits */
403c4762a1bSJed Brown       KSP ksp;
404c4762a1bSJed Brown       PC  pc;
4059566063dSJacob Faibussowitsch       PetscCall(SNESGetKSP(snes, &ksp));
4069566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksp, &pc));
4079566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSetIS(pc, "u", isg[0]));
4089566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSetIS(pc, "k", isg[1]));
409c4762a1bSJed Brown     } else {
410c4762a1bSJed Brown       /* The same names come from the options prefix for dau and dak. This option can support geometric multigrid inside
411c4762a1bSJed Brown        * of splits, but it requires using a DM (perhaps your own implementation). */
4129566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, pack));
413c4762a1bSJed Brown     }
4149566063dSJacob Faibussowitsch     PetscCall(SNESSolve(snes, NULL, X));
415c4762a1bSJed Brown     break;
416c4762a1bSJed Brown   }
4179566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(X, NULL, "-view_sol"));
418c4762a1bSJed Brown 
419c4762a1bSJed Brown   if (0) {
420c4762a1bSJed Brown     PetscInt  col      = 0;
421c4762a1bSJed Brown     PetscBool mult_dup = PETSC_FALSE, view_dup = PETSC_FALSE;
422c4762a1bSJed Brown     Mat       D;
423c4762a1bSJed Brown     Vec       Y;
424c4762a1bSJed Brown 
4259566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetInt(NULL, 0, "-col", &col, 0));
4269566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(NULL, 0, "-mult_dup", &mult_dup, 0));
4279566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(NULL, 0, "-view_dup", &view_dup, 0));
428c4762a1bSJed Brown 
4299566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(X, &Y));
4309566063dSJacob Faibussowitsch     /* PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY)); */
4319566063dSJacob Faibussowitsch     /* PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY)); */
4329566063dSJacob Faibussowitsch     PetscCall(MatConvert(B, MATAIJ, MAT_INITIAL_MATRIX, &D));
4339566063dSJacob Faibussowitsch     PetscCall(VecZeroEntries(X));
4349566063dSJacob Faibussowitsch     PetscCall(VecSetValue(X, col, 1.0, INSERT_VALUES));
4359566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(X));
4369566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(X));
4379566063dSJacob Faibussowitsch     PetscCall(MatMult(mult_dup ? D : B, X, Y));
4389566063dSJacob Faibussowitsch     PetscCall(MatView(view_dup ? D : B, PETSC_VIEWER_STDOUT_WORLD));
4399566063dSJacob Faibussowitsch     /* PetscCall(VecView(X,PETSC_VIEWER_STDOUT_WORLD)); */
4409566063dSJacob Faibussowitsch     PetscCall(VecView(Y, PETSC_VIEWER_STDOUT_WORLD));
4419566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
4429566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&Y));
443c4762a1bSJed Brown   }
444c4762a1bSJed Brown 
4459566063dSJacob Faibussowitsch   PetscCall(DMCompositeRestoreLocalVectors(pack, &user->Uloc, &user->Kloc));
4469566063dSJacob Faibussowitsch   PetscCall(PetscFree(user));
447c4762a1bSJed Brown 
4489566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&isg[0]));
4499566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&isg[1]));
4509566063dSJacob Faibussowitsch   PetscCall(PetscFree(isg));
4519566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&X));
4529566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&F));
4539566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&B));
4549566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dau));
4559566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dak));
4569566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&pack));
4579566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes));
4589566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
459b122ec5aSJacob Faibussowitsch   return 0;
460c4762a1bSJed Brown }
461c4762a1bSJed Brown 
462c4762a1bSJed Brown /*TEST
463c4762a1bSJed Brown 
464c4762a1bSJed Brown    test:
465c4762a1bSJed Brown       suffix: 0
466c4762a1bSJed Brown       nsize: 3
467c4762a1bSJed Brown       args: -u_da_grid_x 20 -snes_converged_reason -snes_monitor_short -problem_type 0
468c4762a1bSJed Brown 
469c4762a1bSJed Brown    test:
470c4762a1bSJed Brown       suffix: 1
471c4762a1bSJed Brown       nsize: 3
472c4762a1bSJed Brown       args: -u_da_grid_x 20 -snes_converged_reason -snes_monitor_short -problem_type 1
473c4762a1bSJed Brown 
474c4762a1bSJed Brown    test:
475c4762a1bSJed Brown       suffix: 2
476c4762a1bSJed Brown       nsize: 3
477c4762a1bSJed Brown       args: -u_da_grid_x 20 -snes_converged_reason -snes_monitor_short -problem_type 2
478c4762a1bSJed Brown 
479fb3c7e2dSJunchao Zhang    testset:
480c4762a1bSJed Brown       suffix: 3
481c4762a1bSJed Brown       nsize: 3
482fb3c7e2dSJunchao Zhang       output_file: output/ex28_3.out
483fb3c7e2dSJunchao Zhang       args: -u_da_grid_x 20 -snes_converged_reason -snes_monitor_short -ksp_monitor_short -problem_type 2 -snes_mf_operator -pc_type fieldsplit -pc_fieldsplit_dm_splits -pc_fieldsplit_type additive -fieldsplit_u_ksp_type gmres -fieldsplit_k_pc_type jacobi
484fb3c7e2dSJunchao Zhang 
485fb3c7e2dSJunchao Zhang       test:
486fb3c7e2dSJunchao Zhang         suffix: std
487fb3c7e2dSJunchao Zhang         args: -pack_dm_mat_type {{aij nest}}
488fb3c7e2dSJunchao Zhang 
489fb3c7e2dSJunchao Zhang       test:
490fb3c7e2dSJunchao Zhang         suffix: cuda
491fb3c7e2dSJunchao Zhang         requires: cuda
492fb3c7e2dSJunchao Zhang         args: -pack_dm_mat_type aijcusparse -pack_dm_vec_type cuda
493fb3c7e2dSJunchao Zhang 
494fb3c7e2dSJunchao Zhang       test:
495fb3c7e2dSJunchao Zhang         suffix: hip
496fb3c7e2dSJunchao Zhang         requires: hip
497fb3c7e2dSJunchao Zhang         args: -pack_dm_mat_type aijhipsparse -pack_dm_vec_type hip
498fb3c7e2dSJunchao Zhang 
499fb3c7e2dSJunchao Zhang       test:
500fb3c7e2dSJunchao Zhang         suffix: kok
501fb3c7e2dSJunchao Zhang         requires: kokkos_kernels
502fb3c7e2dSJunchao Zhang         args: -pack_dm_mat_type aijkokkos -pack_dm_vec_type kokkos
503c4762a1bSJed Brown 
504c4762a1bSJed Brown    test:
50562671d91SStefano Zampini       requires: mumps
50662671d91SStefano Zampini       suffix: 3_nest_lu
50750c845baSStefano Zampini       nsize: {{1 3}}
50862671d91SStefano Zampini       output_file: output/ex28_3.out
50962671d91SStefano Zampini       args: -pack_dm_mat_type nest -u_da_grid_x 20 -snes_converged_reason -snes_monitor_short -ksp_monitor_short -problem_type 2 -snes_mf_operator -pc_type lu -pc_factor_mat_solver_type mumps
51062671d91SStefano Zampini 
51162671d91SStefano Zampini    test:
512c4762a1bSJed Brown       suffix: 4
513c4762a1bSJed Brown       nsize: 6
514c4762a1bSJed Brown       args: -u_da_grid_x 257 -snes_converged_reason -snes_monitor_short -ksp_monitor_short -problem_type 2 -snes_mf_operator -pack_dm_mat_type aij -pc_type fieldsplit -pc_fieldsplit_type multiplicative -fieldsplit_u_ksp_type gmres -fieldsplit_u_ksp_pc_side right -fieldsplit_u_pc_type mg -fieldsplit_u_pc_mg_levels 4 -fieldsplit_u_mg_levels_ksp_type richardson -fieldsplit_u_mg_levels_ksp_max_it 1 -fieldsplit_u_mg_levels_pc_type sor -fieldsplit_u_pc_mg_galerkin pmat -fieldsplit_u_ksp_converged_reason -fieldsplit_k_pc_type jacobi
515c4762a1bSJed Brown       requires: !single
516c4762a1bSJed Brown 
517c4762a1bSJed Brown    test:
518c4762a1bSJed Brown       suffix: glvis_composite_da_1d
519c4762a1bSJed Brown       args: -u_da_grid_x 20 -problem_type 0 -snes_monitor_solution glvis:
520c4762a1bSJed Brown 
52105ec3129SRichard Tran Mills    test:
52205ec3129SRichard Tran Mills       suffix: cuda
52305ec3129SRichard Tran Mills       nsize: 1
52405ec3129SRichard Tran Mills       requires: cuda
52505ec3129SRichard Tran Mills       args: -u_da_grid_x 20 -snes_converged_reason -snes_monitor_short -problem_type 2 -pack_dm_mat_type aijcusparse -pack_dm_vec_type cuda
52605ec3129SRichard Tran Mills 
52705ec3129SRichard Tran Mills    test:
52805ec3129SRichard Tran Mills       suffix: viennacl
52905ec3129SRichard Tran Mills       nsize: 1
53005ec3129SRichard Tran Mills       requires: viennacl
53105ec3129SRichard Tran Mills       args: -u_da_grid_x 20 -snes_converged_reason -snes_monitor_short -problem_type 2 -pack_dm_mat_type aijviennacl -pack_dm_vec_type viennacl
53205ec3129SRichard Tran Mills 
533c4762a1bSJed Brown TEST*/
534