<commit_before># Highly Optimized Object-Oriented Molecular Dynamics (HOOMD) Open
# Source Software License
# Copyright (c) 2008 Ames Laboratory Iowa State University
# All rights reserved.

# Redistribution and use of HOOMD, in source and binary forms, with or
# without modification, are permitted, provided that the following
# conditions are met:

# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.

# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.

# * Neither the name of the copyright holder nor the names HOOMD's
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.

# Disclaimer

# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND
# CONTRIBUTORS ``AS IS''  AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 

# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS  BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.

# $Id$
# $URL$

## \package hoomd_script.pair
# \brief Commands that create forces between pairs of particles
#
# Generally, %pair forces are short range and are summed over all non-bonded particles
# within a certain cutoff radius of each particle. Any number of %pair forces
# can be defined in a single simulation. The net %force on each particle due to
# all types of %pair forces is summed.
#
# Pair forces require that parameters be set for each unique type %pair. Coefficients
# are set through the aid of the coeff class. To set this coefficients, specify 
# a %pair %force and save it in a variable
# \code
# my_force = pair.some_pair_force(arguments...)
# \endcode
# Then the coefficients can be set using the saved variable.
# \code
# my_force.pair_coeff.set('A', 'A', epsilon=1.0, sigma=1.0, alpha=0.0)
# my_force.pair_coeff.set('A', 'B', epsilon=1.0, sigma=1.0, alpha=0.0)
# my_force.pair_coeff.set('B', 'B', epsilon=1.0, sigma=1.0, alpha=1.0)
# \endcode
# This example set the parameters \a epsilon, \a sigma, and \a alpha 
# (which are used in pair.lj). Different %pair forces require that different
# coefficients are set. Check the documentation of each to see the definition
# of the coefficients.
#
# \sa \ref page_quick_start

import globals;
import force;
import hoomd;
import util;
import tune;

import math;
import sys;

## Defines %pair coefficients
# 
# All %pair forces use coeff to specify the coefficients between different
# pairs of particles indexed by type. The set of %pair coefficients is a symmetric
# matrix defined over all possible pairs of particle types.
#
# There are two ways to set the coefficients for a particular %pair %force. 
# The first way is to save the %pair %force in a variable and call set() directly.
# To see an example of this, see the documentation for the package pair
# or the \ref page_quick_start
#
# The second method is to build the coeff class first and then assign it to the
# %pair %force. There are some advantages to this method in that you could specify a
# complicated set of %pair coefficients in a separate python file and import it into
# your job script.
#
# Example (file \em force_field.py):
# \code
# from hoomd_script import *
# my_coeffs = pair.coeff();
# my_coeffs.set('A', 'A', epsilon=1.0, sigma=1.0, alpha=0.0)
# my_coeffs.set('A', 'B', epsilon=1.0, sigma=1.0, alpha=0.0)
# my_coeffs.set('B', 'B', epsilon=1.0, sigma=1.0, alpha=1.0)
# \endcode
# Example job script:
# \code
# from hoomd_script import *
# import force_field
#
# .....
# my_force = pair.some_pair_force(arguments...)
# my_force.pair_coeff = force_field.my_coeffs
# \endcode
class coeff:
	
	## \internal
	# \brief Initializes the class
	# \details
	# The main task to be performed during initialization is just to init some variables
	# \param self Python required class instance variable
	def __init__(self):
		self.values = {};
		
	## \var values
	# \internal
	# \brief Contains the matrix of set values in a dictionary
	
	## Sets parameters for one type %pair
	# \param a First particle type in the %pair
	# \param b Second particle type in the %pair
	# \param coeffs Named coefficients (see below for examples)
	#
	# Calling set() results in one or more parameters being set for a single type %pair.
	# Particle types are identified by name, and parameters are also added by name. 
	# Which parameters you need to specify depends on the %pair %force you are setting
	# these coefficients for, see the corresponding documentation.
	#
	# All possible type pairs as defined in the simulation box must be specified before
	# executing run(). You will receive an error if you fail to do so. It is not an error,
	# however, to specify coefficients for particle types that do not exist in the simulation.
	# This can be useful in defining a %force field for many different types of particles even
	# when some simulations only include a subset.
	#
	# There is no need to specify coefficients for both pairs 'A','B' and 'B','A'. Specifying
	# only one is sufficient.
	#
	# \b Examples:
	# \code
	# coeff.set('A', 'A', epsilon=1.0, sigma=1.0)
	# coeff.set('B', 'B', epsilon=2.0, sigma=1.0)
	# coeff.set('A', 'B', epsilon=1.5, sigma=1.0)
	# \endcode
	#
	# \note Single parameters can be updated. If both epsilon and sigma have already been 
	# set for a type %pair, then executing coeff.set('A', 'B', epsilon=1.1) will %update 
	# the value of epsilon and leave sigma as it was previously set.
	def set(self, a, b, **coeffs):
		util.print_status_line();
		
		# create the pair if it hasn't been created it
		if (not (a,b) in self.values) and (not (b,a) in self.values):
			self.values[(a,b)] = {};
			
		# Find the pair to update
		if (a,b) in self.values:
			cur_pair = (a,b);
		elif (b,a) in self.values:
			cur_pair = (b,a);
		else:
			print >> sys.stderr, "\nBug detected in pair.coeff. Please report\n"
			raise RuntimeError("Error setting pair coeff");
		
		# update each of the values provided
		if len(coeffs) == 0:
			print >> sys.stderr, "\n***Error! No coefficents specified\n";
		for name, val in coeffs.items():
			self.values[cur_pair][name] = val;
	
	## \internal
	# \brief Verifies set parameters form a full matrix with all values set
	# \details
	# \param self Python required self variable
	# \param required_coeffs list of required variables
	#
	# This can only be run after the system has been initialized
	def verify(self, *required_coeffs):
		# first, check that the system has been initialized
		if globals.system == None:
			print >> sys.stderr, "\n***Error! Cannot verify pair coefficients before initialization\n";
			raise RuntimeError('Error verifying pair coefficients');
		
		# get a list of types from the particle data
		ntypes = globals.particle_data.getNTypes();
		type_list = [];
		for i in xrange(0,ntypes):
			type_list.append(globals.particle_data.getNameByType(i));
		
		valid = True;
		# loop over all possible pairs and verify that all required variables are set
		for i in xrange(0,ntypes):
			for j in xrange(i,ntypes):
				a = type_list[i];
				b = type_list[j];
				
				# find which half of the pair is set
				if (a,b) in self.values:
					cur_pair = (a,b);
				elif (b,a) in self.values:
					cur_pair = (b,a);
				else:
					print >> sys.stderr, "\n***Error! Type pair", (a,b), "not found in pair coeff\n"
					valid = False;
					continue;
				
				# verify that all required values are set by counting the matches
				count = 0;
				for coeff_name in self.values[cur_pair].keys():
					if not coeff_name in required_coeffs:
						print "Notice: Possible typo? Pair coeff", coeff_name, "is specified for pair", (a,b), ", but is not used by the pair force";
					else:
						count += 1;
				
				if count != len(required_coeffs):
					print >> sys.stderr, "\n***Error! Type pair", (a,b), "is missing required coefficients\n";
					valid = False;
				
			
		return valid;
		
	## \internal
	# \brief Gets the value of a single pair coefficient
	# \detail
	# \param a First name in the type pair
	# \param b Second name in the type pair
	# \param coeff_name Coefficient to get
	def get(self, a, b, coeff_name):
		# Find the pair to update
		if (a,b) in self.values:
			cur_pair = (a,b);
		elif (b,a) in self.values:
			cur_pair = (b,a);
		else:
			print >> sys.stderr, "\nBug detected in pair.coeff. Please report\n"
			raise RuntimeError("Error setting pair coeff");
		
		return self.values[cur_pair][coeff_name];
		
		
## Interface for controlling neighbor list parameters
#
# A neighbor list should not be directly created by you. One will be automatically
# created whenever a %pair %force is specified. The cutoff radius is set to the
# maximum of that set for all defined %pair forces.
#
# Any bonds defined in the simulation are automatically used to exclude bonded particle
# pairs from appearing in the neighbor list.
class nlist:
	## \internal
	# \brief Constructs a neighbor list
	# \details
	# \param self Python required instance variable
	# \param r_cut Cutoff radius
	def __init__(self, r_cut):
		# check if initialization has occured
		if globals.system == None:
			print >> sys.stderr, "\n***Error!Cannot create neighbor list before initialization\n";
			raise RuntimeError('Error creating neighbor list');
		
		# decide wether to create an all-to-all neighbor list or a binned one based on box size:
		default_r_buff = 0.8;
		
		mode = "binned";
		
		box = globals.particle_data.getBox();
		min_width_for_bin = (default_r_buff + r_cut)*3.0;
		if (box.xhi - box.xlo) < min_width_for_bin or (box.yhi - box.ylo) < min_width_for_bin or (box.zhi - box.zlo) < min_width_for_bin:
			print "Notice: Forcing use of O(N^2) neighbor list due to small box dimensions";
			mode = "nsq";
		
		# create the C++ mirror class
		if globals.particle_data.getExecConf().exec_mode == hoomd.ExecutionConfiguration.executionMode.CPU:
			if mode == "binned":
				self.cpp_nlist = hoomd.BinnedNeighborList(globals.particle_data, r_cut, default_r_buff)
			elif mode == "nsq":
				self.cpp_nlist = hoomd.NeighborList(globals.particle_data, r_cut, default_r_buff)
			else:
				print >> sys.stderr, "\n***Error! Invalid neighbor list mode\n";
				raise RuntimeError("Error creating neighbor list");
		elif globals.particle_data.getExecConf().exec_mode == hoomd.ExecutionConfiguration.executionMode.GPU:
			if mode == "binned":
				self.cpp_nlist = hoomd.BinnedNeighborListGPU(globals.particle_data, r_cut, default_r_buff)<commit_msg>Expanded warning message when O(N^2) nlist is forced. ticket #260<commit_after># Highly Optimized Object-Oriented Molecular Dynamics (HOOMD) Open
# Source Software License
# Copyright (c) 2008 Ames Laboratory Iowa State University
# All rights reserved.

# Redistribution and use of HOOMD, in source and binary forms, with or
# without modification, are permitted, provided that the following
# conditions are met:

# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.

# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.

# * Neither the name of the copyright holder nor the names HOOMD's
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.

# Disclaimer

# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND
# CONTRIBUTORS ``AS IS''  AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 

# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS  BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.

# $Id$
# $URL$

## \package hoomd_script.pair
# \brief Commands that create forces between pairs of particles
#
# Generally, %pair forces are short range and are summed over all non-bonded particles
# within a certain cutoff radius of each particle. Any number of %pair forces
# can be defined in a single simulation. The net %force on each particle due to
# all types of %pair forces is summed.
#
# Pair forces require that parameters be set for each unique type %pair. Coefficients
# are set through the aid of the coeff class. To set this coefficients, specify 
# a %pair %force and save it in a variable
# \code
# my_force = pair.some_pair_force(arguments...)
# \endcode
# Then the coefficients can be set using the saved variable.
# \code
# my_force.pair_coeff.set('A', 'A', epsilon=1.0, sigma=1.0, alpha=0.0)
# my_force.pair_coeff.set('A', 'B', epsilon=1.0, sigma=1.0, alpha=0.0)
# my_force.pair_coeff.set('B', 'B', epsilon=1.0, sigma=1.0, alpha=1.0)
# \endcode
# This example set the parameters \a epsilon, \a sigma, and \a alpha 
# (which are used in pair.lj). Different %pair forces require that different
# coefficients are set. Check the documentation of each to see the definition
# of the coefficients.
#
# \sa \ref page_quick_start

import globals;
import force;
import hoomd;
import util;
import tune;

import math;
import sys;

## Defines %pair coefficients
# 
# All %pair forces use coeff to specify the coefficients between different
# pairs of particles indexed by type. The set of %pair coefficients is a symmetric
# matrix defined over all possible pairs of particle types.
#
# There are two ways to set the coefficients for a particular %pair %force. 
# The first way is to save the %pair %force in a variable and call set() directly.
# To see an example of this, see the documentation for the package pair
# or the \ref page_quick_start
#
# The second method is to build the coeff class first and then assign it to the
# %pair %force. There are some advantages to this method in that you could specify a
# complicated set of %pair coefficients in a separate python file and import it into
# your job script.
#
# Example (file \em force_field.py):
# \code
# from hoomd_script import *
# my_coeffs = pair.coeff();
# my_coeffs.set('A', 'A', epsilon=1.0, sigma=1.0, alpha=0.0)
# my_coeffs.set('A', 'B', epsilon=1.0, sigma=1.0, alpha=0.0)
# my_coeffs.set('B', 'B', epsilon=1.0, sigma=1.0, alpha=1.0)
# \endcode
# Example job script:
# \code
# from hoomd_script import *
# import force_field
#
# .....
# my_force = pair.some_pair_force(arguments...)
# my_force.pair_coeff = force_field.my_coeffs
# \endcode
class coeff:
	
	## \internal
	# \brief Initializes the class
	# \details
	# The main task to be performed during initialization is just to init some variables
	# \param self Python required class instance variable
	def __init__(self):
		self.values = {};
		
	## \var values
	# \internal
	# \brief Contains the matrix of set values in a dictionary
	
	## Sets parameters for one type %pair
	# \param a First particle type in the %pair
	# \param b Second particle type in the %pair
	# \param coeffs Named coefficients (see below for examples)
	#
	# Calling set() results in one or more parameters being set for a single type %pair.
	# Particle types are identified by name, and parameters are also added by name. 
	# Which parameters you need to specify depends on the %pair %force you are setting
	# these coefficients for, see the corresponding documentation.
	#
	# All possible type pairs as defined in the simulation box must be specified before
	# executing run(). You will receive an error if you fail to do so. It is not an error,
	# however, to specify coefficients for particle types that do not exist in the simulation.
	# This can be useful in defining a %force field for many different types of particles even
	# when some simulations only include a subset.
	#
	# There is no need to specify coefficients for both pairs 'A','B' and 'B','A'. Specifying
	# only one is sufficient.
	#
	# \b Examples:
	# \code
	# coeff.set('A', 'A', epsilon=1.0, sigma=1.0)
	# coeff.set('B', 'B', epsilon=2.0, sigma=1.0)
	# coeff.set('A', 'B', epsilon=1.5, sigma=1.0)
	# \endcode
	#
	# \note Single parameters can be updated. If both epsilon and sigma have already been 
	# set for a type %pair, then executing coeff.set('A', 'B', epsilon=1.1) will %update 
	# the value of epsilon and leave sigma as it was previously set.
	def set(self, a, b, **coeffs):
		util.print_status_line();
		
		# create the pair if it hasn't been created it
		if (not (a,b) in self.values) and (not (b,a) in self.values):
			self.values[(a,b)] = {};
			
		# Find the pair to update
		if (a,b) in self.values:
			cur_pair = (a,b);
		elif (b,a) in self.values:
			cur_pair = (b,a);
		else:
			print >> sys.stderr, "\nBug detected in pair.coeff. Please report\n"
			raise RuntimeError("Error setting pair coeff");
		
		# update each of the values provided
		if len(coeffs) == 0:
			print >> sys.stderr, "\n***Error! No coefficents specified\n";
		for name, val in coeffs.items():
			self.values[cur_pair][name] = val;
	
	## \internal
	# \brief Verifies set parameters form a full matrix with all values set
	# \details
	# \param self Python required self variable
	# \param required_coeffs list of required variables
	#
	# This can only be run after the system has been initialized
	def verify(self, *required_coeffs):
		# first, check that the system has been initialized
		if globals.system == None:
			print >> sys.stderr, "\n***Error! Cannot verify pair coefficients before initialization\n";
			raise RuntimeError('Error verifying pair coefficients');
		
		# get a list of types from the particle data
		ntypes = globals.particle_data.getNTypes();
		type_list = [];
		for i in xrange(0,ntypes):
			type_list.append(globals.particle_data.getNameByType(i));
		
		valid = True;
		# loop over all possible pairs and verify that all required variables are set
		for i in xrange(0,ntypes):
			for j in xrange(i,ntypes):
				a = type_list[i];
				b = type_list[j];
				
				# find which half of the pair is set
				if (a,b) in self.values:
					cur_pair = (a,b);
				elif (b,a) in self.values:
					cur_pair = (b,a);
				else:
					print >> sys.stderr, "\n***Error! Type pair", (a,b), "not found in pair coeff\n"
					valid = False;
					continue;
				
				# verify that all required values are set by counting the matches
				count = 0;
				for coeff_name in self.values[cur_pair].keys():
					if not coeff_name in required_coeffs:
						print "Notice: Possible typo? Pair coeff", coeff_name, "is specified for pair", (a,b), ", but is not used by the pair force";
					else:
						count += 1;
				
				if count != len(required_coeffs):
					print >> sys.stderr, "\n***Error! Type pair", (a,b), "is missing required coefficients\n";
					valid = False;
				
			
		return valid;
		
	## \internal
	# \brief Gets the value of a single pair coefficient
	# \detail
	# \param a First name in the type pair
	# \param b Second name in the type pair
	# \param coeff_name Coefficient to get
	def get(self, a, b, coeff_name):
		# Find the pair to update
		if (a,b) in self.values:
			cur_pair = (a,b);
		elif (b,a) in self.values:
			cur_pair = (b,a);
		else:
			print >> sys.stderr, "\nBug detected in pair.coeff. Please report\n"
			raise RuntimeError("Error setting pair coeff");
		
		return self.values[cur_pair][coeff_name];
		
		
## Interface for controlling neighbor list parameters
#
# A neighbor list should not be directly created by you. One will be automatically
# created whenever a %pair %force is specified. The cutoff radius is set to the
# maximum of that set for all defined %pair forces.
#
# Any bonds defined in the simulation are automatically used to exclude bonded particle
# pairs from appearing in the neighbor list.
class nlist:
	## \internal
	# \brief Constructs a neighbor list
	# \details
	# \param self Python required instance variable
	# \param r_cut Cutoff radius
	def __init__(self, r_cut):
		# check if initialization has occured
		if globals.system == None:
			print >> sys.stderr, "\n***Error!Cannot create neighbor list before initialization\n";
			raise RuntimeError('Error creating neighbor list');
		
		# decide wether to create an all-to-all neighbor list or a binned one based on box size:
		default_r_buff = 0.8;
		
		mode = "binned";
		
		box = globals.particle_data.getBox();
		min_width_for_bin = (default_r_buff + r_cut)*3.0;
		if (box.xhi - box.xlo) < min_width_for_bin or (box.yhi - box.ylo) < min_width_for_bin or (box.zhi - box.zlo) < min_width_for_bin:
			if globals.particle_data.getN() >= 2000:
				print "\n***Warning!: At least one simulation box dimension is less than (r_cut + r_buff)*3.0. This forces the use of an";
				print "             EXTREMELY SLOW O(N^2) calculation for the neighbor list. If your simulation is confined to a 2D"
				print "             plane, you can increase the smallest box dimension to enable the more efficient O(N) calculation.\n"
			else:
				print "Notice: The system is in a very small box, forcing the use of an O(N^2) neighbor list calculation."
				
			mode = "nsq";
		
		# create the C++ mirror class
		if globals.particle_data.getExecConf().exec_mode == hoomd.ExecutionConfiguration.executionMode.CPU:
			if mode == "binned":
				self.cpp_nlist = hoomd.BinnedNeighborList(globals.particle_data, r_cut, default_r_buff)
			elif mode == "nsq":
				self.cpp_nlist = hoomd.NeighborList(globals.particle_data, r_cut, default_r_buff)
			else:
				print >> sys.stderr, "\n***Error! Invalid neighbor list mode\n";
				raise RuntimeError("Error creating neighbor list");
		elif globals.particle_data.getExecConf().exec_mode == hoomd.ExecutionConfiguration.executionMode.GPU:
			if mode == "binned":
				self.cpp_nlist = hoomd.BinnedNeighborListGPU(globals.particle_data, r_cut, default_r_buff)
{'fraction_non_alphanumeric': 0.09515007481735763, 'fraction_numerical': 0.0061614294516327784, 'mean_word_length': 3.8305697278911564, 'pattern_counts': {'":': 6, '<': 9, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '401865', 'n_tokens_mistral': 7486, 'n_tokens_neox': 6809, 'n_words': 2900}