[lammps-users] Generating Random number at specified interval.

Hi all,

Is it possible to hold the value of a random number as constant for a fixed time interval instead of changing after each timestep in lammps(10Mar2021)?

with regards,

Diljith

Try using fix ave/time on an equal style variable. If you set nrepeat to 1 the fix becomes effectively a cache for instantaneous data.

Thank you Axel.

Not working, I am using the following lines,

variable friction equal normal(10,1,12345)

fix hold_friction all ave/time 1 1 1000 v_friction

fix print_friction all print 100 “${friction}”

The variable friction is changing at each time step.

Try adding:

variable friction_held equal f_hold_friction

and then printing the instantaneous values of friction_held.

As per the documentation, fix ave/time creates a new output value (in this case scalar) which you must access separately through a new equal-style variable. LAMMPS fixes in general do not modify variables passed to them, “reference” style, unless they are internal-style variables.

Cheers
Shern

Dear Shern,

I tried your suggestion
variable friction equal normal(10,1,12345)

fix hold_friction all ave/time 1 1 1000 v_friction

variable friction_held equal f_hold_friction

fix print_friction all print 100 “${friction_held}”

The above gave me an error.
ERROR: Variable friction_held: Fix in variable not computed at a compatible time (src/src/variable.cpp:1661)

Regards,
Diljith

well, you cannot access the data from fix ave/time until it has at least acquired one sample (which will be at step 1000). you are trying to read it at step 100.
try adding short “dummy” MD run (possibly without time integration so particles won’t move) to “prime” the fix.

Thanks Axel. I will try that.

Dear Axel,

I tried your suggestion. I am still getting the same error. I have attached my code.

Regards,

DIljith

hmm… the data is accessible in between runs.
this works for me:

variable friction equal normal(10,1,12345)
fix 0 all ave/time 1 1 100 v_friction
variable friction_hold equal f_0

run 110 post no
print "${friction_hold}"
run 30 pre no post no
print "${friction_hold}"
run 30 pre no post no
print "${friction_hold}"
run 30 pre no post no
print "${friction_hold}"
run 30 pre no post no
print "${friction_hold}"

output of the print commands is 3x one value and 2x another value.

Hi Axel and Diljith,

I can confirm that (1) print “${friction_hold}” works, (2) just about any other output mechanism doesn’t (e.g. fix print, thermo_modify custom, etc) – maybe the test in src/variable.cpp:1681 is too restrictive for this case?

What can be done is to use a fix vector to accumulate values of the random variable and then use an equal-style variable to “point” to the same index for N steps, giving the desired result. This will eat a bit of memory for allocating the fix vector, but it should be alright for reasonable-sized runs. MWE attached below – note that fix vector has to fire off every step on which output is requested, not every N steps, or else it runs into the same issue as the fix ave/time method.

Diljith – you also have an error in the following line:

variable trelax equal 50/${friction_held}

which should be v_friction_held in the denominator instead. What you have written will give a trelax value that is constant for the entire run, instead of changing every N steps like you want. See the documentation on LAMMPS script parsing rules for the meaning of ${}.

MWE for fix vector method (also look at the difference between v0 and v1):

region box block 0 10 0 10 0 10
create_box 1 box

mass 1 1

variable friction equal normal(10,1,12345)
variable nvect equal 1 # 20 seems to also work, but not 100

fix 1 all vector 1 v_friction
variable nstep equal 100
variable index equal floor(step/v_nstep)+1
variable friction_hold equal f_1[v_index]

run 100 # need pre-run because on step 0 f_1 has no entries

variable v0 equal 50/${friction_hold}
variable v1 equal 50/v_friction_hold
thermo 20
thermo_style custom step v_friction v_friction_hold v_v0 v_v1
run 200

MWE for fix ave/time errors:

region box block 0 10 0 10 0 10
create_box 1 box
mass 1 1

variable friction equal normal(10,1,12345)
fix 0 all ave/time 1 100 100 v_friction

variable friction_hold equal f_0

thermo 20
run 100
fix p all print 20 "${friction} ${friction_hold}" screen yesthermo_style custom v_friction v_friction_hold
run 80 # pre no <- will allow script to run, but doesn't initialize fix p

Outlook-whkz0cf0.png

Which means that the whole exercise with fix ave/time was not needed. With a loop the variable can return a different random number every time.

Outlook-whkz0cf0.png

Outlook-whkz0cf0.png

Outlook-whkz0cf0.png

For that matter, the documentation does not say that fix langevin will accept an equal-style variable defined with “v_” for the damp input – and looking at the source code, it definitely won’t. What LAMMPS will do with your script is run a long run using whatever value the variable had at the start of the run as a constant damping factor. (As per documentation this is the expected behaviour using “${}”.) To do what you are trying to do, you will have to use some sort of loop.

Cheers,
Shern

Outlook-whkz0cf0.png

Outlook-whkz0cf0.png

Dear Shern and Axel,

Thank you for your valuable feedback.

Regards,
Diljith