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

Generated by: LCOV version 1.14