1 /*! 2 * \file mtest/src/SchemeBase.cxx 3 * \brief 4 * \author Thomas Helfer 5 * \date 02 oct. 2015 6 * \copyright Copyright (C) 2006-2018 CEA/DEN, EDF R&D. All rights 7 * reserved. 8 * This project is publicly released under either the GNU GPL Licence 9 * or the CECILL-A licence. A copy of thoses licences are delivered 10 * with the sources of TFEL. CEA or EDF may also distribute this 11 * project under specific licensing conditions. 12 */ 13 14 #include <sstream> 15 #include <algorithm> 16 17 #include "TFEL/Raise.hxx" 18 #include "MFront/MFrontLogStream.hxx" 19 #include "MTest/AccelerationAlgorithmFactory.hxx" 20 #include "MTest/CastemAccelerationAlgorithm.hxx" 21 #include "MTest/Evolution.hxx" 22 #include "MTest/SchemeBase.hxx" 23 24 namespace mtest { 25 SchemeBase()26 SchemeBase::SchemeBase() : evm(new EvolutionManager()) { 27 // declare time variable 28 this->declareVariable("t", true); 29 } // end of SchemeBase::SchemeBase 30 addEvolution(const std::string & n,const EvolutionPtr p,const bool b1,const bool b2)31 void SchemeBase::addEvolution(const std::string& n, 32 const EvolutionPtr p, 33 const bool b1, 34 const bool b2) { 35 if (b1) { 36 this->declareVariable(n, b1); 37 } else { 38 tfel::raise_if(std::find(this->vnames.begin(), this->vnames.end(), n) == 39 this->vnames.end(), 40 "SchemeBase::addEvolution: " 41 "variable '" + 42 n + "' is not defined"); 43 } 44 if (b2) { 45 tfel::raise_if(this->evm->find(n) != this->evm->end(), 46 "SchemeBase::addEvolution: " 47 "evolution '" + 48 n + "' already defined"); 49 } 50 (*(this->evm))[n] = p; 51 } // end of SchemeBase::addEvolution 52 setEvolutionValue(const std::string & n,const real t,const real v)53 void SchemeBase::setEvolutionValue(const std::string& n, 54 const real t, 55 const real v) { 56 const auto pev = this->evm->find(n); 57 tfel::raise_if( 58 pev == this->evm->end(), 59 "SchemeBase::setEvolutionValue : no evolution '" + n + "' declared"); 60 pev->second->setValue(t, v); 61 } // end of SchemeBase::setEvolutionValue 62 getEvolutions() const63 const EvolutionManager& SchemeBase::getEvolutions() const { 64 return *(this->evm); 65 } // end of SchemeBase::getEvolutions() const 66 setTimes(const std::vector<real> & t)67 void SchemeBase::setTimes(const std::vector<real>& t) { 68 tfel::raise_if(!this->times.empty(), 69 "SchemeBase::setTimes: " 70 "times already defined"); 71 this->times = t; 72 } // end of SchemeBase::setTimes 73 setMaximumNumberOfIterations(const unsigned int i)74 void SchemeBase::setMaximumNumberOfIterations(const unsigned int i) { 75 tfel::raise_if(this->options.iterMax != -1, 76 "SchemeBase::setMaximumNumberOfIterations: " 77 "the maximum number of iterations " 78 "has already been declared"); 79 tfel::raise_if(i == 0, 80 "SchemeBase::setMaximumNumberOfIterations: " 81 "invalid number of iterations"); 82 this->options.iterMax = static_cast<int>(i); 83 } 84 setMaximumNumberOfSubSteps(const unsigned int i)85 void SchemeBase::setMaximumNumberOfSubSteps(const unsigned int i) { 86 tfel::raise_if(this->options.mSubSteps != -1, 87 "SchemeBase::setMaximumNumberOfSubSteps: " 88 "the maximum number of sub steps " 89 "has already been declared"); 90 tfel::raise_if(i == 0, 91 "SchemeBase::setMaximumNumberOfSubSteps: " 92 "invalid number of sub steps"); 93 this->options.mSubSteps = static_cast<int>(i); 94 } 95 setOutputFrequency(const OutputFrequency o)96 void SchemeBase::setOutputFrequency(const OutputFrequency o) { 97 this->output_frequency = o; 98 } 99 setDynamicTimeStepScaling(const bool b)100 void SchemeBase::setDynamicTimeStepScaling(const bool b) { 101 this->options.dynamic_time_step_scaling = b; 102 } 103 setMaximalTimeStep(const real v)104 void SchemeBase::setMaximalTimeStep(const real v) { 105 TFEL_CONSTEXPR const auto emin = 100 * std::numeric_limits<real>::min(); 106 TFEL_CONSTEXPR const auto eps = 100 * std::numeric_limits<real>::epsilon(); 107 tfel::raise_if(this->options.maximal_time_step > 0, 108 "SchemeBase::setMaximalTimeStep: " 109 "the maximal time step " 110 "has already been declared"); 111 if (this->options.minimal_time_step > 0) { 112 tfel::raise_if(v <= this->options.minimal_time_step, 113 "SchemeBase::setMaximalTimeStep: " 114 "the specified maximal time step " 115 "is lower than the minimal time step"); 116 tfel::raise_if((std::abs(v - this->options.minimal_time_step) < emin) || 117 (std::abs(v - this->options.minimal_time_step) < eps), 118 "SchemeBase::setMaximalTimeStep: " 119 "the minimal and the maximal time step are too close"); 120 } 121 tfel::raise_if(v <= emin, 122 "SchemeBase::setMaximalTimeStep: " 123 "the maximal time step is either negative or too small"); 124 this->options.maximal_time_step = v; 125 } 126 setMinimalTimeStep(const real v)127 void SchemeBase::setMinimalTimeStep(const real v) { 128 TFEL_CONSTEXPR const auto emin = 100 * std::numeric_limits<real>::min(); 129 TFEL_CONSTEXPR const auto eps = 100 * std::numeric_limits<real>::epsilon(); 130 tfel::raise_if(this->options.minimal_time_step > 0, 131 "SchemeBase::setMinimalTimeStep: " 132 "the minimal time step " 133 "has already been declared"); 134 if (this->options.maximal_time_step > 0) { 135 tfel::raise_if(v >= this->options.maximal_time_step, 136 "SchemeBase::setMinimalTimeStep: " 137 "the specified minimal time step " 138 "is greater than the maximal time step"); 139 const auto d = std::abs(this->options.maximal_time_step - v); 140 tfel::raise_if((d < emin) || (d < eps * this->options.maximal_time_step), 141 "SchemeBase::setMinimalTimeStep: " 142 "the maximal and the minimal time step are too close"); 143 } 144 tfel::raise_if(v <= emin, 145 "SchemeBase::setMinimalTimeStep: " 146 "the specified minimal time step is " 147 "either negative or too small"); 148 this->options.minimal_time_step = v; 149 } 150 setMinimalTimeStepScalingFactor(const real v)151 void SchemeBase::setMinimalTimeStepScalingFactor(const real v) { 152 tfel::raise_if(this->options.minimal_time_step_scaling_factor > 0, 153 "SchemeBase::setMinimalTimeStepScalingFactor: " 154 "the minimal time step scaling factor " 155 "has already been declared"); 156 tfel::raise_if(v >= 1, 157 "SchemeBase::setMinimalTimeStepScalingFactor: " 158 "the minimal time step scaling factor " 159 "is greater than one "); 160 tfel::raise_if(v <= 100 * std::numeric_limits<real>::epsilon(), 161 "SchemeBase::setMinimalTimeStepScalingFactor: " 162 "the minimal time step scaling is either " 163 "negative or too small"); 164 this->options.minimal_time_step_scaling_factor = v; 165 } 166 setMaximalTimeStepScalingFactor(const real v)167 void SchemeBase::setMaximalTimeStepScalingFactor(const real v) { 168 tfel::raise_if(this->options.maximal_time_step_scaling_factor > 0, 169 "SchemeBase::setMaximalTimeStepScalingFactor: " 170 "the maximal time step scaling factor " 171 "has already been declared"); 172 tfel::raise_if(v < 1, 173 "SchemeBase::setMaximalTimeStepScalingFactor: " 174 "the maximal time step scaling factor " 175 "is lower than one "); 176 this->options.maximal_time_step_scaling_factor = v; 177 } 178 setDescription(const std::string & d)179 void SchemeBase::setDescription(const std::string& d) { 180 tfel::raise_if(!this->description.empty(), 181 "SchemeBase::setDescription: " 182 "description already set."); 183 this->description = d; 184 } // end of SchemeBase::setDescription 185 setAuthor(const std::string & a)186 void SchemeBase::setAuthor(const std::string& a) { 187 tfel::raise_if(!this->author.empty(), 188 "SchemeBase::setAuthor: " 189 "author already set."); 190 this->author = a; 191 } // end of SchemeBase::setAuthor 192 setDate(const std::string & d)193 void SchemeBase::setDate(const std::string& d) { 194 tfel::raise_if(!this->date.empty(), 195 "SchemeBase::setDate: " 196 "date already set."); 197 this->date = d; 198 } // end of SchemeBase::setDate 199 setModellingHypothesis(const std::string & h)200 void SchemeBase::setModellingHypothesis(const std::string& h) { 201 tfel::raise_if(this->hypothesis != ModellingHypothesis::UNDEFINEDHYPOTHESIS, 202 "SchemeBase::setModellingHypothesis: " 203 "the modelling hypothesis is already defined"); 204 this->hypothesis = ModellingHypothesis::fromString(h); 205 } // end of SchemeBase::setModellingHypothesis 206 207 tfel::material::ModellingHypothesis::Hypothesis getModellingHypothesis() const208 SchemeBase::getModellingHypothesis() const { 209 tfel::raise_if(this->hypothesis == ModellingHypothesis::UNDEFINEDHYPOTHESIS, 210 "SchemeBase::getModellingHypothesis: " 211 "the modelling hypothesis is not defined"); 212 return this->hypothesis; 213 } 214 getDimension() const215 unsigned short SchemeBase::getDimension() const { 216 tfel::raise_if(this->hypothesis == ModellingHypothesis::UNDEFINEDHYPOTHESIS, 217 "SchemeBase::getDimension: " 218 "the modelling hypothesis is " 219 "not defined"); 220 return tfel::material::getSpaceDimension(this->hypothesis); 221 } 222 setAccelerationAlgorithm(const std::string & a)223 void SchemeBase::setAccelerationAlgorithm(const std::string& a) { 224 tfel::raise_if(this->options.aa != nullptr, 225 "SchemeBase::setAccelerationAlgorithm: " 226 "acceleration algorithm already set"); 227 auto& f = AccelerationAlgorithmFactory::getAccelerationAlgorithmFactory(); 228 this->options.aa = f.getAlgorithm(a); 229 } 230 setAccelerationAlgorithmParameter(const std::string & p,const std::string & v)231 void SchemeBase::setAccelerationAlgorithmParameter(const std::string& p, 232 const std::string& v) { 233 tfel::raise_if(this->options.aa == nullptr, 234 "SchemeBase::setAccelerationAlgorithmParameter: " 235 "no acceleration algorithm set"); 236 this->options.aa->setParameter(p, v); 237 } 238 setPredictionPolicy(const PredictionPolicy p)239 void SchemeBase::setPredictionPolicy(const PredictionPolicy p) { 240 tfel::raise_if( 241 this->options.ppolicy != PredictionPolicy::UNSPECIFIEDPREDICTIONPOLICY, 242 "SchemeBase::setPredictionPolicy: " 243 "prediction policy already declared"); 244 this->options.ppolicy = p; 245 } // end of SchemeBase::setPredictionPolicy 246 setStiffnessMatrixType(const StiffnessMatrixType k)247 void SchemeBase::setStiffnessMatrixType(const StiffnessMatrixType k) { 248 tfel::raise_if(this->options.ktype != 249 StiffnessMatrixType::UNSPECIFIEDSTIFFNESSMATRIXTYPE, 250 "SchemeBase::setStiffnessMatrixType: " 251 "stiffness matrix type already specificed"); 252 this->options.ktype = k; 253 } 254 setUseCastemAccelerationAlgorithm(const bool ucaa)255 void SchemeBase::setUseCastemAccelerationAlgorithm(const bool ucaa) { 256 if (ucaa) { 257 tfel::raise_if(this->options.aa != nullptr, 258 "SchemeBase::setUseCastemAccelerationAlgorithm: " 259 "an algorithm was already set"); 260 this->options.aa = std::shared_ptr<AccelerationAlgorithm>( 261 new CastemAccelerationAlgorithm); 262 } 263 this->options.useCastemAcceleration = ucaa; 264 } 265 setCastemAccelerationTrigger(const int i)266 void SchemeBase::setCastemAccelerationTrigger(const int i) { 267 tfel::raise_if(!this->options.useCastemAcceleration, 268 "SchemeBase::setCastemAccelerationTrigger: " 269 "the castem acceleration algorithm has " 270 "not been set using the " 271 "@UseCast3mAccelerationAlgorithm keyword. " 272 "If the Cast3M acceleration algorithm " 273 "was specified using the " 274 "@AccelerationAlgorithm keyword, please " 275 "use the @AccelerationAlgorithmParameter " 276 "keyword to specify the acceleration trigger."); 277 tfel::raise_if(this->options.aa == nullptr, 278 "SchemeBase::setCastemAccelerationTrigger: " 279 "internal error"); 280 std::ostringstream nb; 281 nb << i; 282 this->options.aa->setParameter("AccelerationTrigger", nb.str()); 283 } 284 setCastemAccelerationPeriod(const int p)285 void SchemeBase::setCastemAccelerationPeriod(const int p) { 286 tfel::raise_if(!this->options.useCastemAcceleration, 287 "SchemeBase::setCastemAccelerationPeriod: " 288 "the castem acceleration algorithm has not " 289 "been set using the " 290 "@UseCast3mAccelerationAlgorithm keyword. " 291 "If the Cast3M acceleration algorithm was " 292 "specified using the @AccelerationAlgorithm " 293 "keyword, please use the " 294 "@AccelerationAlgorithmParameter keyword to " 295 "specify the acceleration period."); 296 tfel::raise_if(this->options.aa == nullptr, 297 "SchemeBase::setCastemAccelerationPeriod: " 298 "internal error"); 299 std::ostringstream nb; 300 nb << p; 301 this->options.aa->setParameter("AccelerationPeriod", nb.str()); 302 } 303 setStiffnessUpdatingPolicy(const StiffnessUpdatingPolicy p)304 void SchemeBase::setStiffnessUpdatingPolicy(const StiffnessUpdatingPolicy p) { 305 tfel::raise_if( 306 this->options.ks != 307 StiffnessUpdatingPolicy::UNSPECIFIEDSTIFFNESSUPDATINGPOLICY, 308 "SchemeBase::setStiffnessUpdatePolicy: " 309 "stiffness matrix type already specificed"); 310 this->options.ks = p; 311 } // end of SchemeBase::setStiffnessUpdatingPolicy 312 resetOutputFile()313 void SchemeBase::resetOutputFile() { 314 // output file 315 if (!this->output.empty()) { 316 this->out.close(); 317 this->out.open(this->output.c_str()); 318 tfel::raise_if(!this->out, 319 "SchemeBase::resetOutputFile: " 320 "can't open file '" + 321 this->output + "'"); 322 this->out.exceptions(std::ofstream::failbit | std::ofstream::badbit); 323 if (this->oprec != -1) { 324 this->out.precision(static_cast<std::streamsize>(this->oprec)); 325 } 326 } 327 // residual file 328 if (!this->residualFileName.empty()) { 329 this->residual.close(); 330 this->residual.open(this->residualFileName.c_str()); 331 tfel::raise_if(!this->residual, 332 "SchemeBase::resetOutputFile: " 333 "unable to open file '" + 334 this->residualFileName + "'"); 335 this->residual.exceptions(std::ofstream::failbit | std::ofstream::badbit); 336 if (this->rprec != -1) { 337 this->residual.precision(static_cast<std::streamsize>(this->rprec)); 338 } else { 339 if (this->oprec != -1) { 340 this->residual.precision(static_cast<std::streamsize>(this->oprec)); 341 } 342 } 343 } 344 } // end of resetOutputFile 345 completeInitialisation()346 void SchemeBase::completeInitialisation() { 347 tfel::raise_if(this->initialisationFinished, 348 "SchemeBase::completeInitialisation : " 349 "object already initialised"); 350 // initialisation is complete 351 this->initialisationFinished = true; 352 try { 353 if (this->hypothesis == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 354 this->setDefaultModellingHypothesis(); 355 } 356 // numerical parameters 357 if (this->options.mSubSteps == -1) { 358 this->options.mSubSteps = 10; 359 } 360 if (this->options.iterMax == -1) { 361 this->options.iterMax = 100; 362 } 363 if (this->options.aa != nullptr) { 364 this->options.aa->initialize(this->getNumberOfUnknowns()); 365 } 366 // prediction policy 367 if (this->options.ppolicy == 368 PredictionPolicy::UNSPECIFIEDPREDICTIONPOLICY) { 369 this->options.ppolicy = PredictionPolicy::NOPREDICTION; 370 } 371 // stiffness matrix type 372 if (this->options.ktype == 373 StiffnessMatrixType::UNSPECIFIEDSTIFFNESSMATRIXTYPE) { 374 this->options.ktype = this->getDefaultStiffnessMatrixType(); 375 } 376 // options selected 377 if (mfront::getVerboseMode() >= mfront::VERBOSE_LEVEL1) { 378 auto& log = mfront::getLogStream(); 379 if (this->options.aa != nullptr) { 380 log << "** " << this->options.aa->getName() 381 << " acceleration algorithm selected\n"; 382 } 383 if (this->options.ppolicy == PredictionPolicy::LINEARPREDICTION) { 384 log << "** using linear prediction\n"; 385 } else if (this->options.ppolicy == 386 PredictionPolicy::ELASTICPREDICTION) { 387 log << "** prediction using elastic stiffness\n"; 388 } else if (this->options.ppolicy == 389 PredictionPolicy::ELASTICPREDICTIONFROMMATERIALPROPERTIES) { 390 log << "** prediction using elastic stiffness computed from material " 391 "properties\n"; 392 } else if (this->options.ppolicy == 393 PredictionPolicy::TANGENTOPERATORPREDICTION) { 394 log << "** prediction using tangent operator\n"; 395 } else { 396 tfel::raise_if( 397 this->options.ppolicy != PredictionPolicy::NOPREDICTION, 398 "MTest::completeInitialisation : " 399 "internal error, unsupported " 400 "prediction policy"); 401 log << "** no prediction\n"; 402 } 403 } 404 this->resetOutputFile(); 405 } catch (...) { 406 this->initialisationFinished = false; 407 throw; 408 } 409 } // end of SchemeBase::completeInitialisation 410 declareVariable(const std::string & v,const bool check)411 void SchemeBase::declareVariable(const std::string& v, const bool check) { 412 if (std::find(this->vnames.begin(), this->vnames.end(), v) != 413 this->vnames.end()) { 414 tfel::raise_if(check, 415 "SchemeBase::declareVariable: " 416 "variable '" + 417 v + "' already declared"); 418 } else { 419 this->vnames.push_back(v); 420 } 421 } 422 declareVariables(const std::vector<std::string> & v,const bool check)423 void SchemeBase::declareVariables(const std::vector<std::string>& v, 424 const bool check) { 425 for (const auto& n : v) { 426 this->declareVariable(n, check); 427 } 428 } 429 setOutputFileName(const std::string & o)430 void SchemeBase::setOutputFileName(const std::string& o) { 431 tfel::raise_if(!this->output.empty(), 432 "SchemeBase::setOutputFileName: " 433 "output file name already defined"); 434 this->output = o; 435 } 436 isOutputFileNameDefined() const437 bool SchemeBase::isOutputFileNameDefined() const { 438 return !this->output.empty(); 439 } 440 setOutputFilePrecision(const unsigned int p)441 void SchemeBase::setOutputFilePrecision(const unsigned int p) { 442 tfel::raise_if(this->oprec != -1, 443 "SchemeBase::setOutputFileName: " 444 "output file precision already defined"); 445 this->oprec = static_cast<int>(p); 446 } 447 setResidualFileName(const std::string & o)448 void SchemeBase::setResidualFileName(const std::string& o) { 449 tfel::raise_if(!this->residualFileName.empty(), 450 "SchemeBase::setResidualFileName : " 451 "residual file name already defined"); 452 this->residualFileName = o; 453 } 454 isResidualFileNameDefined() const455 bool SchemeBase::isResidualFileNameDefined() const { 456 return !this->residualFileName.empty(); 457 } 458 setResidualFilePrecision(const unsigned int p)459 void SchemeBase::setResidualFilePrecision(const unsigned int p) { 460 tfel::raise_if(this->rprec != -1, 461 "SchemeBase::setResidualFileName: " 462 "residual file precision already defined"); 463 this->rprec = static_cast<int>(p); 464 } 465 setXMLOutputFileName(const std::string & o)466 void SchemeBase::setXMLOutputFileName(const std::string& o) { 467 tfel::raise_if(!this->xmlFileName.empty(), 468 "SchemeBase::setXMLOutputFileName : " 469 "XMLOutput file name already defined"); 470 this->xmlFileName = o; 471 } 472 isXMLOutputFileNameDefined() const473 bool SchemeBase::isXMLOutputFileNameDefined() const { 474 return !this->xmlFileName.empty(); 475 } 476 getXMLOutputFileName() const477 std::string SchemeBase::getXMLOutputFileName() const { 478 tfel::raise_if(this->xmlFileName.empty(), 479 "SchemeBase::getXMLOutputFileName : " 480 "XML output file name not defined"); 481 return this->xmlFileName; 482 } 483 484 SchemeBase::~SchemeBase() = default; 485 486 } // end of namespace mtest 487