Tutorial: Contact Angle Analysis (Binning Method)
This tutorial demonstrates how to compute the contact angle using the binning method in wetting_angle_kit.
The method divides the simulation box into spatial bins to calculate the liquid–solid interface and the corresponding contact angle, for a group of frames.
1. Overview
The binning method works by:
Collecting the positions of water molecules (typically oxygen atoms).
Dividing the region of interest into bins in the x–z plane.
Computing density profiles and fitting the interface shape.
Deriving the contact angle from the interface curvature.
2. Prerequisites
Your trajectory file (e.g., a LAMMPS dump file) should contain:
Atom IDs, types, and positions
Liquid particles (in this case, water molecules: O and H atoms)
Example trajectory:
tests/trajectories/traj_10_3_330w_nve_4k_reajust.lammpstrj
3. Example Script
# Import necessary modules
from wetting_angle_kit.parsers import LammpsDumpParser, LammpsDumpWaterFinder
from wetting_angle_kit.analysis import BinningTrajectoryAnalyzer
# --- Step 1: Define the trajectory file ---
filename = "../../tests/trajectories/traj_10_3_330w_nve_4k_reajust.lammpstrj"
# --- Step 2: Initialize the water molecule finder ---
# This identifies O and H atoms in water molecules
wat_find = LammpsDumpWaterFinder(
filename,
particle_type_wall={3}, # Wall atom types
oxygen_type=1, # Oxygen atom type
hydrogen_type=2, # Hydrogen atom type
)
# --- Step 3: Get oxygen atom indices for the first frame ---
oxygen_indices = wat_find.get_water_oxygen_ids(frame_index=0)
print("Number of water molecules:", len(oxygen_indices))
# --- Step 4: Define binning parameters ---
binning_params = {
"xi_0": 0.0, # Minimum x-coordinate
"xi_f": 100.0, # Maximum x-coordinate
"nbins_xi": 50, # Number of bins along x
"zi_0": 0.0, # Minimum z-coordinate
"zi_f": 100.0, # Maximum z-coordinate
"nbins_zi": 25, # Number of bins along z
}
# --- Step 5: Initialize the parser ---
parser = LammpsDumpParser(filename)
# --- Step 6: Create the contact angle analyzer ---
analyzer = BinningTrajectoryAnalyzer(
parser=parser,
atom_indices=oxygen_indices,
droplet_geometry="cylinder_y", # Interface fitting model
binning_params=binning_params,
)
# --- Step 7: Run analysis for a frame range ---
results = analyzer.analyze([1]) # Analyze frame 1
print("Mean contact angle (°):", results.mean_angle)
4. Output
Running this example will:
Parse the trajectory.
Compute the interface shape and local contact angle for each batch.
Return a
BinningResultsdataclass holding angles, density fields and fitted isolines for every batch (no files written).
Example printed output:
Number of water molecules: 4000
Mean contact angle (°): 94.58987060394456
The returned results object exposes mean_angle, std_angle,
angles_per_batch and a batches list whose entries carry the
density field (xi_cc, zi_cc, rho_cc) and the fitted
droplet / wall isoline coordinates. Feed it directly to
BinningTrajectoryPlotter to draw the interactive density
contour with the fitted semi-circle:
from wetting_angle_kit.visualization import BinningTrajectoryPlotter
plotter = BinningTrajectoryPlotter(results)
fig = plotter.plot_density_contour(batch_index=0)
fig.show()
5. Tips
Adjust
xi_f,zi_f, and the bin counts (nbins_xi,nbins_zi) according to your simulation box dimensions.If the wall surface is not flat or the system is tilted, pre-align it before analysis.
Multi-batch analysis:
analyzer.analyze(range(0, 100), split_factor=10)splits the frame range into batches of ten frames each.