Physics-PVD
view release on metacpan or search on metacpan
lib/Physics/PVD/Interface/LAMMPS.pm view on Meta::CPAN
package Physics::PVD::Interface::LAMMPS;
use strict;
use warnings;
use Carp;
use File::Temp qw(tempfile);
use File::Spec;
# âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
# Interface to LAMMPS for advanced PVD molecular dynamics
#
# Uses LAMMPS to perform:
# - Classical MD of sputtering impact cascades
# - Film growth with realistic interatomic potentials (EAM, MEAM, Tersoff)
# - Substrate heating and thermal effects
# - Stress evolution during deposition
# - Adatom mobility on realistic surfaces
# âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
sub new {
my ($class, %opts) = @_;
my $self = bless {
executable => $opts{executable} // 'lmp',
mpi_cmd => $opts{mpi_cmd} // 'mpirun',
n_procs => $opts{n_procs} // 1,
work_dir => $opts{work_dir} // './lammps_pvd',
potential_dir => $opts{potential_dir} // './potentials',
# Simulation parameters
timestep => $opts{timestep} // 1.0, # fs
temperature => $opts{temperature} // 300, # K
pressure => $opts{pressure} // 0, # bar (0 for NVT)
# Substrate
substrate_material => $opts{substrate_material} // 'Cu',
substrate_size => $opts{substrate_size} // [10, 10, 5], # unit cells
substrate_orient => $opts{substrate_orient} // [1, 0, 0], # surface normal
# Potential
potential_type => $opts{potential_type} // 'eam/alloy',
potential_file => $opts{potential_file} // '',
# Deposition
deposit_species => $opts{deposit_species} // 'Ta',
deposit_energy => $opts{deposit_energy} // 5.0, # eV
deposit_rate => $opts{deposit_rate} // 1, # atoms per N timesteps
deposit_interval => $opts{deposit_interval} // 1000, # timesteps between deposits
deposit_angle => $opts{deposit_angle} // 0, # degrees from normal
verbose => $opts{verbose} // 0,
}, $class;
mkdir $self->{work_dir} unless -d $self->{work_dir};
return $self;
}
# Check if LAMMPS is available
sub check_availability {
my ($self) = @_;
my $output = `which $self->{executable} 2>/dev/null`;
chomp $output;
return $output ? 1 : 0;
}
# Generate LAMMPS input script for PVD deposition
sub generate_input {
my ($self, %opts) = @_;
my $template = $opts{template} // 'deposition';
my $filename = $opts{filename} // "$self->{work_dir}/in.pvd";
my $params = $opts{params} // {};
# Merge default params
my %p = (
lib/Physics/PVD/Interface/LAMMPS.pm view on Meta::CPAN
region deposit block 0 $sx 0 $sy $sz @{[$sz+20]} units lattice
# Interatomic potential
pair_style $pot_type
pair_coeff * * $pot_file $sub_mat $dep_mat
# Groups
group substrate type 1
group mobile type 2
# Thermalization of substrate
velocity substrate create $T 12345 dist gaussian
fix thermostat substrate nvt temp $T $T 100.0
fix freeze_bot substrate setforce 0.0 0.0 0.0
# Reflecting wall at top
fix wall all wall/reflect zhi EDGE
# Time integration
timestep $dt
fix integrate mobile nve
# Output
thermo 1000
thermo_style custom step temp pe ke etotal press vol atoms
dump film all atom 5000 $self->{work_dir}/dump.pvd.lammpstrj
# Deposition loop
variable n_deposited equal 0
label deposit_loop
variable dep_x equal random(0,$sx*3.615,12345)
variable dep_y equal random(0,$sy*3.615,23456)
variable dep_z equal ($sz+2)*3.615
variable vz equal -sqrt(2*$dep_E*1.602e-19/(180.95*1.66e-27))*1e-5
create_atoms 2 single \${dep_x} \${dep_y} \${dep_z}
group mobile type 2
velocity mobile set 0.0 0.0 \${vz} units box
run $interval
# Repeat deposition
variable n_deposited equal \${n_deposited}+1
if "\${n_deposited} < $n_dep" then "jump SELF deposit_loop"
# Final relaxation
run @{[$interval * 5]}
write_data $self->{work_dir}/final.data
EOF
}
sub _template_sputtering {
my ($self, %p) = @_;
my $T = $p{temperature};
my $dt = $p{timestep};
my $ion_energy = $p{ion_energy} // 500; # eV
return <<EOF;
# LAMMPS Sputtering Simulation â Generated by Physics::PVD
# Ion bombardment to study sputter yield and cascade dynamics
units metal
atom_style atomic
boundary p p s
lattice bcc 3.3
region target block 0 10 0 10 0 8
create_box 2 target
create_atoms 1 box
pair_style $self->{potential_type}
pair_coeff * * $self->{potential_file} $self->{substrate_material} Ar
# Create Ar ion above target
create_atoms 2 single 5.0 5.0 30.0
group ion type 2
group target type 1
velocity target create $T 54321
velocity ion set 0.0 0.0 -@{[sqrt(2*$ion_energy*1.6e-19/(39.948*1.66e-27))*1e-5]}
fix nve_all all nve
fix temp_ctrl target langevin $T $T 100.0 48279
timestep $dt
thermo 100
dump cascade all atom 50 $self->{work_dir}/dump.sputter.lammpstrj
run @{[$p{total_steps} // 10000]}
write_data $self->{work_dir}/post_sputter.data
EOF
}
sub _template_annealing {
my ($self, %p) = @_;
my $T_start = $p{temperature};
my $T_end = $p{anneal_temp} // 600; # K
return <<EOF;
# LAMMPS Post-Deposition Annealing â Generated by Physics::PVD
units metal
atom_style atomic
boundary p p f
read_data $self->{work_dir}/final.data
pair_style $self->{potential_type}
pair_coeff * * $self->{potential_file} $self->{substrate_material} $self->{deposit_species}
# Ramp temperature for annealing
fix anneal all nvt temp $T_start $T_end 100.0
timestep $self->{timestep}
thermo 1000
dump anneal all atom 5000 $self->{work_dir}/dump.anneal.lammpstrj
run @{[$p{total_steps} // 50000]}
# Cool down
unfix anneal
fix cool all nvt temp $T_end $T_start 100.0
run @{[$p{total_steps} // 50000]}
write_data $self->{work_dir}/annealed.data
EOF
}
# Run LAMMPS with the given input file
sub run {
my ($self, %opts) = @_;
my $input = $opts{input_file} // "$self->{work_dir}/in.pvd";
my $np = $opts{n_procs} // $self->{n_procs};
croak "Input file not found: $input" unless -f $input;
my $cmd;
if ($np > 1) {
$cmd = "$self->{mpi_cmd} -np $np $self->{executable} -in $input > $self->{work_dir}/log.lammps 2>&1";
} else {
$cmd = "$self->{executable} -in $input > $self->{work_dir}/log.lammps 2>&1";
}
print " Running LAMMPS: $cmd\n" if $self->{verbose};
my $rc = system($cmd);
croak "LAMMPS run failed (exit code: $rc)" if $rc != 0;
return $self;
lib/Physics/PVD/Interface/LAMMPS.pm view on Meta::CPAN
push @{$frame->{atoms}}, {
id => $f[0], type => $f[1],
x => $f[2], y => $f[3], z => $f[4],
};
}
}
}
push @frames, $frame if $frame;
close $fh;
return \@frames;
}
# Parse LAMMPS log file for thermodynamic data
sub parse_log {
my ($self, $filename) = @_;
$filename //= "$self->{work_dir}/log.lammps";
croak "Log file not found: $filename" unless -f $filename;
my @thermo;
my $in_thermo = 0;
my @headers;
open my $fh, '<', $filename or croak "Cannot read $filename: $!";
while (<$fh>) {
chomp;
if (/^Step\s/) {
$in_thermo = 1;
@headers = split /\s+/;
next;
}
if ($in_thermo) {
if (/^Loop time/) {
$in_thermo = 0;
next;
}
my @vals = split /\s+/;
next unless @vals == @headers;
my %row;
$row{$headers[$_]} = $vals[$_] for 0 .. $#headers;
push @thermo, \%row;
}
}
close $fh;
return \@thermo;
}
1;
__END__
=head1 NAME
Physics::PVD::Interface::LAMMPS - Interface to LAMMPS for advanced PVD MD
=head1 DESCRIPTION
Generates LAMMPS input scripts and manages molecular dynamics simulations
for PVD processes including deposition, sputtering cascades, and post-
deposition annealing. Supports EAM, MEAM, and Tersoff potentials.
=cut
( run in 0.766 second using v1.01-cache-2.11-cpan-e7c6538aa59 )