xref: /petsc/src/tao/constrained/tutorials/ex1.c (revision 647d62bacb8391928cd2e1fd4b5c8cb238cecf4c)
1 /* Program usage: mpiexec -n 2 ./ex1 [-help] [all TAO options] */
2 
3 /* ----------------------------------------------------------------------
4 min f(x) = (x0 - 2)^2 + (x1 - 2)^2 - 2*(x0 + x1)
5 s.t.  x0^2 + x1 - 2 = 0
6       0  <= x0^2 - x1 <= 1
7       -1 <= x0, x1 <= 2
8 -->
9       g(x)  = 0
10       h(x) >= 0
11       -1 <= x0, x1 <= 2
12 where
13       g(x) = x0^2 + x1 - 2
14       h(x) = [x0^2 - x1
15               1 -(x0^2 - x1)]
16 ---------------------------------------------------------------------- */
17 
18 #include <petsctao.h>
19 
20 static  char help[]= "Solves constrained optimiztion problem using pdipm.\n\
21 Input parameters include:\n\
22   -tao_type pdipm    : sets Tao solver\n\
23   -no_eq             : removes the equaility constraints from the problem\n\
24   -snes_fd           : snes with finite difference Jacobian (needed for pdipm)\n\
25   -snes_compare_explicit : compare user Jacobian with finite difference Jacobian \n\
26   -tao_cmonitor      : convergence monitor with constraint norm \n\
27   -tao_view_solution : view exact solution at each itteration\n\
28   Note: external package MUMPS is required to run pdipm. This is designed for a maximum of 2 processors, the code will error if size > 2.\n";
29 
30 /*
31    User-defined application context - contains data needed by the application
32 */
33 typedef struct {
34   PetscInt   n;  /* Global length of x */
35   PetscInt   ne; /* Global number of equality constraints */
36   PetscInt   ni; /* Global number of inequality constraints */
37   PetscBool  noeqflag;
38   Vec        x,xl,xu;
39   Vec        ce,ci,bl,bu,Xseq;
40   Mat        Ae,Ai,H;
41   VecScatter scat;
42 } AppCtx;
43 
44 /* -------- User-defined Routines --------- */
45 PetscErrorCode InitializeProblem(AppCtx *);
46 PetscErrorCode DestroyProblem(AppCtx *);
47 PetscErrorCode FormFunctionGradient(Tao,Vec,PetscReal *,Vec,void *);
48 PetscErrorCode FormHessian(Tao,Vec,Mat,Mat, void*);
49 PetscErrorCode FormInequalityConstraints(Tao,Vec,Vec,void*);
50 PetscErrorCode FormEqualityConstraints(Tao,Vec,Vec,void*);
51 PetscErrorCode FormInequalityJacobian(Tao,Vec,Mat,Mat, void*);
52 PetscErrorCode FormEqualityJacobian(Tao,Vec,Mat,Mat, void*);
53 
54 PetscErrorCode main(int argc,char **argv)
55 {
56   PetscErrorCode ierr;  /* used to check for functions returning nonzeros */
57   Tao            tao;
58   KSP            ksp;
59   PC             pc;
60   AppCtx         user;  /* application context */
61   Vec            x;
62   PetscMPIInt    rank;
63   TaoType        type;
64   PetscBool      pdipm;
65 
66   ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr;
67   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRMPI(ierr);
68   if (rank>1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_WRONG_MPI_SIZE,"More than 2 processors detected. Example written to use max of 2 processors.\n");
69 
70   ierr = PetscPrintf(PETSC_COMM_WORLD,"---- Constrained Problem -----\n");CHKERRQ(ierr);
71   ierr = InitializeProblem(&user);CHKERRQ(ierr); /* sets up problem, function below */
72   ierr = TaoCreate(PETSC_COMM_WORLD,&tao);CHKERRQ(ierr);
73   ierr = TaoSetType(tao,TAOPDIPM);CHKERRQ(ierr);
74   ierr = TaoSetInitialVector(tao,user.x);CHKERRQ(ierr); /* gets solution vector from problem */
75   ierr = TaoSetVariableBounds(tao,user.xl,user.xu);CHKERRQ(ierr); /* sets lower upper bounds from given solution */
76   ierr = TaoSetObjectiveAndGradientRoutine(tao,FormFunctionGradient,(void*)&user);CHKERRQ(ierr);
77 
78   if (!user.noeqflag) {
79     ierr = TaoSetEqualityConstraintsRoutine(tao,user.ce,FormEqualityConstraints,(void*)&user);CHKERRQ(ierr);
80   }
81   ierr = TaoSetInequalityConstraintsRoutine(tao,user.ci,FormInequalityConstraints,(void*)&user);CHKERRQ(ierr);
82   if (!user.noeqflag) {
83     ierr = TaoSetJacobianEqualityRoutine(tao,user.Ae,user.Ae,FormEqualityJacobian,(void*)&user);CHKERRQ(ierr); /* equality jacobian */
84   }
85   ierr = TaoSetJacobianInequalityRoutine(tao,user.Ai,user.Ai,FormInequalityJacobian,(void*)&user);CHKERRQ(ierr); /* inequality jacobian */
86   ierr = TaoSetTolerances(tao,1.e-6,1.e-6,1.e-6);CHKERRQ(ierr);
87   ierr = TaoSetConstraintTolerances(tao,1.e-6,1.e-6);CHKERRQ(ierr);
88 
89   ierr = TaoGetKSP(tao,&ksp);CHKERRQ(ierr);
90   ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
91   ierr = PCSetType(pc,PCCHOLESKY);CHKERRQ(ierr);
92   /*
93       This algorithm produces matrices with zeros along the diagonal therefore we use
94     MUMPS which provides solver for indefinite matrices
95   */
96   ierr = PCFactorSetMatSolverType(pc,MATSOLVERMUMPS);CHKERRQ(ierr);  /* requires mumps to solve pdipm */
97   ierr = KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr);
98   ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr);
99 
100   ierr = TaoSetFromOptions(tao);CHKERRQ(ierr);
101   ierr = TaoGetType(tao,&type);CHKERRQ(ierr);
102   ierr = PetscObjectTypeCompare((PetscObject)tao,TAOPDIPM,&pdipm);CHKERRQ(ierr);
103   if (pdipm) {
104     ierr = TaoSetHessianRoutine(tao,user.H,user.H,FormHessian,(void*)&user);CHKERRQ(ierr);
105   }
106 
107   ierr = TaoSolve(tao);CHKERRQ(ierr);
108   ierr = TaoGetSolutionVector(tao,&x);CHKERRQ(ierr);
109   ierr = VecView(x,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
110 
111   /* Free objects */
112   ierr = DestroyProblem(&user);CHKERRQ(ierr);
113   ierr = TaoDestroy(&tao);CHKERRQ(ierr);
114   ierr = PetscFinalize();
115   return ierr;
116 }
117 
118 PetscErrorCode InitializeProblem(AppCtx *user)
119 {
120   PetscErrorCode ierr;
121   PetscMPIInt    size;
122   PetscMPIInt    rank;
123   PetscInt       nloc,neloc,niloc;
124 
125   PetscFunctionBegin;
126   ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRMPI(ierr);
127   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRMPI(ierr);
128   user->noeqflag = PETSC_FALSE;
129   ierr = PetscOptionsGetBool(NULL,NULL,"-no_eq",&user->noeqflag,NULL);CHKERRQ(ierr);
130 
131   if (!user->noeqflag) {
132     ierr = PetscPrintf(PETSC_COMM_WORLD,"Solution should be f(1,1)=-2\n");CHKERRQ(ierr);
133   }
134 
135   /* create vector x and set initial values */
136   user->n = 2; /* global length */
137   nloc = (rank==0)?user->n:0;
138   ierr = VecCreate(PETSC_COMM_WORLD,&user->x);CHKERRQ(ierr);
139   ierr = VecSetSizes(user->x,nloc,user->n);CHKERRQ(ierr);
140   ierr = VecSetFromOptions(user->x);CHKERRQ(ierr);
141   ierr = VecSet(user->x,0);CHKERRQ(ierr);
142 
143   /* create and set lower and upper bound vectors */
144   ierr = VecDuplicate(user->x,&user->xl);CHKERRQ(ierr);
145   ierr = VecDuplicate(user->x,&user->xu);CHKERRQ(ierr);
146   ierr = VecSet(user->xl,-1.0);CHKERRQ(ierr);
147   ierr = VecSet(user->xu,2.0);CHKERRQ(ierr);
148 
149   /* create scater to zero */
150   ierr = VecScatterCreateToZero(user->x,&user->scat,&user->Xseq);CHKERRQ(ierr);
151 
152     user->ne = 1;
153     user->ni = 2;
154     neloc = (rank==0)?user->ne:0;
155     niloc = (rank==0)?user->ni:0;
156 
157   if (!user->noeqflag) {
158     ierr = VecCreate(PETSC_COMM_WORLD,&user->ce);CHKERRQ(ierr); /* a 1x1 vec for equality constraints */
159     ierr = VecSetSizes(user->ce,neloc,user->ne);CHKERRQ(ierr);
160     ierr = VecSetFromOptions(user->ce);CHKERRQ(ierr);
161     ierr = VecSetUp(user->ce);CHKERRQ(ierr);
162   }
163 
164   ierr = VecCreate(PETSC_COMM_WORLD,&user->ci);CHKERRQ(ierr); /* a 2x1 vec for inequality constraints */
165   ierr = VecSetSizes(user->ci,niloc,user->ni);CHKERRQ(ierr);
166   ierr = VecSetFromOptions(user->ci);CHKERRQ(ierr);
167   ierr = VecSetUp(user->ci);CHKERRQ(ierr);
168 
169   /* nexn & nixn matricies for equaly and inequalty constriants */
170   if (!user->noeqflag) {
171     ierr = MatCreate(PETSC_COMM_WORLD,&user->Ae);CHKERRQ(ierr);
172     ierr = MatSetSizes(user->Ae,neloc,nloc,user->ne,user->n);CHKERRQ(ierr);
173     ierr = MatSetFromOptions(user->Ae);CHKERRQ(ierr);
174     ierr = MatSetUp(user->Ae);CHKERRQ(ierr);
175   }
176 
177   ierr = MatCreate(PETSC_COMM_WORLD,&user->Ai);CHKERRQ(ierr);
178   ierr = MatSetSizes(user->Ai,niloc,nloc,user->ni,user->n);CHKERRQ(ierr);
179   ierr = MatSetFromOptions(user->Ai);CHKERRQ(ierr);
180   ierr = MatSetUp(user->Ai);CHKERRQ(ierr);
181 
182   ierr = MatCreate(PETSC_COMM_WORLD,&user->H);CHKERRQ(ierr);
183   ierr = MatSetSizes(user->H,nloc,nloc,user->n,user->n);CHKERRQ(ierr);
184   ierr = MatSetFromOptions(user->H);CHKERRQ(ierr);
185   ierr = MatSetUp(user->H);CHKERRQ(ierr);
186   PetscFunctionReturn(0);
187 }
188 
189 PetscErrorCode DestroyProblem(AppCtx *user)
190 {
191   PetscErrorCode ierr;
192 
193   PetscFunctionBegin;
194   if (!user->noeqflag) {
195    ierr = MatDestroy(&user->Ae);CHKERRQ(ierr);
196   }
197   ierr = MatDestroy(&user->Ai);CHKERRQ(ierr);
198   ierr = MatDestroy(&user->H);CHKERRQ(ierr);
199 
200   ierr = VecDestroy(&user->x);CHKERRQ(ierr);
201   if (!user->noeqflag) {
202     ierr = VecDestroy(&user->ce);CHKERRQ(ierr);
203   }
204   ierr = VecDestroy(&user->ci);CHKERRQ(ierr);
205   ierr = VecDestroy(&user->xl);CHKERRQ(ierr);
206   ierr = VecDestroy(&user->xu);CHKERRQ(ierr);
207   ierr = VecDestroy(&user->Xseq);CHKERRQ(ierr);
208   ierr = VecScatterDestroy(&user->scat);CHKERRQ(ierr);
209   PetscFunctionReturn(0);
210 }
211 
212 /* Evaluate
213    f(x) = (x0 - 2)^2 + (x1 - 2)^2 - 2*(x0 + x1)
214    G = grad f = [2*(x0 - 2) - 2;
215                  2*(x1 - 2) - 2]
216 */
217 PetscErrorCode FormFunctionGradient(Tao tao, Vec X, PetscReal *f, Vec G, void *ctx)
218 {
219   PetscScalar       g;
220   const PetscScalar *x;
221   MPI_Comm          comm;
222   PetscMPIInt       rank;
223   PetscErrorCode    ierr;
224   PetscReal         fin;
225   AppCtx            *user=(AppCtx*)ctx;
226   Vec               Xseq=user->Xseq;
227   VecScatter        scat=user->scat;
228 
229   PetscFunctionBegin;
230   ierr = PetscObjectGetComm((PetscObject)tao,&comm);CHKERRQ(ierr);
231   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
232 
233   ierr = VecScatterBegin(scat,X,Xseq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
234   ierr = VecScatterEnd(scat,X,Xseq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
235 
236   fin = 0.0;
237   if (!rank) {
238     ierr = VecGetArrayRead(Xseq,&x);CHKERRQ(ierr);
239     fin = (x[0]-2.0)*(x[0]-2.0) + (x[1]-2.0)*(x[1]-2.0) - 2.0*(x[0]+x[1]);
240     g = 2.0*(x[0]-2.0) - 2.0;
241     ierr = VecSetValue(G,0,g,INSERT_VALUES);CHKERRQ(ierr);
242     g = 2.0*(x[1]-2.0) - 2.0;
243     ierr = VecSetValue(G,1,g,INSERT_VALUES);CHKERRQ(ierr);
244     ierr = VecRestoreArrayRead(Xseq,&x);CHKERRQ(ierr);
245   }
246   ierr = MPI_Allreduce(&fin,f,1,MPIU_REAL,MPIU_SUM,comm);CHKERRMPI(ierr);
247   ierr = VecAssemblyBegin(G);CHKERRQ(ierr);
248   ierr = VecAssemblyEnd(G);CHKERRQ(ierr);
249   PetscFunctionReturn(0);
250 }
251 
252 /* Evaluate
253    H = fxx + grad (grad g^T*DI) - grad (grad h^T*DE)]
254      = [ 2*(1+de[0]-di[0]+di[1]), 0;
255                    0,             2]
256 */
257 PetscErrorCode FormHessian(Tao tao, Vec x,Mat H, Mat Hpre, void *ctx)
258 {
259   AppCtx            *user=(AppCtx*)ctx;
260   Vec               DE,DI;
261   const PetscScalar *de,*di;
262   PetscInt          zero=0,one=1;
263   PetscScalar       two=2.0;
264   PetscScalar       val=0.0;
265   Vec               Deseq,Diseq=user->Xseq;
266   VecScatter        Descat,Discat=user->scat;
267   PetscMPIInt       rank;
268   MPI_Comm          comm;
269   PetscErrorCode    ierr;
270 
271   PetscFunctionBegin;
272   ierr = TaoGetDualVariables(tao,&DE,&DI);CHKERRQ(ierr);
273 
274   ierr = PetscObjectGetComm((PetscObject)tao,&comm);CHKERRQ(ierr);
275   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
276 
277   if (!user->noeqflag) {
278    ierr = VecScatterCreateToZero(DE,&Descat,&Deseq);CHKERRQ(ierr);
279    ierr = VecScatterBegin(Descat,DE,Deseq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
280    ierr = VecScatterEnd(Descat,DE,Deseq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
281   }
282   ierr = VecScatterBegin(Discat,DI,Diseq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
283   ierr = VecScatterEnd(Discat,DI,Diseq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
284 
285   if (!rank) {
286     if (!user->noeqflag) {
287       ierr = VecGetArrayRead(Deseq,&de);CHKERRQ(ierr);  /* places equality constraint dual into array */
288     }
289     ierr = VecGetArrayRead(Diseq,&di);CHKERRQ(ierr);  /* places inequality constraint dual into array */
290 
291     if (!user->noeqflag) {
292       val = 2.0 * (1 + de[0] - di[0] + di[1]);
293       ierr = VecRestoreArrayRead(Deseq,&de);CHKERRQ(ierr);
294       ierr = VecRestoreArrayRead(Diseq,&di);CHKERRQ(ierr);
295     } else {
296       val = 2.0 * (1 - di[0] + di[1]);
297     }
298     ierr = VecRestoreArrayRead(Diseq,&di);CHKERRQ(ierr);
299     ierr = MatSetValues(H,1,&zero,1,&zero,&val,INSERT_VALUES);CHKERRQ(ierr);
300     ierr = MatSetValues(H,1,&one,1,&one,&two,INSERT_VALUES);CHKERRQ(ierr);
301   }
302   ierr = MatAssemblyBegin(H,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
303   ierr = MatAssemblyEnd(H,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
304   if (!user->noeqflag) {
305     ierr = VecScatterDestroy(&Descat);CHKERRQ(ierr);
306     ierr = VecDestroy(&Deseq);CHKERRQ(ierr);
307   }
308   PetscFunctionReturn(0);
309 }
310 
311 /* Evaluate
312    h = [ x0^2 - x1;
313          1 -(x0^2 - x1)]
314 */
315 PetscErrorCode FormInequalityConstraints(Tao tao,Vec X,Vec CI,void *ctx)
316 {
317   const PetscScalar *x;
318   PetscScalar       ci;
319   PetscErrorCode    ierr;
320   MPI_Comm          comm;
321   PetscMPIInt       rank;
322   AppCtx            *user=(AppCtx*)ctx;
323   Vec               Xseq=user->Xseq;
324   VecScatter        scat=user->scat;
325 
326   PetscFunctionBegin;
327   ierr = PetscObjectGetComm((PetscObject)tao,&comm);CHKERRQ(ierr);
328   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
329 
330   ierr = VecScatterBegin(scat,X,Xseq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
331   ierr = VecScatterEnd(scat,X,Xseq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
332 
333   if (!rank) {
334     ierr = VecGetArrayRead(Xseq,&x);CHKERRQ(ierr);
335     ci = x[0]*x[0] - x[1];
336     ierr = VecSetValue(CI,0,ci,INSERT_VALUES);CHKERRQ(ierr);
337     ci = -x[0]*x[0] + x[1] + 1.0;
338     ierr = VecSetValue(CI,1,ci,INSERT_VALUES);CHKERRQ(ierr);
339     ierr = VecRestoreArrayRead(Xseq,&x);CHKERRQ(ierr);
340   }
341   ierr = VecAssemblyBegin(CI);CHKERRQ(ierr);
342   ierr = VecAssemblyEnd(CI);CHKERRQ(ierr);
343   PetscFunctionReturn(0);
344 }
345 
346 /* Evaluate
347    g = [ x0^2 + x1 - 2]
348 */
349 PetscErrorCode FormEqualityConstraints(Tao tao,Vec X,Vec CE,void *ctx)
350 {
351   const PetscScalar *x;
352   PetscScalar       ce;
353   PetscErrorCode    ierr;
354   MPI_Comm          comm;
355   PetscMPIInt       rank;
356   AppCtx            *user=(AppCtx*)ctx;
357   Vec               Xseq=user->Xseq;
358   VecScatter        scat=user->scat;
359 
360   PetscFunctionBegin;
361   ierr = PetscObjectGetComm((PetscObject)tao,&comm);CHKERRQ(ierr);
362   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
363 
364   ierr = VecScatterBegin(scat,X,Xseq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
365   ierr = VecScatterEnd(scat,X,Xseq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
366 
367   if (!rank) {
368     ierr = VecGetArrayRead(Xseq,&x);CHKERRQ(ierr);
369     ce = x[0]*x[0] + x[1] - 2.0;
370     ierr = VecSetValue(CE,0,ce,INSERT_VALUES);CHKERRQ(ierr);
371     ierr = VecRestoreArrayRead(Xseq,&x);CHKERRQ(ierr);
372   }
373   ierr = VecAssemblyBegin(CE);CHKERRQ(ierr);
374   ierr = VecAssemblyEnd(CE);CHKERRQ(ierr);
375   PetscFunctionReturn(0);
376 }
377 
378 /*
379   grad h = [  2*x0, -1;
380              -2*x0,  1]
381 */
382 PetscErrorCode FormInequalityJacobian(Tao tao, Vec X, Mat JI, Mat JIpre,  void *ctx)
383 {
384   AppCtx            *user=(AppCtx*)ctx;
385   PetscInt          cols[2],min,max,i;
386   PetscScalar       vals[2];
387   const PetscScalar *x;
388   PetscErrorCode    ierr;
389   Vec               Xseq=user->Xseq;
390   VecScatter        scat=user->scat;
391   MPI_Comm          comm;
392   PetscMPIInt       rank;
393 
394   PetscFunctionBegin;
395   ierr = PetscObjectGetComm((PetscObject)tao,&comm);CHKERRQ(ierr);
396   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
397   ierr = VecScatterBegin(scat,X,Xseq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
398   ierr = VecScatterEnd(scat,X,Xseq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
399 
400   ierr = VecGetArrayRead(Xseq,&x);CHKERRQ(ierr);
401   ierr = MatGetOwnershipRange(JI,&min,&max);CHKERRQ(ierr);
402 
403   cols[0] = 0; cols[1] = 1;
404   for (i=min;i<max;i++) {
405     if (i==0) {
406       vals[0] = 2*x[0]; vals[1] = -1.0;
407       ierr = MatSetValues(JI,1,&i,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
408     }
409     if (i==1) {
410       vals[0] = -2*x[0]; vals[1] = 1.0;
411       ierr = MatSetValues(JI,1,&i,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
412     }
413   }
414   ierr = VecRestoreArrayRead(Xseq,&x);CHKERRQ(ierr);
415 
416   ierr = MatAssemblyBegin(JI,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
417   ierr = MatAssemblyEnd(JI,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
418   PetscFunctionReturn(0);
419 }
420 
421 /*
422   grad g = [2*x0
423              1.0 ]
424 */
425 PetscErrorCode FormEqualityJacobian(Tao tao,Vec X,Mat JE,Mat JEpre,void *ctx)
426 {
427   PetscInt          rows[2];
428   PetscScalar       vals[2];
429   const PetscScalar *x;
430   PetscMPIInt       rank;
431   MPI_Comm          comm;
432   PetscErrorCode    ierr;
433 
434   PetscFunctionBegin;
435   ierr = PetscObjectGetComm((PetscObject)tao,&comm);CHKERRQ(ierr);
436   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
437 
438   if (!rank) {
439     ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
440     rows[0] = 0;       rows[1] = 1;
441     vals[0] = 2*x[0];  vals[1] = 1.0;
442     ierr = MatSetValues(JE,1,rows,2,rows,vals,INSERT_VALUES);CHKERRQ(ierr);
443     ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
444   }
445   ierr = MatAssemblyBegin(JE,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
446   ierr = MatAssemblyEnd(JE,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
447   PetscFunctionReturn(0);
448 }
449 
450 /*TEST
451 
452    build:
453       requires: !complex !define(PETSC_USE_CXX) mumps
454 
455    test:
456       args: -tao_converged_reason -tao_pdipm_kkt_shift_pd
457 
458    test:
459       suffix: 2
460       nsize: 2
461       args: -tao_converged_reason -tao_pdipm_kkt_shift_pd
462 
463    test:
464       suffix: 3
465       args: -tao_converged_reason -no_eq
466 
467    test:
468       suffix: 4
469       nsize: 2
470       args: -tao_converged_reason -no_eq
471 
472    test:
473       suffix: 5
474       args: -tao_cmonitor -tao_type almm
475 
476    test:
477       suffix: 6
478       args: -tao_cmonitor -tao_type almm -tao_almm_type phr
479 
480    test:
481       suffix: 7
482       nsize: 2
483       args: -tao_cmonitor -tao_type almm
484 
485    test:
486       suffix: 8
487       nsize: 2
488       requires: cuda
489       args: -tao_cmonitor -tao_type almm -vec_type cuda -mat_type aijcusparse
490 
491    test:
492       suffix: 9
493       nsize: 2
494       args: -tao_cmonitor -tao_type almm -no_eq
495 
496    test:
497       suffix: 10
498       nsize: 2
499       args: -tao_cmonitor -tao_type almm -tao_almm_type phr -no_eq
500 
501 TEST*/
502