IntegrationPointMetaData getIntegrationPointMetaData(MeshLib::Mesh const& mesh,
                                                     std::string const& name)
{
    if (!mesh.getProperties().existsPropertyVector<char>(
            "IntegrationPointMetaData"))
    {
        OGS_FATAL(
            "Integration point data '%s' is present in the vtk field "
            "data but the required 'IntegrationPointMetaData' array "
            "is not available.",
            name.c_str());
    }
    auto const& mesh_property_ip_meta_data =
        *mesh.getProperties().template getPropertyVector<char>(
            "IntegrationPointMetaData");

    if (mesh_property_ip_meta_data.getMeshItemType() !=
        MeshLib::MeshItemType::IntegrationPoint)
    {
        OGS_FATAL("IntegrationPointMetaData array must be field data.");
    }

    // Find the current integration point data entry and extract the
    // meta data.
    auto const ip_meta_data = extractIntegrationPointMetaData(
        json::parse(mesh_property_ip_meta_data.begin(),
                    mesh_property_ip_meta_data.end()),
        name);

    return ip_meta_data;
}
Example #2
0
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));
}
void writeToFile(std::string const& id_area_fname, std::string const& csv_fname,
    std::vector<std::pair<std::size_t, double>> const& ids_and_areas,
    std::vector<MeshLib::Node*> const& mesh_nodes)
{
    std::ofstream ids_and_area_out(id_area_fname);
    if (!ids_and_area_out) {
        OGS_FATAL("Unable to open the file \"%s\" - aborting.", id_area_fname.c_str());
    }
    std::ofstream csv_out(csv_fname);
    if (!csv_out) {
        OGS_FATAL("Unable to open the file \"%s\" - aborting.", csv_fname.c_str());
    }

    ids_and_area_out << std::setprecision(20);
    csv_out << std::setprecision(20);

    ids_and_area_out << ids_and_areas[0].first << " " << ids_and_areas[0].second;
    csv_out << "ID x y z area node_id\n"; // CSV header
    csv_out << 0 << " " << *mesh_nodes[ids_and_areas[0].first]
            << ids_and_areas[0].second << " " << ids_and_areas[0].first;
    for (std::size_t k(1); k<ids_and_areas.size(); k++) {
        ids_and_area_out << "\n"
            << ids_and_areas[k].first << " " << ids_and_areas[k].second;
        csv_out << "\n" << k << " " << *mesh_nodes[ids_and_areas[k].first]
            << ids_and_areas[k].second << " " << ids_and_areas[k].first;
    }
    ids_and_area_out << "\n";
    csv_out << "\n";
}
static void checkJacobianDeterminant(const double detJ,
                                     MeshLib::Element const& element)
{
    if (detJ > 0)  // The usual case
        return;

    if (detJ < 0)
    {
        ERR("det J = %g is negative for element %d.", detJ, element.getID());
#ifndef NDEBUG
        std::cerr << element << "\n";
#endif  // NDEBUG
        OGS_FATAL("Please check the node numbering of the element.");
    }

    if (detJ == 0)
    {
        ERR("det J is zero for element %d.", element.getID());
#ifndef NDEBUG
        std::cerr << element << "\n";
#endif  // NDEBUG
        OGS_FATAL(
            "Please check whether:\n"
            "\t the element nodes may have the same coordinates,\n"
            "\t or the coordinates of all nodes are not given on the x-axis "
            "for a 1D problem or in the xy-plane in the 2D case.");
    }
}
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);
}
Example #6
0
std::pair<std::unique_ptr<NonlinearSolverBase>, NonlinearSolverTag>
createNonlinearSolver(GlobalLinearSolver& linear_solver,
                      BaseLib::ConfigTree const& config)
{
    //! \ogs_file_param{prj__nonlinear_solvers__nonlinear_solver__type}
    auto const type = config.getConfigParameter<std::string>("type");
    //! \ogs_file_param{prj__nonlinear_solvers__nonlinear_solver__max_iter}
    auto const max_iter = config.getConfigParameter<unsigned>("max_iter");

    if (type == "Picard") {
        auto const tag = NonlinearSolverTag::Picard;
        using ConcreteNLS = NonlinearSolver<tag>;
        return std::make_pair(
            std::make_unique<ConcreteNLS>(linear_solver, max_iter), tag);
    }
    if (type == "Newton")
    {
        //! \ogs_file_param{prj__nonlinear_solvers__nonlinear_solver__damping}
        auto const damping = config.getConfigParameter<double>("damping", 1.0);
        if (damping <= 0)
        {
            OGS_FATAL(
                "The damping factor for the Newon method must be positive, got "
                "%g.",
                damping);
        }
        auto const tag = NonlinearSolverTag::Newton;
        using ConcreteNLS = NonlinearSolver<tag>;
        return std::make_pair(
            std::make_unique<ConcreteNLS>(linear_solver, max_iter, damping),
            tag);
    }
    OGS_FATAL("Unsupported nonlinear solver type");
}
Example #7
0
ConfigTreeTopLevel
makeConfigTree(const std::string& filepath, const bool be_ruthless,
               const std::string& toplevel_tag)
{
    ConfigTree::PTree ptree;

    // note: Trimming whitespace and ignoring comments is crucial in order
    //       for our configuration tree implementation to work!
    try {
        read_xml(filepath, ptree,
                 boost::property_tree::xml_parser::no_comments |
                 boost::property_tree::xml_parser::trim_whitespace);
    } catch (boost::property_tree::xml_parser_error e) {
        OGS_FATAL("Error while parsing XML file `%s' at line %lu: %s.",
                  e.filename().c_str(), e.line(), e.message().c_str());
    }

    DBUG("Project configuration from file \'%s\' read.", filepath.c_str());

    if (auto child = ptree.get_child_optional(toplevel_tag)) {
        return ConfigTreeTopLevel(filepath, be_ruthless, std::move(*child));
    } else {
        OGS_FATAL("Tag <%s> has not been found in file `%s'.",
                  toplevel_tag.c_str(), filepath.c_str());
    }
}
Example #8
0
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));
}
Example #9
0
std::unique_ptr<FluidProperty> createViscosityModel(
    BaseLib::ConfigTree const& config)
{
    //! \ogs_file_param{material__fluid__viscosity__type}
    auto const type = config.getConfigParameter<std::string>("type");

    if (type == "Constant")
        return std::unique_ptr<FluidProperty>(new ConstantFluidProperty(
            //! \ogs_file_param{material__fluid__viscosity__Constant__value}
            config.getConfigParameter<double>("value")));
    else if (type == "LinearPressure")
        return createLinearPressureDependentViscosity(config);
    else if (type == "TemperatureDependent")
        return createTemperatureDependentViscosity(config);
    else if (type == "Vogels")
    {
        INFO("Using Vogels model, which gives viscosity in SI unit, Pa s");
        auto const fluid_type =
            //! \ogs_file_param{material__fluid__viscosity__Vogels__liquid_type}
            config.getConfigParameter<std::string>("liquid_type");
        if (fluid_type == "Water")
        {
            const VogelsViscosityConstantsWater constants;
            return std::unique_ptr<FluidProperty>(
                new VogelsLiquidDynamicViscosity<VogelsViscosityConstantsWater>(
                    constants));
        }
        else if (fluid_type == "CO2")
        {
            const VogelsViscosityConstantsCO2 constants;
            return std::unique_ptr<FluidProperty>(
                new VogelsLiquidDynamicViscosity<VogelsViscosityConstantsCO2>(
                    constants));
        }
        else if (fluid_type == "CH4")
        {
            const VogelsViscosityConstantsCH4 constants;
            return std::unique_ptr<FluidProperty>(
                new VogelsLiquidDynamicViscosity<VogelsViscosityConstantsCH4>(
                    constants));
        }
        else
        {
            OGS_FATAL(
                "The fluid type %s for Vogels model is unavailable.\n"
                "The available fluid types are Water, CO2 and CH4\n",
                fluid_type.data());
        }
    }
    else
    {
        OGS_FATAL(
            "The viscosity type %s is unavailable.\n"
            "The available types are \n\tConstant, \n\tLinearPressure "
            "\n\tTemperatureDependent, \n\tVogels\n",
            type.data());
    }
}
void LocalLinearLeastSquaresExtrapolator::calculateResiduals(
    const unsigned num_components,
    ExtrapolatableElementCollection const& extrapolatables,
    const double t,
    GlobalVector const& current_solution,
    LocalToGlobalIndexMap const& dof_table)
{
    auto const num_element_dof_result = static_cast<GlobalIndexType>(
        _dof_table_single_component.size() * num_components);

    if (!_residuals || _residuals->size() != num_element_dof_result)
    {
#ifndef USE_PETSC
        _residuals.reset(new GlobalVector{num_element_dof_result});
#else
        _residuals.reset(new GlobalVector{num_element_dof_result, false});
#endif
    }

    if (static_cast<std::size_t>(num_element_dof_result) !=
        extrapolatables.size() * num_components)
    {
        OGS_FATAL("mismatch in number of D.o.F.");
    }

    auto const size = extrapolatables.size();
    for (std::size_t i = 0; i < size; ++i)
    {
        calculateResidualElement(i, num_components, extrapolatables, t,
                                 current_solution, dof_table);
    }
    MathLib::LinAlg::finalizeAssembly(*_residuals);
}
Example #11
0
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);
}
MeshLib::Element* BoundaryElementsAlongPolyline::modifyEdgeNodeOrdering(
    const MeshLib::Element& edge, const GeoLib::Polyline& ply,
    const std::vector<std::size_t>& edge_node_distances_along_ply,
    const std::vector<std::size_t>& node_ids_on_poly) const
{
    // The first node of the edge should be always closer to the beginning of
    // the polyline than other nodes.
    if (edge_node_distances_along_ply.front() >
            edge_node_distances_along_ply.back() ||
        (ply.isClosed() &&
         edge_node_distances_along_ply.back() == node_ids_on_poly.size() - 1))
    {  // Create a new element with reversed local node index
        auto new_nodes = new MeshLib::Node*[edge.getNumberOfNodes()];
        if (auto const* e = dynamic_cast<MeshLib::Line const*>(&edge))
        {
            new_nodes[0] = const_cast<MeshLib::Node*>(e->getNode(1));
            new_nodes[1] = const_cast<MeshLib::Node*>(e->getNode(0));
        }
        else if (auto const* e = dynamic_cast<MeshLib::Line3 const*>(&edge))
        {
            new_nodes[0] = const_cast<MeshLib::Node*>(e->getNode(1));
            new_nodes[1] = const_cast<MeshLib::Node*>(e->getNode(0));
            new_nodes[2] = const_cast<MeshLib::Node*>(e->getNode(2));
        }
        else
            OGS_FATAL("Not implemented for element type %s", typeid(edge).name());

        return edge.clone(new_nodes, edge.getID());
    }

    // Return the original edge otherwise.
    return const_cast<MeshLib::Element*>(&edge);
}
Example #13
0
void ConvergenceCriterionPerComponentDeltaX::checkDeltaX(
    const GlobalVector& minus_delta_x, GlobalVector const& x)
{
    if ((!_dof_table) || (!_mesh))
        OGS_FATAL("D.o.f. table or mesh have not been set.");

    bool satisfied_abs = true;
    bool satisfied_rel = true;

    for (unsigned global_component = 0; global_component < _abstols.size();
         ++global_component)
    {
        // TODO short cut if tol <= 0.0
        auto error_dx = norm(minus_delta_x, global_component, _norm_type,
                             *_dof_table, *_mesh);
        auto norm_x =
            norm(x, global_component, _norm_type, *_dof_table, *_mesh);

        INFO(
            "Convergence criterion, component %u: |dx|=%.4e, |x|=%.4e, "
            "|dx|/|x|=%.4e",
            error_dx, global_component, norm_x, error_dx / norm_x);

        satisfied_abs = satisfied_abs && error_dx < _abstols[global_component];
        satisfied_rel =
            satisfied_rel && checkRelativeTolerance(_reltols[global_component],
                                                    error_dx, norm_x);
    }

    _satisfied = _satisfied && (satisfied_abs || satisfied_rel);
}
Example #14
0
/**
    \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));
}
Example #15
0
ProcessVariable& findProcessVariable(
    std::vector<ProcessVariable> const& variables,
    BaseLib::ConfigTree const& pv_config, std::string const& tag)
{
    // Find process variable name in process config.
    //! \ogs_file_special
    std::string const name = pv_config.getConfigParameter<std::string>(tag);

        // Find corresponding variable by name.
    auto variable = std::find_if(variables.cbegin(), variables.cend(),
                                 [&name](ProcessVariable const& v)
                                 {
                                     return v.getName() == name;
                                 });

    if (variable == variables.end())
    {
        OGS_FATAL(
            "Could not find process variable '%s' in the provided variables "
            "list for config tag <%s>.",
            name.c_str(), tag.c_str());
    }
    DBUG("Found process variable \'%s\' for config tag <%s>.",
         variable->getName().c_str(), tag.c_str());

    // Const cast is needed because of variables argument constness.
    return const_cast<ProcessVariable&>(*variable);
}
Example #16
0
std::pair<std::unique_ptr<NonlinearSolverBase>, NonlinearSolverTag>
createNonlinearSolver(GlobalLinearSolver& linear_solver,
                      BaseLib::ConfigTree const& config)
{
    using AbstractNLS = NonlinearSolverBase;

    //! \ogs_file_param{prj__nonlinear_solvers__nonlinear_solver__type}
    auto const type = config.getConfigParameter<std::string>("type");
    //! \ogs_file_param{prj__nonlinear_solvers__nonlinear_solver__tol}
    auto const tol = config.getConfigParameter<double>("tol");
    //! \ogs_file_param{prj__nonlinear_solvers__nonlinear_solver__max_iter}
    auto const max_iter = config.getConfigParameter<unsigned>("max_iter");

    if (type == "Picard")
    {
        auto const tag = NonlinearSolverTag::Picard;
        using ConcreteNLS = NonlinearSolver<tag>;
        return std::make_pair(std::unique_ptr<AbstractNLS>(new ConcreteNLS{
                                  linear_solver, tol, max_iter}),
                              tag);
    }
    else if (type == "Newton")
    {
        auto const tag = NonlinearSolverTag::Newton;
        using ConcreteNLS = NonlinearSolver<tag>;
        return std::make_pair(std::unique_ptr<AbstractNLS>(new ConcreteNLS{
                                  linear_solver, tol, max_iter}),
                              tag);
    }
    OGS_FATAL("Unsupported nonlinear solver type");
}
Example #17
0
PhaseFieldProcess<DisplacementDim>::PhaseFieldProcess(
    MeshLib::Mesh& mesh,
    std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
    std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
    unsigned const integration_order,
    std::vector<std::vector<std::reference_wrapper<ProcessVariable>>>&&
        process_variables,
    PhaseFieldProcessData<DisplacementDim>&& process_data,
    SecondaryVariableCollection&& secondary_variables,
    NumLib::NamedFunctionCaller&& named_function_caller,
    bool const use_monolithic_scheme)
    : Process(mesh, std::move(jacobian_assembler), parameters,
              integration_order, std::move(process_variables),
              std::move(secondary_variables), std::move(named_function_caller),
              use_monolithic_scheme),
      _process_data(std::move(process_data))
{
    if (use_monolithic_scheme)
    {
        OGS_FATAL(
            "Monolithic scheme is not implemented for the PhaseField process.");
    }

    _nodal_forces = MeshLib::getOrCreateMeshProperty<double>(
        mesh, "NodalForces", MeshLib::MeshItemType::Node, DisplacementDim);
}
Example #18
0
CentralDifferencesJacobianAssembler::CentralDifferencesJacobianAssembler(
    std::vector<double>&& absolute_epsilons)
    : _absolute_epsilons(std::move(absolute_epsilons))
{
    if (_absolute_epsilons.empty())
        OGS_FATAL("No values for the absolute epsilons have been given.");
}
std::unique_ptr<BHEBottomDirichletBoundaryCondition>
createBHEBottomDirichletBoundaryCondition(
    std::pair<GlobalIndexType, GlobalIndexType>&& in_out_global_indices)
{
    DBUG("Constructing BHEBottomDirichletBoundaryCondition.");

    // In case of partitioned mesh the boundary could be empty, i.e. there is no
    // boundary condition.
#ifdef USE_PETSC
    // For this special boundary condition the boundary condition is not empty
    // if the global indices are non-negative.
    if (in_out_global_indices.first < 0 && in_out_global_indices.second < 0)
    {
        return nullptr;
    }
    // If only one of the global indices (in or out) is negative the
    // implementation is not valid.
    if (in_out_global_indices.first < 0 || in_out_global_indices.second < 0)
    {
        OGS_FATAL(
            "The partition cuts the BHE into two independent parts. This "
            "behaviour is not implemented.");
    }
#endif  // USE_PETSC

    return std::make_unique<BHEBottomDirichletBoundaryCondition>(
        std::move(in_out_global_indices));
}
void ConvergenceCriterionPerComponentResidual::checkDeltaX(
    const GlobalVector& minus_delta_x, GlobalVector const& x)
{
    if ((!_dof_table) || (!_mesh))
    {
        OGS_FATAL("D.o.f. table or mesh have not been set.");
    }

    for (unsigned global_component = 0; global_component < _abstols.size();
         ++global_component)
    {
        // TODO short cut if tol <= 0.0
        auto error_dx = norm(minus_delta_x, global_component, _norm_type,
                             *_dof_table, *_mesh);
        auto norm_x =
            norm(x, global_component, _norm_type, *_dof_table, *_mesh);

        INFO(
            "Convergence criterion, component %u: |dx|=%.4e, |x|=%.4e, "
            "|dx|/|x|=%.4e",
            error_dx, global_component, norm_x,
            (norm_x == 0. ? std::numeric_limits<double>::quiet_NaN()
                          : (error_dx / norm_x)));
    }
}
Example #21
0
static std::unique_ptr<ProcessData> makeProcessData(
    std::unique_ptr<NumLib::TimeStepAlgorithm>&& timestepper,
    NumLib::NonlinearSolverBase& nonlinear_solver,
    Process& process,
    std::unique_ptr<NumLib::TimeDiscretization>&& time_disc,
    std::unique_ptr<NumLib::ConvergenceCriterion>&& conv_crit,
    ProcessOutput&& process_output)
{
    using Tag = NumLib::NonlinearSolverTag;

    if (auto* nonlinear_solver_picard =
            dynamic_cast<NumLib::NonlinearSolver<Tag::Picard>*>(
                &nonlinear_solver))
    {
        return std::make_unique<ProcessData>(
            std::move(timestepper), *nonlinear_solver_picard,
            std::move(conv_crit), std::move(time_disc), process,
            std::move(process_output));
    }
    if (auto* nonlinear_solver_newton =
            dynamic_cast<NumLib::NonlinearSolver<Tag::Newton>*>(
                &nonlinear_solver))
    {
        return std::make_unique<ProcessData>(
            std::move(timestepper), *nonlinear_solver_newton,
            std::move(conv_crit), std::move(time_disc), process,
            std::move(process_output));
    }

    OGS_FATAL("Encountered unknown nonlinear solver type. Aborting");
}
std::pair<MatVec*, bool>
SimpleMatrixVectorProvider::
get_(std::size_t& id,
     std::map<std::size_t, MatVec*>& unused_map,
     std::map<MatVec*, std::size_t>& used_map,
     Args&&... args)
{
    if (id >= _next_id) {
        OGS_FATAL("An obviously uninitialized id argument has been passed."
            " This might not be a serious error for the current implementation,"
            " but it might become one in the future."
            " Hence, I will abort now.");
    }

    if (do_search)
    {
        auto it = unused_map.find(id);
        if (it != unused_map.end()) // unused matrix/vector found
            return { ::detail::transfer(unused_map, used_map, it), false };
    }

    // not searched or not found, so create a new one
    id = _next_id++;
    auto res = used_map.emplace(
        MathLib::MatrixVectorTraits<MatVec>::newInstance(std::forward<Args>(args)...).release(),
        id);
    assert(res.second && "Emplacement failed.");
    return { res.first->first, true };
}
Example #23
0
std::unique_ptr<TESFEMReactionAdaptor> TESFEMReactionAdaptor::newInstance(
    TESLocalAssemblerData const& data)
{
    auto const* ads = data.ap.react_sys.get();
    if (dynamic_cast<Adsorption::AdsorptionReaction const*>(ads) != nullptr)
    {
        return std::unique_ptr<TESFEMReactionAdaptor>(
            new TESFEMReactionAdaptorAdsorption(data));
    }
    else if (dynamic_cast<Adsorption::ReactionInert const*>(ads) != nullptr)
    {
        return std::unique_ptr<TESFEMReactionAdaptor>(
            new TESFEMReactionAdaptorInert(data));
    }
    else if (dynamic_cast<Adsorption::ReactionSinusoidal const*>(ads) !=
             nullptr)
    {
        return std::unique_ptr<TESFEMReactionAdaptor>(
            new TESFEMReactionAdaptorSinusoidal(data));
    }
    else if (dynamic_cast<Adsorption::ReactionCaOH2 const*>(ads) != nullptr)
    {
        return std::unique_ptr<TESFEMReactionAdaptor>(
            new TESFEMReactionAdaptorCaOH2(data));
    }

    OGS_FATAL("No suitable TESFEMReactionAdaptor found. Aborting.");
    return std::unique_ptr<TESFEMReactionAdaptor>(nullptr);
}
std::unique_ptr<TimeDiscretization> createTimeDiscretization(
    BaseLib::ConfigTree const& config)
{
    //! \ogs_file_param{prj__time_loop__processes__process__time_discretization__type}
    auto const type = config.getConfigParameter<std::string>("type");

    //! \ogs_file_param_special{prj__time_loop__processes__process__time_discretization__BackwardEuler}
    if (type == "BackwardEuler")
    {
        return std::make_unique<BackwardEuler>();
    }
    //! \ogs_file_param_special{prj__time_loop__processes__process__time_discretization__ForwardEuler}
    if (type == "ForwardEuler")
    {
        return std::make_unique<ForwardEuler>();
    }
    //! \ogs_file_param_special{prj__time_loop__processes__process__time_discretization__CrankNicolson}
    if (type == "CrankNicolson")
    {
        //! \ogs_file_param{prj__time_loop__processes__process__time_discretization__CrankNicolson__theta}
        auto const theta = config.getConfigParameter<double>("theta");
        return std::make_unique<CrankNicolson>(theta);
    }
    //! \ogs_file_param_special{prj__time_loop__processes__process__time_discretization__BackwardDifferentiationFormula}
    if (type == "BackwardDifferentiationFormula")
    {
        //! \ogs_file_param{prj__time_loop__processes__process__time_discretization__BackwardDifferentiationFormula__order}
        auto const order = config.getConfigParameter<unsigned>("order");
        return std::make_unique<BackwardDifferentiationFormula>(order);
    }

    OGS_FATAL("Unrecognized time discretization type `%s'", type.c_str());
}
Example #25
0
LocalToGlobalIndexMap::LocalToGlobalIndexMap(
    std::vector<MeshLib::MeshSubset>&& mesh_subsets,
    std::vector<int> const& global_component_ids,
    std::vector<int> const& variable_component_offsets,
    std::vector<MeshLib::Element*> const& elements,
    NumLib::MeshComponentMap&& mesh_component_map,
    LocalToGlobalIndexMap::ConstructorTag)
    : _mesh_subsets(std::move(mesh_subsets)),
      _mesh_component_map(std::move(mesh_component_map)),
      _variable_component_offsets(variable_component_offsets)
{
    // Each subset in the mesh_subsets represents a single component.
    if (_mesh_subsets.size() != global_component_ids.size())
        OGS_FATAL(
            "Number of mesh subsets is not equal to number of components. "
            "There are %d mesh subsets and %d components.",
            _mesh_subsets.size(), global_component_ids.size());

    for (int i = 0; i < static_cast<int>(global_component_ids.size()); ++i)
    {
        auto const& ms = _mesh_subsets[i];

        // For all MeshSubset in mesh_subsets and each element of that
        // MeshSubset save a line of global indices.
        std::size_t const mesh_id = ms.getMeshID();

        findGlobalIndices(elements.cbegin(), elements.cend(), ms.getNodes(),
                          mesh_id, global_component_ids[i], i);
    }
}
/**
    \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);
}
/**
    \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);
}
Example #28
0
// this is almost a copy of the implementation in the GroundwaterFlow
void HTProcess::postTimestepConcreteProcess(GlobalVector const& x,
                                            const double t,
                                            const double /*delta_t*/,
                                            int const process_id)
{
    // For the monolithic scheme, process_id is always zero.
    if (_use_monolithic_scheme && process_id != 0)
    {
        OGS_FATAL(
            "The condition of process_id = 0 must be satisfied for "
            "monolithic HTProcess, which is a single process.");
    }
    if (!_use_monolithic_scheme && process_id != _hydraulic_process_id)
    {
        DBUG("This is the thermal part of the staggered HTProcess.");
        return;
    }
    if (!_surfaceflux)  // computing the surfaceflux is optional
    {
        return;
    }

    ProcessLib::ProcessVariable const& pv = getProcessVariables(process_id)[0];

    _surfaceflux->integrate(x, t, *this, process_id, _integration_order, _mesh,
                            pv.getActiveElementIDs());
    _surfaceflux->save(t);
}
Example #29
0
/**
    \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));
}
Example #30
0
ConvergenceCriterionPerComponentDeltaX::ConvergenceCriterionPerComponentDeltaX(
    std::vector<double>&& absolute_tolerances,
    std::vector<double>&& relative_tolerances,
    MathLib::VecNormType norm_type)
    : _abstols(std::move(absolute_tolerances)),
      _reltols(std::move(relative_tolerances)),
      _norm_type(norm_type)
{
    if (_abstols.size() != _reltols.size())
        OGS_FATAL(
            "The number of absolute and relative tolerances given must be the "
            "same.");

    if (_abstols.empty())
        OGS_FATAL("The given tolerances vector is empty.");
}