diff -Naur lammps-12Jan09/doc/fix_rigid.html lammps-13Jan09/doc/fix_rigid.html --- lammps-12Jan09/doc/fix_rigid.html 2008-10-08 09:02:35.000000000 -0600 +++ lammps-13Jan09/doc/fix_rigid.html 2009-01-13 07:38:26.000000000 -0700 @@ -13,25 +13,41 @@

Syntax:

-
fix ID group-ID rigid keyword values 
+
fix ID group-ID rigid bodystyle args keyword values ... 
 

Examples:

fix 1 clump rigid single
+fix 1 clump rigid single force 1 off off on
 fix 1 polychains rigid molecule
-fix 2 fluid rigid group clump1 clump2 clump3 
+fix 1 polychains rigid molecule force 1*5 off off off force 6*10 off off on
+fix 2 fluid rigid group 3 clump1 clump2 clump3
+fix 2 fluid rigid group 3 clump1 clump2 clump3 torque * off off off 
 

Description:

@@ -46,20 +62,44 @@ a constant-energy time integration, so you should not update the same atoms via other fixes (e.g. nve, nvt, npt).

-

Each body must have two or more atoms. Which atoms are in which -bodies can be defined via several options. +

Each body must have two or more atoms. An atom can belong to at most +one rigid body. Which atoms are in which bodies can be defined via +several options.

-

For option single the entire group of atoms is treated as one rigid -body. +

For bodystyle single the entire fix group of atoms is treated as one +rigid body.

-

For option molecule, each set of atoms in the group with a different -molecule ID is treated as a rigid body. +

For bodystyle molecule, each set of atoms in the fix group with a +different molecule ID is treated as a rigid body.

-

For option group, each of the listed groups is treated as a separate -rigid body. Note that only atoms that are also in the fix group are +

For bodystyle group, each of the listed groups is treated as a +separate rigid body. Only atoms that are also in the fix group are included in each rigid body.

-

For computational efficiency, you should also turn off pairwise and +

By default, each rigid body is acted on by other atoms which induce a +force and torque on its center of mass, causing it to translate and +rotate. Components of the center-of-mass force and torque can be +turned off by the force and torque keywords. This may be useful +if you wish a body to rotate but not translate, or vice versa. Note +that if you expect a rigid body not to move or rotate by using these +keywords, you must insure its initial center-of-mass translational or +angular velocity is 0.0. +

+

An xflag, yflag, or zflag set to off means turn off the component of +force of torque in that dimension. A setting of on means turn on +the component, which is the default. Which rigid body(s) the settings +apply to is determined by the first argument of the force and +torque keywords. It can be an integer M from 1 to Nbody, where +Nbody is the number of rigid bodies defined. A wild-card asterisk can +be used in place of, or in conjunction with, the M argument to set the +flags for multiple rigid bodies. This takes the form "*" or "*n" or +"n*" or "m*n". If N = the number of rigid bodies, then an asterisk +with no numeric values means all bodies from 1 to N. A leading +asterisk means all bodies from 1 to n (inclusive). A trailing +asterisk means all bodies from n to N (inclusive). A middle asterisk +means all types from m to n (inclusive). +

+

For computational efficiency, you may wish to turn off pairwise and bond interactions within each rigid body, as they no longer contribute to the motion. The neigh_modify exclude and delete_bonds commands are used to do this. @@ -83,7 +123,13 @@ compute_modify command. E.g. for a simulation of 10 such rigid bodies, use "compute_modify thermo_temp extra 13", after the thermo_style command, where 3 is the default setting and an -additional 10 degrees-of-freedom are subtracted. +additional 10 degrees-of-freedom are subtracted. You may also wish to +manually subtract additional degrees-of-freedom if you use the force +and torque keywords to eliminate certain motions of the rigid body. +Alternatively, you can define the temperature compute +to exclude atoms in rigid bodies, which may be a better strategy, +i.e. measure the temperature of the free atoms around the rigid body +or bodies.

IMPORTANT NOTE: The periodic image flags of atoms in rigid bodies are modified when the center-of-mass of the rigid body moves across a @@ -103,11 +149,32 @@

No information about this fix is written to binary restart files. None of the fix_modify options -are relevant to this fix. No global scalar or vector or per-atom -quantities are stored by this fix for access by various output -commands. No parameter of this fix can be -used with the start/stop keywords of the run command. -This fix is not invoked during energy minimization. +are relevant to this fix. +

+

This fix computes a global vector of quantities which can be accessed +by various output commands. For each rigid +body, 12 values are stored: the xyz coords of the center of mass +(COM), the xyz components of the COM velocity, the xyz components of +the force acting on the COM, and the xyz components of the torque +acting on the COM. The force and torque values in the vector are not +affected by the force and torque keywords in the fix rigid +command; they reflect values before any changes are made by those +keywords. +

+

The total length of the vector is 12*Nbody where Nbody is the number +of rigid bodies defined by the fix. Thus the 15th value in the vector +would be the z-coord of the COM of the 2nd rigid body. LAMMPS chooses +the ordering of the rigid bodies internally. The ordering of the +rigid bodies is as follows. For the single keyword there is just +one rigid body. For the molecule keyword, the bodies are ordered by +ascending molecule ID. For the group keyword, the list of group IDs +determines the ordering of bodies. The vector values calculated by +this fix are "intensive", meaning they are independent of the number +of atoms in the simulation. +

+

No parameter of this fix can be used with the start/stop keywords of +the run command. This fix is not invoked during energy +minimization.

Restrictions:

@@ -124,13 +191,17 @@ stationary. A better way to do this is to not include those atoms in your time integration fix. E.g. use "fix 1 mobile nve" instead of "fix 1 all nve", where "mobile" is the group of atoms that you want to -move. +move. Alternatively, you can also set the force on those atoms to 0.0 +via the fix setforce command.

Related commands:

delete_bonds, neigh_modify exclude

-

Default: none +

Default: +

+

The option defaults are force * 1 1 1 and torque * 1 1 1, meaning +all rigid bodies are acted on by center-of-mass force and torque.

diff -Naur lammps-12Jan09/doc/fix_rigid.txt lammps-13Jan09/doc/fix_rigid.txt --- lammps-12Jan09/doc/fix_rigid.txt 2008-10-08 09:02:35.000000000 -0600 +++ lammps-13Jan09/doc/fix_rigid.txt 2009-01-13 07:38:26.000000000 -0700 @@ -10,21 +10,35 @@ [Syntax:] -fix ID group-ID rigid keyword values :pre +fix ID group-ID rigid bodystyle args keyword values ... :pre ID, group-ID are documented in "fix"_fix.html command :ulb,l rigid = style name of this fix command :l -keyword = {single} or {molecule} or {group} :l - {single} values = none - {molecule} values = none - {group} values = list of group IDs :pre +bodystyle = {single} or {molecule} or {group} :l + {single} args = none + {molecule} args = none + {group} args = N groupID1 groupID2 ... + N = # of groups + groupID1, groupID2, ... = list of N group IDs :pre + +zero or more keyword/value pairs may be appended :l +keyword = {force} or {torque} :l + {force} values = M xflag yflag zflag + M = which rigid body from 1-Nbody (see asterisk form below) + xflag,yflag,zflag = off/on if component of center-of-mass force is active + {torque} values = M xflag yflag zflag + M = which rigid body from 1-Nbody (see asterisk form below) + xflag,yflag,zflag = off/on if component of center-of-mass torque is active :pre :ule [Examples:] fix 1 clump rigid single +fix 1 clump rigid single force 1 off off on fix 1 polychains rigid molecule -fix 2 fluid rigid group clump1 clump2 clump3 :pre +fix 1 polychains rigid molecule force 1*5 off off off force 6*10 off off on +fix 2 fluid rigid group 3 clump1 clump2 clump3 +fix 2 fluid rigid group 3 clump1 clump2 clump3 torque * off off off :pre [Description:] @@ -39,20 +53,44 @@ a constant-energy time integration, so you should not update the same atoms via other fixes (e.g. nve, nvt, npt). -Each body must have two or more atoms. Which atoms are in which -bodies can be defined via several options. +Each body must have two or more atoms. An atom can belong to at most +one rigid body. Which atoms are in which bodies can be defined via +several options. -For option {single} the entire group of atoms is treated as one rigid -body. +For bodystyle {single} the entire fix group of atoms is treated as one +rigid body. -For option {molecule}, each set of atoms in the group with a different -molecule ID is treated as a rigid body. +For bodystyle {molecule}, each set of atoms in the fix group with a +different molecule ID is treated as a rigid body. -For option {group}, each of the listed groups is treated as a separate -rigid body. Note that only atoms that are also in the fix group are +For bodystyle {group}, each of the listed groups is treated as a +separate rigid body. Only atoms that are also in the fix group are included in each rigid body. -For computational efficiency, you should also turn off pairwise and +By default, each rigid body is acted on by other atoms which induce a +force and torque on its center of mass, causing it to translate and +rotate. Components of the center-of-mass force and torque can be +turned off by the {force} and {torque} keywords. This may be useful +if you wish a body to rotate but not translate, or vice versa. Note +that if you expect a rigid body not to move or rotate by using these +keywords, you must insure its initial center-of-mass translational or +angular velocity is 0.0. + +An xflag, yflag, or zflag set to {off} means turn off the component of +force of torque in that dimension. A setting of {on} means turn on +the component, which is the default. Which rigid body(s) the settings +apply to is determined by the first argument of the {force} and +{torque} keywords. It can be an integer M from 1 to Nbody, where +Nbody is the number of rigid bodies defined. A wild-card asterisk can +be used in place of, or in conjunction with, the M argument to set the +flags for multiple rigid bodies. This takes the form "*" or "*n" or +"n*" or "m*n". If N = the number of rigid bodies, then an asterisk +with no numeric values means all bodies from 1 to N. A leading +asterisk means all bodies from 1 to n (inclusive). A trailing +asterisk means all bodies from n to N (inclusive). A middle asterisk +means all types from m to n (inclusive). + +For computational efficiency, you may wish to turn off pairwise and bond interactions within each rigid body, as they no longer contribute to the motion. The "neigh_modify exclude"_neigh_modify.html and "delete_bonds"_delete_bonds.html commands are used to do this. @@ -76,7 +114,13 @@ "compute_modify"_compute_modify.html command. E.g. for a simulation of 10 such rigid bodies, use "compute_modify thermo_temp extra 13", after the thermo_style command, where 3 is the default setting and an -additional 10 degrees-of-freedom are subtracted. +additional 10 degrees-of-freedom are subtracted. You may also wish to +manually subtract additional degrees-of-freedom if you use the {force} +and {torque} keywords to eliminate certain motions of the rigid body. +Alternatively, you can define the temperature "compute"_compute.html +to exclude atoms in rigid bodies, which may be a better strategy, +i.e. measure the temperature of the free atoms around the rigid body +or bodies. IMPORTANT NOTE: The periodic image flags of atoms in rigid bodies are modified when the center-of-mass of the rigid body moves across a @@ -96,11 +140,32 @@ No information about this fix is written to "binary restart files"_restart.html. None of the "fix_modify"_fix_modify.html options -are relevant to this fix. No global scalar or vector or per-atom -quantities are stored by this fix for access by various "output -commands"_Section_howto.html#4_15. No parameter of this fix can be -used with the {start/stop} keywords of the "run"_run.html command. -This fix is not invoked during "energy minimization"_minimize.html. +are relevant to this fix. + +This fix computes a global vector of quantities which can be accessed +by various "output commands"_Section_howto.html#4_15. For each rigid +body, 12 values are stored: the xyz coords of the center of mass +(COM), the xyz components of the COM velocity, the xyz components of +the force acting on the COM, and the xyz components of the torque +acting on the COM. The force and torque values in the vector are not +affected by the {force} and {torque} keywords in the fix rigid +command; they reflect values before any changes are made by those +keywords. + +The total length of the vector is 12*Nbody where Nbody is the number +of rigid bodies defined by the fix. Thus the 15th value in the vector +would be the z-coord of the COM of the 2nd rigid body. LAMMPS chooses +the ordering of the rigid bodies internally. The ordering of the +rigid bodies is as follows. For the {single} keyword there is just +one rigid body. For the {molecule} keyword, the bodies are ordered by +ascending molecule ID. For the {group} keyword, the list of group IDs +determines the ordering of bodies. The vector values calculated by +this fix are "intensive", meaning they are independent of the number +of atoms in the simulation. + +No parameter of this fix can be used with the {start/stop} keywords of +the "run"_run.html command. This fix is not invoked during "energy +minimization"_minimize.html. [Restrictions:] @@ -117,11 +182,16 @@ stationary. A better way to do this is to not include those atoms in your time integration fix. E.g. use "fix 1 mobile nve" instead of "fix 1 all nve", where "mobile" is the group of atoms that you want to -move. +move. Alternatively, you can also set the force on those atoms to 0.0 +via the "fix setforce"_fix_setforce.html command. [Related commands:] "delete_bonds"_delete_bonds.html, "neigh_modify"_neigh_modify.html exclude -[Default:] none +[Default:] + +The option defaults are force * 1 1 1 and torque * 1 1 1, meaning +all rigid bodies are acted on by center-of-mass force and torque. + diff -Naur lammps-12Jan09/doc/units.html lammps-13Jan09/doc/units.html --- lammps-12Jan09/doc/units.html 2008-08-05 17:58:09.000000000 -0600 +++ lammps-13Jan09/doc/units.html 2009-01-13 07:38:26.000000000 -0700 @@ -49,6 +49,7 @@
  • energy = epsilon, where E* = E / epsilon
  • velocity = sigma/tau, where v* = v tau / sigma
  • force = epsilon/sigma, where f* = f sigma / epsilon +
  • torque = epsilon, where t* = t / epsilon
  • temperature = reduced LJ temperature, where T* = T Kb / epsilon
  • pressure = reduced LJ pressure, where P* = P sigma^3 / epsilon
  • viscosity = reduced LJ viscosity, where eta* = eta sigma^3 / epsilon / tau @@ -64,6 +65,7 @@
  • energy = Kcal/mole
  • velocity = Angstroms/femtosecond
  • force = Kcal/mole-Angstrom +
  • torque = Kcal/mole
  • temperature = degrees K
  • pressure = atmospheres
  • viscosity = Poise @@ -79,6 +81,7 @@
  • energy = eV
  • velocity = Angstroms/picosecond
  • force = eV/Angstrom +
  • torque = eV
  • temperature = degrees K
  • pressure = bars
  • viscosity = Poise @@ -94,6 +97,7 @@
  • energy = Joules
  • velocity = meters/second
  • force = Newtons +
  • torque = Newton-meters
  • temperature = degrees K
  • pressure = Pascals
  • viscosity = Pascal*second @@ -107,8 +111,9 @@
  • distance = centimeters
  • time = seconds
  • energy = ergs -
  • velocity = cm/second +
  • velocity = centimeters/second
  • force = dynes +
  • torque = dyne-centimeters
  • temperature = degrees K
  • pressure = dyne/cm^2 or barye = 1.0e-6 bars
  • viscosity = Poise diff -Naur lammps-12Jan09/doc/units.txt lammps-13Jan09/doc/units.txt --- lammps-12Jan09/doc/units.txt 2008-08-05 17:58:09.000000000 -0600 +++ lammps-13Jan09/doc/units.txt 2009-01-13 07:38:26.000000000 -0700 @@ -46,6 +46,7 @@ energy = epsilon, where E* = E / epsilon velocity = sigma/tau, where v* = v tau / sigma force = epsilon/sigma, where f* = f sigma / epsilon +torque = epsilon, where t* = t / epsilon temperature = reduced LJ temperature, where T* = T Kb / epsilon pressure = reduced LJ pressure, where P* = P sigma^3 / epsilon viscosity = reduced LJ viscosity, where eta* = eta sigma^3 / epsilon / tau @@ -61,6 +62,7 @@ energy = Kcal/mole velocity = Angstroms/femtosecond force = Kcal/mole-Angstrom +torque = Kcal/mole temperature = degrees K pressure = atmospheres viscosity = Poise @@ -76,6 +78,7 @@ energy = eV velocity = Angstroms/picosecond force = eV/Angstrom +torque = eV temperature = degrees K pressure = bars viscosity = Poise @@ -91,6 +94,7 @@ energy = Joules velocity = meters/second force = Newtons +torque = Newton-meters temperature = degrees K pressure = Pascals viscosity = Pascal*second @@ -104,8 +108,9 @@ distance = centimeters time = seconds energy = ergs -velocity = cm/second +velocity = centimeters/second force = dynes +torque = dyne-centimeters temperature = degrees K pressure = dyne/cm^2 or barye = 1.0e-6 bars viscosity = Poise diff -Naur lammps-12Jan09/potentials/Ag_u3.eam lammps-13Jan09/potentials/Ag_u3.eam --- lammps-12Jan09/potentials/Ag_u3.eam 2007-06-11 10:54:20.000000000 -0600 +++ lammps-13Jan09/potentials/Ag_u3.eam 2009-01-12 15:22:37.000000000 -0700 @@ -1,4 +1,4 @@ -Ag functions (universal 3) +Ag functions (universal 3), SM Foiles et al, PRB, 33, 7983 (1986) 47 107.87 4.0900 FCC 500 5.0100200400801306e-04 500 1.1212121212121229e-02 5.5500000000000114e+00 0. -5.3437496524125194e-01 -7.9903970176950523e-01 -1.0066582430185846e+00 -1.1839019175820411e+00 diff -Naur lammps-12Jan09/potentials/Au_u3.eam lammps-13Jan09/potentials/Au_u3.eam --- lammps-12Jan09/potentials/Au_u3.eam 2007-06-11 10:54:20.000000000 -0600 +++ lammps-13Jan09/potentials/Au_u3.eam 2009-01-12 15:22:37.000000000 -0700 @@ -1,4 +1,4 @@ -Au functions (universal 3) +Au functions (universal 3), SM Foiles et al, PRB, 33, 7983 (1986) 79 196.97 4.0800 FCC 500 5.0100200400801306e-04 500 1.1212121212121229e-02 5.5500000000000114e+00 0. -4.8957152905617285e-01 -7.9715640025473178e-01 -1.0578883960846852e+00 -1.2926127947875230e+00 diff -Naur lammps-12Jan09/potentials/Cu_u3.eam lammps-13Jan09/potentials/Cu_u3.eam --- lammps-12Jan09/potentials/Cu_u3.eam 2007-06-11 10:54:20.000000000 -0600 +++ lammps-13Jan09/potentials/Cu_u3.eam 2009-01-12 15:22:37.000000000 -0700 @@ -1,4 +1,4 @@ -Cu functions (universal 3) +Cu functions (universal 3), SM Foiles et al, PRB, 33, 7983 (1986) 29 63.550 3.6150 FCC 500 5.0100200400801306e-04 500 1.0000000000000009e-02 4.9499999999999886e+00 0. -3.1561636903424350e-01 -5.2324876182494506e-01 -6.9740831416804383e-01 -8.5202525457518519e-01 diff -Naur lammps-12Jan09/potentials/Ni_u3.eam lammps-13Jan09/potentials/Ni_u3.eam --- lammps-12Jan09/potentials/Ni_u3.eam 2007-06-11 10:54:20.000000000 -0600 +++ lammps-13Jan09/potentials/Ni_u3.eam 2009-01-12 15:22:37.000000000 -0700 @@ -1,4 +1,4 @@ -Ni function (universal 3) +Ni function (universal 3), SM Foiles et al, PRB, 33, 7983 (1986) 28 58.710 3.5200 FCC 500 5.0100200400801306e-04 500 9.6969696969697039e-03 4.8000000000000114e+00 0. -5.0517016048996766e-01 -7.9317853848267106e-01 -1.0217438587039425e+00 -1.2174805690269395e+00 diff -Naur lammps-12Jan09/potentials/Pd_u3.eam lammps-13Jan09/potentials/Pd_u3.eam --- lammps-12Jan09/potentials/Pd_u3.eam 2007-06-11 10:54:20.000000000 -0600 +++ lammps-13Jan09/potentials/Pd_u3.eam 2009-01-12 15:22:37.000000000 -0700 @@ -1,4 +1,4 @@ -Pd functions (universal 3) +Pd functions (universal 3), SM Foiles et al, PRB, 33, 7983 (1986) 46 106.40 3.8900 FCC 500 5.0100200400801306e-04 500 1.0707070707070721e-02 5.3000000000000114e+00 0. -3.1306711517055952e-01 -5.5466277050516410e-01 -7.7291856038441153e-01 -9.7731378837169558e-01 diff -Naur lammps-12Jan09/potentials/Pt_u3.eam lammps-13Jan09/potentials/Pt_u3.eam --- lammps-12Jan09/potentials/Pt_u3.eam 2007-06-11 10:54:20.000000000 -0600 +++ lammps-13Jan09/potentials/Pt_u3.eam 2009-01-12 15:22:37.000000000 -0700 @@ -1,4 +1,4 @@ -Pt functions (universal 3) +Pt functions (universal 3), SM Foiles et al, PRB, 33, 7983 (1986) 78 195.09 3.9200 FCC 500 5.0100200400801306e-04 500 1.0707070707070721e-02 5.3000000000000114e+00 0. -4.8256532387839535e-01 -8.2163069483085494e-01 -1.1184672638766031e+00 -1.3913023282712871e+00 diff -Naur lammps-12Jan09/src/fix_rigid.cpp lammps-13Jan09/src/fix_rigid.cpp --- lammps-12Jan09/src/fix_rigid.cpp 2008-12-03 15:18:28.000000000 -0700 +++ lammps-13Jan09/src/fix_rigid.cpp 2009-01-13 07:38:35.000000000 -0700 @@ -13,6 +13,7 @@ #include "math.h" #include "stdio.h" +#include "stdlib.h" #include "string.h" #include "fix_rigid.h" #include "atom.h" @@ -64,9 +65,10 @@ // nbody = 1 // all atoms in fix group are part of body - if (strcmp(arg[3],"single") == 0) { - if (narg != 4) error->all("Illegal fix rigid command"); + int iarg; + if (strcmp(arg[3],"single") == 0) { + iarg = 4; nbody = 1; int *mask = atom->mask; @@ -84,7 +86,7 @@ // use nall as incremented ptr to set body[] values for each atom } else if (strcmp(arg[3],"molecule") == 0) { - if (narg != 4) error->all("Illegal fix rigid command"); + iarg = 4; if (atom->molecular == 0) error->all("Must use a molecular atom style with fix rigid molecule"); @@ -128,12 +130,15 @@ // error if atom belongs to more than 1 rigid body } else if (strcmp(arg[3],"group") == 0) { - nbody = narg-4; + if (narg < 5) error->all("Illegal fix rigid command"); + nbody = atoi(arg[4]); if (nbody <= 0) error->all("Illegal fix rigid command"); + if (narg < 5+nbody) error->all("Illegal fix rigid command"); + iarg = 5 + nbody; int *igroups = new int[nbody]; for (ibody = 0; ibody < nbody; ibody++) { - igroups[ibody] = group->find(arg[ibody+4]); + igroups[ibody] = group->find(arg[5+ibody]); if (igroups[ibody] == -1) error->all("Could not find fix rigid group ID"); } @@ -182,11 +187,94 @@ torque = memory->create_2d_double_array(nbody,3,"rigid:torque"); quat = memory->create_2d_double_array(nbody,4,"rigid:quat"); image = (int *) memory->smalloc(nbody*sizeof(int),"rigid:image"); + fflag = memory->create_2d_double_array(nbody,3,"rigid:fflag"); + tflag = memory->create_2d_double_array(nbody,3,"rigid:tflag"); sum = memory->create_2d_double_array(nbody,6,"rigid:sum"); all = memory->create_2d_double_array(nbody,6,"rigid:all"); remapflag = memory->create_2d_int_array(nbody,4,"rigid:remapflag"); - + + // initialize force/torque flags to default = 1.0 + + vector_flag = 1; + size_vector = 12*nbody; + scalar_vector_freq = 1; + extvector = 0; + + for (i = 0; i < nbody; i++) { + fflag[i][0] = fflag[i][1] = fflag[i][2] = 1.0; + tflag[i][0] = tflag[i][1] = tflag[i][2] = 1.0; + } + + // parse optional args that set fflag and tflag + + while (iarg < narg) { + if (strcmp(arg[iarg],"force") == 0) { + if (iarg+5 > narg) error->all("Illegal fix rigid command"); + + int mlo,mhi; + force->bounds(arg[iarg+1],nbody,mlo,mhi); + + double xflag,yflag,zflag; + if (strcmp(arg[iarg+2],"off") == 0) xflag = 0.0; + else if (strcmp(arg[iarg+2],"on") == 0) xflag = 1.0; + else error->all("Ill3gal fix rigid command"); + if (strcmp(arg[iarg+2],"off") == 0) yflag = 0.0; + else if (strcmp(arg[iarg+3],"on") == 0) yflag = 1.0; + else error->all("Illegal fix rigid command"); + if (strcmp(arg[iarg+4],"off") == 0) zflag = 0.0; + else if (strcmp(arg[iarg+4],"on") == 0) zflag = 1.0; + else error->all("Illegal fix rigid command"); + + int count = 0; + for (int m = mlo; m <= mhi; i++) { + fflag[m-1][0] = xflag; + fflag[m-1][1] = yflag; + fflag[m-1][2] = zflag; + count++; + } + if (count == 0) error->all("Illegal fix rigid command"); + + iarg += 5; + } else if (strcmp(arg[iarg],"torque") == 0) { + if (iarg+5 > narg) error->all("Illegal fix rigid command"); + + int mlo,mhi; + force->bounds(arg[iarg+1],nbody,mlo,mhi); + + double xflag,yflag,zflag; + if (strcmp(arg[iarg+2],"off") == 0) xflag = 0.0; + else if (strcmp(arg[iarg+2],"on") == 0) xflag = 1.0; + else error->all("Ill3gal fix rigid command"); + if (strcmp(arg[iarg+3],"off") == 0) yflag = 0.0; + else if (strcmp(arg[iarg+3],"on") == 0) yflag = 1.0; + else error->all("Illegal fix rigid command"); + if (strcmp(arg[iarg+4],"off") == 0) zflag = 0.0; + else if (strcmp(arg[iarg+4],"on") == 0) zflag = 1.0; + else error->all("Illegal fix rigid command"); + + int count = 0; + for (int m = mlo; m <= mhi; m++) { + tflag[m-1][0] = xflag; + tflag[m-1][1] = yflag; + tflag[m-1][2] = zflag; + count++; + } + if (count == 0) error->all("Illegal fix rigid command"); + + iarg += 5; + } else error->all("Illegal fix rigid command"); + } + + // initialize vector output quantities in case accessed before run + + for (i = 0; i < nbody; i++) { + xcm[i][0] = xcm[i][1] = xcm[i][2] = 0.0; + vcm[i][0] = vcm[i][1] = vcm[i][2] = 0.0; + fcm[i][0] = fcm[i][1] = fcm[i][2] = 0.0; + torque[i][0] = torque[i][1] = torque[i][2] = 0.0; + } + // nrigid[n] = # of atoms in Nth rigid body // error if one or zero atoms @@ -251,6 +339,8 @@ memory->destroy_2d_double_array(torque); memory->destroy_2d_double_array(quat); memory->sfree(image); + memory->destroy_2d_double_array(fflag); + memory->destroy_2d_double_array(tflag); memory->destroy_2d_double_array(sum); memory->destroy_2d_double_array(all); @@ -677,8 +767,8 @@ // set velocities from angmom & omega for (ibody = 0; ibody < nbody; ibody++) - omega_from_mq(angmom[ibody],ex_space[ibody],ey_space[ibody], - ez_space[ibody],inertia[ibody],omega[ibody]); + omega_from_angmom(angmom[ibody],ex_space[ibody],ey_space[ibody], + ez_space[ibody],inertia[ibody],omega[ibody]); set_v(); // guestimate virial as 2x the set_v contribution @@ -703,9 +793,9 @@ // update vcm by 1/2 step dtfm = dtf / masstotal[ibody]; - vcm[ibody][0] += dtfm * fcm[ibody][0]; - vcm[ibody][1] += dtfm * fcm[ibody][1]; - vcm[ibody][2] += dtfm * fcm[ibody][2]; + vcm[ibody][0] += dtfm * fcm[ibody][0] * fflag[ibody][0]; + vcm[ibody][1] += dtfm * fcm[ibody][1] * fflag[ibody][1]; + vcm[ibody][2] += dtfm * fcm[ibody][2] * fflag[ibody][2]; // update xcm by full step @@ -715,9 +805,9 @@ // update angular momentum by 1/2 step - angmom[ibody][0] += dtf * torque[ibody][0]; - angmom[ibody][1] += dtf * torque[ibody][1]; - angmom[ibody][2] += dtf * torque[ibody][2]; + angmom[ibody][0] += dtf * torque[ibody][0] * tflag[ibody][0]; + angmom[ibody][1] += dtf * torque[ibody][1] * tflag[ibody][1]; + angmom[ibody][2] += dtf * torque[ibody][2] * tflag[ibody][2]; // update quaternion a full step // returns new normalized quat @@ -747,12 +837,12 @@ { // compute omega at 1/2 step from m at 1/2 step and q at 0 - omega_from_mq(m,ex,ey,ez,moments,w); + omega_from_angmom(m,ex,ey,ez,moments,w); // full update from dq/dt = 1/2 w q double wq[4]; - multiply(w,q,wq); + vecquat(w,q,wq); double qfull[4]; qfull[0] = q[0] + dtq * wq[0]; @@ -777,8 +867,8 @@ // recompute wq exyz_from_q(qhalf,ex,ey,ez); - omega_from_mq(m,ex,ey,ez,moments,w); - multiply(w,qhalf,wq); + omega_from_angmom(m,ex,ey,ez,moments,w); + vecquat(w,qhalf,wq); // 2nd half update from dq/dt = 1/2 w q @@ -873,23 +963,23 @@ // update vcm by 1/2 step dtfm = dtf / masstotal[ibody]; - vcm[ibody][0] += dtfm * fcm[ibody][0]; - vcm[ibody][1] += dtfm * fcm[ibody][1]; - vcm[ibody][2] += dtfm * fcm[ibody][2]; + vcm[ibody][0] += dtfm * fcm[ibody][0] * fflag[ibody][0]; + vcm[ibody][1] += dtfm * fcm[ibody][1] * fflag[ibody][1]; + vcm[ibody][2] += dtfm * fcm[ibody][2] * fflag[ibody][2]; // update angular momentum by 1/2 step - angmom[ibody][0] += dtf * torque[ibody][0]; - angmom[ibody][1] += dtf * torque[ibody][1]; - angmom[ibody][2] += dtf * torque[ibody][2]; + angmom[ibody][0] += dtf * torque[ibody][0] * tflag[ibody][0]; + angmom[ibody][1] += dtf * torque[ibody][1] * tflag[ibody][1]; + angmom[ibody][2] += dtf * torque[ibody][2] * tflag[ibody][2]; } // set velocities from angmom & omega // virial is already setup from initial_integrate for (ibody = 0; ibody < nbody; ibody++) - omega_from_mq(angmom[ibody],ex_space[ibody],ey_space[ibody], - ez_space[ibody],inertia[ibody],omega[ibody]); + omega_from_angmom(angmom[ibody],ex_space[ibody],ey_space[ibody], + ez_space[ibody],inertia[ibody],omega[ibody]); set_v(); } @@ -1129,7 +1219,7 @@ /* ---------------------------------------------------------------------- create quaternion from space-frame ex,ey,ez - ex,ey,ez are columns of evectors rotation matrix + ex,ey,ez are columns of a rotation matrix ------------------------------------------------------------------------- */ void FixRigid::q_from_exyz(double *ex, double *ey, double *ez, double *q) @@ -1192,10 +1282,10 @@ } /* ---------------------------------------------------------------------- - quaternion multiply: c = a*b where a = (0,a) + vector-quaternion multiply: c = a*b, where a = (0,a) ------------------------------------------------------------------------- */ -void FixRigid::multiply(double *a, double *b, double *c) +void FixRigid::vecquat(double *a, double *b, double *c) { c[0] = -(a[0]*b[1] + a[1]*b[2] + a[2]*b[3]); c[1] = b[0]*a[0] + a[1]*b[3] - a[2]*b[2]; @@ -1204,6 +1294,30 @@ } /* ---------------------------------------------------------------------- + quaternion-vector multiply: c = a*b, where b = (0,b) +------------------------------------------------------------------------- */ + +void FixRigid::quatvec(double *a, double *b, double *c) +{ + c[0] = - (a[1]*b[0] + a[2]*b[1] + a[3]*b[2]); + c[1] = a[0]*b[0] + a[2]*b[2] - a[3]*b[1]; + c[2] = a[0]*b[1] + a[3]*b[0] - a[1]*b[2]; + c[3] = a[0]*b[2] + a[1]*b[1] - a[2]*b[0]; +} + +/* ---------------------------------------------------------------------- + quaternion-quaternion multiply: c = a*b +------------------------------------------------------------------------- */ + +void FixRigid::quatquat(double *a, double *b, double *c) +{ + c[0] = a[0]*b[0] - (a[1]*b[1] + a[2]*b[2] + a[3]*b[3]); + c[1] = a[0]*b[1] + b[0]*a[1] + a[2]*b[3] - a[3]*b[2]; + c[2] = a[0]*b[2] + b[0]*a[2] + a[3]*b[1] - a[1]*b[3]; + c[3] = a[0]*b[3] + b[0]*a[3] + a[1]*b[2] - a[2]*b[1]; +} + +/* ---------------------------------------------------------------------- normalize a quaternion ------------------------------------------------------------------------- */ @@ -1217,17 +1331,18 @@ } /* ---------------------------------------------------------------------- - compute omega from angular momentum - w = omega = angular velocity in space frame - wbody = angular velocity in body frame + compute omega from angular momentum, both in space frame + only know Idiag so need to do M = Iw in body frame + ex,ey,ez are column vectors of rotation matrix P + Mbody = P_transpose Mspace + wbody = Mbody / Ibody + wspace = P wbody set wbody component to 0.0 if inertia component is 0.0 otherwise body can spin easily around that axis - project space-frame angular momentum onto body axes - and divide by principal moments ------------------------------------------------------------------------- */ -void FixRigid::omega_from_mq(double *m, double *ex, double *ey, double *ez, - double *inertia, double *w) +void FixRigid::omega_from_angmom(double *m, double *ex, double *ey, double *ez, + double *inertia, double *w) { double wbody[3]; @@ -1244,6 +1359,29 @@ } /* ---------------------------------------------------------------------- + compute angular momentum from omega, both in space frame + only know Idiag so need to do M = Iw in body frame + ex,ey,ez are column vectors of rotation matrix P + wbody = P_transpose wspace + Mbody = Ibody wbody + Mspace = P Mbody +------------------------------------------------------------------------- */ + +void FixRigid::angmom_from_omega(double *w, double *ex, double *ey, double *ez, + double *inertia, double *m) +{ + double mbody[3]; + + mbody[0] = (w[0]*ex[0] + w[1]*ex[1] + w[2]*ex[2]) * inertia[0]; + mbody[1] = (w[0]*ey[0] + w[1]*ey[1] + w[2]*ey[2]) * inertia[1]; + mbody[2] = (w[0]*ez[0] + w[1]*ez[1] + w[2]*ez[2]) * inertia[2]; + + m[0] = mbody[0]*ex[0] + mbody[1]*ey[0] + mbody[2]*ez[0]; + m[1] = mbody[0]*ex[1] + mbody[1]*ey[1] + mbody[2]*ez[1]; + m[2] = mbody[0]*ex[2] + mbody[1]*ey[2] + mbody[2]*ez[2]; +} + +/* ---------------------------------------------------------------------- set space-frame coords and velocity of each atom in each rigid body x = Q displace + Xcm, mapped back to periodic box v = Vcm + (W cross (x - Xcm)) @@ -1526,3 +1664,21 @@ dtf = 0.5 * update->dt * force->ftm2v; dtq = 0.5 * update->dt; } + +/* ---------------------------------------------------------------------- + return attributes of a rigid body + 12 values per body + xcm = 1,2,3; vcm = 4,5,6; fcm = 7,8,9; torque = 10,11,12 +------------------------------------------------------------------------- */ + +double FixRigid::compute_vector(int n) +{ + int ibody = n/12; + int iattribute = (n % 12) / 3; + int index = n % 3; + + if (iattribute == 0) return xcm[ibody][index]; + else if (iattribute == 1) return vcm[ibody][index]; + else if (iattribute == 2) return fcm[ibody][index]; + else return torque[ibody][index]; +} diff -Naur lammps-12Jan09/src/fix_rigid.h lammps-13Jan09/src/fix_rigid.h --- lammps-12Jan09/src/fix_rigid.h 2008-10-01 16:10:25.000000000 -0600 +++ lammps-13Jan09/src/fix_rigid.h 2009-01-13 07:38:35.000000000 -0700 @@ -40,6 +40,7 @@ int dof(int); void deform(int); void reset_dt(); + double compute_vector(int); private: double dtv,dtf,dtq; @@ -62,6 +63,8 @@ int *image; // image flags of xcm of each rigid body int *body; // which body each atom is part of (-1 if none) double **displace; // displacement of each atom in body coords + double **fflag; // flag for on/off of center-of-mass force + double **tflag; // flag for on/off of center-of-mass torque double **sum,**all; // work vectors for each rigid body int **remapflag; // PBC remap flags for each rigid body @@ -70,12 +73,16 @@ void rotate(double **, int, int, int, int, double, double); void q_from_exyz(double *, double *, double *, double *); void exyz_from_q(double *, double *, double *, double *); - void multiply(double *, double *, double *); + void vecquat(double *, double *, double *); + void quatvec(double *, double *, double *); + void quatquat(double *, double *, double *); void normalize(double *); void richardson(double *, double *, double *, double *, double *, double *, double *); - void omega_from_mq(double *, double *, double *, - double *, double *, double *); + void omega_from_angmom(double *, double *, double *, + double *, double *, double *); + void angmom_from_omega(double *, double *, double *, + double *, double *, double *); void set_xv(); void set_v(); };