/** \param config ConfigTree object which contains the input data including <type>vanGenuchten</type> and it has a tag of <capillary_pressure> */ static std::unique_ptr<CapillaryPressureSaturation> createVanGenuchten( BaseLib::ConfigTree const& config) { //! \ogs_file_param{material_property__porous_medium__porous_medium__capillary_pressure__type} config.checkConfigParameter("type", "vanGenuchten"); //! \ogs_file_param{material_property__porous_medium__porous_medium__capillary_pressure__vanGenuchten__pd} const double pd = config.getConfigParameter<double>("pd"); //! \ogs_file_param{material_property__porous_medium__porous_medium__capillary_pressure__vanGenuchten__sr} const double Sr = config.getConfigParameter<double>("sr"); //! \ogs_file_param{material_property__porous_medium__porous_medium__capillary_pressure__vanGenuchten__smax} const double Smax = config.getConfigParameter<double>("smax"); //! \ogs_file_param{material_property__porous_medium__porous_medium__capillary_pressure__vanGenuchten__m} const double m = config.getConfigParameter<double>("m"); if (m > 1.0) // m <= 1 { OGS_FATAL( "The exponent parameter of van Genuchten capillary pressure " "saturation model, m, must be in an interval of [0, 1]"); } //! \ogs_file_param{material_property__porous_medium__porous_medium__capillary_pressure__vanGenuchten__pc_max} const double Pc_max = config.getConfigParameter<double>("pc_max"); return std::unique_ptr<CapillaryPressureSaturation>( new VanGenuchtenCapillaryPressureSaturation(pd, Sr, Smax, m, Pc_max)); }
std::unique_ptr<ConvergenceCriterionPerComponentDeltaX> createConvergenceCriterionPerComponentDeltaX(const BaseLib::ConfigTree& config) { //! \ogs_file_param{prj__time_loop__processes__process__convergence_criterion__type} config.checkConfigParameter("type", "PerComponentDeltaX"); auto abstols = //! \ogs_file_param{prj__time_loop__processes__process__convergence_criterion__PerComponentDeltaX__abstols} config.getConfigParameterOptional<std::vector<double>>("abstols"); auto reltols = //! \ogs_file_param{prj__time_loop__processes__process__convergence_criterion__PerComponentDeltaX__reltols} config.getConfigParameterOptional<std::vector<double>>("reltols"); auto const norm_type_str = //! \ogs_file_param{prj__time_loop__processes__process__convergence_criterion__PerComponentDeltaX__norm_type} config.getConfigParameter<std::string>("norm_type"); if ((!abstols) && (!reltols)) OGS_FATAL( "At least one of absolute or relative tolerance has to be " "specified."); if (!abstols) { abstols = std::vector<double>(reltols->size()); } else if (!reltols) { reltols = std::vector<double>(abstols->size()); } auto const norm_type = MathLib::convertStringToVecNormType(norm_type_str); if (norm_type == MathLib::VecNormType::INVALID) OGS_FATAL("Unknown vector norm type `%s'.", norm_type_str.c_str()); return std::unique_ptr<ConvergenceCriterionPerComponentDeltaX>( new ConvergenceCriterionPerComponentDeltaX( std::move(*abstols), std::move(*reltols), norm_type)); }
std::unique_ptr<DirichletBoundaryCondition> createDirichletBoundaryCondition( BaseLib::ConfigTree const& config, MeshLib::Mesh const& bc_mesh, NumLib::LocalToGlobalIndexMap const& dof_table_bulk, int const variable_id, int const component_id, const std::vector<std::unique_ptr<ProcessLib::ParameterBase>>& parameters) { DBUG("Constructing DirichletBoundaryCondition from config."); //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__type} config.checkConfigParameter("type", "Dirichlet"); //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__Dirichlet__parameter} auto const param_name = config.getConfigParameter<std::string>("parameter"); DBUG("Using parameter %s", param_name.c_str()); auto& param = findParameter<double>(param_name, parameters, 1); // In case of partitioned mesh the boundary could be empty, i.e. there is no // boundary condition. #ifdef USE_PETSC // This can be extracted to createBoundaryCondition() but then the config // parameters are not read and will cause an error. // TODO (naumov): Add a function to ConfigTree for skipping the tags of the // subtree and move the code up in createBoundaryCondition(). if (bc_mesh.getDimension() == 0 && bc_mesh.getNumberOfNodes() == 0 && bc_mesh.getNumberOfElements() == 0) { return nullptr; } #endif // USE_PETSC return std::make_unique<DirichletBoundaryCondition>( param, bc_mesh, dof_table_bulk, variable_id, component_id); }
std::unique_ptr<RobinBoundaryCondition> createRobinBoundaryCondition( BaseLib::ConfigTree const& config, std::vector<MeshLib::Element*>&& elements, NumLib::LocalToGlobalIndexMap const& dof_table, int const variable_id, int const component_id, bool is_axially_symmetric, unsigned const integration_order, unsigned const global_dim, std::vector<std::unique_ptr<ParameterBase>> const& parameters) { DBUG("Constructing RobinBcConfig from config."); //! \ogs_file_param{boundary_condition__type} config.checkConfigParameter("type", "Robin"); //! \ogs_file_param{boundary_condition__Robin__alpha} auto const alpha_name = config.getConfigParameter<std::string>("alpha"); //! \ogs_file_param{boundary_condition__Robin__u_0} auto const u_0_name = config.getConfigParameter<std::string>("u_0"); auto const& alpha = findParameter<double>(alpha_name, parameters, 1); auto const& u_0 = findParameter<double>(u_0_name, parameters, 1); return std::unique_ptr<RobinBoundaryCondition>(new RobinBoundaryCondition( is_axially_symmetric, integration_order, dof_table, variable_id, component_id, global_dim, std::move(elements), RobinBoundaryConditionData{alpha, u_0})); }
/** \param config ConfigTree object which contains the input data including `<type>NonWettingPhaseVanGenuchten</type>` and it has a tag of `<relative_permeability>` */ std::unique_ptr<RelativePermeability> createNonWettingPhaseVanGenuchten( BaseLib::ConfigTree const& config) { //! \ogs_file_param{material__porous_medium__relative_permeability__type} config.checkConfigParameter("type", "NonWettingPhaseVanGenuchten"); //! \ogs_file_param{material__porous_medium__relative_permeability__NonWettingPhaseVanGenuchten__sr} const auto Sr = config.getConfigParameter<double>("sr"); //! \ogs_file_param{material__porous_medium__relative_permeability__NonWettingPhaseVanGenuchten__smax} const auto Smax = config.getConfigParameter<double>("smax"); //! \ogs_file_param{material__porous_medium__relative_permeability__NonWettingPhaseVanGenuchten__m} const auto m = config.getConfigParameter<double>("m"); if (m < 0. || m > 1.0) { OGS_FATAL( "The exponent parameter of NonWettingPhaseVanGenuchten relative\n" " permeability model, m, must be in an interval of [0, 1]"); } //! \ogs_file_param{material__porous_medium__relative_permeability__NonWettingPhaseVanGenuchten__krel_min} const auto krel_min = config.getConfigParameter<double>("krel_min"); return std::make_unique<NonWettingPhaseVanGenuchten>(Sr, Smax, m, krel_min); }
std::unique_ptr<Process> createHeatConductionProcess( MeshLib::Mesh& mesh, std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler, std::vector<ProcessVariable> const& variables, std::vector<std::unique_ptr<ParameterBase>> const& parameters, unsigned const integration_order, BaseLib::ConfigTree const& config) { //! \ogs_file_param{process__type} config.checkConfigParameter("type", "HEAT_CONDUCTION"); DBUG("Create HeatConductionProcess."); // Process variable. auto process_variables = findProcessVariables( variables, config, {//! \ogs_file_param_special{process__HEAT_CONDUCTION__process_variables__process_variable} "process_variable"}); // thermal conductivity parameter. auto& thermal_conductivity = findParameter<double>( config, //! \ogs_file_param_special{process__HEAT_CONDUCTION__thermal_conductivity} "thermal_conductivity", parameters, 1); DBUG("Use \'%s\' as thermal conductivity parameter.", thermal_conductivity.name.c_str()); // heat capacity parameter. auto& heat_capacity = findParameter<double>( config, //! \ogs_file_param_special{process__HEAT_CONDUCTION__heat_capacity} "heat_capacity", parameters, 1); DBUG("Use \'%s\' as heat capacity parameter.", heat_capacity.name.c_str()); // density parameter. auto& density = findParameter<double>( config, //! \ogs_file_param_special{process__HEAT_CONDUCTION__density} "density", parameters, 1); DBUG("Use \'%s\' as density parameter.", density.name.c_str()); HeatConductionProcessData process_data{thermal_conductivity, heat_capacity, density}; SecondaryVariableCollection secondary_variables; NumLib::NamedFunctionCaller named_function_caller( {"HeatConduction_temperature"}); ProcessLib::parseSecondaryVariables(config, secondary_variables, named_function_caller); return std::unique_ptr<Process>{new HeatConductionProcess{ mesh, std::move(jacobian_assembler), parameters, integration_order, std::move(process_variables), std::move(process_data), std::move(secondary_variables), std::move(named_function_caller)}}; }
std::unique_ptr<ParameterBase> createCurveScaledParameter( std::string const& name, BaseLib::ConfigTree const& config, std::map<std::string, std::unique_ptr<MathLib::PiecewiseLinearInterpolation>> const& curves) { //! \ogs_file_param{prj__parameters__parameter__type} config.checkConfigParameter("type", "CurveScaled"); //! \ogs_file_param{prj__parameters__parameter__CurveScaled__curve} auto curve_name = config.getConfigParameter<std::string>("curve"); DBUG("Using curve %s", curve_name.c_str()); auto const curve_it = curves.find(curve_name); if (curve_it == curves.end()) OGS_FATAL("Curve `%s' does not exists.", curve_name.c_str()); auto referenced_parameter_name = //! \ogs_file_param{prj__parameters__parameter__CurveScaled__parameter} config.getConfigParameter<std::string>("parameter"); DBUG("Using parameter %s", referenced_parameter_name.c_str()); // TODO other data types than only double return std::make_unique<CurveScaledParameter<double>>( name, *curve_it->second, referenced_parameter_name); }
std::unique_ptr<ParameterBase> createMeshElementParameter( BaseLib::ConfigTree const& config, MeshLib::Mesh const& mesh) { //! \ogs_file_param{parameter__type} config.checkConfigParameter("type", "MeshElement"); //! \ogs_file_param{parameter__MeshElement__field_name} auto const field_name = config.getConfigParameter<std::string>("field_name"); DBUG("Using field_name %s", field_name.c_str()); if (!mesh.getProperties().hasPropertyVector(field_name)) { OGS_FATAL("The required property %s does not exists in the mesh.", field_name.c_str()); } // TODO other data types than only double auto const& property = mesh.getProperties().getPropertyVector<double>(field_name); if (!property) { OGS_FATAL("The mesh property `%s' is not of the requested type.", field_name.c_str()); } if (property->getMeshItemType() != MeshLib::MeshItemType::Cell) { OGS_FATAL("The mesh property `%s' is not an element property.", field_name.c_str()); } return std::unique_ptr<ParameterBase>( new MeshElementParameter<double>(*property)); }
std::unique_ptr<PythonBoundaryCondition> createPythonBoundaryCondition( BaseLib::ConfigTree const& config, MeshLib::Mesh const& boundary_mesh, NumLib::LocalToGlobalIndexMap const& dof_table, std::size_t bulk_mesh_id, int const variable_id, int const component_id, unsigned const integration_order, unsigned const shapefunction_order, unsigned const global_dim) { //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__type} config.checkConfigParameter("type", "Python"); //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__Python__bc_object} auto const bc_object = config.getConfigParameter<std::string>("bc_object"); //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__Python__flush_stdout} auto const flush_stdout = config.getConfigParameter("flush_stdout", false); // Evaluate Python code in scope of main module pybind11::object scope = pybind11::module::import("__main__").attr("__dict__"); if (!scope.contains(bc_object)) OGS_FATAL( "Function `%s' is not defined in the python script file, or there " "was no python script file specified.", bc_object.c_str()); auto* bc = scope[bc_object.c_str()] .cast<PythonBoundaryConditionPythonSideInterface*>(); if (variable_id >= static_cast<int>(dof_table.getNumberOfVariables()) || component_id >= dof_table.getNumberOfVariableComponents(variable_id)) { OGS_FATAL( "Variable id or component id too high. Actual values: (%d, %d), " "maximum values: (%d, %d).", variable_id, component_id, dof_table.getNumberOfVariables(), dof_table.getNumberOfVariableComponents(variable_id)); } // In case of partitioned mesh the boundary could be empty, i.e. there is no // boundary condition. #ifdef USE_PETSC // This can be extracted to createBoundaryCondition() but then the config // parameters are not read and will cause an error. // TODO (naumov): Add a function to ConfigTree for skipping the tags of the // subtree and move the code up in createBoundaryCondition(). if (boundary_mesh.getDimension() == 0 && boundary_mesh.getNumberOfNodes() == 0 && boundary_mesh.getNumberOfElements() == 0) { return nullptr; } #endif // USE_PETSC return std::make_unique<PythonBoundaryCondition>( PythonBoundaryConditionData{ bc, dof_table, bulk_mesh_id, dof_table.getGlobalComponent(variable_id, component_id), boundary_mesh}, integration_order, shapefunction_order, global_dim, flush_stdout); }
/** \param config ConfigTree object which contains the input data including <type>BrookCorey</type> and it has a tag of <capillary_pressure> */ static std::unique_ptr<CapillaryPressureSaturation> createBrookCorey( BaseLib::ConfigTree const& config) { //! \ogs_file_param{material_property__porous_medium__porous_medium__capillary_pressure__type} config.checkConfigParameter("type", "BrookCorey"); //! \ogs_file_param{material_property__porous_medium__porous_medium__capillary_pressure__BrookCorey__pd} const double pd = config.getConfigParameter<double>("pd"); //! \ogs_file_param{material_property__porous_medium__porous_medium__capillary_pressure__BrookCorey__sr} const double Sr = config.getConfigParameter<double>("sr"); //! \ogs_file_param{material_property__porous_medium__porous_medium__capillary_pressure__BrookCorey__smax} const double Smax = config.getConfigParameter<double>("smax"); //! \ogs_file_param{material_property__porous_medium__porous_medium__capillary_pressure__BrookCorey__m} const double m = config.getConfigParameter<double>("m"); if (m < 1.0) // m >= 1 { OGS_FATAL( "The exponent parameter of BrookCorey capillary pressure " "saturation model, m, must not be smaller than 1"); } //! \ogs_file_param{material_property__porous_medium__porous_medium__capillary_pressure__BrookCorey__pc_max} const double Pc_max = config.getConfigParameter<double>("pc_max"); return std::unique_ptr<CapillaryPressureSaturation>( new BrookCoreyCapillaryPressureSaturation(pd, Sr, Smax, m, Pc_max)); }
/** \param config ConfigTree object which contains the input data including `<type>NonWettingPhaseBrooksCoreyOilGas</type>` and it has a tag of `<relative_permeability>` */ std::unique_ptr<RelativePermeability> createNonWettingPhaseBrooksCoreyOilGas( BaseLib::ConfigTree const& config) { //! \ogs_file_param{material__porous_medium__relative_permeability__type} config.checkConfigParameter("type", "NonWettingPhaseBrooksCoreyOilGas"); //! \ogs_file_param{material__porous_medium__relative_permeability__NonWettingPhaseBrooksCoreyOilGas__sr} const auto Sr = config.getConfigParameter<double>("sr"); //! \ogs_file_param{material__porous_medium__relative_permeability__NonWettingPhaseBrooksCoreyOilGas__smax} const auto Smax = config.getConfigParameter<double>("smax"); //! \ogs_file_param{material__porous_medium__relative_permeability__NonWettingPhaseBrooksCoreyOilGas__m} const auto m = config.getConfigParameter<double>("m"); if (m < 1.0) // m >= 1 { OGS_FATAL( "The exponent parameter of NonWettingPhaseBrooksCoreyOilGas\n" "relative permeability model, m, must not be smaller than 1"); } //! \ogs_file_param{material__porous_medium__relative_permeability__NonWettingPhaseBrooksCoreyOilGas__krel_min} const auto krel_min = config.getConfigParameter<double>("krel_min"); return std::make_unique<NonWettingPhaseBrooksCoreyOilGas>( Sr, Smax, m, krel_min); }
std::unique_ptr<Process> createGroundwaterFlowProcess( MeshLib::Mesh& mesh, Process::NonlinearSolver& nonlinear_solver, std::unique_ptr<Process::TimeDiscretization>&& time_discretization, std::vector<ProcessVariable> const& variables, std::vector<std::unique_ptr<ParameterBase>> const& parameters, BaseLib::ConfigTree const& config) { //! \ogs_file_param{process__type} config.checkConfigParameter("type", "GROUNDWATER_FLOW"); DBUG("Create GroundwaterFlowProcess."); // Process variable. auto process_variables = findProcessVariables( variables, config, {//! \ogs_file_param_special{process__GROUNDWATER_FLOW__process_variables__process_variable} "process_variable"}); // Hydraulic conductivity parameter. auto& hydraulic_conductivity = findParameter<double, MeshLib::Element const&>( config, //! \ogs_file_param_special{process__GROUNDWATER_FLOW__hydraulic_conductivity} "hydraulic_conductivity", parameters); DBUG("Use \'%s\' as hydraulic conductivity parameter.", hydraulic_conductivity.name.c_str()); GroundwaterFlowProcessData process_data{hydraulic_conductivity}; SecondaryVariableCollection secondary_variables{ //! \ogs_file_param{process__secondary_variables} config.getConfigSubtreeOptional("secondary_variables"), {//! \ogs_file_param_special{process__GROUNDWATER_FLOW__secondary_variables__darcy_velocity_x} "darcy_velocity_x", //! \ogs_file_param_special{process__GROUNDWATER_FLOW__secondary_variables__darcy_velocity_y} "darcy_velocity_y", //! \ogs_file_param_special{process__GROUNDWATER_FLOW__secondary_variables__darcy_velocity_z} "darcy_velocity_z"}}; ProcessOutput //! \ogs_file_param{process__output} process_output{config.getConfigSubtree("output"), process_variables, secondary_variables}; return std::unique_ptr<Process>{new GroundwaterFlowProcess{ mesh, nonlinear_solver, std::move(time_discretization), std::move(process_variables), std::move(process_data), std::move(secondary_variables), std::move(process_output)}}; }
std::unique_ptr<PhaseFieldIrreversibleDamageOracleBoundaryCondition> createPhaseFieldIrreversibleDamageOracleBoundaryCondition( BaseLib::ConfigTree const& config, NumLib::LocalToGlobalIndexMap const& dof_table, MeshLib::Mesh const& mesh, int const variable_id, int const component_id) { DBUG( "Constructing PhaseFieldIrreversibleDamageOracleBoundaryCondition from " "config."); //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__type} config.checkConfigParameter( "type", "PhaseFieldIrreversibleDamageOracleBoundaryCondition"); return std::make_unique< PhaseFieldIrreversibleDamageOracleBoundaryCondition>( dof_table, mesh, variable_id, component_id); }
std::unique_ptr<RelativePermeability> createRelativePermeabilityModel( BaseLib::ConfigTree const& config) { //! \ogs_file_param{material__porous_medium__relative_permeability__type} auto const type = config.peekConfigParameter<std::string>("type"); if (type == "WettingPhaseVanGenuchten") { return createWettingPhaseVanGenuchten(config); } if (type == "NonWettingPhaseVanGenuchten") { return createNonWettingPhaseVanGenuchten(config); } if (type == "WettingPhaseBrooksCoreyOilGas") { return createWettingPhaseBrooksCoreyOilGas(config); } if (type == "NonWettingPhaseBrooksCoreyOilGas") { return createNonWettingPhaseBrooksCoreyOilGas(config); } if (type == "Curve") { //! \ogs_file_param{material__porous_medium__relative_permeability__type} config.checkConfigParameter("type", "Curve"); //! \ogs_file_param{material__porous_medium__relative_permeability__Curve__curve} auto const& curve_config = config.getConfigSubtree("curve"); auto curve = MathLib::createPiecewiseLinearCurve<MathLib ::PiecewiseLinearInterpolation>(curve_config); return std::make_unique<RelativePermeabilityCurve>(std::move(curve)); } OGS_FATAL( "The relative permeability model %s is unavailable.\n" "The available models are:" "\n\tWettingPhaseVanGenuchten," "\n\tNonWettingPhaseVanGenuchten," "\n\tWettingPhaseBrooksCoreyOilGas," "\n\tNonWettingPhaseBrooksCoreyOilGas,", "\n\tCurve.\n", type.data()); }
std::unique_ptr<NodalSourceTerm> createNodalSourceTerm( BaseLib::ConfigTree const& config, const NumLib::LocalToGlobalIndexMap& dof_table, std::size_t const mesh_id, std::size_t const node_id, const int variable_id, const int component_id, std::vector<std::unique_ptr<ProcessLib::ParameterBase>> const& parameters) { DBUG("Constructing NodalSourceTerm from config."); //! \ogs_file_param{prj__process_variables__process_variable__source_terms__source_term__type} config.checkConfigParameter("type", "Nodal"); //! \ogs_file_param{prj__process_variables__process_variable__source_terms__source_term__Nodal__parameter} auto const param_name = config.getConfigParameter<std::string>("parameter"); DBUG("Using parameter %s as nodal source term.", param_name.c_str()); auto& param = findParameter<double>(param_name, parameters, 1); return std::make_unique<NodalSourceTerm>( dof_table, mesh_id, node_id, variable_id, component_id, param); }
std::unique_ptr<FractureModelBase<DisplacementDim>> createMohrCoulomb( std::vector<std::unique_ptr<ProcessLib::ParameterBase>> const& parameters, BaseLib::ConfigTree const& config) { //! \ogs_file_param{material__fracture_model__type} config.checkConfigParameter("type", "MohrCoulomb"); DBUG("Create MohrCoulomb material"); auto& Kn = ProcessLib::findParameter<double>( //! \ogs_file_param_special{material__fracture_model__MohrCoulomb__normal_stiffness} config, "normal_stiffness", parameters, 1); auto& Ks = ProcessLib::findParameter<double>( //! \ogs_file_param_special{material__fracture_model__MohrCoulomb__shear_stiffness} config, "shear_stiffness", parameters, 1); auto& friction_angle = ProcessLib::findParameter<double>( //! \ogs_file_param_special{material__fracture_model__MohrCoulomb__friction_angle} config, "friction_angle", parameters, 1); auto& dilatancy_angle = ProcessLib::findParameter<double>( //! \ogs_file_param_special{material__fracture_model__MohrCoulomb__dilatancy_angle} config, "dilatancy_angle", parameters, 1); auto& cohesion = ProcessLib::findParameter<double>( //! \ogs_file_param_special{material__fracture_model__MohrCoulomb__cohesion} config, "cohesion", parameters, 1); auto const penalty_aperture_cutoff = //! \ogs_file_param{material__fracture_model__MohrCoulomb__penalty_aperture_cutoff} config.getConfigParameter<double>("penalty_aperture_cutoff"); auto const tension_cutoff = //! \ogs_file_param{material__fracture_model__MohrCoulomb__tension_cutoff} config.getConfigParameter<bool>("tension_cutoff"); typename MohrCoulomb<DisplacementDim>::MaterialProperties mp{ Kn, Ks, friction_angle, dilatancy_angle, cohesion}; return std::make_unique<MohrCoulomb<DisplacementDim>>( penalty_aperture_cutoff, tension_cutoff, mp); }
std::unique_ptr<CentralDifferencesJacobianAssembler> createCentralDifferencesJacobianAssembler(BaseLib::ConfigTree const& config) { //! \ogs_file_param{prj__processes__process__jacobian_assembler__type} config.checkConfigParameter("type", "CentralDifferences"); // TODO make non-optional. //! \ogs_file_param{prj__processes__process__jacobian_assembler__relative_epsilons} auto rel_eps = config.getConfigParameterOptional<std::vector<double>>( "relative_epsilons"); //! \ogs_file_param{prj__processes__process__jacobian_assembler__component_magnitudes} auto comp_mag = config.getConfigParameterOptional<std::vector<double>>( "component_magnitudes"); if (!!rel_eps != !!comp_mag) { OGS_FATAL( "Either both or none of <relative_epsilons> and " "<component_magnitudes> have to be specified."); } std::vector<double> abs_eps; if (rel_eps) { if (rel_eps->size() != comp_mag->size()) { OGS_FATAL( "The numbers of components of <relative_epsilons> and " "<component_magnitudes> do not match."); } abs_eps.resize(rel_eps->size()); for (std::size_t i=0; i<rel_eps->size(); ++i) { abs_eps[i] = (*rel_eps)[i] * (*comp_mag)[i]; } } else { // By default 1e-8 is used as epsilon for all components. // TODO: remove this default value. abs_eps.emplace_back(1e-8); } return std::unique_ptr<CentralDifferencesJacobianAssembler>( new CentralDifferencesJacobianAssembler(std::move(abs_eps))); }
std::unique_ptr<Process> createTESProcess( MeshLib::Mesh& mesh, std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler, std::vector<ProcessVariable> const& variables, std::vector<std::unique_ptr<ParameterBase>> const& parameters, unsigned const integration_order, BaseLib::ConfigTree const& config) { //! \ogs_file_param{prj__processes__process__type} config.checkConfigParameter("type", "TES"); DBUG("Create TESProcess."); //! \ogs_file_param{prj__processes__process__TES__process_variables} auto const pv_config = config.getConfigSubtree("process_variables"); auto per_process_variables = findProcessVariables( variables, pv_config, { //! \ogs_file_param_special{prj__processes__process__TES__process_variables__fluid_pressure} "fluid_pressure", //! \ogs_file_param_special{prj__processes__process__TES__process_variables__temperature} "temperature", //! \ogs_file_param_special{prj__processes__process__TES__process_variables__vapour_mass_fraction} "vapour_mass_fraction"}); std::vector<std::vector<std::reference_wrapper<ProcessVariable>>> process_variables; process_variables.push_back(std::move(per_process_variables)); SecondaryVariableCollection secondary_variables; NumLib::NamedFunctionCaller named_function_caller( {"TES_pressure", "TES_temperature", "TES_vapour_mass_fraction"}); ProcessLib::createSecondaryVariables(config, secondary_variables, named_function_caller); return std::make_unique<TESProcess>( mesh, std::move(jacobian_assembler), parameters, integration_order, std::move(process_variables), std::move(secondary_variables), std::move(named_function_caller), config); }
std::unique_ptr<DirichletBoundaryCondition> createDirichletBoundaryCondition( BaseLib::ConfigTree const& config, std::vector<std::size_t>&& mesh_node_ids, NumLib::LocalToGlobalIndexMap const& dof_table, std::size_t const mesh_id, int const variable_id, int const component_id, const std::vector<std::unique_ptr<ProcessLib::ParameterBase>>& parameters) { DBUG("Constructing DirichletBoundaryCondition from config."); //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__type} config.checkConfigParameter("type", "Dirichlet"); //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__Dirichlet__parameter} auto const param_name = config.getConfigParameter<std::string>("parameter"); DBUG("Using parameter %s", param_name.c_str()); auto& param = findParameter<double>(param_name, parameters, 1); return std::unique_ptr<DirichletBoundaryCondition>( new DirichletBoundaryCondition(param, std::move(mesh_node_ids), dof_table, mesh_id, variable_id, component_id)); }
std::unique_ptr<RobinBoundaryCondition> createRobinBoundaryCondition( BaseLib::ConfigTree const& config, MeshLib::Mesh const& bc_mesh, NumLib::LocalToGlobalIndexMap const& dof_table, int const variable_id, int const component_id, unsigned const integration_order, unsigned const shapefunction_order, unsigned const global_dim, std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters) { DBUG("Constructing RobinBcConfig from config."); //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__type} config.checkConfigParameter("type", "Robin"); //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__Robin__alpha} auto const alpha_name = config.getConfigParameter<std::string>("alpha"); //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__Robin__u_0} auto const u_0_name = config.getConfigParameter<std::string>("u_0"); auto const& alpha = ParameterLib::findParameter<double>(alpha_name, parameters, 1); auto const& u_0 = ParameterLib::findParameter<double>(u_0_name, parameters, 1); // In case of partitioned mesh the boundary could be empty, i.e. there is no // boundary condition. #ifdef USE_PETSC // This can be extracted to createBoundaryCondition() but then the config // parameters are not read and will cause an error. // TODO (naumov): Add a function to ConfigTree for skipping the tags of the // subtree and move the code up in createBoundaryCondition(). if (bc_mesh.getDimension() == 0 && bc_mesh.getNumberOfNodes() == 0 && bc_mesh.getNumberOfElements() == 0) { return nullptr; } #endif // USE_PETSC return std::make_unique<RobinBoundaryCondition>( integration_order, shapefunction_order, dof_table, variable_id, component_id, global_dim, bc_mesh, RobinBoundaryConditionData{alpha, u_0}); }
std::unique_ptr<LinearElasticOrthotropic<DisplacementDim>> createLinearElasticOrthotropic( std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters, boost::optional<ParameterLib::CoordinateSystem> const& local_coordinate_system, BaseLib::ConfigTree const& config, const bool skip_type_checking) { if (!skip_type_checking) { //! \ogs_file_param{material__solid__constitutive_relation__type} config.checkConfigParameter("type", "LinearElasticOrthotropic"); DBUG("Create LinearElasticOrthotropic material"); } // The three Youngs moduli are required even in two-dimensional case. Same // for the shear moduli and the Poissons ratios. auto& youngs_moduli = ParameterLib::findParameter<double>( //! \ogs_file_param_special{material__solid__constitutive_relation__LinearElasticOrthotropic__youngs_moduli} config, "youngs_moduli", parameters, 3); DBUG("Use '%s' as youngs_moduli parameter.", youngs_moduli.name.c_str()); // Shear moduli auto& shear_moduli = ParameterLib::findParameter<double>( //! \ogs_file_param_special{material__solid__constitutive_relation__LinearElasticOrthotropic__shear_moduli} config, "shear_moduli", parameters, 3); DBUG("Use '%s' as shear_moduli parameter.", shear_moduli.name.c_str()); // Poissons ratios auto& poissons_ratios = ParameterLib::findParameter<double>( //! \ogs_file_param_special{material__solid__constitutive_relation__LinearElasticOrthotropic__poissons_ratios} config, "poissons_ratios", parameters, 3); DBUG("Use '%s' as poissons_ratios parameter.", poissons_ratios.name.c_str()); typename LinearElasticOrthotropic<DisplacementDim>::MaterialProperties mp{ youngs_moduli, shear_moduli, poissons_ratios}; return std::make_unique<LinearElasticOrthotropic<DisplacementDim>>( mp, local_coordinate_system); }
std::unique_ptr<ConvergenceCriterionResidual> createConvergenceCriterionResidual(const BaseLib::ConfigTree& config) { //! \ogs_file_param{prj__time_loop__processes__process__convergence_criterion__type} config.checkConfigParameter("type", "Residual"); //! \ogs_file_param{prj__time_loop__processes__process__convergence_criterion__Residual__abstol} auto abstol = config.getConfigParameterOptional<double>("abstol"); //! \ogs_file_param{prj__time_loop__processes__process__convergence_criterion__Residual__reltol} auto reltol = config.getConfigParameterOptional<double>("reltol"); auto const norm_type_str = //! \ogs_file_param{prj__time_loop__processes__process__convergence_criterion__Residual__norm_type} config.getConfigParameter<std::string>("norm_type"); auto const norm_type = MathLib::convertStringToVecNormType(norm_type_str); if (norm_type == MathLib::VecNormType::INVALID) OGS_FATAL("Unknown vector norm type `%s'.", norm_type_str.c_str()); return std::unique_ptr<ConvergenceCriterionResidual>( new ConvergenceCriterionResidual(std::move(abstol), std::move(reltol), norm_type)); }
std::unique_ptr<FractureModelBase<DisplacementDim>> createLinearElasticIsotropic( std::vector<std::unique_ptr<ProcessLib::ParameterBase>> const& parameters, BaseLib::ConfigTree const& config) { //! \ogs_file_param{material__solid__constitutive_relation__type} config.checkConfigParameter("type", "LinearElasticIsotropic"); DBUG("Create LinearElasticIsotropic material"); auto& Kn = ProcessLib::findParameter<double>( //! \ogs_file_param_special{material__solid__constitutive_relation__LinearElasticIsotropic__normal_stiffness} config, "normal_stiffness", parameters, 1); auto& Ks = ProcessLib::findParameter<double>( //! \ogs_file_param_special{material__solid__constitutive_relation__LinearElasticIsotropic__shear_stiffness} config, "shear_stiffness", parameters, 1); typename LinearElasticIsotropic<DisplacementDim>::MaterialProperties mp{ Kn, Ks}; return std::unique_ptr<LinearElasticIsotropic<DisplacementDim>>{ new LinearElasticIsotropic<DisplacementDim>{mp}}; }
std::unique_ptr<ParameterBase> createConstantParameter( std::string const& name, BaseLib::ConfigTree const& config) { //! \ogs_file_param{prj__parameters__parameter__type} config.checkConfigParameter("type", "Constant"); // Optional case for single-component variables where the value can be used. // If the 'value' tag is found, use it and return. Otherwise continue with // then required tag 'values'. { //! \ogs_file_param{prj__parameters__parameter__Constant__value} auto const value = config.getConfigParameterOptional<double>("value"); if (value) { DBUG("Using value %g for constant parameter.", *value); return std::make_unique<ConstantParameter<double>>(name, *value); } } // Value tag not available; continue with required values tag. std::vector<double> const values = //! \ogs_file_param{prj__parameters__parameter__Constant__values} config.getConfigParameter<std::vector<double>>("values"); if (values.empty()) OGS_FATAL("No value available for constant parameter."); DBUG("Using following values for the constant parameter:"); for (double const v : values) { (void)v; // unused value if building w/o DBUG output. DBUG("\t%g", v); } return std::make_unique<ConstantParameter<double>>(name, values); }
std::unique_ptr<Process> createHydroMechanicsProcess( MeshLib::Mesh& mesh, std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler, std::vector<ProcessVariable> const& variables, std::vector<std::unique_ptr<ParameterBase>> const& parameters, unsigned const integration_order, BaseLib::ConfigTree const& config) { //! \ogs_file_param{prj__processes__process__type} config.checkConfigParameter("type", "HYDRO_MECHANICS"); DBUG("Create HydroMechanicsProcess."); // Process variable. //! \ogs_file_param{prj__processes__process__HYDRO_MECHANICS__process_variables} auto const pv_config = config.getConfigSubtree("process_variables"); auto process_variables = findProcessVariables( variables, pv_config, { //! \ogs_file_param_special{prj__processes__process__HYDRO_MECHANICS__process_variables__pressure} "pressure", //! \ogs_file_param_special{prj__processes__process__HYDRO_MECHANICS__process_variables__displacement} "displacement" }); DBUG("Associate displacement with process variable \'%s\'.", process_variables[1].get().getName().c_str()); if (process_variables[1].get().getNumberOfComponents() != DisplacementDim) { OGS_FATAL( "Number of components of the process variable '%s' is different " "from the displacement dimension: got %d, expected %d", process_variables[1].get().getName().c_str(), process_variables[1].get().getNumberOfComponents(), DisplacementDim); } DBUG("Associate pressure with process variable \'%s\'.", process_variables[0].get().getName().c_str()); if (process_variables[0].get().getNumberOfComponents() != 1) { OGS_FATAL( "Pressure process variable '%s' is not a scalar variable but has " "%d components.", process_variables[0].get().getName().c_str(), process_variables[0].get().getNumberOfComponents()); } // Constitutive relation. // read type; auto const constitutive_relation_config = //! \ogs_file_param{prj__processes__process__HYDRO_MECHANICS__constitutive_relation} config.getConfigSubtree("constitutive_relation"); auto const type = //! \ogs_file_param{prj__processes__process__HYDRO_MECHANICS__constitutive_relation__type} constitutive_relation_config.peekConfigParameter<std::string>("type"); std::unique_ptr<MaterialLib::Solids::MechanicsBase<DisplacementDim>> material = nullptr; if (type == "LinearElasticIsotropic") { material = MaterialLib::Solids::createLinearElasticIsotropic<DisplacementDim>( parameters, constitutive_relation_config); } else { OGS_FATAL( "Cannot construct constitutive relation of given type \'%s\'.", type.c_str()); } // Intrinsic permeability auto& intrinsic_permeability = findParameter<double>( config, //! \ogs_file_param_special{prj__processes__process__HYDRO_MECHANICS__intrinsic_permeability} "intrinsic_permeability", parameters, 1); DBUG("Use \'%s\' as intrinsic conductivity parameter.", intrinsic_permeability.name.c_str()); // Storage coefficient auto& specific_storage = findParameter<double>( config, //! \ogs_file_param_special{prj__processes__process__HYDRO_MECHANICS__specific_storage} "specific_storage", parameters, 1); DBUG("Use \'%s\' as storage coefficient parameter.", specific_storage.name.c_str()); // Fluid viscosity auto& fluid_viscosity = findParameter<double>( config, //! \ogs_file_param_special{prj__processes__process__HYDRO_MECHANICS__fluid_viscosity} "fluid_viscosity", parameters, 1); DBUG("Use \'%s\' as fluid viscosity parameter.", fluid_viscosity.name.c_str()); // Fluid density auto& fluid_density = findParameter<double>( config, //! \ogs_file_param_special{prj__processes__process__HYDRO_MECHANICS__fluid_density} "fluid_density", parameters, 1); DBUG("Use \'%s\' as fluid density parameter.", fluid_density.name.c_str()); // Biot coefficient auto& biot_coefficient = findParameter<double>( config, //! \ogs_file_param_special{prj__processes__process__HYDRO_MECHANICS__biot_coefficient} "biot_coefficient", parameters, 1); DBUG("Use \'%s\' as Biot coefficient parameter.", biot_coefficient.name.c_str()); // Porosity auto& porosity = findParameter<double>( config, //! \ogs_file_param_special{prj__processes__process__HYDRO_MECHANICS__porosity} "porosity", parameters, 1); DBUG("Use \'%s\' as porosity parameter.", porosity.name.c_str()); // Solid density auto& solid_density = findParameter<double>( config, //! \ogs_file_param_special{prj__processes__process__HYDRO_MECHANICS__solid_density} "solid_density", parameters, 1); DBUG("Use \'%s\' as solid density parameter.", solid_density.name.c_str()); // Specific body force Eigen::Matrix<double, DisplacementDim, 1> specific_body_force; { std::vector<double> const b = //! \ogs_file_param{prj__processes__process__HYDRO_MECHANICS__specific_body_force} config.getConfigParameter<std::vector<double>>( "specific_body_force"); if (specific_body_force.size() != DisplacementDim) OGS_FATAL( "The size of the specific body force vector does not match the " "displacement dimension. Vector size is %d, displacement " "dimension is %d", specific_body_force.size(), DisplacementDim); std::copy_n(b.data(), b.size(), specific_body_force.data()); } HydroMechanicsProcessData<DisplacementDim> process_data{ std::move(material), intrinsic_permeability, specific_storage, fluid_viscosity, fluid_density, biot_coefficient, porosity, solid_density, specific_body_force}; SecondaryVariableCollection secondary_variables; NumLib::NamedFunctionCaller named_function_caller( {"HydroMechanics_displacement"}); ProcessLib::parseSecondaryVariables(config, secondary_variables, named_function_caller); return std::unique_ptr<HydroMechanicsProcess<DisplacementDim>> { new HydroMechanicsProcess<DisplacementDim>{ mesh, std::move(jacobian_assembler), parameters, integration_order, std::move(process_variables), std::move(process_data), std::move(secondary_variables), std::move(named_function_caller) } }; }
std::unique_ptr<Process> createTwoPhaseFlowWithPPProcess( MeshLib::Mesh& mesh, std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler, std::vector<ProcessVariable> const& variables, std::vector<std::unique_ptr<ParameterBase>> const& parameters, unsigned const integration_order, BaseLib::ConfigTree const& config, std::map<std::string, std::unique_ptr<MathLib::PiecewiseLinearInterpolation>> const& curves) { //! \ogs_file_param{prj__processes__process__type} config.checkConfigParameter("type", "TWOPHASE_FLOW_PP"); DBUG("Create TwoPhaseFlowProcess with PP model."); //! \ogs_file_param{prj__processes__process__TWOPHASE_FLOW_PP__process_variables} auto const pv_config = config.getConfigSubtree("process_variables"); auto per_process_variables = findProcessVariables( variables, pv_config, {//! \ogs_file_param_special{prj__processes__process__TWOPHASE_FLOW_PP__process_variables__gas_pressure} "gas_pressure", //! \ogs_file_param_special{prj__processes__process__TWOPHASE_FLOW_PP__process_variables__capillary_pressure} "capillary_pressure"}); std::vector<std::vector<std::reference_wrapper<ProcessVariable>>> process_variables; process_variables.push_back(std::move(per_process_variables)); SecondaryVariableCollection secondary_variables; NumLib::NamedFunctionCaller named_function_caller( {"TwoPhaseFlow_pressure"}); ProcessLib::createSecondaryVariables(config, secondary_variables, named_function_caller); // Specific body force std::vector<double> const b = //! \ogs_file_param{prj__processes__process__TWOPHASE_FLOW_PP__specific_body_force} config.getConfigParameter<std::vector<double>>("specific_body_force"); assert(!b.empty() && b.size() < 4); Eigen::VectorXd specific_body_force(b.size()); bool const has_gravity = MathLib::toVector(b).norm() > 0; if (has_gravity) std::copy_n(b.data(), b.size(), specific_body_force.data()); //! \ogs_file_param{prj__processes__process__TWOPHASE_FLOW_PP__mass_lumping} auto const mass_lumping = config.getConfigParameter<bool>("mass_lumping"); auto& temperature = findParameter<double>( config, //! \ogs_file_param_special{prj__processes__process__TWOPHASE_FLOW_PP__temperature} "temperature", parameters, 1); //! \ogs_file_param{prj__processes__process__TWOPHASE_FLOW_PP__material_property} auto const& mat_config = config.getConfigSubtree("material_property"); auto const material_ids = materialIDs(mesh); if (material_ids) { INFO("The twophase flow is in heterogeneous porous media."); } else { INFO("The twophase flow is in homogeneous porous media."); } std::unique_ptr<TwoPhaseFlowWithPPMaterialProperties> material = createTwoPhaseFlowWithPPMaterialProperties(mat_config, material_ids, parameters); TwoPhaseFlowWithPPProcessData process_data{ specific_body_force, has_gravity, mass_lumping, temperature, std::move(material)}; return std::make_unique<TwoPhaseFlowWithPPProcess>( mesh, std::move(jacobian_assembler), parameters, integration_order, std::move(process_variables), std::move(process_data), std::move(secondary_variables), std::move(named_function_caller), mat_config, curves); }
std::unique_ptr<Process> createSmallDeformationProcess( MeshLib::Mesh& mesh, std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler, std::vector<ProcessVariable> const& variables, std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters, boost::optional<ParameterLib::CoordinateSystem> const& local_coordinate_system, unsigned const integration_order, BaseLib::ConfigTree const& config) { //! \ogs_file_param{prj__processes__process__type} config.checkConfigParameter("type", "SMALL_DEFORMATION_WITH_LIE"); DBUG("Create SmallDeformationProcess with LIE."); // Process variables //! \ogs_file_param{prj__processes__process__SMALL_DEFORMATION_WITH_LIE__process_variables} auto const pv_conf = config.getConfigSubtree("process_variables"); auto range = //! \ogs_file_param{prj__processes__process__SMALL_DEFORMATION_WITH_LIE__process_variables__process_variable} pv_conf.getConfigParameterList<std::string>("process_variable"); std::vector<std::reference_wrapper<ProcessVariable>> per_process_variables; std::size_t n_var_du = 0; for (std::string const& pv_name : range) { if (pv_name != "displacement" && pv_name.find("displacement_jump") != 0) { OGS_FATAL( "Found a process variable name '%s'. It should be " "'displacement' or 'displacement_jumpN' or " "'displacement_junctionN'"); } if (pv_name.find("displacement_jump") == 0) { n_var_du++; } auto variable = std::find_if(variables.cbegin(), variables.cend(), [&pv_name](ProcessVariable const& v) { return v.getName() == pv_name; }); if (variable == variables.end()) { OGS_FATAL( "Could not find process variable '%s' in the provided " "variables " "list for config tag <%s>.", pv_name.c_str(), "process_variable"); } DBUG("Found process variable '%s' for config tag <%s>.", variable->getName().c_str(), "process_variable"); per_process_variables.emplace_back( const_cast<ProcessVariable&>(*variable)); } if (n_var_du < 1) { OGS_FATAL("No displacement jump variables are specified"); } DBUG("Associate displacement with process variable '%s'.", per_process_variables.back().get().getName().c_str()); if (per_process_variables.back().get().getNumberOfComponents() != DisplacementDim) { OGS_FATAL( "Number of components of the process variable '%s' is different " "from the displacement dimension: got %d, expected %d", per_process_variables.back().get().getName().c_str(), per_process_variables.back().get().getNumberOfComponents(), DisplacementDim); } std::vector<std::vector<std::reference_wrapper<ProcessVariable>>> process_variables; process_variables.push_back(std::move(per_process_variables)); auto solid_constitutive_relations = MaterialLib::Solids::createConstitutiveRelations<DisplacementDim>( parameters, local_coordinate_system, config); // Fracture constitutive relation. // read type; auto const fracture_model_config = //! \ogs_file_param{prj__processes__process__SMALL_DEFORMATION_WITH_LIE__fracture_model} config.getConfigSubtree("fracture_model"); auto const frac_type = //! \ogs_file_param{prj__processes__process__SMALL_DEFORMATION_WITH_LIE__fracture_model__type} fracture_model_config.peekConfigParameter<std::string>("type"); std::unique_ptr<MaterialLib::Fracture::FractureModelBase<DisplacementDim>> fracture_model = nullptr; if (frac_type == "LinearElasticIsotropic") { fracture_model = MaterialLib::Fracture::createLinearElasticIsotropic< DisplacementDim>(parameters, fracture_model_config); } else if (frac_type == "MohrCoulomb") { fracture_model = MaterialLib::Fracture::createMohrCoulomb<DisplacementDim>( parameters, fracture_model_config); } else if (frac_type == "CohesiveZoneModeI") { fracture_model = MaterialLib::Fracture::CohesiveZoneModeI::createCohesiveZoneModeI< DisplacementDim>(parameters, fracture_model_config); } else { OGS_FATAL( "Cannot construct fracture constitutive relation of given type " "'%s'.", frac_type.c_str()); } // Fracture properties std::vector<FractureProperty> fracture_properties; for ( auto fracture_properties_config : //! \ogs_file_param{prj__processes__process__SMALL_DEFORMATION_WITH_LIE__fracture_properties} config.getConfigSubtreeList("fracture_properties")) { fracture_properties.emplace_back( fracture_properties.size(), //! \ogs_file_param{prj__processes__process__SMALL_DEFORMATION_WITH_LIE__fracture_properties__material_id} fracture_properties_config.getConfigParameter<int>("material_id"), ParameterLib::findParameter<double>( //! \ogs_file_param_special{prj__processes__process__SMALL_DEFORMATION_WITH_LIE__fracture_properties__initial_aperture} fracture_properties_config, "initial_aperture", parameters, 1)); } if (n_var_du < fracture_properties.size()) { OGS_FATAL( "The number of displacement jumps and the number of " "<fracture_properties> " "are not consistent"); } // Reference temperature const auto& reference_temperature = //! \ogs_file_param{prj__processes__process__SMALL_DEFORMATION_WITH_LIE__reference_temperature} config.getConfigParameter<double>( "reference_temperature", std::numeric_limits<double>::quiet_NaN()); SmallDeformationProcessData<DisplacementDim> process_data( materialIDs(mesh), std::move(solid_constitutive_relations), std::move(fracture_model), std::move(fracture_properties), reference_temperature); SecondaryVariableCollection secondary_variables; NumLib::NamedFunctionCaller named_function_caller( {"SmallDeformation_displacement"}); ProcessLib::createSecondaryVariables(config, secondary_variables, named_function_caller); return std::make_unique<SmallDeformationProcess<DisplacementDim>>( mesh, std::move(jacobian_assembler), parameters, integration_order, std::move(process_variables), std::move(process_data), std::move(secondary_variables), std::move(named_function_caller)); }
std::unique_ptr<Process> createLiquidFlowProcess( MeshLib::Mesh& mesh, std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler, std::vector<ProcessVariable> const& variables, std::vector<std::unique_ptr<ParameterBase>> const& parameters, unsigned const integration_order, BaseLib::ConfigTree const& config) { //! \ogs_file_param{process__type} config.checkConfigParameter("type", "LIQUID_FLOW"); DBUG("Create LiquidFlowProcess."); // Process variable. auto process_variables = findProcessVariables( variables, config, {//! \ogs_file_param_special{process__LIQUID_FLOW__process_variables__process_variable} "process_variable"}); SecondaryVariableCollection secondary_variables; NumLib::NamedFunctionCaller named_function_caller({"LiquidFlow_pressure"}); ProcessLib::parseSecondaryVariables(config, secondary_variables, named_function_caller); // Get the gravity vector for the Darcy velocity //! \ogs_file_param{process__LIQUID_FLOW__darcy_gravity} auto const& darcy_g_config = config.getConfigSubtree("darcy_gravity"); const int gravity_axis_id_input = //! \ogs_file_param_special{process__LIQUID_FLOW__darcy_gravity_axis_id} darcy_g_config.getConfigParameter<int>("axis_id"); assert(gravity_axis_id_input < static_cast<int>(mesh.getDimension())); const double g = //! \ogs_file_param_special{process__LIQUID_FLOW__darcy_gravity_g} darcy_g_config.getConfigParameter<double>("g"); assert(g >= 0.); const int gravity_axis_id = (g == 0.) ? -1 : gravity_axis_id_input; //! \ogs_file_param{process__LIQUID_FLOW__material_property} auto const& mat_config = config.getConfigSubtree("material_property"); auto const& mat_ids = mesh.getProperties().getPropertyVector<int>("MaterialIDs"); if (mat_ids) { INFO("The liquid flow is in heterogeneous porous media."); const bool has_material_ids = true; return std::unique_ptr<Process>{new LiquidFlowProcess{ mesh, std::move(jacobian_assembler), parameters, integration_order, std::move(process_variables), std::move(secondary_variables), std::move(named_function_caller), *mat_ids, has_material_ids, gravity_axis_id, g, mat_config}}; } else { INFO("The liquid flow is in homogeneous porous media."); MeshLib::Properties dummy_property; // For a reference argument of LiquidFlowProcess(...). auto const& dummy_property_vector = dummy_property.createNewPropertyVector<int>( "MaterialIDs", MeshLib::MeshItemType::Cell, 1); // Since dummy_property_vector is only visible in this function, // the following constant, has_material_ids, is employed to indicate // that material_ids does not exist. const bool has_material_ids = false; return std::unique_ptr<Process>{new LiquidFlowProcess{ mesh, std::move(jacobian_assembler), parameters, integration_order, std::move(process_variables), std::move(secondary_variables), std::move(named_function_caller), *dummy_property_vector, has_material_ids, gravity_axis_id, g, mat_config}}; } }
std::unique_ptr<Process> createPhaseFieldProcess( MeshLib::Mesh& mesh, std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler, std::vector<ProcessVariable> const& variables, std::vector<std::unique_ptr<ParameterBase>> const& parameters, unsigned const integration_order, BaseLib::ConfigTree const& config) { //! \ogs_file_param{prj__processes__process__type} config.checkConfigParameter("type", "PHASE_FIELD"); DBUG("Create PhaseFieldProcess."); auto const staggered_scheme = //! \ogs_file_param{prj__processes__process__PHASE_FIELD__coupling_scheme} config.getConfigParameterOptional<std::string>("coupling_scheme"); const bool use_monolithic_scheme = !(staggered_scheme && (*staggered_scheme == "staggered")); // Process variable. //! \ogs_file_param{prj__processes__process__PHASE_FIELD__process_variables} auto const pv_config = config.getConfigSubtree("process_variables"); ProcessVariable* variable_ph; ProcessVariable* variable_u; std::vector<std::vector<std::reference_wrapper<ProcessVariable>>> process_variables; if (use_monolithic_scheme) // monolithic scheme. { auto per_process_variables = findProcessVariables( variables, pv_config, {//! \ogs_file_param_special{prj__processes__process__PHASE_FIELD__process_variables__phasefield} "phasefield", //! \ogs_file_param_special{prj__processes__process__PHASE_FIELD__process_variables__displacement} "displacement"}); variable_ph = &per_process_variables[0].get(); variable_u = &per_process_variables[1].get(); process_variables.push_back(std::move(per_process_variables)); } else // staggered scheme. { using namespace std::string_literals; for (auto const& variable_name : {"phasefield"s, "displacement"s}) { auto per_process_variables = findProcessVariables(variables, pv_config, {variable_name}); process_variables.push_back(std::move(per_process_variables)); } variable_ph = &process_variables[0][0].get(); variable_u = &process_variables[1][0].get(); } DBUG("Associate displacement with process variable \'%s\'.", variable_u->getName().c_str()); if (variable_u->getNumberOfComponents() != DisplacementDim) { OGS_FATAL( "Number of components of the process variable '%s' is different " "from the displacement dimension: got %d, expected %d", variable_u->getName().c_str(), variable_u->getNumberOfComponents(), DisplacementDim); } DBUG("Associate phase field with process variable \'%s\'.", variable_ph->getName().c_str()); if (variable_ph->getNumberOfComponents() != 1) { OGS_FATAL( "Pressure process variable '%s' is not a scalar variable but has " "%d components.", variable_ph->getName().c_str(), variable_ph->getNumberOfComponents()); } // Constitutive relation. // read type; auto const constitutive_relation_config = //! \ogs_file_param{prj__processes__process__PHASE_FIELD__constitutive_relation} config.getConfigSubtree("constitutive_relation"); auto const phasefield_parameters_config = //! \ogs_file_param{prj__processes__process__PHASE_FIELD__phasefield_parameters} config.getConfigSubtree("phasefield_parameters"); auto const type = //! \ogs_file_param{prj__processes__process__PHASE_FIELD__constitutive_relation__type} constitutive_relation_config.peekConfigParameter<std::string>("type"); std::unique_ptr<MaterialLib::Solids::PhaseFieldExtension<DisplacementDim>> material = nullptr; if (type == "LinearElasticIsotropic") { auto elastic_model = MaterialLib::Solids::createLinearElasticIsotropic< DisplacementDim>(parameters, constitutive_relation_config); material = std::make_unique<MaterialLib::Solids::LinearElasticIsotropicPhaseField< DisplacementDim>>(std::move(elastic_model->getMaterialProperties())); } else { OGS_FATAL( "Cannot construct constitutive relation of given type \'%s\'.", type.c_str()); } // Residual stiffness auto& residual_stiffness = findParameter<double>( phasefield_parameters_config, //! \ogs_file_param_special{prj__processes__process__PHASE_FIELD__phasefield_parameters__residual_stiffness} "residual_stiffness", parameters, 1); DBUG("Use \'%s\' as residual stiffness.", residual_stiffness.name.c_str()); // Crack resistance auto& crack_resistance = findParameter<double>( phasefield_parameters_config, //! \ogs_file_param_special{prj__processes__process__PHASE_FIELD__phasefield_parameters__crack_resistance} "crack_resistance", parameters, 1); DBUG("Use \'%s\' as crack resistance.", crack_resistance.name.c_str()); // Crack length scale auto& crack_length_scale = findParameter<double>( phasefield_parameters_config, //! \ogs_file_param_special{prj__processes__process__PHASE_FIELD__phasefield_parameters__crack_length_scale} "crack_length_scale", parameters, 1); DBUG("Use \'%s\' as crack length scale.", crack_length_scale.name.c_str()); // Kinetic coefficient auto& kinetic_coefficient = findParameter<double>( phasefield_parameters_config, //! \ogs_file_param_special{prj__processes__process__PHASE_FIELD__phasefield_parameters__kinetic_coefficient} "kinetic_coefficient", parameters, 1); DBUG("Use \'%s\' as kinetic coefficient.", kinetic_coefficient.name.c_str()); // Solid density auto& solid_density = findParameter<double>( config, //! \ogs_file_param_special{prj__processes__process__PHASE_FIELD__solid_density} "solid_density", parameters, 1); DBUG("Use \'%s\' as solid density parameter.", solid_density.name.c_str()); // History field auto& history_field = findParameter<double>( phasefield_parameters_config, //! \ogs_file_param_special{prj__processes__process__PHASE_FIELD__phasefield_parameters__history_field} "history_field", parameters, 1); DBUG("Use \'%s\' as history field.", history_field.name.c_str()); // Specific body force Eigen::Matrix<double, DisplacementDim, 1> specific_body_force; { std::vector<double> const b = //! \ogs_file_param{prj__processes__process__PHASE_FIELD__specific_body_force} config.getConfigParameter<std::vector<double>>( "specific_body_force"); if (b.size() != DisplacementDim) OGS_FATAL( "The size of the specific body force vector does not match the " "displacement dimension. Vector size is %d, displacement " "dimension is %d", b.size(), DisplacementDim); std::copy_n(b.data(), b.size(), specific_body_force.data()); } PhaseFieldProcessData<DisplacementDim> process_data{ std::move(material), residual_stiffness, crack_resistance, crack_length_scale, kinetic_coefficient, solid_density, history_field, specific_body_force}; SecondaryVariableCollection secondary_variables; NumLib::NamedFunctionCaller named_function_caller( {"PhaseField_displacement"}); ProcessLib::createSecondaryVariables(config, secondary_variables, named_function_caller); return std::make_unique<PhaseFieldProcess<DisplacementDim>>( mesh, std::move(jacobian_assembler), parameters, integration_order, std::move(process_variables), std::move(process_data), std::move(secondary_variables), std::move(named_function_caller), use_monolithic_scheme); }
std::unique_ptr<Process> createSmallDeformationProcess( MeshLib::Mesh& mesh, std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler, std::vector<ProcessVariable> const& variables, std::vector<std::unique_ptr<ParameterBase>> const& parameters, unsigned const integration_order, BaseLib::ConfigTree const& config) { //! \ogs_file_param{process__type} config.checkConfigParameter("type", "SMALL_DEFORMATION_WITH_LIE"); DBUG("Create SmallDeformationProcess with LIE."); // Process variables auto const pv_conf = config.getConfigSubtree("process_variables"); auto range = pv_conf.getConfigParameterList<std::string>("process_variable"); std::vector<std::reference_wrapper<ProcessVariable>> process_variables; for (std::string const& pv_name : range) { if (pv_name != "displacement" && pv_name.find("displacement_jump")==std::string::npos) OGS_FATAL("Found a process variable name '%s'. It should be 'displacement' or 'displacement_jumpN'"); auto variable = std::find_if( variables.cbegin(), variables.cend(), [&pv_name](ProcessVariable const& v) { return v.getName() == pv_name; }); if (variable == variables.end()) { OGS_FATAL( "Could not find process variable '%s' in the provided variables " "list for config tag <%s>.", pv_name.c_str(), "process_variable"); } DBUG("Found process variable \'%s\' for config tag <%s>.", variable->getName().c_str(), "process_variable"); process_variables.emplace_back(const_cast<ProcessVariable&>(*variable)); } if (process_variables.size() > 2) OGS_FATAL("Currently only one displacement jump is supported"); DBUG("Associate displacement with process variable \'%s\'.", process_variables.back().get().getName().c_str()); if (process_variables.back().get().getNumberOfComponents() != DisplacementDim) { OGS_FATAL( "Number of components of the process variable '%s' is different " "from the displacement dimension: got %d, expected %d", process_variables.back().get().getName().c_str(), process_variables.back().get().getNumberOfComponents(), DisplacementDim); } // Constitutive relation. // read type; auto const constitutive_relation_config = //! \ogs_file_param{process__SMALL_DEFORMATION_WITH_LIE__constitutive_relation} config.getConfigSubtree("constitutive_relation"); auto const type = constitutive_relation_config.peekConfigParameter<std::string>("type"); std::unique_ptr<MaterialLib::Solids::MechanicsBase<DisplacementDim>> material = nullptr; if (type == "LinearElasticIsotropic") { material = MaterialLib::Solids::createLinearElasticIsotropic<DisplacementDim>( parameters, constitutive_relation_config); } else { OGS_FATAL( "Cannot construct constitutive relation of given type \'%s\'.", type.c_str()); } // Fracture constitutive relation. // read type; auto const fracture_constitutive_relation_config = //! \ogs_file_param{process__SMALL_DEFORMATION_WITH_LIE__constitutive_relation} config.getConfigSubtree("fracture_constitutive_relation"); auto const frac_type = fracture_constitutive_relation_config.peekConfigParameter<std::string>("type"); std::unique_ptr<MaterialLib::Fracture::FractureModelBase<DisplacementDim>> fracture_model = nullptr; if (frac_type == "LinearElasticIsotropic") { fracture_model = MaterialLib::Fracture::createLinearElasticIsotropic<DisplacementDim>( parameters, fracture_constitutive_relation_config); } else if (frac_type == "MohrCoulomb") { fracture_model = MaterialLib::Fracture::createMohrCoulomb<DisplacementDim>( parameters, fracture_constitutive_relation_config); } else { OGS_FATAL( "Cannot construct fracture constitutive relation of given type \'%s\'.", frac_type.c_str()); } // Fracture properties //! \ogs_file_param{process__SMALL_DEFORMATION_WITH_LIE__fracture_properties} auto fracture_properties_config = config.getConfigSubtree("fracture_properties"); auto ¶_b0 = ProcessLib::findParameter<double>(fracture_properties_config, "initial_aperture", parameters, 1); std::unique_ptr<FractureProperty> frac_prop(new FractureProperty()); frac_prop->mat_id = fracture_properties_config.getConfigParameter<int>("material_id"); frac_prop->aperture0 = ¶_b0; SmallDeformationProcessData<DisplacementDim> process_data( std::move(material), std::move(fracture_model), std::move(frac_prop)); SecondaryVariableCollection secondary_variables; NumLib::NamedFunctionCaller named_function_caller( {"SmallDeformation_displacement"}); ProcessLib::parseSecondaryVariables(config, secondary_variables, named_function_caller); return std::unique_ptr<SmallDeformationProcess<DisplacementDim>>{ new SmallDeformationProcess<DisplacementDim>{ mesh, std::move(jacobian_assembler), parameters, integration_order, std::move(process_variables), std::move(process_data), std::move(secondary_variables), std::move(named_function_caller)}}; }