I need to use lammps as a library when coupling it with my own C code.
I follow the example from couple/simple, and I need to change the positions of atoms in certain region every time step.
So I changed the file simple.c in couple/simple, and the loop is used as follows:
The problem is that the computational time when using this couple scheme is much longer than the case without coupling. Then I checked the log file and found that after every time step the information is written into log.lammps, and the output time took a large proportion of the whole computational time. so I use the command “log none” to stop the output to the file log.lammps, however the problem still existed (i.e. the computational time was still as long as the case when I didn’t use “log none” command).
Can someone tell me where the problem is and what I should do to reduce the computational time? Thanks a lot.
the problem is (as far as I understand it) that you do 100000 1 step runs. And every time the system setup is done in lammps (and that takes more time than just a simple time step forward).
In particular that means that the neighbor list is rebuild for each and every time step, bottom line: that takes probably anywhere from 5-50 times longer alone.
The next bad thing is that you reallocate your position array every timestep. Depending on your system and the cutoff that might bite another big chunk out of your performance - though I would guess the first problem is much worse.
What you could do (though I dont know exactly how to do that with the library) is to use a minimal setup for each run, with reneighboring only done every 10 timesteps or so.
The alternative is to write your own fix which does what your current C code does at every timestep. I think that option is actually not too hard. Especially since you only work with positions. Take a look at one of the more simple fixes to get a feeling for what to do (i.e. fix_enforce2d or so).
The way to do a "minimal" setup, whether from
an input script or thru the library interface, is
to use the "pre" and "post" options on the run command.
If all you run 1 commands (except the first and last)
are run 1 pre no post no, then you will run nearly
as fast as if you used run 1000000.
Thanks, Steve. Actually I need to add an additional force to every atom in the specified region before every “run”, and the force changes with time. So I used the code as follows:
for (int i=1; i<=100000; i++) {
char s[1024];
char s1[30];
strcpy(s,"fix 99 flow addforce “);
double d = ComputeExternalForce(); //this function calculated the additional force
sprintf(s1, “%lf”, d);
char *s2 = " 0.0 0.0 region 8”;
strcat(s,s1);
strcat(s,s2); // now the content of s is “fix 99 flow addforce force 0.0 0.0 region 8”
lammps_command(ptr,s);
lammps_command(ptr,“run 1”);
lammps_command(ptr,“unfix 99”);
}
However, the manual says: If your input script changes settings between 2 runs (e.g. adds a fix or dump or compute or changes a neighbor list parameter), then the initial setup must be performed. LAMMPS does not check for this, but it would be an error to use the pre no option in this case.
It seems in this case I cannot use pre no command since I have used fix command, then what should I do?
In addition, I am confused about the pre no command. If we use pre no, then the initial setup is skipped. Does it mean that before a “run” there is no such process as neighbor lists and computing forces if we use pre no? But in my opinion, the force should be computed before every timestep in order to update the acceleration of atoms. So how to understand the function of “pre no”?
I think that it might be the simplest way to just implement your modifications in a fix. Basically what you want to do is just take the addforce fix and calculate the "xvalue" from ComputeExternalForce(). That shouldnt be too difficult.
I think that it might be the simplest way to just implement your modifications in a fix. Basically what you want to do is just take the addforce fix and calculate the "xvalue" from ComputeExternalForce(). That shouldnt be too difficult.
absolutely, but beyond that.
one question is, how complicated is the formula that ComputeExternalForce()
is evaluating? perhaps it can even be cast into a lammps variable and then no
modifications to lammps are needed at all.
Thanks, Christian and Axel. I tried to change the function post_force(int vflag) in fix_addforce.cpp, in order that xvalue can be obtained from the data file “data.txt”, then I update the force in “data.txt” in simple.c every timestep. The changed code of post_force() is as follows:
if (varflag == CONSTANT) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (iregion >= 0 &&
!domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2]))
continue;
foriginal[0] -= xvaluex[i][0] + yvaluex[i][1] + zvalue*x[i][2];
foriginal[1] += f[i][0];
foriginal[2] += f[i][1];
foriginal[3] += f[i][2];
f[i][0] += xvalue;
f[i][1] += yvalue;
f[i][2] += zvalue;
}
However, it seems that the function post_force(int vflag) is only called once at the first timestep. Even the content of “data.txt” is changed, the additional force doesn’t change at all. So how can I change the additional force in “fix addforce” command via the file “data.txt”? Thanks!
Using pre no, doesn't mean LAMMPS never computes neighbor
lists. It just means it does it when it needs to like in a normal
long LAMMPS run. And not before every run, like it normally would.
The warning about fixes not being initialized is just a warning. In
the case of what you want to do, I think it will work fine. The fix
is already in the list of things to invoke (which is calculated before
the first run). All you are doing is changing a value internal to
the fix by re-specifying it, so I think it should just work.
You can also look at fix external which lets your caller provide
a callback for forces. This would be easy to modify, for example, to add forces
instead of compute them, if that was what you needed.