Actual source code: ex27.c
petsc-3.7.3 2016-08-01
1: static char help[] = "Test sequential USFFT interface on a uniform DMDA and compares the result to FFTW\n\n";
3: /*
4: Compiling the code:
5: This code uses the complex numbers version of PETSc and the FFTW package, so configure
6: must be run to enable these.
8: */
10: #include <petscmat.h>
11: #include <petscdm.h>
12: #include <petscdmda.h>
15: PetscInt main(PetscInt argc,char **args)
16: {
17: typedef enum {RANDOM, CONSTANT, TANH, NUM_FUNCS} FuncType;
18: const char *funcNames[NUM_FUNCS] = {"random", "constant", "tanh"};
19: Mat A, AA;
20: PetscMPIInt size;
21: PetscInt N,i, stencil=1,dof=1;
22: PetscInt dim[3] = {10,10,10}, ndim = 3;
23: Vec coords,x,y,z,xx,yy,zz;
24: PetscReal h[3];
25: PetscScalar s;
26: PetscRandom rdm;
27: PetscReal norm, enorm;
28: PetscInt func;
29: FuncType function = TANH;
30: DM da, coordsda;
31: PetscBool view_x = PETSC_FALSE, view_y = PETSC_FALSE, view_z = PETSC_FALSE;
34: PetscInitialize(&argc,&args,(char*)0,help);
35: #if !defined(PETSC_USE_COMPLEX)
36: SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP, "This example requires complex numbers");
37: #endif
38: MPI_Comm_size(PETSC_COMM_WORLD, &size);
39: if (size != 1) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP, "This is a uniprocessor example only!");
40: PetscOptionsBegin(PETSC_COMM_WORLD, NULL, "USFFT Options", "ex27");
41: PetscOptionsEList("-function", "Function type", "ex27", funcNames, NUM_FUNCS, funcNames[function], &func, NULL);
42: function = (FuncType) func;
43: PetscOptionsEnd();
44: PetscOptionsGetBool(NULL,NULL,"-view_x",&view_x,NULL);
45: PetscOptionsGetBool(NULL,NULL,"-view_y",&view_y,NULL);
46: PetscOptionsGetBool(NULL,NULL,"-view_z",&view_z,NULL);
47: PetscOptionsGetIntArray(NULL,NULL,"-dim",dim,&ndim,NULL);
51: DMDACreate3d(PETSC_COMM_SELF,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DMDA_STENCIL_STAR,
52: dim[0], dim[1], dim[2],
53: PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE,
54: dof, stencil,
55: NULL, NULL, NULL,
56: &da);
57: /* Coordinates */
58: DMGetCoordinateDM(da, &coordsda);
59: DMGetGlobalVector(coordsda, &coords);
60: PetscObjectSetName((PetscObject) coords, "Grid coordinates");
61: for (i = 0, N = 1; i < 3; i++) {
62: h[i] = 1.0/dim[i];
63: PetscScalar *a;
64: VecGetArray(coords, &a);
65: PetscInt j,k,n = 0;
66: for (i = 0; i < 3; ++i) {
67: for (j = 0; j < dim[i]; ++j) {
68: for (k = 0; k < 3; ++k) {
69: a[n] = j*h[i]; /* coordinate along the j-th point in the i-th dimension */
70: ++n;
71: }
72: }
73: }
74: VecRestoreArray(coords, &a);
76: }
77: DMSetCoordinates(da, coords);
79: /* Work vectors */
80: DMGetGlobalVector(da, &x);
81: PetscObjectSetName((PetscObject) x, "Real space vector");
82: DMGetGlobalVector(da, &xx);
83: PetscObjectSetName((PetscObject) xx, "Real space vector");
84: DMGetGlobalVector(da, &y);
85: PetscObjectSetName((PetscObject) y, "USFFT frequency space vector");
86: DMGetGlobalVector(da, &yy);
87: PetscObjectSetName((PetscObject) yy, "FFTW frequency space vector");
88: DMGetGlobalVector(da, &z);
89: PetscObjectSetName((PetscObject) z, "USFFT reconstructed vector");
90: DMGetGlobalVector(da, &zz);
91: PetscObjectSetName((PetscObject) zz, "FFTW reconstructed vector");
93: PetscPrintf(PETSC_COMM_SELF, "%3-D: USFFT on vector of ");
94: for (i = 0, N = 1; i < 3; i++) {
95: PetscPrintf(PETSC_COMM_SELF, "dim[%d] = %d ",i,dim[i]);
96: N *= dim[i];
97: }
98: PetscPrintf(PETSC_COMM_SELF, "; total size %d \n",N);
101: if (function == RANDOM) {
102: PetscRandomCreate(PETSC_COMM_SELF, &rdm);
103: PetscRandomSetFromOptions(rdm);
104: VecSetRandom(x, rdm);
105: PetscRandomDestroy(&rdm);
106: } else if (function == CONSTANT) {
107: VecSet(x, 1.0);
108: } else if (function == TANH) {
109: PetscScalar *a;
110: VecGetArray(x, &a);
111: PetscInt j,k = 0;
112: for (i = 0; i < 3; ++i) {
113: for (j = 0; j < dim[i]; ++j) {
114: a[k] = tanh((j - dim[i]/2.0)*(10.0/dim[i]));
115: ++k;
116: }
117: }
118: VecRestoreArray(x, &a);
119: }
120: if (view_x) {
121: VecView(x, PETSC_VIEWER_STDOUT_WORLD);
122: }
123: VecCopy(x,xx);
125: VecNorm(x,NORM_2,&norm);
126: PetscPrintf(PETSC_COMM_SELF, "|x|_2 = %g\n",norm);
128: /* create USFFT object */
129: MatCreateSeqUSFFT(coords,da,&A);
130: /* create FFTW object */
131: MatCreateSeqFFTW(PETSC_COMM_SELF,3,dim,&AA);
133: /* apply USFFT and FFTW FORWARD "preemptively", so the fftw_plans can be reused on different vectors */
134: MatMult(A,x,z);
135: MatMult(AA,xx,zz);
136: /* Now apply USFFT and FFTW forward several (3) times */
137: for (i=0; i<3; ++i) {
138: MatMult(A,x,y);
139: MatMult(AA,xx,yy);
140: MatMultTranspose(A,y,z);
141: MatMultTranspose(AA,yy,zz);
142: }
144: if (view_y) {
145: PetscPrintf(PETSC_COMM_WORLD, "y = \n");
146: VecView(y, PETSC_VIEWER_STDOUT_WORLD);
147: PetscPrintf(PETSC_COMM_WORLD, "yy = \n");
148: VecView(yy, PETSC_VIEWER_STDOUT_WORLD);
149: }
151: if (view_z) {
152: PetscPrintf(PETSC_COMM_WORLD, "z = \n");
153: VecView(z, PETSC_VIEWER_STDOUT_WORLD);
154: PetscPrintf(PETSC_COMM_WORLD, "zz = \n");
155: VecView(zz, PETSC_VIEWER_STDOUT_WORLD);
156: }
158: /* compare x and z. USFFT computes an unnormalized DFT, thus z = N*x */
159: s = 1.0/(PetscReal)N;
160: VecScale(z,s);
161: VecAXPY(x,-1.0,z);
162: VecNorm(x,NORM_1,&enorm);
163: PetscPrintf(PETSC_COMM_SELF, "|x-z| = %g\n",enorm);
165: /* compare xx and zz. FFTW computes an unnormalized DFT, thus zz = N*x */
166: s = 1.0/(PetscReal)N;
167: VecScale(zz,s);
168: VecAXPY(xx,-1.0,zz);
169: VecNorm(xx,NORM_1,&enorm);
170: PetscPrintf(PETSC_COMM_SELF, "|xx-zz| = %g\n",enorm);
172: /* compare y and yy: USFFT and FFTW results*/
173: VecNorm(y,NORM_2,&norm);
174: VecAXPY(y,-1.0,yy);
175: VecNorm(y,NORM_1,&enorm);
176: PetscPrintf(PETSC_COMM_SELF, "|y|_2 = %g\n",norm);
177: PetscPrintf(PETSC_COMM_SELF, "|y-yy| = %g\n",enorm);
179: /* compare z and zz: USFFT and FFTW results*/
180: VecNorm(z,NORM_2,&norm);
181: VecAXPY(z,-1.0,zz);
182: VecNorm(z,NORM_1,&enorm);
183: PetscPrintf(PETSC_COMM_SELF, "|z|_2 = %g\n",norm);
184: PetscPrintf(PETSC_COMM_SELF, "|z-zz| = %g\n",enorm);
187: /* free spaces */
188: DMRestoreGlobalVector(da,&x);
189: DMRestoreGlobalVector(da,&xx);
190: DMRestoreGlobalVector(da,&y);
191: DMRestoreGlobalVector(da,&yy);
192: DMRestoreGlobalVector(da,&z);
193: DMRestoreGlobalVector(da,&zz);
194: VecDestroy(&coords);
195: DMDestroy(&da);
196: PetscFinalize();
197: return 0;
198: }