Coverage for examples/molecules.py: 100%
101 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
1import numpy as np
2import gamdpy as gp
4gp.select_gpu()
6# Simulation params
7rho, temperature = 0.85, 1.5
8N_A, N_B, N_C = 8, 4, 4 # Number of atoms of each tyoe
9particles_per_molecule = N_A + N_B + N_C
10filename = 'Data/molecules'
11num_timeblocks = 64
12steps_per_timeblock = 1 * 1024 # 8 * 1024 to show reliable pattern formation
14positions = []
15particle_types = []
16masses = []
18# A particles
19for i in range(N_A):
20 positions.append( [ i*1.0, (i%2)*.1, 0. ] ) # x, y, z for this particle
21 particle_types.append( 0 )
22 masses.append( 1.0 )
24# B particles
25for i in range(N_B):
26 positions.append( [ 0, (i+1)*1.0, ((i+1)%2)*.1 ] ) # x, y, z for this particle
27 particle_types.append( 1 )
28 masses.append( 1.0 )
30# C particles
31for i in range(N_C):
32 positions.append( [ ((i+1)%2)*.1, 0, (i+1)*1.0 ] ) # x, y, z for this particle
33 particle_types.append( 2 )
34 masses.append( 1.0 )
36# Setup configuration: Single molecule first, then duplicate
37top = gp.Topology(['MyMolecule', ])
38top.bonds = gp.bonds_from_positions(positions, cut_off=1.1, bond_type=0)
39top.angles = gp.angles_from_bonds(top.bonds, angle_type=0)
40top.dihedrals = gp.dihedrals_from_angles(top.angles, dihedral_type=0)
41top.molecules['MyMolecule'] = gp.molecules_from_bonds(top.bonds)
44dict_this_mol = {"positions" : positions,
45 "particle_types" : particle_types,
46 "masses" : masses,
47 "topology" : top}
49print('Initial Positions:')
50for position in positions:
51 print('\t\t', position)
52print('Particle types:\t', particle_types)
53print('Bonds: \t', top.bonds)
54print('Angles: \t', top.angles)
55print('Dihedrals: \t', top.dihedrals)
56print()
58# This call creates the pdf "molecule.pdf" with a drawing of the molecule
59# Use block=True to visualize the molecule before running the simulation
60gp.plot_molecule(top, positions, particle_types, filename="molecule.pdf", block=False)
62configuration = gp.replicate_molecules([dict_this_mol], [216], safety_distance=2.0, compute_flags={"stresses":True})
64configuration.randomize_velocities(temperature=temperature)
66print(f'Number of molecules: {len(configuration.topology.molecules["MyMolecule"])}')
67print(f'Number of particles: {configuration.N}\n')
69# Make bond interactions
70bond_potential = gp.harmonic_bond_function
71bond_params = [[0.8, 1000.], ]
72bonds = gp.Bonds(bond_potential, bond_params, configuration.topology.bonds)
74# Make angle interactions
75angle_potential = gp.cos_angle_function
76angle0, k = 2.0, 500.0
77angles = gp.Angles(angle_potential, configuration.topology.angles, parameters=[[k, angle0],])
79# Make dihedral interactions
80dihedral_potential = gp.ryckbell_dihedral
81rbcoef=[.0, 5.0, .0, .0, .0, .0]
82dihedrals = gp.Dihedrals(dihedral_potential, configuration.topology.dihedrals, parameters=[rbcoef, ])
84# Exlusion list
85exclusions = dihedrals.get_exclusions(configuration)
86#exclusions = bonds.get_exclusions(configuration)
88# Make pair potential
89pair_func = gp.apply_shifted_force_cutoff(gp.LJ_12_6_sigma_epsilon)
90sig = [[1.00, 1.00, 1.00],
91 [1.00, 1.00, 1.00],
92 [1.00, 1.00, 1.00],]
93eps = [[1.00, 1.00, 1.00],
94 [1.00, 1.00, 0.80],
95 [1.00, 0.80, 1.00],]
96cut = [[2.50, 1.12, 1.12],
97 [1.12, 2.50, 2.50],
98 [1.12, 2.50, 2.50]]
100pair_pot = gp.PairPotential(pair_func, params=[sig, eps, cut], exclusions=exclusions, max_num_nbs=1000)
102# Make integrator
103integrator = gp.integrators.NVT(temperature=temperature, tau=0.1, dt=0.004)
105# Setup runtime actions, i.e. actions performed during simulation of timeblocks
106runtime_actions = [gp.TrajectorySaver(),
107 gp.ScalarSaver(32),
108 gp.StressSaver(32, compute_flags={'stresses':True}),
109 gp.MomentumReset(100)]
111# Setup simulation
112sim = gp.Simulation(configuration, [pair_pot, bonds, angles, dihedrals], integrator, runtime_actions,
113 num_timeblocks=num_timeblocks, steps_per_timeblock=steps_per_timeblock,
114 storage='memory')
116print('\nCompression and equilibration: ')
117dump_filename = 'Data/dump_compress.lammps'
118with open(dump_filename, 'w') as f:
119 print(gp.configuration_to_lammps(sim.configuration, timestep=0), file=f)
121initial_rho = configuration.N / configuration.get_volume()
122for block in sim.run_timeblocks():
123 volume = configuration.get_volume()
124 N = configuration.N
125 print(sim.status(per_particle=True), f'rho= {N/volume:.3}', end='\t')
126 print(f'P= {(N*temperature + np.sum(configuration["W"]))/volume:.3}') # pV = NkT + W
127 with open(dump_filename, 'a') as f:
128 print(gp.configuration_to_lammps(sim.configuration, timestep=sim.steps_per_block*(block+1)), file=f)
130 # Scale configuration to get closer to final density, rho
131 if block<sim.num_blocks/2:
132 desired_rho = (block+1)/(sim.num_blocks/2)*(rho - initial_rho) + initial_rho
133 configuration.atomic_scale(density=desired_rho)
134 configuration.copy_to_device() # Since we altered configuration, we need to copy it back to device
135print(sim.summary())
136print(configuration)
138sim = gp.Simulation(configuration, [pair_pot, bonds, angles, dihedrals], integrator, runtime_actions,
139 num_timeblocks=num_timeblocks, steps_per_timeblock=steps_per_timeblock,
140 compute_plan=sim.compute_plan, storage=filename+'.h5')
142print('\nProduction: ')
143dump_filename = 'Data/dump.lammps'
144with open(dump_filename, 'w') as f:
145 print(gp.configuration_to_lammps(sim.configuration, timestep=0), file=f)
147for block in sim.run_timeblocks():
148 print(sim.status(per_particle=True))
149 with open(dump_filename, 'a') as f:
150 print(gp.configuration_to_lammps(sim.configuration, timestep=sim.steps_per_block*(block+1)), file=f)
152print(sim.summary())
153print(configuration)
155W = gp.extract_scalars(sim.output, 'W')
156full_stress_tensor = gp.extract_stress_tensor(sim.output)
157mean_diagonal_sts = (full_stress_tensor[:,0,0] + full_stress_tensor[:,1,1] + full_stress_tensor[:,2,2])/3
159print("Mean diagonal stress", np.mean(mean_diagonal_sts) )
160print("Pressure", np.mean(W)*rho/N + temperature*rho)
162print('\nAnalyse structure with:')
163print(' python3 analyze_structure.py Data/molecules')
165print('\nAnalyze dynamics with:')
166print(' python3 analyze_dynamics.py Data/molecules')
168print('\nVisualize simulation in ovito with:')
169print(' ovito Data/dump.lammps')
171#print('\nVisualize simulation in VMD with:')
172#print(' vmd -lammpstrj Data/dump.lammps')