void FunctionParserUtils::addFParserConstants(ADFunctionPtr & parser, const std::vector<std::string> & constant_names, const std::vector<std::string> & constant_expressions) { // check constant vectors unsigned int nconst = constant_expressions.size(); if (nconst != constant_expressions.size()) mooseError("The parameter vectors constant_names and constant_values must have equal length."); // previously evaluated constant_expressions may be used in following constant_expressions std::vector<Real> constant_values(nconst); for (unsigned int i = 0; i < nconst; ++i) { ADFunctionPtr expression = ADFunctionPtr(new ADFunction()); // set FParser internal feature flags setParserFeatureFlags(expression); // add previously evaluated constants for (unsigned int j = 0; j < i; ++j) if (!expression->AddConstant(constant_names[j], constant_values[j])) mooseError("Invalid constant name in ParsedMaterialHelper"); // build the temporary comnstant expression function if (expression->Parse(constant_expressions[i], "") >= 0) mooseError("Invalid constant expression\n", constant_expressions[i], "\n in parsed function object.\n", expression->ErrorMsg()); constant_values[i] = expression->Eval(NULL); if (!parser->AddConstant(constant_names[i], constant_values[i])) mooseError("Invalid constant name in parsed function object"); } }
ParsedGenerateSideset::ParsedGenerateSideset(const InputParameters & parameters) : SideSetsGeneratorBase(parameters), FunctionParserUtils(parameters), _input(getMesh("input")), _function(parameters.get<std::string>("combinatorial_geometry")), _sideset_name(getParam<BoundaryName>("new_sideset_name")), _check_subdomains(isParamValid("included_subdomain_ids")), _check_normal(parameters.isParamSetByUser("normal")), _included_ids(_check_subdomains ? parameters.get<std::vector<SubdomainID>>("included_subdomain_ids") : std::vector<SubdomainID>()), _normal(getParam<Point>("normal")) { if (typeid(_input).name() == typeid(std::unique_ptr<DistributedMesh>).name()) mooseError("GenerateAllSideSetsByNormals only works with ReplicatedMesh."); // base function object _func_F = ADFunctionPtr(new ADFunction()); // set FParser internal feature flags setParserFeatureFlags(_func_F); // add the constant expressions addFParserConstants(_func_F, getParam<std::vector<std::string>>("constant_names"), getParam<std::vector<std::string>>("constant_expressions")); // parse function if (_func_F->Parse(_function, "x,y,z") >= 0) mooseError("Invalid function\n", _function, "\nin ParsedAddSideset ", name(), ".\n", _func_F->ErrorMsg()); _func_params.resize(3); }
ParsedODEKernel::ParsedODEKernel(const InputParameters & parameters) : ODEKernel(parameters), FunctionParserUtils(parameters), _function(getParam<std::string>("function")), _nargs(coupledScalarComponents("args")), _args(_nargs), _arg_names(_nargs), _func_dFdarg(_nargs), _number_of_nl_variables(_sys.nVariables()), _arg_index(_number_of_nl_variables, -1) { // build variables argument (start with variable the kernel is operating on) std::string variables = _var.name(); // add additional coupled variables for (unsigned int i = 0; i < _nargs; ++i) { _arg_names[i] = getScalarVar("args", i)->name(); variables += "," + _arg_names[i]; _args[i] = &coupledScalarValue("args", i); // populate number -> arg index lookup table skipping aux variables unsigned int number = coupledScalar("args", i); if (number < _number_of_nl_variables) _arg_index[number] = i; } // base function object _func_F = ADFunctionPtr(new ADFunction()); // set FParser interneal feature flags setParserFeatureFlags(_func_F); // add the constant expressions addFParserConstants(_func_F, getParam<std::vector<std::string>>("constant_names"), getParam<std::vector<std::string>>("constant_expressions")); // parse function if (_func_F->Parse(_function, variables) >= 0) mooseError("Invalid function\n", _function, "\nin ParsedODEKernel ", name(), ".\n", _func_F->ErrorMsg()); // on-diagonal derivative _func_dFdu = ADFunctionPtr(new ADFunction(*_func_F)); if (_func_dFdu->AutoDiff(_var.name()) != -1) mooseError("Failed to take first derivative w.r.t. ", _var.name()); // off-diagonal derivatives for (unsigned int i = 0; i < _nargs; ++i) { _func_dFdarg[i] = ADFunctionPtr(new ADFunction(*_func_F)); if (_func_dFdarg[i]->AutoDiff(_arg_names[i]) != -1) mooseError("Failed to take first derivative w.r.t. ", _arg_names[i]); } // optimize if (!_disable_fpoptimizer) { _func_F->Optimize(); _func_dFdu->Optimize(); for (unsigned int i = 0; i < _nargs; ++i) _func_dFdarg[i]->Optimize(); } // just-in-time compile if (_enable_jit) { _func_F->JITCompile(); _func_dFdu->JITCompile(); for (unsigned int i = 0; i < _nargs; ++i) _func_dFdarg[i]->JITCompile(); } // reserve storage for parameter passing buffer _func_params.resize(_nargs + 1); }
void ParsedMaterialHelper::functionParse(const std::string & function_expression, const std::vector<std::string> & constant_names, const std::vector<std::string> & constant_expressions, const std::vector<std::string> & mat_prop_expressions, const std::vector<std::string> & tol_names, const std::vector<Real> & tol_values) { // build base function object _func_F = ADFunctionPtr(new ADFunction()); // set FParser internal feature flags setParserFeatureFlags(_func_F); // initialize constants addFParserConstants(_func_F, constant_names, constant_expressions); // add further constants coming from default value coupling if (_map_mode == USE_PARAM_NAMES) for (const auto & acd : _arg_constant_defaults) if (!_func_F->AddConstant(acd, _pars.defaultCoupledValue(acd))) mooseError("Invalid constant name in parsed function object"); // set variable names based on map_mode switch (_map_mode) { case USE_MOOSE_NAMES: for (unsigned int i = 0; i < _nargs; ++i) _variable_names[i] = _arg_names[i]; break; case USE_PARAM_NAMES: // we do not allow vector coupling in this mode if (!_mapping_is_unique) mooseError("Derivative parsed materials must couple exactly one non-linear variable per " "coupled variable input parameter."); for (unsigned i = 0; i < _nargs; ++i) _variable_names[i] = _arg_param_names[i]; break; default: mooseError("Unnknown variable mapping mode."); } // tolerance vectors if (tol_names.size() != tol_values.size()) mooseError("The parameter vectors tol_names and tol_values must have equal length."); // set tolerances _tol.resize(_nargs); for (unsigned int i = 0; i < _nargs; ++i) { _tol[i] = -1.0; // for every argument look through the entire tolerance vector to find a match for (auto j = beginIndex(tol_names); j < tol_names.size(); ++j) if (_variable_names[i] == tol_names[j]) { _tol[i] = tol_values[j]; break; } } // build 'variables' argument for fparser std::string variables; for (unsigned i = 0; i < _nargs; ++i) variables += "," + _variable_names[i]; // get all material properties unsigned int nmat_props = mat_prop_expressions.size(); _mat_prop_descriptors.resize(nmat_props); for (unsigned int i = 0; i < nmat_props; ++i) { // parse the material property parameter entry into a FunctionMaterialPropertyDescriptor _mat_prop_descriptors[i] = FunctionMaterialPropertyDescriptor(mat_prop_expressions[i], this); // get the fparser symbol name for the new material property variables += "," + _mat_prop_descriptors[i].getSymbolName(); } // erase leading comma variables.erase(0, 1); // build the base function if (_func_F->Parse(function_expression, variables) >= 0) mooseError("Invalid function\n", function_expression, '\n', variables, "\nin ParsedMaterialHelper.\n", _func_F->ErrorMsg()); // create parameter passing buffer _func_params.resize(_nargs + nmat_props); // perform next steps (either optimize or take derivatives and then optimize) functionsPostParse(); }