View Javadoc
1   // ******************************************************************************
2   //
3   // Title:       Force Field X.
4   // Description: Force Field X - Software for Molecular Biophysics.
5   // Copyright:   Copyright (c) Michael J. Schnieders 2001-2025.
6   //
7   // This file is part of Force Field X.
8   //
9   // Force Field X is free software; you can redistribute it and/or modify it
10  // under the terms of the GNU General Public License version 3 as published by
11  // the Free Software Foundation.
12  //
13  // Force Field X is distributed in the hope that it will be useful, but WITHOUT
14  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16  // details.
17  //
18  // You should have received a copy of the GNU General Public License along with
19  // Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
20  // Place, Suite 330, Boston, MA 02111-1307 USA
21  //
22  // Linking this library statically or dynamically with other modules is making a
23  // combined work based on this library. Thus, the terms and conditions of the
24  // GNU General Public License cover the whole combination.
25  //
26  // As a special exception, the copyright holders of this library give you
27  // permission to link this library with independent modules to produce an
28  // executable, regardless of the license terms of these independent modules, and
29  // to copy and distribute the resulting executable under terms of your choice,
30  // provided that you also meet, for each linked independent module, the terms
31  // and conditions of the license of that module. An independent module is a
32  // module which is not derived from or based on this library. If you modify this
33  // library, you may extend this exception to your version of the library, but
34  // you are not obligated to do so. If you do not wish to do so, delete this
35  // exception statement from your version.
36  //
37  // ******************************************************************************
38  package ffx.numerics.fft;
39  
40  import ffx.utilities.FFXTest;
41  import org.junit.Before;
42  import org.junit.Test;
43  import org.junit.runner.RunWith;
44  import org.junit.runners.Parameterized;
45  import org.junit.runners.Parameterized.Parameters;
46  
47  import java.util.Arrays;
48  import java.util.Collection;
49  import java.util.Random;
50  
51  import static org.junit.Assert.assertEquals;
52  
53  /**
54   * @author Michael J. Schnieders
55   */
56  @RunWith(Parameterized.class)
57  public class Complex2DTest extends FFXTest {
58  
59    private final String info;
60    private final int nx;
61    private final int ny;
62    private final int tot;
63    private final double[] data;
64    private final double[] dataBlocked;
65    private final double[] expected;
66    private final double tolerance = 1.0e-14;
67  
68    public Complex2DTest(String info, int nx, int ny) {
69      this.info = info;
70      this.nx = nx;
71      this.ny = ny;
72      tot = nx * ny;
73      data = new double[tot * 2];
74      dataBlocked = new double[tot * 2];
75      expected = new double[tot];
76    }
77  
78    @Parameters
79    public static Collection<Object[]> data() {
80      return Arrays.asList(
81          new Object[][]{
82              {"Test {nx=32, ny=32}", 32, 32},
83              {"Test {ny=45, nz=21}", 45, 21}
84          });
85    }
86  
87    @Before
88    public void setUp() {
89      Random random = new Random();
90      for (int i = 0; i < tot; i++) {
91        int index = i * 2;
92        double r = random.nextDouble();
93        data[index] = r;
94        dataBlocked[i] = r;
95        expected[i] = r;
96      }
97    }
98  
99    /**
100    * Test of the fft and ifft methods, of class Complex3D.
101    */
102   @Test
103   public void testInterleavedScalar() {
104     Complex2D complex2D = new Complex2D(nx, ny);
105     complex2D.setUseSIMD(false);
106     complex2D.setPackFFTs(false);
107     int offset = 0;
108     complex2D.fft(data, offset);
109     complex2D.ifft(data, offset);
110     for (int i = 0; i < tot; i++) {
111       int index = i * 2;
112       double actual = data[index] / tot;
113       double orig = expected[i];
114       assertEquals(info, orig, actual, tolerance);
115     }
116   }
117 
118   /**
119    * Test of the fft and ifft methods, of class Complex3D.
120    */
121   @Test
122   public void testBlockedScalar() {
123     Complex2D complex2D = new Complex2D(nx, ny, DataLayout2D.BLOCKED_XY, nx * ny);
124     complex2D.setUseSIMD(false);
125     complex2D.setPackFFTs(false);
126     int offset = 0;
127     complex2D.fft(dataBlocked, offset);
128     complex2D.ifft(dataBlocked, offset);
129     for (int i = 0; i < tot; i++) {
130       double actual = dataBlocked[i] / tot;
131       double orig = expected[i];
132       String message = info + " i = " + i;
133       assertEquals(message, orig, actual, tolerance);
134     }
135   }
136 
137   /**
138    * Test of the fft and ifft methods, of class Complex3D.
139    */
140   @Test
141   public void testInterleavedSIMD() {
142     Complex2D complex2D = new Complex2D(nx, ny);
143     complex2D.setUseSIMD(true);
144     complex2D.setPackFFTs(false);
145     int offset = 0;
146     complex2D.fft(data, offset);
147     complex2D.ifft(data, offset);
148     for (int i = 0; i < tot; i++) {
149       int index = i * 2;
150       double actual = data[index] / tot;
151       double orig = expected[i];
152       assertEquals(info, orig, actual, tolerance);
153     }
154   }
155 
156   /**
157    * Test of the fft and ifft methods, of class Complex3D.
158    */
159   @Test
160   public void testBlockedSIMD() {
161     Complex2D complex2D = new Complex2D(nx, ny, DataLayout2D.BLOCKED_XY, nx * ny);
162     complex2D.setUseSIMD(true);
163     complex2D.setPackFFTs(false);
164     int offset = 0;
165     complex2D.fft(dataBlocked, offset);
166     complex2D.ifft(dataBlocked, offset);
167     for (int i = 0; i < tot; i++) {
168       double actual = dataBlocked[i] / tot;
169       double orig = expected[i];
170       String message = info + " i = " + i;
171       assertEquals(message, orig, actual, tolerance);
172     }
173   }
174 
175   /**
176    * Test of the fft and ifft methods, of class Complex3D.
177    */
178   @Test
179   public void testInterleavedScalarPacked() {
180     Complex2D complex2D = new Complex2D(nx, ny);
181     complex2D.setUseSIMD(false);
182     complex2D.setPackFFTs(true);
183     int offset = 0;
184     complex2D.fft(data, offset);
185     complex2D.ifft(data, offset);
186     for (int i = 0; i < tot; i++) {
187       int index = i * 2;
188       double actual = data[index] / tot;
189       double orig = expected[i];
190       String message = info + " i = " + i;
191       assertEquals(message, orig, actual, tolerance);
192     }
193   }
194 
195   /**
196    * Test of the fft and ifft methods, of class Complex3D.
197    */
198   @Test
199   public void testBlockedScalarPacked() {
200     Complex2D complex2D = new Complex2D(nx, ny, DataLayout2D.BLOCKED_XY, nx * ny);
201     complex2D.setUseSIMD(false);
202     complex2D.setPackFFTs(true);
203     int offset = 0;
204     complex2D.fft(dataBlocked, offset);
205     complex2D.ifft(dataBlocked, offset);
206     for (int i = 0; i < tot; i++) {
207       double actual = dataBlocked[i] / tot;
208       double orig = expected[i];
209       String message = info + " i = " + i;
210       assertEquals(message, orig, actual, tolerance);
211     }
212   }
213 
214   /**
215    * Test of the fft and ifft methods, of class Complex3D.
216    */
217   @Test
218   public void testInterleavedSIMDPacked() {
219     Complex2D complex2D = new Complex2D(nx, ny);
220     complex2D.setUseSIMD(true);
221     complex2D.setPackFFTs(true);
222     int offset = 0;
223     complex2D.fft(data, offset);
224     complex2D.ifft(data, offset);
225     for (int i = 0; i < tot; i++) {
226       int index = i * 2;
227       double actual = data[index] / tot;
228       double orig = expected[i];
229       String message = info + " i = " + i;
230       assertEquals(message, orig, actual, tolerance);
231     }
232   }
233 
234   /**
235    * Test of the fft and ifft methods, of class Complex3D.
236    */
237   @Test
238   public void testBlockedSIMDPacked() {
239     Complex2D complex2D = new Complex2D(nx, ny, DataLayout2D.BLOCKED_XY, nx * ny);
240     complex2D.setUseSIMD(true);
241     complex2D.setPackFFTs(true);
242     int offset = 0;
243     complex2D.fft(dataBlocked, offset);
244     complex2D.ifft(dataBlocked, offset);
245     for (int i = 0; i < tot; i++) {
246       double actual = dataBlocked[i] / tot;
247       double orig = expected[i];
248       String message = info + " i = " + i;
249       assertEquals(message, orig, actual, tolerance);
250     }
251   }
252 }