https://gitlab.opengeosys.org/ogs/ogs.git
Raw File
Tip revision: 718b674cc0af413d7a07a561c7533c9988097d93 authored by Lars Bilke on 23 March 2021, 10:20:21 UTC
[cmake] Simplified (MSVC) folder setup.
Tip revision: 718b674
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