PolymerSequence

class PolymerSequence(monomer_configurations, number_of_monomers=10, number_of_chains=1, tactic_ratio=None, monomer_ratios=None, monomer_additions=None, monomer_block_sizes=None, block_contamination=None, head_tail_flip_probability=None, alpha_group=None, omega_group=None, random_seed=None)

Calculate sequences of polymer monomers so that they can be used by the Monte Carlo polymer builder to create polymer melts. Different types of sequences can be generated depending on the type of polymer being studied.

Parameters:
  • monomer_configurations (list of type MoleculeConfiguration) – A list with each entry containing a MoleculeConfiguration containing a monomer to be used in the polymer sequence. The atoms on each end where the polymer connects should be labelled with the tags ‘HEAD_CONNECT’ and ‘TAIL_CONNECT’ respectively. The first atom of any groups to be removed to form the polymer should be labeled with the tags ‘HEAD_GROUP_A’ and TAIL_GROUP_A. These 4 tags are mandatory for each monomor. Optionally in the case of tactic monomers additional groups on each end should be labeled with the tags ‘HEAD_GROUP_B’ and ‘TAIL_GROUP_B’ respectively.

  • number_of_monomers (int) – The number of monomers to add into each polymer chain.

  • number_of_chains (int) – The number of chains to generate for the polymer melt

  • tactic_ratio (float) – Determines how biased the selection of monomers is towards the same (0) or alternating (1) monomer addition points, for monomers with two stereochemical substitution groups. These are isotactic and syndiotactic polymers respectively. Atactic random polymers are specified with 0.5, which shows no bias towards either addition point.
    Default: 0.5

  • monomer_ratios (1D list of floats) – A list of the relative amount of each monomer in the polymer system. This, along with monomer_additions, determines how likely each monomer is to be selected in the body of a polymer chain. These ratios alone also specify the probability of a chain being started with each monomer.
    Default: Each monomer is equally likely to be selected.

  • monomer_additions (2D list of floats) – A list of probabilities of adding each monomer onto an existing one. This can be used to make specific alternating structures. For each monomer the probability of adding any other monomer needs to be specified, so that an NxN array is required.
    Default: Each monomer has equal addition probability

  • monomer_block_sizes (1D list of integers) – A list of block sizes for each monomer. Specifying all block sizes as 1 results in a random polymer.
    Default: All the monomer block sizes are set to 1.

  • block_contamination (float) – A float that sets the probability of contamination by other monomers in a block polymer. 0 means each block is strictly created, 1 results in a random co-polymer.
    Default: 0

  • head_tail_flip_probability (float | None) – Probability that a monomer will be flipped so that it connects to join head to head and tail to tail. Monomer orientation is completely randomized by setting this to 0.5. Setting this this probability to 1 will flip all monomers, so that head to tail connections are preserved.
    Default: 0

  • alpha_group (MoleculeConfiguration | None) – Specifies the configuration to be used at the start of the chain building process. In this configuration the tags ‘HEAD_CONNECT’ and ‘TAIL_CONNECT’ can point to the same atom, although this is not necessary. As with monomers mandatory ‘HEAD_GROUP_A’ and ‘TAIL_GROUP_A’ as well as optional ‘HEAD_GROUP_B’ and ‘TAIL_GROUP_B’ can be added.

  • omega_group (MoleculeConfiguration | None) – Specifies the configuration to be used at the start of the chain building process. In this configuration the tags ‘HEAD_CONNECT’ and ‘TAIL_CONNECT’ can point to the same atom, although this is not necessary. As with monomers mandatory ‘HEAD_GROUP_A’ and ‘TAIL_GROUP_A’ as well as optional ‘HEAD_GROUP_B’ and ‘TAIL_GROUP_B’ can be added.

  • random_seed (int | None) – The seed for the random number generator. Must be a positive integer. This can be used so that the same sequence can be generated multiple times.
    Default: Arbitrary random seed

allMonomerConfigurations()
Returns:

The list of monomer configurations, including alpha and omega end groups.

Return type:

list of MoleculeConfigurations

alphaGroup()
Returns:

The configuration used for the alpha group, if set. Returns None if not.

Return type:

MoleculeConfiguration | None

alphaId()
Returns:

The integer ID of the alpha end group, if set. Returns None if not.

Return type:

int | None

blockContamination()
Returns:

The probability of block contamination in the sequence

Return type:

float

headTailFlipProbability()
Returns:

The probability of flipping a monomer so that it attaches head-head and tail-tail.

Return type:

float

monomer(index)

Returns a single monomer, by reference. The indexing also includes alpha/omega groups.

Parameters:

index (int) – The monomer configuration to be returned. The numbering starts from zero and goes through first monomers, then end groups, if defined.

Returns:

The monomer refered to by index.

Return type:

MoleculeConfiguration

monomerAdditions()
Returns:

The matrix of addition probabilites for the polymer sequence

Return type:

2D list of floats

monomerBlockSizes()
Returns:

The block sizes of each monomer in the polymer sequence

Return type:

list of int

monomerConfigurations()
Returns:

The list of monomer configurations, excluding end groups

Return type:

list of MoleculeConfiguration

monomerConnectionPoints(index)

Calculate the number of connection points that a monomer has, based on counting the number of group tags.

Parameters:

index (int) – The index of the monomer with the connections being counted. The index includes referencing the alpha/omega groups.

Returns:

The number of connection points.

Return type:

int

monomerFraction()

Return a list of the fraction of each monomer in the polymer sequence.

Returns:

List of the relative fraction of each monomer in the sequence

Return type:

1D numpy array of float

monomerRatios()
Returns:

The fraction of each monomer in the polymer sequence

Return type:

list of floats

numberOfChains()
Returns:

The number of chains in the polymer sequence

Return type:

int

numberOfMonomers()
Returns:

The number of monomers in each polymer chain

Return type:

int

numberOfSelectableMonomers()
Returns:

The number of monomers used in creating the polymer sequence, excluding the alpha and omega groups.

Return type:

int

numberOfUniqueMonomers()
Returns:

The number of unique monomer used in the polymer sequence, including the alpha and omega groups.

Return type:

int

omegaGroup()
Returns:

The configuration used for the omega group, if set. Returns None if not.

Return type:

MoleculeConfiguration | None

omegaId()
Returns:

The integer ID of the omega end group, if set. Returns None if not.

Return type:

int | None

randomSeed()
Returns:

The random seed used for the random number generator if set, else None.

Return type:

int | None

sequence()

Returns the generated polymer sequence. This is a list of 2D numpy integer arrays. Each element of the returned list is an ndarray defining a single polymer chain. The ndarray is of size Nx3, where N is the number of monomers. For each monomer in the ndarray the first index defines the identity of the monomer, the second defines the connection point and the third defines the monomer orientation.

Returns:

The integer sequence of monomers, tacticites and orientations.

Return type:

List of ndarray.

tacticRatio()
Returns:

The tactic ratio for the polymer chains

Return type:

float

uniqueString()

Return a unique string representing the state of the object.

Usage Examples

Define a monomer of methyl methacrylate, including the correct tags, and create a sequence for isotactic poly(methyl methacrylate)

# Define the methyl methacrylate monomer.
# First define elements.
elements = [Carbon, Carbon, Hydrogen, Hydrogen, Hydrogen, Carbon, Hydrogen,
            Hydrogen, Hydrogen, Carbon, Hydrogen, Hydrogen, Hydrogen, Carbon,
            Oxygen, Oxygen, Carbon, Hydrogen, Hydrogen, Hydrogen]

# Define coordinates
cartesian_coordinates = [[ 0.000053397617,  0.759772999835, -0.            ],
                         [-0.000053397617, -0.759772999835,  0.            ],
                         [-1.029486689503, -1.169152751252,  0.            ],
                         [ 0.514760310502, -1.169153624436, -0.89158       ],
                         [ 0.514760310502, -1.169153624436,  0.89158       ],
                         [-0.702972150254,  1.318819958684, -1.217534630654],
                         [-1.778994926992,  1.349871730145, -1.034368525823],
                         [-0.338426412209,  2.328764163503, -1.416490865706],
                         [-0.498848545074,  0.68155340126 , -2.080342189714],
                         [-0.702972150254,  1.318819958684,  1.217534630654],
                         [-1.779477850521,  1.34478390329 ,  1.036425819709],
                         [-0.494517798241,  0.684267886286,  2.08145298674 ],
                         [-0.34232383993 ,  2.330614899434,  1.413534093682],
                         [ 1.40596301868 ,  1.318867926842, -0.            ],
                         [ 1.84446749371 ,  2.344022687006, -0.473701649871],
                         [ 2.276658987984,  0.518045908871,  0.638886174971],
                         [ 3.418813357507,  0.987763274498,  0.630284279326],
                         [ 3.36418399788 ,  2.078158275911,  0.650119210394],
                         [ 3.96408273255 ,  0.634713205819,  1.508066389582],
                         [ 3.938029190653,  0.665721116071, -0.274655366275]]*Angstrom

# Set up configuration
methyl_methacrylate = MoleculeConfiguration(
    elements=elements,
    cartesian_coordinates=cartesian_coordinates
)

# Add tags
# Note that the tail groups are on the carbons of the methyl groups, not hydrogens.
methyl_methacrylate.addTags('HEAD_CONNECT', [1])
methyl_methacrylate.addTags('HEAD_GROUP_A', [4])
methyl_methacrylate.addTags('TAIL_CONNECT', [0])
methyl_methacrylate.addTags('TAIL_GROUP_A', [5])
methyl_methacrylate.addTags('TAIL_GROUP_B', [9])

# Add bonds
bonds = [[ 0,  1],
         [ 0,  5],
         [ 0,  9],
         [ 0, 13],
         [ 1,  2],
         [ 1,  3],
         [ 1,  4],
         [ 5,  6],
         [ 5,  7],
         [ 5,  8],
         [ 9, 10],
         [ 9, 11],
         [ 9, 12],
         [13, 14],
         [13, 15],
         [15, 16],
         [16, 17],
         [16, 18],
         [16, 19]]
methyl_methacrylate.setBonds(bonds)

# Create the sequence with a tactic ratio of 0, giving an isotactic sequence.
sequence = PolymerSequence(
    [methyl_methacrylate],
    number_of_monomers=40,
    number_of_chains=20,
    tactic_ratio=0,
)

tactic_polymer.py

Define a phenyl endgroup and create a random copolymer of 25% styrene and 75% vinyl chloride, capped with a phenyl endgroup.

# Load the monomers into memory
styrene = nlread('Styrene.hdf5', class_type=MoleculeConfiguration)[-1]
vinyl_chloride = nlread('Vinyl_Chloride.hdf5', class_type=MoleculeConfiguration)[-1]

# Define a phenyl endgroup
# Define elements
elements = [Carbon, Carbon, Carbon, Carbon, Carbon, Carbon, Hydrogen, Hydrogen,
            Hydrogen, Hydrogen, Hydrogen, Hydrogen]

# Define coordinates
cartesian_coordinates = [[ 0.            , -0.000000000011, -1.399795      ],
                         [ 0.            ,  1.212252999995, -0.699760000009],
                         [ 0.            ,  1.212253000005,  0.699759999991],
                         [ 0.            ,  0.000000000011,  1.399795      ],
                         [-0.            , -1.212252999995,  0.699760000009],
                         [-0.            , -1.212253000005, -0.699759999991],
                         [ 0.            , -0.000000000019, -2.500678      ],
                         [ 0.            ,  2.165670999991, -1.250363000016],
                         [ 0.            ,  2.165671000009,  1.250362999984],
                         [ 0.            ,  0.000000000019,  2.500678      ],
                         [-0.            , -2.165670999991,  1.250363000016],
                         [-0.            , -2.165671000009, -1.250362999984]]*Angstrom

# Set up configuration
phenyl = MoleculeConfiguration(
    elements=elements,
    cartesian_coordinates=cartesian_coordinates
)

# Add tags
phenyl.addTags('HEAD_CONNECT', [2])
phenyl.addTags('HEAD_GROUP_A', [8])
phenyl.addTags('TAIL_CONNECT', [2])
phenyl.addTags('TAIL_GROUP_A', [8])

# Add bonds
bonds = [[ 0,  1],
         [ 0,  5],
         [ 0,  6],
         [ 1,  2],
         [ 1,  7],
         [ 2,  3],
         [ 2,  8],
         [ 3,  4],
         [ 3,  9],
         [ 4,  5],
         [ 4, 10],
         [ 5, 11]]
phenyl.setBonds(bonds)

# Create the sequence made of 25% styrene and 75% vinyl chloride monomers randomly
# arranged.  Also cap the polymer with the phenyl group.
sequence = PolymerSequence(
    [styrene, vinyl_chloride],
    number_of_monomers=40,
    number_of_chains=20,
    monomer_ratios=[0.25, 0.75],
    omega_group=phenyl,
)

random_copolymer.py

Load two MoleculeConfiguration containing the monomers for the condensation polymer PET and create an alternating polymer from these monomers

# Load the monomers into memory
ethylenediamine = nlread('Ethylene_Glycol.hdf5', class_type=MoleculeConfiguration)[-1]
terephthalic_acid = nlread('Terephthalic_Acid.hdf5', class_type=MoleculeConfiguration)[-1]

# Create the polymer sequence with alternating monomers
# This is done by setting the diagonal elements of monomer_additions to zero,
# and the off-diagonal elements to 1.
sequence = PolymerSequence(
    [ethylenediamine, terephthalic_acid],
    number_of_monomers=40,
    number_of_chains=20,
    monomer_additions=[[0, 1], [1, 0]]
)

condensation_polymer.py Ethylene_Glycol.hdf5 Terephthalic_Acid.hdf5

Load two MoleculeConfiguration containing the monomers methyl acrylate and propylene and create diblock copolymer from these monomers.

# Load the monomers into memory
methyl_acrylate = nlread('Methyl_Acrylate.hdf5', class_type=MoleculeConfiguration)[-1]
propylene = nlread('Propylene.hdf5', class_type=MoleculeConfiguration)[-1]

# Create the polymer sequence with two polymer blocks
# This is done by setting the monomer_additions to enforce two different blocks.
# To make an A-B block copolymer the sum of the block sizes need to be as long as
# the polymer chain
sequence = PolymerSequence(
    [methyl_acrylate, propylene],
    number_of_monomers=40,
    number_of_chains=20,
    monomer_additions=[[0, 1], [1, 0]],
    monomer_block_sizes=[10, 30],
)

block_copolymer.py Methyl_Acrylate.hdf5 Propylene.hdf5

Notes

The PolymerSequence object creates properly randomized sequences of monomers from which polymer melts can be created. The different options control how the monomers are selected for the sequence and determine the types of polymers that can be created.

Specific tags must be placed on the monomers, so that builders such as the PolymerMonteCarloBuilder can determine how different monomers are to be connected. To mark the atoms that form part of the backbone of the polymer chain, the tags HEAD_CONNECT and TAIL_CONNECT are used. In constructing the polymer chain a bond is created between the TAIL_CONNECT atom of one monomer and the HEAD_CONNECT atom of the next monomer. In order to make room for this bond one of the groups connected to each atom must be removed. These groups are specified by placing the tag HEAD_GROUP_A on the atom in the group that is bonded to the HEAD_CONNECT atom, with the same pattern being repeated for the monomer tail. In cases where the polymer chain has atoms with two different side groups, such as in vinyl polymers, removing a group to add the chain creates a stereochemical center. In this case specifying only one group for removal means that only one stereochemistry will be present in the polymer. To have different stereochemistries a second removal group can be specified using the HEAD_GROUP_B or TAIL_GROUP_B tags. The group that is removed to form the polymer will then be selected based on the tactic_ratio parameter.

The following image shows an example of how the tags can be set for the monomer used to make the polymer poly(methyl methacrylate). Note that as monomers are entered in a chemically saturated state, the double bond in methyl methacrylate has been replaced with a hydrogen and methyl group on the HEAD and TAIL ends of the monomer respectively. Removing these groups to form the polymer chain approximates chemical addition to the double bond. Also note that as the HEAD atom contains two identical hydrogens, only one removal group is specified. Conversely on the TAIL atom two different functional groups are present, and so two different methyl groups are tagged for possible removal to create different stereochemistries.

../../../_images/methyl_methacrylate_tags.png

Specifying removal groups works similarly for condensation polymers, where the polymerization takes place by removing small molecules, such as water. Here the atoms in each monomer that form the leaving molecule can be specified by placing a HEAD/TAIL_GROUP_A/B tag on the atom that connects to the HEAD/TAIL_CONNECT backbone atom. For instance, in the above condensation polymer example where PET is formed, the hydroxyl oxygen is tagged as the ‘HEAD/TAIL_GROUP_A’ on the terephthalic acid. Likewise an amine hydrogen is tagged as the ‘HEAD/TAIL_GROUP_A’ on the ethylenediamine. When the ‘HEAD_CONNECT’ and ‘TAIL_CONNECT’ atoms on each monomer are connected the hydroxyl group from the terephthalic acid and the hydrogen from the ethylenediamine are removed, resulting in the two monomers forming an amide group. The removed atoms can form a water molecule.

The monomers used for the alpha and omega end groups follow a slightly different scheme. Here, as each monomer may only have one atom which is bonded to cap the polymer chain, the HEAD and TAIL atoms may be the same. If this is the case then the same monomer may be used either as a starting or ending group.

The above examples show how some common types of polymers may be created. Tacticity is controlled globally through the tactic_ratio parameter. The general proportion of each monomer in the resulting system is specified with the monomer_ratios parameter. This is useful for creating random copolymers with different ratios of monomers. It also controls the probability of selecting different monomers to start the polymer chain. The parameter monomer_additions controls the probability of adding one monomer onto another. Each row in this matrix corresponds to a monomer type and describes the probabilities of adding the next monomer type. This is useful for creating alternating copolymers and some types of block copolymers, especially diblock copolymers. This is also often necessary in creating condensation polymers such as PET or nylon, where two different monomers react to form the polymer chain. In general the probability of adding a monomer either outside or at the start of a block is the product of the monomer ratio and monomer addition probability for that monomer.

Monomer blocks within polymers can be created using the monomer_block_sizes parameter, which specifies how large blocks should be for each monomer. It is also possible to contaminate blocks through the block_contamination parameter. For each monomer in a block the probability of that monomer being different from the others is given by this parameter. Which monomer to contaminate the block with is controlled by the monomer_ratios and monomer_additions parameters.

The orientation of monomers being added to the polymer chain can also be controlled with the parameter head_tail_flip_probability. By default, polymer chains are created by connecting the head group of the incoming monomer to the tail group of the previous one. The head_tail_flip_probability controls the probability that an incoming monomer is re-orientated so that the the tail group is connected to the tail group of the previous monomer, allowing the next monomer to connect to the head group of the existing monomer. Complete randomization of the monomer orientation is achieved by setting head_tail_flip_probability to 0.5. Setting this parameter to 0 maintains the same orientation for all monomers, while setting it to 1 maintains the same reversed orientation for all monomers.

The alpha_group and omega_group parameters are designed to allow specific end groups to be placed on polymer chains. These groups may be the result of how polymers are synthesized, or as the result of a post-synthetic functionalization step. The molecules used as end groups attach onto the polymer chain, and only need one connection point. This allows for the HEAD and TAIL tags to be placed on the same atoms.

Once the PolymerSequence object is created it internally creates a polymer sequence. This is returned with the sequence function. The generated polymer sequence is stored as a list of two dimensional integer numpy arrays. Each array in the list describes one chain in the polymer melt. In the numpy arrays the first dimension indexes each monomer position in the chain. The second dimension has two elements. The first element contains the integer index of the monomer at that position in the chain (including the alpha and omega end groups), which is ordered according to the input order of the monomers. The second element is a number indicating which groups need to be removed to form the polymer chain. Selecting either HEAD_GROUP_A or HEAD_GROUP_B adds either 0 or 2 respectively onto this number. Likewise selecting either TAIL_GROUP_A or TAIL_GROUP_B adds either 0 or 1 respectively to this number. In this way the combination of groups selected is stored in a two digit binary fashion.