https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
18void
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
25 _communicator = communicator;
26}
27
28extern "C" void
29getnumcpus_(int * num)
30{
31 auto communicator = AbaqusUtils::getCommunicator();
32 *num = communicator->size();
33}
34
35extern "C" void
36getrank_(int * rank)
37{
38 auto communicator = AbaqusUtils::getCommunicator();
39 *rank = communicator->rank();
40}
41
42extern "C" MPI_Comm
44{
45 auto communicator = AbaqusUtils::getCommunicator();
46 return communicator->get();
47}
48
49// Threads
50
51extern "C" int
53{
54 return libMesh::n_threads();
55}
56
57extern "C" int
59{
61 return puid.id;
62}
63
64// Output directory
65
66std::string AbaqusUtils::_output_dir = "";
67std::string AbaqusUtils::_job_name = "";
68
69void
70AbaqusUtils::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 " != ",
88 ". Are you running a multiapps simulation?");
89
90 _output_dir = output_dir;
91 _job_name = job_name;
92}
93
94extern "C" void
95getoutdir_(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
103extern "C" void
104getjobname_(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
114extern "C" void
115stdb_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:
178 mooseError(message);
179 break;
180
181 default:
182 mooseError("Invalid LOP code passed to STDB_ABQERR: ", *lop);
183 break;
184 }
185}
186
187void
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
208std::map<int, std::vector<int>> AbaqusUtils::_sma_int_array;
209std::map<int, std::vector<Real>> AbaqusUtils::_sma_float_array;
210std::vector<std::map<int, std::vector<int>>> AbaqusUtils::_sma_local_int_array;
211std::vector<std::map<int, std::vector<Real>>> AbaqusUtils::_sma_local_float_array;
212
213extern "C" int *
214SMAIntArrayCreate(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
222extern "C" double *
223SMAFloatArrayCreate(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
231extern "C" int *
232SMALocalIntArrayCreate(int id, int len, int val)
233{
236 "SMALocalIntArrayCreate")[id];
237 array.assign(len, val);
238 return array.data();
239}
240
241extern "C" double *
242SMALocalFloatArrayCreate(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
253extern "C" int *
255{
256 auto it = AbaqusUtils::getSMAIterator(AbaqusUtils::_sma_int_array, id, "SMAIntArrayAccess");
257 return it->second.data();
258}
259
260extern "C" double *
262{
263 auto it = AbaqusUtils::getSMAIterator(AbaqusUtils::_sma_float_array, id, "SMAFloatArrayAccess");
264 return it->second.data();
265}
266
267extern "C" int *
269{
270 auto & array =
272 auto it = AbaqusUtils::getSMAIterator(array, id, "SMALocalIntArrayAccess");
273 return it->second.data();
274}
275
276extern "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
287extern "C" std::size_t
289{
290 auto it = AbaqusUtils::getSMAIterator(AbaqusUtils::_sma_int_array, id, "SMAIntArraySize");
291 return it->second.size();
292}
293
294extern "C" std::size_t
296{
297 auto it = AbaqusUtils::getSMAIterator(AbaqusUtils::_sma_float_array, id, "SMAFloatArraySize");
298 return it->second.size();
299}
300
301extern "C" std::size_t
303{
304 auto & array =
306 auto it = AbaqusUtils::getSMAIterator(array, id, "SMALocalIntArraySize");
307 return it->second.size();
308}
309
310extern "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
321extern "C" void
323{
324 auto it = AbaqusUtils::getSMAIterator(AbaqusUtils::_sma_int_array, id, "SMAIntArrayDelete");
326}
327
328extern "C" void
330{
331 auto it = AbaqusUtils::getSMAIterator(AbaqusUtils::_sma_float_array, id, "SMAFloatArrayDelete");
333}
334
335extern "C" void
337{
338 auto & array =
340 auto it = AbaqusUtils::getSMAIterator(array, id, "SMALocalIntArrayDelete");
341 array.erase(it);
342}
343
344extern "C" void
346{
348 "SMALocalFloatArrayDelete");
349 auto it = AbaqusUtils::getSMAIterator(array, id, "SMALocalFloatArrayDelete");
350 array.erase(it);
351}
352
353// Mutex handling
354
355std::array<std::unique_ptr<Threads::spin_mutex>, 101> AbaqusUtils::_mutex = {{nullptr}};
356
357void
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
369void
371{
372 if (n >= _mutex.size() || !_mutex[n])
373 mooseError("Invalid or uninitialized mutex ", n);
374 _mutex[n]->lock();
375}
376
377void
379{
380 if (n >= _mutex.size() || !_mutex[n])
381 mooseError("Invalid or uninitialized mutex ", n);
382 _mutex[n]->unlock();
383}
384
385extern "C" void
387{
389}
390
391extern "C" void
393{
395}
396
397extern "C" void
399{
401}
void MutexInit(int id)
void SMALocalIntArrayDelete(int id)
int * SMAIntArrayAccess(int id)
int getnumthreads_()
Definition AbaqusUtils.C:52
std::size_t SMALocalIntArraySize(int id)
void getjobname_(char *dir, int *len)
int * SMALocalIntArrayCreate(int id, int len, int val)
int get_thread_id_()
Definition AbaqusUtils.C:58
void MutexUnlock(int id)
double * SMALocalFloatArrayCreate(int id, int len, Real val)
void SMALocalFloatArrayDelete(int id)
double * SMAFloatArrayAccess(int id)
void getrank_(int *rank)
Definition AbaqusUtils.C:36
std::size_t SMALocalFloatArraySize(int id)
void stdb_abqerr_(int *lop, char *format, int *intv, double *realv, char *charv, int format_len)
void getnumcpus_(int *num)
Definition AbaqusUtils.C:29
void MutexLock(int id)
void getoutdir_(char *dir, int *len)
Definition AbaqusUtils.C:95
int * SMALocalIntArrayAccess(int id)
void SMAIntArrayDelete(int id)
std::size_t SMAFloatArraySize(int id)
int * SMAIntArrayCreate(int id, int len, int val)
double * SMAFloatArrayCreate(int id, int len, Real val)
std::size_t SMAIntArraySize(int id)
MPI_Comm get_communicator()
Definition AbaqusUtils.C:43
void SMAFloatArrayDelete(int id)
double * SMALocalFloatArrayAccess(int id)
void mooseWarning(Args &&... args)
void mooseError(Args &&... args)
int getnumthreads_()
Definition AbaqusUtils.C:52
static std::map< int, std::vector< int > > _sma_int_array
Shared Memory Arrays.
Definition AbaqusUtils.h:52
static std::vector< std::map< int, std::vector< Real > > > _sma_local_float_array
Definition AbaqusUtils.h:55
static std::vector< std::map< int, std::vector< int > > > _sma_local_int_array
Definition AbaqusUtils.h:54
static void smaInitialize()
thread storage initialization
static void mutexInit(std::size_t n)
Mutex API.
static const libMesh::Parallel::Communicator * _communicator
Definition AbaqusUtils.h:67
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
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
static const libMesh::Parallel::Communicator * getCommunicator()
Definition AbaqusUtils.h:35
static std::string getJobName()
Definition AbaqusUtils.h:28
static std::string _job_name
Definition AbaqusUtils.h:66
static std::string _output_dir
Definition AbaqusUtils.h:65
static std::map< int, std::vector< Real > > _sma_float_array
Definition AbaqusUtils.h:53
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
static std::string getOutputDir()
Definition AbaqusUtils.h:27
static void mutexUnlock(std::size_t n)
static std::array< std::unique_ptr< Threads::spin_mutex >, 101 > _mutex
static void mutexLock(std::size_t n)
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 stripExtension(const std::string &s, const bool rfind)
unsigned int n_threads()
std::string mooseMsgFmt(const std::string &msg, const std::string &title, const std::string &color)