https://mooseframework.inl.gov
AbaqusUtils.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "AbaqusUtils.h"
11 #include "MooseUtils.h"
12 #include "libmesh/threads.h"
13 
14 // MPI
15 
17 
18 void
20 {
21  if (_communicator != nullptr && communicator != _communicator)
22  mooseWarning("Conflicting MPI communicators specified in Abaqus compatibility objects. Are you "
23  "running a multiapps simulation?");
24 
26 }
27 
28 extern "C" void
29 getnumcpus_(int * num)
30 {
32  *num = communicator->size();
33 }
34 
35 extern "C" void
36 getrank_(int * rank)
37 {
39  *rank = communicator->rank();
40 }
41 
42 extern "C" MPI_Comm
44 {
46  return communicator->get();
47 }
48 
49 // Threads
50 
51 extern "C" int
53 {
54  return libMesh::n_threads();
55 }
56 
57 extern "C" int
59 {
60  ParallelUniqueId puid;
61  return puid.id;
62 }
63 
64 // Output directory
65 
66 std::string AbaqusUtils::_output_dir = "";
67 std::string AbaqusUtils::_job_name = "";
68 
69 void
70 AbaqusUtils::setInputFile(const std::string & input_file)
71 {
72  auto split = MooseUtils::splitFileName(input_file);
73  auto output_dir = split.first;
74  auto job_name = MooseUtils::stripExtension(split.second);
75 
76  if (!_output_dir.empty() && output_dir != _output_dir)
77  mooseWarning("Conflicting output directories specified in Abaqus compatibility objects: ",
78  output_dir,
79  " != ",
81  ". Are you running a multiapps simulation?");
82 
83  if (!_job_name.empty() && job_name != _job_name)
84  mooseWarning("Conflicting job names specified in Abaqus compatibility objects: ",
85  job_name,
86  " != ",
87  _job_name,
88  ". Are you running a multiapps simulation?");
89 
90  _output_dir = output_dir;
91  _job_name = job_name;
92 }
93 
94 extern "C" void
95 getoutdir_(char * dir, int * len)
96 {
97  auto output_dir = AbaqusUtils::getOutputDir();
98  *len = output_dir.length();
99  for (int i = 0; i < 256; ++i)
100  dir[i] = i < *len ? output_dir[i] : ' ';
101 }
102 
103 extern "C" void
104 getjobname_(char * dir, int * len)
105 {
106  auto job_name = AbaqusUtils::getJobName();
107  *len = job_name.length();
108  for (int i = 0; i < 256; ++i)
109  dir[i] = i < *len ? job_name[i] : ' ';
110 }
111 
112 // error/warning/info message output
113 
114 extern "C" void
115 stdb_abqerr_(int * lop, char * format, int * intv, double * realv, char * charv, int format_len)
116 {
117  std::string message;
118  unsigned int int_index = 0;
119  unsigned int real_index = 0;
120  unsigned int char_index = 0;
121 
122  for (int i = 0; i < format_len; ++i)
123  {
124  // interpret %I, %R, and %S
125  if (format[i] == '%' && i < format_len - 1)
126  {
127  auto next = format[i + 1];
128 
129  // integer output
130  if (next == 'I' || next == 'i')
131  {
132  message += std::to_string(intv[int_index++]);
133  i++;
134  continue;
135  }
136 
137  // Real output
138  if (next == 'R' || next == 'r')
139  {
140  message += std::to_string(realv[real_index++]);
141  i++;
142  continue;
143  }
144 
145  // char[8] output
146  if (next == 'S' || next == 's')
147  {
148  for (unsigned int j = 0; j < 8; ++j)
149  message += charv[char_index++];
150  i++;
151  continue;
152  }
153  }
154 
155  // append character to string
156  message += format[i];
157  }
158 
159  // output at the selected error level
160  switch (*lop)
161  {
162  case 1:
163  Moose::out << moose::internal::mooseMsgFmt(message, "** Abaqus Info **", COLOR_CYAN)
164  << std::flush;
165  break;
166 
167  case -1:
168  Moose::out << moose::internal::mooseMsgFmt(message, "** Abaqus Warning **", COLOR_YELLOW)
169  << std::flush;
170  break;
171 
172  case -2:
173  Moose::out << moose::internal::mooseMsgFmt(message, "** Abaqus Non-fatal Error **", COLOR_RED)
174  << std::flush;
175  break;
176 
177  case -3:
179  break;
180 
181  default:
182  mooseError("Invalid LOP code passed to STDB_ABQERR: ", *lop);
183  break;
184  }
185 }
186 
187 void
189 {
190  static bool initialized = false;
191 
192  // Guard the initialization with a double checked lock
193  if (!initialized)
194  {
195  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
196  if (!initialized)
197  {
198  const auto n = getnumthreads_();
199  _sma_local_int_array.resize(n);
200  _sma_local_float_array.resize(n);
201  initialized = true;
202  }
203  }
204 }
205 
206 // Array creation
207 
208 std::map<int, std::vector<int>> AbaqusUtils::_sma_int_array;
209 std::map<int, std::vector<Real>> AbaqusUtils::_sma_float_array;
210 std::vector<std::map<int, std::vector<int>>> AbaqusUtils::_sma_local_int_array;
211 std::vector<std::map<int, std::vector<Real>>> AbaqusUtils::_sma_local_float_array;
212 
213 extern "C" int *
214 SMAIntArrayCreate(int id, int len, int val)
215 {
216  auto ib = AbaqusUtils::_sma_int_array.emplace(id, std::vector<int>(len, val));
217  if (ib.second == false)
218  mooseError("Error creating threaded storage in SMAIntArrayCreate");
219  return ib.first->second.data();
220 }
221 
222 extern "C" double *
223 SMAFloatArrayCreate(int id, int len, Real val)
224 {
225  auto ib = AbaqusUtils::_sma_float_array.emplace(id, std::vector<Real>(len, val));
226  if (ib.second == false)
227  mooseError("Error creating threaded storage in SMAFloatArrayCreate");
228  return ib.first->second.data();
229 }
230 
231 extern "C" int *
232 SMALocalIntArrayCreate(int id, int len, int val)
233 {
236  "SMALocalIntArrayCreate")[id];
237  array.assign(len, val);
238  return array.data();
239 }
240 
241 extern "C" double *
242 SMALocalFloatArrayCreate(int id, int len, Real val)
243 {
246  "SMALocalFloatArrayCreate")[id];
247  array.assign(len, val);
248  return array.data();
249 }
250 
251 // Array access
252 
253 extern "C" int *
255 {
256  auto it = AbaqusUtils::getSMAIterator(AbaqusUtils::_sma_int_array, id, "SMAIntArrayAccess");
257  return it->second.data();
258 }
259 
260 extern "C" double *
262 {
263  auto it = AbaqusUtils::getSMAIterator(AbaqusUtils::_sma_float_array, id, "SMAFloatArrayAccess");
264  return it->second.data();
265 }
266 
267 extern "C" int *
269 {
270  auto & array =
272  auto it = AbaqusUtils::getSMAIterator(array, id, "SMALocalIntArrayAccess");
273  return it->second.data();
274 }
275 
276 extern "C" double *
278 {
280  "SMALocalFloatArrayAccess");
281  auto it = AbaqusUtils::getSMAIterator(array, id, "SMALocalFloatArrayAccess");
282  return it->second.data();
283 }
284 
285 // Array size check
286 
287 extern "C" std::size_t
289 {
290  auto it = AbaqusUtils::getSMAIterator(AbaqusUtils::_sma_int_array, id, "SMAIntArraySize");
291  return it->second.size();
292 }
293 
294 extern "C" std::size_t
296 {
297  auto it = AbaqusUtils::getSMAIterator(AbaqusUtils::_sma_float_array, id, "SMAFloatArraySize");
298  return it->second.size();
299 }
300 
301 extern "C" std::size_t
303 {
304  auto & array =
306  auto it = AbaqusUtils::getSMAIterator(array, id, "SMALocalIntArraySize");
307  return it->second.size();
308 }
309 
310 extern "C" std::size_t
312 {
313  auto & array =
315  auto it = AbaqusUtils::getSMAIterator(array, id, "SMALocalFloatArraySize");
316  return it->second.size();
317 }
318 
319 // Array deletion
320 
321 extern "C" void
323 {
324  auto it = AbaqusUtils::getSMAIterator(AbaqusUtils::_sma_int_array, id, "SMAIntArrayDelete");
325  AbaqusUtils::_sma_int_array.erase(it);
326 }
327 
328 extern "C" void
330 {
331  auto it = AbaqusUtils::getSMAIterator(AbaqusUtils::_sma_float_array, id, "SMAFloatArrayDelete");
333 }
334 
335 extern "C" void
337 {
338  auto & array =
340  auto it = AbaqusUtils::getSMAIterator(array, id, "SMALocalIntArrayDelete");
341  array.erase(it);
342 }
343 
344 extern "C" void
346 {
348  "SMALocalFloatArrayDelete");
349  auto it = AbaqusUtils::getSMAIterator(array, id, "SMALocalFloatArrayDelete");
350  array.erase(it);
351 }
352 
353 // Mutex handling
354 
355 std::array<std::unique_ptr<Threads::spin_mutex>, 101> AbaqusUtils::_mutex = {{nullptr}};
356 
357 void
359 {
360  // Guard the initialization with a double checked lock
361  if (!_mutex[n])
362  {
363  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
364  if (!_mutex[n])
365  _mutex[n] = std::make_unique<Threads::spin_mutex>();
366  }
367 }
368 
369 void
371 {
372  if (n >= _mutex.size() || !_mutex[n])
373  mooseError("Invalid or uninitialized mutex ", n);
374  _mutex[n]->lock();
375 }
376 
377 void
379 {
380  if (n >= _mutex.size() || !_mutex[n])
381  mooseError("Invalid or uninitialized mutex ", n);
382  _mutex[n]->unlock();
383 }
384 
385 extern "C" void
386 MutexInit(int id)
387 {
389 }
390 
391 extern "C" void
392 MutexLock(int id)
393 {
395 }
396 
397 extern "C" void
398 MutexUnlock(int id)
399 {
401 }
static std::string getOutputDir()
Definition: AbaqusUtils.h:27
void stdb_abqerr_(int *lop, char *format, int *intv, double *realv, char *charv, int format_len)
Definition: AbaqusUtils.C:115
int * SMAIntArrayAccess(int id)
Definition: AbaqusUtils.C:254
void SMAIntArrayDelete(int id)
Definition: AbaqusUtils.C:322
static void setCommunicator(const libMesh::Parallel::Communicator *communicator)
Global storage for the MPI communicator, this will be set by any Abaqus class.
Definition: AbaqusUtils.C:19
unsigned int n_threads()
static std::array< std::unique_ptr< Threads::spin_mutex >, 101 > _mutex
Definition: AbaqusUtils.h:64
int getnumthreads_()
Definition: AbaqusUtils.C:52
static std::string getJobName()
Definition: AbaqusUtils.h:28
void mooseError(Args &&... args)
MPI_Comm get_communicator()
Definition: AbaqusUtils.C:43
void getrank_(int *rank)
Definition: AbaqusUtils.C:36
void mooseWarning(Args &&... args)
std::pair< std::filesystem::path, std::filesystem::path > splitFileName(const T &full_file)
double * SMALocalFloatArrayCreate(int id, int len, Real val)
Definition: AbaqusUtils.C:242
static std::map< int, std::vector< T > >::iterator getSMAIterator(std::map< int, std::vector< T >> &array, int id, const std::string &function)
get data vector iterator with error checking
Definition: AbaqusUtils.h:72
double * SMALocalFloatArrayAccess(int id)
Definition: AbaqusUtils.C:277
std::size_t SMALocalIntArraySize(int id)
Definition: AbaqusUtils.C:302
int * SMAIntArrayCreate(int id, int len, int val)
Definition: AbaqusUtils.C:214
void SMALocalFloatArrayDelete(int id)
Definition: AbaqusUtils.C:345
static void mutexInit(std::size_t n)
Mutex API.
Definition: AbaqusUtils.C:358
static void smaInitialize()
thread storage initialization
Definition: AbaqusUtils.C:188
void MutexUnlock(int id)
Definition: AbaqusUtils.C:398
static std::vector< std::map< int, std::vector< Real > > > _sma_local_float_array
Definition: AbaqusUtils.h:55
std::string stripExtension(const std::string &s, const bool rfind=false)
static const libMesh::Parallel::Communicator * getCommunicator()
Definition: AbaqusUtils.h:35
static void mutexLock(std::size_t n)
Definition: AbaqusUtils.C:370
std::size_t SMAFloatArraySize(int id)
Definition: AbaqusUtils.C:295
void MutexInit(int id)
Definition: AbaqusUtils.C:386
static void mutexUnlock(std::size_t n)
Definition: AbaqusUtils.C:378
void SMALocalIntArrayDelete(int id)
Definition: AbaqusUtils.C:336
static const libMesh::Parallel::Communicator * _communicator
Definition: AbaqusUtils.h:67
double * SMAFloatArrayAccess(int id)
Definition: AbaqusUtils.C:261
void getoutdir_(char *dir, int *len)
Definition: AbaqusUtils.C:95
static std::string _output_dir
Definition: AbaqusUtils.h:65
static std::string _job_name
Definition: AbaqusUtils.h:66
tbb::split split
static std::map< int, std::vector< int > > _sma_int_array
Shared Memory Arrays.
Definition: AbaqusUtils.h:52
int * SMALocalIntArrayAccess(int id)
Definition: AbaqusUtils.C:268
static const std::string message
DIE A HORRIBLE DEATH HERE typedef MPI_Comm communicator
void getnumcpus_(int *num)
Definition: AbaqusUtils.C:29
void SMAFloatArrayDelete(int id)
Definition: AbaqusUtils.C:329
std::size_t SMALocalFloatArraySize(int id)
Definition: AbaqusUtils.C:311
bool initialized()
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
std::size_t SMAIntArraySize(int id)
Definition: AbaqusUtils.C:288
void getjobname_(char *dir, int *len)
Definition: AbaqusUtils.C:104
static std::map< int, std::vector< Real > > _sma_float_array
Definition: AbaqusUtils.h:53
double * SMAFloatArrayCreate(int id, int len, Real val)
Definition: AbaqusUtils.C:223
int get_thread_id_()
Definition: AbaqusUtils.C:58
static void setInputFile(const std::string &input_file)
Global storage for the simulation output directory, this will be set by any Abaqus class...
Definition: AbaqusUtils.C:70
std::string mooseMsgFmt(const std::string &msg, const std::string &title, const std::string &color)
int * SMALocalIntArrayCreate(int id, int len, int val)
Definition: AbaqusUtils.C:232
void MutexLock(int id)
Definition: AbaqusUtils.C:392
static std::vector< std::map< int, std::vector< int > > > _sma_local_int_array
Definition: AbaqusUtils.h:54
static std::map< int, std::vector< T > > & getSMAThreadArray(std::vector< std::map< int, std::vector< T >>> &local_array, const std::string &function)
get thread local array
Definition: AbaqusUtils.h:84