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"; #include "petscksp.h" /* Declare user-defined routines */ extern PetscReal src(PetscReal,PetscReal); extern PetscReal ubdy(PetscReal,PetscReal); extern PetscReal polyBasisFunc(PetscInt,PetscInt,PetscReal*,PetscReal); extern PetscReal derivPolyBasisFunc(PetscInt,PetscInt,PetscReal*,PetscReal); extern PetscErrorCode Form1DElementMass(PetscReal,PetscInt,double*,double*,PetscReal*); extern PetscErrorCode Form1DElementStiffness(PetscReal,PetscInt,double*,double*,PetscReal*); extern PetscErrorCode Form2DElementMass(PetscInt,PetscReal*,PetscReal*); extern PetscErrorCode Form2DElementStiffness(PetscInt,PetscReal*,PetscReal*,PetscReal*); extern PetscErrorCode FormNodalRhs(PetscInt,PetscReal,PetscReal,PetscReal,double*,PetscReal*); extern PetscErrorCode FormNodalSoln(PetscInt,PetscReal,PetscReal,PetscReal,double*,PetscReal*); extern void leggaulob(double, double, double [], double [], int); extern void qAndLEvaluation(int, double, double*, double*, double*); #undef __FUNCT__ #define __FUNCT__ "main" int main(int argc,char **args) { PetscInt p = 2, m = 5; PetscInt num1Dnodes, num2Dnodes; PetscReal *Ke1D,*Ke2D,*Me1D,*Me2D; PetscReal *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; PetscInitialize(&argc,&args,(char *)0,help); ierr = PetscOptionsGetInt(PETSC_NULL,"-m",&m,PETSC_NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(PETSC_NULL,"-p",&p,PETSC_NULL);CHKERRQ(ierr); 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);CHKERRQ(ierr); ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(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); start = rank*(M/size) + ((M%size) < rank ? (M%size) : rank); end = start + M/size + ((M%size) > rank); /* 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); 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 = PetscMalloc((num1Dnodes*num1Dnodes)*sizeof(PetscReal),&Me1D);CHKERRQ(ierr); ierr = PetscMalloc((num1Dnodes*num1Dnodes)*sizeof(PetscReal),&Ke1D);CHKERRQ(ierr); ierr = PetscMalloc((num2Dnodes*num2Dnodes)*sizeof(PetscReal),&Me2D);CHKERRQ(ierr); ierr = PetscMalloc((num2Dnodes*num2Dnodes)*sizeof(PetscReal),&Ke2D);CHKERRQ(ierr); ierr = PetscMalloc(num2Dnodes*sizeof(PetscInt),&idx);CHKERRQ(ierr); ierr = PetscMalloc(num2Dnodes*sizeof(PetscReal),&r);CHKERRQ(ierr); ierr = PetscMalloc(num2Dnodes*sizeof(PetscReal),&ue);CHKERRQ(ierr); /* Allocate quadrature and create stiffness matrices */ ierr = PetscMalloc((p+1)*sizeof(PetscReal),&gllNode);CHKERRQ(ierr); ierr = PetscMalloc((p+1)*sizeof(PetscReal),&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; } /******************************************************************************/ void qAndLEvaluation(int n, double x, double* q, double* qp, double* 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. *******************************************************************************/ { int k; double Lnp; double Lnp1, Lnp1p; double Lnm1, Lnm1p; double 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; }