Merge branch 'maint'
[hoomd-blue.git] / test / unit / test_communication.cc
blobbe00dc9e948203e15c2e4e398385cff92d1a1721
1 /*
2 Highly Optimized Object-oriented Many-particle Dynamics -- Blue Edition
3 (HOOMD-blue) Open Source Software License Copyright 2009-2014 The Regents of
4 the University of Michigan All rights reserved.
6 HOOMD-blue may contain modifications ("Contributions") provided, and to which
7 copyright is held, by various Contributors who have granted The Regents of the
8 University of Michigan the right to modify and/or distribute such Contributions.
10 You may redistribute, use, and create derivate works of HOOMD-blue, in source
11 and binary forms, provided you abide by the following conditions:
13 * Redistributions of source code must retain the above copyright notice, this
14 list of conditions, and the following disclaimer both in the code and
15 prominently in any materials provided with the distribution.
17 * Redistributions in binary form must reproduce the above copyright notice, this
18 list of conditions, and the following disclaimer in the documentation and/or
19 other materials provided with the distribution.
21 * All publications and presentations based on HOOMD-blue, including any reports
22 or published results obtained, in whole or in part, with HOOMD-blue, will
23 acknowledge its use according to the terms posted at the time of submission on:
24 http://codeblue.umich.edu/hoomd-blue/citations.html
26 * Any electronic documents citing HOOMD-Blue will link to the HOOMD-Blue website:
27 http://codeblue.umich.edu/hoomd-blue/
29 * Apart from the above required attributions, neither the name of the copyright
30 holder nor the names of HOOMD-blue's contributors may be used to endorse or
31 promote products derived from this software without specific prior written
32 permission.
34 Disclaimer
36 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' AND
37 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND/OR ANY
39 WARRANTIES THAT THIS SOFTWARE IS FREE OF INFRINGEMENT ARE DISCLAIMED.
41 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
42 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
43 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
44 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
45 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
46 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
47 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 #ifdef ENABLE_MPI
52 #define CHECK_CLOSE(a,b,tol) ( fabs(a-b) < 0.01*tol*fabs(a))
54 //! name the boost unit test module
55 #define BOOST_TEST_MODULE CommunicationTests
57 // this has to be included after naming the test module
58 #include "boost_utf_configure.h"
60 #include "System.h"
62 #include <boost/shared_ptr.hpp>
63 #include <boost/bind.hpp>
65 #include "ExecutionConfiguration.h"
66 #include "Communicator.h"
67 #include "DomainDecomposition.h"
69 #include "ConstForceCompute.h"
70 #include "TwoStepNVE.h"
71 #include "IntegratorTwoStep.h"
73 #ifdef ENABLE_CUDA
74 #include "CommunicatorGPU.h"
75 #endif
77 #include <algorithm>
79 #define TO_TRICLINIC(v) dest_box.makeCoordinates(ref_box.makeFraction(make_scalar3(v.x,v.y,v.z)))
80 #define TO_POS4(v) make_scalar4(v.x,v.y,v.z,h_pos.data[rtag].w)
81 #define FROM_TRICLINIC(v) ref_box.makeCoordinates(dest_box.makeFraction(make_scalar3(v.x,v.y,v.z)))
83 using namespace boost;
85 //! Typedef for function that creates the Communnicator on the CPU or GPU
86 typedef boost::function<boost::shared_ptr<Communicator> (boost::shared_ptr<SystemDefinition> sysdef,
87 boost::shared_ptr<DomainDecomposition> decomposition)> communicator_creator;
89 boost::shared_ptr<Communicator> base_class_communicator_creator(boost::shared_ptr<SystemDefinition> sysdef,
90 boost::shared_ptr<DomainDecomposition> decomposition);
92 #ifdef ENABLE_CUDA
93 boost::shared_ptr<Communicator> gpu_communicator_creator(boost::shared_ptr<SystemDefinition> sysdef,
94 boost::shared_ptr<DomainDecomposition> decomposition);
95 #endif
97 void test_domain_decomposition(boost::shared_ptr<ExecutionConfiguration> exec_conf)
99 // this test needs to be run on eight processors
100 int size;
101 MPI_Comm_size(MPI_COMM_WORLD, &size);
102 BOOST_REQUIRE_EQUAL(size,8);
104 // create a system with eight particles
105 boost::shared_ptr<SystemDefinition> sysdef(new SystemDefinition(8, // number of particles
106 BoxDim(2.0), // box dimensions
107 1, // number of particle types
108 0, // number of bond types
109 0, // number of angle types
110 0, // number of dihedral types
111 0, // number of dihedral types
112 exec_conf));
116 boost::shared_ptr<ParticleData> pdata(sysdef->getParticleData());
118 ArrayHandle<Scalar4> h_pos(pdata->getPositions(), access_location::host, access_mode::readwrite);
120 // set up eight particles, one in every domain
121 h_pos.data[0].x = -0.5;
122 h_pos.data[0].y = -0.5;
123 h_pos.data[0].z = -0.5;
125 h_pos.data[1].x = 0.5;
126 h_pos.data[1].y = -0.5;
127 h_pos.data[1].z = -0.5;
129 h_pos.data[2].x = -0.5;
130 h_pos.data[2].y = 0.5;
131 h_pos.data[2].z = -0.5;
133 h_pos.data[3].x = 0.5;
134 h_pos.data[3].y = 0.5;
135 h_pos.data[3].z = -0.5;
137 h_pos.data[4].x = -0.5;
138 h_pos.data[4].y = -0.5;
139 h_pos.data[4].z = 0.5;
141 h_pos.data[5].x = 0.5;
142 h_pos.data[5].y = -0.5;
143 h_pos.data[5].z = 0.5;
145 h_pos.data[6].x = -0.5;
146 h_pos.data[6].y = 0.5;
147 h_pos.data[6].z = 0.5;
149 h_pos.data[7].x = 0.5;
150 h_pos.data[7].y = 0.5;
151 h_pos.data[7].z = 0.5;
154 SnapshotParticleData snap(8);
155 pdata->takeSnapshot(snap);
157 // initialize a 2x2x2 domain decomposition on processor with rank 0
158 boost::shared_ptr<DomainDecomposition> decomposition(new DomainDecomposition(exec_conf, pdata->getBox().getL()));
160 pdata->setDomainDecomposition(decomposition);
162 // check that periodic flags are correctly set on the box
163 BOOST_CHECK_EQUAL(pdata->getBox().getPeriodic().x, 0);
164 BOOST_CHECK_EQUAL(pdata->getBox().getPeriodic().y, 0);
165 BOOST_CHECK_EQUAL(pdata->getBox().getPeriodic().z, 0);
167 pdata->initializeFromSnapshot(snap);
169 // check that every domain has exactly one particle
170 BOOST_CHECK_EQUAL(pdata->getN(), 1);
172 // check that every particle ended up in the domain to where it belongs
173 BOOST_CHECK_EQUAL(pdata->getOwnerRank(0), 0);
174 BOOST_CHECK_EQUAL(pdata->getOwnerRank(1), 1);
175 BOOST_CHECK_EQUAL(pdata->getOwnerRank(2), 2);
176 BOOST_CHECK_EQUAL(pdata->getOwnerRank(3), 3);
177 BOOST_CHECK_EQUAL(pdata->getOwnerRank(4), 4);
178 BOOST_CHECK_EQUAL(pdata->getOwnerRank(5), 5);
179 BOOST_CHECK_EQUAL(pdata->getOwnerRank(6), 6);
180 BOOST_CHECK_EQUAL(pdata->getOwnerRank(7), 7);
182 // check that the positions have been transferred correctly
183 Scalar3 pos = pdata->getPosition(0);
184 BOOST_CHECK_CLOSE(pos.x, -0.5, tol);
185 BOOST_CHECK_CLOSE(pos.y, -0.5, tol);
186 BOOST_CHECK_CLOSE(pos.z, -0.5, tol);
188 pos = pdata->getPosition(1);
189 BOOST_CHECK_CLOSE(pos.x, 0.5, tol);
190 BOOST_CHECK_CLOSE(pos.y, -0.5, tol);
191 BOOST_CHECK_CLOSE(pos.z, -0.5, tol);
193 pos = pdata->getPosition(2);
194 BOOST_CHECK_CLOSE(pos.x, -0.5, tol);
195 BOOST_CHECK_CLOSE(pos.y, 0.5, tol);
196 BOOST_CHECK_CLOSE(pos.z, -0.5, tol);
198 pos = pdata->getPosition(3);
199 BOOST_CHECK_CLOSE(pos.x, 0.5, tol);
200 BOOST_CHECK_CLOSE(pos.y, 0.5, tol);
201 BOOST_CHECK_CLOSE(pos.z, -0.5, tol);
203 pos = pdata->getPosition(4);
204 BOOST_CHECK_CLOSE(pos.x, -0.5, tol);
205 BOOST_CHECK_CLOSE(pos.y, -0.5, tol);
206 BOOST_CHECK_CLOSE(pos.z, 0.5, tol);
208 pos = pdata->getPosition(5);
209 BOOST_CHECK_CLOSE(pos.x, 0.5, tol);
210 BOOST_CHECK_CLOSE(pos.y, -0.5, tol);
211 BOOST_CHECK_CLOSE(pos.z, 0.5, tol);
213 pos = pdata->getPosition(6);
214 BOOST_CHECK_CLOSE(pos.x, -0.5, tol);
215 BOOST_CHECK_CLOSE(pos.y, 0.5, tol);
216 BOOST_CHECK_CLOSE(pos.z, 0.5, tol);
218 pos = pdata->getPosition(7);
219 BOOST_CHECK_CLOSE(pos.x, 0.5, tol);
220 BOOST_CHECK_CLOSE(pos.y, 0.5, tol);
221 BOOST_CHECK_CLOSE(pos.z, 0.5, tol);
224 //! Test particle migration of Communicator
225 void test_communicator_migrate(communicator_creator comm_creator, boost::shared_ptr<ExecutionConfiguration> exec_conf,
226 BoxDim dest_box)
228 // this test needs to be run on eight processors
229 int size;
230 MPI_Comm_size(MPI_COMM_WORLD, &size);
231 BOOST_REQUIRE_EQUAL(size,8);
233 BoxDim ref_box = BoxDim(2.0);
234 // create a system with eight particles
235 boost::shared_ptr<SystemDefinition> sysdef(new SystemDefinition(8, // number of particles
236 dest_box, // box dimensions
237 1, // number of particle types
238 0, // number of bond types
239 0, // number of angle types
240 0, // number of dihedral types
241 0, // number of dihedral types
242 exec_conf));
246 boost::shared_ptr<ParticleData> pdata(sysdef->getParticleData());
248 pdata->setPosition(0, TO_TRICLINIC(make_scalar3(-0.5,-0.5,-0.5)),false);
249 pdata->setPosition(1, TO_TRICLINIC(make_scalar3( 0.5,-0.5,-0.5)),false);
250 pdata->setPosition(2, TO_TRICLINIC(make_scalar3(-0.5, 0.5,-0.5)),false);
251 pdata->setPosition(3, TO_TRICLINIC(make_scalar3( 0.5, 0.5,-0.5)),false);
252 pdata->setPosition(4, TO_TRICLINIC(make_scalar3(-0.5,-0.5, 0.5)),false);
253 pdata->setPosition(5, TO_TRICLINIC(make_scalar3( 0.5,-0.5, 0.5)),false);
254 pdata->setPosition(6, TO_TRICLINIC(make_scalar3(-0.5, 0.5, 0.5)),false);
255 pdata->setPosition(7, TO_TRICLINIC(make_scalar3( 0.5, 0.5, 0.5)),false);
257 SnapshotParticleData snap(8);
259 pdata->takeSnapshot(snap);
261 // initialize a 2x2x2 domain decomposition on processor with rank 0
262 boost::shared_ptr<DomainDecomposition> decomposition(new DomainDecomposition(exec_conf, pdata->getBox().getL(),2,2,2));
264 boost::shared_ptr<Communicator> comm = comm_creator(sysdef, decomposition);
266 pdata->setDomainDecomposition(decomposition);
268 pdata->initializeFromSnapshot(snap);
270 // migrate atoms
271 comm->migrateParticles();
273 // check that every domain has exactly one particle
274 BOOST_CHECK_EQUAL(pdata->getN(), 1);
276 // check that every particle stayed where it was
277 BOOST_CHECK_EQUAL(pdata->getOwnerRank(0), 0);
278 BOOST_CHECK_EQUAL(pdata->getOwnerRank(1), 1);
279 BOOST_CHECK_EQUAL(pdata->getOwnerRank(2), 2);
280 BOOST_CHECK_EQUAL(pdata->getOwnerRank(3), 3);
281 BOOST_CHECK_EQUAL(pdata->getOwnerRank(4), 4);
282 BOOST_CHECK_EQUAL(pdata->getOwnerRank(5), 5);
283 BOOST_CHECK_EQUAL(pdata->getOwnerRank(6), 6);
284 BOOST_CHECK_EQUAL(pdata->getOwnerRank(7), 7);
286 // Now move particle 0 into domain 1
287 pdata->setPosition(0, TO_TRICLINIC(make_scalar3(0.1,-0.5,-0.5)),false);
288 // move particle 1 into domain 2
289 pdata->setPosition(1, TO_TRICLINIC(make_scalar3(-0.2, 0.5, -0.5)),false);
290 // move particle 2 into domain 3
291 pdata->setPosition(2, TO_TRICLINIC(make_scalar3(0.2, 0.3, -0.5)),false);
292 // move particle 3 into domain 4
293 pdata->setPosition(3, TO_TRICLINIC(make_scalar3(-0.5, -0.3, 0.2)),false);
294 // move particle 4 into domain 5
295 pdata->setPosition(4, TO_TRICLINIC(make_scalar3(0.1, -0.3, 0.2)),false);
296 // move particle 5 into domain 6
297 pdata->setPosition(5, TO_TRICLINIC(make_scalar3(-0.2, 0.4, 0.2)),false);
298 // move particle 6 into domain 7
299 pdata->setPosition(6, TO_TRICLINIC(make_scalar3(0.6, 0.1, 0.2)),false);
300 // move particle 7 into domain 0
301 pdata->setPosition(7, TO_TRICLINIC(make_scalar3(-0.6, -0.1,- 0.2)),false);
303 // migrate atoms
304 comm->migrateParticles();
306 // check that every particle has ended up in the right domain
307 BOOST_CHECK_EQUAL(pdata->getOwnerRank(0), 1);
308 BOOST_CHECK_EQUAL(pdata->getOwnerRank(1), 2);
309 BOOST_CHECK_EQUAL(pdata->getOwnerRank(2), 3);
310 BOOST_CHECK_EQUAL(pdata->getOwnerRank(3), 4);
311 BOOST_CHECK_EQUAL(pdata->getOwnerRank(4), 5);
312 BOOST_CHECK_EQUAL(pdata->getOwnerRank(5), 6);
313 BOOST_CHECK_EQUAL(pdata->getOwnerRank(6), 7);
314 BOOST_CHECK_EQUAL(pdata->getOwnerRank(7), 0);
316 // check positions
317 Scalar3 pos = pdata->getPosition(0);
318 pos = FROM_TRICLINIC(pos);
319 BOOST_CHECK_CLOSE(pos.x, 0.1, tol);
320 BOOST_CHECK_CLOSE(pos.y, -0.5, tol);
321 BOOST_CHECK_CLOSE(pos.z, -0.5, tol);
323 pos = pdata->getPosition(1);
324 pos = FROM_TRICLINIC(pos);
325 BOOST_CHECK_CLOSE(pos.x, -0.2, tol);
326 BOOST_CHECK_CLOSE(pos.y, 0.5, tol);
327 BOOST_CHECK_CLOSE(pos.z, -0.5, tol);
329 pos = pdata->getPosition(2);
330 pos = FROM_TRICLINIC(pos);
331 BOOST_CHECK_CLOSE(pos.x, 0.2, tol);
332 BOOST_CHECK_CLOSE(pos.y, 0.3, tol);
333 BOOST_CHECK_CLOSE(pos.z, -0.5, tol);
335 pos = pdata->getPosition(3);
336 pos = FROM_TRICLINIC(pos);
337 BOOST_CHECK_CLOSE(pos.x, -0.5, tol);
338 BOOST_CHECK_CLOSE(pos.y, -0.3, tol);
339 BOOST_CHECK_CLOSE(pos.z, 0.2, tol);
341 pos = pdata->getPosition(4);
342 pos = FROM_TRICLINIC(pos);
343 BOOST_CHECK_CLOSE(pos.x, 0.1, tol);
344 BOOST_CHECK_CLOSE(pos.y, -0.3, tol);
345 BOOST_CHECK_CLOSE(pos.z, 0.2, tol);
347 pos = pdata->getPosition(5);
348 pos = FROM_TRICLINIC(pos);
349 BOOST_CHECK_CLOSE(pos.x, -0.2, tol);
350 BOOST_CHECK_CLOSE(pos.y, 0.4, tol);
351 BOOST_CHECK_CLOSE(pos.z, 0.2, tol);
353 pos = pdata->getPosition(6);
354 pos = FROM_TRICLINIC(pos);
355 BOOST_CHECK_CLOSE(pos.x, 0.6, tol);
356 BOOST_CHECK_CLOSE(pos.y, 0.1, tol);
357 BOOST_CHECK_CLOSE(pos.z, 0.2, tol);
359 pos = pdata->getPosition(7);
360 pos = FROM_TRICLINIC(pos);
361 BOOST_CHECK_CLOSE(pos.x, -0.6, tol);
362 BOOST_CHECK_CLOSE(pos.y, -0.1, tol);
363 BOOST_CHECK_CLOSE(pos.z, -0.2, tol);
366 // check that that particles are correctly wrapped across the boundary
369 // particle 0 crosses the global boundary in +x direction
370 pdata->setPosition(0, TO_TRICLINIC(make_scalar3(1.1,-0.5,-0.5)),false);
371 // particle 1 crosses the global bounadry in the -x direction
372 pdata->setPosition(1, TO_TRICLINIC(make_scalar3(-1.1, 0.5, -0.5)),false);
373 // particle 2 crosses the global boundary in the + y direction
374 pdata->setPosition(2, TO_TRICLINIC(make_scalar3(0.2, 1.3, -0.5)),false);
375 // particle 3 crosses the global boundary in the - y direction
376 pdata->setPosition(3, TO_TRICLINIC(make_scalar3(-0.5, -1.5, 0.2)),false);
377 // particle 4 crosses the global boundary in the + z direction
378 pdata->setPosition(4, TO_TRICLINIC(make_scalar3(0.1, -0.3, 1.6)),false);
379 // particle 5 crosses the global boundary in the + z direction and in the -x direction
380 pdata->setPosition(5, TO_TRICLINIC(make_scalar3(-1.1, 0.4, 1.25)),false);
381 // particle 6 crosses the global boundary in the + z direction and in the +x direction
382 pdata->setPosition(6, TO_TRICLINIC(make_scalar3(1.3, 0.1, 1.05)),false);
383 // particle 7 crosses the global boundary in the - z direction
384 pdata->setPosition(7, TO_TRICLINIC(make_scalar3(-0.6, -0.1,- 1.5)),false);
386 // migrate particles
387 comm->migrateParticles();
389 // check number of particles
390 switch (exec_conf->getRank())
392 case 0:
393 BOOST_CHECK_EQUAL(pdata->getN(), 1);
394 break;
395 case 1:
396 BOOST_CHECK_EQUAL(pdata->getN(), 2);
397 break;
398 case 2:
399 BOOST_CHECK_EQUAL(pdata->getN(), 1);
400 break;
401 case 3:
402 BOOST_CHECK_EQUAL(pdata->getN(), 2);
403 break;
404 case 4:
405 BOOST_CHECK_EQUAL(pdata->getN(), 1);
406 break;
407 case 5:
408 BOOST_CHECK_EQUAL(pdata->getN(), 0);
409 break;
410 case 6:
411 BOOST_CHECK_EQUAL(pdata->getN(), 1);
412 break;
413 case 7:
414 BOOST_CHECK_EQUAL(pdata->getN(), 0);
415 break;
418 // check that every particle has ended up in the right domain
419 BOOST_CHECK_EQUAL(pdata->getOwnerRank(0), 0);
420 BOOST_CHECK_EQUAL(pdata->getOwnerRank(1), 3);
421 BOOST_CHECK_EQUAL(pdata->getOwnerRank(2), 1);
422 BOOST_CHECK_EQUAL(pdata->getOwnerRank(3), 6);
423 BOOST_CHECK_EQUAL(pdata->getOwnerRank(4), 1);
424 BOOST_CHECK_EQUAL(pdata->getOwnerRank(5), 3);
425 BOOST_CHECK_EQUAL(pdata->getOwnerRank(6), 2);
426 BOOST_CHECK_EQUAL(pdata->getOwnerRank(7), 4);
428 // check positions (taking into account that particles should have been wrapped)
429 pos = pdata->getPosition(0);
430 pos = FROM_TRICLINIC(pos);
431 BOOST_CHECK_CLOSE(pos.x, -0.9, tol);
432 BOOST_CHECK_CLOSE(pos.y, -0.5, tol);
433 BOOST_CHECK_CLOSE(pos.z, -0.5, tol);
435 pos = pdata->getPosition(1);
436 pos = FROM_TRICLINIC(pos);
437 BOOST_CHECK_CLOSE(pos.x, 0.9, tol);
438 BOOST_CHECK_CLOSE(pos.y, 0.5, tol);
439 BOOST_CHECK_CLOSE(pos.z, -0.5, tol);
441 pos = pdata->getPosition(2);
442 pos = FROM_TRICLINIC(pos);
443 BOOST_CHECK_CLOSE(pos.x, 0.2, tol);
444 BOOST_CHECK_CLOSE(pos.y, -0.7, tol);
445 BOOST_CHECK_CLOSE(pos.z, -0.5, tol);
447 pos = pdata->getPosition(3);
448 pos = FROM_TRICLINIC(pos);
449 BOOST_CHECK_CLOSE(pos.x, -0.5, tol);
450 BOOST_CHECK_CLOSE(pos.y, 0.5, tol);
451 BOOST_CHECK_CLOSE(pos.z, 0.2, tol);
453 pos = pdata->getPosition(4);
454 pos = FROM_TRICLINIC(pos);
455 BOOST_CHECK_CLOSE(pos.x, 0.1, tol);
456 BOOST_CHECK_CLOSE(pos.y, -0.3, tol);
457 BOOST_CHECK_CLOSE(pos.z, -0.4, tol);
459 pos = pdata->getPosition(5);
460 pos = FROM_TRICLINIC(pos);
461 BOOST_CHECK_CLOSE(pos.x, 0.9, tol);
462 BOOST_CHECK_CLOSE(pos.y, 0.4, tol);
463 BOOST_CHECK_CLOSE(pos.z,-0.75, tol);
465 pos = pdata->getPosition(6);
466 pos = FROM_TRICLINIC(pos);
467 BOOST_CHECK_CLOSE(pos.x, -0.7, tol);
468 BOOST_CHECK_CLOSE(pos.y, 0.1, tol);
469 BOOST_CHECK_CLOSE(pos.z,-0.95, tol);
471 pos = pdata->getPosition(7);
472 pos = FROM_TRICLINIC(pos);
473 BOOST_CHECK_CLOSE(pos.x, -0.6, tol);
474 BOOST_CHECK_CLOSE(pos.y, -0.1, tol);
475 BOOST_CHECK_CLOSE(pos.z, 0.5, tol);
478 //! Test ghost particle communication
479 void test_communicator_ghosts(communicator_creator comm_creator, boost::shared_ptr<ExecutionConfiguration> exec_conf, const BoxDim& dest_box)
481 // this test needs to be run on eight processors
482 int size;
483 MPI_Comm_size(MPI_COMM_WORLD, &size);
484 BOOST_REQUIRE_EQUAL(size,8);
486 // create a system with eight particles
487 boost::shared_ptr<SystemDefinition> sysdef(new SystemDefinition(16, // number of particles
488 dest_box, // box dimensions
489 1, // number of particle types
490 0, // number of bond types
491 0, // number of angle types
492 0, // number of dihedral types
493 0, // number of dihedral types
494 exec_conf));
498 boost::shared_ptr<ParticleData> pdata(sysdef->getParticleData());
499 BoxDim ref_box = BoxDim(2.0);
501 // Set initial atom positions
502 // place one particle in the middle of every box (outside the ghost layer)
503 pdata->setPosition(0, TO_TRICLINIC(make_scalar3(-0.5,-0.5,-0.5)),false);
504 pdata->setPosition(1, TO_TRICLINIC(make_scalar3( 0.5,-0.5,-0.5)),false);
505 pdata->setPosition(2, TO_TRICLINIC(make_scalar3(-0.5, 0.5,-0.5)),false);
506 pdata->setPosition(3, TO_TRICLINIC(make_scalar3( 0.5, 0.5,-0.5)),false);
507 pdata->setPosition(4, TO_TRICLINIC(make_scalar3(-0.5,-0.5, 0.5)),false);
508 pdata->setPosition(5, TO_TRICLINIC(make_scalar3( 0.5,-0.5, 0.5)),false);
509 pdata->setPosition(6, TO_TRICLINIC(make_scalar3(-0.5, 0.5, 0.5)),false);
510 pdata->setPosition(7, TO_TRICLINIC(make_scalar3( 0.5, 0.5, 0.5)),false);
512 // place particle 8 in the same box as particle 0 and in the ghost layer of its +x neighbor
513 pdata->setPosition(8, TO_TRICLINIC(make_scalar3(-0.02,-0.5,-0.5)),false);
514 // place particle 9 in the same box as particle 0 and in the ghost layer of its +y neighbor
515 pdata->setPosition(9, TO_TRICLINIC(make_scalar3(-0.5,-0.05,-0.5)),false);
516 // place particle 10 in the same box as particle 0 and in the ghost layer of its +y and +z neighbor
517 pdata->setPosition(10, TO_TRICLINIC(make_scalar3(-0.5, -0.01,-0.05)),false);
518 // place particle 11 in the same box as particle 0 and in the ghost layer of its +x and +y neighbor
519 pdata->setPosition(11, TO_TRICLINIC(make_scalar3(-0.05, -0.03,-0.5)),false);
520 // place particle 12 in the same box as particle 0 and in the ghost layer of its +x , +y and +z neighbor
521 pdata->setPosition(12, TO_TRICLINIC(make_scalar3(-0.05, -0.03,-0.001)),false);
522 // place particle 13 in the same box as particle 1 and in the ghost layer of its -x neighbor
523 pdata->setPosition(13, TO_TRICLINIC(make_scalar3( 0.05, -0.5, -0.5)),false);
524 // place particle 14 in the same box as particle 1 and in the ghost layer of its -x neighbor and its +y neighbor
525 pdata->setPosition(14, TO_TRICLINIC(make_scalar3( 0.01, -0.0123, -0.5)),false);
526 // place particle 15 in the same box as particle 1 and in the ghost layer of its -x neighbor, of its +y neighbor, and of its +z neighbor
527 pdata->setPosition(15, TO_TRICLINIC(make_scalar3( 0.01, -0.0123, -0.09)),false);
529 // distribute particle data on processors
530 SnapshotParticleData snap(16);
531 pdata->takeSnapshot(snap);
533 // initialize a 2x2x2 domain decomposition on processor with rank 0
534 boost::shared_ptr<DomainDecomposition> decomposition(new DomainDecomposition(exec_conf, pdata->getBox().getL()));
535 boost::shared_ptr<Communicator> comm = comm_creator(sysdef, decomposition);
537 pdata->setDomainDecomposition(decomposition);
539 pdata->initializeFromSnapshot(snap);
541 // width of ghost layer
542 Scalar ghost_layer_width = Scalar(0.05)*ref_box.getL().x;
543 comm->setGhostLayerWidth(ghost_layer_width);
544 // Check number of particles
545 switch (exec_conf->getRank())
547 case 0:
548 BOOST_CHECK_EQUAL(pdata->getN(), 6);
549 break;
550 case 1:
551 BOOST_CHECK_EQUAL(pdata->getN(), 4);
552 break;
553 case 2:
554 BOOST_CHECK_EQUAL(pdata->getN(), 1);
555 break;
556 case 3:
557 BOOST_CHECK_EQUAL(pdata->getN(), 1);
558 break;
559 case 4:
560 BOOST_CHECK_EQUAL(pdata->getN(), 1);
561 break;
562 case 5:
563 BOOST_CHECK_EQUAL(pdata->getN(), 1);
564 break;
565 case 6:
566 BOOST_CHECK_EQUAL(pdata->getN(), 1);
567 break;
568 case 7:
569 BOOST_CHECK_EQUAL(pdata->getN(), 1);
570 break;
573 // we should have zero ghosts before the exchange
574 BOOST_CHECK_EQUAL(pdata->getNGhosts(),0);
576 // set ghost exchange flags for position
577 CommFlags flags(0);
578 flags[comm_flag::position] = 1;
579 flags[comm_flag::tag] = 1;
580 comm->setFlags(flags);
582 // exchange ghosts
583 comm->exchangeGhosts();
585 Scalar3 cmp;
586 // check ghost atom numbers and positions
588 ArrayHandle<Scalar4> h_pos(pdata->getPositions(), access_location::host, access_mode::read);
589 ArrayHandle<unsigned int> h_global_rtag(pdata->getRTags(), access_location::host, access_mode::read);
590 unsigned int rtag;
591 switch (exec_conf->getRank())
593 case 0:
594 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 3);
596 rtag = h_global_rtag.data[13];
597 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
598 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
599 BOOST_CHECK_CLOSE(cmp.x, 0.05,tol);
600 BOOST_CHECK_CLOSE(cmp.y, -0.5,tol);
601 BOOST_CHECK_CLOSE(cmp.z, -0.5,tol);
603 rtag = h_global_rtag.data[14];
604 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
605 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
606 BOOST_CHECK_CLOSE(cmp.x, 0.01,tol);
607 BOOST_CHECK_CLOSE(cmp.y, -0.0123, tol);
608 BOOST_CHECK_CLOSE(cmp.z, -0.5,tol);
610 rtag = h_global_rtag.data[15];
611 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
612 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
613 BOOST_CHECK_CLOSE(cmp.x, 0.01, tol);
614 BOOST_CHECK_CLOSE(cmp.y, -0.0123, tol);
615 BOOST_CHECK_CLOSE(cmp.z, -0.09, tol);
616 break;
617 case 1:
618 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 3);
620 rtag = h_global_rtag.data[8];
621 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
622 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
623 BOOST_CHECK_CLOSE(cmp.x, -0.02, tol);
624 BOOST_CHECK_CLOSE(cmp.y, -0.5, tol);
625 BOOST_CHECK_CLOSE(cmp.z, -0.5, tol);
627 rtag = h_global_rtag.data[11];
628 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
629 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
630 BOOST_CHECK_CLOSE(cmp.x, -0.05, tol);
631 BOOST_CHECK_CLOSE(cmp.y, -0.03, tol);
632 BOOST_CHECK_CLOSE(cmp.z, -0.5, tol);
634 rtag = h_global_rtag.data[12];
635 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
636 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
637 BOOST_CHECK_CLOSE(cmp.x, -0.05, tol);
638 BOOST_CHECK_CLOSE(cmp.y, -0.03, tol);
639 BOOST_CHECK_CLOSE(cmp.z, -0.001, tol);
641 break;
642 case 2:
643 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 6);
645 rtag = h_global_rtag.data[9];
646 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
647 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
648 BOOST_CHECK_CLOSE(cmp.x, -0.5, tol);
649 BOOST_CHECK_CLOSE(cmp.y, -0.05, tol);
650 BOOST_CHECK_CLOSE(cmp.z, -0.5, tol);
652 rtag = h_global_rtag.data[10];
653 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
654 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
655 BOOST_CHECK_CLOSE(cmp.x, -0.5, tol);
656 BOOST_CHECK_CLOSE(cmp.y, -0.01, tol);
657 BOOST_CHECK_CLOSE(cmp.z, -0.05, tol);
659 rtag = h_global_rtag.data[11];
660 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
661 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
662 BOOST_CHECK_CLOSE(cmp.x, -0.05, tol);
663 BOOST_CHECK_CLOSE(cmp.y, -0.03, tol);
664 BOOST_CHECK_CLOSE(cmp.z, -0.5, tol);
666 rtag = h_global_rtag.data[12];
667 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
668 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
669 BOOST_CHECK_CLOSE(cmp.x, -0.05, tol);
670 BOOST_CHECK_CLOSE(cmp.y, -0.03, tol);
671 BOOST_CHECK_CLOSE(cmp.z, -0.001, tol);
673 rtag = h_global_rtag.data[14];
674 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
675 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
676 BOOST_CHECK_CLOSE(cmp.x, 0.01, tol);
677 BOOST_CHECK_CLOSE(cmp.y, -0.0123, tol);
678 BOOST_CHECK_CLOSE(cmp.z, -0.5, tol);
680 rtag = h_global_rtag.data[15];
681 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
682 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
683 BOOST_CHECK_CLOSE(cmp.x, 0.01, tol);
684 BOOST_CHECK_CLOSE(cmp.y, -0.0123, tol);
685 BOOST_CHECK_CLOSE(cmp.z, -0.09, tol);
687 break;
688 case 3:
689 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 4);
691 rtag = h_global_rtag.data[11];
692 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
693 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
694 BOOST_CHECK_CLOSE(cmp.x, -0.05, tol);
695 BOOST_CHECK_CLOSE(cmp.y, -0.03, tol);
696 BOOST_CHECK_CLOSE(cmp.z, -0.5, tol);
698 rtag = h_global_rtag.data[12];
699 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
700 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
701 BOOST_CHECK_CLOSE(cmp.x, -0.05, tol);
702 BOOST_CHECK_CLOSE(cmp.y, -0.03, tol);
703 BOOST_CHECK_CLOSE(cmp.z, -0.001, tol);
705 rtag = h_global_rtag.data[14];
706 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
707 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
708 BOOST_CHECK_CLOSE(cmp.x, 0.01,tol);
709 BOOST_CHECK_CLOSE(cmp.y, -0.0123, tol);
710 BOOST_CHECK_CLOSE(cmp.z, -0.5,tol);
712 rtag = h_global_rtag.data[15];
713 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
714 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
715 BOOST_CHECK_CLOSE(cmp.x, 0.01, tol);
716 BOOST_CHECK_CLOSE(cmp.y, -0.0123, tol);
717 BOOST_CHECK_CLOSE(cmp.z, -0.09, tol);
719 break;
720 case 4:
721 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 3);
723 rtag = h_global_rtag.data[10];
724 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
725 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
726 BOOST_CHECK_CLOSE(cmp.x, -0.5, tol);
727 BOOST_CHECK_CLOSE(cmp.y, -0.01, tol);
728 BOOST_CHECK_CLOSE(cmp.z, -0.05, tol);
730 rtag = h_global_rtag.data[12];
731 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
732 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
733 BOOST_CHECK_CLOSE(cmp.x, -0.05, tol);
734 BOOST_CHECK_CLOSE(cmp.y, -0.03, tol);
735 BOOST_CHECK_CLOSE(cmp.z, -0.001, tol);
737 rtag = h_global_rtag.data[15];
738 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
739 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
740 BOOST_CHECK_CLOSE(cmp.x, 0.01, tol);
741 BOOST_CHECK_CLOSE(cmp.y, -0.0123, tol);
742 BOOST_CHECK_CLOSE(cmp.z, -0.09, tol);
743 break;
745 case 5:
746 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 2);
748 rtag = h_global_rtag.data[12];
749 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
750 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
751 BOOST_CHECK_CLOSE(cmp.x, -0.05, tol);
752 BOOST_CHECK_CLOSE(cmp.y, -0.03, tol);
753 BOOST_CHECK_CLOSE(cmp.z, -0.001, tol);
755 rtag = h_global_rtag.data[15];
756 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
757 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
758 BOOST_CHECK_CLOSE(cmp.x, 0.01, tol);
759 BOOST_CHECK_CLOSE(cmp.y, -0.0123, tol);
760 BOOST_CHECK_CLOSE(cmp.z, -0.09, tol);
761 break;
763 case 6:
764 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 3);
766 rtag = h_global_rtag.data[10];
767 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
768 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
769 BOOST_CHECK_CLOSE(cmp.x, -0.5, tol);
770 BOOST_CHECK_CLOSE(cmp.y, -0.01, tol);
771 BOOST_CHECK_CLOSE(cmp.z, -0.05, tol);
773 rtag = h_global_rtag.data[12];
774 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
775 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
776 BOOST_CHECK_CLOSE(cmp.x, -0.05, tol);
777 BOOST_CHECK_CLOSE(cmp.y, -0.03, tol);
778 BOOST_CHECK_CLOSE(cmp.z, -0.001, tol);
780 rtag = h_global_rtag.data[15];
781 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
782 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
783 BOOST_CHECK_CLOSE(cmp.x, 0.01, tol);
784 BOOST_CHECK_CLOSE(cmp.y, -0.0123, tol);
785 BOOST_CHECK_CLOSE(cmp.z, -0.09, tol);
786 break;
788 case 7:
789 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 2);
791 rtag = h_global_rtag.data[12];
792 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
793 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
794 BOOST_CHECK_CLOSE(cmp.x, -0.05, tol);
795 BOOST_CHECK_CLOSE(cmp.y, -0.03, tol);
796 BOOST_CHECK_CLOSE(cmp.z, -0.001, tol);
798 rtag = h_global_rtag.data[15];
799 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
800 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
801 BOOST_CHECK_CLOSE(cmp.x, 0.01, tol);
802 BOOST_CHECK_CLOSE(cmp.y, -0.0123, tol);
803 BOOST_CHECK_CLOSE(cmp.z, -0.09, tol);
804 break;
808 // migrate atoms
809 // this should reset the number of ghost particles
810 comm->migrateParticles();
812 BOOST_CHECK_EQUAL(pdata->getNGhosts(),0);
815 // check handling of periodic boundary conditions
818 // place some atoms in a ghost layer at a global boundary
820 // place particle 8 in the same box as particle 0 and in the ghost layer of its -x neighbor and -y neighbor
821 pdata->setPosition(8, TO_TRICLINIC(make_scalar3(-0.02,-0.95,-0.5)),false);
822 // place particle 9 in the same box as particle 0 and in the ghost layer of its -y neighbor
823 pdata->setPosition(9, TO_TRICLINIC(make_scalar3(-0.5,-0.96,-0.5)),false);
824 // place particle 10 in the same box as particle 0 and in the ghost layer of its +y neighbor and -z neighbor
825 pdata->setPosition(10, TO_TRICLINIC(make_scalar3(-0.5, -0.01,-0.97)),false);
826 // place particle 11 in the same box as particle 0 and in the ghost layer of its -x and -y neighbor
827 pdata->setPosition(11, TO_TRICLINIC(make_scalar3(-0.97, -0.99,-0.5)),false);
828 // place particle 12 in the same box as particle 0 and in the ghost layer of its -x , -y and -z neighbor
829 pdata->setPosition(12, TO_TRICLINIC(make_scalar3(-0.997, -0.998,-0.999)),false);
830 // place particle 13 in the same box as particle 0 and in the ghost layer of its -x neighbor and +y neighbor
831 pdata->setPosition(13, TO_TRICLINIC(make_scalar3( -0.96, -0.005, -0.50)),false);
832 // place particle 14 in the same box as particle 7 and in the ghost layer of its +x neighbor and its +y neighbor
833 pdata->setPosition(14, TO_TRICLINIC(make_scalar3( 0.901, .98, 0.50)),false);
834 // place particle 15 in the same box as particle 7 and in the ghost layer of its +x neighbor, of its +y neighbor, and of its +z neighbor
835 pdata->setPosition(15, TO_TRICLINIC(make_scalar3( 0.99, 0.999, 0.9999)),false);
837 // migrate atoms in their respective boxes
838 comm->migrateParticles();
840 // Check number of particles
841 switch (exec_conf->getRank())
843 case 0:
844 BOOST_CHECK_EQUAL(pdata->getN(), 7);
845 break;
846 case 1:
847 BOOST_CHECK_EQUAL(pdata->getN(), 1);
848 break;
849 case 2:
850 BOOST_CHECK_EQUAL(pdata->getN(), 1);
851 break;
852 case 3:
853 BOOST_CHECK_EQUAL(pdata->getN(), 1);
854 break;
855 case 4:
856 BOOST_CHECK_EQUAL(pdata->getN(), 1);
857 break;
858 case 5:
859 BOOST_CHECK_EQUAL(pdata->getN(), 1);
860 break;
861 case 6:
862 BOOST_CHECK_EQUAL(pdata->getN(), 1);
863 break;
864 case 7:
865 BOOST_CHECK_EQUAL(pdata->getN(), 3);
866 break;
869 // exchange ghosts
870 comm->exchangeGhosts();
872 // check ghost atom numbers and positions, taking into account that the particles should have been
873 // wrapped across the boundaries
875 ArrayHandle<Scalar4> h_pos(pdata->getPositions(), access_location::host, access_mode::read);
876 ArrayHandle<unsigned int> h_global_rtag(pdata->getRTags(), access_location::host, access_mode::read);
877 unsigned int rtag;
878 switch (exec_conf->getRank())
880 case 0:
881 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 1);
883 rtag = h_global_rtag.data[15];
884 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
885 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
886 BOOST_CHECK_CLOSE(cmp.x, -1.01, tol);
887 BOOST_CHECK_CLOSE(cmp.y, -1.001, tol);
888 BOOST_CHECK_CLOSE(cmp.z, -1.0001, tol);
889 break;
891 case 1:
892 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 5);
894 rtag = h_global_rtag.data[8];
895 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
896 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
897 BOOST_CHECK_CLOSE(cmp.x, -0.02, tol);
898 BOOST_CHECK_CLOSE(cmp.y, -0.95, tol);
899 BOOST_CHECK_CLOSE(cmp.z, -0.5, tol);
901 rtag = h_global_rtag.data[11];
902 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
903 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
904 BOOST_CHECK_CLOSE(cmp.x, 1.03, tol);
905 BOOST_CHECK_CLOSE(cmp.y, -0.99, tol);
906 BOOST_CHECK_CLOSE(cmp.z, -0.5, tol);
908 rtag = h_global_rtag.data[12];
909 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
910 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
911 BOOST_CHECK_CLOSE(cmp.x, 1.003, tol);
912 BOOST_CHECK_CLOSE(cmp.y,-0.998, tol);
913 BOOST_CHECK_CLOSE(cmp.z,-0.999, tol);
915 rtag = h_global_rtag.data[13];
916 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
917 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
918 BOOST_CHECK_CLOSE(cmp.x, 1.04, tol);
919 BOOST_CHECK_CLOSE(cmp.y,-0.005, tol);
920 BOOST_CHECK_CLOSE(cmp.z,-0.50, tol);
923 rtag = h_global_rtag.data[15];
924 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
925 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
926 BOOST_CHECK_CLOSE(cmp.x, 0.99, tol);
927 BOOST_CHECK_CLOSE(cmp.y,-1.001, tol);
928 BOOST_CHECK_CLOSE(cmp.z,-1.0001, tol);
929 break;
931 case 2:
932 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 7);
933 rtag = h_global_rtag.data[8];
934 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
935 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
936 BOOST_CHECK_CLOSE(cmp.x, -0.02, tol);
937 BOOST_CHECK_CLOSE(cmp.y, 1.05, tol);
938 BOOST_CHECK_CLOSE(cmp.z, -0.5, tol);
940 rtag = h_global_rtag.data[9];
941 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
942 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
943 BOOST_CHECK_CLOSE(cmp.x, -0.5, tol);
944 BOOST_CHECK_CLOSE(cmp.y, 1.04, tol);
945 BOOST_CHECK_CLOSE(cmp.z, -0.5, tol);
947 rtag = h_global_rtag.data[10];
948 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
949 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
950 BOOST_CHECK_CLOSE(cmp.x, -0.5, tol);
951 BOOST_CHECK_CLOSE(cmp.y, -0.01, tol);
952 BOOST_CHECK_CLOSE(cmp.z,-0.97, tol);
954 rtag = h_global_rtag.data[11];
955 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
956 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
957 BOOST_CHECK_CLOSE(cmp.x, -0.97, tol);
958 BOOST_CHECK_CLOSE(cmp.y, 1.01, tol);
959 BOOST_CHECK_CLOSE(cmp.z, -0.5, tol);
961 rtag = h_global_rtag.data[12];
962 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
963 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
964 BOOST_CHECK_CLOSE(cmp.x, -0.997, tol);
965 BOOST_CHECK_CLOSE(cmp.y, 1.002, tol);
966 BOOST_CHECK_CLOSE(cmp.z, -0.999, tol);
968 rtag = h_global_rtag.data[13];
969 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
970 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
971 BOOST_CHECK_CLOSE(cmp.x, -0.96, tol);
972 BOOST_CHECK_CLOSE(cmp.y, -0.005, tol);
973 BOOST_CHECK_CLOSE(cmp.z, -0.50, tol);
975 rtag = h_global_rtag.data[15];
976 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
977 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
978 BOOST_CHECK_CLOSE(cmp.x, -1.01, tol);
979 BOOST_CHECK_CLOSE(cmp.y, 0.999, tol);
980 BOOST_CHECK_CLOSE(cmp.z,-1.0001, tol);
981 break;
983 case 3:
984 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 5);
986 rtag = h_global_rtag.data[8];
987 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
988 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
989 BOOST_CHECK_CLOSE(cmp.x, -0.02, tol);
990 BOOST_CHECK_CLOSE(cmp.y, 1.05, tol);
991 BOOST_CHECK_CLOSE(cmp.z, -0.5, tol);
993 rtag = h_global_rtag.data[11];
994 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
995 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
996 BOOST_CHECK_CLOSE(cmp.x, 1.03, tol);
997 BOOST_CHECK_CLOSE(cmp.y, 1.01, tol);
998 BOOST_CHECK_CLOSE(cmp.z, -0.5, tol);
1000 rtag = h_global_rtag.data[12];
1001 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1002 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1003 BOOST_CHECK_CLOSE(cmp.x, 1.003, tol);
1004 BOOST_CHECK_CLOSE(cmp.y, 1.002, tol);
1005 BOOST_CHECK_CLOSE(cmp.z,-0.999, tol);
1007 rtag = h_global_rtag.data[13];
1008 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1009 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1010 BOOST_CHECK_CLOSE(cmp.x, 1.04, tol);
1011 BOOST_CHECK_CLOSE(cmp.y,-0.005, tol);
1012 BOOST_CHECK_CLOSE(cmp.z,-0.50, tol);
1014 rtag = h_global_rtag.data[15];
1015 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1016 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1017 BOOST_CHECK_CLOSE(cmp.x, 0.99, tol);
1018 BOOST_CHECK_CLOSE(cmp.y, 0.999, tol);
1019 BOOST_CHECK_CLOSE(cmp.z,-1.0001, tol);
1020 break;
1022 case 4:
1023 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 4);
1025 rtag = h_global_rtag.data[10];
1026 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1027 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1028 BOOST_CHECK_CLOSE(cmp.x, -0.5, tol);
1029 BOOST_CHECK_CLOSE(cmp.y, -0.01, tol);
1030 BOOST_CHECK_CLOSE(cmp.z, 1.03, tol);
1032 rtag = h_global_rtag.data[12];
1033 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1034 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1035 BOOST_CHECK_CLOSE(cmp.x,-0.997, tol);
1036 BOOST_CHECK_CLOSE(cmp.y,-0.998, tol);
1037 BOOST_CHECK_CLOSE(cmp.z, 1.001, tol);
1039 rtag = h_global_rtag.data[14];
1040 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1041 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1042 BOOST_CHECK_CLOSE(cmp.x,-1.099, tol);
1043 BOOST_CHECK_CLOSE(cmp.y, -1.02, tol);
1044 BOOST_CHECK_CLOSE(cmp.z, 0.50, tol);
1046 rtag = h_global_rtag.data[15];
1047 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1048 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1049 BOOST_CHECK_CLOSE(cmp.x,-1.01, tol);
1050 BOOST_CHECK_CLOSE(cmp.y,-1.001, tol);
1051 BOOST_CHECK_CLOSE(cmp.z,0.9999, tol);
1052 break;
1054 case 5:
1055 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 3);
1057 rtag = h_global_rtag.data[12];
1058 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1059 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1060 BOOST_CHECK_CLOSE(cmp.x,1.003, tol);
1061 BOOST_CHECK_CLOSE(cmp.y,-0.998, tol);
1062 BOOST_CHECK_CLOSE(cmp.z,1.001, tol);
1064 rtag = h_global_rtag.data[14];
1065 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1066 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1067 BOOST_CHECK_CLOSE(cmp.x,0.901, tol);
1068 BOOST_CHECK_CLOSE(cmp.y,-1.02, tol);
1069 BOOST_CHECK_CLOSE(cmp.z,0.50, tol);
1071 rtag = h_global_rtag.data[15];
1072 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1073 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1074 BOOST_CHECK_CLOSE(cmp.x,0.99, tol);
1075 BOOST_CHECK_CLOSE(cmp.y,-1.001, tol);
1076 BOOST_CHECK_CLOSE(cmp.z,0.9999, tol);
1077 break;
1079 case 6:
1080 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 4);
1082 rtag = h_global_rtag.data[10];
1083 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1084 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1085 BOOST_CHECK_CLOSE(cmp.x,-0.5, tol);
1086 BOOST_CHECK_CLOSE(cmp.y,-0.01, tol);
1087 BOOST_CHECK_CLOSE(cmp.z,1.03, tol);
1089 rtag = h_global_rtag.data[12];
1090 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1091 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1092 BOOST_CHECK_CLOSE(cmp.x,-0.997, tol);
1093 BOOST_CHECK_CLOSE(cmp.y,1.002, tol);
1094 BOOST_CHECK_CLOSE(cmp.z,1.001, tol);
1096 rtag = h_global_rtag.data[14];
1097 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1098 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1099 BOOST_CHECK_CLOSE(cmp.x,-1.099, tol);
1100 BOOST_CHECK_CLOSE(cmp.y,0.98, tol);
1101 BOOST_CHECK_CLOSE(cmp.z,0.50, tol);
1103 rtag = h_global_rtag.data[15];
1104 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1105 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1106 BOOST_CHECK_CLOSE(cmp.x,-1.01, tol);
1107 BOOST_CHECK_CLOSE(cmp.y,0.999, tol);
1108 BOOST_CHECK_CLOSE(cmp.z,0.9999, tol);
1109 break;
1111 case 7:
1112 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 1);
1114 rtag = h_global_rtag.data[12];
1115 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1116 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1117 BOOST_CHECK_CLOSE(cmp.x,1.003, tol);
1118 BOOST_CHECK_CLOSE(cmp.y,1.002, tol);
1119 BOOST_CHECK_CLOSE(cmp.z,1.001, tol);
1120 break;
1125 // Test ghost updating
1128 // set some new positions for the ghost particles
1129 // the ghost particles could have moved anywhere
1130 // even outside the ghost layers or boxes they were in originally
1131 //(but they should not move further than half the skin length),
1134 unsigned int rtag;
1135 ArrayHandle<unsigned int> h_rtag(pdata->getRTags(), access_location::host, access_mode::read);
1136 ArrayHandle<Scalar4> h_pos(pdata->getPositions(), access_location::host, access_mode::readwrite);
1138 switch (exec_conf->getRank())
1140 case 0:
1141 rtag = h_rtag.data[8];
1142 h_pos.data[rtag].x = -0.12;
1143 h_pos.data[rtag].y = -1.05;
1144 h_pos.data[rtag].z = -0.6;
1145 h_pos.data[rtag] = TO_POS4(TO_TRICLINIC(h_pos.data[rtag]));
1147 rtag = h_rtag.data[9];
1148 h_pos.data[rtag].x = -0.03;
1149 h_pos.data[rtag].y = -1.09;
1150 h_pos.data[rtag].z = -0.3;
1151 h_pos.data[rtag] = TO_POS4(TO_TRICLINIC(h_pos.data[rtag]));
1153 rtag = h_rtag.data[10];
1154 h_pos.data[rtag].x = -0.11;
1155 h_pos.data[rtag].y = 0.01;
1156 h_pos.data[rtag].z = -1.02;
1157 h_pos.data[rtag] = TO_POS4(TO_TRICLINIC(h_pos.data[rtag]));
1159 rtag = h_rtag.data[11];
1160 h_pos.data[rtag].x = -0.81;
1161 h_pos.data[rtag].y = -0.92;
1162 h_pos.data[rtag].z = -0.2;
1163 h_pos.data[rtag] = TO_POS4(TO_TRICLINIC(h_pos.data[rtag]));
1165 rtag = h_rtag.data[12];
1166 h_pos.data[rtag].x = -1.02;
1167 h_pos.data[rtag].y = -1.05;
1168 h_pos.data[rtag].z = -1.100;
1169 h_pos.data[rtag] = TO_POS4(TO_TRICLINIC(h_pos.data[rtag]));
1171 rtag = h_rtag.data[13];
1172 h_pos.data[rtag].x = -0.89;
1173 h_pos.data[rtag].y = 0.005;
1174 h_pos.data[rtag].z = -0.99;
1175 h_pos.data[rtag] = TO_POS4(TO_TRICLINIC(h_pos.data[rtag]));
1177 break;
1178 case 7:
1179 rtag = h_rtag.data[14];
1180 h_pos.data[rtag].x = 1.123;
1181 h_pos.data[rtag].y = 1.121;
1182 h_pos.data[rtag].z = 0.9;
1183 h_pos.data[rtag] = TO_POS4(TO_TRICLINIC(h_pos.data[rtag]));
1185 rtag = h_rtag.data[15];
1186 h_pos.data[rtag].x = 0.85;
1187 h_pos.data[rtag].y = 1.001;
1188 h_pos.data[rtag].z = 1.012;
1189 h_pos.data[rtag] = TO_POS4(TO_TRICLINIC(h_pos.data[rtag]));
1191 break;
1192 default:
1193 break;
1197 // update ghosts
1198 comm->beginUpdateGhosts(0);
1199 comm->finishUpdateGhosts(0);
1201 // check ghost positions, taking into account that the particles should have been wrapped across the boundaries
1203 ArrayHandle<Scalar4> h_pos(pdata->getPositions(), access_location::host, access_mode::read);
1204 ArrayHandle<unsigned int> h_global_rtag(pdata->getRTags(), access_location::host, access_mode::read);
1205 unsigned int rtag;
1206 int rank;
1207 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1208 switch (rank)
1210 case 0:
1211 rtag = h_global_rtag.data[15];
1212 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1213 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1214 BOOST_CHECK_CLOSE(cmp.x, -1.15, tol);
1215 BOOST_CHECK_CLOSE(cmp.y, -0.999, tol);
1216 BOOST_CHECK_CLOSE(cmp.z, -0.988, tol);
1217 break;
1219 case 1:
1220 rtag = h_global_rtag.data[8];
1221 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1222 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1223 BOOST_CHECK_CLOSE(cmp.x, -0.12, tol);
1224 BOOST_CHECK_CLOSE(cmp.y, -1.05, tol);
1225 BOOST_CHECK_CLOSE(cmp.z, -0.6, tol);
1227 rtag = h_global_rtag.data[11];
1228 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1229 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1230 BOOST_CHECK_CLOSE(cmp.x, 1.19, tol);
1231 BOOST_CHECK_CLOSE(cmp.y, -0.92, tol);
1232 BOOST_CHECK_CLOSE(cmp.z, -0.2, tol);
1234 rtag = h_global_rtag.data[12];
1235 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1236 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1237 BOOST_CHECK_CLOSE(cmp.x, 0.98, tol);
1238 BOOST_CHECK_CLOSE(cmp.y,-1.05, tol);
1239 BOOST_CHECK_CLOSE(cmp.z,-1.100, tol);
1241 rtag = h_global_rtag.data[13];
1242 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1243 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1244 BOOST_CHECK_CLOSE(cmp.x, 1.11, tol);
1245 BOOST_CHECK_CLOSE(cmp.y, 0.005, tol);
1246 BOOST_CHECK_CLOSE(cmp.z,-0.99, tol);
1249 rtag = h_global_rtag.data[15];
1250 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1251 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1252 BOOST_CHECK_CLOSE(cmp.x, 0.85, tol);
1253 BOOST_CHECK_CLOSE(cmp.y,-0.999, tol);
1254 BOOST_CHECK_CLOSE(cmp.z,-0.988, tol);
1255 break;
1257 case 2:
1258 rtag = h_global_rtag.data[8];
1259 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1260 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1261 BOOST_CHECK_CLOSE(cmp.x, -0.12, tol);
1262 BOOST_CHECK_CLOSE(cmp.y, 0.95, tol);
1263 BOOST_CHECK_CLOSE(cmp.z, -0.6, tol);
1265 rtag = h_global_rtag.data[9];
1266 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1267 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1268 BOOST_CHECK_CLOSE(cmp.x, -0.03, tol);
1269 BOOST_CHECK_CLOSE(cmp.y, 0.91, tol);
1270 BOOST_CHECK_CLOSE(cmp.z, -0.3, tol);
1272 rtag = h_global_rtag.data[10];
1273 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1274 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1275 BOOST_CHECK_CLOSE(cmp.x, -0.11, tol);
1276 BOOST_CHECK_CLOSE(cmp.y, 0.01, tol);
1277 BOOST_CHECK_CLOSE(cmp.z,-1.02, tol);
1279 rtag = h_global_rtag.data[11];
1280 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1281 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1282 BOOST_CHECK_CLOSE(cmp.x, -0.81, tol);
1283 BOOST_CHECK_CLOSE(cmp.y, 1.08, tol);
1284 BOOST_CHECK_CLOSE(cmp.z, -0.2, tol);
1286 rtag = h_global_rtag.data[12];
1287 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1288 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1289 BOOST_CHECK_CLOSE(cmp.x, -1.02, tol);
1290 BOOST_CHECK_CLOSE(cmp.y, 0.95, tol);
1291 BOOST_CHECK_CLOSE(cmp.z, -1.100, tol);
1293 rtag = h_global_rtag.data[13];
1294 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1295 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1296 BOOST_CHECK_CLOSE(cmp.x, -0.89, tol);
1297 BOOST_CHECK_CLOSE(cmp.y, 0.005, tol);
1298 BOOST_CHECK_CLOSE(cmp.z, -0.99, tol);
1300 rtag = h_global_rtag.data[15];
1301 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1302 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1303 BOOST_CHECK_CLOSE(cmp.x, -1.15, tol);
1304 BOOST_CHECK_CLOSE(cmp.y, 1.001, tol);
1305 BOOST_CHECK_CLOSE(cmp.z,-0.988, tol);
1306 break;
1308 case 3:
1309 rtag = h_global_rtag.data[8];
1310 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1311 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1312 BOOST_CHECK_CLOSE(cmp.x, -.12, tol);
1313 BOOST_CHECK_CLOSE(cmp.y, 0.95, tol);
1314 BOOST_CHECK_CLOSE(cmp.z,-0.6, tol);
1316 rtag = h_global_rtag.data[11];
1317 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1318 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1319 BOOST_CHECK_CLOSE(cmp.x, 1.19, tol);
1320 BOOST_CHECK_CLOSE(cmp.y, 1.08, tol);
1321 BOOST_CHECK_CLOSE(cmp.z, -0.2, tol);
1323 rtag = h_global_rtag.data[12];
1324 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1325 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1326 BOOST_CHECK_CLOSE(cmp.x, 0.98, tol);
1327 BOOST_CHECK_CLOSE(cmp.y, 0.95, tol);
1328 BOOST_CHECK_CLOSE(cmp.z,-1.100, tol);
1330 rtag = h_global_rtag.data[13];
1331 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1332 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1333 BOOST_CHECK_CLOSE(cmp.x, 1.11, tol);
1334 BOOST_CHECK_CLOSE(cmp.y, 0.005, tol);
1335 BOOST_CHECK_CLOSE(cmp.z,-0.99, tol);
1337 rtag = h_global_rtag.data[15];
1338 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1339 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1340 BOOST_CHECK_CLOSE(cmp.x, 0.85, tol);
1341 BOOST_CHECK_CLOSE(cmp.y, 1.001, tol);
1342 BOOST_CHECK_CLOSE(cmp.z,-0.988, tol);
1343 break;
1345 case 4:
1346 rtag = h_global_rtag.data[10];
1347 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1348 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1349 BOOST_CHECK_CLOSE(cmp.x, -0.11, tol);
1350 BOOST_CHECK_CLOSE(cmp.y, 0.01, tol);
1351 BOOST_CHECK_CLOSE(cmp.z, 0.98, tol);
1353 rtag = h_global_rtag.data[12];
1354 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1355 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1356 BOOST_CHECK_CLOSE(cmp.x,-1.02, tol);
1357 BOOST_CHECK_CLOSE(cmp.y,-1.05, tol);
1358 BOOST_CHECK_CLOSE(cmp.z, 0.90, tol);
1360 rtag = h_global_rtag.data[14];
1361 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1362 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1363 BOOST_CHECK_CLOSE(cmp.x,-0.877, tol);
1364 BOOST_CHECK_CLOSE(cmp.y,-0.879, tol);
1365 BOOST_CHECK_CLOSE(cmp.z, 0.90, tol);
1367 rtag = h_global_rtag.data[15];
1368 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1369 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1370 BOOST_CHECK_CLOSE(cmp.x,-1.15, tol);
1371 BOOST_CHECK_CLOSE(cmp.y,-0.999, tol);
1372 BOOST_CHECK_CLOSE(cmp.z, 1.012, tol);
1373 break;
1375 case 5:
1376 rtag = h_global_rtag.data[12];
1377 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1378 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1379 BOOST_CHECK_CLOSE(cmp.x,0.98, tol);
1380 BOOST_CHECK_CLOSE(cmp.y,-1.05, tol);
1381 BOOST_CHECK_CLOSE(cmp.z,0.900, tol);
1383 rtag = h_global_rtag.data[14];
1384 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1385 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1386 BOOST_CHECK_CLOSE(cmp.x,1.123, tol);
1387 BOOST_CHECK_CLOSE(cmp.y,-0.879, tol);
1388 BOOST_CHECK_CLOSE(cmp.z,0.90, tol);
1390 rtag = h_global_rtag.data[15];
1391 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1392 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1393 BOOST_CHECK_CLOSE(cmp.x,0.85, tol);
1394 BOOST_CHECK_CLOSE(cmp.y,-0.999, tol);
1395 BOOST_CHECK_CLOSE(cmp.z,1.012, tol);
1396 break;
1398 case 6:
1399 rtag = h_global_rtag.data[10];
1400 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1401 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1402 BOOST_CHECK_CLOSE(cmp.x,-0.11, tol);
1403 BOOST_CHECK_CLOSE(cmp.y, 0.01, tol);
1404 BOOST_CHECK_CLOSE(cmp.z,0.98, tol);
1406 rtag = h_global_rtag.data[12];
1407 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1408 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1409 BOOST_CHECK_CLOSE(cmp.x,-1.02, tol);
1410 BOOST_CHECK_CLOSE(cmp.y, 0.95, tol);
1411 BOOST_CHECK_CLOSE(cmp.z, 0.90, tol);
1413 rtag = h_global_rtag.data[14];
1414 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1415 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1416 BOOST_CHECK_CLOSE(cmp.x,-0.877, tol);
1417 BOOST_CHECK_CLOSE(cmp.y,1.121, tol);
1418 BOOST_CHECK_CLOSE(cmp.z,0.90, tol);
1420 rtag = h_global_rtag.data[15];
1421 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1422 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1423 BOOST_CHECK_CLOSE(cmp.x,-1.15, tol);
1424 BOOST_CHECK_CLOSE(cmp.y,1.001, tol);
1425 BOOST_CHECK_CLOSE(cmp.z,1.012, tol);
1426 break;
1428 case 7:
1429 rtag = h_global_rtag.data[12];
1430 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
1431 cmp = FROM_TRICLINIC(h_pos.data[rtag]);
1432 BOOST_CHECK_CLOSE(cmp.x,0.980, tol);
1433 BOOST_CHECK_CLOSE(cmp.y,0.950, tol);
1434 BOOST_CHECK_CLOSE(cmp.z,0.900, tol);
1435 break;
1441 //! Test particle communication for covalently bonded ghosts
1442 void test_communicator_bond_exchange(communicator_creator comm_creator, boost::shared_ptr<ExecutionConfiguration> exec_conf)
1444 // this test needs to be run on eight processors
1445 int size;
1446 MPI_Comm_size(MPI_COMM_WORLD, &size);
1447 BOOST_REQUIRE_EQUAL(size,8);
1449 // create a system with eight particles
1450 boost::shared_ptr<SystemDefinition> sysdef(new SystemDefinition(8, // number of particles
1451 BoxDim(2.0), // box dimensions
1452 1, // number of particle types
1453 1, // number of bond types
1454 0, // number of angle types
1455 0, // number of dihedral types
1456 0, // number of dihedral types
1457 exec_conf));
1461 boost::shared_ptr<ParticleData> pdata(sysdef->getParticleData());
1463 // Set initial atom positions
1464 // place one particle slightly away from the middle of every box (in direction towards
1465 // the center of the global box - bonds cannot extend over more than half the box length)
1466 pdata->setPosition(0, make_scalar3(-0.4,-0.4,-0.4),false);
1467 pdata->setPosition(1, make_scalar3( 0.4,-0.4,-0.4),false);
1468 pdata->setPosition(2, make_scalar3(-0.4, 0.4,-0.4),false);
1469 pdata->setPosition(3, make_scalar3( 0.4, 0.4,-0.4),false);
1470 pdata->setPosition(4, make_scalar3(-0.4,-0.4, 0.4),false);
1471 pdata->setPosition(5, make_scalar3( 0.4,-0.4, 0.4),false);
1472 pdata->setPosition(6, make_scalar3(-0.4, 0.4, 0.4),false);
1473 pdata->setPosition(7, make_scalar3( 0.4, 0.4, 0.4),false);
1475 // now bond these particles together, forming a cube
1477 boost::shared_ptr<BondData> bdata(sysdef->getBondData());
1479 bdata->addBondedGroup(Bond(0,0,1)); // bond 0
1480 bdata->addBondedGroup(Bond(0,0,2)); // bond 1
1481 bdata->addBondedGroup(Bond(0,0,4)); // bond 2
1482 bdata->addBondedGroup(Bond(0,1,3)); // bond 3
1483 bdata->addBondedGroup(Bond(0,1,5)); // bond 4
1484 bdata->addBondedGroup(Bond(0,2,3)); // bond 5
1485 bdata->addBondedGroup(Bond(0,2,6)); // bond 6
1486 bdata->addBondedGroup(Bond(0,3,7)); // bond 7
1487 bdata->addBondedGroup(Bond(0,4,5)); // bond 8
1488 bdata->addBondedGroup(Bond(0,4,6)); // bond 9
1489 bdata->addBondedGroup(Bond(0,5,7)); // bond 10
1490 bdata->addBondedGroup(Bond(0,6,7)); // bond 11
1492 SnapshotParticleData snap(8);
1493 pdata->takeSnapshot(snap);
1495 BondData::Snapshot bdata_snap(12);
1496 bdata->takeSnapshot(bdata_snap);
1498 // initialize a 2x2x2 domain decomposition on processor with rank 0
1499 boost::shared_ptr<DomainDecomposition> decomposition(new DomainDecomposition(exec_conf, pdata->getBox().getL()));
1500 boost::shared_ptr<Communicator> comm = comm_creator(sysdef, decomposition);
1502 // width of ghost layer
1503 Scalar ghost_layer_width = Scalar(0.1);
1504 comm->setGhostLayerWidth(ghost_layer_width);
1506 pdata->setDomainDecomposition(decomposition);
1508 // distribute particle data on processors
1509 pdata->initializeFromSnapshot(snap);
1511 // distribute bonds on processors
1512 bdata->initializeFromSnapshot(bdata_snap);
1514 // we should have one particle
1515 BOOST_CHECK_EQUAL(pdata->getN(), 1);
1517 // and zero ghost particles
1518 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 0);
1520 // check global number of bonds
1521 BOOST_CHECK_EQUAL(bdata->getNGlobal(), 12);
1523 // every domain should have three bonds
1524 BOOST_CHECK_EQUAL(bdata->getN(), 3);
1526 // exchange ghost particles
1527 comm->migrateParticles();
1529 // check that nothing has changed
1530 BOOST_CHECK_EQUAL(pdata->getN(), 1);
1531 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 0);
1532 BOOST_CHECK_EQUAL(bdata->getN(), 3);
1534 // now move particle 0 to box 1
1535 pdata->setPosition(0, make_scalar3(.3, -0.4, -0.4),false);
1537 // migrate particles
1538 comm->migrateParticles();
1540 switch(exec_conf->getRank())
1542 case 0:
1543 // box 0 should have zero particles and 0 bonds
1544 BOOST_CHECK_EQUAL(pdata->getN(), 0);
1545 BOOST_CHECK_EQUAL(bdata->getN(), 0);
1548 // we should not own any bonds
1549 ArrayHandle<unsigned int> h_rtag(bdata->getRTags(), access_location::host, access_mode::read);
1551 BOOST_CHECK(h_rtag.data[0] == GROUP_NOT_LOCAL);
1552 BOOST_CHECK(h_rtag.data[1] == GROUP_NOT_LOCAL);
1553 BOOST_CHECK(h_rtag.data[2] == GROUP_NOT_LOCAL);
1554 BOOST_CHECK(h_rtag.data[3] == GROUP_NOT_LOCAL);
1555 BOOST_CHECK(h_rtag.data[4] == GROUP_NOT_LOCAL);
1556 BOOST_CHECK(h_rtag.data[5] == GROUP_NOT_LOCAL);
1557 BOOST_CHECK(h_rtag.data[6] == GROUP_NOT_LOCAL);
1558 BOOST_CHECK(h_rtag.data[7] == GROUP_NOT_LOCAL);
1559 BOOST_CHECK(h_rtag.data[8] == GROUP_NOT_LOCAL);
1560 BOOST_CHECK(h_rtag.data[9] == GROUP_NOT_LOCAL);
1561 BOOST_CHECK(h_rtag.data[10] == GROUP_NOT_LOCAL);
1562 BOOST_CHECK(h_rtag.data[11] == GROUP_NOT_LOCAL);
1565 break;
1566 case 1:
1567 // box 1 should have two particles and 5 bonds
1568 BOOST_CHECK_EQUAL(pdata->getN(), 2);
1569 BOOST_CHECK_EQUAL(bdata->getN(), 5);
1572 // we should own bonds 0-4
1573 ArrayHandle<unsigned int> h_rtag(bdata->getRTags(), access_location::host, access_mode::read);
1575 BOOST_REQUIRE(h_rtag.data[0] < bdata->getN());
1576 BOOST_REQUIRE(h_rtag.data[1] < bdata->getN());
1577 BOOST_REQUIRE(h_rtag.data[2] < bdata->getN());
1578 BOOST_REQUIRE(h_rtag.data[3] < bdata->getN());
1579 BOOST_REQUIRE(h_rtag.data[4] < bdata->getN());
1580 BOOST_REQUIRE(h_rtag.data[5] == GROUP_NOT_LOCAL);
1581 BOOST_REQUIRE(h_rtag.data[6] == GROUP_NOT_LOCAL);
1582 BOOST_REQUIRE(h_rtag.data[7] == GROUP_NOT_LOCAL);
1583 BOOST_REQUIRE(h_rtag.data[8] == GROUP_NOT_LOCAL);
1584 BOOST_REQUIRE(h_rtag.data[9] == GROUP_NOT_LOCAL);
1585 BOOST_REQUIRE(h_rtag.data[10] == GROUP_NOT_LOCAL);
1586 BOOST_REQUIRE(h_rtag.data[11] == GROUP_NOT_LOCAL);
1588 ArrayHandle<BondData::members_t> h_bonds(bdata->getMembersArray(), access_location::host, access_mode::read);
1589 ArrayHandle<unsigned int> h_tag(bdata->getTags(), access_location::host, access_mode::read);
1590 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[0]],0);
1591 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[0]].tag[0],0);
1592 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[0]].tag[1],1);
1594 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[1]],1);
1595 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[1]].tag[0],0);
1596 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[1]].tag[1],2);
1598 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[2]],2);
1599 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[2]].tag[0],0);
1600 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[2]].tag[1],4);
1602 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[3]],3);
1603 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[3]].tag[0],1);
1604 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[3]].tag[1],3);
1606 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[4]],4);
1607 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[4]].tag[0],1);
1608 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[4]].tag[1],5);
1610 break;
1611 case 2:
1612 // box 2 should have three bonds
1613 BOOST_CHECK_EQUAL(pdata->getN(), 1);
1614 BOOST_CHECK_EQUAL(bdata->getN(), 3);
1617 // we should own bonds 1,5,6
1618 ArrayHandle<unsigned int> h_rtag(bdata->getRTags(), access_location::host, access_mode::read);
1620 BOOST_REQUIRE(h_rtag.data[0] == GROUP_NOT_LOCAL);
1621 BOOST_REQUIRE(h_rtag.data[1] < bdata->getN());
1622 BOOST_REQUIRE(h_rtag.data[2] == GROUP_NOT_LOCAL);
1623 BOOST_REQUIRE(h_rtag.data[3] == GROUP_NOT_LOCAL);
1624 BOOST_REQUIRE(h_rtag.data[4] == GROUP_NOT_LOCAL);
1625 BOOST_REQUIRE(h_rtag.data[5] < bdata->getN());
1626 BOOST_REQUIRE(h_rtag.data[6] < bdata->getN());
1627 BOOST_REQUIRE(h_rtag.data[7] == GROUP_NOT_LOCAL);
1628 BOOST_REQUIRE(h_rtag.data[8] == GROUP_NOT_LOCAL);
1629 BOOST_REQUIRE(h_rtag.data[9] == GROUP_NOT_LOCAL);
1630 BOOST_REQUIRE(h_rtag.data[10] == GROUP_NOT_LOCAL);
1631 BOOST_REQUIRE(h_rtag.data[11] == GROUP_NOT_LOCAL);
1633 ArrayHandle<BondData::members_t> h_bonds(bdata->getMembersArray(), access_location::host, access_mode::read);
1634 ArrayHandle<unsigned int> h_tag(bdata->getTags(), access_location::host, access_mode::read);
1635 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[1]],1);
1636 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[1]].tag[0],0);
1637 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[1]].tag[1],2);
1639 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[5]],5);
1640 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[5]].tag[0],2);
1641 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[5]].tag[1],3);
1643 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[6]],6);
1644 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[6]].tag[0],2);
1645 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[6]].tag[1],6);
1647 break;
1648 case 3:
1649 // box 3 should have three bonds
1650 BOOST_CHECK_EQUAL(pdata->getN(), 1);
1651 BOOST_CHECK_EQUAL(bdata->getN(), 3);
1654 // we should own bonds 3,5,7
1655 ArrayHandle<unsigned int> h_rtag(bdata->getRTags(), access_location::host, access_mode::read);
1657 BOOST_REQUIRE(h_rtag.data[0] == GROUP_NOT_LOCAL);
1658 BOOST_REQUIRE(h_rtag.data[1] == GROUP_NOT_LOCAL);
1659 BOOST_REQUIRE(h_rtag.data[2] == GROUP_NOT_LOCAL);
1660 BOOST_REQUIRE(h_rtag.data[3] < bdata->getN());
1661 BOOST_REQUIRE(h_rtag.data[4] == GROUP_NOT_LOCAL);
1662 BOOST_REQUIRE(h_rtag.data[5] < bdata->getN());
1663 BOOST_REQUIRE(h_rtag.data[6] == GROUP_NOT_LOCAL);
1664 BOOST_REQUIRE(h_rtag.data[7] < bdata->getN());
1665 BOOST_REQUIRE(h_rtag.data[8] == GROUP_NOT_LOCAL);
1666 BOOST_REQUIRE(h_rtag.data[9] == GROUP_NOT_LOCAL);
1667 BOOST_REQUIRE(h_rtag.data[10] == GROUP_NOT_LOCAL);
1668 BOOST_REQUIRE(h_rtag.data[11] == GROUP_NOT_LOCAL);
1670 ArrayHandle<BondData::members_t> h_bonds(bdata->getMembersArray(), access_location::host, access_mode::read);
1671 ArrayHandle<unsigned int> h_tag(bdata->getTags(), access_location::host, access_mode::read);
1672 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[3]],3);
1673 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[3]].tag[0],1);
1674 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[3]].tag[1],3);
1676 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[5]],5);
1677 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[5]].tag[0],2);
1678 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[5]].tag[1],3);
1680 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[7]],7);
1681 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[7]].tag[0],3);
1682 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[7]].tag[1],7);
1684 break;
1685 case 4:
1686 // box 4 should have three bonds
1687 BOOST_CHECK_EQUAL(pdata->getN(), 1);
1688 BOOST_CHECK_EQUAL(bdata->getN(), 3);
1691 // we should own bonds 2,8,9
1692 ArrayHandle<unsigned int> h_rtag(bdata->getRTags(), access_location::host, access_mode::read);
1694 BOOST_REQUIRE(h_rtag.data[0] == GROUP_NOT_LOCAL);
1695 BOOST_REQUIRE(h_rtag.data[1] == GROUP_NOT_LOCAL);
1696 BOOST_REQUIRE(h_rtag.data[2] < bdata->getN());
1697 BOOST_REQUIRE(h_rtag.data[3] == GROUP_NOT_LOCAL);
1698 BOOST_REQUIRE(h_rtag.data[4] == GROUP_NOT_LOCAL);
1699 BOOST_REQUIRE(h_rtag.data[5] == GROUP_NOT_LOCAL);
1700 BOOST_REQUIRE(h_rtag.data[6] == GROUP_NOT_LOCAL);
1701 BOOST_REQUIRE(h_rtag.data[7] == GROUP_NOT_LOCAL);
1702 BOOST_REQUIRE(h_rtag.data[8] < bdata->getN());
1703 BOOST_REQUIRE(h_rtag.data[9] < bdata->getN());
1704 BOOST_REQUIRE(h_rtag.data[10] == GROUP_NOT_LOCAL);
1705 BOOST_REQUIRE(h_rtag.data[11] == GROUP_NOT_LOCAL);
1707 ArrayHandle<BondData::members_t> h_bonds(bdata->getMembersArray(), access_location::host, access_mode::read);
1708 ArrayHandle<unsigned int> h_tag(bdata->getTags(), access_location::host, access_mode::read);
1710 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[2]],2);
1711 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[2]].tag[0],0);
1712 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[2]].tag[1],4);
1714 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[8]],8);
1715 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[8]].tag[0],4);
1716 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[8]].tag[1],5);
1718 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[9]],9);
1719 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[9]].tag[0],4);
1720 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[9]].tag[1],6);
1722 break;
1723 case 5:
1724 // box 5 should have three bonds
1725 BOOST_CHECK_EQUAL(pdata->getN(), 1);
1726 BOOST_CHECK_EQUAL(bdata->getN(), 3);
1729 // we should own bonds 4,8,10
1730 ArrayHandle<unsigned int> h_rtag(bdata->getRTags(), access_location::host, access_mode::read);
1732 BOOST_REQUIRE(h_rtag.data[0] == GROUP_NOT_LOCAL);
1733 BOOST_REQUIRE(h_rtag.data[1] == GROUP_NOT_LOCAL);
1734 BOOST_REQUIRE(h_rtag.data[2] == GROUP_NOT_LOCAL);
1735 BOOST_REQUIRE(h_rtag.data[3] == GROUP_NOT_LOCAL);
1736 BOOST_REQUIRE(h_rtag.data[4] < bdata->getN());
1737 BOOST_REQUIRE(h_rtag.data[5] == GROUP_NOT_LOCAL);
1738 BOOST_REQUIRE(h_rtag.data[6] == GROUP_NOT_LOCAL);
1739 BOOST_REQUIRE(h_rtag.data[7] == GROUP_NOT_LOCAL);
1740 BOOST_REQUIRE(h_rtag.data[8] < bdata->getN());
1741 BOOST_REQUIRE(h_rtag.data[9] == GROUP_NOT_LOCAL);
1742 BOOST_REQUIRE(h_rtag.data[10] < bdata->getN());
1743 BOOST_REQUIRE(h_rtag.data[11] == GROUP_NOT_LOCAL);
1745 ArrayHandle<BondData::members_t> h_bonds(bdata->getMembersArray(), access_location::host, access_mode::read);
1746 ArrayHandle<unsigned int> h_tag(bdata->getTags(), access_location::host, access_mode::read);
1748 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[4]],4);
1749 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[4]].tag[0],1);
1750 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[4]].tag[1],5);
1752 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[8]],8);
1753 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[8]].tag[0],4);
1754 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[8]].tag[1],5);
1756 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[10]],10);
1757 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[10]].tag[0],5);
1758 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[10]].tag[1],7);
1760 break;
1761 case 6:
1762 // box 6 should have three bonds
1763 BOOST_CHECK_EQUAL(pdata->getN(), 1);
1764 BOOST_CHECK_EQUAL(bdata->getN(), 3);
1767 // we should own bonds 6,9,11
1768 ArrayHandle<unsigned int> h_rtag(bdata->getRTags(), access_location::host, access_mode::read);
1770 BOOST_REQUIRE(h_rtag.data[0] == GROUP_NOT_LOCAL);
1771 BOOST_REQUIRE(h_rtag.data[1] == GROUP_NOT_LOCAL);
1772 BOOST_REQUIRE(h_rtag.data[2] == GROUP_NOT_LOCAL);
1773 BOOST_REQUIRE(h_rtag.data[3] == GROUP_NOT_LOCAL);
1774 BOOST_REQUIRE(h_rtag.data[4] == GROUP_NOT_LOCAL);
1775 BOOST_REQUIRE(h_rtag.data[5] == GROUP_NOT_LOCAL);
1776 BOOST_REQUIRE(h_rtag.data[6] < bdata->getN());
1777 BOOST_REQUIRE(h_rtag.data[7] == GROUP_NOT_LOCAL);
1778 BOOST_REQUIRE(h_rtag.data[8] == GROUP_NOT_LOCAL);
1779 BOOST_REQUIRE(h_rtag.data[9] < bdata->getN());
1780 BOOST_REQUIRE(h_rtag.data[10] == GROUP_NOT_LOCAL);
1781 BOOST_REQUIRE(h_rtag.data[11] < bdata->getN());
1783 ArrayHandle<BondData::members_t> h_bonds(bdata->getMembersArray(), access_location::host, access_mode::read);
1784 ArrayHandle<unsigned int> h_tag(bdata->getTags(), access_location::host, access_mode::read);
1786 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[6]],6);
1787 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[6]].tag[0],2);
1788 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[6]].tag[1],6);
1790 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[9]],9);
1791 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[9]].tag[0],4);
1792 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[9]].tag[1],6);
1794 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[11]],11);
1795 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[11]].tag[0],6);
1796 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[11]].tag[1],7);
1798 break;
1799 case 7:
1800 // box 7 should have three bonds
1801 BOOST_CHECK_EQUAL(pdata->getN(), 1);
1802 BOOST_CHECK_EQUAL(bdata->getN(), 3);
1805 // we should own bonds 7,10,11
1806 ArrayHandle<unsigned int> h_rtag(bdata->getRTags(), access_location::host, access_mode::read);
1808 BOOST_REQUIRE(h_rtag.data[0] == GROUP_NOT_LOCAL);
1809 BOOST_REQUIRE(h_rtag.data[1] == GROUP_NOT_LOCAL);
1810 BOOST_REQUIRE(h_rtag.data[2] == GROUP_NOT_LOCAL);
1811 BOOST_REQUIRE(h_rtag.data[3] == GROUP_NOT_LOCAL);
1812 BOOST_REQUIRE(h_rtag.data[4] == GROUP_NOT_LOCAL);
1813 BOOST_REQUIRE(h_rtag.data[5] == GROUP_NOT_LOCAL);
1814 BOOST_REQUIRE(h_rtag.data[6] == GROUP_NOT_LOCAL);
1815 BOOST_REQUIRE(h_rtag.data[7] < bdata->getN());
1816 BOOST_REQUIRE(h_rtag.data[8] == GROUP_NOT_LOCAL);
1817 BOOST_REQUIRE(h_rtag.data[9] == GROUP_NOT_LOCAL);
1818 BOOST_REQUIRE(h_rtag.data[10] < bdata->getN());
1819 BOOST_REQUIRE(h_rtag.data[11] < bdata->getN());
1821 ArrayHandle<BondData::members_t> h_bonds(bdata->getMembersArray(), access_location::host, access_mode::read);
1822 ArrayHandle<unsigned int> h_tag(bdata->getTags(), access_location::host, access_mode::read);
1824 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[7]],7);
1825 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[7]].tag[0],3);
1826 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[7]].tag[1],7);
1828 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[10]],10);
1829 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[10]].tag[0],5);
1830 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[10]].tag[1],7);
1832 BOOST_CHECK_EQUAL(h_tag.data[h_rtag.data[11]],11);
1833 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[11]].tag[0],6);
1834 BOOST_CHECK_EQUAL(h_bonds.data[h_rtag.data[11]].tag[1],7);
1836 break;
1839 // move particle back
1840 pdata->setPosition(0, make_scalar3(-.4, -0.4, -0.4),false);
1842 comm->migrateParticles();
1844 // check that old state has been restored
1845 BOOST_CHECK_EQUAL(pdata->getN(), 1);
1846 BOOST_CHECK_EQUAL(bdata->getN(), 3);
1848 // swap ptl 0 and 1
1849 pdata->setPosition(0, make_scalar3(.4, -0.4, -0.4),false);
1850 pdata->setPosition(1, make_scalar3(-.4, -0.4, -0.4),false);
1852 comm->migrateParticles();
1854 switch(exec_conf->getRank())
1856 case 0:
1857 BOOST_CHECK_EQUAL(pdata->getN(), 1);
1858 BOOST_CHECK_EQUAL(bdata->getN(), 3);
1861 // we should own three bonds
1862 ArrayHandle<unsigned int> h_rtag(bdata->getRTags(), access_location::host, access_mode::read);
1864 BOOST_CHECK(h_rtag.data[0] < bdata->getN());
1865 BOOST_CHECK(h_rtag.data[1] == GROUP_NOT_LOCAL);
1866 BOOST_CHECK(h_rtag.data[2] == GROUP_NOT_LOCAL);
1867 BOOST_CHECK(h_rtag.data[3] < bdata->getN());
1868 BOOST_CHECK(h_rtag.data[4] < bdata->getN());
1869 BOOST_CHECK(h_rtag.data[5] == GROUP_NOT_LOCAL);
1870 BOOST_CHECK(h_rtag.data[6] == GROUP_NOT_LOCAL);
1871 BOOST_CHECK(h_rtag.data[7] == GROUP_NOT_LOCAL);
1872 BOOST_CHECK(h_rtag.data[8] == GROUP_NOT_LOCAL);
1873 BOOST_CHECK(h_rtag.data[9] == GROUP_NOT_LOCAL);
1874 BOOST_CHECK(h_rtag.data[10] == GROUP_NOT_LOCAL);
1875 BOOST_CHECK(h_rtag.data[11] == GROUP_NOT_LOCAL);
1878 break;
1879 case 1:
1880 // box 1 should own three bonds
1881 BOOST_CHECK_EQUAL(pdata->getN(), 1);
1882 BOOST_CHECK_EQUAL(bdata->getN(), 3);
1885 // we should own bonds 0-2
1886 ArrayHandle<unsigned int> h_rtag(bdata->getRTags(), access_location::host, access_mode::read);
1888 BOOST_CHECK(h_rtag.data[0] < bdata->getN());
1889 BOOST_CHECK(h_rtag.data[1] < bdata->getN());
1890 BOOST_CHECK(h_rtag.data[2] < bdata->getN());
1891 BOOST_CHECK(h_rtag.data[3] == GROUP_NOT_LOCAL);
1892 BOOST_CHECK(h_rtag.data[4] == GROUP_NOT_LOCAL);
1893 BOOST_CHECK(h_rtag.data[5] == GROUP_NOT_LOCAL);
1894 BOOST_CHECK(h_rtag.data[6] == GROUP_NOT_LOCAL);
1895 BOOST_CHECK(h_rtag.data[7] == GROUP_NOT_LOCAL);
1896 BOOST_CHECK(h_rtag.data[8] == GROUP_NOT_LOCAL);
1897 BOOST_CHECK(h_rtag.data[9] == GROUP_NOT_LOCAL);
1898 BOOST_CHECK(h_rtag.data[10] == GROUP_NOT_LOCAL);
1899 BOOST_CHECK(h_rtag.data[11] == GROUP_NOT_LOCAL);
1902 break;
1904 default:
1905 break;
1908 // swap ptl 0 and 6
1909 pdata->setPosition(0, make_scalar3(-.4, 0.4, 0.4),false);
1910 pdata->setPosition(6, make_scalar3(.4, -0.4, -0.4),false);
1912 comm->migrateParticles();
1914 switch(exec_conf->getRank())
1916 case 0:
1917 BOOST_CHECK_EQUAL(pdata->getN(), 1);
1918 BOOST_CHECK_EQUAL(bdata->getN(), 3);
1921 // we should have three bonds
1922 ArrayHandle<unsigned int> h_rtag(bdata->getRTags(), access_location::host, access_mode::read);
1924 BOOST_CHECK(h_rtag.data[0] < bdata->getN());
1925 BOOST_CHECK(h_rtag.data[1] == GROUP_NOT_LOCAL);
1926 BOOST_CHECK(h_rtag.data[2] == GROUP_NOT_LOCAL);
1927 BOOST_CHECK(h_rtag.data[3] < bdata->getN());
1928 BOOST_CHECK(h_rtag.data[4] < bdata->getN());
1929 BOOST_CHECK(h_rtag.data[5] == GROUP_NOT_LOCAL);
1930 BOOST_CHECK(h_rtag.data[6] == GROUP_NOT_LOCAL);
1931 BOOST_CHECK(h_rtag.data[7] == GROUP_NOT_LOCAL);
1932 BOOST_CHECK(h_rtag.data[8] == GROUP_NOT_LOCAL);
1933 BOOST_CHECK(h_rtag.data[9] == GROUP_NOT_LOCAL);
1934 BOOST_CHECK(h_rtag.data[10] == GROUP_NOT_LOCAL);
1935 BOOST_CHECK(h_rtag.data[11] == GROUP_NOT_LOCAL);
1937 break;
1939 case 1:
1940 BOOST_CHECK_EQUAL(pdata->getN(), 1);
1941 BOOST_CHECK_EQUAL(bdata->getN(), 3);
1944 // we should own bonds 6,9,11
1945 ArrayHandle<unsigned int> h_rtag(bdata->getRTags(), access_location::host, access_mode::read);
1947 BOOST_CHECK(h_rtag.data[0] == GROUP_NOT_LOCAL);
1948 BOOST_CHECK(h_rtag.data[1] == GROUP_NOT_LOCAL);
1949 BOOST_CHECK(h_rtag.data[2] == GROUP_NOT_LOCAL);
1950 BOOST_CHECK(h_rtag.data[3] == GROUP_NOT_LOCAL);
1951 BOOST_CHECK(h_rtag.data[4] == GROUP_NOT_LOCAL);
1952 BOOST_CHECK(h_rtag.data[5] == GROUP_NOT_LOCAL);
1953 BOOST_CHECK(h_rtag.data[6] < bdata->getN());
1954 BOOST_CHECK(h_rtag.data[7] == GROUP_NOT_LOCAL);
1955 BOOST_CHECK(h_rtag.data[8] == GROUP_NOT_LOCAL);
1956 BOOST_CHECK(h_rtag.data[9] < bdata->getN());
1957 BOOST_CHECK(h_rtag.data[10] == GROUP_NOT_LOCAL);
1958 BOOST_CHECK(h_rtag.data[11] < bdata->getN());
1960 break;
1961 case 2:
1962 // box 2 should have three bonds
1963 BOOST_CHECK_EQUAL(pdata->getN(), 1);
1964 BOOST_CHECK_EQUAL(bdata->getN(), 3);
1967 // we should own bonds 1,5,6
1968 ArrayHandle<unsigned int> h_rtag(bdata->getRTags(), access_location::host, access_mode::read);
1970 BOOST_CHECK(h_rtag.data[0] == GROUP_NOT_LOCAL);
1971 BOOST_CHECK(h_rtag.data[1] < bdata->getN());
1972 BOOST_CHECK(h_rtag.data[2] == GROUP_NOT_LOCAL);
1973 BOOST_CHECK(h_rtag.data[3] == GROUP_NOT_LOCAL);
1974 BOOST_CHECK(h_rtag.data[4] == GROUP_NOT_LOCAL);
1975 BOOST_CHECK(h_rtag.data[5] < bdata->getN());
1976 BOOST_CHECK(h_rtag.data[6] < bdata->getN());
1977 BOOST_CHECK(h_rtag.data[7] == GROUP_NOT_LOCAL);
1978 BOOST_CHECK(h_rtag.data[8] == GROUP_NOT_LOCAL);
1979 BOOST_CHECK(h_rtag.data[9] == GROUP_NOT_LOCAL);
1980 BOOST_CHECK(h_rtag.data[10] == GROUP_NOT_LOCAL);
1981 BOOST_CHECK(h_rtag.data[11] == GROUP_NOT_LOCAL);
1983 break;
1984 case 3:
1985 // box 3 should have three bonds
1986 BOOST_CHECK_EQUAL(pdata->getN(), 1);
1987 BOOST_CHECK_EQUAL(bdata->getN(), 3);
1990 // we should own bonds 3,5,7
1991 ArrayHandle<unsigned int> h_rtag(bdata->getRTags(), access_location::host, access_mode::read);
1993 BOOST_CHECK(h_rtag.data[0] == GROUP_NOT_LOCAL);
1994 BOOST_CHECK(h_rtag.data[1] == GROUP_NOT_LOCAL);
1995 BOOST_CHECK(h_rtag.data[2] == GROUP_NOT_LOCAL);
1996 BOOST_CHECK(h_rtag.data[3] < bdata->getN());
1997 BOOST_CHECK(h_rtag.data[4] == GROUP_NOT_LOCAL);
1998 BOOST_CHECK(h_rtag.data[5] < bdata->getN());
1999 BOOST_CHECK(h_rtag.data[6] == GROUP_NOT_LOCAL);
2000 BOOST_CHECK(h_rtag.data[7] < bdata->getN());
2001 BOOST_CHECK(h_rtag.data[8] == GROUP_NOT_LOCAL);
2002 BOOST_CHECK(h_rtag.data[9] == GROUP_NOT_LOCAL);
2003 BOOST_CHECK(h_rtag.data[10] == GROUP_NOT_LOCAL);
2004 BOOST_CHECK(h_rtag.data[11] == GROUP_NOT_LOCAL);
2006 break;
2007 case 4:
2008 // box 4 should have three bonds
2009 BOOST_CHECK_EQUAL(pdata->getN(), 1);
2010 BOOST_CHECK_EQUAL(bdata->getN(), 3);
2013 // we should own bonds 2,8,9
2014 ArrayHandle<unsigned int> h_rtag(bdata->getRTags(), access_location::host, access_mode::read);
2016 BOOST_CHECK(h_rtag.data[0] == GROUP_NOT_LOCAL);
2017 BOOST_CHECK(h_rtag.data[1] == GROUP_NOT_LOCAL);
2018 BOOST_CHECK(h_rtag.data[2] < bdata->getN());
2019 BOOST_CHECK(h_rtag.data[3] == GROUP_NOT_LOCAL);
2020 BOOST_CHECK(h_rtag.data[4] == GROUP_NOT_LOCAL);
2021 BOOST_CHECK(h_rtag.data[5] == GROUP_NOT_LOCAL);
2022 BOOST_CHECK(h_rtag.data[6] == GROUP_NOT_LOCAL);
2023 BOOST_CHECK(h_rtag.data[7] == GROUP_NOT_LOCAL);
2024 BOOST_CHECK(h_rtag.data[8] < bdata->getN());
2025 BOOST_CHECK(h_rtag.data[9] < bdata->getN());
2026 BOOST_CHECK(h_rtag.data[10] == GROUP_NOT_LOCAL);
2027 BOOST_CHECK(h_rtag.data[11] == GROUP_NOT_LOCAL);
2029 break;
2030 case 5:
2031 // box 5 should have three bonds
2032 BOOST_CHECK_EQUAL(pdata->getN(), 1);
2033 BOOST_CHECK_EQUAL(bdata->getN(), 3);
2036 // we should own bonds 4,8,10
2037 ArrayHandle<unsigned int> h_rtag(bdata->getRTags(), access_location::host, access_mode::read);
2039 BOOST_CHECK(h_rtag.data[0] == GROUP_NOT_LOCAL);
2040 BOOST_CHECK(h_rtag.data[1] == GROUP_NOT_LOCAL);
2041 BOOST_CHECK(h_rtag.data[2] == GROUP_NOT_LOCAL);
2042 BOOST_CHECK(h_rtag.data[3] == GROUP_NOT_LOCAL);
2043 BOOST_CHECK(h_rtag.data[4] < bdata->getN());
2044 BOOST_CHECK(h_rtag.data[5] == GROUP_NOT_LOCAL);
2045 BOOST_CHECK(h_rtag.data[6] == GROUP_NOT_LOCAL);
2046 BOOST_CHECK(h_rtag.data[7] == GROUP_NOT_LOCAL);
2047 BOOST_CHECK(h_rtag.data[8] < bdata->getN());
2048 BOOST_CHECK(h_rtag.data[9] == GROUP_NOT_LOCAL);
2049 BOOST_CHECK(h_rtag.data[10] < bdata->getN());
2050 BOOST_CHECK(h_rtag.data[11] == GROUP_NOT_LOCAL);
2052 break;
2053 case 6:
2054 // box 6 should own three bonds
2055 BOOST_CHECK_EQUAL(pdata->getN(), 1);
2056 BOOST_CHECK_EQUAL(bdata->getN(), 3);
2059 // we should own bonds 0-2
2060 ArrayHandle<unsigned int> h_rtag(bdata->getRTags(), access_location::host, access_mode::read);
2062 BOOST_CHECK(h_rtag.data[0] < bdata->getN());
2063 BOOST_CHECK(h_rtag.data[1] < bdata->getN());
2064 BOOST_CHECK(h_rtag.data[2] < bdata->getN());
2065 BOOST_CHECK(h_rtag.data[3] == GROUP_NOT_LOCAL);
2066 BOOST_CHECK(h_rtag.data[4] == GROUP_NOT_LOCAL);
2067 BOOST_CHECK(h_rtag.data[5] == GROUP_NOT_LOCAL);
2068 BOOST_CHECK(h_rtag.data[6] == GROUP_NOT_LOCAL);
2069 BOOST_CHECK(h_rtag.data[7] == GROUP_NOT_LOCAL);
2070 BOOST_CHECK(h_rtag.data[8] == GROUP_NOT_LOCAL);
2071 BOOST_CHECK(h_rtag.data[9] == GROUP_NOT_LOCAL);
2072 BOOST_CHECK(h_rtag.data[10] == GROUP_NOT_LOCAL);
2073 BOOST_CHECK(h_rtag.data[11] == GROUP_NOT_LOCAL);
2076 break;
2078 case 7:
2079 // box 7 should have three bonds
2080 BOOST_CHECK_EQUAL(pdata->getN(), 1);
2081 BOOST_CHECK_EQUAL(bdata->getN(), 3);
2084 // we should own bonds 7,10,11
2085 ArrayHandle<unsigned int> h_rtag(bdata->getRTags(), access_location::host, access_mode::read);
2087 BOOST_CHECK(h_rtag.data[0] == GROUP_NOT_LOCAL);
2088 BOOST_CHECK(h_rtag.data[1] == GROUP_NOT_LOCAL);
2089 BOOST_CHECK(h_rtag.data[2] == GROUP_NOT_LOCAL);
2090 BOOST_CHECK(h_rtag.data[3] == GROUP_NOT_LOCAL);
2091 BOOST_CHECK(h_rtag.data[4] == GROUP_NOT_LOCAL);
2092 BOOST_CHECK(h_rtag.data[5] == GROUP_NOT_LOCAL);
2093 BOOST_CHECK(h_rtag.data[6] == GROUP_NOT_LOCAL);
2094 BOOST_CHECK(h_rtag.data[7] < bdata->getN());
2095 BOOST_CHECK(h_rtag.data[8] == GROUP_NOT_LOCAL);
2096 BOOST_CHECK(h_rtag.data[9] == GROUP_NOT_LOCAL);
2097 BOOST_CHECK(h_rtag.data[10] < bdata->getN());
2098 BOOST_CHECK(h_rtag.data[11] < bdata->getN());
2101 break;
2107 //! Test particle communication for covalently bonded ghosts
2108 void test_communicator_bonded_ghosts(communicator_creator comm_creator, boost::shared_ptr<ExecutionConfiguration> exec_conf)
2110 // this test needs to be run on eight processors
2111 int size;
2112 MPI_Comm_size(MPI_COMM_WORLD, &size);
2113 BOOST_REQUIRE_EQUAL(size,8);
2115 // create a system with eight particles
2116 boost::shared_ptr<SystemDefinition> sysdef(new SystemDefinition(8, // number of particles
2117 BoxDim(2.0), // box dimensions
2118 1, // number of particle types
2119 1, // number of bond types
2120 0, // number of angle types
2121 0, // number of dihedral types
2122 0, // number of dihedral types
2123 exec_conf));
2127 boost::shared_ptr<ParticleData> pdata(sysdef->getParticleData());
2129 // Set initial atom positions
2130 // place one particle slightly away from the middle of every box (in direction towards
2131 // the center of the global box - bonds cannot extend over more than half the box length)
2132 pdata->setPosition(0, make_scalar3(-0.4,-0.4,-0.4),false);
2133 pdata->setPosition(1, make_scalar3( 0.4,-0.4,-0.4),false);
2134 pdata->setPosition(2, make_scalar3(-0.4, 0.4,-0.4),false);
2135 pdata->setPosition(3, make_scalar3( 0.4, 0.4,-0.4),false);
2136 pdata->setPosition(4, make_scalar3(-0.4,-0.4, 0.4),false);
2137 pdata->setPosition(5, make_scalar3( 0.4,-0.4, 0.4),false);
2138 pdata->setPosition(6, make_scalar3(-0.4, 0.4, 0.4),false);
2139 pdata->setPosition(7, make_scalar3( 0.4, 0.4, 0.4),false);
2141 // now bond these particles together, forming a cube
2143 boost::shared_ptr<BondData> bdata(sysdef->getBondData());
2145 bdata->addBondedGroup(Bond(0,0,1)); // bond type, tag a, tag b
2146 bdata->addBondedGroup(Bond(0,0,2));
2147 bdata->addBondedGroup(Bond(0,0,4));
2148 bdata->addBondedGroup(Bond(0,1,3));
2149 bdata->addBondedGroup(Bond(0,1,5));
2150 bdata->addBondedGroup(Bond(0,2,3));
2151 bdata->addBondedGroup(Bond(0,2,6));
2152 bdata->addBondedGroup(Bond(0,3,7));
2153 bdata->addBondedGroup(Bond(0,4,5));
2154 bdata->addBondedGroup(Bond(0,4,6));
2155 bdata->addBondedGroup(Bond(0,5,7));
2156 bdata->addBondedGroup(Bond(0,6,7));
2158 SnapshotParticleData snap(8);
2159 pdata->takeSnapshot(snap);
2161 BondData::Snapshot snap_bdata(12);
2162 bdata->takeSnapshot(snap_bdata);
2164 // initialize a 2x2x2 domain decomposition on processor with rank 0
2165 boost::shared_ptr<DomainDecomposition> decomposition(new DomainDecomposition(exec_conf, pdata->getBox().getL()));
2166 boost::shared_ptr<Communicator> comm = comm_creator(sysdef, decomposition);
2168 // communicate tags, necessary for gpu bond table
2169 CommFlags flags(0);
2170 flags[comm_flag::tag] = 1;
2171 comm->setFlags(flags);
2173 // width of ghost layer
2174 Scalar ghost_layer_width = Scalar(0.1);
2175 comm->setGhostLayerWidth(ghost_layer_width);
2177 pdata->setDomainDecomposition(decomposition);
2179 // distribute particle data on processors
2180 pdata->initializeFromSnapshot(snap);
2182 bdata->initializeFromSnapshot(snap_bdata);
2184 // we should have zero ghost particles
2185 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 0);
2187 // migrate particles (to initialize bond rank table)
2188 comm->migrateParticles();
2190 // exchange ghost particles
2191 comm->exchangeGhosts();
2194 // all bonds should be complete, every processor should have three bonds
2195 ArrayHandle<BondData::members_t> h_gpu_bondlist(bdata->getGPUTable(), access_location::host, access_mode::read);
2196 ArrayHandle<unsigned int> h_n_bonds(bdata->getNGroupsArray(), access_location::host, access_mode::read);
2197 ArrayHandle<unsigned int> h_tag(pdata->getTags(), access_location::host, access_mode::read);
2199 BOOST_CHECK_EQUAL(h_n_bonds.data[0],3);
2200 unsigned int pitch = bdata->getGPUTableIndexer().getW();
2202 unsigned int sorted_tags[3];
2203 sorted_tags[0] = h_tag.data[h_gpu_bondlist.data[0].idx[0]];
2204 sorted_tags[1] = h_tag.data[h_gpu_bondlist.data[pitch].idx[0]];
2205 sorted_tags[2] = h_tag.data[h_gpu_bondlist.data[2*pitch].idx[0]];
2207 std::sort(sorted_tags, sorted_tags + 3);
2209 // check bond partners
2210 int rank;
2211 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
2213 switch (rank)
2215 case 0:
2216 BOOST_CHECK_EQUAL(sorted_tags[0], 1);
2217 BOOST_CHECK_EQUAL(sorted_tags[1], 2);
2218 BOOST_CHECK_EQUAL(sorted_tags[2], 4);
2219 break;
2220 case 1:
2221 BOOST_CHECK_EQUAL(sorted_tags[0], 0);
2222 BOOST_CHECK_EQUAL(sorted_tags[1], 3);
2223 BOOST_CHECK_EQUAL(sorted_tags[2], 5);
2224 break;
2225 case 2:
2226 BOOST_CHECK_EQUAL(sorted_tags[0], 0);
2227 BOOST_CHECK_EQUAL(sorted_tags[1], 3);
2228 BOOST_CHECK_EQUAL(sorted_tags[2], 6);
2229 break;
2230 case 3:
2231 BOOST_CHECK_EQUAL(sorted_tags[0], 1);
2232 BOOST_CHECK_EQUAL(sorted_tags[1], 2);
2233 BOOST_CHECK_EQUAL(sorted_tags[2], 7);
2234 break;
2235 case 4:
2236 BOOST_CHECK_EQUAL(sorted_tags[0], 0);
2237 BOOST_CHECK_EQUAL(sorted_tags[1], 5);
2238 BOOST_CHECK_EQUAL(sorted_tags[2], 6);
2239 break;
2240 case 5:
2241 BOOST_CHECK_EQUAL(sorted_tags[0], 1);
2242 BOOST_CHECK_EQUAL(sorted_tags[1], 4);
2243 BOOST_CHECK_EQUAL(sorted_tags[2], 7);
2244 break;
2245 case 6:
2246 BOOST_CHECK_EQUAL(sorted_tags[0], 2);
2247 BOOST_CHECK_EQUAL(sorted_tags[1], 4);
2248 BOOST_CHECK_EQUAL(sorted_tags[2], 7);
2249 break;
2250 case 7:
2251 BOOST_CHECK_EQUAL(sorted_tags[0], 3);
2252 BOOST_CHECK_EQUAL(sorted_tags[1], 5);
2253 BOOST_CHECK_EQUAL(sorted_tags[2], 6);
2254 break;
2259 bool migrate_request(unsigned int timestep)
2261 return true;
2264 CommFlags comm_flag_request(unsigned int timestep)
2266 CommFlags flags(0);
2267 flags[comm_flag::position] = 1;
2268 flags[comm_flag::tag] = 1;
2269 return flags;
2272 void test_communicator_compare(communicator_creator comm_creator_1,
2273 communicator_creator comm_creator_2,
2274 boost::shared_ptr<ExecutionConfiguration> exec_conf_1,
2275 boost::shared_ptr<ExecutionConfiguration> exec_conf_2)
2278 if (exec_conf_1->getRank() == 0)
2279 std::cout << "Begin random ghost comparison test" << std::endl;
2281 unsigned int n = 1000;
2282 // create a system with eight particles
2283 boost::shared_ptr<SystemDefinition> sysdef_1(new SystemDefinition(n, // number of particles
2284 BoxDim(2.0), // box dimensions
2285 1, // number of particle types
2286 1, // number of bond types
2287 0, // number of angle types
2288 0, // number of dihedral types
2289 0, // number of dihedral types
2290 exec_conf_1));
2291 boost::shared_ptr<SystemDefinition> sysdef_2(new SystemDefinition(n, // number of particles
2292 BoxDim(2.0), // box dimensions
2293 1, // number of particle types
2294 1, // number of bond types
2295 0, // number of angle types
2296 0, // number of dihedral types
2297 0, // number of dihedral types
2298 exec_conf_2));
2300 boost::shared_ptr<ParticleData> pdata_1 = sysdef_1->getParticleData();
2301 boost::shared_ptr<ParticleData> pdata_2 = sysdef_2->getParticleData();
2303 Scalar3 lo = pdata_1->getBox().getLo();
2304 Scalar3 L = pdata_1->getBox().getL();
2306 SnapshotParticleData snap(n);
2307 snap.type_mapping.push_back("A");
2309 srand(12345);
2310 for (unsigned int i = 0; i < n; ++i)
2312 snap.pos[i] = make_scalar3(lo.x + (Scalar)rand()/(Scalar)RAND_MAX*L.x,
2313 lo.y + (Scalar)rand()/(Scalar)RAND_MAX*L.y,
2314 lo.z + (Scalar)rand()/(Scalar)RAND_MAX*L.z);
2317 // initialize dommain decomposition on processor with rank 0
2318 boost::shared_ptr<DomainDecomposition> decomposition_1(new DomainDecomposition(exec_conf_1, pdata_1->getBox().getL()));
2319 boost::shared_ptr<DomainDecomposition> decomposition_2(new DomainDecomposition(exec_conf_2, pdata_2->getBox().getL()));
2321 boost::shared_ptr<Communicator> comm_1 = comm_creator_1(sysdef_1, decomposition_1);
2322 boost::shared_ptr<Communicator> comm_2 = comm_creator_2(sysdef_2, decomposition_2);
2324 // width of ghost layer
2325 Scalar ghost_layer_width = Scalar(0.2);
2326 comm_1->setGhostLayerWidth(ghost_layer_width);
2327 comm_2->setGhostLayerWidth(ghost_layer_width);
2329 pdata_1->setDomainDecomposition(decomposition_1);
2330 pdata_2->setDomainDecomposition(decomposition_2);
2332 // distribute particle data on processors
2333 pdata_1->initializeFromSnapshot(snap);
2334 pdata_2->initializeFromSnapshot(snap);
2336 // Create ConstForceComputes
2337 // boost::shared_ptr<ConstForceCompute> fc_1(new ConstForceCompute(sysdef_1, Scalar(-0.3), Scalar(0.2), Scalar(-0.123)));
2338 // boost::shared_ptr<ConstForceCompute> fc_2(new ConstForceCompute(sysdef_2, Scalar(-0.3), Scalar(0.2), Scalar(-0.123)));
2340 boost::shared_ptr<ParticleSelector> selector_all_1(new ParticleSelectorTag(sysdef_1, 0, pdata_1->getNGlobal()-1));
2341 boost::shared_ptr<ParticleGroup> group_all_1(new ParticleGroup(sysdef_1, selector_all_1));
2343 boost::shared_ptr<ParticleSelector> selector_all_2(new ParticleSelectorTag(sysdef_2, 0, pdata_2->getNGlobal()-1));
2344 boost::shared_ptr<ParticleGroup> group_all_2(new ParticleGroup(sysdef_2, selector_all_2));
2346 boost::shared_ptr<TwoStepNVE> two_step_nve_1(new TwoStepNVE(sysdef_1, group_all_1));
2347 boost::shared_ptr<TwoStepNVE> two_step_nve_2(new TwoStepNVE(sysdef_2, group_all_2));
2349 Scalar deltaT=0.001;
2350 boost::shared_ptr<IntegratorTwoStep> nve_up_1(new IntegratorTwoStep(sysdef_1, deltaT));
2351 boost::shared_ptr<IntegratorTwoStep> nve_up_2(new IntegratorTwoStep(sysdef_2, deltaT));
2352 nve_up_1->addIntegrationMethod(two_step_nve_1);
2353 nve_up_2->addIntegrationMethod(two_step_nve_2);
2355 // nve_up_1->addForceCompute(fc_1);
2356 // nve_up_2->addForceCompute(fc_2);
2358 // set constant velocities
2359 for (unsigned int tag= 0; tag < n; ++tag)
2361 pdata_1->setVelocity(tag, make_scalar3(0.01,0.02,0.03));
2362 pdata_2->setVelocity(tag, make_scalar3(0.01,0.02,0.03));
2365 comm_1->addMigrateRequest(bind(&migrate_request,_1));
2366 comm_2->addMigrateRequest(bind(&migrate_request,_1));
2368 comm_1->addCommFlagsRequest(bind(&comm_flag_request, _1));
2369 comm_2->addCommFlagsRequest(bind(&comm_flag_request, _1));
2371 nve_up_1->setCommunicator(comm_1);
2372 nve_up_2->setCommunicator(comm_2);
2374 nve_up_1->prepRun(0);
2375 nve_up_2->prepRun(0);
2376 exec_conf_1->msg->notice(1) << "Running 1000 steps..." << std::endl;
2377 bool err = false;
2378 for (unsigned int step = 0; step < 1000; ++step)
2380 if (! (step % 100)) exec_conf_1->msg->notice(1) << "Step " << step << std::endl;
2382 // both communicators should replicate the same number of ghosts
2383 BOOST_CHECK_EQUAL(pdata_1->getNGhosts(), pdata_2->getNGhosts());
2386 ArrayHandle<unsigned int> h_rtag_1(pdata_1->getRTags(), access_location::host, access_mode::read);
2387 ArrayHandle<Scalar4> h_pos_1(pdata_1->getPositions(), access_location::host, access_mode::read);
2388 ArrayHandle<unsigned int> h_rtag_2(pdata_2->getRTags(), access_location::host, access_mode::read);
2389 ArrayHandle<Scalar4> h_pos_2(pdata_2->getPositions(), access_location::host, access_mode::read);
2390 for (unsigned int i = 0; i < n; ++i)
2392 bool has_ghost_1 = false, has_ghost_2 = false;
2394 if (h_rtag_1.data[i] >= pdata_1->getN() && (h_rtag_1.data[i] < (pdata_1->getN() + pdata_1->getNGhosts())))
2395 has_ghost_1 = true;
2397 if (h_rtag_2.data[i] >= pdata_2->getN() && (h_rtag_2.data[i] < (pdata_2->getN() + pdata_2->getNGhosts())))
2398 has_ghost_2 = true;
2400 // particle is either in both systems' ghost layers or in none
2401 BOOST_REQUIRE((has_ghost_1 && has_ghost_2) || (!has_ghost_1 && !has_ghost_2));
2403 if (has_ghost_1 && has_ghost_2)
2405 Scalar tol_rough = .1;
2406 BOOST_CHECK_CLOSE(h_pos_1.data[h_rtag_1.data[i]].x, h_pos_2.data[h_rtag_2.data[i]].x,tol_rough);
2407 BOOST_CHECK_CLOSE(h_pos_1.data[h_rtag_1.data[i]].y, h_pos_2.data[h_rtag_2.data[i]].y,tol_rough);
2408 BOOST_CHECK_CLOSE(h_pos_1.data[h_rtag_1.data[i]].z, h_pos_2.data[h_rtag_2.data[i]].z,tol_rough);
2412 // error out on first time step where test fails
2413 BOOST_REQUIRE(!err);
2415 nve_up_1->update(step);
2416 nve_up_2->update(step);
2419 if (exec_conf_1->getRank() == 0)
2420 std::cout << "Finish random ghosts test" << std::endl;
2423 //! Test ghost particle communication
2424 void test_communicator_ghost_fields(communicator_creator comm_creator, boost::shared_ptr<ExecutionConfiguration> exec_conf)
2426 // this test needs to be run on eight processors
2427 int size;
2428 MPI_Comm_size(MPI_COMM_WORLD, &size);
2429 BOOST_REQUIRE_EQUAL(size,8);
2431 // create a system with eight + 1 one ptls (1 ptl in ghost layer)
2432 boost::shared_ptr<SystemDefinition> sysdef(new SystemDefinition(9, // number of particles
2433 BoxDim(2.0), // box dimensions
2434 1, // number of particle types
2435 0, // number of bond types
2436 0, // number of angle types
2437 0, // number of dihedral types
2438 0, // number of dihedral types
2439 exec_conf));
2442 boost::shared_ptr<ParticleData> pdata(sysdef->getParticleData());
2444 // Set initial atom positions
2445 // place one particle in the middle of every box (outside the ghost layer)
2446 pdata->setPosition(0, make_scalar3(-0.5,-0.5,-0.5),false);
2447 pdata->setPosition(1, make_scalar3( 0.5,-0.5,-0.5),false);
2448 pdata->setPosition(2, make_scalar3(-0.5, 0.5,-0.5),false);
2449 pdata->setPosition(3, make_scalar3( 0.5, 0.5,-0.5),false);
2450 pdata->setPosition(4, make_scalar3(-0.5,-0.5, 0.5),false);
2451 pdata->setPosition(5, make_scalar3( 0.5,-0.5, 0.5),false);
2452 pdata->setPosition(6, make_scalar3(-0.5, 0.5, 0.5),false);
2453 pdata->setPosition(7, make_scalar3( 0.5, 0.5, 0.5),false);
2455 // particle 8 in the ghost layer of its +x neighbor
2456 pdata->setPosition(8, make_scalar3( -0.05, -0.5, -0.5),false);
2458 // set other properties of ptl 8
2459 pdata->setVelocity(8, make_scalar3(1.0,2.0,3.0));
2460 pdata->setMass(8, 4.0);
2461 pdata->setCharge(8, 5.0);
2462 pdata->setDiameter(8, 6.0);
2463 pdata->setOrientation(8,make_scalar4(97.0,98.0,99.0,100.0));
2465 // distribute particle data on processors
2466 SnapshotParticleData snap(9);
2467 pdata->takeSnapshot(snap);
2469 // initialize a 2x2x2 domain decomposition on processor with rank 0
2470 boost::shared_ptr<DomainDecomposition> decomposition(new DomainDecomposition(exec_conf, pdata->getBox().getL()));
2471 boost::shared_ptr<Communicator> comm = comm_creator(sysdef, decomposition);
2473 pdata->setDomainDecomposition(decomposition);
2475 pdata->initializeFromSnapshot(snap);
2477 // width of ghost layer
2478 Scalar ghost_layer_width = Scalar(0.1);
2479 comm->setGhostLayerWidth(ghost_layer_width);
2481 // Check number of particles
2482 switch (exec_conf->getRank())
2484 case 0:
2485 BOOST_CHECK_EQUAL(pdata->getN(), 2);
2486 break;
2487 case 1:
2488 BOOST_CHECK_EQUAL(pdata->getN(), 1);
2489 break;
2490 case 2:
2491 BOOST_CHECK_EQUAL(pdata->getN(), 1);
2492 break;
2493 case 3:
2494 BOOST_CHECK_EQUAL(pdata->getN(), 1);
2495 break;
2496 case 4:
2497 BOOST_CHECK_EQUAL(pdata->getN(), 1);
2498 break;
2499 case 5:
2500 BOOST_CHECK_EQUAL(pdata->getN(), 1);
2501 break;
2502 case 6:
2503 BOOST_CHECK_EQUAL(pdata->getN(), 1);
2504 break;
2505 case 7:
2506 BOOST_CHECK_EQUAL(pdata->getN(), 1);
2507 break;
2510 // we should have zero ghosts before the exchange
2511 BOOST_CHECK_EQUAL(pdata->getNGhosts(),0);
2513 // set ghost exchange flags for position
2514 CommFlags flags(0);
2515 flags[comm_flag::position] = 1;
2516 flags[comm_flag::velocity] = 1;
2517 flags[comm_flag::orientation] = 1;
2518 flags[comm_flag::charge] = 1;
2519 flags[comm_flag::diameter] = 1;
2520 flags[comm_flag::tag] = 1;
2521 comm->setFlags(flags);
2523 // reset numbers of ghosts
2524 comm->migrateParticles();
2526 // exchange ghosts
2527 comm->exchangeGhosts();
2530 // check ghost atom numbers, positions, velocities, etc.
2531 ArrayHandle<Scalar4> h_pos(pdata->getPositions(), access_location::host, access_mode::read);
2532 ArrayHandle<Scalar4> h_vel(pdata->getVelocities(), access_location::host, access_mode::read);
2533 ArrayHandle<Scalar> h_charge(pdata->getCharges(), access_location::host, access_mode::read);
2534 ArrayHandle<Scalar> h_diameter(pdata->getDiameters(), access_location::host, access_mode::read);
2535 ArrayHandle<Scalar4> h_orientation(pdata->getOrientationArray(), access_location::host, access_mode::read);
2536 ArrayHandle<unsigned int> h_global_rtag(pdata->getRTags(), access_location::host, access_mode::read);
2538 unsigned int rtag;
2539 switch (exec_conf->getRank())
2541 case 0:
2542 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 0);
2543 break;
2545 case 1:
2546 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 1);
2548 rtag = h_global_rtag.data[8];
2549 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
2550 BOOST_CHECK_CLOSE(h_pos.data[rtag].x, -0.05,tol);
2551 BOOST_CHECK_CLOSE(h_pos.data[rtag].y, -0.5,tol);
2552 BOOST_CHECK_CLOSE(h_pos.data[rtag].z, -0.5,tol);
2554 BOOST_CHECK_CLOSE(h_vel.data[rtag].x, 1.0,tol);
2555 BOOST_CHECK_CLOSE(h_vel.data[rtag].y, 2.0,tol);
2556 BOOST_CHECK_CLOSE(h_vel.data[rtag].z, 3.0,tol);
2557 BOOST_CHECK_CLOSE(h_vel.data[rtag].w, 4.0,tol); // mass
2559 BOOST_CHECK_CLOSE(h_charge.data[rtag], 5.0,tol);
2560 BOOST_CHECK_CLOSE(h_diameter.data[rtag], 6.0,tol);
2562 BOOST_CHECK_CLOSE(h_orientation.data[rtag].x, 97.0,tol);
2563 BOOST_CHECK_CLOSE(h_orientation.data[rtag].y, 98.0,tol);
2564 BOOST_CHECK_CLOSE(h_orientation.data[rtag].z, 99.0,tol);
2565 break;
2567 case 2:
2568 case 3:
2569 case 4:
2570 case 5:
2571 case 6:
2572 case 7:
2573 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 0);
2574 break;
2578 // set some new fields for the ghost particles
2579 pdata->setPosition(8, make_scalar3(-0.13,-0.5,-0.5),false);
2580 pdata->setVelocity(8, make_scalar3(-3.0,-2.0,-1.0));
2581 pdata->setMass(8, 0.1);
2582 pdata->setOrientation(8,make_scalar4(22.0,23.0,24.0,25.0));
2585 // update ghosts
2586 comm->beginUpdateGhosts(0);
2587 comm->finishUpdateGhosts(0);
2590 // check ghost atom numbers, positions, velocities, etc.
2591 ArrayHandle<Scalar4> h_pos(pdata->getPositions(), access_location::host, access_mode::read);
2592 ArrayHandle<Scalar4> h_vel(pdata->getVelocities(), access_location::host, access_mode::read);
2593 ArrayHandle<Scalar> h_charge(pdata->getCharges(), access_location::host, access_mode::read);
2594 ArrayHandle<Scalar> h_diameter(pdata->getDiameters(), access_location::host, access_mode::read);
2595 ArrayHandle<Scalar4> h_orientation(pdata->getOrientationArray(), access_location::host, access_mode::read);
2596 ArrayHandle<unsigned int> h_global_rtag(pdata->getRTags(), access_location::host, access_mode::read);
2598 unsigned int rtag;
2599 switch (exec_conf->getRank())
2601 case 1:
2602 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 1);
2604 rtag = h_global_rtag.data[8];
2605 BOOST_CHECK(rtag >= pdata->getN() && rtag < pdata->getN()+pdata->getNGhosts());
2606 BOOST_CHECK_CLOSE(h_pos.data[rtag].x, -0.13,tol);
2607 BOOST_CHECK_CLOSE(h_pos.data[rtag].y, -0.5,tol);
2608 BOOST_CHECK_CLOSE(h_pos.data[rtag].z, -0.5,tol);
2610 BOOST_CHECK_CLOSE(h_vel.data[rtag].x, -3.0,tol);
2611 BOOST_CHECK_CLOSE(h_vel.data[rtag].y, -2.0,tol);
2612 BOOST_CHECK_CLOSE(h_vel.data[rtag].z, -1.0,tol);
2613 BOOST_CHECK_CLOSE(h_vel.data[rtag].w, 0.1,tol); // mass
2615 // charge and diameter should be unchanged
2616 BOOST_CHECK_CLOSE(h_charge.data[rtag], 5.0,tol);
2617 BOOST_CHECK_CLOSE(h_diameter.data[rtag], 6.0,tol);
2619 BOOST_CHECK_CLOSE(h_orientation.data[rtag].x, 22.0,tol);
2620 BOOST_CHECK_CLOSE(h_orientation.data[rtag].y, 23.0,tol);
2621 BOOST_CHECK_CLOSE(h_orientation.data[rtag].z, 24.0,tol);
2622 break;
2624 case 0:
2625 case 2:
2626 case 3:
2627 case 4:
2628 case 5:
2629 case 6:
2630 case 7:
2631 BOOST_CHECK_EQUAL(pdata->getNGhosts(), 0);
2632 break;
2637 //! Communicator creator for unit tests
2638 boost::shared_ptr<Communicator> base_class_communicator_creator(boost::shared_ptr<SystemDefinition> sysdef,
2639 boost::shared_ptr<DomainDecomposition> decomposition)
2641 return boost::shared_ptr<Communicator>(new Communicator(sysdef, decomposition) );
2644 #ifdef ENABLE_CUDA
2645 boost::shared_ptr<Communicator> gpu_communicator_creator(boost::shared_ptr<SystemDefinition> sysdef,
2646 boost::shared_ptr<DomainDecomposition> decomposition)
2648 return boost::shared_ptr<Communicator>(new CommunicatorGPU(sysdef, decomposition) );
2650 #endif
2652 //! Tests particle distribution
2653 BOOST_AUTO_TEST_CASE( DomainDecomposition_test )
2655 test_domain_decomposition(boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::CPU)));
2658 BOOST_AUTO_TEST_CASE( communicator_migrate_test )
2660 communicator_creator communicator_creator_base = bind(base_class_communicator_creator, _1, _2);
2661 // cubic box
2662 test_communicator_migrate(communicator_creator_base, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::CPU)),BoxDim(2.0));
2663 // orthorhombic box
2664 test_communicator_migrate(communicator_creator_base, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::CPU)),BoxDim(1.0,2.0,3.0));
2665 // triclinic box 1
2666 test_communicator_migrate(communicator_creator_base, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::CPU)),BoxDim(1.0,0.5,0.6,0.8));
2667 // triclinic box 1
2668 test_communicator_migrate(communicator_creator_base, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::CPU)),BoxDim(1.0,-0.5,0.7,0.3));
2671 BOOST_AUTO_TEST_CASE( communicator_ghosts_test )
2673 communicator_creator communicator_creator_base = bind(base_class_communicator_creator, _1, _2);
2675 // test in a cubic box
2676 test_communicator_ghosts(communicator_creator_base, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::CPU)),BoxDim(2.0));
2677 // triclinic box 1
2678 test_communicator_ghosts(communicator_creator_base, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::CPU)),BoxDim(1.0,.1,.2,.3));
2679 // triclinic box 2
2680 test_communicator_ghosts(communicator_creator_base, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::CPU)),BoxDim(1.0,-.6,.7,.5));
2683 BOOST_AUTO_TEST_CASE( communicator_bonded_ghosts_test )
2685 communicator_creator communicator_creator_base = bind(base_class_communicator_creator, _1, _2);
2686 test_communicator_bonded_ghosts(communicator_creator_base, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::CPU)));
2689 BOOST_AUTO_TEST_CASE( communicator_bond_exchange_test )
2691 communicator_creator communicator_creator_base = bind(base_class_communicator_creator, _1, _2);
2692 test_communicator_bond_exchange(communicator_creator_base, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::CPU)));
2695 BOOST_AUTO_TEST_CASE( communicator_ghost_fields_test )
2697 communicator_creator communicator_creator_base = bind(base_class_communicator_creator, _1, _2);
2698 test_communicator_ghost_fields(communicator_creator_base, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::CPU)));
2701 #ifdef ENABLE_CUDA
2703 //! Tests particle distribution on GPU
2704 BOOST_AUTO_TEST_CASE( DomainDecomposition_test_GPU )
2706 test_domain_decomposition(boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::GPU)));
2709 BOOST_AUTO_TEST_CASE( communicator_migrate_test_GPU )
2711 communicator_creator communicator_creator_gpu = bind(gpu_communicator_creator, _1, _2);
2712 // cubic box
2713 test_communicator_migrate(communicator_creator_gpu, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::GPU)),BoxDim(2.0));
2714 // orthorhombic box
2715 test_communicator_migrate(communicator_creator_gpu, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::GPU)),BoxDim(1.0,2.0,3.0));
2716 // triclinic box 1
2717 test_communicator_migrate(communicator_creator_gpu, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::GPU)),BoxDim(1.0,0.5,0.6,0.8));
2718 // triclinic box 2
2719 test_communicator_migrate(communicator_creator_gpu, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::GPU)),BoxDim(1.0,-0.5,0.7,0.3));
2722 BOOST_AUTO_TEST_CASE( communicator_ghosts_test_GPU )
2724 communicator_creator communicator_creator_gpu = bind(gpu_communicator_creator, _1, _2);
2725 // test in a cubic box
2726 test_communicator_ghosts(communicator_creator_gpu, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::GPU)),BoxDim(2.0));
2727 // triclinic box 1
2728 test_communicator_ghosts(communicator_creator_gpu, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::GPU)),BoxDim(1.0,.1,.2,.3));
2729 // triclinic box 2
2730 test_communicator_ghosts(communicator_creator_gpu, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::GPU)),BoxDim(1.0,-.6,.7,.5));
2733 BOOST_AUTO_TEST_CASE( communicator_bonded_ghosts_test_GPU )
2735 communicator_creator communicator_creator_gpu = bind(gpu_communicator_creator, _1, _2);
2736 test_communicator_bonded_ghosts(communicator_creator_gpu, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::GPU)));
2738 BOOST_AUTO_TEST_CASE( communicator_bond_exchange_test_GPU )
2740 communicator_creator communicator_creator_gpu = bind(gpu_communicator_creator, _1, _2);
2741 test_communicator_bond_exchange(communicator_creator_gpu, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::GPU)));
2744 BOOST_AUTO_TEST_CASE( communicator_ghost_fields_test_GPU )
2746 communicator_creator communicator_creator_gpu = bind(gpu_communicator_creator, _1, _2);
2747 test_communicator_ghost_fields(communicator_creator_gpu, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::GPU)));
2750 BOOST_AUTO_TEST_CASE (communicator_compare_test )
2752 communicator_creator communicator_creator_gpu = bind(gpu_communicator_creator, _1, _2);
2753 communicator_creator communicator_creator_cpu = bind(base_class_communicator_creator, _1, _2);
2754 test_communicator_compare(communicator_creator_cpu, communicator_creator_gpu, boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::CPU)),boost::shared_ptr<ExecutionConfiguration>(new ExecutionConfiguration(ExecutionConfiguration::GPU)));
2756 #endif
2758 #endif //ENABLE_MPI