Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patchy particle pressure #66

Merged
merged 31 commits into from
Oct 23, 2023
Merged

Patchy particle pressure #66

merged 31 commits into from
Oct 23, 2023

Conversation

tcmoore3
Copy link
Member

@tcmoore3 tcmoore3 commented Oct 8, 2023

Description

Validate pressure computation for discontinuous pair potentials simulated with HPMC.

I also changed the comparison plots to show the distributions of sampled pressures and densities.

Motivation and context

The pressure pressure computation for systems with discontinuous pair potentials in HPMC is currently not tested for validity but should be.

I will add another validation test for the hard sphere + square well + square shoulder system we discussed, but I wanted to get this PR opened because the code will not change very much.

Resolves #43.

How has this been tested?

We discovered a conceptual error in the implementation of the SDF calculation for systems with pair potentials. We implemented a fix at glotzerlab/hoomd-blue@8d7cb2c. That commit is the version of HOOMD-blue I used to generate the results below.

I ran NVT simulations of 4,096 particles interacting either through a hard sphere + square well potential, or through a Kern–Frenkel potential, i.e., a hard sphere + square well model with an angular component to the pair potential. I ran NVT simulations, measured the pressure for the given density and temperature, and then ran NPT simulations at the corresponding pressure. The agreement between the pressure measured in NVT simulations and the density measured at the corresponding NPT simulations is shown in the figures below. These results are from 16 replicates at each statepoint. \chi = 1.0 corresponds to the hard sphere + square well state points, and \chi = 0.7 is the Kern–Frenkel model.

image
image
image
image
image

Checklist:

@tcmoore3 tcmoore3 requested review from a team and joaander and removed request for a team October 8, 2023 22:56
@joaander
Copy link
Member

joaander commented Oct 9, 2023

With short simulations, I tested:

sigma = 1.0
lambda_ = 1.5
epsilon = 1/3.0

with patch code:

    evaluate_square_well = f'''float rsq = dot(r_ij, r_ij);
                               if (rsq < {(lambda_ * sigma/2)**2}f)
                                   return param_array[0];
                               else if (rsq < {(lambda_ * sigma)**2}f)
                                   return param_array[1];
                               else
                                   return 0.0f;
                            '''
    square_well = hoomd.hpmc.pair.user.CPPPotential(r_cut=lambda_ * sigma,
                                                    code=evaluate_square_well,
                                                    param_array=[-epsilon, epsilon])

at a variety of pressures (2-10) and densities (around ~0.7).

Copy link
Member

@joaander joaander left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you have GPU jobs definitions in the workflow. Do you plan to validate that these work properly before merging?

@@ -34,7 +34,7 @@ def __init__(self, config_file_path=DEFAULT_CONFIG_PATH):
config.get("max_cores_submission", 16))
self["max_gpus_submission"] = int(config.get("max_gpus_submission", 1))
self["max_walltime"] = int(config.get("max_walltime", 24))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
self["max_walltime"] = int(config.get("max_walltime", 24))
self["max_walltime"] = float(config.get("max_walltime", 24))

For consistency with the below change.

Comment on lines 20 to 25
# alj_2d,
# lj_fluid,
# lj_union,
# hard_disk,
# hard_sphere,
# simple_polygon,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# alj_2d,
# lj_fluid,
# lj_union,
# hard_disk,
# hard_sphere,
# simple_polygon,
alj_2d,
lj_fluid,
lj_union,
hard_disk,
hard_sphere,
simple_polygon,

# hard_disk,
# hard_sphere,
# simple_polygon,
patchy_particle_pressure
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
patchy_particle_pressure
patchy_particle_pressure,

@@ -28,7 +28,7 @@ def get_job_filename(sim_mode, device, name, type):
return f"{sim_mode}_{suffix}_{name}.{type}"


def run_up_to_walltime(sim, end_step, steps, walltime_stop):
def run_up_to_walltime(sim, end_step, steps, walltime_stop, minutes_per_run=None):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def run_up_to_walltime(sim, end_step, steps, walltime_stop, minutes_per_run=None):
def run_up_to_walltime(sim, end_step, steps, walltime_stop):

unused.


if numpy.all(data_arr == data_arr[0]):
histogram[:] = 0

max_density_histogram = max(max_density_histogram, numpy.max(histogram))

ax.plot(bin_edges[:-1], histogram, label=mode)
if plot_rotated:
XX, YY = histogram, bin_centers #bin_edges[:-1]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the need for the variables by placing the call to plot inside the conditional.

Alternately, replace meaningless XX and YY variable names with something meaningful.

ax.set_ylabel(xlabel)
ax.set_xlabel('probability density')
else:
XX, YY = bin_edges[:-1], histogram
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The unrotated plot should also use bin_centers.

#Y, X = bin_edges[:-1], expected(bin_edges[:-1])
Y, X = bin_centers, expected(bin_centers)
else:
X, Y = bin_edges[:-1], expected(bin_edges[:-1])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The unrotated plot should also use bin_centers.

expected(bin_edges[:-1]),
if plot_rotated:
#Y, X = bin_edges[:-1], expected(bin_edges[:-1])
Y, X = bin_centers, expected(bin_centers)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the need for the variables by placing the call to plot inside the conditional.

Alternately, name these variables with a PEP8 compliant name.

@@ -299,3 +318,46 @@ def plot_timeseries(ax,
def _sort_sim_modes(sim_modes):
"""Sort simulation modes for comparison."""
sim_modes.sort(key=lambda x: ('nvt' in x or 'nec' in x, 'md' in x, x))


def _single_patch_kern_frenkel_code(delta_rad, lambda_, sigma, kT):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this function to patchy_particle_pressure.py.


@Project.pre.after(patchy_particle_pressure_create_initial_state)
@Project.post.isfile(f'{mode}_{device_name}_complete')
#@Project.post(lambda j: j.isfile(f'{mode}_{device_name}_complete') or j.sp.pressure <= 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#@Project.post(lambda j: j.isfile(f'{mode}_{device_name}_complete') or j.sp.pressure <= 0)

@tcmoore3
Copy link
Member Author

Results for the hard sphere + square well + repulsive shoulder potential. It shows similar quantitative agreement NPT and NVT simulations as the Kern–Frenkel and hard sphere + square well systems.
image

Copy link
Member

@joaander joaander left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More fixes to prevent deadlock.

Comment on lines 617 to 618
print(f'completed patchy_particle_pressure_{mode}_{device_name} '
f'{job} in {communicator.walltime} s')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
print(f'completed patchy_particle_pressure_{mode}_{device_name} '
f'{job} in {communicator.walltime} s')
print(f'completed patchy_particle_pressure_{mode}_{device_name}: {job}')

See #67.

Comment on lines 248 to 249
print(f'completed patchy_particle_pressure_create_initial_state: '
f'{job} in {communicator.walltime} s')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
print(f'completed patchy_particle_pressure_create_initial_state: '
f'{job} in {communicator.walltime} s')
print(f'completed patchy_particle_pressure_create_initial_state: {job}')

See #67.

@tcmoore3
Copy link
Member Author

GPU results from 8 replicates at each of 3 statepoints, 1 KF, 1 HSSW, 1 HSSW with a repulsive shoulder. Note that I took the average pressure from the CPU NVT runs, so the deviation from the expected pressure in the 'nvt_gpu' runs are nonzero.
image
image
image

Copy link
Member

@joaander joaander left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! There is one minor change to make, then this is ready to merge.

Comment on lines 36 to 48
# (10.0, 0.95, 11.951630531873338, 0.7, 1.5, 1.0),
(1.0, 0.95, 10.208625410213362, 0.7, 1.5, 1.0),
# (0.6, 0.95, 8.927827449359, 0.7, 1.5, 1.0),
# hard sphere + square well statepoints, from 10.1063/1.3054361
# pressure from NVT simulations, NOT from values in paper
# (0.5714, 0.8, -0.2692376274894095, 1.0, 1.5, 1.0),
# (1.0, 0.8, 2.2766339608381325, 1.0, 1.5, 1.0),
(3.0, 0.8, 4.837436833423719, 1.0, 1.5, 1.0),
# hard sphere + square well + repulsive shoulder statepoints.
# temperatures/densities from initial tests, pressures from NVT
# simulations.
(3.0, 0.7, 4.00804, 1.0, 1.0, -1.0),
# (1.0, 0.7, -5.0, 1.0, 1.0, -1.0),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# (10.0, 0.95, 11.951630531873338, 0.7, 1.5, 1.0),
(1.0, 0.95, 10.208625410213362, 0.7, 1.5, 1.0),
# (0.6, 0.95, 8.927827449359, 0.7, 1.5, 1.0),
# hard sphere + square well statepoints, from 10.1063/1.3054361
# pressure from NVT simulations, NOT from values in paper
# (0.5714, 0.8, -0.2692376274894095, 1.0, 1.5, 1.0),
# (1.0, 0.8, 2.2766339608381325, 1.0, 1.5, 1.0),
(3.0, 0.8, 4.837436833423719, 1.0, 1.5, 1.0),
# hard sphere + square well + repulsive shoulder statepoints.
# temperatures/densities from initial tests, pressures from NVT
# simulations.
(3.0, 0.7, 4.00804, 1.0, 1.0, -1.0),
# (1.0, 0.7, -5.0, 1.0, 1.0, -1.0),
(1.0, 0.95, 10.208625410213362, 0.7, 1.5, 1.0),
# hard sphere + square well statepoints, from 10.1063/1.3054361
# pressure from NVT simulations, NOT from values in paper
(3.0, 0.8, 4.837436833423719, 1.0, 1.5, 1.0),
# hard sphere + square well + repulsive shoulder statepoints.
# temperatures/densities from initial tests, pressures from NVT
# simulations.
(3.0, 0.7, 4.00804, 1.0, 1.0, -1.0),

Remove unused state points.

Copy link
Member

@joaander joaander left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@joaander joaander merged commit b6ab253 into trunk Oct 23, 2023
2 checks passed
@joaander joaander deleted the patchy-particle-pressure branch October 23, 2023 13:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Validate expansive SDF.
2 participants