1 /*! 2 * \file StandardElastoViscoPlasticityBrick.cxx 3 * \brief 4 * \author Thomas Helfer 5 * \date 17/03/2018 6 */ 7 8 #include "TFEL/Raise.hxx" 9 #include "TFEL/Utilities/Data.hxx" 10 #include "MFront/ImplicitDSLBase.hxx" 11 #include "MFront/NonLinearSystemSolver.hxx" 12 #include "MFront/BehaviourBrick/StressPotential.hxx" 13 #include "MFront/BehaviourBrick/StressPotentialFactory.hxx" 14 #include "MFront/BehaviourBrick/InelasticFlow.hxx" 15 #include "MFront/BehaviourBrick/InelasticFlowFactory.hxx" 16 #include "MFront/AbstractBehaviourDSL.hxx" 17 #include "MFront/StandardElastoViscoPlasticityBrick.hxx" 18 19 namespace mfront { 20 21 static std::string getId(const size_t i, const size_t m) { 22 if (m == 1) { getReservedNames() const23 return ""; 24 } 25 return std::to_string(i); 26 } // end of getId 27 28 StandardElastoViscoPlasticityBrick::StandardElastoViscoPlasticityBrick( 29 AbstractBehaviourDSL& dsl_, 30 BehaviourDescription& mb_, 31 const Parameters&, usesJacobian() const32 const DataMap& d) 33 : BehaviourBrickBase(dsl_, mb_) { 34 auto raise = [](const std::string& m) { 35 tfel::raise( 36 "StandardElastoViscoPlasticityBrick::" 37 "StandardElastoViscoPlasticityBrick: " + 38 m); 39 }; // end of raise 40 auto& iff = bbrick::InelasticFlowFactory::getFactory(); 41 auto getDataStructure = [&raise](const std::string& n, const Data& ds) { 42 if (ds.is<std::string>()) { 43 tfel::utilities::DataStructure nds; 44 nds.name = ds.get<std::string>(); 45 return nds; 46 } 47 if (!ds.is<tfel::utilities::DataStructure>()) { 48 raise("invalid data type for entry '" + n + "'"); 49 } 50 return ds.get<tfel::utilities::DataStructure>(); 51 }; // end of getDataStructure 52 auto getStressPotential = [&d,&getDataStructure,&raise, this](const char* const n) { 53 if (d.count(n) != 0) { 54 const auto ds = getDataStructure(n, d.at(n)); 55 if (this->stress_potential != nullptr) { 56 raise("the stress potential has already been defined"); 57 } 58 auto& spf = bbrick::StressPotentialFactory::getFactory(); 59 this->stress_potential = spf.generate(ds.name); 60 this->stress_potential->initialize(this->bd, this->dsl, ds.data); 61 } 62 }; 63 getStressPotential("elastic_potential"); 64 getStressPotential("stress_potential"); 65 if (this->stress_potential == nullptr) { 66 raise("no stress potential defined"); 67 } 68 for (const auto& e : d) { 69 if ((e.first == "elastic_potential") || (e.first == "stress_potential")) { 70 // already treated 71 } else if (e.first == "inelastic_flow") { 72 auto append_flow = [this, &iff, getDataStructure](const Data& ifd, 73 const size_t msize) { 74 const auto ds = getDataStructure("inelatic_flow", ifd); 75 auto iflow = iff.generate(ds.name); 76 iflow->initialize(this->bd, this->dsl, 77 getId(this->flows.size(), msize), ds.data); 78 this->flows.push_back(iflow); 79 }; 80 if (e.second.is<std::vector<Data>>()) { 81 // multiple inelastic flows are defined 82 const auto& ifs = e.second.get<std::vector<Data>>(); 83 for (const auto& iflow : ifs) { 84 append_flow(iflow, ifs.size()); 85 } 86 } else { 87 append_flow(e.second, 1u); 88 } 89 } else { 90 raise("unsupported entry '" + e.first + "'"); 91 } 92 } 93 } // end of StandardElastoViscoPlasticityBrick 94 95 std::string StandardElastoViscoPlasticityBrick::getName() const { 96 return "ElastoViscoPlasticity"; 97 } 98 99 std::vector<StandardElastoViscoPlasticityBrick::Hypothesis> 100 StandardElastoViscoPlasticityBrick::getSupportedModellingHypotheses() const { writeResolutionAlgorithm(std::ostream & out,const BehaviourDescription & mb,const Hypothesis h) const101 return this->stress_potential->getSupportedModellingHypotheses(this->bd, 102 this->dsl); 103 } 104 105 void StandardElastoViscoPlasticityBrick::completeVariableDeclaration() const { 106 this->stress_potential->completeVariableDeclaration(this->bd, this->dsl); 107 auto i = size_t{}; 108 for (const auto& f : this->flows) { 109 f->completeVariableDeclaration(this->bd, this->dsl, 110 getId(i, this->flows.size())); 111 ++i; 112 } 113 } // end of StandardElastoViscoPlasticityBrick::completeVariableDeclaration 114 115 void StandardElastoViscoPlasticityBrick::endTreatment() const { 116 const auto& idsl = dynamic_cast<const ImplicitDSLBase&>(this->dsl); 117 this->stress_potential->endTreatment(this->bd, this->dsl); 118 const bool requiresAnalyticalJacobian = 119 ((idsl.getSolver().usesJacobian()) && 120 (!idsl.getSolver().requiresNumericalJacobian())); 121 if (requiresAnalyticalJacobian) { 122 this->stress_potential->writeStressDerivatives(this->bd); 123 } 124 auto i = size_t{}; 125 for (const auto& f : this->flows) { 126 f->endTreatment(this->bd, this->dsl, *(this->stress_potential), 127 getId(i, this->flows.size())); 128 ++i; 129 } 130 // at this stage, one assumes that the various components of the inelastic 131 // flow (stress_potential, isotropic hardening rule) have added the 132 // initialization of their material properties the 133 // `BeforeInitializeLocalVariables`. We then ask the inelastic flows if 134 // they 135 // require an activation state (in practice, it mean that an isotropic 136 // hardening rule has been defined). If so, the initialization of the 137 // activation states requires the the computation of an elastic prediction 138 // of the stress. The brik asks the stress potential to compute it in a 139 // variable called sigel and the inelastic flows shall use it to compute 140 // their initial state. All thoses steps must be added to the 141 // `BeforeInitializeLocalVariables` code block. 142 const bool bep = [this] { 143 for (const auto& pf : this->flows) { 144 if (pf->requiresActivationState()) { 145 return true; 146 } 147 } 148 return false; 149 }(); 150 if (bep) { 151 // compute the elastic prediction 152 this->stress_potential->computeElasticPrediction(bd); 153 i = size_t{}; 154 for (const auto& pf : this->flows) { 155 if (pf->requiresActivationState()) { 156 pf->computeInitialActivationState(bd, *(this->stress_potential), 157 getId(i, this->flows.size())); 158 } 159 ++i; 160 } 161 } 162 } // end of StandardElastoViscoPlasticityBrick::endTreatment 163 164 StandardElastoViscoPlasticityBrick::~StandardElastoViscoPlasticityBrick() = 165 default; 166 167 } // end of namespace mfront 168