Peano
Loading...
Searching...
No Matches
test_periodic_BC-3D.py
Go to the documentation of this file.
1import os
2import argparse
3import numpy as np
4
5import peano4.api
6import exaparty
7import dastgen2
8
9import shutil
10
11
14
15parser = argparse.ArgumentParser(description="Test periodic boundary conditions")
16parser.add_argument(
17 "-j", "--parallel-builds", dest="j", type=int, default=-1, help="Parallel builds"
18)
19parser.add_argument(
20 "-v",
21 "--verbose",
22 dest="verbose",
23 action="store_true",
24 default=False,
25 help="Verbose",
26)
27parser.add_argument(
28 "-c",
29 "--clean",
30 dest="clean_temporary_directories",
31 action="store_true",
32 help="Remove temporary directories before script starts",
33)
34parser.add_argument(
35 "-et",
36 "--end-time",
37 dest="end_time",
38 type=float,
39 default=1.0,
40 help="End of simulation",
41)
42parser.add_argument(
43 "-dt",
44 "--timestep-size",
45 dest="timestep_size",
46 type=float,
47 default=1e-3,
48 help="Global timestep size",
49)
50parser.add_argument(
51 "-plot",
52 "--plot-delta",
53 dest="plot_delta",
54 type=float,
55 default=0.01,
56 help="Plot delta (0 switches off)",
57)
58parser.add_argument(
59 "-cs",
60 "--cell-size",
61 dest="cell_size",
62 type=float,
63 default=0.1,
64 help="Cell size (default 0.1)",
65)
66parser.add_argument(
67 "-pd",
68 "--peano-dir",
69 dest="peanodir",
70 default="../../../../",
71 help="Peano4 directory",
72)
73parser.add_argument(
74 "-asserts",
75 "--asserts",
76 dest="asserts",
77 action="store_true",
78 default=False,
79 help="Switch on assertions",
80)
81parser.add_argument(
82 "-d",
83 "--debug",
84 dest="debug",
85 action="store_true",
86 default=False,
87 help="Switch on debug assertions",
88)
89args = parser.parse_args()
90
91
92
95
96dimensions = 3
97hydro_dimensions = 3
98
99
101 namespace=["tests", "exaparty", "periodicBoundaryConditions3D"],
102 project_name="periodicBoundaryConditions3D",
103 executable="periodicBCTest3D",
104)
105
106
108 name="GenericParticle",
109 cfl_factor=0.9,
110 initial_time_step_size=args.timestep_size,
111 particles_per_cell=0,
112 min_h=args.cell_size,
113 max_h=0.3,
114 add_partid=(not args.asserts),
115)
116particle_set = project.add_particle_species(particle)
117
118
119if args.debug:
120 build_mode = peano4.api.output.CompileMode.DEBUG
121elif args.asserts:
122 build_mode = peano4.api.output.CompileMode.ASSERTS
123else:
124 build_mode = peano4.api.output.CompileMode.RELEASE
125
126offset = [0, 0, 0]
127domain_size = [1, 1, 1]
128periodic_boundary_conditions = [True, True, True] # Periodic BC
129
130project.set_global_simulation_parameters(
131 dimensions=dimensions,
132 offset=offset,
133 domain_size=domain_size,
134 min_end_time=args.end_time,
135 max_end_time=0.0,
136 first_plot_time_stamp=0.0,
137 time_in_between_plots=args.plot_delta,
138 periodic_BC=periodic_boundary_conditions,
139 plotter_precision=8, # plotter precision
140)
141
142project.set_load_balancing(
143 "toolbox::loadbalancing::strategies::SpreadOutHierarchically",
144 "new toolbox::loadbalancing::DefaultConfiguration()",
145)
146
147project.set_Peano4_installation(args.peanodir, build_mode)
148
149
150
155
156particle_force = ""
157
158# particle.cell_kernel = particle_force
159
160
161
171search_radius = args.cell_size / 100.0
172initialisation_snippet = (
173 """
174 /* Internal search radius used by Peano.
175 * Not really used here. */
176 particle->setSearchRadius("""
177 + str(search_radius)
178 + """);
179 particle->setA( {0., 0., 0.} );
180
181 const double boxsize_x = """
182 + str(domain_size[0])
183 + """;
184 const double boxsize_y = """
185 + str(domain_size[1])
186 + """;
187 const double boxsize_z = """
188 + str(domain_size[2])
189 + """;
190 const double offset_x = """
191 + str(offset[0])
192 + """;
193 const double offset_y = """
194 + str(offset[1])
195 + """;
196 const double offset_z = """
197 + str(offset[2])
198 + """;
199 const double sq3 = std::sqrt(3);
200 const double sq2 = std::sqrt(2);
201
202
203 if( particle->getX(0) < offset_x + 1./ 3. * boxsize_x ) {
204
205 if (particle->getX(1) < offset_y + 1./3. * boxsize_y) {
206 // Low left square
207
208 if (particle->getX(2) < offset_z + 1./3. * boxsize_z) {
209
210 // Low left square, z ~ 0
211
212 particle->setV(0, -sq3);
213 particle->setV(1, -sq3);
214 particle->setV(2, -sq3);
215
216 } else if (particle->getX(2) < offset_z + 2./3. * boxsize_z) {
217
218 // Low left square, z ~ 0.5
219
220 particle->setV(0, -sq2);
221 particle->setV(1, -sq2);
222 particle->setV(2, 0.);
223
224 } else {
225
226 // Low left square, z ~ 1.
227
228 particle->setV(0, -sq3);
229 particle->setV(1, -sq3);
230 particle->setV(2, sq3);
231
232 }
233
234 } else if (particle->getX(1) < offset_y + 2./3. * boxsize_y) {
235 // Mid left square
236
237 if (particle->getX(2) < offset_z + 1./3. * boxsize_z) {
238
239 // Mid left square, z ~ 0
240
241 particle->setV(0, -sq2);
242 particle->setV(1, 0.);
243 particle->setV(2, -sq2);
244
245 } else if (particle->getX(2) < offset_z + 2./3. * boxsize_z) {
246
247 // Mid left square, z ~ 0.5
248
249 particle->setV(0, 0.);
250 particle->setV(1, -1.);
251 particle->setV(2, 0.);
252
253 } else {
254
255 // Mid left square, z ~ 1.
256
257 particle->setV(0, -sq2);
258 particle->setV(1, 0.);
259 particle->setV(2, sq2);
260
261 }
262
263 } else {
264 // Top left square
265
266 if (particle->getX(2) < offset_z + 1./3. * boxsize_z) {
267
268 // Top left square, z ~ 0
269
270 particle->setV(0, -sq3);
271 particle->setV(1, sq3);
272 particle->setV(2, -sq3);
273
274 } else if (particle->getX(2) < offset_z + 2./3. * boxsize_z) {
275
276 // Top left square, z ~ 0.5
277
278 particle->setV(0, -sq2);
279 particle->setV(1, 0.);
280 particle->setV(2, -sq2);
281
282 } else {
283
284 // Top left square, z ~ 1.
285
286 particle->setV(0, -sq3);
287 particle->setV(1, sq3);
288 particle->setV(2, sq3);
289
290 }
291 }
292 } else if( particle->getX(0) < offset_x + 2./ 3. * boxsize_x ) {
293
294 if (particle->getX(1) < offset_y + 1./3. * boxsize_y) {
295 // Low Center square, z ~ 0
296
297 if (particle->getX(2) < offset_z + 1./3. * boxsize_z) {
298
299 // Low Center square, z ~ 0
300
301 particle->setV(0, 0.);
302 particle->setV(1, -sq2);
303 particle->setV(2, -sq2);
304
305 } else if (particle->getX(2) < offset_z + 2./3. * boxsize_z) {
306
307 // Low Center square, z ~ 0.5
308
309 particle->setV(0, 0.);
310 particle->setV(1, -1.);
311 particle->setV(2, 0.);
312
313 } else {
314
315 // Low Center square, z ~ 1.
316
317 particle->setV(0, 0.);
318 particle->setV(1, -sq2);
319 particle->setV(2, sq2);
320
321 }
322
323 } else if (particle->getX(1) < offset_y + 2./3. * boxsize_y) {
324 // Mid Center square
325
326 if (particle->getX(2) < offset_z + 1./3. * boxsize_z) {
327
328 // Mid Center square, z ~ 0
329
330 particle->setV(0, 0.);
331 particle->setV(1, 0.);
332 particle->setV(2, -1.);
333
334 } else if (particle->getX(2) < offset_z + 2./3. * boxsize_z) {
335
336 // Mid Center square, z ~ 0.5
337
338 particle->setV(0, 0.);
339 particle->setV(1, 0.);
340 particle->setV(2, 0.);
341
342 } else {
343
344 // Mid Center square, z ~ 1.
345
346 particle->setV(0, 0.);
347 particle->setV(1, 0.);
348 particle->setV(2, 1.);
349
350 }
351
352 } else {
353 // Top Center square
354
355 if (particle->getX(2) < offset_z + 1./3. * boxsize_z) {
356
357 // Top Center square, z ~ 0
358
359 particle->setV(0, 0);
360 particle->setV(1, sq2);
361 particle->setV(2, -sq2);
362
363 } else if (particle->getX(2) < offset_z + 2./3. * boxsize_z) {
364
365 // Top Center square, z ~ 0.5
366
367 particle->setV(0, 0.);
368 particle->setV(1, 1.);
369 particle->setV(2, 0. );
370
371 } else {
372
373 // Top Center square, z ~ 1.
374
375 particle->setV(0, 0.);
376 particle->setV(1, sq2);
377 particle->setV(2, sq2);
378
379 }
380 }
381
382 } else {
383
384 if (particle->getX(1) < offset_y + 1./3. * boxsize_y) {
385 // Low Right square
386
387 if (particle->getX(2) < offset_z + 1./3. * boxsize_z) {
388
389 // Low Right square, z ~ 0
390
391 particle->setV(0, sq3);
392 particle->setV(1, sq3);
393 particle->setV(2, -sq3);
394
395 } else if (particle->getX(2) < offset_z + 2./3. * boxsize_z) {
396
397 // Low Right square, z ~ 0.5
398
399 particle->setV(0, sq2);
400 particle->setV(1, -sq2);
401 particle->setV(2, 0.);
402
403 } else {
404
405 // Low Right square, z ~ 1.
406
407 particle->setV(0, sq3);
408 particle->setV(1, -sq3);
409 particle->setV(2, sq3);
410
411 }
412
413 } else if (particle->getX(1) < offset_y + 2./3. * boxsize_y) {
414 // Mid Right square
415
416 if (particle->getX(2) < offset_z + 1./3. * boxsize_z) {
417
418 // Mid Right square, z ~ 0
419
420 particle->setV(0, sq2);
421 particle->setV(1, 0.);
422 particle->setV(2, -sq2);
423
424 } else if (particle->getX(2) < offset_z + 2./3. * boxsize_z) {
425
426 // Mid Right square, z ~ 0.5
427
428 particle->setV(0, 0.);
429 particle->setV(1, 1.);
430 particle->setV(2, 0.);
431
432 } else {
433
434 // Mid Right square, z ~ 1.
435
436 particle->setV(0, sq2);
437 particle->setV(1, 0.);
438 particle->setV(2, sq2);
439
440 }
441
442 } else {
443 // Top Right square
444
445 if (particle->getX(2) < offset_z + 1./3. * boxsize_z) {
446
447 // Top Right square, z ~ 0
448
449 particle->setV(0, sq3);
450 particle->setV(1, sq3);
451 particle->setV(2, -sq3);
452
453 } else if (particle->getX(2) < offset_z + 2./3. * boxsize_z) {
454
455 // Top Right square, z ~ 0.5
456
457 particle->setV(0, sq2);
458 particle->setV(1, sq2);
459 particle->setV(2, 0.);
460
461 } else {
462
463 // Top Right square, z ~ 1.
464
465 particle->setV(0, sq3);
466 particle->setV(1, sq3);
467 particle->setV(2, sq3);
468
469 }
470 }
471 }
472
473 // hack to get a somewhat flexible, but always unique
474 // and reproducible particle ID: Assume we have a 1600^3
475 // uniform grid particle distribution. (1600^3 is close)
476 // to the numeric limits of integers.
477
478 double dx = boxsize_x / 1600.;
479 double dy = boxsize_y / 1600.;
480
481 int i = (int) ((particle->getX(0) - offset_x) / dx + 0.5);
482 int j = (int) ((particle->getX(1) - offset_y) / dy + 0.5);
483 particle->setPartid(i + 1600*j);
484
485"""
486)
487
488
489def rotation_matrix(axis, theta):
490 """
491 Return the rotation matrix associated with counterclockwise rotation about
492 the given axis by theta radians.
493
494 https://stackoverflow.com/questions/6802577/rotation-of-3d-vector
495 """
496 axis = np.asarray(axis)
497 axis = axis / np.sqrt(np.dot(axis, axis))
498 a = np.cos(theta / 2.0)
499 b, c, d = -axis * np.sin(theta / 2.0)
500 aa, bb, cc, dd = a * a, b * b, c * c, d * d
501 bc, ad, ac, ab, bd, cd = b * c, a * d, a * c, a * b, b * d, c * d
502 return np.array(
503 [
504 [aa + bb - cc - dd, 2 * (bc + ad), 2 * (bd - ac)],
505 [2 * (bc - ad), aa + cc - bb - dd, 2 * (cd + ab)],
506 [2 * (bd + ac), 2 * (cd - ab), aa + dd - bb - cc],
507 ]
508 )
509
510
512 scale=1.0, origin=[0.0, 0.0, 0.0], plane=0, random_shift=True, shift_scale=0.05
513):
514 """
515 Draw a letter R consisting of 17 particles.
516
517 scale: what the total size of the letter R should be.
518 origin: where to put lower left corner of R
519 plane: along which plane to put the letter:
520 0: x-y plane.
521 1: y-z plane.
522 2: x-z plane.
523 3: rotate by 45deg around axis (1, 1, 1,)
524 perturb: Whether to randomly shift the resulting array
525 by up to `shift_scale`. Use this to avoid having
526 particles end up overlapping once the simulation
527 is running.
528
529 returns: numpy array of 3D coordinates of 17 particles
530 """
531
532 points = [
533 [0.0, 0.0],
534 [0.0, 0.2],
535 [0.0, 0.4],
536 [0.0, 0.6],
537 [0.0, 0.8],
538 [0.0, 1.0],
539 [0.1, 1.0],
540 [0.2, 0.95],
541 [0.3, 0.8],
542 [0.2, 0.625],
543 [0.05, 0.6],
544 [0.1, 0.5],
545 [0.15, 0.4],
546 [0.2, 0.3],
547 [0.25, 0.2],
548 [0.3, 0.1],
549 [0.35, 0.0],
550 ]
551
552 R = np.array(points)
553
554 result = np.zeros((R.shape[0], 3))
555
556 if plane == 0:
557 result[:, 0] = R[:, 0]
558 result[:, 1] = R[:, 1]
559 elif plane == 1:
560 result[:, 1] = R[:, 0]
561 result[:, 2] = R[:, 1]
562 elif plane == 2:
563 result[:, 0] = R[:, 0]
564 result[:, 2] = R[:, 1]
565 elif plane == 3:
566 result[:, 0] = R[:, 0]
567 result[:, 1] = R[:, 1]
568 rot = rotation_matrix([1.0, 1.0, 1], np.pi / 4.0)
569 for i in range(result.shape[0]):
570 result[i, :] = np.dot(rot, result[i, :])
571
572 if random_shift:
573 shift = np.random.uniform(0, shift_scale, size=3)
574 result += shift
575
576 result *= scale
577 result += np.array(origin)
578
579 return result
580
581
582# Generate coorinates.
583
584R1 = draw_R(scale=0.2, origin=[0.1, 0.4, 0.5], plane=0)
585R2 = draw_R(scale=0.2, origin=[0.8, 0.4, 0.5], plane=0)
586R3 = draw_R(scale=0.2, origin=[0.5, 0.1, 0.4], plane=1)
587R4 = draw_R(scale=0.2, origin=[0.5, 0.8, 0.4], plane=1)
588R5 = draw_R(scale=0.2, origin=[0.4, 0.5, 0.1], plane=2)
589R6 = draw_R(scale=0.2, origin=[0.4, 0.5, 0.8], plane=2)
590R7 = draw_R(scale=0.2, origin=[0.1, 0.1, 0.1], plane=3)
591R8 = draw_R(scale=0.2, origin=[0.8, 0.1, 0.1], plane=3)
592R9 = draw_R(scale=0.2, origin=[0.1, 0.8, 0.1], plane=3)
593R10 = draw_R(scale=0.2, origin=[0.8, 0.8, 0.1], plane=3)
594R11 = draw_R(scale=0.2, origin=[0.1, 0.1, 0.8], plane=3)
595R12 = draw_R(scale=0.2, origin=[0.8, 0.1, 0.8], plane=3)
596R13 = draw_R(scale=0.2, origin=[0.1, 0.8, 0.8], plane=3)
597R14 = draw_R(scale=0.2, origin=[0.8, 0.8, 0.8], plane=3)
598
599coords = np.concatenate(
600 (R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14), axis=0
601)
602
603
604project.algorithm_step_initial_conditions.add_action_set(
606 particle_set=particle_set,
607 initialisation_call=initialisation_snippet,
608 coordinates=coords,
609 )
610)
611
612
613
637 "particles",
638 particle_set,
639 "globaldata::{}::getSpecies().getMinTimeStamp()".format(particle.name),
640)
641particle_plotter.add_attribute_to_plot(particle.velocity, dimensions)
642particle_plotter.add_attribute_to_plot(particle.partid, 1)
643project.algorithm_step_plot.add_action_set(particle_plotter)
644
645
646
655peano4_project = project.generate_Peano4_project(verbose=args.verbose)
656peano4_project.output.makefile.add_CXX_flag("-D" + "HYDRO_DIMENSION=3")
657
658peano4_project.constants.export_const_with_type(
659 "GLOBAL_TIME_STEP_SIZE", str(args.timestep_size), "double"
660)
661
662# If we want to start a project from scratch, we may want to remove some of the generated code
663if args.clean_temporary_directories:
664 dirs = ["vertexdata/", "repositories/", "globaldata/", "observers/"]
665 for dir in dirs:
666 shutil.rmtree(dir)
667
668peano4_project.generate(
669 overwrite=peano4.api.output.Overwrite.Always, throw_away_data_after_generation=True
670)
671peano4_project.build(make_clean_first=True, number_of_parallel_builds=args.j)
672
673# remove output files from previous runs
674output_files = [
675 f
676 for f in os.listdir(".")
677 if f.endswith(".peano-patch-file") or f.endswith(".vtu") or f.endswith(".pvd")
678]
679for f in output_files:
680 os.remove(f)
ExaParty project.
Definition Project.py:27
rotation_matrix(axis, theta)
Return the rotation matrix associated with counterclockwise rotation about the given axis by theta ra...
draw_R(scale=1.0, origin=[0.0, 0.0, 0.0], plane=0, random_shift=True, shift_scale=0.05)
Draw a letter R consisting of 17 particles.