1c4762a1bSJed Brown static const char help[] = "Newton's method to solve a two-variable system, sequentially.\n" 2c4762a1bSJed Brown "The same problem is solved twice - i) fully assembled system + ii) block system\n\n"; 3c4762a1bSJed Brown 4c4762a1bSJed Brown /*T 5c4762a1bSJed Brown Concepts: SNES^basic uniprocessor example, block objects 6c4762a1bSJed Brown Processors: 1 7c4762a1bSJed Brown T*/ 8c4762a1bSJed Brown 9c4762a1bSJed Brown /* 10c4762a1bSJed Brown Include "petscsnes.h" so that we can use SNES solvers. Note that this 11c4762a1bSJed Brown file automatically includes: 12c4762a1bSJed Brown petscsys.h - base PETSc routines petscvec.h - vectors 13c4762a1bSJed Brown petscsys.h - system routines petscmat.h - matrices 14c4762a1bSJed Brown petscis.h - index sets petscksp.h - Krylov subspace methods 15c4762a1bSJed Brown petscviewer.h - viewers petscpc.h - preconditioners 16c4762a1bSJed Brown petscksp.h - linear solvers 17c4762a1bSJed Brown */ 18c4762a1bSJed Brown #include <petscsnes.h> 19c4762a1bSJed Brown 20c4762a1bSJed Brown /* 21c4762a1bSJed Brown This example is block version of the test found at 22c4762a1bSJed Brown ${PETSC_DIR}/src/snes/tutorials/ex1.c 23c4762a1bSJed Brown In this test we replace the Jacobian systems 24c4762a1bSJed Brown [J]{x} = {F} 25c4762a1bSJed Brown where 26c4762a1bSJed Brown 27c4762a1bSJed Brown [J] = (j_00, j_01), {x} = (x_0, x_1)^T, {F} = (f_0, f_1)^T 28c4762a1bSJed Brown (j_10, j_11) 29c4762a1bSJed Brown where [J] \in \mathbb^{2 \times 2}, {x},{F} \in \mathbb^{2 \times 1}, 30c4762a1bSJed Brown 31c4762a1bSJed Brown with a block system in which each block is of length 1. 32c4762a1bSJed Brown i.e. The block system is thus 33c4762a1bSJed Brown 34c4762a1bSJed Brown [J] = ([j00], [j01]), {x} = ({x0}, {x1})^T, {F} = ({f0}, {f1})^T 35c4762a1bSJed Brown ([j10], [j11]) 36c4762a1bSJed Brown where 37c4762a1bSJed Brown [j00], [j01], [j10], [j11] \in \mathbb^{1 \times 1} 38c4762a1bSJed Brown {x0}, {x1}, {f0}, {f1} \in \mathbb^{1 \times 1} 39c4762a1bSJed Brown 40c4762a1bSJed Brown In practice we would not bother defing blocks of size one, and would instead assemble the 41c4762a1bSJed Brown full system. This is just a simple test to illustrate how to manipulate the blocks and 42c4762a1bSJed Brown to confirm the implementation is correct. 43c4762a1bSJed Brown */ 44c4762a1bSJed Brown 45c4762a1bSJed Brown /* 46c4762a1bSJed Brown User-defined routines 47c4762a1bSJed Brown */ 48c4762a1bSJed Brown static PetscErrorCode FormJacobian1(SNES,Vec,Mat,Mat,void*); 49c4762a1bSJed Brown static PetscErrorCode FormFunction1(SNES,Vec,Vec,void*); 50c4762a1bSJed Brown static PetscErrorCode FormJacobian2(SNES,Vec,Mat,Mat,void*); 51c4762a1bSJed Brown static PetscErrorCode FormFunction2(SNES,Vec,Vec,void*); 52c4762a1bSJed Brown static PetscErrorCode FormJacobian1_block(SNES,Vec,Mat,Mat,void*); 53c4762a1bSJed Brown static PetscErrorCode FormFunction1_block(SNES,Vec,Vec,void*); 54c4762a1bSJed Brown static PetscErrorCode FormJacobian2_block(SNES,Vec,Mat,Mat,void*); 55c4762a1bSJed Brown static PetscErrorCode FormFunction2_block(SNES,Vec,Vec,void*); 56c4762a1bSJed Brown 57c4762a1bSJed Brown static PetscErrorCode assembled_system(void) 58c4762a1bSJed Brown { 59c4762a1bSJed Brown SNES snes; /* nonlinear solver context */ 60c4762a1bSJed Brown KSP ksp; /* linear solver context */ 61c4762a1bSJed Brown PC pc; /* preconditioner context */ 62c4762a1bSJed Brown Vec x,r; /* solution, residual vectors */ 63c4762a1bSJed Brown Mat J; /* Jacobian matrix */ 64c4762a1bSJed Brown PetscInt its; 65c4762a1bSJed Brown PetscScalar pfive = .5,*xx; 66c4762a1bSJed Brown PetscBool flg; 67c4762a1bSJed Brown 68c4762a1bSJed Brown PetscFunctionBeginUser; 699566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\n\n========================= Assembled system =========================\n\n")); 70c4762a1bSJed Brown 71c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 72c4762a1bSJed Brown Create nonlinear solver context 73c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 74c4762a1bSJed Brown 759566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD,&snes)); 76c4762a1bSJed Brown 77c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 78c4762a1bSJed Brown Create matrix and vector data structures; set corresponding routines 79c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 80c4762a1bSJed Brown 81c4762a1bSJed Brown /* 82c4762a1bSJed Brown Create vectors for solution and nonlinear function 83c4762a1bSJed Brown */ 849566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF,2,&x)); 859566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x,&r)); 86c4762a1bSJed Brown 87c4762a1bSJed Brown /* 88c4762a1bSJed Brown Create Jacobian matrix data structure 89c4762a1bSJed Brown */ 909566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF,&J)); 919566063dSJacob Faibussowitsch PetscCall(MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,2,2)); 929566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 939566063dSJacob Faibussowitsch PetscCall(MatSetUp(J)); 94c4762a1bSJed Brown 959566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL,NULL,"-hard",&flg)); 96c4762a1bSJed Brown if (!flg) { 97c4762a1bSJed Brown /* 98c4762a1bSJed Brown Set function evaluation routine and vector. 99c4762a1bSJed Brown */ 1009566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes,r,FormFunction1,NULL)); 101c4762a1bSJed Brown 102c4762a1bSJed Brown /* 103c4762a1bSJed Brown Set Jacobian matrix data structure and Jacobian evaluation routine 104c4762a1bSJed Brown */ 1059566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes,J,J,FormJacobian1,NULL)); 106c4762a1bSJed Brown } else { 1079566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes,r,FormFunction2,NULL)); 1089566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes,J,J,FormJacobian2,NULL)); 109c4762a1bSJed Brown } 110c4762a1bSJed Brown 111c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 112c4762a1bSJed Brown Customize nonlinear solver; set runtime options 113c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 114c4762a1bSJed Brown 115c4762a1bSJed Brown /* 116c4762a1bSJed Brown Set linear solver defaults for this problem. By extracting the 117c4762a1bSJed Brown KSP, KSP, and PC contexts from the SNES context, we can then 118c4762a1bSJed Brown directly call any KSP, KSP, and PC routines to set various options. 119c4762a1bSJed Brown */ 1209566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes,&ksp)); 1219566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp,&pc)); 1229566063dSJacob Faibussowitsch PetscCall(PCSetType(pc,PCNONE)); 1239566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(ksp,1.e-4,PETSC_DEFAULT,PETSC_DEFAULT,20)); 124c4762a1bSJed Brown 125c4762a1bSJed Brown /* 126c4762a1bSJed Brown Set SNES/KSP/KSP/PC runtime options, e.g., 127c4762a1bSJed Brown -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc> 128c4762a1bSJed Brown These options will override those specified above as long as 129c4762a1bSJed Brown SNESSetFromOptions() is called _after_ any other customization 130c4762a1bSJed Brown routines. 131c4762a1bSJed Brown */ 1329566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes)); 133c4762a1bSJed Brown 134c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 135c4762a1bSJed Brown Evaluate initial guess; then solve nonlinear system 136c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 137c4762a1bSJed Brown if (!flg) { 1389566063dSJacob Faibussowitsch PetscCall(VecSet(x,pfive)); 139c4762a1bSJed Brown } else { 1409566063dSJacob Faibussowitsch PetscCall(VecGetArray(x,&xx)); 141c4762a1bSJed Brown xx[0] = 2.0; xx[1] = 3.0; 1429566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(x,&xx)); 143c4762a1bSJed Brown } 144c4762a1bSJed Brown /* 145c4762a1bSJed Brown Note: The user should initialize the vector, x, with the initial guess 146c4762a1bSJed Brown for the nonlinear solver prior to calling SNESSolve(). In particular, 147c4762a1bSJed Brown to employ an initial guess of zero, the user should explicitly set 148c4762a1bSJed Brown this vector to zero by calling VecSet(). 149c4762a1bSJed Brown */ 150c4762a1bSJed Brown 1519566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes,NULL,x)); 1529566063dSJacob Faibussowitsch PetscCall(SNESGetIterationNumber(snes,&its)); 153c4762a1bSJed Brown if (flg) { 154c4762a1bSJed Brown Vec f; 1559566063dSJacob Faibussowitsch PetscCall(VecView(x,PETSC_VIEWER_STDOUT_WORLD)); 1569566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes,&f,0,0)); 1579566063dSJacob Faibussowitsch PetscCall(VecView(r,PETSC_VIEWER_STDOUT_WORLD)); 158c4762a1bSJed Brown } 1599566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF,"number of SNES iterations = %D\n\n",its)); 160c4762a1bSJed Brown 161c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 162c4762a1bSJed Brown Free work space. All PETSc objects should be destroyed when they 163c4762a1bSJed Brown are no longer needed. 164c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 165c4762a1bSJed Brown 1669566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); PetscCall(VecDestroy(&r)); 1679566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); PetscCall(SNESDestroy(&snes)); 168c4762a1bSJed Brown PetscFunctionReturn(0); 169c4762a1bSJed Brown } 170c4762a1bSJed Brown 171c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 172c4762a1bSJed Brown /* 173c4762a1bSJed Brown FormFunction1 - Evaluates nonlinear function, F(x). 174c4762a1bSJed Brown 175c4762a1bSJed Brown Input Parameters: 176c4762a1bSJed Brown . snes - the SNES context 177c4762a1bSJed Brown . x - input vector 178c4762a1bSJed Brown . dummy - optional user-defined context (not used here) 179c4762a1bSJed Brown 180c4762a1bSJed Brown Output Parameter: 181c4762a1bSJed Brown . f - function vector 182c4762a1bSJed Brown */ 183c4762a1bSJed Brown static PetscErrorCode FormFunction1(SNES snes,Vec x,Vec f,void *dummy) 184c4762a1bSJed Brown { 185c4762a1bSJed Brown const PetscScalar *xx; 186c4762a1bSJed Brown PetscScalar *ff; 187c4762a1bSJed Brown 188c4762a1bSJed Brown PetscFunctionBeginUser; 189c4762a1bSJed Brown /* 190c4762a1bSJed Brown Get pointers to vector data. 191c4762a1bSJed Brown - For default PETSc vectors, VecGetArray() returns a pointer to 192c4762a1bSJed Brown the data array. Otherwise, the routine is implementation dependent. 193c4762a1bSJed Brown - You MUST call VecRestoreArray() when you no longer need access to 194c4762a1bSJed Brown the array. 195c4762a1bSJed Brown */ 1969566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x,&xx)); 1979566063dSJacob Faibussowitsch PetscCall(VecGetArray(f,&ff)); 198c4762a1bSJed Brown 199c4762a1bSJed Brown /* 200c4762a1bSJed Brown Compute function 201c4762a1bSJed Brown */ 202c4762a1bSJed Brown ff[0] = xx[0]*xx[0] + xx[0]*xx[1] - 3.0; 203c4762a1bSJed Brown ff[1] = xx[0]*xx[1] + xx[1]*xx[1] - 6.0; 204c4762a1bSJed Brown 205c4762a1bSJed Brown /* 206c4762a1bSJed Brown Restore vectors 207c4762a1bSJed Brown */ 2089566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x,&xx)); 2099566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(f,&ff)); 210c4762a1bSJed Brown PetscFunctionReturn(0); 211c4762a1bSJed Brown } 212c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 213c4762a1bSJed Brown /* 214c4762a1bSJed Brown FormJacobian1 - Evaluates Jacobian matrix. 215c4762a1bSJed Brown 216c4762a1bSJed Brown Input Parameters: 217c4762a1bSJed Brown . snes - the SNES context 218c4762a1bSJed Brown . x - input vector 219c4762a1bSJed Brown . dummy - optional user-defined context (not used here) 220c4762a1bSJed Brown 221c4762a1bSJed Brown Output Parameters: 222c4762a1bSJed Brown . jac - Jacobian matrix 223c4762a1bSJed Brown . B - optionally different preconditioning matrix 224c4762a1bSJed Brown . flag - flag indicating matrix structure 225c4762a1bSJed Brown */ 226c4762a1bSJed Brown static PetscErrorCode FormJacobian1(SNES snes,Vec x,Mat jac,Mat B,void *dummy) 227c4762a1bSJed Brown { 228c4762a1bSJed Brown const PetscScalar *xx; 229c4762a1bSJed Brown PetscScalar A[4]; 230c4762a1bSJed Brown PetscInt idx[2] = {0,1}; 231c4762a1bSJed Brown 232c4762a1bSJed Brown PetscFunctionBeginUser; 233c4762a1bSJed Brown /* 234c4762a1bSJed Brown Get pointer to vector data 235c4762a1bSJed Brown */ 2369566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x,&xx)); 237c4762a1bSJed Brown 238c4762a1bSJed Brown /* 239c4762a1bSJed Brown Compute Jacobian entries and insert into matrix. 240c4762a1bSJed Brown - Since this is such a small problem, we set all entries for 241c4762a1bSJed Brown the matrix at once. 242c4762a1bSJed Brown */ 243c4762a1bSJed Brown A[0] = 2.0*xx[0] + xx[1]; A[1] = xx[0]; 244c4762a1bSJed Brown A[2] = xx[1]; A[3] = xx[0] + 2.0*xx[1]; 2459566063dSJacob Faibussowitsch PetscCall(MatSetValues(jac,2,idx,2,idx,A,INSERT_VALUES)); 246c4762a1bSJed Brown 247c4762a1bSJed Brown /* 248c4762a1bSJed Brown Restore vector 249c4762a1bSJed Brown */ 2509566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x,&xx)); 251c4762a1bSJed Brown 252c4762a1bSJed Brown /* 253c4762a1bSJed Brown Assemble matrix 254c4762a1bSJed Brown */ 2559566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY)); 2569566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY)); 257c4762a1bSJed Brown PetscFunctionReturn(0); 258c4762a1bSJed Brown } 259c4762a1bSJed Brown 260c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 261c4762a1bSJed Brown static PetscErrorCode FormFunction2(SNES snes,Vec x,Vec f,void *dummy) 262c4762a1bSJed Brown { 263c4762a1bSJed Brown const PetscScalar *xx; 264c4762a1bSJed Brown PetscScalar *ff; 265c4762a1bSJed Brown 266c4762a1bSJed Brown PetscFunctionBeginUser; 267c4762a1bSJed Brown /* 268c4762a1bSJed Brown Get pointers to vector data. 269c4762a1bSJed Brown - For default PETSc vectors, VecGetArray() returns a pointer to 270c4762a1bSJed Brown the data array. Otherwise, the routine is implementation dependent. 271c4762a1bSJed Brown - You MUST call VecRestoreArray() when you no longer need access to 272c4762a1bSJed Brown the array. 273c4762a1bSJed Brown */ 2749566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x,&xx)); 2759566063dSJacob Faibussowitsch PetscCall(VecGetArray(f,&ff)); 276c4762a1bSJed Brown 277c4762a1bSJed Brown /* 278c4762a1bSJed Brown Compute function 279c4762a1bSJed Brown */ 280c4762a1bSJed Brown ff[0] = PetscSinScalar(3.0*xx[0]) + xx[0]; 281c4762a1bSJed Brown ff[1] = xx[1]; 282c4762a1bSJed Brown 283c4762a1bSJed Brown /* 284c4762a1bSJed Brown Restore vectors 285c4762a1bSJed Brown */ 2869566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x,&xx)); 2879566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(f,&ff)); 288c4762a1bSJed Brown PetscFunctionReturn(0); 289c4762a1bSJed Brown } 290c4762a1bSJed Brown 291c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 292c4762a1bSJed Brown static PetscErrorCode FormJacobian2(SNES snes,Vec x,Mat jac,Mat B,void *dummy) 293c4762a1bSJed Brown { 294c4762a1bSJed Brown const PetscScalar *xx; 295c4762a1bSJed Brown PetscScalar A[4]; 296c4762a1bSJed Brown PetscInt idx[2] = {0,1}; 297c4762a1bSJed Brown 298c4762a1bSJed Brown PetscFunctionBeginUser; 299c4762a1bSJed Brown /* 300c4762a1bSJed Brown Get pointer to vector data 301c4762a1bSJed Brown */ 3029566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x,&xx)); 303c4762a1bSJed Brown 304c4762a1bSJed Brown /* 305c4762a1bSJed Brown Compute Jacobian entries and insert into matrix. 306c4762a1bSJed Brown - Since this is such a small problem, we set all entries for 307c4762a1bSJed Brown the matrix at once. 308c4762a1bSJed Brown */ 309c4762a1bSJed Brown A[0] = 3.0*PetscCosScalar(3.0*xx[0]) + 1.0; A[1] = 0.0; 310c4762a1bSJed Brown A[2] = 0.0; A[3] = 1.0; 3119566063dSJacob Faibussowitsch PetscCall(MatSetValues(jac,2,idx,2,idx,A,INSERT_VALUES)); 312c4762a1bSJed Brown 313c4762a1bSJed Brown /* 314c4762a1bSJed Brown Restore vector 315c4762a1bSJed Brown */ 3169566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x,&xx)); 317c4762a1bSJed Brown 318c4762a1bSJed Brown /* 319c4762a1bSJed Brown Assemble matrix 320c4762a1bSJed Brown */ 3219566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY)); 3229566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY)); 323c4762a1bSJed Brown PetscFunctionReturn(0); 324c4762a1bSJed Brown } 325c4762a1bSJed Brown 326b5675b0fSBarry Smith static PetscErrorCode block_system(void) 327c4762a1bSJed Brown { 328c4762a1bSJed Brown SNES snes; /* nonlinear solver context */ 329c4762a1bSJed Brown KSP ksp; /* linear solver context */ 330c4762a1bSJed Brown PC pc; /* preconditioner context */ 331c4762a1bSJed Brown Vec x,r; /* solution, residual vectors */ 332c4762a1bSJed Brown Mat J; /* Jacobian matrix */ 333c4762a1bSJed Brown PetscInt its; 334c4762a1bSJed Brown PetscScalar pfive = .5; 335c4762a1bSJed Brown PetscBool flg; 336c4762a1bSJed Brown 337c4762a1bSJed Brown Mat j11, j12, j21, j22; 338c4762a1bSJed Brown Vec x1, x2, r1, r2; 339c4762a1bSJed Brown Vec bv; 340c4762a1bSJed Brown Vec bx[2]; 341c4762a1bSJed Brown Mat bA[2][2]; 342c4762a1bSJed Brown 343c4762a1bSJed Brown PetscFunctionBeginUser; 3449566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\n\n========================= Block system =========================\n\n")); 345c4762a1bSJed Brown 3469566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD,&snes)); 347c4762a1bSJed Brown 348c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 349c4762a1bSJed Brown Create matrix and vector data structures; set corresponding routines 350c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 351c4762a1bSJed Brown 352c4762a1bSJed Brown /* 353c4762a1bSJed Brown Create sub vectors for solution and nonlinear function 354c4762a1bSJed Brown */ 3559566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF,1,&x1)); 3569566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x1,&r1)); 357c4762a1bSJed Brown 3589566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF,1,&x2)); 3599566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x2,&r2)); 360c4762a1bSJed Brown 361c4762a1bSJed Brown /* 362c4762a1bSJed Brown Create the block vectors 363c4762a1bSJed Brown */ 364c4762a1bSJed Brown bx[0] = x1; 365c4762a1bSJed Brown bx[1] = x2; 3669566063dSJacob Faibussowitsch PetscCall(VecCreateNest(PETSC_COMM_WORLD,2,NULL,bx,&x)); 3679566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(x)); 3689566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(x)); 3699566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x1)); 3709566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x2)); 371c4762a1bSJed Brown 372c4762a1bSJed Brown bx[0] = r1; 373c4762a1bSJed Brown bx[1] = r2; 3749566063dSJacob Faibussowitsch PetscCall(VecCreateNest(PETSC_COMM_WORLD,2,NULL,bx,&r)); 3759566063dSJacob Faibussowitsch PetscCall(VecDestroy(&r1)); 3769566063dSJacob Faibussowitsch PetscCall(VecDestroy(&r2)); 3779566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(r)); 3789566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(r)); 379c4762a1bSJed Brown 380c4762a1bSJed Brown /* 381c4762a1bSJed Brown Create sub Jacobian matrix data structure 382c4762a1bSJed Brown */ 3839566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &j11)); 3849566063dSJacob Faibussowitsch PetscCall(MatSetSizes(j11, 1, 1, 1, 1)); 3859566063dSJacob Faibussowitsch PetscCall(MatSetType(j11, MATSEQAIJ)); 3869566063dSJacob Faibussowitsch PetscCall(MatSetUp(j11)); 387c4762a1bSJed Brown 3889566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &j12)); 3899566063dSJacob Faibussowitsch PetscCall(MatSetSizes(j12, 1, 1, 1, 1)); 3909566063dSJacob Faibussowitsch PetscCall(MatSetType(j12, MATSEQAIJ)); 3919566063dSJacob Faibussowitsch PetscCall(MatSetUp(j12)); 392c4762a1bSJed Brown 3939566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &j21)); 3949566063dSJacob Faibussowitsch PetscCall(MatSetSizes(j21, 1, 1, 1, 1)); 3959566063dSJacob Faibussowitsch PetscCall(MatSetType(j21, MATSEQAIJ)); 3969566063dSJacob Faibussowitsch PetscCall(MatSetUp(j21)); 397c4762a1bSJed Brown 3989566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &j22)); 3999566063dSJacob Faibussowitsch PetscCall(MatSetSizes(j22, PETSC_DECIDE, PETSC_DECIDE, 1, 1)); 4009566063dSJacob Faibussowitsch PetscCall(MatSetType(j22, MATSEQAIJ)); 4019566063dSJacob Faibussowitsch PetscCall(MatSetUp(j22)); 402c4762a1bSJed Brown /* 403c4762a1bSJed Brown Create block Jacobian matrix data structure 404c4762a1bSJed Brown */ 405c4762a1bSJed Brown bA[0][0] = j11; 406c4762a1bSJed Brown bA[0][1] = j12; 407c4762a1bSJed Brown bA[1][0] = j21; 408c4762a1bSJed Brown bA[1][1] = j22; 409c4762a1bSJed Brown 4109566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PETSC_COMM_WORLD,2,NULL,2,NULL,&bA[0][0],&J)); 4119566063dSJacob Faibussowitsch PetscCall(MatSetUp(J)); 4129566063dSJacob Faibussowitsch PetscCall(MatNestSetVecType(J,VECNEST)); 4139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&j11)); 4149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&j12)); 4159566063dSJacob Faibussowitsch PetscCall(MatDestroy(&j21)); 4169566063dSJacob Faibussowitsch PetscCall(MatDestroy(&j22)); 417c4762a1bSJed Brown 4189566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY)); 4199566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY)); 420c4762a1bSJed Brown 4219566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL,NULL,"-hard",&flg)); 422c4762a1bSJed Brown if (!flg) { 423c4762a1bSJed Brown /* 424c4762a1bSJed Brown Set function evaluation routine and vector. 425c4762a1bSJed Brown */ 4269566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes,r,FormFunction1_block,NULL)); 427c4762a1bSJed Brown 428c4762a1bSJed Brown /* 429c4762a1bSJed Brown Set Jacobian matrix data structure and Jacobian evaluation routine 430c4762a1bSJed Brown */ 4319566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes,J,J,FormJacobian1_block,NULL)); 432c4762a1bSJed Brown } else { 4339566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes,r,FormFunction2_block,NULL)); 4349566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes,J,J,FormJacobian2_block,NULL)); 435c4762a1bSJed Brown } 436c4762a1bSJed Brown 437c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 438c4762a1bSJed Brown Customize nonlinear solver; set runtime options 439c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 440c4762a1bSJed Brown 441c4762a1bSJed Brown /* 442c4762a1bSJed Brown Set linear solver defaults for this problem. By extracting the 443c4762a1bSJed Brown KSP, KSP, and PC contexts from the SNES context, we can then 444c4762a1bSJed Brown directly call any KSP, KSP, and PC routines to set various options. 445c4762a1bSJed Brown */ 4469566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes,&ksp)); 4479566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp,&pc)); 4489566063dSJacob Faibussowitsch PetscCall(PCSetType(pc,PCNONE)); 4499566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(ksp,1.e-4,PETSC_DEFAULT,PETSC_DEFAULT,20)); 450c4762a1bSJed Brown 451c4762a1bSJed Brown /* 452c4762a1bSJed Brown Set SNES/KSP/KSP/PC runtime options, e.g., 453c4762a1bSJed Brown -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc> 454c4762a1bSJed Brown These options will override those specified above as long as 455c4762a1bSJed Brown SNESSetFromOptions() is called _after_ any other customization 456c4762a1bSJed Brown routines. 457c4762a1bSJed Brown */ 4589566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes)); 459c4762a1bSJed Brown 460c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 461c4762a1bSJed Brown Evaluate initial guess; then solve nonlinear system 462c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 463c4762a1bSJed Brown if (!flg) { 4649566063dSJacob Faibussowitsch PetscCall(VecSet(x,pfive)); 465c4762a1bSJed Brown } else { 466c4762a1bSJed Brown Vec *vecs; 4679566063dSJacob Faibussowitsch PetscCall(VecNestGetSubVecs(x, NULL, &vecs)); 468c4762a1bSJed Brown bv = vecs[0]; 4699566063dSJacob Faibussowitsch /* PetscCall(VecBlockGetSubVec(x, 0, &bv)); */ 4709566063dSJacob Faibussowitsch PetscCall(VecSetValue(bv, 0, 2.0, INSERT_VALUES)); /* xx[0] = 2.0; */ 4719566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(bv)); 4729566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(bv)); 473c4762a1bSJed Brown 4749566063dSJacob Faibussowitsch /* PetscCall(VecBlockGetSubVec(x, 1, &bv)); */ 475c4762a1bSJed Brown bv = vecs[1]; 4769566063dSJacob Faibussowitsch PetscCall(VecSetValue(bv, 0, 3.0, INSERT_VALUES)); /* xx[1] = 3.0; */ 4779566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(bv)); 4789566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(bv)); 479c4762a1bSJed Brown } 480c4762a1bSJed Brown /* 481c4762a1bSJed Brown Note: The user should initialize the vector, x, with the initial guess 482c4762a1bSJed Brown for the nonlinear solver prior to calling SNESSolve(). In particular, 483c4762a1bSJed Brown to employ an initial guess of zero, the user should explicitly set 484c4762a1bSJed Brown this vector to zero by calling VecSet(). 485c4762a1bSJed Brown */ 4869566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes,NULL,x)); 4879566063dSJacob Faibussowitsch PetscCall(SNESGetIterationNumber(snes,&its)); 488c4762a1bSJed Brown if (flg) { 489c4762a1bSJed Brown Vec f; 4909566063dSJacob Faibussowitsch PetscCall(VecView(x,PETSC_VIEWER_STDOUT_WORLD)); 4919566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes,&f,0,0)); 4929566063dSJacob Faibussowitsch PetscCall(VecView(r,PETSC_VIEWER_STDOUT_WORLD)); 493c4762a1bSJed Brown } 494c4762a1bSJed Brown 4959566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF,"number of SNES iterations = %D\n\n",its)); 496c4762a1bSJed Brown 497c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 498c4762a1bSJed Brown Free work space. All PETSc objects should be destroyed when they 499c4762a1bSJed Brown are no longer needed. 500c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 5019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); PetscCall(VecDestroy(&r)); 5029566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); PetscCall(SNESDestroy(&snes)); 503c4762a1bSJed Brown PetscFunctionReturn(0); 504c4762a1bSJed Brown } 505c4762a1bSJed Brown 506c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 507c4762a1bSJed Brown static PetscErrorCode FormFunction1_block(SNES snes,Vec x,Vec f,void *dummy) 508c4762a1bSJed Brown { 509c4762a1bSJed Brown Vec *xx, *ff, x1,x2, f1,f2; 510c4762a1bSJed Brown PetscScalar ff_0, ff_1; 511c4762a1bSJed Brown PetscScalar xx_0, xx_1; 512c4762a1bSJed Brown PetscInt index,nb; 513c4762a1bSJed Brown 514c4762a1bSJed Brown PetscFunctionBeginUser; 515c4762a1bSJed Brown /* get blocks for function */ 5169566063dSJacob Faibussowitsch PetscCall(VecNestGetSubVecs(f, &nb, &ff)); 517c4762a1bSJed Brown f1 = ff[0]; f2 = ff[1]; 518c4762a1bSJed Brown 519c4762a1bSJed Brown /* get blocks for solution */ 5209566063dSJacob Faibussowitsch PetscCall(VecNestGetSubVecs(x, &nb, &xx)); 521c4762a1bSJed Brown x1 = xx[0]; x2 = xx[1]; 522c4762a1bSJed Brown 523c4762a1bSJed Brown /* get solution values */ 524c4762a1bSJed Brown index = 0; 5259566063dSJacob Faibussowitsch PetscCall(VecGetValues(x1,1, &index, &xx_0)); 5269566063dSJacob Faibussowitsch PetscCall(VecGetValues(x2,1, &index, &xx_1)); 527c4762a1bSJed Brown 528c4762a1bSJed Brown /* Compute function */ 529c4762a1bSJed Brown ff_0 = xx_0*xx_0 + xx_0*xx_1 - 3.0; 530c4762a1bSJed Brown ff_1 = xx_0*xx_1 + xx_1*xx_1 - 6.0; 531c4762a1bSJed Brown 532c4762a1bSJed Brown /* set function values */ 5339566063dSJacob Faibussowitsch PetscCall(VecSetValue(f1, index, ff_0, INSERT_VALUES)); 534c4762a1bSJed Brown 5359566063dSJacob Faibussowitsch PetscCall(VecSetValue(f2, index, ff_1, INSERT_VALUES)); 536c4762a1bSJed Brown 5379566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(f)); 5389566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(f)); 539c4762a1bSJed Brown PetscFunctionReturn(0); 540c4762a1bSJed Brown } 541c4762a1bSJed Brown 542c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 543c4762a1bSJed Brown static PetscErrorCode FormJacobian1_block(SNES snes,Vec x,Mat jac,Mat B,void *dummy) 544c4762a1bSJed Brown { 545c4762a1bSJed Brown Vec *xx, x1,x2; 546c4762a1bSJed Brown PetscScalar xx_0, xx_1; 547c4762a1bSJed Brown PetscInt index,nb; 548c4762a1bSJed Brown PetscScalar A_00, A_01, A_10, A_11; 549c4762a1bSJed Brown Mat j11, j12, j21, j22; 550c4762a1bSJed Brown Mat **mats; 551c4762a1bSJed Brown 552c4762a1bSJed Brown PetscFunctionBeginUser; 553c4762a1bSJed Brown /* get blocks for solution */ 5549566063dSJacob Faibussowitsch PetscCall(VecNestGetSubVecs(x, &nb, &xx)); 555c4762a1bSJed Brown x1 = xx[0]; x2 = xx[1]; 556c4762a1bSJed Brown 557c4762a1bSJed Brown /* get solution values */ 558c4762a1bSJed Brown index = 0; 5599566063dSJacob Faibussowitsch PetscCall(VecGetValues(x1,1, &index, &xx_0)); 5609566063dSJacob Faibussowitsch PetscCall(VecGetValues(x2,1, &index, &xx_1)); 561c4762a1bSJed Brown 562c4762a1bSJed Brown /* get block matrices */ 5639566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(jac,NULL,NULL,&mats)); 564c4762a1bSJed Brown j11 = mats[0][0]; 565c4762a1bSJed Brown j12 = mats[0][1]; 566c4762a1bSJed Brown j21 = mats[1][0]; 567c4762a1bSJed Brown j22 = mats[1][1]; 568c4762a1bSJed Brown 569c4762a1bSJed Brown /* compute jacobian entries */ 570c4762a1bSJed Brown A_00 = 2.0*xx_0 + xx_1; 571c4762a1bSJed Brown A_01 = xx_0; 572c4762a1bSJed Brown A_10 = xx_1; 573c4762a1bSJed Brown A_11 = xx_0 + 2.0*xx_1; 574c4762a1bSJed Brown 575c4762a1bSJed Brown /* set jacobian values */ 5769566063dSJacob Faibussowitsch PetscCall(MatSetValue(j11, 0,0, A_00, INSERT_VALUES)); 5779566063dSJacob Faibussowitsch PetscCall(MatSetValue(j12, 0,0, A_01, INSERT_VALUES)); 5789566063dSJacob Faibussowitsch PetscCall(MatSetValue(j21, 0,0, A_10, INSERT_VALUES)); 5799566063dSJacob Faibussowitsch PetscCall(MatSetValue(j22, 0,0, A_11, INSERT_VALUES)); 580c4762a1bSJed Brown 581c4762a1bSJed Brown /* Assemble sub matrix */ 5829566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY)); 5839566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY)); 584c4762a1bSJed Brown PetscFunctionReturn(0); 585c4762a1bSJed Brown } 586c4762a1bSJed Brown 587c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 588c4762a1bSJed Brown static PetscErrorCode FormFunction2_block(SNES snes,Vec x,Vec f,void *dummy) 589c4762a1bSJed Brown { 590c4762a1bSJed Brown PetscScalar *ff; 591c4762a1bSJed Brown const PetscScalar *xx; 592c4762a1bSJed Brown 593c4762a1bSJed Brown PetscFunctionBeginUser; 594c4762a1bSJed Brown /* 595c4762a1bSJed Brown Get pointers to vector data. 596c4762a1bSJed Brown - For default PETSc vectors, VecGetArray() returns a pointer to 597c4762a1bSJed Brown the data array. Otherwise, the routine is implementation dependent. 598c4762a1bSJed Brown - You MUST call VecRestoreArray() when you no longer need access to 599c4762a1bSJed Brown the array. 600c4762a1bSJed Brown */ 6019566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x,&xx)); 6029566063dSJacob Faibussowitsch PetscCall(VecGetArray(f,&ff)); 603c4762a1bSJed Brown 604c4762a1bSJed Brown /* 605c4762a1bSJed Brown Compute function 606c4762a1bSJed Brown */ 607c4762a1bSJed Brown ff[0] = PetscSinScalar(3.0*xx[0]) + xx[0]; 608c4762a1bSJed Brown ff[1] = xx[1]; 609c4762a1bSJed Brown 610c4762a1bSJed Brown /* 611c4762a1bSJed Brown Restore vectors 612c4762a1bSJed Brown */ 6139566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x,&xx)); 6149566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(f,&ff)); 615c4762a1bSJed Brown PetscFunctionReturn(0); 616c4762a1bSJed Brown } 617c4762a1bSJed Brown 618c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 619c4762a1bSJed Brown static PetscErrorCode FormJacobian2_block(SNES snes,Vec x,Mat jac,Mat B,void *dummy) 620c4762a1bSJed Brown { 621c4762a1bSJed Brown const PetscScalar *xx; 622c4762a1bSJed Brown PetscScalar A[4]; 623c4762a1bSJed Brown PetscInt idx[2] = {0,1}; 624c4762a1bSJed Brown 625c4762a1bSJed Brown PetscFunctionBeginUser; 626c4762a1bSJed Brown /* 627c4762a1bSJed Brown Get pointer to vector data 628c4762a1bSJed Brown */ 6299566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x,&xx)); 630c4762a1bSJed Brown 631c4762a1bSJed Brown /* 632c4762a1bSJed Brown Compute Jacobian entries and insert into matrix. 633c4762a1bSJed Brown - Since this is such a small problem, we set all entries for 634c4762a1bSJed Brown the matrix at once. 635c4762a1bSJed Brown */ 636c4762a1bSJed Brown A[0] = 3.0*PetscCosScalar(3.0*xx[0]) + 1.0; A[1] = 0.0; 637c4762a1bSJed Brown A[2] = 0.0; A[3] = 1.0; 6389566063dSJacob Faibussowitsch PetscCall(MatSetValues(jac,2,idx,2,idx,A,INSERT_VALUES)); 639c4762a1bSJed Brown 640c4762a1bSJed Brown /* 641c4762a1bSJed Brown Restore vector 642c4762a1bSJed Brown */ 6439566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x,&xx)); 644c4762a1bSJed Brown 645c4762a1bSJed Brown /* 646c4762a1bSJed Brown Assemble matrix 647c4762a1bSJed Brown */ 6489566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY)); 6499566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY)); 650c4762a1bSJed Brown PetscFunctionReturn(0); 651c4762a1bSJed Brown } 652c4762a1bSJed Brown 653c4762a1bSJed Brown int main(int argc,char **argv) 654c4762a1bSJed Brown { 655c4762a1bSJed Brown PetscMPIInt size; 656c4762a1bSJed Brown 6579566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc,&argv,(char*)0,help)); 6589566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size)); 659*be096a46SBarry Smith PetscCheck(size == 1,PETSC_COMM_WORLD, PETSC_ERR_WRONG_MPI_SIZE,"This is a uniprocessor example only!"); 6609566063dSJacob Faibussowitsch PetscCall(assembled_system()); 6619566063dSJacob Faibussowitsch PetscCall(block_system()); 6629566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 663b122ec5aSJacob Faibussowitsch return 0; 664c4762a1bSJed Brown } 665c4762a1bSJed Brown 666c4762a1bSJed Brown /*TEST 667c4762a1bSJed Brown 668c4762a1bSJed Brown test: 669c4762a1bSJed Brown args: -snes_monitor_short 670c4762a1bSJed Brown requires: !single 671c4762a1bSJed Brown 672c4762a1bSJed Brown TEST*/ 673