Coverage for examples/rubber_cube.py: 83%
66 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
1""" A rubber cube modeled as particles connected by springs """
3from itertools import product
4from math import pi, sin, cos
6import numpy as np
7import matplotlib.pyplot as plt
9import gamdpy as gp
11# A rotated cube of particles
12lattice_length = 8 # Number of particles in each direction
13cm = np.array([0.0, 0.0, 0.0]) # Initial position of center of mass
14theta_z = pi/12 # 1st rotation around z-axis
15theta_x = pi/24 # 2nd rotation around x-axis
16cube = np.array([(x, y, z) for x, y, z in product(range(lattice_length), repeat=3)])
17center = cube.mean(axis=0)
18rot_matrix_z = np.array([
19 [cos(theta_z), sin(theta_z), 0],
20 [-sin(theta_z), cos(theta_z), 0],
21 [0, 0, 1]
22])
23rot_matrix_x = np.array([
24 [1, 0, 0],
25 [0, cos(theta_z), sin(theta_z)],
26 [0, -sin(theta_z), cos(theta_z)],
27])
28N = lattice_length**3
29cube = (cube - center) @ rot_matrix_z @ rot_matrix_x + cm
30configuration = gp.Configuration(D=3, N=N)
31configuration['r'] = cube
32configuration['m'] = 1.0
33box_length = 64
34configuration.simbox = gp.Orthorhombic(3, [box_length, box_length, box_length])
35configuration.randomize_velocities(temperature=0.001)
36# Compute plan
37compute_plan = {'pb': 16, 'tp': 4, 'skin': 2.0, 'UtilizeNIII': False, 'gridsync': False, 'nblist': 'N squared'}
39# Create bonds
40bond_potential = gp.harmonic_bond_function
41bond_params = [
42 [1.0, 100.0],
43 [2**0.5, 10.0]
44]
45bond_directions =[
46 # (dx, dy, dz), bond_type
47 ((1, 0, 0), 0),
48 ((0, 1, 0), 0),
49 ((0, 0, 1), 0),
50 ((0, 1, 1), 1),
51 ((1, 0, 1), 1),
52 ((1, 1, 0), 1)
53]
54L = lattice_length
55def xyz2idx(x, y, z):
56 return x + y*L + z*L**2
57neighbour_bonds = []
58for x, y, z in product(range(L), repeat=3):
59 this = xyz2idx(x, y, z)
60 for (dx, dy, dz), bond_type in bond_directions:
61 if x + dx < L and y + dy < L and z + dz < L:
62 that = xyz2idx(x+dx, y+dy, z+dz)
63 neighbour_bonds.append([this, that, bond_type])
64bonds = gp.Bonds(bond_potential, bond_params, neighbour_bonds)
66# Create a 3D figure showing bonds
67plot = False
68if plot:
69 fig = plt.figure()
70 ax = fig.add_subplot(111, projection='3d')
71 pos = configuration['r']
72 for bond in neighbour_bonds:
73 n, m, _ = bond
74 xs = [pos[n, 0], pos[m, 0]]
75 ys = [pos[n, 1], pos[m, 1]]
76 zs = [pos[n, 2], pos[m, 2]]
77 ax.plot(xs, ys, zs, 'k-', linewidth=1)
78 ax.scatter(cube[:, 0], cube[:, 1], cube[:, 2], c=cube[:, 2])
79 plt.show()
81# Add two smooth walls
82wall_distance = box_length/2
83walls = gp.interactions.Planar(
84 potential=gp.harmonic_repulsion,
85 params=[[100.0, 1.0], [100.0, 1.0]],
86 indices=[[n, 0] for n in range(N)] + [[n, 1] for n in range(N)], # All particles feel both walls
87 normal_vectors=[[0.0, 1.0, 0.0], [0.0, -1.0, 0.0]],
88 points=[[0.0, -wall_distance/2, 0], [0.0, wall_distance/2, 0]]
89)
91# Add gravity
92mg = 0.0005
93potential_gravity = gp.make_IPL_n(-1)
94gravity = gp.interactions.Planar(
95 potential=potential_gravity,
96 params= [[mg, 10*wall_distance]],
97 indices= [[n, 0] for n in range(N)], # All particles feel the gravity
98 normal_vectors= [[0,1,0], ],
99 points= [[0, -wall_distance/2.0, 0] ] # Defining 0 for potential energy on lower wall
100)
102# Setup simulation
103integrator = gp.integrators.NVE(dt=0.01)
104runtime_actions = [gp.TrajectorySaver(),
105 gp.ScalarSaver(steps_between_output=1)]
106interactions = [bonds, walls, gravity]
107sim = gp.Simulation(configuration, interactions, integrator, runtime_actions,
108 num_timeblocks=64, steps_per_timeblock=1024,
109 storage='memory')
111# Run simulation and save as lammps trajectory
112dump_filename = 'Data/rubber_cube.lammps'
113with open(dump_filename, 'w') as f:
114 print(gp.configuration_to_lammps(sim.configuration, timestep=0), file=f)
116for block in sim.run_timeblocks():
117 print(sim.status(per_particle=True))
118 with open(dump_filename, 'a') as f:
119 print(gp.configuration_to_lammps(sim.configuration, timestep=sim.steps_per_block*(block+1)), file=f)
121print(sim.summary())