1 /* ----------------------------------------------------------------------
2 This is the
3
4 ██╗ ██╗ ██████╗ ██████╗ ██████╗ ██╗ ██╗████████╗███████╗
5 ██║ ██║██╔════╝ ██╔════╝ ██╔════╝ ██║ ██║╚══██╔══╝██╔════╝
6 ██║ ██║██║ ███╗██║ ███╗██║ ███╗███████║ ██║ ███████╗
7 ██║ ██║██║ ██║██║ ██║██║ ██║██╔══██║ ██║ ╚════██║
8 ███████╗██║╚██████╔╝╚██████╔╝╚██████╔╝██║ ██║ ██║ ███████║
9 ╚══════╝╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝®
10
11 DEM simulation engine, released by
12 DCS Computing Gmbh, Linz, Austria
13 http://www.dcs-computing.com, office@dcs-computing.com
14
15 LIGGGHTS® is part of CFDEM®project:
16 http://www.liggghts.com | http://www.cfdem.com
17
18 Core developer and main author:
19 Christoph Kloss, christoph.kloss@dcs-computing.com
20
21 LIGGGHTS® is open-source, distributed under the terms of the GNU Public
22 License, version 2 or later. It is distributed in the hope that it will
23 be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
24 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. You should have
25 received a copy of the GNU General Public License along with LIGGGHTS®.
26 If not, see http://www.gnu.org/licenses . See also top-level README
27 and LICENSE files.
28
29 LIGGGHTS® and CFDEM® are registered trade marks of DCS Computing GmbH,
30 the producer of the LIGGGHTS® software and the CFDEM®coupling software
31 See http://www.cfdem.com/terms-trademark-policy for details.
32
33 -------------------------------------------------------------------------
34 Contributing author and copyright for this file:
35 (if not contributing author is listed, this file has been contributed
36 by the core developer)
37
38 Copyright 2012- DCS Computing GmbH, Linz
39 Copyright 2009-2012 JKU Linz
40 ------------------------------------------------------------------------- */
41
42 #include <stdio.h>
43 #include <string.h>
44 #include <cmath>
45 #include <algorithm>
46 #include "modify.h"
47 #include "style_compute.h"
48 #include "style_fix.h"
49 #include "atom.h"
50 #include "comm.h"
51 #include "fix.h"
52 #include "compute.h"
53 #include "group.h"
54 #include "update.h"
55 #include "fix_property_atom.h"
56 #include "fix_property_global.h"
57 #include "domain.h"
58 #include "memory.h"
59 #include "error.h"
60
61 using namespace LAMMPS_NS;
62
63 /* ----------------------------------------------------------------------
64
65 add a fix property
66 ------------------------------------------------------------------------- */
67
add_fix_property_global(int narg,char ** arg,const char * caller)68 FixPropertyGlobal* Modify::add_fix_property_global(int narg,char **arg,const char *caller)
69 {
70 if(narg < 5) error->all(FLERR,"Not enough arguments to add a fix property");
71 add_fix(narg,arg);
72 return static_cast<FixPropertyGlobal*>(find_fix_property(arg[3],"property/global",arg[4],0,0,caller));
73 }
74
add_fix_property_atom(int narg,char ** arg,const char * caller)75 FixPropertyAtom* Modify::add_fix_property_atom(int narg,char **arg,const char *caller)
76 {
77 if(narg < 5) error->all(FLERR,"Not enough arguments to add a fix property");
78 add_fix(narg,arg);
79 return static_cast<FixPropertyAtom*>(find_fix_property(arg[3],"property/atom",arg[4],0,0,caller));
80 }
81
82 /* ----------------------------------------------------------------------
83 find a fix scalar transport equation
84 ------------------------------------------------------------------------- */
85
find_fix_scalar_transport_equation_strict(const char * equation_id)86 FixScalarTransportEquation* Modify::find_fix_scalar_transport_equation_strict(const char *equation_id)
87 {
88
89 for(int ifix = 0; ifix < nfix; ifix++)
90 if(strcmp(fix[ifix]->style,"transportequation/scalar") == 0)
91 {
92 FixScalarTransportEquation *fix_ste = static_cast<FixScalarTransportEquation*>(fix[ifix]);
93 if(fix_ste->match_equation_id(equation_id)) return fix_ste;
94 }
95 return NULL;
96 }
97
find_fix_scalar_transport_equation(const char * equation_id)98 FixScalarTransportEquation* Modify::find_fix_scalar_transport_equation(const char *equation_id)
99 {
100
101 for(int ifix = 0; ifix < nfix; ifix++)
102 if(dynamic_cast<FixScalarTransportEquation*>(fix[ifix]))
103 {
104 FixScalarTransportEquation *fix_ste = static_cast<FixScalarTransportEquation*>(fix[ifix]);
105 if(fix_ste->match_equation_id(equation_id)) return fix_ste;
106 }
107 return NULL;
108 }
109
110 /* ----------------------------------------------------------------------
111 find a fix with the requested style
112 ------------------------------------------------------------------------- */
113
find_fix_style_strict(const char * style,int rank)114 Fix* Modify::find_fix_style_strict(const char *style, int rank)
115 {
116 for(int ifix = 0; ifix < nfix; ifix++)
117 if(strcmp(fix[ifix]->style,style) == 0)
118 {
119 if(rank > 0) rank --;
120 else return fix[ifix];
121 }
122 return NULL;
123 }
124
find_fix_style(const char * style,int rank)125 Fix* Modify::find_fix_style(const char *style, int rank)
126 {
127 int len = strlen(style);
128 for(int ifix = 0; ifix < nfix; ifix++)
129 if(strncmp(fix[ifix]->style,style,len) == 0)
130 {
131 if(rank > 0) rank --;
132 else return fix[ifix];
133 }
134 return NULL;
135 }
136
137 /* ----------------------------------------------------------------------
138 find a compute with the requested style
139 ------------------------------------------------------------------------- */
140
find_compute_style_strict(const char * style,int rank)141 Compute* Modify::find_compute_style_strict(const char *style, int rank)
142 {
143 for(int icompute = 0; icompute < ncompute; icompute++)
144 if(strcmp(compute[icompute]->style,style) == 0)
145 {
146 if(rank > 0) rank --;
147 else return compute[icompute];
148 }
149 return NULL;
150 }
151
152 /* ----------------------------------------------------------------------
153 find a fix by ID, return NULL if not found
154 ------------------------------------------------------------------------- */
155
find_fix_id(const char * id)156 Fix* Modify::find_fix_id(const char *id)
157 {
158 int ifix;
159 for (ifix = 0; ifix < nfix; ifix++)
160 if (strcmp(id,fix[ifix]->id) == 0) break;
161 if (ifix == nfix) return NULL;
162 return fix[ifix];
163 }
164
165 /* ----------------------------------------------------------------------
166 find a compute by ID, return NULL if not found
167 ------------------------------------------------------------------------- */
168
find_compute_id(const char * id)169 Compute* Modify::find_compute_id(const char *id)
170 {
171 int icompute;
172 for (icompute = 0; icompute < ncompute; icompute++)
173 if (strcmp(id,compute[icompute]->id) == 0) break;
174 if (icompute == ncompute) return NULL;
175 return compute[icompute];
176 }
177
178 /* ----------------------------------------------------------------------
179 find a fix by ID and style, return NULL if not found
180 ------------------------------------------------------------------------- */
181
find_fix_id_style(const char * id,const char * style)182 Fix* Modify::find_fix_id_style(const char *id,const char* style)
183 {
184 int ifix;
185 for (ifix = 0; ifix < nfix; ifix++)
186 if (strcmp(id,fix[ifix]->id) == 0 && strncmp(style,fix[ifix]->style,strlen(style)) == 0) break;
187 if (ifix == nfix) return NULL;
188 return fix[ifix];
189 }
190
191 /* ----------------------------------------------------------------------
192 return number of fixes/computes with requested style
193 ------------------------------------------------------------------------- */
194
n_fixes_style(const char * style)195 int Modify::n_fixes_style(const char *style)
196 {
197 int n_fixes,len;
198
199 n_fixes = 0;
200 len = strlen(style);
201
202 for(int ifix = 0; ifix < nfix; ifix++)
203 if(strncmp(fix[ifix]->style,style,len) == 0)
204 n_fixes++;
205
206 return n_fixes;
207 }
208
n_computes_style(const char * style)209 int Modify::n_computes_style(const char *style)
210 {
211 int n_computes,len;
212
213 n_computes = 0;
214 len = strlen(style);
215
216 for(int icompute = 0; icompute < ncompute; icompute++)
217 if(strncmp(compute[icompute]->style,style,len) == 0)
218 n_computes++;
219
220 return n_computes;
221 }
222
n_fixes_style_strict(const char * style)223 int Modify::n_fixes_style_strict(const char *style)
224 {
225 int n_fixes = 0;
226
227 for(int ifix = 0; ifix < nfix; ifix++)
228 if(strcmp(fix[ifix]->style,style) == 0)
229 n_fixes++;
230
231 return n_fixes;
232 }
233
234 /* ----------------------------------------------------------------------
235 find a fix property/atom for output
236 ------------------------------------------------------------------------- */
237
n_fixes_property_atom()238 int Modify::n_fixes_property_atom()
239 {
240 int n_fixes = 0;
241
242 for(int ifix = 0; ifix < nfix; ifix++)
243 if(dynamic_cast<FixPropertyAtom*>(fix[ifix]))
244 n_fixes++;
245
246 return n_fixes;
247 }
248
find_fix_property_atom(int rank)249 FixPropertyAtom* Modify::find_fix_property_atom(int rank)
250 {
251 for(int ifix = 0; ifix < nfix; ifix++)
252 if(dynamic_cast<FixPropertyAtom*>(fix[ifix]))
253 {
254 if(rank > 0) rank --;
255 else return dynamic_cast<FixPropertyAtom*>(fix[ifix]);
256 }
257 return NULL;
258 }
259
260 /* ----------------------------------------------------------------------
261 find a fix property/atom for output
262 ------------------------------------------------------------------------- */
263
n_fixes_property_atom_not_internal()264 int Modify::n_fixes_property_atom_not_internal()
265 {
266 int n_fixes = 0;
267
268 for(int ifix = 0; ifix < nfix; ifix++)
269 if(dynamic_cast<FixPropertyAtom*>(fix[ifix]) && !dynamic_cast<FixPropertyAtom*>(fix[ifix])->get_internal())
270 n_fixes++;
271
272 return n_fixes;
273 }
274
dump_size_fixes_property_atom_not_internal()275 int Modify::dump_size_fixes_property_atom_not_internal()
276 {
277 int n_dump = 0;
278
279 for(int ifix = 0; ifix < nfix; ifix++)
280 if(dynamic_cast<FixPropertyAtom*>(fix[ifix]) && !dynamic_cast<FixPropertyAtom*>(fix[ifix])->get_internal())
281 {
282 n_dump += dynamic_cast<FixPropertyAtom*>(fix[ifix])->get_nvalues();
283 }
284
285 return n_dump;
286 }
287
find_fix_property_atom_not_internal(int rank)288 FixPropertyAtom* Modify::find_fix_property_atom_not_internal(int rank)
289 {
290 for(int ifix = 0; ifix < nfix; ifix++)
291 if(dynamic_cast<FixPropertyAtom*>(fix[ifix]) && !dynamic_cast<FixPropertyAtom*>(fix[ifix])->get_internal())
292 {
293 if(rank > 0) rank --;
294 else return dynamic_cast<FixPropertyAtom*>(fix[ifix]);
295 }
296 return NULL;
297 }
298
299 /* ----------------------------------------------------------------------
300
301 checks if I am the first fix of a specified style
302 ------------------------------------------------------------------------- */
303
i_am_first_of_style(Fix * fix_to_check)304 bool Modify::i_am_first_of_style(Fix *fix_to_check)
305 {
306 for(int ifix = 0; ifix < nfix; ifix++)
307 {
308 if(strcmp(fix[ifix]->style,fix_to_check->style) == 0)
309 {
310 if(fix_to_check == fix[ifix]) return true;
311 return false;
312 }
313 }
314
315 // no fix at all of this style found
316 return false;
317 }
318
319 /* ----------------------------------------------------------------------
320
321 returns the index of first/last fix of specified style
322 ------------------------------------------------------------------------- */
323
index_first_fix_of_style(const char * style)324 int Modify::index_first_fix_of_style(const char *style)
325 {
326 for(int ifix = 0; ifix < nfix; ifix++)
327 if(strcmp(fix[ifix]->style,style) == 0)
328 return ifix;
329
330 return -1;
331 }
332
index_last_fix_of_style(const char * style)333 int Modify::index_last_fix_of_style(const char *style)
334 {
335 int idx = -1;
336
337 for(int ifix = 0; ifix < nfix; ifix++)
338 if(strcmp(fix[ifix]->style,style) == 0)
339 idx = ifix;
340
341 return idx;
342 }
343
344 /* ----------------------------------------------------------------------
345
346 returns the index of first fix that implements a specified function
347 ------------------------------------------------------------------------- */
348
my_index(Fix * fixptr)349 int Modify::my_index(Fix *fixptr)
350 {
351
352 for(int ifix = 0; ifix < nfix; ifix++)
353 if(fix[ifix] == fixptr)
354 return ifix;
355
356 return -1;
357 }
358
359 /* ----------------------------------------------------------------------
360
361 returns the index of first fix that implements a specified function
362 ------------------------------------------------------------------------- */
363
index_first_fix_with_function(const int FUNCTION,bool integrate)364 int Modify::index_first_fix_with_function(const int FUNCTION, bool integrate)
365 {
366
367 for(int ifix = 0; ifix < nfix; ifix++)
368 if((!integrate || fix[ifix]->time_integrate) && (fmask[ifix] & FUNCTION))
369 return ifix;
370
371 return -1;
372 }
373
374 /* ----------------------------------------------------------------------
375
376 find a property registered by a fix property/global or fix property/atom
377 check if it is of desired style
378 return the index in the fix array
379 ------------------------------------------------------------------------- */
380
find_fix_property(const char * varname,const char * style,const char * svmstyle,int len1,int len2,const char * caller)381 Fix* Modify::find_fix_property(const char *varname,const char *style,const char *svmstyle,int len1,int len2,const char *caller)
382 {
383 return find_fix_property(varname,style,svmstyle,len1,len2,caller,true);
384 }
385
find_fix_property(const char * varname,const char * style,const char * svmstyle,int len1,int len2,const char * caller,bool errflag)386 Fix* Modify::find_fix_property(const char *varname,const char *style,const char *svmstyle,int len1,int len2,const char *caller,bool errflag)
387 {
388 int ifix;
389 char errmsg[500];
390 Fix *fix_i = NULL;
391
392 if((strcmp(style,"property/global")) && (strncmp(style,"property/atom",13)))
393 error->all(FLERR,"Valid styles for find_fix_property are 'property/global' and 'property/atom'");
394
395 if((len1 < 0) || (len2 < 0))
396 error->all(FLERR,"Lengths for find_fix_property not valid");
397
398 for(ifix = 0; ifix < nfix; ifix++)
399 {
400 if(strncmp(fix[ifix]->style,"property/atom",13) == 0 && dynamic_cast<FixPropertyAtom*>(fix[ifix]))
401 fix_i = static_cast<FixPropertyAtom*>(fix[ifix])->check_fix(varname,svmstyle,len1,len2,caller,errflag);
402 else if(strcmp(fix[ifix]->style,"property/global") == 0 && dynamic_cast<FixPropertyGlobal*>(fix[ifix]))
403 fix_i = static_cast<FixPropertyGlobal*>(fix[ifix])->check_fix(varname,svmstyle,len1,len2,caller,errflag);
404
405 // check_fix returns either this or NULL
406 if(fix_i) return fix_i;
407 }
408
409 // no fix found
410 if(errflag)
411 {
412 sprintf(errmsg,"Could not locate a fix/property storing value(s) for %s as requested by %s.",varname,caller);
413 error->all(FLERR,errmsg);
414 }
415 return NULL;
416 }
417
418 /* ----------------------------------------------------------------------
419 return if fix restart in progress
420 ------------------------------------------------------------------------- */
421
fix_restart_in_progress()422 int Modify::fix_restart_in_progress()
423 {
424 return nfix_restart_global || nfix_restart_peratom;
425 }
426
427 /* ----------------------------------------------------------------------
428 check if restart data available for this fix
429 ------------------------------------------------------------------------- */
430
have_restart_data(Fix * f)431 bool Modify::have_restart_data(Fix *f)
432 {
433
434 // check if Fix is in restart_global list
435
436 for (int i = 0; i < nfix_restart_global; i++)
437 if (strcmp(id_restart_global[i],f->id) == 0 && strcmp(style_restart_global[i],f->style) == 0)
438 return true;
439
440 // check if Fix is in restart_peratom list
441
442 for (int i = 0; i < nfix_restart_peratom; i++)
443 if (strcmp(id_restart_peratom[i],f->id) == 0 && strcmp(style_restart_peratom[i],f->style) == 0)
444 return true;
445
446 return false;
447 }
448
have_restart_data_style(const char * _style)449 bool Modify::have_restart_data_style(const char* _style)
450 {
451
452 // check if Fix is in restart_global list
453
454 for (int i = 0; i < nfix_restart_global; i++)
455 if (strncmp(style_restart_global[i],_style,strlen(_style)) == 0)
456 return true;
457
458 // check if Fix is in restart_peratom list
459
460 for (int i = 0; i < nfix_restart_peratom; i++)
461 if (strncmp(style_restart_peratom[i],_style,strlen(_style)) == 0)
462 return true;
463
464 return false;
465 }
466
n_restart_data_global_style(const char * _style)467 int Modify::n_restart_data_global_style(const char* _style)
468 {
469
470 int nhave = 0;
471
472 // check if Fix is in restart_global list
473
474 for (int i = 0; i < nfix_restart_global; i++)
475 if (strncmp(style_restart_global[i],_style,strlen(_style)) == 0)
476 nhave++;
477
478 return nhave;
479 }
480
id_restart_data_global_style(const char * _style,int _rank)481 char* Modify::id_restart_data_global_style(const char* _style,int _rank)
482 {
483
484 // check if Fix is in restart_global list
485
486 for (int i = 0; i < nfix_restart_global; i++)
487 if (strncmp(style_restart_global[i],_style,strlen(_style)) == 0)
488 {
489 if(_rank > 0) _rank --;
490 else return id_restart_global[i];
491 }
492
493 return 0;
494 }
495
496 /* ----------------------------------------------------------------------
497 let fixes extend bounding box
498 ------------------------------------------------------------------------- */
499
box_extent(double & xlo,double & xhi,double & ylo,double & yhi,double & zlo,double & zhi)500 void Modify::box_extent(double &xlo,double &xhi,double &ylo,double &yhi,double &zlo,double &zhi)
501 {
502
503 // check if Fix is in restart_global list
504
505 for (int i = 0; i < nfix; i++)
506 fix[i]->box_extent(xlo,xhi,ylo,yhi,zlo,zhi);
507 }
508
509 /* ----------------------------------------------------------------------
510 return min particle radius
511 ------------------------------------------------------------------------- */
512
max_min_rad(double & maxrad,double & minrad)513 void Modify::max_min_rad(double &maxrad,double &minrad)
514 {
515 maxrad = 0.;
516 minrad = 1000.;
517 int nlocal = atom->nlocal;
518 double *radius = atom->radius;
519 int ntypes = atom->ntypes;
520
521 for (int i = 0; i < nfix; i++) {
522 for (int j = 1; j <= ntypes; j++) {
523
524 maxrad = std::max(maxrad,fix[i]->max_rad(j));
525 if(modify->fix[i]->min_rad(j) > 0.)
526 minrad = std::min(minrad,fix[i]->min_rad(j));
527 }
528 }
529
530 if (radius) {
531 for (int i = 0; i < nlocal; i++) {
532 maxrad = std::max(maxrad,radius[i]);
533 minrad = std::min(minrad,radius[i]);
534 }
535 }
536
537 MPI_Min_Scalar(minrad,world);
538 MPI_Max_Scalar(maxrad,world);
539 }
540
541 /* ----------------------------------------------------------------------
542 calls the exchange routine for fix mesh/...
543 This is a kind of workaround.
544 ------------------------------------------------------------------------- */
545
forceMeshExchange()546 void Modify::forceMeshExchange()
547 {
548 for (int i = 0; i < n_pre_force; ++i) {
549 Fix *cfix = fix[list_pre_force[i]];
550 if( strncmp(cfix->style,"mesh/surface",12) == 0 && dynamic_cast<FixMesh*>(cfix) )
551 static_cast<FixMesh*>(cfix)->setup_pre_force(0);
552 }
553 }
554