xref: /petsc/src/snes/tests/ex17.c (revision c4762a1b19cd2af06abeed90e8f9d34fb975dd94)
1*c4762a1bSJed Brown static const char help[] = "Newton's method to solve a two-variable system, sequentially.\n"
2*c4762a1bSJed Brown                            "The same problem is solved twice - i) fully assembled system + ii) block system\n\n";
3*c4762a1bSJed Brown 
4*c4762a1bSJed Brown /*T
5*c4762a1bSJed Brown Concepts: SNES^basic uniprocessor example, block objects
6*c4762a1bSJed Brown Processors: 1
7*c4762a1bSJed Brown T*/
8*c4762a1bSJed Brown 
9*c4762a1bSJed Brown 
10*c4762a1bSJed Brown 
11*c4762a1bSJed Brown /*
12*c4762a1bSJed Brown Include "petscsnes.h" so that we can use SNES solvers.  Note that this
13*c4762a1bSJed Brown file automatically includes:
14*c4762a1bSJed Brown petscsys.h       - base PETSc routines   petscvec.h - vectors
15*c4762a1bSJed Brown petscsys.h    - system routines       petscmat.h - matrices
16*c4762a1bSJed Brown petscis.h     - index sets            petscksp.h - Krylov subspace methods
17*c4762a1bSJed Brown petscviewer.h - viewers               petscpc.h  - preconditioners
18*c4762a1bSJed Brown petscksp.h   - linear solvers
19*c4762a1bSJed Brown */
20*c4762a1bSJed Brown #include <petscsnes.h>
21*c4762a1bSJed Brown 
22*c4762a1bSJed Brown /*
23*c4762a1bSJed Brown This example is block version of the test found at
24*c4762a1bSJed Brown   ${PETSC_DIR}/src/snes/tutorials/ex1.c
25*c4762a1bSJed Brown In this test we replace the Jacobian systems
26*c4762a1bSJed Brown   [J]{x} = {F}
27*c4762a1bSJed Brown where
28*c4762a1bSJed Brown 
29*c4762a1bSJed Brown [J] = (j_00, j_01),  {x} = (x_0, x_1)^T,   {F} = (f_0, f_1)^T
30*c4762a1bSJed Brown       (j_10, j_11)
31*c4762a1bSJed Brown where [J] \in \mathbb^{2 \times 2}, {x},{F} \in \mathbb^{2 \times 1},
32*c4762a1bSJed Brown 
33*c4762a1bSJed Brown with a block system in which each block is of length 1.
34*c4762a1bSJed Brown i.e. The block system is thus
35*c4762a1bSJed Brown 
36*c4762a1bSJed Brown [J] = ([j00], [j01]),  {x} = ({x0}, {x1})^T, {F} = ({f0}, {f1})^T
37*c4762a1bSJed Brown       ([j10], [j11])
38*c4762a1bSJed Brown where
39*c4762a1bSJed Brown [j00], [j01], [j10], [j11] \in \mathbb^{1 \times 1}
40*c4762a1bSJed Brown {x0}, {x1}, {f0}, {f1} \in \mathbb^{1 \times 1}
41*c4762a1bSJed Brown 
42*c4762a1bSJed Brown In practice we would not bother defing blocks of size one, and would instead assemble the
43*c4762a1bSJed Brown full system. This is just a simple test to illustrate how to manipulate the blocks and
44*c4762a1bSJed Brown to confirm the implementation is correct.
45*c4762a1bSJed Brown */
46*c4762a1bSJed Brown 
47*c4762a1bSJed Brown /*
48*c4762a1bSJed Brown User-defined routines
49*c4762a1bSJed Brown */
50*c4762a1bSJed Brown static PetscErrorCode FormJacobian1(SNES,Vec,Mat,Mat,void*);
51*c4762a1bSJed Brown static PetscErrorCode FormFunction1(SNES,Vec,Vec,void*);
52*c4762a1bSJed Brown static PetscErrorCode FormJacobian2(SNES,Vec,Mat,Mat,void*);
53*c4762a1bSJed Brown static PetscErrorCode FormFunction2(SNES,Vec,Vec,void*);
54*c4762a1bSJed Brown static PetscErrorCode FormJacobian1_block(SNES,Vec,Mat,Mat,void*);
55*c4762a1bSJed Brown static PetscErrorCode FormFunction1_block(SNES,Vec,Vec,void*);
56*c4762a1bSJed Brown static PetscErrorCode FormJacobian2_block(SNES,Vec,Mat,Mat,void*);
57*c4762a1bSJed Brown static PetscErrorCode FormFunction2_block(SNES,Vec,Vec,void*);
58*c4762a1bSJed Brown 
59*c4762a1bSJed Brown 
60*c4762a1bSJed Brown static PetscErrorCode assembled_system(void)
61*c4762a1bSJed Brown {
62*c4762a1bSJed Brown   SNES           snes;         /* nonlinear solver context */
63*c4762a1bSJed Brown   KSP            ksp;         /* linear solver context */
64*c4762a1bSJed Brown   PC             pc;           /* preconditioner context */
65*c4762a1bSJed Brown   Vec            x,r;         /* solution, residual vectors */
66*c4762a1bSJed Brown   Mat            J;            /* Jacobian matrix */
67*c4762a1bSJed Brown   PetscErrorCode ierr;
68*c4762a1bSJed Brown   PetscInt       its;
69*c4762a1bSJed Brown   PetscScalar    pfive = .5,*xx;
70*c4762a1bSJed Brown   PetscBool      flg;
71*c4762a1bSJed Brown 
72*c4762a1bSJed Brown   PetscFunctionBeginUser;
73*c4762a1bSJed Brown   PetscPrintf(PETSC_COMM_WORLD, "\n\n========================= Assembled system =========================\n\n");
74*c4762a1bSJed Brown 
75*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
76*c4762a1bSJed Brown   Create nonlinear solver context
77*c4762a1bSJed Brown   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
78*c4762a1bSJed Brown 
79*c4762a1bSJed Brown   ierr = SNESCreate(PETSC_COMM_WORLD,&snes);CHKERRQ(ierr);
80*c4762a1bSJed Brown 
81*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
82*c4762a1bSJed Brown   Create matrix and vector data structures; set corresponding routines
83*c4762a1bSJed Brown   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
84*c4762a1bSJed Brown 
85*c4762a1bSJed Brown   /*
86*c4762a1bSJed Brown   Create vectors for solution and nonlinear function
87*c4762a1bSJed Brown   */
88*c4762a1bSJed Brown   ierr = VecCreateSeq(PETSC_COMM_SELF,2,&x);CHKERRQ(ierr);
89*c4762a1bSJed Brown   ierr = VecDuplicate(x,&r);CHKERRQ(ierr);
90*c4762a1bSJed Brown 
91*c4762a1bSJed Brown   /*
92*c4762a1bSJed Brown   Create Jacobian matrix data structure
93*c4762a1bSJed Brown   */
94*c4762a1bSJed Brown   ierr = MatCreate(PETSC_COMM_SELF,&J);CHKERRQ(ierr);
95*c4762a1bSJed Brown   ierr = MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,2,2);CHKERRQ(ierr);
96*c4762a1bSJed Brown   ierr = MatSetFromOptions(J);CHKERRQ(ierr);
97*c4762a1bSJed Brown   ierr = MatSetUp(J);CHKERRQ(ierr);
98*c4762a1bSJed Brown 
99*c4762a1bSJed Brown   ierr = PetscOptionsHasName(NULL,NULL,"-hard",&flg);CHKERRQ(ierr);
100*c4762a1bSJed Brown   if (!flg) {
101*c4762a1bSJed Brown     /*
102*c4762a1bSJed Brown     Set function evaluation routine and vector.
103*c4762a1bSJed Brown     */
104*c4762a1bSJed Brown     ierr = SNESSetFunction(snes,r,FormFunction1,NULL);CHKERRQ(ierr);
105*c4762a1bSJed Brown 
106*c4762a1bSJed Brown     /*
107*c4762a1bSJed Brown     Set Jacobian matrix data structure and Jacobian evaluation routine
108*c4762a1bSJed Brown     */
109*c4762a1bSJed Brown     ierr = SNESSetJacobian(snes,J,J,FormJacobian1,NULL);CHKERRQ(ierr);
110*c4762a1bSJed Brown   } else {
111*c4762a1bSJed Brown     ierr = SNESSetFunction(snes,r,FormFunction2,NULL);CHKERRQ(ierr);
112*c4762a1bSJed Brown     ierr = SNESSetJacobian(snes,J,J,FormJacobian2,NULL);CHKERRQ(ierr);
113*c4762a1bSJed Brown   }
114*c4762a1bSJed Brown 
115*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
116*c4762a1bSJed Brown   Customize nonlinear solver; set runtime options
117*c4762a1bSJed Brown   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
118*c4762a1bSJed Brown 
119*c4762a1bSJed Brown   /*
120*c4762a1bSJed Brown   Set linear solver defaults for this problem. By extracting the
121*c4762a1bSJed Brown   KSP, KSP, and PC contexts from the SNES context, we can then
122*c4762a1bSJed Brown   directly call any KSP, KSP, and PC routines to set various options.
123*c4762a1bSJed Brown   */
124*c4762a1bSJed Brown   ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr);
125*c4762a1bSJed Brown   ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
126*c4762a1bSJed Brown   ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr);
127*c4762a1bSJed Brown   ierr = KSPSetTolerances(ksp,1.e-4,PETSC_DEFAULT,PETSC_DEFAULT,20);CHKERRQ(ierr);
128*c4762a1bSJed Brown 
129*c4762a1bSJed Brown   /*
130*c4762a1bSJed Brown   Set SNES/KSP/KSP/PC runtime options, e.g.,
131*c4762a1bSJed Brown   -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc>
132*c4762a1bSJed Brown   These options will override those specified above as long as
133*c4762a1bSJed Brown   SNESSetFromOptions() is called _after_ any other customization
134*c4762a1bSJed Brown   routines.
135*c4762a1bSJed Brown   */
136*c4762a1bSJed Brown   ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
137*c4762a1bSJed Brown 
138*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
139*c4762a1bSJed Brown   Evaluate initial guess; then solve nonlinear system
140*c4762a1bSJed Brown   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
141*c4762a1bSJed Brown   if (!flg) {
142*c4762a1bSJed Brown     ierr = VecSet(x,pfive);CHKERRQ(ierr);
143*c4762a1bSJed Brown   } else {
144*c4762a1bSJed Brown     ierr  = VecGetArray(x,&xx);CHKERRQ(ierr);
145*c4762a1bSJed Brown     xx[0] = 2.0; xx[1] = 3.0;
146*c4762a1bSJed Brown     ierr  = VecRestoreArray(x,&xx);CHKERRQ(ierr);
147*c4762a1bSJed Brown   }
148*c4762a1bSJed Brown   /*
149*c4762a1bSJed Brown   Note: The user should initialize the vector, x, with the initial guess
150*c4762a1bSJed Brown   for the nonlinear solver prior to calling SNESSolve().  In particular,
151*c4762a1bSJed Brown   to employ an initial guess of zero, the user should explicitly set
152*c4762a1bSJed Brown   this vector to zero by calling VecSet().
153*c4762a1bSJed Brown   */
154*c4762a1bSJed Brown 
155*c4762a1bSJed Brown   ierr = SNESSolve(snes,NULL,x);CHKERRQ(ierr);
156*c4762a1bSJed Brown   ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr);
157*c4762a1bSJed Brown   if (flg) {
158*c4762a1bSJed Brown     Vec f;
159*c4762a1bSJed Brown     ierr = VecView(x,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
160*c4762a1bSJed Brown     ierr = SNESGetFunction(snes,&f,0,0);CHKERRQ(ierr);
161*c4762a1bSJed Brown     ierr = VecView(r,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
162*c4762a1bSJed Brown   }
163*c4762a1bSJed Brown 
164*c4762a1bSJed Brown   ierr = PetscPrintf(PETSC_COMM_SELF,"number of SNES iterations = %D\n\n",its);CHKERRQ(ierr);
165*c4762a1bSJed Brown 
166*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
167*c4762a1bSJed Brown   Free work space.  All PETSc objects should be destroyed when they
168*c4762a1bSJed Brown   are no longer needed.
169*c4762a1bSJed Brown   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
170*c4762a1bSJed Brown 
171*c4762a1bSJed Brown   ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&r);CHKERRQ(ierr);
172*c4762a1bSJed Brown   ierr = MatDestroy(&J);CHKERRQ(ierr); ierr = SNESDestroy(&snes);CHKERRQ(ierr);
173*c4762a1bSJed Brown   PetscFunctionReturn(0);
174*c4762a1bSJed Brown }
175*c4762a1bSJed Brown 
176*c4762a1bSJed Brown /* ------------------------------------------------------------------- */
177*c4762a1bSJed Brown /*
178*c4762a1bSJed Brown FormFunction1 - Evaluates nonlinear function, F(x).
179*c4762a1bSJed Brown 
180*c4762a1bSJed Brown Input Parameters:
181*c4762a1bSJed Brown .  snes - the SNES context
182*c4762a1bSJed Brown .  x - input vector
183*c4762a1bSJed Brown .  dummy - optional user-defined context (not used here)
184*c4762a1bSJed Brown 
185*c4762a1bSJed Brown Output Parameter:
186*c4762a1bSJed Brown .  f - function vector
187*c4762a1bSJed Brown */
188*c4762a1bSJed Brown static PetscErrorCode FormFunction1(SNES snes,Vec x,Vec f,void *dummy)
189*c4762a1bSJed Brown {
190*c4762a1bSJed Brown   PetscErrorCode    ierr;
191*c4762a1bSJed Brown   const PetscScalar *xx;
192*c4762a1bSJed Brown   PetscScalar       *ff;
193*c4762a1bSJed Brown 
194*c4762a1bSJed Brown   PetscFunctionBeginUser;
195*c4762a1bSJed Brown   /*
196*c4762a1bSJed Brown   Get pointers to vector data.
197*c4762a1bSJed Brown   - For default PETSc vectors, VecGetArray() returns a pointer to
198*c4762a1bSJed Brown   the data array.  Otherwise, the routine is implementation dependent.
199*c4762a1bSJed Brown   - You MUST call VecRestoreArray() when you no longer need access to
200*c4762a1bSJed Brown   the array.
201*c4762a1bSJed Brown   */
202*c4762a1bSJed Brown   ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
203*c4762a1bSJed Brown   ierr = VecGetArray(f,&ff);CHKERRQ(ierr);
204*c4762a1bSJed Brown 
205*c4762a1bSJed Brown   /*
206*c4762a1bSJed Brown   Compute function
207*c4762a1bSJed Brown   */
208*c4762a1bSJed Brown   ff[0] = xx[0]*xx[0] + xx[0]*xx[1] - 3.0;
209*c4762a1bSJed Brown   ff[1] = xx[0]*xx[1] + xx[1]*xx[1] - 6.0;
210*c4762a1bSJed Brown 
211*c4762a1bSJed Brown 
212*c4762a1bSJed Brown   /*
213*c4762a1bSJed Brown   Restore vectors
214*c4762a1bSJed Brown   */
215*c4762a1bSJed Brown   ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
216*c4762a1bSJed Brown   ierr = VecRestoreArray(f,&ff);CHKERRQ(ierr);
217*c4762a1bSJed Brown   PetscFunctionReturn(0);
218*c4762a1bSJed Brown }
219*c4762a1bSJed Brown /* ------------------------------------------------------------------- */
220*c4762a1bSJed Brown /*
221*c4762a1bSJed Brown FormJacobian1 - Evaluates Jacobian matrix.
222*c4762a1bSJed Brown 
223*c4762a1bSJed Brown Input Parameters:
224*c4762a1bSJed Brown .  snes - the SNES context
225*c4762a1bSJed Brown .  x - input vector
226*c4762a1bSJed Brown .  dummy - optional user-defined context (not used here)
227*c4762a1bSJed Brown 
228*c4762a1bSJed Brown Output Parameters:
229*c4762a1bSJed Brown .  jac - Jacobian matrix
230*c4762a1bSJed Brown .  B - optionally different preconditioning matrix
231*c4762a1bSJed Brown .  flag - flag indicating matrix structure
232*c4762a1bSJed Brown */
233*c4762a1bSJed Brown static PetscErrorCode FormJacobian1(SNES snes,Vec x,Mat jac,Mat B,void *dummy)
234*c4762a1bSJed Brown {
235*c4762a1bSJed Brown   const PetscScalar *xx;
236*c4762a1bSJed Brown   PetscScalar       A[4];
237*c4762a1bSJed Brown   PetscErrorCode    ierr;
238*c4762a1bSJed Brown   PetscInt          idx[2] = {0,1};
239*c4762a1bSJed Brown 
240*c4762a1bSJed Brown   PetscFunctionBeginUser;
241*c4762a1bSJed Brown   /*
242*c4762a1bSJed Brown   Get pointer to vector data
243*c4762a1bSJed Brown   */
244*c4762a1bSJed Brown   ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
245*c4762a1bSJed Brown 
246*c4762a1bSJed Brown   /*
247*c4762a1bSJed Brown   Compute Jacobian entries and insert into matrix.
248*c4762a1bSJed Brown   - Since this is such a small problem, we set all entries for
249*c4762a1bSJed Brown   the matrix at once.
250*c4762a1bSJed Brown   */
251*c4762a1bSJed Brown   A[0]  = 2.0*xx[0] + xx[1]; A[1] = xx[0];
252*c4762a1bSJed Brown   A[2]  = xx[1]; A[3] = xx[0] + 2.0*xx[1];
253*c4762a1bSJed Brown   ierr  = MatSetValues(jac,2,idx,2,idx,A,INSERT_VALUES);CHKERRQ(ierr);
254*c4762a1bSJed Brown 
255*c4762a1bSJed Brown   /*
256*c4762a1bSJed Brown   Restore vector
257*c4762a1bSJed Brown   */
258*c4762a1bSJed Brown   ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
259*c4762a1bSJed Brown 
260*c4762a1bSJed Brown   /*
261*c4762a1bSJed Brown   Assemble matrix
262*c4762a1bSJed Brown   */
263*c4762a1bSJed Brown   ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
264*c4762a1bSJed Brown   ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
265*c4762a1bSJed Brown   PetscFunctionReturn(0);
266*c4762a1bSJed Brown }
267*c4762a1bSJed Brown 
268*c4762a1bSJed Brown 
269*c4762a1bSJed Brown /* ------------------------------------------------------------------- */
270*c4762a1bSJed Brown static PetscErrorCode FormFunction2(SNES snes,Vec x,Vec f,void *dummy)
271*c4762a1bSJed Brown {
272*c4762a1bSJed Brown   PetscErrorCode    ierr;
273*c4762a1bSJed Brown   const PetscScalar *xx;
274*c4762a1bSJed Brown   PetscScalar       *ff;
275*c4762a1bSJed Brown 
276*c4762a1bSJed Brown   PetscFunctionBeginUser;
277*c4762a1bSJed Brown   /*
278*c4762a1bSJed Brown   Get pointers to vector data.
279*c4762a1bSJed Brown   - For default PETSc vectors, VecGetArray() returns a pointer to
280*c4762a1bSJed Brown   the data array.  Otherwise, the routine is implementation dependent.
281*c4762a1bSJed Brown   - You MUST call VecRestoreArray() when you no longer need access to
282*c4762a1bSJed Brown   the array.
283*c4762a1bSJed Brown   */
284*c4762a1bSJed Brown   ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
285*c4762a1bSJed Brown   ierr = VecGetArray(f,&ff);CHKERRQ(ierr);
286*c4762a1bSJed Brown 
287*c4762a1bSJed Brown   /*
288*c4762a1bSJed Brown   Compute function
289*c4762a1bSJed Brown   */
290*c4762a1bSJed Brown   ff[0] = PetscSinScalar(3.0*xx[0]) + xx[0];
291*c4762a1bSJed Brown   ff[1] = xx[1];
292*c4762a1bSJed Brown 
293*c4762a1bSJed Brown   /*
294*c4762a1bSJed Brown   Restore vectors
295*c4762a1bSJed Brown   */
296*c4762a1bSJed Brown   ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
297*c4762a1bSJed Brown   ierr = VecRestoreArray(f,&ff);CHKERRQ(ierr);
298*c4762a1bSJed Brown   PetscFunctionReturn(0);
299*c4762a1bSJed Brown }
300*c4762a1bSJed Brown 
301*c4762a1bSJed Brown /* ------------------------------------------------------------------- */
302*c4762a1bSJed Brown static PetscErrorCode FormJacobian2(SNES snes,Vec x,Mat jac,Mat B,void *dummy)
303*c4762a1bSJed Brown {
304*c4762a1bSJed Brown   const PetscScalar *xx;
305*c4762a1bSJed Brown   PetscScalar       A[4];
306*c4762a1bSJed Brown   PetscErrorCode    ierr;
307*c4762a1bSJed Brown   PetscInt          idx[2] = {0,1};
308*c4762a1bSJed Brown 
309*c4762a1bSJed Brown   PetscFunctionBeginUser;
310*c4762a1bSJed Brown   /*
311*c4762a1bSJed Brown   Get pointer to vector data
312*c4762a1bSJed Brown   */
313*c4762a1bSJed Brown   ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
314*c4762a1bSJed Brown 
315*c4762a1bSJed Brown   /*
316*c4762a1bSJed Brown   Compute Jacobian entries and insert into matrix.
317*c4762a1bSJed Brown   - Since this is such a small problem, we set all entries for
318*c4762a1bSJed Brown   the matrix at once.
319*c4762a1bSJed Brown   */
320*c4762a1bSJed Brown   A[0]  = 3.0*PetscCosScalar(3.0*xx[0]) + 1.0; A[1] = 0.0;
321*c4762a1bSJed Brown   A[2]  = 0.0;                     A[3] = 1.0;
322*c4762a1bSJed Brown   ierr  = MatSetValues(jac,2,idx,2,idx,A,INSERT_VALUES);CHKERRQ(ierr);
323*c4762a1bSJed Brown 
324*c4762a1bSJed Brown   /*
325*c4762a1bSJed Brown   Restore vector
326*c4762a1bSJed Brown   */
327*c4762a1bSJed Brown   ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
328*c4762a1bSJed Brown 
329*c4762a1bSJed Brown   /*
330*c4762a1bSJed Brown   Assemble matrix
331*c4762a1bSJed Brown   */
332*c4762a1bSJed Brown   ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
333*c4762a1bSJed Brown   ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
334*c4762a1bSJed Brown   PetscFunctionReturn(0);
335*c4762a1bSJed Brown }
336*c4762a1bSJed Brown 
337*c4762a1bSJed Brown static int block_system(void)
338*c4762a1bSJed Brown {
339*c4762a1bSJed Brown   SNES           snes;         /* nonlinear solver context */
340*c4762a1bSJed Brown   KSP            ksp;         /* linear solver context */
341*c4762a1bSJed Brown   PC             pc;           /* preconditioner context */
342*c4762a1bSJed Brown   Vec            x,r;         /* solution, residual vectors */
343*c4762a1bSJed Brown   Mat            J;            /* Jacobian matrix */
344*c4762a1bSJed Brown   PetscErrorCode ierr;
345*c4762a1bSJed Brown   PetscInt       its;
346*c4762a1bSJed Brown   PetscScalar    pfive = .5;
347*c4762a1bSJed Brown   PetscBool      flg;
348*c4762a1bSJed Brown 
349*c4762a1bSJed Brown   Mat j11, j12, j21, j22;
350*c4762a1bSJed Brown   Vec x1, x2, r1, r2;
351*c4762a1bSJed Brown   Vec bv;
352*c4762a1bSJed Brown   Vec bx[2];
353*c4762a1bSJed Brown   Mat bA[2][2];
354*c4762a1bSJed Brown 
355*c4762a1bSJed Brown   PetscFunctionBeginUser;
356*c4762a1bSJed Brown   PetscPrintf(PETSC_COMM_WORLD, "\n\n========================= Block system =========================\n\n");
357*c4762a1bSJed Brown 
358*c4762a1bSJed Brown   ierr = SNESCreate(PETSC_COMM_WORLD,&snes);CHKERRQ(ierr);
359*c4762a1bSJed Brown 
360*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
361*c4762a1bSJed Brown   Create matrix and vector data structures; set corresponding routines
362*c4762a1bSJed Brown   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
363*c4762a1bSJed Brown 
364*c4762a1bSJed Brown   /*
365*c4762a1bSJed Brown   Create sub vectors for solution and nonlinear function
366*c4762a1bSJed Brown   */
367*c4762a1bSJed Brown   ierr = VecCreateSeq(PETSC_COMM_SELF,1,&x1);CHKERRQ(ierr);
368*c4762a1bSJed Brown   ierr = VecDuplicate(x1,&r1);CHKERRQ(ierr);
369*c4762a1bSJed Brown 
370*c4762a1bSJed Brown   ierr = VecCreateSeq(PETSC_COMM_SELF,1,&x2);CHKERRQ(ierr);
371*c4762a1bSJed Brown   ierr = VecDuplicate(x2,&r2);CHKERRQ(ierr);
372*c4762a1bSJed Brown 
373*c4762a1bSJed Brown   /*
374*c4762a1bSJed Brown   Create the block vectors
375*c4762a1bSJed Brown   */
376*c4762a1bSJed Brown   bx[0] = x1;
377*c4762a1bSJed Brown   bx[1] = x2;
378*c4762a1bSJed Brown   ierr  = VecCreateNest(PETSC_COMM_WORLD,2,NULL,bx,&x);CHKERRQ(ierr);
379*c4762a1bSJed Brown   ierr  = VecAssemblyBegin(x);CHKERRQ(ierr);
380*c4762a1bSJed Brown   ierr  = VecAssemblyEnd(x);CHKERRQ(ierr);
381*c4762a1bSJed Brown   ierr  = VecDestroy(&x1);CHKERRQ(ierr);
382*c4762a1bSJed Brown   ierr  = VecDestroy(&x2);CHKERRQ(ierr);
383*c4762a1bSJed Brown 
384*c4762a1bSJed Brown   bx[0] = r1;
385*c4762a1bSJed Brown   bx[1] = r2;
386*c4762a1bSJed Brown   ierr  = VecCreateNest(PETSC_COMM_WORLD,2,NULL,bx,&r);CHKERRQ(ierr);
387*c4762a1bSJed Brown   ierr  = VecDestroy(&r1);CHKERRQ(ierr);
388*c4762a1bSJed Brown   ierr  = VecDestroy(&r2);CHKERRQ(ierr);
389*c4762a1bSJed Brown   ierr  = VecAssemblyBegin(r);CHKERRQ(ierr);
390*c4762a1bSJed Brown   ierr  = VecAssemblyEnd(r);CHKERRQ(ierr);
391*c4762a1bSJed Brown 
392*c4762a1bSJed Brown   /*
393*c4762a1bSJed Brown   Create sub Jacobian matrix data structure
394*c4762a1bSJed Brown   */
395*c4762a1bSJed Brown   ierr = MatCreate(PETSC_COMM_WORLD, &j11);CHKERRQ(ierr);
396*c4762a1bSJed Brown   ierr = MatSetSizes(j11, 1, 1, 1, 1);CHKERRQ(ierr);
397*c4762a1bSJed Brown   ierr = MatSetType(j11, MATSEQAIJ);CHKERRQ(ierr);
398*c4762a1bSJed Brown   ierr = MatSetUp(j11);CHKERRQ(ierr);
399*c4762a1bSJed Brown 
400*c4762a1bSJed Brown   ierr = MatCreate(PETSC_COMM_WORLD, &j12);CHKERRQ(ierr);
401*c4762a1bSJed Brown   ierr = MatSetSizes(j12, 1, 1, 1, 1);CHKERRQ(ierr);
402*c4762a1bSJed Brown   ierr = MatSetType(j12, MATSEQAIJ);CHKERRQ(ierr);
403*c4762a1bSJed Brown   ierr = MatSetUp(j12);CHKERRQ(ierr);
404*c4762a1bSJed Brown 
405*c4762a1bSJed Brown   ierr = MatCreate(PETSC_COMM_WORLD, &j21);CHKERRQ(ierr);
406*c4762a1bSJed Brown   ierr = MatSetSizes(j21, 1, 1, 1, 1);CHKERRQ(ierr);
407*c4762a1bSJed Brown   ierr = MatSetType(j21, MATSEQAIJ);CHKERRQ(ierr);
408*c4762a1bSJed Brown   ierr = MatSetUp(j21);CHKERRQ(ierr);
409*c4762a1bSJed Brown 
410*c4762a1bSJed Brown   ierr = MatCreate(PETSC_COMM_WORLD, &j22);CHKERRQ(ierr);
411*c4762a1bSJed Brown   ierr = MatSetSizes(j22, PETSC_DECIDE, PETSC_DECIDE, 1, 1);CHKERRQ(ierr);
412*c4762a1bSJed Brown   ierr = MatSetType(j22, MATSEQAIJ);CHKERRQ(ierr);
413*c4762a1bSJed Brown   ierr = MatSetUp(j22);CHKERRQ(ierr);
414*c4762a1bSJed Brown   /*
415*c4762a1bSJed Brown   Create block Jacobian matrix data structure
416*c4762a1bSJed Brown   */
417*c4762a1bSJed Brown   bA[0][0] = j11;
418*c4762a1bSJed Brown   bA[0][1] = j12;
419*c4762a1bSJed Brown   bA[1][0] = j21;
420*c4762a1bSJed Brown   bA[1][1] = j22;
421*c4762a1bSJed Brown 
422*c4762a1bSJed Brown   ierr = MatCreateNest(PETSC_COMM_WORLD,2,NULL,2,NULL,&bA[0][0],&J);CHKERRQ(ierr);
423*c4762a1bSJed Brown   ierr = MatSetUp(J);CHKERRQ(ierr);
424*c4762a1bSJed Brown   ierr = MatNestSetVecType(J,VECNEST);CHKERRQ(ierr);
425*c4762a1bSJed Brown   ierr = MatDestroy(&j11);CHKERRQ(ierr);
426*c4762a1bSJed Brown   ierr = MatDestroy(&j12);CHKERRQ(ierr);
427*c4762a1bSJed Brown   ierr = MatDestroy(&j21);CHKERRQ(ierr);
428*c4762a1bSJed Brown   ierr = MatDestroy(&j22);CHKERRQ(ierr);
429*c4762a1bSJed Brown 
430*c4762a1bSJed Brown   ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
431*c4762a1bSJed Brown   ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
432*c4762a1bSJed Brown 
433*c4762a1bSJed Brown   ierr = PetscOptionsHasName(NULL,NULL,"-hard",&flg);CHKERRQ(ierr);
434*c4762a1bSJed Brown   if (!flg) {
435*c4762a1bSJed Brown     /*
436*c4762a1bSJed Brown     Set function evaluation routine and vector.
437*c4762a1bSJed Brown     */
438*c4762a1bSJed Brown     ierr = SNESSetFunction(snes,r,FormFunction1_block,NULL);CHKERRQ(ierr);
439*c4762a1bSJed Brown 
440*c4762a1bSJed Brown     /*
441*c4762a1bSJed Brown     Set Jacobian matrix data structure and Jacobian evaluation routine
442*c4762a1bSJed Brown     */
443*c4762a1bSJed Brown     ierr = SNESSetJacobian(snes,J,J,FormJacobian1_block,NULL);CHKERRQ(ierr);
444*c4762a1bSJed Brown   } else {
445*c4762a1bSJed Brown     ierr = SNESSetFunction(snes,r,FormFunction2_block,NULL);CHKERRQ(ierr);
446*c4762a1bSJed Brown     ierr = SNESSetJacobian(snes,J,J,FormJacobian2_block,NULL);CHKERRQ(ierr);
447*c4762a1bSJed Brown   }
448*c4762a1bSJed Brown 
449*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
450*c4762a1bSJed Brown   Customize nonlinear solver; set runtime options
451*c4762a1bSJed Brown   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
452*c4762a1bSJed Brown 
453*c4762a1bSJed Brown   /*
454*c4762a1bSJed Brown   Set linear solver defaults for this problem. By extracting the
455*c4762a1bSJed Brown   KSP, KSP, and PC contexts from the SNES context, we can then
456*c4762a1bSJed Brown   directly call any KSP, KSP, and PC routines to set various options.
457*c4762a1bSJed Brown   */
458*c4762a1bSJed Brown   ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr);
459*c4762a1bSJed Brown   ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
460*c4762a1bSJed Brown   ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr);
461*c4762a1bSJed Brown   ierr = KSPSetTolerances(ksp,1.e-4,PETSC_DEFAULT,PETSC_DEFAULT,20);CHKERRQ(ierr);
462*c4762a1bSJed Brown 
463*c4762a1bSJed Brown   /*
464*c4762a1bSJed Brown   Set SNES/KSP/KSP/PC runtime options, e.g.,
465*c4762a1bSJed Brown   -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc>
466*c4762a1bSJed Brown   These options will override those specified above as long as
467*c4762a1bSJed Brown   SNESSetFromOptions() is called _after_ any other customization
468*c4762a1bSJed Brown   routines.
469*c4762a1bSJed Brown   */
470*c4762a1bSJed Brown   ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
471*c4762a1bSJed Brown 
472*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
473*c4762a1bSJed Brown   Evaluate initial guess; then solve nonlinear system
474*c4762a1bSJed Brown   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
475*c4762a1bSJed Brown   if (!flg) {
476*c4762a1bSJed Brown     ierr = VecSet(x,pfive);CHKERRQ(ierr);
477*c4762a1bSJed Brown   } else {
478*c4762a1bSJed Brown     Vec *vecs;
479*c4762a1bSJed Brown     ierr = VecNestGetSubVecs(x, NULL, &vecs);CHKERRQ(ierr);
480*c4762a1bSJed Brown     bv   = vecs[0];
481*c4762a1bSJed Brown /*    ierr = VecBlockGetSubVec(x, 0, &bv);CHKERRQ(ierr); */
482*c4762a1bSJed Brown     ierr = VecSetValue(bv, 0, 2.0, INSERT_VALUES);CHKERRQ(ierr);  /* xx[0] = 2.0; */
483*c4762a1bSJed Brown     ierr = VecAssemblyBegin(bv);CHKERRQ(ierr);
484*c4762a1bSJed Brown     ierr = VecAssemblyEnd(bv);CHKERRQ(ierr);
485*c4762a1bSJed Brown 
486*c4762a1bSJed Brown /*    ierr = VecBlockGetSubVec(x, 1, &bv);CHKERRQ(ierr); */
487*c4762a1bSJed Brown     bv   = vecs[1];
488*c4762a1bSJed Brown     ierr = VecSetValue(bv, 0, 3.0, INSERT_VALUES);CHKERRQ(ierr);  /* xx[1] = 3.0; */
489*c4762a1bSJed Brown     ierr = VecAssemblyBegin(bv);CHKERRQ(ierr);
490*c4762a1bSJed Brown     ierr = VecAssemblyEnd(bv);CHKERRQ(ierr);
491*c4762a1bSJed Brown   }
492*c4762a1bSJed Brown   /*
493*c4762a1bSJed Brown   Note: The user should initialize the vector, x, with the initial guess
494*c4762a1bSJed Brown   for the nonlinear solver prior to calling SNESSolve().  In particular,
495*c4762a1bSJed Brown   to employ an initial guess of zero, the user should explicitly set
496*c4762a1bSJed Brown   this vector to zero by calling VecSet().
497*c4762a1bSJed Brown   */
498*c4762a1bSJed Brown   ierr = SNESSolve(snes,NULL,x);CHKERRQ(ierr);
499*c4762a1bSJed Brown   ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr);
500*c4762a1bSJed Brown   if (flg) {
501*c4762a1bSJed Brown     Vec f;
502*c4762a1bSJed Brown     ierr = VecView(x,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
503*c4762a1bSJed Brown     ierr = SNESGetFunction(snes,&f,0,0);CHKERRQ(ierr);
504*c4762a1bSJed Brown     ierr = VecView(r,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
505*c4762a1bSJed Brown   }
506*c4762a1bSJed Brown 
507*c4762a1bSJed Brown   ierr = PetscPrintf(PETSC_COMM_SELF,"number of SNES iterations = %D\n\n",its);CHKERRQ(ierr);
508*c4762a1bSJed Brown 
509*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
510*c4762a1bSJed Brown   Free work space.  All PETSc objects should be destroyed when they
511*c4762a1bSJed Brown   are no longer needed.
512*c4762a1bSJed Brown   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
513*c4762a1bSJed Brown   ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&r);CHKERRQ(ierr);
514*c4762a1bSJed Brown   ierr = MatDestroy(&J);CHKERRQ(ierr); ierr = SNESDestroy(&snes);CHKERRQ(ierr);
515*c4762a1bSJed Brown   PetscFunctionReturn(0);
516*c4762a1bSJed Brown }
517*c4762a1bSJed Brown 
518*c4762a1bSJed Brown /* ------------------------------------------------------------------- */
519*c4762a1bSJed Brown static PetscErrorCode FormFunction1_block(SNES snes,Vec x,Vec f,void *dummy)
520*c4762a1bSJed Brown {
521*c4762a1bSJed Brown   Vec            *xx, *ff, x1,x2, f1,f2;
522*c4762a1bSJed Brown   PetscScalar    ff_0, ff_1;
523*c4762a1bSJed Brown   PetscScalar    xx_0, xx_1;
524*c4762a1bSJed Brown   PetscInt       index,nb;
525*c4762a1bSJed Brown   PetscErrorCode ierr;
526*c4762a1bSJed Brown 
527*c4762a1bSJed Brown   PetscFunctionBeginUser;
528*c4762a1bSJed Brown   /* get blocks for function */
529*c4762a1bSJed Brown   ierr = VecNestGetSubVecs(f, &nb, &ff);CHKERRQ(ierr);
530*c4762a1bSJed Brown   f1   = ff[0];  f2 = ff[1];
531*c4762a1bSJed Brown 
532*c4762a1bSJed Brown   /* get blocks for solution */
533*c4762a1bSJed Brown   ierr = VecNestGetSubVecs(x, &nb, &xx);CHKERRQ(ierr);
534*c4762a1bSJed Brown   x1   = xx[0];  x2 = xx[1];
535*c4762a1bSJed Brown 
536*c4762a1bSJed Brown   /* get solution values */
537*c4762a1bSJed Brown   index = 0;
538*c4762a1bSJed Brown   ierr  = VecGetValues(x1,1, &index, &xx_0);CHKERRQ(ierr);
539*c4762a1bSJed Brown   ierr  = VecGetValues(x2,1, &index, &xx_1);CHKERRQ(ierr);
540*c4762a1bSJed Brown 
541*c4762a1bSJed Brown   /* Compute function */
542*c4762a1bSJed Brown   ff_0 = xx_0*xx_0 + xx_0*xx_1 - 3.0;
543*c4762a1bSJed Brown   ff_1 = xx_0*xx_1 + xx_1*xx_1 - 6.0;
544*c4762a1bSJed Brown 
545*c4762a1bSJed Brown   /* set function values */
546*c4762a1bSJed Brown   ierr = VecSetValue(f1, index, ff_0, INSERT_VALUES);CHKERRQ(ierr);
547*c4762a1bSJed Brown 
548*c4762a1bSJed Brown   ierr = VecSetValue(f2, index, ff_1, INSERT_VALUES);CHKERRQ(ierr);
549*c4762a1bSJed Brown 
550*c4762a1bSJed Brown   ierr = VecAssemblyBegin(f);CHKERRQ(ierr);
551*c4762a1bSJed Brown   ierr = VecAssemblyEnd(f);CHKERRQ(ierr);
552*c4762a1bSJed Brown   PetscFunctionReturn(0);
553*c4762a1bSJed Brown }
554*c4762a1bSJed Brown 
555*c4762a1bSJed Brown /* ------------------------------------------------------------------- */
556*c4762a1bSJed Brown static PetscErrorCode FormJacobian1_block(SNES snes,Vec x,Mat jac,Mat B,void *dummy)
557*c4762a1bSJed Brown {
558*c4762a1bSJed Brown   Vec            *xx, x1,x2;
559*c4762a1bSJed Brown   PetscScalar    xx_0, xx_1;
560*c4762a1bSJed Brown   PetscInt       index,nb;
561*c4762a1bSJed Brown   PetscScalar    A_00, A_01, A_10, A_11;
562*c4762a1bSJed Brown   Mat            j11, j12, j21, j22;
563*c4762a1bSJed Brown   Mat            **mats;
564*c4762a1bSJed Brown   PetscErrorCode ierr;
565*c4762a1bSJed Brown 
566*c4762a1bSJed Brown   PetscFunctionBeginUser;
567*c4762a1bSJed Brown   /* get blocks for solution */
568*c4762a1bSJed Brown   ierr = VecNestGetSubVecs(x, &nb, &xx);CHKERRQ(ierr);
569*c4762a1bSJed Brown   x1   = xx[0];  x2 = xx[1];
570*c4762a1bSJed Brown 
571*c4762a1bSJed Brown   /* get solution values */
572*c4762a1bSJed Brown   index = 0;
573*c4762a1bSJed Brown   ierr  = VecGetValues(x1,1, &index, &xx_0);CHKERRQ(ierr);
574*c4762a1bSJed Brown   ierr  = VecGetValues(x2,1, &index, &xx_1);CHKERRQ(ierr);
575*c4762a1bSJed Brown 
576*c4762a1bSJed Brown   /* get block matrices */
577*c4762a1bSJed Brown   ierr = MatNestGetSubMats(jac,NULL,NULL,&mats);CHKERRQ(ierr);
578*c4762a1bSJed Brown   j11  = mats[0][0];
579*c4762a1bSJed Brown   j12  = mats[0][1];
580*c4762a1bSJed Brown   j21  = mats[1][0];
581*c4762a1bSJed Brown   j22  = mats[1][1];
582*c4762a1bSJed Brown 
583*c4762a1bSJed Brown   /* compute jacobian entries */
584*c4762a1bSJed Brown   A_00 = 2.0*xx_0 + xx_1;
585*c4762a1bSJed Brown   A_01 = xx_0;
586*c4762a1bSJed Brown   A_10 = xx_1;
587*c4762a1bSJed Brown   A_11 = xx_0 + 2.0*xx_1;
588*c4762a1bSJed Brown 
589*c4762a1bSJed Brown   /* set jacobian values */
590*c4762a1bSJed Brown   ierr = MatSetValue(j11, 0,0, A_00, INSERT_VALUES);CHKERRQ(ierr);
591*c4762a1bSJed Brown   ierr = MatSetValue(j12, 0,0, A_01, INSERT_VALUES);CHKERRQ(ierr);
592*c4762a1bSJed Brown   ierr = MatSetValue(j21, 0,0, A_10, INSERT_VALUES);CHKERRQ(ierr);
593*c4762a1bSJed Brown   ierr = MatSetValue(j22, 0,0, A_11, INSERT_VALUES);CHKERRQ(ierr);
594*c4762a1bSJed Brown 
595*c4762a1bSJed Brown   /* Assemble sub matrix */
596*c4762a1bSJed Brown   ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
597*c4762a1bSJed Brown   ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
598*c4762a1bSJed Brown   PetscFunctionReturn(0);
599*c4762a1bSJed Brown }
600*c4762a1bSJed Brown 
601*c4762a1bSJed Brown /* ------------------------------------------------------------------- */
602*c4762a1bSJed Brown static PetscErrorCode FormFunction2_block(SNES snes,Vec x,Vec f,void *dummy)
603*c4762a1bSJed Brown {
604*c4762a1bSJed Brown   PetscErrorCode    ierr;
605*c4762a1bSJed Brown   PetscScalar       *ff;
606*c4762a1bSJed Brown   const PetscScalar *xx;
607*c4762a1bSJed Brown 
608*c4762a1bSJed Brown   PetscFunctionBeginUser;
609*c4762a1bSJed Brown   /*
610*c4762a1bSJed Brown   Get pointers to vector data.
611*c4762a1bSJed Brown   - For default PETSc vectors, VecGetArray() returns a pointer to
612*c4762a1bSJed Brown   the data array.  Otherwise, the routine is implementation dependent.
613*c4762a1bSJed Brown   - You MUST call VecRestoreArray() when you no longer need access to
614*c4762a1bSJed Brown   the array.
615*c4762a1bSJed Brown   */
616*c4762a1bSJed Brown   ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
617*c4762a1bSJed Brown   ierr = VecGetArray(f,&ff);CHKERRQ(ierr);
618*c4762a1bSJed Brown 
619*c4762a1bSJed Brown   /*
620*c4762a1bSJed Brown   Compute function
621*c4762a1bSJed Brown   */
622*c4762a1bSJed Brown   ff[0] = PetscSinScalar(3.0*xx[0]) + xx[0];
623*c4762a1bSJed Brown   ff[1] = xx[1];
624*c4762a1bSJed Brown 
625*c4762a1bSJed Brown   /*
626*c4762a1bSJed Brown   Restore vectors
627*c4762a1bSJed Brown   */
628*c4762a1bSJed Brown   ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
629*c4762a1bSJed Brown   ierr = VecRestoreArray(f,&ff);CHKERRQ(ierr);
630*c4762a1bSJed Brown   PetscFunctionReturn(0);
631*c4762a1bSJed Brown }
632*c4762a1bSJed Brown 
633*c4762a1bSJed Brown /* ------------------------------------------------------------------- */
634*c4762a1bSJed Brown static PetscErrorCode FormJacobian2_block(SNES snes,Vec x,Mat jac,Mat B,void *dummy)
635*c4762a1bSJed Brown {
636*c4762a1bSJed Brown   const PetscScalar *xx;
637*c4762a1bSJed Brown   PetscScalar       A[4];
638*c4762a1bSJed Brown   PetscErrorCode    ierr;
639*c4762a1bSJed Brown   PetscInt          idx[2] = {0,1};
640*c4762a1bSJed Brown 
641*c4762a1bSJed Brown   PetscFunctionBeginUser;
642*c4762a1bSJed Brown   /*
643*c4762a1bSJed Brown   Get pointer to vector data
644*c4762a1bSJed Brown   */
645*c4762a1bSJed Brown   ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
646*c4762a1bSJed Brown 
647*c4762a1bSJed Brown   /*
648*c4762a1bSJed Brown   Compute Jacobian entries and insert into matrix.
649*c4762a1bSJed Brown   - Since this is such a small problem, we set all entries for
650*c4762a1bSJed Brown   the matrix at once.
651*c4762a1bSJed Brown   */
652*c4762a1bSJed Brown   A[0]  = 3.0*PetscCosScalar(3.0*xx[0]) + 1.0; A[1] = 0.0;
653*c4762a1bSJed Brown   A[2]  = 0.0;                     A[3] = 1.0;
654*c4762a1bSJed Brown   ierr  = MatSetValues(jac,2,idx,2,idx,A,INSERT_VALUES);CHKERRQ(ierr);
655*c4762a1bSJed Brown 
656*c4762a1bSJed Brown   /*
657*c4762a1bSJed Brown   Restore vector
658*c4762a1bSJed Brown   */
659*c4762a1bSJed Brown   ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
660*c4762a1bSJed Brown 
661*c4762a1bSJed Brown   /*
662*c4762a1bSJed Brown   Assemble matrix
663*c4762a1bSJed Brown   */
664*c4762a1bSJed Brown   ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
665*c4762a1bSJed Brown   ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
666*c4762a1bSJed Brown   PetscFunctionReturn(0);
667*c4762a1bSJed Brown }
668*c4762a1bSJed Brown 
669*c4762a1bSJed Brown int main(int argc,char **argv)
670*c4762a1bSJed Brown {
671*c4762a1bSJed Brown   PetscMPIInt    size;
672*c4762a1bSJed Brown   PetscErrorCode ierr;
673*c4762a1bSJed Brown 
674*c4762a1bSJed Brown   ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr;
675*c4762a1bSJed Brown 
676*c4762a1bSJed Brown   ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
677*c4762a1bSJed Brown   if (size != 1) SETERRQ(PETSC_COMM_WORLD, 1,"This is a uniprocessor example only!");
678*c4762a1bSJed Brown 
679*c4762a1bSJed Brown   ierr = assembled_system();CHKERRQ(ierr);
680*c4762a1bSJed Brown 
681*c4762a1bSJed Brown   ierr = block_system();CHKERRQ(ierr);
682*c4762a1bSJed Brown 
683*c4762a1bSJed Brown   ierr = PetscFinalize();
684*c4762a1bSJed Brown   return ierr;
685*c4762a1bSJed Brown }
686*c4762a1bSJed Brown 
687*c4762a1bSJed Brown 
688*c4762a1bSJed Brown /*TEST
689*c4762a1bSJed Brown 
690*c4762a1bSJed Brown    test:
691*c4762a1bSJed Brown       args: -snes_monitor_short
692*c4762a1bSJed Brown       requires: !single
693*c4762a1bSJed Brown 
694*c4762a1bSJed Brown TEST*/
695