LCOV - code coverage report
Current view: top level - src/utils - AbaqusUtils.C (source / functions) Hit Total Coverage
Test: idaholab/moose tensor_mechanics: d6b47a Lines: 157 163 96.3 %
Date: 2024-02-27 11:53:14 Functions: 33 33 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://www.mooseframework.org
       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             : 
      16             : const libMesh::Parallel::Communicator * AbaqusUtils::_communicator = nullptr;
      17             : 
      18             : void
      19          76 : AbaqusUtils::setCommunicator(const libMesh::Parallel::Communicator * communicator)
      20             : {
      21          76 :   if (_communicator != nullptr && communicator != _communicator)
      22             :     mooseWarning("Conflicting MPI communicators specified in Abaqus compatibility objects. Are you "
      23             :                  "running a multiapps simulation?");
      24             : 
      25          76 :   _communicator = communicator;
      26          76 : }
      27             : 
      28             : extern "C" void
      29          94 : getnumcpus_(int * num)
      30             : {
      31             :   auto communicator = AbaqusUtils::getCommunicator();
      32          94 :   *num = communicator->size();
      33          94 : }
      34             : 
      35             : extern "C" void
      36          94 : getrank_(int * rank)
      37             : {
      38             :   auto communicator = AbaqusUtils::getCommunicator();
      39          94 :   *rank = communicator->rank();
      40          94 : }
      41             : 
      42             : extern "C" MPI_Comm
      43          30 : get_communicator()
      44             : {
      45             :   auto communicator = AbaqusUtils::getCommunicator();
      46          30 :   return communicator->get();
      47             : }
      48             : 
      49             : // Threads
      50             : 
      51             : extern "C" int
      52        4744 : getnumthreads_()
      53             : {
      54        4744 :   return libMesh::n_threads();
      55             : }
      56             : 
      57             : extern "C" int
      58        4675 : get_thread_id_()
      59             : {
      60             :   ParallelUniqueId puid;
      61        4675 :   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          76 : AbaqusUtils::setInputFile(const std::string & input_file)
      71             : {
      72          76 :   auto split = MooseUtils::splitFileName(input_file);
      73          76 :   auto output_dir = split.first;
      74         152 :   auto job_name = MooseUtils::stripExtension(split.second);
      75             : 
      76         124 :   if (!_output_dir.empty() && output_dir != _output_dir)
      77             :     mooseWarning("Conflicting output directories specified in Abaqus compatibility objects: ",
      78             :                  output_dir,
      79             :                  " != ",
      80             :                  _output_dir,
      81             :                  ". Are you running a multiapps simulation?");
      82             : 
      83          76 :   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         152 :   _output_dir = output_dir;
      91             :   _job_name = job_name;
      92          76 : }
      93             : 
      94             : extern "C" void
      95          62 : getoutdir_(char * dir, int * len)
      96             : {
      97             :   auto output_dir = AbaqusUtils::getOutputDir();
      98          62 :   *len = output_dir.length();
      99       15934 :   for (int i = 0; i < 256; ++i)
     100       15872 :     dir[i] = i < *len ? output_dir[i] : ' ';
     101          62 : }
     102             : 
     103             : extern "C" void
     104          62 : getjobname_(char * dir, int * len)
     105             : {
     106             :   auto job_name = AbaqusUtils::getJobName();
     107          62 :   *len = job_name.length();
     108       15934 :   for (int i = 0; i < 256; ++i)
     109       15872 :     dir[i] = i < *len ? job_name[i] : ' ';
     110          62 : }
     111             : 
     112             : // error/warning/info message output
     113             : 
     114             : extern "C" void
     115          85 : 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        4398 :   for (int i = 0; i < format_len; ++i)
     123             :   {
     124             :     // interpret %I, %R, and %S
     125        4313 :     if (format[i] == '%' && i < format_len - 1)
     126             :     {
     127         595 :       auto next = format[i + 1];
     128             : 
     129             :       // integer output
     130         595 :       if (next == 'I' || next == 'i')
     131             :       {
     132         170 :         message += std::to_string(intv[int_index++]);
     133         170 :         i++;
     134         170 :         continue;
     135             :       }
     136             : 
     137             :       // Real output
     138         425 :       if (next == 'R' || next == 'r')
     139             :       {
     140         255 :         message += std::to_string(realv[real_index++]);
     141         255 :         i++;
     142         255 :         continue;
     143             :       }
     144             : 
     145             :       // char[8] output
     146         170 :       if (next == 'S' || next == 's')
     147             :       {
     148        1530 :         for (unsigned int j = 0; j < 8; ++j)
     149        1360 :           message += charv[char_index++];
     150         170 :         i++;
     151         170 :         continue;
     152         170 :       }
     153             :     }
     154             : 
     155             :     // append character to string
     156        3718 :     message += format[i];
     157             :   }
     158             : 
     159             :   // output at the selected error level
     160          85 :   switch (*lop)
     161             :   {
     162             :     case 1:
     163         108 :       Moose::out << moose::internal::mooseMsgFmt(message, "** Abaqus Info **", COLOR_CYAN)
     164             :                  << std::flush;
     165          54 :       break;
     166             : 
     167             :     case -1:
     168          12 :       Moose::out << moose::internal::mooseMsgFmt(message, "** Abaqus Warning **", COLOR_YELLOW)
     169             :                  << std::flush;
     170           6 :       break;
     171             : 
     172             :     case -2:
     173          48 :       Moose::out << moose::internal::mooseMsgFmt(message, "** Abaqus Non-fatal Error **", COLOR_RED)
     174             :                  << std::flush;
     175          24 :       break;
     176             : 
     177           1 :     case -3:
     178           1 :       mooseError(message);
     179             :       break;
     180             : 
     181           0 :     default:
     182           0 :       mooseError("Invalid LOP code passed to STDB_ABQERR: ", *lop);
     183             :       break;
     184             :   }
     185          84 : }
     186             : 
     187             : void
     188          36 : AbaqusUtils::smaInitialize()
     189             : {
     190             :   static bool initialized = false;
     191             : 
     192             :   // Guard the initialization with a double checked lock
     193          36 :   if (!initialized)
     194             :   {
     195             :     Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
     196          18 :     if (!initialized)
     197             :     {
     198           6 :       const auto n = getnumthreads_();
     199           6 :       _sma_local_int_array.resize(n);
     200           6 :       _sma_local_float_array.resize(n);
     201           6 :       initialized = true;
     202             :     }
     203             :   }
     204          36 : }
     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           3 : SMAIntArrayCreate(int id, int len, int val)
     215             : {
     216           3 :   auto ib = AbaqusUtils::_sma_int_array.emplace(id, std::vector<int>(len, val));
     217           3 :   if (ib.second == false)
     218           0 :     mooseError("Error creating threaded storage in SMAIntArrayCreate");
     219           3 :   return ib.first->second.data();
     220             : }
     221             : 
     222             : extern "C" double *
     223           3 : SMAFloatArrayCreate(int id, int len, Real val)
     224             : {
     225           3 :   auto ib = AbaqusUtils::_sma_float_array.emplace(id, std::vector<Real>(len, val));
     226           3 :   if (ib.second == false)
     227           0 :     mooseError("Error creating threaded storage in SMAFloatArrayCreate");
     228           3 :   return ib.first->second.data();
     229             : }
     230             : 
     231             : extern "C" int *
     232          18 : SMALocalIntArrayCreate(int id, int len, int val)
     233             : {
     234          18 :   AbaqusUtils::smaInitialize();
     235          18 :   auto & array = AbaqusUtils::getSMAThreadArray(AbaqusUtils::_sma_local_int_array,
     236          18 :                                                 "SMALocalIntArrayCreate")[id];
     237          18 :   array.assign(len, val);
     238          18 :   return array.data();
     239             : }
     240             : 
     241             : extern "C" double *
     242          18 : SMALocalFloatArrayCreate(int id, int len, Real val)
     243             : {
     244          18 :   AbaqusUtils::smaInitialize();
     245          18 :   auto & array = AbaqusUtils::getSMAThreadArray(AbaqusUtils::_sma_local_float_array,
     246          18 :                                                 "SMALocalFloatArrayCreate")[id];
     247          18 :   array.assign(len, val);
     248          18 :   return array.data();
     249             : }
     250             : 
     251             : // Array access
     252             : 
     253             : extern "C" int *
     254          12 : SMAIntArrayAccess(int id)
     255             : {
     256          24 :   auto it = AbaqusUtils::getSMAIterator(AbaqusUtils::_sma_int_array, id, "SMAIntArrayAccess");
     257          12 :   return it->second.data();
     258             : }
     259             : 
     260             : extern "C" double *
     261          12 : SMAFloatArrayAccess(int id)
     262             : {
     263          24 :   auto it = AbaqusUtils::getSMAIterator(AbaqusUtils::_sma_float_array, id, "SMAFloatArrayAccess");
     264          12 :   return it->second.data();
     265             : }
     266             : 
     267             : extern "C" int *
     268          72 : SMALocalIntArrayAccess(int id)
     269             : {
     270             :   auto & array =
     271          72 :       AbaqusUtils::getSMAThreadArray(AbaqusUtils::_sma_local_int_array, "SMALocalIntArrayAccess");
     272         144 :   auto it = AbaqusUtils::getSMAIterator(array, id, "SMALocalIntArrayAccess");
     273          72 :   return it->second.data();
     274             : }
     275             : 
     276             : extern "C" double *
     277          72 : SMALocalFloatArrayAccess(int id)
     278             : {
     279          72 :   auto & array = AbaqusUtils::getSMAThreadArray(AbaqusUtils::_sma_local_float_array,
     280             :                                                 "SMALocalFloatArrayAccess");
     281         144 :   auto it = AbaqusUtils::getSMAIterator(array, id, "SMALocalFloatArrayAccess");
     282          72 :   return it->second.data();
     283             : }
     284             : 
     285             : // Array size check
     286             : 
     287             : extern "C" std::size_t
     288         363 : SMAIntArraySize(int id)
     289             : {
     290         726 :   auto it = AbaqusUtils::getSMAIterator(AbaqusUtils::_sma_int_array, id, "SMAIntArraySize");
     291         363 :   return it->second.size();
     292             : }
     293             : 
     294             : extern "C" std::size_t
     295          57 : SMAFloatArraySize(int id)
     296             : {
     297         114 :   auto it = AbaqusUtils::getSMAIterator(AbaqusUtils::_sma_float_array, id, "SMAFloatArraySize");
     298          57 :   return it->second.size();
     299             : }
     300             : 
     301             : extern "C" std::size_t
     302        2166 : SMALocalIntArraySize(int id)
     303             : {
     304             :   auto & array =
     305        2166 :       AbaqusUtils::getSMAThreadArray(AbaqusUtils::_sma_local_int_array, "SMALocalIntArraySize");
     306        4332 :   auto it = AbaqusUtils::getSMAIterator(array, id, "SMALocalIntArraySize");
     307        2166 :   return it->second.size();
     308             : }
     309             : 
     310             : extern "C" std::size_t
     311         330 : SMALocalFloatArraySize(int id)
     312             : {
     313             :   auto & array =
     314         330 :       AbaqusUtils::getSMAThreadArray(AbaqusUtils::_sma_local_float_array, "SMALocalFloatArraySize");
     315         660 :   auto it = AbaqusUtils::getSMAIterator(array, id, "SMALocalFloatArraySize");
     316         330 :   return it->second.size();
     317             : }
     318             : 
     319             : // Array deletion
     320             : 
     321             : extern "C" void
     322           3 : SMAIntArrayDelete(int id)
     323             : {
     324           6 :   auto it = AbaqusUtils::getSMAIterator(AbaqusUtils::_sma_int_array, id, "SMAIntArrayDelete");
     325           3 :   AbaqusUtils::_sma_int_array.erase(it);
     326           3 : }
     327             : 
     328             : extern "C" void
     329           3 : SMAFloatArrayDelete(int id)
     330             : {
     331           6 :   auto it = AbaqusUtils::getSMAIterator(AbaqusUtils::_sma_float_array, id, "SMAFloatArrayDelete");
     332           3 :   AbaqusUtils::_sma_float_array.erase(it);
     333           3 : }
     334             : 
     335             : extern "C" void
     336          18 : SMALocalIntArrayDelete(int id)
     337             : {
     338             :   auto & array =
     339          18 :       AbaqusUtils::getSMAThreadArray(AbaqusUtils::_sma_local_int_array, "SMALocalIntArrayDelete");
     340          36 :   auto it = AbaqusUtils::getSMAIterator(array, id, "SMALocalIntArrayDelete");
     341          18 :   array.erase(it);
     342          18 : }
     343             : 
     344             : extern "C" void
     345          18 : SMALocalFloatArrayDelete(int id)
     346             : {
     347          18 :   auto & array = AbaqusUtils::getSMAThreadArray(AbaqusUtils::_sma_local_float_array,
     348             :                                                 "SMALocalFloatArrayDelete");
     349          36 :   auto it = AbaqusUtils::getSMAIterator(array, id, "SMALocalFloatArrayDelete");
     350          18 :   array.erase(it);
     351          18 : }
     352             : 
     353             : // Mutex handling
     354             : 
     355             : std::array<std::unique_ptr<Threads::spin_mutex>, 101> AbaqusUtils::_mutex = {{nullptr}};
     356             : 
     357             : void
     358          21 : AbaqusUtils::mutexInit(std::size_t n)
     359             : {
     360             :   // Guard the initialization with a double checked lock
     361          21 :   if (!_mutex[n])
     362             :   {
     363             :     Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
     364          20 :     if (!_mutex[n])
     365          18 :       _mutex[n] = std::make_unique<Threads::spin_mutex>();
     366             :   }
     367          21 : }
     368             : 
     369             : void
     370       21021 : AbaqusUtils::mutexLock(std::size_t n)
     371             : {
     372       21021 :   if (n >= _mutex.size() || !_mutex[n])
     373           0 :     mooseError("Invalid or uninitialized mutex ", n);
     374             :   _mutex[n]->lock();
     375       21021 : }
     376             : 
     377             : void
     378       21021 : AbaqusUtils::mutexUnlock(std::size_t n)
     379             : {
     380       21021 :   if (n >= _mutex.size() || !_mutex[n])
     381           0 :     mooseError("Invalid or uninitialized mutex ", n);
     382             :   _mutex[n]->unlock();
     383       21021 : }
     384             : 
     385             : extern "C" void
     386          21 : MutexInit(int id)
     387             : {
     388          21 :   AbaqusUtils::mutexInit(id);
     389          21 : }
     390             : 
     391             : extern "C" void
     392       21021 : MutexLock(int id)
     393             : {
     394       21021 :   AbaqusUtils::mutexLock(id);
     395       21021 : }
     396             : 
     397             : extern "C" void
     398       21021 : MutexUnlock(int id)
     399             : {
     400       21021 :   AbaqusUtils::mutexUnlock(id);
     401       21021 : }

Generated by: LCOV version 1.14