static PetscErrorCode FormFunction1_block(SNES snes,Vec x,Vec f,void *dummy) { Vec *xx, *ff, x1,x2, f1,f2; PetscScalar ff_0, ff_1; PetscScalar xx_0, xx_1; PetscInt index,nb; PetscErrorCode ierr; PetscFunctionBegin; /* get blocks for function */ ierr = VecNestGetSubVecs( f, &nb, &ff ); CHKERRQ(ierr); f1 = ff[0]; f2 = ff[1]; /* get blocks for solution */ ierr = VecNestGetSubVecs( x, &nb, &xx ); CHKERRQ(ierr); x1 = xx[0]; x2 = xx[1]; /* get solution values */ index = 0; ierr = VecGetValues( x1,1, &index, &xx_0 ); CHKERRQ(ierr); ierr = VecGetValues( x2,1, &index, &xx_1 ); CHKERRQ(ierr); /* Compute function */ ff_0 = xx_0*xx_0 + xx_0*xx_1 - 3.0; ff_1 = xx_0*xx_1 + xx_1*xx_1 - 6.0; /* set function values */ ierr = VecSetValue( f1, index, ff_0, INSERT_VALUES ); CHKERRQ(ierr); ierr = VecSetValue( f2, index, ff_1, INSERT_VALUES ); CHKERRQ(ierr); ierr = VecAssemblyBegin(f); CHKERRQ(ierr); ierr = VecAssemblyEnd(f); CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode FormJacobian1_block(SNES snes,Vec x,Mat *jac,Mat *B,MatStructure *flag,void *dummy) { Vec *xx, x1,x2; PetscScalar xx_0, xx_1; PetscInt index,nb; PetscScalar A_00, A_01, A_10, A_11; Mat j11, j12, j21, j22; Mat **mats; PetscErrorCode ierr; PetscFunctionBegin; /* get blocks for solution */ ierr = VecNestGetSubVecs( x, &nb, &xx ); CHKERRQ(ierr); x1 = xx[0]; x2 = xx[1]; /* get solution values */ index = 0; ierr = VecGetValues( x1,1, &index, &xx_0 ); CHKERRQ(ierr); ierr = VecGetValues( x2,1, &index, &xx_1 ); CHKERRQ(ierr); /* get block matrices */ ierr = MatNestGetSubMats(*jac,PETSC_NULL,PETSC_NULL,&mats); CHKERRQ(ierr); j11 = mats[0][0]; j12 = mats[0][1]; j21 = mats[1][0]; j22 = mats[1][1]; /* compute jacobian entries */ A_00 = 2.0*xx_0 + xx_1; A_01 = xx_0; A_10 = xx_1; A_11 = xx_0 + 2.0*xx_1; /* set jacobian values */ ierr = MatSetValue( j11, 0,0, A_00, INSERT_VALUES); CHKERRQ(ierr); ierr = MatSetValue( j12, 0,0, A_01, INSERT_VALUES); CHKERRQ(ierr); ierr = MatSetValue( j21, 0,0, A_10, INSERT_VALUES); CHKERRQ(ierr); ierr = MatSetValue( j22, 0,0, A_11, INSERT_VALUES); CHKERRQ(ierr); *flag = SAME_NONZERO_PATTERN; /* Assemble sub matrix */ ierr = MatAssemblyBegin(*jac,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = MatAssemblyEnd(*jac,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode test_solve(void) { Mat A11, A12,A21,A22, A, tmp[2][2]; KSP ksp; PC pc; Vec b,x, f,h, diag, x1,x2; Vec tmp_x[2],*_tmp_x; int n, np, i,j; PetscErrorCode ierr; PetscFunctionBeginUser; PetscPrintf(PETSC_COMM_WORLD, "%s \n", PETSC_FUNCTION_NAME); n = 3; np = 2; /* Create matrices */ /* A11 */ ierr = VecCreate(PETSC_COMM_WORLD, &diag);CHKERRQ(ierr); ierr = VecSetSizes(diag, PETSC_DECIDE, n);CHKERRQ(ierr); ierr = VecSetFromOptions(diag);CHKERRQ(ierr); ierr = VecSet(diag, (1.0/10.0));CHKERRQ(ierr); /* so inverse = diag(10) */ /* As a test, create a diagonal matrix for A11 */ ierr = MatCreate(PETSC_COMM_WORLD, &A11);CHKERRQ(ierr); ierr = MatSetSizes(A11, PETSC_DECIDE, PETSC_DECIDE, n, n);CHKERRQ(ierr); ierr = MatSetType(A11, MATAIJ);CHKERRQ(ierr); ierr = MatSeqAIJSetPreallocation(A11, n, NULL);CHKERRQ(ierr); ierr = MatMPIAIJSetPreallocation(A11, np, NULL,np, NULL);CHKERRQ(ierr); ierr = MatDiagonalSet(A11, diag, INSERT_VALUES);CHKERRQ(ierr); ierr = VecDestroy(&diag);CHKERRQ(ierr); /* A12 */ ierr = MatCreate(PETSC_COMM_WORLD, &A12);CHKERRQ(ierr); ierr = MatSetSizes(A12, PETSC_DECIDE, PETSC_DECIDE, n, np);CHKERRQ(ierr); ierr = MatSetType(A12, MATAIJ);CHKERRQ(ierr); ierr = MatSeqAIJSetPreallocation(A12, np, NULL);CHKERRQ(ierr); ierr = MatMPIAIJSetPreallocation(A12, np, NULL,np, NULL);CHKERRQ(ierr); for (i=0; i<n; i++) { for (j=0; j<np; j++) { ierr = MatSetValue(A12, i,j, (PetscScalar)(i+j*n), INSERT_VALUES);CHKERRQ(ierr); } } ierr = MatSetValue(A12, 2,1, (PetscScalar)(4), INSERT_VALUES);CHKERRQ(ierr); ierr = MatAssemblyBegin(A12, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A12, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* A21 */ ierr = MatTranspose(A12, MAT_INITIAL_MATRIX, &A21);CHKERRQ(ierr); A22 = NULL; /* Create block matrix */ tmp[0][0] = A11; tmp[0][1] = A12; tmp[1][0] = A21; tmp[1][1] = A22; ierr = MatCreateNest(PETSC_COMM_WORLD,2,NULL,2,NULL,&tmp[0][0],&A);CHKERRQ(ierr); ierr = MatNestSetVecType(A,VECNEST);CHKERRQ(ierr); ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* Create vectors */ ierr = MatCreateVecs(A12, &h, &f);CHKERRQ(ierr); ierr = VecSet(f, 1.0);CHKERRQ(ierr); ierr = VecSet(h, 0.0);CHKERRQ(ierr); /* Create block vector */ tmp_x[0] = f; tmp_x[1] = h; ierr = VecCreateNest(PETSC_COMM_WORLD,2,NULL,tmp_x,&b);CHKERRQ(ierr); ierr = VecAssemblyBegin(b);CHKERRQ(ierr); ierr = VecAssemblyEnd(b);CHKERRQ(ierr); ierr = VecDuplicate(b, &x);CHKERRQ(ierr); ierr = KSPCreate(PETSC_COMM_WORLD, &ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp, A, A);CHKERRQ(ierr); ierr = KSPSetType(ksp, "gmres");CHKERRQ(ierr); ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); ierr = PCSetType(pc, "none");CHKERRQ(ierr); ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); ierr = KSPSolve(ksp, b, x);CHKERRQ(ierr); ierr = VecNestGetSubVecs(x,NULL,&_tmp_x);CHKERRQ(ierr); x1 = _tmp_x[0]; x2 = _tmp_x[1]; PetscPrintf(PETSC_COMM_WORLD, "x1 \n"); PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); ierr = VecView(x1, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); PetscPrintf(PETSC_COMM_WORLD, "x2 \n"); ierr = VecView(x2, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = KSPDestroy(&ksp);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = MatDestroy(&A11);CHKERRQ(ierr); ierr = MatDestroy(&A12);CHKERRQ(ierr); ierr = MatDestroy(&A21);CHKERRQ(ierr); ierr = VecDestroy(&f);CHKERRQ(ierr); ierr = VecDestroy(&h);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); PetscFunctionReturn(0); }
static int block_system(void) { SNES snes; /* nonlinear solver context */ KSP ksp; /* linear solver context */ PC pc; /* preconditioner context */ Vec x,r; /* solution, residual vectors */ Mat J; /* Jacobian matrix */ PetscErrorCode ierr; PetscInt its; PetscScalar pfive = .5; PetscBool flg; Mat j11, j12, j21, j22; Vec x1, x2, r1, r2; Vec bv; Vec bx[2]; Mat bA[2][2]; PetscFunctionBegin; PetscPrintf( PETSC_COMM_WORLD, "\n\n========================= Block system =========================\n\n" ); ierr = SNESCreate(PETSC_COMM_WORLD,&snes); CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create matrix and vector data structures; set corresponding routines - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Create sub vectors for solution and nonlinear function */ ierr = VecCreateSeq(PETSC_COMM_SELF,1,&x1); CHKERRQ(ierr); ierr = VecDuplicate(x1,&r1); CHKERRQ(ierr); ierr = VecCreateSeq(PETSC_COMM_SELF,1,&x2); CHKERRQ(ierr); ierr = VecDuplicate(x2,&r2); CHKERRQ(ierr); /* Create the block vectors */ bx[0] = x1; bx[1] = x2; ierr = VecCreateNest(PETSC_COMM_WORLD,2,PETSC_NULL,bx,&x); CHKERRQ(ierr); ierr = VecAssemblyBegin(x); CHKERRQ(ierr); ierr = VecAssemblyEnd(x); CHKERRQ(ierr); ierr = VecDestroy(&x1); CHKERRQ(ierr); ierr = VecDestroy(&x2); CHKERRQ(ierr); bx[0] = r1; bx[1] = r2; ierr = VecCreateNest(PETSC_COMM_WORLD,2,PETSC_NULL,bx,&r); CHKERRQ(ierr); ierr = VecDestroy(&r1); CHKERRQ(ierr); ierr = VecDestroy(&r2); CHKERRQ(ierr); ierr = VecAssemblyBegin(r); CHKERRQ(ierr); ierr = VecAssemblyEnd(r); CHKERRQ(ierr); /* Create sub Jacobian matrix data structure */ ierr = MatCreate( PETSC_COMM_WORLD, &j11 ); CHKERRQ(ierr); ierr = MatSetSizes( j11, 1, 1, 1, 1 ); CHKERRQ(ierr); ierr = MatSetType( j11, MATSEQAIJ ); CHKERRQ(ierr); ierr = MatSetUp(j11); CHKERRQ(ierr); ierr = MatCreate( PETSC_COMM_WORLD, &j12 ); CHKERRQ(ierr); ierr = MatSetSizes( j12, 1, 1, 1, 1 ); CHKERRQ(ierr); ierr = MatSetType( j12, MATSEQAIJ ); CHKERRQ(ierr); ierr = MatSetUp(j12); CHKERRQ(ierr); ierr = MatCreate( PETSC_COMM_WORLD, &j21 ); CHKERRQ(ierr); ierr = MatSetSizes( j21, 1, 1, 1, 1 ); CHKERRQ(ierr); ierr = MatSetType( j21, MATSEQAIJ ); CHKERRQ(ierr); ierr = MatSetUp(j21); CHKERRQ(ierr); ierr = MatCreate( PETSC_COMM_WORLD, &j22 ); CHKERRQ(ierr); ierr = MatSetSizes( j22, PETSC_DECIDE, PETSC_DECIDE, 1, 1 ); CHKERRQ(ierr); ierr = MatSetType( j22, MATSEQAIJ ); CHKERRQ(ierr); ierr = MatSetUp(j22); CHKERRQ(ierr); /* Create block Jacobian matrix data structure */ bA[0][0] = j11; bA[0][1] = j12; bA[1][0] = j21; bA[1][1] = j22; ierr = MatCreateNest(PETSC_COMM_WORLD,2,PETSC_NULL,2,PETSC_NULL,&bA[0][0],&J); CHKERRQ(ierr); ierr = MatSetUp(J); CHKERRQ(ierr); ierr = MatNestSetVecType(J,VECNEST); CHKERRQ(ierr); ierr = MatDestroy(&j11); CHKERRQ(ierr); ierr = MatDestroy(&j12); CHKERRQ(ierr); ierr = MatDestroy(&j21); CHKERRQ(ierr); ierr = MatDestroy(&j22); CHKERRQ(ierr); ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = PetscOptionsHasName(PETSC_NULL,"-hard",&flg); CHKERRQ(ierr); if (!flg) { /* Set function evaluation routine and vector. */ ierr = SNESSetFunction(snes,r,FormFunction1_block,PETSC_NULL); CHKERRQ(ierr); /* Set Jacobian matrix data structure and Jacobian evaluation routine */ ierr = SNESSetJacobian(snes,J,J,FormJacobian1_block,PETSC_NULL); CHKERRQ(ierr); } else { ierr = SNESSetFunction(snes,r,FormFunction2_block,PETSC_NULL); CHKERRQ(ierr); ierr = SNESSetJacobian(snes,J,J,FormJacobian2_block,PETSC_NULL); CHKERRQ(ierr); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Customize nonlinear solver; set runtime options - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Set linear solver defaults for this problem. By extracting the KSP, KSP, and PC contexts from the SNES context, we can then directly call any KSP, KSP, and PC routines to set various options. */ ierr = SNESGetKSP(snes,&ksp); CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc); CHKERRQ(ierr); ierr = PCSetType(pc,PCNONE); CHKERRQ(ierr); ierr = KSPSetTolerances(ksp,1.e-4,PETSC_DEFAULT,PETSC_DEFAULT,20); CHKERRQ(ierr); /* Set SNES/KSP/KSP/PC runtime options, e.g., -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc> These options will override those specified above as long as SNESSetFromOptions() is called _after_ any other customization routines. */ ierr = SNESSetFromOptions(snes); CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Evaluate initial guess; then solve nonlinear system - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ if (!flg) { ierr = VecSet(x,pfive); CHKERRQ(ierr); } else { Vec *vecs; ierr = VecNestGetSubVecs( x, PETSC_NULL, &vecs ); CHKERRQ(ierr); bv = vecs[0]; // ierr = VecBlockGetSubVec( x, 0, &bv );CHKERRQ(ierr); ierr = VecSetValue( bv, 0, 2.0, INSERT_VALUES ); CHKERRQ(ierr); /* xx[0] = 2.0; */ ierr = VecAssemblyBegin(bv); CHKERRQ(ierr); ierr = VecAssemblyEnd(bv); CHKERRQ(ierr); // ierr = VecBlockGetSubVec( x, 1, &bv );CHKERRQ(ierr); bv = vecs[1]; ierr = VecSetValue( bv, 0, 3.0, INSERT_VALUES ); CHKERRQ(ierr); /* xx[1] = 3.0; */ ierr = VecAssemblyBegin(bv); CHKERRQ(ierr); ierr = VecAssemblyEnd(bv); CHKERRQ(ierr); } /* Note: The user should initialize the vector, x, with the initial guess for the nonlinear solver prior to calling SNESSolve(). In particular, to employ an initial guess of zero, the user should explicitly set this vector to zero by calling VecSet(). */ ierr = SNESSolve(snes,PETSC_NULL,x); CHKERRQ(ierr); ierr = SNESGetIterationNumber(snes,&its); CHKERRQ(ierr); if (flg) { Vec f; ierr = VecView(x,PETSC_VIEWER_STDOUT_WORLD); CHKERRQ(ierr); ierr = SNESGetFunction(snes,&f,0,0); CHKERRQ(ierr); ierr = VecView(r,PETSC_VIEWER_STDOUT_WORLD); CHKERRQ(ierr); } ierr = PetscPrintf(PETSC_COMM_SELF,"number of SNES iterations = %D\n\n",its); CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Free work space. All PETSc objects should be destroyed when they are no longer needed. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = VecDestroy(&x); CHKERRQ(ierr); ierr = VecDestroy(&r); CHKERRQ(ierr); ierr = MatDestroy(&J); CHKERRQ(ierr); ierr = SNESDestroy(&snes); CHKERRQ(ierr); PetscFunctionReturn(0); }