-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Dear PETSc users,
I'm trying to write a Poisson solver in Fortran using the
KSPSetComputeOperators etc. framework. When debugging this, I ended up
modifying ksp/ex22.f so that it matches ksp/ex34.c. The difference
between these is that ex34.c has a non-constant RHS and Neumann BCs,
which is closer to what I want.
Now, when I run these two programs I get the following:
./ex22f_mod
Residual, L2 norm 1.007312
Error, sup norm 0.020941
Error, L1 norm 10.687882
Error, L2 norm 0.340425
./ex34
Residual, L2 norm 1.07124e-05
Error, sup norm 0.0209405
Error, L1 norm 0.00618512
Error, L2 norm 0.000197005
but when I MatView/VecView the matrix and RHS for each example (write
them to file), there is no difference. I have attached ex22f_mod.F90,
any suggestions on what the error is?
Once this example works, you can of course include it with PETSc.
Regards,
Åsmund
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
iQEcBAEBAgAGBQJTPWWZAAoJED+FDAHgGz19aNYIANyq9k3a5kHzTlAdybkZCYDw
yKtDE5l/4iWYmNL49FH8AocHVcRivLaeJG5CGKqySFtZUXOlC9DM7rn4UmuQecni
dgIQuTk0Ym+OJccHyT5xxnebpFVNrIOTpInfQaDW6dTyeL1svAMeHqslKaGepySL
q/cODbgNDYgl6uumB+POMZevtlM6HPhl/1m7HofcHC9upvTRjSPqP1cg+kg+/8m2
Fdie/X7PCBfShrAys94kNXNcwtbO7taauphkQGMfyl0gUd+lFATG6zrEZdDqSFlV
c44GFFbxW/SRIDBXdOeX9/cy75KW5do1Sildwb6R4H/i7t6/hCJUJuss7FHjmLc=
=tV3N
-----END PGP SIGNATURE-----
!
! Laplacian in 3D. Modeled by the partial differential equation
!
! Laplacian u = 1,0 < x,y,z < 1,
!
! with boundary conditions
!
! u = 1 for x = 0, x = 1, y = 0, y = 1, z = 0, z = 1.
!
! This uses multigrid to solve the linear system
program main
implicit none
! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
! Include files
! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!
! petscsys.h - base PETSc routines petscvec.h - vectors
! petscmat.h - matrices
! petscksp.h - Krylov subspace methods petscpc.h - preconditioners
#include <finclude/petscsys.h>
#include <finclude/petscvec.h>
#include <finclude/petscmat.h>
#include <finclude/petscpc.h>
#include <finclude/petscksp.h>
#include <finclude/petscdmda.h>
#include <finclude/petscdmda.h90>
PetscErrorCode ierr
DM da
KSP ksp
Vec x,b,r
PetscInt i1,i3
PetscInt ctx
PetscScalar r1, norm,Hx,Hy,hz
MatNullSpace nullspace
character(len=255) :: Fstr
PetscScalar, pointer :: array(:,:,:)
PetscInt i,j,k,mx,my,mz,xm,ym,zm,xs,ys,zs
interface
subroutine ComputeRHS(ksp,rhs,ctx,ierr)
KSP, intent(in) :: ksp
Vec, intent(inout) :: rhs
PetscInt, intent(in) :: ctx
PetscErrorCode, intent(inout) :: ierr
end subroutine ComputeRHS
!
subroutine ComputeMatrix(ksp,JJ,A,str,ctx,ierr)
KSP, intent(in) :: ksp
Mat, intent(in) :: A,JJ
MatStructure, intent(in) :: str
PetscInt, intent(in) :: ctx
PetscErrorCode, intent(in) :: ierr
end subroutine ComputeMatrix
end interface
call PetscInitialize(PETSC_NULL_CHARACTER,ierr)
i3 = -12
i1 = 1
call KSPCreate(MPI_COMM_WORLD,ksp,ierr)
call DMDACreate3d(PETSC_COMM_WORLD,DMDA_BOUNDARY_NONE, &
& DMDA_BOUNDARY_NONE,DMDA_BOUNDARY_NONE, &
& DMDA_STENCIL_STAR,i3,i3,i3,PETSC_DECIDE,PETSC_DECIDE, &
& PETSC_DECIDE,i1,i1,PETSC_NULL_INTEGER,PETSC_NULL_INTEGER, &
& PETSC_NULL_INTEGER,da,ierr)
call DMDASetInterpolationType(da, DMDA_Q0, ierr)
call KSPSetDM(ksp,da,ierr)
! call MatNullSpaceCreate(PETSC_COMM_WORLD,PETSC_TRUE,0,0,nullspace,ierr)
! call KSPSetNullSpace(ksp,nullspace,ierr)
call KSPSetComputeRHS(ksp,ComputeRHS,ctx,ierr)
call KSPSetComputeOperators(ksp,ComputeMatrix,ctx,ierr)
call KSPSetFromOptions(ksp,ierr)
call KSPSolve(ksp,PETSC_NULL_OBJECT,PETSC_NULL_OBJECT,ierr)
call KSPGetSolution(ksp,x,ierr)
call KSPGetRhs(ksp,b,ierr)
call KSPGetOperators(ksp,PETSC_NULL_OBJECT,J,PETSC_NULL_OBJECT,ierr)
call VecDuplicate(b,r,ierr)
call MatMult(J,x,r,ierr)
call VecAXPY(r,-1.0,b,ierr)
call VecNorm(r,NORM_2,norm,ierr)
write(Fstr,101) norm
call PetscPrintf(PETSC_COMM_WORLD,Fstr,ierr)
call DMDAGetInfo(da,PETSC_NULL_INTEGER,mx,my,mz, &
& PETSC_NULL_INTEGER,PETSC_NULL_INTEGER, &
& PETSC_NULL_INTEGER,PETSC_NULL_INTEGER, &
& PETSC_NULL_INTEGER,PETSC_NULL_INTEGER, &
& PETSC_NULL_INTEGER,PETSC_NULL_INTEGER, &
& PETSC_NULL_INTEGER,ierr)
Hx = 1.d0 / (mx)
Hy = 1.d0 / (my)
Hz = 1.d0 / (mz)
call DMDAGetCorners(da,xs,ys,zs,xm,ym,zm,ierr)
call DMDAVecGetArrayF90(da,x,array,ierr)
r1=1.d0
do k=zs,zs+zm-1
do j=ys,ys+ym-1
do i=xs,xs+xm-1
array(i,j,k) = array(i,j,k) - &
cos(2*PETSC_PI*((r1*i+0.5)*Hx))* &
cos(2*PETSC_PI*((r1*j+0.5)*Hy))* &
cos(2*PETSC_PI*((r1*k+0.5)*Hz))
end do
end do
end do
call DMDAVecRestoreArrayF90(da,x,array,ierr)
call VecAssemblyBegin(x,ierr)
call VecAssemblyEnd(x,ierr)
call VecNorm(x,NORM_INFINITY,norm,ierr)
write(Fstr,102) norm
call PetscPrintf(PETSC_COMM_WORLD,Fstr,ierr)
call VecNorm(x,NORM_1,norm,ierr)
write(Fstr,103) norm
call PetscPrintf(PETSC_COMM_WORLD,Fstr,ierr)
call VecNorm(x,NORM_2,norm,ierr)
write(Fstr,104) norm
call PetscPrintf(PETSC_COMM_WORLD,Fstr,ierr)
call KSPDestroy(ksp,ierr)
call DMDestroy(da,ierr)
call PetscFinalize(ierr)
101 format(1x,"Residual, L2 norm ",F16.6,"\n")
102 format(1x,"Error, sup norm ",F16.6,"\n")
103 format(1x,"Error, L1 norm ",F16.6,"\n")
104 format(1x,"Error, L2 norm ",F16.6,"\n")
end
subroutine ComputeRHS(ksp,b,ctx,ierr)
implicit none
#include <finclude/petscsys.h>
#include <finclude/petscvec.h>
#include <finclude/petscdmda.h>
#include <finclude/petscdmda.h90>
KSP ksp
Vec b
PetscInt ctx
PetscErrorCode ierr
PetscInt mx,my,mz
PetscScalar Hx,Hy,Hz,r1
DM da
PetscInt i,j,k,xm,ym,zm,xs,ys,zs
PetscScalar, pointer :: array(:,:,:)
MatNullSpace nullspace
PetscViewer viewer
call KSPGetDM(ksp,da,ierr)
call DMDAGetInfo(da,PETSC_NULL_INTEGER,mx,my,mz, &
& PETSC_NULL_INTEGER,PETSC_NULL_INTEGER, &
& PETSC_NULL_INTEGER,PETSC_NULL_INTEGER, &
& PETSC_NULL_INTEGER,PETSC_NULL_INTEGER, &
& PETSC_NULL_INTEGER,PETSC_NULL_INTEGER, &
& PETSC_NULL_INTEGER,ierr)
Hx=1.d0/(mx)
Hy=1.d0/(my)
Hz=1.d0/(mz)
call DMDAGetCorners(da,xs,ys,zs,xm,ym,zm,ierr)
call DMDAVecGetArrayF90(da,b,array,ierr)
r1=1.d0
do k=zs,zs+zm-1
do j=ys,ys+ym-1
do i=xs,xs+xm-1
array(i,j,k) = 12*PETSC_PI*PETSC_PI* &
cos(2*PETSC_PI*((r1*i+0.5)*Hx))* &
cos(2*PETSC_PI*((r1*j+0.5)*Hy))* &
cos(2*PETSC_PI*((r1*k+0.5)*Hz)) * Hx*Hy*Hz
end do
end do
end do
call DMDAVecRestoreArrayF90(da,b,array,ierr)
call VecAssemblyBegin(b,ierr)
call VecAssemblyEnd(b,ierr)
call MatNullSpaceCreate(PETSC_COMM_WORLD,PETSC_TRUE,0,0,nullspace,ierr)
call MatNullSpaceRemove(nullspace,b,PETSC_NULL_OBJECT,ierr)
call MatNullSpaceDestroy(nullspace,ierr)
call PetscViewerASCIIOpen(PETSC_COMM_WORLD,"vec22.out",viewer,ierr)
call VecView(b,viewer,ierr)
return
end
!---------------------------------------------------------------------
subroutine ComputeMatrix(ksp,JJ,A,str,ctx,ierr)
implicit none
#include <finclude/petscsys.h>
#include <finclude/petscvec.h>
#include <finclude/petscviewer.h>
#include <finclude/petscdmda.h>
#include <finclude/petscdmda.h90>
#include "finclude/petscmat.h"
#include "finclude/petscksp.h"
#include "finclude/petscpc.h"
!
KSP, intent(in) :: ksp
Mat, intent(in) :: A,JJ
MatStructure, intent(in) :: str
PetscInt, intent(in) :: ctx
PetscErrorCode, intent(in) :: ierr
!
DM da
PetscInt i,j,k,mx,my,mz,im
PetscInt jm,km,is,js,ks,i1,i7,MSi,MSj,MSk
PetscInt :: num,numi,numj,numk
PetscScalar v(7)
PetscScalar HxHydHz,HyHzdHx,HxHzdHy,dx,dy,dz
MatStencil row(4),col(4,7)
MatNullSpace nullspace
PetscViewer viewer
!
i1 = 1
i7 = 7
MSi=MatStencil_i
MSj=MatStencil_j
MSk=MatStencil_k
!
call KSPGetDM(ksp,da,ierr)
call DMDAGetCorners(da,is,js,ks,im,jm,km,ierr)
im=is+im-1
jm=js+jm-1
km=ks+km-1
call DMDAGetInfo(da,PETSC_NULL_INTEGER,mx,my,mz,&
PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,&
PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,&
PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,ierr)
!
dx=1.d0/(mx)
dy=1.d0/(my)
dz=1.d0/(mz)
HxHydHz = dx*dy/dz
HxHzdHy = dx*dz/dy
HyHzdHx = dy*dz/dx
!
! Set the matrix values
do k=ks,km
do j=js,jm
do i=is,im
row(MSi) = i
row(MSj) = j
row(MSk) = k
if (i==0 .or. j==0 .or. k==0 .or. &
i==mx-1 .or. j==my-1 .or. k==mz-1) then
! BC's
num=1
numi=0
numj=0
numk=0
! Lots of if's to check the edges.
!
! Eg. if we are not at the bottom, include the bottom stencil part
if (k/=0) then
v(num) = -HxHydHz
col(MSi,num) = i
col(MSj,num) = j
col(MSk,num) = k-1
num=num+1
numk=numk+1
end if
if (j/=0) then
v(num) = -HxHzdHy
col(MSi,num) = i
col(MSj,num) = j-1
col(MSk,num) = k
num=num+1
numj=numj+1
end if
if (i/=0) then
v(num) = -HyHzdHx
col(MSi,num) = i-1
col(MSj,num) = j
col(MSk,num) = k
num=num+1
numi=numi+1
end if
if (i/=mx-1) then
v(num) = -HyHzdHx
col(MSi,num) = i+1
col(MSj,num) = j
col(MSk,num) = k
num=num+1
numi=numi+1
end if
if (j/=my-1) then
v(num) = -HxHzdHy
col(MSi,num) = i
col(MSj,num) = j+1
col(MSk,num) = k
num=num+1
numj=numj+1
end if
if (k/=mz-1) then
v(num) = -HxHydHz
col(MSi,num) = i
col(MSj,num) = j
col(MSk,num) = k+1
num=num+1
numk=numk+1
end if
! Central point
v(num) = numk*HxHydHz + numj*HxHzdHy + numi*HyHzdHx
col(MSi,num) = i
col(MSj,num) = j
col(MSk,num) = k
call MatSetValuesStencil(A,1,row,num,col,v,INSERT_VALUES,ierr)
CHKERRQ(ierr)
else
! Standard stencil away from boundaries
col(MSi,:)=i
col(MSj,:)=j
col(MSk,:)=k
v(1) = -HxHydHz; col(MSk,1) = k-1
v(2) = -HxHzdHy; col(MSj,2) = j-1
v(3) = -HyHzdHx; col(MSi,3) = i-1
v(4) = 2.0*(HyHzdHx + HxHzdHy + HxHydHz)
v(5) = -HyHzdHx; col(MSi,5) = i+1
v(6) = -HxHzdHy; col(MSj,6) = j+1
v(7) = -HxHydHz; col(MSk,7) = k+1
! Set these values into the matrix
call MatSetValuesStencil(A,i1,row,i7,col,v,INSERT_VALUES,ierr)
CHKERRQ(ierr)
end if
end do
end do
end do
!
! Assemble the A matrix and right-hand-side vector
call MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY,ierr)
CHKERRQ(ierr)
call MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY,ierr)
CHKERRQ(ierr)
call MatNullSpaceCreate(PETSC_COMM_WORLD,PETSC_TRUE,0,0,nullspace,ierr)
call MatSetNullSpace(A,nullspace,ierr)
call MatNullSpaceDestroy(nullspace,ierr)
call PetscViewerASCIIOpen(PETSC_COMM_WORLD,"mat22.out",viewer,ierr)
call MatView(A,viewer,ierr)
end subroutine ComputeMatrix