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 
36     Christoph Kloss (DCS Computing GmbH, Linz)
37     Christoph Kloss (JKU Linz)
38     Richard Berger (JKU Linz)
39     Arno Mayrhofer (CFDEMresearch GmbH, Linz)
40 
41     Copyright 2012-     DCS Computing GmbH, Linz
42     Copyright 2009-2012 JKU Linz
43     Copyright 2016-     CFDEMresearch GmbH, Linz
44 ------------------------------------------------------------------------- */
45 
46 #include <mpi.h>
47 #include "ctype.h"
48 #include "float.h"
49 #include "limits.h"
50 #include <cmath>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include "pair.h"
55 #include "atom.h"
56 #include "neighbor.h"
57 #include "neigh_list.h"
58 #include "domain.h"
59 #include "comm.h"
60 #include "force.h"
61 #include "kspace.h"
62 #include "update.h"
63 #include "accelerator_cuda.h"
64 #include "suffix.h"
65 #include "atom_masks.h"
66 #include "memory.h"
67 #include "error.h"
68 #include "utils.h"
69 
70 #include <string>
71 #include <iostream>
72 #include "contact_models.h"
73 
74 namespace LIGGGHTS {
75 namespace ContactModels {
76 
Factory()77 Factory::Factory() {
78   // register contact model string to contact mappings
79   #define SURFACE_MODEL(identifier,str,constant) \
80   addSurfaceModel(#str, identifier);
81   #include "style_surface_model.h"
82   #undef SURFACE_MODEL
83 
84   addNormalModel("off", NORMAL_OFF);
85   #define NORMAL_MODEL(identifier,str,constant) \
86   addNormalModel(#str, identifier);
87   #include "style_normal_model.h"
88   #undef NORMAL_MODEL
89 
90   addTangentialModel("off", TANGENTIAL_OFF);
91   #define TANGENTIAL_MODEL(identifier,str,constant) \
92   addTangentialModel(#str, identifier);
93   #include "style_tangential_model.h"
94   #undef TANGENTIAL_MODEL
95 
96   addCohesionModel("off", COHESION_OFF);
97   #define COHESION_MODEL(identifier,str,constant) \
98   addCohesionModel(#str, identifier);
99   #include "style_cohesion_model.h"
100   #undef COHESION_MODEL
101 
102   addRollingModel("off", ROLLING_OFF);
103   #define ROLLING_MODEL(identifier,str,constant) \
104   addRollingModel(#str, identifier);
105   #include "style_rolling_model.h"
106   #undef ROLLING_MODEL
107 }
108 
instance()109 Factory & Factory::instance() {
110     static Factory _instance;
111     return _instance;
112 }
113 
addNormalModel(const std::string & name,int identifier)114 void Factory::addNormalModel(const std::string & name, int identifier) {
115   normal_models[name] = identifier;
116 }
117 
addTangentialModel(const std::string & name,int identifier)118 void Factory::addTangentialModel(const std::string & name, int identifier){
119   tangential_models[name] = identifier;
120 }
121 
addCohesionModel(const std::string & name,int identifier)122 void Factory::addCohesionModel(const std::string & name, int identifier) {
123   cohesion_models[name] = identifier;
124 }
125 
addRollingModel(const std::string & name,int identifier)126 void Factory::addRollingModel(const std::string & name, int identifier) {
127   rolling_models[name] = identifier;
128 }
129 
addSurfaceModel(const std::string & name,int identifier)130 void Factory::addSurfaceModel(const std::string & name, int identifier) {
131   surface_models[name] = identifier;
132 }
133 
getNormalModelId(const std::string & name)134 int Factory::getNormalModelId(const std::string & name) {
135   return normal_models[name];
136 }
137 
getTangentialModelId(const std::string & name)138 int Factory::getTangentialModelId(const std::string & name) {
139   return tangential_models[name];
140 }
141 
getCohesionModelId(const std::string & name)142 int Factory::getCohesionModelId(const std::string & name) {
143   return cohesion_models[name];
144 }
145 
getRollingModelId(const std::string & name)146 int Factory::getRollingModelId(const std::string & name) {
147   return rolling_models[name];
148 }
149 
getSurfaceModelId(const std::string & name)150 int Factory::getSurfaceModelId(const std::string & name) {
151   return surface_models[name];
152 }
153 
select(int & narg,char ** & args,Custom_contact_models ccm)154 int64_t Factory::select(int & narg, char ** & args,Custom_contact_models ccm) {
155   return instance().select_model(narg, args,ccm);
156 }
157 
select_model(int & narg,char ** & args,Custom_contact_models ccm)158 int64_t Factory::select_model(int & narg, char ** & args, Custom_contact_models ccm)
159 {
160     // this method will consume arguments to determine which granular contact model is active
161 
162     // default configuration
163     int model = NORMAL_OFF;
164     int tangential = TANGENTIAL_OFF;
165     int cohesion = COHESION_OFF;
166     int rolling = ROLLING_OFF;
167     int surface = SURFACE_DEFAULT;
168 
169     // select normal model
170     if (narg > 1 && strcmp(args[0], "model") == 0)
171     {
172         if (normal_models.find(args[1]) != normal_models.end())
173             model = normal_models[args[1]];
174         else if (0 == strcmp(args[1],"custom"))
175         {
176             if (normal_models.find(ccm.custom_normal_model) != normal_models.end())
177                model = normal_models[ccm.custom_normal_model];
178             else
179                model = -1;
180         }
181         else
182             model = -1;
183 
184         if(narg > 2)
185             args = &args[2];
186         narg -= 2;
187     }
188 
189     // OPTIONAL: select tangential model
190     if (narg > 1 && strcmp(args[0], "tangential") == 0)
191     {
192         if (tangential_models.find(args[1]) != tangential_models.end())
193             tangential = tangential_models[args[1]];
194         else if (0 == strcmp(args[1],"custom"))
195         {
196             if (tangential_models.find(ccm.custom_tangential_model) != tangential_models.end())
197                tangential = tangential_models[ccm.custom_tangential_model];
198             else
199                tangential = -1;
200         }
201         else
202             tangential = -1;
203 
204         if(narg > 2)
205             args = &args[2];
206         narg -= 2;
207     }
208 
209     // OPTIONAL: select cohesion model
210     if (narg > 1 && strcmp(args[0], "cohesion") == 0)
211     {
212         if (cohesion_models.find(args[1]) != cohesion_models.end())
213             cohesion = cohesion_models[args[1]];
214         else if (0 == strcmp(args[1],"custom"))
215         {
216             if (cohesion_models.find(ccm.custom_cohesion_model) != cohesion_models.end())
217                cohesion = cohesion_models[ccm.custom_cohesion_model];
218             else
219                cohesion = -1;
220         }
221         else
222             cohesion = -1;
223 
224         if(narg > 2)
225             args = &args[2];
226         narg -= 2;
227     }
228 
229     // OPTIONAL: select rolling model
230     if (narg > 1 && strcmp(args[0], "rolling_friction") == 0)
231     {
232         if (rolling_models.find(args[1]) != rolling_models.end())
233             rolling = rolling_models[args[1]];
234         else if (0 == strcmp(args[1],"custom"))
235         {
236             if (rolling_models.find(ccm.custom_rolling_model) != rolling_models.end())
237                rolling = rolling_models[ccm.custom_rolling_model];
238             else
239                rolling = -1;
240         }
241         else
242           rolling = -1;
243 
244         if(narg > 2)
245             args = &args[2];
246         narg -= 2;
247     }
248 
249     // OPTIONAL: select surface model
250     if (narg > 1 && strcmp(args[0], "surface") == 0)
251     {
252         if (surface_models.find(args[1]) != surface_models.end())
253             surface = surface_models[args[1]];
254         else if (0 == strcmp(args[1],"custom"))
255         {
256             if (surface_models.find(ccm.custom_surface_model) != surface_models.end())
257                surface = surface_models[ccm.custom_surface_model];
258             else
259                surface = -1;
260         }
261         else
262           surface = -1;
263 
264         if(narg > 2)
265             args = &args[2];
266         narg -= 2;
267     }
268 
269     if((model != -1 && tangential != -1 && cohesion != -1 && rolling != -1 && surface != -1) &&
270        !(model == NORMAL_OFF && tangential == TANGENTIAL_OFF && cohesion == COHESION_OFF && rolling == ROLLING_OFF))
271         return Utils::generate_gran_hashcode(model, tangential, cohesion, rolling, surface);
272     return -1;
273 }
274 
get_history_offset(const string hname)275 int ContactModelBase::get_history_offset(const string hname)
276 {
277     std::map<std::string, int>::iterator it = history_offsets.find(hname);
278     if (it != history_offsets.end())
279         return it->second;
280     return -1;
281 }
282 
add_history_offset(const string hname,const int offset,const bool overwrite)283 void ContactModelBase::add_history_offset(const string hname, const int offset, const bool overwrite)
284 {
285     std::map<std::string, int>::iterator it = history_offsets.find(hname);
286     if (it == history_offsets.end() || overwrite)
287     {
288 
289         history_offsets[hname] = offset;
290     }
291     else
292        error->one(FLERR, "Could not add history offset as key exists already and overwrite is not set");
293     return;
294 }
295 
296 } // ContactModels
297 } // LIGGGHTS
298