static char help[] = "This example solves a linear system in parallel with KSP. The matrix\n\ uses arbitrary order polynomials for finite elements on the unit square. To test the parallel\n\ matrix assembly, the matrix is intentionally laid out across processors\n\ differently from the way it is assembled. Input arguments are:\n\ -m -p : mesh size and polynomial order\n\n"; /* Contributed by Travis Austin , 2010. based on src/ksp/ksp/tutorials/ex3.c */ #include /* Declare user-defined routines */ static PetscReal src(PetscReal,PetscReal); static PetscReal ubdy(PetscReal,PetscReal); static PetscReal polyBasisFunc(PetscInt,PetscInt,PetscReal*,PetscReal); static PetscReal derivPolyBasisFunc(PetscInt,PetscInt,PetscReal*,PetscReal); static PetscErrorCode Form1DElementMass(PetscReal,PetscInt,PetscReal*,PetscReal*,PetscScalar*); static PetscErrorCode Form1DElementStiffness(PetscReal,PetscInt,PetscReal*,PetscReal*,PetscScalar*); static PetscErrorCode Form2DElementMass(PetscInt,PetscScalar*,PetscScalar*); static PetscErrorCode Form2DElementStiffness(PetscInt,PetscScalar*,PetscScalar*,PetscScalar*); static PetscErrorCode FormNodalRhs(PetscInt,PetscReal,PetscReal,PetscReal,PetscReal*,PetscScalar*); static PetscErrorCode FormNodalSoln(PetscInt,PetscReal,PetscReal,PetscReal,PetscReal*,PetscScalar*); static void leggaulob(PetscReal, PetscReal, PetscReal [], PetscReal [], int); static void qAndLEvaluation(int, PetscReal, PetscReal*, PetscReal*, PetscReal*); int main(int argc,char **args) { PetscInt p = 2, m = 5; PetscInt num1Dnodes, num2Dnodes; PetscScalar *Ke1D,*Ke2D,*Me1D,*Me2D; PetscScalar *r,*ue,val; Vec u,ustar,b,q; Mat A,Mass; KSP ksp; PetscInt M,N; PetscMPIInt rank,size; PetscReal x,y,h,norm; PetscInt *idx,indx,count,*rows,i,j,k,start,end,its; PetscReal *rowsx,*rowsy; PetscReal *gllNode, *gllWgts; PetscErrorCode ierr; ierr = PetscInitialize(&argc,&args,(char*)0,help);if (ierr) return ierr; ierr = PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"Options for p-FEM","");CHKERRQ(ierr); ierr = PetscOptionsInt("-m","Number of elements in each direction","None",m,&m,NULL);CHKERRQ(ierr); ierr = PetscOptionsInt("-p","Order of each element (tensor product basis)","None",p,&p,NULL);CHKERRQ(ierr); ierr = PetscOptionsEnd();CHKERRQ(ierr); if (p <=0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Option -p value should be greater than zero"); N = (p*m+1)*(p*m+1); /* dimension of matrix */ M = m*m; /* number of elements */ h = 1.0/m; /* mesh width */ ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRMPI(ierr); ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRMPI(ierr); /* Create stiffness matrix */ ierr = MatCreate(PETSC_COMM_WORLD,&A);CHKERRQ(ierr); ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,N,N);CHKERRQ(ierr); ierr = MatSetFromOptions(A);CHKERRQ(ierr); ierr = MatSetUp(A);CHKERRQ(ierr); /* Create matrix */ ierr = MatCreate(PETSC_COMM_WORLD,&Mass);CHKERRQ(ierr); ierr = MatSetSizes(Mass,PETSC_DECIDE,PETSC_DECIDE,N,N);CHKERRQ(ierr); ierr = MatSetFromOptions(Mass);CHKERRQ(ierr); ierr = MatSetUp(Mass);CHKERRQ(ierr); start = rank*(M/size) + ((M%size) < rank ? (M%size) : rank); end = start + M/size + ((M%size) > rank); /* Allocate element stiffness matrices */ num1Dnodes = (p+1); num2Dnodes = num1Dnodes*num1Dnodes; ierr = PetscMalloc1(num1Dnodes*num1Dnodes,&Me1D);CHKERRQ(ierr); ierr = PetscMalloc1(num1Dnodes*num1Dnodes,&Ke1D);CHKERRQ(ierr); ierr = PetscMalloc1(num2Dnodes*num2Dnodes,&Me2D);CHKERRQ(ierr); ierr = PetscMalloc1(num2Dnodes*num2Dnodes,&Ke2D);CHKERRQ(ierr); ierr = PetscMalloc1(num2Dnodes,&idx);CHKERRQ(ierr); ierr = PetscMalloc1(num2Dnodes,&r);CHKERRQ(ierr); ierr = PetscMalloc1(num2Dnodes,&ue);CHKERRQ(ierr); /* Allocate quadrature and create stiffness matrices */ ierr = PetscMalloc1(p+1,&gllNode);CHKERRQ(ierr); ierr = PetscMalloc1(p+1,&gllWgts);CHKERRQ(ierr); leggaulob(0.0,1.0,gllNode,gllWgts,p); /* Get GLL nodes and weights */ ierr = Form1DElementMass(h,p,gllNode,gllWgts,Me1D);CHKERRQ(ierr); ierr = Form1DElementStiffness(h,p,gllNode,gllWgts,Ke1D);CHKERRQ(ierr); ierr = Form2DElementMass(p,Me1D,Me2D);CHKERRQ(ierr); ierr = Form2DElementStiffness(p,Ke1D,Me1D,Ke2D);CHKERRQ(ierr); /* Assemble matrix */ for (i=start; i 3.0e-11); qAndLEvaluation(n,z,&q,&qp,&Ln); x[j] = xm+xl*z; /* Scale the root to the desired interval, */ x[n-j] = xm-xl*z; /* and put in its symmetric counterpart. */ w[j] = 2.0/(n*(n+1)*Ln*Ln); /* Compute the weight */ w[n-j] = w[j]; /* and its symmetric counterpart. */ } } if (n%2==0) { qAndLEvaluation(n,0.0,&q,&qp,&Ln); x[n/2]=(x2-x1)/2.0; w[n/2]=2.0/(n*(n+1)*Ln*Ln); } /* scale the weights according to mapping from [-1,1] to [0,1] */ scale = (x2-x1)/2.0; for (j=0; j<=n; ++j) w[j] = w[j]*scale; } /******************************************************************************/ static void qAndLEvaluation(int n, PetscReal x, PetscReal *q, PetscReal *qp, PetscReal *Ln) /******************************************************************************* Compute the polynomial qn(x) = L_{N+1}(x) - L_{n-1}(x) and its derivative in addition to L_N(x) as these are needed for the GLL points. See the book titled "Implementing Spectral Methods for Partial Differential Equations: Algorithms for Scientists and Engineers" by David A. Kopriva. *******************************************************************************/ { PetscInt k; PetscReal Lnp; PetscReal Lnp1, Lnp1p; PetscReal Lnm1, Lnm1p; PetscReal Lnm2, Lnm2p; Lnm1 = 1.0; *Ln = x; Lnm1p = 0.0; Lnp = 1.0; for (k=2; k<=n; ++k) { Lnm2 = Lnm1; Lnm1 = *Ln; Lnm2p = Lnm1p; Lnm1p = Lnp; *Ln = (2.*k-1.)/(1.0*k)*x*Lnm1 - (k-1.)/(1.0*k)*Lnm2; Lnp = Lnm2p + (2.0*k-1)*Lnm1; } k = n+1; Lnp1 = (2.*k-1.)/(1.0*k)*x*(*Ln) - (k-1.)/(1.0*k)*Lnm1; Lnp1p = Lnm1p + (2.0*k-1)*(*Ln); *q = Lnp1 - Lnm1; *qp = Lnp1p - Lnm1p; } /*TEST test: nsize: 2 args: -ksp_monitor_short TEST*/