https://gitlab.opengeosys.org/ogs/ogs.git
Raw File
Tip revision: f6b976663f470740ec446fa007812d1a8d81c9bb authored by Lars Bilke on 19 February 2021, 10:47:42 UTC
[doxygen] Added branch indicator.
Tip revision: f6b9766
Subdivision.cpp
/**
 * \file
 * \copyright
 * Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org)
 *            Distributed under a Modified BSD License.
 *              See accompanying file LICENSE.txt or
 *              http://www.opengeosys.org/project/license
 *
 */

#include "Subdivision.h"

#include <algorithm>
#include <cmath>

#include <BaseLib/Error.h>

namespace BaseLib
{
GradualSubdivision::GradualSubdivision(const double L,
                                       const double dL0,
                                       const double max_dL,
                                       const double multiplier)
    : _length(L), _dL0(dL0), _max_dL(max_dL), _multiplier(multiplier)
{
    // Check if accumulated subdivisions can ever sum up to length.
    // Cf. geometric series formula.
    if (multiplier < 1.0 && dL0 / (1.0 - multiplier) < L) {
        OGS_FATAL(
            "Using dL0={:g} and multiplier={:g} the generated subdivisions can "
            "not sum up to a total length of {:g}.",
            dL0,
            multiplier,
            L);
    }
}

std::vector<double> GradualSubdivision::operator()() const
{
    std::vector<double> vec_x;

    double x = 0;
    unsigned i = 0;
    do {
        vec_x.push_back(x);
        x += std::min(_max_dL,
                      _dL0 * std::pow(_multiplier, static_cast<double>(i)));
        i++;
    } while (x < _length);

    if (vec_x.back() < _length) {
        double last_dx = vec_x[vec_x.size() - 1] - vec_x[vec_x.size() - 2];
        if (_length - vec_x.back() < last_dx)
        {
            vec_x[vec_x.size() - 1] = _length;
        }
        else
        {
            vec_x.push_back(_length);
        }
    }
    return vec_x;
}

GradualSubdivisionFixedNum::GradualSubdivisionFixedNum(
    const double L, const std::size_t num_subdivisions, const double multiplier)
    : _length{L}, _num_subdivisions{num_subdivisions}, _multiplier{multiplier}
{
}

std::vector<double> GradualSubdivisionFixedNum::operator()() const
{
    std::vector<double> subdivisions;
    subdivisions.reserve(_num_subdivisions + 1);
    subdivisions.push_back(0.0);
    auto const q = _multiplier;

    if (q == 1.0) {
        double const dx = _length / _num_subdivisions;

        for (std::size_t i = 1; i < _num_subdivisions; ++i) {
            subdivisions.push_back(dx * i);
        }
    } else {
        // compute initial subdivision size
        auto const a =
            _length * (q - 1.0) / (std::pow(q, _num_subdivisions) - 1.0);

        double qi = q;  // q^i
        for (std::size_t i = 1; i < _num_subdivisions; ++i) {
            subdivisions.push_back(a * (qi - 1.0) / (q - 1.0));
            qi *= q;
        }
    }

    subdivisions.push_back(_length);

    return subdivisions;
}

}  // namespace BaseLib
back to top